From da0c3910a3fe1008f37db52d02f00a73b1905c11 Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Tue, 27 Oct 2020 19:23:15 +1000 Subject: [PATCH 001/214] 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/214] 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/214] 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/214] 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/214] 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/214] 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/214] 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/214] 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/214] 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/214] 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/214] 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/214] 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/214] 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/214] 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 1ff85aae430cef067db7e2a9933942fa158a4c25 Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Fri, 6 Nov 2020 00:15:31 +1000 Subject: [PATCH 015/214] cosmos sdk master sync on interval --- .github/workflows/repo-sync.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 .github/workflows/repo-sync.yml diff --git a/.github/workflows/repo-sync.yml b/.github/workflows/repo-sync.yml new file mode 100644 index 000000000000..8e9cbed5e419 --- /dev/null +++ b/.github/workflows/repo-sync.yml @@ -0,0 +1,19 @@ +on: + schedule: + - cron: "*/15 * * * *" + workflow_dispatch: + +jobs: + repo-sync: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + persist-credentials: false + - name: repo-sync + uses: repo-sync/github-sync@v2 + with: + source_repo: "https://github.com/cosmos/cosmos-sdk" + source_branch: "master" + destination_branch: "master" + github_token: ${{ secrets.PAT }} \ No newline at end of file From e63f9f28ea3f7c23c3f12cdf83d1d3087b4c5d1c Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Fri, 6 Nov 2020 00:38:14 +1000 Subject: [PATCH 016/214] add line break at the end --- .github/workflows/repo-sync.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/repo-sync.yml b/.github/workflows/repo-sync.yml index 8e9cbed5e419..7844b46fa8dc 100644 --- a/.github/workflows/repo-sync.yml +++ b/.github/workflows/repo-sync.yml @@ -16,4 +16,4 @@ jobs: source_repo: "https://github.com/cosmos/cosmos-sdk" source_branch: "master" destination_branch: "master" - github_token: ${{ secrets.PAT }} \ No newline at end of file + github_token: ${{ secrets.PAT }} From 5b0b3232ae3649595b6f005519f7e0376bd6defa Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Sun, 10 Jan 2021 00:28:56 -0500 Subject: [PATCH 017/214] 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 3edb7148095668341438d8d08c1a03e9be1058ad Mon Sep 17 00:00:00 2001 From: Tess Rinearson Date: Mon, 18 Jan 2021 17:48:19 +0100 Subject: [PATCH 018/214] 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 019/214] 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 020/214] 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 021/214] 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 022/214] 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 023/214] 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 024/214] 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 025/214] 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 026/214] 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 027/214] 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 56ed27ad9cf8e97853955cff371f33552e534a67 Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Fri, 22 Jan 2021 10:37:21 -0500 Subject: [PATCH 028/214] 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 029/214] 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 d84942c1c030a415216f8d95e7d8037abf089d5f Mon Sep 17 00:00:00 2001 From: Amaury Date: Wed, 3 Feb 2021 21:38:23 +0100 Subject: [PATCH 030/214] 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 031/214] 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 032/214] 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 033/214] 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 034/214] 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 035/214] 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 036/214] 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 037/214] 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 038/214] 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 039/214] 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 040/214] 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 041/214] 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 042/214] 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 043/214] 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 044/214] 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 045/214] 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 046/214] 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 047/214] 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 048/214] 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 049/214] 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 050/214] 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 051/214] 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 052/214] 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 352a19e6eb75eb17e329acd1ba53e0f25a77721a Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Thu, 11 Feb 2021 11:30:42 -0600 Subject: [PATCH 053/214] Add epoched staking ADR --- docs/architecture/adr-033-epoched-staking.md | 111 +++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 docs/architecture/adr-033-epoched-staking.md diff --git a/docs/architecture/adr-033-epoched-staking.md b/docs/architecture/adr-033-epoched-staking.md new file mode 100644 index 000000000000..01929758bed2 --- /dev/null +++ b/docs/architecture/adr-033-epoched-staking.md @@ -0,0 +1,111 @@ +# ADR 032: Typed Events + +## Changelog + +- 10-Feb-2021: Initial Draft + +## Authors + +- Dev Ojha (@valardragon) +- Sunny Aggarwall (@sunnya97) + +## Status + +Proposed + +## Abstract + +This ADR updates the proof of stake module to buffer the staking weight updates for a number of blocks before updating the consensus' staking weights. The length of the buffer is dubbed an epoch. The prior functionality of the staking module is then a special case of the abstracted module, with the epoch being set to 1 block. + +## Context + +The current proof of stake module takes the design decision to apply staking weight changes to the consensus engine immediately. This means that delegations and unbonds get applied immediately to the validator set. This decision was primarily done as it was implementationally simplest, and because we at the time believed that this would lead to better UX for clients. + +An alternative design choice is to allow buffering staking updates (delegations, unbonds, validators joining) for a number of blocks. This 'epoch'd proof of stake consensus provides the guarantee that the consensus weights for validators will not change mid-epoch, except in the event of a slash condition. + +The decision to have immediate execution of staking changes was primarily done as it was implementationally simplest, and because we at the time believed that this would lead to better UX for clients. The UX hurdle may not be as significant as was previously thought, since it is possible to provide users acknowledgement that their bond was recorded and will be executed. + +Furthermore, it has become clearer over time that immediate execution of staking events comes with limitations, such as: + +* Threshold based cryptography. One of the main limitations is that because the validator set can change so regularly, it makes the running of multiparty computation by a fixed validator set difficult. Many threshold-based cryptographic features for blockchains such as randomness beacons and threshold decryption require a computationally-expensive DKG process (will take much longer than 1 block to create). To productively use these, we need to guarantee that the result of the DKG will be used for a reasonably long time. It wouldn't be feasible to rerun the DKG every block. By epoching staking, it guarantees we'll only need to run a new DKG once every epoch. + +* Light client efficiency. This would lessen the overhead for IBC. Because of the lite client bisection algorithm, the number of headers you need to verify is related to bounding the validator set diffs between two successively verified headers. By limiting the frequency of validator set changes, we can reduce the size of IBC lite client proofs. + +* Fairness of deterministic leader election. Currently we have no ways of reasoning of fairness of deterministic leader election in the presence of staking changes without epochs (tendermint/spec#217). Adding epochs at least makes it easier for our deterministic leader election to match something we can prove secure. (Albeit, we still haven’t proven if our current algorithm is fair with > 2 validators) + +* Staking derivative design. Currently, reward distribution is done lazily using the F1 fee distribution. While saving computational complexity, lazy accounting increases “statefulness of staking”. Right now, each delegation entry has to track the time of last withdrawal. Handling this can be a challenge for some staking derivatives designs (see example). Force-withdrawing rewards to users can help solve this, however it is infeasible to force-withdraw rewards to users on a per block basis. With epoching, a chain could more easily alter the design to have rewards be forcefully withdrawn (iterating over delegator accounts only once per-epoch), and thus remove the time of delegation from state. This preliminarily seems like it may be of utility in certain staking derivative designs. + +## Design considerations + +### Slashing + +There is a design consideration for whether to apply a slash immediately or at the end of an epoch. A slash event should apply to only members who are actually staked during the time of the infraction, namely during the epoch the slash event occured. + +Applying it immediately can be viewed as offering greater consensus layer security, at potential costs to the aforementioned usecases. The benefits of immediate slashing for consensus layer security can be all be obtained by executing the validator jailing immediately (thus removing it from the validator set), and delaying the actual slash change to the validator's weight until the epoch boundary. For the use cases mentioned above, workarounds can be integrated to avoid problems, as follows: + +- For threshold based cryptography, it can keep using the original keep epoch weights for the cryptography thresholds, but allow the underlying finality to benefit from extra security more quickly. +- For light client efficiency, there can be a bit included in the header indicating an intra-epoch slash (ala https://github.com/tendermint/spec/issues/199). +- For fairness of deterministic leader election, this will cause problems with the formalization of it / proximity of implementation to formally provable spec. However, a less formal claim can be made that the amount lost due to the slash should hopefully outweigh slight biases into the leader election process. This claim is dubious with the presence of MEV, but potentially formal upperbounds on MEV for fairness here could be derived. +- For staking derivative design, this will not cause problems with the suggested design there, nor does it increase the stateful of staking. (As whether a slash has occured is fully queryable given the validator address) + +However, for achieving consensus layer security, it suffices to apply the validator jailing immediately, but still delay the actual slash changes to waiting until the end of the epoch. This largely mitigates the concern for the fairness of deterministic leader election as well, since that validator is removed the set being rotated from immediately. + +### Token lockup + +When someone makes a transaction to delegate, even though they are not immediately staked, their tokens should be moved into a pool managed by the staking module which will then be used at the end of an epoch. This prevents concerns where they stake, and then spend those tokens not realizing they were already allocated for staking, and thus having their staking tx fail. + +### Pipelining the epochs + +For threshold based cryptography in particular, we need a pipeline for epoch changes. This is because when we are in epoch N, we want the epoch N+1 weights to be fixed so that the validator set can do the DKG accordingly. So if we are currently in epoch N, the stake weights for epoch N+1 should already be fixed, and new stake changes should be getting applied to epoch N + 2. + +This can be handled by making a parameter for the epoch pipeline. This parameter should not be alterable except during hard forks, to mitigate implementation complexity of switching the pipeline length. + +### Rewards + +Even though all staking updates are applied at epoch boundaries, rewards can still be distributed immediately when they are claimed. This is because they do not affect the current stake weights, as we do not implement auto-bonding of rewards. If such a feature were to be implemented, it would have to be setup so that rewards are auto-bonded at the epoch boundary. + +## Decision + +__Step-1__: Implement buffering of all staking and slashing messages. + +First we create a pool for storing tokens that are being bonded, but should be applied at the epoch boundary called the `EpochDelegationPool`. Then, we have two separate queues, one for staking, one for slashing. We describe what happens on each message being delivered below: + +### Staking messages +- **MsgCreateValidator**: Move user's self-bond to `EpochDelegationPool` immediately. Queue a message for the epoch boundary to handle the self-bond, taking the funds from the `EpochDelegationPool`. If Epoch execution fail, return back funds from `EpochDelegationPool` to user's account. +- **MsgEditValidator**: Validate message and if valid queue the message for execution at the end of the Epoch. +- **MsgDelegate**: Move user's funds to `EpochDelegationPool` immediately. Queue a message for the epoch boundary to handle the delegation, taking the funds from the `EpochDelegationPool`. If Epoch execution fail, return back funds from `EpochDelegationPool` to user's account. +- **MsgBeginRedelegate**: Validate message and if valid queue the message for execution at the end of the Epoch. +- **MsgUndelegate**: Validate message and if valid queue the message for execution at the end of the Epoch. + +### Slashing messages +- **MsgUnjail**: Validate message and if valid queue the message for execution at the end of the Epoch. +- **Slash Event**: Whenever a slash event is created, it gets queued in the slashing module to apply at the end of the epoch. The queues should be setup such that this slash applies immediately. + +### Evidence Messages + - **MsgSubmitEvidence**: This gets executed immediately, and the validator gets jailed immediately. However in slashing, the actual slash event gets queued. + +Then we add methods to the end blockers, to ensure that at the epoch boundary the queues are cleared and delegation updates are applied. + + +__Step-2__: Implement querying of queued staking txs. + +When querying the staking activity of a given address, the status should return not only the amount of tokens staked, but also if there are any queued stake events for that address. This will require nodes supporting querying to either do some more indexing to have this be efficiently queryable, or to have transactions + +__Step-3__: Adjust gas + +Currently gas represents the cost of executing a transaction when its done immediately. (Merging together costs of p2p overhead, state access overhead, and computational overhead) However, now a transaction can cause computation in a future block, namely at the epoch boundary. + +To handle this, we should initially include parameters for estimating the amount of future computation (denominated in gas), and add that as a flat charge needed for the message. +We leave it as out of scope for how to weight future computation versus current computation in gas pricing, and have it set such that the are weighted equally for now. + +## Consequences + +### Positive + +* Abstracts the proof of stake module that allows retaining the existing functionality +* Enables new features such as validator-set based threshold cryptography + +### Negative + +* Increases complexity of integrating more complex gas pricing mechanisms, as they now have to consider future execution costs as well. + From 3a7cc3bd3a620f45949dce2524c6652e0346eb69 Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Thu, 11 Feb 2021 16:23:53 -0500 Subject: [PATCH 054/214] epoched staking --- docs/architecture/README.md | 3 +- docs/architecture/adr-039-epoched-staking.md | 110 +++++++++++++++++++ 2 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 docs/architecture/adr-039-epoched-staking.md diff --git a/docs/architecture/README.md b/docs/architecture/README.md index 19e6d6e2db49..da4f77898da0 100644 --- a/docs/architecture/README.md +++ b/docs/architecture/README.md @@ -74,4 +74,5 @@ Read about the [PROCESS](./PROCESS.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) -- [ADR 038: State Listening](./adr-038-state-listening.md) \ No newline at end of file +- [ADR 038: State Listening](./adr-038-state-listening.md) +- [ADR 039: Epoched Staking](./adr-039-epoched-staking.md) \ No newline at end of file diff --git a/docs/architecture/adr-039-epoched-staking.md b/docs/architecture/adr-039-epoched-staking.md new file mode 100644 index 000000000000..9e7720627ccf --- /dev/null +++ b/docs/architecture/adr-039-epoched-staking.md @@ -0,0 +1,110 @@ +# ADR 039: Epoched Staking + +## Changelog + +- 10-Feb-2021: Initial Draft + +## Authors + +- Dev Ojha (@valardragon) +- Sunny Aggarwall (@sunnya97) + +## Status + +Proposed + +## Abstract + +This ADR updates the proof of stake module to buffer the staking weight updates for a number of blocks before updating the consensus' staking weights. The length of the buffer is dubbed an epoch. The prior functionality of the staking module is then a special case of the abstracted module, with the epoch being set to 1 block. + +## Context + +The current proof of stake module takes the design decision to apply staking weight changes to the consensus engine immediately. This means that delegations and unbonds get applied immediately to the validator set. This decision was primarily done as it was implementationally simplest, and because we at the time believed that this would lead to better UX for clients. + +An alternative design choice is to allow buffering staking updates (delegations, unbonds, validators joining) for a number of blocks. This 'epoch'd proof of stake consensus provides the guarantee that the consensus weights for validators will not change mid-epoch, except in the event of a slash condition. + +The decision to have immediate execution of staking changes was primarily done as it was implementationally simplest, and because we at the time believed that this would lead to better UX for clients. The UX hurdle may not be as significant as was previously thought, since it is possible to provide users acknowledgement that their bond was recorded and will be executed. + +Furthermore, it has become clearer over time that immediate execution of staking events comes with limitations, such as: + +* Threshold based cryptography. One of the main limitations is that because the validator set can change so regularly, it makes the running of multiparty computation by a fixed validator set difficult. Many threshold-based cryptographic features for blockchains such as randomness beacons and threshold decryption require a computationally-expensive DKG process (will take much longer than 1 block to create). To productively use these, we need to guarantee that the result of the DKG will be used for a reasonably long time. It wouldn't be feasible to rerun the DKG every block. By epoching staking, it guarantees we'll only need to run a new DKG once every epoch. + +* Light client efficiency. This would lessen the overhead for IBC. Because of the lite client bisection algorithm, the number of headers you need to verify is related to bounding the validator set diffs between two successively verified headers. By limiting the frequency of validator set changes, we can reduce the size of IBC lite client proofs. + +* Fairness of deterministic leader election. Currently we have no ways of reasoning of fairness of deterministic leader election in the presence of staking changes without epochs (tendermint/spec#217). Adding epochs at least makes it easier for our deterministic leader election to match something we can prove secure. (Albeit, we still haven’t proven if our current algorithm is fair with > 2 validators) + +* Staking derivative design. Currently, reward distribution is done lazily using the F1 fee distribution. While saving computational complexity, lazy accounting increases “statefulness of staking”. Right now, each delegation entry has to track the time of last withdrawal. Handling this can be a challenge for some staking derivatives designs (see example). Force-withdrawing rewards to users can help solve this, however it is infeasible to force-withdraw rewards to users on a per block basis. With epoching, a chain could more easily alter the design to have rewards be forcefully withdrawn (iterating over delegator accounts only once per-epoch), and thus remove the time of delegation from state. This preliminarily seems like it may be of utility in certain staking derivative designs. + +## Design considerations + +### Slashing + +There is a design consideration for whether to apply a slash immediately or at the end of an epoch. A slash event should apply to only members who are actually staked during the time of the infraction, namely during the epoch the slash event occured. + +Applying it immediately can be viewed as offering greater consensus layer security, at potential costs to the aforementioned usecases. The benefits of immediate slashing for consensus layer security can be all be obtained by executing the validator jailing immediately (thus removing it from the validator set), and delaying the actual slash change to the validator's weight until the epoch boundary. For the use cases mentioned above, workarounds can be integrated to avoid problems, as follows: + +- For threshold based cryptography, it can keep using the original keep epoch weights for the cryptography thresholds, but allow the underlying finality to benefit from extra security more quickly. +- For light client efficiency, there can be a bit included in the header indicating an intra-epoch slash (ala https://github.com/tendermint/spec/issues/199). +- For fairness of deterministic leader election, this will cause problems with the formalization of it / proximity of implementation to formally provable spec. However, a less formal claim can be made that the amount lost due to the slash should hopefully outweigh slight biases into the leader election process. This claim is dubious with the presence of MEV, but potentially formal upperbounds on MEV for fairness here could be derived. +- For staking derivative design, this will not cause problems with the suggested design there, nor does it increase the stateful of staking. (As whether a slash has occured is fully queryable given the validator address) + +However, for achieving consensus layer security, it suffices to apply the validator jailing immediately, but still delay the actual slash changes to waiting until the end of the epoch. This largely mitigates the concern for the fairness of deterministic leader election as well, since that validator is removed the set being rotated from immediately. + +### Token lockup + +When someone makes a transaction to delegate, even though they are not immediately staked, their tokens should be moved into a pool managed by the staking module which will then be used at the end of an epoch. This prevents concerns where they stake, and then spend those tokens not realizing they were already allocated for staking, and thus having their staking tx fail. + +### Pipelining the epochs + +For threshold based cryptography in particular, we need a pipeline for epoch changes. This is because when we are in epoch N, we want the epoch N+1 weights to be fixed so that the validator set can do the DKG accordingly. So if we are currently in epoch N, the stake weights for epoch N+1 should already be fixed, and new stake changes should be getting applied to epoch N + 2. + +This can be handled by making a parameter for the epoch pipeline. This parameter should not be alterable except during hard forks, to mitigate implementation complexity of switching the pipeline length. + +### Rewards + +Even though all staking updates are applied at epoch boundaries, rewards can still be distributed immediately when they are claimed. This is because they do not affect the current stake weights, as we do not implement auto-bonding of rewards. If such a feature were to be implemented, it would have to be setup so that rewards are auto-bonded at the epoch boundary. + +## Decision + +__Step-1__: Implement buffering of all staking and slashing messages. + +First we create a pool for storing tokens that are being bonded, but should be applied at the epoch boundary called the `EpochDelegationPool`. Then, we have two separate queues, one for staking, one for slashing. We describe what happens on each message being delivered below: + +### Staking messages +- **MsgCreateValidator**: Move user's self-bond to `EpochDelegationPool` immediately. Queue a message for the epoch boundary to handle the self-bond, taking the funds from the `EpochDelegationPool`. If Epoch execution fail, return back funds from `EpochDelegationPool` to user's account. +- **MsgEditValidator**: Validate message and if valid queue the message for execution at the end of the Epoch. +- **MsgDelegate**: Move user's funds to `EpochDelegationPool` immediately. Queue a message for the epoch boundary to handle the delegation, taking the funds from the `EpochDelegationPool`. If Epoch execution fail, return back funds from `EpochDelegationPool` to user's account. +- **MsgBeginRedelegate**: Validate message and if valid queue the message for execution at the end of the Epoch. +- **MsgUndelegate**: Validate message and if valid queue the message for execution at the end of the Epoch. + +### Slashing messages +- **MsgUnjail**: Validate message and if valid queue the message for execution at the end of the Epoch. +- **Slash Event**: Whenever a slash event is created, it gets queued in the slashing module to apply at the end of the epoch. The queues should be setup such that this slash applies immediately. + +### Evidence Messages + - **MsgSubmitEvidence**: This gets executed immediately, and the validator gets jailed immediately. However in slashing, the actual slash event gets queued. + +Then we add methods to the end blockers, to ensure that at the epoch boundary the queues are cleared and delegation updates are applied. + + +__Step-2__: Implement querying of queued staking txs. + +When querying the staking activity of a given address, the status should return not only the amount of tokens staked, but also if there are any queued stake events for that address. This will require nodes supporting querying to either do some more indexing to have this be efficiently queryable, or to have transactions + +__Step-3__: Adjust gas + +Currently gas represents the cost of executing a transaction when its done immediately. (Merging together costs of p2p overhead, state access overhead, and computational overhead) However, now a transaction can cause computation in a future block, namely at the epoch boundary. + +To handle this, we should initially include parameters for estimating the amount of future computation (denominated in gas), and add that as a flat charge needed for the message. +We leave it as out of scope for how to weight future computation versus current computation in gas pricing, and have it set such that the are weighted equally for now. + +## Consequences + +### Positive + +* Abstracts the proof of stake module that allows retaining the existing functionality +* Enables new features such as validator-set based threshold cryptography + +### Negative + +* Increases complexity of integrating more complex gas pricing mechanisms, as they now have to consider future execution costs as well. From 090411a7b5ddd6165f741c7b41b82089dda8947d Mon Sep 17 00:00:00 2001 From: Riccardo Montagnin Date: Fri, 12 Feb 2021 12:52:03 +0100 Subject: [PATCH 055/214] 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 056/214] 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 057/214] 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 058/214] 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 059/214] 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 060/214] 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 061/214] 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 062/214] 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 063/214] 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 064/214] 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 065/214] 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 066/214] 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 067/214] 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 068/214] 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 069/214] 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 070/214] 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 071/214] 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 072/214] 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 073/214] =?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 074/214] 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 075/214] 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 076/214] 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 077/214] [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 078/214] 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 079/214] 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 080/214] 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 081/214] 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 c6355fdb99925db14d8a59a6a75f8170e0d477ce Mon Sep 17 00:00:00 2001 From: Helder Moreira Date: Fri, 19 Feb 2021 14:46:58 +0000 Subject: [PATCH 082/214] utils: fix wrong filename in error message (#8643) --- server/util.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/util.go b/server/util.go index b431b715db27..bc913eb2962c 100644 --- a/server/util.go +++ b/server/util.go @@ -210,7 +210,7 @@ func interceptConfigs(rootViper *viper.Viper) (*tmcfg.Config, error) { rootViper.SetConfigName("config") rootViper.AddConfigPath(configPath) if err := rootViper.ReadInConfig(); err != nil { - return nil, fmt.Errorf("failed to read in app.toml: %w", err) + return nil, fmt.Errorf("failed to read in config.toml: %w", err) } } From 9b7a12f7db294a6a8106e93fc771e7a98a7e63ec Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Fri, 19 Feb 2021 15:02:53 +0000 Subject: [PATCH 083/214] run make format (#8642) Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- simapp/app_test.go | 2 +- types/bench_test.go | 84 +++++++++---------- .../types/proposal_handle_test.go | 2 +- 3 files changed, 44 insertions(+), 44 deletions(-) diff --git a/simapp/app_test.go b/simapp/app_test.go index 2adcf2e7e8d2..049e00b77ae8 100644 --- a/simapp/app_test.go +++ b/simapp/app_test.go @@ -94,7 +94,7 @@ func TestRunMigrations(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 + // tests (due to the difficulty of maintaining multiple versions of a // module), we're just testing here that the migration logic is // called. called := 0 diff --git a/types/bench_test.go b/types/bench_test.go index e4d8a07e1ca0..e9ed9fa12bff 100644 --- a/types/bench_test.go +++ b/types/bench_test.go @@ -30,51 +30,51 @@ 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 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)) - } - } + 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 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)) - } - } + 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/x/ibc/light-clients/07-tendermint/types/proposal_handle_test.go b/x/ibc/light-clients/07-tendermint/types/proposal_handle_test.go index c1fb05413d9d..66a5120309c0 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 @@ -307,7 +307,7 @@ func (suite *TendermintTestSuite) TestCheckSubstituteAndUpdateState() { suite.coordinator.CommitBlock(suite.chainA, suite.chainB) } - // get updated substitue + // get updated substitute substituteClientState = suite.chainA.GetClientState(substitute).(*types.ClientState) subjectClientStore := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), subject) From ceeb2a0b3439bfd1074f8bc10ceba539a6c01827 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?colin=20axn=C3=A9r?= <25233464+colin-axner@users.noreply.github.com> Date: Fri, 19 Feb 2021 16:07:52 +0100 Subject: [PATCH 084/214] Update baseapp docs (#8630) * update docs * Update docs/core/baseapp.md Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- docs/core/baseapp.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/core/baseapp.md b/docs/core/baseapp.md index 8e36a7363ddf..5d0fd115f3ef 100644 --- a/docs/core/baseapp.md +++ b/docs/core/baseapp.md @@ -286,7 +286,7 @@ Before the first transaction of a given block is processed, a [volatile state](# 1. The `AnteHandler` does **not** check that the transaction's `gas-prices` is sufficient. That is because the `min-gas-prices` value `gas-prices` is checked against is local to the node, and therefore what is enough for one full-node might not be for another. This means that the proposer can potentially include transactions for free, although they are not incentivised to do so, as they earn a bonus on the total fee of the block they propose. 2. For each `Msg` in the transaction, route to the appropriate module's [`Msg` service](../building-modules/msg-services.md). Additional _stateful_ checks are performed, and the branched multistore held in `deliverState`'s `context` is updated by the module's `keeper`. If the `Msg` service returns successfully, the branched multistore held in `context` is written to `deliverState` `CacheMultiStore`. -During step 5., each read/write to the store increases the value of `GasConsumed`. You can find the default cost of each operation: +During the additional fifth step outlined in (2), each read/write to the store increases the value of `GasConsumed`. You can find the default cost of each operation: +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/store/types/gas.go#L153-L162 From e577378497e652e57c9afd18415df68b744d8631 Mon Sep 17 00:00:00 2001 From: Jack Zampolin Date: Fri, 19 Feb 2021 07:23:52 -0800 Subject: [PATCH 085/214] Add failing address to multisig validation (#8518) * Add helper to multisig validation * Added bech32 address output * Fix test Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Amaury M <1293565+amaurym@users.noreply.github.com> --- x/auth/client/cli/cli_test.go | 2 +- x/auth/client/cli/tx_multisign.go | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/x/auth/client/cli/cli_test.go b/x/auth/client/cli/cli_test.go index efc7fbee9459..c9e4a1cb8bda 100644 --- a/x/auth/client/cli/cli_test.go +++ b/x/auth/client/cli/cli_test.go @@ -732,7 +732,7 @@ func (s *IntegrationTestSuite) TestCLIMultisign() { // Does not work in offline mode. _, err = authtest.TxMultiSignExec(val1.ClientCtx, multisigInfo.GetName(), multiGeneratedTxFile.Name(), "--offline", sign1File.Name(), sign2File.Name()) - s.Require().EqualError(err, "couldn't verify signature: unable to verify single signer signature") + s.Require().EqualError(err, fmt.Sprintf("couldn't verify signature for address %s", account1.GetAddress())) val1.ClientCtx.Offline = false multiSigWith2Signatures, err := authtest.TxMultiSignExec(val1.ClientCtx, multisigInfo.GetName(), multiGeneratedTxFile.Name(), sign1File.Name(), sign2File.Name()) diff --git a/x/auth/client/cli/tx_multisign.go b/x/auth/client/cli/tx_multisign.go index 2910244f6bf0..ebffeaf0b3a4 100644 --- a/x/auth/client/cli/tx_multisign.go +++ b/x/auth/client/cli/tx_multisign.go @@ -125,7 +125,8 @@ func makeMultiSignCmd() func(cmd *cobra.Command, args []string) (err error) { for _, sig := range sigs { err = signing.VerifySignature(sig.PubKey, signingData, sig.Data, txCfg.SignModeHandler(), txBuilder.GetTx()) if err != nil { - return fmt.Errorf("couldn't verify signature: %w", err) + addr, _ := sdk.AccAddressFromHex(sig.PubKey.Address().String()) + return fmt.Errorf("couldn't verify signature for address %s", addr) } if err := multisig.AddSignatureV2(multisigSig, sig, multisigPub.GetPubKeys()); err != nil { From 7e481cc716207b9cadbd7657182b3003e1ab80ae Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Fri, 19 Feb 2021 10:34:54 -0500 Subject: [PATCH 086/214] ADR 033: Inter-Module Communication (#7459) * Initial WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * Update Invoker * WIP * Tidying up * Update title * Cleanup diff * cleanup * Update context * Add ClientConn impl * WIP * updates * revert go.mod * Describe internal methods and authorization * Add comparison to x/capability * Cleanup * Apply suggestions from code review Co-authored-by: Robert Zaremba * Update docs/architecture/adr-033-protobuf-inter-module-comm.md Co-authored-by: Robert Zaremba * Update docs/architecture/adr-033-protobuf-inter-module-comm.md Co-authored-by: Robert Zaremba * Update docs/architecture/adr-033-protobuf-inter-module-comm.md Co-authored-by: Robert Zaremba * Update docs/architecture/adr-033-protobuf-inter-module-comm.md Co-authored-by: Robert Zaremba * ADR-033 Updates / Amendments (#8190) * updates to ADR33 based on 12.04.20 architecture call * add comments about improved devx * Update docs/architecture/adr-033-protobuf-inter-module-comm.md Co-authored-by: Aaron Craelius * update with atomicity note Co-authored-by: Aaron Craelius Co-authored-by: Robert Zaremba Co-authored-by: Aleksandr Bezobchuk Co-authored-by: Cory Co-authored-by: Alessio Treglia --- docs/architecture/README.md | 1 + .../adr-033-protobuf-inter-module-comm.md | 371 ++++++++++++++++++ 2 files changed, 372 insertions(+) create mode 100644 docs/architecture/adr-033-protobuf-inter-module-comm.md diff --git a/docs/architecture/README.md b/docs/architecture/README.md index 19e6d6e2db49..2f362178a066 100644 --- a/docs/architecture/README.md +++ b/docs/architecture/README.md @@ -72,6 +72,7 @@ Read about the [PROCESS](./PROCESS.md). - [ADR 027: Deterministic Protobuf Serialization](./adr-027-deterministic-protobuf-serialization.md) - [ADR 028: Public Key Addresses](./adr-028-public-key-addresses.md) - [ADR 032: Typed Events](./adr-032-typed-events.md) +- [ADR 033: Inter-module RPC](architecture/adr-033-protobuf-inter-module-comm.md) - [ADR 035: Rosetta API Support](./adr-035-rosetta-api-support.md) - [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-033-protobuf-inter-module-comm.md b/docs/architecture/adr-033-protobuf-inter-module-comm.md new file mode 100644 index 000000000000..8321afa6d63b --- /dev/null +++ b/docs/architecture/adr-033-protobuf-inter-module-comm.md @@ -0,0 +1,371 @@ +# ADR 033: Protobuf-based Inter-Module Communication + +## Changelog + +- 2020-10-05: Initial Draft + +## Status + +Proposed + +## Abstract + +This ADR introduces a system for permissioned inter-module communication leveraging the protobuf `Query` and `Msg` +service definitions defined in [ADR 021](./adr-021-protobuf-query-encoding.md) and +[ADR 031](./adr-031-msg-service.md) which provides: +- stable protobuf based module interfaces to potentially later replace the keeper paradigm +- stronger inter-module object capabilities guarantees +- module accounts and sub-account authorization + +## Context + +In the current Cosmos SDK documentation on the [Object-Capability Model](../docs/core/ocap.md), it is state that: + +> We assume that a thriving ecosystem of Cosmos-SDK modules that are easy to compose into a blockchain application will contain faulty or malicious modules. + +There is currently not a thriving ecosystem of Cosmos SDK modules. We hypothesize that this is in part due to: +1. lack of a stable v1.0 Cosmos SDK to build modules off of. Module interfaces are changing, sometimes dramatically, from +point release to point release, often for good reasons, but this does not create a stable foundation to build on. +2. lack of a properly implemented object capability or even object-oriented encapsulation system which makes refactors +of module keeper interfaces inevitable because the current interfaces are poorly constrained. + +### `x/bank` Case Study + +Currently the `x/bank` keeper gives pretty much unrestricted access to any module which references it. For instance, the +`SetBalance` method allows the caller to set the balance of any account to anything, bypassing even proper tracking of supply. + +There appears to have been some later attempts to implement some semblance of Ocaps using module-level minting, staking +and burning permissions. These permissions allow a module to mint, burn or delegate tokens with reference to the module’s +own account. These permissions are actually stored as a `[]string` array on the `ModuleAccount` type in state. + +However, these permissions don’t really do much. They control what modules can be referenced in the `MintCoins`, +`BurnCoins` and `DelegateCoins***` methods, but for one there is no unique object capability token that controls access — +just a simple string. So the `x/upgrade` module could mint tokens for the `x/staking` module simple by calling +`MintCoins(“staking”)`. Furthermore, all modules which have access to these keeper methods, also have access to +`SetBalance` negating any other attempt at Ocaps and breaking even basic object-oriented encapsulation. + +## Decision + +Starting from the work in [ADR 021](./adr-021-protobuf-query-encoding.md) and [ADR 31](./adr-031-msg-service.md), we introduce +the following inter-module communication system as an new paradigm for secure module based authorization and OCAPS +framework. When implemented, this could also serve as an alternative the existing paradigm of passing keepers between +modules. The approach outlined here-in is intended to form the basis of a Cosmos SDK v1.0 that provides the necessary +stability and encapsulation guarantees that allow a thriving module ecosystem to emerge. + +Of particular note — the decision is to _enable_ this functionality for modules to adopt at their own discretion. +Proposals to migrate existing modules to this new paradigm will have to be a separate conversation, potentially +addressed as amendments to this ADR. + +### New "Keeper" Paradigm + +In [ADR 021](./adr-021-protobuf-query-encoding.md), a mechanism for using protobuf service definitions to define queriers +was introduced and in [ADR 31](./adr-031-msg-service.md), a mechanism for using protobuf service to define `Msg`s was added. +Protobuf service definitions generate two golang interfaces representing the client and server sides of a service plus +some helper code. Here is a minimal example for the bank `Send` `Msg`. + +```go +package bank + +type MsgClient interface { + Send(context.Context, *MsgSend, opts ...grpc.CallOption) (*MsgSendResponse, error) +} + +type MsgServer interface { + Send(context.Context, *MsgSend) (*MsgSendResponse, error) +} +``` + +[ADR 021](./adr-021-protobuf-query-encoding.md) and [ADR 31](./adr-031-msg-service.md) specifies how modules can implement the generated `QueryServer` +and `MsgServer` interfaces as replacements for the legacy queriers and `Msg` handlers respectively. + +In this ADR we explain how modules can make queries and send `Msg`s to other modules using the generated `QueryClient` +and `MsgClient` interfaces and propose this mechanism as a replacement for the existing `Keeper` paradigm. To be clear, +this ADR does not necessitate the creation of new protobuf definitions or services. Rather, it leverages the same proto +based service interfaces already used by clients for inter-module communication. + +Using this `QueryClient`/`MsgClient` approach has the following key benefits over keepers: +1. Protobuf types are checked for breaking changes using [buf](https://buf.build/docs/breaking-overview) and because of +the way protobuf is designed this will give us strong backwards compatibility guarantees while allowing for forward +evolution. +2. The separation between the client and server interfaces will allow us to insert permission checking code in between +the two which checks if one module is authorized to send the specified `Msg` to the other module providing a proper +object capability system. +3. The router for inter-module communication gives us a convenient place to handle rollback of transactions, +enabling atomicy of operations ([currently a problem](https://github.com/cosmos/cosmos-sdk/issues/8030)). Any failure within a module-to-module call would result in a failure of the entire +transaction + +This mechanism has the added benefits of: +- reducing boilerplate through code generation, and +- allowing for modules in other languages either via a VM like CosmWasm or sub-processes using gRPC + +### Inter-module Communication + +To use the `Client` generated by the protobuf compiler we need a `grpc.ClientConn` implementation. For this we introduce +a new type, `ModuleKey`, which implements the `grpc.ClientConn` interface. `ModuleKey` can be thought of as the "private +key" corresponding to a module account, where authentication is provided through use of a special `Invoker()` function, +described in more detail below. + +Whereas external clients use their account's private key to sign transactions containing `Msg`s where they are listed as signers, +modules use their `ModuleKey` to send `Msg`s where they are listed as the sole signer to other modules. For example, modules +could use their `ModuleKey` to "sign" a `/cosmos.bank.Msg/Send` transaction to send coins from the module's account to another +account. + +Here's an example of a hypothetical module `foo` interacting with `x/bank`: +```go +package foo + +func (fooMsgServer *MsgServer) Bar(ctx context.Context, req *MsgBarRequest) (*MsgBarResponse, error) { + bankQueryClient := bank.NewQueryClient(fooMsgServer.moduleKey) + balance, err := bankQueryClient.Balance(&bank.QueryBalanceRequest{Address: fooMsgServer.moduleKey.Address(), Denom: "foo"}) + + ... + + bankMsgClient := bank.NewMsgClient(fooMsgServer.moduleKey) + res, err := bankMsgClient.Send(ctx, &bank.MsgSendRequest{FromAddress: fooMsgServer.moduleKey.Address(), ...}) + + ... +} +``` + +This design is also intended to be extensible to cover use cases of more fine grained permissioning like minting by +denom prefix being restricted to certain modules (as discussed in +[#7459](https://github.com/cosmos/cosmos-sdk/pull/7459#discussion_r529545528)). + +### `ModuleKey`s and `ModuleID`s + +A `ModuleKey` can be thought of as a "private key" for a module account and a `ModuleID` can be thought of as the +corresponding "public key". From the [ADR 028](./adr-028-public-key-addresses.md), modules can have both a root module account and any number of sub-accounts +or derived accounts that can be used for different pools (ex. staking pools) or managed accounts (ex. group +accounts). We can also think of module sub-accounts as similar to derived keys - there is a root key and then some +derivation path. `ModuleID` is a simple struct which contains the module name and optional "derivation" path, +and forms its address based on the `AddressHash` method from [the ADR 028 draft](https://github.com/cosmos/cosmos-sdk/pull/7086): + +```go +type ModuleID struct { + ModuleName string + Path []byte +} + +func (key ModuleID) Address() []byte { + return AddressHash(key.ModuleName, key.Path) +} +``` + +In addition to being able to generate a `ModuleID` and address, a `ModuleKey` contains a special function closure called +the `Invoker` which is the key to safe inter-module access. The `InvokeFn` closure corresponds to the `Invoke` method in +the `grpc.ClientConn` interface and under the hood is able to route messages to the appropriate `Msg` and `Query` handlers +performing appropriate security checks on `Msg`s. This allows for even safer inter-module access than keeper's whose +private member variables could be manipulated through reflection. Golang does not support reflection on a function +closure's captured variables and direct manipulation of memory would be needed for a truly malicious module to bypass +the `ModuleKey` security. + +The two `ModuleKey` types are `RootModuleKey` and `DerivedModuleKey`: + +```go +func Invoker(callInfo CallInfo) func(ctx context.Context, request, response interface{}, opts ...interface{}) error + +type CallInfo { + Method string + Caller ModuleID +} + +type RootModuleKey struct { + moduleName string + invoker Invoker +} + +type DerivedModuleKey struct { + moduleName string + path []byte + invoker Invoker +} +``` + +A module can get access to a `DerivedModuleKey`, using the `Derive(path []byte)` method on `RootModuleKey` and then +would use this key to authenticate `Msg`s from a sub-account. Ex: + +```go +package foo + +func (fooMsgServer *MsgServer) Bar(ctx context.Context, req *MsgBar) (*MsgBarResponse, error) { + derivedKey := fooMsgServer.moduleKey.Derive(req.SomePath) + bankMsgClient := bank.NewMsgClient(derivedKey) + res, err := bankMsgClient.Balance(ctx, &bank.MsgSend{FromAddress: derivedKey.Address(), ...}) + ... +} +``` + +In this way, a module can gain permissioned access to a root account and any number of sub-accounts and send +authenticated `Msg`s from these accounts. The `Invoker` `callInfo.Caller` parameter is used under the hood to +distinguish between different module accounts, but either way the function returned by `Invoker` only allows `Msg`s +from either the root or a derived module account to pass through. + +Note that `Invoker` itself returns a function closure based on the `CallInfo` passed in. This will allow client implementations +in the future that cache the invoke function for each method type avoiding the overhead of hash table lookup. +This would reduce the performance overhead of this inter-module communication method to the bare minimum required for +checking permissions. + +To re-iterate, the closure only allows access to authorized calls. There is no access to anything else regardless of any +name impersonation. + +Below is a rough sketch of the implementation of `grpc.ClientConn.Invoke` for `RootModuleKey`: + +```go +func (key RootModuleKey) Invoke(ctx context.Context, method string, args, reply interface{}, opts ...grpc.CallOption) error { + f := key.invoker(CallInfo {Method: method, Caller: ModuleID {ModuleName: key.moduleName}}) + return f(ctx, args, reply) +} +``` + +### `AppModule` Wiring and Requirements + +In [ADR 031](./adr-031-msg-service.md), the `AppModule.RegisterService(Configurator)` method was introduced. To support +inter-module communication, we extend the `Configurator` interface to pass in the `ModuleKey` and to allow modules to +specify their dependencies on other modules using `RequireServer()`: + + +```go +type Configurator interface { + MsgServer() grpc.Server + QueryServer() grpc.Server + + ModuleKey() ModuleKey + RequireServer(serverInterface interface{}) +} +``` + +The `ModuleKey` is passed to modules in the `RegisterService` method itself so that `RegisterServices` serves as a single +entry point for configuring module services. This is intended to also have the side-effect of greatly reducing boilerplate in +`app.go`. For now, `ModuleKey`s will be created based on `AppModuleBasic.Name()`, but a more flexible system may be +introduced in the future. The `ModuleManager` will handle creation of module accounts behind the scenes. + +Because modules do not get direct access to each other anymore, modules may have unfulfilled dependencies. To make sure +that module dependencies are resolved at startup, the `Configurator.RequireServer` method should be added. The `ModuleManager` +will make sure that all dependencies declared with `RequireServer` can be resolved before the app starts. An example +module `foo` could declare it's dependency on `x/bank` like this: + +```go +package foo + +func (am AppModule) RegisterServices(cfg Configurator) { + cfg.RequireServer((*bank.QueryServer)(nil)) + cfg.RequireServer((*bank.MsgServer)(nil)) +} +``` + +### Security Considerations + +In addition to checking for `ModuleKey` permissions, a few additional security precautions will need to be taken by +the underlying router infrastructure. + +#### Recursion and Re-entry + +Recursive or re-entrant method invocations pose a potential security threat. This can be a problem if Module A +calls Module B and Module B calls module A again in the same call. + +One basic way for the router system to deal with this is to maintain a call stack which prevents a module from +being referenced more than once in the call stack so that there is no re-entry. A `map[string]interface{}` table +in the router could be used to perform this security check. + +#### Queries + +Queries in Cosmos SDK are generally un-permissioned so allowing one module to query another module should not pose +any major security threats assuming basic precautions are taken. The basic precaution that the router system will +need to take is making sure that the `sdk.Context` passed to query methods does not allow writing to the store. This +can be done for now with a `CacheMultiStore` as is currently done for `BaseApp` queries. + +### Internal Methods + +In many cases, we may wish for modules to call methods on other modules which are not exposed to clients at all. For this +purpose, we add the `InternalServer` method to `Configurator`: + +```go +type Configurator interface { + MsgServer() grpc.Server + QueryServer() grpc.Server + InternalServer() grpc.Server +} +``` + +As an example, x/slashing's Slash must call x/staking's Slash, but we don't want to expose x/staking's Slash to end users +and clients. + +This wound also require creating a corresponding `internal.proto` file with a protobuf service in the given module's +proto package. + +Services registered against `InternalServer` will be callable from other modules but not by external clients. + +An alternative solution to internal-only methods could involve hooks / plugins as discussed [here](https://github.com/cosmos/cosmos-sdk/pull/7459#issuecomment-733807753). +A more detailed evaluation of a hooks / plugin system will be addressed later in follow-ups to this ADR or as a separate +ADR. + +### Authorization + +By default, the inter-module router requires that messages are sent by the first signer returned by `GetSigners`. The +inter-module router should also accept authorization middleware such as that provided by [ADR 030](https://github.com/cosmos/cosmos-sdk/pull/7105). +This middleware will allow accounts to otherwise specific module accounts to perform actions on their behalf. +Authorization middleware should take into account the need to grant certain modules effectively "admin" privileges to +other modules. This will be addressed in separate ADRs or updates to this ADR. + +### Future Work + +Other future improvements may include: +* custom code generation that: + * simplifies interfaces (ex. generates code with `sdk.Context` instead of `context.Context`) + * optimizes inter-module calls - for instance caching resolved methods after first invocation +* combining `StoreKey`s and `ModuleKey`s into a single interface so that modules have a single Ocaps handle +* code generation which makes inter-module communication more performant +* decoupling `ModuleKey` creation from `AppModuleBasic.Name()` so that app's can override root module account names +* inter-module hooks and plugins + +## Alternatives + +### MsgServices vs `x/capability` + +The `x/capability` module does provide a proper object-capability implementation that can be used by any module in the +SDK and could even be used for inter-module Ocaps as described in [\#5931](https://github.com/cosmos/cosmos-sdk/issues/5931). + +The advantages of the approach described in this ADR are mostly around how it integrates with other parts of the SDK, +specifically: + +* protobuf so that: + * code generation of interfaces can be leveraged for a better dev UX + * module interfaces are versioned and checked for breakage using [buf](https://docs.buf.build/breaking-overview) +* sub-module accounts as per ADR 028 +* the general `Msg` passing paradigm and the way signers are specified by `GetSigners` + +Also, this is a complete replacement for keepers and could be applied to _all_ inter-module communication whereas the +`x/capability` approach in #5931 would need to be applied method by method. + +## Consequences + +### Backwards Compatibility + +This ADR is intended to provide a pathway to a scenario where there is greater long term compatibility between modules. +In the short-term, this will likely result in breaking certain `Keeper` interfaces which are too permissive and/or +replacing `Keeper` interfaces altogether. + +### Positive + +- an alternative to keepers which can more easily lead to stable inter-module interfaces +- proper inter-module Ocaps +- improved module developer DevX, as commented on by several particpants on + [Architecture Review Call, Dec 3](https://hackmd.io/E0wxxOvRQ5qVmTf6N_k84Q) +- lays the groundwork for what can be a greatly simplified `app.go` +- router can be setup to enforce atomic transactions for moule-to-module calls + +### Negative + +- modules which adopt this will need significant refactoring + +### Neutral + +## Test Cases [optional] + +## References + +- [ADR 021](./adr-021-protobuf-query-encoding.md) +- [ADR 031](./adr-031-msg-service.md) +- [ADR 028](./adr-028-public-key-addresses.md) +- [ADR 030 draft](https://github.com/cosmos/cosmos-sdk/pull/7105) +- [Object-Capability Model](../docs/core/ocap.md) \ No newline at end of file From 7df79b55f0d3df917f95266a0d78b11215d39620 Mon Sep 17 00:00:00 2001 From: MD Aleem <72057206+aleem1314@users.noreply.github.com> Date: Sat, 20 Feb 2021 12:27:57 +0530 Subject: [PATCH 087/214] x/authz: Add DelegateAuthorization, UndelegateAuthorization (#8472) * add proto msgs * add delegate authorization * add delegate authorization tests * add delegate authorization to cli * fix lint * add cli tests * made max_tokens optional * add tests * add table tests * resolve conflicts * add undelegate authorization * proto-gen * fix errors * fix lint * resolve conflicts * fix imports * add allow & deny lists to delegate authorization * refactor authorizations * proto-docs * fix lint * review changes * golint * proto lint * review changes * add staking authorization * review changes * fix protos * review changes * review changes * clean docs * proto-docs * proto-gen * proto-docs --- docs/core/proto-docs.md | 9485 +++++++++-------- proto/cosmos/authz/v1beta1/authz.proto | 10 - proto/cosmos/authz/v1beta1/genesis.proto | 1 - proto/cosmos/authz/v1beta1/query.proto | 3 - proto/cosmos/bank/v1beta1/authz.proto | 17 + proto/cosmos/staking/v1beta1/authz.proto | 43 + x/authz/client/cli/query.go | 3 +- x/authz/client/cli/query_test.go | 186 + x/authz/client/cli/tx.go | 98 +- .../client/cli/{cli_test.go => tx_test.go} | 688 +- x/authz/client/rest/grpc_query_test.go | 44 +- x/authz/client/testutil/test_helpers.go | 32 +- x/authz/exported/authorizations.go | 21 + x/authz/exported/keeper.go | 6 +- x/authz/genesis.go | 3 +- x/authz/genesis_test.go | 4 +- x/authz/keeper/grpc_query_test.go | 14 +- x/authz/keeper/keeper.go | 15 +- x/authz/keeper/keeper_test.go | 38 +- x/authz/simulation/decoder_test.go | 3 +- x/authz/simulation/operations.go | 12 +- x/authz/simulation/operations_test.go | 7 +- ...thorizations.go => authorization_grant.go} | 26 +- x/authz/types/authz.pb.go | 248 +- x/authz/types/codec.go | 8 +- x/authz/types/generic_authorization.go | 7 +- x/authz/types/genesis.go | 3 +- x/authz/types/genesis.pb.go | 46 +- x/authz/types/keys_test.go | 3 +- x/authz/types/msgs.go | 11 +- x/authz/types/msgs_test.go | 15 +- x/authz/types/query.pb.go | 65 +- x/bank/types/authz.pb.go | 338 + x/{authz => bank}/types/send_authorization.go | 19 +- x/gov/types/tx.pb.go | 2 +- x/staking/types/authz.go | 135 + x/staking/types/authz.pb.go | 797 ++ x/staking/types/authz_test.go | 282 + x/staking/types/staking.pb.go | 1217 +-- 39 files changed, 8017 insertions(+), 5938 deletions(-) create mode 100644 proto/cosmos/bank/v1beta1/authz.proto create mode 100644 proto/cosmos/staking/v1beta1/authz.proto create mode 100644 x/authz/client/cli/query_test.go rename x/authz/client/cli/{cli_test.go => tx_test.go} (52%) create mode 100644 x/authz/exported/authorizations.go rename x/authz/types/{authorizations.go => authorization_grant.go} (54%) create mode 100644 x/bank/types/authz.pb.go rename x/{authz => bank}/types/send_authorization.go (55%) create mode 100644 x/staking/types/authz.go create mode 100644 x/staking/types/authz.pb.go create mode 100644 x/staking/types/authz_test.go diff --git a/docs/core/proto-docs.md b/docs/core/proto-docs.md index 2e39a4befc9a..6e386fbb0729 100644 --- a/docs/core/proto-docs.md +++ b/docs/core/proto-docs.md @@ -4,360 +4,239 @@ ## 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/auth/v1beta1/genesis.proto](#cosmos/auth/v1beta1/genesis.proto) - - [GenesisState](#cosmos.auth.v1beta1.GenesisState) - -- [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/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/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) - - [Metadata](#cosmos.bank.v1beta1.Metadata) - - [Output](#cosmos.bank.v1beta1.Output) - - [Params](#cosmos.bank.v1beta1.Params) - - [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) - - [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) - - [QuerySupplyOfResponse](#cosmos.bank.v1beta1.QuerySupplyOfResponse) - - [QueryTotalSupplyRequest](#cosmos.bank.v1beta1.QueryTotalSupplyRequest) - - [QueryTotalSupplyResponse](#cosmos.bank.v1beta1.QueryTotalSupplyResponse) - - - [Query](#cosmos.bank.v1beta1.Query) - -- [cosmos/bank/v1beta1/tx.proto](#cosmos/bank/v1beta1/tx.proto) - - [MsgMultiSend](#cosmos.bank.v1beta1.MsgMultiSend) - - [MsgMultiSendResponse](#cosmos.bank.v1beta1.MsgMultiSendResponse) - - [MsgSend](#cosmos.bank.v1beta1.MsgSend) - - [MsgSendResponse](#cosmos.bank.v1beta1.MsgSendResponse) - - - [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/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/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) - - - [Service](#cosmos.base.tendermint.v1beta1.Service) - -- [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/crisis/v1beta1/genesis.proto](#cosmos/crisis/v1beta1/genesis.proto) - - [GenesisState](#cosmos.crisis.v1beta1.GenesisState) +- [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/crisis/v1beta1/tx.proto](#cosmos/crisis/v1beta1/tx.proto) - - [MsgVerifyInvariant](#cosmos.crisis.v1beta1.MsgVerifyInvariant) - - [MsgVerifyInvariantResponse](#cosmos.crisis.v1beta1.MsgVerifyInvariantResponse) +- [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](#cosmos.crisis.v1beta1.Msg) + - [Msg](#ibc.applications.transfer.v1.Msg) -- [cosmos/crypto/ed25519/keys.proto](#cosmos/crypto/ed25519/keys.proto) - - [PrivKey](#cosmos.crypto.ed25519.PrivKey) - - [PubKey](#cosmos.crypto.ed25519.PubKey) +- [ibc/applications/transfer/v1/query.proto](#ibc/applications/transfer/v1/query.proto) + - [QueryDenomTraceRequest](#ibc.applications.transfer.v1.QueryDenomTraceRequest) + - [QueryDenomTraceResponse](#ibc.applications.transfer.v1.QueryDenomTraceResponse) + - [QueryDenomTracesRequest](#ibc.applications.transfer.v1.QueryDenomTracesRequest) + - [QueryDenomTracesResponse](#ibc.applications.transfer.v1.QueryDenomTracesResponse) + - [QueryParamsRequest](#ibc.applications.transfer.v1.QueryParamsRequest) + - [QueryParamsResponse](#ibc.applications.transfer.v1.QueryParamsResponse) -- [cosmos/crypto/multisig/keys.proto](#cosmos/crypto/multisig/keys.proto) - - [LegacyAminoPubKey](#cosmos.crypto.multisig.LegacyAminoPubKey) + - [Query](#ibc.applications.transfer.v1.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) +- [ibc/applications/transfer/v1/genesis.proto](#ibc/applications/transfer/v1/genesis.proto) + - [GenesisState](#ibc.applications.transfer.v1.GenesisState) -- [cosmos/crypto/secp256k1/keys.proto](#cosmos/crypto/secp256k1/keys.proto) - - [PrivKey](#cosmos.crypto.secp256k1.PrivKey) - - [PubKey](#cosmos.crypto.secp256k1.PubKey) +- [ibc/core/types/v1/genesis.proto](#ibc/core/types/v1/genesis.proto) + - [GenesisState](#ibc.core.types.v1.GenesisState) -- [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) +- [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) -- [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) +- [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) -- [cosmos/distribution/v1beta1/query.proto](#cosmos/distribution/v1beta1/query.proto) - - [QueryCommunityPoolRequest](#cosmos.distribution.v1beta1.QueryCommunityPoolRequest) - - [QueryCommunityPoolResponse](#cosmos.distribution.v1beta1.QueryCommunityPoolResponse) - - [QueryDelegationRewardsRequest](#cosmos.distribution.v1beta1.QueryDelegationRewardsRequest) - - [QueryDelegationRewardsResponse](#cosmos.distribution.v1beta1.QueryDelegationRewardsResponse) - - [QueryDelegationTotalRewardsRequest](#cosmos.distribution.v1beta1.QueryDelegationTotalRewardsRequest) - - [QueryDelegationTotalRewardsResponse](#cosmos.distribution.v1beta1.QueryDelegationTotalRewardsResponse) - - [QueryDelegatorValidatorsRequest](#cosmos.distribution.v1beta1.QueryDelegatorValidatorsRequest) - - [QueryDelegatorValidatorsResponse](#cosmos.distribution.v1beta1.QueryDelegatorValidatorsResponse) - - [QueryDelegatorWithdrawAddressRequest](#cosmos.distribution.v1beta1.QueryDelegatorWithdrawAddressRequest) - - [QueryDelegatorWithdrawAddressResponse](#cosmos.distribution.v1beta1.QueryDelegatorWithdrawAddressResponse) - - [QueryParamsRequest](#cosmos.distribution.v1beta1.QueryParamsRequest) - - [QueryParamsResponse](#cosmos.distribution.v1beta1.QueryParamsResponse) - - [QueryValidatorCommissionRequest](#cosmos.distribution.v1beta1.QueryValidatorCommissionRequest) - - [QueryValidatorCommissionResponse](#cosmos.distribution.v1beta1.QueryValidatorCommissionResponse) - - [QueryValidatorOutstandingRewardsRequest](#cosmos.distribution.v1beta1.QueryValidatorOutstandingRewardsRequest) - - [QueryValidatorOutstandingRewardsResponse](#cosmos.distribution.v1beta1.QueryValidatorOutstandingRewardsResponse) - - [QueryValidatorSlashesRequest](#cosmos.distribution.v1beta1.QueryValidatorSlashesRequest) - - [QueryValidatorSlashesResponse](#cosmos.distribution.v1beta1.QueryValidatorSlashesResponse) + - [Msg](#ibc.core.client.v1.Msg) - - [Query](#cosmos.distribution.v1beta1.Query) +- [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) -- [cosmos/distribution/v1beta1/tx.proto](#cosmos/distribution/v1beta1/tx.proto) - - [MsgFundCommunityPool](#cosmos.distribution.v1beta1.MsgFundCommunityPool) - - [MsgFundCommunityPoolResponse](#cosmos.distribution.v1beta1.MsgFundCommunityPoolResponse) - - [MsgSetWithdrawAddress](#cosmos.distribution.v1beta1.MsgSetWithdrawAddress) - - [MsgSetWithdrawAddressResponse](#cosmos.distribution.v1beta1.MsgSetWithdrawAddressResponse) - - [MsgWithdrawDelegatorReward](#cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward) - - [MsgWithdrawDelegatorRewardResponse](#cosmos.distribution.v1beta1.MsgWithdrawDelegatorRewardResponse) - - [MsgWithdrawValidatorCommission](#cosmos.distribution.v1beta1.MsgWithdrawValidatorCommission) - - [MsgWithdrawValidatorCommissionResponse](#cosmos.distribution.v1beta1.MsgWithdrawValidatorCommissionResponse) + - [Query](#ibc.core.client.v1.Query) - - [Msg](#cosmos.distribution.v1beta1.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) -- [cosmos/evidence/v1beta1/evidence.proto](#cosmos/evidence/v1beta1/evidence.proto) - - [Equivocation](#cosmos.evidence.v1beta1.Equivocation) +- [ibc/core/commitment/v1/commitment.proto](#ibc/core/commitment/v1/commitment.proto) + - [MerklePath](#ibc.core.commitment.v1.MerklePath) + - [MerklePrefix](#ibc.core.commitment.v1.MerklePrefix) + - [MerkleProof](#ibc.core.commitment.v1.MerkleProof) + - [MerkleRoot](#ibc.core.commitment.v1.MerkleRoot) -- [cosmos/evidence/v1beta1/genesis.proto](#cosmos/evidence/v1beta1/genesis.proto) - - [GenesisState](#cosmos.evidence.v1beta1.GenesisState) +- [ibc/core/channel/v1/tx.proto](#ibc/core/channel/v1/tx.proto) + - [MsgAcknowledgement](#ibc.core.channel.v1.MsgAcknowledgement) + - [MsgAcknowledgementResponse](#ibc.core.channel.v1.MsgAcknowledgementResponse) + - [MsgChannelCloseConfirm](#ibc.core.channel.v1.MsgChannelCloseConfirm) + - [MsgChannelCloseConfirmResponse](#ibc.core.channel.v1.MsgChannelCloseConfirmResponse) + - [MsgChannelCloseInit](#ibc.core.channel.v1.MsgChannelCloseInit) + - [MsgChannelCloseInitResponse](#ibc.core.channel.v1.MsgChannelCloseInitResponse) + - [MsgChannelOpenAck](#ibc.core.channel.v1.MsgChannelOpenAck) + - [MsgChannelOpenAckResponse](#ibc.core.channel.v1.MsgChannelOpenAckResponse) + - [MsgChannelOpenConfirm](#ibc.core.channel.v1.MsgChannelOpenConfirm) + - [MsgChannelOpenConfirmResponse](#ibc.core.channel.v1.MsgChannelOpenConfirmResponse) + - [MsgChannelOpenInit](#ibc.core.channel.v1.MsgChannelOpenInit) + - [MsgChannelOpenInitResponse](#ibc.core.channel.v1.MsgChannelOpenInitResponse) + - [MsgChannelOpenTry](#ibc.core.channel.v1.MsgChannelOpenTry) + - [MsgChannelOpenTryResponse](#ibc.core.channel.v1.MsgChannelOpenTryResponse) + - [MsgRecvPacket](#ibc.core.channel.v1.MsgRecvPacket) + - [MsgRecvPacketResponse](#ibc.core.channel.v1.MsgRecvPacketResponse) + - [MsgTimeout](#ibc.core.channel.v1.MsgTimeout) + - [MsgTimeoutOnClose](#ibc.core.channel.v1.MsgTimeoutOnClose) + - [MsgTimeoutOnCloseResponse](#ibc.core.channel.v1.MsgTimeoutOnCloseResponse) + - [MsgTimeoutResponse](#ibc.core.channel.v1.MsgTimeoutResponse) -- [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) + - [Msg](#ibc.core.channel.v1.Msg) - - [Query](#cosmos.evidence.v1beta1.Query) +- [ibc/core/channel/v1/query.proto](#ibc/core/channel/v1/query.proto) + - [QueryChannelClientStateRequest](#ibc.core.channel.v1.QueryChannelClientStateRequest) + - [QueryChannelClientStateResponse](#ibc.core.channel.v1.QueryChannelClientStateResponse) + - [QueryChannelConsensusStateRequest](#ibc.core.channel.v1.QueryChannelConsensusStateRequest) + - [QueryChannelConsensusStateResponse](#ibc.core.channel.v1.QueryChannelConsensusStateResponse) + - [QueryChannelRequest](#ibc.core.channel.v1.QueryChannelRequest) + - [QueryChannelResponse](#ibc.core.channel.v1.QueryChannelResponse) + - [QueryChannelsRequest](#ibc.core.channel.v1.QueryChannelsRequest) + - [QueryChannelsResponse](#ibc.core.channel.v1.QueryChannelsResponse) + - [QueryConnectionChannelsRequest](#ibc.core.channel.v1.QueryConnectionChannelsRequest) + - [QueryConnectionChannelsResponse](#ibc.core.channel.v1.QueryConnectionChannelsResponse) + - [QueryNextSequenceReceiveRequest](#ibc.core.channel.v1.QueryNextSequenceReceiveRequest) + - [QueryNextSequenceReceiveResponse](#ibc.core.channel.v1.QueryNextSequenceReceiveResponse) + - [QueryPacketAcknowledgementRequest](#ibc.core.channel.v1.QueryPacketAcknowledgementRequest) + - [QueryPacketAcknowledgementResponse](#ibc.core.channel.v1.QueryPacketAcknowledgementResponse) + - [QueryPacketAcknowledgementsRequest](#ibc.core.channel.v1.QueryPacketAcknowledgementsRequest) + - [QueryPacketAcknowledgementsResponse](#ibc.core.channel.v1.QueryPacketAcknowledgementsResponse) + - [QueryPacketCommitmentRequest](#ibc.core.channel.v1.QueryPacketCommitmentRequest) + - [QueryPacketCommitmentResponse](#ibc.core.channel.v1.QueryPacketCommitmentResponse) + - [QueryPacketCommitmentsRequest](#ibc.core.channel.v1.QueryPacketCommitmentsRequest) + - [QueryPacketCommitmentsResponse](#ibc.core.channel.v1.QueryPacketCommitmentsResponse) + - [QueryPacketReceiptRequest](#ibc.core.channel.v1.QueryPacketReceiptRequest) + - [QueryPacketReceiptResponse](#ibc.core.channel.v1.QueryPacketReceiptResponse) + - [QueryUnreceivedAcksRequest](#ibc.core.channel.v1.QueryUnreceivedAcksRequest) + - [QueryUnreceivedAcksResponse](#ibc.core.channel.v1.QueryUnreceivedAcksResponse) + - [QueryUnreceivedPacketsRequest](#ibc.core.channel.v1.QueryUnreceivedPacketsRequest) + - [QueryUnreceivedPacketsResponse](#ibc.core.channel.v1.QueryUnreceivedPacketsResponse) -- [cosmos/evidence/v1beta1/tx.proto](#cosmos/evidence/v1beta1/tx.proto) - - [MsgSubmitEvidence](#cosmos.evidence.v1beta1.MsgSubmitEvidence) - - [MsgSubmitEvidenceResponse](#cosmos.evidence.v1beta1.MsgSubmitEvidenceResponse) + - [Query](#ibc.core.channel.v1.Query) - - [Msg](#cosmos.evidence.v1beta1.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) -- [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) +- [ibc/core/channel/v1/channel.proto](#ibc/core/channel/v1/channel.proto) + - [Acknowledgement](#ibc.core.channel.v1.Acknowledgement) + - [Channel](#ibc.core.channel.v1.Channel) + - [Counterparty](#ibc.core.channel.v1.Counterparty) + - [IdentifiedChannel](#ibc.core.channel.v1.IdentifiedChannel) + - [Packet](#ibc.core.channel.v1.Packet) + - [PacketState](#ibc.core.channel.v1.PacketState) -- [cosmos/feegrant/v1beta1/genesis.proto](#cosmos/feegrant/v1beta1/genesis.proto) - - [GenesisState](#cosmos.feegrant.v1beta1.GenesisState) + - [Order](#ibc.core.channel.v1.Order) + - [State](#ibc.core.channel.v1.State) -- [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) +- [ibc/core/connection/v1/tx.proto](#ibc/core/connection/v1/tx.proto) + - [MsgConnectionOpenAck](#ibc.core.connection.v1.MsgConnectionOpenAck) + - [MsgConnectionOpenAckResponse](#ibc.core.connection.v1.MsgConnectionOpenAckResponse) + - [MsgConnectionOpenConfirm](#ibc.core.connection.v1.MsgConnectionOpenConfirm) + - [MsgConnectionOpenConfirmResponse](#ibc.core.connection.v1.MsgConnectionOpenConfirmResponse) + - [MsgConnectionOpenInit](#ibc.core.connection.v1.MsgConnectionOpenInit) + - [MsgConnectionOpenInitResponse](#ibc.core.connection.v1.MsgConnectionOpenInitResponse) + - [MsgConnectionOpenTry](#ibc.core.connection.v1.MsgConnectionOpenTry) + - [MsgConnectionOpenTryResponse](#ibc.core.connection.v1.MsgConnectionOpenTryResponse) - - [Query](#cosmos.feegrant.v1beta1.Query) + - [Msg](#ibc.core.connection.v1.Msg) -- [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) +- [ibc/core/connection/v1/connection.proto](#ibc/core/connection/v1/connection.proto) + - [ClientPaths](#ibc.core.connection.v1.ClientPaths) + - [ConnectionEnd](#ibc.core.connection.v1.ConnectionEnd) + - [ConnectionPaths](#ibc.core.connection.v1.ConnectionPaths) + - [Counterparty](#ibc.core.connection.v1.Counterparty) + - [IdentifiedConnection](#ibc.core.connection.v1.IdentifiedConnection) + - [Version](#ibc.core.connection.v1.Version) - - [Msg](#cosmos.feegrant.v1beta1.Msg) + - [State](#ibc.core.connection.v1.State) -- [cosmos/genutil/v1beta1/genesis.proto](#cosmos/genutil/v1beta1/genesis.proto) - - [GenesisState](#cosmos.genutil.v1beta1.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) + - [QueryConnectionClientStateRequest](#ibc.core.connection.v1.QueryConnectionClientStateRequest) + - [QueryConnectionClientStateResponse](#ibc.core.connection.v1.QueryConnectionClientStateResponse) + - [QueryConnectionConsensusStateRequest](#ibc.core.connection.v1.QueryConnectionConsensusStateRequest) + - [QueryConnectionConsensusStateResponse](#ibc.core.connection.v1.QueryConnectionConsensusStateResponse) + - [QueryConnectionRequest](#ibc.core.connection.v1.QueryConnectionRequest) + - [QueryConnectionResponse](#ibc.core.connection.v1.QueryConnectionResponse) + - [QueryConnectionsRequest](#ibc.core.connection.v1.QueryConnectionsRequest) + - [QueryConnectionsResponse](#ibc.core.connection.v1.QueryConnectionsResponse) -- [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) - - [WeightedVoteOption](#cosmos.gov.v1beta1.WeightedVoteOption) + - [Query](#ibc.core.connection.v1.Query) - - [ProposalStatus](#cosmos.gov.v1beta1.ProposalStatus) - - [VoteOption](#cosmos.gov.v1beta1.VoteOption) +- [ibc/core/connection/v1/genesis.proto](#ibc/core/connection/v1/genesis.proto) + - [GenesisState](#ibc.core.connection.v1.GenesisState) -- [cosmos/gov/v1beta1/genesis.proto](#cosmos/gov/v1beta1/genesis.proto) - - [GenesisState](#cosmos.gov.v1beta1.GenesisState) +- [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) -- [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) +- [ibc/lightclients/localhost/v1/localhost.proto](#ibc/lightclients/localhost/v1/localhost.proto) + - [ClientState](#ibc.lightclients.localhost.v1.ClientState) - - [Query](#cosmos.gov.v1beta1.Query) +- [ibc/lightclients/solomachine/v1/solomachine.proto](#ibc/lightclients/solomachine/v1/solomachine.proto) + - [ChannelStateData](#ibc.lightclients.solomachine.v1.ChannelStateData) + - [ClientState](#ibc.lightclients.solomachine.v1.ClientState) + - [ClientStateData](#ibc.lightclients.solomachine.v1.ClientStateData) + - [ConnectionStateData](#ibc.lightclients.solomachine.v1.ConnectionStateData) + - [ConsensusState](#ibc.lightclients.solomachine.v1.ConsensusState) + - [ConsensusStateData](#ibc.lightclients.solomachine.v1.ConsensusStateData) + - [Header](#ibc.lightclients.solomachine.v1.Header) + - [HeaderData](#ibc.lightclients.solomachine.v1.HeaderData) + - [Misbehaviour](#ibc.lightclients.solomachine.v1.Misbehaviour) + - [NextSequenceRecvData](#ibc.lightclients.solomachine.v1.NextSequenceRecvData) + - [PacketAcknowledgementData](#ibc.lightclients.solomachine.v1.PacketAcknowledgementData) + - [PacketCommitmentData](#ibc.lightclients.solomachine.v1.PacketCommitmentData) + - [PacketReceiptAbsenceData](#ibc.lightclients.solomachine.v1.PacketReceiptAbsenceData) + - [SignBytes](#ibc.lightclients.solomachine.v1.SignBytes) + - [SignatureAndData](#ibc.lightclients.solomachine.v1.SignatureAndData) + - [TimestampedSignatureData](#ibc.lightclients.solomachine.v1.TimestampedSignatureData) -- [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) - - [MsgVoteWeighted](#cosmos.gov.v1beta1.MsgVoteWeighted) - - [MsgVoteWeightedResponse](#cosmos.gov.v1beta1.MsgVoteWeightedResponse) + - [DataType](#ibc.lightclients.solomachine.v1.DataType) - - [Msg](#cosmos.gov.v1beta1.Msg) +- [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/mint/v1beta1/mint.proto](#cosmos/mint/v1beta1/mint.proto) - - [Minter](#cosmos.mint.v1beta1.Minter) - - [Params](#cosmos.mint.v1beta1.Params) +- [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/mint/v1beta1/genesis.proto](#cosmos/mint/v1beta1/genesis.proto) - - [GenesisState](#cosmos.mint.v1beta1.GenesisState) + - [Query](#cosmos.upgrade.v1beta1.Query) -- [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/capability/v1beta1/capability.proto](#cosmos/capability/v1beta1/capability.proto) + - [Capability](#cosmos.capability.v1beta1.Capability) + - [CapabilityOwners](#cosmos.capability.v1beta1.CapabilityOwners) + - [Owner](#cosmos.capability.v1beta1.Owner) - - [Query](#cosmos.mint.v1beta1.Query) +- [cosmos/capability/v1beta1/genesis.proto](#cosmos/capability/v1beta1/genesis.proto) + - [GenesisOwners](#cosmos.capability.v1beta1.GenesisOwners) + - [GenesisState](#cosmos.capability.v1beta1.GenesisState) - [cosmos/params/v1beta1/params.proto](#cosmos/params/v1beta1/params.proto) - [ParamChange](#cosmos.params.v1beta1.ParamChange) @@ -369,31 +248,101 @@ - [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/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/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) + - [Msg](#cosmos.authz.v1beta1.Msg) -- [cosmos/slashing/v1beta1/query.proto](#cosmos/slashing/v1beta1/query.proto) - - [QueryParamsRequest](#cosmos.slashing.v1beta1.QueryParamsRequest) - - [QueryParamsResponse](#cosmos.slashing.v1beta1.QueryParamsResponse) - - [QuerySigningInfoRequest](#cosmos.slashing.v1beta1.QuerySigningInfoRequest) - - [QuerySigningInfoResponse](#cosmos.slashing.v1beta1.QuerySigningInfoResponse) - - [QuerySigningInfosRequest](#cosmos.slashing.v1beta1.QuerySigningInfosRequest) - - [QuerySigningInfosResponse](#cosmos.slashing.v1beta1.QuerySigningInfosResponse) +- [cosmos/authz/v1beta1/authz.proto](#cosmos/authz/v1beta1/authz.proto) + - [AuthorizationGrant](#cosmos.authz.v1beta1.AuthorizationGrant) + - [GenericAuthorization](#cosmos.authz.v1beta1.GenericAuthorization) - - [Query](#cosmos.slashing.v1beta1.Query) +- [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/slashing/v1beta1/tx.proto](#cosmos/slashing/v1beta1/tx.proto) - - [MsgUnjail](#cosmos.slashing.v1beta1.MsgUnjail) - - [MsgUnjailResponse](#cosmos.slashing.v1beta1.MsgUnjailResponse) + - [Query](#cosmos.authz.v1beta1.Query) - - [Msg](#cosmos.slashing.v1beta1.Msg) +- [cosmos/authz/v1beta1/genesis.proto](#cosmos/authz/v1beta1/genesis.proto) + - [GenesisState](#cosmos.authz.v1beta1.GenesisState) + - [GrantAuthorization](#cosmos.authz.v1beta1.GrantAuthorization) + +- [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/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/genesis.proto](#cosmos/evidence/v1beta1/genesis.proto) + - [GenesisState](#cosmos.evidence.v1beta1.GenesisState) + +- [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/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/staking/v1beta1/staking.proto](#cosmos/staking/v1beta1/staking.proto) - [Commission](#cosmos.staking.v1beta1.Commission) @@ -419,9 +368,25 @@ - [BondStatus](#cosmos.staking.v1beta1.BondStatus) -- [cosmos/staking/v1beta1/genesis.proto](#cosmos/staking/v1beta1/genesis.proto) - - [GenesisState](#cosmos.staking.v1beta1.GenesisState) - - [LastValidatorPower](#cosmos.staking.v1beta1.LastValidatorPower) +- [cosmos/staking/v1beta1/tx.proto](#cosmos/staking/v1beta1/tx.proto) + - [MsgBeginRedelegate](#cosmos.staking.v1beta1.MsgBeginRedelegate) + - [MsgBeginRedelegateResponse](#cosmos.staking.v1beta1.MsgBeginRedelegateResponse) + - [MsgCreateValidator](#cosmos.staking.v1beta1.MsgCreateValidator) + - [MsgCreateValidatorResponse](#cosmos.staking.v1beta1.MsgCreateValidatorResponse) + - [MsgDelegate](#cosmos.staking.v1beta1.MsgDelegate) + - [MsgDelegateResponse](#cosmos.staking.v1beta1.MsgDelegateResponse) + - [MsgEditValidator](#cosmos.staking.v1beta1.MsgEditValidator) + - [MsgEditValidatorResponse](#cosmos.staking.v1beta1.MsgEditValidatorResponse) + - [MsgUndelegate](#cosmos.staking.v1beta1.MsgUndelegate) + - [MsgUndelegateResponse](#cosmos.staking.v1beta1.MsgUndelegateResponse) + + - [Msg](#cosmos.staking.v1beta1.Msg) + +- [cosmos/staking/v1beta1/authz.proto](#cosmos/staking/v1beta1/authz.proto) + - [StakeAuthorization](#cosmos.staking.v1beta1.StakeAuthorization) + - [StakeAuthorization.Validators](#cosmos.staking.v1beta1.StakeAuthorization.Validators) + + - [AuthorizationType](#cosmos.staking.v1beta1.AuthorizationType) - [cosmos/staking/v1beta1/query.proto](#cosmos/staking/v1beta1/query.proto) - [QueryDelegationRequest](#cosmos.staking.v1beta1.QueryDelegationRequest) @@ -455,354 +420,446 @@ - [Query](#cosmos.staking.v1beta1.Query) -- [cosmos/staking/v1beta1/tx.proto](#cosmos/staking/v1beta1/tx.proto) - - [MsgBeginRedelegate](#cosmos.staking.v1beta1.MsgBeginRedelegate) - - [MsgBeginRedelegateResponse](#cosmos.staking.v1beta1.MsgBeginRedelegateResponse) - - [MsgCreateValidator](#cosmos.staking.v1beta1.MsgCreateValidator) - - [MsgCreateValidatorResponse](#cosmos.staking.v1beta1.MsgCreateValidatorResponse) - - [MsgDelegate](#cosmos.staking.v1beta1.MsgDelegate) - - [MsgDelegateResponse](#cosmos.staking.v1beta1.MsgDelegateResponse) - - [MsgEditValidator](#cosmos.staking.v1beta1.MsgEditValidator) - - [MsgEditValidatorResponse](#cosmos.staking.v1beta1.MsgEditValidatorResponse) - - [MsgUndelegate](#cosmos.staking.v1beta1.MsgUndelegate) - - [MsgUndelegateResponse](#cosmos.staking.v1beta1.MsgUndelegateResponse) +- [cosmos/staking/v1beta1/genesis.proto](#cosmos/staking/v1beta1/genesis.proto) + - [GenesisState](#cosmos.staking.v1beta1.GenesisState) + - [LastValidatorPower](#cosmos.staking.v1beta1.LastValidatorPower) - - [Msg](#cosmos.staking.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/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/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/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/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/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) + + - [Service](#cosmos.base.tendermint.v1beta1.Service) + +- [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/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/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/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/tx.proto](#cosmos/bank/v1beta1/tx.proto) + - [MsgMultiSend](#cosmos.bank.v1beta1.MsgMultiSend) + - [MsgMultiSendResponse](#cosmos.bank.v1beta1.MsgMultiSendResponse) + - [MsgSend](#cosmos.bank.v1beta1.MsgSend) + - [MsgSendResponse](#cosmos.bank.v1beta1.MsgSendResponse) + + - [Msg](#cosmos.bank.v1beta1.Msg) + +- [cosmos/bank/v1beta1/authz.proto](#cosmos/bank/v1beta1/authz.proto) + - [SendAuthorization](#cosmos.bank.v1beta1.SendAuthorization) + +- [cosmos/bank/v1beta1/query.proto](#cosmos/bank/v1beta1/query.proto) + - [QueryAllBalancesRequest](#cosmos.bank.v1beta1.QueryAllBalancesRequest) + - [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) + - [QuerySupplyOfResponse](#cosmos.bank.v1beta1.QuerySupplyOfResponse) + - [QueryTotalSupplyRequest](#cosmos.bank.v1beta1.QueryTotalSupplyRequest) + - [QueryTotalSupplyResponse](#cosmos.bank.v1beta1.QueryTotalSupplyResponse) - - [SignMode](#cosmos.tx.signing.v1beta1.SignMode) + - [Query](#cosmos.bank.v1beta1.Query) -- [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/bank/v1beta1/bank.proto](#cosmos/bank/v1beta1/bank.proto) + - [DenomUnit](#cosmos.bank.v1beta1.DenomUnit) + - [Input](#cosmos.bank.v1beta1.Input) + - [Metadata](#cosmos.bank.v1beta1.Metadata) + - [Output](#cosmos.bank.v1beta1.Output) + - [Params](#cosmos.bank.v1beta1.Params) + - [SendEnabled](#cosmos.bank.v1beta1.SendEnabled) + - [Supply](#cosmos.bank.v1beta1.Supply) -- [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/bank/v1beta1/genesis.proto](#cosmos/bank/v1beta1/genesis.proto) + - [Balance](#cosmos.bank.v1beta1.Balance) + - [GenesisState](#cosmos.bank.v1beta1.GenesisState) - - [BroadcastMode](#cosmos.tx.v1beta1.BroadcastMode) +- [cosmos/genutil/v1beta1/genesis.proto](#cosmos/genutil/v1beta1/genesis.proto) + - [GenesisState](#cosmos.genutil.v1beta1.GenesisState) - - [Service](#cosmos.tx.v1beta1.Service) +- [cosmos/slashing/v1beta1/slashing.proto](#cosmos/slashing/v1beta1/slashing.proto) + - [Params](#cosmos.slashing.v1beta1.Params) + - [ValidatorSigningInfo](#cosmos.slashing.v1beta1.ValidatorSigningInfo) -- [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/slashing/v1beta1/tx.proto](#cosmos/slashing/v1beta1/tx.proto) + - [MsgUnjail](#cosmos.slashing.v1beta1.MsgUnjail) + - [MsgUnjailResponse](#cosmos.slashing.v1beta1.MsgUnjailResponse) -- [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) + - [Msg](#cosmos.slashing.v1beta1.Msg) - - [Query](#cosmos.upgrade.v1beta1.Query) +- [cosmos/slashing/v1beta1/query.proto](#cosmos/slashing/v1beta1/query.proto) + - [QueryParamsRequest](#cosmos.slashing.v1beta1.QueryParamsRequest) + - [QueryParamsResponse](#cosmos.slashing.v1beta1.QueryParamsResponse) + - [QuerySigningInfoRequest](#cosmos.slashing.v1beta1.QuerySigningInfoRequest) + - [QuerySigningInfoResponse](#cosmos.slashing.v1beta1.QuerySigningInfoResponse) + - [QuerySigningInfosRequest](#cosmos.slashing.v1beta1.QuerySigningInfosRequest) + - [QuerySigningInfosResponse](#cosmos.slashing.v1beta1.QuerySigningInfosResponse) -- [cosmos/vesting/v1beta1/tx.proto](#cosmos/vesting/v1beta1/tx.proto) - - [MsgCreateVestingAccount](#cosmos.vesting.v1beta1.MsgCreateVestingAccount) - - [MsgCreateVestingAccountResponse](#cosmos.vesting.v1beta1.MsgCreateVestingAccountResponse) + - [Query](#cosmos.slashing.v1beta1.Query) - - [Msg](#cosmos.vesting.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/vesting/v1beta1/vesting.proto](#cosmos/vesting/v1beta1/vesting.proto) - - [BaseVestingAccount](#cosmos.vesting.v1beta1.BaseVestingAccount) - - [ContinuousVestingAccount](#cosmos.vesting.v1beta1.ContinuousVestingAccount) - - [DelayedVestingAccount](#cosmos.vesting.v1beta1.DelayedVestingAccount) - - [Period](#cosmos.vesting.v1beta1.Period) - - [PeriodicVestingAccount](#cosmos.vesting.v1beta1.PeriodicVestingAccount) +- [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) -- [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) + - [Msg](#cosmos.feegrant.v1beta1.Msg) -- [ibc/applications/transfer/v1/genesis.proto](#ibc/applications/transfer/v1/genesis.proto) - - [GenesisState](#ibc.applications.transfer.v1.GenesisState) +- [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) -- [ibc/applications/transfer/v1/query.proto](#ibc/applications/transfer/v1/query.proto) - - [QueryDenomTraceRequest](#ibc.applications.transfer.v1.QueryDenomTraceRequest) - - [QueryDenomTraceResponse](#ibc.applications.transfer.v1.QueryDenomTraceResponse) - - [QueryDenomTracesRequest](#ibc.applications.transfer.v1.QueryDenomTracesRequest) - - [QueryDenomTracesResponse](#ibc.applications.transfer.v1.QueryDenomTracesResponse) - - [QueryParamsRequest](#ibc.applications.transfer.v1.QueryParamsRequest) - - [QueryParamsResponse](#ibc.applications.transfer.v1.QueryParamsResponse) +- [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](#ibc.applications.transfer.v1.Query) + - [Query](#cosmos.feegrant.v1beta1.Query) -- [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) +- [cosmos/feegrant/v1beta1/genesis.proto](#cosmos/feegrant/v1beta1/genesis.proto) + - [GenesisState](#cosmos.feegrant.v1beta1.GenesisState) -- [ibc/applications/transfer/v1/tx.proto](#ibc/applications/transfer/v1/tx.proto) - - [MsgTransfer](#ibc.applications.transfer.v1.MsgTransfer) - - [MsgTransferResponse](#ibc.applications.transfer.v1.MsgTransferResponse) +- [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) - - [Msg](#ibc.applications.transfer.v1.Msg) +- [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) -- [ibc/core/channel/v1/channel.proto](#ibc/core/channel/v1/channel.proto) - - [Acknowledgement](#ibc.core.channel.v1.Acknowledgement) - - [Channel](#ibc.core.channel.v1.Channel) - - [Counterparty](#ibc.core.channel.v1.Counterparty) - - [IdentifiedChannel](#ibc.core.channel.v1.IdentifiedChannel) - - [Packet](#ibc.core.channel.v1.Packet) - - [PacketState](#ibc.core.channel.v1.PacketState) + - [Query](#cosmos.auth.v1beta1.Query) - - [Order](#ibc.core.channel.v1.Order) - - [State](#ibc.core.channel.v1.State) +- [cosmos/auth/v1beta1/genesis.proto](#cosmos/auth/v1beta1/genesis.proto) + - [GenesisState](#cosmos.auth.v1beta1.GenesisState) -- [ibc/core/channel/v1/genesis.proto](#ibc/core/channel/v1/genesis.proto) - - [GenesisState](#ibc.core.channel.v1.GenesisState) - - [PacketSequence](#ibc.core.channel.v1.PacketSequence) +- [cosmos/crisis/v1beta1/tx.proto](#cosmos/crisis/v1beta1/tx.proto) + - [MsgVerifyInvariant](#cosmos.crisis.v1beta1.MsgVerifyInvariant) + - [MsgVerifyInvariantResponse](#cosmos.crisis.v1beta1.MsgVerifyInvariantResponse) -- [ibc/core/channel/v1/query.proto](#ibc/core/channel/v1/query.proto) - - [QueryChannelClientStateRequest](#ibc.core.channel.v1.QueryChannelClientStateRequest) - - [QueryChannelClientStateResponse](#ibc.core.channel.v1.QueryChannelClientStateResponse) - - [QueryChannelConsensusStateRequest](#ibc.core.channel.v1.QueryChannelConsensusStateRequest) - - [QueryChannelConsensusStateResponse](#ibc.core.channel.v1.QueryChannelConsensusStateResponse) - - [QueryChannelRequest](#ibc.core.channel.v1.QueryChannelRequest) - - [QueryChannelResponse](#ibc.core.channel.v1.QueryChannelResponse) - - [QueryChannelsRequest](#ibc.core.channel.v1.QueryChannelsRequest) - - [QueryChannelsResponse](#ibc.core.channel.v1.QueryChannelsResponse) - - [QueryConnectionChannelsRequest](#ibc.core.channel.v1.QueryConnectionChannelsRequest) - - [QueryConnectionChannelsResponse](#ibc.core.channel.v1.QueryConnectionChannelsResponse) - - [QueryNextSequenceReceiveRequest](#ibc.core.channel.v1.QueryNextSequenceReceiveRequest) - - [QueryNextSequenceReceiveResponse](#ibc.core.channel.v1.QueryNextSequenceReceiveResponse) - - [QueryPacketAcknowledgementRequest](#ibc.core.channel.v1.QueryPacketAcknowledgementRequest) - - [QueryPacketAcknowledgementResponse](#ibc.core.channel.v1.QueryPacketAcknowledgementResponse) - - [QueryPacketAcknowledgementsRequest](#ibc.core.channel.v1.QueryPacketAcknowledgementsRequest) - - [QueryPacketAcknowledgementsResponse](#ibc.core.channel.v1.QueryPacketAcknowledgementsResponse) - - [QueryPacketCommitmentRequest](#ibc.core.channel.v1.QueryPacketCommitmentRequest) - - [QueryPacketCommitmentResponse](#ibc.core.channel.v1.QueryPacketCommitmentResponse) - - [QueryPacketCommitmentsRequest](#ibc.core.channel.v1.QueryPacketCommitmentsRequest) - - [QueryPacketCommitmentsResponse](#ibc.core.channel.v1.QueryPacketCommitmentsResponse) - - [QueryPacketReceiptRequest](#ibc.core.channel.v1.QueryPacketReceiptRequest) - - [QueryPacketReceiptResponse](#ibc.core.channel.v1.QueryPacketReceiptResponse) - - [QueryUnreceivedAcksRequest](#ibc.core.channel.v1.QueryUnreceivedAcksRequest) - - [QueryUnreceivedAcksResponse](#ibc.core.channel.v1.QueryUnreceivedAcksResponse) - - [QueryUnreceivedPacketsRequest](#ibc.core.channel.v1.QueryUnreceivedPacketsRequest) - - [QueryUnreceivedPacketsResponse](#ibc.core.channel.v1.QueryUnreceivedPacketsResponse) + - [Msg](#cosmos.crisis.v1beta1.Msg) - - [Query](#ibc.core.channel.v1.Query) +- [cosmos/crisis/v1beta1/genesis.proto](#cosmos/crisis/v1beta1/genesis.proto) + - [GenesisState](#cosmos.crisis.v1beta1.GenesisState) -- [ibc/core/channel/v1/tx.proto](#ibc/core/channel/v1/tx.proto) - - [MsgAcknowledgement](#ibc.core.channel.v1.MsgAcknowledgement) - - [MsgAcknowledgementResponse](#ibc.core.channel.v1.MsgAcknowledgementResponse) - - [MsgChannelCloseConfirm](#ibc.core.channel.v1.MsgChannelCloseConfirm) - - [MsgChannelCloseConfirmResponse](#ibc.core.channel.v1.MsgChannelCloseConfirmResponse) - - [MsgChannelCloseInit](#ibc.core.channel.v1.MsgChannelCloseInit) - - [MsgChannelCloseInitResponse](#ibc.core.channel.v1.MsgChannelCloseInitResponse) - - [MsgChannelOpenAck](#ibc.core.channel.v1.MsgChannelOpenAck) - - [MsgChannelOpenAckResponse](#ibc.core.channel.v1.MsgChannelOpenAckResponse) - - [MsgChannelOpenConfirm](#ibc.core.channel.v1.MsgChannelOpenConfirm) - - [MsgChannelOpenConfirmResponse](#ibc.core.channel.v1.MsgChannelOpenConfirmResponse) - - [MsgChannelOpenInit](#ibc.core.channel.v1.MsgChannelOpenInit) - - [MsgChannelOpenInitResponse](#ibc.core.channel.v1.MsgChannelOpenInitResponse) - - [MsgChannelOpenTry](#ibc.core.channel.v1.MsgChannelOpenTry) - - [MsgChannelOpenTryResponse](#ibc.core.channel.v1.MsgChannelOpenTryResponse) - - [MsgRecvPacket](#ibc.core.channel.v1.MsgRecvPacket) - - [MsgRecvPacketResponse](#ibc.core.channel.v1.MsgRecvPacketResponse) - - [MsgTimeout](#ibc.core.channel.v1.MsgTimeout) - - [MsgTimeoutOnClose](#ibc.core.channel.v1.MsgTimeoutOnClose) - - [MsgTimeoutOnCloseResponse](#ibc.core.channel.v1.MsgTimeoutOnCloseResponse) - - [MsgTimeoutResponse](#ibc.core.channel.v1.MsgTimeoutResponse) +- [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) + - [WeightedVoteOption](#cosmos.gov.v1beta1.WeightedVoteOption) - - [Msg](#ibc.core.channel.v1.Msg) + - [ProposalStatus](#cosmos.gov.v1beta1.ProposalStatus) + - [VoteOption](#cosmos.gov.v1beta1.VoteOption) -- [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) +- [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) + - [MsgVoteWeighted](#cosmos.gov.v1beta1.MsgVoteWeighted) + - [MsgVoteWeightedResponse](#cosmos.gov.v1beta1.MsgVoteWeightedResponse) -- [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](#cosmos.gov.v1beta1.Msg) - - [Query](#ibc.core.client.v1.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) -- [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](#cosmos.gov.v1beta1.Query) - - [Msg](#ibc.core.client.v1.Msg) +- [cosmos/gov/v1beta1/genesis.proto](#cosmos/gov/v1beta1/genesis.proto) + - [GenesisState](#cosmos.gov.v1beta1.GenesisState) -- [ibc/core/commitment/v1/commitment.proto](#ibc/core/commitment/v1/commitment.proto) - - [MerklePath](#ibc.core.commitment.v1.MerklePath) - - [MerklePrefix](#ibc.core.commitment.v1.MerklePrefix) - - [MerkleProof](#ibc.core.commitment.v1.MerkleProof) - - [MerkleRoot](#ibc.core.commitment.v1.MerkleRoot) +- [cosmos/mint/v1beta1/mint.proto](#cosmos/mint/v1beta1/mint.proto) + - [Minter](#cosmos.mint.v1beta1.Minter) + - [Params](#cosmos.mint.v1beta1.Params) -- [ibc/core/connection/v1/connection.proto](#ibc/core/connection/v1/connection.proto) - - [ClientPaths](#ibc.core.connection.v1.ClientPaths) - - [ConnectionEnd](#ibc.core.connection.v1.ConnectionEnd) - - [ConnectionPaths](#ibc.core.connection.v1.ConnectionPaths) - - [Counterparty](#ibc.core.connection.v1.Counterparty) - - [IdentifiedConnection](#ibc.core.connection.v1.IdentifiedConnection) - - [Version](#ibc.core.connection.v1.Version) +- [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) - - [State](#ibc.core.connection.v1.State) + - [Query](#cosmos.mint.v1beta1.Query) -- [ibc/core/connection/v1/genesis.proto](#ibc/core/connection/v1/genesis.proto) - - [GenesisState](#ibc.core.connection.v1.GenesisState) +- [cosmos/mint/v1beta1/genesis.proto](#cosmos/mint/v1beta1/genesis.proto) + - [GenesisState](#cosmos.mint.v1beta1.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) - - [QueryConnectionClientStateRequest](#ibc.core.connection.v1.QueryConnectionClientStateRequest) - - [QueryConnectionClientStateResponse](#ibc.core.connection.v1.QueryConnectionClientStateResponse) - - [QueryConnectionConsensusStateRequest](#ibc.core.connection.v1.QueryConnectionConsensusStateRequest) - - [QueryConnectionConsensusStateResponse](#ibc.core.connection.v1.QueryConnectionConsensusStateResponse) - - [QueryConnectionRequest](#ibc.core.connection.v1.QueryConnectionRequest) - - [QueryConnectionResponse](#ibc.core.connection.v1.QueryConnectionResponse) - - [QueryConnectionsRequest](#ibc.core.connection.v1.QueryConnectionsRequest) - - [QueryConnectionsResponse](#ibc.core.connection.v1.QueryConnectionsResponse) +- [cosmos/vesting/v1beta1/tx.proto](#cosmos/vesting/v1beta1/tx.proto) + - [MsgCreateVestingAccount](#cosmos.vesting.v1beta1.MsgCreateVestingAccount) + - [MsgCreateVestingAccountResponse](#cosmos.vesting.v1beta1.MsgCreateVestingAccountResponse) - - [Query](#ibc.core.connection.v1.Query) + - [Msg](#cosmos.vesting.v1beta1.Msg) -- [ibc/core/connection/v1/tx.proto](#ibc/core/connection/v1/tx.proto) - - [MsgConnectionOpenAck](#ibc.core.connection.v1.MsgConnectionOpenAck) - - [MsgConnectionOpenAckResponse](#ibc.core.connection.v1.MsgConnectionOpenAckResponse) - - [MsgConnectionOpenConfirm](#ibc.core.connection.v1.MsgConnectionOpenConfirm) - - [MsgConnectionOpenConfirmResponse](#ibc.core.connection.v1.MsgConnectionOpenConfirmResponse) - - [MsgConnectionOpenInit](#ibc.core.connection.v1.MsgConnectionOpenInit) - - [MsgConnectionOpenInitResponse](#ibc.core.connection.v1.MsgConnectionOpenInitResponse) - - [MsgConnectionOpenTry](#ibc.core.connection.v1.MsgConnectionOpenTry) - - [MsgConnectionOpenTryResponse](#ibc.core.connection.v1.MsgConnectionOpenTryResponse) +- [cosmos/vesting/v1beta1/vesting.proto](#cosmos/vesting/v1beta1/vesting.proto) + - [BaseVestingAccount](#cosmos.vesting.v1beta1.BaseVestingAccount) + - [ContinuousVestingAccount](#cosmos.vesting.v1beta1.ContinuousVestingAccount) + - [DelayedVestingAccount](#cosmos.vesting.v1beta1.DelayedVestingAccount) + - [Period](#cosmos.vesting.v1beta1.Period) + - [PeriodicVestingAccount](#cosmos.vesting.v1beta1.PeriodicVestingAccount) - - [Msg](#ibc.core.connection.v1.Msg) +- [cosmos/distribution/v1beta1/tx.proto](#cosmos/distribution/v1beta1/tx.proto) + - [MsgFundCommunityPool](#cosmos.distribution.v1beta1.MsgFundCommunityPool) + - [MsgFundCommunityPoolResponse](#cosmos.distribution.v1beta1.MsgFundCommunityPoolResponse) + - [MsgSetWithdrawAddress](#cosmos.distribution.v1beta1.MsgSetWithdrawAddress) + - [MsgSetWithdrawAddressResponse](#cosmos.distribution.v1beta1.MsgSetWithdrawAddressResponse) + - [MsgWithdrawDelegatorReward](#cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward) + - [MsgWithdrawDelegatorRewardResponse](#cosmos.distribution.v1beta1.MsgWithdrawDelegatorRewardResponse) + - [MsgWithdrawValidatorCommission](#cosmos.distribution.v1beta1.MsgWithdrawValidatorCommission) + - [MsgWithdrawValidatorCommissionResponse](#cosmos.distribution.v1beta1.MsgWithdrawValidatorCommissionResponse) -- [ibc/core/types/v1/genesis.proto](#ibc/core/types/v1/genesis.proto) - - [GenesisState](#ibc.core.types.v1.GenesisState) + - [Msg](#cosmos.distribution.v1beta1.Msg) -- [ibc/lightclients/localhost/v1/localhost.proto](#ibc/lightclients/localhost/v1/localhost.proto) - - [ClientState](#ibc.lightclients.localhost.v1.ClientState) +- [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) -- [ibc/lightclients/solomachine/v1/solomachine.proto](#ibc/lightclients/solomachine/v1/solomachine.proto) - - [ChannelStateData](#ibc.lightclients.solomachine.v1.ChannelStateData) - - [ClientState](#ibc.lightclients.solomachine.v1.ClientState) - - [ClientStateData](#ibc.lightclients.solomachine.v1.ClientStateData) - - [ConnectionStateData](#ibc.lightclients.solomachine.v1.ConnectionStateData) - - [ConsensusState](#ibc.lightclients.solomachine.v1.ConsensusState) - - [ConsensusStateData](#ibc.lightclients.solomachine.v1.ConsensusStateData) - - [Header](#ibc.lightclients.solomachine.v1.Header) - - [HeaderData](#ibc.lightclients.solomachine.v1.HeaderData) - - [Misbehaviour](#ibc.lightclients.solomachine.v1.Misbehaviour) - - [NextSequenceRecvData](#ibc.lightclients.solomachine.v1.NextSequenceRecvData) - - [PacketAcknowledgementData](#ibc.lightclients.solomachine.v1.PacketAcknowledgementData) - - [PacketCommitmentData](#ibc.lightclients.solomachine.v1.PacketCommitmentData) - - [PacketReceiptAbsenceData](#ibc.lightclients.solomachine.v1.PacketReceiptAbsenceData) - - [SignBytes](#ibc.lightclients.solomachine.v1.SignBytes) - - [SignatureAndData](#ibc.lightclients.solomachine.v1.SignatureAndData) - - [TimestampedSignatureData](#ibc.lightclients.solomachine.v1.TimestampedSignatureData) +- [cosmos/distribution/v1beta1/query.proto](#cosmos/distribution/v1beta1/query.proto) + - [QueryCommunityPoolRequest](#cosmos.distribution.v1beta1.QueryCommunityPoolRequest) + - [QueryCommunityPoolResponse](#cosmos.distribution.v1beta1.QueryCommunityPoolResponse) + - [QueryDelegationRewardsRequest](#cosmos.distribution.v1beta1.QueryDelegationRewardsRequest) + - [QueryDelegationRewardsResponse](#cosmos.distribution.v1beta1.QueryDelegationRewardsResponse) + - [QueryDelegationTotalRewardsRequest](#cosmos.distribution.v1beta1.QueryDelegationTotalRewardsRequest) + - [QueryDelegationTotalRewardsResponse](#cosmos.distribution.v1beta1.QueryDelegationTotalRewardsResponse) + - [QueryDelegatorValidatorsRequest](#cosmos.distribution.v1beta1.QueryDelegatorValidatorsRequest) + - [QueryDelegatorValidatorsResponse](#cosmos.distribution.v1beta1.QueryDelegatorValidatorsResponse) + - [QueryDelegatorWithdrawAddressRequest](#cosmos.distribution.v1beta1.QueryDelegatorWithdrawAddressRequest) + - [QueryDelegatorWithdrawAddressResponse](#cosmos.distribution.v1beta1.QueryDelegatorWithdrawAddressResponse) + - [QueryParamsRequest](#cosmos.distribution.v1beta1.QueryParamsRequest) + - [QueryParamsResponse](#cosmos.distribution.v1beta1.QueryParamsResponse) + - [QueryValidatorCommissionRequest](#cosmos.distribution.v1beta1.QueryValidatorCommissionRequest) + - [QueryValidatorCommissionResponse](#cosmos.distribution.v1beta1.QueryValidatorCommissionResponse) + - [QueryValidatorOutstandingRewardsRequest](#cosmos.distribution.v1beta1.QueryValidatorOutstandingRewardsRequest) + - [QueryValidatorOutstandingRewardsResponse](#cosmos.distribution.v1beta1.QueryValidatorOutstandingRewardsResponse) + - [QueryValidatorSlashesRequest](#cosmos.distribution.v1beta1.QueryValidatorSlashesRequest) + - [QueryValidatorSlashesResponse](#cosmos.distribution.v1beta1.QueryValidatorSlashesResponse) - - [DataType](#ibc.lightclients.solomachine.v1.DataType) + - [Query](#cosmos.distribution.v1beta1.Query) -- [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) +- [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) - [Scalar Value Types](#scalar-value-types) - +

Top

-## cosmos/auth/v1beta1/auth.proto +## ibc/applications/transfer/v1/transfer.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). +### DenomTrace +DenomTrace contains the base denomination for ICS20 fungible tokens and the +source tracing information path. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | | -| `pub_key` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `account_number` | [uint64](#uint64) | | | -| `sequence` | [uint64](#uint64) | | | +| `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. | - + -### ModuleAccount -ModuleAccount defines an account for modules that holds coins on a pool. +### 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 | | ----- | ---- | ----- | ----------- | -| `base_account` | [BaseAccount](#cosmos.auth.v1beta1.BaseAccount) | | | -| `name` | [string](#string) | | | -| `permissions` | [string](#string) | repeated | | +| `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 parameters for the auth module. +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 | | ----- | ---- | ----- | ----------- | -| `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) | | | +| `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/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. @@ -814,80 +871,93 @@ Params defines the parameters for the auth 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. | | + - +

Top

-## cosmos/auth/v1beta1/genesis.proto +## ibc/applications/transfer/v1/query.proto - + -### GenesisState -GenesisState defines the auth module's genesis state. +### QueryDenomTraceRequest +QueryDenomTraceRequest is the request type for the Query/DenomTrace 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. | +| `hash` | [string](#string) | | hash (in hex format) of the denomination trace information. | - - + - +### QueryDenomTraceResponse +QueryDenomTraceResponse is the response type for the Query/DenomTrace RPC +method. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `denom_trace` | [DenomTrace](#ibc.applications.transfer.v1.DenomTrace) | | denom_trace returns the requested denomination trace information. | - -

Top

-## cosmos/auth/v1beta1/query.proto - + -### QueryAccountRequest -QueryAccountRequest is the request type for the Query/Account RPC method. +### QueryDenomTracesRequest +QueryConnectionsRequest is the request type for the Query/DenomTraces RPC +method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | address defines the address to query for. | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | - + -### QueryAccountResponse -QueryAccountResponse is the response type for the Query/Account RPC method. +### QueryDenomTracesResponse +QueryConnectionsResponse is the response type for the Query/DenomTraces RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `account` | [google.protobuf.Any](#google.protobuf.Any) | | account defines the account of the corresponding address. | +| `denom_traces` | [DenomTrace](#ibc.applications.transfer.v1.DenomTrace) | repeated | denom_traces returns all denominations trace information. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | - + ### QueryParamsRequest QueryParamsRequest is the request type for the Query/Params RPC method. @@ -897,7 +967,7 @@ QueryParamsRequest is the request type for the Query/Params RPC method. - + ### QueryParamsResponse QueryParamsResponse is the response type for the Query/Params RPC method. @@ -905,7 +975,7 @@ QueryParamsResponse is the 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](#ibc.applications.transfer.v1.Params) | | params defines the parameters of the module. | @@ -918,154 +988,200 @@ QueryParamsResponse is the response type for the Query/Params RPC method. - + ### Query -Query defines the gRPC querier service. +Query provides 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| +| `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

-## cosmos/base/v1beta1/coin.proto - +## ibc/applications/transfer/v1/genesis.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. +### GenesisState +GenesisState defines the ibc-transfer genesis state | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `denom` | [string](#string) | | | -| `amount` | [string](#string) | | | +| `port_id` | [string](#string) | | | +| `denom_traces` | [DenomTrace](#ibc.applications.transfer.v1.DenomTrace) | repeated | | +| `params` | [Params](#ibc.applications.transfer.v1.Params) | | | + - + -### 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. + + + + + +

Top

+ +## ibc/core/types/v1/genesis.proto + + + + + +### GenesisState +GenesisState defines the ibc module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `denom` | [string](#string) | | | -| `amount` | [string](#string) | | | +| `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 | + - + -### DecProto -DecProto defines a Protobuf wrapper around a Dec object. + + + + + + + +

Top

+ +## ibc/core/client/v1/client.proto + + + + + +### ClientConsensusStates +ClientConsensusStates defines all the stored consensus states for a given +client. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `dec` | [string](#string) | | | +| `client_id` | [string](#string) | | client identifier | +| `consensus_states` | [ConsensusStateWithHeight](#ibc.core.client.v1.ConsensusStateWithHeight) | repeated | consensus states and their heights associated with the client | - + -### IntProto -IntProto defines a Protobuf wrapper around an Int object. +### ClientUpdateProposal +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 | | ----- | ---- | ----- | ----------- | -| `int` | [string](#string) | | | +| `title` | [string](#string) | | the title of the update proposal | +| `description` | [string](#string) | | the description of the proposal | +| `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 | - - + - +### ConsensusStateWithHeight +ConsensusStateWithHeight defines a consensus state with an additional height field. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `height` | [Height](#ibc.core.client.v1.Height) | | consensus state height | +| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | consensus state | - -

Top

-## cosmos/authz/v1beta1/authz.proto - + -### AuthorizationGrant -AuthorizationGrant gives permissions to execute -the provide method with expiration time. +### Height +Height is a monotonically increasing data type +that can be compared against another Height for the purposes of updating and +freezing clients + +Normally the RevisionHeight is incremented at each height while keeping RevisionNumber +the same. However some consensus algorithms may choose to reset the +height in certain conditions e.g. hard forks, state-machine breaking changes +In these cases, the RevisionNumber is incremented so that height continues to +be monitonically increasing even as the RevisionHeight gets reset | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `revision_number` | [uint64](#uint64) | | the revision that the client is currently on | +| `revision_height` | [uint64](#uint64) | | the height within the given revision | - + -### GenericAuthorization -GenericAuthorization gives the grantee unrestricted permissions to execute -the provided method on behalf of the granter's account. +### IdentifiedClientState +IdentifiedClientState defines a client state with an additional client +identifier field. | 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` | +| `client_id` | [string](#string) | | client identifier | +| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | client state | - + -### SendAuthorization -SendAuthorization allows the grantee to spend up to spend_limit coins from -the granter's account. +### Params +Params defines the set of IBC light client parameters. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `spend_limit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `allowed_clients` | [string](#string) | repeated | allowed_clients defines the list of allowed client state types. | @@ -1081,417 +1197,397 @@ the granter's account. - +

Top

-## cosmos/base/abci/v1beta1/abci.proto +## ibc/core/client/v1/tx.proto - + -### ABCIMessageLog -ABCIMessageLog defines a structure containing an indexed tx ABCI message log. +### MsgCreateClient +MsgCreateClient defines a message to create an IBC client | 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. | - - - - +| `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 | - -### 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) | | | + +### MsgCreateClientResponse +MsgCreateClientResponse defines the Msg/CreateClient response type. - -### 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. | +### 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 | - -### MsgData -MsgData defines the data returned in a Result object during message -execution. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `msg_type` | [string](#string) | | | -| `data` | [bytes](#bytes) | | | +### MsgSubmitMisbehaviourResponse +MsgSubmitMisbehaviourResponse defines the Msg/SubmitMisbehaviour response type. - + -### Result -Result is the union of ResponseFormat and ResponseCheckTx. +### MsgUpdateClient +MsgUpdateClient defines an sdk.Msg to update a IBC client state using +the given header. | 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. | - - +| `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 | - -### 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 | +### MsgUpdateClientResponse +MsgUpdateClientResponse defines the Msg/UpdateClient response type. - + -### SimulationResponse -SimulationResponse defines the response generated when a transaction is -successfully simulated. +### MsgUpgradeClient +MsgUpgradeClient defines an sdk.Msg to upgrade an IBC client to a new client state | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `gas_info` | [GasInfo](#cosmos.base.abci.v1beta1.GasInfo) | | | -| `result` | [Result](#cosmos.base.abci.v1beta1.Result) | | | +| `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 | - + -### StringEvent -StringEvent defines en Event object wrapper where all the attributes -contain key/value pairs that are strings instead of raw bytes. +### MsgUpgradeClientResponse +MsgUpgradeClientResponse defines the Msg/UpgradeClient response type. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `type` | [string](#string) | | | -| `attributes` | [Attribute](#cosmos.base.abci.v1beta1.Attribute) | repeated | | + + + - -### TxMsgData -TxMsgData defines a list of MsgData. A transaction will have a MsgData object -for each message. + +### Msg +Msg defines the ibc/client Msg service. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `data` | [MsgData](#cosmos.base.abci.v1beta1.MsgData) | repeated | | +| 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/query.proto - -### 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 | -| ----- | ---- | ----- | ----------- | -| `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. | +### QueryClientParamsRequest +QueryClientParamsRequest is the request type for the Query/ClientParams RPC method. - - + - +### 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. | - -

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. +### QueryClientStateRequest +QueryClientStateRequest is the request type for the Query/ClientState RPC +method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `grantee` | [string](#string) | | | -| `msgs` | [google.protobuf.Any](#google.protobuf.Any) | repeated | | +| `client_id` | [string](#string) | | client state unique identifier | - + -### MsgExecAuthorizedResponse -MsgExecAuthorizedResponse defines the Msg/MsgExecAuthorizedResponse 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 | | ----- | ---- | ----- | ----------- | -| `result` | [cosmos.base.abci.v1beta1.Result](#cosmos.base.abci.v1beta1.Result) | | | +| `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 | - + -### MsgGrantAuthorizationRequest -MsgGrantAuthorizationRequest grants the provided authorization to the grantee on the granter's -account with the provided expiration time. +### QueryClientStatesRequest +QueryClientStatesRequest is the request type for the Query/ClientStates RPC +method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | -| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | - + -### MsgGrantAuthorizationResponse -MsgGrantAuthorizationResponse defines the Msg/MsgGrantAuthorization 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 | - + -### MsgRevokeAuthorizationRequest -MsgRevokeAuthorizationRequest revokes any authorization with the provided sdk.Msg type on the -granter's account with that has been granted to the grantee. +### 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 | | ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | -| `method_name` | [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 | - -### MsgRevokeAuthorizationResponse -MsgRevokeAuthorizationResponse defines the Msg/MsgRevokeAuthorizationResponse 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 | - - - - -### 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. | | +### QueryConsensusStatesRequest +QueryConsensusStatesRequest is the request type for the Query/ConsensusStates +RPC method. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `client_id` | [string](#string) | | client identifier | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | - -

Top

-## cosmos/authz/v1beta1/genesis.proto - + -### GenesisState -GenesisState defines the authz module's genesis state. +### QueryConsensusStatesResponse +QueryConsensusStatesResponse is the response type for the +Query/ConsensusStates RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `authorization` | [GrantAuthorization](#cosmos.authz.v1beta1.GrantAuthorization) | repeated | | +| `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 | + - + + + -### GrantAuthorization -GrantAuthorization defines the GenesisState/GrantAuthorization type. + + +### 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| -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | -| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | + + +

Top

+## ibc/core/client/v1/genesis.proto - - - + - +### GenesisMetadata +GenesisMetadata defines the genesis type for metadata that clients may return +with ExportMetadata +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `key` | [bytes](#bytes) | | store key of metadata without clientID-prefix | +| `value` | [bytes](#bytes) | | metadata value | - -

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; - } +### GenesisState +GenesisState defines the ibc client submodule's genesis state. | 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. | - +| `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 | - -### 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; - } +### IdentifiedGenesisMetadata +IdentifiedGenesisMetadata has the client metadata with the corresponding client id. | 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 | +| `client_id` | [string](#string) | | | +| `client_metadata` | [GenesisMetadata](#ibc.core.client.v1.GenesisMetadata) | repeated | | @@ -1507,72 +1603,76 @@ corresponding request message has used PageRequest. - +

Top

-## cosmos/authz/v1beta1/query.proto +## ibc/core/commitment/v1/commitment.proto - + -### QueryAuthorizationRequest -QueryAuthorizationRequest is the request type for the Query/Authorization RPC method. +### MerklePath +MerklePath is the path used to verify commitment proofs, which can be an +arbitrary structured object (defined by a commitment type). +MerklePath is represented from root-to-leaf | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | -| `method_name` | [string](#string) | | | +| `key_path` | [string](#string) | repeated | | - + -### QueryAuthorizationResponse -QueryAuthorizationResponse is the response type for the Query/Authorization RPC method. +### MerklePrefix +MerklePrefix is merkle path prefixed to the key. +The constructed key from the Path and the key will be append(Path.KeyPath, +append(Path.KeyPrefix, key...)) | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `authorization` | [AuthorizationGrant](#cosmos.authz.v1beta1.AuthorizationGrant) | | authorization is a authorization granted for grantee by granter. | +| `key_prefix` | [bytes](#bytes) | | | - + -### QueryAuthorizationsRequest -QueryAuthorizationsRequest is the request type for the Query/Authorizations RPC method. +### MerkleProof +MerkleProof is a wrapper type over a chain of CommitmentProofs. +It demonstrates membership or non-membership for an element or set of +elements, verifiable in conjunction with a known commitment root. Proofs +should be succinct. +MerkleProofs are ordered from leaf-to-root | 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. | +| `proofs` | [ics23.CommitmentProof](#ics23.CommitmentProof) | repeated | | - + -### QueryAuthorizationsResponse -QueryAuthorizationsResponse is the response type for the Query/Authorizations RPC method. +### MerkleRoot +MerkleRoot defines a merkle root hash. +In the Cosmos SDK, the AppHash of a block header becomes the root. | 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. | +| `hash` | [bytes](#bytes) | | | @@ -1584,825 +1684,805 @@ 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 +## ibc/core/channel/v1/tx.proto - + -### DenomUnit -DenomUnit represents a struct that describes a given -denomination unit of the basic token. +### MsgAcknowledgement +MsgAcknowledgement receives incoming IBC acknowledgement | 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 | - - +| `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) | | | - -### Input -Input models transaction input. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | | -| `coins` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +### MsgAcknowledgementResponse +MsgAcknowledgementResponse defines the Msg/Acknowledgement response type. - + -### Metadata -Metadata represents a struct that describes -a basic token. +### 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 | | ----- | ---- | ----- | ----------- | -| `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. | - - +| `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) | | | - -### Output -Output models transaction outputs. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | | -| `coins` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +### MsgChannelCloseConfirmResponse +MsgChannelCloseConfirmResponse defines the Msg/ChannelCloseConfirm response type. - + -### Params -Params defines the parameters for the bank module. +### MsgChannelCloseInit +MsgChannelCloseInit defines a msg sent by a Relayer to Chain A +to close a channel with Chain B. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `send_enabled` | [SendEnabled](#cosmos.bank.v1beta1.SendEnabled) | repeated | | -| `default_send_enabled` | [bool](#bool) | | | - - +| `port_id` | [string](#string) | | | +| `channel_id` | [string](#string) | | | +| `signer` | [string](#string) | | | - -### 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) | | | +### MsgChannelCloseInitResponse +MsgChannelCloseInitResponse defines the Msg/ChannelCloseInit response type. - + -### Supply -Supply represents a struct that passively keeps track of the total supply -amounts in the network. +### 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 | | ----- | ---- | ----- | ----------- | -| `total` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | - - - - - - - - - - - - - - - - -

Top

+| `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) | | | -## cosmos/bank/v1beta1/genesis.proto - -### Balance -Balance defines an account address and balance pair used in the bank module's -genesis state. + -| 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. | +### MsgChannelOpenAckResponse +MsgChannelOpenAckResponse defines the Msg/ChannelOpenAck response type. - + -### GenesisState -GenesisState defines the bank module's genesis state. +### 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 | | ----- | ---- | ----- | ----------- | -| `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. | - - +| `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) | | | - - - - + +### MsgChannelOpenConfirmResponse +MsgChannelOpenConfirmResponse defines the Msg/ChannelOpenConfirm response type. - -

Top

-## cosmos/bank/v1beta1/query.proto - + -### QueryAllBalancesRequest -QueryBalanceRequest is the request type for the Query/AllBalances 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 | | ----- | ---- | ----- | ----------- | -| `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. | - - +| `port_id` | [string](#string) | | | +| `channel` | [Channel](#ibc.core.channel.v1.Channel) | | | +| `signer` | [string](#string) | | | - -### 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. | +### MsgChannelOpenInitResponse +MsgChannelOpenInitResponse defines the Msg/ChannelOpenInit response type. - + -### QueryBalanceRequest -QueryBalanceRequest is the request type for the Query/Balance RPC method. +### MsgChannelOpenTry +MsgChannelOpenInit defines a msg sent by a Relayer to try to open a channel +on Chain B. | 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. | - - +| `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) | | | - -### 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. | +### MsgChannelOpenTryResponse +MsgChannelOpenTryResponse defines the Msg/ChannelOpenTry response type. - + -### QueryDenomMetadataRequest -QueryDenomMetadataRequest is the request type for the Query/DenomMetadata RPC method. +### MsgRecvPacket +MsgRecvPacket receives incoming IBC packet | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `denom` | [string](#string) | | denom is the coin denom to query the metadata for. | - - +| `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) | | | - -### 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. | +### MsgRecvPacketResponse +MsgRecvPacketResponse defines the Msg/RecvPacket response type. - + -### QueryDenomsMetadataRequest -QueryDenomsMetadataRequest is the request type for the Query/DenomsMetadata RPC method. +### MsgTimeout +MsgTimeout receives timed-out packet | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | +| `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) | | | - + -### QueryDenomsMetadataResponse -QueryDenomsMetadataResponse is the response type for the Query/DenomsMetadata RPC -method. +### MsgTimeoutOnClose +MsgTimeoutOnClose timed-out packet upon counterparty channel closure. | 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. | - - - - - +| `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) | | | - -### QueryParamsRequest -QueryParamsRequest defines the request type for querying x/bank parameters. + +### MsgTimeoutOnCloseResponse +MsgTimeoutOnCloseResponse defines the Msg/TimeoutOnClose response type. - -### QueryParamsResponse -QueryParamsResponse defines the response type for querying x/bank parameters. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.bank.v1beta1.Params) | | | + +### MsgTimeoutResponse +MsgTimeoutResponse defines the Msg/Timeout response type. - -### 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. | + + + +### 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. | | - + -### 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. | + +

Top

+## ibc/core/channel/v1/query.proto + +### QueryChannelClientStateRequest +QueryChannelClientStateRequest is the request type for the Query/ClientState +RPC method - -### QueryTotalSupplyRequest -QueryTotalSupplyRequest is the request type for the Query/TotalSupply RPC -method. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `port_id` | [string](#string) | | port unique identifier | +| `channel_id` | [string](#string) | | channel unique identifier | - + -### QueryTotalSupplyResponse -QueryTotalSupplyResponse is the response type for the Query/TotalSupply RPC -method +### QueryChannelClientStateResponse +QueryChannelClientStateResponse is the Response type for the +Query/QueryChannelClientState RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `supply` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | supply is the supply of the coins | - - - - +| `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 | - - - - -### 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| +### 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 | - -

Top

-## cosmos/bank/v1beta1/tx.proto - + -### MsgMultiSend -MsgMultiSend represents an arbitrary multi-in, multi-out send message. +### QueryChannelConsensusStateResponse +QueryChannelClientStateResponse is the Response type for the +Query/QueryChannelClientState RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `inputs` | [Input](#cosmos.bank.v1beta1.Input) | repeated | | -| `outputs` | [Output](#cosmos.bank.v1beta1.Output) | repeated | | +| `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 | + + - +### QueryChannelRequest +QueryChannelRequest is the request type for the Query/Channel RPC method -### MsgMultiSendResponse -MsgMultiSendResponse defines the Msg/MultiSend response type. + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `port_id` | [string](#string) | | port unique identifier | +| `channel_id` | [string](#string) | | channel unique identifier | - + -### MsgSend -MsgSend represents a message to send coins from one account to another. +### 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 | | ----- | ---- | ----- | ----------- | -| `from_address` | [string](#string) | | | -| `to_address` | [string](#string) | | | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | - - +| `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 | - -### MsgSendResponse -MsgSendResponse defines the Msg/Send 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 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. | | +### 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

-## cosmos/base/kv/v1beta1/kv.proto - + -### Pair -Pair defines a key/value bytes tuple. +### QueryConnectionChannelsRequest +QueryConnectionChannelsRequest is the request type for the +Query/QueryConnectionChannels RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | | -| `value` | [bytes](#bytes) | | | +| `connection` | [string](#string) | | connection unique identifier | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | - + -### Pairs -Pairs defines a repeated slice of Pair objects. +### QueryConnectionChannelsResponse +QueryConnectionChannelsResponse is the Response type for the +Query/QueryConnectionChannels RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `pairs` | [Pair](#cosmos.base.kv.v1beta1.Pair) | repeated | | +| `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 | - - + - +### 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 | - -

Top

-## cosmos/base/reflection/v1beta1/reflection.proto - + -### ListAllInterfacesRequest -ListAllInterfacesRequest is the request type of the ListAllInterfaces RPC. +### 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 | + - -### ListAllInterfacesResponse -ListAllInterfacesResponse is the response type of the ListAllInterfaces RPC. + + +### QueryPacketAcknowledgementRequest +QueryPacketAcknowledgementRequest is the request type for the +Query/PacketAcknowledgement RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `interface_names` | [string](#string) | repeated | interface_names is an array of all the registered interfaces. | +| `port_id` | [string](#string) | | port unique identifier | +| `channel_id` | [string](#string) | | channel unique identifier | +| `sequence` | [uint64](#uint64) | | packet sequence | - + -### ListImplementationsRequest -ListImplementationsRequest is the request type of the ListImplementations -RPC. +### 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 | | ----- | ---- | ----- | ----------- | -| `interface_name` | [string](#string) | | interface_name defines the interface to query the implementations for. | +| `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 | - + -### ListImplementationsResponse -ListImplementationsResponse is the response type of the ListImplementations -RPC. +### QueryPacketAcknowledgementsRequest +QueryPacketAcknowledgementsRequest is the request type for the +Query/QueryPacketCommitments RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `implementation_message_names` | [string](#string) | repeated | | - - - - +| `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 | - - - - -### 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| +### 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 | - -

Top

-## cosmos/base/snapshots/v1beta1/snapshot.proto - + -### Metadata -Metadata contains SDK-specific snapshot metadata. +### QueryPacketCommitmentRequest +QueryPacketCommitmentRequest is the request type for the +Query/PacketCommitment RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `chunk_hashes` | [bytes](#bytes) | repeated | SHA-256 chunk hashes | +| `port_id` | [string](#string) | | port unique identifier | +| `channel_id` | [string](#string) | | channel unique identifier | +| `sequence` | [uint64](#uint64) | | packet sequence | - + -### Snapshot -Snapshot contains Tendermint state sync snapshot info. +### 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 | | ----- | ---- | ----- | ----------- | -| `height` | [uint64](#uint64) | | | -| `format` | [uint32](#uint32) | | | -| `chunks` | [uint32](#uint32) | | | -| `hash` | [bytes](#bytes) | | | -| `metadata` | [Metadata](#cosmos.base.snapshots.v1beta1.Metadata) | | | +| `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 | - - + - +### QueryPacketCommitmentsRequest +QueryPacketCommitmentsRequest is the request type for the +Query/QueryPacketCommitments RPC method - +| 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 | - -

Top

-## cosmos/base/store/v1beta1/commit_info.proto - + -### CommitID -CommitID defines the committment information when a specific store is -committed. +### QueryPacketCommitmentsResponse +QueryPacketCommitmentsResponse is the request type for the +Query/QueryPacketCommitments RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `version` | [int64](#int64) | | | -| `hash` | [bytes](#bytes) | | | +| `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 | - + -### CommitInfo -CommitInfo defines commit information used by the multi-store when committing -a version/height. +### QueryPacketReceiptRequest +QueryPacketReceiptRequest is the request type for the +Query/PacketReceipt RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `version` | [int64](#int64) | | | -| `store_infos` | [StoreInfo](#cosmos.base.store.v1beta1.StoreInfo) | repeated | | +| `port_id` | [string](#string) | | port unique identifier | +| `channel_id` | [string](#string) | | channel unique identifier | +| `sequence` | [uint64](#uint64) | | packet sequence | - + -### StoreInfo -StoreInfo defines store-specific commit information. It contains a reference -between a store name and the commit ID. +### 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 | | ----- | ---- | ----- | ----------- | -| `name` | [string](#string) | | | -| `commit_id` | [CommitID](#cosmos.base.store.v1beta1.CommitID) | | | +| `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 | - - + - +### 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 | +| `packet_ack_sequences` | [uint64](#uint64) | repeated | list of acknowledgement sequences | - -

Top

-## cosmos/base/store/v1beta1/snapshot.proto - + -### SnapshotIAVLItem -SnapshotIAVLItem is an exported IAVL node. +### QueryUnreceivedAcksResponse +QueryUnreceivedAcksResponse is the response type for the +Query/UnreceivedAcks RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | | -| `value` | [bytes](#bytes) | | | -| `version` | [int64](#int64) | | | -| `height` | [int32](#int32) | | | +| `sequences` | [uint64](#uint64) | repeated | list of unreceived acknowledgement sequences | +| `height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | query block height | - + -### SnapshotItem -SnapshotItem is an item contained in a rootmulti.Store snapshot. +### QueryUnreceivedPacketsRequest +QueryUnreceivedPacketsRequest is the request type for the +Query/UnreceivedPackets RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `store` | [SnapshotStoreItem](#cosmos.base.store.v1beta1.SnapshotStoreItem) | | | -| `iavl` | [SnapshotIAVLItem](#cosmos.base.store.v1beta1.SnapshotIAVLItem) | | | +| `port_id` | [string](#string) | | port unique identifier | +| `channel_id` | [string](#string) | | channel unique identifier | +| `packet_commitment_sequences` | [uint64](#uint64) | repeated | list of packet sequences | - + -### SnapshotStoreItem -SnapshotStoreItem contains metadata about a snapshotted store. +### QueryUnreceivedPacketsResponse +QueryUnreceivedPacketsResponse is the response type for the +Query/UnreceivedPacketCommitments RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `name` | [string](#string) | | | +| `sequences` | [uint64](#uint64) | repeated | list of unreceived packet sequences | +| `height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | query block height | @@ -2414,320 +2494,389 @@ SnapshotStoreItem contains metadata about a snapshotted store. + + + +### 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

-## cosmos/base/tendermint/v1beta1/query.proto +## ibc/core/channel/v1/genesis.proto - + -### GetBlockByHeightRequest -GetBlockByHeightRequest is the request type for the Query/GetBlockByHeight RPC method. +### GenesisState +GenesisState defines the ibc channel submodule's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `height` | [int64](#int64) | | | +| `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 | - + -### GetBlockByHeightResponse -GetBlockByHeightResponse is the response type for the Query/GetBlockByHeight RPC method. +### PacketSequence +PacketSequence defines the genesis type necessary to retrieve and store +next send and receive sequences. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `block_id` | [tendermint.types.BlockID](#tendermint.types.BlockID) | | | -| `block` | [tendermint.types.Block](#tendermint.types.Block) | | | +| `port_id` | [string](#string) | | | +| `channel_id` | [string](#string) | | | +| `sequence` | [uint64](#uint64) | | | + + + - + + + -### GetLatestBlockRequest -GetLatestBlockRequest is the request type for the Query/GetLatestBlock RPC method. + +

Top

+## ibc/core/channel/v1/channel.proto - + -### GetLatestBlockResponse -GetLatestBlockResponse is the response type for the Query/GetLatestBlock 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 | | ----- | ---- | ----- | ----------- | -| `block_id` | [tendermint.types.BlockID](#tendermint.types.BlockID) | | | -| `block` | [tendermint.types.Block](#tendermint.types.Block) | | | +| `result` | [bytes](#bytes) | | | +| `error` | [string](#string) | | | - + -### GetLatestValidatorSetRequest -GetLatestValidatorSetRequest is the request type for the Query/GetValidatorSetByHeight 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 defines an pagination for the 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 | - + -### GetLatestValidatorSetResponse -GetLatestValidatorSetResponse is the response type for the Query/GetValidatorSetByHeight RPC method. +### Counterparty +Counterparty defines a channel end counterparty | 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. | - - - - - - - - -### GetNodeInfoRequest -GetNodeInfoRequest is the request type for the Query/GetNodeInfo RPC method. +| `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 | - + -### GetNodeInfoResponse -GetNodeInfoResponse is the request type for the Query/GetNodeInfo RPC method. +### IdentifiedChannel +IdentifiedChannel defines a channel with additional port and channel +identifier fields. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `default_node_info` | [tendermint.p2p.DefaultNodeInfo](#tendermint.p2p.DefaultNodeInfo) | | | -| `application_version` | [VersionInfo](#cosmos.base.tendermint.v1beta1.VersionInfo) | | | +| `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 | - + -### GetSyncingRequest -GetSyncingRequest is the request type for the Query/GetSyncing RPC method. +### Packet +Packet defines a type that carries data across different chains through IBC + + +| 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 | - + -### GetSyncingResponse -GetSyncingResponse is the response type for the Query/GetSyncing 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 | | ----- | ---- | ----- | ----------- | -| `syncing` | [bool](#bool) | | | +| `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. | + - -### GetValidatorSetByHeightRequest -GetValidatorSetByHeightRequest is the request type for the Query/GetValidatorSetByHeight RPC method. + +### Order +Order defines if a channel is ORDERED or UNORDERED -| 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. | +| 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. | - + -### 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. | + +

Top

+## ibc/core/connection/v1/tx.proto - + -### Module -Module is the type for VersionInfo +### MsgConnectionOpenAck +MsgConnectionOpenAck defines a msg sent by a Relayer to Chain A to +acknowledge the change of connection state to TRYOPEN on Chain B. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `path` | [string](#string) | | module path | -| `version` | [string](#string) | | module version | -| `sum` | [string](#string) | | checksum | - - +| `connection_id` | [string](#string) | | | +| `counterparty_connection_id` | [string](#string) | | | +| `version` | [Version](#ibc.core.connection.v1.Version) | | | +| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | +| `proof_try` | [bytes](#bytes) | | proof of the initialization the connection on Chain B: `UNITIALIZED -> TRYOPEN` | +| `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) | | | - -### Validator -Validator is the type for the validator-set. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | | -| `pub_key` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `voting_power` | [int64](#int64) | | | -| `proposer_priority` | [int64](#int64) | | | +### MsgConnectionOpenAckResponse +MsgConnectionOpenAckResponse defines the Msg/ConnectionOpenAck response type. - + -### VersionInfo -VersionInfo is the type for the GetNodeInfoResponse message. +### MsgConnectionOpenConfirm +MsgConnectionOpenConfirm defines a msg sent by a Relayer to Chain B to +acknowledge the change of connection state to OPEN on Chain A. | 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 | | +| `connection_id` | [string](#string) | | | +| `proof_ack` | [bytes](#bytes) | | proof for the change of the connection state on Chain A: `INIT -> OPEN` | +| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | +| `signer` | [string](#string) | | | - - + - +### MsgConnectionOpenConfirmResponse +MsgConnectionOpenConfirmResponse defines the Msg/ConnectionOpenConfirm response type. - -### 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}| - + +### MsgConnectionOpenInit +MsgConnectionOpenInit defines the msg sent by an account on Chain A to +initialize a connection with Chain B. - -

Top

-## cosmos/capability/v1beta1/capability.proto +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `client_id` | [string](#string) | | | +| `counterparty` | [Counterparty](#ibc.core.connection.v1.Counterparty) | | | +| `version` | [Version](#ibc.core.connection.v1.Version) | | | +| `delay_period` | [uint64](#uint64) | | | +| `signer` | [string](#string) | | | - -### 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) | | | + +### MsgConnectionOpenInitResponse +MsgConnectionOpenInitResponse defines the Msg/ConnectionOpenInit response type. - -### CapabilityOwners -CapabilityOwners defines a set of owners of a single Capability. The set of -owners must be unique. + + +### MsgConnectionOpenTry +MsgConnectionOpenTry defines a msg sent by a Relayer to try to open a +connection on Chain B. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `owners` | [Owner](#cosmos.capability.v1beta1.Owner) | repeated | | - - +| `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) | | | - -### Owner -Owner defines a single capability owner. An owner is defined by the name of -capability and the module name. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `module` | [string](#string) | | | -| `name` | [string](#string) | | | +### MsgConnectionOpenTryResponse +MsgConnectionOpenTryResponse defines the Msg/ConnectionOpenTry response type. @@ -2739,314 +2888,337 @@ capability and the module name. + + + +### 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

-## cosmos/capability/v1beta1/genesis.proto +## ibc/core/connection/v1/connection.proto - + -### GenesisOwners -GenesisOwners defines the capability owners with their corresponding index. +### ClientPaths +ClientPaths define all the connection paths for a client state. | 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. | +| `paths` | [string](#string) | repeated | list of connection paths | - + -### GenesisState -GenesisState defines the capability module's genesis state. +### ConnectionEnd +ConnectionEnd defines a stateful object on a chain connected to another +separate one. +NOTE: there must only be 2 defined ConnectionEnds to establish +a connection between two chains. | 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. | +| `client_id` | [string](#string) | | client associated with this connection. | +| `versions` | [Version](#ibc.core.connection.v1.Version) | repeated | IBC version which can be utilised to determine encodings or protocols for channels or packets utilising this connection. | +| `state` | [State](#ibc.core.connection.v1.State) | | current state of the connection end. | +| `counterparty` | [Counterparty](#ibc.core.connection.v1.Counterparty) | | counterparty chain associated with this connection. | +| `delay_period` | [uint64](#uint64) | | delay period that must pass before a consensus state can be used for packet-verification NOTE: delay period logic is only implemented by some clients. | - - + - +### ConnectionPaths +ConnectionPaths define all the connection paths for a given client state. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `client_id` | [string](#string) | | client state unique identifier | +| `paths` | [string](#string) | repeated | list of connection paths | - -

Top

-## cosmos/crisis/v1beta1/genesis.proto - + -### GenesisState -GenesisState defines the crisis module's genesis state. +### Counterparty +Counterparty defines the counterparty chain associated with a connection end. | 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. | +| `client_id` | [string](#string) | | identifies the client on the counterparty chain associated with a given connection. | +| `connection_id` | [string](#string) | | identifies the connection end on the counterparty chain associated with a given connection. | +| `prefix` | [ibc.core.commitment.v1.MerklePrefix](#ibc.core.commitment.v1.MerklePrefix) | | commitment merkle prefix of the counterparty chain. | - - + - +### IdentifiedConnection +IdentifiedConnection defines a connection with additional connection +identifier field. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `id` | [string](#string) | | connection identifier. | +| `client_id` | [string](#string) | | client associated with this connection. | +| `versions` | [Version](#ibc.core.connection.v1.Version) | repeated | IBC version which can be utilised to determine encodings or protocols for channels or packets utilising this connection | +| `state` | [State](#ibc.core.connection.v1.State) | | current state of the connection end. | +| `counterparty` | [Counterparty](#ibc.core.connection.v1.Counterparty) | | counterparty chain associated with this connection. | +| `delay_period` | [uint64](#uint64) | | delay period associated with this connection. | - -

Top

-## cosmos/crisis/v1beta1/tx.proto - + -### MsgVerifyInvariant -MsgVerifyInvariant represents a message to verify a particular invariance. +### Version +Version defines the versioning scheme used to negotiate the IBC verison in +the connection handshake. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `sender` | [string](#string) | | | -| `invariant_module_name` | [string](#string) | | | -| `invariant_route` | [string](#string) | | | - - +| `identifier` | [string](#string) | | unique version identifier | +| `features` | [string](#string) | repeated | list of features compatible with the specified identifier | - -### MsgVerifyInvariantResponse -MsgVerifyInvariantResponse defines the Msg/VerifyInvariant response type. + + +### State +State defines if a connection is in one of the following states: +INIT, TRYOPEN, OPEN or UNINITIALIZED. +| Name | Number | Description | +| ---- | ------ | ----------- | +| STATE_UNINITIALIZED_UNSPECIFIED | 0 | Default State | +| STATE_INIT | 1 | A connection end has just started the opening handshake. | +| STATE_TRYOPEN | 2 | A connection end has acknowledged the handshake step on the counterparty chain. | +| STATE_OPEN | 3 | A connection end has completed the handshake. | - - - - -### 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. | | - - +

Top

-## cosmos/crypto/ed25519/keys.proto +## ibc/core/connection/v1/query.proto - + -### PrivKey -Deprecated: PrivKey defines a ed25519 private key. -NOTE: ed25519 keys must not be used in SDK apps except in a tendermint validator context. +### QueryClientConnectionsRequest +QueryClientConnectionsRequest is the request type for the +Query/ClientConnections RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | | +| `client_id` | [string](#string) | | client identifier associated with a connection | - + -### PubKey -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. +### QueryClientConnectionsResponse +QueryClientConnectionsResponse is the response type for the +Query/ClientConnections RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | | +| `connection_paths` | [string](#string) | repeated | slice of all the connection paths associated with a client. | +| `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 generated | - - + - +### QueryConnectionClientStateRequest +QueryConnectionClientStateRequest is the request type for the +Query/ConnectionClientState RPC method - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `connection_id` | [string](#string) | | connection identifier | - -

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. +### QueryConnectionClientStateResponse +QueryConnectionClientStateResponse is the response type for the +Query/ConnectionClientState RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `threshold` | [uint32](#uint32) | | | -| `public_keys` | [google.protobuf.Any](#google.protobuf.Any) | repeated | | +| `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 | - - + - +### QueryConnectionConsensusStateRequest +QueryConnectionConsensusStateRequest is the request type for the +Query/ConnectionConsensusState RPC method - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `connection_id` | [string](#string) | | connection identifier | +| `revision_number` | [uint64](#uint64) | | | +| `revision_height` | [uint64](#uint64) | | | - -

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. +### QueryConnectionConsensusStateResponse +QueryConnectionConsensusStateResponse is the response type for the +Query/ConnectionConsensusState RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `extra_bits_stored` | [uint32](#uint32) | | | -| `elems` | [bytes](#bytes) | | | +| `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 | - + -### 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. +### QueryConnectionRequest +QueryConnectionRequest is the request type for the Query/Connection RPC +method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `signatures` | [bytes](#bytes) | repeated | | +| `connection_id` | [string](#string) | | connection unique identifier | - - + - +### QueryConnectionResponse +QueryConnectionResponse is the response type for the Query/Connection RPC +method. Besides the connection end, it includes a proof and the height from +which the proof was retrieved. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `connection` | [ConnectionEnd](#ibc.core.connection.v1.ConnectionEnd) | | connection associated with the request identifier | +| `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

-## cosmos/crypto/secp256k1/keys.proto - + -### PrivKey -PrivKey defines a secp256k1 private key. +### QueryConnectionsRequest +QueryConnectionsRequest is the request type for the Query/Connections RPC +method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | | - + -### 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. +### QueryConnectionsResponse +QueryConnectionsResponse is the response type for the Query/Connections RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | | +| `connections` | [IdentifiedConnection](#ibc.core.connection.v1.IdentifiedConnection) | repeated | list of stored connections 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 | @@ -3058,692 +3230,768 @@ This prefix is followed with the x-coordinate. + + + +### Query +Query provides defines the gRPC querier service + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Connection` | [QueryConnectionRequest](#ibc.core.connection.v1.QueryConnectionRequest) | [QueryConnectionResponse](#ibc.core.connection.v1.QueryConnectionResponse) | Connection queries an IBC connection end. | GET|/ibc/core/connection/v1beta1/connections/{connection_id}| +| `Connections` | [QueryConnectionsRequest](#ibc.core.connection.v1.QueryConnectionsRequest) | [QueryConnectionsResponse](#ibc.core.connection.v1.QueryConnectionsResponse) | Connections queries all the IBC connections of a chain. | GET|/ibc/core/connection/v1beta1/connections| +| `ClientConnections` | [QueryClientConnectionsRequest](#ibc.core.connection.v1.QueryClientConnectionsRequest) | [QueryClientConnectionsResponse](#ibc.core.connection.v1.QueryClientConnectionsResponse) | ClientConnections queries the connection paths associated with a client state. | GET|/ibc/core/connection/v1beta1/client_connections/{client_id}| +| `ConnectionClientState` | [QueryConnectionClientStateRequest](#ibc.core.connection.v1.QueryConnectionClientStateRequest) | [QueryConnectionClientStateResponse](#ibc.core.connection.v1.QueryConnectionClientStateResponse) | ConnectionClientState queries the client state associated with the connection. | GET|/ibc/core/connection/v1beta1/connections/{connection_id}/client_state| +| `ConnectionConsensusState` | [QueryConnectionConsensusStateRequest](#ibc.core.connection.v1.QueryConnectionConsensusStateRequest) | [QueryConnectionConsensusStateResponse](#ibc.core.connection.v1.QueryConnectionConsensusStateResponse) | ConnectionConsensusState queries the consensus state associated with the connection. | GET|/ibc/core/connection/v1beta1/connections/{connection_id}/consensus_state/revision/{revision_number}/height/{revision_height}| + - +

Top

-## cosmos/distribution/v1beta1/distribution.proto +## ibc/core/connection/v1/genesis.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. +### GenesisState +GenesisState defines the ibc connection submodule's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `title` | [string](#string) | | | -| `description` | [string](#string) | | | -| `recipient` | [string](#string) | | | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `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 | + - + -### CommunityPoolSpendProposalWithDeposit -CommunityPoolSpendProposalWithDeposit defines a CommunityPoolSpendProposal -with a deposit + + + + + + + +

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 | | ----- | ---- | ----- | ----------- | -| `title` | [string](#string) | | | -| `description` | [string](#string) | | | -| `recipient` | [string](#string) | | | -| `amount` | [string](#string) | | | -| `deposit` | [string](#string) | | | +| `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 | - + -### DelegationDelegatorReward -DelegationDelegatorReward represents the properties -of a delegator's delegation reward. +### ConsensusState +ConsensusState defines the consensus state from Tendermint. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator_address` | [string](#string) | | | -| `reward` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | +| `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) | | | - + -### 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. +### Fraction +Fraction defines the protobuf message type for tmmath.Fraction that only supports positive values. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `previous_period` | [uint64](#uint64) | | | -| `stake` | [string](#string) | | | -| `height` | [uint64](#uint64) | | | +| `numerator` | [uint64](#uint64) | | | +| `denominator` | [uint64](#uint64) | | | - + -### FeePool -FeePool is the global fee pool for distribution. +### 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 | | ----- | ---- | ----- | ----------- | -| `community_pool` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | +| `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) | | | - + -### Params -Params defines the set of params for the distribution module. +### Misbehaviour +Misbehaviour is a wrapper over two conflicting Headers +that implements Misbehaviour interface expected by ICS-02 | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `community_tax` | [string](#string) | | | -| `base_proposer_reward` | [string](#string) | | | -| `bonus_proposer_reward` | [string](#string) | | | -| `withdraw_addr_enabled` | [bool](#bool) | | | +| `client_id` | [string](#string) | | | +| `header_1` | [Header](#ibc.lightclients.tendermint.v1.Header) | | | +| `header_2` | [Header](#ibc.lightclients.tendermint.v1.Header) | | | + - + -### ValidatorAccumulatedCommission -ValidatorAccumulatedCommission represents accumulated commission -for a validator kept as a running counter, can be withdrawn at any time. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `commission` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | + +

Top

+## ibc/lightclients/localhost/v1/localhost.proto - + -### 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. +### ClientState +ClientState defines a loopback (localhost) client. It requires (read-only) +access to keys outside the client prefix. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `rewards` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | -| `period` | [uint64](#uint64) | | | +| `chain_id` | [string](#string) | | self chain ID | +| `height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | self latest block height | + - + -### 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 | -| ----- | ---- | ----- | ----------- | -| `cumulative_reward_ratio` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | -| `reference_count` | [uint32](#uint32) | | | + +

Top

+## ibc/lightclients/solomachine/v1/solomachine.proto - + -### ValidatorOutstandingRewards -ValidatorOutstandingRewards represents outstanding (un-withdrawn) rewards -for a validator inexpensive to track, allows simple sanity checks. +### ChannelStateData +ChannelStateData returns the SignBytes data for channel state +verification. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `rewards` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | +| `path` | [bytes](#bytes) | | | +| `channel` | [ibc.core.channel.v1.Channel](#ibc.core.channel.v1.Channel) | | | - + -### 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. +### ClientState +ClientState defines a solo machine client that tracks the current consensus +state and if the client is frozen. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator_period` | [uint64](#uint64) | | | -| `fraction` | [string](#string) | | | +| `sequence` | [uint64](#uint64) | | latest sequence of the client state | +| `frozen_sequence` | [uint64](#uint64) | | frozen sequence of the solo machine | +| `consensus_state` | [ConsensusState](#ibc.lightclients.solomachine.v1.ConsensusState) | | | +| `allow_update_after_proposal` | [bool](#bool) | | when set to true, will allow governance to update a solo machine client. The client will be unfrozen if it is frozen. | - + -### ValidatorSlashEvents -ValidatorSlashEvents is a collection of ValidatorSlashEvent messages. +### ClientStateData +ClientStateData returns the SignBytes data for client state verification. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator_slash_events` | [ValidatorSlashEvent](#cosmos.distribution.v1beta1.ValidatorSlashEvent) | repeated | | +| `path` | [bytes](#bytes) | | | +| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | | - - + - +### ConnectionStateData +ConnectionStateData returns the SignBytes data for connection state +verification. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `path` | [bytes](#bytes) | | | +| `connection` | [ibc.core.connection.v1.ConnectionEnd](#ibc.core.connection.v1.ConnectionEnd) | | | - -

Top

-## cosmos/distribution/v1beta1/genesis.proto - + -### DelegatorStartingInfoRecord -DelegatorStartingInfoRecord used for import / export via genesis json. +### ConsensusState +ConsensusState defines a solo machine consensus state. The sequence of a consensus state +is contained in the "height" key used in storing the consensus state. | 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. | +| `public_key` | [google.protobuf.Any](#google.protobuf.Any) | | public key of the solo machine | +| `diversifier` | [string](#string) | | diversifier allows the same public key to be re-used across different solo machine clients (potentially on different chains) without being considered misbehaviour. | +| `timestamp` | [uint64](#uint64) | | | - + -### 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. +### ConsensusStateData +ConsensusStateData returns the SignBytes data for consensus state +verification. | 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. | +| `path` | [bytes](#bytes) | | | +| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | | - + -### GenesisState -GenesisState defines the distribution module's genesis state. +### Header +Header defines a solo machine consensus header | 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. | +| `sequence` | [uint64](#uint64) | | sequence to update solo machine public key at | +| `timestamp` | [uint64](#uint64) | | | +| `signature` | [bytes](#bytes) | | | +| `new_public_key` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `new_diversifier` | [string](#string) | | | - + -### ValidatorAccumulatedCommissionRecord -ValidatorAccumulatedCommissionRecord is used for import / export via genesis -json. +### HeaderData +HeaderData returns the SignBytes data for update verification. | 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. | +| `new_pub_key` | [google.protobuf.Any](#google.protobuf.Any) | | header public key | +| `new_diversifier` | [string](#string) | | header diversifier | - + -### ValidatorCurrentRewardsRecord -ValidatorCurrentRewardsRecord is used for import / export via genesis json. +### Misbehaviour +Misbehaviour defines misbehaviour for a solo machine which consists +of a sequence and two signatures over different messages at that sequence. | 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. | +| `client_id` | [string](#string) | | | +| `sequence` | [uint64](#uint64) | | | +| `signature_one` | [SignatureAndData](#ibc.lightclients.solomachine.v1.SignatureAndData) | | | +| `signature_two` | [SignatureAndData](#ibc.lightclients.solomachine.v1.SignatureAndData) | | | - + -### ValidatorHistoricalRewardsRecord -ValidatorHistoricalRewardsRecord is used for import / export via genesis -json. +### NextSequenceRecvData +NextSequenceRecvData returns the SignBytes data for verification of the next +sequence to be received. | 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. | +| `path` | [bytes](#bytes) | | | +| `next_seq_recv` | [uint64](#uint64) | | | - + -### ValidatorOutstandingRewardsRecord -ValidatorOutstandingRewardsRecord is used for import/export via genesis json. +### PacketAcknowledgementData +PacketAcknowledgementData returns the SignBytes data for acknowledgement +verification. | 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. | +| `path` | [bytes](#bytes) | | | +| `acknowledgement` | [bytes](#bytes) | | | - + -### ValidatorSlashEventRecord -ValidatorSlashEventRecord is used for import / export via genesis json. +### PacketCommitmentData +PacketCommitmentData returns the SignBytes data for packet commitment +verification. | 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. | +| `path` | [bytes](#bytes) | | | +| `commitment` | [bytes](#bytes) | | | - - + - +### PacketReceiptAbsenceData +PacketReceiptAbsenceData returns the SignBytes data for +packet receipt absence verification. - + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `path` | [bytes](#bytes) | | | - -

Top

-## cosmos/distribution/v1beta1/query.proto + - +### SignBytes +SignBytes defines the signed bytes used for signature verification. -### QueryCommunityPoolRequest -QueryCommunityPoolRequest is the request type for the Query/CommunityPool RPC -method. + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `sequence` | [uint64](#uint64) | | | +| `timestamp` | [uint64](#uint64) | | | +| `diversifier` | [string](#string) | | | +| `data_type` | [DataType](#ibc.lightclients.solomachine.v1.DataType) | | type of the data used | +| `data` | [bytes](#bytes) | | marshaled data | - + -### QueryCommunityPoolResponse -QueryCommunityPoolResponse is the response type for the Query/CommunityPool -RPC method. +### SignatureAndData +SignatureAndData contains a signature and the data signed over to create that +signature. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `pool` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | pool defines community pool's coins. | +| `signature` | [bytes](#bytes) | | | +| `data_type` | [DataType](#ibc.lightclients.solomachine.v1.DataType) | | | +| `data` | [bytes](#bytes) | | | +| `timestamp` | [uint64](#uint64) | | | - + -### QueryDelegationRewardsRequest -QueryDelegationRewardsRequest is the request type for the -Query/DelegationRewards RPC method. +### TimestampedSignatureData +TimestampedSignatureData contains the signature data and the timestamp of the +signature. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | delegator_address defines the delegator address to query for. | -| `validator_address` | [string](#string) | | validator_address defines the validator address to query for. | +| `signature_data` | [bytes](#bytes) | | | +| `timestamp` | [uint64](#uint64) | | | + - -### QueryDelegationRewardsResponse -QueryDelegationRewardsResponse is the response type for the -Query/DelegationRewards RPC method. + +### DataType +DataType defines the type of solo machine proof being created. This is done to preserve uniqueness of different +data sign byte encodings. + +| Name | Number | Description | +| ---- | ------ | ----------- | +| DATA_TYPE_UNINITIALIZED_UNSPECIFIED | 0 | Default State | +| DATA_TYPE_CLIENT_STATE | 1 | Data type for client state verification | +| DATA_TYPE_CONSENSUS_STATE | 2 | Data type for consensus state verification | +| DATA_TYPE_CONNECTION_STATE | 3 | Data type for connection state verification | +| DATA_TYPE_CHANNEL_STATE | 4 | Data type for channel state verification | +| DATA_TYPE_PACKET_COMMITMENT | 5 | Data type for packet commitment verification | +| DATA_TYPE_PACKET_ACKNOWLEDGEMENT | 6 | Data type for packet acknowledgement verification | +| DATA_TYPE_PACKET_RECEIPT_ABSENCE | 7 | Data type for packet receipt absence verification | +| DATA_TYPE_NEXT_SEQUENCE_RECV | 8 | Data type for next sequence recv verification | +| DATA_TYPE_HEADER | 9 | Data type for header verification | -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `rewards` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | rewards defines the rewards accrued by a delegation. | + + + - + +

Top

-### QueryDelegationTotalRewardsRequest -QueryDelegationTotalRewardsRequest is the request type for the -Query/DelegationTotalRewards RPC method. +## cosmos/upgrade/v1beta1/upgrade.proto + + + + + +### CancelSoftwareUpgradeProposal +CancelSoftwareUpgradeProposal is a gov Content type for cancelling a software +upgrade. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | delegator_address defines the delegator address to query for. | +| `title` | [string](#string) | | | +| `description` | [string](#string) | | | - + -### QueryDelegationTotalRewardsResponse -QueryDelegationTotalRewardsResponse is the response type for the -Query/DelegationTotalRewards RPC method. +### Plan +Plan specifies information about a planned upgrade and when it should occur. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `rewards` | [DelegationDelegatorReward](#cosmos.distribution.v1beta1.DelegationDelegatorReward) | repeated | rewards defines all the rewards accrued by a delegator. | -| `total` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | total defines the sum of all the rewards. | +| `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 | - + -### QueryDelegatorValidatorsRequest -QueryDelegatorValidatorsRequest is the request type for the -Query/DelegatorValidators RPC method. +### SoftwareUpgradeProposal +SoftwareUpgradeProposal is a gov Content type for initiating a software +upgrade. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | delegator_address defines the delegator address to query for. | +| `title` | [string](#string) | | | +| `description` | [string](#string) | | | +| `plan` | [Plan](#cosmos.upgrade.v1beta1.Plan) | | | + - + -### QueryDelegatorValidatorsResponse -QueryDelegatorValidatorsResponse is the response type for the -Query/DelegatorValidators RPC method. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `validators` | [string](#string) | repeated | validators defines the validators a delegator is delegating for. | + +

Top

+## cosmos/upgrade/v1beta1/query.proto - + -### QueryDelegatorWithdrawAddressRequest -QueryDelegatorWithdrawAddressRequest is the request type for the -Query/DelegatorWithdrawAddress RPC method. +### QueryAppliedPlanRequest +QueryCurrentPlanRequest is the request type for the Query/AppliedPlan RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | delegator_address defines the delegator address to query for. | +| `name` | [string](#string) | | name is the name of the applied plan to query for. | - + -### QueryDelegatorWithdrawAddressResponse -QueryDelegatorWithdrawAddressResponse is the response type for the -Query/DelegatorWithdrawAddress RPC method. +### QueryAppliedPlanResponse +QueryAppliedPlanResponse is the response type for the Query/AppliedPlan RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `withdraw_address` | [string](#string) | | withdraw_address defines the delegator address to query for. | +| `height` | [int64](#int64) | | height is the block height at which the plan was applied. | - + -### QueryParamsRequest -QueryParamsRequest is the request type for the Query/Params RPC method. +### QueryCurrentPlanRequest +QueryCurrentPlanRequest is the request type for the Query/CurrentPlan RPC +method. - + -### QueryParamsResponse -QueryParamsResponse is the response type for the Query/Params RPC method. +### QueryCurrentPlanResponse +QueryCurrentPlanResponse is the response type for the Query/CurrentPlan RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.distribution.v1beta1.Params) | | params defines the parameters of the module. | +| `plan` | [Plan](#cosmos.upgrade.v1beta1.Plan) | | plan is the current upgrade plan. | - + -### QueryValidatorCommissionRequest -QueryValidatorCommissionRequest is the request type for the -Query/ValidatorCommission RPC method +### QueryUpgradedConsensusStateRequest +QueryUpgradedConsensusStateRequest is the request type for the Query/UpgradedConsensusState +RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator_address` | [string](#string) | | validator_address defines the validator address to query for. | +| `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 | - + -### QueryValidatorCommissionResponse -QueryValidatorCommissionResponse is the response type for the -Query/ValidatorCommission RPC method +### QueryUpgradedConsensusStateResponse +QueryUpgradedConsensusStateResponse is the response type for the Query/UpgradedConsensusState +RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `commission` | [ValidatorAccumulatedCommission](#cosmos.distribution.v1beta1.ValidatorAccumulatedCommission) | | commission defines the commision the validator received. | +| `upgraded_consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | | + - + -### QueryValidatorOutstandingRewardsRequest -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. | + +### 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

-### QueryValidatorOutstandingRewardsResponse -QueryValidatorOutstandingRewardsResponse is the response type for the -Query/ValidatorOutstandingRewards RPC method. +## 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 | | ----- | ---- | ----- | ----------- | -| `rewards` | [ValidatorOutstandingRewards](#cosmos.distribution.v1beta1.ValidatorOutstandingRewards) | | | +| `index` | [uint64](#uint64) | | | - + -### QueryValidatorSlashesRequest -QueryValidatorSlashesRequest is the request type for the -Query/ValidatorSlashes RPC method +### CapabilityOwners +CapabilityOwners defines a set of owners of a single Capability. The set of +owners must be unique. | 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. | +| `owners` | [Owner](#cosmos.capability.v1beta1.Owner) | repeated | | - + -### QueryValidatorSlashesResponse -QueryValidatorSlashesResponse is the response type for the -Query/ValidatorSlashes 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 | | ----- | ---- | ----- | ----------- | -| `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. | +| `module` | [string](#string) | | | +| `name` | [string](#string) | | | @@ -3755,136 +4003,141 @@ 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/capability/v1beta1/genesis.proto - -

Top

+ -## cosmos/distribution/v1beta1/tx.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. | - -### 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) | | | + +### 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. | - -### 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) | | | + +

Top

+## cosmos/params/v1beta1/params.proto + +### ParamChange +ParamChange defines an individual parameter change, for use in +ParameterChangeProposal. - -### MsgSetWithdrawAddressResponse -MsgSetWithdrawAddressResponse defines the Msg/SetWithdrawAddress response type. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `subspace` | [string](#string) | | | +| `key` | [string](#string) | | | +| `value` | [string](#string) | | | - + -### MsgWithdrawDelegatorReward -MsgWithdrawDelegatorReward represents delegation withdrawal to a delegator -from a single validator. +### ParameterChangeProposal +ParameterChangeProposal defines a proposal to change one or more parameters. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `validator_address` | [string](#string) | | | +| `title` | [string](#string) | | | +| `description` | [string](#string) | | | +| `changes` | [ParamChange](#cosmos.params.v1beta1.ParamChange) | repeated | | + - + -### MsgWithdrawDelegatorRewardResponse -MsgWithdrawDelegatorRewardResponse defines the Msg/WithdrawDelegatorReward response type. + + + + +

Top

+ +## cosmos/params/v1beta1/query.proto - + -### MsgWithdrawValidatorCommission -MsgWithdrawValidatorCommission withdraws the full commission to the validator -address. +### QueryParamsRequest +QueryParamsRequest is request type for the Query/Params RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator_address` | [string](#string) | | | +| `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. | - + -### MsgWithdrawValidatorCommissionResponse -MsgWithdrawValidatorCommissionResponse defines the Msg/WithdrawValidatorCommission response type. +### QueryParamsResponse +QueryParamsResponse is response type for the Query/Params RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `param` | [ParamChange](#cosmos.params.v1beta1.ParamChange) | | param defines the queried parameter. | @@ -3897,152 +4150,171 @@ MsgWithdrawValidatorCommissionResponse defines the Msg/WithdrawValidatorCommissi - + -### Msg -Msg defines the distribution Msg service. +### Query +Query defines the gRPC querier 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. | | +| `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/evidence/v1beta1/evidence.proto +## cosmos/authz/v1beta1/tx.proto - + -### Equivocation -Equivocation implements the Evidence interface and defines evidence of double -signing misbehavior. +### 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 | | ----- | ---- | ----- | ----------- | -| `height` | [int64](#int64) | | | -| `time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | -| `power` | [int64](#int64) | | | -| `consensus_address` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `msgs` | [google.protobuf.Any](#google.protobuf.Any) | repeated | | - - + - +### MsgExecAuthorizedResponse +MsgExecAuthorizedResponse defines the Msg/MsgExecAuthorizedResponse response type. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `result` | [cosmos.base.abci.v1beta1.Result](#cosmos.base.abci.v1beta1.Result) | | | - -

Top

-## cosmos/evidence/v1beta1/genesis.proto - + -### GenesisState -GenesisState defines the evidence module's genesis state. +### MsgGrantAuthorizationRequest +MsgGrantAuthorizationRequest grants the provided authorization to the grantee on the granter's +account with the provided expiration time. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | repeated | evidence defines all the evidence at genesis. | - - +| `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/evidence/v1beta1/query.proto - + -### QueryAllEvidenceRequest -QueryEvidenceRequest is the request type for the Query/AllEvidence 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 | | ----- | ---- | ----- | ----------- | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `method_name` | [string](#string) | | | - + -### QueryAllEvidenceResponse -QueryAllEvidenceResponse is the response type for the Query/AllEvidence RPC -method. +### MsgRevokeAuthorizationResponse +MsgRevokeAuthorizationResponse defines the Msg/MsgRevokeAuthorizationResponse response type. -| 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. | + + + - -### QueryEvidenceRequest -QueryEvidenceRequest is the request type for the Query/Evidence RPC method. + + +### 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/authz.proto + + + + + +### AuthorizationGrant +AuthorizationGrant gives permissions to execute +the provide method with expiration time. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `evidence_hash` | [bytes](#bytes) | | evidence_hash defines the hash of the requested evidence. | +| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | - + -### QueryEvidenceResponse -QueryEvidenceResponse is the response type for the Query/Evidence 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 | | ----- | ---- | ----- | ----------- | -| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | | evidence returns the requested evidence. | +| `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` | @@ -4054,54 +4326,76 @@ QueryEvidenceResponse is the response type for the Query/Evidence RPC method. + + + + + +

Top

+ +## cosmos/authz/v1beta1/query.proto + + + + + +### 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) | | | + + + + - -### 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| +### 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/evidence/v1beta1/tx.proto - + -### MsgSubmitEvidence -MsgSubmitEvidence represents a message that supports submitting arbitrary -Evidence of misbehavior such as equivocation or counterfactual signing. +### QueryAuthorizationsRequest +QueryAuthorizationsRequest is the request type for the Query/Authorizations RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `submitter` | [string](#string) | | | -| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | - + -### MsgSubmitEvidenceResponse -MsgSubmitEvidenceResponse defines the Msg/SubmitEvidence response type. +### QueryAuthorizationsResponse +QueryAuthorizationsResponse is the response type for the Query/Authorizations RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `hash` | [bytes](#bytes) | | hash defines the hash of the evidence. | +| `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. | @@ -4114,108 +4408,102 @@ MsgSubmitEvidenceResponse defines the Msg/SubmitEvidence response type. - + -### Msg -Msg defines the evidence Msg service. +### Query +Query defines the gRPC querier 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. | | +| `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/authz/v1beta1/genesis.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. +### GenesisState +GenesisState defines the authz module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `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 | +| `authorization` | [GrantAuthorization](#cosmos.authz.v1beta1.GrantAuthorization) | repeated | | - + -### Duration -Duration is a span of a clock time or number of blocks. -This is designed to be added to an ExpiresAt struct. +### GrantAuthorization +GrantAuthorization defines the GenesisState/GrantAuthorization type. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `duration` | [google.protobuf.Duration](#google.protobuf.Duration) | | | -| `blocks` | [uint64](#uint64) | | | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | + - + -### ExpiresAt -ExpiresAt is a point in time where something expires. -It may be *either* block time or block height + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | -| `height` | [int64](#int64) | | | + +

Top

+## cosmos/evidence/v1beta1/tx.proto - + -### FeeAllowanceGrant -FeeAllowanceGrant is stored in the KVStore to record a grant with full context +### MsgSubmitEvidence +MsgSubmitEvidence represents a message that supports submitting arbitrary +Evidence of misbehavior such as equivocation or counterfactual signing. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | -| `allowance` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `submitter` | [string](#string) | | | +| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | | | - + -### PeriodicFeeAllowance -PeriodicFeeAllowance extends FeeAllowance to allow for both a maximum cap, -as well as a limit per time period. +### MsgSubmitEvidenceResponse +MsgSubmitEvidenceResponse defines the Msg/SubmitEvidence response type. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `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 | +| `hash` | [bytes](#bytes) | | hash defines the hash of the evidence. | @@ -4227,26 +4515,40 @@ as well as a limit per time period. + + + +### 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/feegrant/v1beta1/genesis.proto +## cosmos/evidence/v1beta1/evidence.proto - + -### GenesisState -GenesisState contains a set of fee allowances, persisted from the store +### Equivocation +Equivocation implements the Evidence interface and defines evidence of double +signing misbehavior. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `fee_allowances` | [FeeAllowanceGrant](#cosmos.feegrant.v1beta1.FeeAllowanceGrant) | repeated | | +| `height` | [int64](#int64) | | | +| `time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `power` | [int64](#int64) | | | +| `consensus_address` | [string](#string) | | | @@ -4262,70 +4564,70 @@ GenesisState contains a set of fee allowances, persisted from the store - +

Top

-## cosmos/feegrant/v1beta1/query.proto +## cosmos/evidence/v1beta1/query.proto - + -### QueryFeeAllowanceRequest -QueryFeeAllowanceRequest is the request type for the Query/FeeAllowance RPC method. +### QueryAllEvidenceRequest +QueryEvidenceRequest is the request type for the Query/AllEvidence RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | - + -### QueryFeeAllowanceResponse -QueryFeeAllowanceResponse is the response type for the Query/FeeAllowance RPC method. +### QueryAllEvidenceResponse +QueryAllEvidenceResponse is the response type for the Query/AllEvidence RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `fee_allowance` | [FeeAllowanceGrant](#cosmos.feegrant.v1beta1.FeeAllowanceGrant) | | fee_allowance is a fee_allowance granted for grantee by granter. | +| `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. | - + -### QueryFeeAllowancesRequest -QueryFeeAllowancesRequest is the request type for the Query/FeeAllowances RPC method. +### QueryEvidenceRequest +QueryEvidenceRequest is the request type for the Query/Evidence 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. | +| `evidence_hash` | [bytes](#bytes) | | evidence_hash defines the hash of the requested evidence. | - + -### QueryFeeAllowancesResponse -QueryFeeAllowancesResponse is the response type for the Query/FeeAllowances RPC method. +### QueryEvidenceResponse +QueryEvidenceResponse is the response type for the Query/Evidence RPC method. | 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. | +| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | | evidence returns the requested evidence. | @@ -4338,628 +4640,656 @@ 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}| +| `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/feegrant/v1beta1/tx.proto +## cosmos/evidence/v1beta1/genesis.proto - + -### MsgGrantFeeAllowance -MsgGrantFeeAllowance adds permission for Grantee to spend up to Allowance -of fees from the account of Granter. +### GenesisState +GenesisState defines the evidence module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | -| `allowance` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | repeated | evidence defines all the evidence at genesis. | + - + -### MsgGrantFeeAllowanceResponse -MsgGrantFeeAllowanceResponse defines the Msg/GrantFeeAllowanceResponse response type. + + + +

Top

+## cosmos/tx/v1beta1/tx.proto - -### MsgRevokeFeeAllowance -MsgRevokeFeeAllowance removes any existing FeeAllowance from Granter to Grantee. + + + +### AuthInfo +AuthInfo describes the fee and signer modes that are used to sign a +transaction. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | +| `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. | - + -### MsgRevokeFeeAllowanceResponse -MsgRevokeFeeAllowanceResponse defines the Msg/RevokeFeeAllowanceResponse 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 | - - + + +### 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 | + + - - -### 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. | | +### 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 | - -

Top

-## cosmos/genutil/v1beta1/genesis.proto - + -### GenesisState -GenesisState defines the raw genesis transaction in JSON. +### 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 | | ----- | ---- | ----- | ----------- | -| `gen_txs` | [bytes](#bytes) | repeated | gen_txs defines the genesis transactions. | +| `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 | - -

Top

-## cosmos/gov/v1beta1/gov.proto - + -### Deposit -Deposit defines an amount deposited by an account address to an active -proposal. +### SignerInfo +SignerInfo describes the public key and signing mode of a single top-level +signer. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | | -| `depositor` | [string](#string) | | | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `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. | - + -### DepositParams -DepositParams defines the params for deposits on governance proposals. +### Tx +Tx is the standard type used for broadcasting transactions. | 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. | +| `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. | - + -### Proposal -Proposal defines the core field members of a governance proposal. +### TxBody +TxBody is the body of a transaction that all signers sign over. | 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) | | | +| `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 | - + -### TallyParams -TallyParams defines the params for tallying votes on governance proposals. +### 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 | | ----- | ---- | ----- | ----------- | -| `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. | +| `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. | + - + -### 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/tx/v1beta1/service.proto - + -### TextProposal -TextProposal defines a standard text proposal whose changes need to be -manually updated in case of approval. +### BroadcastTxRequest +BroadcastTxRequest is the request type for the Service.BroadcastTxRequest +RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `title` | [string](#string) | | | -| `description` | [string](#string) | | | +| `tx_bytes` | [bytes](#bytes) | | tx_bytes is the raw transaction. | +| `mode` | [BroadcastMode](#cosmos.tx.v1beta1.BroadcastMode) | | | - + -### Vote -Vote defines a vote on a governance proposal. -A Vote consists of a proposal ID, the voter, and the vote option. +### BroadcastTxResponse +BroadcastTxResponse is the response type for the +Service.BroadcastTx method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | | -| `voter` | [string](#string) | | | -| `options` | [WeightedVoteOption](#cosmos.gov.v1beta1.WeightedVoteOption) | repeated | | +| `tx_response` | [cosmos.base.abci.v1beta1.TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | | tx_response is the queried TxResponses. | - + -### VotingParams -VotingParams defines the params for voting on governance proposals. +### GetTxRequest +GetTxRequest is the request type for the Service.GetTx +RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `voting_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | Length of the voting period. | +| `hash` | [string](#string) | | hash is the tx hash to query, encoded as a hex string. | - + -### WeightedVoteOption -WeightedVoteOption defines a unit of vote for vote split. +### GetTxResponse +GetTxResponse is the response type for the Service.GetTx method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `option` | [VoteOption](#cosmos.gov.v1beta1.VoteOption) | | | -| `weight` | [string](#string) | | | - +| `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. | - - + -### ProposalStatus -ProposalStatus enumerates the valid statuses of a proposal. +### GetTxsEventRequest +GetTxsEventRequest is the request type for the Service.TxsByEvents +RPC method. -| 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 | +| ----- | ---- | ----- | ----------- | +| `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. | - -### 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. | - + - +### 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. | - -

Top

-## cosmos/gov/v1beta1/genesis.proto - + -### GenesisState -GenesisState defines the gov module's genesis state. +### SimulateRequest +SimulateRequest is the request type for the Service.Simulate +RPC method. | 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. | +| `tx` | [Tx](#cosmos.tx.v1beta1.Tx) | | tx is the transaction to simulate. | - - + - +### SimulateResponse +SimulateResponse is the response type for the +Service.SimulateRPC method. - +| 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. | - -

Top

-## cosmos/gov/v1beta1/query.proto + - -### QueryDepositRequest -QueryDepositRequest is the request type for the Query/Deposit RPC method. + +### BroadcastMode +BroadcastMode specifies the broadcast mode for the TxService.Broadcast RPC method. -| 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. | +| 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. -### QueryDepositResponse -QueryDepositResponse is the response type for the Query/Deposit RPC method. +| 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 | -| ----- | ---- | ----- | ----------- | -| `deposit` | [Deposit](#cosmos.gov.v1beta1.Deposit) | | deposit defines the requested deposit. | + +

Top

+## cosmos/tx/signing/v1beta1/signing.proto - + -### QueryDepositsRequest -QueryDepositsRequest is the request type for the Query/Deposits 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 | | ----- | ---- | ----- | ----------- | -| `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. | +| `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. | - + -### QueryDepositsResponse -QueryDepositsResponse is the response type for the Query/Deposits RPC method. +### SignatureDescriptor.Data +Data represents signature data | 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. | +| `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 | - + -### QueryParamsRequest -QueryParamsRequest is the request type for the Query/Params RPC method. +### SignatureDescriptor.Data.Multi +Multi is the signature data for a multisig public key | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params_type` | [string](#string) | | params_type defines which parameters to query for, can be one of "voting", "tallying" or "deposit". | +| `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 | - + -### QueryParamsResponse -QueryParamsResponse is the response type for the Query/Params RPC method. +### SignatureDescriptor.Data.Single +Single is the signature data for a single signer | 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. | +| `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 | - + -### QueryProposalRequest -QueryProposalRequest is the request type for the Query/Proposal RPC method. +### SignatureDescriptors +SignatureDescriptors wraps multiple SignatureDescriptor's. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | - - - - +| `signatures` | [SignatureDescriptor](#cosmos.tx.signing.v1beta1.SignatureDescriptor) | repeated | signatures are the signature descriptors | - -### QueryProposalResponse -QueryProposalResponse is the response type for the Query/Proposal RPC method. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `proposal` | [Proposal](#cosmos.gov.v1beta1.Proposal) | | | + + +### 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 | - + -### 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/crypto/multisig/keys.proto - + -### QueryProposalsResponse -QueryProposalsResponse is the response type for the Query/Proposals RPC -method. +### 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 | | ----- | ---- | ----- | ----------- | -| `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. | +| `threshold` | [uint32](#uint32) | | | +| `public_keys` | [google.protobuf.Any](#google.protobuf.Any) | repeated | | + - + -### QueryTallyResultRequest -QueryTallyResultRequest is the request type for the Query/Tally RPC method. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | + +

Top

+## cosmos/crypto/multisig/v1beta1/multisig.proto - + -### QueryTallyResultResponse -QueryTallyResultResponse is the response type for the Query/Tally 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 | | ----- | ---- | ----- | ----------- | -| `tally` | [TallyResult](#cosmos.gov.v1beta1.TallyResult) | | tally defines the requested tally. | +| `extra_bits_stored` | [uint32](#uint32) | | | +| `elems` | [bytes](#bytes) | | | - + -### QueryVoteRequest -QueryVoteRequest is the request type for the Query/Vote 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 | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | -| `voter` | [string](#string) | | voter defines the oter address for the proposals. | +| `signatures` | [bytes](#bytes) | repeated | | + - + -### 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/crypto/secp256k1/keys.proto - + -### QueryVotesRequest -QueryVotesRequest is the request type for the Query/Votes RPC method. +### PrivKey +PrivKey defines a secp256k1 private key. | 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. | +| `key` | [bytes](#bytes) | | | - + -### QueryVotesResponse -QueryVotesResponse is the response type for the Query/Votes 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 | | ----- | ---- | ----- | ----------- | -| `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. | +| `key` | [bytes](#bytes) | | | @@ -4971,396 +5301,434 @@ 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/crypto/ed25519/keys.proto - + -### MsgDeposit -MsgDeposit defines a message to submit a deposit to an existing proposal. +### PrivKey +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 | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | | -| `depositor` | [string](#string) | | | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `key` | [bytes](#bytes) | | | - + -### MsgDepositResponse -MsgDepositResponse defines the Msg/Deposit response type. +### PubKey +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 | +| ----- | ---- | ----- | ----------- | +| `key` | [bytes](#bytes) | | | - -### 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/staking/v1beta1/staking.proto - + -### MsgSubmitProposalResponse -MsgSubmitProposalResponse defines the Msg/SubmitProposal response type. +### Commission +Commission defines commission parameters for a given validator. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | | +| `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. | - + -### MsgVote -MsgVote defines a message to cast a vote. +### CommissionRates +CommissionRates defines the initial commission rates to be used for creating +a validator. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | | -| `voter` | [string](#string) | | | -| `option` | [VoteOption](#cosmos.gov.v1beta1.VoteOption) | | | +| `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. | - + + +### 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. -### MsgVoteResponse -MsgVoteResponse defines the Msg/Vote response type. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `delegator_address` | [string](#string) | | | +| `validator_address` | [string](#string) | | | - -### MsgVoteWeighted -MsgVote defines a message to cast a vote. + + +### DVPairs +DVPairs defines an array of DVPair objects. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | | -| `voter` | [string](#string) | | | -| `options` | [WeightedVoteOption](#cosmos.gov.v1beta1.WeightedVoteOption) | repeated | | - - +| `pairs` | [DVPair](#cosmos.staking.v1beta1.DVPair) | repeated | | - -### MsgVoteWeightedResponse -MsgVoteWeightedResponse defines the MsgVoteWeighted response type. + +### 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 | +| ----- | ---- | ----- | ----------- | +| `delegator_address` | [string](#string) | | | +| `validator_src_address` | [string](#string) | | | +| `validator_dst_address` | [string](#string) | | | - - - - -### 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. | | -| `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. | | +### DVVTriplets +DVVTriplets defines an array of DVVTriplet objects. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `triplets` | [DVVTriplet](#cosmos.staking.v1beta1.DVVTriplet) | repeated | | - -

Top

-## cosmos/mint/v1beta1/mint.proto - + -### Minter -Minter represents the minting state. +### 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 | | ----- | ---- | ----- | ----------- | -| `inflation` | [string](#string) | | current annual inflation rate | -| `annual_provisions` | [string](#string) | | current annual expected provisions | +| `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. | - + -### Params -Params holds parameters for the mint module. +### 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 | | ----- | ---- | ----- | ----------- | -| `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 | +| `delegation` | [Delegation](#cosmos.staking.v1beta1.Delegation) | | | +| `balance` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | - - + - +### 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/mint/v1beta1/genesis.proto - + -### GenesisState -GenesisState defines the mint module's genesis state. +### 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 | | ----- | ---- | ----- | ----------- | -| `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. | +| `header` | [tendermint.types.Header](#tendermint.types.Header) | | | +| `valset` | [Validator](#cosmos.staking.v1beta1.Validator) | repeated | | - - + - +### 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. | - -

Top

-## cosmos/mint/v1beta1/query.proto - + + +### Pool +Pool is used for tracking bonded and not-bonded token supply of the bond +denomination. -### QueryAnnualProvisionsRequest -QueryAnnualProvisionsRequest is the request type for the -Query/AnnualProvisions RPC method. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `not_bonded_tokens` | [string](#string) | | | +| `bonded_tokens` | [string](#string) | | | - -### QueryAnnualProvisionsResponse -QueryAnnualProvisionsResponse is the response type for the -Query/AnnualProvisions RPC method. + + +### 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 | | ----- | ---- | ----- | ----------- | -| `annual_provisions` | [bytes](#bytes) | | annual_provisions is the current minting annual provisions value. | +| `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 | - -### QueryInflationRequest -QueryInflationRequest is the request type for the Query/Inflation RPC method. + + +### RedelegationEntry +RedelegationEntry defines a redelegation object with relevant metadata. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `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. | - + -### QueryInflationResponse -QueryInflationResponse is the response type for the Query/Inflation 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 | | ----- | ---- | ----- | ----------- | -| `inflation` | [bytes](#bytes) | | inflation is the current minting inflation value. | - +| `redelegation_entry` | [RedelegationEntry](#cosmos.staking.v1beta1.RedelegationEntry) | | | +| `balance` | [string](#string) | | | - -### QueryParamsRequest -QueryParamsRequest is the request type for the Query/Params 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 | +| ----- | ---- | ----- | ----------- | +| `redelegation` | [Redelegation](#cosmos.staking.v1beta1.Redelegation) | | | +| `entries` | [RedelegationEntryResponse](#cosmos.staking.v1beta1.RedelegationEntryResponse) | repeated | | - -### 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. | + +### 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 | - - - - -### 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| +### UnbondingDelegationEntry +UnbondingDelegationEntry defines an unbonding object with relevant metadata. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `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. | - -

Top

-## cosmos/params/v1beta1/params.proto - + -### ParamChange -ParamChange defines an individual parameter change, for use in -ParameterChangeProposal. +### ValAddresses +ValAddresses defines a repeated set of validator addresses. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `subspace` | [string](#string) | | | -| `key` | [string](#string) | | | -| `value` | [string](#string) | | | +| `addresses` | [string](#string) | repeated | | - + -### ParameterChangeProposal -ParameterChangeProposal defines a proposal to change one or more parameters. +### 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 | | ----- | ---- | ----- | ----------- | -| `title` | [string](#string) | | | -| `description` | [string](#string) | | | -| `changes` | [ParamChange](#cosmos.params.v1beta1.ParamChange) | repeated | | +| `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. | @@ -5368,6 +5736,20 @@ ParameterChangeProposal defines a proposal to change one or more parameters. + + + +### 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. | + + @@ -5376,743 +5758,701 @@ ParameterChangeProposal defines a proposal to change one or more parameters. - +

Top

-## cosmos/params/v1beta1/query.proto +## cosmos/staking/v1beta1/tx.proto - + -### QueryParamsRequest -QueryParamsRequest is request type for the Query/Params RPC method. +### 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 | | ----- | ---- | ----- | ----------- | -| `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. | +| `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 | | ----- | ---- | ----- | ----------- | -| `param` | [ParamChange](#cosmos.params.v1beta1.ParamChange) | | param defines the queried parameter. | +| `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) | | | -### 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

+ + +### MsgCreateValidatorResponse +MsgCreateValidatorResponse defines the Msg/CreateValidator response type. -## cosmos/slashing/v1beta1/slashing.proto - -### Params -Params represents the parameters used for by the slashing module. + + + +### MsgDelegate +MsgDelegate defines a SDK message for performing a delegation of coins +from a delegator to a validator. | 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) | | | +| `delegator_address` | [string](#string) | | | +| `validator_address` | [string](#string) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | - + -### ValidatorSigningInfo -ValidatorSigningInfo defines a validator's signing info for monitoring their -liveness activity. +### MsgDelegateResponse +MsgDelegateResponse defines the Msg/Delegate response type. -| 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`. | + - +### 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) | | | - - -

Top

-## cosmos/slashing/v1beta1/genesis.proto + + + +### MsgEditValidatorResponse +MsgEditValidatorResponse defines the Msg/EditValidator response type. - -### GenesisState -GenesisState defines the slashing module's genesis state. + + + + +### MsgUndelegate +MsgUndelegate defines a SDK message for performing an undelegation from a +delegate and a 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) | | | +| `validator_address` | [string](#string) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | - + -### MissedBlock -MissedBlock contains height and missed status as boolean. +### MsgUndelegateResponse +MsgUndelegateResponse defines the Msg/Undelegate response type. | 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. | +| `completion_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | + - + -### SigningInfo -SigningInfo stores validator signing info of corresponding address. + -| 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. | + +### 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

-### ValidatorMissedBlocks -ValidatorMissedBlocks contains array of missed blocks of corresponding -address. +## cosmos/staking/v1beta1/authz.proto -| 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. | + +### StakeAuthorization +StakeAuthorization defines authorization for delegate/undelegate/redelegate. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `max_tokens` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | max_tokens specifies the maximum amount of tokens can be delegate to a validator. If it is empty, there is no spend limit and any amount of coins can be delegated. | +| `allow_list` | [StakeAuthorization.Validators](#cosmos.staking.v1beta1.StakeAuthorization.Validators) | | allow_list specifies list of validator addresses to whom grantee can delegate tokens on behalf of granter's account. | +| `deny_list` | [StakeAuthorization.Validators](#cosmos.staking.v1beta1.StakeAuthorization.Validators) | | deny_list specifies list of validator addresses to whom grantee can not delegate tokens. | +| `authorization_type` | [AuthorizationType](#cosmos.staking.v1beta1.AuthorizationType) | | authorization_type defines one of AuthorizationType. | - - - - + - -

Top

+### StakeAuthorization.Validators +Validators defines list of validator addresses. -## cosmos/slashing/v1beta1/query.proto + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `address` | [string](#string) | repeated | | - -### QueryParamsRequest -QueryParamsRequest is the request type for the Query/Params RPC method + + +### AuthorizationType +AuthorizationType defines the type of staking module authorization type +| Name | Number | Description | +| ---- | ------ | ----------- | +| AUTHORIZATION_TYPE_UNSPECIFIED | 0 | AUTHORIZATION_TYPE_UNSPECIFIED specifies an unknown authorization type | +| AUTHORIZATION_TYPE_DELEGATE | 1 | AUTHORIZATION_TYPE_DELEGATE defines an authorization type for Msg/Delegate | +| AUTHORIZATION_TYPE_UNDELEGATE | 2 | AUTHORIZATION_TYPE_UNDELEGATE defines an authorization type for Msg/Undelegate | +| AUTHORIZATION_TYPE_REDELEGATE | 3 | AUTHORIZATION_TYPE_REDELEGATE defines an authorization type for Msg/BeginRedelegate | - -### QueryParamsResponse -QueryParamsResponse is the response type for the Query/Params RPC method + + + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.slashing.v1beta1.Params) | | | + +

Top

+## cosmos/staking/v1beta1/query.proto - + -### QuerySigningInfoRequest -QuerySigningInfoRequest is the request type for the Query/SigningInfo RPC -method +### QueryDelegationRequest +QueryDelegationRequest is request type for the Query/Delegation RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `cons_address` | [string](#string) | | cons_address is the address to query signing info of | +| `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. | - + -### QuerySigningInfoResponse -QuerySigningInfoResponse is the response type for the Query/SigningInfo RPC -method +### QueryDelegationResponse +QueryDelegationResponse is response type for the Query/Delegation RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `val_signing_info` | [ValidatorSigningInfo](#cosmos.slashing.v1beta1.ValidatorSigningInfo) | | val_signing_info is the signing info of requested val cons address | +| `delegation_response` | [DelegationResponse](#cosmos.staking.v1beta1.DelegationResponse) | | delegation_responses defines the delegation info of a delegation. | - + -### QuerySigningInfosRequest -QuerySigningInfosRequest is the request type for the Query/SigningInfos RPC -method +### QueryDelegatorDelegationsRequest +QueryDelegatorDelegationsRequest is request type for the +Query/DelegatorDelegations RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | | +| `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. | - + -### QuerySigningInfosResponse -QuerySigningInfosResponse is the response type for the Query/SigningInfos RPC -method +### QueryDelegatorDelegationsResponse +QueryDelegatorDelegationsResponse is response type for the +Query/DelegatorDelegations 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) | | | - - - - +| `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. | - - - - -### 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| +### QueryDelegatorUnbondingDelegationsRequest +QueryDelegatorUnbondingDelegationsRequest is request type for the +Query/DelegatorUnbondingDelegations 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. | - -

Top

-## cosmos/slashing/v1beta1/tx.proto - + -### MsgUnjail -MsgUnjail defines the Msg/Unjail request type +### QueryDelegatorUnbondingDelegationsResponse +QueryUnbondingDelegatorDelegationsResponse is response type for the +Query/UnbondingDelegatorDelegations RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator_addr` | [string](#string) | | | - - +| `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. | - -### MsgUnjailResponse -MsgUnjailResponse defines the Msg/Unjail response type + +### QueryDelegatorValidatorRequest +QueryDelegatorValidatorRequest is request type for the +Query/DelegatorValidator 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. | - - - - -### 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. | | +### QueryDelegatorValidatorResponse +QueryDelegatorValidatorResponse response type for the +Query/DelegatorValidator RPC method. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `validator` | [Validator](#cosmos.staking.v1beta1.Validator) | | validator defines the the validator info. | - -

Top

-## cosmos/staking/v1beta1/staking.proto - + -### Commission -Commission defines commission parameters for a given validator. +### QueryDelegatorValidatorsRequest +QueryDelegatorValidatorsRequest is request type for the +Query/DelegatorValidators RPC method. | 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. | +| `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. | - + -### CommissionRates -CommissionRates defines the initial commission rates to be used for creating -a validator. +### QueryDelegatorValidatorsResponse +QueryDelegatorValidatorsResponse is response type for the +Query/DelegatorValidators RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `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. | +| `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. | - + -### 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. +### QueryHistoricalInfoRequest +QueryHistoricalInfoRequest is request type for the Query/HistoricalInfo RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `validator_address` | [string](#string) | | | +| `height` | [int64](#int64) | | height defines at which height to query the historical info. | - + -### DVPairs -DVPairs defines an array of DVPair objects. +### QueryHistoricalInfoResponse +QueryHistoricalInfoResponse is response type for the Query/HistoricalInfo RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `pairs` | [DVPair](#cosmos.staking.v1beta1.DVPair) | repeated | | - - +| `hist` | [HistoricalInfo](#cosmos.staking.v1beta1.HistoricalInfo) | | hist defines the historical info at the given height. | - -### 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 | -| ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `validator_src_address` | [string](#string) | | | -| `validator_dst_address` | [string](#string) | | | +### QueryParamsRequest +QueryParamsRequest is request type for the Query/Params RPC method. - + -### DVVTriplets -DVVTriplets defines an array of DVVTriplet objects. +### QueryParamsResponse +QueryParamsResponse is response type for the Query/Params RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `triplets` | [DVVTriplet](#cosmos.staking.v1beta1.DVVTriplet) | repeated | | - - +| `params` | [Params](#cosmos.staking.v1beta1.Params) | | params holds all the parameters of this module. | - -### 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. | +### QueryPoolRequest +QueryPoolRequest is request type for the Query/Pool RPC method. - + -### DelegationResponse -DelegationResponse is equivalent to Delegation except that it contains a -balance in addition to shares which is more suitable for client responses. +### QueryPoolResponse +QueryPoolResponse is response type for the Query/Pool RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegation` | [Delegation](#cosmos.staking.v1beta1.Delegation) | | | -| `balance` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | +| `pool` | [Pool](#cosmos.staking.v1beta1.Pool) | | pool defines the pool info. | - + -### Description -Description defines a validator description. +### QueryRedelegationsRequest +QueryRedelegationsRequest is request type for the Query/Redelegations RPC +method. | 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. | +| `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. | - + -### 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). +### QueryRedelegationsResponse +QueryRedelegationsResponse is response type for the Query/Redelegations RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `header` | [tendermint.types.Header](#tendermint.types.Header) | | | -| `valset` | [Validator](#cosmos.staking.v1beta1.Validator) | repeated | | +| `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. | - + -### Params -Params defines the parameters for the staking module. +### QueryUnbondingDelegationRequest +QueryUnbondingDelegationRequest is request type for the +Query/UnbondingDelegation RPC method. | 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. | +| `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. | - + -### Pool -Pool is used for tracking bonded and not-bonded token supply of the bond -denomination. +### QueryUnbondingDelegationResponse +QueryDelegationResponse is response type for the Query/UnbondingDelegation +RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `not_bonded_tokens` | [string](#string) | | | -| `bonded_tokens` | [string](#string) | | | +| `unbond` | [UnbondingDelegation](#cosmos.staking.v1beta1.UnbondingDelegation) | | unbond defines the unbonding information of a delegation. | - + -### Redelegation -Redelegation contains the list of a particular delegator's redelegating bonds -from a particular source validator to a particular destination validator. +### QueryValidatorDelegationsRequest +QueryValidatorDelegationsRequest is request type for the +Query/ValidatorDelegations RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `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 | +| `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. | - + -### RedelegationEntry -RedelegationEntry defines a redelegation object with relevant metadata. +### QueryValidatorDelegationsResponse +QueryValidatorDelegationsResponse is response type for the +Query/ValidatorDelegations RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `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. | +| `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. | - + -### RedelegationEntryResponse -RedelegationEntryResponse is equivalent to a RedelegationEntry except that it -contains a balance in addition to shares which is more suitable for client -responses. +### QueryValidatorRequest +QueryValidatorRequest is response type for the Query/Validator RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `redelegation_entry` | [RedelegationEntry](#cosmos.staking.v1beta1.RedelegationEntry) | | | -| `balance` | [string](#string) | | | +| `validator_addr` | [string](#string) | | validator_addr defines the validator address 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. +### QueryValidatorResponse +QueryValidatorResponse is response type for the Query/Validator RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `redelegation` | [Redelegation](#cosmos.staking.v1beta1.Redelegation) | | | -| `entries` | [RedelegationEntryResponse](#cosmos.staking.v1beta1.RedelegationEntryResponse) | repeated | | +| `validator` | [Validator](#cosmos.staking.v1beta1.Validator) | | validator defines the the validator info. | - + -### UnbondingDelegation -UnbondingDelegation stores all of a single delegator's unbonding bonds -for a single validator in an time-ordered list. +### QueryValidatorUnbondingDelegationsRequest +QueryValidatorUnbondingDelegationsRequest is required type for the +Query/ValidatorUnbondingDelegations RPC method | 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 | +| `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. | - + -### UnbondingDelegationEntry -UnbondingDelegationEntry defines an unbonding object with relevant metadata. +### QueryValidatorUnbondingDelegationsResponse +QueryValidatorUnbondingDelegationsResponse is response type for the +Query/ValidatorUnbondingDelegations RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `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. | +| `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. | - + -### ValAddresses -ValAddresses defines a repeated set of validator addresses. +### QueryValidatorsRequest +QueryValidatorsRequest is request type for Query/Validators RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `addresses` | [string](#string) | repeated | | +| `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. | - + -### 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. +### QueryValidatorsResponse +QueryValidatorsResponse is response type for the Query/Validators RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `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. | +| `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. | @@ -6120,23 +6460,32 @@ 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 | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `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| @@ -6196,454 +6545,392 @@ LastValidatorPower required for validator set update logic. - +

Top

-## cosmos/staking/v1beta1/query.proto - - - - - -### QueryDelegationRequest -QueryDelegationRequest is request type for the Query/Delegation 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. | - - - - - - - - -### QueryDelegationResponse -QueryDelegationResponse is response type for the Query/Delegation RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `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. | - - - - - - - - -### 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. | - - - - - - - - -### QueryDelegatorUnbondingDelegationsRequest -QueryDelegatorUnbondingDelegationsRequest is request type for the -Query/DelegatorUnbondingDelegations 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. | - - - +## cosmos/base/abci/v1beta1/abci.proto - + -### QueryDelegatorUnbondingDelegationsResponse -QueryUnbondingDelegatorDelegationsResponse is response type for the -Query/UnbondingDelegatorDelegations RPC method. +### ABCIMessageLog +ABCIMessageLog defines a structure containing an indexed tx ABCI message log. | 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. | - +| `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. | - -### QueryDelegatorValidatorRequest -QueryDelegatorValidatorRequest is request type for the -Query/DelegatorValidator RPC method. + + +### Attribute +Attribute defines an attribute wrapper where the key and value are +strings instead of raw bytes. | 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. | +| `key` | [string](#string) | | | +| `value` | [string](#string) | | | - + -### QueryDelegatorValidatorResponse -QueryDelegatorValidatorResponse response type for the -Query/DelegatorValidator RPC method. +### GasInfo +GasInfo defines tx execution gas context. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator` | [Validator](#cosmos.staking.v1beta1.Validator) | | validator defines the the validator info. | +| `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. | - + -### QueryDelegatorValidatorsRequest -QueryDelegatorValidatorsRequest is request type for the -Query/DelegatorValidators RPC method. +### MsgData +MsgData defines the data returned in a Result object during message +execution. | 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_type` | [string](#string) | | | +| `data` | [bytes](#bytes) | | | - + -### QueryDelegatorValidatorsResponse -QueryDelegatorValidatorsResponse is response type for the -Query/DelegatorValidators RPC method. +### Result +Result is the union of ResponseFormat and ResponseCheckTx. | 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. | +| `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. | - + -### QueryHistoricalInfoRequest -QueryHistoricalInfoRequest is request type for the Query/HistoricalInfo RPC -method. +### SearchTxsResult +SearchTxsResult defines a structure for querying txs pageable | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `height` | [int64](#int64) | | height defines at which height to query the historical info. | +| `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 | - + -### QueryHistoricalInfoResponse -QueryHistoricalInfoResponse is response type for the Query/HistoricalInfo RPC -method. +### SimulationResponse +SimulationResponse defines the response generated when a transaction is +successfully simulated. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `hist` | [HistoricalInfo](#cosmos.staking.v1beta1.HistoricalInfo) | | hist defines the historical info at the given height. | +| `gas_info` | [GasInfo](#cosmos.base.abci.v1beta1.GasInfo) | | | +| `result` | [Result](#cosmos.base.abci.v1beta1.Result) | | | - + -### QueryParamsRequest -QueryParamsRequest is request type for the Query/Params 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 | +| ----- | ---- | ----- | ----------- | +| `type` | [string](#string) | | | +| `attributes` | [Attribute](#cosmos.base.abci.v1beta1.Attribute) | repeated | | - -### QueryParamsResponse -QueryParamsResponse is response type for the Query/Params RPC method. + + + +### TxMsgData +TxMsgData defines a list of MsgData. A transaction will have a MsgData object +for each message. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.staking.v1beta1.Params) | | params holds all the parameters of this module. | +| `data` | [MsgData](#cosmos.base.abci.v1beta1.MsgData) | repeated | | - + -### QueryPoolRequest -QueryPoolRequest is request type for the Query/Pool RPC method. +### 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 | +| ----- | ---- | ----- | ----------- | +| `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. | - -### 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. | + + + + +

Top

+## cosmos/base/kv/v1beta1/kv.proto - -### QueryRedelegationsRequest -QueryRedelegationsRequest is request type for the Query/Redelegations RPC -method. + + +### Pair +Pair defines a key/value bytes tuple. | 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. | +| `key` | [bytes](#bytes) | | | +| `value` | [bytes](#bytes) | | | - + -### QueryRedelegationsResponse -QueryRedelegationsResponse is response type for the Query/Redelegations RPC -method. +### Pairs +Pairs defines a repeated slice of Pair objects. | 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. | +| `pairs` | [Pair](#cosmos.base.kv.v1beta1.Pair) | repeated | | + - + -### QueryUnbondingDelegationRequest -QueryUnbondingDelegationRequest is request type for the -Query/UnbondingDelegation 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. | + +

Top

+## cosmos/base/v1beta1/coin.proto - + -### QueryUnbondingDelegationResponse -QueryDelegationResponse is response type for the Query/UnbondingDelegation -RPC method. +### 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 | | ----- | ---- | ----- | ----------- | -| `unbond` | [UnbondingDelegation](#cosmos.staking.v1beta1.UnbondingDelegation) | | unbond defines the unbonding information of a delegation. | +| `denom` | [string](#string) | | | +| `amount` | [string](#string) | | | - + -### QueryValidatorDelegationsRequest -QueryValidatorDelegationsRequest is request type for the -Query/ValidatorDelegations RPC method +### 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. | 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. | +| `denom` | [string](#string) | | | +| `amount` | [string](#string) | | | - + -### QueryValidatorDelegationsResponse -QueryValidatorDelegationsResponse is response type for the -Query/ValidatorDelegations RPC method +### DecProto +DecProto defines a Protobuf wrapper around a Dec object. | 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. | +| `dec` | [string](#string) | | | - + -### QueryValidatorRequest -QueryValidatorRequest is response type for the Query/Validator RPC method +### IntProto +IntProto defines a Protobuf wrapper around an Int object. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator_addr` | [string](#string) | | validator_addr defines the validator address to query for. | - - +| `int` | [string](#string) | | | - -### QueryValidatorResponse -QueryValidatorResponse is response type for the Query/Validator RPC method + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `validator` | [Validator](#cosmos.staking.v1beta1.Validator) | | validator defines the the validator info. | + + + +

Top

+## cosmos/base/reflection/v1beta1/reflection.proto - -### QueryValidatorUnbondingDelegationsRequest -QueryValidatorUnbondingDelegationsRequest is required type for the -Query/ValidatorUnbondingDelegations RPC method + -| 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. | +### ListAllInterfacesRequest +ListAllInterfacesRequest is the request type of the ListAllInterfaces RPC. - + -### QueryValidatorUnbondingDelegationsResponse -QueryValidatorUnbondingDelegationsResponse is response type for the -Query/ValidatorUnbondingDelegations RPC method. +### ListAllInterfacesResponse +ListAllInterfacesResponse is the response type of the ListAllInterfaces RPC. | 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. | +| `interface_names` | [string](#string) | repeated | interface_names is an array of all the registered interfaces. | - + -### QueryValidatorsRequest -QueryValidatorsRequest is request type for Query/Validators RPC method. +### ListImplementationsRequest +ListImplementationsRequest is the request type of the ListImplementations +RPC. | 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. | +| `interface_name` | [string](#string) | | interface_name defines the interface to query the implementations for. | - + -### QueryValidatorsResponse -QueryValidatorsResponse is response type for the Query/Validators RPC method +### ListImplementationsResponse +ListImplementationsResponse is the response type of the ListImplementations +RPC. | 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. | +| `implementation_message_names` | [string](#string) | repeated | | @@ -6656,300 +6943,327 @@ QueryValidatorsResponse is response type for the Query/Validators RPC method - + -### Query -Query defines the gRPC querier service. +### ReflectionService +ReflectionService defines a service for interface reflection. | 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| +| `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

-## cosmos/staking/v1beta1/tx.proto +## cosmos/base/tendermint/v1beta1/query.proto - + -### MsgBeginRedelegate -MsgBeginRedelegate defines a SDK message for performing a redelegation -of coins from a delegator and source validator to a destination validator. +### GetBlockByHeightRequest +GetBlockByHeightRequest is the request type for the Query/GetBlockByHeight 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) | | | +| `height` | [int64](#int64) | | | - + -### MsgBeginRedelegateResponse -MsgBeginRedelegateResponse defines the Msg/BeginRedelegate response type. +### GetBlockByHeightResponse +GetBlockByHeightResponse is the response type for the Query/GetBlockByHeight RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `completion_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `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. + + -### MsgCreateValidator -MsgCreateValidator defines a SDK message for creating a new validator. + + + + + +### GetLatestBlockResponse +GetLatestBlockResponse is the response type for the Query/GetLatestBlock RPC method. | 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) | | | +| `block_id` | [tendermint.types.BlockID](#tendermint.types.BlockID) | | | +| `block` | [tendermint.types.Block](#tendermint.types.Block) | | | - + -### MsgCreateValidatorResponse -MsgCreateValidatorResponse defines the Msg/CreateValidator response type. +### 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. | - + -### MsgDelegate -MsgDelegate defines a SDK message for performing a delegation of coins -from a delegator to a validator. +### GetLatestValidatorSetResponse +GetLatestValidatorSetResponse is the response type for the Query/GetValidatorSetByHeight RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `validator_address` | [string](#string) | | | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | +| `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. | - + -### MsgDelegateResponse -MsgDelegateResponse defines the Msg/Delegate response type. +### GetNodeInfoRequest +GetNodeInfoRequest is the request type for the Query/GetNodeInfo RPC method. - + -### MsgEditValidator -MsgEditValidator defines a SDK message for editing an existing validator. +### GetNodeInfoResponse +GetNodeInfoResponse is the request type for the Query/GetNodeInfo RPC method. | 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) | | | +| `default_node_info` | [tendermint.p2p.DefaultNodeInfo](#tendermint.p2p.DefaultNodeInfo) | | | +| `application_version` | [VersionInfo](#cosmos.base.tendermint.v1beta1.VersionInfo) | | | - + -### MsgEditValidatorResponse -MsgEditValidatorResponse defines the Msg/EditValidator response type. +### GetSyncingRequest +GetSyncingRequest is the request type for the Query/GetSyncing RPC method. - + -### MsgUndelegate -MsgUndelegate defines a SDK message for performing an undelegation from a -delegate and a validator. +### GetSyncingResponse +GetSyncingResponse is the response type for the Query/GetSyncing RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `validator_address` | [string](#string) | | | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | +| `syncing` | [bool](#bool) | | | - + -### MsgUndelegateResponse -MsgUndelegateResponse defines the Msg/Undelegate response type. +### GetValidatorSetByHeightRequest +GetValidatorSetByHeightRequest is the request type for the Query/GetValidatorSetByHeight RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `completion_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `height` | [int64](#int64) | | | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | - - + - +### 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. | -### 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 +### 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 | - -### 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. + + + + + + +### Validator +Validator is the type for the validator-set. | 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. | +| `address` | [string](#string) | | | +| `pub_key` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `voting_power` | [int64](#int64) | | | +| `proposer_priority` | [int64](#int64) | | | - + -### SignatureDescriptor.Data -Data represents signature data +### VersionInfo +VersionInfo is the type for the GetNodeInfoResponse message. | 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 | +| `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 | | + - + -### 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 | + +### 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

-### SignatureDescriptor.Data.Single -Single is the signature data for a single signer +## 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; + } | 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 | +| `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. | - + -### SignatureDescriptors -SignatureDescriptors wraps multiple SignatureDescriptor's. +### 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 | | ----- | ---- | ----- | ----------- | -| `signatures` | [SignatureDescriptor](#cosmos.tx.signing.v1beta1.SignatureDescriptor) | repeated | signatures are the signature descriptors | +| `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 | @@ -6957,20 +7271,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 | - - @@ -6979,186 +7279,173 @@ SignMode represents a signing mode with its own security guarantees. - +

Top

-## cosmos/tx/v1beta1/tx.proto +## cosmos/base/snapshots/v1beta1/snapshot.proto - + -### AuthInfo -AuthInfo describes the fee and signer modes that are used to sign a -transaction. +### Metadata +Metadata contains SDK-specific snapshot metadata. | 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. | +| `chunk_hashes` | [bytes](#bytes) | repeated | SHA-256 chunk hashes | - + -### 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. +### Snapshot +Snapshot contains Tendermint state sync snapshot info. | 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 | +| `height` | [uint64](#uint64) | | | +| `format` | [uint32](#uint32) | | | +| `chunks` | [uint32](#uint32) | | | +| `hash` | [bytes](#bytes) | | | +| `metadata` | [Metadata](#cosmos.base.snapshots.v1beta1.Metadata) | | | + - + -### 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 | + +

Top

+## cosmos/base/store/v1beta1/snapshot.proto - + -### ModeInfo.Multi -Multi is the mode info for a multisig public key +### SnapshotIAVLItem +SnapshotIAVLItem is an exported IAVL node. | 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 | +| `key` | [bytes](#bytes) | | | +| `value` | [bytes](#bytes) | | | +| `version` | [int64](#int64) | | | +| `height` | [int32](#int32) | | | - + -### 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 +### SnapshotItem +SnapshotItem is an item contained in a rootmulti.Store snapshot. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `mode` | [cosmos.tx.signing.v1beta1.SignMode](#cosmos.tx.signing.v1beta1.SignMode) | | mode is the signing mode of the single signer | +| `store` | [SnapshotStoreItem](#cosmos.base.store.v1beta1.SnapshotStoreItem) | | | +| `iavl` | [SnapshotIAVLItem](#cosmos.base.store.v1beta1.SnapshotIAVLItem) | | | - + -### SignDoc -SignDoc is the type used for generating sign bytes for SIGN_MODE_DIRECT. +### SnapshotStoreItem +SnapshotStoreItem contains metadata about a snapshotted store. | 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 | +| `name` | [string](#string) | | | + - + -### 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. | + +

Top

+## cosmos/base/store/v1beta1/commit_info.proto - + -### Tx -Tx is the standard type used for broadcasting transactions. +### CommitID +CommitID defines the committment information when a specific store is +committed. | 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. | +| `version` | [int64](#int64) | | | +| `hash` | [bytes](#bytes) | | | - + -### TxBody -TxBody is the body of a transaction that all signers sign over. +### CommitInfo +CommitInfo defines commit information used by the multi-store when committing +a version/height. | 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 | +| `version` | [int64](#int64) | | | +| `store_infos` | [StoreInfo](#cosmos.base.store.v1beta1.StoreInfo) | repeated | | - + -### 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. +### StoreInfo +StoreInfo defines store-specific commit information. It contains a reference +between a store name and the commit ID. | 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. | +| `name` | [string](#string) | | | +| `commit_id` | [CommitID](#cosmos.base.store.v1beta1.CommitID) | | | @@ -7174,140 +7461,103 @@ 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) | | | - - - +## cosmos/bank/v1beta1/tx.proto - + -### BroadcastTxResponse -BroadcastTxResponse is the response type for the -Service.BroadcastTx method. +### MsgMultiSend +MsgMultiSend represents an arbitrary multi-in, multi-out send message. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `tx_response` | [cosmos.base.abci.v1beta1.TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | | tx_response is the queried TxResponses. | - - +| `inputs` | [Input](#cosmos.bank.v1beta1.Input) | repeated | | +| `outputs` | [Output](#cosmos.bank.v1beta1.Output) | repeated | | - -### GetTxRequest -GetTxRequest is the request type for the Service.GetTx -RPC method. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `hash` | [string](#string) | | hash is the tx hash to query, encoded as a hex string. | +### MsgMultiSendResponse +MsgMultiSendResponse defines the Msg/MultiSend response type. - + -### GetTxResponse -GetTxResponse is the response type for the Service.GetTx method. +### MsgSend +MsgSend represents a message to send coins from one account to another. | 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. | - - - - - - - - -### GetTxsEventRequest -GetTxsEventRequest is the request type for the Service.TxsByEvents -RPC method. - +| `from_address` | [string](#string) | | | +| `to_address` | [string](#string) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | -| 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. | + - +### MsgSendResponse +MsgSendResponse defines the Msg/Send response type. -### 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. | + + + - + -### SimulateRequest -SimulateRequest is the request type for the Service.Simulate -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. | | -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `tx` | [Tx](#cosmos.tx.v1beta1.Tx) | | tx is the transaction to simulate. | + + +

Top

+## cosmos/bank/v1beta1/authz.proto - -### SimulateResponse -SimulateResponse is the response type for the -Service.SimulateRPC method. + + +### SendAuthorization +SendAuthorization allows the grantee to spend up to spend_limit coins from +the granter's account. | 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. | +| `spend_limit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | @@ -7315,261 +7565,224 @@ Service.SimulateRPC method. + - + -### 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/bank/v1beta1/query.proto - -### 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| +### 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. | - -

Top

-## cosmos/upgrade/v1beta1/upgrade.proto - + -### CancelSoftwareUpgradeProposal -CancelSoftwareUpgradeProposal is a gov Content type for cancelling a software -upgrade. +### QueryAllBalancesResponse +QueryAllBalancesResponse is the response type for the Query/AllBalances RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `title` | [string](#string) | | | -| `description` | [string](#string) | | | +| `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. | - + -### Plan -Plan specifies information about a planned upgrade and when it should occur. +### QueryBalanceRequest +QueryBalanceRequest is the request type for the Query/Balance RPC method. | 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 | +| `address` | [string](#string) | | address is the address to query balances for. | +| `denom` | [string](#string) | | denom is the coin denom to query balances for. | - + -### SoftwareUpgradeProposal -SoftwareUpgradeProposal is a gov Content type for initiating a software -upgrade. +### QueryBalanceResponse +QueryBalanceResponse is the response type for the Query/Balance RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `title` | [string](#string) | | | -| `description` | [string](#string) | | | -| `plan` | [Plan](#cosmos.upgrade.v1beta1.Plan) | | | +| `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. | - -

Top

-## cosmos/upgrade/v1beta1/query.proto - + -### QueryAppliedPlanRequest -QueryCurrentPlanRequest is the request type for the Query/AppliedPlan RPC +### QueryDenomMetadataResponse +QueryDenomMetadataResponse is the response type for the Query/DenomMetadata RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `name` | [string](#string) | | name is the name of the applied plan to query for. | +| `metadata` | [Metadata](#cosmos.bank.v1beta1.Metadata) | | metadata describes and provides all the client information for the requested token. | - + -### QueryAppliedPlanResponse -QueryAppliedPlanResponse is the response type for the Query/AppliedPlan RPC -method. +### QueryDenomsMetadataRequest +QueryDenomsMetadataRequest is the request type for the Query/DenomsMetadata RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `height` | [int64](#int64) | | height is the block height at which the plan was applied. | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | - + -### QueryCurrentPlanRequest -QueryCurrentPlanRequest is the request type for the Query/CurrentPlan RPC +### 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. | - -### QueryCurrentPlanResponse -QueryCurrentPlanResponse is the response type for the Query/CurrentPlan RPC -method. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `plan` | [Plan](#cosmos.upgrade.v1beta1.Plan) | | plan is the current upgrade plan. | +### QueryParamsRequest +QueryParamsRequest defines the request type for querying x/bank parameters. - + -### QueryUpgradedConsensusStateRequest -QueryUpgradedConsensusStateRequest is the request type for the Query/UpgradedConsensusState -RPC method. +### QueryParamsResponse +QueryParamsResponse defines the response type for querying x/bank parameters. | 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 | +| `params` | [Params](#cosmos.bank.v1beta1.Params) | | | - + -### QueryUpgradedConsensusStateResponse -QueryUpgradedConsensusStateResponse is the response type for the Query/UpgradedConsensusState -RPC method. +### QuerySupplyOfRequest +QuerySupplyOfRequest is the request type for the Query/SupplyOf RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `upgraded_consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | | - - - - +| `denom` | [string](#string) | | denom is the coin denom to query balances for. | - - - - -### 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}| +### 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. | - -

Top

-## cosmos/vesting/v1beta1/tx.proto - + -### MsgCreateVestingAccount -MsgCreateVestingAccount defines a message that enables creating a vesting -account. +### QueryTotalSupplyRequest +QueryTotalSupplyRequest is the request type for the Query/TotalSupply RPC +method. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `from_address` | [string](#string) | | | -| `to_address` | [string](#string) | | | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | -| `end_time` | [int64](#int64) | | | -| `delayed` | [bool](#bool) | | | + +### QueryTotalSupplyResponse +QueryTotalSupplyResponse is the response type for the Query/TotalSupply RPC +method - -### MsgCreateVestingAccountResponse -MsgCreateVestingAccountResponse defines the Msg/CreateVestingAccount response type. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `supply` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | supply is the supply of the coins | @@ -7582,180 +7795,195 @@ MsgCreateVestingAccountResponse defines the Msg/CreateVestingAccount response ty - + -### Msg -Msg defines the bank Msg service. +### Query +Query defines the gRPC querier service. | Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | | ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `CreateVestingAccount` | [MsgCreateVestingAccount](#cosmos.vesting.v1beta1.MsgCreateVestingAccount) | [MsgCreateVestingAccountResponse](#cosmos.vesting.v1beta1.MsgCreateVestingAccountResponse) | CreateVestingAccount defines a method that enables creating a vesting account. | | +| `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

+ +

Top

+ +## cosmos/bank/v1beta1/bank.proto + + + + + +### DenomUnit +DenomUnit represents a struct that describes a given +denomination unit of the basic token. + + +| 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 | + + -## cosmos/vesting/v1beta1/vesting.proto - + -### BaseVestingAccount -BaseVestingAccount implements the VestingAccount interface. It contains all -the necessary fields needed for any vesting account implementation. +### Input +Input models transaction input. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `base_account` | [cosmos.auth.v1beta1.BaseAccount](#cosmos.auth.v1beta1.BaseAccount) | | | -| `original_vesting` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | -| `delegated_free` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | -| `delegated_vesting` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | -| `end_time` | [int64](#int64) | | | +| `address` | [string](#string) | | | +| `coins` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | - + -### ContinuousVestingAccount -ContinuousVestingAccount implements the VestingAccount interface. It -continuously vests by unlocking coins linearly with respect to time. +### Metadata +Metadata represents a struct that describes +a basic token. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `base_vesting_account` | [BaseVestingAccount](#cosmos.vesting.v1beta1.BaseVestingAccount) | | | -| `start_time` | [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. | - + -### DelayedVestingAccount -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. +### Output +Output models transaction outputs. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `base_vesting_account` | [BaseVestingAccount](#cosmos.vesting.v1beta1.BaseVestingAccount) | | | +| `address` | [string](#string) | | | +| `coins` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | - + -### Period -Period defines a length of time and amount of coins that will vest. +### Params +Params defines the parameters for the bank module. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `length` | [int64](#int64) | | | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `send_enabled` | [SendEnabled](#cosmos.bank.v1beta1.SendEnabled) | repeated | | +| `default_send_enabled` | [bool](#bool) | | | - + -### PeriodicVestingAccount -PeriodicVestingAccount implements the VestingAccount interface. It -periodically vests by unlocking coins during each specified period. +### SendEnabled +SendEnabled maps coin denom to a send_enabled status (whether a denom is +sendable). | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `base_vesting_account` | [BaseVestingAccount](#cosmos.vesting.v1beta1.BaseVestingAccount) | | | -| `start_time` | [int64](#int64) | | | -| `vesting_periods` | [Period](#cosmos.vesting.v1beta1.Period) | repeated | | +| `denom` | [string](#string) | | | +| `enabled` | [bool](#bool) | | | - - + - +### Supply +Supply represents a struct that passively keeps track of the total supply +amounts in the network. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `total` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | - -

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. | + +

Top

+## cosmos/bank/v1beta1/genesis.proto - + -### 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 +### Balance +Balance defines an account address and balance pair used in the bank module's +genesis state. | 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 | +| `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. | - + -### 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. +### GenesisState +GenesisState defines the bank module's genesis state. | 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. | +| `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. | @@ -7771,24 +7999,22 @@ parameter for the denomination to false. - +

Top

-## ibc/applications/transfer/v1/genesis.proto +## cosmos/genutil/v1beta1/genesis.proto - + ### GenesisState -GenesisState defines the ibc-transfer genesis state +GenesisState defines the raw genesis transaction in JSON. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | | -| `denom_traces` | [DenomTrace](#ibc.applications.transfer.v1.DenomTrace) | repeated | | -| `params` | [Params](#ibc.applications.transfer.v1.Params) | | | +| `gen_txs` | [bytes](#bytes) | repeated | gen_txs defines the genesis transactions. | @@ -7804,97 +8030,88 @@ GenesisState defines the ibc-transfer genesis state - +

Top

-## ibc/applications/transfer/v1/query.proto +## cosmos/slashing/v1beta1/slashing.proto - + -### QueryDenomTraceRequest -QueryDenomTraceRequest is the request type for the Query/DenomTrace RPC -method +### Params +Params represents the parameters used for by the slashing module. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `hash` | [string](#string) | | hash (in hex format) of the denomination trace information. | +| `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) | | | - + -### QueryDenomTraceResponse -QueryDenomTraceResponse is the response type for the Query/DenomTrace RPC -method. +### ValidatorSigningInfo +ValidatorSigningInfo defines a validator's signing info for monitoring their +liveness activity. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `denom_trace` | [DenomTrace](#ibc.applications.transfer.v1.DenomTrace) | | denom_trace returns the requested denomination trace information. | +| `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`. | + - + -### QueryDenomTracesRequest -QueryConnectionsRequest is the request type for the Query/DenomTraces 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/slashing/v1beta1/tx.proto - + -### QueryDenomTracesResponse -QueryConnectionsResponse is the response type for the Query/DenomTraces RPC -method. +### MsgUnjail +MsgUnjail defines the Msg/Unjail request type | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `denom_traces` | [DenomTrace](#ibc.applications.transfer.v1.DenomTrace) | repeated | denom_traces returns all denominations trace information. | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | - - - - - - - - -### QueryParamsRequest -QueryParamsRequest is the request type for the Query/Params RPC method. - - +| `validator_addr` | [string](#string) | | | - -### QueryParamsResponse -QueryParamsResponse is the response type for the Query/Params RPC method. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `params` | [Params](#ibc.applications.transfer.v1.Params) | | params defines the parameters of the module. | +### MsgUnjailResponse +MsgUnjailResponse defines the Msg/Unjail response type @@ -7907,134 +8124,110 @@ QueryParamsResponse is the response type for the Query/Params RPC method. - + -### Query -Query provides defines the gRPC querier service. +### Msg +Msg defines the slashing Msg 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| +| `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

-## ibc/core/client/v1/client.proto - - +## cosmos/slashing/v1beta1/query.proto - -### ClientConsensusStates -ClientConsensusStates defines all the stored consensus states for a given -client. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client identifier | -| `consensus_states` | [ConsensusStateWithHeight](#ibc.core.client.v1.ConsensusStateWithHeight) | repeated | consensus states and their heights associated with the client | +### QueryParamsRequest +QueryParamsRequest is the request type for the Query/Params RPC method - + -### ClientUpdateProposal -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). +### QueryParamsResponse +QueryParamsResponse is the response type for the Query/Params RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `title` | [string](#string) | | the title of the update proposal | -| `description` | [string](#string) | | the description of the proposal | -| `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 | +| `params` | [Params](#cosmos.slashing.v1beta1.Params) | | | - + -### ConsensusStateWithHeight -ConsensusStateWithHeight defines a consensus state with an additional height field. +### QuerySigningInfoRequest +QuerySigningInfoRequest is the request type for the Query/SigningInfo RPC +method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `height` | [Height](#ibc.core.client.v1.Height) | | consensus state height | -| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | consensus state | - +| `cons_address` | [string](#string) | | cons_address is the address to query signing info of | - -### Height -Height is a monotonically increasing data type -that can be compared against another Height for the purposes of updating and -freezing clients + -Normally the RevisionHeight is incremented at each height while keeping RevisionNumber -the same. However some consensus algorithms may choose to reset the -height in certain conditions e.g. hard forks, state-machine breaking changes -In these cases, the RevisionNumber is incremented so that height continues to -be monitonically increasing even as the RevisionHeight gets reset +### QuerySigningInfoResponse +QuerySigningInfoResponse is the response type for the Query/SigningInfo RPC +method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `revision_number` | [uint64](#uint64) | | the revision that the client is currently on | -| `revision_height` | [uint64](#uint64) | | the height within the given revision | +| `val_signing_info` | [ValidatorSigningInfo](#cosmos.slashing.v1beta1.ValidatorSigningInfo) | | val_signing_info is the signing info of requested val cons address | - + -### IdentifiedClientState -IdentifiedClientState defines a client state with an additional client -identifier field. +### QuerySigningInfosRequest +QuerySigningInfosRequest is the request type for the Query/SigningInfos RPC +method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client identifier | -| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | client state | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | | - + -### Params -Params defines the set of IBC light client parameters. +### QuerySigningInfosResponse +QuerySigningInfosResponse is the response type for the Query/SigningInfos RPC +method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `allowed_clients` | [string](#string) | repeated | allowed_clients defines the list of allowed client state types. | +| `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) | | | @@ -8046,1361 +8239,1282 @@ Params defines the set of IBC light client parameters. + + + +### 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| + - +

Top

-## ibc/applications/transfer/v1/tx.proto +## cosmos/slashing/v1beta1/genesis.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 +### GenesisState +GenesisState defines the slashing module's genesis state. | 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. | - - +| `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. | - -### MsgTransferResponse -MsgTransferResponse defines the Msg/Transfer response type. + +### 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. | - - - - -### 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. | | +### SigningInfo +SigningInfo stores validator signing info of corresponding address. - +| 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. | - -

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 +### ValidatorMissedBlocks +ValidatorMissedBlocks contains array of missed blocks of corresponding +address. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `result` | [bytes](#bytes) | | | -| `error` | [string](#string) | | | +| `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. | + - + -### 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 | -| ----- | ---- | ----- | ----------- | -| `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 | + +

Top

+## cosmos/feegrant/v1beta1/tx.proto - + -### Counterparty -Counterparty defines a channel end counterparty +### MsgGrantFeeAllowance +MsgGrantFeeAllowance adds permission for Grantee to spend up to Allowance +of fees from the account of Granter. | 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 | - - +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `allowance` | [google.protobuf.Any](#google.protobuf.Any) | | | - -### IdentifiedChannel -IdentifiedChannel defines a channel with additional port and channel -identifier fields. + -| 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 | +### MsgGrantFeeAllowanceResponse +MsgGrantFeeAllowanceResponse defines the Msg/GrantFeeAllowanceResponse response type. - + -### Packet -Packet defines a type that carries data across different chains through IBC +### MsgRevokeFeeAllowance +MsgRevokeFeeAllowance removes any existing FeeAllowance from Granter to Grantee. | 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 | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | - + -### 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. +### MsgRevokeFeeAllowanceResponse +MsgRevokeFeeAllowanceResponse defines the Msg/RevokeFeeAllowanceResponse response type. -| 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. | + + - + - + -### Order -Order defines if a channel is ORDERED or UNORDERED +### Msg +Msg defines the feegrant msg service. -| 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 | +| 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. | | + - -### State -State defines if a channel is in one of the following states: -CLOSED, INIT, TRYOPEN, OPEN or UNINITIALIZED. + +

Top

-| 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. | +## 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 | +| ----- | ---- | ----- | ----------- | +| `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 | - -

Top

-## ibc/core/channel/v1/genesis.proto - + -### GenesisState -GenesisState defines the ibc channel submodule'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 | | ----- | ---- | ----- | ----------- | -| `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 | +| `duration` | [google.protobuf.Duration](#google.protobuf.Duration) | | | +| `blocks` | [uint64](#uint64) | | | - + -### PacketSequence -PacketSequence defines the genesis type necessary to retrieve and store -next send and receive sequences. +### ExpiresAt +ExpiresAt is a point in time where something expires. +It may be *either* block time or block height | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | | -| `channel_id` | [string](#string) | | | -| `sequence` | [uint64](#uint64) | | | +| `time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `height` | [int64](#int64) | | | - - + - +### FeeAllowanceGrant +FeeAllowanceGrant is stored in the KVStore to record a grant with full context - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `allowance` | [google.protobuf.Any](#google.protobuf.Any) | | | - -

Top

-## ibc/core/channel/v1/query.proto - + -### QueryChannelClientStateRequest -QueryChannelClientStateRequest is the request type for the Query/ClientState -RPC method +### PeriodicFeeAllowance +PeriodicFeeAllowance extends FeeAllowance to allow for both a maximum cap, +as well as a limit per time period. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | port unique identifier | -| `channel_id` | [string](#string) | | channel unique identifier | +| `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 | + - + -### QueryChannelClientStateResponse -QueryChannelClientStateResponse is the Response type for the -Query/QueryChannelClientState RPC method + + -| 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 | + +

Top

+## cosmos/feegrant/v1beta1/query.proto - + -### QueryChannelConsensusStateRequest -QueryChannelConsensusStateRequest is the request type for the -Query/ConsensusState RPC method +### QueryFeeAllowanceRequest +QueryFeeAllowanceRequest is the request type for the Query/FeeAllowance 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 | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | - + -### QueryChannelConsensusStateResponse -QueryChannelClientStateResponse is the Response type for the -Query/QueryChannelClientState RPC method +### QueryFeeAllowanceResponse +QueryFeeAllowanceResponse is the response type for the Query/FeeAllowance 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 | +| `fee_allowance` | [FeeAllowanceGrant](#cosmos.feegrant.v1beta1.FeeAllowanceGrant) | | fee_allowance is a fee_allowance granted for grantee by granter. | - + -### QueryChannelRequest -QueryChannelRequest is the request type for the Query/Channel RPC method +### QueryFeeAllowancesRequest +QueryFeeAllowancesRequest is the request type for the Query/FeeAllowances RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | port unique identifier | -| `channel_id` | [string](#string) | | channel unique identifier | +| `grantee` | [string](#string) | | | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | - + -### 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. +### QueryFeeAllowancesResponse +QueryFeeAllowancesResponse is the response type for the Query/FeeAllowances 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 | +| `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. | + - + -### 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 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/genesis.proto - -### QueryChannelsResponse -QueryChannelsResponse is the response type for the Query/Channels RPC method. + + + +### GenesisState +GenesisState contains a set of fee allowances, persisted from the store | 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 | +| `fee_allowances` | [FeeAllowanceGrant](#cosmos.feegrant.v1beta1.FeeAllowanceGrant) | repeated | | + - + -### 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 | + +

Top

+## cosmos/auth/v1beta1/auth.proto - + -### QueryConnectionChannelsResponse -QueryConnectionChannelsResponse is the Response type for the -Query/QueryConnectionChannels RPC method +### 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 | | ----- | ---- | ----- | ----------- | -| `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 | +| `address` | [string](#string) | | | +| `pub_key` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `account_number` | [uint64](#uint64) | | | +| `sequence` | [uint64](#uint64) | | | - + -### QueryNextSequenceReceiveRequest -QueryNextSequenceReceiveRequest is the request type for the -Query/QueryNextSequenceReceiveRequest RPC method +### ModuleAccount +ModuleAccount defines an account for modules that holds coins on a pool. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | port unique identifier | -| `channel_id` | [string](#string) | | channel unique identifier | +| `base_account` | [BaseAccount](#cosmos.auth.v1beta1.BaseAccount) | | | +| `name` | [string](#string) | | | +| `permissions` | [string](#string) | repeated | | - + -### QueryNextSequenceReceiveResponse -QuerySequenceResponse is the request type for the -Query/QueryNextSequenceReceiveResponse RPC method +### Params +Params defines the parameters for the auth module. | 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 | +| `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) | | | + - + -### QueryPacketAcknowledgementRequest -QueryPacketAcknowledgementRequest is the request type for the -Query/PacketAcknowledgement 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 | + +

Top

+## cosmos/auth/v1beta1/query.proto - + -### QueryPacketAcknowledgementResponse -QueryPacketAcknowledgementResponse defines the client query response for a -packet which also includes a proof and the height from which the -proof was retrieved +### QueryAccountRequest +QueryAccountRequest is the request type for the Query/Account RPC method. | 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 | +| `address` | [string](#string) | | address defines the address to query for. | - + -### QueryPacketAcknowledgementsRequest -QueryPacketAcknowledgementsRequest is the request type for the -Query/QueryPacketCommitments RPC method +### QueryAccountResponse +QueryAccountResponse is the response type for the Query/Account RPC method. | 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 | - - +| `account` | [google.protobuf.Any](#google.protobuf.Any) | | account defines the account of the corresponding address. | - -### 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 | +### QueryParamsRequest +QueryParamsRequest is the request type for the Query/Params RPC method. - + -### QueryPacketCommitmentRequest -QueryPacketCommitmentRequest is the request type for the -Query/PacketCommitment RPC method +### QueryParamsResponse +QueryParamsResponse is the response type for the Query/Params 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 | +| `params` | [Params](#cosmos.auth.v1beta1.Params) | | params defines the parameters of the module. | + - + -### 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 | + + +### 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/auth/v1beta1/genesis.proto - -### QueryPacketCommitmentsRequest -QueryPacketCommitmentsRequest is the request type for the -Query/QueryPacketCommitments RPC method + + + +### GenesisState +GenesisState defines the auth module's genesis state. | 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 | +| `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. | + - + -### 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

+## cosmos/crisis/v1beta1/tx.proto - + -### QueryPacketReceiptRequest -QueryPacketReceiptRequest is the request type for the -Query/PacketReceipt RPC method +### MsgVerifyInvariant +MsgVerifyInvariant represents a message to verify a particular invariance. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | port unique identifier | -| `channel_id` | [string](#string) | | channel unique identifier | -| `sequence` | [uint64](#uint64) | | packet sequence | +| `sender` | [string](#string) | | | +| `invariant_module_name` | [string](#string) | | | +| `invariant_route` | [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 +### MsgVerifyInvariantResponse +MsgVerifyInvariantResponse defines the Msg/VerifyInvariant response type. -| 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 | + + + - -### QueryUnreceivedAcksRequest -QueryUnreceivedAcks is the request type for the -Query/UnreceivedAcks RPC method + +### Msg +Msg defines the bank Msg service. -| 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 | +| 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/crisis/v1beta1/genesis.proto - -### QueryUnreceivedAcksResponse -QueryUnreceivedAcksResponse is the response type for the -Query/UnreceivedAcks RPC method + + + +### GenesisState +GenesisState defines the crisis module's genesis state. | 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 | +| `constant_fee` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | constant_fee is the fee used to verify the invariant in the crisis module. | + - + -### 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 | + +

Top

+## cosmos/gov/v1beta1/gov.proto - + -### QueryUnreceivedPacketsResponse -QueryUnreceivedPacketsResponse is the response type for the -Query/UnreceivedPacketCommitments RPC method +### Deposit +Deposit defines an amount deposited by an account address to an active +proposal. | 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 | - - - - +| `proposal_id` | [uint64](#uint64) | | | +| `depositor` | [string](#string) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | - - - - -### 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| +### 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

-## ibc/core/channel/v1/tx.proto - + -### MsgAcknowledgement -MsgAcknowledgement receives incoming IBC acknowledgement +### Proposal +Proposal defines the core field members of a governance proposal. | 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) | | | +| `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) | | | - + -### MsgAcknowledgementResponse -MsgAcknowledgementResponse defines the Msg/Acknowledgement response type. +### 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. | - + -### MsgChannelCloseConfirm -MsgChannelCloseConfirm defines a msg sent by a Relayer to Chain B -to acknowledge the change of channel state to CLOSED on Chain A. +### TallyResult +TallyResult defines a standard tally for a governance proposal. | 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) | | | +| `yes` | [string](#string) | | | +| `abstain` | [string](#string) | | | +| `no` | [string](#string) | | | +| `no_with_veto` | [string](#string) | | | - + -### MsgChannelCloseConfirmResponse -MsgChannelCloseConfirmResponse defines the Msg/ChannelCloseConfirm response type. +### TextProposal +TextProposal defines a standard text proposal whose changes need to be +manually updated in case of approval. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `title` | [string](#string) | | | +| `description` | [string](#string) | | | - -### 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) | | | +### 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) | | | +| `options` | [WeightedVoteOption](#cosmos.gov.v1beta1.WeightedVoteOption) | repeated | | - -### MsgChannelCloseInitResponse -MsgChannelCloseInitResponse defines the Msg/ChannelCloseInit response type. + +### 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. | - -### 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) | | | -| `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) | | | + +### WeightedVoteOption +WeightedVoteOption defines a unit of vote for vote split. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `option` | [VoteOption](#cosmos.gov.v1beta1.VoteOption) | | | +| `weight` | [string](#string) | | | - -### MsgChannelOpenAckResponse -MsgChannelOpenAckResponse defines the Msg/ChannelOpenAck response type. + + +### 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. | -### 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) | | | -| `channel_id` | [string](#string) | | | -| `proof_ack` | [bytes](#bytes) | | | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | -| `signer` | [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. | + + - + -### MsgChannelOpenConfirmResponse -MsgChannelOpenConfirmResponse defines the Msg/ChannelOpenConfirm response type. + +

Top

+## cosmos/gov/v1beta1/tx.proto - + -### MsgChannelOpenInit -MsgChannelOpenInit defines an sdk.Msg to initialize a channel handshake. It -is called by a relayer on Chain A. +### MsgDeposit +MsgDeposit defines a message to submit a deposit to an existing proposal. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | | -| `channel` | [Channel](#ibc.core.channel.v1.Channel) | | | -| `signer` | [string](#string) | | | +| `proposal_id` | [uint64](#uint64) | | | +| `depositor` | [string](#string) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | - + -### MsgChannelOpenInitResponse -MsgChannelOpenInitResponse defines the Msg/ChannelOpenInit response type. +### MsgDepositResponse +MsgDepositResponse defines the Msg/Deposit response type. - + -### MsgChannelOpenTry -MsgChannelOpenInit defines a msg sent by a Relayer to try to open a channel -on Chain B. +### MsgSubmitProposal +MsgSubmitProposal defines an sdk.Msg type that supports submitting arbitrary +proposal Content. | 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) | | | +| `content` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `initial_deposit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `proposer` | [string](#string) | | | - + -### MsgChannelOpenTryResponse -MsgChannelOpenTryResponse defines the Msg/ChannelOpenTry response type. +### MsgSubmitProposalResponse +MsgSubmitProposalResponse defines the Msg/SubmitProposal response type. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `proposal_id` | [uint64](#uint64) | | | - + -### MsgRecvPacket -MsgRecvPacket receives incoming IBC packet +### MsgVote +MsgVote defines a message to cast a vote. | 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) | | | +| `proposal_id` | [uint64](#uint64) | | | +| `voter` | [string](#string) | | | +| `option` | [VoteOption](#cosmos.gov.v1beta1.VoteOption) | | | - + -### MsgRecvPacketResponse -MsgRecvPacketResponse defines the Msg/RecvPacket response type. +### MsgVoteResponse +MsgVoteResponse defines the Msg/Vote response type. - + -### MsgTimeout -MsgTimeout receives timed-out packet +### MsgVoteWeighted +MsgVote defines a message to cast a vote. | 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) | | | +| `proposal_id` | [uint64](#uint64) | | | +| `voter` | [string](#string) | | | +| `options` | [WeightedVoteOption](#cosmos.gov.v1beta1.WeightedVoteOption) | repeated | | - + -### MsgTimeoutOnClose -MsgTimeoutOnClose timed-out packet upon counterparty channel closure. +### MsgVoteWeightedResponse +MsgVoteWeightedResponse defines the Msg/VoteWeighted response type. -| 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) | | | + + + - -### MsgTimeoutOnCloseResponse -MsgTimeoutOnCloseResponse defines the Msg/TimeoutOnClose response type. + + +### 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. | | +| `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. | | + + +

Top

+## cosmos/gov/v1beta1/query.proto - -### MsgTimeoutResponse -MsgTimeoutResponse defines the Msg/Timeout response type. + +### QueryDepositRequest +QueryDepositRequest is the request type for the Query/Deposit RPC method. +| 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. | - - - - -### 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. | | +### QueryDepositResponse +QueryDepositResponse is the response type for the Query/Deposit RPC method. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `deposit` | [Deposit](#cosmos.gov.v1beta1.Deposit) | | deposit defines the requested deposit. | - -

Top

-## ibc/core/client/v1/genesis.proto - + -### GenesisMetadata -GenesisMetadata defines the genesis type for metadata that clients may return -with ExportMetadata +### QueryDepositsRequest +QueryDepositsRequest is the request type for the Query/Deposits RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | store key of metadata without clientID-prefix | -| `value` | [bytes](#bytes) | | metadata value | +| `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. | - + -### GenesisState -GenesisState defines the ibc client submodule's genesis state. +### QueryDepositsResponse +QueryDepositsResponse is the response type for the Query/Deposits 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 | +| `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. | - + -### IdentifiedGenesisMetadata -IdentifiedGenesisMetadata has the client metadata with the corresponding client id. +### QueryParamsRequest +QueryParamsRequest is the request type for the Query/Params RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | | -| `client_metadata` | [GenesisMetadata](#ibc.core.client.v1.GenesisMetadata) | repeated | | +| `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

-## ibc/core/client/v1/query.proto - + -### QueryClientParamsRequest -QueryClientParamsRequest is the request type for the Query/ClientParams RPC method. +### 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. | - -### QueryClientParamsResponse -QueryClientParamsResponse is the response type for the Query/ClientParams RPC method. + + + +### QueryProposalResponse +QueryProposalResponse is the response type for the Query/Proposal RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params` | [Params](#ibc.core.client.v1.Params) | | params defines the parameters of the module. | +| `proposal` | [Proposal](#cosmos.gov.v1beta1.Proposal) | | | - + -### QueryClientStateRequest -QueryClientStateRequest is the request type for the Query/ClientState RPC -method +### QueryProposalsRequest +QueryProposalsRequest is the request type for the Query/Proposals RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client state unique identifier | +| `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. | - + -### 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. +### QueryProposalsResponse +QueryProposalsResponse is the response type for the Query/Proposals RPC +method. | 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 | +| `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. | - + -### QueryClientStatesRequest -QueryClientStatesRequest is the request type for the Query/ClientStates RPC -method +### QueryTallyResultRequest +QueryTallyResultRequest is the request type for the Query/Tally RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | +| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | - + -### QueryClientStatesResponse -QueryClientStatesResponse is the response type for the Query/ClientStates RPC -method. +### QueryTallyResultResponse +QueryTallyResultResponse is the response type for the Query/Tally 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 | +| `tally` | [TallyResult](#cosmos.gov.v1beta1.TallyResult) | | tally defines the requested tally. | - + -### 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. +### QueryVoteRequest +QueryVoteRequest is the request type for the Query/Vote RPC method. | 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 | +| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | +| `voter` | [string](#string) | | voter defines the oter address for the proposals. | - + -### QueryConsensusStateResponse -QueryConsensusStateResponse is the response type for the Query/ConsensusState -RPC method +### QueryVoteResponse +QueryVoteResponse is the response type for the Query/Vote 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 | +| `vote` | [Vote](#cosmos.gov.v1beta1.Vote) | | vote defined the queried vote. | - + -### QueryConsensusStatesRequest -QueryConsensusStatesRequest is the request type for the Query/ConsensusStates -RPC method. +### QueryVotesRequest +QueryVotesRequest is the request type for the Query/Votes RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client identifier | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | +| `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. | - + -### QueryConsensusStatesResponse -QueryConsensusStatesResponse is the response type for the -Query/ConsensusStates RPC method +### QueryVotesResponse +QueryVotesResponse is the response type for the Query/Votes 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 | +| `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. | @@ -9413,137 +9527,194 @@ Query/ConsensusStates RPC method - + ### Query -Query provides defines the gRPC querier service +Query defines the gRPC querier service for gov module | 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| +| `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/genesis.proto + + + + + +### GenesisState +GenesisState defines the gov module's genesis state. + + +| 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. | + + + + + + + + + + - -

Top

+ +

Top

+ +## cosmos/mint/v1beta1/mint.proto + + + + + +### Minter +Minter represents the minting state. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `inflation` | [string](#string) | | current annual inflation rate | +| `annual_provisions` | [string](#string) | | current annual expected provisions | + + + + + + + + +### 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 | + + -## ibc/core/client/v1/tx.proto + - + -### 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 | + +

Top

+## cosmos/mint/v1beta1/query.proto - + -### MsgCreateClientResponse -MsgCreateClientResponse defines the Msg/CreateClient response type. +### QueryAnnualProvisionsRequest +QueryAnnualProvisionsRequest is the request type for the +Query/AnnualProvisions RPC method. - + -### MsgSubmitMisbehaviour -MsgSubmitMisbehaviour defines an sdk.Msg type that submits Evidence for -light client misbehaviour. +### QueryAnnualProvisionsResponse +QueryAnnualProvisionsResponse is the response type for the +Query/AnnualProvisions 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 | +| `annual_provisions` | [bytes](#bytes) | | annual_provisions is the current minting annual provisions value. | - + -### MsgSubmitMisbehaviourResponse -MsgSubmitMisbehaviourResponse defines the Msg/SubmitMisbehaviour response type. +### QueryInflationRequest +QueryInflationRequest is the request type for the Query/Inflation RPC method. - + -### MsgUpdateClient -MsgUpdateClient defines an sdk.Msg to update a IBC client state using -the given header. +### QueryInflationResponse +QueryInflationResponse is the response type for the Query/Inflation 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 | +| `inflation` | [bytes](#bytes) | | inflation is the current minting inflation value. | - + -### MsgUpdateClientResponse -MsgUpdateClientResponse defines the Msg/UpdateClient response type. +### QueryParamsRequest +QueryParamsRequest is the request type for the Query/Params RPC method. - + -### MsgUpgradeClient -MsgUpgradeClient defines an sdk.Msg to upgrade an IBC client to a new client state +### QueryParamsResponse +QueryParamsResponse is the response type for the Query/Params RPC method. | 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 | - - - - - - - - -### MsgUpgradeClientResponse -MsgUpgradeClientResponse defines the Msg/UpgradeClient response type. +| `params` | [Params](#cosmos.mint.v1beta1.Params) | | params defines the parameters of the module. | @@ -9556,92 +9727,84 @@ MsgUpgradeClientResponse defines the Msg/UpgradeClient response type. - + -### Msg -Msg defines the ibc/client Msg service. +### Query +Query provides defines the gRPC querier 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. | | +| `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

-## ibc/core/commitment/v1/commitment.proto +## cosmos/mint/v1beta1/genesis.proto - + -### MerklePath -MerklePath is the path used to verify commitment proofs, which can be an -arbitrary structured object (defined by a commitment type). -MerklePath is represented from root-to-leaf +### GenesisState +GenesisState defines the mint module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key_path` | [string](#string) | repeated | | +| `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. | + - + -### MerklePrefix -MerklePrefix is merkle path prefixed to the key. -The constructed key from the Path and the key will be append(Path.KeyPath, -append(Path.KeyPrefix, key...)) + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `key_prefix` | [bytes](#bytes) | | | + +

Top

+## cosmos/vesting/v1beta1/tx.proto - + -### MerkleProof -MerkleProof is a wrapper type over a chain of CommitmentProofs. -It demonstrates membership or non-membership for an element or set of -elements, verifiable in conjunction with a known commitment root. Proofs -should be succinct. -MerkleProofs are ordered from leaf-to-root +### MsgCreateVestingAccount +MsgCreateVestingAccount defines a message that enables creating a vesting +account. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proofs` | [ics23.CommitmentProof](#ics23.CommitmentProof) | repeated | | - - +| `from_address` | [string](#string) | | | +| `to_address` | [string](#string) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `end_time` | [int64](#int64) | | | +| `delayed` | [bool](#bool) | | | - -### MerkleRoot -MerkleRoot defines a merkle root hash. -In the Cosmos SDK, the AppHash of a block header becomes the root. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `hash` | [bytes](#bytes) | | | +### MsgCreateVestingAccountResponse +MsgCreateVestingAccountResponse defines the Msg/CreateVestingAccount response type. @@ -9653,140 +9816,115 @@ In the Cosmos SDK, the AppHash of a block header becomes the root. - - - - - -

Top

- -## ibc/core/connection/v1/connection.proto - + - +### Msg +Msg defines the bank Msg service. -### ClientPaths -ClientPaths define all the connection paths for a client state. +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `CreateVestingAccount` | [MsgCreateVestingAccount](#cosmos.vesting.v1beta1.MsgCreateVestingAccount) | [MsgCreateVestingAccountResponse](#cosmos.vesting.v1beta1.MsgCreateVestingAccountResponse) | CreateVestingAccount defines a method that enables creating a vesting account. | | + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `paths` | [string](#string) | repeated | list of connection paths | + +

Top

+## cosmos/vesting/v1beta1/vesting.proto - + -### ConnectionEnd -ConnectionEnd defines a stateful object on a chain connected to another -separate one. -NOTE: there must only be 2 defined ConnectionEnds to establish -a connection between two chains. +### BaseVestingAccount +BaseVestingAccount implements the VestingAccount interface. It contains all +the necessary fields needed for any vesting account implementation. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client associated with this connection. | -| `versions` | [Version](#ibc.core.connection.v1.Version) | repeated | IBC version which can be utilised to determine encodings or protocols for channels or packets utilising this connection. | -| `state` | [State](#ibc.core.connection.v1.State) | | current state of the connection end. | -| `counterparty` | [Counterparty](#ibc.core.connection.v1.Counterparty) | | counterparty chain associated with this connection. | -| `delay_period` | [uint64](#uint64) | | delay period that must pass before a consensus state can be used for packet-verification NOTE: delay period logic is only implemented by some clients. | +| `base_account` | [cosmos.auth.v1beta1.BaseAccount](#cosmos.auth.v1beta1.BaseAccount) | | | +| `original_vesting` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `delegated_free` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `delegated_vesting` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `end_time` | [int64](#int64) | | | - + -### ConnectionPaths -ConnectionPaths define all the connection paths for a given client state. +### ContinuousVestingAccount +ContinuousVestingAccount implements the VestingAccount interface. It +continuously vests by unlocking coins linearly with respect to time. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client state unique identifier | -| `paths` | [string](#string) | repeated | list of connection paths | +| `base_vesting_account` | [BaseVestingAccount](#cosmos.vesting.v1beta1.BaseVestingAccount) | | | +| `start_time` | [int64](#int64) | | | - + -### Counterparty -Counterparty defines the counterparty chain associated with a connection end. +### DelayedVestingAccount +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. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | identifies the client on the counterparty chain associated with a given connection. | -| `connection_id` | [string](#string) | | identifies the connection end on the counterparty chain associated with a given connection. | -| `prefix` | [ibc.core.commitment.v1.MerklePrefix](#ibc.core.commitment.v1.MerklePrefix) | | commitment merkle prefix of the counterparty chain. | +| `base_vesting_account` | [BaseVestingAccount](#cosmos.vesting.v1beta1.BaseVestingAccount) | | | - + -### IdentifiedConnection -IdentifiedConnection defines a connection with additional connection -identifier field. +### Period +Period defines a length of time and amount of coins that will vest. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `id` | [string](#string) | | connection identifier. | -| `client_id` | [string](#string) | | client associated with this connection. | -| `versions` | [Version](#ibc.core.connection.v1.Version) | repeated | IBC version which can be utilised to determine encodings or protocols for channels or packets utilising this connection | -| `state` | [State](#ibc.core.connection.v1.State) | | current state of the connection end. | -| `counterparty` | [Counterparty](#ibc.core.connection.v1.Counterparty) | | counterparty chain associated with this connection. | -| `delay_period` | [uint64](#uint64) | | delay period associated with this connection. | - - - - - +| `length` | [int64](#int64) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | - -### Version -Version defines the versioning scheme used to negotiate the IBC verison in -the connection handshake. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `identifier` | [string](#string) | | unique version identifier | -| `features` | [string](#string) | repeated | list of features compatible with the specified identifier | + +### PeriodicVestingAccount +PeriodicVestingAccount implements the VestingAccount interface. It +periodically vests by unlocking coins during each specified period. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `base_vesting_account` | [BaseVestingAccount](#cosmos.vesting.v1beta1.BaseVestingAccount) | | | +| `start_time` | [int64](#int64) | | | +| `vesting_periods` | [Period](#cosmos.vesting.v1beta1.Period) | repeated | | - -### State -State defines if a connection is in one of the following states: -INIT, TRYOPEN, OPEN or UNINITIALIZED. -| Name | Number | Description | -| ---- | ------ | ----------- | -| STATE_UNINITIALIZED_UNSPECIFIED | 0 | Default State | -| STATE_INIT | 1 | A connection end has just started the opening handshake. | -| STATE_TRYOPEN | 2 | A connection end has acknowledged the handshake step on the counterparty chain. | -| STATE_OPEN | 3 | A connection end has completed the handshake. | + @@ -9796,375 +9934,366 @@ INIT, TRYOPEN, OPEN or UNINITIALIZED. - +

Top

-## ibc/core/connection/v1/genesis.proto +## cosmos/distribution/v1beta1/tx.proto - + -### GenesisState -GenesisState defines the ibc connection submodule's genesis state. +### MsgFundCommunityPool +MsgFundCommunityPool allows an account to directly +fund the community pool. | 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 | - - +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `depositor` | [string](#string) | | | - - - - + +### MsgFundCommunityPoolResponse +MsgFundCommunityPoolResponse defines the Msg/FundCommunityPool response type. - -

Top

-## ibc/core/connection/v1/query.proto - + -### QueryClientConnectionsRequest -QueryClientConnectionsRequest is the request type for the -Query/ClientConnections RPC method +### MsgSetWithdrawAddress +MsgSetWithdrawAddress sets the withdraw address for +a delegator (or validator self-delegation). | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client identifier associated with a connection | - - +| `delegator_address` | [string](#string) | | | +| `withdraw_address` | [string](#string) | | | - -### QueryClientConnectionsResponse -QueryClientConnectionsResponse is the response type for the -Query/ClientConnections RPC method + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `connection_paths` | [string](#string) | repeated | slice of all the connection paths associated with a client. | -| `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 generated | +### MsgSetWithdrawAddressResponse +MsgSetWithdrawAddressResponse defines the Msg/SetWithdrawAddress response type. - + -### QueryConnectionClientStateRequest -QueryConnectionClientStateRequest is the request type for the -Query/ConnectionClientState RPC method +### MsgWithdrawDelegatorReward +MsgWithdrawDelegatorReward represents delegation withdrawal to a delegator +from a single validator. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `connection_id` | [string](#string) | | connection identifier | - - +| `delegator_address` | [string](#string) | | | +| `validator_address` | [string](#string) | | | - -### QueryConnectionClientStateResponse -QueryConnectionClientStateResponse is the response type for the -Query/ConnectionClientState RPC method + -| 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 | +### MsgWithdrawDelegatorRewardResponse +MsgWithdrawDelegatorRewardResponse defines the Msg/WithdrawDelegatorReward response type. - + -### QueryConnectionConsensusStateRequest -QueryConnectionConsensusStateRequest is the request type for the -Query/ConnectionConsensusState RPC method +### MsgWithdrawValidatorCommission +MsgWithdrawValidatorCommission withdraws the full commission to the validator +address. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `connection_id` | [string](#string) | | connection identifier | -| `revision_number` | [uint64](#uint64) | | | -| `revision_height` | [uint64](#uint64) | | | +| `validator_address` | [string](#string) | | | - + -### QueryConnectionConsensusStateResponse -QueryConnectionConsensusStateResponse is the response type for the -Query/ConnectionConsensusState RPC method +### MsgWithdrawValidatorCommissionResponse +MsgWithdrawValidatorCommissionResponse defines the Msg/WithdrawValidatorCommission response type. -| 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 | + + + - -### QueryConnectionRequest -QueryConnectionRequest is the request type for the Query/Connection RPC -method + +### Msg +Msg defines the distribution Msg service. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `connection_id` | [string](#string) | | connection unique identifier | +| 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/distribution.proto - -### QueryConnectionResponse -QueryConnectionResponse is the response type for the Query/Connection RPC -method. Besides the connection end, it includes a proof and the height from -which the proof was retrieved. + + + +### 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 | | ----- | ---- | ----- | ----------- | -| `connection` | [ConnectionEnd](#ibc.core.connection.v1.ConnectionEnd) | | connection associated with the request identifier | -| `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 | +| `title` | [string](#string) | | | +| `description` | [string](#string) | | | +| `recipient` | [string](#string) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | - + -### QueryConnectionsRequest -QueryConnectionsRequest is the request type for the Query/Connections RPC -method +### CommunityPoolSpendProposalWithDeposit +CommunityPoolSpendProposalWithDeposit defines a CommunityPoolSpendProposal +with a deposit | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | | +| `title` | [string](#string) | | | +| `description` | [string](#string) | | | +| `recipient` | [string](#string) | | | +| `amount` | [string](#string) | | | +| `deposit` | [string](#string) | | | - + -### QueryConnectionsResponse -QueryConnectionsResponse is the response type for the Query/Connections RPC -method. +### DelegationDelegatorReward +DelegationDelegatorReward represents the properties +of a delegator's delegation reward. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `connections` | [IdentifiedConnection](#ibc.core.connection.v1.IdentifiedConnection) | repeated | list of stored connections 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 | - - - - +| `validator_address` | [string](#string) | | | +| `reward` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | - - - - -### Query -Query provides defines the gRPC querier service + -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Connection` | [QueryConnectionRequest](#ibc.core.connection.v1.QueryConnectionRequest) | [QueryConnectionResponse](#ibc.core.connection.v1.QueryConnectionResponse) | Connection queries an IBC connection end. | GET|/ibc/core/connection/v1beta1/connections/{connection_id}| -| `Connections` | [QueryConnectionsRequest](#ibc.core.connection.v1.QueryConnectionsRequest) | [QueryConnectionsResponse](#ibc.core.connection.v1.QueryConnectionsResponse) | Connections queries all the IBC connections of a chain. | GET|/ibc/core/connection/v1beta1/connections| -| `ClientConnections` | [QueryClientConnectionsRequest](#ibc.core.connection.v1.QueryClientConnectionsRequest) | [QueryClientConnectionsResponse](#ibc.core.connection.v1.QueryClientConnectionsResponse) | ClientConnections queries the connection paths associated with a client state. | GET|/ibc/core/connection/v1beta1/client_connections/{client_id}| -| `ConnectionClientState` | [QueryConnectionClientStateRequest](#ibc.core.connection.v1.QueryConnectionClientStateRequest) | [QueryConnectionClientStateResponse](#ibc.core.connection.v1.QueryConnectionClientStateResponse) | ConnectionClientState queries the client state associated with the connection. | GET|/ibc/core/connection/v1beta1/connections/{connection_id}/client_state| -| `ConnectionConsensusState` | [QueryConnectionConsensusStateRequest](#ibc.core.connection.v1.QueryConnectionConsensusStateRequest) | [QueryConnectionConsensusStateResponse](#ibc.core.connection.v1.QueryConnectionConsensusStateResponse) | ConnectionConsensusState queries the consensus state associated with the connection. | GET|/ibc/core/connection/v1beta1/connections/{connection_id}/consensus_state/revision/{revision_number}/height/{revision_height}| +### 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

-## ibc/core/connection/v1/tx.proto - + -### MsgConnectionOpenAck -MsgConnectionOpenAck defines a msg sent by a Relayer to Chain A to -acknowledge the change of connection state to TRYOPEN on Chain B. +### FeePool +FeePool is the global fee pool for distribution. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `connection_id` | [string](#string) | | | -| `counterparty_connection_id` | [string](#string) | | | -| `version` | [Version](#ibc.core.connection.v1.Version) | | | -| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | -| `proof_try` | [bytes](#bytes) | | proof of the initialization the connection on Chain B: `UNITIALIZED -> TRYOPEN` | -| `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) | | | +| `community_pool` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | - + + +### Params +Params defines the set of params for the distribution module. -### MsgConnectionOpenAckResponse -MsgConnectionOpenAckResponse defines the Msg/ConnectionOpenAck response type. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `community_tax` | [string](#string) | | | +| `base_proposer_reward` | [string](#string) | | | +| `bonus_proposer_reward` | [string](#string) | | | +| `withdraw_addr_enabled` | [bool](#bool) | | | - -### MsgConnectionOpenConfirm -MsgConnectionOpenConfirm defines a msg sent by a Relayer to Chain B to -acknowledge the change of connection state to OPEN on Chain A. + + +### ValidatorAccumulatedCommission +ValidatorAccumulatedCommission represents accumulated commission +for a validator kept as a running counter, can be withdrawn at any time. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `connection_id` | [string](#string) | | | -| `proof_ack` | [bytes](#bytes) | | proof for the change of the connection state on Chain A: `INIT -> OPEN` | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | -| `signer` | [string](#string) | | | +| `commission` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | - + -### MsgConnectionOpenConfirmResponse -MsgConnectionOpenConfirmResponse defines the Msg/ConnectionOpenConfirm response type. +### 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) | | | - + -### MsgConnectionOpenInit -MsgConnectionOpenInit defines the msg sent by an account on Chain A to -initialize a connection with Chain B. +### 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 | | ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | | -| `counterparty` | [Counterparty](#ibc.core.connection.v1.Counterparty) | | | -| `version` | [Version](#ibc.core.connection.v1.Version) | | | -| `delay_period` | [uint64](#uint64) | | | -| `signer` | [string](#string) | | | +| `cumulative_reward_ratio` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | +| `reference_count` | [uint32](#uint32) | | | - + -### MsgConnectionOpenInitResponse -MsgConnectionOpenInitResponse defines the Msg/ConnectionOpenInit response type. +### ValidatorOutstandingRewards +ValidatorOutstandingRewards represents outstanding (un-withdrawn) rewards +for a validator inexpensive to track, allows simple sanity checks. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `rewards` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | - -### MsgConnectionOpenTry -MsgConnectionOpenTry defines a msg sent by a Relayer to try to open a -connection on Chain B. + + + +### 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 | | ----- | ---- | ----- | ----------- | -| `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) | | | +| `validator_period` | [uint64](#uint64) | | | +| `fraction` | [string](#string) | | | - + -### MsgConnectionOpenTryResponse -MsgConnectionOpenTryResponse defines the Msg/ConnectionOpenTry response type. +### ValidatorSlashEvents +ValidatorSlashEvents is a collection of ValidatorSlashEvent messages. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `validator_slash_events` | [ValidatorSlashEvent](#cosmos.distribution.v1beta1.ValidatorSlashEvent) | repeated | | @@ -10176,513 +10305,471 @@ 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

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

Top

+ -## ibc/core/types/v1/genesis.proto +### QueryCommunityPoolRequest +QueryCommunityPoolRequest is the request type for the Query/CommunityPool RPC +method. - -### GenesisState -GenesisState defines the ibc module's genesis state. + + + + +### QueryCommunityPoolResponse +QueryCommunityPoolResponse is the response type for the Query/CommunityPool +RPC method. | 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 | +| `pool` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | pool defines community pool's coins. | - - + - +### QueryDelegationRewardsRequest +QueryDelegationRewardsRequest is the request type for the +Query/DelegationRewards RPC method. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `delegator_address` | [string](#string) | | delegator_address defines the delegator address to query for. | +| `validator_address` | [string](#string) | | validator_address defines the validator address to query for. | - -

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. +### QueryDelegationRewardsResponse +QueryDelegationRewardsResponse is the response type for the +Query/DelegationRewards RPC method. | 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 | +| `rewards` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | rewards defines the rewards accrued by a delegation. | - - + - +### QueryDelegationTotalRewardsRequest +QueryDelegationTotalRewardsRequest is the request type for the +Query/DelegationTotalRewards RPC method. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `delegator_address` | [string](#string) | | delegator_address defines the delegator address to query for. | - -

Top

-## ibc/lightclients/solomachine/v1/solomachine.proto - + -### ChannelStateData -ChannelStateData returns the SignBytes data for channel state -verification. +### QueryDelegationTotalRewardsResponse +QueryDelegationTotalRewardsResponse is the response type for the +Query/DelegationTotalRewards RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `path` | [bytes](#bytes) | | | -| `channel` | [ibc.core.channel.v1.Channel](#ibc.core.channel.v1.Channel) | | | +| `rewards` | [DelegationDelegatorReward](#cosmos.distribution.v1beta1.DelegationDelegatorReward) | repeated | rewards defines all the rewards accrued by a delegator. | +| `total` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | total defines the sum of all the rewards. | - + -### ClientState -ClientState defines a solo machine client that tracks the current consensus -state and if the client is frozen. +### QueryDelegatorValidatorsRequest +QueryDelegatorValidatorsRequest is the request type for the +Query/DelegatorValidators RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `sequence` | [uint64](#uint64) | | latest sequence of the client state | -| `frozen_sequence` | [uint64](#uint64) | | frozen sequence of the solo machine | -| `consensus_state` | [ConsensusState](#ibc.lightclients.solomachine.v1.ConsensusState) | | | -| `allow_update_after_proposal` | [bool](#bool) | | when set to true, will allow governance to update a solo machine client. The client will be unfrozen if it is frozen. | +| `delegator_address` | [string](#string) | | delegator_address defines the delegator address to query for. | - + -### ClientStateData -ClientStateData returns the SignBytes data for client state verification. +### QueryDelegatorValidatorsResponse +QueryDelegatorValidatorsResponse is the response type for the +Query/DelegatorValidators RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `path` | [bytes](#bytes) | | | -| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `validators` | [string](#string) | repeated | validators defines the validators a delegator is delegating for. | - + -### ConnectionStateData -ConnectionStateData returns the SignBytes data for connection state -verification. +### QueryDelegatorWithdrawAddressRequest +QueryDelegatorWithdrawAddressRequest is the request type for the +Query/DelegatorWithdrawAddress RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `path` | [bytes](#bytes) | | | -| `connection` | [ibc.core.connection.v1.ConnectionEnd](#ibc.core.connection.v1.ConnectionEnd) | | | +| `delegator_address` | [string](#string) | | delegator_address defines the delegator address to query for. | - + -### ConsensusState -ConsensusState defines a solo machine consensus state. The sequence of a consensus state -is contained in the "height" key used in storing the consensus state. +### QueryDelegatorWithdrawAddressResponse +QueryDelegatorWithdrawAddressResponse is the response type for the +Query/DelegatorWithdrawAddress RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `public_key` | [google.protobuf.Any](#google.protobuf.Any) | | public key of the solo machine | -| `diversifier` | [string](#string) | | diversifier allows the same public key to be re-used across different solo machine clients (potentially on different chains) without being considered misbehaviour. | -| `timestamp` | [uint64](#uint64) | | | - - +| `withdraw_address` | [string](#string) | | withdraw_address defines the delegator address to query for. | - -### ConsensusStateData -ConsensusStateData returns the SignBytes data for consensus state -verification. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `path` | [bytes](#bytes) | | | -| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | | +### QueryParamsRequest +QueryParamsRequest is the request type for the Query/Params RPC method. - + -### Header -Header defines a solo machine consensus header +### QueryParamsResponse +QueryParamsResponse is the response type for the Query/Params RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `sequence` | [uint64](#uint64) | | sequence to update solo machine public key at | -| `timestamp` | [uint64](#uint64) | | | -| `signature` | [bytes](#bytes) | | | -| `new_public_key` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `new_diversifier` | [string](#string) | | | +| `params` | [Params](#cosmos.distribution.v1beta1.Params) | | params defines the parameters of the module. | - + -### HeaderData -HeaderData returns the SignBytes data for update verification. +### QueryValidatorCommissionRequest +QueryValidatorCommissionRequest is the request type for the +Query/ValidatorCommission RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `new_pub_key` | [google.protobuf.Any](#google.protobuf.Any) | | header public key | -| `new_diversifier` | [string](#string) | | header diversifier | +| `validator_address` | [string](#string) | | validator_address defines the validator address to query for. | - + -### Misbehaviour -Misbehaviour defines misbehaviour for a solo machine which consists -of a sequence and two signatures over different messages at that sequence. +### QueryValidatorCommissionResponse +QueryValidatorCommissionResponse is the response type for the +Query/ValidatorCommission RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | | -| `sequence` | [uint64](#uint64) | | | -| `signature_one` | [SignatureAndData](#ibc.lightclients.solomachine.v1.SignatureAndData) | | | -| `signature_two` | [SignatureAndData](#ibc.lightclients.solomachine.v1.SignatureAndData) | | | +| `commission` | [ValidatorAccumulatedCommission](#cosmos.distribution.v1beta1.ValidatorAccumulatedCommission) | | commission defines the commision the validator received. | - + -### NextSequenceRecvData -NextSequenceRecvData returns the SignBytes data for verification of the next -sequence to be received. +### QueryValidatorOutstandingRewardsRequest +QueryValidatorOutstandingRewardsRequest is the request type for the +Query/ValidatorOutstandingRewards RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `path` | [bytes](#bytes) | | | -| `next_seq_recv` | [uint64](#uint64) | | | +| `validator_address` | [string](#string) | | validator_address defines the validator address to query for. | - + -### PacketAcknowledgementData -PacketAcknowledgementData returns the SignBytes data for acknowledgement -verification. +### QueryValidatorOutstandingRewardsResponse +QueryValidatorOutstandingRewardsResponse is the response type for the +Query/ValidatorOutstandingRewards RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `path` | [bytes](#bytes) | | | -| `acknowledgement` | [bytes](#bytes) | | | +| `rewards` | [ValidatorOutstandingRewards](#cosmos.distribution.v1beta1.ValidatorOutstandingRewards) | | | - + -### PacketCommitmentData -PacketCommitmentData returns the SignBytes data for packet commitment -verification. +### QueryValidatorSlashesRequest +QueryValidatorSlashesRequest is the request type for the +Query/ValidatorSlashes RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `path` | [bytes](#bytes) | | | -| `commitment` | [bytes](#bytes) | | | +| `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. | - + -### PacketReceiptAbsenceData -PacketReceiptAbsenceData returns the SignBytes data for -packet receipt absence verification. +### QueryValidatorSlashesResponse +QueryValidatorSlashesResponse is the response type for the +Query/ValidatorSlashes RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `path` | [bytes](#bytes) | | | - +| `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. | - + -### SignBytes -SignBytes defines the signed bytes used for signature verification. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `sequence` | [uint64](#uint64) | | | -| `timestamp` | [uint64](#uint64) | | | -| `diversifier` | [string](#string) | | | -| `data_type` | [DataType](#ibc.lightclients.solomachine.v1.DataType) | | type of the data used | -| `data` | [bytes](#bytes) | | marshaled data | + +### 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| + - -### SignatureAndData -SignatureAndData contains a signature and the data signed over to create that -signature. + +

Top

+## cosmos/distribution/v1beta1/genesis.proto -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `signature` | [bytes](#bytes) | | | -| `data_type` | [DataType](#ibc.lightclients.solomachine.v1.DataType) | | | -| `data` | [bytes](#bytes) | | | -| `timestamp` | [uint64](#uint64) | | | + +### 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. | - -### TimestampedSignatureData -TimestampedSignatureData contains the signature data and the timestamp of the -signature. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `signature_data` | [bytes](#bytes) | | | -| `timestamp` | [uint64](#uint64) | | | + +### 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. | - -### DataType -DataType defines the type of solo machine proof being created. This is done to preserve uniqueness of different -data sign byte encodings. -| Name | Number | Description | -| ---- | ------ | ----------- | -| DATA_TYPE_UNINITIALIZED_UNSPECIFIED | 0 | Default State | -| DATA_TYPE_CLIENT_STATE | 1 | Data type for client state verification | -| DATA_TYPE_CONSENSUS_STATE | 2 | Data type for consensus state verification | -| DATA_TYPE_CONNECTION_STATE | 3 | Data type for connection state verification | -| DATA_TYPE_CHANNEL_STATE | 4 | Data type for channel state verification | -| DATA_TYPE_PACKET_COMMITMENT | 5 | Data type for packet commitment verification | -| DATA_TYPE_PACKET_ACKNOWLEDGEMENT | 6 | Data type for packet acknowledgement verification | -| DATA_TYPE_PACKET_RECEIPT_ABSENCE | 7 | Data type for packet receipt absence verification | -| DATA_TYPE_NEXT_SEQUENCE_RECV | 8 | Data type for next sequence recv verification | -| DATA_TYPE_HEADER | 9 | Data type for header verification | - + - +### 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. | - -

Top

-## ibc/lightclients/tendermint/v1/tendermint.proto - + -### ClientState -ClientState from Tendermint tracks the current validator set, latest height, -and a possible frozen height. +### ValidatorAccumulatedCommissionRecord +ValidatorAccumulatedCommissionRecord is used for import / export via genesis +json. | 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 | +| `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. | - + -### ConsensusState -ConsensusState defines the consensus state from Tendermint. +### ValidatorCurrentRewardsRecord +ValidatorCurrentRewardsRecord is used for import / export via genesis json. | 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) | | | +| `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. | - + -### Fraction -Fraction defines the protobuf message type for tmmath.Fraction that only supports positive values. +### ValidatorHistoricalRewardsRecord +ValidatorHistoricalRewardsRecord is used for import / export via genesis +json. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `numerator` | [uint64](#uint64) | | | -| `denominator` | [uint64](#uint64) | | | +| `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. | - + -### 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. +### ValidatorOutstandingRewardsRecord +ValidatorOutstandingRewardsRecord is used for import/export via genesis json. | 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) | | | +| `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. | - + -### Misbehaviour -Misbehaviour is a wrapper over two conflicting Headers -that implements Misbehaviour interface expected by ICS-02 +### ValidatorSlashEventRecord +ValidatorSlashEventRecord is used for import / export via genesis json. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | | -| `header_1` | [Header](#ibc.lightclients.tendermint.v1.Header) | | | -| `header_2` | [Header](#ibc.lightclients.tendermint.v1.Header) | | | +| `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. | diff --git a/proto/cosmos/authz/v1beta1/authz.proto b/proto/cosmos/authz/v1beta1/authz.proto index 56c403a79ff7..43078f8666f1 100644 --- a/proto/cosmos/authz/v1beta1/authz.proto +++ b/proto/cosmos/authz/v1beta1/authz.proto @@ -1,7 +1,6 @@ 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"; @@ -9,15 +8,6 @@ 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 { diff --git a/proto/cosmos/authz/v1beta1/genesis.proto b/proto/cosmos/authz/v1beta1/genesis.proto index 940d42e1f29b..e593c43f219c 100644 --- a/proto/cosmos/authz/v1beta1/genesis.proto +++ b/proto/cosmos/authz/v1beta1/genesis.proto @@ -5,7 +5,6 @@ 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"; diff --git a/proto/cosmos/authz/v1beta1/query.proto b/proto/cosmos/authz/v1beta1/query.proto index 8c7d50a8d7e1..7a73325815a5 100644 --- a/proto/cosmos/authz/v1beta1/query.proto +++ b/proto/cosmos/authz/v1beta1/query.proto @@ -1,10 +1,7 @@ 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"; diff --git a/proto/cosmos/bank/v1beta1/authz.proto b/proto/cosmos/bank/v1beta1/authz.proto new file mode 100644 index 000000000000..f3505ad41cab --- /dev/null +++ b/proto/cosmos/bank/v1beta1/authz.proto @@ -0,0 +1,17 @@ +syntax = "proto3"; +package cosmos.bank.v1beta1; + +import "gogoproto/gogo.proto"; +import "cosmos_proto/cosmos.proto"; +import "cosmos/base/v1beta1/coin.proto"; + +option go_package = "github.com/cosmos/cosmos-sdk/x/bank/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"]; +} diff --git a/proto/cosmos/staking/v1beta1/authz.proto b/proto/cosmos/staking/v1beta1/authz.proto new file mode 100644 index 000000000000..6345612f2d18 --- /dev/null +++ b/proto/cosmos/staking/v1beta1/authz.proto @@ -0,0 +1,43 @@ +syntax = "proto3"; +package cosmos.staking.v1beta1; + +import "gogoproto/gogo.proto"; +import "cosmos_proto/cosmos.proto"; +import "cosmos/base/v1beta1/coin.proto"; + +option go_package = "github.com/cosmos/cosmos-sdk/x/staking/types"; + +// StakeAuthorization defines authorization for delegate/undelegate/redelegate. +message StakeAuthorization { + option (cosmos_proto.implements_interface) = "Authorization"; + + // max_tokens specifies the maximum amount of tokens can be delegate to a validator. If it is + // empty, there is no spend limit and any amount of coins can be delegated. + cosmos.base.v1beta1.Coin max_tokens = 1 [(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coin"]; + // validators is the oneof that represents either allow_list or deny_list + oneof validators { + // allow_list specifies list of validator addresses to whom grantee can delegate tokens on behalf of granter's + // account. + Validators allow_list = 2; + // deny_list specifies list of validator addresses to whom grantee can not delegate tokens. + Validators deny_list = 3; + } + // Validators defines list of validator addresses. + message Validators { + repeated string address = 1; + } + // authorization_type defines one of AuthorizationType. + AuthorizationType authorization_type = 4; +} + +// AuthorizationType defines the type of staking module authorization type +enum AuthorizationType { + // AUTHORIZATION_TYPE_UNSPECIFIED specifies an unknown authorization type + AUTHORIZATION_TYPE_UNSPECIFIED = 0; + // AUTHORIZATION_TYPE_DELEGATE defines an authorization type for Msg/Delegate + AUTHORIZATION_TYPE_DELEGATE = 1; + // AUTHORIZATION_TYPE_UNDELEGATE defines an authorization type for Msg/Undelegate + AUTHORIZATION_TYPE_UNDELEGATE = 2; + // AUTHORIZATION_TYPE_REDELEGATE defines an authorization type for Msg/BeginRedelegate + AUTHORIZATION_TYPE_REDELEGATE = 3; +} diff --git a/x/authz/client/cli/query.go b/x/authz/client/cli/query.go index ef7f326f71e7..269a68e099f0 100644 --- a/x/authz/client/cli/query.go +++ b/x/authz/client/cli/query.go @@ -12,6 +12,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/version" "github.com/cosmos/cosmos-sdk/x/authz/types" + bank "github.com/cosmos/cosmos-sdk/x/bank/types" ) // GetQueryCmd returns the cli query commands for this module @@ -97,7 +98,7 @@ func GetCmdQueryAuthorization() *cobra.Command { 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()), +`, version.AppName, types.ModuleName, bank.SendAuthorization{}.MethodName()), ), RunE: func(cmd *cobra.Command, args []string) error { clientCtx, err := client.GetClientQueryContext(cmd) diff --git a/x/authz/client/cli/query_test.go b/x/authz/client/cli/query_test.go new file mode 100644 index 000000000000..e011d990d70b --- /dev/null +++ b/x/authz/client/cli/query_test.go @@ -0,0 +1,186 @@ +// +build norace + +package cli_test + +import ( + "fmt" + "strings" + "time" + + tmcli "github.com/tendermint/tendermint/libs/cli" + + "github.com/cosmos/cosmos-sdk/client/flags" + clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/authz/client/cli" + + authztestutil "github.com/cosmos/cosmos-sdk/x/authz/client/testutil" + "github.com/cosmos/cosmos-sdk/x/authz/types" +) + +func (s *IntegrationTestSuite) TestQueryAuthorizations() { + val := s.network.Validators[0] + + grantee := s.grantee + twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() + + _, err := authztestutil.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 := authztestutil.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.bank.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) + } + }) + } +} diff --git a/x/authz/client/cli/tx.go b/x/authz/client/cli/tx.go index 81540ef1f58b..44df6f5e9aa4 100644 --- a/x/authz/client/cli/tx.go +++ b/x/authz/client/cli/tx.go @@ -16,12 +16,20 @@ import ( "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/exported" "github.com/cosmos/cosmos-sdk/x/authz/types" + bank "github.com/cosmos/cosmos-sdk/x/bank/types" + staking "github.com/cosmos/cosmos-sdk/x/staking/types" ) const FlagSpendLimit = "spend-limit" const FlagMsgType = "msg-type" const FlagExpiration = "expiration" +const FlagAllowedValidators = "allowed-validators" +const FlagDenyValidators = "deny-validators" +const delegate = "delegate" +const redelegate = "redelegate" +const unbond = "unbond" // GetTxCmd returns the transaction commands for this module func GetTxCmd() *cobra.Command { @@ -45,7 +53,7 @@ func GetTxCmd() *cobra.Command { func NewCmdGrantAuthorization() *cobra.Command { cmd := &cobra.Command{ - Use: "grant --from ", + 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: @@ -53,20 +61,26 @@ func NewCmdGrantAuthorization() *cobra.Command { 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), + `, version.AppName, types.ModuleName, bank.SendAuthorization{}.MethodName(), version.AppName, types.ModuleName), ), - Args: cobra.RangeArgs(2, 3), + 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 } - var authorization types.Authorization + exp, err := cmd.Flags().GetInt64(FlagExpiration) + if err != nil { + return err + } + + var authorization exported.Authorization switch args[1] { case "send": limit, err := cmd.Flags().GetString(FlagSpendLimit) @@ -83,9 +97,7 @@ Examples: return fmt.Errorf("spend-limit should be greater than zero") } - authorization = &types.SendAuthorization{ - SpendLimit: spendLimit, - } + authorization = bank.NewSendAuthorization(spendLimit) case "generic": msgType, err := cmd.Flags().GetString(FlagMsgType) if err != nil { @@ -93,15 +105,61 @@ Examples: } authorization = types.NewGenericAuthorization(msgType) + case delegate, unbond, redelegate: + limit, err := cmd.Flags().GetString(FlagSpendLimit) + if err != nil { + return err + } + + allowValidators, err := cmd.Flags().GetStringSlice(FlagAllowedValidators) + if err != nil { + return err + } + + denyValidators, err := cmd.Flags().GetStringSlice(FlagDenyValidators) + if err != nil { + return err + } + + var delegateLimit *sdk.Coin + if limit != "" { + spendLimit, err := sdk.ParseCoinsNormalized(limit) + if err != nil { + return err + } + + if !spendLimit.IsAllPositive() { + return fmt.Errorf("spend-limit should be greater than zero") + } + delegateLimit = &spendLimit[0] + } + + allowed, err := bech32toValidatorAddresses(allowValidators) + if err != nil { + return err + } + + denied, err := bech32toValidatorAddresses(denyValidators) + if err != nil { + return err + } + + switch args[1] { + case delegate: + authorization, err = staking.NewStakeAuthorization(allowed, denied, staking.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, delegateLimit) + case unbond: + authorization, err = staking.NewStakeAuthorization(allowed, denied, staking.AuthorizationType_AUTHORIZATION_TYPE_UNDELEGATE, delegateLimit) + default: + authorization, err = staking.NewStakeAuthorization(allowed, denied, staking.AuthorizationType_AUTHORIZATION_TYPE_REDELEGATE, delegateLimit) + } + if err != nil { + return err + } + 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 @@ -120,6 +178,8 @@ Examples: 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().StringSlice(FlagAllowedValidators, []string{}, "Allowed validators addresses separated by ,") + cmd.Flags().StringSlice(FlagDenyValidators, []string{}, "Deny validators addresses separated by ,") cmd.Flags().Int64(FlagExpiration, time.Now().AddDate(1, 0, 0).Unix(), "The Unix timestamp. Default is one year.") return cmd } @@ -132,7 +192,7 @@ func NewCmdRevokeAuthorization() *cobra.Command { 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()), + `, version.AppName, types.ModuleName, bank.SendAuthorization{}.MethodName()), ), Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) error { @@ -220,3 +280,15 @@ Example: return cmd } + +func bech32toValidatorAddresses(validators []string) ([]sdk.ValAddress, error) { + vals := make([]sdk.ValAddress, len(validators)) + for i, validator := range validators { + addr, err := sdk.ValAddressFromBech32(validator) + if err != nil { + return nil, err + } + vals[i] = addr + } + return vals, nil +} diff --git a/x/authz/client/cli/cli_test.go b/x/authz/client/cli/tx_test.go similarity index 52% rename from x/authz/client/cli/cli_test.go rename to x/authz/client/cli/tx_test.go index 4ad3d93f3d1e..7964a93c1a28 100644 --- a/x/authz/client/cli/cli_test.go +++ b/x/authz/client/cli/tx_test.go @@ -1,10 +1,7 @@ -// +build norace - package cli_test import ( "fmt" - "strings" "testing" "time" @@ -12,8 +9,6 @@ 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" @@ -26,10 +21,12 @@ import ( 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" + stakingcli "github.com/cosmos/cosmos-sdk/x/staking/client/cli" - "github.com/cosmos/cosmos-sdk/x/authz/types" + authztestutil "github.com/cosmos/cosmos-sdk/x/authz/client/testutil" bankcli "github.com/cosmos/cosmos-sdk/x/bank/client/testutil" banktestutil "github.com/cosmos/cosmos-sdk/x/bank/client/testutil" + bank "github.com/cosmos/cosmos-sdk/x/bank/types" ) type IntegrationTestSuite struct { @@ -68,6 +65,9 @@ func (s *IntegrationTestSuite) SetupSuite() { s.Require().NoError(err) s.grantee = newAddr + _, err = s.network.WaitForHeight(1) + s.Require().NoError(err) + // create a proposal with deposit _, err = govtestutil.MsgSubmitProposal(val.ClientCtx, val.Address.String(), "Text Proposal 1", "Where is the title!?", govtypes.ProposalTypeText, @@ -83,175 +83,10 @@ func (s *IntegrationTestSuite) TearDownSuite() { s.network.Cleanup() } -var typeMsgSend = types.SendAuthorization{}.MethodName() +var typeMsgSend = bank.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) - } - }) - } -} +var commonFlags = []string{} func (s *IntegrationTestSuite) TestCLITxGrantAuthorization() { val := s.network.Validators[0] @@ -315,13 +150,94 @@ func (s *IntegrationTestSuite) TestCLITxGrantAuthorization() { 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()), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), }, &sdk.TxResponse{}, 29, false, }, + { + "failed with error both validators not allowed", + []string{ + grantee.String(), + "delegate", + fmt.Sprintf("--%s=100stake", cli.FlagSpendLimit), + 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", cli.FlagAllowedValidators, fmt.Sprintf("%s", val.ValAddress.String())), + fmt.Sprintf("--%s=%s", cli.FlagDenyValidators, fmt.Sprintf("%s", val.ValAddress.String())), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + nil, 0, + true, + }, + { + "valid tx delegate authorization allowed validators", + []string{ + grantee.String(), + "delegate", + fmt.Sprintf("--%s=100stake", cli.FlagSpendLimit), + 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", cli.FlagAllowedValidators, fmt.Sprintf("%s", val.ValAddress.String())), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + &sdk.TxResponse{}, 0, + false, + }, + { + "valid tx delegate authorization deny validators", + []string{ + grantee.String(), + "delegate", + fmt.Sprintf("--%s=100stake", cli.FlagSpendLimit), + 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", cli.FlagDenyValidators, fmt.Sprintf("%s", val.ValAddress.String())), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + &sdk.TxResponse{}, 0, + false, + }, + { + "valid tx undelegate authorization", + []string{ + grantee.String(), + "unbond", + fmt.Sprintf("--%s=100stake", cli.FlagSpendLimit), + 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", cli.FlagAllowedValidators, fmt.Sprintf("%s", val.ValAddress.String())), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + &sdk.TxResponse{}, 0, + false, + }, + { + "valid tx redelegate authorization", + []string{ + grantee.String(), + "redelegate", + fmt.Sprintf("--%s=100stake", cli.FlagSpendLimit), + 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", cli.FlagAllowedValidators, fmt.Sprintf("%s", val.ValAddress.String())), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + &sdk.TxResponse{}, 0, + false, + }, { "Valid tx send authorization", []string{ @@ -358,7 +274,7 @@ func (s *IntegrationTestSuite) TestCLITxGrantAuthorization() { tc := tc s.Run(tc.name, func() { clientCtx := val.ClientCtx - out, err := execGrantAuthorization( + out, err := authztestutil.ExecGrantAuthorization( val, tc.args, ) @@ -374,8 +290,8 @@ func (s *IntegrationTestSuite) TestCLITxGrantAuthorization() { } } -func execGrantAuthorization(val *network.Validator, args []string) (testutil.BufferWriter, error) { - cmd := cli.NewCmdGrantAuthorization() +func execDelegate(val *network.Validator, args []string) (testutil.BufferWriter, error) { + cmd := stakingcli.NewDelegateCmd() clientCtx := val.ClientCtx return clitestutil.ExecTestCLICmd(clientCtx, cmd, args) } @@ -387,7 +303,7 @@ func (s *IntegrationTestSuite) TestCmdRevokeAuthorizations() { twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() // send-authorization - _, err := execGrantAuthorization( + _, err := authztestutil.ExecGrantAuthorization( val, []string{ grantee.String(), @@ -403,7 +319,7 @@ func (s *IntegrationTestSuite) TestCmdRevokeAuthorizations() { s.Require().NoError(err) // generic-authorization - _, err = execGrantAuthorization( + _, err = authztestutil.ExecGrantAuthorization( val, []string{ grantee.String(), @@ -501,7 +417,7 @@ func (s *IntegrationTestSuite) TestExecAuthorizationWithExpiration() { grantee := s.grantee tenSeconds := time.Now().Add(time.Second * time.Duration(10)).Unix() - _, err := execGrantAuthorization( + _, err := authztestutil.ExecGrantAuthorization( val, []string{ grantee.String(), @@ -541,7 +457,7 @@ func (s *IntegrationTestSuite) TestNewExecGenericAuthorized() { grantee := s.grantee twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() - _, err := execGrantAuthorization( + _, err := authztestutil.ExecGrantAuthorization( val, []string{ grantee.String(), @@ -630,7 +546,7 @@ func (s *IntegrationTestSuite) TestNewExecGrantAuthorized() { grantee := s.grantee twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() - _, err := execGrantAuthorization( + _, err := authztestutil.ExecGrantAuthorization( val, []string{ grantee.String(), @@ -662,32 +578,192 @@ func (s *IntegrationTestSuite) TestNewExecGrantAuthorized() { testCases := []struct { name string args []string - respType proto.Message expectedCode uint32 expectErr bool }{ { - "fail invalid grantee", + "valid txn", []string{ execMsg.Name(), - fmt.Sprintf("--%s=%s", flags.FlagFrom, "grantee"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee.String()), fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), }, - nil, 0, - true, + false, }, { - "fail invalid json path", + "error over spent", []string{ - "/invalid/file.txt", + 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), + }, + 4, + 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 { + var response sdk.TxResponse + s.Require().NoError(err) + s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), &response), out.String()) + s.Require().Equal(tc.expectedCode, response.Code, out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestExecDelegateAuthorization() { + val := s.network.Validators[0] + grantee := s.grantee + twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() + + _, err := authztestutil.ExecGrantAuthorization( + val, + []string{ + grantee.String(), + "delegate", + fmt.Sprintf("--%s=100stake", cli.FlagSpendLimit), + 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", cli.FlagAllowedValidators, fmt.Sprintf("%s", val.ValAddress.String())), + 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("stake", sdk.NewInt(50)), + ) + + delegateTx := fmt.Sprintf(`{"body":{"messages":[{"@type":"/cosmos.staking.v1beta1.Msg/Delegate","delegator_address":"%s","validator_address":"%s","amount":{"denom":"%s","amount":"%s"}}],"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(), val.ValAddress.String(), + tokens.GetDenomByIndex(0), tokens[0].Amount) + execMsg := testutil.WriteToNewTempFile(s.T(), delegateTx) + + testCases := []struct { + name string + args []string + expectedCode uint32 + expectErr bool + errMsg string + }{ + { + "valid txn: (delegate half tokens)", + []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), }, - nil, 0, - true, + false, + "", + }, + { + "valid txn: (delegate remaining half tokens)", + []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), + }, + 0, + false, + "", + }, + { + "failed with error no authorization found", + []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), + }, + 4, + false, + "authorization not found", + }, + } + + 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) + s.Require().Contains(err.Error(), tc.errMsg) + } else { + var response sdk.TxResponse + s.Require().NoError(err) + s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), &response), out.String()) + s.Require().Equal(tc.expectedCode, response.Code, out.String()) + } + }) + } + + //test delegate no spend-limit + _, err = authztestutil.ExecGrantAuthorization( + val, + []string{ + grantee.String(), + "delegate", + 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", cli.FlagAllowedValidators, fmt.Sprintf("%s", val.ValAddress.String())), + 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("stake", sdk.NewInt(50)), + ) + + delegateTx = fmt.Sprintf(`{"body":{"messages":[{"@type":"/cosmos.staking.v1beta1.Msg/Delegate","delegator_address":"%s","validator_address":"%s","amount":{"denom":"%s","amount":"%s"}}],"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(), val.ValAddress.String(), + tokens.GetDenomByIndex(0), tokens[0].Amount) + execMsg = testutil.WriteToNewTempFile(s.T(), delegateTx) + + testCases = []struct { + name string + args []string + expectedCode uint32 + expectErr bool + errMsg string + }{ + { + "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), + }, + 0, + false, + "", }, { "valid txn", @@ -698,9 +774,9 @@ func (s *IntegrationTestSuite) TestNewExecGrantAuthorized() { 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, + "", }, } @@ -713,11 +789,231 @@ func (s *IntegrationTestSuite) TestNewExecGrantAuthorized() { out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) if tc.expectErr { s.Require().Error(err) + s.Require().Contains(err.Error(), tc.errMsg) } else { + var response sdk.TxResponse 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()) + s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), &response), out.String()) + s.Require().Equal(tc.expectedCode, response.Code, out.String()) + } + }) + } + + // test delegating to denied validator + _, err = authztestutil.ExecGrantAuthorization( + val, + []string{ + grantee.String(), + "delegate", + fmt.Sprintf("--%s=100stake", cli.FlagSpendLimit), + 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", cli.FlagDenyValidators, fmt.Sprintf("%s", val.ValAddress.String())), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + ) + s.Require().NoError(err) + + args := []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), + } + cmd := cli.NewCmdExecAuthorization() + out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cmd, args) + s.Require().NoError(err) + s.Contains(out.String(), fmt.Sprintf("cannot delegate/undelegate to %s validator", val.ValAddress.String())) + +} + +func (s *IntegrationTestSuite) TestExecUndelegateAuthorization() { + val := s.network.Validators[0] + grantee := s.grantee + twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() + + // granting undelegate msg authorization + _, err := authztestutil.ExecGrantAuthorization( + val, + []string{ + grantee.String(), + "unbond", + fmt.Sprintf("--%s=100stake", cli.FlagSpendLimit), + 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", cli.FlagAllowedValidators, fmt.Sprintf("%s", val.ValAddress.String())), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + ) + s.Require().NoError(err) + + // delegating stakes to validator + _, err = execDelegate( + val, + []string{ + val.ValAddress.String(), + "100stake", + 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=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + ) + s.Require().NoError(err) + + tokens := sdk.NewCoins( + sdk.NewCoin("stake", sdk.NewInt(50)), + ) + + undelegateTx := fmt.Sprintf(`{"body":{"messages":[{"@type":"/cosmos.staking.v1beta1.Msg/Undelegate","delegator_address":"%s","validator_address":"%s","amount":{"denom":"%s","amount":"%s"}}],"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(), val.ValAddress.String(), + tokens.GetDenomByIndex(0), tokens[0].Amount) + execMsg := testutil.WriteToNewTempFile(s.T(), undelegateTx) + + testCases := []struct { + name string + args []string + expectedCode uint32 + expectErr bool + errMsg string + }{ + { + "valid txn: (undelegate half tokens)", + []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), + }, + 0, + false, + "", + }, + { + "valid txn: (undelegate remaining half tokens)", + []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), + }, + 0, + false, + "", + }, + { + "failed with error no authorization found", + []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), + }, + 4, + false, + "authorization not found", + }, + } + + 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) + s.Require().Contains(err.Error(), tc.errMsg) + } else { + var response sdk.TxResponse + s.Require().NoError(err) + s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), &response), out.String()) + s.Require().Equal(tc.expectedCode, response.Code, out.String()) + } + }) + } + + // grant undelegate authorization without limit + _, err = authztestutil.ExecGrantAuthorization( + val, + []string{ + grantee.String(), + "unbond", + 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", cli.FlagAllowedValidators, fmt.Sprintf("%s", val.ValAddress.String())), + 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("stake", sdk.NewInt(50)), + ) + + undelegateTx = fmt.Sprintf(`{"body":{"messages":[{"@type":"/cosmos.staking.v1beta1.Msg/Undelegate","delegator_address":"%s","validator_address":"%s","amount":{"denom":"%s","amount":"%s"}}],"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(), val.ValAddress.String(), + tokens.GetDenomByIndex(0), tokens[0].Amount) + execMsg = testutil.WriteToNewTempFile(s.T(), undelegateTx) + + testCases = []struct { + name string + args []string + expectedCode uint32 + expectErr bool + errMsg string + }{ + { + "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), + }, + 0, + false, + "", + }, + { + "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), + }, + 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) + s.Require().Contains(err.Error(), tc.errMsg) + } else { + var response sdk.TxResponse + s.Require().NoError(err) + s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), &response), out.String()) + s.Require().Equal(tc.expectedCode, response.Code, out.String()) } }) } diff --git a/x/authz/client/rest/grpc_query_test.go b/x/authz/client/rest/grpc_query_test.go index 8ed8e857c6af..e12336b49ed1 100644 --- a/x/authz/client/rest/grpc_query_test.go +++ b/x/authz/client/rest/grpc_query_test.go @@ -1,10 +1,9 @@ -// +build norace - package rest_test import ( "fmt" "testing" + "time" "github.com/stretchr/testify/suite" @@ -14,9 +13,11 @@ 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/authz/client/cli" 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" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) type IntegrationTestSuite struct { @@ -26,7 +27,8 @@ type IntegrationTestSuite struct { grantee sdk.AccAddress } -var typeMsgSend = types.SendAuthorization{}.MethodName() +var typeMsgSend = banktypes.SendAuthorization{}.MethodName() +var typeMsgVote = "/cosmos.gov.v1beta1.Msg/Vote" func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") @@ -55,7 +57,16 @@ func (s *IntegrationTestSuite) SetupSuite() { s.Require().NoError(err) // grant authorization - _, err = authztestutil.MsgGrantAuthorizationExec(val.ClientCtx, val.Address.String(), newAddr.String(), typeMsgSend, "100stake") + _, err = authztestutil.ExecGrantAuthorization(val, []string{ + newAddr.String(), + "send", + fmt.Sprintf("--%s=100steak", cli.FlagSpendLimit), + 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(sdk.DefaultBondDenom, sdk.NewInt(10))).String()), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, time.Now().Add(time.Minute*time.Duration(120)).Unix()), + }) s.Require().NoError(err) s.grantee = newAddr @@ -79,37 +90,37 @@ func (s *IntegrationTestSuite) TestQueryAuthorizationGRPC() { }{ { "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), + fmt.Sprintf("%s/cosmos/authz/v1beta1/granters/%s/grantees/%s/grant?method_name=%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), + fmt.Sprintf("%s/cosmos/authz/v1beta1/granters/%s/grantees/%s/grant?method_name=%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), + fmt.Sprintf("%s/cosmos/authz/v1beta1/granters/%s/grantees/%s/grant?method_name=%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), + fmt.Sprintf("%s/cosmos/authz/v1beta1/granters/%s/grantees/%s/grant?method_name=%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"), + fmt.Sprintf("%s/cosmos/authz/v1beta1/granters/%s/grantees/%s/grant?method_name=%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), + fmt.Sprintf("%s/cosmos/authz/v1beta1/granters/%s/grantees/%s/grant?method_name=%s", baseURL, val.Address.String(), s.grantee.String(), typeMsgSend), false, "", }, @@ -126,7 +137,7 @@ func (s *IntegrationTestSuite) TestQueryAuthorizationGRPC() { s.Require().NoError(err) authorization.Authorization.UnpackInterfaces(val.ClientCtx.InterfaceRegistry) auth := authorization.Authorization.GetAuthorizationGrant() - s.Require().Equal(auth.MethodName(), types.SendAuthorization{}.MethodName()) + s.Require().Equal(auth.MethodName(), banktypes.SendAuthorization{}.MethodName()) } }) } @@ -184,7 +195,16 @@ func (s *IntegrationTestSuite) TestQueryAuthorizationsGRPC() { false, "", func() { - _, err := authztestutil.MsgGrantAuthorizationExec(val.ClientCtx, val.Address.String(), s.grantee.String(), "/cosmos.gov.v1beta1.Msg/Vote", "") + _, err := authztestutil.ExecGrantAuthorization(val, []string{ + s.grantee.String(), + "generic", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=%s", cli.FlagMsgType, typeMsgVote), + 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()), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, time.Now().Add(time.Minute*time.Duration(120)).Unix()), + }) s.Require().NoError(err) }, func(authorizations *types.QueryAuthorizationsResponse) { diff --git a/x/authz/client/testutil/test_helpers.go b/x/authz/client/testutil/test_helpers.go index a56429a4d96a..e1b728389902 100644 --- a/x/authz/client/testutil/test_helpers.go +++ b/x/authz/client/testutil/test_helpers.go @@ -1,34 +1,14 @@ 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" + "github.com/cosmos/cosmos-sdk/testutil/network" + "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) +func ExecGrantAuthorization(val *network.Validator, args []string) (testutil.BufferWriter, error) { + cmd := cli.NewCmdGrantAuthorization() + clientCtx := val.ClientCtx + return clitestutil.ExecTestCLICmd(clientCtx, cmd, args) } diff --git a/x/authz/exported/authorizations.go b/x/authz/exported/authorizations.go new file mode 100644 index 000000000000..d7cca5ae79d0 --- /dev/null +++ b/x/authz/exported/authorizations.go @@ -0,0 +1,21 @@ +package exported + +import ( + "github.com/gogo/protobuf/proto" + + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// Authorization represents the interface of various Authorization types. +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) (updated Authorization, delete bool, err error) +} diff --git a/x/authz/exported/keeper.go b/x/authz/exported/keeper.go index 9858ba821729..0efffca81c08 100644 --- a/x/authz/exported/keeper.go +++ b/x/authz/exported/keeper.go @@ -3,8 +3,6 @@ package exported import ( "time" - "github.com/cosmos/cosmos-sdk/x/authz/types" - sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -14,7 +12,7 @@ type Keeper interface { // 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 + Grant(ctx sdk.Context, grantee sdk.AccAddress, granter sdk.AccAddress, authorization 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) @@ -22,5 +20,5 @@ type Keeper interface { // 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) + GetOrRevokeAuthorization(ctx sdk.Context, grantee sdk.AccAddress, granter sdk.AccAddress, msgType string) (cap Authorization, expiration time.Time) } diff --git a/x/authz/genesis.go b/x/authz/genesis.go index e84ddf5987a0..8cce4973b9b4 100644 --- a/x/authz/genesis.go +++ b/x/authz/genesis.go @@ -2,6 +2,7 @@ package authz import ( sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/authz/exported" "github.com/cosmos/cosmos-sdk/x/authz/keeper" "github.com/cosmos/cosmos-sdk/x/authz/types" ) @@ -17,7 +18,7 @@ func InitGenesis(ctx sdk.Context, keeper keeper.Keeper, data *types.GenesisState if err != nil { panic(err) } - authorization, ok := entry.Authorization.GetCachedValue().(types.Authorization) + authorization, ok := entry.Authorization.GetCachedValue().(exported.Authorization) if !ok { panic("expected authorization") } diff --git a/x/authz/genesis_test.go b/x/authz/genesis_test.go index 2d770d4c5210..5e623a60604b 100644 --- a/x/authz/genesis_test.go +++ b/x/authz/genesis_test.go @@ -12,7 +12,7 @@ import ( 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" + bank "github.com/cosmos/cosmos-sdk/x/bank/types" ) type GenesisTestSuite struct { @@ -41,7 +41,7 @@ func (suite *GenesisTestSuite) TestImportExportGenesis() { coins := sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(1_000))) now := suite.ctx.BlockHeader().Time - grant := &types.SendAuthorization{SpendLimit: coins} + grant := &bank.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) diff --git a/x/authz/keeper/grpc_query_test.go b/x/authz/keeper/grpc_query_test.go index cc301fbca140..568cdd4afea0 100644 --- a/x/authz/keeper/grpc_query_test.go +++ b/x/authz/keeper/grpc_query_test.go @@ -6,14 +6,16 @@ import ( "time" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/authz/exported" "github.com/cosmos/cosmos-sdk/x/authz/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) func (suite *TestSuite) TestGRPCQueryAuthorization() { app, ctx, queryClient, addrs := suite.app, suite.ctx, suite.queryClient, suite.addrs var ( req *types.QueryAuthorizationRequest - expAuthorization types.Authorization + expAuthorization exported.Authorization ) testCases := []struct { msg string @@ -55,7 +57,7 @@ func (suite *TestSuite) TestGRPCQueryAuthorization() { func() { now := ctx.BlockHeader().Time newCoins := sdk.NewCoins(sdk.NewInt64Coin("steak", 100)) - expAuthorization = &types.SendAuthorization{SpendLimit: newCoins} + expAuthorization = &banktypes.SendAuthorization{SpendLimit: newCoins} err := app.AuthzKeeper.Grant(ctx, addrs[0], addrs[1], expAuthorization, now.Add(time.Hour)) suite.Require().NoError(err) req = &types.QueryAuthorizationRequest{ @@ -66,7 +68,7 @@ func (suite *TestSuite) TestGRPCQueryAuthorization() { }, true, func(res *types.QueryAuthorizationResponse) { - var auth types.Authorization + var auth exported.Authorization err := suite.app.InterfaceRegistry().UnpackAny(res.Authorization.Authorization, &auth) suite.Require().NoError(err) suite.Require().NotNil(auth) @@ -92,7 +94,7 @@ func (suite *TestSuite) TestGRPCQueryAuthorizations() { app, ctx, queryClient, addrs := suite.app, suite.ctx, suite.queryClient, suite.addrs var ( req *types.QueryAuthorizationsRequest - expAuthorization types.Authorization + expAuthorization exported.Authorization ) testCases := []struct { msg string @@ -123,7 +125,7 @@ func (suite *TestSuite) TestGRPCQueryAuthorizations() { func() { now := ctx.BlockHeader().Time newCoins := sdk.NewCoins(sdk.NewInt64Coin("steak", 100)) - expAuthorization = &types.SendAuthorization{SpendLimit: newCoins} + expAuthorization = &banktypes.SendAuthorization{SpendLimit: newCoins} err := app.AuthzKeeper.Grant(ctx, addrs[0], addrs[1], expAuthorization, now.Add(time.Hour)) suite.Require().NoError(err) req = &types.QueryAuthorizationsRequest{ @@ -133,7 +135,7 @@ func (suite *TestSuite) TestGRPCQueryAuthorizations() { }, true, func(res *types.QueryAuthorizationsResponse) { - var auth types.Authorization + var auth exported.Authorization suite.Require().Equal(1, len(res.Authorizations)) err := suite.app.InterfaceRegistry().UnpackAny(res.Authorizations[0].Authorization, &auth) suite.Require().NoError(err) diff --git a/x/authz/keeper/keeper.go b/x/authz/keeper/keeper.go index 2888e17449b9..33d6248f7123 100644 --- a/x/authz/keeper/keeper.go +++ b/x/authz/keeper/keeper.go @@ -13,6 +13,7 @@ import ( 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/exported" "github.com/cosmos/cosmos-sdk/x/authz/types" ) @@ -47,7 +48,7 @@ func (k Keeper) getAuthorizationGrant(ctx sdk.Context, grantStoreKey []byte) (gr return grant, true } -func (k Keeper) update(ctx sdk.Context, grantee sdk.AccAddress, granter sdk.AccAddress, updated types.Authorization) error { +func (k Keeper) update(ctx sdk.Context, grantee sdk.AccAddress, granter sdk.AccAddress, updated exported.Authorization) error { grantStoreKey := types.GetAuthorizationStoreKey(grantee, granter, updated.MethodName()) grant, found := k.getAuthorizationGrant(ctx, grantStoreKey) if !found { @@ -86,9 +87,9 @@ func (k Keeper) DispatchActions(ctx sdk.Context, grantee sdk.AccAddress, service 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") + updated, del, err := authorization.Accept(serviceMsg, ctx.BlockHeader()) + if err != nil { + return nil, err } if del { k.Revoke(ctx, grantee, granter, serviceMsg.Type()) @@ -117,7 +118,7 @@ func (k Keeper) DispatchActions(ctx sdk.Context, grantee sdk.AccAddress, service // 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 { +func (k Keeper) Grant(ctx sdk.Context, grantee, granter sdk.AccAddress, authorization exported.Authorization, expiration time.Time) error { store := ctx.KVStore(k.storeKey) grant, err := types.NewAuthorizationGrant(authorization, expiration) @@ -164,7 +165,7 @@ func (k Keeper) Revoke(ctx sdk.Context, grantee sdk.AccAddress, granter sdk.AccA } // 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) { +func (k Keeper) GetAuthorizations(ctx sdk.Context, grantee sdk.AccAddress, granter sdk.AccAddress) (authorizations []exported.Authorization) { store := ctx.KVStore(k.storeKey) key := types.GetAuthorizationStoreKey(grantee, granter, "") iter := sdk.KVStorePrefixIterator(store, key) @@ -180,7 +181,7 @@ func (k Keeper) GetAuthorizations(ctx sdk.Context, grantee sdk.AccAddress, grant // 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) { +func (k Keeper) GetOrRevokeAuthorization(ctx sdk.Context, grantee sdk.AccAddress, granter sdk.AccAddress, msgType string) (cap exported.Authorization, expiration time.Time) { grant, found := k.getAuthorizationGrant(ctx, types.GetAuthorizationStoreKey(grantee, granter, msgType)) if !found { return nil, time.Time{} diff --git a/x/authz/keeper/keeper_test.go b/x/authz/keeper/keeper_test.go index 3d53ac8ce4da..161fed6e98bd 100644 --- a/x/authz/keeper/keeper_test.go +++ b/x/authz/keeper/keeper_test.go @@ -53,7 +53,7 @@ func (s *TestSuite) TestKeeper() { recipientAddr := addrs[2] s.T().Log("verify that no authorization returns nil") - authorization, expiration := app.AuthzKeeper.GetOrRevokeAuthorization(ctx, granteeAddr, granterAddr, types.SendAuthorization{}.MethodName()) + authorization, expiration := app.AuthzKeeper.GetOrRevokeAuthorization(ctx, granteeAddr, granterAddr, banktypes.SendAuthorization{}.MethodName()) s.Require().Nil(authorization) s.Require().Equal(expiration, time.Time{}) now := s.ctx.BlockHeader().Time @@ -61,38 +61,38 @@ 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} + x := &banktypes.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()) + authorization, _ = app.AuthzKeeper.GetOrRevokeAuthorization(ctx, granteeAddr, granterAddr, banktypes.SendAuthorization{}.MethodName()) s.Require().Nil(authorization) s.T().Log("verify if authorization is accepted") - x = &types.SendAuthorization{SpendLimit: newCoins} + x = &banktypes.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()) + authorization, _ = app.AuthzKeeper.GetOrRevokeAuthorization(ctx, granteeAddr, granterAddr, banktypes.SendAuthorization{}.MethodName()) s.Require().NotNil(authorization) - s.Require().Equal(authorization.MethodName(), types.SendAuthorization{}.MethodName()) + s.Require().Equal(authorization.MethodName(), banktypes.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()) + authorization, _ = app.AuthzKeeper.GetOrRevokeAuthorization(ctx, recipientAddr, granterAddr, banktypes.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()) + err = app.AuthzKeeper.Revoke(ctx, recipientAddr, granterAddr, banktypes.SendAuthorization{}.MethodName()) s.Require().Error(err) - authorization, _ = app.AuthzKeeper.GetOrRevokeAuthorization(ctx, recipientAddr, granterAddr, types.SendAuthorization{}.MethodName()) + authorization, _ = app.AuthzKeeper.GetOrRevokeAuthorization(ctx, recipientAddr, granterAddr, banktypes.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()) + err = app.AuthzKeeper.Revoke(ctx, granteeAddr, granterAddr, banktypes.SendAuthorization{}.MethodName()) s.Require().NoError(err) - authorization, _ = app.AuthzKeeper.GetOrRevokeAuthorization(ctx, granteeAddr, granterAddr, types.SendAuthorization{}.MethodName()) + authorization, _ = app.AuthzKeeper.GetOrRevokeAuthorization(ctx, granteeAddr, granterAddr, banktypes.SendAuthorization{}.MethodName()) s.Require().Nil(authorization) } @@ -112,7 +112,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} + x := &banktypes.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") @@ -141,7 +141,7 @@ func (s *TestSuite) TestKeeperFees() { msgs := types.NewMsgExecAuthorized(granteeAddr, []sdk.ServiceMsg{ { - MethodName: types.SendAuthorization{}.MethodName(), + MethodName: banktypes.SendAuthorization{}.MethodName(), Request: &banktypes.MsgSend{ Amount: sdk.NewCoins(sdk.NewInt64Coin("steak", 2)), FromAddress: granterAddr.String(), @@ -162,12 +162,12 @@ func (s *TestSuite) TestKeeperFees() { s.T().Log("verify dispatch executes with correct information") // grant authorization - err = app.AuthzKeeper.Grant(s.ctx, granteeAddr, granterAddr, &types.SendAuthorization{SpendLimit: smallCoin}, now) + err = app.AuthzKeeper.Grant(s.ctx, granteeAddr, granterAddr, &banktypes.SendAuthorization{SpendLimit: smallCoin}, now) s.Require().NoError(err) - authorization, _ := app.AuthzKeeper.GetOrRevokeAuthorization(s.ctx, granteeAddr, granterAddr, types.SendAuthorization{}.MethodName()) + authorization, _ := app.AuthzKeeper.GetOrRevokeAuthorization(s.ctx, granteeAddr, granterAddr, banktypes.SendAuthorization{}.MethodName()) s.Require().NotNil(authorization) - s.Require().Equal(authorization.MethodName(), types.SendAuthorization{}.MethodName()) + s.Require().Equal(authorization.MethodName(), banktypes.SendAuthorization{}.MethodName()) executeMsgs, err = msgs.GetServiceMsgs() s.Require().NoError(err) @@ -176,7 +176,7 @@ func (s *TestSuite) TestKeeperFees() { s.Require().NoError(err) s.Require().NotNil(result) - authorization, _ = app.AuthzKeeper.GetOrRevokeAuthorization(s.ctx, granteeAddr, granterAddr, types.SendAuthorization{}.MethodName()) + authorization, _ = app.AuthzKeeper.GetOrRevokeAuthorization(s.ctx, granteeAddr, granterAddr, banktypes.SendAuthorization{}.MethodName()) s.Require().NotNil(authorization) s.T().Log("verify dispatch fails with overlimit") @@ -184,7 +184,7 @@ func (s *TestSuite) TestKeeperFees() { msgs = types.NewMsgExecAuthorized(granteeAddr, []sdk.ServiceMsg{ { - MethodName: types.SendAuthorization{}.MethodName(), + MethodName: banktypes.SendAuthorization{}.MethodName(), Request: &banktypes.MsgSend{ Amount: someCoin, FromAddress: granterAddr.String(), @@ -201,7 +201,7 @@ func (s *TestSuite) TestKeeperFees() { s.Require().Nil(result) s.Require().NotNil(err) - authorization, _ = app.AuthzKeeper.GetOrRevokeAuthorization(s.ctx, granteeAddr, granterAddr, types.SendAuthorization{}.MethodName()) + authorization, _ = app.AuthzKeeper.GetOrRevokeAuthorization(s.ctx, granteeAddr, granterAddr, banktypes.SendAuthorization{}.MethodName()) s.Require().NotNil(authorization) } diff --git a/x/authz/simulation/decoder_test.go b/x/authz/simulation/decoder_test.go index 86c2dfd6abb4..8b5e71cfbdd7 100644 --- a/x/authz/simulation/decoder_test.go +++ b/x/authz/simulation/decoder_test.go @@ -12,13 +12,14 @@ import ( "github.com/cosmos/cosmos-sdk/types/kv" "github.com/cosmos/cosmos-sdk/x/authz/simulation" "github.com/cosmos/cosmos-sdk/x/authz/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/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()) + grant, _ := types.NewAuthorizationGrant(banktypes.NewSendAuthorization(sdk.NewCoins(sdk.NewInt64Coin("foo", 123))), time.Now().UTC()) grantBz, err := cdc.MarshalBinaryBare(&grant) require.NoError(t, err) kvPairs := kv.Pairs{ diff --git a/x/authz/simulation/operations.go b/x/authz/simulation/operations.go index 5533d9fa6916..959b0c06fe65 100644 --- a/x/authz/simulation/operations.go +++ b/x/authz/simulation/operations.go @@ -97,7 +97,7 @@ func SimulateMsgGrantAuthorization(ak types.AccountKeeper, bk types.BankKeeper, blockTime := ctx.BlockTime() msg, err := types.NewMsgGrantAuthorization(granter.Address, grantee.Address, - types.NewSendAuthorization(spendableCoins.Sub(fees)), blockTime.AddDate(1, 0, 0)) + banktype.NewSendAuthorization(spendableCoins.Sub(fees)), blockTime.AddDate(1, 0, 0)) if err != nil { return simtypes.NoOpMsg(types.ModuleName, TypeMsgGrantAuthorization, err.Error()), nil, err @@ -239,7 +239,7 @@ func SimulateMsgExecuteAuthorized(ak types.AccountKeeper, bk types.BankKeeper, k sendCoins := sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(10))) execMsg := sdk.ServiceMsg{ - MethodName: types.SendAuthorization{}.MethodName(), + MethodName: banktype.SendAuthorization{}.MethodName(), Request: banktype.NewMsgSend( granterAddr, granteeAddr, @@ -248,10 +248,10 @@ func SimulateMsgExecuteAuthorized(ak types.AccountKeeper, bk types.BankKeeper, k } 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 + sendGrant := targetGrant.Authorization.GetCachedValue().(*banktype.SendAuthorization) + _, _, err = sendGrant.Accept(execMsg, ctx.BlockHeader()) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgExecDelegated, err.Error()), nil, nil } txGen := simappparams.MakeTestEncodingConfig().TxConfig diff --git a/x/authz/simulation/operations_test.go b/x/authz/simulation/operations_test.go index b3b447dcdb09..3dc3dd08ddbc 100644 --- a/x/authz/simulation/operations_test.go +++ b/x/authz/simulation/operations_test.go @@ -17,6 +17,7 @@ import ( simtypes "github.com/cosmos/cosmos-sdk/types/simulation" "github.com/cosmos/cosmos-sdk/x/authz/simulation" "github.com/cosmos/cosmos-sdk/x/authz/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) type SimTestSuite struct { @@ -136,7 +137,7 @@ func (suite *SimTestSuite) TestSimulateRevokeAuthorization() { granter := accounts[0] grantee := accounts[1] - authorization := types.NewSendAuthorization(initCoins) + authorization := banktypes.NewSendAuthorization(initCoins) err := suite.app.AuthzKeeper.Grant(suite.ctx, grantee.Address, granter.Address, authorization, time.Now().Add(30*time.Hour)) suite.Require().NoError(err) @@ -152,7 +153,7 @@ func (suite *SimTestSuite) TestSimulateRevokeAuthorization() { 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().Equal(banktypes.SendAuthorization{}.MethodName(), msg.MethodName) suite.Require().Len(futureOperations, 0) } @@ -171,7 +172,7 @@ func (suite *SimTestSuite) TestSimulateExecAuthorization() { granter := accounts[0] grantee := accounts[1] - authorization := types.NewSendAuthorization(initCoins) + authorization := banktypes.NewSendAuthorization(initCoins) err := suite.app.AuthzKeeper.Grant(suite.ctx, grantee.Address, granter.Address, authorization, time.Now().Add(30*time.Hour)) suite.Require().NoError(err) diff --git a/x/authz/types/authorizations.go b/x/authz/types/authorization_grant.go similarity index 54% rename from x/authz/types/authorizations.go rename to x/authz/types/authorization_grant.go index 18533fe07201..c94e9d6d730a 100644 --- a/x/authz/types/authorizations.go +++ b/x/authz/types/authorization_grant.go @@ -3,28 +3,14 @@ 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" + "github.com/cosmos/cosmos-sdk/x/authz/exported" + proto "github.com/gogo/protobuf/proto" ) -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) { +func NewAuthorizationGrant(authorization exported.Authorization, expiration time.Time) (AuthorizationGrant, error) { auth := AuthorizationGrant{ Expiration: expiration, } @@ -49,13 +35,13 @@ var ( // UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces func (auth AuthorizationGrant) UnpackInterfaces(unpacker types.AnyUnpacker) error { - var authorization Authorization + var authorization exported.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) +func (auth AuthorizationGrant) GetAuthorizationGrant() exported.Authorization { + authorization, ok := auth.Authorization.GetCachedValue().(exported.Authorization) if !ok { return nil } diff --git a/x/authz/types/authz.pb.go b/x/authz/types/authz.pb.go index 3343083205f5..15c103c61312 100644 --- a/x/authz/types/authz.pb.go +++ b/x/authz/types/authz.pb.go @@ -5,9 +5,7 @@ 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" + 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" @@ -31,52 +29,6 @@ var _ = time.Kitchen // 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 { @@ -90,7 +42,7 @@ 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} + return fileDescriptor_544dc2e84b61c637, []int{0} } func (m *GenericAuthorization) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -129,15 +81,15 @@ func (m *GenericAuthorization) GetMessageName() string { // 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"` + Authorization *types.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} + return fileDescriptor_544dc2e84b61c637, []int{1} } func (m *AuthorizationGrant) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -166,7 +118,7 @@ func (m *AuthorizationGrant) XXX_DiscardUnknown() { var xxx_messageInfo_AuthorizationGrant proto.InternalMessageInfo -func (m *AuthorizationGrant) GetAuthorization() *types1.Any { +func (m *AuthorizationGrant) GetAuthorization() *types.Any { if m != nil { return m.Authorization } @@ -181,7 +133,6 @@ func (m *AuthorizationGrant) GetExpiration() 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") } @@ -189,70 +140,28 @@ func init() { 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 + // 333 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x64, 0x91, 0xc1, 0x4e, 0xfa, 0x40, + 0x10, 0xc6, 0xbb, 0xff, 0xc3, 0x3f, 0xba, 0x84, 0x18, 0x9a, 0x1e, 0x84, 0x43, 0x4b, 0x38, 0x19, + 0x13, 0x5a, 0xd1, 0x9b, 0x37, 0x1a, 0x12, 0x4e, 0x78, 0x20, 0x9e, 0xf4, 0x40, 0xb6, 0x30, 0xb6, + 0x8d, 0x6e, 0xa7, 0xe9, 0x6e, 0x0d, 0xf0, 0x14, 0xbc, 0x86, 0x77, 0x1f, 0x82, 0x78, 0x22, 0x9e, + 0x3c, 0xa1, 0x29, 0x2f, 0x62, 0xe8, 0x2e, 0x09, 0xe0, 0x69, 0x67, 0xbe, 0xfd, 0xbe, 0xdf, 0x4e, + 0x76, 0x68, 0x73, 0x8c, 0x82, 0xa3, 0xf0, 0x58, 0x2e, 0xa3, 0xb9, 0xf7, 0xda, 0x09, 0x40, 0xb2, + 0x8e, 0xea, 0xdc, 0x34, 0x43, 0x89, 0xa6, 0xa5, 0x1c, 0xae, 0xd2, 0xb4, 0xa3, 0x51, 0x57, 0xea, + 0xa8, 0xf4, 0x78, 0xda, 0x52, 0x36, 0x0d, 0x27, 0x44, 0x0c, 0x5f, 0xc0, 0x2b, 0xbb, 0x20, 0x7f, + 0xf2, 0x64, 0xcc, 0x41, 0x48, 0xc6, 0x53, 0x6d, 0xb0, 0x42, 0x0c, 0x51, 0x05, 0xb7, 0x95, 0x56, + 0xeb, 0xc7, 0x31, 0x96, 0xcc, 0xd4, 0x55, 0xeb, 0x91, 0x5a, 0x7d, 0x48, 0x20, 0x8b, 0xc7, 0xdd, + 0x5c, 0x46, 0x98, 0xc5, 0x73, 0x26, 0x63, 0x4c, 0xcc, 0x2b, 0x5a, 0xe1, 0x20, 0x23, 0x9c, 0x8c, + 0x12, 0xc6, 0xe1, 0x9c, 0x34, 0xc9, 0xc5, 0xa9, 0x7f, 0x56, 0xac, 0x9d, 0xca, 0x00, 0x84, 0x60, + 0x21, 0xdc, 0x31, 0x0e, 0x43, 0xaa, 0x3c, 0xdb, 0xfa, 0xb6, 0xf6, 0xf9, 0xde, 0xae, 0x1e, 0x40, + 0x5a, 0x6f, 0x84, 0x9a, 0x07, 0x4a, 0x3f, 0x63, 0x89, 0x34, 0x07, 0xb4, 0xca, 0xf6, 0xd5, 0x92, + 0x5e, 0xb9, 0xb6, 0x5c, 0x35, 0xa6, 0xbb, 0x1b, 0xd3, 0xed, 0x26, 0x33, 0xbf, 0xf6, 0x71, 0x8c, + 0x1d, 0x1e, 0xa6, 0xcd, 0x1e, 0xa5, 0x30, 0x4d, 0xe3, 0x4c, 0xb1, 0xfe, 0x95, 0xac, 0xc6, 0x1f, + 0xd6, 0xfd, 0xee, 0xa7, 0xfc, 0x93, 0xe5, 0xda, 0x31, 0x16, 0xdf, 0x0e, 0x19, 0xee, 0xe5, 0xfc, + 0xde, 0xb2, 0xb0, 0xc9, 0xaa, 0xb0, 0xc9, 0x4f, 0x61, 0x93, 0xc5, 0xc6, 0x36, 0x56, 0x1b, 0xdb, + 0xf8, 0xda, 0xd8, 0xc6, 0xc3, 0x65, 0x18, 0xcb, 0x28, 0x0f, 0xdc, 0x31, 0x72, 0xbd, 0x0d, 0x7d, + 0xb4, 0xc5, 0xe4, 0xd9, 0x9b, 0xea, 0xfd, 0xca, 0x59, 0x0a, 0x22, 0xf8, 0x5f, 0xbe, 0x77, 0xf3, + 0x1b, 0x00, 0x00, 0xff, 0xff, 0x62, 0x49, 0x9d, 0xc0, 0xfc, 0x01, 0x00, 0x00, } func (m *GenericAuthorization) Marshal() (dAtA []byte, err error) { @@ -339,21 +248,6 @@ func encodeVarintAuthz(dAtA []byte, offset int, v uint64) int { 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 @@ -388,90 +282,6 @@ func sovAuthz(x uint64) (n int) { 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 @@ -613,7 +423,7 @@ func (m *AuthorizationGrant) Unmarshal(dAtA []byte) error { return io.ErrUnexpectedEOF } if m.Authorization == nil { - m.Authorization = &types1.Any{} + m.Authorization = &types.Any{} } if err := m.Authorization.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err diff --git a/x/authz/types/codec.go b/x/authz/types/codec.go index 88b30932df9f..c6119f2a0bbb 100644 --- a/x/authz/types/codec.go +++ b/x/authz/types/codec.go @@ -4,6 +4,9 @@ import ( types "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/msgservice" + "github.com/cosmos/cosmos-sdk/x/authz/exported" + bank "github.com/cosmos/cosmos-sdk/x/bank/types" + staking "github.com/cosmos/cosmos-sdk/x/staking/types" ) // RegisterInterfaces registers the interfaces types with the interface registry @@ -16,9 +19,10 @@ func RegisterInterfaces(registry types.InterfaceRegistry) { registry.RegisterInterface( "cosmos.authz.v1beta1.Authorization", - (*Authorization)(nil), - &SendAuthorization{}, + (*exported.Authorization)(nil), + &bank.SendAuthorization{}, &GenericAuthorization{}, + &staking.StakeAuthorization{}, ) msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) diff --git a/x/authz/types/generic_authorization.go b/x/authz/types/generic_authorization.go index 242608c6311a..672260c67f34 100644 --- a/x/authz/types/generic_authorization.go +++ b/x/authz/types/generic_authorization.go @@ -4,10 +4,11 @@ import ( tmproto "github.com/tendermint/tendermint/proto/tendermint/types" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/authz/exported" ) var ( - _ Authorization = &GenericAuthorization{} + _ exported.Authorization = &GenericAuthorization{} ) // NewGenericAuthorization creates a new GenericAuthorization object. @@ -23,6 +24,6 @@ func (cap GenericAuthorization) MethodName() string { } // Accept implements Authorization.Accept. -func (cap GenericAuthorization) Accept(msg sdk.ServiceMsg, block tmproto.Header) (allow bool, updated Authorization, delete bool) { - return true, &cap, false +func (cap GenericAuthorization) Accept(msg sdk.ServiceMsg, block tmproto.Header) (updated exported.Authorization, delete bool, err error) { + return &cap, false, nil } diff --git a/x/authz/types/genesis.go b/x/authz/types/genesis.go index 6ae3529d2ec0..8d2a356f5e75 100644 --- a/x/authz/types/genesis.go +++ b/x/authz/types/genesis.go @@ -2,6 +2,7 @@ package types import ( "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/x/authz/exported" ) // NewGenesisState creates new GenesisState object @@ -36,6 +37,6 @@ func (data GenesisState) UnpackInterfaces(unpacker types.AnyUnpacker) error { // UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces func (msg GrantAuthorization) UnpackInterfaces(unpacker types.AnyUnpacker) error { - var authorization Authorization + var authorization exported.Authorization return unpacker.UnpackAny(msg.Authorization, &authorization) } diff --git a/x/authz/types/genesis.pb.go b/x/authz/types/genesis.pb.go index 0cf5c8557754..20dfb9d232b5 100644 --- a/x/authz/types/genesis.pb.go +++ b/x/authz/types/genesis.pb.go @@ -153,29 +153,29 @@ func init() { } 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, + // 340 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x52, 0xbb, 0x6e, 0xc2, 0x30, + 0x14, 0x8d, 0x0b, 0xea, 0xc3, 0x94, 0xa1, 0x11, 0x43, 0xca, 0x10, 0x10, 0x53, 0x54, 0x09, 0x5b, + 0xd0, 0x2f, 0x20, 0x42, 0x62, 0xea, 0x42, 0x99, 0xba, 0x54, 0x0e, 0xb8, 0x26, 0x6a, 0x13, 0x47, + 0xb1, 0xa9, 0x80, 0xaf, 0xe0, 0x63, 0xfa, 0x11, 0xa8, 0x13, 0x63, 0x97, 0x3e, 0x04, 0x3f, 0x52, + 0xc5, 0x76, 0x54, 0x08, 0x9d, 0x72, 0x6f, 0xce, 0xb9, 0xe7, 0x1c, 0x5f, 0x1b, 0xb6, 0xc6, 0x5c, + 0x44, 0x5c, 0x60, 0x32, 0x93, 0xd3, 0x25, 0x7e, 0xed, 0x04, 0x54, 0x92, 0x0e, 0x66, 0x34, 0xa6, + 0x22, 0x14, 0x28, 0x49, 0xb9, 0xe4, 0x76, 0x4d, 0x73, 0x90, 0xe2, 0x20, 0xc3, 0xa9, 0x37, 0x18, + 0xe7, 0xec, 0x85, 0x62, 0xc5, 0x09, 0x66, 0x4f, 0x58, 0x86, 0x11, 0x15, 0x92, 0x44, 0x89, 0x1e, + 0xab, 0x5f, 0x17, 0x09, 0x24, 0x5e, 0x18, 0xa8, 0xc6, 0x38, 0xe3, 0xaa, 0xc4, 0x59, 0x95, 0x0f, + 0x68, 0x9f, 0x47, 0x0d, 0x18, 0x53, 0xd5, 0xb4, 0x26, 0xf0, 0x72, 0xa0, 0x33, 0xdd, 0x4b, 0x22, + 0xa9, 0x3d, 0x82, 0xd5, 0x2c, 0x0d, 0x4f, 0xc3, 0x25, 0x91, 0x21, 0x8f, 0x1d, 0xd0, 0x2c, 0x79, + 0x95, 0xae, 0x87, 0xfe, 0x8b, 0x8a, 0x06, 0x29, 0x89, 0x65, 0x6f, 0x9f, 0xef, 0x97, 0xd7, 0x5f, + 0x0d, 0x6b, 0x78, 0x28, 0xd2, 0xfa, 0x04, 0xd0, 0x3e, 0xe6, 0xda, 0x0e, 0x3c, 0x63, 0xd9, 0x5f, + 0x9a, 0x3a, 0xa0, 0x09, 0xbc, 0x8b, 0x61, 0xde, 0xfe, 0x21, 0xd4, 0x39, 0xd9, 0x47, 0xa8, 0x7d, + 0x57, 0x0c, 0x58, 0x6a, 0x02, 0xaf, 0xd2, 0xad, 0x21, 0xbd, 0x14, 0x94, 0x2f, 0x05, 0xf5, 0xe2, + 0x85, 0x7f, 0xf5, 0xfe, 0xd6, 0xae, 0x1e, 0x78, 0x16, 0x92, 0xd9, 0x7d, 0x08, 0xe9, 0x3c, 0x09, + 0x53, 0xad, 0x55, 0x56, 0x5a, 0xf5, 0x23, 0xad, 0x51, 0x7e, 0x03, 0xfe, 0x79, 0x76, 0xbc, 0xd5, + 0x77, 0x03, 0x0c, 0xf7, 0xe6, 0xfc, 0xfe, 0x7a, 0xeb, 0x82, 0xcd, 0xd6, 0x05, 0x3f, 0x5b, 0x17, + 0xac, 0x76, 0xae, 0xb5, 0xd9, 0xb9, 0xd6, 0xc7, 0xce, 0xb5, 0x1e, 0x6e, 0x58, 0x28, 0xa7, 0xb3, + 0x00, 0x8d, 0x79, 0x64, 0x16, 0x6f, 0x3e, 0x6d, 0x31, 0x79, 0xc6, 0x73, 0xf3, 0x3c, 0xe4, 0x22, + 0xa1, 0x22, 0x38, 0x55, 0x7e, 0xb7, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x94, 0xbe, 0x5b, 0xfa, + 0x3b, 0x02, 0x00, 0x00, } func (m *GenesisState) Marshal() (dAtA []byte, err error) { diff --git a/x/authz/types/keys_test.go b/x/authz/types/keys_test.go index 1d6d7cef6623..caad7ba5cf1c 100644 --- a/x/authz/types/keys_test.go +++ b/x/authz/types/keys_test.go @@ -7,11 +7,12 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" sdk "github.com/cosmos/cosmos-sdk/types" + bank "github.com/cosmos/cosmos-sdk/x/bank/types" ) var granter = sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address()) var grantee = sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address()) -var msgType = SendAuthorization{}.MethodName() +var msgType = bank.SendAuthorization{}.MethodName() func TestGrantkey(t *testing.T) { granter1, grantee1 := ExtractAddressesFromGrantKey(GetAuthorizationStoreKey(grantee, granter, msgType)) diff --git a/x/authz/types/msgs.go b/x/authz/types/msgs.go index 59ae59c20aa6..8fa3bdd1f0a4 100644 --- a/x/authz/types/msgs.go +++ b/x/authz/types/msgs.go @@ -8,6 +8,7 @@ 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/cosmos/cosmos-sdk/x/authz/exported" ) var ( @@ -21,7 +22,7 @@ var ( // NewMsgGrantAuthorization creates a new MsgGrantAuthorization //nolint:interfacer -func NewMsgGrantAuthorization(granter sdk.AccAddress, grantee sdk.AccAddress, authorization Authorization, expiration time.Time) (*MsgGrantAuthorizationRequest, error) { +func NewMsgGrantAuthorization(granter sdk.AccAddress, grantee sdk.AccAddress, authorization exported.Authorization, expiration time.Time) (*MsgGrantAuthorizationRequest, error) { m := &MsgGrantAuthorizationRequest{ Granter: granter.String(), Grantee: grantee.String(), @@ -66,8 +67,8 @@ func (msg MsgGrantAuthorizationRequest) ValidateBasic() error { } // GetGrantAuthorization returns the cache value from the MsgGrantAuthorization.Authorization if present. -func (msg *MsgGrantAuthorizationRequest) GetGrantAuthorization() Authorization { - authorization, ok := msg.Authorization.GetCachedValue().(Authorization) +func (msg *MsgGrantAuthorizationRequest) GetGrantAuthorization() exported.Authorization { + authorization, ok := msg.Authorization.GetCachedValue().(exported.Authorization) if !ok { return nil } @@ -75,7 +76,7 @@ func (msg *MsgGrantAuthorizationRequest) GetGrantAuthorization() Authorization { } // SetAuthorization converts Authorization to any and adds it to MsgGrantAuthorization.Authorization. -func (msg *MsgGrantAuthorizationRequest) SetAuthorization(authorization Authorization) error { +func (msg *MsgGrantAuthorizationRequest) SetAuthorization(authorization exported.Authorization) error { m, ok := authorization.(proto.Message) if !ok { return sdkerrors.Wrapf(sdkerrors.ErrPackAny, "can't proto marshal %T", m) @@ -103,7 +104,7 @@ func (msg MsgExecAuthorizedRequest) UnpackInterfaces(unpacker types.AnyUnpacker) // UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces func (msg MsgGrantAuthorizationRequest) UnpackInterfaces(unpacker types.AnyUnpacker) error { - var authorization Authorization + var authorization exported.Authorization return unpacker.UnpackAny(msg.Authorization, &authorization) } diff --git a/x/authz/types/msgs_test.go b/x/authz/types/msgs_test.go index 3c6cea890576..c27c750b0d93 100644 --- a/x/authz/types/msgs_test.go +++ b/x/authz/types/msgs_test.go @@ -9,6 +9,7 @@ import ( banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/authz/exported" "github.com/cosmos/cosmos-sdk/x/authz/types" ) @@ -29,7 +30,7 @@ func TestMsgExecAuthorized(t *testing.T) { {"zero-messages test: should fail", grantee, []sdk.ServiceMsg{}, false}, {"valid test: msg type", grantee, []sdk.ServiceMsg{ { - MethodName: types.SendAuthorization{}.MethodName(), + MethodName: banktypes.SendAuthorization{}.MethodName(), Request: &banktypes.MsgSend{ Amount: sdk.NewCoins(sdk.NewInt64Coin("steak", 2)), FromAddress: granter.String(), @@ -73,17 +74,17 @@ func TestMsgGrantAuthorization(t *testing.T) { tests := []struct { title string granter, grantee sdk.AccAddress - authorization types.Authorization + authorization exported.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 granter address", nil, grantee, &banktypes.SendAuthorization{SpendLimit: coinsPos}, time.Now(), false, false}, + {"nil grantee address", granter, nil, &banktypes.SendAuthorization{SpendLimit: coinsPos}, time.Now(), false, false}, + {"nil granter and grantee address", nil, nil, &banktypes.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}, + {"valid test case", granter, grantee, &banktypes.SendAuthorization{SpendLimit: coinsPos}, time.Now().AddDate(0, 1, 0), false, true}, + {"past time", granter, grantee, &banktypes.SendAuthorization{SpendLimit: coinsPos}, time.Now().AddDate(0, 0, -1), false, false}, } for i, tc := range tests { msg, err := types.NewMsgGrantAuthorization( diff --git a/x/authz/types/query.pb.go b/x/authz/types/query.pb.go index 91accaa109d5..493412f7524f 100644 --- a/x/authz/types/query.pb.go +++ b/x/authz/types/query.pb.go @@ -6,12 +6,9 @@ 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" @@ -266,38 +263,36 @@ func init() { 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, + // 461 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x94, 0x31, 0x8f, 0xd3, 0x30, + 0x14, 0xc7, 0xeb, 0x56, 0x80, 0x70, 0x75, 0x37, 0x58, 0x0c, 0x21, 0xa0, 0x50, 0x65, 0x80, 0xd3, + 0x49, 0xc4, 0xb4, 0x7c, 0x82, 0x3b, 0x4e, 0x9c, 0x60, 0x38, 0x1d, 0x19, 0x59, 0x90, 0xd3, 0x3e, + 0x25, 0x11, 0x4d, 0x9c, 0xc6, 0x0e, 0xa2, 0x45, 0x2c, 0xac, 0x2c, 0x48, 0x2c, 0x7c, 0x14, 0x16, + 0x06, 0x36, 0xc6, 0x4a, 0x2c, 0x8c, 0xa8, 0xe5, 0x83, 0xa0, 0xda, 0x4e, 0x9b, 0xa0, 0xa0, 0x6b, + 0xd5, 0x29, 0xc9, 0x7b, 0xef, 0xff, 0xfe, 0xbf, 0xf7, 0x6c, 0x05, 0xf7, 0x86, 0x5c, 0x24, 0x5c, + 0x50, 0x56, 0xc8, 0x68, 0x46, 0xdf, 0xf4, 0x03, 0x90, 0xac, 0x4f, 0x27, 0x05, 0xe4, 0x53, 0x2f, + 0xcb, 0xb9, 0xe4, 0xe4, 0x96, 0xae, 0xf0, 0x54, 0x85, 0x67, 0x2a, 0xec, 0xbb, 0x21, 0xe7, 0xe1, + 0x18, 0x28, 0xcb, 0x62, 0xca, 0xd2, 0x94, 0x4b, 0x26, 0x63, 0x9e, 0x0a, 0xad, 0xb1, 0x8f, 0x4d, + 0xd7, 0x80, 0x09, 0xd0, 0xcd, 0xd6, 0xad, 0x33, 0x16, 0xc6, 0xa9, 0x2a, 0x36, 0xb5, 0xcd, 0x04, + 0xda, 0x4d, 0x55, 0xb8, 0x19, 0xbe, 0xfd, 0x62, 0xd5, 0xe3, 0xa4, 0x90, 0x11, 0xcf, 0xe3, 0x99, + 0x52, 0xfb, 0x30, 0x29, 0x40, 0x48, 0x62, 0xe1, 0x1b, 0x61, 0xce, 0x52, 0x09, 0xb9, 0x85, 0x7a, + 0xe8, 0xe8, 0xa6, 0x5f, 0x7e, 0x6e, 0x32, 0x60, 0xb5, 0xab, 0x19, 0x20, 0xf7, 0x70, 0x37, 0x01, + 0x19, 0xf1, 0xd1, 0xab, 0x94, 0x25, 0x60, 0x75, 0x54, 0x16, 0xeb, 0xd0, 0x05, 0x4b, 0xc0, 0x1d, + 0x63, 0xbb, 0xc9, 0x51, 0x64, 0x3c, 0x15, 0x40, 0x2e, 0xf0, 0x01, 0xab, 0x26, 0x94, 0x71, 0x77, + 0x70, 0xe4, 0x35, 0x6d, 0xca, 0xab, 0xf5, 0x38, 0x5f, 0x11, 0xf8, 0x75, 0xb9, 0xfb, 0x05, 0x35, + 0xd9, 0x89, 0x7d, 0x26, 0x7c, 0x8a, 0xf1, 0x66, 0xd1, 0x6a, 0xc0, 0xee, 0xe0, 0x7e, 0xc9, 0xb7, + 0x3a, 0x15, 0x4f, 0x1f, 0x71, 0x09, 0x79, 0xc9, 0x42, 0x30, 0x7e, 0x7e, 0x45, 0xe9, 0x7e, 0x45, + 0xf8, 0x4e, 0x23, 0x9a, 0x59, 0xc5, 0x25, 0x3e, 0xac, 0xcd, 0x22, 0x2c, 0xd4, 0xeb, 0xec, 0xb4, + 0x8b, 0x7f, 0xf4, 0xe4, 0xbc, 0x46, 0xde, 0x56, 0xe4, 0x0f, 0xae, 0x24, 0xd7, 0x38, 0x55, 0xf4, + 0xc1, 0xc7, 0x0e, 0xbe, 0xa6, 0xd0, 0xc9, 0x37, 0x84, 0x0f, 0x6a, 0xce, 0x84, 0x36, 0xe3, 0xfd, + 0xf7, 0x96, 0xd9, 0x8f, 0xb6, 0x17, 0x68, 0x14, 0xf7, 0xd9, 0x87, 0x9f, 0x7f, 0x3e, 0xb7, 0x9f, + 0x90, 0x13, 0xda, 0x78, 0xbf, 0xcd, 0x11, 0x0a, 0xfa, 0xce, 0xbc, 0xbd, 0x37, 0x21, 0x58, 0x87, + 0xc0, 0x84, 0xc8, 0x77, 0x84, 0x0f, 0xeb, 0xfb, 0x27, 0x5b, 0xf3, 0x94, 0xb7, 0xc8, 0xee, 0xef, + 0xa0, 0x30, 0x23, 0x3c, 0x57, 0x23, 0x9c, 0x91, 0xd3, 0xbd, 0x47, 0x10, 0xa7, 0x67, 0x3f, 0x16, + 0x0e, 0x9a, 0x2f, 0x1c, 0xf4, 0x7b, 0xe1, 0xa0, 0x4f, 0x4b, 0xa7, 0x35, 0x5f, 0x3a, 0xad, 0x5f, + 0x4b, 0xa7, 0xf5, 0xf2, 0x38, 0x8c, 0x65, 0x54, 0x04, 0xde, 0x90, 0x27, 0xa5, 0x8f, 0x7e, 0x3c, + 0x14, 0xa3, 0xd7, 0xf4, 0xad, 0x31, 0x95, 0xd3, 0x0c, 0x44, 0x70, 0x5d, 0xfd, 0x10, 0x1e, 0xff, + 0x0d, 0x00, 0x00, 0xff, 0xff, 0x91, 0xf5, 0x18, 0x65, 0xb6, 0x04, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/bank/types/authz.pb.go b/x/bank/types/authz.pb.go new file mode 100644 index 000000000000..92444cb98e91 --- /dev/null +++ b/x/bank/types/authz.pb.go @@ -0,0 +1,338 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cosmos/bank/v1beta1/authz.proto + +package types + +import ( + fmt "fmt" + 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/regen-network/cosmos-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 + +// 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_a4d2a37888ea779f, []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 +} + +func init() { + proto.RegisterType((*SendAuthorization)(nil), "cosmos.bank.v1beta1.SendAuthorization") +} + +func init() { proto.RegisterFile("cosmos/bank/v1beta1/authz.proto", fileDescriptor_a4d2a37888ea779f) } + +var fileDescriptor_a4d2a37888ea779f = []byte{ + // 257 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4f, 0xce, 0x2f, 0xce, + 0xcd, 0x2f, 0xd6, 0x4f, 0x4a, 0xcc, 0xcb, 0xd6, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, 0x49, 0x34, 0xd4, + 0x4f, 0x2c, 0x2d, 0xc9, 0xa8, 0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x86, 0x28, 0xd0, + 0x03, 0x29, 0xd0, 0x83, 0x2a, 0x90, 0x12, 0x49, 0xcf, 0x4f, 0xcf, 0x07, 0xcb, 0xeb, 0x83, 0x58, + 0x10, 0xa5, 0x52, 0x92, 0x10, 0xa5, 0xf1, 0x10, 0x09, 0xa8, 0x3e, 0x88, 0x94, 0x1c, 0xdc, 0x9a, + 0xe2, 0x54, 0xb8, 0x35, 0xc9, 0xf9, 0x99, 0x79, 0x10, 0x79, 0xa5, 0x29, 0x8c, 0x5c, 0x82, 0xc1, + 0xa9, 0x79, 0x29, 0x8e, 0xa5, 0x25, 0x19, 0xf9, 0x45, 0x99, 0x55, 0x89, 0x25, 0x99, 0xf9, 0x79, + 0x42, 0x39, 0x5c, 0xdc, 0xc5, 0x05, 0xa9, 0x79, 0x29, 0xf1, 0x39, 0x99, 0xb9, 0x99, 0x25, 0x12, + 0x8c, 0x0a, 0xcc, 0x1a, 0xdc, 0x46, 0x92, 0x7a, 0x70, 0x17, 0x15, 0xa7, 0xc2, 0x5c, 0xa4, 0xe7, + 0x9c, 0x9f, 0x99, 0xe7, 0x64, 0x70, 0xe2, 0x9e, 0x3c, 0xc3, 0xaa, 0xfb, 0xf2, 0x1a, 0xe9, 0x99, + 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9, 0xf9, 0xb9, 0x50, 0x67, 0x40, 0x29, 0xdd, 0xe2, 0x94, 0x6c, + 0xfd, 0x92, 0xca, 0x82, 0xd4, 0x62, 0xb0, 0x86, 0xe2, 0x20, 0x2e, 0xb0, 0xf9, 0x3e, 0x20, 0xe3, + 0xad, 0x04, 0x2f, 0x6d, 0xd1, 0xe5, 0x45, 0x71, 0x80, 0x93, 0xf3, 0x89, 0x47, 0x72, 0x8c, 0x17, + 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c, 0xc3, 0x85, 0xc7, 0x72, 0x0c, + 0x37, 0x1e, 0xcb, 0x31, 0x44, 0x69, 0xe2, 0xb5, 0xa2, 0x02, 0x12, 0x9e, 0x60, 0x9b, 0x92, 0xd8, + 0xc0, 0x5e, 0x34, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0x3b, 0xce, 0xe1, 0x4c, 0x6b, 0x01, 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 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 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 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/send_authorization.go b/x/bank/types/send_authorization.go similarity index 55% rename from x/authz/types/send_authorization.go rename to x/bank/types/send_authorization.go index 2bb2a63a74f6..ccd755c1fce5 100644 --- a/x/authz/types/send_authorization.go +++ b/x/bank/types/send_authorization.go @@ -6,11 +6,12 @@ import ( tmproto "github.com/tendermint/tendermint/proto/tendermint/types" sdk "github.com/cosmos/cosmos-sdk/types" - bank "github.com/cosmos/cosmos-sdk/x/bank/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + authz "github.com/cosmos/cosmos-sdk/x/authz/exported" ) var ( - _ Authorization = &SendAuthorization{} + _ authz.Authorization = &SendAuthorization{} ) // NewSendAuthorization creates a new SendAuthorization object. @@ -26,20 +27,20 @@ func (authorization SendAuthorization) MethodName() string { } // 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) +func (authorization SendAuthorization) Accept(msg sdk.ServiceMsg, block tmproto.Header) (updated authz.Authorization, delete bool, err error) { + if reflect.TypeOf(msg.Request) == reflect.TypeOf(&MsgSend{}) { + msg, ok := msg.Request.(*MsgSend) if ok { limitLeft, isNegative := authorization.SpendLimit.SafeSub(msg.Amount) if isNegative { - return false, nil, false + return nil, false, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFunds, "requested amount is more than spend limit") } if limitLeft.IsZero() { - return true, nil, true + return nil, true, nil } - return true, &SendAuthorization{SpendLimit: limitLeft}, false + return &SendAuthorization{SpendLimit: limitLeft}, false, nil } } - return false, nil, false + return nil, false, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "type mismatch") } diff --git a/x/gov/types/tx.pb.go b/x/gov/types/tx.pb.go index 851f2b622fde..76bbd1c19aca 100644 --- a/x/gov/types/tx.pb.go +++ b/x/gov/types/tx.pb.go @@ -232,7 +232,7 @@ func (m *MsgVoteResponse) XXX_DiscardUnknown() { var xxx_messageInfo_MsgVoteResponse proto.InternalMessageInfo -// MsgVoteWeightedResponse defines the MsgVoteWeighted response type. +// MsgVoteWeightedResponse defines the Msg/VoteWeighted response type. type MsgVoteWeightedResponse struct { } diff --git a/x/staking/types/authz.go b/x/staking/types/authz.go new file mode 100644 index 000000000000..aae9b706f1fe --- /dev/null +++ b/x/staking/types/authz.go @@ -0,0 +1,135 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + authz "github.com/cosmos/cosmos-sdk/x/authz/exported" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" +) + +var ( + _ authz.Authorization = &StakeAuthorization{} + TypeDelegate = "/cosmos.staking.v1beta1.Msg/Delegate" + TypeUndelegate = "/cosmos.staking.v1beta1.Msg/Undelegate" + TypeBeginRedelegate = "/cosmos.staking.v1beta1.Msg/BeginRedelegate" +) + +// NewStakeAuthorization creates a new StakeAuthorization object. +func NewStakeAuthorization(allowed []sdk.ValAddress, denied []sdk.ValAddress, authzType AuthorizationType, amount *sdk.Coin) (*StakeAuthorization, error) { + allowedValidators, deniedValidators, err := validateAndBech32fy(allowed, denied) + if err != nil { + return nil, err + } + + authorization := StakeAuthorization{} + if allowedValidators != nil { + authorization.Validators = &StakeAuthorization_AllowList{AllowList: &StakeAuthorization_Validators{Address: allowedValidators}} + } else { + authorization.Validators = &StakeAuthorization_DenyList{DenyList: &StakeAuthorization_Validators{Address: deniedValidators}} + } + + if amount != nil { + authorization.MaxTokens = amount + } + authorization.AuthorizationType = authzType + + return &authorization, nil +} + +// MethodName implements Authorization.MethodName. +func (authorization StakeAuthorization) MethodName() string { + authzType, err := normalizeAuthzType(authorization.AuthorizationType) + if err != nil { + panic(err) + } + return authzType +} + +// Accept implements Authorization.Accept. +func (authorization StakeAuthorization) Accept(msg sdk.ServiceMsg, block tmproto.Header) (updated authz.Authorization, delete bool, err error) { + var validatorAddress string + var amount sdk.Coin + + switch msg := msg.Request.(type) { + case *MsgDelegate: + validatorAddress = msg.ValidatorAddress + amount = msg.Amount + case *MsgUndelegate: + validatorAddress = msg.ValidatorAddress + amount = msg.Amount + case *MsgBeginRedelegate: + validatorAddress = msg.ValidatorDstAddress + amount = msg.Amount + default: + return nil, false, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "unknown msg type") + } + + isValidatorExists := false + allowedList := authorization.GetAllowList().GetAddress() + for _, validator := range allowedList { + if validator == validatorAddress { + isValidatorExists = true + break + } + } + denyList := authorization.GetDenyList().GetAddress() + for _, validator := range denyList { + if validator == validatorAddress { + return nil, false, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, " cannot delegate/undelegate to %s validator", validator) + } + } + + if !isValidatorExists { + return nil, false, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "cannot delegate/undelegate to %s validator", validatorAddress) + } + + if authorization.MaxTokens == nil { + return &StakeAuthorization{Validators: authorization.GetValidators(), AuthorizationType: authorization.GetAuthorizationType()}, false, nil + } + + limitLeft := authorization.MaxTokens.Sub(amount) + if limitLeft.IsZero() { + return nil, true, nil + } + + return &StakeAuthorization{Validators: authorization.GetValidators(), MaxTokens: &limitLeft, AuthorizationType: authorization.GetAuthorizationType()}, false, nil + +} + +func validateAndBech32fy(allowed []sdk.ValAddress, denied []sdk.ValAddress) ([]string, []string, error) { + if len(allowed) == 0 && len(denied) == 0 { + return nil, nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "both allowed & deny list cannot be empty") + } + + if len(allowed) > 0 && len(denied) > 0 { + return nil, nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "cannot set both allowed & deny list") + } + + allowedValidators := make([]string, len(allowed)) + if len(allowed) > 0 { + for i, validator := range allowed { + allowedValidators[i] = validator.String() + } + return allowedValidators, nil, nil + } + + deniedValidators := make([]string, len(denied)) + for i, validator := range denied { + deniedValidators[i] = validator.String() + } + + return nil, deniedValidators, nil +} + +func normalizeAuthzType(authzType AuthorizationType) (string, error) { + switch authzType { + case AuthorizationType_AUTHORIZATION_TYPE_DELEGATE: + return TypeDelegate, nil + case AuthorizationType_AUTHORIZATION_TYPE_UNDELEGATE: + return TypeUndelegate, nil + case AuthorizationType_AUTHORIZATION_TYPE_REDELEGATE: + return TypeBeginRedelegate, nil + default: + return "", sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "unknown authorization type %T", authzType) + } +} diff --git a/x/staking/types/authz.pb.go b/x/staking/types/authz.pb.go new file mode 100644 index 000000000000..d556e0155df1 --- /dev/null +++ b/x/staking/types/authz.pb.go @@ -0,0 +1,797 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cosmos/staking/v1beta1/authz.proto + +package types + +import ( + fmt "fmt" + types "github.com/cosmos/cosmos-sdk/types" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + _ "github.com/regen-network/cosmos-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 + +// AuthorizationType defines the type of staking module authorization type +type AuthorizationType int32 + +const ( + // AUTHORIZATION_TYPE_UNSPECIFIED specifies an unknown authorization type + AuthorizationType_AUTHORIZATION_TYPE_UNSPECIFIED AuthorizationType = 0 + // AUTHORIZATION_TYPE_DELEGATE defines an authorization type for Msg/Delegate + AuthorizationType_AUTHORIZATION_TYPE_DELEGATE AuthorizationType = 1 + // AUTHORIZATION_TYPE_UNDELEGATE defines an authorization type for Msg/Undelegate + AuthorizationType_AUTHORIZATION_TYPE_UNDELEGATE AuthorizationType = 2 + // AUTHORIZATION_TYPE_REDELEGATE defines an authorization type for Msg/BeginRedelegate + AuthorizationType_AUTHORIZATION_TYPE_REDELEGATE AuthorizationType = 3 +) + +var AuthorizationType_name = map[int32]string{ + 0: "AUTHORIZATION_TYPE_UNSPECIFIED", + 1: "AUTHORIZATION_TYPE_DELEGATE", + 2: "AUTHORIZATION_TYPE_UNDELEGATE", + 3: "AUTHORIZATION_TYPE_REDELEGATE", +} + +var AuthorizationType_value = map[string]int32{ + "AUTHORIZATION_TYPE_UNSPECIFIED": 0, + "AUTHORIZATION_TYPE_DELEGATE": 1, + "AUTHORIZATION_TYPE_UNDELEGATE": 2, + "AUTHORIZATION_TYPE_REDELEGATE": 3, +} + +func (x AuthorizationType) String() string { + return proto.EnumName(AuthorizationType_name, int32(x)) +} + +func (AuthorizationType) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_d6d8cdbc6f4432f0, []int{0} +} + +// StakeAuthorization defines authorization for delegate/undelegate/redelegate. +type StakeAuthorization struct { + // max_tokens specifies the maximum amount of tokens can be delegate to a validator. If it is + // empty, there is no spend limit and any amount of coins can be delegated. + MaxTokens *types.Coin `protobuf:"bytes,1,opt,name=max_tokens,json=maxTokens,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coin" json:"max_tokens,omitempty"` + // validators is the oneof that represents either allow_list or deny_list + // + // Types that are valid to be assigned to Validators: + // *StakeAuthorization_AllowList + // *StakeAuthorization_DenyList + Validators isStakeAuthorization_Validators `protobuf_oneof:"validators"` + // authorization_type defines one of AuthorizationType. + AuthorizationType AuthorizationType `protobuf:"varint,4,opt,name=authorization_type,json=authorizationType,proto3,enum=cosmos.staking.v1beta1.AuthorizationType" json:"authorization_type,omitempty"` +} + +func (m *StakeAuthorization) Reset() { *m = StakeAuthorization{} } +func (m *StakeAuthorization) String() string { return proto.CompactTextString(m) } +func (*StakeAuthorization) ProtoMessage() {} +func (*StakeAuthorization) Descriptor() ([]byte, []int) { + return fileDescriptor_d6d8cdbc6f4432f0, []int{0} +} +func (m *StakeAuthorization) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *StakeAuthorization) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_StakeAuthorization.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 *StakeAuthorization) XXX_Merge(src proto.Message) { + xxx_messageInfo_StakeAuthorization.Merge(m, src) +} +func (m *StakeAuthorization) XXX_Size() int { + return m.Size() +} +func (m *StakeAuthorization) XXX_DiscardUnknown() { + xxx_messageInfo_StakeAuthorization.DiscardUnknown(m) +} + +var xxx_messageInfo_StakeAuthorization proto.InternalMessageInfo + +type isStakeAuthorization_Validators interface { + isStakeAuthorization_Validators() + MarshalTo([]byte) (int, error) + Size() int +} + +type StakeAuthorization_AllowList struct { + AllowList *StakeAuthorization_Validators `protobuf:"bytes,2,opt,name=allow_list,json=allowList,proto3,oneof" json:"allow_list,omitempty"` +} +type StakeAuthorization_DenyList struct { + DenyList *StakeAuthorization_Validators `protobuf:"bytes,3,opt,name=deny_list,json=denyList,proto3,oneof" json:"deny_list,omitempty"` +} + +func (*StakeAuthorization_AllowList) isStakeAuthorization_Validators() {} +func (*StakeAuthorization_DenyList) isStakeAuthorization_Validators() {} + +func (m *StakeAuthorization) GetValidators() isStakeAuthorization_Validators { + if m != nil { + return m.Validators + } + return nil +} + +func (m *StakeAuthorization) GetMaxTokens() *types.Coin { + if m != nil { + return m.MaxTokens + } + return nil +} + +func (m *StakeAuthorization) GetAllowList() *StakeAuthorization_Validators { + if x, ok := m.GetValidators().(*StakeAuthorization_AllowList); ok { + return x.AllowList + } + return nil +} + +func (m *StakeAuthorization) GetDenyList() *StakeAuthorization_Validators { + if x, ok := m.GetValidators().(*StakeAuthorization_DenyList); ok { + return x.DenyList + } + return nil +} + +func (m *StakeAuthorization) GetAuthorizationType() AuthorizationType { + if m != nil { + return m.AuthorizationType + } + return AuthorizationType_AUTHORIZATION_TYPE_UNSPECIFIED +} + +// XXX_OneofWrappers is for the internal use of the proto package. +func (*StakeAuthorization) XXX_OneofWrappers() []interface{} { + return []interface{}{ + (*StakeAuthorization_AllowList)(nil), + (*StakeAuthorization_DenyList)(nil), + } +} + +// Validators defines list of validator addresses. +type StakeAuthorization_Validators struct { + Address []string `protobuf:"bytes,1,rep,name=address,proto3" json:"address,omitempty"` +} + +func (m *StakeAuthorization_Validators) Reset() { *m = StakeAuthorization_Validators{} } +func (m *StakeAuthorization_Validators) String() string { return proto.CompactTextString(m) } +func (*StakeAuthorization_Validators) ProtoMessage() {} +func (*StakeAuthorization_Validators) Descriptor() ([]byte, []int) { + return fileDescriptor_d6d8cdbc6f4432f0, []int{0, 0} +} +func (m *StakeAuthorization_Validators) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *StakeAuthorization_Validators) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_StakeAuthorization_Validators.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 *StakeAuthorization_Validators) XXX_Merge(src proto.Message) { + xxx_messageInfo_StakeAuthorization_Validators.Merge(m, src) +} +func (m *StakeAuthorization_Validators) XXX_Size() int { + return m.Size() +} +func (m *StakeAuthorization_Validators) XXX_DiscardUnknown() { + xxx_messageInfo_StakeAuthorization_Validators.DiscardUnknown(m) +} + +var xxx_messageInfo_StakeAuthorization_Validators proto.InternalMessageInfo + +func (m *StakeAuthorization_Validators) GetAddress() []string { + if m != nil { + return m.Address + } + return nil +} + +func init() { + proto.RegisterEnum("cosmos.staking.v1beta1.AuthorizationType", AuthorizationType_name, AuthorizationType_value) + proto.RegisterType((*StakeAuthorization)(nil), "cosmos.staking.v1beta1.StakeAuthorization") + proto.RegisterType((*StakeAuthorization_Validators)(nil), "cosmos.staking.v1beta1.StakeAuthorization.Validators") +} + +func init() { + proto.RegisterFile("cosmos/staking/v1beta1/authz.proto", fileDescriptor_d6d8cdbc6f4432f0) +} + +var fileDescriptor_d6d8cdbc6f4432f0 = []byte{ + // 462 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x93, 0xcb, 0x6e, 0xd3, 0x40, + 0x14, 0x86, 0x3d, 0x0d, 0x02, 0x72, 0xb8, 0xa8, 0x19, 0x21, 0x94, 0x06, 0x31, 0x2d, 0x59, 0x40, + 0xb8, 0x74, 0xac, 0x16, 0xb1, 0x61, 0x97, 0xb4, 0x2e, 0x8d, 0x54, 0xb5, 0x95, 0xeb, 0x56, 0xd0, + 0x8d, 0x35, 0x89, 0x47, 0xc9, 0x28, 0xb6, 0x27, 0xf2, 0x4c, 0x4a, 0xd2, 0xa7, 0xe0, 0x09, 0x78, + 0x00, 0xd6, 0x3c, 0x04, 0x0b, 0x16, 0x15, 0x2b, 0x76, 0xa0, 0xe4, 0x45, 0x90, 0xc7, 0xae, 0xa1, + 0x34, 0x65, 0xc3, 0xca, 0x97, 0xf3, 0xcd, 0xf7, 0x9f, 0x63, 0x1d, 0x43, 0xbd, 0x2b, 0x55, 0x24, + 0x95, 0xad, 0x34, 0x1b, 0x88, 0xb8, 0x67, 0x9f, 0xac, 0x75, 0xb8, 0x66, 0x6b, 0x36, 0x1b, 0xe9, + 0xfe, 0x29, 0x1d, 0x26, 0x52, 0x4b, 0x7c, 0x3f, 0x63, 0x68, 0xce, 0xd0, 0x9c, 0xa9, 0xdd, 0xeb, + 0xc9, 0x9e, 0x34, 0x88, 0x9d, 0xde, 0x65, 0x74, 0x6d, 0x29, 0xa3, 0xfd, 0xac, 0x90, 0x1f, 0xcd, + 0x4a, 0x24, 0x0f, 0xeb, 0x30, 0xc5, 0x8b, 0xa4, 0xae, 0x14, 0x71, 0x56, 0xaf, 0x7f, 0x2d, 0x01, + 0x3e, 0xd0, 0x6c, 0xc0, 0x9b, 0x23, 0xdd, 0x97, 0x89, 0x38, 0x65, 0x5a, 0xc8, 0x18, 0x73, 0x80, + 0x88, 0x8d, 0x7d, 0x2d, 0x07, 0x3c, 0x56, 0x55, 0xb4, 0x82, 0x1a, 0xb7, 0xd6, 0x97, 0x68, 0x6e, + 0x4e, 0x5d, 0xe7, 0x1d, 0xd1, 0x0d, 0x29, 0xe2, 0xd6, 0xf3, 0x4f, 0x3f, 0x96, 0x9f, 0xf4, 0x84, + 0xee, 0x8f, 0x3a, 0xb4, 0x2b, 0xa3, 0xbc, 0x85, 0xfc, 0xb2, 0xaa, 0x82, 0x81, 0xad, 0x27, 0x43, + 0xae, 0x0c, 0xec, 0x96, 0x23, 0x36, 0xf6, 0x8c, 0x18, 0x1f, 0x01, 0xb0, 0x30, 0x94, 0xef, 0xfd, + 0x50, 0x28, 0x5d, 0x5d, 0x30, 0x31, 0xaf, 0xe8, 0xfc, 0xd9, 0xe9, 0xe5, 0x36, 0xe9, 0x11, 0x0b, + 0x45, 0xc0, 0xb4, 0x4c, 0xd4, 0xb6, 0xe5, 0x96, 0x8d, 0x6a, 0x47, 0x28, 0x8d, 0x3d, 0x28, 0x07, + 0x3c, 0x9e, 0x64, 0xda, 0xd2, 0xff, 0x69, 0x6f, 0xa6, 0x26, 0x63, 0x7d, 0x0b, 0x98, 0xfd, 0xc9, + 0xf9, 0xe9, 0x50, 0xd5, 0x6b, 0x2b, 0xa8, 0x71, 0x77, 0xfd, 0xe9, 0x55, 0xfa, 0x0b, 0x66, 0x6f, + 0x32, 0xe4, 0x6e, 0x85, 0xfd, 0xfd, 0xaa, 0xf6, 0x18, 0xe0, 0x77, 0x26, 0xae, 0xc2, 0x0d, 0x16, + 0x04, 0x09, 0x57, 0xe9, 0x97, 0x2f, 0x35, 0xca, 0xee, 0xf9, 0xe3, 0xeb, 0xca, 0xb7, 0xcf, 0xab, + 0x77, 0x2e, 0x18, 0x5b, 0xb7, 0x01, 0x4e, 0x8a, 0xa3, 0xcf, 0x3e, 0x22, 0xa8, 0x5c, 0x4a, 0xc4, + 0x75, 0x20, 0xcd, 0x43, 0x6f, 0x7b, 0xcf, 0x6d, 0x1f, 0x37, 0xbd, 0xf6, 0xde, 0xae, 0xef, 0xbd, + 0xdb, 0x77, 0xfc, 0xc3, 0xdd, 0x83, 0x7d, 0x67, 0xa3, 0xbd, 0xd5, 0x76, 0x36, 0x17, 0x2d, 0xbc, + 0x0c, 0x0f, 0xe6, 0x30, 0x9b, 0xce, 0x8e, 0xf3, 0xa6, 0xe9, 0x39, 0x8b, 0x08, 0x3f, 0x82, 0x87, + 0x73, 0x25, 0x05, 0xb2, 0x70, 0x05, 0xe2, 0x3a, 0x05, 0x52, 0x6a, 0x6d, 0x7d, 0x99, 0x12, 0x74, + 0x36, 0x25, 0xe8, 0xe7, 0x94, 0xa0, 0x0f, 0x33, 0x62, 0x9d, 0xcd, 0x88, 0xf5, 0x7d, 0x46, 0xac, + 0xe3, 0x17, 0xff, 0xdc, 0x9f, 0x71, 0xf1, 0xbb, 0x98, 0x4d, 0xea, 0x5c, 0x37, 0xeb, 0xfb, 0xf2, + 0x57, 0x00, 0x00, 0x00, 0xff, 0xff, 0x54, 0x04, 0xbf, 0x8c, 0x4d, 0x03, 0x00, 0x00, +} + +func (m *StakeAuthorization) 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 *StakeAuthorization) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *StakeAuthorization) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.AuthorizationType != 0 { + i = encodeVarintAuthz(dAtA, i, uint64(m.AuthorizationType)) + i-- + dAtA[i] = 0x20 + } + if m.Validators != nil { + { + size := m.Validators.Size() + i -= size + if _, err := m.Validators.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + } + } + if m.MaxTokens != nil { + { + size, err := m.MaxTokens.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 *StakeAuthorization_AllowList) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *StakeAuthorization_AllowList) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.AllowList != nil { + { + size, err := m.AllowList.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintAuthz(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + return len(dAtA) - i, nil +} +func (m *StakeAuthorization_DenyList) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *StakeAuthorization_DenyList) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.DenyList != nil { + { + size, err := m.DenyList.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintAuthz(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + return len(dAtA) - i, nil +} +func (m *StakeAuthorization_Validators) 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 *StakeAuthorization_Validators) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *StakeAuthorization_Validators) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Address) > 0 { + for iNdEx := len(m.Address) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Address[iNdEx]) + copy(dAtA[i:], m.Address[iNdEx]) + i = encodeVarintAuthz(dAtA, i, uint64(len(m.Address[iNdEx]))) + 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 *StakeAuthorization) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.MaxTokens != nil { + l = m.MaxTokens.Size() + n += 1 + l + sovAuthz(uint64(l)) + } + if m.Validators != nil { + n += m.Validators.Size() + } + if m.AuthorizationType != 0 { + n += 1 + sovAuthz(uint64(m.AuthorizationType)) + } + return n +} + +func (m *StakeAuthorization_AllowList) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.AllowList != nil { + l = m.AllowList.Size() + n += 1 + l + sovAuthz(uint64(l)) + } + return n +} +func (m *StakeAuthorization_DenyList) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.DenyList != nil { + l = m.DenyList.Size() + n += 1 + l + sovAuthz(uint64(l)) + } + return n +} +func (m *StakeAuthorization_Validators) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Address) > 0 { + for _, s := range m.Address { + l = len(s) + 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 *StakeAuthorization) 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: StakeAuthorization: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: StakeAuthorization: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxTokens", 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.MaxTokens == nil { + m.MaxTokens = &types.Coin{} + } + if err := m.MaxTokens.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AllowList", 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 + } + v := &StakeAuthorization_Validators{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Validators = &StakeAuthorization_AllowList{v} + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DenyList", 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 + } + v := &StakeAuthorization_Validators{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Validators = &StakeAuthorization_DenyList{v} + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field AuthorizationType", wireType) + } + m.AuthorizationType = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthz + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.AuthorizationType |= AuthorizationType(b&0x7F) << shift + if b < 0x80 { + break + } + } + 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 *StakeAuthorization_Validators) 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: Validators: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Validators: 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 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.Address = append(m.Address, 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 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/staking/types/authz_test.go b/x/staking/types/authz_test.go new file mode 100644 index 000000000000..7f5dd2c22c10 --- /dev/null +++ b/x/staking/types/authz_test.go @@ -0,0 +1,282 @@ +package types_test + +import ( + "testing" + + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + + sdk "github.com/cosmos/cosmos-sdk/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/stretchr/testify/require" +) + +var ( + coin100 = sdk.NewInt64Coin("steak", 100) + coin50 = sdk.NewInt64Coin("steak", 50) + delAddr = sdk.AccAddress("_____delegator _____") + val1 = sdk.ValAddress("_____validator1_____") + val2 = sdk.ValAddress("_____validator2_____") + val3 = sdk.ValAddress("_____validator3_____") +) + +func TestAuthzAuthorizations(t *testing.T) { + + // verify MethodName + delAuth, _ := stakingtypes.NewStakeAuthorization([]sdk.ValAddress{val1, val2}, []sdk.ValAddress{}, stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, &coin100) + require.Equal(t, delAuth.MethodName(), stakingtypes.TypeDelegate) + + // error both allow & deny list + _, err := stakingtypes.NewStakeAuthorization([]sdk.ValAddress{val1, val2}, []sdk.ValAddress{val1}, stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, &coin100) + require.Error(t, err) + + // verify MethodName + undelAuth, _ := stakingtypes.NewStakeAuthorization([]sdk.ValAddress{val1, val2}, []sdk.ValAddress{}, stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_UNDELEGATE, &coin100) + require.Equal(t, undelAuth.MethodName(), stakingtypes.TypeUndelegate) + + // verify MethodName + beginRedelAuth, _ := stakingtypes.NewStakeAuthorization([]sdk.ValAddress{val1, val2}, []sdk.ValAddress{}, stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_REDELEGATE, &coin100) + require.Equal(t, beginRedelAuth.MethodName(), stakingtypes.TypeBeginRedelegate) + + validators1_2 := []string{val1.String(), val2.String()} + + testCases := []struct { + msg string + allowed []sdk.ValAddress + denied []sdk.ValAddress + msgType stakingtypes.AuthorizationType + limit *sdk.Coin + srvMsg sdk.ServiceMsg + expectErr bool + isDelete bool + updatedAuthorization *stakingtypes.StakeAuthorization + }{ + { + "delegate: expect 0 remaining coins", + []sdk.ValAddress{val1, val2}, + []sdk.ValAddress{}, + stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, + &coin100, + createSrvMsgDelegate(delAuth.MethodName(), delAddr, val1, coin100), + false, + true, + nil, + }, + { + "delegate: verify remaining coins", + []sdk.ValAddress{val1, val2}, + []sdk.ValAddress{}, + stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, + &coin100, + createSrvMsgDelegate(delAuth.MethodName(), delAddr, val1, coin50), + false, + false, + &stakingtypes.StakeAuthorization{ + Validators: &stakingtypes.StakeAuthorization_AllowList{ + AllowList: &stakingtypes.StakeAuthorization_Validators{Address: validators1_2}, + }, MaxTokens: &coin50, AuthorizationType: stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE}, + }, + { + "delegate: testing with invalid validator", + []sdk.ValAddress{val1, val2}, + []sdk.ValAddress{}, + stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, + &coin100, + createSrvMsgDelegate(delAuth.MethodName(), delAddr, val3, coin100), + true, + false, + nil, + }, + { + "delegate: testing delegate without spent limit", + []sdk.ValAddress{val1, val2}, + []sdk.ValAddress{}, + stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, + nil, + createSrvMsgDelegate(delAuth.MethodName(), delAddr, val2, coin100), + false, + false, + &stakingtypes.StakeAuthorization{ + Validators: &stakingtypes.StakeAuthorization_AllowList{ + AllowList: &stakingtypes.StakeAuthorization_Validators{Address: validators1_2}, + }, MaxTokens: nil, AuthorizationType: stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE}, + }, + { + "delegate: fail validator denied", + []sdk.ValAddress{}, + []sdk.ValAddress{val1}, + stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_DELEGATE, + nil, + createSrvMsgDelegate(delAuth.MethodName(), delAddr, val1, coin100), + true, + false, + nil, + }, + + { + "undelegate: expect 0 remaining coins", + []sdk.ValAddress{val1, val2}, + []sdk.ValAddress{}, + stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_UNDELEGATE, + &coin100, + createSrvMsgUndelegate(undelAuth.MethodName(), delAddr, val1, coin100), + false, + true, + nil, + }, + { + "undelegate: verify remaining coins", + []sdk.ValAddress{val1, val2}, + []sdk.ValAddress{}, + stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_UNDELEGATE, + &coin100, + createSrvMsgUndelegate(undelAuth.MethodName(), delAddr, val1, coin50), + false, + false, + &stakingtypes.StakeAuthorization{ + Validators: &stakingtypes.StakeAuthorization_AllowList{ + AllowList: &stakingtypes.StakeAuthorization_Validators{Address: validators1_2}, + }, MaxTokens: &coin50, AuthorizationType: stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_UNDELEGATE}, + }, + { + "undelegate: testing with invalid validator", + []sdk.ValAddress{val1, val2}, + []sdk.ValAddress{}, + stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_UNDELEGATE, + &coin100, + createSrvMsgUndelegate(undelAuth.MethodName(), delAddr, val3, coin100), + true, + false, + nil, + }, + { + "undelegate: testing delegate without spent limit", + []sdk.ValAddress{val1, val2}, + []sdk.ValAddress{}, + stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_UNDELEGATE, + nil, + createSrvMsgUndelegate(undelAuth.MethodName(), delAddr, val2, coin100), + false, + false, + &stakingtypes.StakeAuthorization{ + Validators: &stakingtypes.StakeAuthorization_AllowList{ + AllowList: &stakingtypes.StakeAuthorization_Validators{Address: validators1_2}, + }, MaxTokens: nil, AuthorizationType: stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_UNDELEGATE}, + }, + { + "undelegate: fail cannot undelegate, permission denied", + []sdk.ValAddress{}, + []sdk.ValAddress{val1}, + stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_UNDELEGATE, + &coin100, + createSrvMsgUndelegate(undelAuth.MethodName(), delAddr, val1, coin100), + true, + false, + nil, + }, + + { + "redelegate: expect 0 remaining coins", + []sdk.ValAddress{val1, val2}, + []sdk.ValAddress{}, + stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_REDELEGATE, + &coin100, + createSrvMsgUndelegate(undelAuth.MethodName(), delAddr, val1, coin100), + false, + true, + nil, + }, + { + "redelegate: verify remaining coins", + []sdk.ValAddress{val1, val2}, + []sdk.ValAddress{}, + stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_REDELEGATE, + &coin100, + createSrvMsgReDelegate(undelAuth.MethodName(), delAddr, val1, coin50), + false, + false, + &stakingtypes.StakeAuthorization{ + Validators: &stakingtypes.StakeAuthorization_AllowList{ + AllowList: &stakingtypes.StakeAuthorization_Validators{Address: validators1_2}, + }, MaxTokens: &coin50, AuthorizationType: stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_REDELEGATE}, + }, + { + "redelegate: testing with invalid validator", + []sdk.ValAddress{val1, val2}, + []sdk.ValAddress{}, + stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_REDELEGATE, + &coin100, + createSrvMsgReDelegate(undelAuth.MethodName(), delAddr, val3, coin100), + true, + false, + nil, + }, + { + "redelegate: testing delegate without spent limit", + []sdk.ValAddress{val1, val2}, + []sdk.ValAddress{}, + stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_REDELEGATE, + nil, + createSrvMsgReDelegate(undelAuth.MethodName(), delAddr, val2, coin100), + false, + false, + &stakingtypes.StakeAuthorization{ + Validators: &stakingtypes.StakeAuthorization_AllowList{ + AllowList: &stakingtypes.StakeAuthorization_Validators{Address: validators1_2}, + }, MaxTokens: nil, AuthorizationType: stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_REDELEGATE}, + }, + { + "redelegate: fail cannot undelegate, permission denied", + []sdk.ValAddress{}, + []sdk.ValAddress{val1}, + stakingtypes.AuthorizationType_AUTHORIZATION_TYPE_REDELEGATE, + &coin100, + createSrvMsgReDelegate(undelAuth.MethodName(), delAddr, val1, coin100), + true, + false, + nil, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.msg, func(t *testing.T) { + delAuth, err := stakingtypes.NewStakeAuthorization(tc.allowed, tc.denied, tc.msgType, tc.limit) + require.NoError(t, err) + updated, del, err := delAuth.Accept(tc.srvMsg, tmproto.Header{}) + if tc.expectErr { + require.Error(t, err) + require.Equal(t, tc.isDelete, del) + } else { + require.NoError(t, err) + require.Equal(t, tc.isDelete, del) + if tc.updatedAuthorization != nil { + require.Equal(t, tc.updatedAuthorization.String(), updated.String()) + } + } + }) + } +} + +func createSrvMsgUndelegate(methodName string, delAddr sdk.AccAddress, valAddr sdk.ValAddress, amount sdk.Coin) sdk.ServiceMsg { + msg := stakingtypes.NewMsgUndelegate(delAddr, valAddr, amount) + return sdk.ServiceMsg{ + MethodName: methodName, + Request: msg, + } +} + +func createSrvMsgReDelegate(methodName string, delAddr sdk.AccAddress, valAddr sdk.ValAddress, amount sdk.Coin) sdk.ServiceMsg { + msg := stakingtypes.NewMsgBeginRedelegate(delAddr, valAddr, valAddr, amount) + return sdk.ServiceMsg{ + MethodName: methodName, + Request: msg, + } +} + +func createSrvMsgDelegate(methodName string, delAddr sdk.AccAddress, valAddr sdk.ValAddress, amount sdk.Coin) sdk.ServiceMsg { + msg := stakingtypes.NewMsgDelegate(delAddr, valAddr, amount) + return sdk.ServiceMsg{ + MethodName: methodName, + Request: msg, + } +} diff --git a/x/staking/types/staking.pb.go b/x/staking/types/staking.pb.go index 45b30b7a0e5e..36b5a0b666d6 100644 --- a/x/staking/types/staking.pb.go +++ b/x/staking/types/staking.pb.go @@ -1260,608 +1260,621 @@ func (this *Pool) Description() (desc *github_com_gogo_protobuf_protoc_gen_gogo_ func StakingDescription() (desc *github_com_gogo_protobuf_protoc_gen_gogo_descriptor.FileDescriptorSet) { d := &github_com_gogo_protobuf_protoc_gen_gogo_descriptor.FileDescriptorSet{} var gzipped = []byte{ - // 9603 bytes of a gzipped FileDescriptorSet - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x7d, 0x6d, 0x70, 0x24, 0xd7, - 0x71, 0xd8, 0xcd, 0xee, 0x02, 0xd8, 0x6d, 0x2c, 0x80, 0xc5, 0x03, 0xee, 0x6e, 0x6f, 0x79, 0x04, - 0xc0, 0xe1, 0xd7, 0xf1, 0x48, 0x02, 0xe4, 0x91, 0x77, 0x24, 0xf7, 0x24, 0xd2, 0x58, 0x60, 0x0f, - 0x07, 0x1e, 0xbe, 0x38, 0x00, 0x8e, 0xd4, 0x87, 0xb3, 0x35, 0x98, 0x7d, 0x58, 0x0c, 0xb1, 0x3b, - 0x33, 0x9c, 0x99, 0xbd, 0x3b, 0x50, 0x52, 0x15, 0x2d, 0x29, 0x8a, 0x44, 0xc7, 0x91, 0x14, 0xb9, - 0x1c, 0x89, 0xd6, 0x29, 0x92, 0xe5, 0x44, 0x8e, 0xac, 0xc4, 0x1f, 0x52, 0x94, 0x38, 0x49, 0x55, - 0xa4, 0x24, 0x8e, 0x25, 0xa5, 0xe2, 0x92, 0x2a, 0xae, 0xc4, 0x71, 0x25, 0x67, 0x87, 0x52, 0x39, - 0x8c, 0xa2, 0xc4, 0xf2, 0x59, 0x4e, 0x9c, 0x52, 0xa5, 0x92, 0x7a, 0x5f, 0xf3, 0xb5, 0x1f, 0xb3, - 0x0b, 0xdd, 0x49, 0x72, 0x9c, 0x5f, 0xd8, 0xd7, 0xaf, 0xbb, 0x5f, 0xbf, 0x7e, 0xfd, 0xba, 0xfb, - 0x7d, 0x0d, 0xe0, 0x9f, 0x9f, 0x87, 0x99, 0x9a, 0x69, 0xd6, 0xea, 0x78, 0xce, 0xb2, 0x4d, 0xd7, - 0xdc, 0x69, 0xee, 0xce, 0x55, 0xb1, 0xa3, 0xd9, 0xba, 0xe5, 0x9a, 0xf6, 0x2c, 0x85, 0xa1, 0x31, - 0x86, 0x31, 0x2b, 0x30, 0xe4, 0x55, 0x18, 0xbf, 0xa0, 0xd7, 0xf1, 0xa2, 0x87, 0xb8, 0x89, 0x5d, - 0xf4, 0x24, 0xa4, 0x76, 0xf5, 0x3a, 0xce, 0x4b, 0x33, 0xc9, 0x53, 0xc3, 0x67, 0xee, 0x99, 0x8d, - 0x10, 0xcd, 0x86, 0x29, 0x36, 0x08, 0x58, 0xa1, 0x14, 0xf2, 0xb7, 0x52, 0x30, 0xd1, 0xa6, 0x16, - 0x21, 0x48, 0x19, 0x6a, 0x83, 0x70, 0x94, 0x4e, 0x65, 0x14, 0xfa, 0x1b, 0xe5, 0x61, 0xc8, 0x52, - 0xb5, 0x7d, 0xb5, 0x86, 0xf3, 0x09, 0x0a, 0x16, 0x45, 0x34, 0x05, 0x50, 0xc5, 0x16, 0x36, 0xaa, - 0xd8, 0xd0, 0x0e, 0xf2, 0xc9, 0x99, 0xe4, 0xa9, 0x8c, 0x12, 0x80, 0xa0, 0x07, 0x61, 0xdc, 0x6a, - 0xee, 0xd4, 0x75, 0xad, 0x12, 0x40, 0x83, 0x99, 0xe4, 0xa9, 0x01, 0x25, 0xc7, 0x2a, 0x16, 0x7d, - 0xe4, 0xfb, 0x61, 0xec, 0x2a, 0x56, 0xf7, 0x83, 0xa8, 0xc3, 0x14, 0x75, 0x94, 0x80, 0x03, 0x88, - 0x0b, 0x90, 0x6d, 0x60, 0xc7, 0x51, 0x6b, 0xb8, 0xe2, 0x1e, 0x58, 0x38, 0x9f, 0xa2, 0xbd, 0x9f, - 0x69, 0xe9, 0x7d, 0xb4, 0xe7, 0xc3, 0x9c, 0x6a, 0xeb, 0xc0, 0xc2, 0x68, 0x1e, 0x32, 0xd8, 0x68, - 0x36, 0x18, 0x87, 0x81, 0x0e, 0xfa, 0x2b, 0x1b, 0xcd, 0x46, 0x94, 0x4b, 0x9a, 0x90, 0x71, 0x16, - 0x43, 0x0e, 0xb6, 0xaf, 0xe8, 0x1a, 0xce, 0x0f, 0x52, 0x06, 0xf7, 0xb7, 0x30, 0xd8, 0x64, 0xf5, - 0x51, 0x1e, 0x82, 0x0e, 0x2d, 0x40, 0x06, 0x5f, 0x73, 0xb1, 0xe1, 0xe8, 0xa6, 0x91, 0x1f, 0xa2, - 0x4c, 0xee, 0x6d, 0x33, 0x8a, 0xb8, 0x5e, 0x8d, 0xb2, 0xf0, 0xe9, 0xd0, 0x39, 0x18, 0x32, 0x2d, - 0x57, 0x37, 0x0d, 0x27, 0x9f, 0x9e, 0x91, 0x4e, 0x0d, 0x9f, 0x39, 0xd9, 0xd6, 0x10, 0xd6, 0x19, - 0x8e, 0x22, 0x90, 0xd1, 0x32, 0xe4, 0x1c, 0xb3, 0x69, 0x6b, 0xb8, 0xa2, 0x99, 0x55, 0x5c, 0xd1, - 0x8d, 0x5d, 0x33, 0x9f, 0xa1, 0x0c, 0xa6, 0x5b, 0x3b, 0x42, 0x11, 0x17, 0xcc, 0x2a, 0x5e, 0x36, - 0x76, 0x4d, 0x65, 0xd4, 0x09, 0x95, 0xd1, 0x31, 0x18, 0x74, 0x0e, 0x0c, 0x57, 0xbd, 0x96, 0xcf, - 0x52, 0x0b, 0xe1, 0x25, 0xf9, 0x37, 0x06, 0x61, 0xac, 0x17, 0x13, 0x3b, 0x0f, 0x03, 0xbb, 0xa4, - 0x97, 0xf9, 0x44, 0x3f, 0x3a, 0x60, 0x34, 0x61, 0x25, 0x0e, 0x1e, 0x52, 0x89, 0xf3, 0x30, 0x6c, - 0x60, 0xc7, 0xc5, 0x55, 0x66, 0x11, 0xc9, 0x1e, 0x6d, 0x0a, 0x18, 0x51, 0xab, 0x49, 0xa5, 0x0e, - 0x65, 0x52, 0x2f, 0xc0, 0x98, 0x27, 0x52, 0xc5, 0x56, 0x8d, 0x9a, 0xb0, 0xcd, 0xb9, 0x38, 0x49, - 0x66, 0xcb, 0x82, 0x4e, 0x21, 0x64, 0xca, 0x28, 0x0e, 0x95, 0xd1, 0x22, 0x80, 0x69, 0x60, 0x73, - 0xb7, 0x52, 0xc5, 0x5a, 0x3d, 0x9f, 0xee, 0xa0, 0xa5, 0x75, 0x82, 0xd2, 0xa2, 0x25, 0x93, 0x41, - 0xb5, 0x3a, 0x7a, 0xca, 0x37, 0xb5, 0xa1, 0x0e, 0x96, 0xb2, 0xca, 0x26, 0x59, 0x8b, 0xb5, 0x6d, - 0xc3, 0xa8, 0x8d, 0x89, 0xdd, 0xe3, 0x2a, 0xef, 0x59, 0x86, 0x0a, 0x31, 0x1b, 0xdb, 0x33, 0x85, - 0x93, 0xb1, 0x8e, 0x8d, 0xd8, 0xc1, 0x22, 0xba, 0x1b, 0x3c, 0x40, 0x85, 0x9a, 0x15, 0x50, 0x2f, - 0x94, 0x15, 0xc0, 0x35, 0xb5, 0x81, 0x0b, 0x2f, 0xc3, 0x68, 0x58, 0x3d, 0x68, 0x12, 0x06, 0x1c, - 0x57, 0xb5, 0x5d, 0x6a, 0x85, 0x03, 0x0a, 0x2b, 0xa0, 0x1c, 0x24, 0xb1, 0x51, 0xa5, 0x5e, 0x6e, - 0x40, 0x21, 0x3f, 0xd1, 0x4f, 0xf8, 0x1d, 0x4e, 0xd2, 0x0e, 0xdf, 0xd7, 0x3a, 0xa2, 0x21, 0xce, - 0xd1, 0x7e, 0x17, 0x9e, 0x80, 0x91, 0x50, 0x07, 0x7a, 0x6d, 0x5a, 0x7e, 0x27, 0x1c, 0x6d, 0xcb, - 0x1a, 0xbd, 0x00, 0x93, 0x4d, 0x43, 0x37, 0x5c, 0x6c, 0x5b, 0x36, 0x26, 0x16, 0xcb, 0x9a, 0xca, - 0xff, 0xe7, 0xa1, 0x0e, 0x36, 0xb7, 0x1d, 0xc4, 0x66, 0x5c, 0x94, 0x89, 0x66, 0x2b, 0xf0, 0x74, - 0x26, 0xfd, 0xc6, 0x50, 0xee, 0x95, 0x57, 0x5e, 0x79, 0x25, 0x21, 0x7f, 0x79, 0x10, 0x26, 0xdb, - 0xcd, 0x99, 0xb6, 0xd3, 0xf7, 0x18, 0x0c, 0x1a, 0xcd, 0xc6, 0x0e, 0xb6, 0xa9, 0x92, 0x06, 0x14, - 0x5e, 0x42, 0xf3, 0x30, 0x50, 0x57, 0x77, 0x70, 0x3d, 0x9f, 0x9a, 0x91, 0x4e, 0x8d, 0x9e, 0x79, - 0xb0, 0xa7, 0x59, 0x39, 0xbb, 0x42, 0x48, 0x14, 0x46, 0x89, 0x9e, 0x86, 0x14, 0x77, 0xd1, 0x84, - 0xc3, 0xe9, 0xde, 0x38, 0x90, 0xb9, 0xa4, 0x50, 0x3a, 0x74, 0x07, 0x64, 0xc8, 0x5f, 0x66, 0x1b, - 0x83, 0x54, 0xe6, 0x34, 0x01, 0x10, 0xbb, 0x40, 0x05, 0x48, 0xd3, 0x69, 0x52, 0xc5, 0x22, 0xb4, - 0x79, 0x65, 0x62, 0x58, 0x55, 0xbc, 0xab, 0x36, 0xeb, 0x6e, 0xe5, 0x8a, 0x5a, 0x6f, 0x62, 0x6a, - 0xf0, 0x19, 0x25, 0xcb, 0x81, 0x97, 0x09, 0x0c, 0x4d, 0xc3, 0x30, 0x9b, 0x55, 0xba, 0x51, 0xc5, - 0xd7, 0xa8, 0xf7, 0x1c, 0x50, 0xd8, 0x44, 0x5b, 0x26, 0x10, 0xd2, 0xfc, 0x8b, 0x8e, 0x69, 0x08, - 0xd3, 0xa4, 0x4d, 0x10, 0x00, 0x6d, 0xfe, 0x89, 0xa8, 0xe3, 0xbe, 0xb3, 0x7d, 0xf7, 0x5a, 0xe6, - 0xd2, 0xfd, 0x30, 0x46, 0x31, 0x1e, 0xe3, 0x43, 0xaf, 0xd6, 0xf3, 0xe3, 0x33, 0xd2, 0xa9, 0xb4, - 0x32, 0xca, 0xc0, 0xeb, 0x1c, 0x2a, 0x7f, 0x31, 0x01, 0x29, 0xea, 0x58, 0xc6, 0x60, 0x78, 0xeb, - 0x2d, 0x1b, 0xe5, 0xca, 0xe2, 0xfa, 0x76, 0x69, 0xa5, 0x9c, 0x93, 0xd0, 0x28, 0x00, 0x05, 0x5c, - 0x58, 0x59, 0x9f, 0xdf, 0xca, 0x25, 0xbc, 0xf2, 0xf2, 0xda, 0xd6, 0xb9, 0xc7, 0x73, 0x49, 0x8f, - 0x60, 0x9b, 0x01, 0x52, 0x41, 0x84, 0xc7, 0xce, 0xe4, 0x06, 0x50, 0x0e, 0xb2, 0x8c, 0xc1, 0xf2, - 0x0b, 0xe5, 0xc5, 0x73, 0x8f, 0xe7, 0x06, 0xc3, 0x90, 0xc7, 0xce, 0xe4, 0x86, 0xd0, 0x08, 0x64, - 0x28, 0xa4, 0xb4, 0xbe, 0xbe, 0x92, 0x4b, 0x7b, 0x3c, 0x37, 0xb7, 0x94, 0xe5, 0xb5, 0xa5, 0x5c, - 0xc6, 0xe3, 0xb9, 0xa4, 0xac, 0x6f, 0x6f, 0xe4, 0xc0, 0xe3, 0xb0, 0x5a, 0xde, 0xdc, 0x9c, 0x5f, - 0x2a, 0xe7, 0x86, 0x3d, 0x8c, 0xd2, 0x5b, 0xb6, 0xca, 0x9b, 0xb9, 0x6c, 0x48, 0xac, 0xc7, 0xce, - 0xe4, 0x46, 0xbc, 0x26, 0xca, 0x6b, 0xdb, 0xab, 0xb9, 0x51, 0x34, 0x0e, 0x23, 0xac, 0x09, 0x21, - 0xc4, 0x58, 0x04, 0x74, 0xee, 0xf1, 0x5c, 0xce, 0x17, 0x84, 0x71, 0x19, 0x0f, 0x01, 0xce, 0x3d, - 0x9e, 0x43, 0xf2, 0x02, 0x0c, 0x50, 0x33, 0x44, 0x08, 0x46, 0x57, 0xe6, 0x4b, 0xe5, 0x95, 0xca, - 0xfa, 0xc6, 0xd6, 0xf2, 0xfa, 0xda, 0xfc, 0x4a, 0x4e, 0xf2, 0x61, 0x4a, 0xf9, 0xb9, 0xed, 0x65, - 0xa5, 0xbc, 0x98, 0x4b, 0x04, 0x61, 0x1b, 0xe5, 0xf9, 0xad, 0xf2, 0x62, 0x2e, 0x29, 0x6b, 0x30, - 0xd9, 0xce, 0xa1, 0xb6, 0x9d, 0x42, 0x01, 0x5b, 0x48, 0x74, 0xb0, 0x05, 0xca, 0x2b, 0x6a, 0x0b, - 0xf2, 0x37, 0x13, 0x30, 0xd1, 0x26, 0xa8, 0xb4, 0x6d, 0xe4, 0x19, 0x18, 0x60, 0xb6, 0xcc, 0xc2, - 0xec, 0x03, 0x6d, 0xa3, 0x13, 0xb5, 0xec, 0x96, 0x50, 0x4b, 0xe9, 0x82, 0xa9, 0x46, 0xb2, 0x43, - 0xaa, 0x41, 0x58, 0xb4, 0x18, 0xec, 0x4f, 0xb6, 0x38, 0x7f, 0x16, 0x1f, 0xcf, 0xf5, 0x12, 0x1f, - 0x29, 0xac, 0xbf, 0x20, 0x30, 0xd0, 0x26, 0x08, 0x9c, 0x87, 0xf1, 0x16, 0x46, 0x3d, 0x3b, 0xe3, - 0xf7, 0x48, 0x90, 0xef, 0xa4, 0x9c, 0x18, 0x97, 0x98, 0x08, 0xb9, 0xc4, 0xf3, 0x51, 0x0d, 0xde, - 0xd5, 0x79, 0x10, 0x5a, 0xc6, 0xfa, 0x33, 0x12, 0x1c, 0x6b, 0x9f, 0x52, 0xb6, 0x95, 0xe1, 0x69, - 0x18, 0x6c, 0x60, 0x77, 0xcf, 0x14, 0x69, 0xd5, 0x7d, 0x6d, 0x82, 0x35, 0xa9, 0x8e, 0x0e, 0x36, - 0xa7, 0x0a, 0x46, 0xfb, 0x64, 0xa7, 0xbc, 0x90, 0x49, 0xd3, 0x22, 0xe9, 0x07, 0x12, 0x70, 0xb4, - 0x2d, 0xf3, 0xb6, 0x82, 0xde, 0x09, 0xa0, 0x1b, 0x56, 0xd3, 0x65, 0xa9, 0x13, 0xf3, 0xc4, 0x19, - 0x0a, 0xa1, 0xce, 0x8b, 0x78, 0xd9, 0xa6, 0xeb, 0xd5, 0x27, 0x69, 0x3d, 0x30, 0x10, 0x45, 0x78, - 0xd2, 0x17, 0x34, 0x45, 0x05, 0x9d, 0xea, 0xd0, 0xd3, 0x16, 0xc3, 0x7c, 0x04, 0x72, 0x5a, 0x5d, - 0xc7, 0x86, 0x5b, 0x71, 0x5c, 0x1b, 0xab, 0x0d, 0xdd, 0xa8, 0xd1, 0x50, 0x93, 0x2e, 0x0e, 0xec, - 0xaa, 0x75, 0x07, 0x2b, 0x63, 0xac, 0x7a, 0x53, 0xd4, 0x12, 0x0a, 0x6a, 0x40, 0x76, 0x80, 0x62, - 0x30, 0x44, 0xc1, 0xaa, 0x3d, 0x0a, 0xf9, 0xc3, 0x19, 0x18, 0x0e, 0x24, 0xe0, 0xe8, 0x2e, 0xc8, - 0xbe, 0xa8, 0x5e, 0x51, 0x2b, 0x62, 0x51, 0xc5, 0x34, 0x31, 0x4c, 0x60, 0x1b, 0x7c, 0x61, 0xf5, - 0x08, 0x4c, 0x52, 0x14, 0xb3, 0xe9, 0x62, 0xbb, 0xa2, 0xd5, 0x55, 0xc7, 0xa1, 0x4a, 0x4b, 0x53, - 0x54, 0x44, 0xea, 0xd6, 0x49, 0xd5, 0x82, 0xa8, 0x41, 0x67, 0x61, 0x82, 0x52, 0x34, 0x9a, 0x75, - 0x57, 0xb7, 0xea, 0xb8, 0x42, 0x96, 0x79, 0x0e, 0x0d, 0x39, 0x9e, 0x64, 0xe3, 0x04, 0x63, 0x95, - 0x23, 0x10, 0x89, 0x1c, 0xb4, 0x08, 0x77, 0x52, 0xb2, 0x1a, 0x36, 0xb0, 0xad, 0xba, 0xb8, 0x82, - 0x5f, 0x6a, 0xaa, 0x75, 0xa7, 0xa2, 0x1a, 0xd5, 0xca, 0x9e, 0xea, 0xec, 0xe5, 0x27, 0x09, 0x83, - 0x52, 0x22, 0x2f, 0x29, 0x27, 0x08, 0xe2, 0x12, 0xc7, 0x2b, 0x53, 0xb4, 0x79, 0xa3, 0x7a, 0x51, - 0x75, 0xf6, 0x50, 0x11, 0x8e, 0x51, 0x2e, 0x8e, 0x6b, 0xeb, 0x46, 0xad, 0xa2, 0xed, 0x61, 0x6d, - 0xbf, 0xd2, 0x74, 0x77, 0x9f, 0xcc, 0xdf, 0x11, 0x6c, 0x9f, 0x4a, 0xb8, 0x49, 0x71, 0x16, 0x08, - 0xca, 0xb6, 0xbb, 0xfb, 0x24, 0xda, 0x84, 0x2c, 0x19, 0x8c, 0x86, 0xfe, 0x32, 0xae, 0xec, 0x9a, - 0x36, 0x8d, 0xa1, 0xa3, 0x6d, 0x5c, 0x53, 0x40, 0x83, 0xb3, 0xeb, 0x9c, 0x60, 0xd5, 0xac, 0xe2, - 0xe2, 0xc0, 0xe6, 0x46, 0xb9, 0xbc, 0xa8, 0x0c, 0x0b, 0x2e, 0x17, 0x4c, 0x9b, 0x18, 0x54, 0xcd, - 0xf4, 0x14, 0x3c, 0xcc, 0x0c, 0xaa, 0x66, 0x0a, 0xf5, 0x9e, 0x85, 0x09, 0x4d, 0x63, 0x7d, 0xd6, - 0xb5, 0x0a, 0x5f, 0x8c, 0x39, 0xf9, 0x5c, 0x48, 0x59, 0x9a, 0xb6, 0xc4, 0x10, 0xb8, 0x8d, 0x3b, - 0xe8, 0x29, 0x38, 0xea, 0x2b, 0x2b, 0x48, 0x38, 0xde, 0xd2, 0xcb, 0x28, 0xe9, 0x59, 0x98, 0xb0, - 0x0e, 0x5a, 0x09, 0x51, 0xa8, 0x45, 0xeb, 0x20, 0x4a, 0xf6, 0x04, 0x4c, 0x5a, 0x7b, 0x56, 0x2b, - 0xdd, 0xe9, 0x20, 0x1d, 0xb2, 0xf6, 0xac, 0x28, 0xe1, 0xbd, 0x74, 0x65, 0x6e, 0x63, 0x4d, 0x75, - 0x71, 0x35, 0x7f, 0x3c, 0x88, 0x1e, 0xa8, 0x40, 0xb3, 0x90, 0xd3, 0xb4, 0x0a, 0x36, 0xd4, 0x9d, - 0x3a, 0xae, 0xa8, 0x36, 0x36, 0x54, 0x27, 0x3f, 0x4d, 0x91, 0x53, 0xae, 0xdd, 0xc4, 0xca, 0xa8, - 0xa6, 0x95, 0x69, 0xe5, 0x3c, 0xad, 0x43, 0xa7, 0x61, 0xdc, 0xdc, 0x79, 0x51, 0x63, 0x16, 0x59, - 0xb1, 0x6c, 0xbc, 0xab, 0x5f, 0xcb, 0xdf, 0x43, 0xd5, 0x3b, 0x46, 0x2a, 0xa8, 0x3d, 0x6e, 0x50, - 0x30, 0x7a, 0x00, 0x72, 0x9a, 0xb3, 0xa7, 0xda, 0x16, 0x75, 0xc9, 0x8e, 0xa5, 0x6a, 0x38, 0x7f, - 0x2f, 0x43, 0x65, 0xf0, 0x35, 0x01, 0x26, 0x33, 0xc2, 0xb9, 0xaa, 0xef, 0xba, 0x82, 0xe3, 0xfd, - 0x6c, 0x46, 0x50, 0x18, 0xe7, 0x76, 0x0a, 0x72, 0x44, 0x13, 0xa1, 0x86, 0x4f, 0x51, 0xb4, 0x51, - 0x6b, 0xcf, 0x0a, 0xb6, 0x7b, 0x37, 0x8c, 0x10, 0x4c, 0xbf, 0xd1, 0x07, 0x58, 0xe2, 0x66, 0xed, - 0x05, 0x5a, 0x7c, 0x1c, 0x8e, 0x11, 0xa4, 0x06, 0x76, 0xd5, 0xaa, 0xea, 0xaa, 0x01, 0xec, 0x87, - 0x28, 0x36, 0x51, 0xfb, 0x2a, 0xaf, 0x0c, 0xc9, 0x69, 0x37, 0x77, 0x0e, 0x3c, 0xc3, 0x7a, 0x98, - 0xc9, 0x49, 0x60, 0xc2, 0xb4, 0x6e, 0x5b, 0x72, 0x2e, 0x17, 0x21, 0x1b, 0xb4, 0x7b, 0x94, 0x01, - 0x66, 0xf9, 0x39, 0x89, 0x24, 0x41, 0x0b, 0xeb, 0x8b, 0x24, 0x7d, 0x79, 0x6b, 0x39, 0x97, 0x20, - 0x69, 0xd4, 0xca, 0xf2, 0x56, 0xb9, 0xa2, 0x6c, 0xaf, 0x6d, 0x2d, 0xaf, 0x96, 0x73, 0xc9, 0x40, - 0x62, 0xff, 0x6c, 0x2a, 0x7d, 0x5f, 0xee, 0x7e, 0xf9, 0x1b, 0x09, 0x18, 0x0d, 0xaf, 0xd4, 0xd0, - 0x9b, 0xe0, 0xb8, 0xd8, 0x56, 0x71, 0xb0, 0x5b, 0xb9, 0xaa, 0xdb, 0x74, 0x42, 0x36, 0x54, 0x16, - 0x1c, 0x3d, 0xfb, 0x99, 0xe4, 0x58, 0x9b, 0xd8, 0x7d, 0x5e, 0xb7, 0xc9, 0x74, 0x6b, 0xa8, 0x2e, - 0x5a, 0x81, 0x69, 0xc3, 0xac, 0x38, 0xae, 0x6a, 0x54, 0x55, 0xbb, 0x5a, 0xf1, 0x37, 0xb4, 0x2a, - 0xaa, 0xa6, 0x61, 0xc7, 0x31, 0x59, 0x20, 0xf4, 0xb8, 0x9c, 0x34, 0xcc, 0x4d, 0x8e, 0xec, 0x47, - 0x88, 0x79, 0x8e, 0x1a, 0x31, 0xdf, 0x64, 0x27, 0xf3, 0xbd, 0x03, 0x32, 0x0d, 0xd5, 0xaa, 0x60, - 0xc3, 0xb5, 0x0f, 0x68, 0x7e, 0x9e, 0x56, 0xd2, 0x0d, 0xd5, 0x2a, 0x93, 0xf2, 0x0f, 0x65, 0x99, - 0xf4, 0x6c, 0x2a, 0x9d, 0xce, 0x65, 0x9e, 0x4d, 0xa5, 0x33, 0x39, 0x90, 0x5f, 0x4f, 0x42, 0x36, - 0x98, 0xaf, 0x93, 0xe5, 0x8f, 0x46, 0x23, 0x96, 0x44, 0x7d, 0xda, 0xdd, 0x5d, 0xb3, 0xfb, 0xd9, - 0x05, 0x12, 0xca, 0x8a, 0x83, 0x2c, 0x39, 0x56, 0x18, 0x25, 0x49, 0x23, 0x88, 0xb1, 0x61, 0x96, - 0x8c, 0xa4, 0x15, 0x5e, 0x42, 0x4b, 0x30, 0xf8, 0xa2, 0x43, 0x79, 0x0f, 0x52, 0xde, 0xf7, 0x74, - 0xe7, 0xfd, 0xec, 0x26, 0x65, 0x9e, 0x79, 0x76, 0xb3, 0xb2, 0xb6, 0xae, 0xac, 0xce, 0xaf, 0x28, - 0x9c, 0x1c, 0x9d, 0x80, 0x54, 0x5d, 0x7d, 0xf9, 0x20, 0x1c, 0xf4, 0x28, 0xa8, 0xd7, 0x41, 0x38, - 0x01, 0xa9, 0xab, 0x58, 0xdd, 0x0f, 0x87, 0x1a, 0x0a, 0xba, 0x8d, 0x93, 0x61, 0x0e, 0x06, 0xa8, - 0xbe, 0x10, 0x00, 0xd7, 0x58, 0xee, 0x08, 0x4a, 0x43, 0x6a, 0x61, 0x5d, 0x21, 0x13, 0x22, 0x07, - 0x59, 0x06, 0xad, 0x6c, 0x2c, 0x97, 0x17, 0xca, 0xb9, 0x84, 0x7c, 0x16, 0x06, 0x99, 0x12, 0xc8, - 0x64, 0xf1, 0xd4, 0x90, 0x3b, 0xc2, 0x8b, 0x9c, 0x87, 0x24, 0x6a, 0xb7, 0x57, 0x4b, 0x65, 0x25, - 0x97, 0x08, 0x0f, 0x75, 0x2a, 0x37, 0x20, 0x3b, 0x90, 0x0d, 0xe6, 0xe1, 0x3f, 0x9c, 0xc5, 0xf8, - 0x97, 0x24, 0x18, 0x0e, 0xe4, 0xd5, 0x24, 0x21, 0x52, 0xeb, 0x75, 0xf3, 0x6a, 0x45, 0xad, 0xeb, - 0xaa, 0xc3, 0x4d, 0x03, 0x28, 0x68, 0x9e, 0x40, 0x7a, 0x1d, 0xba, 0x1f, 0xd2, 0x14, 0x19, 0xc8, - 0x0d, 0xca, 0x9f, 0x90, 0x20, 0x17, 0x4d, 0x6c, 0x23, 0x62, 0x4a, 0x3f, 0x4a, 0x31, 0xe5, 0x8f, - 0x4b, 0x30, 0x1a, 0xce, 0x66, 0x23, 0xe2, 0xdd, 0xf5, 0x23, 0x15, 0xef, 0x0f, 0x12, 0x30, 0x12, - 0xca, 0x61, 0x7b, 0x95, 0xee, 0x25, 0x18, 0xd7, 0xab, 0xb8, 0x61, 0x99, 0x2e, 0x36, 0xb4, 0x83, - 0x4a, 0x1d, 0x5f, 0xc1, 0xf5, 0xbc, 0x4c, 0x9d, 0xc6, 0x5c, 0xf7, 0x2c, 0x79, 0x76, 0xd9, 0xa7, - 0x5b, 0x21, 0x64, 0xc5, 0x89, 0xe5, 0xc5, 0xf2, 0xea, 0xc6, 0xfa, 0x56, 0x79, 0x6d, 0xe1, 0x2d, - 0x95, 0xed, 0xb5, 0x4b, 0x6b, 0xeb, 0xcf, 0xaf, 0x29, 0x39, 0x3d, 0x82, 0x76, 0x1b, 0xa7, 0xfd, - 0x06, 0xe4, 0xa2, 0x42, 0xa1, 0xe3, 0xd0, 0x4e, 0xac, 0xdc, 0x11, 0x34, 0x01, 0x63, 0x6b, 0xeb, - 0x95, 0xcd, 0xe5, 0xc5, 0x72, 0xa5, 0x7c, 0xe1, 0x42, 0x79, 0x61, 0x6b, 0x93, 0xed, 0x7b, 0x78, - 0xd8, 0x5b, 0xa1, 0x09, 0x2e, 0xbf, 0x96, 0x84, 0x89, 0x36, 0x92, 0xa0, 0x79, 0xbe, 0x62, 0x61, - 0x8b, 0xa8, 0x87, 0x7b, 0x91, 0x7e, 0x96, 0xe4, 0x0c, 0x1b, 0xaa, 0xed, 0xf2, 0x05, 0xce, 0x03, - 0x40, 0xb4, 0x64, 0xb8, 0xfa, 0xae, 0x8e, 0x6d, 0xbe, 0x9f, 0xc4, 0x96, 0x31, 0x63, 0x3e, 0x9c, - 0x6d, 0x29, 0x3d, 0x04, 0xc8, 0x32, 0x1d, 0xdd, 0xd5, 0xaf, 0xe0, 0x8a, 0x6e, 0x88, 0xcd, 0x27, - 0xb2, 0xac, 0x49, 0x29, 0x39, 0x51, 0xb3, 0x6c, 0xb8, 0x1e, 0xb6, 0x81, 0x6b, 0x6a, 0x04, 0x9b, - 0x38, 0xf3, 0xa4, 0x92, 0x13, 0x35, 0x1e, 0xf6, 0x5d, 0x90, 0xad, 0x9a, 0x4d, 0x92, 0xeb, 0x31, - 0x3c, 0x12, 0x3b, 0x24, 0x65, 0x98, 0xc1, 0x3c, 0x14, 0x9e, 0xc5, 0xfb, 0xbb, 0x5e, 0x59, 0x65, - 0x98, 0xc1, 0x18, 0xca, 0xfd, 0x30, 0xa6, 0xd6, 0x6a, 0x36, 0x61, 0x2e, 0x18, 0xb1, 0x75, 0xc9, - 0xa8, 0x07, 0xa6, 0x88, 0x85, 0x67, 0x21, 0x2d, 0xf4, 0x40, 0x42, 0x35, 0xd1, 0x44, 0xc5, 0x62, - 0x8b, 0xed, 0xc4, 0xa9, 0x8c, 0x92, 0x36, 0x44, 0xe5, 0x5d, 0x90, 0xd5, 0x9d, 0x8a, 0xbf, 0x89, - 0x9f, 0x98, 0x49, 0x9c, 0x4a, 0x2b, 0xc3, 0xba, 0xe3, 0x6d, 0x80, 0xca, 0x9f, 0x49, 0xc0, 0x68, - 0xf8, 0x10, 0x02, 0x2d, 0x42, 0xba, 0x6e, 0x6a, 0x2a, 0x35, 0x2d, 0x76, 0x02, 0x76, 0x2a, 0xe6, - 0xdc, 0x62, 0x76, 0x85, 0xe3, 0x2b, 0x1e, 0x65, 0xe1, 0xb7, 0x25, 0x48, 0x0b, 0x30, 0x3a, 0x06, - 0x29, 0x4b, 0x75, 0xf7, 0x28, 0xbb, 0x81, 0x52, 0x22, 0x27, 0x29, 0xb4, 0x4c, 0xe0, 0x8e, 0xa5, - 0x1a, 0xd4, 0x04, 0x38, 0x9c, 0x94, 0xc9, 0xb8, 0xd6, 0xb1, 0x5a, 0xa5, 0x8b, 0x1e, 0xb3, 0xd1, - 0xc0, 0x86, 0xeb, 0x88, 0x71, 0xe5, 0xf0, 0x05, 0x0e, 0x46, 0x0f, 0xc2, 0xb8, 0x6b, 0xab, 0x7a, - 0x3d, 0x84, 0x9b, 0xa2, 0xb8, 0x39, 0x51, 0xe1, 0x21, 0x17, 0xe1, 0x84, 0xe0, 0x5b, 0xc5, 0xae, - 0xaa, 0xed, 0xe1, 0xaa, 0x4f, 0x34, 0x48, 0x37, 0x37, 0x8e, 0x73, 0x84, 0x45, 0x5e, 0x2f, 0x68, - 0xe5, 0x6f, 0x48, 0x30, 0x2e, 0x96, 0x69, 0x55, 0x4f, 0x59, 0xab, 0x00, 0xaa, 0x61, 0x98, 0x6e, - 0x50, 0x5d, 0xad, 0xa6, 0xdc, 0x42, 0x37, 0x3b, 0xef, 0x11, 0x29, 0x01, 0x06, 0x85, 0x06, 0x80, - 0x5f, 0xd3, 0x51, 0x6d, 0xd3, 0x30, 0xcc, 0x4f, 0x98, 0xe8, 0x31, 0x25, 0x5b, 0xd8, 0x03, 0x03, - 0x91, 0xf5, 0x1c, 0x9a, 0x84, 0x81, 0x1d, 0x5c, 0xd3, 0x0d, 0xbe, 0x6f, 0xcc, 0x0a, 0x62, 0xfb, - 0x25, 0xe5, 0x6d, 0xbf, 0x94, 0x3e, 0x28, 0xc1, 0x84, 0x66, 0x36, 0xa2, 0xf2, 0x96, 0x72, 0x91, - 0xdd, 0x05, 0xe7, 0xa2, 0xf4, 0xd6, 0xa7, 0x6b, 0xba, 0xbb, 0xd7, 0xdc, 0x99, 0xd5, 0xcc, 0xc6, - 0x5c, 0xcd, 0xac, 0xab, 0x46, 0xcd, 0x3f, 0x67, 0xa5, 0x3f, 0xb4, 0x87, 0x6b, 0xd8, 0x78, 0xb8, - 0x66, 0x06, 0x4e, 0x5d, 0xcf, 0xfb, 0x3f, 0xff, 0x4c, 0x92, 0x7e, 0x21, 0x91, 0x5c, 0xda, 0x28, - 0x7d, 0x36, 0x51, 0x58, 0x62, 0xcd, 0x6d, 0x08, 0xf5, 0x28, 0x78, 0xb7, 0x8e, 0x35, 0xd2, 0x65, - 0xf8, 0xf6, 0x83, 0x30, 0x59, 0x33, 0x6b, 0x26, 0xe5, 0x38, 0x47, 0x7e, 0xf1, 0x93, 0xdb, 0x8c, - 0x07, 0x2d, 0xc4, 0x1e, 0xf3, 0x16, 0xd7, 0x60, 0x82, 0x23, 0x57, 0xe8, 0xd1, 0x11, 0x5b, 0xd8, - 0xa0, 0xae, 0xbb, 0x6a, 0xf9, 0x5f, 0xfb, 0x16, 0x0d, 0xe8, 0xca, 0x38, 0x27, 0x25, 0x75, 0x6c, - 0xed, 0x53, 0x54, 0xe0, 0x68, 0x88, 0x1f, 0x9b, 0xb6, 0xd8, 0x8e, 0xe1, 0xf8, 0x9b, 0x9c, 0xe3, - 0x44, 0x80, 0xe3, 0x26, 0x27, 0x2d, 0x2e, 0xc0, 0x48, 0x3f, 0xbc, 0xfe, 0x25, 0xe7, 0x95, 0xc5, - 0x41, 0x26, 0x4b, 0x30, 0x46, 0x99, 0x68, 0x4d, 0xc7, 0x35, 0x1b, 0xd4, 0x27, 0x76, 0x67, 0xf3, - 0x5b, 0xdf, 0x62, 0xf3, 0x68, 0x94, 0x90, 0x2d, 0x78, 0x54, 0xc5, 0x22, 0xd0, 0xd3, 0xb2, 0x2a, - 0xd6, 0xea, 0x31, 0x1c, 0xbe, 0xc2, 0x05, 0xf1, 0xf0, 0x8b, 0x97, 0x61, 0x92, 0xfc, 0xa6, 0x2e, - 0x2b, 0x28, 0x49, 0xfc, 0x16, 0x5c, 0xfe, 0x1b, 0xef, 0x61, 0x53, 0x75, 0xc2, 0x63, 0x10, 0x90, - 0x29, 0x30, 0x8a, 0x35, 0xec, 0xba, 0xd8, 0x76, 0x2a, 0x6a, 0xbd, 0x9d, 0x78, 0x81, 0x3d, 0x8c, - 0xfc, 0xc7, 0xbe, 0x13, 0x1e, 0xc5, 0x25, 0x46, 0x39, 0x5f, 0xaf, 0x17, 0xb7, 0xe1, 0x78, 0x1b, - 0xab, 0xe8, 0x81, 0xe7, 0x6b, 0x9c, 0xe7, 0x64, 0x8b, 0x65, 0x10, 0xb6, 0x1b, 0x20, 0xe0, 0xde, - 0x58, 0xf6, 0xc0, 0xf3, 0xe7, 0x39, 0x4f, 0xc4, 0x69, 0xc5, 0x90, 0x12, 0x8e, 0xcf, 0xc2, 0xf8, - 0x15, 0x6c, 0xef, 0x98, 0x0e, 0xdf, 0x37, 0xea, 0x81, 0xdd, 0xc7, 0x39, 0xbb, 0x31, 0x4e, 0x48, - 0x37, 0x92, 0x08, 0xaf, 0xa7, 0x20, 0xbd, 0xab, 0x6a, 0xb8, 0x07, 0x16, 0xd7, 0x39, 0x8b, 0x21, - 0x82, 0x4f, 0x48, 0xe7, 0x21, 0x5b, 0x33, 0x79, 0xd4, 0x8a, 0x27, 0xff, 0x04, 0x27, 0x1f, 0x16, - 0x34, 0x9c, 0x85, 0x65, 0x5a, 0xcd, 0x3a, 0x09, 0x69, 0xf1, 0x2c, 0xfe, 0xa6, 0x60, 0x21, 0x68, - 0x38, 0x8b, 0x3e, 0xd4, 0xfa, 0x49, 0xc1, 0xc2, 0x09, 0xe8, 0xf3, 0x19, 0x18, 0x36, 0x8d, 0xfa, - 0x81, 0x69, 0xf4, 0x22, 0xc4, 0xa7, 0x38, 0x07, 0xe0, 0x24, 0x84, 0xc1, 0x79, 0xc8, 0xf4, 0x3a, - 0x10, 0x7f, 0xeb, 0x3b, 0x62, 0x7a, 0x88, 0x11, 0x58, 0x82, 0x31, 0xe1, 0xa0, 0x74, 0xd3, 0xe8, - 0x81, 0xc5, 0xdf, 0xe6, 0x2c, 0x46, 0x03, 0x64, 0xbc, 0x1b, 0x2e, 0x76, 0xdc, 0x1a, 0xee, 0x85, - 0xc9, 0x67, 0x44, 0x37, 0x38, 0x09, 0x57, 0xe5, 0x0e, 0x36, 0xb4, 0xbd, 0xde, 0x38, 0xfc, 0x92, - 0x50, 0xa5, 0xa0, 0x21, 0x2c, 0x16, 0x60, 0xa4, 0xa1, 0xda, 0xce, 0x9e, 0x5a, 0xef, 0x69, 0x38, - 0xfe, 0x0e, 0xe7, 0x91, 0xf5, 0x88, 0xb8, 0x46, 0x9a, 0x46, 0x3f, 0x6c, 0x3e, 0x2b, 0x34, 0x12, - 0x20, 0xe3, 0x53, 0xcf, 0x71, 0xe9, 0x26, 0x5b, 0x3f, 0xdc, 0x7e, 0x59, 0x4c, 0x3d, 0x46, 0xbb, - 0x1a, 0xe4, 0x78, 0x1e, 0x32, 0x8e, 0xfe, 0x72, 0x4f, 0x6c, 0x3e, 0x27, 0x46, 0x9a, 0x12, 0x10, - 0xe2, 0xb7, 0xc0, 0x89, 0xb6, 0x61, 0xa2, 0x07, 0x66, 0x7f, 0x97, 0x33, 0x3b, 0xd6, 0x26, 0x54, - 0x70, 0x97, 0xd0, 0x2f, 0xcb, 0xbf, 0x27, 0x5c, 0x02, 0x8e, 0xf0, 0xda, 0x20, 0xeb, 0x08, 0x47, - 0xdd, 0xed, 0x4f, 0x6b, 0xbf, 0x22, 0xb4, 0xc6, 0x68, 0x43, 0x5a, 0xdb, 0x82, 0x63, 0x9c, 0x63, - 0x7f, 0xe3, 0xfa, 0xab, 0xc2, 0xb1, 0x32, 0xea, 0xed, 0xf0, 0xe8, 0xbe, 0x0d, 0x0a, 0x9e, 0x3a, - 0x45, 0xc2, 0xea, 0x54, 0x1a, 0xaa, 0xd5, 0x03, 0xe7, 0x5f, 0xe3, 0x9c, 0x85, 0xc7, 0xf7, 0x32, - 0x5e, 0x67, 0x55, 0xb5, 0x08, 0xf3, 0x17, 0x20, 0x2f, 0x98, 0x37, 0x0d, 0x1b, 0x6b, 0x66, 0xcd, - 0xd0, 0x5f, 0xc6, 0xd5, 0x1e, 0x58, 0xff, 0x7a, 0x64, 0xa8, 0xb6, 0x03, 0xe4, 0x84, 0xf3, 0x32, - 0xe4, 0xbc, 0x5c, 0xa5, 0xa2, 0x37, 0x2c, 0xd3, 0x76, 0x63, 0x38, 0x7e, 0x5e, 0x8c, 0x94, 0x47, - 0xb7, 0x4c, 0xc9, 0x8a, 0x65, 0x60, 0x27, 0xcf, 0xbd, 0x9a, 0xe4, 0x17, 0x38, 0xa3, 0x11, 0x9f, - 0x8a, 0x3b, 0x0e, 0xcd, 0x6c, 0x58, 0xaa, 0xdd, 0x8b, 0xff, 0xfb, 0xfb, 0xc2, 0x71, 0x70, 0x12, - 0xee, 0x38, 0xdc, 0x03, 0x0b, 0x93, 0x68, 0xdf, 0x03, 0x87, 0x2f, 0x0a, 0xc7, 0x21, 0x68, 0x38, - 0x0b, 0x91, 0x30, 0xf4, 0xc0, 0xe2, 0x1f, 0x08, 0x16, 0x82, 0x86, 0xb0, 0x78, 0xce, 0x0f, 0xb4, - 0x36, 0xae, 0xe9, 0x8e, 0x6b, 0xb3, 0x34, 0xb9, 0x3b, 0xab, 0x7f, 0xf8, 0x9d, 0x70, 0x12, 0xa6, - 0x04, 0x48, 0x89, 0x27, 0xe2, 0xdb, 0xae, 0x74, 0x15, 0x15, 0x2f, 0xd8, 0x6f, 0x08, 0x4f, 0x14, - 0x20, 0x23, 0xb2, 0x05, 0x32, 0x44, 0xa2, 0x76, 0x8d, 0xac, 0x1d, 0x7a, 0x60, 0xf7, 0x8f, 0x22, - 0xc2, 0x6d, 0x0a, 0x5a, 0xc2, 0x33, 0x90, 0xff, 0x34, 0x8d, 0x7d, 0x7c, 0xd0, 0x93, 0x75, 0xfe, - 0xe3, 0x48, 0xfe, 0xb3, 0xcd, 0x28, 0x99, 0x0f, 0x19, 0x8b, 0xe4, 0x53, 0x28, 0xee, 0x9e, 0x51, - 0xfe, 0xa7, 0xbe, 0xc7, 0xfb, 0x1b, 0x4e, 0xa7, 0x8a, 0x2b, 0xc4, 0xc8, 0xc3, 0x49, 0x4f, 0x3c, - 0xb3, 0xf7, 0x7c, 0xcf, 0xb3, 0xf3, 0x50, 0xce, 0x53, 0xbc, 0x00, 0x23, 0xa1, 0x84, 0x27, 0x9e, - 0xd5, 0x7b, 0x39, 0xab, 0x6c, 0x30, 0xdf, 0x29, 0x9e, 0x85, 0x14, 0x49, 0x5e, 0xe2, 0xc9, 0xff, - 0x32, 0x27, 0xa7, 0xe8, 0xc5, 0x37, 0x43, 0x5a, 0x24, 0x2d, 0xf1, 0xa4, 0xef, 0xe3, 0xa4, 0x1e, - 0x09, 0x21, 0x17, 0x09, 0x4b, 0x3c, 0xf9, 0x5f, 0x11, 0xe4, 0x82, 0x84, 0x90, 0xf7, 0xae, 0xc2, - 0x2f, 0xfd, 0x74, 0x8a, 0x07, 0x1d, 0xa1, 0xbb, 0xf3, 0x30, 0xc4, 0x33, 0x95, 0x78, 0xea, 0x0f, - 0xf0, 0xc6, 0x05, 0x45, 0xf1, 0x09, 0x18, 0xe8, 0x51, 0xe1, 0x3f, 0xc3, 0x49, 0x19, 0x7e, 0x71, - 0x01, 0x86, 0x03, 0xd9, 0x49, 0x3c, 0xf9, 0x5f, 0xe3, 0xe4, 0x41, 0x2a, 0x22, 0x3a, 0xcf, 0x4e, - 0xe2, 0x19, 0x7c, 0x50, 0x88, 0xce, 0x29, 0x88, 0xda, 0x44, 0x62, 0x12, 0x4f, 0xfd, 0x21, 0xa1, - 0x75, 0x41, 0x52, 0x7c, 0x06, 0x32, 0x5e, 0xb0, 0x89, 0xa7, 0xff, 0x30, 0xa7, 0xf7, 0x69, 0x88, - 0x06, 0x02, 0xc1, 0x2e, 0x9e, 0xc5, 0x5f, 0x17, 0x1a, 0x08, 0x50, 0x91, 0x69, 0x14, 0x4d, 0x60, - 0xe2, 0x39, 0x7d, 0x44, 0x4c, 0xa3, 0x48, 0xfe, 0x42, 0x46, 0x93, 0xfa, 0xfc, 0x78, 0x16, 0x3f, - 0x2b, 0x46, 0x93, 0xe2, 0x13, 0x31, 0xa2, 0x19, 0x41, 0x3c, 0x8f, 0xbf, 0x21, 0xc4, 0x88, 0x24, - 0x04, 0xc5, 0x0d, 0x40, 0xad, 0xd9, 0x40, 0x3c, 0xbf, 0x8f, 0x72, 0x7e, 0xe3, 0x2d, 0xc9, 0x40, - 0xf1, 0x79, 0x38, 0xd6, 0x3e, 0x13, 0x88, 0xe7, 0xfa, 0xb1, 0xef, 0x45, 0xd6, 0x6e, 0xc1, 0x44, - 0xa0, 0xb8, 0xe5, 0x87, 0x94, 0x60, 0x16, 0x10, 0xcf, 0xf6, 0xb5, 0xef, 0x85, 0x1d, 0x77, 0x30, - 0x09, 0x28, 0xce, 0x03, 0xf8, 0x01, 0x38, 0x9e, 0xd7, 0xc7, 0x39, 0xaf, 0x00, 0x11, 0x99, 0x1a, - 0x3c, 0xfe, 0xc6, 0xd3, 0x5f, 0x17, 0x53, 0x83, 0x53, 0x90, 0xa9, 0x21, 0x42, 0x6f, 0x3c, 0xf5, - 0x27, 0xc4, 0xd4, 0x10, 0x24, 0xc4, 0xb2, 0x03, 0xd1, 0x2d, 0x9e, 0xc3, 0xa7, 0x84, 0x65, 0x07, - 0xa8, 0x8a, 0x6b, 0x30, 0xde, 0x12, 0x10, 0xe3, 0x59, 0xfd, 0x02, 0x67, 0x95, 0x8b, 0xc6, 0xc3, - 0x60, 0xf0, 0xe2, 0xc1, 0x30, 0x9e, 0xdb, 0xa7, 0x23, 0xc1, 0x8b, 0xc7, 0xc2, 0xe2, 0x79, 0x48, - 0x1b, 0xcd, 0x7a, 0x9d, 0x4c, 0x1e, 0xd4, 0xfd, 0x6e, 0x60, 0xfe, 0xbf, 0x7c, 0x9f, 0x6b, 0x47, - 0x10, 0x14, 0xcf, 0xc2, 0x00, 0x6e, 0xec, 0xe0, 0x6a, 0x1c, 0xe5, 0xb7, 0xbf, 0x2f, 0x1c, 0x26, - 0xc1, 0x2e, 0x3e, 0x03, 0xc0, 0xb6, 0x46, 0xe8, 0xf1, 0x60, 0x0c, 0xed, 0x7f, 0xfd, 0x3e, 0xbf, - 0x8c, 0xe3, 0x93, 0xf8, 0x0c, 0xd8, 0xd5, 0x9e, 0xee, 0x0c, 0xbe, 0x13, 0x66, 0x40, 0x47, 0xe4, - 0x29, 0x18, 0x7a, 0xd1, 0x31, 0x0d, 0x57, 0xad, 0xc5, 0x51, 0xff, 0x37, 0x4e, 0x2d, 0xf0, 0x89, - 0xc2, 0x1a, 0xa6, 0x8d, 0x5d, 0xb5, 0xe6, 0xc4, 0xd1, 0xfe, 0x77, 0x4e, 0xeb, 0x11, 0x10, 0x62, - 0x4d, 0x75, 0xdc, 0x5e, 0xfa, 0xfd, 0x47, 0x82, 0x58, 0x10, 0x10, 0xa1, 0xc9, 0xef, 0x7d, 0x7c, - 0x10, 0x47, 0xfb, 0x5d, 0x21, 0x34, 0xc7, 0x2f, 0xbe, 0x19, 0x32, 0xe4, 0x27, 0xbb, 0x61, 0x17, - 0x43, 0xfc, 0xc7, 0x9c, 0xd8, 0xa7, 0x20, 0x2d, 0x3b, 0x6e, 0xd5, 0xd5, 0xe3, 0x95, 0x7d, 0x93, - 0x8f, 0xb4, 0xc0, 0x2f, 0xce, 0xc3, 0xb0, 0xe3, 0x56, 0xab, 0x4d, 0x9e, 0x9f, 0xc6, 0x90, 0xff, - 0xc9, 0xf7, 0xbd, 0x2d, 0x0b, 0x8f, 0x86, 0x8c, 0xf6, 0xd5, 0x7d, 0xd7, 0x32, 0xe9, 0x11, 0x48, - 0x1c, 0x87, 0xef, 0x71, 0x0e, 0x01, 0x92, 0xe2, 0x02, 0x64, 0x49, 0x5f, 0x6c, 0x6c, 0x61, 0x7a, - 0x5e, 0x15, 0xc3, 0xe2, 0x4f, 0xb9, 0x02, 0x42, 0x44, 0xa5, 0x9f, 0xfc, 0xca, 0xeb, 0x53, 0xd2, - 0xd7, 0x5f, 0x9f, 0x92, 0xfe, 0xe0, 0xf5, 0x29, 0xe9, 0x43, 0xdf, 0x9c, 0x3a, 0xf2, 0xf5, 0x6f, - 0x4e, 0x1d, 0xf9, 0xdd, 0x6f, 0x4e, 0x1d, 0x69, 0xbf, 0x6d, 0x0c, 0x4b, 0xe6, 0x92, 0xc9, 0x36, - 0x8c, 0xdf, 0x2a, 0x87, 0xb6, 0x8b, 0x6b, 0xa6, 0xbf, 0x5b, 0xeb, 0x2d, 0x72, 0xe0, 0x4f, 0x25, - 0xb2, 0x60, 0x0e, 0xef, 0xe5, 0xaa, 0xc6, 0x41, 0x87, 0xb7, 0x3a, 0x85, 0xb6, 0x1b, 0xc3, 0xf2, - 0x9b, 0x20, 0x39, 0x6f, 0x1c, 0xa0, 0x13, 0xcc, 0xe7, 0x55, 0x9a, 0x76, 0x9d, 0xdf, 0xfc, 0x1a, - 0x22, 0xe5, 0x6d, 0xbb, 0x8e, 0x26, 0xfd, 0xeb, 0x99, 0xd2, 0xa9, 0x2c, 0xbf, 0x73, 0x59, 0x4c, - 0x7d, 0xf7, 0x53, 0xd3, 0x47, 0x4a, 0xfb, 0xd1, 0x1e, 0x7e, 0x29, 0xb6, 0x97, 0xe9, 0x79, 0xe3, - 0x80, 0x76, 0x72, 0x43, 0x7a, 0xeb, 0x00, 0x69, 0xc3, 0x11, 0x1b, 0xdb, 0x53, 0xd1, 0x8d, 0xed, - 0xe7, 0x71, 0xbd, 0x7e, 0xc9, 0x30, 0xaf, 0x1a, 0x5b, 0x04, 0x6d, 0x67, 0x90, 0x5d, 0x23, 0x86, - 0xbf, 0x9a, 0x80, 0xa9, 0x96, 0x3d, 0x6c, 0x3e, 0xf2, 0x9d, 0x1e, 0x2a, 0x15, 0x21, 0xbd, 0x28, - 0x0c, 0x2a, 0x0f, 0x43, 0x0e, 0xd6, 0x4c, 0xa3, 0xea, 0xd0, 0xae, 0x26, 0x15, 0x51, 0x24, 0x5d, - 0x35, 0x54, 0xc3, 0x74, 0xf8, 0xed, 0x48, 0x56, 0x28, 0xfd, 0xac, 0xd4, 0xdf, 0x38, 0x8e, 0x88, - 0x96, 0x44, 0x37, 0x4f, 0x77, 0xdb, 0xfb, 0xa7, 0x2a, 0xf0, 0xe4, 0x0f, 0xec, 0xf3, 0xf7, 0xaa, - 0x8e, 0x0f, 0x25, 0x60, 0x3a, 0xaa, 0x0e, 0x32, 0x8f, 0x1c, 0x57, 0x6d, 0x58, 0x9d, 0xf4, 0x71, - 0x1e, 0x32, 0x5b, 0x02, 0xa7, 0x6f, 0x85, 0xfc, 0x5c, 0x9f, 0x0a, 0x19, 0xf5, 0x9a, 0x12, 0x1a, - 0x79, 0x30, 0x5e, 0x23, 0x5e, 0x17, 0x0e, 0xa1, 0x92, 0x77, 0x27, 0xe1, 0x84, 0x66, 0x3a, 0x0d, - 0xd3, 0xa9, 0x30, 0x83, 0x67, 0x05, 0xae, 0x8c, 0x6c, 0xb0, 0xaa, 0x87, 0xe3, 0x90, 0x8b, 0x30, - 0x4a, 0x9d, 0x02, 0xdd, 0x08, 0xa6, 0x7e, 0x38, 0x36, 0x74, 0x7e, 0xf5, 0xdf, 0x0e, 0xd0, 0x49, - 0x34, 0xe2, 0x11, 0xd2, 0x9b, 0x2e, 0x5b, 0x30, 0xa9, 0x37, 0xac, 0x3a, 0xa6, 0x47, 0x62, 0x15, - 0xaf, 0x2e, 0x9e, 0xdf, 0xd7, 0x38, 0xbf, 0x09, 0x9f, 0x7c, 0x59, 0x50, 0x17, 0x57, 0x60, 0x5c, - 0xd5, 0x34, 0x6c, 0x85, 0x58, 0xc6, 0x38, 0x2c, 0x21, 0x60, 0x8e, 0x53, 0x7a, 0xdc, 0x4a, 0xcf, - 0x74, 0x1a, 0xdb, 0xb7, 0xde, 0x1b, 0x18, 0x34, 0x1b, 0xd7, 0xb0, 0xf1, 0xb0, 0x81, 0xdd, 0xab, - 0xa6, 0xbd, 0xcf, 0xd5, 0xfb, 0x30, 0x6b, 0x4a, 0x0c, 0xc2, 0x7b, 0x93, 0x30, 0xc5, 0x2a, 0xe6, - 0x76, 0x54, 0x07, 0xcf, 0x5d, 0x79, 0x74, 0x07, 0xbb, 0xea, 0xa3, 0x73, 0x9a, 0xa9, 0x8b, 0x69, - 0x3a, 0xc1, 0xc7, 0x85, 0xd4, 0xcf, 0xf2, 0xfa, 0x0e, 0x7e, 0x6a, 0x09, 0x52, 0x0b, 0xa6, 0x6e, - 0x10, 0x8b, 0xac, 0x62, 0xc3, 0x6c, 0x70, 0x2f, 0xc5, 0x0a, 0xe8, 0x6e, 0x18, 0x54, 0x1b, 0x66, - 0xd3, 0x70, 0xd9, 0x69, 0x5e, 0x69, 0xf8, 0x2b, 0x37, 0xa6, 0x8f, 0xfc, 0xde, 0x8d, 0xe9, 0xe4, - 0xb2, 0xe1, 0x2a, 0xbc, 0xaa, 0x98, 0x7a, 0xe3, 0x93, 0xd3, 0x92, 0xfc, 0x2c, 0x0c, 0x2d, 0x62, - 0xed, 0x30, 0xbc, 0x16, 0xb1, 0x16, 0xe1, 0xf5, 0x00, 0xa4, 0x97, 0x0d, 0x97, 0xdd, 0x20, 0xbe, - 0x13, 0x92, 0xba, 0xc1, 0x2e, 0xa5, 0x45, 0xda, 0x27, 0x70, 0x82, 0xba, 0x88, 0x35, 0x0f, 0xb5, - 0x8a, 0xb5, 0x28, 0x2a, 0x61, 0x4f, 0xe0, 0xa5, 0xc5, 0xdf, 0xfd, 0x4f, 0x53, 0x47, 0x5e, 0x79, - 0x7d, 0xea, 0x48, 0xc7, 0x91, 0x08, 0x46, 0x07, 0xae, 0x62, 0x3e, 0x04, 0x4e, 0x75, 0x7f, 0xce, - 0x0d, 0xcd, 0x85, 0xcf, 0xa6, 0xe0, 0x4e, 0xfa, 0x78, 0xc4, 0x6e, 0xe8, 0x86, 0x3b, 0xa7, 0xd9, - 0x07, 0x96, 0x4b, 0xc3, 0x89, 0xb9, 0xcb, 0x47, 0x61, 0xdc, 0xaf, 0x9e, 0x65, 0xd5, 0x1d, 0xc6, - 0x60, 0x17, 0x06, 0x36, 0x08, 0x1d, 0x51, 0x9c, 0x6b, 0xba, 0x6a, 0x9d, 0xbb, 0x0b, 0x56, 0x20, - 0x50, 0xf6, 0xe0, 0x24, 0xc1, 0xa0, 0xba, 0x78, 0x6b, 0x52, 0xc7, 0xea, 0x2e, 0xbb, 0xb7, 0x9b, - 0xa4, 0x21, 0x24, 0x4d, 0x00, 0xf4, 0x8a, 0xee, 0x24, 0x0c, 0xa8, 0x4d, 0x76, 0xe4, 0x9c, 0x24, - 0xb1, 0x85, 0x16, 0xe4, 0x4b, 0x30, 0xc4, 0x8f, 0xb9, 0x50, 0x0e, 0x92, 0xfb, 0xf8, 0x80, 0xb6, - 0x93, 0x55, 0xc8, 0x4f, 0x34, 0x0b, 0x03, 0x54, 0x78, 0xfe, 0x20, 0x21, 0x3f, 0xdb, 0x22, 0xfd, - 0x2c, 0x15, 0x52, 0x61, 0x68, 0xf2, 0xb3, 0x90, 0x5e, 0x34, 0x1b, 0xba, 0x61, 0x86, 0xb9, 0x65, - 0x18, 0x37, 0x2a, 0xb3, 0xd5, 0xe4, 0x63, 0xad, 0xb0, 0x02, 0x3a, 0x06, 0x83, 0xec, 0x1e, 0x37, - 0x3f, 0x36, 0xe7, 0x25, 0x79, 0x01, 0x86, 0x28, 0xef, 0x75, 0x0b, 0x21, 0xfe, 0x02, 0x88, 0x5f, - 0x18, 0xa7, 0x6e, 0x81, 0xb3, 0x4f, 0xf8, 0xc2, 0x22, 0x48, 0x55, 0x55, 0x57, 0xe5, 0xfd, 0xa6, - 0xbf, 0xe5, 0xa7, 0x21, 0xcd, 0x99, 0x38, 0xe8, 0x0c, 0x24, 0x4d, 0xcb, 0xe1, 0x07, 0xdf, 0x85, - 0x4e, 0x5d, 0x59, 0xb7, 0x4a, 0x29, 0x62, 0x25, 0x0a, 0x41, 0x2e, 0x29, 0x1d, 0xcd, 0xe2, 0xc9, - 0x80, 0x59, 0x04, 0x86, 0x3c, 0xf0, 0x93, 0x0d, 0x69, 0x8b, 0x39, 0x78, 0xc6, 0xf2, 0xa9, 0x04, - 0x4c, 0x05, 0x6a, 0xaf, 0x60, 0x9b, 0xac, 0xf5, 0x98, 0x45, 0x71, 0x6b, 0x41, 0x01, 0x21, 0x79, - 0x7d, 0x07, 0x73, 0x79, 0x33, 0x24, 0xe7, 0x2d, 0x0b, 0x15, 0x20, 0xcd, 0x0e, 0xb8, 0x4d, 0x66, - 0x2f, 0x29, 0xc5, 0x2b, 0x93, 0x3a, 0xc7, 0xdc, 0x75, 0xaf, 0xaa, 0xb6, 0xf7, 0xd4, 0x49, 0x94, - 0xe5, 0xa7, 0x20, 0xb3, 0x60, 0x1a, 0x0e, 0x36, 0x9c, 0x26, 0x0d, 0x44, 0x3b, 0x75, 0x53, 0xdb, - 0xe7, 0x1c, 0x58, 0x81, 0x28, 0x5c, 0xb5, 0x2c, 0x4a, 0x99, 0x52, 0xc8, 0x4f, 0x36, 0x2f, 0x4b, - 0x9b, 0x1d, 0x55, 0xf4, 0x54, 0xff, 0x2a, 0xe2, 0x9d, 0xf4, 0x74, 0xf4, 0xbf, 0x25, 0x38, 0xd9, - 0x3a, 0xa1, 0xf6, 0xf1, 0x81, 0xd3, 0xef, 0x7c, 0x7a, 0x01, 0x32, 0x1b, 0xf4, 0xbd, 0xf1, 0x25, - 0x7c, 0x80, 0x0a, 0x30, 0x84, 0xab, 0x67, 0xce, 0x9e, 0x7d, 0xf4, 0x29, 0x66, 0xed, 0x17, 0x8f, - 0x28, 0x02, 0x80, 0xa6, 0x20, 0xe3, 0x60, 0xcd, 0x3a, 0x73, 0xf6, 0xdc, 0xfe, 0xa3, 0xcc, 0xbc, - 0x2e, 0x1e, 0x51, 0x7c, 0x50, 0x31, 0x4d, 0x7a, 0xfd, 0xc6, 0xa7, 0xa6, 0xa5, 0xd2, 0x00, 0x24, - 0x9d, 0x66, 0xe3, 0xb6, 0xda, 0xc8, 0x6b, 0x03, 0x30, 0x13, 0xa4, 0xa4, 0xd1, 0xfa, 0x8a, 0x5a, - 0xd7, 0xab, 0xaa, 0xff, 0x52, 0x3c, 0x17, 0xd0, 0x01, 0xc5, 0x68, 0xaf, 0x82, 0x42, 0x57, 0x4d, - 0xca, 0xbf, 0x2e, 0x41, 0xf6, 0xb2, 0xe0, 0xbc, 0x89, 0x5d, 0x74, 0x1e, 0xc0, 0x6b, 0x49, 0x4c, - 0x9b, 0x3b, 0x66, 0xa3, 0x6d, 0xcd, 0x7a, 0x34, 0x4a, 0x00, 0x1d, 0x3d, 0x41, 0x0d, 0xd1, 0x32, - 0x1d, 0xfe, 0xfc, 0x25, 0x86, 0xd4, 0x43, 0x46, 0x0f, 0x01, 0xa2, 0x1e, 0xae, 0x72, 0xc5, 0x74, - 0x75, 0xa3, 0x56, 0xb1, 0xcc, 0xab, 0xfc, 0x51, 0x61, 0x52, 0xc9, 0xd1, 0x9a, 0xcb, 0xb4, 0x62, - 0x83, 0xc0, 0x89, 0xd0, 0x19, 0x8f, 0x0b, 0xc9, 0xad, 0xd4, 0x6a, 0xd5, 0xc6, 0x8e, 0xc3, 0x9d, - 0x98, 0x28, 0xa2, 0xf3, 0x30, 0x64, 0x35, 0x77, 0x2a, 0xc2, 0x63, 0x0c, 0x9f, 0x39, 0xd9, 0x6e, - 0xfe, 0x0b, 0xfb, 0xe0, 0x1e, 0x60, 0xd0, 0x6a, 0xee, 0x10, 0x6b, 0xb9, 0x0b, 0xb2, 0x6d, 0x84, - 0x19, 0xbe, 0xe2, 0xcb, 0x41, 0x9f, 0xb9, 0xf3, 0x1e, 0x54, 0x2c, 0x5b, 0x37, 0x6d, 0xdd, 0x3d, - 0xa0, 0xb7, 0x57, 0x92, 0x4a, 0x4e, 0x54, 0x6c, 0x70, 0xb8, 0xbc, 0x0f, 0x63, 0x9b, 0x34, 0xb7, - 0xf0, 0x25, 0x3f, 0xeb, 0xcb, 0x27, 0xc5, 0xcb, 0xd7, 0x51, 0xb2, 0x44, 0x8b, 0x64, 0xa5, 0xe7, - 0x3a, 0x5a, 0xe7, 0x13, 0xfd, 0x5b, 0x67, 0x38, 0xda, 0xfd, 0xd1, 0x89, 0xd0, 0xe4, 0xe4, 0xa9, - 0x64, 0xc0, 0x7d, 0xf5, 0x6a, 0x98, 0x71, 0x29, 0x75, 0xa1, 0x7b, 0x50, 0x2d, 0xc4, 0xb8, 0xd1, - 0x42, 0xec, 0x14, 0x92, 0x9f, 0x82, 0x91, 0x0d, 0xd5, 0x76, 0x37, 0xb1, 0x7b, 0x11, 0xab, 0x55, - 0x6c, 0x87, 0xa3, 0xee, 0x88, 0x88, 0xba, 0x08, 0x52, 0x34, 0xb4, 0xb2, 0xa8, 0x43, 0x7f, 0xcb, - 0x7b, 0x90, 0xa2, 0x37, 0xd8, 0xbc, 0x88, 0xcc, 0x29, 0x58, 0x44, 0x26, 0xbe, 0xf4, 0xc0, 0xc5, - 0x8e, 0x58, 0xd0, 0xd1, 0x02, 0x7a, 0x5c, 0xc4, 0xd5, 0x64, 0xf7, 0xb8, 0xca, 0x0d, 0x91, 0x47, - 0xd7, 0x3a, 0x0c, 0x95, 0x88, 0x2b, 0x5e, 0x5e, 0xf4, 0x04, 0x91, 0x7c, 0x41, 0xd0, 0x2a, 0x8c, - 0x59, 0xaa, 0xed, 0xd2, 0xab, 0xfb, 0x7b, 0xb4, 0x17, 0xdc, 0xd6, 0xa7, 0x5b, 0x67, 0x5e, 0xa8, - 0xb3, 0xbc, 0x95, 0x11, 0x2b, 0x08, 0x94, 0xff, 0x30, 0x05, 0x83, 0x5c, 0x19, 0x6f, 0x86, 0x21, - 0xae, 0x56, 0x6e, 0x9d, 0x77, 0xce, 0xb6, 0x06, 0xa6, 0x59, 0x2f, 0x80, 0x70, 0x7e, 0x82, 0x06, - 0xdd, 0x07, 0x69, 0x6d, 0x4f, 0xd5, 0x8d, 0x8a, 0x5e, 0x15, 0x69, 0xde, 0xeb, 0x37, 0xa6, 0x87, - 0x16, 0x08, 0x6c, 0x79, 0x51, 0x19, 0xa2, 0x95, 0xcb, 0x55, 0x92, 0x09, 0xec, 0x61, 0xbd, 0xb6, - 0xe7, 0xf2, 0x19, 0xc6, 0x4b, 0xe8, 0x49, 0x48, 0x11, 0x83, 0xe0, 0x0f, 0xbb, 0x0a, 0x2d, 0xc9, - 0xb6, 0xb7, 0xe2, 0x29, 0xa5, 0x49, 0xc3, 0x1f, 0xfa, 0xfd, 0x69, 0x49, 0xa1, 0x14, 0x68, 0x01, - 0x46, 0xea, 0xaa, 0xe3, 0x56, 0x68, 0x04, 0x23, 0xcd, 0x0f, 0x50, 0x16, 0x27, 0x5a, 0x15, 0xc2, - 0x15, 0xcb, 0x45, 0x1f, 0x26, 0x54, 0x0c, 0x54, 0x45, 0xa7, 0x20, 0x47, 0x99, 0x68, 0x66, 0xa3, - 0xa1, 0xbb, 0x2c, 0xb7, 0x1a, 0xa4, 0x7a, 0x1f, 0x25, 0xf0, 0x05, 0x0a, 0xa6, 0x19, 0xd6, 0x1d, - 0x90, 0xa1, 0x4f, 0x49, 0x28, 0x0a, 0xbb, 0x36, 0x99, 0x26, 0x00, 0x5a, 0x79, 0x3f, 0x8c, 0xf9, - 0xfe, 0x91, 0xa1, 0xa4, 0x19, 0x17, 0x1f, 0x4c, 0x11, 0x1f, 0x81, 0x49, 0x03, 0x5f, 0xa3, 0x17, - 0x39, 0x43, 0xd8, 0x19, 0x8a, 0x8d, 0x48, 0xdd, 0xe5, 0x30, 0xc5, 0xbd, 0x30, 0xaa, 0x09, 0xe5, - 0x33, 0x5c, 0xa0, 0xb8, 0x23, 0x1e, 0x94, 0xa2, 0x9d, 0x80, 0xb4, 0x6a, 0x59, 0x0c, 0x61, 0x98, - 0xfb, 0x47, 0xcb, 0xa2, 0x55, 0xa7, 0x61, 0x9c, 0xf6, 0xd1, 0xc6, 0x4e, 0xb3, 0xee, 0x72, 0x26, - 0x59, 0x8a, 0x33, 0x46, 0x2a, 0x14, 0x06, 0xa7, 0xb8, 0x77, 0xc3, 0x08, 0xbe, 0xa2, 0x57, 0xb1, - 0xa1, 0x61, 0x86, 0x37, 0x42, 0xf1, 0xb2, 0x02, 0x48, 0x91, 0x1e, 0x00, 0xcf, 0xef, 0x55, 0x84, - 0x4f, 0x1e, 0x65, 0xfc, 0x04, 0x7c, 0x9e, 0x81, 0xe5, 0x3c, 0xa4, 0x16, 0x55, 0x57, 0x25, 0x09, - 0x86, 0x7b, 0x8d, 0x05, 0x9a, 0xac, 0x42, 0x7e, 0xca, 0x6f, 0x24, 0x20, 0x75, 0xd9, 0x74, 0x31, - 0x7a, 0x2c, 0x90, 0x00, 0x8e, 0xb6, 0xb3, 0xe7, 0x4d, 0xbd, 0x66, 0xe0, 0xea, 0xaa, 0x53, 0x0b, - 0xbc, 0xfb, 0xf6, 0xcd, 0x29, 0x11, 0x32, 0xa7, 0x49, 0x18, 0xb0, 0xcd, 0xa6, 0x51, 0x15, 0x37, - 0x0e, 0x69, 0x01, 0x95, 0x21, 0xed, 0x59, 0x49, 0x2a, 0xce, 0x4a, 0xc6, 0x88, 0x95, 0x10, 0x1b, - 0xe6, 0x00, 0x65, 0x68, 0x87, 0x1b, 0x4b, 0x09, 0x32, 0x9e, 0xf3, 0xe2, 0xd6, 0xd6, 0x9b, 0xc1, - 0xfa, 0x64, 0x24, 0x98, 0x78, 0x63, 0xef, 0x29, 0x8f, 0x59, 0x5c, 0xce, 0xab, 0xe0, 0xda, 0x0b, - 0x99, 0x15, 0x7f, 0x83, 0x3e, 0x44, 0xfb, 0xe5, 0x9b, 0x15, 0x7b, 0x87, 0x7e, 0x12, 0x32, 0x8e, - 0x5e, 0x33, 0x54, 0xb7, 0x69, 0x63, 0x6e, 0x79, 0x3e, 0x40, 0xfe, 0x92, 0x04, 0x83, 0xcc, 0x92, - 0x03, 0x7a, 0x93, 0xda, 0xeb, 0x2d, 0xd1, 0x49, 0x6f, 0xc9, 0xc3, 0xeb, 0x6d, 0x1e, 0xc0, 0x13, - 0xc6, 0xe1, 0x4f, 0x83, 0xdb, 0x64, 0x0c, 0x4c, 0xc4, 0x4d, 0xbd, 0xc6, 0x27, 0x6a, 0x80, 0x48, - 0xfe, 0x8f, 0x12, 0x49, 0x62, 0x79, 0x3d, 0x9a, 0x87, 0x11, 0x21, 0x57, 0x65, 0xb7, 0xae, 0xd6, - 0xb8, 0xed, 0xdc, 0xd9, 0x51, 0xb8, 0x0b, 0x75, 0xb5, 0xa6, 0x0c, 0x73, 0x79, 0x48, 0xa1, 0xfd, - 0x38, 0x24, 0x3a, 0x8c, 0x43, 0x68, 0xe0, 0x93, 0x87, 0x1b, 0xf8, 0xd0, 0x10, 0xa5, 0xa2, 0x43, - 0xf4, 0xf9, 0x04, 0x5d, 0xcc, 0x58, 0xa6, 0xa3, 0xd6, 0x7f, 0x18, 0x33, 0xe2, 0x0e, 0xc8, 0x58, - 0x66, 0xbd, 0xc2, 0x6a, 0xd8, 0x4d, 0xdc, 0xb4, 0x65, 0xd6, 0x95, 0x96, 0x61, 0x1f, 0xb8, 0x45, - 0xd3, 0x65, 0xf0, 0x16, 0x68, 0x6d, 0x28, 0xaa, 0x35, 0x1b, 0xb2, 0x4c, 0x15, 0x3c, 0x96, 0x3d, - 0x42, 0x74, 0x40, 0x83, 0xa3, 0xd4, 0x1a, 0x7b, 0x99, 0xd8, 0x0c, 0x53, 0xe1, 0x78, 0x84, 0x82, - 0xb9, 0xfe, 0x76, 0xab, 0xe0, 0xa0, 0x59, 0x2a, 0x1c, 0x4f, 0xfe, 0x39, 0x09, 0x60, 0x85, 0x68, - 0x96, 0xf6, 0x97, 0x44, 0x21, 0x87, 0x8a, 0x50, 0x09, 0xb5, 0x3c, 0xd5, 0x69, 0xd0, 0x78, 0xfb, - 0x59, 0x27, 0x28, 0xf7, 0x02, 0x8c, 0xf8, 0xc6, 0xe8, 0x60, 0x21, 0xcc, 0x54, 0x97, 0xac, 0x7a, - 0x13, 0xbb, 0x4a, 0xf6, 0x4a, 0xa0, 0x24, 0xff, 0x33, 0x09, 0x32, 0x54, 0xa6, 0x55, 0xec, 0xaa, - 0xa1, 0x31, 0x94, 0x0e, 0x3f, 0x86, 0x77, 0x02, 0x30, 0x36, 0x8e, 0xfe, 0x32, 0xe6, 0x96, 0x95, - 0xa1, 0x90, 0x4d, 0xfd, 0x65, 0x8c, 0xce, 0x79, 0x0a, 0x4f, 0x76, 0x57, 0xb8, 0xc8, 0xba, 0xb9, - 0xda, 0x8f, 0xc3, 0x10, 0xfd, 0x94, 0xce, 0x35, 0x87, 0x27, 0xd2, 0x83, 0x46, 0xb3, 0xb1, 0x75, - 0xcd, 0x91, 0x5f, 0x84, 0xa1, 0xad, 0x6b, 0x6c, 0x6f, 0xe4, 0x0e, 0xc8, 0xd8, 0xa6, 0xc9, 0x63, - 0x32, 0xcb, 0x85, 0xd2, 0x04, 0x40, 0x43, 0x90, 0xd8, 0x0f, 0x48, 0xf8, 0xfb, 0x01, 0xfe, 0x86, - 0x46, 0xb2, 0xa7, 0x0d, 0x8d, 0xd3, 0xff, 0x4e, 0x82, 0xe1, 0x80, 0x7f, 0x40, 0x8f, 0xc2, 0xd1, - 0xd2, 0xca, 0xfa, 0xc2, 0xa5, 0xca, 0xf2, 0x62, 0xe5, 0xc2, 0xca, 0xfc, 0x92, 0xff, 0xd6, 0xa4, - 0x70, 0xec, 0xd5, 0xeb, 0x33, 0x28, 0x80, 0xbb, 0x6d, 0xec, 0x1b, 0xe6, 0x55, 0x03, 0xcd, 0xc1, - 0x64, 0x98, 0x64, 0xbe, 0xb4, 0x59, 0x5e, 0xdb, 0xca, 0x49, 0x85, 0xa3, 0xaf, 0x5e, 0x9f, 0x19, - 0x0f, 0x50, 0xcc, 0xef, 0x38, 0xd8, 0x70, 0x5b, 0x09, 0x16, 0xd6, 0x57, 0x57, 0x97, 0xb7, 0x72, - 0x89, 0x16, 0x02, 0xee, 0xb0, 0x1f, 0x80, 0xf1, 0x30, 0xc1, 0xda, 0xf2, 0x4a, 0x2e, 0x59, 0x40, - 0xaf, 0x5e, 0x9f, 0x19, 0x0d, 0x60, 0xaf, 0xe9, 0xf5, 0x42, 0xfa, 0xfd, 0x9f, 0x9e, 0x3a, 0xf2, - 0x4b, 0xbf, 0x38, 0x25, 0x91, 0x9e, 0x8d, 0x84, 0x7c, 0x04, 0x7a, 0x08, 0x8e, 0x6f, 0x2e, 0x2f, - 0xad, 0x95, 0x17, 0x2b, 0xab, 0x9b, 0x4b, 0x15, 0xf6, 0x8d, 0x0d, 0xaf, 0x77, 0x63, 0xaf, 0x5e, - 0x9f, 0x19, 0xe6, 0x5d, 0xea, 0x84, 0xbd, 0xa1, 0x94, 0x2f, 0xaf, 0x6f, 0x95, 0x73, 0x12, 0xc3, - 0xde, 0xb0, 0xf1, 0x15, 0xd3, 0x65, 0xdf, 0xda, 0x7a, 0x04, 0x4e, 0xb4, 0xc1, 0xf6, 0x3a, 0x36, - 0xfe, 0xea, 0xf5, 0x99, 0x91, 0x0d, 0x1b, 0xb3, 0xf9, 0x43, 0x29, 0x66, 0x21, 0xdf, 0x4a, 0xb1, - 0xbe, 0xb1, 0xbe, 0x39, 0xbf, 0x92, 0x9b, 0x29, 0xe4, 0x5e, 0xbd, 0x3e, 0x93, 0x15, 0xce, 0x90, - 0xe0, 0xfb, 0x3d, 0xbb, 0x9d, 0x2b, 0x9e, 0x3f, 0x79, 0x18, 0xee, 0xe1, 0x7b, 0x80, 0x8e, 0xab, - 0xee, 0xeb, 0x46, 0xcd, 0xdb, 0x69, 0xe5, 0x65, 0xbe, 0xf2, 0x39, 0xc6, 0x37, 0x5b, 0x05, 0xb4, - 0xeb, 0x7e, 0x6b, 0xa1, 0xf3, 0xc9, 0x52, 0x21, 0xe6, 0xf0, 0x25, 0x7e, 0xe9, 0xd4, 0x79, 0x6f, - 0xbe, 0x10, 0xb3, 0x63, 0x5c, 0xe8, 0xba, 0xb8, 0x93, 0x3f, 0x20, 0xc1, 0xe8, 0x45, 0xdd, 0x71, - 0x4d, 0x5b, 0xd7, 0xd4, 0x3a, 0x7d, 0x61, 0x72, 0xae, 0x57, 0xdf, 0x1a, 0x99, 0xea, 0xcf, 0xc0, - 0xe0, 0x15, 0xb5, 0xce, 0x9c, 0x5a, 0x92, 0x7e, 0x10, 0xa3, 0xbd, 0xfa, 0x7c, 0xd7, 0x26, 0x18, - 0x30, 0x32, 0xf9, 0x57, 0x12, 0x30, 0x46, 0x27, 0x83, 0xc3, 0x3e, 0x95, 0x44, 0xd6, 0x58, 0x25, - 0x48, 0xd9, 0xaa, 0xcb, 0x37, 0x0d, 0x4b, 0xb3, 0x7c, 0xe7, 0xf7, 0xbe, 0xf8, 0xdd, 0xdc, 0xd9, - 0x45, 0xac, 0x29, 0x94, 0x16, 0xbd, 0x1d, 0xd2, 0x0d, 0xf5, 0x5a, 0x85, 0xf2, 0x61, 0x2b, 0x97, - 0xf9, 0xfe, 0xf8, 0xdc, 0xbc, 0x31, 0x3d, 0x76, 0xa0, 0x36, 0xea, 0x45, 0x59, 0xf0, 0x91, 0x95, - 0xa1, 0x86, 0x7a, 0x8d, 0x88, 0x88, 0x2c, 0x18, 0x23, 0x50, 0x6d, 0x4f, 0x35, 0x6a, 0x98, 0x35, - 0x42, 0xb7, 0x40, 0x4b, 0x17, 0xfb, 0x6e, 0xe4, 0x98, 0xdf, 0x48, 0x80, 0x9d, 0xac, 0x8c, 0x34, - 0xd4, 0x6b, 0x0b, 0x14, 0x40, 0x5a, 0x2c, 0xa6, 0x3f, 0xfa, 0xc9, 0xe9, 0x23, 0x74, 0x37, 0xfd, - 0x1b, 0x12, 0x80, 0xaf, 0x31, 0xf4, 0x76, 0xc8, 0x69, 0x5e, 0x89, 0xd2, 0x3a, 0x7c, 0x0c, 0xef, - 0xef, 0x34, 0x16, 0x11, 0x7d, 0xb3, 0xd8, 0xfc, 0xf5, 0x1b, 0xd3, 0x92, 0x32, 0xa6, 0x45, 0x86, - 0xe2, 0x6d, 0x30, 0xdc, 0xb4, 0xaa, 0xaa, 0x8b, 0x2b, 0x74, 0x1d, 0x97, 0x88, 0x8d, 0xf3, 0x53, - 0x84, 0xd7, 0xcd, 0x1b, 0xd3, 0x88, 0x75, 0x2b, 0x40, 0x2c, 0xd3, 0xe8, 0x0f, 0x0c, 0x42, 0x08, - 0x02, 0x7d, 0xfa, 0xaa, 0x04, 0xc3, 0x8b, 0x81, 0x9b, 0x5e, 0x79, 0x18, 0x6a, 0x98, 0x86, 0xbe, - 0xcf, 0xed, 0x31, 0xa3, 0x88, 0x22, 0x2a, 0x40, 0x9a, 0x3d, 0xba, 0x73, 0x0f, 0xc4, 0x56, 0xa8, - 0x28, 0x13, 0xaa, 0xab, 0x78, 0xc7, 0xd1, 0xc5, 0x68, 0x28, 0xa2, 0x88, 0x2e, 0x40, 0xce, 0xc1, - 0x5a, 0xd3, 0xd6, 0xdd, 0x83, 0x8a, 0x66, 0x1a, 0xae, 0xaa, 0xb9, 0xec, 0xf9, 0x56, 0xe9, 0x8e, - 0x9b, 0x37, 0xa6, 0x8f, 0x33, 0x59, 0xa3, 0x18, 0xb2, 0x32, 0x26, 0x40, 0x0b, 0x0c, 0x42, 0x5a, - 0xa8, 0x62, 0x57, 0xd5, 0xeb, 0x4e, 0x9e, 0x1d, 0x0c, 0x89, 0x62, 0xa0, 0x2f, 0x9f, 0x1b, 0x0a, - 0x6e, 0x6c, 0x5d, 0x80, 0x9c, 0x69, 0x61, 0x3b, 0x94, 0x88, 0x4a, 0xd1, 0x96, 0xa3, 0x18, 0xb2, - 0x32, 0x26, 0x40, 0x22, 0x49, 0x75, 0xc9, 0x30, 0x8b, 0x85, 0xa2, 0xd5, 0xdc, 0xf1, 0xf7, 0xc3, - 0x26, 0x5b, 0x46, 0x63, 0xde, 0x38, 0x28, 0x3d, 0xe6, 0x73, 0x8f, 0xd2, 0xc9, 0x5f, 0xfb, 0xc2, - 0xc3, 0x93, 0xdc, 0x34, 0xfc, 0xfd, 0xa9, 0x4b, 0xf8, 0x80, 0x0c, 0x3f, 0x47, 0xdd, 0xa0, 0x98, - 0x24, 0xed, 0x7c, 0x51, 0xd5, 0xeb, 0xe2, 0x19, 0xb2, 0xc2, 0x4b, 0xa8, 0x08, 0x83, 0x8e, 0xab, - 0xba, 0x4d, 0x87, 0x7f, 0x1c, 0x4c, 0xee, 0x64, 0x6a, 0x25, 0xd3, 0xa8, 0x6e, 0x52, 0x4c, 0x85, - 0x53, 0xa0, 0x0b, 0x30, 0xe8, 0x9a, 0xfb, 0xd8, 0xe0, 0x2a, 0xec, 0x6b, 0x7e, 0xd3, 0x73, 0x2a, - 0x46, 0x4d, 0x34, 0x52, 0xc5, 0x75, 0x5c, 0x63, 0x69, 0xd5, 0x9e, 0x4a, 0x56, 0x1f, 0xf4, 0x1b, - 0x61, 0xa5, 0xe5, 0xbe, 0x27, 0x21, 0xd7, 0x54, 0x94, 0x9f, 0xac, 0x8c, 0x79, 0xa0, 0x4d, 0x0a, - 0x41, 0x97, 0x42, 0x57, 0x12, 0xf9, 0x87, 0xf4, 0xee, 0xee, 0xd4, 0xfd, 0x80, 0x4d, 0x8b, 0xfd, - 0x89, 0xe0, 0x85, 0xc6, 0x0b, 0x90, 0x6b, 0x1a, 0x3b, 0xa6, 0x41, 0xdf, 0x0a, 0xf2, 0xfc, 0x9e, - 0xac, 0xef, 0x92, 0x41, 0xe3, 0x88, 0x62, 0xc8, 0xca, 0x98, 0x07, 0xba, 0xc8, 0x56, 0x01, 0x55, - 0x18, 0xf5, 0xb1, 0xe8, 0x44, 0xcd, 0xc4, 0x4e, 0xd4, 0xbb, 0xf8, 0x44, 0x3d, 0x1a, 0x6d, 0xc5, - 0x9f, 0xab, 0x23, 0x1e, 0x90, 0x90, 0xa1, 0x8b, 0x00, 0xbe, 0x7b, 0xa0, 0xfb, 0x14, 0xc3, 0x9d, - 0x07, 0xde, 0xf7, 0x31, 0x62, 0xbd, 0xe7, 0xd3, 0xa2, 0x77, 0xc2, 0x44, 0x43, 0x37, 0x2a, 0x0e, - 0xae, 0xef, 0x56, 0xb8, 0x82, 0x09, 0x4b, 0xfa, 0xa9, 0x97, 0xd2, 0x4a, 0x7f, 0xf6, 0x70, 0xf3, - 0xc6, 0x74, 0x81, 0xbb, 0xd0, 0x56, 0x96, 0xb2, 0x32, 0xde, 0xd0, 0x8d, 0x4d, 0x5c, 0xdf, 0x5d, - 0xf4, 0x60, 0xc5, 0xec, 0xfb, 0x3f, 0x39, 0x7d, 0x84, 0x4f, 0xd7, 0x23, 0xf2, 0x39, 0xba, 0x77, - 0xce, 0xa7, 0x19, 0x76, 0xc8, 0x9a, 0x44, 0x15, 0x05, 0xba, 0xa3, 0x91, 0x51, 0x7c, 0x00, 0x9b, - 0xe6, 0xaf, 0xfc, 0x87, 0x19, 0x49, 0xfe, 0x9c, 0x04, 0x83, 0x8b, 0x97, 0x37, 0x54, 0xdd, 0x46, - 0xcb, 0x30, 0xee, 0x5b, 0x4e, 0x78, 0x92, 0x9f, 0xbc, 0x79, 0x63, 0x3a, 0x1f, 0x35, 0x2e, 0x6f, - 0x96, 0xfb, 0x06, 0x2c, 0xa6, 0xf9, 0x72, 0xa7, 0x85, 0x6b, 0x88, 0x55, 0x0b, 0x8a, 0xdc, 0xba, - 0xac, 0x8d, 0x74, 0xb3, 0x0c, 0x43, 0x4c, 0x5a, 0x07, 0x15, 0x61, 0xc0, 0x22, 0x3f, 0xf8, 0xc1, - 0xc0, 0x54, 0x47, 0xe3, 0xa5, 0xf8, 0xde, 0x46, 0x26, 0x21, 0x91, 0x3f, 0x9c, 0x00, 0x58, 0xbc, - 0x7c, 0x79, 0xcb, 0xd6, 0xad, 0x3a, 0x76, 0x6f, 0x65, 0xcf, 0xb7, 0xe0, 0x68, 0x60, 0x95, 0x64, - 0x6b, 0x91, 0xde, 0xcf, 0xdc, 0xbc, 0x31, 0x7d, 0x32, 0xda, 0xfb, 0x00, 0x9a, 0xac, 0x4c, 0xf8, - 0xeb, 0x25, 0x5b, 0x6b, 0xcb, 0xb5, 0xea, 0xb8, 0x1e, 0xd7, 0x64, 0x67, 0xae, 0x01, 0xb4, 0x20, - 0xd7, 0x45, 0xc7, 0x6d, 0xaf, 0xda, 0x4d, 0x18, 0xf6, 0x55, 0xe2, 0xa0, 0x45, 0x48, 0xbb, 0xfc, - 0x37, 0xd7, 0xb0, 0xdc, 0x59, 0xc3, 0x82, 0x8c, 0x6b, 0xd9, 0xa3, 0x94, 0xff, 0x4c, 0x02, 0xf0, - 0x6d, 0xf6, 0xc7, 0xd3, 0xc4, 0x88, 0x2b, 0xe7, 0x8e, 0x37, 0x79, 0xa8, 0x54, 0x8d, 0x53, 0x47, - 0xf4, 0xf9, 0xd3, 0x09, 0x98, 0xd8, 0x16, 0x9e, 0xe7, 0xc7, 0x5e, 0x07, 0x1b, 0x30, 0x84, 0x0d, - 0xd7, 0xd6, 0xa9, 0x12, 0xc8, 0x68, 0x3f, 0xd2, 0x69, 0xb4, 0xdb, 0xf4, 0x89, 0x7e, 0xec, 0x46, - 0x6c, 0xba, 0x73, 0x36, 0x11, 0x6d, 0x7c, 0x30, 0x09, 0xf9, 0x4e, 0x94, 0x68, 0x01, 0xc6, 0x34, - 0x1b, 0x53, 0x40, 0x25, 0xb8, 0xf3, 0x57, 0x2a, 0xf8, 0x99, 0x65, 0x04, 0x41, 0x56, 0x46, 0x05, - 0x84, 0x47, 0x8f, 0x1a, 0x90, 0xb4, 0x8f, 0x98, 0x1d, 0xc1, 0xea, 0x31, 0xcf, 0x93, 0x79, 0xf8, - 0x10, 0x8d, 0x84, 0x19, 0xb0, 0xf8, 0x31, 0xea, 0x43, 0x69, 0x00, 0x79, 0x09, 0xc6, 0x74, 0x43, - 0x77, 0x75, 0xb5, 0x5e, 0xd9, 0x51, 0xeb, 0xaa, 0xa1, 0x1d, 0x26, 0x6b, 0x66, 0x2e, 0x9f, 0x37, - 0x1b, 0x61, 0x27, 0x2b, 0xa3, 0x1c, 0x52, 0x62, 0x00, 0x74, 0x11, 0x86, 0x44, 0x53, 0xa9, 0x43, - 0x65, 0x1b, 0x82, 0x3c, 0x90, 0xe0, 0xfd, 0x4c, 0x12, 0xc6, 0x15, 0x5c, 0xfd, 0xff, 0x43, 0xd1, - 0xdf, 0x50, 0xac, 0x02, 0xb0, 0xe9, 0x4e, 0x1c, 0xec, 0x21, 0x46, 0x83, 0x38, 0x8c, 0x0c, 0xe3, - 0xb0, 0xe8, 0xb8, 0x81, 0xf1, 0xb8, 0x91, 0x80, 0x6c, 0x70, 0x3c, 0xfe, 0x82, 0x46, 0x25, 0xb4, - 0xec, 0x7b, 0xa2, 0x14, 0xff, 0x44, 0x68, 0x07, 0x4f, 0xd4, 0x62, 0xbd, 0xdd, 0x5d, 0xd0, 0xff, - 0x48, 0xc0, 0xe0, 0x86, 0x6a, 0xab, 0x0d, 0x07, 0x69, 0x2d, 0x99, 0xa6, 0xd8, 0x7e, 0x6c, 0xf9, - 0x10, 0x34, 0xdf, 0xed, 0x88, 0x49, 0x34, 0x3f, 0xda, 0x26, 0xd1, 0xfc, 0x09, 0x18, 0x25, 0xcb, - 0xe1, 0xc0, 0x15, 0x06, 0xa2, 0xed, 0x91, 0xd2, 0x09, 0x9f, 0x4b, 0xb8, 0x9e, 0xad, 0x96, 0x2f, - 0x07, 0xef, 0x30, 0x0c, 0x13, 0x0c, 0xdf, 0x31, 0x13, 0xf2, 0x63, 0xfe, 0xb2, 0x34, 0x50, 0x29, - 0x2b, 0xd0, 0x50, 0xaf, 0x95, 0x59, 0x01, 0xad, 0x00, 0xda, 0xf3, 0x76, 0x46, 0x2a, 0xbe, 0x3a, - 0x09, 0xfd, 0x9d, 0x37, 0x6f, 0x4c, 0x9f, 0x60, 0xf4, 0xad, 0x38, 0xb2, 0x32, 0xee, 0x03, 0x05, - 0xb7, 0xc7, 0x01, 0x48, 0xbf, 0x2a, 0xec, 0xfa, 0x1c, 0x5b, 0xee, 0x1c, 0xbd, 0x79, 0x63, 0x7a, - 0x9c, 0x71, 0xf1, 0xeb, 0x64, 0x25, 0x43, 0x0a, 0x8b, 0xe4, 0x77, 0xc0, 0xb2, 0x3f, 0x2d, 0x01, - 0xf2, 0x5d, 0xbe, 0x82, 0x1d, 0x8b, 0xac, 0xcf, 0x48, 0x22, 0x1e, 0xc8, 0x9a, 0xa5, 0xee, 0x89, - 0xb8, 0x4f, 0x2f, 0x12, 0xf1, 0xc0, 0x4c, 0x79, 0xca, 0x77, 0x8f, 0x09, 0x3e, 0x8e, 0x6d, 0xee, - 0x1a, 0xce, 0x2e, 0x98, 0xba, 0xa0, 0x6e, 0xf1, 0x87, 0x47, 0xe4, 0x7f, 0x25, 0xc1, 0x89, 0x16, - 0x8b, 0xf2, 0x84, 0xfd, 0x4b, 0x80, 0xec, 0x40, 0x25, 0xff, 0xde, 0x1b, 0x13, 0xba, 0x6f, 0x03, - 0x1d, 0xb7, 0x5b, 0xfc, 0xee, 0xad, 0xf3, 0xf0, 0xec, 0xb2, 0xe2, 0x3f, 0x95, 0x60, 0x32, 0xd8, - 0xbc, 0xd7, 0x91, 0x35, 0xc8, 0x06, 0x5b, 0xe7, 0x5d, 0xb8, 0xa7, 0x97, 0x2e, 0x70, 0xe9, 0x43, - 0xf4, 0xe8, 0x39, 0x7f, 0xba, 0xb2, 0xbd, 0xb3, 0x47, 0x7b, 0xd6, 0x86, 0x90, 0x29, 0x3a, 0x6d, - 0x53, 0x74, 0x3c, 0xfe, 0x8f, 0x04, 0xa9, 0x0d, 0xd3, 0xac, 0x23, 0x13, 0xc6, 0x0d, 0xd3, 0xad, - 0x10, 0xcb, 0xc2, 0xd5, 0x0a, 0x5f, 0x74, 0x33, 0x3f, 0xb8, 0xd0, 0x9f, 0x92, 0xbe, 0x7d, 0x63, - 0xba, 0x95, 0x95, 0x32, 0x66, 0x98, 0x6e, 0x89, 0x42, 0xb6, 0xd8, 0x92, 0xfc, 0x9d, 0x30, 0x12, - 0x6e, 0x8c, 0x79, 0xc9, 0xe7, 0xfb, 0x6e, 0x2c, 0xcc, 0xe6, 0xe6, 0x8d, 0xe9, 0x49, 0x7f, 0xc6, - 0x78, 0x60, 0x59, 0xc9, 0xee, 0x04, 0x5a, 0x67, 0xd7, 0xbb, 0xbe, 0xfb, 0xc9, 0x69, 0xe9, 0xf4, - 0x17, 0x25, 0x00, 0x7f, 0xe7, 0x01, 0x3d, 0x04, 0xc7, 0x4b, 0xeb, 0x6b, 0x8b, 0x95, 0xcd, 0xad, - 0xf9, 0xad, 0xed, 0xcd, 0xca, 0xf6, 0xda, 0xe6, 0x46, 0x79, 0x61, 0xf9, 0xc2, 0x72, 0x79, 0xd1, - 0xdf, 0x1e, 0x77, 0x2c, 0xac, 0xe9, 0xbb, 0x3a, 0xae, 0xa2, 0xfb, 0x60, 0x32, 0x8c, 0x4d, 0x4a, - 0xe5, 0xc5, 0x9c, 0x54, 0xc8, 0xbe, 0x7a, 0x7d, 0x26, 0xcd, 0x72, 0x31, 0x5c, 0x45, 0xa7, 0xe0, - 0x68, 0x2b, 0xde, 0xf2, 0xda, 0x52, 0x2e, 0x51, 0x18, 0x79, 0xf5, 0xfa, 0x4c, 0xc6, 0x4b, 0xda, - 0x90, 0x0c, 0x28, 0x88, 0xc9, 0xf9, 0x25, 0x0b, 0xf0, 0xea, 0xf5, 0x99, 0x41, 0xa6, 0xc0, 0x42, - 0xea, 0xfd, 0x9f, 0x9e, 0x3a, 0x52, 0xba, 0xd0, 0x71, 0x03, 0xfc, 0xa1, 0xae, 0xba, 0xbb, 0xe6, - 0x6d, 0x6a, 0x87, 0x77, 0xbd, 0xff, 0x78, 0xa8, 0xe3, 0xae, 0x77, 0x0d, 0x1b, 0xd8, 0xd1, 0x9d, - 0x43, 0xed, 0x7a, 0xf7, 0xb4, 0x93, 0x2e, 0xff, 0xce, 0x00, 0x64, 0x97, 0x58, 0x2b, 0x64, 0x20, - 0x30, 0x7a, 0x13, 0x0c, 0x5a, 0x34, 0x8c, 0x78, 0xc7, 0x68, 0x1d, 0x0c, 0x9e, 0x05, 0x1b, 0xef, - 0x2e, 0x17, 0x0b, 0x3d, 0x0e, 0xbf, 0xcc, 0xc1, 0xee, 0x98, 0xf9, 0xb7, 0xa6, 0xb2, 0x7d, 0xed, - 0xf7, 0xb0, 0x9c, 0x85, 0x6f, 0xad, 0x44, 0xf9, 0xc9, 0xec, 0x5e, 0xc8, 0x16, 0x81, 0xb0, 0xdb, - 0x61, 0xef, 0x95, 0xe0, 0x28, 0xc5, 0xf2, 0x03, 0x31, 0xc5, 0x14, 0xc9, 0xfe, 0xe9, 0x4e, 0x5d, - 0x58, 0x51, 0x1d, 0xff, 0xae, 0x07, 0xbb, 0xcf, 0x75, 0x0f, 0x0f, 0x84, 0x27, 0x03, 0x8d, 0x47, - 0xd9, 0xca, 0xca, 0x44, 0xbd, 0x85, 0xd2, 0x41, 0x4b, 0xa1, 0x0b, 0x7d, 0xa9, 0xfe, 0xb6, 0xda, - 0x83, 0x97, 0xfb, 0x9e, 0x85, 0x61, 0xdf, 0x97, 0x38, 0xfc, 0xff, 0x53, 0xf4, 0x1e, 0x3b, 0x82, - 0xc4, 0xe8, 0x7d, 0x12, 0x1c, 0xf5, 0xa3, 0x79, 0x90, 0x2d, 0xfb, 0x3f, 0x1e, 0x0f, 0xf6, 0xb1, - 0x10, 0x8a, 0x2a, 0xa7, 0x2d, 0x5f, 0x59, 0x99, 0x6c, 0xb6, 0x92, 0x92, 0x25, 0xd8, 0x48, 0xd0, - 0xb3, 0x3a, 0x79, 0xf1, 0xa9, 0xba, 0xde, 0x5d, 0x73, 0x98, 0x01, 0xfb, 0xdf, 0x02, 0x96, 0x69, - 0xbb, 0xb8, 0x4a, 0x37, 0xe4, 0xd2, 0x8a, 0x57, 0x96, 0xd7, 0x00, 0xb5, 0x0e, 0x6e, 0xf4, 0x02, - 0x63, 0xc6, 0xbf, 0xc0, 0x38, 0x09, 0x03, 0xc1, 0x2b, 0x7e, 0xac, 0x50, 0x4c, 0xbf, 0x9f, 0x87, - 0xcf, 0x5b, 0x3e, 0xe7, 0xff, 0x45, 0x02, 0x4e, 0x07, 0x8f, 0x87, 0x5e, 0x6a, 0x62, 0xfb, 0xc0, - 0x9b, 0xa2, 0x96, 0x5a, 0xd3, 0x8d, 0xe0, 0x1b, 0xa0, 0x13, 0xc1, 0x80, 0x4f, 0x71, 0x85, 0x9e, - 0x64, 0x03, 0x86, 0x37, 0xd4, 0x1a, 0x56, 0xf0, 0x4b, 0x4d, 0xec, 0xb8, 0x6d, 0x2e, 0x99, 0x1f, - 0x83, 0x41, 0x73, 0x77, 0x57, 0x1c, 0x69, 0xa7, 0x14, 0x5e, 0x22, 0x5d, 0xae, 0xeb, 0x0d, 0x9d, - 0xdd, 0x06, 0x4b, 0x29, 0xac, 0x80, 0xa6, 0x61, 0x58, 0x33, 0x9b, 0x06, 0x9f, 0x71, 0xf9, 0x94, - 0xf8, 0x00, 0x44, 0xd3, 0x60, 0x33, 0x4e, 0x7e, 0x06, 0xb2, 0xac, 0x3d, 0x1e, 0x71, 0x4f, 0x40, - 0x9a, 0x5e, 0xa7, 0xf2, 0x5b, 0x1d, 0x22, 0xe5, 0x4b, 0xec, 0x42, 0x3a, 0xe3, 0xc2, 0x1a, 0x66, - 0x85, 0x52, 0xa9, 0xa3, 0x2a, 0x4f, 0xc5, 0xbb, 0x06, 0xa6, 0x28, 0x4f, 0x8d, 0xbf, 0x39, 0x00, - 0x47, 0xf9, 0x09, 0x9d, 0x6a, 0xe9, 0x73, 0x7b, 0xae, 0x2b, 0x5e, 0x09, 0x01, 0x4f, 0x75, 0x55, - 0x4b, 0x97, 0x0f, 0x20, 0x75, 0xd1, 0x75, 0x2d, 0x74, 0x1a, 0x06, 0xec, 0x66, 0x1d, 0x8b, 0x1d, - 0x1f, 0x6f, 0x4f, 0x5e, 0xb5, 0xf4, 0x59, 0x82, 0xa0, 0x34, 0xeb, 0x58, 0x61, 0x28, 0xa8, 0x0c, - 0xd3, 0xbb, 0xcd, 0x7a, 0xfd, 0xa0, 0x52, 0xc5, 0xf4, 0x7f, 0xf7, 0x78, 0x5f, 0xbf, 0xc7, 0xd7, - 0x2c, 0x55, 0x7c, 0x43, 0x8f, 0xe8, 0xe6, 0x24, 0x45, 0x5b, 0xa4, 0x58, 0xe2, 0xcb, 0xf7, 0x65, - 0x81, 0x23, 0xff, 0x5e, 0x02, 0xd2, 0x82, 0x35, 0xbd, 0x21, 0x8e, 0xeb, 0x58, 0x73, 0x4d, 0x71, - 0x62, 0xe2, 0x95, 0x11, 0x82, 0x64, 0x8d, 0x0f, 0x51, 0xe6, 0xe2, 0x11, 0x85, 0x14, 0x08, 0xcc, - 0xbb, 0xb7, 0x4f, 0x60, 0x56, 0x93, 0x8c, 0x5a, 0xca, 0x32, 0xc5, 0xd2, 0xec, 0xe2, 0x11, 0x85, - 0x96, 0x50, 0x1e, 0x06, 0xc9, 0xcc, 0x70, 0xd9, 0x87, 0x09, 0x09, 0x9c, 0x97, 0xd1, 0x31, 0x18, - 0xb0, 0x54, 0x57, 0x63, 0x57, 0xea, 0x48, 0x05, 0x2b, 0xa2, 0x27, 0x60, 0x90, 0x3d, 0x08, 0x8d, - 0xfe, 0x63, 0x0c, 0xa2, 0x0c, 0xf6, 0xe5, 0x2d, 0x22, 0xf7, 0x86, 0xea, 0xba, 0xd8, 0x36, 0x08, - 0x43, 0x86, 0x8e, 0x10, 0xa4, 0x76, 0xcc, 0xea, 0x01, 0xff, 0x67, 0x1d, 0xf4, 0x37, 0xff, 0xef, - 0x00, 0xd4, 0x1e, 0x2a, 0xb4, 0x92, 0xfd, 0x8f, 0xa2, 0xac, 0x00, 0x96, 0x08, 0x52, 0x19, 0x26, - 0xd4, 0x6a, 0x55, 0x67, 0xff, 0x37, 0xa3, 0xb2, 0xa3, 0x53, 0x0f, 0xe1, 0xd0, 0xff, 0x40, 0xd5, - 0x69, 0x2c, 0x90, 0x4f, 0x50, 0xe2, 0xf8, 0xa5, 0x0c, 0x0c, 0x59, 0x4c, 0x28, 0xf9, 0x3c, 0x8c, - 0xb7, 0x48, 0x4a, 0xe4, 0xdb, 0xd7, 0x8d, 0xaa, 0x78, 0xcc, 0x40, 0x7e, 0x13, 0x18, 0xfd, 0x7a, - 0x1e, 0x3b, 0x8b, 0xa2, 0xbf, 0x4b, 0xef, 0xee, 0xfc, 0xf0, 0x6b, 0x34, 0xf0, 0xf0, 0x4b, 0xb5, - 0xf4, 0x52, 0x86, 0xf2, 0xe7, 0xcf, 0xbd, 0xe6, 0x79, 0x05, 0x7b, 0xea, 0x35, 0x6b, 0xda, 0x35, - 0x12, 0xa5, 0x45, 0xf4, 0x25, 0x55, 0xaa, 0xa5, 0x3b, 0xd4, 0x1c, 0xfd, 0xaf, 0xf9, 0x39, 0xe7, - 0x03, 0xbf, 0xe9, 0x23, 0xb0, 0xd4, 0xd2, 0xfc, 0xc6, 0xb2, 0x67, 0xc7, 0x5f, 0x4e, 0xc0, 0xc9, - 0x80, 0x1d, 0x07, 0x90, 0x5b, 0xcd, 0xb9, 0xd0, 0xde, 0xe2, 0x7b, 0x78, 0xfc, 0x75, 0x09, 0x52, - 0x04, 0x1f, 0xc5, 0x7c, 0xbb, 0x3f, 0xff, 0xab, 0x5f, 0xfb, 0x27, 0x72, 0xf8, 0xd4, 0x2a, 0x34, - 0x2a, 0x94, 0x49, 0xe9, 0x7d, 0xbd, 0xeb, 0x2f, 0xe7, 0x7f, 0xc8, 0xd0, 0xb9, 0x75, 0x6a, 0x8c, - 0xea, 0xf0, 0x5b, 0x67, 0x41, 0xee, 0x90, 0xf2, 0x30, 0x8f, 0xd9, 0x3d, 0x89, 0xea, 0xc3, 0x1d, - 0x77, 0xba, 0xff, 0xdf, 0x6d, 0x04, 0x7b, 0x4c, 0xc7, 0xae, 0xc1, 0xb1, 0xe7, 0x48, 0xdb, 0xfe, - 0x32, 0x59, 0x38, 0xf6, 0x63, 0xde, 0x69, 0x9e, 0xc4, 0xff, 0x01, 0x98, 0x38, 0xa9, 0x03, 0x5f, - 0x3e, 0xbe, 0x40, 0xbc, 0x6f, 0xb6, 0x63, 0xbc, 0x98, 0x0d, 0x04, 0x0b, 0x25, 0x40, 0x29, 0xff, - 0xb2, 0x04, 0xc7, 0x5b, 0x9a, 0xe6, 0x3e, 0x7e, 0xa9, 0xcd, 0x53, 0x85, 0x43, 0x65, 0x36, 0x4b, - 0x6d, 0x84, 0xbd, 0x3f, 0x56, 0x58, 0x26, 0x45, 0x48, 0xda, 0xa7, 0xe1, 0x68, 0x58, 0x58, 0xa1, - 0xa6, 0x7b, 0x61, 0x34, 0xbc, 0x23, 0xcc, 0xd5, 0x35, 0x12, 0xda, 0x13, 0x96, 0x2b, 0x51, 0x3d, - 0x7b, 0x7d, 0x2d, 0x43, 0xc6, 0x43, 0xe5, 0x29, 0x70, 0xcf, 0x5d, 0xf5, 0x29, 0xe5, 0x0f, 0x4b, - 0x30, 0x13, 0x6e, 0x21, 0x90, 0x0c, 0xf5, 0x27, 0xec, 0x2d, 0x1b, 0xe2, 0x37, 0x24, 0xb8, 0xab, - 0x8b, 0x4c, 0x5c, 0x01, 0x2f, 0xc3, 0x64, 0x60, 0x27, 0x40, 0xb8, 0x70, 0x31, 0xec, 0xa7, 0xe3, - 0xd3, 0x50, 0x6f, 0xe1, 0x7b, 0x07, 0x51, 0xca, 0x67, 0x7f, 0x7f, 0x7a, 0xa2, 0xb5, 0xce, 0x51, - 0x26, 0x5a, 0x57, 0xef, 0xb7, 0xd0, 0x3e, 0x5e, 0x93, 0xe0, 0x81, 0x70, 0x57, 0xdb, 0xe4, 0xb3, - 0x3f, 0xaa, 0x71, 0xf8, 0xf7, 0x12, 0x9c, 0xee, 0x45, 0x38, 0x3e, 0x20, 0x3b, 0x30, 0xe1, 0x67, - 0xda, 0xd1, 0xf1, 0xe8, 0x2b, 0x7f, 0x67, 0x56, 0x8a, 0x3c, 0x6e, 0xb7, 0x41, 0xf1, 0x16, 0x9f, - 0x58, 0xc1, 0x21, 0xf7, 0x94, 0x1c, 0xde, 0xcd, 0x15, 0x4a, 0x0e, 0xed, 0xe7, 0xb6, 0x19, 0x8b, - 0x44, 0x9b, 0xb1, 0xf0, 0x53, 0x73, 0xf9, 0x0a, 0xf7, 0x5b, 0x6d, 0xf6, 0xe0, 0xde, 0x06, 0x13, - 0x6d, 0x4c, 0x99, 0xcf, 0xea, 0x3e, 0x2c, 0x59, 0x41, 0xad, 0xc6, 0x2a, 0x1f, 0xc0, 0x34, 0x6d, - 0xb7, 0x8d, 0xa2, 0x6f, 0x77, 0x97, 0x1b, 0xdc, 0xb7, 0xb4, 0x6d, 0x9a, 0xf7, 0x7d, 0x19, 0x06, - 0xd9, 0x38, 0xf3, 0xee, 0x1e, 0xc2, 0x50, 0x38, 0x03, 0xf9, 0xe7, 0x85, 0x2f, 0x5b, 0x14, 0x62, - 0xb7, 0x9f, 0x43, 0xbd, 0xf4, 0xf5, 0x16, 0xcd, 0xa1, 0x80, 0x32, 0xbe, 0x21, 0xbc, 0x5a, 0x7b, - 0xe9, 0xb8, 0x3a, 0xb4, 0x5b, 0xe6, 0xd5, 0x98, 0x6e, 0x6e, 0xaf, 0xfb, 0xfa, 0x45, 0xe1, 0xbe, - 0xbc, 0x3e, 0xc5, 0xb8, 0xaf, 0x1f, 0x8d, 0xea, 0x3d, 0x47, 0x16, 0x23, 0xe6, 0x9f, 0x47, 0x47, - 0xf6, 0x5d, 0x09, 0x4e, 0xd0, 0xbe, 0x05, 0x37, 0x22, 0xfa, 0x55, 0xf9, 0x43, 0x80, 0x1c, 0x5b, - 0xab, 0xb4, 0x9d, 0xdd, 0x39, 0xc7, 0xd6, 0x2e, 0x87, 0xe2, 0xcb, 0x43, 0x80, 0xaa, 0xa1, 0xed, - 0x26, 0x8a, 0xcd, 0x6e, 0xc9, 0xe5, 0xaa, 0x81, 0xdd, 0x8c, 0x36, 0xc3, 0x99, 0xba, 0x05, 0xc3, - 0xf9, 0x75, 0x09, 0x0a, 0xed, 0xba, 0xcc, 0x87, 0x4f, 0x87, 0x63, 0xa1, 0x43, 0x82, 0xe8, 0x08, - 0x3e, 0xd4, 0xcb, 0x56, 0x4e, 0x64, 0x1a, 0x1d, 0xb5, 0xf1, 0xed, 0xce, 0x03, 0xa6, 0xc3, 0x16, - 0xda, 0x9a, 0x59, 0xff, 0xc8, 0xa6, 0xcf, 0x17, 0x5a, 0xfc, 0xea, 0x9f, 0x8b, 0xdc, 0xfb, 0x1a, - 0x4c, 0x75, 0x90, 0xfa, 0x76, 0xc7, 0xbd, 0xbd, 0x8e, 0x83, 0x79, 0xab, 0xd3, 0xf7, 0xc7, 0xf9, - 0x4c, 0x08, 0xdf, 0xc0, 0x0e, 0xac, 0xc5, 0xda, 0x3d, 0xe1, 0x92, 0xdf, 0x02, 0x77, 0xb4, 0xa5, - 0xe2, 0xb2, 0x15, 0x21, 0xb5, 0xa7, 0x3b, 0x2e, 0x17, 0xeb, 0xbe, 0x4e, 0x62, 0x45, 0xa8, 0x29, - 0x8d, 0x8c, 0x20, 0x47, 0x59, 0x6f, 0x98, 0x66, 0x9d, 0x8b, 0x21, 0x5f, 0x82, 0xf1, 0x00, 0x8c, - 0x37, 0x72, 0x0e, 0x52, 0x96, 0xc9, 0x3f, 0x4f, 0x30, 0x7c, 0xe6, 0x64, 0xc7, 0xdd, 0x7b, 0xd3, - 0xac, 0xf3, 0x6e, 0x53, 0x7c, 0x79, 0x12, 0x10, 0x63, 0x46, 0x37, 0xf2, 0x45, 0x13, 0x9b, 0x30, - 0x11, 0x82, 0xf2, 0x46, 0x7e, 0xa0, 0x43, 0x82, 0x33, 0xdf, 0x3e, 0x0a, 0x03, 0x94, 0x2b, 0xfa, - 0x98, 0x04, 0x10, 0x38, 0x11, 0x9e, 0xed, 0xc4, 0xa6, 0xfd, 0x9a, 0xb8, 0x30, 0xd7, 0x33, 0x3e, - 0xcf, 0xd9, 0x4e, 0xbf, 0xfb, 0xdf, 0x7c, 0xeb, 0x23, 0x89, 0x7b, 0x90, 0x3c, 0xd7, 0x61, 0x35, - 0x1e, 0x98, 0x2f, 0x9f, 0x09, 0xbd, 0x7d, 0x7f, 0xb8, 0xb7, 0xa6, 0x84, 0x64, 0xb3, 0xbd, 0xa2, - 0x73, 0xc1, 0xce, 0x53, 0xc1, 0xce, 0xa2, 0xc7, 0xe2, 0x05, 0x9b, 0x7b, 0x47, 0x78, 0xd2, 0xbc, - 0x0b, 0xfd, 0x8e, 0x04, 0x93, 0xed, 0x96, 0x74, 0xe8, 0xc9, 0xde, 0xa4, 0x68, 0x4d, 0x29, 0x0a, - 0x4f, 0x1d, 0x82, 0x92, 0x77, 0x65, 0x89, 0x76, 0x65, 0x1e, 0x3d, 0x73, 0x88, 0xae, 0xcc, 0x05, - 0xf7, 0xf7, 0xff, 0x97, 0x04, 0x77, 0x76, 0x5d, 0x21, 0xa1, 0xf9, 0xde, 0xa4, 0xec, 0x92, 0x3b, - 0x15, 0x4a, 0x3f, 0x08, 0x0b, 0xde, 0xe3, 0xe7, 0x68, 0x8f, 0x2f, 0xa1, 0xe5, 0xc3, 0xf4, 0xb8, - 0xed, 0x21, 0x0a, 0xfa, 0xad, 0xf0, 0xcd, 0xc2, 0xee, 0xe6, 0xd4, 0xb2, 0xf0, 0x88, 0x99, 0x18, - 0xad, 0x49, 0xad, 0xfc, 0x02, 0xed, 0x82, 0x82, 0x36, 0x7e, 0xc0, 0x41, 0x9b, 0x7b, 0x47, 0xd8, - 0xf1, 0xbf, 0x0b, 0xfd, 0x4f, 0xa9, 0xfd, 0x45, 0xc1, 0x27, 0xba, 0x8a, 0xd8, 0x79, 0x51, 0x55, - 0x78, 0xb2, 0x7f, 0x42, 0xde, 0xc9, 0x06, 0xed, 0x64, 0x0d, 0xe1, 0x5b, 0xdd, 0xc9, 0xb6, 0x83, - 0x88, 0xbe, 0x2a, 0xc1, 0x64, 0xbb, 0x35, 0x49, 0xcc, 0xb4, 0xec, 0xb2, 0xc8, 0x8a, 0x99, 0x96, - 0xdd, 0x16, 0x40, 0xf2, 0x9b, 0x68, 0xe7, 0xcf, 0xa1, 0xc7, 0x3b, 0x75, 0xbe, 0xeb, 0x28, 0x92, - 0xb9, 0xd8, 0x35, 0xc9, 0x8f, 0x99, 0x8b, 0xbd, 0xac, 0x63, 0x62, 0xe6, 0x62, 0x4f, 0x6b, 0x8c, - 0xf8, 0xb9, 0xe8, 0xf5, 0xac, 0xc7, 0x61, 0x74, 0xd0, 0x97, 0x25, 0x18, 0x09, 0x65, 0xc4, 0xe8, - 0xd1, 0xae, 0x82, 0xb6, 0x5b, 0x30, 0x14, 0xce, 0xf4, 0x43, 0xc2, 0xfb, 0xb2, 0x4c, 0xfb, 0xb2, - 0x80, 0xe6, 0x0f, 0xd3, 0x97, 0xf0, 0x59, 0xe9, 0xd7, 0x25, 0x98, 0x68, 0x93, 0x65, 0xc6, 0xcc, - 0xc2, 0xce, 0x49, 0x73, 0xe1, 0xc9, 0xfe, 0x09, 0x79, 0xaf, 0x2e, 0xd0, 0x5e, 0xfd, 0x04, 0x7a, - 0xfa, 0x30, 0xbd, 0x0a, 0xc4, 0xe7, 0x1b, 0xfe, 0xbd, 0xab, 0x40, 0x3b, 0xe8, 0x5c, 0x9f, 0x82, - 0x89, 0x0e, 0x3d, 0xd1, 0x37, 0x1d, 0xef, 0xcf, 0xf3, 0xb4, 0x3f, 0xcf, 0xa1, 0xf5, 0x1f, 0xac, - 0x3f, 0xad, 0x61, 0xfd, 0xf3, 0xad, 0x2f, 0x00, 0xbb, 0x5b, 0x51, 0xdb, 0x64, 0xb5, 0xf0, 0x58, - 0x5f, 0x34, 0xbc, 0x53, 0x4f, 0xd2, 0x4e, 0x9d, 0x41, 0x8f, 0x74, 0xea, 0x54, 0xe0, 0x72, 0x9d, - 0x6e, 0xec, 0x9a, 0x73, 0xef, 0x60, 0x29, 0xf0, 0xbb, 0xd0, 0x4f, 0x89, 0x8b, 0x4d, 0xa7, 0xba, - 0xb6, 0x1b, 0xc8, 0x63, 0x0b, 0x0f, 0xf4, 0x80, 0xc9, 0xe5, 0xba, 0x87, 0xca, 0x35, 0x85, 0x4e, - 0x76, 0x92, 0x8b, 0xe4, 0xb2, 0xe8, 0x03, 0x92, 0x77, 0x17, 0xf2, 0x74, 0x77, 0xde, 0xc1, 0x64, - 0xb7, 0xf0, 0x60, 0x4f, 0xb8, 0x5c, 0x92, 0xfb, 0xa8, 0x24, 0x33, 0x68, 0xaa, 0xa3, 0x24, 0x2c, - 0xf5, 0xbd, 0xd5, 0x37, 0x07, 0x5e, 0x3d, 0x0e, 0xd3, 0x1d, 0x5a, 0x74, 0xaf, 0xc5, 0x9c, 0x71, - 0x75, 0x79, 0x08, 0x1b, 0xfb, 0xd0, 0xb5, 0xc3, 0xd3, 0xda, 0xc3, 0x3f, 0x7f, 0xed, 0xed, 0x40, - 0xec, 0x5f, 0xa7, 0x00, 0xad, 0x3a, 0xb5, 0x05, 0x1b, 0xb3, 0x7f, 0x7a, 0xc7, 0x67, 0x79, 0xe4, - 0x85, 0x97, 0xf4, 0x03, 0xbd, 0xf0, 0x5a, 0x0d, 0xbd, 0x99, 0x4a, 0xf4, 0xf7, 0x2e, 0xb3, 0xe7, - 0x87, 0x53, 0xc9, 0x1f, 0xca, 0xc3, 0xa9, 0xf6, 0xf7, 0xaa, 0x53, 0xb7, 0xee, 0x01, 0xc6, 0xc0, - 0x61, 0x1f, 0xa1, 0xf0, 0xf7, 0x90, 0x83, 0x5d, 0xde, 0x43, 0xe6, 0x3b, 0x3e, 0x7a, 0xe4, 0xd4, - 0xe8, 0xac, 0xf8, 0x80, 0xef, 0x50, 0x6f, 0x37, 0x61, 0xf9, 0x17, 0x7e, 0xfd, 0x2d, 0x84, 0x93, - 0x50, 0x68, 0x35, 0x27, 0x6f, 0x52, 0x7f, 0x24, 0x09, 0xb9, 0x55, 0xa7, 0x56, 0xae, 0xea, 0xee, - 0x6d, 0xb2, 0xb5, 0x67, 0x3a, 0x3f, 0x6a, 0x41, 0x37, 0x6f, 0x4c, 0x8f, 0x32, 0x9d, 0x76, 0xd1, - 0x64, 0x03, 0xc6, 0x22, 0x4f, 0x89, 0xb9, 0x65, 0x2d, 0x1e, 0xe6, 0x45, 0x73, 0x84, 0x95, 0x4c, - 0xdf, 0x20, 0x04, 0xec, 0x1b, 0x5d, 0x6b, 0x6f, 0xcc, 0xcc, 0xa0, 0x2e, 0xde, 0xce, 0x17, 0x80, - 0xfe, 0x98, 0x15, 0x20, 0x1f, 0x1d, 0x14, 0x6f, 0xc4, 0xfe, 0x50, 0x82, 0xe1, 0x55, 0x47, 0xa4, - 0x82, 0xf8, 0xc7, 0xf4, 0xfd, 0xd1, 0x13, 0xde, 0x77, 0x58, 0x93, 0xbd, 0xd9, 0xad, 0xf8, 0x36, - 0xab, 0xaf, 0x84, 0xa3, 0x30, 0x11, 0xe8, 0xa7, 0xd7, 0xff, 0xdf, 0x4e, 0x50, 0xff, 0x58, 0xc2, - 0x35, 0xdd, 0xf0, 0xb2, 0x48, 0xfc, 0x17, 0xf5, 0x75, 0x85, 0xaf, 0xe7, 0xd4, 0x61, 0xf5, 0xbc, - 0x4f, 0x1d, 0x44, 0x44, 0x9f, 0xde, 0xc6, 0xd7, 0x6a, 0xeb, 0xdb, 0x1f, 0xa9, 0x8f, 0xcf, 0xea, - 0x44, 0x5e, 0xf8, 0xc8, 0x6f, 0x48, 0x30, 0xb2, 0xea, 0xd4, 0xb6, 0x8d, 0xea, 0xff, 0xf3, 0xf6, - 0xbb, 0x0b, 0x47, 0x43, 0x3d, 0xbd, 0x4d, 0x2a, 0x3d, 0xf3, 0x5a, 0x0a, 0x92, 0xab, 0x4e, 0x0d, - 0xbd, 0x04, 0x63, 0xd1, 0xa4, 0xa1, 0x63, 0x2e, 0xd8, 0x1a, 0x11, 0x3a, 0xaf, 0xd7, 0x3a, 0x47, - 0x0f, 0xb4, 0x0f, 0x23, 0xe1, 0xc8, 0x71, 0xaa, 0x0b, 0x93, 0x10, 0x66, 0xe1, 0x91, 0x5e, 0x31, - 0xbd, 0xc6, 0xde, 0x0e, 0x69, 0xcf, 0xe9, 0xdd, 0xdd, 0x85, 0x5a, 0x20, 0x75, 0xce, 0x6e, 0xdb, - 0xb8, 0x15, 0xa2, 0xbd, 0xa8, 0x4b, 0xe9, 0xa6, 0xbd, 0x08, 0x6e, 0x57, 0xed, 0x75, 0x9a, 0x5a, - 0x3b, 0x00, 0x81, 0x79, 0x70, 0x6f, 0x17, 0x0e, 0x3e, 0x5a, 0xe1, 0xe1, 0x9e, 0xd0, 0xbc, 0x43, - 0xa7, 0x5b, 0x9c, 0x8c, 0xff, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xd5, 0xca, 0x34, 0x9e, 0x6a, - 0x94, 0x00, 0x00, + // 9822 bytes of a gzipped FileDescriptorSet + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x7d, 0x6d, 0x70, 0x5c, 0xd7, + 0x75, 0x18, 0xde, 0x7e, 0x00, 0xbb, 0x07, 0x0b, 0x60, 0x71, 0x01, 0x92, 0xcb, 0x25, 0x09, 0x40, + 0x4f, 0x5f, 0x14, 0x25, 0x82, 0x12, 0x25, 0x52, 0xd2, 0xd2, 0x96, 0xbc, 0x8b, 0x5d, 0x82, 0x10, + 0xf1, 0xa5, 0x07, 0x80, 0x92, 0x65, 0xa7, 0x3b, 0x0f, 0xbb, 0x17, 0x8b, 0x27, 0xec, 0xbe, 0xf7, + 0xf4, 0xde, 0x5b, 0x12, 0x90, 0xed, 0x19, 0xc5, 0x76, 0x5d, 0x9b, 0x69, 0x6a, 0xbb, 0xce, 0xa4, + 0xb6, 0x62, 0xba, 0x76, 0x9c, 0xd6, 0xa9, 0xe3, 0x36, 0x1f, 0x76, 0xdd, 0xa6, 0xed, 0x4c, 0xed, + 0xb6, 0x69, 0x6c, 0xb7, 0xc9, 0xd8, 0x6d, 0xa6, 0x4d, 0x33, 0x2d, 0x9d, 0xca, 0x9e, 0x54, 0x75, + 0xdd, 0xc6, 0x61, 0x9c, 0x36, 0x1d, 0x4f, 0xa7, 0x9d, 0xfb, 0xf5, 0xbe, 0xf6, 0x13, 0x10, 0x69, + 0x3b, 0x4d, 0x7e, 0x61, 0xef, 0xb9, 0xe7, 0x9c, 0x7b, 0xee, 0xb9, 0xe7, 0x9c, 0x7b, 0xee, 0xd7, + 0x03, 0xfc, 0xf3, 0x0b, 0x30, 0x53, 0x33, 0x8c, 0x5a, 0x1d, 0x9f, 0x31, 0x2d, 0xc3, 0x31, 0x36, + 0x9b, 0x5b, 0x67, 0xaa, 0xd8, 0xae, 0x58, 0x9a, 0xe9, 0x18, 0xd6, 0x2c, 0x85, 0xa1, 0x31, 0x86, + 0x31, 0x2b, 0x30, 0xe4, 0x25, 0x18, 0xbf, 0xa8, 0xd5, 0x71, 0xd1, 0x45, 0x5c, 0xc3, 0x0e, 0x7a, + 0x02, 0x62, 0x5b, 0x5a, 0x1d, 0x67, 0xa4, 0x99, 0xe8, 0xc9, 0xe1, 0xb3, 0xf7, 0xcc, 0x86, 0x88, + 0x66, 0x83, 0x14, 0xab, 0x04, 0xac, 0x50, 0x0a, 0xf9, 0xdb, 0x31, 0x98, 0x68, 0x53, 0x8b, 0x10, + 0xc4, 0x74, 0xb5, 0x41, 0x38, 0x4a, 0x27, 0x93, 0x0a, 0xfd, 0x8d, 0x32, 0x30, 0x64, 0xaa, 0x95, + 0x1d, 0xb5, 0x86, 0x33, 0x11, 0x0a, 0x16, 0x45, 0x34, 0x05, 0x50, 0xc5, 0x26, 0xd6, 0xab, 0x58, + 0xaf, 0xec, 0x65, 0xa2, 0x33, 0xd1, 0x93, 0x49, 0xc5, 0x07, 0x41, 0x0f, 0xc2, 0xb8, 0xd9, 0xdc, + 0xac, 0x6b, 0x95, 0xb2, 0x0f, 0x0d, 0x66, 0xa2, 0x27, 0xe3, 0x4a, 0x9a, 0x55, 0x14, 0x3d, 0xe4, + 0xfb, 0x61, 0xec, 0x1a, 0x56, 0x77, 0xfc, 0xa8, 0xc3, 0x14, 0x75, 0x94, 0x80, 0x7d, 0x88, 0x73, + 0x90, 0x6a, 0x60, 0xdb, 0x56, 0x6b, 0xb8, 0xec, 0xec, 0x99, 0x38, 0x13, 0xa3, 0xbd, 0x9f, 0x69, + 0xe9, 0x7d, 0xb8, 0xe7, 0xc3, 0x9c, 0x6a, 0x7d, 0xcf, 0xc4, 0x28, 0x0f, 0x49, 0xac, 0x37, 0x1b, + 0x8c, 0x43, 0xbc, 0x83, 0xfe, 0x4a, 0x7a, 0xb3, 0x11, 0xe6, 0x92, 0x20, 0x64, 0x9c, 0xc5, 0x90, + 0x8d, 0xad, 0xab, 0x5a, 0x05, 0x67, 0x06, 0x29, 0x83, 0xfb, 0x5b, 0x18, 0xac, 0xb1, 0xfa, 0x30, + 0x0f, 0x41, 0x87, 0xe6, 0x20, 0x89, 0x77, 0x1d, 0xac, 0xdb, 0x9a, 0xa1, 0x67, 0x86, 0x28, 0x93, + 0x7b, 0xdb, 0x8c, 0x22, 0xae, 0x57, 0xc3, 0x2c, 0x3c, 0x3a, 0x74, 0x1e, 0x86, 0x0c, 0xd3, 0xd1, + 0x0c, 0xdd, 0xce, 0x24, 0x66, 0xa4, 0x93, 0xc3, 0x67, 0x8f, 0xb7, 0x35, 0x84, 0x15, 0x86, 0xa3, + 0x08, 0x64, 0xb4, 0x00, 0x69, 0xdb, 0x68, 0x5a, 0x15, 0x5c, 0xae, 0x18, 0x55, 0x5c, 0xd6, 0xf4, + 0x2d, 0x23, 0x93, 0xa4, 0x0c, 0xa6, 0x5b, 0x3b, 0x42, 0x11, 0xe7, 0x8c, 0x2a, 0x5e, 0xd0, 0xb7, + 0x0c, 0x65, 0xd4, 0x0e, 0x94, 0xd1, 0x61, 0x18, 0xb4, 0xf7, 0x74, 0x47, 0xdd, 0xcd, 0xa4, 0xa8, + 0x85, 0xf0, 0x92, 0xfc, 0xeb, 0x83, 0x30, 0xd6, 0x8f, 0x89, 0x5d, 0x80, 0xf8, 0x16, 0xe9, 0x65, + 0x26, 0xb2, 0x1f, 0x1d, 0x30, 0x9a, 0xa0, 0x12, 0x07, 0x0f, 0xa8, 0xc4, 0x3c, 0x0c, 0xeb, 0xd8, + 0x76, 0x70, 0x95, 0x59, 0x44, 0xb4, 0x4f, 0x9b, 0x02, 0x46, 0xd4, 0x6a, 0x52, 0xb1, 0x03, 0x99, + 0xd4, 0xf3, 0x30, 0xe6, 0x8a, 0x54, 0xb6, 0x54, 0xbd, 0x26, 0x6c, 0xf3, 0x4c, 0x2f, 0x49, 0x66, + 0x4b, 0x82, 0x4e, 0x21, 0x64, 0xca, 0x28, 0x0e, 0x94, 0x51, 0x11, 0xc0, 0xd0, 0xb1, 0xb1, 0x55, + 0xae, 0xe2, 0x4a, 0x3d, 0x93, 0xe8, 0xa0, 0xa5, 0x15, 0x82, 0xd2, 0xa2, 0x25, 0x83, 0x41, 0x2b, + 0x75, 0xf4, 0xa4, 0x67, 0x6a, 0x43, 0x1d, 0x2c, 0x65, 0x89, 0x39, 0x59, 0x8b, 0xb5, 0x6d, 0xc0, + 0xa8, 0x85, 0x89, 0xdd, 0xe3, 0x2a, 0xef, 0x59, 0x92, 0x0a, 0x31, 0xdb, 0xb3, 0x67, 0x0a, 0x27, + 0x63, 0x1d, 0x1b, 0xb1, 0xfc, 0x45, 0x74, 0x37, 0xb8, 0x80, 0x32, 0x35, 0x2b, 0xa0, 0x51, 0x28, + 0x25, 0x80, 0xcb, 0x6a, 0x03, 0x67, 0x5f, 0x86, 0xd1, 0xa0, 0x7a, 0xd0, 0x24, 0xc4, 0x6d, 0x47, + 0xb5, 0x1c, 0x6a, 0x85, 0x71, 0x85, 0x15, 0x50, 0x1a, 0xa2, 0x58, 0xaf, 0xd2, 0x28, 0x17, 0x57, + 0xc8, 0x4f, 0xf4, 0x16, 0xaf, 0xc3, 0x51, 0xda, 0xe1, 0xfb, 0x5a, 0x47, 0x34, 0xc0, 0x39, 0xdc, + 0xef, 0xec, 0xe3, 0x30, 0x12, 0xe8, 0x40, 0xbf, 0x4d, 0xcb, 0xef, 0x84, 0x43, 0x6d, 0x59, 0xa3, + 0xe7, 0x61, 0xb2, 0xa9, 0x6b, 0xba, 0x83, 0x2d, 0xd3, 0xc2, 0xc4, 0x62, 0x59, 0x53, 0x99, 0xff, + 0x32, 0xd4, 0xc1, 0xe6, 0x36, 0xfc, 0xd8, 0x8c, 0x8b, 0x32, 0xd1, 0x6c, 0x05, 0x9e, 0x4a, 0x26, + 0x5e, 0x1f, 0x4a, 0xbf, 0xf2, 0xca, 0x2b, 0xaf, 0x44, 0xe4, 0x2f, 0x0f, 0xc2, 0x64, 0x3b, 0x9f, + 0x69, 0xeb, 0xbe, 0x87, 0x61, 0x50, 0x6f, 0x36, 0x36, 0xb1, 0x45, 0x95, 0x14, 0x57, 0x78, 0x09, + 0xe5, 0x21, 0x5e, 0x57, 0x37, 0x71, 0x3d, 0x13, 0x9b, 0x91, 0x4e, 0x8e, 0x9e, 0x7d, 0xb0, 0x2f, + 0xaf, 0x9c, 0x5d, 0x24, 0x24, 0x0a, 0xa3, 0x44, 0x4f, 0x41, 0x8c, 0x87, 0x68, 0xc2, 0xe1, 0x54, + 0x7f, 0x1c, 0x88, 0x2f, 0x29, 0x94, 0x0e, 0x1d, 0x83, 0x24, 0xf9, 0xcb, 0x6c, 0x63, 0x90, 0xca, + 0x9c, 0x20, 0x00, 0x62, 0x17, 0x28, 0x0b, 0x09, 0xea, 0x26, 0x55, 0x2c, 0xa6, 0x36, 0xb7, 0x4c, + 0x0c, 0xab, 0x8a, 0xb7, 0xd4, 0x66, 0xdd, 0x29, 0x5f, 0x55, 0xeb, 0x4d, 0x4c, 0x0d, 0x3e, 0xa9, + 0xa4, 0x38, 0xf0, 0x0a, 0x81, 0xa1, 0x69, 0x18, 0x66, 0x5e, 0xa5, 0xe9, 0x55, 0xbc, 0x4b, 0xa3, + 0x67, 0x5c, 0x61, 0x8e, 0xb6, 0x40, 0x20, 0xa4, 0xf9, 0x17, 0x6d, 0x43, 0x17, 0xa6, 0x49, 0x9b, + 0x20, 0x00, 0xda, 0xfc, 0xe3, 0xe1, 0xc0, 0x7d, 0xa2, 0x7d, 0xf7, 0x5a, 0x7c, 0xe9, 0x7e, 0x18, + 0xa3, 0x18, 0x8f, 0xf2, 0xa1, 0x57, 0xeb, 0x99, 0xf1, 0x19, 0xe9, 0x64, 0x42, 0x19, 0x65, 0xe0, + 0x15, 0x0e, 0x95, 0xbf, 0x18, 0x81, 0x18, 0x0d, 0x2c, 0x63, 0x30, 0xbc, 0xfe, 0xd6, 0xd5, 0x52, + 0xb9, 0xb8, 0xb2, 0x51, 0x58, 0x2c, 0xa5, 0x25, 0x34, 0x0a, 0x40, 0x01, 0x17, 0x17, 0x57, 0xf2, + 0xeb, 0xe9, 0x88, 0x5b, 0x5e, 0x58, 0x5e, 0x3f, 0xff, 0x58, 0x3a, 0xea, 0x12, 0x6c, 0x30, 0x40, + 0xcc, 0x8f, 0xf0, 0xe8, 0xd9, 0x74, 0x1c, 0xa5, 0x21, 0xc5, 0x18, 0x2c, 0x3c, 0x5f, 0x2a, 0x9e, + 0x7f, 0x2c, 0x3d, 0x18, 0x84, 0x3c, 0x7a, 0x36, 0x3d, 0x84, 0x46, 0x20, 0x49, 0x21, 0x85, 0x95, + 0x95, 0xc5, 0x74, 0xc2, 0xe5, 0xb9, 0xb6, 0xae, 0x2c, 0x2c, 0xcf, 0xa7, 0x93, 0x2e, 0xcf, 0x79, + 0x65, 0x65, 0x63, 0x35, 0x0d, 0x2e, 0x87, 0xa5, 0xd2, 0xda, 0x5a, 0x7e, 0xbe, 0x94, 0x1e, 0x76, + 0x31, 0x0a, 0x6f, 0x5d, 0x2f, 0xad, 0xa5, 0x53, 0x01, 0xb1, 0x1e, 0x3d, 0x9b, 0x1e, 0x71, 0x9b, + 0x28, 0x2d, 0x6f, 0x2c, 0xa5, 0x47, 0xd1, 0x38, 0x8c, 0xb0, 0x26, 0x84, 0x10, 0x63, 0x21, 0xd0, + 0xf9, 0xc7, 0xd2, 0x69, 0x4f, 0x10, 0xc6, 0x65, 0x3c, 0x00, 0x38, 0xff, 0x58, 0x1a, 0xc9, 0x73, + 0x10, 0xa7, 0x66, 0x88, 0x10, 0x8c, 0x2e, 0xe6, 0x0b, 0xa5, 0xc5, 0xf2, 0xca, 0xea, 0xfa, 0xc2, + 0xca, 0x72, 0x7e, 0x31, 0x2d, 0x79, 0x30, 0xa5, 0xf4, 0xec, 0xc6, 0x82, 0x52, 0x2a, 0xa6, 0x23, + 0x7e, 0xd8, 0x6a, 0x29, 0xbf, 0x5e, 0x2a, 0xa6, 0xa3, 0x72, 0x05, 0x26, 0xdb, 0x05, 0xd4, 0xb6, + 0x2e, 0xe4, 0xb3, 0x85, 0x48, 0x07, 0x5b, 0xa0, 0xbc, 0xc2, 0xb6, 0x20, 0x7f, 0x2b, 0x02, 0x13, + 0x6d, 0x26, 0x95, 0xb6, 0x8d, 0x3c, 0x0d, 0x71, 0x66, 0xcb, 0x6c, 0x9a, 0x7d, 0xa0, 0xed, 0xec, + 0x44, 0x2d, 0xbb, 0x65, 0xaa, 0xa5, 0x74, 0xfe, 0x54, 0x23, 0xda, 0x21, 0xd5, 0x20, 0x2c, 0x5a, + 0x0c, 0xf6, 0x27, 0x5a, 0x82, 0x3f, 0x9b, 0x1f, 0xcf, 0xf7, 0x33, 0x3f, 0x52, 0xd8, 0xfe, 0x26, + 0x81, 0x78, 0x9b, 0x49, 0xe0, 0x02, 0x8c, 0xb7, 0x30, 0xea, 0x3b, 0x18, 0xbf, 0x47, 0x82, 0x4c, + 0x27, 0xe5, 0xf4, 0x08, 0x89, 0x91, 0x40, 0x48, 0xbc, 0x10, 0xd6, 0xe0, 0x5d, 0x9d, 0x07, 0xa1, + 0x65, 0xac, 0x3f, 0x23, 0xc1, 0xe1, 0xf6, 0x29, 0x65, 0x5b, 0x19, 0x9e, 0x82, 0xc1, 0x06, 0x76, + 0xb6, 0x0d, 0x91, 0x56, 0xdd, 0xd7, 0x66, 0xb2, 0x26, 0xd5, 0xe1, 0xc1, 0xe6, 0x54, 0xfe, 0xd9, + 0x3e, 0xda, 0x29, 0x2f, 0x64, 0xd2, 0xb4, 0x48, 0xfa, 0x81, 0x08, 0x1c, 0x6a, 0xcb, 0xbc, 0xad, + 0xa0, 0x27, 0x00, 0x34, 0xdd, 0x6c, 0x3a, 0x2c, 0x75, 0x62, 0x91, 0x38, 0x49, 0x21, 0x34, 0x78, + 0x91, 0x28, 0xdb, 0x74, 0xdc, 0xfa, 0x28, 0xad, 0x07, 0x06, 0xa2, 0x08, 0x4f, 0x78, 0x82, 0xc6, + 0xa8, 0xa0, 0x53, 0x1d, 0x7a, 0xda, 0x62, 0x98, 0x0f, 0x43, 0xba, 0x52, 0xd7, 0xb0, 0xee, 0x94, + 0x6d, 0xc7, 0xc2, 0x6a, 0x43, 0xd3, 0x6b, 0x74, 0xaa, 0x49, 0xe4, 0xe2, 0x5b, 0x6a, 0xdd, 0xc6, + 0xca, 0x18, 0xab, 0x5e, 0x13, 0xb5, 0x84, 0x82, 0x1a, 0x90, 0xe5, 0xa3, 0x18, 0x0c, 0x50, 0xb0, + 0x6a, 0x97, 0x42, 0xfe, 0x70, 0x12, 0x86, 0x7d, 0x09, 0x38, 0xba, 0x0b, 0x52, 0x2f, 0xaa, 0x57, + 0xd5, 0xb2, 0x58, 0x54, 0x31, 0x4d, 0x0c, 0x13, 0xd8, 0x2a, 0x5f, 0x58, 0x3d, 0x0c, 0x93, 0x14, + 0xc5, 0x68, 0x3a, 0xd8, 0x2a, 0x57, 0xea, 0xaa, 0x6d, 0x53, 0xa5, 0x25, 0x28, 0x2a, 0x22, 0x75, + 0x2b, 0xa4, 0x6a, 0x4e, 0xd4, 0xa0, 0x73, 0x30, 0x41, 0x29, 0x1a, 0xcd, 0xba, 0xa3, 0x99, 0x75, + 0x5c, 0x26, 0xcb, 0x3c, 0x9b, 0x4e, 0x39, 0xae, 0x64, 0xe3, 0x04, 0x63, 0x89, 0x23, 0x10, 0x89, + 0x6c, 0x54, 0x84, 0x13, 0x94, 0xac, 0x86, 0x75, 0x6c, 0xa9, 0x0e, 0x2e, 0xe3, 0x97, 0x9a, 0x6a, + 0xdd, 0x2e, 0xab, 0x7a, 0xb5, 0xbc, 0xad, 0xda, 0xdb, 0x99, 0x49, 0xc2, 0xa0, 0x10, 0xc9, 0x48, + 0xca, 0x51, 0x82, 0x38, 0xcf, 0xf1, 0x4a, 0x14, 0x2d, 0xaf, 0x57, 0x2f, 0xa9, 0xf6, 0x36, 0xca, + 0xc1, 0x61, 0xca, 0xc5, 0x76, 0x2c, 0x4d, 0xaf, 0x95, 0x2b, 0xdb, 0xb8, 0xb2, 0x53, 0x6e, 0x3a, + 0x5b, 0x4f, 0x64, 0x8e, 0xf9, 0xdb, 0xa7, 0x12, 0xae, 0x51, 0x9c, 0x39, 0x82, 0xb2, 0xe1, 0x6c, + 0x3d, 0x81, 0xd6, 0x20, 0x45, 0x06, 0xa3, 0xa1, 0xbd, 0x8c, 0xcb, 0x5b, 0x86, 0x45, 0xe7, 0xd0, + 0xd1, 0x36, 0xa1, 0xc9, 0xa7, 0xc1, 0xd9, 0x15, 0x4e, 0xb0, 0x64, 0x54, 0x71, 0x2e, 0xbe, 0xb6, + 0x5a, 0x2a, 0x15, 0x95, 0x61, 0xc1, 0xe5, 0xa2, 0x61, 0x11, 0x83, 0xaa, 0x19, 0xae, 0x82, 0x87, + 0x99, 0x41, 0xd5, 0x0c, 0xa1, 0xde, 0x73, 0x30, 0x51, 0xa9, 0xb0, 0x3e, 0x6b, 0x95, 0x32, 0x5f, + 0x8c, 0xd9, 0x99, 0x74, 0x40, 0x59, 0x95, 0xca, 0x3c, 0x43, 0xe0, 0x36, 0x6e, 0xa3, 0x27, 0xe1, + 0x90, 0xa7, 0x2c, 0x3f, 0xe1, 0x78, 0x4b, 0x2f, 0xc3, 0xa4, 0xe7, 0x60, 0xc2, 0xdc, 0x6b, 0x25, + 0x44, 0x81, 0x16, 0xcd, 0xbd, 0x30, 0xd9, 0xe3, 0x30, 0x69, 0x6e, 0x9b, 0xad, 0x74, 0xa7, 0xfc, + 0x74, 0xc8, 0xdc, 0x36, 0xc3, 0x84, 0xf7, 0xd2, 0x95, 0xb9, 0x85, 0x2b, 0xaa, 0x83, 0xab, 0x99, + 0x23, 0x7e, 0x74, 0x5f, 0x05, 0x9a, 0x85, 0x74, 0xa5, 0x52, 0xc6, 0xba, 0xba, 0x59, 0xc7, 0x65, + 0xd5, 0xc2, 0xba, 0x6a, 0x67, 0xa6, 0x29, 0x72, 0xcc, 0xb1, 0x9a, 0x58, 0x19, 0xad, 0x54, 0x4a, + 0xb4, 0x32, 0x4f, 0xeb, 0xd0, 0x29, 0x18, 0x37, 0x36, 0x5f, 0xac, 0x30, 0x8b, 0x2c, 0x9b, 0x16, + 0xde, 0xd2, 0x76, 0x33, 0xf7, 0x50, 0xf5, 0x8e, 0x91, 0x0a, 0x6a, 0x8f, 0xab, 0x14, 0x8c, 0x1e, + 0x80, 0x74, 0xc5, 0xde, 0x56, 0x2d, 0x93, 0x86, 0x64, 0xdb, 0x54, 0x2b, 0x38, 0x73, 0x2f, 0x43, + 0x65, 0xf0, 0x65, 0x01, 0x26, 0x1e, 0x61, 0x5f, 0xd3, 0xb6, 0x1c, 0xc1, 0xf1, 0x7e, 0xe6, 0x11, + 0x14, 0xc6, 0xb9, 0x9d, 0x84, 0x34, 0xd1, 0x44, 0xa0, 0xe1, 0x93, 0x14, 0x6d, 0xd4, 0xdc, 0x36, + 0xfd, 0xed, 0xde, 0x0d, 0x23, 0x04, 0xd3, 0x6b, 0xf4, 0x01, 0x96, 0xb8, 0x99, 0xdb, 0xbe, 0x16, + 0x1f, 0x83, 0xc3, 0x04, 0xa9, 0x81, 0x1d, 0xb5, 0xaa, 0x3a, 0xaa, 0x0f, 0xfb, 0x21, 0x8a, 0x4d, + 0xd4, 0xbe, 0xc4, 0x2b, 0x03, 0x72, 0x5a, 0xcd, 0xcd, 0x3d, 0xd7, 0xb0, 0x4e, 0x33, 0x39, 0x09, + 0x4c, 0x98, 0xd6, 0x1d, 0x4b, 0xce, 0xe5, 0x1c, 0xa4, 0xfc, 0x76, 0x8f, 0x92, 0xc0, 0x2c, 0x3f, + 0x2d, 0x91, 0x24, 0x68, 0x6e, 0xa5, 0x48, 0xd2, 0x97, 0x17, 0x4a, 0xe9, 0x08, 0x49, 0xa3, 0x16, + 0x17, 0xd6, 0x4b, 0x65, 0x65, 0x63, 0x79, 0x7d, 0x61, 0xa9, 0x94, 0x8e, 0xfa, 0x12, 0xfb, 0x67, + 0x62, 0x89, 0xfb, 0xd2, 0xf7, 0xcb, 0xdf, 0x88, 0xc0, 0x68, 0x70, 0xa5, 0x86, 0xde, 0x04, 0x47, + 0xc4, 0xb6, 0x8a, 0x8d, 0x9d, 0xf2, 0x35, 0xcd, 0xa2, 0x0e, 0xd9, 0x50, 0xd9, 0xe4, 0xe8, 0xda, + 0xcf, 0x24, 0xc7, 0x5a, 0xc3, 0xce, 0x73, 0x9a, 0x45, 0xdc, 0xad, 0xa1, 0x3a, 0x68, 0x11, 0xa6, + 0x75, 0xa3, 0x6c, 0x3b, 0xaa, 0x5e, 0x55, 0xad, 0x6a, 0xd9, 0xdb, 0xd0, 0x2a, 0xab, 0x95, 0x0a, + 0xb6, 0x6d, 0x83, 0x4d, 0x84, 0x2e, 0x97, 0xe3, 0xba, 0xb1, 0xc6, 0x91, 0xbd, 0x19, 0x22, 0xcf, + 0x51, 0x43, 0xe6, 0x1b, 0xed, 0x64, 0xbe, 0xc7, 0x20, 0xd9, 0x50, 0xcd, 0x32, 0xd6, 0x1d, 0x6b, + 0x8f, 0xe6, 0xe7, 0x09, 0x25, 0xd1, 0x50, 0xcd, 0x12, 0x29, 0xff, 0x50, 0x96, 0x49, 0xcf, 0xc4, + 0x12, 0x89, 0x74, 0xf2, 0x99, 0x58, 0x22, 0x99, 0x06, 0xf9, 0xb5, 0x28, 0xa4, 0xfc, 0xf9, 0x3a, + 0x59, 0xfe, 0x54, 0xe8, 0x8c, 0x25, 0xd1, 0x98, 0x76, 0x77, 0xd7, 0xec, 0x7e, 0x76, 0x8e, 0x4c, + 0x65, 0xb9, 0x41, 0x96, 0x1c, 0x2b, 0x8c, 0x92, 0xa4, 0x11, 0xc4, 0xd8, 0x30, 0x4b, 0x46, 0x12, + 0x0a, 0x2f, 0xa1, 0x79, 0x18, 0x7c, 0xd1, 0xa6, 0xbc, 0x07, 0x29, 0xef, 0x7b, 0xba, 0xf3, 0x7e, + 0x66, 0x8d, 0x32, 0x4f, 0x3e, 0xb3, 0x56, 0x5e, 0x5e, 0x51, 0x96, 0xf2, 0x8b, 0x0a, 0x27, 0x47, + 0x47, 0x21, 0x56, 0x57, 0x5f, 0xde, 0x0b, 0x4e, 0x7a, 0x14, 0xd4, 0xef, 0x20, 0x1c, 0x85, 0xd8, + 0x35, 0xac, 0xee, 0x04, 0xa7, 0x1a, 0x0a, 0xba, 0x83, 0xce, 0x70, 0x06, 0xe2, 0x54, 0x5f, 0x08, + 0x80, 0x6b, 0x2c, 0x3d, 0x80, 0x12, 0x10, 0x9b, 0x5b, 0x51, 0x88, 0x43, 0xa4, 0x21, 0xc5, 0xa0, + 0xe5, 0xd5, 0x85, 0xd2, 0x5c, 0x29, 0x1d, 0x91, 0xcf, 0xc1, 0x20, 0x53, 0x02, 0x71, 0x16, 0x57, + 0x0d, 0xe9, 0x01, 0x5e, 0xe4, 0x3c, 0x24, 0x51, 0xbb, 0xb1, 0x54, 0x28, 0x29, 0xe9, 0x48, 0x70, + 0xa8, 0x63, 0xe9, 0xb8, 0x6c, 0x43, 0xca, 0x9f, 0x87, 0xff, 0x70, 0x16, 0xe3, 0x5f, 0x92, 0x60, + 0xd8, 0x97, 0x57, 0x93, 0x84, 0x48, 0xad, 0xd7, 0x8d, 0x6b, 0x65, 0xb5, 0xae, 0xa9, 0x36, 0x37, + 0x0d, 0xa0, 0xa0, 0x3c, 0x81, 0xf4, 0x3b, 0x74, 0x3f, 0x24, 0x17, 0x89, 0xa7, 0x07, 0xe5, 0x4f, + 0x48, 0x90, 0x0e, 0x27, 0xb6, 0x21, 0x31, 0xa5, 0x1f, 0xa5, 0x98, 0xf2, 0xc7, 0x25, 0x18, 0x0d, + 0x66, 0xb3, 0x21, 0xf1, 0xee, 0xfa, 0x91, 0x8a, 0xf7, 0xfb, 0x11, 0x18, 0x09, 0xe4, 0xb0, 0xfd, + 0x4a, 0xf7, 0x12, 0x8c, 0x6b, 0x55, 0xdc, 0x30, 0x0d, 0x07, 0xeb, 0x95, 0xbd, 0x72, 0x1d, 0x5f, + 0xc5, 0xf5, 0x8c, 0x4c, 0x83, 0xc6, 0x99, 0xee, 0x59, 0xf2, 0xec, 0x82, 0x47, 0xb7, 0x48, 0xc8, + 0x72, 0x13, 0x0b, 0xc5, 0xd2, 0xd2, 0xea, 0xca, 0x7a, 0x69, 0x79, 0xee, 0xad, 0xe5, 0x8d, 0xe5, + 0xcb, 0xcb, 0x2b, 0xcf, 0x2d, 0x2b, 0x69, 0x2d, 0x84, 0x76, 0x07, 0xdd, 0x7e, 0x15, 0xd2, 0x61, + 0xa1, 0xd0, 0x11, 0x68, 0x27, 0x56, 0x7a, 0x00, 0x4d, 0xc0, 0xd8, 0xf2, 0x4a, 0x79, 0x6d, 0xa1, + 0x58, 0x2a, 0x97, 0x2e, 0x5e, 0x2c, 0xcd, 0xad, 0xaf, 0xb1, 0x7d, 0x0f, 0x17, 0x7b, 0x3d, 0xe0, + 0xe0, 0xf2, 0xab, 0x51, 0x98, 0x68, 0x23, 0x09, 0xca, 0xf3, 0x15, 0x0b, 0x5b, 0x44, 0x9d, 0xee, + 0x47, 0xfa, 0x59, 0x92, 0x33, 0xac, 0xaa, 0x96, 0xc3, 0x17, 0x38, 0x0f, 0x00, 0xd1, 0x92, 0xee, + 0x68, 0x5b, 0x1a, 0xb6, 0xf8, 0x7e, 0x12, 0x5b, 0xc6, 0x8c, 0x79, 0x70, 0xb6, 0xa5, 0xf4, 0x10, + 0x20, 0xd3, 0xb0, 0x35, 0x47, 0xbb, 0x8a, 0xcb, 0x9a, 0x2e, 0x36, 0x9f, 0xc8, 0xb2, 0x26, 0xa6, + 0xa4, 0x45, 0xcd, 0x82, 0xee, 0xb8, 0xd8, 0x3a, 0xae, 0xa9, 0x21, 0x6c, 0x12, 0xcc, 0xa3, 0x4a, + 0x5a, 0xd4, 0xb8, 0xd8, 0x77, 0x41, 0xaa, 0x6a, 0x34, 0x49, 0xae, 0xc7, 0xf0, 0xc8, 0xdc, 0x21, + 0x29, 0xc3, 0x0c, 0xe6, 0xa2, 0xf0, 0x2c, 0xde, 0xdb, 0xf5, 0x4a, 0x29, 0xc3, 0x0c, 0xc6, 0x50, + 0xee, 0x87, 0x31, 0xb5, 0x56, 0xb3, 0x08, 0x73, 0xc1, 0x88, 0xad, 0x4b, 0x46, 0x5d, 0x30, 0x45, + 0xcc, 0x3e, 0x03, 0x09, 0xa1, 0x07, 0x32, 0x55, 0x13, 0x4d, 0x94, 0x4d, 0xb6, 0xd8, 0x8e, 0x9c, + 0x4c, 0x2a, 0x09, 0x5d, 0x54, 0xde, 0x05, 0x29, 0xcd, 0x2e, 0x7b, 0x9b, 0xf8, 0x91, 0x99, 0xc8, + 0xc9, 0x84, 0x32, 0xac, 0xd9, 0xee, 0x06, 0xa8, 0xfc, 0x99, 0x08, 0x8c, 0x06, 0x0f, 0x21, 0x50, + 0x11, 0x12, 0x75, 0xa3, 0xa2, 0x52, 0xd3, 0x62, 0x27, 0x60, 0x27, 0x7b, 0x9c, 0x5b, 0xcc, 0x2e, + 0x72, 0x7c, 0xc5, 0xa5, 0xcc, 0xfe, 0xb6, 0x04, 0x09, 0x01, 0x46, 0x87, 0x21, 0x66, 0xaa, 0xce, + 0x36, 0x65, 0x17, 0x2f, 0x44, 0xd2, 0x92, 0x42, 0xcb, 0x04, 0x6e, 0x9b, 0xaa, 0x4e, 0x4d, 0x80, + 0xc3, 0x49, 0x99, 0x8c, 0x6b, 0x1d, 0xab, 0x55, 0xba, 0xe8, 0x31, 0x1a, 0x0d, 0xac, 0x3b, 0xb6, + 0x18, 0x57, 0x0e, 0x9f, 0xe3, 0x60, 0xf4, 0x20, 0x8c, 0x3b, 0x96, 0xaa, 0xd5, 0x03, 0xb8, 0x31, + 0x8a, 0x9b, 0x16, 0x15, 0x2e, 0x72, 0x0e, 0x8e, 0x0a, 0xbe, 0x55, 0xec, 0xa8, 0x95, 0x6d, 0x5c, + 0xf5, 0x88, 0x06, 0xe9, 0xe6, 0xc6, 0x11, 0x8e, 0x50, 0xe4, 0xf5, 0x82, 0x56, 0xfe, 0x86, 0x04, + 0xe3, 0x62, 0x99, 0x56, 0x75, 0x95, 0xb5, 0x04, 0xa0, 0xea, 0xba, 0xe1, 0xf8, 0xd5, 0xd5, 0x6a, + 0xca, 0x2d, 0x74, 0xb3, 0x79, 0x97, 0x48, 0xf1, 0x31, 0xc8, 0x36, 0x00, 0xbc, 0x9a, 0x8e, 0x6a, + 0x9b, 0x86, 0x61, 0x7e, 0xc2, 0x44, 0x8f, 0x29, 0xd9, 0xc2, 0x1e, 0x18, 0x88, 0xac, 0xe7, 0xd0, + 0x24, 0xc4, 0x37, 0x71, 0x4d, 0xd3, 0xf9, 0xbe, 0x31, 0x2b, 0x88, 0xed, 0x97, 0x98, 0xbb, 0xfd, + 0x52, 0xf8, 0xa0, 0x04, 0x13, 0x15, 0xa3, 0x11, 0x96, 0xb7, 0x90, 0x0e, 0xed, 0x2e, 0xd8, 0x97, + 0xa4, 0x17, 0x9e, 0xaa, 0x69, 0xce, 0x76, 0x73, 0x73, 0xb6, 0x62, 0x34, 0xce, 0xd4, 0x8c, 0xba, + 0xaa, 0xd7, 0xbc, 0x73, 0x56, 0xfa, 0xa3, 0x72, 0xba, 0x86, 0xf5, 0xd3, 0x35, 0xc3, 0x77, 0xea, + 0x7a, 0xc1, 0xfb, 0xf9, 0xa7, 0x92, 0xf4, 0xf3, 0x91, 0xe8, 0xfc, 0x6a, 0xe1, 0xb3, 0x91, 0xec, + 0x3c, 0x6b, 0x6e, 0x55, 0xa8, 0x47, 0xc1, 0x5b, 0x75, 0x5c, 0x21, 0x5d, 0x86, 0xef, 0x3c, 0x08, + 0x93, 0x35, 0xa3, 0x66, 0x50, 0x8e, 0x67, 0xc8, 0x2f, 0x7e, 0x72, 0x9b, 0x74, 0xa1, 0xd9, 0x9e, + 0xc7, 0xbc, 0xb9, 0x65, 0x98, 0xe0, 0xc8, 0x65, 0x7a, 0x74, 0xc4, 0x16, 0x36, 0xa8, 0xeb, 0xae, + 0x5a, 0xe6, 0x57, 0xbf, 0x4d, 0x27, 0x74, 0x65, 0x9c, 0x93, 0x92, 0x3a, 0xb6, 0xf6, 0xc9, 0x29, + 0x70, 0x28, 0xc0, 0x8f, 0xb9, 0x2d, 0xb6, 0x7a, 0x70, 0xfc, 0x0d, 0xce, 0x71, 0xc2, 0xc7, 0x71, + 0x8d, 0x93, 0xe6, 0xe6, 0x60, 0x64, 0x3f, 0xbc, 0xfe, 0x25, 0xe7, 0x95, 0xc2, 0x7e, 0x26, 0xf3, + 0x30, 0x46, 0x99, 0x54, 0x9a, 0xb6, 0x63, 0x34, 0x68, 0x4c, 0xec, 0xce, 0xe6, 0x37, 0xbf, 0xcd, + 0xfc, 0x68, 0x94, 0x90, 0xcd, 0xb9, 0x54, 0xb9, 0x1c, 0xd0, 0xd3, 0xb2, 0x2a, 0xae, 0xd4, 0x7b, + 0x70, 0xf8, 0x0a, 0x17, 0xc4, 0xc5, 0xcf, 0x5d, 0x81, 0x49, 0xf2, 0x9b, 0x86, 0x2c, 0xbf, 0x24, + 0xbd, 0xb7, 0xe0, 0x32, 0xdf, 0x78, 0x0f, 0x73, 0xd5, 0x09, 0x97, 0x81, 0x4f, 0x26, 0xdf, 0x28, + 0xd6, 0xb0, 0xe3, 0x60, 0xcb, 0x2e, 0xab, 0xf5, 0x76, 0xe2, 0xf9, 0xf6, 0x30, 0x32, 0x1f, 0xfb, + 0x6e, 0x70, 0x14, 0xe7, 0x19, 0x65, 0xbe, 0x5e, 0xcf, 0x6d, 0xc0, 0x91, 0x36, 0x56, 0xd1, 0x07, + 0xcf, 0x57, 0x39, 0xcf, 0xc9, 0x16, 0xcb, 0x20, 0x6c, 0x57, 0x41, 0xc0, 0xdd, 0xb1, 0xec, 0x83, + 0xe7, 0xcf, 0x71, 0x9e, 0x88, 0xd3, 0x8a, 0x21, 0x25, 0x1c, 0x9f, 0x81, 0xf1, 0xab, 0xd8, 0xda, + 0x34, 0x6c, 0xbe, 0x6f, 0xd4, 0x07, 0xbb, 0x8f, 0x73, 0x76, 0x63, 0x9c, 0x90, 0x6e, 0x24, 0x11, + 0x5e, 0x4f, 0x42, 0x62, 0x4b, 0xad, 0xe0, 0x3e, 0x58, 0xdc, 0xe0, 0x2c, 0x86, 0x08, 0x3e, 0x21, + 0xcd, 0x43, 0xaa, 0x66, 0xf0, 0x59, 0xab, 0x37, 0xf9, 0x27, 0x38, 0xf9, 0xb0, 0xa0, 0xe1, 0x2c, + 0x4c, 0xc3, 0x6c, 0xd6, 0xc9, 0x94, 0xd6, 0x9b, 0xc5, 0xdf, 0x14, 0x2c, 0x04, 0x0d, 0x67, 0xb1, + 0x0f, 0xb5, 0x7e, 0x52, 0xb0, 0xb0, 0x7d, 0xfa, 0x7c, 0x1a, 0x86, 0x0d, 0xbd, 0xbe, 0x67, 0xe8, + 0xfd, 0x08, 0xf1, 0x29, 0xce, 0x01, 0x38, 0x09, 0x61, 0x70, 0x01, 0x92, 0xfd, 0x0e, 0xc4, 0xdf, + 0xfa, 0xae, 0x70, 0x0f, 0x31, 0x02, 0xf3, 0x30, 0x26, 0x02, 0x94, 0x66, 0xe8, 0x7d, 0xb0, 0xf8, + 0xdb, 0x9c, 0xc5, 0xa8, 0x8f, 0x8c, 0x77, 0xc3, 0xc1, 0xb6, 0x53, 0xc3, 0xfd, 0x30, 0xf9, 0x8c, + 0xe8, 0x06, 0x27, 0xe1, 0xaa, 0xdc, 0xc4, 0x7a, 0x65, 0xbb, 0x3f, 0x0e, 0xbf, 0x28, 0x54, 0x29, + 0x68, 0x08, 0x8b, 0x39, 0x18, 0x69, 0xa8, 0x96, 0xbd, 0xad, 0xd6, 0xfb, 0x1a, 0x8e, 0xbf, 0xc3, + 0x79, 0xa4, 0x5c, 0x22, 0xae, 0x91, 0xa6, 0xbe, 0x1f, 0x36, 0x9f, 0x15, 0x1a, 0xf1, 0x91, 0x71, + 0xd7, 0xb3, 0x1d, 0xba, 0xc9, 0xb6, 0x1f, 0x6e, 0xbf, 0x24, 0x5c, 0x8f, 0xd1, 0x2e, 0xf9, 0x39, + 0x5e, 0x80, 0xa4, 0xad, 0xbd, 0xdc, 0x17, 0x9b, 0xcf, 0x89, 0x91, 0xa6, 0x04, 0x84, 0xf8, 0xad, + 0x70, 0xb4, 0xed, 0x34, 0xd1, 0x07, 0xb3, 0xbf, 0xcb, 0x99, 0x1d, 0x6e, 0x33, 0x55, 0xf0, 0x90, + 0xb0, 0x5f, 0x96, 0x7f, 0x4f, 0x84, 0x04, 0x1c, 0xe2, 0xb5, 0x4a, 0xd6, 0x11, 0xb6, 0xba, 0xb5, + 0x3f, 0xad, 0xfd, 0xb2, 0xd0, 0x1a, 0xa3, 0x0d, 0x68, 0x6d, 0x1d, 0x0e, 0x73, 0x8e, 0xfb, 0x1b, + 0xd7, 0x5f, 0x11, 0x81, 0x95, 0x51, 0x6f, 0x04, 0x47, 0xf7, 0x6d, 0x90, 0x75, 0xd5, 0x29, 0x12, + 0x56, 0xbb, 0xdc, 0x50, 0xcd, 0x3e, 0x38, 0xff, 0x2a, 0xe7, 0x2c, 0x22, 0xbe, 0x9b, 0xf1, 0xda, + 0x4b, 0xaa, 0x49, 0x98, 0x3f, 0x0f, 0x19, 0xc1, 0xbc, 0xa9, 0x5b, 0xb8, 0x62, 0xd4, 0x74, 0xed, + 0x65, 0x5c, 0xed, 0x83, 0xf5, 0xaf, 0x85, 0x86, 0x6a, 0xc3, 0x47, 0x4e, 0x38, 0x2f, 0x40, 0xda, + 0xcd, 0x55, 0xca, 0x5a, 0xc3, 0x34, 0x2c, 0xa7, 0x07, 0xc7, 0xcf, 0x8b, 0x91, 0x72, 0xe9, 0x16, + 0x28, 0x59, 0xae, 0x04, 0xec, 0xe4, 0xb9, 0x5f, 0x93, 0xfc, 0x02, 0x67, 0x34, 0xe2, 0x51, 0xf1, + 0xc0, 0x51, 0x31, 0x1a, 0xa6, 0x6a, 0xf5, 0x13, 0xff, 0xfe, 0xbe, 0x08, 0x1c, 0x9c, 0x84, 0x07, + 0x0e, 0x67, 0xcf, 0xc4, 0x64, 0xb6, 0xef, 0x83, 0xc3, 0x17, 0x45, 0xe0, 0x10, 0x34, 0x9c, 0x85, + 0x48, 0x18, 0xfa, 0x60, 0xf1, 0x0f, 0x04, 0x0b, 0x41, 0x43, 0x58, 0x3c, 0xeb, 0x4d, 0xb4, 0x16, + 0xae, 0x69, 0xb6, 0x63, 0xb1, 0x34, 0xb9, 0x3b, 0xab, 0x7f, 0xf8, 0xdd, 0x60, 0x12, 0xa6, 0xf8, + 0x48, 0x49, 0x24, 0xe2, 0xdb, 0xae, 0x74, 0x15, 0xd5, 0x5b, 0xb0, 0x5f, 0x17, 0x91, 0xc8, 0x47, + 0x46, 0x64, 0xf3, 0x65, 0x88, 0x44, 0xed, 0x15, 0xb2, 0x76, 0xe8, 0x83, 0xdd, 0x3f, 0x0a, 0x09, + 0xb7, 0x26, 0x68, 0x09, 0x4f, 0x5f, 0xfe, 0xd3, 0xd4, 0x77, 0xf0, 0x5e, 0x5f, 0xd6, 0xf9, 0x8f, + 0x43, 0xf9, 0xcf, 0x06, 0xa3, 0x64, 0x31, 0x64, 0x2c, 0x94, 0x4f, 0xa1, 0x5e, 0xf7, 0x8c, 0x32, + 0x3f, 0xf9, 0x7d, 0xde, 0xdf, 0x60, 0x3a, 0x95, 0x5b, 0x24, 0x46, 0x1e, 0x4c, 0x7a, 0x7a, 0x33, + 0x7b, 0xcf, 0xf7, 0x5d, 0x3b, 0x0f, 0xe4, 0x3c, 0xb9, 0x8b, 0x30, 0x12, 0x48, 0x78, 0x7a, 0xb3, + 0x7a, 0x2f, 0x67, 0x95, 0xf2, 0xe7, 0x3b, 0xb9, 0x73, 0x10, 0x23, 0xc9, 0x4b, 0x6f, 0xf2, 0xbf, + 0xcc, 0xc9, 0x29, 0x7a, 0xee, 0xcd, 0x90, 0x10, 0x49, 0x4b, 0x6f, 0xd2, 0xf7, 0x71, 0x52, 0x97, + 0x84, 0x90, 0x8b, 0x84, 0xa5, 0x37, 0xf9, 0x5f, 0x11, 0xe4, 0x82, 0x84, 0x90, 0xf7, 0xaf, 0xc2, + 0x2f, 0xfd, 0x54, 0x8c, 0x4f, 0x3a, 0x42, 0x77, 0x17, 0x60, 0x88, 0x67, 0x2a, 0xbd, 0xa9, 0x3f, + 0xc0, 0x1b, 0x17, 0x14, 0xb9, 0xc7, 0x21, 0xde, 0xa7, 0xc2, 0x7f, 0x9a, 0x93, 0x32, 0xfc, 0xdc, + 0x1c, 0x0c, 0xfb, 0xb2, 0x93, 0xde, 0xe4, 0x7f, 0x8d, 0x93, 0xfb, 0xa9, 0x88, 0xe8, 0x3c, 0x3b, + 0xe9, 0xcd, 0xe0, 0x83, 0x42, 0x74, 0x4e, 0x41, 0xd4, 0x26, 0x12, 0x93, 0xde, 0xd4, 0x1f, 0x12, + 0x5a, 0x17, 0x24, 0xb9, 0xa7, 0x21, 0xe9, 0x4e, 0x36, 0xbd, 0xe9, 0x3f, 0xcc, 0xe9, 0x3d, 0x1a, + 0xa2, 0x01, 0xdf, 0x64, 0xd7, 0x9b, 0xc5, 0x5f, 0x17, 0x1a, 0xf0, 0x51, 0x11, 0x37, 0x0a, 0x27, + 0x30, 0xbd, 0x39, 0x7d, 0x44, 0xb8, 0x51, 0x28, 0x7f, 0x21, 0xa3, 0x49, 0x63, 0x7e, 0x6f, 0x16, + 0x3f, 0x23, 0x46, 0x93, 0xe2, 0x13, 0x31, 0xc2, 0x19, 0x41, 0x6f, 0x1e, 0x7f, 0x43, 0x88, 0x11, + 0x4a, 0x08, 0x72, 0xab, 0x80, 0x5a, 0xb3, 0x81, 0xde, 0xfc, 0x3e, 0xca, 0xf9, 0x8d, 0xb7, 0x24, + 0x03, 0xb9, 0xe7, 0xe0, 0x70, 0xfb, 0x4c, 0xa0, 0x37, 0xd7, 0x8f, 0x7d, 0x3f, 0xb4, 0x76, 0xf3, + 0x27, 0x02, 0xb9, 0x75, 0x6f, 0x4a, 0xf1, 0x67, 0x01, 0xbd, 0xd9, 0xbe, 0xfa, 0xfd, 0x60, 0xe0, + 0xf6, 0x27, 0x01, 0xb9, 0x3c, 0x80, 0x37, 0x01, 0xf7, 0xe6, 0xf5, 0x71, 0xce, 0xcb, 0x47, 0x44, + 0x5c, 0x83, 0xcf, 0xbf, 0xbd, 0xe9, 0x6f, 0x08, 0xd7, 0xe0, 0x14, 0xc4, 0x35, 0xc4, 0xd4, 0xdb, + 0x9b, 0xfa, 0x13, 0xc2, 0x35, 0x04, 0x09, 0xb1, 0x6c, 0xdf, 0xec, 0xd6, 0x9b, 0xc3, 0xa7, 0x84, + 0x65, 0xfb, 0xa8, 0x72, 0xcb, 0x30, 0xde, 0x32, 0x21, 0xf6, 0x66, 0xf5, 0xf3, 0x9c, 0x55, 0x3a, + 0x3c, 0x1f, 0xfa, 0x27, 0x2f, 0x3e, 0x19, 0xf6, 0xe6, 0xf6, 0xe9, 0xd0, 0xe4, 0xc5, 0xe7, 0xc2, + 0xdc, 0x05, 0x48, 0xe8, 0xcd, 0x7a, 0x9d, 0x38, 0x0f, 0xea, 0x7e, 0x37, 0x30, 0xf3, 0x5f, 0x7f, + 0xc0, 0xb5, 0x23, 0x08, 0x72, 0xe7, 0x20, 0x8e, 0x1b, 0x9b, 0xb8, 0xda, 0x8b, 0xf2, 0x3b, 0x3f, + 0x10, 0x01, 0x93, 0x60, 0xe7, 0x9e, 0x06, 0x60, 0x5b, 0x23, 0xf4, 0x78, 0xb0, 0x07, 0xed, 0x7f, + 0xfb, 0x01, 0xbf, 0x8c, 0xe3, 0x91, 0x78, 0x0c, 0xd8, 0xd5, 0x9e, 0xee, 0x0c, 0xbe, 0x1b, 0x64, + 0x40, 0x47, 0xe4, 0x49, 0x18, 0x7a, 0xd1, 0x36, 0x74, 0x47, 0xad, 0xf5, 0xa2, 0xfe, 0xef, 0x9c, + 0x5a, 0xe0, 0x13, 0x85, 0x35, 0x0c, 0x0b, 0x3b, 0x6a, 0xcd, 0xee, 0x45, 0xfb, 0x3f, 0x38, 0xad, + 0x4b, 0x40, 0x88, 0x2b, 0xaa, 0xed, 0xf4, 0xd3, 0xef, 0x3f, 0x14, 0xc4, 0x82, 0x80, 0x08, 0x4d, + 0x7e, 0xef, 0xe0, 0xbd, 0x5e, 0xb4, 0xdf, 0x13, 0x42, 0x73, 0xfc, 0xdc, 0x9b, 0x21, 0x49, 0x7e, + 0xb2, 0x1b, 0x76, 0x3d, 0x88, 0xff, 0x88, 0x13, 0x7b, 0x14, 0xa4, 0x65, 0xdb, 0xa9, 0x3a, 0x5a, + 0x6f, 0x65, 0xdf, 0xe2, 0x23, 0x2d, 0xf0, 0x73, 0x79, 0x18, 0xb6, 0x9d, 0x6a, 0xb5, 0xc9, 0xf3, + 0xd3, 0x1e, 0xe4, 0x7f, 0xfc, 0x03, 0x77, 0xcb, 0xc2, 0xa5, 0x21, 0xa3, 0x7d, 0x6d, 0xc7, 0x31, + 0x0d, 0x7a, 0x04, 0xd2, 0x8b, 0xc3, 0xf7, 0x39, 0x07, 0x1f, 0x49, 0x6e, 0x0e, 0x52, 0xa4, 0x2f, + 0x16, 0x36, 0x31, 0x3d, 0xaf, 0xea, 0xc1, 0xe2, 0x4f, 0xb8, 0x02, 0x02, 0x44, 0x85, 0x9f, 0xf8, + 0xca, 0x6b, 0x53, 0xd2, 0xd7, 0x5f, 0x9b, 0x92, 0x7e, 0xff, 0xb5, 0x29, 0xe9, 0x43, 0xdf, 0x9a, + 0x1a, 0xf8, 0xfa, 0xb7, 0xa6, 0x06, 0x7e, 0xf7, 0x5b, 0x53, 0x03, 0xed, 0xb7, 0x8d, 0x61, 0xde, + 0x98, 0x37, 0xd8, 0x86, 0xf1, 0x0b, 0x72, 0x60, 0xbb, 0xb8, 0x66, 0x78, 0xbb, 0xb5, 0xee, 0x22, + 0x07, 0xde, 0x1d, 0x85, 0xa3, 0x15, 0xc3, 0x6e, 0x18, 0x76, 0x99, 0xed, 0xf7, 0xb2, 0x02, 0xdf, + 0xf1, 0x4d, 0xf9, 0xab, 0xfa, 0xd8, 0xf4, 0xbd, 0x04, 0xa3, 0xb4, 0xeb, 0x74, 0xbb, 0x8b, 0x5a, + 0x5b, 0xcf, 0x00, 0xf1, 0xd5, 0x7f, 0x17, 0xa7, 0xbd, 0x1e, 0x71, 0x09, 0xe9, 0x79, 0xfe, 0x3a, + 0x4c, 0x6a, 0x0d, 0xb3, 0x8e, 0xe9, 0xc6, 0x7f, 0xd9, 0xad, 0xeb, 0xcd, 0xef, 0x6b, 0x9c, 0xdf, + 0x84, 0x47, 0xbe, 0x20, 0xa8, 0x73, 0x8b, 0x30, 0xae, 0x56, 0x2a, 0xd8, 0x0c, 0xb0, 0xec, 0x31, + 0x2c, 0x42, 0xc0, 0x34, 0xa7, 0x74, 0xb9, 0x15, 0x9e, 0xee, 0x34, 0x34, 0x2f, 0xdc, 0xeb, 0xd3, + 0xbc, 0x85, 0x6b, 0x58, 0x3f, 0xad, 0x63, 0xe7, 0x9a, 0x61, 0xed, 0x70, 0xf5, 0x9e, 0x66, 0x4d, + 0x0d, 0xb2, 0x3b, 0xcd, 0xf0, 0xde, 0x28, 0x4c, 0xb1, 0x8a, 0x33, 0x9b, 0xaa, 0x8d, 0xcf, 0x5c, + 0x7d, 0x64, 0x13, 0x3b, 0xea, 0x23, 0x67, 0x2a, 0x86, 0xa6, 0xf3, 0x91, 0x98, 0xe0, 0xe3, 0x42, + 0xea, 0x67, 0x79, 0x7d, 0xb6, 0xed, 0x36, 0xbd, 0x3c, 0x0f, 0xb1, 0x39, 0x43, 0xd3, 0xd1, 0x24, + 0xc4, 0xab, 0x58, 0x37, 0x1a, 0xfc, 0x16, 0x1e, 0x2b, 0xa0, 0xbb, 0x61, 0x50, 0x6d, 0x18, 0x4d, + 0xdd, 0x61, 0x67, 0x16, 0x85, 0xe1, 0xaf, 0xdc, 0x9c, 0x1e, 0xf8, 0xbd, 0x9b, 0xd3, 0xd1, 0x05, + 0xdd, 0x51, 0x78, 0x55, 0x2e, 0xf6, 0xfa, 0x27, 0xa7, 0x25, 0xf9, 0x19, 0x18, 0x2a, 0xe2, 0xca, + 0x41, 0x78, 0x15, 0x71, 0x25, 0xc4, 0xeb, 0x01, 0x48, 0x2c, 0xe8, 0x0e, 0xbb, 0x27, 0x79, 0x02, + 0xa2, 0x9a, 0xce, 0xae, 0xde, 0x84, 0xda, 0x27, 0x70, 0x82, 0x5a, 0xc4, 0x15, 0x17, 0xb5, 0x8a, + 0x2b, 0x61, 0x54, 0xc2, 0x9e, 0xc0, 0x0b, 0xc5, 0xdf, 0xfd, 0xcf, 0x53, 0x03, 0xaf, 0xbc, 0x36, + 0x35, 0xd0, 0x71, 0x24, 0xfc, 0x3e, 0xc0, 0x55, 0xcc, 0x87, 0xc0, 0xae, 0xee, 0x9c, 0x21, 0x26, + 0x6a, 0xbb, 0xc3, 0xf0, 0x5b, 0x83, 0x20, 0x73, 0x1c, 0xdb, 0x51, 0x77, 0x34, 0xbd, 0xe6, 0x8e, + 0x84, 0xda, 0x74, 0xb6, 0x5f, 0xe6, 0x43, 0x71, 0x98, 0x0f, 0x05, 0xc7, 0xe9, 0x3e, 0x1a, 0xd9, + 0xce, 0xde, 0x95, 0xed, 0x31, 0xe6, 0xf2, 0xbf, 0x8e, 0x02, 0x5a, 0x73, 0xd4, 0x1d, 0x9c, 0x6f, + 0x3a, 0xdb, 0x86, 0xa5, 0xbd, 0xcc, 0x62, 0x19, 0x06, 0x68, 0xa8, 0xbb, 0x65, 0xc7, 0xd8, 0xc1, + 0xba, 0x4d, 0x55, 0x33, 0x7c, 0xf6, 0xe8, 0x6c, 0x1b, 0xfb, 0x98, 0x25, 0x43, 0x57, 0x78, 0xf0, + 0xb3, 0xdf, 0x9c, 0xbe, 0xbf, 0xb7, 0x16, 0x28, 0x32, 0x49, 0xae, 0x77, 0xd7, 0x29, 0x63, 0x74, + 0x05, 0xd8, 0xb5, 0x8b, 0x72, 0x5d, 0xb3, 0x1d, 0x7e, 0x73, 0xfb, 0xdc, 0x6c, 0xfb, 0xbe, 0xcf, + 0xb6, 0x8a, 0x39, 0x7b, 0x45, 0xad, 0x6b, 0x55, 0xd5, 0x31, 0x2c, 0xfb, 0xd2, 0x80, 0x92, 0xa4, + 0xac, 0x16, 0x35, 0xdb, 0x41, 0xeb, 0x90, 0xac, 0x62, 0x7d, 0x8f, 0xb1, 0x8d, 0xbe, 0x31, 0xb6, + 0x09, 0xc2, 0x89, 0x72, 0x7d, 0x1e, 0x90, 0xea, 0xc7, 0x13, 0x4f, 0x95, 0xd8, 0x8d, 0xcb, 0x0e, + 0xec, 0x03, 0x9c, 0xe9, 0xcb, 0x8a, 0x71, 0x35, 0x0c, 0xca, 0xde, 0x07, 0xe0, 0xb5, 0x89, 0x32, + 0x30, 0xa4, 0x56, 0xab, 0x16, 0xb6, 0x6d, 0x7a, 0x24, 0x98, 0x54, 0x44, 0x31, 0x37, 0xfe, 0x6f, + 0xbe, 0x70, 0x7a, 0x24, 0xc0, 0xb1, 0x90, 0x02, 0xb8, 0xea, 0x92, 0x9e, 0xfa, 0x84, 0x04, 0xe3, + 0x2d, 0x2d, 0x22, 0x19, 0xa6, 0xf2, 0x1b, 0xeb, 0x97, 0x56, 0x94, 0x85, 0x17, 0xf2, 0xeb, 0x0b, + 0x2b, 0xcb, 0x65, 0xf6, 0x08, 0x60, 0x79, 0x6d, 0xb5, 0x34, 0xb7, 0x70, 0x71, 0xa1, 0x54, 0x4c, + 0x0f, 0xa0, 0x69, 0x38, 0xd6, 0x06, 0xa7, 0x58, 0x5a, 0x2c, 0xcd, 0xe7, 0xd7, 0x4b, 0x69, 0x09, + 0xdd, 0x05, 0x27, 0xda, 0x32, 0x71, 0x51, 0x22, 0x1d, 0x50, 0x94, 0x92, 0x8b, 0x12, 0x2d, 0x5c, + 0xec, 0xe8, 0x45, 0x0f, 0x75, 0xb5, 0x9f, 0x5d, 0xd7, 0x5d, 0x82, 0xfe, 0xf4, 0x27, 0x12, 0x1c, + 0x0d, 0x4f, 0x19, 0xaa, 0xbe, 0xd7, 0xe1, 0x1d, 0x68, 0x87, 0x68, 0xf6, 0x26, 0x88, 0xe6, 0xf5, + 0x3d, 0x74, 0x94, 0xe5, 0xd3, 0xe5, 0xa6, 0x55, 0xe7, 0x31, 0x68, 0x88, 0x94, 0x37, 0xac, 0x3a, + 0x89, 0x4d, 0xe2, 0xea, 0xbf, 0x74, 0x32, 0xc5, 0xef, 0xf3, 0xe7, 0x62, 0xdf, 0xfb, 0xd4, 0xf4, + 0x40, 0x61, 0x27, 0xdc, 0xa5, 0x2f, 0xf5, 0x9c, 0x41, 0x13, 0x79, 0x7d, 0x8f, 0x06, 0x9f, 0x55, + 0xe9, 0x85, 0x38, 0xed, 0x90, 0x38, 0x34, 0x9d, 0x0a, 0x1f, 0x9a, 0x3e, 0x87, 0xeb, 0xf5, 0xcb, + 0xba, 0x71, 0x8d, 0x8e, 0xa4, 0xd7, 0xef, 0xbf, 0x1a, 0x81, 0xa9, 0x96, 0xa9, 0x92, 0x67, 0x15, + 0x9d, 0x1e, 0xc1, 0xe6, 0x20, 0x51, 0x14, 0xc9, 0x4a, 0x06, 0x86, 0x6c, 0x5c, 0x31, 0xf4, 0x2a, + 0xf3, 0xee, 0xa8, 0x22, 0x8a, 0xa4, 0xab, 0xba, 0xaa, 0x1b, 0x36, 0xbf, 0x79, 0xcf, 0x0a, 0x85, + 0x9f, 0x91, 0xf6, 0x97, 0x23, 0x8c, 0x88, 0x96, 0x44, 0x37, 0x4f, 0x75, 0x3b, 0x57, 0xa6, 0x2a, + 0x70, 0xe5, 0xf7, 0x9d, 0x21, 0xf7, 0xab, 0x8e, 0x0f, 0x45, 0x60, 0x3a, 0xac, 0x0e, 0x92, 0xa3, + 0xd9, 0x8e, 0xda, 0x30, 0x3b, 0xe9, 0xe3, 0x02, 0x24, 0xd7, 0x05, 0xce, 0xbe, 0x15, 0xf2, 0xb3, + 0xfb, 0x54, 0xc8, 0xa8, 0xdb, 0x94, 0xd0, 0xc8, 0x83, 0xbd, 0x35, 0xe2, 0x76, 0xe1, 0x00, 0x2a, + 0xf9, 0x6c, 0x0c, 0x4e, 0xd0, 0xc7, 0x58, 0x56, 0x43, 0xd3, 0x9d, 0x33, 0x15, 0x6b, 0xcf, 0x74, + 0x68, 0x7a, 0x66, 0x6c, 0x71, 0x85, 0x8c, 0x7b, 0xd5, 0xb3, 0xac, 0xba, 0x83, 0x7f, 0x6c, 0x41, + 0x7c, 0x95, 0xd0, 0x11, 0x55, 0x38, 0x86, 0xa3, 0xd6, 0xb9, 0x8a, 0x58, 0x81, 0x40, 0xd9, 0x03, + 0xae, 0x08, 0x83, 0x6a, 0xe2, 0xed, 0x56, 0x1d, 0xab, 0x5b, 0xec, 0x1e, 0x7c, 0x94, 0xba, 0x4d, + 0x82, 0x00, 0xe8, 0x95, 0xf7, 0x49, 0x88, 0xab, 0x4d, 0x76, 0x85, 0x23, 0x4a, 0xfc, 0x89, 0x16, + 0xe4, 0xcb, 0x30, 0xc4, 0x8f, 0x8d, 0x51, 0x1a, 0xa2, 0x3b, 0x78, 0x8f, 0xb6, 0x93, 0x52, 0xc8, + 0x4f, 0x34, 0x0b, 0x71, 0x2a, 0x3c, 0x9f, 0x26, 0x32, 0xb3, 0x2d, 0xd2, 0xcf, 0x52, 0x21, 0x15, + 0x86, 0x26, 0x3f, 0x03, 0x89, 0xa2, 0xd1, 0xd0, 0x74, 0x23, 0xc8, 0x2d, 0xc9, 0xb8, 0x51, 0x99, + 0xcd, 0x26, 0xcf, 0x2a, 0x14, 0x56, 0x40, 0x87, 0x61, 0x90, 0xbd, 0x8b, 0xe0, 0xd7, 0x50, 0x78, + 0x49, 0x9e, 0x83, 0x21, 0xca, 0x7b, 0xc5, 0x44, 0x88, 0xbf, 0xa8, 0xe3, 0x0f, 0x30, 0x68, 0x02, + 0xca, 0xd9, 0x47, 0x3c, 0x61, 0x11, 0xc4, 0xaa, 0xaa, 0xa3, 0xf2, 0x7e, 0xd3, 0xdf, 0xf2, 0x53, + 0x90, 0xe0, 0x4c, 0x6c, 0x74, 0x16, 0xa2, 0x86, 0x69, 0xf3, 0x8b, 0x24, 0xd9, 0x4e, 0x5d, 0x59, + 0x31, 0x0b, 0x31, 0x92, 0x8f, 0x28, 0x04, 0xb9, 0xa0, 0x74, 0x0c, 0x9d, 0x4f, 0xf8, 0x2c, 0xc9, + 0x37, 0xe4, 0xbe, 0x9f, 0x6c, 0x48, 0x5b, 0xcc, 0xc1, 0x35, 0x96, 0x4f, 0x45, 0x60, 0xca, 0x57, + 0x7b, 0x15, 0x5b, 0xb6, 0x66, 0xe8, 0x7c, 0xd6, 0x66, 0xd6, 0x82, 0x7c, 0x42, 0xf2, 0xfa, 0x0e, + 0xe6, 0xf2, 0x66, 0x88, 0xe6, 0x4d, 0x13, 0x65, 0x21, 0xc1, 0x2e, 0x8c, 0x18, 0xcc, 0x5e, 0x62, + 0x8a, 0x5b, 0x26, 0x75, 0xb6, 0xb1, 0xe5, 0x5c, 0x53, 0x2d, 0xf7, 0xe9, 0xa0, 0x28, 0xcb, 0x4f, + 0x42, 0x72, 0xce, 0xd0, 0x6d, 0xac, 0xdb, 0x4d, 0xea, 0x7c, 0x9b, 0x75, 0xa3, 0xb2, 0xc3, 0x39, + 0xb0, 0x02, 0x51, 0xb8, 0x6a, 0x9a, 0x94, 0x32, 0xa6, 0x90, 0x9f, 0x2c, 0x03, 0x2c, 0xac, 0x75, + 0x54, 0xd1, 0x93, 0xfb, 0x57, 0x11, 0xef, 0xa4, 0xab, 0xa3, 0xff, 0x23, 0xc1, 0xf1, 0x56, 0x87, + 0xda, 0xc1, 0x7b, 0xf6, 0x7e, 0xfd, 0xe9, 0x79, 0x48, 0xae, 0xd2, 0xf7, 0xfb, 0x97, 0xf1, 0x1e, + 0xca, 0xc2, 0x10, 0xae, 0x9e, 0x3d, 0x77, 0xee, 0x91, 0x27, 0x99, 0xb5, 0x5f, 0x1a, 0x50, 0x04, + 0x00, 0x4d, 0x41, 0xd2, 0xc6, 0x15, 0xf3, 0xec, 0xb9, 0xf3, 0x3b, 0x8f, 0x30, 0xf3, 0x22, 0x79, + 0x8e, 0x0b, 0xca, 0x25, 0x48, 0xaf, 0x5f, 0xff, 0xd4, 0xb4, 0x54, 0x88, 0x43, 0xd4, 0x6e, 0x36, + 0xee, 0xa8, 0x8d, 0xbc, 0x1a, 0x87, 0x19, 0x3f, 0x25, 0x8d, 0x50, 0x6e, 0xee, 0xc1, 0x75, 0x90, + 0xf6, 0xe9, 0x80, 0x62, 0x74, 0x48, 0x59, 0xbb, 0x6a, 0x52, 0xfe, 0x35, 0x09, 0x52, 0x6e, 0x42, + 0xb4, 0x86, 0x1d, 0x74, 0xc1, 0x9f, 0xe5, 0x70, 0xb7, 0x39, 0x36, 0x1b, 0x6e, 0xcb, 0x4b, 0xdc, + 0x14, 0x1f, 0x3a, 0x7a, 0x9c, 0x1a, 0xa2, 0x69, 0xd8, 0xfc, 0x39, 0x59, 0x0f, 0x52, 0x17, 0x19, + 0x3d, 0x04, 0x88, 0x46, 0xb8, 0xf2, 0x55, 0xc3, 0xd1, 0xf4, 0x5a, 0xd9, 0x34, 0xae, 0xf1, 0x47, + 0xba, 0x51, 0x25, 0x4d, 0x6b, 0xae, 0xd0, 0x8a, 0x55, 0x02, 0x27, 0x42, 0x27, 0x5d, 0x2e, 0xc1, + 0x24, 0x8e, 0x04, 0x01, 0x51, 0x44, 0x17, 0x60, 0xc8, 0x6c, 0x6e, 0x96, 0x45, 0xc4, 0x18, 0x3e, + 0x7b, 0xbc, 0x9d, 0xff, 0x0b, 0xfb, 0xe0, 0x11, 0x60, 0xd0, 0x6c, 0x6e, 0x12, 0x6b, 0xb9, 0x0b, + 0x52, 0x6d, 0x84, 0x19, 0xbe, 0xea, 0xc9, 0x41, 0x3f, 0x1b, 0xc1, 0x7b, 0x50, 0x36, 0x2d, 0xcd, + 0xb0, 0x34, 0x67, 0x8f, 0x66, 0xa9, 0x51, 0x25, 0x2d, 0x2a, 0x56, 0x39, 0x5c, 0xde, 0x81, 0xb1, + 0x35, 0xba, 0x8a, 0xf5, 0x24, 0x3f, 0xe7, 0xc9, 0x27, 0xf5, 0x96, 0xaf, 0xa3, 0x64, 0x91, 0x16, + 0xc9, 0x0a, 0xcf, 0x76, 0xb4, 0xce, 0xc7, 0xf7, 0x6f, 0x9d, 0xc1, 0x3c, 0xf0, 0x0f, 0x8f, 0x06, + 0x9c, 0x93, 0x4f, 0x9f, 0xbe, 0xf0, 0xd5, 0xaf, 0x61, 0xf6, 0x4a, 0x23, 0xb2, 0xdd, 0x27, 0xd5, + 0x6c, 0x8f, 0x30, 0x9a, 0xed, 0xe9, 0x42, 0xf2, 0x93, 0x30, 0xb2, 0xaa, 0x5a, 0xce, 0x1a, 0x76, + 0x2e, 0x61, 0xb5, 0x8a, 0xad, 0xe0, 0xac, 0x3b, 0x22, 0x66, 0x5d, 0x04, 0x31, 0x3a, 0xb5, 0xb2, + 0x59, 0x87, 0xfe, 0x96, 0xb7, 0x21, 0x46, 0x6f, 0x84, 0xba, 0x33, 0x32, 0xa7, 0x60, 0x33, 0x32, + 0x89, 0xa5, 0x7b, 0x0e, 0xb6, 0x45, 0x12, 0x4b, 0x0b, 0xe8, 0x31, 0x31, 0xaf, 0x46, 0xbb, 0xcf, + 0xab, 0xdc, 0x10, 0xf9, 0xec, 0x5a, 0x87, 0xa1, 0x02, 0x09, 0xc5, 0x0b, 0x45, 0x57, 0x10, 0xc9, + 0x13, 0x04, 0x2d, 0xc1, 0x98, 0xa9, 0x5a, 0x0e, 0x7d, 0x0a, 0xb3, 0x4d, 0x7b, 0xc1, 0x6d, 0x7d, + 0xba, 0xd5, 0xf3, 0x02, 0x9d, 0xe5, 0xad, 0x8c, 0x98, 0x7e, 0xa0, 0xfc, 0x07, 0x31, 0x18, 0xe4, + 0xca, 0x78, 0x33, 0x0c, 0x71, 0xb5, 0x72, 0xeb, 0x3c, 0x31, 0xdb, 0x3a, 0x31, 0xcd, 0xba, 0x13, + 0x08, 0xe7, 0x27, 0x68, 0xd0, 0x7d, 0x90, 0xa8, 0x6c, 0xab, 0x9a, 0x5e, 0xd6, 0xaa, 0x62, 0x43, + 0xe1, 0xb5, 0x9b, 0xd3, 0x43, 0x73, 0x04, 0xb6, 0x50, 0x54, 0x86, 0x68, 0xe5, 0x42, 0x95, 0x64, + 0x02, 0xdb, 0x58, 0xab, 0x6d, 0x3b, 0xdc, 0xc3, 0x78, 0x09, 0x3d, 0x01, 0x31, 0x62, 0x10, 0xfc, + 0xa1, 0x64, 0xb6, 0x65, 0x5b, 0xc7, 0xcd, 0xf2, 0x0a, 0x09, 0xd2, 0xf0, 0x87, 0xbe, 0x39, 0x2d, + 0x29, 0x94, 0x02, 0xcd, 0xc1, 0x48, 0x5d, 0xb5, 0x9d, 0x32, 0x9d, 0xc1, 0x48, 0xf3, 0x71, 0xbe, + 0xaa, 0x6e, 0x51, 0x08, 0x57, 0x2c, 0x17, 0x7d, 0x98, 0x50, 0x31, 0x50, 0x15, 0x9d, 0x84, 0x34, + 0x65, 0x52, 0x31, 0x1a, 0x0d, 0xcd, 0x61, 0xb9, 0xd5, 0x20, 0xd5, 0xfb, 0x28, 0x81, 0xcf, 0x51, + 0x30, 0xcd, 0xb0, 0x8e, 0x41, 0x92, 0x3e, 0xcd, 0xa2, 0x28, 0xec, 0x1a, 0x72, 0x82, 0x00, 0x68, + 0xe5, 0xfd, 0x30, 0xe6, 0xc5, 0x47, 0x86, 0x92, 0x60, 0x5c, 0x3c, 0x30, 0x45, 0x7c, 0x18, 0x26, + 0x75, 0xbc, 0x4b, 0x2f, 0x46, 0x07, 0xb0, 0x93, 0x14, 0x1b, 0x91, 0xba, 0x2b, 0x41, 0x8a, 0x7b, + 0x61, 0xb4, 0x22, 0x94, 0xcf, 0x70, 0x81, 0xe2, 0x8e, 0xb8, 0x50, 0x8a, 0x76, 0x14, 0x12, 0xaa, + 0x69, 0x32, 0x84, 0x61, 0x1e, 0x1f, 0x4d, 0x93, 0x56, 0x9d, 0x82, 0x71, 0xda, 0x47, 0x0b, 0xdb, + 0xcd, 0xba, 0xc3, 0x99, 0xa4, 0x28, 0xce, 0x18, 0xa9, 0x50, 0x18, 0x9c, 0xe2, 0xde, 0x0d, 0x23, + 0xf8, 0xaa, 0x56, 0xc5, 0x7a, 0x05, 0x33, 0xbc, 0x11, 0x8a, 0x97, 0x12, 0x40, 0x8a, 0xf4, 0x00, + 0xb8, 0x71, 0xaf, 0x2c, 0x62, 0xf2, 0x28, 0xe3, 0x27, 0xe0, 0x79, 0x06, 0x96, 0x33, 0x10, 0x2b, + 0xaa, 0x8e, 0x4a, 0x12, 0x0c, 0x67, 0x97, 0x4d, 0x34, 0x29, 0x85, 0xfc, 0x94, 0x5f, 0x8f, 0x40, + 0xec, 0x8a, 0xe1, 0x60, 0xf4, 0xa8, 0x2f, 0x01, 0x1c, 0x6d, 0x67, 0xcf, 0x6b, 0x5a, 0x4d, 0xc7, + 0xd5, 0x25, 0xbb, 0xe6, 0xfb, 0x8e, 0x82, 0x67, 0x4e, 0x91, 0x80, 0x39, 0x4d, 0x42, 0xdc, 0x32, + 0x9a, 0x7a, 0x55, 0xdc, 0xe0, 0xa5, 0x05, 0x54, 0x82, 0x84, 0x6b, 0x25, 0xb1, 0x5e, 0x56, 0x32, + 0x46, 0xac, 0x84, 0xd8, 0x30, 0x07, 0x28, 0x43, 0x9b, 0xdc, 0x58, 0x0a, 0x90, 0x74, 0x83, 0x17, + 0xb7, 0xb6, 0xfe, 0x0c, 0xd6, 0x23, 0x23, 0x93, 0x89, 0x3b, 0xf6, 0xae, 0xf2, 0x98, 0xc5, 0xa5, + 0xdd, 0x0a, 0xae, 0xbd, 0x80, 0x59, 0xf1, 0x6f, 0x3a, 0x0c, 0xd1, 0x7e, 0x79, 0x66, 0xc5, 0xbe, + 0xeb, 0x70, 0x1c, 0x92, 0xb6, 0x56, 0xd3, 0x55, 0xa7, 0x69, 0x61, 0x6e, 0x79, 0x1e, 0x40, 0xfe, + 0x92, 0x04, 0x83, 0xcc, 0x92, 0x7d, 0x7a, 0x93, 0xda, 0xeb, 0x2d, 0xd2, 0x49, 0x6f, 0xd1, 0x83, + 0xeb, 0x2d, 0x0f, 0xe0, 0x0a, 0x63, 0xf3, 0xa7, 0xf6, 0x6d, 0x32, 0x06, 0x26, 0xe2, 0x9a, 0x56, + 0xe3, 0x8e, 0xea, 0x23, 0x92, 0xff, 0x93, 0x44, 0x92, 0x58, 0x5e, 0x8f, 0xf2, 0x30, 0x22, 0xe4, + 0x2a, 0x6f, 0xd5, 0xd5, 0x1a, 0xb7, 0x9d, 0x13, 0x1d, 0x85, 0xbb, 0x58, 0x57, 0x6b, 0xca, 0x30, + 0x97, 0x87, 0x14, 0xda, 0x8f, 0x43, 0xa4, 0xc3, 0x38, 0x04, 0x06, 0x3e, 0x7a, 0xb0, 0x81, 0x0f, + 0x0c, 0x51, 0x2c, 0x3c, 0x44, 0x9f, 0x8f, 0xd0, 0xc5, 0x8c, 0x69, 0xd8, 0x6a, 0xfd, 0x87, 0xe1, + 0x11, 0xc7, 0x20, 0x69, 0x1a, 0xf5, 0x32, 0xab, 0x61, 0x37, 0xdb, 0x13, 0xa6, 0x51, 0x57, 0x5a, + 0x86, 0x3d, 0x7e, 0x9b, 0xdc, 0x65, 0xf0, 0x36, 0x68, 0x6d, 0x28, 0xac, 0x35, 0x0b, 0x52, 0x4c, + 0x15, 0x7c, 0x2e, 0x7b, 0x98, 0xe8, 0x80, 0x4e, 0x8e, 0x52, 0xeb, 0xdc, 0xcb, 0xc4, 0x66, 0x98, + 0x0a, 0xc7, 0x23, 0x14, 0x2c, 0xf4, 0xb7, 0x5b, 0x05, 0xfb, 0xcd, 0x52, 0xe1, 0x78, 0xf2, 0xcf, + 0x4a, 0x00, 0x8b, 0x44, 0xb3, 0xb4, 0xbf, 0x64, 0x16, 0xb2, 0xa9, 0x08, 0xe5, 0x40, 0xcb, 0x53, + 0x9d, 0x06, 0x8d, 0xb7, 0x9f, 0xb2, 0xfd, 0x72, 0xcf, 0xc1, 0x88, 0x67, 0x8c, 0x36, 0x16, 0xc2, + 0x4c, 0x75, 0xc9, 0xaa, 0xd7, 0xb0, 0xa3, 0xa4, 0xae, 0xfa, 0x4a, 0xf2, 0x3f, 0x93, 0x20, 0x49, + 0x65, 0x5a, 0xc2, 0x8e, 0x1a, 0x18, 0x43, 0xe9, 0xe0, 0x63, 0x78, 0x02, 0x80, 0xb1, 0xb1, 0xb5, + 0x97, 0x31, 0xb7, 0xac, 0x24, 0x85, 0xac, 0x69, 0x2f, 0x63, 0x74, 0xde, 0x55, 0x78, 0xb4, 0xbb, + 0xc2, 0x45, 0xd6, 0xcd, 0xd5, 0x7e, 0x04, 0x86, 0xe8, 0xa7, 0xa9, 0x76, 0x6d, 0x9e, 0x48, 0x0f, + 0xea, 0xcd, 0xc6, 0xfa, 0xae, 0x2d, 0xbf, 0x08, 0x43, 0xeb, 0xbb, 0x6c, 0x6f, 0xe4, 0x18, 0x24, + 0x2d, 0xc3, 0xe0, 0x73, 0x32, 0xcb, 0x85, 0x12, 0x04, 0x40, 0xa7, 0x20, 0xb1, 0x1f, 0x10, 0xf1, + 0xf6, 0x03, 0xbc, 0x0d, 0x8d, 0x68, 0x5f, 0x1b, 0x1a, 0xa7, 0xfe, 0xbd, 0x04, 0xc3, 0xbe, 0xf8, + 0x80, 0x1e, 0x81, 0x43, 0x85, 0xc5, 0x95, 0xb9, 0xcb, 0xe5, 0x85, 0x62, 0xf9, 0xe2, 0x62, 0x7e, + 0xde, 0x7b, 0xbb, 0x95, 0x3d, 0x7c, 0xfd, 0xc6, 0x0c, 0xf2, 0xe1, 0x6e, 0xe8, 0x3b, 0xba, 0x71, + 0x4d, 0x47, 0x67, 0x60, 0x32, 0x48, 0x92, 0x2f, 0xac, 0x95, 0x96, 0xd7, 0xd3, 0x52, 0xf6, 0xd0, + 0xf5, 0x1b, 0x33, 0xe3, 0x3e, 0x8a, 0xfc, 0xa6, 0x8d, 0x75, 0xa7, 0x95, 0x60, 0x6e, 0x65, 0x69, + 0x69, 0x61, 0x3d, 0x1d, 0x69, 0x21, 0xe0, 0x01, 0xfb, 0x01, 0x18, 0x0f, 0x12, 0x2c, 0x2f, 0x2c, + 0xa6, 0xa3, 0x59, 0x74, 0xfd, 0xc6, 0xcc, 0xa8, 0x0f, 0x7b, 0x59, 0xab, 0x67, 0x13, 0xef, 0xff, + 0xf4, 0xd4, 0xc0, 0x2f, 0xfe, 0xc2, 0x94, 0x44, 0x7a, 0x36, 0x12, 0x88, 0x11, 0xe8, 0x21, 0x38, + 0xb2, 0xb6, 0x30, 0xbf, 0x5c, 0x2a, 0x96, 0x97, 0xd6, 0xe6, 0xc5, 0x4e, 0xb3, 0xe8, 0xdd, 0xd8, + 0xf5, 0x1b, 0x33, 0xc3, 0xbc, 0x4b, 0x9d, 0xb0, 0x57, 0x95, 0xd2, 0x95, 0x95, 0xf5, 0x52, 0x5a, + 0x62, 0xd8, 0xab, 0x16, 0xbe, 0x6a, 0x38, 0xec, 0xdb, 0x75, 0x0f, 0xc3, 0xd1, 0x36, 0xd8, 0x6e, + 0xc7, 0xc6, 0xaf, 0xdf, 0x98, 0x19, 0x59, 0xb5, 0x30, 0xf3, 0x1f, 0x4a, 0x31, 0x0b, 0x99, 0x56, + 0x8a, 0x95, 0xd5, 0x95, 0xb5, 0xfc, 0x62, 0x7a, 0x26, 0x9b, 0xbe, 0x7e, 0x63, 0x26, 0x25, 0x82, + 0x21, 0xdd, 0xce, 0x77, 0x7b, 0x76, 0x27, 0x57, 0x3c, 0x7f, 0x7c, 0x1a, 0xee, 0xe9, 0x70, 0x92, + 0x24, 0xce, 0x20, 0x0e, 0x74, 0x96, 0xd4, 0x71, 0x37, 0x3d, 0xdb, 0x63, 0xc3, 0xb9, 0xf7, 0xd2, + 0xe9, 0xe0, 0xe7, 0x54, 0xd9, 0xae, 0x8b, 0x3b, 0xf9, 0x03, 0x12, 0x8c, 0x5e, 0xd2, 0x6c, 0xc7, + 0xb0, 0xb4, 0x8a, 0x5a, 0xa7, 0x2f, 0xb6, 0xce, 0xf7, 0x1b, 0x5b, 0x43, 0xae, 0xfe, 0x34, 0x0c, + 0x5e, 0x55, 0xeb, 0x2c, 0xa8, 0x45, 0xe9, 0x07, 0x66, 0x3a, 0x1c, 0xec, 0xb8, 0xa1, 0x4d, 0x30, + 0x60, 0x64, 0xf2, 0x2f, 0x47, 0x60, 0x8c, 0x3a, 0x83, 0xcd, 0x3e, 0x3d, 0x46, 0xd6, 0x58, 0x05, + 0x88, 0x59, 0xaa, 0xc3, 0x37, 0x0d, 0x0b, 0xb3, 0xfc, 0x8c, 0xf1, 0xbe, 0x3e, 0x4e, 0xcc, 0x8a, + 0xb8, 0xa2, 0x50, 0x5a, 0xf4, 0x76, 0x48, 0x34, 0xd4, 0xdd, 0x32, 0xe5, 0xc3, 0x56, 0x2e, 0xf9, + 0xfd, 0xf1, 0xb9, 0x75, 0x73, 0x7a, 0x6c, 0x4f, 0x6d, 0xd4, 0x73, 0xb2, 0xe0, 0x23, 0x2b, 0x43, + 0x0d, 0x75, 0x97, 0x88, 0x88, 0x4c, 0x18, 0x23, 0xd0, 0xca, 0xb6, 0xaa, 0xd7, 0x30, 0x6b, 0x84, + 0x6e, 0x81, 0x16, 0x2e, 0xed, 0xbb, 0x91, 0xc3, 0x5e, 0x23, 0x3e, 0x76, 0xb2, 0x32, 0xd2, 0x50, + 0x77, 0xe7, 0x28, 0x80, 0xb4, 0x98, 0x4b, 0x7c, 0xf4, 0x93, 0xd3, 0x03, 0xf4, 0xdc, 0xf6, 0x1b, + 0x12, 0x80, 0xa7, 0x31, 0xf4, 0x76, 0x48, 0x57, 0xdc, 0x12, 0xa5, 0x15, 0x27, 0x90, 0xf7, 0x77, + 0x1a, 0x8b, 0x90, 0xbe, 0xd9, 0xdc, 0xfc, 0xf5, 0x9b, 0xd3, 0x92, 0x32, 0x56, 0x09, 0x0d, 0xc5, + 0xdb, 0x60, 0xb8, 0x69, 0x56, 0x55, 0x07, 0x97, 0xe9, 0x3a, 0x2e, 0xd2, 0x73, 0x9e, 0x9f, 0x22, + 0xbc, 0x6e, 0xdd, 0x9c, 0x46, 0xac, 0x5b, 0x3e, 0x62, 0x99, 0xce, 0xfe, 0xc0, 0x20, 0x84, 0xc0, + 0xd7, 0xa7, 0xaf, 0x4a, 0x30, 0x5c, 0xf4, 0xdd, 0x9c, 0xcc, 0xc0, 0x50, 0xc3, 0xd0, 0xb5, 0x1d, + 0x6e, 0x8f, 0x49, 0x45, 0x14, 0x51, 0x16, 0x12, 0xec, 0x11, 0xab, 0xb3, 0x27, 0xb6, 0x42, 0x45, + 0x99, 0x50, 0x5d, 0xc3, 0x9b, 0xb6, 0x26, 0x46, 0x43, 0x11, 0x45, 0x74, 0x11, 0xd2, 0x36, 0xae, + 0x34, 0x2d, 0xcd, 0xd9, 0x2b, 0x57, 0x0c, 0xdd, 0x51, 0x2b, 0x0e, 0x7b, 0x0e, 0x59, 0x38, 0x76, + 0xeb, 0xe6, 0xf4, 0x11, 0x26, 0x6b, 0x18, 0x43, 0x56, 0xc6, 0x04, 0x68, 0x8e, 0x41, 0x48, 0x0b, + 0x55, 0xec, 0xa8, 0x5a, 0xdd, 0xce, 0xb0, 0x2b, 0x08, 0xa2, 0xe8, 0xeb, 0xcb, 0xe7, 0x86, 0xfc, + 0x1b, 0x5b, 0x17, 0x21, 0x6d, 0x98, 0xd8, 0x0a, 0x24, 0xa2, 0x52, 0xb8, 0xe5, 0x30, 0x86, 0xac, + 0x8c, 0x09, 0x90, 0x48, 0x52, 0x1d, 0x32, 0xcc, 0x62, 0xa1, 0x68, 0x36, 0x37, 0xbd, 0xfd, 0xb0, + 0xc9, 0x96, 0xd1, 0xc8, 0xeb, 0x7b, 0x85, 0x47, 0x3d, 0xee, 0x61, 0x3a, 0xf9, 0x6b, 0x5f, 0x38, + 0x3d, 0xc9, 0x4d, 0xc3, 0xdb, 0x9f, 0xba, 0x8c, 0xf7, 0xc8, 0xf0, 0x73, 0xd4, 0x55, 0x8a, 0x49, + 0xd2, 0xce, 0x17, 0x55, 0xad, 0x2e, 0x9e, 0xf5, 0x2b, 0xbc, 0x84, 0x72, 0x30, 0x68, 0x3b, 0xaa, + 0xd3, 0xb4, 0xf9, 0x79, 0xae, 0xdc, 0xc9, 0xd4, 0x0a, 0x86, 0x5e, 0x5d, 0xa3, 0x98, 0x0a, 0xa7, + 0x40, 0x17, 0x61, 0x90, 0x1f, 0x94, 0xc7, 0xf7, 0xed, 0xdf, 0xf4, 0x46, 0x04, 0xa3, 0x26, 0x1a, + 0xa9, 0xe2, 0x3a, 0xae, 0xb1, 0xb4, 0x6a, 0x5b, 0x25, 0xab, 0x0f, 0xfa, 0xcd, 0xbd, 0xc2, 0xc2, + 0xbe, 0x9d, 0x90, 0x6b, 0x2a, 0xcc, 0x4f, 0x56, 0xc6, 0x5c, 0xd0, 0x1a, 0x85, 0xa0, 0xcb, 0x81, + 0x2b, 0xbe, 0xfc, 0xc3, 0x94, 0x77, 0x77, 0xea, 0xbe, 0xcf, 0xa6, 0xc5, 0xfe, 0x84, 0xff, 0x82, + 0xf0, 0x45, 0x48, 0x37, 0xf5, 0x4d, 0x43, 0xa7, 0x6f, 0x6f, 0x79, 0x7e, 0x4f, 0xd6, 0x77, 0x51, + 0xbf, 0x71, 0x84, 0x31, 0x64, 0x65, 0xcc, 0x05, 0x5d, 0x62, 0xab, 0x80, 0x2a, 0x8c, 0x7a, 0x58, + 0xd4, 0x51, 0x93, 0x3d, 0x1d, 0xf5, 0x2e, 0xee, 0xa8, 0x87, 0xc2, 0xad, 0x78, 0xbe, 0x3a, 0xe2, + 0x02, 0x09, 0x19, 0xba, 0x04, 0xe0, 0x85, 0x07, 0xba, 0x4f, 0x31, 0xdc, 0x79, 0xe0, 0xbd, 0x18, + 0x23, 0xd6, 0x7b, 0x1e, 0x2d, 0x7a, 0x27, 0x4c, 0x34, 0x34, 0xbd, 0x6c, 0xe3, 0xfa, 0x56, 0x99, + 0x2b, 0x98, 0xb0, 0xa4, 0x9f, 0x4e, 0x2a, 0x2c, 0xee, 0xcf, 0x1e, 0x6e, 0xdd, 0x9c, 0xce, 0xf2, + 0x10, 0xda, 0xca, 0x52, 0x56, 0xc6, 0x1b, 0x9a, 0xbe, 0x86, 0xeb, 0x5b, 0x45, 0x17, 0x96, 0x4b, + 0xbd, 0xff, 0x93, 0xd3, 0x03, 0xdc, 0x5d, 0x07, 0xe4, 0xf3, 0x74, 0xef, 0x9c, 0xbb, 0x19, 0xb6, + 0xc9, 0x9a, 0x44, 0x15, 0x05, 0x7e, 0xa1, 0xc0, 0x03, 0x30, 0x37, 0x7f, 0xe5, 0x3f, 0xce, 0x48, + 0xf2, 0xe7, 0x24, 0x18, 0x2c, 0x5e, 0x59, 0x55, 0x35, 0x0b, 0x2d, 0xc0, 0xb8, 0x67, 0x39, 0x41, + 0x27, 0x3f, 0x7e, 0xeb, 0xe6, 0x74, 0x26, 0x6c, 0x5c, 0xae, 0x97, 0x7b, 0x06, 0x2c, 0xdc, 0x7c, + 0xa1, 0xd3, 0xc2, 0x35, 0xc0, 0xaa, 0x05, 0x45, 0x6e, 0x5d, 0xd6, 0x86, 0xba, 0x59, 0x82, 0x21, + 0x26, 0xad, 0x8d, 0x72, 0x10, 0x37, 0xc9, 0x0f, 0x7e, 0x30, 0x30, 0xd5, 0xd1, 0x78, 0x29, 0xbe, + 0xbb, 0x91, 0x49, 0x48, 0xe4, 0x0f, 0x47, 0x00, 0x8a, 0x57, 0xae, 0xac, 0x5b, 0x9a, 0x59, 0xc7, + 0xce, 0xed, 0xec, 0xf9, 0x3a, 0x1c, 0xf2, 0xad, 0x92, 0xac, 0x4a, 0xa8, 0xf7, 0x33, 0xb7, 0x6e, + 0x4e, 0x1f, 0x0f, 0xf7, 0xde, 0x87, 0x26, 0x2b, 0x13, 0xde, 0x7a, 0xc9, 0xaa, 0xb4, 0xe5, 0x5a, + 0xb5, 0x1d, 0x97, 0x6b, 0xb4, 0x33, 0x57, 0x1f, 0x9a, 0x9f, 0x6b, 0xd1, 0x76, 0xda, 0xab, 0x76, + 0x0d, 0x86, 0x3d, 0x95, 0xd8, 0xa8, 0x08, 0x09, 0x87, 0xff, 0xe6, 0x1a, 0x96, 0x3b, 0x6b, 0x58, + 0x90, 0x71, 0x2d, 0xbb, 0x94, 0xf2, 0x9f, 0x4a, 0x00, 0x9e, 0xcd, 0xfe, 0x78, 0x9a, 0x18, 0x09, + 0xe5, 0x3c, 0xf0, 0x46, 0x0f, 0x94, 0xaa, 0x71, 0xea, 0x90, 0x3e, 0x7f, 0x2a, 0x02, 0x13, 0x1b, + 0x22, 0xf2, 0xfc, 0xd8, 0xeb, 0x60, 0x15, 0x86, 0xb0, 0xee, 0x58, 0x1a, 0x55, 0x02, 0x19, 0xed, + 0x87, 0x3b, 0x8d, 0x76, 0x9b, 0x3e, 0xd1, 0x8f, 0x47, 0x89, 0x4d, 0x77, 0xce, 0x26, 0xa4, 0x8d, + 0x0f, 0x46, 0x21, 0xd3, 0x89, 0x12, 0xcd, 0xc1, 0x58, 0xc5, 0xc2, 0xec, 0x7a, 0x95, 0x7f, 0xe7, + 0xaf, 0x90, 0xf5, 0x32, 0xcb, 0x10, 0x82, 0xac, 0x8c, 0x0a, 0x08, 0x9f, 0x3d, 0x6a, 0x40, 0xd2, + 0x3e, 0x62, 0x76, 0xf4, 0x96, 0x56, 0x7f, 0x79, 0x9e, 0xcc, 0xa7, 0x0f, 0xd1, 0x48, 0x90, 0x01, + 0x9b, 0x3f, 0x46, 0x3d, 0x28, 0x9d, 0x40, 0x5e, 0x82, 0x31, 0x4d, 0xd7, 0x1c, 0x4d, 0xad, 0x97, + 0x37, 0xd5, 0xba, 0xaa, 0x57, 0x0e, 0x92, 0x35, 0xb3, 0x90, 0xcf, 0x9b, 0x0d, 0xb1, 0x93, 0x95, + 0x51, 0x0e, 0x29, 0x30, 0x00, 0xba, 0x04, 0x43, 0xa2, 0xa9, 0xd8, 0x81, 0xb2, 0x0d, 0x41, 0xee, + 0x4b, 0xf0, 0x7e, 0x3a, 0x0a, 0xe3, 0x0a, 0xae, 0xfe, 0xc5, 0x50, 0xec, 0x6f, 0x28, 0x96, 0x00, + 0x98, 0xbb, 0x93, 0x00, 0x7b, 0x80, 0xd1, 0x20, 0x01, 0x23, 0xc9, 0x38, 0x14, 0x6d, 0xc7, 0x37, + 0x1e, 0x37, 0x23, 0x90, 0xf2, 0x8f, 0xc7, 0x9f, 0xd3, 0x59, 0x09, 0x2d, 0x78, 0x91, 0x28, 0xc6, + 0x3f, 0xb9, 0xdb, 0x21, 0x12, 0xb5, 0x58, 0x6f, 0xf7, 0x10, 0xf4, 0x3f, 0x23, 0x30, 0xb8, 0xaa, + 0x5a, 0x6a, 0xc3, 0x46, 0x95, 0x96, 0x4c, 0x53, 0x6c, 0x3f, 0xb6, 0x7c, 0x58, 0x9d, 0xef, 0x76, + 0xf4, 0x48, 0x34, 0x3f, 0xda, 0x26, 0xd1, 0x7c, 0x0b, 0x8c, 0x92, 0xe5, 0xb0, 0xef, 0x0a, 0x03, + 0xd1, 0xf6, 0x48, 0xe1, 0xa8, 0xc7, 0x25, 0x58, 0xcf, 0x56, 0xcb, 0x57, 0xfc, 0x77, 0x18, 0x86, + 0x09, 0x86, 0x17, 0x98, 0x09, 0xf9, 0x61, 0x6f, 0x59, 0xea, 0xab, 0x94, 0x15, 0x68, 0xa8, 0xbb, + 0x25, 0x56, 0x40, 0x8b, 0x80, 0xb6, 0xdd, 0x9d, 0x91, 0xb2, 0xa7, 0x4e, 0x42, 0x7f, 0xe2, 0xd6, + 0xcd, 0xe9, 0xa3, 0x8c, 0xbe, 0x15, 0x47, 0x56, 0xc6, 0x3d, 0xa0, 0xe0, 0xf6, 0x18, 0x00, 0xe9, + 0x57, 0x99, 0x5d, 0xd4, 0x66, 0xcb, 0x9d, 0x43, 0xb7, 0x6e, 0x4e, 0x8f, 0x33, 0x2e, 0x5e, 0x9d, + 0xac, 0x24, 0x49, 0xa1, 0x48, 0x7e, 0xfb, 0x2c, 0xfb, 0xd3, 0x12, 0x20, 0x2f, 0xe4, 0x2b, 0xd8, + 0x36, 0xc9, 0xfa, 0x8c, 0x24, 0xe2, 0xbe, 0xac, 0x59, 0xea, 0x9e, 0x88, 0x7b, 0xf4, 0x22, 0x11, + 0xf7, 0x79, 0xca, 0x93, 0x5e, 0x78, 0x8c, 0xf4, 0xba, 0xb5, 0xcc, 0x4d, 0x24, 0x1c, 0x0f, 0x07, + 0xe4, 0x7f, 0x25, 0xc1, 0xd1, 0x16, 0x8b, 0x72, 0x85, 0xfd, 0x4b, 0x80, 0x2c, 0x5f, 0x25, 0xff, + 0x7e, 0x22, 0x13, 0x7a, 0xdf, 0x06, 0x3a, 0x6e, 0xb5, 0xc4, 0xdd, 0xdb, 0x17, 0xe1, 0xd9, 0xb5, + 0xf8, 0x7f, 0x2a, 0xc1, 0xa4, 0xbf, 0x79, 0xb7, 0x23, 0xcb, 0x90, 0xf2, 0xb7, 0xce, 0xbb, 0x70, + 0x4f, 0x3f, 0x5d, 0xe0, 0xd2, 0x07, 0xe8, 0xd1, 0xb3, 0x9e, 0xbb, 0xb2, 0xbd, 0xb3, 0x47, 0xfa, + 0xd6, 0x86, 0x90, 0x29, 0xec, 0xb6, 0x31, 0x3a, 0x1e, 0xff, 0x57, 0x82, 0xd8, 0xaa, 0x61, 0xd4, + 0x91, 0x01, 0xe3, 0xba, 0xe1, 0x94, 0x89, 0x65, 0xe1, 0xaa, 0xff, 0x76, 0x7a, 0xb2, 0x30, 0xb7, + 0x3f, 0x25, 0x7d, 0xe7, 0xe6, 0x74, 0x2b, 0x2b, 0x65, 0x4c, 0x37, 0x9c, 0x02, 0x85, 0xf0, 0x0b, + 0xea, 0xef, 0x84, 0x91, 0x60, 0x63, 0x2c, 0x4a, 0x3e, 0xb7, 0xef, 0xc6, 0x82, 0x6c, 0x6e, 0xdd, + 0x9c, 0x9e, 0xf4, 0x3c, 0xc6, 0x05, 0xcb, 0x4a, 0x6a, 0xd3, 0xd7, 0x3a, 0xbb, 0xde, 0xf5, 0xbd, + 0x4f, 0x4e, 0x4b, 0xa7, 0xbe, 0x28, 0x01, 0x78, 0x3b, 0x0f, 0xe8, 0x21, 0x38, 0x52, 0x58, 0x59, + 0x2e, 0x96, 0xd7, 0xd6, 0xf3, 0xeb, 0x1b, 0x6b, 0xc1, 0x9b, 0xdc, 0x62, 0x7b, 0xdc, 0x36, 0x71, + 0x45, 0xdb, 0xd2, 0x70, 0x15, 0xdd, 0x07, 0x93, 0x41, 0x6c, 0x52, 0x2a, 0x15, 0xd3, 0x52, 0x36, + 0x75, 0xfd, 0xc6, 0x4c, 0x82, 0xe5, 0x62, 0xb8, 0x8a, 0x4e, 0xc2, 0xa1, 0x56, 0xbc, 0x85, 0xe5, + 0xf9, 0x74, 0x24, 0x3b, 0x72, 0xfd, 0xc6, 0x4c, 0xd2, 0x4d, 0xda, 0x90, 0x0c, 0xc8, 0x8f, 0xc9, + 0xf9, 0x45, 0xb3, 0x70, 0xfd, 0xc6, 0xcc, 0x20, 0x53, 0x60, 0x36, 0xf6, 0xfe, 0x4f, 0x4f, 0x0d, + 0xdc, 0xf6, 0xfb, 0xde, 0x7f, 0x34, 0xd4, 0x71, 0xd7, 0xbb, 0x86, 0x75, 0x6c, 0x6b, 0xf6, 0x81, + 0x76, 0xbd, 0xfb, 0xda, 0x49, 0x97, 0x7f, 0x27, 0x0e, 0xa9, 0x79, 0xd6, 0x0a, 0x19, 0x08, 0x8c, + 0xde, 0x04, 0x83, 0x26, 0x9d, 0x46, 0xdc, 0x63, 0xb4, 0x0e, 0x06, 0xcf, 0x26, 0x1b, 0xf7, 0x2e, + 0x17, 0x9b, 0x7a, 0x6c, 0x7e, 0x99, 0x83, 0xdd, 0x31, 0xf3, 0x6e, 0x4d, 0xa5, 0xf6, 0xb5, 0xdf, + 0xc3, 0x72, 0x16, 0xbe, 0xb5, 0x12, 0xe6, 0x27, 0xb3, 0x7b, 0x21, 0xeb, 0x04, 0xc2, 0x6e, 0x87, + 0xbd, 0x57, 0x82, 0x43, 0x14, 0xcb, 0x9b, 0x88, 0x29, 0xa6, 0x48, 0xf6, 0x4f, 0x75, 0xea, 0xc2, + 0xa2, 0x6a, 0x7b, 0x77, 0x3d, 0xd8, 0x7d, 0xae, 0x7b, 0xf8, 0x44, 0x78, 0xdc, 0xd7, 0x78, 0x98, + 0xad, 0xac, 0x4c, 0xd4, 0x5b, 0x28, 0x6d, 0x34, 0x1f, 0xb8, 0xd0, 0x17, 0xdb, 0xdf, 0x56, 0xbb, + 0xff, 0x72, 0xdf, 0x33, 0x30, 0xec, 0xc5, 0x12, 0x9b, 0xff, 0xbf, 0x97, 0xfe, 0xe7, 0x0e, 0x3f, + 0x31, 0x7a, 0x9f, 0x04, 0x87, 0xbc, 0xd9, 0xdc, 0xcf, 0x96, 0xfd, 0x5f, 0x9c, 0x07, 0xf7, 0xb1, + 0x10, 0x0a, 0x2b, 0xa7, 0x2d, 0x5f, 0x59, 0x99, 0x6c, 0xb6, 0x92, 0x92, 0x25, 0xd8, 0x88, 0x3f, + 0xb2, 0xda, 0x19, 0xf1, 0xe9, 0xc7, 0xfe, 0x43, 0x73, 0x90, 0x01, 0xfb, 0x5f, 0x1d, 0xa6, 0x61, + 0x39, 0xb8, 0x4a, 0x37, 0xe4, 0x12, 0x8a, 0x5b, 0x96, 0x97, 0x01, 0xb5, 0x0e, 0x6e, 0xf8, 0x02, + 0xa3, 0xf7, 0x0a, 0x05, 0x4d, 0x42, 0xdc, 0x7f, 0xc5, 0x8f, 0x15, 0x72, 0x89, 0xf7, 0xf3, 0xe9, + 0xf3, 0xb6, 0xfb, 0xfc, 0xbf, 0x88, 0xc0, 0x29, 0xff, 0xf1, 0xd0, 0x4b, 0x4d, 0x6c, 0xed, 0xb9, + 0x2e, 0x6a, 0xaa, 0x35, 0x4d, 0xf7, 0xbf, 0x7b, 0x38, 0xea, 0x9f, 0xf0, 0x29, 0xae, 0xd0, 0x93, + 0xac, 0xc3, 0xf0, 0xaa, 0x5a, 0xc3, 0x0a, 0x7e, 0xa9, 0x89, 0x6d, 0xa7, 0xcd, 0x25, 0xf3, 0xc3, + 0x30, 0x68, 0x6c, 0x6d, 0x89, 0x23, 0xed, 0x98, 0xc2, 0x4b, 0xa4, 0xcb, 0x75, 0xad, 0xa1, 0xb1, + 0xdb, 0x60, 0x31, 0x85, 0x15, 0xd0, 0x34, 0x0c, 0x57, 0x8c, 0xa6, 0xce, 0x3d, 0x2e, 0x13, 0x13, + 0x1f, 0x54, 0x69, 0xea, 0xcc, 0xe3, 0xe4, 0xa7, 0x21, 0xc5, 0xda, 0xe3, 0x33, 0xee, 0x51, 0x48, + 0xd0, 0xeb, 0x54, 0x5e, 0xab, 0x43, 0xa4, 0x7c, 0x99, 0x5d, 0x48, 0x67, 0x5c, 0x58, 0xc3, 0xac, + 0x50, 0x28, 0x74, 0x54, 0xe5, 0xc9, 0xde, 0xa1, 0x81, 0x29, 0xca, 0x55, 0xe3, 0x6f, 0xc4, 0xe1, + 0x10, 0x3f, 0xa1, 0x53, 0x4d, 0xed, 0xcc, 0xb6, 0xe3, 0x88, 0x97, 0x11, 0xc0, 0x53, 0x5d, 0xd5, + 0xd4, 0xe4, 0x3d, 0x88, 0x5d, 0x72, 0x1c, 0x13, 0x9d, 0x82, 0xb8, 0xd5, 0xac, 0x63, 0xb1, 0xe3, + 0xe3, 0xee, 0xc9, 0xab, 0xa6, 0x36, 0x4b, 0x10, 0x94, 0x66, 0x1d, 0x2b, 0x0c, 0x05, 0x95, 0x60, + 0x7a, 0xab, 0x59, 0xaf, 0xef, 0x95, 0xab, 0x98, 0xfe, 0x2f, 0x2c, 0xf7, 0xbf, 0x49, 0xe0, 0x5d, + 0x53, 0x15, 0xdf, 0xa4, 0x24, 0xba, 0x39, 0x4e, 0xd1, 0x8a, 0x14, 0x4b, 0xfc, 0x27, 0x89, 0x92, + 0xc0, 0x91, 0x7f, 0x2f, 0x02, 0x09, 0xc1, 0x9a, 0xde, 0x10, 0xc7, 0x75, 0x5c, 0x71, 0x0c, 0x71, + 0x62, 0xe2, 0x96, 0x11, 0x82, 0x68, 0x8d, 0x0f, 0x51, 0xf2, 0xd2, 0x80, 0x42, 0x0a, 0x04, 0xe6, + 0xde, 0xdb, 0x27, 0x30, 0xb3, 0x49, 0x46, 0x2d, 0x66, 0x1a, 0x62, 0x69, 0x76, 0x69, 0x40, 0xa1, + 0x25, 0x94, 0x81, 0x41, 0xe2, 0x19, 0x0e, 0xfb, 0xd0, 0x27, 0x81, 0xf3, 0x32, 0x3a, 0x0c, 0x71, + 0x53, 0x75, 0x2a, 0xec, 0x4a, 0x1d, 0xa9, 0x60, 0x45, 0xf4, 0x38, 0x0c, 0xb2, 0x07, 0xd6, 0xe1, + 0x7f, 0x34, 0x43, 0x94, 0xc1, 0xbe, 0x64, 0x47, 0xe4, 0x5e, 0x55, 0x1d, 0x07, 0x5b, 0x3a, 0x61, + 0xc8, 0xd0, 0x11, 0x82, 0xd8, 0xa6, 0x51, 0xdd, 0xe3, 0xff, 0xfc, 0x86, 0xfe, 0xe6, 0xff, 0x6d, + 0x83, 0xda, 0x43, 0x99, 0x56, 0xb2, 0xff, 0xf9, 0x95, 0x12, 0xc0, 0x02, 0x41, 0x2a, 0xc1, 0x84, + 0x5a, 0xad, 0x6a, 0xec, 0xff, 0xd0, 0x94, 0x37, 0x35, 0x1a, 0x21, 0x6c, 0xfa, 0x1f, 0xdd, 0x3a, + 0x8d, 0x05, 0xf2, 0x08, 0x0a, 0x1c, 0xbf, 0x90, 0x84, 0x21, 0x93, 0x09, 0x25, 0x5f, 0x80, 0xf1, + 0x16, 0x49, 0x89, 0x7c, 0x3b, 0x9a, 0x5e, 0x15, 0x8f, 0x19, 0xc8, 0x6f, 0x02, 0xa3, 0x5f, 0xa3, + 0x64, 0x67, 0x51, 0xf4, 0x77, 0xe1, 0xdd, 0x9d, 0x1f, 0xbb, 0x8c, 0xfa, 0x1e, 0xbb, 0xa8, 0xa6, + 0x56, 0x48, 0x52, 0xfe, 0xfc, 0x89, 0x4b, 0x9e, 0x57, 0xb0, 0xe7, 0x2d, 0xb3, 0x86, 0x55, 0x23, + 0xb3, 0xb4, 0x98, 0x7d, 0x49, 0x95, 0x6a, 0x6a, 0x36, 0x35, 0x47, 0xef, 0xeb, 0x98, 0xf6, 0x05, + 0xdf, 0x6f, 0xfa, 0xf0, 0x25, 0x36, 0x9f, 0x5f, 0x5d, 0x70, 0xed, 0xf8, 0xcb, 0x11, 0x38, 0xee, + 0xb3, 0x63, 0x1f, 0x72, 0xab, 0x39, 0x67, 0xdb, 0x5b, 0x7c, 0x1f, 0xcf, 0x8c, 0x2f, 0x43, 0x8c, + 0xe0, 0xa3, 0x1e, 0xff, 0x0b, 0x23, 0xf3, 0x2b, 0x5f, 0xfb, 0x27, 0x72, 0xf0, 0xd4, 0x2a, 0x30, + 0x2a, 0x94, 0x49, 0xe1, 0x7d, 0xfd, 0xeb, 0x2f, 0xed, 0x7d, 0x18, 0xd4, 0xbe, 0x7d, 0x6a, 0x0c, + 0xeb, 0xf0, 0xdb, 0xe7, 0x3a, 0x3e, 0x43, 0x65, 0x11, 0xb3, 0x7b, 0x12, 0xb5, 0x8f, 0x70, 0xdc, + 0xe9, 0xfe, 0x7f, 0xb7, 0x11, 0xec, 0x33, 0x1d, 0xdb, 0x85, 0xc3, 0xcf, 0x92, 0xb6, 0xbd, 0x65, + 0xb2, 0x08, 0xec, 0x87, 0xdd, 0xd3, 0x3c, 0x89, 0xff, 0x43, 0x3d, 0x71, 0x52, 0x07, 0x9e, 0x7c, + 0x7c, 0x81, 0x78, 0xdf, 0x6c, 0xc7, 0xf9, 0x62, 0xd6, 0x37, 0x59, 0x28, 0x3e, 0x4a, 0xf9, 0x97, + 0x24, 0x38, 0xd2, 0xd2, 0x34, 0x8f, 0xf1, 0xf3, 0x6d, 0x9e, 0x2a, 0x1c, 0x28, 0xb3, 0x99, 0x6f, + 0x23, 0xec, 0xfd, 0x3d, 0x85, 0x65, 0x52, 0x04, 0xa4, 0x7d, 0x0a, 0x0e, 0x05, 0x85, 0x15, 0x6a, + 0xba, 0x17, 0x46, 0x83, 0x3b, 0xc2, 0x5c, 0x5d, 0x23, 0x81, 0x3d, 0x61, 0xb9, 0x1c, 0xd6, 0xb3, + 0xdb, 0xd7, 0x12, 0x24, 0x5d, 0x54, 0x9e, 0x02, 0xf7, 0xdd, 0x55, 0x8f, 0x52, 0xfe, 0xb0, 0x04, + 0x33, 0xc1, 0x16, 0x7c, 0xc9, 0xd0, 0xfe, 0x84, 0xbd, 0x6d, 0x43, 0xfc, 0xba, 0x04, 0x77, 0x75, + 0x91, 0x89, 0x2b, 0xe0, 0x65, 0x98, 0xf4, 0xed, 0x04, 0x88, 0x10, 0x2e, 0x86, 0xfd, 0x54, 0xef, + 0x34, 0xd4, 0x5d, 0xf8, 0x1e, 0x23, 0x4a, 0xf9, 0xec, 0x37, 0xa7, 0x27, 0x5a, 0xeb, 0x6c, 0x65, + 0xa2, 0x75, 0xf5, 0x7e, 0x1b, 0xed, 0xe3, 0x55, 0x09, 0x1e, 0x08, 0x76, 0xb5, 0x4d, 0x3e, 0xfb, + 0xa3, 0x1a, 0x87, 0xff, 0x20, 0xc1, 0xa9, 0x7e, 0x84, 0xe3, 0x03, 0xb2, 0x09, 0x13, 0x5e, 0xa6, + 0x1d, 0x1e, 0x8f, 0x7d, 0xe5, 0xef, 0xcc, 0x4a, 0x91, 0xcb, 0xed, 0x0e, 0x28, 0xde, 0xe4, 0x8e, + 0xe5, 0x1f, 0x72, 0x57, 0xc9, 0xc1, 0xdd, 0x5c, 0xa1, 0xe4, 0xc0, 0x7e, 0x6e, 0x9b, 0xb1, 0x88, + 0xb4, 0x19, 0x0b, 0x2f, 0x35, 0x97, 0xaf, 0xf2, 0xb8, 0xd5, 0x66, 0x0f, 0xee, 0x6d, 0x30, 0xd1, + 0xc6, 0x94, 0xb9, 0x57, 0xef, 0xc3, 0x92, 0x15, 0xd4, 0x6a, 0xac, 0xf2, 0x1e, 0x4c, 0xd3, 0x76, + 0xdb, 0x28, 0xfa, 0x4e, 0x77, 0xb9, 0xc1, 0x63, 0x4b, 0xdb, 0xa6, 0x79, 0xdf, 0x17, 0x60, 0x90, + 0x8d, 0x33, 0xef, 0xee, 0x01, 0x0c, 0x85, 0x33, 0x90, 0x7f, 0x4e, 0xc4, 0xb2, 0xa2, 0x10, 0xbb, + 0xbd, 0x0f, 0xf5, 0xd3, 0xd7, 0xdb, 0xe4, 0x43, 0x3e, 0x65, 0x7c, 0x43, 0x44, 0xb5, 0xf6, 0xd2, + 0x71, 0x75, 0x54, 0x6e, 0x5b, 0x54, 0x63, 0xba, 0xb9, 0xb3, 0xe1, 0xeb, 0x17, 0x44, 0xf8, 0x72, + 0xfb, 0xd4, 0x23, 0x7c, 0xfd, 0x68, 0x54, 0xef, 0x06, 0xb2, 0x1e, 0x62, 0xfe, 0x59, 0x0c, 0x64, + 0xdf, 0x93, 0xe0, 0x28, 0xed, 0x9b, 0x7f, 0x23, 0x62, 0xbf, 0x2a, 0x7f, 0x08, 0x90, 0x6d, 0x55, + 0xca, 0x6d, 0xbd, 0x3b, 0x6d, 0x5b, 0x95, 0x2b, 0x81, 0xf9, 0xe5, 0x21, 0x40, 0xd5, 0xc0, 0x76, + 0x13, 0xc5, 0x66, 0xb7, 0xe4, 0xd2, 0x55, 0xdf, 0x6e, 0x46, 0x9b, 0xe1, 0x8c, 0xdd, 0x86, 0xe1, + 0xfc, 0xba, 0x04, 0xd9, 0x76, 0x5d, 0xe6, 0xc3, 0xa7, 0xc1, 0xe1, 0xc0, 0x21, 0x41, 0x78, 0x04, + 0x1f, 0xea, 0x67, 0x2b, 0x27, 0xe4, 0x46, 0x87, 0x2c, 0x7c, 0xa7, 0xf3, 0x80, 0xe9, 0xa0, 0x85, + 0xb6, 0x66, 0xd6, 0x3f, 0x32, 0xf7, 0xf9, 0x42, 0x4b, 0x5c, 0xfd, 0x33, 0x91, 0x7b, 0xef, 0xc2, + 0x54, 0x07, 0xa9, 0xef, 0xf4, 0xbc, 0xb7, 0xdd, 0x71, 0x30, 0x6f, 0x77, 0xfa, 0xfe, 0x18, 0xf7, + 0x84, 0xe0, 0x0d, 0x6c, 0xdf, 0x5a, 0xac, 0xdd, 0x13, 0x2e, 0xf9, 0xad, 0x70, 0xac, 0x2d, 0x15, + 0x97, 0x2d, 0x07, 0xb1, 0x6d, 0xcd, 0x76, 0xb8, 0x58, 0xf7, 0x75, 0x12, 0x2b, 0x44, 0x4d, 0x69, + 0x64, 0x04, 0x69, 0xca, 0x7a, 0xd5, 0x30, 0xea, 0x5c, 0x0c, 0xf9, 0x32, 0x8c, 0xfb, 0x60, 0xbc, + 0x91, 0xf3, 0x10, 0x33, 0x0d, 0xfe, 0x79, 0x82, 0xe1, 0xb3, 0xc7, 0x3b, 0xee, 0xde, 0x1b, 0x46, + 0x9d, 0x77, 0x9b, 0xe2, 0xcb, 0x93, 0x80, 0x18, 0x33, 0xba, 0x91, 0x2f, 0x9a, 0x58, 0x83, 0x89, + 0x00, 0x94, 0x37, 0xf2, 0x86, 0x0e, 0x09, 0xce, 0x7e, 0xe7, 0x10, 0xc4, 0x29, 0x57, 0xf4, 0x31, + 0x29, 0xf0, 0x95, 0xa0, 0xd9, 0x4e, 0x6c, 0xda, 0xaf, 0x89, 0xb3, 0x67, 0xfa, 0xc6, 0xe7, 0x39, + 0xdb, 0xa9, 0x77, 0xff, 0xdb, 0x6f, 0x7f, 0x24, 0x72, 0x0f, 0x92, 0xcf, 0x74, 0x58, 0x8d, 0xfb, + 0xfc, 0xe5, 0x33, 0x81, 0xb7, 0xef, 0xa7, 0xfb, 0x6b, 0x4a, 0x48, 0x36, 0xdb, 0x2f, 0x3a, 0x17, + 0xec, 0x02, 0x15, 0xec, 0x1c, 0x7a, 0xb4, 0xb7, 0x60, 0x67, 0xde, 0x11, 0x74, 0x9a, 0x77, 0xa1, + 0xdf, 0x91, 0x60, 0xb2, 0xdd, 0x92, 0x0e, 0x3d, 0xd1, 0x9f, 0x14, 0xad, 0x29, 0x45, 0xf6, 0xc9, + 0x03, 0x50, 0xf2, 0xae, 0xcc, 0xd3, 0xae, 0xe4, 0xd1, 0xd3, 0x07, 0xe8, 0xca, 0x19, 0xff, 0xfe, + 0xfe, 0xff, 0x96, 0xe0, 0x44, 0xd7, 0x15, 0x12, 0xca, 0xf7, 0x27, 0x65, 0x97, 0xdc, 0x29, 0x5b, + 0x78, 0x23, 0x2c, 0x78, 0x8f, 0x9f, 0xa5, 0x3d, 0xbe, 0x8c, 0x16, 0x0e, 0xd2, 0xe3, 0xb6, 0x87, + 0x28, 0xe8, 0x37, 0x83, 0x37, 0x0b, 0xbb, 0x9b, 0x53, 0xcb, 0xc2, 0xa3, 0x87, 0x63, 0xb4, 0x26, + 0xb5, 0xf2, 0xf3, 0xb4, 0x0b, 0x0a, 0x5a, 0x7d, 0x83, 0x83, 0x76, 0xe6, 0x1d, 0xc1, 0xc0, 0xff, + 0x2e, 0xf4, 0xbf, 0xa4, 0xf6, 0x17, 0x05, 0x1f, 0xef, 0x2a, 0x62, 0xe7, 0x45, 0x55, 0xf6, 0x89, + 0xfd, 0x13, 0xf2, 0x4e, 0x36, 0x68, 0x27, 0x6b, 0x08, 0xdf, 0xee, 0x4e, 0xb6, 0x1d, 0x44, 0xf4, + 0x55, 0x09, 0x26, 0xdb, 0xad, 0x49, 0x7a, 0xb8, 0x65, 0x97, 0x45, 0x56, 0x0f, 0xb7, 0xec, 0xb6, + 0x00, 0x92, 0xdf, 0x44, 0x3b, 0x7f, 0x1e, 0x3d, 0xd6, 0xa9, 0xf3, 0x5d, 0x47, 0x91, 0xf8, 0x62, + 0xd7, 0x24, 0xbf, 0x87, 0x2f, 0xf6, 0xb3, 0x8e, 0xe9, 0xe1, 0x8b, 0x7d, 0xad, 0x31, 0x7a, 0xfb, + 0xa2, 0xdb, 0xb3, 0x3e, 0x87, 0xd1, 0x46, 0x5f, 0x96, 0x60, 0x24, 0x90, 0x11, 0xa3, 0x47, 0xba, + 0x0a, 0xda, 0x6e, 0xc1, 0x90, 0x3d, 0xbb, 0x1f, 0x12, 0xde, 0x97, 0x05, 0xda, 0x97, 0x39, 0x94, + 0x3f, 0x48, 0x5f, 0x82, 0x67, 0xa5, 0x5f, 0x97, 0x60, 0xa2, 0x4d, 0x96, 0xd9, 0xc3, 0x0b, 0x3b, + 0x27, 0xcd, 0xd9, 0x27, 0xf6, 0x4f, 0xc8, 0x7b, 0x75, 0x91, 0xf6, 0xea, 0x2d, 0xe8, 0xa9, 0x83, + 0xf4, 0xca, 0x37, 0x3f, 0xdf, 0xf4, 0xee, 0x5d, 0xf9, 0xda, 0x41, 0xe7, 0xf7, 0x29, 0x98, 0xe8, + 0xd0, 0xe3, 0xfb, 0xa6, 0xe3, 0xfd, 0x79, 0x8e, 0xf6, 0xe7, 0x59, 0xb4, 0xf2, 0xc6, 0xfa, 0xd3, + 0x3a, 0xad, 0x7f, 0xbe, 0xf5, 0x05, 0x60, 0x77, 0x2b, 0x6a, 0x9b, 0xac, 0x66, 0x1f, 0xdd, 0x17, + 0x0d, 0xef, 0xd4, 0x13, 0xb4, 0x53, 0x67, 0xd1, 0xc3, 0x9d, 0x3a, 0xe5, 0xbb, 0x5c, 0xa7, 0xe9, + 0x5b, 0xc6, 0x99, 0x77, 0xb0, 0x14, 0xf8, 0x5d, 0xe8, 0x27, 0xc5, 0xc5, 0xa6, 0x93, 0x5d, 0xdb, + 0xf5, 0xe5, 0xb1, 0xd9, 0x07, 0xfa, 0xc0, 0xe4, 0x72, 0xdd, 0x43, 0xe5, 0x9a, 0x42, 0xc7, 0x3b, + 0xc9, 0x45, 0x72, 0x59, 0xf4, 0x01, 0xc9, 0xbd, 0x0b, 0x79, 0xaa, 0x3b, 0x6f, 0x7f, 0xb2, 0x9b, + 0x7d, 0xb0, 0x2f, 0x5c, 0x2e, 0xc9, 0x7d, 0x54, 0x92, 0x19, 0x34, 0xd5, 0x51, 0x12, 0x96, 0xfa, + 0xde, 0xee, 0x9b, 0x03, 0xd7, 0x8f, 0xc0, 0x74, 0x87, 0x16, 0x9d, 0xdd, 0x1e, 0x67, 0x5c, 0x5d, + 0x1e, 0xc2, 0xf6, 0x7c, 0xe8, 0x7a, 0xbb, 0x3f, 0xd3, 0xda, 0xe7, 0x81, 0xd8, 0x6f, 0xc5, 0x00, + 0x2d, 0xd9, 0xb5, 0x39, 0x0b, 0xb3, 0x7f, 0x22, 0xc9, 0xbd, 0x3c, 0xf4, 0xc2, 0x4b, 0x7a, 0x43, + 0x2f, 0xbc, 0x96, 0x02, 0x6f, 0xa6, 0x22, 0xfb, 0x7b, 0x97, 0xd9, 0xf7, 0xc3, 0xa9, 0xe8, 0x0f, + 0xe5, 0xe1, 0x54, 0xfb, 0x7b, 0xd5, 0xb1, 0xdb, 0xf7, 0x00, 0x23, 0x7e, 0xd0, 0x47, 0x28, 0xfc, + 0x3d, 0xe4, 0x60, 0x97, 0xf7, 0x90, 0x99, 0x8e, 0x8f, 0x1e, 0x39, 0x35, 0x3a, 0x27, 0x3e, 0x5a, + 0x3a, 0xd4, 0xdf, 0x4d, 0x58, 0xfe, 0x55, 0x53, 0x6f, 0x0b, 0xe1, 0x38, 0x64, 0x5b, 0xcd, 0xc9, + 0x75, 0xea, 0x8f, 0x44, 0x21, 0xbd, 0x64, 0xd7, 0x4a, 0x55, 0xcd, 0xb9, 0x43, 0xb6, 0xf6, 0x74, + 0xe7, 0x47, 0x2d, 0xe8, 0xd6, 0xcd, 0xe9, 0x51, 0xa6, 0xd3, 0x2e, 0x9a, 0x6c, 0xc0, 0x58, 0xe8, + 0x29, 0x31, 0xb7, 0xac, 0xe2, 0x41, 0x5e, 0x34, 0x87, 0x58, 0xc9, 0xf4, 0x0d, 0x82, 0xcf, 0xbe, + 0xd1, 0x6e, 0x7b, 0x63, 0x66, 0x06, 0x75, 0xe9, 0x4e, 0xbe, 0x00, 0xf4, 0xc6, 0x2c, 0x0b, 0x99, + 0xf0, 0xa0, 0xb8, 0x23, 0xf6, 0x07, 0x12, 0x0c, 0x2f, 0xd9, 0x22, 0x15, 0xc4, 0x3f, 0xa6, 0xef, + 0x8f, 0x1e, 0x77, 0xbf, 0xf8, 0x1d, 0xed, 0xcf, 0x6e, 0xc5, 0x57, 0xc0, 0x3d, 0x25, 0x1c, 0x82, + 0x09, 0x5f, 0x3f, 0xdd, 0xfe, 0xff, 0x76, 0x84, 0xc6, 0xc7, 0x02, 0xae, 0x69, 0xba, 0x9b, 0x45, + 0xe2, 0x3f, 0xaf, 0xaf, 0x2b, 0x3c, 0x3d, 0xc7, 0x0e, 0xaa, 0xe7, 0x1d, 0x1a, 0x20, 0x42, 0xfa, + 0x74, 0x37, 0xbe, 0x96, 0x5a, 0xdf, 0xfe, 0x48, 0xfb, 0xf8, 0xac, 0x4e, 0xe8, 0x85, 0x8f, 0xfc, + 0xba, 0x04, 0x23, 0x4b, 0x76, 0x6d, 0x43, 0xaf, 0xfe, 0x7f, 0x6f, 0xbf, 0x5b, 0x70, 0x28, 0xd0, + 0xd3, 0x3b, 0xa4, 0xd2, 0xb3, 0xaf, 0xc6, 0x20, 0xba, 0x64, 0xd7, 0xd0, 0x4b, 0x30, 0x16, 0x4e, + 0x1a, 0x3a, 0xe6, 0x82, 0xad, 0x33, 0x42, 0xe7, 0xf5, 0x5a, 0xe7, 0xd9, 0x03, 0xed, 0xc0, 0x48, + 0x70, 0xe6, 0x38, 0xd9, 0x85, 0x49, 0x00, 0x33, 0xfb, 0x70, 0xbf, 0x98, 0x6e, 0x63, 0x6f, 0x87, + 0x84, 0x1b, 0xf4, 0xee, 0xee, 0x42, 0x2d, 0x90, 0x3a, 0x67, 0xb7, 0x6d, 0xc2, 0x0a, 0xd1, 0x5e, + 0x38, 0xa4, 0x74, 0xd3, 0x5e, 0x08, 0xb7, 0xab, 0xf6, 0x3a, 0xb9, 0xd6, 0x26, 0x80, 0xcf, 0x0f, + 0xee, 0xed, 0xc2, 0xc1, 0x43, 0xcb, 0x9e, 0xee, 0x0b, 0xcd, 0x3d, 0x74, 0xba, 0xcd, 0xc9, 0xf8, + 0xff, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x80, 0x38, 0xe7, 0x40, 0xba, 0x97, 0x00, 0x00, } r := bytes.NewReader(gzipped) gzipr, err := compress_gzip.NewReader(r) From 2f426136bda08b965236043399046144436160bb Mon Sep 17 00:00:00 2001 From: Afanti Date: Sat, 20 Feb 2021 17:48:39 +0800 Subject: [PATCH 088/214] typo fix (#8647) Co-authored-by: Marko --- x/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/README.md b/x/README.md index e90ee59cebcb..7ca27e617e55 100644 --- a/x/README.md +++ b/x/README.md @@ -15,7 +15,7 @@ Here are some production-grade modules that can be used in Cosmos SDK applicatio - [Distribution](distribution/spec/README.md) - Fee distribution, and staking token provision distribution. - [Evidence](evidence/spec/README.md) - Evidence handling for double signing, misbehaviour, etc. - [Governance](gov/spec/README.md) - On-chain proposals and voting. -- [IBC](ibc/spec/README.md) - IBC protocol for transport, authentication adn ordering. +- [IBC](ibc/spec/README.md) - IBC protocol for transport, authentication and ordering. - [IBC Transfer](ibc/spec/README.md) - Cross-chain fungible token transfer implementation through IBC. - [Mint](mint/spec/README.md) - Creation of new units of staking token. - [Params](params/spec/README.md) - Globally available parameter store. From a846e4e4f97ec1b444bcb24ec5e3d4d72c4b6945 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Feb 2021 09:10:38 +0000 Subject: [PATCH 089/214] build(deps): bump github.com/otiai10/copy from 1.4.2 to 1.5.0 (#8655) Bumps [github.com/otiai10/copy](https://github.com/otiai10/copy) from 1.4.2 to 1.5.0. - [Release notes](https://github.com/otiai10/copy/releases) - [Commits](https://github.com/otiai10/copy/compare/v1.4.2...v1.5.0) 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 ea2011e8fbc9..a7b144bafbe6 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( 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 + github.com/otiai10/copy v1.5.0 github.com/pelletier/go-toml v1.8.1 // indirect github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.8.0 diff --git a/go.sum b/go.sum index 0f376c9f1a70..306e008eb8e2 100644 --- a/go.sum +++ b/go.sum @@ -505,8 +505,8 @@ github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxS github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/otiai10/copy v1.4.2 h1:RTiz2sol3eoXPLF4o+YWqEybwfUa/Q2Nkc4ZIUs3fwI= -github.com/otiai10/copy v1.4.2/go.mod h1:XWfuS3CrI0R6IE0FbgHsEazaXO8G0LpMp9o8tos0x4E= +github.com/otiai10/copy v1.5.0 h1:SoXDGnlTUZoqB/wSuj/Y5L6T5i6iN4YRAcMCd+JnLNU= +github.com/otiai10/copy v1.5.0/go.mod h1:XWfuS3CrI0R6IE0FbgHsEazaXO8G0LpMp9o8tos0x4E= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= github.com/otiai10/curr v1.0.0 h1:TJIWdbX0B+kpNagQrjgq8bCMrbhiuX73M2XwgtDMoOI= github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= From 7b527673cc623825d431e67537a19cb94ce8ae5f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Feb 2021 10:35:23 +0000 Subject: [PATCH 090/214] build(deps): bump github.com/prometheus/common from 0.16.0 to 0.17.0 (#8637) Bumps [github.com/prometheus/common](https://github.com/prometheus/common) from 0.16.0 to 0.17.0. - [Release notes](https://github.com/prometheus/common/releases) - [Commits](https://github.com/prometheus/common/compare/v0.16.0...v0.17.0) 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 a7b144bafbe6..4a04e6d95e11 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.16.0 + github.com/prometheus/common v0.17.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 306e008eb8e2..a2cfaea41db9 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.16.0 h1:VMiIg2fcMM+QkvAaPo6Hatk8OgpVHh4Yzp1+ljjjQAQ= -github.com/prometheus/common v0.16.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= +github.com/prometheus/common v0.17.0 h1:kDIZLI74SS+3tedSvEkykgBkD7txMxaJAPj8DtJUKYA= +github.com/prometheus/common v0.17.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 81cc5c11949611e1ae635a4ebc6c5057b03c974c Mon Sep 17 00:00:00 2001 From: MD Aleem <72057206+aleem1314@users.noreply.github.com> Date: Mon, 22 Feb 2021 17:00:45 +0530 Subject: [PATCH 091/214] gRPC gateway issue with colons in the account url path (#8649) * add allow_colon_final_segments flag * add test * Update x/auth/client/rest/rest_test.go Co-authored-by: Amaury <1293565+amaurym@users.noreply.github.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- client/grpc/reflection/reflection.pb.gw.go | 4 +-- client/grpc/tmservice/query.pb.gw.go | 12 ++++---- scripts/protocgen.sh | 2 +- types/tx/service.pb.gw.go | 8 +++--- x/auth/client/rest/rest_test.go | 12 ++++++++ x/auth/types/query.pb.gw.go | 4 +-- x/authz/types/query.pb.gw.go | 4 +-- x/bank/types/query.pb.gw.go | 14 +++++----- x/distribution/types/query.pb.gw.go | 18 ++++++------ x/evidence/types/query.pb.gw.go | 4 +-- x/feegrant/types/query.pb.gw.go | 4 +-- x/gov/types/query.pb.gw.go | 16 +++++------ .../transfer/types/query.pb.gw.go | 6 ++-- x/ibc/core/02-client/types/query.pb.gw.go | 10 +++---- x/ibc/core/03-connection/types/query.pb.gw.go | 10 +++---- x/ibc/core/04-channel/types/query.pb.gw.go | 26 ++++++++--------- x/mint/types/query.pb.gw.go | 6 ++-- x/params/types/proposal/query.pb.gw.go | 2 +- x/slashing/types/query.pb.gw.go | 6 ++-- x/staking/types/query.pb.gw.go | 28 +++++++++---------- x/upgrade/types/query.pb.gw.go | 6 ++-- 21 files changed, 107 insertions(+), 95 deletions(-) diff --git a/client/grpc/reflection/reflection.pb.gw.go b/client/grpc/reflection/reflection.pb.gw.go index ab486750e860..7bb8a5e12836 100644 --- a/client/grpc/reflection/reflection.pb.gw.go +++ b/client/grpc/reflection/reflection.pb.gw.go @@ -234,9 +234,9 @@ func RegisterReflectionServiceHandlerClient(ctx context.Context, mux *runtime.Se } var ( - pattern_ReflectionService_ListAllInterfaces_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"cosmos", "base", "reflection", "v1beta1", "interfaces"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_ReflectionService_ListAllInterfaces_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"cosmos", "base", "reflection", "v1beta1", "interfaces"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_ReflectionService_ListImplementations_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6}, []string{"cosmos", "base", "reflection", "v1beta1", "interfaces", "interface_name", "implementations"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_ReflectionService_ListImplementations_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6}, []string{"cosmos", "base", "reflection", "v1beta1", "interfaces", "interface_name", "implementations"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( diff --git a/client/grpc/tmservice/query.pb.gw.go b/client/grpc/tmservice/query.pb.gw.go index 90135d79b937..a53a31fccfc0 100644 --- a/client/grpc/tmservice/query.pb.gw.go +++ b/client/grpc/tmservice/query.pb.gw.go @@ -538,17 +538,17 @@ func RegisterServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, cl } var ( - pattern_Service_GetNodeInfo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"cosmos", "base", "tendermint", "v1beta1", "node_info"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Service_GetNodeInfo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"cosmos", "base", "tendermint", "v1beta1", "node_info"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Service_GetSyncing_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"cosmos", "base", "tendermint", "v1beta1", "syncing"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Service_GetSyncing_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"cosmos", "base", "tendermint", "v1beta1", "syncing"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Service_GetLatestBlock_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 2, 5}, []string{"cosmos", "base", "tendermint", "v1beta1", "blocks", "latest"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Service_GetLatestBlock_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 2, 5}, []string{"cosmos", "base", "tendermint", "v1beta1", "blocks", "latest"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Service_GetBlockByHeight_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"cosmos", "base", "tendermint", "v1beta1", "blocks", "height"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Service_GetBlockByHeight_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"cosmos", "base", "tendermint", "v1beta1", "blocks", "height"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Service_GetLatestValidatorSet_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 2, 5}, []string{"cosmos", "base", "tendermint", "v1beta1", "validatorsets", "latest"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Service_GetLatestValidatorSet_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 2, 5}, []string{"cosmos", "base", "tendermint", "v1beta1", "validatorsets", "latest"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Service_GetValidatorSetByHeight_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"cosmos", "base", "tendermint", "v1beta1", "validatorsets", "height"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Service_GetValidatorSetByHeight_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"cosmos", "base", "tendermint", "v1beta1", "validatorsets", "height"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( diff --git a/scripts/protocgen.sh b/scripts/protocgen.sh index bd3e4009712b..84eb751c3a10 100755 --- a/scripts/protocgen.sh +++ b/scripts/protocgen.sh @@ -20,7 +20,7 @@ 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:. \ - --grpc-gateway_out=logtostderr=true:. \ + --grpc-gateway_out=logtostderr=true,allow_colon_final_segments=true:. \ $(find "${dir}" -maxdepth 1 -name '*.proto') done diff --git a/types/tx/service.pb.gw.go b/types/tx/service.pb.gw.go index 6d94c423ecbd..25560e1cdfb2 100644 --- a/types/tx/service.pb.gw.go +++ b/types/tx/service.pb.gw.go @@ -400,13 +400,13 @@ func RegisterServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, cl } var ( - pattern_Service_Simulate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "tx", "v1beta1", "simulate"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Service_Simulate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "tx", "v1beta1", "simulate"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Service_GetTx_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"cosmos", "tx", "v1beta1", "txs", "hash"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Service_GetTx_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"cosmos", "tx", "v1beta1", "txs", "hash"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Service_BroadcastTx_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "tx", "v1beta1", "txs"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Service_BroadcastTx_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "tx", "v1beta1", "txs"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Service_GetTxsEvent_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "tx", "v1beta1", "txs"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Service_GetTxsEvent_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "tx", "v1beta1", "txs"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( diff --git a/x/auth/client/rest/rest_test.go b/x/auth/client/rest/rest_test.go index b78acd2c8a9a..b420c7a780c6 100644 --- a/x/auth/client/rest/rest_test.go +++ b/x/auth/client/rest/rest_test.go @@ -156,6 +156,18 @@ func (s *IntegrationTestSuite) TestEncodeDecode() { require.Equal(stdTx, legacytx.StdTx(decodeResp)) } +func (s *IntegrationTestSuite) TestQueryAccountWithColon() { + val := s.network.Validators[0] + // This address is not a valid simapp address! It is only used to test that addresses with + // colon don't 501. See + // https://github.com/cosmos/cosmos-sdk/issues/8650 + addrWithColon := "cosmos:1m4f6lwd9eh8e5nxt0h00d46d3fr03apfh8qf4g" + + res, err := rest.GetRequest(fmt.Sprintf("%s/cosmos/auth/v1beta1/accounts/%s", val.APIAddress, addrWithColon)) + s.Require().NoError(err) + s.Require().Contains(string(res), "decoding bech32 failed") +} + func (s *IntegrationTestSuite) TestEncodeIBCTx() { val := s.network.Validators[0] diff --git a/x/auth/types/query.pb.gw.go b/x/auth/types/query.pb.gw.go index 0525b9c15364..1f9c0a70a152 100644 --- a/x/auth/types/query.pb.gw.go +++ b/x/auth/types/query.pb.gw.go @@ -234,9 +234,9 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie } var ( - pattern_Query_Account_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"cosmos", "auth", "v1beta1", "accounts", "address"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_Account_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"cosmos", "auth", "v1beta1", "accounts", "address"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "auth", "v1beta1", "params"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "auth", "v1beta1", "params"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( diff --git a/x/authz/types/query.pb.gw.go b/x/authz/types/query.pb.gw.go index d1cd24bc0b54..d353c1bf07fb 100644 --- a/x/authz/types/query.pb.gw.go +++ b/x/authz/types/query.pb.gw.go @@ -350,9 +350,9 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie } 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_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(false))) - 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))) + 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(false))) ) var ( diff --git a/x/bank/types/query.pb.gw.go b/x/bank/types/query.pb.gw.go index 06c7e2d04aa5..3dec93b8b363 100644 --- a/x/bank/types/query.pb.gw.go +++ b/x/bank/types/query.pb.gw.go @@ -690,19 +690,19 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie } var ( - pattern_Query_Balance_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", "bank", "v1beta1", "balances", "address", "denom"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_Balance_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", "bank", "v1beta1", "balances", "address", "denom"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_AllBalances_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", "balances", "address"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_AllBalances_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", "balances", "address"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_TotalSupply_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "bank", "v1beta1", "supply"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_TotalSupply_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "bank", "v1beta1", "supply"}, "", runtime.AssumeColonVerbOpt(false))) - 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_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(false))) - 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_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "bank", "v1beta1", "params"}, "", runtime.AssumeColonVerbOpt(false))) - 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_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(false))) - 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))) + 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(false))) ) var ( diff --git a/x/distribution/types/query.pb.gw.go b/x/distribution/types/query.pb.gw.go index 7bbe7b7a29fb..2e8f1cde3ff1 100644 --- a/x/distribution/types/query.pb.gw.go +++ b/x/distribution/types/query.pb.gw.go @@ -896,23 +896,23 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie } var ( - pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "distribution", "v1beta1", "params"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "distribution", "v1beta1", "params"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_ValidatorOutstandingRewards_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"cosmos", "distribution", "v1beta1", "validators", "validator_address", "outstanding_rewards"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_ValidatorOutstandingRewards_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"cosmos", "distribution", "v1beta1", "validators", "validator_address", "outstanding_rewards"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_ValidatorCommission_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"cosmos", "distribution", "v1beta1", "validators", "validator_address", "commission"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_ValidatorCommission_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"cosmos", "distribution", "v1beta1", "validators", "validator_address", "commission"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_ValidatorSlashes_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"cosmos", "distribution", "v1beta1", "validators", "validator_address", "slashes"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_ValidatorSlashes_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"cosmos", "distribution", "v1beta1", "validators", "validator_address", "slashes"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_DelegationRewards_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}, []string{"cosmos", "distribution", "v1beta1", "delegators", "delegator_address", "rewards", "validator_address"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_DelegationRewards_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}, []string{"cosmos", "distribution", "v1beta1", "delegators", "delegator_address", "rewards", "validator_address"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_DelegationTotalRewards_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"cosmos", "distribution", "v1beta1", "delegators", "delegator_address", "rewards"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_DelegationTotalRewards_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"cosmos", "distribution", "v1beta1", "delegators", "delegator_address", "rewards"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_DelegatorValidators_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"cosmos", "distribution", "v1beta1", "delegators", "delegator_address", "validators"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_DelegatorValidators_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"cosmos", "distribution", "v1beta1", "delegators", "delegator_address", "validators"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_DelegatorWithdrawAddress_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"cosmos", "distribution", "v1beta1", "delegators", "delegator_address", "withdraw_address"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_DelegatorWithdrawAddress_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"cosmos", "distribution", "v1beta1", "delegators", "delegator_address", "withdraw_address"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_CommunityPool_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "distribution", "v1beta1", "community_pool"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_CommunityPool_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "distribution", "v1beta1", "community_pool"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( diff --git a/x/evidence/types/query.pb.gw.go b/x/evidence/types/query.pb.gw.go index e15d163524b4..6f85fd6f1e10 100644 --- a/x/evidence/types/query.pb.gw.go +++ b/x/evidence/types/query.pb.gw.go @@ -252,9 +252,9 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie } var ( - pattern_Query_Evidence_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 1, 1, 0, 4, 1, 5, 3}, []string{"cosmos", "evidence", "v1beta1", "evidence_hash"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_Evidence_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 1, 1, 0, 4, 1, 5, 3}, []string{"cosmos", "evidence", "v1beta1", "evidence_hash"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_AllEvidence_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 1}, []string{"cosmos", "evidence", "v1beta1"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_AllEvidence_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 1}, []string{"cosmos", "evidence", "v1beta1"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( diff --git a/x/feegrant/types/query.pb.gw.go b/x/feegrant/types/query.pb.gw.go index 499e4a441d18..ef81bab40a70 100644 --- a/x/feegrant/types/query.pb.gw.go +++ b/x/feegrant/types/query.pb.gw.go @@ -310,9 +310,9 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie } 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_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(false))) - 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))) + 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(false))) ) var ( diff --git a/x/gov/types/query.pb.gw.go b/x/gov/types/query.pb.gw.go index 52814511b9cb..4b6832d41e7b 100644 --- a/x/gov/types/query.pb.gw.go +++ b/x/gov/types/query.pb.gw.go @@ -896,21 +896,21 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie } var ( - pattern_Query_Proposal_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"cosmos", "gov", "v1beta1", "proposals", "proposal_id"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_Proposal_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"cosmos", "gov", "v1beta1", "proposals", "proposal_id"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_Proposals_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "gov", "v1beta1", "proposals"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_Proposals_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "gov", "v1beta1", "proposals"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_Vote_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}, []string{"cosmos", "gov", "v1beta1", "proposals", "proposal_id", "votes", "voter"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_Vote_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}, []string{"cosmos", "gov", "v1beta1", "proposals", "proposal_id", "votes", "voter"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_Votes_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"cosmos", "gov", "v1beta1", "proposals", "proposal_id", "votes"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_Votes_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"cosmos", "gov", "v1beta1", "proposals", "proposal_id", "votes"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"cosmos", "gov", "v1beta1", "params", "params_type"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"cosmos", "gov", "v1beta1", "params", "params_type"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_Deposit_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}, []string{"cosmos", "gov", "v1beta1", "proposals", "proposal_id", "deposits", "depositor"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_Deposit_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}, []string{"cosmos", "gov", "v1beta1", "proposals", "proposal_id", "deposits", "depositor"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_Deposits_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"cosmos", "gov", "v1beta1", "proposals", "proposal_id", "deposits"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_Deposits_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"cosmos", "gov", "v1beta1", "proposals", "proposal_id", "deposits"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_TallyResult_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"cosmos", "gov", "v1beta1", "proposals", "proposal_id", "tally"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_TallyResult_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"cosmos", "gov", "v1beta1", "proposals", "proposal_id", "tally"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( diff --git a/x/ibc/applications/transfer/types/query.pb.gw.go b/x/ibc/applications/transfer/types/query.pb.gw.go index 99a7f1906350..007ed6682074 100644 --- a/x/ibc/applications/transfer/types/query.pb.gw.go +++ b/x/ibc/applications/transfer/types/query.pb.gw.go @@ -310,11 +310,11 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie } var ( - pattern_Query_DenomTrace_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"ibc", "applications", "transfer", "v1beta1", "denom_traces", "hash"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_DenomTrace_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"ibc", "applications", "transfer", "v1beta1", "denom_traces", "hash"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_DenomTraces_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"ibc", "applications", "transfer", "v1beta1", "denom_traces"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_DenomTraces_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"ibc", "applications", "transfer", "v1beta1", "denom_traces"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"ibc", "applications", "transfer", "v1beta1", "params"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"ibc", "applications", "transfer", "v1beta1", "params"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( 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..40bc6a85fdd0 100644 --- a/x/ibc/core/02-client/types/query.pb.gw.go +++ b/x/ibc/core/02-client/types/query.pb.gw.go @@ -578,15 +578,15 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie } var ( - pattern_Query_ClientState_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"ibc", "core", "client", "v1beta1", "client_states", "client_id"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_ClientState_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"ibc", "core", "client", "v1beta1", "client_states", "client_id"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_ClientStates_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"ibc", "core", "client", "v1beta1", "client_states"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_ClientStates_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"ibc", "core", "client", "v1beta1", "client_states"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_ConsensusState_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8, 1, 0, 4, 1, 5, 9}, []string{"ibc", "core", "client", "v1beta1", "consensus_states", "client_id", "revision", "revision_number", "height", "revision_height"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_ConsensusState_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8, 1, 0, 4, 1, 5, 9}, []string{"ibc", "core", "client", "v1beta1", "consensus_states", "client_id", "revision", "revision_number", "height", "revision_height"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_ConsensusStates_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"ibc", "core", "client", "v1beta1", "consensus_states", "client_id"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_ConsensusStates_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"ibc", "core", "client", "v1beta1", "consensus_states", "client_id"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_ClientParams_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"ibc", "client", "v1beta1", "params"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_ClientParams_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"ibc", "client", "v1beta1", "params"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( 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..f9824f5bd2ae 100644 --- a/x/ibc/core/03-connection/types/query.pb.gw.go +++ b/x/ibc/core/03-connection/types/query.pb.gw.go @@ -578,15 +578,15 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie } var ( - pattern_Query_Connection_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"ibc", "core", "connection", "v1beta1", "connections", "connection_id"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_Connection_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"ibc", "core", "connection", "v1beta1", "connections", "connection_id"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_Connections_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"ibc", "core", "connection", "v1beta1", "connections"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_Connections_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"ibc", "core", "connection", "v1beta1", "connections"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_ClientConnections_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"ibc", "core", "connection", "v1beta1", "client_connections", "client_id"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_ClientConnections_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"ibc", "core", "connection", "v1beta1", "client_connections", "client_id"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_ConnectionClientState_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6}, []string{"ibc", "core", "connection", "v1beta1", "connections", "connection_id", "client_state"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_ConnectionClientState_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6}, []string{"ibc", "core", "connection", "v1beta1", "connections", "connection_id", "client_state"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_ConnectionConsensusState_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 2, 7, 1, 0, 4, 1, 5, 8, 2, 9, 1, 0, 4, 1, 5, 10}, []string{"ibc", "core", "connection", "v1beta1", "connections", "connection_id", "consensus_state", "revision", "revision_number", "height", "revision_height"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_ConnectionConsensusState_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 2, 7, 1, 0, 4, 1, 5, 8, 2, 9, 1, 0, 4, 1, 5, 10}, []string{"ibc", "core", "connection", "v1beta1", "connections", "connection_id", "consensus_state", "revision", "revision_number", "height", "revision_height"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( 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..f38c05956ee9 100644 --- a/x/ibc/core/04-channel/types/query.pb.gw.go +++ b/x/ibc/core/04-channel/types/query.pb.gw.go @@ -1736,31 +1736,31 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie } var ( - pattern_Query_Channel_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7}, []string{"ibc", "core", "channel", "v1beta1", "channels", "channel_id", "ports", "port_id"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_Channel_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7}, []string{"ibc", "core", "channel", "v1beta1", "channels", "channel_id", "ports", "port_id"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_Channels_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"ibc", "core", "channel", "v1beta1", "channels"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_Channels_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"ibc", "core", "channel", "v1beta1", "channels"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_ConnectionChannels_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6}, []string{"ibc", "core", "channel", "v1beta1", "connections", "connection", "channels"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_ConnectionChannels_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6}, []string{"ibc", "core", "channel", "v1beta1", "connections", "connection", "channels"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_ChannelClientState_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8}, []string{"ibc", "core", "channel", "v1beta1", "channels", "channel_id", "ports", "port_id", "client_state"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_ChannelClientState_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8}, []string{"ibc", "core", "channel", "v1beta1", "channels", "channel_id", "ports", "port_id", "client_state"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_ChannelConsensusState_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8, 2, 9, 1, 0, 4, 1, 5, 10, 2, 11, 1, 0, 4, 1, 5, 12}, []string{"ibc", "core", "channel", "v1beta1", "channels", "channel_id", "ports", "port_id", "consensus_state", "revision", "revision_number", "height", "revision_height"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_ChannelConsensusState_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8, 2, 9, 1, 0, 4, 1, 5, 10, 2, 11, 1, 0, 4, 1, 5, 12}, []string{"ibc", "core", "channel", "v1beta1", "channels", "channel_id", "ports", "port_id", "consensus_state", "revision", "revision_number", "height", "revision_height"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_PacketCommitment_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8, 1, 0, 4, 1, 5, 9}, []string{"ibc", "core", "channel", "v1beta1", "channels", "channel_id", "ports", "port_id", "packet_commitments", "sequence"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_PacketCommitment_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8, 1, 0, 4, 1, 5, 9}, []string{"ibc", "core", "channel", "v1beta1", "channels", "channel_id", "ports", "port_id", "packet_commitments", "sequence"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_PacketCommitments_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8}, []string{"ibc", "core", "channel", "v1beta1", "channels", "channel_id", "ports", "port_id", "packet_commitments"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_PacketCommitments_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8}, []string{"ibc", "core", "channel", "v1beta1", "channels", "channel_id", "ports", "port_id", "packet_commitments"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_PacketReceipt_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8, 1, 0, 4, 1, 5, 9}, []string{"ibc", "core", "channel", "v1beta1", "channels", "channel_id", "ports", "port_id", "packet_receipts", "sequence"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_PacketReceipt_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8, 1, 0, 4, 1, 5, 9}, []string{"ibc", "core", "channel", "v1beta1", "channels", "channel_id", "ports", "port_id", "packet_receipts", "sequence"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_PacketAcknowledgement_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8, 1, 0, 4, 1, 5, 9}, []string{"ibc", "core", "channel", "v1beta1", "channels", "channel_id", "ports", "port_id", "packet_acks", "sequence"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_PacketAcknowledgement_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8, 1, 0, 4, 1, 5, 9}, []string{"ibc", "core", "channel", "v1beta1", "channels", "channel_id", "ports", "port_id", "packet_acks", "sequence"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_PacketAcknowledgements_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8}, []string{"ibc", "core", "channel", "v1beta1", "channels", "channel_id", "ports", "port_id", "packet_acknowledgements"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_PacketAcknowledgements_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8}, []string{"ibc", "core", "channel", "v1beta1", "channels", "channel_id", "ports", "port_id", "packet_acknowledgements"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_UnreceivedPackets_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8, 1, 0, 4, 1, 5, 9, 2, 10}, []string{"ibc", "core", "channel", "v1beta1", "channels", "channel_id", "ports", "port_id", "packet_commitments", "packet_commitment_sequences", "unreceived_packets"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_UnreceivedPackets_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8, 1, 0, 4, 1, 5, 9, 2, 10}, []string{"ibc", "core", "channel", "v1beta1", "channels", "channel_id", "ports", "port_id", "packet_commitments", "packet_commitment_sequences", "unreceived_packets"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_UnreceivedAcks_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8, 1, 0, 4, 1, 5, 9, 2, 10}, []string{"ibc", "core", "channel", "v1beta1", "channels", "channel_id", "ports", "port_id", "packet_commitments", "packet_ack_sequences", "unreceived_acks"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_UnreceivedAcks_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8, 1, 0, 4, 1, 5, 9, 2, 10}, []string{"ibc", "core", "channel", "v1beta1", "channels", "channel_id", "ports", "port_id", "packet_commitments", "packet_ack_sequences", "unreceived_acks"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_NextSequenceReceive_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8}, []string{"ibc", "core", "channel", "v1beta1", "channels", "channel_id", "ports", "port_id", "next_sequence"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_NextSequenceReceive_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8}, []string{"ibc", "core", "channel", "v1beta1", "channels", "channel_id", "ports", "port_id", "next_sequence"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( diff --git a/x/mint/types/query.pb.gw.go b/x/mint/types/query.pb.gw.go index c70c3e60b077..576b206d4a4e 100644 --- a/x/mint/types/query.pb.gw.go +++ b/x/mint/types/query.pb.gw.go @@ -256,11 +256,11 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie } var ( - pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "mint", "v1beta1", "params"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "mint", "v1beta1", "params"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_Inflation_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "mint", "v1beta1", "inflation"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_Inflation_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "mint", "v1beta1", "inflation"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_AnnualProvisions_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "mint", "v1beta1", "annual_provisions"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_AnnualProvisions_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "mint", "v1beta1", "annual_provisions"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( diff --git a/x/params/types/proposal/query.pb.gw.go b/x/params/types/proposal/query.pb.gw.go index c7fab13fca65..f5b9f9d5b686 100644 --- a/x/params/types/proposal/query.pb.gw.go +++ b/x/params/types/proposal/query.pb.gw.go @@ -158,7 +158,7 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie } var ( - pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 1}, []string{"cosmos", "params", "v1beta1"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 1}, []string{"cosmos", "params", "v1beta1"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( diff --git a/x/slashing/types/query.pb.gw.go b/x/slashing/types/query.pb.gw.go index 083fe73aa9f5..95446797bfab 100644 --- a/x/slashing/types/query.pb.gw.go +++ b/x/slashing/types/query.pb.gw.go @@ -310,11 +310,11 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie } var ( - pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "slashing", "v1beta1", "params"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "slashing", "v1beta1", "params"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_SigningInfo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"cosmos", "slashing", "v1beta1", "signing_infos", "cons_address"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_SigningInfo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"cosmos", "slashing", "v1beta1", "signing_infos", "cons_address"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_SigningInfos_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "slashing", "v1beta1", "signing_infos"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_SigningInfos_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "slashing", "v1beta1", "signing_infos"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( diff --git a/x/staking/types/query.pb.gw.go b/x/staking/types/query.pb.gw.go index eecdb3f3168d..0982dfc3d671 100644 --- a/x/staking/types/query.pb.gw.go +++ b/x/staking/types/query.pb.gw.go @@ -1482,33 +1482,33 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie } var ( - pattern_Query_Validators_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "staking", "v1beta1", "validators"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_Validators_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "staking", "v1beta1", "validators"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_Validator_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"cosmos", "staking", "v1beta1", "validators", "validator_addr"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_Validator_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"cosmos", "staking", "v1beta1", "validators", "validator_addr"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_ValidatorDelegations_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"cosmos", "staking", "v1beta1", "validators", "validator_addr", "delegations"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_ValidatorDelegations_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"cosmos", "staking", "v1beta1", "validators", "validator_addr", "delegations"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_ValidatorUnbondingDelegations_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"cosmos", "staking", "v1beta1", "validators", "validator_addr", "unbonding_delegations"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_ValidatorUnbondingDelegations_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"cosmos", "staking", "v1beta1", "validators", "validator_addr", "unbonding_delegations"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_Delegation_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}, []string{"cosmos", "staking", "v1beta1", "validators", "validator_addr", "delegations", "delegator_addr"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_Delegation_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}, []string{"cosmos", "staking", "v1beta1", "validators", "validator_addr", "delegations", "delegator_addr"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_UnbondingDelegation_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", "staking", "v1beta1", "validators", "validator_addr", "delegations", "delegator_addr", "unbonding_delegation"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_UnbondingDelegation_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", "staking", "v1beta1", "validators", "validator_addr", "delegations", "delegator_addr", "unbonding_delegation"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_DelegatorDelegations_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"cosmos", "staking", "v1beta1", "delegations", "delegator_addr"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_DelegatorDelegations_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"cosmos", "staking", "v1beta1", "delegations", "delegator_addr"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_DelegatorUnbondingDelegations_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"cosmos", "staking", "v1beta1", "delegators", "delegator_addr", "unbonding_delegations"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_DelegatorUnbondingDelegations_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"cosmos", "staking", "v1beta1", "delegators", "delegator_addr", "unbonding_delegations"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_Redelegations_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"cosmos", "staking", "v1beta1", "delegators", "delegator_addr", "redelegations"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_Redelegations_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"cosmos", "staking", "v1beta1", "delegators", "delegator_addr", "redelegations"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_DelegatorValidators_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"cosmos", "staking", "v1beta1", "delegators", "delegator_addr", "validators"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_DelegatorValidators_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"cosmos", "staking", "v1beta1", "delegators", "delegator_addr", "validators"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_DelegatorValidator_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}, []string{"cosmos", "staking", "v1beta1", "delegators", "delegator_addr", "validators", "validator_addr"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_DelegatorValidator_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}, []string{"cosmos", "staking", "v1beta1", "delegators", "delegator_addr", "validators", "validator_addr"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_HistoricalInfo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"cosmos", "staking", "v1beta1", "historical_info", "height"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_HistoricalInfo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"cosmos", "staking", "v1beta1", "historical_info", "height"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_Pool_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "staking", "v1beta1", "pool"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_Pool_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "staking", "v1beta1", "pool"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "staking", "v1beta1", "params"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "staking", "v1beta1", "params"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( diff --git a/x/upgrade/types/query.pb.gw.go b/x/upgrade/types/query.pb.gw.go index cf1f9def8eee..166646416525 100644 --- a/x/upgrade/types/query.pb.gw.go +++ b/x/upgrade/types/query.pb.gw.go @@ -328,11 +328,11 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie } var ( - pattern_Query_CurrentPlan_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "upgrade", "v1beta1", "current_plan"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_CurrentPlan_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "upgrade", "v1beta1", "current_plan"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_AppliedPlan_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"cosmos", "upgrade", "v1beta1", "applied_plan", "name"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_AppliedPlan_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"cosmos", "upgrade", "v1beta1", "applied_plan", "name"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_UpgradedConsensusState_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"cosmos", "upgrade", "v1beta1", "upgraded_consensus_state", "last_height"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_UpgradedConsensusState_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"cosmos", "upgrade", "v1beta1", "upgraded_consensus_state", "last_height"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( From 2f069c90b355232a69a9f172e1ee15fb4803da7e Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Mon, 22 Feb 2021 06:51:35 -0500 Subject: [PATCH 092/214] server: fix interceptConfigs (#8641) * server: fix interceptConfigs * cl++ * revert call * update error message * revise TestInterceptConfigsPreRunHandlerDoesNotMixConfigFiles * remove TestInterceptConfigsPreRunHandlerDoesNotMixConfigFiles Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- CHANGELOG.md | 1 + server/util.go | 29 ++++++++++--------- server/util_test.go | 70 --------------------------------------------- 3 files changed, 17 insertions(+), 83 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 45c93da693c5..65d0f352aa04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,6 +64,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (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 +* (server) [\#8641](https://github.com/cosmos/cosmos-sdk/pull/8641) Fix Tendermint and application configuration reading from file ## [v0.41.1](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.41.1) - 2021-02-17 diff --git a/server/util.go b/server/util.go index bc913eb2962c..68f1c4828166 100644 --- a/server/util.go +++ b/server/util.go @@ -184,11 +184,11 @@ func SetCmdServerContext(cmd *cobra.Command, serverCtx *Context) error { func interceptConfigs(rootViper *viper.Viper) (*tmcfg.Config, error) { rootDir := rootViper.GetString(flags.FlagHome) configPath := filepath.Join(rootDir, "config") - configFile := filepath.Join(configPath, "config.toml") + tmCfgFile := filepath.Join(configPath, "config.toml") conf := tmcfg.DefaultConfig() - switch _, err := os.Stat(configFile); { + switch _, err := os.Stat(tmCfgFile); { case os.IsNotExist(err): tmcfg.EnsureRoot(rootDir) @@ -200,7 +200,7 @@ func interceptConfigs(rootViper *viper.Viper) (*tmcfg.Config, error) { conf.P2P.RecvRate = 5120000 conf.P2P.SendRate = 5120000 conf.Consensus.TimeoutCommit = 5 * time.Second - tmcfg.WriteConfigFile(configFile, conf) + tmcfg.WriteConfigFile(tmCfgFile, conf) case err != nil: return nil, err @@ -209,34 +209,37 @@ func interceptConfigs(rootViper *viper.Viper) (*tmcfg.Config, error) { rootViper.SetConfigType("toml") rootViper.SetConfigName("config") rootViper.AddConfigPath(configPath) + if err := rootViper.ReadInConfig(); err != nil { - return nil, fmt.Errorf("failed to read in config.toml: %w", err) + return nil, fmt.Errorf("failed to read in %s: %w", tmCfgFile, err) } } - // Read into the configuration whatever data the viper instance has for it - // This may come from the configuration file above but also any of the other sources - // viper uses + // Read into the configuration whatever data the viper instance has for it. + // This may come from the configuration file above but also any of the other + // sources viper uses. if err := rootViper.Unmarshal(conf); err != nil { return nil, err } + conf.SetRoot(rootDir) - appConfigFilePath := filepath.Join(configPath, "app.toml") - if _, err := os.Stat(appConfigFilePath); os.IsNotExist(err) { + appCfgFilePath := filepath.Join(configPath, "app.toml") + if _, err := os.Stat(appCfgFilePath); os.IsNotExist(err) { appConf, err := config.ParseConfig(rootViper) if err != nil { - return nil, fmt.Errorf("failed to parse app.toml: %w", err) + return nil, fmt.Errorf("failed to parse %s: %w", appCfgFilePath, err) } - config.WriteConfigFile(appConfigFilePath, appConf) + config.WriteConfigFile(appCfgFilePath, appConf) } rootViper.SetConfigType("toml") rootViper.SetConfigName("app") rootViper.AddConfigPath(configPath) - if err := rootViper.ReadInConfig(); err != nil { - return nil, fmt.Errorf("failed to read in app.toml: %w", err) + + if err := rootViper.MergeInConfig(); err != nil { + return nil, fmt.Errorf("failed to merge configuration: %w", err) } return conf, nil diff --git a/server/util_test.go b/server/util_test.go index a0ff6479b82d..0800b59a30c1 100644 --- a/server/util_test.go +++ b/server/util_test.go @@ -162,76 +162,6 @@ func TestInterceptConfigsPreRunHandlerReadsAppToml(t *testing.T) { } } -func TestInterceptConfigsPreRunHandlerDoesNotMixConfigFiles(t *testing.T) { - // The goal of this test is to make sure that app.toml and config.toml - // are separate files and that mixing values does not work - const testDbBackend = "awesome_test_db" - const testHaltTime = 1337 - const testHaltHeight = 2001 - - tempDir := t.TempDir() - err := os.Mkdir(path.Join(tempDir, "config"), os.ModePerm) - if err != nil { - t.Fatalf("creating config dir failed: %v", err) - } - configTomlPath := path.Join(tempDir, "config", "config.toml") - writer, err := os.Create(configTomlPath) - if err != nil { - t.Fatalf("creating config.toml file failed: %v", err) - } - - // Put a value in config.toml that should be in app.toml - _, err = writer.WriteString(fmt.Sprintf("halt-time = %d\ndb_backend = \"%s\"\n", testHaltTime, testDbBackend)) - if err != nil { - t.Fatalf("Failed writing string to config.toml: %v", err) - } - - if err := writer.Close(); err != nil { - t.Fatalf("Failed closing config.toml: %v", err) - } - - appTomlPath := path.Join(tempDir, "config", "app.toml") - writer, err = os.Create(appTomlPath) - if err != nil { - t.Fatalf("creating app.toml file failed %v", err) - } - - // Put a different value in app.toml - _, err = writer.WriteString(fmt.Sprintf("halt-height = %d\n", testHaltHeight)) - if err != nil { - t.Fatalf("Failed writing string to app.toml: %v", err) - } - - if err := writer.Close(); err != nil { - t.Fatalf("Failed closing app.toml: %v", err) - } - - cmd := StartCmd(nil, tempDir) - cmd.PreRunE = preRunETestImpl - - serverCtx := &Context{} - ctx := context.WithValue(context.Background(), ServerContextKey, serverCtx) - - if err := cmd.ExecuteContext(ctx); err != CancelledInPreRun { - t.Fatalf("function failed with [%T] %v", err, err) - } - - // check that the intended value from config.toml is used - if testDbBackend != serverCtx.Config.DBBackend { - t.Error("DBPath was not set from config.toml") - } - - // The value from app.toml should be used for this - if testHaltHeight != serverCtx.Viper.GetInt("halt-height") { - t.Error("Halt height is not using provided value") - } - - // The value from config.toml should not be used, default is used instead - if 0 != serverCtx.Viper.GetInt("halt-time") { - t.Error("Halt time is not using default") - } -} - func TestInterceptConfigsPreRunHandlerReadsFlags(t *testing.T) { const testAddr = "tcp://127.1.2.3:12345" tempDir := t.TempDir() From 0b3af0e4e04229176028596295c77a424d6f0efc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Feb 2021 12:34:58 +0000 Subject: [PATCH 093/214] build(deps): bump github.com/prometheus/client_golang from 1.8.0 to 1.9.0 (#8180) * build(deps): bump github.com/prometheus/client_golang Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.8.0 to 1.9.0. - [Release notes](https://github.com/prometheus/client_golang/releases) - [Changelog](https://github.com/prometheus/client_golang/blob/master/CHANGELOG.md) - [Commits](https://github.com/prometheus/client_golang/compare/v1.8.0...v1.9.0) Signed-off-by: dependabot[bot] * go mod tidy Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Robert Zaremba Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Amaury M <1293565+amaurym@users.noreply.github.com> --- go.mod | 2 +- go.sum | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 4a04e6d95e11..3f499cf7aebd 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,7 @@ require ( github.com/otiai10/copy v1.5.0 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/client_golang v1.9.0 github.com/prometheus/common v0.17.0 github.com/rakyll/statik v0.1.7 github.com/regen-network/cosmos-proto v0.3.1 diff --git a/go.sum b/go.sum index a2cfaea41db9..d9e12cebd799 100644 --- a/go.sum +++ b/go.sum @@ -546,6 +546,8 @@ github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3O github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.8.0 h1:zvJNkoCFAnYFNC24FV8nW4JdRJ3GIFcLbg65lL/JDcw= github.com/prometheus/client_golang v1.8.0/go.mod h1:O9VU6huf47PktckDQfMTX0Y8tY0/7TSWwj+ITvv0TnM= +github.com/prometheus/client_golang v1.9.0 h1:Rrch9mh17XcxvEu9D9DEpb4isxjGBtcevQjKvxPRQIU= +github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -561,6 +563,7 @@ 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/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/common v0.17.0 h1:kDIZLI74SS+3tedSvEkykgBkD7txMxaJAPj8DtJUKYA= github.com/prometheus/common v0.17.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= @@ -861,6 +864,8 @@ golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7w 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/sys v0.0.0-20201214210602-f9fddec55a1e h1:AyodaIpKjppX+cBfTASF2E1US3H2JFBj920Ot3rtDjs= +golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From 3e6fb55e001f37db0e09eba852227f3846d94ccd Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Mon, 22 Feb 2021 14:09:03 +0000 Subject: [PATCH 094/214] merge changelogs (#8661) --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 65d0f352aa04..f438fda06fe7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -66,6 +66,18 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (server) [\#8399](https://github.com/cosmos/cosmos-sdk/pull/8399) fix gRPC-web flag default value * (server) [\#8641](https://github.com/cosmos/cosmos-sdk/pull/8641) Fix Tendermint and application configuration reading from file +## [v0.41.3](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.41.3) - 2021-02-18 + +### Bug Fixes + +* [\#8617](https://github.com/cosmos/cosmos-sdk/pull/8617) Fix build failures caused by a small API breakage introduced in tendermint v0.34.7. + +## [v0.41.2](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.41.2) - 2021-02-18 + +### Improvements + +* Bump tendermint dependency to v0.34.7. + ## [v0.41.1](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.41.1) - 2021-02-17 ### Bug Fixes From c2be53a44733f32f53db3c33029972b86b78575b Mon Sep 17 00:00:00 2001 From: Riccardo Montagnin Date: Mon, 22 Feb 2021 15:21:46 +0100 Subject: [PATCH 095/214] auth: query all accounts stored via gRPC (#8522) * Added the ability to query all accounts stored using gRPC * Added CHANGELOG entry * Fixed linting errors * Update CHANGELOG.md Co-authored-by: Amaury * Update proto/cosmos/auth/v1beta1/query.proto Co-authored-by: Amaury * Run make proto-all * Merged origin/master * Applied suggestions * Added CLI command * Updated CHANGELOG * Fixed merge conflicts Co-authored-by: Amaury Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- CHANGELOG.md | 2 + docs/core/proto-docs.md | 9474 ++++++++++---------- proto/cosmos/auth/v1beta1/query.proto | 21 + proto/cosmos/staking/v1beta1/staking.proto | 50 +- x/auth/client/cli/cli_test.go | 14 + x/auth/client/cli/query.go | 33 + x/auth/keeper/grpc_query.go | 31 + x/auth/keeper/grpc_query_test.go | 58 + x/auth/types/query.pb.go | 535 +- x/auth/types/query.pb.gw.go | 80 + 10 files changed, 5521 insertions(+), 4777 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f438fda06fe7..f06db43e4f37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,8 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements +* (x/auth) [\#8522](https://github.com/cosmos/cosmos-sdk/pull/8522) Allow to query all stored accounts + ### Bug Fixes * (x/evidence) [#8461](https://github.com/cosmos/cosmos-sdk/pull/8461) Fix bech32 prefix in evidence validator address conversion diff --git a/docs/core/proto-docs.md b/docs/core/proto-docs.md index 6e386fbb0729..6cd751f026bb 100644 --- a/docs/core/proto-docs.md +++ b/docs/core/proto-docs.md @@ -4,230 +4,158 @@ ## Table of Contents -- [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/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/query.proto](#ibc/applications/transfer/v1/query.proto) - - [QueryDenomTraceRequest](#ibc.applications.transfer.v1.QueryDenomTraceRequest) - - [QueryDenomTraceResponse](#ibc.applications.transfer.v1.QueryDenomTraceResponse) - - [QueryDenomTracesRequest](#ibc.applications.transfer.v1.QueryDenomTracesRequest) - - [QueryDenomTracesResponse](#ibc.applications.transfer.v1.QueryDenomTracesResponse) - - [QueryParamsRequest](#ibc.applications.transfer.v1.QueryParamsRequest) - - [QueryParamsResponse](#ibc.applications.transfer.v1.QueryParamsResponse) - - - [Query](#ibc.applications.transfer.v1.Query) - -- [ibc/applications/transfer/v1/genesis.proto](#ibc/applications/transfer/v1/genesis.proto) - - [GenesisState](#ibc.applications.transfer.v1.GenesisState) - -- [ibc/core/types/v1/genesis.proto](#ibc/core/types/v1/genesis.proto) - - [GenesisState](#ibc.core.types.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) +- [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) -- [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) +- [cosmos/auth/v1beta1/genesis.proto](#cosmos/auth/v1beta1/genesis.proto) + - [GenesisState](#cosmos.auth.v1beta1.GenesisState) - - [Msg](#ibc.core.client.v1.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) -- [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) +- [cosmos/auth/v1beta1/query.proto](#cosmos/auth/v1beta1/query.proto) + - [QueryAccountRequest](#cosmos.auth.v1beta1.QueryAccountRequest) + - [QueryAccountResponse](#cosmos.auth.v1beta1.QueryAccountResponse) + - [QueryAccountsRequest](#cosmos.auth.v1beta1.QueryAccountsRequest) + - [QueryAccountsResponse](#cosmos.auth.v1beta1.QueryAccountsResponse) + - [QueryParamsRequest](#cosmos.auth.v1beta1.QueryParamsRequest) + - [QueryParamsResponse](#cosmos.auth.v1beta1.QueryParamsResponse) - - [Query](#ibc.core.client.v1.Query) + - [Query](#cosmos.auth.v1beta1.Query) -- [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) +- [cosmos/authz/v1beta1/authz.proto](#cosmos/authz/v1beta1/authz.proto) + - [AuthorizationGrant](#cosmos.authz.v1beta1.AuthorizationGrant) + - [GenericAuthorization](#cosmos.authz.v1beta1.GenericAuthorization) -- [ibc/core/commitment/v1/commitment.proto](#ibc/core/commitment/v1/commitment.proto) - - [MerklePath](#ibc.core.commitment.v1.MerklePath) - - [MerklePrefix](#ibc.core.commitment.v1.MerklePrefix) - - [MerkleProof](#ibc.core.commitment.v1.MerkleProof) - - [MerkleRoot](#ibc.core.commitment.v1.MerkleRoot) +- [cosmos/authz/v1beta1/genesis.proto](#cosmos/authz/v1beta1/genesis.proto) + - [GenesisState](#cosmos.authz.v1beta1.GenesisState) + - [GrantAuthorization](#cosmos.authz.v1beta1.GrantAuthorization) -- [ibc/core/channel/v1/tx.proto](#ibc/core/channel/v1/tx.proto) - - [MsgAcknowledgement](#ibc.core.channel.v1.MsgAcknowledgement) - - [MsgAcknowledgementResponse](#ibc.core.channel.v1.MsgAcknowledgementResponse) - - [MsgChannelCloseConfirm](#ibc.core.channel.v1.MsgChannelCloseConfirm) - - [MsgChannelCloseConfirmResponse](#ibc.core.channel.v1.MsgChannelCloseConfirmResponse) - - [MsgChannelCloseInit](#ibc.core.channel.v1.MsgChannelCloseInit) - - [MsgChannelCloseInitResponse](#ibc.core.channel.v1.MsgChannelCloseInitResponse) - - [MsgChannelOpenAck](#ibc.core.channel.v1.MsgChannelOpenAck) - - [MsgChannelOpenAckResponse](#ibc.core.channel.v1.MsgChannelOpenAckResponse) - - [MsgChannelOpenConfirm](#ibc.core.channel.v1.MsgChannelOpenConfirm) - - [MsgChannelOpenConfirmResponse](#ibc.core.channel.v1.MsgChannelOpenConfirmResponse) - - [MsgChannelOpenInit](#ibc.core.channel.v1.MsgChannelOpenInit) - - [MsgChannelOpenInitResponse](#ibc.core.channel.v1.MsgChannelOpenInitResponse) - - [MsgChannelOpenTry](#ibc.core.channel.v1.MsgChannelOpenTry) - - [MsgChannelOpenTryResponse](#ibc.core.channel.v1.MsgChannelOpenTryResponse) - - [MsgRecvPacket](#ibc.core.channel.v1.MsgRecvPacket) - - [MsgRecvPacketResponse](#ibc.core.channel.v1.MsgRecvPacketResponse) - - [MsgTimeout](#ibc.core.channel.v1.MsgTimeout) - - [MsgTimeoutOnClose](#ibc.core.channel.v1.MsgTimeoutOnClose) - - [MsgTimeoutOnCloseResponse](#ibc.core.channel.v1.MsgTimeoutOnCloseResponse) - - [MsgTimeoutResponse](#ibc.core.channel.v1.MsgTimeoutResponse) +- [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) - - [Msg](#ibc.core.channel.v1.Msg) + - [Query](#cosmos.authz.v1beta1.Query) -- [ibc/core/channel/v1/query.proto](#ibc/core/channel/v1/query.proto) - - [QueryChannelClientStateRequest](#ibc.core.channel.v1.QueryChannelClientStateRequest) - - [QueryChannelClientStateResponse](#ibc.core.channel.v1.QueryChannelClientStateResponse) - - [QueryChannelConsensusStateRequest](#ibc.core.channel.v1.QueryChannelConsensusStateRequest) - - [QueryChannelConsensusStateResponse](#ibc.core.channel.v1.QueryChannelConsensusStateResponse) - - [QueryChannelRequest](#ibc.core.channel.v1.QueryChannelRequest) - - [QueryChannelResponse](#ibc.core.channel.v1.QueryChannelResponse) - - [QueryChannelsRequest](#ibc.core.channel.v1.QueryChannelsRequest) - - [QueryChannelsResponse](#ibc.core.channel.v1.QueryChannelsResponse) - - [QueryConnectionChannelsRequest](#ibc.core.channel.v1.QueryConnectionChannelsRequest) - - [QueryConnectionChannelsResponse](#ibc.core.channel.v1.QueryConnectionChannelsResponse) - - [QueryNextSequenceReceiveRequest](#ibc.core.channel.v1.QueryNextSequenceReceiveRequest) - - [QueryNextSequenceReceiveResponse](#ibc.core.channel.v1.QueryNextSequenceReceiveResponse) - - [QueryPacketAcknowledgementRequest](#ibc.core.channel.v1.QueryPacketAcknowledgementRequest) - - [QueryPacketAcknowledgementResponse](#ibc.core.channel.v1.QueryPacketAcknowledgementResponse) - - [QueryPacketAcknowledgementsRequest](#ibc.core.channel.v1.QueryPacketAcknowledgementsRequest) - - [QueryPacketAcknowledgementsResponse](#ibc.core.channel.v1.QueryPacketAcknowledgementsResponse) - - [QueryPacketCommitmentRequest](#ibc.core.channel.v1.QueryPacketCommitmentRequest) - - [QueryPacketCommitmentResponse](#ibc.core.channel.v1.QueryPacketCommitmentResponse) - - [QueryPacketCommitmentsRequest](#ibc.core.channel.v1.QueryPacketCommitmentsRequest) - - [QueryPacketCommitmentsResponse](#ibc.core.channel.v1.QueryPacketCommitmentsResponse) - - [QueryPacketReceiptRequest](#ibc.core.channel.v1.QueryPacketReceiptRequest) - - [QueryPacketReceiptResponse](#ibc.core.channel.v1.QueryPacketReceiptResponse) - - [QueryUnreceivedAcksRequest](#ibc.core.channel.v1.QueryUnreceivedAcksRequest) - - [QueryUnreceivedAcksResponse](#ibc.core.channel.v1.QueryUnreceivedAcksResponse) - - [QueryUnreceivedPacketsRequest](#ibc.core.channel.v1.QueryUnreceivedPacketsRequest) - - [QueryUnreceivedPacketsResponse](#ibc.core.channel.v1.QueryUnreceivedPacketsResponse) +- [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](#ibc.core.channel.v1.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) -- [ibc/core/channel/v1/genesis.proto](#ibc/core/channel/v1/genesis.proto) - - [GenesisState](#ibc.core.channel.v1.GenesisState) - - [PacketSequence](#ibc.core.channel.v1.PacketSequence) + - [Msg](#cosmos.authz.v1beta1.Msg) -- [ibc/core/channel/v1/channel.proto](#ibc/core/channel/v1/channel.proto) - - [Acknowledgement](#ibc.core.channel.v1.Acknowledgement) - - [Channel](#ibc.core.channel.v1.Channel) - - [Counterparty](#ibc.core.channel.v1.Counterparty) - - [IdentifiedChannel](#ibc.core.channel.v1.IdentifiedChannel) - - [Packet](#ibc.core.channel.v1.Packet) - - [PacketState](#ibc.core.channel.v1.PacketState) +- [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) - - [Order](#ibc.core.channel.v1.Order) - - [State](#ibc.core.channel.v1.State) +- [cosmos/bank/v1beta1/authz.proto](#cosmos/bank/v1beta1/authz.proto) + - [SendAuthorization](#cosmos.bank.v1beta1.SendAuthorization) -- [ibc/core/connection/v1/tx.proto](#ibc/core/connection/v1/tx.proto) - - [MsgConnectionOpenAck](#ibc.core.connection.v1.MsgConnectionOpenAck) - - [MsgConnectionOpenAckResponse](#ibc.core.connection.v1.MsgConnectionOpenAckResponse) - - [MsgConnectionOpenConfirm](#ibc.core.connection.v1.MsgConnectionOpenConfirm) - - [MsgConnectionOpenConfirmResponse](#ibc.core.connection.v1.MsgConnectionOpenConfirmResponse) - - [MsgConnectionOpenInit](#ibc.core.connection.v1.MsgConnectionOpenInit) - - [MsgConnectionOpenInitResponse](#ibc.core.connection.v1.MsgConnectionOpenInitResponse) - - [MsgConnectionOpenTry](#ibc.core.connection.v1.MsgConnectionOpenTry) - - [MsgConnectionOpenTryResponse](#ibc.core.connection.v1.MsgConnectionOpenTryResponse) +- [cosmos/bank/v1beta1/bank.proto](#cosmos/bank/v1beta1/bank.proto) + - [DenomUnit](#cosmos.bank.v1beta1.DenomUnit) + - [Input](#cosmos.bank.v1beta1.Input) + - [Metadata](#cosmos.bank.v1beta1.Metadata) + - [Output](#cosmos.bank.v1beta1.Output) + - [Params](#cosmos.bank.v1beta1.Params) + - [SendEnabled](#cosmos.bank.v1beta1.SendEnabled) + - [Supply](#cosmos.bank.v1beta1.Supply) - - [Msg](#ibc.core.connection.v1.Msg) +- [cosmos/bank/v1beta1/genesis.proto](#cosmos/bank/v1beta1/genesis.proto) + - [Balance](#cosmos.bank.v1beta1.Balance) + - [GenesisState](#cosmos.bank.v1beta1.GenesisState) -- [ibc/core/connection/v1/connection.proto](#ibc/core/connection/v1/connection.proto) - - [ClientPaths](#ibc.core.connection.v1.ClientPaths) - - [ConnectionEnd](#ibc.core.connection.v1.ConnectionEnd) - - [ConnectionPaths](#ibc.core.connection.v1.ConnectionPaths) - - [Counterparty](#ibc.core.connection.v1.Counterparty) - - [IdentifiedConnection](#ibc.core.connection.v1.IdentifiedConnection) - - [Version](#ibc.core.connection.v1.Version) +- [cosmos/bank/v1beta1/query.proto](#cosmos/bank/v1beta1/query.proto) + - [QueryAllBalancesRequest](#cosmos.bank.v1beta1.QueryAllBalancesRequest) + - [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) + - [QuerySupplyOfResponse](#cosmos.bank.v1beta1.QuerySupplyOfResponse) + - [QueryTotalSupplyRequest](#cosmos.bank.v1beta1.QueryTotalSupplyRequest) + - [QueryTotalSupplyResponse](#cosmos.bank.v1beta1.QueryTotalSupplyResponse) - - [State](#ibc.core.connection.v1.State) + - [Query](#cosmos.bank.v1beta1.Query) -- [ibc/core/connection/v1/query.proto](#ibc/core/connection/v1/query.proto) - - [QueryClientConnectionsRequest](#ibc.core.connection.v1.QueryClientConnectionsRequest) - - [QueryClientConnectionsResponse](#ibc.core.connection.v1.QueryClientConnectionsResponse) - - [QueryConnectionClientStateRequest](#ibc.core.connection.v1.QueryConnectionClientStateRequest) - - [QueryConnectionClientStateResponse](#ibc.core.connection.v1.QueryConnectionClientStateResponse) - - [QueryConnectionConsensusStateRequest](#ibc.core.connection.v1.QueryConnectionConsensusStateRequest) - - [QueryConnectionConsensusStateResponse](#ibc.core.connection.v1.QueryConnectionConsensusStateResponse) - - [QueryConnectionRequest](#ibc.core.connection.v1.QueryConnectionRequest) - - [QueryConnectionResponse](#ibc.core.connection.v1.QueryConnectionResponse) - - [QueryConnectionsRequest](#ibc.core.connection.v1.QueryConnectionsRequest) - - [QueryConnectionsResponse](#ibc.core.connection.v1.QueryConnectionsResponse) +- [cosmos/bank/v1beta1/tx.proto](#cosmos/bank/v1beta1/tx.proto) + - [MsgMultiSend](#cosmos.bank.v1beta1.MsgMultiSend) + - [MsgMultiSendResponse](#cosmos.bank.v1beta1.MsgMultiSendResponse) + - [MsgSend](#cosmos.bank.v1beta1.MsgSend) + - [MsgSendResponse](#cosmos.bank.v1beta1.MsgSendResponse) - - [Query](#ibc.core.connection.v1.Query) + - [Msg](#cosmos.bank.v1beta1.Msg) -- [ibc/core/connection/v1/genesis.proto](#ibc/core/connection/v1/genesis.proto) - - [GenesisState](#ibc.core.connection.v1.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) -- [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) +- [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) -- [ibc/lightclients/localhost/v1/localhost.proto](#ibc/lightclients/localhost/v1/localhost.proto) - - [ClientState](#ibc.lightclients.localhost.v1.ClientState) + - [ReflectionService](#cosmos.base.reflection.v1beta1.ReflectionService) -- [ibc/lightclients/solomachine/v1/solomachine.proto](#ibc/lightclients/solomachine/v1/solomachine.proto) - - [ChannelStateData](#ibc.lightclients.solomachine.v1.ChannelStateData) - - [ClientState](#ibc.lightclients.solomachine.v1.ClientState) - - [ClientStateData](#ibc.lightclients.solomachine.v1.ClientStateData) - - [ConnectionStateData](#ibc.lightclients.solomachine.v1.ConnectionStateData) - - [ConsensusState](#ibc.lightclients.solomachine.v1.ConsensusState) - - [ConsensusStateData](#ibc.lightclients.solomachine.v1.ConsensusStateData) - - [Header](#ibc.lightclients.solomachine.v1.Header) - - [HeaderData](#ibc.lightclients.solomachine.v1.HeaderData) - - [Misbehaviour](#ibc.lightclients.solomachine.v1.Misbehaviour) - - [NextSequenceRecvData](#ibc.lightclients.solomachine.v1.NextSequenceRecvData) - - [PacketAcknowledgementData](#ibc.lightclients.solomachine.v1.PacketAcknowledgementData) - - [PacketCommitmentData](#ibc.lightclients.solomachine.v1.PacketCommitmentData) - - [PacketReceiptAbsenceData](#ibc.lightclients.solomachine.v1.PacketReceiptAbsenceData) - - [SignBytes](#ibc.lightclients.solomachine.v1.SignBytes) - - [SignatureAndData](#ibc.lightclients.solomachine.v1.SignatureAndData) - - [TimestampedSignatureData](#ibc.lightclients.solomachine.v1.TimestampedSignatureData) +- [cosmos/base/snapshots/v1beta1/snapshot.proto](#cosmos/base/snapshots/v1beta1/snapshot.proto) + - [Metadata](#cosmos.base.snapshots.v1beta1.Metadata) + - [Snapshot](#cosmos.base.snapshots.v1beta1.Snapshot) - - [DataType](#ibc.lightclients.solomachine.v1.DataType) +- [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/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/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/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/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) - - [Query](#cosmos.upgrade.v1beta1.Query) + - [Service](#cosmos.base.tendermint.v1beta1.Service) - [cosmos/capability/v1beta1/capability.proto](#cosmos/capability/v1beta1/capability.proto) - [Capability](#cosmos.capability.v1beta1.Capability) @@ -238,111 +166,244 @@ - [GenesisOwners](#cosmos.capability.v1beta1.GenesisOwners) - [GenesisState](#cosmos.capability.v1beta1.GenesisState) -- [cosmos/params/v1beta1/params.proto](#cosmos/params/v1beta1/params.proto) - - [ParamChange](#cosmos.params.v1beta1.ParamChange) - - [ParameterChangeProposal](#cosmos.params.v1beta1.ParameterChangeProposal) +- [cosmos/crisis/v1beta1/genesis.proto](#cosmos/crisis/v1beta1/genesis.proto) + - [GenesisState](#cosmos.crisis.v1beta1.GenesisState) -- [cosmos/params/v1beta1/query.proto](#cosmos/params/v1beta1/query.proto) - - [QueryParamsRequest](#cosmos.params.v1beta1.QueryParamsRequest) - - [QueryParamsResponse](#cosmos.params.v1beta1.QueryParamsResponse) +- [cosmos/crisis/v1beta1/tx.proto](#cosmos/crisis/v1beta1/tx.proto) + - [MsgVerifyInvariant](#cosmos.crisis.v1beta1.MsgVerifyInvariant) + - [MsgVerifyInvariantResponse](#cosmos.crisis.v1beta1.MsgVerifyInvariantResponse) - - [Query](#cosmos.params.v1beta1.Query) + - [Msg](#cosmos.crisis.v1beta1.Msg) -- [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/crypto/ed25519/keys.proto](#cosmos/crypto/ed25519/keys.proto) + - [PrivKey](#cosmos.crypto.ed25519.PrivKey) + - [PubKey](#cosmos.crypto.ed25519.PubKey) - - [Msg](#cosmos.authz.v1beta1.Msg) +- [cosmos/crypto/multisig/keys.proto](#cosmos/crypto/multisig/keys.proto) + - [LegacyAminoPubKey](#cosmos.crypto.multisig.LegacyAminoPubKey) -- [cosmos/authz/v1beta1/authz.proto](#cosmos/authz/v1beta1/authz.proto) - - [AuthorizationGrant](#cosmos.authz.v1beta1.AuthorizationGrant) - - [GenericAuthorization](#cosmos.authz.v1beta1.GenericAuthorization) +- [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/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) + - [QueryCommunityPoolResponse](#cosmos.distribution.v1beta1.QueryCommunityPoolResponse) + - [QueryDelegationRewardsRequest](#cosmos.distribution.v1beta1.QueryDelegationRewardsRequest) + - [QueryDelegationRewardsResponse](#cosmos.distribution.v1beta1.QueryDelegationRewardsResponse) + - [QueryDelegationTotalRewardsRequest](#cosmos.distribution.v1beta1.QueryDelegationTotalRewardsRequest) + - [QueryDelegationTotalRewardsResponse](#cosmos.distribution.v1beta1.QueryDelegationTotalRewardsResponse) + - [QueryDelegatorValidatorsRequest](#cosmos.distribution.v1beta1.QueryDelegatorValidatorsRequest) + - [QueryDelegatorValidatorsResponse](#cosmos.distribution.v1beta1.QueryDelegatorValidatorsResponse) + - [QueryDelegatorWithdrawAddressRequest](#cosmos.distribution.v1beta1.QueryDelegatorWithdrawAddressRequest) + - [QueryDelegatorWithdrawAddressResponse](#cosmos.distribution.v1beta1.QueryDelegatorWithdrawAddressResponse) + - [QueryParamsRequest](#cosmos.distribution.v1beta1.QueryParamsRequest) + - [QueryParamsResponse](#cosmos.distribution.v1beta1.QueryParamsResponse) + - [QueryValidatorCommissionRequest](#cosmos.distribution.v1beta1.QueryValidatorCommissionRequest) + - [QueryValidatorCommissionResponse](#cosmos.distribution.v1beta1.QueryValidatorCommissionResponse) + - [QueryValidatorOutstandingRewardsRequest](#cosmos.distribution.v1beta1.QueryValidatorOutstandingRewardsRequest) + - [QueryValidatorOutstandingRewardsResponse](#cosmos.distribution.v1beta1.QueryValidatorOutstandingRewardsResponse) + - [QueryValidatorSlashesRequest](#cosmos.distribution.v1beta1.QueryValidatorSlashesRequest) + - [QueryValidatorSlashesResponse](#cosmos.distribution.v1beta1.QueryValidatorSlashesResponse) + + - [Query](#cosmos.distribution.v1beta1.Query) + +- [cosmos/distribution/v1beta1/tx.proto](#cosmos/distribution/v1beta1/tx.proto) + - [MsgFundCommunityPool](#cosmos.distribution.v1beta1.MsgFundCommunityPool) + - [MsgFundCommunityPoolResponse](#cosmos.distribution.v1beta1.MsgFundCommunityPoolResponse) + - [MsgSetWithdrawAddress](#cosmos.distribution.v1beta1.MsgSetWithdrawAddress) + - [MsgSetWithdrawAddressResponse](#cosmos.distribution.v1beta1.MsgSetWithdrawAddressResponse) + - [MsgWithdrawDelegatorReward](#cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward) + - [MsgWithdrawDelegatorRewardResponse](#cosmos.distribution.v1beta1.MsgWithdrawDelegatorRewardResponse) + - [MsgWithdrawValidatorCommission](#cosmos.distribution.v1beta1.MsgWithdrawValidatorCommission) + - [MsgWithdrawValidatorCommissionResponse](#cosmos.distribution.v1beta1.MsgWithdrawValidatorCommissionResponse) + + - [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/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/genesis.proto](#cosmos/feegrant/v1beta1/genesis.proto) + - [GenesisState](#cosmos.feegrant.v1beta1.GenesisState) + +- [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/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) + - [WeightedVoteOption](#cosmos.gov.v1beta1.WeightedVoteOption) + + - [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/authz/v1beta1/genesis.proto](#cosmos/authz/v1beta1/genesis.proto) - - [GenesisState](#cosmos.authz.v1beta1.GenesisState) - - [GrantAuthorization](#cosmos.authz.v1beta1.GrantAuthorization) +- [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) + - [MsgVoteWeighted](#cosmos.gov.v1beta1.MsgVoteWeighted) + - [MsgVoteWeightedResponse](#cosmos.gov.v1beta1.MsgVoteWeightedResponse) -- [cosmos/evidence/v1beta1/tx.proto](#cosmos/evidence/v1beta1/tx.proto) - - [MsgSubmitEvidence](#cosmos.evidence.v1beta1.MsgSubmitEvidence) - - [MsgSubmitEvidenceResponse](#cosmos.evidence.v1beta1.MsgSubmitEvidenceResponse) + - [Msg](#cosmos.gov.v1beta1.Msg) - - [Msg](#cosmos.evidence.v1beta1.Msg) +- [cosmos/mint/v1beta1/mint.proto](#cosmos/mint/v1beta1/mint.proto) + - [Minter](#cosmos.mint.v1beta1.Minter) + - [Params](#cosmos.mint.v1beta1.Params) -- [cosmos/evidence/v1beta1/evidence.proto](#cosmos/evidence/v1beta1/evidence.proto) - - [Equivocation](#cosmos.evidence.v1beta1.Equivocation) +- [cosmos/mint/v1beta1/genesis.proto](#cosmos/mint/v1beta1/genesis.proto) + - [GenesisState](#cosmos.mint.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) +- [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.evidence.v1beta1.Query) + - [Query](#cosmos.mint.v1beta1.Query) -- [cosmos/evidence/v1beta1/genesis.proto](#cosmos/evidence/v1beta1/genesis.proto) - - [GenesisState](#cosmos.evidence.v1beta1.GenesisState) +- [cosmos/params/v1beta1/params.proto](#cosmos/params/v1beta1/params.proto) + - [ParamChange](#cosmos.params.v1beta1.ParamChange) + - [ParameterChangeProposal](#cosmos.params.v1beta1.ParameterChangeProposal) -- [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/params/v1beta1/query.proto](#cosmos/params/v1beta1/query.proto) + - [QueryParamsRequest](#cosmos.params.v1beta1.QueryParamsRequest) + - [QueryParamsResponse](#cosmos.params.v1beta1.QueryParamsResponse) -- [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) + - [Query](#cosmos.params.v1beta1.Query) - - [BroadcastMode](#cosmos.tx.v1beta1.BroadcastMode) +- [cosmos/slashing/v1beta1/slashing.proto](#cosmos/slashing/v1beta1/slashing.proto) + - [Params](#cosmos.slashing.v1beta1.Params) + - [ValidatorSigningInfo](#cosmos.slashing.v1beta1.ValidatorSigningInfo) - - [Service](#cosmos.tx.v1beta1.Service) +- [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/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/slashing/v1beta1/query.proto](#cosmos/slashing/v1beta1/query.proto) + - [QueryParamsRequest](#cosmos.slashing.v1beta1.QueryParamsRequest) + - [QueryParamsResponse](#cosmos.slashing.v1beta1.QueryParamsResponse) + - [QuerySigningInfoRequest](#cosmos.slashing.v1beta1.QuerySigningInfoRequest) + - [QuerySigningInfoResponse](#cosmos.slashing.v1beta1.QuerySigningInfoResponse) + - [QuerySigningInfosRequest](#cosmos.slashing.v1beta1.QuerySigningInfosRequest) + - [QuerySigningInfosResponse](#cosmos.slashing.v1beta1.QuerySigningInfosResponse) - - [SignMode](#cosmos.tx.signing.v1beta1.SignMode) + - [Query](#cosmos.slashing.v1beta1.Query) -- [cosmos/crypto/multisig/keys.proto](#cosmos/crypto/multisig/keys.proto) - - [LegacyAminoPubKey](#cosmos.crypto.multisig.LegacyAminoPubKey) +- [cosmos/slashing/v1beta1/tx.proto](#cosmos/slashing/v1beta1/tx.proto) + - [MsgUnjail](#cosmos.slashing.v1beta1.MsgUnjail) + - [MsgUnjailResponse](#cosmos.slashing.v1beta1.MsgUnjailResponse) -- [cosmos/crypto/multisig/v1beta1/multisig.proto](#cosmos/crypto/multisig/v1beta1/multisig.proto) - - [CompactBitArray](#cosmos.crypto.multisig.v1beta1.CompactBitArray) - - [MultiSignature](#cosmos.crypto.multisig.v1beta1.MultiSignature) + - [Msg](#cosmos.slashing.v1beta1.Msg) -- [cosmos/crypto/secp256k1/keys.proto](#cosmos/crypto/secp256k1/keys.proto) - - [PrivKey](#cosmos.crypto.secp256k1.PrivKey) - - [PubKey](#cosmos.crypto.secp256k1.PubKey) +- [cosmos/staking/v1beta1/authz.proto](#cosmos/staking/v1beta1/authz.proto) + - [StakeAuthorization](#cosmos.staking.v1beta1.StakeAuthorization) + - [StakeAuthorization.Validators](#cosmos.staking.v1beta1.StakeAuthorization.Validators) -- [cosmos/crypto/ed25519/keys.proto](#cosmos/crypto/ed25519/keys.proto) - - [PrivKey](#cosmos.crypto.ed25519.PrivKey) - - [PubKey](#cosmos.crypto.ed25519.PubKey) + - [AuthorizationType](#cosmos.staking.v1beta1.AuthorizationType) - [cosmos/staking/v1beta1/staking.proto](#cosmos/staking/v1beta1/staking.proto) - [Commission](#cosmos.staking.v1beta1.Commission) @@ -368,25 +429,9 @@ - [BondStatus](#cosmos.staking.v1beta1.BondStatus) -- [cosmos/staking/v1beta1/tx.proto](#cosmos/staking/v1beta1/tx.proto) - - [MsgBeginRedelegate](#cosmos.staking.v1beta1.MsgBeginRedelegate) - - [MsgBeginRedelegateResponse](#cosmos.staking.v1beta1.MsgBeginRedelegateResponse) - - [MsgCreateValidator](#cosmos.staking.v1beta1.MsgCreateValidator) - - [MsgCreateValidatorResponse](#cosmos.staking.v1beta1.MsgCreateValidatorResponse) - - [MsgDelegate](#cosmos.staking.v1beta1.MsgDelegate) - - [MsgDelegateResponse](#cosmos.staking.v1beta1.MsgDelegateResponse) - - [MsgEditValidator](#cosmos.staking.v1beta1.MsgEditValidator) - - [MsgEditValidatorResponse](#cosmos.staking.v1beta1.MsgEditValidatorResponse) - - [MsgUndelegate](#cosmos.staking.v1beta1.MsgUndelegate) - - [MsgUndelegateResponse](#cosmos.staking.v1beta1.MsgUndelegateResponse) - - - [Msg](#cosmos.staking.v1beta1.Msg) - -- [cosmos/staking/v1beta1/authz.proto](#cosmos/staking/v1beta1/authz.proto) - - [StakeAuthorization](#cosmos.staking.v1beta1.StakeAuthorization) - - [StakeAuthorization.Validators](#cosmos.staking.v1beta1.StakeAuthorization.Validators) - - - [AuthorizationType](#cosmos.staking.v1beta1.AuthorizationType) +- [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) @@ -420,397 +465,354 @@ - [Query](#cosmos.staking.v1beta1.Query) -- [cosmos/staking/v1beta1/genesis.proto](#cosmos/staking/v1beta1/genesis.proto) - - [GenesisState](#cosmos.staking.v1beta1.GenesisState) - - [LastValidatorPower](#cosmos.staking.v1beta1.LastValidatorPower) - -- [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) - -- [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/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/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) - - - [Service](#cosmos.base.tendermint.v1beta1.Service) - -- [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/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/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/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/tx.proto](#cosmos/bank/v1beta1/tx.proto) - - [MsgMultiSend](#cosmos.bank.v1beta1.MsgMultiSend) - - [MsgMultiSendResponse](#cosmos.bank.v1beta1.MsgMultiSendResponse) - - [MsgSend](#cosmos.bank.v1beta1.MsgSend) - - [MsgSendResponse](#cosmos.bank.v1beta1.MsgSendResponse) - - - [Msg](#cosmos.bank.v1beta1.Msg) - -- [cosmos/bank/v1beta1/authz.proto](#cosmos/bank/v1beta1/authz.proto) - - [SendAuthorization](#cosmos.bank.v1beta1.SendAuthorization) +- [cosmos/staking/v1beta1/tx.proto](#cosmos/staking/v1beta1/tx.proto) + - [MsgBeginRedelegate](#cosmos.staking.v1beta1.MsgBeginRedelegate) + - [MsgBeginRedelegateResponse](#cosmos.staking.v1beta1.MsgBeginRedelegateResponse) + - [MsgCreateValidator](#cosmos.staking.v1beta1.MsgCreateValidator) + - [MsgCreateValidatorResponse](#cosmos.staking.v1beta1.MsgCreateValidatorResponse) + - [MsgDelegate](#cosmos.staking.v1beta1.MsgDelegate) + - [MsgDelegateResponse](#cosmos.staking.v1beta1.MsgDelegateResponse) + - [MsgEditValidator](#cosmos.staking.v1beta1.MsgEditValidator) + - [MsgEditValidatorResponse](#cosmos.staking.v1beta1.MsgEditValidatorResponse) + - [MsgUndelegate](#cosmos.staking.v1beta1.MsgUndelegate) + - [MsgUndelegateResponse](#cosmos.staking.v1beta1.MsgUndelegateResponse) -- [cosmos/bank/v1beta1/query.proto](#cosmos/bank/v1beta1/query.proto) - - [QueryAllBalancesRequest](#cosmos.bank.v1beta1.QueryAllBalancesRequest) - - [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) - - [QuerySupplyOfResponse](#cosmos.bank.v1beta1.QuerySupplyOfResponse) - - [QueryTotalSupplyRequest](#cosmos.bank.v1beta1.QueryTotalSupplyRequest) - - [QueryTotalSupplyResponse](#cosmos.bank.v1beta1.QueryTotalSupplyResponse) + - [Msg](#cosmos.staking.v1beta1.Msg) - - [Query](#cosmos.bank.v1beta1.Query) +- [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/bank/v1beta1/bank.proto](#cosmos/bank/v1beta1/bank.proto) - - [DenomUnit](#cosmos.bank.v1beta1.DenomUnit) - - [Input](#cosmos.bank.v1beta1.Input) - - [Metadata](#cosmos.bank.v1beta1.Metadata) - - [Output](#cosmos.bank.v1beta1.Output) - - [Params](#cosmos.bank.v1beta1.Params) - - [SendEnabled](#cosmos.bank.v1beta1.SendEnabled) - - [Supply](#cosmos.bank.v1beta1.Supply) + - [SignMode](#cosmos.tx.signing.v1beta1.SignMode) -- [cosmos/bank/v1beta1/genesis.proto](#cosmos/bank/v1beta1/genesis.proto) - - [Balance](#cosmos.bank.v1beta1.Balance) - - [GenesisState](#cosmos.bank.v1beta1.GenesisState) +- [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/genutil/v1beta1/genesis.proto](#cosmos/genutil/v1beta1/genesis.proto) - - [GenesisState](#cosmos.genutil.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/slashing/v1beta1/slashing.proto](#cosmos/slashing/v1beta1/slashing.proto) - - [Params](#cosmos.slashing.v1beta1.Params) - - [ValidatorSigningInfo](#cosmos.slashing.v1beta1.ValidatorSigningInfo) + - [BroadcastMode](#cosmos.tx.v1beta1.BroadcastMode) -- [cosmos/slashing/v1beta1/tx.proto](#cosmos/slashing/v1beta1/tx.proto) - - [MsgUnjail](#cosmos.slashing.v1beta1.MsgUnjail) - - [MsgUnjailResponse](#cosmos.slashing.v1beta1.MsgUnjailResponse) + - [Service](#cosmos.tx.v1beta1.Service) - - [Msg](#cosmos.slashing.v1beta1.Msg) +- [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/slashing/v1beta1/query.proto](#cosmos/slashing/v1beta1/query.proto) - - [QueryParamsRequest](#cosmos.slashing.v1beta1.QueryParamsRequest) - - [QueryParamsResponse](#cosmos.slashing.v1beta1.QueryParamsResponse) - - [QuerySigningInfoRequest](#cosmos.slashing.v1beta1.QuerySigningInfoRequest) - - [QuerySigningInfoResponse](#cosmos.slashing.v1beta1.QuerySigningInfoResponse) - - [QuerySigningInfosRequest](#cosmos.slashing.v1beta1.QuerySigningInfosRequest) - - [QuerySigningInfosResponse](#cosmos.slashing.v1beta1.QuerySigningInfosResponse) +- [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.slashing.v1beta1.Query) + - [Query](#cosmos.upgrade.v1beta1.Query) -- [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/vesting/v1beta1/tx.proto](#cosmos/vesting/v1beta1/tx.proto) + - [MsgCreateVestingAccount](#cosmos.vesting.v1beta1.MsgCreateVestingAccount) + - [MsgCreateVestingAccountResponse](#cosmos.vesting.v1beta1.MsgCreateVestingAccountResponse) -- [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.vesting.v1beta1.Msg) - - [Msg](#cosmos.feegrant.v1beta1.Msg) +- [cosmos/vesting/v1beta1/vesting.proto](#cosmos/vesting/v1beta1/vesting.proto) + - [BaseVestingAccount](#cosmos.vesting.v1beta1.BaseVestingAccount) + - [ContinuousVestingAccount](#cosmos.vesting.v1beta1.ContinuousVestingAccount) + - [DelayedVestingAccount](#cosmos.vesting.v1beta1.DelayedVestingAccount) + - [Period](#cosmos.vesting.v1beta1.Period) + - [PeriodicVestingAccount](#cosmos.vesting.v1beta1.PeriodicVestingAccount) -- [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) +- [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/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) +- [ibc/applications/transfer/v1/genesis.proto](#ibc/applications/transfer/v1/genesis.proto) + - [GenesisState](#ibc.applications.transfer.v1.GenesisState) - - [Query](#cosmos.feegrant.v1beta1.Query) +- [ibc/applications/transfer/v1/query.proto](#ibc/applications/transfer/v1/query.proto) + - [QueryDenomTraceRequest](#ibc.applications.transfer.v1.QueryDenomTraceRequest) + - [QueryDenomTraceResponse](#ibc.applications.transfer.v1.QueryDenomTraceResponse) + - [QueryDenomTracesRequest](#ibc.applications.transfer.v1.QueryDenomTracesRequest) + - [QueryDenomTracesResponse](#ibc.applications.transfer.v1.QueryDenomTracesResponse) + - [QueryParamsRequest](#ibc.applications.transfer.v1.QueryParamsRequest) + - [QueryParamsResponse](#ibc.applications.transfer.v1.QueryParamsResponse) -- [cosmos/feegrant/v1beta1/genesis.proto](#cosmos/feegrant/v1beta1/genesis.proto) - - [GenesisState](#cosmos.feegrant.v1beta1.GenesisState) + - [Query](#ibc.applications.transfer.v1.Query) -- [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) +- [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) -- [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) +- [ibc/applications/transfer/v1/tx.proto](#ibc/applications/transfer/v1/tx.proto) + - [MsgTransfer](#ibc.applications.transfer.v1.MsgTransfer) + - [MsgTransferResponse](#ibc.applications.transfer.v1.MsgTransferResponse) - - [Query](#cosmos.auth.v1beta1.Query) + - [Msg](#ibc.applications.transfer.v1.Msg) -- [cosmos/auth/v1beta1/genesis.proto](#cosmos/auth/v1beta1/genesis.proto) - - [GenesisState](#cosmos.auth.v1beta1.GenesisState) +- [ibc/core/channel/v1/channel.proto](#ibc/core/channel/v1/channel.proto) + - [Acknowledgement](#ibc.core.channel.v1.Acknowledgement) + - [Channel](#ibc.core.channel.v1.Channel) + - [Counterparty](#ibc.core.channel.v1.Counterparty) + - [IdentifiedChannel](#ibc.core.channel.v1.IdentifiedChannel) + - [Packet](#ibc.core.channel.v1.Packet) + - [PacketState](#ibc.core.channel.v1.PacketState) -- [cosmos/crisis/v1beta1/tx.proto](#cosmos/crisis/v1beta1/tx.proto) - - [MsgVerifyInvariant](#cosmos.crisis.v1beta1.MsgVerifyInvariant) - - [MsgVerifyInvariantResponse](#cosmos.crisis.v1beta1.MsgVerifyInvariantResponse) + - [Order](#ibc.core.channel.v1.Order) + - [State](#ibc.core.channel.v1.State) - - [Msg](#cosmos.crisis.v1beta1.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) -- [cosmos/crisis/v1beta1/genesis.proto](#cosmos/crisis/v1beta1/genesis.proto) - - [GenesisState](#cosmos.crisis.v1beta1.GenesisState) +- [ibc/core/channel/v1/query.proto](#ibc/core/channel/v1/query.proto) + - [QueryChannelClientStateRequest](#ibc.core.channel.v1.QueryChannelClientStateRequest) + - [QueryChannelClientStateResponse](#ibc.core.channel.v1.QueryChannelClientStateResponse) + - [QueryChannelConsensusStateRequest](#ibc.core.channel.v1.QueryChannelConsensusStateRequest) + - [QueryChannelConsensusStateResponse](#ibc.core.channel.v1.QueryChannelConsensusStateResponse) + - [QueryChannelRequest](#ibc.core.channel.v1.QueryChannelRequest) + - [QueryChannelResponse](#ibc.core.channel.v1.QueryChannelResponse) + - [QueryChannelsRequest](#ibc.core.channel.v1.QueryChannelsRequest) + - [QueryChannelsResponse](#ibc.core.channel.v1.QueryChannelsResponse) + - [QueryConnectionChannelsRequest](#ibc.core.channel.v1.QueryConnectionChannelsRequest) + - [QueryConnectionChannelsResponse](#ibc.core.channel.v1.QueryConnectionChannelsResponse) + - [QueryNextSequenceReceiveRequest](#ibc.core.channel.v1.QueryNextSequenceReceiveRequest) + - [QueryNextSequenceReceiveResponse](#ibc.core.channel.v1.QueryNextSequenceReceiveResponse) + - [QueryPacketAcknowledgementRequest](#ibc.core.channel.v1.QueryPacketAcknowledgementRequest) + - [QueryPacketAcknowledgementResponse](#ibc.core.channel.v1.QueryPacketAcknowledgementResponse) + - [QueryPacketAcknowledgementsRequest](#ibc.core.channel.v1.QueryPacketAcknowledgementsRequest) + - [QueryPacketAcknowledgementsResponse](#ibc.core.channel.v1.QueryPacketAcknowledgementsResponse) + - [QueryPacketCommitmentRequest](#ibc.core.channel.v1.QueryPacketCommitmentRequest) + - [QueryPacketCommitmentResponse](#ibc.core.channel.v1.QueryPacketCommitmentResponse) + - [QueryPacketCommitmentsRequest](#ibc.core.channel.v1.QueryPacketCommitmentsRequest) + - [QueryPacketCommitmentsResponse](#ibc.core.channel.v1.QueryPacketCommitmentsResponse) + - [QueryPacketReceiptRequest](#ibc.core.channel.v1.QueryPacketReceiptRequest) + - [QueryPacketReceiptResponse](#ibc.core.channel.v1.QueryPacketReceiptResponse) + - [QueryUnreceivedAcksRequest](#ibc.core.channel.v1.QueryUnreceivedAcksRequest) + - [QueryUnreceivedAcksResponse](#ibc.core.channel.v1.QueryUnreceivedAcksResponse) + - [QueryUnreceivedPacketsRequest](#ibc.core.channel.v1.QueryUnreceivedPacketsRequest) + - [QueryUnreceivedPacketsResponse](#ibc.core.channel.v1.QueryUnreceivedPacketsResponse) -- [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) - - [WeightedVoteOption](#cosmos.gov.v1beta1.WeightedVoteOption) + - [Query](#ibc.core.channel.v1.Query) - - [ProposalStatus](#cosmos.gov.v1beta1.ProposalStatus) - - [VoteOption](#cosmos.gov.v1beta1.VoteOption) +- [ibc/core/channel/v1/tx.proto](#ibc/core/channel/v1/tx.proto) + - [MsgAcknowledgement](#ibc.core.channel.v1.MsgAcknowledgement) + - [MsgAcknowledgementResponse](#ibc.core.channel.v1.MsgAcknowledgementResponse) + - [MsgChannelCloseConfirm](#ibc.core.channel.v1.MsgChannelCloseConfirm) + - [MsgChannelCloseConfirmResponse](#ibc.core.channel.v1.MsgChannelCloseConfirmResponse) + - [MsgChannelCloseInit](#ibc.core.channel.v1.MsgChannelCloseInit) + - [MsgChannelCloseInitResponse](#ibc.core.channel.v1.MsgChannelCloseInitResponse) + - [MsgChannelOpenAck](#ibc.core.channel.v1.MsgChannelOpenAck) + - [MsgChannelOpenAckResponse](#ibc.core.channel.v1.MsgChannelOpenAckResponse) + - [MsgChannelOpenConfirm](#ibc.core.channel.v1.MsgChannelOpenConfirm) + - [MsgChannelOpenConfirmResponse](#ibc.core.channel.v1.MsgChannelOpenConfirmResponse) + - [MsgChannelOpenInit](#ibc.core.channel.v1.MsgChannelOpenInit) + - [MsgChannelOpenInitResponse](#ibc.core.channel.v1.MsgChannelOpenInitResponse) + - [MsgChannelOpenTry](#ibc.core.channel.v1.MsgChannelOpenTry) + - [MsgChannelOpenTryResponse](#ibc.core.channel.v1.MsgChannelOpenTryResponse) + - [MsgRecvPacket](#ibc.core.channel.v1.MsgRecvPacket) + - [MsgRecvPacketResponse](#ibc.core.channel.v1.MsgRecvPacketResponse) + - [MsgTimeout](#ibc.core.channel.v1.MsgTimeout) + - [MsgTimeoutOnClose](#ibc.core.channel.v1.MsgTimeoutOnClose) + - [MsgTimeoutOnCloseResponse](#ibc.core.channel.v1.MsgTimeoutOnCloseResponse) + - [MsgTimeoutResponse](#ibc.core.channel.v1.MsgTimeoutResponse) -- [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) - - [MsgVoteWeighted](#cosmos.gov.v1beta1.MsgVoteWeighted) - - [MsgVoteWeightedResponse](#cosmos.gov.v1beta1.MsgVoteWeightedResponse) + - [Msg](#ibc.core.channel.v1.Msg) - - [Msg](#cosmos.gov.v1beta1.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) -- [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) +- [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](#cosmos.gov.v1beta1.Query) + - [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) -- [cosmos/gov/v1beta1/genesis.proto](#cosmos/gov/v1beta1/genesis.proto) - - [GenesisState](#cosmos.gov.v1beta1.GenesisState) + - [Msg](#ibc.core.client.v1.Msg) -- [cosmos/mint/v1beta1/mint.proto](#cosmos/mint/v1beta1/mint.proto) - - [Minter](#cosmos.mint.v1beta1.Minter) - - [Params](#cosmos.mint.v1beta1.Params) +- [ibc/core/commitment/v1/commitment.proto](#ibc/core/commitment/v1/commitment.proto) + - [MerklePath](#ibc.core.commitment.v1.MerklePath) + - [MerklePrefix](#ibc.core.commitment.v1.MerklePrefix) + - [MerkleProof](#ibc.core.commitment.v1.MerkleProof) + - [MerkleRoot](#ibc.core.commitment.v1.MerkleRoot) -- [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) +- [ibc/core/connection/v1/connection.proto](#ibc/core/connection/v1/connection.proto) + - [ClientPaths](#ibc.core.connection.v1.ClientPaths) + - [ConnectionEnd](#ibc.core.connection.v1.ConnectionEnd) + - [ConnectionPaths](#ibc.core.connection.v1.ConnectionPaths) + - [Counterparty](#ibc.core.connection.v1.Counterparty) + - [IdentifiedConnection](#ibc.core.connection.v1.IdentifiedConnection) + - [Version](#ibc.core.connection.v1.Version) - - [Query](#cosmos.mint.v1beta1.Query) + - [State](#ibc.core.connection.v1.State) -- [cosmos/mint/v1beta1/genesis.proto](#cosmos/mint/v1beta1/genesis.proto) - - [GenesisState](#cosmos.mint.v1beta1.GenesisState) +- [ibc/core/connection/v1/genesis.proto](#ibc/core/connection/v1/genesis.proto) + - [GenesisState](#ibc.core.connection.v1.GenesisState) -- [cosmos/vesting/v1beta1/tx.proto](#cosmos/vesting/v1beta1/tx.proto) - - [MsgCreateVestingAccount](#cosmos.vesting.v1beta1.MsgCreateVestingAccount) - - [MsgCreateVestingAccountResponse](#cosmos.vesting.v1beta1.MsgCreateVestingAccountResponse) +- [ibc/core/connection/v1/query.proto](#ibc/core/connection/v1/query.proto) + - [QueryClientConnectionsRequest](#ibc.core.connection.v1.QueryClientConnectionsRequest) + - [QueryClientConnectionsResponse](#ibc.core.connection.v1.QueryClientConnectionsResponse) + - [QueryConnectionClientStateRequest](#ibc.core.connection.v1.QueryConnectionClientStateRequest) + - [QueryConnectionClientStateResponse](#ibc.core.connection.v1.QueryConnectionClientStateResponse) + - [QueryConnectionConsensusStateRequest](#ibc.core.connection.v1.QueryConnectionConsensusStateRequest) + - [QueryConnectionConsensusStateResponse](#ibc.core.connection.v1.QueryConnectionConsensusStateResponse) + - [QueryConnectionRequest](#ibc.core.connection.v1.QueryConnectionRequest) + - [QueryConnectionResponse](#ibc.core.connection.v1.QueryConnectionResponse) + - [QueryConnectionsRequest](#ibc.core.connection.v1.QueryConnectionsRequest) + - [QueryConnectionsResponse](#ibc.core.connection.v1.QueryConnectionsResponse) - - [Msg](#cosmos.vesting.v1beta1.Msg) + - [Query](#ibc.core.connection.v1.Query) -- [cosmos/vesting/v1beta1/vesting.proto](#cosmos/vesting/v1beta1/vesting.proto) - - [BaseVestingAccount](#cosmos.vesting.v1beta1.BaseVestingAccount) - - [ContinuousVestingAccount](#cosmos.vesting.v1beta1.ContinuousVestingAccount) - - [DelayedVestingAccount](#cosmos.vesting.v1beta1.DelayedVestingAccount) - - [Period](#cosmos.vesting.v1beta1.Period) - - [PeriodicVestingAccount](#cosmos.vesting.v1beta1.PeriodicVestingAccount) +- [ibc/core/connection/v1/tx.proto](#ibc/core/connection/v1/tx.proto) + - [MsgConnectionOpenAck](#ibc.core.connection.v1.MsgConnectionOpenAck) + - [MsgConnectionOpenAckResponse](#ibc.core.connection.v1.MsgConnectionOpenAckResponse) + - [MsgConnectionOpenConfirm](#ibc.core.connection.v1.MsgConnectionOpenConfirm) + - [MsgConnectionOpenConfirmResponse](#ibc.core.connection.v1.MsgConnectionOpenConfirmResponse) + - [MsgConnectionOpenInit](#ibc.core.connection.v1.MsgConnectionOpenInit) + - [MsgConnectionOpenInitResponse](#ibc.core.connection.v1.MsgConnectionOpenInitResponse) + - [MsgConnectionOpenTry](#ibc.core.connection.v1.MsgConnectionOpenTry) + - [MsgConnectionOpenTryResponse](#ibc.core.connection.v1.MsgConnectionOpenTryResponse) -- [cosmos/distribution/v1beta1/tx.proto](#cosmos/distribution/v1beta1/tx.proto) - - [MsgFundCommunityPool](#cosmos.distribution.v1beta1.MsgFundCommunityPool) - - [MsgFundCommunityPoolResponse](#cosmos.distribution.v1beta1.MsgFundCommunityPoolResponse) - - [MsgSetWithdrawAddress](#cosmos.distribution.v1beta1.MsgSetWithdrawAddress) - - [MsgSetWithdrawAddressResponse](#cosmos.distribution.v1beta1.MsgSetWithdrawAddressResponse) - - [MsgWithdrawDelegatorReward](#cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward) - - [MsgWithdrawDelegatorRewardResponse](#cosmos.distribution.v1beta1.MsgWithdrawDelegatorRewardResponse) - - [MsgWithdrawValidatorCommission](#cosmos.distribution.v1beta1.MsgWithdrawValidatorCommission) - - [MsgWithdrawValidatorCommissionResponse](#cosmos.distribution.v1beta1.MsgWithdrawValidatorCommissionResponse) + - [Msg](#ibc.core.connection.v1.Msg) - - [Msg](#cosmos.distribution.v1beta1.Msg) +- [ibc/core/types/v1/genesis.proto](#ibc/core/types/v1/genesis.proto) + - [GenesisState](#ibc.core.types.v1.GenesisState) -- [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) +- [ibc/lightclients/localhost/v1/localhost.proto](#ibc/lightclients/localhost/v1/localhost.proto) + - [ClientState](#ibc.lightclients.localhost.v1.ClientState) -- [cosmos/distribution/v1beta1/query.proto](#cosmos/distribution/v1beta1/query.proto) - - [QueryCommunityPoolRequest](#cosmos.distribution.v1beta1.QueryCommunityPoolRequest) - - [QueryCommunityPoolResponse](#cosmos.distribution.v1beta1.QueryCommunityPoolResponse) - - [QueryDelegationRewardsRequest](#cosmos.distribution.v1beta1.QueryDelegationRewardsRequest) - - [QueryDelegationRewardsResponse](#cosmos.distribution.v1beta1.QueryDelegationRewardsResponse) - - [QueryDelegationTotalRewardsRequest](#cosmos.distribution.v1beta1.QueryDelegationTotalRewardsRequest) - - [QueryDelegationTotalRewardsResponse](#cosmos.distribution.v1beta1.QueryDelegationTotalRewardsResponse) - - [QueryDelegatorValidatorsRequest](#cosmos.distribution.v1beta1.QueryDelegatorValidatorsRequest) - - [QueryDelegatorValidatorsResponse](#cosmos.distribution.v1beta1.QueryDelegatorValidatorsResponse) - - [QueryDelegatorWithdrawAddressRequest](#cosmos.distribution.v1beta1.QueryDelegatorWithdrawAddressRequest) - - [QueryDelegatorWithdrawAddressResponse](#cosmos.distribution.v1beta1.QueryDelegatorWithdrawAddressResponse) - - [QueryParamsRequest](#cosmos.distribution.v1beta1.QueryParamsRequest) - - [QueryParamsResponse](#cosmos.distribution.v1beta1.QueryParamsResponse) - - [QueryValidatorCommissionRequest](#cosmos.distribution.v1beta1.QueryValidatorCommissionRequest) - - [QueryValidatorCommissionResponse](#cosmos.distribution.v1beta1.QueryValidatorCommissionResponse) - - [QueryValidatorOutstandingRewardsRequest](#cosmos.distribution.v1beta1.QueryValidatorOutstandingRewardsRequest) - - [QueryValidatorOutstandingRewardsResponse](#cosmos.distribution.v1beta1.QueryValidatorOutstandingRewardsResponse) - - [QueryValidatorSlashesRequest](#cosmos.distribution.v1beta1.QueryValidatorSlashesRequest) - - [QueryValidatorSlashesResponse](#cosmos.distribution.v1beta1.QueryValidatorSlashesResponse) +- [ibc/lightclients/solomachine/v1/solomachine.proto](#ibc/lightclients/solomachine/v1/solomachine.proto) + - [ChannelStateData](#ibc.lightclients.solomachine.v1.ChannelStateData) + - [ClientState](#ibc.lightclients.solomachine.v1.ClientState) + - [ClientStateData](#ibc.lightclients.solomachine.v1.ClientStateData) + - [ConnectionStateData](#ibc.lightclients.solomachine.v1.ConnectionStateData) + - [ConsensusState](#ibc.lightclients.solomachine.v1.ConsensusState) + - [ConsensusStateData](#ibc.lightclients.solomachine.v1.ConsensusStateData) + - [Header](#ibc.lightclients.solomachine.v1.Header) + - [HeaderData](#ibc.lightclients.solomachine.v1.HeaderData) + - [Misbehaviour](#ibc.lightclients.solomachine.v1.Misbehaviour) + - [NextSequenceRecvData](#ibc.lightclients.solomachine.v1.NextSequenceRecvData) + - [PacketAcknowledgementData](#ibc.lightclients.solomachine.v1.PacketAcknowledgementData) + - [PacketCommitmentData](#ibc.lightclients.solomachine.v1.PacketCommitmentData) + - [PacketReceiptAbsenceData](#ibc.lightclients.solomachine.v1.PacketReceiptAbsenceData) + - [SignBytes](#ibc.lightclients.solomachine.v1.SignBytes) + - [SignatureAndData](#ibc.lightclients.solomachine.v1.SignatureAndData) + - [TimestampedSignatureData](#ibc.lightclients.solomachine.v1.TimestampedSignatureData) - - [Query](#cosmos.distribution.v1beta1.Query) + - [DataType](#ibc.lightclients.solomachine.v1.DataType) -- [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) +- [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

-## ibc/applications/transfer/v1/transfer.proto +## cosmos/auth/v1beta1/auth.proto - + -### DenomTrace -DenomTrace contains the base denomination for ICS20 fungible tokens and the -source tracing information path. +### 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 | | ----- | ---- | ----- | ----------- | -| `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. | +| `address` | [string](#string) | | | +| `pub_key` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `account_number` | [uint64](#uint64) | | | +| `sequence` | [uint64](#uint64) | | | - + -### 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 +### ModuleAccount +ModuleAccount defines an account for modules that holds coins on a pool. | 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 | +| `base_account` | [BaseAccount](#cosmos.auth.v1beta1.BaseAccount) | | | +| `name` | [string](#string) | | | +| `permissions` | [string](#string) | repeated | | - + ### 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. +Params defines the parameters for the auth module. | 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. | +| `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) | | | @@ -826,109 +828,141 @@ parameter for the denomination to false. - +

Top

-## ibc/applications/transfer/v1/tx.proto +## cosmos/auth/v1beta1/genesis.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 +### GenesisState +GenesisState defines the auth module's genesis state. | 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. | +| `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. | + + + + + + + + + + + + + + + + +

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; + } + + +| 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. | - -### MsgTransferResponse -MsgTransferResponse defines the Msg/Transfer response type. + +### 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 | +| ----- | ---- | ----- | ----------- | +| `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 | - - - - + -### 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/query.proto +## cosmos/auth/v1beta1/query.proto - + -### QueryDenomTraceRequest -QueryDenomTraceRequest is the request type for the Query/DenomTrace RPC -method +### QueryAccountRequest +QueryAccountRequest is the request type for the Query/Account RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `hash` | [string](#string) | | hash (in hex format) of the denomination trace information. | +| `address` | [string](#string) | | address defines the address to query for. | - + -### QueryDenomTraceResponse -QueryDenomTraceResponse is the response type for the Query/DenomTrace RPC -method. +### QueryAccountResponse +QueryAccountResponse is the response type for the Query/Account RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `denom_trace` | [DenomTrace](#ibc.applications.transfer.v1.DenomTrace) | | denom_trace returns the requested denomination trace information. | +| `account` | [google.protobuf.Any](#google.protobuf.Any) | | account defines the account of the corresponding address. | - + -### QueryDenomTracesRequest -QueryConnectionsRequest is the request type for the Query/DenomTraces RPC -method +### QueryAccountsRequest +QueryAccountsRequest is the request type for the Query/Accounts RPC method. | Field | Type | Label | Description | @@ -940,16 +974,15 @@ method - + -### QueryDenomTracesResponse -QueryConnectionsResponse is the response type for the Query/DenomTraces RPC -method. +### QueryAccountsResponse +QueryAccountsResponse is the response type for the Query/Accounts RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `denom_traces` | [DenomTrace](#ibc.applications.transfer.v1.DenomTrace) | repeated | denom_traces returns all denominations trace information. | +| `accounts` | [google.protobuf.Any](#google.protobuf.Any) | repeated | accounts are the existing accounts | | `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | @@ -957,7 +990,7 @@ method. - + ### QueryParamsRequest QueryParamsRequest is the request type for the Query/Params RPC method. @@ -967,7 +1000,7 @@ QueryParamsRequest is the request type for the Query/Params RPC method. - + ### QueryParamsResponse QueryParamsResponse is the response type for the Query/Params RPC method. @@ -975,7 +1008,7 @@ QueryParamsResponse is the response type for the Query/Params RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params` | [Params](#ibc.applications.transfer.v1.Params) | | params defines the parameters of the module. | +| `params` | [Params](#cosmos.auth.v1beta1.Params) | | params defines the parameters of the module. | @@ -988,39 +1021,55 @@ QueryParamsResponse is the response type for the Query/Params RPC method. - + ### Query -Query provides defines the gRPC querier service. +Query 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| +| `Accounts` | [QueryAccountsRequest](#cosmos.auth.v1beta1.QueryAccountsRequest) | [QueryAccountsResponse](#cosmos.auth.v1beta1.QueryAccountsResponse) | Accounts returns all the existing accounts | GET|/cosmos/auth/v1beta1/accounts| +| `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

-## ibc/applications/transfer/v1/genesis.proto +## cosmos/authz/v1beta1/authz.proto - + -### GenesisState -GenesisState defines the ibc-transfer genesis state +### AuthorizationGrant +AuthorizationGrant gives permissions to execute +the provide method with expiration time. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | | -| `denom_traces` | [DenomTrace](#ibc.applications.transfer.v1.DenomTrace) | repeated | | -| `params` | [Params](#ibc.applications.transfer.v1.Params) | | | +| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | + + + + + + + + +### 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` | @@ -1036,24 +1085,40 @@ GenesisState defines the ibc-transfer genesis state - +

Top

-## ibc/core/types/v1/genesis.proto +## cosmos/authz/v1beta1/genesis.proto - + ### GenesisState -GenesisState defines the ibc module's genesis state. +GenesisState defines the authz 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 | +| `authorization` | [GrantAuthorization](#cosmos.authz.v1beta1.GrantAuthorization) | repeated | | + + + + + + + + +### 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) | | | @@ -1069,248 +1134,280 @@ GenesisState defines the ibc module's genesis state. - +

Top

-## ibc/core/client/v1/client.proto +## cosmos/authz/v1beta1/query.proto - + -### ClientConsensusStates -ClientConsensusStates defines all the stored consensus states for a given -client. +### QueryAuthorizationRequest +QueryAuthorizationRequest is the request type for the Query/Authorization RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client identifier | -| `consensus_states` | [ConsensusStateWithHeight](#ibc.core.client.v1.ConsensusStateWithHeight) | repeated | consensus states and their heights associated with the client | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `method_name` | [string](#string) | | | - + -### ClientUpdateProposal -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). +### QueryAuthorizationResponse +QueryAuthorizationResponse is the response type for the Query/Authorization RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `title` | [string](#string) | | the title of the update proposal | -| `description` | [string](#string) | | the description of the proposal | -| `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 | +| `authorization` | [AuthorizationGrant](#cosmos.authz.v1beta1.AuthorizationGrant) | | authorization is a authorization granted for grantee by granter. | - + -### ConsensusStateWithHeight -ConsensusStateWithHeight defines a consensus state with an additional height field. +### QueryAuthorizationsRequest +QueryAuthorizationsRequest is the request type for the Query/Authorizations RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `height` | [Height](#ibc.core.client.v1.Height) | | consensus state height | -| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | consensus state | - +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | - -### Height -Height is a monotonically increasing data type -that can be compared against another Height for the purposes of updating and -freezing clients + -Normally the RevisionHeight is incremented at each height while keeping RevisionNumber -the same. However some consensus algorithms may choose to reset the -height in certain conditions e.g. hard forks, state-machine breaking changes -In these cases, the RevisionNumber is incremented so that height continues to -be monitonically increasing even as the RevisionHeight gets reset +### QueryAuthorizationsResponse +QueryAuthorizationsResponse is the response type for the Query/Authorizations RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `revision_number` | [uint64](#uint64) | | the revision that the client is currently on | -| `revision_height` | [uint64](#uint64) | | the height within the given revision | +| `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. | + - + -### IdentifiedClientState -IdentifiedClientState defines a client state with an additional client -identifier field. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client identifier | -| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | client state | + +### 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

-### Params -Params defines the set of IBC light client parameters. +## cosmos/base/abci/v1beta1/abci.proto + + + + + +### ABCIMessageLog +ABCIMessageLog defines a structure containing an indexed tx ABCI message log. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `allowed_clients` | [string](#string) | repeated | allowed_clients defines the list of allowed client state types. | +| `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. | - - + - +### 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) | | | - -

Top

-## ibc/core/client/v1/tx.proto - + -### MsgCreateClient -MsgCreateClient defines a message to create an IBC client +### GasInfo +GasInfo defines tx execution gas context. | 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 | +| `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. | - + -### MsgCreateClientResponse -MsgCreateClientResponse defines the Msg/CreateClient response type. +### MsgData +MsgData defines the data returned in a Result object during message +execution. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `msg_type` | [string](#string) | | | +| `data` | [bytes](#bytes) | | | - -### MsgSubmitMisbehaviour -MsgSubmitMisbehaviour defines an sdk.Msg type that submits Evidence for -light client misbehaviour. + + + +### Result +Result is the union of ResponseFormat and ResponseCheckTx. | 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 | +| `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. | - + -### MsgSubmitMisbehaviourResponse -MsgSubmitMisbehaviourResponse defines the Msg/SubmitMisbehaviour response type. +### 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 | + - -### MsgUpdateClient -MsgUpdateClient defines an sdk.Msg to update a IBC client state using -the given header. + + +### SimulationResponse +SimulationResponse defines the response generated when a transaction is +successfully simulated. | 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 | +| `gas_info` | [GasInfo](#cosmos.base.abci.v1beta1.GasInfo) | | | +| `result` | [Result](#cosmos.base.abci.v1beta1.Result) | | | - + -### MsgUpdateClientResponse -MsgUpdateClientResponse defines the Msg/UpdateClient response type. +### 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 | | - -### MsgUpgradeClient -MsgUpgradeClient defines an sdk.Msg to upgrade an IBC client to a new client state + + + +### TxMsgData +TxMsgData defines a list of MsgData. A transaction will have a MsgData object +for each message. | 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 | +| `data` | [MsgData](#cosmos.base.abci.v1beta1.MsgData) | repeated | | - + -### MsgUpgradeClientResponse -MsgUpgradeClientResponse defines the Msg/UpgradeClient response type. +### 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 | +| ----- | ---- | ----- | ----------- | +| `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. | @@ -1322,189 +1419,197 @@ 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. | | - - +

Top

-## ibc/core/client/v1/query.proto +## cosmos/authz/v1beta1/tx.proto - + -### QueryClientParamsRequest -QueryClientParamsRequest is the request type for the Query/ClientParams 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 | +| ----- | ---- | ----- | ----------- | +| `grantee` | [string](#string) | | | +| `msgs` | [google.protobuf.Any](#google.protobuf.Any) | repeated | | - + -### QueryClientParamsResponse -QueryClientParamsResponse is the response type for the Query/ClientParams RPC method. +### MsgExecAuthorizedResponse +MsgExecAuthorizedResponse defines the Msg/MsgExecAuthorizedResponse response type. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params` | [Params](#ibc.core.client.v1.Params) | | params defines the parameters of the module. | +| `result` | [cosmos.base.abci.v1beta1.Result](#cosmos.base.abci.v1beta1.Result) | | | - + -### QueryClientStateRequest -QueryClientStateRequest is the request type for the Query/ClientState 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 | | ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client state unique identifier | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | - + -### 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. +### MsgGrantAuthorizationResponse +MsgGrantAuthorizationResponse defines the Msg/MsgGrantAuthorization response type. + + + + + + + + +### 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 | | ----- | ---- | ----- | ----------- | -| `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 | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `method_name` | [string](#string) | | | - + -### QueryClientStatesRequest -QueryClientStatesRequest is the request type for the Query/ClientStates RPC -method +### MsgRevokeAuthorizationResponse +MsgRevokeAuthorizationResponse defines the Msg/MsgRevokeAuthorizationResponse response type. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | + + + - -### QueryClientStatesResponse -QueryClientStatesResponse is the response type for the Query/ClientStates RPC -method. + +### Msg +Msg defines the authz Msg service. -| 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 | +| 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/base/v1beta1/coin.proto - -### 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. + + +### 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 | | ----- | ---- | ----- | ----------- | -| `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 | +| `denom` | [string](#string) | | | +| `amount` | [string](#string) | | | - + -### QueryConsensusStateResponse -QueryConsensusStateResponse is the response type for the Query/ConsensusState -RPC method +### 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. | 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 | - +| `denom` | [string](#string) | | | +| `amount` | [string](#string) | | | - -### QueryConsensusStatesRequest -QueryConsensusStatesRequest is the request type for the Query/ConsensusStates -RPC method. + + +### DecProto +DecProto defines a Protobuf wrapper around a Dec object. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client identifier | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | +| `dec` | [string](#string) | | | - + -### QueryConsensusStatesResponse -QueryConsensusStatesResponse is the response type for the -Query/ConsensusStates RPC method +### IntProto +IntProto defines a Protobuf wrapper around an Int object. | 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 | +| `int` | [string](#string) | | | @@ -1516,163 +1621,161 @@ Query/ConsensusStates RPC method - - - -### 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/client/v1/genesis.proto +## cosmos/bank/v1beta1/authz.proto - + -### GenesisMetadata -GenesisMetadata defines the genesis type for metadata that clients may return -with ExportMetadata +### SendAuthorization +SendAuthorization allows the grantee to spend up to spend_limit coins from +the granter's account. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | store key of metadata without clientID-prefix | -| `value` | [bytes](#bytes) | | metadata value | +| `spend_limit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | + - + -### GenesisState -GenesisState defines the ibc client submodule's genesis state. + + + + + + + +

Top

+ +## cosmos/bank/v1beta1/bank.proto + + + + + +### DenomUnit +DenomUnit represents a struct that describes a given +denomination unit of the basic token. | 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 | +| `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 | - + -### IdentifiedGenesisMetadata -IdentifiedGenesisMetadata has the client metadata with the corresponding client id. +### Input +Input models transaction input. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | | -| `client_metadata` | [GenesisMetadata](#ibc.core.client.v1.GenesisMetadata) | repeated | | +| `address` | [string](#string) | | | +| `coins` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | - - + - +### Metadata +Metadata represents a struct that describes +a basic token. - +| 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. | - -

Top

-## ibc/core/commitment/v1/commitment.proto - + -### MerklePath -MerklePath is the path used to verify commitment proofs, which can be an -arbitrary structured object (defined by a commitment type). -MerklePath is represented from root-to-leaf +### Output +Output models transaction outputs. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key_path` | [string](#string) | repeated | | +| `address` | [string](#string) | | | +| `coins` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | - + -### MerklePrefix -MerklePrefix is merkle path prefixed to the key. -The constructed key from the Path and the key will be append(Path.KeyPath, -append(Path.KeyPrefix, key...)) +### Params +Params defines the parameters for the bank module. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key_prefix` | [bytes](#bytes) | | | +| `send_enabled` | [SendEnabled](#cosmos.bank.v1beta1.SendEnabled) | repeated | | +| `default_send_enabled` | [bool](#bool) | | | - + -### MerkleProof -MerkleProof is a wrapper type over a chain of CommitmentProofs. -It demonstrates membership or non-membership for an element or set of -elements, verifiable in conjunction with a known commitment root. Proofs -should be succinct. -MerkleProofs are ordered from leaf-to-root +### SendEnabled +SendEnabled maps coin denom to a send_enabled status (whether a denom is +sendable). | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proofs` | [ics23.CommitmentProof](#ics23.CommitmentProof) | repeated | | +| `denom` | [string](#string) | | | +| `enabled` | [bool](#bool) | | | - + -### MerkleRoot -MerkleRoot defines a merkle root hash. -In the Cosmos SDK, the AppHash of a block header becomes the root. +### Supply +Supply represents a struct that passively keeps track of the total supply +amounts in the network. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `hash` | [bytes](#bytes) | | | +| `total` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | @@ -1688,303 +1791,267 @@ In the Cosmos SDK, the AppHash of a block header becomes the root. - +

Top

-## ibc/core/channel/v1/tx.proto +## cosmos/bank/v1beta1/genesis.proto - + -### MsgAcknowledgement -MsgAcknowledgement receives incoming IBC acknowledgement +### Balance +Balance defines an account address and balance pair used in the bank module's +genesis state. | 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. +| `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. | - + -### MsgChannelCloseConfirm -MsgChannelCloseConfirm defines a msg sent by a Relayer to Chain B -to acknowledge the change of channel state to CLOSED on Chain A. +### GenesisState +GenesisState defines the bank module's genesis state. | 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) | | | - - - - - +| `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. | - -### MsgChannelCloseConfirmResponse -MsgChannelCloseConfirmResponse defines the Msg/ChannelCloseConfirm response type. + + + - + -### 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) | | | + +

Top

+## cosmos/bank/v1beta1/query.proto + +### QueryAllBalancesRequest +QueryBalanceRequest is the request type for the Query/AllBalances RPC method. - -### MsgChannelCloseInitResponse -MsgChannelCloseInitResponse defines the Msg/ChannelCloseInit response type. +| 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. | - + -### MsgChannelOpenAck -MsgChannelOpenAck defines a msg sent by a Relayer to Chain A to acknowledge -the change of channel state to TRYOPEN on Chain B. +### QueryAllBalancesResponse +QueryAllBalancesResponse is the response type for the Query/AllBalances 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) | | | +| `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. | - + -### MsgChannelOpenAckResponse -MsgChannelOpenAckResponse defines the Msg/ChannelOpenAck response type. +### 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. | - + -### MsgChannelOpenConfirm -MsgChannelOpenConfirm defines a msg sent by a Relayer to Chain B to -acknowledge the change of channel state to OPEN on Chain A. +### QueryBalanceResponse +QueryBalanceResponse is the response type for the Query/Balance 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) | | | +| `balance` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | balance is the balance of the coin. | - + -### MsgChannelOpenConfirmResponse -MsgChannelOpenConfirmResponse defines the Msg/ChannelOpenConfirm 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. | - + -### MsgChannelOpenInit -MsgChannelOpenInit defines an sdk.Msg to initialize a channel handshake. It -is called by a relayer on Chain A. +### QueryDenomMetadataResponse +QueryDenomMetadataResponse is the response type for the Query/DenomMetadata RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | | -| `channel` | [Channel](#ibc.core.channel.v1.Channel) | | | -| `signer` | [string](#string) | | | +| `metadata` | [Metadata](#cosmos.bank.v1beta1.Metadata) | | metadata describes and provides all the client information for the requested token. | - + -### MsgChannelOpenInitResponse -MsgChannelOpenInitResponse defines the Msg/ChannelOpenInit 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. | - -### MsgChannelOpenTry -MsgChannelOpenInit defines a msg sent by a Relayer to try to open a channel -on Chain B. + + + +### QueryDenomsMetadataResponse +QueryDenomsMetadataResponse is the response type for the Query/DenomsMetadata 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) | | | +| `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. | - + -### MsgChannelOpenTryResponse -MsgChannelOpenTryResponse defines the Msg/ChannelOpenTry response type. +### QueryParamsRequest +QueryParamsRequest defines the request type for querying x/bank parameters. - + -### MsgRecvPacket -MsgRecvPacket receives incoming IBC packet +### QueryParamsResponse +QueryParamsResponse defines the response type for querying x/bank parameters. | 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) | | | - - - - - - - - -### MsgRecvPacketResponse -MsgRecvPacketResponse defines the Msg/RecvPacket response type. +| `params` | [Params](#cosmos.bank.v1beta1.Params) | | | - + -### MsgTimeout -MsgTimeout receives timed-out packet +### QuerySupplyOfRequest +QuerySupplyOfRequest is the request type for the Query/SupplyOf 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) | | | +| `denom` | [string](#string) | | denom is the coin denom to query balances for. | - + -### MsgTimeoutOnClose -MsgTimeoutOnClose timed-out packet upon counterparty channel closure. +### QuerySupplyOfResponse +QuerySupplyOfResponse is the response type for the Query/SupplyOf 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) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | amount is the supply of the coin. | - + -### MsgTimeoutOnCloseResponse -MsgTimeoutOnCloseResponse defines the Msg/TimeoutOnClose response type. +### QueryTotalSupplyRequest +QueryTotalSupplyRequest is the request type for the Query/TotalSupply RPC +method. - + -### MsgTimeoutResponse -MsgTimeoutResponse defines the Msg/Timeout response type. +### 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 | @@ -1997,886 +2064,776 @@ MsgTimeoutResponse defines the Msg/Timeout response type. - + -### Msg -Msg defines the ibc/channel Msg service. +### Query +Query 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. | | +| `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

-## ibc/core/channel/v1/query.proto +## cosmos/bank/v1beta1/tx.proto - + -### QueryChannelClientStateRequest -QueryChannelClientStateRequest is the request type for the Query/ClientState -RPC method +### MsgMultiSend +MsgMultiSend represents an arbitrary multi-in, multi-out send message. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | port unique identifier | -| `channel_id` | [string](#string) | | channel unique identifier | - - +| `inputs` | [Input](#cosmos.bank.v1beta1.Input) | repeated | | +| `outputs` | [Output](#cosmos.bank.v1beta1.Output) | repeated | | - -### QueryChannelClientStateResponse -QueryChannelClientStateResponse is the Response type for the -Query/QueryChannelClientState RPC method + -| 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 | +### MsgMultiSendResponse +MsgMultiSendResponse defines the Msg/MultiSend response type. - + -### QueryChannelConsensusStateRequest -QueryChannelConsensusStateRequest is the request type for the -Query/ConsensusState RPC method +### MsgSend +MsgSend represents a message to send coins from one account to another. | 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 | - - - - - - - - -### QueryChannelConsensusStateResponse -QueryChannelClientStateResponse is the Response type for the -Query/QueryChannelClientState RPC method +| `from_address` | [string](#string) | | | +| `to_address` | [string](#string) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | -| 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 | + +### MsgSendResponse +MsgSendResponse defines the Msg/Send 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 | + + + + - +### Msg +Msg defines the bank Msg service. -### 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. +| 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 | -| ----- | ---- | ----- | ----------- | -| `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 | + +

Top

+## cosmos/base/kv/v1beta1/kv.proto - + -### QueryChannelsRequest -QueryChannelsRequest is the request type for the Query/Channels RPC method +### Pair +Pair defines a key/value bytes tuple. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | +| `key` | [bytes](#bytes) | | | +| `value` | [bytes](#bytes) | | | - + -### QueryChannelsResponse -QueryChannelsResponse is the response type for the Query/Channels RPC method. +### Pairs +Pairs defines a repeated slice of Pair objects. | 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 | - - +| `pairs` | [Pair](#cosmos.base.kv.v1beta1.Pair) | repeated | | - -### 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 | + + + +

Top

+## cosmos/base/reflection/v1beta1/reflection.proto - -### 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 | +### ListAllInterfacesRequest +ListAllInterfacesRequest is the request type of the ListAllInterfaces RPC. - + -### QueryNextSequenceReceiveRequest -QueryNextSequenceReceiveRequest is the request type for the -Query/QueryNextSequenceReceiveRequest RPC method +### ListAllInterfacesResponse +ListAllInterfacesResponse is the response type of the ListAllInterfaces RPC. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | port unique identifier | -| `channel_id` | [string](#string) | | channel unique identifier | +| `interface_names` | [string](#string) | repeated | interface_names is an array of all the registered interfaces. | - + -### QueryNextSequenceReceiveResponse -QuerySequenceResponse is the request type for the -Query/QueryNextSequenceReceiveResponse RPC method +### ListImplementationsRequest +ListImplementationsRequest is the request type of the ListImplementations +RPC. | 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 | +| `interface_name` | [string](#string) | | interface_name defines the interface to query the implementations for. | - + -### QueryPacketAcknowledgementRequest -QueryPacketAcknowledgementRequest is the request type for the -Query/PacketAcknowledgement RPC method +### ListImplementationsResponse +ListImplementationsResponse is the response type of the ListImplementations +RPC. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | port unique identifier | -| `channel_id` | [string](#string) | | channel unique identifier | -| `sequence` | [uint64](#uint64) | | packet sequence | +| `implementation_message_names` | [string](#string) | repeated | | + - + -### 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 | + + +### 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

+## cosmos/base/snapshots/v1beta1/snapshot.proto - -### QueryPacketAcknowledgementsRequest -QueryPacketAcknowledgementsRequest is the request type for the -Query/QueryPacketCommitments RPC method + + +### Metadata +Metadata contains SDK-specific snapshot metadata. | 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 | +| `chunk_hashes` | [bytes](#bytes) | repeated | SHA-256 chunk hashes | - + -### QueryPacketAcknowledgementsResponse -QueryPacketAcknowledgemetsResponse is the request type for the -Query/QueryPacketAcknowledgements RPC method +### Snapshot +Snapshot contains Tendermint state sync snapshot info. | 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 | +| `height` | [uint64](#uint64) | | | +| `format` | [uint32](#uint32) | | | +| `chunks` | [uint32](#uint32) | | | +| `hash` | [bytes](#bytes) | | | +| `metadata` | [Metadata](#cosmos.base.snapshots.v1beta1.Metadata) | | | + - + -### QueryPacketCommitmentRequest -QueryPacketCommitmentRequest is the request type for the -Query/PacketCommitment 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 | + +

Top

+## cosmos/base/store/v1beta1/commit_info.proto - + -### QueryPacketCommitmentResponse -QueryPacketCommitmentResponse defines the client query response for a packet -which also includes a proof and the height from which the proof was -retrieved +### CommitID +CommitID defines the committment information when a specific store is +committed. | 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 | +| `version` | [int64](#int64) | | | +| `hash` | [bytes](#bytes) | | | - + -### QueryPacketCommitmentsRequest -QueryPacketCommitmentsRequest is the request type for the -Query/QueryPacketCommitments RPC method +### CommitInfo +CommitInfo defines commit information used by the multi-store when committing +a version/height. | 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 | +| `version` | [int64](#int64) | | | +| `store_infos` | [StoreInfo](#cosmos.base.store.v1beta1.StoreInfo) | repeated | | - + -### QueryPacketCommitmentsResponse -QueryPacketCommitmentsResponse is the request type for the -Query/QueryPacketCommitments 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 | | ----- | ---- | ----- | ----------- | -| `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 | +| `name` | [string](#string) | | | +| `commit_id` | [CommitID](#cosmos.base.store.v1beta1.CommitID) | | | + - + -### 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 | + +

Top

+## cosmos/base/store/v1beta1/snapshot.proto - + -### 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 +### SnapshotIAVLItem +SnapshotIAVLItem is an exported IAVL node. | 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 | +| `key` | [bytes](#bytes) | | | +| `value` | [bytes](#bytes) | | | +| `version` | [int64](#int64) | | | +| `height` | [int32](#int32) | | | - + -### QueryUnreceivedAcksRequest -QueryUnreceivedAcks is the request type for the -Query/UnreceivedAcks RPC method +### SnapshotItem +SnapshotItem is an item contained in a rootmulti.Store snapshot. | 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 | +| `store` | [SnapshotStoreItem](#cosmos.base.store.v1beta1.SnapshotStoreItem) | | | +| `iavl` | [SnapshotIAVLItem](#cosmos.base.store.v1beta1.SnapshotIAVLItem) | | | - + -### QueryUnreceivedAcksResponse -QueryUnreceivedAcksResponse is the response type for the -Query/UnreceivedAcks RPC method +### SnapshotStoreItem +SnapshotStoreItem contains metadata about a snapshotted store. | 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 | - +| `name` | [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 | + + +

Top

+## cosmos/base/tendermint/v1beta1/query.proto - -### QueryUnreceivedPacketsResponse -QueryUnreceivedPacketsResponse is the response type for the -Query/UnreceivedPacketCommitments RPC method + + +### GetBlockByHeightRequest +GetBlockByHeightRequest is the request type for the Query/GetBlockByHeight 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 | +| `height` | [int64](#int64) | | | - - + - +### 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) | | | -### 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

+ -## ibc/core/channel/v1/genesis.proto +### GetLatestBlockRequest +GetLatestBlockRequest is the request type for the Query/GetLatestBlock RPC method. - -### GenesisState -GenesisState defines the ibc channel submodule's genesis state. + + + + +### GetLatestBlockResponse +GetLatestBlockResponse is the response type for the Query/GetLatestBlock RPC method. | 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 | +| `block_id` | [tendermint.types.BlockID](#tendermint.types.BlockID) | | | +| `block` | [tendermint.types.Block](#tendermint.types.Block) | | | - + -### PacketSequence -PacketSequence defines the genesis type necessary to retrieve and store -next send and receive sequences. +### GetLatestValidatorSetRequest +GetLatestValidatorSetRequest is the request type for the Query/GetValidatorSetByHeight RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | | -| `channel_id` | [string](#string) | | | -| `sequence` | [uint64](#uint64) | | | - - +| `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. - -

Top

+| 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. | -## 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 | -| ----- | ---- | ----- | ----------- | -| `result` | [bytes](#bytes) | | | -| `error` | [string](#string) | | | +### GetNodeInfoRequest +GetNodeInfoRequest is the request type for the Query/GetNodeInfo 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. +### GetNodeInfoResponse +GetNodeInfoResponse is the request type for the Query/GetNodeInfo 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 | - - +| `default_node_info` | [tendermint.p2p.DefaultNodeInfo](#tendermint.p2p.DefaultNodeInfo) | | | +| `application_version` | [VersionInfo](#cosmos.base.tendermint.v1beta1.VersionInfo) | | | - -### Counterparty -Counterparty defines a channel end counterparty + -| 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 | +### GetSyncingRequest +GetSyncingRequest is the request type for the Query/GetSyncing RPC method. - + -### IdentifiedChannel -IdentifiedChannel defines a channel with additional port and channel -identifier fields. +### GetSyncingResponse +GetSyncingResponse is the response type for the Query/GetSyncing 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 | +| `syncing` | [bool](#bool) | | | - + -### Packet -Packet defines a type that carries data across different chains through IBC +### GetValidatorSetByHeightRequest +GetValidatorSetByHeightRequest is the request type for the Query/GetValidatorSetByHeight 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 | +| `height` | [int64](#int64) | | | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | - + -### 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. +### GetValidatorSetByHeightResponse +GetValidatorSetByHeightResponse is the response type for the Query/GetValidatorSetByHeight 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. | - +| `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. | - - + -### Order -Order defines if a channel is ORDERED or UNORDERED +### Module +Module is the type for VersionInfo -| 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 | +| ----- | ---- | ----- | ----------- | +| `path` | [string](#string) | | module path | +| `version` | [string](#string) | | module version | +| `sum` | [string](#string) | | checksum | - -### 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. | - + - +### Validator +Validator is the type for the validator-set. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `address` | [string](#string) | | | +| `pub_key` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `voting_power` | [int64](#int64) | | | +| `proposer_priority` | [int64](#int64) | | | - -

Top

-## ibc/core/connection/v1/tx.proto - + -### MsgConnectionOpenAck -MsgConnectionOpenAck defines a msg sent by a Relayer to Chain A to -acknowledge the change of connection state to TRYOPEN on Chain B. +### VersionInfo +VersionInfo is the type for the GetNodeInfoResponse message. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `connection_id` | [string](#string) | | | -| `counterparty_connection_id` | [string](#string) | | | -| `version` | [Version](#ibc.core.connection.v1.Version) | | | -| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | -| `proof_try` | [bytes](#bytes) | | proof of the initialization the connection on Chain B: `UNITIALIZED -> TRYOPEN` | -| `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) | | | +| `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 | | + + + - + -### MsgConnectionOpenAckResponse -MsgConnectionOpenAckResponse defines the Msg/ConnectionOpenAck response type. + + + +### 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/capability/v1beta1/capability.proto - + -### MsgConnectionOpenConfirm -MsgConnectionOpenConfirm defines a msg sent by a Relayer to Chain B to -acknowledge the change of connection state to OPEN on Chain A. +### Capability +Capability defines an implementation of an object capability. The index +provided to a Capability must be globally unique. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `connection_id` | [string](#string) | | | -| `proof_ack` | [bytes](#bytes) | | proof for the change of the connection state on Chain A: `INIT -> OPEN` | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | -| `signer` | [string](#string) | | | +| `index` | [uint64](#uint64) | | | - + -### MsgConnectionOpenConfirmResponse -MsgConnectionOpenConfirmResponse defines the Msg/ConnectionOpenConfirm response type. +### CapabilityOwners +CapabilityOwners defines a set of owners of a single Capability. The set of +owners must be unique. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `owners` | [Owner](#cosmos.capability.v1beta1.Owner) | repeated | | - + -### MsgConnectionOpenInit -MsgConnectionOpenInit defines the msg sent by an account on Chain A to -initialize a connection with Chain B. +### Owner +Owner defines a single capability owner. An owner is defined by the name of +capability and the module name. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | | -| `counterparty` | [Counterparty](#ibc.core.connection.v1.Counterparty) | | | -| `version` | [Version](#ibc.core.connection.v1.Version) | | | -| `delay_period` | [uint64](#uint64) | | | -| `signer` | [string](#string) | | | +| `module` | [string](#string) | | | +| `name` | [string](#string) | | | + - + -### MsgConnectionOpenInitResponse -MsgConnectionOpenInitResponse defines the Msg/ConnectionOpenInit response type. + + + +

Top

+## cosmos/capability/v1beta1/genesis.proto - -### MsgConnectionOpenTry -MsgConnectionOpenTry defines a msg sent by a Relayer to try to open a -connection on Chain B. + + + +### GenesisOwners +GenesisOwners defines the capability owners with their corresponding index. | 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) | | | +| `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. | - + -### MsgConnectionOpenTryResponse -MsgConnectionOpenTryResponse defines the Msg/ConnectionOpenTry response type. +### 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. | @@ -2888,154 +2845,137 @@ 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/connection.proto +## cosmos/crisis/v1beta1/genesis.proto - + -### ClientPaths -ClientPaths define all the connection paths for a client state. +### GenesisState +GenesisState defines the crisis module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `paths` | [string](#string) | repeated | list of connection paths | +| `constant_fee` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | constant_fee is the fee used to verify the invariant in the crisis module. | + - + -### ConnectionEnd -ConnectionEnd defines a stateful object on a chain connected to another -separate one. -NOTE: there must only be 2 defined ConnectionEnds to establish -a connection between two chains. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client associated with this connection. | -| `versions` | [Version](#ibc.core.connection.v1.Version) | repeated | IBC version which can be utilised to determine encodings or protocols for channels or packets utilising this connection. | -| `state` | [State](#ibc.core.connection.v1.State) | | current state of the connection end. | -| `counterparty` | [Counterparty](#ibc.core.connection.v1.Counterparty) | | counterparty chain associated with this connection. | -| `delay_period` | [uint64](#uint64) | | delay period that must pass before a consensus state can be used for packet-verification NOTE: delay period logic is only implemented by some clients. | + +

Top

+## cosmos/crisis/v1beta1/tx.proto - + -### ConnectionPaths -ConnectionPaths define all the connection paths for a given client state. +### MsgVerifyInvariant +MsgVerifyInvariant represents a message to verify a particular invariance. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client state unique identifier | -| `paths` | [string](#string) | repeated | list of connection paths | +| `sender` | [string](#string) | | | +| `invariant_module_name` | [string](#string) | | | +| `invariant_route` | [string](#string) | | | - + -### Counterparty -Counterparty defines the counterparty chain associated with a connection end. +### MsgVerifyInvariantResponse +MsgVerifyInvariantResponse defines the Msg/VerifyInvariant response type. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | identifies the client on the counterparty chain associated with a given connection. | -| `connection_id` | [string](#string) | | identifies the connection end on the counterparty chain associated with a given connection. | -| `prefix` | [ibc.core.commitment.v1.MerklePrefix](#ibc.core.commitment.v1.MerklePrefix) | | commitment merkle prefix of the counterparty chain. | + + + - -### IdentifiedConnection -IdentifiedConnection defines a connection with additional connection -identifier field. + +### Msg +Msg defines the bank Msg service. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `id` | [string](#string) | | connection identifier. | -| `client_id` | [string](#string) | | client associated with this connection. | -| `versions` | [Version](#ibc.core.connection.v1.Version) | repeated | IBC version which can be utilised to determine encodings or protocols for channels or packets utilising this connection | -| `state` | [State](#ibc.core.connection.v1.State) | | current state of the connection end. | -| `counterparty` | [Counterparty](#ibc.core.connection.v1.Counterparty) | | counterparty chain associated with this connection. | -| `delay_period` | [uint64](#uint64) | | delay period associated with this connection. | +| 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 - -### Version -Version defines the versioning scheme used to negotiate the IBC verison in -the connection handshake. + + +### PrivKey +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 | | ----- | ---- | ----- | ----------- | -| `identifier` | [string](#string) | | unique version identifier | -| `features` | [string](#string) | repeated | list of features compatible with the specified identifier | +| `key` | [bytes](#bytes) | | | - + + +### PubKey +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 | +| ----- | ---- | ----- | ----------- | +| `key` | [bytes](#bytes) | | | - -### State -State defines if a connection is in one of the following states: -INIT, TRYOPEN, OPEN or UNINITIALIZED. -| Name | Number | Description | -| ---- | ------ | ----------- | -| STATE_UNINITIALIZED_UNSPECIFIED | 0 | Default State | -| STATE_INIT | 1 | A connection end has just started the opening handshake. | -| STATE_TRYOPEN | 2 | A connection end has acknowledged the handshake step on the counterparty chain. | -| STATE_OPEN | 3 | A connection end has completed the handshake. | + + @@ -3044,383 +2984,366 @@ INIT, TRYOPEN, OPEN or UNINITIALIZED. - +

Top

-## ibc/core/connection/v1/query.proto +## cosmos/crypto/multisig/keys.proto - + -### QueryClientConnectionsRequest -QueryClientConnectionsRequest is the request type for the -Query/ClientConnections RPC method +### 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 | | ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client identifier associated with a connection | +| `threshold` | [uint32](#uint32) | | | +| `public_keys` | [google.protobuf.Any](#google.protobuf.Any) | repeated | | + - + -### QueryClientConnectionsResponse -QueryClientConnectionsResponse is the response type for the -Query/ClientConnections RPC method + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `connection_paths` | [string](#string) | repeated | slice of all the connection paths associated with a client. | -| `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 generated | + +

Top

+## cosmos/crypto/multisig/v1beta1/multisig.proto - + -### QueryConnectionClientStateRequest -QueryConnectionClientStateRequest is the request type for the -Query/ConnectionClientState 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 | | ----- | ---- | ----- | ----------- | -| `connection_id` | [string](#string) | | connection identifier | +| `extra_bits_stored` | [uint32](#uint32) | | | +| `elems` | [bytes](#bytes) | | | - + -### QueryConnectionClientStateResponse -QueryConnectionClientStateResponse is the response type for the -Query/ConnectionClientState 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 | | ----- | ---- | ----- | ----------- | -| `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 | +| `signatures` | [bytes](#bytes) | repeated | | + - + -### QueryConnectionConsensusStateRequest -QueryConnectionConsensusStateRequest is the request type for the -Query/ConnectionConsensusState RPC method + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `connection_id` | [string](#string) | | connection identifier | -| `revision_number` | [uint64](#uint64) | | | -| `revision_height` | [uint64](#uint64) | | | + +

Top

+## cosmos/crypto/secp256k1/keys.proto - + -### QueryConnectionConsensusStateResponse -QueryConnectionConsensusStateResponse is the response type for the -Query/ConnectionConsensusState RPC method +### PrivKey +PrivKey defines a secp256k1 private key. | 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 | +| `key` | [bytes](#bytes) | | | - + -### QueryConnectionRequest -QueryConnectionRequest is the request type for the Query/Connection 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 | | ----- | ---- | ----- | ----------- | -| `connection_id` | [string](#string) | | connection unique identifier | +| `key` | [bytes](#bytes) | | | + - + -### QueryConnectionResponse -QueryConnectionResponse is the response type for the Query/Connection RPC -method. Besides the connection end, it includes a proof and the height from -which the proof was retrieved. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `connection` | [ConnectionEnd](#ibc.core.connection.v1.ConnectionEnd) | | connection associated with the request identifier | -| `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

+## cosmos/distribution/v1beta1/distribution.proto - + -### QueryConnectionsRequest -QueryConnectionsRequest is the request type for the Query/Connections 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 | | ----- | ---- | ----- | ----------- | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | | +| `title` | [string](#string) | | | +| `description` | [string](#string) | | | +| `recipient` | [string](#string) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | - + -### QueryConnectionsResponse -QueryConnectionsResponse is the response type for the Query/Connections RPC -method. +### CommunityPoolSpendProposalWithDeposit +CommunityPoolSpendProposalWithDeposit defines a CommunityPoolSpendProposal +with a deposit | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `connections` | [IdentifiedConnection](#ibc.core.connection.v1.IdentifiedConnection) | repeated | list of stored connections 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 | - - - - +| `title` | [string](#string) | | | +| `description` | [string](#string) | | | +| `recipient` | [string](#string) | | | +| `amount` | [string](#string) | | | +| `deposit` | [string](#string) | | | - - - - -### Query -Query provides defines the gRPC querier service + -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Connection` | [QueryConnectionRequest](#ibc.core.connection.v1.QueryConnectionRequest) | [QueryConnectionResponse](#ibc.core.connection.v1.QueryConnectionResponse) | Connection queries an IBC connection end. | GET|/ibc/core/connection/v1beta1/connections/{connection_id}| -| `Connections` | [QueryConnectionsRequest](#ibc.core.connection.v1.QueryConnectionsRequest) | [QueryConnectionsResponse](#ibc.core.connection.v1.QueryConnectionsResponse) | Connections queries all the IBC connections of a chain. | GET|/ibc/core/connection/v1beta1/connections| -| `ClientConnections` | [QueryClientConnectionsRequest](#ibc.core.connection.v1.QueryClientConnectionsRequest) | [QueryClientConnectionsResponse](#ibc.core.connection.v1.QueryClientConnectionsResponse) | ClientConnections queries the connection paths associated with a client state. | GET|/ibc/core/connection/v1beta1/client_connections/{client_id}| -| `ConnectionClientState` | [QueryConnectionClientStateRequest](#ibc.core.connection.v1.QueryConnectionClientStateRequest) | [QueryConnectionClientStateResponse](#ibc.core.connection.v1.QueryConnectionClientStateResponse) | ConnectionClientState queries the client state associated with the connection. | GET|/ibc/core/connection/v1beta1/connections/{connection_id}/client_state| -| `ConnectionConsensusState` | [QueryConnectionConsensusStateRequest](#ibc.core.connection.v1.QueryConnectionConsensusStateRequest) | [QueryConnectionConsensusStateResponse](#ibc.core.connection.v1.QueryConnectionConsensusStateResponse) | ConnectionConsensusState queries the consensus state associated with the connection. | GET|/ibc/core/connection/v1beta1/connections/{connection_id}/consensus_state/revision/{revision_number}/height/{revision_height}| +### 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 | | - -

Top

-## ibc/core/connection/v1/genesis.proto - + -### GenesisState -GenesisState defines the ibc connection submodule's genesis state. +### 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 | | ----- | ---- | ----- | ----------- | -| `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 | +| `previous_period` | [uint64](#uint64) | | | +| `stake` | [string](#string) | | | +| `height` | [uint64](#uint64) | | | - - + - +### FeePool +FeePool is the global fee pool for distribution. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `community_pool` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | - -

Top

-## ibc/lightclients/tendermint/v1/tendermint.proto - + -### ClientState -ClientState from Tendermint tracks the current validator set, latest height, -and a possible frozen height. +### Params +Params defines the set of params for the distribution module. | 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 | +| `community_tax` | [string](#string) | | | +| `base_proposer_reward` | [string](#string) | | | +| `bonus_proposer_reward` | [string](#string) | | | +| `withdraw_addr_enabled` | [bool](#bool) | | | - + -### ConsensusState -ConsensusState defines the consensus state from Tendermint. +### ValidatorAccumulatedCommission +ValidatorAccumulatedCommission represents accumulated commission +for a validator kept as a running counter, can be withdrawn at any time. | 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) | | | +| `commission` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | - + -### Fraction -Fraction defines the protobuf message type for tmmath.Fraction that only supports positive values. +### 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 | | ----- | ---- | ----- | ----------- | -| `numerator` | [uint64](#uint64) | | | -| `denominator` | [uint64](#uint64) | | | - - - - - - - +| `rewards` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | +| `period` | [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. + + + + + + + +### 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 | | ----- | ---- | ----- | ----------- | -| `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) | | | +| `cumulative_reward_ratio` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | +| `reference_count` | [uint32](#uint32) | | | - + -### Misbehaviour -Misbehaviour is a wrapper over two conflicting Headers -that implements Misbehaviour interface expected by ICS-02 +### ValidatorOutstandingRewards +ValidatorOutstandingRewards represents outstanding (un-withdrawn) rewards +for a validator inexpensive to track, allows simple sanity checks. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | | -| `header_1` | [Header](#ibc.lightclients.tendermint.v1.Header) | | | -| `header_2` | [Header](#ibc.lightclients.tendermint.v1.Header) | | | +| `rewards` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | - - + - +### 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

-## ibc/lightclients/localhost/v1/localhost.proto - + -### ClientState -ClientState defines a loopback (localhost) client. It requires (read-only) -access to keys outside the client prefix. +### ValidatorSlashEvents +ValidatorSlashEvents is a collection of ValidatorSlashEvent messages. | 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 | +| `validator_slash_events` | [ValidatorSlashEvent](#cosmos.distribution.v1beta1.ValidatorSlashEvent) | repeated | | @@ -3436,485 +3359,449 @@ access to keys outside the client prefix. - +

Top

-## ibc/lightclients/solomachine/v1/solomachine.proto +## cosmos/distribution/v1beta1/genesis.proto - + -### ChannelStateData -ChannelStateData returns the SignBytes data for channel state -verification. +### DelegatorStartingInfoRecord +DelegatorStartingInfoRecord used for import / export via genesis json. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `path` | [bytes](#bytes) | | | -| `channel` | [ibc.core.channel.v1.Channel](#ibc.core.channel.v1.Channel) | | | +| `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. | - + -### ClientState -ClientState defines a solo machine client that tracks the current consensus -state and if the client is frozen. +### 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 | | ----- | ---- | ----- | ----------- | -| `sequence` | [uint64](#uint64) | | latest sequence of the client state | -| `frozen_sequence` | [uint64](#uint64) | | frozen sequence of the solo machine | -| `consensus_state` | [ConsensusState](#ibc.lightclients.solomachine.v1.ConsensusState) | | | -| `allow_update_after_proposal` | [bool](#bool) | | when set to true, will allow governance to update a solo machine client. The client will be unfrozen if it is frozen. | +| `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. | - + -### ClientStateData -ClientStateData returns the SignBytes data for client state verification. +### GenesisState +GenesisState defines the distribution module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `path` | [bytes](#bytes) | | | -| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `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. | - + -### ConnectionStateData -ConnectionStateData returns the SignBytes data for connection state -verification. +### ValidatorAccumulatedCommissionRecord +ValidatorAccumulatedCommissionRecord is used for import / export via genesis +json. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `path` | [bytes](#bytes) | | | -| `connection` | [ibc.core.connection.v1.ConnectionEnd](#ibc.core.connection.v1.ConnectionEnd) | | | +| `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. | - + -### ConsensusState -ConsensusState defines a solo machine consensus state. The sequence of a consensus state -is contained in the "height" key used in storing the consensus state. +### ValidatorCurrentRewardsRecord +ValidatorCurrentRewardsRecord is used for import / export via genesis json. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `public_key` | [google.protobuf.Any](#google.protobuf.Any) | | public key of the solo machine | -| `diversifier` | [string](#string) | | diversifier allows the same public key to be re-used across different solo machine clients (potentially on different chains) without being considered misbehaviour. | -| `timestamp` | [uint64](#uint64) | | | +| `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. | - + -### ConsensusStateData -ConsensusStateData returns the SignBytes data for consensus state -verification. +### ValidatorHistoricalRewardsRecord +ValidatorHistoricalRewardsRecord is used for import / export via genesis +json. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `path` | [bytes](#bytes) | | | -| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `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. | - + -### Header -Header defines a solo machine consensus header +### ValidatorOutstandingRewardsRecord +ValidatorOutstandingRewardsRecord is used for import/export via genesis json. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `sequence` | [uint64](#uint64) | | sequence to update solo machine public key at | -| `timestamp` | [uint64](#uint64) | | | -| `signature` | [bytes](#bytes) | | | -| `new_public_key` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `new_diversifier` | [string](#string) | | | +| `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. | - + -### HeaderData -HeaderData returns the SignBytes data for update verification. +### ValidatorSlashEventRecord +ValidatorSlashEventRecord is used for import / export via genesis json. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `new_pub_key` | [google.protobuf.Any](#google.protobuf.Any) | | header public key | -| `new_diversifier` | [string](#string) | | header diversifier | - - +| `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. | - -### Misbehaviour -Misbehaviour defines misbehaviour for a solo machine which consists -of a sequence and two signatures over different messages at that sequence. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | | -| `sequence` | [uint64](#uint64) | | | -| `signature_one` | [SignatureAndData](#ibc.lightclients.solomachine.v1.SignatureAndData) | | | -| `signature_two` | [SignatureAndData](#ibc.lightclients.solomachine.v1.SignatureAndData) | | | + + + +

Top

+## cosmos/distribution/v1beta1/query.proto - -### NextSequenceRecvData -NextSequenceRecvData returns the SignBytes data for verification of the next -sequence to be received. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `path` | [bytes](#bytes) | | | -| `next_seq_recv` | [uint64](#uint64) | | | +### QueryCommunityPoolRequest +QueryCommunityPoolRequest is the request type for the Query/CommunityPool RPC +method. - + -### PacketAcknowledgementData -PacketAcknowledgementData returns the SignBytes data for acknowledgement -verification. +### QueryCommunityPoolResponse +QueryCommunityPoolResponse is the response type for the Query/CommunityPool +RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `path` | [bytes](#bytes) | | | -| `acknowledgement` | [bytes](#bytes) | | | +| `pool` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | pool defines community pool's coins. | - + -### PacketCommitmentData -PacketCommitmentData returns the SignBytes data for packet commitment -verification. +### QueryDelegationRewardsRequest +QueryDelegationRewardsRequest is the request type for the +Query/DelegationRewards RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `path` | [bytes](#bytes) | | | -| `commitment` | [bytes](#bytes) | | | +| `delegator_address` | [string](#string) | | delegator_address defines the delegator address to query for. | +| `validator_address` | [string](#string) | | validator_address defines the validator address to query for. | - + -### PacketReceiptAbsenceData -PacketReceiptAbsenceData returns the SignBytes data for -packet receipt absence verification. +### QueryDelegationRewardsResponse +QueryDelegationRewardsResponse is the response type for the +Query/DelegationRewards RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `path` | [bytes](#bytes) | | | - - +| `rewards` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | rewards defines the rewards accrued by a delegation. | - -### SignBytes -SignBytes defines the signed bytes used for signature verification. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `sequence` | [uint64](#uint64) | | | -| `timestamp` | [uint64](#uint64) | | | -| `diversifier` | [string](#string) | | | -| `data_type` | [DataType](#ibc.lightclients.solomachine.v1.DataType) | | type of the data used | -| `data` | [bytes](#bytes) | | marshaled data | +### QueryDelegationTotalRewardsRequest +QueryDelegationTotalRewardsRequest is the request type for the +Query/DelegationTotalRewards RPC method. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `delegator_address` | [string](#string) | | delegator_address defines the delegator address to query for. | - -### SignatureAndData -SignatureAndData contains a signature and the data signed over to create that -signature. + + + +### QueryDelegationTotalRewardsResponse +QueryDelegationTotalRewardsResponse is the response type for the +Query/DelegationTotalRewards RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `signature` | [bytes](#bytes) | | | -| `data_type` | [DataType](#ibc.lightclients.solomachine.v1.DataType) | | | -| `data` | [bytes](#bytes) | | | -| `timestamp` | [uint64](#uint64) | | | +| `rewards` | [DelegationDelegatorReward](#cosmos.distribution.v1beta1.DelegationDelegatorReward) | repeated | rewards defines all the rewards accrued by a delegator. | +| `total` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | total defines the sum of all the rewards. | - + -### TimestampedSignatureData -TimestampedSignatureData contains the signature data and the timestamp of the -signature. +### QueryDelegatorValidatorsRequest +QueryDelegatorValidatorsRequest is the request type for the +Query/DelegatorValidators RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `signature_data` | [bytes](#bytes) | | | -| `timestamp` | [uint64](#uint64) | | | - - - - - - +| `delegator_address` | [string](#string) | | delegator_address defines the delegator address to query for. | - -### DataType -DataType defines the type of solo machine proof being created. This is done to preserve uniqueness of different -data sign byte encodings. -| Name | Number | Description | -| ---- | ------ | ----------- | -| DATA_TYPE_UNINITIALIZED_UNSPECIFIED | 0 | Default State | -| DATA_TYPE_CLIENT_STATE | 1 | Data type for client state verification | -| DATA_TYPE_CONSENSUS_STATE | 2 | Data type for consensus state verification | -| DATA_TYPE_CONNECTION_STATE | 3 | Data type for connection state verification | -| DATA_TYPE_CHANNEL_STATE | 4 | Data type for channel state verification | -| DATA_TYPE_PACKET_COMMITMENT | 5 | Data type for packet commitment verification | -| DATA_TYPE_PACKET_ACKNOWLEDGEMENT | 6 | Data type for packet acknowledgement verification | -| DATA_TYPE_PACKET_RECEIPT_ABSENCE | 7 | Data type for packet receipt absence verification | -| DATA_TYPE_NEXT_SEQUENCE_RECV | 8 | Data type for next sequence recv verification | -| DATA_TYPE_HEADER | 9 | Data type for header verification | - + - +### QueryDelegatorValidatorsResponse +QueryDelegatorValidatorsResponse is the response type for the +Query/DelegatorValidators RPC method. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `validators` | [string](#string) | repeated | validators defines the validators a delegator is delegating for. | - -

Top

-## cosmos/upgrade/v1beta1/upgrade.proto - + -### CancelSoftwareUpgradeProposal -CancelSoftwareUpgradeProposal is a gov Content type for cancelling a software -upgrade. +### QueryDelegatorWithdrawAddressRequest +QueryDelegatorWithdrawAddressRequest is the request type for the +Query/DelegatorWithdrawAddress RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `title` | [string](#string) | | | -| `description` | [string](#string) | | | +| `delegator_address` | [string](#string) | | delegator_address defines the delegator address to query for. | - + -### Plan -Plan specifies information about a planned upgrade and when it should occur. +### QueryDelegatorWithdrawAddressResponse +QueryDelegatorWithdrawAddressResponse is the response type for the +Query/DelegatorWithdrawAddress RPC method. | 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 | - - +| `withdraw_address` | [string](#string) | | withdraw_address defines the delegator address to query for. | - -### SoftwareUpgradeProposal -SoftwareUpgradeProposal is a gov Content type for initiating a software -upgrade. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `title` | [string](#string) | | | -| `description` | [string](#string) | | | -| `plan` | [Plan](#cosmos.upgrade.v1beta1.Plan) | | | +### QueryParamsRequest +QueryParamsRequest is the request type for the Query/Params RPC method. - - + - +### QueryParamsResponse +QueryParamsResponse is the response type for the Query/Params RPC method. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `params` | [Params](#cosmos.distribution.v1beta1.Params) | | params defines the parameters of the module. | - -

Top

-## cosmos/upgrade/v1beta1/query.proto - + -### QueryAppliedPlanRequest -QueryCurrentPlanRequest is the request type for the Query/AppliedPlan RPC -method. +### QueryValidatorCommissionRequest +QueryValidatorCommissionRequest is the request type for the +Query/ValidatorCommission RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `name` | [string](#string) | | name is the name of the applied plan to query for. | +| `validator_address` | [string](#string) | | validator_address defines the validator address to query for. | - + -### QueryAppliedPlanResponse -QueryAppliedPlanResponse is the response type for the Query/AppliedPlan RPC -method. +### QueryValidatorCommissionResponse +QueryValidatorCommissionResponse is the response type for the +Query/ValidatorCommission RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `height` | [int64](#int64) | | height is the block height at which the plan was applied. | +| `commission` | [ValidatorAccumulatedCommission](#cosmos.distribution.v1beta1.ValidatorAccumulatedCommission) | | commission defines the commision the validator received. | - + -### QueryCurrentPlanRequest -QueryCurrentPlanRequest is the request type for the Query/CurrentPlan RPC -method. +### QueryValidatorOutstandingRewardsRequest +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. | - -### QueryCurrentPlanResponse -QueryCurrentPlanResponse is the response type for the Query/CurrentPlan RPC -method. + + + +### QueryValidatorOutstandingRewardsResponse +QueryValidatorOutstandingRewardsResponse is the response type for the +Query/ValidatorOutstandingRewards RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `plan` | [Plan](#cosmos.upgrade.v1beta1.Plan) | | plan is the current upgrade plan. | +| `rewards` | [ValidatorOutstandingRewards](#cosmos.distribution.v1beta1.ValidatorOutstandingRewards) | | | - + -### QueryUpgradedConsensusStateRequest -QueryUpgradedConsensusStateRequest is the request type for the Query/UpgradedConsensusState -RPC method. +### QueryValidatorSlashesRequest +QueryValidatorSlashesRequest is the request type for the +Query/ValidatorSlashes RPC method | 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 | +| `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. | - + -### QueryUpgradedConsensusStateResponse -QueryUpgradedConsensusStateResponse is the response type for the Query/UpgradedConsensusState -RPC method. +### QueryValidatorSlashesResponse +QueryValidatorSlashesResponse is the response type for the +Query/ValidatorSlashes RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `upgraded_consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `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. | @@ -3927,170 +3814,135 @@ RPC method. - + ### Query -Query defines the gRPC upgrade querier service. +Query defines the gRPC querier service for distribution module. | 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}| +| `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/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) | | | - - - +## cosmos/distribution/v1beta1/tx.proto - + -### CapabilityOwners -CapabilityOwners defines a set of owners of a single Capability. The set of -owners must be unique. +### MsgFundCommunityPool +MsgFundCommunityPool allows an account to directly +fund the community pool. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `owners` | [Owner](#cosmos.capability.v1beta1.Owner) | repeated | | - - - - - +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `depositor` | [string](#string) | | | - -### Owner -Owner defines a single capability owner. An owner is defined by the name of -capability and the module name. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `module` | [string](#string) | | | -| `name` | [string](#string) | | | + +### MsgFundCommunityPoolResponse +MsgFundCommunityPoolResponse defines the Msg/FundCommunityPool response type. - - - - + +### MsgSetWithdrawAddress +MsgSetWithdrawAddress sets the withdraw address for +a delegator (or validator self-delegation). - -

Top

-## cosmos/capability/v1beta1/genesis.proto +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `delegator_address` | [string](#string) | | | +| `withdraw_address` | [string](#string) | | | - -### 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. | + +### MsgSetWithdrawAddressResponse +MsgSetWithdrawAddressResponse defines the Msg/SetWithdrawAddress response type. - -### GenesisState -GenesisState defines the capability module's genesis state. + + +### MsgWithdrawDelegatorReward +MsgWithdrawDelegatorReward represents delegation withdrawal to a delegator +from a single validator. | 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. | - - +| `delegator_address` | [string](#string) | | | +| `validator_address` | [string](#string) | | | - - - - + +### MsgWithdrawDelegatorRewardResponse +MsgWithdrawDelegatorRewardResponse defines the Msg/WithdrawDelegatorReward response type. - -

Top

-## cosmos/params/v1beta1/params.proto - + -### ParamChange -ParamChange defines an individual parameter change, for use in -ParameterChangeProposal. +### MsgWithdrawValidatorCommission +MsgWithdrawValidatorCommission withdraws the full commission to the validator +address. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `subspace` | [string](#string) | | | -| `key` | [string](#string) | | | -| `value` | [string](#string) | | | - - +| `validator_address` | [string](#string) | | | - -### 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 | | +### MsgWithdrawValidatorCommissionResponse +MsgWithdrawValidatorCommissionResponse defines the Msg/WithdrawValidatorCommission response type. @@ -4102,42 +3954,43 @@ ParameterChangeProposal defines a proposal to change one or more parameters. - - - - - -

Top

- -## cosmos/params/v1beta1/query.proto - + - +### Msg +Msg defines the distribution Msg service. -### QueryParamsRequest -QueryParamsRequest is request type for the Query/Params RPC method. +| 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. | | + -| 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. | + +

Top

+## cosmos/evidence/v1beta1/evidence.proto - + -### QueryParamsResponse -QueryParamsResponse is response type for the Query/Params RPC method. +### Equivocation +Equivocation implements the Evidence interface and defines evidence of double +signing misbehavior. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `param` | [ParamChange](#cosmos.params.v1beta1.ParamChange) | | param defines the queried parameter. | +| `height` | [int64](#int64) | | | +| `time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `power` | [int64](#int64) | | | +| `consensus_address` | [string](#string) | | | @@ -4149,111 +4002,105 @@ 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/authz/v1beta1/tx.proto +## cosmos/evidence/v1beta1/genesis.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. +### GenesisState +GenesisState defines the evidence module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `grantee` | [string](#string) | | | -| `msgs` | [google.protobuf.Any](#google.protobuf.Any) | repeated | | +| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | repeated | evidence defines all the evidence at genesis. | + - + -### MsgExecAuthorizedResponse -MsgExecAuthorizedResponse defines the Msg/MsgExecAuthorizedResponse response type. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `result` | [cosmos.base.abci.v1beta1.Result](#cosmos.base.abci.v1beta1.Result) | | | + +

Top

+## cosmos/evidence/v1beta1/query.proto - + -### MsgGrantAuthorizationRequest -MsgGrantAuthorizationRequest grants the provided authorization to the grantee on the granter's -account with the provided expiration time. +### QueryAllEvidenceRequest +QueryEvidenceRequest is the request type for the Query/AllEvidence RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | -| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | - + -### MsgGrantAuthorizationResponse -MsgGrantAuthorizationResponse defines the Msg/MsgGrantAuthorization 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. | - -### MsgRevokeAuthorizationRequest -MsgRevokeAuthorizationRequest revokes any authorization with the provided sdk.Msg type on the -granter's account with that has been granted to the grantee. + + + +### QueryEvidenceRequest +QueryEvidenceRequest is the request type for the Query/Evidence RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | -| `method_name` | [string](#string) | | | +| `evidence_hash` | [bytes](#bytes) | | evidence_hash defines the hash of the requested evidence. | - + -### MsgRevokeAuthorizationResponse -MsgRevokeAuthorizationResponse defines the Msg/MsgRevokeAuthorizationResponse 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. | @@ -4266,55 +4113,53 @@ MsgRevokeAuthorizationResponse defines the Msg/MsgRevokeAuthorizationResponse re - + -### Msg -Msg defines the authz Msg service. +### Query +Query defines the gRPC querier 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. | | +| `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/authz/v1beta1/authz.proto +## cosmos/evidence/v1beta1/tx.proto - + -### AuthorizationGrant -AuthorizationGrant gives permissions to execute -the provide method with expiration time. +### MsgSubmitEvidence +MsgSubmitEvidence represents a message that supports submitting arbitrary +Evidence of misbehavior such as equivocation or counterfactual signing. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `submitter` | [string](#string) | | | +| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | | | - + -### GenericAuthorization -GenericAuthorization gives the grantee unrestricted permissions to execute -the provided method on behalf of the granter's account. +### MsgSubmitEvidenceResponse +MsgSubmitEvidenceResponse defines the Msg/SubmitEvidence response type. | 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` | +| `hash` | [bytes](#bytes) | | hash defines the hash of the evidence. | @@ -4326,76 +4171,109 @@ the provided method on behalf of the granter's account. + + + +### 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/authz/v1beta1/query.proto +## 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 | +| ----- | ---- | ----- | ----------- | +| `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 | + + - -### QueryAuthorizationRequest -QueryAuthorizationRequest is the request type for the Query/Authorization RPC method. + + +### 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 | | ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | -| `method_name` | [string](#string) | | | +| `duration` | [google.protobuf.Duration](#google.protobuf.Duration) | | | +| `blocks` | [uint64](#uint64) | | | - + -### QueryAuthorizationResponse -QueryAuthorizationResponse is the response type for the Query/Authorization RPC method. +### ExpiresAt +ExpiresAt is a point in time where something expires. +It may be *either* block time or block height | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `authorization` | [AuthorizationGrant](#cosmos.authz.v1beta1.AuthorizationGrant) | | authorization is a authorization granted for grantee by granter. | +| `time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `height` | [int64](#int64) | | | - + -### QueryAuthorizationsRequest -QueryAuthorizationsRequest is the request type for the Query/Authorizations RPC method. +### FeeAllowanceGrant +FeeAllowanceGrant is stored in the KVStore to record a grant with full context | 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. | +| `allowance` | [google.protobuf.Any](#google.protobuf.Any) | | | - + -### QueryAuthorizationsResponse -QueryAuthorizationsResponse is the response type for the Query/Authorizations RPC method. +### PeriodicFeeAllowance +PeriodicFeeAllowance extends FeeAllowance to allow for both a maximum cap, +as well as a limit per time period. | 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. | +| `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 | @@ -4407,55 +4285,26 @@ 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/authz/v1beta1/genesis.proto +## cosmos/feegrant/v1beta1/genesis.proto - + ### GenesisState -GenesisState defines the authz module's genesis state. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `authorization` | [GrantAuthorization](#cosmos.authz.v1beta1.GrantAuthorization) | repeated | | - - - - - - - - -### GrantAuthorization -GrantAuthorization defines the GenesisState/GrantAuthorization type. +GenesisState contains a set of fee allowances, persisted from the store | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | -| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `fee_allowances` | [FeeAllowanceGrant](#cosmos.feegrant.v1beta1.FeeAllowanceGrant) | repeated | | @@ -4471,84 +4320,70 @@ GrantAuthorization defines the GenesisState/GrantAuthorization type. - +

Top

-## cosmos/evidence/v1beta1/tx.proto +## cosmos/feegrant/v1beta1/query.proto - + -### MsgSubmitEvidence -MsgSubmitEvidence represents a message that supports submitting arbitrary -Evidence of misbehavior such as equivocation or counterfactual signing. +### QueryFeeAllowanceRequest +QueryFeeAllowanceRequest is the request type for the Query/FeeAllowance RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `submitter` | [string](#string) | | | -| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | - + -### MsgSubmitEvidenceResponse -MsgSubmitEvidenceResponse defines the Msg/SubmitEvidence response type. +### QueryFeeAllowanceResponse +QueryFeeAllowanceResponse is the response type for the Query/FeeAllowance RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `hash` | [bytes](#bytes) | | hash defines the hash of the evidence. | - - - - +| `fee_allowance` | [FeeAllowanceGrant](#cosmos.feegrant.v1beta1.FeeAllowanceGrant) | | fee_allowance is a fee_allowance granted for grantee by granter. | - - - - -### 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. | | +### 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/evidence/v1beta1/evidence.proto - + -### Equivocation -Equivocation implements the Evidence interface and defines evidence of double -signing misbehavior. +### QueryFeeAllowancesResponse +QueryFeeAllowancesResponse is the response type for the Query/FeeAllowances RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `height` | [int64](#int64) | | | -| `time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | -| `power` | [int64](#int64) | | | -| `consensus_address` | [string](#string) | | | +| `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. | @@ -4560,74 +4395,76 @@ signing misbehavior. + + + +### 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/evidence/v1beta1/query.proto +## cosmos/feegrant/v1beta1/tx.proto - + -### QueryAllEvidenceRequest -QueryEvidenceRequest is the request type for the Query/AllEvidence RPC -method. +### MsgGrantFeeAllowance +MsgGrantFeeAllowance adds permission for Grantee to spend up to Allowance +of fees from the account of Granter. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | - - +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `allowance` | [google.protobuf.Any](#google.protobuf.Any) | | | - -### 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. | +### MsgGrantFeeAllowanceResponse +MsgGrantFeeAllowanceResponse defines the Msg/GrantFeeAllowanceResponse response type. - + -### QueryEvidenceRequest -QueryEvidenceRequest is the request type for the Query/Evidence RPC method. +### MsgRevokeFeeAllowance +MsgRevokeFeeAllowance removes any existing FeeAllowance from Granter to Grantee. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `evidence_hash` | [bytes](#bytes) | | evidence_hash defines the hash of the requested evidence. | - - +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | - -### 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. | +### MsgRevokeFeeAllowanceResponse +MsgRevokeFeeAllowanceResponse defines the Msg/RevokeFeeAllowanceResponse response type. @@ -4640,36 +4477,36 @@ QueryEvidenceResponse is the response type for the Query/Evidence RPC method. - + -### Query -Query defines the gRPC querier service. +### Msg +Msg defines the feegrant msg 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| +| `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/evidence/v1beta1/genesis.proto +## cosmos/genutil/v1beta1/genesis.proto - + ### GenesisState -GenesisState defines the evidence module's genesis state. +GenesisState defines the raw genesis transaction in JSON. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | repeated | evidence defines all the evidence at genesis. | +| `gen_txs` | [bytes](#bytes) | repeated | gen_txs defines the genesis transactions. | @@ -4685,192 +4522,202 @@ GenesisState defines the evidence module's genesis state. - +

Top

-## cosmos/tx/v1beta1/tx.proto +## cosmos/gov/v1beta1/gov.proto - + -### AuthInfo -AuthInfo describes the fee and signer modes that are used to sign a -transaction. +### Deposit +Deposit defines an amount deposited by an account address to an active +proposal. | 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. | +| `proposal_id` | [uint64](#uint64) | | | +| `depositor` | [string](#string) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | - + -### 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. +### DepositParams +DepositParams defines the params for deposits on governance proposals. -| 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 | +| 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. | - + -### ModeInfo -ModeInfo describes the signing mode of a single or nested multisig signer. +### Proposal +Proposal defines the core field members of a governance proposal. | 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 | +| `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) | | | - + -### ModeInfo.Multi -Multi is the mode info for a multisig public key +### TallyParams +TallyParams defines the params for tallying votes on governance proposals. | 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 | +| `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. | - + -### 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 +### TallyResult +TallyResult defines a standard tally for a governance proposal. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `mode` | [cosmos.tx.signing.v1beta1.SignMode](#cosmos.tx.signing.v1beta1.SignMode) | | mode is the signing mode of the single signer | +| `yes` | [string](#string) | | | +| `abstain` | [string](#string) | | | +| `no` | [string](#string) | | | +| `no_with_veto` | [string](#string) | | | - + -### SignDoc -SignDoc is the type used for generating sign bytes for SIGN_MODE_DIRECT. +### TextProposal +TextProposal defines a standard text proposal whose changes need to be +manually updated in case of approval. | 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 | +| `title` | [string](#string) | | | +| `description` | [string](#string) | | | - + -### SignerInfo -SignerInfo describes the public key and signing mode of a single top-level -signer. +### 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 | | ----- | ---- | ----- | ----------- | -| `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. | +| `proposal_id` | [uint64](#uint64) | | | +| `voter` | [string](#string) | | | +| `options` | [WeightedVoteOption](#cosmos.gov.v1beta1.WeightedVoteOption) | repeated | | - + -### Tx -Tx is the standard type used for broadcasting transactions. +### VotingParams +VotingParams defines the params for voting on governance proposals. | 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. | +| `voting_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | Length of the voting period. | - + -### TxBody -TxBody is the body of a transaction that all signers sign over. +### WeightedVoteOption +WeightedVoteOption defines a unit of vote for vote split. | 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 | +| `option` | [VoteOption](#cosmos.gov.v1beta1.VoteOption) | | | +| `weight` | [string](#string) | | | + - -### 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. + +### ProposalStatus +ProposalStatus enumerates the valid statuses of a proposal. -| 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. | +| 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. | - @@ -4880,314 +4727,297 @@ as the transaction ID. - +

Top

-## cosmos/tx/v1beta1/service.proto +## cosmos/gov/v1beta1/genesis.proto - + -### BroadcastTxRequest -BroadcastTxRequest is the request type for the Service.BroadcastTxRequest -RPC method. +### GenesisState +GenesisState defines the gov module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `tx_bytes` | [bytes](#bytes) | | tx_bytes is the raw transaction. | -| `mode` | [BroadcastMode](#cosmos.tx.v1beta1.BroadcastMode) | | | +| `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. | + - + -### BroadcastTxResponse -BroadcastTxResponse is the response type for the -Service.BroadcastTx method. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `tx_response` | [cosmos.base.abci.v1beta1.TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | | tx_response is the queried TxResponses. | + +

Top

+## cosmos/gov/v1beta1/query.proto - + -### GetTxRequest -GetTxRequest is the request type for the Service.GetTx -RPC method. +### QueryDepositRequest +QueryDepositRequest is the request type for the Query/Deposit RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `hash` | [string](#string) | | hash is the tx hash to query, encoded as a hex string. | +| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | +| `depositor` | [string](#string) | | depositor defines the deposit addresses from the proposals. | - + -### GetTxResponse -GetTxResponse is the response type for the Service.GetTx method. +### QueryDepositResponse +QueryDepositResponse is the response type for the Query/Deposit RPC 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. | +| `deposit` | [Deposit](#cosmos.gov.v1beta1.Deposit) | | deposit defines the requested deposit. | - + -### GetTxsEventRequest -GetTxsEventRequest is the request type for the Service.TxsByEvents -RPC method. +### QueryDepositsRequest +QueryDepositsRequest is the request type for the Query/Deposits 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. | +| `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. | - + -### GetTxsEventResponse -GetTxsEventResponse is the response type for the Service.TxsByEvents -RPC method. +### QueryDepositsResponse +QueryDepositsResponse is the response type for the Query/Deposits 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. | +| `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. | - + -### SimulateRequest -SimulateRequest is the request type for the Service.Simulate -RPC method. +### QueryParamsRequest +QueryParamsRequest is the request type for the Query/Params RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `tx` | [Tx](#cosmos.tx.v1beta1.Tx) | | tx is the transaction to simulate. | +| `params_type` | [string](#string) | | params_type defines which parameters to query for, can be one of "voting", "tallying" or "deposit". | - + -### SimulateResponse -SimulateResponse is the response type for the -Service.SimulateRPC method. +### QueryParamsResponse +QueryParamsResponse is the response type for the Query/Params RPC method. | 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. | - +| `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. | - - + -### BroadcastMode -BroadcastMode specifies the broadcast mode for the TxService.Broadcast RPC method. +### QueryProposalRequest +QueryProposalRequest is the request type for the Query/Proposal 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 | +| ----- | ---- | ----- | ----------- | +| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | - - - -### 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| + - +### QueryProposalResponse +QueryProposalResponse is the response type for the Query/Proposal RPC method. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `proposal` | [Proposal](#cosmos.gov.v1beta1.Proposal) | | | - -

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. + + +### QueryProposalsRequest +QueryProposalsRequest is the request type for the Query/Proposals RPC method. | 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. | +| `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. | - + -### SignatureDescriptor.Data -Data represents signature data +### QueryProposalsResponse +QueryProposalsResponse is the response type for the Query/Proposals RPC +method. | 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 | +| `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. | - + -### SignatureDescriptor.Data.Multi -Multi is the signature data for a multisig public key +### QueryTallyResultRequest +QueryTallyResultRequest is the request type for the Query/Tally RPC method. | 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 | +| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | - + -### SignatureDescriptor.Data.Single -Single is the signature data for a single signer +### QueryTallyResultResponse +QueryTallyResultResponse is the response type for the Query/Tally RPC method. | 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 | +| `tally` | [TallyResult](#cosmos.gov.v1beta1.TallyResult) | | tally defines the requested tally. | - + -### SignatureDescriptors -SignatureDescriptors wraps multiple SignatureDescriptor's. +### QueryVoteRequest +QueryVoteRequest is the request type for the Query/Vote RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `signatures` | [SignatureDescriptor](#cosmos.tx.signing.v1beta1.SignatureDescriptor) | repeated | signatures are the signature descriptors | +| `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. -### 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 | +| ----- | ---- | ----- | ----------- | +| `vote` | [Vote](#cosmos.gov.v1beta1.Vote) | | vote defined the queried vote. | - - - + - -

Top

+### QueryVotesRequest +QueryVotesRequest is the request type for the Query/Votes RPC method. -## cosmos/crypto/multisig/keys.proto +| 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. | - -### LegacyAminoPubKey -LegacyAminoPubKey specifies a public key type -which nests multiple public keys and a threshold, -it uses legacy amino address rules. + + + + + +### QueryVotesResponse +QueryVotesResponse is the response type for the Query/Votes RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `threshold` | [uint32](#uint32) | | | -| `public_keys` | [google.protobuf.Any](#google.protobuf.Any) | 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. | @@ -5199,148 +5029,142 @@ it uses legacy amino address rules. + + + +### 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/crypto/multisig/v1beta1/multisig.proto +## cosmos/gov/v1beta1/tx.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. +### MsgDeposit +MsgDeposit defines a message to submit a deposit to an existing proposal. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `extra_bits_stored` | [uint32](#uint32) | | | -| `elems` | [bytes](#bytes) | | | - - +| `proposal_id` | [uint64](#uint64) | | | +| `depositor` | [string](#string) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | 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. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `signatures` | [bytes](#bytes) | repeated | | +### 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/crypto/secp256k1/keys.proto - + -### PrivKey -PrivKey defines a secp256k1 private key. +### MsgSubmitProposalResponse +MsgSubmitProposalResponse defines the Msg/SubmitProposal response type. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | | +| `proposal_id` | [uint64](#uint64) | | | - + -### 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. +### MsgVote +MsgVote defines a message to cast a vote. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | | - - +| `proposal_id` | [uint64](#uint64) | | | +| `voter` | [string](#string) | | | +| `option` | [VoteOption](#cosmos.gov.v1beta1.VoteOption) | | | - - - - + +### MsgVoteResponse +MsgVoteResponse defines the Msg/Vote response type. - -

Top

-## cosmos/crypto/ed25519/keys.proto - + -### PrivKey -Deprecated: PrivKey defines a ed25519 private key. -NOTE: ed25519 keys must not be used in SDK apps except in a tendermint validator context. +### MsgVoteWeighted +MsgVote defines a message to cast a vote. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | | - - +| `proposal_id` | [uint64](#uint64) | | | +| `voter` | [string](#string) | | | +| `options` | [WeightedVoteOption](#cosmos.gov.v1beta1.WeightedVoteOption) | repeated | | - -### PubKey -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 | -| ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | | +### MsgVoteWeightedResponse +MsgVoteWeightedResponse defines the Msg/VoteWeighted response type. @@ -5352,383 +5176,362 @@ then you must create a new proto message and follow ADR-28 for Address construct + + + +### 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. | | +| `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. | | + - +

Top

-## cosmos/staking/v1beta1/staking.proto - +## cosmos/mint/v1beta1/mint.proto - -### Commission -Commission defines commission parameters for a given validator. + + +### Minter +Minter represents the minting state. | 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. | +| `inflation` | [string](#string) | | current annual inflation rate | +| `annual_provisions` | [string](#string) | | current annual expected provisions | - + -### CommissionRates -CommissionRates defines the initial commission rates to be used for creating -a validator. +### Params +Params holds parameters for the mint module. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `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. | +| `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 | + - + -### 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 | -| ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `validator_address` | [string](#string) | | | + +

Top

+## cosmos/mint/v1beta1/genesis.proto - + -### DVPairs -DVPairs defines an array of DVPair objects. +### GenesisState +GenesisState defines the mint module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `pairs` | [DVPair](#cosmos.staking.v1beta1.DVPair) | repeated | | - - +| `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. | - -### 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 | -| ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `validator_src_address` | [string](#string) | | | -| `validator_dst_address` | [string](#string) | | | + + + +

Top

+## cosmos/mint/v1beta1/query.proto - -### DVVTriplets -DVVTriplets defines an array of DVVTriplet objects. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `triplets` | [DVVTriplet](#cosmos.staking.v1beta1.DVVTriplet) | repeated | | +### QueryAnnualProvisionsRequest +QueryAnnualProvisionsRequest is the request type for the +Query/AnnualProvisions 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. +### QueryAnnualProvisionsResponse +QueryAnnualProvisionsResponse is the response type for the +Query/AnnualProvisions RPC method. | 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. | - - +| `annual_provisions` | [bytes](#bytes) | | annual_provisions is the current minting annual provisions value. | - -### 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) | | | +### QueryInflationRequest +QueryInflationRequest is the request type for the Query/Inflation RPC method. - + -### Description -Description defines a validator description. +### QueryInflationResponse +QueryInflationResponse is the response type for the Query/Inflation RPC +method. | 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. | - - +| `inflation` | [bytes](#bytes) | | inflation is the current minting inflation value. | - -### 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 | | +### QueryParamsRequest +QueryParamsRequest is the request type for the Query/Params RPC method. - + -### Params -Params defines the parameters for the staking module. +### QueryParamsResponse +QueryParamsResponse is the response type for the Query/Params RPC method. | 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. | +| `params` | [Params](#cosmos.mint.v1beta1.Params) | | params defines the parameters of the module. | + - + -### 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) | | | + + +### 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/params/v1beta1/params.proto - + -### Redelegation -Redelegation contains the list of a particular delegator's redelegating bonds -from a particular source validator to a particular destination validator. +### ParamChange +ParamChange defines an individual parameter change, for use in +ParameterChangeProposal. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `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 | +| `subspace` | [string](#string) | | | +| `key` | [string](#string) | | | +| `value` | [string](#string) | | | - + -### RedelegationEntry -RedelegationEntry defines a redelegation object with relevant metadata. +### ParameterChangeProposal +ParameterChangeProposal defines a proposal to change one or more parameters. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `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. | +| `title` | [string](#string) | | | +| `description` | [string](#string) | | | +| `changes` | [ParamChange](#cosmos.params.v1beta1.ParamChange) | 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. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `redelegation_entry` | [RedelegationEntry](#cosmos.staking.v1beta1.RedelegationEntry) | | | -| `balance` | [string](#string) | | | + +

Top

+## cosmos/params/v1beta1/query.proto - + -### 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. +### QueryParamsRequest +QueryParamsRequest is request type for the Query/Params RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `redelegation` | [Redelegation](#cosmos.staking.v1beta1.Redelegation) | | | -| `entries` | [RedelegationEntryResponse](#cosmos.staking.v1beta1.RedelegationEntryResponse) | repeated | | +| `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. | - + -### UnbondingDelegation -UnbondingDelegation stores all of a single delegator's unbonding bonds -for a single validator in an time-ordered list. +### QueryParamsResponse +QueryParamsResponse is response type for the Query/Params RPC method. | 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. +| `param` | [ParamChange](#cosmos.params.v1beta1.ParamChange) | | param defines the queried parameter. | -unbonding delegation entries | + + - + -### UnbondingDelegationEntry -UnbondingDelegationEntry defines an unbonding object with relevant metadata. + + +### 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| + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `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. | + +

Top

+## cosmos/slashing/v1beta1/slashing.proto - + -### ValAddresses -ValAddresses defines a repeated set of validator addresses. +### Params +Params represents the parameters used for by the slashing module. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `addresses` | [string](#string) | repeated | | +| `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 -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. +### ValidatorSigningInfo +ValidatorSigningInfo defines a validator's signing info for monitoring their +liveness activity. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `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. | +| `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`. | @@ -5736,20 +5539,6 @@ 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. | - - @@ -5758,224 +5547,179 @@ BondStatus is the status of a validator. - +

Top

-## cosmos/staking/v1beta1/tx.proto +## cosmos/slashing/v1beta1/genesis.proto - + -### MsgBeginRedelegate -MsgBeginRedelegate defines a SDK message for performing a redelegation -of coins from a delegator and source validator to a destination validator. +### GenesisState +GenesisState defines the slashing module's genesis state. | 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) | | | +| `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. | - + -### MsgBeginRedelegateResponse -MsgBeginRedelegateResponse defines the Msg/BeginRedelegate response type. +### MissedBlock +MissedBlock contains height and missed status as boolean. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `completion_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `index` | [int64](#int64) | | index is the height at which the block was missed. | +| `missed` | [bool](#bool) | | missed is the missed status. | - + -### MsgCreateValidator -MsgCreateValidator defines a SDK message for creating a new validator. +### SigningInfo +SigningInfo stores validator signing info of corresponding address. | 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. +| `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. | - + -### MsgDelegate -MsgDelegate defines a SDK message for performing a delegation of coins -from a delegator to a validator. +### ValidatorMissedBlocks +ValidatorMissedBlocks contains array of missed blocks of corresponding +address. | 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. +| `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. | + - + -### 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) | | | + +

Top

+## cosmos/slashing/v1beta1/query.proto - + -### MsgEditValidatorResponse -MsgEditValidatorResponse defines the Msg/EditValidator response type. +### QueryParamsRequest +QueryParamsRequest is the request type for the Query/Params RPC method - + -### MsgUndelegate -MsgUndelegate defines a SDK message for performing an undelegation from a -delegate and a validator. +### QueryParamsResponse +QueryParamsResponse is the response type for the Query/Params RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `validator_address` | [string](#string) | | | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | +| `params` | [Params](#cosmos.slashing.v1beta1.Params) | | | - + -### MsgUndelegateResponse -MsgUndelegateResponse defines the Msg/Undelegate response type. +### QuerySigningInfoRequest +QuerySigningInfoRequest is the request type for the Query/SigningInfo RPC +method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `completion_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | - - - - +| `cons_address` | [string](#string) | | cons_address is the address to query signing info of | - - - - -### 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. | | +### QuerySigningInfoResponse +QuerySigningInfoResponse is the response type for the Query/SigningInfo RPC +method - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `val_signing_info` | [ValidatorSigningInfo](#cosmos.slashing.v1beta1.ValidatorSigningInfo) | | val_signing_info is the signing info of requested val cons address | - -

Top

-## cosmos/staking/v1beta1/authz.proto - + -### StakeAuthorization -StakeAuthorization defines authorization for delegate/undelegate/redelegate. +### QuerySigningInfosRequest +QuerySigningInfosRequest is the request type for the Query/SigningInfos RPC +method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `max_tokens` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | max_tokens specifies the maximum amount of tokens can be delegate to a validator. If it is empty, there is no spend limit and any amount of coins can be delegated. | -| `allow_list` | [StakeAuthorization.Validators](#cosmos.staking.v1beta1.StakeAuthorization.Validators) | | allow_list specifies list of validator addresses to whom grantee can delegate tokens on behalf of granter's account. | -| `deny_list` | [StakeAuthorization.Validators](#cosmos.staking.v1beta1.StakeAuthorization.Validators) | | deny_list specifies list of validator addresses to whom grantee can not delegate tokens. | -| `authorization_type` | [AuthorizationType](#cosmos.staking.v1beta1.AuthorizationType) | | authorization_type defines one of AuthorizationType. | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | | - + -### StakeAuthorization.Validators -Validators defines list of validator addresses. +### QuerySigningInfosResponse +QuerySigningInfosResponse is the response type for the Query/SigningInfos RPC +method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | repeated | | +| `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) | | | @@ -5983,476 +5727,513 @@ Validators defines list of validator addresses. + - - -### AuthorizationType -AuthorizationType defines the type of staking module authorization type + -| Name | Number | Description | -| ---- | ------ | ----------- | -| AUTHORIZATION_TYPE_UNSPECIFIED | 0 | AUTHORIZATION_TYPE_UNSPECIFIED specifies an unknown authorization type | -| AUTHORIZATION_TYPE_DELEGATE | 1 | AUTHORIZATION_TYPE_DELEGATE defines an authorization type for Msg/Delegate | -| AUTHORIZATION_TYPE_UNDELEGATE | 2 | AUTHORIZATION_TYPE_UNDELEGATE defines an authorization type for Msg/Undelegate | -| AUTHORIZATION_TYPE_REDELEGATE | 3 | AUTHORIZATION_TYPE_REDELEGATE defines an authorization type for Msg/BeginRedelegate | + - +### 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| - +

Top

-## cosmos/staking/v1beta1/query.proto +## cosmos/slashing/v1beta1/tx.proto - + -### QueryDelegationRequest -QueryDelegationRequest is request type for the Query/Delegation RPC method. +### MsgUnjail +MsgUnjail defines the Msg/Unjail request type | 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. | +| `validator_addr` | [string](#string) | | | - + -### QueryDelegationResponse -QueryDelegationResponse is response type for the Query/Delegation RPC method. +### MsgUnjailResponse +MsgUnjailResponse defines the Msg/Unjail response type -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `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. +### 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. | | -| 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. | + + +

Top

+## cosmos/staking/v1beta1/authz.proto - -### QueryDelegatorDelegationsResponse -QueryDelegatorDelegationsResponse is response type for the -Query/DelegatorDelegations RPC method. + + +### StakeAuthorization +StakeAuthorization defines authorization for delegate/undelegate/redelegate. | 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. | +| `max_tokens` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | max_tokens specifies the maximum amount of tokens can be delegate to a validator. If it is empty, there is no spend limit and any amount of coins can be delegated. | +| `allow_list` | [StakeAuthorization.Validators](#cosmos.staking.v1beta1.StakeAuthorization.Validators) | | allow_list specifies list of validator addresses to whom grantee can delegate tokens on behalf of granter's account. | +| `deny_list` | [StakeAuthorization.Validators](#cosmos.staking.v1beta1.StakeAuthorization.Validators) | | deny_list specifies list of validator addresses to whom grantee can not delegate tokens. | +| `authorization_type` | [AuthorizationType](#cosmos.staking.v1beta1.AuthorizationType) | | authorization_type defines one of AuthorizationType. | - + -### QueryDelegatorUnbondingDelegationsRequest -QueryDelegatorUnbondingDelegationsRequest is request type for the -Query/DelegatorUnbondingDelegations RPC method. +### StakeAuthorization.Validators +Validators defines list of validator addresses. | 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. | - - - - +| `address` | [string](#string) | repeated | | - -### 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. | + + +### AuthorizationType +AuthorizationType defines the type of staking module authorization type +| Name | Number | Description | +| ---- | ------ | ----------- | +| AUTHORIZATION_TYPE_UNSPECIFIED | 0 | AUTHORIZATION_TYPE_UNSPECIFIED specifies an unknown authorization type | +| AUTHORIZATION_TYPE_DELEGATE | 1 | AUTHORIZATION_TYPE_DELEGATE defines an authorization type for Msg/Delegate | +| AUTHORIZATION_TYPE_UNDELEGATE | 2 | AUTHORIZATION_TYPE_UNDELEGATE defines an authorization type for Msg/Undelegate | +| AUTHORIZATION_TYPE_REDELEGATE | 3 | AUTHORIZATION_TYPE_REDELEGATE defines an authorization type for Msg/BeginRedelegate | - + -### QueryDelegatorValidatorRequest -QueryDelegatorValidatorRequest is request type for the -Query/DelegatorValidator 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. | + +

Top

+## cosmos/staking/v1beta1/staking.proto - + -### QueryDelegatorValidatorResponse -QueryDelegatorValidatorResponse response type for the -Query/DelegatorValidator RPC method. +### Commission +Commission defines commission parameters for a given validator. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator` | [Validator](#cosmos.staking.v1beta1.Validator) | | validator defines the the validator info. | +| `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. | - + -### QueryDelegatorValidatorsRequest -QueryDelegatorValidatorsRequest is request type for the -Query/DelegatorValidators RPC method. +### CommissionRates +CommissionRates defines the initial commission rates to be used for creating +a validator. | 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. | +| `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. | - + -### QueryDelegatorValidatorsResponse -QueryDelegatorValidatorsResponse is response type for the -Query/DelegatorValidators 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 | | ----- | ---- | ----- | ----------- | -| `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. | +| `delegator_address` | [string](#string) | | | +| `validator_address` | [string](#string) | | | - + -### QueryHistoricalInfoRequest -QueryHistoricalInfoRequest is request type for the Query/HistoricalInfo RPC -method. +### DVPairs +DVPairs defines an array of DVPair objects. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `height` | [int64](#int64) | | height defines at which height to query the historical info. | +| `pairs` | [DVPair](#cosmos.staking.v1beta1.DVPair) | repeated | | - + -### QueryHistoricalInfoResponse -QueryHistoricalInfoResponse is response type for the Query/HistoricalInfo 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 | | ----- | ---- | ----- | ----------- | -| `hist` | [HistoricalInfo](#cosmos.staking.v1beta1.HistoricalInfo) | | hist defines the historical info at the given height. | - - - - - - - - -### QueryParamsRequest -QueryParamsRequest is request type for the Query/Params RPC method. +| `delegator_address` | [string](#string) | | | +| `validator_src_address` | [string](#string) | | | +| `validator_dst_address` | [string](#string) | | | - + -### QueryParamsResponse -QueryParamsResponse is response type for the Query/Params RPC method. +### DVVTriplets +DVVTriplets defines an array of DVVTriplet objects. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.staking.v1beta1.Params) | | params holds all the parameters of this module. | +| `triplets` | [DVVTriplet](#cosmos.staking.v1beta1.DVVTriplet) | repeated | | - + -### QueryPoolRequest -QueryPoolRequest is request type for the Query/Pool 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 | +| ----- | ---- | ----- | ----------- | +| `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. | - + -### QueryPoolResponse -QueryPoolResponse is response type for the Query/Pool RPC 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 | | ----- | ---- | ----- | ----------- | -| `pool` | [Pool](#cosmos.staking.v1beta1.Pool) | | pool defines the pool info. | +| `delegation` | [Delegation](#cosmos.staking.v1beta1.Delegation) | | | +| `balance` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | - + -### QueryRedelegationsRequest -QueryRedelegationsRequest is request type for the Query/Redelegations RPC -method. +### Description +Description defines a validator description. | 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. | +| `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. | - + -### QueryRedelegationsResponse -QueryRedelegationsResponse is response type for the Query/Redelegations RPC -method. +### 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 | | ----- | ---- | ----- | ----------- | -| `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. | +| `header` | [tendermint.types.Header](#tendermint.types.Header) | | | +| `valset` | [Validator](#cosmos.staking.v1beta1.Validator) | repeated | | - + -### QueryUnbondingDelegationRequest -QueryUnbondingDelegationRequest is request type for the -Query/UnbondingDelegation RPC method. +### Params +Params defines the parameters for the staking module. | 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. | - +| `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. | - -### QueryUnbondingDelegationResponse -QueryDelegationResponse is response type for the Query/UnbondingDelegation -RPC method. + + +### Pool +Pool is used for tracking bonded and not-bonded token supply of the bond +denomination. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `unbond` | [UnbondingDelegation](#cosmos.staking.v1beta1.UnbondingDelegation) | | unbond defines the unbonding information of a delegation. | +| `not_bonded_tokens` | [string](#string) | | | +| `bonded_tokens` | [string](#string) | | | - + -### QueryValidatorDelegationsRequest -QueryValidatorDelegationsRequest is request type for the -Query/ValidatorDelegations RPC method +### 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 | | ----- | ---- | ----- | ----------- | -| `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) | | 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 | - -### QueryValidatorDelegationsResponse -QueryValidatorDelegationsResponse is response type for the -Query/ValidatorDelegations RPC method + + +### RedelegationEntry +RedelegationEntry defines a redelegation object with relevant metadata. | 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. | +| `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. | - + -### QueryValidatorRequest -QueryValidatorRequest is response type for the Query/Validator 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 | | ----- | ---- | ----- | ----------- | -| `validator_addr` | [string](#string) | | validator_addr defines the validator address to query for. | +| `redelegation_entry` | [RedelegationEntry](#cosmos.staking.v1beta1.RedelegationEntry) | | | +| `balance` | [string](#string) | | | - + -### QueryValidatorResponse -QueryValidatorResponse is response type for the Query/Validator 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 | | ----- | ---- | ----- | ----------- | -| `validator` | [Validator](#cosmos.staking.v1beta1.Validator) | | validator defines the the validator info. | +| `redelegation` | [Redelegation](#cosmos.staking.v1beta1.Redelegation) | | | +| `entries` | [RedelegationEntryResponse](#cosmos.staking.v1beta1.RedelegationEntryResponse) | repeated | | - + -### QueryValidatorUnbondingDelegationsRequest -QueryValidatorUnbondingDelegationsRequest is required type for the -Query/ValidatorUnbondingDelegations 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 | | ----- | ---- | ----- | ----------- | -| `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) | | 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 | - + -### QueryValidatorUnbondingDelegationsResponse -QueryValidatorUnbondingDelegationsResponse is response type for the -Query/ValidatorUnbondingDelegations RPC method. +### UnbondingDelegationEntry +UnbondingDelegationEntry defines an unbonding object with relevant metadata. | 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. | +| `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. | - + -### QueryValidatorsRequest -QueryValidatorsRequest is request type for Query/Validators RPC method. +### ValAddresses +ValAddresses defines a repeated set of validator addresses. | 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. | +| `addresses` | [string](#string) | repeated | | - + -### QueryValidatorsResponse -QueryValidatorsResponse is response type for the Query/Validators 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 | | ----- | ---- | ----- | ----------- | -| `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. | +| `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. | @@ -6460,32 +6241,23 @@ QueryValidatorsResponse is response type for the Query/Validators RPC method - - + +### 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 | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `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| + + + @@ -6545,392 +6317,454 @@ LastValidatorPower required for validator set update logic. - +

Top

-## cosmos/base/abci/v1beta1/abci.proto +## cosmos/staking/v1beta1/query.proto - + -### ABCIMessageLog -ABCIMessageLog defines a structure containing an indexed tx ABCI message log. +### QueryDelegationRequest +QueryDelegationRequest is request type for the Query/Delegation 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. | +| `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. | - + -### Attribute -Attribute defines an attribute wrapper where the key and value are -strings instead of raw bytes. +### QueryDelegationResponse +QueryDelegationResponse is response type for the Query/Delegation RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `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. | + + + + + + + + +### 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. | + + + + + + + + +### QueryDelegatorUnbondingDelegationsRequest +QueryDelegatorUnbondingDelegationsRequest is request type for the +Query/DelegatorUnbondingDelegations 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. | + + + + + + + + +### 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. | + + + + + + + + +### QueryDelegatorValidatorRequest +QueryDelegatorValidatorRequest is request type for the +Query/DelegatorValidator RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [string](#string) | | | -| `value` | [string](#string) | | | +| `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. | - + -### GasInfo -GasInfo defines tx execution gas context. +### QueryDelegatorValidatorResponse +QueryDelegatorValidatorResponse response type for the +Query/DelegatorValidator 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. | +| `validator` | [Validator](#cosmos.staking.v1beta1.Validator) | | validator defines the the validator info. | - + -### MsgData -MsgData defines the data returned in a Result object during message -execution. +### QueryDelegatorValidatorsRequest +QueryDelegatorValidatorsRequest is request type for the +Query/DelegatorValidators RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `msg_type` | [string](#string) | | | -| `data` | [bytes](#bytes) | | | +| `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. | - + -### Result -Result is the union of ResponseFormat and ResponseCheckTx. +### QueryDelegatorValidatorsResponse +QueryDelegatorValidatorsResponse is response type for the +Query/DelegatorValidators 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. | +| `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. | - + -### SearchTxsResult -SearchTxsResult defines a structure for querying txs pageable +### QueryHistoricalInfoRequest +QueryHistoricalInfoRequest is request type for the Query/HistoricalInfo 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 | +| `height` | [int64](#int64) | | height defines at which height to query the historical info. | - + -### SimulationResponse -SimulationResponse defines the response generated when a transaction is -successfully simulated. +### QueryHistoricalInfoResponse +QueryHistoricalInfoResponse is response type for the Query/HistoricalInfo RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `gas_info` | [GasInfo](#cosmos.base.abci.v1beta1.GasInfo) | | | -| `result` | [Result](#cosmos.base.abci.v1beta1.Result) | | | - - +| `hist` | [HistoricalInfo](#cosmos.staking.v1beta1.HistoricalInfo) | | hist defines the historical info at the given height. | - -### 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 | | +### QueryParamsRequest +QueryParamsRequest is request type for the Query/Params RPC method. - + -### TxMsgData -TxMsgData defines a list of MsgData. A transaction will have a MsgData object -for each message. +### QueryParamsResponse +QueryParamsResponse is response type for the Query/Params RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `data` | [MsgData](#cosmos.base.abci.v1beta1.MsgData) | repeated | | - - +| `params` | [Params](#cosmos.staking.v1beta1.Params) | | params holds all the parameters of this module. | - -### 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 | -| ----- | ---- | ----- | ----------- | -| `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. | +### QueryPoolRequest +QueryPoolRequest is request type for the Query/Pool RPC method. - - + - +### 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. | - -

Top

-## cosmos/base/kv/v1beta1/kv.proto - + -### Pair -Pair defines a key/value bytes tuple. +### QueryRedelegationsRequest +QueryRedelegationsRequest is request type for the Query/Redelegations RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | | -| `value` | [bytes](#bytes) | | | +| `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. | - + -### Pairs -Pairs defines a repeated slice of Pair objects. +### QueryRedelegationsResponse +QueryRedelegationsResponse is response type for the Query/Redelegations RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `pairs` | [Pair](#cosmos.base.kv.v1beta1.Pair) | repeated | | - +| `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. | - - - + - +### QueryUnbondingDelegationRequest +QueryUnbondingDelegationRequest is request type for the +Query/UnbondingDelegation 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. | - -

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. +### QueryUnbondingDelegationResponse +QueryDelegationResponse is response type for the Query/UnbondingDelegation +RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `denom` | [string](#string) | | | -| `amount` | [string](#string) | | | - +| `unbond` | [UnbondingDelegation](#cosmos.staking.v1beta1.UnbondingDelegation) | | unbond defines the unbonding information of a delegation. | - -### 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. +### QueryValidatorDelegationsRequest +QueryValidatorDelegationsRequest is request type for the +Query/ValidatorDelegations RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `denom` | [string](#string) | | | -| `amount` | [string](#string) | | | +| `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. | - + -### DecProto -DecProto defines a Protobuf wrapper around a Dec object. +### QueryValidatorDelegationsResponse +QueryValidatorDelegationsResponse is response type for the +Query/ValidatorDelegations RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `dec` | [string](#string) | | | +| `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. | - + -### IntProto -IntProto defines a Protobuf wrapper around an Int object. +### QueryValidatorRequest +QueryValidatorRequest is response type for the Query/Validator RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `int` | [string](#string) | | | +| `validator_addr` | [string](#string) | | validator_addr defines the validator address to query for. | - - + - +### QueryValidatorResponse +QueryValidatorResponse is response type for the Query/Validator RPC method - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `validator` | [Validator](#cosmos.staking.v1beta1.Validator) | | validator defines the the validator info. | - -

Top

-## cosmos/base/reflection/v1beta1/reflection.proto - + -### ListAllInterfacesRequest -ListAllInterfacesRequest is the request type of the ListAllInterfaces RPC. +### QueryValidatorUnbondingDelegationsRequest +QueryValidatorUnbondingDelegationsRequest is required type for the +Query/ValidatorUnbondingDelegations RPC method + + +| 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. | - + -### ListAllInterfacesResponse -ListAllInterfacesResponse is the response type of the ListAllInterfaces RPC. +### QueryValidatorUnbondingDelegationsResponse +QueryValidatorUnbondingDelegationsResponse is response type for the +Query/ValidatorUnbondingDelegations RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `interface_names` | [string](#string) | repeated | interface_names is an array of all the registered interfaces. | +| `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. | - + -### ListImplementationsRequest -ListImplementationsRequest is the request type of the ListImplementations -RPC. +### QueryValidatorsRequest +QueryValidatorsRequest is request type for Query/Validators RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `interface_name` | [string](#string) | | interface_name defines the interface to query the implementations 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. | - + -### ListImplementationsResponse -ListImplementationsResponse is the response type of the ListImplementations -RPC. +### QueryValidatorsResponse +QueryValidatorsResponse is response type for the Query/Validators RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `implementation_message_names` | [string](#string) | repeated | | +| `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. | @@ -6943,327 +6777,300 @@ RPC. - + -### ReflectionService -ReflectionService defines a service for interface reflection. +### Query +Query 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| +| `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/base/tendermint/v1beta1/query.proto +## cosmos/staking/v1beta1/tx.proto - + -### GetBlockByHeightRequest -GetBlockByHeightRequest is the request type for the Query/GetBlockByHeight RPC method. +### 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 | | ----- | ---- | ----- | ----------- | -| `height` | [int64](#int64) | | | +| `delegator_address` | [string](#string) | | | +| `validator_src_address` | [string](#string) | | | +| `validator_dst_address` | [string](#string) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | - + -### GetBlockByHeightResponse -GetBlockByHeightResponse is the response type for the Query/GetBlockByHeight RPC method. +### MsgBeginRedelegateResponse +MsgBeginRedelegateResponse defines the Msg/BeginRedelegate response type. | 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. +| `completion_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | - + -### GetLatestBlockResponse -GetLatestBlockResponse is the response type for the Query/GetLatestBlock RPC method. +### MsgCreateValidator +MsgCreateValidator defines a SDK message for creating a new validator. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `block_id` | [tendermint.types.BlockID](#tendermint.types.BlockID) | | | -| `block` | [tendermint.types.Block](#tendermint.types.Block) | | | - - +| `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) | | | - -### 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. | +### MsgCreateValidatorResponse +MsgCreateValidatorResponse defines the Msg/CreateValidator response type. - + -### GetLatestValidatorSetResponse -GetLatestValidatorSetResponse is the response type for the Query/GetValidatorSetByHeight RPC method. +### MsgDelegate +MsgDelegate defines a SDK message for performing a delegation of coins +from a delegator to a validator. | 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. | +| `delegator_address` | [string](#string) | | | +| `validator_address` | [string](#string) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | - + -### GetNodeInfoRequest -GetNodeInfoRequest is the request type for the Query/GetNodeInfo RPC method. +### MsgDelegateResponse +MsgDelegateResponse defines the Msg/Delegate response type. - + -### GetNodeInfoResponse -GetNodeInfoResponse is the request type for the Query/GetNodeInfo RPC method. +### MsgEditValidator +MsgEditValidator defines a SDK message for editing an existing validator. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `default_node_info` | [tendermint.p2p.DefaultNodeInfo](#tendermint.p2p.DefaultNodeInfo) | | | -| `application_version` | [VersionInfo](#cosmos.base.tendermint.v1beta1.VersionInfo) | | | +| `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) | | | - + -### GetSyncingRequest -GetSyncingRequest is the request type for the Query/GetSyncing RPC method. +### MsgEditValidatorResponse +MsgEditValidatorResponse defines the Msg/EditValidator response type. - + -### GetSyncingResponse -GetSyncingResponse is the response type for the Query/GetSyncing RPC method. +### MsgUndelegate +MsgUndelegate defines a SDK message for performing an undelegation from a +delegate and a validator. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `syncing` | [bool](#bool) | | | +| `delegator_address` | [string](#string) | | | +| `validator_address` | [string](#string) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | - + -### GetValidatorSetByHeightRequest -GetValidatorSetByHeightRequest is the request type for the Query/GetValidatorSetByHeight RPC method. +### MsgUndelegateResponse +MsgUndelegateResponse defines the Msg/Undelegate response type. | 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. | - - - - - +| `completion_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | - -### 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. | + + + + - +### Msg +Msg defines the staking Msg service. -### Module -Module is the type for VersionInfo +| 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. | | + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `path` | [string](#string) | | module path | -| `version` | [string](#string) | | module version | -| `sum` | [string](#string) | | checksum | + +

Top

+## cosmos/tx/signing/v1beta1/signing.proto - + -### Validator -Validator is the type for the validator-set. +### 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 | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | | -| `pub_key` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `voting_power` | [int64](#int64) | | | -| `proposer_priority` | [int64](#int64) | | | +| `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. | - + -### VersionInfo -VersionInfo is the type for the GetNodeInfoResponse message. +### SignatureDescriptor.Data +Data represents signature data | 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 | | - - - - - - +| `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 | - - - -### 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}| + - +### 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/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; - } +### SignatureDescriptor.Data.Single +Single is the signature data for a single signer | 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. | - +| `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 | - -### 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; - } +### SignatureDescriptors +SignatureDescriptors wraps multiple SignatureDescriptor's. | 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 | +| `signatures` | [SignatureDescriptor](#cosmos.tx.signing.v1beta1.SignatureDescriptor) | repeated | signatures are the signature descriptors | @@ -7271,6 +7078,20 @@ corresponding request message has used PageRequest. + + + +### 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 | + + @@ -7279,173 +7100,186 @@ corresponding request message has used PageRequest. - +

Top

-## cosmos/base/snapshots/v1beta1/snapshot.proto +## cosmos/tx/v1beta1/tx.proto - + -### Metadata -Metadata contains SDK-specific snapshot metadata. +### AuthInfo +AuthInfo describes the fee and signer modes that are used to sign a +transaction. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `chunk_hashes` | [bytes](#bytes) | repeated | SHA-256 chunk hashes | +| `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. | - + -### Snapshot -Snapshot contains Tendermint state sync snapshot info. +### 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 | | ----- | ---- | ----- | ----------- | -| `height` | [uint64](#uint64) | | | -| `format` | [uint32](#uint32) | | | -| `chunks` | [uint32](#uint32) | | | -| `hash` | [bytes](#bytes) | | | -| `metadata` | [Metadata](#cosmos.base.snapshots.v1beta1.Metadata) | | | +| `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 | - -

Top

-## cosmos/base/store/v1beta1/snapshot.proto - + -### SnapshotIAVLItem -SnapshotIAVLItem is an exported IAVL node. +### ModeInfo.Multi +Multi is the mode info for a multisig public key | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | | -| `value` | [bytes](#bytes) | | | -| `version` | [int64](#int64) | | | -| `height` | [int32](#int32) | | | +| `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 | - + -### SnapshotItem -SnapshotItem is an item contained in a rootmulti.Store snapshot. +### 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 | | ----- | ---- | ----- | ----------- | -| `store` | [SnapshotStoreItem](#cosmos.base.store.v1beta1.SnapshotStoreItem) | | | -| `iavl` | [SnapshotIAVLItem](#cosmos.base.store.v1beta1.SnapshotIAVLItem) | | | +| `mode` | [cosmos.tx.signing.v1beta1.SignMode](#cosmos.tx.signing.v1beta1.SignMode) | | mode is the signing mode of the single signer | - + -### SnapshotStoreItem -SnapshotStoreItem contains metadata about a snapshotted store. +### SignDoc +SignDoc is the type used for generating sign bytes for SIGN_MODE_DIRECT. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `name` | [string](#string) | | | +| `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. | - -

Top

-## cosmos/base/store/v1beta1/commit_info.proto - + -### CommitID -CommitID defines the committment information when a specific store is -committed. +### Tx +Tx is the standard type used for broadcasting transactions. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `version` | [int64](#int64) | | | -| `hash` | [bytes](#bytes) | | | +| `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. | - + -### CommitInfo -CommitInfo defines commit information used by the multi-store when committing -a version/height. +### TxBody +TxBody is the body of a transaction that all signers sign over. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `version` | [int64](#int64) | | | -| `store_infos` | [StoreInfo](#cosmos.base.store.v1beta1.StoreInfo) | repeated | | +| `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 | - + -### StoreInfo -StoreInfo defines store-specific commit information. It contains a reference -between a store name and the commit ID. +### 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 | | ----- | ---- | ----- | ----------- | -| `name` | [string](#string) | | | -| `commit_id` | [CommitID](#cosmos.base.store.v1beta1.CommitID) | | | +| `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. | @@ -7461,328 +7295,344 @@ between a store name and the commit ID. - +

Top

-## cosmos/bank/v1beta1/tx.proto +## cosmos/tx/v1beta1/service.proto - + -### MsgMultiSend -MsgMultiSend represents an arbitrary multi-in, multi-out send message. +### BroadcastTxRequest +BroadcastTxRequest is the request type for the Service.BroadcastTxRequest +RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `inputs` | [Input](#cosmos.bank.v1beta1.Input) | repeated | | -| `outputs` | [Output](#cosmos.bank.v1beta1.Output) | repeated | | +| `tx_bytes` | [bytes](#bytes) | | tx_bytes is the raw transaction. | +| `mode` | [BroadcastMode](#cosmos.tx.v1beta1.BroadcastMode) | | | - + -### MsgMultiSendResponse -MsgMultiSendResponse defines the Msg/MultiSend response type. +### BroadcastTxResponse +BroadcastTxResponse is the response type for the +Service.BroadcastTx method. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `tx_response` | [cosmos.base.abci.v1beta1.TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | | tx_response is the queried TxResponses. | - -### 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 | | +### GetTxRequest +GetTxRequest is the request type for the Service.GetTx +RPC method. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `hash` | [string](#string) | | hash is the tx hash to query, encoded as a hex string. | - -### MsgSendResponse -MsgSendResponse defines the Msg/Send response type. + +### 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. | - - - - -### 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. | | +### GetTxsEventRequest +GetTxsEventRequest is the request type for the Service.TxsByEvents +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. | - -

Top

-## cosmos/bank/v1beta1/authz.proto - + -### SendAuthorization -SendAuthorization allows the grantee to spend up to spend_limit coins from -the granter's account. +### GetTxsEventResponse +GetTxsEventResponse is the response type for the Service.TxsByEvents +RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `spend_limit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | 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. | - - + - +### 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/bank/v1beta1/query.proto - + -### QueryAllBalancesRequest -QueryBalanceRequest is the request type for the Query/AllBalances RPC method. +### SimulateResponse +SimulateResponse is the response type for the +Service.SimulateRPC 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. | +| `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. | + - -### QueryAllBalancesResponse -QueryAllBalancesResponse is the response type for the Query/AllBalances RPC -method. + +### BroadcastMode +BroadcastMode specifies the broadcast mode for the TxService.Broadcast 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. | +| 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. -### QueryBalanceRequest -QueryBalanceRequest is the request type for the Query/Balance RPC method. +| 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 | -| ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | address is the address to query balances for. | -| `denom` | [string](#string) | | denom is the coin denom to query balances for. | + +

Top

+## cosmos/upgrade/v1beta1/upgrade.proto - + -### QueryBalanceResponse -QueryBalanceResponse is the response type for the Query/Balance RPC method. +### CancelSoftwareUpgradeProposal +CancelSoftwareUpgradeProposal is a gov Content type for cancelling a software +upgrade. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `balance` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | balance is the balance of the coin. | +| `title` | [string](#string) | | | +| `description` | [string](#string) | | | - + -### QueryDenomMetadataRequest -QueryDenomMetadataRequest is the request type for the Query/DenomMetadata RPC method. +### Plan +Plan specifies information about a planned upgrade and when it should occur. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `denom` | [string](#string) | | denom is the coin denom to query the metadata for. | +| `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 | - + -### QueryDenomMetadataResponse -QueryDenomMetadataResponse is the response type for the Query/DenomMetadata RPC -method. +### SoftwareUpgradeProposal +SoftwareUpgradeProposal is a gov Content type for initiating a software +upgrade. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `metadata` | [Metadata](#cosmos.bank.v1beta1.Metadata) | | metadata describes and provides all the client information for the requested token. | +| `title` | [string](#string) | | | +| `description` | [string](#string) | | | +| `plan` | [Plan](#cosmos.upgrade.v1beta1.Plan) | | | + - + -### 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/upgrade/v1beta1/query.proto - + -### QueryDenomsMetadataResponse -QueryDenomsMetadataResponse is the response type for the Query/DenomsMetadata RPC +### QueryAppliedPlanRequest +QueryCurrentPlanRequest is the request type for the Query/AppliedPlan 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. | +| `name` | [string](#string) | | name is the name of the applied plan to query for. | - + -### QueryParamsRequest -QueryParamsRequest defines the request type for querying x/bank parameters. +### QueryAppliedPlanResponse +QueryAppliedPlanResponse is the response type for the Query/AppliedPlan RPC +method. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `height` | [int64](#int64) | | height is the block height at which the plan was applied. | - -### QueryParamsResponse -QueryParamsResponse defines the response type for querying x/bank parameters. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.bank.v1beta1.Params) | | | +### QueryCurrentPlanRequest +QueryCurrentPlanRequest is the request type for the Query/CurrentPlan RPC +method. - + -### QuerySupplyOfRequest -QuerySupplyOfRequest is the request type for the Query/SupplyOf RPC method. +### QueryCurrentPlanResponse +QueryCurrentPlanResponse is the response type for the Query/CurrentPlan RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `denom` | [string](#string) | | denom is the coin denom to query balances for. | +| `plan` | [Plan](#cosmos.upgrade.v1beta1.Plan) | | plan is the current upgrade plan. | - + -### QuerySupplyOfResponse -QuerySupplyOfResponse is the response type for the Query/SupplyOf RPC method. +### QueryUpgradedConsensusStateRequest +QueryUpgradedConsensusStateRequest is the request type for the Query/UpgradedConsensusState +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. +| `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 | - + -### QueryTotalSupplyResponse -QueryTotalSupplyResponse is the response type for the Query/TotalSupply RPC -method +### QueryUpgradedConsensusStateResponse +QueryUpgradedConsensusStateResponse is the response type for the Query/UpgradedConsensusState +RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `supply` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | supply is the supply of the coins | +| `upgraded_consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | | @@ -7795,144 +7645,166 @@ method - + ### Query -Query defines the gRPC querier service. +Query defines the gRPC upgrade 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| +| `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/bank/v1beta1/bank.proto +## cosmos/vesting/v1beta1/tx.proto - + -### DenomUnit -DenomUnit represents a struct that describes a given -denomination unit of the basic token. +### MsgCreateVestingAccount +MsgCreateVestingAccount defines a message that enables creating a vesting +account. | 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 | +| `from_address` | [string](#string) | | | +| `to_address` | [string](#string) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `end_time` | [int64](#int64) | | | +| `delayed` | [bool](#bool) | | | - + -### Input -Input models transaction input. +### MsgCreateVestingAccountResponse +MsgCreateVestingAccountResponse defines the Msg/CreateVestingAccount response type. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | | -| `coins` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | + + + - -### Metadata -Metadata represents a struct that describes -a basic token. + + +### Msg +Msg defines the bank Msg service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `CreateVestingAccount` | [MsgCreateVestingAccount](#cosmos.vesting.v1beta1.MsgCreateVestingAccount) | [MsgCreateVestingAccountResponse](#cosmos.vesting.v1beta1.MsgCreateVestingAccountResponse) | CreateVestingAccount defines a method that enables creating a vesting account. | | + + + + + + +

Top

+ +## cosmos/vesting/v1beta1/vesting.proto + + + + + +### BaseVestingAccount +BaseVestingAccount implements the VestingAccount interface. It contains all +the necessary fields needed for any vesting account implementation. | 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. | +| `base_account` | [cosmos.auth.v1beta1.BaseAccount](#cosmos.auth.v1beta1.BaseAccount) | | | +| `original_vesting` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `delegated_free` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `delegated_vesting` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `end_time` | [int64](#int64) | | | - + -### Output -Output models transaction outputs. +### ContinuousVestingAccount +ContinuousVestingAccount implements the VestingAccount interface. It +continuously vests by unlocking coins linearly with respect to time. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | | -| `coins` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `base_vesting_account` | [BaseVestingAccount](#cosmos.vesting.v1beta1.BaseVestingAccount) | | | +| `start_time` | [int64](#int64) | | | - + -### Params -Params defines the parameters for the bank module. +### DelayedVestingAccount +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. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `send_enabled` | [SendEnabled](#cosmos.bank.v1beta1.SendEnabled) | repeated | | -| `default_send_enabled` | [bool](#bool) | | | +| `base_vesting_account` | [BaseVestingAccount](#cosmos.vesting.v1beta1.BaseVestingAccount) | | | - + -### SendEnabled -SendEnabled maps coin denom to a send_enabled status (whether a denom is -sendable). +### Period +Period defines a length of time and amount of coins that will vest. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `denom` | [string](#string) | | | -| `enabled` | [bool](#bool) | | | +| `length` | [int64](#int64) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | - + -### Supply -Supply represents a struct that passively keeps track of the total supply -amounts in the network. +### PeriodicVestingAccount +PeriodicVestingAccount implements the VestingAccount interface. It +periodically vests by unlocking coins during each specified period. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `total` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `base_vesting_account` | [BaseVestingAccount](#cosmos.vesting.v1beta1.BaseVestingAccount) | | | +| `start_time` | [int64](#int64) | | | +| `vesting_periods` | [Period](#cosmos.vesting.v1beta1.Period) | repeated | | @@ -7948,42 +7820,63 @@ amounts in the network. - +

Top

-## cosmos/bank/v1beta1/genesis.proto +## ibc/applications/transfer/v1/transfer.proto - + -### Balance -Balance defines an account address and balance pair used in the bank module's -genesis state. +### DenomTrace +DenomTrace contains the base denomination for ICS20 fungible tokens and the +source tracing information path. | 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. | +| `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. | - + -### GenesisState -GenesisState defines the bank module's genesis state. +### 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 | | ----- | ---- | ----- | ----------- | -| `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. | +| `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. | @@ -7999,22 +7892,24 @@ GenesisState defines the bank module's genesis state. - +

Top

-## cosmos/genutil/v1beta1/genesis.proto +## ibc/applications/transfer/v1/genesis.proto - + ### GenesisState -GenesisState defines the raw genesis transaction in JSON. +GenesisState defines the ibc-transfer genesis state | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `gen_txs` | [bytes](#bytes) | repeated | gen_txs defines the genesis transactions. | +| `port_id` | [string](#string) | | | +| `denom_traces` | [DenomTrace](#ibc.applications.transfer.v1.DenomTrace) | repeated | | +| `params` | [Params](#ibc.applications.transfer.v1.Params) | | | @@ -8030,298 +7925,286 @@ GenesisState defines the raw genesis transaction in JSON. - +

Top

-## cosmos/slashing/v1beta1/slashing.proto +## ibc/applications/transfer/v1/query.proto - + -### Params -Params represents the parameters used for by the slashing module. +### QueryDenomTraceRequest +QueryDenomTraceRequest is the request type for the Query/DenomTrace RPC +method | 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) | | | +| `hash` | [string](#string) | | hash (in hex format) of the denomination trace information. | - + -### ValidatorSigningInfo -ValidatorSigningInfo defines a validator's signing info for monitoring their -liveness activity. +### QueryDenomTraceResponse +QueryDenomTraceResponse is the response type for the Query/DenomTrace RPC +method. | 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`. | +| `denom_trace` | [DenomTrace](#ibc.applications.transfer.v1.DenomTrace) | | denom_trace returns the requested denomination trace information. | - - + - +### QueryDenomTracesRequest +QueryConnectionsRequest is the request type for the Query/DenomTraces 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/slashing/v1beta1/tx.proto - + -### MsgUnjail -MsgUnjail defines the Msg/Unjail request type +### QueryDenomTracesResponse +QueryConnectionsResponse is the response type for the Query/DenomTraces RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator_addr` | [string](#string) | | | - - - - - - - - -### MsgUnjailResponse -MsgUnjailResponse defines the Msg/Unjail response type +| `denom_traces` | [DenomTrace](#ibc.applications.transfer.v1.DenomTrace) | repeated | denom_traces returns all denominations trace information. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | - - + - +### QueryParamsRequest +QueryParamsRequest is the request type for the Query/Params RPC method. - -### 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. | | - + +### QueryParamsResponse +QueryParamsResponse is the response type for the Query/Params RPC method. - -

Top

-## cosmos/slashing/v1beta1/query.proto +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `params` | [Params](#ibc.applications.transfer.v1.Params) | | params defines the parameters of the module. | - -### QueryParamsRequest -QueryParamsRequest is the request type for the Query/Params RPC method + + + + - +### Query +Query provides defines the gRPC querier service. -### QueryParamsResponse -QueryParamsResponse is the response type for the Query/Params RPC method +| 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| + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.slashing.v1beta1.Params) | | | + +

Top

+## ibc/core/client/v1/client.proto - + -### QuerySigningInfoRequest -QuerySigningInfoRequest is the request type for the Query/SigningInfo RPC -method +### ClientConsensusStates +ClientConsensusStates defines all the stored consensus states for a given +client. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `cons_address` | [string](#string) | | cons_address is the address to query signing info of | +| `client_id` | [string](#string) | | client identifier | +| `consensus_states` | [ConsensusStateWithHeight](#ibc.core.client.v1.ConsensusStateWithHeight) | repeated | consensus states and their heights associated with the client | - + -### QuerySigningInfoResponse -QuerySigningInfoResponse is the response type for the Query/SigningInfo RPC -method +### ClientUpdateProposal +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 | | ----- | ---- | ----- | ----------- | -| `val_signing_info` | [ValidatorSigningInfo](#cosmos.slashing.v1beta1.ValidatorSigningInfo) | | val_signing_info is the signing info of requested val cons address | +| `title` | [string](#string) | | the title of the update proposal | +| `description` | [string](#string) | | the description of the proposal | +| `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 | - + -### QuerySigningInfosRequest -QuerySigningInfosRequest is the request type for the Query/SigningInfos RPC -method +### ConsensusStateWithHeight +ConsensusStateWithHeight defines a consensus state with an additional height field. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | | +| `height` | [Height](#ibc.core.client.v1.Height) | | consensus state height | +| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | consensus state | - + -### QuerySigningInfosResponse -QuerySigningInfosResponse is the response type for the Query/SigningInfos RPC -method +### Height +Height is a monotonically increasing data type +that can be compared against another Height for the purposes of updating and +freezing clients + +Normally the RevisionHeight is incremented at each height while keeping RevisionNumber +the same. However some consensus algorithms may choose to reset the +height in certain conditions e.g. hard forks, state-machine breaking changes +In these cases, the RevisionNumber is incremented so that height continues to +be monitonically increasing even as the RevisionHeight gets reset | 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) | | | - - - - +| `revision_number` | [uint64](#uint64) | | the revision that the client is currently on | +| `revision_height` | [uint64](#uint64) | | the height within the given revision | - - - - -### 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| +### IdentifiedClientState +IdentifiedClientState defines a client state with an additional client +identifier field. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `client_id` | [string](#string) | | client identifier | +| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | client state | - -

Top

-## cosmos/slashing/v1beta1/genesis.proto - + -### GenesisState -GenesisState defines the slashing module's genesis state. +### Params +Params defines the set of IBC light client parameters. | 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. | +| `allowed_clients` | [string](#string) | repeated | allowed_clients defines the list of allowed client state types. | + - + -### 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

+## ibc/applications/transfer/v1/tx.proto - + -### SigningInfo -SigningInfo stores validator signing info of corresponding address. +### 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 | | ----- | ---- | ----- | ----------- | -| `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. | - - +| `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. | - -### ValidatorMissedBlocks -ValidatorMissedBlocks contains array of missed blocks of corresponding -address. + -| 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. | +### MsgTransferResponse +MsgTransferResponse defines the Msg/Transfer response type. @@ -8333,180 +8216,230 @@ address. + + + +### 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

-## cosmos/feegrant/v1beta1/tx.proto +## ibc/core/channel/v1/channel.proto - + -### MsgGrantFeeAllowance -MsgGrantFeeAllowance adds permission for Grantee to spend up to Allowance -of fees from the account of Granter. +### 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 | | ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | -| `allowance` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `result` | [bytes](#bytes) | | | +| `error` | [string](#string) | | | - + -### MsgGrantFeeAllowanceResponse -MsgGrantFeeAllowanceResponse defines the Msg/GrantFeeAllowanceResponse response type. +### 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 | +| ----- | ---- | ----- | ----------- | +| `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 | - + -### MsgRevokeFeeAllowance -MsgRevokeFeeAllowance removes any existing FeeAllowance from Granter to Grantee. +### Counterparty +Counterparty defines a channel end counterparty | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | - - +| `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 | - -### MsgRevokeFeeAllowanceResponse -MsgRevokeFeeAllowanceResponse defines the Msg/RevokeFeeAllowanceResponse response type. + +### IdentifiedChannel +IdentifiedChannel defines a channel with additional port and channel +identifier fields. +| 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 | - - - - -### 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. | | +### Packet +Packet defines a type that carries data across different chains through IBC - +| 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 | - -

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. +### 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 | | ----- | ---- | ----- | ----------- | -| `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 | +| `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. | + - -### Duration -Duration is a span of a clock time or number of blocks. -This is designed to be added to an ExpiresAt struct. + + +### 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 | -| ----- | ---- | ----- | ----------- | -| `duration` | [google.protobuf.Duration](#google.protobuf.Duration) | | | -| `blocks` | [uint64](#uint64) | | | + +### 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. | - + -### ExpiresAt -ExpiresAt is a point in time where something expires. -It may be *either* block time or block height + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | -| `height` | [int64](#int64) | | | + +

Top

+## ibc/core/channel/v1/genesis.proto - + -### FeeAllowanceGrant -FeeAllowanceGrant is stored in the KVStore to record a grant with full context +### GenesisState +GenesisState defines the ibc channel submodule's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | -| `allowance` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `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 | - + -### PeriodicFeeAllowance -PeriodicFeeAllowance extends FeeAllowance to allow for both a maximum cap, -as well as a limit per time period. +### PacketSequence +PacketSequence defines the genesis type necessary to retrieve and store +next send and receive sequences. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `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 | +| `port_id` | [string](#string) | | | +| `channel_id` | [string](#string) | | | +| `sequence` | [uint64](#uint64) | | | @@ -8522,999 +8455,1073 @@ as well as a limit per time period. - +

Top

-## cosmos/feegrant/v1beta1/query.proto +## ibc/core/channel/v1/query.proto - + -### QueryFeeAllowanceRequest -QueryFeeAllowanceRequest is the request type for the Query/FeeAllowance RPC method. +### QueryChannelClientStateRequest +QueryChannelClientStateRequest is the request type for the Query/ClientState +RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | +| `port_id` | [string](#string) | | port unique identifier | +| `channel_id` | [string](#string) | | channel unique identifier | - + -### QueryFeeAllowanceResponse -QueryFeeAllowanceResponse is the response type for the Query/FeeAllowance RPC method. +### QueryChannelClientStateResponse +QueryChannelClientStateResponse is the Response type for the +Query/QueryChannelClientState RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `fee_allowance` | [FeeAllowanceGrant](#cosmos.feegrant.v1beta1.FeeAllowanceGrant) | | fee_allowance is a fee_allowance granted for grantee by granter. | +| `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 | - + -### QueryFeeAllowancesRequest -QueryFeeAllowancesRequest is the request type for the Query/FeeAllowances RPC method. +### QueryChannelConsensusStateRequest +QueryChannelConsensusStateRequest is the request type for the +Query/ConsensusState 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. | +| `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 | - + -### QueryFeeAllowancesResponse -QueryFeeAllowancesResponse is the response type for the Query/FeeAllowances RPC method. +### QueryChannelConsensusStateResponse +QueryChannelClientStateResponse is the Response type for the +Query/QueryChannelClientState RPC method | 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. | +| `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 | - - + - +### 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 | -### 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/genesis.proto +### 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 | - -### GenesisState -GenesisState contains a set of fee allowances, persisted from the store + + + + +### QueryChannelsRequest +QueryChannelsRequest is the request type for the Query/Channels 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 request | - - + - +### 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

-## 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). +### QueryConnectionChannelsRequest +QueryConnectionChannelsRequest is the request type for the +Query/QueryConnectionChannels RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | | -| `pub_key` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `account_number` | [uint64](#uint64) | | | -| `sequence` | [uint64](#uint64) | | | +| `connection` | [string](#string) | | connection unique identifier | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | - + -### ModuleAccount -ModuleAccount defines an account for modules that holds coins on a pool. +### QueryConnectionChannelsResponse +QueryConnectionChannelsResponse is the Response type for the +Query/QueryConnectionChannels RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `base_account` | [BaseAccount](#cosmos.auth.v1beta1.BaseAccount) | | | -| `name` | [string](#string) | | | -| `permissions` | [string](#string) | repeated | | +| `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 | - + -### Params -Params defines the parameters for the auth module. +### QueryNextSequenceReceiveRequest +QueryNextSequenceReceiveRequest is the request type for the +Query/QueryNextSequenceReceiveRequest 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) | | | +| `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

-## cosmos/auth/v1beta1/query.proto - + -### QueryAccountRequest -QueryAccountRequest is the request type for the Query/Account RPC method. +### QueryPacketAcknowledgementRequest +QueryPacketAcknowledgementRequest is the request type for the +Query/PacketAcknowledgement RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | address defines the address to query for. | +| `port_id` | [string](#string) | | port unique identifier | +| `channel_id` | [string](#string) | | channel unique identifier | +| `sequence` | [uint64](#uint64) | | packet sequence | - + -### QueryAccountResponse -QueryAccountResponse is the response type for the Query/Account RPC method. +### 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 | | ----- | ---- | ----- | ----------- | -| `account` | [google.protobuf.Any](#google.protobuf.Any) | | account defines the account of the corresponding address. | +| `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 | + + + + + + + + +### QueryPacketAcknowledgementsRequest +QueryPacketAcknowledgementsRequest is the request type for the +Query/QueryPacketCommitments RPC method +| 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 | - -### QueryParamsRequest -QueryParamsRequest is the request type for the Query/Params RPC method. + +### 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 | - -### QueryParamsResponse -QueryParamsResponse is the 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. | + +### QueryPacketCommitmentRequest +QueryPacketCommitmentRequest is the request type for the +Query/PacketCommitment 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 | - - - - -### 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| +### 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 | - -

Top

-## cosmos/auth/v1beta1/genesis.proto - + -### GenesisState -GenesisState defines the auth module's genesis state. +### QueryPacketCommitmentsRequest +QueryPacketCommitmentsRequest is the request type for the +Query/QueryPacketCommitments 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. | +| `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 | - - + - +### 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

-## cosmos/crisis/v1beta1/tx.proto - + -### MsgVerifyInvariant -MsgVerifyInvariant represents a message to verify a particular invariance. +### QueryPacketReceiptRequest +QueryPacketReceiptRequest is the request type for the +Query/PacketReceipt RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `sender` | [string](#string) | | | -| `invariant_module_name` | [string](#string) | | | -| `invariant_route` | [string](#string) | | | - - +| `port_id` | [string](#string) | | port unique identifier | +| `channel_id` | [string](#string) | | channel unique identifier | +| `sequence` | [uint64](#uint64) | | packet sequence | - -### MsgVerifyInvariantResponse -MsgVerifyInvariantResponse defines the Msg/VerifyInvariant 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 | - - - - -### 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. | | +### 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 | +| `packet_ack_sequences` | [uint64](#uint64) | repeated | list of acknowledgement sequences | - -

Top

-## cosmos/crisis/v1beta1/genesis.proto - + -### GenesisState -GenesisState defines the crisis module's genesis state. +### QueryUnreceivedAcksResponse +QueryUnreceivedAcksResponse is the response type for the +Query/UnreceivedAcks RPC method | 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. | +| `sequences` | [uint64](#uint64) | repeated | list of unreceived acknowledgement sequences | +| `height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | query block height | - - + - +### 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 | - -

Top

-## cosmos/gov/v1beta1/gov.proto - + -### Deposit -Deposit defines an amount deposited by an account address to an active -proposal. +### QueryUnreceivedPacketsResponse +QueryUnreceivedPacketsResponse is the response type for the +Query/UnreceivedPacketCommitments RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | | -| `depositor` | [string](#string) | | | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `sequences` | [uint64](#uint64) | repeated | list of unreceived packet sequences | +| `height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | query block height | + - + -### 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. | + + +### 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

+## ibc/core/channel/v1/tx.proto - -### Proposal -Proposal defines the core field members of a governance proposal. + -| 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) | | | +### 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) | | | - -### 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. | +### MsgAcknowledgementResponse +MsgAcknowledgementResponse defines the Msg/Acknowledgement response type. - + -### TallyResult -TallyResult defines a standard tally for a governance proposal. +### 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 | | ----- | ---- | ----- | ----------- | -| `yes` | [string](#string) | | | -| `abstain` | [string](#string) | | | -| `no` | [string](#string) | | | -| `no_with_veto` | [string](#string) | | | - - +| `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) | | | - -### TextProposal -TextProposal defines a standard text proposal whose changes need to be -manually updated in case of approval. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `title` | [string](#string) | | | -| `description` | [string](#string) | | | +### MsgChannelCloseConfirmResponse +MsgChannelCloseConfirmResponse defines the Msg/ChannelCloseConfirm response type. - + -### Vote -Vote defines a vote on a governance proposal. -A Vote consists of a proposal ID, the voter, and the vote option. +### MsgChannelCloseInit +MsgChannelCloseInit defines a msg sent by a Relayer to Chain A +to close a channel with Chain B. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | | -| `voter` | [string](#string) | | | -| `options` | [WeightedVoteOption](#cosmos.gov.v1beta1.WeightedVoteOption) | repeated | | - - +| `port_id` | [string](#string) | | | +| `channel_id` | [string](#string) | | | +| `signer` | [string](#string) | | | - -### 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. | +### MsgChannelCloseInitResponse +MsgChannelCloseInitResponse defines the Msg/ChannelCloseInit response type. - + -### WeightedVoteOption -WeightedVoteOption defines a unit of vote for vote split. +### 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 | | ----- | ---- | ----- | ----------- | -| `option` | [VoteOption](#cosmos.gov.v1beta1.VoteOption) | | | -| `weight` | [string](#string) | | | +| `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) | | | - + - +### MsgChannelOpenAckResponse +MsgChannelOpenAckResponse defines the Msg/ChannelOpenAck response type. -### 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. | - -### 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. | +### 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) | | | +| `channel_id` | [string](#string) | | | +| `proof_ack` | [bytes](#bytes) | | | +| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | +| `signer` | [string](#string) | | | - - - -

Top

-## cosmos/gov/v1beta1/tx.proto + +### MsgChannelOpenConfirmResponse +MsgChannelOpenConfirmResponse defines the Msg/ChannelOpenConfirm response type. - -### MsgDeposit -MsgDeposit defines a message to submit a deposit to an existing proposal. + + + + + +### MsgChannelOpenInit +MsgChannelOpenInit defines an sdk.Msg to initialize a channel handshake. It +is called by a relayer on Chain A. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | | -| `depositor` | [string](#string) | | | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `port_id` | [string](#string) | | | +| `channel` | [Channel](#ibc.core.channel.v1.Channel) | | | +| `signer` | [string](#string) | | | - + -### MsgDepositResponse -MsgDepositResponse defines the Msg/Deposit response type. +### MsgChannelOpenInitResponse +MsgChannelOpenInitResponse defines the Msg/ChannelOpenInit response type. - + -### MsgSubmitProposal -MsgSubmitProposal defines an sdk.Msg type that supports submitting arbitrary -proposal Content. +### MsgChannelOpenTry +MsgChannelOpenInit defines a msg sent by a Relayer to try to open a channel +on Chain B. | 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) | | | - - +| `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) | | | - -### MsgSubmitProposalResponse -MsgSubmitProposalResponse defines the Msg/SubmitProposal response type. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | | +### MsgChannelOpenTryResponse +MsgChannelOpenTryResponse defines the Msg/ChannelOpenTry response type. - + -### MsgVote -MsgVote defines a message to cast a vote. +### MsgRecvPacket +MsgRecvPacket receives incoming IBC packet | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | | -| `voter` | [string](#string) | | | -| `option` | [VoteOption](#cosmos.gov.v1beta1.VoteOption) | | | +| `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) | | | - + -### MsgVoteResponse -MsgVoteResponse defines the Msg/Vote response type. +### MsgRecvPacketResponse +MsgRecvPacketResponse defines the Msg/RecvPacket response type. - + -### MsgVoteWeighted -MsgVote defines a message to cast a vote. +### MsgTimeout +MsgTimeout receives timed-out packet | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | | -| `voter` | [string](#string) | | | -| `options` | [WeightedVoteOption](#cosmos.gov.v1beta1.WeightedVoteOption) | repeated | | - - +| `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) | | | - -### MsgVoteWeightedResponse -MsgVoteWeightedResponse defines the Msg/VoteWeighted 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) | | | - - - - -### 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. | | -| `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. | | +### MsgTimeoutOnCloseResponse +MsgTimeoutOnCloseResponse defines the Msg/TimeoutOnClose response type. - - -

Top

-## cosmos/gov/v1beta1/query.proto + +### MsgTimeoutResponse +MsgTimeoutResponse defines the Msg/Timeout response type. - -### QueryDepositRequest -QueryDepositRequest is the request type for the Query/Deposit RPC method. -| 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. | + + + + - +### Msg +Msg defines the ibc/channel Msg service. -### QueryDepositResponse -QueryDepositResponse is the response type for the Query/Deposit RPC method. +| 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. | | + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `deposit` | [Deposit](#cosmos.gov.v1beta1.Deposit) | | deposit defines the requested deposit. | + +

Top

+## ibc/core/client/v1/genesis.proto - + -### QueryDepositsRequest -QueryDepositsRequest is the request type for the Query/Deposits RPC method. +### GenesisMetadata +GenesisMetadata defines the genesis type for metadata that clients may return +with ExportMetadata | 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. | +| `key` | [bytes](#bytes) | | store key of metadata without clientID-prefix | +| `value` | [bytes](#bytes) | | metadata value | - + -### QueryDepositsResponse -QueryDepositsResponse is the response type for the Query/Deposits RPC method. +### GenesisState +GenesisState defines the ibc client submodule's genesis state. | 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. | +| `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 | - + -### QueryParamsRequest -QueryParamsRequest is the request type for the Query/Params RPC method. +### IdentifiedGenesisMetadata +IdentifiedGenesisMetadata has the client metadata with the corresponding client id. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params_type` | [string](#string) | | params_type defines which parameters to query for, can be one of "voting", "tallying" or "deposit". | - - +| `client_id` | [string](#string) | | | +| `client_metadata` | [GenesisMetadata](#ibc.core.client.v1.GenesisMetadata) | repeated | | - -### 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

+## ibc/core/client/v1/query.proto - -### 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. | +### QueryClientParamsRequest +QueryClientParamsRequest is the request type for the Query/ClientParams RPC method. - + -### QueryProposalResponse -QueryProposalResponse is the response type for the Query/Proposal RPC method. +### QueryClientParamsResponse +QueryClientParamsResponse is the response type for the Query/ClientParams RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal` | [Proposal](#cosmos.gov.v1beta1.Proposal) | | | +| `params` | [Params](#ibc.core.client.v1.Params) | | params defines the parameters of the module. | - + -### QueryProposalsRequest -QueryProposalsRequest is the request type for the Query/Proposals RPC method. +### QueryClientStateRequest +QueryClientStateRequest is the request type for the Query/ClientState 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. | +| `client_id` | [string](#string) | | client state unique identifier | - + -### QueryProposalsResponse -QueryProposalsResponse is the response type for the Query/Proposals RPC -method. +### 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 | | ----- | ---- | ----- | ----------- | -| `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. | +| `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 | - + -### QueryTallyResultRequest -QueryTallyResultRequest is the request type for the Query/Tally RPC method. +### QueryClientStatesRequest +QueryClientStatesRequest is the request type for the Query/ClientStates 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 request | - + -### QueryTallyResultResponse -QueryTallyResultResponse is the response type for the Query/Tally RPC method. +### QueryClientStatesResponse +QueryClientStatesResponse is the response type for the Query/ClientStates RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `tally` | [TallyResult](#cosmos.gov.v1beta1.TallyResult) | | tally defines the requested tally. | +| `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 | - + -### QueryVoteRequest -QueryVoteRequest is the request type for the Query/Vote RPC method. +### 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 | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | -| `voter` | [string](#string) | | voter defines the oter address for the proposals. | +| `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 | - + -### QueryVoteResponse -QueryVoteResponse is the response type for the Query/Vote RPC method. +### QueryConsensusStateResponse +QueryConsensusStateResponse is the response type for the Query/ConsensusState +RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `vote` | [Vote](#cosmos.gov.v1beta1.Vote) | | vote defined the queried vote. | +| `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 | - + -### QueryVotesRequest -QueryVotesRequest is the request type for the Query/Votes RPC method. +### QueryConsensusStatesRequest +QueryConsensusStatesRequest is the request type for the Query/ConsensusStates +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. | +| `client_id` | [string](#string) | | client identifier | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | - + -### QueryVotesResponse -QueryVotesResponse is the response type for the Query/Votes RPC method. +### QueryConsensusStatesResponse +QueryConsensusStatesResponse is the response type for the +Query/ConsensusStates RPC method | 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. | +| `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 | @@ -9527,194 +9534,137 @@ QueryVotesResponse is the response type for the Query/Votes RPC method. - + ### Query -Query defines the gRPC querier service for gov module +Query provides defines the gRPC querier service | 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/genesis.proto - - - - - -### GenesisState -GenesisState defines the gov module's genesis state. - - -| 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. | - - - - - - - - - - +| `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

- -## cosmos/mint/v1beta1/mint.proto - - - - - -### Minter -Minter represents the minting state. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `inflation` | [string](#string) | | current annual inflation rate | -| `annual_provisions` | [string](#string) | | current annual expected provisions | - - - - - - - - -### 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 | - - + +

Top

+## ibc/core/client/v1/tx.proto - - + - +### 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 | - -

Top

-## cosmos/mint/v1beta1/query.proto - + -### QueryAnnualProvisionsRequest -QueryAnnualProvisionsRequest is the request type for the -Query/AnnualProvisions RPC method. +### MsgCreateClientResponse +MsgCreateClientResponse defines the Msg/CreateClient response type. - + -### QueryAnnualProvisionsResponse -QueryAnnualProvisionsResponse is the response type for the -Query/AnnualProvisions RPC method. +### MsgSubmitMisbehaviour +MsgSubmitMisbehaviour defines an sdk.Msg type that submits Evidence for +light client misbehaviour. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `annual_provisions` | [bytes](#bytes) | | annual_provisions is the current minting annual provisions value. | +| `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 | - + -### QueryInflationRequest -QueryInflationRequest is the request type for the Query/Inflation RPC method. +### MsgSubmitMisbehaviourResponse +MsgSubmitMisbehaviourResponse defines the Msg/SubmitMisbehaviour response type. - + -### QueryInflationResponse -QueryInflationResponse is the response type for the Query/Inflation RPC -method. +### MsgUpdateClient +MsgUpdateClient defines an sdk.Msg to update a IBC client state using +the given header. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `inflation` | [bytes](#bytes) | | inflation is the current minting inflation value. | +| `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 | - + -### QueryParamsRequest -QueryParamsRequest is the request type for the Query/Params RPC method. +### MsgUpdateClientResponse +MsgUpdateClientResponse defines the Msg/UpdateClient response type. - + -### QueryParamsResponse -QueryParamsResponse is the response type for the Query/Params RPC method. +### MsgUpgradeClient +MsgUpgradeClient defines an sdk.Msg to upgrade an IBC client to a new client state | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.mint.v1beta1.Params) | | params defines the parameters of the module. | +| `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 | + + + + + + + + +### MsgUpgradeClientResponse +MsgUpgradeClientResponse defines the Msg/UpgradeClient response type. @@ -9727,84 +9677,92 @@ QueryParamsResponse is the response type for the Query/Params RPC method. - + -### Query -Query provides defines the gRPC querier service. +### Msg +Msg defines the ibc/client Msg 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| +| `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

-## cosmos/mint/v1beta1/genesis.proto +## ibc/core/commitment/v1/commitment.proto - + -### GenesisState -GenesisState defines the mint module's genesis state. +### MerklePath +MerklePath is the path used to verify commitment proofs, which can be an +arbitrary structured object (defined by a commitment type). +MerklePath is represented from root-to-leaf | 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. | +| `key_path` | [string](#string) | repeated | | - - + - +### MerklePrefix +MerklePrefix is merkle path prefixed to the key. +The constructed key from the Path and the key will be append(Path.KeyPath, +append(Path.KeyPrefix, key...)) - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `key_prefix` | [bytes](#bytes) | | | - -

Top

-## cosmos/vesting/v1beta1/tx.proto - + -### MsgCreateVestingAccount -MsgCreateVestingAccount defines a message that enables creating a vesting -account. +### MerkleProof +MerkleProof is a wrapper type over a chain of CommitmentProofs. +It demonstrates membership or non-membership for an element or set of +elements, verifiable in conjunction with a known commitment root. Proofs +should be succinct. +MerkleProofs are ordered from leaf-to-root | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `from_address` | [string](#string) | | | -| `to_address` | [string](#string) | | | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | -| `end_time` | [int64](#int64) | | | -| `delayed` | [bool](#bool) | | | +| `proofs` | [ics23.CommitmentProof](#ics23.CommitmentProof) | repeated | | - + + +### MerkleRoot +MerkleRoot defines a merkle root hash. +In the Cosmos SDK, the AppHash of a block header becomes the root. -### MsgCreateVestingAccountResponse -MsgCreateVestingAccountResponse defines the Msg/CreateVestingAccount response type. + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `hash` | [bytes](#bytes) | | | @@ -9816,115 +9774,140 @@ MsgCreateVestingAccountResponse defines the Msg/CreateVestingAccount response ty + - -### Msg -Msg defines the bank Msg service. -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `CreateVestingAccount` | [MsgCreateVestingAccount](#cosmos.vesting.v1beta1.MsgCreateVestingAccount) | [MsgCreateVestingAccountResponse](#cosmos.vesting.v1beta1.MsgCreateVestingAccountResponse) | CreateVestingAccount defines a method that enables creating a vesting account. | | + +

Top

- +## ibc/core/connection/v1/connection.proto - -

Top

+ -## cosmos/vesting/v1beta1/vesting.proto +### ClientPaths +ClientPaths define all the connection paths for a client state. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `paths` | [string](#string) | repeated | list of connection paths | - -### BaseVestingAccount -BaseVestingAccount implements the VestingAccount interface. It contains all -the necessary fields needed for any vesting account implementation. + + + + +### ConnectionEnd +ConnectionEnd defines a stateful object on a chain connected to another +separate one. +NOTE: there must only be 2 defined ConnectionEnds to establish +a connection between two chains. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `base_account` | [cosmos.auth.v1beta1.BaseAccount](#cosmos.auth.v1beta1.BaseAccount) | | | -| `original_vesting` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | -| `delegated_free` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | -| `delegated_vesting` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | -| `end_time` | [int64](#int64) | | | +| `client_id` | [string](#string) | | client associated with this connection. | +| `versions` | [Version](#ibc.core.connection.v1.Version) | repeated | IBC version which can be utilised to determine encodings or protocols for channels or packets utilising this connection. | +| `state` | [State](#ibc.core.connection.v1.State) | | current state of the connection end. | +| `counterparty` | [Counterparty](#ibc.core.connection.v1.Counterparty) | | counterparty chain associated with this connection. | +| `delay_period` | [uint64](#uint64) | | delay period that must pass before a consensus state can be used for packet-verification NOTE: delay period logic is only implemented by some clients. | - + -### ContinuousVestingAccount -ContinuousVestingAccount implements the VestingAccount interface. It -continuously vests by unlocking coins linearly with respect to time. +### ConnectionPaths +ConnectionPaths define all the connection paths for a given client state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `base_vesting_account` | [BaseVestingAccount](#cosmos.vesting.v1beta1.BaseVestingAccount) | | | -| `start_time` | [int64](#int64) | | | +| `client_id` | [string](#string) | | client state unique identifier | +| `paths` | [string](#string) | repeated | list of connection paths | - + -### DelayedVestingAccount -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. +### Counterparty +Counterparty defines the counterparty chain associated with a connection end. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `base_vesting_account` | [BaseVestingAccount](#cosmos.vesting.v1beta1.BaseVestingAccount) | | | +| `client_id` | [string](#string) | | identifies the client on the counterparty chain associated with a given connection. | +| `connection_id` | [string](#string) | | identifies the connection end on the counterparty chain associated with a given connection. | +| `prefix` | [ibc.core.commitment.v1.MerklePrefix](#ibc.core.commitment.v1.MerklePrefix) | | commitment merkle prefix of the counterparty chain. | - + -### Period -Period defines a length of time and amount of coins that will vest. +### IdentifiedConnection +IdentifiedConnection defines a connection with additional connection +identifier field. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `length` | [int64](#int64) | | | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `id` | [string](#string) | | connection identifier. | +| `client_id` | [string](#string) | | client associated with this connection. | +| `versions` | [Version](#ibc.core.connection.v1.Version) | repeated | IBC version which can be utilised to determine encodings or protocols for channels or packets utilising this connection | +| `state` | [State](#ibc.core.connection.v1.State) | | current state of the connection end. | +| `counterparty` | [Counterparty](#ibc.core.connection.v1.Counterparty) | | counterparty chain associated with this connection. | +| `delay_period` | [uint64](#uint64) | | delay period associated with this connection. | - + + +### Version +Version defines the versioning scheme used to negotiate the IBC verison in +the connection handshake. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `identifier` | [string](#string) | | unique version identifier | +| `features` | [string](#string) | repeated | list of features compatible with the specified identifier | + + -### PeriodicVestingAccount -PeriodicVestingAccount implements the VestingAccount interface. It -periodically vests by unlocking coins during each specified period. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `base_vesting_account` | [BaseVestingAccount](#cosmos.vesting.v1beta1.BaseVestingAccount) | | | -| `start_time` | [int64](#int64) | | | -| `vesting_periods` | [Period](#cosmos.vesting.v1beta1.Period) | repeated | | + + +### State +State defines if a connection is in one of the following states: +INIT, TRYOPEN, OPEN or UNINITIALIZED. +| Name | Number | Description | +| ---- | ------ | ----------- | +| STATE_UNINITIALIZED_UNSPECIFIED | 0 | Default State | +| STATE_INIT | 1 | A connection end has just started the opening handshake. | +| STATE_TRYOPEN | 2 | A connection end has acknowledged the handshake step on the counterparty chain. | +| STATE_OPEN | 3 | A connection end has completed the handshake. | - @@ -9934,366 +9917,375 @@ periodically vests by unlocking coins during each specified period. - +

Top

-## cosmos/distribution/v1beta1/tx.proto +## ibc/core/connection/v1/genesis.proto - + -### MsgFundCommunityPool -MsgFundCommunityPool allows an account to directly -fund the community pool. +### GenesisState +GenesisState defines the ibc connection submodule's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | -| `depositor` | [string](#string) | | | +| `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 | + - + -### MsgFundCommunityPoolResponse -MsgFundCommunityPoolResponse defines the Msg/FundCommunityPool response type. + + + + +

Top

+## ibc/core/connection/v1/query.proto - -### MsgSetWithdrawAddress -MsgSetWithdrawAddress sets the withdraw address for -a delegator (or validator self-delegation). + + +### QueryClientConnectionsRequest +QueryClientConnectionsRequest is the request type for the +Query/ClientConnections RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `withdraw_address` | [string](#string) | | | +| `client_id` | [string](#string) | | client identifier associated with a connection | - + + +### QueryClientConnectionsResponse +QueryClientConnectionsResponse is the response type for the +Query/ClientConnections RPC method -### MsgSetWithdrawAddressResponse -MsgSetWithdrawAddressResponse defines the Msg/SetWithdrawAddress response type. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `connection_paths` | [string](#string) | repeated | slice of all the connection paths associated with a client. | +| `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 generated | - -### MsgWithdrawDelegatorReward -MsgWithdrawDelegatorReward represents delegation withdrawal to a delegator -from a single validator. + + +### QueryConnectionClientStateRequest +QueryConnectionClientStateRequest is the request type for the +Query/ConnectionClientState RPC method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `validator_address` | [string](#string) | | | +| `connection_id` | [string](#string) | | connection identifier | - + -### MsgWithdrawDelegatorRewardResponse -MsgWithdrawDelegatorRewardResponse defines the Msg/WithdrawDelegatorReward response type. +### QueryConnectionClientStateResponse +QueryConnectionClientStateResponse is the response type for the +Query/ConnectionClientState RPC method +| 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 | - -### MsgWithdrawValidatorCommission -MsgWithdrawValidatorCommission withdraws the full commission to the validator -address. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `validator_address` | [string](#string) | | | +### QueryConnectionConsensusStateRequest +QueryConnectionConsensusStateRequest is the request type for the +Query/ConnectionConsensusState RPC method +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `connection_id` | [string](#string) | | connection identifier | +| `revision_number` | [uint64](#uint64) | | | +| `revision_height` | [uint64](#uint64) | | | - -### MsgWithdrawValidatorCommissionResponse -MsgWithdrawValidatorCommissionResponse defines the Msg/WithdrawValidatorCommission response type. + +### QueryConnectionConsensusStateResponse +QueryConnectionConsensusStateResponse is the response type for the +Query/ConnectionConsensusState 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 | - - - - -### 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. | | +### QueryConnectionRequest +QueryConnectionRequest is the request type for the Query/Connection RPC +method - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `connection_id` | [string](#string) | | connection unique identifier | - -

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. +### QueryConnectionResponse +QueryConnectionResponse is the response type for the Query/Connection RPC +method. Besides the connection end, it includes a proof and the height from +which the proof was retrieved. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `title` | [string](#string) | | | -| `description` | [string](#string) | | | -| `recipient` | [string](#string) | | | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `connection` | [ConnectionEnd](#ibc.core.connection.v1.ConnectionEnd) | | connection associated with the request identifier | +| `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 | - + -### CommunityPoolSpendProposalWithDeposit -CommunityPoolSpendProposalWithDeposit defines a CommunityPoolSpendProposal -with a deposit +### QueryConnectionsRequest +QueryConnectionsRequest is the request type for the Query/Connections RPC +method | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `title` | [string](#string) | | | -| `description` | [string](#string) | | | -| `recipient` | [string](#string) | | | -| `amount` | [string](#string) | | | -| `deposit` | [string](#string) | | | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | | - + -### DelegationDelegatorReward -DelegationDelegatorReward represents the properties -of a delegator's delegation reward. +### QueryConnectionsResponse +QueryConnectionsResponse is the response type for the Query/Connections RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator_address` | [string](#string) | | | -| `reward` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | +| `connections` | [IdentifiedConnection](#ibc.core.connection.v1.IdentifiedConnection) | repeated | list of stored connections 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 | + - + -### 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) | | | + +### Query +Query provides defines the gRPC querier service +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Connection` | [QueryConnectionRequest](#ibc.core.connection.v1.QueryConnectionRequest) | [QueryConnectionResponse](#ibc.core.connection.v1.QueryConnectionResponse) | Connection queries an IBC connection end. | GET|/ibc/core/connection/v1beta1/connections/{connection_id}| +| `Connections` | [QueryConnectionsRequest](#ibc.core.connection.v1.QueryConnectionsRequest) | [QueryConnectionsResponse](#ibc.core.connection.v1.QueryConnectionsResponse) | Connections queries all the IBC connections of a chain. | GET|/ibc/core/connection/v1beta1/connections| +| `ClientConnections` | [QueryClientConnectionsRequest](#ibc.core.connection.v1.QueryClientConnectionsRequest) | [QueryClientConnectionsResponse](#ibc.core.connection.v1.QueryClientConnectionsResponse) | ClientConnections queries the connection paths associated with a client state. | GET|/ibc/core/connection/v1beta1/client_connections/{client_id}| +| `ConnectionClientState` | [QueryConnectionClientStateRequest](#ibc.core.connection.v1.QueryConnectionClientStateRequest) | [QueryConnectionClientStateResponse](#ibc.core.connection.v1.QueryConnectionClientStateResponse) | ConnectionClientState queries the client state associated with the connection. | GET|/ibc/core/connection/v1beta1/connections/{connection_id}/client_state| +| `ConnectionConsensusState` | [QueryConnectionConsensusStateRequest](#ibc.core.connection.v1.QueryConnectionConsensusStateRequest) | [QueryConnectionConsensusStateResponse](#ibc.core.connection.v1.QueryConnectionConsensusStateResponse) | ConnectionConsensusState queries the consensus state associated with the connection. | GET|/ibc/core/connection/v1beta1/connections/{connection_id}/consensus_state/revision/{revision_number}/height/{revision_height}| + - + +

Top

-### FeePool -FeePool is the global fee pool for distribution. +## ibc/core/connection/v1/tx.proto -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `community_pool` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | + + + +### MsgConnectionOpenAck +MsgConnectionOpenAck defines a msg sent by a Relayer to Chain A to +acknowledge the change of connection state to TRYOPEN on Chain B. +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `connection_id` | [string](#string) | | | +| `counterparty_connection_id` | [string](#string) | | | +| `version` | [Version](#ibc.core.connection.v1.Version) | | | +| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | +| `proof_try` | [bytes](#bytes) | | proof of the initialization the connection on Chain B: `UNITIALIZED -> TRYOPEN` | +| `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) | | | - -### 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) | | | +### MsgConnectionOpenAckResponse +MsgConnectionOpenAckResponse defines the Msg/ConnectionOpenAck response type. - + -### ValidatorAccumulatedCommission -ValidatorAccumulatedCommission represents accumulated commission -for a validator kept as a running counter, can be withdrawn at any time. +### MsgConnectionOpenConfirm +MsgConnectionOpenConfirm defines a msg sent by a Relayer to Chain B to +acknowledge the change of connection state to OPEN on Chain A. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `commission` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | - - +| `connection_id` | [string](#string) | | | +| `proof_ack` | [bytes](#bytes) | | proof for the change of the connection state on Chain A: `INIT -> OPEN` | +| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | +| `signer` | [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. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `rewards` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | -| `period` | [uint64](#uint64) | | | +### MsgConnectionOpenConfirmResponse +MsgConnectionOpenConfirmResponse defines the Msg/ConnectionOpenConfirm response type. - + -### 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 +### MsgConnectionOpenInit +MsgConnectionOpenInit defines the msg sent by an account on Chain A to +initialize a connection with Chain B. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `cumulative_reward_ratio` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | -| `reference_count` | [uint32](#uint32) | | | - - +| `client_id` | [string](#string) | | | +| `counterparty` | [Counterparty](#ibc.core.connection.v1.Counterparty) | | | +| `version` | [Version](#ibc.core.connection.v1.Version) | | | +| `delay_period` | [uint64](#uint64) | | | +| `signer` | [string](#string) | | | - -### ValidatorOutstandingRewards -ValidatorOutstandingRewards represents outstanding (un-withdrawn) rewards -for a validator inexpensive to track, allows simple sanity checks. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `rewards` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | +### MsgConnectionOpenInitResponse +MsgConnectionOpenInitResponse defines the Msg/ConnectionOpenInit response type. - + -### 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. +### MsgConnectionOpenTry +MsgConnectionOpenTry defines a msg sent by a Relayer to try to open a +connection on Chain B. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator_period` | [uint64](#uint64) | | | -| `fraction` | [string](#string) | | | - - +| `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) | | | - -### ValidatorSlashEvents -ValidatorSlashEvents is a collection of ValidatorSlashEvent messages. + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `validator_slash_events` | [ValidatorSlashEvent](#cosmos.distribution.v1beta1.ValidatorSlashEvent) | repeated | | +### MsgConnectionOpenTryResponse +MsgConnectionOpenTryResponse defines the Msg/ConnectionOpenTry response type. @@ -10305,471 +10297,513 @@ ValidatorSlashEvents is a collection of ValidatorSlashEvent messages. - - - - - -

Top

-## cosmos/distribution/v1beta1/query.proto + +### 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. | | - + -### QueryCommunityPoolRequest -QueryCommunityPoolRequest is the request type for the Query/CommunityPool RPC -method. + +

Top

+## ibc/core/types/v1/genesis.proto - + -### QueryCommunityPoolResponse -QueryCommunityPoolResponse is the response type for the Query/CommunityPool -RPC method. +### GenesisState +GenesisState defines the ibc module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `pool` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | pool defines community pool's coins. | +| `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 | + - + -### QueryDelegationRewardsRequest -QueryDelegationRewardsRequest is the request type for the -Query/DelegationRewards RPC method. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | delegator_address defines the delegator address to query for. | -| `validator_address` | [string](#string) | | validator_address defines the validator address to query for. | + +

Top

+## ibc/lightclients/localhost/v1/localhost.proto - + -### QueryDelegationRewardsResponse -QueryDelegationRewardsResponse is the response type for the -Query/DelegationRewards RPC method. +### ClientState +ClientState defines a loopback (localhost) client. It requires (read-only) +access to keys outside the client prefix. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `rewards` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | rewards defines the rewards accrued by a delegation. | +| `chain_id` | [string](#string) | | self chain ID | +| `height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | self latest block height | + - + -### QueryDelegationTotalRewardsRequest -QueryDelegationTotalRewardsRequest is the request type for the -Query/DelegationTotalRewards RPC method. + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | delegator_address defines the delegator address to query for. | + +

Top

+## ibc/lightclients/solomachine/v1/solomachine.proto - + -### QueryDelegationTotalRewardsResponse -QueryDelegationTotalRewardsResponse is the response type for the -Query/DelegationTotalRewards RPC method. +### ChannelStateData +ChannelStateData returns the SignBytes data for channel state +verification. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `rewards` | [DelegationDelegatorReward](#cosmos.distribution.v1beta1.DelegationDelegatorReward) | repeated | rewards defines all the rewards accrued by a delegator. | -| `total` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | total defines the sum of all the rewards. | +| `path` | [bytes](#bytes) | | | +| `channel` | [ibc.core.channel.v1.Channel](#ibc.core.channel.v1.Channel) | | | - + -### QueryDelegatorValidatorsRequest -QueryDelegatorValidatorsRequest is the request type for the -Query/DelegatorValidators RPC method. +### ClientState +ClientState defines a solo machine client that tracks the current consensus +state and if the client is frozen. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | delegator_address defines the delegator address to query for. | +| `sequence` | [uint64](#uint64) | | latest sequence of the client state | +| `frozen_sequence` | [uint64](#uint64) | | frozen sequence of the solo machine | +| `consensus_state` | [ConsensusState](#ibc.lightclients.solomachine.v1.ConsensusState) | | | +| `allow_update_after_proposal` | [bool](#bool) | | when set to true, will allow governance to update a solo machine client. The client will be unfrozen if it is frozen. | - + -### QueryDelegatorValidatorsResponse -QueryDelegatorValidatorsResponse is the response type for the -Query/DelegatorValidators RPC method. +### ClientStateData +ClientStateData returns the SignBytes data for client state verification. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validators` | [string](#string) | repeated | validators defines the validators a delegator is delegating for. | +| `path` | [bytes](#bytes) | | | +| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | | - + -### QueryDelegatorWithdrawAddressRequest -QueryDelegatorWithdrawAddressRequest is the request type for the -Query/DelegatorWithdrawAddress RPC method. +### ConnectionStateData +ConnectionStateData returns the SignBytes data for connection state +verification. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | delegator_address defines the delegator address to query for. | +| `path` | [bytes](#bytes) | | | +| `connection` | [ibc.core.connection.v1.ConnectionEnd](#ibc.core.connection.v1.ConnectionEnd) | | | - + -### QueryDelegatorWithdrawAddressResponse -QueryDelegatorWithdrawAddressResponse is the response type for the -Query/DelegatorWithdrawAddress RPC method. +### ConsensusState +ConsensusState defines a solo machine consensus state. The sequence of a consensus state +is contained in the "height" key used in storing the consensus state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `withdraw_address` | [string](#string) | | withdraw_address defines the delegator address to query for. | +| `public_key` | [google.protobuf.Any](#google.protobuf.Any) | | public key of the solo machine | +| `diversifier` | [string](#string) | | diversifier allows the same public key to be re-used across different solo machine clients (potentially on different chains) without being considered misbehaviour. | +| `timestamp` | [uint64](#uint64) | | | - + -### QueryParamsRequest -QueryParamsRequest is the request type for the Query/Params RPC method. +### ConsensusStateData +ConsensusStateData returns the SignBytes data for consensus state +verification. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `path` | [bytes](#bytes) | | | +| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | | - + -### QueryParamsResponse -QueryParamsResponse is the response type for the Query/Params RPC method. +### Header +Header defines a solo machine consensus header | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.distribution.v1beta1.Params) | | params defines the parameters of the module. | +| `sequence` | [uint64](#uint64) | | sequence to update solo machine public key at | +| `timestamp` | [uint64](#uint64) | | | +| `signature` | [bytes](#bytes) | | | +| `new_public_key` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `new_diversifier` | [string](#string) | | | - + -### QueryValidatorCommissionRequest -QueryValidatorCommissionRequest is the request type for the -Query/ValidatorCommission RPC method +### HeaderData +HeaderData returns the SignBytes data for update verification. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator_address` | [string](#string) | | validator_address defines the validator address to query for. | +| `new_pub_key` | [google.protobuf.Any](#google.protobuf.Any) | | header public key | +| `new_diversifier` | [string](#string) | | header diversifier | - + -### QueryValidatorCommissionResponse -QueryValidatorCommissionResponse is the response type for the -Query/ValidatorCommission RPC method +### Misbehaviour +Misbehaviour defines misbehaviour for a solo machine which consists +of a sequence and two signatures over different messages at that sequence. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `commission` | [ValidatorAccumulatedCommission](#cosmos.distribution.v1beta1.ValidatorAccumulatedCommission) | | commission defines the commision the validator received. | +| `client_id` | [string](#string) | | | +| `sequence` | [uint64](#uint64) | | | +| `signature_one` | [SignatureAndData](#ibc.lightclients.solomachine.v1.SignatureAndData) | | | +| `signature_two` | [SignatureAndData](#ibc.lightclients.solomachine.v1.SignatureAndData) | | | - + -### QueryValidatorOutstandingRewardsRequest -QueryValidatorOutstandingRewardsRequest is the request type for the -Query/ValidatorOutstandingRewards RPC method. +### NextSequenceRecvData +NextSequenceRecvData returns the SignBytes data for verification of the next +sequence to be received. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator_address` | [string](#string) | | validator_address defines the validator address to query for. | +| `path` | [bytes](#bytes) | | | +| `next_seq_recv` | [uint64](#uint64) | | | - + -### QueryValidatorOutstandingRewardsResponse -QueryValidatorOutstandingRewardsResponse is the response type for the -Query/ValidatorOutstandingRewards RPC method. +### PacketAcknowledgementData +PacketAcknowledgementData returns the SignBytes data for acknowledgement +verification. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `rewards` | [ValidatorOutstandingRewards](#cosmos.distribution.v1beta1.ValidatorOutstandingRewards) | | | +| `path` | [bytes](#bytes) | | | +| `acknowledgement` | [bytes](#bytes) | | | - + -### QueryValidatorSlashesRequest -QueryValidatorSlashesRequest is the request type for the -Query/ValidatorSlashes RPC method +### PacketCommitmentData +PacketCommitmentData returns the SignBytes data for packet commitment +verification. | 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. | +| `path` | [bytes](#bytes) | | | +| `commitment` | [bytes](#bytes) | | | - + -### QueryValidatorSlashesResponse -QueryValidatorSlashesResponse is the response type for the -Query/ValidatorSlashes RPC method. +### PacketReceiptAbsenceData +PacketReceiptAbsenceData returns the SignBytes data for +packet receipt absence verification. | 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. | - - - - +| `path` | [bytes](#bytes) | | | - - - - -### 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| +### SignBytes +SignBytes defines the signed bytes used for signature verification. - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `sequence` | [uint64](#uint64) | | | +| `timestamp` | [uint64](#uint64) | | | +| `diversifier` | [string](#string) | | | +| `data_type` | [DataType](#ibc.lightclients.solomachine.v1.DataType) | | type of the data used | +| `data` | [bytes](#bytes) | | marshaled data | - -

Top

-## cosmos/distribution/v1beta1/genesis.proto - + -### DelegatorStartingInfoRecord -DelegatorStartingInfoRecord used for import / export via genesis json. +### SignatureAndData +SignatureAndData contains a signature and the data signed over to create that +signature. | 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. | +| `signature` | [bytes](#bytes) | | | +| `data_type` | [DataType](#ibc.lightclients.solomachine.v1.DataType) | | | +| `data` | [bytes](#bytes) | | | +| `timestamp` | [uint64](#uint64) | | | - + -### 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. +### TimestampedSignatureData +TimestampedSignatureData contains the signature data and the timestamp of the +signature. | 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. | +| `signature_data` | [bytes](#bytes) | | | +| `timestamp` | [uint64](#uint64) | | | + - -### GenesisState -GenesisState defines the distribution module's genesis state. + +### DataType +DataType defines the type of solo machine proof being created. This is done to preserve uniqueness of different +data sign byte encodings. -| 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. | +| Name | Number | Description | +| ---- | ------ | ----------- | +| DATA_TYPE_UNINITIALIZED_UNSPECIFIED | 0 | Default State | +| DATA_TYPE_CLIENT_STATE | 1 | Data type for client state verification | +| DATA_TYPE_CONSENSUS_STATE | 2 | Data type for consensus state verification | +| DATA_TYPE_CONNECTION_STATE | 3 | Data type for connection state verification | +| DATA_TYPE_CHANNEL_STATE | 4 | Data type for channel state verification | +| DATA_TYPE_PACKET_COMMITMENT | 5 | Data type for packet commitment verification | +| DATA_TYPE_PACKET_ACKNOWLEDGEMENT | 6 | Data type for packet acknowledgement verification | +| DATA_TYPE_PACKET_RECEIPT_ABSENCE | 7 | Data type for packet receipt absence verification | +| DATA_TYPE_NEXT_SEQUENCE_RECV | 8 | Data type for next sequence recv verification | +| DATA_TYPE_HEADER | 9 | Data type for header verification | + + + - -### ValidatorAccumulatedCommissionRecord -ValidatorAccumulatedCommissionRecord is used for import / export via genesis -json. + +

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 | | ----- | ---- | ----- | ----------- | -| `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. | +| `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 | - + -### ValidatorCurrentRewardsRecord -ValidatorCurrentRewardsRecord is used for import / export via genesis json. +### ConsensusState +ConsensusState defines the consensus state from Tendermint. | 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. | +| `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) | | | - + -### ValidatorHistoricalRewardsRecord -ValidatorHistoricalRewardsRecord is used for import / export via genesis -json. +### Fraction +Fraction defines the protobuf message type for tmmath.Fraction that only supports positive values. | 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. | +| `numerator` | [uint64](#uint64) | | | +| `denominator` | [uint64](#uint64) | | | - + -### ValidatorOutstandingRewardsRecord -ValidatorOutstandingRewardsRecord is used for import/export via genesis json. +### 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 | | ----- | ---- | ----- | ----------- | -| `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. | +| `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) | | | - + -### ValidatorSlashEventRecord -ValidatorSlashEventRecord is used for import / export via genesis json. +### Misbehaviour +Misbehaviour is a wrapper over two conflicting Headers +that implements Misbehaviour interface expected by ICS-02 | 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. | +| `client_id` | [string](#string) | | | +| `header_1` | [Header](#ibc.lightclients.tendermint.v1.Header) | | | +| `header_2` | [Header](#ibc.lightclients.tendermint.v1.Header) | | | diff --git a/proto/cosmos/auth/v1beta1/query.proto b/proto/cosmos/auth/v1beta1/query.proto index a8857926833f..76d30dd610cc 100644 --- a/proto/cosmos/auth/v1beta1/query.proto +++ b/proto/cosmos/auth/v1beta1/query.proto @@ -1,6 +1,7 @@ syntax = "proto3"; package cosmos.auth.v1beta1; +import "cosmos/base/query/v1beta1/pagination.proto"; import "gogoproto/gogo.proto"; import "google/protobuf/any.proto"; import "google/api/annotations.proto"; @@ -11,6 +12,11 @@ option go_package = "github.com/cosmos/cosmos-sdk/x/auth/types"; // Query defines the gRPC querier service. service Query { + // Accounts returns all the existing accounts + rpc Accounts(QueryAccountsRequest) returns (QueryAccountsResponse) { + option (google.api.http).get = "/cosmos/auth/v1beta1/accounts"; + } + // Account returns account details based on address. rpc Account(QueryAccountRequest) returns (QueryAccountResponse) { option (google.api.http).get = "/cosmos/auth/v1beta1/accounts/{address}"; @@ -22,6 +28,21 @@ service Query { } } +// QueryAccountsRequest is the request type for the Query/Accounts RPC method. +message QueryAccountsRequest { + // pagination defines an optional pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 1; +} + +// QueryAccountsResponse is the response type for the Query/Accounts RPC method. +message QueryAccountsResponse { + // accounts are the existing accounts + repeated google.protobuf.Any accounts = 1 [(cosmos_proto.accepts_interface) = "AccountI"]; + + // pagination defines the pagination in the response. + cosmos.base.query.v1beta1.PageResponse pagination = 2; +} + // QueryAccountRequest is the request type for the Query/Account RPC method. message QueryAccountRequest { option (gogoproto.equal) = false; diff --git a/proto/cosmos/staking/v1beta1/staking.proto b/proto/cosmos/staking/v1beta1/staking.proto index e37b28b6d098..76e9599e2d35 100644 --- a/proto/cosmos/staking/v1beta1/staking.proto +++ b/proto/cosmos/staking/v1beta1/staking.proto @@ -28,7 +28,7 @@ message CommissionRates { 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]; + 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\"", @@ -49,9 +49,9 @@ message Commission { 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]; + 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 + google.protobuf.Timestamp update_time = 2 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true, (gogoproto.moretags) = "yaml:\"update_time\""]; } @@ -61,15 +61,15 @@ message Description { option (gogoproto.goproto_stringer) = false; // moniker defines a human-readable name for the validator. - string moniker = 1; + string moniker = 1; // identity defines an optional identity signature (ex. UPort or Keybase). - string identity = 2; + string identity = 2; // website defines an optional website link. - string website = 3; + 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; + string details = 5; } // Validator defines a validator, together with the total amount of the @@ -86,12 +86,12 @@ message Validator { 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\""]; + 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; + bool jailed = 3; // status is the validator status (bonded/unbonding/unbonded). BondStatus status = 4; // tokens define the delegated tokens (incl. self-delegation). @@ -103,16 +103,16 @@ message Validator { (gogoproto.nullable) = false ]; // description defines the description terms for the validator. - Description description = 7 [(gogoproto.nullable) = false]; + 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\""]; + 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 + 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]; + Commission commission = 10 [(gogoproto.nullable) = false]; // min_self_delegation is the validator's self declared minimum self delegation. - string min_self_delegation = 11 [ + string min_self_delegation = 11 [ (gogoproto.moretags) = "yaml:\"min_self_delegation\"", (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.nullable) = false @@ -201,9 +201,9 @@ message UnbondingDelegation { option (gogoproto.goproto_stringer) = false; // delegator_address is the bech32-encoded address of the delegator. - string delegator_address = 1 [(gogoproto.moretags) = "yaml:\"delegator_address\""]; + 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\""]; + 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 } @@ -214,7 +214,7 @@ message UnbondingDelegationEntry { option (gogoproto.goproto_stringer) = false; // creation_height is the height which the unbonding took place. - int64 creation_height = 1 [(gogoproto.moretags) = "yaml:\"creation_height\""]; + 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\""]; @@ -234,7 +234,7 @@ message RedelegationEntry { option (gogoproto.goproto_stringer) = false; // creation_height defines the height which the redelegation took place. - int64 creation_height = 1 [(gogoproto.moretags) = "yaml:\"creation_height\""]; + 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\""]; @@ -257,13 +257,13 @@ message Redelegation { option (gogoproto.goproto_stringer) = false; // delegator_address is the bech32-encoded address of the delegator. - string delegator_address = 1 [(gogoproto.moretags) = "yaml:\"delegator_address\""]; + 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\""]; + 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\""]; + 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 + repeated RedelegationEntry entries = 4 [(gogoproto.nullable) = false]; // redelegation entries } // Params defines the parameters for the staking module. @@ -275,13 +275,13 @@ message Params { 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\""]; + 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\""]; + 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\""]; + string bond_denom = 5 [(gogoproto.moretags) = "yaml:\"bond_denom\""]; } // DelegationResponse is equivalent to Delegation except that it contains a diff --git a/x/auth/client/cli/cli_test.go b/x/auth/client/cli/cli_test.go index c9e4a1cb8bda..5e0a262e8ab5 100644 --- a/x/auth/client/cli/cli_test.go +++ b/x/auth/client/cli/cli_test.go @@ -851,6 +851,20 @@ func (s *IntegrationTestSuite) TestGetAccountCmd() { } } +func (s *IntegrationTestSuite) TestGetAccountsCmd() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + + out, err := clitestutil.ExecTestCLICmd(clientCtx, authcli.GetAccountsCmd(), []string{ + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }) + s.Require().NoError(err) + + var res authtypes.QueryAccountsResponse + s.Require().NoError(val.ClientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), &res)) + s.Require().NotEmpty(res.Accounts) +} + func TestGetBroadcastCommand_OfflineFlag(t *testing.T) { clientCtx := client.Context{}.WithOffline(true) clientCtx = clientCtx.WithTxConfig(simapp.MakeTestEncodingConfig().TxConfig) diff --git a/x/auth/client/cli/query.go b/x/auth/client/cli/query.go index a236e900fbe5..8ee3a05758d6 100644 --- a/x/auth/client/cli/query.go +++ b/x/auth/client/cli/query.go @@ -34,6 +34,7 @@ func GetQueryCmd() *cobra.Command { cmd.AddCommand( GetAccountCmd(), + GetAccountsCmd(), QueryParamsCmd(), ) @@ -103,6 +104,38 @@ func GetAccountCmd() *cobra.Command { return cmd } +// GetAccountsCmd returns a query command that will display a list of accounts +func GetAccountsCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "accounts", + Short: "Query all the accounts", + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } + + queryClient := types.NewQueryClient(clientCtx) + res, err := queryClient.Accounts(cmd.Context(), &types.QueryAccountsRequest{Pagination: pageReq}) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + flags.AddPaginationFlagsToCmd(cmd, "all-accounts") + + return cmd +} + // QueryTxsByEventsCmd returns a command to search through transactions by events. func QueryTxsByEventsCmd() *cobra.Command { cmd := &cobra.Command{ diff --git a/x/auth/keeper/grpc_query.go b/x/auth/keeper/grpc_query.go index cf3c7b844362..4305c1cd0a8e 100644 --- a/x/auth/keeper/grpc_query.go +++ b/x/auth/keeper/grpc_query.go @@ -3,6 +3,9 @@ package keeper import ( "context" + "github.com/cosmos/cosmos-sdk/store/prefix" + "github.com/cosmos/cosmos-sdk/types/query" + "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -13,6 +16,34 @@ import ( var _ types.QueryServer = AccountKeeper{} +func (ak AccountKeeper) Accounts(c context.Context, req *types.QueryAccountsRequest) (*types.QueryAccountsResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + + ctx := sdk.UnwrapSDKContext(c) + store := ctx.KVStore(ak.key) + accountsStore := prefix.NewStore(store, types.AddressStoreKeyPrefix) + + var accounts []*codectypes.Any + pageRes, err := query.Paginate(accountsStore, req.Pagination, func(key, value []byte) error { + account := ak.decodeAccount(value) + any, err := codectypes.NewAnyWithValue(account) + if err != nil { + return err + } + + accounts = append(accounts, any) + return nil + }) + + if err != nil { + return nil, status.Errorf(codes.Internal, "paginate: %v", err) + } + + return &types.QueryAccountsResponse{Accounts: accounts, Pagination: pageRes}, err +} + // Account returns account details based on address func (ak AccountKeeper) Account(c context.Context, req *types.QueryAccountRequest) (*types.QueryAccountResponse, error) { if req == nil { diff --git a/x/auth/keeper/grpc_query_test.go b/x/auth/keeper/grpc_query_test.go index 47c48f027629..e593829a7172 100644 --- a/x/auth/keeper/grpc_query_test.go +++ b/x/auth/keeper/grpc_query_test.go @@ -8,6 +8,64 @@ import ( "github.com/cosmos/cosmos-sdk/x/auth/types" ) +func (suite *KeeperTestSuite) TestGRPCQueryAccounts() { + var ( + req *types.QueryAccountsRequest + ) + _, _, first := testdata.KeyTestPubAddr() + _, _, second := testdata.KeyTestPubAddr() + + testCases := []struct { + msg string + malleate func() + expPass bool + posttests func(res *types.QueryAccountsResponse) + }{ + { + "success", + func() { + suite.app.AccountKeeper.SetAccount(suite.ctx, + suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, first)) + suite.app.AccountKeeper.SetAccount(suite.ctx, + suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, second)) + req = &types.QueryAccountsRequest{} + }, + true, + func(res *types.QueryAccountsResponse) { + for _, acc := range res.Accounts { + var account types.AccountI + err := suite.app.InterfaceRegistry().UnpackAny(acc, &account) + suite.Require().NoError(err) + + suite.Require().True( + first.Equals(account.GetAddress()) || second.Equals(account.GetAddress())) + } + }, + }, + } + + 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.Accounts(ctx, req) + + if tc.expPass { + suite.Require().NoError(err) + suite.Require().NotNil(res) + } else { + suite.Require().Error(err) + suite.Require().Nil(res) + } + + tc.posttests(res) + }) + } +} + func (suite *KeeperTestSuite) TestGRPCQueryAccount() { var ( req *types.QueryAccountRequest diff --git a/x/auth/types/query.pb.go b/x/auth/types/query.pb.go index fcb0efa96614..25c0a13630ad 100644 --- a/x/auth/types/query.pb.go +++ b/x/auth/types/query.pb.go @@ -7,6 +7,7 @@ import ( context "context" fmt "fmt" types "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" @@ -31,6 +32,107 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package +// QueryAccountsRequest is the request type for the Query/Accounts RPC method. +type QueryAccountsRequest struct { + // pagination defines an optional pagination for the request. + Pagination *query.PageRequest `protobuf:"bytes,1,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryAccountsRequest) Reset() { *m = QueryAccountsRequest{} } +func (m *QueryAccountsRequest) String() string { return proto.CompactTextString(m) } +func (*QueryAccountsRequest) ProtoMessage() {} +func (*QueryAccountsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_c451370b3929a27c, []int{0} +} +func (m *QueryAccountsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryAccountsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryAccountsRequest.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 *QueryAccountsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryAccountsRequest.Merge(m, src) +} +func (m *QueryAccountsRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryAccountsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryAccountsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryAccountsRequest proto.InternalMessageInfo + +func (m *QueryAccountsRequest) GetPagination() *query.PageRequest { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryAccountsResponse is the response type for the Query/Accounts RPC method. +type QueryAccountsResponse struct { + // accounts are the existing accounts + Accounts []*types.Any `protobuf:"bytes,1,rep,name=accounts,proto3" json:"accounts,omitempty"` + // pagination defines the pagination in the response. + Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryAccountsResponse) Reset() { *m = QueryAccountsResponse{} } +func (m *QueryAccountsResponse) String() string { return proto.CompactTextString(m) } +func (*QueryAccountsResponse) ProtoMessage() {} +func (*QueryAccountsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_c451370b3929a27c, []int{1} +} +func (m *QueryAccountsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryAccountsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryAccountsResponse.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 *QueryAccountsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryAccountsResponse.Merge(m, src) +} +func (m *QueryAccountsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryAccountsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryAccountsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryAccountsResponse proto.InternalMessageInfo + +func (m *QueryAccountsResponse) GetAccounts() []*types.Any { + if m != nil { + return m.Accounts + } + return nil +} + +func (m *QueryAccountsResponse) GetPagination() *query.PageResponse { + if m != nil { + return m.Pagination + } + return nil +} + // QueryAccountRequest is the request type for the Query/Account RPC method. type QueryAccountRequest struct { // address defines the address to query for. @@ -41,7 +143,7 @@ func (m *QueryAccountRequest) Reset() { *m = QueryAccountRequest{} } func (m *QueryAccountRequest) String() string { return proto.CompactTextString(m) } func (*QueryAccountRequest) ProtoMessage() {} func (*QueryAccountRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_c451370b3929a27c, []int{0} + return fileDescriptor_c451370b3929a27c, []int{2} } func (m *QueryAccountRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -80,7 +182,7 @@ func (m *QueryAccountResponse) Reset() { *m = QueryAccountResponse{} } func (m *QueryAccountResponse) String() string { return proto.CompactTextString(m) } func (*QueryAccountResponse) ProtoMessage() {} func (*QueryAccountResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_c451370b3929a27c, []int{1} + return fileDescriptor_c451370b3929a27c, []int{3} } func (m *QueryAccountResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -124,7 +226,7 @@ func (m *QueryParamsRequest) Reset() { *m = QueryParamsRequest{} } func (m *QueryParamsRequest) String() string { return proto.CompactTextString(m) } func (*QueryParamsRequest) ProtoMessage() {} func (*QueryParamsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_c451370b3929a27c, []int{2} + return fileDescriptor_c451370b3929a27c, []int{4} } func (m *QueryParamsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -163,7 +265,7 @@ func (m *QueryParamsResponse) Reset() { *m = QueryParamsResponse{} } func (m *QueryParamsResponse) String() string { return proto.CompactTextString(m) } func (*QueryParamsResponse) ProtoMessage() {} func (*QueryParamsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_c451370b3929a27c, []int{3} + return fileDescriptor_c451370b3929a27c, []int{5} } func (m *QueryParamsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -200,6 +302,8 @@ func (m *QueryParamsResponse) GetParams() Params { } func init() { + proto.RegisterType((*QueryAccountsRequest)(nil), "cosmos.auth.v1beta1.QueryAccountsRequest") + proto.RegisterType((*QueryAccountsResponse)(nil), "cosmos.auth.v1beta1.QueryAccountsResponse") proto.RegisterType((*QueryAccountRequest)(nil), "cosmos.auth.v1beta1.QueryAccountRequest") proto.RegisterType((*QueryAccountResponse)(nil), "cosmos.auth.v1beta1.QueryAccountResponse") proto.RegisterType((*QueryParamsRequest)(nil), "cosmos.auth.v1beta1.QueryParamsRequest") @@ -209,34 +313,41 @@ func init() { func init() { proto.RegisterFile("cosmos/auth/v1beta1/query.proto", fileDescriptor_c451370b3929a27c) } var fileDescriptor_c451370b3929a27c = []byte{ - // 424 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x91, 0x31, 0x6f, 0xda, 0x40, - 0x14, 0xc7, 0x6d, 0xd4, 0x02, 0xbd, 0x76, 0x3a, 0x3c, 0x50, 0xd3, 0xda, 0x95, 0x3b, 0x00, 0x03, - 0x77, 0x82, 0x4e, 0x54, 0x5d, 0xa0, 0x53, 0x37, 0x6a, 0x75, 0xea, 0x52, 0x9d, 0xcd, 0xd5, 0xa0, - 0x16, 0x9f, 0xf1, 0x9d, 0xab, 0xa2, 0xaa, 0x52, 0x94, 0x29, 0x5b, 0x22, 0x65, 0xcd, 0xc0, 0x87, - 0xc8, 0x87, 0x40, 0x99, 0x90, 0xb2, 0x64, 0x8a, 0x22, 0xc8, 0x90, 0x8f, 0x11, 0x71, 0x77, 0x1e, - 0x90, 0x1c, 0x25, 0x13, 0xbc, 0xf7, 0xfe, 0xff, 0xff, 0xfb, 0xf9, 0x1d, 0x70, 0x43, 0xc6, 0x67, - 0x8c, 0x63, 0x92, 0x89, 0x09, 0xfe, 0xd3, 0x0d, 0xa8, 0x20, 0x5d, 0x3c, 0xcf, 0x68, 0xba, 0x40, - 0x49, 0xca, 0x04, 0x83, 0x35, 0x25, 0x40, 0x3b, 0x01, 0xd2, 0x02, 0xdb, 0x8a, 0x58, 0xc4, 0xe4, - 0x1c, 0xef, 0xfe, 0x29, 0xa9, 0xfd, 0x3a, 0x62, 0x2c, 0xfa, 0x4d, 0xb1, 0xac, 0x82, 0xec, 0x27, - 0x26, 0xb1, 0x4e, 0xb1, 0xdf, 0xe8, 0x11, 0x49, 0xa6, 0x98, 0xc4, 0x31, 0x13, 0x44, 0x4c, 0x59, - 0xcc, 0xf5, 0xd4, 0x29, 0x82, 0x90, 0x0b, 0x75, 0xb0, 0x9a, 0xff, 0x50, 0x1b, 0x35, 0x90, 0x2c, - 0xbc, 0x3e, 0xa8, 0x7d, 0xdd, 0xd1, 0x0e, 0xc2, 0x90, 0x65, 0xb1, 0xf0, 0xe9, 0x3c, 0xa3, 0x5c, - 0xc0, 0x3a, 0xa8, 0x90, 0xf1, 0x38, 0xa5, 0x9c, 0xd7, 0xcd, 0x77, 0x66, 0xeb, 0x85, 0x9f, 0x97, - 0x1f, 0xab, 0x47, 0x4b, 0xd7, 0xb8, 0x5b, 0xba, 0x86, 0xf7, 0x0d, 0x58, 0xfb, 0x56, 0x9e, 0xb0, - 0x98, 0x53, 0xf8, 0x09, 0x54, 0x88, 0x6a, 0x49, 0xef, 0xcb, 0x9e, 0x85, 0x14, 0x3d, 0xca, 0x3f, - 0x0c, 0x0d, 0xe2, 0xc5, 0xf0, 0xd5, 0xc5, 0x79, 0xa7, 0xaa, 0xbd, 0x5f, 0xfc, 0xdc, 0xe2, 0x59, - 0x00, 0xca, 0xd4, 0x11, 0x49, 0xc9, 0x8c, 0x6b, 0x1e, 0x6f, 0xa4, 0x31, 0xf3, 0xae, 0x5e, 0xd5, - 0x07, 0xe5, 0x44, 0x76, 0xf4, 0xa6, 0x06, 0x2a, 0xb8, 0x36, 0x52, 0xa6, 0xe1, 0xb3, 0xd5, 0xb5, - 0x6b, 0xf8, 0xda, 0xd0, 0x3b, 0x2b, 0x81, 0xe7, 0x32, 0x12, 0x1e, 0x9b, 0xa0, 0xa2, 0x39, 0x60, - 0xab, 0x30, 0xa0, 0xe0, 0x42, 0x76, 0xfb, 0x09, 0x4a, 0x45, 0xe9, 0xe1, 0xc3, 0xcb, 0xdb, 0xd3, - 0x52, 0x1b, 0x36, 0x71, 0xe1, 0x3b, 0x29, 0x35, 0xc7, 0xff, 0xf4, 0x89, 0xff, 0xc3, 0x03, 0x13, - 0x94, 0x15, 0x34, 0x6c, 0x3e, 0xbc, 0x66, 0xef, 0x42, 0x76, 0xeb, 0x71, 0xa1, 0xc6, 0x79, 0x2f, - 0x71, 0xde, 0xc2, 0x46, 0x21, 0x8e, 0x3a, 0xcf, 0xf0, 0xf3, 0x6a, 0xe3, 0x98, 0xeb, 0x8d, 0x63, - 0xde, 0x6c, 0x1c, 0xf3, 0x64, 0xeb, 0x18, 0xeb, 0xad, 0x63, 0x5c, 0x6d, 0x1d, 0xe3, 0x7b, 0x3b, - 0x9a, 0x8a, 0x49, 0x16, 0xa0, 0x90, 0xcd, 0xf2, 0x00, 0xf5, 0xd3, 0xe1, 0xe3, 0x5f, 0xf8, 0xaf, - 0x4a, 0x13, 0x8b, 0x84, 0xf2, 0xa0, 0x2c, 0x1f, 0xfc, 0xc3, 0x7d, 0x00, 0x00, 0x00, 0xff, 0xff, - 0xef, 0x40, 0xd8, 0x2e, 0x25, 0x03, 0x00, 0x00, + // 537 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0x41, 0x6b, 0x13, 0x4f, + 0x18, 0xc6, 0x77, 0xda, 0xff, 0x3f, 0x89, 0x53, 0x4f, 0xd3, 0x08, 0x71, 0x6b, 0x77, 0xcb, 0x8a, + 0x26, 0x29, 0x74, 0x86, 0xc6, 0x53, 0x45, 0x84, 0x46, 0x50, 0xbc, 0xc5, 0xc5, 0x93, 0x07, 0x65, + 0x36, 0x19, 0xb7, 0x41, 0xb3, 0xb3, 0xcd, 0xec, 0x8a, 0x41, 0x04, 0xf1, 0xd4, 0x9b, 0x82, 0x5f, + 0x20, 0x37, 0xbf, 0x80, 0x1f, 0xa2, 0x78, 0x2a, 0x78, 0xf1, 0x24, 0x92, 0x78, 0xf0, 0x63, 0x48, + 0x66, 0xde, 0x89, 0x8d, 0xac, 0x26, 0xa7, 0xdd, 0x99, 0x79, 0x9f, 0xe7, 0xf9, 0xbd, 0xef, 0x0c, + 0xf6, 0xbb, 0x52, 0x0d, 0xa4, 0x62, 0x3c, 0xcf, 0x8e, 0xd8, 0x8b, 0xfd, 0x48, 0x64, 0x7c, 0x9f, + 0x1d, 0xe7, 0x62, 0x38, 0xa2, 0xe9, 0x50, 0x66, 0x92, 0x6c, 0x9a, 0x02, 0x3a, 0x2b, 0xa0, 0x50, + 0xe0, 0xee, 0x82, 0x2a, 0xe2, 0x4a, 0x98, 0xea, 0xb9, 0x36, 0xe5, 0x71, 0x3f, 0xe1, 0x59, 0x5f, + 0x26, 0xc6, 0xc0, 0xad, 0xc6, 0x32, 0x96, 0xfa, 0x97, 0xcd, 0xfe, 0x60, 0xf7, 0x72, 0x2c, 0x65, + 0xfc, 0x5c, 0x30, 0xbd, 0x8a, 0xf2, 0xa7, 0x8c, 0x27, 0x90, 0xe8, 0x5e, 0x81, 0x23, 0x9e, 0xf6, + 0x19, 0x4f, 0x12, 0x99, 0x69, 0x37, 0x05, 0xa7, 0x5e, 0x11, 0xb0, 0x86, 0x03, 0x63, 0x73, 0xfe, + 0xc4, 0x24, 0x02, 0xbc, 0x5e, 0x04, 0x8f, 0x71, 0xf5, 0xc1, 0x8c, 0xf5, 0xb0, 0xdb, 0x95, 0x79, + 0x92, 0xa9, 0x50, 0x1c, 0xe7, 0x42, 0x65, 0xe4, 0x2e, 0xc6, 0xbf, 0xa9, 0x6b, 0x68, 0x07, 0x35, + 0x36, 0x5a, 0xd7, 0x29, 0x48, 0x67, 0x2d, 0x52, 0x33, 0x10, 0x48, 0xa3, 0x1d, 0x1e, 0x0b, 0xd0, + 0x86, 0xe7, 0x94, 0xc1, 0x18, 0xe1, 0x4b, 0x7f, 0x04, 0xa8, 0x54, 0x26, 0x4a, 0x90, 0xdb, 0xb8, + 0xc2, 0x61, 0xaf, 0x86, 0x76, 0xd6, 0x1b, 0x1b, 0xad, 0x2a, 0x35, 0x5d, 0x52, 0x3b, 0x00, 0x7a, + 0x98, 0x8c, 0xda, 0x17, 0x3f, 0x7f, 0xda, 0xab, 0x80, 0xfa, 0x7e, 0x38, 0xd7, 0x90, 0x7b, 0x0b, + 0x84, 0x6b, 0x9a, 0xb0, 0xbe, 0x94, 0xd0, 0x84, 0x2f, 0x20, 0x1e, 0xe0, 0xcd, 0xf3, 0x84, 0x76, + 0x02, 0x35, 0x5c, 0xe6, 0xbd, 0xde, 0x50, 0x28, 0xa5, 0xdb, 0xbf, 0x10, 0xda, 0xe5, 0xcd, 0xca, + 0xc9, 0xd8, 0x77, 0x7e, 0x8e, 0x7d, 0x27, 0x78, 0xb8, 0x38, 0xbd, 0x79, 0x6f, 0xb7, 0x70, 0x19, + 0x38, 0x61, 0x74, 0xab, 0xb4, 0x66, 0x25, 0x41, 0x15, 0x13, 0xed, 0xda, 0xe1, 0x43, 0x3e, 0xb0, + 0x37, 0x12, 0x74, 0x00, 0xd3, 0xee, 0x42, 0xd4, 0x01, 0x2e, 0xa5, 0x7a, 0x07, 0x92, 0xb6, 0x68, + 0xc1, 0xe3, 0xa4, 0x46, 0xd4, 0xfe, 0xef, 0xf4, 0x9b, 0xef, 0x84, 0x20, 0x68, 0x7d, 0x5c, 0xc7, + 0xff, 0x6b, 0x4b, 0x72, 0x82, 0xb0, 0xe5, 0x50, 0xa4, 0x59, 0xe8, 0x50, 0xf4, 0x4a, 0xdc, 0xdd, + 0x55, 0x4a, 0x0d, 0x68, 0x70, 0xed, 0xed, 0x97, 0x1f, 0x1f, 0xd6, 0x7c, 0xb2, 0xcd, 0x0a, 0x5f, + 0xab, 0x4d, 0x7f, 0x87, 0x70, 0x19, 0xb4, 0xa4, 0xb1, 0xd4, 0xde, 0x82, 0x34, 0x57, 0xa8, 0x04, + 0x0e, 0xa6, 0x39, 0x9a, 0xa4, 0xfe, 0x4f, 0x0e, 0xf6, 0x0a, 0x6e, 0xfb, 0x35, 0x79, 0x83, 0x70, + 0xc9, 0xcc, 0x8f, 0xd4, 0xff, 0x1e, 0xb3, 0x70, 0x59, 0x6e, 0x63, 0x79, 0x21, 0xe0, 0x5c, 0xd5, + 0x38, 0xdb, 0x64, 0xab, 0x10, 0xc7, 0xdc, 0x54, 0xfb, 0xce, 0xe9, 0xc4, 0x43, 0x67, 0x13, 0x0f, + 0x7d, 0x9f, 0x78, 0xe8, 0xfd, 0xd4, 0x73, 0xce, 0xa6, 0x9e, 0xf3, 0x75, 0xea, 0x39, 0x8f, 0x9a, + 0x71, 0x3f, 0x3b, 0xca, 0x23, 0xda, 0x95, 0x03, 0x6b, 0x60, 0x3e, 0x7b, 0xaa, 0xf7, 0x8c, 0xbd, + 0x34, 0x6e, 0xd9, 0x28, 0x15, 0x2a, 0x2a, 0xe9, 0xb7, 0x77, 0xe3, 0x57, 0x00, 0x00, 0x00, 0xff, + 0xff, 0x2a, 0xe1, 0x81, 0xd3, 0xdf, 0x04, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -251,6 +362,8 @@ const _ = grpc.SupportPackageIsVersion4 // // 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 { + // Accounts returns all the existing accounts + Accounts(ctx context.Context, in *QueryAccountsRequest, opts ...grpc.CallOption) (*QueryAccountsResponse, error) // Account returns account details based on address. Account(ctx context.Context, in *QueryAccountRequest, opts ...grpc.CallOption) (*QueryAccountResponse, error) // Params queries all parameters. @@ -265,6 +378,15 @@ func NewQueryClient(cc grpc1.ClientConn) QueryClient { return &queryClient{cc} } +func (c *queryClient) Accounts(ctx context.Context, in *QueryAccountsRequest, opts ...grpc.CallOption) (*QueryAccountsResponse, error) { + out := new(QueryAccountsResponse) + err := c.cc.Invoke(ctx, "/cosmos.auth.v1beta1.Query/Accounts", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *queryClient) Account(ctx context.Context, in *QueryAccountRequest, opts ...grpc.CallOption) (*QueryAccountResponse, error) { out := new(QueryAccountResponse) err := c.cc.Invoke(ctx, "/cosmos.auth.v1beta1.Query/Account", in, out, opts...) @@ -285,6 +407,8 @@ func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts . // QueryServer is the server API for Query service. type QueryServer interface { + // Accounts returns all the existing accounts + Accounts(context.Context, *QueryAccountsRequest) (*QueryAccountsResponse, error) // Account returns account details based on address. Account(context.Context, *QueryAccountRequest) (*QueryAccountResponse, error) // Params queries all parameters. @@ -295,6 +419,9 @@ type QueryServer interface { type UnimplementedQueryServer struct { } +func (*UnimplementedQueryServer) Accounts(ctx context.Context, req *QueryAccountsRequest) (*QueryAccountsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Accounts not implemented") +} func (*UnimplementedQueryServer) Account(ctx context.Context, req *QueryAccountRequest) (*QueryAccountResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Account not implemented") } @@ -306,6 +433,24 @@ func RegisterQueryServer(s grpc1.Server, srv QueryServer) { s.RegisterService(&_Query_serviceDesc, srv) } +func _Query_Accounts_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryAccountsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Accounts(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cosmos.auth.v1beta1.Query/Accounts", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Accounts(ctx, req.(*QueryAccountsRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _Query_Account_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(QueryAccountRequest) if err := dec(in); err != nil { @@ -346,6 +491,10 @@ var _Query_serviceDesc = grpc.ServiceDesc{ ServiceName: "cosmos.auth.v1beta1.Query", HandlerType: (*QueryServer)(nil), Methods: []grpc.MethodDesc{ + { + MethodName: "Accounts", + Handler: _Query_Accounts_Handler, + }, { MethodName: "Account", Handler: _Query_Account_Handler, @@ -359,6 +508,90 @@ var _Query_serviceDesc = grpc.ServiceDesc{ Metadata: "cosmos/auth/v1beta1/query.proto", } +func (m *QueryAccountsRequest) 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 *QueryAccountsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryAccountsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryAccountsResponse) 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 *QueryAccountsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryAccountsResponse) 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.Accounts) > 0 { + for iNdEx := len(m.Accounts) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Accounts[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 *QueryAccountRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -491,6 +724,38 @@ func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { dAtA[offset] = uint8(v) return base } +func (m *QueryAccountsRequest) 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 *QueryAccountsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Accounts) > 0 { + for _, e := range m.Accounts { + 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 *QueryAccountRequest) Size() (n int) { if m == nil { return 0 @@ -543,6 +808,212 @@ func sovQuery(x uint64) (n int) { func sozQuery(x uint64) (n int) { return sovQuery(uint64((x << 1) ^ uint64((int64(x) >> 63)))) } +func (m *QueryAccountsRequest) 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: QueryAccountsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAccountsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageRequest{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryAccountsResponse) 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: QueryAccountsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAccountsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Accounts", 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.Accounts = append(m.Accounts, &types.Any{}) + if err := m.Accounts[len(m.Accounts)-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 *QueryAccountRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/x/auth/types/query.pb.gw.go b/x/auth/types/query.pb.gw.go index 1f9c0a70a152..f6d93f2924f2 100644 --- a/x/auth/types/query.pb.gw.go +++ b/x/auth/types/query.pb.gw.go @@ -31,6 +31,42 @@ var _ = runtime.String var _ = utilities.NewDoubleArray var _ = descriptor.ForMessage +var ( + filter_Query_Accounts_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_Query_Accounts_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAccountsRequest + 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_Accounts_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.Accounts(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Accounts_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAccountsRequest + 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_Accounts_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.Accounts(ctx, &protoReq) + return msg, metadata, err + +} + 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 var metadata runtime.ServerMetadata @@ -109,6 +145,26 @@ func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshal // 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_Accounts_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_Accounts_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_Accounts_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + 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() @@ -190,6 +246,26 @@ func RegisterQueryHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc // "QueryClient" to call the correct interceptors. func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error { + mux.Handle("GET", pattern_Query_Accounts_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_Accounts_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_Accounts_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + 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() @@ -234,12 +310,16 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie } var ( + pattern_Query_Accounts_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "auth", "v1beta1", "accounts"}, "", runtime.AssumeColonVerbOpt(false))) + pattern_Query_Account_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"cosmos", "auth", "v1beta1", "accounts", "address"}, "", runtime.AssumeColonVerbOpt(false))) pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "auth", "v1beta1", "params"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( + forward_Query_Accounts_0 = runtime.ForwardResponseMessage + forward_Query_Account_0 = runtime.ForwardResponseMessage forward_Query_Params_0 = runtime.ForwardResponseMessage From f49e1554e62479fc818aecd1c811a185081a668c Mon Sep 17 00:00:00 2001 From: Riccardo Montagnin Date: Mon, 22 Feb 2021 16:14:09 +0100 Subject: [PATCH 096/214] Deprecate SetFullFundraiserPath in favor of SetPurpose and SetCoinType (#8629) Co-authored-by: Alessio Treglia --- CHANGELOG.md | 1 + client/keys/add_ledger_test.go | 4 +-- client/keys/delete_test.go | 2 +- client/keys/export_test.go | 2 +- client/keys/list_test.go | 2 +- types/address.go | 5 ++- types/config.go | 49 +++++++++++++++++++++------- types/config_test.go | 12 +++++++ x/authz/types/authorization_grant.go | 3 +- x/staking/types/authz.go | 3 +- x/staking/types/authz_test.go | 3 +- 11 files changed, 66 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f06db43e4f37..11ef49af3134 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (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. +* [\#8629](https://github.com/cosmos/cosmos-sdk/pull/8629) Deprecated `SetFullFundraiserPath` from `Config` in favor of `SetPurpose` and `SetCoinType`. ### State Machine Breaking diff --git a/client/keys/add_ledger_test.go b/client/keys/add_ledger_test.go index b8ba1ec7f59e..5e32f755f70e 100644 --- a/client/keys/add_ledger_test.go +++ b/client/keys/add_ledger_test.go @@ -29,8 +29,8 @@ func Test_runAddCmdLedgerWithCustomCoinType(t *testing.T) { bech32PrefixConsAddr := "terravalcons" bech32PrefixConsPub := "terravalconspub" + config.SetPurpose(44) config.SetCoinType(330) - config.SetFullFundraiserPath("44'/330'/0'/0/0") config.SetBech32PrefixForAccount(bech32PrefixAccAddr, bech32PrefixAccPub) config.SetBech32PrefixForValidator(bech32PrefixValAddr, bech32PrefixValPub) config.SetBech32PrefixForConsensusNode(bech32PrefixConsAddr, bech32PrefixConsPub) @@ -77,8 +77,8 @@ func Test_runAddCmdLedgerWithCustomCoinType(t *testing.T) { "terrapub1addwnpepqvpg7r26nl2pvqqern00m6s9uaax3hauu2rzg8qpjzq9hy6xve7sw0d84m6", sdk.MustBech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, key1.GetPubKey())) + config.SetPurpose(44) config.SetCoinType(118) - config.SetFullFundraiserPath("44'/118'/0'/0/0") config.SetBech32PrefixForAccount(sdk.Bech32PrefixAccAddr, sdk.Bech32PrefixAccPub) config.SetBech32PrefixForValidator(sdk.Bech32PrefixValAddr, sdk.Bech32PrefixValPub) config.SetBech32PrefixForConsensusNode(sdk.Bech32PrefixConsAddr, sdk.Bech32PrefixConsPub) diff --git a/client/keys/delete_test.go b/client/keys/delete_test.go index 5a0013967196..49da92bf1f72 100644 --- a/client/keys/delete_test.go +++ b/client/keys/delete_test.go @@ -31,7 +31,7 @@ func Test_runDeleteCmd(t *testing.T) { fakeKeyName1 := "runDeleteCmd_Key1" fakeKeyName2 := "runDeleteCmd_Key2" - path := sdk.GetConfig().GetFullFundraiserPath() + path := sdk.GetConfig().GetFullBIP44Path() kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, kbHome, mockIn) require.NoError(t, err) diff --git a/client/keys/export_test.go b/client/keys/export_test.go index b01bbf823023..782af754024f 100644 --- a/client/keys/export_test.go +++ b/client/keys/export_test.go @@ -31,7 +31,7 @@ func Test_runExportCmd(t *testing.T) { kb.Delete("keyname1") // nolint:errcheck }) - path := sdk.GetConfig().GetFullFundraiserPath() + path := sdk.GetConfig().GetFullBIP44Path() _, err = kb.NewAccount("keyname1", testutil.TestMnemonic, "", path, hd.Secp256k1) require.NoError(t, err) diff --git a/client/keys/list_test.go b/client/keys/list_test.go index 5904f74bfdd2..17f8dd8e4f94 100644 --- a/client/keys/list_test.go +++ b/client/keys/list_test.go @@ -30,7 +30,7 @@ func Test_runListCmd(t *testing.T) { clientCtx := client.Context{}.WithKeyring(kb) ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx) - path := "" //sdk.GetConfig().GetFullFundraiserPath() + path := "" //sdk.GetConfig().GetFullBIP44Path() _, err = kb.NewAccount("something", testutil.TestMnemonic, "", path, hd.Secp256k1) require.NoError(t, err) diff --git a/types/address.go b/types/address.go index eabff6fa97ee..9f3f8216051e 100644 --- a/types/address.go +++ b/types/address.go @@ -26,13 +26,16 @@ const ( // config.SetBech32PrefixForAccount(yourBech32PrefixAccAddr, yourBech32PrefixAccPub) // config.SetBech32PrefixForValidator(yourBech32PrefixValAddr, yourBech32PrefixValPub) // config.SetBech32PrefixForConsensusNode(yourBech32PrefixConsAddr, yourBech32PrefixConsPub) + // config.SetPurpose(yourPurpose) // config.SetCoinType(yourCoinType) - // config.SetFullFundraiserPath(yourFullFundraiserPath) // config.Seal() // Bech32MainPrefix defines the main SDK Bech32 prefix of an account's address Bech32MainPrefix = "cosmos" + // Purpose is the ATOM purpose as defined in SLIP44 (https://github.com/satoshilabs/slips/blob/master/slip-0044.md) + Purpose = 44 + // CoinType is the ATOM coin type as defined in SLIP44 (https://github.com/satoshilabs/slips/blob/master/slip-0044.md) CoinType = 118 diff --git a/types/config.go b/types/config.go index a3181703df1e..00b701a025d7 100644 --- a/types/config.go +++ b/types/config.go @@ -2,6 +2,7 @@ package types import ( "context" + "fmt" "sync" "github.com/cosmos/cosmos-sdk/version" @@ -18,9 +19,13 @@ type Config struct { txEncoder TxEncoder addressVerifier func([]byte) error mtx sync.RWMutex - coinType uint32 - sealed bool - sealedch chan struct{} + + // SLIP-44 related + purpose uint32 + coinType uint32 + + sealed bool + sealedch chan struct{} } // cosmos-sdk wide global singleton @@ -41,9 +46,11 @@ func NewConfig() *Config { "validator_pub": Bech32PrefixValPub, "consensus_pub": Bech32PrefixConsPub, }, - coinType: CoinType, fullFundraiserPath: FullFundraiserPath, - txEncoder: nil, + + purpose: Purpose, + coinType: CoinType, + txEncoder: nil, } } @@ -112,16 +119,24 @@ func (config *Config) SetAddressVerifier(addressVerifier func([]byte) error) { config.addressVerifier = addressVerifier } -// Set the BIP-0044 CoinType code on the config -func (config *Config) SetCoinType(coinType uint32) { +// Set the FullFundraiserPath (BIP44Prefix) on the config. +// +// Deprecated: This method is supported for backward compatibility only and will be removed in a future release. Use SetPurpose and SetCoinType instead. +func (config *Config) SetFullFundraiserPath(fullFundraiserPath string) { config.assertNotSealed() - config.coinType = coinType + config.fullFundraiserPath = fullFundraiserPath } -// Set the FullFundraiserPath (BIP44Prefix) on the config -func (config *Config) SetFullFundraiserPath(fullFundraiserPath string) { +// Set the BIP-0044 Purpose code on the config +func (config *Config) SetPurpose(purpose uint32) { config.assertNotSealed() - config.fullFundraiserPath = fullFundraiserPath + config.purpose = purpose +} + +// Set the BIP-0044 CoinType code on the config +func (config *Config) SetCoinType(coinType uint32) { + config.assertNotSealed() + config.coinType = coinType } // Seal seals the config such that the config state could not be modified further @@ -181,16 +196,28 @@ func (config *Config) GetAddressVerifier() func([]byte) error { return config.addressVerifier } +// GetPurpose returns the BIP-0044 Purpose code on the config. +func (config *Config) GetPurpose() uint32 { + return config.purpose +} + // GetCoinType returns the BIP-0044 CoinType code on the config. func (config *Config) GetCoinType() uint32 { return config.coinType } // GetFullFundraiserPath returns the BIP44Prefix. +// +// Deprecated: This method is supported for backward compatibility only and will be removed in a future release. Use GetFullBIP44Path instead. func (config *Config) GetFullFundraiserPath() string { return config.fullFundraiserPath } +// GetFullBIP44Path returns the BIP44Prefix. +func (config *Config) GetFullBIP44Path() string { + return fmt.Sprintf("m/%d'/%d'/0'/0/0", config.purpose, config.coinType) +} + func KeyringServiceName() string { if len(version.Name) == 0 { return DefaultKeyringServiceName diff --git a/types/config_test.go b/types/config_test.go index e2027f38569f..df281b1f852a 100644 --- a/types/config_test.go +++ b/types/config_test.go @@ -17,6 +17,18 @@ func TestConfigTestSuite(t *testing.T) { suite.Run(t, new(configTestSuite)) } +func (s *contextTestSuite) TestConfig_SetPurpose() { + config := sdk.NewConfig() + config.SetPurpose(44) + s.Require().Equal(uint32(44), config.GetPurpose()) + + config.SetPurpose(0) + s.Require().Equal(uint32(0), config.GetPurpose()) + + config.Seal() + s.Require().Panics(func() { config.SetPurpose(10) }) +} + func (s *configTestSuite) TestConfig_SetCoinType() { config := sdk.NewConfig() config.SetCoinType(1) diff --git a/x/authz/types/authorization_grant.go b/x/authz/types/authorization_grant.go index c94e9d6d730a..03a83bdefd5c 100644 --- a/x/authz/types/authorization_grant.go +++ b/x/authz/types/authorization_grant.go @@ -3,10 +3,11 @@ package types import ( "time" + proto "github.com/gogo/protobuf/proto" + "github.com/cosmos/cosmos-sdk/codec/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/authz/exported" - proto "github.com/gogo/protobuf/proto" ) // NewAuthorizationGrant returns new AuthrizationGrant diff --git a/x/staking/types/authz.go b/x/staking/types/authz.go index aae9b706f1fe..e88288da4e2d 100644 --- a/x/staking/types/authz.go +++ b/x/staking/types/authz.go @@ -1,10 +1,11 @@ package types import ( + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" authz "github.com/cosmos/cosmos-sdk/x/authz/exported" - tmproto "github.com/tendermint/tendermint/proto/tendermint/types" ) var ( diff --git a/x/staking/types/authz_test.go b/x/staking/types/authz_test.go index 7f5dd2c22c10..18709d9ecd51 100644 --- a/x/staking/types/authz_test.go +++ b/x/staking/types/authz_test.go @@ -5,9 +5,10 @@ import ( tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + "github.com/stretchr/testify/require" + sdk "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - "github.com/stretchr/testify/require" ) var ( From 39b816ebb3952bbbbb44cbf45ab139abcee79c8e Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Mon, 22 Feb 2021 15:50:58 +0000 Subject: [PATCH 097/214] ci: update golangci-lint (#8660) --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 157f0d217850..e917d2ecbb75 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -23,7 +23,7 @@ jobs: - uses: golangci/golangci-lint-action@master with: # Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version. - version: v1.28 + version: v1.37 args: --timeout 10m github-token: ${{ secrets.github_token }} if: env.GIT_DIFF From 846cede5bfc330826c72b776f73c17d718489238 Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Mon, 22 Feb 2021 14:33:47 -0600 Subject: [PATCH 098/214] Repsond to comments, improve descriptions --- docs/architecture/adr-039-epoched-staking.md | 27 ++++++++++++-------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/docs/architecture/adr-039-epoched-staking.md b/docs/architecture/adr-039-epoched-staking.md index 9e7720627ccf..82d453b7a5af 100644 --- a/docs/architecture/adr-039-epoched-staking.md +++ b/docs/architecture/adr-039-epoched-staking.md @@ -7,7 +7,7 @@ ## Authors - Dev Ojha (@valardragon) -- Sunny Aggarwall (@sunnya97) +- Sunny Aggarwal (@sunnya97) ## Status @@ -23,17 +23,17 @@ The current proof of stake module takes the design decision to apply staking wei An alternative design choice is to allow buffering staking updates (delegations, unbonds, validators joining) for a number of blocks. This 'epoch'd proof of stake consensus provides the guarantee that the consensus weights for validators will not change mid-epoch, except in the event of a slash condition. -The decision to have immediate execution of staking changes was primarily done as it was implementationally simplest, and because we at the time believed that this would lead to better UX for clients. The UX hurdle may not be as significant as was previously thought, since it is possible to provide users acknowledgement that their bond was recorded and will be executed. +Additionally, the UX hurdle may not be as significant as was previously thought. This is because it is possible to provide users immediate acknowledgement that their bond was recorded and will be executed. Furthermore, it has become clearer over time that immediate execution of staking events comes with limitations, such as: * Threshold based cryptography. One of the main limitations is that because the validator set can change so regularly, it makes the running of multiparty computation by a fixed validator set difficult. Many threshold-based cryptographic features for blockchains such as randomness beacons and threshold decryption require a computationally-expensive DKG process (will take much longer than 1 block to create). To productively use these, we need to guarantee that the result of the DKG will be used for a reasonably long time. It wouldn't be feasible to rerun the DKG every block. By epoching staking, it guarantees we'll only need to run a new DKG once every epoch. -* Light client efficiency. This would lessen the overhead for IBC. Because of the lite client bisection algorithm, the number of headers you need to verify is related to bounding the validator set diffs between two successively verified headers. By limiting the frequency of validator set changes, we can reduce the size of IBC lite client proofs. +* Light client efficiency. This would lessen the overhead for IBC. Because of the light client bisection algorithm, the number of headers you need to verify is related to bounding the difference in validator sets between two successively verified headers. By limiting the frequency of validator set changes, we can reduce the size of IBC lite client proofs. -* Fairness of deterministic leader election. Currently we have no ways of reasoning of fairness of deterministic leader election in the presence of staking changes without epochs (tendermint/spec#217). Adding epochs at least makes it easier for our deterministic leader election to match something we can prove secure. (Albeit, we still haven’t proven if our current algorithm is fair with > 2 validators) +* Fairness of deterministic leader election. Currently we have no ways of reasoning of fairness of deterministic leader election in the presence of staking changes without epochs (tendermint/spec#217). Breaking fairness of leader election is profitable for validators, as they earn additional rewards from being the proposer. Adding epochs at least makes it easier for our deterministic leader election to match something we can prove secure. (Albeit, we still haven’t proven if our current algorithm is fair with > 2 validators in the presence of stake changes) -* Staking derivative design. Currently, reward distribution is done lazily using the F1 fee distribution. While saving computational complexity, lazy accounting increases “statefulness of staking”. Right now, each delegation entry has to track the time of last withdrawal. Handling this can be a challenge for some staking derivatives designs (see example). Force-withdrawing rewards to users can help solve this, however it is infeasible to force-withdraw rewards to users on a per block basis. With epoching, a chain could more easily alter the design to have rewards be forcefully withdrawn (iterating over delegator accounts only once per-epoch), and thus remove the time of delegation from state. This preliminarily seems like it may be of utility in certain staking derivative designs. +* Staking derivative design. Currently, reward distribution is done lazily using the F1 fee distribution. While saving computational complexity, lazy accounting requires a more stateful staking implementation. Right now, each delegation entry has to track the time of last withdrawal. Handling this can be a challenge for some staking derivatives designs that seek to provide fungibility for all tokens staked to a single validator. Force-withdrawing rewards to users can help solve this, however it is infeasible to force-withdraw rewards to users on a per block basis. With epochs, a chain could more easily alter the design to have rewards be forcefully withdrawn (iterating over delegator accounts only once per-epoch), and can thus remove delegation timing from state. This may be useful for certain staking derivative designs. ## Design considerations @@ -43,12 +43,12 @@ There is a design consideration for whether to apply a slash immediately or at t Applying it immediately can be viewed as offering greater consensus layer security, at potential costs to the aforementioned usecases. The benefits of immediate slashing for consensus layer security can be all be obtained by executing the validator jailing immediately (thus removing it from the validator set), and delaying the actual slash change to the validator's weight until the epoch boundary. For the use cases mentioned above, workarounds can be integrated to avoid problems, as follows: -- For threshold based cryptography, it can keep using the original keep epoch weights for the cryptography thresholds, but allow the underlying finality to benefit from extra security more quickly. +- For threshold based cryptography, this setting will have the threshold cryptography use the original epoch weights, while consensus has an update that lets it more rapidly benefit from additional security. If the threshold based cryptography blocks liveness of the chain, then we have effectively raised the liveness threshold of the remaining validators for the rest of the epoch. (Alternatively, jailed nodes could still contribute shares) This plan will fail in the extreme case that more than 1/3rd of the validators have been jailed within a single epoch. For such an extreme scenario, the chain already have its own custom incident response plan, and defining how to handle the threshold cryptography should be a part of that. - For light client efficiency, there can be a bit included in the header indicating an intra-epoch slash (ala https://github.com/tendermint/spec/issues/199). -- For fairness of deterministic leader election, this will cause problems with the formalization of it / proximity of implementation to formally provable spec. However, a less formal claim can be made that the amount lost due to the slash should hopefully outweigh slight biases into the leader election process. This claim is dubious with the presence of MEV, but potentially formal upperbounds on MEV for fairness here could be derived. +- For fairness of deterministic leader election, applying a slash or jailing within an epoch would break the guarantee we were seeking to provide. This then re-introduces a new (but significantly simpler) problem for trying to provide fairness guarantees. Namely, that validators can adversarially elect to remove themself from the set of proposers. From a security perspective, this could potentially be handled by two different mechanisms (or prove to still be too difficult to achieve). One is making a security statement acknowledging the ability for an adversary to force an ahead-of-time fixed threshold of users to drop out of the proposer set within an epoch. The second method would be to parameterize such that the cost of a slash within the epoch far outweights benefits due to being a proposer. However, this latter criterion is quite dubious, since being a proposer can have many advantageous side-effects in chains with complex state machines. (Namely, DeFi games such as Fomo3D) - For staking derivative design, this will not cause problems with the suggested design there, nor does it increase the stateful of staking. (As whether a slash has occured is fully queryable given the validator address) -However, for achieving consensus layer security, it suffices to apply the validator jailing immediately, but still delay the actual slash changes to waiting until the end of the epoch. This largely mitigates the concern for the fairness of deterministic leader election as well, since that validator is removed the set being rotated from immediately. +However, for achieving consensus layer security, it suffices to apply the validator jailing immediately, but still delay the actual slash changes to waiting until the end of the epoch. This largely mitigates the concern for fairness of deterministic leader election as well, since the validator is removed the set of potential proposers immediately. ### Token lockup @@ -58,7 +58,11 @@ When someone makes a transaction to delegate, even though they are not immediate For threshold based cryptography in particular, we need a pipeline for epoch changes. This is because when we are in epoch N, we want the epoch N+1 weights to be fixed so that the validator set can do the DKG accordingly. So if we are currently in epoch N, the stake weights for epoch N+1 should already be fixed, and new stake changes should be getting applied to epoch N + 2. -This can be handled by making a parameter for the epoch pipeline. This parameter should not be alterable except during hard forks, to mitigate implementation complexity of switching the pipeline length. +This can be handled by making a parameter for the epoch pipeline length. This parameter should not be alterable except during hard forks, to mitigate implementation complexity of switching the pipeline length. + + +With pipeline length 1, if I redelegate during epoch N, then my redelegation is applied prior to the beginning of epoch N+1. +With pipeline length 2, if I redelegate during epoch N, then my redelegation is applied prior to the beginning of epoch N+2. ### Rewards @@ -89,7 +93,9 @@ Then we add methods to the end blockers, to ensure that at the epoch boundary th __Step-2__: Implement querying of queued staking txs. -When querying the staking activity of a given address, the status should return not only the amount of tokens staked, but also if there are any queued stake events for that address. This will require nodes supporting querying to either do some more indexing to have this be efficiently queryable, or to have transactions +When querying the staking activity of a given address, the status should return not only the amount of tokens staked, but also if there are any queued stake events for that address. This will require more work to be done in the querying logic, to trace the queued upcoming staking events. + +As an initial implementation, this can be implemented as a linear search over all queued staking events, but eventually nodes that support querying should maintain an auxilliary hashmap to make these queries constant time. __Step-3__: Adjust gas @@ -108,3 +114,4 @@ We leave it as out of scope for how to weight future computation versus current ### Negative * Increases complexity of integrating more complex gas pricing mechanisms, as they now have to consider future execution costs as well. +* When epoch > 1, validators can no longer leave the network immediately, and must wait until an epoch boundary. From e858c5179991453116146ae81a3b8c8096550be2 Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Mon, 22 Feb 2021 14:38:08 -0600 Subject: [PATCH 099/214] Missed a comment --- docs/architecture/adr-039-epoched-staking.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/architecture/adr-039-epoched-staking.md b/docs/architecture/adr-039-epoched-staking.md index 82d453b7a5af..6443c7b61afc 100644 --- a/docs/architecture/adr-039-epoched-staking.md +++ b/docs/architecture/adr-039-epoched-staking.md @@ -48,8 +48,6 @@ Applying it immediately can be viewed as offering greater consensus layer securi - For fairness of deterministic leader election, applying a slash or jailing within an epoch would break the guarantee we were seeking to provide. This then re-introduces a new (but significantly simpler) problem for trying to provide fairness guarantees. Namely, that validators can adversarially elect to remove themself from the set of proposers. From a security perspective, this could potentially be handled by two different mechanisms (or prove to still be too difficult to achieve). One is making a security statement acknowledging the ability for an adversary to force an ahead-of-time fixed threshold of users to drop out of the proposer set within an epoch. The second method would be to parameterize such that the cost of a slash within the epoch far outweights benefits due to being a proposer. However, this latter criterion is quite dubious, since being a proposer can have many advantageous side-effects in chains with complex state machines. (Namely, DeFi games such as Fomo3D) - For staking derivative design, this will not cause problems with the suggested design there, nor does it increase the stateful of staking. (As whether a slash has occured is fully queryable given the validator address) -However, for achieving consensus layer security, it suffices to apply the validator jailing immediately, but still delay the actual slash changes to waiting until the end of the epoch. This largely mitigates the concern for fairness of deterministic leader election as well, since the validator is removed the set of potential proposers immediately. - ### Token lockup When someone makes a transaction to delegate, even though they are not immediately staked, their tokens should be moved into a pool managed by the staking module which will then be used at the end of an epoch. This prevents concerns where they stake, and then spend those tokens not realizing they were already allocated for staking, and thus having their staking tx fail. From 649a4e603a0214f033a8626559ac9de9028f7dc2 Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Mon, 22 Feb 2021 15:37:53 -0600 Subject: [PATCH 100/214] Add section for parameterizing the epoch length --- docs/architecture/adr-039-epoched-staking.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/docs/architecture/adr-039-epoched-staking.md b/docs/architecture/adr-039-epoched-staking.md index 6443c7b61afc..6ad61c884076 100644 --- a/docs/architecture/adr-039-epoched-staking.md +++ b/docs/architecture/adr-039-epoched-staking.md @@ -29,7 +29,7 @@ Furthermore, it has become clearer over time that immediate execution of staking * Threshold based cryptography. One of the main limitations is that because the validator set can change so regularly, it makes the running of multiparty computation by a fixed validator set difficult. Many threshold-based cryptographic features for blockchains such as randomness beacons and threshold decryption require a computationally-expensive DKG process (will take much longer than 1 block to create). To productively use these, we need to guarantee that the result of the DKG will be used for a reasonably long time. It wouldn't be feasible to rerun the DKG every block. By epoching staking, it guarantees we'll only need to run a new DKG once every epoch. -* Light client efficiency. This would lessen the overhead for IBC. Because of the light client bisection algorithm, the number of headers you need to verify is related to bounding the difference in validator sets between two successively verified headers. By limiting the frequency of validator set changes, we can reduce the size of IBC lite client proofs. +* Light client efficiency. This would lessen the overhead for IBC when there is high churn in the validator set. In the Tendermint light client bisection algorithm, the number of headers you need to verify is related to bounding the difference in validator sets between a trusted header and the latest header. If the difference is too great, you verify more header in between the two. By limiting the frequency of validator set changes, we can reduce the worst case size of IBC lite client proofs, which occurs when a validator set has high churn. * Fairness of deterministic leader election. Currently we have no ways of reasoning of fairness of deterministic leader election in the presence of staking changes without epochs (tendermint/spec#217). Breaking fairness of leader election is profitable for validators, as they earn additional rewards from being the proposer. Adding epochs at least makes it easier for our deterministic leader election to match something we can prove secure. (Albeit, we still haven’t proven if our current algorithm is fair with > 2 validators in the presence of stake changes) @@ -46,7 +46,7 @@ Applying it immediately can be viewed as offering greater consensus layer securi - For threshold based cryptography, this setting will have the threshold cryptography use the original epoch weights, while consensus has an update that lets it more rapidly benefit from additional security. If the threshold based cryptography blocks liveness of the chain, then we have effectively raised the liveness threshold of the remaining validators for the rest of the epoch. (Alternatively, jailed nodes could still contribute shares) This plan will fail in the extreme case that more than 1/3rd of the validators have been jailed within a single epoch. For such an extreme scenario, the chain already have its own custom incident response plan, and defining how to handle the threshold cryptography should be a part of that. - For light client efficiency, there can be a bit included in the header indicating an intra-epoch slash (ala https://github.com/tendermint/spec/issues/199). - For fairness of deterministic leader election, applying a slash or jailing within an epoch would break the guarantee we were seeking to provide. This then re-introduces a new (but significantly simpler) problem for trying to provide fairness guarantees. Namely, that validators can adversarially elect to remove themself from the set of proposers. From a security perspective, this could potentially be handled by two different mechanisms (or prove to still be too difficult to achieve). One is making a security statement acknowledging the ability for an adversary to force an ahead-of-time fixed threshold of users to drop out of the proposer set within an epoch. The second method would be to parameterize such that the cost of a slash within the epoch far outweights benefits due to being a proposer. However, this latter criterion is quite dubious, since being a proposer can have many advantageous side-effects in chains with complex state machines. (Namely, DeFi games such as Fomo3D) -- For staking derivative design, this will not cause problems with the suggested design there, nor does it increase the stateful of staking. (As whether a slash has occured is fully queryable given the validator address) +- For staking derivative design, there is no issue introduced. This does not increase the state size of staking records, since whether a slash has occured is fully queryable given the validator address. ### Token lockup @@ -66,6 +66,12 @@ With pipeline length 2, if I redelegate during epoch N, then my redelegation is Even though all staking updates are applied at epoch boundaries, rewards can still be distributed immediately when they are claimed. This is because they do not affect the current stake weights, as we do not implement auto-bonding of rewards. If such a feature were to be implemented, it would have to be setup so that rewards are auto-bonded at the epoch boundary. +### Parameterizing the epoch length + +When choosing the epoch length, there is a trade-off queued state/computation buildup, and countering the previously discussed limitations of immediate execution if they apply to a given chain. + +Until an ABCI mechanism for variable block times is introduced, it is ill-advised to be using high epoch lengths due to the computation buildup. This is because when a block's execution time is greater than the expected block time from Tendermint, rounds may increment. + ## Decision __Step-1__: Implement buffering of all staking and slashing messages. @@ -93,7 +99,7 @@ __Step-2__: Implement querying of queued staking txs. When querying the staking activity of a given address, the status should return not only the amount of tokens staked, but also if there are any queued stake events for that address. This will require more work to be done in the querying logic, to trace the queued upcoming staking events. -As an initial implementation, this can be implemented as a linear search over all queued staking events, but eventually nodes that support querying should maintain an auxilliary hashmap to make these queries constant time. +As an initial implementation, this can be implemented as a linear search over all queued staking events. However, for chains that need long epochs, they should eventually build additional support for nodes that support querying to be able to produce results in constant time. (This is do-able by maintaining an auxilliary hashmap for indexing upcoming staking events by address) __Step-3__: Adjust gas From d880d744984e519b199e107a078dd09bdb56c5f3 Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Mon, 22 Feb 2021 17:39:50 -0600 Subject: [PATCH 101/214] Fix accidentally committed files --- .github/workflows/repo-sync.yml | 19 ---- docs/architecture/adr-033-epoched-staking.md | 111 ------------------- 2 files changed, 130 deletions(-) delete mode 100644 .github/workflows/repo-sync.yml delete mode 100644 docs/architecture/adr-033-epoched-staking.md diff --git a/.github/workflows/repo-sync.yml b/.github/workflows/repo-sync.yml deleted file mode 100644 index 7844b46fa8dc..000000000000 --- a/.github/workflows/repo-sync.yml +++ /dev/null @@ -1,19 +0,0 @@ -on: - schedule: - - cron: "*/15 * * * *" - workflow_dispatch: - -jobs: - repo-sync: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - with: - persist-credentials: false - - name: repo-sync - uses: repo-sync/github-sync@v2 - with: - source_repo: "https://github.com/cosmos/cosmos-sdk" - source_branch: "master" - destination_branch: "master" - github_token: ${{ secrets.PAT }} diff --git a/docs/architecture/adr-033-epoched-staking.md b/docs/architecture/adr-033-epoched-staking.md deleted file mode 100644 index 01929758bed2..000000000000 --- a/docs/architecture/adr-033-epoched-staking.md +++ /dev/null @@ -1,111 +0,0 @@ -# ADR 032: Typed Events - -## Changelog - -- 10-Feb-2021: Initial Draft - -## Authors - -- Dev Ojha (@valardragon) -- Sunny Aggarwall (@sunnya97) - -## Status - -Proposed - -## Abstract - -This ADR updates the proof of stake module to buffer the staking weight updates for a number of blocks before updating the consensus' staking weights. The length of the buffer is dubbed an epoch. The prior functionality of the staking module is then a special case of the abstracted module, with the epoch being set to 1 block. - -## Context - -The current proof of stake module takes the design decision to apply staking weight changes to the consensus engine immediately. This means that delegations and unbonds get applied immediately to the validator set. This decision was primarily done as it was implementationally simplest, and because we at the time believed that this would lead to better UX for clients. - -An alternative design choice is to allow buffering staking updates (delegations, unbonds, validators joining) for a number of blocks. This 'epoch'd proof of stake consensus provides the guarantee that the consensus weights for validators will not change mid-epoch, except in the event of a slash condition. - -The decision to have immediate execution of staking changes was primarily done as it was implementationally simplest, and because we at the time believed that this would lead to better UX for clients. The UX hurdle may not be as significant as was previously thought, since it is possible to provide users acknowledgement that their bond was recorded and will be executed. - -Furthermore, it has become clearer over time that immediate execution of staking events comes with limitations, such as: - -* Threshold based cryptography. One of the main limitations is that because the validator set can change so regularly, it makes the running of multiparty computation by a fixed validator set difficult. Many threshold-based cryptographic features for blockchains such as randomness beacons and threshold decryption require a computationally-expensive DKG process (will take much longer than 1 block to create). To productively use these, we need to guarantee that the result of the DKG will be used for a reasonably long time. It wouldn't be feasible to rerun the DKG every block. By epoching staking, it guarantees we'll only need to run a new DKG once every epoch. - -* Light client efficiency. This would lessen the overhead for IBC. Because of the lite client bisection algorithm, the number of headers you need to verify is related to bounding the validator set diffs between two successively verified headers. By limiting the frequency of validator set changes, we can reduce the size of IBC lite client proofs. - -* Fairness of deterministic leader election. Currently we have no ways of reasoning of fairness of deterministic leader election in the presence of staking changes without epochs (tendermint/spec#217). Adding epochs at least makes it easier for our deterministic leader election to match something we can prove secure. (Albeit, we still haven’t proven if our current algorithm is fair with > 2 validators) - -* Staking derivative design. Currently, reward distribution is done lazily using the F1 fee distribution. While saving computational complexity, lazy accounting increases “statefulness of staking”. Right now, each delegation entry has to track the time of last withdrawal. Handling this can be a challenge for some staking derivatives designs (see example). Force-withdrawing rewards to users can help solve this, however it is infeasible to force-withdraw rewards to users on a per block basis. With epoching, a chain could more easily alter the design to have rewards be forcefully withdrawn (iterating over delegator accounts only once per-epoch), and thus remove the time of delegation from state. This preliminarily seems like it may be of utility in certain staking derivative designs. - -## Design considerations - -### Slashing - -There is a design consideration for whether to apply a slash immediately or at the end of an epoch. A slash event should apply to only members who are actually staked during the time of the infraction, namely during the epoch the slash event occured. - -Applying it immediately can be viewed as offering greater consensus layer security, at potential costs to the aforementioned usecases. The benefits of immediate slashing for consensus layer security can be all be obtained by executing the validator jailing immediately (thus removing it from the validator set), and delaying the actual slash change to the validator's weight until the epoch boundary. For the use cases mentioned above, workarounds can be integrated to avoid problems, as follows: - -- For threshold based cryptography, it can keep using the original keep epoch weights for the cryptography thresholds, but allow the underlying finality to benefit from extra security more quickly. -- For light client efficiency, there can be a bit included in the header indicating an intra-epoch slash (ala https://github.com/tendermint/spec/issues/199). -- For fairness of deterministic leader election, this will cause problems with the formalization of it / proximity of implementation to formally provable spec. However, a less formal claim can be made that the amount lost due to the slash should hopefully outweigh slight biases into the leader election process. This claim is dubious with the presence of MEV, but potentially formal upperbounds on MEV for fairness here could be derived. -- For staking derivative design, this will not cause problems with the suggested design there, nor does it increase the stateful of staking. (As whether a slash has occured is fully queryable given the validator address) - -However, for achieving consensus layer security, it suffices to apply the validator jailing immediately, but still delay the actual slash changes to waiting until the end of the epoch. This largely mitigates the concern for the fairness of deterministic leader election as well, since that validator is removed the set being rotated from immediately. - -### Token lockup - -When someone makes a transaction to delegate, even though they are not immediately staked, their tokens should be moved into a pool managed by the staking module which will then be used at the end of an epoch. This prevents concerns where they stake, and then spend those tokens not realizing they were already allocated for staking, and thus having their staking tx fail. - -### Pipelining the epochs - -For threshold based cryptography in particular, we need a pipeline for epoch changes. This is because when we are in epoch N, we want the epoch N+1 weights to be fixed so that the validator set can do the DKG accordingly. So if we are currently in epoch N, the stake weights for epoch N+1 should already be fixed, and new stake changes should be getting applied to epoch N + 2. - -This can be handled by making a parameter for the epoch pipeline. This parameter should not be alterable except during hard forks, to mitigate implementation complexity of switching the pipeline length. - -### Rewards - -Even though all staking updates are applied at epoch boundaries, rewards can still be distributed immediately when they are claimed. This is because they do not affect the current stake weights, as we do not implement auto-bonding of rewards. If such a feature were to be implemented, it would have to be setup so that rewards are auto-bonded at the epoch boundary. - -## Decision - -__Step-1__: Implement buffering of all staking and slashing messages. - -First we create a pool for storing tokens that are being bonded, but should be applied at the epoch boundary called the `EpochDelegationPool`. Then, we have two separate queues, one for staking, one for slashing. We describe what happens on each message being delivered below: - -### Staking messages -- **MsgCreateValidator**: Move user's self-bond to `EpochDelegationPool` immediately. Queue a message for the epoch boundary to handle the self-bond, taking the funds from the `EpochDelegationPool`. If Epoch execution fail, return back funds from `EpochDelegationPool` to user's account. -- **MsgEditValidator**: Validate message and if valid queue the message for execution at the end of the Epoch. -- **MsgDelegate**: Move user's funds to `EpochDelegationPool` immediately. Queue a message for the epoch boundary to handle the delegation, taking the funds from the `EpochDelegationPool`. If Epoch execution fail, return back funds from `EpochDelegationPool` to user's account. -- **MsgBeginRedelegate**: Validate message and if valid queue the message for execution at the end of the Epoch. -- **MsgUndelegate**: Validate message and if valid queue the message for execution at the end of the Epoch. - -### Slashing messages -- **MsgUnjail**: Validate message and if valid queue the message for execution at the end of the Epoch. -- **Slash Event**: Whenever a slash event is created, it gets queued in the slashing module to apply at the end of the epoch. The queues should be setup such that this slash applies immediately. - -### Evidence Messages - - **MsgSubmitEvidence**: This gets executed immediately, and the validator gets jailed immediately. However in slashing, the actual slash event gets queued. - -Then we add methods to the end blockers, to ensure that at the epoch boundary the queues are cleared and delegation updates are applied. - - -__Step-2__: Implement querying of queued staking txs. - -When querying the staking activity of a given address, the status should return not only the amount of tokens staked, but also if there are any queued stake events for that address. This will require nodes supporting querying to either do some more indexing to have this be efficiently queryable, or to have transactions - -__Step-3__: Adjust gas - -Currently gas represents the cost of executing a transaction when its done immediately. (Merging together costs of p2p overhead, state access overhead, and computational overhead) However, now a transaction can cause computation in a future block, namely at the epoch boundary. - -To handle this, we should initially include parameters for estimating the amount of future computation (denominated in gas), and add that as a flat charge needed for the message. -We leave it as out of scope for how to weight future computation versus current computation in gas pricing, and have it set such that the are weighted equally for now. - -## Consequences - -### Positive - -* Abstracts the proof of stake module that allows retaining the existing functionality -* Enables new features such as validator-set based threshold cryptography - -### Negative - -* Increases complexity of integrating more complex gas pricing mechanisms, as they now have to consider future execution costs as well. - From f2ee972e31e00eb5604b613f50255f848dfe61c0 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Tue, 23 Feb 2021 08:46:01 +0000 Subject: [PATCH 102/214] various linter fixes (#8666) --- client/docs/statik/init.go | 2 +- client/rest/rest.go | 1 + client/rpc/block.go | 2 +- client/rpc/validators.go | 2 +- simapp/test_helpers.go | 4 ++-- store/gaskv/store.go | 1 - types/decimal.go | 15 ++------------- types/decimal_test.go | 2 -- types/errors/errors.go | 1 - types/module/module.go | 8 -------- types/simulation/config.go | 4 ++-- types/simulation/types.go | 2 -- types/uint.go | 2 -- x/auth/legacy/v034/types.go | 1 - x/auth/legacy/v036/migrate.go | 1 - x/auth/legacy/v036/types.go | 1 - x/auth/legacy/v038/types.go | 1 - x/auth/legacy/v039/types.go | 1 - x/auth/module.go | 8 +++----- x/auth/testutil/suite.go | 3 +-- x/auth/types/account_retriever.go | 1 - x/auth/types/params.go | 1 - x/auth/vesting/types/vesting_account.go | 4 ---- x/bank/legacy/v036/types.go | 1 - x/bank/legacy/v038/types.go | 1 - x/bank/module.go | 4 ---- x/bank/simulation/operations.go | 3 --- x/crisis/handler_test.go | 2 -- x/crisis/keeper/msg_server.go | 16 ++-------------- x/crisis/module.go | 2 -- x/distribution/legacy/v034/types.go | 1 - x/distribution/legacy/v036/types.go | 1 - x/distribution/legacy/v038/migrate.go | 1 - x/distribution/legacy/v038/types.go | 1 - x/distribution/module.go | 4 ---- x/evidence/module.go | 2 -- x/feegrant/module.go | 2 -- x/genaccounts/legacy/v034/types.go | 1 - x/genaccounts/legacy/v036/types.go | 1 - x/genutil/module.go | 2 -- x/gov/client/rest/rest.go | 1 - x/gov/client/utils/utils.go | 4 ++-- x/gov/legacy/v034/types.go | 1 - x/gov/legacy/v036/types.go | 1 - x/gov/module.go | 4 ---- x/gov/types/vote.go | 1 - x/ibc/applications/transfer/module.go | 4 ---- x/ibc/core/module.go | 2 -- x/ibc/testing/mock/mock.go | 2 -- x/mint/keeper/keeper.go | 6 ------ x/mint/module.go | 4 ---- x/params/module.go | 2 -- x/simulation/log.go | 1 - x/simulation/mock_tendermint.go | 2 -- x/simulation/operation.go | 4 ---- x/simulation/params.go | 3 --- x/simulation/simulate.go | 2 -- x/slashing/keeper/hooks.go | 2 -- x/slashing/module.go | 4 ---- x/slashing/simulation/operations.go | 1 - x/slashing/types/events.go | 1 - x/staking/keeper/alias_functions.go | 2 -- x/staking/keeper/querier.go | 1 - x/staking/keeper/query_utils.go | 4 +--- x/staking/keeper/slash_test.go | 1 - x/staking/keeper/validator.go | 1 - x/staking/legacy/v034/types.go | 1 - x/staking/legacy/v036/migrate.go | 1 - x/staking/legacy/v036/types.go | 1 - x/staking/legacy/v038/migrate.go | 1 - x/staking/legacy/v038/types.go | 1 - x/staking/module.go | 2 -- x/staking/simulation/operations.go | 5 ----- x/staking/types/expected_keepers.go | 1 - 74 files changed, 19 insertions(+), 168 deletions(-) diff --git a/client/docs/statik/init.go b/client/docs/statik/init.go index 7d91b40fcd37..db70716be44b 100644 --- a/client/docs/statik/init.go +++ b/client/docs/statik/init.go @@ -1,3 +1,3 @@ package statik -//This just for fixing the error in importing empty github.com/cosmos/cosmos-sdk/client/docs/statik +// This just for fixing the error in importing empty github.com/cosmos/cosmos-sdk/client/docs/statik diff --git a/client/rest/rest.go b/client/rest/rest.go index ac05891e04c7..035b0f5dbb97 100644 --- a/client/rest/rest.go +++ b/client/rest/rest.go @@ -25,6 +25,7 @@ func addHTTPDeprecationHeaders(h http.Handler) http.Handler { // WithHTTPDeprecationHeaders returns a new *mux.Router, identical to its input // but with the addition of HTTP Deprecation headers. This is used to mark legacy // amino REST endpoints as deprecated in the REST API. +// nolint: gocritic func WithHTTPDeprecationHeaders(r *mux.Router) *mux.Router { subRouter := r.NewRoute().Subrouter() subRouter.Use(addHTTPDeprecationHeaders) diff --git a/client/rpc/block.go b/client/rpc/block.go index d6b79c9fe6da..530f7c45df73 100644 --- a/client/rpc/block.go +++ b/client/rpc/block.go @@ -15,7 +15,7 @@ import ( "github.com/cosmos/cosmos-sdk/types/rest" ) -//BlockCommand returns the verified block data for a given heights +// BlockCommand returns the verified block data for a given heights func BlockCommand() *cobra.Command { cmd := &cobra.Command{ Use: "block [height]", diff --git a/client/rpc/validators.go b/client/rpc/validators.go index 7760aead9935..7fb9cf9572b3 100644 --- a/client/rpc/validators.go +++ b/client/rpc/validators.go @@ -22,7 +22,7 @@ import ( // TODO these next two functions feel kinda hacky based on their placement -//ValidatorCommand returns the validator set for a given height +// ValidatorCommand returns the validator set for a given height func ValidatorCommand() *cobra.Command { cmd := &cobra.Command{ Use: "tendermint-validator-set [height]", diff --git a/simapp/test_helpers.go b/simapp/test_helpers.go index 9df0fdb75434..df80e4fccadc 100644 --- a/simapp/test_helpers.go +++ b/simapp/test_helpers.go @@ -219,9 +219,9 @@ func createIncrementalAccounts(accNum int) []sdk.AccAddress { // start at 100 so we can make up to 999 test addresses with valid test addresses for i := 100; i < (accNum + 100); i++ { numString := strconv.Itoa(i) - buffer.WriteString("A58856F0FD53BF058B4909A21AEC019107BA6") //base address string + buffer.WriteString("A58856F0FD53BF058B4909A21AEC019107BA6") // base address string - buffer.WriteString(numString) //adding on final two digits to make addresses unique + buffer.WriteString(numString) // adding on final two digits to make addresses unique res, _ := sdk.AccAddressFromHex(buffer.String()) bech := res.String() addr, _ := TestAddr(buffer.String(), bech) diff --git a/store/gaskv/store.go b/store/gaskv/store.go index d5c1f86c20aa..06b55f5ead48 100644 --- a/store/gaskv/store.go +++ b/store/gaskv/store.go @@ -19,7 +19,6 @@ type Store struct { } // NewStore returns a reference to a new GasKVStore. -// nolint func NewStore(parent types.KVStore, gasMeter types.GasMeter, gasConfig types.GasConfig) *Store { kvs := &Store{ gasMeter: gasMeter, diff --git a/types/decimal.go b/types/decimal.go index bf93f43c3faa..706859a8567d 100644 --- a/types/decimal.go +++ b/types/decimal.go @@ -80,8 +80,6 @@ func precisionMultiplier(prec int64) *big.Int { return precisionMultipliers[prec] } -//______________________________________________________________________________________________ - // create a new Dec from integer assuming whole number func NewDec(i int64) Dec { return NewDecWithPrec(i, 0) @@ -195,8 +193,6 @@ func MustNewDecFromStr(s string) Dec { return dec } -//______________________________________________________________________________________________ -//nolint func (d Dec) IsNil() bool { return d.i == nil } // is decimal nil func (d Dec) IsZero() bool { return (d.i).Sign() == 0 } // is equal to zero func (d Dec) IsNegative() bool { return (d.i).Sign() == -1 } // is negative @@ -215,8 +211,8 @@ func (d Dec) BigInt() *big.Int { return nil } - copy := new(big.Int) - return copy.Set(d.i) + cp := new(big.Int) + return cp.Set(d.i) } // addition @@ -561,8 +557,6 @@ func (d Dec) RoundInt() Int { return NewIntFromBigInt(chopPrecisionAndRoundNonMutative(d.i)) } -//___________________________________________________________________________________ - // similar to chopPrecisionAndRound, but always rounds down func chopPrecisionAndTruncate(d *big.Int) *big.Int { return d.Quo(d, precisionReuse) @@ -612,8 +606,6 @@ func (d Dec) Ceil() Dec { return NewDecFromBigInt(quo.Add(quo, oneInt)) } -//___________________________________________________________________________________ - // MaxSortableDec is the largest Dec that can be passed into SortableDecBytes() // Its negative form is the least Dec that can be passed in. var MaxSortableDec = OneDec().Quo(SmallestDec()) @@ -648,8 +640,6 @@ func SortableDecBytes(dec Dec) []byte { return []byte(fmt.Sprintf(fmt.Sprintf("%%0%ds", Precision*2+1), dec.String())) } -//___________________________________________________________________________________ - // reuse nil values var nilJSON []byte @@ -758,7 +748,6 @@ func (dp DecProto) String() string { return dp.Dec.String() } -//___________________________________________________________________________________ // helpers // test if two decimal arrays are equal diff --git a/types/decimal_test.go b/types/decimal_test.go index 8e62275a0eba..050d19f500ef 100644 --- a/types/decimal_test.go +++ b/types/decimal_test.go @@ -29,8 +29,6 @@ func (s *decimalTestSuite) mustNewDecFromStr(str string) (d sdk.Dec) { return d } -//_______________________________________ - func (s *decimalTestSuite) TestNewDecFromStr() { largeBigInt, success := new(big.Int).SetString("3144605511029693144278234343371835", 10) s.Require().True(success) diff --git a/types/errors/errors.go b/types/errors/errors.go index 6c540a1d6149..1dcc63e6566b 100644 --- a/types/errors/errors.go +++ b/types/errors/errors.go @@ -15,7 +15,6 @@ const UndefinedCodespace = "undefined" var ( // errInternal should never be exposed, but we reserve this code for non-specified errors - //nolint errInternal = Register(UndefinedCodespace, 1, "internal") // ErrTxDecode is returned if we cannot parse a transaction diff --git a/types/module/module.go b/types/module/module.go index 58bb4927b29a..b998f273af5a 100644 --- a/types/module/module.go +++ b/types/module/module.go @@ -43,8 +43,6 @@ import ( sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) -//__________________________________________________________________________________________ - // AppModuleBasic is the standard form for basic non-dependant elements of an application module. type AppModuleBasic interface { Name() string @@ -146,8 +144,6 @@ func (bm BasicManager) AddQueryCommands(rootQueryCmd *cobra.Command) { } } -//_________________________________________________________ - // AppModuleGenesis is the standard form for an application module genesis functions type AppModuleGenesis interface { AppModuleBasic @@ -186,8 +182,6 @@ type AppModule interface { EndBlock(sdk.Context, abci.RequestEndBlock) []abci.ValidatorUpdate } -//___________________________ - // GenesisOnlyAppModule is an AppModule that only has import/export functionality type GenesisOnlyAppModule struct { AppModuleGenesis @@ -226,8 +220,6 @@ func (GenesisOnlyAppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []ab return []abci.ValidatorUpdate{} } -//____________________________________________________________________________ - // Manager defines a module manager that provides the high level utility for managing and executing // operations for a group of modules type Manager struct { diff --git a/types/simulation/config.go b/types/simulation/config.go index 58a39bb17d5b..8bad709545c9 100644 --- a/types/simulation/config.go +++ b/types/simulation/config.go @@ -6,8 +6,8 @@ type Config struct { ParamsFile string // custom simulation params file which overrides any random params; cannot be used with genesis ExportParamsPath string // custom file path to save the exported params JSON - ExportParamsHeight int //height to which export the randomly generated params - ExportStatePath string //custom file path to save the exported app state JSON + ExportParamsHeight int // height to which export the randomly generated params + ExportStatePath string // custom file path to save the exported app state JSON ExportStatsPath string // custom file path to save the exported simulation statistics JSON Seed int64 // simulation random seed diff --git a/types/simulation/types.go b/types/simulation/types.go index 46ede62a3536..fabbcd47552b 100644 --- a/types/simulation/types.go +++ b/types/simulation/types.go @@ -125,8 +125,6 @@ func (om OperationMsg) LogEvent(eventLogger func(route, op, evResult string)) { eventLogger(om.Route, om.Name, pass) } -//________________________________________________________________________ - // FutureOperation is an operation which will be ran at the beginning of the // provided BlockHeight. If both a BlockHeight and BlockTime are specified, it // will use the BlockHeight. In the (likely) event that multiple operations diff --git a/types/uint.go b/types/uint.go index d449c5262b19..dbdd17bd58a9 100644 --- a/types/uint.go +++ b/types/uint.go @@ -207,8 +207,6 @@ func (u *Uint) Size() int { func (u Uint) MarshalAmino() ([]byte, error) { return u.Marshal() } func (u *Uint) UnmarshalAmino(bz []byte) error { return u.Unmarshal(bz) } -//__________________________________________________________________________ - // UintOverflow returns true if a given unsigned integer overflows and false // otherwise. func UintOverflow(i *big.Int) error { diff --git a/x/auth/legacy/v034/types.go b/x/auth/legacy/v034/types.go index c5df671017b2..83fa2d36eace 100644 --- a/x/auth/legacy/v034/types.go +++ b/x/auth/legacy/v034/types.go @@ -1,5 +1,4 @@ // DONTCOVER -// nolint package v034 import ( diff --git a/x/auth/legacy/v036/migrate.go b/x/auth/legacy/v036/migrate.go index c651df6994d8..2ab4aa14379b 100644 --- a/x/auth/legacy/v036/migrate.go +++ b/x/auth/legacy/v036/migrate.go @@ -1,5 +1,4 @@ // DONTCOVER -// nolint package v036 import ( diff --git a/x/auth/legacy/v036/types.go b/x/auth/legacy/v036/types.go index 2490f4baa22e..908165f26505 100644 --- a/x/auth/legacy/v036/types.go +++ b/x/auth/legacy/v036/types.go @@ -1,5 +1,4 @@ // DONTCOVER -// nolint package v036 import v034auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v034" diff --git a/x/auth/legacy/v038/types.go b/x/auth/legacy/v038/types.go index e9977c1d2966..b7dedf003e13 100644 --- a/x/auth/legacy/v038/types.go +++ b/x/auth/legacy/v038/types.go @@ -1,7 +1,6 @@ package v038 // DONTCOVER -// nolint import ( "bytes" diff --git a/x/auth/legacy/v039/types.go b/x/auth/legacy/v039/types.go index 55c3014eb7f0..3de576f27ffa 100644 --- a/x/auth/legacy/v039/types.go +++ b/x/auth/legacy/v039/types.go @@ -1,7 +1,6 @@ package v039 // DONTCOVER -// nolint import ( "bytes" diff --git a/x/auth/module.go b/x/auth/module.go index 9e4af71ff037..ff053d8c7c76 100644 --- a/x/auth/module.go +++ b/x/auth/module.go @@ -67,7 +67,9 @@ func (AppModuleBasic) RegisterRESTRoutes(clientCtx client.Context, rtr *mux.Rout // RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the auth module. func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) { - types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)) + if err := types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)); err != nil { + panic(err) + } } // GetTxCmd returns the root tx command for the auth module. @@ -85,8 +87,6 @@ func (AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) types.RegisterInterfaces(registry) } -//____________________________________________________________________________ - // AppModule implements an application module for the auth module. type AppModule struct { AppModuleBasic @@ -159,8 +159,6 @@ func (AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.Validato return []abci.ValidatorUpdate{} } -//____________________________________________________________________________ - // AppModuleSimulation functions // GenerateGenesisState creates a randomized GenState of the auth module diff --git a/x/auth/testutil/suite.go b/x/auth/testutil/suite.go index f8002e68e4e6..b1e9f25c311b 100644 --- a/x/auth/testutil/suite.go +++ b/x/auth/testutil/suite.go @@ -15,8 +15,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/auth/signing" ) -// TxConfigTestSuite provides a test suite that can be used to test that a TxConfig implementation is correct -//nolint:golint // type name will be used as tx.TxConfigTestSuite by other packages, and that stutters; consider calling this GeneratorTestSuite +// TxConfigTestSuite provides a test suite that can be used to test that a TxConfig implementation is correct. type TxConfigTestSuite struct { suite.Suite TxConfig client.TxConfig diff --git a/x/auth/types/account_retriever.go b/x/auth/types/account_retriever.go index f84c744188ff..792524fff017 100644 --- a/x/auth/types/account_retriever.go +++ b/x/auth/types/account_retriever.go @@ -32,7 +32,6 @@ func (ar AccountRetriever) GetAccount(clientCtx client.Context, addr sdk.AccAddr // GetAccountWithHeight queries for an account given an address. Returns the // height of the query with the account. An error is returned if the query // or decoding fails. -//nolint:interfacer func (ar AccountRetriever) GetAccountWithHeight(clientCtx client.Context, addr sdk.AccAddress) (client.Account, int64, error) { var header metadata.MD diff --git a/x/auth/types/params.go b/x/auth/types/params.go index 710ee963b4a3..13db369d2353 100644 --- a/x/auth/types/params.go +++ b/x/auth/types/params.go @@ -48,7 +48,6 @@ func ParamKeyTable() paramtypes.KeyTable { // ParamSetPairs implements the ParamSet interface and returns all the key/value pairs // pairs of auth module's parameters. -// nolint func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { return paramtypes.ParamSetPairs{ paramtypes.NewParamSetPair(KeyMaxMemoCharacters, &p.MaxMemoCharacters, validateMaxMemoCharacters), diff --git a/x/auth/vesting/types/vesting_account.go b/x/auth/vesting/types/vesting_account.go index e011bd6efbbf..0438a338bd16 100644 --- a/x/auth/vesting/types/vesting_account.go +++ b/x/auth/vesting/types/vesting_account.go @@ -19,7 +19,6 @@ var ( _ vestexported.VestingAccount = (*DelayedVestingAccount)(nil) ) -//----------------------------------------------------------------------------- // Base Vesting Account // NewBaseVestingAccount creates a new BaseVestingAccount object. It is the @@ -216,7 +215,6 @@ func (bva BaseVestingAccount) MarshalYAML() (interface{}, error) { return string(bz), err } -//----------------------------------------------------------------------------- // Continuous Vesting Account var _ vestexported.VestingAccount = (*ContinuousVestingAccount)(nil) @@ -345,7 +343,6 @@ func (cva ContinuousVestingAccount) MarshalYAML() (interface{}, error) { return string(bz), err } -//----------------------------------------------------------------------------- // Periodic Vesting Account var _ vestexported.VestingAccount = (*PeriodicVestingAccount)(nil) @@ -504,7 +501,6 @@ func (pva PeriodicVestingAccount) MarshalYAML() (interface{}, error) { return string(bz), err } -//----------------------------------------------------------------------------- // Delayed Vesting Account var _ vestexported.VestingAccount = (*DelayedVestingAccount)(nil) diff --git a/x/bank/legacy/v036/types.go b/x/bank/legacy/v036/types.go index 1de8ffb9b71f..ada368404855 100644 --- a/x/bank/legacy/v036/types.go +++ b/x/bank/legacy/v036/types.go @@ -1,5 +1,4 @@ // DONTCOVER -// nolint package v036 import ( diff --git a/x/bank/legacy/v038/types.go b/x/bank/legacy/v038/types.go index e67640bf2b12..eba8d3518ca1 100644 --- a/x/bank/legacy/v038/types.go +++ b/x/bank/legacy/v038/types.go @@ -1,7 +1,6 @@ package v038 // DONTCOVER -// nolint const ( ModuleName = "bank" diff --git a/x/bank/module.go b/x/bank/module.go index 77bff6b73b61..c335c3409fa5 100644 --- a/x/bank/module.go +++ b/x/bank/module.go @@ -86,8 +86,6 @@ func (AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) types.RegisterInterfaces(registry) } -//____________________________________________________________________________ - // AppModule implements an application module for the bank module. type AppModule struct { AppModuleBasic @@ -166,8 +164,6 @@ func (AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.Validato return []abci.ValidatorUpdate{} } -//____________________________________________________________________________ - // AppModuleSimulation functions // GenerateGenesisState creates a randomized GenState of the bank module. diff --git a/x/bank/simulation/operations.go b/x/bank/simulation/operations.go index 40be2feeb4a0..78feff814ccd 100644 --- a/x/bank/simulation/operations.go +++ b/x/bank/simulation/operations.go @@ -81,7 +81,6 @@ func SimulateMsgSend(ak types.AccountKeeper, bk keeper.Keeper) simtypes.Operatio } // sendMsgSend sends a transaction with a MsgSend from a provided random account. -// nolint: interfacer func sendMsgSend( r *rand.Rand, app *baseapp.BaseApp, bk keeper.Keeper, ak types.AccountKeeper, msg *types.MsgSend, ctx sdk.Context, chainID string, privkeys []cryptotypes.PrivKey, @@ -223,7 +222,6 @@ func SimulateMsgMultiSend(ak types.AccountKeeper, bk keeper.Keeper) simtypes.Ope // sendMsgMultiSend sends a transaction with a MsgMultiSend from a provided random // account. -// nolint: interfacer func sendMsgMultiSend( r *rand.Rand, app *baseapp.BaseApp, bk keeper.Keeper, ak types.AccountKeeper, msg *types.MsgMultiSend, ctx sdk.Context, chainID string, privkeys []cryptotypes.PrivKey, @@ -289,7 +287,6 @@ func sendMsgMultiSend( // randomSendFields returns the sender and recipient simulation accounts as well // as the transferred amount. -// nolint: interfacer func randomSendFields( r *rand.Rand, ctx sdk.Context, accs []simtypes.Account, bk keeper.Keeper, ak types.AccountKeeper, ) (simtypes.Account, simtypes.Account, sdk.Coins, bool) { diff --git a/x/crisis/handler_test.go b/x/crisis/handler_test.go index 593763ad82cb..e981a1a78749 100644 --- a/x/crisis/handler_test.go +++ b/x/crisis/handler_test.go @@ -42,8 +42,6 @@ func createTestApp() (*simapp.SimApp, sdk.Context, []sdk.AccAddress) { return app, ctx, addrs } -//____________________________________________________________________________ - func TestHandleMsgVerifyInvariant(t *testing.T) { app, ctx, addrs := createTestApp() sender := addrs[0] diff --git a/x/crisis/keeper/msg_server.go b/x/crisis/keeper/msg_server.go index 304f8b17243d..a3eb07e6ba47 100644 --- a/x/crisis/keeper/msg_server.go +++ b/x/crisis/keeper/msg_server.go @@ -43,20 +43,8 @@ func (k Keeper) VerifyInvariant(goCtx context.Context, msg *types.MsgVerifyInvar } if stop { - // NOTE currently, because the chain halts here, this transaction will never be included - // in the blockchain thus the constant fee will have never been deducted. Thus no - // refund is required. - - // TODO uncomment the following code block with implementation of the circuit breaker - //// refund constant fee - //err := k.distrKeeper.DistributeFromFeePool(ctx, constantFee, msg.Sender) - //if err != nil { - //// if there are insufficient coins to refund, log the error, - //// but still halt the chain. - //logger := ctx.Logger().With("module", "x/crisis") - //logger.Error(fmt.Sprintf( - //"WARNING: insufficient funds to allocate to sender from fee pool, err: %s", err)) - //} + // Currently, because the chain halts here, this transaction will never be included in the + // blockchain thus the constant fee will have never been deducted. Thus no refund is required. // TODO replace with circuit breaker panic(res) diff --git a/x/crisis/module.go b/x/crisis/module.go index 66d829be810e..ecea78f111c3 100644 --- a/x/crisis/module.go +++ b/x/crisis/module.go @@ -80,8 +80,6 @@ func (AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) types.RegisterInterfaces(registry) } -//____________________________________________________________________________ - // AppModule implements an application module for the crisis module. type AppModule struct { AppModuleBasic diff --git a/x/distribution/legacy/v034/types.go b/x/distribution/legacy/v034/types.go index 3ef672f4af3b..4e8b209ad67b 100644 --- a/x/distribution/legacy/v034/types.go +++ b/x/distribution/legacy/v034/types.go @@ -1,5 +1,4 @@ // DONTCOVER -// nolint package v034 import ( diff --git a/x/distribution/legacy/v036/types.go b/x/distribution/legacy/v036/types.go index 1c43eb5acd2a..2a11518b4ac2 100644 --- a/x/distribution/legacy/v036/types.go +++ b/x/distribution/legacy/v036/types.go @@ -1,5 +1,4 @@ // DONTCOVER -// nolint package v036 import ( diff --git a/x/distribution/legacy/v038/migrate.go b/x/distribution/legacy/v038/migrate.go index cd00668b1efd..73e933da4589 100644 --- a/x/distribution/legacy/v038/migrate.go +++ b/x/distribution/legacy/v038/migrate.go @@ -1,7 +1,6 @@ package v038 // DONTCOVER -// nolint import ( v036distr "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v036" diff --git a/x/distribution/legacy/v038/types.go b/x/distribution/legacy/v038/types.go index af7146418dbc..335fbc1245e2 100644 --- a/x/distribution/legacy/v038/types.go +++ b/x/distribution/legacy/v038/types.go @@ -7,7 +7,6 @@ import ( ) // DONTCOVER -// nolint const ( ModuleName = "distribution" diff --git a/x/distribution/module.go b/x/distribution/module.go index 0f0c0d358a91..0cc40570b5f3 100644 --- a/x/distribution/module.go +++ b/x/distribution/module.go @@ -88,8 +88,6 @@ func (b AppModuleBasic) RegisterInterfaces(registry cdctypes.InterfaceRegistry) types.RegisterInterfaces(registry) } -//____________________________________________________________________________ - // AppModule implements an application module for the distribution module. type AppModule struct { AppModuleBasic @@ -175,8 +173,6 @@ func (AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.Validato return []abci.ValidatorUpdate{} } -//____________________________________________________________________________ - // AppModuleSimulation functions // GenerateGenesisState creates a randomized GenState of the distribution module. diff --git a/x/evidence/module.go b/x/evidence/module.go index 9143e208e716..204cb263516a 100644 --- a/x/evidence/module.go +++ b/x/evidence/module.go @@ -189,8 +189,6 @@ func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.Val return []abci.ValidatorUpdate{} } -//____________________________________________________________________________ - // AppModuleSimulation functions // GenerateGenesisState creates a randomized GenState of the evidence module. diff --git a/x/feegrant/module.go b/x/feegrant/module.go index 31b08e6baab1..a6f1f4f62000 100644 --- a/x/feegrant/module.go +++ b/x/feegrant/module.go @@ -179,8 +179,6 @@ func (AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.Validato return []abci.ValidatorUpdate{} } -//____________________________________________________________________________ - // AppModuleSimulation functions // GenerateGenesisState creates a randomized GenState of the feegrant module. diff --git a/x/genaccounts/legacy/v034/types.go b/x/genaccounts/legacy/v034/types.go index 080b534d8ec1..f4bb73fa37c4 100644 --- a/x/genaccounts/legacy/v034/types.go +++ b/x/genaccounts/legacy/v034/types.go @@ -1,5 +1,4 @@ // DONTCOVER -// nolint package v034 import ( diff --git a/x/genaccounts/legacy/v036/types.go b/x/genaccounts/legacy/v036/types.go index 8d143e69d2dc..e91db341db48 100644 --- a/x/genaccounts/legacy/v036/types.go +++ b/x/genaccounts/legacy/v036/types.go @@ -1,5 +1,4 @@ // DONTCOVER -// nolint package v036 import ( diff --git a/x/genutil/module.go b/x/genutil/module.go index 7a65531e453f..ebfb70c4ab43 100644 --- a/x/genutil/module.go +++ b/x/genutil/module.go @@ -66,8 +66,6 @@ func (AppModuleBasic) GetTxCmd() *cobra.Command { return nil } // GetQueryCmd returns no root query command for the genutil module. func (AppModuleBasic) GetQueryCmd() *cobra.Command { return nil } -//____________________________________________________________________________ - // AppModule implements an application module for the genutil module. type AppModule struct { AppModuleBasic diff --git a/x/gov/client/rest/rest.go b/x/gov/client/rest/rest.go index f11798e96760..46d66c240bc2 100644 --- a/x/gov/client/rest/rest.go +++ b/x/gov/client/rest/rest.go @@ -12,7 +12,6 @@ import ( ) // REST Variable names -// nolint const ( RestParamsType = "type" RestProposalID = "proposal-id" diff --git a/x/gov/client/utils/utils.go b/x/gov/client/utils/utils.go index 0e0bf04de7db..c88be3df3cb3 100644 --- a/x/gov/client/utils/utils.go +++ b/x/gov/client/utils/utils.go @@ -40,7 +40,7 @@ func NormalizeWeightedVoteOptions(options string) string { return strings.Join(newOptions, ",") } -//NormalizeProposalType - normalize user specified proposal type +// NormalizeProposalType - normalize user specified proposal type. func NormalizeProposalType(proposalType string) string { switch proposalType { case "Text", "text": @@ -51,7 +51,7 @@ func NormalizeProposalType(proposalType string) string { } } -//NormalizeProposalStatus - normalize user specified proposal status +// NormalizeProposalStatus - normalize user specified proposal status. func NormalizeProposalStatus(status string) string { switch status { case "DepositPeriod", "deposit_period": diff --git a/x/gov/legacy/v034/types.go b/x/gov/legacy/v034/types.go index dd98cca21be3..14e0b7a26590 100644 --- a/x/gov/legacy/v034/types.go +++ b/x/gov/legacy/v034/types.go @@ -1,5 +1,4 @@ // DONTCOVER -// nolint package v034 import ( diff --git a/x/gov/legacy/v036/types.go b/x/gov/legacy/v036/types.go index d0bc4620bc73..6632c6da255c 100644 --- a/x/gov/legacy/v036/types.go +++ b/x/gov/legacy/v036/types.go @@ -1,5 +1,4 @@ // DONTCOVER -// nolint package v036 import ( diff --git a/x/gov/module.go b/x/gov/module.go index b72a4bfe5f5c..30ce817e70d4 100644 --- a/x/gov/module.go +++ b/x/gov/module.go @@ -109,8 +109,6 @@ func (a AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry types.RegisterInterfaces(registry) } -//____________________________________________________________________________ - // AppModule implements an application module for the gov module. type AppModule struct { AppModuleBasic @@ -190,8 +188,6 @@ func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.Val return []abci.ValidatorUpdate{} } -//____________________________________________________________________________ - // AppModuleSimulation functions // GenerateGenesisState creates a randomized GenState of the gov module. diff --git a/x/gov/types/vote.go b/x/gov/types/vote.go index da4317285c1f..6b7c1660d1bd 100644 --- a/x/gov/types/vote.go +++ b/x/gov/types/vote.go @@ -56,7 +56,6 @@ func (v Vote) Empty() bool { } // NewNonSplitVoteOption creates a single option vote with weight 1 -//nolint:interfacer func NewNonSplitVoteOption(option VoteOption) WeightedVoteOptions { return WeightedVoteOptions{{option, sdk.NewDec(1)}} } diff --git a/x/ibc/applications/transfer/module.go b/x/ibc/applications/transfer/module.go index 25290d69a64c..b93253ad7a8c 100644 --- a/x/ibc/applications/transfer/module.go +++ b/x/ibc/applications/transfer/module.go @@ -157,8 +157,6 @@ func (am AppModule) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) []abci.V return []abci.ValidatorUpdate{} } -//____________________________________________________________________________ - // AppModuleSimulation functions // GenerateGenesisState creates a randomized GenState of the transfer module. @@ -186,8 +184,6 @@ func (am AppModule) WeightedOperations(_ module.SimulationState) []simtypes.Weig return nil } -//____________________________________________________________________________ - // ValidateTransferChannelParams does validation of a newly created transfer channel. A transfer // channel must be UNORDERED, use the correct port (by default 'transfer'), and use the current // supported version. Only 2^32 channels are allowed to be created. diff --git a/x/ibc/core/module.go b/x/ibc/core/module.go index 6527ab71eb2f..9d5d4e86328c 100644 --- a/x/ibc/core/module.go +++ b/x/ibc/core/module.go @@ -170,8 +170,6 @@ func (am AppModule) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) []abci.V return []abci.ValidatorUpdate{} } -//____________________________________________________________________________ - // AppModuleSimulation functions // GenerateGenesisState creates a randomized GenState of the ibc module. diff --git a/x/ibc/testing/mock/mock.go b/x/ibc/testing/mock/mock.go index 663497aa05ca..16e2ad345c2b 100644 --- a/x/ibc/testing/mock/mock.go +++ b/x/ibc/testing/mock/mock.go @@ -124,8 +124,6 @@ func (am AppModule) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) []abci.V return []abci.ValidatorUpdate{} } -//____________________________________________________________________________ - // OnChanOpenInit implements the IBCModule interface. func (am AppModule) OnChanOpenInit( ctx sdk.Context, _ channeltypes.Order, _ []string, portID string, diff --git a/x/mint/keeper/keeper.go b/x/mint/keeper/keeper.go index de0a31222845..46eb6ba535f5 100644 --- a/x/mint/keeper/keeper.go +++ b/x/mint/keeper/keeper.go @@ -45,8 +45,6 @@ func NewKeeper( } } -//______________________________________________________________________ - // Logger returns a module-specific logger. func (k Keeper) Logger(ctx sdk.Context) log.Logger { return ctx.Logger().With("module", "x/"+types.ModuleName) @@ -71,8 +69,6 @@ func (k Keeper) SetMinter(ctx sdk.Context, minter types.Minter) { store.Set(types.MinterKey, b) } -//______________________________________________________________________ - // GetParams returns the total set of minting parameters. func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) { k.paramSpace.GetParamSet(ctx, ¶ms) @@ -84,8 +80,6 @@ func (k Keeper) SetParams(ctx sdk.Context, params types.Params) { k.paramSpace.SetParamSet(ctx, ¶ms) } -//______________________________________________________________________ - // StakingTokenSupply implements an alias call to the underlying staking keeper's // StakingTokenSupply to be used in BeginBlocker. func (k Keeper) StakingTokenSupply(ctx sdk.Context) sdk.Int { diff --git a/x/mint/module.go b/x/mint/module.go index d33043b36a2e..a4d1f113f08f 100644 --- a/x/mint/module.go +++ b/x/mint/module.go @@ -83,8 +83,6 @@ func (AppModuleBasic) GetQueryCmd() *cobra.Command { return cli.GetQueryCmd() } -//____________________________________________________________________________ - // AppModule implements an application module for the mint module. type AppModule struct { AppModuleBasic @@ -160,8 +158,6 @@ func (AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.Validato return []abci.ValidatorUpdate{} } -//____________________________________________________________________________ - // AppModuleSimulation functions // GenerateGenesisState creates a randomized GenState of the mint module. diff --git a/x/params/module.go b/x/params/module.go index c1a115b210c1..624ff2d25e96 100644 --- a/x/params/module.go +++ b/x/params/module.go @@ -72,8 +72,6 @@ func (am AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistr proposal.RegisterInterfaces(registry) } -//____________________________________________________________________________ - // AppModule implements an application module for the distribution module. type AppModule struct { AppModuleBasic diff --git a/x/simulation/log.go b/x/simulation/log.go index 236a7244074f..ba22b2af4a7e 100644 --- a/x/simulation/log.go +++ b/x/simulation/log.go @@ -68,7 +68,6 @@ func createLogFile() *os.File { return f } -//_____________________ // dummy log writter type DummyLogWriter struct{} diff --git a/x/simulation/mock_tendermint.go b/x/simulation/mock_tendermint.go index ad84e8213d54..55c2ca544465 100644 --- a/x/simulation/mock_tendermint.go +++ b/x/simulation/mock_tendermint.go @@ -59,8 +59,6 @@ func (vals mockValidators) getKeys() []string { return keys } -//_________________________________________________________________________________ - // randomProposer picks a random proposer from the current validator set func (vals mockValidators) randomProposer(r *rand.Rand) tmbytes.HexBytes { keys := vals.getKeys() diff --git a/x/simulation/operation.go b/x/simulation/operation.go index 914daafc8b91..7aab48e9fbec 100644 --- a/x/simulation/operation.go +++ b/x/simulation/operation.go @@ -64,8 +64,6 @@ func (oe OperationEntry) MustMarshal() json.RawMessage { return out } -//_____________________________________________________________________ - // OperationQueue defines an object for a queue of operations type OperationQueue map[int][]simulation.Operation @@ -107,8 +105,6 @@ func queueOperations(queuedOps OperationQueue, queuedTimeOps []simulation.Future } } -//________________________________________________________________________ - // WeightedOperation is an operation with associated weight. // This is used to bias the selection operation within the simulator. type WeightedOperation struct { diff --git a/x/simulation/params.go b/x/simulation/params.go index 12e8e097263f..b0569e94898c 100644 --- a/x/simulation/params.go +++ b/x/simulation/params.go @@ -87,7 +87,6 @@ func RandomParams(r *rand.Rand) Params { } } -//----------------------------------------------------------------------------- // Param change proposals // ParamChange defines the object used for simulating parameter change proposals @@ -123,7 +122,6 @@ func (spc ParamChange) ComposedKey() string { return fmt.Sprintf("%s/%s", spc.Subspace(), spc.Key()) } -//----------------------------------------------------------------------------- // Proposal Contents // WeightedProposalContent defines a common struct for proposal contents defined by @@ -150,7 +148,6 @@ func (w WeightedProposalContent) ContentSimulatorFn() simulation.ContentSimulato return w.contentSimulatorFn } -//----------------------------------------------------------------------------- // Param change proposals // randomConsensusParams returns random simulation consensus parameters, it extracts the Evidence from the Staking genesis state. diff --git a/x/simulation/simulate.go b/x/simulation/simulate.go index fdcf224611ba..6e391aa2eb08 100644 --- a/x/simulation/simulate.go +++ b/x/simulation/simulate.go @@ -240,8 +240,6 @@ func SimulateFromSeed( return false, exportedParams, nil } -//______________________________________________________________________________ - type blockSimFn func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accounts []simulation.Account, header tmproto.Header) (opCount int) diff --git a/x/slashing/keeper/hooks.go b/x/slashing/keeper/hooks.go index d59601425842..e3a00e9f5556 100644 --- a/x/slashing/keeper/hooks.go +++ b/x/slashing/keeper/hooks.go @@ -42,8 +42,6 @@ func (k Keeper) AfterValidatorRemoved(ctx sdk.Context, address sdk.ConsAddress) k.deleteAddrPubkeyRelation(ctx, crypto.Address(address)) } -//_________________________________________________________________________________________ - // Hooks wrapper struct for slashing keeper type Hooks struct { k Keeper diff --git a/x/slashing/module.go b/x/slashing/module.go index ba5cfb60adb9..a1b99e044186 100644 --- a/x/slashing/module.go +++ b/x/slashing/module.go @@ -91,8 +91,6 @@ func (AppModuleBasic) GetQueryCmd() *cobra.Command { return cli.GetQueryCmd() } -//____________________________________________________________________________ - // AppModule implements an application module for the slashing module. type AppModule struct { AppModuleBasic @@ -173,8 +171,6 @@ func (AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.Validato return []abci.ValidatorUpdate{} } -//____________________________________________________________________________ - // AppModuleSimulation functions // GenerateGenesisState creates a randomized GenState of the slashing module. diff --git a/x/slashing/simulation/operations.go b/x/slashing/simulation/operations.go index 1c49775cc193..19f106ddb7ee 100644 --- a/x/slashing/simulation/operations.go +++ b/x/slashing/simulation/operations.go @@ -43,7 +43,6 @@ func WeightedOperations( } // SimulateMsgUnjail generates a MsgUnjail with random values -// nolint: interfacer func SimulateMsgUnjail(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper, sk stakingkeeper.Keeper) simtypes.Operation { return func( r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, diff --git a/x/slashing/types/events.go b/x/slashing/types/events.go index 62b6493c34a1..e9fb254545f5 100644 --- a/x/slashing/types/events.go +++ b/x/slashing/types/events.go @@ -1,4 +1,3 @@ -//noalias package types // Slashing module event types diff --git a/x/staking/keeper/alias_functions.go b/x/staking/keeper/alias_functions.go index 1d563c690783..36c2d23661c6 100644 --- a/x/staking/keeper/alias_functions.go +++ b/x/staking/keeper/alias_functions.go @@ -7,7 +7,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/staking/types" ) -//_______________________________________________________________________ // Validator Set // iterate through the validator set and perform the provided function @@ -96,7 +95,6 @@ func (k Keeper) ValidatorByConsAddr(ctx sdk.Context, addr sdk.ConsAddress) types return val } -//_______________________________________________________________________ // Delegation Set // Returns self as it is both a validatorset and delegationset diff --git a/x/staking/keeper/querier.go b/x/staking/keeper/querier.go index 48272e245191..06bab770467d 100644 --- a/x/staking/keeper/querier.go +++ b/x/staking/keeper/querier.go @@ -444,7 +444,6 @@ func queryParameters(ctx sdk.Context, k Keeper, legacyQuerierCdc *codec.LegacyAm return res, nil } -//______________________________________________________ // util func DelegationToDelegationResponse(ctx sdk.Context, k Keeper, del types.Delegation) (types.DelegationResponse, error) { diff --git a/x/staking/keeper/query_utils.go b/x/staking/keeper/query_utils.go index a6f323092ae6..d757522f6dd7 100644 --- a/x/staking/keeper/query_utils.go +++ b/x/staking/keeper/query_utils.go @@ -50,8 +50,6 @@ func (k Keeper) GetDelegatorValidator( return validator, nil } -//_____________________________________________________________________________________ - // return all delegations for a delegator func (k Keeper) GetAllDelegatorDelegations(ctx sdk.Context, delegator sdk.AccAddress) []types.Delegation { delegations := make([]types.Delegation, 0) @@ -59,7 +57,7 @@ func (k Keeper) GetAllDelegatorDelegations(ctx sdk.Context, delegator sdk.AccAdd store := ctx.KVStore(k.storeKey) delegatorPrefixKey := types.GetDelegationsKey(delegator) - iterator := sdk.KVStorePrefixIterator(store, delegatorPrefixKey) //smallest to largest + iterator := sdk.KVStorePrefixIterator(store, delegatorPrefixKey) // smallest to largest defer iterator.Close() i := 0 diff --git a/x/staking/keeper/slash_test.go b/x/staking/keeper/slash_test.go index 146ed5868732..3f72e857f497 100644 --- a/x/staking/keeper/slash_test.go +++ b/x/staking/keeper/slash_test.go @@ -381,7 +381,6 @@ func TestSlashWithUnbondingDelegation(t *testing.T) { require.Equal(t, validator.GetStatus(), types.Unbonding) } -//_________________________________________________________________________________ // tests Slash at a previous height with a redelegation func TestSlashWithRedelegation(t *testing.T) { app, ctx, addrDels, addrVals := bootstrapSlashTest(t, 10) diff --git a/x/staking/keeper/validator.go b/x/staking/keeper/validator.go index 0253c197aed3..46585c4ff123 100644 --- a/x/staking/keeper/validator.go +++ b/x/staking/keeper/validator.go @@ -240,7 +240,6 @@ func (k Keeper) ValidatorsPowerStoreIterator(ctx sdk.Context) sdk.Iterator { return sdk.KVStoreReversePrefixIterator(store, types.ValidatorsByPowerIndexKey) } -//_______________________________________________________________________ // Last Validator Index // Load the last validator power. diff --git a/x/staking/legacy/v034/types.go b/x/staking/legacy/v034/types.go index 9f8622d4bec2..539e6534bc5f 100644 --- a/x/staking/legacy/v034/types.go +++ b/x/staking/legacy/v034/types.go @@ -1,5 +1,4 @@ // DONTCOVER -// nolint package v034 import ( diff --git a/x/staking/legacy/v036/migrate.go b/x/staking/legacy/v036/migrate.go index cc4d7a4089b6..bb1f78bc4045 100644 --- a/x/staking/legacy/v036/migrate.go +++ b/x/staking/legacy/v036/migrate.go @@ -1,5 +1,4 @@ // DONTCOVER -// nolint package v036 import ( diff --git a/x/staking/legacy/v036/types.go b/x/staking/legacy/v036/types.go index b433b0070100..44cf3746d153 100644 --- a/x/staking/legacy/v036/types.go +++ b/x/staking/legacy/v036/types.go @@ -1,5 +1,4 @@ // DONTCOVER -// nolint package v036 import ( diff --git a/x/staking/legacy/v038/migrate.go b/x/staking/legacy/v038/migrate.go index 21029881a3fd..d2f65edadfe7 100644 --- a/x/staking/legacy/v038/migrate.go +++ b/x/staking/legacy/v038/migrate.go @@ -1,5 +1,4 @@ // DONTCOVER -// nolint package v038 import ( diff --git a/x/staking/legacy/v038/types.go b/x/staking/legacy/v038/types.go index 58ffa1351ba5..e11157d0e473 100644 --- a/x/staking/legacy/v038/types.go +++ b/x/staking/legacy/v038/types.go @@ -1,5 +1,4 @@ // DONTCOVER -// nolint package v038 import ( diff --git a/x/staking/module.go b/x/staking/module.go index 48c67e6f5cd1..ea4033a2f8c3 100644 --- a/x/staking/module.go +++ b/x/staking/module.go @@ -171,8 +171,6 @@ func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.Val return EndBlocker(ctx, am.keeper) } -//____________________________________________________________________________ - // AppModuleSimulation functions // GenerateGenesisState creates a randomized GenState of the staking module. diff --git a/x/staking/simulation/operations.go b/x/staking/simulation/operations.go index d9621bc7321c..cf99446b9f3d 100644 --- a/x/staking/simulation/operations.go +++ b/x/staking/simulation/operations.go @@ -92,7 +92,6 @@ func WeightedOperations( } // SimulateMsgCreateValidator generates a MsgCreateValidator with random values -// nolint: interfacer func SimulateMsgCreateValidator(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper) simtypes.Operation { return func( r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string, @@ -178,7 +177,6 @@ func SimulateMsgCreateValidator(ak types.AccountKeeper, bk types.BankKeeper, k k } // SimulateMsgEditValidator generates a MsgEditValidator with random values -// nolint: interfacer func SimulateMsgEditValidator(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper) simtypes.Operation { return func( r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string, @@ -249,7 +247,6 @@ func SimulateMsgEditValidator(ak types.AccountKeeper, bk types.BankKeeper, k kee } // SimulateMsgDelegate generates a MsgDelegate with random values -// nolint: interfacer func SimulateMsgDelegate(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper) simtypes.Operation { return func( r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string, @@ -322,7 +319,6 @@ func SimulateMsgDelegate(ak types.AccountKeeper, bk types.BankKeeper, k keeper.K } // SimulateMsgUndelegate generates a MsgUndelegate with random values -// nolint: interfacer func SimulateMsgUndelegate(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper) simtypes.Operation { return func( r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string, @@ -412,7 +408,6 @@ func SimulateMsgUndelegate(ak types.AccountKeeper, bk types.BankKeeper, k keeper } // SimulateMsgBeginRedelegate generates a MsgBeginRedelegate with random values -// nolint: interfacer func SimulateMsgBeginRedelegate(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper) simtypes.Operation { return func( r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string, diff --git a/x/staking/types/expected_keepers.go b/x/staking/types/expected_keepers.go index 07ceb7af1787..2b7326f99e44 100644 --- a/x/staking/types/expected_keepers.go +++ b/x/staking/types/expected_keepers.go @@ -82,7 +82,6 @@ type DelegationSet interface { fn func(index int64, delegation DelegationI) (stop bool)) } -//_______________________________________________________________________________ // Event Hooks // These can be utilized to communicate between a staking keeper and another // keeper which must take particular actions when validators/delegators change From 4c70268c9bf26b69cf2d5fb05b8a3be9f8176ddf Mon Sep 17 00:00:00 2001 From: Cyrus Goh Date: Tue, 23 Feb 2021 02:57:04 -0800 Subject: [PATCH 103/214] docs: update master docs (#8353) * bump docs theme to 1.0.180 * add v0.40 to config.js versions * Fix code snippet link * reorganize order of versions * 0.39, 0.41, master * defaulting to 0.41 Co-authored-by: billy rennekamp Co-authored-by: Amaury Martiny Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- docs/.vuepress/config.js | 4 + docs/core/cli.md | 2 +- docs/package-lock.json | 216 +++++++++++++++++++-------------------- 3 files changed, 113 insertions(+), 109 deletions(-) diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index ce94542714cd..59e33da233d0 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -42,6 +42,10 @@ module.exports = { "label": "v0.39", "key": "v0.39" }, + { + "label": "v0.41", + "key": "v0.41" + }, { "label": "master", "key": "master" diff --git a/docs/core/cli.md b/docs/core/cli.md index 10203e769e8c..a09b81407c67 100644 --- a/docs/core/cli.md +++ b/docs/core/cli.md @@ -96,7 +96,7 @@ This `queryCmd` function adds all the queries available to end-users for the app 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 ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/simapp/simd/cmd/root.go#L99-L121 ## Flags diff --git a/docs/package-lock.json b/docs/package-lock.json index d6bc2513349f..7e60448152d8 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -5,118 +5,118 @@ "requires": true, "dependencies": { "@algolia/cache-browser-local-storage": { - "version": "4.8.3", - "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.8.3.tgz", - "integrity": "sha512-Cwc03hikHSUI+xvgUdN+H+f6jFyoDsC9fegzXzJ2nPn1YSN9EXzDMBnbrgl0sbl9iLGXe0EIGMYqR2giCv1wMQ==", + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.8.4.tgz", + "integrity": "sha512-qSS3VMP3oMhcLrYIFveRyt3F5XB6MqWogF4Vooj8KvOvqv6jBmYwkAueSXCF5pkJEaA72VL9+9NbBpfC8ez2ww==", "requires": { - "@algolia/cache-common": "4.8.3" + "@algolia/cache-common": "4.8.4" } }, "@algolia/cache-common": { - "version": "4.8.3", - "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.8.3.tgz", - "integrity": "sha512-Cf7zZ2i6H+tLSBTkFePHhYvlgc9fnMPKsF9qTmiU38kFIGORy/TN2Fx5n1GBuRLIzaSXvcf+oHv1HvU0u1gE1g==" + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.8.4.tgz", + "integrity": "sha512-5+dLmj6qFy4WOtnNQuFRfWTIIDdpUigv+dXaKMFplNPBvZHGFy3hcRjWqYzGcqaeLqcXbN8cU5r75mvrlJIxcw==" }, "@algolia/cache-in-memory": { - "version": "4.8.3", - "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.8.3.tgz", - "integrity": "sha512-+N7tkvmijXiDy2E7u1mM73AGEgGPWFmEmPeJS96oT46I98KXAwVPNYbcAqBE79YlixdXpkYJk41cFcORzNh+Iw==", + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.8.4.tgz", + "integrity": "sha512-PBN4YKxn/L+HjVKqUE5rtLiFKqzm4qnUoF7QvCFFmFAViCdYwZSMFVmDobstqWY3KULfsEqaeD4eU4jxZbKhEA==", "requires": { - "@algolia/cache-common": "4.8.3" + "@algolia/cache-common": "4.8.4" } }, "@algolia/client-account": { - "version": "4.8.3", - "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.8.3.tgz", - "integrity": "sha512-Uku8LqnXBwfDCtsTCDYTUOz2/2oqcAQCKgaO0uGdIR8DTQENBXFQvzziambHdn9KuFuY+6Et9k1+cjpTPBDTBg==", + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.8.4.tgz", + "integrity": "sha512-mrsOnGV4O2b+t1CumUH72+Psw9d9qwngBEp2le7IMSceJQywQvNCyJ4B4qyoozHsIGapXfcVAOhRxqUsNQ6U6g==", "requires": { - "@algolia/client-common": "4.8.3", - "@algolia/client-search": "4.8.3", - "@algolia/transporter": "4.8.3" + "@algolia/client-common": "4.8.4", + "@algolia/client-search": "4.8.4", + "@algolia/transporter": "4.8.4" } }, "@algolia/client-analytics": { - "version": "4.8.3", - "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.8.3.tgz", - "integrity": "sha512-9ensIWmjYJprZ+YjAVSZdWUG05xEnbytENXp508X59tf34IMIX8BR2xl0RjAQODtxBdAteGxuKt5THX6U9tQLA==", + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.8.4.tgz", + "integrity": "sha512-Xy70njSUgG/QTv5+rPjsTIzBF/bjxseS5h9SawrQGzovTosbJbu9JBlg4YwVJnYvjovzpr7S39+gPIPc8M7+Rg==", "requires": { - "@algolia/client-common": "4.8.3", - "@algolia/client-search": "4.8.3", - "@algolia/requester-common": "4.8.3", - "@algolia/transporter": "4.8.3" + "@algolia/client-common": "4.8.4", + "@algolia/client-search": "4.8.4", + "@algolia/requester-common": "4.8.4", + "@algolia/transporter": "4.8.4" } }, "@algolia/client-common": { - "version": "4.8.3", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.8.3.tgz", - "integrity": "sha512-TU3623AEFAWUQlDTznkgAMSYo8lfS9pNs5QYDQzkvzWdqK0GBDWthwdRfo9iIsfxiR9qdCMHqwEu+AlZMVhNSA==", + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.8.4.tgz", + "integrity": "sha512-sQlRa+KWFn+D8AOEZb4kj6RE/i6DnPwVOF4AnNf9IjNB0mUUhLWw96cQN6GDx0KE4lhW67t+qR39ZuuDBgR9ww==", "requires": { - "@algolia/requester-common": "4.8.3", - "@algolia/transporter": "4.8.3" + "@algolia/requester-common": "4.8.4", + "@algolia/transporter": "4.8.4" } }, "@algolia/client-recommendation": { - "version": "4.8.3", - "resolved": "https://registry.npmjs.org/@algolia/client-recommendation/-/client-recommendation-4.8.3.tgz", - "integrity": "sha512-qysGbmkcc6Agt29E38KWJq9JuxjGsyEYoKuX9K+P5HyQh08yR/BlRYrA8mB7vT/OIUHRGFToGO6Vq/rcg0NIOQ==", + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/@algolia/client-recommendation/-/client-recommendation-4.8.4.tgz", + "integrity": "sha512-CE0CVqLGWotVOaUXyU33FVD9FZ/7rqcbwFPH5MgSjVdE0B1YWVedhR0s2BNKodXLcIGVLVYfXR05CLdvOlTw+A==", "requires": { - "@algolia/client-common": "4.8.3", - "@algolia/requester-common": "4.8.3", - "@algolia/transporter": "4.8.3" + "@algolia/client-common": "4.8.4", + "@algolia/requester-common": "4.8.4", + "@algolia/transporter": "4.8.4" } }, "@algolia/client-search": { - "version": "4.8.3", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.8.3.tgz", - "integrity": "sha512-rAnvoy3GAhbzOQVniFcKVn1eM2NX77LearzYNCbtFrFYavG+hJI187bNVmajToiuGZ10FfJvK99X2OB1AzzezQ==", + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.8.4.tgz", + "integrity": "sha512-eH2tRPnDU3tqpp0BSqP6coRRQe8fceqsupuf/1ho+Mcs5DM13mEuFmNOyPywHRlYLVPmbbCPRhDr5rB8QoN7XQ==", "requires": { - "@algolia/client-common": "4.8.3", - "@algolia/requester-common": "4.8.3", - "@algolia/transporter": "4.8.3" + "@algolia/client-common": "4.8.4", + "@algolia/requester-common": "4.8.4", + "@algolia/transporter": "4.8.4" } }, "@algolia/logger-common": { - "version": "4.8.3", - "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.8.3.tgz", - "integrity": "sha512-03wksHRbhl2DouEKnqWuUb64s1lV6kDAAabMCQ2Du1fb8X/WhDmxHC4UXMzypeOGlH5BZBsgVwSB7vsZLP3MZg==" + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.8.4.tgz", + "integrity": "sha512-6hOaFG75Onmant9adcaeCZgvPYfnif7n0H1ycbixm6/WH3SmxqPMG+CMiW8mTNTRrrAEceQVrq6tDHD8jdnOOw==" }, "@algolia/logger-console": { - "version": "4.8.3", - "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.8.3.tgz", - "integrity": "sha512-Npt+hI4UF8t3TLMluL5utr9Gc11BjL5kDnGZOhDOAz5jYiSO2nrHMFmnpLT4Cy/u7a5t7EB5dlypuC4/AGStkA==", + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.8.4.tgz", + "integrity": "sha512-+9T3t/eB9vseANFz9YbFHG0cHjzVP/DVfGqzTAkeSlvMHP69JzJga9Wb0Ai6J3xXE3d4k9K+k6t+kkjCQjzEqg==", "requires": { - "@algolia/logger-common": "4.8.3" + "@algolia/logger-common": "4.8.4" } }, "@algolia/requester-browser-xhr": { - "version": "4.8.3", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.8.3.tgz", - "integrity": "sha512-/LTTIpgEmEwkyhn8yXxDdBWqXqzlgw5w2PtTpIwkSlP2/jDwdR/9w1TkFzhNbJ81ki6LAEQM5mSwoTTnbIIecg==", + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.8.4.tgz", + "integrity": "sha512-BYa8O/pht0UL2bcm0ZkLZiyC+5dHrbc6gvKIo+OgqxmDb/K4KrVo6RIof3BVpR8fgcfxQJohjNVHKXHxEUhBCQ==", "requires": { - "@algolia/requester-common": "4.8.3" + "@algolia/requester-common": "4.8.4" } }, "@algolia/requester-common": { - "version": "4.8.3", - "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.8.3.tgz", - "integrity": "sha512-+Yo9vBkofoKR1SCqqtMnmnfq9yt/BiaDewY/6bYSMNxSYCnu2Fw1JKSIaf/4zos09PMSsxGpLohZwGas3+0GDQ==" + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.8.4.tgz", + "integrity": "sha512-br3LXb6srfAy7F04axwExmrkPOlXCDckgTFoLFv/RT9Oo28SpoyvHqktyBovQLdzdTs+Laglf+LtOHr0iUrZJg==" }, "@algolia/requester-node-http": { - "version": "4.8.3", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.8.3.tgz", - "integrity": "sha512-k2fiKIeMIFqgC01FnzII6kqC2GQBAfbNaUX4k7QCPa6P8t4sp2xE6fImOUiztLnnL3C9X9ZX6Fw3L+cudi7jvQ==", + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.8.4.tgz", + "integrity": "sha512-o5Cc4UxYPn3IBHQSDBNFFhq1LQLv40eYvCvK0FPJ8xZkrnNXhjPvaLCu/lQTHpk/HX7DaE6fQ/KboU0OSPKevQ==", "requires": { - "@algolia/requester-common": "4.8.3" + "@algolia/requester-common": "4.8.4" } }, "@algolia/transporter": { - "version": "4.8.3", - "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.8.3.tgz", - "integrity": "sha512-nU7fy2iU8snxATlsks0MjMyv97QJWQmOVwTjDc+KZ4+nue8CLcgm4LA4dsTBqvxeCQIoEtt3n72GwXcaqiJSjQ==", + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.8.4.tgz", + "integrity": "sha512-EvXFYICxrr9QEO6m6awUeNOBstOxePQ2Fy0jtYlS1v9TY2P5HqKRzkxmaZjeYRBsXOImpVjgQIzTzj1Au4br2w==", "requires": { - "@algolia/cache-common": "4.8.3", - "@algolia/logger-common": "4.8.3", - "@algolia/requester-common": "4.8.3" + "@algolia/cache-common": "4.8.4", + "@algolia/logger-common": "4.8.4", + "@algolia/requester-common": "4.8.4" } }, "@babel/code-frame": { @@ -1241,9 +1241,9 @@ } }, "@types/json-schema": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz", - "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==" + "version": "7.0.7", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz", + "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==" }, "@types/minimatch": { "version": "3.0.3", @@ -1251,9 +1251,9 @@ "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==" }, "@types/node": { - "version": "14.14.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.21.tgz", - "integrity": "sha512-cHYfKsnwllYhjOzuC5q1VpguABBeecUp24yFluHpn/BQaVxB1CuQ1FSRZCzrPxrkIfWISXV2LbeoBthLWg0+0A==" + "version": "14.14.22", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.22.tgz", + "integrity": "sha512-g+f/qj/cNcqKkc3tFqlXOYjrmZA+jNBiDzbP3kH+B+otKFqAdPgVTGP1IeKRdMml/aE69as5S4FqtxAbl+LaMw==" }, "@types/q": { "version": "1.5.4", @@ -1337,9 +1337,9 @@ }, "dependencies": { "core-js": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.8.2.tgz", - "integrity": "sha512-FfApuSRgrR6G5s58casCBd9M2k+4ikuu4wbW6pJyYU7bd9zvFc9qf7vr5xmrZOhT9nn+8uwlH1oRR9jTnFoA3A==" + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.8.3.tgz", + "integrity": "sha512-KPYXeVZYemC2TkNEkX/01I+7yd+nX3KddKwZ1Ww7SKWdI2wQprSgLmrTddT8nw92AjEklTsPBoSdQBhbI1bQ6Q==" } } }, @@ -1510,9 +1510,9 @@ }, "dependencies": { "core-js": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.8.2.tgz", - "integrity": "sha512-FfApuSRgrR6G5s58casCBd9M2k+4ikuu4wbW6pJyYU7bd9zvFc9qf7vr5xmrZOhT9nn+8uwlH1oRR9jTnFoA3A==" + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.8.3.tgz", + "integrity": "sha512-KPYXeVZYemC2TkNEkX/01I+7yd+nX3KddKwZ1Ww7SKWdI2wQprSgLmrTddT8nw92AjEklTsPBoSdQBhbI1bQ6Q==" } } }, @@ -1861,24 +1861,24 @@ "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==" }, "algoliasearch": { - "version": "4.8.3", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.8.3.tgz", - "integrity": "sha512-pljX9jEE2TQ3i1JayhG8afNdE8UuJg3O9c7unW6QO67yRWCKr6b0t5aKC3hSVtjt7pA2TQXLKoAISb4SHx9ozQ==", - "requires": { - "@algolia/cache-browser-local-storage": "4.8.3", - "@algolia/cache-common": "4.8.3", - "@algolia/cache-in-memory": "4.8.3", - "@algolia/client-account": "4.8.3", - "@algolia/client-analytics": "4.8.3", - "@algolia/client-common": "4.8.3", - "@algolia/client-recommendation": "4.8.3", - "@algolia/client-search": "4.8.3", - "@algolia/logger-common": "4.8.3", - "@algolia/logger-console": "4.8.3", - "@algolia/requester-browser-xhr": "4.8.3", - "@algolia/requester-common": "4.8.3", - "@algolia/requester-node-http": "4.8.3", - "@algolia/transporter": "4.8.3" + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.8.4.tgz", + "integrity": "sha512-QbXpFvBKj/QhKWE7xBoqaWOWyw7ni6W6THSuFJHOcADRrInhjFCBYjrv+YsIhv9huCepKXWpfV4UJup9BslVhQ==", + "requires": { + "@algolia/cache-browser-local-storage": "4.8.4", + "@algolia/cache-common": "4.8.4", + "@algolia/cache-in-memory": "4.8.4", + "@algolia/client-account": "4.8.4", + "@algolia/client-analytics": "4.8.4", + "@algolia/client-common": "4.8.4", + "@algolia/client-recommendation": "4.8.4", + "@algolia/client-search": "4.8.4", + "@algolia/logger-common": "4.8.4", + "@algolia/logger-console": "4.8.4", + "@algolia/requester-browser-xhr": "4.8.4", + "@algolia/requester-common": "4.8.4", + "@algolia/requester-node-http": "4.8.4", + "@algolia/transporter": "4.8.4" } }, "align-text": { @@ -2864,9 +2864,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001178", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001178.tgz", - "integrity": "sha512-VtdZLC0vsXykKni8Uztx45xynytOi71Ufx9T8kHptSw9AL4dpqailUJJHavttuzUe1KYuBYtChiWv+BAb7mPmQ==" + "version": "1.0.30001179", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001179.tgz", + "integrity": "sha512-blMmO0QQujuUWZKyVrD1msR4WNDAqb/UPO1Sw2WWsQ7deoM5bJiicKnWJ1Y0NS/aGINSnKPIWBMw5luX+NDUCA==" }, "caseless": { "version": "0.12.0", @@ -3406,11 +3406,11 @@ "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==" }, "core-js-compat": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.8.2.tgz", - "integrity": "sha512-LO8uL9lOIyRRrQmZxHZFl1RV+ZbcsAkFWTktn5SmH40WgLtSNYN4m4W2v9ONT147PxBY/XrRhrWq8TlvObyUjQ==", + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.8.3.tgz", + "integrity": "sha512-1sCb0wBXnBIL16pfFG1Gkvei6UzvKyTNYpiC41yrdjEv0UoJoq9E/abTMzyYJ6JpTkAj15dLjbqifIzEBDVvog==", "requires": { - "browserslist": "^4.16.0", + "browserslist": "^4.16.1", "semver": "7.0.0" }, "dependencies": { @@ -4123,9 +4123,9 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "electron-to-chromium": { - "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==" + "version": "1.3.642", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.642.tgz", + "integrity": "sha512-cev+jOrz/Zm1i+Yh334Hed6lQVOkkemk2wRozfMF4MtTR7pxf3r3L5Rbd7uX1zMcEqVJ7alJBnJL7+JffkC6FQ==" }, "elliptic": { "version": "6.5.3", @@ -6515,9 +6515,9 @@ } }, "node-releases": { - "version": "1.1.69", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.69.tgz", - "integrity": "sha512-DGIjo79VDEyAnRlfSqYTsy+yoHd2IOjJiKUozD2MV2D85Vso6Bug56mb9tT/fY5Urt0iqk01H7x+llAruDR2zA==" + "version": "1.1.70", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.70.tgz", + "integrity": "sha512-Slf2s69+2/uAD79pVVQo8uSiC34+g8GWY8UH2Qtqv34ZfhYrxpYpfzs9Js9d6O0mbDmALuxaTlplnBTnSELcrw==" }, "nopt": { "version": "1.0.10", From 8db9bbba04204f4556578369bd2ef03067f62736 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Tue, 23 Feb 2021 14:38:37 +0100 Subject: [PATCH 104/214] linter: ignore false positives in types/address (#8674) --- types/address/hash.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/types/address/hash.go b/types/address/hash.go index 8c0cddae02e6..d6a249a8a287 100644 --- a/types/address/hash.go +++ b/types/address/hash.go @@ -67,8 +67,8 @@ func Module(moduleName string, key []byte) []byte { // 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 := *(*reflect.SliceHeader)(unsafe.Pointer(&s)) // nolint:govet sh.Cap = sh.Len - bs := *(*[]byte)(unsafe.Pointer(&sh)) + bs := *(*[]byte)(unsafe.Pointer(&sh)) // nolint:govet return bs } From 8dd6c325bae70c5c912344db6ac04a38f4dc6d3e Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Tue, 23 Feb 2021 16:55:06 +0100 Subject: [PATCH 105/214] multisig checks and optimization (#8600) * Add Equal method to the CompactBitArray * optimize NumTrueBitsBefore * fix compact_bit_array * add more tests and update comments * add check for unique keys * add unit tests * LegacyAminoPubKey: rollback pubkey uniqueness check * comment update * Bechmark NumTrueBitsBefore * Adding one more test * changelog update * Update crypto/types/compact_bit_array.go Co-authored-by: Alessio Treglia * change iff to if and only if * add comment to NumTrueBitsBefore * merge conflict * Changelog cosmetic update * Update CHANGELOG.md Co-authored-by: Alessio Treglia --- CHANGELOG.md | 2 + crypto/keys/multisig/multisig.go | 12 +++-- crypto/keys/multisig/multisig_test.go | 64 +++++++++++++++++-------- crypto/types/compact_bit_array.go | 46 +++++++++++++----- crypto/types/compact_bit_array_test.go | 38 +++++++++++++++ crypto/types/multisig/multisignature.go | 3 +- x/auth/testutil/suite.go | 11 +---- 7 files changed, 129 insertions(+), 47 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 11ef49af3134..444e0bf9450f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -61,6 +61,8 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements * (x/auth) [\#8522](https://github.com/cosmos/cosmos-sdk/pull/8522) Allow to query all stored accounts +* (crypto/types) [\#8600](https://github.com/cosmos/cosmos-sdk/pull/8600) `CompactBitArray`: optimize the `NumTrueBitsBefore` method and add an `Equal` method. + ### Bug Fixes diff --git a/crypto/keys/multisig/multisig.go b/crypto/keys/multisig/multisig.go index 590e5ba11001..b3d8d8fab8ab 100644 --- a/crypto/keys/multisig/multisig.go +++ b/crypto/keys/multisig/multisig.go @@ -15,6 +15,8 @@ var _ multisigtypes.PubKey = &LegacyAminoPubKey{} var _ types.UnpackInterfacesMessage = &LegacyAminoPubKey{} // NewLegacyAminoPubKey returns a new LegacyAminoPubKey. +// Multisig can be constructed with multiple same keys - it will increase the power of +// the owner of that key (he will still need to add multiple signatures in the right order). // Panics if len(pubKeys) < k or 0 >= k. func NewLegacyAminoPubKey(k int, pubKeys []cryptotypes.PubKey) *LegacyAminoPubKey { if k <= 0 { @@ -40,7 +42,11 @@ func (m *LegacyAminoPubKey) Bytes() []byte { return AminoCdc.MustMarshalBinaryBare(m) } -// VerifyMultisignature implements the multisigtypes.PubKey VerifyMultisignature method +// VerifyMultisignature implements the multisigtypes.PubKey VerifyMultisignature method. +// The signatures must be added in an order corresponding to the public keys order in +// LegacyAminoPubKey. It's OK to have multiple same keys in the multisig - it will increase +// the power of the owner of that key - in that case the signer will still need to append +// multiple same signatures in the right order. func (m *LegacyAminoPubKey) VerifyMultisignature(getSignBytes multisigtypes.GetSignBytesFunc, sig *signing.MultiSignatureData) error { bitarray := sig.BitArray sigs := sig.Signatures @@ -48,7 +54,7 @@ func (m *LegacyAminoPubKey) VerifyMultisignature(getSignBytes multisigtypes.GetS pubKeys := m.GetPubKeys() // ensure bit array is the correct size if len(pubKeys) != size { - return fmt.Errorf("bit array size is incorrect %d", len(pubKeys)) + return fmt.Errorf("bit array size is incorrect, expecting: %d", len(pubKeys)) } // ensure size of signature list if len(sigs) < int(m.Threshold) || len(sigs) > size { @@ -56,7 +62,7 @@ func (m *LegacyAminoPubKey) VerifyMultisignature(getSignBytes multisigtypes.GetS } // ensure at least k signatures are set if bitarray.NumTrueBitsBefore(size) < int(m.Threshold) { - return fmt.Errorf("minimum number of signatures not set, have %d, expected %d", bitarray.NumTrueBitsBefore(size), int(m.Threshold)) + return fmt.Errorf("not enough signatures set, have %d, expected %d", bitarray.NumTrueBitsBefore(size), int(m.Threshold)) } // index in the list of signatures which we are concerned with. sigIndex := 0 diff --git a/crypto/keys/multisig/multisig_test.go b/crypto/keys/multisig/multisig_test.go index 2b91e74eb6c5..69b4f10d2694 100644 --- a/crypto/keys/multisig/multisig_test.go +++ b/crypto/keys/multisig/multisig_test.go @@ -15,6 +15,15 @@ import ( "github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx" ) +func TestNewMultiSig(t *testing.T) { + require := require.New(t) + pk1 := secp256k1.GenPrivKey().PubKey() + pks := []cryptotypes.PubKey{pk1, pk1} + + require.NotNil(kmultisig.NewLegacyAminoPubKey(1, pks), + "Should support not unique public keys") +} + func TestAddress(t *testing.T) { msg := []byte{1, 2, 3, 4} pubKeys, _ := generatePubKeysAndSignatures(5, msg) @@ -85,21 +94,20 @@ func TestVerifyMultisignature(t *testing.T) { testCases := []struct { msg string - malleate func() + malleate func(*require.Assertions) expectPass bool }{ { "nested multisignature", - func() { + func(require *require.Assertions) { genPk, genSig := generateNestedMultiSignature(3, msg) sig = genSig pk = genPk }, true, - }, - { + }, { "wrong size for sig bit array", - func() { + func(require *require.Assertions) { pubKeys, _ := generatePubKeysAndSignatures(3, msg) pk = kmultisig.NewLegacyAminoPubKey(3, pubKeys) sig = multisig.NewMultisig(1) @@ -108,7 +116,7 @@ func TestVerifyMultisignature(t *testing.T) { }, { "single signature data, expects the first k signatures to be valid", - func() { + func(require *require.Assertions) { k := 2 signingIndices := []int{0, 3, 1} pubKeys, sigs := generatePubKeysAndSignatures(5, msg) @@ -119,32 +127,26 @@ func TestVerifyMultisignature(t *testing.T) { for i := 0; i < k-1; i++ { signingIndex := signingIndices[i] require.NoError( - t, multisig.AddSignatureFromPubKey(sig, sigs[signingIndex], pubKeys[signingIndex], pubKeys), ) require.Error( - t, pk.VerifyMultisignature(signBytesFn, sig), "multisig passed when i < k, i %d", i, ) require.NoError( - t, multisig.AddSignatureFromPubKey(sig, sigs[signingIndex], pubKeys[signingIndex], pubKeys), ) require.Equal( - t, i+1, len(sig.Signatures), "adding a signature for the same pubkey twice increased signature count by 2, index %d", i, ) } require.Error( - t, pk.VerifyMultisignature(signBytesFn, sig), "multisig passed with k - 1 sigs", ) require.NoError( - t, multisig.AddSignatureFromPubKey( sig, sigs[signingIndices[k]], @@ -153,30 +155,50 @@ func TestVerifyMultisignature(t *testing.T) { ), ) require.NoError( - t, pk.VerifyMultisignature(signBytesFn, sig), "multisig failed after k good signatures", ) }, true, - }, - { + }, { "duplicate signatures", - func() { + func(require *require.Assertions) { pubKeys, sigs := generatePubKeysAndSignatures(5, msg) pk = kmultisig.NewLegacyAminoPubKey(2, pubKeys) sig = multisig.NewMultisig(5) - require.Error(t, pk.VerifyMultisignature(signBytesFn, sig)) + require.Error(pk.VerifyMultisignature(signBytesFn, sig)) multisig.AddSignatureFromPubKey(sig, sigs[0], pubKeys[0], pubKeys) // Add second signature manually sig.Signatures = append(sig.Signatures, sigs[0]) }, false, - }, - { + }, { + "duplicated key", + func(require *require.Assertions) { + // here we test an edge case where we create a multi sig with two same + // keys. It should work. + pubkeys, sigs := generatePubKeysAndSignatures(3, msg) + pubkeys[1] = pubkeys[0] + pk = kmultisig.NewLegacyAminoPubKey(2, pubkeys) + sig = multisig.NewMultisig(len(pubkeys)) + multisig.AddSignature(sig, sigs[0], 0) + multisig.AddSignature(sig, sigs[0], 1) + }, + true, + }, { + "same key used twice", + func(require *require.Assertions) { + pubkeys, sigs := generatePubKeysAndSignatures(3, msg) + pk = kmultisig.NewLegacyAminoPubKey(2, pubkeys) + sig = multisig.NewMultisig(len(pubkeys)) + multisig.AddSignature(sig, sigs[0], 0) + multisig.AddSignature(sig, sigs[0], 1) + }, + false, + }, { "unable to verify signature", - func() { + func(require *require.Assertions) { pubKeys, _ := generatePubKeysAndSignatures(2, msg) _, sigs := generatePubKeysAndSignatures(2, msg) pk = kmultisig.NewLegacyAminoPubKey(2, pubKeys) @@ -190,7 +212,7 @@ func TestVerifyMultisignature(t *testing.T) { for _, tc := range testCases { t.Run(tc.msg, func(t *testing.T) { - tc.malleate() + tc.malleate(require.New(t)) err := pk.VerifyMultisignature(signBytesFn, sig) if tc.expectPass { require.NoError(t, err) diff --git a/crypto/types/compact_bit_array.go b/crypto/types/compact_bit_array.go index 7c7188f6abd5..2d81636f4abb 100644 --- a/crypto/types/compact_bit_array.go +++ b/crypto/types/compact_bit_array.go @@ -30,14 +30,14 @@ func NewCompactBitArray(bits int) *CompactBitArray { func (bA *CompactBitArray) Count() int { if bA == nil { return 0 - } else if bA.ExtraBitsStored == uint32(0) { + } else if bA.ExtraBitsStored == 0 { return len(bA.Elems) * 8 } return (len(bA.Elems)-1)*8 + int(bA.ExtraBitsStored) } -// GetIndex returns the bit at index i within the bit array. +// GetIndex returns true if the bit at index i is set; returns false otherwise. // The behavior is undefined if i >= bA.Count() func (bA *CompactBitArray) GetIndex(i int) bool { if bA == nil { @@ -47,11 +47,11 @@ func (bA *CompactBitArray) GetIndex(i int) bool { return false } - return bA.Elems[i>>3]&(uint8(1)< 0 + return bA.Elems[i>>3]&(1< 0 } -// SetIndex sets the bit at index i within the bit array. -// The behavior is undefined if i >= bA.Count() +// SetIndex sets the bit at index i within the bit array. Returns true if and only if the +// operation succeeded. The behavior is undefined if i >= bA.Count() func (bA *CompactBitArray) SetIndex(i int, v bool) bool { if bA == nil { return false @@ -62,9 +62,9 @@ func (bA *CompactBitArray) SetIndex(i int, v bool) bool { } if v { - bA.Elems[i>>3] |= (uint8(1) << uint8(7-(i%8))) + bA.Elems[i>>3] |= (1 << uint8(7-(i%8))) } else { - bA.Elems[i>>3] &= ^(uint8(1) << uint8(7-(i%8))) + bA.Elems[i>>3] &= ^(1 << uint8(7-(i%8))) } return true @@ -75,13 +75,23 @@ func (bA *CompactBitArray) SetIndex(i int, v bool) bool { // there are two bits set to true before index 4. func (bA *CompactBitArray) NumTrueBitsBefore(index int) int { numTrueValues := 0 - for i := 0; i < index; i++ { - if bA.GetIndex(i) { - numTrueValues++ + max := bA.Count() + if index > max { + index = max + } + // below we iterate over the bytes then over bits (in low endian) and count bits set to 1 + var i = 0 + for elem := 0; ; elem++ { + for b := 7; b >= 0; b-- { + if i >= index { + return numTrueValues + } + i++ + if (bA.Elems[elem]>>b)&1 == 1 { + numTrueValues++ + } } } - - return numTrueValues } // Copy returns a copy of the provided bit array. @@ -99,6 +109,18 @@ func (bA *CompactBitArray) Copy() *CompactBitArray { } } +// Equal checks if both bit arrays are equal. If both arrays are nil then it returns true. +func (bA *CompactBitArray) Equal(other *CompactBitArray) bool { + if bA == other { + return true + } + if bA == nil || other == nil { + return false + } + return bA.ExtraBitsStored == other.ExtraBitsStored && + bytes.Equal(bA.Elems, other.Elems) +} + // String returns a string representation of CompactBitArray: BA{}, // where is a sequence of 'x' (1) and '_' (0). // The includes spaces and newlines to help people. diff --git a/crypto/types/compact_bit_array_test.go b/crypto/types/compact_bit_array_test.go index 44408e43ae06..be4b87a23c20 100644 --- a/crypto/types/compact_bit_array_test.go +++ b/crypto/types/compact_bit_array_test.go @@ -36,6 +36,34 @@ func TestNewBitArrayNeverCrashesOnNegatives(t *testing.T) { } } +func TestBitArrayEqual(t *testing.T) { + empty := new(CompactBitArray) + big1, _ := randCompactBitArray(1000) + big1Cpy := *big1 + big2, _ := randCompactBitArray(1000) + big2.SetIndex(500, !big1.GetIndex(500)) // ensure they are different + cases := []struct { + name string + b1 *CompactBitArray + b2 *CompactBitArray + eq bool + }{ + {name: "both nil are equal", b1: nil, b2: nil, eq: true}, + {name: "if one is nil then not equal", b1: nil, b2: empty, eq: false}, + {name: "nil and empty not equal", b1: empty, b2: nil, eq: false}, + {name: "empty and empty equal", b1: empty, b2: new(CompactBitArray), eq: true}, + {name: "same bits should be equal", b1: big1, b2: &big1Cpy, eq: true}, + {name: "different should not be equal", b1: big1, b2: big2, eq: false}, + } + for _, tc := range cases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + eq := tc.b1.Equal(tc.b2) + require.Equal(t, tc.eq, eq) + }) + } +} + func TestJSONMarshalUnmarshal(t *testing.T) { bA1 := NewCompactBitArray(0) @@ -200,3 +228,13 @@ func TestCompactBitArrayGetSetIndex(t *testing.T) { } } } + +func BenchmarkNumTrueBitsBefore(b *testing.B) { + ba, _ := randCompactBitArray(100) + + b.Run("new", func(b *testing.B) { + for i := 0; i < b.N; i++ { + ba.NumTrueBitsBefore(90) + } + }) +} diff --git a/crypto/types/multisig/multisignature.go b/crypto/types/multisig/multisignature.go index 20e3ef1129e4..362fa469358b 100644 --- a/crypto/types/multisig/multisignature.go +++ b/crypto/types/multisig/multisignature.go @@ -34,7 +34,8 @@ func getIndex(pk types.PubKey, keys []types.PubKey) int { return -1 } -// AddSignature adds a signature to the multisig, at the corresponding index. +// AddSignature adds a signature to the multisig, at the corresponding index. The index must +// represent the pubkey index in the LegacyAmingPubKey structure, which verifies this signature. // If the signature already exists, replace it. func AddSignature(mSig *signing.MultiSignatureData, sig signing.SignatureData, index int) { newSigIndex := mSig.BitArray.NumTrueBitsBefore(index) diff --git a/x/auth/testutil/suite.go b/x/auth/testutil/suite.go index b1e9f25c311b..15f6334b40a3 100644 --- a/x/auth/testutil/suite.go +++ b/x/auth/testutil/suite.go @@ -199,16 +199,7 @@ func sigDataEquals(data1, data2 signingtypes.SignatureData) bool { if !ok { return false } - - if data1.BitArray.ExtraBitsStored != data2.BitArray.ExtraBitsStored { - return false - } - - if !bytes.Equal(data1.BitArray.Elems, data2.BitArray.Elems) { - return false - } - - if len(data1.Signatures) != len(data2.Signatures) { + if !data1.BitArray.Equal(data2.BitArray) || len(data1.Signatures) != len(data2.Signatures) { return false } From cc70749b0764fac72486591459c43453398ebfd6 Mon Sep 17 00:00:00 2001 From: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Date: Tue, 23 Feb 2021 13:49:09 -0300 Subject: [PATCH 106/214] keyring: remove hardcoded default passphrase on NewMnemonic (#8662) * keyring: remove hardcoded default passphrase on NewMnemonic * minor changes * changelog * address @alessio's comment * Update CHANGELOG.md * test fixes * update comment and test Co-authored-by: Alessio Treglia Co-authored-by: Jonathan Gimeno Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- CHANGELOG.md | 2 + client/keys/delete_test.go | 2 +- client/tx/tx_test.go | 4 +- crypto/armor_test.go | 2 +- crypto/keyring/keyring.go | 32 +++++--- crypto/keyring/keyring_ledger_test.go | 2 +- crypto/keyring/keyring_test.go | 92 +++++++++++------------ server/init.go | 4 +- x/auth/client/cli/cli_test.go | 6 +- x/auth/client/rest/rest_test.go | 2 +- x/authz/client/cli/tx_test.go | 2 +- x/authz/client/rest/grpc_query_test.go | 2 +- x/feegrant/client/cli/cli_test.go | 2 +- x/feegrant/client/rest/grpc_query_test.go | 2 +- x/staking/client/cli/cli_test.go | 6 +- 15 files changed, 89 insertions(+), 73 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 444e0bf9450f..21c7a9ac67c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### API Breaking Changes +* (keyring) [#\8662](https://github.com/cosmos/cosmos-sdk/pull/8662) `NewMnemonic` now receives an additional `passphrase` argument to secure the key generated by the bip39 mnemonic. * (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. @@ -66,6 +67,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Bug Fixes +* (keyring) [#\8635](https://github.com/cosmos/cosmos-sdk/issues/8635) Remove hardcoded default passphrase value on `NewMnemonic` * (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 diff --git a/client/keys/delete_test.go b/client/keys/delete_test.go index 49da92bf1f72..76f8c211f264 100644 --- a/client/keys/delete_test.go +++ b/client/keys/delete_test.go @@ -39,7 +39,7 @@ func Test_runDeleteCmd(t *testing.T) { _, err = kb.NewAccount(fakeKeyName1, testutil.TestMnemonic, "", path, hd.Secp256k1) require.NoError(t, err) - _, _, err = kb.NewMnemonic(fakeKeyName2, keyring.English, sdk.FullFundraiserPath, hd.Secp256k1) + _, _, err = kb.NewMnemonic(fakeKeyName2, keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) require.NoError(t, err) cmd.SetArgs([]string{"blah", fmt.Sprintf("--%s=%s", flags.FlagHome, kbHome)}) diff --git a/client/tx/tx_test.go b/client/tx/tx_test.go index 3c7a4bebef0e..58edbc0eafd8 100644 --- a/client/tx/tx_test.go +++ b/client/tx/tx_test.go @@ -132,10 +132,10 @@ func TestSign(t *testing.T) { var from2 = "test_key2" // create a new key using a mnemonic generator and test if we can reuse seed to recreate that account - _, seed, err := kr.NewMnemonic(from1, keyring.English, path, hd.Secp256k1) + _, seed, err := kr.NewMnemonic(from1, keyring.English, path, keyring.DefaultBIP39Passphrase, hd.Secp256k1) requireT.NoError(err) requireT.NoError(kr.Delete(from1)) - info1, _, err := kr.NewMnemonic(from1, keyring.English, path, hd.Secp256k1) + info1, _, err := kr.NewMnemonic(from1, keyring.English, path, keyring.DefaultBIP39Passphrase, hd.Secp256k1) requireT.NoError(err) info2, err := kr.NewAccount(from2, seed, "", path, hd.Secp256k1) diff --git a/crypto/armor_test.go b/crypto/armor_test.go index 70854f6dcb41..fb80b5266ab8 100644 --- a/crypto/armor_test.go +++ b/crypto/armor_test.go @@ -73,7 +73,7 @@ func TestArmorUnarmorPubKey(t *testing.T) { cstore := keyring.NewInMemory() // Add keys and see they return in alphabetical order - info, _, err := cstore.NewMnemonic("Bob", keyring.English, types.FullFundraiserPath, hd.Secp256k1) + info, _, err := cstore.NewMnemonic("Bob", keyring.English, types.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) require.NoError(t, err) armored := crypto.ArmorPubKeyBytes(legacy.Cdc.Amino.MustMarshalBinaryBare(info.GetPubKey()), "") pubBytes, algo, err := crypto.UnarmorPubKeyBytes(armored) diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index 164e6bfc19d5..14dd4581a5f3 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -64,14 +64,17 @@ type Keyring interface { Delete(uid string) error DeleteByAddress(address sdk.Address) error - // NewMnemonic generates a new mnemonic, derives a hierarchical deterministic - // key from that, and persists it to the storage. Returns the generated mnemonic and the key - // Info. It returns an error if it fails to generate a key for the given algo type, or if - // another key is already stored under the same name. - NewMnemonic(uid string, language Language, hdPath string, algo SignatureAlgo) (Info, string, error) + // NewMnemonic generates a new mnemonic, derives a hierarchical deterministic key from it, and + // persists the key to storage. Returns the generated mnemonic and the key Info. + // It returns an error if it fails to generate a key for the given algo type, or if + // another key is already stored under the same name or address. + // + // A passphrase set to the empty string will set the passphrase to the DefaultBIP39Passphrase value. + NewMnemonic(uid string, language Language, hdPath, bip39Passphrase string, algo SignatureAlgo) (Info, string, error) // NewAccount converts a mnemonic to a private key and BIP-39 HD Path and persists it. - NewAccount(uid, mnemonic, bip39Passwd, hdPath string, algo SignatureAlgo) (Info, error) + // It fails if there is an existing key Info with the same address. + NewAccount(uid, mnemonic, bip39Passphrase, hdPath string, algo SignatureAlgo) (Info, error) // SaveLedgerKey retrieves a public key reference from a Ledger device and persists it. SaveLedgerKey(uid string, algo SignatureAlgo, hrp string, coinType, account, index uint32) (Info, error) @@ -477,7 +480,7 @@ func (ks keystore) List() ([]Info, error) { return res, nil } -func (ks keystore) NewMnemonic(uid string, language Language, hdPath string, algo SignatureAlgo) (Info, string, error) { +func (ks keystore) NewMnemonic(uid string, language Language, hdPath, bip39Passphrase string, algo SignatureAlgo) (Info, string, error) { if language != English { return nil, "", ErrUnsupportedLanguage } @@ -498,12 +501,16 @@ func (ks keystore) NewMnemonic(uid string, language Language, hdPath string, alg return nil, "", err } - info, err := ks.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, hdPath, algo) + if bip39Passphrase == "" { + bip39Passphrase = DefaultBIP39Passphrase + } + + info, err := ks.NewAccount(uid, mnemonic, bip39Passphrase, hdPath, algo) if err != nil { return nil, "", err } - return info, mnemonic, err + return info, mnemonic, nil } func (ks keystore) NewAccount(uid string, mnemonic string, bip39Passphrase string, hdPath string, algo SignatureAlgo) (Info, error) { @@ -519,6 +526,13 @@ func (ks keystore) NewAccount(uid string, mnemonic string, bip39Passphrase strin privKey := algo.Generate()(derivedPriv) + // check if the a key already exists with the same address and return an error + // if found + address := sdk.AccAddress(privKey.PubKey().Address()) + if _, err := ks.KeyByAddress(address); err == nil { + return nil, fmt.Errorf("account with address %s already exists in keyring, delete the key first if you want to recreate it", address) + } + return ks.writeLocalKey(uid, privKey, algo.Name()) } diff --git a/crypto/keyring/keyring_ledger_test.go b/crypto/keyring/keyring_ledger_test.go index eb7e85f9e89c..5cdac5069fe8 100644 --- a/crypto/keyring/keyring_ledger_test.go +++ b/crypto/keyring/keyring_ledger_test.go @@ -80,7 +80,7 @@ func TestSignVerifyKeyRingWithLedger(t *testing.T) { require.True(t, i1.GetPubKey().VerifySignature(d1, s1)) require.True(t, bytes.Equal(s1, s2)) - localInfo, _, err := kb.NewMnemonic("test", English, types.FullFundraiserPath, hd.Secp256k1) + localInfo, _, err := kb.NewMnemonic("test", English, types.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) require.NoError(t, err) _, _, err = SignWithLedger(localInfo, d1) require.Error(t, err) diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index bcd7eddf39f9..c9f387e78e41 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -42,7 +42,7 @@ func TestNewKeyring(t *testing.T) { require.Equal(t, "unknown keyring backend fuzzy", err.Error()) mockIn.Reset("password\npassword\n") - info, _, err := kr.NewMnemonic("foo", English, sdk.FullFundraiserPath, hd.Secp256k1) + info, _, err := kr.NewMnemonic("foo", English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) require.NoError(t, err) require.Equal(t, "foo", info.GetName()) } @@ -59,17 +59,17 @@ func TestKeyManagementKeyRing(t *testing.T) { require.Nil(t, err) require.Empty(t, l) - _, _, err = kb.NewMnemonic(n1, English, sdk.FullFundraiserPath, notSupportedAlgo{}) + _, _, err = kb.NewMnemonic(n1, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, notSupportedAlgo{}) require.Error(t, err, "ed25519 keys are currently not supported by keybase") // create some keys _, err = kb.Key(n1) require.Error(t, err) - i, _, err := kb.NewMnemonic(n1, English, sdk.FullFundraiserPath, algo) + i, _, err := kb.NewMnemonic(n1, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, algo) require.NoError(t, err) require.Equal(t, n1, i.GetName()) - _, _, err = kb.NewMnemonic(n2, English, sdk.FullFundraiserPath, algo) + _, _, err = kb.NewMnemonic(n2, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, algo) require.NoError(t, err) // we can get these keys @@ -137,10 +137,10 @@ func TestSignVerifyKeyRing(t *testing.T) { n1, n2, n3 := "some dude", "a dudette", "dude-ish" // create two users and get their info - i1, _, err := kb.NewMnemonic(n1, English, sdk.FullFundraiserPath, algo) + i1, _, err := kb.NewMnemonic(n1, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, algo) require.Nil(t, err) - i2, _, err := kb.NewMnemonic(n2, English, sdk.FullFundraiserPath, algo) + i2, _, err := kb.NewMnemonic(n2, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, algo) require.Nil(t, err) // let's try to sign some messages @@ -209,7 +209,7 @@ func TestExportImportKeyRing(t *testing.T) { kb, err := New("keybasename", "test", t.TempDir(), nil) require.NoError(t, err) - info, _, err := kb.NewMnemonic("john", English, sdk.FullFundraiserPath, hd.Secp256k1) + info, _, err := kb.NewMnemonic("john", English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) require.NoError(t, err) require.Equal(t, info.GetName(), "john") @@ -243,7 +243,7 @@ func TestExportImportPubKeyKeyRing(t *testing.T) { algo := hd.Secp256k1 // CreateMnemonic a private-public key pair and ensure consistency - info, _, err := kb.NewMnemonic("john", English, sdk.FullFundraiserPath, algo) + info, _, err := kb.NewMnemonic("john", English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, algo) require.Nil(t, err) require.NotEqual(t, info, "") require.Equal(t, info.GetName(), "john") @@ -285,7 +285,7 @@ func TestAdvancedKeyManagementKeyRing(t *testing.T) { n1, n2 := "old-name", "new name" // make sure key works with initial password - _, _, err = kb.NewMnemonic(n1, English, sdk.FullFundraiserPath, algo) + _, _, err = kb.NewMnemonic(n1, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, algo) require.Nil(t, err, "%+v", err) _, err = kb.ExportPubKeyArmor(n1 + ".notreal") @@ -320,7 +320,7 @@ func TestSeedPhraseKeyRing(t *testing.T) { n1, n2 := "lost-key", "found-again" // make sure key works with initial password - info, mnemonic, err := kb.NewMnemonic(n1, English, sdk.FullFundraiserPath, algo) + info, mnemonic, err := kb.NewMnemonic(n1, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, algo) require.Nil(t, err, "%+v", err) require.Equal(t, n1, info.GetName()) require.NotEmpty(t, mnemonic) @@ -345,7 +345,7 @@ func TestKeyringKeybaseExportImportPrivKey(t *testing.T) { kb, err := New("keybasename", "test", t.TempDir(), nil) require.NoError(t, err) - _, _, err = kb.NewMnemonic("john", English, sdk.FullFundraiserPath, hd.Secp256k1) + _, _, err = kb.NewMnemonic("john", English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) require.NoError(t, err) keystr, err := kb.ExportPrivKeyArmor("john", "somepassword") @@ -372,7 +372,7 @@ func TestKeyringKeybaseExportImportPrivKey(t *testing.T) { func TestInMemoryLanguage(t *testing.T) { kb := NewInMemory() - _, _, err := kb.NewMnemonic("something", Japanese, sdk.FullFundraiserPath, hd.Secp256k1) + _, _, err := kb.NewMnemonic("something", Japanese, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) require.Error(t, err) require.Equal(t, "unsupported language: only english is supported", err.Error()) } @@ -412,17 +412,17 @@ func TestInMemoryKeyManagement(t *testing.T) { require.Nil(t, err) require.Empty(t, l) - _, _, err = cstore.NewMnemonic(n1, English, sdk.FullFundraiserPath, notSupportedAlgo{}) + _, _, err = cstore.NewMnemonic(n1, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, notSupportedAlgo{}) require.Error(t, err, "ed25519 keys are currently not supported by keybase") // create some keys _, err = cstore.Key(n1) require.Error(t, err) - i, _, err := cstore.NewMnemonic(n1, English, sdk.FullFundraiserPath, algo) + i, _, err := cstore.NewMnemonic(n1, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, algo) require.NoError(t, err) require.Equal(t, n1, i.GetName()) - _, _, err = cstore.NewMnemonic(n2, English, sdk.FullFundraiserPath, algo) + _, _, err = cstore.NewMnemonic(n2, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, algo) require.NoError(t, err) // we can get these keys @@ -492,10 +492,10 @@ func TestInMemorySignVerify(t *testing.T) { n1, n2, n3 := "some dude", "a dudette", "dude-ish" // create two users and get their info - i1, _, err := cstore.NewMnemonic(n1, English, sdk.FullFundraiserPath, algo) + i1, _, err := cstore.NewMnemonic(n1, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, algo) require.Nil(t, err) - i2, _, err := cstore.NewMnemonic(n2, English, sdk.FullFundraiserPath, algo) + i2, _, err := cstore.NewMnemonic(n2, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, algo) require.Nil(t, err) // let's try to sign some messages @@ -566,7 +566,7 @@ func TestInMemoryExportImport(t *testing.T) { // make the storage with reasonable defaults cstore := NewInMemory() - info, _, err := cstore.NewMnemonic("john", English, sdk.FullFundraiserPath, hd.Secp256k1) + info, _, err := cstore.NewMnemonic("john", English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) require.NoError(t, err) require.Equal(t, info.GetName(), "john") @@ -596,7 +596,7 @@ func TestInMemoryExportImport(t *testing.T) { func TestInMemoryExportImportPrivKey(t *testing.T) { kb := NewInMemory() - info, _, err := kb.NewMnemonic("john", English, sdk.FullFundraiserPath, hd.Secp256k1) + info, _, err := kb.NewMnemonic("john", English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) require.NoError(t, err) require.Equal(t, info.GetName(), "john") priv1, err := kb.Key("john") @@ -624,7 +624,7 @@ func TestInMemoryExportImportPubKey(t *testing.T) { cstore := NewInMemory() // CreateMnemonic a private-public key pair and ensure consistency - info, _, err := cstore.NewMnemonic("john", English, sdk.FullFundraiserPath, hd.Secp256k1) + info, _, err := cstore.NewMnemonic("john", English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) require.Nil(t, err) require.NotEqual(t, info, "") require.Equal(t, info.GetName(), "john") @@ -663,7 +663,7 @@ func TestInMemoryAdvancedKeyManagement(t *testing.T) { n1, n2 := "old-name", "new name" // make sure key works with initial password - _, _, err := cstore.NewMnemonic(n1, English, sdk.FullFundraiserPath, algo) + _, _, err := cstore.NewMnemonic(n1, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, algo) require.Nil(t, err, "%+v", err) // exporting requires the proper name and passphrase @@ -698,7 +698,7 @@ func TestInMemorySeedPhrase(t *testing.T) { n1, n2 := "lost-key", "found-again" // make sure key works with initial password - info, mnemonic, err := cstore.NewMnemonic(n1, English, sdk.FullFundraiserPath, algo) + info, mnemonic, err := cstore.NewMnemonic(n1, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, algo) require.Nil(t, err, "%+v", err) require.Equal(t, n1, info.GetName()) require.NotEmpty(t, mnemonic) @@ -724,7 +724,7 @@ func TestKeyChain_ShouldFailWhenAddingSameGeneratedAccount(t *testing.T) { require.NoError(t, err) // Given we create a mnemonic - _, seed, err := kr.NewMnemonic("test", English, "", hd.Secp256k1) + _, seed, err := kr.NewMnemonic("test", English, "", DefaultBIP39Passphrase, hd.Secp256k1) require.NoError(t, err) require.NoError(t, kr.Delete("test")) @@ -745,7 +745,7 @@ func ExampleNew() { sec := hd.Secp256k1 // Add keys and see they return in alphabetical order - bob, _, err := cstore.NewMnemonic("Bob", English, sdk.FullFundraiserPath, sec) + bob, _, err := cstore.NewMnemonic("Bob", English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, sec) if err != nil { // this should never happen fmt.Println(err) @@ -753,8 +753,8 @@ func ExampleNew() { // return info here just like in List fmt.Println(bob.GetName()) } - _, _, _ = cstore.NewMnemonic("Alice", English, sdk.FullFundraiserPath, sec) - _, _, _ = cstore.NewMnemonic("Carl", English, sdk.FullFundraiserPath, sec) + _, _, _ = cstore.NewMnemonic("Alice", English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, sec) + _, _, _ = cstore.NewMnemonic("Carl", English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, sec) info, _ := cstore.List() for _, i := range info { fmt.Println(i.GetName()) @@ -799,16 +799,16 @@ func TestAltKeyring_List(t *testing.T) { require.Empty(t, list) // Fails on creating unsupported pubKeyType - _, _, err = keyring.NewMnemonic("failing", English, sdk.FullFundraiserPath, notSupportedAlgo{}) + _, _, err = keyring.NewMnemonic("failing", English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, notSupportedAlgo{}) require.EqualError(t, err, ErrUnsupportedSigningAlgo.Error()) // Create 3 keys uid1, uid2, uid3 := "Zkey", "Bkey", "Rkey" - _, _, err = keyring.NewMnemonic(uid1, English, sdk.FullFundraiserPath, hd.Secp256k1) + _, _, err = keyring.NewMnemonic(uid1, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) require.NoError(t, err) - _, _, err = keyring.NewMnemonic(uid2, English, sdk.FullFundraiserPath, hd.Secp256k1) + _, _, err = keyring.NewMnemonic(uid2, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) require.NoError(t, err) - _, _, err = keyring.NewMnemonic(uid3, English, sdk.FullFundraiserPath, hd.Secp256k1) + _, _, err = keyring.NewMnemonic(uid3, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) require.NoError(t, err) list, err = keyring.List() @@ -852,7 +852,7 @@ func TestAltKeyring_Get(t *testing.T) { require.NoError(t, err) uid := someKey - mnemonic, _, err := keyring.NewMnemonic(uid, English, sdk.FullFundraiserPath, hd.Secp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) require.NoError(t, err) key, err := keyring.Key(uid) @@ -865,7 +865,7 @@ func TestAltKeyring_KeyByAddress(t *testing.T) { require.NoError(t, err) uid := someKey - mnemonic, _, err := keyring.NewMnemonic(uid, English, sdk.FullFundraiserPath, hd.Secp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) require.NoError(t, err) key, err := keyring.KeyByAddress(mnemonic.GetAddress()) @@ -878,7 +878,7 @@ func TestAltKeyring_Delete(t *testing.T) { require.NoError(t, err) uid := someKey - _, _, err = keyring.NewMnemonic(uid, English, sdk.FullFundraiserPath, hd.Secp256k1) + _, _, err = keyring.NewMnemonic(uid, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) require.NoError(t, err) list, err := keyring.List() @@ -898,7 +898,7 @@ func TestAltKeyring_DeleteByAddress(t *testing.T) { require.NoError(t, err) uid := someKey - mnemonic, _, err := keyring.NewMnemonic(uid, English, sdk.FullFundraiserPath, hd.Secp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) require.NoError(t, err) list, err := keyring.List() @@ -940,9 +940,9 @@ func TestAltKeyring_SaveMultisig(t *testing.T) { keyring, err := New(t.Name(), BackendTest, t.TempDir(), nil) require.NoError(t, err) - mnemonic1, _, err := keyring.NewMnemonic("key1", English, sdk.FullFundraiserPath, hd.Secp256k1) + mnemonic1, _, err := keyring.NewMnemonic("key1", English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) require.NoError(t, err) - mnemonic2, _, err := keyring.NewMnemonic("key2", English, sdk.FullFundraiserPath, hd.Secp256k1) + mnemonic2, _, err := keyring.NewMnemonic("key2", English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) require.NoError(t, err) key := "multi" @@ -969,7 +969,7 @@ func TestAltKeyring_Sign(t *testing.T) { require.NoError(t, err) uid := "jack" - _, _, err = keyring.NewMnemonic(uid, English, sdk.FullFundraiserPath, hd.Secp256k1) + _, _, err = keyring.NewMnemonic(uid, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) require.NoError(t, err) msg := []byte("some message") @@ -985,7 +985,7 @@ func TestAltKeyring_SignByAddress(t *testing.T) { require.NoError(t, err) uid := "jack" - mnemonic, _, err := keyring.NewMnemonic(uid, English, sdk.FullFundraiserPath, hd.Secp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) require.NoError(t, err) msg := []byte("some message") @@ -1001,7 +1001,7 @@ func TestAltKeyring_ImportExportPrivKey(t *testing.T) { require.NoError(t, err) uid := theID - _, _, err = keyring.NewMnemonic(uid, English, sdk.FullFundraiserPath, hd.Secp256k1) + _, _, err = keyring.NewMnemonic(uid, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) require.NoError(t, err) passphrase := "somePass" @@ -1027,7 +1027,7 @@ func TestAltKeyring_ImportExportPrivKey_ByAddress(t *testing.T) { require.NoError(t, err) uid := theID - mnemonic, _, err := keyring.NewMnemonic(uid, English, sdk.FullFundraiserPath, hd.Secp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) require.NoError(t, err) passphrase := "somePass" @@ -1054,7 +1054,7 @@ func TestAltKeyring_ImportExportPubKey(t *testing.T) { require.NoError(t, err) uid := theID - _, _, err = keyring.NewMnemonic(uid, English, sdk.FullFundraiserPath, hd.Secp256k1) + _, _, err = keyring.NewMnemonic(uid, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) require.NoError(t, err) armor, err := keyring.ExportPubKeyArmor(uid) @@ -1076,7 +1076,7 @@ func TestAltKeyring_ImportExportPubKey_ByAddress(t *testing.T) { require.NoError(t, err) uid := theID - mnemonic, _, err := keyring.NewMnemonic(uid, English, sdk.FullFundraiserPath, hd.Secp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) require.NoError(t, err) armor, err := keyring.ExportPubKeyArmorByAddress(mnemonic.GetAddress()) @@ -1099,7 +1099,7 @@ func TestAltKeyring_UnsafeExportPrivKeyHex(t *testing.T) { uid := theID - _, _, err = keyring.NewMnemonic(uid, English, sdk.FullFundraiserPath, hd.Secp256k1) + _, _, err = keyring.NewMnemonic(uid, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) require.NoError(t, err) unsafeKeyring := NewUnsafe(keyring) @@ -1121,11 +1121,11 @@ func TestAltKeyring_ConstructorSupportedAlgos(t *testing.T) { require.NoError(t, err) // should fail when using unsupported signing algorythm. - _, _, err = keyring.NewMnemonic("test", English, sdk.FullFundraiserPath, notSupportedAlgo{}) + _, _, err = keyring.NewMnemonic("test", English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, notSupportedAlgo{}) require.EqualError(t, err, "unsupported signing algo") // but works with default signing algo. - _, _, err = keyring.NewMnemonic("test", English, sdk.FullFundraiserPath, hd.Secp256k1) + _, _, err = keyring.NewMnemonic("test", English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) require.NoError(t, err) // but we can create a new keybase with our provided algos. @@ -1137,7 +1137,7 @@ func TestAltKeyring_ConstructorSupportedAlgos(t *testing.T) { require.NoError(t, err) // now this new keyring does not fail when signing with provided algo - _, _, err = keyring2.NewMnemonic("test", English, sdk.FullFundraiserPath, notSupportedAlgo{}) + _, _, err = keyring2.NewMnemonic("test", English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, notSupportedAlgo{}) require.NoError(t, err) } diff --git a/server/init.go b/server/init.go index f14e236cdf8b..389b231e9975 100644 --- a/server/init.go +++ b/server/init.go @@ -12,7 +12,7 @@ import ( // phrase to recover the private key. func GenerateCoinKey(algo keyring.SignatureAlgo) (sdk.AccAddress, string, error) { // generate a private key, with recovery phrase - info, secret, err := keyring.NewInMemory().NewMnemonic("name", keyring.English, sdk.FullFundraiserPath, algo) + info, secret, err := keyring.NewInMemory().NewMnemonic("name", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, algo) if err != nil { return sdk.AccAddress([]byte{}), "", err } @@ -43,7 +43,7 @@ func GenerateSaveCoinKey(keybase keyring.Keyring, keyName string, overwrite bool } } - info, secret, err := keybase.NewMnemonic(keyName, keyring.English, sdk.FullFundraiserPath, algo) + info, secret, err := keybase.NewMnemonic(keyName, keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, algo) if err != nil { return sdk.AccAddress([]byte{}), "", err } diff --git a/x/auth/client/cli/cli_test.go b/x/auth/client/cli/cli_test.go index 5e0a262e8ab5..178dcd01a823 100644 --- a/x/auth/client/cli/cli_test.go +++ b/x/auth/client/cli/cli_test.go @@ -52,13 +52,13 @@ func (s *IntegrationTestSuite) SetupSuite() { s.network = network.New(s.T(), cfg) kb := s.network.Validators[0].ClientCtx.Keyring - _, _, err := kb.NewMnemonic("newAccount", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1) + _, _, err := kb.NewMnemonic("newAccount", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) s.Require().NoError(err) - account1, _, err := kb.NewMnemonic("newAccount1", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1) + account1, _, err := kb.NewMnemonic("newAccount1", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) s.Require().NoError(err) - account2, _, err := kb.NewMnemonic("newAccount2", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1) + account2, _, err := kb.NewMnemonic("newAccount2", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) s.Require().NoError(err) multi := kmultisig.NewLegacyAminoPubKey(2, []cryptotypes.PubKey{account1.GetPubKey(), account2.GetPubKey()}) diff --git a/x/auth/client/rest/rest_test.go b/x/auth/client/rest/rest_test.go index b420c7a780c6..cfca5275087a 100644 --- a/x/auth/client/rest/rest_test.go +++ b/x/auth/client/rest/rest_test.go @@ -49,7 +49,7 @@ func (s *IntegrationTestSuite) SetupSuite() { s.network = network.New(s.T(), cfg) kb := s.network.Validators[0].ClientCtx.Keyring - _, _, err := kb.NewMnemonic("newAccount", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1) + _, _, err := kb.NewMnemonic("newAccount", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) s.Require().NoError(err) _, err = s.network.WaitForHeight(1) diff --git a/x/authz/client/cli/tx_test.go b/x/authz/client/cli/tx_test.go index 7964a93c1a28..0f604a12c76a 100644 --- a/x/authz/client/cli/tx_test.go +++ b/x/authz/client/cli/tx_test.go @@ -49,7 +49,7 @@ func (s *IntegrationTestSuite) SetupSuite() { val := s.network.Validators[0] // Create new account in the keyring. - info, _, err := val.ClientCtx.Keyring.NewMnemonic("grantee", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1) + info, _, err := val.ClientCtx.Keyring.NewMnemonic("grantee", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) s.Require().NoError(err) newAddr := sdk.AccAddress(info.GetPubKey().Address()) diff --git a/x/authz/client/rest/grpc_query_test.go b/x/authz/client/rest/grpc_query_test.go index e12336b49ed1..c5aae6b5f6c0 100644 --- a/x/authz/client/rest/grpc_query_test.go +++ b/x/authz/client/rest/grpc_query_test.go @@ -41,7 +41,7 @@ func (s *IntegrationTestSuite) SetupSuite() { val := s.network.Validators[0] // Create new account in the keyring. - info, _, err := val.ClientCtx.Keyring.NewMnemonic("grantee", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1) + info, _, err := val.ClientCtx.Keyring.NewMnemonic("grantee", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) s.Require().NoError(err) newAddr := sdk.AccAddress(info.GetPubKey().Address()) diff --git a/x/feegrant/client/cli/cli_test.go b/x/feegrant/client/cli/cli_test.go index df4ac286f7d4..66827e6148c4 100644 --- a/x/feegrant/client/cli/cli_test.go +++ b/x/feegrant/client/cli/cli_test.go @@ -573,7 +573,7 @@ func (s *IntegrationTestSuite) TestTxWithFeeGrant() { 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) + info, _, err := val.ClientCtx.Keyring.NewMnemonic("grantee", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) s.Require().NoError(err) grantee := sdk.AccAddress(info.GetPubKey().Address()) diff --git a/x/feegrant/client/rest/grpc_query_test.go b/x/feegrant/client/rest/grpc_query_test.go index 7b665ee9153b..5dac57a8fb84 100644 --- a/x/feegrant/client/rest/grpc_query_test.go +++ b/x/feegrant/client/rest/grpc_query_test.go @@ -36,7 +36,7 @@ func (s *IntegrationTestSuite) SetupSuite() { val := s.network.Validators[0] // Create new account in the keyring. - info, _, err := val.ClientCtx.Keyring.NewMnemonic("grantee", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1) + info, _, err := val.ClientCtx.Keyring.NewMnemonic("grantee", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) s.Require().NoError(err) newAddr := sdk.AccAddress(info.GetPubKey().Address()) diff --git a/x/staking/client/cli/cli_test.go b/x/staking/client/cli/cli_test.go index f1ef9edc6b8a..73f60e22c048 100644 --- a/x/staking/client/cli/cli_test.go +++ b/x/staking/client/cli/cli_test.go @@ -82,7 +82,7 @@ func (s *IntegrationTestSuite) TestNewCreateValidatorCmd() { consPubKey, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeConsPub, consPrivKey.PubKey()) s.Require().NoError(err) - info, _, err := val.ClientCtx.Keyring.NewMnemonic("NewValidator", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1) + info, _, err := val.ClientCtx.Keyring.NewMnemonic("NewValidator", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) s.Require().NoError(err) newAddr := sdk.AccAddress(info.GetPubKey().Address()) @@ -1037,7 +1037,7 @@ func (s *IntegrationTestSuite) TestNewCmdEditValidator() { func (s *IntegrationTestSuite) TestNewCmdDelegate() { val := s.network.Validators[0] - info, _, err := val.ClientCtx.Keyring.NewMnemonic("NewAccount", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1) + info, _, err := val.ClientCtx.Keyring.NewMnemonic("NewAccount", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) s.Require().NoError(err) newAddr := sdk.AccAddress(info.GetPubKey().Address()) @@ -1277,7 +1277,7 @@ func (s *IntegrationTestSuite) TestBlockResults() { val := s.network.Validators[0] // Create new account in the keyring. - info, _, err := val.ClientCtx.Keyring.NewMnemonic("NewDelegator", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1) + info, _, err := val.ClientCtx.Keyring.NewMnemonic("NewDelegator", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) require.NoError(err) newAddr := sdk.AccAddress(info.GetPubKey().Address()) From 09c4dc0074f60c8c7f57bcad52582f0f419f3220 Mon Sep 17 00:00:00 2001 From: Cory Date: Tue, 23 Feb 2021 23:22:19 -0800 Subject: [PATCH 107/214] add mergify config for automated launchpad backports (#8667) --- .mergify.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.mergify.yml b/.mergify.yml index ed1892e5cbae..129fb0090bb5 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -16,3 +16,11 @@ pull_request_rules: backport: branches: - release/v0.41.x + - name: backport patches to v0.39.x branch + conditions: + - base=master + - label=backport/0.39.x (Launchpad) + actions: + backport: + branches: + - launchpad/backports From 06ababdf3687aeb986e228d1ccb188d43efd8e7c Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Wed, 24 Feb 2021 12:45:21 +0100 Subject: [PATCH 108/214] ADR-033 cosmetic updates (#8676) * ADR-033 cosmetic updates * Apply suggestions from code review Co-authored-by: Aaron Craelius * remove invoker middleware framing * Update NewFooMsgServer * Update docs/architecture/adr-033-protobuf-inter-module-comm.md Co-authored-by: Aaron Craelius * Update docs/architecture/adr-033-protobuf-inter-module-comm.md Co-authored-by: Cory * Update docs/architecture/adr-033-protobuf-inter-module-comm.md Co-authored-by: Cory Co-authored-by: Aaron Craelius Co-authored-by: Cory Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- docs/architecture/README.md | 2 +- docs/architecture/adr-030-authz-module.md | 8 +- .../adr-033-protobuf-inter-module-comm.md | 92 ++++++++++++------- 3 files changed, 63 insertions(+), 39 deletions(-) diff --git a/docs/architecture/README.md b/docs/architecture/README.md index 2f362178a066..665c120c5e2e 100644 --- a/docs/architecture/README.md +++ b/docs/architecture/README.md @@ -72,7 +72,7 @@ Read about the [PROCESS](./PROCESS.md). - [ADR 027: Deterministic Protobuf Serialization](./adr-027-deterministic-protobuf-serialization.md) - [ADR 028: Public Key Addresses](./adr-028-public-key-addresses.md) - [ADR 032: Typed Events](./adr-032-typed-events.md) -- [ADR 033: Inter-module RPC](architecture/adr-033-protobuf-inter-module-comm.md) +- [ADR 033: Inter-module RPC](./adr-033-protobuf-inter-module-comm.md) - [ADR 035: Rosetta API Support](./adr-035-rosetta-api-support.md) - [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-030-authz-module.md b/docs/architecture/adr-030-authz-module.md index c61940fce8ea..2a30167b92d0 100644 --- a/docs/architecture/adr-030-authz-module.md +++ b/docs/architecture/adr-030-authz-module.md @@ -4,7 +4,7 @@ - 2019-11-06: Initial Draft - 2020-10-12: Updated Draft -- 2021-11-13: Accepted +- 2020-11-13: Accepted ## Status @@ -55,7 +55,7 @@ type Authorization interface { MethodName() string // Accept determines whether this grant permits the provided sdk.ServiceMsg to be performed, and if - // so provides an upgraded authorization instance. + // 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 @@ -146,7 +146,7 @@ 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. + // 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` } ``` @@ -216,7 +216,7 @@ message GenericAuthorization { - 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 +`Authorization` interface approach can be extended to cover other use cases by SDK users ### Negative diff --git a/docs/architecture/adr-033-protobuf-inter-module-comm.md b/docs/architecture/adr-033-protobuf-inter-module-comm.md index 8321afa6d63b..584ee2382d09 100644 --- a/docs/architecture/adr-033-protobuf-inter-module-comm.md +++ b/docs/architecture/adr-033-protobuf-inter-module-comm.md @@ -14,12 +14,12 @@ This ADR introduces a system for permissioned inter-module communication leverag service definitions defined in [ADR 021](./adr-021-protobuf-query-encoding.md) and [ADR 031](./adr-031-msg-service.md) which provides: - stable protobuf based module interfaces to potentially later replace the keeper paradigm -- stronger inter-module object capabilities guarantees +- stronger inter-module object capabilities (OCAPs) guarantees - module accounts and sub-account authorization ## Context -In the current Cosmos SDK documentation on the [Object-Capability Model](../docs/core/ocap.md), it is state that: +In the current Cosmos SDK documentation on the [Object-Capability Model](../docs/core/ocap.md), it is stated that: > We assume that a thriving ecosystem of Cosmos-SDK modules that are easy to compose into a blockchain application will contain faulty or malicious modules. @@ -34,7 +34,7 @@ of module keeper interfaces inevitable because the current interfaces are poorly Currently the `x/bank` keeper gives pretty much unrestricted access to any module which references it. For instance, the `SetBalance` method allows the caller to set the balance of any account to anything, bypassing even proper tracking of supply. -There appears to have been some later attempts to implement some semblance of Ocaps using module-level minting, staking +There appears to have been some later attempts to implement some semblance of OCAPs using module-level minting, staking and burning permissions. These permissions allow a module to mint, burn or delegate tokens with reference to the module’s own account. These permissions are actually stored as a `[]string` array on the `ModuleAccount` type in state. @@ -42,13 +42,13 @@ However, these permissions don’t really do much. They control what modules can `BurnCoins` and `DelegateCoins***` methods, but for one there is no unique object capability token that controls access — just a simple string. So the `x/upgrade` module could mint tokens for the `x/staking` module simple by calling `MintCoins(“staking”)`. Furthermore, all modules which have access to these keeper methods, also have access to -`SetBalance` negating any other attempt at Ocaps and breaking even basic object-oriented encapsulation. +`SetBalance` negating any other attempt at OCAPs and breaking even basic object-oriented encapsulation. ## Decision -Starting from the work in [ADR 021](./adr-021-protobuf-query-encoding.md) and [ADR 31](./adr-031-msg-service.md), we introduce -the following inter-module communication system as an new paradigm for secure module based authorization and OCAPS -framework. When implemented, this could also serve as an alternative the existing paradigm of passing keepers between +Based on [ADR-021](./adr-021-protobuf-query-encoding.md) and [ADR-031](./adr-031-msg-service.md), we introduce the +Inter-Module Communication framework for secure module authorization and OCAPs. +When implemented, this could also serve as an alternative to the existing paradigm of passing keepers between modules. The approach outlined here-in is intended to form the basis of a Cosmos SDK v1.0 that provides the necessary stability and encapsulation guarantees that allow a thriving module ecosystem to emerge. @@ -61,7 +61,7 @@ addressed as amendments to this ADR. In [ADR 021](./adr-021-protobuf-query-encoding.md), a mechanism for using protobuf service definitions to define queriers was introduced and in [ADR 31](./adr-031-msg-service.md), a mechanism for using protobuf service to define `Msg`s was added. Protobuf service definitions generate two golang interfaces representing the client and server sides of a service plus -some helper code. Here is a minimal example for the bank `Send` `Msg`. +some helper code. Here is a minimal example for the bank `cosmos.bank.Msg/Send` message type: ```go package bank @@ -83,45 +83,67 @@ and `MsgClient` interfaces and propose this mechanism as a replacement for the e this ADR does not necessitate the creation of new protobuf definitions or services. Rather, it leverages the same proto based service interfaces already used by clients for inter-module communication. -Using this `QueryClient`/`MsgClient` approach has the following key benefits over keepers: +Using this `QueryClient`/`MsgClient` approach has the following key benefits over exposing keepers to external modules: 1. Protobuf types are checked for breaking changes using [buf](https://buf.build/docs/breaking-overview) and because of the way protobuf is designed this will give us strong backwards compatibility guarantees while allowing for forward evolution. 2. The separation between the client and server interfaces will allow us to insert permission checking code in between the two which checks if one module is authorized to send the specified `Msg` to the other module providing a proper -object capability system. +object capability system (see below). 3. The router for inter-module communication gives us a convenient place to handle rollback of transactions, enabling atomicy of operations ([currently a problem](https://github.com/cosmos/cosmos-sdk/issues/8030)). Any failure within a module-to-module call would result in a failure of the entire transaction This mechanism has the added benefits of: - reducing boilerplate through code generation, and -- allowing for modules in other languages either via a VM like CosmWasm or sub-processes using gRPC +- allowing for modules in other languages either via a VM like CosmWasm or sub-processes using gRPC ### Inter-module Communication -To use the `Client` generated by the protobuf compiler we need a `grpc.ClientConn` implementation. For this we introduce +To use the `Client` generated by the protobuf compiler we need a `grpc.ClientConn` [interface](https://github.com/regen-network/protobuf/blob/cosmos/grpc/types.go#L12) +implementation. For this we introduce a new type, `ModuleKey`, which implements the `grpc.ClientConn` interface. `ModuleKey` can be thought of as the "private -key" corresponding to a module account, where authentication is provided through use of a special `Invoker()` function, +key" corresponding to a module account, where authentication is provided through use of a special `Invoker()` function, described in more detail below. -Whereas external clients use their account's private key to sign transactions containing `Msg`s where they are listed as signers, -modules use their `ModuleKey` to send `Msg`s where they are listed as the sole signer to other modules. For example, modules -could use their `ModuleKey` to "sign" a `/cosmos.bank.Msg/Send` transaction to send coins from the module's account to another -account. +Blockchain users (external clients) use their account's private key to sign transactions containing `Msg`s where they are listed as signers (each +message specifies required signers with `Msg.GetSigner`). The authentication checks is performed by `AnteHandler`. + +Here, we extend this process, by allowing modules to be identified in `Msg.GetSigners`. When a module wants to trigger the execution a `Msg` in another module, +its `ModuleKey` acts as the sender (through the `ClientConn` interface we describe below) and is set as a sole "signer". It's worth to note +that we don't use any cryptographic signature in this case. +For example, module `A` could use its `A.ModuleKey` to create `MsgSend` object for `/cosmos.bank.Msg/Send` transaction. `MsgSend` validation +will assure that the `from` account (`A.ModuleKey` in this case) is the signer. Here's an example of a hypothetical module `foo` interacting with `x/bank`: ```go package foo -func (fooMsgServer *MsgServer) Bar(ctx context.Context, req *MsgBarRequest) (*MsgBarResponse, error) { - bankQueryClient := bank.NewQueryClient(fooMsgServer.moduleKey) - balance, err := bankQueryClient.Balance(&bank.QueryBalanceRequest{Address: fooMsgServer.moduleKey.Address(), Denom: "foo"}) - + +type FooMsgServer { + // ... + + bankQuery bank.QueryClient + bankMsg bank.MsgClient +} + +func NewFooMsgServer(moduleKey RootModuleKey, ...) FooMsgServer { + // ... + + return FooMsgServer { + // ... + modouleKey: moduleKey, + bankQuery: bank.NewQueryClient(moduleKey), + bankMsg: bank.NewMsgClient(moduleKey), + } +} + +func (foo *FooMsgServer) Bar(ctx context.Context, req *MsgBarRequest) (*MsgBarResponse, error) { + balance, err := foo.bankQuery.Balance(&bank.QueryBalanceRequest{Address: fooMsgServer.moduleKey.Address(), Denom: "foo"}) + ... - bankMsgClient := bank.NewMsgClient(fooMsgServer.moduleKey) - res, err := bankMsgClient.Send(ctx, &bank.MsgSendRequest{FromAddress: fooMsgServer.moduleKey.Address(), ...}) + res, err := foo.bankMsg.Send(ctx, &bank.MsgSendRequest{FromAddress: fooMsgServer.moduleKey.Address(), ...}) ... } @@ -138,7 +160,7 @@ corresponding "public key". From the [ADR 028](./adr-028-public-key-addresses.md or derived accounts that can be used for different pools (ex. staking pools) or managed accounts (ex. group accounts). We can also think of module sub-accounts as similar to derived keys - there is a root key and then some derivation path. `ModuleID` is a simple struct which contains the module name and optional "derivation" path, -and forms its address based on the `AddressHash` method from [the ADR 028 draft](https://github.com/cosmos/cosmos-sdk/pull/7086): +and forms its address based on the `AddressHash` method from [the ADR-028](https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-028-public-key-addresses.md): ```go type ModuleID struct { @@ -151,8 +173,8 @@ func (key ModuleID) Address() []byte { } ``` -In addition to being able to generate a `ModuleID` and address, a `ModuleKey` contains a special function closure called -the `Invoker` which is the key to safe inter-module access. The `InvokeFn` closure corresponds to the `Invoke` method in +In addition to being able to generate a `ModuleID` and address, a `ModuleKey` contains a special function called +`Invoker` which is the key to safe inter-module access. The `Invoker` creates an `InvokeFn` closure which is used as an `Invoke` method in the `grpc.ClientConn` interface and under the hood is able to route messages to the appropriate `Msg` and `Query` handlers performing appropriate security checks on `Msg`s. This allows for even safer inter-module access than keeper's whose private member variables could be manipulated through reflection. Golang does not support reflection on a function @@ -162,7 +184,7 @@ the `ModuleKey` security. The two `ModuleKey` types are `RootModuleKey` and `DerivedModuleKey`: ```go -func Invoker(callInfo CallInfo) func(ctx context.Context, request, response interface{}, opts ...interface{}) error +type Invoker func(callInfo CallInfo) func(ctx context.Context, request, response interface{}, opts ...interface{}) error type CallInfo { Method string @@ -174,6 +196,8 @@ type RootModuleKey struct { invoker Invoker } +func (rm RootModuleKey) Derive(path []byte) DerivedModuleKey { /* ... */} + type DerivedModuleKey struct { moduleName string path []byte @@ -230,7 +254,7 @@ type Configurator interface { QueryServer() grpc.Server ModuleKey() ModuleKey - RequireServer(serverInterface interface{}) + RequireServer(msgServer interface{}) } ``` @@ -290,7 +314,7 @@ type Configurator interface { As an example, x/slashing's Slash must call x/staking's Slash, but we don't want to expose x/staking's Slash to end users and clients. -This wound also require creating a corresponding `internal.proto` file with a protobuf service in the given module's +Internal protobuf services will be defined in a corresponding `internal.proto` file in the given module's proto package. Services registered against `InternalServer` will be callable from other modules but not by external clients. @@ -302,7 +326,7 @@ ADR. ### Authorization By default, the inter-module router requires that messages are sent by the first signer returned by `GetSigners`. The -inter-module router should also accept authorization middleware such as that provided by [ADR 030](https://github.com/cosmos/cosmos-sdk/pull/7105). +inter-module router should also accept authorization middleware such as that provided by [ADR 030](https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-030-authz-module.md). This middleware will allow accounts to otherwise specific module accounts to perform actions on their behalf. Authorization middleware should take into account the need to grant certain modules effectively "admin" privileges to other modules. This will be addressed in separate ADRs or updates to this ADR. @@ -313,7 +337,7 @@ Other future improvements may include: * custom code generation that: * simplifies interfaces (ex. generates code with `sdk.Context` instead of `context.Context`) * optimizes inter-module calls - for instance caching resolved methods after first invocation -* combining `StoreKey`s and `ModuleKey`s into a single interface so that modules have a single Ocaps handle +* combining `StoreKey`s and `ModuleKey`s into a single interface so that modules have a single OCAPs handle * code generation which makes inter-module communication more performant * decoupling `ModuleKey` creation from `AppModuleBasic.Name()` so that app's can override root module account names * inter-module hooks and plugins @@ -323,7 +347,7 @@ Other future improvements may include: ### MsgServices vs `x/capability` The `x/capability` module does provide a proper object-capability implementation that can be used by any module in the -SDK and could even be used for inter-module Ocaps as described in [\#5931](https://github.com/cosmos/cosmos-sdk/issues/5931). +SDK and could even be used for inter-module OCAPs as described in [\#5931](https://github.com/cosmos/cosmos-sdk/issues/5931). The advantages of the approach described in this ADR are mostly around how it integrates with other parts of the SDK, specifically: @@ -348,7 +372,7 @@ replacing `Keeper` interfaces altogether. ### Positive - an alternative to keepers which can more easily lead to stable inter-module interfaces -- proper inter-module Ocaps +- proper inter-module OCAPs - improved module developer DevX, as commented on by several particpants on [Architecture Review Call, Dec 3](https://hackmd.io/E0wxxOvRQ5qVmTf6N_k84Q) - lays the groundwork for what can be a greatly simplified `app.go` @@ -368,4 +392,4 @@ replacing `Keeper` interfaces altogether. - [ADR 031](./adr-031-msg-service.md) - [ADR 028](./adr-028-public-key-addresses.md) - [ADR 030 draft](https://github.com/cosmos/cosmos-sdk/pull/7105) -- [Object-Capability Model](../docs/core/ocap.md) \ No newline at end of file +- [Object-Capability Model](../docs/core/ocap.md) From 7969135abc464e3d23a809768ed62f617f20624f Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Wed, 24 Feb 2021 13:47:32 +0100 Subject: [PATCH 109/214] rework unsafe string -> bytes conversion #8674 (#8684) Changing the unsafe string -> bytes conversion to fix a security concern. Closes: #8670 Co-authored-by: Alessio Treglia --- types/address/hash.go | 11 +++++------ types/address/hash_test.go | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/types/address/hash.go b/types/address/hash.go index d6a249a8a287..ddfec81dff78 100644 --- a/types/address/hash.go +++ b/types/address/hash.go @@ -64,11 +64,10 @@ func Module(moduleName string, key []byte) []byte { 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 +// unsafeStrToByteArray uses unsafe to convert string into byte array. Returned bytes +// must not be altered after this function is called as it will cause a segmentation fault. func unsafeStrToByteArray(s string) []byte { - sh := *(*reflect.SliceHeader)(unsafe.Pointer(&s)) // nolint:govet - sh.Cap = sh.Len - bs := *(*[]byte)(unsafe.Pointer(&sh)) // nolint:govet - return bs + var buf = *(*[]byte)(unsafe.Pointer(&s)) + (*reflect.SliceHeader)(unsafe.Pointer(&buf)).Cap = len(s) + return buf } diff --git a/types/address/hash_test.go b/types/address/hash_test.go index be096c357fec..4cc6c6880621 100644 --- a/types/address/hash_test.go +++ b/types/address/hash_test.go @@ -2,7 +2,9 @@ package address import ( "crypto/sha256" + "runtime" "testing" + "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/suite" @@ -75,6 +77,23 @@ func (suite *AddressSuite) TestModule() { assert.NotEqual(addr2, addr3, "changing key must change address") } +func unsafeConvertABC() []byte { + return unsafeStrToByteArray("abc") +} + +func (suite *AddressSuite) TestUnsafeStrToBytes() { + // we convert in other function to trigger GC. We want to check that + // the underlying array in []bytes is accessible after GC will finish swapping. + for i := 0; i < 5; i++ { + b := unsafeConvertABC() + runtime.GC() + <-time.NewTimer(2 * time.Millisecond).C + b2 := append(b, 'd') + suite.Equal("abc", string(b)) + suite.Equal("abcd", string(b2)) + } +} + type addrMock struct { Addr []byte } From 2539acd6f730ffb685b5331a1ab1e188ccd523db Mon Sep 17 00:00:00 2001 From: Amaury <1293565+amaurym@users.noreply.github.com> Date: Wed, 24 Feb 2021 15:49:34 +0100 Subject: [PATCH 110/214] simapp InitChainer: use json instead of tmjson (#7523) * simapp InitChainer: use json instead of tmjson * First run for test * Revert export_test Co-authored-by: Alessio Treglia --- simapp/app.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/simapp/app.go b/simapp/app.go index 388c8c50eb8a..41376c8ee3a5 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -1,6 +1,7 @@ package simapp import ( + "encoding/json" "io" "net/http" "os" @@ -10,7 +11,6 @@ import ( "github.com/rakyll/statik/fs" "github.com/spf13/cast" abci "github.com/tendermint/tendermint/abci/types" - tmjson "github.com/tendermint/tendermint/libs/json" "github.com/tendermint/tendermint/libs/log" tmos "github.com/tendermint/tendermint/libs/os" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" @@ -484,7 +484,7 @@ func (app *SimApp) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.Re // InitChainer application update at chain initialization func (app *SimApp) InitChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain { var genesisState GenesisState - if err := tmjson.Unmarshal(req.AppStateBytes, &genesisState); err != nil { + if err := json.Unmarshal(req.AppStateBytes, &genesisState); err != nil { panic(err) } return app.mm.InitGenesis(ctx, app.appCodec, genesisState) From 897f20b1d15f8e3ed7a544c503060877876694f2 Mon Sep 17 00:00:00 2001 From: MD Aleem <72057206+aleem1314@users.noreply.github.com> Date: Wed, 24 Feb 2021 20:33:27 +0530 Subject: [PATCH 111/214] fix REST endpoints in migration docs (#8648) * fix endpoints * update docs * fix routes * update docs Co-authored-by: Anil Kumar Kammari --- docs/migrations/rest.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/migrations/rest.md b/docs/migrations/rest.md index b1675543eb05..b3ff87ba90ec 100644 --- a/docs/migrations/rest.md +++ b/docs/migrations/rest.md @@ -32,11 +32,11 @@ 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 _gRPC-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). -| Legacy REST Endpoint | Description | New gGPC-gateway REST Endpoint | +| Legacy REST Endpoint | Description | New gRPC-gateway REST Endpoint | | ------------------------------------------------------------------------------- | ------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | | `GET /txs/{hash}` | Query tx by hash | `GET /cosmos/tx/v1beta1/txs/{hash}` | | `GET /txs` | Query tx by events | `GET /cosmos/tx/v1beta1/txs` | @@ -44,7 +44,7 @@ Some modules expose legacy `POST` endpoints to generate unsigned transactions fo | `POST /txs/encode` | Encodes an Amino JSON tx to an Amino binary tx | N/A, use Protobuf directly | | `POST /txs/decode` | Decodes an Amino binary tx into an Amino JSON tx | N/A, use Protobuf directly | | `POST /bank/*` | Create unsigned `Msg`s for bank tx | N/A, use Protobuf directly | -| `GET /bank/balances/{address}` | Get the balance of an address | `GET /cosmos/bank/v1beta1/balances/{address}/{denom}` | +| `GET /bank/balances/{address}` | Get the balance of an address | `GET /cosmos/bank/v1beta1/balances/{address}` | | `GET /bank/total` | Get the total supply of all coins | `GET /cosmos/bank/v1beta1/supply` | | `GET /bank/total/{denom}` | Get the total supply of one coin | `GET /cosmos/bank/v1beta1/supply/{denom}` | | `POST /distribution/delegators/{delegatorAddr}/rewards` | Withdraw all delegator rewards | N/A, use Protobuf directly | @@ -52,8 +52,8 @@ Some modules expose legacy `POST` endpoints to generate unsigned transactions fo | `GET /distribution/delegators/{delegatorAddr}/rewards` | Get the total rewards balance from all delegations | `GET /cosmos/distribution/v1beta1/v1beta1/delegators/{delegator_address}/rewards` | | `GET /distribution/delegators/{delegatorAddr}/rewards/{validatorAddr}` | Query a delegation reward | `GET /cosmos/distribution/v1beta1/delegators/{delegatorAddr}/rewards/{validatorAddr}` | | `GET /distribution/delegators/{delegatorAddr}/withdraw_address` | Get the rewards withdrawal address | `GET /cosmos/distribution/v1beta1/delegators/{delegatorAddr}/withdraw_address` | -| `GET /distribution/validators/{validatorAddr}` | Validator distribution information | `GET /cosmos/distribution/v1beta1/validators/{validatorAddr}` | -| `GET /distribution/validators/{validatorAddr}/rewards` | Commission and self-delegation rewards of a single a validator | `GET /cosmos/distribution/v1beta1/validators/{validatorAddr}/rewards` | +| `GET /distribution/validators/{validatorAddr}` | Validator distribution information | N/A | +| `GET /distribution/validators/{validatorAddr}/rewards` | Commission and outstanding rewards of a single a validator | `GET /cosmos/distribution/v1beta1/validators/{validatorAddr}/commission`
`GET /cosmos/distribution/v1beta1/validators/{validatorAddr}/outstanding_rewards` | | `GET /distribution/validators/{validatorAddr}/outstanding_rewards` | Outstanding rewards of a single validator | `GET /cosmos/distribution/v1beta1/validators/{validatorAddr}/outstanding_rewards` | | `GET /distribution/parameters` | Get the current distribution parameter values | `GET /cosmos/distribution/v1beta1/params` | | `GET /distribution/community_pool` | Get the amount held in the community pool | `GET /cosmos/distribution/v1beta1/community_pool` | @@ -77,12 +77,12 @@ Some modules expose legacy `POST` endpoints to generate unsigned transactions fo | `GET /slashing/signing_infos` | Get all signing infos | `GET /cosmos/slashing/v1beta1/signing_infos` | | `GET /slashing/parameters` | Get slashing parameters | `GET /cosmos/slashing/v1beta1/params` | | `POST /staking/*` | Create unsigned `Msg`s for staking | N/A, use Protobuf directly | -| `GET /staking/delegators/{delegatorAddr}/delegations` | Get all delegations from a delegator | `GET /cosmos/staking/v1beta1/delegators/{delegatorAddr}/delegations` | +| `GET /staking/delegators/{delegatorAddr}/delegations` | Get all delegations from a delegator | `GET /cosmos/staking/v1beta1/delegations/{delegatorAddr}` | | `GET /staking/delegators/{delegatorAddr}/unbonding_delegations` | Get all unbonding delegations from a delegator | `GET /cosmos/staking/v1beta1/delegators/{delegatorAddr}/unbonding_delegations` | | `GET /staking/delegators/{delegatorAddr}/txs` | Get all staking txs (i.e msgs) from a delegator | Removed | | `GET /staking/delegators/{delegatorAddr}/validators` | Query all validators that a delegator is bonded to | `GET /cosmos/staking/v1beta1/delegators/{delegatorAddr}/validators` | | `GET /staking/delegators/{delegatorAddr}/validators/{validatorAddr}` | Query a validator that a delegator is bonded to | `GET /cosmos/staking/v1beta1/delegators/{delegatorAddr}/validators/{validatorAddr}` | -| `GET /staking/delegators/{delegatorAddr}/delegations/{validatorAddr}` | Query a delegation between a delegator and a validator | `GET /cosmos/staking/v1beta1/delegators/{delegatorAddr}/delegations/{validatorAddr}` | +| `GET /staking/delegators/{delegatorAddr}/delegations/{validatorAddr}` | Query a delegation between a delegator and a validator | `GET /cosmos/staking/v1beta1/validators/{validatorAddr}/delegations/{delegatorAddr}` | | `GET /staking/delegators/{delegatorAddr}/unbonding_delegations/{validatorAddr}` | Query all unbonding delegations between a delegator and a validator | `GET /cosmos/staking/v1beta1/delegators/{delegatorAddr}/unbonding_delegations/{validatorAddr}` | | `GET /staking/redelegations` | Query redelegations | `GET /cosmos/staking/v1beta1/v1beta1/delegators/{delegator_addr}/redelegations` | | `GET /staking/validators` | Get all validators | `GET /cosmos/staking/v1beta1/validators` | From 2c18d8a28b12015c2ba0d56b5d75b49601390c32 Mon Sep 17 00:00:00 2001 From: Marko Date: Wed, 24 Feb 2021 19:43:12 +0000 Subject: [PATCH 112/214] add tm version to makefile (#8689) --- Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f49f95e73449..87c842b710a6 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,7 @@ PACKAGES_NOSIMULATION=$(shell go list ./... | grep -v '/simulation') PACKAGES_SIMTEST=$(shell go list ./... | grep '/simulation') VERSION := $(shell echo $(shell git describe --always) | sed 's/^v//') +TMVERSION := $(shell go list -m github.com/tendermint/tendermint | sed 's:.* ::') COMMIT := $(shell git log -1 --format='%H') LEDGER_ENABLED ?= true BINDIR ?= $(GOPATH)/bin @@ -58,7 +59,8 @@ ldflags = -X github.com/cosmos/cosmos-sdk/version.Name=sim \ -X github.com/cosmos/cosmos-sdk/version.AppName=simd \ -X github.com/cosmos/cosmos-sdk/version.Version=$(VERSION) \ -X github.com/cosmos/cosmos-sdk/version.Commit=$(COMMIT) \ - -X "github.com/cosmos/cosmos-sdk/version.BuildTags=$(build_tags_comma_sep)" + -X "github.com/cosmos/cosmos-sdk/version.BuildTags=$(build_tags_comma_sep)" \ + -X github.com/tendermint/tendermint/version.TMCoreSemVer=$(TMVERSION) # DB backend selection ifeq (cleveldb,$(findstring cleveldb,$(COSMOS_BUILD_OPTIONS))) From 77668a3c23cfb28b9866c65616202f302dc92152 Mon Sep 17 00:00:00 2001 From: SaReN Date: Thu, 25 Feb 2021 01:26:10 +0530 Subject: [PATCH 113/214] Add multisign batch command (#7787) * initial commit * update signing data * Update signature * code cleanup * code cleanup * Add test for ms batch * update test * add build flag * update flags * update tests * add test for signbatch multisig * update test * fix sign batch multisig * add test * update offline usage * update with sign batch fix * fix lint * update tests * update test * update tests * fix signature only * update seq * fix conflicts * update multisign * revert unintended * fix tests * rename flags * code refactor * fix typo * update docs * update test * Update x/auth/client/cli/tx_multisign.go * use named return values and explicit return * Update x/auth/client/cli/tx_multisign.go Co-authored-by: Robert Zaremba * Update x/auth/client/cli/tx_multisign.go Co-authored-by: Robert Zaremba Co-authored-by: Alessio Treglia Co-authored-by: Jonathan Gimeno Co-authored-by: Jonathan Gimeno Co-authored-by: Robert Zaremba Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- simapp/simd/cmd/root.go | 1 + x/auth/client/cli/cli_test.go | 77 +++++++++++ x/auth/client/cli/tx_multisign.go | 221 ++++++++++++++++++++++++++++-- x/auth/client/cli/tx_sign.go | 15 +- x/auth/client/testutil/helpers.go | 14 ++ 5 files changed, 307 insertions(+), 21 deletions(-) diff --git a/simapp/simd/cmd/root.go b/simapp/simd/cmd/root.go index f76948d59cd5..836036bcf08c 100644 --- a/simapp/simd/cmd/root.go +++ b/simapp/simd/cmd/root.go @@ -136,6 +136,7 @@ func txCommand() *cobra.Command { authcmd.GetSignCommand(), authcmd.GetSignBatchCommand(), authcmd.GetMultiSignCommand(), + authcmd.GetMultiSignBatchCmd(), authcmd.GetValidateSignaturesCommand(), flags.LineBreak, authcmd.GetBroadcastCommand(), diff --git a/x/auth/client/cli/cli_test.go b/x/auth/client/cli/cli_test.go index 178dcd01a823..6cd102cade97 100644 --- a/x/auth/client/cli/cli_test.go +++ b/x/auth/client/cli/cli_test.go @@ -812,6 +812,83 @@ func (s *IntegrationTestSuite) TestSignBatchMultisig() { s.Require().NoError(err) } +func (s *IntegrationTestSuite) TestMultisignBatch() { + val := s.network.Validators[0] + + // Fetch 2 accounts and a multisig. + account1, err := val.ClientCtx.Keyring.Key("newAccount1") + s.Require().NoError(err) + account2, err := val.ClientCtx.Keyring.Key("newAccount2") + s.Require().NoError(err) + multisigInfo, err := val.ClientCtx.Keyring.Key("multi") + + // Send coins from validator to multisig. + sendTokens := sdk.NewInt64Coin(s.cfg.BondDenom, 1000) + _, err = bankcli.MsgSendExec( + val.ClientCtx, + val.Address, + multisigInfo.GetAddress(), + 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) + s.Require().NoError(s.network.WaitForNextBlock()) + + generatedStd, err := bankcli.MsgSendExec( + val.ClientCtx, + multisigInfo.GetAddress(), + val.Address, + sdk.NewCoins( + sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(1)), + ), + 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) + + // Write the output to disk + filename := testutil.WriteToNewTempFile(s.T(), strings.Repeat(generatedStd.String(), 3)) + val.ClientCtx.HomeDir = strings.Replace(val.ClientCtx.HomeDir, "simd", "simcli", 1) + + queryResJSON, err := authtest.QueryAccountExec(val.ClientCtx, multisigInfo.GetAddress()) + s.Require().NoError(err) + var account authtypes.AccountI + s.Require().NoError(val.ClientCtx.JSONMarshaler.UnmarshalInterfaceJSON(queryResJSON.Bytes(), &account)) + + // sign-batch file + res, err := authtest.TxSignBatchExec(val.ClientCtx, account1.GetAddress(), filename.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID), "--multisig", multisigInfo.GetAddress().String(), fmt.Sprintf("--%s", flags.FlagOffline), fmt.Sprintf("--%s=%s", flags.FlagAccountNumber, fmt.Sprint(account.GetAccountNumber())), fmt.Sprintf("--%s=%s", flags.FlagSequence, fmt.Sprint(account.GetSequence()))) + s.Require().NoError(err) + s.Require().Equal(3, len(strings.Split(strings.Trim(res.String(), "\n"), "\n"))) + // write sigs to file + file1 := testutil.WriteToNewTempFile(s.T(), res.String()) + + // sign-batch file with account2 + res, err = authtest.TxSignBatchExec(val.ClientCtx, account2.GetAddress(), filename.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID), "--multisig", multisigInfo.GetAddress().String(), fmt.Sprintf("--%s", flags.FlagOffline), fmt.Sprintf("--%s=%s", flags.FlagAccountNumber, fmt.Sprint(account.GetAccountNumber())), fmt.Sprintf("--%s=%s", flags.FlagSequence, fmt.Sprint(account.GetSequence()))) + s.Require().NoError(err) + s.Require().Equal(3, len(strings.Split(strings.Trim(res.String(), "\n"), "\n"))) + + // multisign the file + file2 := testutil.WriteToNewTempFile(s.T(), res.String()) + res, err = authtest.TxMultiSignBatchExec(val.ClientCtx, filename.Name(), multisigInfo.GetName(), file1.Name(), file2.Name()) + s.Require().NoError(err) + signedTxs := strings.Split(strings.Trim(res.String(), "\n"), "\n") + + // Broadcast transactions. + for _, signedTx := range signedTxs { + signedTxFile := testutil.WriteToNewTempFile(s.T(), signedTx) + val.ClientCtx.BroadcastMode = flags.BroadcastBlock + res, err = authtest.TxBroadcastExec(val.ClientCtx, signedTxFile.Name()) + s.T().Log(res) + s.Require().NoError(err) + s.Require().NoError(s.network.WaitForNextBlock()) + } +} + func (s *IntegrationTestSuite) TestGetAccountCmd() { val := s.network.Validators[0] _, _, addr1 := testdata.KeyTestPubAddr() diff --git a/x/auth/client/cli/tx_multisign.go b/x/auth/client/cli/tx_multisign.go index ebffeaf0b3a4..61ec84bdc219 100644 --- a/x/auth/client/cli/tx_multisign.go +++ b/x/auth/client/cli/tx_multisign.go @@ -1,13 +1,13 @@ package cli import ( - "bufio" "fmt" "io/ioutil" "os" "strings" "github.com/spf13/cobra" + "github.com/spf13/viper" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" @@ -16,6 +16,7 @@ import ( kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig" "github.com/cosmos/cosmos-sdk/crypto/types/multisig" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/errors" signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing" "github.com/cosmos/cosmos-sdk/version" authclient "github.com/cosmos/cosmos-sdk/x/auth/client" @@ -35,7 +36,7 @@ Read signature(s) from [signature] file(s), generate a multisig signature compli multisig key [name], and attach it to the transaction read from [file]. Example: -$ %s multisign transaction.json k1k2k3 k1sig.json k2sig.json k3sig.json +$ %s tx multisign transaction.json k1k2k3 k1sig.json k2sig.json k3sig.json If the flag --signature-only flag is on, it outputs a JSON representation of the generated signature only. @@ -43,6 +44,9 @@ of the generated signature only. The --offline flag makes sure that the client will not reach out to an external node. Thus account number or sequence number lookups will not be performed and it is recommended to set such parameters manually. + +The current multisig implementation doesn't support SIGN_MORE_DIRECT and defaults +to amino-json sign mode.' `, version.AppName, ), @@ -82,20 +86,9 @@ func makeMultiSignCmd() func(cmd *cobra.Command, args []string) (err error) { return err } - backend, _ := cmd.Flags().GetString(flags.FlagKeyringBackend) - - inBuf := bufio.NewReader(cmd.InOrStdin()) - kb, err := keyring.New(sdk.KeyringServiceName(), backend, clientCtx.HomeDir, inBuf) - if err != nil { - return - } - - multisigInfo, err := kb.Key(args[1]) + multisigInfo, err := getMultisigInfo(clientCtx, args[1]) if err != nil { - return - } - if multisigInfo.GetType() != keyring.TypeMulti { - return fmt.Errorf("%q must be of type %s: %s", args[1], keyring.TypeMulti, multisigInfo.GetType()) + return err } multisigPub := multisigInfo.GetPubKey().(*kmultisig.LegacyAminoPubKey) @@ -196,6 +189,171 @@ func makeMultiSignCmd() func(cmd *cobra.Command, args []string) (err error) { } } +func GetMultiSignBatchCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "multisign-batch [file] [name] [[signature-file]...]", + Short: "Assemble multisig transactions in batch from batch signatures", + Long: strings.TrimSpace( + fmt.Sprintf(`Assemble a batch of multisig transactions generated by batch sign command. + +Read signature(s) from [signature] file(s), generates multisig signatures compliant to the +multisig key [name], and attach it to the transactions read from [file]. + +Example: +$ %s tx multisign-batch transactions.json multisigk1k2k3 k1sigs.json k2sigs.json k3sig.json + +The current multisig implementation doesn't support sign_mode_direct and defaults +to amino-json sign mode.' +`, version.AppName, + ), + ), + PreRun: preSignCmd, + RunE: makeBatchMultisignCmd(), + Args: cobra.MinimumNArgs(3), + } + + cmd.Flags().Bool(flagNoAutoIncrement, false, "disable sequence auto increment") + cmd.Flags().String( + flagMultisig, "", + "Address of the multisig account on behalf of which the transaction shall be signed", + ) + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +func makeBatchMultisignCmd() func(cmd *cobra.Command, args []string) error { + return func(cmd *cobra.Command, args []string) (err error) { + var clientCtx client.Context + + clientCtx, err = client.GetClientTxContext(cmd) + if err != nil { + return err + } + + txCfg := clientCtx.TxConfig + txFactory := tx.NewFactoryCLI(clientCtx, cmd.Flags()) + if txFactory.SignMode() == signingtypes.SignMode_SIGN_MODE_UNSPECIFIED { + txFactory = txFactory.WithSignMode(signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON) + } + + var infile = os.Stdin + if args[0] != "-" { + infile, err = os.Open(args[0]) + defer func() { + err2 := infile.Close() + if err == nil { + err = err2 + } + }() + + if err != nil { + return fmt.Errorf("couldn't open %s: %w", args[0], err) + } + } + scanner := authclient.NewBatchScanner(txCfg, infile) + + multisigInfo, err := getMultisigInfo(clientCtx, args[1]) + if err != nil { + return err + } + + var signatureBatch [][]signingtypes.SignatureV2 + for i := 2; i < len(args); i++ { + sigs, err := readSignaturesFromFile(clientCtx, args[i]) + if err != nil { + return err + } + + signatureBatch = append(signatureBatch, sigs) + } + + if !clientCtx.Offline { + accnum, seq, err := clientCtx.AccountRetriever.GetAccountNumberSequence(clientCtx, multisigInfo.GetAddress()) + if err != nil { + return err + } + + txFactory = txFactory.WithAccountNumber(accnum).WithSequence(seq) + } + + for i := 0; scanner.Scan(); i++ { + txBldr, err := txCfg.WrapTxBuilder(scanner.Tx()) + if err != nil { + return err + } + + multisigPub := multisigInfo.GetPubKey().(*kmultisig.LegacyAminoPubKey) + multisigSig := multisig.NewMultisig(len(multisigPub.PubKeys)) + signingData := signing.SignerData{ + ChainID: txFactory.ChainID(), + AccountNumber: txFactory.AccountNumber(), + Sequence: txFactory.Sequence(), + } + + for _, sig := range signatureBatch { + err = signing.VerifySignature(sig[i].PubKey, signingData, sig[i].Data, txCfg.SignModeHandler(), txBldr.GetTx()) + if err != nil { + return fmt.Errorf("couldn't verify signature: %w %v", err, sig) + } + + if err := multisig.AddSignatureV2(multisigSig, sig[i], multisigPub.GetPubKeys()); err != nil { + return err + } + } + + sigV2 := signingtypes.SignatureV2{ + PubKey: multisigPub, + Data: multisigSig, + Sequence: txFactory.Sequence(), + } + + err = txBldr.SetSignatures(sigV2) + if err != nil { + return err + } + + sigOnly, _ := cmd.Flags().GetBool(flagSigOnly) + aminoJSON, _ := cmd.Flags().GetBool(flagAmino) + + var json []byte + + if aminoJSON { + stdTx, err := tx.ConvertTxToStdTx(clientCtx.LegacyAmino, txBldr.GetTx()) + if err != nil { + return err + } + + req := rest.BroadcastReq{ + Tx: stdTx, + Mode: "block|sync|async", + } + + json, _ = clientCtx.LegacyAmino.MarshalJSON(req) + + } else { + json, err = marshalSignatureJSON(txCfg, txBldr, sigOnly) + if err != nil { + return err + } + } + + err = clientCtx.PrintString(fmt.Sprintf("%s\n", json)) + if err != nil { + return err + } + + if viper.GetBool(flagNoAutoIncrement) { + continue + } + sequence := txFactory.Sequence() + 1 + txFactory = txFactory.WithSequence(sequence) + } + + return nil + } +} + func unmarshalSignatureJSON(clientCtx client.Context, filename string) (sigs []signingtypes.SignatureV2, err error) { var bytes []byte if bytes, err = ioutil.ReadFile(filename); err != nil { @@ -203,3 +361,36 @@ func unmarshalSignatureJSON(clientCtx client.Context, filename string) (sigs []s } return clientCtx.TxConfig.UnmarshalSignatureJSON(bytes) } + +func readSignaturesFromFile(ctx client.Context, filename string) (sigs []signingtypes.SignatureV2, err error) { + bz, err := ioutil.ReadFile(filename) + if err != nil { + return nil, err + } + + newString := strings.TrimSuffix(string(bz), "\n") + lines := strings.Split(newString, "\n") + + for _, bz := range lines { + sig, err := ctx.TxConfig.UnmarshalSignatureJSON([]byte(bz)) + if err != nil { + return nil, err + } + + sigs = append(sigs, sig...) + } + return sigs, nil +} + +func getMultisigInfo(clientCtx client.Context, name string) (keyring.Info, error) { + kb := clientCtx.Keyring + multisigInfo, err := kb.Key(name) + if err != nil { + return nil, errors.Wrap(err, "error getting keybase multisig account") + } + if multisigInfo.GetType() != keyring.TypeMulti { + return nil, fmt.Errorf("%q must be of type %s: %s", name, keyring.TypeMulti, multisigInfo.GetType()) + } + + return multisigInfo, nil +} diff --git a/x/auth/client/cli/tx_sign.go b/x/auth/client/cli/tx_sign.go index 251282bb8e0c..955554512125 100644 --- a/x/auth/client/cli/tx_sign.go +++ b/x/auth/client/cli/tx_sign.go @@ -16,10 +16,11 @@ import ( ) const ( - flagMultisig = "multisig" - flagOverwrite = "overwrite" - flagSigOnly = "signature-only" - flagAmino = "amino" + flagMultisig = "multisig" + flagOverwrite = "overwrite" + flagSigOnly = "signature-only" + flagAmino = "amino" + flagNoAutoIncrement = "no-auto-increment" ) // GetSignBatchCommand returns the transaction sign-batch command. @@ -203,8 +204,10 @@ func preSignCmd(cmd *cobra.Command, _ []string) { } func makeSignCmd() func(cmd *cobra.Command, args []string) error { - return func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientTxContext(cmd) + return func(cmd *cobra.Command, args []string) (err error) { + var clientCtx client.Context + + clientCtx, err = client.GetClientTxContext(cmd) if err != nil { return err } diff --git a/x/auth/client/testutil/helpers.go b/x/auth/client/testutil/helpers.go index e4f31727768e..6d68ef9236f2 100644 --- a/x/auth/client/testutil/helpers.go +++ b/x/auth/client/testutil/helpers.go @@ -92,4 +92,18 @@ func QueryAccountExec(clientCtx client.Context, address fmt.Stringer, extraArgs return clitestutil.ExecTestCLICmd(clientCtx, cli.GetAccountCmd(), append(args, extraArgs...)) } +func TxMultiSignBatchExec(clientCtx client.Context, filename string, from string, sigFile1 string, sigFile2 string, extraArgs ...string) (testutil.BufferWriter, error) { + args := []string{ + fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, keyring.BackendTest), + filename, + from, + sigFile1, + sigFile2, + } + + args = append(args, extraArgs...) + + return clitestutil.ExecTestCLICmd(clientCtx, cli.GetMultiSignBatchCmd(), args) +} + // DONTCOVER From 149bed48fd3f6937020a5e2519d52a79fff56f3e Mon Sep 17 00:00:00 2001 From: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Date: Wed, 24 Feb 2021 20:06:04 -0300 Subject: [PATCH 114/214] bank: name and symbol metadata fields (#8677) * bank: name and symbol metadata fields * cli test * changelog --- CHANGELOG.md | 1 + docs/core/proto-docs.md | 2 + proto/cosmos/bank/v1beta1/bank.proto | 5 + x/bank/client/cli/cli_test.go | 10 ++ x/bank/client/rest/grpc_query_test.go | 4 + x/bank/client/rest/query_test.go | 2 + x/bank/keeper/keeper_test.go | 4 + x/bank/types/bank.pb.go | 180 ++++++++++++++++++++------ x/bank/types/genesis_test.go | 8 ++ x/bank/types/metadata.go | 9 ++ x/bank/types/metadata_test.go | 56 +++++++- 11 files changed, 243 insertions(+), 38 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 21c7a9ac67c4..a5cc29513f54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -61,6 +61,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements +* (x/bank) [\#8614](https://github.com/cosmos/cosmos-sdk/issues/8614) Add `Name` and `Symbol` fields to denom metadata * (x/auth) [\#8522](https://github.com/cosmos/cosmos-sdk/pull/8522) Allow to query all stored accounts * (crypto/types) [\#8600](https://github.com/cosmos/cosmos-sdk/pull/8600) `CompactBitArray`: optimize the `NumTrueBitsBefore` method and add an `Equal` method. diff --git a/docs/core/proto-docs.md b/docs/core/proto-docs.md index 6cd751f026bb..10e309d9e24a 100644 --- a/docs/core/proto-docs.md +++ b/docs/core/proto-docs.md @@ -1711,6 +1711,8 @@ a basic token. | `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. | +| `name` | [string](#string) | | name defines the name of the token (eg: Cosmos Atom) | +| `symbol` | [string](#string) | | symbol is the token symbol usually shown on exchanges (eg: ATOM). This can be the same as the display. | diff --git a/proto/cosmos/bank/v1beta1/bank.proto b/proto/cosmos/bank/v1beta1/bank.proto index 5a9383362e42..fb9069214415 100644 --- a/proto/cosmos/bank/v1beta1/bank.proto +++ b/proto/cosmos/bank/v1beta1/bank.proto @@ -82,4 +82,9 @@ message Metadata { // display indicates the suggested denom that should be // displayed in clients. string display = 4; + // name defines the name of the token (eg: Cosmos Atom) + string name = 5; + // symbol is the token symbol usually shown on exchanges (eg: ATOM). This can + // be the same as the display. + string symbol = 6; } diff --git a/x/bank/client/cli/cli_test.go b/x/bank/client/cli/cli_test.go index 98127101be7a..19325b430c17 100644 --- a/x/bank/client/cli/cli_test.go +++ b/x/bank/client/cli/cli_test.go @@ -40,6 +40,8 @@ func (s *IntegrationTestSuite) SetupSuite() { bankGenesis.DenomMetadata = []types.Metadata{ { + Name: "Cosmos Hub Atom", + Symbol: "ATOM", Description: "The native staking token of the Cosmos Hub.", DenomUnits: []*types.DenomUnit{ { @@ -57,6 +59,8 @@ func (s *IntegrationTestSuite) SetupSuite() { Display: "atom", }, { + Name: "Ethereum", + Symbol: "ETH", Description: "Ethereum mainnet token", DenomUnits: []*types.DenomUnit{ { @@ -246,6 +250,8 @@ func (s *IntegrationTestSuite) TestGetCmdQueryDenomsMetadata() { expected: &types.QueryDenomsMetadataResponse{ Metadatas: []types.Metadata{ { + Name: "Cosmos Hub Atom", + Symbol: "ATOM", Description: "The native staking token of the Cosmos Hub.", DenomUnits: []*types.DenomUnit{ { @@ -263,6 +269,8 @@ func (s *IntegrationTestSuite) TestGetCmdQueryDenomsMetadata() { Display: "atom", }, { + Name: "Ethereum", + Symbol: "ETH", Description: "Ethereum mainnet token", DenomUnits: []*types.DenomUnit{ { @@ -293,6 +301,8 @@ func (s *IntegrationTestSuite) TestGetCmdQueryDenomsMetadata() { respType: &types.QueryDenomMetadataResponse{}, expected: &types.QueryDenomMetadataResponse{ Metadata: types.Metadata{ + Name: "Cosmos Hub Atom", + Symbol: "ATOM", Description: "The native staking token of the Cosmos Hub.", DenomUnits: []*types.DenomUnit{ { diff --git a/x/bank/client/rest/grpc_query_test.go b/x/bank/client/rest/grpc_query_test.go index d6290a1fef94..438cca5294d8 100644 --- a/x/bank/client/rest/grpc_query_test.go +++ b/x/bank/client/rest/grpc_query_test.go @@ -121,6 +121,8 @@ func (s *IntegrationTestSuite) TestDenomMetadataGRPCHandler() { &types.QueryDenomsMetadataResponse{ Metadatas: []types.Metadata{ { + Name: "Cosmos Hub Atom", + Symbol: "ATOM", Description: "The native staking token of the Cosmos Hub.", DenomUnits: []*types.DenomUnit{ { @@ -151,6 +153,8 @@ func (s *IntegrationTestSuite) TestDenomMetadataGRPCHandler() { &types.QueryDenomMetadataResponse{}, &types.QueryDenomMetadataResponse{ Metadata: types.Metadata{ + Name: "Cosmos Hub Atom", + Symbol: "ATOM", Description: "The native staking token of the Cosmos Hub.", DenomUnits: []*types.DenomUnit{ { diff --git a/x/bank/client/rest/query_test.go b/x/bank/client/rest/query_test.go index 11d731b6dcba..0201e6763125 100644 --- a/x/bank/client/rest/query_test.go +++ b/x/bank/client/rest/query_test.go @@ -33,6 +33,8 @@ func (s *IntegrationTestSuite) SetupSuite() { bankGenesis.DenomMetadata = []types.Metadata{ { + Name: "Cosmos Hub Atom", + Symbol: "ATOM", Description: "The native staking token of the Cosmos Hub.", DenomUnits: []*types.DenomUnit{ { diff --git a/x/bank/keeper/keeper_test.go b/x/bank/keeper/keeper_test.go index 20ec854a81c2..97d0b3a8769b 100644 --- a/x/bank/keeper/keeper_test.go +++ b/x/bank/keeper/keeper_test.go @@ -1004,6 +1004,8 @@ func (suite *IntegrationTestSuite) TestIterateAllDenomMetaData() { func (suite *IntegrationTestSuite) getTestMetadata() []types.Metadata { return []types.Metadata{{ + Name: "Cosmos Hub Atom", + Symbol: "ATOM", Description: "The native staking token of the Cosmos Hub.", DenomUnits: []*types.DenomUnit{ {"uatom", uint32(0), []string{"microatom"}}, @@ -1014,6 +1016,8 @@ func (suite *IntegrationTestSuite) getTestMetadata() []types.Metadata { Display: "atom", }, { + Name: "Token", + Symbol: "TOKEN", Description: "The native staking token of the Token Hub.", DenomUnits: []*types.DenomUnit{ {"1token", uint32(5), []string{"decitoken"}}, diff --git a/x/bank/types/bank.pb.go b/x/bank/types/bank.pb.go index ef1c52c1ccb5..645e0aef5faf 100644 --- a/x/bank/types/bank.pb.go +++ b/x/bank/types/bank.pb.go @@ -327,6 +327,11 @@ type Metadata struct { // display indicates the suggested denom that should be // displayed in clients. Display string `protobuf:"bytes,4,opt,name=display,proto3" json:"display,omitempty"` + // name defines the name of the token (eg: Cosmos Atom) + Name string `protobuf:"bytes,5,opt,name=name,proto3" json:"name,omitempty"` + // symbol is the token symbol usually shown on exchanges (eg: ATOM). This can + // be the same as the display. + Symbol string `protobuf:"bytes,6,opt,name=symbol,proto3" json:"symbol,omitempty"` } func (m *Metadata) Reset() { *m = Metadata{} } @@ -390,6 +395,20 @@ func (m *Metadata) GetDisplay() string { return "" } +func (m *Metadata) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *Metadata) GetSymbol() string { + if m != nil { + return m.Symbol + } + return "" +} + func init() { proto.RegisterType((*Params)(nil), "cosmos.bank.v1beta1.Params") proto.RegisterType((*SendEnabled)(nil), "cosmos.bank.v1beta1.SendEnabled") @@ -403,43 +422,44 @@ func init() { func init() { proto.RegisterFile("cosmos/bank/v1beta1/bank.proto", fileDescriptor_dd052eee12edf988) } var fileDescriptor_dd052eee12edf988 = []byte{ - // 566 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x54, 0xbf, 0x6f, 0x13, 0x31, - 0x14, 0x3e, 0x37, 0x4d, 0x48, 0x1d, 0x58, 0x4c, 0x86, 0x6b, 0x24, 0xee, 0x8e, 0x93, 0x90, 0x52, - 0x44, 0x2f, 0x14, 0xc4, 0x92, 0x05, 0x29, 0xa5, 0x42, 0x1d, 0x10, 0xe8, 0x2a, 0x84, 0x04, 0x43, - 0xe4, 0xc4, 0x6e, 0xb0, 0x7a, 0x67, 0x9f, 0x62, 0x1f, 0x6a, 0xfe, 0x03, 0x26, 0x60, 0x44, 0x62, - 0xe9, 0xcc, 0x88, 0xf8, 0x23, 0x3a, 0x56, 0xb0, 0x30, 0x05, 0x94, 0x2c, 0xcc, 0xfd, 0x0b, 0x90, - 0xed, 0xcb, 0x8f, 0x4a, 0x01, 0x31, 0x30, 0x30, 0x9d, 0x9f, 0xdf, 0xf7, 0xbe, 0xf7, 0xe9, 0x7b, - 0xcf, 0x07, 0xbd, 0xbe, 0x90, 0xa9, 0x90, 0xad, 0x1e, 0xe6, 0x47, 0xad, 0x57, 0x3b, 0x3d, 0xaa, - 0xf0, 0x8e, 0x09, 0xa2, 0x6c, 0x28, 0x94, 0x40, 0x57, 0x6d, 0x3e, 0x32, 0x57, 0x45, 0xbe, 0x51, - 0x1f, 0x88, 0x81, 0x30, 0xf9, 0x96, 0x3e, 0x59, 0x68, 0x63, 0xd3, 0x42, 0xbb, 0x36, 0x51, 0xd4, - 0xd9, 0xd4, 0xa2, 0x8b, 0xa4, 0xf3, 0x2e, 0x7d, 0xc1, 0xb8, 0xcd, 0x87, 0x5f, 0x01, 0xac, 0x3c, - 0xc1, 0x43, 0x9c, 0x4a, 0x74, 0x08, 0x2f, 0x4b, 0xca, 0x49, 0x97, 0x72, 0xdc, 0x4b, 0x28, 0x71, - 0x41, 0x50, 0x6a, 0xd6, 0xee, 0x04, 0xd1, 0x0a, 0x1d, 0xd1, 0x01, 0xe5, 0x64, 0xcf, 0xe2, 0x3a, - 0xd7, 0xcf, 0xc7, 0xfe, 0xb5, 0x11, 0x4e, 0x93, 0x76, 0xb8, 0x5c, 0x7f, 0x4b, 0xa4, 0x4c, 0xd1, - 0x34, 0x53, 0xa3, 0x30, 0xae, 0xc9, 0x05, 0x1e, 0xbd, 0x80, 0x75, 0x42, 0x0f, 0x71, 0x9e, 0xa8, - 0xee, 0x85, 0x7e, 0x6b, 0x01, 0x68, 0x56, 0x3b, 0x5b, 0xe7, 0x63, 0xff, 0x86, 0x65, 0x5b, 0x85, - 0x5a, 0x66, 0x45, 0x05, 0x60, 0x49, 0x4c, 0x7b, 0xfd, 0xfd, 0x89, 0xef, 0x84, 0x0f, 0x61, 0x6d, - 0xe9, 0x12, 0xd5, 0x61, 0x99, 0x50, 0x2e, 0x52, 0x17, 0x04, 0xa0, 0xb9, 0x11, 0xdb, 0x00, 0xb9, - 0xf0, 0xd2, 0x85, 0xd6, 0xf1, 0x2c, 0x6c, 0x57, 0x35, 0xc9, 0xcf, 0x13, 0x1f, 0x84, 0x6f, 0x00, - 0x2c, 0xef, 0xf3, 0x2c, 0x57, 0x1a, 0x8d, 0x09, 0x19, 0x52, 0x29, 0x0b, 0x96, 0x59, 0x88, 0x30, - 0x2c, 0x6b, 0x43, 0xa5, 0xbb, 0x66, 0x0c, 0xdb, 0x5c, 0x18, 0x26, 0xe9, 0xdc, 0xb0, 0x5d, 0xc1, - 0x78, 0xe7, 0xf6, 0xe9, 0xd8, 0x77, 0x3e, 0x7e, 0xf7, 0x9b, 0x03, 0xa6, 0x5e, 0xe6, 0xbd, 0xa8, - 0x2f, 0xd2, 0x62, 0x5a, 0xc5, 0x67, 0x5b, 0x92, 0xa3, 0x96, 0x1a, 0x65, 0x54, 0x9a, 0x02, 0x19, - 0x5b, 0xe6, 0x76, 0xf5, 0xb5, 0x15, 0xe4, 0x84, 0x6f, 0x01, 0xac, 0x3c, 0xce, 0xd5, 0x7f, 0xa4, - 0xe8, 0x13, 0x80, 0x95, 0x83, 0x3c, 0xcb, 0x92, 0x91, 0xee, 0xab, 0x84, 0xc2, 0x49, 0xb1, 0x3a, - 0xff, 0xb6, 0xaf, 0x61, 0x6e, 0xef, 0xe9, 0xbe, 0xb3, 0xf1, 0x7c, 0xf9, 0xbc, 0x7d, 0xef, 0xe6, - 0x1f, 0x19, 0x8e, 0xed, 0xf3, 0xa2, 0xc7, 0x99, 0x18, 0x2a, 0x4a, 0x22, 0x2b, 0x74, 0x3f, 0x7c, - 0x06, 0x37, 0x1e, 0xe8, 0x25, 0x78, 0xca, 0x99, 0xfa, 0xcd, 0x7a, 0x34, 0x60, 0x55, 0x97, 0x71, - 0xca, 0x95, 0xd9, 0x8f, 0x2b, 0xf1, 0x3c, 0x36, 0xd6, 0x27, 0x0c, 0x4b, 0x2a, 0xdd, 0x52, 0x50, - 0x32, 0xd6, 0xdb, 0x30, 0xfc, 0x00, 0x60, 0xf5, 0x11, 0x55, 0x98, 0x60, 0x85, 0x51, 0x00, 0x6b, - 0x84, 0xca, 0xfe, 0x90, 0x65, 0x8a, 0x09, 0x5e, 0xd0, 0x2f, 0x5f, 0xa1, 0xfb, 0x1a, 0xc1, 0x45, - 0xda, 0xcd, 0x39, 0x53, 0xb3, 0x79, 0x79, 0x2b, 0x9f, 0xdc, 0x5c, 0x6f, 0x0c, 0xc9, 0xec, 0x28, - 0x11, 0x82, 0xeb, 0xda, 0x5d, 0xb7, 0x64, 0xb8, 0xcd, 0x59, 0xab, 0x23, 0x4c, 0x66, 0x09, 0x1e, - 0xb9, 0xeb, 0x76, 0x31, 0x8a, 0xb0, 0xb3, 0x7b, 0x3a, 0xf1, 0xc0, 0xd9, 0xc4, 0x03, 0x3f, 0x26, - 0x1e, 0x78, 0x37, 0xf5, 0x9c, 0xb3, 0xa9, 0xe7, 0x7c, 0x9b, 0x7a, 0xce, 0xf3, 0xad, 0xbf, 0xb1, - 0xd1, 0xcc, 0xa3, 0x57, 0x31, 0x7f, 0x8e, 0xbb, 0xbf, 0x02, 0x00, 0x00, 0xff, 0xff, 0xe2, 0x72, - 0xf6, 0xc6, 0xc1, 0x04, 0x00, 0x00, + // 588 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x54, 0xbf, 0x6f, 0xd3, 0x4e, + 0x14, 0xf7, 0x35, 0x8d, 0xbf, 0xe9, 0xe5, 0xcb, 0x72, 0x54, 0xc8, 0xad, 0x84, 0x6d, 0x2c, 0x21, + 0xa5, 0x88, 0x3a, 0x14, 0xc4, 0x92, 0x05, 0x29, 0xa5, 0x42, 0x1d, 0x10, 0xc8, 0x15, 0x42, 0x82, + 0x21, 0x3a, 0xe7, 0xae, 0xc1, 0xaa, 0x7d, 0x67, 0xe5, 0xce, 0xa8, 0xfe, 0x0f, 0x98, 0x80, 0x91, + 0xb1, 0x33, 0x23, 0xe2, 0x7f, 0xa0, 0x63, 0x05, 0x0b, 0x53, 0x40, 0xc9, 0xc2, 0xdc, 0xbf, 0x00, + 0xdd, 0x9d, 0xf3, 0xa3, 0x52, 0x40, 0x0c, 0x0c, 0x4c, 0xb9, 0xcf, 0x7b, 0x9f, 0xf7, 0x79, 0x4f, + 0x9f, 0xf7, 0x1c, 0xe8, 0xf6, 0xb9, 0xc8, 0xb8, 0x68, 0xc7, 0x98, 0x1d, 0xb5, 0x5f, 0xee, 0xc4, + 0x54, 0xe2, 0x1d, 0x0d, 0xc2, 0x7c, 0xc8, 0x25, 0x47, 0x97, 0x4d, 0x3e, 0xd4, 0xa1, 0x2a, 0xbf, + 0xb9, 0x3e, 0xe0, 0x03, 0xae, 0xf3, 0x6d, 0xf5, 0x32, 0xd4, 0xcd, 0x0d, 0x43, 0xed, 0x99, 0x44, + 0x55, 0x67, 0x52, 0xf3, 0x2e, 0x82, 0xce, 0xba, 0xf4, 0x79, 0xc2, 0x4c, 0x3e, 0xf8, 0x02, 0xa0, + 0xfd, 0x18, 0x0f, 0x71, 0x26, 0xd0, 0x21, 0xfc, 0x5f, 0x50, 0x46, 0x7a, 0x94, 0xe1, 0x38, 0xa5, + 0xc4, 0x01, 0x7e, 0xad, 0xd5, 0xbc, 0xed, 0x87, 0x4b, 0xe6, 0x08, 0x0f, 0x28, 0x23, 0x7b, 0x86, + 0xd7, 0xbd, 0x76, 0x3e, 0xf2, 0xae, 0x96, 0x38, 0x4b, 0x3b, 0xc1, 0x62, 0xfd, 0x4d, 0x9e, 0x25, + 0x92, 0x66, 0xb9, 0x2c, 0x83, 0xa8, 0x29, 0xe6, 0x7c, 0xf4, 0x1c, 0xae, 0x13, 0x7a, 0x88, 0x8b, + 0x54, 0xf6, 0x2e, 0xf4, 0x5b, 0xf1, 0x41, 0xab, 0xd1, 0xdd, 0x3a, 0x1f, 0x79, 0xd7, 0x8d, 0xda, + 0x32, 0xd6, 0xa2, 0x2a, 0xaa, 0x08, 0x0b, 0xc3, 0x74, 0x56, 0xdf, 0x9d, 0x78, 0x56, 0xf0, 0x00, + 0x36, 0x17, 0x82, 0x68, 0x1d, 0xd6, 0x09, 0x65, 0x3c, 0x73, 0x80, 0x0f, 0x5a, 0x6b, 0x91, 0x01, + 0xc8, 0x81, 0xff, 0x5d, 0x68, 0x1d, 0x4d, 0x61, 0xa7, 0xa1, 0x44, 0x7e, 0x9c, 0x78, 0x20, 0x78, + 0x0d, 0x60, 0x7d, 0x9f, 0xe5, 0x85, 0x54, 0x6c, 0x4c, 0xc8, 0x90, 0x0a, 0x51, 0xa9, 0x4c, 0x21, + 0xc2, 0xb0, 0xae, 0x0c, 0x15, 0xce, 0x8a, 0x36, 0x6c, 0x63, 0x6e, 0x98, 0xa0, 0x33, 0xc3, 0x76, + 0x79, 0xc2, 0xba, 0xb7, 0x4e, 0x47, 0x9e, 0xf5, 0xfe, 0x9b, 0xd7, 0x1a, 0x24, 0xf2, 0x45, 0x11, + 0x87, 0x7d, 0x9e, 0x55, 0xdb, 0xaa, 0x7e, 0xb6, 0x05, 0x39, 0x6a, 0xcb, 0x32, 0xa7, 0x42, 0x17, + 0x88, 0xc8, 0x28, 0x77, 0x1a, 0xaf, 0xcc, 0x40, 0x56, 0xf0, 0x06, 0x40, 0xfb, 0x51, 0x21, 0xff, + 0xa1, 0x89, 0x3e, 0x00, 0x68, 0x1f, 0x14, 0x79, 0x9e, 0x96, 0xaa, 0xaf, 0xe4, 0x12, 0xa7, 0xd5, + 0xe9, 0xfc, 0xdd, 0xbe, 0x5a, 0xb9, 0xb3, 0xa7, 0xfa, 0x4e, 0xd7, 0xf3, 0xf9, 0xe3, 0xf6, 0xdd, + 0x1b, 0xbf, 0x55, 0x38, 0x36, 0x9f, 0x17, 0x3d, 0xce, 0xf9, 0x50, 0x52, 0x12, 0x9a, 0x41, 0xf7, + 0x83, 0xa7, 0x70, 0xed, 0xbe, 0x3a, 0x82, 0x27, 0x2c, 0x91, 0xbf, 0x38, 0x8f, 0x4d, 0xd8, 0x50, + 0x65, 0x8c, 0x32, 0xa9, 0xef, 0xe3, 0x52, 0x34, 0xc3, 0xda, 0xfa, 0x34, 0xc1, 0x82, 0x0a, 0xa7, + 0xe6, 0xd7, 0xb4, 0xf5, 0x06, 0x06, 0x9f, 0x00, 0x6c, 0x3c, 0xa4, 0x12, 0x13, 0x2c, 0x31, 0xf2, + 0x61, 0x93, 0x50, 0xd1, 0x1f, 0x26, 0xb9, 0x4c, 0x38, 0xab, 0xe4, 0x17, 0x43, 0xe8, 0x9e, 0x62, + 0x30, 0x9e, 0xf5, 0x0a, 0x96, 0xc8, 0xe9, 0xbe, 0xdc, 0xa5, 0x9f, 0xdc, 0x6c, 0xde, 0x08, 0x92, + 0xe9, 0x53, 0x20, 0x04, 0x57, 0x95, 0xbb, 0x4e, 0x4d, 0x6b, 0xeb, 0xb7, 0x9a, 0x8e, 0x24, 0x22, + 0x4f, 0x71, 0xe9, 0xac, 0x9a, 0xc3, 0xa8, 0xa0, 0x62, 0x33, 0x9c, 0x51, 0xa7, 0x6e, 0xd8, 0xea, + 0x8d, 0xae, 0x40, 0x5b, 0x94, 0x59, 0xcc, 0x53, 0xc7, 0xd6, 0xd1, 0x0a, 0x75, 0x77, 0x4f, 0xc7, + 0x2e, 0x38, 0x1b, 0xbb, 0xe0, 0xfb, 0xd8, 0x05, 0x6f, 0x27, 0xae, 0x75, 0x36, 0x71, 0xad, 0xaf, + 0x13, 0xd7, 0x7a, 0xb6, 0xf5, 0x27, 0x96, 0xeb, 0xdd, 0xc5, 0xb6, 0xfe, 0x97, 0xb9, 0xf3, 0x33, + 0x00, 0x00, 0xff, 0xff, 0xa8, 0xf5, 0xda, 0x82, 0xed, 0x04, 0x00, 0x00, } func (this *SendEnabled) Equal(that interface{}) bool { @@ -774,6 +794,20 @@ func (m *Metadata) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.Symbol) > 0 { + i -= len(m.Symbol) + copy(dAtA[i:], m.Symbol) + i = encodeVarintBank(dAtA, i, uint64(len(m.Symbol))) + i-- + dAtA[i] = 0x32 + } + if len(m.Name) > 0 { + i -= len(m.Name) + copy(dAtA[i:], m.Name) + i = encodeVarintBank(dAtA, i, uint64(len(m.Name))) + i-- + dAtA[i] = 0x2a + } if len(m.Display) > 0 { i -= len(m.Display) copy(dAtA[i:], m.Display) @@ -956,6 +990,14 @@ func (m *Metadata) Size() (n int) { if l > 0 { n += 1 + l + sovBank(uint64(l)) } + l = len(m.Name) + if l > 0 { + n += 1 + l + sovBank(uint64(l)) + } + l = len(m.Symbol) + if l > 0 { + n += 1 + l + sovBank(uint64(l)) + } return n } @@ -1779,6 +1821,70 @@ func (m *Metadata) Unmarshal(dAtA []byte) error { } m.Display = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBank + } + 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 ErrInvalidLengthBank + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthBank + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Symbol", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBank + } + 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 ErrInvalidLengthBank + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthBank + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Symbol = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipBank(dAtA[iNdEx:]) diff --git a/x/bank/types/genesis_test.go b/x/bank/types/genesis_test.go index 634b247e0190..a177ddcdab5c 100644 --- a/x/bank/types/genesis_test.go +++ b/x/bank/types/genesis_test.go @@ -28,6 +28,8 @@ func TestGenesisStateValidate(t *testing.T) { Supply: sdk.Coins{sdk.NewInt64Coin("uatom", 1)}, DenomMetadata: []Metadata{ { + Name: "Cosmos Hub Atom", + Symbol: "ATOM", Description: "The native staking token of the Cosmos Hub.", DenomUnits: []*DenomUnit{ {"uatom", uint32(0), []string{"microatom"}}, @@ -85,6 +87,8 @@ func TestGenesisStateValidate(t *testing.T) { GenesisState{ DenomMetadata: []Metadata{ { + Name: "Cosmos Hub Atom", + Symbol: "ATOM", Description: "The native staking token of the Cosmos Hub.", DenomUnits: []*DenomUnit{ {"uatom", uint32(0), []string{"microatom"}}, @@ -95,6 +99,8 @@ func TestGenesisStateValidate(t *testing.T) { Display: "atom", }, { + Name: "Cosmos Hub Atom", + Symbol: "ATOM", Description: "The native staking token of the Cosmos Hub.", DenomUnits: []*DenomUnit{ {"uatom", uint32(0), []string{"microatom"}}, @@ -113,6 +119,8 @@ func TestGenesisStateValidate(t *testing.T) { GenesisState{ DenomMetadata: []Metadata{ { + Name: "Cosmos Hub Atom", + Symbol: "ATOM", Description: "The native staking token of the Cosmos Hub.", DenomUnits: []*DenomUnit{ {"uatom", uint32(0), []string{"microatom"}}, diff --git a/x/bank/types/metadata.go b/x/bank/types/metadata.go index ce7794053d93..9583b85ce44d 100644 --- a/x/bank/types/metadata.go +++ b/x/bank/types/metadata.go @@ -9,12 +9,21 @@ import ( ) // Validate performs a basic validation of the coin metadata fields. It checks: +// - Name and Symbol are not blank // - 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 strings.TrimSpace(m.Name) == "" { + return errors.New("name field cannot be blank") + } + + if strings.TrimSpace(m.Symbol) == "" { + return errors.New("symbol field cannot be blank") + } + if err := sdk.ValidateDenom(m.Base); err != nil { return fmt.Errorf("invalid metadata base denom: %w", err) } diff --git a/x/bank/types/metadata_test.go b/x/bank/types/metadata_test.go index 8ec2fe52ec02..3d4fe0a0e634 100644 --- a/x/bank/types/metadata_test.go +++ b/x/bank/types/metadata_test.go @@ -18,6 +18,8 @@ func TestMetadataValidate(t *testing.T) { { "non-empty coins", types.Metadata{ + Name: "Cosmos Hub Atom", + Symbol: "ATOM", Description: "The native staking token of the Cosmos Hub.", DenomUnits: []*types.DenomUnit{ {"uatom", uint32(0), []string{"microatom"}}, @@ -32,6 +34,8 @@ func TestMetadataValidate(t *testing.T) { { "base coin is display coin", types.Metadata{ + Name: "Cosmos Hub Atom", + Symbol: "ATOM", Description: "The native staking token of the Cosmos Hub.", DenomUnits: []*types.DenomUnit{ {"atom", uint32(0), []string{"ATOM"}}, @@ -42,16 +46,35 @@ func TestMetadataValidate(t *testing.T) { false, }, {"empty metadata", types.Metadata{}, true}, + { + "blank name", + types.Metadata{ + Name: "", + }, + true, + }, + { + "blank symbol", + types.Metadata{ + Name: "Cosmos Hub Atom", + Symbol: "", + }, + true, + }, { "invalid base denom", types.Metadata{ - Base: "", + Name: "Cosmos Hub Atom", + Symbol: "ATOM", + Base: "", }, true, }, { "invalid display denom", types.Metadata{ + Name: "Cosmos Hub Atom", + Symbol: "ATOM", Base: "uatom", Display: "", }, @@ -60,6 +83,8 @@ func TestMetadataValidate(t *testing.T) { { "duplicate denom unit", types.Metadata{ + Name: "Cosmos Hub Atom", + Symbol: "ATOM", Description: "The native staking token of the Cosmos Hub.", DenomUnits: []*types.DenomUnit{ {"uatom", uint32(0), []string{"microatom"}}, @@ -73,6 +98,8 @@ func TestMetadataValidate(t *testing.T) { { "invalid denom unit", types.Metadata{ + Name: "Cosmos Hub Atom", + Symbol: "ATOM", Description: "The native staking token of the Cosmos Hub.", DenomUnits: []*types.DenomUnit{ {"", uint32(0), []string{"microatom"}}, @@ -85,6 +112,8 @@ func TestMetadataValidate(t *testing.T) { { "invalid denom unit alias", types.Metadata{ + Name: "Cosmos Hub Atom", + Symbol: "ATOM", Description: "The native staking token of the Cosmos Hub.", DenomUnits: []*types.DenomUnit{ {"uatom", uint32(0), []string{""}}, @@ -97,6 +126,8 @@ func TestMetadataValidate(t *testing.T) { { "duplicate denom unit alias", types.Metadata{ + Name: "Cosmos Hub Atom", + Symbol: "ATOM", Description: "The native staking token of the Cosmos Hub.", DenomUnits: []*types.DenomUnit{ {"uatom", uint32(0), []string{"microatom", "microatom"}}, @@ -109,6 +140,8 @@ func TestMetadataValidate(t *testing.T) { { "no base denom unit", types.Metadata{ + Name: "Cosmos Hub Atom", + Symbol: "ATOM", Description: "The native staking token of the Cosmos Hub.", DenomUnits: []*types.DenomUnit{ {"matom", uint32(3), []string{"milliatom"}}, @@ -122,6 +155,8 @@ func TestMetadataValidate(t *testing.T) { { "base denom exponent not zero", types.Metadata{ + Name: "Cosmos Hub Atom", + Symbol: "ATOM", Description: "The native staking token of the Cosmos Hub.", DenomUnits: []*types.DenomUnit{ {"uatom", uint32(1), []string{"microatom"}}, @@ -133,9 +168,26 @@ func TestMetadataValidate(t *testing.T) { }, true, }, + { + "invalid denom unit", + types.Metadata{ + Name: "Cosmos Hub Atom", + Symbol: "ATOM", + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + {"uatom", uint32(0), []string{"microatom"}}, + {"", uint32(3), []string{"milliatom"}}, + }, + Base: "uatom", + Display: "uatom", + }, + true, + }, { "no display denom unit", types.Metadata{ + Name: "Cosmos Hub Atom", + Symbol: "ATOM", Description: "The native staking token of the Cosmos Hub.", DenomUnits: []*types.DenomUnit{ {"uatom", uint32(0), []string{"microatom"}}, @@ -148,6 +200,8 @@ func TestMetadataValidate(t *testing.T) { { "denom units not sorted", types.Metadata{ + Name: "Cosmos Hub Atom", + Symbol: "ATOM", Description: "The native staking token of the Cosmos Hub.", DenomUnits: []*types.DenomUnit{ {"uatom", uint32(0), []string{"microatom"}}, From 115096b09dbdce91dce27d0324a4139621fba967 Mon Sep 17 00:00:00 2001 From: Kimura Yu <33382781+KimuraYu45z@users.noreply.github.com> Date: Thu, 25 Feb 2021 16:52:17 +0900 Subject: [PATCH 115/214] change dir '.appd' to '.app' (#8695) --- docs/basics/app-anatomy.md | 4 ++-- docs/cn/basics/app-anatomy.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/basics/app-anatomy.md b/docs/basics/app-anatomy.md index 225da66c3c29..1f329f814b69 100644 --- a/docs/basics/app-anatomy.md +++ b/docs/basics/app-anatomy.md @@ -33,7 +33,7 @@ The blockchain full-node presents itself as a binary, generally suffixed by `-d` Once the main binary is built, the node can be started by running the [`start` command](../core/node.md#start-command). This command function primarily does three things: 1. Create an instance of the state-machine defined in [`app.go`](#core-application-file). -2. Initialize the state-machine with the latest known state, extracted from the `db` stored in the `~/.appd/data` folder. At this point, the state-machine is at height `appBlockHeight`. +2. Initialize the state-machine with the latest known state, extracted from the `db` stored in the `~/.app/data` folder. At this point, the state-machine is at height `appBlockHeight`. 3. Create and start a new Tendermint instance. Among other things, the node will perform a handshake with its peers. It will get the latest `blockHeight` from them, and replay blocks to sync to this height if it is greater than the local `appBlockHeight`. If `appBlockHeight` is `0`, the node is starting from genesis and Tendermint sends an `InitChain` message via the ABCI to the `app`, which triggers the [`InitChainer`](#initchainer). ## Core Application File @@ -77,7 +77,7 @@ Here are the main actions performed by this function: - Mount the stores. - Return the application. -Note that this function only creates an instance of the app, while the actual state is either carried over from the `~/.appd/data` folder if the node is restarted, or generated from the genesis file if the node is started for the first time. +Note that this function only creates an instance of the app, while the actual state is either carried over from the `~/.app/data` folder if the node is restarted, or generated from the genesis file if the node is started for the first time. See an example of application constructor from `simapp`: diff --git a/docs/cn/basics/app-anatomy.md b/docs/cn/basics/app-anatomy.md index 813e9c6c4445..9ac8feb822e0 100644 --- a/docs/cn/basics/app-anatomy.md +++ b/docs/cn/basics/app-anatomy.md @@ -28,7 +28,7 @@ Blockchain Node | | Consensus | | 1. [`app.go`] 创建了一个状态机实例。 -2. 用最新的已知状态初始化状态机,该状态机是从存储在 `~/.appd/data` 文件夹中的 db 中提取的。 此时,状态机的高度为:`appBlockHeight`。 +2. 用最新的已知状态初始化状态机,该状态机是从存储在 `~/.app/data` 文件夹中的 db 中提取的。 此时,状态机的高度为:`appBlockHeight`。 3. 创建并启动一个新的 Tendermint 实例。 该节点将与对等节点进行连接交换信息。 它将从他们那里获取最新的 `blockHeight`,如果它大于本地的 `appBlockHeight`,则重播块以同步到该高度。 如果 `appBlockHeight` 为 `0`,则该节点从创世开始,并且 Tendermint 通过 ABCI 接口向 `app` 发送 `InitChain` 初始化链命令,从而触发 [`InitChainer`](https://docs.cosmos.network/master/basics/app-anatomy.html#initchainer)。 @@ -73,7 +73,7 @@ Blockchain Node | | Consensus | | - 挂载存储. - 返回应用实例. -请注意,此函数仅创建该应用的一个实例,而如果重新启动节点,则状态将从 `〜/.appd/data` 文件夹中保留下来状态加载,如果节点是第一次启动,则从创世文件生成。See an example of application constructor from [`gaia`](https://github.com/cosmos/gaia): +请注意,此函数仅创建该应用的一个实例,而如果重新启动节点,则状态将从 `〜/.app/data` 文件夹中保留下来状态加载,如果节点是第一次启动,则从创世文件生成。See an example of application constructor from [`gaia`](https://github.com/cosmos/gaia): +++ https://github.com/cosmos/gaia/blob/f41a660cdd5bea173139965ade55bd25d1ee3429/app/app.go#L110-L222 From eeb3eabdc6512dd2dbdd12306d07c46fb9610515 Mon Sep 17 00:00:00 2001 From: Amaury <1293565+amaurym@users.noreply.github.com> Date: Thu, 25 Feb 2021 08:57:06 +0100 Subject: [PATCH 116/214] docs: Add mention to use gRPC v1.33.2 (#8658) Co-authored-by: Marko --- docs/basics/app-anatomy.md | 12 ++++++++++++ docs/basics/query-lifecycle.md | 12 ++++++++++++ docs/core/grpc_rest.md | 12 ++++++++++++ 3 files changed, 36 insertions(+) diff --git a/docs/basics/app-anatomy.md b/docs/basics/app-anatomy.md index 1f329f814b69..b75ecf8e7aaf 100644 --- a/docs/basics/app-anatomy.md +++ b/docs/basics/app-anatomy.md @@ -237,6 +237,18 @@ See an example of an application's main command-line file from the [nameservice ## Dependencies and Makefile +::: warning +A patch introduced in `go-grpc v1.34.0` made gRPC incompatible with the `gogoproto` library, making some [gRPC queries](https://github.com/cosmos/cosmos-sdk/issues/8426) panic. As such, the SDK requires that `go-grpc <=v1.33.2` is installed in your `go.mod`. + +To make sure that gRPC is working properly, it is **highly recommended** to add the following line in your application's `go.mod`: + +``` +replace google.golang.org/grpc => google.golang.org/grpc v1.33.2 +``` + +Please see [issue #8392](https://github.com/cosmos/cosmos-sdk/issues/8392) for more info. +::: + This section is optional, as developers are free to choose their dependency manager and project building method. That said, the current most used framework for versioning control is [`go.mod`](https://github.com/golang/go/wiki/Modules). It ensures each of the libraries used throughout the application are imported with the correct version. See an example from the [nameservice tutorial](https://github.com/cosmos/sdk-tutorials/tree/master/nameservice): +++ https://github.com/cosmos/sdk-tutorials/blob/c6754a1e313eb1ed973c5c91dcc606f2fd288811/go.mod#L1-L18 diff --git a/docs/basics/query-lifecycle.md b/docs/basics/query-lifecycle.md index 4b4c509bb354..55902e698d3c 100644 --- a/docs/basics/query-lifecycle.md +++ b/docs/basics/query-lifecycle.md @@ -38,6 +38,18 @@ The CLI understands a specific set of commands, defined in a hierarchical struct ### gRPC +::: warning +A patch introduced in `go-grpc v1.34.0` made gRPC incompatible with the `gogoproto` library, making some [gRPC queries](https://github.com/cosmos/cosmos-sdk/issues/8426) panic. As such, the SDK requires that `go-grpc <=v1.33.2` is installed in your `go.mod`. + +To make sure that gRPC is working properly, it is **highly recommended** to add the following line in your application's `go.mod`: + +``` +replace google.golang.org/grpc => google.golang.org/grpc v1.33.2 +``` + +Please see [issue #8392](https://github.com/cosmos/cosmos-sdk/issues/8392) for more info. +::: + 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: diff --git a/docs/core/grpc_rest.md b/docs/core/grpc_rest.md index ca59d3f14908..cea6c0ed3cea 100644 --- a/docs/core/grpc_rest.md +++ b/docs/core/grpc_rest.md @@ -20,6 +20,18 @@ The node also exposes some other endpoints, such as the Tendermint P2P endpoint, ## gRPC Server +::: warning +A patch introduced in `go-grpc v1.34.0` made gRPC incompatible with the `gogoproto` library, making some [gRPC queries](https://github.com/cosmos/cosmos-sdk/issues/8426) panic. As such, the SDK requires that `go-grpc <=v1.33.2` is installed in your `go.mod`. + +To make sure that gRPC is working properly, it is **highly recommended** to add the following line in your application's `go.mod`: + +``` +replace google.golang.org/grpc => google.golang.org/grpc v1.33.2 +``` + +Please see [issue #8392](https://github.com/cosmos/cosmos-sdk/issues/8392) for more info. +::: + Cosmos SDK v0.40 introduced Protobuf as the main [encoding](./encoding) library, and this brings a wide range of Protobuf-based tools that can be plugged into the SDK. One such tool is [gRPC](https://grpc.io), a modern open source high performance RPC framework that has decent client support in several languages. 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: From ba74a7c7376dac9cce8a3f84e75c7c6a7edc9204 Mon Sep 17 00:00:00 2001 From: Amaury <1293565+amaurym@users.noreply.github.com> Date: Thu, 25 Feb 2021 11:43:31 +0100 Subject: [PATCH 117/214] x{stake,slash,gov,distrib} In-place Store Migrations (#8504) * 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 * Add distrib legacy folder * Add tests for distrib migration * Add gov migrations * Copy paste whole keys file * Add gov migrations * Add staking * Fix staking tests * Update spec and module.go * Update to latest changes * Update migration scripts * capability to 1 * Fix tests * Add package godoc * Remove whitespace * Remove global * Use Migrator * Remove 042 keys files * Fix build * Unlambda * Rename to Migrate1to2 Co-authored-by: Robert Zaremba --- simapp/app_test.go | 71 ++++- types/module/module.go | 2 +- x/bank/keeper/migrations.go | 19 +- x/bank/legacy/v040/keys.go | 2 + x/bank/legacy/v042/keys.go | 50 ---- x/bank/legacy/v042/store.go | 3 +- x/bank/legacy/v042/store_test.go | 3 +- x/bank/module.go | 6 +- x/distribution/keeper/migrations.go | 21 ++ x/distribution/legacy/v040/keys.go | 196 ++++++++++++++ x/distribution/legacy/v040/types.go | 6 - x/distribution/legacy/v042/helpers.go | 70 +++++ x/distribution/legacy/v042/store.go | 23 ++ x/distribution/legacy/v042/store_test.go | 99 +++++++ x/distribution/module.go | 5 +- x/distribution/spec/02_state.md | 14 +- x/gov/keeper/migrations.go | 21 ++ x/gov/legacy/v040/keys.go | 167 ++++++++++++ x/gov/legacy/v040/types.go | 6 - x/gov/legacy/v042/store.go | 43 +++ x/gov/legacy/v042/store_test.go | 85 ++++++ x/gov/module.go | 5 +- x/slashing/keeper/migrations.go | 21 ++ x/slashing/legacy/v040/keys.go | 69 +++++ x/slashing/legacy/v040/types.go | 5 - x/slashing/legacy/v042/store.go | 20 ++ x/slashing/legacy/v042/store_test.go | 68 +++++ x/slashing/module.go | 3 + x/slashing/spec/02_state.md | 4 +- x/staking/keeper/migrations.go | 21 ++ x/staking/legacy/v040/keys.go | 330 +++++++++++++++++++++++ x/staking/legacy/v040/types.go | 5 - x/staking/legacy/v042/store.go | 78 ++++++ x/staking/legacy/v042/store_test.go | 137 ++++++++++ x/staking/module.go | 5 +- x/staking/spec/01_state.md | 20 +- 36 files changed, 1588 insertions(+), 115 deletions(-) delete mode 100644 x/bank/legacy/v042/keys.go create mode 100644 x/distribution/keeper/migrations.go create mode 100644 x/distribution/legacy/v040/keys.go delete mode 100644 x/distribution/legacy/v040/types.go create mode 100644 x/distribution/legacy/v042/helpers.go create mode 100644 x/distribution/legacy/v042/store.go create mode 100644 x/distribution/legacy/v042/store_test.go create mode 100644 x/gov/keeper/migrations.go create mode 100644 x/gov/legacy/v040/keys.go delete mode 100644 x/gov/legacy/v040/types.go create mode 100644 x/gov/legacy/v042/store.go create mode 100644 x/gov/legacy/v042/store_test.go create mode 100644 x/slashing/keeper/migrations.go create mode 100644 x/slashing/legacy/v040/keys.go delete mode 100644 x/slashing/legacy/v040/types.go create mode 100644 x/slashing/legacy/v042/store.go create mode 100644 x/slashing/legacy/v042/store_test.go create mode 100644 x/staking/keeper/migrations.go create mode 100644 x/staking/legacy/v040/keys.go delete mode 100644 x/staking/legacy/v040/types.go create mode 100644 x/staking/legacy/v042/store.go create mode 100644 x/staking/legacy/v042/store_test.go diff --git a/simapp/app_test.go b/simapp/app_test.go index 049e00b77ae8..8f596f5ecc0d 100644 --- a/simapp/app_test.go +++ b/simapp/app_test.go @@ -11,8 +11,27 @@ import ( tmproto "github.com/tendermint/tendermint/proto/tendermint/types" dbm "github.com/tendermint/tm-db" + "github.com/cosmos/cosmos-sdk/baseapp" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" + "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cosmos/cosmos-sdk/x/auth/vesting" + "github.com/cosmos/cosmos-sdk/x/authz" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/cosmos/cosmos-sdk/x/capability" + "github.com/cosmos/cosmos-sdk/x/crisis" + "github.com/cosmos/cosmos-sdk/x/distribution" + "github.com/cosmos/cosmos-sdk/x/evidence" + feegrant "github.com/cosmos/cosmos-sdk/x/feegrant" + "github.com/cosmos/cosmos-sdk/x/genutil" + "github.com/cosmos/cosmos-sdk/x/gov" + transfer "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer" + ibc "github.com/cosmos/cosmos-sdk/x/ibc/core" + "github.com/cosmos/cosmos-sdk/x/mint" + "github.com/cosmos/cosmos-sdk/x/params" + "github.com/cosmos/cosmos-sdk/x/slashing" + "github.com/cosmos/cosmos-sdk/x/staking" + "github.com/cosmos/cosmos-sdk/x/upgrade" ) func TestSimAppExportAndBlockedAddrs(t *testing.T) { @@ -52,11 +71,33 @@ func TestGetMaccPerms(t *testing.T) { 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. + logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) + app := NewSimApp(logger, db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encCfg, EmptyAppOptions{}) + + // Create a new baseapp and configurator for the purpose of this test. + bApp := baseapp.NewBaseApp(appName, logger, db, encCfg.TxConfig.TxDecoder()) + bApp.SetCommitMultiStoreTracer(nil) + bApp.SetInterfaceRegistry(encCfg.InterfaceRegistry) + app.BaseApp = bApp app.configurator = module.NewConfigurator(app.MsgServiceRouter(), app.GRPCQueryRouter()) + // We register all modules on the Configurator, except x/bank. x/bank will + // serve as the test subject on which we run the migration tests. + // + // The loop below is the same as calling `RegisterServices` on + // ModuleManager, except that we skip x/bank. + for _, module := range app.mm.Modules { + if module.Name() == banktypes.ModuleName { + continue + } + + module.RegisterServices(app.configurator) + } + + // Initialize the chain + app.InitChain(abci.RequestInitChain{}) + app.Commit() + testCases := []struct { name string moduleName string @@ -115,12 +156,30 @@ func TestRunMigrations(t *testing.T) { } require.NoError(t, err) + // Run migrations only for bank. That's why we put the initial + // version for bank as 1, and for all other modules, we put as + // their latest ConsensusVersion. 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, + "bank": 1, + "auth": auth.AppModule{}.ConsensusVersion(), + "authz": authz.AppModule{}.ConsensusVersion(), + "staking": staking.AppModule{}.ConsensusVersion(), + "mint": mint.AppModule{}.ConsensusVersion(), + "distribution": distribution.AppModule{}.ConsensusVersion(), + "slashing": slashing.AppModule{}.ConsensusVersion(), + "gov": gov.AppModule{}.ConsensusVersion(), + "params": params.AppModule{}.ConsensusVersion(), + "ibc": ibc.AppModule{}.ConsensusVersion(), + "upgrade": upgrade.AppModule{}.ConsensusVersion(), + "vesting": vesting.AppModule{}.ConsensusVersion(), + "feegrant": feegrant.AppModule{}.ConsensusVersion(), + "transfer": transfer.AppModule{}.ConsensusVersion(), + "evidence": evidence.AppModule{}.ConsensusVersion(), + "crisis": crisis.AppModule{}.ConsensusVersion(), + "genutil": genutil.AppModule{}.ConsensusVersion(), + "capability": capability.AppModule{}.ConsensusVersion(), }, ) if tc.expRunErr { diff --git a/types/module/module.go b/types/module/module.go index b998f273af5a..9123c9af7ec9 100644 --- a/types/module/module.go +++ b/types/module/module.go @@ -331,7 +331,7 @@ func (m *Manager) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) map[st } // MigrationHandler is the migration function that each module registers. -type MigrationHandler func(store sdk.Context) error +type MigrationHandler func(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. diff --git a/x/bank/keeper/migrations.go b/x/bank/keeper/migrations.go index de6b61a9c2b6..3a200fc2730d 100644 --- a/x/bank/keeper/migrations.go +++ b/x/bank/keeper/migrations.go @@ -5,16 +5,17 @@ import ( 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 +// Migrator is a struct for handling in-place store migrations. +type Migrator struct { + keeper BaseKeeper } -var _ MigrationKeeper = (*BaseKeeper)(nil) +// NewMigrator returns a new Migrator. +func NewMigrator(keeper BaseKeeper) Migrator { + return Migrator{keeper: keeper} +} -// Migrate1 implements MigrationKeeper.Migrate1 method. -func (keeper BaseKeeper) Migrate1(ctx sdk.Context) error { - return v042.MigrateStore(ctx, keeper.storeKey) +// Migrate1to2 migrates from version 1 to 2. +func (m Migrator) Migrate1to2(ctx sdk.Context) error { + return v042.MigrateStore(ctx, m.keeper.storeKey) } diff --git a/x/bank/legacy/v040/keys.go b/x/bank/legacy/v040/keys.go index bd1035599164..043c208b627c 100644 --- a/x/bank/legacy/v040/keys.go +++ b/x/bank/legacy/v040/keys.go @@ -1,3 +1,5 @@ +// Package v040 is copy-pasted from: +// https://github.com/cosmos/cosmos-sdk/blob/v0.41.0/x/bank/types/key.go package v040 import ( diff --git a/x/bank/legacy/v042/keys.go b/x/bank/legacy/v042/keys.go deleted file mode 100644 index 8d718b1c5d3c..000000000000 --- a/x/bank/legacy/v042/keys.go +++ /dev/null @@ -1,50 +0,0 @@ -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 index 9295d8d2ff77..894305b6c8f7 100644 --- a/x/bank/legacy/v042/store.go +++ b/x/bank/legacy/v042/store.go @@ -5,6 +5,7 @@ import ( 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" + "github.com/cosmos/cosmos-sdk/x/bank/types" ) // MigrateStore performs in-place store migrations from v0.40 to v0.42. The @@ -27,7 +28,7 @@ func MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey) error { for ; oldStoreIter.Valid(); oldStoreIter.Next() { addr := v040bank.AddressFromBalancesStore(oldStoreIter.Key()) denom := oldStoreIter.Key()[v040auth.AddrLen:] - newStoreKey := append(CreateAccountBalancesPrefix(addr), denom...) + newStoreKey := append(types.CreateAccountBalancesPrefix(addr), denom...) // Set new key on store. Values don't change. store.Set(newStoreKey, oldStoreIter.Value()) diff --git a/x/bank/legacy/v042/store_test.go b/x/bank/legacy/v042/store_test.go index e1b6a7987a04..7481232f5c59 100644 --- a/x/bank/legacy/v042/store_test.go +++ b/x/bank/legacy/v042/store_test.go @@ -10,6 +10,7 @@ import ( 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" + "github.com/cosmos/cosmos-sdk/x/bank/types" ) func TestStoreMigration(t *testing.T) { @@ -27,7 +28,7 @@ func TestStoreMigration(t *testing.T) { err := v042bank.MigrateStore(ctx, bankKey) require.NoError(t, err) - newKey := append(v042bank.CreateAccountBalancesPrefix(addr), denom...) + newKey := append(types.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)) diff --git a/x/bank/module.go b/x/bank/module.go index c335c3409fa5..3e728e6039fe 100644 --- a/x/bank/module.go +++ b/x/bank/module.go @@ -98,9 +98,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) - }) + + m := keeper.NewMigrator(am.keeper.(keeper.BaseKeeper)) + cfg.RegisterMigration(types.ModuleName, 1, m.Migrate1to2) } // NewAppModule creates a new AppModule object diff --git a/x/distribution/keeper/migrations.go b/x/distribution/keeper/migrations.go new file mode 100644 index 000000000000..7c5d40dba4db --- /dev/null +++ b/x/distribution/keeper/migrations.go @@ -0,0 +1,21 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + v042 "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v042" +) + +// Migrator is a struct for handling in-place store migrations. +type Migrator struct { + keeper Keeper +} + +// NewMigrator returns a new Migrator. +func NewMigrator(keeper Keeper) Migrator { + return Migrator{keeper: keeper} +} + +// Migrate1to2 migrates from version 1 to 2. +func (m Migrator) Migrate1to2(ctx sdk.Context) error { + return v042.MigrateStore(ctx, m.keeper.storeKey) +} diff --git a/x/distribution/legacy/v040/keys.go b/x/distribution/legacy/v040/keys.go new file mode 100644 index 000000000000..88a3c78079bb --- /dev/null +++ b/x/distribution/legacy/v040/keys.go @@ -0,0 +1,196 @@ +// Package v040 is copy-pasted from: +// https://github.com/cosmos/cosmos-sdk/blob/v0.41.0/x/distribution/types/keys.go +package v040 + +import ( + "encoding/binary" + + sdk "github.com/cosmos/cosmos-sdk/types" + v040auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v040" +) + +const ( + // ModuleName is the module name constant used in many places + ModuleName = "distribution" + + // StoreKey is the store key string for distribution + StoreKey = ModuleName + + // RouterKey is the message route for distribution + RouterKey = ModuleName + + // QuerierRoute is the querier route for distribution + QuerierRoute = ModuleName +) + +// Keys for distribution store +// Items are stored with the following key: values +// +// - 0x00: FeePol +// +// - 0x01: sdk.ConsAddress +// +// - 0x02: ValidatorOutstandingRewards +// +// - 0x03: sdk.AccAddress +// +// - 0x04: DelegatorStartingInfo +// +// - 0x05: ValidatorHistoricalRewards +// +// - 0x06: ValidatorCurrentRewards +// +// - 0x07: ValidatorCurrentRewards +// +// - 0x08: ValidatorSlashEvent +var ( + FeePoolKey = []byte{0x00} // key for global distribution state + ProposerKey = []byte{0x01} // key for the proposer operator address + ValidatorOutstandingRewardsPrefix = []byte{0x02} // key for outstanding rewards + + DelegatorWithdrawAddrPrefix = []byte{0x03} // key for delegator withdraw address + DelegatorStartingInfoPrefix = []byte{0x04} // key for delegator starting info + ValidatorHistoricalRewardsPrefix = []byte{0x05} // key for historical validators rewards / stake + ValidatorCurrentRewardsPrefix = []byte{0x06} // key for current validator rewards + ValidatorAccumulatedCommissionPrefix = []byte{0x07} // key for accumulated validator commission + ValidatorSlashEventPrefix = []byte{0x08} // key for validator slash fraction +) + +// gets an address from a validator's outstanding rewards key +func GetValidatorOutstandingRewardsAddress(key []byte) (valAddr sdk.ValAddress) { + addr := key[1:] + if len(addr) != v040auth.AddrLen { + panic("unexpected key length") + } + return sdk.ValAddress(addr) +} + +// gets an address from a delegator's withdraw info key +func GetDelegatorWithdrawInfoAddress(key []byte) (delAddr sdk.AccAddress) { + addr := key[1:] + if len(addr) != v040auth.AddrLen { + panic("unexpected key length") + } + return sdk.AccAddress(addr) +} + +// gets the addresses from a delegator starting info key +func GetDelegatorStartingInfoAddresses(key []byte) (valAddr sdk.ValAddress, delAddr sdk.AccAddress) { + addr := key[1 : 1+v040auth.AddrLen] + if len(addr) != v040auth.AddrLen { + panic("unexpected key length") + } + valAddr = sdk.ValAddress(addr) + addr = key[1+v040auth.AddrLen:] + if len(addr) != v040auth.AddrLen { + panic("unexpected key length") + } + delAddr = sdk.AccAddress(addr) + return +} + +// gets the address & period from a validator's historical rewards key +func GetValidatorHistoricalRewardsAddressPeriod(key []byte) (valAddr sdk.ValAddress, period uint64) { + addr := key[1 : 1+v040auth.AddrLen] + if len(addr) != v040auth.AddrLen { + panic("unexpected key length") + } + valAddr = sdk.ValAddress(addr) + b := key[1+v040auth.AddrLen:] + if len(b) != 8 { + panic("unexpected key length") + } + period = binary.LittleEndian.Uint64(b) + return +} + +// gets the address from a validator's current rewards key +func GetValidatorCurrentRewardsAddress(key []byte) (valAddr sdk.ValAddress) { + addr := key[1:] + if len(addr) != v040auth.AddrLen { + panic("unexpected key length") + } + return sdk.ValAddress(addr) +} + +// gets the address from a validator's accumulated commission key +func GetValidatorAccumulatedCommissionAddress(key []byte) (valAddr sdk.ValAddress) { + addr := key[1:] + if len(addr) != v040auth.AddrLen { + panic("unexpected key length") + } + return sdk.ValAddress(addr) +} + +// gets the height from a validator's slash event key +func GetValidatorSlashEventAddressHeight(key []byte) (valAddr sdk.ValAddress, height uint64) { + addr := key[1 : 1+v040auth.AddrLen] + if len(addr) != v040auth.AddrLen { + panic("unexpected key length") + } + valAddr = sdk.ValAddress(addr) + startB := 1 + v040auth.AddrLen + 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 +func GetValidatorOutstandingRewardsKey(valAddr sdk.ValAddress) []byte { + return append(ValidatorOutstandingRewardsPrefix, valAddr.Bytes()...) +} + +// gets the key for a delegator's withdraw addr +func GetDelegatorWithdrawAddrKey(delAddr sdk.AccAddress) []byte { + return append(DelegatorWithdrawAddrPrefix, delAddr.Bytes()...) +} + +// gets 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()...) +} + +// gets the prefix key for a validator's historical rewards +func GetValidatorHistoricalRewardsPrefix(v sdk.ValAddress) []byte { + return append(ValidatorHistoricalRewardsPrefix, v.Bytes()...) +} + +// gets 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...) +} + +// gets the key for a validator's current rewards +func GetValidatorCurrentRewardsKey(v sdk.ValAddress) []byte { + return append(ValidatorCurrentRewardsPrefix, v.Bytes()...) +} + +// gets the key for a validator's current commission +func GetValidatorAccumulatedCommissionKey(v sdk.ValAddress) []byte { + return append(ValidatorAccumulatedCommissionPrefix, v.Bytes()...) +} + +// gets the prefix key for a validator's slash fractions +func GetValidatorSlashEventPrefix(v sdk.ValAddress) []byte { + return append(ValidatorSlashEventPrefix, v.Bytes()...) +} + +// gets 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...)..., + ) +} + +// gets 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/distribution/legacy/v040/types.go b/x/distribution/legacy/v040/types.go deleted file mode 100644 index aa502303803e..000000000000 --- a/x/distribution/legacy/v040/types.go +++ /dev/null @@ -1,6 +0,0 @@ -package v040 - -// Default parameter values -const ( - ModuleName = "distribution" -) diff --git a/x/distribution/legacy/v042/helpers.go b/x/distribution/legacy/v042/helpers.go new file mode 100644 index 000000000000..afc99cf70888 --- /dev/null +++ b/x/distribution/legacy/v042/helpers.go @@ -0,0 +1,70 @@ +package v042 + +import ( + "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" + v040auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v040" +) + +// MigratePrefixAddress is a helper function that migrates all keys of format: +// prefix_bytes | address_bytes +// into format: +// prefix_bytes | address_len (1 byte) | address_bytes +func MigratePrefixAddress(store sdk.KVStore, prefixBz []byte) { + oldStore := prefix.NewStore(store, prefixBz) + + oldStoreIter := oldStore.Iterator(nil, nil) + defer oldStoreIter.Close() + + for ; oldStoreIter.Valid(); oldStoreIter.Next() { + addr := oldStoreIter.Key() + newStoreKey := append(prefixBz, address.MustLengthPrefix(addr)...) + + // Set new key on store. Values don't change. + store.Set(newStoreKey, oldStoreIter.Value()) + oldStore.Delete(oldStoreIter.Key()) + } +} + +// MigratePrefixAddressBytes is a helper function that migrates all keys of format: +// prefix_bytes | address_bytes | arbitrary_bytes +// into format: +// prefix_bytes | address_len (1 byte) | address_bytes | arbitrary_bytes +func MigratePrefixAddressBytes(store sdk.KVStore, prefixBz []byte) { + oldStore := prefix.NewStore(store, prefixBz) + + oldStoreIter := oldStore.Iterator(nil, nil) + defer oldStoreIter.Close() + + for ; oldStoreIter.Valid(); oldStoreIter.Next() { + addr := oldStoreIter.Key()[:v040auth.AddrLen] + endBz := oldStoreIter.Key()[v040auth.AddrLen:] + newStoreKey := append(append(prefixBz, address.MustLengthPrefix(addr)...), endBz...) + + // Set new key on store. Values don't change. + store.Set(newStoreKey, oldStoreIter.Value()) + oldStore.Delete(oldStoreIter.Key()) + } +} + +// MigratePrefixAddressAddress is a helper function that migrates all keys of format: +// prefix_bytes | address_1_bytes | address_2_bytes +// into format: +// prefix_bytes | address_1_len (1 byte) | address_1_bytes | address_2_len (1 byte) | address_2_bytes +func MigratePrefixAddressAddress(store sdk.KVStore, prefixBz []byte) { + oldStore := prefix.NewStore(store, prefixBz) + + oldStoreIter := oldStore.Iterator(nil, nil) + defer oldStoreIter.Close() + + for ; oldStoreIter.Valid(); oldStoreIter.Next() { + addr1 := oldStoreIter.Key()[:v040auth.AddrLen] + addr2 := oldStoreIter.Key()[v040auth.AddrLen:] + newStoreKey := append(append(prefixBz, address.MustLengthPrefix(addr1)...), address.MustLengthPrefix(addr2)...) + + // Set new key on store. Values don't change. + store.Set(newStoreKey, oldStoreIter.Value()) + oldStore.Delete(oldStoreIter.Key()) + } +} diff --git a/x/distribution/legacy/v042/store.go b/x/distribution/legacy/v042/store.go new file mode 100644 index 000000000000..31c575b4adc3 --- /dev/null +++ b/x/distribution/legacy/v042/store.go @@ -0,0 +1,23 @@ +package v042 + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + v040distribution "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v040" +) + +// MigrateStore performs in-place store migrations from v0.40 to v0.42. The +// migration includes: +// +// - Change addresses to be length-prefixed. +func MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey) error { + store := ctx.KVStore(storeKey) + MigratePrefixAddress(store, v040distribution.ValidatorOutstandingRewardsPrefix) + MigratePrefixAddress(store, v040distribution.DelegatorWithdrawAddrPrefix) + MigratePrefixAddressAddress(store, v040distribution.DelegatorStartingInfoPrefix) + MigratePrefixAddressBytes(store, v040distribution.ValidatorHistoricalRewardsPrefix) + MigratePrefixAddress(store, v040distribution.ValidatorCurrentRewardsPrefix) + MigratePrefixAddress(store, v040distribution.ValidatorAccumulatedCommissionPrefix) + MigratePrefixAddressBytes(store, v040distribution.ValidatorSlashEventPrefix) + + return nil +} diff --git a/x/distribution/legacy/v042/store_test.go b/x/distribution/legacy/v042/store_test.go new file mode 100644 index 000000000000..2a4a5df75bb1 --- /dev/null +++ b/x/distribution/legacy/v042/store_test.go @@ -0,0 +1,99 @@ +package v042_test + +import ( + "bytes" + "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" + v040distribution "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v040" + v042distribution "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v042" + "github.com/cosmos/cosmos-sdk/x/distribution/types" +) + +func TestStoreMigration(t *testing.T) { + distributionKey := sdk.NewKVStoreKey("distribution") + ctx := testutil.DefaultContext(distributionKey, sdk.NewTransientStoreKey("transient_test")) + store := ctx.KVStore(distributionKey) + + _, _, addr1 := testdata.KeyTestPubAddr() + valAddr := sdk.ValAddress(addr1) + _, _, addr2 := testdata.KeyTestPubAddr() + // Use dummy value for all keys. + value := []byte("foo") + + testCases := []struct { + name string + oldKey []byte + newKey []byte + }{ + { + "FeePoolKey", + v040distribution.FeePoolKey, + types.FeePoolKey, + }, + { + "ProposerKey", + v040distribution.ProposerKey, + types.ProposerKey, + }, + { + "ValidatorOutstandingRewards", + v040distribution.GetValidatorOutstandingRewardsKey(valAddr), + types.GetValidatorOutstandingRewardsKey(valAddr), + }, + { + "DelegatorWithdrawAddr", + v040distribution.GetDelegatorWithdrawAddrKey(addr2), + types.GetDelegatorWithdrawAddrKey(addr2), + }, + { + "DelegatorStartingInfo", + v040distribution.GetDelegatorStartingInfoKey(valAddr, addr2), + types.GetDelegatorStartingInfoKey(valAddr, addr2), + }, + { + "ValidatorHistoricalRewards", + v040distribution.GetValidatorHistoricalRewardsKey(valAddr, 6), + types.GetValidatorHistoricalRewardsKey(valAddr, 6), + }, + { + "ValidatorCurrentRewards", + v040distribution.GetValidatorCurrentRewardsKey(valAddr), + types.GetValidatorCurrentRewardsKey(valAddr), + }, + { + "ValidatorAccumulatedCommission", + v040distribution.GetValidatorAccumulatedCommissionKey(valAddr), + types.GetValidatorAccumulatedCommissionKey(valAddr), + }, + { + "ValidatorSlashEvent", + v040distribution.GetValidatorSlashEventKey(valAddr, 6, 8), + types.GetValidatorSlashEventKey(valAddr, 6, 8), + }, + } + + // Set all the old keys to the store + for _, tc := range testCases { + store.Set(tc.oldKey, value) + } + + // Run migrations. + err := v042distribution.MigrateStore(ctx, distributionKey) + require.NoError(t, err) + + // Make sure the new keys are set and old keys are deleted. + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + if bytes.Compare(tc.oldKey, tc.newKey) != 0 { + require.Nil(t, store.Get(tc.oldKey)) + } + require.Equal(t, value, store.Get(tc.newKey)) + }) + } +} diff --git a/x/distribution/module.go b/x/distribution/module.go index 0cc40570b5f3..d6261d3cd573 100644 --- a/x/distribution/module.go +++ b/x/distribution/module.go @@ -141,6 +141,9 @@ func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sd func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) types.RegisterQueryServer(cfg.QueryServer(), am.keeper) + + m := keeper.NewMigrator(am.keeper) + cfg.RegisterMigration(types.ModuleName, 1, m.Migrate1to2) } // InitGenesis performs genesis initialization for the distribution module. It returns @@ -160,7 +163,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json } // ConsensusVersion implements AppModule/ConsensusVersion. -func (AppModule) ConsensusVersion() uint64 { return 1 } +func (AppModule) ConsensusVersion() uint64 { return 2 } // BeginBlock returns the begin blocker for the distribution module. func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { diff --git a/x/distribution/spec/02_state.md b/x/distribution/spec/02_state.md index b8dbde4a9ae4..4111089cc7fd 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 -> ProtocolBuffer(FeePool)` +- FeePool: `0x00 -> ProtocolBuffer(FeePool)` ```go // coins with decimal @@ -33,12 +33,12 @@ type DecCoin struct { Validator distribution information for the relevant validator is updated each time: - 1. delegation amount to a validator is updated, - 2. a validator successfully proposes a block and receives a reward, - 3. any delegator withdraws from a validator, or - 4. the validator withdraws it's commission. +1. delegation amount to a validator is updated, +2. a validator successfully proposes a block and receives a reward, +3. any delegator withdraws from a validator, or +4. the validator withdraws it's commission. -- ValidatorDistInfo: `0x02 | ValOperatorAddr -> ProtocolBuffer(validatorDistribution)` +- ValidatorDistInfo: `0x02 | ValOperatorAddrLen (1 byte) | ValOperatorAddr -> ProtocolBuffer(validatorDistribution)` ```go type ValidatorDistInfo struct { @@ -56,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 -> ProtocolBuffer(delegatorDist)` +- DelegationDistInfo: `0x02 | DelegatorAddrLen (1 byte) | DelegatorAddr | ValOperatorAddrLen (1 byte) | ValOperatorAddr -> ProtocolBuffer(delegatorDist)` ```go type DelegationDistInfo struct { diff --git a/x/gov/keeper/migrations.go b/x/gov/keeper/migrations.go new file mode 100644 index 000000000000..c643c6dd7b99 --- /dev/null +++ b/x/gov/keeper/migrations.go @@ -0,0 +1,21 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + v042 "github.com/cosmos/cosmos-sdk/x/gov/legacy/v042" +) + +// Migrator is a struct for handling in-place store migrations. +type Migrator struct { + keeper Keeper +} + +// NewMigrator returns a new Migrator. +func NewMigrator(keeper Keeper) Migrator { + return Migrator{keeper: keeper} +} + +// Migrate1to2 migrates from version 1 to 2. +func (m Migrator) Migrate1to2(ctx sdk.Context) error { + return v042.MigrateStore(ctx, m.keeper.storeKey) +} diff --git a/x/gov/legacy/v040/keys.go b/x/gov/legacy/v040/keys.go new file mode 100644 index 000000000000..b1559875bb1f --- /dev/null +++ b/x/gov/legacy/v040/keys.go @@ -0,0 +1,167 @@ +// Package v040 is copy-pasted from: +// https://github.com/cosmos/cosmos-sdk/blob/v0.41.0/x/gov/types/keys.go +package v040 + +import ( + "encoding/binary" + "fmt" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + v040auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v040" +) + +const ( + // ModuleName is the name of the module + ModuleName = "gov" + + // StoreKey is the store key string for gov + StoreKey = ModuleName + + // RouterKey is the message route for gov + RouterKey = ModuleName + + // QuerierRoute is the querier route for gov + QuerierRoute = ModuleName +) + +// Keys for governance store +// Items are stored with the following key: values +// +// - 0x00: Proposal +// +// - 0x01: activeProposalID +// +// - 0x02: inactiveProposalID +// +// - 0x03: nextProposalID +// +// - 0x10: Deposit +// +// - 0x20: Voter +var ( + ProposalsKeyPrefix = []byte{0x00} + ActiveProposalQueuePrefix = []byte{0x01} + InactiveProposalQueuePrefix = []byte{0x02} + ProposalIDKey = []byte{0x03} + + DepositsKeyPrefix = []byte{0x10} + + VotesKeyPrefix = []byte{0x20} +) + +var lenTime = len(sdk.FormatTimeBytes(time.Now())) + +// GetProposalIDBytes returns the byte representation of the proposalID +func GetProposalIDBytes(proposalID uint64) (proposalIDBz []byte) { + proposalIDBz = make([]byte, 8) + binary.BigEndian.PutUint64(proposalIDBz, proposalID) + return +} + +// GetProposalIDFromBytes returns proposalID in uint64 format from a byte array +func GetProposalIDFromBytes(bz []byte) (proposalID uint64) { + return binary.BigEndian.Uint64(bz) +} + +// ProposalKey gets a specific proposal from the store +func ProposalKey(proposalID uint64) []byte { + return append(ProposalsKeyPrefix, GetProposalIDBytes(proposalID)...) +} + +// ActiveProposalByTimeKey gets the active proposal queue key by endTime +func ActiveProposalByTimeKey(endTime time.Time) []byte { + return append(ActiveProposalQueuePrefix, sdk.FormatTimeBytes(endTime)...) +} + +// ActiveProposalQueueKey returns the key for a proposalID in the activeProposalQueue +func ActiveProposalQueueKey(proposalID uint64, endTime time.Time) []byte { + return append(ActiveProposalByTimeKey(endTime), GetProposalIDBytes(proposalID)...) +} + +// InactiveProposalByTimeKey gets the inactive proposal queue key by endTime +func InactiveProposalByTimeKey(endTime time.Time) []byte { + return append(InactiveProposalQueuePrefix, sdk.FormatTimeBytes(endTime)...) +} + +// InactiveProposalQueueKey returns the key for a proposalID in the inactiveProposalQueue +func InactiveProposalQueueKey(proposalID uint64, endTime time.Time) []byte { + return append(InactiveProposalByTimeKey(endTime), GetProposalIDBytes(proposalID)...) +} + +// DepositsKey gets the first part of the deposits key based on the proposalID +func DepositsKey(proposalID uint64) []byte { + return append(DepositsKeyPrefix, GetProposalIDBytes(proposalID)...) +} + +// DepositKey key of a specific deposit from the store +func DepositKey(proposalID uint64, depositorAddr sdk.AccAddress) []byte { + return append(DepositsKey(proposalID), depositorAddr.Bytes()...) +} + +// VotesKey gets the first part of the votes key based on the proposalID +func VotesKey(proposalID uint64) []byte { + return append(VotesKeyPrefix, GetProposalIDBytes(proposalID)...) +} + +// VoteKey key of a specific vote from the store +func VoteKey(proposalID uint64, voterAddr sdk.AccAddress) []byte { + return append(VotesKey(proposalID), voterAddr.Bytes()...) +} + +// Split keys function; used for iterators + +// SplitProposalKey split the proposal key and returns the proposal id +func SplitProposalKey(key []byte) (proposalID uint64) { + if len(key[1:]) != 8 { + panic(fmt.Sprintf("unexpected key length (%d ≠ 8)", len(key[1:]))) + } + + return GetProposalIDFromBytes(key[1:]) +} + +// SplitActiveProposalQueueKey split the active proposal key and returns the proposal id and endTime +func SplitActiveProposalQueueKey(key []byte) (proposalID uint64, endTime time.Time) { + return splitKeyWithTime(key) +} + +// SplitInactiveProposalQueueKey split the inactive proposal key and returns the proposal id and endTime +func SplitInactiveProposalQueueKey(key []byte) (proposalID uint64, endTime time.Time) { + return splitKeyWithTime(key) +} + +// SplitKeyDeposit split the deposits key and returns the proposal id and depositor address +func SplitKeyDeposit(key []byte) (proposalID uint64, depositorAddr sdk.AccAddress) { + return splitKeyWithAddress(key) +} + +// SplitKeyVote split the votes key and returns the proposal id and voter address +func SplitKeyVote(key []byte) (proposalID uint64, voterAddr sdk.AccAddress) { + return splitKeyWithAddress(key) +} + +// private functions + +func splitKeyWithTime(key []byte) (proposalID uint64, endTime time.Time) { + if len(key[1:]) != 8+lenTime { + panic(fmt.Sprintf("unexpected key length (%d ≠ %d)", len(key[1:]), lenTime+8)) + } + + endTime, err := sdk.ParseTimeBytes(key[1 : 1+lenTime]) + if err != nil { + panic(err) + } + + proposalID = GetProposalIDFromBytes(key[1+lenTime:]) + return +} + +func splitKeyWithAddress(key []byte) (proposalID uint64, addr sdk.AccAddress) { + if len(key[1:]) != 8+v040auth.AddrLen { + panic(fmt.Sprintf("unexpected key length (%d ≠ %d)", len(key), 8+v040auth.AddrLen)) + } + + proposalID = GetProposalIDFromBytes(key[1:9]) + addr = sdk.AccAddress(key[9:]) + return +} diff --git a/x/gov/legacy/v040/types.go b/x/gov/legacy/v040/types.go deleted file mode 100644 index 27f668b2e1aa..000000000000 --- a/x/gov/legacy/v040/types.go +++ /dev/null @@ -1,6 +0,0 @@ -package v040 - -// Default parameter values -const ( - ModuleName = "gov" -) diff --git a/x/gov/legacy/v042/store.go b/x/gov/legacy/v042/store.go new file mode 100644 index 000000000000..acf824a16139 --- /dev/null +++ b/x/gov/legacy/v042/store.go @@ -0,0 +1,43 @@ +package v042 + +import ( + "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" + v040gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v040" +) + +const proposalIDLen = 8 + +// migratePrefixProposalAddress is a helper function that migrates all keys of format: +// +// into format: +// +func migratePrefixProposalAddress(store sdk.KVStore, prefixBz []byte) { + oldStore := prefix.NewStore(store, prefixBz) + + oldStoreIter := oldStore.Iterator(nil, nil) + defer oldStoreIter.Close() + + for ; oldStoreIter.Valid(); oldStoreIter.Next() { + proposalID := oldStoreIter.Key()[:proposalIDLen] + addr := oldStoreIter.Key()[proposalIDLen:] + newStoreKey := append(append(prefixBz, proposalID...), address.MustLengthPrefix(addr)...) + + // Set new key on store. Values don't change. + store.Set(newStoreKey, oldStoreIter.Value()) + oldStore.Delete(oldStoreIter.Key()) + } +} + +// MigrateStore performs in-place store migrations from v0.40 to v0.42. The +// migration includes: +// +// - Change addresses to be length-prefixed. +func MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey) error { + store := ctx.KVStore(storeKey) + migratePrefixProposalAddress(store, v040gov.DepositsKeyPrefix) + migratePrefixProposalAddress(store, v040gov.VotesKeyPrefix) + + return nil +} diff --git a/x/gov/legacy/v042/store_test.go b/x/gov/legacy/v042/store_test.go new file mode 100644 index 000000000000..6bcb056a9c99 --- /dev/null +++ b/x/gov/legacy/v042/store_test.go @@ -0,0 +1,85 @@ +package v042_test + +import ( + "bytes" + "testing" + "time" + + "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" + v040gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v040" + v042gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v042" + "github.com/cosmos/cosmos-sdk/x/gov/types" +) + +func TestStoreMigration(t *testing.T) { + govKey := sdk.NewKVStoreKey("gov") + ctx := testutil.DefaultContext(govKey, sdk.NewTransientStoreKey("transient_test")) + store := ctx.KVStore(govKey) + + _, _, addr1 := testdata.KeyTestPubAddr() + proposalID := uint64(6) + now := time.Now() + // Use dummy value for all keys. + value := []byte("foo") + + testCases := []struct { + name string + oldKey []byte + newKey []byte + }{ + { + "ProposalKey", + v040gov.ProposalKey(proposalID), + types.ProposalKey(proposalID), + }, + { + "ActiveProposalQueue", + v040gov.ActiveProposalQueueKey(proposalID, now), + types.ActiveProposalQueueKey(proposalID, now), + }, + { + "InactiveProposalQueue", + v040gov.InactiveProposalQueueKey(proposalID, now), + types.InactiveProposalQueueKey(proposalID, now), + }, + { + "ProposalIDKey", + v040gov.ProposalIDKey, + types.ProposalIDKey, + }, + { + "DepositKey", + v040gov.DepositKey(proposalID, addr1), + types.DepositKey(proposalID, addr1), + }, + { + "VotesKeyPrefix", + v040gov.VoteKey(proposalID, addr1), + types.VoteKey(proposalID, addr1), + }, + } + + // Set all the old keys to the store + for _, tc := range testCases { + store.Set(tc.oldKey, value) + } + + // Run migrations. + err := v042gov.MigrateStore(ctx, govKey) + require.NoError(t, err) + + // Make sure the new keys are set and old keys are deleted. + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + if bytes.Compare(tc.oldKey, tc.newKey) != 0 { + require.Nil(t, store.Get(tc.oldKey)) + } + require.Equal(t, value, store.Get(tc.newKey)) + }) + } +} diff --git a/x/gov/module.go b/x/gov/module.go index 30ce817e70d4..5e24cda3ab13 100644 --- a/x/gov/module.go +++ b/x/gov/module.go @@ -157,6 +157,9 @@ func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sd func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) types.RegisterQueryServer(cfg.QueryServer(), am.keeper) + + m := keeper.NewMigrator(am.keeper) + cfg.RegisterMigration(types.ModuleName, 1, m.Migrate1to2) } // InitGenesis performs genesis initialization for the gov module. It returns @@ -176,7 +179,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json } // ConsensusVersion implements AppModule/ConsensusVersion. -func (AppModule) ConsensusVersion() uint64 { return 1 } +func (AppModule) ConsensusVersion() uint64 { return 2 } // BeginBlock performs a no-op. func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} diff --git a/x/slashing/keeper/migrations.go b/x/slashing/keeper/migrations.go new file mode 100644 index 000000000000..b1bda4ab648e --- /dev/null +++ b/x/slashing/keeper/migrations.go @@ -0,0 +1,21 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + v042 "github.com/cosmos/cosmos-sdk/x/slashing/legacy/v042" +) + +// Migrator is a struct for handling in-place store migrations. +type Migrator struct { + keeper Keeper +} + +// NewMigrator returns a new Migrator. +func NewMigrator(keeper Keeper) Migrator { + return Migrator{keeper: keeper} +} + +// Migrate1to2 migrates from version 1 to 2. +func (m Migrator) Migrate1to2(ctx sdk.Context) error { + return v042.MigrateStore(ctx, m.keeper.storeKey) +} diff --git a/x/slashing/legacy/v040/keys.go b/x/slashing/legacy/v040/keys.go new file mode 100644 index 000000000000..02cefbc4525e --- /dev/null +++ b/x/slashing/legacy/v040/keys.go @@ -0,0 +1,69 @@ +// Package v040 is copy-pasted from: +// https://github.com/cosmos/cosmos-sdk/blob/v0.41.0/x/slashing/types/keys.go +package v040 + +import ( + "encoding/binary" + + sdk "github.com/cosmos/cosmos-sdk/types" + v040auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v040" +) + +const ( + // ModuleName is the name of the module + ModuleName = "slashing" + + // StoreKey is the store key string for slashing + StoreKey = ModuleName + + // RouterKey is the message route for slashing + RouterKey = ModuleName + + // QuerierRoute is the querier route for slashing + QuerierRoute = ModuleName +) + +// Keys for slashing store +// Items are stored with the following key: values +// +// - 0x01: ValidatorSigningInfo +// +// - 0x02: bool +// +// - 0x03: crypto.PubKey +var ( + ValidatorSigningInfoKeyPrefix = []byte{0x01} // Prefix for signing info + ValidatorMissedBlockBitArrayKeyPrefix = []byte{0x02} // Prefix for missed block bit array + AddrPubkeyRelationKeyPrefix = []byte{0x03} // Prefix for address-pubkey relation +) + +// ValidatorSigningInfoKey - stored by *Consensus* address (not operator address) +func ValidatorSigningInfoKey(v sdk.ConsAddress) []byte { + return append(ValidatorSigningInfoKeyPrefix, 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) != v040auth.AddrLen { + panic("unexpected key length") + } + return sdk.ConsAddress(addr) +} + +// ValidatorMissedBlockBitArrayPrefixKey - stored by *Consensus* address (not operator address) +func ValidatorMissedBlockBitArrayPrefixKey(v sdk.ConsAddress) []byte { + return append(ValidatorMissedBlockBitArrayKeyPrefix, 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...) +} diff --git a/x/slashing/legacy/v040/types.go b/x/slashing/legacy/v040/types.go deleted file mode 100644 index b95fa6fe2445..000000000000 --- a/x/slashing/legacy/v040/types.go +++ /dev/null @@ -1,5 +0,0 @@ -package v040 - -const ( - ModuleName = "slashing" -) diff --git a/x/slashing/legacy/v042/store.go b/x/slashing/legacy/v042/store.go new file mode 100644 index 000000000000..7864087b10ff --- /dev/null +++ b/x/slashing/legacy/v042/store.go @@ -0,0 +1,20 @@ +package v042 + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + v042distribution "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v042" + v040slashing "github.com/cosmos/cosmos-sdk/x/slashing/legacy/v040" +) + +// MigrateStore performs in-place store migrations from v0.40 to v0.42. The +// migration includes: +// +// - Change addresses to be length-prefixed. +func MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey) error { + store := ctx.KVStore(storeKey) + v042distribution.MigratePrefixAddress(store, v040slashing.ValidatorSigningInfoKeyPrefix) + v042distribution.MigratePrefixAddressBytes(store, v040slashing.ValidatorMissedBlockBitArrayKeyPrefix) + v042distribution.MigratePrefixAddress(store, v040slashing.AddrPubkeyRelationKeyPrefix) + + return nil +} diff --git a/x/slashing/legacy/v042/store_test.go b/x/slashing/legacy/v042/store_test.go new file mode 100644 index 000000000000..60bf43a27b84 --- /dev/null +++ b/x/slashing/legacy/v042/store_test.go @@ -0,0 +1,68 @@ +package v042_test + +import ( + "bytes" + "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" + v040slashing "github.com/cosmos/cosmos-sdk/x/slashing/legacy/v040" + v042slashing "github.com/cosmos/cosmos-sdk/x/slashing/legacy/v042" + "github.com/cosmos/cosmos-sdk/x/slashing/types" +) + +func TestStoreMigration(t *testing.T) { + slashingKey := sdk.NewKVStoreKey("slashing") + ctx := testutil.DefaultContext(slashingKey, sdk.NewTransientStoreKey("transient_test")) + store := ctx.KVStore(slashingKey) + + _, _, addr1 := testdata.KeyTestPubAddr() + consAddr := sdk.ConsAddress(addr1) + // Use dummy value for all keys. + value := []byte("foo") + + testCases := []struct { + name string + oldKey []byte + newKey []byte + }{ + { + "ValidatorSigningInfoKey", + v040slashing.ValidatorSigningInfoKey(consAddr), + types.ValidatorSigningInfoKey(consAddr), + }, + { + "ValidatorMissedBlockBitArrayKey", + v040slashing.ValidatorMissedBlockBitArrayKey(consAddr, 2), + types.ValidatorMissedBlockBitArrayKey(consAddr, 2), + }, + { + "AddrPubkeyRelationKey", + v040slashing.AddrPubkeyRelationKey(consAddr), + types.AddrPubkeyRelationKey(consAddr), + }, + } + + // Set all the old keys to the store + for _, tc := range testCases { + store.Set(tc.oldKey, value) + } + + // Run migrations. + err := v042slashing.MigrateStore(ctx, slashingKey) + require.NoError(t, err) + + // Make sure the new keys are set and old keys are deleted. + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + if bytes.Compare(tc.oldKey, tc.newKey) != 0 { + require.Nil(t, store.Get(tc.oldKey)) + } + require.Equal(t, value, store.Get(tc.newKey)) + }) + } +} diff --git a/x/slashing/module.go b/x/slashing/module.go index a1b99e044186..69e96b49d68d 100644 --- a/x/slashing/module.go +++ b/x/slashing/module.go @@ -139,6 +139,9 @@ func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sd func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) types.RegisterQueryServer(cfg.QueryServer(), am.keeper) + + m := keeper.NewMigrator(am.keeper) + cfg.RegisterMigration(types.ModuleName, 1, m.Migrate1to2) } // InitGenesis performs genesis initialization for the slashing module. It returns diff --git a/x/slashing/spec/02_state.md b/x/slashing/spec/02_state.md index 3644ff9651e9..8b2755a180b5 100644 --- a/x/slashing/spec/02_state.md +++ b/x/slashing/spec/02_state.md @@ -27,8 +27,8 @@ 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 -> ProtocolBuffer(ValSigningInfo)` -- MissedBlocksBitArray: ` 0x02 | ConsAddress | LittleEndianUint64(signArrayIndex) -> VarInt(didMiss)` (varint is a number encoding format) +- ValidatorSigningInfo: ` 0x01 | ConsAddrLen (1 byte) | ConsAddress -> ProtocolBuffer(ValSigningInfo)` +- MissedBlocksBitArray: ` 0x02 | ConsAddrLen (1 byte) | 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. diff --git a/x/staking/keeper/migrations.go b/x/staking/keeper/migrations.go new file mode 100644 index 000000000000..948f93ed67af --- /dev/null +++ b/x/staking/keeper/migrations.go @@ -0,0 +1,21 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + v042 "github.com/cosmos/cosmos-sdk/x/staking/legacy/v042" +) + +// Migrator is a struct for handling in-place store migrations. +type Migrator struct { + keeper Keeper +} + +// NewMigrator returns a new Migrator. +func NewMigrator(keeper Keeper) Migrator { + return Migrator{keeper: keeper} +} + +// Migrate1to2 migrates from version 1 to 2. +func (m Migrator) Migrate1to2(ctx sdk.Context) error { + return v042.MigrateStore(ctx, m.keeper.storeKey) +} diff --git a/x/staking/legacy/v040/keys.go b/x/staking/legacy/v040/keys.go new file mode 100644 index 000000000000..8c074a1ed097 --- /dev/null +++ b/x/staking/legacy/v040/keys.go @@ -0,0 +1,330 @@ +// Package v040 is copy-pasted from: +// https://github.com/cosmos/cosmos-sdk/blob/v0.41.0/x/staking/types/keys.go +package v040 + +import ( + "bytes" + "encoding/binary" + "fmt" + "strconv" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + v040auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v040" + "github.com/cosmos/cosmos-sdk/x/staking/types" +) + +const ( + // ModuleName is the name of the staking module + ModuleName = "staking" + + // StoreKey is the string store representation + StoreKey = ModuleName + + // QuerierRoute is the querier route for the staking module + QuerierRoute = ModuleName + + // RouterKey is the msg router key for the staking module + RouterKey = ModuleName +) + +var ( + // Keys for store prefixes + // Last* values are constant during a block. + LastValidatorPowerKey = []byte{0x11} // prefix for each key to a validator index, for bonded validators + LastTotalPowerKey = []byte{0x12} // prefix for the total power + + ValidatorsKey = []byte{0x21} // prefix for each key to a validator + ValidatorsByConsAddrKey = []byte{0x22} // prefix for each key to a validator index, by pubkey + ValidatorsByPowerIndexKey = []byte{0x23} // prefix for each key to a validator index, sorted by power + + DelegationKey = []byte{0x31} // key for a delegation + UnbondingDelegationKey = []byte{0x32} // key for an unbonding-delegation + UnbondingDelegationByValIndexKey = []byte{0x33} // prefix for each key for an unbonding-delegation, by validator operator + RedelegationKey = []byte{0x34} // key for a redelegation + RedelegationByValSrcIndexKey = []byte{0x35} // prefix for each key for an redelegation, by source validator operator + RedelegationByValDstIndexKey = []byte{0x36} // prefix for each key for an redelegation, by destination validator operator + + UnbondingQueueKey = []byte{0x41} // prefix for the timestamps in unbonding queue + RedelegationQueueKey = []byte{0x42} // prefix for the timestamps in redelegations queue + ValidatorQueueKey = []byte{0x43} // prefix for the timestamps in validator queue + + HistoricalInfoKey = []byte{0x50} // prefix for the historical info +) + +// gets the key for the validator with address +// VALUE: staking/Validator +func GetValidatorKey(operatorAddr sdk.ValAddress) []byte { + return append(ValidatorsKey, operatorAddr.Bytes()...) +} + +// gets the key for the validator with pubkey +// VALUE: validator operator address ([]byte) +func GetValidatorByConsAddrKey(addr sdk.ConsAddress) []byte { + return append(ValidatorsByConsAddrKey, addr.Bytes()...) +} + +// Get the validator operator address from LastValidatorPowerKey +func AddressFromLastValidatorPowerKey(key []byte) []byte { + return key[1:] // remove prefix bytes +} + +// get 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) +func GetValidatorsByPowerIndexKey(validator types.Validator) []byte { + // NOTE the address doesn't need to be stored because counter bytes must always be different + // NOTE the larger values are of higher value + + consensusPower := sdk.TokensToConsensusPower(validator.Tokens) + consensusPowerBytes := make([]byte, 8) + binary.BigEndian.PutUint64(consensusPowerBytes, uint64(consensusPower)) + + powerBytes := consensusPowerBytes + powerBytesLen := len(powerBytes) // 8 + + // key is of format prefix || powerbytes || addrBytes + key := make([]byte, 1+powerBytesLen+v040auth.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) + + for i, b := range operAddrInvr { + operAddrInvr[i] = ^b + } + + copy(key[powerBytesLen+1:], operAddrInvr) + + return key +} + +// get the bonded validator index key for an operator address +func GetLastValidatorPowerKey(operator sdk.ValAddress) []byte { + return append(LastValidatorPowerKey, operator...) +} + +// parse the validators operator address from power rank key +func ParseValidatorPowerRankKey(key []byte) (operAddr []byte) { + powerBytesLen := 8 + if len(key) != 1+powerBytesLen+v040auth.AddrLen { + panic("Invalid validator power rank key length") + } + + operAddr = sdk.CopyBytes(key[powerBytesLen+1:]) + + for i, b := range operAddr { + operAddr[i] = ^b + } + + return operAddr +} + +// GetValidatorQueueKey returns the prefix key used for getting a set of unbonding +// validators whose unbonding completion occurs at the given time and height. +func GetValidatorQueueKey(timestamp time.Time, height int64) []byte { + heightBz := sdk.Uint64ToBigEndian(uint64(height)) + timeBz := sdk.FormatTimeBytes(timestamp) + timeBzL := len(timeBz) + prefixL := len(ValidatorQueueKey) + + bz := make([]byte, prefixL+8+timeBzL+8) + + // copy the prefix + copy(bz[:prefixL], ValidatorQueueKey) + + // copy the encoded time bytes length + copy(bz[prefixL:prefixL+8], sdk.Uint64ToBigEndian(uint64(timeBzL))) + + // copy the encoded time bytes + copy(bz[prefixL+8:prefixL+8+timeBzL], timeBz) + + // copy the encoded height + copy(bz[prefixL+8+timeBzL:], heightBz) + + return bz +} + +// ParseValidatorQueueKey returns the encoded time and height from a key created +// from GetValidatorQueueKey. +func ParseValidatorQueueKey(bz []byte) (time.Time, int64, error) { + prefixL := len(ValidatorQueueKey) + if prefix := bz[:prefixL]; !bytes.Equal(prefix, ValidatorQueueKey) { + return time.Time{}, 0, fmt.Errorf("invalid prefix; expected: %X, got: %X", ValidatorQueueKey, prefix) + } + + timeBzL := sdk.BigEndianToUint64(bz[prefixL : prefixL+8]) + ts, err := sdk.ParseTimeBytes(bz[prefixL+8 : prefixL+8+int(timeBzL)]) + if err != nil { + return time.Time{}, 0, err + } + + height := sdk.BigEndianToUint64(bz[prefixL+8+int(timeBzL):]) + + return ts, int64(height), nil +} + +// gets 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()...) +} + +// gets the prefix for a delegator for all validators +func GetDelegationsKey(delAddr sdk.AccAddress) []byte { + return append(DelegationKey, delAddr.Bytes()...) +} + +// gets 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()...) +} + +// gets 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()...) +} + +// rearranges the ValIndexKey to get the UBDKey +func GetUBDKeyFromValIndexKey(indexKey []byte) []byte { + addrs := indexKey[1:] // remove prefix bytes + if len(addrs) != 2*v040auth.AddrLen { + panic("unexpected key length") + } + + valAddr := addrs[:v040auth.AddrLen] + delAddr := addrs[v040auth.AddrLen:] + + return GetUBDKey(delAddr, valAddr) +} + +// gets the prefix for all unbonding delegations from a delegator +func GetUBDsKey(delAddr sdk.AccAddress) []byte { + return append(UnbondingDelegationKey, delAddr.Bytes()...) +} + +// gets the prefix keyspace for the indexes of unbonding delegations for a validator +func GetUBDsByValIndexKey(valAddr sdk.ValAddress) []byte { + return append(UnbondingDelegationByValIndexKey, valAddr.Bytes()...) +} + +// gets the prefix for all unbonding delegations from a delegator +func GetUnbondingDelegationTimeKey(timestamp time.Time) []byte { + bz := sdk.FormatTimeBytes(timestamp) + return append(UnbondingQueueKey, bz...) +} + +// 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+v040auth.AddrLen*3) + + copy(key[0:v040auth.AddrLen+1], GetREDsKey(delAddr.Bytes())) + copy(key[v040auth.AddrLen+1:2*v040auth.AddrLen+1], valSrcAddr.Bytes()) + copy(key[2*v040auth.AddrLen+1:3*v040auth.AddrLen+1], valDstAddr.Bytes()) + + return key +} + +// gets 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*v040auth.AddrLen) + copy(key[0:offset], REDSFromValsSrcKey) + copy(key[offset:offset+v040auth.AddrLen], delAddr.Bytes()) + copy(key[offset+v040auth.AddrLen:offset+2*v040auth.AddrLen], valDstAddr.Bytes()) + + return key +} + +// gets 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*v040auth.AddrLen) + copy(key[0:offset], REDSToValsDstKey) + copy(key[offset:offset+v040auth.AddrLen], delAddr.Bytes()) + copy(key[offset+v040auth.AddrLen:offset+2*v040auth.AddrLen], 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*v040auth.AddrLen+1 { + panic("unexpected key length") + } + + valSrcAddr := indexKey[1 : v040auth.AddrLen+1] + delAddr := indexKey[v040auth.AddrLen+1 : 2*v040auth.AddrLen+1] + valDstAddr := indexKey[2*v040auth.AddrLen+1 : 3*v040auth.AddrLen+1] + + 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*v040auth.AddrLen+1 { + panic("unexpected key length") + } + + valDstAddr := indexKey[1 : v040auth.AddrLen+1] + delAddr := indexKey[v040auth.AddrLen+1 : 2*v040auth.AddrLen+1] + valSrcAddr := indexKey[2*v040auth.AddrLen+1 : 3*v040auth.AddrLen+1] + + return GetREDKey(delAddr, valSrcAddr, valDstAddr) +} + +// GetRedelegationTimeKey returns a key prefix for indexing an unbonding +// redelegation based on a completion time. +func GetRedelegationTimeKey(timestamp time.Time) []byte { + bz := sdk.FormatTimeBytes(timestamp) + return append(RedelegationQueueKey, bz...) +} + +// GetREDsKey returns a key prefix for indexing a redelegation from a delegator +// address. +func GetREDsKey(delAddr sdk.AccAddress) []byte { + return append(RedelegationKey, delAddr.Bytes()...) +} + +// GetREDsFromValSrcIndexKey returns a key prefix for indexing a redelegation to +// a source validator. +func GetREDsFromValSrcIndexKey(valSrcAddr sdk.ValAddress) []byte { + return append(RedelegationByValSrcIndexKey, valSrcAddr.Bytes()...) +} + +// 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()...) +} + +// 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()...) +} + +// GetHistoricalInfoKey returns a key prefix for indexing HistoricalInfo objects. +func GetHistoricalInfoKey(height int64) []byte { + return append(HistoricalInfoKey, []byte(strconv.FormatInt(height, 10))...) +} diff --git a/x/staking/legacy/v040/types.go b/x/staking/legacy/v040/types.go deleted file mode 100644 index 6ad280e277e5..000000000000 --- a/x/staking/legacy/v040/types.go +++ /dev/null @@ -1,5 +0,0 @@ -package v040 - -const ( - ModuleName = "staking" -) diff --git a/x/staking/legacy/v042/store.go b/x/staking/legacy/v042/store.go new file mode 100644 index 000000000000..2be604e66099 --- /dev/null +++ b/x/staking/legacy/v042/store.go @@ -0,0 +1,78 @@ +package v042 + +import ( + "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" + v040auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v040" + v042distribution "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v042" + v040staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v040" + "github.com/cosmos/cosmos-sdk/x/staking/types" +) + +// migratePrefixAddressAddressAddress is a helper function that migrates all keys of format: +// prefix_bytes | address_1_bytes | address_2_bytes | address_3_bytes +// into format: +// prefix_bytes | address_1_len (1 byte) | address_1_bytes | address_2_len (1 byte) | address_2_bytes | address_3_len (1 byte) | address_3_bytes +func migratePrefixAddressAddressAddress(store sdk.KVStore, prefixBz []byte) { + oldStore := prefix.NewStore(store, prefixBz) + + oldStoreIter := oldStore.Iterator(nil, nil) + defer oldStoreIter.Close() + + for ; oldStoreIter.Valid(); oldStoreIter.Next() { + addr1 := oldStoreIter.Key()[:v040auth.AddrLen] + addr2 := oldStoreIter.Key()[v040auth.AddrLen : 2*v040auth.AddrLen] + addr3 := oldStoreIter.Key()[2*v040auth.AddrLen:] + newStoreKey := append(append(append( + prefixBz, + address.MustLengthPrefix(addr1)...), address.MustLengthPrefix(addr2)...), address.MustLengthPrefix(addr3)..., + ) + + // Set new key on store. Values don't change. + store.Set(newStoreKey, oldStoreIter.Value()) + oldStore.Delete(oldStoreIter.Key()) + } +} + +const powerBytesLen = 8 + +func migrateValidatorsByPowerIndexKey(store sdk.KVStore) { + oldStore := prefix.NewStore(store, v040staking.ValidatorsByPowerIndexKey) + + oldStoreIter := oldStore.Iterator(nil, nil) + defer oldStoreIter.Close() + + for ; oldStoreIter.Valid(); oldStoreIter.Next() { + powerBytes := oldStoreIter.Key()[:powerBytesLen] + valAddr := oldStoreIter.Key()[powerBytesLen:] + newStoreKey := append(append(types.ValidatorsByPowerIndexKey, powerBytes...), address.MustLengthPrefix(valAddr)...) + + // Set new key on store. Values don't change. + store.Set(newStoreKey, oldStoreIter.Value()) + oldStore.Delete(oldStoreIter.Key()) + } +} + +// MigrateStore performs in-place store migrations from v0.40 to v0.42. The +// migration includes: +// +// - Change addresses to be length-prefixed. +func MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey) error { + store := ctx.KVStore(storeKey) + + v042distribution.MigratePrefixAddress(store, v040staking.LastValidatorPowerKey) + + v042distribution.MigratePrefixAddress(store, v040staking.ValidatorsKey) + v042distribution.MigratePrefixAddress(store, v040staking.ValidatorsByConsAddrKey) + migrateValidatorsByPowerIndexKey(store) + + v042distribution.MigratePrefixAddressAddress(store, v040staking.DelegationKey) + v042distribution.MigratePrefixAddressAddress(store, v040staking.UnbondingDelegationKey) + v042distribution.MigratePrefixAddressAddress(store, v040staking.UnbondingDelegationByValIndexKey) + migratePrefixAddressAddressAddress(store, v040staking.RedelegationKey) + migratePrefixAddressAddressAddress(store, v040staking.RedelegationByValSrcIndexKey) + migratePrefixAddressAddressAddress(store, v040staking.RedelegationByValDstIndexKey) + + return nil +} diff --git a/x/staking/legacy/v042/store_test.go b/x/staking/legacy/v042/store_test.go new file mode 100644 index 000000000000..963ef02ed9c9 --- /dev/null +++ b/x/staking/legacy/v042/store_test.go @@ -0,0 +1,137 @@ +package v042_test + +import ( + "bytes" + "testing" + "time" + + "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" + v040staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v040" + v042staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v042" + "github.com/cosmos/cosmos-sdk/x/staking/teststaking" + "github.com/cosmos/cosmos-sdk/x/staking/types" +) + +func TestStoreMigration(t *testing.T) { + stakingKey := sdk.NewKVStoreKey("staking") + ctx := testutil.DefaultContext(stakingKey, sdk.NewTransientStoreKey("transient_test")) + store := ctx.KVStore(stakingKey) + + _, pk1, addr1 := testdata.KeyTestPubAddr() + valAddr1 := sdk.ValAddress(addr1) + val := teststaking.NewValidator(t, valAddr1, pk1) + _, pk1, addr2 := testdata.KeyTestPubAddr() + valAddr2 := sdk.ValAddress(addr2) + _, _, addr3 := testdata.KeyTestPubAddr() + consAddr := sdk.ConsAddress(addr3.String()) + _, _, addr4 := testdata.KeyTestPubAddr() + now := time.Now() + // Use dummy value for all keys. + value := []byte("foo") + + testCases := []struct { + name string + oldKey []byte + newKey []byte + }{ + { + "LastValidatorPowerKey", + v040staking.GetLastValidatorPowerKey(valAddr1), + types.GetLastValidatorPowerKey(valAddr1), + }, + { + "LastTotalPowerKey", + v040staking.LastTotalPowerKey, + types.LastTotalPowerKey, + }, + { + "ValidatorsKey", + v040staking.GetValidatorKey(valAddr1), + types.GetValidatorKey(valAddr1), + }, + { + "ValidatorsByConsAddrKey", + v040staking.GetValidatorByConsAddrKey(consAddr), + types.GetValidatorByConsAddrKey(consAddr), + }, + { + "ValidatorsByPowerIndexKey", + v040staking.GetValidatorsByPowerIndexKey(val), + types.GetValidatorsByPowerIndexKey(val), + }, + { + "DelegationKey", + v040staking.GetDelegationKey(addr4, valAddr1), + types.GetDelegationKey(addr4, valAddr1), + }, + { + "UnbondingDelegationKey", + v040staking.GetUBDKey(addr4, valAddr1), + types.GetUBDKey(addr4, valAddr1), + }, + { + "UnbondingDelegationByValIndexKey", + v040staking.GetUBDByValIndexKey(addr4, valAddr1), + types.GetUBDByValIndexKey(addr4, valAddr1), + }, + { + "RedelegationKey", + v040staking.GetREDKey(addr4, valAddr1, valAddr2), + types.GetREDKey(addr4, valAddr1, valAddr2), + }, + { + "RedelegationByValSrcIndexKey", + v040staking.GetREDByValSrcIndexKey(addr4, valAddr1, valAddr2), + types.GetREDByValSrcIndexKey(addr4, valAddr1, valAddr2), + }, + { + "RedelegationByValDstIndexKey", + v040staking.GetREDByValDstIndexKey(addr4, valAddr1, valAddr2), + types.GetREDByValDstIndexKey(addr4, valAddr1, valAddr2), + }, + { + "UnbondingQueueKey", + v040staking.GetUnbondingDelegationTimeKey(now), + types.GetUnbondingDelegationTimeKey(now), + }, + { + "RedelegationQueueKey", + v040staking.GetRedelegationTimeKey(now), + types.GetRedelegationTimeKey(now), + }, + { + "ValidatorQueueKey", + v040staking.GetValidatorQueueKey(now, 4), + types.GetValidatorQueueKey(now, 4), + }, + { + "HistoricalInfoKey", + v040staking.GetHistoricalInfoKey(4), + types.GetHistoricalInfoKey(4), + }, + } + + // Set all the old keys to the store + for _, tc := range testCases { + store.Set(tc.oldKey, value) + } + + // Run migrations. + err := v042staking.MigrateStore(ctx, stakingKey) + require.NoError(t, err) + + // Make sure the new keys are set and old keys are deleted. + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + if bytes.Compare(tc.oldKey, tc.newKey) != 0 { + require.Nil(t, store.Get(tc.oldKey)) + } + require.Equal(t, value, store.Get(tc.newKey)) + }) + } +} diff --git a/x/staking/module.go b/x/staking/module.go index ea4033a2f8c3..067620cc6f38 100644 --- a/x/staking/module.go +++ b/x/staking/module.go @@ -138,6 +138,9 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) querier := keeper.Querier{Keeper: am.keeper} types.RegisterQueryServer(cfg.QueryServer(), querier) + + m := keeper.NewMigrator(am.keeper) + cfg.RegisterMigration(types.ModuleName, 1, m.Migrate1to2) } // InitGenesis performs genesis initialization for the staking module. It returns @@ -158,7 +161,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json } // ConsensusVersion implements AppModule/ConsensusVersion. -func (AppModule) ConsensusVersion() uint64 { return 1 } +func (AppModule) ConsensusVersion() uint64 { return 2 } // BeginBlock returns the begin blocker for the staking module. func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) { diff --git a/x/staking/spec/01_state.md b/x/staking/spec/01_state.md index e090acb01541..045bc5f35d44 100644 --- a/x/staking/spec/01_state.md +++ b/x/staking/spec/01_state.md @@ -44,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 -> ProtocolBuffer(validator)` -- ValidatorsByConsAddr: `0x22 | ConsAddr -> OperatorAddr` -- ValidatorsByPower: `0x23 | BigEndian(ConsensusPower) | OperatorAddr -> OperatorAddr` -- LastValidatorsPower: `0x11 OperatorAddr -> ProtocolBuffer(ConsensusPower)` +- Validators: `0x21 | OperatorAddrLen (1 byte) | OperatorAddr -> ProtocolBuffer(validator)` +- ValidatorsByConsAddr: `0x22 | ConsAddrLen (1 byte) | ConsAddr -> OperatorAddr` +- ValidatorsByPower: `0x23 | BigEndian(ConsensusPower) | OperatorAddrLen (1 byte) | OperatorAddr -> OperatorAddr` +- LastValidatorsPower: `0x11 | OperatorAddrLen (1 byte) | 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 @@ -79,7 +79,7 @@ Each validator's state is stored in a `Validator` struct: 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 -> ProtocolBuffer(delegation)` +- Delegation: `0x31 | DelegatorAddrLen (1 byte) | DelegatorAddr | ValidatorAddrLen (1 byte) | 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 @@ -115,8 +115,8 @@ detected. `UnbondingDelegation` are indexed in the store as: -- UnbondingDelegation: `0x32 | DelegatorAddr | ValidatorAddr -> ProtocolBuffer(unbondingDelegation)` -- UnbondingDelegationsFromValidator: `0x33 | ValidatorAddr | DelegatorAddr -> nil` +- UnbondingDelegation: `0x32 | DelegatorAddrLen (1 byte) | DelegatorAddr | ValidatorAddrLen (1 byte) | ValidatorAddr -> ProtocolBuffer(unbondingDelegation)` +- UnbondingDelegationsFromValidator: `0x33 | ValidatorAddrLen (1 byte) | ValidatorAddr | DelegatorAddrLen (1 byte) | 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 @@ -137,9 +137,9 @@ committed by the source validator. `Redelegation` are indexed in the store as: -- Redelegations: `0x34 | DelegatorAddr | ValidatorSrcAddr | ValidatorDstAddr -> ProtocolBuffer(redelegation)` -- RedelegationsBySrc: `0x35 | ValidatorSrcAddr | ValidatorDstAddr | DelegatorAddr -> nil` -- RedelegationsByDst: `0x36 | ValidatorDstAddr | ValidatorSrcAddr | DelegatorAddr -> nil` +- Redelegations: `0x34 | DelegatorAddrLen (1 byte) | DelegatorAddr | ValidatorAddrLen (1 byte) | ValidatorSrcAddr | ValidatorDstAddr -> ProtocolBuffer(redelegation)` +- RedelegationsBySrc: `0x35 | ValidatorSrcAddrLen (1 byte) | ValidatorSrcAddr | ValidatorDstAddrLen (1 byte) | ValidatorDstAddr | DelegatorAddrLen (1 byte) | DelegatorAddr -> nil` +- RedelegationsByDst: `0x36 | ValidatorDstAddrLen (1 byte) | ValidatorDstAddr | ValidatorSrcAddrLen (1 byte) | ValidatorSrcAddr | DelegatorAddrLen (1 byte) | DelegatorAddr -> nil` 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`, From 929b62cd4689f7353cff8a5d4324e67bb8e634c8 Mon Sep 17 00:00:00 2001 From: Emmanuel T Odeke Date: Thu, 25 Feb 2021 03:01:03 -0800 Subject: [PATCH 118/214] types: intern AccAddress.String() to gut wasted expensive recomputations (#8694) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Given that AccAddress is a []byte type, and its .String() method is quite expensive, continuously invoking the method doesn't easily provide a way for the result to be memoized. In memory profiles from benchmarking OneBankSendTxPerBlock and run for a while, it showed >2GiB burnt and SendCoins consuming a bunch of memory: >2GiB. This change introduces a simple global cache with a map to intern AccAddress values, so that we quickly look up the expensively computed values. With it, the prior memory profiles are erased, and benchmarks show improvements: ```shell $ benchstat before.txt after.txt name old time/op new time/op delta OneBankSendTxPerBlock-8 1.94ms ± 9% 1.92ms ±11% -1.34% (p=0.011 n=58+57) name old alloc/op new alloc/op delta OneBankSendTxPerBlock-8 428kB ± 0% 365kB ± 0% -14.67% (p=0.000 n=58+54) name old allocs/op new allocs/op delta OneBankSendTxPerBlock-8 6.34k ± 0% 5.90k ± 0% -7.06% (p=0.000 n=58+57) ``` Fixes #8693 Co-authored-by: Alessio Treglia --- types/address.go | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/types/address.go b/types/address.go index 9f3f8216051e..8e6a8103f3b0 100644 --- a/types/address.go +++ b/types/address.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "strings" + "sync" yaml "gopkg.in/yaml.v2" @@ -236,8 +237,28 @@ func (aa AccAddress) Bytes() []byte { return aa } +// AccAddress.String() is expensive and if unoptimized dominantly showed up in profiles, +// yet has no mechanisms to trivially cache the result given that AccAddress is a []byte type. +// With the string interning below, we are able to achieve zero cost allocations for string->[]byte +// because the Go compiler recognizes the special case of map[string([]byte)] when used exactly +// in that pattern. See https://github.com/cosmos/cosmos-sdk/issues/8693. +var addMu sync.Mutex +var addrStrMemoize = make(map[string]string) + // String implements the Stringer interface. -func (aa AccAddress) String() string { +func (aa AccAddress) String() (str string) { + addMu.Lock() + defer addMu.Unlock() + + if str, ok := addrStrMemoize[string(aa)]; ok { + return str + } + + // Otherwise cache it for later memoization. + defer func() { + addrStrMemoize[string(aa)] = str + }() + if aa.Empty() { return "" } From 96587cf3c2bedd9b332f2bc288d24ddbe2d513ee Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Feb 2021 12:59:36 +0000 Subject: [PATCH 119/214] build(deps): bump google.golang.org/grpc from 1.35.0 to 1.36.0 (#8696) Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.35.0 to 1.36.0. - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.35.0...v1.36.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 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 3f499cf7aebd..a5d7ef5bbb09 100644 --- a/go.mod +++ b/go.mod @@ -51,7 +51,7 @@ require ( 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 + google.golang.org/grpc v1.36.0 google.golang.org/protobuf v1.25.0 gopkg.in/ini.v1 v1.61.0 // indirect gopkg.in/yaml.v2 v2.4.0 From d51875b07eb8a3a32ad71714e3f46f2b953e7b45 Mon Sep 17 00:00:00 2001 From: Rikard Hjort <8545447+hjorthjort@users.noreply.github.com> Date: Thu, 25 Feb 2021 15:42:41 +0100 Subject: [PATCH 120/214] Updates and clarifications to the staking specs (#8675) --- x/staking/spec/01_state.md | 2 +- x/staking/spec/02_state_transitions.md | 33 +++++++++++++++++++++++--- x/staking/spec/03_messages.md | 9 ++++++- x/staking/spec/08_params.md | 2 +- 4 files changed, 40 insertions(+), 6 deletions(-) diff --git a/x/staking/spec/01_state.md b/x/staking/spec/01_state.md index 045bc5f35d44..66c6c0c5d61c 100644 --- a/x/staking/spec/01_state.md +++ b/x/staking/spec/01_state.md @@ -34,7 +34,7 @@ Validators can have one of three statuses 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`. + before moving their tokens to their accounts from the `BondedPool`. Validators objects should be primarily stored and accessed by the `OperatorAddr`, an SDK validator address for the operator of the validator. Two diff --git a/x/staking/spec/02_state_transitions.md b/x/staking/spec/02_state_transitions.md index 9e245719cc24..4a69769b95dd 100644 --- a/x/staking/spec/02_state_transitions.md +++ b/x/staking/spec/02_state_transitions.md @@ -105,6 +105,9 @@ Redelegations affect the delegation, source and destination validators. 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` +From when a redelegation begins until it completes, the delegator is in a state of "pseudo-unbonding", and can still be +slashed for infractions that occured before the redelegation began. + ### Complete Redelegation When a redelegations complete the following occurs: @@ -119,13 +122,17 @@ 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. -- Every unbonding delegation and redelegation from the validator are slashed by the `slashFactor` - percentage of the initialBalance. +- Every unbonding delegation and pseudo-unbonding redelegation such that the infraction occured before the unbonding or + redelegation began from the validator are slashed by the `slashFactor` percentage of the initialBalance. - Each amount slashed from redelegations and unbonding delegations is subtracted from the 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. +In the case of a slash due to any infraction that requires evidence to submitted (for example double-sign), the slash +occurs at the block where the evidence is included, not at the block where the infraction occured. +Put otherwise, validators are not slashed retroactively, only when they are caught. + ### Slash Unbonding Delegation When a validator is slashed, so are those unbonding delegations from the validator that began unbonding @@ -137,5 +144,25 @@ delegation and is capped to prevent a resulting negative balance. Completed (or When a validator is slashed, so are all redelegations from the validator that began after the infraction. Redelegations are slashed by `slashFactor`. +Redelegations that began before the infraction are not slashed. The amount slashed is calculated from the `InitialBalance` of the delegation and is capped to -prevent a resulting negative balance. Mature redelegations are not slashed. +prevent a resulting negative balance. +Mature redelegations (that have completed pseudo-unbonding) are not slashed. + +## How Shares are calculated + +At any given point in time, each validator has a number of tokens, `T`, and has a number of shares issued, `S`. +Each delegator, `i`, holds a number of shares, `S_i`. +The number of tokens is the sum of all tokens delegated to the validator, plus the rewards, minus the slashes. + +The delegator is entitled to a portion of the underlying tokens proportional to their proportion of shares. +So delegator `i` is entitled to `T * S_i / S` of the validator's tokens. + +When a delegator delegates new tokens to the validator, they receive a number of shares proportional to their contribution. +So when delegator `j` delegates `T_j` tokens, they receive `S_j = S * T_j / T` shares. +The total number of tokens is now `T + T_j`, and the total number of shares is `S + S_j`. +`j`s proportion of the shares is the same as their proportion of the total tokens contributed: `(S + S_j) / S = (T + T_j) / T`. + +A special case is the initial delegation, when `T = 0` and `S = 0`, so `T_j / T` is undefined. +For the initial delegation, delegator `j` who delegates `T_j` tokens receive `S_j = T_j` shares. +So a validator that hasn't received any rewards and has not been slashed will have `T = S`. diff --git a/x/staking/spec/03_messages.md b/x/staking/spec/03_messages.md index 1155da93d97d..d0f059ecf6b6 100644 --- a/x/staking/spec/03_messages.md +++ b/x/staking/spec/03_messages.md @@ -9,6 +9,7 @@ In this section we describe the processing of the staking messages and the corre ## Msg/CreateValidator A validator is created using the `Msg/CreateValidator` service message. +The validator must be created with an initial delegation from the operator. +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L16-L17 @@ -63,11 +64,17 @@ 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` +- the exchange rate is invalid, meaning the validator has no tokens (due to slashing) but there are outstanding shares +- the amount delegated is less than the minimum allowed delegation If an existing `Delegation` object for provided addresses does not already -exist than it is created as part of this service message otherwise the existing +exist then it is created as part of this message otherwise the existing `Delegation` is updated to include the newly received shares. +The delegator receives newly minted shares at the current exchange rate. +The exchange rate is the number of existing shares in the validator divided by +the number of currently delegated tokens. + ## Msg/Undelegate The `Msg/Undelegate` service message allows delegators to undelegate their tokens from diff --git a/x/staking/spec/08_params.md b/x/staking/spec/08_params.md index 3d87879e18a0..8d78efa5c51a 100644 --- a/x/staking/spec/08_params.md +++ b/x/staking/spec/08_params.md @@ -12,4 +12,4 @@ The staking module contains the following parameters: | MaxValidators | uint16 | 100 | | KeyMaxEntries | uint16 | 7 | | HistoricalEntries | uint16 | 3 | -| BondDenom | string | "uatom" | +| BondDenom | string | "stake" | From 5d3f29b0898bc571bc60a1d53e1e8835f7fb89da Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Thu, 25 Feb 2021 14:58:12 +0000 Subject: [PATCH 121/214] update tendermint to v0.34.8 (#8701) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a5d7ef5bbb09..e5d258eb4443 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.7 + github.com/tendermint/tendermint v0.34.8 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 d9e12cebd799..bf6adda80984 100644 --- a/go.sum +++ b/go.sum @@ -680,8 +680,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.7 h1:lvBJFNqpDuEzKfLZKtUXOL5dMOpqHonHlO6LCujyl6E= -github.com/tendermint/tendermint v0.34.7/go.mod h1:JVuu3V1ZexOaZG8VJMRl8lnfrGw6hEB2TVnoUwKRbss= +github.com/tendermint/tendermint v0.34.8 h1:PMWgUx47FrNTsfhxCWzoiIlVAC1SE9+WBlnsF9oQW0I= +github.com/tendermint/tendermint v0.34.8/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 19e79e00d6aea7e32562f58d1feba6a65a283634 Mon Sep 17 00:00:00 2001 From: Amaury <1293565+amaurym@users.noreply.github.com> Date: Thu, 25 Feb 2021 16:40:04 +0100 Subject: [PATCH 122/214] ADR-019/020 cleanups: HybridCodec, Pubkey (#8683) * wip adr019 * Remove hybrid codec * Change date * Update docs/architecture/adr-019-protobuf-state-encoding.md Co-authored-by: Robert Zaremba * Update pubkey interface Co-authored-by: Robert Zaremba Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- .../adr-019-protobuf-state-encoding.md | 23 +++++++++++-------- .../adr-020-protobuf-transaction-encoding.md | 3 ++- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/docs/architecture/adr-019-protobuf-state-encoding.md b/docs/architecture/adr-019-protobuf-state-encoding.md index 2a4d8b046258..e69621e66836 100644 --- a/docs/architecture/adr-019-protobuf-state-encoding.md +++ b/docs/architecture/adr-019-protobuf-state-encoding.md @@ -7,6 +7,7 @@ - 2020 Apr 27: Convert usages of `oneof` for interfaces to `Any` - 2020 May 15: Describe `cosmos_proto` extensions and amino compatibility - 2020 Dec 4: Move and rename `MarshalAny` and `UnmarshalAny` into the `codec.Marshaler` interface. +- 2021 Feb 24: Remove mentions of `HybridCodec`, which has been abandoned in [#6843](https://github.com/cosmos/cosmos-sdk/pull/6843). ## Status @@ -59,24 +60,26 @@ We will adopt [Protocol Buffers](https://developers.google.com/protocol-buffers) persisted structured data in the Cosmos SDK while providing a clean mechanism and developer UX for applications wishing to continue to use Amino. We will provide this mechanism by updating modules to accept a codec interface, `Marshaler`, instead of a concrete Amino codec. Furthermore, the Cosmos SDK -will provide three concrete implementations of the `Marshaler` interface: `AminoCodec`, `ProtoCodec`, -and `HybridCodec`. +will provide two concrete implementations of the `Marshaler` interface: `AminoCodec` and `ProtoCodec`. - `AminoCodec`: Uses Amino for both binary and JSON encoding. -- `ProtoCodec`: Uses Protobuf for or both binary and JSON encoding. -- `HybridCodec`: Uses Amino for JSON encoding and Protobuf for binary encoding. +- `ProtoCodec`: Uses Protobuf for both binary and JSON encoding. -Until the client migration landscape is fully understood and designed, modules will use a `HybridCodec` -as the concrete codec it accepts and/or extends. This means that all client JSON encoding, including -genesis state, will still use Amino. The ultimate goal will be to replace Amino JSON encoding with -Protbuf encoding and thus have modules accept and/or extend `ProtoCodec`. +Modules will use whichever codec that is instantiated in the app. By default, the SDK's `simapp` +instantiates a `ProtoCodec` as the concrete implementation of `Marshaler`, inside the `MakeTestEncodingConfig` +function. This can be easily overwritten by app developers if they so desire. + +The ultimate goal will be to replace Amino JSON encoding with Protobuf encoding and thus have +modules accept and/or extend `ProtoCodec`. Until then, Amino JSON is still provided for legacy use-cases. +A handful of places in the SDK still have Amino JSON hardcoded, such as the Legacy API REST endpoints +and the `x/params` store. They are planned to be converted to Protobuf in a gradual manner. ### Module Codecs Modules that do not require the ability to work with and serialize interfaces, the path to Protobuf migration is pretty straightforward. These modules are to simply migrate any existing types that are encoded and persisted via their concrete Amino codec to Protobuf and have their keeper accept a -`Marshaler` that will be a `HybridCodec`. This migration is simple as things will just work as-is. +`Marshaler` that will be a `ProtoCodec`. This migration is simple as things will just work as-is. Note, any business logic that needs to encode primitive types like `bool` or `int64` should use [gogoprotobuf](https://github.com/gogo/protobuf) Value types. @@ -207,7 +210,7 @@ Note that `InterfaceRegistry` usage does not deviate from standard protobuf usage of `Any`, it just introduces a security and introspection layer for golang usage. -`InterfaceRegistry` will be a member of `ProtoCodec` and `HybridCodec` as +`InterfaceRegistry` will be a member of `ProtoCodec` described above. In order for modules to register interface types, app modules can optionally implement the following interface: diff --git a/docs/architecture/adr-020-protobuf-transaction-encoding.md b/docs/architecture/adr-020-protobuf-transaction-encoding.md index 0c050c5d14bb..062dac13eb2b 100644 --- a/docs/architecture/adr-020-protobuf-transaction-encoding.md +++ b/docs/architecture/adr-020-protobuf-transaction-encoding.md @@ -12,6 +12,7 @@ - 2020 August 19: Move sequence field from `SignDoc` to `SignerInfo`, as discussed in [#6966](https://github.com/cosmos/cosmos-sdk/issues/6966). - 2020 September 25: Remove `PublicKey` type in favor of `secp256k1.PubKey`, `ed25519.PubKey` and `multisig.LegacyAminoPubKey`. - 2020 October 15: Add `GetAccount` and `GetAccountWithHeight` methods to the `AccountRetriever` interface. +- 2021 Feb 24: The SDK does not use Tendermint's `PubKey` interface anymore, but its own `cryptotypes.PubKey`. Updates to reflect this. ## Status @@ -286,7 +287,7 @@ and `FileDescriptor`s and returns a boolean result. ### Public Key Encoding -Public keys in the Cosmos SDK implement Tendermint's `crypto.PubKey` interface. +Public keys in the Cosmos SDK implement the `cryptotypes.PubKey` interface. We propose to use `Any` for protobuf encoding as we are doing with other interfaces (e.g. in `BaseAccount` `PubKey` or `SignerInfo` `PublicKey`). Following public keys are implemented: secp256k1, ed25519 and multisignature. From ef9968debd1fa4c492d7e1df6c8cf146c1ede6d0 Mon Sep 17 00:00:00 2001 From: Frojdi Dymylja <33157909+fdymylja@users.noreply.github.com> Date: Thu, 25 Feb 2021 19:15:02 +0100 Subject: [PATCH 123/214] [bank]: add balance tracking events (#8656) * change(bank): add utxo events and simplify logic * add(bank): balance and supply tracking test * chore(bank): fix balance tracking test comment * fix(grpc): service test * fix(bank): sub unlocked coins to use less gas * fix(auth): cli test gas * fix(rest): grpc gas test * fix(staking/cli): increase delegation required gas * add: burn events, fix tests * fix(auth/tx): grpc test * add(bank): coin events in delegate * fix(bank): add amt check in delegate coins back * change(bank): add coin spent and coin recv events in burn and mint * change(bank): revert sub coin function * change(auth): revert cli test * change(auth): revert service test * chore(auth): fix events comment in service_test.go * chore: update CHANGELOG.md * remove(bank): balanceError func * chore(bank): address lint warnings * chore(bank): update events spec Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- CHANGELOG.md | 1 + x/auth/client/cli/cli_test.go | 9 +- x/auth/tx/service_test.go | 9 +- x/bank/keeper/genesis_test.go | 4 +- x/bank/keeper/keeper.go | 26 +++-- x/bank/keeper/keeper_test.go | 129 +++++++++++++++++++--- x/bank/keeper/send.go | 29 +++-- x/bank/keeper/view.go | 16 ++- x/bank/spec/04_events.md | 120 ++++++++++++++++++++ x/bank/types/events.go | 55 +++++++++ x/staking/client/cli/cli_test.go | 10 +- x/staking/client/rest/grpc_query_test.go | 14 ++- x/staking/client/testutil/test_helpers.go | 2 + 13 files changed, 375 insertions(+), 49 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a5cc29513f54..feae9a1997ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,6 +58,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (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 +* (x/bank) [\#8656](https://github.com/cosmos/cosmos-sdk/pull/8656) balance and supply are now correctly tracked via `coin_spent`, `coin_received`, `coinbase` and `burn` events. ### Improvements diff --git a/x/auth/client/cli/cli_test.go b/x/auth/client/cli/cli_test.go index 6cd102cade97..6d9d776f1b03 100644 --- a/x/auth/client/cli/cli_test.go +++ b/x/auth/client/cli/cli_test.go @@ -1102,7 +1102,7 @@ func (s *IntegrationTestSuite) TestSignWithMultiSigners_AminoJSON() { banktypes.NewMsgSend(val1.Address, addr1, sdk.NewCoins(val1Coin)), ) txBuilder.SetFeeAmount(sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10)))) - txBuilder.SetGasLimit(testdata.NewTestGasLimit()) + txBuilder.SetGasLimit(testdata.NewTestGasLimit()) // min required is 101892 require.Equal([]sdk.AccAddress{val0.Address, val1.Address}, txBuilder.GetTx().GetSigners()) // Write the unsigned tx into a file. @@ -1126,7 +1126,12 @@ func (s *IntegrationTestSuite) TestSignWithMultiSigners_AminoJSON() { signedTxFile := testutil.WriteToNewTempFile(s.T(), signedTx.String()) // Now let's try to send this tx. - res, err := authtest.TxBroadcastExec(val0.ClientCtx, signedTxFile.Name(), fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock)) + res, err := authtest.TxBroadcastExec( + val0.ClientCtx, + signedTxFile.Name(), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + ) + require.NoError(err) var txRes sdk.TxResponse require.NoError(val0.ClientCtx.JSONMarshaler.UnmarshalJSON(res.Bytes(), &txRes)) diff --git a/x/auth/tx/service_test.go b/x/auth/tx/service_test.go index 4f5db8e9c99d..58b21c139772 100644 --- a/x/auth/tx/service_test.go +++ b/x/auth/tx/service_test.go @@ -5,13 +5,14 @@ import ( "fmt" "testing" + "github.com/cosmos/cosmos-sdk/testutil/testdata" + "github.com/stretchr/testify/suite" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" 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" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" query "github.com/cosmos/cosmos-sdk/types/query" @@ -106,7 +107,7 @@ func (s IntegrationTestSuite) TestSimulateTx_GRPC() { } else { s.Require().NoError(err) // Check the result and gas used are correct. - s.Require().Equal(len(res.GetResult().GetEvents()), 4) // 1 transfer, 3 messages. + s.Require().Equal(len(res.GetResult().GetEvents()), 6) // 1 coin recv 1 coin spent, 1 transfer, 3 messages. s.Require().True(res.GetGasInfo().GetGasUsed() > 0) // Gas used sometimes change, just check it's not empty. } }) @@ -143,7 +144,7 @@ func (s IntegrationTestSuite) TestSimulateTx_GRPCGateway() { err = val.ClientCtx.JSONMarshaler.UnmarshalJSON(res, &result) s.Require().NoError(err) // Check the result and gas used are correct. - s.Require().Equal(len(result.GetResult().GetEvents()), 4) // 1 transfer, 3 messages. + s.Require().Equal(len(result.GetResult().GetEvents()), 6) // 1 coin recv, 1 coin spent,1 transfer, 3 messages. s.Require().True(result.GetGasInfo().GetGasUsed() > 0) // Gas used sometimes change, just check it's not empty. } }) @@ -412,7 +413,7 @@ func (s IntegrationTestSuite) TestBroadcastTx_GRPCGateway() { var result tx.BroadcastTxResponse err = val.ClientCtx.JSONMarshaler.UnmarshalJSON(res, &result) s.Require().NoError(err) - s.Require().Equal(uint32(0), result.TxResponse.Code) + s.Require().Equal(uint32(0), result.TxResponse.Code, "rawlog", result.TxResponse.RawLog) } }) } diff --git a/x/bank/keeper/genesis_test.go b/x/bank/keeper/genesis_test.go index 7bf7dc920315..35e56c1295d1 100644 --- a/x/bank/keeper/genesis_test.go +++ b/x/bank/keeper/genesis_test.go @@ -25,8 +25,6 @@ func (suite *IntegrationTestSuite) TestExportGenesis() { Require(). NoError(app.BankKeeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, accAddr, expectedBalances[i].Coins)) } - // 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) @@ -34,6 +32,8 @@ func (suite *IntegrationTestSuite) TestExportGenesis() { suite.Require().Len(exportGenesis.Params.SendEnabled, 0) suite.Require().Equal(types.DefaultParams().DefaultSendEnabled, exportGenesis.Params.DefaultSendEnabled) suite.Require().Equal(totalSupply.Total, exportGenesis.Supply) + // add mint module balance as nil + expectedBalances = append(expectedBalances, types.Balance{Address: "cosmos1m3h30wlvsf8llruxtpukdvsy0km2kum8g38c8q", Coins: nil}) suite.Require().Equal(expectedBalances, exportGenesis.Balances) suite.Require().Equal(expectedMetadata, exportGenesis.DenomMetadata) } diff --git a/x/bank/keeper/keeper.go b/x/bank/keeper/keeper.go index 153d5d4a55d9..c65a3ab7c0f0 100644 --- a/x/bank/keeper/keeper.go +++ b/x/bank/keeper/keeper.go @@ -1,8 +1,6 @@ package keeper import ( - "time" - "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" @@ -107,9 +105,13 @@ func (k BaseKeeper) DelegateCoins(ctx sdk.Context, delegatorAddr, moduleAccAddr } } - if err := k.trackDelegation(ctx, delegatorAddr, ctx.BlockHeader().Time, balances, amt); err != nil { + if err := k.trackDelegation(ctx, delegatorAddr, balances, amt); err != nil { return sdkerrors.Wrap(err, "failed to track delegation") } + // emit coin spent event + ctx.EventManager().EmitEvent( + types.NewCoinSpentEvent(delegatorAddr, amt), + ) err := k.addCoins(ctx, moduleAccAddr, amt) if err != nil { @@ -134,7 +136,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.subUnlockedCoins(ctx, moduleAccAddr, amt) if err != nil { return err } @@ -345,6 +347,11 @@ func (k BaseKeeper) MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) logger := k.Logger(ctx) logger.Info("minted coins from module account", "amount", amt.String(), "from", moduleName) + // emit mint event + ctx.EventManager().EmitEvent( + types.NewCoinMintEvent(acc.GetAddress(), amt), + ) + return nil } @@ -360,7 +367,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.subUnlockedCoins(ctx, acc.GetAddress(), amt) if err != nil { return err } @@ -373,10 +380,15 @@ func (k BaseKeeper) BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) logger := k.Logger(ctx) logger.Info("burned tokens from module account", "amount", amt.String(), "from", moduleName) + // emit burn event + ctx.EventManager().EmitEvent( + types.NewCoinBurnEvent(acc.GetAddress(), amt), + ) + return nil } -func (k BaseKeeper) trackDelegation(ctx sdk.Context, addr sdk.AccAddress, blockTime time.Time, balance, amt sdk.Coins) error { +func (k BaseKeeper) trackDelegation(ctx sdk.Context, addr sdk.AccAddress, balance, amt sdk.Coins) error { acc := k.ak.GetAccount(ctx, addr) if acc == nil { return sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "account %s does not exist", addr) @@ -385,7 +397,7 @@ func (k BaseKeeper) trackDelegation(ctx sdk.Context, addr sdk.AccAddress, blockT vacc, ok := acc.(vestexported.VestingAccount) if ok { // TODO: return error on account.TrackDelegation - vacc.TrackDelegation(blockTime, balance, amt) + vacc.TrackDelegation(ctx.BlockHeader().Time, balance, amt) } return nil diff --git a/x/bank/keeper/keeper_test.go b/x/bank/keeper/keeper_test.go index 97d0b3a8769b..ffd4838d036b 100644 --- a/x/bank/keeper/keeper_test.go +++ b/x/bank/keeper/keeper_test.go @@ -153,17 +153,17 @@ func (suite *IntegrationTestSuite) TestSupply_SendCoins() { suite.Require().NoError( keeper.SendCoinsFromModuleToModule(ctx, holderAcc.GetName(), authtypes.Burner, initCoins), ) - suite.Require().Equal(sdk.Coins(nil), getCoinsByName(ctx, keeper, authKeeper, holderAcc.GetName())) + suite.Require().Equal(sdk.NewCoins().String(), getCoinsByName(ctx, keeper, authKeeper, holderAcc.GetName()).String()) suite.Require().Equal(initCoins, getCoinsByName(ctx, keeper, authKeeper, authtypes.Burner)) suite.Require().NoError( keeper.SendCoinsFromModuleToAccount(ctx, authtypes.Burner, baseAcc.GetAddress(), initCoins), ) - suite.Require().Equal(sdk.Coins(nil), getCoinsByName(ctx, keeper, authKeeper, authtypes.Burner)) + suite.Require().Equal(sdk.NewCoins().String(), getCoinsByName(ctx, keeper, authKeeper, authtypes.Burner).String()) suite.Require().Equal(initCoins, keeper.GetAllBalances(ctx, baseAcc.GetAddress())) suite.Require().NoError(keeper.SendCoinsFromAccountToModule(ctx, baseAcc.GetAddress(), authtypes.Burner, initCoins)) - suite.Require().Equal(sdk.Coins(nil), keeper.GetAllBalances(ctx, baseAcc.GetAddress())) + suite.Require().Equal(sdk.NewCoins().String(), keeper.GetAllBalances(ctx, baseAcc.GetAddress()).String()) suite.Require().Equal(initCoins, getCoinsByName(ctx, keeper, authKeeper, authtypes.Burner)) } @@ -266,7 +266,7 @@ func (suite *IntegrationTestSuite) TestSupply_BurnCoins() { 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(sdk.NewCoins().String(), getCoinsByName(ctx, keeper, authKeeper, authtypes.Burner).String()) suite.Require().Equal(supplyAfterInflation.GetTotal().Sub(initCoins), keeper.GetSupply(ctx).GetTotal()) // test same functionality on module account with multiple permissions @@ -280,7 +280,7 @@ func (suite *IntegrationTestSuite) TestSupply_BurnCoins() { 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(sdk.NewCoins().String(), getCoinsByName(ctx, keeper, authKeeper, multiPermAcc.GetName()).String()) suite.Require().Equal(supplyAfterInflation.GetTotal().Sub(initCoins), keeper.GetSupply(ctx).GetTotal()) } @@ -537,6 +537,7 @@ func (suite *IntegrationTestSuite) TestMsgSendEvents() { event1.Attributes, abci.EventAttribute{Key: []byte(sdk.AttributeKeyAmount), Value: []byte(newCoins.String())}, ) + event2 := sdk.Event{ Type: sdk.EventTypeMessage, Attributes: []abci.EventAttribute{}, @@ -556,9 +557,9 @@ func (suite *IntegrationTestSuite) TestMsgSendEvents() { // events are shifted due to the funding account events events = ctx.EventManager().ABCIEvents() - suite.Require().Equal(6, len(events)) - suite.Require().Equal(abci.Event(event1), events[4]) - suite.Require().Equal(abci.Event(event2), events[5]) + suite.Require().Equal(12, len(events)) + suite.Require().Equal(abci.Event(event1), events[8]) + suite.Require().Equal(abci.Event(event2), events[9]) } func (suite *IntegrationTestSuite) TestMsgMultiSendEvents() { @@ -597,7 +598,7 @@ func (suite *IntegrationTestSuite) TestMsgMultiSendEvents() { suite.Require().Error(app.BankKeeper.InputOutputCoins(ctx, inputs, outputs)) events = ctx.EventManager().ABCIEvents() - suite.Require().Equal(3, len(events)) // 3 events because minting event is there + suite.Require().Equal(8, len(events)) // 7 events because account funding causes extra minting + coin_spent + coin_recv events event1 := sdk.Event{ Type: sdk.EventTypeMessage, @@ -607,7 +608,7 @@ func (suite *IntegrationTestSuite) TestMsgMultiSendEvents() { event1.Attributes, abci.EventAttribute{Key: []byte(types.AttributeKeySender), Value: []byte(addr.String())}, ) - suite.Require().Equal(abci.Event(event1), events[2]) // it's the third event since we have the minting event before + suite.Require().Equal(abci.Event(event1), events[7]) // Set addr's coins and addr2's coins suite.Require().NoError(simapp.FundAccount(app, ctx, addr, sdk.NewCoins(sdk.NewInt64Coin(fooDenom, 50)))) @@ -619,7 +620,7 @@ func (suite *IntegrationTestSuite) TestMsgMultiSendEvents() { suite.Require().NoError(app.BankKeeper.InputOutputCoins(ctx, inputs, outputs)) events = ctx.EventManager().ABCIEvents() - suite.Require().Equal(11, len(events)) + suite.Require().Equal(28, len(events)) // 25 due to account funding + coin_spent + coin_recv events event2 := sdk.Event{ Type: sdk.EventTypeMessage, @@ -652,12 +653,11 @@ func (suite *IntegrationTestSuite) TestMsgMultiSendEvents() { event4.Attributes, abci.EventAttribute{Key: []byte(sdk.AttributeKeyAmount), Value: []byte(newCoins2.String())}, ) - // 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]) + suite.Require().Equal(abci.Event(event1), events[21]) + suite.Require().Equal(abci.Event(event2), events[23]) + suite.Require().Equal(abci.Event(event3), events[25]) + suite.Require().Equal(abci.Event(event4), events[27]) } func (suite *IntegrationTestSuite) TestSpendableCoins() { @@ -1002,6 +1002,103 @@ func (suite *IntegrationTestSuite) TestIterateAllDenomMetaData() { } } +func (suite *IntegrationTestSuite) TestBalanceTrackingEvents() { + // replace account keeper and bank keeper otherwise the account keeper won't be aware of the + // existence of the new module account because GetModuleAccount checks for the existence via + // permissions map and not via state... weird + maccPerms := simapp.GetMaccPerms() + maccPerms[multiPerm] = []string{authtypes.Burner, authtypes.Minter, authtypes.Staking} + + suite.app.AccountKeeper = authkeeper.NewAccountKeeper( + suite.app.AppCodec(), suite.app.GetKey(authtypes.StoreKey), suite.app.GetSubspace(authtypes.ModuleName), + authtypes.ProtoBaseAccount, maccPerms, + ) + + suite.app.BankKeeper = keeper.NewBaseKeeper(suite.app.AppCodec(), suite.app.GetKey(types.StoreKey), + suite.app.AccountKeeper, suite.app.GetSubspace(types.ModuleName), nil) + + // set account with multiple permissions + suite.app.AccountKeeper.SetModuleAccount(suite.ctx, multiPermAcc) + // mint coins + suite.Require().NoError( + suite.app.BankKeeper.MintCoins( + suite.ctx, + multiPermAcc.Name, + sdk.NewCoins(sdk.NewCoin("utxo", sdk.NewInt(100000)))), + ) + // send coins to address + addr1 := sdk.AccAddress("addr1_______________") + suite.Require().NoError( + suite.app.BankKeeper.SendCoinsFromModuleToAccount( + suite.ctx, + multiPermAcc.Name, + addr1, + sdk.NewCoins(sdk.NewCoin("utxo", sdk.NewInt(50000))), + ), + ) + + // burn coins from module account + suite.Require().NoError( + suite.app.BankKeeper.BurnCoins( + suite.ctx, + multiPermAcc.Name, + sdk.NewCoins(sdk.NewInt64Coin("utxo", 1000)), + ), + ) + + // process balances and supply from events + supply := sdk.NewCoins() + + balances := make(map[string]sdk.Coins) + + for _, e := range suite.ctx.EventManager().ABCIEvents() { + switch e.Type { + case types.EventTypeCoinBurn: + burnedCoins, err := sdk.ParseCoinsNormalized((string)(e.Attributes[1].Value)) + suite.Require().NoError(err) + supply = supply.Sub(burnedCoins) + + case types.EventTypeCoinMint: + mintedCoins, err := sdk.ParseCoinsNormalized((string)(e.Attributes[1].Value)) + suite.Require().NoError(err) + supply = supply.Add(mintedCoins...) + + case types.EventTypeCoinSpent: + coinsSpent, err := sdk.ParseCoinsNormalized((string)(e.Attributes[1].Value)) + suite.Require().NoError(err) + spender, err := sdk.AccAddressFromBech32((string)(e.Attributes[0].Value)) + suite.Require().NoError(err) + balances[spender.String()] = balances[spender.String()].Sub(coinsSpent) + + case types.EventTypeCoinReceived: + coinsRecv, err := sdk.ParseCoinsNormalized((string)(e.Attributes[1].Value)) + suite.Require().NoError(err) + receiver, err := sdk.AccAddressFromBech32((string)(e.Attributes[0].Value)) + suite.Require().NoError(err) + balances[receiver.String()] = balances[receiver.String()].Add(coinsRecv...) + } + } + + // check balance and supply tracking + savedSupply := suite.app.BankKeeper.GetSupply(suite.ctx) + utxoSupply := savedSupply.GetTotal().AmountOf("utxo") + suite.Require().Equal(utxoSupply, supply.AmountOf("utxo")) + // iterate accounts and check balances + suite.app.BankKeeper.IterateAllBalances(suite.ctx, func(address sdk.AccAddress, coin sdk.Coin) (stop bool) { + // if it's not utxo coin then skip + if coin.Denom != "utxo" { + return false + } + + balance, exists := balances[address.String()] + suite.Require().True(exists) + + expectedUtxo := sdk.NewCoin("utxo", balance.AmountOf(coin.Denom)) + suite.Require().Equal(expectedUtxo.String(), coin.String()) + return false + }) +} + func (suite *IntegrationTestSuite) getTestMetadata() []types.Metadata { return []types.Metadata{{ Name: "Cosmos Hub Atom", diff --git a/x/bank/keeper/send.go b/x/bank/keeper/send.go index c0c3a4cb62dc..0093a3b805a5 100644 --- a/x/bank/keeper/send.go +++ b/x/bank/keeper/send.go @@ -83,7 +83,7 @@ func (k BaseSendKeeper) InputOutputCoins(ctx sdk.Context, inputs []types.Input, return err } - err = k.subtractCoins(ctx, inAddress, in.Coins) + err = k.subUnlockedCoins(ctx, inAddress, in.Coins) if err != nil { return err } @@ -144,7 +144,7 @@ func (k BaseSendKeeper) SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAd ), }) - err := k.subtractCoins(ctx, fromAddr, amt) + err := k.subUnlockedCoins(ctx, fromAddr, amt) if err != nil { return err } @@ -167,9 +167,10 @@ 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 +// subUnlockedCoins removes the unlocked amt coins of the given account. 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 { +// A coin_spent event is emitted after. +func (k BaseSendKeeper) subUnlockedCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) error { if !amt.IsValid() { return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, amt.String()) } @@ -194,12 +195,15 @@ func (k BaseSendKeeper) subtractCoins(ctx sdk.Context, addr sdk.AccAddress, amt } } + // emit coin spent event + ctx.EventManager().EmitEvent( + types.NewCoinSpentEvent(addr, amt), + ) return nil } -// 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. +// addCoins increase the addr balance by the given amt. Fails if the provided amt is invalid. +// It emits a coin received event. 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,11 +219,16 @@ func (k BaseSendKeeper) addCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.C } } + // emit coin received event + ctx.EventManager().EmitEvent( + types.NewCoinReceivedEvent(addr, amt), + ) + return nil } -// ClearBalances removes all balances for a given account by address. -func (k BaseSendKeeper) ClearBalances(ctx sdk.Context, addr sdk.AccAddress) { +// clearBalances removes all balances for a given account by address. +func (k BaseSendKeeper) clearBalances(ctx sdk.Context, addr sdk.AccAddress) { keys := [][]byte{} k.IterateAccountBalances(ctx, addr, func(balance sdk.Coin) bool { keys = append(keys, []byte(balance.Denom)) @@ -237,7 +246,7 @@ func (k BaseSendKeeper) ClearBalances(ctx sdk.Context, addr sdk.AccAddress) { // 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 { - k.ClearBalances(ctx, addr) + k.clearBalances(ctx, addr) for _, balance := range balances { err := k.setBalance(ctx, addr, balance) diff --git a/x/bank/keeper/view.go b/x/bank/keeper/view.go index 1b50fb81d3aa..7271bba05945 100644 --- a/x/bank/keeper/view.go +++ b/x/bank/keeper/view.go @@ -171,15 +171,23 @@ func (k BaseViewKeeper) LockedCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Co // by address. If the account has no spendable coins, an empty Coins slice is // returned. func (k BaseViewKeeper) SpendableCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins { - balances := k.GetAllBalances(ctx, addr) + spendable, _ := k.spendableCoins(ctx, addr) + return spendable +} + +// spendableCoins returns the coins the given address can spend alongside the total amount of coins it holds. +// It exists for gas efficiency, in order to avoid to have to get balance multiple times. +func (k BaseViewKeeper) spendableCoins(ctx sdk.Context, addr sdk.AccAddress) (spendable, total sdk.Coins) { + total = k.GetAllBalances(ctx, addr) locked := k.LockedCoins(ctx, addr) - spendable, hasNeg := balances.SafeSub(locked) + spendable, hasNeg := total.SafeSub(locked) if hasNeg { - return sdk.NewCoins() + spendable = sdk.NewCoins() + return } - return spendable + return } // ValidateBalance validates all balances for a given account address returning diff --git a/x/bank/spec/04_events.md b/x/bank/spec/04_events.md index 55c93b805ed1..71c068b0835a 100644 --- a/x/bank/spec/04_events.md +++ b/x/bank/spec/04_events.md @@ -27,3 +27,123 @@ The bank module emits the following events: | message | module | bank | | message | action | multisend | | message | sender | {senderAddress} | + +## Keeper events + +In addition to handlers events, the bank keeper will produce events when the following methods are called (or any method which ends up calling them) + +### MintCoins + +```json +{ + "type": "coinbase", + "attributes": [ + { + "key": "minter", + "value": "{{sdk.AccAddress of the module minting coins}}", + "index": true + }, + { + "key": "amount", + "value": "{{sdk.Coins being minted}}", + "index": true + } + ] +} +``` + +```json +{ + "type": "coin_received", + "attributes": [ + { + "key": "receiver", + "value": "{{sdk.AccAddress of the module minting coins}}", + "index": true + }, + { + "key": "amount", + "value": "{{sdk.Coins being received}}", + "index": true + } + ] +} +``` + +### BurnCoins + +```json +{ + "type": "burn", + "attributes": [ + { + "key": "burner", + "value": "{{sdk.AccAddress of the module burning coins}}", + "index": true + }, + { + "key": "amount", + "value": "{{sdk.Coins being burned}}", + "index": true + } + ] +} +``` + +```json +{ + "type": "coin_spent", + "attributes": [ + { + "key": "spender", + "value": "{{sdk.AccAddress of the module burning coins}}", + "index": true + }, + { + "key": "amount", + "value": "{{sdk.Coins being burned}}", + "index": true + } + ] +} +``` + +### addCoins + +```json +{ + "type": "coin_received", + "attributes": [ + { + "key": "receiver", + "value": "{{sdk.AccAddress of the address beneficiary of the coins}}", + "index": true + }, + { + "key": "amount", + "value": "{{sdk.Coins being received}}", + "index": true + } + ] +} +``` + +### subUnlockedCoins/DelegateCoins + +```json +{ + "type": "coin_spent", + "attributes": [ + { + "key": "spender", + "value": "{{sdk.AccAddress of the address which is spending coins}}", + "index": true + }, + { + "key": "amount", + "value": "{{sdk.Coins being spent}}", + "index": true + } + ] +} +``` \ No newline at end of file diff --git a/x/bank/types/events.go b/x/bank/types/events.go index c03d142f00b6..9f06b85e491c 100644 --- a/x/bank/types/events.go +++ b/x/bank/types/events.go @@ -1,5 +1,9 @@ package types +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + // bank module event types const ( EventTypeTransfer = "transfer" @@ -8,4 +12,55 @@ const ( AttributeKeySender = "sender" AttributeValueCategory = ModuleName + + // supply and balance tracking events name and attributes + EventTypeCoinSpent = "coin_spent" + EventTypeCoinReceived = "coin_received" + EventTypeCoinMint = "coinbase" // NOTE(fdymylja): using mint clashes with mint module event + EventTypeCoinBurn = "burn" + + AttributeKeySpender = "spender" + AttributeKeyReceiver = "receiver" + AttributeKeyMinter = "minter" + AttributeKeyBurner = "burner" ) + +// NewCoinSpentEvent constructs a new coin spent sdk.Event +// nolint: interfacer +func NewCoinSpentEvent(spender sdk.AccAddress, amount sdk.Coins) sdk.Event { + return sdk.NewEvent( + EventTypeCoinSpent, + sdk.NewAttribute(AttributeKeySpender, spender.String()), + sdk.NewAttribute(sdk.AttributeKeyAmount, amount.String()), + ) +} + +// NewCoinReceivedEvent constructs a new coin received sdk.Event +// nolint: interfacer +func NewCoinReceivedEvent(receiver sdk.AccAddress, amount sdk.Coins) sdk.Event { + return sdk.NewEvent( + EventTypeCoinReceived, + sdk.NewAttribute(AttributeKeyReceiver, receiver.String()), + sdk.NewAttribute(sdk.AttributeKeyAmount, amount.String()), + ) +} + +// NewCoinMintEvent construct a new coin minted sdk.Event +// nolint: interfacer +func NewCoinMintEvent(minter sdk.AccAddress, amount sdk.Coins) sdk.Event { + return sdk.NewEvent( + EventTypeCoinMint, + sdk.NewAttribute(AttributeKeyMinter, minter.String()), + sdk.NewAttribute(sdk.AttributeKeyAmount, amount.String()), + ) +} + +// NewCoinBurnEvent constructs a new coin burned sdk.Event +// nolint: interfacer +func NewCoinBurnEvent(burner sdk.AccAddress, amount sdk.Coins) sdk.Event { + return sdk.NewEvent( + EventTypeCoinBurn, + sdk.NewAttribute(AttributeKeyBurner, burner.String()), + sdk.NewAttribute(sdk.AttributeKeyAmount, amount.String()), + ) +} diff --git a/x/staking/client/cli/cli_test.go b/x/staking/client/cli/cli_test.go index 73f60e22c048..adaa825f92b7 100644 --- a/x/staking/client/cli/cli_test.go +++ b/x/staking/client/cli/cli_test.go @@ -58,11 +58,17 @@ func (s *IntegrationTestSuite) SetupSuite() { val2 := s.network.Validators[1] // redelegate - _, err = stakingtestutil.MsgRedelegateExec(val.ClientCtx, val.Address, val.ValAddress, val2.ValAddress, unbond) + _, err = stakingtestutil.MsgRedelegateExec( + val.ClientCtx, + val.Address, + val.ValAddress, + val2.ValAddress, + unbond, + fmt.Sprintf("--%s=%d", flags.FlagGas, 202954), // 202954 is the required + ) s.Require().NoError(err) _, err = s.network.WaitForHeight(1) s.Require().NoError(err) - // unbonding _, err = stakingtestutil.MsgUnbondExec(val.ClientCtx, val.Address, val.ValAddress, unbond) s.Require().NoError(err) diff --git a/x/staking/client/rest/grpc_query_test.go b/x/staking/client/rest/grpc_query_test.go index 696a55ff9bd2..69e9f34adc23 100644 --- a/x/staking/client/rest/grpc_query_test.go +++ b/x/staking/client/rest/grpc_query_test.go @@ -6,6 +6,8 @@ import ( "fmt" "testing" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/gogo/protobuf/proto" "github.com/stretchr/testify/suite" @@ -46,7 +48,15 @@ func (s *IntegrationTestSuite) SetupSuite() { val2 := s.network.Validators[1] // redelegate - _, err = stakingtestutil.MsgRedelegateExec(val.ClientCtx, val.Address, val.ValAddress, val2.ValAddress, unbond) + _, err = stakingtestutil.MsgRedelegateExec( + val.ClientCtx, + val.Address, + val.ValAddress, + val2.ValAddress, + unbond, + fmt.Sprintf("--%s=%d", flags.FlagGas, 254000), + ) // expected gas is 202987 + s.Require().NoError(err) _, err = s.network.WaitForHeight(1) s.Require().NoError(err) @@ -330,7 +340,7 @@ func (s *IntegrationTestSuite) TestQueryDelegationGRPC() { s.Run(tc.name, func() { resp, err := rest.GetRequest(tc.url) s.Require().NoError(err) - + s.T().Logf("%s", resp) err = val.ClientCtx.JSONMarshaler.UnmarshalJSON(resp, tc.respType) if tc.error { diff --git a/x/staking/client/testutil/test_helpers.go b/x/staking/client/testutil/test_helpers.go index 1a2a4b84bcbf..ad60b96a4f8a 100644 --- a/x/staking/client/testutil/test_helpers.go +++ b/x/staking/client/testutil/test_helpers.go @@ -27,6 +27,7 @@ func MsgRedelegateExec(clientCtx client.Context, from, src, dst, amount fmt.Stri amount.String(), fmt.Sprintf("--%s=%s", flags.FlagFrom, from.String()), } + args = append(args, extraArgs...) args = append(args, commonArgs...) return clitestutil.ExecTestCLICmd(clientCtx, stakingcli.NewRedelegateCmd(), args) @@ -43,5 +44,6 @@ func MsgUnbondExec(clientCtx client.Context, from fmt.Stringer, valAddress, } args = append(args, commonArgs...) + args = append(args, extraArgs...) return clitestutil.ExecTestCLICmd(clientCtx, stakingcli.NewUnbondCmd(), args) } From 70089844f7e8f1edfd7d0f8bcf8104a457fca596 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Thu, 25 Feb 2021 21:57:41 +0100 Subject: [PATCH 124/214] scripts: indent multiline commands (#8706) --- scripts/protoc-swagger-gen.sh | 10 +++++----- scripts/protocgen.sh | 18 +++++++++--------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/scripts/protoc-swagger-gen.sh b/scripts/protoc-swagger-gen.sh index bf62cd31e57c..d1d2bf96e001 100755 --- a/scripts/protoc-swagger-gen.sh +++ b/scripts/protoc-swagger-gen.sh @@ -10,11 +10,11 @@ for dir in $proto_dirs; do query_file=$(find "${dir}" -maxdepth 1 \( -name 'query.proto' -o -name 'service.proto' \)) if [[ ! -z "$query_file" ]]; then buf protoc \ - -I "proto" \ - -I "third_party/proto" \ - "$query_file" \ - --swagger_out=./tmp-swagger-gen \ - --swagger_opt=logtostderr=true --swagger_opt=fqn_for_swagger_name=true --swagger_opt=simple_operation_ids=true + -I "proto" \ + -I "third_party/proto" \ + "$query_file" \ + --swagger_out=./tmp-swagger-gen \ + --swagger_opt=logtostderr=true --swagger_opt=fqn_for_swagger_name=true --swagger_opt=simple_operation_ids=true fi done diff --git a/scripts/protocgen.sh b/scripts/protocgen.sh index 84eb751c3a10..20b8d7020069 100755 --- a/scripts/protocgen.sh +++ b/scripts/protocgen.sh @@ -16,22 +16,22 @@ protoc_gen_gocosmos proto_dirs=$(find ./proto -path -prune -o -name '*.proto' -print0 | xargs -0 -n1 dirname | sort | uniq) for dir in $proto_dirs; do buf protoc \ - -I "proto" \ - -I "third_party/proto" \ - --gocosmos_out=plugins=interfacetype+grpc,\ + -I "proto" \ + -I "third_party/proto" \ + --gocosmos_out=plugins=interfacetype+grpc,\ Mgoogle/protobuf/any.proto=github.com/cosmos/cosmos-sdk/codec/types:. \ - --grpc-gateway_out=logtostderr=true,allow_colon_final_segments=true:. \ + --grpc-gateway_out=logtostderr=true,allow_colon_final_segments=true:. \ $(find "${dir}" -maxdepth 1 -name '*.proto') done # command to generate docs using protoc-gen-doc buf protoc \ --I "proto" \ --I "third_party/proto" \ ---doc_out=./docs/core \ ---doc_opt=./docs/protodoc-markdown.tmpl,proto-docs.md \ -$(find "$(pwd)/proto" -maxdepth 5 -name '*.proto') + -I "proto" \ + -I "third_party/proto" \ + --doc_out=./docs/core \ + --doc_opt=./docs/protodoc-markdown.tmpl,proto-docs.md \ + $(find "$(pwd)/proto" -maxdepth 5 -name '*.proto') go mod tidy # generate codec/testdata proto code From b19ac2c4f8dd3a3f700a41076c136dea5c812308 Mon Sep 17 00:00:00 2001 From: Cory Date: Thu, 25 Feb 2021 16:48:21 -0800 Subject: [PATCH 125/214] Add warning notice in changelog for v0.41.x bug (ref: #8461) (#8707) * add disclaimer for v0.41 series for non-hub SDK chains due to #8461 * update issue link * update issue link, pt2 * fix bad issue link --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index feae9a1997ae..c1138a121d95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -77,6 +77,8 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [v0.41.3](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.41.3) - 2021-02-18 +**IMPORTANT:** Due to a bug in the `v0.41.x` series with how evidence handles validator consensus addresses [\#8461](https://github.com/cosmos/cosmos-sdk/issues/8461), SDK based chains that are not using the default bech32 prefix (`cosmos`, aka all chains except for the Cosmos Hub) **should not** use this release or any release in the `v0.41.x` series. Please see [\#8668](https://github.com/cosmos/cosmos-sdk/issues/8668) for tracking & timeline for the v0.42.0 release, which will include a fix for this issue. + ### Bug Fixes * [\#8617](https://github.com/cosmos/cosmos-sdk/pull/8617) Fix build failures caused by a small API breakage introduced in tendermint v0.34.7. From 92bc2904d31b78c9b483b4e1a8295ded6e43cad8 Mon Sep 17 00:00:00 2001 From: Segue Date: Fri, 26 Feb 2021 16:28:48 +0800 Subject: [PATCH 126/214] Fix legacy rest api (#8434) --- CHANGELOG.md | 1 + client/docs/statik/statik.go | 9 +- client/docs/swagger-ui/swagger.yaml | 4429 +++++++++++++++++++++++---- client/docs/swagger_legacy.yaml | 78 +- 4 files changed, 3864 insertions(+), 653 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c1138a121d95..9a3ce60607a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -71,6 +71,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (keyring) [#\8635](https://github.com/cosmos/cosmos-sdk/issues/8635) Remove hardcoded default passphrase value on `NewMnemonic` * (x/evidence) [#8461](https://github.com/cosmos/cosmos-sdk/pull/8461) Fix bech32 prefix in evidence validator address conversion +* (x/bank) [\#8434](https://github.com/cosmos/cosmos-sdk/pull/8434) Fix legacy REST API `GET /bank/total` and `GET /bank/total/{denom}` in swagger * (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 * (server) [\#8641](https://github.com/cosmos/cosmos-sdk/pull/8641) Fix Tendermint and application configuration reading from file diff --git a/client/docs/statik/statik.go b/client/docs/statik/statik.go index 75f4b5e05b23..071f22c4cbf4 100644 --- a/client/docs/statik/statik.go +++ b/client/docs/statik/statik.go @@ -1,14 +1,13 @@ // Code generated by statik. DO NOT EDIT. +// Package statik contains static assets. package statik import ( "github.com/rakyll/statik/fs" ) - func init() { - data := "PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00 \x00favicon-16x16.pngUT\x05\x00\x01\x80Cm8\x00\xbd\x01B\xfe\x89PNG\x0d\n\x1a\n\x00\x00\x00\x0dIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\x00\x00\x01\x84IDATx\x01\x95S\x03Luq\x1c\xfd\x8c\xf1\xc3\xec0\xa7)\xcda\xb6k6\xb2\x9b\xf9\xb2k\xc85/\xdb\x8dqx\xc6\x94m\xcc{\xef\x7fO\xff\xf3l\xdc\xed\xf2\xe0\xfe\xf8\xc9\xffP\x14\x11/\x14[\xa3P\xc4\xa1\xbc?\xf1t>7\x12s\x13\x03\x85\xca7IR a\xb5j\x8f\xa71\xbe]\x88\xf6\xb9L\xf0\x1c\x93\xcf\xda\xe3)\x10\x93f\x8d\xe4\x06\x13\xcf\xde<\x9b\xd14\x95\x8a\x92\x81OA\xcfF\x89\xdd<\x9b M\xe6}L\xe4\x07\x15\xc5\xf5\xe3\xffI\x0c{\xd6\x8d\xffs\x994\xbasfh\xae?\xafk\x1aprw\x10 <\xb9\xdb\xc7\x86\xa6\xd1\x19I\n\xa8\xb1\xd7\x84y3g\x171T$\xb5c\x7fq\xfbbq\xbfk\x8e'\x1dQ\xb0\xc2,\x92\x0bx|;F\xe5\xf0\xef\x00\x83\xf2\xa1\x1fx|?q\xbd\xcb\xc2\x16\x80ZF\xf0\xc4J\xf3\xe3\xe4n1\xcc\x17k`:}\xcby\xe8\x98\xcbB\xc7|6z\x97r\xd14\x9d\x06\xd3\xf9\x8a\xe4\x94\x90\x8b\xb6\xd9\x0cP\xebc@\xd0|\xbe*\xc94\xc8\xa7\x98'\xcdh\x00\xe3\xd92\xa6vK}\x0cB\xa4\xf0+D\n\xc7\x81)\xb0\x10\x9a\xe3\xa9\xd8\x8bx\xe4(\xa2\xbb\x8dl\x0d\x01\xb6\x8a-\xf378\xbe\xdd\xc7\xa6\xb6\xc9\xd9\xc6d\xd8\\m\xf4\x0c\x92 uQ\x0e\xd2\xf5\xb3\xd1\xf1w\xdfQ\x16\xb34a$\xa1\xc4\xc4(V\xbcF\xd9\xdf\xa4\x91\xe9\xb0&,\x12+\xcd\x93\xcf\x1c\x1cb\xdc\xca\x00qt\xeb\xcc-\x14\x89\xfe\xfc\x0fm2j\x88\xec\xccs\x18\x00\x00\x00\x00IEND\xaeB`\x82\x01\x00\x00\xff\xffPK\x07\x08\xd4`4t\xc7\x01\x00\x00\xbd\x01\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00 \x00favicon-32x32.pngUT\x05\x00\x01\x80Cm8\x00u\x04\x8a\xfb\x89PNG\x0d\n\x1a\n\x00\x00\x00\x0dIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\x00\x00\x04|ID\xc4\xcf\xd0@\x04&%\xad\x1e\x16\x0f\xf7\x8d\x97AR\xfa\xca\xe7l\x87\x05\xf8\xd2\xfb\x0c\x84\x1d\x0dLVY\xdc/ju\x13\x1a\x88\xd2\xa0\xaaa\x82|nzp_\xf4\x03\xc8 \xd4;^\x8a9}\xeeu\x9a\x91 `\x04\x14s\xec\xe1\x0c\xc6]\xa3\x05``\xd1w\x12*~ \x00\xf3\xae\xd3\xa0\x9cb\x82\xa2bx(\xb3n\x1fqx\xd2\xf2\xda4\x1d\x8a}\x1ck\xd4>\x9cI+\xeb\xb3\xf4k\xc8u`L\x93\xf3]4\xb5\xd0\xc3\xe33\xd9\xee\xd7\xf2\xd9\x19\xea\x18\xc9\xc1Y:\x18\xfb(-\xadN\x82\x06e\xd5\x1f0\xa2\x1dV\xf8\xbe0\xc1\x985\x01\xf8\xd2~\\\xa6\xa5\xb5)&\xf6\x98V\x80l\xe4\x03\xf8\x03\x04\x00s\x9a^\xec\x85\x00\xf4+\x0b\x00\xe1:G\xf2p\x96\x0e\xc4,\xe46\x1e5\xbbP\xdd\x15J\x80}\xce\xa4\xe2\xc8{m\xa4\xe2\xc3\xc2\x01\x07\xc0\xdb\xa4\x18-\xa1\x931\xba\x10S\xfa%\xb6P`\x10\x19v\x99#|Gg\x9b \x10W\xf6\x8dI1\xba\x92\xd66\x17E\x12\xfa\xd9\xa8\xf3UTe\n\x1b\x95\x9d\x81f\xe5\x18\xa5umc\x81\x86\xa6\xeb\xec \x804\xcbg\x17\xa19\xfa\xc6\xf7<\xa3\xbd\xf2\x0e\x7f\x02\x80\x97Y\xc7\xac\x184$h\xa3v\xba! \xcc{\xcd\xb4!\xb1\xd8\x92%h\xe3\x93\xdc\xd3_\xda1\xe6\xaei\xcf\x83\xa6p\xbc$\xf0\xb2\xda\x94\xa2q\x14B@\x13\xdb\xff\xf3\xd7\x0d\xfaA\xb9\xc5n{\x8e\xd6Y\x08\x01u\xc1'~\x16\x8e\xe9\x04\xa2\xfbA+\xc74\x0c\x98\xab\xd7:\xfc0\xd1v\xaf$\xa2#\xb7\xf1\x08\xfdm!OXh8\x10j|g\xd1\xe0a\xb2\x99\x04\x9a[y\x9a\xbdk\xf24C$\xa0\x9e#\x9f\xa3\xa8\x001\xc6\x1a\"\xc0\xe4i\xa6\xcc0\xf3\xf7\xb7\xf5XE\xb8\xe0\xa1\xc9\xc2\x0c\x90\x83\x80$\x838\xdf\xd6\xe3\xd4\x82FNG\x0f\x876\x8a\xbf1\xa8d(\xa7@\x8cQX\x90\xdb\x19\x9f\xc5YG\xe9\x9e\x00\xa5y3]\x9aJ\xe1\"\x00\x00\x00\x00IEND\xaeB`\x82\x01\x00\x00\xff\xffPK\x07\x086B\xc8\xd7\x7f\x04\x00\x00u\x04\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00 \x00index.htmlUT\x05\x00\x01\x80Cm8\x9cT]k\xdc:\x10}\xdf_1Q\x1e\x92\\\"\xfb&\x81p\xf1\xb5\xfd\x90\xa6\xa5\x81\x94\x06\x92}(\xa5\x14\xd9\x1a{\xa7\x91\xa5E\x92\xf7#!\xff\xbdX\xf6\xae\xb7\xdd\x90BYX\x8f\xe7\x9c9\x1a\x1d\x8d\x9c\x1ep\x0e\x1f\x1f>\xddBe,8/<\x95 \xc9yKE\xeb\xc9h(Z-\x15B\xd1\x92\x92\xc0y>I\x0f\xae?\xbf{\xf8r\xf7\x1ef\xbeQ\xf9$\xed\x1e\xa0\x84\xae3\x86\x9a\xe5\x13\x80t\x86Bv\x01@\xda\xa0\x17P\xce\x84u\xe836}\xf8\xc0\xffc\x03\xe4\xc9+\xcc\xef\x97\xa2\xae\xd1\xc2\xf4&\x8d\xfbL\x8f*\xd2\x8f`Qe\xcc\xf9\xb5B7C\xf4\x0c\xfcz\x8e\x19\xf3\xb8\xf2q\xe9\x1c\x83\x99\xc5*c\xae\xd7\xe0-E!\xbb'A\xa5\xd1\x9bbjD\x8d\xf1\\\xd7\x9b\xeaJ,:\x9c_\x9c\xaf.\xce\xa3\x008zB\x97\xb1\x90a\x10\xff\x9d\xde\xd9\xe5\xea\xec\xf2\x17\xbd\x90\x19\xf5\xc2\xc6\xfa\x18\x82\x9bC\xf8<<\x01\n\xb3\xe2\x8e\x9eH\xd7 \x14\xc6J\xb4\xbc0\xab\xff\xb7\xb8Y\xa0\xad\x94Y&\xc0\x1b\xf3\xc4]i\x8dR\x85\xb0\x8e/\xd0z*\x85\xda\xe7\xf2u\x02=q\x83\xbdL\x86\xe0\x9f\xd3M\x90\x14X\x19\x8b\xe3\xbb\xa8<\xda7\xfb#=CK~O\xb40r\xbdW\xd8\x08[\x93N\xfe\x1d\xdb+D\xf9X[\xd3j\x99\xc0a%\xba\xdf(\xd5\xfd\xa7\xf1\xd6\xaf4\xee'\xac\x0b;\xf9\xc1OI\x0b \xb9;\x0e,OcI\x8b|2\x18^Z\x9a{p\xb6\xdc%\xf1~\xc6\xa3\x1f\x8e\xe5\xdd*\x81\x94\xbfY\xe1\xbc\xd0R(\xa3\x91\xcf-:\xf4o\x14\xf7/K\xd2\xd2,#\xa3\x95\x11\x122\xa8Z]v\x17\xec\xf8\x04\x9e7N\xc51\\\x85{&\xc0\xad\x9d\xc7f\xc8\x97F;\x0f-A\x06\xc3m\x99\xde\\\x85\x9e\x8fGG[\xab\x12`Q\xeb\x8c\xd8v\xfb_}K7\xd3F\xfe]\xb1\xa1\x82h%q{\x8b\x9b6\x88/\xc4i }\xc07u~}\xe5\xad\xfd\xc9\x98\xe7q\xd8_}o\xf1\x92%\x9dx\x15\x9f\xd3yO\xbdX]\x1aA\xc9>t\xd6o\x93\xd3\x92\xf2\x04l\xc5\x8d\x92jz\xc1jN\xd6\xf2\xa9\x87\xfa\xb5]\x05\xcc\xf9\x1acB\xa9,\x9f\xd0\x08\x05\xb7\x962\xec\xdb\xb6\xe2\x16b\xc6\xd5\x942H\x05KfI\x06\x7f\x9c\x98\xa8\xc0\xd5\x9c\xa2\x0c\x13\xa3\xe7U\x8e\xb55;'Nk\xe6\xd0\x9d;\xd4%^\x14\xbd\xd5\xf7\x92QN\x8e.\x1c`\x079m\xe3\x9e\x8a\xfe\xed\xa2\xad\xe0y>\xe6\xe23\xdc\xf8u\xa7=\xa3\xf6\xa1\x98\xb4\x17g\xa9\xf4\x1dA\xa8Z\xe4\xf6\x88_\xfc)\xf8\xd5N\xcf,\xea\xb4\xabS\xf2\xd2\xe0v\x10\x90\x82\xbd\xb3\xe1\xc1g\xc8>\x120\x0c{\x1d\xbd\x1c\xd1\x7fd\xb4\xbf\x82|\xf7\x9f\xd0\xa7\x1e\x82\xc5`H\xc0\x94F3p0$H.\x0f]v3\xaa\x9b\x1c\x83EW}\xba4\x12O`_\xb5!H5\xd1 \x9a\x0c\xaa\xcd\x04\x8cE\xe7M:\xe1\x08\xfe\xefQ\xab\x02\xfe\xb7A\xeb\xb6k\xbb\x05{\xef\x8e\xde\x84\xcb\x9c\xb2\x8f\x04\xd7U\xf9\x9aQ:\xbe\xf51\xf1\x1a\xaaW\x97uR\xdd\xe7\xf59\x974\xb7\xfc5s\xd0\xc4P\xdf\xdd\"\xd7\x96\xc2\xdab7x\xb8;\xfc\x01\xfa'\x00\x00\xff\xffPK\x07\x08]\x12r 9\x03\x00\x00T \x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\x00 \x00swagger-ui-bundle.jsUT\x05\x00\x01\x80Cm8\xec\xfdyw\xdb6\xf68\x8c\xff\xffy\x15\xd7\xfa\xf6\x9b!kZ\xb1\x9d\xa5\xad\x13\xc5\x93\xc5m\xb3g\xe2\xa4\xcb\xa8\x1a\x1fZ\x82,6\x14\xa8\x90\x90m\xb5\xf2\xef\xb5\xff\x0e.\x00\x12$\x01\x10r\xdc\x99\xf9<\xcf\xc3s\xdaX\\\xb0\\\\\\\xdc\xfdn\xc1tI\xc7,\xc9h@\"`!\xfc\xf9?\x00\x00\xbd\xec\xf4w2f=\x18\x0c\x80\xad\x16$\x9b\x02\xb9\\d9+\xe0\xd6-\xd3\xd3y6Y\xa6\x04\x0e\xe5\x1f}\xf5\xf6\x00X\x10\xc2\x01\xf4T7\xfaG\x132M(\xe1-\x8a\xbf\xfa\xf1|\x02\x87\xf2G0\x1c\xe1\x80\x0e\\\x839T\x7f\xf5\x8f/\xe2\xb33\x92\x7f|\xfedI'));&\xe6'\xffs\x15\xb0YRD\xd5\xf4\xd5\xd4s\xc2\x969\xd5\xc0\xa2\x1e\xf0\xeb<\xce\x81\xc1\x00\xfe\xbcz\xf0?\xe5M\xf5*\xd0 \xd7_\xe6W2\x85\x80\x0d\xf3Q\xa8\xda\xe5?\x14t\x1e\xd4^\xe5mg|t\xc3|\xc4\xbb\xa8=\xc4\xb6\x0e \x8fZw\xd3\x03\xd8\xdak\xdf\x96]\x1c\xc0\x9fW\xb5gW\xf5N\xe5\xa8\x08\x1f\xd58N\xd3 S\x83\x8b \x8b@\xfbEC\xfe3\x85\x01l\xedj\x0f\xca\xd6\xaand\x9b\xb4?\x87\x01\x90\x08h\x7f\xcc\xa7\xc5\xff\x98\xc0\xa0\x8ep\x11\xb4@F\xfb\x99\xc4\xc5\xf5\x1a\xde\xe2\xd2\xf7\x05J\xbc\xcb\xb3\x05\xc9\xd9J~\xd9\x86\xd08\xa3\xd3\xe4l\x99\xc7\xa7)\xb1\x80\x85.\xe7D=\xdfm??#\xec\x00\xf2:\xc4\xc2j\x8e|\x0e\xb46\x87\xe6\xe8\x15\x86 Z\x93\xfe\xc9 )^\xab\xbd\xd1\xc25\xfdR+\xc1\xe7\x1a/SV\x1f\x03\x1c\xf8}\xed\xb1\xd6\xb4? X\x04\xbd\xb8\xc7\x81\x1c\x01\xabO/k.Q\xb3;\xd9\x8c\\\x99E\x9e\xb1\x8c\xef\xca\xfe,.\xde^P\xb5F\x02\x9b\xf0\xfbz\xfb\x0b\x18@\xef\xf6$)X/\x02\x1a\xd0>'\x12w\xef\xde\x13\xaf]\x05\xc3\x06~P\xbd\xff\xde\xb2 P\xb0<\x19\xb3^59\x9d\xdc\xd0\xe0\x1b\xd5T\xd4D\xb5ZS\xf5\x8f\xbe\xbdw'\x0c\xbc\xbe3\x0f\x81\xe9+-\xb6\x08S+\xd9\x05PN#\xb6\x02\x02 -XL\xc7\x9c\xbe\xb10\x046\xcb\xb3\x0b\xa0\xe4\x02>\xac\x16\xe4(\xcf\xb3<\xe8=\x8d)\xcd\x18p\xe0B\x0c\xe34.\n\x88\x0b\x88\xcb\x1ezacG\xde\xcct\xaaG\x1c\xc1\xf3\x08)\x15\x0d\xf6\xef\xef\x87\xf5M\x94\xc0\x00\x82\x1c\x06\x90\x85|\x07\xe4\xf5\x1d\x90\xc3\x81\x01y%\x9cZ\x1bO\x1f\x8f\x01\x96M8\x96t\x98\x18\xc1\x8c\xafd9\x04|\x06|\x13\xef>\x00\n\x0f\x81\xf5SB\xcf\xd8\xec\x01\xd0\xedm\xd3G\xa0f\x8d\xc4\x99\x8e\x1e\x18\xdf\xc8\xfb\x15m\x81A\xfd\xe7z\xcd\x89\x11\xe4}\x9d@I4\xe9\x9d\xc7\xe9\x92\xf4 \xa1\x90s\x88\x05y\xff\"OX\xf9F\x18A\xb0\x1bA\xa2 \x10\xf2\xc9\xe5\xfdOd\xc5igk(\x0djo\xda\xb9%\x009.\x18\x08\xb0\xf6*E*\x16h\xdb\\\x1c\x04\xb9\xbc\xcf\xbf\xd6)H\xbd\xcf+\xbf\x1d\xa5\xef\xc4\xfaHJ\xc4\xa0\xc17\xf7\xef70\xadB,N\xca\xff\x9dX\x7f\xf7\xde\x7f\x0e\xe9\xad\x04\x84\xe8\x14\xe3=\x99\x92\x9c\xd0\xb1\"\x1b\x9c\xd7\x81Y\\\xd0\xbf18%\x84BB\x13\x96\xc4iR\x90 \xec@\xb1\\\x90<\x08kop\x12C&\xbd\xd0x\x86l1\x8e\xd3%c\xb65\x18@p\x9e%\x13\xd8\x85\x01\xe7\xd2\xe0\x10zK*N\xedI\x0f\x0e\x9a(\xcc\xe9\x1bg$+\xaep\xab\xe4\xed\xf8\xc7\x04\x0e\xf4s\xe9\xaf[R\x18@\x1cp\xec\xfa6l\xaci&\x1f\xdd\xb9\xfb]\xf3Q\"\x1f\xdd\xbd\x17\x86&>0n\xb3\x05\xea|6p\x05\xc4\x8d\x1e\xc4\xb6\xb9\xae\x87'\x16\x90\xdf\xba\x05t\x99\xa6\xb8\x92\xccr\xf6\x1cs,\xe1\x8ceN\x8a\x82\xcfs\xbe,\x18\x90\x84\xcdH\x0e\xa7D4\x90\xe5\xdaa\x14\x01?\xacz\xb0\xbd1v4\xd0\x8eT\x04\x88o5d@\xab\xd7\xf9\xe8k$\xca\xc8\x19\x16,_\x8eY\x96\x9b\xa0\x0d\x88\x0f\xe9\x92\x1c\x00i3\x85\xd0d\x1c\x0d\x8c%\xbf\x14\xdd6\xb3\x96\xd0fPw[/5\xc87'\xae\xf2PPk|\x88\xd3\xcfk\xc7\x01\x13\x92\xce\xc9 \xc2\xe0\xe4\x84\x1fT\x1b\xf2\x01\xb8\x1b*\xa0\xe7\xae\x83\xd6\xbc\xd5T+|\x85\x1e\xe7y\xbc\xd2x\xc3\"M\xc6D\xdb*\xa0o\x17f=\xae\xc5\xdc\xeb\x8b/\xf9\xceqNbV;\x99\xc20\xd2\xf1\xa4\xaf-9\xe7\xc7\x1b\xdb\xc8<\x14\x03C\x0f\xd5\xee\xc5}-6\xec\x8b\x80\x84^-\xe6\xce\x16\x97U\x8b\xbf\xfa\xb6\x989[,\xaa\x16_\xfa\xb6\x98t\xcf\xfa\xd6-\xd8J\xab\xa6\x7f\xf0m\xda@\n\xb5\xa6\xb7\x82-\xc1\x1c\x91\xe1t\xe4\xd7\xe0\xd2\xb7\xc1\x85g\x83\x85o\x83\x13\xcf\x06\xd3\xee\x15_\xaf\xb1[\xaf\xe6\xc6\xbe\xe3\x9b\xb5\xc6\xa7\xffbA.X7\x16d\xea\x8fD\xfcA\xfbI\xf1\x9c\x95\x9ck,\xee\xbc$+\xc2\xc5\xf5\xa5|\x81N\xc8%\xde(\xc4\x8d\xc7E\x91\x8d\x93\x98%\xe7\xfc\xa3T\xdc|\x9bOH\x8eo\x8d\xf9\x0d\xd5\x06\xef\xba_\xb5\xc0\x07\xd0?&\xfc\xbcJ\xda\xf4c\xca\x05\xc4\xbf\xff\xfd\xe4\xe4\xf9\xeb\xd7\x1f?<~\xf2\xea\xe8\xe4\xf9\x87\xa3\xf7\xf8\xc7\xc9\xdf\xff\xdekS\xd6E\xfb\x8b\x97G\xbf\x1e=\xb3\xbc>1t\xf0\xe6\xd9\xd1/\xd6\x0ff\xed\x0f\xde\xbe\x7fv\xf4\xde\xfa\xc19\x0c\xe0^\xfb\xf6\x1c\x06\xb0\x07\x0f\x1f\xc2\xb9A\xf1\x00\x03\x98\xc3\x0e\x18\x8e\x96\x15*\x9c\xda\xf7O\x8dZ\"\xa8\x8e\xb2\xad\xbd\xd6SC3'\xd7i\xc6F\xcb/\x9c\xd8J\xfa\xd8$g\xc4\xf6\"O\x92|dn\x91\xc8\xa3\xa1lp\xd7o;]\xf2\xd3\xcc\xf6\xf0\xd8q\x12q\xbee\xbd\x86\xdd\xb6\xf4W\x13*_\xc7l\xd6\x9f\xc7\x97\xfc\x90&R\xb2\x84\x1dT\xb4\xf0c\x88\xb3Tx8\x06\xa8O\x13Rh\x06\x0f\x81>\x80\x8c\x8b\x9f\xf90\x1b\xf1\xe3j\x98\xc160\x83\xac)A\x99{\xcd\xf6\xa9s94\x9e\x8c\xf4\x8b\xe4\x0f\x05S\xfcs\x80\x0cE\xc2\xe9\x02#\xc1cq\xba\xf2'^\x1d\x7f\xb2B\x12\x99P\xba\x9c\x9f\x92\xbc\xc6\x82\xba$o\x8a\xd0\x7f\xf4\xe8\x91 \xfc\xa0\x1a\xe5|&\x15\x1c,_\xa9\xbb\xfb\xdf\xdd\xfd\xee\xfe7\xfb\xdf\xdd\xc3\x19\xd2R\x05\xfb&~cn\x85/2m\xe3\xba\x0d|\x0c\x1e\xc2.\x1c\n o\x03\xab\xc9,\xe0\x00\xcec\x97\n\xaf\xc1\x14\xda\xdaxkb\xe2\x1aM\x05rm94\xe4Zs\xe8\x08\xa1\x1e\x1e\x0e`\x87\xe2\xc9^g\xce\x0d/3x\xc4\x01\xe85\xb0w\xd6\x95\x97\xa3z-G\xee\xb9a?\xf8\xb6\xc7\xfc\xda{\xed\x018}c\xc0!P\xce]\xcb\xc5\xd6\xf77\x83m \x9c\xf5n\x087\x9cC\x12\xef%\xa8di\x9d\xf4\xfa/\x8e\xdf\xcf9\x1dhS\xe6\xdf\xf9y\xd1\xbe\xfd\x06\x06\xb0\xdf\xbe\xfd\x9e\x9fR\x95tW\x19K\x8eW\xf3\xd3,\xe5\xeb(\xfe\xea\x8bM\x9d\x19\x8c \xcf\xc4I\xa7^0\x1cm\xaf`\x00\xef9\x8e<\xb3\x1d\x01\x1f\xcd4\x87\xcd\x92\xa2O\xc9%\xf3f\xc6?\xab\x95\xb2\xe8\xa8\x94\xc1\xa4Z(\xbe\x05\xf7j\xcb6\xe4\xdf;\xa8(\x1cB^\x9e!\x19\x1c \x91v\x9e\x86\x99Y\xb2\x9bd\xd4v\xe2z\xd2\xea\xef]T\xc19$\x81~\xcequJ\x9a\x96A\xfd\xe1\xe6>\xb7~\xf4ec\x9f\xb8\x19\x83\x866H\xb3\xf4!\xcexu\xf1\x93\xb9\x0be\x91\xe1C\xb5\"\x82\xd4!\x08\xa3\x85\xdf\x8c~tw'\x0e\xd3\xf7Hk\x87\xefG|\xcb\x90\xe1\xb3\x91a\x08\x0d\xb5\xcc@?\x13\xd5\xf0\xbcF\xf4\xb3\x07\x8c\xd5\xc9\xabCXp)^]\xbcpv\x81\x1a\xa0\xe6\x91\xa3\xb6cB\xd0 \xab\x84\xe8>\xcb\x8e\xc9g\xbc\xa5Z7\xb7\x0d\x1aP\x0b\"\xc5'\x93M\x18\x95X\xe4\x02\x181\xae4(M\xa9M\xbfut\xb9 cF&\x82A\x83,\x87DIE\xa27\xc8\xa6b\xcb\x15\x11\x7f\xfa \xa5\x1b\xf1\xe8\x00\xb5\\\xb6n\x8d\xab\xc8\xaf+_d\xfb\xf5\xcb\xe0\xdeg\x19\xcab\n\xe2r\x11\x96\xed\xb5 \xfdi\x9e\xcd\x8f(\xcbW\xe5\xcb\xc4w\x94/\xbfl\x94\x86\x81\x11} |\x9cR\x8aT\xb7\x96\xdec\xfb\xc19\xb6\xe0\xcb\x07\xa7F\x13\"4\x19\xdeo\x8cL\xff\xf5QSU\xb1\xec\x98\xe5 =s)\xdd\xb4\xc1\xf6\x86\xcf\xe5\x01=\xea\xd5{\x88\xe0c\xff\xe5\xd1\xaf\xc70\x80\xe7\xfc\xef\x9f\x1e\xbf\xfax\xc4\x7f\xfd\xce\x7f\x1d\xbd\xf9\xf0\xfe9\xfe|\x13\xd5\xfaOh\xc1Q\x1f\x06\xcdQe\xcb|Le\xf2\xd9\xb3M\xd3\xd8^\\\x7fQ\x11|''%\x00{|$\x7f\xf6\"\xe8]\xf5\x9cc\x1e\xc7\xe3\x19yO\x8a\x0e\xeb\xa8\xd6\xd5\x96\xe8\x0b?\xc4sOt-e\xbd\x8f\x14\x1fL\xf0\xfc\xd2\xdf\x1c\x88\x17+\xac\xef\xb3L\xc8\xb2a$\x1eI\xc1Q\xfbH\x9e-\xf2\x05\xd74\xca\xfe\xbb\xac\x18\xdaDR\"\xbdx\x04\xa3\xd8\xd2\x01\x98{\xc8\xf2\x0d\xba\x18wv\xc1\x82_#x\x11F\xf0km\xf1\x15\xbd\xf5\\\x133\xa6\xbf\x14-\xbf\xf4\xc7\xf4\x97\x0eL\x7fY\x1b`EI=\x9b6\x0d\xf1\xe5\x0d#\xfc\x90#\xfc\xa8\x8d\xf0/o\x18S\xf6\xbcz\xf8\"Liw\xc1\x82\x1f\xc4z\xfe\xe0\xbf\x9e?8\xd6\xf3\x87\x06\xe5b_\xb6\x96/\xfaI!Z\xc8\x08\xff\xa5\xb4\xb7\x1c\xbd\xa5\xba\x96\x8f_S\xe4\xbelko\xbf\x8a\xe0\x9f\x11\xfc\x12\xc1?\xdaJ\xd3\xe3\xa3\x7f\xa0\xc2\xd4&9\x12\xe2\x10\x1dOb\xe4\xca\xd0\xa3L'6\x1b\xb1\xaf\xcc\xd2\x83\xe2/\xa5q\xe9\x13Y\x15F\x1eR\x8cDr\x83\xd5PN\xf8\x07\xc2\xc7\xadF\x077\x19\x1auN>\xa9\xf4\xf3\x96\xf9\xa3\x80\xe1\xaf\xa0\xcb\xbb\xbb\x93\x86\xb3\xa8q\xef\xa9<\x0c\x86#\xaf\x8e2KG\xea,\xaa\x0c\x18\xff\xf04\xb0 7fm\xf0+\xdeZ\xf0\x95\xd4\xb5\x12\x12\x0cG\xa1_\xbbq\x07r\x08\xa3fR\x883\x0fy@\xd9\x05 \xdb\\\xf3\x93\xea\x8d\xdc\xfc\xc6\x1f\xd5\x1b\xd4\xfc\x86Q\xca9\xac\x84\x9cR\xf5d\x16*\xbfL\xd2\x19~\x8a\xe0|\x04\xfc\xb8O6\x92x6\x92Y\x97\x1d@/\xcc\xc2\xdc\x97OO\x08r74\x8b\xc2\x8d\xe4?7\xb0\xc5\x80\x1e\x06|(W\xd7k\x08)\xf1T\x97\x11\xc9\x9a\x99\x81\x9a\xd9D\xf0\xd2\xca\x91\xf0\x03\xa2\xb2l\xecE\x10\x0b3F\x0c\x0f\x07\x90<\x80\xd8\xeeF\x07r\x1cK\xde\xc6\x90r\xd1\nv \xe6\xb2\x95\xc5\xad\x0e\xd4b\x0b\xbd\x1e\x0b\x96\xc3\xbdQ\x84\x8a\xbb\xe5pw\xc4\xbf\x8c\x80\x84\xa5\xa6$\x86mh+\xe1\xa0%~\xa9K}\xd6zhU\xfb\x936\xab\x8c\x9et~Df\xfc\x17/\x93q\x85\xac\x90\x15+\xe7\x02\x0c\xc7\xc6\x8f\x81\x93\xa5P\x97r\xfe\xf0_X\x05\xfc\xedmx\x04 \x1c:\x1a\x07?u\xa7\xba\xacjOu]\xc1\x01|F\x07F.\xcaKL\x12\xe8L\x86{\x8d\x93\xa8\xfc\xa8}\xdb\x03M\xb2\xfc\x1ax2\xb5;\xb1*\xca\xa4y\x94\x0b_L\x8eR\x11XQ\x83\xe3M\xfd\x0c\xa3\xd5\xbe\x91\xba\xcf\x0c\x9bx\x19\xd0\xb0?\x8f\x17\xd5\xba\xbb\xda\x05m\xd2\x08Q\x0c\x1d\xa06\x10:Ts\x13b\x1d\xd2\xaf\xff\x81!\xa9-\xd0^t\xb4\xeaD\xd0\xeb\x99|\xcd\xf8\xd5\xeb5=\xf7\xf0;N\xd3\x17\xde*\xab\x85\xfbT1\xf0#/9\x1b\xc1\xa1\xb4 \\:\x7f\x95\x14\"\nfB\xc4\xf3_\xeb\xcf_\xc7\x0b\xa1\xbb\xf2\x1a\xce\xc4=\x1ce=\xae\xf9]\x0d\x14O\xdd\xd4\xaa\xe9\xaf\xf9Acf\xdf\x11\x1cwHe\xbe$\xb0%\xf5\xef\x0c-\xcc%Fm\xd9\x18%\xc1\x82j/\xeem\xa0\xa6\x97N\x08o\xa7V#\x06So\xb8\xb6f \xb8y\xf9f\x10\x868\xa1\x00=\x0f\xf4\xbb\x9bN\x10\xec\x93\xf4\xa7f[f\xc7Q\xd2'\x9f\x97qZ\xa0J\xde\xf4\x02\xd3^\xd8Ro\x07\xcc\x93#?\xf7Z\xf2\xee\xe5\x8d\x03\x11M\xa4\xd9\xb5+\x87\x07\xed&+o\xca\xc7\xda\xcd\xe6\xe7''\xb3\xb8\x98\xb5\x1a\xa8n\x97\xaf\xd4\x1e\xac\xd7B\x7f\xcco.\xe5\xb0\nu\xa3\x907\xc6\xea\xc6\x18=\xa5;\x90\xb2\xe9\xc1!\x0d\xd1\xf8\xdb \x1b\xe5Z\x81\x9e}\xe6\xb6\xf9H\\\xac\x06J\x88})#\x04\x1d\xe6\x8f>9'\xf9*\xe8T\xa8\xa8K\xb1B9\xda\x00\x83P\xec\x82Nv\"\xe3@\x98\x91 CNQ8/\x06\x94\xc3\x15o\xeeb\\\xa1\xed(\x00\xf4\xdf\x97\xfdq.\xc2c\x8f\xa8q\xda\x16\xa8\xe5gc\xee\xbc\xf1\xaaZ@\x0b\xcd\xd1\xd5\xbe\x88m\xda\x0d\xdbB\x90\xb4 \x0exg\x0d\x0f\xf9\xe6\xa5xK\xc7\x12\x10\xa9\x05\x81\x01$f\x08\x1b\xa17\x15\xc10\xc6/\x16 \xb6\x8frE*\xd1\xc7\x14<\xa8_\x1c\x9e\x9c\x13\xdd\xc2\xd8\xb4\x00\x9d\xa43\xfe{\x86<\x01\xe9\x9f\x11\xf4\x8a\\\x85\xfc \xbf\xab\xddB\x1cQ\x185\x95\x1ek\x06\x8a \x885V\xf1q\xaa\x11\x13\xbe\xa8\x0b/\xba7w\xd3\xbd-T4\xea\xf1bsM\x02\xe2\x1c\xbbj\xc0\x8c\x8fB\x9f\xa3\xbc\x1e\x1a\xfa\xa4\x86/\xcb\x1e\xdc\x86\xdd\xd2\x9fE\xfa\xbd\x84\x91zC}\xe8:\xd8\xfeY\x0e\xed\x9ff\xc4\xf9\xa7\xb4\x19tl5\x1b\xb4\xce:\xa0U\x8b\x8c\x11*\x02O_\xa1\x15q9\x0b\x99\x97b\xd5X\n\xad\x0d\xf3j\x9c\x91@\xbaZE\xa0\xe2\xfb\nF\x16\x10\xc3\xfb\x98\x9e\x118]\xc1n/\x8cpo\xe19\xb4\x1b\xd5W \x0d5\xe8[z\x1bv\xc3\x08i\xba\xf6\x02\xc5e\x94K\x18\x9f\x16\xe8z\xc8\xe0\xa1\xe4\xd8\xf8\xdb;T\x99pN\n\x16\xe75\xdd&\xa1\x13M\xb5y\x82C\xc3\xc1\xeaX\xa3\xa3\x07\xfe=&I\x1a\x04\x0cv8\x01\xbe\x0d\x94\x8bV!\x97\xcd7\xc3\x9d_JX\xfeb\xc6\x9d_\xbe\x0cwN\xcd\xbaD\x81/\x9aJ\xe9\xf1i\xc1\xf2x\xcc\x9a\x96 K\xb3'\xc4\xe5fz\xe1|z$\x9f\xea\x0f53\xd6\xf0\x1f#\x15`\x1a\x10\x12\xc1K\x8e\x19z\xdc\xc3\x19\xe9\x0c\x04\x82\x86\x15\x86\x93G\x94\x0f4M\xfb\xf0\x932g\x84\xa3\xb6gc\xa3\xcf\x8dL25\x7fY\xadG\xe9![S-U\x1e\xb2\x03\xc8\x85\x8b\xac\x15W\xa4\x8a\x88\x04t\xc80\xecn\x07=\xba\xb2\x11\n\x7f\xbc\xa3jgf\x1c\x15\xadT;\xf3\x9a\xac\x9fu\xc84Q\xe3\x14Z\x937\xbe\x95\x9956\x9bikJ \xaa7\xbd\\M\xa8/\xf4\xc3CbD\xf9Z\xdf\xb3\xb8p&\x02\x80\xa6\xa5S4\xdd\x08\x93o\xa9\x02\x1a\xbd|\xe9\xc6\x12\x9d\x8a\x9dU\x99\xaa\"\xc9V\xeb;-\x11;-\xe1;-{\x00\x89;\x16:\xe6\xdf\xe3bf\xb0\x03 \x1c@b\xd1\xf35vf<\x8a n\xee\xc6\xc4\xa8\xb4\xb5\n\xa3\x89\x17\xc8\xae\xb3=%\xb8\xac\xfbS\x03\xa1uw\xe6\x9d{8\xb9\x89=\xbc\xd9*(\xc8\xa1\xa65\xfb\xf7\xed\xf9\x98\xef\xf9\xd8o\x8fk\x8b8\x9cU\x87\x1c\x95\x87\x1c5\xee\x8b\xd2[\xc5c\xad\x91\xf7\x0dk\xbb\xb2&4iB\x86\x85{V\xd8\xf2SP7\xcb\x86v\x94\xb1\xe8$\x9e\x04\xd4\"\x83\x96\xbb8{\x00[\x01F\x9cKyT\x08\xa4\x18\x8b\xb7'\xb4\x10A&d\xe2\x08\xf2\xedm\xb9\xab\x1e\xd8\xa5\x91\xbc s#L+}\xf5\x8d\x025\xcb7\x86\xaaE\x9d\xf3D\xd7\x12\x8b\xed\xf2\xbd\xa5Y\xcb\nl\xbe\xd5\x98\xb6\x0e\x1dZ\x0e\\$\xe1\x8c\x8e{@,\x8dX(\xaf\x8d\x10\xe4\x12\xe5\xf3\xff\x02\x94\xaf\x0e\x15\xfd\x14)C\x08D\xca\xa2\xb6\x83\x80~\xa0\x94\xc6\xa8\x07\x1e\xcc[6LF\x11'T\xadC\xc226\xbeK\xa8\xa6%\x12\xbb\xe4A\x17\xdd\xa4.m\x12\x9a\xd8\x86\xc9H\x84C\x96c\x8b\xeb\x03;\xcdI\xfc\xa9\xbd\xa06lk\x1d[\xc6\xe5\xfd\x8f\xed\xbe\xc6\xc2Z \x9ai\xb1\x8d/\xdf\x08\xab\x8a+\x01\x8f\xaac\xb5Ka\xd8\xbdQA\xc1\x0d\x11\xa5\x02\x9eC\xb1(\x82\xf2\xe4\x1e6\xbe\xe6\xb4.+\xf67\x1f\xfa3\xbcsI\x03\xe6\xe4\xfa.v\x0dA\x1b\x0e\xa1\xf7\x9e,H\xcc`8\xea\xc1A\xf5\x0b\xbd \x98\xa6\x16\xda\x86^u\x0f\xbf\xe5wX2'\x05\xb4\x9d\x8e\xe7\xd7g\xcaML\xb8\x18\x82\x81\x01\xaf\xf5\x93\xd0q\xba\x9c\x10o.|Ft\xc5W;*\xab\xd1<\xa6,\xf0\x99Hm\xffpPYQ^\x8b\xd9\x13S\x85\x03\xa5\xad\xab\x8d\xec\x83\xb0\x13\xc3\x8e\x08\xa6k2\n\xcd\x91\xe6\xe4\x9c\xe4\xc5&n\xda\x1dp\x9d\x90\xcb\xb7\xd3\xeb\x83\x15\x0eQc\xb8\xb3\xe7\xec&\x8d\x0b\xf6\xfc\x06\xba\xaa0\xb4\xb3\xcb\xeb\x0bS*UT\xb9\xc4\x98+\xcaJ\xb0\xca\x03\xa36\\\xda<\xd1\xa8S A\xbd\xe6\xb2\xb9\x94\xb3\x11\xab\xba\x19\xb1Vl&<\x04\xaa(N\xc5\x02Q \x89\xd0\x98\xf0F]7\"~xP\xd8\x1a4\xa5\x91\xd2\x13\x0fI]\xf5\x0e\x87m\xcc\xd4\xa6z\xde\xb6\xf7s\xfa\xbe\x92\xf4}u\xc3\xf4\x1dU\xc6\x8a\xbc\x8b\x1f\x1au\x17\xda\xddm\xe8\xf5\xfb\xfd\xea.\xa1\x13\xd8\x86@\x08\x15\xeaE\xb2\xe0\xed\xc1\xe9\xaa\xf69Y\xf0\x86{!\x9e\x07\xed\x93`u\xb3'\x81\x1an\xa5\x8b\x84\xaf\xebCi\x9d\x11\xabk\x9d\x11\x8as\x08\x08\xec\xe8}\x87p[\xeb\xcf\xba?0@zW\x18\xe452!n\xf05B\x9d\xf84\xcd\x0c\xb6\x87\xc6\x90\xbd\xcf\x9d\xc6\xa1Rv\xaa\x1d.\xe8R \x02\xb2\xcb\xa7\x91\xb0\x15\xe0\x19S\xdd\x0d\xe1\xe1\xa0\xf4-]\x91`7\x82\xddP\x1eO+\x89\xdcg\x84\x05\xbaU@\x99\x0c\xf8}f\xb8\x8f k\x9f]\xab\xeb\x1c6\xe7eTemy,\xf6-\xf8\xbf:\x92\x0c\x06|.vi@d\x17p\xaf3\x94\xf6D\xb5\xd0\xb5\xf3 4\x13mp\x89\x03\xed\xc3j\xf5\x85\xe7#\x0eGB\xd4@sV7s\x16V\xd8\x8dz\xc3J$\xe0\x90\x93\xf2`k\x03S\xf8\x1a\xf3\xe0iw\xeb*G\xeaT9\xd6%\xc4\x08\x12\xa3\x06\xd1\xbcl\x19l\x8b\x11\xed\xf0\x01\xe4\xfe\x0b\xd4\x92\xd7\x8c\x00\xdc\xfc\x00\xae\x80g\x1co\x03\xa0\x969\xf9\x02\xd9\x0c\xce\x9b8\xec\x95 \x9d9\xd5!\x0d\xe8\xf3E\x7f\x84\x16\xc9\xbf\x98\x03P\xca\x17\x94\xd7c\x1f\x91kuC\x0c\xc1\x8a4\x16F\xf8}\xc8\x1fe\xb8\x1d\x9aU\xc5\x13\xfegy_\x92,\xf9 \x9eq\xe7ed\x91\x81\x8f8%*\x9d\xd3 \x89\xe0\x94\xe0\x9f\x17\xd5\x9fG\xea\xcfSRF\xf4\x887\xb5@\x1e\xf1\xbe\x0c\xf29jH0|\xa1/\x89-\xbb\x04\x9el\xc9|\x89 &v\xf6\xab\xd3\x8e\xdf\x0b\xaa$,\x11\xec\x87*\x7f\x06\xbe~\xe0\xbfk\xee\xdf\xbbw\xe7\x1e\xdc\xe2\xe7\xd9\x9a\x13s\xfb\xc6)\xdfd\xe2M;\x92\xe3^\xd9F\xb7\xbbG\x8f\x1e\xc1\xde\xfdP\xde\xe1O\x02V\xde|\xf8\x10\xf6\xee\x8b\xdc3!\xac\x9b\xce\xf8\xb6P\xa6\xe3._Il\x1en\xc1\xde\xee7w\xbe\xb9\xbb\xf7\xed\xfe]X\xc3\x9d\xfd\xfd\xbd\xfd\xfd{w\xbf\xe1O\xfc\x9c2\x9fZ:\xd2)&\xac\xd7\x8e\xe0\xeb\x92\x86Z4\xd5\xdd>\x8f\xaa\xa3\xb6\x07\xa3\xbb\xe3\xae\x9e\xb7\x9a#4Px\xc5\x18\xa8qY\xe6P\xa5=\x18\xd8}\xce\x12\xf4)\xdc\x92C\x15\x0e;\xc2\xa7\xc21P\xd0\xf0t\x17\xd66\xe7(q\xec\x8d\xe0\xbd\x80\xf5\x1b\x993\x83`:\x1cxF0\xf1\x19>\xe7T\x1c\x1b\xe7K}\x9d,\x0bp :\xdb\x08\xc7gq1{\x9aM\x88\x06\x19u\xcb\xa4\\\xc4\x96\xaa\x90-\x1d\xa4\x9e \xb43\x9e\x1f\x9a\xbe\xaa\x08\xbfw\xc2c\x8d\x84a\x97\x1a3\xa9\x9c\x0b\xcb\xaf\xc9\xf09\x19y}\xb9\xf5\xd6:n\xb05\xceOS\xb4q?/\x8e\xaaT\xd8\xe8\x0egz\xe25\x16[g\xdd\xe0\xd5\xbf\x96\xa3\xa0\xd9\x84|X-\xf8\x96\xdb\x0d\xa1\xb8H\xd8x\x06Au\xbf\xab)~\x8d\xe3\x82\xc0\xdeA\xe7{\xa0\xd1\xfe\xfe\x92&\x9f\x97\xe4\xf93\xfb\x1c\xd5\x85\xcd\x7f\xb7a\xf3\x93l\x8c\x01\xc3G)\xe1\xff\x88\xc96n\x96cp6mVj\x83\xdcR\xdaj\x19\xdf3\x7f\xcd\x97k{\xfb5\x89\xf4\xa3\xef\x16\xbc\x16{\xff5\xee}G\x88\xc8\x07\x12r\xac/\xa4,z=G\xd7\x06\n=V6\xd5\x01\xfe@\x97\xe7\xa6\xc7`\xefMFw\xc8%#\xb4H\xaa@\xc2\x02\xe2\x9c`\x92\xe38M\xb3\x0b2\x81\xb8\x80OdU\xf4\x9b\x89\xb3\x9b\xdd\xf3\x0de-n\xf1\xdc\x98\xc3X\xbf|\xd2\x11\xab\xab\xbb*\x86~iI\x8c;\xde\x94|\xbay\xf1\x01\xcc~\xb1\xea\xc2\x15j\xac\xc3\xa6$C\xb2\xc9Z$\x89\xc6\xc1\x9b>\x08\xad\x0d\xb9\xd5m\xfa\xa5\xcb\xda\xfe=\xf7\xe3\xc5\"]I6\xde\x12\xd1\xaf_W\x91\x83L\xf23\xb0\x03\xb2\xddD\xb0\xe6\x94^\x91\xbc\x16\xde\x7f\xa4\x08!\x96AA\x18\xc4@\xf9>\xa8 \xa7\xc6\x08\x19\x95{\xc2\x89\xfa\xfc*\xe7`\x9f\xfd\x06\xf4\xc4y\xeaot\xda+\xe5kI\xd68\xc3\xa0e\xb41\xe6\x03h@\xeb'4]\xf1&\x85\xd6\x14\xd5\xa4c\xe1\xd4{J\x80s\x0fd\xd2\xf7\xf4\"\xfdd\xe1\xedKu\x0c\x13\x8c\x92f\xa1 \xf5b\x16\xfc\x85;{\xf0\xb5HU\xd8\x1f\xcf\xe2\x9c3/\x8fY@Q\x98\xb1\x8aG\xc7\xa4\xed#\xad\xff\xe2\xbd?&U\xc6\x84\xa48*ic\x9bj\xbc\xf5\xdaa,_9\xf0V\xa9;\x8d4\xf3\xcf\xab\x08z\x7f\xefE\x82]\xb4\xea\x04\xc6\xb18\xe2]{\\\xf6cs\xf57\xa0Y\xd8\x16\x97\xdf\x91\x08>XE\xe6\x9fI\xfc\xe9u\xdc\xd02\n\x06/xGd\xe6\x02\xf9\x92\xa1qqF\xb6\xa1\xfc\x1c;<9I\xe6\xf3%\x92p\x8em''\x8d\x14\xed\x1d)\"\x03lE\xfc\x0e\x9e\x93&\xd2\xf3\xfe\x7f\xe7o\xec\xdd7$\xa6\xe4\x0f\xf6\xef\x192\x1f\xbf\xb7\x0cY\xb2\xf86)\xfa\x95e\x03\x9c\x91@\xc4f\xa1tV\xb9\xcd/H>\xcd\xf2\xb9P\x7f\xc7\xa2\x8d\x8b\x84\xcd \xa6\x90\xd0iB\x13F\xa0H\xfe \xbe;\xf0\xa3[\x8cw&\x0d\xfbE$\x0d\xfb\x8cMp\xfeb\x1c\x94\xf9\xd3\xf9\xb3>\x1f\xd9\xeb%\x8byO\x85\x16\xd6\xd2\xa5\xab\xce\xad\xe9\xed^\x91\x80*-?\xedO\xb3\xfc(\x1e\xcfj\xf1V\xc6@\x06u)R\x8a\xdc\x15m\xa9\x9b\xd4e\x8a\x82\xf6\x03\xe7g\xef\\ \x7f\x90\x8el\xe6\x1fI\x04'|\x9e\x1f\x89G2\x9d\xd2| B\x8a\xcb\x038r\xa9\x88\\\x8bd%!\x1d\x15\x86`{\x00\xfb]\xa2\x14\xda\x85\xe1Q\x95@\xc6p,\xbfN\x8a\"\xa1g\x82 \xc3^?\x91\x95\xc8f\xc1\x86\xd4\x94fR]\x82y\xe6/E\xfcU\xde\x97-\xdc\xbds\x9d\x11\xfc\xd76_\n\x85\xa7\x96\x01\xeau\xbc\xb0\xa6<\xfb\xf8\x85\x96\xc5\x93<\xcb*\x959\xff\x81\xa2s\x19K#\xf26\x85&\x93b\xad\xebb\xa3\xae\xff\xa1'\x85r\xcf\xa9 \xec9\xdd\xa0i\x9c\xc8r1\x89\x19y\x8e/\xaf\x0c\xd5\x0cm\xdfn\xba\xb29\x99g\xe7\xa4S\xd26\xccz\xe5nxBR\xc2'\xe0\xdbtk\xd6\xbeS^m:e\xd1IsA\xdc\x89\xa3\x85\x08Y\x92\x17\xa5G;\x94\xae \xa12\xce\x94\x13\x18\x92\x91l\xd4c,m\xf4\xb0\x8c\x06\x83]\xd1)R\xc6b\n\x14w\xf8\xc8\x96$\xda'\x91\xc4\xb9\x8c\x03\x15\xa6\x8d\x95]'\x1aw\xfa\xe2qr\x17K?<;Q<\x97)c\x12YM\xcbb\xd6RW\x01\x03\xc8\x82\xa5\x83\x06\xca\xe5*p\x02K\xe9\xac\xdb\x8e!\x03\xab\xd4qF\x82\x04cH\xd0p\xc3\xf7n\x04\xbd\x84\x9e\xc7i2\xe1\x94\xf8]\xccf69\x88\xcf&\x85\x01\xc4.\x0fT\xfe\xd2XNy\xc5\xa7\x8c\xd4*\xe5\xfb\xc9\xfe\x01?\x07I0\xae\x16\xd0\xa9(\x9d\xe2\xec\xc7r\xf6\xe2\xd7\x8a\xff\x92\xbb=H9\xbe\x06I\xc5\xcb\xb0\x10\xcf\x8e4\x82\xa9\x81\x07\x90{\x9eR\xd4\xe9Z\"\x1ee\xdfy\xd9\x9b\xe4\x9aZu\xd0\x1a;`\x9c\x92\xd8Y\x94Hk\xbc\xed\x16\xc3\x84?\x84Ym\xc0:\xea\x8d\xb3\xee\xf6k2P\xe7\x04J\x8b,_\xa9\xb8x-t\x11&\x06@\x8e\x86 b\xb1\xfeE\\<\x16\xf44@\x1f\xb6\xfe\xc9 \xa1\xc52'o9\xbd\x0e\xea\xc4[\xb1R\xce\x81\x97\xbd{\xee\xc1\xd6\xf9P?7\xf4\xd1pQ\xec\xd2\x0d\xb6\xb8x\xae41\x9b\xf5\xaf\xf7\xd3\xb12%\xc86\xebA\x9e[\xce\xb67spR\x1a\x11r\x01/\xfde\x9e\x8d\xbc\xd0\xbe\xd4\x89Y;\xdcKo\x1b\x94\x03\xdb\x99E:\x88\x08\xba3\x93\x80a\x82\x19\x86\x19eL6\xf7H\x94}\xea\x80\x80\xb6\xda\x9d{K\xed\x98\x8a\xc11`+?\xd2\xfeI*\xd6Fgk\xa2*\xaf\x03\xb24\xc8\xe15\x1a\xd2r?\xe8\x0c\xce\x9edp\x0c\xd3I\n.\xb9\x0f\xe0\xb3\xc1s\xe8{\x12\x01\xb2W\x8dd\xc0\xaf\x1f\xbf\xb3TO{\xc2\xdf\xd6\x81dS\x0f\xfedO\xfc\x81\xc3oOH&*j\x19\x1f\xac5>\x9c @,\x9d\x9c&l\x8e\xe0PN\xb14\x13.\xc8\xd4\xab\xcf\x9f\xaf\xd3\xe78[Rv\xed._\\\xa7\xcbOd\xf5\xa3`\x8aY\x0b\xba~\xdd\xfezs\xdd\xae\xbc;}\xd9\xdd\xe9 \x13\xa5FK\xa7\xe6*\xc2\x86V\xbe\xcd\xf1\xf8\x93H\xd3\xa9(\xcaW$\x90\xbf\xfc\xb4\xa1?t\xa6x\x14\x15\x90D\xc6\xaaVRJ[\xb3_u6k\xa6m\x1ce\xac\xe5o\xd1\xab\xf8\xc0\xe6\x8eyr\xb2\xc8\xc9\xb9\xc9\x14\xec\x97\x85\xe5\x9f\xbeIQ\xeb\xc5_\x9f8\xf2\xf6fJ\xaa#\x11d\xa5H\xc7\xf0\x87F\xe9\xa8\xb8!\xa5\xbb\\\xfc\xaa\x13\xbd\xcck\n\xbf8\x93R\x7f\x8fz\xed\xe0{>\xa0\x7f\x92`\xd73\xff\xdd?\x9c\xb8z.k\x92\x9b\x8d\x9c\n\x15-\xab\xadt8\x17\xc1\xa9\xc5\x9d\x12d~\xd8\x8b\xe0\xc4\xa1\xbc\xc1\x04pL\xf5\x86\x91/\n\xbc\x11h\xcaU\xb1\xb8I\x04q\x18\xc1\x96T}T~U\xe6\x0eD\x1e\\\x19~\x18$\xb2P\xd7!\xe7\x02\xa4\xf6`g\x0fK~\x1d4\xab\xc9\xf1\xeb\xcae\n\x17zvl\xc6g\x14{U\xf9\xc6\x9fp\x9bW\x93\x1cZ\xa1'\x8a\x8f\x19\x1f\x9b\x82@m\xc8C\xea*\x8b\xb2>c\x16\x95\xd4\x07Q\x97\xb4\xd5\x14\xa4\xa5\xa3@O\xb8\\p\x08\x19\xee6\x93\xbe\xc2\x82\x8f\xd2\xe9\xa6\xd4/\x89\x05\x8d`\xe9\xe4U\xb8D%$\xb6\xc0\xf8\xe9\x01GD\xb9\x9e\x84\xf3#G\xc12\x8c\xe0(\x881\xeb\xc3\x05?'D\x0e\xd7!\xff\xcc7\x9d;cn\x1e\xaa\x95\xa8\xf4W\xe1\xf6\xd9\xba\xff\xc2\xcf\x13\x976\x80c\xea[l\xcc\xf2\x08\x1b\x0c\xf8\x02h\xac\xf3\x8br\xa6\xb2\xbaP\x04\x99\xc9\x96\x83\xbbW$\xde\x0e\xaa$_U\xcb\x07\xda\xdf\x8f\x1e=\xe2\xf4\xe3\x16\x9c\x99\xf7\xf9\xb2\xde\x08\xba\xe9k\x1fY),\x1f\xef\x8f8^\xaci\x1b\xc3Z\xfc\xb1\xc4qI\xbd\xea\xb0\x82\nl\xc3\xb9\x84\xccH\xe8\x15\x07\xf5\xd5\xcdB\xfe\xe5C\xf1\x1d\xe1+\x0d\x070L\" \xbeK\x9e3\x17\xbd\xac\x12k`\xf5\x82Z\x86\x02Z\x9a\xe8:\x12\xdfph\xd1a2\xb2\xd3\xcc\x02M\xb46\xeds\x1c,\xd1-:\xe0\xaf\x15\xf5\x8c\xc6>~ \xd3V4\xa1\xba\xae\xc2\x90\x1f_\x8be1\x0b\x0c\x9eEV\xf2\x12+\xa0e~@\xce\x9c@.w=zmUj\x95[\xb7\x00\xb3\xb0\xd6\xd4+\"'c\x99\xd8Wl\x7f?\xce\x12\xc1S\x82\xc9h\x87\xbc\xa3QX\xe3\xc8\x98\x0fG\xa6.\xe5l\xc0\x86\xb6\x04x\xea\xca\x10\xab%\xf9'5\x115FEKl\xad\xfe\x01F.J]\n\xd9\xcd\xb4\x99wU8\x8d\xf2|\n\x0b\x90\xd1a\x9a\x82W\xc9\x99\xd6\x8e\xb9d\xb7\xe0\xb8\x85\x14\xa9\xe8\xb2\xf9\x1f\"\x7f\x9dJ\xdb\xff\x0e\xec\xc1!L\xfa\x8bLT\x82\x98\x0cSN\x8dZ7\x86|\xe4\x9c\x1f\x9f\x08\x06S\xfc\x0e#\xec9hh\xff&\x95)\\ \xcc\x11L\xbaX\xd2\xab\x08~\xbc693F\x97!vY6+\n\xf5\\\\ \x82z\xfdp\x11\xf9IP\xf6\xb1hF\x12EC\x84\xa6\xd7J\xd8x\xc3\\\xce\xb9%\xb8\xbb24\x1b\x95\xb3\xc3%\x13\x8f03\xf2H\xc4q \x19\x89\x99\xd8\x89&x\xaeM\x17k\x99\xa1U\x02\xe8\xa7$\xc8m\xa0\xd2\x04D&Y\x1e\x8a@b\x0e\xa9\xb2P\xf0]\x9a\x9f\xa7u\x18\x9a_\x1acL\xe5\xd6\x00\x82\x14n\x81 \xb5\x91\xae!\xa1\xce\x1a\xca\x1c3AUtz\xc9D\x93\x08|s\xe7\x0b5B\\.\xf3;|\xef\x8d\xe1\x10\x16\xc3\xe9\x08\xdc!\xeb3\xa1(\x9b\x08\x0b\x8cX\xe8\xfaZ\x99g'\xd4\x04\x13\x8f\x83B\xc0\x01E\x97\x85F\xde\xc7N\xf2\xeep\xf3\xaaU\xfc\x92\x0c\x01\xdf\xcf\xa2\xde\xcc<\x8c\x103v\x1fHV\x9f>\x80%\xa6\xf9\xe1\xb81\x80\xbd\x10\xe2\xe1r\x84hp\x0b5\x0bl\x98lo\x8f\x1c5\xeb@\x13J\x87\xf9H\xa8\xb8\x84/|\x80 \x05\xb7\xb1\xda\x98\x81\x90\xf0\xc7\x8b\x08\xd2\x08\x96\x11\xcc,\x90\x94\xe79\xff\xbf\x08S/\xa1\xc4\xe5?\x16,\x86{\xf0/\x98j\x9c\x8b\xba\xe3h\x0f?\xde357\xab\xda\x99\x99\x11\xf1tSr\x7f\"\xd1m\x86\x14\xfc\x00R\xf8\x17\x92\xfd\x14\xd6`\xc1\xd0\x0b\xed\x93\x82\x05\x8b\x08\xa6\x11\xcc\"8\x0d\x9b\x01\xf8\x1d\xe2\xc7yY\xed\xa3\xf2\x80\xb0\x1f\xb5B\xbdZ\xa6\xbf\xc9\xb5\x08Z!\xc5P\x80O\xb9\xa7\x1eb\x99=Q\xf3\xacslz\x97\x88\xf6\xf5\x0e\xdd*\x8d\xa4\xfa\xcc1\x06\xb7\xa2#\xe9\x92\x16\xf0%\xb5L5\x00\xa8\xbbn\x19\xa2\x81_0\x80\xafH\x90X\xed\xe7\xe0\x14\x17\xc6\x19e \xdd\xa8\xf8C\xbb\x7f\xedW_\xf8\xccv\xecj\xa8\xb6\xa7mct\xe6J\xb5\xe6Im\x10\x90:0\xf9*\xa7|\x06s\xb8\x0dw\xdb-\x8f\xd5\xb3\xfd\xf6\xb3i\xf9\x9d\xcds\x7fa\xf1\x188\x97\xb1CG\xc6\x80a\xe4\x9b\xbb\xf3XZ\xe4\xea \xe6\xc9+\xa9\x9d\x99/\xa4\x18:\xec\xaa\xe7D\xdd5\x1e\xc4`r\xa9\x03\n^\x89\xe3:\x87G\"kt\x0e\x0fa\x0e\x87p\x81\x99\x07\xf2\x08U\x0c\x18g\x8a\x85 X@\xfb,\x13\xf2w\x88ei\xd9\xc6n1\xe8'r\x9c\xfc!z6\xa4\x01\xe9\xd2\xf4\x96\x9a\xda\x0e\x7f\x13\x93\x17\x89\x9f\xa7\xc5\xc4\xed0\xa2\xe5\x01\x99\xb1\x8e< \x0b\x16\xc1\x05\xe1l2\xf3\xc8\x03\xa2 \x1f\x81=\xc6r\xc1\xb4#\xeeKsZ\xbcJ\n\x06\xc3^\x04\xbdQ;\xa9E\xad'\xcf\xa4\x16\x89\xaa\x15_%\xc5\x0f\xcb\xac\xe4\xa4\x9e\x95\xdcq\x9ar\x01\xb6d-1I3\x8e<\xcb\x93\xb3\xc4\xe6\xd9\xa6d.\xde\x13\xed\x8b2\xa1\x04n\xc1\x99!\x14\xd2\n '\x0c6\xcb\xae\xe1k\xbf@\x901\x04\x99d\xabjU\xf3\x1dE\xa00\xb1\x7f\xe5\xc4\xc6\xe0\xa1\x96\x0dvs\x975\xc0c\xe1!\xec\xc2!|\x92\x19\x0cq\x9b\xed\xca\x08SqsW\xa8\x1f\xf7\xc43f\x8c.\x03\xb0'\xd8c\xe8\xfb\xa4\x16\xd3\xfcNe\xcf9aq\x92\xba\x19*\xe5\xdeo})q\x06\n \x14\xdfb\x94\xc08^\xc4\xe3\x84\xad\x84A|\x00\x97Xo\xbb\x195 \xe4A\x14\xb12\xf1R\xd6x\x89\xf4ORrN\xd2\xea]\xfb\"n%~\xe1\x06\x89\x08\x9b\xa8BL\xcbuV^\xf6b\x14\x1c^\x9b\xb8\xdc;7\xd3\x05\x82E\xac\x14~\xad \xa4\xcf13z\x17^\xb9\xe2,k\xdbj\xb3\xf4-H \xcaJ\x1c\x9aU\x03 \xcb,\x992T\\h2\xaf\xcah\xaf^R\xba\x0d\xf1p\x91&c\xe4\xdb\xf6lQ\xbb\xb5\xc1&\xb4 \xf9&d\xa0\xd1\xcbn'8\xfe\x0d\xc9$tjZ\xfeTK\xab'\x9b\xc0\x15\xe6\xf8\xd3\xc8>!%%\x81j\xd7NE\xc1\x19)'(\x16\xcbb\xd6\x05 %\xbcU\x11\xfa\x96]\xae\xc1\xc9\xca \xe1\x1b\x16\xbai%\xe0\x9f\x90\x11\x91dQ\xd9R-;\xbe\xe6\x16\xbc\x8b2\xbb\x96\x16\x11%w*\xe8*l\xe3\x1e\x1e\xe6^%\xd9\xea`\xcb|\xf3:|R\x87\xecn\x04;{\xeeV\x97\x14wWW\xcb\xad\xf5\xb8\x16\xb0\xad\xa1a\x9f\xf0\xc8\xd9\xf1\x05\xb3#\xfbd\x99HnH7\x07\xb1\x17(\x9a@\xee\x00\xf0&\x89W\x1e\xfb'^i\xf7\xe1\x95\x90\xa3\xd9\x91o\xe2\x95vw\x1b\xe4\x19y\xec\x97g\xc4\xdc\x87\xd7\xb4\xce\xaf\x93\xd7\xe3qg\x9e\x91&\x9fx,\x08\xad\xd7\x89\xa6o\xc2v\x11\x8dz\xcb\xbe\xf5\x97\xce\xbf\xa8\xee_9\"Y\xe2\xaf\xac\xfa\xe7\x1e\xddfI\x19\xca\xedi\x17gOJ\xe4\xb3\xaf\xcd\x06\x05a0\x14\xb1\xabB.\x9e\xa8\xa7\xec\xdfW\x04\x86b\xd1\xd6\x8d)\xd0F\xd9)\x9aur\xa5\xfe\xd8 _\xbc\x02\xa1s@\xa1\x04\xc1\xa2\xd7w\xa6\xd7\xad\xec\xdc\x98\xc8_\x92d\xe2\x82\x05:\x9b\x135\xb8\x9c\x1a\x87\xa3s7\x91\xc6\xdcl\x94\x90\xc2\xb4\\I\x81\x12\xf6\x00&\xac\xad\xc1\x9a\xb1v\xe2\x89W\xcf\x8f?X2O\x9c\xa3\x05]\x83\x9cM\x7f5gV<\xc0\xb1\xa3h\xac%-\xa8f\xd2\x8cn\xd3\x7f\x9d\xb3\xe1\x8c\xa9`\x90sV\x05\x83\x9c\xb32\x18\xe4\x9c\x95\x89\"\x9f\xc8\x9c\x91\xda\xbbx\xbf|[\xbd\xa5~\xe1\x8b\xa5\xfd\xed\x89\xb2\xc5i\xb7\xd5\x17\xea\x17>\xaaR{=)\xf3|U\x0f\xcadOOj\xd9\x9f\xf0\x85f\xe2\xa0'\x0d\x89\x19_\xd2\x93\xf4<\xd1r\xf6\xc8\x87z\x0e\x9d'\xb5\xa4:\xa2\x0b=\x03\xce\x13=#N\x04\xf3\xb6\x08\xf4\x84L\xb3\xdcd}\xb4iZh\xe9\xd0\x84\xde\xcc\x0c#\xdb\xca\x8d\x81\xeb\\\x86^hL\x97Y\xbb\x88\xfaC\xe1\x13e\x0e\xad\x15\x0e\x80\x8f\\\xadK=\xe1p\xc4O2s7\x99\xf4\xbb\x10\xaaHs/LT\xbd\xb0S\xf2\x18\xf4Q\x0c]\x06,,R\x1fs\xba\x15\xd7\xc0\x8c\xb0\x85\x1d\xd4q\x86!\x8e\x06\xdfJj\xa0jSe\xe3\x80\x85\x95,\xf3\x80\xf2\x12\x06p\\\xe5\xce2\xcf\x7f+1\xabTj\x8e\x13\xbb\x0f\xa0\x10.\xa6\x05\xfaIJX\x14\xa3R\xfc\xb2\x12\xe4\x0c\xddD\x96%\xf48\x8d\x0f#X6)\x98\x01G\x1fO\x19i\x1d\xef\x9d(\x1a\xd4q\x14\x83\x8c\xbf\x00S\xa5\xf5\x13\x85\xfa\x0e\x84\xcd\xdc\x08k\xee\xc4\x0b\x07\x93:\x0e\xda,J\x88\x839&\xcb\xe4\xd8\xa5\x83\xd1\x80\x82\xf8Rf\x86\x0c\x1a\xbf6DN\xb5Y\x9c('\x9b\x8ceoRY\x91\xa1\x92/\x92~mq9M\xceD\x85\x11\xc4udi\x1fog,\x82\x15\x8b8\xd3\xe0J\xa3~b?\xad*^]\x1d\xe2F\x08KEay\xb2\x1b_\xc2\x04-,\xc8\x1dQ3Ryf\x87O-\x91\x88d\x1cv\xc3\xc6\xc4\xa0\x16\xf7\xcc\xe7\xb6\x8c\xc0jc\xad\xe9q\x96\xb5rV\x16O\x13u)b\x12K\xff\xa5C\x85`\xe2x?PQ\xee\xf8\xd3\xce\xa3\x82\xf4K\x89e\xe5\xc3]\xf4\x8c\xdd\x81\xd8\xfd \xaa\x18\xf9k\x16\xbe\x11_y\x04s\xc4\x1d\xfe\xf2\xdca\x0f\x95@\xe8\xe4\xe1\xd5\x95\xa0\xe3,\x9fvZ\xee\x87SG\xd1\x11\xd0\xd4\x12X\xedq'\x85\x03N5\xdd\x9f\xc8\x96\xd1\xb3k9$\xe6\\)`\xdcvx\x97/a\xd1t\xcb\xcfPs\xdc\xb1\xac\xc2\xa9\xd5\x7f\x01S$/\xf5\x05L\xe0\xd1#\xc8\xdc\xdf\x8d1\x00f\x9b\x1f\xeb\xea\x03\xc72\x8d\xcb\x05\x1d\xdf\xf0\x82\xe2\xb9\xf6\xc0\xea`\xa1_|\xed\x8d\x19]L\x97Z\xf4\xa5M\xe8k^\x89,\xb2\xc7E\x9d.\x85|\xf3ZJUh\xe7\xcbv;\xbe\xba\xf80\xd2\x86/a\x17\x82\x83.\xf5#\x92\x8f\xe1\x00\xd2.$\x079\xf2X\xb8\xa2\x17\x98y?\x13\x87R\xc2Q\x83\xf2S;\x0b\xedn \xe0\x9c\x92co ]l=\xf6K(qaL\xf6c;D\x96\xad\xec\\\xe7\x0e\x8d\xc2\xb2T\x93\xc3\x0e\x17\x92\x96\x9a\xaa\\\xfc\xd4T\xe5\x0co(=9\xc5_U\xd6\xa3e\xa9$\xcf\xf0\x87&5&\xe2\x86\xd4\x97\xc7\xe2W=\xb9\xd7\xd2\x0b\x14G\xcc\xa5Q;c\x18\x06}\xc6\x07$\xec\xfa\\|\xf34\x85_\xb6\xa1l\x03q,\xfc\xf1er\x1ewL\x05\x11N\xf3\x0f\x15qS\x8a\xd9\xd6\x07\xc8\x0b#^j\xbe\x14\x99kc\n\x96\xb3\x83sK\x1b\xc4u\xb8td\xcc\x19\x0b\x13\x9f\xb4\xe5\x89\x8d\xa1`\xe1\xd4$\x8d\xc5 \xa5\xf2F\x05\x92\x0d\x136\xde\xb2c\x18\xc0\xd8\x1c6h[\xd1\xa2>\xf2\xf2\xf8'\x95[\xa6\xdeUT\x83\x9d\x80<\n;-\xde\x12\x0e\xcb\x9b\xcaD\x16\xeb\xe3l\xc7 \xd8\xf0\xe6\xd8\xce\xd3\x95j6\xf4\x07(c\xf0\x88\xe6\x99J\xa4\x07\xea\x9c\x05\"?\x97dK\x91+\xe5\xa3\xe2\xe2\xa5g\x1a\xc3\xa7\xf6\x91\x94\x16\xf4\x86\xedW\xb7\xac\x9a\xf9A\xf1\xe5C!\xd0(V\x10\xb6\xe1\xdc\x86t5sD\xc9DJ\xbe\x15\xbf~ \xfc\x16\xd0\x15\x07\x0b\xab\x0eJ\x1f\x06\x11\xaa\x95\xa3'\x03\xffhg\x00\xe7N\xc4\xeb*\xf3n\xad\xe8\xe5L\xd2\xa3\x05\xbd\xa8\xa83Q\xeeX\x7f\xa2\xe2\x0f,\xe5\x8d5\xb3\xbe\x9en\x07\xf33\xd8\xd9\xf6\x0e\xf6?\xf1a\xff1\xc6\x03\xb6m\xc5\x19\x96\xa5\xcc\x8c\xd8H\x91\x9b>@\xb3\xd1.\xfe\xbd\x8d!c\xbc\x05\x83\xc7\x02\xc7\x87\xb8\xb9\xbf\x92.2\x15s\xdc[j\xd8\x86\x86_\x13\xa7R\x13\xfb+\xd1#\xd5\x91i\xac\x82N\xb7a\xccG\xfd \xc4\xe7r\x1fa\xf5\xac\xb4\xbe\xe3\x0fa\xa8\x8cG\xe9H\xee*.\xd8\x8da[e\x1f(\xf8\x9f\xe7\x86\x11\x8d\x85L\xc8\x1f\x8f#QF}\xcc\x0f\x00\xf1o\x82\xff\xba&2\x15\xd2X\x82\x11\x04\xf8\xe72|\x00\x0b\x0e\x11\xec\xb9\xe0\xbb\xc9k\n\xb5\xa1\x8b\xf1\x9a\xf1n\xd2\xe5N2\xc3 \x8a\x87\x18#!\xc8\xc6RH\xdc\x07|`x[Soat\xe3\xc4\xbc\xb2X0]|s\xeb\x16\xc6\x01\xa3h6i\xa8 :h\xc5\x1c#X\x90\x90\xa7bz\x9c\xdf(\x1e\xc0\n\x1e\xc19\xff\x87S\x82.Y\xe2\x14\x060E\n\xb22+I\xd4\xc5\xbb\x9bK\x92s:\x12\xfdV\xbf\xad \xa4\xcc\xfc\x9d\xfaP\xf4|\x8e\xb4\x0b\x060\xe9\xa0L\xa0\x18|\x05\xb2\x80/\n\xc6\xac\xcfj\x8a\x93\x1c\xd9\x98e\x88g\xdd\xa3\x01,B\x8898\x16\xb8h\xf8o!\xdc\x16*\x07\x85VSR\x0f(\xda2\x85O\x96\xee\xc8\\8\xce8\xa5B\xfcp\xae\x9c\xdc\x87\xa9S\x98\xe1\x0bs\"\x84\xeeG\x8f\xf8\x81\xeeZ\x18>\x80\x13\xa4\xae\x8b\xea\xf5\x10Ns\x12\x7f\xb2\x7fu\"\x05\xb5\xed\x01\x04bK\x85\xf05\x9c\xe0&\xd9)!#\xf7\xd3\xf0\xc4,\xdc\x9a\x177\x15X\xfdH\xaa\x11E;M\x90\x16|ev`\xcc\x97(\x15\xfb\xe1\xa1\xd8\x0f\xb5\x0f\xca\xe5,8%\x90\xef+\xea\xb2#\xa9\xca\x8e1\x8ar\xe3\x94\xa4KTkT\xc7\x89`\xbbI\x8d\x9d_V\xba\x1d\xc08\xce\xca\xbd*\xd5\xdd\xabf\xbe\xeeU\x9cL\\\xb0 \x16\xe2\x0eFj6\xa3\x1b-\xc7\xf1c\xbf|\x91\xb9\x9e/\xb2\x16A_eY[\xba#B0)\xb6\x93 F \xc6\x9a\xbe'\x15\x10~$\xf7l\x82\xeb++\xfd\xc5A!RJ\x8aU\xbf\xe9\x94\x92\xb9\x88GK7@\x8f\x04\x1e)\xa7\xc9[\xb7D\x82\xa8\xca+9A\x92\xa2 \xdf\xccrcY\xa9\xb7])\xe6\x84[\xf5.*\xe5\x94\xce\xfa\x9co\xcas\xaf\xf6\xdf\xb9\xdbw\x16z|.\xdc\xe1>\xb0\xaa\xbe#\xbf\xb5\xb1\xdf\xcd\xf9\xff\xfa\xfa\x8e\x1f\xdcP,Ka\x8e\x9b\x08gk\xf0\xb5oJ\xbe\xba\xea\xe1\x9dfT\xb1+!\xaa\x14\xe1(\x02\xe1\x8f\x03\xb4\xdb\xf7OD\xea \x91;<\x15\xf6e\x8f\xdc\xe1^sz\xeeT&\xac\x842a\xc5{|\xcd\x02Q\xdd\xe6\x88\x05\xadP?K\xeb\xbf\xbb%\x0ci\xda\x89\x14KoM\xbd\x14K>8)\x1c\xfc\xbcHI\xc1,\n\xff\xa2\xe2\xf8\xf9\xd1\xba\xb4\xa9\x12\x06\"o\x93\x19o\x85~\xa2KQ\x18K\xf28\x10\xda\xd3\xea\xe7>|\x0d\x89r\xdcD\x1b\x910V\xb6\x93\x9fZDXu\xc9\xfe\xb5\xf9H\x15\x0bJk\x96}\x14\xf6Y\xf6\x92\xac\xc8\xe4\x98|\x0e\xc2\xcd)3\x19\xeeZ\xb8\x86\xb0?M\x93E\xc0;x\x1d\x8b|:\x1anr\xa2\x9b\xd7p\xb5\x8e\xb9\xba\x933:\\\xa0\xf1L\x95}c\xa10\xfe)%\x86\xe6\xdc\x1bkj\x0bND\x96J45(/\xb5X3\xabm\xa6B\x80\x18Qi\x19\x0e\xf7F]\x8b\x9d\x0b\xd5\x9eXG9\n\x91j\xdd:\x081?\xe9L\x1f+\x12Z\xb5\x10\xcbB)\xb2\x19+\xc9\xb0\xf1=\xb9\xfc\x9e(\xca!|\xc3%\xe5\xc8\xcc\x9c\x0c\x07\xe3kt\x7f\xf7\xcc\xbc\xfc\xa6\xc3\xeb\x04\xdd\x954\xaf\x93\x93eA^\x92U\x01U)\x0bE\xf1\xdaI|m\x9d\xbe\xb7\xd0tc\x8f\x9b7\xff\xec\xafm\xfe\xd5_\xdb\xfc\xc7\x8e8\xb6\x7f0W\x8aXV\x1bA\xbd{~\x83o\xf1.\xafN\xad9CR\xe6\x08\x8b9\xaa\xe2%\x9d\x0d\x9d\x97e\x92\xe5G\xb2\xfe\x19\xfa^9\x15b\xfe\x83\x05}7\xc9n\x02\x0b#\x12\x99*\x8a\xf09\xcd\xe2\xa2\xd3\x0d\x15\xf4\x8e\x12:N\x97\x13R4\xab\xda\x97-\xaa\x176kv\x16\xdb[\x1c\xc7\xe3\x19yO\x8a%\x86Q\x12\x1aaE3\xe9Q\xf8\x91\xe2\xe3Z\xd9.W\x04\x93\x12C\xcc\xce\x14P\xa7P\xadzV\x9e\x8c\xa1\xf4:\x14\xbc\xa1]\x1da-v\xa5y\xa7n:?\xa1\xef\xe5\x07\xc1\x9b.\xa9^i7UW\xa2]\xbb\x98\xaeXx?'Vu)\xbbf\xee,_\xab.\xe4RHg\x1d[uU\xfb\x0c\xdd\\\x87\xbb\x1d\xd9\x90\x00\xc3:\xd5\xbb\xda\x87{\xa3H\xfb\xbb\xe5^\xd8\xbc\xdcfQ+\x19Q\x97-\x8b\xb9\x1f>\xf2\x95\xc2\x15\xfe\x9d\xcbLp\x00\xbf[\x11\xa9v\xd3F{?ws\xba\x9d\x148o\x12\xdd|s\xd2b\xa7\x01y3\xa4\xd3\xa7\xa82\xc6\x81bbz7\xc5\xadj\xa6d\x18&\x8c\xbe\xf6\xa2\xc4Nn\x14\xedp@N\x02\xe43\xbck\x13\xa0\xac\xc3\xd9\xa6N\x83\xf2\xa0\x9a\x91\xfaXZ\x04mD)\xeb\x98\xb2\x99(\xf9\xcc\xb9\x86\xc3o:\xeb*o@i\x94\xf8\x9atR\x19t\xb4\x93\x04F\xc9\xaf\xf6\xb7\xcf\xa5OZ&h\x83\xdbE\x05}\x13\x9c4H\xc9\xef\x1cZ\xcbHC\xb6\x18)\xd0\x92\xe3\x9bq\x01\xc0\xa2NhUE\xb4\xec\xf1\xef\xbb=\xd7\xdc\x1b\x9c\xea,\x16m\xeev\xba s\xe4\xe2\xb2\x88`\x7f\xd02\xe7\xcd \xa9S\xe0\xa3y\x06\xa0sW\x1b\x8c\x13\xf4\xbd(\xa4D\xdb\x961pW\xa8Yj\x90-W:\xc1\xb2'\xd4\x04\xc8\xbc\x8f;{\xb0cHa\x0d\x92{h\xd2X+WP\xa7\xb1\xb5\xc6--_\x8f\x8d\xeb\xe0\x0e\xa9\x81\x97\xa3\xe6\xe8\x90\xff8\x0f\xd7Q\x8c\xe4*\x82-\x1b\xec\xcc\xb1E\xae\x19\x19\xcfx{\x0f^[\xfe\x0f_\x95_\xc7\xc9\x8e\x9b1k\xa2\x9a\x15\x8f\xcf\xcbD\xbd~\xc7o\x86\xc7\xd4\x8a\xf7\xb2\xb5U\x11\xc4\xccq\xfaf\x7f-;P\x8e\xa7\xcd\x0bH[\xbb\xa1\xb4P(t\x98\x0e\xa6\xc0\xe5My\xae\xc5 \xd8\xcf\x98\xa5\xb9*/t#|\xe2p\xeb\x05%5\xe8|\x02~P%R\xdc\xde\x8e \xe3\x0d\xe5\x12\x02hn\xb6\xe7\xf9\xe4Sm\xfa\x84\x81Z<7\x1f\xe1\x03\xa6&\x1f\x918*/v\x03m\x036\xc3\xd3\xf9S\xe1\\\xdc\xc9\x8d\x80\n\xca\xa8s$\x89\xfb\x0be\x08K|\xb8\x12\x906\xb1b\xb8\xeb\xb0\x9a\xa9\x0b\xb3Y\x1a\x13\x83\xeaW\x1d_\xc6h*\xd4r\x02}\xc6\x8a\x882\xb7:\"\xcf\xd8\xcap\x82U\xf01\xf3;~\xb6\x81'\xbe\xc4\x8fX\"N\xf9\x0c7r#\xe2B\xc4\x1e\xdcF\x1f\x1c\x0cDD\x9f\x1c\xf9\xfe[Y\xc1,\xeb\xcc\x9b\xc4\xd1\xe6\x9d\xa8cf\xb7'|@\ni \xc8\xe1\x04\x0c\x12X\xaf!\xe6\x7f\xc5e\x8f\x1c&}\x96 \x15\xbav\x10\x07a\x05)\xf3\xa0\xa4\x93w\x0c;&\xcc,`0\x10\x9e~\x01\xdfl\x85tD\xda\x85\x03c\xa5\x89s\xe9\xd5\xe8>vR\xc5bV\xe1\x06K\xac\xac\xa5\x8c\xa1\xcb\xca\x80\x18\xc1\x16\x9eR\x992\x8b-\xcb4>A\xda<+<\x8ea\x99\xe1\x86\xc9p\xd3*)\x10\x93E\x15\x15\x93\xb6\xcd\xe9$\xa6\x9b1\xf8\xb1\x85\x11\xa4_\xa6\xa7\xca\x9c\xe09\x96!\xda\xa4\xc2\xbcf!F\x11\xb4\xdd\xe5\xaf\xf45\xbe\x9e\xb2N\xda\xf4x\xff^K\xe4\xd6\xd3)\xb4\xd1Zm\xab\xf8\xec\xeb\xe3\xb1\xbc7|\x96\xaa\xb5z\x10B\xd6yZrxmo\x17\xf0HC\xf9\xae\x93\xd8+\xfa\x1d\xba\"\xe0\xf9u\xe5V\x13\x10T\x13tM\xa1\xe4\xaa1 \x96\xd2\xe2\x11\x0c\xb0g\x91\xa8\xa3\x13\xc9'\xcfU\x92\\\xf4\xc6\xd05\x95\x9b(\x08\xeaXk;0\x7f\xf2=0\xddd\xfb\x86x`;\x19K|\xf6\x08 \x1c.\xef\xe72\xc8\xc2E\xa7\xba\x11\xdd\xc1i\xa7\x9d\xa4J\xa4\xe4\xc6\xd3\xb2\xc9u\xa7aE\xb5\x8a\x16\xdb]\xb8\xd9\xee0\x02C\xa0\xe5\xcd\xf0\xdc7\xb0,Y\xee\xb3.\x9b0\xf7_~\xdel@\xb0p\x93\xe3\"\x19\x12\xb5\xabk\x92uP\xa4De\x1d\\JZ\x11\xd6Y\x7f\xa4\x0cY\x832d\x918\xc2\xb2.\xba\xd0-7L+\xabG\x07\x8f\xcf1\x04+\xf9\x8d\xf1/\xde\x81\xe0\xf2\x8a\x1a\xde\x8ee<\x93\x83\xbd\x87\x8bY\x92\x12\xb0:\xe5\x81\xae\x0e@\xdb\x95>\xf3\x04\xfb\xd8\x88\xe6\xf9 ?\xde\x88\xe1\xe3\x8b-\x01\x0e\xfcE:e\xa9s$\x07P\xce\x86\x04E\x07\xed9WUC\xac[\x99_\x85\x89\xb2e\x1d\n\x04\xd0\xb8\xe7-\xf4\xbcJ\xe1!\x16\xac\xb9\x05q\x80U\xfb\x90(\xa7\x18\xa8\x0d\x07*M7R\x04*\xcb\x01$()\x86\xa5$\xb1\xb5\x8b\xc59\xedxeW\x95\xf3\x85\xe5_\xb7K(\xfd\x15\xa6\x8c\xdc.\xae\x81\\\xc5aG\xa1\xf3\x1b\xa3R\x92\xadJ\xbc\x94\x14\xc4\xcbd\x02\xea\xdc\x92\xa9\xe672\xcf\xa6\xbe\xf4\x06d/\xb9\xa4\x00\xa5\xfb\xf5po\xc4%T\xd4\x10\x06K\x15O\x81\xd8\xc5\x8f\xd18H\xab#\x93\x96\x84#\x8f\xc4\xf9\x99v\x93E~-\x85sn\"K\xa3\xa5\xad\xe5u\xb6\xa0\\\xb4\x90\xac\xa3g\x97\x1di\xbb(`\xd7\xaa\xdd C\xbb\x01E\xf533\xfd\xec\xa4\xa8\xc2#\x13]@M\xf2\x8b\"\xb8Kk\xda\xe8\xccN-\xc5\x9eT\xda\x8d\x9a\x83 \xeb(\xe2$\xe1>\xccq\xe4\x99(\xbdx\x08\xe2C\xe9^\xc6\xac\xee\x83e\x96i\xeb\x11\x91\xf4\x8b,g~\xd2\xacb\xa2\x022\xbc3\x8a\x80\x0e\xef\x8c\x10\xcb\xc9p\x7f\x04;@\x87\xfb\x86\x0c\xc1aU\x90\xbc\x91\x95\xc1j\xb1I\x86l\xa4v\xd2\x00\xf6\xdbm6+\xf4\xb9\x1a\xe2\xa0\x1f\xee\x99\x06&8\xd7_e\x8d\x0f\xe1\xd6\xfdR\xfc\xfa!h(\x04m8\xf5\xc2\x89S\xc2\xdfE\xc3+\x0f\xbb\xd1\x17\xe2 \x1fJ\x89\x1bV\xbc\xc8\xc9d9\xde@\x87![\xff\x15=+\x05;G\xd1\x87S(*,\xf9\xf2\xdd\xb6\x0c\xd4\x8a\xe5&\xdfWG@\xca&\x03\xaf\x0f:\x12\x89\xf9\xcc\xc3\xf5\xf4|\xff\xd5\x8b'\x13\xf5s\xec[N%\x8f\xbfu\x0b\xa8\xa6\xbf\xad\x85M\xae\xd7U4\x82\xf8\x05[\x03\xde\xedz-b[\xbd\xc6\xfb\xb2\x8a\xbf\xf8\x02\xa1Y\xea:\xf91OH\x90\xfbz8\x97k\xd6\xf2\xb3\x04\x81\x84\xf3\x84\x06u\xcb\x14\x0c\xfc\xf6u3\x0b\x9f\xf0\xf3\xac\xce\xc4\xdfE\xbcv&Bx\xb6T\xfd\x0bM\xa2\x81Z\xfa=i\xa9\x10\xe4\x95\xd9\x92\xf0\x81\x06\x94\xf6|\xba\x05Y\xe2\xc1\xb9\xe5\x9e\xc0U\x97\x022_\x1f~2\xc1O\x01\x86\xb0W>\x97\x1c\xdf\x1d\x07\xfe\xf5\xf5m\x1e\xec\xff\x06\x9c!\xaef\xa7\x00\x86\xba \\\xce\xe4\x9a\x80\x92X\xe0\x02\x88H@\xd2/\xb29\xb9N\x07\x1c\xbd\x1c\xcd\xcb\xfaR\xffFFJ\xe5\xc7\x8c\x11\xbb\xa5\xb3\xaf,Gq](\xe2\x00]\xb3\xbcy\x81\xf8\x87\xce\\\x08\xc2\xc4\"jr\x90\xfe8\xa3\x05\xcb\x97c\xd4,\xfb\xd1\xf7\xaf,\x8e\xdeI\x99\xcdFD a\x89\x116\xcb\xb3\x0bD\xf1\x0f\xab\x059\xca\xf3,\x0fzG\x97\x0b2fd\x02\xc3\x97\x11\xfc4\x02\xb6\\\xa4\xe4\x00z\xb0\xdd\xcaHk\x19\xc3?\xdd\xd1U\xaf\x88\x8cG\x08#x\xea\x1b`\xf5\x8b\xbb\xcd\xa5\x00[^\xb1A\x19\x17x\xbd\x9a\xfe\x87\xbb\xe9z\xc4V {\xfaUc\xb88\xb7\x15j\x81\\^\xbd\x12\x8f\xea\x1c\x9c\x14\xd7\\zT\xee\xf6\xd6\x13\xb41\xce\x9aY\xdd\xf1-\xe9\xa4/\xf3\xac\xbf\xd0\xb3\xcbW\xdf\x0bm\x13k\xa7.\xb5\x8c\x9eu\xe6\xba'\xf0Hf\xa3<\x10\xc5>\xe0\x10v\xf8\x0f\xbfs\x9fZ\xb6\xf2\xb9\xf4E\xfb\xc9x\xe0\xa3\x14m\xe7\xa5\xf9\xd3\x9f=0\x1f\x8f\xc0\xd3\x94@\x96\x03\x06E\xef\xa4\xc9\xa7r\x0f\x98I\xbc\x18\x14\x1f\xb5\x81@X\x97\xd9\x0b\x16yG\xe2d\xc1A\x94$\xd0\x99SLX\xb0\x13Z\xb0\x98\x8eI6\xd5*\x9e;\x9c\"\x10r\x88\x1e\xf5Ok\xc9>\xf3\xc0\xa6z.\x9bpr\xe8\xfc\xa2\xa8\x96\xea\xd6\xb2\xc6U(\xe5'\xb2*\xac~\x89\xea\xda\xf2\xe3\xca\xf4\x8b\xe5+\x8f\xb7\xf8\xc5\x8c\x11\xae^\x9d\xa8K\xceeB\xa6 %\xef\xf2lAr\xb6\x92\x9c\xaf\x7f+\xfc:#L\x13-7\x19\x83\xbat\x12$\xc2&7j\xe2\xaa\xdb F\xbf\x8a\xdax;\x8fo\xd3uF\x1a\x89\x98#\xe8=\x8d)\xcd\x18o\x1d2\n1\x85\xa4L\xcf\x9b\x93q\x96O\xfa\xbd\x92d\x8ah;\x07\x8bi\xba\xba3\xb7\xa9\xcb\x12\x8d\xd0\xbc\xae\xfa\xa7 \x9d\x04U\xd4]\xf7gW0\x8e\xd9x\x06\x086\xf7\x80\xae\x02\xe5\x9a\xae\x8e\x88X\xea'\x90\xeb\xa7\xf1\x9c\x94\xa1\xc3\x9fD(^\x8c?&d\x1a/S\xf6\x13\xe7\x960\xe7\x8c\xb5\x1b\xfb\x00\xc4\xea\x88\x80\xc3\x8f\xa4\xa9\x98P\x97\x05q2\x94)\xcaS\xab\x15C\x9d\x99t]\xa5\xe4\xa7\xb1P\"\xda\xb1\xa9h\xd3\x7f\xb1\xe0\x1d\x8b\xe0#gL\xde\xdd\\\x95\xaew7Y\xa5\xebm>!9\x99\xbc\x8e\x17\xf0g/\x82\xdeU\xbbV\xd7\xbbk\xd4\xea:\xd7k\x04\xf0\x95\x125\xfc\xed\x90\xadyh\xc9b:\x18F\x8a\x1f\xd2PT\xa6m\xd5\xd0z\xf7o\xaenS\x96\x9d\xe1S\x92I\x95\"}\xb4\xb5{\xa1\xcc\x88\xe0\x1c\xf5f\x95\xbf~g\xae\xdaG\xef\xae_\xfbHo\xb8]\x06\xb5\xd6p-\xf5\xb8\x0f\xb0+\x90U\x9f\x06\xa8\xb8\xd1 \xa7?rv\xbf\x91nDGD+\xf2i\xa30\xd8\xd2\xba\xdc\xe8E\xbe\xb9\x80\xa1\x0e\x90\xa1\x05\xd6\x12\xde\xe57/\xbf\x12\x17\xed\xa1O\xf3l~DY\xbe\x12\xbaRM\xf9\xd3\x8d+\x9b\x15J\x10\xc2\xdf\xa0U%\xc1#\xbf6\xab\x11\x85Z\xb7V3BEH\xe4\x12\xd5?\xb2.+\xdf\xd5\xaf\x99t\xe5$\xfe\xd5\x16\xd4\xd1\xc2\xf4\x9d-\xf2^\x18$\x1a\x84dRh\x84t\x00\x1fX\x1d\xbe\xc3\x99\xaanP\x83zY\xe7\xc0\xb0o#`\xc1\x1b\x16\xc1\xafa\x04o\xaeA\x81\xdb\x82\x1fR`\x13&\xd4\x9ao\xc4\x0dt\x96K\x13m\x8b\xa2i\xce\x86Q?rL>oD3\xb0q\xf5e\x9b.\xbc\xa9\xc3\xcd+T\xe8\\\xab\xc8l\xc67\x0e\xdf\xef\x159\xdc2%\x1b\xac\x8dQ%\x1b@\xa3\x86\xf74A\xd7\x1d\x89y*+\x87=8\xfc*l\x05\x896\x80 0\xb7\x13;t\xb2h\x06\x02\xa7\x02\x9fk\x87\xcd\x06`\xc8\xaf\x03\x06\xda\x00\xc3<^\x18\xf0\x15$\x18Z\x85_\xde|\xd9\x19\x119B\x94\xda(\xa99\xe0\xd6&\xaf\x99\xf3<\x1c\x97I\xc0l1KW\x9c@\xa9|\xcb\xff\x14\xeb\x10\x8a,=e\x0fV\xd5y\xd9|\x16\xc9|\xcd\x14\x0eD1 SWa'Q\xd8\xechB\x1b\x9f\x0e\x96\xd0\x01Au<\x99\x8f\x0bZ\xd7=\xb5\x0c\x1aV\xd4m\x82\xcd\xba\xa8\x9e\nye\x19\xa2N\xef\x8bRL@\x83\x8aP\x1a\xa2\xa2Y\xac\x02\x16\xc4G\xbf\xb0\xd2\xbcbZ\x0e\xd7RT' \x0b\xde\xb3\x08^\x86\x11\xbc\xd7\x97\xca\x14\x08\xe8I\xc4\xcbh\xc06%\x7f\xffe\x9b\xab\x93\xd2\xd8\xd7\xc7\xb8\xe9\xbcy3\xdca\x08r_\x96\xcc8S?\xbc\xff\"\x84\xbd\x11\x0ce\xbe\x18\xca\x14\x862\x85\xa1\xa2\xda\x96\xc2K\xaf\x9aa,x\xc6\"\xf8!\x8c\xe0\xd9\x97s\x10\x0e\xe4{v#\xc8\xf7Wb\x18\xf3\xc7/\xe3dn\x0c\xbf\xfe\xc3HT\xe1\xcf\x86\x88\xf4Jr\xba\xaft\xe8\x10)\xcct\xf1\x10\xedu\x94,D\xb3\x9fW\xff\x95\x88\x84\xc7\xa5\xed!\xbf\xbeb\x81\xb5\x88\x9e\xe6d\x11;\xdf*\xd1\x15K\xf4\xa30 \xaa\x12\xa3\xd8Z\xdd\xdc\x157-R,\xbf\xdaz9#\xa2\x1b\x81\xfd_\x83\xe8\x1e\x91\xa1~{\x01\xca\xf0\xca\x9a[\xb8\xa3\xa2\x86Z/\xd6\xe5e\x89\xde\x95\xae\x11\x82@\x0eS\x18\xa0~)\xde%\xee|S\x0e\x1e\xf7r\x06\x87\"\x91\x8b@\x89\x1cQ\xa2\xba\xb9'n\xee\xb5\xf3\xe5\xeb\x97\xc5e\xd1\x83&\xd4\xce\xe1z\x1a\x827\xf6G\xcf\xec\x8f^\xd9\x1fa\x8e\xaa \xa7\x11\x9c\x10.ZP\xed\xcd/T\xb0.\xa9\xe4A\xb7\xa1g\xd5\xb0\xd6:\xdc\xf8\xf8\xaci\xd4\xf9\xe7o/he\xf2qw\xe6\xa9L\x10v\xd0YY\x1d\xdd\x85\xe6\xf5\xcd[\x1b\xdc\x90\x18\xe2\x94ks\xe1\xe2\xeba\xf5\xb7\xd2Y\x18b6\x9b3\xf1R\xfeV\x92\x89Qe%\xfa\xbfuK\x1b@M\x9fk\x9eli\x1f\xd7l\x03v\x9dT\xff\x84\xcc\x17l\x85br\xf9c\x001\x95\xa2\xf6/\xa4\x9d\xf2\xb41UO\x8dq{\xd1*+\xb5\xb0P\xffM\xb3j-\xe9'\x9a]P\xf8DV\xd0\xfb\x1bl\x03\x81m\xf8[\x0f2\n\xfc\x97\xc2c\x8b\x91\xbc\x06\xbd\xad\n|\xb2\x98~Y\x8b\xc3\x8c\x14\x1ez\xc3\x9a1\xa1\xbeD\x85\xd2ku\xe0V\xad,\x846\x9a\n\xe7\xe0\xa0Z\x87v\x1d\xe6\xda\x1ax*\xd7\xed\x1b\xc7OCZ\x9f\xa9\xccS\xea\xca\xac\xd8\x9a)\xeb\x9ci\xfb\xe8\xae\xcd\xf4\x86\xb4\xfd\xce>\xae\xcf\x1eX!\x91\x07\x06\\k:jZ:\x00])e1Y_uk\xd8\x8dS\xbc9v\xf3\xdf8C\xe25\xc1\xff\x84 \xa1\xbeA62\x0dT\x1b@\x06\x0d\xf8\x1a\x04\x1ap\xa8w\x82\xcc\x16z\xd7j\xc0\xb1\x15\xa8\x8c\xc5\nuxO\xd7\xed\xd3\xf2\xd7\x19a\xefT\xf3o\xa7\x9c\xb4\xd8\x11E\x1b\x7f\xde\xcc\xe4\xed\x17(\xb2\xec(\x99--\xfe\xebu\xdd\xcb\xb0\xaf\xee\xf6\xde\xa3\x93D\xcf\xab\xb3\xc2\xdd\x993'\xfd9E\xff\xde\x94\xcacgk\x1c\x94\xc9\xe9\xf9\xb3k'\xa7O\xae\x9d\x9c\xde\xc5\xc1\x97\x92t<\x99\xd8\x8b\x11\x18\xb6\xa6\x17 S7 \xb7\x82-\x04\xe1\x16\x19N\x9b9\xa4\xeb,zF+[UFK\x0bUy\x1b\xeb`\x97\x0f\xda\xe5\xb73*Jdk\xd5\xb2\xab\x9b?'\x18\xd4\xa2\x1e\xf0\x9f\xd5\xc3V\xf9m\xf5\xe0\x19!\x8bF\xf1\xed\xfa\xc3F\xb3\xeaV\xfd%c\x01\xef\x8c\x1aJ\x8dg\xd4XA\xbc\xbc\xdd\xae \x9eQ\x8f:\xe0\x19\xed\xdb\xeb\x80\xe3CW\x1dp\x16\x144\x82#\x8ey\x05\xbd1\x07\x93\x82\xa2-Yf\xd0\xf6\x96D\x02Nq\xfb\x9f\x88\xb0?\x9bZ\xbd1\xa9\xaawL\x98U\x9a*\xbeH\x9a\xaa\xb8Vg\xbb\xf1d\xe2\xdb\xee\xa4\xc0\x9aq\xac\xac\xbcC\xb7\xb7CH\x026\xa4\xa3\xb0}\xec85\x8a\xe5\xb1\xcd\x8f\x1d\x8b\xfa\xc6x\xec(\x07\xa9Z$\xc1p\xb7yx4\x96>\xa1\x8c\xe4\x05\x19\xb3\x9b]\xfe*\xa3\x12\xf3\xab\xbd.0\xc4/\xbeC6\x94\x98NeS\x18\x9f\x17\xcb~-,0\xf0\x14N\xbfg\xd6'\xe7$_y\xb4\xac\xae\x12\x1dJ#\x8cE\xf5\x0b\x02 \x90\xcd\x93\xa4\xc5\xa6$\xeefZ\x1aHR,OY\x1e\xff\x7f8\xf2o\xc2\x91\xeb\xc6ry\xa2\x08&\xb2\xbai\x14Q<\xa4\xcf1\x85`\xc43G\xab\xe5\x10\x81\x93\xebi\xf4$9H7I=/K\xaf6\xd1q\xafCM\xd3\x1e\\[\xe7T\xdf!Y\xce|y\x819\x0d~.\xbdw:Nf\xde\xee\x93\x95\x8f^\xc2\xd08\xebn\xff/\xd2 \x15\x7f\xadz\x85iZ\x85\xb61\xcf#3t\x90c\xcc\xb9\xafa\xd88\x1d?\x85Xk\xc4\x9b\xea\x80L\xf9\xb0;\xd5[\xc5\x7f^\xfb\xb3\x99\xc2G\xf65\x8f?\x91\xe0\x0bu>8\xfb\xa48FM|J\xdb*\xa01\x8d`\xcaq\xac\xf7\xf7\xbf\x9f\x9c<\x7f\xfd\xfa\xe3\x87\xc7O^\x1d\x9d\x1c\x1f}89\xf9\xfb\xdf{mG\x90\x05\x7f\xbb\xf0P\x1aM:\x11\x81X\xaa5\xb1f\xb5&\x05\x05U([j\x88\xb1\x1c\x9c<4\xa5w<\xae\xf0|\xc1V\"|\xba\x04\xa3\x9f\"b\xd6\xbd\x17\xebJ\xae\x85#\x08\xa3\xcaf\xdf(_G\xd5\xb4\x88\xc8\xea]\xad)\xf3M\xc2}\xee\xa4Kc\xcc;\x10\x8c\xf9xg40\x99j,\xed\xce\xbf@\xa5u!TZg\xb4\xd2d]\xfc\xbfM\x93u\xe6\x86_\xa9\xee3\x14X\xd4\x7f-\xe8pJ\x95\x03\xddBSj-*\xa5\xd6\xa2\xae`R?\xeb\x0f$k\xb0\xa0\xba\xcej\xe1\xa3\xf0Y\xb8\x14>\x8b.\x85\xcf\x82\xaa}\x08\x038\xa7\xf2\x06\xdf\x8a\x88\x92\x11\xb0`N9q\n#\x98\xdf\x9cFh\xfe\x97h\x84\xe67\xa9\x11\x92\xfe\xf7.\xc5\xd0\x9cV~\xfa\x82r\x9f\x19(\xf7\x8aFp\xca\xf7\xc9\xdc\x83\x16\x9flJ\xd8N\xffC\x84\xed\xc2 \xcd\x95 l+>\xde\x13\x1a<\xf7/\xbby\xf4\x05\x84\xed\xad l\x97\x1aa\xe3\xb7\xfaKZ\xcc\x92){\x9c\xa6\xbe\xd1\xfc\x97\xde\x8a\xee\xa7nE\xf7)\xad\x1clO\xf5\xbdvA\xe5\x0d\xb9\xd7Np\xaf\x1d\xd1\x08.8\xb5<\xba\xb9\xbdvt\x93\xbb\xe2\x98\xc5\xe3O0\xe4\x1bb\xd4\xde\x10G\xd7p\x05\xa9\x1b\xe3g$6\x14\xaaG\xbd\x15\xd1\x92r\x93\xf0\x81H\xbcNvv\x1e\x84\xf8\xbd\xf0\xaa\xb2\xef\x058\x04\x99\x84\xc6\x14\xf7W\x1b\xf9\x82\x90O\x1b\x01\x88\x8f\xba2\x1c\xf2_\x86\xec\x1d\xad^\x96\xc5\xac\xab\x97J\xdbP\xae\xaf\x9f\xd6\xa1\xd4\xf4\x95\xce$\xb8\xfb\xb7[\xedD\x1a\x03\xcc\x07\x1e!0\x9bo\xc1\x0e\xecq\x88?\x12j\xc3\x9d\x9d\x10?\xb3\xf1\x05\x98Y\xa5lcH-\xb9\x0f\xf9\x825\xd7\x82_\x86D\xcbu|\xb4\x04S\x96\x9c6\xae\x87\x16o\xd5\xac\x18*\xef\xd6\xcb\x9f3\xe9\xda\xff\x98\x9a\xc5\x93\xd6\xe2=\xe6\xa4\xc8C0\x91\xead\xb4u\x05$\x0c\x05G\xe4^\xbf*\x07I\x87\xd4\x82\x0c\xb8\x19\xba\x1d\x9b\xaa\xe4\xed\xcb\xf0\xa0\x0d84&\xb2\xe4\xd9P\x00*4pT\xa7\x10\xeb\xdfN\x9d\x0f-2\x8aw\xca\xc0X\xdb\xfa\xb3\xc6\xfa\xd3\xeb\xae\x7f\xdb\xfd\xba\xb5\xfeYge*\x1de\x8b4\x19\x93`\xcf\xdd\xa6<\xa66i\x97\xa3\xa1\xa7:\xca\xd4\x95\x0f\x067\xbb3\x9d\xa2\x8d\xd67\x9fF\xb6\xb8\xce,6\xb12}i|\xb6D\xa9\x06\x06m\x82W\x9c\x15q\x83\x8d#\x89\xcf\x91\xc9\x89\xca[\xe9\xe8Q\x0e\xd6\xc7\x15\x8cbq\x11\xa2\x7fe\xd6p\x7f\x08jM\xd7-TeG\x17\xa49\xfa*M\x8f5\xc6\xaf<\x99\xf2\xda\xc9\x84e\xce\xb2:\xc9\xe2\x07\xcd\x83\x10\xeff\xee\xd3\xdd\xbd\x88yc\x11\xb3k\xad\xdfcj\xaa0\xddX\xc3\xcd\xd4V\xa5.\xa9\xad\xb9\xaa\x10\x94\xe3\xeacZMH\x9f\xcc\x86a\xc8\xfa\xcc\xf6,z\xa8\xa3kkAe\xdc\x81\xbe$\xd5\xd1\xa2y~\xb9\x90\x82\x8a=\x977\x10!\xaf%\x13\xccU0\x08\xd5\x92 \xe27y\x07\x13\xe85Y?\x1d\xa9\xd7l3\xb3\x0e\xb1\x9a\xa9\xf1\xec\xcb\xfdNn\xcf\xc8\x84N\xaf\x7f\xc5O\xe4]\xf1\x03\xb2\xdf\n\xd0\x91\xf0\xec\x17\xcb`Q\xd1\x98g(Z\xead\x1e\xba\xb2\xf393\xf3\xf9D\x05\x1c\xa1\xd6\x15\x85\x9a\x01\\\x1a\xa4\xf7c\x1a\xc1S\x93\xde\xf5\xc3\xe3\xa7/-\x9a\xd7O\xfc\xfd#\x0fi\xffq\xe9\xae\xd7\x91?\xb4.\xf3\x7frf\x94\xa9\x98\xe1L\xe7\x84\xb3\xa6\xa3^V\xd1\xbf\\\xfc\xaaS\x07\xbf\x94\x81o\x9d\xa7\xee\xb1\xd0\x03\x1cs\x80<\xa6A\xcb=\xc5\xd2\xe8\xbbnq\xb1D{\xabYR;\x9c\x86\xa8\xa3cCjH\x84k\x85\xa4\x9e\xbe\x8bU\xbc1\x0d#\xa8\\&\xb5\xd0\x88\xe3\xd5\xfc4K\xb1B\x82\xeby\xb3\xadf}|\xfd\xd7':|Z\xaa\x17?\xf9h\x03?\xb9\xb4\x81\x9f\xba\xb4\x81\xbc\x0b\xdd\xb6\xf6D\xb7\xb5E@\xfb\xcf+\x02\xf91\xe2\xcbDM\xe9\xbfdJl\x8f4_\xafH\xe0bE@.8\x91\xb9qE\xa6\xed\xeah_\xaf\x8d6zh0\x06U\xbe\x07\x8b\xe9\xcdi\xdaV\xd8c\xa61\xad\x15\xc4\xbbm\x9a\xc0\xb2\xe7tB.\xc9\xe4\x98|\xf6\x00\x8cF\xe2\xdf\xcb\xa8s\xbf^^\x1c\xfb\xb7\x8e\xc01\xa6\xc2\xf6\xd1\xccc\x82\xdf\x9e\xfa\xa4\x07\x9c\x85Y-H6\xc5\xfc\xda/\x8eQ\xe7\xc8\xff\x10\x16\x1e\x0b\xf8P\xbb\xc4\xdf\xf1\x9d\xde\xdb7\xff-\x13|\xfb\xa6\x9c\xe2\xdb779\xc9\x97du\x0dAC\xf8\x13\xd8\xfa\xa4\x93F\x8f\x1eU\xa3\x10\x98\xfcS\xcc\x89\x1aX\xcc\x1b\xa0\xebI\x0f1\xa1\x89\xb9<\xb8aXB+\xb4\x19,j\xc8\x125W\x9c\xa1\x84\x8ay\xbbYh.Sc\x18\x08\xe7@|6o\xa3oRZR\x04=\x84C\xe8aE\x028\x80^\xd4\xb3c2\x83\x01\xf4\x0czTu} \xa6\xbbp\x9c\xcaR\xfd[{\xe8\xb2\xba-,%\xfc_t3\xdaR%\xa4\xb4I\xe1\x9a\x96^4x\xe6\xf4\xda\x9c%\xc8\x1d\xe0\xc5\xb7}\"\xab/ ?\xcf\xbdVt^\x93C=\xd0\xaa\xdcb\xf5\x94\x9d^\x9d\x89\xb3t\xc3\x0d\x16A\xe6\\\xe0\x06\xae\xb5\x1cT\x1e\xc2>\xe6G\xe4\x98\x02\x07b\xc3\xb6\xb6\x83\xae\x06\xc0\x9a\xb5\x0e\xe4\xc8\xe0\x10\x82LR9l.\x94\xed\x92\xb2\xf4\xad\xa8\x18\x988\x0b2\xe7\xfe {\x9f\x9c\xcd\xd8\x86pS\x84Ig\x84*C\x94\x9b>I\xaeG\x9a\xdes\xab\xdd\x1dl\x83\xc6^\xfcq\xb7D*=\x19\xaeWWh\\\xbe&\x06?\xb9\xde!\xc1\xb9\x91\xcdz\x14yYD\xac\xdc\x1b\x8a\xa5\xc2LY0L]\xe5^5&\x9a3\xb3\x06\xe4\x80\xb9\x1f\x94\xba\xbf\x80\xd6\xfc\xee\xd5\xcb\xe9\x92\xbd\x8a7Q\x0f\x88}\x8d\x1e2\xbb\x11\xec\xecy\xf5\x92\x14G\xf3\x05\xf3\xb11\xc8^4\"\xae\xcb\xe9M\xc9\xfd@.c\x9d\x19\xf5\xe0EmFH\xaf\xd9\x8c\xb3%m\xee\xfc\x8e\xf9<\x0dH\xa5J\x12\xdb^\n\xb0\xe2\xe3\x0d\xf4*\xd8\xfb\x13_\xf6T\xf6\xefK\xa5@\xa3T\x1fI\x10V\x06)W\x06<%\xe5\x98\x88w\x17\xeb\x8a\xdf\xcb\xbc AU\xa7\\T\x12\xe7\xbbR\xcfy\xec%\xb5i2\x97\x99\xddU\x97\xa3\x94\n\x9e\x05\xba\xb9\xcdR!\xefJ?o}V\x8f|^\xc6\xe9&\xc2\xd69)\xc9\x86W\xfb2k\xa6\xc7V\xd3\x1dN\xcdk\x8b\x81Z\xfd\x13L\x97W+\xceDHu\xdf\xcd)\xd6\xab\xb7\xfeN\xc3\x86\xaa\xd5\xcd'\xd6\xaa\x1at\xf9\x8e5>&\xc6<\xa0\xea\xba\xf2\xe4\xf7\xc4.}\x93m\xb8\xdf\xa5\xf8\x81;|\xa3\xd3\xa5\x14Y6\xe7,,\xd5\";xn\xea']V\xc2%m\n\x97\xbc\xefa\x16\x01\x1d9\x05L/\xd6\x8aO\xff%\xf1%n5o\xf4M\x84=T\x8dQc\xa9]\xf3\x98\x1agd\xc7\x8a\xe8 7\xb3z8\xda\xb2\x99MF\xb1!rx\x0e\xa5\x02\xdc\xa6\xe3\xf1_-\xcf\xa1\xbc$r\x05\xfdF\x91o\xcc\xbc \xe8\x1f\xfb5\x9f\xc6\xec\xf5\xb5\xa51\xdf5\x02m\x13\xffb\xae\x93\xa4\xae&m\xabk\xea\xbb6\xb2\xd6Bn8k]\xc7\xa1\xae\x895o\xf1\x8d%O\xd9\xe2\x06ga \xd9\x1f5)\xc1WD\xd0\x8f\x12\x7f\x8c\xe1\xa7\xdd\xab\x0d\xcc\x90\xf5\x82y\x1e\xd8R\xa1\xa4.\xef\xfa\x14\x1f\x9fa]m\x9b>5\xaa\xfcd}\x07\xfe\x9cz\x0e\xddTnZ\xf8\x03c\xa1MUa:\xabU\x98\xee\xcc\xb6\x9c`\\\x90GV\xe4\x00}\x1a\xb1Z:\xc6-\xa9\xa4\xc4I\x04+\xceJ\xafB\x14\x13V\x95\xbf\xa7\x19D\xaee\xf1:\xad\xce\xf2l\xb9\xf8w\xb0\xe2~6\xbc@f\xbb{\xc7P\xd5\xc5\xf9wO\x06\xde\xc8\xb9w\xe9\\\xf8\x95\xb59w\xfe\x99\xe0\xdc\xbb\xf7\xb5~I\xf0\x04\"\x04r\xbd\x86\xe1(\xc4\x18\x06\xccY>\x8c#HFp\x00\x89\x87q\xd0A\xc7\xec0P(\xe8G\x81\xb3:\xe5\xed4?U\x14\x8cD\x90\x04&\x12\xa9.\xcb\xf87\x165f\xf1&r\x06\xd2!\x99py%b\x08V\x9e\xbd<\xdf\x84\x86\xab~\x9e\xd3M{J\x8a\xe3\xe5\xa9g\x81\xcfR\x06\x1c\xd8|\xc2\xcaJ)\xc2\xea,y\xf4J'\xe4\xb7\xb4\xe5y\\&\xc6\xd9 \x9f\x96y\x8a\x0b\xce\x0bm2\xc9\xc05K 3m\x96ay\xd3\xffT\xfbDVo\xa7\x1b\x0c\xa9<\xd483\xb7\x11$o\xc0H(\"\xce\xfd\x8f\xf8\x9aV\x86\xef\xea\xe7-)\xd5\xa7\xdbts5Z\xab\xe4W\x1f\xf9Y\xff\xfe^^g],\xbc7\xae\xb11\x97U\xbb\xefy|\xb9A\xaf/\xd8F*\x8cy|\xb9\xe9\x99\xfa\xa2\x96\x8f\xc8\xab\x13?\xa3Yk\x06p\x08\xef\xa9pa\xf9\xe8'(\xcd\x13z\xfd\xe9\x88\xee\x98\xe8\xcewn9\xd9\x18\x13\x8d!\x8f`n\xbe\xf8\x94,6\x80\x9d\xd6\xfe\xeb\x98\xcd\xfa\xf3\xf82\xb0T$\xb6t\xd6\x14\xbe}\xa5\x04\xcb\x1e\xe3M\x06D\xbb\xe3=\x90\x9fgI\xba\xa1\x99\xa1\x1c\xccO\xd74l|J\x16\x1f)K\xd2\xcd\xba\x15@WC\xdeL\x05%\x12\x82m\xd6_\xdb\xcaa\xc8\x0c\x06\xe6\xfeX\xfc\x89l\xb0\xbc\xacf\x80\xb8\x06J\xf1\xfen\x18\xa5x\x93\x9b\xa3\x14\xff\xeaKP\xea:\x92\xc4?\xbc\xb8[\xad\x84\xd1G\x8aj\xdeZ\xf26\x8c\xac\xec`x\x15;\xcd\xac\xdaeuq\x91.\xab\xc7\xe6i\x05Zja \xd8\xb1\xbb\xb5sY\xcf\xbf\xa3\xec\x7f\xc9\xb8\x19\x04\x1f\x82*\x91e\xd7\x0c\xb5f*\xe9\xa7\xfc\xf6\xd6-\xd8\xde\x8eQH\x95\x0dZ\n\x95\xab\xeb*\x8c \xb6\xbeq\x15\x81^\x06\xe9\xbfhU\xb2|\x93e!5o,\xfe\x9d[\xae\xe5\xd7\xd2\xe1Q\xa2.9N\xcf(K\xfdB\xdf\xa9e9\xd3\xee\x0f\xc0?\xe2Q\xbf\x9c\xd1\x8f\xfae\x89\x95\xd0/e\xba\x89;\x8bS\xa9K\xe8\xf0kE\xaa<\x1c\x1aUD\xa3\xac\xdf\xeb7\xd1B:\xab\xfa\xbd\x9d\xe2\xdb{\x1d\xae\xad`\xdaki\x04\x05j<\x0f9i\x1b\x0c\xe0\x8d\x14s>s\x8c,\xf0\x05\x91\xe6o)=C\xfe\x0b\x16\xb7\x8b\x088)\x80\xf1\xe1\xe6\x9aW~\xf0\\\x97\xa9(\x0f\xad\xcd\x98\n\x15C\xb0!_\xba\xb9\x186\x8b\x8b\xd9\xd3l\xb2\x81\xa3\x0b\x9bU\xd9\x05\xb0\x8a\xf3L\xcf6\xd0\xcd#@\xb9\xbd\x84\x83\xf2`\x00{p\x1bv\xcb\x8d\xe6 ]\xcaL:\xeeT\xf0\xf9\xb9\xf2\xa36\x16\x0ea\xcf\\\xf5\xb6|M\x0c\xcck\xf1\x1b\xdf\xf0\xd1^\xa2\x90~\xe7\xee\x9d\xfd\xef\xf6\xbe\xbds\xefN\x18\x95\xb7\xe1\xe1C\xd8\xbb\x07k`\xf0\xe8\xd1#\xd8\xd9\xbb\x17\xc1\xdd\xfb{\xdf\xde\xbd\xf7\xdd\xee7\xcd\xf7\xeeh\xef\xdd\x89\xe0^\xf5\x1c\xd3\xb9\x07\x0c\xb6\xe1\xce\xb7\xf7\xef\xee\x7f\xb7\xbf\xf7\xdd}Xs\x98\xfe\x8bo\xe9\x7f\xc9\xcf\xf6\xeeG\xb0\xbf\x7f\xf7\xfe\xb7\xfb\xfb\xf7\xca\xe6\x8f\xe5\xe7\xd8M\xf9\xe6\x9d\x08\xee\xec\xdf\xbf\x7f\xf7\xdb\xef\xbe\xdb\xfd.\xd4\x9bpl\xb9@\xe7\x0f(\xd6\xba<\xdc\x10j0\x80;{\xf05\xe4\xb0\x0d\x9fi\xf0\x94\xe0\xa6yJ\x02\x16\x86|F\xf6\xce\xc1sw\xaaKh\xc5\xaf\xd1K}R>\xdd\x943\xc2\x8e:;\xd8\xacq\xcfvCc9k( \xa2\x89\x14\xd6\xee4\x95\xc1|/~\x10\xc9\xc9\xb4\\\x00\xfa\x1b\x1f\xe8p\xaa\x02\xbc?\xd0\xe1+\xfe\xf7\x07i\xb2(\xf8-\x19:*n\xcb\xc0\xea\xf2\xbe\x1e8\x04\x03xF\xf1IB\x8b\x85\xc8\x8d\x8f\x9f\x1cg\xcb\xbc\x9eW\xc6\x04\xb2\x86\x12I\xba\xb7\xd6g\x87\xad\x8fgqBE\xdb\xd2\x96)ng\x94\xc5 F\xa5\xe3\x10\x84\xee\x12c\xc4s\xd3)9M\x93\x0dB#K\x01\xe5#\xb3\xae\x84I\xed\xb38j\xb9\xf7\xfbZ\xff\xedT1\xb7\xcb\x02N\xe1n#\xc3j)M('\x89a\x12A6\xb2\x17\x9f\x06\x10FU\xcd&\xe9)4\xce\xe3\xc5\xcb\xba\x0f\xb2/\x8c\xae\x01\x04\xbe\xeeMXt\x89\x19-X\x88h\x04\x07\x10\xb0\x93\xeb\xec\xd6\xd7\x14\x93\x9btf\xeexn\x07\x92\xdaI\xf5\xbe,\xed\xfc\xde\xd9\xce\x90E@F^\x8d\xbd\xb1\x90\xc3\xe6\xd9\xdc\xb1\xd9\xb6\x88O2.h\xc3\xd32\xac\xf773\xac\x9d\x1b\x1e\xd63\xf7\xb0z\x05\xd2\xc0\x9a\xf1\x03\x0e\xe1\xc5\xf1\xdb7}\xf1(\x99\xae\x84\xdaVRK\xcf\xdc\xa2\xaf\x9c\x04\xf8\xd8\x9a\xc9\xd3\xd2\xdc\xc7N\x0c\"\xf0\xb0\xe4\xe0\x08<\xc2\xbfw\x90\x9d\xf3\xea\xe0\xb3G\x07\x9c\xf5\xd9\x86\xfd\xfb\xf7\xee\xde\xbds\xef\x9b\xfb\xdf\xc16\x04\x843d\xf7C\xf1\xe7\xa3G\xb0\xdf>}\xeb\x0b%[{M\x87\x0bu$\xbe\xae\x8eD\x19\xa8\xc5\xef5\xceD\x91^\xa0|\xd08\x14;\x89\x9a\xec\xb6\xb1\xb0\x0c\xa3o\x0f0\xfc\x161\xa5>p<\xd82s\xf2\x93/M\xdf\xe0\xa73\xbf\xd1\xc0\xa9=\xbf\x93b\x9a\xd0 JO\x9e\xdd~\x817\xdd!:\xd3\xc1\x01\xec\xb4\xfd\xffLfN>*?\xc3\xd5\xb9\x9e>S\x99\xa8\x9c\xa3\xd1\xd2\x0c\x97{\xc7\xcb\xd53\x8d\x0b\xf6\xfc\x9a#+\x8dq\x7f\xd9\xe8n\"~\xc3\x13qn2~\xc3\xb7\xcb\xc5\x06}*Dm\x86\x15\xd9\x9d\x98\xf9:U\x96\x02.u\x8a\xa0Z\xb1\x10\x98\xf6j_\xfe\x89\x15\x8c;\xb23\xf2\x8b\xa8\xec\x8c\x9c`\xef*\xe7~t\xce\xafRDt\x04\x85VI\x15\x959\xa3\x03{J0\xef\xc9\xd1\x1eB\x0e\x07\x90\xab\xd0\xfdc=\x02x_94\x88\xd61\xc7\x81gP\xb0r\xee\xfc\"\xf2Qz\xab\xfe\x15$\xe4:\x8e\x9f\xa2\x9a\xbdW\xeb7\xe4\x9a\xe8\x89\xfd\x1b;\x0d6\xd2k\x87\x88\x82\xaa\x14]]\x0b\xa5e^\xafG\xd3\xdc\xba%\xf8\x8b\x99\x96dU\xe1\xed\xb5\xfc\x11EUmKV\xa5M\xdd\x117s^j\xc1\xe3\xd1\x00v1\x07\x85%\x90\xc8\x02(d\xbefUt\xd1\xce^\xf5\xa5<\xb4Z\xd5\x14\xc1v\xc61\x92/\xb2b\x13\xd3\xe6\xf5\x93|\xf8\x99\xf5\xaa\x12\x03%\n\xec\xc3\xd7\xea\xd7\x0e\xec\x89\x02\x03\x0e\xcb\x9f-\xf5\xa1~)\xa3\x01s\xca\xe5\xeaJ\xbe\xd8V\xd79 \xad\x8d`+\xc1R\x00b]Eh)\x17\xd1\xb30\xd4\x92\x96b\xb3\xf2\xbe\xb3\xe5+\xde{\xe4\xca\xa3\xa1C\xd4l\xb6\xf3\x06i\x84\xb0\xaa\x19\xd0~\xc7\xfe;'\xefo\x0f\xbd\x86\xfd\xac\x84l\xc6!\x1b\xc3\xff\xe5\xb2\x03\xdfz\x1c\x07\x92\x9a\x0b0\xc6\xfc\x1e\x88w\xe0\x10>\xf3\xb9\xc7\"\x1d)Zm\xd4\xcfL\xa5\x8c\xed\x02\xbf\xd3ZbIU^Q \xefm\x9c\x92\xf8\xdc\x87\xf3Rf\xb9!\xefbd8\x94C\xc7bq\x1e\xe5\xa5 \x00J\xff\x12\xc1\xcb~6EgZ\xebg\"?\x89\xe6\x9d\xef}\\\xc3\xbf\x8e\x1f\xf8\x9e\x11\xaa7\xed\xde\xe3y\xf2\xffq-\xbd\xeaK\xf5\xc7+\x1a\xb9\x90\xcd{\x0c?'l\xe6sN)\x99G\xef\xc5\x8do\x9c\xa7S\x01\x02\xed\xf1\xdbL\x96\xb5;W!\xa7\x08Uz\xd8\x89\xd27\xe87\xcb\xba-\xef\xd0q\xbd=\xfc\x8dy,\xc4 Q\x0bZ\x9a\x95\xbd\xe4\xb4\xeb\xe6\xd31T\x9d\x86\x9b\xd9l\xd8|\x95\xc3\xcd\x03\xda\x89\x96g[\x94\xd0\xaeY \xf4\xc7\x9a%A\xbf]3)\xfc\x1a\xe9J\xda\x10\xef\xbd\xac-\x9f\xb8\xf7C\xadiq\xef\x84\x18>\xbe \x86\xaf\x8fH\xf3\xf36TT~\xb9\x03\xa0m\xb8\"P_\xb4\xef?\xcd\xd2\x94 \xa4\x0f\xe0\xd4\xe0\x03\x81\x01b\x1f\x0d\x0f\xf4\xb4\x92\xefX\xfb\xb9\xc8\xcb\xb70<\x91\xa9\x02\x8f\x8c\xa3d\x07P\x18\x1e\xe8Y%\xe7\x86\xe7\xef\xc98\xcb'\x07\x90\x9b\x9e\xc5\xf4\x8c\x1c\xc0\xca0\x89\xf7dAb\xde\xa4\xe1YR\x1c\xc0\xccp\x7f\x9agsLmkK\x97|\x15\x01\xe9\x93\xcbE\x96\xb3\x02\x93\xc4 \xac\xbcr\xfb\xb4\xf5\x96\x05\x81\x82\xe5\xc9\x98i\xf9i\x94 ]\xdbn\x9a\x0f\x8d\xdeQ\xb3u\x15\xfb\x16G\xb0\x8c\xa0hn$L\xc6\x1e\xb00\x82-\xe3\x1e\xe6]\xa7m\xfa\xa7\xa5\x01C=OX&L;\xca\xf3,\x0fz\xaf\x13\x9aL\x132\x01r9&\x0b> \xc8\xc6\xe3e\x9e\x93\xc9\x03\xe0\x93d3\x024\xa3;s\xf5\xe2\x84\x9c\x03\xa1\xe7I\x9eQNu1\x02\x8b\xbf4]\xa6)\x10\xde*\xccIQ\xc4g\x04b:\x81x2Ix\xb3q\n3\x92.\xa6\xcb\x14.\xe2\x9c&\xf4\xac\xe8\xf7\x0c\x14\x9b\xa4\x05q\x90\xfc1\xe7i\x9a\xc0r\xf8\xf7L\xed\xfcfP\x07\x05\xeb\xe7d\x91\xc6c\x12\xdc\xfe\xbf\xc5\xed\xb3\xa8\x9b\xa8AE\xd8\xc6\xc3\xe9\xf6v;\x84\x17\x90\x8a\x85a\x9f\xc6s\x0c\x8dxN\xcf\xe3<\x89)\x83\x9f\x92,\xc5\xe4\xdb\x86\xfc\x92\xad;l\x96g\x17\x90\xf6\xa7y<'\xc5\x87\xec\x1dV\x91\xd9k\xa6b\xd3\xb0\xfa\xcb\x91\x98\x06w\xee\x86f\xdc\xcd\xaf\xdf\xba#K\xa2L~>!\xd3\x84\x12\x95\xfc\x9c\x8bE\xbd\x93\x13R\xbc\xce&\xcb\x94\xf4L\xa4T:I5\\\x9e0\x8f\x12\xe7\xbb\x9ef\xf3yF\x8f.\x19\xa1\x85\xcc\x7f\x8e\xf7\x1bwH1\x8e\x17XS\xf1UB?\xbd\x8b\xb1\xae\xa2J\x9d\xdf\xba]\xcc\xe24\xcd.\x8e>/\xe3TV#d\xfd\xd3e\x92N\xbe\xcf\xf2\xf9\xb3\x98\xc5\xe2\xb5,g$\x97OY&o\x92<\x89\xd3\xe4\x0frL\xe2|,\xda[\xc4y\xa1\xff>#\xec8\x9e/Rr<\x9e\x91\xb9\xf8\xee\xaf\x17\xc7o\xdf\x88\x9d\xd1\xe9\x01\xc6\xf2U\x07\xb3\x8c\xb6*D5\xab\x8eF\xe8\xa8o\xdd\x82^\x86\xbd\xf6D\x11\xb2\x86\xb1\xa0\xb7\xa4b\x9fNzp\x00\\\x82*\xf8\xc6\x8d\x97)\x0b\x03\x16\x86\x8ex\xd7+\x18\xc7l<\x03q8\xb6\x1e\xcb\xef\x1a\xd9\x1b\xae\xf8^\x16\x03J\xa6\xabNH\xc8F\x8e\x05\xc3|$\xf9f-\xa9<\x1c4\xfb\xc6\x1e\xe2<\x8fW\x1bt@d\xb3\xe8]\xa3\xff-\xeaI\n+\xefp\xd4\xeeH\xb0%\x92O\xd2z\x03b\x0eM\xe3\xabr\x84\x1eT\n\xae\xe6\xb3\x9eAB\x0b\x16\xd31\xc9\xa6\xb0RK\xd2\xe7[\xd2\xf5i /\xc6\x01U\xcf\x86\x8b\xb7\xd2\xb2)\xce\xb8\xcb\xb4\xbc$\xec\x8b\x8c\xce8\xdb\xea\x95\x8a\xd9\xac\xde4\xd5Nd\x98`\xf0Cv\xcc<\x0b\x05)\x15\xa3)\x87\xbb\xd2\xfd\xecF\xb0\xacP\x91\xb4\xb3\xf3v [\xe6\xf0\xc5!3$\xe80\x14\xbe\xeb*\xc6N\x879\x17\x0f\xc90\x1f\x89\xf4\x8at\x99\xa6fMt+\x13&\x82\x8cf\xf9\x1c\x0f\x0f\x81s\x03\xb8\x8c\x90N|O}\x91\xd6<\xc1vOIQ\xd2\x9dc\xd9\xc7\x92\x8eo\xbe\x175\x11\xaff\x9b\x99\x9a\x8dT\xe2u\xbc\xf0A'+\xca4\x93\xfa\xba\xf4\xa2\xf5ue\x01_Y\xa1\x8a5\xe5\xee\x84?\xdb\xa5\x84p\xc8\xef\xb1\xcb\x7f\xdb\xa8K\xc5x9^\xa7\xee$s\x1e\x08Y\xd7\x81 U\xda\xfcn\\\xdd\xa5\x18r\xb1\x01\x98\x8aU\xc1\xc8\xfc\xc3lI?\xbdN&\x93\x94\\\xc49\xf1E\x9c\xee\xfd\xcf\xfa\x93\xa4X\xf0\xb3I2\x8eH\x97\x9cp\xe9n\xd4\xf4\xb2\xd3\x82\x05\x1d[\x08\xcd\x93\x01 0\x959\x0b,\xbel`\x14#\xccw\x0d\xe7\xa0\\#\x0e\x80e\xf14\x9btC\xf9\xbcL\xb2\xa5\xaal[I4+55\xc1\x05?[.\xf8D\xfc\x93\xa8+\xe0\xec\xf7Ty\xd4m\xe8\xf5Bc\x06\xa5\x10\x19pK0\xf3\x95\\f~\x82\xf9l<\x8c\xce\xa9N9\xa5\xc0\xe1\xbc\xa7\xfc3\xd0\x8a)V/\x8a\x13\xb2\x0d\x0eu\x9a\x11\x99\x83\xc0p\xec2\xce>\xb0\x91\x1d\x96\xf5^\xfaI\x81\x9dQ\x91\xf8\xfe\xa05\x88\xf6\xfcg\xc9\xd9,M\xcef\xdd\xdc\xa5Z\xe1I6Fu\xab\x99\x01\xd9\xaa\xf8\x8c\x9e!s\xaf\x08N`\xe4\x92=\xcd(#\x94\xa94\xac\x8f\xe0\x1e\xb9S\xc5\x03\xe9\xafX'\xdf\x8d+\xb5\xec0\xba\xd2@\xa4\x83\xab\xfa\x88\x90\x0b\xdf\x8dP=\xb2\x1c\xee\x8e\"\xd44\xecE\xa8@ \xfd\x84R\x92\xff\xf8\xe1\xf5+\x91q\x18\x16\xa8V\x10r\xb2\xa8g\xbb\x80\x87\xf0\x0d\x92\xc9\xdf~\xc3\xfdJ\xa5\xe7\xdc\xd8\x99m\x86\x03\x84\xf7\x94\xaa\xae\xb7\xb7\x8b\x910\xafM+\xd8\xecE\xb05\x86\xf5\x1a\x16\xf0\x08\xbe\x15\xbd\x08\xaa\x80w\x87\xb7\x7f;\xbe\xddg\xa4`\xc18\x8c\xf8\xdb\xfc\x83\xdb\xc3\xaf~\xbb\x18i\xf7\x83\xdem9\xb2\xf5\xbal\x80\"iN\"\xf8[\xefo\xa0\xdcN\x92\x08z\x7f\xeb\xe9?\x97\xc3\x02v\xe0\xee\x08\xb6\xd1)\x9e\xf2g\xbd\x9d\x9d\xdf.\xefp\x99\xbc\xba\xf5\xf5\xed\xdeh\xb8\x18\xb9\x8de\xb8,SQ\x98\xa1\x1f/\x16\x84N\x9e\xce\x92t\x12\xc4\x9a\xc8}\x94\x12\x8efA\xafX\xc4\xb4\x17\x86\xfd\x82\xb0\xc7\x8c\xe5\xc9\xe9\x92\x91\xa0W\xb0\x15\xaa\x03\x86\xbdq\x96f\xf9\x01\xfc\x9f{\xf7\xee=\x80iF\xd9\xce\x05\x11 qO\xb3t\xf2\xa0\x17\xe1\x8a\xe1\x7f\xfa\xabxo4\\\xc0!\xae\xdd\x1d8\x84}8@\x08\xdf\x87C\xb8+\xff\xe6\xf7\xef\xc0\x01l\xdf\xfeW\x10\x07\xa7\x05\xcb\xe31[\xa7I\\\xac\xe9d\xadL\x0fk\xbeg\xd7E0_\x17$g\xe1\xe1z\xc9\xb2p}\x1a\xc4\x05Y\x93\xb3\x84\xae\xb3,\x0dHL\xc3\xc3uN\xe2O\xeb\x15#\xe1z\x8c\x8f\xf9\x81\xb3\x9e\xc5\xf9\x1aE\xdb\xc9:\x8d\x8bb\x9df\x94\xac\xb3\xf9\"]g\xb4`\xeb\x8c\xb2\x84.I\xb8\x9e\x90\xe0tyvF\xf2\xf58\x99\xc7\xe9z\x9c\xc69YO\x03\xbe\xc7\xd7$\x0f\x0f\xd7 M\xd8:\x0d\xc8Y\xcc\xc8\x9a0\x12\x1e\x86\xebI\xb6\x9ed\xcb\xd3\x94\xacI0\x9ee\xeb\xb48L\xa6\xeb\xb4 A2\x0d\x0f\xf9<\xb0\xf6\xe8\x9a.\xe7\xebsB\xd9\xfa2\x18\x93\x05[\x93\xf1z\x11\xa4\xc98a\xeb,g\xe1\x9a\x91\x80N\x8a5*M\xd69\x0d\xc3\x90w\x9d\xa6l\x96g\xcb\xb3\xd9:N\x0b\xb2Nh\x9c\x06\xe9\x8a\x0f\xe5\x92O'\x8b\xf9\xd7\x01\x89\xc73>\xfb\x84p\xb0e\xf3\xf5\x92\x8e\x03\xbe{\xf9\x00\xcf\xd2\xec4N\xd7g\x19\xcb\xd6g\xcb8\x9f\xac\x93`\xba\x9e/\x02\x81\x03\xc5Z\x1b\x04\x0d\x12\xb6F\x95~p\x92\xd11 \x0f\xd7i\xc2\xa1\xb5dk%\xfa\xacY@\xf2i<&k\x92\xd38\x0d\x0f\xc3\xc3u\x11\xae\xd3 \x9e\x9fN\xe25a\xebl\xfci\x9d\xd1\xb3p=\x0f\x92q\x9e! \\\xa3\x8ai-\xd4\x08\xe1\xfaM\xfcfM\x83xN\x8a\x05o)f\xc99Y\x93K\xb6&\x17\xeb$]gl\xbdL\xd3p\x9d\x05\xc8\x16\xad\x17\xc2\x10\xbe\xce\xd7K\xb6>'y\x9eLH\xb8^\x04\xf1\xf8S|F\xd6q\x1e\xcf\x8bu\x9e\x9c\xf3u\xc93F\xc6\x8cp@\xb0l\x9c\xa5\xeb\xe5i\x9a\x8c\xc3u\x1e\xc4 \xc7\x98 \x9ed4]\xf1\x85\x9b\xae\xcf\x92\x82\x91|\xbd 1[\x7f^&y5\xefb\xbc$k\xa1b[\xb3|\xb5\xe6T1\x0c\xd7Ep\xba\xe2\x8b\x1f\xa7d\xb2&\xe9t=\xcbr\xb6N\xce(\x99\xac\x93?\x10<1K\xc6kT\xe7\xacY\xbe\x1c\xb3\xf5\xf2\xb4\x18\xe7\xc9\x82\xad\x97\x0b\x92\xafWt<\xcb3\x9a\xfcA&\xeb\x8b\x84\x8dg!\x87\xe8|\x91\xf2\xc1\xcf\x08]\xcf\x92b=\xcb\xb3\x8b\xe2p\x9d\xc7\xb4H8\xd2\xe4K\xb2\xceW\xeb\xd5\x82\x041\xee\x8f \x99\xae\x93\xc9\x9a\xc6s\xb2\xce\xa6a\xb8^\x064\x18K4\x9f\x90i\xc0\xd9E\x8e'\x19]\xa7\xa4(\xd6\x85\x18#K\xd2p]\x90u\x91\xf0\x05:\x0f\xe2|\x9d\xe4l\x19\xa7\xeb,\x99\xacQm\xca\xd7\xe7\"\x18\xcf\xe2\xfc\x84\x89\x01\x91\x9c\xacgIJ\xd6 \x9b\x85\xeb\xcb,_\xaf\x12\x92N\xc2\xaf$\x01\x9cr~iw\x14r\x16T'9\x8a\xdc| \x97\xecM6!\xc14\x0cC\x91Al\xc1)\x94\xa0\xeb\x9cF\x1c\xf0\xf3c\xaa\x1d\x00{{\x0f`k\xb8\x17\xc1\xed\xe1o\xb7\xff\xbc\x1a\x06\xbf\xedl\x7f=x\xf8\xe8\xe0\xc1\xfa\xb7\xdf\xfa\xd1\xe1\xd6\xad\xbf\xff\xfft\xfa{{\xf8\xdb(\xac\xdfhPhI\xa0\xc7\xbc\xe3\x0cS\x93sR\xff\xb0\x07[x\xceH\x12=.\xa9\xf3\x98\x1fS\xdb\x90\xc26\x12\xe8m\xd8\x1b\x95\x7f\xee\x8f\x90 \xffvyg\xbc\xb5\xb3\xd3So\xf2{\xb7\xbf\xae\xff\xbc\xcdi\xe1\xff\x11-\x8e\x86;;\x8b\xd1\x03\x87\x07\xcf\x14\xb6\x070\xf6e.\x8d2\xda<^|\xc8\x1a|\x97M\xf5as\xb1\xe4\xc7b#\xc9~\xf9\xcapo\x04\x87\xf5\x9f\x07\xd0\xfbDV\x06\x96D)\x06\x0d\xed\xef[\xdb\xdf\xaf\xb7\xbf?\xaa1[\xaf\xe3\x85\x89\xe1k0\x90\xaf\xe3E?)\x84\x96\x04=\x81\x84\xf7\xc3\x06\x1cd\x9dc\xa4\xa2\x82\x0dE\x0b\x89\x89g\xe4\xfd\xd3*\xef\xfd^\xa5\x11\xea\xcfI~F\x02\x93\x14x.\xa3\xe5\xbbG\xc3\xdf\xe4\x8c\x155V\x07\xe2O\x0bK\xf4\xbc2\xecl\xed\x99\x9fM-:]p*=K\xe6o\x11\xc1\x04\x06(~&\x9a\x96RE\x06\x04!\xa6 \xe4\x83\x0b\xf8\xb6\x9e\xd4\x1c\x85\xc2\x07r\xd8..\x8e\xf72\xe3\x14\xc3'8\xfd\\\x8e%\xab\xc62C\x17Y\xe7Ws\x0e\x83\xceP\xf63|k\xaf\xe3\xad\x15\xe7i\x83\xb3\x08h\x99m'\x82\x9c3X\xc12\x82yS\x0d\xad_mTPB\xc7\x8a\x0b\x1d\xb1r\xfe\xc0\xec\x87\xb1H\x9a\xb72s\x83\x06b\xa1\xab\x86\x8d\xdf\x8c\xa5k\x05r\xe5\x86\xef\xa7\x9c\xfbHm\x18a\xc7\x15~ma \xdeI_n\n\xedo[\xe2\xe6\x8e\xee@\xf1\xf7\xa14\xe0M}\xe1\xd0\xba#\xc7\x14\xb7I)\xb9D\x8e\xf4\xfb$%o\xe29\xf9>\xcf\xe6R\xa6y\x96\x14\x8b\xac@\xe3\xeb\x8f$\x9ex\x94\x95W\"\xde\xedi\x92\x12~l\x0fz\xc1\xf0_\x0fF_\x87\x0f\x0e{\xb7\x93>\xb9$c\xa3\xe1\x00\xcb\x9e\x08\xdb\x00g\xea\xebm\x94MT-\xd8\x88\x93\xaa\x9e\x82\xcdh\xb2\xa1F\xaa\x8c\xf9\x19\x94\x12n\x99\xa6m\x08-\xe2b\x1c\xa7O\xe3\x82\xc0\x00\x9e\xd6\xef|/\x07\xd9 \x1a\xd9\xc3\xd3\x80Tf\xe2\xdf\xfa\xc3\x7f\xf5o\x8f\xbe\xfe\xea6\x17%B\x93\xc6*\xa6 K\xfe \x1f\xf3\xb4\xb3\x07\x0e\x802vlK\x8b\x1d\xe3\xc2\x9a\xd0u\xb8ekM18\xd6{\x0e\x8dG\xf0\x19a\x8f\xc7\x9c\xcb\xe7\xd8\x92gi\x9a\xd0\xb3\xf7\xa4Xd\xb4\xe8\x86F\xe3$\xab\x14\xfe\xfd\xa4\xd0\xb4\xff\x9a:\x84/\x8dMcP?\xf6\xccoV\xfa\xa5\xbaCx\x97Wry\xc2\x15,\xceY\xf1s\xc2fAo\xbfW\xea#u\x15*:\xe9\xf5\xc6b\xf7\xf4\xf04\xfd\xf3*\xac\xb0\xd0V\xa8\xc1LlK\xd5N\xd0\x93]\x88&\x8dv\x12K\x1b|\xcb\x06\xd40.s#a\xa9|\x93\xa6.5v\xa1\x0d2CVA\x887\x9b\xb7\xf1dB\xc8\"]\x1d\xb3\x8e\xbaLmJ\xf3\xdeP\x86\xffye\x0eLi\xe0hf09\xd9\x15\xdaU\x1cQ\x1edC6\xc2\xbdr\x08\x13\x92\x12F\x80\xdf\xe1B\x0d\xff\x87\xf3\x03\xe2\x0dj\xcce`\xcaV\xabl\x03\x06\xb2\xa7\xa2!\xbd\x08\x89)`\xd6\x95\x19HV We=\x95Y\xd7r\xa6X\xad\x16\xa4k\xc1\x89\xb0Z\x94\x87\x12 \x1d\x0c\x84F|s\xad\x89\x08\x84}o\xdf\x00R\xc5\xect\x19$\xcdQ\xc2\xe0\xe2\x13\x88#\x15\x03\xebS\xf4\xbd\xf8\x90\x95\xfe\x1c\x1ek$\xbe\xb1\xac\x91\xd6\x9b\x15M\x1a\xa6\xbf\xfa{\xe7\xb2\x92\xe7I@\x83oL>\x12ctH\xba\xf7\xcd\x9e\xe1\xd9T~x\xef\x1b\xa3{\xc5B\xb9f|\xbbkz<)\x1f\xdf5=\x9e\x95\x8f\x8d\xe3:\x97\x8f\xef\xdf36>W.%\xbb\xf7L\x8f\xcfpV{\xdf\x99x\xff\x95\xfc\xf4\x8eqR\xa7\nX\xfbw8\xe2\xd7\x9e\x97\x04\xfa\xa4\xc3w\xe1\xd6-\x0c\xe1P\xbeU\xd2\xb5\xd8\x8c\x8b\x12\xa5M\xa5\xea\x9bQ\xf3\xfa/\xbe\xb0\x170\x80\xf2\x08lO\xe5\xc8\xe0\xc0\xd3\xad\xd9o\xc9\xc8fsL{\xb06`]ndv\xae\n\x047&on\xfc\xd8\xd9\xf8\xd6\x16q\xdaW}(\x95c\x0dtO\xa9\x89\xfa\xc8\x06\x86\xa7\xce\x91\xf2~\x17U\xbf\xfc\xe7\xd4\x7f\x18u\x07\xaeN\x16\xce\xa1\xf8\xd9\x8c\x8b\x18Z\xc4a\x0b\x8br\xc7\xda\xf8\x9dz\xe3wD\xe3NN\xbcn\xa2\x97} \xefQ\x7f\xc8\xca\x87\xeb5 `\xcfk\xc7\x88\x0e-\xab\xfd\x18\x9d\x84\xab\xfc\xdf\xb4b\xbfM\x9a\x15\xd0\xfd\x00\x86\xd4\x92\xf6\xces\xa3\xc1!h\x02AR\x04\x182\xc5Q\xd5\xcaq\xf9\xa05\n?\xb6\x06|\xfc\x0e\xf0\x08'\xf8i\xd6&\x06\x82{k\xd4l\xeb*`\xb3\xc5{\x99k\xc3\x1cR\xceY\x0d\xa9\xc1\xeau\xd5\xdc\x12\xeds\xef\x93\xc5\xe1\xb1s\x7f\x80\xb2\xa7\xc2#\xa8\xc2\xc4{?\xc5\xe9\x92\xc0|Y08%\x90\x92\xa2\x006\x8b)\xc8\x96\xbd\xca\xd9?\xb68fn0\xa6\x87\xf61\x9d\xa1\xc2=\x97\xc3\x12\x8d{\x0d\xeb\xad\xd9\x85\xb4\xfb\xb4@9\xf3\xf6\xbfv\x0e\x7f\x9bl\x07\xbf\xf5\xf9?\xe1\xa1\xb2\x0chRjc\xa01H\xb6\xc7gp\xef,>\xaf\x9b\x8d\xcecP\x14#\x01\xcf<\x87\xf5\xc1\xe4\x9b\xeb7&<\x95\xb6\x02\xe2\xf0)\xb4Cn\x9a\xa4\xc4k\x80\xaf-\x0e\xc5~c\xec\xb1|Iz\xb2n0?D\xa7qZ\xe87\xb6v\xb5\xbf\xf7\x14#o\x1b\xf5\xa9\xe8\xdek\xe0\xcf\xcd\xce\xd1~\xe3\x16\x835\xa8{\xecc\x93/\xfb\x0c\xedw\x9b3\xb7\xdf\xe0\x92\xe2M\xfc&\xe0\x9f\x95\xce\xc2\x8e\x95V\xcd{\x8d\xec\x8d\xc9\xef\xdcoTJ\xd8S\xa2F\x9fe\xaf\xb2\x0b\x92?\x8d\x0b\x12\x84\x11l\xdd\xfe\xd7\xf0\xcf`t8\xdc\xdd\xf9.\xde\x99\x8e\xfe\xfc\xf6j\xa7\xfc\xfb\xae\xc7\xdf{\xfbW\xc3\xf0j\xe4E\x18\xf8\xc8\xbd&\xfc\xde\xea~\xefOL+\xde\xc4\x8f\xce\x8b.\xbc\x86\xf7\xcc\x1a3\xb0\xf9\xf06 \xf9\x1b\x8c\xf0\x95%\xd2\xc1{|[\x94\\\xc0{rvt\x89\xfe\xc8\xae\xa5\x9dfi\x9a]\xc0Bv\xd2\x83m\x93\x03{\xfd\x0co\xc7et\x8e\xec\xba\x9c\xed\xad[\xb5\xdfv\xae\xd6\xc6\xf1\"\xab\x87\x94\xe74\x9b\xac\xa4RY\xa8\x17\x13\xda\x13N\xf2\xf8\x0b\xcdX'\x97\xf3\xb4\x87\xee\xf2\xda\xcd\x9eEU\x99T\xea\xce\x9c\xa0\x9b\xc2\xc4\xf6j\x0c\xc2;J\xbe^`\x84\x8b\xe8\xc8\xa2\"\x8e\xcb\xd5\xca\xedv\xc7X47\x97|\x8e\xa5\xf3\xb1\xf6\xa6d=,oN\xab79q\xb6\xbd\xb6\xa8^\x9bf\xf9\x8f\xe0,\x82\xd3\x08N\"\xb8\x88\xe0(\x82\xcb\x08\x8eG\x0d\xe1\xd59\xf6J\xdfd|\xc5V\x92\x0eYB\xe4\x9f\x9f\x86\xcd\xb9\xbf\x97\xb4\x1e\xa6 I'\x90\x14@3\x06\x8b<;O&x\x02\x98(\xb6j\xf4\xdc5X>\xf1\x8f0\x80WA\x16\xc1\xb9\xc3%\xe1#\x1a8\xc4x>\xfa\xba\x1a\x80\x1c\xc2\xa4\xda:\x93\xae\xd1|\x86\x01\xbc\xe7\xa3\x998F\xf3Y\x1b\xcd\xe7MG3\xeb\x1a\xc2\xf70\x80g|\x083\xc7\x10\xbe\xd7\x86\xf0\xfd\xa6CXV\x00q\x96\x1d\xe1\xa3\xf9\x03S]a\x91\x11\xfbh\xfe\xd0F\xf3\xc7\xa6\xa3\x19W\xa3\x19w\x8d\xe6 \x0c\xe01\x1f\xcd\xd81\x9a'\xdah\x9el:\x9a\xfa\x91\xd85\x9e\x9f\x1c^K\xeaB\xee&\xf8 5\xe41#;\x8c\xcbQ\xd8\xfc\x02\x0e\xe1\xf7\x00Uh\xbd%\x176\xca\xbbo\xc4\xdd\xe7\x82\x88\xda\xf9\"u\xc9\xd9\xfedsb\xa9\xc8l\xfd`\xeb\x9a\xdf\x8f0\x80\xd7\x81\xab\xda\n\xce\xee\xc7\x0d\xc6\xf8c\xf7\x18k\x87g\xd7\x10\x7f\x86\x01\xbc\xed\x1e\xe2\xcf\x1b\x0c\xf1\xe7\xee!\xd6O\xe8\xae1\xbe\xc0\xec\x8d\x9dc|\xb1\xc1\x18_t\x8fQg\xb0\xbaF\xf8k\xc7\xd0N\x91\xf9)\xd90\x9f\x81\xfe\xaax\xd6\xe74\x18\xf6\x12F\xe6E/\x02\xc1g\x8f0\xc9N\xcb\xcc\xdd\xe5\xe9\x01\x9a`\xd5\xb5\xed\xf8U\xc3\xa4_\xd1E\x82#\x0b\x86\xaa\xd6\x97P=|'\x1f\xeaT\xe0Wd\xc0\xf8\xd3\xe7\\\xa8\x8c\xa4\xb9]\xac\x83{\xb0\xfcJDVKC\xde\x95\xe6\x85\x995\x0e,\x99\xc4\xd4\xe5\xac7\xdb\x89\x13\x1a\x83\xdc\x85\x12/a\x00\x1f\xba\x91\xf6\xa5\x0f.H`\xbd\xf4\xa5\xc6V\xab\xb7\xc1{\xa5\x9dF\xc1\xcd))7\xa3/w66X:Az\x05m*\xf6\xb7\x0cZ\xa6\xf8g\x0e\xef\xdb\x97\xf3T\xea\xae\x98U\xbeK\x84\xcf\xd5\xe5<\xc5m\x8b\x7fa~\x12\xd7\x9a\x0b=\x0f\xff\x86K\xf9\xf2\xdb?\xaf\"\xfe\xfdW_\xe5d\xaa;\x03\xac\x16\xe8\xb4F\xfa\xb8\xaf\xc5\x9f\x0b\x91\xcf#!\xf2w\x95\x16\xe6]\xf5\xe4\x10\xfe\xf6\xf0\x907~N\xf2\"\xc9\xe8\xa0\xb7\xd7\xdf\xed\x01\xa1\xe3l\x92\xd0\xb3A\xef\xe3\x87\xefw\xbe\xed\x1d>\xfa\x8dJ\xb7v\xf8\xe5\xf5+ \x97\xb8\xc40\x8e)g>O \x9c\x11\x8a\xc9\x19' B\x94\xfef\xf5~R\xd7yY^\n\xa7\xd3\x9fsQ \xb8\xfd\xdb\xf1\xd7\xbf\xdd\x0e~;\xde\x0e\xbf\xba\xed@\xf6\n\x88\xb2\x84\x94'*C\xddXx\xa6,\xb5\x93\xa7\xa8/\xfb\xe5\xf5\xab#17\xe1J\xe2\xe3\x01r.\xcb\xaa\xd5\xdb\x13\x9b\xe0\xfb<\x9b\x8b\x8d \xdbk\xcfH)\xc5l\x92]\xd2%\xd9%a\x08\x87M?\x98\xa4\xf2\x83\x81\x83F\x8eJ\xe9\xa3\xa9\xa7?q\xba}\x9d\xcb\xcc\x86\x7f\x1at\x85 \x93\x17V\xe2|\x9a\x8d1\xcbN\xbf\xc0\xc6-\xfa\xa5Joi\xdbZ=\xa1\xa4w)MD\x16\x94byZ\xb0<\xd8\x0b\xfb\xc5\"MX\xd0\xbbe\xd2\xc6\x80\xee\x9f\x9eCB\x81\x86@\xfb\xb3\xb8x{A\xcb\xdc7\xb9pS\xc4(\xc3a>R-\x0e\xb8XE\x86\x132\xce&\xe4\xe3\xfb\xe7O\xb3\xf9\"\xa3\x84\xb2 \x1f\xee\x8e\xc2\x11\x0c \xe7T\xe8\xd6-0\xbe\xb37\x12v\xd5\x9e\x0f>\xa9m\xdd^\xb3v\x1a\x1b7m\xb5Z\xc5\xfd\xca\x97\xab\x81\xd0\xd6\x8cD\xca\xfdA\x0f\xb6MO\xc9\x90\x19\x0d\xb3\xfd\xdf\xb3\x84\xe2\xf2\xb4\xa7&S\xf5\xb8\x07\xa5\xe6S\xcb\xb9\xa1r\x17Sr\x01$`\x9a\xb9\"\x82\xde\x92Mw\xbe\xed\x85au\xb7w\x1a\x17\xe4\xfe]\xd3\x18\xaa\xd4A\xed\xae3\x0c6K2Z\x1c\xe3[6\xaf\x9d8]\xccb\xcf\\\x83\xa0\xbb\x8f)m\xe2\xac\x17\xe2\x16J \x07h\x9c\xf3)i\xcf,G\xb6yc\xce \x9be\x93k\x8fF|n\x1b\x8fz\xea\xcdD\xb4\xc7\xc8\xe2\xb3\xbf\n\x9c\x8d!{\x0f\xd2\x80\x99\x8d\x14S~\xec\x8c\xc9I\xa5\x8a\x8d\xe6\xe4\xc7z\xfa+_^b\xf5\x10\xd1\xd8\x96\x1c5\x88\xbd\xeao&x\xbb!\x8d\xf8\x06\x8dL\xfb3\x0f\xb5\xc4k\xfb\xbb\xb7\xcf\"\xe8m\xf7\xc2\x91\xdc\x9f\xa6%\xb5R)\xe6\xda\xd4\x86\x94]\xb5\x95\xb48\xd6\x94J3N\xb8f\x15\xe1\xa2\x9aSN\x97\xcb\xc8F\x1e#\xf5\x91\xd7a\xae\x94b\x96\xbcd^\x04\xd8X\xa0\x063\x8ektL\x9a\xb31\xa5Q\x9e\xcc\x03m\x91~\xc3\xecx\xbd\x13\xb4\xd8\xf4z\xae\xe1Z\xb2\xaay\x0d\x93\xc3\xec\xb4\x82\xd9\xc7\xb6{Yd\xc8\xe3\xe6\xd54ig\x9b\xe8N\xc2z\xfb_\x97;%s\xdd\xb9l\x915\xf7\xdc_9Bi\xffY\x97\xf6\xa5ui=ZK\xbb\xd8ZZ\xbd\xfc\xa7\xf2?\xd5\x83\xb2\x90\x16\x0d\xee\xdd\x0d\xfbO\x96\xd3)\x91\xde\xe2\xd7\xca\x06hN\x88\xd9\x9cfI\xa9\x8c\x92\x99\xc8\x15\x0f\xff\x7f\xf2\xde\xbc\xbbm\x1cK\x14\xff\xbf?\xc55\xa7_\x8a,\xd3\xb4$\xaf\x91\xedx\xb28\xdd\x99\xc9\xf6b\xa7\xea\xd7\xa3\xf2xh\n\x92\xd8\xa1H\x15\x17;\xae\xb2\xe7\xb3\xff\x0e.\x00\x12\x04\x01\x92rR\xd3\xfd\xde\xe3\xc9\x89E\x12\xc4r\x01\\\xdc\xfd\x9e@\x15\xcb\xf2\x13\xf1\x83\x9c\xc7\xa2\xfc\x17$\x0b(\x81p\x047a\x16\xe6\xb0\xc8\xf3\xd5x{{\xe6\x07\xe4:I\xbex\xf30_\x14\xd7^\x98l\xa7\xf4\xbb\xedi\x12d\xdb\xf8\xf1\x16#\x9fRo\x91/\xa3\xd3P\xc4nd\x94\x86\xcb\xf3\xb9A\n\xc7\x90\x1fA\xba\xb9\xe9@\x0c\x9b'`=\xf1\xd3y6\xb94Q$\x157\x97\xa2\xcb\xaeB\x1f\xb2:\xeaq5ED\xcd$\xed\x1f\x94\xb3\n\xc8\x99uG\xe2l\xa2\x99\xa4\x16\x1dS\xe5\x15\x98C[\xd2\x1a\xd8\x12\xc58j\xc4\xca\xca\n\xef\xbb\xc4\xa8'\x14\xd8\xe7\xa4\x1f\xac\x932\x1a\xf1#\x9a\xacB\x19\xcbcf\x1d\xa8nz\xf5#\xcb\xfd\xe0\xcb#\xba\x80\x11\x98\xd9\xb8\xe9/:r\xfa\xb7W\x9b!\xb7\xd0}D\xb3\xc2\xb8\x17[\xd6\x18\xfd\xf6j?\xc5H\xcfk\xb5^\xd4\xb3\xbd\x88\xa8=\xad\xca\xa8\xf2\x84\xc84'\x04\x8b\xac\xc3\x8c\x102x\x06{p\n\x19l\xc1\x1e\x8c1\xf3R\x00'\xb0w\x04\x01\x1cCv\x04\x01E\xe3\xd1$\xa0\x05.\xe5\xda&AKb\xf0\x1b\xee\xa5n\xb6\xa3\x86R\xdb3\x93\xe9\xac\xd4c\xc1\xb0\x8d\xe2:q\xd1\x16\xd0\xd4\xc4\x9eux\x8a\x03\xb75 \xdb\xe5\xdf\x1c\xdcR,h\x8a\xc3\xa3p\x8afOSzb\xc2\x7f\xd1\x9f\x05\xfd\xf9_\x90\xcc\x90Zd\xcfV\xecYV\xacV\x11=\x7f\xf2\x84=O\xf0\xb9\x0b\xe4\xeb\n\x03\x9c\x80\x1fC\xe9\xd8\xe1\xfd=\xe3\xa1\xbf=\x8d\xe8A\\z)\x19\xc8\xb3\xbch\xe5X\xc4EK\xde \xe7\xb2\xe8H\xe9\xde\xa9\x8b\x16\x97\xb0\x8d\x99\x95\xd9\x03\xdb\xacN\xe4\x0b\x1d\xf3y\x1eJ\x91~h\xb2taQ\xaeo\n9\x8f\xc2pQfP\x88\xda<\xf1\xc5E;?/\xe5W\xf3\xd6\xf2f\xd8\x1a\x82\xc5\xf5\xda\xe4\xd9\xc2_\x911\xac\x9aoD\xa07\xed\xcb\xa5\xbfzY\xbe\xef\x8d\x1ef\x88\x9c\x1ew\x06F\x18\xe5>\xb3\xf5\xe7\xb6\xb6\x87X\xbc\xd9Z\xdb\xf9\x8a\x9f\xf4<+\xb5'#V\xd0<\xeb\xdaN6\xb9\xcd\xae\xb3\xcap2\xb1V\x0dg\x8d\xae\x9f\xbf\xf2~\xfe\xca\xfb\xf9+\xf6\xf3WM\xd9\x94\xc7\xfb\xcfl\x8b\xed\x7f\xcb\xed?\xe1D\x87.\x9b\xb3\xadi6,S,d\xf6\x9a\xc7\x99\xec&&z\n~\xb3\xaf\x82+\x11|t}\xbb\xf2\x11h\x9c\xc7\x84\xfeu\\\x1f\x1e\xb3R\xa5\xef\x85\xfc}\xac\x8e_\xf4\x97\x16\xaa0+r\x1ae\xcen\xbb\x14>\x03\x06F\xac\x05\xdf}\xd0\x8c\xac\xd00]\xe2]\xce\x8f\xe1\xb4\x0c\x9e\xa7\x9b\xb0\xb5N\xe0}~\x02\xefK'\xf0\xbe\xee\x04\xde\xef>\x81\x05\xd5\x00'\x80\xa6+)\x0b\x9e\xc7\x8c\x1c]\xe1\xbd\xcb\xe2\xb3\x9e\x02QQpm`2\xe2\xe5\xc9\xe8\xa5\xe3\xb14u\xa2\xc0\xf6\x1b\xe7\xe3\xad\xcfl\x9f\xb2\x15 \x18S\x16\xc6\xac@\x88\x05<\x94\x97\xb0\x86\xebk\xad\xb1\xa2\x98&A\n\x0f\xbc1t\xb4++\xf6\xc2\xac\xec\x96\xfa\xcd\xa0\x16\\U7\xed\x99\x96\xfco\xd2ar\xf4D\xed\xec\x8b\x89\xa7P6\xa9X\xec\xac\xd5\xe44B\xda\xa6#\x87\x8f\x81X \xdb\x89\x95\xa8/\xb1\xf2_\xa5\xac\xe0\xbft\x14\x8aQ\xec\xd8\x8c;\xe2\xb4\xc2=2\xc9\x1b\x9b\xa0\xaf\xe0\xaeI\n\x02\xf2\xc6\x8b\xb4\x1b/(7^\xc4I\xdfH\"}g\x8c\xf4\x9d\xc11DG0\xa3\x1b/\x98\xcc\x9a\xa4\xef\xcc\x10\xd0i\x85\xaa\xa6\xc44\xe7\xb1\xbdj\x9ds\xbaf\x0b3\xfd\x84F\xd0\xf6\xeaQKB\xa2_3\xcd\x92X\x18\x96D\xd8E\xbf\xa2K\x00#\xd5\xfa,\x10fW\xc1'S\xef\xe7\xa3\x19\x00-#\x1ce\x0d]\xc4y_\xa5\xc9\xea\xa2\x1cS\xd6\xe8{\xb9\xe2\xb4\x99V\xca\x95s\x83\x91\xab\xca\xc8\xf5.\x92\xb8\x03\x97\xd3\xac<\xa1-,\xe1\x18\xe6G\xb0\xa4\x8b\xc4<\xa5\x18ZJE\xb27.,\xcbEL{9\xa1\xfd]\xd2_\x97V\x89t\x03\x13\xb5K\x81x'\x9f\x82\x08\xae\x12\x80w\x1d\xf3\xd0\xb1\x19\x85xC\x17.\xbb\xb9\x1f[\xb7`\xa2\xdd\x82a\xb9\x05\x13\xc7\xe5 \x10\xc1\x87cH\x8e\xc0\xa7\xd0\x0c'~}\xbb\xf9\xe6s\x0eQ\x07vU\x01r\x88:]\x16\x7f \xf3\x8d\xb8r\xb7\xab!\xa2[\xae~\xfe\xcaq\x84\xdaq\xf8\xe58B\x8eJB \x95\x14\x0c\x95\x14p\x0c\xe1\x11\x14t\\\xfe\xa4h\xa2\x92\xc2\xa4E\xe2(\x8cLrC \xe3^\xca\xda\xf6\xd2\x17r\x97]H\xfb\xc9NV\\\x08\x9a\x91 \x89\xa7e\xd7\x9c\xe6V\x8bM[\xad\xc9\xe6\xb6o5\x90\xa1\x8b\xe1~\xe5H=\xe5\xbe\x9b\xb1}G\xb1jP\xee;\x8a\x9cW\x1c9\x9b9T\x81N3u\xef\x05.\xcc\xca\x99G\xa4\xb8\xf5\x8c\x02\xc5\xa6\xe3\x08&\xb3K\xfa\xcc\xa9v\xa1\xdf\xc6s2\x8bi\xe3Nl\x92\xe5\xa0\xc5\x8a\x0fNs\xf5\xea\x0f\x98l\x9d\x9d<3\xd3\xe7\x92\x05\x8bb\xb7U1\x060\xae\xbdk\x9eK\xb1\xa9\"\xb4\xd1\xd2r\x15\xb5:G\x97Z\"\xee\xff\xa5\xd3\xfe\xb1\xc7y\xd1~\x9cO\xff\x87\x8e\xf3\x9b2\xcec%\xffi=X\xbb4\xebK\xc4x7-\x18o\xd9\xb5\xeb\xe9)\xbdTw\xfd\xc2\x85\x9b\xda\x89\x8b\x1c\xe2M\xf7Y\x0b=%J\x9d\xc6\n\xed[u\xd5\xdc\xaa\x95|G\xfeT\xfc\x925\x85\xcc~\xecQ\x8a\xa3\xed\x1f\xcb\x9f\x8c\xc3\xde\xf2\xb3,\x9cWl\x92\x1d8p\x1e\xc6\xd3\x94\xc0y\x92.\x8a\n\x01\xfdk\x14\x06$\xce\x08\xbc{sQ>\xfcq\xbb\xfc)tR<\x8d\xd9\x9c\xe4\x92)\xd7\xf9\xdd\xf2:\x89\xb2\xa6\xae\x8a\x97\xae%\xb9\x94\xbek\xea\xae\x1a\x1fp\xcb\xca\xbb7\xd9Y\\,\x19\xda9\xd2\xc2\xcdH\xc4\xe8=\xa9pS\xf3\xe6\x18\x94Z\xc3\x89\xdcp\xbb<\xba\x83\x85u\x93\x7f\x1d\x98|\x11\xc9\x04\xb1\x8e5%\x96\x0b\xd6\x1e\xb34\xd4\xc2\xee\xbd\xbf$\x99M\x9c\xc9\xe0\xb2\xb5\x0355\xf1\xef\x0fL)<8\x82\x18\x8eaH\xffR\x84\x97O\xac+\xba\x15X\x0f1\x0f\xd3\xcb\x85\x9f\xbeL\xa6\xc4\x8e\xd1t.\xd6\xf7\xd7\x1a\x0cG;\xbb{\xfb\x07\x87O\x99}KK_s\xc5\xa6\xadK\xc4\x95\xabq\x84\x00$\x0b5\xab=\x8c\x8bXw-I\x91\xe8\xc9p3\xb4\xb6\xb2\xd2\xb6\xc2\x94\xd7\xc4\xbb\x9aE\xfe<\x83'PPZ\xe5\xa5\x1f,\x08K\xa5@[\xd1\xcbxo\xcaLG\x154\xe8\x17)\xd1$\x80\x06\x11\xa7\x82%m\xc2\x82M\x9c@\xc6\xb2\xb8\x02\xed\xe7\xb55!zV\xed\xea\xc3Vm\xfb\x0d\x8fx\x1fO\xc2\x8e8\xea\x19\x02\xddw\xbc\xabi\xb2|\xf3\xaa\x9d\xa2f\x16\xb2Z\xaeN\xbepTGU\xd4\xd1\xe4\x08\xa1\x91`P\xfa\xf3\xf0:\n\xe3\xb9Yy..\xda`d'\x94\x8b\xecjP\\3\xdbw\xa1\xcd\xa3K\xbe\x02\x9e\x91FC\x08\xa8\x97Y\xe7L\xaf\xd4\xb6vF\x16\xed\xa7\xb1\x98A5\xdd\\\x12bi\xde\x9f\xe8\xd7\xe6\x9f\xf4\xdf\xeb\xb6\xc0\xb4\xb9\xb5\x19\xd1\x9aU4(\xbd92\xec~&qa\x96\xd7\xb0\x81%M\xc4\x03w\x7f#\x98\xda\xdb[\xf9)\x89q\xc3:\xb2vA\xb3\x01p?U\xc5\x0d\x83\x83jI\x91\xd2U\x11\x87q\x84U\xa4\xde*Y\xd9\x8e\x83\xd8\x8a\xf6Y\x98U>y\x02+z\x96\xaa(E\x90\xac\x7fj\xb6%\xb8\xe3\xfa8\xe7$\x7f\x19%\x19\xc9rq\xc6\xbcN\x93%\xed\xf2\x18\xa6\xaeZ\xb4Y\xa6\x9d\xfc\x12\xf4\xfeT\x1b\x97^\x82 \xca\x0b\x99I\xba\x84\x13y\x18\xc2\x9c\xfb\x87\xd5\x81\xd8\xe8\x1c\xfd\x86vLt\xb2\xabsa=\xfb:\x91Z\xc6\x98\xcc\xd6\xce\x0e\xba\xf2T\xcf%7\xba\xf2Y\x07\xa7\xc3V\x98T\xdc\x11V\xf7\xa4\xaa\xfb#\xae\x13\xd4\x8f\xda\xd6\xce.\xb6\n'\xf5\xb7\x86v\x8e\xca@\xfcl\xc5\xe4b\xc5\xe01!\xf7\xdd\x08\x7f\xa9P\x1b\x84W) \xe8\x96\xadvl\xc3nD\x14\xe1KC!ub\xf9]\xafe\xd3\nf&L\xe7\xd1\xb2\xe9\xc9Y\x1b.\xdd/E\x14\x19\x8d\xa5\xf5<\xf8\x02\x9f\xaa\x04\xa4\xdc\xc5\xea\xb0\xac\xbeR\xce{\xe6\x1d9\x06k\xe4\xedy{\x96\xaeMM\xc0\xe6\xab+\x86\x01\xe8\xdf\x13q^~+);\xd0\x19\xe0N\xac/a<\xa5|}J\xb2$\xba!,\xf7Z\x9ca\xae)z#D\xc8\x1ff\xf4n\x95\x92i\x18\xf89a\x9f\xacR\x92\x91\x18\xcbq\xf3\xffs\x9e\xec\x8de}{\x1e\x85~F2\xeb\xb2I.O\xac,\xf0#?\xc5\xb2\xe4\xd7\x82\xc4\x01~\xb7\xf4W\xab0\x9e[\x97\x1d\x92\x11#y\xe5\x82__ \xe1\x8c\xe5\xb9\xc8\x85'\xac\xcc\xe1\xe6}\xc3\xb4\xd3Z\xb6x\xd8 \x0f\x9d\xc1?\xcc\xd0w\xb7b\x1bS\xfb\x87\xcf\xf1\x978\xb9\x8d\x81\xa9.\xc0\xfa\x81\x13\xa8?X\x10f\xb0$9%\x80\x90KD\x03oHf\xac\x0cae\xfe\xf6\xfc\xdd[\\\x04\xde\x0f\xcaju\\\xc8\x17a\xe6\xe5\xfe\x9c\xae8~G'\x0f7:\xfe\xe0\xf1\xed\xf9;>\xa1\xf8Z\xfc\xbe\xbf7\x8b\x96@b\xd3\x15\xb3\x07^c\xb9.\x98[Ky'\xd7\xda\xea*\xa1\xad\xb5Z`,\xbctu[\x1fO\xb9\xf4\x18f+\xef\xd4Q\xf35\xc9\xc7-\xee\xea\xa5\xe4\xc5\x8a\x05k\x0f\xeae\xe5\x85\x8c\xec\x1cs\x1e\x95\x9f\x96\x1f\xf8B\x9e%hB\x8c1 \xaf\xb7\xb8\xaf\x08'\x9e\x90\xcb\x9eK\x93^\xfe\xa4d\xc6LR\x9f\xc6\x82\xf2\x1d\x17\xf8\x92\x0e\xab%-\xd6\x95ii\xe3Rc\x0b\xbb\\\x82b\x81W\x165\xf4@\xea\\\xd9\xbdx\xf4\n\x85\x8dvG\x8em\xdd~\xc9\xd4\xf8j\x8c+\x1f\xee\x1b\xd8\xf2\x1d\xc7cR\xdd&s\xaeM\xdc+\x99\xe3\xda\xfd\xfc^\xf8\x02G\x91\xdb\xfd=\xd8\\\xf6\xe6\xd3\xd9\x0f\xc5C\x1f\xf5\xb0cH\x1c\xdbb\xfda\xc6`\x92\xb3\xd4\x83\xe3ey\x82\xa9\x92\xd3>\xb0\xd1#\xfd\\\x0e\x15_\x0f\xdc%\x80\x19\xda\xb1\xbd\xb7\x7f\xa8\x06\xacO\xf8\xab\xa7CG+7\x08\x8dC\xef\x1f\xa3\xde\x10\x9f\xfe\xe1O\xcd_\xe5\xbel\x13\x89\x0bmD\xdb\xc1\x00\x1c\x81\xab\xf6}\x15\x11\xa7\x17\x81)\xce\xf1\xa5\xf0\xae\xfa\xb0\xb3Y\x90\x08\x05S\xb0Gz\xa5,_\x96\xf1}\x88!\xe1\xcc\xef\xfd\x8e`*\xed1\xd8J:\xb5`bH%\xeb\x19\xc1\xbck\x98\xe3\xa6@\xd5u-\xef\x1a\xe3V\x18%[\xb0\xbcj\x94EbHW\x8e\xa4\x9e;G|\x9c\x06\xe6\xb5_`\xb7\x90\xa7\x16\xf3\xb5\x88\x0e\xa0_\xbe\xaf\xee\xa0t\x1b\xe8\x18\x9bIi\xc6\xb2\xf64c\xd0\xb3i\xe0\xcb+\x14(\xd67W\xa7\x1f\x9f\xf6\xa9\xe0\xa1\x1a/\x1f\xd8\xea\xd4\xd0\xcd:\x91\xb7\xd0\xe6\xfayN\x96\xab\x1c\xf2\x04\xa6\x84\x1d\xf5E\xca\xbc\xd9\x84\xbdni`\xa0*\x03\xaa\xcdl\xf7\xa2^%:u\xbf\x1d\xc9\x0f\xf7\xb5H~4\xfc\xbf\x16\xc9K\x07\xa0^\x1c=\xdc\xd3\x82d\xf7\xa9F\x1a\x1d\xdb\x0d!u\xc1\x1e\xab\xa9M\xfaz]\xa3\xf2\xc1\x05f\xbd\xb2\x02\x0c\xe0\x0d\x99\xf7Z\x8f\xaa\xa6e\x81\xbf\xe8\x0b,\xca\x02\xe7\xfa\x027e\x81\x8f\xfa\x02\xcb\xb2\xc0\x0b}\x81yY\xe0g}\x81;8\x81)\x9cB\"\x92.\xd1\x99\xe5\xd9\x97~7e\x11\xbb\xc6h&\xa5\xb6W_\xe8\x8a\xd7\x9c\xc2\x18\x16\xf4/\xcb\xecd\xa7\xbc\x95\xdf\x1f\x9c\xaa\n\x03\x9b\x8f\x9a\x9ei)\"\xca\x1d:1\x98\x9a|\x03\xf3\xe0^)\x11\x8a\xae&\x11\xd3\xb1\x14\xf6\x1d\xaa\x7f\xe8h(\xb1\x1d\xc0)\xbe\x841\xaa\x81\\\xb8c:!\xac[k\xbf\x85\xa5O\xb14\x8caI\xcb\xd1JB{\x86&yc\x98c\x07\xb0\x9a\x13\x98\xc1i\x07c\x00\x12\x83_\xd1\xb8z\x0b?\xf9B\x96n\x11f\xb5x\x1e]\xe2\xd3\x0c\xf3#\x83\xad\xea\xd6\xba\xbe\xa3W\xe0g\x04\x06\xe3\xcerP\xb7\x8f\xd1L\xa1za\xcd\xc3\xf5k\xb6u\xf8\\\xbd\xb0\xf2\xd1c*\xd7\xc60\x92\xaf\x0ea\xb1Z\x996W\x99\xb8\xccu\x95b)f5C\xe7\xdc\xad\x94\xa3\xfa\x1a5\xdau\x90\xc4\xa1\xd5\xfebr\xd9r\xc3\xea\x02\x88\xb3d\xd47\xca\x86\xa8N\x91\x19\xae\xfe\xd7\xfc\x0d\xaa5]\xc0of.\xfb\xcc\xb6\xef\xbc\x1b\x96\x14\x1b7^u\x87\xb8\xc4a[n\xe6r\x8c\xf4\x89~sM\xff\xdb\xb8\xa6\xaf\x9e<\x01\xdf\xbev\x01\xab5\xa7(\xc9\xbc\xd7\xcci;\xf3\xfe\x02'0\xa2?\xce\xe1\x04v\xe9\x8f\x8fp\x02\x87\xf4\xc7\x0bZf\x9f\xfe\xfa\x19N`\x07K}\x86\x13\xd8\xc7b\x9f\xe8\xdb\xd1\xa1[\x93\xb70Q\xfc\xbaR09\xeeT\x85=n\xc3x\x9a\xdc\xd2!\xb1_\xde;\x0c2q\x82ZL8\x15\xef\xc7\x86\xcf3\x12a\x10e\xfaW\xfd\x14\xdf\x8dAL\x84m\x89\xd9^\x84\x99\xe5\xc8\xa6_Zq\xdb\x9c\x8b\xdb\xe6\xdf(n\xeb\xe2\xbc\\~b\x8f\xf6\xd5\xd3\x16\x03\x81\xd1S\x9eE\xcaN\xeb\x9cT\xda\xceI\xa5\xa6e\xa1e\xa0\xda=\x1aPBEx`\xb0\xb0\x96\xd9(w\xb5\xc7\x7fT\x901h\xd4\x83\xa44r\x1ak9\x9b \x89g\xe1\xbch)q\x9b\x86\xb9x[\x1f\"\x86\xa0g\x07r\xec\xd6T\xb1\xd0=wfym \xd1\xd8\xde\xdb\xd9Q\xa6\xa8\x9a\x91Z\x7f\xf4M\xeavH\x8d\xfb\xd4\x8b7\xe3>\xfd\xff\xc6\xb5\xa7\x8e\xeb\x8f_z\xe52j\x17\x15\xd6\x94%\xc3#\xc8\xb5\x860\xb9\xde\x10\xe6F\xcd\xd4\xa0\xb5NoDr\xeb\xb0\xea+\x0dUx\x8072I/\xb9\xf7\x94\x89\xe3\x01\xbd\x89\x00=\xa8\xde\xef\xef\x0d\x06\x07\xec\xfd\xfe\xde\xde\xce\x1e]I\xfc\xd7\x13`\xf2&z\xb7\xaby.*\x1c\x94\x95\x1d\xb2\xe7\xc3a\x95]J\x14\x1a\xee\x96\xa5v\x86\xb5\xcf\x87\xa3\x83\xf2\xd5p\xef\xa9\x03<\xbf\xd63\x18\x0e\x87\xbb\xc3\xe1\xd0a\x97\x04\xd3&T4\xbe\xba!\xcf\x02\x87\x9d6\xa11\x8a\xfe\x18\xc06\xc1\xb6 l\x9d`\xf9}\x07\x9e=\x83\xa1\xca\xbe\x8b\x8b\"\xbf\xbd\xfd\x9d\xd1\x80~5\x1c\x8cv\x10&FM\xaf\xce\xac\xb6I\xf5k\xd1\x9a\xeeS\xad)\xf8\x0dw6\xdd~bO\xfc\xad\xdf\xfe\xe5\x92\xfe?\xd8zz\xf9\xfb\xd0\xdd\x19>8G\xdbs\xc5\xe0\x8dR\xc5\xdb\xff\xf9/\xb6}:\xfe:\xf1\xb7f\xbc\xf0\xe1\xc3\xfd\xa4\xfc\xe98\xdb\xcaW,\xe7\xec\xeep_+\xb4n7\xc5R\xc4\xa5|\x88\x89\x1d\xf0\x14\xcc\x01\xe3\xd0w\xf6PO\x92{\x01\x1f\xf1\xf3\xdc\x1e\xe0\xb2\x88Dx.F\xabc|\xab\xaf\xcc\x946\x9f\x0c/\xeb\xb9\xaf\xe0\x140\x80\xea\x9b8\xb7\xf3\xd2D\xcf\x85\xe1>\xa5h\x1a\xaf\x86\xf4\xd5\x00\xe3\xb4\x16v\x8cD\x8f\x01\xcc+\n\xb8\xc9\x93\xe3g\xd6\xe5v\x1d8S\xe9\xcd\xbc\xfe\xaai\x02B/\xeb\x895\x06\xeb\x89\xbf\\\x1diB#[\xc7\xf86\xca\xb5/\x9f\xe1\xcb\xb9\xf6\xe5\x0f\xd6\x0f\xf4\xe5\xafE\x92\x1f5b\xd15\xa7\xed\xc6\x88S\x16\xb2\x11\xb6\xac-\xe0V\xba=\x84x\x93K\x06a\x86\x1eK\x9a\xc1\x85\xe1:\xfa\xe0\xd6dVR2Lq\x0c\xe6z#c\xb4`\x149H\xf8W\x06\xe6\xbeKum\x0coH/2\x89/y\xe4\x1bm\x19]\x0c\x91\xfa<95Z\xdb\xc5l\xc0=\xd2\xe9q\xa0[\x1368\x8e@.y\x04\xf3V \x11\xff\xb4q<\nSW~\xbe5\xcd\xa9\xeb\xdd\\\xf8xN\xd3\x9fE\xcc\"\x1d\xbek\xcfgWJ\x1e\x84b\xd4\xfa\xe5\x17\xcb\x81c\x18p\xcd\x16)\xe3,\x86.X\x7f\x1eZ\x8e\n\x99\x9f\xfc(\x9c\x9e\xc5y\x98\xdf\xbddf(>}\x81x3\x99\x92\x8fI\x88j\xea\xc2e\x9ajZ\x17\x96\x0eI/A\xb4\xd4\xb5'\x86\x9ee\xae\x9c\x18\x08\xbb\xc5\x06\xff\xd7\x1c\x03\x84w\xb6\xb1\x12I\xd80\"\x83\xa8v\xea\xc2\x8d\x0e\x19\xb51Ak\xc9\xd8\xa5\xa0\xd6U\xe0\xcbS)\xc1;\x8c\xf5\xf2\x98\xae\x1e\x19E\xeb\x0dn\x8f1K\xfb\xeai\xcbD\xeb{\x87Z\xd1\xfa\x81Z \x13\xad\x0fGj-\x8f\x93\xad\xbb\x92\xf4\xdc ^_t\x89\xd7o\xba\xc4\xeb\xcb.\xf1\xfa\xbcK\xbc~\x07'L\xb6\x8d\x923.\xe3f\n\x13!A7\x8a\xbc\xcd\xa2\xf5\xc5\xba\xf2\xf8+8\x81kI\xd8G\xbf\xb9\xae \xff~\xd7\xa5Q\xaaD\xechY)\x89\xd8\xd1+\xd3f\x82v\x14\x91\xdfA]\xd0~\x87\x82\xf6S\xb8\x831\xc4\x0eJ\xd4\xe9\xb1\x8c\xc2\xa5\x00\x8fp!&G\xc9\xb9Q\xa0X\x98\x04\x8aw\x8c\xc4\xb8c\xe2@!2\xfc\xec\xb8\x80\xb2\xc2\x0d\x9ee,\xe4\x02\xc3\x15\x06\x08\x10\x02y\xf1\xd6\xbe\xe2\"G\xa301\xf5\x02\xa6\x9eJ\xdc\xffi\xc1\xa2Y\xf5\xa5*\xb3\xb8\xeak\xa0\xaa\xc4\xf8\x06Uw\"\xdd\xa0\xdb\x96J\x00\x15\x9a}hP=\xdc\xf0\xa8\x01\xdc\xcc&\xc4\x1c\"\xda\x85W``KtM0R\xdf<\xf22*\x95\xed\x82\x85\x11\x15~\xec?\x9c\xa0\xe1\x0coH\n\xba\xec\xbb%\xf9\xe4\xa0U\xcd\x0f\x0e\x8fF\xf6\xactu?\xde.}\"\x9e\x19\x03\xfe\xaegP\xa7\xf1X\x8b\x99\xea3\xb7\x0b\xc7\x85\xd4N\xbd\x8f\xb0 \xa9\xf7\x1a~\x84\xa4=\x02\x83\xe0o,\x0b&\xe4\xd2\xa6c0\x02)gF\x03\n\x05}\x7f\x0f9w\x88\xa3_K\xd9\xe0\xeb\xc3u0 #\xc6O\xae\xb15\xddG\x15\x8e\xba\xeaU\xdc\xc3\xfa$_\x84\x95\xd1\xfa\x83,on\x9a\x19\xd0\xfab:\x0c\xa3\xb4\x1aq\xd5\xc0\x05r\xe3G\x8em\xb1\xc7U\xf5F# \xcd\xb1Y\xc9\xdc\x11\x93\xb1[\x1d\xaf\xf6\x9d\xa4\x905Q\xe3S\xdd\xe6\xfc\xfe\xa2\xc6^\x9e\xb37\"\x19E\xa3\x01\x91xb\xacMT\xb1\x08\xb3SV\x160\xf1\xf0j\xb9\xd0\x84\xe7C\x91\xd89\xf6\xb2\x15 \xceIDh/2\xcd#\xbc\xfb\xb7,i\x15\xf7\x89\xa3\xcc\xf4\xad. \x8e\xb8x\xa7}\xbb\xa0\x0cmi \\\xd7\x1e\xd25\xa8XH\xff\xfe\x80\xb1lb\x9d\xa5\x80|}H\xc3\xb1\xc6\xdeF\\\x0f\x18\xd5\xd3\xd4l\xeeB\xd8\xf7x\x85j0\xe2\xd4\xb8\xf5\xd3\xd8\xb6p\x95\xde\xa6\xfejE\xd21\x04I\x11M\xe3\x1fr\x98\x13\x16\x17\xd4r\xdc\xa6\x9fa\xb3 \xad\x17\x99@dt{\x0c\xfe\xa1\x86\xf4\xcd\x86[\"\xe3\xf2\xcdGiZ\x7f\x15\xaa\x9bO0\xae\xcd\x944\xcc\xf9\xae\xbe\xc9v\xbc\x81g!\x8d\x9fW\x0c\xdan\x17\x13f\xe6\xfe\x0f\x9d.\xeeU\x1d\x15:\xc1\xa7h\xe3\xcf\x08\x91J\xde\x8eqCE\x02l?\xe6\"\xf7\x0d\xc3\x88\x1f-R\x1c\x1d\xa8RBLy\xd1\xe4\xd1d*\xa0\xa4\x06\x18\xda\x96\"\xb2\x887M\x8e*\xa5\xfcb\xd2\xcaQ\xea\xa1\xa7\x0f\xcf$\x8f\xa6\x1f\xaco\xfa\xc4V\x16\xae\xbdL\x03[\x03\x03\xed\xba\"\x0d[s\xa9tx?\xd6\xfc\xb2\xdb\xcc\x7f\xae\x8b\xf9E\x92D2\xb3\xd9\xab}I\x90\xac\xda\xa7\x0b\xab\x1bu1\x84\xdcv[uZ\xf2+k\x80\xfa\x99-\x9f\xb23\xa6\xf1\xdc\x95\xa2\xe6\xd4\x0b\xab\xd1s4\x87\x13\xba\xb4\xa3\xeb1\xda\xe8P\xb4\x8a\xe4Qj\xc7\x8ekN\xdb_\x1e\x0d\xa2\xdaZ\x89\x1a\xe1\xfe\xd0h\xcf\x9a\x93\xdcb\x91j\xe8\x9cg\xe2\xae\xb9I\xad\xe7A@\xb2\x8c\x9e\x7f\x18\xab\xb9X\xd19#S\xd36\xb5\x90d\xe1u3\x86\x8c\x99\x87\x95\x0e)kn\xe4~Vb\x0dw\x84\xb5\xac\xc4\x1e\xd7\xa4\xbab\xbe\xa5\xc9N\xb7a\x83\xcb\x81\xce\x88,\xb6w\xf6v\xb5\x8a\x91}Uz[\xf0\xe2\xaa\xe7\x02J\x9f\xecCu\xafD\xac\xd1]u\xe4L\xf1\xaf\x96\x9ei\\\xadV\x18\xb0\xb3\x0eS\xb4L\x9b\x93\xfcc\x92Dd\xaa\xe6\x87Xh\xe4\x1a7%2)\x1f\x97'\xeb\xb2\xc1\x1d\x9cy\x98\xde\xea\x13 \x928\x08#r\x91\xfaq\xe6\xb3\xd2O\x9e\xc0\x0d0'\xff\xe1h\xc72YOP\xeem\xa2l\xdb8\xccY6\xcfq;\xe3\xc5<]\xc34\xbf+i\xdb\x8ce\x18\xc3\xbc\x18\xecX\xae}\xa5\x88\xa54\x82\xabu\x1a\xd98\xa9\x9a\x81S\xb0g(\xb5\x0d\x08%\x19\xcd\x9f9.\xdc\xdaH\xfe\x95\xdf\x9e\x18\xc3\xb0?\xa8t\xe6z\xc0 \xfc(\xba\xf6\x83/\xff\xbb \x05\xf1R\x92\x91\\\x11{<\x16\"\xf5\x9a\xe3$\x0fgw\xcf\xa3H\xad\xbd\x1a\xc8\xa5nI\xdd5\xe3\xff1\x1f\xe7j\x98\xd2\x9a\xb2\x9d6\xb8\xf2\x95\xebj\xfa\xd7\xd8\x07\xa2\x19\xcd\xba=i[\xd5R%\x1b\x83v\xdb\xa8\xeb6\xe35\xe2]-\x93\"\xce1\x15\x06lA.\xdf\xb7V{\xd5F\xdej\xe1\xa2\x88G\xeb\xab\x96\xc5\xfe\x18\x8ev-\xc4\x9c\xe2\xb9C\x7ffI\x9a\xdb\xd7\x8e\x0b\xab\xcd\xcdz%Ud\xba*\xaca\xce\xa3\x1a6\xd7\x0b\x17tR\x04:\x9b\xc4\x06\x0fQ\x1f\xe7\xe8jE\xe2i\x18\xcf_\xf2\xd9\xcb\x9a\x0c\x1c\xba\x156\x0b\x96\xb3_xQ2\xbfHVo\xc9\x0d\x89>a\x88'c\xa0\xa3\x1b\x1e\xbd\xd6\x90\x9e(\xf4\xae\x82\"MI\x9cs\xc6\x0c\xf3\x89c\x9e\x03?\xc8E\x1b?3\x16\x0b\x8f\xe4\x88\x8d\xa2\x11g\xcba\n\x03\x8be\x03,VS?',\xb8WD\x97\xd4{\x7fI\xe8\xaa\x14\x0c\\\x1e.\x89\x9dt\x19\xab\x00\x87F\xe6\xadH:K\xd2\xe5g\xac\xf7\xcd\xec=\xa1\x84\x85\x9f\xde\xd9\xa1\x8bF\x0d\xcd\x85\xcct\xa7 *n\xa5F\xcf\xe2)\x8b\x0c\xae\xe7>{D\xbe#\nf \xf1\xaf\xf4\xaf\xedO\x82K\x97\xef\xc2\xe2:\n\x03\x11\xb8\xc6V}>\xfe\xd4\xfc\x95\xd8\xb2\xdf\x19D*R\x9c\x93\\\x1a\x1b\x9f\x90\xac\x03\x8d\xf1\xad8oC\x87\xc2-4I\xfb\xe0\xc4v\xb4\x14z)\x89\x88\x9f\x11\xbb\x89\xa0\x1c\x03\xd6b_\xb6!\xa4Z\x9d\xba\x99\xee@v]\xa1\x86\xf8\xd2\xea&\xb6\xa1\x02i$\x16$\xcf\xd1\x89>M\xc6N\x88\xc2-E\\\xd0\x93\xe2\xd5R\xa1k\xd6\xf3\xa7S\x8a\x9c\xc3x~\x91\xd8w\x8a8\xef\xb6M\xcc\xc9\xa3\x0b\x95h\xf1\xfe\x1e\x16\xc6(Y\xb3\x0e\xb7:\xa1\x88\xbb\x93\x8f\x1c=\x86!b\xf0\xf6\x95HKO\xd7\xc2]9\xad\xba\xd4v\xdaN\x19{\xc3\xa8<}\xf3\xe2\xe4\xd0\x04\xb5\x03-\xfd\x08\xb9|\xd4\xd7\xd6tWG\x8d\x82\xa4\xb3\x06/`\\\xed,2V}\x81^Sn\x8cL\x19\xee\xcb\x9a\xeb\xb4\xcc\x17\xd3\xb2`\x97t,7^\xbd\xaaf\x05m\xfb\x84\xe3\xb9\xcf\x1c\xb5\x97\xe75\xd1\xdbP\xf2\x16\xc3\xec\x05m3\x8c\xe7\xbcQFFb\xa0\x81\x9c\x0b\xe8PZ\xe0]\xb1C\x03\x8b\xbfGm\x08\x17Ji^\x9c`N\xbc!\xd2\x98\xdaQ\xb5\x8ed\x16\x15\xd9\xe2\x85\x02\xd5[\x85\x19\x8a)G\xceT\xca\xcd\xe5\x88/\xf5\xf3g\x16\xb1\x88\x8b\x94L\xc3\xbe\xe5\xb4\xe2>\xbd\xb6\xb0I^\xb0\xfe\x08@\x9f\xe7\xa9\x9f\x93\xf9\xddz}9\xa0}\xd1gOQ\x00\\\x92T\x87\xf8\xc95\xdd:\xbe\xf2Es\xda\xc5GO\xe9G7\xfa\x91\xb5M\x9a\x9f\xf9\xab\x1e\xa9T\x03[\xb3\xe6\\N\x97\xf0[\x8f\xd5\xf5\xd2\x8f\x7f\xc8\xc5\xb2\x06?\xc6&@\x1cP\x10\xc6\xe0c\xe8E\xf25\x87\xdb\x05II\xc1\x87\xe2c\x08\x85\x1c\xaeI\x18\xcf\xc5\xf6\xf4\xe8\xb8\xa6%5\x80\xfds\x19n2\xb2>z\x81\xd6\x19>]C\xce\xb0\x11\xdb{C\xc7l\xb4\xc3q\xc0\x01\x9d!\xbd*\xe9\xf7\x07\x17,\xbf\xa1B\x02FytP\x06r\x13]s\xeaxU\x9c\x8c\x87G\xa84\xc5\xd3.O9\xcc~@\xc1\xf2T\x17\x1f\x07_\x8d\x86\xea\xab\xd0\x14h\xa2\xd4b\xa0\xcd_\x861!\xe4\xf7\xa5\xf6\xa4\xd3[^\xc8tUSWz=@\xd7\x8e\x95\xf5\x0b\xdd\x1d%U|\xaf$\xe5Q\xcf\xe4\xd7,\xe2i\xa9\xa0\xa9\xcc*O\xab1\x8e\x0d]]\xcf\x83\xe8\xbb*D\xc4/\xd9;\xb1\x1b\x18\xd2\xac\x9d@hW\xfa\xae\xd6)\xe3\xfd\x97\xc3JR\xe8H\x86\x00c\xd4\x03U\xddk\x9d\xc3\x7f\xc4\xfc\xad\xd1\xf7\xc7oG\xb3\xd4\x93\xb3\x97J\xc4O}S&\xfc\xd6 \xd0\x9a^Bgx\xfe=\xc6( T\x0d\x86\xe6\xaa\x84\x94\x0bTu\xf2T;\xb6\x9f:.L\xaci\x98\xad\xe8\x01\xf2\x12=\xa9-\x17\xac\xab\xdcOylVz\x1b\xfbyx\xc3\xfc+1\x96c\xf6\x8a\xcd\xf7\xc7\x94\xd0gd\xca\x9eRT\xee\xcf\xd1\x08\xee\xa5\xa94B\x1f\xca\xdd%j\xd8p\xdf\x18K\xdb\x10\x1d\xad4\xfb\xd3ft\x03\\\xd4\xa7\xd8i\x96\x01\x8e{\xe3Y\x0c\x00\xec`\xf0y \x8f=D\xc5\xecX\xfa&\x9e\xf8\x9a\xdc!\x0d\xe8\x08Y\x1d\xe6B\xf5\xd4Y\x87S\xdd\xc31l\xb08\x8e1\xb7\xde\xfb\xa9i\xbc(i\x84\xbd&\"\x80\x13\xa0\xdcU\xd8\xb0\x9aR\xf6\x1bZY\x89\xc8\x9d\x1a\xc4\x81<\xb1\xbe\xfc\x9f\x9acN\xedL\x96\\\xd5\xa7l\xc5\xfa\xf6J\x9c\xea=$L\xcdAmh&\\H \xd4\xd5\xda,\xc9t\xd5\xc4\xabw\x05}\xa1\xea\x8fl\x87\xd9\xf8a\x88\xcc:7#M\x08\xafM~r\x02h\xadf\x9e\x95\xc6\x8c\xb4r\xa7Y\x9e\xac\xa4I\xe9\x00\xda\xfa\x80P\xeaGH(\xcfZ@\xc1\xb0\xea\x0bD\xbd\xbc\xc2\xda\xa3\x13\xa6\x80\xee\xbd\xb8:\xc1\xb1\"i\x86\x99\xc4\xbb\xd7N\x98}d\x85\x19\xdaj\xb4\xd3\xd6\x8c\xfc\xadv\xbf\xd4J\xf7\x96\x9a\xd6\xa6\xa7\x07\xae\x84z\x0c\x0d\x96\xd1\x0c\xf1\x0f\xd3\x84k\xa3\xd3\xeb\x94\x15\x95\xd0\x9aebB\x146\x89//\xb5\x12\xd1j_;.dU\xe7\x98kc\xe6\xf9\xc5|I\xe2\xfce\xe4g\xbd\x1dNd\xb8\xa8\xbe'5\x1f.\x84\x8d!b\xda\x0d\x8fn\x10\x93[\xf5\x18J\x99\xec\xbf\xfc\xd0\xa9\xdda\"\x16\xf9A\x9d\x98\x06\x8c\xa6.\x8f3E&\x18\xfbR>f<\x9e\x8b\x98\xa4\x19\x908H\xa6a<\xafgD\xc8\x17$\xc6\x8d\x87\xc9\xd2\xca\xc3\x0fD\xe0\x17\x1fx\x03\x06e\xb88c\xb9\xc1@/\xd57\xffF\x18\x19\x18\xcc\x04\xf4S\x13\xb5\x88\x85\xc0\x0cCC\x8c\x9b\x1f\x84}n}\xdc<\x9b\xa6\x0f\xac\xa2\x16gp\xbd\x03\x1d\xae\xdb\x17\x0c\xdb=y\x82LO\xb9\x1e\xe4w\xcdC\xbe\x85P\xc3\xd0>\xde\xf5]N\xde\xf2l\xdd1FWA\xcf\xf3\xea1\x1cWv\xcb\xeaV\xfd!\x99\xcd2\x92\xff@\x97@R\xe4\x90\xcc\xe0:)\xe2if\x9a]\xb5MZ9l\x82\x8d\xb6\xfd\x03\xc7\xd8\x0e\xdbs\xfd\xdb\xc9\xeb\x99\xd1\x99!juO!\xd5@\nuE\x80\xae\x08n\xe0\xb1\xee1\x05\xb3\xbe'\xad\x88)oCD\xb4\x00\xcf|\xd8\xbaU4J\xe2\xda\xec\x8f\xf5\xde,\xdd\x04\xa1\xb84\x9f#@\xcb\xe8\x0e\xf7\xf7\xcc\xed\xde*\xf2\xd9a\xdb\xd4od^\x98\x9dq\xbca\xc7\x8ei\x13 \xd4bIh\x83\x1d\n\xac+%\xee\xd1\xed$\x90\xce\xd3\x01\xdc\xc3\x82M\x9c\xde\xe2\x10\xf8\xe1\x8a\xd3\x81\xc7V\xea8\xdem\x1a\xe63/HX\xa7\xdcL\x8d\xe1\x98\x11\x91\x84rZ$\xb9)\x1bUJi\x08\xfag\xf3\x04\x86t`\x18\xbax\xb4\xb7\x07O \x9f\xa4\x1a=\xd7Z#\xd4$^\x85r\xdd<;\xa1\xbc\x95\x89jy^e\x96\xf1#\x0c\xbfB\xf8\xce\x82\xc8O\xe7\x842\xa8~\x0cK\xffk\xb8,\x96\x90\xa1;\xc7\xe0+\xe5\xb3}9\xcd\xf5p\xdfAWNJ6i)\x9e\x12a\xdf\xf7\x1c\xd4\xa2u%J'\x8b\x9c;JH\xcb\xf5\xdb\xb4\x0f\x92\xd6\xdasHe\xbc0\xfb)$,\xd0H\xf31\x9d\x88\xfb{ \x06\x14/\xf7\xb4\"0\x9b\xbd\xd5\xb8\xd6W\x8c\x9e\xa5\x13r\x80\xb4\x9c\xdb\xa1\xc0\xa9\xcd\xb2'\x9a\xedU[\xbe\x1b\xc3\xa3#\xa7\x14\x0d\x1bOB\x14\x88Z~\x16\x84\xa1\xa5\x17\x8b\xb2\x12\x91\x9f\x87\xf1\xb0\xb5\xc8u\x18\xfb\xe9\x9d\xa1\x08H\x12(\xfdq\xc2*A2\xaf\xad\x95\"\x9fm\xb5\x96`\x84vg/^\xdb\xc41\x02\x1c\xaa\xe6\x82l\xd4\xde\x9f \xdb\xea(\x91\xcf\x86\xfb\x11\xe9*\xb3\xd5R\x08\xaa~\x8f\xe0\xc7v\x08.\xc8\xd7\xeeZbx\xf6\xec\x19\x18\xac\xb6\xf9t\xfa\x19\xd9\xdf\xed\xae\xea\xb7.@\n\xa32cE\xa8\xedpzO\x0cp&\xcc\xc6\x1d\x95;\xf5\xe8f.\xcf\x8f\xd6\xf8T\x95\xbe\xeb\xd1\xd7M\x1b\xc7\"\xf6\x16\xd1F\xc6\xe7riz\xfc\xb9\xe2\x10L{5\xba\x94\x98*\x83\xc6\xa1B\x01\xa4\xa4\x189\xc0\xb64\xd3h\x10\xb7\xc4\x94;L\x99\xf0\x1cOn\xe49\xe1\x99,\x91;\xc575\x11\x1d=\xdd\xb7\xca'\x87 b\xa1I\xcf\x1cV\xe1f\xecB\x98\xbd\xf7\xdf\xdb\xb1S\x16K\xf8\xe1\\\xca\xb7\xb6`\xe8\x08\x91\x80(T\xbe\xdcDZ?\xa6\x07 \xe9p\x84@\xcb\x95V8\x00\x8f\xfe$7\xdd\\\x19@\xa2\x8c`m1\xa3\xd7\xcc\xcdm\xf4k\xafk\xf9A\x8bH\x8c\xd9\xdd#\xcf>K\x93%\xe5\x15S\x07\x15\xc35\xae\xac\xc6J\xe5\x15\xfb\xb45\x841\xcc\x95\x15eX!Z\xe1\x13\xaf8\x87'H\xeb\xb8\x069\x83\xe9\xd0\xad\xc4\x17\x92\xf6\x97\xc7\xd9\xc5\x08\xa4\xa7\xadE*\xf5\x04\xe7Z\xb5\x85#?\xcb\xdf\x18>\xc0\xb1O\xf2\xcb\xb6\xd1ky\x97\x1b?* {\xc1\xae0\x08Q\xce\x843Z\xfd\xe8q\x15\xfe\x06d\x12\xb2\xf0l\x86\xd8o\x85\xb4p\xf5%2\x89\n\xd6O\xb1\x14\\\x95\x89\x14\xd8\x89\xc6\xf8\xef\xb4\x8a\xc6\x99*h\x14\xe9!~\xb8q\xa1\x15>\xe0gY\xfd\xd1\x96\xf4\xcc(/@\xb2\xb6\xa2\xd8GL\x18X\xddw\xee+\x9fEO-`\x9bEQ\xe5\x7fc\xfc\xab\xd9o\x8dG\x8a`\xd6\xd4Q\xde\x8dai\x92FX\x00{\xe2\xa5\xc4\x9f~~\x13\xe7\xc3\xfd\x17gv\x0e?\xea\xdc\x18\xf5\xfb\xdc\xa8E\x16\xce\x8e\xa6A#M\x87j\x98#\x08\xe1\x18\x8a#\x0877\xf5L\x19\xf0\xc6px\xa1\x83\xfdG\xad4OQ\x1cp<\x1c\xc2\x16\x04\xadr\x1dQS\xf9!]9\xb4\x9b\xa1\xe3\xb2\xcfa\x93\x03(+\xe7-\xa0\x001V\xc9\x91\xec\x16K\"\xc1j\x0ca\xeb\x84\xf7\xc6\xe5P0 g3lb\xd8\x84\x0c\x9eAQ\x9e$\x05lA\xe60\x7f`\x84\xda3d\xe6\xc2\xad\xad\xb6!\x97\xc4\xf3\x8c\x07\x0b\\1\x1ep\x05\xc7\x90\x1d\xc1\xaa\x0d\xe8P\x03[{>\x1cCz\x04\x9b\x9b~\x1b\xfa\xa0\xc7\x84\x9c\xf7\xa2\xb8\xce\xf2\xd4\xa6|\x82\xef\x02O\x8d\xa1_X8H\xa4\xd6\x8a\x8a\xa0\xf0\xf5e\xc9\x84\xee4f\xba\xdb\x03\xe9\x89\xcaz-\x9a\xeb\x8eE\xc3+{a\xbf\xa6\x1bJ^\x16\x0e\xaa\xe4\x9a&@\xa6\x96\xae\xfa\xb6d6\x18(\xeb\x94smM.]Y\x14V\xb2\xf2L\"\x963\x87K&8\"r\x02\x94\xb8C\xa2\xafK\xa8\x98\xaf;\xe8\xdb~\x83\xae\xc1\xa6W\xc5g\xfd*~a\xff\xb6~\xa7\xbf\xf6\xad\xbb\x97V\xa3\x92W\x96\xde\xb6|\xd6\xa4\xadF\xa4\xa0\x15\x1b\xb6\x9d\xd3\xd3i\x84i!\x1c\xbe \x19+!\xcd\x9f\xcf\xf9M\xcaO\xc3!\x8f\xdaL\xd1\xc6\xde\xbe\x0b!\x9b\xf6\xc4)\x7f\x9a4yF\x94\xfc\xf0\xad\x0b\xfe\xbc\x8d\x9f\xad\xb3\x10t\xd8q\x8d\xc5\x84SH\x91\x07yq\x97\x13\x91\xf1\x9dbU\xf5!WQ\xe5u\x9b\xae\xb6~\xbdl\xeb\x17\x05\xf3;?_x\xcb0.i\xc6\x1e\"[:\x9f\xe8\x1aq\x04 \x8an\xdb\xd0&\xa5\xbd]\xb4\xafu1F\x07\x99$-\xc9\xe5\x03\x11,\xc1X\x82\x9e\xe0\x11e\xa5w\x9e\xc2)\xec\xc2\x98\xdd\x8dv\xe0\x14v\xf8\xdd\xf0\xe9\x10Na\x04c\x93\xe8\x05iE\xd8\x84\x19\x1c\xa3\xb0O\xc8\xeffm4D\x9f\x04\xb8\x11\x1c\xc3ptX\x12rQ\x8b^ \x04\x9da.\xd2'-.m\x8er\x19\xc3\xa7#x\xc2\x88X2\xa1\x83\x1b^:L8@\xd9\x17{g\x08O r\xe0\xf8\x18\xf6\xe1\x1e\xf6w\xe0 %^\x9f\x89\x0cb\xd8\xdd\xec;t\xd7`\xf6).\xb9\x7f<3>\xde\x8d.]e(!\xf6\xbe\xfe\xcc\x97F4\xdc+G4\x1c\xc1=\xd8bL\xf2\x10}:\xc4\xd1`\xf7\x80\x7fw\xcc\x13\x96\xdd\xdf#9+%x\xfb^\xe3\xdf}\xfc\xf8\x8b\xf2ng\x0dh\xd4\x9f\x15\x06\x08\x1d*\x10\x92@\xe6\xd7AV8\"\xef\x1b\xad\x89\x82\x8c\xa5\x92\x1bI`\xd2\x0eQO\x12\x97\xc6X\x94/\xc2\xcfi\xdd;.\xee\xe4!\xc5s\x81\xdc\x9e\x1d\x94i\xe4\\H\x19>\x0f\x98\x18u\x00O\x00\xf3\xc5\xdd\xb3I\xe4\xdc\x0c\xcb%w\x0f<\x95\x1cer\xc4w\x18\x1bg\xf3\x04fM\x8co\xc2\xd2\xdd\x14\xc9M\x19\xa7\xa9M|\x8a\x8aq\x8a^\xbe\x94$\x9f&\x1d\x1d\xb71>\xe7b\x10\x9d\xde\x02$\xdd\x85\xa5\xc9V&\xaeT\xaf\x0c\x04(\xc3\xa2\xa4\xa8=\xa4\xc7\xeb\xe6I\x9f\xce\xf0\xe3&u\x99j\xeeK\x07\x11\x157\x81l7\x8eO\xf9.\xf7\xb8b\xe9\x84\x1e\x0e\xb9w\x1e%\xb7\xe5\x93\xf6y\xd8$U\x84N\x82\x12V\x0dC\xc0\xba\x95y\xa8\xba\xb37\x1b\x1e8\x90{o\xde\x9f\x7f<{yq\xf5\xee\xf9\xffw\xf5\xe2o\x17g\xe7t=\x0dL\xb2\xb8\x139\x89\x0e1\x98\x05\xe9\x9fwy\xf6\x18\x83\xdf\x0b\xdf\x1a\xc5di\xd8a\xa2R\xb3J2\x9fie)\xbd\x00\xb0\xe5\x18N\x92\x1e\x01\x13\xc4\xc5{\xb5\xdb\x94\x1f\x89K\x8f;\x1e\\\xd8\x1dqZi\x96$\xb6c\x14\x87\x12\xca\x901K\xd3'O\x84'x\xf9\xcc\x1eb\xc2\xbcJ\xa9\xd8\\\xaa\x9d\xd9\x0d\xf8\x1864\xb2\x93\xfa\xbab\xf1u\xbe\xbc\xf3\xbf\x96\x91\xa3|\x1b\x05\xcb\xab$\x89\xce\xc3\xdf\xe8t\x1e\x0e\x9fb\xf2\xa1+\xeea\xd3\xb9\xe2\xb5\x13[sJT=\xbf\xb8`\xbb\x87\x1f\x8cT\x7fd\xf3\xf0EZ\x0b\xcc\x16!\xb5\xec Y\xeb\xa3v]\xd1\x91k\xcb\xb8\x06\xfb\xc9st\xf5\xa7\x0d\xb1_\x18\x1cJ+!\x13\xdetY\xa9Xa_hmM\x98\xe1K\xdd\xd5\xad\xcd\xccAV\xec16\x08\x02ZGc\xdf\xd43\xd0\xc9\xb5\xd5\\j\xb5\xd0B\x0c\x933\x0c\xd2\"\xd5\xa5\xbc\x07\x99\xc4\x97FvK\xc8\xa5j\xc7\x83\xad\xcb\xb3\x0f\xdcV\xdc\x84\xee\xcc\xbd0\x13\xe7>7F1\xb3\x812\n\xf7\xff\xa0\xf9\xa3\x97\xcf\x8c\xb9Q\x13\xce\x19_\xe1 \xdf\xb1\x16\xa1Z\xb7is\x91J\xce\x1e'\xb0p\xa1F\xe9I\xc7\xe7\xc6\xa0\xfe.\xbb\xf5W\xc3\xfd\xb6x\x9d\xa0\x06\x0fh\xd3\x13\x11\xad\x9eH6\xd7\xe4=\xc9(\x89]\x99\x0e/\x8b(\x0fW\x11\xa1\x10\x1c\xeeo]\x87\xb9\xf6X\xac)\x1a\x06Gh\xbeK\x8e\xd8\xf2\x1b9p#\xe2\x9f\xba\x98\xb4R\xc7\x7f e\x82\x1cB\x04\x04\x10\xeb`\xd9\x19}W\xb0\xec~#XvF\x8f\x02\xcbn\x03,;\x8e[=\xa2`b\x7ftZ\xb85\xa0\xb5\xbf\xfb]\xa1u\xf8\x8d\xd0\xda\xdf}\x14\xb4\x0e\x1b\xd0:\xd0Ck_y\x9d\xe8\xda\xf9\x83F0\xcc\xe6LX}a\xfc\x16x&\x8f\xa7\xf2(\xb1\xfa\xd5\x8b~S\xb1Z\x890\x90\x90\x1f\xa2\x19\x1e.\xba>M\xa0\xd9(\x96>>\xa1\xbd\xe5w\x9d\x1f\xe3\xeac \xa4\x89\xe4\xcc%\x19(\x1b\xa5\x1b\xd0\x83\xee\x14\x17\xef\xc5\xc7j1\x9b\x9c\xac\xa0\x0f\xb5\n\xbd(Vq\xf1\xc6_\xae\xd3x\x1b\x9d+.^\xef\xf3u\xeam\xa5\x8e\xa1\x1f\x85,.\xde\xfe\x87u\xda\xef\xb4\x1d\x86\xaa\xe2\xf3u*n\xa1\xc6\xa1\x17E\x0e=\xa9rX\x872\x87j4\x17\xfdF\xd3I\xac\x03\x94v\xd1Z\xc6\xfa3\x8b\x0eUz+\x8e\xb51\x14\xd4\x8b0w\xc4M\xb0\xac\xbef\xd3\xa0\xa5\xc9\x1eD\x0c\x12\x1c\xac)\x0cI\x1d\xa9\x93_\x0b?j\x8f\x1f\x01ZiC\x87lA:\x0c\x85\x8df\xeb\xc1\xc3\xcf\x80\xfb{\x8e,KY\x88\xde/\\\x19E\x18g+L+\xd6\xefd2)F\x98\xffRC\xca\xdf\xdaqq>=\xe3f\xd3%]Q\xba\xf3 \x8e\xe4\xfe\x92\xde\xd2\xcf\x83\x85\xbd\xed\xfd>z\xd8\x9e;\xde\xdf\x930\xb6-\xb0Dx\xb0\xb22\x9e\xec\x89\xa5P\xf7<\x0f,\xc7q\xc1:\xe6\xf4\x06\xae+]6\xf4:\\\x0c\xf2\xa4N\xa3\xf6\xef?\xd5*\x8fW;YU\xcfmf{\x8e\xda\x11\x0e\x90\xb1Z.-\xed\xb6\x94\x17\xcc\xd6,i\x9c\xa8\xb9\xf0u\xa7'pY\xef\xfd=\np\x06,\xd5\x9cr4\xeb)>\xee\x8f\x9e\xd2G\x80\xf6\xd1\xa6\xf1\xa6\xf0\x8c\xf7'\xa7\xbfZ\xdd\x84\xaa\xf2\x9d.\x04Je\xe6RH\x07\xb8\x10\x97\xbf\xd2\xf2WR\xfe\xaa6_/\xf1^\x88\xae\x03[t\xf5`\x0e,\xd8\xa2\xcb\xa9\x90%z\xa1\x0b\xbe\xc3\xcc7\x10\x9c\xa5^0\xe1*\xd8\x9ae\n\xd3\xec\x0e\x8e`\xc6\x0ci77gf `4\x991 `0\x99\xb5J\x00i7ia\xd6KZ\xda\x8c\x83\x1f!\x01\x0c\xe1\x18\x8d\x90Q\x02\xe8\xc31\x84f \xa0\x8c\xa5\x82\xa8\x98\x92>\xb1\xc6\xa4\xb6\xb8q.\x82\x92\x9b\xe3\xdbf z\xd3\xba\x7f\xad\xc6\x96\xf5\x90\x1a\x98:\xaf\xad\x11\xc9\xe4\xff[\x1b\x1a\xb66\x84\x1e\xfaz\x0cf=\xbdp\xdf\xd4E\x10\x86\x1cm}\xa5\x10?X\xac\x0f\xda0@\\X\"\xe2\x87\x984\xd99\xba\xa8\xf1\xe5\x1f\x1a\x03\x03\xa9\x91\xfe\xd4\xd8t\xa6\xeacz&IB\x07s\x1c\xcc)\xf9\n\xb2x\xa1'D\xff\xde\xc1\x0c\xe5\xa5O\x7f\xce\xed\xa9\xf7p\xc2\xf5z\xc9\xda\xeeU\xadud\xaf\x17\x17Fu\xc3\x1d\xee\x8e\x96\\\x02\xea!\x9e`P\x9e\xe3c8\x84\x1f)\xfd{\n \x8ca\x08[\x908\x0e\xdahk^\xf4\x1a\xf0\xfb\xb5\x06\xbc;z\xba\xfbt\xff`\xf4\xf4;\x8dz\xd7<\xea\xbc9\xac\x1d\x1c\x16\x03F\xaf\xc1}\xea\xbd?\xbeea\x99\x96j\x0b>y\xf4\xfa|U\x1bQ[J\xc6\x90\xeeB\x04\xc0\xc0e\xa0v!\xe1<\xae\\\xc7h\x87\xbd\xa3\x10\xd8\xed\xd5\x87\xb7\x8f\xee\xc3\xa1\xa1\x0f{#\xf6\x8e\xf6\xe1P\xe9\x83|\x97\xa9t]\x1f\xfb\x1d\xe1\x15\xd7OI}\x02\xff\xfd\xdf\xc4U\x83`\xe6p\x8a\xa9Z\xfe\xfb\xbfs\x97\x9d\x14,\x0c\xe5&=\xb5\xcb\x1dBD\xc4\x11B\x0f\xf6\xf2Q\xeaT!\xc9\xec\\\xf9&\x17\xdf\xe4\xe57\xb9\xf4\x0d)\x9f\x10\xc7`\x03\xecT:\xcf\xd2\xea\x1aaa\x0c\x90\xb9\x96\xfc\xa4\xa4\xc0`K\x8d\xcb/\xae\xb8\x0c\xf3\x9b\x08q\x86\x81\xbb\xa81\xe7\x9cNH8\x19\x13S\"\x80\x0d\x04)\x00\xd2\x95\n\x07\xaa\x85V\xf7\x80P\xd8\x0f\x11\xd5\xe0\xedYO\xb9\x1a\xe1\x92\x19!\xb8A\xaaM\x90\x13\xb2|\xa3\x05\xf7\x89\xe56!\xdcgoX\x12G\x9b\x9bt\xd89\x17\xae\xffxB\xe9\x1e\xe7\x88\x13\xb5\xec\x1b\xd8\x84\xf0\x12~\xd4\xb9v\xebIY\xfd\x88_\xfccF\x0c\x9b\xb0\xb5\x95\x8bq\x1f\xe1\xd2\x1et\x0c\x97~\xf0\xed\x03>\xec\x83\x10\x84\xc6\xa9\x1c\xe3\xd0U\x15\x1cl\xe2\xfa\xb48\xdco.\xab^\x8d\x8e\x0c\x8drK\x0f\x04\xca\xf0\x12\xcf\xfc~\xfdhN\xf6\xb7\xf5\x03\xa9\x8dZg\xfa\xf4cg\xf4Hx\xec\xaa\xfd\xb0\xcd\x00\x91\x1f\x8d\xf0\x11\x8b\xf37\xdc?88\x18\x0d)\x17Q\xbe\xdf\xe9\xd9\xedG\x82\xaf\xd1\xedF\x1f(gc+#\x18\xee7\x87P\x1b\xd5\xcee\xab\x08\x9fv\xfb\xff:\x8c\x06\xcfN\xf8\xe7\xc3\xd1\xa1\xc3E\xe1[\x9cv\\%\xb76\xa5\x12(X\x1d\xc7\xedF\x07\xff\x10\xf4W\x03\x8c\x84\xdb\xd2\xcb#$/\x9bX0T\xb0`\xda\x0e\xa4P\x03\xa4\xd0\x08\xa4\xb0\x07\x90\xbe\x13\xcaD\xdf\xebr\xc5\xa3:\xefG\xc0\x88\x10[\xd2>@\xaf\xd3\x9e\xd8u\x0d\xe4j\xc4fM8\xde\x88\xd8\xaaF\xe4b\x84\xfd\xce\xe8`\x9f\x0e2\x86S\xc6\x08\x0d\x86\x07\xfb\x03\xb8\x87\x18\xc6\xdd\x14\xc8\x1a8\xfa\xd1\xc3a\x83\xb8\xaf\xa1\xf0?n8\xdf\x0f\xd5\xaf\x87\xe9\xebx\x92>\x1b\xed\xf6\xean?\xe8\xf7\xef.\xb6\xdc\xect\x0f\xe4\xde\xd5\xdd\xd7Q\xe2k\xb0\xfb\xe3\xba\x9b`\x95\x95\xa2ac \xb8\xbe^\xdd\xf8^Pktc\xd8\xb7\x1b\xaf\x92\xe2:\"\x8f\x04\xc7ag?\x06\x82\x01\xed\xd7\x8fG\xc2\xa3\xbb\x1f\xc3>\xfd@\xe6\xd9\xc8\xcd\x18\x848\xc8\x86n\x92\xda\x01\xc7\xacXPm\xfbF5 P\x0f\x93\xd8\x81-\x8a\xf2M\x8e(\x899\xc6_\xd8\xe2\xf4\x81\x1b\"\xafBN\x13AI\xc4\x8dc\x92\x15eD\xc4 \x10\xd8\x86\x84\xc9\x81\x8c\xe8\x8d\x16n\xc5b%$\xb5d\xc2?\x10\x921\x161BSc\xa4$AS\x88\xcfJ\x88nm%\x18 \x8e\x93\n\x1a\x90&\x02\xa4\xe1w\x03i\x83\xa8h\xb7`\xd1\x00U\x85%E\x16{{.\xeaQ\x8c\xf9~pv\x10\xe4\xb3(IP\xd2\xcd\xb1\xb5\xbc\xca\xb8\xc9\x7f\xaf\x81\xe8(\x90o\x1e\xcb\xc8e\x92\xe3\xb6\xd1\x9cj\xb6\x87[\xcd\xd9\x90\xcd\x19\x8aH)M\xf5\xf7Z\x03,G*=|z\x0e\xb27\xa5\xfc\x07\x0e\x92\x8fF\x1d$\x1f\xbbf\x90\xc3\xb5\x06\xa9\xa3V\xbey\x90\xbb\xae$\x12\xef5RF\xb3\x88\xd1\x8ev\xa5\xe1\x8e\xaa\xe7\xc3}\xc3\\k\x963\x85\xcc{\xfd\xf4\xb7\x92E\x12d\xfe\x80\xe9_\x1f2\x06\xa8\x0c\x0dP\x19\xe9\xd7\xccN;d\x86\xbd!\xb3\xe6\x11+\xa4\xc72X6\x8c\x06G\x02\xd57\x8e\x07\x0c\x1d\xad\x97\x9d6\xce\x96\x84\x1d%[\x1a7o\xbd=\x18\x9e\xc5\xfa\x83\xa5#J\xef#Op_:n\x88\x10y3\x89z\xc1~\nsLv\xb6\xd3\x01]\xe2\x97\x05\x86(r\x95s\xdf\xa6\xa7\x94\x0f\xcf\x9e\xc1\x80\x9e\xa3\xc5w9\xaf\xd6\xa4\x00\xfeO\x99\xe8\x16*\xe2\x9b&[\xcc\x85D`\x84\x15\x81\xb1\xf6\x8co\xfecf\xfc\x0f!P\x86\xa3\x03\x17\xb6\x86\xa3\xc3\xb5i\x14R\xd3!Q\xd02\x9f\x84\xe1\xb7\xd0/\x7f \xf9\xb23:\xd8\xa7cE\x19B?\xd4\xfe\x07\xd20\x7f \xf3\x88\x81\xfe\x81t\xcc\x1fH\xc6T\xf9\x10\\%\xedA\x8f!\xb7\xcfm\x0f\x12\xa7F\x12}\x13A\xf3\x07\xd23f\x10\xd5\xb7o\xcdHB\xec\xe2\x1eP\xfc'\"~\x0c\xf2\xa7v(\xbeR\xe6\xac\xcb\xab\xa2ji\xdd\xf9RZ\x1a\xf6j\xc9$Ejo\xea\xedc\x06e\x12\x14\xad\xd5T\xe7\xa8\x82du\xb7\x1e\xddR\xa5\x9b\x1c\xa0Cd\xe9\"X\xd9\xd5\xe7\x8a\xa7\x97\x94\xa5\xa42E\x90\x0b\xd0\x0f\xf3\xb2F\xae\xe2HK\x12\x10\x9d\x17\x98\xf7eWz\xa7\xb0\x11 \xa5\xea\xa0\xdc\xad\x8e*\xf26\xc3\x9b\xdcO\xe7$?\xcf\xfd4\xef\xce\x86Z\x9a\xf1\x003\xd6T\xba\xa1o!K\x8a4 k\xb4\x90\xb6\xf5\x97\xd5v\x16O\xbb\xebJ\xeb\xce\x17%\xf4\xeb3*\xd9_\xe5\x18{iK\x9a\xa8\xda\xcbM\xadU.\x12\xb4L\xbf\x95\xea\xe3\xd6\xe3\x1cTn\xa8\x18t\x99+\x07\xb1\xc5\x96\x904 \xb0t \xc3#HxV\x83\xad-4\x0bK`\x13\x10I\"\xae\xa3w\xba\xb8/\xa5\x93\x11eA\x86d\x07X\x18\xaf\xf5\xb2\xfe\xb105\x8aY\xda\x1a\xedk\xf3\xb9d$\xaf\xf2\xb8\xd4Lubf\xf6\x14:\xfa\\\x98B\xef\xd7\x86\x08fa\x14\xad\x87\x084NWkg\xb6\x16\xe9 0\xa4\x06?6\x95\x1d\xa2M\x9f+\xe1\x85\xe6'.\xcf\xba\xd1\x95\x19 $\xde\xaa\x16\xb0\xdcdy\x04\x18\x80\xe8\x18m\x8c\xc5Am\x88\x8ff\xce\xb7\xaa&\x9b\xd1\xe4\xc33\xf9\xb3\x97\x19\xbf\xfb&\xf36\x80\x1d\xdb\xad\xe7\x02NM^\xc5&\xcf\x8fF{\x95\x12`:-\xc9\x9b)\xcb-\xe2T\xe9\x17a9\x00n\xab\x87>\xca\xb5A\x08\xbc\xe8OB\xf8_P\xaca\xb3\x977b\xe4\xd4\xfb@\x07\xfb\x19N`{\xf2\x9f\x9b\xbfl\x0f\xb6\x9e>\xdf\xfa\x0f\x7f\xeb\xb7\xad\xab\xcb\xed\xb9\xc9\xf5\xe6\xd7\xf6\x10\xae\x80\xca\xd9S\xb0\x06\xe8\xf4_O\x13:V\x1e\xd4\xfbfh\xf0\xb5Q\x01x\xa3\x0f\xd0\x96\x03\x8f\x8a3\x84\xed\xce\x1c\x97\x95\x83L\"\xc2\xf3\xeb\xf2:\xb4\xa7P Y`\x9bFb\x07\x07\x9ea4\xef=qD\xef\x1d\xec\xec\xee\xb6!\xdc\x90\xe7\x873\x97\x80r\x93>\x83\xbd\xfd\x9d\xe1\xd3\xae\xc2\xf4b\x89(vh\x7f\xb6\x86\xb43<\x99\xc4h\xe7\xa9\x0b\xc3\xa7C\x17\x86\x87O[\xd0\xba\xb8\x82$\xce\xc3\xb8\xd0\xe7R\x12\x979{\x10\xf0\xbe\xfb R?\x19\xa5z\xf2\xf5O\xd4{\\$\xed-u\xb6\xd2\x9e] \x97\xc9\xfe\xce\xc8\x98BP\\\xfd\xa0\xe2\xfe\xc1]\x8e\xb9\x8f\xc6>lR\xban\x8b\xa7 8>\x86!3t\xd9\xe2\xa3\xd1\xd6\xc0O\xc5\x84\xf3==\xc6c>\xc9\xab\xfd\x1b\xb3D\x15]\xfb\x8c58d\xd9Y\xba\xd2\x1f\xf0\xce\xc4\xad\xe3\x10\xf37\x1a\xec\xf6l}\xb4^\xeb\xf0\xec\x19\xe62\xc0\x00\xdb\x98\xd0 \xa6w\xa3\xc3^\xdd\xc2y\xea\xd7\xaf\x9d\xf5\xfb\x85I\x17F\xa3]\x16\xc2\x03\xf6\xe1 \xed!\xf6n\x8d\xbev\xa0F\x1c\x07O\xd9\xa0\x8b3 \xd2i\x05\xc9\x94\xc0*1x\x91\xc9U\xb2\xf1\xee>b\xbc\x87t\xbc\xbb\xe4\xeb*I\xf3\x0cN\xe0\xf7\x07\x89v,\xc1\x106<\xd2\x1b\x9b7#\xf9E\xb8$I\x91\xc3\xc2g~\xa0\xd7\x84\xc4 B\xe6W\xf0~\xd04\xe0w7\x10D\xc4O\xbf\xa1\x89\xa2\xb9\xe0\x19n\xc5\x18`e\xef\xab\xe8\xc2\xe5#\n>\x95o\x16T\xe3\xc9 \xf3\xe2\xda`\xf9\x8e5\xf5\xd0C\xb6z\xecv\xd4\xab\xcf\xb7!\xaab_\xd4\x97\x81\xc8\x0f\xa17\x955\xa6\xef\x10U\xb2\xa5SF\xcb\xd79\xfc\xb7\xb6\xd0\xac\xab\x94\xd2v\x07\x0f\xa8&l\xa3Z\xac\x8d\x95\xa0\x1d\x03f\x9d\x11\xdf\xc8\xbc\xa6\xb4\x10O\xe5\x9b\xb1\x8av[\x13k\xd0\xeaU4-\xdf\x19\xe6\xc9\xd4\xa9\xda\xe2=\xad\xdf\x8e\xd5,\x89\xad\x1d\xa3M\xa8Y\x15\xcb_\xb6\xb4\x9a\xe8\x1e\xe7\xa9\xcd&Jb\xb3\x00C\xbf\xd4\x9f\xcdx\x12\xda\xe6\xc6Y5f\x04\xb3\xb7b\x1a\x0b\x9bW\x05\xa5X\xe0\x14[\x14\x01\xc4\xed\x08\xc3\xa7b\xdd.D\x92\xecuj;\xed\xfbu\xdah\x16\x89\x88\xc0\xc4L\xd2\xb3\xad\xb0W\x1a\x8a\x01\xfb\xd8\xc6KR\xa6S\xf4\xed\x083\x11\xe9\xd79~@\xb1d$\xe0\x8aA\xc4x\xf6\"\x9e\xf2cv\xe9\xa5El\x9b<\xfc8(\xe4&;v \xf0D\xcfl\x8f\xea\xe6N\\\xfd\x8ev&T\xa7\x98K^\x86U\x1a_\xe9\xa1\xdd\x16P\x12Q \xab\xc8G\x14\xc8b5h+\xa5\xabV~\xe1\xf6o\xc6\x8c\xc2\xc4\x95\xda\x06\xf9\x12\xf4\xc2^\xe2\xean\x08d\xf2K\xc6\x9b\xe6\xe6a\xad.@\xa3\x01\x8eL;\x1a0\x8f^\xfb\xe6A\x05\xd8C\xebN\\h\x858(\x0b\x9c\x15(9\xe1B{\x96\xe6\xe8D\xcaZ\xaa\xab\xee\x86n\xec\xaa\xc5\xc4\x8b\xc9\xd7\xfc\"\x0c\xbe\xb4\x12\xa7b\x9fR\x8a\x80\xd1\xbc\x8d\xb8\xcdM\x93!\x94W\xa8\xc5\x9e\xc1\xb0 \xce\x12\x17\xc4\xcc'\x93\xb2*\xea\x97G\x10onRr-f\x86XR\xe8\xe8F\x98\xfd\x883\x1b\xe4V\x80\x0fe\xf7\x98\x15Z\xa2\x07\x03\xfa_aO%T\xe8\xc2B\xb6\xabG\x00\x9b\xcfF> <\x1c+[\x8e\xd5\\\xd4\xaaM\xbc<\xcc#\x0cJz\x9d&\xb7\x19I-\xfa\x90\xff\xe6a\xf2\x13\x8f\xc47H\x07\xd2\xdf~:\xbf\x11y5\xbd\x1b\x92ft\xfeX$\x93\xf2>+K\xe3\xbb\x1b\xfcn:}\x1bf9\x89\xb1\xde\x1b\xf6\x12\xdd\xd1\xd9\xef\xd9L\xfcL\xc92\xb9!ja\xf6\xf4y\x14\x89\x17\x99xC\x96a.~\xafR\xb2\"q\xa3%\xfe\xf8C\x1c4\xea\x8d\xa4\xea\xccK\x8d\xef\xc0\xc9e\x1dz\xd7a\xdc\x99\\\xa5A\xb5\xae\xd2$ YV~\xccC\xa4HA\xf1\xea\x8d\x04\xb7\xd3\xb6\xf9\x16\xac\xd2\xb6\xa5|\xb6\x98\x86\xe9\xe3z\xc6>\xed\xeaW\xb1\xf4\xb3/=z6\x90\xb6>h\xb8\x10E\xc5o\x15\x19AEO\x90KL\x9c\xcc\x90\x98G\x84\x1a\xa0\x8a\xd8\xda\x90Uu:}\x0f\x06\xb1\x15\x03\xf5\xcb\x8aU\x19C\x83k|\xc4@\x9aH/\xd5\xe2\xd0\xca\xbe\xe6\xa4\x0bk&f\x94\xd8\xc0p\xc7'0\xa4\x88E\xd2\xdeT\x98jx\xc9\x835\xc8\x8f\x9a\xf4DlLx+duZ\xb0\x19\xd7\x07\xa8\xc2{\xb5\xd7Lt\xcfP{\xea\xa8\x02|\x9fb\xdep\xe2\xd7\xb1\xaeof\x961\x17\xd6\x86\x88\xa2\x19\x0b\xd0 \xc3&\x91\xa1\xa1GnHzW\xcb\"\xdd\x95\xda\x0c\x19\xb7x\x92^j\xf8\x1bts\xb1\x19W\xcdp2\x9b\x04\x17B\xc7a:\xb5\xd05s\xf2Z\xde\xbb1\xf15\xc2\xb5 \xc7\xb8\x84cN\x0f;8\xc5\xe0\x14C\x1e\xd98e\x07\x1c\xcb\xb9 )\x85k3\xa9\x9d\xe4-\xa0\x16\x97\x00]\xfb\xa6\xef\x03}6\xc4Y\x9a,[Yv;4\xcc\xc3\x83\xf1\xb8\x8f\xbc\x94dE\x94\xbf.\xe2\x80\xae%\x17\x9f\x04\xc9rU\xe4~\xce\xd9\x94\xce\xcd&6Z\xe3\xe5\x03\xab/#\xf9\xa7GWJgH[q\xed\xa1L\x0c\x88_\xb9wuE\xb2w\xc9\xb4@\xf6\x8d\xf2i\x98:\xd6/\xa2\xfc\x1dY&,soB\x9f\"\xda$\x02\x8b\xbedH\x94\x11\x1d\xe5\xcb<-\x82\xbcH\xc9\xb4D\xb6}\x18\xefGP\x99\xbeBe6\x99s+\xc1<\xb8F\xea]\xc8\xfeM\x1dg\x87C\x06\xb30\xcd\xf2*^\";\x18\xfc\x18X\xf5p\xbb )\x01\xe2\x07\x0bX\xf1\\\xbb\x94\x11\xf0A\x9c%\x9a\xa3\xc3Gk\xb0\xb2SG\x0d\xa0\xd0\xbd\xc6\xd3\xf8~!wYC\x88UR\x8bq\x1dU\xb5\xf9\xc3\xd3\x0dY_\x0e\x8e\xdb\x93\xe4\"Z\x84\x9cW\x08\x81\xd3~\x03F\xfb\x11N\xfb\xe5\x93\xb4\x9d\xee\x03i(^J\xa6E@l\x85\x13\xea\"\x98\xc9\x84R\xcb\x97\xcc\x18R\xa3\x8es\xe1\xf7\x07E %\xb1\x9fu\x91\xb6\x8f\x04L}\x99\xd3\xf5m'z\xb5\x97\xc2\xa7 \xee#\xb6\x87\xc3\x03\xe5@D\xc6\xc6\x1e\xed\xee8zV4\xb6\x87\x83\x01\xa5\xfc\xda\x1a\x00Y\x84'\xd2'$6Z\xabK\x83\xea\x91TLZ\x12\xcc\x18tM\x96\xb4\x1a\xea\xc1\xaeaD\xed\xcc\xf5\x86\x1c\x0b\xd5\xc4G\x8b=\xb6\xf1H>Z\xedq\xac*$\xeb\xfb\x8e\xc9\x9c\xc6`\x8d\xbc=o\xcf\xd2\xad\x12\x8d\xfd\xe1\xd5\x153\xd4\xa4\x7fO\x84\xdb@o\xf0\x8d\x0e\x0e\xd6\x86\x9f\xcc\x85\xca)\xe7j\xb2\xeau\xa7Q\xbf`\xf7\x0ev\x95\xe7!\x7f\xbe\xa7<\xa7{\xc7\x9ap\x9c\xf8\xbe\x88\xa2K%Tx!\x17\xf8,\xd2\x9d\xab\xa524n?E\x13\x04f\x0fx\xe1\xcf\xcb\xcc\xde\xdf\x01R\xd2\x89Bo\x0b\xcc|2\xe6\n\x16\x08c\x8ev\x99q'\nF\xc6\xc8&?\x16\xb0{OGz\xc8>\xdd\xeb\x9cx\x0d\xbd,\x96q\xc2\xdej\xb7E\xca\xb2\\\xc4%\xd8\x1e\xdb\xf7\xd1Su\x96Y\xdf\xf7w\xd41\xb1Uqp\xd89$\xc3\x0c\x85\x0c\xde)\x83w\xb26\xbc\xf5\xb2> !\xef\x0e4#\x91NXJl\xb4\x93\xd4\x82V\x99h\xce0\x89s c\xa42\x84U\x98\xf9\xbc\xab\xbdx0\xc0\xad>\x96\x90\x1f\x14\xfbR\xb5\xa1\x17\xc6\x0b\x92\x86\xfc\x149\x1c:\xcd3-\xb6w\x06\xeaL\x16\xac\xae\xda*\xac\xea\xb2g.\xf8\xd2\x9br\x80\x19\xae\xbd\xa2\xd2\"\xf0\x14I\x83#\x88\xe0\x18*uFD \x80\xe6\xda\xa5\x04t6\x89\x14\x18\xce\xaa\xfa&\xc1%\x8a\xb9\x94G\x94)\x93\x1f\xb4\xebwg\x86C\x879\xc7\x88@\xda\xc9\x0cfU~IJ\x12\xce\x1a\x84\x96_W\x95\xb9P\xa8\x0f\x10\xfbo\x08\xd7\x89\x94\xf8S\xff:\xe2\xb1c\x17aV=9a^\x80\xf5\xf2\xb7i\x98\xd7\xcb\x97Oxy\xa6q\x89\xa2\xe4\xf6\xaf~4\xfb\xb0\"1'\xd3\xeb\x15\xd5K\x94\xb55>,\xabL\xe2\x80\xd8\x16\x89\xa7\x96\x0b\xabvp6\xb5\xf4\x9a\xba\x85\xc3\xc1\x95\x18\xc0y\xee\xe7\xc4#\xf1\x94L\xe9\xcb\xb4\xd4\xc5\xd9S\xd6\x85.\x1d}c\x0e\xb16[E\x0d\xf4\xe2;\x99\x1d*\x1f9\x19.\xaf!\x17,\xd1\xaf\xbf\x86\xf3\xc5\xcf~N\xd2w~\xfa\xc5r\xd56\xe2bIRZn\xdc\xd0\x85\xcfI>n\xa7\x98\xc5\xe6\xd6\x00b!7[\xdf\xfc\xd5\x80\x1c\xb7\xd7P\xa6$\xcb\xd3\xe4\x8eL\x1b\xdd\xef\xddE\xc9\x9f\x86\xf5V\xacS\xec-]@\x8d\x12\xb5\xf1TK\xac\xfe\xa5W\xf6\x0d\xbd\xce4\x80(\x0b(d\xb9B\x08\xd4\x06\xa2\xc7\xc8\x7f\xfc\x10*\xfd\xb3i\x10\xb4\x88Q\xe1M\x19,I\xe1z\xc5\xbf\xea:\xe4\xb1Av\x80\x14Q$6,\xae}W\xdeGyM{\xff]\x0e\xca\x9d\xe1\xc8\xb1\x1f{\x8a\x93\xca=\xabT\x91t\xd1\xe8k\xf6o\xff@w\x90\xb3\x10\xf7\xfe\xd7G\xf6;\xb1\x07.\xd2\x1e\xdf\x00\xccu\xcbk\xa9\x94\xa1flvl\x1f:]\xf2\xbe\x90;~z\xe2l\xfb\x98$\xc2\x16\xc0\xc4@\x0b\x82\xa6\xf9\x1d*8\xf4\xb2;\x19\xc1 \xc3Pz\n6\x05\xd6F\x0bez\xd0\xd2\xef\x1b\x86\"\x1a\x9a\xb2}\xd4D>\xca\xf1h\xa7\xe7\x8cm\x8d\xf6,t\xb7\xc5\xedVP.\xde\x16\x9bH\x03\x1f8\xe6\x1b.I\xa2\xf3\xf07R\xe2\xad:L\xe8vl\xa4o\xad\xdd\xfa((\xab=*\x1a\\&\x16\x9cNi\x9d\x94\xb9I\xc6\xed\xa8@\\%\xfb\xda:-q\xad\xcf\xdc\xba\"\xf6\xe6$\xa7\xf7\x88\xac\xd0\x01\xca\xa7O\xcb\xf1\xa2czu{\x02\xc3\x81C\x0b\xa4$\"~F\x98\x84\xaf)\xa1}\xd0\xa8oc\"\xd2\xa9b\x83\xe9X\x05\x08\xbd\xf2\xdbD-\xd5\x0b\x06\x8fY\xe4 \xeb\xa6\xd6Y\xe8\xa0[\xec1\x8b\x10\xe0\xe8\xc0\x01\xda5\x0f\xbauO\xab\xe8\x03\xce|\x91\x92\x06@\xbbD;\xe2\xfa\x16h\xa5\xdf\x05Zi\x19G\xa9\x114Z\\\xfd\x01\xd6\x88\xc8\x00z\x98\xcd\x92\"\xed\x02Y\x8bT\xf1[\xa0\x96|\x17\xa8%R\xf4\xa9\xd4Q\xf5\xf9\xe2Z\x0bp\xae\xd6\xf1\xb8\x8e\xca\xf4Gg\x81O\xdb\xe4ju\x03\x7fmq\xb3\x98tO\x95.%\xfcy\xb7l\xc4p\x94\xa7v\xb2\xfe9.\xf7\xe8\xd1-s\xb9\xd1#\xc8\x08\x89\xfa\xda\xd1\xcb\x8a\x0e\xb5\xe2\x96\xe1P}\xce\x98\xfd\xe1\xfe\x81c[Y\x1aX\x1a\x9e\xff5\xefH)_k\xca\xdfX\xfe\xc1\xc2\xf1\xb2U\x14\xe6\xb6%J\xcaR\xd8\xd8\xde\x1f8\"a\xf99F\xca\xe8\x03$\xce=\x93\x9a\x05\x98m\x94~\xe1\xda-tr\x84\xc8d\x0d\xafx4FH\xe4\x87\x14s[\xb1\xbf$\x16\x1a\xd1$\xd5=7\x9fDIxi\xd2cK\x9f\xf9\xd5\x17>/\x87\xf2\xd6M\xf6{\x0c\x19\xb3H\xe0\xde\xcb\xb9\xe3\xb0\xa8b,\xb6\xcbi)c\x871\x14\xe2\xb6\xf64\xa9\xd6\xc4\x18\xec)\x89HN\xf0\xbd+\xbd\x92\xd7\x94c\x97\x93(3\x85\xe54\xb5hu\xf84h!\x87\x04\x14\xa7}&>Ja$a\x87\xdc\xfeZH\xa1sM\x94z:9\xf4\xc1\xa9\xc4A\xc0\xb8\xcb^\xa5\xd76\xeb\xa4\xbe\xf5\x9bo\xb4o\x10\x81\xef\xeckw\xdf\xde\xaeJ\xc53Q\xdb\x81Z<\xe3\xc5UYj\xc4\x9f\xab\x12\xbb\x80?W\xeb\x99\xf1\xe7*2X\xa1\xd0\x8ci\xb3\xce\"B\x0f\xc4z\x81\xa9T\xe0\xb5O\xc9\xe4\xbbz\x81\x05+\x10%\xb1\xbe\x82\x1b8\x81\xb4\xfeh\xd9I\xb47t7\xd0<\xc8\xe7Z\xb2\xf9\xe5\"\x8c\xa6)\x89\xc7\x86sx\xe9\xaf\xc6\x10zK\x7f\xd5$\x0b\x80 1\xcf\xfc`A\xcb\xf0\x9f\xfarAR\xc49-\x85?\xf4e\xf2\x045\x9f\xb4\x14\xff\xa9/\x97\xc4\xd1\xdd\x18f\x8dw\x1a\xca\xe5e\xb2\\%1\xa1M'^y\xd3,\xf7\xb1HI\xadl\xedA\xb3|m\x05\x8cA\x03\x1cy\x86\xc7\xa0\x81J\x98\xfd\xe4G\xe1\xb4,Rx\xf5'\x9aN\xa6\xc9\xea\x82\x99De\xa6.\xbd\x8c\xfc,\x1bC`z\xcf\xd7\xe4\x18\xa6\xa6\x12\xef\xc2\xafa<\x86e\xf3\xfd\xab\x0f\xef\xc6\xe07\x9f\x97J>\x8d\xf1\xe9\xd5U\xb6J\x89?\x1d\xc3M}q\xea)\x829>\xfdc\x90Nc\x93\x87L\x12\xf0\x94\xb2\x1e\xf6h\x7f\xbf\x12\x14V\xe2\xa5\x85\x9f}\xb8\x8d\x85\xc8P\x8b\x9cF\xfb\xaa\x9eO\xcf\xa1~!wc\xd8\xd0XA\xa6d\xa6\x7fqu\x95\x91\xc8\xfc\x0e)\x84\xb1\x9a\xbeX\xeb\x10\x9a\x19O\nI\x9cG\xbc\x94T\xbbJ'?\x8e\xfaU\xf3\x85\xdcI\xd5\x88_BU\xa1\xe1\x1cX2C\x03Y\xd2\xd4*\xd3\xeb\xcf\x7ff'\x96vE\xe6\x98^\x994_\xe0\x1ch\xb6\x16NA\xdc|\xbeJ\x93U6\x86B\x03\xff\xe46\xa6|PhZ\xd6P\x01\xa7\x8a\x0b#\xbd\x0f\xea\xc7\x88\x060:`\xa4\xcc\xd0\xfaw\x1d\x97\x06&\x0b\xf0\x15\xe8,\xc0\xd1\x9b\x96\x11\x04:\xde\x19\xd5S)\x84t\xf1\xe4,3\xcf\nm9R2s\\\x88\xc4\xc3\x19:\x98\xc0&\xa0\xd2\xcfqky\x06=\xb6\x84\x05\xe91.\x9f4\x8b1z\xb7^\x10\x9f!\x1d\x14\x96\x921\xe6\xb5\xb6Q([\xd3\xe6\x99\x87}f\x1f\x93OR5\xe3.\x05\xdfTg\x18\xb5\x05\xa3&d\x98\x0eh\xea\x80\xef\x05\xfc\x8c\x84Fl\x8f2\xe2\xc3\x14\xbd\x944\xcb\xb4T\xf2-J\xc3\x9e)\x85\x11S\xef\xdd\xc01L\x8f\xe0fs\xd3\x81\xc5\xe4\xa6n\xd8s\x83\x811\x9b\\\xee\xc0\xad\xf7\xa9\xee\x8f\xf8\xd0\x18 \n\xdf\x88\xb0?\xa3\xf0\xcat=\xa5\x9d\\\xa21\x87\\\xb2\xd9|\xb5.\x96N\xcd\x96\x8c\x02^\x9a\x81e\xc3\xe0\xfeA\xb77\x02\xba\xdag.\xac0\xa9&z4\x05E\x9a\xd2\x03\x10\xfc\x1aK\x13\xd4\xc9\xaa^Fp\xca&C\xb7\x9e\xd2 P\xbbWs\x8f\"\x0f\xae\xa4P\x9a\xa7G\xfa\xf3x\xfa\x89\xc5F\xf8w\xd2\xa9t\xa8\xc6\xe81\x86\"w\x19\x96\xa5\x7f\xf8>\xa0?\xf8:'\x1e\xc3*\xf4\x17b\x1eu\xfc\x12M\xd1\x13_\xf8\x0c\xb8\x94\xa8\xb4\x7f\x7f\xa8*n\" \xd4\xba\xd0-\xdc|\xb5\x00~8h\xce~\x0cj\xdd2\x16\x8d\x87_\x17\xd2\xf1kHg!\x90\x0e\xdb5\xe5\xf2\x90q\xd0T\xc5A\x0c\xdel\xe1\xe39.\xaf\xe9\x12mi\xde9\n\xb6\xf1\x0d\xd8\x86=\xb7e$F\xf9\xbb\xba~\x8c\xe2\xbd\x15\xf3\x81\x99\xd1?cqG\xcbj\xb0\xd3rM\xec\xb4t`\xd5\x07;-;\xb1\xd3\xbc\xc4NK\xc7\x85;\x86\x9d\xee\xe0\x18\x96GpG\xb1\xd3|rW\xc7Nw\x06\xecT\xeb\xd0\xbc\xd7\xfe\xe7{c\xea\xc2B \x81\x9b\xba\xfe\x9c.\xfe:u\xfch&\xb8\xa6Gc\x0bD\x90\x12\x0c\x8d\xc9\xad\xca\xa4i\xf0'\xe8&M%\xb1\xd3\x81\xe3\x9d\xdf-\xaf\x93HO\xe9\xa6\xebU7:\xd4\x9b\x0d\x0d\x0f\xbf\xcd\xd6m\x83C!\xa9\x0c\xd0q\xc1\x7f\x8b\xdd\xdb\xc8 \x81|\xaa\xaa\x19\x19\xd3\xbf\xdf\xb0#bt\xf5\xfe\xb0sdf\x94+E\x12\xe4f]p\n\x13r\x89\x96g\xfe\xb7\xc8\x131\x1e~cxJ\xf8\xbb~\x13\x11\x1aB\x972\x95\x1b\xa9\xechH\x13W`\xe0b\xd8lD\xe1\x11k\x7f\xc0j\xa4\x93I\xfbF\xe8\xddV\x02\xa7`m\x0d,J_u\x8c\xbf\xc6p\xe9$E\x9cUb\xe7+F\x1c\xea9C\xc4\xcb\x8a\x15I\xaf\xb8yq\xc5lU\xd6c\xacR;\x97eqM\xec\x15$\xb1\xd0E\x9a\xc4\x17\x98\x98_\xcb @\x87]\x8a\xb8\x84\x89\x82\x9e\x0b\x03\xd6\x8dY8/D=\x1a\x9f\x81\xda\x93\x87\xbaU\xf1\xa3\xc0\xd6\\\x0e\xaa\xd7\xb9\xc2\x88\xc45(\xd7\xe0Z\x9f\x80\x98\xdc\xa2\xe9r-.w f\xf8\xfe\xb6\x07\xfb\x9d\x9b\\\xb7kj\xa6\xceJ\x98\xd8\x97~\x1c'9\xd0\x86\x11\xc5%)\x14q\x19sH\xbb[\xbe\xcb\xa0\x1a^\x1f\xcaxyt@\xfb\xa0\x81@P\x10\x91b\x04_\xba_S\xb9\"\xe6\xfb\xdb\\\xdd\x9ch\x19\xab\x99c\xe5\xfe\xf02\x9d\xd0\xec\xe3\xc9\xf4\x87x.\x89\x93\xa8>\x04\xdd\x0c\xd9\x03\x17B1 g\xed\xc3\xa9\xe7\x8c\xb9\x06\xa0\xb5\x18\x0d\xab;M\xf2\x99\x16f\xab\x18\xff\xf7\xc3\x8cr\xa8\x98X\xe6\xfe\xbeK\xceT\xc6\xd6\xe6Lm\xccX*\xd2dj\x1b\x10|\x048\xca\xc7\xa5\x9c'\xed\x92\xf30S\xef\xfb{a\x06\xde\xc4\x0b \xefg/\xcc\xde'\xf9\x82EcH\xdd\xda\x0b\x06\x8a>\x04K7=W\xf5An\x83\x0b\x93\xfb4\xa1\xee\x04NBpjbB\xc9\x079\xd5o\xad\x99\x94\xac\x88\xdfo\xdd0\xcf\x1e\xf5\xe8\xc6\xa5\x133\xda;f^\xd61lb\xd4L\xccP\x85\xc5\\\xefL\xcf\xc1\xe6F\xf4[e\x81\x1a\xcby1\x18/\x8c\x83\xa8\x98\x12\xa1\x95\xe9p\x1fG\xef\xe0\xb2\xad\xda\xeb\x07\xae\xc9\xed[S\xb3\\\x9bEM\xee\xe5\xfe\x9c\x9b[\xd3_O\x9eP\x1e>\xa4\x8b\x88\x89\x92\xe9O<\x13M!a\x1f\xd0\xaeJkJ\x86ofa\x94\x93\xd4n]\x91PAn\x8b\xc7J.\xb1v\xaeV*\xad\x93\xe6\x84i\xa2\x16r\xf3\x15\x9c\x0e\x14:\x88\xdf\xf7\xf7hK\xc6\xde/WQ\x18\x84,\x1dIy#\x97 _\xa5\x12\xe5\x8d\xae\x8e\x9e3\x85\xb2A/J\xfc\xe9\xbfs [Y\xe0G~jq1\xbex%\xd3Y\x89m]\xa0s&\xbac\xc6I\xbc\xc5\xbeA\x84LO\xbc|A\xa0\xec\x7f\x14f\x18\x07\xdf\x87,X\x90\xa5\xef\xc1\x1b\xf1*%Y\x12\xdd\xd0\x13!\x99AV\x04\x0b\xe6\xed\xdf\x08l\xe3Y\xcdIe\x86=\xc9r\x15Fd\xfa\xa6\x82\x9c\xcf]\x08,\xd1\x01\xcb\x85\xc9\xa5\xfa\xc1\xd9\xd7\xe6\x07\x02\x9e\xda\x0f(m\xf9\xce_)\x14v\x03\x9etK\xf2\x1d\xa4\xd5X\xd0\x8b\x01k\xac\x95\xdf\xe3{\xf2kA\xe2\x80\x98K,\xfd\xd5\ns\x1f\x98\n\xcc\xfc(\xba\xf6\x83/c9h\x97\xb8\x1e\x94H\xf3\xd0q\xea\x8b+\x9e\xb0\xadx9\xc1m\x8af\x16\x9eh\xa9z\xa6\xf1\x15m6GQ9a\xa8\\\xe7\xa7|\x84q\xed\xf3#\x16,v\xe8H2'R!!U\xae\x08Fj\xd2\xd6\xae\x16\xc3\x9aP\xc9Jz\x15\xde\xab\xb3\xd7\xcf?\xbf\xbd\x10\xfa\x95R\xc1\xdf\xb6\"\xc4j\xa8w3\xbb\x0d1\xb2\x9c:h\x1d\xdc\x03?#0\x1ck\xe7\x03\x83'\x8a~)p\x9c\x0c\x0c1\x02\x0c\xf1\x96\xb1\x9d\x91\xb9\x1d\xb9b\xb5)\xd5G\\\\\x86\xa6\x04\xd3\xa2\xfd\xa6\x86d~N\x93x\x0e\xcc3\x141\x88h\x12\xd7\xcf9\xc3&|\x16J\xe9D\x9b\xba!\xe4y.SA\x0e\xa2\x83u^{\x92;.l\x90^\xf1_\xc49+[K\x17\n\xa2R\xf0\xe6\xf9\x8a\x04\xe1,$\xd3\x12-\"C\xcfQc\x06v\x92RD\x19\xc6\xf3\x88\xf0\x11r_]\x07\x83\xc6\xfba,pn\xed\xad\xa72\xb5k\x84\xb1\xd1\x0d#\\w\x18\x7f{\xfe\xee-\xc7\xde\xb51P\xbci\x1a\x81\xf4\xae\xd1\x7f\xb1\x8f\xc9-\x14\xb6\xe6\xdcb\xc7\xa7V\xaa#\xf0\xf8X\xf5\x05\xac \x93\xbb\xad1\xd7$\xf6\x86\xc3\x9a\x19\xdf\xa1\x96\x96K\xda\xe4\x956\x81'\xf4\xa5\x1aXLn+\xd4\x1e+\xef>\x9f_\\}>?\xbb\xfa\xf8\xe9\xc3\xc7\xb3O\x17\x7f\x1b\xeb\x92\xa1\xfe\xf5\xf9\xf9\xd5\x8b\x0f\x1f\xde\x9e=\x7f\x7f\xf5\xd3\xf3\xb7\x9f\xcf\xc6\xb0\xab/\xf5\xfe\xf3\xbb\xb3Oo^\x8aR\x87\xfaR\x1f?\x9c\xbfA\xd6@)>2\xd4\xfa\xe1\xa7\xb3Oo?<\x7fu\xf6J\xed\xc6\xce\xa8\xf9E\x18\xd3\x85\xf1\xea\xc3;\xc1\x10\xbfD\x19[\x97\xf3\x12H\xb2\xd1P\x7f:\x02'v\x89\xc7\xab\x0e z8\x98NS\xe0\xe2h\xe2\xbd\xfa\xf0\xeey\x9e\xa7\xe1u\x91\x93\xf7\xfe\x92d+?\xe8\xfe6\xd3\x7f\xdb\xf5Y$>\x13\x00\xe8\xf5U \xbez\xc7\xe3\x9d\xbc#\xf9\"\x99\xf2\xef\xf4\x98\xba\x94W\xccP^\xe1\x85\xd9\xcb\"\xcb\x93e\xd9_J\x18\x16\xdeU\xe3\xb9\xb0\x97\xe4^U\x9a/\x9d\x16\xba\x1f\xf0`]\x95s\xa0\xea\xd7fL\x12f[\xbb\x87\x96\x0b\xb3\x16co\xdaw\xa4\xcd\xbc&Y\x98\x877\xc4X\xa7\x1e\xcb\xf5\xab\xfc\xc3\x0dI)\x07E\xa6\xc6\xe1\x9b\x90b\x93\xc9\x95/\xc3F\x06~\xf2/<\x05\xe2\xb0 \xf8L\x1e\xa5x\xa6\xefd\x19*(\xb5\xad\xbd\x01\xee?\x174[\xb4ms\x03\xdf\x9a7\xe8\x9c>\xeb\x08[\xb5\xf0j{\x02N\x14sA\xf9\xd2\xbbi\x00:\x96k\xb1\x88\xad\xd4\x8e;\x0es|\xcd(\xaf\x17\x19\xbf\x92w\x1b\x9c@\xc4\xca\x07\xc6\xf2\xf5\xcd\x06'\x10\xb0/dD7\x99]6lv\xc4\xa5\xe1\xd7jO4\xbeq\xd6\xf8\xf9\xd6\x7f\\\xf9[\xbf\xfd\xf2K1\x18\xbc\x1cl\xe1\xdfW\xfb\xec\xcf!\xbb}\xcdn_\xb3\xdb\xd1\xeb\xd7\xf4\xcf\xce\x01+\xbcs\xf0\x8a\xfdyMo\x87\xaf\xf1\xedh0x\xb9\xc5\xfe\xbe\xc2?\xac\xf0hx\x88o_\x0e\xd8\xed\xeb3z\xbb3\x18\x0c\xe9\xed\xab\x03\xfc\xf6\xf5S\xf6\xf6\xf5\xab\x97x\xfb\xea5\xbb}\xfd\xfa\x95&|Is\x05\xbdyu\xf5\xfc\xe2\xe2\xd3\x9b\x17\x9f/\xce\xae\xde?\x7fw6\x06k\xea\xe7\xfeVJ\xfc \x0f\xa7Vs\xfb}\xfa\xf0\xe1\xa2\xed\xa34Ir\xcdg\xf5/\xae\xce/\x9e\x7f\xba\xb8z\xf9\xd7\xe7\x9f\xb4F\x85Ji^\x0e6\xc1\xfa\xe5\x97-o\xb0\xf5\x14\x81\xfc\xe2\x00\xa19\xe0\xc0\xddg\xd0\xdcy\xcd\xa0\xb9;\xd0t\xa3Z\x1cz\xae\x1e]\x0d\xb3,d\x8e\xd2\xf1\xd4O\xa7\x0c\xff\xeb\x91y\xcbQ=n\xa4\x16\x00\xb4DV\xca\xf7\xa1\xb3\xea\xfa \xa6\xfai'\x13jj!3\xe2\xc00\xf5\x03\xb7\xbd\xb2I~\xe9\xc8\nr\x8d\xd6\x15\x8c\xa8B|3ln7\x13)\x8a\xe6\xcdFS\xcf\xef\xceO\x1c\x1c\xee\xd4\x18\x8a\x1df\xa3\xfc\xd4\xc0W4x\n\x8a\xef\xfc`\xf1\x89\xcc2.\xe1Bi\xc7\x157\x9d\xe264:a\x87\x9e\xcfX&E\x9cK\xf6\xf1\xea\xd8P\x98\x1f\xa2\xb5\x94^.V eZ\xaf\xc6\xae\x7fi\x94\xe7\x10\xb5\xdf\x92\xce\xa7\xf9\xd2K\xc9\x8cI\x91\xe7$\xffD7\xff;\xda\xea'\xe2O\xefl\xc7#\xf1\xaf\x05)\x08z\x04R\xcc\xdc\x86_\xe7$\xffk\x92\xe5\xef\x93i\xe7\x8e(\xbb*}c\xb7:6\x17q+P\xb5\x8dxSRN+3\xb1S&\x94>S+n\x08\xb0\xeb\xfd\xe0\xf1\xf3Z'74M+\xe3\x8c\x94^4'\x12\x95:(T\xc6\xc4\x13!\x97/_\x05I\x9c\x93\xafF\xdfdM\n\x10\x90\xd6S\xeae\x8b\xa4\x88\xa6\x9fWS?'\x08\x14_\x9ft\x18\xf0\xacA-B\x1d\x82\xbe\xc3\xec1\xeb \xb0\xc5\xa8]\xf6\xd5\xe3\x16`\xdcc\x016\x11P\xdbT\xadH:K\xd2%\x1b\xef\x9b\xd9{\x12\x90,\xf3\xd3\xbb~\xfe\xcb\xc4\xbb*\xf0\xcb\x17~\x1e,\x98\x86\x8f'\x8a\xc51\x9ajo\xac\x9f\nk\xe81`\xf8=0\xe0\xc8\x10\xedo\xb8\xfbT\xab?\x1b\x19\xfc6w\xf6\xd4\xf2\x183\xad2\x08\x91\"YN\x93\xa0\x10\xd3\xab J'^{\xe2\xc7\xbb\x84)q\xf4\xb5\xc5\xfeM8\xc7h\x9erf\xe5\x93\xe6{\xaf\xc8H\xfa|\xce\x1b\xde\xfe\xe5\xfal:'\xbfl\xff2\xdd\xf6r\x92\xe5\xb6\xa6\xa0\xf6\x1c\xd0\xf8x\xd0\x8d\xd7\xf0\xa9\x00\xd9\x82\xcc\x8b\x93\xa9\xc1:*\xe69V\x995\xa7~W\x8b8\xedz\x8e\xa5\x16?\x9e\xc7\xb1\x8cK:\x00\xc3Y\xb2,h\x93\xf4\xd2\xc5\x1d\xa5\xd9\xbch\xc5Z\xed\xb6E\xbe\x8c0\x8a\x1c\xda\x8e\xd1;\x07\xc6\xd2{\x8aP(\x1c}V\x00\xf1\x8bi\xfd\xd6\xd6]\x84Q)\xbbv\xd2p\xc8=\x16(\xdc\xf0?\x94db\x02\\\xdd\x0b:\xf7\x95\xd9B\xed=\xa5\xe1\xea2\x0bf\xeb\xc1\x03\xeb\x89\x92\x82a\xf9\xfc\xe9\x0d\xc6\x83\xd2C\xe1\x1c+\x10\x85\x84\xd2\x94A\x8e\xb7\xaf>\xbc\x93\x7f\xb3\xca\xc5\xddE\xf2\x85\xc4\xec\xc6\xcf\xfd\x8b\xd4\x8f\xb3\x19I\xdf\xe4d\x89\x0f_\x87\xbcQ\xba\x9d\x9fG\xd1\xcb$\x8a\x18\xc7\x8bO\x94\xdb\xd7I\xba\x14\x0e\xca\xf4\x9e\x85t\x16O\xde\x91i\xe8ce\xef\xc2%\x1e\x80\xcc\x8d\x9b\x9e\x03S\x8a\xce\xde\xf9+\x97\xfe\xc52\x1f\xfd\x90\x8e\xe1\xd7\x82d\xac\xeb\x1f\xa3b\x1e\xc6\xfc\x0f\xfb\xf2\xfc\xa7\xbf\xbc\xc5\xb5\x8e\x05\xce\x7f\xfa\x0b#\\\xc5\xddG?_\x9c\x93yy\x9b\x84q.n$(\x9c\xff\xf4\x176\xee$e\x83f\xd15^\x14\xb3\x99\xa8\x8b\x82\xfb|A\x08\xfb\x9c\xa2\xa1\x8b\xd4\x0f\xbe\xbc\xe4\x00/\x1f\xb0\xbb\xa4\x08\xb0G\x96\x88\xe7\xe1\xd2y\xcc\x18\x99\x93\xa1(Dl\xd1L\x1f\xb4\x93\xee\xccb\x92iv&\xddK)\xdd\x89\x8d73\xe0\xfb-\xa8,G\x15t\x81\xce\x1b3\xee\x8a\x94`\xc8Q\x17\"\xba\x10'\xd1%\xdd\xee\x1e\xc2\xb5c\xcd\xab8\x91\xa1\xa62\xbcI\x17\x024\x1c\xe9\xb1\x08T\xe2eQ\x18\x10\xfb\xd0\x85\xada\x97!\xafi\xbb\x9b[\xeb\xce3\xd5\x99c\xea{\x04\xc7\xeem\xd8o$xj\xee \xf6\x10\x9e\xd0s\xbf\xb9\\\xea\xee\x07\xf6\xc8PNrd\xb0w\x0de\xb8\xbb\x84\xa2;_\x0fAJ\xb8pG\xe5\xbd8\x0f\xb7o\x8a\xd8\xde;xp\xe5\xe5\xe3B\xd2\xb5\x84\x8c\x1d\xdc\x1d8\xdeL\xd7\xc3=},\xe6&\xee\xee\xda z&\x82E\x99M\xd0\x1e%\xe6&\xc6D\xf6\xc9\x08\xb9\xf6\x93\xa0l\xac\xb92T\x97\x93\xbe3\xb9&\xa4\xba\x98\xf4\xdd\xbd=\xc7\xde\x18\xd4D\x95\xa3\x9d\x03\x87\xc7\xedq\xc1jF\xcf\xd1\x9bG^QR\x8eG\xfb!\xc2\xfe\xee\xaa\x9e\x82\xe3\xa1%\x06\x8f\xb0\xb6\x12\xd1\xc2\xae4>\xfee\xb8\xba\xabPooRK\xfe}\xaa\xa5\xa8\x10\xa8<]L\xe3\xf54\x895\xe1\x18\x90\xdbB\xff\xdb\x9c\xf1Wbl\x9b'\xa5\xaf\x84n\x8e\xcd\xaeK\xbc\x9d\xa1qn\x1d\xed\xe4\xfe\x13!\xf5\x162n#\xb6\x87\x83\xa1c\x1b\xa7\x9a\xb7{@\x11\xbb>\xae\xef\xef\x0f.X~#\x8c/\xf4\n\xe5+7\xd1x\xa9\x88\xe7\x1c\xcf_\x07\xe8\xfd\xe0\xda\x9aQ|c\xa3!Vn\xcf>\xadU\x8ftat#\x89\xddk6e\xb3(\xdd\x01\xc0\x02\xcb\x86\xf1#\x17\x1c\x81g0@\x1e#ET\xf1t08\x18>}:\xda\xdb=\xd8\x1d<}:\xa4,\xc7\x9a4\xfd\xb7d\xb5lM\xa1\x07[0d\xe6\xc0\xd6\xbb0fVs(\x12\x06B\xc9\x0f\xf8\x17\x0cyFi\x90#\xb8 \xb30\x87E\x9e\xaf\xc6\xdb\xdb3? \xd7I\xf2\xc5\x9b\x87\xf9\xa2\xb8\xf6\xc2d\x1b\x15\x99\xdb\xd3$\xc8\xb6\xf1\xe3\xad) \x92)ar\x9f\xd30\xbe\xf1\xd3\xd0\x8f\xf3\x13\xac\xb2\x96:\xa6L\x1bHQ\x8e\xf5\xc4O\xe7\xd9\xe4\x92\x95\x8bi\x15\x9f?\xbd\xa9d\xdfRb\x19\xd8\x84\xa1\xeao\xc4\xea\xc0Qc\xae\xb6\"\x8a`I\xb2\xcc\x9f\x13t\xb4\xcb\x08>\x8f\x93xk)F<%7@\xe2\x9b0Mb\x14\xaf\xd2\x8f\xf1C\x1cG\x06~<\x05\x7f:\x0d)\x80\xfd\x08\x16$Z\xcd\x8a\x08n\xfd4\x0e\xe3y\xe6)n27<,d\x95oHM \xc0\xa8\xbc\x04\x85d\x14\xf6o\x04p\xe0\xa70\x89\x90\x9d\xc2\x8c\xb8\xb3\xd4_\x92\xec\"\xf9\x98\xac\xe0\x84\xceT\xf2\xc8\x8d\xd1\x87\xbe\xe3IC)]CJ\xb7\xeb\x1c\xc9\xd3\xf5Vk\x8bI\xa7x\x03\xedj\xaa\x86\xf7\x998\x03\x1a\x91\x04\xa1\x81\xf4r\xe1\x1d\xd5\xba+\xa4\xc6j.Up\xdat\xb1\x1aW)L\xf0\xd9%\x93\x94\xc6\xcd\xc8\xc0\xd887T\xe9\xdb\xbcu\xcd\xca\x9b\x932\xf2z\xdf\xa3\xdc\xb5_\xa5\x1a\xaf7\xa5\xa6\x0fi\x99\x8ee\xcdJMu2}M\xbf\xaa4\xda\x0bm\xadl\xd6{\xd7\xaaqU\xd7\xd6\x8aa\x0f\xfa\xd7\x8a\xc5;k]\x1b\x9e\xb2\xab\xa2\xae\xc2Od~\xf6u\xd5\xb7\xb6r\x8d\xb2\xcf:\x16i\x0f\xa7F\xb9\xee\xfe\x8e\x8dR\x1b\xaf\x14\x0f\x84^\xbd\xa7\x1fu\xf4\x1dq\xea\xda\x15\xe3WR\xcd\x0c\xcfIf\xe5X@\xd7\x9e0\xea\xe8\xdd\xa4(\xd5\xb9d>\xa6\xe1\x12\x0d\xfc\xfaV]\xedk\xd4\xeb\xe9P\x07\xbe\xd0l/|n\x88\xe5\xa0[\xe2P\xcf\xc4\xa7\xed?\x93O1\x970~S\x16{p\xca\x185\xb1\xbd\xb7\xebx\xec\xbd\x9e\n]\xdf\xfdWs\x8e\xe1\x04J\xc1K9'#\x0e\xd9\xbf=\x7f\xf7\xf6\xeck@V\xfcx\xc5\x97)\xf13\x9cY\xc2\x1f,\xfd\xf4\x0b\x0b\xfc\xc0n9\xe9pR%v\xa1\xe5)\xcc\xec\"\xfe\x12'\xb71\xb0g\x8e\xe5\xc0&/\x85\x95\x9c\x82\xc52\xfe\x89'\xe5)f\xe3\x99b9n\xd9\xe5U^\xa4\xe4<\xf7\x83/\x17\xa9\x8fQ\xc6\x0codk\x19)\xee\x01\xad\x10\x9fe\xb4$\x86\x0d\x14\xc4\x87\xc3\x9f\xd1.K\xe9\xcd\xca_iK|\x0b\xd6 9\xedOj\x8c\xbb\x90\xd6_\x8a\xb1\xb6\xae\xec\x1b9\x1b\x01\xce\xd3&Xc\xd0G\x0c\xc9)e\xd79 .lT\xc1\xfcq\x1e0\xe1\x07\xa3\nM\xd3\xe1(\xa1\xb4\xd6\x8e\x83\xd3%\x8884E\x91\xa0\xd3\x94*>$\xa5\xff\xc8$\xb6wv\x07\x8e\"h\x15\xbe\x83\xf8\xfe`o\x88\x96W\x07{#\xb5\\\xe5j\x82\xe5vx\xb9]\xfew\x8f\xff\xddw$w\xf1G\xecN\xf1T\xe6\xaat\xe9:b{\xd4Hu\x11r\x13\x08\xf5\xb90\x8dP\xa5\\E\x15\x103\xf5\xe6L\x14NX\x0c\xaf&\x92\xc8L\xd2-\xd1\xd3\xb61\xaaeso\x1af+\xca\xc82O\x0fo\xb5\xf032\xfdD\xe6a\x963\x05\x08Z\xeeNbs\x14\x89\xc2&\x8d\xa0\xec\x0f\xf4Y\xdc\xb4\nJ\x99\xaa\xdd\xbb\x12\xcd\x8a\xa1\xa2\x01\x8b\xf6\x05\x8b\x1c/\xbdy\xc3\xcf\xb6\xc6'\xe5\x0b\x17\xeaq\x86\x9a@\xd4\x04\xd4\x14\xe1\xfaz\xc1\x03\xa5\xfc^\x9e\xfa7$\xcd\xc8\xc5m\xf2\x91\x96\xb3\x89w\x95\xfb\xe9\x9c\xe4\xb4+.dJN\x9bf?\x02\xbd\x18}\xad\xbe\x98\xe6\x97\xd9\x99\xc8\x1dj\x14\x03!\x9e\xa3|=\xa6\xd6@\x05\xb8\x00$\xd3M7#X\xd2K3\xfaX\x1d1@]\xe6\xd1\x1c\xff\xcc\xb4H\xd1\xc8\x85\x99s)PH\x95\xf1\xb7-\xef\xce\x8f\xf5 \xa1\xfb\x9a\xafj\xcd\xc0\x1f\xb3\x84\x93o[\xc2\xd0 \xc8U\xdf\x05\xadB\x80\x16\x9a\xa9\x0bw\xa0I\xc6\x04\x1c\xae\xd3\x86\xce\xd7\x0f\x82bYD~^.\x85W\xbcM\x92u\x19pb\xf0\x83\xa8\xd5R\xb2\xad\xfa\xf3/\xe1\xea\x02;\xde\xab!U\x15nj\xe8U\x98\x92 _s\x14\xab\x9e\x95\x9f\xc59I\xdf\x12\xff\xc6\x00\xa6\xd2\xb4W\xd7R\xb5\xed\xaajlf\xcd;\xe3 ]L\xabF\x7fRO\xf1\xe97\x1f\x8d\x86\x93Q\x1fy\xaeyb\xf2\x88\xceC\xdd\xc9\xa8;I3\xc3I\x1aUI\xa6~Ws0a\xcc\xf9\x86\xc9\xd1\xacK\x8c\x04b+\xd9\xa1G\xbe\x92\xa0\xc8\xa5y{\x13\x7fH\xa7\x84\xd3\xedh\xfb\x95}$i\x86\x1b?\xb7\x193&\x13\x94\"\x0f\x91\xdd\xd8\xdd\xf5^\xf5f\x8f\x11\x81n\x0cZ+\xeb\xcd\xb9\xb3\xca\x86\xad\x95-\xfaVfy(\xe9\xf4\xae\xd2$A\x93\xaa7\xaf\xea\xf5\xd6\x17\xd2M\x03\xadH\x1e\x00\xcdF\xd8\xcb\xb3\x1b\x12\xe7\xccl\x01\xe7a\x0c\x89\xa7\x7f\xd3D\xf4\x8dr\xd9\x0b\xee\xde\xa7\xa9\x83\xbfk\x9d\xb2\xa2\xa4\xdb\xfa\x19\x06ku\xe51S@ZOw-\xfcR<\xd6\x1cD7\xdce`\xd1H\xf4I/;\x9a\xe4,\xfbh\xc4\"\x81\xfd\xfe\xe08\x93\x10#H\xe8\xeb\xc2\x94_\x8d\xf3\x81\xd9\xebd\xda0b>\x1a|z\xd3p\xfa\xb1\x1a\xbc\xeeY \x866\x00J\x84o\x0f\xa3|\xa1I\x8b\xb4=\xa3\xe4C\x9f9\x00)6\x84v1\x8b\x0b\x835XI\xfc2\n\x83/\x96>\x90B\xa3\xdcK\xc6\xe6\xf6(\xfe*)\xae#\xd2\xb7r\xa9t\xff&\xde%EF^%\xb7\xf1:e\xd7\xac\xfe]r\xb3V\xd95\xab\xff\xbc\xea_\xb2\xbbj\x90\xf4t\xf6\x06\x92\x8a\xfeu\xc4\x12\xbcbT\xc0\xdc\x05\xeb\xba\xc8s\xb6Cy2H+\x8cWE.?\xc8\xd0\x14K~\x92\x93\xaf\xb9\x9f\x12\x9f?sZ\xbc\xa8[#s\x88K\xf4\xb2\xe98\x05\xa0\xea \xc4\x85\x87s\xe3\xcd\x03\xb3\xceV]'DDJ\xf59\x8bY\xed\xc8b:=\xeeH\x8dx\xa8T\xf2SZ~\x92^\xb6a\x00\x96/\xe8\x11H`=\xb4\xc5\xf9\x8a\xdb0\x8a^\xd5Z4=g\xed\x9bG\xae\xc7AX\x1dO\x81\x94N(tz\x0c\xfey\x14\x95lC\x17\xd5)\x98<=\xe0\xeby\xbc\x15\x12[\\\x14O6\xfcpc\xb4\x82\x89&\xf1\xe5$\xbflC\x8ab\xfcf\xf0\xeb\xc4\x06\xe2B\xf8\xa4\x86i\xd0=\xb7\xb9\xa1<\x87)\xef`\x8f=\xf1\xa0J\x90\xf2\xd4\xe7\xc7{\x7f\xca\xbb\x84g\xe8\xf2\xa3r\xc5H\x83\x9a\xfd\xa1\xdff\x7f(.a\x87\xe8O2\x03|p^\xba@O \xda\xc8\xab\x8dF\x1e\x83\x19\xf2\xccv8D.7\xa4\\\x91~q4\x11K\xf3 \xdf\xdea+\xbc\x99\xebU\x13\xdefR;\xc0\xbe\x05\x1a.X!\xba\xd2$ Y\x86U\xffo\xdaHW\xf5b\xcf\x04M\xe8\x94\xfc\x01d\x88%\xe1\x14V0\x86\xa9\xe32\x80Q\xaa\x0c\x93\xb1\xfa^JP\xd5\xfd\xd2/\xe6\x8b\x9c\xe9\xc2[\xbbyu\xb5*\xd29\xe90\x81\x89*S\x0fc=\x12\x91\xf4\xc2\x8f\xbf\xf4\xcb\x8f\x1d\xd5\xeb,\xef\x0c,!\x0b\x01\xf0\x8d,a#\x85\x97` \xd5$A\xfa\xe8:7!\xb9\xed\x9aK(\x83\xe9\xd1\xd2U\xd0n\xbc\xd5\xaf~1\xfd\x89\x16e\x82\xf0\x99\xf4n\xc3x\x9a\xdc2\xcb\x81\xb2b\x8d\x87%H\x87P\xeea\xe2\x85W\xdcKM_\xb8<\x0eO!\x16!o\x7f\n\xc9-\xc6t\xe5\xfe'?\xb3\xc6\xc7\xc0z\xd1\xdc\x85MffJr?\x8c\xfa\x00\xac\x04\x12\xfb\x84\xb6\xdb\x199\xbb5B\xa6\x0b\x89\xda\x16oCRZIy@\x1bf\xa3\xf8\x85\xe7\x17s\n5\xcc\xa3e\xfb\xcc\x0bT^\x94\xfe\xb7/J\xb5\x93\xcb\xe4\xa6\x13_\x10\xcc\xa7\x1e\xe4o\xe2\x9c\xa4\xb1\x1f \x01\x1d\xdd&\xa8El\xdb\xae=\xc4R\xe5t\xe8\x9bi\xab}\xe1w\"\xd3\xbaF\x9e{\xff\xae\xdd\x90\x92\xbe\xde$#1C\xcah\xd7\xac\xc7?\xbdTS8\xa9\xd5\xf7\xdb?nH\x8d\xbcLVwi8_\xe4`\x07\x0e\x8c\x06\xc3}\xf872\x85\x9f\xfd\xdcT\xec\xefdz\xcb\xea\xabl\xc5\x02\xbaz\xd1E\xb0,\xff\xe3\xf6\xffQ}\xdc0\x1f(\xfa\xcd\x05u\xab\xd6:)\xa9D\xbd,\x91G3t\x02\xc8\x14\x16\xe1\xd9\xbe\xa5\x10\x17\xcdh\x95-\xe1,\xc4\x86\xafl\xeat\xf49plo\xcc\x9f\x0c\x92\x90\x85\xcbaR3Q\xa5$\x958\x81P1Y8\x81\xd0\x01\xc2\x9c\xfe\xda\xa8\xb32}L\xddb+u\xca\xaf\x13\xcf_\xad\xa2;\x9eP\xa9\x95\xbf,+\xaby\xc3\x86z\x82O\\\xe5D`F\xa0\xd4\x11\xc6\xc6\xa9\xc8\xcb\x93rG\x17\xde\x1f\xff\x9b\xe9G\xc2\xf2\xceZ\xd0\x1aKR\xc6c\xacy\x814\xeai0\x92\xd2\x85\x0eGk\xd7\xb4\xa2-x\xb2\x9e\x9e\xfa\x81C9\xc7\xd8\xb4(\xcb\xade\xf7\x95T\x9e\x0f\xf6zV\xc8\xdc.\xb8\x0f\x8a\xe3\x9e\x1b:\xd5\xf3?\x81A\xaf\xda]\x16*\xbc\xde\x9a\xe8i\xea\xc7\xd3diw\xfan\x18\xbak1\xf36\xdb\xf2\x82$\x0e\xfc\xdc\xae\x85\xc4\xc74\xc6cJeX\xce\x95\xe5\x82\xbd\xb9\x19\xc3&\xa4Ne\x0e\xb1\xb3\xff\xf8\xe43\x8dh\x06<\xb5e\xe39Sp\xec6\xe6\xcb\x07\x83\xd5|\x05\x8d\xdcc\xd9o\x87\x83\x81\x03\xa7\xfa\xd2\xd0-ZF\x94V\x06Y\x0d\xe9\xf2\xdd\x188.\xa46\xe5\x9d\x13\xa7\xdd\xd0\xdd\x14\x8c\\\xb6v\x7fh\xb4g\xcdInQ\\\xc1\xacW2q\xd7t\xfc\xb2\x9e\x07\x94aKR%\xdc\xb4\xc9\xf3\xcbBw\x0c^7\xe5\x0cE\xb2i\x0f_P\"\xf1\x11KTsP\x89\"\xeb\x9a\x17\xc7e\xce\x88F\\\x9f>=\xc1\x9d\x11\x9002l\x9aY\x94$iW\xef\x0c]\x0b\xb3\xf7\xfe{\xf4\x81\xd9\xc44\n\x03\xe6\x12\xc3v}\nc\x88\xd7O\xe8!\xe1\xa4Q\xaf\x87J\xe3>\xc3\x99\xa6\x91\x1b\xb4\xc4qn\xf4\xc1 \\R\xcaK\xddh\x98\xd6\x88\xcb\xd4\x93\x9d\xfe=\xd1\xb0n\x9aO\xea\x9d\xa91p\xf2\xa5\xf0\x8c\xba\x05\xd9\xe7\x0c&\xd5\xa9[\x92ofC\x08X\xe3\xd05\xef\x97\x7f\xa0\xe7\xaa\xd9Gr_\x9f\xc8b\xcf\xe4\xc3\xd9\x89\x0eR;Y?\xffZ\x97\x98gO/\xe69\xd0Iy\x98\x87Y\xf3\\\xc4A\xd5\x1f3\xbd\xff\xb0;\xc7\x9e\xd9\x14.cF<\x1ao[\x96\x94\xdeGk%\xcb\x82 \xb9\xd4\xb9\xf7\xa2\\\x7f`\xf0\x06\x8f\x1a\x11\xd8C\xb3\xe7\x1cH\x82']8`!^\x9ad\x97]\x84\xaaT\\\xe3%\xe72\xef<6\xa6f\x02\x0ds\xc21X\x1f,\xd8\x84\xcdMM\xf2oq\xddj\x93l@\xe3\xdc\xc1'\xad\x92\xf9\x99H\xeb\xa2\x8dfB\xaf\x7f?\xfb\xdb\x184\xf6#\xef\xcf\xce^\xe9\xd3\x17\xce\xfc,\xffw\xa2\x86\x873mg\xcc\x1a\x90\xc8A5\xb5n\x0b\xcc[]\x9f\xb6\xf2\x14\xacs\xca\xfdX\x1f\xd1X\x9f\x98e\x1d\x1b!NOk\x04a,\x97\xd5:\xf4\xdaj\x97{lT\xd4\x9bu\xd6R6P]_\xc4\xa5\x9fLq\x86N\xd2K/lNl\x13\xf2s\x92\xffL\xfc/\xeb@\xfeQ\x00\xd90\x84H\x84&<6\x86\x7f\x088zi\x05\x92\xf8uJ\xc8o\x9dBn\xa8*\x8f\xd0\x1e\xd4\xa3\x8b\x9b\xfe\xc2\xd8vO\x9e\x80\x00\x13\xfd\x1d\xd8u\xb6K\\:\x02\xb0\x8d6c\xfc\xee\xef\x0fe\xb8\xe77\xd9Y\x19yC\xfb\xf5Z\xb4\xc9\xef\xdf\"]\xd6W\xadw{\xcf]\xb0\xaa\xc8F\x0d\xf7w\x8e\xf2\xe4xG\x947\xf7^\xbe={\xfe\xe9\xea\xc5\xdfPs\x847\xf8\xeb\xfd\xd9\xcfW\xcf?_\xfc\xf5\xea\xecS\xf5\xe0\xfc\xe3\xd9K\xfa\xe0\xea\xc5\xf3\x8b\x97\x7fm<.\x1f\\\xfc\xf5\xd3\x87\x9f\xdfkJV/J\xc5\x05\xedCLn/(}\x1b\x9f\xa5\xed\x9eg|u4\x97\x0e\xc5A\xda\xa8\xcd+\xff.J\xfc\xe9\xb8%\x83$\xd4\x89y\xb5C\x18/\xf3[z\xa59@\xca^\x91\x8e^\x9c\xafH\xf0\x8d@\xc9\xbe\xbd\xf9o\x06\x81&\xbe^\xef>\xbf\xba\xa6;\xd7j2\x01\x0d\xc4]~\x9c\xadH\xa0i92\x1f\x02\x8dO\xb5\xad\x06\xbac\xa5\xfc\xd4/\xf2\x85\xa6\xd5Y\xedT\xc2\xd2\xb8\x80\x95b\xab\xaa\x18;\xc9\xaa\x92W\xd7w\xcc-\xb37_\xb6\xaf2X\\\xc6\xaeK\xdcY\xba?3\xa5\xc0\xe5\xda\xe1C\xdaH\xed\xfb{\xb4\x0fa6?\xc4\xa1\xef*\xeasMfs\x7f\xc7\xe1\xec\x96\x0b\x16s?5E\xaf\xeaE\x98H5\x0f\xf4\xee\x88\xfb\x0d\x19\x0bO\xf7?\xd03\xb0\xfb\x03\xbd\xf0e\x7f\xb0\xdb7\xdc\xb1\x10nli\x98\xa1\x98[U\x01W\xd3\x0c0\xe6\x16W\xe2\xd6\xd7\\\x92r?c\\@\xb6s\x04\x9b\x9b9\x1cCl\x0c\xb3\x99\x1a3\\3\xafa\x92\xdb)f\xcfK'\xc3\xcbv)\"\xbd2\xd9\x0b\x98\x9f@\xa9[{\xccm\x0fO \xa9?\x9f\x13\x96\xfc\xaa\xf6p\xe1\xa3\xe5J\xfda\x86%\x8b\xbauK\xb6\xde\xdc\x0f\x07{}$c*\xd8$\x93\xd0\x13)_x\xbc\xb5u\xd4\xe4C\xb8\x94~\x12_\xb2\xfc\x83\x92\x19\xb0\xf6\xac\xd8\x1a>z\x8f\x0c\xba\x93\xd1kFS\x0d\xe4\xeaj\xea\xe7\xfe\xd5\x95\xb6_\xa9\x9d;p\n\xf1D\xc3:\xe7\x94u\x16\x8f\xc7`-\xfcla\xd1\x134\xf6\x96\xfe\xea\xd1\xe31\xb8C\xed7\xe2\xf2\x89\xf0v\x06w\xa8]\xfd\xc6\xec\x11\n\xd7\x84\xeeD \x9dlA\xde\xa5!\x85\x86.:\xc6)\xf86*\x93\x12\x9b\xe0\xba tg\x89T\xddc\x94\xb8v\xc0M\xee\xdbZ\xbd'\xde-\xb9^\xf9\xc1\x97\x8fIt7\x0b\xa3\x88\xab\xe4\xa7d\x95\x92\xa0\x99\x17\x14=\xdeW~\xbe\xc8\xb8=I\x15z\x99\x7fY\xde\x9e\xb0\xf4\xb3z\x06\x8f\xb8`\xb1dM\xda\xd8f\xb5p\x91\x9a\xf0tk\xc5>#^\xd4x\xad0\xd6\xad\xfd\x0c\xffG\xfa\xa8\x11\xc64\xfa\xd8\x9c\xad\x13\x18>R_\xab\x9a&\xd4\x07@w\xdd\xf6\x7f\xda\xa7\xe3\xc1\xfdd\xb8\xf5\xf4\xf2\x97\xe9\x8f\xce\x9f\xb7\xbb\xb6\x88\x01\xa3$\x95\xb1\x8f>\xef\xfb\xc6\x86\xfd\xff\xb3\xf7\xef}q\xe3\xc8\xe20\xfe\xff\xbe\x8a\xc2\xe7\x9c\xac=\x18\x03I&\x97\xce\xb0,\x03\x9d\x1d\xce\x06\xc8\x0f\xc8\xcc\xce\xaf\xc3\x971\xb6\xba\xdb\x1b\xb7\xddk\xab\x9b\xb0\x9b<\xaf\xfd\xf9\xa8$\xd9\xb2,\xd9\x86\xb0{.\xcf\xd7\x7f@[\xd6]\xa5RU\xa9.T9\xd3\x18\n\xc9`\xc4*{\xf2\x04\\\xd5EI\xde\xf0A\xb2\xb1\xc7M\x87\x0b\x1e]\x80xX\x80\xc0\x1f`k\x97\xff\xfa\x0f\xf4e\xcfi}\x8c\xc5\xfb\x80\x99\xd2]L\xf5\xcd\x82\xed(\x17\xfa5\x8a\xe9\xa2\xf9z\x8b+\xd8\x18\xf1\n\x86\x03P\xba\x82*\xae}\xc8\xa1\x83\x90\xd2\xb1\xa1`\x1f^Y\xc8\x9dg\xfa\xfd\x99 w\x9e\xe9\x0e\xc6\x05V}\xa6\xd3\x99\xa5\x99*M\xc5%\x81^\x0d^\x18\xb9\x85\xd7&\xa4S7\xf7\xdats\xea&Zj\x8c\xa9\xa1\x96:\xc7\xd4\x95\x96\x8a\xe1\xdd\xea%q\xb9\xe1\x91\xe2m(\xfc9!\xb7W\x08vk\x97\xbb\xe3`\x7fQ\x97\x8c\xbb\xacqw=\xae\xd5\x947\xca\x9e\x84K\xb5X\xee\xf1\xd01j\x96\xf7E\xbeHJ\"\xb3%\x01\x0f*N\\^_\xd8\xc8|A\xa8Z_\x88YV\x8d,\xbf\x90\xf0\x93\xd6\xec\x8ao\x0fw=\x08ZK\xe3=_\xa62\n|c\\9r\xcf6\xfd\xbc\xd8\x9d\x8b\"\xf4\xc1>\xa4n\xc6\xdd\xdbh\xd7~\\\x81P*)\x18/\xf7\xf1Z>\xea\xbc\x967\xac\\\x9b\xa6\xc5z\xa6\xc3\xea\xc1\xe9\xb4T\xb1\x1cVE\xb5\xca\x96j\xe2a\xd5\xe0\xfa[\xaa\x98\x0f\xab\xa2\x82\x8fFn\xa3\x8a\x81\x8235\x05\xf2AV\x0d\n\x89\xfd\xecu/\x95e\xbf|\xce5\xaeG\x88nF`\xb4%\x13}W\xb4arq\xaa\xf49F\xb4v\xbf%T\xe1\xd8\xf2\xd5\xce\x90Au\xf2\x0d;\xdc\xb9>\x1e\x82\xe8[\x97x^\xcdJ\xc8x0l\xf3f\xf0\x03$o<\x94i\x91I\xee\xd2I\xb6\xb9y\xe5]\x19\x07\xcf\x8d\xf2\x90\xd7\x16\xf4\xa8\xa6_?h\x02\xccr\xfb\xfaZ\xb45\xb4\x0d\x1a\xacIQ&\xdc\xef\x92PE\x92IA\x92\xc5\xe4\xf3\xd9\xd4u\xd6;\x81\xe3u\xe7\xd8e9\x9e<\x11\x02:s\x8eW,\xcf~\xcf\x85cF>\xd3\xcb$\xd2n\xb1z\xf4u\xfaUX\x18V\xad\xd5X~\xefDa\x9a\xde\x84\xd1'\xa7\x92\x1eb\xf8Y\xb8!\x8aZ\xcb\xef-\xaa\xc5ka\x07\xc7c(\xb4\x94\xb3\x8de$\x8e4\x06F\x92\x0f\xa2\x85\x9d\x1e+_\x8b\xc2\x97|$*\x08\xe4LZ\x8d}\xa0G}K>\xed\x1a{ie\xf5\x11\x1aT\\]\xdb\xa2X&\x1f=\x10\x89\xfat\xe9w\xc9\xe7Q\xbbjU>\x93Ooo\x9f\xffk{k\xd5N\x93OW\x87\x07\xd9b#.D\x12SRS\xee\n\xb6\x90\xb3 \xb9\xb9B\xc8\xd0\x9e\xdc \x1e$\x93ps\xf3\xaaa\x8d\x10\xf6D\xe5\xfd\xe6YQ\xcd\x03zt\xfd\xbf\x0e\xbd\x81\xd68<\x14\xe3\xd5hL=wU\x07\x89\xdf{f\xcdx\xbb\xa6\xb5\x89\xcc/\x84\x97E\x93<2\xe9;\xb2\x92\x0c\x91\xe0$\xbb\xc2s(S\xfc\xc2u\xd9\xb5Y\x84\x10y\xf5]\xa9F\xfe\xca\x83i\x91/\x00\x9d\x83\x85i\x9aG\xca\xcf\x0fY\x19NI+\xe1\"\xcdo\xb5#\x81\x91\xa3n\xe2\x16\xdc\xa7\x0c\x0d*w\x94\xa1\xe7C\xe2\xe6<~b\xc8\xdb\xea\xa7G\xf0h0x\xce4\x1f\x0c\xceA\xe34\xc8rq\"\x88\n\xcc\x94\x8biRX\x0f\xf9\x1c\xdc\xb3\x8b\xbdg\x97\xd6\xc5\x8e\xeeI\xb0j\x9b{6I\xae\x0d\xc1\x14\x98\xc2\x05\xc2>\x14\xc14\x91Z\xc1\x8c\x86\x13\xaf\xcaoT\xb07\x8c],z\xaf\xf2\xe9?a\xec\xf5\xd2\x98\x16E\x01\xbe\xff\xc2\xce\x15\x01\xeb\x81`G{\x05\x87\x83h=u#e\xee\x8b\x97\xdf{\xae3\xcd\x8bq\x18\xcd\x9dA\xa8\xa8O\xe3\xf5\xd9\xaeY\x10\xf1\xcc\xe2\x06r\xf7\xb5.)\x10\x82\x88W\xaa\x18\xd7\x1dL\x8c#R\xc3\xf8$+T\xcfL\x8d3\xdb\xbaC\xfe\x01\x9e6\\\xe5n4\x84\xban)\x9c\xc3r\x97\xb1D\xb0/\x0c\xc2\xcb\xc6\xd1\xf5T\x04\x8c\x94\x8c\x0dFO[\xa1I\x13\xe7\x0b6\xd0n\x08\x93\xc3J\x7f\xd3\x89\x1c\x11\x93KI#2\x04\x97\x92v\xebx\x9e\xcf\x0d\xe1\x1b\xa3\x82Z\x91\xc6\xe0\xc6\xb0\x19\x96%kgP\xc5\x9fI\xfbs\x1d\xa2G\x8fK\x0c%\xdb\xfen\xee\x96\xac[ld\xb5x\xf6\xab\x17\xcc\x86\xf2\x83b\xa9|\xdd\xef@u\x0di^\x15\x945\xf1@\x06\xe6\xc5I\x1b\x8b\xf3LY\x1c\x86\xceh\xa5\xec\x03#H\xc4=\x88\xf8\x8e\x16\xe8\xcd\xef\x19\xb7qS\x1a\xe5\x1fqA\xd3\xba\x0f\xca\x17\x0d\x18$ \x945 \xac\x0c\x80P\xb6\x00\x01},\x98\x16\x1d\x05\xd3\x86%G\x9bd\xc3J7A\xc1\xa0\x01\xa4\x82B\xa9\xafv*V;\xf5D\x0c\xbd\xe8~(\xa9\xc6\x12\xadp\xb9\x02I<5_\x01={f2\x18\xcb\\\x8b\xb0rwW\x17nrt\xb7\xfbB\xc7M\xdc\xa7D[R\xa9\xaa\xbd\xb8TS\x82\xd5\x87\x88\xbe\x05\x97&\xb8\x8e}\x98\xfb\xb0\xf6a\xe1\xc3\x0c\xf6`\xa9\xaa\x89\xdbhU);n}dD\xa5Y\x94w\x87\xc2\x06\xde\x11\x06\xd9Oa\x04:\xbae\xcf\x0d\x92\xe0\xcd \xb6q\xc6\xb3\x1e\xe3\x8e\x84r8i\x99v\xb0\x1a\x13wf\xd4\x19E\xba3\xe6\xa6\x072F\xef\x1b\x88\xe1\x0fp\xf3\x06n67\xcd\xd46\xab\xd1]\x08G\xacwn\xe8\xce\x91T\xbd\xb9\xf2\xf0\x8em.\xee\xd8\xee\\L\xf3P\x06\x81\xb7_\x0b\x1e\x0b\xb2\xba\x9a]4!\x1a\xcd\x7f\xcd}\\\xc3\x1eTq'\xde\xc0\x066\xb9F\x8e\xc3\xf5\xbc \xce3b\xb8\x14\x06\xb5\xb3\xb9\xbb\xf6\xe1\xce\x879\xb7\xc5\xe3w\xc4\x03\xba\xf6\xd5\x0b~<\x1f\x1f\xfc\x99\xc7j\xa5\xc1\xf9\xf8\xf2\xc3\xf9)\xec\x89\xdd\xf6\x8d\xe7\xb3\xd5'u\x11\x1c\x8d\xdf\x1e|xw \xfd\xfe\xa9ww^\xf5\xf8\x9d~)\xfcL\xbf\x12\xff_\xdf\xdb\xdf\xb4BR<\xb7\xdcm\xec\xe8\xdb<1\\\xf1\xdc\xdf\x94\xd1rH\x85Fm\x8aD1pD\xee\xc5\x0d\xb1\x18\xddd\x83\x00\xad6a&\x1f\xec\x96\xd6+W\xa8\x869O_\xeaGCU\xcchc]}\xb5-\xdc\x0e\xa7}\xd9\x7f\xdep\x05\xa7\x07\x82\xc9\x8cxp\xf8\xda \xb39FQ\xde\xe2(\x10\xa6I\x16\xa6ig\xd7:;\x0eP\xb9&\xeb\xcf\x08r\xa4Q\x9a\x97b\x00\x9d\x05\x9aF\xe6\xdcu\xc5\xe0\n\x86\x0c\x0e\xba\xe6\xde\x93\xa8\x15{\x1a@\xba\xd2\xb0\xd9)\x81d-\xb0\x11s\x03a\xdbu\x8b|V\xed\xab\x05\x90\xd8\x81\xfb\x83GM?\xae\xff\x93U\xbcNh\xe7u*\xcffA$\xa0\xf8\x80\xbaa\xa7+\n\xae\x01\xd6\xa3T\xc5\x88,\xe7\xc9\xdfV9}\xd3\xe1\x8b\x83=7\x05 ?\xd9\xb3\xf0\xd6^\x0di-\\,\x1f\xa5\xb1\xd7C\x1a\xfb\xb7\xcfO_>Fk/:\x14\x0d\xa1j-}\x94i|\xd1\xa3b\xc8\xdb\x9a}k[\x83t\xd8\xa2<\xa3I\xb6j\xdf\x0c\x81\x95\xc5\xe3|0j\xf6\xbb l2\xfcX\xaen\xf8\xb5\xb5\xbb\xf2!\xf4\xe4e>\xe3@\x19+\xbc\xa9#:s\xe5b\xaf\xca\xfa\xf7Y\xc9v\xe50\xd2C\x0c<\x92\xbaH\x83\xea2\xfa\xa67\x851\x0b\x852\xb5\xd9@\xaf\xcd\\\x96\"\xbf\xce@ [\x92\x96FId\xb8\xb5\x9d\xa2p\xa1\x99\xb6l\xa3\xabvx>\xf6\xd0|yp\x93\x17t\x04N\xc8\xfe\x1b\xd0\x1f\xcb\x92%\x0b\x0c\xe11\xce\xe2\x11\x94\xae\x13\xca\x04\x92\xc5\\\xff\xb9\x99\xd4]\xcb1%<\"H\xb3\xaeD&\xeb5\xd6\x1f\xba\xeb\xbd\xa0!\x1b\x89Zg\xc9\x92\xf4\xfax\xa2\xb1\xae\x1f\xd3U1\x02\xe7&]\xe9&\xed\"\xc3a\x98\xbdO\xc3\xbb\x118Q\x98-\xd3\xf0\xae3\xdb\xe5\xbc\xc8W\xb3y\x9d\x9b\xf2\x04K\xa1y\x98\xcd\x08\xcb\x8c?,\x99RT\x01w\"\x8c e\xce\x92/\x96y\x99T\x0b\xe6Du\x82uu\x94Bb\x1e\xd5b\x1dS\xa6\x14\xfc\xb0\x8cQ&\xa0\x96\\a\x9a\xadhF\xc9gzB\xb2\x15\x16\xc2\xb7\x05\xc9V\xb6\xecK\x9c\xf8|i\x9b\xf5\x15v{e\xe9\xa9\x12\x1ek\x04N|\x93v\xcc\xe1Q\x11\xceX\xa6\"\x9c\xd93\xf0\xd9ey\xac\xd3\xca\xb3QRT\x19)\xb1\x80\x16f\xfd\x9cP\x99\xf3sb\x1bG\x11\xce0\xc0\xa3\xc8\x99\xb2\xdf\xf6\xacg\xeb\xaa\xf5|\xdd\xd5\xb8\\w\x96\xb3c\xc1\x8f\x8a|\x89\xb9\xf2\xa5%\xc3\x8ao\xd7\n\x9ec\x91\xd0\x05\xd7\xe3\xc5\x92&\x84\xcd'\xe1\xbf,\xd9\xb2\xa8\xb8[R\x9eQ\xfe\xb6e\x8dE\xb6\xd8\x9a\xa5(r67\x84\xfd7gy\x9bG\xabr\x04\xce\x94\xfd7g9\xce\x96\x08x<\x02\x981\xcb\x9f\xc9\xddQ~\x9b\x8d\xc0\xf9D\xee\xe2\xfc\xd6\x82\xca\xfeL\xee\xde\x17\xa4,y\xbe%\xfbi\xcd\xf8a\xc9s\xad,\xab\xf0\x0e-\x93\x19\x0f2\x92f\xca\x8cs\xe9\xca|Bh\x18\xab\x05\x16\"\xc1^H\xc2\x0c\xcb\xdf\x013U\xe0\xb8\x118\x0b\xf6\xdb>\x07U\x108\x99\x95qW\x1dY\xcfp\xee1gn\x9b~\x9e\x91\xef\x03\x9e\xd3\xba\x11D\x988\x99\xd16\xbb\xef\xc3\x121\xdd\x92\xfd\xb7eY\x95<\xcb\xaa\xb4e\xe1G\x89\xfd\x1ca\x19\x92l&\xf2$\x99\x05\x19\xbd/\xf2\x99\x80\x9b\xa5\xf8i\xcex\x1eRRm\xcb\"\xa4\xa4kKr \xdb\x08\x9c\x12\x7fX2\x11\xf2 \xb7Y\x89?\xec\x99\xf80J\xfe\xcb\x96-\xe5\x91=\xab.\x962\xa5\xb3\x9f4LS\xde\x07\xfe\xcb\x92mU. b\xec\x92\xff2g\xbb$\x9f\xa9\xdc\xd1T\xfe\xb6dM\x16\xa4:\xf3h\xb2 ]\x87\xdde\xbe\x8a\xe6\x87a\x16\x116\xa5\x94\xbdE\xf8\xd6\x91\x9d\x1f0\x98\xd7\xde_\xf6U\xec\x17\xcci\xdf/\x98U\xeeX\xcc\xdb\xb1e\xf1\xda/Q\xa9>Z\xa5\xd4d_3\xcdX\xd1\xcfy\xbaZ\xd4P\xb7\xc6\xd7\xae\xf5\xfc%L(\x87\x96[\xfe\xcb\x92mNp*o\xd9\x7f\xcd\x04\xb4Y`\xcex(\x1e\x85\xa6\n\xa2w|\xe4\xc0\xa6\x90\x18\xb9\x8d8\x04^P\xa6ID\xdc\xa7^\x93\x1dX\xa3j\xdb?\xbe\xa2VE\x93\x94>'2\xd2Z\x1d\xa4\xb0}\x990 p\xad\xa9\xa2~\xf99:\x8f\xf9)\xcc\xe2\x94\\\xe6\xcbwdMRw\x1d\xcc\x1b \x9e\x0f\xeb\xa0]=\xec\xf5{ll\x8e\xa2$t\x9ca@\xcc\xbe\xae\x19\xdb{\xf2\xc4\x98\x1e\xd4\xd5\xb6\\\x01j\xb3X\xb6\x9b7\xb5.5\x88\xdc\x0dc?\xbe|\x01\xe3\x87\xa0\xaa\xdf\xed\x0e1\x97b\x81\xcb|\x80S\xd1\x86\xa4\x98\xfa\xd0\xed;O>b\x00=j}\x95\x16\xde\\D\"\x99\xcc\xaf`\x0f\x96\x9b\x9b>D\x13\xf6&\x82\xfcV\xaf\xed\xe5\xe6\x11 `\x0f\x92V\xc0\xc6#\xc20%\xc9\xa2\x84\x94\x13r\xd50f\xcb\x87\x08\xb3P\xcb\x9d\xed\x1c\xabu[\xa1\xc7\x99\\\x89X2+\x1e\xa7\xd8\x91{\x9d\xcb\x86Wht/v\xbd\x07\xfbfp\xa2E\xb8\xfcqu\xc3\xd6\x11?(\xb5\xf8\x12e\x08\xb3\x9d\xd4\xe5G\xfd7\xd5\xa8\xd4 \xaa}@%Gg'H~\\\x88\xf3\x96W\xe4TGqc\x02\xe4\xa1\x0c\x1b;\x9d}\x16\x01o\x95\xf6\xaa\xea\xeb:\xee\xd9cC\x0d\xc6\xc2\xbf\x1c\x9f\x1e\x9d\xfdr\xfd\xd3\xc1\xe9\xd1\xbb\xb1\x1c\x0bR\xd4r(x\x86p\xbe\xbb\x1e\x9d\x9b\xba\x92\xde\x16\xa3s\xef1\xbc\xb7\xa2dUEf\xc1}\x96\xf2\xd8\x17_\n\x01 \xf3\x04\x90`uI\xe6\x08\x15\xd7\xc1\x93\xd5\xecO\x92\xf5\xf5\xa8U\x81\xec\x10\x96G\x1a\x97u\xca\x87\"\x10\x1f\x85N\n\xbeck\x98\xc0\xba\x1d\x9b\xf7\xd6\xb0\xb6W>\xc4\x93\xd5\x15\xef.n\xc7\xbdVHy\xe8;.\xf4Z\xfb\x03\xd5\x80b\x867\xa8\x9f-\x85bK7\x1aK\xfd8\xfdhB\xcf\x90\x8e\x88\xc86<4\xe9\xfbpF\xfe\xf2k\xcfA\x86\xb7\x17\xfa\xad\x1e+\xdd\xe9Kz-\x9c\x86\x9a\n\xba\x0e\xa2\x19\xfcm\xd2\xe3\x92\xf7$\xaa\xd3\x06UQ\xa0k|$+W\x85\xc0`?\x87\xe9\x8a\x9c\xe4YB\xf3\x02 \xba\xdeq*\xae.\x90T\xc0K\xdcu`\x984\x97\xed\x80\x0d\xcc\xb41\xed:|\xd8$\xac\x82\x82L\x0bR\xce\x95~\x95\x96\xfb@\xd3R/\xf8\x18\x94\xd2\xe8\xebzZ\x87\xecR\x1fm?To_-\x06\x08\x83<\x904\xc5\xd4Ur\xa5\xd1P\xb4\xe6\x94k\xb4^\x17\xab\x94\x94\xd7\xd7\x0d\xdd\xf0\xeb(\x8c\xe6\x04\x13-\xd7\x8b\x85Bp\\_O\x93,\xc6\xdcv\xaa\xa5\xad\xf7W5-\xc8\x04~\x8d\xb7\xb5\xfb\x06\xa8\xd5\xb1`\xb3\xe0ds3\xbbB\x85\x01\xae*s\x0fO\x83\xbe6\x82(_,\x93\x944\x07a\xbaB'\xa2\xfb\x06\x96\x83M\xa1\xe3hT\x0cQ\xc6)\xecI\xddn\xda\x8e\x04\x84\x13\x98\xfc~\xe3\xf5\x18\x07\xa8\x95\xa2\xae\xfe?\xd0\x07q\xaby[ OY\x92\xc7\xda\xe2\xae\xf3:\x86oD\xa9\xec\xc9\xd4)p\xd1!X\x86\x13!\x07G\xf9\xe0\xbe|\xd1Z\xe5#\xcd\x82if\x88M\xdd\x1a\xad\x0d\x1cB:\xd0\xf2\xa5\xa8a\x99o\x01\xa3\x11\x1a^\x12\xb1\xbe\xea>\xa3\x19Doq\xb5\x81B\xb5\x8c\x16V\xd1\xef\xc3\xa2$\x05\xb0\xe9C\xc3\xb2i\xbeB~\x1f6A7K\xd7\xf6Eq\x15L\xa5\xf1g\xebK\x98b$c\xfc\xff\xe5\xcb\x90]\xdf\x9c\x9d\x1b2\xcd\x0bb4\xf7k\xb9\xb1ZK\xcfx\xbd\x93\x94Hm\x9c\x8eI\xca\x1fs\x92\x82r\x89l|\xee\xc3\x8e\xc9\xf5!C+F\x13R\"\xd9K\x93C\xc4if4/\x0dS:\x82\xa4\x9e\xf2\xd6\xb6\xbb\xd7\n\x84SJ\x8a\xff=\x0b\xc0o~\xff\xa7-\x02\xc34\xf7@\x13F\x04\xa0M\x08\"/\xdb$\x18T[z'\xc10q8 \xc5cM\x02\xefA\x9f\xf2\x17\xcb\xd0\x0cJ\x8b\xae` \x8c\x00e\x06\xdc\xe3cs.\x86\x1dy\xf5Y\xd9\xd2\xa0\xe7\x87\xd9\xb0j4\xba\xa4\xda%fU!\xca\xce\x1e\xc3N8g]\x87E\x98\x853R\x8c \xc9\xd6a\x9a\xc4bg0\"\xc5\xb4'\xa0\x8d\xbd\xe9\x95:*=\x84\x13\xe6\xbe\xef:\xc5I\xd9Z(}\"\xdc\xeee\xf2\xfe\x17\xcc\xe5\xeec\xcc\xe5\x8cP\xde\xbb\x01jo\xc2\xcb\xc1\x9e\xdeB\x0d\xef\x15\xe1\xe9\xb6\xfa1!W\xda\x1e\xfd\xea\xdf\xdf\xf3{\xbf\xbb\x93\xce\xbd\xbb\xe6nC\nn1hq\xd6\x8e\x16\xc0\xc12/O\xc2\xcf\xed\xaf+\xf9\xb5\xfd\xa9\xc4OIy\x9c\xbd\x0boH\xda>x\x94\x8f^M\xc7\x9b\xf2\xa5,\xcf\x87l\x11\xd2hN\xe2\x8b(_\x92\xb2\x8e\x0dj\xfc\xbc\xb5\xe5\xb7*C>\x05{\x8bf\xf5x4)\x9d\x10\xa2\x14F\\\xed\xbe\xe1\xa3\x82\x1f 4z\x9ag\xfdz\xcd\x0fN7\x07\xa1\xca\xaf\xea\xecaq\xcf\xf3 \xdb\xdclCr\x15\x82\xfb\xf53\xe1\xdb\x11\xbd\x04\xb2\x9f[[V\xd2\x99\x0b{\xcc\xbc+\xea\x80\xb5\xbe\xb4u\xabP)\xb7$EP~J\x96\x97\xf9'\x92\xd9\xc3\xef\x80\xa2\x11\x0f\xfb\xdc\xc5\x19_l\xcb\xa4\xc3\x1e\xf7\x0cb\xfd\x9a\xc1\x16\x9ft\xbe\x06+}\xfeK\xff\xe1a\x15^\xdb\xa2`r)\xba\xeb\xfc\xdd\xf1\x8cq\xa5\\%\xb6r\xa7V\xaa\xd4w\xbd\xa8=B\x15\x02\x8f\"\xc1C]\xc7a\xc3\x17\x0d\xf6j\xa3\xa9\xf5\x0f\xd3\xb8m\xc8IL\xa1H\x9d\xc30\xfb=\x85(LSX\x10:\xcfc\xc830b\xd4\x96\xcb\x8d{\xcew+&\xa20S\xd8\xf5\x02)x\xd2no\xd0a\x87\x08\xe0\xe2\xe6M%\xf5^\x1f\xa4\x96\xc5H`\x1f\xb4\xaa\\\xf4:\xaf\xd8\xb1\xdd\x7f`}\x9d1 S\x14\xd5\x15jD8\xcdW\xb8\xc0\xb6y\x1b\xc1!\x8dd\xf2\x97\xedr\xedt\x19\xae\x9c\x87]+\x10\xe1\xc8\x18\xd3^\xdd\x9e\xa1\xe6\x8eJ\xd1?\xc7\xd9\xf4\xfeun\xfcs\xbak\x83\xe4<[\x93\x82\x82p\xfbKsX\x16\xc9\"\xa1\xc9\x9ap\xefON\xdf.\xd3\xd6\xb9\xe9\x0c\xec\xfb\x9d\xfb\xfa\xe5\xd0\xadpd\xd4w\xdd'\xb8\xf0\xf4\xf5B\xd7\x1f\x0dE\xfa\xae\xe7:\xc7\xe3\xeb\xf7\xe7g\x97gz\xd0\xd1U+jA\xe3s\xd9%\xc8\x02)\xcc\x12\x8e\x99\xdc\xdd\xef_x\xae\x93L\x8bpA\xf4\x86\xe4S\xe0\x05\xa0\xcdS+\x8f\xc2\x12\xa0I\x10#7\x97ix\x07{\xe0dyF\x1c\x1f\xa3R\xecx\x0d;\x17\xee\xa4\xb0,\"\x96\xed\xaf\xe1:\xe4VE#\xc7\xe7\xa4(\x0dP\xe3/\xa3\xbf$Y\x9c\xdfV\x08\xc3\x0b\xf2%\xc9\\\x1e*\xa0H(q\x9d\x1fx\xd1?T\xc2\xec\xb7{\x1c\xbf\xfe\xf0q[|r0?\x1a\xbc\xba\xc2\x95\x14 \xde\xbe\x81bk\xeb\x8d\x07\"<\x8b\x12oe\x92L\x8a+\xc3\x8d\xa4\x00\xcc\xd2\xd5\x0e\xc4\xaecE\xa0\x1eP\xa3\xb6Zi-#\x02\x16\xa2v\xe9.Kq\x8e\xcf\x8f\x17N\x91\xa0\x03t\x1f\x9a\x9f\x85\x93\xd3I\x88n,\xd1\xfe\x04=\x9fka\xd4\xa5\xe3h7\xfb\xff^D\xfa\x17O=\xd7\xf9D\xeeJs`\xdf\xdd\xdd\xfe83\x96\x8e\x17\x82\x86w\xf1\x07w(\xf9\xe0~>5\xd9$\x17\x13\x871\x11\x05\xd9\xfaky]\xce\xc3\x82\xc4\xd7\xd7\x8el\xd4\xfc\x0d\xef\xfb\x1f8\xa2\\\x8e(\xe7#\xfa\xc7\xd7\xbe\xf1\xd8\x10\xab\xa38\xd2\xf7\x9b\xd7\x90~R\xbe\x97 |6\xf5M\x04\x99O\xf3wy\x14\xa6\x84\x9f#\xbe\xe4\x9e'\xb0u\x82~\x07\xd1\xa1\xacsVG]B\xbb\xb2\x02\xcd\"-T\x18;\\\xc34%8be\xe9F\xc2\x12\x19\x1e\x008\xde5#8773\xd8\x84\xc2\xab\x18\x13F\xc4\xf7\x9dl\xd6\xbd\xf0\xd2\xe2\xea\xf7\xd9\xffx\xb6\xf7y\x0f\xa9\xf4\xe2\xe5C{\xfb\xa8\xa4\xd2\xee\xeeK/\x98\x9a\x899\x93\x07\x17\x13\x9e\xea\x1b\x87\xf9\xbe\x07\x95a6r$V3!='5A\xeeC\"\x03\x84\xa2\x03\xb6\xf6foz\xa25\xdd\xecH\x87\xc6\xcd\x8d~\xcf\xb9\xea\xf5\x80\xf3t\xd74\x03\x18{\xbdw-\x19#b\xcf\x04\n\xcem3X(\x03_\xf2\x18B\x82\xa7!\x0d\xdf\x11\xc6XI\xa0\x13L\x8c\xa5\xf9\xf2Eu\xd4\x9e\x19$a?\x86\xb1\x8cW\x04\n9ju\xcf\xc7=)g\x95\xec]}\xaa\xcb3\x11\xd5J\xa0\xd1*\x11e\x13\xe8\x8eVc\x1d\xbf\x81uy\xfa\xbdY\xd4\xf0\xbdM\xce\xd9\x07\xbe F\xefd\xc8\xbf5W|k\xfc\x9b\x03\x9b\x90\xa1\xbf\xdb8'e\xf6{\na\x14\x91%\x85\x82\xcc\xc8\xe7\x96\xd3[\x01\x11\x02\xa9~\xdb\xa6f[\x14\xa5\xc5\xfd\x9b\xd3x\xc6\xc3\x1el\x07\xdb\x9aH\xc9x\xe2:\xdb\xc1\xb6\x03\x13r\xe5jnu\xaa\xa3\xd6(\x80\xef=\xbe\xe9\xa4\xb8\xe2\xf6\xb8\xb0am\x03z\x8et\xd3\xfcn\xdc3\xe0\x11\xc5\x8d\x8c\xb4\xfd\x90\xec=L(\xb27F\xac\xda2Q\x16\xa2\xad\xd6 \xc9M\xa0\x9f\xefx\xc1\xf4\xa1k\x9b\x07\xfc\xcc\xe7\xec\xa9|\xe1\x81\xa1\xfe\xf1\x15\x83.\xd4\x19\xfe\xa1Gtq\xae\x91\xc4!xAs@\xdd\x1d\xd4\x97'\x90d\x1c\x93\xac0f\x95 c\x0b|\x1c\x06\xd3\xd65I\x1f\xac\xb7\x97DH\x8cf\x84*\xfc0\xef\xb6\xd9\x8d\x07\x0fXz\x7fT\xdf\xa1\xcd\xb5\xfd\xddFs\x90\xdf\xc1\x1fc\xc2\x05iI\x9e\xc19\x89VE\x99\xac\x89\x94\xb8\x92\xcf\x94dq\x92\xcdZ\xc5\xc2\x15\x9d\xe7\x05\xfc\x9c\x84\xd1\x9c\x94i\xb8\x86w9-\x17a\x96\xaf\xe1\x87T\xfe|\xf5\xfa\x8f\xb3E\x98\xa4A\x94/\xfe\xd0\xaa#M\"\x92\x95\x04N\x8e/\xb5oz\xd6\xcb9\xe6\x82w\xa2\x84{r|\xe9\xf5\x949\xcc\x97wE2\x9bSp#\x0f\x9e\xee\xec>\xdbz\xba\xb3\xfb\xca\xd8\xe5\x9e\xaa\xde\x93b\x91\x94\x18\x14,)aN\nrs\x07\xb3\"\xcc(\x89}\x98\x16\x84@>\x05\x06_3\xb6L9\x84\xd9\x1d,IQ\xe6\x19\xe474L\xb2$\x9bA\x08Q\xbe\xbc\x83|\xaaW\xcf\xce\x11(\xf3)\xbd\x0d\x0b\x02a\x16CX\x96y\x94\x84\x94\xc4\x95\x1e/Zf\xc04II .\x9d\x13p.D \xc7\xc36c\x12\xa6\x90d\xed\xca \xc8\x9cp\x9b\xd0y\xbeb(\x9d\x83M\x92g\xbe\xf0s\xcdz(?\xa7\xc9\"\x11\x0d\xb2\xe28\x8b%\xd0\\\xaf{U\x12\x1f\x07\xe5\xc3\"\x8f\x93)\xfbOp\x0e\x96\xab\x9b4)\xe7>\xc4 k\xe9fE\x89\x0f%K\xc4\x05\xf4\xd9(\xb7\xf3\x02J\x92\xa6\xac\x86\x84\x94\xc6\x89\xa9\xfb\x8eE\xf0\n\x80-\x06\x15\xd3\xcbz\x05\xb7\xf3|\xd1\x1cgR\xc2tUdI9'X&\xce\xa1\xcc}\xbd\xfarU\xdd+\xb0\xd2\xd3>\x1a\x1f\x81sp\x01\xc7\x17\x8e\x0f\xbf\x1c_\xfet\xf6\xe1\x12~98??8\xbd\xfc\x15\xce\xde\xc2\xc1\xe9\xaf\xf0\xe7\xe3\xd3#\x1f\xc6\x7fy\x7f>\xbe\xb8\x80\xb3s\xbd\xe6\xe3\x93\xf7\xef\x8e\xc7G>\x1c\x9f\x1e\xbe\xfbpt|\xfa'\xf8\xf1\xc3%\x9c\x9e]\xc2\xbb\xe3\x93\xe3\xcb\xf1\x11\\\x9ea\xfb\xa2\xe6\xe3\xf1\x05\xab\xfbd|~\xf8\xd3\xc1\xe9\xe5\xc1\x8f\xc7\xef\x8e/\x7f\xf5\xe1\xed\xf1\xe5\xe9\xf8\xe2B\xaf\xff\xed\xd99\x1c\xc0\xfb\x83\xf3\xcb\xe3\xc3\x0f\xef\x0e\xce\xe1\xfd\x87\xf3\xf7g\x17c88=\x82\xd3\xb3\xd3\xe3\xd3\xb7\xe7\xc7\xa7\x7f\x1a\x9f\x8cO/\x038>\x85\xd33\x18\xff<>\xbd\x84\x8b\x9f\x0e\xde\xbd\xc3\x96\x0f>\\\xfetvn\xea\xfd\xe1\xd9\xfb_\xcf\x8f\xff\xf4\xd3%\xfct\xf6\xeeh|~\x01?\x8e\xe1\xdd\xf1\xc1\x8f\xef\xc6\xbc\xe5\xd3_\xe1\xf0\xdd\xc1\xf1\x89\x0fG\x07'\x07\x7fb}?\x87\xb3\xcb\x9f\xc6\xe7\x98M\xf4\xfd\x97\x9f\xc6,\xa957\xa7pp\n\x07\x87\x97\xc7g\xa7l\xcc\x87g\xa7\x97\xe7\x07\x87\x97>\\\x9e\x9d_V5\xfdr|1\xf6\xe1\xe0\xfc\xf8\x82\xcd\xde\xdb\xf3\xb3\x13\x1f\xd8R\x9c\xbdeY\x8eO\xdb\x9d>=\x1d\xf3J\xd9\xaa5\x17\xf7\xec\x1c\xdf?\\\x8c\xeb\x9e\x1e\x8d\x0f\xde\x1d\x9f\xfe\xe9\x82uH\xcd\xacC\xcdv\xe3]\x9e%`!\xf7\xa5\xf4\x02\x92\x8c\xc1g\xc4\xe3\xfc\x8a\xf3\xb5J9\x12\x97$\x8d\xc4s2\x1b\x7fn:\xf1S\xe2oAS\xc7\xdd\xd88\xea\x874Z\xb6q\x10R&AE\x04\xaa}\xf9\xab\x0e\xca\x00#dI\xa8\x12\xa6\xc1XU\xa5x\xc26<\x1a\xd0\x19\xbc\x92\xf7w\x95M\x89\xa7\xb2U,\xc1E%\xa4\xcbdA\x1a\xd2.k%|\n\x1b\xd5\xf0$\xa3ZVK\x17\xebCF>/I\xc4N\x992\xa1+\xe1\x83e\xd0\x8a\xe4VI\x97\x14\xd3\\_#o|}\xedT\xf7PUh\x99\x96\xb0\xab9ak\xe1\x94\xcbH%\xda\x00\xc1\x10\xe0h\x17\xad\xccd\xd4\xfa:\xd0G\x1d g\xe7\xaa\xd3\x96\xc6R\xefS\xaf%\xab\x9c\xec\x18\xae\x14\xe5M,7\x9e\xec\xce+*\xe4jz\xb5N\x1aZ$\xf3\xeb\xf3\xaa\xbc\x0f\xbb\x06\x9d=k\x14M\xc3\x04\xa0\xf9]%\xe0\xc4\xb7\xa6~\xe0\nidA\xb2~\"w\xa5\xbb24iu\xa1\x0f\nc\x84\x12\x9f\x90\xfb\xa2G\xe1I\xee\xa2gz\x1e\x19$T\xc1\xc2\xd0S\xd2\xe8\xa9\x8c\x9c\xeb\x86\x93\xb2\xba\xf54h6\xaay*\x90%f\xeb\x06\xf5Y\x0b\xa5\xea\xc9\xd0x\x8cm\x03\ntN\xd5\xdd\n\xa8\x8b\xa2\x85G\xaf\xee\x83\xd9~i\x8e\x0c\xa35\xe5\xe2\xba\x97\x8bw\xb3F\xa2\x90\xf9\x8a\xb7\x04-\xd6\xd5\x94\xb6\xf7-\xf5\xf9\xea\xf9\x90[s|E\xdd\x96\x11?\x06\x9a\x13\\\x88O\x86\xd5\xa3\x8d\xd5\xa3m8\xa3ze\xbc\xd7\xbc\xc2f:\x0f,l\xec\xa0!d%\x1bMhA1\xcd\x80\x94\xcf=\x11Oq\x10\xbf|\x1f\xa5K\x9b\x00\xbb\xbd\xf4D\x89\x92\xc4\xd6\xd6b\x94\x88\xcc\xba\x01u\xb4\xd4{qZ'W(\x11n\xe7\xcf\xb8>\xba\x1et\x9a=\xea\x8e\xa7\x86\x1do\x0d7,Q6\x9d\xe4\x96\xbdc\x0c\xb9\x94\x08\xffqO\x9e\x98\xa6\x85\xf1\xf7[\xbb\\\xc6W[\x08M\xf2+6\xbcb\x92_a<\xf7\xc3\xa4\x88ViX\\90\x92\xa9\x04\xb3\xf9\x90 \x97\x0e;\x08P\xe2\xa3!\x00\xaa)\n\xac!\xf6#\xe56ih\x9f(\xcc\xd3D\xda\xd0\xf2\x0bR\x96\xe1LV!\xdf\xf6\xea/C+*i\x18}\x12\xd5\xf0\xdf{2\xd5P\x85\x14\xc57w\x04\x03\xf0 \x06\x922\xde\x06\xe1m\xca\xe4\xad\xf8\xc2-?\x84\x1f_\xe0~\xd5\xf2\xecn\x91\xafJ\xc7\x83Mpp\xfe\x1f\xacP\xf8\xfd+\xf35\xe3\x0bc\xc8#\x96n\xf2|\xcc\xd2\xf5k\x80\x95H\x7f\xed\x99\xcc'K\xbb\xd8\xc9\xa4\x10\x8d\xda8J\x84\xbb\x1d\xae\xf0j\xd0\x9d\xe2zS\xdc\x19? \x0b\xd7{\x03\x9b\x9b\x14~\x80\xcc\xa8S,g\xa2\x1do \xa4\xec\xbc$\xd4-0\xfeW1\xd9\xbd\xb2\xe9\xed\xd6\xbf\x14\xa5'\xde\x07\x86\xac\xfdF\xb2P\x8f\xc2`\x1ceS\x15\x9em\x94f\xe2{\xe9\xf9\xe0\x9c\x84K\x9b\x10x\x90V\xbc\"Un\x85\xd0\x13\x10e\xf1\xea\xf8\xc2\"\xd2|\xd1\x12\x81\n\x88\xda\xd5E\xf4\xa5H\x7fi\x84\xb4\xd4\x0ei\xc2< \x0ei\xc8\xad\x140\x1a\x99\xd1\xca\xaaL\xfe\xce\xf1\x05\xfbaX\xf4\xd4\xb0\xe8\xb9\xdfH\xae\x16=i\xa6\xf3E\x0f\x9b\x89|\xd1W\xcdD\xbe\xe8es\xd1S\xe3\xf2\xa8C\x1e\xacN\xdb\xf0\x9b\xb2\xb5\xcb\x1d\xa7\xd0\xca\x9c\x98\xeb\xdcK\x1f$\x9b\x9b\x19\xfc\x00\xc5\x1b\x0f\xc8$\x87M\xc0\xf81\xed\xb05\x92o\xd3\xe6l08\xbdx\xaa#\x1c\xa1\xf2\xfcZ\x07\x1bcL6\xa3\xaaS\x0b\xda\xba\x84\xc4m\x18\x0c\xd5\xe0\x8a]\xec\xb9\x8a\xb1\x90,@B\\Q\x1e(\xdc\x90\x1b\xb6[E\xc7Z\x8dj\x10\xb8V\xbe\xaf\xba\x03\x1dF\x83\x9a\xf7\xf4\xea\xbe\x8b`>%\x9e\xebkcZ\x83\xf6t'\x9a\x97\x8c\xf6\x14'\x03\x16\x0eq\xd37\xaa\xb6\x08u\xc7A\xab\x99\xb3\xaf<\xe8L\x15E\x15\xd56\xb8\x87\x92\x8dU;\xbd\xd9\x9ey)\x06!\xed\x0e\x1b\xb1z\x95\x9e\xe9\xab\x015\xf2m!e\x90\xbaB\x16\x8e\x08\xffl\xd0 \xcbcry\xb7D\xd2\xc9d\xfe\x88\xf7Af:\x92;\xa4\xc7zH\xa3\x1e\x83\xe9%\xdfW8\xbb\xd5\xd4\xec\xf1\xab&\x19t^\xb0&&\xbf\xe0l\x1e\xdd\x15\xec\xc3*HJ-7\xb2\xd4\x9a\xde{{\xfeAgPv\x9f=\xf7\xaa\xcb\xd5!z7\xafwv^\xee\xbe~\xfd\xf4\xfb\xe7/\x9f\xef\xbc~\xbd\xfbP6\xc5\xe4\xbf\x1d\xe7\xf1\x0f\x8c(\xc7_\xff\x81\xbe\xf1\xb93\x02\x02?\xec)\xa2\xb0\xfek\xb1{\xf5\xa6\x1b1I\xdc\xde\xba\xd4\xed\xe9\xceC\x80\xfb\xe9K\x9d\xc0\x04\x01\xdd\xdf\x08\xc1l\x13\xe4\x8f\x00\xc1\xd5NH\x1a\x10\x8cU\xa3\xb9cDJ\x83\xc5\x9env\xd0\xca\x00\x9d\xf7\xe0 \xe5]u\xeb\x05\xf9\xdb*)H\xe3\xc5uV4I\x1d/`\x03\xb3xb\x01U\xae\xfc\xe5\x8b\xdc\x8e7 \xdeD6^du\xc6zz\x02[}u=\xfbf\\=`3v(W\x99\xaf\xd6[FT\x0c\x04\xb6?\x06_>N\xdc\xfd\xd1\xe4\xffL>^]}\xf7\xc5\x9d8\xbf\xbf\xf2\xdc\xfd\x91\xbb\xbf\xf1q\xd7\x9b\xfc\x9f\x8f\x1f\xaf\xbe|\xfc\x18x\xdf\xed\x7f\xdc\xf5>\xea\x81Yx\x00\x98\x8f\xb7\xdf\xfd{oH\x07\x8b!S\xc3\x8eI\x17\x8bV\x92t\x01\x98F\"k\xc3\xad\xb0\xc7\xc6\x1ed\x08\xd4%R1JB\x158B\xa64\xdc\x0em\xa0F .?\x8f\x05\xc2\xa3\xc8n$\xea\x9b,A\xf9\xf6H\xa4\xd3<\xf7^\x86\x0e\xf7BD\xf7\xa4\x1f\xcd\xf2\"A\x99pm\xd3\xcaE\x17\xf5\xc1\xb9\xbe&\xe5I\x1e\xafR\xe2\xe8\x1a B\x1bAU\x08AC\x9b\x05Y\xe4\xc9\xdfI|\x11.\x96)y[\xe4\x8b\x8bhN\x16\xa1\x90*\xf0\x8f\x87\xa8,\xf8\x97\x93w\xe3\xcf\x98\x8d\xb3\x10\xf8\xf3/\x8bT+\x94dSR(\xefe\xbbfq\x00\x824\x81i\xd4\xac(z(\xec\x98\x89\x1b\x0b\xdd\xcc}\xf1\xfd\x0b\xcf\xb0\x0f\xf0\xd3\x8b\xd7\x9e\x91\x97\n\xed\xeb\x83\xa0\x10\xd4\xf3(T\xf5\xdaXKFF\xd0\xddZ\xfd\xae\xfdk-|\x19\xb6+\xe1\xa2\x99\xe1qm\xa5,\xa7\x95\xc7\x10F\x8bg\xbd&\x8b0I\xef\xd1\xc2\xaa$\xc5\x1f _\x8c \xca\x17\x83\xda\x12\xfdb,(\xd9\xa2\xc9\x828\xc3[t\xe5\xf5\x95\x17\xd0\xfc\xf8\xe2L\xa8\x84\x19\xf8\x02\x83<\x05\xd1\xc4\xf0\xb6\x06\xc5u\xe3\x95^O\xd3<\xa4\x8f\\u\x92Q2{\xf4\x0e\x0bT\xd8G\xff\x83\xb2\xca*\xf6\x94\xb88\x10 \x8dW\xad\xf2\xa5\xdd~\x13\xdc\xdb\xbcLw'\xa4\xcc\x82mt\x17\x9d\x0frr%\x99\xdeyF\xff3 \xc4f4h3a\xf2AO6\xc14/\x16\xa1\x812\x02\x81\x12V\x13\xd4O\xbcv`\x13\xb8\xa9\xcc\xca\x18\xd5S\xc2%\xf6.)\xdf\xae\xb2\xc8s\x13\xc6c%\\O\xda\xf9\x90}\xca\xf2\xdb\x0c\xb5 \x85K\x1b\xec]\xd7\xd4\xa46\\Xa%\xcb\x0d\x93<2[7\x89\x7f\x00\xa4\xa3\x15U\xd6\xfa\x8ep\xf7\n\xf6\x9b\xaf\xa3\x96)\xa8|r\xd3RP\xcbR \x99\xd9\xb1\x14\xca\x97\"P\xe1\x8035V\xb3Vg\xaa9\xef\x1c[\x16\x00m\xce\xb26\x844\x93\xcf\xa2\xe3\xdb\x0c\xc9\xb0\xcf\x0bC\xc0f\xf60\x1c6\xc3;j\xf3\xf7\x1b\xfc\xbe,\xc841x\xb4b\xcfuU\x03F\xab5g\xba\xe5S\x9b\xad\x16\xe6\xef\xe3\x8aG\xb6\x1c\xe0a\xc7\x01\xceN\x90\xd4C\xa8\xfa\x97\x9c\xe2a\xdf)\xee\xb2Y\xbd\xc3K\xff,\xa7\xe1\x8cM\x8e\xc3\xcd\xa5\xdc\x1b\xd8\x87\x1bF\x96\x8f\xd0>\x16u\x01\xee|\xb8\xe6\xde\xd2\x17\x13\xf6\xdd\xf9\xbcH\xb3r\xc4\xce\x8e\x1b\x96 _\xd1_\xc1\xb5\x85\xc0Q\x0f\x05\xc48\x91\x0d\xf9\xb2\xdc\x11\x83\x07\xd8\x03\xfe\xff\xcb\x17\x98qK\x10\x9f\xa7HU\x0d\xe5\x85\xe5\xe1P\x023\x11\xa9>\xae\x88\xbf\xf5$\x93nn\x9b'\x04\x9e\x0d\xd3\x81ns\xe5\x13\xc9\x1d\xc8\xfd\xb6\xb2\xca\x85\xdf^v\"\xe4V\x9d\xa6\xd6\xf94g\xad\xcf\xef\xdd\xba|\xb6\xac\x8b\xfb\x8d\x0bs\xaf\xf6E\xaeV\xa6\x01\xe4\xb6U;\x91M\xfd\x85\x99\xdc\xee!\xa7\x0f\x199\xad\xec\x19\xb4$\x95\x1b\xf0\xc2N\x9d\xb2\xbe]\xe8q\n\x0e9\xde\xd8\xb8\x98\x1c*\x84\xf7\x97/\xb0T?\xd4$7#\xc6-\xd3\xd5h\x87\x95\xe2H\xa2\xfa){(\xde\x03\x06\xb3h\xa9\xd2\xb5l\xf2a\x03\xff\xd4R\xbc\xc3\xba\x90Jc\x9d\xad\xde&;Wv\x96E}\x0ed\xff:\x0fm\xfd9\x93\xa5\x04D\xd91\xbd|\x16\x93j\xd4\x12\x1d\x1e^UG\x16\x92M\x07l\x04\x07\xd04\xb5\x9dN\x0e\x91\xef\xc1\xff\xcdOg,\xfd\x8c%~b\x7fJ\x9c\x8b\xee\x85\xf9\xdaw\x80\xc9\xa7\xd9\xd9=hw\xbe\xe1\xf3H\x9dA\x8d\x18\x94\x03p\x1byx\xba\x05\xce\xd5\x87\xad\xfa{d\x99.\x86\x15h\x82\xc7{Tw\xe5;\x05\xd1\xa8pa\xf0^\xa2[\x8e\x04\xde\xf7L[\x17j\x94\xcc\xa4h\xa8\x0fQ7\xa9\xcd\x118\x07\xd9\x1d\x9d\xa3\x0dT\x98\xc1\x0dAc7\x0bU\x80\xe1Q\x86\x9e\x08zC\xa5\x8doeH\xee\x11\xcf\x99\x018R\xcc\xdc\xb8 \xffSv\xd4W,\x15&\xcd\xd9\xf9\xdbB\xff\xb7lQo9WV\xa2]\xb8Xa\xc6\xe1M\xcc}\xb7\xf6\xfb\xab\x0fcV\xd1X\xef\xfaW\xe3=\xc8\xd4x\x89'\x05\x8e\x11\xff\xda\x84R\x86\x0d\xb3\x86\x9c+\x97x\xc3s3\x93\x19lL\xa24\x94\x81{M~\x0b\x92,\xc6\xc0*\xceG\xaa\x85c\xd3\xaf\xe1\x00\xcda;.\xa5X\x7f\x92\xba?\xd3\xbe\x1b.-\x7f\xda\xaf&Q\xcd][t\xcf\xd5\xf0\xc8\x9aq\x87\x95V\x9ex\x15\x87\x05O[\x84\x9f\xabxrU\xc6Fb\x85\x1b\x95 hw\xc1`\xd7$\x85\"2OCl\xd8YY~?\x8ds\xd5\xd8\xa0\xbb\xe2\xc4Z\xb1\xeaz\xc5\xb0\xd2\x0dGY>d\x01\x06W\x19/\x12\xca\xdd\xdcc\x9a\x12\xac\xa3\x9ayy\xbb\xd8\xf8\xaaMz\x9dG\xac\xfeI\xf3\xfb\xaeV\xbe$z\x0e\xbb\xd4\x03\xa9&\xe5\x06\x9b*\xc6(D\x06\xa8\x10\xbe\xebL\x1e\x152X\xacJ\xca\xd0g\x08<\x1e\xf2\x9a\x88[)\x8b\x1b\x05#\\\x11\x0eo\xf5\xcc6GD\x16 \xed\xb7\x9f\xe7\xfe\x8f|X\xf9P\xfa`\xf0\xc4\xac\x83\xb9\xabm\x03\x0c!'\"\xe5\n+\x1c$\xc4\xd4l\x01~F\x05'\xb7\x9d\xce\xd5\xd2\xda\xe9\xd2\xd0\xceDo\xb1\x9e\xa1\x8b#U^\xe3\xa9\xc6oc^5\x9f|\x03\xcd\xc3F\x1f eZ\xbe.\xbf\xff\x90E\xe1j6\xa7>\xac\xb2rI\xa2d\x9a\x90\xb8\x1a\x1bv-\x00\xf7\xf7\xb0\x89\x0e\xa2\x1d\xcf\xe4.\x84\xb7\x17\x05\"j5\xa7\xde\xa3&\xdak\xcdq\x82^\xa2\xd4\x19\x98\x90+\xbb\x92\x05\xd7\xc2\xc8<\x0f\xca\xdb\x04UXt9\x97i\xca\xa2\xb0$\xb0k\x8e\xf4/\\\xb0\xa2[t3\xd5\x82>\xa4\xdb\x9f\xb0\xd2\xa7\xbd\x95\xfa\xcdu\xba\x7f\x13\xcf\xee\xd9\x84\xfa\xf6\xf4\x9e\x0d\xca\x9b\x7fc\x99UE\xd4\xf7[\xe1\xb1\xfd\x18.\x97\xe9\x9d\xe8\xe0J\xd7{\xad\x84\xf4\xb9k\n\\\x83,\xd4\xfd\x1a\xc4C/\xc5\xeb-n\xda\xe2y\x95^t\xc9C4r\xc7\xe5Pnnz\x90N\xca+\xad\x8bF\xfc\xa3j\x954\xb1L\x18\xc7J\xcc\xd0N\xe5!\xb6\xe3\xc26$oX\xfc\xce\xa4\xb2\xda\x1aYV\xa7^\x17\x96\xecAU\x0d<\x93\x91[5\x02)~cx\xd3u\x94/\x0e\xfa\xff(\\\x1a\xc8.y(\x90\xaf:8\x02\xaaU\x94\x04\x08/\xa5\x9f\xf6\xae\x074\x87$\x8b\n\xc2\x90\x0d\xfa\xb7\x08\x9c\xd6\x92J\xe4\xea\x9b\xe9/\xd9\x7fZ\x84\x11\x1e\x82\x8d\x04\x0cL\xd7u^\xe7h\xe6\x00\x1b`\x15\xb9&<\xfa\x8du5\xd9\xc3\x03\x88d\x12\x83\xee\x83[\xfd\xdec\x8c\x8dyU\xd0\x08[F\xd8J8M\xf0\xad\xeb\xd4\xbf\x13\xfb\xb7\xdaA\x9a\x0e\xe3\xad\xd6F\x07\x81\xad\xed\xd1\xb3\x156:\xc6\\\x15\xe5\x9ci\xeb\x8ax_g\xf4\xd1\x87\x98~\xe6>y\xd2\xb9/\xda]2\xb7f\x05t\x8a\x0e\xc8\x1a#\xd6\x97G8\x02\x90K\xd8\x9eh\xa3\x0d\xb7J+\x19\x8a\xe8\x8dh\xf0#cC\xaa\x0b\x0eF\x9e\xa6\xb0\xf04\x96\x93!\xb3\xa1\x03\x83\xc6\x04N\xd0\x9bjo\xbc\xb1W:\xa9\xf6\xcc\x16\xb4\xf8\x0e1\x13]\xcbh\x03\xeat\x10,\x9b\xc8\xd26\x8d\xc4\xdd\xf1\xea\xdbx\xbfE\xfc\x19(?I\xe3\xc3H\x8b\x16e\xea\xeba\xbe\xca\xba\x05\x02:\xbboS\xae\xa0\xed\x85m\xc3YRy\x94\x14\xd3`q\xa0R\x87+\x96\x16\x9c\xfd\xf8F\xe3F\xec#4\x1c\xe6\x95\xbaJ\xa3T\xbfI\x80n\x0cD5\x0f4\x99\xfbl\xe7{\xcf\x0b.hA\xc2\x85\xa0H\x82s\x12\xc6\"\x02\x1b\xbe\xffR$T\xbcg\xee\xee\xeb\xefQ\x80y\xb4Z\xa6\xe437\x80\xe3)\x97E\x98\x95\xd3\xbcX\xf0\x8aww0\xf5}X\x96\x97\xf3\"_\xcd\xe6<\xf3\x8b\xe7\x83LMz\x1d\x01\xf28_&T,\xdc9>\xdf\xf1l\xf4\x9fA\xd7\x1e481II\x12\xc6|\xa1|\x84\x07\xaa\xe0\xa7PF\x8b\xbbf\xd24\xc9\x92f\xc0E\xdb9\xbd\xd19\x07\xfa#-\x0f\x08o\xd4~\xb6\x93F\xaf\xec\xf9\x04R*\x8c\xe6\xfb\xea\xb3\x16^d\nd\xe0o\xc2\xc8 \x82P\x1f\x1a,\xb9\x93\xc5\xe8fk\x8b\xf1y\x18v\x1d+`3h-k\xbe\x07\x02\xac1\xca\x8bO$>'\x7f[\x91\x92\x96o\x0b\xf4\xe9mJ\x96\x8bDP/\xcdPlO\xd3\xdb\x92\xcfW\xee\x91\xa5\xf5\xedk\xc7\xeeV\xb7\xd3]\x9b\x0fYq\x11\xc6\x06\x0dn\x8a\xfc\xb6\xe4\xd4\xcb\xc4Y\xef\x04\xbb;\x8e\x0f\xec\xc7\xeb\xc0\xb9\xaa]\x81\x04kR\x94I^y\xf9\xf0\xe1{\x8fk\xd2\n{\xda\x04\x87w\x99\xe8KpW\xed\xd3\x0b\x1a\xa2-\xfc\xac\xdd\x9dT\xd8\xad\xbc\xd0\x8e\x954H\xb29)\x12\x81\x15^\xed\x1aX\xaa\xc8h-\x02(|\x12z\xa6#\xdc\xe0\xcf\x06\x99IL\x05\xfe\xd1=\x0e\x80\xd4uvw\x9f\xefJG6\xed,\\u\xebC\x92\xd1W(i\x025`\x8d\xd7R1e\x03\x98\xfb\xa8\xa1\xc5\x1a}iE\x0d\x0b,l\xf983bg\x10\"6\xee\x82\x8a\xa3C\x0420\x84Q\x05e\x1fSU\xf6k \xd5\x11\x99\xf0\x8b\x8e\x93\xd9\x15\xfc\xeaz\x7f\xea/\x10\x19z\xb7\x0f\xbb/`\x04\xbb/\x9e\xbdzn\x99\x85FW\xd0\xaa\xf4\xcb\x17A\x0c\xe7\xb0\x0f9\x8c\xc4\\\xa4\xf5\x87\x94Q$)\x8c \xf2\xcd\x95\xd4\xb1~\xdc\xf6w\xafF\xe6az\x18\xa62,\xa7/\x0f\x02\x12\x1f\x15a\x92\xa9\x89\x1c\xe7i)\xcdr\xfclh\xa6\xc5\xa4\xa4E~'\x12\xcd+\x82\xf1\xf99\x7fE\x82\x98Dy,\xa2\xc9\xd8N\xaaF\x1eVxZ\xb5\x86B\xb2q\x16\xe5\xa2\xb7\xa4\x95\xf6\xe5\x0b8+:}%\xe5I*\x13\x87 l\xc5\xb5\xa1rD\xab\xe4)\xef\xb2HJL\xd8\xfb\x0dn\xe5\xf7\xdcZW+\x9cg\xa8\xff\xd2\xab\xb8\x0b\xedC\xb3\xef\xc4\xe4A\xdc\xaeoU\xec\xd8\xad\x84RpY\xf4]\x16u\xe7\xe3\x81\xe0\xb0\xe3\xd1\x8d\xfd@d\x14c\xff\xa8\xe4C\xb4\xb9%\xb2\x81\x8a\xc6 \x15\x7f \xf7\x1eII\xe6+\xbf\xd9\"X\x1b\xf9\x8a\x871\xf5\x0c\xc4\x87\x99\xa6\xd2\x9f\xad-\xe5x\xf71r\x80[\x9fJn\xeeC\xe1\xf9\xca9\xe5^\x08\xa6\xdco\xad\x03\x97\x9br\xb9\xa8\x14\xa9\x12\xc1\xd8\xf3+,V\x19\xe3\x15\xdc\xdc-\x1e\\\x81\x0f\x17\x1cT\xecZ(\xe89\x8aO\x00es\xd0A\\\xf5+\xf8\xe0\xad\x01\xec\xc1\xd8\xd5YD\xfd \xf1\xcc\x90{\x07\x7f\xb7\xb6 C\xde2\xb9\xa2dX\xea-gB}\x8cfZ\xba\xd78\xcd\xfcj4gsv\xed*\xef\xf6\x91\x1b\xbfXi!\x05\x01\xa8@Y'\n\xf8kl\xfa\xba\xdb\x8d\xfciX\xd2\x1f\xbb2T`\xa6\xd4\x88\x8a\xcem$\xaa\x03\xc2\xae\xb9\x03\x92\xdf\xdai`-\x8d<\xcc\xc8-\x84\xfcf\xb11\x016\xba\xe0\xce\xbc\xad\xb9\xe6s\x930\xd8p\xe7\xfc\x12\xec\x8ew\x00\x8d\xbe\xd9\x8f\x06-\xe05\x1c\xa0\xdeY|\x9f2n\xf6V#\xfaX~N\xa6(\xe1\xa2ok\x0e\x0e7\x08\x9e\x94f}\x0c\xbe\x86\xca\xc5\x87\xc4\xcb\xe2\x8b\xed\"A|^\xeb%\xd7u\xd1\xb5\xbd\xac8\x01\x95\xc22e\xaf\xfej/\x8eg\xb4R\x98\xbf\xef\xc9/\x9e\xe7\xc3T\xb9-\x1e\xb4\xa67M\xa4\xc8E\xe9\xc6k\x03\x15\xec\x19\xfaP\xf6F(_\x05>\xc7\xcb\x03\xe5\\\xc4\xa8+r\xa6\x18\xe6\xa4\xf2$\xe4a\x87\xf9\x17\x97\xb7^\x7fSk\xd9\x1d4\x9ake4\xa6Ad\xd0\x17\xf0Q>\"\x06\xa3<\x83\x9e<\x01\xaa\x10C\xb8\x06-\xe2Hb\xe4\x98\xa59\x06,\xfc\xd5\x15\x07\x84\xc68\x16n\x8d\xbb\x07\x8d\xf3\xd6\xdawj\xa4?\x0c\xb6\x0c\xeb\xca\xb1\xb2\x86:\xcc\xb2\xa0j\xf9PD\xcfo#\xd8\xc9g\x9b\xbf\x8a\xf87b&;\xc1\x91\x8b\xcd\xcd5\xf4\x8a\x0e\x83AtZi@l\xe6\x93(\xa9e\x05\xe6\x0c\x95R\xf4\x8a\xa3\xcd\x92\xcf\x1b:\xfd\xcb\xf1\xc6\x82k=\xa1w \xbc'\xc3\x1c\xbb2\xd0'\xce\x86\x0f+\xd8\xdc3\xc9\xd3\xd8\x93\x07a\x9a\xf2\x83\xa0\xe4^\xd8\xe4\xee\xe3;\xa6\xf2\x92\xe6\x83\xe30\xd2\x82\x1f\x00Mx\xd9\xdc\xc4\xac\x1dG\n'I\x18\xb9b\x11\x0b$\xa2\xaf\x89*\xe7\xf1\xecb\x04qN`?l\xe7L\x1b\xd6\xbb(\x08)&\xee\x94\xc8T\x9c|\x10\xcdW\x99\x85\xd1\x92\x0f\xea\x0b\x05DP\xf6\xddy\xb99r\xbf\x88\x87\xc1}\xb5B\xbb\x88\x99\x1a\xdc\x1c\x8c \xad\x16-\xf5\x19\x036\xd5\xc0\xc1\x0b\xae\n\xb9\xa3\x81S\xdau\xf4\xca\x83\xbd\xa6\xb9\xf9\x1e\xb2\xd4ZW\xa9\x87\x0bhn\xa4Z\xb4\xc8H^\x86\x06fM\x07\x9d\xc2\xa7\\\x8f\xb4\xbc:\x85*\xf1\x96\xb6\x07xx\xf0\xc9\xd5\x1b o<6\x0c\xb4=\x92\xa28\x9c6\xebJk\xe1\xe9\x0c\xc2\xca>A~\xb7\x171\xb3s$e\x1e|p\xf8pZ.\x92\xf4gF\xe8\x08\x0d\xad\x84\xc8\xb5\xdbI\xa3\xfe\xa8\xb7{\xd5\xd4\x1b\xdc\xda\xa8\xcfW\x1f\x1c\x8d\xe9\xe6}\x85\xa4\xacE\xbfBYI\xcbX//\xe3nH\x18\x07\x8e\x0f\xce\xd1\xf8\xfd\xce\xce\xce3\x8b\x8f3ho\xf0*\xb9\xd7\xfd\x99\x85E\x10\xb1\xb4\x9e<\x11\xbf\x82yX\x1e\x0b~\x0bl\xa1C\xa5\x9b\xe8z\x99&\xed\xd2Wh(\x07{\x03s\xfb\x16X\xb8\xf3\x0d=\xeb\x08\xe0\xd5/O\x92Z\x90\x1bsU\xdf\x94\xd4\xfc&\xdb\xed\x9c\xe3\x92\x0e\xa6\x9a\xbc\xa4\xc2\x8f\xce\xfaN\xcb\xaf\x88\x85\xe6\xbd\xe2;y\xce5\"\x9c\xb4\xee\xe5}P\x15G\x97\xc9\x92\xf4a\x07.\x01h\x1e4uP\x90\xc30\xcbr\n\xac\"\x1f\xd8\xafB\xdcp\xea\xac\x88\xd6r[$i\xbf\xa3C\xb2\x9e\x1b\xf0\x1b\x18s\xbb\x8d\xfd\x86\xc1#7\x88\x0b\x85\x8d\\\xa5\xab\xd01:W\xa1_V\xae8\xdd\x02\x17\xb4P'4\xb6\x1fi+$\x0d\x94\xe2\xdc\xed\xaa;L\xf0**Y\x06\xd3\"_\xe8\xf1\xe3\x00DH\x05\xcb\x16D\"\x85\xebWpT\x8dT\x18\xe3\x0b\xf6\xf1U\"@FmsEX\xbc\xe1\xd1$\xd3\xcd\xdak;\x86\xac\xaa}\xe1\xf9\x90\x0b\xb9\xfb\xfe\xb0\xb3[R\x03\n\xc8\xf0\xa5\x0f\xa7\x94\x14@\xb2\xd8\x16d\xd3D\xdd(G\xb4\xc5y\x86\xd8\x8b\x19\x9e\xdc\xab\x16\xe7m\xe7\xd2A\xb9\x9e1Y-\xc9'\xb4\\$\x80B\xdc\xd4\xa4\xf2>\xf7\nN\x1az\x80'\xe1\x1dn\x15>\x11\x98\x1bQ\x0fF'+Q_\xc0\xf1\x8c\xd1\xa3\xb9,A\xb1\xa3\xc989\xd4\xbc\x8er\x0dm\x1eg\xeb0Mb\xc8\xf2l\x8bW\xbb-N\x1a\xe4s\x1c\x0f\x95\xc5\xb9/\x8e\xe6\xbc\x87\xcdy/xJ.\xf9\xd0v\x10\x10\xb9\x069\x97\x99\xf2\x00\xd2n\xde$\xc0B\xc3\xde\xaf\xa4A\xb6\xf5AU\xae\xdek|S\xd5}\x078\xd1o\xf4\x8c\xd7Axw#\x17E\x8b[\x82{Jl_\xda\xe1\xc2G>F\xf2H}\xbeVz\x18\xf6\x8a\n\xee\xb2\xa4\xda\xa0\x8c\x88\xcc\x95\x0d\xcf\x15\x03,\xce#\xcc|\x9e\x94F\x18\xf8\xce\xc2\x18\xb9@>\x95\xd8j\xd3\xaa\x1b\xc9\xeaF\x0b\xb8:8\x12m\xde\x0c\x9a\xcb \xed\xfd\xa6\xeck\xa7\xc3GR-\x18\xc4\xed\xc1\x05\x0c}p\xc3=\xb6\x19\xd8Z\xfb\xfc\xdb\xb8\xe0n`\xc3\x1d7\x02\xc3\xcd\xbb\xfaH\xb1\xc2\x08\xf4P\x84\xda\x83\x07\xce\x08\xb2\x1eY\x85\x90<\x8c \xe9\xce\xc8v:\x8fgo\x07M\x1f-\x86S)\xca1O\xc3\xc8\xc8\xe4\x1b\xf3Z\x85<\x9b{\xd0vs\x06\xb5\xa4G\x95\x94\xacj\xfc\xd1\x89\x9e\xcb.\x8c\xb5\xf2A\xa2\x8cvL\xa0& \xc3\xa0j\x10\xf1\xa4\x11\xee\x1c\x1a77\xbb\xea^eCjo\xf0l\xcdV\xda3 \x1b\x16H\x9e\xbflm\xf9\xca\xad(:\x82\xac\xef\xcb\x14\xa9\x07\xbe\x19o\xcf\xda\x02\x13\xbc=\x93$q'\x11X\x12z\xd4\xba1\xef\xa6\x95\xd0\xd6\xd2\xe2\"O\xb8\x99\xa2\xf9\xbb\xfc\x96\x14\x87a\xc9\x8d,6\xdc\x893'\x9f\x19w$\xee\xdd\xd9\xff-\xfc\x11\x96Q\x92\xb0\x1f7I\x16\x16w\xf8+,\xc9\x8b\xe7\x98+*\x9f\x8a\xff[OE\xb1\xdd\x17\xe8k\x17k\x90\xbf\x8b\xf0VQ3r l\x82\xe3xZ?P\xcf\xa8\xb2\n\xd0Ng\xe9`\xb2\xde\xf3\xe8d\xb2G]W\x83+\x83\xf2\x81I3\xd7\xca&5X\xe6[\x93\xda\x89\x91\x83&U\x9c\x83\x91\x91\xe2F\xae\xba\x97\x93\xee\x18W\xe3\x80h\xef\xdd\xe6\xe8\xbc&\x84]\xdf\x87\xcf\xc8\\\x85J\x15\xd7C\x1e\xe3\xc4\x19\xb1\x96,\x96)Y\x90\x8c\x92\xb8\x87\xb5\xa9/\xe7\xb8h\\\xfdF\xb2x`g\xaa\xbb\x8c!{\xdb\x1a\x90 \xa9\x02\xc2\x055\xe2\xeeW\x11\xbd\xdf\x8b\x99\xa8\xcd\xbf\xa1\xe9$\x83{\xa8\xaf\xee\xa8\xa5\xcc\xabP\xf1MQ\xab\xb0\xc8\xcbc\x8e\xe2p\x87\x16R6\xcb\xd8\xad\x06\xd2\x192S\x80\x07q\xad\x1f\xb4S 7\xfdJX]\xd5\xb9\xaf\xd2\xb2\x19\xbf \xcc\xb3\x88TB\xb7\x0e\xd2\x8d\xd6*G;\xbe\xa2\x9a\xd5\x16Q\x83r\xa8\x14-Fe\xe0\x16\xacT\x97\x8c\xdb\xee^\xdbJY-\xd3\xd5v\xa5\x84\xae#\x14\xd1\x81\xf6\xd8\xda\xdb\xbcl\xf4\xc7\xca\xe7Z\x9aw;\xdb\xc7\xd8\x8d\xf7\xdc\xf9\xf5%\xf7Z\xfe\xd6\xb6\xe9*S\xf3ToZ\xae:O/\xbf\xcb%%Y\xecz>\xd0V\x0c\xf8\xdf\xd5=U\x03\n~\xcf\xa0\xd4}\xb6\xf3\xcac\xc7\xe1\xf1bA\xe2$\xa4\x04\x13w\x87\x85\x0ex\x8c(\x83F\x04\xf2\xbbf\xe7\xbf\xb9\x1b\x99\xfb\xe2\xf5\x8e\xe7z\x95\xdbN\xc6-a\x98\xc8\x17\xafw\xbfa\xa8\xeb\xcam\xfc\xcb\x1ds\xf0\x84\x17\xa6\x88?\x99\xfb\xea\xa9!\x86\x97n]-\x0e\xf6f\xc6\x95)jSWx\xa0R*E\x867\x9a\xff\xc5\xb4\xa1.y\xdf\x05\\W^\x1b\"_u\xa5\x0f\xb51\xa2\x12\x9f!\xb4\x98W6\xcb\xe1\x85@\x86\xc1W\xb9A\xb0W\x9b\xbaF\x9a\x93\x05~F\xa0sI\xf4p\x11y\"\xce]\x04\x7f\xd8\x83\x1d\xc6&\xb0\xb4\x914H\x96vN[\x90\xba\xa5\x1by\xde\x1b\xe0a\xee`s\xd3p\x1d\x85z>\xaa\x94\x95rq\xc2T\x1c\x8d\x13z\xe5C\xe1N\xbdz\x8c\x1a\xbf&R\x15w\xc9\xdf\x00\xcd\x0d#\x89\xd6i$\x05\x95Z\x07\x86\x11\xb5&\xd1\x1b1\xd3\x8bHaJ\xc2\xc4nD\n\x8aT\xb8\xf1\xe1+\x97\x12tw\xaa\x06,\x967\xce#\\r\x11\xc0\xe1\x92|\xa6\xa7yL\\\xc7\xe9p\x1cn\xd0\x00QT\xaf\x06\xdc\xaf \x83\xd3\xc1\xe6{\xf2\x80\xe7\x97\xeb\xdc=\x16\xb5\x9d\xdfC\xfc_f\xfd\xfe/\xb11\xe3W\xb3D\x05\xad\xd6\x9a\xe4\x94E\x8e[;Z\"B\xf3\xa3\xca\x8f'8\xd1c\xd0\xc8\x077l\x1e\xc4!\xe5\xe1|\xf6`s3\x81\xff\x80\xa7\\\xdd\x01k\x0b\xcay2\xa5.z\xa1\x10\xe2\x17ix-(\\6\x82 \xad\x96qH\xc9\xbb\xf0\x8e\xcd\xf3\x00*\xd7@\xb2cD\x0f\x83\x80u\x19\xde\xa5y\x18w\x84\xfb\xa9;\xf06I)\xe9>\xe5{:`\x10\xc9\x0e\xeb@9\xcfo\xfb\xc9C\xc6\xa0\xb6|B\xf5\xf8>\xe7\xc1\xb4\x94\x04#UE*\x17\xb0\xba\xfby\x06\xc5\xb6\xe1\xae:\x86ke\x1b\xb3\xd9\xc8\x14\xbf\x8e=l\x16\xb2\x91\xe1.\xc5f]\x88s\x17\xcd\xc3lF\x84UW\xff\x0c\xdes\xfe\xda\xbe\xe3\x1d\xe7\x11\xa70|\xe4)\\\xe41\xb9\xd7\x0c\x9a\xb8/c\xd0\xae\xf6\x06vR\xdc\xb1\xd7|\xf7\\\xf37\xa7\xcd\x9f\xb5\x91\x81Vr\x8a\x1b\xcfi\xb3p:Z\xd1\xca\xb1\xc1:m~\xae\xc2J2;\x83+\xee\xa2\xf2\xbf\x1ea\xe2\xf5mH\xc9\x8fd\x9a\x17d\xfc\x99D+\x14l\xd2 \n3\xf1\x8a~.y\"k\x0cOR%m\x1e\x96?\xe5\xe2\x12\xa6\xfa\xfeKB\xe7'\x84\xf2Y[\x86E\xb8 \x94\x14\xe6\xd4\xe3,JW%\xab\x94P\x9ad\xb3\xb7ya.\xf6\xe3\xddqL2\x9a\xd0;\xfc\x1e\xa6i~{Y\xdc\x1d\xd3\xb3\x15\x95\x85\x16\xec\xa8\xafn\x0ddj\xa1\xbf\x96\xcb<+\x89\xb9P\xa9\x16)\x1b\x05\xf8\x1b\x0dg3\x12\x9f\xc9\xb1\x96\xcd\xa1\x97\xac\xbb\x97\xe1\xac\xca{Dh\x98\xa4\xd5\xab)\xfby\x9e\xd3c\xaet\x87r)\xca\xa3Z\x88\xf6\xe6rzo\xc2\x92\xbc\x0f\xd1\xacO\x00@Rw`\x9ad\xf1Q\x95\xc6+!\xd1\xaaH\xe8\xdd\x91\x96U\xa6\xf3i.\xf2x\x15\x89\xa6\xa2<+W\xb2\xdd\xbc9\xc2eH\xe7\xb2\xfcb\xcd\xfd!I\xe3g\xfcM>SRdaz\x94G<_\x92M\xf9^M\xca\xb3\x83\x8bg\xbc\xec\x92D\xd5\x8f\xff,9\xa8\x9c\x932O\xd7$\xbeX\xdd\xd0\x82\x88\xe6Y\x06\xedC+\xbdQS\xf5r\x91\xaf\x8a\xa8\xce|Ay_WE}\x19\x8b,\xaf!>\x82\xa2\x15\x94\xb9\xafLA\xdaQ\xa5'GyA\xd1\x0c\xf1Wt\x87\xf8+\x9aH\xafn\x13cm\xbf\x97\xd0nVa\xb0\x1c\xfd\x08\x17\xecL\x9d\\1\x96bF\xe8q\xe6N\x9c\x05\xa1\xa1\xe3\x83\x83K\xe6T.\x9e5G\xb5\xd4\xf3a\xe2T\xdb\xact\xae<\x1f\x0f\x8d\x12Eh\xffy\xe1\xb9\x93+\xcfC\xc8\xea\xb1\x87\x94\x97\xa0\xc1I\xb8\x0c\x92\xf2$\\\nE%\xec\x93\xeb`\xb0\x06\xaf\xd6\xf4\x16\xc9I&\x12\xb5\xb9A2\x81\xf7\xe4$\\z*9\xea\xab\x98\xe1g\xae\xe0\xd2\x7f\xf7a\x9a\xae\xf7Bj%)\xbf \xb1O\x94\xe7\xf1\x0e+\x93%\xa7\xea]RR\xcf\xf5\xbc\xa0 l\x1f\xb9\x8d\xaet\xdd\xc1\xc8\x08\xa4\xb1\x081A\x959\xd9\x97o\x88\xb8\xaf?/R\x87[5\xd4\x89]r\x19F\x9c\xbbj}\x9b\xe0\x04\x0el\xca\n\xf8r0\xb0j\xce\xbb\xbe\xfc\xffP\xa3\xa87\xa7\xbe<\xe6AX\x8e\xb3\xff\x1a:\x87\xf1\x84|\xf2\x83\xa4d\xffT\x81$ \xca|A\xbe\x11f+\xe0\xd4\x94\x8d\xfbf\xe4\x92\x07\x1d\xba\xf49>\xa5$\xa3,\xc9\x0c\xabz\xc7\x14\x08}\xd3\x9aH6\xd5\xb1K\xbcj\x9f\xf7\xed\xef\xd6~f\x0b\xda&\xd5\xb8\x8b\x92\xfb\"\x8f\x81\x953Tz\"n\xceZ\x1fQ\xa7\xac\xb5\xb5x\\]r+vW\xbb\xd8\n\x1d\x93`1yb]\x8bM\x811\xd2\xcd_Fp\x89\xd1\xf30j\x15\xcb\xe8,V)M\x96aA\xb7\xa7y\xb1\xd8\x8aC\x1a:u\xb6\xbcX\x1c\xb1\x14\xcc\xcapE\x12\xe1q\xb8\xfdy\xeb\xf6\xf6v\x0b\x8b\xac\x8a\x14\xaf\xd7I\xecT~\xda\x8d\x04\xb96U\x06h\x14\n*\x15\xc0\x189\x1aI\x894\xf2\xe5\x9d\x00Z\x1d\xe3\x87\xf5\xe1\xde \x83&dy/\xb0c\xc7\x8a\x9c}\xc3\xa1\xd2\xc6*\xd1\xaa(HF\xdf\x0bR\x84\xd3e'\xcdS\x19A\xc5\xfd^\xbfrY\x99y\x04~1\xf4\xd2k\xd6\xc1\xce\xff\x893#\x14\xe1{\xc5\xff\xe5%\xfe\xe7\x1e\xba\xd8\xaf|\x89D\x0f\xfb9'a,\xf6B4g?\xd0\xcb\xa6\xa3E\xd2\x88z\xc5\xde\x15Wf;\xd7\x00Z\xf7\x9fS\x1e%M\xa5VX\xd1P\x08\xcb/HJ\"\x9a\x17\x9e\x1b\xf5\x05\x82\xac\xb0\"\xee\x8b\xaaBM\x9d\x9fs\x04\x9cHz\x94\x86V\x85\x1e\x15\x9d7Q\xd3d\x8f\xd2\x0c\xab\x8e\xa3\x0cG\xf7\xfc\xef\xeb\x04\xe1\xa35\xc8k\x14\xcdf9\xdd\"qB\xf3\xc2\xd6\x01A\x9e>J\xf3\x7f-\xf3\xac\xa2>8\x18\xe9\xb3\xacm\x86%\x87$\x8dp~\x94\xce\x14\xa2\xbe\x9e\x0e\xf9Vz\xbe\x97\\R\xdbC\xecSh\xccB\xf7\x11\xc5Qr\x8b\xce\x91\xcd\xca\x80\x89\xc3\xe8\x03~M\xa8\xa6d\xdc\x8f1\xce\x05\x8f\xca\x8a \"~b\x19\x9c\x151)H\xccg%X\x90bF\x18\xc3S\xd3\xa9#\xdd\x16K[\xbbx\x08\xb3\xf4mK\xd9\xdd\xd3\xa5\xdf\x00<\xcf\xd7\x97\xbeZ\x87\xf6\xaa7\xde\xe7*\xff7\xa8c\xd3\x96\xbaC\xb3\xc6\xb5\x88#)\xb9K\xf34\xcc\xfd\xee\x0b\x16\xd1\x98n\x0f\x8a0+8\xd8\xfe\x8a\xbb\x86\xf1Wi\xaf#\xc8\xcai\xde\x9e*m\xae\x16|d\x1aG\xfd\x98\xddP\xab6\xac\\\x83\xb57\xb7\xbb\x1e\xd8\xae\xda\xaa\xa8\xb3u,h\xc3\x9f \x84%\xe5\x0c\xe6\x0e,\x06v`{\xbd\xefNv\xb6^_}\xe7}\x0c\xda\xbf\xb6\x93\x80|&\x11#p\xb8\x0b\xb7]\xd3lH\xe9\x87\xb9+\xf1\xc0\xae\x10I\xeb2\x02\xaag\x12\xee\xdaB\x18s\xe3\xb3\xbe\xc6\xf1\x0e\x9a\x07\x0e \xca\xe4\xef\x04~\x80]\xaf\xb9\xfb\x05\x17\xdbf)%\x03\xd7\x93\xad\xb9\xd6\"\n\x1d\xec\x83K\xda!\xe9H\x87\xca]\xdd\xd5\x8d\xaad\xd5Uk\x18bc\x1bV\x83\x1c\x10F\xae\\\xb3\xb6\xf0d0\x15\x97K\xd9\xf0\x9a\xb7\x8f\\W\x1f\xb6\x9a\xbd\x9a\xf2\x0bB\xe7y\xdc\xab\x9f_-\xb7U\xa6.\x9f\x84U\xc6\x18\xfb-\xc6\xd8\x9bU\x07\x80\xc3\x95\xe5J\xdat/\x8f\x87\xf0\xa8\xb9\xda\xfanh\xbc\xdf\xe8r\xc3oCR\xbc\xe1\x0bB=\x974\xd9\xb8\xbe\xe3\xe5Z\x97f>vGd\xd5}\x1d\xb9\x95\xc8\xab\x12\xb2~[O$\xd5)\xeak \x9e\x0c\xc8\xca,\xf8}\xd4n(U\x1b\x89\xfc\x968\xba\x97\xd0\xab]\xbfY)=d\xd3\xeav}\xa0W\xbe\xd031\x82xS\xb0!\x08g[\x15v\xb5\"\xd4 F\x99D\xeb\xa6\xdcoI\xe2\x1fe\x96\xd5.\xda\x85\xa1P\xcd\xb6r3\xf0(\xed\xcb\xfa\x8cK+\xee#\x1e\xa5!V\x97\x99I\xac.@\x1e\xa5\x1dQ\xdd\x006\xa5\xfbf\xc6\xdc\x99;\x1fn|\xb8\xee\xbe\xceku\xac\x11\xd8\xdd\xaa\xc5Qe\xe7\xd7\x8c\xaeSu\xd0\xe9\x9b\x02\xf9\xa0\xd7\xa3\xae\x0c2\xd3FS\x18\xda\xaf\xb5\x06j\x07o\x13:\x97\xaa6\xe5\x80\x91\x19+\xd1p>'Z\xe4\xd0\xab\xf4\xa1#W\x1f\x03b\x17|\x8ekP\x11\xd5\x9f\xaf5\xe3S\x1f\x04\xcd\xdeU\xe9\x8f\xdc;\x83E\xb2\xfe|m\x85\xb6o\xe7\xb0~\xb6\xfbpnt\xca\x80|\xe4c$%\xb4\xbd\xa5\xa1h\xae\x97#\xeeC\x1fe\x8b\xb3\xbaz\x0f\xc7\xc6\xfbg\xd9\x87\xfa\x8a\xb6\xf7\x94\x92S\x82~\x81*\xc4\\]\x02q\xe5\x01W\xd9G\x83\xee\xcf\xa05\x1a\xe5\xc6\xcc\xa0?\xd1\x89\xc6\x9a\x83\xbc\xd0\xd8\x08\xe5z\xda<\xed\xb7>\x8c\xfd\xc1\x13A\x06\xdf{\x81r\xc6+`N\xab\xf3YEl|5\xaflJ\xb7\xf2d\x0e\"\xf4\xab\xcfH\xf8]\xf4\xcc'\xf7\xa2\x10\x02\xe9\xf0\xd0\x07QZ\xfdD\x06\xce\xb2@=\xc6A1\x8c\xbf\xd32\\G\xe8\xd9\x03\xfb\x08C\xfb \xf6\xed\xff\xd5\xea2\xf4^\xcbZuC\xb9w\x94w\x8c\x1d\xfb\x11TPn\xc8\x9fz6\xee!'\xb1\x0d\x8a\x18\x83\x10F\x95i\x10\x9c\xe2x\x0e\xf3l\x9a\xccJ\xb6<\xf6\x85\xc5\xcb,\x06\xb8\x17yAM>\xd0\xe5\xc3\xfd\x10\xd7{\x92\xe7\xef\x04\xf5\x0b\x94O\xe4\x05\xfd\xf1n\xd8\x9a(e\xcd\xee\x00\xba\x02\xd4\xea\x8f\x9c\x0f\xa3\xdej!t\x1fV\xd8?R\x94\xca\x1cL\nK\x14}P\xe9\xeb}\x90]\xe8\xb0\x11\xff\xea5)\xa6>\x0f\x0c\xf2\x9e\xdd\xd8g\xe9\x83\xbc\xee\xb3\xbe\x1a\x93\xbc'^z\x02{8t\x8aU\xb8\x05^\xd0\xf7\x0eV\xc1\xdb\xdd[\xbb>\x96F\xdc\xd9[\xd6\x01z\xa0\x8a\x0e\xca\x11$\xf7F\x04\x86\x9d\xd9\xdc\x82\xbe\xa6\x07e><\x86\xca\x9ck\x192\xaf\xf0~\x17\x1a\x9f\xf0LST\xb4\x1e\xa93\xbc\xbe>&\xa1\xf1~\x80]ik\x90=J\x8f\xb4j\xef\xd5\xb13\x8e#\x9b\xban\xf7\xe0O\x0e\x95\x1b_\x96U\xb2\xc9&\xa8P\xb4\xeb\xee\xd1\xc2\xa7\xc1-\x98\xb4\xfa\xee\xd1\xd0\xc1\xe0\x86\x0c:\x85U;\x1d\x0dh\xc6)M\xbd\x10\xa3\xfa\xe2\x90\xdeK\x04v\xef\xbbw\xa3JW\xf3|5\xa3\x92\xfcA\x8a \x03\x9b\xb4\xcaW\x8a\x81\x9c\xb0\x14E\xe7\xb89\xb2\x06\x9d,\x15\x9c2y\xc9\xe2\xd8\xc6\x08\xe2\xa4\x1eX\x0b\xa6\xcd\xc3r\xce\xc5\xac\xf8\xf30\x8f\x89q@\xa0\xe3y\xc3\xa5\x9aXq\x93\x11\xca\x03Y\x85JQI\xed\xb6Y\xf7NMi\xb7o^\xb7N,\xf3\x9ec\x99\x1ee^\x1d\xda-\xc2y\xe9)+\xab\x16\xc2@\x13\xa9c\x7f8\x98^'\xb2\xa3\x0c\xab\xe6\x0cf7\xf4{\x1f\xe3.\xbe\xffh\xfe\x19\xdb\xf7\x1b\x01\xa5\xb0\x80\xc7P\x90\xb0\xae\xca\x99\x98\x93\xdc0\x95&\xe5\xf0oD\x83\xbc\xd0\xd5c\xa1\xb8\x07T\x97\xd4\x9ah]\xba\xa1\x0d\x04\xd7y1\xa5N\xa4<\xac\x0c\xb8\x02p/Z\xd7\xc1\x8e}\xd0\xf7\x17\xf2i\xcd\x0e'\xfa>W\xf5\x93k\x1d\xff\x07Hj$\xdanH|\x8d:r\x06\x17<\xdc\xcc\xb1V\x1a\xc5\xf8\xcf\xce\xb6\x08K9\xd9Q\x02\x12\xaa\x11\xa2do\xe0\xd2\xde\x9f\xff\x81*\xa9lRz\x95R\x0d\xb3p\xf2\xaf\xd155\\\xa3\xa0\x99\xb2\xf4\xf1\xd2\xb9\xbd\x1f\x88\xd0\x85\xccU(y^y\x9d\xf7A\xb9T7\xe5#\xaa\xe5\xb5;\xbd\x97@x\xff\x83A\xac\x1a\xaa\xa0x\xa7\xd4\\\x8a\xdf\xb5\x7f\xb11\x1e7\xe5p\x95\x05M\x1f\nl\xcc\x8fP\xaa\x0b\x16!\x8d\xe6\xee\xf6\xffq'\xe1\xd6\xdf\xaf\xd8\x9f\x9d\xad\xd7\x9b\x1f\xb7\x82\xab\xef\xbc\xd1\xb6E\x0b\x97\xbb\xa0HJ\x19\x90\x80\xb1\xed\x1c\x92\xb3V\xd0\xc1\xd6)\xcb/P$\x8a\x14\x92\xef\xd6G\xe7Z\xac\x0f\x1f\x9e\xc33\xe6\x9ar^\xc3\xf6\xc1`h\xd47%\xa2s\x13gN\xe9\x12\xd54)]\x96\x8a\xb7\xac\xe3\xaa$\xf7\x90U\xb7\xdce\xf4\xd4)\x0d\xe9\xdd,zd\x8a\xc7\xa1S\xecF\x19-\x8d\x07\xdb\xe6Rp/z\xdf,M\x96\x03\x02\xcfJqj\xe5\xfa\xd1\xa0\x0b\x93\xa9\xeb\xd8\xc65\x7fm\xf7\xc4\x8c\xd6\xf61\xde#W\xf3> \x97\xda\xb6\xf9\xaf\xb7\x8d#\x8a5\x9c\xf8\xddp8\x98\xcf\xd4\xd7\x92p3\xf3\xa6W\xc2\x92\xd0\xd6+\xe7\xc7\xb9E\x12J\x80\xc7\x8b%\xbdC\xfb\x9f\x8az\xc6\xaf\x12N\xf1\x93\xb4\xa8\x92\x89\x9a\x16\xe0a\x18\xcd\xd5:M\x86S\x82O7\x7f\xc2\xb4\x0bi\x9c\xb5\x0c\x8b\x92\\\xe6\x95U\xd5\xc5\xf8\xf2\xfa\xe2\xf0\xa7\xf1I\xc3\x9c\xfa||q\xf6\xee\xe7\xf1\xd1\xf5\xc5\x87\x1f/\xcf\xc7\xc6oj\xda\xd9\xfb\xf1\xf9\xc1\xe5\xf1\xd9\xe9\xf5\xc9\xf8\xf2\xe0\xfa\xe7\x83w\x1fx\x99\xc3w\xe3\x83s\xf6~\x8c\xf9\xde\x1f\x9c\x1f\x9c\\(_\xce\xc7\xff\xbf\x0f\xe3\x8b\xcbF\xca\xc5\xfb\xb3\xd3\x0b^\xfc\xdd\xd9\x9f\x1aYXoO>\\\x1e\\\x8e\x8fZ\xe9\xedw\xa5\"S\x0fD\xdf\xc7'\xef/\x7f\xe5\xe9\xd7\xc7\xa7\x87\xef>\\\x1c\x9f\x9d\xaa\x19\xf0\x93\x9a\xf0\x9f\x17\xcd\x0c\x1f\xce\xdf\xa9\xaf\x17\xef\xc7\x876\x034\xd8\x83\x1b7s\x9f~\xaf\x93\x9d\xb9\xf8\xf2\xea\xb9\xfe%\x91e\x9e\xe9_B\xf1\xe5\xf9S\xfd\xcbJ\x96\xd9i\x15*\xc5\xa7g\xcf^\xe9\x9f\xd2\xea\xd3k\xfdS$\x9b\xfa\xdek\xd0\x8f\x1c&/\xfaT?%\xb6z\xc7\xe8\x8e\x82,\xd30\"\xee\xf6G\xba=\xf3\xc1\x01\xd0\xf1\x96\xcdkc\xad/\xd6Fsh/q\xdd>\x1f+3g\x8d\xaej\x9e\x1c\xcd\xbd\xf5-\xb6\xf9\xa7\x1d]\x18\xe0\x1c\xe0\x03j\xe9?\xb8\xf5\xdbok\x9d\xa1\x85\xde\xc5\xec\xe9\xc2\xf8\xa1]\xe0\x06\xf6\x88\x13\xcd\xbc\xb8! bO_>w\xf4\xc5\xcc\xa9q\x95?\x8b\x86\x9e8P,\xf7?x\xb4\x9f\x86\x0b2\x02K\xf0\xa8%?\n\xac*\x85I\xf9\x97E\xaa[\xfd\x00\x0crL\x80\xf3\xd6)\x89\xb4\x1b\x9b\xfe\x8b\xa6\x0f\x87o\x9d\x1c1\xb9\xddSS\xdcsjR\x12\x16?\xeb\xa7\xed\x83A\xfb\xf8A\xf3q\"\x14D\xdbj\x1c\x03\x96U\x9av\xa1\x91a\x1f)\xdb\xd3\xfd\xbf>\xa8\xfb}\xbb\xc1\xb2\x9c\x9f\xc8\xdd\x08tS\xbd\x87\xcc\x80\xb4\x1d\xfb\x1f:\x03\x1a\x1f{\xcf\x19`\xf0\xab\x10\x96\xdf2\xf6\xcb\xc7\x1d\xbbT{\xbe\x87\x0f\x10eD\x92r\xfe\x96\x01\x9d\xfc\xb7\x18PI\xe8}\xd9[\xdb\x80\x8e\xee= \xce\x9ew \\6^\x0bx\xca\xf1\x1ad\xc3\xb6\xf16\x89\xd9iEd\xbe4\xd9\xa5e\xaen\xd1\x19W\x05Z\xf4\xe5\\|\xda}\xd9\xfa\xb4\x96Ti\x9b\xcc]\x88O/_\xb4\xc8\xdcY\xf5\xa9Ej\xdfI\xc3R\x13\x93{c=\x14dh\x1e\xd51\x04\xe9v\x0ca%w\x1a\xf3xm`\x1e\xd0\x14Q\xfa\x9fA;\xc8\xe6\x18n\xdb\xfcG\xa3\xc8\xaaH\xb5\x12c\x03\x07\xd3(\xc2\x95\xa8\x1be>\x9b\xd8\xa0F!<\xd2\xb5R\x83\xb8\xabF-\x84\xf1\xc9\xbc\xae\xfa\xfaF\xab\xf5\xd0\xc2\xc7\xf1\x8a$\xf3l\xec\xd0'\x13O\xc8\xcb\x95\x84^\xcb\x8bt\xad\xd4\x81\x81\xb3T\x0b!\n\xd3\xca\x9cup\xa9uYq\xe9m\xa9\xe3\xbd\x81\xf3\xe5e\xd3|f)ca\xa0y1D\xb9\xb6Q\x9e\x18\x99\xf1fAS\x8b\xc7\x9d\xec\xbdZ\xbesi\xfe:@\x8a\xd0\x00\x95J\xccz\xbd 4\x14\x87j\xb3\xceS\x8b\xb4\xa2QOm\xde\xda({\xde#\x051\xd6q]r\x81\x8bV\xd7Q\x05\x0c\x95\x80\xc5a\xcb/e\xaa\x8d\xcc\xef\x86\xaa\xb8\xb9;>\xba\xa8\x16R\xc5J\xdc\xa6\x9bH\xab\\zS\xe8\xd3K\xfeV\x19:\xad9\xb8\xc5\xe7\x01\xe6,\xcdGLQe\x937J\x96\x8c\xdc\x99\x10)\x8a\xce\xea\xf8\x95\x9c027g \x85{R\x83\x1c\xd4\x1a\x16\x10\xc3@\xc0\x97/\x90\xb8\x18\xb0\n\xc1\xb6C\x87\xabD\x0bqF\xda\xb1i-\xda$\x1d{\xbez\"h\x91\\\xaa\xa0\x0c\xa7\xe4]\x1e\xc6\xc6h]j4=\xf3T\xf2\xa5a\xf4t\x9e\x8aX\xfb\xe8\xf1-\x0f2r\xcbx\xf6qq\x9fN\x9b\xa7\x8f=)Y\x93t\x042\xa0\x935\xdf\x82\x94e8c\xc4GP\x90\xb0\xcc;\xcc\xe4\xd2$\xc3|\x8b\xb0\xf8\xc4OQ\xf6+`\xc9\xa8\xdb[\xbfmb\xe4 .:\xb3\xcck{\xf2l[\x05\x03\x1d)\xde6\xf7\xc0Uba\x85\xb0\x0f\xce*\xe3\"et\xf2\xc1\xb6VTo\xad\xd0\xe3&\xe0M\xd1\x88\x1bz\xec\xd0\x1fH#}0\xc4\x95\xfb[\xa5\xbf\xa5Hf; a0\xecM\xab\x86d\xe5\x85\xa8\x7f\x7fBus6`\x8f\x82t\x83\xde\xbbO\xa1\xf2\xff2\xed\x00\x8a\x15\xecA\x18L \x8d\xe6\xf6L%f\x12S\xd5\x01`\x98\xed\xe0\xc2\xc0\xe3\xc8'\xaaD\xb2\xb8\xfa)\xec\xc3?\xbe\xc2\x08R{\x91\xa9\xbcT\x14:\xc2f\xb5\xa0\x0fh, 7\xe6mXd\xdc\x91\x84\x98\xa2\xc6:7\xc2tB\x99d\x11\x81\xf5\xb3`w'\xd8\x810\x8b\xe16IS\xb8!P\x90E\xbe&1$\x19\xac\x9f\x07;\xc1\xce\x1bX\x95\x04,r~\x11\xd0s\xc3\xf1|\x0ep\xb6XW\x0c4\x18i>\xedRv\x8e10\xd9\"\x8fI*/ZN\xc2\xa8\xe8\x88*5\xc7\x12\xd5\xcdVO\xee5\xe6\x16C9\xce()\"\xb2\xa4y\x87R\xf5B\x94\xe0\x04\x8cR\xc42\xcaz\x95\xeb8?y\xe5i\xc1\xad\x9dG\xf0\xfb\xf6\xca%x\x1e\xac\x8a\xd4\xaa\xfe\xc5&\x8fq\x15\x11\x83\x88wIFNW\x8b\x1bR\xbc\xcd\x0b\xb4\xcf\xdb\xb7}h\x86\xdd0\x84\xc2\x90\xcf]\xd5\xcd\x0bZ\xd8\\w\xcb\x1b\xb7\x0eT\x8f[\xca\xe8cH>\xac\x8dN3\xe4\x9b\xb0$Gyd\xe5\x1dA\xb8\x00mB\xc8\x08b{\xf6&x\x8c\xa0c\xd3\xb7ac\x04\xeb\xae\xec-\xc0\x18\xc1\xc2\x98\xfd\xab\x17\xd09\xc9\x06\xe8WA\xe3\x8e\x95M\x98\xbd\x03\xec\xe1\xf6\xad\xfc\x1a\xd6\xae*\x9eL\xc1Mz \x0c\xa8$\x02\x0e\xba\xf3\xcf\xcc$\x06\x082\xa3y\xfb\x9f\xe1\x1do\xa6(\xd6t\x0d\x11T\xe5\xbc\x81\xda\x9a\xeac%K\x08?\xcf\xd9\xa4LWi*\xb6\xc8\xcc\xbd\xf3\x95\x14i\x15\xc0\xd2\x96\xdc\xc8\xb5\x91\xbd~ \xfe\x9a'\x99\xeb\x04\x8eZ\x04)\x15FU\xcb\xd8\x93$\xa0\xdcE\x9b\x9c7\x1f\xb5s\x84\x8b iu\xccr\x9a\xef\x93\x89\x0f\x8e kz\xa3?\xcb\xa7\x11\xcf\xaa#\x10\xa8\xfa\x08\xb9! Dc\xbd\x85\x86X\x01\xda\xa1\x8e= #\x13/qV\xc6E\xf1#j\x99\xe4\xdf`9XhWfvS\xaaVr\xcb\xfc`r\xa5\x1dGo\x85>\xda\xa2&\xc6\xd8kZ\xbf\x96\x15Y\xcdh\xc7\nh\x81X\x03\xdfQ5b\xa8\x0f!\x0f\x80\xe2C\xec\xc3\xdc\x87\xb5\x0f\x0b\x1f*k\xdf[\x1f\xc6V\x85\xa1\xba\xed\xdbb\xd0\x86\xc1p\x0bo\xdexP\xde&\x9c\xca\x0f\x96\x05F\xfc\xe2\xc1\xd0\xbb6Z\x14\x96\x04vF\xddk;\xe5\xe7\xd7\xdf\x82\xf2\xae\xa4d1d\xe3\x12\x19\x8c\xf1y7\xdc\xb0\xe7\xa6 a;\x92\x9a\xfa\xd8\xc1\x05lH\xc2\x89\xc9\x8d\x00\x1e\xe9\x05`\x04q\x9e\xfd\x9e\xc2<\\\x13\x08\x81\x0f\x06h.\x0c`\x08\xe4\x99\x0f\xe1M^\xd0$\x9b\x05\xdcaQxS\xac\x96h\xe2\xc1\xda\xb0\x05\x07\x069\x93\xcf\xfbg2\xd3yQ\xc1\xc6\x92\xa2\xa8)d\xc1\xb1N3\x1fi\xe2\xbc\xa2\xf2\xf8P8\xef\x97#E\xaaS\x9e\xa1\xa4\xfc\xade\xee9\x04\x94\xd6\"R\xe8`\xacK\x0dw\xf3\xb6\x87U\x1eb\xe8\xd4\x14\x91\xf0\x12\x91\xf0\xa2\x1fh\xe1\x1bp\xb0\xe9\xf9\x16\xbclz\x86\xe0j\xd3S)\x14\x8au{\xeaw\x99\x1b\x9a\x1el\xf9\xe9\x83[\x0e9\x91K2\xea\x0b\xb6\xbc \xe5*\xa5'\xe1\xd2\x17\xbc5\x83\xf2_\x12:?\xe4\x0e=%\xcaV\xa0\xed\xa5\x0f\x89\x9b\xe2\xf9z\xbfi\x93O\xc5tL9\x1f6\x8c\x96\xd2\x1f\x13[r\xf7\xb0\xaat\x96\xe5\xe6a\xd5\x98\xd8\x19\x83\xa2\xd2\x90\xc7\xc8\xea\xdc\xde\xbb\xaa>bQ\x7f\x10\xbc^>\x18\xbc\"\x05\xbc\x96\x88x9\x9f\xc4\x8f\xba\x88sWP\x04a\x9a\xe2 R\xba\x1e\xf7f\x86\x8c\xcc\x10n\xc9\xf6\x0c\xe4\xa2lO\x9b\xbbZ\"w\xb5\xd4\xcc\x16\\.\xa1\xb8?\xfbdz*l`b\xa0\xe6\xee\xfa\x7f\x1b\x03ez\x1e\xc2T\x99\x9e{3Z\xa6\xa7\x9f\xf92=\xa8Pm`\xba\x16\xd2\xbd\xf6\xac>WW\x885\xe3\xf6\x87\xb4\xfa\xd0\xa2\x83\x1e:\xbd\x15f\xef\x94\x10u=\x96\xa3`\x04\xf6\x08\xf0\xb6\xe7A\x88h\xf7\xfb\xfba\",\xe4\x90,v\xeeW\x0e\xd4\xcdX\xd2|i\xf1\x91cz\xba\xa9g\xf9|\xc5\xe8\xf1&G\xb6\xc6\xdc6\xc9\xa4\xfa\xb4\xae\xf0z|)\xa8O5Xs\xd0\xcf\xde:\xba\x07\xfd\x95Q\xc3\xab\x8an\x13\xb8d\x00bW \xd6\x9d\x9a\x9c\x0d\xbb\x93\xab\xcac\xcfR\x9a\xd0\x074\xff\xcf\x8b!D\x84\x15\x9c\xa7\x8a\xc8X\xd4\xd6=\xc0\xae\xf5\xe1\x90\xdb\xc3~\x8e\x95\x83\x92{-\xafxz\x1f\xaf\x8dx0\x10I&>\xed\x06\x07\xe4\xf1\xfaz\xf4\xba\xbbG5c\xf1\x1aO\x87\x1d\xec!^V\xba\xbb\xbb\x9e\xafK\xfe\x02j\xbb{\x80\x8aL\xed\xa1Sc\xb3\xa1\x83\xcb\xc6>\xae \xd3\xdef\x9e\xd9\x9b\x19\x8a\x11\x86\xec\xfe6\xd0\xab\xbb\xda\x87\x89\xb1\xd4\x841j\xbb\xaf\xafZ\x1f\xaf\xda\x0e2\xe0\xd9\xf7\x0d\x9d{\xab\xb5\xc77^\xec\xffM\xc6\xc1\xf4+\xa8\x03\x0cC\xfaV\xf7LX\xbd}m\xdb\x02\xdc\xd3\x11x\x8fJ\xdcy{\xff~\x8b\x8e\x9fT\xd8l\xaf\x99m\x80\xfe\x10\xdb\x1c+o\xfdO\x1a\xdd\xc4\xe2\xc0F\x0cO\xc5\x83\xf7\x1bi\xcb0\xe9[\xd6\xee\xf0A\xa3\xab\xb4\xa5\xcdC\xe4.\xc1\xef\xbd\x84]\xf6X\xdf\xae'\x7f\xf1\xcf\x18\xe9#\x98\x13\xf0\xb058\xea\x9f\x85\xe9\xc2\xf0iS\xb7v\xd3\xbc\xed\xc1j\xae\x03&\xa5_=\xd7\xfc\xb9`'\xb6\xc9\xcd\x81e\xc9>uAK\xc3\xb8\xef\xbf\xe7h\xffv\xaf\xd1\x1e\xf4\x8c\xb6e\xe0\xf8\xbfa\xd0g]\x83n\x18y\xf6\x1e\x9c\x1d\xe34\x8c\x857\xff\xbe\xab\xf9\x96\xd9io\x17\x86*\xe5\xd9Tn\x8aa*{\xf9P\x95\xbd\x95&\xeb6\xe7\x12\xf1\x06\xc3\xf2YOu)\x12\x96\x0c<\x18\xca3\xe7\xe1r$qW`\xcc1\xc5\x1c\x95\x8e\xa8\x05m\xc2\x1e\xacl\x9c\xc1\xfd\xb4S\xac\x9a)\xe6\xec3\xbc0\xe0\xacD\x9b|M\xa6\xe0\xce\xe0\xc9\x13\x98)\xa1\xc7\xf4w)y\xd2\x93\x85{\xd2~\xf1\x93\xa4iY\x0d\x1bBK\x86{\xc7\xaa\xcf\x89\xf6\x1e3\x98\xa5w\xc6\x0b\xcf;\x1d\x07\xb9\x93\xd4\x87\xe8\x8am\x84\x8c\xad6\xd2X^\x17\x9bJ\xd4)\xd9k\xbe~\xf9b\x8d\x1f\x00\xca\xd6P\xcbLx\xc3\x1d\x1e\x0c\xdd\x0dt\x0e\x8e\xa1\xfcv\x84\x8b\xa52\xf9;w\xda\xe1\x9a\xea\x82=p\x0c\xbe\x97\xc0\xcc#\xa0H\x07\x83\xc8}\xa6\x1f\xaa\xc8Lq-\xfa\x91\xcaH\x01\xcd/\xd0\x12\x96\xb1\xcf\x02<*\x00?\x8eQ\xc8\xa7\xbe\xefi\xdfG\xbcP\xca\xfeD\xa2\xf3\xcd\xfcY\x90/\x8fcw\xc6\xefc<\xd4)\xe5d\x96k]\x136\xa97\xb0\x07)l\x823r`\x13\"\xf3\\2v\xb6\xe0\xb1>\xca\xa0D\x1c@\xe2\x0bLro\x90ko%w\xe8_]\x8bjX\xbe\x9f\xc3\" oR\xd2\xa5\n\x05\x18,\x9d\xe5\x1eU=\xe9\x96\x08\xb0\xa5,\x97aDFpc\xcd\xf8\xb5_\xbap\xfb\x08=\xedo\xbf{\xce\xabv+\xf7>\x15t]{\x12\x91\xec\xc35\x8c\xe0\xd6G5^=R\x1d\x0e\xa2\x9d\xec\"\xa0\xf0\"\xad\xa8u\xa2L+\x9d\x17B\x87!\xdfm\x7f\xe7\xd8\x17y\xac\xb6\xfac\x1es\x9c\xc4\x8b\x9bK\xb1\xc1\xdd\x05I\xf9\x9f\x17g\xa7\\0\xed\xb9cT\x8cW\xab\x81=`\x19\xb86\xbc;\xf6F0f\xfba\x8csi\xc8<\x16\x93\x0c\xa3\xf6\xa7\xf6\x86n\xa5\xb0\xa1|\x163\xaf\xb8\x01\xf9\x07z\xe6m\x8f\xe33\xee\xc4\x9bU\x92J2\xcc\xfd\xec\xf9P(\xc4\xa8\xab\x1c\x90\xf5A\x08\x9f\x0d\xb5\x11\xc3\x11\xa6R\x19\xbd\xfeq\xd7\x0d!\xe0\x84\xea*:\xea\x93\x9bG\x99u\xab0\x16m\xc2\xd32\xc0\xbc\xe1\x9bD>_U\xf8k\x0e\xd3p\x97\xcc\xc6u\x01{p\x14R\x12d\xf9mG\xa8\x9bLRg.\xd1\xd5\x05\xad\xd3F\x83x\xc5Qj\xa3\x0d\xd8\x82\x8bj\x0dyO-c4\xa8O}\xf5\x84\xa0\xad\xbfyuJ{\x1a\xea8c\xb9\xf6F\xd7}\x0b)\n.^\x98\xab~m\xccg\x9ei@\x8d$\x0b\xafI\xdan{\xf4aK\xf5\x04\x83\xa3\xaf\x1d\xab\xa3\xaf\x9d\xa6\xa3\xaf\x9d+T\xe37P\xef\x15%\xda\xfe\x96uR\xa0\x89\xd8\x07\xb9b\x9e\xc3}\xfeP\x0c1\xc9\xcb9Wf\x1fi\xdd\xa4\x9bT\xd2$\xc14\xebR\x9a\x0f+}\xd5\x01\xf4;\xe9\xe7\x07\xca\xea\xf6\xdf\x16\xa5\xce\xed>\x0c\xb9\xfa\x80\xe6\x1d\x8b_K\xd8\xa9\xfc\xb0\x1d_W8x\xednl\x8a\xf7\xc9\xed\x03\xcb\xce\x08D\xa6\xa3\xca\x9c\x9d\xd1J\xdb\x9f\x17\xe9v\x12P\x86\xac\xa6\x96N\xccq\x00\x15\x81\xd8\xe8\xbe\x0f\xb1\xfd\xec\x16\x80\xb0\xd2\xb8C\xd4},\x9a\xb85\xb1md\xa1\xfcm\xd1\xbf\xe7\x8a\xdf\x96\xa5\x96\xd8\xa2\xdfb\xd8V^\x92\xc4V\xednS,\xdc\xa9\xa5\xab\xc2\xb4\xd9b\x9fa\x0c\x97\xbb4\xa0\x1c+\xce\xc1_=\xce\xa8H@>/\xf3\x02\xfd>7\xe7\xbb\xb2\xf1\xcd\xdc\x97\xcf\x9ej\x90P\xdb\x087\xbdO\x19\x9b\xb4\xb57@,\x89\x91]\\n\x00\x12f\x11\xbaUD\nKA\x80\xe8\x11\xb4\x80$\x03\xe2\x01\xde\xea\x03\x9b,T\xb4p\xd1\x1f\xeb\x08\x92,\xca\x8b\x82D\x14\x92l\x9ds\x07x\x1b\x16W\x8e\xe4~3hv\xe7U\xd9(\xb9\xaf\x9f+\xcdT\xc3\x0f\xa6CD\"\x19\xb9\x1d\x805Y\x8f\xda{\x8d\xd15\xc1\xb2\xc8\x17 \x8a4YUdX\x9096\xe9\xca\xfcRm\xbe\xb3\xf6,;?\x861\xbc\x17mEyV\xd2b\xc50\xb3M\x97\x11O \x1f\x0f\x1b\x83\xbc\xd6\xf3y\xe7\xc5\x05*\xcb\x84\xbe\xe5D\"\xa3~1M\x0b.\xf3U\xb5;\x1c\xb4t\xf5\"}\xbfcZ\xa4\x01bB\xd4\xb0\xe3GW\x921\xd8D~\x9aLrv\x16\xe3\xbf=\xa0\xec\xdf\x08\nVG\xee\xe3\xeb\xbf\x04\xf2^>\xdf\xb5\x8c\xaax\x8c\xea_\xbd\xb0\xd4\xce@M\xd7g\"\x9f\x97i\x12%t\x04\x13\xd6\xb1\xe7\x8c\xe0u_>\xff^\xfc\x7f\xe1\xa9\xdeP\x1f\xde\xbb\x0eJR\x99\x97\x17\xbb\x167\x93\xec\x9b\x8e\xea@\xd0=\x9a\xc7\xca`s\xeb\xea\xbb\x91\xb7\xef~\xdc\xfe\xb8\xed\xed\xbb\x93\x8f\x17\x1fK\x0c\xc9\xd9.\x1eb\xf1\xc9\xc1\xd6\xff\x1f+\xe0\xffw\xb6^on\x05W\xdf\x8dX\x05\xdb\xedB\x8c|\xb1\\\xad:\xff\x86\x9e#\xc3r\xae\x87\xf3\xae\xb3\xec\xb3,\x7f[\x91\xe2\xce\x9eg[\xfatDG\xca\xd6l\x7fd\xd9\xc2\x15\x92x\xbb\xb6\\\xa7\xe1)\xeb\x13\x8fH.\xaf\x86w;\nl\x8f\xdc\x8f\xf1\xa6\xf7\xef\xdb\x18\xc8\xbch\x14\xebo\x04{\xac5\xd4*c\xa8\xa6}\xce\xc9\x87M\xe7\x08v\xcd-\xe3D\x8e`\xb7\xf5Q\xf5# \xaa\x9b\x8d\xd4\x8e\xaf3\xaepo\xb3\x94C\x015\xfa\x83s+\xc3m\x1a\xa4\xe2\xd4\xe2\xc2@\x8bp\xd5\xb9I\xf3\x9b\x91#d\x9e\xcb\"\xa7y\x94\xa7\x1e\x87{v\x96\xb8\xab\x8c\x94Q\xb8\x94\xbc\x13\x9bF\xcf7WH\xd2\x92\xe8\x8e\xea\xf6t\xf7\xd8\xf2A<\x981\x1cX\xb7E\xb0b\x1fJO\xeaz\x14\x93\xcc \x91\xac\x1bR-\x99\xad\xda\xd6uS\x84\xa1\xdb$\x03\x94\x90\xba\xacr6_\x93LG\xaf\xf2Ql\x14\x8a\xa0L\xc3rNP\xfc\xec\xd6o\x8c\xb0\xa5\x9cQ\x9f\x17dj\x8a\xfa\xd3J\x91\xbc\xe9\xef\x9a\xd9\xccp\x11u{;\xad\x02\xfaZ\x89g\xf3\xa4\xc8\xb5\x1e\x01\xe5\x0e\x9f\xd9\xbf\x80\xe6\xef\xf2[R\x1c\x86%A)\x8fc\xb1v\x17\xa3\x1f\xc1\xc6\x06\x9d<\xb5\xec\xbe\x82\x94\x94U\xff\xac\xbd\xd1\xf4+V\xf3\xd0\xa7\xb6C\x14*J\x8f\x1d\xf1*\xb17\xad\xbdPW0E\xcd\x82\x176\x83\xdc\xec\xa9\x94\x1a\xf7sn\xc1\xb0\x12\xc1\x91-\xdc\xcc\x02j\x97\xdd\xe6\x1c3\x96c\x9eX\xb8\x8a;\xd8\x83\x9dv\x7f\x10L+\x88f\x84\xd3\x02\xad\xf5\xe5f\xaaR\xb8=\x8e\x8f\xcb\xcf\x1d@s\"B \xfe\xb3Q\xf50\xabJ\xe4\\\xcc\xe7\xf1\x82)RH\xec\x9c\xdap\xd9q\x13\xb9\x84{.\xf6\xbc\n\x0f\xe0\x85H(A\xdd\x87Y\x03\xea\xe5\xef/_ \xe1\x1eu\x95\x8cU\x15\xc8\xf8\xc9\x17DL\xea\x9b\xe3\xf8\\l\xc1h7\xea7ku\xd7\x93\xa7l\x83N\xb6\xdd\xe0;o\xbbq\xf4xo\xe0\x0e~\x80\xb5\x10s\xbc\x81\xbb\xcdM\x0f\x91\xb5\xcbx\xd8\xf5\xe4\xee\xca\x9b\xec\\\xf9\xdc\x12{\xb2{\xe5C\xc9f\xa5\x84}\x98M\xe6\xb8\xef\x19|\xb7]j\xb2\x1c\xff\x8f\x1b\xa3,@\xfaX.=~\xc9\xe1dh\xfe\xa2f_\xb2>\xee\x83++\x15\xa0\xb3#tT\x95\xa4\x1861\xb7\x87A\x87\xb5\xfczf,\xcfs\xc6(\xfc\x15\xbb\x9c\xf7C\x14\x8eq\\z1\xdek\xcf\xf3\xe5@\xf1\x9f\\\xa5\xe5\xe4\xd9\x15\xae\x96Hd+\xb0\x9c<\xbfR\xebe\xff\x9a\xa8\xc0\xb0}8`\xcd\x02<\xe9\x90\x14\x12\xbf=\x84+\x15 @\xf1c?\xab\x8e\x91 \x9a\x87\xc5\x01uw\xc4\xdc\xea\xdfy\xef8GQ\x9f=\xa2\xd5*\xd3\x00?\x11\xa0\x92\xdd\x18\xe9\x0c9\x14g\xdb\xf1\x82r\x99&\xd4\xe5?\xe5\x0cn\xedz\xd2a5Q2x\xbep\"\xc1A\x8e\x1b\xbce\x93\x02\xb6\x18\xfd\xc1\xb7\xd2.7s\xdby\x03\xc5\xd6\xd6\x1b\x0f#{\xe0M\xd9\xa4\xb8B\xcf\x19\xac\xba\x08#\x13\xec\"~\x0d\x9a\x19\xdcf\x0e\x1fB\x06\xd6#\xee\xb7\xc3\xdd\xa9\x03Z\xb8 \xf7j\xe0C\xab\xc4\xd6V\xb7\x94\x19\xd7&\x0bVY9O\xa6\xd4u\x1c\xcf\xc7~\xb2\x89\xceq\xa9\x82\xea\xed\xcb\x17\xc8\xb8\x0e\x1cf\xcb\x84\xce\xfc\xb6)\xa2\x8a\xb2*\xbe\xbabl\xde\xd8\xb7\xbc\xa0*f\xe0\xfa\xa93\x19a\x97\xff\xe0\x85yf~{\xc8\xdeV%)\xc4b\xb36\xca\xf26/b\xfc\xcc\xbe2B\x13\xa7d\x89\xdf\xd9\xab\\\xb5Q\xab\xfcr\xb2S\x81}\xa3.\x86#\x04\x02d_\xf2\"\x99%\x19oP\xc1\x86\xa2\xbb\x88l\x93\x94\x8c*\x98\x95y\xf6\xd5\x97Mp\xb6\xb7\x1d\xd8\x94\xc5F\xe00|\x8dM3b\x01\xab\xaf/3\xb53Q}\x9b\xf2J\x85)B\x1b\xc4KBG\xbd\xac\xa7|\xf0\xe0\x13'\x94\x19R*\xeb\xaf\xae\x0bh\xae2\xca9\x86n\xa5\xd1\xdeX\x17\xd2\xdd\x84\x8b\xd4\xaa<\xa8x\xa0\x85d\x82\x17\xc9=\xe6_C4{9\xd7\xd0c\xee*Zc0K}H\x14p\xdd\x17~1\x12 \xb2I\x05\xb2\xd5\x95/\x0f(o\xc8Q\x8d\xc3\xe92\xd7\x84\xa1#\xa98\x9a\xa1\xa3I\xf8\x96\xe2\x13\xbd\xb9'\xba\xcbS\xd9$\xcb\x1e?\xc64#O7\xb4c\xdb\xa3\x8f\xf1\xe6\xbfos\x1a\x9a\xb2Yv\x85\xffxe\x0b'\x12!\xd0`\x99/\xdd\xaa\xc3bSS\x81\x96F\x8e\xa7\xcc\xbf\xfc\xa8\x14\x7f\x9c\xc9\x97 \xd17F\x95\x08\xa2\xcd\xf3\x94\xf5\xa9\xa6\xa56z\xa2N\x0f\xeb\x95\xa4\x8d\xfa\x94\xbcQ\x0c\xd0o\xf4=\xc8\xd6\x13\x0dW\xd9\xc4V\xad\x0b'3\xfbx\xe0\x8f\xc0\xf97\xcb\xb5\xb6\xfaHhP(\x82\x0da\x16\x1e\xb2M\x05&\xe5V\xf5\xf9*X\xc2\xc7@\x15R\x8c=\x08~\x8d\x99\xccF\x1f\x15\x05Rr\x02\xa1\x84\x1f`U\x91\xaf%;\xe7\xed\xf3\xcd\xca10ZM\xca\x0e\x0d\x9dT\xd2q\xc9$\x9d\xec^\xb1\x1e\x8a_\x1a5w\x8fnK\xa2\xa1>\x11\x93\xc6\x89\x98\x18O\xc4D=\x11\x13\xc3\x89\x98\xe8'b\"O\xc4\xa4\xa1\xde\xd3\x0e\xeei\xba\x9f\x14\x05F=\xb2o@\xd7vMNI\xf1\xa5\x8f\x04\x89\xf0\x8c\x84\xf5%\xd3\xbb\x0e\xcd\x1b\xca\xe5\xd1v>\x0f@\xc6\xc9\x95\xe3\xb7\xd0e\xd8%1s\x85\xdc\x04\x85<\x1c\xb7\x18\xa9\x88B\x07\x81\xb8;\xfa\xc4\xe3\xb4n\"\x1d)\xd0\xcb>\x9f\xf2\x91\x1d\xf9U\x97\xfc\x15\x9d\xc4 \xcc\xcd=%\x8d\x11\x7f\x15\xb9T}\xe7\xc7H\xfd\x05I\x7f\x96\xfeGG\xfe\xcc\xf8J\xf3\\\x92\x10\xcf\x87\x8d4X\xa6\xabY\x92\x95\x93\xec\xaa\x0biR\xb9\x86\xe35\xc9h)\xeby)\xeaQ\xab\xe9>5\xe4)G\x03\xb2\x167\xab\x1d\x1e\xad\x14D\x9fd\x10z\xb0r\xc3Iy\x85\xeb\\z\xb2\x17\xaf\x1c\x94;\x19<_\x82\x11\x17\xab\xd7\xb4\xed\x95\\\xd9h\xfe\x94w\xf94\\\x90\xa3\xa4\\\x864\x9a\x0b\xedd\xb6\x19\xcen\xb3\xcaP\x99{\xc9b]{\xed\xa0*BGY!8m\xceA\xad\x8f\xb1\x9c\x87%\x89\xcf\xc9,))\xd7q`uhS\xc6A\xcd\xb0|\xd5\xfc%l\xfe\xacR]\xaeS\xab\x0d\"\xf1<(\xdd|\x92\\\x89\xe9\xe8\xd9\xe9P\xa3?=\xae\xed\xefLy6HPh\xc3B\xfcR\xba\xed\x0f\xa2\x07>c\xd3;\x17\xaf\xb4/\x9e^'\xbfB/\x19\xf5\xc1\x17kwg\xa7\x02\xe7\x8e\xccH\x06\xb7s\x1c\x91%\xc9b\x92EI\x95M\x01\xf1Iv\x15\xc4J\x0ee\x10\xf2\x97\xa4K\x9a\xfd\x16\xfb\xaam\x95e\x83\xa7\xb6\xda\x91e,\xfd\x19\xd5!\xb5s/\xf3\xb2LnR\xd2\x82M\xe1\x01\xa0 \xa1\x19;\x9e\x10y\xbc\xc7\x11a\x8c\xc9>\"#\xafVf\x97\x9d\x81u0\xba\x8a\x83\xe7\x92&~0\xb0\x95\x0bu\xd6\xbf\xa7\x1b\xe5\x8fw\\)e\xc0M?\n\xa5,\xb2f.\x0e\xc3k\x11\xeb\x0e#m4\xd1G\xa7\xe6\xe2N\xc5\x8e!\x133\xeeI\x10\xadH\xb9\x93\x8b\xafr.\x9f\n\x9c\xc4\xf3\xe0\xad8\x17\x80\x0dD\x9fH\xa1\xf6L\xf4\x8c\x88 \xe6\xc0\xf66/p\xd2\x87\xce3 \xe2\x06T\xb7\xc7\x8flUk\x13V\x17\x16\xf6\x1d\xdc.\x84\xb2*\xb3[g]\x1b\xc3\x86\x8e\xbbNqn83\x08\x8f\xcb\xa7\x02)\xd4\xac1`^\xf9\xe0\xc9\xaeC@\xd1 V\xa0\x80\x96}\x96\xb2Iq\xd5\x01uP\x1f:b\xc2\xdbQ\x85\xe4\xd3u\xfe\xcaG\x92\xcd\xab4\xed\x82\xaa\xeb\x82\x94\xa4\xb1}Gv5Nh\x11[\xb9\xb8\xe4A\x8fg\xad\x8d\xc3\xe5\xe1\xe2\xb2\x94\x91]\xed\xe1Wd\x8e\xe4'\x8c\x97O\x12\x88\xedg~\x1f\x12\xa1\x1e\x0f\x9e\xdb\xde\xd7\xa2{\xd4\x88\x13$Yk]\xd6\x8evC\xbc>\xf6\xa0\xd0\xdb\x0d\xd5v\x8bI\xd8\xbc\x804j\xd9\xaa\xf4;_\xcf\x87S\xe9\xdc\xa3\xa2\x99VG/\xd0\xee\xd3\xdd\xa7\n\xdd+Hw\xf7\xb51\xfe\xc6\xaaC\xdd\xad\xa6\xb9P4\xfc\xe5\x0b8\xab\xecS\x96\xdff[\xb8\x8e\x9a\xf0\x85\x04\x11w\xe9p\x19\x163B\xf1biF\xe8i\x1e\x93\xb7E\xbe8\x16\xf7\xa8n\x81\x97\x84\xfb\x10\x06I\xb6\xce?\x91?\xad\xc2\"&\xf1a\x98\xa67a\xf4 }Cp\x7f\x99\xd8-\x82W\x14\xe6\xbcU\x16\xdf\xd0zc\xef4\xa9\x8a\xb6\xdeER\x8e\xb38)\xe7}\xf8X\xecK\x87\xe6\xcb\x93|U\x92\x0fK)\x94b\xd3C\xf3\xe5e\xbe\x8a\xe6\xe3,6%\x1f\xb2\xf1\xa7\xe2K\xd7\xb6N\xca\x93|M\x1e\xd0\x1dV\xcc\xd4\xb2\x92\xde\xdd\xee\x05\x0d\x0b\xfa\x80\x86\x8f\xf2\xdb\xcc\xd40\xd67\xa0e\xa1\x82{\x94\x14$\xa2\x129\xf4u\xa2>\x1c\xaf\xe5\xe9\xf8.))\xc9\x88M\x0b;k\xe6\x960i\xc0\x03M?T\x94\xd3\x10\x8cXx\xe6\x18\xa1\x8dA\xb4\x19\xde3\xcf\x18\x18\x18\x14\xfc\xc4\nS\x97\xd83J\x95<#\x90\xfb\xc6 0}\xac\xc6[},\x06-\n/M\xca\xe36\x95j\xb9\x16]WV\x80C\x97\xa6\x18\xbc4\xec\x9c\xd5\x9d0w\xe8\x01I4\xb6\xf3\x06r\xf8\xa1v\xd5\xfc\xe4 l\x90 )\x19b\x0fg\\[\x9e\xe6\xcb%\x89]\xef\x0d\xe4\x9b\x9b^\x8d\x1d'\xf9\x95\x0fE[U\x12\xa4\xc2\x10^X7\x90\xa9!\xe3\x03W\xe9!K\xc4Fr@/\x8b\xd5`J\xbe_\xbay\xff\xed\x06\xf7\xdar`\\[\xdaI\xbc)\x84!\xbf\x19\x87\x1f\x1a7\x7f\x1d+\\lnv;\x18B\x8azR\\\xb1Ue\xe4\x9f\xa2\xfd3)\xdajG\xa0\xdc\x15\xa0\x87\xe0'O\xd8\xa6\xe6\xc1\xb3e\xc1n!\xa9\xbe\xd8Xe\x97\xfaU\xe7\xde\xee\x847\xda\x05U\xf3\xb0\xac!\xaa\x0f\x80\x14\xf1E\xbb\xbd\xaeV0\x9e7\xef4C\x98\x0cq\x0el\xab\x08\x0ce\xf5@/\xed\xd6t\xd4|\x9f\xd6Zh\xbd\xbb\xb5\xa4<`k\x81\x0e#{\x91\xa5\xe4\x18\x82\xba\x14\xcf\xdb3\x9ew\xf9-Zw,\x16y\xf6\x90\xe6,U\x0cj\xfb}\xc8\xce\xa1{\xce$6\xd9,\xd93\x8f\xb4\x08\xd7\xa4(\xc9\xe5m\xfe\x9e1\x8c\xc3\x14\x11\xaa\xe6\xf4\xe2U\xa1!m\x8e3J\x8aw$\\\x1bZE\xd7\xe6FYu\xab\xed\xba\x1a\xadp'\xfc\xa0\\&\xc93\x93g\x0f\xfe\xf10_,\xf3\x8c\x11\x03\x05\xe9]\x00\x90'l\x1b\xbf\xb4Q7\xaf\x9fU{\xc9\xc7\x10\xa6C\xea\xcf\xcd\xf5\xff\xce\xfcfa\x8f8\xc6x8{\x042 U\x95\\\xf1:\xb9\x0dd\xcc\xb1\xaah\xcb\xa4\xa33j\x14kUQ\xa1\xc2\xc9\xee6\x86\x02\xe5^M\xe3FL\xccN\xcb\xca\xac\x9b}je/\x08\x1a\xca\x1c\x86\xab\xd9\x9c\n\xd7\xe1\x9d\xb2\x02v\x8aY\xcdr\xd6\xc2&\xd4\x12\x14\x86\xdb\xe4\x14\xf5Y\xf4\xadp\x91<\x1c.\xcc\x164&n\x97S7\x94\x13\xd7_\xbe\x00 \xca\"\x1a\xa7dA2|\xbfM\xb28\xbf}\xa3O+\xdb\xef4@\x9b\xaer\x99gq\x92\xcd>\x94D\x96\x93\xfaG\xd6\x1c\x9e\x0f\xcfxh\x9c \xcbc\x82F\xfd\xfb<\x8c\x1c\xc9\xf0\xe0i\xe8(|\xab5\x8e\xd0-t\x9f\xaa\x163y\x10\x85\xd9\x87\x92\x1c\x9d\x9dT\xe0\x1b\xe7\x11\x1a\xef\x06\xc9b\xc9{\xca/'\x9f<\xb1}\n\xe6a\xf9\x96\x84tUH\x7f'\x1b{\xd6z\x94\xcc\xae\xe3\xf8\xa8\x1d\xdc\x98\xd9\xed\xef\xbekB\xcdwp8'\xd1\xa7\x92Af\x98q\x81?$%\x94\xab%[_\x1e\xc0\x89\xce \x08.IP\xc7\xe82=['E\x9ea7\xb4J\xf56N\xcf.\xc7#\xb8\x9c'%\x8f\x0f\x95\xe5\x14n\xf3\xe2\x13\x08\xa3\xbd\xf4\x0e\xa9\xce,\xcf\xb6f\x8c\xc6I\"\xde\x13\xd6\x8fh\x0ea \xbf\xf1H\xca\xbf\xf9z\xd5\xbf\xa1\xb8\xee7\x1f~K\xf30f\xff\xd1\x08\xfc7\x1f\xa3Q\xfd\xc6\x1ds\xfc\xd6\xd7\xc1\x1f\xf3\xa2\xc8oK\x98\x16\xf9\x02N\xf2\x98\x14Y\xf2\xf7\xa2\xaf\xd4\x1f\xd1^\x14\xfe\xc1\xb5\x0f\xbe\xd6\xd7%\x17\xab\xe94\xf9\x0c(D\x84L\x98\xaf\xcf\x02p\xa24\x89>9z\xbdUE\xfb7y\x9e\x920chq\x89K\x8e\xab\xc3\x16\x07\xd7@$\xa2\x9c\xb7\xb1J\xed\x1a\xa51AU#c\\dE\xedenW\x90\xb036\x0b\xd3\xd6\x874\x89HV\x92z\x9a\xe0Y\xb0\x13\xec,\x0b\x02\xee\xe1\xaa\xa4\xf9\x02~\\%i\xec\xc1\x1789\xbe\xd4\xcao7\xde}\xbb-\x9e\x8eL\xd0~@\xddS_\xbe\xf0[\x82\x0d\xd7 \xe3\x18\xe7Z\xd2\xc8\x0e\x83Z\xb9GjVA\xbfY\x91\x1c\xb5\x93g\x0el\x9a\xfc`\xa1PP\xad\xecM\xbbOF\x92e-\xae\xa0\xab\x8d\x1a\x15$\xa4\x12=\xb9N\x9c\xacM\xea\x1daP\x12z@i\x91\xdc\xac(q3\x1f\x84\xb3\xe47\x8e\xd0\xfe7\xaa\xc2\x84\x93\xcc&2\x05\x85\x9d@Mb\xae\xbdr;'\x95\xd8\x0c\xa4~\xf2\x10\xac\xc2\xef\xe6\x03^\xde\x07\xe7Y\xb0\x83\xaa\xd6\xc9\xa3!\xd3\xd6\xd1}\x90\xd2\x118aJ\xffL\xee\xf4\x90\xbayF\x8b<\x1d\x81\x13\xd1\"m\x7f?!4\x1c\xa1\xdb\x82\xb0\xfd\xf1b\x9eLY\xcd\xa8W\xcd>\xd7C\xb0\xd0:\xb6\x03\x0e\x0dW\xb3\x90&k\x82\xf3\xd3\x86\x12\xf43v\x92\xc7\xc94!\xc5\x05\x0di}\x8d\xd4\xfe\xd4bO%\xa0\x16\xad\x1b\x83\x8aS\xc43dc\x83\xaa\x90PC\xc1\xb0\xf3\xbau\xcd\xf2\x08K\x99\xb9\xaf^\x1b\xd4_2\xf7e+=\xe1j1\xbb\xdcv\xf4\xd9k\xfc\xf7t\xf7\x95\x1e\xfd\x9a\x8b\xe4w\x9f\xeb\xe5W\x98\xfe\xec{\xb3X\xbe4b\x151d\x93h\x92S\x18\x93\xdd+!\\\xa7\xe8\xb5\xf8\"\xb9I\x93l\x86\x1eu\xa6IQ\xd2\xc3y\x92\xc6\x86)_\x8b\xab\xf6\xc4\xedc\xafH\x90d%)\xe8\x8fd\x9a\x17\xc2\xb1D]\xa1q0\x91\xad\xaeB\xd4\xc58\x0dQ_\x8b?3\xe94XM\xb7Z3\xb3ob\xdcl(07+\xeaTaK\xec\x840\x8fI\xa4\xcc\xb8]\xb8\x95\xba\xdc\xee\xba\xe0\xd7\xf7\xdc\x82\xbdCk4\xafh_\xf5\xd1\x88g\x1c\x1cZ$Q\xb4\xdaA\x91s:l2\x97\xd6\x03l\x88\x1c\xae\xba\xcf\x9d\xec\x1a\xee\xdfb\xac\x1b?\xef\\\xf1;v\x12\xf0`\x9b\x08\x89-\x0eK\x0355+\xed\x1eFl\x83\x89\x8e\xe5\xab\xc4\xef\xddK\x87|P\xcfR5\xfbZ\x0cc\xfc\xe6\x0861\xa3\x15\x8b|U\xa6w\xe7d\x99\x86\x11a$?\xe3\xe3N\xc2\xe2\xd3j\xd9DS\xeb\xb6k\x8c\x9e\xf2-\xef \x05\xcfuD\xd2d\x91P\x12_\x92\xcf\x03\x0d<\xe4\x84\x11\x8571K~\xf9\xbda\xe7\xb4\xe6\"\x1c\xe8>\x17\x9e\xa7n\xe1\xeb\x14\x08\xeb\x19\x8a\xf6\x18\xe4\xe4x=\x02\xfb\xe0\xae\xf0\xde\xcf\xf3!v\xf9u(E\xd5||\xeb\x95]-\x8b<\"e\xf9\x01=\x14\x97\x03\xc4e\x0d\xeb\xae\x9d7\x90)\"\xe67\x90\xd9u\xab+\xf0\xb2\xea\xabHS\x98\x02oXm\xf5@\xa5]\x7f|z1>\xbf\xbc>98\xff\xf3\x87\xf7=j\xf6\x88u\x0b\xe9\xd8\xc7\xe7GJ\x11\x84SJ\n6\xa7}\xd1\x0d\x06\xd9\x05\x9c\x9c\xfd<\xbe\x1e\xff\xe5\xf8\xe2\xf2\xf8\xf4O=\x1d\x9a\xf2\x0eL\x85\xb8\xf6\x9f\xd4\xa3\x8b\xf1\xc0\xf9 \x1b\xf3\xf3\x18M_\x8e\xffry}xvz9>\xbd\xeci|\xf5\xe8\x8d\x9f\x8fq-N\xcf\x8e\xc6=m/\x9b\xeb0T\xc9\xe9\x9e\xf2\x9a5\xa6>\x88\x1a\xb3{\x01\x9a\xd3\x05#\x9f\xe7\x94.G\xdb\xdb\xb7\xb7\xb7\xc1\xed\xb3 /f\xdb\xbb\xaf_\xbf\xde\xfe\xcc>kd\xf3\"\xa4s{\x99W\xdb'!\x9d\xe3\x9f\x93wZ\xc9r=3\x16{\xba\xb3\xb3\xb3]\xaeg\n\x01\xfe8C\xed%u\xd5\xe8\xe9\xb5\x0d\xf6\xc9\xc5\xc1r\xc9\x10(\xfe@S\xde\x0f\x19\x0f~\x1f\x85\xe9[y>*\x94P%\x826\xaa\xbfvV\xd3\x1f\xd6N^L\xa9\xad\xb4aI\x17\xac\x8e\x1e\xdb\xdb\x8cQ\x8d=s_\xed\xbc4\xd0\xf1\x99\xfb\xf4\xc5+\xcf\xcd\xdc\x97\xdf{AR\xfe\x1c\xa6I\\\xc9\xe6\x1a\xb9CE\x19\xdee4\x7f{\x12nV\x94\xe6\x99\xd9\xaf_4'\xd1\xa7\x9b\xfc\xb3\xf9k\xb2\xc0\xf8\xfe\xa6O\xf3$\x8e\x89\xa5\xd2\"\x8c\x93\xdc\xf2\x89\xa0\xed\xa6\xe9S\xb9\xbaY$t\xd4\xd2L\xb6i \xe9\xeb\x8d\xe2\xee\x0dv\xc8\xe3\xa0H\xfc.\xc9>10\xac?`x\x04\x99\\\xb8\xce\xab\x97N\xaf\xae\xb2\xde\xcc\n\x95X]\xadR\xa9\x9f\xc8\x93\xf2\xec\x10\xe5mR\xc7\xfc\xd5\xab\x9ev\x0c\xdePZ\xed\x88Q\xf5\xb4\xf4\xba\xd1\x92\xfc\xc5\xc002\x9a\xd2\x8a\x88\x11Ch-P\x18f2\xa1\xa8\x93\x19N\xb8.\xd6\x15\x17N\xcb\xee\xf0\xb7\x82\x84\xf1Y\x96\xde\xf1\xb78)\xc3\x9b\x94\xc4\x8c\xbcb\xfd\x1f\xa1\xcb\n\xe1 \xeb\xd7|%\xc3\x83\xc6\x10\xc2o\xd8\xad\xdfX\xd2\x12h\x0e!\xa3y\x160MH\x1a\xc3mB\xe7\xf9\x8aB\x98\xc1o\xb2\xc1\xdf`\x1efqJ\x8a@\x91\x93\x16$\x8bI\x01!\xb0\x8el\xe5\xac'XC\x00\xc7\\\x90\xc7\xeb+\xe7\xf9*\x8d\xe1\x86\xc0bEY\x171\xd4\xfeo\xc22\x0e\xbd\xf7\xfd\x16\xc0\x19\x9d\x93\xe26)\x19\x99@(\x90\x84\xbd\xab\x1d\xc8\x0b\xf8M\x8e\xf8\xb7\xc0d2n\xd9~$~\xf8\xfc?\xe2\x94\x8b\xbe\xfc\xb7\x98\xf4C\xd1\x97\x7f\xd2\xb4\xcb\xd2#H\x026\xf3\xbf\xeb\xc8?\xb5\xda\x13-\xdb\x9b\x16u\xc8m|\n\xbf\xcb\x99\x11\x94q\xdb\xfc\xbf\xd3J\xb0\xe5\x08\xe95\x9b31\xa9\xdc\xff\"\xe4S\xf8\x8d[~m\x82\xf3[\xd0\x0ckh\x94]::m\x00\xa2Oq\x0b) \x18\xbc/\xf2%\x1aE\x0c\x83\xcc\xa62td\x03^6\xbe\xc8\xa4\n-%\x16\xd1\xa4\xb8b\xc74\xe7\x9a\x1c\x06\x88\x8e/\xee\xeb\xf2\x0e\xcb\xa9D\xf5\x89\x83\xe0\xcd%\xdb\x89\x0c\xfb\xc7\xba5\xedV\xdb\x99T\x99\xafP\xd5\xdeN\xde.u!\x81|zI\xd4&d\xcd\x08\xfdY\xc7\xbe\xa6.V\x9a5\xf5\xf1\xb5\x8f68(\xbc\xa8\x12\xff_\xf6\xfew\xbdm\x1cY\x18\xc4\xbf\xf7U\x94\xf9;\xa7\x0f9\xa6\x15\xc9v\x9cD\x89\xe3\xe3v\xdc\xd3\x997\x89sbg\xfa\x9d\x9f\xc6G\x0f-A\x16'\x12\xa9CRv<\x93\x9c\xeb\xd8o{\x0d{\x01\xfb\xec%\xed^\xc2>(\x00$\x08\x14H\xcaq\xf7\xf4\xec;\xfc\x90X\x04\x88?\x85B\xa1\xaaP\x7f\xc4_\"X\xf5\x8d\x15\xc4\xdf\xee\xfb\xc4\xa6=\x8d\xbd\xeb\xa7\xea\x11\xaa\x8d\x84\xd9a\xf5Z\x1f\x81|\xdd4\x06i)vVn\xc6V\xc1\xb7+$T\x94Ql\xd7/\xe4\xfd\xa9\x1c^m|M\xb3q\xb4\"\xab\xc8vJ\xf2{\xa4\xfd\x10\xce.*\xf8\x1aFI\x10?\x1c;\xd5!\xb1\x08\xe8\xfd\x12|\xa7\xe4\x18\xb7\xcc2\xfb\xe2\x1f*\xf5\x8c\xa9\xc4\xb1]\x88\xa0\xd2f\xa0\xda)cI\xa9\xd5\xa0k7Z\x95T\x15N\xab\xcb\xd26|UO\xe5\x98\xb4/b*\x90\xb3@\x92L\x96\xc8h\x18\xc4\\@\x06\x8f#\x8a\xc4M\xb6\xc1\xc1\xaa\xa7\x95<\xd0X\xf0\x0dv\x06\n\x0bd\xae\xd6\xca%\xabN\x83\xdd\xa6)\x0e\xb9\x8f\x95\x8a2q\x9f\x8e\xcc\x87\x16\x0du\x00\x8f\xb0\x0e\xfeQ\xf0}\x82\xdc*\xda\x1f\xa2\xa0Xa>9\xe5FB\x80N-\xa2\xa4\xba\x9a\xec\xdbwFZl\xb1\x9a\xcf{i\x16#\xec\xc2\xedZE\xadV\xd1z\xff)\xa1\xfb\x89\xdd!%\xb2q\xdc\xa8cjW\x84\x87\x90\xb4\x10\x15\xe1\x04\xc4\x0fg\xcf\x9aK\x08*\x00#\xcd\x8a\xf89\x06Q\xb2\x071\x03\x7f+\xab\xdc\xb3G\x91H\x99\xb9\x95\xfal\xc4\x7f\xa1\xaa\x1e\xffp\xdf\xf8\x96\xd06\xd6\xef^\xc8\xd9y\xc1\x15\x9c\xeb\x0b\xb75\x10\x7f\x132\xa6^\xb7\xd0\xea\x12\x17\x8b\x18\x81'\xab\xaca\x85\xbd\x94\xbd\xceU\xd0I\xd7=\xb7B\x1e\x12b\xf5\x10\x91\x88wUl5\xfe\xe6\xa8^%\xb6\xaa\xc40\x84Z\xfcG\xbc\x8dV\xe9\x9a\xd1T\x07\xff\xc4\x97\x9f\xd8\x9d|\xf7\x89\xdd=\xc4Z\xd17\xcb\"Tf\x1bAV\xac/M\xaa\xbdCo\x08\xdea\xdf\x11y\xd1\x1bb\xf1\xae\x9d\xba\x9bH\xf8\xa3\x80\xfd/\x9c9\xf6=4J\x08\x14u\xf7\x1f\x8d\x0e\x87\x97\x8f\xae\xc3\x0e\xe7\x87\xbaZ\x1e1\"\x96c\xa3._\xc5\x0f\xfdV\xa0\xf4q\xda.\xa0\x1c\xee\xf2\xe2\xe1&@\x11\xe0\xf0U\x8466\xea\xa3\xb7)\x87\x95\xf8\x8dQ1Y/__ D\xf4w\x05\x83S\xbd\x18\x04\x81\x06M\xff\xb0\xff\xe5p7xx\x80V\xf8J\xd3\x8a\x07 \xce\xec\xe2\x8a\xf6\x0fP\x916\x18\xec\x9a\xd7\xe6\xf2z]\xde\xab\xef\xef\x05\x9d=\xda\"BN\xec\xb1\xe4\xbf\xd6l\xcd\x04\xdfP\x8f\xccm\xb7@h\xbbJ\xdb I\x94\x1a\xcf?\xfd\x14+\xe8C\x0csQ\xa9\xb8\xe4\x82\x8ah/z*B!\x11\x014\xb3\x8e@\x92\x04fF\x8a\x8e\xf2\xf7\x0b\xd8\xed\xe3\x95\xdb6x\xe0\xf3&\x86\xc0q5\x93a\xaeB\xf0\x02^\x16x\xa0g\xffs\x87\x16p\x9d\x1fh\xeb\xed\x1a^\xa2\x0e}\xad\x03\xbd\x01\xdb\xed?\xce\xdf\xa6\xeb\xa4h\x97\xa0\xd4R\xd1\xfd\x83n\x86RH3\x94\xdeXH\xfclZ\xdaT\xd77\x89!I d\xaa\xecr\xbb\x08\xed\x8b2\xd9k\xe9\xbc\x88U\xed\xe1\xa9mc\xaf-\x94\x9cEu\x84\xd2\xeeb\xbd\xf1\x8a\xa1\x95\xa9\xea,\x87#\xea\xad\x08\xbf\x88\"\x13\xf5\xcd!\x8c\x8a\xcb\x10\"\xebB\xbb\x11 \xaf\xa51^\x07\x11\x93\x91\x03%\xdej\x03\xa5\xbe)\x07\xda\xecM \x07\xfac\x9aM$-\xe8\x8aM\xf4bH\xe3\xder@Z\xc3(\x98\xf0\x11\x15fJ\x0crH\xf2\xe6\x1e-\xaa\xba!T3\x9aH#\xf4rd\xd8\xf0\x7f\xf0\x9e\x14\xac\xaa2\xbdo9l=\xc1\x82\xa6\xd4\x97\xbf|\x02\x99\x85\xf5_\xd5\x90\x17\x84\x9b\xa2a\xd2\x80\x86\xc9e \xf0\xb0\x0b0\xcfYA\x01\xd2\x05\xc5\xc4 E1[?\xa1\xc0\xf8\xe5\x0b\xd0\x05\x870\xba\x0c\x02\x85\xb0|\xd4\xa6{\"=jy\xe3\xe4\xd8=\x0e,\xa86\x8327\xc7h,\xac7\x96\xc9\x0e\xf9\xf9\xdb\xbe1\xcc\xe5\xec\x0093\xd6\x99.\xf7I]\xc0\xee\xae\x87#\xe7\x07\xea\x86l\xc77x\xc9'\xfe`/\xa0\xb8\x90\xbd}\x9a\x0b\xe1<\x86\xee\xaf\xa9\x8f#\xbd\xff8\xba\xdd\xed\xdeT\xc1\xdeP\x928I\xa7\x8c\x16j&\xf3(\xe3\xa5h/\xccP\x1b\xc0yI_(\xbaU)^M\x0d\x84?ARZ\x06\x0e\xf6\xf8\xde\x92\xc8P\xc0\xcbC\xd8\xdbE\xd5\xc1^\xa9[(`\x08\x1bJ\x9a\x15h\xad<\x15\xd2\xc5`\xf7)y\xdd\xbao\xde\xc2b\x98\xc7\x91`\xa1${si\xb0\xe3k8\x04u\x0d]\xe9V\xeaurB\xfbR\xaf\x81q\x0e\xcb \x80\xf5\xb2 \x86,\xa8+k\xec\xdb\x89\x85\x90\xeae\xde\xc3M\x97[\x18a\xf3\xf7\x18\xaa\x8b\x05|\xdfD\x8dJ\x0fdf,\xf2\x84\xe24\xa15\xe9\xd3\x0c\xe7\xa4\xd4Ex\xb5\x8c8\xa8$\xd2yO\x1a\xf7\xaam~X\x0f\xfe\x9e\xe8w\x01\xc2\x8eK\xf4\x94\x04\xbc\xea\xec\xbe\x08\xb5\xfb\xecI a\x8c>\x83j5\xcff!4\x82\xbe\x93\xbc\xa2\xf7\xe3\xcaJ\xd3\xb2eA&1\xd2a\xe7\xb3\xde\xd5]\xc1\xde\x08u\x12\xcd\xf8b6\x9a\"\xe8\xe5\xac\xf0\xc5\x0f\x0cb\xdd\xe6\xdec\x8e^\x05\x87\xc4\xf5\x9b\xc7yo*\xe6\xa5R \x0e!\xe2EJmm\x16\xba\xc1\xa0\x00\xaam\xfc\x01n\xf2G\xfa\xc6\xff\xef\xbe\xd8\xf8\xfa\xbeG\x94\xc4\xa8\x0b\xc5\xfc\x03\x9b\xac\xb3<\xc6$\x86\xebP\xf8r\xf1\xf7mWB\xb8w\x8d\x8dk\xedX\xc5\x95H\xaabs\xab\x9e\xa7|(\x84s\xb8f\x1c%\xe84z\xda\xce\xd2u\x82~\xbcY\x9a\x16\x8e\x9c\x98\xe6~\xc6I\xce\xa3\xfc\xa3BhmB\xc0\xec`\xf3q\x15\xc4\xb0\x99{\x16&B$fuq\x8e\x01\xcb{ \x94\xfe&u\xec\xc5c\x90\xfc\x1a\x14\xf4}\xe4\xc0\x02\x02\xd9\xd4\xf3\x95\xcc\\V^\x94\xb9\xc6\xa7\xae\xdbb\xdf\xb4u\xd5\x9f\x08\x15\xaar\xd4\xeeyjg|\xd4qV\xe9(\xb9l\x99\x18\xb9\xdb\xaa\xe4w_\xeb\xb2~3\xef^\xa2E\xa1\x19(;\"yH\xc3\x12\x91\x92\xbdL\xf9\xa9l\x9cD\x96,\xe1K\x89\xb9 \x12\xf9\x13\x0fl.\x89\xc8\xdfe.fyh\xf0wE\xc6\x98\xe5\xd8EN\x14\xcd\xb5Y]B\xf0q\xdbh{\xa3\xe8!w)l\xb1:\xc6\xd0\xa8d \xcb7Q\x08\xef\x83\xc7\xa6\xbeD\x08\xefOLY_\xba8\x0e\x1e\x93.\x8e\xcf\x06OZ%\xac\x86k\x04\xce\x06Q\x97\xc0\xbc\x81]G\x19\x17\xf2\xf7\x1ce\\\xc8\xdfw\x94q\xf1\xfe\xc0Q\xb6\x82Cx\x0c\xea:\x9cH\xa2<\x05y\xfd\xbd&iV9\xd9\"\xe4\xb4w\xde\xc8D\xdf\x84\xb0\x0c1\xd1\x1bnKL\xea\x96\xfa\xd7A\x08W\x98kv\x8d\xd9\xe4\xf6\x82\x10\xc6\xfcL\xf1\xef*6\xfbV\x90\x99S\xf4\x05?\x82)\xefo\xccE\xa4\\\xfd\xeaW\x06R\xcfa\x0c/\xe1\xf69\xdc\xba\xb6*\xdf\xa6\xfe\nc_p\xa2,\xa3\xe4/\xe1\x10\xae\xfc\x1b8\x84\xbb\xd1\xede\x08\xb7!\xf0\xc1\x99Z>\xb3\xa1$\x80\xd3\xd1-\xe7\xf5\x974\x11\xe1OI\xc5\x96A\xb7TA\xa0\x18\x9a\xbdf\xbf\x17\xd0\xcfjw\xff\xa0\x9a{\xdc\xb9\xb9\x9b\x0e\xad\x1dtn\xed\xb6Ck\xbb\xed\xad\x9d\ny\xe5\xc6\xbd$\xda\x891i\xe4\x7f\x14\n\xc3\x11\x17K\x86\x80\xd9\xf5&p\x04\x13\x18\xc2i\xad\xba\xe9\xeax/\xcd\xa9\x14\xdb\xc4a^j$\x8a\x10\xbc*\xd3\xb7g\xfa^H\xd3z\x9d\x0d\xe3T\x13Sv\xa5Y\xfcW\x95\xde\x1d\xcf\xdf\xf2\xe5\xf1\x04\xed\xca\xa4-\xda\x0fQ\x1eO\x8e\xd7\xc5\x9c%E\\\xa6bpV\xff1\xcd\x96\xef\xa3,Z\xe6F\xad\xd5jA~\xfe\xbeJ V\xf4V\x19;V\x05\xaf\x97\"!1\x16\x9c\x9c\xbd\xfb\xf1\xf5\xef?~8\x1d\x1f\x7f\xbc\xf8 _\xfd\xf1\xf8\xcd\xebW\xc7\x17\xa7\xf8\x83\xbf=\xfb\xf0\xfa\xff\x7f:>\xe3\x7f\xee\xe2\xcb\xf7\xb2\xbaU\xf0\xe6\xec\xf7g\x1f/\xea\x1f\xe2\xaf\xf3\x9f\xce~\xc6O\xc6\xef\xcf\xde\x7f|\x0f\x87\x8a(|W\x81T\x86\xcf\xf5\x13\x7f\xff\xb1yE\x9f\xca\x92\xdd=\xea\xf2\x1e\xbf\x19\x04\xb5C*\x9f\xa7\xb7\xaf\xf8\xa2\xc6\x1c4\x9d|\x9e\xecm_`\xea\xf9 A\xa1\xa3\xbbE\x1aM\x87\xcdbG\xb9\x16\xdf\xd2;A\xfe\xbb\xf5\xbeH\xaf\xd3u'V\xdf\xd5\xf5\xea\xbe]\x97\x13?\xe3\x7f\xed~\xcb\x18\xa6\xf7\x1d\xc3\x04\xa3=\xaf\x05\xe2\x7f\xcb\x08\xe6\xf7\x19A\x1d\xb1#\x85\xbe\xfdg&\xfe\xaee\xd1\x9ee\x96\x92\x0bV\xa7OZ\x9e\x10nEJn\x13&\x1e\x15\xf5\x92\x8a\x1c{zJ\xacv\xcf\xa26\x89\x89c'{|\xab\x8dW\xe9j\xbd\xf2\xec+\x8c:%\xf0J\xcc0\xaa\xae\xea\xf4\xc3\x13\xc8kT\x9ab\xcaK\x17\xf9\xf1V\x19\x1b\x97\xed\x8fSD=/\xa4\x89\x98gU4\xa0?\x17}i\xc4\xd0S\x17\x97\xd8\xa6E8\xbd\x12\xe1p\x10^\x8d\x1a9\xe8o+NV\x9c\x1c\xc5\x95\x94\xcay\xdcp\xc7X\xb3!\xe2m\xd1cY\xd6XKx\xd2\xf3\xc6\xe8\xf2H\xc4,K?\xb1\x84\xae ,\xa8\xa5[#]e!\xf2RM\xe6l\x19\xd15&\"\xc2E\xb4t\xf8\xfb\x8b\x9b\xb1kV\xf8\xdel\x91\xdeR\xe1\x82d\xc4\xf4uO\xe2x/\xbf\x8d\xae\xafY\xf6\xf1\xf5\x076\xc5\xb8\xcf\x822\x85\xe0E\xe51+t\x063\xcep\x88\x1c;\xbd\x84\xdd\xf2e;\xcd\xcc\xa4\xfe\xea\xe1\x8d\xbc\x9e\x92G\x04\x7f\xf2t\x9dM\xd8P\xe5\x90\xa7\xe1\xc1n\xd8b\x08\xdem\x94%qr\xed\xa8%%\xc1!x\n\x8f\xc4\x91\xbf\x8c\xee\xe0\x8a\xc1\x1a\xddgCXEy\xce\xa6\x90\xa3y\xc5m\x94\x83\x88\x0e\x86J\x8e\x9ce7,\x83\xf7F\x95\xe4\xdf\n\x89ml*\xc2|a\x1eRQ\x9b\xb0C\x0cB\x88z\x18J\x0c\xed+~M\x10a\xafm\x00\xf2\xfb!\xc4j\xdd\x03?\xa2<\x821\x13\x97qH5\x0c\xdf\no\xa8\x1e\xdc C\x88\x88.\\$U\xa7\n\x14\xaf\xf6\xeb\x92\x04\xd6\xb8\x11c\x11X\xc3\xb9\x11\x059(\x13\xab\x91u\xd62\x84\x87\x98\xa0\x9b$Tu.\xac\x8bt\xf5L\x84zu\x11\xb3\xa4x\xedhk\xa6\xd59g\x93\x8c92\x9b\xaf\x9c&\xba\xfc\xb9\xce\xa2\xa4\x18\x8b\xf3\xdfS\x03s`\x1e\x7f\xf2I\xca\xabrp\xa6+\x96K\xfbF |\x16\x01\xac+A\xf5\xa0\xc7\x9e\xa3l.}\x15\xcd\xf7JKy\xc5\xa5 A\xc0\x16p\x04\xf3^\x9dL\x1c\x82\x87\xf2\x06\x9a_\xf2\x1d\x92\xf7\xae\x8a4\n\xfc\xa8\xcc\xf8\xba\xc6\xbbM^\x96V\xbbgEy\x9d\xf3G-:\x89\xfc\xae\x8f\x14 \x87\xb0&\xe9\x8a\xcc\xc1[\xce\xc2\x9f\xa0\x06`*\x97s\x1cs\x08M\x82\x10f\xf5\xf79\xae3\xdf<\xe8\xba\xd5y\xf2\x93r\xf2\xb3\x00\xd3\xec\x99\xf2\x9b\x83&\\\xa5\xd3\xbb\xa1ji\x1d/\xa6\\8{\x15\x15Q\xe0\xaf\x1c\x8a\xcdu\xb6\x18\x8a\xe0\xce\xbe\x87T\xe3c\xb60Y\x0e\xf5\x08\xb8\xc6\x0eD`\xd1\x94e9\xc9\x96\xf2\x07AH\xb2\xcdPR3\xe2N\xdcI\xafB\xb7\xb0\xf9[\"U\xa9\xac\xc1w\xdf\xb7\x10\xb3f\xe2\xb2\xeeH\\l\x93b\xfd\xa9a\xe7\xb0\xcb\xce\xdc\x84\x8a\xd0\xc1\x00\xd4S#lr\xfbL26eI\x11G\x8b\xbc\x9d\xc4\xa5m\xb4\xcdI\xa3\x1eb{M\xee\xb3e6\xd9{r\x83\xb4\xec=\"r~\xc7\x0d\xe4\xd6\xe9\xb4\xdb\x00\xb98\xf3D\xba:\n\xc6\xf6c\xb6hV\n;m\x8f\xb3\xb2\x8fV!\xa1h\xe5\x1b\x8a\x96\xadVt\xd8j\xc57o\xb5\x1a\xbaG\xfa\xbe\x1bO8\xc7\xefF\xf7 f\x08(z\x13g\xd81\xac\xa5\x0e\xa6!8`\xa1\xd5\x12\xc7\xd4\x10\xd6\xee\x9aj\x11\xc7\xeb,\x1e\x12V\x04\xd0\xb8\xc3\xb2\x07\xd8af\xd2U\xf5\xb4\xef\xb0t\x93\x1df'\x9c\xbe\xd7\x0e\xa2\x95\xa8\xff\xdcJ\xb5\xe7a\xb6\xd2o\xe6\xd4\xfa\xbbm\xe3\xbf\xff\xe6\xbc\xff\xf1\xb7\xd9\xe6\xfc\xa5\x8e\xbf\xeaZ\xe4\xc1x\xc7\x99C\x13%\x90\xfe\x9a\x152\xeb\x1f]+\xef\xc6\x7f.:i\xcf\x84\x824\x8d\xf2\xbds\x0c\xae\x9e\xbaR\x15 \xbdh\xbeb\x93\x96\x8a\xabrx-\x15\xa7Ho8\xe68\x96\x0e\xcbQ6\xa0+\xdc\x94W2(}\xcd\xe1\x08\xfe\xf6\x15\x9cR\xc6\x12\xdb\x93\x08AW\xb9\xae\xb7\xb8T-.\xe9\xeaw-\xec\xf9\x95\xd05dD\xa4 \xfe\x8c[4\x97\xb7p\x08\xfeJ\xc3\x07\x1f\xad\xe2\xff\xf65\xe8E\xd3)\xde\x11E\x8b\xff\xe0\xf0\x11\xd6\xfa\x82-\xa3\xdb:%\xae\xaf\xf4\xb2Y/\xce\xcf\x8e\xcf\xf7\xfc\x80\xcb\xb0\xfd\x10\xa2J\xa0\xbe\na\xd2\x13\xb1\xf7\xd9\xf4\x1cul\xbe\xc8\xac\x0cC\xa2\xee\x8c\xcfXV\x08\xeb^\xe2\xbaU\xd1-\x1c\xd5\"\xf6\x89\xa6\xb2\xaa\xa9\xdb@\\\xa6\x9f\xca\xb4\xf4\x87`\x08\xfa\x7f\xfb\x1a\x82,\x0c\xe1\x96\xb2\xe3\xe3[\xee3\x1c\xc2i\xe9\xd1\xe0;\x88\xc89\xd1\xbc\x93\xa8\xf2\xf3|\x85a\xcc+\xd9\xf2\xd1_\xf24 \xa1`\x9f\x8bG\xabE\x14'!\xfc\xee\xd1\xef\x1a\xa8\xbcw\"\x82[\xee\\\xdc\xad\x98g4\xf6y\xe7\xf6\xf6vg\x96f\xcb\x9du\xb6` ?\n\xa6\xb6b\x13\x04\xb5\xba\xa6\\\xb3z3VL\xe6\x8eY }\xfd\xec\xd8'\x18\xd6i\x08\xde*\xcd\xcd\xdb\x0c\xf5\x94d\xf5\x9c.\x97\x12\xfd\x8dc_\xe0i\xe18\xf9e\x9c\x1bt\xf3\xe2`N\xb3!\xac\xfd\xa0g\xbfw}\x9f\xaf\xd2$gD\x03V\x81\xd5\xc0\xd7\xa0\xc7\xf92\xbf\x99[\x02\x8d+\xd3,KYo\xcaO<\xf7\x92#\xf5\x97.\x91B\x1b\xfd\xe5\x0bx\xaes\x0d\xd4\x15\x88\xfc\x02;9\xd5>\xa3\xed X/\xfd\x84\x0e\xcc_\xbe@\x06G\xb0hWw\x83\xa6\xf2v\xd0Z\xe8\xa8\xd2\x86\x8e\xeaqhP\x7f\x13\x16\x85\xa0T\xe0yG\x158\x94\x8c\xc1\xd8=\x00\xa9\n\xb7\xf9zP\xdd\xfd\x03\x00\x8f\xf5\xf2\"*\xd6\xf9\x05\xfb\xec\x9a\x08\x85\xe6\x98\xaai\x03<\xaf\xacQY\xa0l\xfch\x04D\xcb\xc5r\xb7\x89\x9b]\xf5K\xec\x90\x06\xae\xf9\xa6\x0c\x00P\xfb\xc4m\xf2C\xe7\xa6\xd2\x1f%\xdbh!M*\x17\xad#}\x03\x8bL\xa4\xcd\xe6E\x99\xdc\xb9\xc2sp\xfb\x10\xbc\x10\x98H\x16%\xc2\x04\xe0\x0ft\xee\xc5\xbf\xc6S\x96O\xb2x\x85b\x9e\xfe\x91\xf6\xbe\xf6\xa9\xfeA\x93m\x92\x96k\xcb\xf6\x0e\x02\xa0|\x86\x00\xfd\xec\x7f\xf3\x18\xbd\x01\x1a\xd7^\xfd\xf6l\xab\x10\xad\xfe\x14-\x17\x82\x81s\x99\x10\x95\x19\xa7\xc8\xe8\xbb\x98k*\x15!U\xeb&\x12Y\xb3\x89\x84\x91\xbb\xb6v\xb7o\x0d\xac\xd1\xd8\x94\xdedR\xea\x89\xab\x0bk\x0c\x87\x1cM-g\xea\xc6\xc4p\xb2\x19\x91\x0fT\x13X8\xa2^\xcc\xb3\xf46\xe1\xa8\xaa\xd3\x9f 4q\xfe\xb7\xb7\xf4\x8b4\x9a2a\xc8vq\xf6\xfb\xdf\xbf9\x1d\x0b\xeb\x8bs|\xf5\xf1\xfd\xab\xe3\x0b\xfdU3^\x98\x16\xc5\xbf\x14Z\xacUh\x86Flh\xb1=\"\xb4\x11\xa5\xed\x91q\xd2s\x0e\x9e\xd9 *PrH\x16\xe9\xf5\xf5\xe2\x9b\xcc\xd1\x08\xe5\xe5}\xac\xa1\x88e\x93\x064\xf9X@\x8ep\xc9&\x96\xbf\xfcH\xcc\xcc\xd3W\xa0D\x9br\xb2m\xba\x86\x1a\xfd\xbf\x07\xf6\x97\xafK;\xadL}D\x07AG\x03\xfd<\xc3\x8bmi\xae\xcf\x92\x9b\x9aA\x7f!\xcd\x17\x95\xc9?\x92\x1b\xe4e\x95}?\xe7\xbcr\xcd\xe0\x7f\x95\xe6\xc20[\xfdz\x1bq\xc1M\xf5%\xed\xb7e1\x9e\x9e\xd6Z\x90j\xe3\xf1U:\xbd\x1b#\xf6y\xb6,e5&\xb3T\x8d/\xfe\xf4\x9enN2Vx\xbfk4\x18\xd5\x1b<\x7f\x7f\xf6\xee\xfc\xb4\xa9E\xb1\xd3\x9b\x9a\\\xd7\xe1\xc5\xc14\xfe\xe3\xf1\x87\xd7\xc7?\xbc9%\xe6,\xa06\xbe\x91\x08/\xa7\x8d-\xde\xeb\xd8\xbf\xd1\x02\x95R1\xc2\x12\x7f\xb7O\xba\xc2\x0e\x1e\x9b\xf1\xad\x84/\xecc\xb3\xbap\x85}b\xbe\x16\xee$\xfb\x8f\xcd\xf0\xa8\x0b\xe19kjK&b,\xfbf\xf5\x99\x18\xcc\xb3\xc0\xf7\xe2\x82e\x11Fv\xaaWYq\xfe\xdf\x1f]b,\x14\x8c\x9c\x91p\x8e\x1a\xe2\x04\xe4K\xdf\xf4ui\x94\xd2@Sl\xcc\xe3\xbc\xbe-*\xc8:\xdd}Q\xfa\x9a\x87\xca\xd3\xd5l>\xf7\x13\xacdFQ\xe2+u\x17\xc2U\x08c\xe1\xea\xda\xae\xe0\xc50\x10\x98 \x0b\xf3R\x9c\x94\x9e\x8e'V~Z\xf5tr;\x15148\xe4\x1a\xf2\xad\x89J\x88\x9fM\xd5\x80\x96{\x1b\xebk\xdf$\xec\x16\x12\xe9\xa7\xee\xc8\xe7\xa6\x9eMT\xa9\x9b\x8c\xa8\xfbH\xec\xbe\x08\xf3\x13\xf4P\xc4\x10\xb5\xaf\x15B\xdb\x95>K\x07 \x0e[8<\xa4n\xe3\xce\x85\xd8k\xbd?\x11\xdc\x02\x1d#\x8e?\x9f\xe0\x10NF3\xcc\xfas2\xf2\xfe\xfd\xdf\xcb\x8d\x85\xafn8>\x9d\x8cn.\xed/\x8f\xe1\x10>\xa1\xc3\xb4\x7fC\xdc|\x9d\xc1!\xdc\xc0\x11|\x86#\xb8\xf5=\x96\x14Y\xccr/\x80!\x1c\x97~\xd9\xf6g\xe8\xd4\x85\xb1&\x84~\x1f\xfb\xef\xc9\xafyoF\x82@\x8e\xf5\xefQ\x1f?\x86C\x98\xf8\xefeT6v\x0b,\x08\x02\x8c\xe5i\x86\xbc\xe2\xd5\xc7\x98\xb3\x13?\\\xf8\xe3\x10N\xe55\xb7\xb8\x93S\xa8\xa0\xdf1\x8c%\x94\"^}\x16\xc24\x08B\xf8\xcc[\xc0\xbc_\xe5\x02\xf1\x1e?\x89X \xbc\xf5s\x19i\xf4\xb8#\x95\xf9T\x05c0\xb4i8\xba\xef\xbf\x87\xadk\x0c>\x8f[}\xeb\\,\x90\x1a\xda \x0e\xed8\x08a=*\xb8\xa8z\xcc\xff:\xe5\x7fMC |\xa49\xfc\xee\x9c\xf6ObNC\\D\xbej\xb7\xbe\x9a\xa6\xe3\xaeS\xc4Y^V\xd5\x91n8*\xcbU\x1d\xc2\x19\xb1U\xe0\x9a\xdeV(\xd8_I\x1f}\xfc\xff\x84O=\xe6S\xbf\n\xe1ntuI\\\xa8\xa2\x03x\xea\xa7\xbd\xf7\xb0\x0di\xefG\xf8\x1d\x08o\xff\xf3\x00\xe9\xef\x1d\x1d\x80e\xc3(\xf7\xfa)\xb0\x95\xf8\xfb\xfb\xa8\xd5\xddJ\xfc\xc7\x83\xc0\x9dQP\xf6\xf5\x04\xb6\x0e\x1d\x829?\x80\x0f\x02\x99\x9f>\x04/\xb2ds\x10\xc9w\x86\xedDL\xf5f\x83\xdc\xc0\xb6^\xe5\\!\xefg:\x07\xdaxLG\xc9|B\xe5\x85\xe1l\xc1^\xe0[9cd\xb0\x8d\x83A\xe0{\xafO\xc7\xef?\x9c]\x9cy\xf7\x0e\xb0\x11\"g\x92\x92\x894\x84\xc2\xd2z\xbdp\xc5M\xc3P\x82\xeb\x00\x12\x0ci\x89z{\x7f\x8d\xb0\xc0\xa8\x902\xc4/\xf1\xe1\xf32 \x0e\xbc\x84\xfcy \xbf\xe3G\xc0(\xdf\xde\xbe\x14f2\xff\x1d\xfb\x0bl\xed\xcb\x97\xaa5\x1a=\xcd\xa8\xe2\x9d\x17hw\x10\xf4T\nb\x1a\xa4\x99\xb8\x8fP\x95d\xd0\xdd\xcdzq\xa1\x01u\x0bb/\xb5\x8d\x0e&\x1d\xa7GN\x06\xd3\xac\x07\x8btj\xe4$\x8a\x08\xcdy\x8ca\xe8F\xf1%\x0c\xe9\x13\xc1\x0en\xaf\x07 \xad\x97\x1e\x19\x91\xef\xab\xc3hX\xffL\x86\x88:\x82\x08\x86T\xe4\xf8\xce\xd0\xdf\xdb#\xa0\x9f\x8d\xbc\xf1x\x92fl\xe7/\xf98\x9fG\x19\x9b\x8e\xc7\xe2\xa8\xf7]e\x87\xf0\xb7\xaf\xad\x1b\xcf\x01\xd2t$r8\xfa\xa9\xd0\x9c\xfe\xedk\xd02\x1f\x17=\xbd\x9fF\x91%\xeb%\xcb\xb8\xf04\x84-\x7f\x00\xdf\x03E\x01\x94\xf7\xb4\xaa\xb7\xeb\xa8w\x9b\xc5\x85\xaa\xb3\xef\xa8\xa3\x14#\xb5\x82o\xba\xd8\xa9Z.\xb7\xef\xfe\xe3\xc0\xdf\xd2\xb5\xd4\xfc\xddA\xe0\xcbh\xbf\xe0\x89?\xbc\xa6$\x1a\xa8g\x1e\x17p\x08\xd2\xa2\xaeT\xca\x8f\xe3\xfa\xcdG\xe8>U\xf8\x98\x98L}/\xda\xb3!Rj\xe0\xc71I\xc5\x12xyXQ\xc6#b\x15%L]<\xe34M\x98\x9d\xe0\x15\x86\x18\xcc\x0d2\x91\x7f\xa0\x9a\xdb\xf6a\x19V\x8f:Feg\x04\xaf,\xfb\x19\xd4\xfb\xd1\x10z\xc3cr0\xa0\x03R=\xde\xbb\xefv++4\x05\xd3\x8fC\x88\xc4y(\x17>\xf5\x0bS&V\x0f\x1e\x05~\xe2(\x15A\xa6]\xd1\xd2\xe4\x98rx\x01}\xe1\xd7\xfeR\xb8V28\x02\xcf+\x85\x00\xbeP1\xb6\xa4\x05/\xcc\x83\x00^\xc0\xe3\xc7\xbb\xcf\x0e\x90\xbd\x83\x97\xf0\xf8`o\xf0L4\xb4\x0d\x03\xe9\xa8\xc9iKd}\xcc+\x88\x06\x0e\xf6v\xb1\xf3\x887\xf0do\x7fO\xf6/\xeacG0\xc44H\xe2m\xbe\x88'\xcc\xcfC\xec\x04s\xd5D\xb0#\x9b\xd9\xe6\xe3\xdc\x91\x83z\xf1\x02\x06\xfd\x00\xb6\xe1\xe0\xf1\xe3\xbd\x83_v\xb7\x9b\xfa\x11\xa9\xab1\xb1G\x86-3\xe9\xbeT\xd5\x98\x1a\x9c\xb5\x0c\xf1a\x9e\xc6RWs@\xebj\x06\x96ng\"\xeb\x9b\x83\x94\xca\x9a'\xffT\xd6\x10\xcf?\x955\xfa\xf3Oe\x0d>\xffT\xd6\xfcSY\xf3Oe\xcd/\xa6\xacqjj\x06duw\x18\xd1\x03\xc7\xdd\xc9\xe3\xbe\x83o\xd3\xc2\xb3w\x12DQ\xfcL\xdb$\xa5\x0d\xf9\xca\xb7Q1\xef-\xa3\xcf6\xcf J\xe2\xa4\xc3 \xe9\x18\xb0d\xb4\x19\xf2\\}8\xe2b4l\x83\n\xc2\x19\xfb\xcc\x88\xc9\x0f\x1b\xac\x8f\x9e\xc8#4\xb2\x96\xc4\xb9\x9e1c%_\xbf\xceOK\xb9/,\xd27\xe9$Z0)\x1b\x95)Qpo\x9c\xcd\xbc^\xbeZ\xc4\x85\xef\x85\xde\x86\xec\xfb\xde\xde\xaf\xa2Dq\x04\xad\xdd\xa5\x95i\xc8o\xe5+6A\xfa}\x8f\x15\x95\xea\xb2H.hk\xca\x14\xcd\x13,\xc2CH\xfd\x16Q\x923?\nF\xf1e \x13\xef\xa4z\x92\xf3\xeeh-b\x17\x87J)h\xddR\n^v\xff\x89 \xab\\nL\x07/{`\xf2\xc4\x13Zs\xc2Y\xd9\x89\xca\xcdl\xb3\xb0\x93^\xce\x8a\xd7\xcb%\x9b\xc6Q\xc1l~u\xd2\x9b,X\x949j\xcc\xb1\xc6[a4\x7f2\x8f\x92\x84\x19~\x867X\xe3U\x9c\xaf\xa2bb\x98},m\xe5\xe55\x11\xca\xe7\xae\xed@CA\x1e\x0ea\x9b\x9fe6I\xe6'\xcf\xb5\x99:\x85\xce\x90\x01\x9a\xe1\xc5\xb5\x93\x9b\x95A\xd2x\x85\x10\n\x9f\xf0 \xa8\xbd1\xa6s\xd5\xcad\xdf\xc9\\ \xc2Q\xa5\xdeV5\"<\x96\xa7(D\xae\x1a\x9b\xac\xa5\xfd\x18]\n\xad\xed\xe09D\xd95n\xed\xbcR\xec&\xcf\x03\x95C\xa3,\x1d%\xdb\xdb\xe6I'\xf7\xcf\xf5h{{y\xd9\xb6\xd0\x02(\x7f\xe5\x0c&_\x87\x9b^\x92\xde\xb6\xb6\x86\xb5\x9c\x0d\xcd\xe1H(\x13|$\x93\xec\x16\xe6A\x8f\xd3\xbd\xdd\x10R\xfcc\xd0K\x93*\xb4\xf9\x95\x08T\x1f\xf9qo\x95\xe6\x85\xdc\x85Hk\x06\x18\xcfi\xd2\x8b\xa6\xd3\xd3\x1b\x96\x14o\xe2\xbc` C\x9aN.\x86\xd6\x00r{\x93^\xbc\xe4=\x9e\xa3\x17P\xceG\xd6<\xb5\x89>\x06<@=/\x04\xefw\xf54\x07\xf6\x88|ON\xc8C\xaejK\x8c\x1c]\xa5\xd2$c\xd1\xf4\x0e\x03\xee\x89p|(]/|O\xf8&a\xaa\x15\xf7\x88\xf2^\xb4Z\xb1d\x8a\xf9\xe8}\xed\xab\xa0g\xb7\xdc\x86\xc3y/c\xcb\xf4\x86\x89\xc6\x90g\x0e\xcb}\xea\xf4\x1c\x80\xa6\xcc\x959+.\xe2%K\xd7\x85\x86\x11\x9c\xe9\xa8\xbe\x0f\xeaF\xb3\xd6\xf7V\xa4Y\xa4\xd5C\x98VM\xe0_]\xb9\x15\xf7`\x1b\x9doh:\x8a\xeaF\x9a\x1f\xbf\x19\x02k'\x9b]\x1cv\xdc]\x13\"\x1f\xc8\xae\xdb:n\x81\xde\xa6\xec\xce\x13:D\xff\xe0I{V3G\x9e\x8f\x0cie\xea\x17vj8\x91\x90\xa8-\xb5q\xdc\x9b\xb9\xb2\xfe\xfa\xfd\x10\x92^\xc6\xf2tq\xc3\x02\x8cl\x8f\xa9\xfc\x96\xb1\x96\xdfjC\xc0X\x10\x10\x80yF+\x01\x91\x0dDg\x86v&\x90\xe2\x00\xe9|\xf3\x98\xc7\x8f\xcb\xc9Z\xdaT\x91wF\xb2x[[\x9c\xc9\xf3>\xb0\xeb\xd3\xcf+\xa4\x8di-%\xe6\x86s\xb6\xf8<\x95\xb0\x81\x9c\xf3\xe3{\xe1\x82ZN?\xed\xc9\xab7\x11\x9aA^\\\x89w\x9cK\xb10>\"\xc2\"F\xd2A\xc0O\xf0\x161\xeb\x9d\xa3C(\x17ac\xb7\x05\x00\x88l\x9e\xb6\nA&\x8c\xf1B\x88\xee\x0d\xc4g\xae\xdb\x84Zf\x97Nr\xa9\xa6\xeb\xc9\xea\xc9\xc57\x1a\xd1\xee\x9eC\xa69\xd8Cyc\x12\x15\xbe'\xf8)O0\x1dB\xc2\xab\x875\x9e\xd5\xeez5\xbe\xf4]\xb4d\xbf\x8e\x9c\xbdk\"\xa2\xdc\x934~Z\xe6\x0fR\x9aylj\xce\x854c\xdd\x9eKaf\xcf\x14Z\x16.@\xbc\x92\x0e\xc8\xba\xe4&\xe0&lS\x8e`\x01- peF$\xcc\x98'\xae\xf9\"\xbf\x90\xda\xb7\xd2\xccL|`\x1eH_\xad\xaedN\xa5\x92\xf4\xa6\xfeV\xd6\x9bii\xfdB`\xa3\xe2\xb2m\xc5\xcc\xe5Jp\xa7\x96\xb1C\x1el;\xa8D\xae\xf8\xc9\xa5\xe0\x8a-~\xa6\x13R\xb9Y\x94\xd2\xdd3\xf1\x1f\xef\x99\x18Ty\xeb\xd4\xfdr\xbat\xd9v\xed\xf4\xec\x80\xde\xa4O\xcc\xf7\xb1c3\x08\xf4\xb6\xac=\xe4\xbd\x93\x95tGS\x94Ey\x1e_;\xd4Q[\xb8\xb5[L\xaa\x944KE\xb4-\x1c\xef9\x92\x9c\xdf-\xaf\xd2\x05\x15[\x06\xb9\xe9\xe8j2e\xb3\xeby\xfc\x97O\x8be\x92\xae\xfe+\xcb\x0b\x8f<)e:\xd1'!dJ\xbf\xe4\x05\xbdY\x9a\x9dF\xad\xd1\x1a\nq\x86\x18\x0e\xadA(,\xc4r\xe1l\x1b\xf0\x0e\xca\xf3I\xdc\x95\x89\xa2\"\x08d\x98L\x0f\x93\xeeVn\x16_\xeb\xcc~\x9b\xd7\\\x84{\x9e\xc3\xdc\x94rC\xa49\x83PFK\x9f\x85\xa8!\x89{\xb3\xe7\x90\xc3KX<\xb7\xf9\xd2\xb2\xe5\x95\x90=\xd7\x9ap\xbc\xe0\xc2q(\x14!\\\xfe\xf3\xa7\xe510\xf1\xa7B\x98\xf1\xa7A\x88\x8a\x90y9\x86\xa5H\xc2u\x03/a\xf9<\x00I&\xa6!\xead\xe6\xa3eiQ\x95\x8cV\xa8S\x1f\xad\x1c2\xb8\x96a\x0d\x86\xdd\xb2J\xb5\xed\x9eA\x9f\xe6\xd7\x06\xa6nI\xec\x9e\xdd\x03j\xf7\xf8\xbc\xe0\x80s\x8f\xfe`\xf7 \xa8\xd9{<\xc5\xd7\x8f\xf7\x1e\x93)\x1a\xd6\xd4\x98\xa1t\xd7\xcc\xd2U\xae\xb9\xfdV)\xd4\x95_o\xc6f\xb9\xcc\xe2\xc7\x7f\n\xafh\x9c\x19\xea\xef5Jc\xf7\x9d\xff\x1d\xfb^\xd4\xdd\xa8\xd7\x9aof\x9c\x7f`\xd1\xa4\xd0\xf3\x10\xf2\xed\xa2W\xc9e>\xfd6\x9e\xb1\x8c\x85e\xe4\x82wg\x89\xc7\xbc\xbe[\x87e\xca\xf8\xa7\x8f\xbd\xa0>\xbf\x9e\x91\xd3\xbf\xbc\xaf\x0ceD\x05\xa2\xae\xcab\xafR\xb7\x85\xe0\xa9)\xd4u\x06\xfa$gi6a\x1f\xed\x00\x01\xe4j\x19\x1d\xfeX}\xab\x04x\xd6qp,\x04O\xeb\xba>\xbeE-\xab\xf1Z\xcfj\x9c\xd7\xf3#\xb3[X\xd4^\x1a)\x97s.\xd3\xe5z\x03ZkA\xfd\xcb8\x7f\xbf\xce\x98\x85\x15[\xfd&\x95AY\xd3r\xe5\xe2\x8di\xa5\xb9\x86\xa8p_\x82\x92\xf8\xcf\x02\x9b\xbc\x18\x0bc\xf5l\xfe\x90\xae\xafa\x861\x0c\xba\xfe\x07\x91\xcb\x13q\xb5k\x1fjk\x10\xf5+X;nb\xee\xbf\x04\n\xe8z\xc2\xb0\x07n\x9aT'\n^\x84\xef.\xf1\x17\xdf\xb8\xf5_\xbe\x97q\xdc\xed1q\xaf\xe4\xa1\xc9\xf0A\x7f\xd0\xdf\xfb\xc5F\x9a\xf8\x8f\xf7\xefm\x9d\x86\xe2\xd6\xd6`C\xd6\x98\x1eP\xed\x82\xf0\xfc\xf4\xe4\xc3\xe9\xc5\xf8\xd5\xd9\xf8\xdd\xd9\xc5\xf8\xfd\xf1\xf9\xf9\xf8\xe2\xa7\xd7\xe7\xe3\xb3\x0f\xe3?\x9d}\x1c\xff\xfc\xfa\xcd\x9b\xf1\x0f\xa7\xe3\x1f_\x7f8}\xf5\x0d\xees\x0f\xe65O\xc1u\xd7\x12\x0f\xa51\xe0\x01\xed\x92\xf7\xd82\xd0\x92v^\x074\xc3\xbd\xfb\xe4q\xdd^\xf4\xc9\xbe\xfe\xbb\x87)\x13=\x91k\xfe\xbcH3\xe65\x98}\xaa\x05\xed]i\xb3\n\xabV\xd2\xe5U\x9c\xb0\x0fl\xba\x9e\xa0\xd7gkKi\xcd\xdb\xa0j\xe9*N\xa6\"\x8c\xd0 \x1fY\xda\xa9\xb1\xd8\xd1X\xb4Z-\xee\xde\xc6\xd3\xe9\x82\xddF\x9d&\x189Z\x9ap2\x9fwia\xbd\xb1\x1b\x85\xe3 Ps\xe8\xd0g\\\x1bs\xd1\xd3o\xcb\x80\xc9|\xb0V\xf46\x8e\x8aFJO\x92.a\xf4\xb3\xda\xad/\xe7\xb1\x11\xf9\xc4\xb5\x98(38m-\x15\xf1\x16\xff\x88:\x9f0\xa5/\xc5BED*\xe5\xd3\xcf+\x8c\xf9\x00\xc5\x9c\x01K\xe6Q2a\x19\x14)\\1\x88\xca\xe9\xf6\xa8\xe8\x8ajq}\x16\x08C\xd9Z\x0d[+A\x8e\xa9h\x1bS&\xb0\xbf}H72\x99/\xa1g\xc6{j\xfb\xf5\x84pM\xe1\xef\xf1\x9e\xda~\xbd\x92\xa7W\xad\xa0D\x88)\xa9\x8e\x9c\xe1\xda\x8a\x1c(\xe2\xfa[X\xc6\x06&\xb0\xe8F\xe7MVS\x8bNM\xdc\xd0L\x8csAX\xd3\x82,\xd4\xe5]\xebj\x80v}M\xa5O\x95s\x98\xfaA\x08\xb32\x9a\x8dU\x0d\xb4\xa94\xda(\x8a\xd4\xdb\x0d\x15@\xea,\xb6\x06!\xef\xd5\x1e\x91\xfe(\xd9}&\xb23\x9f\xd9W\x14\xe63C\xfd\xc4\x84\xf9I\x08\x03\xda\x8a\x0b\xac]A\xbfu\xad\xe4\xd2\xbd\x92[Y/B;\x02k\xe9d\xf08X\xae\xf3\x82/\x19\xc6\xe2\x05!x\xe5=\xf8\x983\x98\xac\xf3\"]\xc2\xb2\xa4\xe8\xa8e\x88\xf2\xbbd\x02\x91\xf8\x9c\\^#-:\xeb\xa1l`\x0d\xe1\xdf\xca!Dw\x98\xb2}\x1e\xdd0\x88\x12(\x83\x1d\x83\x87jiPvG=\xf8\x89W\xb9K\xd7\xb0\x8c\xf3|\xc5\x16\x0b6\x85\x08PD\x89\x92\xe2\xe8\xdf\x1c\xa3Y\x11\x00P\xa7g\xd9\xfdT\x1a\x804\xce\xcd\x1dFs%E\x1bNSr\x7fA\x9a\xc2~\x85Y\x9cD\x8bEc\x1b\x03\xfb3\x9b|\xe8\xf6\x12\x9c\\\xcd\xc4\xd9 \x93\xa6k\x89\xe1\xb7\xb7]\xc8\x7f#3\xb6\x17\xa3\xc4aD\x92\xb6^\x80\x82\xa6\x92\xfb\xce]m\xe9\x0c\xc8\x15\xf7^\xbf{}Q\xff\x94V\"\xadI\xc3L\xb5hd\xec\xf1|}\x95O\xb2\xf8\x8a\x91\x11\x96\xafKq\x87\n\xf5\"\xe4'\x89$m\x92\x1f\xdc\x9bp\xf2\x93,a\x9f\x8b\x0f]O3\xf5H\x1d\x0f\x05Y\xf58!\xac\x1e*Th})BX\x8f\xd2^\xd4j?sS\xf9)\x11I\xacu+Fz\xb8\xdaJ\xb5C\x1a\x14\xb4 5\x91\x0e\xeb\x8b\xbb\x15\xa3\xe0\x9d^\xc9t\x89\x12\xd8\x8a\xec!\xac\x9d=\x96\xe4\xb6\xddJ\x9f\x95\xf6\xd4\xe2/\x7fn\x9e\xeb\xfaC\x93~@)\xa2\xe1pQ\xa2Ma9\xc3\xeaO\xa3\x0d\x82z\xd6\x89\x06\x7f;l\x90z\xba\x9cQ\xf8&\xe8\x843P\x0d\xcf\xf2&\x01\x81|\xcc\xc2\xc6\xf2\x05\x11)\x87\x0b]\xb4K\xecc\xeb\x0e0&Q\x91\xef\x94!x\xff\xfe\xef\x9c\xb9\xfc\xfc\x88\xff\xac\x07\x93\xff\x06\x89Z\x17\xf1\x1d~i\xd6\x9d\x8d\x14E\x1f\x9bWB\\\x1a(o\xc7\x84\xd8|I\x84\xc2Qfk.\x9f\x87\x9cp\xfa\xad\xd7\x10\x1eh\xa5Mo\xad\x8c\x1f;\xb9a\xb3X\xaf!\x92\xb9\xe2\xb5\x81\xe8\xa6v\xc1\x1c5\xea4\x90{\x89\x91{\x01\xcc\xd7\x8a\x7fm\xa1hS*\xdal^\xbc\xc0\x1b\x93\xc8b\xcbxs\xa8$\xe6\x1cIQ5\xd1\xb7\x9bH\x90\x1d\x17\x8e\x07a\xcd:\xda\xb3mY\xc8\xa3\xca-\xd7%\xba+2\xbe\x91\xf0I\x02^uV\xa1\xf7\x83 \xda\xe3~\xd0\x8bzB\xa3e\x82~cm\xd5\xa6\xf5\x9dkm.u\xc9\xcc0\xf2.\xacP\x97\xc7x_\xa6q9exIq\x19\xa8Y\x83^\xda\x8b/xQ\xc5\x18\x95\x08\xd0|\xda\xd0\xac\x8d\xdd\xf8\x80n\xbc\x18\xf5/I\x04)zBz\xf5k\xb0l\x18AWB\xca\xfc\xa2\x87j\x18\xc9\x80\x87\x15T\x88\x13\xc88\xec\x1fDq\xf8`J\xbc\x10\n\x15\x00\xb9\x8b\xf2S\\\x10\xd5(\xb7&}\xc0\x11xq\x12\x17q\xb4\x107P\n,*\xabr\x91\x82\xae\x9b\x83!\xa6\x1c\xbf\x89\xd3u.\xd3)gl\xc2\xe2\x1b6\x85\xab;]\xffP\x8b\xec\xaakM\xcb\xd1w\x81e\xb5g\x9f8\x9cQ-\xdb{y\xb1i\x1e\x19\xca\x84\x9frG\x1d\xc0#\xd3\x98]\xb8Q\x1cA=b\x02\xe5\x90\x86r\x0d\x1cA^\x1e\x07e\xc5j\xf5)}5GJ\x8a\xba\x13y\x06\n\x97Q \xaf\x1f\xfb5\xcb\x95\x82KXh\xc3kW\x8d\xf4\xaa\x0bL\xee!\xe8y\xc0\x17\xd6\xa3i~A4\xa6\x08z_\x18\x9fp\x1c\xe3@,\xf8\xaf\x9d5\xc7\xaa\x9d>G\x96d\xb3\xadS\xed{\xa7\xbd\x9c\x96\x0f\xa8\x84\x0e\x9e>\xe2\x08\x92\xb6t\x87\xa5G\x1f\xbe\xae\x0f^_\x0cm\x80Ay\xb6%\xfe\x9e2\xf0\xde\xdc\xfc\xb6\xcd\xbcag l\xbf\xe5\xa9\x8b\xb6\xf4}\x18j\xb1\x01\xd2\x92\xb0g\xc1s\xd8\xde\xe64={\x1e@*\xe8y\xe1\xb3Qr\x89\xcaT\x87\x1dh\xba\x19\xd4\xb5\x83\xf1\xc9A\xe0{E\xfaq\xb5b\xd9I\x943\x97\x15'}Hv\x02\x0eqA\xaf\x06\xb0C\xd8\x1c\x8bh\x97\x94\xaf\x7f\x81>_\"%\xc6!\xec\x14\xf0\x12R \xcb\x14\xb6\xd1h\x0b]\x81\x12Y\x90r|\x0c\xca\x8f\x12\xd8>\x844\x10\xe0\xe6\x1f'\xf2\xe3\x04v\xf8\xef\x97/1v7\xff\xe3\xd0\xcczU.h\\.U\x8aK\x95\xc1\x0bH\x9f\x07\x10\x8f2\xb4\xa5\x19e|$\xf4a\x17\xb7\xac\x92\xb9D|.\xc2\xc2\xd5\xf7F\x7f\xfe\xf3z\xb7\xdf\x9f\xfe\xf9\xcf\xeb\xe9\xd3~\x7f\x87\xff?\x9b\xcd\xfe\xfc\xe7u\x7fO\xfc\xec\xef\x1d\xf0\x9f3\xb6\x8b?glw\x86\xdfL\xf1\xe7n\x7f&J\xfbL\xfc7\xbb\xdc\xdc`W\xce#\xe9\x15,/\xdaM\xcf\xbabG\x08\x19\x85 \xa9\x03A\xe2\x86\xbdD\xac\x1a\xdee\xc6\x12\x03\xf8\nmo\xa7\x97\xb8v)\xbc\x80\xf8y h\x9e\xcfw\xd7(\xbdD\x0f0\xc76\xdb\x90\xb8U\xdbl\xf0\x9420\xae\x84\xf1J\xcdA\xc6\xd7\x8fI\"\xe3\xd6\xb3\xa0\xe1\x9a4\x04)\x9c\xf6\"\x05\xad\"H\x89[\x83\xa4M\x84US-\x99,ZQ-v\xde\x11(\xdeLXldhx5\xea\x13\xa6\xcf\xa0\xd6[\x04*\xb7\xc5{<\x0f\xb9\xec\xe5\xa7\xd5A\x17c\x1eHs\" \xc7)r`\xd7\x07`\xd7,q]e\x00\x88{9o\x14/\xb4\xbe|A'\xc1\xdaG_i\x94)\xbfO\xd8\xad\x1f\xf7N\xf0\x17\x97\xe38\x0bo\xe0\x13\x7fT\x15\xcc\x8e\xa0\xef\x9ax3\x94\xb3ng\x05\xfbd\x19\xf5\xc6\xba\x04}\x9c\xdf%\x13%,\x9b\x82tM\xd6vUZ\xeb\x95~\xcf\x12\x116\xc0U;\xd7k\xbf\xcf\xd2\xcfw\x97\x8e\xab\xf7\x16\xf9\x18\xad\xff\xdb\xc4\xe1\xcc\xe5F\x81\\\x0c:\x95\xe2_\xeb\xf2\xaf\xb8\xfc\xab\xcd\xc8\x86\xa2\xdd\xb6\xd6\xa1\xc52\xb8y\x92\xa5i\x17\xb5\x01\xdd\xeax\x0d\x11m\xff'\xfe\xb4d\x86jmY\xf8\x8fm\xd2\xecWj\x11\xf4\xd4\x10\x1b\xa2\xfa\xa0\x1f\xf8\x89\x7f\xb0\xff$\xd8\x88{ih\xd0\xdc%b\xf3\xec?i92\xcbKo\x19\xfa\xc8q\x80\nv\x15\xad\x0c\x95.\x06\x8a\x92h\xab\xa2-\xe53\xb4\x95\xfa\x89\xf0kV\xf4\x1c#\x02&h\xae\xaa\xf7\xc7x\x97m\xa7r\xc3\xacim\xdc\xee3\xda0\xe4\xc0\xca2\x14\xa1\xb1n\xed\x15\xa7\x07\xbbm\xd8\xae\xd8\x80<\x84E\x08\x13\x8a\x19@g\x02\xf8\x9e\x0c \xaf1\x8cv\xa9\xc8\xa8Dq\x07x\x1f\xc6\x019E \xfb3@\x1f\xdd\x97\xb0j&%\xc2\x8f\x9a\x9f0\x94nm\xce[\x11\xc5\x9a\xe85\xc7%\xb6\xdb\xbaq\xf08Kq\x87f\xbd\xbf\x96`\xe0\x12\x17?\xb63B\xf4\x04\xc5\xf9\xa0\xbb\xb8\xa0N\"!k!dE\xce\xfb\xdc\xc0\x0bX=w\x1d\xe5\x98\xa7\x96\x8c\xef\x02\xd2)\xba\x18\xdd\x10we\x1c\x00y\x80M\x8c\xf9\ns)\xd9\xbf\n\xe1\x0eC\x1d\x15\x88\xa1\x13\xcc\xca\xe8\x8b8F7\"\x9d\x13\x7fK\xb7\xa6\x99r\x8c]*\x1f^o\x1c`\xea\x9a8Y;\x92\x0c.\x0d\xcb:\xfd\xb9\xcaX\xf4\xc9*\xb1I!:\xa77\x8db\x0b\xa5\xf1V]V\xed\x93\xd8\xbf\xc6j\x9cA\xbd\x13\x9a\x1a\xbe\xfb\x17\xd2\xcdTl\x8bIP\xe1\xd2\xb50\x06p&\xbdl\xea\xb1 \n\xe0\x84\x04\x90\xd0\xf8*\xe2\xa7\xc4\x18+\x86/\xd0\x15\xee\xa3\x85\\\xdar\xe0\x8e\xe1|\xeb\x82\x90\x87\xc8\xa4'<\xcaQCZ\xfe(\xeaN\xe9\xf8\xd7\xbd\x84\x95o\x92\xf35\xc9\x9e\xc4\xac\x9a\x98\xefT\xcc\x97\x84\xa9e>N2\xbf\xf7$\xe8}\x8c\x93\xe2)\x8a\xb1\x0fr^\xee>\xa3B\x80r\xb1\x87\xbe\xc79\xd8\xbf\xaf\xe8)\xe2\xa5~\x93/\xddSz\xac\xbb\xedcr\xeb2b\xa1\xa5q(g\xf8l\x8e0\xf4_\xe6\xc7!$\x1dp\xa4D8x\xfc8\xf03\xc7\xd6M7\xebc\xd0\xa7\xa3RqN\xcd\xbf\n!'&v\x0d\x870\xf2X\x96\xa5\x99\x17\x827Y\x08\x7f5o\xca\xf2\"K\xef0\xb0N\xb4\x16\xef2\x96\xaf\x97\xcc\xbbt\xb9\x08\xdd9\x11&\x06y\x1b\xc3a\x88\xde\xe0ROf\xce\x154\x1aU\xe8F\x86\xb1]\x0f\xbd\xc9\xc5\xed\xd3\xdbt\xca\x9b\xdc\xdab\xda\x0b\x19Z\xd9\xb7\xeb\x99o\xbe|\xc1O3\xb9\x7f\xce\xca\x12\xc7\x1d\xa40r\x98\xc7\xd7\xf3\x9f\xa3\x82eo\xa3\xec\x93\xbd& id\xd5\xeeO\xed\x1f\xac\x89\xd1\x1d\xc1\xe0\x00\x8608\xd8{\xba\xef\x80Bm(\xfc,\xe0S\x12'\xa42\xa5\x10\xb0\x88\xaa\x82(\x90\xd9c\xd6!\xdd\x08\xc6\xfb\x9d-\xd24\xf3\xedr\x15\x96@\x08\x8a \\\xeeo\xca\x84\xed\x18\xe4R\xcb\xd8\x1e\x8b<\xe9\x9c\x8f\xd5_\x9d\xa4k\xf4\xa5W\xf5f\x8b\xf4V\xa4\x1a\xd7j\xb2D\xa4\xc8/\xf3\xb5\xb3d*\xe8W\xed-\x87\xb2\xf8\xb6|\x85.>\xc2\x9d\x05\x7f'\x8cM\x15\x91\xac5(Z\xa3\x8a\xd4\xda\x89 \x8aF\xfbbC\x9cO\xe6l\xba^\xd4G#\xf7\x8f\xf9\x12-\xe9N\x93I*\x87\xca\xacw\\\xae^\x17\xb3\xa7*\xe3|t\x1b\xc5\xc5\xab,\x8a\x13\x0dNr\xaeo\xd3\x8c\xd5\xdb\x9f\xa4S\x96\x99\xe0+{\x13oY\xf5\x8a\xa3\xc4\x1c/\xb2\xe6\x92\x82<\x0bzBE\xf1J\xb4\x15\xd8M\xb3[\x98\xfbU#\x81\xdd\x8fVX\xc3W\x97\xe7\xd7\x95\xdb\xf3\xcb\xa4\x1c[\x88\x8b:e\xb8\xaa8\x08>\xb4+\xd2\x95\x0dG8\xce\x8c\x03\x92\xd7\x17DK\x04\xa9\xa8\xad\xb8\n\xf1 \x14\"4\x03\xcc\xebV4\x06\xdb/w|\x10\xba\xd8f\x89\x1b\xda\x87\xea\xcdaU\x1a`\x14\nW\xdcx\x07 \xc7\xd5m\\\x16B\xeab\xe9%\x17\xc1\x0c\x88\xd8`\xabL\xcd\xe1\x08\xfc\xc8\xd8c\x9d\xf8\x04\xd4\x8d\x8b=\xac\xd6\xc9\xee\xa7\xaa(\xf1\xcc\xd5\x1ah\x9c{Y\x99\xb7\xde\xe4b\"\x94\x01\x8a*!\xd4%\xddRy\xd3\xc2*\xb1\xd06o\xb8N}aX\xb1\x91d'\xf6\xed\n\xa0\xb9xI\xb9\xfa!\x9c\x93\x97\xf7\x1ct\x11\x86.\xf2\x91f#\xbew\x82+B\x81\x9es&\xa2\xe4,zq.\xd8'?\x13\xce\x07\xfa\xb6A\xcd%e\xbb\nztn\xa5*1NKa\xa8W\xf7Mz\x9d\xdcD\x8bx\nI\x9a\xec\x88f\x1f\xc9\xc3a2_'\x9f<39\x9dz\xf0\xb8wLDnk\x02n\x11F\xb0\n!F\xe1\x93\x13p\xbf\xe4bb\xcc\xc7c\x0cY\x1a\x9c\x96\xf1\x97\xfb\x1c\xa3]\xf37?&\x93\xc5qi\x16\xb3\x0bi6\xc7\x1c6\xcdv\xde\xc6\xdc\x16\xbdY\x96.i\xdc\xc0 f\xfc\x94\xd6\x8f<{\xbe\x9aC\x9e\xe0({\xeb$\x9f\xc7\xb3\xc2\x0f \x9a\x15,\x03\x96L\x81\xdd`\xf0\x8f\x00s80\xb48\x10!\xfa\x10X\x02U\xbb\xb4\x8d[F5|z\xf6\xa3h\xd2\"\x0eQyd`nK\x0em\x8c\x0bXn\xda\xdb,\x96\x97{&\xb4\xa5\x8e\xaeJ\xf5\xa5\x8fw\xc0{\xfbT\xed\x9bz\x99\x0ci\x8c\xe9\x9ej\x03\xa2\xb0\xcfT,\xb6\xad\xd5\x16\x93`\xe2$\x84\xd5\xb9 \xdc$r\xc0/L\xe6\xb0b\xba\x98\x93\x8e|\xf5\xcd\xf8\xe3\x0e\x1a\x7f\xab\xd1xj\xc0E\xc9E}\xff=\xd4\xddEp)\n\xc1\x16\x1d\xf1)\x88\xb5\x9eFE\xc4\x97\x1ac s\xa0\xf9}\xb1\xa6\x1d\x89\xa2@\xd2\x92\xa6*\xe4Kx\x1b\x14\xa5\xad\x01\xee\xfb\xef\x914\x06\xa1XT3\x10d\xed\x17\xed\x94q\xa5\x87q\xf2J\xc6\xeb\xdb\x93\x9f\xea\nc\x82\x7fP\x01\xad\xea\xaf+\xce\xcf^bB\n\xae\x8d\xc7\x89\x80\x8e\xee\xfd\xc6\xfe\xf9 \xdf\xee,\x13\x82\x06\xbf^\xc5\x88,\xd5\xdf\xf5\n\xe3u\xa2\xd7)\x7f\x19\xb5\xaa:\xad\x87\x99\x90\x06\x10;\xd6\x8b\x05G\x10+\xccw\xbdq^\xb7K\xc37\"EE\x06\xe4\xf29\xc9AVG\xf4\x04\xcfoC{Th1\xdb|\xa4kxld&7/r\x15eu\x86\x9b\xa1;\xa1 \xfb\xc2\xba\x07U\xac\x9e\xf4\n\xc3\xa0\xa9\xe3*\x1c\x1a\x126;\xfcH\x1d&r\xcf\xb5\x9e\xe4\x97/_\xc2\xa0\xf6k\xb7\xf6k\xbf\xf6\xebi\xfd\xbb\x83\x10\xd8\xf6v`:]\x83\xe0\xb6\x03T>\xbd\xa8q\x17\x0c\xe7\xab\xa0\xa9\xcf\xbc\xb04\x06\xfd\x10\xfa\x1dc\xdb\x9c\xd3PPW*\xed\xc2\x97\xdd;\x97\xf3-e\x05\xc7\xfa\xa9\xef\xf1\xd7\xea\x9d\x17V\x8b\x1eP\xdfH\x9d\x88\xe2\x04\xd2*\xf5\xc6 \xba\xa3\x0d\xe1\xa4f\xe6\x02\x0d\xf3<\xa1\xe7)\x87\x04j\x92\x9e\xc8\xb0\x80\x0c\x87\xfe\xee\xc2N\xea@\xf7\xf3\xc9}\x82\xd4\xf4!\xc8\x82\x9b\x1a\x92~\xa8O\xf2X\x10\xd6\x8e\x13\xbb\xca!\x864\"\x01\x0bXV\x9c\x16\x17\x10\xce\x9c\xab\\\xeaK8x\x8bx\xf2\x89\x1ag\xa7>\xde\xb7\xaf\xb0\xc2v\xa1y\xa3zB|w(\xe6,eZ\x85\x90\xa8\xd9\x96\xe8\x18\x82\xb9d\xdarn6\xa5\x8bo%\x02\x88bS\xdf\xe3\xe3\xa9m\xeb\xe7\xf5AJ\x0b\x01\xa5|\xf2\x83\xe7\x86\xc0\xe3\x1a\xe1\xdb\xb6C\xc88z\x8eDWH\x1d-F\xa9{\xaf\xe3\x98\xdeu\x13I\xfaB\xfbU\xb9\xb0\x08\x07\x16\x0c7D\xe2\x15_$\x91\x93\xa4\x16^\x8a\xb8g\x92%;\xa6\xf4\xa0\xff\xd2\x15:\x99\xd8\x93\xcd\x1a\x02)Mx\xe2\xecd\x9a\x91$\x9f\xef\xc0\xb4\x95\x02\x0d\x01 \xa5\x0dM 1\x8a\x00\x8d\x9er\xfd\xa4r\x832\n(\xa9\x9b\xd0\xfeZ\x9al\x0d\xc3\x0f-\x99\xee\xcb\x17\xa5f\xa8n\xac\xe5\x8c\x87`\x89\xef\xa2\x9d\xb0\xfc$l\xd4\x01\xbd\x16\x97\xc40\x84s\x95q\x81\x13D\xd7<%\x81>T*\xa8@k-p0\xfe\xdf\x7f\xafzq\xb5\x8d|\xb2\x0c\xd0Q\x03\x8d\x13}\xa6\xbe\xc7\xebUJ\x82\x10C|\x18Q\xae\x04\xe4\xaa\x93\xc6\x96\x97q\xfcS\xe5\xf6\x00\x0b\x96\xe7P\xcc\xa3\x04ny\x8de\x94}\xf2\xc4\xb8P\xb9\xaa\xc0\x86\xcd*\xd1\xeeH\xad\x05\xff\x91\xe2\x95\x19\xde!\xa4b\xe1\x91\xbf\x93R\xf94\xc5\x01{A\xa8}_S\xa9HM\x91\x05@J\xa3T\xd38\x9aJ\xb5@or\x10\x1a\x82\xb0X\xc1\x04WP\xae\x8aX\xdaL\x1e\xf1}8*\x05\xbc\xa1<\"\x8f\x1cz-\xfe\x7f?\xd0u\x7f;\xa8\xec$gQ\x02\xd01\xa3\xa4\xdaJ\x9a\xc2C\xe2\x8f\x1a*\xea\xc6\xcbk\x94\xda]\x14?\xb0\xea\xa7\x9b\xa1 \x1ew\"(Z\xc3\xc4\x85\xa6\x80x\x00q\x8e\x81s\xe3\xe5JdH`6\x1d6n b\xcc2\xd2\xca\x8c\x96\x82\xd6\xf7B\xb8#\x8b\xa7Y\x14'^\x083\xb2T\xed\xcf%Y*g\x17\xc2\"\x109S\x8d\x8f\x13N\xaa'\x0deWd\x99\xa467AX\xc6\xbd\xde\x8au-!^\xeb\x8fo\xb3\xb8\xa8]\xbcn\x99/\x91\x08\x96\x9f\xcc\xa88\xb9_\x1b\xd6w\xe2\xbc\x8a\xc6\xb5E\xceP\x18\xeeM;\xc5\xb2\x8e\xeb\x06#\x1a\xef\x8b\x04\xf2\x8c\xab\x8cQ9^\\X\x17\"\xea!|\xeb\xc9X\xc6\x02\xc6\xd5.\xa0A\xac\xb20Pes 24\x00\xd4\xb2!8O\x05\xc4$1\xc1P\xb6\x14*j\xc5Jk\x1c\x8e\xbeBt\x91\xd1@k\xe4\x12\x1d&%qW\xa1\x0ej\x15^\xc2\x80W\xda\x11\xcd\xbe\xf3+\xfa/x\xcc\xad\x95b\xa2f\xd1\"g\x80\xddB\xc6\xf2U\x9a\xe4,\x04ek\x9e\x98\x17\xb0\xb5%n(\xdd\xde\x96\x93\xeb\x8bl\xca\xbc\xbdMw\xe3\xb2\x05\x88\x8aT\x15A\x08W~+5\x13\x08'\x10L\xbc\x17\xe7\x82\xc1\x98\x10\x11!\x9a\x06y\xed\xdcV-\x84\xf9\x8a\xa4 \xee\x8e\xee\x9ai\x93l\xbb\xf5\xb8\xd8\xb4\xdb\xab\xa6n\xab\xc3.\xe9\x89\xbf\xbb\x9d\xfdJ\x9e\x15;\xb1$\xfed7]o\x07\x00\xac`n\xba\xb1\xef*c+\x96L\x15P*/=\xb3D\xe4\x98iP\xa1\xf7\xc6h\xc2\x97\x0b\xe4\x91?F\xc5%\x1cA\xe4\xeb/\x02\xb4\xe3\xab~\xd7-\xb2j\x9f\x1e\xc2( k\xaf.\xb1\x8a\xf0\\J\x1c\x04OCeu`\x8b\x03\xa5\xce\x1f\x88w\x06W \x90^\x9e3|3\xc7%\xa1\x95w{\xc8\x8aU7r\x89\xbc\xcd\xf3\x03\xebR\xdf2\x82\xb1\x18\xf3&\x9d\xd5F*\x03\xf7\xdaWL\xd4\x90Jz\xc1\x1f\xc2\xc9%\xd6b9\xeb\x1c\xbdR\x11\xce\xe3\x9c\xfeh\xe0\xfe\x88U\xcc\xa5,\x87#lIXq(\x89Q\x96\xe1Qi8f\xd8^\x19\xfa)8\x90\xd6\xf0j\x11KvA\x18\x13%R\x92%p\x18\x9d\xfd\x9c\xfcB\xe9\xf0#\x0f\x0b'\xa8S\xa8\xcf\x9c\xde,\x9b\xce\x8an\xa5\x163\xb4\xff\x1cb\x0c\x15\n\xf1\xf6v\x00\xd9(\xbet\xc1\xa0Qak\x19\x0e\x01I\xa6nd\x9c\xc3w~Q\x9d\x9f\x0d:8D\x89H[l\xf9\x99\xca\xd9\x13\x850\x08\x0c@\xec\xa0\xe4cc\x93d~\x14\x08\xe5_\xa3\xfe\xa5\xb6{]\x0b\xdf\xb49S\xeb\xc6\xb5Ib\xcek_Vn\x10\xd2p\x83\xc60A\xd1\x05g\x12\x94\x82\x98\xdb\x00\xadT=(\x02C\xf0l*FRe\xb3\xa2\xdao\xc1\xe5.B=\xe0]Q]\x89\x9c\x11.G|\xe7R\xef\xc5\x85\x88\xa5\xc9\xc9\x1c\x0eM\x99\xa6\xec\xca4}\xcey\xa9<\xd4\x04\x853\xb9\xa6\x9b\x1c\xabM\xeb\x1fM\xcb\x93\x0e\x0e\x0d\xcc\x08\x0dU1\xdav\xb4\x98\x19\xde\xc8@\xfb\x9d\x00]\x9e\xb9\xc6QS\x9d2\xcc`\xf7[1\x15\xa4YJ\xdd\xd0D\x19\x1fY\xe6'\xf5\x1b\x88\xf7\xa4\x01\x12\xe0\xd9*\xd1<\x08(;CC\x0f\xc5\xb9\xdb6@U\xaaV\xbe\x8b\x04\x87\x0dr\xb2B\xc7\xd1\xb0E\x82\xb0\xe3>\xc2\x83\x1b\x99w\x87\x05e\xfd\x1c\xd1\x14s\xf2\xab\x0e\xd3\xbd\xcd\xa2\xd5F\xa7\xbb\xfb8\xef|\xf6g\x8e#\xa2<\x1eR\x8c\xc7\x83\x0c\xa5\x10\xa7[\xc5^NN\xa6\xbe\xc7g\xb3bS\x90\xc2}R\xf7\x97P\xba\xf8f\xc9\x99 \xcb\x87nnP\xf2\xec\xd6\xaf\x0f\\Z3p^c\x16\x9a\xa9\xb6\x8d\xbc\xa5&A\xf2\xd6%,HW4\xfe\xe8\x90P\xc2i\x0d\x14~Z\x9b\xa3\x90SS\x8e.[\x89\xe17R*\x95QS\xafY\xef\xa7B\xa4\xf7\xcd\x0f\xb0\x9e\xb2JQb?\xce/\x0d\x04\xd1U\xba\xf1R\x90\xa4\xb6l\x806\x93\xba\xcf\xd4<\xceG\xe9%\xd4c7kR\x81,\xf4UE\x0d\xa9\xdb\x1c\xee[\xd1K\xab\xcb8\xf3/B%3=\x85F\xc7\xf5\xfe\xca\xe1\xdc\x80\xfa\x1agt]^1\"\x83\x84Hp=\x8a/\xb5\x9d\xde\xbb\x8a\x93\xa9\xa4n\xbc\xa8\xc1#\xa7\xd0\xbd)\xdb!\xa3\xa1\xd0X\xde\x1f\x16\x81\xf2\xfe\xce\x14\xe7Z\x89\x11\xf6Di\xda\xd3\xc5\xddD\x91\x90\x9ao7\xe9z\xc2\x92\xf5\x92e\xbc.\x97\x13lj\xb3\x91k\nEak\x17G\xf6\x1c\xeb\xb3C\xbf\x8f\xf1,K\x97\xfcT\x86Cx\xfb]UV\xcf\xac\x10b\n\x1eG\x82\x05C0\xae\xe5j\xb0\xe3Mti\xa2-\x1b\x90\x88\x99Q\x16\x94\n\x83\x94<\xaa\x1b\xb4,_\xc9Q\xd7?\x97~,\x1d\x0c\x8f\xee}\xd7\x03m~D\xee\xd0\x02\xe23K;M\xbc\xaeZsn:\xf4\xb2\x8e\x84\x9f\xde\x11:\xe1\x94\xd6\x9b\x1b\xf4\x83p\xae\xb1\xb3%\xd3\x93*yA9Y\x08s\x9d{\xba6i\x17\xa7\xd6\xc0\xfcF\x08\xd4?\x96\xaf\xfd\xf2\x04 ;h\xb8\xb7\xe4=\xce\x11\xe7\xcb\xf5 &bv 5(\xf3e\x1dV8(\xbc~E\xd0\x92\xfa,\x87\x9cU\xfbYzd\xb5\x10\x93{\xc3}@\xf3w\x99\x1d~\xc1\xf2\xa1\x996\xb6`\x84u\xf8\x96\xe5\x1d\x90\xdf\x12#\xb0\xca\xcd)\xd4+\x08]Vs\x1b\xc6\xa2\x9aNU\x06\xf9\xe9\x9ca\x87\x0c\xc8\x96\x95\xa1g\xaa\xfbvDd\xafL>\xabG\xcf\xca\xd9B\x04\xb5\xe4\xff\x7f\xf9\x02\xb7q2Mom\xfa\x92\xd2\xe1\xef\x91\x93p93\xd1Y.\xa0\xc4\xb4xZ\xf9N\xf5\xc6h\x89\xfd#\xd2K\x07x\xf0\xcb^\xce\x8a\x8bx\xc9\xd2u\xd1Q\xccI\xd8-\xc4~*N\xb0\xeak\x8c\x87P1@!\xe0\x00d\xa1\xa5\xb7\xc0~_'\x05\xcbn\xa2\xc5=;V\x9f\xd3=\xabR\xa2k}d\xa8\x80\xa9}\xd0*\xffH.\x1f5\xb1\xbe\xd5|\\S\x97fl\x86\xb6\x91\xba\xec=3\xe6k|\x84\xed\xb6\x81\xa4\xb6\xc6\x02\"YX\xe2\x011g\x96d\xe9b\xd1EA\xa4C\xc7g\xbc\xb9\x05\x93?_OQ\xfc\xd0_\xd9\xf8\xc5{['D\x7f\x0f\xd2\x99i\x0e\xc7{\x1b#\x9c\x8f'E|#\xb4\xaf\x91\xfa\xf3[:\xa7/\x08\xe5M\xaaV\xd5\xaeW\xc0\xcbC\x99S\xc9l\x15\x0e\xa1\xda2~+/\xcaz\xe34Q\x93\x17\x97\x12\xe5o\xea\xb6\x87p\xb9\n1\xa4\xd5n\xa0\xf6\xdcr\xc9\xa6\xb1\x08\xce\xd2N\xc2\xea_Ta+*Rh\xd5\xe08X\xb2.za\xb9\xf36\x1c\x82\xf1\x0d9\x08\xbbNm\x18\xf5\xe2\xea|\xe8\x94\xe0lc\xe6\xd9\x11S-Eeb\x9c\xebq\x88\x9a\xf1SY$\xe1\x9d\x82\xe7\xc16\x17\x82q\xbeE\xfa&\xbd\x15 \xc9|\xa7\xfd7\x1a\x11ys\xf6\xd9\xa3\x8d{D9FBj\xa9\xb0\xd3\\#\xca'q\xdcX\xe3*N\xa2\xec\xae\xb9J\x94\xb3\x83\xfd\xe6\x91L\xf2\xdd\xb6\n;-5\x8a\xd9\xe0`\xc1\xda\xea\xec\xb4V\xca\xa2[G9h\x1e\xda\xfd{\xda\\\x95\x1e\xde\xf6\x16\xaf\xefnG6,\x8a\x931\x08\x95B.\xdc \xac\xab'\xb8\"\x81\xed\x0c\xbc\xba\x90\x92S\x11x\xd6r\x11T<\x7f\x1e\x94\x03s\xb6\x0c]p\x17:\xe1\xafz:\x0c\x12\xba\xa0!tBE\xe8\x88\x8e\xd0\x15%\xd5\xa3M\x03k\xb7\xcdd\x11\x15q2h\xed\xbdq\xf7\xaaG\xf5-\xdbl\xeb\xbaq\xbbC'\xd2\x02\x1dh\x9cz\x94\xba\xae\xc1\xe8\xa9mO\x82r\xb1h\x0e\xb2\xa5\x1eN\xb3}I\xb4\xeb\xf4ZD\xa3\xd0R\xd8\xea\x0f\xa5#\xa4n&\x1d\xd1{\xc5\xe5b\xed\x989<\x94\xd1\nE\x120\xdb+\xc4\xfb\x98|J\xd2\xdb\x04\x14\x15\x18\x82\x18\xb6[{\x88V{uJT\x05v(#\xd3Q,W\x07\xb4\xc7F\n\xf6\x99C)/\xdb\xe4\xac\xd3B\x80\x8e\x88\xd1\x08n#\xd7VR\x81\x1d\xcc\xe2\xc5\xe2M\x84z\xba\xf5\xfd{i\xc4j}^\x93\xda\xbcf\xa2\xc7\xbd\x8dzlDX]\x89),\xc0\x0ea\x15\"\xe7\xe4k\x1d\x9b\x92B\xed\x17\xd6[Dy\xf1\x8e\xa1\xa0\xadB#\xf2W\x17i\x81\x92\x92\xfe\xeed\x1e \x9f:\xdd\x1f\xb0\xa6\x0d,\xff,\xcf\xaa\xc8&\xf3\xa5\xa9\xc5\x8bC\x18\xec>QIb\xe0\xe5Kx\x0c\x87\x87p #B\xe3\x9b}\xfef\xb0\x0fG\xb0\xa7^\xed\xf1W{}8\x82}\xf5\xea\x80\xbf\xda\x85#\xd8\x19\xc0\x10vv\x1b\x87\xb4v\x1c\x9fJ\x1bXM\x7f\xa7\x0e\"[\xca\xdf\xc4\x05\x1a-Ov\x9f\xf2\xbd\xec\x0f\x9e\xed\xc2\xf7\x98\x14<\xd0\xac\x99\xeaK\xe1\xfd\xdf\xff\xd7\xff\xe9\xa0\xb2\xe8cTU\x97\x16\x83\x9ak\xd8\xa0\xe9h\xa5\x062p\x0dd\xd08\x10\xa0\x06\xb3k\x0c\x06\x7f\x9b\x1d\xee\xba:\xdc\x95\x1dv&\x9e\x85T\x88>\xa7\x90L\x93$\x12t\xb0\x1f\x1aX\xffB\xf36\xc3x^\xe8\x97YCy\\V}\x1f\xf0\x0f\x03c_\x94\x89\x0d\xeb\xfcVho*\x11\x17\xac\xa9\xa32\xc2\x99\xbe\x9f\xcb\x11\xefh!\xd0\x9a\xf7^N\xaa\x00\xf8z\x95\xd9T8\x8a\x07\xf0\xaf\xb0\xcb7P\xbfI)_\xa5n\xf4K\xf2\xee\xb6#i\x0e\x04\x80\xd7\x91\x93y\x94\x9d\xa4Sv\\\xf8\x9a\x0f\xac\x199Z=\x18b\x9f\x8b\xdd\x8f\x1f\xef>;\x004\xcc\x7fq\x08\x8f\x0f\xf6\x06\xcfj&_\x06.Y\x04m\xdfX\xb8Q_\xa4-\xd6 \xb2{i\xd6\x19Xu\x06\x97!$\x95\xa3\xfa\xce\xe0\xfeF\x1e\x14\xde\x9a3\x19\x103\xd9m\x9f \x1f\xa5c\xe1*4C\xa87\"\xd2\xc2M1\xeb7\xe2G\xda\x81$n?\xa8\x9c\xec\xf5\x8d\xd4r\x11\xe4&\xc7\x0d\xdc\xcb\xb6ksj\x10\xe8\xdb\x01\xc1\xc8\x95h\x84\xcc\x84\xdcbj\xfc\xd66\xdb#\x89T_z\x9b\x1c\xd5\xd6J\xb2\x1a\xd2\xf1\xcc71b\x0fv !\xb0bOY\xa4%j5\x1a\xf1\xa3\xd6\xf47\xed\x87 t\x0c\xbf\x86iI\x0b\xcd\x9a=\x1c\xaa\x91[\xe9\xa8\x11;\xcaA\xf7C\x04\xb0\x81\xa9\xc3\x16lX\xb9\x99\x1d\xc7\xf9\xd0\x0c\x8ci\x03\xf3\xd4\x06\x0b\xada\xf5WQ\x8f\xe7\x06\x87\x10\xd75\xd3\x8a\x91t\x0b\xff\x95\xcdmy\x06\x95\x82\xa1\x01~\\\xb6\xd0t|\xee\xb4\xff\xe3*\xef%\xfab\x96\xac\x99b\xe2\x85\x9c\xe3\xe8\x18t\x03%\xd5Mhs\xbb\xf5\xbd/\xec\x14\xd1\xe5\x9bD\xa3\x04c\x92V\x00\xd71\x89\xf3\xfc\x9c\x10$\x81\xe2/\xeao\xf0:I[\x91:\xd4\xa5\x88\xd0xK\xf5\xc0\xf8\x8f\x1cV\x1d\x9d\xebc\x92RL\xe3]\xc2\x8d\x99\x17\xbd\x81\x01\xae\xec\x93+\x8aAs\x0e\x19\xbc\xe0M(\xd2hW\xba\x91\xd9\x03\"\xbf\x18e\x97\x0e\xfe#E\x0d}\xd9L\x8a\x8e\xbcB_\xaf\xa1@\x8aG_\x08)\xdd\xc8\xce\x0e\x0e\x86\xaf\xde\xce\xae\x10\xb3\x9b\x06\x86\x8c\x956\xb2\xa0\xf3\x18v\x7f\xfd1\xc8\xb60\xf8\xce\xa1\xca\xd2Y\x1f\xd5\x1e=*\xd5y}\xfb\xb8M\x8bQOhly\x9b*\x96\x01\xfb\x8d\xaf\xad\xf3-\xb1\xa9\x8c\x1e\xa0\x01v\xc0O,\xcaMn\x0c\x9a\x05\xef\x0b\xcfijh\xf5|a\xf5\x0d\xa3\xa9\x17\x9a\xa9g};\xbe \x08\xa9C4h\xe4\x85\x1eT@\xa9C\xeb\xde\xc3\xd1\xc4\x98\xfa\xa45 \xc68\xa5\xeeu5\xa3\x9b\x1ei9Nn\xb4\\Pt\xa63LcS\x164\xa9\xd7\x11\x87\x11\x04\xb5\x84*\xf5\xb4 \xb1\x9d\x01\xabfu_Zc\x14Y\x94\xe4\xb34[\ns\x0c\xca3\x06C\x83_\xa8z\x1dl\xa7\xc0d\x9b\x8d^h\xa9*\xe9\x95\xb5\x9a]9*\xb1\x0d\x0f\x9c\xc9\x95[J\xdb\xca\xea\xf2\x983v\x80\xe068\x84\xae\xa2\xc9'\x15\xaaf\xb9^\x14\xf1j\xc1\xa0\x88\x97,w\x86\xbcW\x03\x99\xaf\x93O\xa5\x9bJ9\xba\xea\x8d\xcc\xfaW\x94W\x852ut\x88Y\xf8\xdc\x93M\xbb\xda\xc5\xf3'5Lw\xfc\xd4\x8al\xaeLd\xe1\x05\xa4D\xe0\x8d\xaa+\xdf,\xb6z\xfcZ\x99\x81Ri\x04\x19\x9bj\x88C\x99I\xeakN\xd7\x90`\x14\xf1.\\\xc5\x1c\xf4\x8d5*u3\xafT?/h\xfb%\xc2\x13\x83\xaa\xa6E\xf3h\xcc-RNT3y\xaa\xde\x1d\xea5\xdc\xa9Ff\x8bu>\xd7\x1a\x10\xbf\x0fU\x89\xb2\xbaG\x9b\xedU\xc6J_\xbd\xa8M1J\xf1S\xca\x1d\xa3\x8eg\xe4\xc8\xf4\xd1\x1c\xe9\xbfj\x99\xd3Hnl]\x12\xd7\xfa\xa2p.r-\xc9U\xb5\x7f\x9a\xe7\xb1v\xb1}\xb5\xab\x14\xc2\x88\xd4\xe6\x12j\x99GY\x15\xee\xde\x8a\x14\xa0\x0eL\xeb\xa2\xe3$Z,\xf86\xac\x16y\x9a&\x0cn\xe7,\x81\xdb2\xa9\xd2\xd6!\xf4\xcd\\\x86B\x8bi\x10\xcd\x1au\xdc\xb0\xbb\xbc\x88\x17\x8b\xdaV3\xbb,!C\xb8\x03TB[j\xa5V\x0b\xb5w~,\xd8\x95x\xc3\xe0\xee:\x816']\xa3 \xa5\xdfS\xbd}\xcb\x9d\xac\x1ay}0\xb5\xfd\xd6&)X\x00\xae\xbev\xc4\x98qvk\x8b\xb2t\x97ug\xb3\xa63\x13\x85\x13\xfd\x80\xe1P\xa9\x1dB\xac|\xa3]\xb7\x17!le\x06\"\xd1\xf2Q\xe7#\xc7\xcf\x8c5\xc2\xf3\xe5\x17:q\xbe:Al:\x174\xdf\xaa4\xc2\xb6t;)t\x88\xe25\x82\x02\xb8\x88\"\\cW0\x0c\x93\xc9\xc0\xf4-.\xcb\xd7\x1b\x0dU\x93\x15\x03\\\xf4\xea\xdc\x960!\xb6\xb7A\xdf \x89\x8e\xa9\x1at\xfe\xccd\x14\xed\xd6\x8c-\xd6l\x90Q\xf8\xc2fZ\x10Y\xe1Cn\x12w\x83\xb8\xdc\x8b\xd7\xd6\x98j3\xeb$G_\xcc#\xa9KEiv\x1aM\xe6\xf5\x8aq\x95\xdf~\x92\xb1\x1a.tK\xdf\xab\xf0*\x16D\x93\xa4\xaa\xd2\x8a\xb4\xb4\x1am\x03 \xe7\x069\x8eug\xb4iV\x10M]\x12\x99`\xbe\xc08\x80\xc0F\xc9\xa5U\xf9\xab/\xf3f\xa3\\`\xaeUX\xd34\xc2}\x97\x8b\x84g\x00\x7f\xfb\x86&5\x0c\xd0Sen\x92\xb7\x16\x89\x1d\xb9jq\xfe.z\xe7c\xfa_\xd4b\x14B\x7f\x817w\xdf\x7f/\xd5\x15;\x98\x9b!\xc5\xe8\xd6\xc32\xfc\n^ \xb5\xa7O\xef4\xc7\xba\x0b\xce\xc1\x93\xa7\x81\xcf\x87$\x916\xca\xf3\xf8:\x81!\x16=\xfbV\x9b\xc2\x10\xd2\x10\xb3\xc9\x85\xb0\x0eA\xf5h\xec\xadNv\xbd\xd6\x85\x05\x7f\xb4\xb8 Evg|E{g-B\x90Q\x00I'\xacI\x9a\xcc\xe2\xeb\xb5r\xc3\xea\xd3\xcc\x7f\xe4t\xd2js\xe2\xc2,\xd8C0\xcc\x80\xb5u\x85IT\xda\x8fU\xa7\x93\xb8\xf4Xhw\xb9\x99%Y7\x0f\xdd=\xec\xfa\x90\xab\x91\x88\xd0\x86$\x14\xc3\x8d\x13\xd4\xa35\x0cJ\xa6\xa5.\x0b\x1d!ez\x0d?\x13\xf9\xc1\x05K\x81\x9eZ\xd5*e\xfa\xad\n^\x17\xc9\xd4\xd2\x83\x83 \xc4\x8c\xa8\xa3\xcb\x10\xe2v\xaa\x1aR\x1ap\xce\xf9\xacG\xec\xb2d\xe6\xf9\x8fz\x15${\x05\xf6\xf3\x1c\xd8\xce\xce\xf3@\xb9\xb9z\x91\x07\xdb\xe0oo'A\xa5\x82\xda;0\xe5zM\x8f\xa2\xdc&|o\x96\x88\x9c\xb9XTJ\x1c>o\xb0\x90Q\xeeC\xf0\x02\xd8\xe6\xff\xfcM\xb51K\xa4\xc3\xa68;+\xc7\x81\xe7\xf0\xf5y\x9de\xec\xbcF\x04\xc5G\xf9\xc6\xb1f\xaeD\xf2 \x9eZE`\xa9\x1e\xec\xbd\xc9\x9f\xc8OB3\x01\x95\x03\xfd\x81\xba^\xfe\xfa\xad\xc4I\x88\x1cT&u\x1a\xe9\xeb\x00\xaa\xaa]\xb3\xe2\xec6Q\xd5^\xb1|\x92\xc5\xab\"5\x0c\xa8#\xd7\x07\xef\xa2\xa5\x19\xd3d\xed\xaa{~\xb7\xbcJ\x17y\x87\x93\x89\\cA\x82\xe5\xd1\x9c\xf9\x85\x89\xa7('\xea50\xca@\xe4\xe7\x81bv*\xf1\x9b\xce-G\xae4\x7fpOg\xa1H\xba\x9eQ>\xb6\xfa\xd2\x93M\xa0\xa1\x86\xfd]\x1d\x81\\\xaa\x0e\xcc\xe7\xbe\xfe\x07\x9b\x89n\xe0SJ\xe8\xb4\x9c\xfd]\xbd\x95o\xdc\x15\x8f)\xfe7\xf1\x07\xfb\xe6n\x89iO0\xce\x9e\xde\x17I\xf9\xc1Fd\xc2\xe3\xfb\xa7\xa4v\xa3\xddK\x12\x0c\x19\x92+\\!\xbd#\xc1\x87\xac\xa9\xe5HF\xd9%\xfa8)_\x8a\x08\x05\x12\xf5\x85\xb5$I\x0b\xa0\xf5>\xba1\xfcr\xe8[[R\xdb'B\x10\xd4\xd3\xc8}\xf9\xe2P\xe0![\xefR\x10\xceY\xdbh;\xa1\x05\xcdH\x15!x\xe31\xcb\xdf\xa6\xd35\x9a\x9c\x98K\x89\x8c\x8e.W\x06\"\xde<\xda}v\x81\x88\xbdX9\x17\xae\xdf/\xd6\xd7q\x92\x0f\x1d{\x8be\x99\xab\x08\xb0\xed\xe9z\xc2\xb2|\x08~\x9f\x0b\xbar\xe9\xcd\xe2E\xc1\xb2\xee\xc4\x80\xf5>\xb1\xbbs\xf6_~\xd0c7,\xd3\xc8\xb4\x13\xb4`u_\xb4d\x0bD\xa9mT4d6Q\xb2?z\xb8f\"\x16aw\xb2\xefDg\xd6[\xb2\xec\x9a\xf9N \x19\xc5T\";\xdc\x06X0\xfe\xe1O\x0f\x8d\x08\x9a\x1e\xa3\xf2 N~\x0dtH\xe8pZ\xbf\x06\x805)\xb2.\xc2\xc5B\xe5\xb6k^\x97\x89\xcb\x0f\xf3m%\x94\x0f:\x0b\xe5j2\xa6\\./e\xec\xc9\x95\xaa\x03\xc3{\xfa;\xfb/>\x83\x85uG\xc5\x19\x9b!\x18WS\x0bv\xc3\x16\xc32`|\xadl\xc9\xf2<\xba\xe6Go\xe9\xe6\x8d\xb5\x8c\x1e\xff\xbe\xa2\xb7K\xaf\xd5\xa4\xe1\xb4`\xfb\x97\xfc|\xc5&C(z\x9c\xc98W\xda$\xfc\xf5\x87\x04\xd6\x91\xb28f\xf35\xe8\xc0\xb1\xaaok\xa2\x80\xd8\xa1\xf8b\x15 \xbe\xc4l\xba\xc2G\x87\xf6\xf0\xc9\xae\xa9\xd4\x7fH\xed!Er\x08\xf7\xf8\xff\x15\xf4\x80 \x87\x8e7\xd3\x11\xd2\xe4]q\x8f\xc6\xff\xdc\xab\xfe\xdc\x0f\x02a:\xf3\xf7'_\xb4!\xa3\xeb\xc0\xe8\x80\xc67e\xb41\xc4ZI\xc7\xbd\xa0\x17'S\xf6\xf9l\xe6{\xd2\xe21\x9dA\x84g\xbd\x9f\x07\xa6\x11)\x947\xd1/a\xc7\xe9\xf6\x7fS:q\x1b] \x07ft \xa3:S\x96\xb6\x98\x05\xa1\xf0\xbd\x90\xea\x1e\xf4i\xe7z\xfb\xa1\xab\xc3>\x92\xd8\xed\x0ebB\xadqq3\xe1\x9b\x88\xd0\x90\xd7\xcdh\"\x91i\xdc*'4\xb1\xab\xe5\xef\x970\xc0\x83}\x1b\xbc4\xc3\x18)\x05\x0c!\x1b%\xb0\x0d\x83K\xa3\xea\xae\xac\x8a\xc0\x0b\xc1\xd3kj%X\x80\xbf\x9c\x03\xfc\x1a\x82\x97\xcf\xd3\xf5b\nW\x0c\"\x97Z\xc3O6\xc9$\xe0&~\xbf\xe9\xfdD\x9c\xbdEO\x1c\xfc$\xa1\xd1nu\x1dD}\xb0\xf7TCZ\x071\x0f\x91_\xfcMC\xe6\x1b(\x8dkw\xfa\x14\xf9\x11&@\x9e\xf2s\xeay\"e\xeaj\x11M\x98\x9f\xb0[\xf8\xc0\xaeO?\xaf\xfc$\x04\xef\x9aW\xf7\xbc\x80\xd2\x1b({\xa2\xdf:\x1e.\xa2\xbc@ss\x11Yr\xb1\xc0\x1fy\x19\x16\xd6@+R\xb4\x10\x98\xf6\xd8|\x1d[M\n\xa5\x8b0{U\x0cl\xd0q\xf5\xea\x80l\xd3\xb1\x94k\xae\x8b}JXU\x9a\x16cm\xaa\xa9\xd6\xc1B\x8f:n\x1aB\xd9=oG\xe3\xc8\xbf\xc5$\xe9A\x97\x9d\x90F\x1cs\xb0a\xdb\xe5\x92}\x11\xdd\xa5\xeb\xa2\xdb={)\x88\xfc\x03\xdc\xafS8\xfeP\x1c2}\xbf\xbe\xdb\xef\xbb\xef\xd7\x9fv\x16\xe5\xffW\xe0\xab\xff\xbe\xdb\xca\xc6\x99P\xaahvM\xa3\xa8HaM\xfc\xd0X\xb3& \xb4\xb0\xab\xe6\x98\xa4\xd3\xb8\n\x96hm\xaen\xe7\xa3J/\x90\x86\x90\xf7>\xbe\x7fu|q:~s\xfc\xa7\xb3\x8f\x17-\x8a\x82\xfaQ+\x88\x00\x9e\xa0R\xb9\xa7S\xc2\xc6\xde~|\xfd\xe6\xe2\xb4M\x91\\\xefM\x08\xde\x9b\xf5v\xfe\xd3\xd9\xcf-\x9dX\n\xca^>Oo\x13\x9b\x0e\xa9\xa3b]j\xed\xabO\x8ay\x9c\\\xbb\x1c\xe0\x94\x16\x1f\xdb\x95\x87T\xd5\xc8\xdf\xf8\xd8;\x1ev\x1c\x0e\x19\xe1\xd8\xd8\n\x07 \xf5\xb7g\xafN7\x06\x07\xce\x8d\x06GUi\x99N\x99c\xfa\x18\xea\xdc\x1fy\xbcJ\xee]\xaa\xfb\xab\x84\x0f5\x13\xb1C\xd0\xc6\xd9\xabO#\xfd\xad\x1c\xa5|\xd9\xce\xd7\xcbe\x94\xdd\xe1\x94o\xe7\x91\xc8\x0f\xc4\x7f\xc4\xf99_U\x11\x86}\x9de,)~D<\xd5\xdf\xb8\x98-u\xec<\xdd\xfbUO\x1d\x82\x95\x13de`Z\x97\xe5\x92\xda\xe8T\xa5\x9aS\x07\xf6\xe8Z#\x13\xda\xf2\x86\x04\xb4\xba\xb6&\xc9\x80S\xdd\xb50\xd6\xa5 {\xb4\xd6\x8brw'i\xb6\x8c\x16\xf1_\x19\xba{\x05\xd2\xfe\x1d\xfb\xd6wp\xae\xef\xe0\x00\xcb\xeb\xaf\xf9w 9\xcc\x1a\x0eu\xda\x8d\xa5\xdd\xab.\xa0\xd7SX\xe9\xa6\xb1pT\xff\xe9\x8e\x9e\xd3>kj\xef\x1a\xea\xe5\"0\xa6jo\x1bA\x94\xbaK\x06\xb6\xfc\xdb\x81\x1d\xdfBf\xc3c\xd3\xb8Hk\x18\xd2\x89\x94T\xf2\xcf\xdeAG\xd7/N\xa5\x8c\xa1\xd0jt9\xc0\x14\xf3\xe6d~\x12\x8c\xfa\x97!$\xa3\xc1%zc\xfa&EoTm\xab\xbb!\xd6\x13\xcd\xda\xc2\xa90\x14\xd7\x90#\x16\xfec\xd2\xc8Y\xa4\x0e\xac\xf7\xf8]\xfd\xaf\xce\xb0zb\xd2\x0c\xa9\x96x\x16\xf8^\\\xb0,\xc2\xa5\xb0\xc9\x9b\xe1K\xd9\x06o\xc7\x8a\x9b\xa1\xf4\xfd\xac\x87\x0dk\xc9\xc71{\xdaa\x8d\x9f\xddp\x8a\x8dsI\x8d\xb0\"\xf6\xfa\xab\xe5\x1a=\xb9\x1ce\x97f\xfe\xbdX.b\x93\xa4\x06\xaa\x1f#*Q(\xa1\xc8)NM^\xa5\x1a\x108\xb1[oA\x83 \xedx\xd3\xd9r_\xc4AB?\xe6*\x84\x93\x19oE\x913\xf3=\xbdi4\xc0\xd1R!?\xccb\x02\xa6X\x86Y\x97\xda\xa0\nMr\xb0z\xa6i\xc2\x86b\xdc\x9d\x83^\x878\xb0\x0d\xba\x8f\xa86\x98\x1f;\x08\x03\xeb\xe0\x1e\xd5\x05\xcb\x7f\x05\xfe\xe9\x97VE\xe4xk\xea^\xbe\xdb,Z\x1d+\xfdBC\xee\xe8\x7fH\x85\xc5\xde\xaf\xcb:.Paa\x99\x94\xaf\xcb\xa2\x81Y\x94\xcb\xa2\xbd\xfd\x03Z\x97AD_\xfd\xa7.\xe3\x97\xde\x97$:\xadHw\x81X\x95\xec\x99%\x91,yj\x954i),!c!\x9b\xd9\xb3\xba\x9eH\xb5\xc6\xc0x?\x93\xefwI\x84j\x08S\xfaK\xd8\xb9\xd4\xf4,\x99\xa6g\xd1\xac\x0f\xb3\x10fJ\x06?\x7f\x7fz\xd2M\xefQ\xe6G\xd0\xa2\")\x81\x1b\xa3\xe9\xa2Z\x04-Ru\xa5\x08\xe8\xa3V\n\x01\xc7`>~x\xd3m,\xb2\xb3u\xb6\xd0\xfb\"\xc4\xf6\x86\xce\xfep~\xf6n\xa3\xde\xfe\x92\xa7\xa6\xb4u\x96MY\xc6\xa6\x9a\xee%\xe8\xdc\xff\x87\xd3\xf3\xb37\x7f<}\xb5\xc1\x18P\xf8\xc9X\x9e.n\xd8\xd4\xbb|\xf8\xb1\x8c\xcf?\xfep\xf1\xe1tc\xad\x0c\xad\x8fI\x84\x13\xbd]\x98J\x13\xdab\xde\xa2\xa4Qs=__\x15\x193e>]\xad\x14\x04\x0ehd\xdd\xa1\xf0\xfe\xf8\xc3\xf1\xdb\x87\x9a:\x9f\x9d{\xe6Y\xb4|\x17- \xd0\xc4U\x85\xd7\x84\xd6o]\x15\xdb\x85y\x13\xcc1\x9cg/\xce\xff\xe7\x92\x88 7!tB\xea\xbd\xf0T\xe6\xe7\xcf\xfc$\x9d\"\xd1\xda\x8a\x05g\x0dG\xb0\x16\xaa\x88$Z2\xa17\xeby\xb0\xad\xde\xc6\x89|\xc7?\xde\x11\x05\xaa\x1d\x1f\xf3\xf7\x97_\xc4\xf61\xca\xe9\xea\x02\x8e\xc0\xc3\x19\x8d?/\x17\x1e\x0c\xe5/Z\x7f\xa0i\xf7\x18\xe6\xf3F\xeb$7\xd6dA\x08#\x0f\xa1\xc9\n\x86Wv\x93\x10f\x97A\x08yg\xac9}\xfb\xfe\xe2O\x02w\xc6\xaf\xdf\x9d\xbc\xf9x\xfe\xba\x95\xb0l\x84EoY1O\x89\x1a\x0f\x83Kq2Y\xac\xa7\xect\xb9*\xee\xfe\xc8Ak\xf3-\xc2\x1cx+.y\x1ee\xc2v\x1be\x89\xef\xfd\x1ce \x06\x1el\x02\x08L\xd0\xe4\"I\x0b\xb8f \x17^\x19D\x80c\xfb\x1f\xec\xae\x87\x16d6\n\xe4\x18\x1d\xd7\x81#\x0f\xb3\xe8c\x04@\xce\xd9g/\x84\x9c\xaf\xfd\xba}\xed\xffx\xfc\xe6uE3\xce\x7f\xbd\xe5\x8e\xf3\xb3\xe3\xf3=z\xad5\x05YGH\x04\x84\xfa\x9f0\"\xe7\xb4\xe3\xd1\xe7\xe5\xe2Q\xdc+X^\xf8\xb1\xd8\xde\x1c\x0d\xd6K\x96\x8f\xc5\x96\xa4\xbe\xe4{x\xd2\xe3\x9ca\xc4\xa1\xf3s\x8c\xf3\x8bd\xcc\x10ArB\x18\xb1\x86!6\xdfcl4]c\xb7_R\xd3\xefx\xfb1S\xd6\x8f\x1a\xed\x10m\x95\x8e\x15\x94\x01\x95K\xecV\x18\"\x8e\xb0\x9bh\x11\xf3\xc9\xbd\xe7\xad\xa3\x91\xfb\"\x84\xb4\x835\x18\x87FAR\xe4\xa2\xa2\xc8!(\x0b\x85Ks\xfe\xa4\xd1\x93\x1d\x15\xa5}\x7f\x08\x93\xfco\xdc%\xdavx(\x1cH\xdaq`t\xd9\x15\x07\xbaX\x03\x81\xc5F\xd6\xacCj\xdd\x12\xb0\xdf\x18\xf0\xe7\xa7\x17\x9c\x9b{\x7f\xf6\xee\xfc\xc1\xb8\xb8\xcc\x8c\x07\x035\x1e\xce.\xc3k\x9d\xde\xd2A\xc8\xd6\x0ef\xc3_\xa3\x13\x1d\xc2\x07\x8e\xc0\xd0\xea\xdb\xa0\x15\xd6\xd2dP,\x8e\xfcC\xd1V/!\xcf\xc6\xd2\x90_T\x92? \x9e\xaa\x88\x8au\xce\x19\x16U\xb5zS_\x9bP\x96g,_\xa5I\x8eY\x02\xb2\xa07g\xd1\x94\xa19\xd2\xba\xfc\xfb\xcb\x17K?\xc0\x17c\x824\\\xe3}\xb1\x1d\x8e*i\x08\x91\x8b\xdd_;(\xe4B\xc1\xae\xf7\xc3\"\xbd\x12\xda\x97iTDzPm\xbb\x8e?A\x8a\xed\x1aD\x08^\xc1>\x17\x9cr\x88\xd6\xf8\x112\xe9\x88\x95\xff\xf1\xf1\xf4\xbc\xedJ\x7f\x03\xa4\xfc\xaf\xcd\x902\xd6\x90\xb2U\xec\xf8\xaf5\xcb\x0b9\xe9\xd8\x05\xf9.\xa2\x05\x9f\xf9\xdb\x8f\x17\xc7\x17\xa7\xaf\xfe\x91 \xb0\\\x17Q\xc1\xa6\x1f\x1e\x0e\x10\x929<{\x7f\xfa\xe1\xf8\xe2\xf5\xd9\xbb\xf1\xdb\xd3\x8bc~B||0:\xd5$r9\xa4\"\x01\x92O\xec\x8e\x96\xa6F\xad,\x85\x83[\xeaz\x1eYN\xa0\xe5J(V\x0e\xb5\x0e\xae\xcf\xf3 \x080{dY\xbd\xd2\x0el\xfcI\xab\x90\x8d\x9f\x1eUX\xe2\xaa\xb7\xe0\x87ll\x9f\xaci\xd0M\x1b$\x98\x87\x87>\xc5\x9a\xb0\xa3qOL\xd9\x82I&C'\x87Y\x08\xe9e;\xde\xab\xc9<\xe8\xd6\x7f\x98\xb9\x94{\xbb\xe3T8-;?\xf9\xe9\xf4\xed\x83\xadI>\x993\xeat\xfe&*\x96\xf2s,\xd6\x11\xd5\x13\xfdTT,\x13\xca\x87/_\xb0\x9e\xbc\xb6\x1dR\x1fxc \x83s\xf1\xe6\xb2\x9e\x97$(\x7fv\xbe\xbf\xdd\xa3c\x99=\xdb'4\xdd\xf2\xb67_\xb1I\xccr\xaf\x8b\x1d\x00\xb9\x16!\xb2d\x99\xcf\xd0_?/\xb2\xf5\xa4H3\x12zZ*\xa8HK\x0f\x7fx\x08~\x82mD\x01\xdf\xdb\x98\xdbh\x08\xa9n+\xd0\xe9*\xe1\xa6\x16\x87\x15\xe7\xb8\xff\x8cV\xd8\xef\x99 \x91\x86\x85\xfb\x94\xce>\xf1\x07V\x948\xa9\xb1\xa7\x14\xf6\x93\xde*K',78\xdbU\xc9\xfd\x94\x89\xf6k\xe5S,\xafg\xc0\xaf\xd7\x98c\x8d\xb7\x82\x9f<\x99GI\xc2\x0c\x85\xdb\x0d\xd6x\x15\xe7\xab\xa80\xc35/1\x1di\xed\xd55\x11\x80\xee\xae\xed*\xf7F\xa67\xd8\xb6\xc3_\x83\xd4\xea\\\x1bWJ>s\xe6\xbeW\x97Z\xd7V(R\xf5\x08\xba\x82\x15B(|B\x92\xa9\xbd1\xa6s\xd5h\\\xc1\x1fu\xe1%x\xcez[\xd5\x88V|\xe7O1\xc6\xc1\xaa\xb1\xc9*G\xba\x8c\xd6\xcaQ{\xf0\x9c2lJ\xaa\xe8\xaa\x95\x11S\xb2\xbd\xed\xb8g\xbb\x1emo/[o\xda\xd7\x8e$\x1a\xf2\x06\xe8\xc7j\xe0\xa1\x15\xae:\x84\xcc_\x06!,\xbf\xd3^5\xc7\x86\xd7VG\xff\xc8\x93[\x00\x87\x90\xf8\xcf\xf6\x02\x7f\x16\xe0\xb5l#\xec\xd0\x94\xe1\"\x9e|\xf2#\xff\x0e\xe3\x94\x0ct\xfe\x0f\x86p\x83\xc6`\xbd$\xbdmm\x0dk9\x1b\xc2\xd0\xc2\xb12\x19N\xd8-\xcc\x83\x1e'{\xbb\xfct\xe2\x7f\x0czi\"\x8578\x84\xab\x10\xbb\x8b\xfc\xb8\xb7J\xf3B\xeeB$5\x03d>&\xbdh:=\xbdaI\xf1&\xce\x0b\x96\xb0\x0c\\\x01\x0b\xb5\x06P\xdb=\xe9\xc5K\xde\xe39\x86S\xcdU\xd0c\xf7\xd4&\xfa\x18|tt\xe3\x07\xca\xef\xea\xa6\x87\xf6\x88t\xa7\xa1\xab\x10\xb6\xc4\xc8y_^\x9ad,\x9a\xde\xa1\x1d\xc2d\x1e%\xd7\xcc\x838\x81\x85\xef\x89 \xaf\x1e_>\xf7\x88\xf2^\xb4Z\xb1dz2\x8f\x17S_\xfb*\xe8\xd9-\xb7\xe1p\xde\xcb\xd82\xbda\xa21\x91 \xa7\xdc\xa7\x06\xce\xd6\x16\xb5a|\xac\xb8\x88\x97,]\x17\x1aF\x84\xd0\xaf\x1f\xb8\xfa\xd1g}?\x84\x95q\x06pZ=\x84i\xd5\x04\xfe\xf5\xedq2\x1bM\xebh:\xea\x08\xc2\xcd\x9f\x9b!\xb0v\xb2\xd9\x18\xc9\xb5\xb5kBQ\x02\xb2\xeb\xb6\x8e[\xa0\xb7)\xb3\xb3\xfb\x94dvv\xfb\x8f\xef\xc3\xe2`\xb2\x10\xa4\x95\xa9_\x88|\x1b:\x9b#\xed\xedJK\x08[\xf1\x82\x91\xa2{3;\xa5\x98\xf8\x82\xf3\xc2\xa8\x05\xe3b\x92\xb4\xa4\xe5\xec\xc32\xce7\x8cs[\x8fu\xffd\xef[\x02\xda\x17\xba\xe5\xc0!l\xb9\xcc\xb9w\xfb\xbf\xa4Q\x8e>\x1eY\xa7\x8b\xa5d+\xf3\"\x9c%\x1d\xa1\xc5]\xa8\x8f\x89\xe1\xd40j\x8aw2\x9a\x13\xd8\xe3\x81\xccOC\x88\\\xb5\xa112\x85zn\xa4\xb3}1J/\xfd\x88\xd0\x10\x98\x8f\xd0\x0e\xa2\x8a\xc2Y\xb7=\x8a\xb3ztF\x9e\x0c$\xa3\x1e\xdb\xe0K=x\xeb\xb7\xeeM\xd3\xa4\xda7%`\xd5N\xf0\xf3\x00c\xfav\xd0\x80\xab'\xf3=\xce\x15\xcb\xc8\x1b\x89\x88\xd7 \xd2'\\\xb6exq\x918\xc2^\nM\xc0\xb7R_\x84\xc9\x8e\xe5\xff\x98\x0d\x87\x8b\xdb\x9b\xa1Q5\xe9\xc1>}\xca>1\xe5j\xa9R\xd83St\xca\xfc\x15\xe6\xa1,\xc4\xf0\xa7\xfd.g2\xba\x1f\xe4\xd4\xc9\xbc\x15\xa1d\xa9TP\xf5\x8dX\nb\\\x84\xdf\x19\x84(\xb2\xa3\xa7|\x8aQ\xe2\x82@Jb\xa1\x90\xdaa\x07\x06!J\xe9\xecy\x99o\x12\xc5\xbe\xed\xed\x05\xbc\x80\xc9s\xd7\x81\xc2%\xa4\xb5_\x8c\x16\x97\x0e\x82\xcc\x05w\xc2y\x81O\x01{\x995I\xc7\\\xa6_\x8d\xa6\x0e\xe9XO\xaf\xcd\xbb\xe1\xc2C\xee\xdf\x840\x0da\xc5\x99{QA\x98r\xceQ\x80\xb9\xe1\x9c\xfc\x0d\x0c!\xe6c\xc6@\x17\xfc\xcd\xe8\x92\x9f\xceT\xf8!\xebM\xe6\xaf\xb0\x83y \x00\xc6\x87\xf7\x9d\xfb\x13\xb5>\xf7E\xc2\xbd\xfdN\xbc\x1bq\x14{\xe31\x9a\xb9\x8e\xc7b\xaf\xe0\x9e\xe0\x8c\x88\xfc\xc0\x86z{V\x9cZ\x12\x19\xa2\\Z\xa1\x12V1Zb\x1a\xc3\xbf\x01\x95\xd7\xa3\x82\x0b\xf7\x1b\x9a\xb5k\xf4\xc9\xe4\xc5\xd261\xab9\x10\x16C\x95\x9c0\xc4\x0d\xc1\xab\x9b\xe2\xb6\xc5\x8f\xc10\x94\\&E\xb3\x07B\x06p\x9b\xf7\x7f\xf5\x1d\x8b\x9dv\x81\xc7/lN\x1cBQ7\xa1\xc8Q\x17\xcd>\xb3\xc9\xba`\xf2N\x0b_ \xfb\x81?\xe4ir\xbeb\x13\xed\x95\xfc\xe9\nJ\x11\xfb\x89\xbfO\x862\xe7%\x83=\x87\xa3<\x91\xecX\xad\xc5/c\x0b\\\x9bL\xa3\x0cU\xa9\xec\xf3\x15\x9bH\x07\x05R\x1aj\xc4VfX\xf6TL{(L\xd1rv\x91rx\xcbz\x89^\xc55\xa1\x90Z\xa9_c655\xa1\xa9\x1b\x0c+\xc71\x14 #\xcc\xe5\x04\x11\xbc\x80\xe29D\xdb\xdb\x01\xc4\xa3\xe8\xb2\x96&$\"\x0e\x08\x13d1\x82*N\x14\x06\x7f\xa8_\xcf\x9dD\x939\xa3\\\x8c\x94\xd4\x11\x8f\xfa\x0e\x07\xa5\xdc\x0eP\xbf\x0e\xab;\xce\x80\xb2K\xe0\x8f_\x8f\xb9I\xe5\xacq\xf2\xe9F\x7f9\x1a{\x05\xbd\x7f\xc9\xd8\x8c\xa3<\xdeb\xf3\xedh\xcc\xd2W\xa3\n\x81]n\xc2\x80\x87\xd4F\x7fh\\!\xcd\xb8\x94\x0c\xda[\xa4\xd7\xb2k\xe1\xb6\xea\x9b\x1a\xdc\xfah-J\xb5\xc1h\xcb\xb0\x8c\xf7\x1f/\xc3`\xc7\xd2\xae\xd0\x8aRcP\x95\xbf?]\xef\xa2c\xb8\xd1c\xbd\x9d\xa4\xcbU\x9a`VJ\x0b\x04e\x94\xb6\xf3\"\xcd\x1c\xd6\x01Z\xa0b\xbb\x02\xde\xaa\xd5z\xb1\xeb\x08\xab\xa6\x8c%S\x96\xd9\xa5\xb9\x0c\x1c\xfe\x89\xbd\x8dV+6=I\x93\"\x8a\x13\xaa\xea\xa2\xdc\xbeK\xb6L\xe3\xbf\xb2\xc0\x8fDvr\x91>:F\x1e\xdcJ\xa2\xe5T\x0bfiZ\xbcN\xf8\xda8\x9d\xd9\xf4\x99\x0d\x810\x1c\xe7\x0f1\xf8\xa19\xd0\xdc\x1e\xe8\x02\xc7J7)\xa05\x84\xb5\xfdYd\xdd\x88\x80\xc5\xcb\xba=\xd5Z/\x9a6r\xf6\x02\x0d\xd9(\xc2\xd9\xe2\xf4\x05\xbf\xa8\xe3\x17Tk\xeft\xfe\x02d\xe58\xf3\xfe\x94bf\xd0=\xea7\xb2\xf1uTD\xfa'p\x04\xff$0\xb0\x81y\xbb\xe6\xcc\xdbcj\xbe\xd7$[\x17\xcb\x12\xda\xe5\x0cK\xac\xd6\xd6\xaa5\xca\x01\x11?1\x0b\x16\xb2\xc0\xead\"\x0b\xac>f\xb2\xe0\xc0,X\xe1\xd2\x99\x97\xe4S\xac\xbe2\xde\xcee#O\x9eXC\xbd\x11\xe2\xffc\xf3\xfa|)?y\xfa\xf8\x19\xcd\xe6^\xff\xbal._W+\x1d\xb4C\xe5k\x13\x81\x06\xa3l \x8eR\xa7\"Y=\x9a&\xb9\xad*\xd4\xaf\x18\xf2\x8aM\x12\x1a\xefL\xda\xe1L\xcc\x02?\xeb\x952\xb3\x8a\xe8\xbf\xae\x19\x9594\xe7n\x0d)\x90:\x04\xfd\xd1F:\xab\x19\x06%r\x98\x8b\xda\xdbQ\xfb\xdc?\xb1\xbb!xb\x1f{\xf4A\xa0?\x9224r\xec\xd4#\x07>-\xf5\xd7\"\xee\xc7\xa9Hl\xcf\xe9\x91a\xbf\xf67\xf4u\x0fdn\xf3U\x96\xaer\xf9\xf7$M\n\xf6\xb9h\x81#\xb4\xc2\xf2\xebe\x10\x12\xe1\xd8\xcbb\x7f\xd5+\x89\x9dK9\x8d\x98KC-\x95\x9c\xc2\x0d\x1fp\xc2&\x85\x16\xdb\xa4-\x80\xeb\x8dL\x8eo\x9a_\x7fE31\xe6S\xd1'\xd5\xa3PD?\xbe\x96\xd1\ns\xd0_\xa4\xfc\x04@\xdb\xe7v\xa9\xc1h\xb0}\x9d\xf1\xde\x9a\xba\xc7\xd4\x1f\xf7\x9a|\x0d\xfc\xa4\x8c\xf1D\x146d\xf6Ij7\xee\x0d\xd4d#J\xb2\x01\x15\xf9\xadP\x107t\x1f\x96rl@5\xeeC1Z\xa8\xc5M\xef}\x96\xde\xc4\x9c\x97\xef\xd0\x18 j\xa6Y+j\x82\xe0\xb16\xa3Qn\xf2t_:\xdf@\x97Zh\xd2W\xb1\x81`h$\x0ci\xb4\xf4j\x8c(]r\xc6)\xe7\x8c\x1b=\xa7by\xd9JS&\xd2\xba'\x1670\xc9(\xbd\x0c!\xc3\x7f\x19\x99\x88\xa6i6c\xbc\xacp\xb0\x9f\xc44\x85\xcdc\x830\xde,\xb1C\x9d0\xb8x\x1c\xf58(\x82\x9b|\xeb\xa4\xff>\x14C\xa4\xac\xc5\xda8\xb6\xf6\x93\xe2\x8a\x03'\x12Z~\x8c\xb2G\xa3^\x13=\xb5\xa9J\xb1)U\x11\x14e\xa2\x90\xfb\xe7x\xb1\xf8\xc0&,\xbeA\xa1%o 2&\x81id%\xf9\xa3M\xb8\xda\xbd\x9b\xd2\xd4\xafM\xa4\xa7#y\xdc\x944\xaa\xcb\x06\x0e\xd8e\x1d7\x14 \x8a\xa4\xd3\x96\xa6\xee\x8b8A\x18\xb9n\xdc\xf4\xa7@a#\x0e\xc1\xcb\xd2\xb4p\xdd\\\xa8\xa7\x9d\xa5\xdb\xd8\xec\xc1A\xfa\x1a\xc8\xde\xd7P\x97B\xc9\xedn\xc5c\x03\x8db\xa9\xaaY\x08\xde\xf1j\xe55\xcc}\xde\xabl/x\x7f\xbek\xe6q\x88\xb7\xa2\x81\xc5\xcc\xb4\x1aUTJ\xb3$Z\x12z\x8e\x16\x90{\xd3\xf8\xc6\x92\xe5\xd5\x93\x17w\x0b\xd6\x14\x14i\x15M\xa7\xe8B\xee\x0d\xd8\xb2\x01k'\xe9\"\xcd\x86\xe0\xfd\xff\xa2(r\xe4\xbd\xb3W0\x04\xef\xff\xf9\xdf\xff\xb7\xff\x03<\xf7\xf9\xea\xc5\x9e\x00\\\x08\xdeI\xe9\xa8.\xd7\x96/\x0c\xe6\xbf>\x84\x02\x8e\xc0\xe38\x0f%\xb5\xf0`\xc8\x17\xd1\x0b!g\x0c\x8a9+\xbd\xe3=+\xe4w}b\xb7\xad\xca(\xb5&\xdd\x18f\xb9B[>\xab\xd8o!oW\xdcx\x9c\x7f`\xd1\xa4h\x17.\x9a\x0dI\xf5\xa7\xf3\xd1\xa5\x9e\xf2\x08k\xa7:\xd0\xc2\xdf&N\xfe6i<\xad\x92{\xf0\xb7\xd0*\xd5\xd1'RB\x9eHI+\x9f\x0b\xdd\x89\xb9z6%\xea\xea\xa9\xae\x02:\x9cI\xea\xe9 \xe1&n\x1a\xdcI\xc2\xc5\x1bwz\xda\xd2\xbd\xa8Dl\x01\xa3\x06\x0d\xa8Y\xb5\xed\xde\x1dZM\xfdJ\x06\x95\x91\xb7\x83Yy;\x88\x96\xa9\xe2v0\x85\x17\xc0\x9eC\xba\xbd\x1d \xd7Y\xbb\x1dt1\xb0\xa0\xdf.\xe9h\x9b9 \xd7\xc9TP\xb6XOG\xc5\x87\xea\"\x92\xe36\x89G:d;VL=\xc27\xbb\xc0c\xc6\x8d\x1f\x8e\x99Q\xd4\xddPgW0\xb4\x94\xc6\xf6\x19\x9d\x86\x10\x9b@\x8ag\xe0\x97\xc6[U\xe2\xbf4\x90A+\x13v\x0b\x17w+v*\x12x\xbdcl\n\x11\x88\x0fB(R\x981\x0e\xfd\xa8:#z\xf0s\x94\xc3u|\xc3\x12\x880\xd5\x8d\xaf\x99\x04\xa5\xfcPY'BM>\xe5\xe7\x89q\xe1\x9aZA08\xd6 \xa3-3*\x84\\U\xce\x8b\xc5\xbc]\xe4(\xb0\x1b\xfe\xf3N\xb1\x9f>\xfa\x14\xe0\xcf[?\xc2\x1f\xb7\x82[\xf3\x99\x1f\xf4\x16\xe9\xb5\x0c\xeeR\x9d\x86\xb38\x99j\xc7\x1e\xe70$\xb3Q\x0e\xa0\xd3%\xa1\xdb|_Nx\x08\x89\xff\xe4\x89i\xc8W\xe9\x8c\xeb\x97\x03]\xba\xa4\xaf'\xdc\x03\x99G9^\xb3\x0bG\x89w\xe9\x94\xe5C\x18\xddX\x12\xc2:\x04\xe1V\xa4\x90\xd5w\x10T4\xdb\x16\xb1\x93\x1c'\x838\x94\xd7x\n$x\np\xc4Jz\xf2,\x80\xa1\x8a_\x87\xb1\x89\x9d:\xee\x05\xca\x11\x92\xfd\xec)\xa4\xc6hl[\xfd\xc6\x03\xd0\x81\x8e\x8dwR4,\x0b\xa1U\xd1\x1b4\xb8@\xd26[g\xd0\x84\x1b\xec7\xf1\\\xf5Q\xcbKC\x93\xceO\xd1b\x8cz[\xc4K\xa2\xc4SE;\x8bt\x12-<\xbb\x06[F\xf1\xc2~\xbdL\x93bn\xbfN\xd6\xcb+F\x8ck\x15\xe5\xf9m\x9aM\xed\x92\x8c\xef\x07\xfbu\xce\xa2lBtP0b0\x9c\xef'\xde\x923^gD\x03\xb7\x8c}\xaak`\xdb\x94tN.W\\N*v\xb6\xfe\xab\xce\xb5\x92\xac\xae\xce\xe5\x16p\x04[[\xd9Hp\xce\x98b\x8e\xcf4\xcaX$+T\xe3}p\xfc\x12\xa9\x03\xcf'\\\x8c|\xc3f\xc5\xd0\x0c\xe1U\xabq\x91\xae\xac\n\x19\x9be,\x9f\x8b\n\xb8m\xf3\xb6}\x98\xf5\xac~Q:\xf8\x1c\x9aE\x17)\xfaK\xf7\xeejm\xb4\xee\xc3\xec\xdb\xe1\xe4R\x83\xfa\x83\xc7\xa6u\xbatM\xb7B\xc1E]\xd4W\x9c\x82\xb7\x86\xd6f\xbdY\x9c\xe5\x05\xaa\xf4\xddZ\x1b\x94\x9f\x12\x112\x06\xd3ic}\xferO\x8aS\x1cC/\xeeV\xd5\x89s\x93\xc6S_\xbc\xc7\xa5\x83\xc3v\x0f\x15@`k\xeaX\x8bU\xd2V\xc5T\xfbvW\xf9r\xae\xba\x15\x82{\"a]918\xe2\xc4]\x04\xd3AMy}j\x15\xde\x04F0\xa6o\xa0\xdc\xdd(\x07}\x1f\xcbz\xb3t\xb2\xce\xcds\x86v^~\xf0\xdd\x1f%\xf1\x12c\xdb\xbf.d\x90\xfb\x93t\x9d\x104\xf6*\xcd\xa6,{\xbd\x8c\xae\xd9\xd9\xba@\x06\xbf\xa1\xca\xf9\"\x9e\x10$Y\xab\xf1s<\xa5\x8e\x95\xab\xf4\xf3\x8f\x0b\xf6\xd9Y\xf0\xfb,]\xaf\xc8\xd2\xb3l\x1a'\xd1\xc2Qa\x92.\xd6K\xd7\xdcDan\x17\xcc\xc8\xa1\xcc\xc48n\xe9\x92\xf7i\x1e\x17\xf1\x0d1{^z>\xcf\xe2\xe4\x13]\xf6\x8e]G\xee/1\\\xb1]t\x9d\xc5\xd3\x0f\xd4Xd\xc1iB\x1c\xc5\xb2\xec|\x15%\xee\xc2\"\xca\x08X\xf1\xd2\x13\x84WS\x99\xb3WQ\xec\xeeX\x96\xd3}\xcf\xd2\xa4\xf8\x99\xc5\xd7s\xa2l\x11'\xecd\x11-\x89\xb5\xe7E?9>KW\xd1$.\xee\x88\x02\x1a\xdci\xb6\x9aG\x14\xaa\x14\xd1\xd5y\xfcWb\xedn\xe3izK|\xf0\xd7\xd7\xc9\x94\xc2\xae\xbf\xa6\xe9\x92\x98z\xbcX\x9c\xb9\xc6:[\xa4\xe9\xd4Y\xca\xb9\xd9\x86\xc2,\xfd\xc4^E\xf9<\xca\xb2\xa8\xb1B:\x9b\x91\xdb^\xd4x\x1b\x17,[\xc4\xcb\xd8Y\xa3e\x0c%A(\xcb\xbe\xda\x17p#\xefgv\xf5).\xbc\x10\xbce\xce\xff}\x9b\xfe\x95\xffw\xe6i\x9a\x1e\xa9\x89\xf9\xc4\xeer?\xeb\xe2\xee\x9d\xdauh\xa7\xe3Q\xeba\x0e\x9a:\x11\x13WL\xe6Qv\\\xf8\xfd\xa0W\xa4\x1f\xb90+5\x99\xbc,__ \xc3\x0b\x7f@\xd9\xa4\xa3!\xe8%gf\xf4\xd0\x97X\xa6\xa98\x8d{\xca\xd8\xa2\xf1q\xfe1\x89\x8b\x05\xcb\xf3w\x92i7\xdcs\xf3y\x9a\x15\xf3(\x99*\xad\xd5\xe9\xe7U\x94\xe4\"'\xa3=\xc5\xabh\xf2\xe9:K\xd7|\x8f\xd3\x00\xa8j\x1c\x17E4\x99/\x19Ev\xed\xda'\xb4\xaccW\xc4#\xa4KEA\x8d\xd3\xe4\x7fnR\xf9O]*\x7f`+\x16\x15C*\x8d)\xa1:\xb1;i\x87\xdd\xfd\xc7\xdeiD\x92\xc29F\x81\xa5\x8eC\xba^\xe9\\\x98\xc76W*W\xb6\xfb\xd0~H\x8b\x82\x93\xc2\xa6\x01\x8a:\x9d\x86)\xaav\x1a\xac\xa8z\x8f!\x0b\xf1\xa9i\xc0\xbcF\xa7\xe1\xf2\x8a\x9d\x06\xcb+\xdec\xa8\x1f\xc4y\xd84V\xac\xd2i\xb0X\xb3\xd3h\xb1\xe6=\x86\x8bbg\xd3`/\xd2U\xa7\xa1^\xa4\xabN\x03\xbdHW\x1b\x0d\x93\xf3&\xae\x11\xf2\xb2\x96Ny\x95?FY\x1c5\x11\xca&\xfeG\xafC3\"\xeaib\x87\xd4\xc3[\xf91Z\xc6\x8b\xbb\xae\xf3O\xd7\x05o\xd8\x05\x02Y\xdc\xb2D\xb2V\x0b\xacd\xad\x86\xe5\xf9\x8e\xfe\xe5P\x15\xc4\xf8\xf6\x9b\x84\xaa\xc4\x7fj\x06\xe3K\x85a\xd0`\x1f\xe3\x02\xee\x89\xf0\x80O\xfb\x96\x83\xbc4 \xc2rv\x0b\x1f\xd8\xf5\xe9\xe7\x95\xef\xfd\xe7\xc8\x83m\xc8z\xc7\x17\x17\x1f^\xff\xf0\xf1\xe2t\xfc\xee\xf8\xed\xe9\xf8\xfc\xe2\xf8\xc3\xc5\xf8\xe4\xa7\xe3\x0f\xb0\x0d\xde%]\xa9,\xfe\xdd\xbfXi\xcd\"\"\x1e\xfbZ\x06\x80(_\x96w\xa5\xb9\xf3\xaetkkmG`\xc7\x00\x81\x11\xf1\x9e\xcb\xfd2\xfb\x1a\x1a\xb4\xf9\xeb\x11\xbb\xc4\xb0\xaf\xa8\xdd\x85!\xf8\x91\xf6\xa6\x16H\x9bNs\xdc\xc5\x9e\x10\xf3\x84\xcc\xa3\xfc\x874]\xb0(\x11:\x80\xef\xbf\x87\xad\xaa\xe8\xddz\xc9\xb2xR\x16\xc5\xf9\xbb\xe8\x1dg\xfeT\x05%\xce\x99\x15\x0bx\x01\x83\xb2\xd6\xd9\x0d\xcb\x16i4eS\xab\xaf\x01\xa9\xc0\x03\x89<\x13[\x1f\x87V\xcbo\xa3\xec\xd3z\xf5c\x9a\xbd~\xd5\xaaJ\x13\xd3\xcez\xaf_\x8d\xeb\x88\xc0q\xe0\x90cHj\x85\xb4\xae#@\xce\x8a\xe3\xa2\xc8\xe2\xabu\xc1\xac>\x1d\x8c.f\x9b(\xbf\xf2\x89\xee\x89\xe0\xefM3\xfd\x90\xa6m\xd7\x95\xe5T?\x9c\x9d]\xd8\x93\xfd\xb7C\xcf\xfb\xb7\x0d\xe6i\xf4HB\xd7\x9a&\xd1uXK\xdcK\xf4k\xccT\xed\x8c\x0ePV\xea?\xbc\xfc\xe6\x1f\xc5,'\xf6\xd7Q\xad\xc2\x08U\xc8\xb4Q\x15j ]\x82\x0bF\x8b\x14.\x1f\xa5~\xd0\xf3huc\xe9\x07\xd6\x8b\x14tl\xb3\x0e\xf5\x94\xf6\xff\xe6n\xfc\xf2E\xbcl\xd8@\xfdRE\x1e\xab5\x86!\xfe\xad\x90\xbb\x93\xbe\xb2\xc4\x9d8?Y\xe7E\xba\xac\x16\x15\x01X\x91\x0d\xbc\xc1\x1a\xa2\xf8V\xf5 \x01\xba\xc1*\x1b\xbdtXl9\xc4\\RL\x15{\xa7\xc00#\xc6`<\xaf\x05\xd1\x11\x80ndk\x880\x92\xb6\xe0[a\xe1[\xd1\x8co\xa4\x1f!h8\x94\xf60cW\x9c&T\xbeD\xf5\xf0\xa6\xe2@hw]\x06~l\x913GgP\"x\x8a\xee\xbd\xba\x02\\\x98}\x89\xabb\x13pb\xb9\xe8\xeeT\x9b|\x02y\xf11/\xed>\xd0$Q\x81\xe8\x8eo\x8cK:@\xabzZ\x06\x0e\x9a\xbdQZ\xdfq4\x93\xa4?k\xfb\xa3|\x15M\x1c{\xb5\xfa\xea\xc8\xa0~\xef\xce\xfd\xb5\xc8\xa2\x877\xbc\xe8.O\xed\xe8\xb4\xd3\x8eN\xac\xf6}l:P\xa9\x8c\x8c\xf7\xd8\xa5s\xc4\x8e+|\x9b0\x08Hc\xd0}\x82\x14\x14\x06^Lz\xdaV\xd2(\x86\xdcA\x1d\xf7\xa0\x8b\x0886a.\xf3\x00\xf8\x8a& P\x89\x84\x15\xfaXmH\x15%\xa4\x1a\xc7V\xc7\xf4Mh\x145\x8c\xee==\xf0\xc9\xb71%r\x9e|\xa5\x85\x7fgJ\x94\x06\x9c\xad\nU\xf0\xe3\x06r\x84\x1d\xdb\x04\xc2\xbd\xd9\xab\xa3U' \xee\xddj\x1f\xabG\xc0F1\xb2\xd3\x03\x0c\xfb\x8b\x7f{\x0e\x9fc1J{a\x8d\x93\x9d8d\xc5\x97\xf4>\x12\x17\xe2m\xc8R\xfer\xc8f\"9\xe77\xcaf\x03*lq\xe2\xef\x0e\x1c\x11\xc6\xcdp\xeb2\xcf\x97\xd9\xca\xba\x92\xdc\xb6\x06\xa4\x91lnq\xb1x\xd7\x8bV\xccY\x9a\xa25\xcd\xebW\x95\x0dv\xcd\xdci\xc5\x92i\x9c\\\x7fD\xa3\"\n]\xda\xbe\xc1\xe5\xb7\xb1\xc6\xf0.\x10w\xed\xf2\xcaU\x06C \xf1\x04\xc3\x9aW\xf6B\x94\xfdL\xc5\xb1|\xff=(\x03>\x89\x98>\xeb-\xd7\x8b\"^-\xa8\xb4P\x15\x1e8\xc5=\x82X\xde\x94\xd9\xd8\"\xcc\x81B\x1b(\xf5\xd2UaGEu\xde\xba\xa3\xbbA&\xc4d\xdd\xe5 \xa9\xbb\x1cd#AhG\xe9\xe5\xff\xcb\xde\xbbv\xc7\x8d\x1b\x0d\xc2\xdf\xf3+J\xcc\xacCF4\xad\x8b\xc7c\xb7G\xd1\xeb\xb1\xe5\x8d\xb3\xe3\xcbZ\x9e\xe4\xeci+Z\xaa\x1b\xdd\xcd\x11\x9bdH\xb6de\xac\xe7\xb7\xbf\x07\x85\x0bA\x12 \xc0\xb6<\x93d\x1f|\xb0\xd5$\x88K\xa1P\xa8*\xd4\xe5\xac\x93\xc0\xa4\xd5\x92\xd2B\xdcn\xc1L\x89X\xd0\xcd\x0e\xb1\x8b\xa7\xf9\x197\xa4\xd2\x93\x02\xacPaLU2\xc7[\xf1\x0d\x9e\"\xed\xe7Gj\x82xQ:\x1a\x13\x137\"A\xc3\xa6\xde\x02O{r\xda\x01R\x907\xb3@&\xa0l\xdb!t\x87\xba\xa3#\xac\xb1\xe2k\xe2\xc7\xd3\xbd\xee\x17F\xcc\x12\x7f\xe9\x05\xef%\xa9\xff\x9cW5\x06Mq8\x9f\x84<\xc1b\x19\x99\xecA\xf3\x8c\xd9\x01Nz\xd6\x8c\xe2\x8d~\xb3q_xv\xb8\xf4\x97k\xf0\xc8]\xe7\x9b\xac\xfe\x1b\xeb\xcba\"\xe2\xa0U\xf6\xb6\x8e\xdd\xed\x8c\xbf\x07>QZ$\xc8\x9c1*\xc9\x92:\x89Sn\xb9*\x08\x07et2\x984!?\xf1\xbdI\x8f\xc9\x12\x8eU\xecs\x83\xaeP\xc2\x7fX\xcc\x17EXw\x8d%\x8e\xa20@\xf2\x10\xceoy\xe7\xec\"\xcf|~\xeb\x0e\x04\xdf\x85\xba\x9b\xd8\x0eP\xcd\xb9\xe3*.|\x1ec\xcb\x18\xd5\xe0\x96\x85\xaa5\xd9\xf9_\xc7\xd5kN\xbc'\x92\xa0\xd7\x0dA\xefch\xa8\xa6\x8d\xa8\xf9\x8eW\x13r\x1eu\x16\x99\xbe\xdc\xa0\xc9\xcfF\xb7\x8d\xc3\xee^e\xc1\xa3\xf1\xd3\xe7\xcc!\xc8\xb6\xc6\x06/\x0f\x15\x13\x87\xfa,\xf2\xaaf\xa0\xd7\xec-\xd3\xc6bVmZD\xb2n\xb1\xd6\xc8\x0cY\xe7\xa1e\"\xd6\xfe\\Y4{_Je8\xd2-\xb1\xbe\xdf\xd2N8\xc4\xde.\x99\x7f\xb6\x8da \xd9q\xaf\x19A\x08%Ztex\xb6i*42\xd3N\x0f\xbb\x8e\x07\x9amW\xa5]\x0c\xd5\x15?D>\x13\xaf\x17)G\xfe\xfa\xaaLm7\xb0m\xae\xe7u\x19O\xfbx\xbf\x1b\x91\x80g\xcdy\xd45q\xdc\xf0\xe7\xdd\xfb\x8c\x8a;:\xd3\x0e\x809<3\xdewx\x13 \x19\x93N<==\xb4\x96m\xd6\xab\xf7\x11\xcd\xfb<\x1c\x97\x91\x8fxz\xa2}\x91/\x8f\xee\x88\x98\xc7\x00\xf1\xd3\x0e^J\xb9\xccc\xd9\x92Zi\x8e\x86\xf4b\x86\xb3\x88)\xb1h\x03z\xb9S\xeb:\x84A\xfc4\xa1:z!=D\x11|\x8bI%\xbb\x17\xc2\x0cv]\xbc@Ax\xf9\x0eU\x80\x16\x0d\xa3\xbcu\xbc\xd6\xe6nP\x0bg\xab\x85\xf2\x18\x9e\xaf\xc8\xec\x12\x03K\xf1\xc05,\xf55\xe4\x0b\xf8\xbf\xe8\xa3\x05\xbb\xe0\xfd\xdfH/\x9a\x82Q\xb1\x03\x8a!\xb5A\xac\xf5\xf3\xe8<\xbf\xceHI \x87\xef\xed\x1f\xeeyMX\x89\x04\xd5\xc9\x13 \xf2\x10f6\xae\x98\x16MV,\xb6\xec\xc8\xb7\x1c\xc1\x86#\xdc\xab\xac&e\x16\xa72|\x8b\x8f\xc1%]<`\xc4\xac\x1a\x8cQ3p\xdd\xbb'NPf\xf5\xda\n\x95\xa5\xffF\x8dfK9\xc3&\xa4\x8c\xcb'%\x0b%(?\xea\x03\xc9g\x10\x088\x082r\x0d\x15\x9b\xae/~\xb3\x1a~\x1e\x04\x11\xe7\xb2)\xa3\x83\x87}\xd6zr\x04\x19C4\xbcr\xcb\xe7]r\xc16\xae)7\x99\xc7\x9c\x12\xba9\x89\xdb\x0b\xc3\x9d+s\x0c\x1c\xe1#\xb5G\xec\xd8\xf7\xc2\x86\x02\xb4q\\\xde^\x9c#\x00\xd1p\x8fy\x8f\xcbGk\x96\xc1\x97\xb9)w\xf3+\xd1\x92\xfb\x95\xea\xbf\x98t\x05\x86s\x16\xc9\xa1N0g\x8a\x1a\xe4l\x02\xcd\xadC7\x81,{\xf3uN\x92\xef\xbay\xd6\x94P\x17}\xd4\xfd\xf3\xdb\xd3\x0f=\xc7\x00Z\x9e\xbf}\xfd\xee\xed\xe9\xab\x0f'\x13\xd0\x88\x02'\xaf\xdf}\xf8?\x138\xe8\xbfY\x92\xfa\xc3M\xe1\xc4\xb8\xb7/~;'\x01\xdd\xe8\x11v\x83\xea\xea\xa4\xfak\x9c&s\x11\x15\n\xd1\xd6\xb0 \xf8\xbeN\"9\x05\x98@\x12\xd1\x99\x8a\xa4g\xa5\xef\x1d<\xd2'o\xec\x88\xd4\x067\xf1/\xb5=`\"x\x1f, f\xc68Y\x17\xf5\x8dD\xa4\x97\xf1\xac\xce\xcb\x1b'\x88R\x92o\x9bR\x1f;\xfa\x8d\xb1]\xe7\xd4\xa5\x90\xa7\xed\xb0l`\x90Dl\xa2\x94k8\x82<\xbcS\xd8\x9a7\x07\xdf\x05,Ve\x0f\nm\xf5\xf3\x95\xd6K\xdcpL\xd8\x00\xc5\x81\x94S\x04\xa7Tk\x9fR-\x86\xa9\xdc~\xc4v\xd5\xaf%\x83\x8e\xddb\x82ZK\xfbI\xf5\x01\xdd;\xc6M\xa8\x15\xc8&\x19l_\xac\xb7\xce\xd2\x88\xbd\xfc\x9f$#e2\x93cx\x9e\xc6\x95\xd5! \xf8\xd2j\xb0\xbeO\x9bX?\xad\x89:w\x92\xb8l-\xf9\xeb\xeby\x19\x9aQ\xfb\xe1#\xc6\xe1\xef\xf7rj\x08YB\x97\x81S\xec \xff\xa0\x9fiD\xd1\x94{\x91\xa7\x11,\xbc\x89\xe7.\x08H\x9c\xa1\xfc\x8b\x86\x7fW\xef\xceItIn\xe0\x18\xe2\x88T\xb3\xb8 >>\x08P\xc5T\xe7,G\xaa\x7f\xf8H57\x12\x7f\x8d\x89\xd9\xd51=\xa2\xc7\xc6\x9e\x92+\x9e\xa7\xa9\na\x16\xea\x13q\xd2E)BLr\xc2gQ\x1b\x04 %\xd2\x1e\xe5\x00\xd1\xb7\xcb\xbb`\x92\xaaxD\xf9\xaa\x9a\x13\xa2&\x94\x9a\x88\x94\xd10O\xbc\xae\xc26\x89'\x0dTy\x17u\xf4\xcd7|d\x18\xf4Or\xf83\x7f\x81 \xf1\x85p\xa2\x07\x8b\xc6\x0e\xa3\xf7\x84\x13\x94U\xeb\x05\x86\xda\xf0\xbc\xae\xb9\xc5\x97\xfaA\xb2\xd0\xa9h\xcb\xb2 \xa1\xc2tn3v(\xeeuo\x7f\x17\xec\xf6\xf7Q'\xe0%S\x7f\xe9N\xad\xc2\xec4\xfe\x92\xd7Q\x04lq\n\xf5\x177k\x02\xe4\x98\xf2\xa9\xf5?\xa2G\xbb\xb4!\xf6\x98\x07\x12\x06\x89\x0c\xa2\x92\x14i<#\xfe\x83\xe9\xc7\x8f\x7f\xff&\xfa\xe3\xee\xb1\x1fL?\x9e\xfdr\xfb\xf9\xec\xc12\x04\xef\xe3\xc7o\xeeyJ\xb5vW\x9f\xa5oT\x10\xfd\xf1\xd8?>\xfa\xf8\xf1\xa3\x1f|\xc6m\x1b\xed\xf2\x07g\x01\xb6\xf4\xcd~\xf4\xc7c\x86\x18\xdft\x03\xc2\xeb\xbd`\x85~\x8d\x8fV\xa7n\x96\x06|hF\xdc\x0d\x10?\x184X\xd8,\xef\xb7\xbf\xf9]\xff\xaf\x8e\xb2\xae\xe1*\xd8\x11\xb3(\xf3\xb5Qm\xf2:\xc6T\xde\x85\xff:.Z\x06|\xaf\xe3\xc2AQ\xd3\xaa\x85\xdbL\xb6\xd6y\x1e\x18\xdb8%5\xfb\xe8\x94\xd4\xad!\x9c\x92\xdaa\x08\xadZ\xca\x10\xfa\xcf{q\xa4\xaex\x92r*#\xbc\x8e\x8b>b\xae\xf8\xcbS\xd2am\x9c\x12\x9a\xcd\xa3\x8a\xd4\xecm{\x0d\xc3v\x0e\xea\xa1\xe5\x9fGK\xd2\xd7@\xb3D\xb8\xc3\x0d\xcc\xb9i\xa0\xe6\xe3\xd8\x16T\x8ew\xde\xe0\x8f?g4\xb4g\xa1\x85l\xf2\xf0@VQ<\x9fkF1\xecx\x0e<\x07\x83a\n\xd6\x98\x94\xfd)\xac\xf4Sh6\x94\x8e)\xba\xe2\x99\xe6\xbb\xee\x07\xc0\xb3\xf2\xe9\x9e/\xad\x13\x03Eg\x1a\xe9C\x1ai\xda\xbd\x19\xd3.&~~\x95\xd5>\xe1\x1e\x9b\xfe>ej\xf74\x8a\x8a-P[\\\xdf-\xb5T\xef\x8ae\xc8\xac\xc7c\xbd8s\xf4\xed\n\xab\x8bi}6~?\x0c7\xcd#.\xe9\x9av\xdd-*\xafq\x15D\xeb\xb8\xf0o\xb6\xd8.\xc3\xe3\\\xb3l\xf8\xddD\xf9.\xbb\xc9 \x00k\x0d\x00\\\xf7\x9a\n\x80\xb5\x1e\x00\xbf\xeb\xffE\x87E\x05\x85\xe9\x99\x8e/97\xf3%yo\x1eF\xf3\xa8+\x99\xc2y\xb6J\xd2\xf9\xab\x17:\x99\x0c\xc3Oe\xd2\xab\xfa|\x8c\xb5\xd7\xb5E\xc8\xf6>f\xd8G\xc6B\xd13\xcd\xffO\xd9e\x96_g\xc8s\xf8h\xc2\x0f~\\\x03c\x80\x16I\xca\xa2\xf2H\xd6\xe6\xef\xd1\x1f\xa7\x1f?~|p\xf6\x80Y\x1c\xef\x827au\xd3$#\xccM\x9a>\x0c<\x14<\xb19\xa69\x9b\xc3\xc5\x0d6\x9b\xc9\xf7\xaa\xf3\x87nB'}\xb8k\xf4\x05\xde\xef\xc9\xba\xa8o\xb0\xc1q\xf7\x1b\xde\xefk\xf2\xa96}(\xd4\xd8\xfc\x8f \xff#\x9a'U\x91\xc6hY\xca\xdc\x98\xf0i\xc6\x7fJ\x80\x0e\xce\xec\x93\x01\xa3B\xc4\x90Sz\xde\xbeh\xba\xd1Z\x97\x94\xa2b\xa3\x91\xefW\xcaE\xa5\xb7\xd7\x19)_\xbd\xe8a\xab\xd4\x8b\xa2\xe5\x8c\xae\xef<\x08B\xb8\xc6\xfc\x91\x80\xb1\xc8\xcf\xab|S\xce\xda\x1cE{'\x9d\xf6\xb4\xb6yvJXH\x9d\x92dcL\xab\xf4\xd6\x92\x14\xd03\xdf\xdb\x7f\x88\xd1\x923\xb9\xa1\xe8\xee\xeaW\x97\x92z\xc9$\xf5\xb2\xa5\xbe(\x87-\nY\x8e\xb9\xd2\x90Z\x1f\xb8\x0e/\xf7\x13\x93m\xa1\x1ck+:\x7f\xdc\x8cY\xaf\x8c\x8b#\xc2\x83\xf9(\xcch\xeb!6\xbaO\x1b\x8d\xa3\xa4z\x9do2\xba\xc9Xo\xdf\xed\xb7;+\xe2\x92d57\x90R~\x1ea\x8cr\xe5\x01^\x8e\xca\xd6\x0f<&\xec\xc9\xf7.\x176\x1d\xd5h\xf6\x03Y\xe4%y\xdd\xbaAu3\xe7/}c\xb8H\x0e\x87 h2\xaf\x03FSc\x03\x9e@\xa6\xaf\xc0\xec\x9e\xcc\xf6oby&05\xac\xbd\x84\xb9\xd9V\x8f\xc55\xe4\xc1s\xc6Z#\n\xc8\xfd\xc4\x1b\xd1\x83n\x9b\xddC1JA\x194\xfe\x91\x98\xd5\x8bb\xd5\x1b\x96y)\x87N|\xfd`\xea\xf6V\xae\x95a1\x97Va\xf1\xa6b\xf0\xc6r\x95\x92g\x030\xdbf\x8c\xa8\xc7m\x01\xac\x8e\x94\xb5\xdd\xdd\xb5\x8c&[\xdf)\xc8X\xa4\xc7\x16\xa4\xf6\xf5\x90\xaa|\xa2K\xc7x!\x82\xf7\x0f\x8d\xbb\xd8\x94K\xc2\x87N\xe6r\xf0\x95\xc5\xd5\x14\xc3j\x9eF\xe7EI\xaeHV\xbf\xdb\x94\xcb$3*j[\xc9\x94\xf6\x9e\x02\x81\xef\xe1B\xd2fb\xa6\xcd\xb4\x9c\xfb\x17Sr\xe6\xaa8\x03\x9c\xf8@\xd0\xfa\xe1[\xdaf\xb7\x7f\xc9\xe2 \x85\xcaN\x17\xa9\x86\xfa^\x92\xfa9\x8f\xecW\xc7\xb3\xcbg\xf39\xc9\xe6\x9b\xb5\xebHtVO\x836L\x82~\x9c\x0c\x86\xaf.\x99\xe5$Z\n\xe9\xcf\xbe\x1av\x8f\x18\xeb@\x1a\xae\x81s\x11\xd2*\xcav\x9e\x80\xa2\xe4Z\x88\x08\x87\x06\x8aL\xc1N\x9b\xcf\xa3\xf39\xb9\xd8,_\xbd0\xae\x00\x8e\x0d\x99\x9d\x16L\x7f\xb8y\xf5B\xc4\x9c\x17EcB\xdb\xfd\xc4\xb6\x14\x12\xcd\xf9z\x00y\x1a\xb0!|B\x8e\x9f\x08\xce\xeb\x1d\xdf\xbcC\xc8\xd3\x15i{\xb8\"\x8f.7\xfc\x18\xc4T*\x124\x12\x0b\xa6\xf5\xb4t\xaf0\x8f\xae#\xe8\xf0\xb1\x83\x839q\xf3)n\x1at\x1d\x84\x03\x18\xc4\x19\xe9\xd4=g\xb9]\xbbw\x87\x01\x12\x0e\xb6\xefpT\xecO\x89\xf2n\xa3{'\x19$\xb7\xe19@G\x1e\xcfk$Gi\xff\x15Y&UMJ\xc2\xe8U\xdc\xe5@\xaa\xd5\x9b<;\xad\xe3l\x1e\x97\xf3\xbf\xc5e\x96dK$\xbe\x0e\\\xb0\xf1FB\xa4>,I(\xf2\xc2N\xaat\xd8\xecH\xa2N2\x94;\xb5/\xc6\x86\xda?\xc5\xa7\xdb\x1b\x010G\x97\xeeu\xbf\xde\x9e\x969\x1b\xba\xe9{\xa09gH\x14\xcf\xe7'T\x80\xfc\x91{+2'\xa8\xeeSn\x1e\xb6\xb3\xaf\xb5\xadn\x1a]\xe7Wc\xd2\x8a\x08\xff{C_c1\x90\xc5\x9b\x881\xa4'6\xc9'\xd3<\xf0=\x8a\x00\xbb\x0c4w<\x959\xd1w\xb3\xcd,L~\xb5\xfd\xed?\x8b\x8bzS:\x06\xee\x80\xedW~\xef\xae\xc15\xb0\xf2\x9a\x8bKQ\x06`f\x1f]\xa9\xff\xd8\x05\xcc%\xe7\xa0^\x88$\xba\xeaL\x8d\xe6\xdf\xad\x84kwA\x0d\x1e\x1f\xe8\xc2\xf8\xd1\xe7\xfaP\x11\x87\x8f\xba\x99\x00\xb8[\xddw\x07A\xbb\xfd\x8d.M/\xf3aM\xf2\xecy\\\xc4\x17I\x9a\xd4\x89=u\xc2\xd5\x97&\xa0\x80\x8e\x14\xe6\xb7SQ\xdc\xbb\xc7\xb2Ox<\x8d\x00^\x1b}\xfe\xdcKI\xc1\x9e\x95\x1b\"*\xceXL\xff\x93yR\xc7\x17]\xa7`\x93\x03o\x92g\xaf\xb2E^\xb2(\xf4\x16\x0c\x17\x1a\xb6x`Jz4\xc5\x18\xfb\x04\xdd>\x8c)\xbe+1\xa0\xf7\xccc\x1c\x03\x1cj\x97\xc8G\xb7\x91M\xa4\xce\xc2'Zy\x1el'nI\xaa:/\x89l\xc7i\xf9\xd9\x05[lJ\xda\xc3tZ\xca\x9c\x0d\x13\xc6j\xedi\xeb\x14\xed;G\x9c\xe9\xc7\xab\xb52\x84\xdc7\xe5l`\xa1\xe30!\x90\x19z%\xd6\xd8D\x95\n\xbe2\x84*\x08!\xf1\xcb\xe1\xd0E*\xcc\x9d`\xa5\xd7\x1azr\xda\x18l\x1e\x13Q\x90\x007\x96\x1e\x83*\x16\x93^\x81\x17~\xa8\x87,\xc9\xe6\xad\xaa'\xd9\xbc\x8f\x15\xfd\x81I\xebP ^\xd9B\x7f\xb3\xab\xbb\xd6\xb4\xf1m\x12a\xbf\x1f\xee'\x87\xb8`\xf2\xf5\xcc\xb8\x8eD\x08*\x01\xf7\xb4\x12\x18b>)8\x10\xefg\x11=1\x10\x80\xbe7[\xc5e<\xabI\xe9\x85p\x9f\xa7\xf9\xe2\n\xee\x01\xb1\x04A\xcc\x1b\xa2\xcc\xe3`3\xdaV4Y\xfa\xb9\xddR-\xd2]\xbd\xc5\x98\xf7\xd5\xb0*\xe1\xf3\xe7a\x941\x98\xb8\xe3\x04F\xaa\xef+\x03\xf2[n\xd0\xea\xa82\xe3*3\xbb$\x99&\xd6\x15E\xc5V\xaa\x7f\x91\xb6\x9b2w\x86\x1d\xd4\xdd \xb4v\xd8\xd9\x0bp\x04\xaf\xe3z\x15\xad\x93\xccG\xa7\xad\xd6b\xfd\xc6\xfb\x02\x1dt\xf86\xf8@>\xd5\x83[!\x89fy\x9a\xc6EE|d\xe1\x12\x13bg\xf2e\x0fYs\xb8\xcf_\xb3Y\xe9\x12\xcf\x8aH[\x95\x82\x93CQ\x94\xf4<\x12\xcb/\xb8\x15\x8f\xe4\x96\xe2\xa6\x830>\x01\xee\x8d\xd9q\\\x11\x02\xa2XO8n\xfe\x14\xdcy\xd0\x84\xe2\xeb+B\xf5\xea\xa5\x86\xf7\x9e\xd5\xc9\x15Q\xf2\x08\x91\xe8\"\x9fwRH \x81z(\xbc\x8f\xee\xbb\xdf\xb5\xff\xda\n\x9cW6\xef\xdb\xc7z\x86\xb3\x17f:\xd6\xfb\xea\xb2(\x0e\xfb\xdfv\x1b\xafZ.^}\x0f\xaf\x94\xf5\xf2\xb0+\x15\xcf\xf8\xf3n?\xcc8\xfe\xf0\xdb\xee\xf3\x82\xcf\xad\x1bub\xce\xfa\x17\xe1\xb0\x1f>\xea\x0e`\xc5:z\xdcy|\x85\x8f\x0f\x0e\xba\xe3Z\x8364\xdb\x92u\xdf\xcb\xdfu\xc3\xb9\xf6n3\x17\xaa\x03\xdb\xfe\xc3'\xddQ\x9d\xf3\xee\xbb\xd3\xb9n\x1c\xdb\x92~\x00\xe4N\xe5\x13\x8cQ\xa6\x8b\x1f\xdc\xaa\xf6 \x8e\xba\x9e\xd2\xa7p\x04O\xda\x8f\x9e\xd3Z\x9dj\x97\xc68\xde\xcf\x8c&h\xcc4L&\xcf\xa2\xbb\xf6\x14\x1fu\x93qMZ)\xc8\xba\xac\xae\xce:\xec\xad\xb9Sz\xb6\xca\xa0\x80\x8c\x84\xabO\xfck\x96\x8ew\xd8\xfa\xec\x9d\xd8n!\xf2\xa4\xdd\xbe\x90\x96\xb7\xa9\x06%O\x8b\xa8\x9f5\xdbtv\xc6\xe6\xe8=\xec.\xd1\x14\xf2\x03\x8e\xc0C/~\x16\x8ck\xc2L\x155w$1\x1cC\x0c\x13\x88\xbb\xf6x1\x9a\xe2\x05\xa1T\x95\xd5\xc9\x9a\xf4\xaet{\x13\xa6\xfb~\xd5\x89\xf3@\xc1\x94\x85<6\x01w\xa9D\x07\x98n\xf8\xa8DU\xcd\xd1\xfe\xe8Q\x95`\xc8\x81s\x16\xbdC1\xa0\x88\xcek\x0eD\x1e\x0e\x89e\x87\xffQ\x8d\x88\xf0*\xabsLa\xbd\xc1\x85\"\xb8P\xd9\xb0\xb5\xe4\x07eUuKJ\xc9\xe3:B\xe0\xbe'\xb3<\x9b%)\xf9P\xc6Y\x153\xfeuI\xeawy\x9e\x92\xb9\xbf\x83\xcc\xc1,\xdaT\xe49\x9e\xe6|\x01;\xb3\xce\xa3\x82\x94T\x02\xf5\xdf \xb1\x11\xe4|\x10\xe1`\x7f%I \xe5)\xf2\xe1i\xbd6\xe9\x8d\xf0*d/\x84U\xb4\xc94\xeb\x86\xd6D\x9d\xed)\xf8\xec\x9e\xf4\x15<\x85\xbaI\xfb\xf74\x80\x9a\xab\x81\xf0\xb7\xaf\xbc\x1b\x1e\xec+\xb3\xa5\xf0\xb3\xf1\x96\xc2U\xa4\xcbj\xae\xf3Q\x13f%t\xe9>\x7f\x86\x9d,:_\xe5\x15\xbf\xdb\x18cC\xfc\xb3\x91\xf4\xec\xf8;\xdc\xdeU\x02u\x07\xfd\xde$\x1f)\x9f\x9dj\x9e=\x1f\x06\xdc\x1b3\xe0\x1c$U\x0e^=\x9b\xce.\x88\xef\xdd\x1b\x0fN\xdc\x06mX\xf20{\xfd\x9bW\x93e-\xbb\xf6\xc2\x16\x9e\xe7Y\x1d'\x19)_e\x8b\xbcO\x05z\x07\x83\xf8\x8bN\xf1}\xffl{a\xb3\x88\xc7\x08R%^\xbe\xc2\x11\xbc\xefZ\xa95\xc3}\xa1\xf8(%U;\x88\n\x0f\xe7\xf9\xa2\x15\xd9\x06\xe3\x11\x0d\xf4.\xe6N\x07\xa0\x10\xfdfn\xb4A\xde\xd3\x87\x1e1T#\x82\xd2\xb9\xff\xd8\x93\x8c;\xdfL\xe0E\x87\xeb\x10A\x11\xaa\x1fn\x18\x01B(L\xe0\xb2\xc3\xd4a\xa2\xd4\xd7y\x96\xd4\xb9K\xc4\xc7\xae\x84\xd1\x112\xcf\xd9\xbd8\xedl\xc0\xd2U\x7f\xe8B\x03\xb6\x1f\xa3\xd6\xb8\xfc2\xb4\xab\xaf\xaf\"\x92\xfdcC6\x82T\x8b\x00\x19\x92x\x86L\x08\x95\xf5\x9e\xc7iz\x11\xcf.\xd5\x8a\xb9F~\xa2\x87\xd8\xe0\x9c\x196\xbc!\xd7\xd6ik\xe7\xfc3\xcf\x19R\xfa\xde\xe1w^\x10\xc2&\"Y\xb5)\x89\x92\x14\x97\x03\x02\x93J\xf77\xab\x10=1\xde<\xc6\x13\xee\xd6XG\x17T`!sf\x0dQ\xf9\x1f\xd0\xacY\x8cJ\xdf$\x0b\x8c+1\x89o$#\xad\xb8\x9c\xc6g\xf4\x8bp8\n\x07\x83\xd6\xe9\xe6\xa2. \x9e\xf2\x92(8C\xacc\xc6\x82\\`\x11\xadbT\xaerH>\xa6\x90\xfcQ0\x1f\xba\xee\xd4N\x1c\xd6\xf7\x8bF|\x15]\xc5i\x82&#\x1c\xeb\xfc<\xe4|\xde\x8b\xb7\xaf9A\x11\x96\xec\xad0C\x0dr<\xf1B\x93\xad\x8c\x07\x94\xaa\x93\x18\x83\xa3\x15qU%\xd9\x12b`\x95!M. \xfca\x9e\\\xfd!\xc4\x97\x80\xfdr=\x85\xe8\x07\xdf\x07\x90\x97\xf0\xfd<\xb9\x82\x07\x7f\x8a\xd0-DL\xd0\xb1\xc7YJ\xdb\xc7\x0e_\xe6\xf9@w/\xf3\x9cu\xf62\xcfEg\x99\x1a\x03Z\x89U\xc6\xf9f\xec\xf5\xc3*\xa9`\x1d\xdf\xc0\x05\x81Y\xbc\xa9\x98W\xcd&K\xf0\x02!\xc9\xb38Mo \xcd\xe39\x1dP}\x9dC\x92\xcdIA\xe1\x9b\xd50\xcb\x8b\x84Tt\xc8lL\xdc\x07\xc7\xb0\xa5\x98\x9fX\xdc\x19\xf9\x0b\xd3m\x1bR\xf8 h\xe2\x9ci:\xb0\x9a\x9fRq\xbb\xe0n\xa7\x06\x05\x122H\xe7E\x99\xcfHU!o\xc6\xc3\x99\xfaUt>c\x7f\x1a\x15B\xf4\xeb\xa5~\xe2T\x92\x7f\xe3\xeb\xf2d`\x12\x8c\xa1QSa?\x1d\x12{\x0cSY\x80\x7f\xee\xcf\xd8\x15\x80Y\x07L{X\xb0\x1e\xfaB\x05\xe5\xde7\x17i2\x93\xf1\xbb-\x96)sa,k=[\xd4\x9237\xf3\x85\xf9\"\x14@\xab\xa1\x17E\x9eq\xba\xc3\xd2O1\xac@\x82\xa4d\x1e\x84\xb0\xd0\xb6\xa3\xbfk\xfd\xb1'\x07<\xc3\xd8xvS\x0e\xe0\xc0]!\x1f\x99\x19\x00\xb7\xa6\x12\"r\x84;o}\x93\x82\xfd\x06\x8e\xe0\x95\xb1\x89\x0b*\x82a\x13)\xfe\xab C\x00\\9\"\x89w\xf7d\xa5\"a\x16\xc2E\x08I\xe0\x88\x08\xc6C\x8b\x1bK\xe3\x92^\x07!\\\xdb\x8f.\xb7\xfb\xfcf\x95\x07N Ud\x1c\xce\x08\xa2_X\xdb%\xd6\xcf\xcd\x81\xf8p\xcfD\xe6j\xdc\xed:\"\x83\x8e\x0c\xc6T\xb5\xaf\xd0n{_Q\x96\x7f\xe0\x01\x020\xd4D\xa3\x9191\xd0/!V\xed; '\xaf\xcb\xddc/\xa7u\x8f/9\x0b\xfb\\\xcek\xa1;@\xeb\x98\x9e\xb7n\xeb\xa7F\xf7\xa0;\xde\x93\x10b\x1dD(\xac\x14N\x8e\xb9\xa5\x0d\x86c\xdd\xe0^\x1b\n\xee3\x8ffq\xf6\x9el*\x9e\x19\x8a\x8eb\xd3\xc92C\xc5\x0b2\x8bg+\xc2v:\xad\xa1oQP\xf6M[_6\x8f\x9e\xff\xf9\xe4\xf9\xff:\xfd\xe95\xaa\x16\x99\xf6Q\xdf\xc2\xa6\x97\x93c\xc4\xc7\xe2t\xd8D\xf9\xa6&\xe5\x9f?\xbc\xfe\xd1\xd4Ke\x1b_\x08\xdd\xa8\xbc\xa2\x88\x13b \xb5Q\xe1\xe2Y\xaf\x16\xe9\xba\x90\xa9\x97O\xe2\xce)\x94\x9e\x94A\xa8\xfaWf\xcc\xb1r\xb0e\x10\x8c\x80H\xf5\\\x06\x9c\xe1\x91\xbf\xe5j\x1b\x1c\xec\x85P\xc0.\x1c\xec\xa1S\xf4\xc7\x0c\xfc\x8a\x94W\xa4d\xd5g\xe6\xea\xfa\x99\xe9tWtg\x1dx!h\xaee\xfb4\x03\xb5K\x86F\x0e\x19\xaf\xdd\xd3\xef\x19P\x81\x07\x98r\xd5\x90\xe9'\x94GIV\x91\xb2\xfeP\x12\xc2\x1c\x1b}F\x9d\xe81`\xe4\xd3.X\n\x80P\xb3\xd3kE\xab>\xf2:\xefG|\xfa\x85\xf7O\x87\x8f\xbe\x0d\xf4\xcd\x9b\x8f\xa5\xc6\x0fH\x03$TM*\x1a\xe37|\xed\x98\x95@\xd9DS}\x1a\xa01\x8fN\xb9l\xd0A\xb1\x060\x00\xeb\xb1\xf6;\x98\xc8Z,\xe4+\xcf\xeb\xd7\xb3\xf8\xfb\x82\xab\xbb::?'\xd5\xeb|\xbeI\x89F\xcd\xc3C\xb2f~\xf7\xea\x0d\xc3\xe7b\xbc|4\x7f)\xd5f\x8e\xa1\xd4Z\xd8\xcd\x859\\\xdb\xb4\xeeV\x1d\x0d\xaf\x83r>\xff;\xaaVqA:f\xd3t\xe7\xce\xca\xe4\x82L\x94\x8at\xfa\xa8\xc2\xfa\xc7&)\xc9\xbc=\xe2yR\x15\xf4,v\xfe\x80\xf9\x94\xd5C=4+\x10\xdc\xe1\x12\x84-8\x98\x11W\x7f\x0b\xcd\xaf<\xc0\x14\x16I\\\x89\x90\xb2\xccK\xf5\x8e\x04\x1f\xf4\xb8.\xfd\xddt\xbd*\xf3k\x8c\x80t\xc2\xbfj/\xa9\xde\xbc\xdb O\x95\xcb\xe4\xc7\xdd\x1bJ~\x9b\xdc\xb3S\x14\xa9\xae\xba7\xa41\xaf\xdf\xc5\xde\x0d\x7f\xdem\xbf\xe2\xcf\xbb\x17\xc0\xfc\"\xb9\x97^\x80_$\xf7\xd2\x0b,\xf8\xf3\xee\xc5/\xbbH>x\xa2\xbbH\xce\xfc\xc3\xc7\xddy\xb1\xfb\xe3\xfd\xc3n\xfbW\xbc\xfd\xee\xb5\xfa\x9a_\xabw\xdbY\xf2\xe7\xddy\xb1\x1b\xe4\xde=\xf4\x05\x07\x7fw\xba\xe7\xbc\x99\xeep\xae\xf9\xf05W\xc4\xb4zw\x94\x9f\xf0y\xef\xda\xfa\xb4\xafN\x7f\x0eG\xddh\xda\x97p\x04\x0f\xdb\x8f\x9eQN@\x04\x00|V.\xf1\x12\xa9:\xebD\x18|\xab\xd6\x12\xa1\xeb\xba\x95\xde\xa9\x950\xf4n\\\xe7\xa5\xa9\xf6\x07\xb5\xb6\x88<\xd8\xae\xf2\x9a\xdfb\xcb\xdf\xd3gg\x94g\x9b*\x03.\xe3\x9b3O\xf7\xf4\x87\xcdbA\xca\xde\xbb\x17q\x1d\xff5!\xd7\xbd\x17<\xc7\x87\xee\x03\xd2{\xf82\xcd\xe3\xfa\xf0@\xdf=\xbe|\xf4P\xff\xf2UV?6\xbe\xd9\x7fd|e\xea\xecu\\\xf4\x9e1\x17\x14\xf1\xf8C\xe7-\x8b \xd8\xfb\xe8\x94\xd4\xfdg\xc8\xdf\xf5\x1f\xdf\xac/\xf2\xb4\xf7\xf8\xa7\xc487|\xf5<\x8d\xd7\x05\x99\x9bk\x98\xa6O\xdf\xb5\xe6O\xc9\xbc\xf2\x1e\xc9\xa8\xf8\xeam\xe7\xe3\xbf\x91\xf8R\x02ig?\xd4262,\xef\xab\x10~\x0e\xe1M\x08\xefu\xb7w/B\xbc\xbb\xc9\xe0\x1e\x9c\xf6\x99\xeb\x9f\xf8\xab\xe7\xfdW\xff\xe0\xaf.\xdb\xe7\x03ei_\xe1%\xee\x0b*\xb5\xc31\xbc\xa2\xe3\x90#\x98\xd0\xdfA\x10\xaa\xda\xd3\x17R\x84x\xd1ol\xe7Z\xcd[\xdaa\x9e\xe8\x0c^\xe2\xbdBWJ\xa5\x9f\xbe4\x89\xc1thW~M%\xee\x1fe\xd3\x18\xd5\xf7E\xf7\xe02\xc4\xbf\xa5\x1d\xff\x13\x8e`E[\xe9\xbd\xa5\xe5\x078\xa25\x8e\xe0-\x15\xb8\xf1\xafwz\x05\xc6\x85:\xc1\x8a\x8e\xe2G\x83\xaa\x03[\xf9 \xdb{F\xff\xfa\x01\xb5ToLr\x81\x98\xeeO\xac\xee1\xfcr\x0b\x13Xv'\xff\x13\x1c\xc3\x82v\xbd\xf1_0\x1d\xe7\x04f\xf4w\xcc\x7f\xf7\x1a7\x82F\xf4\xba\xf3z\xfa\xcf3\xd9\xc1\x1b\xee/\xfb\x8bA\xefH\xc7\xb8\xa6\x1d\xfe\x93N\xbf\xdf\xdb\xef\xcc\xbf\xde\xa3\x0d\xde{`!\x18\xcb\xa0\x8f\"\x7f\x85#x\x8f\x9aj\x1d\x9a\xfcU\x0e\xf2\xaf\xfd\x97\xef16#bF\x88~\xed\x0d*\xca\x08`\x92}\xe9\xd9t\x00\xde\xdcbXC\xbf\x14\xbb\xb1D&\xe7}\xd7\x12<\x08u\xe8\x7fn\xeb\xd2p\x9f\xf3\x02\xc7\x9d\x87\xa0t\x9c\xbbvLa\xf6g8\x82\x7f\xc01b\xc6\x1c&P\xc0\x04\xff\xbe$7\xd5\xab\x0c\x03\xe2\xf6:\xfd\x1b\x1c\xc1K8\x16{{\x02\x7f\xee\x01\\h5\xfd\xbf\xd1U\xab\x15\xde\xcf4\x93\xbf!5)1\xc6\x13z\xe8\x9e\xa1%\xfd\x0b\x9c\x8f\xdb\xec\xe4\x93\x91\x1c\xe7\xc1\x93.\x87$8N}\"\xaa\xef\x1e\x8f\x9669<\x12\xe6u\x81W~;\x18Z\xbc\x95\xeb`\xe4\xb8\xf7\x1f\x1b\x92\xc2\x1ety2\xce)?\xd6g\x85=x\xd2}\xbei\xc2\xf62\x0f[\x11A\x97\x1d\xa0\x15%#\x83\n\xdfV\x94\x8d\xe9\x19\x8b\xb2\x81\xce[\x14\x04<\xcc\xc6\xb0{{{}a\x02\xb1\x1e\xe8N\x06\xc1\xeab\xeb\x81v\xd8cX\xb9{\xd4\xf6\xab\x8d\xcb\x9c\xb4\xaeuG\xae\xf0\xe3\xc7z\xcc<\xec\xc9H|\xb0\x8f\x0f\xb7\x1dl\xe2+\xa9\xa0\x99\xc9\x18&\xec\xf7\xbe`\xf0]4\xcc\xa5\xde2\xfed\x1b\xa6\xfeF\xa3Q\xa3@\xaeZi\xd7\xa8L\xe1Z\xc6\xfb\xb0\x0f\x13\xc0\xe0\xfd}\xe2e\xbdc\x93\xa8KA\x1a\x0b\xb9\x82\xc5\xfd\xbc\xbf\xcf\xaebs?i:c\x1d\xa1\x14\xc9\x82\xf7o\x82\xa7\xb0\xbb\x1b\xc3\xf7\xb0y\x1a@\xc5\xcd\x11\xa65\xecB|\xa6?\x17Y\xe3\xfawr@\xa9\xec\x816\xb5/{\xa9\x9f\x06\x90\x8a^L=\x08\xf6\x87\x05\x0c\xcd\xfc\nS\x8a\x11\x96S3\x04\x9d\xdeo\xfb\x85\xefn%a\x0f\xbe\x1f\xf8\xa5\x01A\xbf\xc0\xf7\x91S*\xa6\x15i\x12\xab\x87\xe05*\x16\xaf{Y\xce\xb3\xd3*w1\xb7\x81A\x05c@B\x0d\xd5\xcbzZ\xae\xa6\xf5\xa7=H\x99\xf7$\xea\xe2\xd9\x0dV3\x05\xc9\x1f\x90\xfe1^w\x04N\xd1\x884M\xe9/\xafr\x9b\xc0\xbc^,q\xdayTs\\\x11\xb4\xdedQ}\xc94;3\xd8\xdb)\xb0\xa4k\xd9\x80\xc2\xcf\xfc\xfd'\x07\xc1\x17h\xcf\xbe\xf6\x92\x1bM \xf54\x03\xc3\x88\x18\xbd\xa4\x92l\x91k3\x87\xd1\x92\xe6Km\xee0\xc0\x94\xb5e6\x81C\xfdKT\xdcM\xe0a\xef\xa5\xc659\xb3\x1ao\x82\xb2nSrF\xb9\xb6\xfb\x9a\xfb\xd0~\xd3\xccOs\x96g\x8bdYEi\xbeDs\xc0~=F\x02J5\xdb\x00\xa8f\xa7\x89\x8d\x91`\x97Z\x92 \xcb[\xafDR\xc5\x12\xfe\x04\xfb\xa8\x87f'\x00\xa5\xca\x94\xb0\xee?\x05J&\xcb\xa7\x10\xef\xee\x06\x94F\xd2\ngjkZ\xb2\x89\xa0\xfa\xd3\x91\x12\x92\x95+M\x83)9\x8b\xe2\xa2H\x11\xe5\x06\x0d\xda\xc5\xe9\x1a\xd1\xb5D\xfd6&)f\x17\xee\x1e}\x88\xf7\xb3\\/\xdb}\x8fOY\x05\x8aD\xbd\xf7\xf4!{\x8d\x18\xd8{\x8fO=\xad[>^Vc\x0e\xa8\xca\xe4\x17\x8f\xa8\x99\xf4\x91\xc00]\xa7S\xc2\x9a\x07\x8e21]M\xe3\xd7\xb9vpc\x8f\xc4\xc6\x978\xae\xa5u\xfa\xb3\xc0\xc0`\x90\xce}\xc4:\xbe$\x7f\xae\xeb\xc2\xa7\xc4\x97\xbc\xa4\xaf)Y*\xf2\xaa\xc6\x1f\x06\xd5\xc3\xc5&I\xe7\xef\xc9?6\xa4\xaa\xd5\xe6\xd4\xe7\x06\xd2\xc1r{\xab\x1f\xf1G\xfa\xfa%\xa9\xf2\xf4\xaaU\x9f?\x1a\xac\xcfMM4\x9f\xf17\xfa\xaf+R&q\x9a\xfc\x93\xbc'\x95\xfa\xad\xfa\\\xffe^\xbc\x9a\xab_\xacHZ\x90\xb2\x8a\xe8\xf3\xbbEc7\xdc\x91\xc4\xad\xd6\xeb\x0c\xf0\x84\x9e\x96\x8d\xfa\x84\xfe\x10-\xf7\xe9\xd1\x15w\x1d\xa1\xb5\x8cGQ2\x81\xd2p\xd2\x98\xa3\xe3\xf2.'\xba\xa8<\x1aM\x8e\xe0C\xe8h\x91+\xc8\xc5\xa0Q>W~\xa1\x97N\x94r\xcd\xa7|a\x00=\xf0If\x1anF2\x15k\xceNDx\x0d\x83\xe7wGp\xd0\xb9\xdd\x00^\xb9\xe5\x9c\x7f\xf9\xfc\xd9\xc0A\xb0\xaf\xf5\x90e\xfb\x7fS\xc6\x17)\x19\x00e\xb6Y\x13Q\xc7\xc0\x10,I\x8f.\x01h\x82\x10C\x1d\xd9On\x01\xb0\x1e\xbf\xa8\n\xe9\x96#\x9f\x88-\xd3\x1f\x138Dl\x11\xad\x8c\xc0\x9d:\x9a\xfbY\x08^\xcc\xfd\x8a\xb3\xfe\xd4s\x17\xfb\x18\xde\x9c+\xef\xdaO\xbdRG\x05KL\x05\xb5_Gt?\x1f\x1c*\"\xaf?\x1d\x1c\x82J\x072\xff\xe1\x81\xf2e8<\xf8\xce\x97\xdfn\xfbek\xb4\xe3\xbe\xdc\xba\xcf\xc3\xc3\xc7\xe6O5R{\xfb\xd0o\xbd\x92$\xb2\xd4c\xb7@-\x0dr\x13c@\x1fy\xf6\xdb\x93T\xea\x07\x93\x1b\xf1M\xec\xb6.\x1f\n\x7f\x82\x83\x8e\xb5x\xc3\\\x1e\x9c\xc1q\xfb\xe7\xc4\x98\n\x8d\xb29\xbe\xa6\xf5Cc\xeb\x87\xed\xd6\x0f\xcfP\xff\x1eDW\x07o\x0bRbL\x9aWh^\x12\xd7 \xc6/\xb9y\x9d\xcf5\x1e\x9f*\xa8[\xa9\xddTE\x0b&kP,\x10&\xe8\xf87\x13\xf4#\xf0I\x10\xb0(Qy\xd39s\x84U\xd2r}\xac0\xc7\x96\x174\x86a\xab\xf6'\x01L \xe1W[\xfaE\x1e\x9e\x9e\x9e\xbej\xfd\xc5\xcc\x02\xc9@8K\xdd\x12\x8dC\x00\xfb\x12\x99\xc8\xad\xc0A\xbfnG\x84\x80]\xf0\xce1}P+QZ\xb5\xf3\xff\xfd\xfe\x9b\xff\xf1\xf7{\x7f\xf4\x83\xf3\xdd\xa3\xe9/\x1f\xcfn\x9fN\xbe\xff\xd3\xe7\xe8\xe3\x83\xe3\xf0\xe3\xc7?x\xde}\x96<\xed\\g\x99\x0b\x0df\xb0\\\xe8\xcc\xf3\xb0\xb1\xa1\xdbo\xfa\xad\x95~}\xff<\xf8\xe5 \xbc\x0dD\xd3J\xe6\x12\xff<\xf8\xa3@\x80\xe6\x83\xe9\xf9Y\xf0\xc7o\xf8s\xcb\xc6UF\x851X\xe7~M\x87\xd1\x0f\xa4nX\xdc\xd8v\xa0\xf0\x06\xbd\xfb\xfdtL\xa667\xb66+N\x1fw\xf6\x90\x03q\xc6\xc4\xcaDWA\xdc\xc1\xb1\xe0Vb\xcf\xeel\xb3g?\x7f\x86\x1d\x12\x15q\xbd\xaa\xfa\x8du\xaa\xb3jC\xb1-@Qs\xf1\xea\xfd\nR\xb6\xcf!\xc9\xa0\xd4\x9b\xa8*\xeaXZi\x9a\x1b\xa2\xcc\x03\x87\x85\xf7\xee\xd9\xfbg\xafO>\x9c\xbc?e\x83O\xa2:\xff\xa9(laSD\xb9\xe2\x0eg\xb4\xa7ibP\xa6\x8aB;\x8c\x07\xe9el\x83}\x1cX\x87\x04\xd0\x18j\xdbk\x8aR\x15df\x8c\x13\xa6+t\x95XX\xd1\xdc\xfd\xa35\xa9W9\n]-(\xbb7 i\xfed \x9c\xa8Z4:(]\xc1\x0c4\xbe\xc9\x06]-(\x85\xa1W\xb2D\xe8\xcd\xe0Gz\xa7\x97\xfe\x9b\xf6\xaf\xadT\x96\xa0U[b\xe3\x9a\x0bp*g\x95~\xe6\xef?\xee\x06\xff\x00n\xb6\x86o\xbby(\xea(\xa9\xde>;=t\x125\x98.$/H\x16\x17\x89\x91\x89\xe0Y\x15(\xae\x17\x0d\xae\xd3\xc9\x1ez\x1a\x16<\xa9N\xaf\xe3\xe5\x92\x94\x07#\xc6P\xb1O\xb6\x18\xc3\x81n\x0cy\xf1j\xce\x12\xf0\xd7Q2\x7fY\xe6\xebwq\xbdz\x8d\xf8\xcd\xdcI\xeb(%\xcbxv\xf3\xaa\xff6\xa6o\x97\xa4\x96\xc7\xf9\xfb\xf8z\x84\xf8\xc2\xd9[F}\x8f\xd9Ib\xd7\xd7J\xc9/\x12[\xd7\xbc5\x18!f\xbb\xd5\\+\x11\x8b\xcb&\xa1\xdf;x\xe2$\x83'Nb\xa3z\x89\x12\x19i\xc7p\xef%H^\xa2\xf2\x85\x83\x0c\xca4\xf7\x13\x19\xf0\"\xf6\xf9\x1f\x9b\xb3\xa8\xca\xd7\xc4\xb7\x03\x14\xba+\xc2\xee\x16\xb5uu\x91\xd7\x0c\xd9\x10\xd0>>\x9bK\xdc\x80#\xd8\xd0\x87$\x9e\xad\xd4\x87\x15\x8b\x93Q\xaeQ\xcb\xc5w\xc4\x98\x0dQ\x90\x99~mY\x005D/\xb3\xd4\xa1\xb3\xd9\xc1\xb5F\x96\xaf\x8e\xbe\xf9F\x8emn\xba\x8b\x82\xde\x89m\x0c2+\x0e\xda\xccx\xca\"\x9f\xbd\x17\xc2\xa2uZ\x0e\xac\x9d\xc0\x18\xcc\x92\x15\xafIMJ\x0d\xdb!\x8a\x1cgE\xc7\x19\x07\xb0\xe3\xb0\xe7D\x91r\xe0\x948\xf0\x08;\x9did\x0d\xf6{\xb3<\xab\x93lC4\xa9a\xd4r\xc5]qs\x9f9\x7f\x99\x9cqE\xa1\xddj\x83\x02uK9\xad\xa8tB\xffc\x91\xca3\x8a\xc6\xf8\xf4\x08\xa6\x99ev\xc0\x87\x86\x87\xcb\xb4r\xa8M\x076k\x84\xa6\xfd\x00f}{'\x13\xbd\xd4\x15\x12\x9d\x9f\xe7e\xb2L\xb28U\xc4)\xe6\x96\xa1}\x83\x12\x8cBT\xc2\xf6O\x96\xb7\x9f%L\xe7W\xed\xd6\x81\xe8\\\xab\xbbE\x86\x00Td\xc4\xac-\xf4\xba\xcd\x98\x02\xbc\x80#\x98M\xf7\x1c\x00NKa\x84\x91\xe9\x0d\x15P\xda0*:0\xaa\xac=\x9b\x19%\xfb[\xe4\xe5\x9bm\xcc\xce\x18\xeb\xb6\x04\x0e\x9d\xb9%U\x84ZV\x06\xda\xd7-\x92^\\QzQ\x07\xe0\x15e>\xdf\xcc\x08\x1f\xdc\x15\n\x02\xb3<\xab6\xeb\xf6\xb3\x8a\xcc6eR\xdf\x88g\x9f?\x83\xbf\x9a^\x9d\xa1\xb1\xdb\xd5Y\x08s\xb6\xf3V\xba\x0ca\xddB\x01\xb3A\xc6f\xa5\x909v\xa64\xed\xd0\xbf\xb97\xa0\x03\xc8\x80\x83m\xcd\x14\xf5N\xf5\x81{\x18\x98\x14\xe1\xbar\x03G\\Ab\x9f'X3pt\x8b\\\xa0\x8b\x10\x9d\x16(\xd1M\x1b\xa2;\x0f\x9e\xc2\x8eO\xa7\xe8_\xc0\x11\x9cG\x19\xf9T\xfbA\x10\xcd\xf3\x8c\x04O\xf9\xe4]\xc1%\n\xed\x8f\xb2z\x17,\x00\xa8\xdb\xbcD\x91#>\xa1(um'3\xdd\xc2n\x90N\xce\xc6\x8eZ\x94\xde.\xa3\x0c\xcf\xc9\xb6\xad\x01\x87\xc7\xa7\x91h\xa4+\xa7#QKW\x9e\x8fD7]\x19\x87\x82\xba\"\x17\xf92D\xa7\x95\x0eZ^\xd3\xe5\xa3\x98I\xa1\xe6_\xc2\x11<\xebb\xe6'\x8e\x99;\xf6\xab\x981\xe5\x8a\x87\"\xbf\xdc\x06uu\x85bb\x87\xd7v>\xc5mE\xde\x1be\x1e\x81\xb7\x19*p\xc4\\\n\xc4\xbcq\xfe\xd4q\x9d\xac\xb5\xb6\x150n\xfdJ\x0f\x1b\x8d\xf9K\xef\x89<\x89T\x85\x08G\x8e\xceMQ_E\xbb\xe0J\xd8\x87\xdf\xe9T\xb4\x85P\xd1\xf6\x82Z\x03\xf7\x17\xb6k(\xf8\xf0\x98\x07\xa4b\x11\xa1\\\x15rs\x08\x8d\x06\xab\xdf\xe9jL\xa7D\xb9w\xfc\xfb\xc7\xeb\xb3\x07\xcb\x84]\xfe\x0d\x80u\x9c\xe9\xc1\xe3'\x036\x16\xffo\x98\x1e\xdc\xcd\xd5s\x9a\xc7\xf3S\xa3\xc2\xb0\x94\x9c3\xd3R\xd0\xe6\x0d\xe9\xdb\xf5\xc9\xc6\xe4\xdb\xcb \x90(\xbf43\xf2\x9b2\xa5U6e\xca\\\xc5\x8c\x15\xab:\xae7\x15\xe6$\xc1\xbfl5Y\x8aPQ\x9b\xfe2\x7f\xb1\"\xf1\x9c\x94\xd5\x04\x12\x9fD\xfc\x87\x81B\xe8\x1b\x89\xe1\x08r\xf1\xe5\xd4\xe3y\x84\xee\xd3\x9d\xe7\x19\xf4\x10\x1b\xccC\xf9\xf93\x9c\xfb\xb1\xd9\x0f\xca\xdf\xa0kKM>\xb1\xf8\xe5\x17i~\xc1\x14X\x17\xe8'\x1e\x88\xcd\x1c\xd5+\x929(\xb9)\xc9\xceY{hH\x97G\xf3\xb8\x8e\xd9\xdf\x9b\xc0r\x00]\xf5\"\x01;(\xea\x84\xa63.\x8a4\x99\xa1\x02\xe9\xc1\xcf\x15\x8bO\xc1\\w\xfer\xfa\xf6MT\xc4eE|LA\xb4l\x8c>\xe3\x05\xf91\x8f\xe7C\x0c\xf4-\x1d\x85\x0e\x84\xa2\xe4\x98\x01\x01\x8e(\x85\xc8\xa3\xfc\xe2g0j\xf5\x9dX\x83\x9c\x8d\xf5\x84\xdbl\xeb\xb9\x01\xfd\xe9\xc3a\x91\xf7\xa9\x83\x9b\xe1B2\x9cT\xaaO\x19\xf6\x8c\x94a\xafM\x19\xf6\x18e\xd0\xe3\xaa\xce\xbf\x04\x94\xa5\x15\xe3SC\x8e\x10\xa1\xd6e\xf6@:\x1d\xaf\xf9r@ \xba9\xcd\xe8@\x85\xbf \x9a\xfaGI\xc5\x1d\xa1\xa6\xd9Y\x00\xc7\xac\xd2\x04\xa6\xf4\xff\xb3\x10\x7f\n\xb9\x8b\xe2\x93\xf0U\xd1@\x1d\xf1\xb7\x1b,s\xc0ld\xe0\xa4\xd0Gfy\x99\xf0#C\xc4\x89\x13\xcfd\x9c\xd1\xa3\xadl\xaeVm\xfb\x0dS\xe0\x17\x12\x15I\xf1\xa5\x06,\xcdM\xe3,Oy\xd6\x9a\x97\x98\xf0\xcc||\x90(N\xd3\xfc\xfad]\xd47\x18;\xd8|||\xd9\xcc\x8fE\xf2\x1dJ\x1f\xf5WX\xdd\x04@es\xfdb\xc8\xc8\x1f\xfb9\xcb\xdfp\xc1\xa2k\xa8 \xcd\xe5\xd7y\xff\xe3+\x91~'\x9b\xe5s\xf2\xd3\xfbW\x86\x80P\xa0p\x92\xa8\xcdM\xb8j\xe8\xa6\x99]\x1eX\x1dma\xd0\xfc\x16l\x81\x19\x95\xcf;\xf7\xe4:\xee0\x08\xcdW\xbe\xb9m\xa9rfd\xd4\xde\xbf8C\x97G\x18\xfe\x1d\x8e!\x8f\xd6q\xe1'A\xf4s\x9ed\xbe\x17zt\xf3z\xebMZ'\x0c}\xd4J0\xe9\xd4\xd7\x03`V]M\xc0\x0b\x0d\x06\x99\x15\xbe\xfd\x1f\x07{\x86\xf75{\xbf\xf7\xc4\xf0\x9en\xbfj\x02\xdeg\xaf\x0fP\xa4^\x94\xe9\xc0\x14\xd0\x9e\xe7\xb4M\xab\xe1{\xe0\xceU#\xda\x02\xce73U'7Dx\x85\xd1\xd64\x1b\xb8>\xa1\x9bvg\xa7\x8c\xaa\xcb\xa48\xa1\x88\x9ed\xcba\xab\x82\x9c\x87\xeb\xefo\x0bc\x88V\xe0l\x95\x1d\x83EQ9\xf6/\xa2)\xc6^ny\xe2\xbf\x9d6\x82v\xa3Q\x88\"6\xf84\xa1\xc7\xcf\xc6\x8f\x8d\xeeJ\xa2pc\x1fC\x1a\xd2\x10\xf2 \xd4\x05v\x0e)Oo$0\xeb\x86\x9dB\xa90Y\xa0\xe1\x91~\x14l\x85\xcc\x0e\x0eI6Of\x14\xa3u\xf1R\xbb9o`\x00\x8f\xd3\xdf\x8e\x95Aq\xc3*\xf9\x08\xee\xd4\xf3\xd0\x9d\\[=\xc7\xd6\xfe\xb1!\xa5!\x8203\xa9Y\xe4\xe5Z\x7f\xd0\x0c\x86fM\xfb\xfb9 \xc6X\xb3@\x83\x04\xb1\x9fL\xc9\x19;)\x07\x10|`3\x168\x15\x83\x8c\xc3d\x12\xf9\xf29\x7f\xf9\x01_\x9a\xed;P\xe8{\x80\xf4\xbb\x88\xcb\xfa\xe3\x03\n\xa9\xfbT\"y\x90D5\xa9j\xbf\xb0\x9a|\xf08j\xa6\xf8\x9d\x80J\x04.\x01d\xe4\x1a\xe6\xa1\x06\xa8=\xf6\xd4*\xd6\xb06\xa3\xb8(H6gAu\x92i}\x86\xf6\xbdC\x00\xd6om\xa6\xf4\x94\xe3\xac\xfc\xc40\x1d\x1ez\x98\xe1T\x7f\x07j\x91L\x1bq\x058\xf8V\x98)\xb2*\xd2\xa4\xf6\xbdco\x00\x01\xae\xa0g\x0b\xbc\n\xa1\x1b\x8aB-K\xba\x9b\xa6{\x03G ^ O\xf7\x07j\\\xa0=\x86\x19\x85nl\xf8q\x8e\xe9\x96\x04 db\xe6\xcd\x00\xb2t\x90#\xd7 \x87\xeb\xa6\xe3\x8bu>%f%6e\xab.ZCl\xa8\xf4\xf9PFmP\xa9u?\x0b\xa7(&\x8c3\"\xc4\xb5-\x9d\x8d(\xf2fSG\xb0C\x96\x0c\x08\xcfG\x12\xb0l\xbf{O!\x83\xef\x81<\x85lw7\x10bYC\xb8\x87\xac\x8d\x04gRG\x8b$\xadI9~1\xccZ\xfb[\xc1O\xde3\xb9@@\xd3LI\x8f\x84c\x0fv\xf1(\xf7\xfal\x1d \xa3p\x11BE\x99^}{L\xe1u\x04K\xd8\x85\xeb\xb0\xd9\xd4x\x928\xecj\xed\x94\xbe\xb2\xc1q\x08uT\xad\xf2M:\x7f\x91_gi\x1e\xcf\x9f\xa1Z\x8deg%\xe9\xc2p\xdd.\xed\xc3\xfc\xcc?\xe8eK\xa4Eh\xc5\xf7\x86\x94\xe2Z\xa3\xe6\xb9\xd0\xa7\xeb^\xae\x1a\x8b\xe7\xfe\xcb+\xf1Rc\x0f\xad\xba\x1a\x0b\x9b`\xf9\xec\xcf\xec\x8c\x136\xc1l\x07Ri\xf8m\xf9\xbf\xe9\xea K\xce5)\x97\xe4U\x86\xcf\xde\x96\xb4\x02\x1cA\x8ao\xb8\xc3\xb7C\xc0\x1bh\xd6Zz\xdf\xd8\x11\xdf,\x11\xb2]Y\x7fq3\xda\xfa\xb2E\xad\xfb\xad(B\xf2\xeeg\x90a \xbaK\xab\x9b\x03\xaa\x8c\xf5,2\x08\x82\xaa\x01\xbf_\xf2\xc8\xe85\xfe\x95\xf9\xa4\x97\xa8[6\xd1F}Z\xf9\xe0;\x8d\xc5\xfdZ\xa0\xb5\x169\x97\x02\xc5\xbe\xd5\xbd\xbd\x11\xdf\xf6Ru\x02?\xf5\xe4\xae\xd2\x83\xa3\xed(op\xda\xe8\x83a\x02\x9a\xf4\xee\xdd\x1d\xc0\x8f\"\xdbI \x88?=2\xaf\x14S+y\x94\xad\xe3\xf2RRj f\xae\nUL,!\x17Kn\xa0\x97\x01\xf6\x8d2\xc0~[\x06\xd8?\x1b\x08C(Ng9\xcc\xeb2.\x1c\x0f\x14\x16\x82\xfdi\x00\xd5u\xc2T\xc5QQ\x92+\xe4\x8d3\xf2\xc9\xca6\xce\xe2\x8a\xc0\xded\xb0\x0e\x08\xd3,\x93\x10[\xdb\x84X\x91\xc2\x1e5\x02\x14\x96u@O\x1c\x0c6\xbf\x92\x04\xac\xf9\xfb\xf3gL.\xa7\xdd6q\x10\xc2N\x1c\x95,\xa4\x04\xa6)\x9b\x91\xa2\xce\x07w\xb9Z\x18`\xe0\x08\xf6\x1d\x0d\xb1.J\x12_Zk\xda\xef\x87\xe5\xb5$\xef\xff\x11\x9d~\x7f\x1e\xda\xfb\x17\xb5\xe0\x9a=r[3\x12\xd5{\xcc\x1c\x9fdu\x08\xf4\xe7h8=\xf9u\xc1\xc4\x87\x1c;\x00\xe1\x89\x1d\x08,\xe3lmYjlm\xdfa\x1f(\xa7_<$|\xc6&\xe13\x1c\x96/y8+\xce\x81\x19\xbb\x90<\x9a\xb1\x1f~\xb8\x88\x08z\x92,\xec\x1f\x86\xca\x0ex\x14\x82\x8f\xf9\x1eJ\x8c\xed\x82\x071\x06y\xa1O\xcbt\xf8\"\x0b$\xe0\x1c\x90Q\xb2\xab*2\x8aa<\xa1{]=@|\x16\xaf\xd4\xadw\x07,\xa0[A\xed\x1a HU\xe4YE\xbe\x84\x82\x1c|\xf7\xebn\x8d.\x0598d$\xa47\x13\xa3\x0eP\x14\x84\xdc\xc1\xa1\x1b\xe4HT\xef\xb7\x89\xc8\xfexP=\xfauA\xc5\xc7l\xc9\x0f\xc3\xc0\xe0\x82\xbe\x8c\x8c\x18\x9c\xc3Da\xcd}goN\x82\xe5\xd0\x01\x83\x10$.\x1d;n\x04I\x0b\x0e\x9e\xe0b\x1e\xb0\xbb\xb4\xb8\x9e\xad\xfc\xfd\xc3\xc0\x10\xafFW\x9ai\x1c\xda\xa7\x01w\xb8\xba\xcc\xc4\x8b\x8e\xdd\x01.\x87\x0eh\xce\x1a\xf4s\xae\x94c\x19%J\xc5Z#\x08\xf8\x8f\xe7\xf9\x1c\xc3\xc5\xf2\x9fL]\xc5L@ \x97{Q\xde\xc6G\xf5A\xa8\xbb\x99S\x0b\x1b\xa5\x03\xda \x19\x8b\xf2\xcb\xd1\xeb\xf3\xd0\x02'Q\xeev}\xf0\x16\xd1\x0d\x9c\x89\x0e\x9c\x89\x04'}\x1cv\x93\xcfw\x0b\x82\xf1\xe1\x81\x1d\x8c\x92\x8c\xc6\x17\xe5\xa6\xa8}\x8f=\xf0\xc2^ \xefna]X\xf0 +y$\x9b{#\x86R\xd5y1`\"\xa9\x07\xf9-K\x93\x871S\xa7\xc6o\xa7\xf4\xcc?x\xa2\xd7\xf9i\x02\x18\xdc\xea\xd4D|\xa0v\x85t\x03\\\x16\x92\x10\x07'%![(\x8d\xdbnVB\xa125*{\x06%B>\x98\x07\xfe\xcfU\x9e}\xfe\xb4N?\xdf\xc4\xeb\xf43\xa6\x00\xfdx\xf1\x80\xf1\\_|\xb9\xd3\x8d\x10\xb2\xad9\xe1\xc3\xfd\xffxk\xc2\x81\xc1\xb4/1I\xa0\x06Q\xfe\x1eCi\xe2\xd5\x97\xf7\x00\x83\xa0\xe0M\xba]F\x16\xe6\x04\x99`\x02\xddkTS\xe3\xb3\x01\x13)#\xa3\x85\xbaR\xba9\xd8\xbc\x9b\x00\xcfti\xce\x95\xa5\x19GZ5S\x991+g\x9d9\xaa#i]\x0c3\x19\xeeW\xa4\xfc\x0b\x85\xf1\xd2\x8d\xcaiL\x85\x9d\xf1\x19i\x94ua6\xca2\x0db\xee0\x08Q\xb9e&\xeb\xd4\xfaJ\xdf:zAY\xf6\xb8\x88\x9b4x!\xe1\xc5\xf3\xb9\xb0\x8a\xff\xfc\x99\xb2#\xeb\xfc\x8a\xb4\x9f0\x06\xc5\x10\x99\xc6\xb8/;\xc6Z\xa6 ^\x0d\x82\x0f\xa7\xff\xf93\xd0\xb9\"$\xd7\x9b:\x16\x90D\xc9\xfb\xc6\xd1\xd4x=\xd8\xcf\x15o\xdfo\xe0AA\xd7\x07\x80|\x8a\xb7\x16\xbag/\x08)\x9a\xe7n8\xb4t\xc0\xa1\xaf\x8e\xc87Fcl\xb3\x87\x06\x1f\xe1\xa9\xbc\xd6Z\x92\x1aM\xaf\x7f\xb8y\x97'\x19\xa5\x08\xfd\x18\xb8\x00.n\x0f\x82\xbcw\xb2\x86\x86\xda\x88\xd1\xbf3\xff\xbas\xa3\x84\xbe\xecz1t\xeb\x7f\xce_\x1ej\x0d\x06\xae\x87\xec\x10N\xc4\xa7\xda\xdb\xdcO\xe26W\xf7\xf2T|\xaa\xb5~x>d\xc3p)>\xd5:\x0c>\x13o\x1f\xf7\x8d\x18\x9a+\xdc>4\xe3\xf9|2,'\x8b2(3\x81\x90\x9b\xe8>\x1d0\x1c\x1c\x92\x9b@\x91\x9d\xb4\x154\x08\xd6o\x89\x93\x85 $\xbaw\x94\x8a\xde\xe9|9a\xb6Ny\xfb !\xf5\xba\xab1S\xba\xe8\x1a'\x8a8\x899\x19\xca\x86\xa3\xe5\xdc\x06\xdd %\xad\xb7!L\x87\xb6\xa3\x89\x9a\x9b\x0e\x1ae=\xdb\x8a\x0b\xdd\x9a\xdaV\xf1\xaa!\xb6\xe6\x11f\xcc\xeb\xf85\xa9c\x1c\x1d\xa9\x00\x83}\xadI\x8d\xaa\xcd\xb5_3\xd5B\xc7\x8f\\\xd0\xfc\xcf\x9f[xEk^\xe9)\xd7U\xc8\x9b\x15\xe9l\xafl00\x9e\x85\xf5Y\x10\xde\xf1\xc8m\xc0\\v\x0e\xc7a<\xbb\xd0\x83`)A0\x1ee\x14\x06\xe0\xc2\xc8\x00h\x9f\x8a\xdd\xd7{\xa9a\xcf\x8a\xb8$Y\x8d\xa1\xba5<\xda\x10\x83\xd6\xf1\xf0\xac\xed\xf1\xaa\x95\x84\x9aG\x98B\x17\xf1\x95]\x9b0\xbf\x97\x92\xf9\xbd\x18aE\xfbE\x9f\x18\xd4\xc3\xa2s\xb0\xa5O\xf1\xba\xef\xfd\xa3\x01\xc6\"\x8d\xeb\x9ad\x13\xd0\x04}Yl\xd2\xf4\xe6\x8d\x08g\x84s\x1e\xe1;\xbe\xf0g~\xea\x93\xae\xf6\x1a\xf4\xe3\xc8:\xddh<1\x93\xea]\x99\xaf\x93\x8a\x8c\x18D\xc1\xb5\x86s\x9f`,\x14\xa7\xb1p\xcf\xae7\xe4\xda\x117\x86\xe3\xa3\xf0\xa1\xe0}m\xa5U\xb5\x01\xb8\xa8\xdb`\x08\xcf\xc1U\xc4j&\xf7\xaeL\xd6I\x9d8kA\xdcg\xb9\xf9\xcdg\x99T\x7f\xa9\xf2\x8c\xcb`+\xdd\xfb\xe7L\xde\xed\x89i\x16\x84\x92jn!/\x9b\xb4\xdc`\x1a\x18\xefQ\xe3\x1b\x9fT\xaf\xb9&b\x02W\xba\xd7\xcf\xe6s\\\xb0\xa6\xdaZW\xed\x7f\x92\x8c\x94q\x9d\x97#\xe6\xf5\\\x92d\xe5\xfb\x97\xcd\xd7ns\x13\x1fL@\x93P \xa9\x18\xdb=\x81B\xf7\xf2\x84\xe5\xaeu\x1eq+x\n~\xdc\x1fc\xeb \x95\xdf\x15C\x1f\xa9\x0c\xfd\x9dRap#t\xa3\x8e}A\xae\xb4'\xdb~\xba?\x94fm\xf8\xd3'{\x03\x86M\xb6O\xb7\xcebw\xb0\xf7\x9d\xf9\xd3\xff`s*q\xbfw\x07\xfeJz>\x8c\xe5o\xe8;\xae\xe8k\x97\xbcv\xcfF]_\x9d\x850\xb8N\xea\xd5\xf3\x92\xccIV'qZ\xc11xI6K7s\x82&`U\xbc&\xf7Y\x9cx\x8d+\xb6`\x03\xc4z\xdb\x14yd@hB\xe7\xbe\x81Pm\"p\x9d9\xbd&`G]XML\x01\xecX\xf5\x1e\xb0\x8cyTA\x8d\x177,\xfc=\x9b\xd1\xb6&\x9a\xd0g\xc6\xcf\x06\xd2\x1b\xcd\x9a\xe5\x99h\"\x88\x01\x8aw\xaea\xe0@\x95c/\xf2\xb9>x\xa7.\xcb\xc9\xef\xcc\xbf~\x85\xdb\xbdd\xe8\xb2,\x1e\xf0\xe9]\xc7\x97,\xb7\xf2_N\xdf\xbe\x11N\xbd\xb3\x94\xc4\xe5\xf3x\xb6\"6\xbb\xd6**\xd2\xcd2\xc9\xaa\xa8$\x8bJ\xf9\xb0cB|\xeb\x9aQ\x1eT\xc2R\x9b\x17J\x10\x97z\x95\x18\x92\x99\x9c\xa0X\xd8\x19\xe0<\x9f\xe1\xf0X\x14]\x12\x84\xdd\x19,TX\xf8\xd7C\xeae\xddf2\x84;\x01\xd3f\xba0\xe0\x97~JB\x8c\x9a\xb6\x07m\xd0i\n\xeb \x01N\xd5\xb0cI\x81\x931MM\xd3X\x13\xf2>\x08\xf5\xdf\xad\xf5\xdf1\x9cN\x08~\xc7\x8f.$\xec\x85\xb6~\x9c\xa6o\x17A\xd8\x8d\xf9n\x06\xb55k\x9b\xbc\x11\x1a\xa6<\x17qE^\xe4\xb3 \x9clCi\xf8\xf0\x07IfW[\xa1\xe5\xbdE\xa1\x82\xfe\x8b\xa4\x9aQ1$c\xec\xaa\x86\xebmj\xf3\xd5y\x1d\xcf\xca\\\xcb?\x8b\xb2\xce\xe7$\x15\x94\x86W\xefGE\x01\x854\x9e\xbb\xe4E\x86\x8eos\xdc\xac]b\xf4mv\xd5\x1b&\xdb\xb8\x1d\x8b\xf2\xa5\xee\xc7\xa2\xb8\xba!\x8b\"\xcf\x8a\x9e\x07\x87\xc9\x16\xb4[\x98\xeb\xa0[\x8fc\x1c:D\x91#\xb48v\x882\xac\xf2\xe6\x8e\x1e\xe6f\xb4>\x1b\xa283D\x9d\x0f\x9c}8D1(\xd2\xfd\x00&0\xeb%\x13\xb3\x9d\xe6\xa0\x90^\xc2N\x083\x8b9\x94pl1\x1cd\x8bE\x92\xa2{W\xff~\xde\xc4\x8fT(\x8c\xbe\xee\xaa\x1d\xb0\x0b3\x17\x19R\xdc\xb1]\xd2\xa3E\xfa\xcak9\xc66}\xd1\xd7^\xf2\xa6U\xc2\xa5\xaf\x89\xf1\xe3\x9dy\xf9\x0b^\xdb\x91\x97?g\xebr\x99\x14B\x97\x87<\xa7\xbe\xf25\x8b\xe7U\xd7\x1a\x19\x1d\xb8\xc1\x13\x89\xf8Ibd\xfai\xad\x13tc\x0e\xb1E\xbc\xd5\xbe\xa6\xffl\x04\x9d\x0b1fN\xed\x97\x18\x91\xd1\xcck\x8c\xe03\x1cy\x8c\xdb\xc0?\xe1t\xbf\x9b\xfa\xbd\xcfZn8\xf7\xa8\xb5\xb4\xe2\xd2\xfc\xbe\xe6\x15K\xbbY\x19Rnf\xfe\xd6\xba\x83\x83\xbd\xad\x93\xbb?\xd9Z\xfe\xdfZ\xfa\x1f\x18\xabU\xf6W\xdf\xdc\xb9\x10a\xe2\xc8\x0d\xfaOy\xa2\x9b\xd9\x03TAE\xb3\xb8\xa87%9\xad\xe3\xd9\xe5\x872\x9e\x1186\xbd\xe1\x04\x9d\xfe\x1b\xcd\xf2\xac\xaa\xcb\xcd\x0c\xdd\xdf'\xecYEkR^C\xfan\x06\xec\x99\xe5\xaaA\x1fx+k\x05\xde*Y\xe0\xad\x92\x05\xde*ww\x03\xc8\xa6e;\xf0Vi\xe0\xacqpkRU\xf1\x92`\xae\xc6\xbd\xb3\x90\x99\xd0\xd4\xad\x93J\xa7l7\x11\x8c\xac\xb9\x8bW\x9dUC\xf5\x05\xcf\xedC\x8f`\xf5\xa9\x02:\xfai\xd8q\xa8\x1a\xad\xf5\xfb\xed\xf12\xa9^\x96\x84\xa47o\xe25\xb1\xe7w\x90\x86\xe4S\xd2\xf2\xc7\xd1\xae\x1d;\xc4\xa5\x0b\x9d\x91\x80\x97Q\x92\xcd\xc9\xa7\xb7\x0b\xca\xa5\xfc \xee\xefS\xda\x9d\xcb\x87Y\xf30q\x0d=)WZ4BX#}$\xb1\x12e\xf4i\xf2\x1a\xb9K\x17M?\xc7:\xb80 \x1dX\xe5\x85\xa0f5\x0b\xc1\x13\xe7\x05\xfe\x10\xf9\xf8^\xb4\xbf\x98\x89\x90\xb4\xd5\x83j\xb6\"\xeb\xb8\xfb\xb4\xd5\x88\xf2\xbc\xdd\x95\xda\x0c\xef\xe8\x946\xa7\x1f{\x82cg\xfd= \x9f\xe2u\x91\x12\xefl\x0c\xc6v\xc8\xf7\xc3/ \xc3\xadW\xff\x96*X$G\xc6\xedp\x07\n\xda\xfe6B\xf3\x86~03\n\x87\x8cG\xf9\xc3`\xef\x8c\x9c\xed \xc5T\xef3r%\x91>\xb9F\xab\x8f~'\x1d!TP\xdd~E\xb1g\x90r\x97\xa4\xca\xd3+\xe2w\xb5\x82\x96}[G\xf3\xa4\x8a/R\xc6]-\xe2\x19\xc1\x00Q\xdd1\x84\x18]\xfb\x92<+\x92\xeaC\xbc\x94\xd9C\xfd:\xd0G)\x1e\xa2A\xb34!\x99\\\xc1Nt\xb7\xdfL\xcbxh\xd62\xfah\xed\xffm\x80\x91\xe4\x1e\x05\xba\x8a\x82\xa1\xd4\xa7\xf3\xa9\xc4[\xad\xb7A\x8a\xbb\xf9;\x03SY\xfa\xa9!\x8cb\xe6\xef?2\x06Q\\\x0cEP\xd4\x86\xb0[17\xf9'\x86\x00\x8a\x99\xff\xad\x8e#^s\xbe\xb7\x0d\xd8\x1ce\x0d48\x94\x82A\xae\x06CL\xe5\x8f\xe8\"\xc9\xe6~\xb6I\xd3\x90\x7f\x16\xf0X\x1f\x14\x9f1m\xad\xd2\x04\x7f|\xba\xb9\xa8KB\xdf\xce\xd5\xb7\xe4\x13\x99mj\xb4\xd0\x11\x7f\xd3\xc7\x9d\x18\x8fi\xebA\xabB\x13\xf01\xed=\xa4\x15\xdbJd\xe5g\xc82\x85\xb0\xb3\xe1\x87M\x92\xf2f\xae\xa2w\xcf\xde?{}\xf2\xe1\xe4\xfd\xf9\x0f?\xbd\xfa\xf1\xc5\xc9\xfbS\xd3f\x82#Xi_\xd0\x0f.h\x9b\xef\x99\xd4\x84\xed\xaa\x0f\x10r$-X\x9f\xfd\xdd\x90\x17\xaf\xe6\x13Xc\xe2\xfb\xf6\x86\xc0q+-\xc8\xac\xd1\xe2\xf1\xffY\xd8\x17\xfe\x00\x9d\xfc\x98 \xc5\xfe4\x99\x8e\xdao [\x14\xa5\xbd\xcbm\x17o*n\x0d \x84`\x1d(.\xe8y4\x96fe/l\xf4R\xc8\xc3xt\xef{\x83\xbe\xbb\x94\x08WRi\xcf\x02\x88\xd7\x06\xed/\x89Vy\x85\xbe\xba>\xff\xf3\x082\xfc#@ 3I\x80\xbf\x17\xbf\x8e`\xca\xc5\xdcY\x9e\xca\xe8(\xde\x84\x8a\x13^p\x86_^\xc4\x15y\x17\xd7+\xfe\xa9\xfcy\x04T\xba\xb3/\x80\xaa\x03\xc9\xc7\n\xca\x16e\xd3\xde\x80\xd01\xfc\xe9\xfe\x17\x98\xb8l\xadW{\xb2\xf7h\xdbO\x0f\x1fn\xad\x1f{\xb27` \xf4\xef%\x9a\xa9\xbf\xee\x9c\x1bG\x9bdv\x01\x89\xb8I \xd5\xeb\xb8\x18\x08.\x9e\xc3@\x84\xf0d\xc8\x1dX\x1a\x0chu\xbe\x9b![\x83j\xc8W8\x15\xedj\x87$\x82\xa1\x1fj\x9d\x85\x17C\x9e\xc42C\xa86h\xb4\xe0\xe5\x0f\xf6\x86\xdc\x81\x87Y2E\x14\xbd\xf6I@E\xc1\x02\x8d\xb6\xad\xaa\x1a\x11n\xfdP+5\x89x\xeb\xda\x81\x8b8\xda\x87\xda\xb7\"\x8e\xf6Cm\xc3\"\x8e\xf6C\xed2 o\xf0\x87Z\xafm\xe1\x0e\xfeP\xeb\x98\xed\x94\x08A\xb9\x00\x1e<\x80;\xf9\xb5\x98\x98K\x82^.\x12\xf6b\x98\xcdd,\x92g\xf1'\x99\x93\x8b\xcd\xf2GrE(\xe7\x98d\x8b\xdcR_\xde\xfaO-\xael\xac\xe2\x9f\x93\xaa\xce\xcb\x1b\xb3\xd5\x9a(\x8cy\xb07+|s\x1d\xaa\x16\xcc:|.Y:\xdb\x07U\x1dSi\xc46\xd4\xc2\xb5\xbd\xc6\x0c\xc3\xd2\"\xaf\xf8\xa1$d\x82\x9b\xea\xdc,4\xa9\xa5Z\xe5\xd7/\xe8\x02\x9a31\x89\x12\xa7\xa93\x1c\xd8\xd2Q2M\xa5 FY-h\x91&\x17\xafI\xbd\xca\xe7\xd5\xa4\x8b\xab\x9dd0\x14u\x035\x10\xbcu\xdc\x1d\xc6\\\x93RJ\x14\xca\xc1\x04\xfc\x06eI$\xb7w\xbe$5S\x16\xf0\xceE\x05n\xf3\xad\xd6\xe3\x8f\xfa\xd5Wq\xf5~\x93\xc9\xaa\xecg\xbf\xdau\x19\x17\x05\x99\xbfk\xce&\xfaT\x98\xfa\xac\xe3\xc2\x97\xd5X\x1d\xa5\x89@\x84\xe4\x91\xc0\x89\x1a\x13j\xd1\x01\xc7>fD\xd4T\x8c\xe7s\x7fz\x166\x1cp`\xf9\x80\xe3\\\xf3\x11\x7f \xbf\xdb\x14\xf3\xb8&\x1c\xec\xbe\xda\x94\xde\xd2`\xd0\x11\x87\"\xc1\xbcA\x02\x12\xc2\xd4L\xbd.\xc9\xcd\x04<\xa4L\x03h\xc7Y\x03\xbb\xee@\x14\xe4\xef\xe94\x1a\x9a\xc7\x8c\xf5m\x1f\x82z\x9bV\x87Z-1\xbbBc\x17j\x19\xaa\x8c\x8f!\x83\xfb\xb0\x0f\x13\xd8\x0bBd?\xf6\x9fB\x0e\xdfC\xf6\x14\xf2\xdd\xdd\x00\xcai\x8e73\xadK\xb6\xdc\xc1%\x17\xdd\xbfy\x94\x95 J\xf3e\x13\x86Jc\xbd\xa1\x16\xb39\x8b\xc1Fd\xe8\x90a\xcbtE\xca\x8b\xbc\x1a\x8a\x04\xb1\xd5B\xc9v\x99\xf3_{\xd9l\x0d\xc0\xbf\xcf\x82M\xbd)\x06\xce\x84]\xf0\xce(C\x7ff\x8b\xca&\xcaWX\xcb\x86*\x8dYNKx\x05P\x04dAE\\lk\xd4\x827\xb9\x83*\x13Qr\x83\x08\xd0-B\xfa\x99*\xf4\x99\x9ex\x98F\xb8d\xd70h\xf4\xde\xab\x10\xc0\x04t\x04\xda\xc7\xb0m9\xbf\xc9Qk0\xe9G\xc4\xab\xca\xad\xdcu\xb7\\m\x93P[\x14>\xd1\x9d^\x889\xcc\xc5G\xaeHy3\xce\xb1Y-R\x86<\xe2I\x98\x9d\xbe4$\x1bkU\xb1o*\xde\xb7T\xd4tL-K?\x0f\xc1\x988\xb1[0\x16D\x08\xb3\x10\x16!\x14\xe8\x14\xbf\na\x8d\xee\xab7\xf6\xb1\x80n\x85p\x1a\xc2\xf3\x10.Cx\x16\xc2\xdb\x10\xde\xb9A\xbe[,+\x11o;~\xd0\xadL,V&\xdeje\xbae\xdb\x95\xea\x16\xcch\xdd\xa7A\xf9\xa8\x00\x16C%\x96\xf9r\xb6[\xa4nq\x0fk1T\xec!*l\x85\xa5b\xb8$7x\xd3\xbf\x98.T#\x9a;\x07\xde\xc3\xff,\xe0\xf1\x9d\xd7L\x0f\xe3D\xe3\xd9\xe9\xa3>\xf9\x92\xdc \x0d1%.u-,\xe2\xff\x97o\x93f\xa4\x8f\xbfl@\xe0\x96\x11\xc4V\\\x93H\xd9\n\x9a\x89)\x98\x1b\xa2\xe2m1\x9d\x9f\x85\xa8G[H\xab+\xd5l*\x08Q\x8d\xa6>\xc2\x93\x1dC\xa9\xcc\xf1\xcfu\x88\x87B\xa2\x0dD1\x9b\xe6\xd17\xdf\x94dq\xc6\xb2\x95\xee\xec\x85\xa8=\xdb\xd9gf\xbf\"\xed\x91\xa4\x99\xfb\x0fC\xb4\x0d\xee\xb8\xbe\xd0\x9fU\xf3\xd3\x98 \xd3\xb58\xa7C\xb2\x15J\x1c0\xce\xc5'8\x82\x13\xc4\x1d?\x08\xa2y\x9e91r.Eb\xe4\xe1\x7f\x18m\xc0\xe8&p\x04\x9fD\x10\xf9\xe7p\x04\xf9\xf4\xf4,\xc4\xf8\x95\x0b!\xf7\x9c\x06!\x86\xac\xd4\x9c^\xcf\x83\x10\xdeb\x96\x17\xc4\xb2\x10\x06\xd3\xfa\x8e)\xf1\xd8\x84H\xb6\xf2\xaf\x04\xf5\x9dg\xff\x0d&K\x91^W:\xb2\xf6\x16\xe5\xb6\xd9\xf4\xed\x19\xd2\xb4\x80Y\xb8\xa5d\x19\xd7\xe4\xff$$\x9d\xfb\xa5\xcf\xd8\xd6\"\x08\xc1\xab\xf7\xbc\x10\x0e\x1e\xdd\x05\xcdr\xc9\x81e+\x18x\x9aJ{\xa7,d\x0c=\x83\xef\x1c\x1f\x0e-)\xb8\\\xcb\xbf\n>P\xa0\xbd\xc3\xcc\x06\x19\x8b\xd0\x96a$\xbbw\xff\x0d8K\xe9r\x80\x87\xfb\n\x0b\xf8\x1c%\xbcK\xcc\xddZ\xdc\xc5\xfe8tt\x15\x1c*\x82Q\x89\x9b\xf4\x8b_62\xb8CV\xf0\xf0Ny\\\xc7\xcc\xaaC\xe5\xce&v\x07\x94M\xb2\x91\x87\x98\xb3\x153\x0b\xc6\"c\xde\xc3\x80\xf3\x9e{\x8c\xf7\x8c\xadi\x02m\x85\xc9\x1cw \x9b\xcbq?Ty\xe1\x87\xfb!\xec\\P2s\x12\xf1]\xa4\xfc\xddM\xc05\xb68\xa5Hs)\x9426c>\x0ca\xe7\xfc\xce\x89\xe2\xc3;\xd8\x81\xf0/D\x14Y\xde\xbd\xeb/\x9b\x14[\xc1;\xd86\x92D/\x92,\xa9V\xfe\xc3\xc3;\xc1-\x87D\x89\xb6\xd2\x1b\xd9\xde\x9d\x8c\xec\xf1\x97\x8dl\x1b?sS\x913t\xf4?7\x95\xedp\xf26\x84\xd8\x9e\x98\xd0V\xa6Tj\xa7$\x97\x92\xaf\x87\x8f\x1dB\x1a\x9b\xca\x94\xd2\xbc\x10\xa9\xc8\xc3\xef\xdc\xee\x0e\xba\xc5\x10\x15r\xa8\xdc\xb2\xc4\xf1\x9d\x8b\x83\x9b D\x9b+\x0c\xc9\xcb\xcf\x8d\x82\xeb.\xe6\x8a\xeeBj\xe2\x1f\x852f\xac\xa2\xba\xc8uw\xf8\xdd8mc\xf5\x19\x88\x81[`1\xa5\xd5\x18\x84x\x8d\x1e\x02w\xa1\xae(%\x97\xb4\xa5zb;\x9a<\x1e\xdf\xf9N[\xc2\x11\xac\x85\xc6\xa1\xec\x88m7\xfeR\xbcZ\xf28\xa3K)\xc1\xed\xefo\xb3J\xfb[p\xa4\x02\xdd$l\xb7\xd0En\xc1\x97\xb1\xf1n\xc1`\xcaq\x1el\xc1Pn=\xd0-N>\xb9W\xf7\x1fQ\xe8\xb2\xd4\xd3\x9cA|\x14\xf0\xfd\xbd\xc7\xf6w9\x9a?d\x12\xfa\x16\xfc\xa0\x1c\xd6\x81JO\x0e(\xff\xb7\xa0<\xdfJ\xe1\xffV[\xf2\x7f\xce\x99\xc4\xbb\x85%3\x16c\xa2\xfc\xdd\xd6\xf7}\xe5\x97j\x8b~-Z\xc1\xf8\xb3\xf9\xb8An\xad\xa0\x91\xee\x8c\x9c\xcb9\x18\xcb\x7f9\xe73\xef\x96^\xcfc\xf9+\xd6\xf3\xc8\x93\xe8K\xf8'9\xe2\x91\xfc\x92\x1b\x0e\xdc\x86P\x8e\xe7\x87\xa6\x8fB$(t\xf7\x1e\x8ca\x7f\xa6\x07\xc8\xee\xd0Mu\xe0\xc8\xee8\xb07\x16k\x8a[\x9f\x04}\x03\xe2\x9c\x99\x1d\x96\x81\xcd\x8a\x18\xa4=\xe8\x9bxM&\xc0\xa3.|\xfe<\x14~Q\x94V\xe8Y\x95!\x92\x8f\xfd\xdc2\xfa\xd1Q\x8d\xecVN\x94(\x8d\xb6r\xb2\xd1@\xbbw\x9b(\x8aE\xe4\xaam\x16\xdb1\x1eU\xbc?\x9c\xcc\n\xa4\xf7\xd6\x92\xd4\x82\xd3\xac^\xe6%k\xce\xaf\xd5\x8c\xae\xbf\x0d\xd0U\x83\xec;\x84\xbd4\xec\xecX|\xb72\xd8J\xc9K`\xa1\x0c\xb9\xd2\xfb\xcc-u\xa7Z$\xe8q\xe8\x16\xe0~\x05\xe8. \xc7hno?\x02\xb8\xd6\xf9\xa9Q\x13\"\xd9\x11\xa5\x06>\xb1\x1c\x1f\xaa\xd7n\xcb\x1f`Z\xf3\xfc3_\x11\x14\xef7\xd9\xf3|\x93\x0de\xb0\x1a\x0d\x0buB]\x98\xfbDl\xb0\xaf8)\xde\xd7\x87d\xc8 \x7f\xf4\xb4\xf4K\xdc\xcc\xcbm\x951\xe2\xcf\xb4V\xedeX\xf2\xaa\xaf\x08\x0fA\xe7^es\xf2\xe9W\x03\xc9\x87\xa4\xc0\xe4\xcbj\xe7N0\xf2\xb2\xcd\xfa\x82\x94\x1e\xec4\xbe\xd9p\x0c\xf7\xf7\xc1\x94&\x0d\xee\x04Lt\xb7\xde%t$\xbdkX\x83\xbb\x1f=w@\xd8\x96\xae9\xd8\xc8\xb6\xcc\x92\xc7\x916_C\xd4\xb2\xb3\xb6\xbf\x87\xf2\x9c\xa7TG\x1f\x8c\xa1x\x91_\x08+v\x80}E(\x0d\x03\xa5a\xf1\xda\xe9;\xe8f\xe1y&F\x1e\xach\x8d\xd7\x0b\xec\x1f@\xc6\xbd\xcd\x19Dm\x8bE\x0bf\xd8\x19NY\xa1\x16\xb4\x9b\xd0\x1aqKV\x025\x82\x19sK\xf0\xbb+\x00\xde\xff\xcck\x88!\xcb\xb3\xfb,\x0f0\xf3\x1b\xf3Bp\x19-\xf0!d\x91\xf4\xf1b\xb1\x83\x1b?.1\xf5\xb0\xc5Ys\x1e\xcb'2=\x91\xf0\xd5\xec\xb19\xcd\xf7l\"\xad\xf7\x1fV$s\x82+h\x8cM\xd5\\\x1a\x1a\x88U\xd2\xcd\xca'\\\xed&\x86\xbb]\x7f\xe2\x14\xd0\xf4\xc5\x96E\xb2\xc3\xba\xcc\x15\xdd\xe2\x96\x93D-\xfd\x8c\xc7]\xfc\xb463,\xb0~\x0d\x8e\xbc\x03\x991D\xc3\x06\x97v\xe6\xebvL\x16\xb1\xd2hO\xd1qJP^!\x19\xd5\x19\xe3\x88Z\\\xf5\xae\xc8\xb4\xbf\xdc6xdA$q\xba+\xfesM\xe2)\xe6BW\xc75\xc1\xf0\xbev\x14p\x0c\x1ebY\xe1\xe1\x11\xb3\xc0\x14\xd8\xaet\x81mvp3dJ\xa7\xbf\x02\xb2\xb0\\\xc6\xdb\npV\x84iq[]:\xd5\xc4\x07\xb4\x81\xe8{\xd8\x13!n8U\xfeP&d\x0eu\xce\xf3;C\xdc\xf6\n\x86z\x15\xd7\x90T\xd9\x1fj\xa8W\xa4$;\x9e\x0c\xb7\xd9\x1dFU\xa4 \x95\x18C\xd8\xff\n\x00\xee\x11\xdf\xaf\x05^'>\xb5\xd9c\xfc\xafN\x14\x19''!\x11eN\xb7M]\xb6\x154S\xcd\xac\x95m\xfb\x070\xbe\x81\x06\x8d\xd9\xfe\xe9x\xbb\xda\xdc(\x03~\x890\x0e \xee\xfdkB\xa5\xaa\xe5k\x1c\x07\xaa\xd2h\x0c\xee90\x90\x8d\x97\x18\xa0\xe6p/\xd4\x0bBH\xe1\x04\x15h\xa8\x1c\x93'\x05\x95k\x9eW\xb8\x1f-\x01\xd8\xbf\x00\x1c\xcf7eI\xb2\xad\xa0\xe2\x08\x11!w\xe8\xb4u\xfc\x15\x1f\x04\x7f\xfa\x95tG\xfd\xfeG\xccu\x14\xf5\x89\xf4\x92\xbb\x95\xb6\x9b\x00\xe6\xd7\xb0\xfbU\xe8q\x17\xf4#\x00b\x83\x87:\x97\x99\xda\xc7W\x99\x05')o\x17\x1fn\x8aQ:\x80\x11\x1b[\xd8<|\xa5\x8d\xf8cr1b\xe0\x8e\x83F\xf07a+\xee~\xe0\xe7K\xf25t\x8f\x0d\xcb\x8a\xc9\xf1\xdb\xdc\xeaW\x80\xbf\x12\x14\xe3+\xcc\x86m\x82&\xfc \x9d\xd4\x90\xb8\xb4\xf54\xaa\xadf\xe1\xbe\x07z\x13\xa9\xe8D\xbe\xce\xd9\xc4\x83\x8f\x8c\x99\xc8\x98Y\xf44\xe8\xc6\xc3\x08\xfe\x04>;\xd1\xbf\xc6,gi\x9e\x8d\xa2X\x8e\x93\xfc\xcb\xe9\xdb7<@\x1feMsE6\xfd\x1a\xe7\xab\x88\x8d5b&\xb6\x89H\x97lb\x9f4-\x84 \xce-\x81W\x93\xcc\x97k.\xda\xac( a\xfbH\x14\xd09\xfe\xedW\xc6\x99sM\x19\xc0\xba\xb9\xcf\xb5\x19\xc9\xa0R\xcf\xc9\x11_D\x8ck:h\xf1\xec\x0e\xc2\x06\xed+\x97\xda\xa8\xdc1\xb8v\xb7\x88}i\x8a\xb0\xa6+}\xe9\xe4\xeb\xf6f\x87\x85\x88\x96\xed6\n5\xb6+\x9ekN_\x89\x00b\xf8\x1d\xfba\xfd\xce=\xca\x04\x1b\x8d\xaa\x8a\xf5\x13\x11\x0eI\xa0I\xa3\x9a\x0dB\xf5\x9e\x99\x07\xb3M\xbed\x131]0\xbbV@\x9a\x8c\x11C\xd5\xdfx\xd3\x16\xb6\x1f\xb2\x0c\x1e~\xef\x19Rl\xca8k\xea\xff \xf6\xf7\xb4\xd7\xe5\xd6\x98\xbc\xa2\xb0\xf5\xcb\\\x17O,\x9cT\x99r?P\x99\xf4\xc3\xf7\xfeF\xfepE\xa0$\xf1lE\xe6\x10\xc3*.\xe7\x90&\xeb\xa4\x86|A\xc7\xcbMT\xa0\xdcd\x95g\xa3V\x0eD\xa2DW\xb9>\x87.5\x93zK\x03\x97}&\x92\x08i\x9b\x19oy\x00\xe3\xac\x0f\xc0\x01\x00\x00\xd0_\xfe8M\xfd\xcd\x97\x8e\x0fi\xa0\x88\x97\x13\x82\x0cmfm\xe56p\xcdN\xd0-\xdb\x91\xb4/\xd8\xa9\xbc\xc3Q\x03\xcd:Xv\x04\xa5}\x89\xc4\xb9\x9aE\x1a]\x85o \xab'J\x8e\x0dtu-p\x1f\x1cla\xc7]\xa6\x95\xaa\xd9\x97\x0bPD\x11\x87\xc7P&_]\x89\x99\xf1\xfe\xa8o6\x8e\xd1\xa3\xd4\xe2\x0e\x06Qdh\xb2\x8a\x99 w\\\x08J\xbf\x0e\xd9\xaa\xfe\x98\\\xf8A\x10<\x85\x1d\x9fB\xc0\xaf0\xa9A\xcb\x8c\xff)\x87M\x00\xc4\xaf\xf8\xe5\x87\xf3`\xc6\xdft\x89\x12s\xcbi\n0;\xc5\x11\xe5\x16\x16I\x16\xa7\xe9X\x80\x8d\x071-; %\xd7\x85bL]Hc\xeaQ\x8dm;l\x10\xeer\x01\xb70\xde\x8c\xfa\xdc\xcd\x86\x15\x9ck\xde\xb2;p\xd2G0\xeb\xe7\x12Q\xac\xe2\xb0(\xed+Q\x8ck\xeeO-\x91A\x9d\x8cQEa'\xfe\x04\xfaY\xfeu\xe56p\xb1\xa4\x1d\xb9\xceRTj\x99K\x95cf\xd12!2%\xec\xee\x16\x97\xf8i\xd6\x1a\xd2,\xc0\xf1`\xbc\x1dxo\x90\x8d1&}\xef\xd5\xad\xeel:1J\x07%YT\x13X\x0b4\xd1\xd3sL\xa1<\x81\xe5p\xad&\x05\xd7\x04n,Ue\x04\x9c \\\x88\xaa\xfd\xa9\xb4O 5\x0c\xf9u;By\x93ay\\<\xf8\xc3\x87\x03\xf1\xe0\x87?=x\xfc\xdd\xb6\x9f>\xde:\xa5\xe4\xc1\xf6\x91\xef\xf7\xf7\xb6\xfdt\xff\xbb\xed\x13\x04\xec\x7fIF\xca\xd6+\xa9\x94\xf9\x8d\xe2\xed\xeb\x07\x93\x1b\x95\x98,2LT\x93\x8aY5\xe9\x07\x80\xb5jq\x80Q\x99\xecm\xebV\x9d\xe5Z\x8a\xa1$i\\'W\x04~z\xffc\x08\xd7I\xbd\xca75\xac\xe2\xab$[B\x0c\"\x13E\x84Y\xbe'\xf0\x07\x19\xf4\xf4\x0f\xf2\x1d\x7fZ\xe3S].Bh\xa0\xf8\xa9'\x97\xd6Z\xf5w\x9f2\x89ep\x82^b\x84\x9e \x9f\x0c \xcf\xf3M:\x87,\xaf%DJ\xb2 %\xc9f\x04.\xc8,\xa6X\x93/&\x80\xb3\x16\xb92\x11\xc3:c6\x0d$\x1e\xc4)\x1f!\xe9\x05h\xa3P\xfb\xde\xef=\xb7V7\xc6\xe9 \x9b\xbfwS\xa2\x89o\x8b\xda\x084\xe09\xd5\x98\x9eeA0\xc0\xb1 \xab\x80\x14\x99\x90\xe1U\xa6\x0c\xc2E\xc3 ,{\x8b>\xec\xbfr~\xce\x15\xabz\x1eA\x97\x91\xc6\xca\x10\xf3\x91\xa9C\xe1v\x81\xee\xb8W\xf9\xa4+\xce\xda\xfaKM\xf8\xed\xb6\xd0\x95\xbe\x03!B\xeaWY\x88\xcep\x0c\xbae\xae\x038\x86\x1a&\xd0_\x96:\x80 \xf8\xb4U8\x82W,G\xf8_N\xdf\xbe\xe9\xcf\xdb\xc8O\xf2\xcey\x1b\xb5>U`\x88\xef\xdd@\x90Zq}\xa6\xbd\x85f\x9a7.\x17\x7f\x0f\xfbR5V\xf7\xeb\n\xdc>\xed\xde\xd1\xe91\x1d\xcd\x18\x9b\xac\xe4e\x87\xca\xf6\x89J\x91'YMJNG\xe8\x9e\x87yN*\xacC>%U\x0dI\x06\xf3|\x86\xa1\xa9\xb5\xf9Th\x91\xadh\xce\x14\xcd(\xf9t\xbb\xc9\x16\xf5P\x9e\xe9\x11\xad\x95\xfe\xb21\xf9 \xea\x8c?\xdc\x14\x84\xeb\xfbN>\x15dV\xa3\xaa\x8f}\x14\xc2\x12\xadi\xe9\xbcU\x90\xd1\xc3\xd3\xdbd,\xaf\xcc\xdc\x03\x96|\xe0\xaau\xa3c\x9e\x92\xf7\x80Y(\x92\xe9\xde\x99\xbc!!Q\xb5\xb9\xa8\xea\x12s\xc1\x80\xe7\xc9~\xa6g0\xc1\x0cXHb\x1fx\x01\xd3\x86\xb9a\xdfb\x90~\xeb@\xc3\xd9\x82\x13\x89J\x9b\x8cT\xb3\xb8 >\x91\xc9\x9f\x1e\xfc\xd7\xfe\x83e\x88\xb9\x9d\x94g{\xf8\xec\xbf\xbazP\xd3\xd0\x8a\xc1\xa15\xfdkzg\x1d\xed\xa9\xbd\x7f|\xc0\x1e\xee\xbbv?\x1fdP~\xf6\xeb\xc6\xa4wG\xa3\x95\x11\x9b\x97D\xb3U\\>\xab\xfdZ\xda\x0b\xe9\xe9\n\xcb^\x86\xa6C\xf7u\x1e\xfe\xbc/\x8e_j\xdac\x8a!;\x98\xb9^ \x0e\xfb\xf1{\xfe\x03k\xd0_;t3;M~%\xf8\xcc\x10\xb4:1q\x0d\xf5\x01\xef\xc5K\xcdpsL\xf5\x95\xf3\xc0\x15\x1f\xf0\xda\xb9\x0cA\x1b2Sh\xd2\xec\xa7\x0e\xf4\x01\xc1)\xe01\xdd\x12\x13\x84\x00\xb22q\xe1\x17A\x93@Z\xdb\xda\xad\x9f\x19V#\x86#\xf0\xf1\xee\xc2\xfb\xbe*\xc8l\x1d\x17\xf7);\xf8'/\xa0\xd4\xed\xf7\xd8\x89\x9ep\xd6p\x84\xce\xfc\x1d\xdb\x81\xe9Y\x80i\xcf^\xe43\x0cZ\xea'\x98\xca\xd0\x86B\x1b8\x02\xcf3Q\xffq\x19\xadi[\x1b:|\x84Q\x81\xb7\xaa\xf9t\x83$\x86\xfe\xef\xda\x9c\xd2$n\x92\x18c\xb6\xcf\xfd\xd8h\xe8\xa1\xe3h\x86\xe7\x9eO\x13\xbc\"\xc2\xff\xb9\x93\n\xbf\x7f\x89\xbb\xfbW\xfdu\xe7 \xbd\xdaC\xa3Kr5\x94\x93k=\x94Xk9\x98\xb0K\xa6\x82\xd2~{1\x94X\xeb\x9c%\xba\xd5e\xb3\xbd\x16}jSH\x9d\x88>\xb5\xcd~\x1aL\xf2{:\x94\x13\xeb\xb9\x18\xae\x16J\x97B&\xef\xbfz\xc6\xd3\xea\xbf'\xcb\x93O\x85\xef\xfd\xdd\x9f\xc6\xf7\xffy\xb6;y\xf0\xe0\xf3\x83\x07\x81\x17\x82\x97x\x9a\xef\xder}\xf5\xf3\xe6\x8c\xf5(k\xf7\x9e,\xf0\xf0\xf6\xec2\xb4(x\x03&2M\xe2\xc7,_\x7f\x87\xebGk\x00\xe0\x17\x9c:\x04\xef\x0f\xf2\x1d#\x87\xbd\xe7\x1f\xf8\xa4\x07\x94?\xaf\x8d\x8a(f\xcd\xf1MI\x16\x06K\x0e\xa1\x91\xec\xce\xdf@\xdbE\xc1\x8b\x00\xbc\x86a\xa7\xd2^\x08\xda\x83I\x14\x94\xc8i\xad\xcb(\xa9^\x96\x84\xa47o\xe25\x99\x07~e\x0d\xeeN\xfb\xc2\xb4sJ\xf6#?\x93\x14\xd3~1\xaag\xe2\xda\xc20\x05\xd1\x04\xd6\x9b\xaa\x86\x0b\"Y8\xf0)\x9a\xdc\x7fO\x16\x81\x913U\x0bk\xc5\xe1\xfe\x98\x8f}\x02\x0e\xd9A\x16\x1b\xbc\xa3_\xd9,\xcamW\xa4\x14\x8e\x0b8B\xb1\xdc\xdek\x81\xa1\xb7\xf7\x1c\"E`\xd8\xee)\xf3\x9b\xb5en\xa3\xe5\xca\xf1\xbe\xca\xed\x02\x85\xb6\x96\xd2\xae\x0b8\x86\xdc/BH\xa9 gL.+\xca\xb8\xdb\x01\x8e, =-\xec\xb5A\x15X\xe6v\x88\xc0\x18\xd4\x01\x8e>\x0c%\xae\xdc>p\xc5!\xd0\x1f\xc8\xad\xd7V$[6\x91\xc7\xac\x9d\xdd8\"\x03\x12\x90\x95?\x0f\xe1*\x84\n\xcd\xbb\x1c\x16\x029\xa1M\x9aR\xb6\xeb\n\x8e\xc1\xbfA\x91y.\xfc\x07\x19\x9f\xe8/\x05u\xf1o\x02\xc62/9\xd1\x1dV\x93q\x99\xf6_\x06%\\)\n\x8c\xc6\x88\x80\xee\xa9%OhD\xe9(Bh\xe3_\x850\x0f\x82\x88+\xad\xe0\x18\x96\xf2\xef ,\xbb&]N[\x0ddl\xa3\x11\xbb\x0d\xb6\x00/\x8c\x051l\x01f\x18 j\xb0o@\xe0j\xa4\xa5\xc6\xc5\x98\xd3\xa9\xe9\xa9\xa2\xdeZ\xe7W\x84\n3\xb0t\xc8\xfaE\xf7\xefEK\x1b$\xa4\xe4\n\xd3\xdf\xb8-\xc77\x1c\xae\xd6\xca\xb63\x0b\x84\xc6\x89\xee\xca+\x14R\xd3f\x96\x17\xa12N\x91\x1b\xd0\x9acT\x14\xb9\x94W\xd6\xea\xb7\x81\x03\xe8\xdc\xce+\x10\xc4l\x9c\xc5\xb6Z\x84\xfa@\xab\x005\x15iST\xc4\xf5**\xc9|3#\xfe\xd6C\x00\xf52\x96ytNk\xbc:\x9d\xd6nA\xa2h\xc1\x8c\xfd\xee\xfb\x08F$\xa55\x15>hU7\xcc\x9d\xe4\xb9\xb2$S\xb5'\x7f:\x82=\xd4U\xec\x85\xcdmn\xe0\xd7AG\x1cv\xf2\xa4\xd3\x15q\xb1\xe3\xd7\xd3\xcc\xe1\xb2\xbf[\x86\xe2\xf2\xe8\xca\xad_\x8f1\xb7\xb9\xf5K\xe1\xa5q\xd1\x88\xe4\x17\xd6o\xed7\x12\xdd\"p\xc9\xc6\xb5\x81\x95\x011\xbf5\\\xf8\xf7\x9ejd\xb0W\\\x80T$\xbc\xd7&23\xcfg\xcf\xe3\xd9\x8aL\xe0\x9d\x1e\xb5\xe3\x8b*O75I\x167\x13\xc8\xf5uf)\x89K\xde\x8c\x9b\xd2\x85\xf33;\\\xf1;')\xa9 \xbb\x8a\x98t\xf1\xf7\xdd6\x91-\x94\x16\xcd 6\xa8x\xf4\x93TE\xf0 \xbc\xd5W\xba.\xe3\x82\xd7H\xf45\x96\xa4F2n0\xbfG\xdd\xf7\x04b\xfd[\xf2\xa9.\xe3Y\xfd\xb2\xcc\xd7\xd8\xc8F_M\xde\x06\xb9.\x87r\x19x\xce\xee\x920\x81\xec0\x88W$\x9e\xa3\xa1\x87}\xd3<\x9b\xcdHQO\xc0\x8b\x8b\"Mfh\x8f\xf3\xe0\xe7*\xcfBP\x9f\xdc\xc4\xeb\xd4\x1b\xde/\xc3\xf47\xcd\xe3\xf9)\xdaF\xef\x98\xe3\xaf\xdd:\xdf\x0c\x8a\"\xe8^\x84G\xf6\x80\x91\xce\xb6-_K\x02_\xc5\x0b\xf2c\x1e\xcf\x07=\xb4F\xe1-\xc7\x19#\x0fH\x97\xe1\x1dcF?\xe4\xe8\xa42\x81\x99\xbe\xaa\xb8\x1f\xf9\x8b\xfa\xc9%\xc9&\xb0\xe8\xd3\xa5\xa0k\xb9\xc3\xa7\x08G\xf0\xaa\xaf\x8a\xfc\xd9\xaa4\x17*V\xa2^\x0f\x10\xf5z\xa0cp\xd0\xeeD5J\xa9{\xe6FcMZ\x1enm\x0ds\xf0\xed\xf6\x9f>\xfa\x02C\x1a\xf5\xcd\xaf\xa0Z.\xad\xeb \xdb\x1a\xec\xc0\xb0\xd1\x0e\xe8\x8fI\x93\xc29\x17\n\\3\xba\xf6\x87\xc1\x14\x95h\x12\xa7Q!\x99\xb5\x94 ^1\xe8\xa7\x85lv\x1c\xadI\x1dS\xa4\xe6\x7f\xb24\\6\xe5\xe6f\x1b\xe5f\xdeUnn\xacZ\nf\xd0\xd4Isk\xfb\x08T\x0dl\xfb\x16\x1a!\xd8\xe813\x88i\x9b&\xc3$\xb5\x08;\x8fH\x88\xabL\xb1m\x89\x003\xf8Vhn],\xdag\x98\xee\x04\xb7\xc3\xf0X7[\xf0.\x80\x1d`B,8\x82Y\xcf\xfe\xa2[\xa8x\xcd\xf8\x1d\xfc\xc0\xdfca\xd89\xfb\xf4\xcbm\x08\xb3 \x88\x10\xd6n:\xd7i\"\xe5\xe8M\x08\xbf\xdc\x062c6\xe9\xf8\xa78\nb\x887I;\xc4\x97\xfd+\xe0_624\xe5\xb8\xed\xb8A\x0b.\xa4\xa3\x8b\x81\xa0W]\x13\x89\x94`\xfeqH2h#*\x8b\xbdT\xb9\xe0)(\xe6\x1d\x1d\\\xb5\x9bU;\x9b\x18'\xd1\x9a\x94K\xf2\x82\x90\x82\xae\x98E`\xba\xb5\xc5n\xe2\xad.\x98\xac\xdci|\x16\x04!\xcc\x18]\xa2\x84J\xd6\xe2\xba\x9b\xa9D\x96M\x08\x1eV\xf3\x02\xfaM\x9fG\x10\xc5Y\xd6i=\xc1XTc\x0eu\xeb\x19\xd9z%e\xf7\xdf\xc8\xd8T\xfd\xf5+\x1c\xd8\xf9\xd0\xadl\xd2\\\x90\x8e?&\x1b\x9b\xf0Qgei9+{\xd9\xd6q\x1d\xec^\x82\xe2\xbc\xec8\xa6O\xcf\xec\xea\x9d\xfe\x1d\xa2E\x1c\xe9wC\xa9q\xd2\xb1]+\xa3\xaa \xb3\x10\xaa\xa1})e\x90\xfey\xe2@\x84\xdd\xb4}\x9bi}\xa6,h\x19\xc9\xa5{\x1d\xcf\xca\xdcO\xed\xa4e\x94.E\xe0]\xe3\x87j\x0bR\x03\x0d$\xf2\x0e9\x1dv\xec\x18P\xb4\x04\xea\x8a\x88s/\x0bac\x10\xb3\xb4O%!\xd64d5\\\xfdoJ\xf6oB\xc9\x9a\xa4\xcd\xa3(\x99i/\xd0\xd1\xc6z\x1aa\xda\x08\xd2\xb1qC\xd9\x122d\x06NK<\xdd\xb4w\xf4:\x9f\x93T\xc0\x9d\xedjZ\xc7\x80\xeaN\xbbY\xe5\xed\xed\xbbx\x14\xe3>~\xaf\xc5\xff\x8f\xef5\xfd`\xcc.*\xd2T@\xdf\xf3l\x95\xa4\xf3\x92d\x13]\x8cq\x16e\xb0v3BM\x86l\x95\xe4\xe1&b\"\xca`\x0b$*\xca\xbc\xce\xff\xca\x9fgp\x8c\xbbe\xd3\xde-\x99R\xab\x89P\x8a\xc6\xc4W\xec\x99\xbf\xa7\x04\x8c\x08|\x12\x89\x99i\x94\xcb\xc6\xd3T\xb5\x84e_Ok\xc3\xa5V\xab\n\x1cAB\x913\x13\xa3\xd1\xba\x19t=\xf9~u\xc2\x19\x0fY\xfcm\xf8\xcbC\xdd\xcbJ\x98\xd7i-\xe8RA\x90\xb5\x0d\xcfTM\x91 \xf2\xae\x17i\x9d\xb4\xf6\xcc\xb0M\x86o-\xf3\x9cR\xc1\xdc7\x9a\xba\x81\x8d\xe8t\x1c\xc9I\x08S\xf3hd\\\xac\x11\x81\x89\\\xb8\xb9\xabnP\xf5\xb8$\x19\xc6\xc2\xda\xb1\xa5\x1bB\x1b\x13[\xfb\xa0\x08\xc5dJ\xd4t\x03v\xd5\x08p\xa3\xe3L\xee\x00;K\x17O\xcb38\x86\xc4\xa7\x7f\x0821a\x8fq\xbd\xe8\x83\xc1V\xb8\xe7u\xe2\xcb\x85f\xcdl\xd2t@\x91\xae_\x7f{\xc0\xa9;\x8e;G\x17\xc5\x97\xb1;\xa7g\x81\xd6\x19FL\xccE\xed$\xd9\x04\x19\x15\x92\x81$S\xd3,*\x7fS\x9ei\xef)\xe4\xf0}c\x87~\xef\x1e\xf8\x0c\x03\xf2\xb3\x10|D\xb8\x86lN\xcb\xb3\xe0)\xe4\xbb\xbb\x01\x0b\x911--\xd7\xfbb\x1a\x18\xe0E\xa1\xd7_eu\xd8\x8e\x18\xb3F\x0e\xdb\xaeu\x03A\x945\x82cfi4Q\x9f\x1e\x888\xc9Hu\xd0\xafE\x11\x1cu6\x0dN\xfb\x12Ui\x8dA\xa8\x05\x0f@\xdd\xc9#6\xa4\x98j9\xcd\xd0\xa8\x9eE\x8e-Y\xfe\x85\x1c\xad\xd4\xd0\xe8?\x04\xfalxg*\xc4w\xf4V4\xfa\xb7\x9b\x99\xf7\xd9X\x06o\xf8\xd6\xe5p\xc0\xf1\xf9\xdf\x8b5T\x7f\xfd\n\xdc\x84\x10\xc3\x1e\x0e\x89aZnB\xf0!\xfbZ\x8b{\xc1\x88\xeck\xe5;\xc9\x89<2q\"\x99\xff\xed\x00\xf6\x0cr\"W<\x03Y\x87\x99\x94\xa2\x1bKs\xab\xf2*\x03\x9b\x1a\xb7%f\x0b\x9e\x85\xb0\x08\xa1\x08a\x1e\xc2\nMF\xd7h\xbdv\x03G\x10\x97Kt5T2m\x1d\xa0uYc@!\xabL\x0f\xe8!\xda\xfaI\xf9v\xfdn\x97Z\x141\xf6\xeb\xd29\xf2\x14\x9e.O\x9f\x06P]'L>\x14\xd9, \x86\xce\xb1\xd11LW\xe8\x90\xd5S(\xce\xe1\x08nx\\\x99\x93\xacNJ\xf2\xa1$\x84\xa5\x18\xbe\x11\x86\xf5,\xb50\xad\xf6\x8f\x0d\xa9\xeaWYM\xca\x19)\xea\xbcd\xc9\x86\xe9\x9b\xaa\xc8\xb3\x8a\xb4^\x15\xf8\xaa\xad\xe7b\xd9Jo4\xb22\xcbGl'\xd2\x80\xa10\xea\xd5\x8b\xa4\x9a\x95\xc9:\xc9X~\xbe\xcc\x8d{\x92\xa6~\x06+\x90n\xe9O\xd9x\x83\xdf-\x1a\x98L`\xe1\xf6m\x1bh\x13(\xdc>\xebCu\x02s\xeb\x97\xb7!\xda\xce3\xf6[\xa6\xbe9\xbd\x8e\x97KR\x06\x0e!\xf3\xa0 {h\xadKe\xb15\x86\xf2d\x8aY\"\xb2\xac~\x1bv%\x8cN\xea\x0d*\x8c\xael\x863\xa2\xb0\xe1\xac\xdd\xc0\xd6\xcf\x80\xe1\x1a\xad\xab\xbaL\n\x11\x85\x14\xedl\x06\xadcD\xb1^\x12\xe1&\xfe\xd6y\x13/\x99\xe3/\xc9\xea\x10vJJ\xc2\xda\n|\xe6\xdb\x99\xa9\xcc\xe7\x12\xc1\xcfW]\x91\xf8\x97|Y2\xf4\xd6C\x16\x9f\xaeQ|Qn\x8a\xda\xf7X\x87^\x08K\x97\x19X2\xad\x8e\xc9\xac*\xb5\x18\x96L\xaaF\xc6\x960VI\xebb\xd8\x9f\x8a\xb8\xa5\x93j\x8b\x81\xc3F\x0e\x0d\x93\xb0p\xb9X\x9e\x14V\x9d\x99\x1f\x8ce\xaa\xfe\xbdX#\xfd`\xf2A&@s2\xef\x19O\xe6\xbd\xf6\xc9\xbcg:\x99{kjSE1\x0b\xe97\xf1z\xc0+\x809d\xaf1\n\xbb\xb9\x16\xc6\xe2\x8d(Yf\xe1\xb2\x0c\xb9\x9a\x9dG\x08|\x94\x89\x1eV\xfbFX\xed\xb7a\xb5?\xc4\xc5\x80\x8a\xdb\xe4\x13\x99mj\x16rZa\xcf\x86\x891#\xc2\x04I\x8ay\xc7\x86]\x1aDB\xf0\xfa\xe7\xae\x87O{G*}\xbc\xa9H\xf9\x92\xd4\xb3\x95g\x8d\xc1&V\xd4\xca0\xb0%\x9d@9\\M\x0d\xcaeI)\xac,\xffP\xa8\xb4\xdb\x10\x12\x831\xb7\xf5\xd6\xde\xac\x1f6\xed\xb6\x9a\x1d\x1d\x94\xe6k\xbb\xe4*\xd9\x0b\xfd\xdbF\xcd\xc1\x03\n\x1c\x03\x95\xd4\x0d\xa0\xcd\xb1-\xbe\xcc\x1f\xe2\xa5\xbeV\xd2n3\x87c\xf0\xf87\x1e\x18\xcd\xa4c\x96\xec\xe7\xe0m\x03\xe4\xe7\xf9\xba\x88\xeb\xe4\"I\x93\xfa\xe6u>7\xec\xe2\x8d\xc1\xdb\x96\x96\x05\xbe3\x92\x12\xc6\xaf\x90x\xb6\x92\xdd\x06\xf4\xa8\xb0s\xfa\x8d\xb6\xdbNb\x18\xd8l$&\xc5Z\x12\xc7\xf4[\xdaO\xa3:^Vp\x0c3\xfeg\x00\x13\x98&gc\xcd\xc0[\xce\xb4G\xaa3\xad]\xbb\x8a1\x1cX`\x1c\xfc\x8f\xddF\x0c~\x06\\\x97\xcd\x00\x9e\x17\xaf\xe6\x81\x9f\xe2\xfd_n\xdb\xf0\xa2\x0c\xa3\xc6\x04bk+:W\xedn)PDv\x1b\x11\xe7\x98\xed\x8d\xc2\x18\xba%\x8a\xa0_\x86\xfd\xd2-\x12q\x9c\xfd\xd9Z\xe4\xccL\xdeE\xb1\xf9wQ\x8c\xdaLgg\x01\xd0\x7fwwCH\xa6\x9e\x07\xbb0\x83]|D\xf1\xa5\x18n\x83\xa9\xa9\x9b\xb0D\xf4\xecK\xb0M\xfb\x8aP\xcc\xa4\xa2)\xed\x8a\xa2\xa4C\x04a\xacz\x04s\x16\x8a|\xfcp\x81wK\xe5^:L{m\xeeyA+\xb7:\x9c\xd3\xde\xcc\x89\x9bAQ\xe2\xb31\x17\xc6\xba\x06\x06Z\x7f\xa9\xd66;\xfb\xcaj\xb0\x10\xea\xa8\"\xe9\xc2\xe0'\xac\xde\xb2\x1d\xf6-\x10\xd6\xf1%9aL\x0c\x1cQ\xb2\xc1\x1e=+\x92\xeaC\xbc\x94\xb4\xa1\x92\x7f5\x95\x9d\xf4Vw\xc0\xb2\xea\xf7\x1dj\xce\xd4\xe1\x1b\x9d\xf63^\xb3hMh\x80\x1a\xd9h\xe2v\x07*t8?s\xad\xd9\x85Ic`\xa2\xb5\xa5\xe1@\x96w29$\x99\xe9>KVJh\xa5r\x9a\x9f\x0d*\x9c$\x81\xab\xb47\xf4\xc0x\xb5l\x9a\x9f\x05\xd8Xs\xf8V,,\x8d\xb9i\xceMO\xf0\xebi\xa2W\xf2\x9b\xf9\x0e}\xc3q\x91T\xba`\x81=\x1b\x0d=\xe6\xffK\"\xfaV \xf8\x8f\xd9\x03nK\xd9\x9e*=K\xfa\x84Q(\xf6\xbf\xd5\x9a T\\u\xdf\x7f\x93\xda\xb0\x02\x9a%\xd1\xbalj\xd6z6\xc6}\xa5g\x89\xca\xb4\x12:\xd7CMW\x0b\x16.\x8d\x1d\x1a\xfa~\xba\xf03:\x17*\x88\xa9\x13\xdf\x9a\xa5\x19w\x07\xf6\xe4` \xce\xf1\x7f\x86\xa6\xe7\x0b\x85O\x85\xd14\x1f\n>\x89*2\xdb\x94I\x9d\x90*\x04\"\xee*0JPV\x7f\xb8)\x08{\xca\x14\x08\xcac\xc3I\xc3\xa4\xaej\xb6\"&\xd9\x8c\x89\x9c\x9a;\x11m\xed\x8a\xd7\xee\xdf\x93h\xab\xcf\x98\xdc\xcd\"\x19\xfcT\x1ax\xf2\x05\xd6\x92\xea\x0f}\xa5\x82\x81\x87\x0f\xf4\x87|~\x13\xa2\xb6\xb8\xbc\"\xa5a\xf2s\xaeP\xa6U\xfe\x1a\x97I|\x91\x12\x83S\xed\n\xab\xae\xea\xdapE\xb1\xe4R\xaeP\x93\xe8k\xdd\xb4k\xfd\xb0I\xd2\xb9\xb1\xb2\x08\xe2\xf5)J\xaa\xb7\xcfN\x0f\x03\xbf\xd6\x1c\x147\xe8\xaeO\x1b~\x0b\xc7p.\xef!\x95\x88\xe8\x86 \x83\xef\x8c\xc4bS\xa6\x13cd\xa3YI\xe6$\xab\x938\xad&\x80Z\xf6Ut\x9d\xd4\xab\xe7\xcds8\x06/\xc9f\xe9fN0\x0ca\x15\xaf\xc9}\x16C\xcc\xd0h\xe3\x08l85gy~\x89q\xdeuF\x84\xfd\xf9\xc5\xa8\xfd\x7f\xa7A[z\xb4\x07!T\xb2B\x0fS\xe1\x08*\xca\xf4\xf3\x1a\x12\xed(=7\x80\xf2\x83\\\xaa%\xa9%\x91}\x1f_\x07CQew>\xa8\x91U\x9f\xfb^\xc3\xa4P\x89'\xc3\xd0\xb1Y^\xc3\"\xdfds\x9d\xab\x10\xed\xfb5F\x9e\x94\xd4C\x0f\xbeWmm\xd3k8\x86_na\x02\xaf\xf5\xd5\x7f\xc66\x87t1o\xb0\x86\x10\xd7\xf5\xf3{\x17m\xca\x14v\x8f\x8c\xa6\xa1\x83\xaa\x01F\x93\xcc\x01\x03$\xcd0\xdeT\xb2\x8dm\xbcU\xec\xec{c\x18\x9dF'\xf1\xc6pdr\x1d\xc4\xcf}\xcc\x0cB\xd8\xc9\xa4\xa5\x8d\x88(\x10ql\x0e\xe1]\x1fr\x12joBx\xc7\xd7\x80\xa2\x17J\xc1?\x07Q\x9d\xffT\x14\xa4|\x1eW\xc4\xc7\xa08G\xb0d\xca%=~\xbc\x97*\xfej\xfa\xe6\xccT\xb3\xe4\xd8\xce7b\x14\xa3\xbb=e\xa7\x0ch\xf7\x02\x8e\xe0\x99\xe2\xa9u\xea\xbfR\xc8_\x104\xcf\xdf\xb7\x9ek\x9a{1B+'4\x8a7S\x12%\xd9\x80-ai\x89\xb3\x85\xaa\xbd\x8b|~\xe3\xc9\x18\xb2\x8ca@\xbc\x8b\xd5\xbf\xa3\xc6h_Z\xb4-;\x11\xb5\xd0:\x8a}\x94\xc5k\xfck9e\x7f\x9fQn\xce\xf0>\xc1M\x1e\xb10\xadX\x19&p\xe9\xb3\xbfCx\x11tn;D\xc2\x96\xeb\xb8\xcc|\xef\x9d\x80+\x8f\xd4\xcf\x9a\xc6p\xfdI\x05\xf1\xfa\"Yn\xf2M%\x83\xdb\xd7+\x02<\n3\xee=X\xc5\x15\xac\xf3\x92\xbe\x893\xc83\xd2(\xfa1;\x00~\x91!\xee\xf7z\x88\xb39\xbe.\xe2\xaa\"\xf3\xfbI\xa6|\x8b\xba\x8d\n\xe6 \x8b#\xc6\xfa\x848\x83?$\xd9\x1f\xd8\xdb\xc8\x0bB\x11\\\xebh8\xf6bG\xd5%u\xeb\x8a8\x86\x91\xb9\x1bsCy\xf2\x85\xbd\n\x8cCHJ2\xa7\xbfvH\x84\xb7\xe2'\xeb\xa2\xbe\xf9+3\xf9nH2\xf7\xe2|/>h&\xd8\x06\x06\x856\x9dgQ\xe6W\xc9\x9chI\xb5:\x99\xb7]L\xf3\x98;\xa8@E\x8ev\xf5M\x81\x88\xa2\xd1@\x976\xaf\x0d\xe0[@I\xa3:\x90.\xdf\xcdK\x03d\xa02\x058M\xb48\xec\x85;\xb6vqA\x84\x97\x8c+\x1c\x91!\x041\x18\x15s\x80l\xf2\xbd{\x90Y\xb4\xce%\xf9\x871\x0e\x8d(rl\xd6@h\"3\xc1p-E\xa9\xfcj\xb8\xa6\xcdz\xc4\xd9\x9c\\\xa7f\xa6\xa4\xf1\xc7\xbe\xa9\xc3/\xcc*@\x0f6u\xe8N\x9d\xa0\x9d\xf1;\xcem\xd2\x9e\xae\x9b\x9e~\x0c\xe1]\xc0\x83\xef\x9ct\x1e\x07\xe2\xcc\xc3M\xda\xb6\x80\x97\xe7a`\xf1\xbd\xa43\xfc\xa9\x9f\x8aM\xf9~l\x98/q\x9c\xc8&\x8c\xde\x18\xa0J\x96\xbb\xe0cP\xfb{\xc8\xdeb\x18\xec&goE\xca\x04M\x8b\x06l\xceoC\xfa\x99\xbe\xa7\xe6\x10~\x8ec\x82#\xf8\xa9\xbf6\xfd\x13\x9c\x0d\xee\x9d\n\xe8>\xc3\xc1\x02#\xa17\xf6\xab\xec\x7foHy\xf3\xb6|\x99\x97\xeb\xc0\x7f\x17\x84\xf0\xeew\xed>Z?m\xf7\xac\xcama#\xb20\xb9\x97\x9e\x80ng\xbbMV\x06)/\xdbo\x14K\xa7\x1b\xc5\\\x11\x02\xcd\xb5\x12'A\x15\xa4\xbc\xec$TB+\x99!\x12\xffXp\xe6\x03\x86{\x15\xdf\x02J\x92\xb6:\x84\xa9\x87<\x9e\x87\xf7\x85~\xc9\x82\xd3Rv\xf1\xc7\xfc\xbaa\x17=6\xb0\xca;\x0bD\x9c\xb7\x81f\x1cj75\xcc\x03N1n\xbb\xf9\xfd\x8c\xc7\xd94sj9\xc5fDi\x97,\xae\x14\x91\n*\xc6\x8dL\x85*\xcd@6\xa59*\xdb\xd0\x0d_!c\xe9\xe5\x01\xfc \xee#\xcf\xe6\xa7\xec&\x86\xce\xb2\x9a\xaaUL>\x93;io\xba\xb2\xa1j\xbawF\xc7'\xda\xdb;\x0b(1\x14\x8dz\xbfxM\xcfn3o9zL\xcf\x98\x87\xc7\x83_\xfc\xe9\xdfo\xcfv\x83\xdb\x07K\xd5\xcf\xe3)\x0bs\x81\x862> \x9e\x06T\xb6\xd8T+\xbf\x9c\xee\x9f\xd9}6\x0d*`?\xdd\xe6f~\x16]\x89\xfd\x85\xbcq\xf3sJ\xac\x97\xa1b\xc2\xed\xaf\x86\x8fo\xe0\xc4g\xc3\xef\xf3\xa5\x0d\x9b\xfd\xb3\xb2\x13\xc9\xfd\x17\x99\x1c\xe6\xd6\x0b\xc1[\xda\x02\x81\xd0\xa5O\xa5\x97j9\xe8\xccd\xba\xdb\xd4\xf7\xd0\xb5\xc6\xb2m\xac;\xb9\x1c\xb1\x85\xcd\xae\xef\xc2\xe2\xcb\xd6 ]\xca\x95<\xb6\x19\x93l\x8b\xdfPj\xbe\xa9-\xdf\xd0\x13\xe6\x9d\xcf\x1dLgy\x8a\xb4\xf4\x9d_\xb6\x1f\xd8F\x9b\xe0\xbe[\xe5\x15z\x1e\x96\xf8\xd7\xf0\x17\xcc\x85\x8e\x92s\x14T\x1c\xfap\xc9\xac\xcb\xf1E\x84O\xf3\xe97H\x9e\x138\x86\x9cb\xf4\xe4\x01\xe6\xd4\xf0\x13\xd8\x85\x18\x9d\xf0\x82\xe9F\xf5\x00\x84c\xd8\xb4\\\x99`b\xc8\xbaz\xeb\xa7!hr\xb2\xdf\xfa\xe8\x9bk\xa7\x15\xe3x\x8a!=8H\x8e\xc2\x85\x0b\xc8\xdb\xc7z)R\xb2XX\x8c.j\xe5\x03\xa8E\x97\xb7}oT\xf3 T\x98\xf4K\xfc`;\x0e\xfd\xad\x8cma\xf4/\x8a!1\xc3\xcd\xa4\x83\x9b\xab\xba.\x06p\x87\x19\xf4\n\xdcL\xe4_C\xf8\x96\xe27\"\xb0\xbb\xad\xf6\xcc\x82\x99]\xac\x9caz\x17>\xc9\xae\x99+\x96\xf6\x89\xf0\x1b\x17&\xc6\xf2\xbfy\xf80E\xdd\xc4n\x98e\x8di&i\xa2\xe6nU\x03\x82\x7flH\xf9\x95V\xc86{ &\xb3\x8e\xbd\x8ep|\x08\x03\xf6\x17\x87\xc0\xce>w{\xbbw\x0f\xbc\x8b'?\xbd\x7f\xf5<_\x17yF\xb2\xda\xcf4\xbe\xa7:\xcb\xea\xbc\\\xbf\x88\xeb\xf8_\x12\x00~\xc64\xc1=\x0b\x16F\xa5\xe8\xd8\x11<\xf8\x87D\x13\xfa\xcbiC\x89-a\x1ee\xa7\xe3I\x7f,\xe6o]\xb6\xab\x1ei\x1d\xfc\x05\xfe\x93\x03\x0d\xa8\xbf\xee\x9c\xc5\xe8\xcb\xf9\xf9\x90\x12P\xc4`\xd2\x8a\xc8B-\xf9\xed\xe3q\x81r\xff\x05\x08\x8e\xb9bC\xa9\xcdu\x10*QU\xdf\xa4\x03\x95P/K\xd14\x1d\xf6\xae\xe9\xabr\x86%\x18\x8c_g\x1b!8moZp\x16\x13HP?_%\xeb\x82\"\xd4\xe0\x17|J\x13\xd8\xd0ol\x990X6\xa0 \xec\xec\x1b\xab\x99$\xcb!\xfa\x9f\x0b\xd2\xaf\x0bL\xf2\x1f\xc9\x98\x99\x19\xb06K5\xcc\x88l\xfa\x91\x0e\xbcM\xc6mF=n\xdb\xa5\x04+\xd2\x99\xb6\x8b\xe2\xcd )\xde*\x86\x8d|Op\xc3\xb1\\me\xa4\xb4\x0f\nq\xca\xacY!\xdb\\$\xc5\x8c\xa9\xbc}?\xf3\x86\x0fAQ\xf8n\x19\xb5\x15E\xc1-\xe9\x98r\x95\xf7\xe3\xe8\xce\xcew\xa7\ni\xb7\x0f\xc5\xb6\xe3\x07\xf6{\x82f\xb4\xf0\xd0IP\xcd\xc6\x1dJ\xee;e\xf4\xa1\xd0\xdf\x1e\xad'\xb7}U\x0b]\xdf\xa9\xc7S(K\xe6\x8c\x12\x9e\x9a\xbf\xec\x9ad\x11\x14\xbb\xa6g\xae\xdd\x81\xeat!\xc1\xb0\xff\xa8\xe3\xe5\xac\xdf`[t\xe2\xfd\x0f\x14\xfcM\xed\xfd\x9c'\x99\xefi\x9c\x13\x95w\xd0E\xd8_]#\x9b\x0cid\xe3F#\xdb\xd5\xb9\xb2[\x90\x17I\x85\\!\x99S\xfc\x88g5;\x01\xf3P\x1f\xc3\xdeb\xb8i8_\xb5VF\xf5X/\xb0Krcc\x04\x9cTl\x16M,3\xfd\xb42D\xcc\xafk\x88\x1e\x00W\xeb\xda\xe7(\n\x87\x13\xe6\xd6\xb2Ku\xe2(\x1c\x8e\xe1h8\x8f\xa0\x7f\xe6\x88\xc2\xa2\\2\xa6\x92\xb15M\xb6\xdc\xf1{lc\xca;/7Qhrv\xc1\x81\xa4\xf1\x05I\xbb\xe3`.\xf2_e4\xd1\xe0h\xd6q]&\x9f\xbe2X\xc6&r\xe1M\xb2,2 \x1c\xd3\x83\x84\xb9\xfbQ\x06\xef)\x05U\xcdX=\x0c#2a\xaa\xce\x10\x7f\xe9\xc70\xe0\x8e\x8a``\x8a\xb4#\x9b\xa7\xbe\x90`\x13\xee\x1c\xdb\x8ccB\xfb73\x9e[\xc0\x15\x1c`\x0b\xcaBkn\x02\xc0(\xed\xb3-Q\xc43\xf2\x82\xa4\xc9:\xa9)\x93\xee4\xfd\x94O_\x99\xf8o;o\x0f\x83\x15\x18RX\x0d\xcc\xbeH\x8a\xd1\x93\x9f\xfd\xcbM\xfe3\xc6\x0eu\x9dh\xde\x0d H\xeb\xa1AE\xc7\x1d\x92\xbe}\xc2\x1c\x92\x1e\xe9\x1d\x92\x985\xf9#]~\xff\xd4i%\x05\xec&\x0f\x8e\x7f?=\xfb\xffv\xbe\xb9\xf7\x07?\xf8\xe3n\xf8\xf4\xc8\x93\xf7\x19\xdcp\xb6?\x15\x8d&~L\xa7\x0f\xfe>\x8d\xef\xffs\xef\xfe\x93\x8f\xf7\xa3\xf3\xff:\xdb\xfd\xe6A\x12\xd5\xa4\xaau,\xd7\xb6~\x01O\x0e\xf7\xb7\xb7\xd1?\xd8\xfe\xd3\xc3/0\xefo\xbd\xfa\xb7\xd4\x8a\xca\x00\xa9f\x95\xa6\xdd5\xb5\xec[ a\xcc\x9a\xc1\x84(\x96\x08\x95\x9a|(\xd8\xe6`\"\x14\xb3\xdb\xef\xa2\xef=\x8bw\xa3\x86\xcbbtR\x8c\x84\xc2\x9d\x18\xdc{\xe7\xed1\x16b\x8c\x06\xdfeLx \x80\x89F[q\xeb\xd7\xd4\x10n\xe4\n\xb3-\xdc\xbb\x07;;\x1d\xfd\xea\\D\xc8\xd2\x7f\xb8\xee\xc7\xc6\x8aC\x98z3a\xf6\xac:\xfd\xde\x9c\xb2\xf0\x00<\xb6\xcfP*)\xe5\xa6l\xd1\xbd\\]H\xe3\xb4E\xdb8\xad3\xf42P\x14\xd8W\xf4\x1f\x16\xd3\xa6s}\xd5\xc0\x0bG\xd5\xfc\x94a\x7f\x8e\xc1_il4\x06X\x13\x19\xe0&\x83$\x1bN\xde\"8\x98\xf9t(\xb6$p\xa4^O\xb3\x01{\x0f\xb4\x07\xb0\x9d\xd3R\xa1\xcb\xf3\xd6\x7f\xfel\xbb\x10\x03\x8e\xfd9zN\x0c\x9b\x9b\xb0!X\x9bCy?.\x92\xffEx4\xcc8\x00\x0f\x17\x93\xdf3\xf2\xe0\x98\xfeB8\x19\xc8\xeb\xf0$\x08\xc1c(\xd1\xab+.\xcf;\xb5\xd9\x9dp\xaf\xb6\x08\xc0\xa6\xd6\x1e\x9e\x1d\xa8>\x18\xcc/^\x8c\xde\xce\xf2\x80\x8c\x01\x1aW\xc9L\x8c\x86\x85\xccp\xfd\x1e\x14\xae \xc1@\xc1\xf6[\xcfnAuYT\xc4Uu\x9d\x97\x03a\xcatE\xc8\xb3\x8a\x7f,\x0buA\xd9\xa3\xca\x01z\xa2\xc8\xb5\x8a\x9e\xa9w\x8ep\x04\xde\x0f\x14\xfcN\xf1\xbf\xbc\xe5\x81*-R\xae>R\xa1\xe0r\xf9\xb9\x87a\xdf\xe9\x06\x8eVq\xf5\xf6:\x13'`{x\xb9-_\xb2d\xb3 \xcf)Bi\xfa\xdeS\xa8\xe1{8\xf8\xf6\xd1S\xd8\xdd\xad\x03 ,\xda&\xf3\xca\xa1t\xff{\xd8\x7fD\xb9\xb1=\xc5\xf2\xb1\xe5\x17\xd4q\x0c2\xab\xef:>:\xbeR\xb3\x8ebJ:?\xe4l\xca\xb6\xb3V\x91\x18\x8e\x00s\xce\xd5Q\x91\xc6I\xc6>\xa7\x9c\x1a\x87\xdd\xac$qM\xfcl\x93b|y\xca\x0b\x96l\xda%|/\x1d\xb8\xe8\xdc\xcb@UV\x91iy\x86\xf8\x98\xd1?\xd8\xef\xee\x92sS\xe9f\xcd1)6)\x97\xa43\xfe,\xec;\x92\xa2\xba\xb6IC\xd9\xe1\xc3\xd9\x0d\x99T\x7f \x9d\x9b\xd6\x03\x81\xd6\xed\xc6\x0e\x96\xeb\xa8\xb3\xa5E*gVDk\xfa%r\x9cS:\x1d\x83\xe8\xe5\xe7\xedE\xf8\xfc\x99\x8a(i\x9a_\xbf\x13\x18\x8c\x0fw\xcah\x16\xa7\xa9\xdfEo\xba7\x18\x11 S\x0cv\xbb\xb37b\xc3\x0fy\x809LK&\xcd\xecBLp\x87D\xbb\xfa\xbd\xa0\xcd}\xef\xdf\x8c\xcd)A'\xd0\x16\x9aS\xdc@m\xa7\xae\x95^#\xc7\xe0g}\xc1:\x0b!\xd1*\xc0\x18\x8c \xbe>\x062M\x10\x9f\x15\xad\xb6\x84\x02}\xc5k\xfc\xff\xec\xbdk\x97\x1c\xc7\x95 \xf6]\xbf\"P3KU\x0d\n\x8d\xee\x06@\x11MAt\xa3\xbb\x014\xd4\xe8n\xf6\x03 \x00a\xa0\xac\xcc\xa8\xaaDge&\xf2Q\xdd\x8d\x11\xe6\x90#\x8a\xc2\x83;\xb3\xde\x91\xa8\x91=cy\xd6$H\x00\xb3^\xdb\xeb\xb5\xd7\xf6\x8e\xf7\x1c>\xd6>Gs\xa8\x99\xbf\x80?\xb0\xfe >\x117\"2\xf3\xde\xc8\xac\x02 R\x9c\x1d\xd59\x12\x1by\xe3\x1d7\xee+\xee\xbdqFcp[\xfcSc\xeeB\x81M\xe2o(X%\xf9B\x8e\x97\xbe\x9cjS\xf7\xf8a\xda\x0e\xada4\xd6\xe1j\xd2\x1b^\xf7\xebc6ms\xc2#v\xf4\x88\x01\xe8t1bT\xde.\x01\xbe\x90\xa6\xfe \x9cDs\xd4\x18\xca\xf3\xcb\xa6\x0f\x13\xd2H\n\x88\x9d]\x0foX\x06\xc6\xd1\xc0<.$\x95F'A\xfb\x8b\x93\xaa7\xa8_\xc9\xb1X\xce.|Tf\x17f-\x946\xc0<e\xbe\x9e\x9e5_O\x7f\xc7|\x9d\x9b\x9f\x97q\xc5G\xf5\xc0\xe4\xa0\xd8\x82\x80\xb2\xb9\xf9W40\x12\xd8\x0e_\xe7gO\x96>\xcf\x9d\x9eg\xb2\xd9\xef\xb1\x97o\xb0\xa3\xe2\xcb\xfc+\xecG\xec\xe5\x13\xec%f\xea\x9c:5\x7f\xfae\xd3\xff\xa9\xef\x9c8y\xb2hb~\xfe\xa4nbn\xbe\xdc\x06\xb4\xca^b/\x9f\xb07\xddND\x0bs]\xb9\xb0/\x9f:u\xe2e)S\xcc\xcd\xce\xcb\"\x1d\xf6\xdd\xef\xb2\xb9Y\xf6#\xa6\xbe\xa0\xb5\x97; C89k\x86\xf0\n\x19\xc2\xdc<\x19C\xf3\xd0:\x0d\xac\xc2\xce\xd5\xddh\x14;ns\x14n\xf5\xcd6\x8aaQ\xefV\xdd\xc5Cd\xbdr\xa0\xe2g\x9cD\xf1\x02kE\xd5\x0c{\x96fI\xeef\x91zH\xbb\xf4\xa1\xe8\xab\x16\"4\x85b|\xdfb_VaU3/\x16C \x1bTS=\xfe\xcf\xe6g\x8f\x0f\x8a\x16\xca\xf7\xc4\xd5\xc50\x97\xb2\xad\xadsK'N\xbf\xf22J\x1f\xd3\x97i\x89\xe1m \x8a\xbd[\xe7\x96\xe6\xbes\xe2\x95ib\x8c\x88\x90\x19uY\xeb\xa8-\xf3\x04\xa5\x13jh\xcf\xd1\xcd\xc4+\xe6j'f\x1e-\xf5W\x8b\xc0a\x00f\x95\x9eo_\xf5\x0e\x02E(6P\xbe\xbdF\xb7/l\x9f\x9e\xc3a4\xbe\xfa>\x8f\xbe\x9b0W\xb5\xbd\x93n\xfdY\xe9\x04H\xef\xc8P\xbf{\x02O\xb9H\xc7\xac6/;\x9b,;\x99<\x13\x19\xf9\xf8\x1a\xe33\x03\x9e\xed\xf8#\xde\xee@\xf5\xd2\xbf\x17T\xbc\xfe\x11x\x19\xcf\xa2!Vt\xa6\xe2\xbb\xcc\xf62\x03\xe7@\xca\x9f0\xb0\x05\xf9\x97\xfcc\x9aY2\xb5\xf0A\x97\xb9\xf5t;oC\n\x97\\\x12h\xb52G,~f\xba\x02/\xf6\x0fhp\xf1\xef\xa9\xea\xfb\xd2\x80\xa0\x0b\x1e\xf1\x85\"\xa03\xe3\xe8\xd3\xd1\x01\xf3\x91\xfag\xd6\xe92\xc7\xcc\xb4\x81\x07\xa5\xb2\xe9z&#\xad\"\xe94\x13ef\xb2\xca\xbc\x083E\xbaDSm\xc9\xd0\x02`bA\xc5\x18\x14\x1c=\xda|\xe7);\xbe\x1e\xdcP,.\xb81U\x87\xba\xc8\xb4\xe9\xfeX\xad~\xa7\x7fc\xf5\xe8W4\xf1\x8d\xd4X\x96\xcaj\\\xf6\xb4\xc67M\xd2\x8c\xba\xe4s\xb5{\xde/v\x88\xc5\xd3n\x90\xdc\x9c\xfeL\x1a%Y\xbb\xd3e\xb1\xf9K\x06\xea\x95\x9e\x88\x14{\xf7=\xd8\xc3c\xc7\xeawM\x0e\x04v\x8c\xc5\xd3l\x98\xc1\x8e/\xd8\x99\x8c\xed\xbb\x1e\xdc\xe8\xb2#N\x9b_wotY&\xff?\x9c\x8c\xdbZx\xd14\xa8\x90yi\xfa\xfd\xbb\xc5\xb1\xab\xc0\xee\x96\x1c\xa6\x8c\x7fR\xde,kHu\x9c\x15Y\x17\xcfT\x1e\xce\xbaki0\xadm\xf0H\x1bH\xab\x95\xa8\x8a\xef:\xffV\xe9\xbbA\x0e\xe9\xcc\xa9;\xa9(\xfb3n\x14\xcb\xb7\xf8j\xc0\x92_I\xf1\xa8\xa0\x0c\xea!d[\x8f\xd7go<\xaf\x04\xa49%=(\xc0\x0e\xe8u\xb3\x8d}\x9e8=ka\x9f\x13/\x98\xd5\xe2Fj`H\xad\xbbK\x19o\xd8\x9e?1[1\xb4_L\xa3pS\x1cw\xfd\xa0\x9b3S\xfc\x13\xacN<^\n\xa2P>*=s\xd3\xfc\xb3*\xee\xe5\xd6%p#\xfe[G\xc8s\xa9+\xd4\x11\xa2\\&O\xa9;\xdc\xf9\x8c\xf8o\xf5@\xd9\x14\xaa\xc0*\xa9Kw\x03\xd0K\xean5\xb5\xd5\x9e.\xa7d\x02\xa2w\x0b\x17P\xd4\x1f\x8f\xab\xfcO\xc3i\xe4Mt\x97\x85\xb0q\xa6\x8cM\x8bs\x95\x93JR\xe3\xa7R ~\xd3\xd2\xcf\x91\xb9\"\xbc\xeb\x8cN|.\x1f\x98?2\xdb\xe9\xaa\x82V--a\xaf\xb1Dp\xc2\xd9.\xe3\xf2\xeeDH[l\x81\xc5\xf2\xa3\xcc\xb8\xdcR\x179\x00\xa2\xab4V\x99\x0d\xed\xe8XAE\x8b\xa5\x95\"=x\xb0{\x9e\xee7\x8a\xcd\xce\xb93\xa5\xe6\xe4\x1d\x8a:\n\x16\x9b\x9dlF\x9d\xc7\xe7jJ\x8bl\xe2T\xd6\xb7,\xa5C\xd3\xacT\xa3\x05\x8eO\xd1\x93D\xd4\x10D\x94.\xc3\x0d\x89\xad\xaa\x0c\xa1S?\x06ql\xca\x1d\xdaw@\x9a@\xe4\x11cg\x04\xf75\x88\xd81Od\x01\xb8\xc3\xb2a\x12\xed\x8b-#\xcai\xbb\xb5#\x1a0\xce\xc1\xac\xef\xf8\x01\xf7Z]\xd6\xdaY\xd9\xde\xb9\xb9\xb1\xb9\xb2\xb5\xb8\xb3\xba\xb1~\xf3\xdc\xe2\xea\xda\xcarK\xa2T\xd8e|\x82\x18\x86\x16G\xac8E\x92\xba\xcd\xad\xae]i\xc5\xab[\x88\xb7:\x0f\xecf^\xd9\xaa<\xef\xb4\xcd\xb0\x90\x18j\xeb&\xcd+h\x1e\x81g?\x8c\xe2\x1f\xca\x8bL\x9ed\x87\xccOY\x18eL\xa8\xf9Q\xbfX\xe2\x94\xa9\xa8J\xe6\x87l\xeb\xdc\xd2\xb1\x97O\xcf\xce\x8b\x05/\xd6zc\xf3\xe6\xea\xfa\xe5\xc5\xb5\xd5\xe6\xf5\xd6\xcbR%V\x95\x7fE\xca\x92\x8fT)\x8eU)m\xe6l\x03=`\x90WW2\xd0\xac\xdd:\xde\xb2\xd8>a\x17\xc8\xe7!;\xc3,\x8f\x16\x8cKv>\x0b\xb31!b\x146h\x80\x1d\xd6\x84\xe3J\xd3\xe2\xa1|\x1a\xae\x8e:\nb\xf8\xaa\xf5\xcaWl\xf9@\xda\x16\x877\x14\x95-\x11a\x08\xde.\xc7\xb3]\x1f\xdc`\xaf\xc9)\xf4\xc18\xd6\x9e\xed\xb2\xa1N\xc5z\\f\xe7\x1b\x8a\xee\xc7\xec\x18\xe4\xe2o\x8f\x98\xa1\xbc\x95\x00^\xd9\xf8aA\xb8G\x82R\x0f\x8f\x1e\xc5\xf7\xc8^\xad\x89_\xe2\xfa1@\xf4AG.\x9e\xa7\xad\xee\xd6\n\x0d\xae\x8aL\xe3\xbf\xb4\xf6\x95\xa5\xd2A\xa7\xf9H\xac\x1c\xc4\xdc\xcd\xb8\xc7\x9c\x90\xe5a\xea\x0f\x04\xba\xf7\x9c\x94\x1f\x9b\x9be\xea9d\xa6\x08\xf3\xc8\xd9\xf3\xc3\x01\xcb\x86\\6\x96\xf0>Ox\xe8r\x0f\nH\x80\xf4\xe9c<\xe0\xf2\xa8\xef\xfb\xd9P~\xbe\xc3\x93\xe8\x98h\xd6\x03\x81\xb5z\x8a6\x17w.\xdc\\][[9\xbf\xb8vsqkk\xf1\xea\xcd\xd5\xf5\xe5\x957\xd4\x99\x02\xed\x8e5\xbd\xe5W\x9d\xb2\xdc9\xb1\xa0\x7f\xfc\xc7\x83iu\x1b\xa6\x96p\xc8\xbew\x86\x8d'\xdd\xcb\xc8\x85\xae\xf2H\xf1e\xc0\xbeg6q\x021\x1fr\x19\xc6\xe1\xf7}\xbd&\xec\xd2\xee\xf6\x0e[\xdf\xd8a=\xce\x06\xd2W7a\xd9\xd0 a\xc5\xa5\xc1V\xd0'\xb5\xb8\xa9\xa0Jf\xc9\xab\x0bzyqmw\xe5\xe6\xc6\xee\xce\xcd\x8ds7\xcfn\xec\xae/oO\xbf\x96\xf2\xde \xd8\x92\xb4\xdc\xa7\xd7\xc5\xf4n\xc0\xedV\xd8e^\x97\x0d\x04\x99\xeb|\xfd<\x8b\xd5\xd1R\xfd\xb3\x08\xccE \xc3@\xb9\xc5\x1c9\xc3\x06E\xaa\x83?n\x15\xf8\xe2\xcc\xe4!\xe4\x9a\xdct\xb2a\xe1)8\x90\xa7\xbb\x113\xf0\xaa\xe5\xdf\x9cU\xab]1\xbaZ\x1e\x032Y\xc3\xa8l\x02s\x7fz\x81\xd9&\x16\x13\x07\xe1\xe6\xa5\x91\x7f\xb3\x94\xdf\xce\x05\xe5a\xa3<\xcd\xc4qq\xc2\xe2\x18l\xaf\xbc\xbe\xbb\xb2\xbe\xb4rs}c\xe7\xe6\xe2:\x10\x14\x1c\xe12-\xbb5\x9e>\xf2F\x9f\xef3\x1d\xd6\xa4\x0e\xb9\xf2\x00\xebB>Msk\x9a\xb3\xef\xb2\xf4U\x96\x1f=\xdaa\xfe\xf5\\\x86`\xcau\xba\x9e\x0bN\x05\xf7\xf7\x12R\x16\x8d\xac\xda\x8bO\x054\xbfqC\xe2 \x1bRw\x0bU\xbd\xf6\xa2^\xf4\xd3IVJ\x96rB\xa6\xba\xa9\x10&\xb5%\x1bg/\xae,\xed\xb4\x00k\xc5z\xbcJFy$\xbf\xce\xc5\x01\x9a\xb6\xdf\xafD\xa2\xab\x1f\x9eq\xbe-_\xd9\x81\x826\xe5xEa:b\x87\xa9\x86-\x0cr\x8aa)\x9f(9\x92\x82\xc4\x1d\x07\x12\xa7>\x177\x81\x8dc\xfdv\xfdX\xe5\xa9K3'Q\x1c\xbeu\xbc\xf5\xed/6\xde\xb2\x1a\xc7\xa9\x1a\xc7\xa5\x02 X\xadm\xb9\xa5\x027\xedr\x8b\xc2t\xb9\xe3\x84\xa7\xe2X\xb5U\x88\\/\xe0\x025~(F\xf5C\xe6\x84\x1e\xfb\xa1\x18\xcd\x0fK(\xd4\xa9n\xcd\xb9\xad\x8dK7\xb7V^\xdf]\xddZ\x994W#/\x98\xa9V\xd4c\xf3\xb5P+\xcd\x02\x94o\xa1\xb5Eq\xca\x99\xcb\xd2\xd3O\xdd\xf1\xbc\x1fv\xd9\x0f\xd5\xc8\xd4\"\x88\x115,\x02\xc8\x1b_\xfd*83C'\xdd\xd5\xc9n\xdaz%\xbeyK\xb1\xb4\xb8.H\xdd\xd2\xc6\xfa\xce\xe2\xea\xfa\xcd\xdd\xf5\xe5\x95s\xab\xeb\x13\x96\xc6r%Q6\xc5\xa8e\xa87cB\xa0\xb4<\xe3\x85:\xd8\x98_\x83)kxD+\xd8E 1\x1e_\xd2\x98\x94\x1d\x05\x15I\xfd\xb3y\x0f\x96\x9cP.4OdT\xb2\xa3\x16\xb7$\xe48\x99\x14f=\x9e\xfa \xf7\xa4u\xcfB\x03\xd5\xba..\x97W\xb2I\xe6\xab\xc1\xad\xb2\xe5\xc2|,\x0c\x0fM+\xed\x83W\x99\xa3\xdc\xac\xa2\xe7\x9a\xb8\x98be\xce\x8e\x9c\xa9\x10\xf33\xe6E\x1c\xf0\x91\x1f\xf8if\x99\xfd\xee\xfa\xd6\xca\xf6\xc6\xda\xe5\xc5\xb3k+\xd3\xce\x7f\n\xfaZ\x8fQ\x81\x10\x07\xdb\x16\xff}\xfdk2\xd0\xea\x1f\x18j\x81\\O\xbc\xa3\xab\xc9}.~wo\xd0c\xa3\x7fb\xaa\xd2\xeb\xbdq\xc9\xe4\x9c\x03\x99\xf9\xe2K\xec\x9a\x98\xc7\xd4\xfb&\xd9\xc3\xd4\xfb\xd6(\xd7yZ\xae\xc3;f\xf7\x8b\x93B\xd4\xf3Iq/J\xb8\xd6\xdd\x87\x1d\xd6oW\xe4\xeb\xb0\xd3\xc5\x02\xb7\xd0\x03~\xf4#\xa1\x11\xd0F\x1aL\x1e\x89L\x19\xf6\xa3\x1f\xd5\xe5\x01\xac\x84t(\xd7\xfc\xc2\xab1\x12\x82y\xd2\xe6\xd7\xa3\x1b\xd2\xb79\xd4\xc6\x9dI1\x0b\xcd\xee\x81\x926\x94\xfdn\xf1\x1a\xd7]\x81\x88\x1f\xecLm0\x99\xf9K:\xed\xca\xf7\x92\xcf\x1enF~\x98I\x0f\xfa\xc0Du\x17\xfc\xee\x0cs\xcdW\xd8\xdb3\xaco\xbel\xc9p\xbd\x04\xc7\xe7\xe2y\xe9\x0b2u\x8bb\x91\xd4A\xebM\xbe>\xc5V\xadaR\xd6\x8c\x8a\x85\x12\x13\x1c;\x81\xef9\x99\xf4\xe9\x8aK\x1f\x84\xd6\xe5}K\x15\x9b\xc6\xb3-l\xcf\xbfR\xea\xbd\xd6w\xdb\xa6h\x1dI\x94\xb72\x9f\xb9\x99\x81{\xac^\x9e\x9d\xc3\x98\xab5Y\x0de@U\xe6\x0b\xa9#\xe1.\xf7\xc7<\xe92\xf3\x96\x84L)\"x\xe2\x11|\xcc4*!\x1c\xf9BQ\x0b_(\xad\x0cM)SN'Sr\ni\xcf\xcfw*\x8ew\x96<25\xbe\x93\xf4\x909\xfd\x8c'k\x91\xe3M\x13a \xafk\x93(\xcaVC\x08\xc4>C?\xe9w\xc9\xd1\xf7\x19?\xf4\xb3\x8d\xc5<\x1bB\xb2\x98<\x1b.\xca\xde\xd2\x197\n\xfb\xfe O\xb8\x80Zj\xc6 7)\xdc\x16e*(is\xee\xf9\xa1\xd7\x86\xcb\x0f\xe94\xdeT\x0d\xf2\x1a\x9dan\xb5\x16%O\x94\xa5\xa6\x99\x93\xf1\xcd \x1f\xf8\xa15\x0eD\xfcD?u0&W_\x12\x87t\x81Ez\xb3\xeay\xb7\x03\xcb\xd2\x185\x96\xf2\x80\xbbY$Z\xb4\xbf\x0fY\x93\x95\x16r\xdd\xd4\x0ft?q\xe2E\xdd\xbf\xfdQ\xae\x89\xee!U\xdaa\xdd\x05\x0c(v\xb5\x8a\xf0\x91B\xf8\x13\xa7O\xe2\x9c\x19>\xbc<\xd4\x9e?A\xb2M:\nt\xe2\xf4)\x0c\xca\x0dH\xe6\xd90\xb0&\xb7c`C(\xdbc\xd3\xed{&\xa3J(iWQW6\xbc#\x89\xea&$\xe80\x91D*\x05@\x06\xd1\xdf\xfczX\x93K\xa2L$x9\xff\xa7M6\nj}\xaf\xa7\xcfzY\x93\xf1\xb2Y(s5\x89\xb5\x18\xdb\n\x9d\xacL;\x0c\nQ|/\x1e\x0d\xd9\xd6\xa7\x85\x16\xca\xa5\xcdR\x14\x12\xdc\xd5r\xfaMz5?\xddX\xdc>\xd1\x91 \xcd&>\xb2\xc1\x16\xd8\xf5\x96%\xd3b\xcb\x12\xa6*\xd4\x82\xbc\xdd\x11r\xc8j\xd8\xben\xd2E\xa4]v=\xbbA\xd2\xc1\xc0F\x04\xec5\xe6\xcb\x07\x99\x13\x94\n\xb3![\x99\xfd\xdc\xebdq\xb5\xae5:u\x9c\xcd\xcf\xd2F0\xc5\"8\x0b,\x98\xc9\xa2\x8b\xdb\xe8=gHS+NB#\"\xf4\xeb\x1c\x8d4U\x98\x1a\x0b\xfci\xb0\xc0\x81\xb7[j\xb1 7O ~eX \xc3\x98-X\x907aA\xca^c\xd1\xf3b\x81\x0d\xcb\xd5\x96\xa5So\x19\xfb\xa6\x89F]\xed\n-\xa5#\xca+$\x84d^r\x14d\x8e<\x00\x90Kq\xf5;\xe8+$\x1b\x9e\xc3\x11\x16\x81\x8a\x87\x98\xb7\xf2\x14\xf7\xeb!\xa7\xfa\xaf2\xa9\x97\xfeT:'kT\xca\xc9\xdae\xc1\xcc\xf6\x85\x8d+7\x17ww.\xdc\xdc\xdc\xd8\xdc\xdd\x9c\x90oY\xfb\x95e3\xb1-\x9f\x9f\x9e\xd1L\xca\xb3v+\x1dF\xfbe\x84\x17\xa8Q\xda;\xfbx\xc4P6\xb6V\xaf\xad<\xefH(B'&Op?\x89F\x17\xb7;BW&\xa5\x80\x90\x0c\xc4\x80\x8b\x1c\xc1-x8CV\xbe\xe4\xc4\x1d\x1c\xf8n\xd4%\x1ef\xc9\xe16\xbf\xdd\x9e6\xe3\xba\x96\x0dP\xbaN\xdee8\xb0U\xff\xe4,\xaf\xcf\xd6\xe46H$t\xae\x06\nIe\x159i\xc1 \x17T*\x939\xcfjl\x0c\x95T\xab2\xc7H\xe9\xa5\x1d\xbf#W,\x92[\x1c\xda\xcdG\x85\xa9\xac\x94\xdf\xd4\x9a\x97\x87\x95\xc2}\x8aq\xca\x93.\x86\xa9\xb9R\xebFC\xfca`\xaf\xab\x19\x96u\x9aLm|\xdb\xccET\x0e\xbbL\xd5ot\x9f.xe^?*H3\xb7P\xce\xa6\n\x8f\x93\xf5\xb2\xc8)?\xdaS\xf7Ls\xa7S\x1e\x96\xda\xba\x1b]\x98j[\x7f\x98\x98\x11B\x066\xc3y,\xa1\xb7\x10\xad\xa6?\x8a77\xc4\x9f\xf3/\xe6D\x86\x92Q\xdb\xcfaX\x97,\xd9\xa9\xf1u2\xe7\x10\xde\xeb!o\xfd\n\xaa\x17u \xcfH\x95\x14$z]$\xd6T\x96\xc6\x81\x15\x96\x88\xd7\xb9\xd1-\xe7\x05\xac[\xaa\xb5\x8d\xf3\x1b\xbb;/f\x81,\xc4hf\xdf\xcf\x86\x97\xf2\x0c\xaeG\xa6\xc8\xa8h\xc9\xe4\xd5\xf8\x8c+\x9f\x81\xc0\xb2\xda\x10^\x0b\x9a\xd5\x98N,\xb8\x96L^\xc0\xa5\x8d\xf5s\xab\xe7w\xb7V$/z\xde\x85l\x1a \x18\x16,\xdcG\x8d\xea\xb7+\xc0t\xc1\xf6\xb8\x04\x83\x94s\xf2\xd3E\xb3x\x90\xd4\xad\xfaO\xaf`\xa9\xe7\xa2d\x0bLY\xe0\xbe\xa4\xd2\x0f\x94\x98\xee\xd9\xc3ug\xc4S\\q'2}H\x90`\xd5a\xa9\x9a\xe5\xb8i\xdbS\xde\x0e\xdb'\x89t\x15)\x08\x95\xa1 o\xc3),D9J\xb4z\xbe8\xe2\xafDV\x1a\xab\x04B\xf5\xc7\x8a\x9a\x05\xcb\x967\xcb\xe2\x01\x19\x82\xec\x90Z\xe5\xe8\x08enr\x1f\x8a\xbc#\xd9\xa9\x83p\xa6v/'\xf7\\\xd3\xf1tb\x0b\xd2\xa2l\x0f \xb4\x8d\xec\xe4\x80\xecT\xfb\xcaQh\xe4\xa05?\xcd\x88\x90\xc5\xca\x96\x8b\xe7\x16\xb4\x18\x12\xb6\xa2\xa9\x84-fD\xaa:\x81\x8b)\x9c\xae\x17\xbaXIYt\xac\xe2c\xb9T.\xc9T\xd2\x95/%\x86\xe0\x1b\x9b\xa7\xc3vn#\xb9]\x9c\x17\x91\x92\x12\xeb\xe1o$\xa7S#@H\x11\x80\xce\xcb\x8d\xc24\n\xf8\xcc\xbe\x93\x84\xed\xd6\x95\xc5\xad\xf5\xd5\xf5\xf3\x0b\xcc>2?e\x1e\x8f\x13\xee:\xe00\xeb\xb1}?\x08X\x8f\xeb0\x1e\xed\x91\x19\xf2\x83\x8c\x8d\x9c[Q\xc2\xc6\\g\x9aB7\xe2;\xd3\x04\xbb\x11\xe7\x99\xce`,I\x98?\xa1W\x1b\x8f\xc1\xbf\xca\x9b\x039PF\xa9\xba(\xd7\x95T\xd0\xbc\x97^b\xed6\xbcp\xa1$\xe3(\xe6i\xab\xd3\x99\xd9\xe3_h%\x99\xf4~v\xa30s\xfc0U\x17N\xb2\x87T\x8bI\xdc\"w\xeb\xdf]\xe5\xc1\x98+I(\x08\xa2}\xeem\xc3\xa8\xba,\xed\xa8\xe46\x99\x84\xfb]f9\xe9\xba\x1d\x1f\x9e\n\x95\xb9\xcd\xec\xf4\xc0\xaf\xa3\x07\xddI\xa2B\xfdbh|u\x92\x81\xbc\x08L\x0b\x07\xb79V\xcd\x15f\x8a\\\x9f\xbb\xc1^\xab\xfes\xa1\xe9TMEtT\xa16\x18\xfa\n\xaec\xe7~e\xc6\xa3\xfa\xecL\x9f\x84\xdc\x1c\xf14\x1a\xf1)\xc5fSG \x1e/\xe1\x9b\x9f\xa4Y\xbb\x06G\xac\xb2t\xd3.V\xe4\xbf\xc9\xfc}\x82da3rh\xa2\x84\xb8 \x92D_$\x13\xa9\xeeg1\xa6\x06\xe2\x0b\x9b:\xe3\xa7\xe2?\x10\x1b|\xe4H\xa6\x8c\x95\xcf\xbd\xcf*\x97#2\x9b\xf2\xce\xcc\xc8\x89\xa7h\xa5\xd4\xd2\x91#!\xec\x7f\xddv\x1b\xaf\xd1#s\xb6\xad\xd7\x87\x0b\x99W\x19E\x84\x8a\xa2\xf0\xa5\x11A+F\xe5]\xff\x16\xfbFhD\xfc\x80\xbb\xb9\xf4,\xb0j!]\x95\xe5f\xfe\x94E\xd7\x90\xd6\xceH2\x88\xa4\xaa($\xcd\x8aB5^\xb8\"\xe1\x17\xe3\x99R/\xad\xa0\xb7]\xcd\xcf\x9a\x04)|\x9aj\x9f\x83\x89\x94\x1a\\\xe7\x8e\xe8\xa8\x0c\xd6\xd90\xaayr,\x97%\xa6x\xc1M,C\x968\x0d\xcf\xc9\xd6\x1f\x95\xe2\x80/(\x03\x90>\xeeb\x9f\xaa_\xd4\x89\xae\x97\x1eJ\xd4\x7f\x81%5*\x88\xdc~+hb\xfb\xe5W\xdd\xca\x1d\xe0VMS\xf6s_K\xc8x\x1b[\xa9\xac\x0d\x80\x93_\xcd\x1by\xb0\xa3\x0b\xcc\xb1\x83K\x0f\xde\xd4\xd8(\xcb\xaf\xe6X^\xbf\x95rJ\x1d-\xfa\x86P\x89/\xe3\xf1\xd2\x0f\xebnB\xd3\xa1\x94\xd8Vn\xe7N\xf0}~\x08(\x86\xbe\xd1\xf5\xaa[*j?\x917G\xdf\x80\x15\xa4#K\xdba\xfb$y\xe7:2>\x16\x13\xfd\x8dj\x05I>\xd3\xb7\x10\x16{\x82\x02\xf1\xf3\xa2\xfd0\x98\xd2\x1d\x89Y\xc8emj\n\xfd+\xf4D\x9e$\xea\x02\xb9Y]aZQ\x9at\x8d\x8c\x7f\x8e\xa94u?\x10\xf8Tp\xfb\xc95\x02I\x9f\xfb\xa0\xc4v\xcc\xddv6\x93 ~'\xf4\x8a< \xda\x9d\"\x93\xbf.\xb6\x9b\x04u6\n\xfdk\x1e\xbbL\x14#8\xac\xea\xa2[7\xc6\x00\xfe ,\xdc\x0d\xb8\x934\xbc\x8d\xa1\x7f\xcf\x83dB\xfe\x0f\xa6h3O\x82\x05[\x9e\x16\xfc\x13\x03\xde\x96^\xd1G\x1a\x1e<\xd4?\xf5 \xe9j\x98\xf1\xc4\xe5q\x16%\x0b2=\x0f\xfe*\x96j:\xf9\xb5\xfc#w\x8du\xbf\x1a\xef\xee\xf2/\xe1i\x1c\x85)'C%\x9f\x7f\xfbcu\x13\xee\xf10\xf3\x9d ]`\xad\xd4\x19qEg\x1b\xe2\xe0\xf4O\x91\xb7&\xa7\xf6\xf2OP\xc98[\xa8\xbe\xe2y+\x8d\xc2\xee\x1f\x1c\xff\x83\xc9\xe4\xad\xf9\x94\xdc\xed\xccdC\x1e\xb6\xfb]\xd6o\xb8$\xb0Bj\x96\xc9r\xc8\xa6\xd5\x8c\xb4@x\x1d\xa2\x1d\xcc\xd1\xec\xb2V\x11*\xa4i\x8a\xf9\x08zG\xab\xe1\x0d\xf4\xaa\x1553&Nx\\N\xdf\x01r\x95\x11G\xfcg\x01\xc4p)\x90Ws h\xdf\xa8\x92\x1d6\xebLdT\xd9a,\xa8\x85\x90\xb5n\xc2\x02\xddT\x93\xbb B\xf8\x04\xbcQ\xae#\xb6\x04n\xfaW\xb3I\xe4\xab\xcd\xff\xb9V\xb7\x0d\xaa\xdbh7\xe3N\xb7\xb9\xc6)\xa2\xce\x8c_\xfe\xddm\xb2\x0c\x97\x7fU+qe\xb8pc@\xcc\xd4\xfag\xbb\xd9\xb0\xda5i\xe7\xd3\x04\xd8L\x8a[113\x8d\xd9!u\x10N3v\xd5\xa3\xd5B\xb3\x0d\xd8\xf6S\xb3\xb6\xbc.g<\x98 \xd1)]\xf0nQD\xe6;m&=\xf5\x98\xdc`\xed,\xa2\x88j\x1e\xa0\xa2\x9b\xfa-\xfb\xbf\x90\xb5k\x82\xe7O\xf5\xab \xca\x99\x9f:&\xe7\xab\xf2 \xfa\xed\xda\xe5\xbe\xace\xf3\x85\x9e\xa4\x1a\xf32\xab\xe2M\xdf\x8e7\xf6\xba\xea\xdai\xbaH\xb9t\xe6EG\xca}\xe9x6j7u\xdba\xfb\xf4 \x12\x9c\xa6\xee\xa8N\x9c\xb0\\R\xc9\x00NZ\xc5Q\xa0\x93\xb3\xb3\xb6P\x04\x00\x11\x0bm\xaa\xc6pr\xb6\xe6\xecXB\xb9\xfe\xe9\xc5\xb3}\xcd\x01\x18c\x95T\xb2\xda\xc8\x80gk\x91\xeb\x04 `-4\x9b\x03\xb5\xf7\x834K\xc4N\x92\xf2\xab\xceHU\xed\xb4\x0bi\xa9q,\xbf}bf\xec\xd8g\x0fw\x130Tk\xfb>|op6\x85\xf3S\xb9v\xc0U'^w7_\xa2\x96\x169\x9b\xe9\x87`C\xef`E\xb9\xee\"^O\xe9\xb9\\#\xac\x06*}\x99[\xb9*\xa0\xf2\xb7<\xb7\xe6\x9cFh9\xda\\)\x1f~\x97\xf96\x03\xbf9\x0d~\xfd\x1dIh5\xe2\x87U#>{\x8d\xb5\xa3&\xfb\xbdR!:\x02w\x9f\xab\xd8n\x12\xb4[\xe2CU\x89\x08KV\xfd\xc2\xa8?\x93'\x81@2x\x81]HH\x99\x8a\x84#\xe7%\x04\x03\x89ED\xfd\x06\x9f\x9f2\xe6\x0fx6%\xa6q\x15\x0d\x83\xdf\xdf\x94\xf6\xfc\x05\x19J\xf8\x0d\x9d\xa5v\xef\xe8*\xe1q\xde\xf6\xda\x9f\xf4\xf0\xf0\xbf\xbc\x87\x07e\xb0u\xb1~\x82U\xdb\xef>e\x00\x91\x8e\xad+\xc5sE]\x96\xce\xecn./\xee\xac\xdc\x84\xd8\x86\xed A\x0df\xef\xe0\xb9\xf1j\xb4J\xa1\x04\xd0P\n\xdc\xeb\xce\xc6\xf9\xf3k\xd3\xf6\xfa\\1)8U\x89\x19\xb2\x8a\x05;\x82\x02=\xa2o\xc2=\xf7\xf3\xc9\xd3\xd7\x0d[\xb5\xd9\x1f\xa6\x91\xad\xa7\x90o+ \x16\xea\x8b1e-\xe0\xf8\x15\x8d\xe7\xd09\x9f\xfb\xbe\x91C&\x1b\x95c\xb4[xtNa\xb2f%\x84\xda\xf7C/\xda/.3\x86NZ\x93\x00\x0d\xff\xb2\x99\xc09\x8c\xf2L\xc7uKJ\xbe\xccy\xbc\xe6\x87{\x17\x9ct8\xcd\xfd\xd2\x04\x1b]-\xf4K\x98|\xc4\xae\x9a\xfc\xb6\xb5\x1b[\xf2\xcc\x99\x90\x06\xc4$\x1d\xdaq\x06\x0b\x85\xbb\x10\x1dJ\xe5\xcb\xdd\"\xd1\xacEUq\xa4\x9a`UU\x00\xf4\xb2-|\x07@\xdf\xb1+\x17\xce\xd7'W\xff\xf6 \x89\xbc\xcc\xd8v\x93(\x08v\xc0\xf5.U\xffPw\xe0\xf2[\xc2\x1d\xefp'\x82r\x8a\xb8\"\x1c\xae\xd45!X\xcd\x0e\x8f\xfd\xda\xb8\xf6\xbe5\xf2\n\x0c-'g\xb1\x97d\xaej\x9c>AR\xa34\x86\xb6c\xde(\xdf\xa0l\x07V\xac\xe8\x7f}X\xc1\xd4*\xc5\xe5e\x9cH/\x0b\xc67\xc9\xcf\x06\x9c5\x81&5\xc4\xbdLKp+\xef\xf8c\x0f{\xd8h-\xafU\xde\xc2\xcfT\xee\xe3\x08r\x1f\x17\x9e\xf6y\x8d\x99\x1e\xb2*V\xa9y\xd4\xe9\xb2\xb0\xdd\x91\x8f0\nT\xf4\xc3Ag\x8aG`\xc5\xfeG\x13#D\\Yj\xae\xe1\xd6 0O@k\xa14\x10Bi \x84\xd2\xa0\xa1\x9eV\xa6\x13!\xef\x8b\xe3#+\x9fK\xa2\xd1j\xba=\x8c\xf6\xc3\xef\xf3C\x89\x88u\x0d\xc8\xdca}\xf4:ls\x7f1\x8d&\xeeO\x8e\xa5\xf1\xd8\x19\x16O\\\xa9\xa1,\xd5\xb4Rr\xc0n\xa7\xac\x9e:B\xcc\x12\x93\xef\xc8\xa4\xa2\xf5u\xe7\xe5\x9d\x8cyX\xf65\\\xbb-\xe3\xd0\xe1\xcaA\xd3\xa4M'\x83v\xd9Q\xe6Iw\x16\xf1\xd7P\xaaTs\xd5\xf6^z\xe9\xb9\x1b\xac\x8b\x84\x98\xea.\xbe\xaa\x07N\xff\xb2Z\x95hT7\xc4\xc3\xf4\xb7\xf9j\xa4\xd6\xd8\xca\x8a\x8b( \x107\xa1\xcd\x9bYTs\xfdd\xae\x9dp\x1eIE\x06\xafs\xfaTW\xe3T\x86\xb5\x0cf\xaa95[GX\x85RV\xe4\xb2z\x0c\x9f\x92`2\x85\xe6`z)\xa8p\xa7J\x9f$\xbbh\xc2\x8f\xb1\xc9\x06\x04\x0f\x90\xcc5\x1c\x8d\xd6\x11\xf08\x13\xc4\x8c\xe9\xcc\xf9\x91\xa9\xd8\xe9J\xc4o*\xd1L4|\x9c\xf9w\xfah\x12\xfd\xd3'\x9e\xebwhT\xba\xdd\xf6\xf1\x9b\xc7\x07]\xd6b\xad >\x1c\x13(\x94#\xe9\xa8o\xe8\xa6\xa0\xa2\xbb%\xaa\xda\xf6\x1b\xe6\x18J\xfe\xdav\xba\xf0\xdc@h\x8eP\xdby!\xe7rl\x95\x9f&2\xf3\xa9,l\xac\xe2\xf7\x8b\xd0S\xe0\x9f\x96\xeb\x043\xa9Y\x03\xd7xi\xf9i;\x01\xfd;0Z:\xef\x80\xe1:D\x1a\x0c\x92\x11%g\xc7e*\x92\xa5-t\xacq\xddF5\xb2\xe8\x8b[\xb9f!A\xca\xbd`&\xec\x87\xc5Zn:\x89\x98/\x17\x92\x8cY9u\xd7-\x0b\xc8G\x1eg\xb2\xa8\x96\xac\xff\xd68\xc4@\xae(\x96\xf7\xa7\xb1\xd7O\xc3%d\xbb\x8aWP\x87\x1340\xbb\xe5\xa9\xda\x8d=\x9e\x01m\xc4\x94f\x04M\xf0\x8d\x97\xaf\xfeC\xe1U3\xe5\x97\x84|\x14\xe7\x19\xf7\xb6\xb3\xc3@\xe6#\xae\xad \xd6\xb4\xe5\xf4\xd2(\xc83\x95S;\x99\x89\xa3T\xc6\xea\xd4W\x93\xf1\xf7\xec5v\xbc\xed\xe4Y\xf4#X\xc7\x1f\x0d}\xcf\xe3a\xe78[\xa8\x02:\xc7\xeb\x99O\xab\xef\x1fp\x0f\xf7\\\xbc\x90f\xafidx\x99^\xf0U\xf9\x1fG\xf0\xe0b\x91^\xad\xa7\xd221\xbdm\xa5\x9cN\x97\xb5\x8f\xc8wTZi\xe6d\xbe\x0b\xae\xd3\xe5\x81\xbd\xf4\x12\xf3eZ\xe0v2\x13\x8dy\xd2\x0f\xa2}v\x94\x15\xff\xb8Z\xf9\xd7\x1b\x9d\xc2\xdd\xde>\x17=\xd3IX\x88\x14\xc5 \x960\xc0\xf3\xdaT\xa9\x93\x8d_\x88\x96-\xb0\x86D\xe7\xba\xec\x02\xab\x89q\x13\xbf\xcaQ^`\x83\x06,.\xb3\x9f\x056\xae/I\xa4\xae\x056\xb4\x13\x1f{\x1b\xa5{\xe9\xfa\x95\xa8r\xa6i\x1d\xbf\x18\xc3\x9e\xccM\xef$\xf5UZ\xac\xed\x01\xb4_\xd4{\xa44\x8b&\xa9\x1e^;\xf1\xbb,\xb7SgDX\xb2\xa1\x9fvY\x9d]\xd5\x08\xc1\xa9\xd5\x90\xed\x1aCv\xda\xe9J\xeb\xed\xec\xab\xac\x0f\x8f\xf8\xf5\x8f\x1e\xed0\xf7z\xbfj\xc8\xee7\xbf\x16/\xd8\x9cO3\xa7\xc2 \xe5\xbb\x83\xc1\xcc\xcd\x9b\xd2\xb9\xec\xe6M\xed\x12]\xf2)\x0f:\x1d\xe9a\xa6L\xe2\xbc\xcb\xae\x8b\xba&\xc9\xb2\xdb\xe9\xc8\xf0\x99(\\\x8b\x1co\xa2\xfdL\xff4\x07\xf6g\xe2$\x8a\xd3\"\x93\xc2L\x16\xc1\xc1j\xca5\xc0\x14\x17F\x92G8\x939\x83\xae|\x04U}]\xf5\x1a8*\xbe2\xadH\xb0\x82?\xd4\xe9\xc4p\xc3\x10\x12G\x02{V\"J\x96K\xe6\xe9\xbc\xb4\xd2\xf06<\x92I\x82.\xaby\xf6hO\x88=\xad\x84\x87\x1eOj\xcc\xa6\x8a\xdaL\xbc]a\xc5\xa0Rdq0Q\xaai\xec\x84\x84\x9c\xd1F\xfa\x0b\xf0\x9c\x04\xe0Cm\xe1\xbb\xdd\xda\x9e\xb8z\x90B\"F\x1d?\xa7\xab|\xa3\xd3E)\x19\xee\xb6\x8b.\xcc\x15\xf37\xda\x87\xe7\x1bG\xfaCi\x176\xff\xfc\x1d\xd9/\xfd~G\xf6\xbf8\xd9\xb7\xe8\x85\x9a\x13d\xce\xe0\x0b\xd3\xec\xf0w4\xfbw4\xfb\xab\xa6\xd9\xcf\xe7\x1ag!?\xb5It\xa28='\x13\xb2=\x87\xe3R10\xc4Kt\xba\xaf\x93\xb3\xa7-L\xe3E\xe5\xfb\xfa\xe6\xeeG\xa3\xb7(\xc9{gy/\xa5TA\xbe\xd5~\x86\x85&`\x13\x87\x0f\xfc\x97\x85\xa1\x93\xcc\xd4l\x8a`\xa8)\xed\x19\xcc\x04\xeaB$\xf9tlD\xff\xa6\xf5\x1e\xc2?U/\x91\x0f\xc0w\x1b\xbc7'\xb6f7\x9a\x19h\xb3\n\x03\x13\xbf\x98F!\x9e\xfc\x146L\xf6%\xe6os\xe3jwf\xa2P\x90\xdc\x80g\x96G!m?\xb3\x8c/\xbd\xc4Zz\x10\xe5@\xcdP^\xec\xa6<\xdb\xf1G<\xca\xa5\xbb3<\xb8\x7f\x86\x1d\x99\xeb|\x95+_\x0b\xad1s\x92\xaf\xd3\xd2Y9\x15\xeb\xa1/\xefF\xf9\xbd\xc6\x96\xe7d\xce\x82?r\x06\xfcx:\x1e\x1c=\x18\x05\xaf\xf6\x9c\x94\xbf|\xb2\xbbya}\xfe\xda\xe1\xd9\x13\xce\x95\xadYgy\xd6\xbftkq\xdf\xbd0\xf0W\x97\xceF\xd7\xae\x04\xa1s\xe1\xf5\xd3\xab\xb7V\xf7/]8{r\xd5_\x1c\xf0\xf3si/\xbctzu4\x9c\xf5.,\xbe\xbcvx\xfa\x84w\xc2\xcd\xbd;\x97\xf2\xde\x89\x8b\xe1\xda\x9d\xd5\xfdK\xcb\x8bc\xf7\xc4\xb5p\xd5?;\xef\\\xb9|\xe2\xf5\xd1\xe9\x93\x9b\xdb\xab\xfb\xab\xcb\x8b\x83K;\x8b\xfb\xab\xcb+\xfb\x97\x96V\x07\xee\x85\x8b\x81;\x7f\xf9\xd0\x1b]>\xeb\x9e8\x1b\\=\xb1\xb5}\xf5\x8d\xad\xb8wg\xd6\xe7+s\xf1\xb5s\xc1\xbas\xe5u\x7f\xf5\xfczz\xf5\x8d\xf5;\x9b\xdb\x17\xd3k\x17.e\xee\xe8t\xda;\x1f\xe4\xd7\x0eW\x07\xee\x89\xadS\xbd\xf3\xbb\xa7WG\x17\x87W\xe7\xb3\xd0\x1d\x9d\x9e\xeb\x8d^\xcf\x9c+s\xc3k\xf3\xbb/\xaf\x9e?5\xee\x8dv\xbf\xb3z\xbe\nw\xcf\x9f\xbe\xe3\x88\xbe\xe6O\xbe\xbcz>\xc8\xc5\xdfW\xaf\xec\x0f\x9c+\xa7b\xef|0\xec-\xa7\x83\xab\xa3s\xb7\x9cy\xef\xb0w\xe2r~mi\xee\xf0\xda\x1bg\x83\xabo\xbc^W\xde\xdf\xbcup\xcby\xe3\xe2\xad\xde\xf9\xdd\xc1\xd5\x13\x83\xd3\xab\xb7v\xf7W\xfd\xb3\xb7\xf8\xce\xac\xbf\xbe\xb3\xe8\xaf\x9e\xbf\x16\xf7\xce\xef\x9f^\x1d\xc91\xf9\xab\xe7O\x85kW\xce\xcdz\x17V3\xf7\xc4\xd6ao>\x0b6\xb7/~\x87\xcf\xaf\x8f{\xa3k\xf1\xb5\xc3S\xb7z\xf3\x07c7\x9c;\xbd\xea\x9f\xcd\xaf\x1d\xce\x0d\xbd\x0b[\x87ko\xac\xcf\xba\xa3\xd3\xc9\xb5\xed9\xb3o\xfcDv\xab7\x7fj\xe4\\qso>\xd8\xf3\xce\x0fO\xf7\xb7W\x07\xbd\x91\x9b]}ck\xd6\xf5\xe7\x0eQ\xdb\x87W\xafl\xc5\xde\x1b\xeb\xb8\xdc\x1d\xef\xc2\xc5\xb13\xbf\x9b];\x7f\xee\x8es\xfe\xdc\xa1;:w\n\xd5\xdd\xbb\xfa\xc6zt\xf5\x8d\x8b\x87W\xdf\x08d\xfdb\xfc\xab\xb7\xd6wv\xe7\xc4\xffV\xfd\xb3\xa6-\x18\x93X\x93\x15\xb1&\x87\x9b\xdb\xabw\xd6K\xf5\xd6\xael\x0d\xdd\xf9\xe1\xd0\x0d/\x0e\xc5z]\xda\xb9:\xbbvk\xef\xce\xa5;W\x0f\xd6\x97/\x1d\\\xba\xf3\xfa\xfc\xfa\xf2\xca\xdc\xea\xf2\xee\xfc\xda\xad\xbd\x13\xebw\x06'.\xed\xbc~g\xfd\xce\xe0\xf0\xd2\xce\xa5\x93\xab\xb7N\xber\xf5\xca\xa9\xb8w\xe5\xdc\xec\xb5\xcb[\x87W\xaf\x9c\xbasmt\xfa\xb0\xb7}V\xae\x99s\xe5\xe2\x9cw\xfe\xf2\xc6\xd5+sb\x8dg\xdd\xd1\xb9\xdc\x9d\xbf6vG\xb3\xfe\xea\x85\xadS\xae\xc0\xa1\xf0\xe2\xd8;\x7fn\xf6\xda\xf6\xea\xe0\xea\xfc\xb9\xf4\xea\xec\xdc\xf8\x9a\xc4\xad\x83\xb87\xbau\xf9|\x90]{\xe3\xd2\xe9\xd5[\x8b\xdf\xb9\xb4\xbd:\xb8v\xe1\xb2\x98\xf3\x81{\xb8:\xb8:\xba\x1c:WN\x9e^\xbdu\xf6\x8eX\x0b\xc0\xab\xade\x81g\xde\xf2\xac\xef\\9\xb5w\xed\xca\xb5\xb87\n\xc4X\x8en.\x9d\x1e\xf6F\x81\xd8\x9f\xe0\xf2\x85\x8b\xc3^\xb8>\xea\x9d\xb8\x98m\xde\xda\x1f_\x9d\x0f\x0e\xaf\xce\x1f\x04\xe2oq\xe66\x07\xd1\x99\xd67D\"X\x8a\x82\xc0\x89Sx\xbab\xcd\x0f\xf7\xe4\x1f\xe0\xcb#\xff\\\x0d\xe3\x1c\xfe\xda\xe1\x07\xd9b\xc2!\x0d\xea\xd9<\xcb\"\xe0\x16[\xd2KX6\xa5\xfe+\xb3}\xcb\xb7{\xeb\x82\x11\xa5\xff51Ch\xcf\xecW\xac\xafS\xf6mF\x10G7f3i\xf4mF\x90T\x01H\xef\x81\x02\x10#\x88\xab\x00\x15#\x88\xf4\x13\xb7\x9b\xbf\xbf&\x87m\xdaqLx\xbd\xb10p\xab\x85!3\x16\x06\xae^L\x98}\x95\x85\xec\xbb\x8c\xbf\xca\xc2\xa3G;L\xc5\x0d\x17\x16\x86\x10\xa9\xe1jb\xd9tI\xa3U\xe9#G\xd0\xac:3\xb7\"?l\xb7X\xab3\x93%\xfe\xa8\x8dEg&\xb5\xfc2f\xd5wd\x96#\x9b\x14\nLl \x99R\xdbSb\x1c\xc9\xa8a\xa4|G\xdc\xe9(\x99\x05\x8a\x17\x12K]\xec+\x1aIPj\x0b\x9e\xdfE6\x85\xccj=\x98`9\x98\xd6j\xa0\x11\xa4\xd0\xd6\xebET\x95\x834\x0f\x82\xd4M\xb8\xed\x81)\xfd\x0bM\xc9\xfa2\x96\\q\xbc\xcb\xae\xb7\x8a\xf6e&\x9d<\x08j\xdf\x1e\x93\xc9\xec\x8cg\x8e[k\xf5\xe0 \x88B4\xaf\xad!\xed\x84\xd4J\xf7\x9d\xc1\x80'\xc7\\\x8dn2\xabN\xc8^c\xadcr(l\x81\xb5\xea\xbc\xc6\xa7\x1fG\x9b>3\xe97\x99e\xdc\xc0I\xd3u\xf9XZ\xdc\xf6g\xcc?+\xafj\x95\x7fw'\xbb>\xde\xe8Tb\xfd\xdb\xae\xc5\xceR\xa5\xde\x1e\xf1\x97\x1bE=?\xe0bI\xaa\xfb\x9c9\xbd\x80g\x0b\xacu\x0c\xfeB`\x8f\xa7{Y\x14\x0b\xb8\xfa\x13\x15\x08\x9cd \x9a=6\xf4JW\xb3\xafV\xe8A\xf0;J\x00\xbf\xdf\x1a%\x18\xfa^CV8\xa0\x01{\x9c\xc7K\x90\x8d\xb3\xa1=I\x0b\xf8\x0c\xa0\x93\xd0\x02\x01m\xba\xd2\x9bB\"\x88\xf8Sb\x05\xf1\xdb\x90DC\x0cE\x90\x8brw\xe2\xdf\xd0\xa2|\xabQ!\"k\x19\x94c-\xd9b\x8b< k\x86%\x93\xf1\xbe\xf4\x12;\x12NAe\xc0\xb6*C\xe8\x9b\xa9\xcc\xf5\x1a{\xb6\xe1\xd89\xf3C\xe65\xbb>z(\xedG;\xefL\xd2\xf6\xf5u\x83W\x1b\xec\xa4\x7f\xa2\x83\x1c\x1e\x0d2F\xdc)L :\xc8\xa9\xa85\xb1'\xa6z\x0b\xd8w\xd9\xdc4}0\x99\xd4Q\xbe\xe5\xd2\n\xa3\x90\x0b\x02=mT\xad\xa0\xea~\x98O\x91hob =\x84^\x10\xb9{0\x86\xae\xf9\xe8F\xc11\xf9(\xa5\xfc\xde\xd8\xd6\xf3\xda%t\x0cW\x8c\x0c%\xd7K\\\xc1\\\xca8u\x88=\x11\x97\xbf0\xa7J\xb3\xc3\xa0\xf6yl\xfd\xf3\xfc4\x0e\x9c\xc3\x05\xe9}\xacv\xd1\xf2nG\xf9\xd7`9+1\xc7\x9a\x14J/\x86\x19v\x8d\xc2\xf3;\xb6\xf3\xe2\xd8\xce$T\xf4\xfc\xb1\x1d\x0dK|jZ\xc9\xa9\xa8R\x16\xa1Z\xfb\x89\x13\xc7<\xa9u\xd2{!\xd8S\x1c\xc4vI\x85\xfe\x1d&}}\x98\xd4\x93\x8b\xfeU#\x93\xea\xe5+\xc5\xa5\x8e\xfe&\x98?\xcd\x91Y\x1af\xabF|.\x19t\xeaQp\xd2\x82f\xfc s\x12\xee\xb4*\xb7\xec2\xb5\x936\x1d}\xf1\xc6}\xd1\x02j\xb9r\x86\x8c\xa1j\xaa3Tw\xa1Ws\x80(\xdb\xd4\xe6\xab/z\xb0dV6(-\xc7b\xe9b\x08\x85lo\x81\xeb\xe8\xcc\xba\x17 \xd4jB\x00\xa7<02\x15&\xfc\xb5\xc0\xf8\xcc(\x0f2?\x96V\xa7\xeb\xad\x96\xf4\x0bo\x89S \xaf\xf6j\xb3\xac\xaa\xa3\x17Q\xa4\xedZ/~\xf5\xef\x1bC\x13\x9e_\xa9Q\x0f\x0d^\x16\x1d4\x14\x06\xedF\xafj}\xb9\xa4hte\x14g\x87\xb2\xdd\xfa\xe2\x91\x1e\xab\xdc\x17\xd8?\xf9<\x12{\xcd\xfe\xbd-\xb3u!\xc8\x17\x15\xfa\xc4\x81jt\x0f)Q\x16+\xf9\xab\xad\xa8\x17\xaa1\xab\xac\xc6\xb6\x86\xe5 \x97\x86N8\xe0\xc6?\x05\xfei-/P\x94\xbdV?\xdd(V\"n\xfdt\xd5\x80Z\xf6d\xd6w\xbb\xacu\xecX\xab\xa3DWA\xf6\xaaq\xca\xd3\x054|\x99\x012}R\x1a\xa2 Y1\x91m\x999\xb7)}\xfd\xddnQ\xe8\xb7\xc9\xc2\n|92\x87\xac\xfe\xd5\xa3T\xbd\xd7\xa8\xda\xab\x86\x93BM\xcb\xd4\x81\x9e\x99\n\x8a\x95\x9b\x9a\x18\xf2\xc9'\x91\x1a\x08\x9e\xd6m7\x93\x83p\n*\xe3K\xab\x02\x84\xd7+N3\x939\xc9\x80g3\x80Ei\x83\xf3\xb43\xe1\xa5\x1b\x01\x8f\xd8k\xcc\x9f\xce\xd0\xaf\x7f\xc6\xb7\x06\xe8\n\xb7\xfb\x91\xdd}\x9e\xe0~\xd3\xa4\xc4\xe7\x9a\xf6\x04=\xd4\x93\x97\xe5\xba\x103\x04\x81!\x13\x0f\xbbS\xd3l\x17\xdc\x1a\x12[\x88>\xc2\xff\xeaR\x8f\x85\xd0`.\xd8\x9a':A\xe8g\xbfe\xc1\x9f\x91\xb9\xb2\x17\xc2\xec\xd9d\x86\xcf\x9e\x83\xe9\xb3)\x88\xab\xf3e\xf4\x00\xe8 X`\xad0\x8ab\x1e\xf2\x84\x85Q\xc2\xfb\x9fCe\xd5e\xb0\xce\xb6\xd1\x8c\x98c\xf3\x04\x9d;\xf4\x03/\xe1\x96\x90\xeeIK\x0e\x9a\xbc}U'\x9a\x8d\x86\xdc\x1f\x0c\xe5c\x13ymR\x18\xf1\xebE\x89\xc7\x93\x05eUj\x10H\x9cd\xe0\x87\x0b\xac\xe1\xa1\x92\xd8\xf1\x95\xfa\xf2O\xc9\x04\xb0\x1ee\x8b\xa1?r2\xee} \xc9_\xdfN\x17'\xccO7\xc4Y\xf5\x1a\x84\xc2\xb1\x8e\x19,\x1fL\x85\xf0\x82\xb1\xd4\xe2v\x18\xa5n\xe2\xc7\x99\xbe\x00\x98@6\xef\xda\xce\xc1oO\xe5Q\xab=I\xdb\xd1\x0b8I\xdb\xa9'\x11\xac\xb41\xec5p:\x0e\x95\x8f1,\xfc\xc4\x9dI:F\xe3!\xe8by\xb3\xe3\xc5\x8b\xa6z\x15,\xa2\xa9\x1a\xc6\x82v\x00d\xec\x9b\xe1\xffK\x9dp\xbcZ'\x1c\xcf\xe6j\xe3\xeb*6\x1f\x1c\xcf\xe6j\x93+\x8057\xa2gs\xb5 \x14\x80\xe4\xecw\x15\xe0\xf4+\xa71\xa8\xaf@sd`\xb1\x86\xd8\xfdt\xbc\xaf\xc7OG\xffE\xb4\x91\xe7\xa5\xf5E\xfcQ\xd2\xb5\xa5 \xc1d\xbc\xd6\x8c5!\xee(\xa8\xc4\x1d\xb9\xe0\x15\xe4B\xdc\x91{\xf4h\x87\x05\xd7\xdd\xaaW\x90k\xb9\xe0SK)\xa8\x866\x99\xe5\x84\x11\x81\xdf\x19aF\x115\x9b\xd5\xc5\x1c\x052\xe6(\x99\x19\xf0\xecR\xe4\xf1@HO\x13E\xec\xd2\xf8\x94\x17?7^\xfc\xad\xdf;^z\x15\xfbxKf\x93+2\x87\xfd\xe1\xcc\x1f\xfc\xde\x0f\xca%~p\xfcx\x97\xb5\xa4\x05\xc0\xd6\x96k\xd2\xd8\x1eO\xdd!\x1f9\xa4\xc9\x9aB\xbaQ\xd0\xca\xc8\x14\xee\xaaIo\xf1\xfe\xb6\xac\xf2<\x93N\x14[\xab\xbc\xbf;\xd3\xf7C\xafx\xde\xdbf!\xb8\xdb\x85\x9c\x14\x84\xa1'\xc4 \xa5V8H\xad\xc2\x81\xf3<\xc2\xc1\xd7\xca\x18Uj!\xb9=\xcdJ:\x9f\x98\xff\x94)2\xca\xa7}\xf9\xd8\x81\xc2r\x83\xebK\xe5\xb2T\xc2o\xe7~\xd2\xc4\x99SY.l4\xd2\xb9\x8a\xcbo\xf1~}\xa1\xbe\x99\xc3f\xeds\xf9L\x11`>\xa3nz\x9b\x8d\x832\x8dd\xbb\x05\xecN\x9e\xe4V\x83\xb9b\x08\xa5%\x95\x9aXx\x0c\x857\x13\x7f\xe4g\xfe\x98O\xac0bgX+\x92#i\xd0\x1e\x06\x82\x04\xc2\xab\x902)\xd0\xef\xff~\xc2\xfbuna2 \xa9|\xccx\x00\xe1\x0f\x1a\x07\xcbt\xab=\x10\xb4\xec\x88S\x14sJ\xc5\xccIo\xa7P\xcc\xb8\xa3\x04\xb5\xd6\xdcI\xa1~\xe5[\xa2\x91\x18\x06\x93\xff\x7f,\xf3\xb3\x80\xd7Z<_`\x7f\xd0\xd3\xcd\x9b\x19?\xc8j\xfb\x8b\x05_\x10\xbc\xa8\xb6c\x7f4h\xec7M\xdc\x05\x16\xb6O\xce\xcd5!\x95V/\xe7g\xe3\x83\x86\x8d\xdf\xf7\xbdl8\xb9\xd8Du\x96\x19\x15t\x8d\xf7E\xbfs|4\xe9\xa5=\x95\xbcL\x92\xc2\xc0\x11\xd8<\xa1F/\xca\xb2h\xb4\xc0Zb\xb0\xb5%k\xe2_\xea\\G\x04\x15=\x94\x89\x1a\xfctcq\xfbD\xbbS:\x07\x1e\x8f\x13\xeeJ\xcd\xad\xa6z\xba\xef\xcbL\x84\xae1:J\xbe\xe9\n\xa5\x8c-\xb0#G\x06]y\x06\xcb\xa7+;\x8c9\xbc\x997j2\xf9\xb8N\xca\xcd\xd9]h\\\x99 \x87\xc7\xa3\xb6\xa1\xc6\xe6\x18Bo5\x86\xc6:\xcfelb*\xc0N\x90\xdc\x05\xd6@\x9d\xf5\xaf\xe0F\x8d\xf7)\xfa\x07\\\xa6\xf1\xa12\xfd\x0b\xe5\x14\xa7xL\xbf\xc0\x85\x05v8\xb9\xb8d;\x0b\xccm^\xb4\xa6\xcc\xb1\xb0\xff\x8e\xe0\x0b_n\xfb\x87_r\xfba\x08/v\xf7\xff\xf1m\xa8\x96I\xea\x1e\x8b\xd3\xbf)\xf6T\xbd\xf8X\xbf\xa9P,\xccG=\x9eL,\xe6\x87\x19\x1fLQ\xae\x17E\x01w\xc2\x86rZ\x03\xfc2\xc86\xfe\x92vh\xa6\x91C\xc9\xa9\x13\xef\x02\xd9\x7f\xe9\xd8d\x85O\x8c\xe7\xac\xb5\x0c\x95\xb0s(\xb7d\xe70\xe6\xd4,\xa4\xd7\xa8o\xf6YZ\xa2\xb9w\xc9\x89\xa5Lm\x93\xd0\xab\x1b\x17\x9b\xaaB\x97i\xae\xa46o\xca*\x15\x95\xa3\\\x0b8Um=\xd8\xcd\xa28\x1c\xc4j\x99\x92\x88?\xa9\xa8\xa2\xf1E!q\xc4\xaaE\x8a}n*\xc5\x0fbG(\xac\xb1`\x87EA \x00hx\xd3\x14*\xf1VS.\xf0\xd3\xf2\xc2\x14\xa8Q\x8d\xa6\x87L\xa5\xbf]\xfb\x9e\x18Q\xea\x08\xdd\xfd\x8e\x0c\x90\n\xa8\xc1/\xb7Y\xd6\x84\xe6\xda\xce\xc1J\xd6\x95EN\xce\x9d\xea\xd8\x8c\x7f\xb2\xd0\xec)\xab\xfdO\xc2\xe6N\xd8\x0dm\xf9\xd7kh36\xb0\x19\xc7\xf3.D\xd1^\xbb\xd5\xe3\xfd(\xe1\xdbjy\x14\xd9M\x1b\xd3:\x9a{\xe6a\xc2\xfb0\xcc\x94g\x8bY\x96\xf8\xbd<\xe3m!\x80\xb7\xba\xf6\xdb\xbfN\xb74LlzM\xa7q\x89;\xfe\x87\xd7\x17\x8f]\xfbA:{\xec\xf4\x91\xd7~0s\xe3\xe8\xef\x1f\x1f\xa8d\xc5Ug8\xba\xda\xf5i\x98\x8a\x85\xd1\x88\"\xf0\x94\xae\xf5\xe2\xf2\xf2\xcd\xc5\x9d\x9d\xad\x05v\xbd\x05\x97\xe8\xadj\x86P\x92\xda\x82\xd5\xe6c\xc2C).\x11\xd3(O\\\x8bE\x00\xee\x19\x1a\xfc\x89\xfcBm8s\x06\xee\x0eZ\xd2w\xbc*B\x08\x95;mgE\xd6\xe6\xa4N{\xac\xbb\x94\xach\xabN\xb2\xe7E\xfbaU\xa4\xbbK\x0d\xac\x10\xbbq\x86\x85|\xbf\xb0c\xd6\x08\x8f\xc3l\x14\x88clg}\xd9a\x1c\x0d\x12'\x1e\xf2\xa4\xbeP/\xe1\xce^Z\x0f\x0f\xfcp\xcf\xef\x1f6\x17\xd8\x91\x9b\xbc\xc0Z7{\x81\x13\xeeY\xd2\xa8w\xd4EK;\xb3(\xd0\xae\xcc\x12\x96\xa3\x850w\xff\xafI\x15\x05\xf8\x9fq\x8d\x91\xe3\x8aa\x7fJ\x86\xa6\x01\x04\xb1FN \xd6\xeb\xd9Gx\xd7\x17/m.\xb0\xd6K\xa4|l\xf9\xba\x18J\xccy\xfc\xe7\xb84|\xbf\xf7!\xfd\xae@\x8f\x7fNA\x00\xf8K\nH\x83H>)\xf1\xec\xf1_P\xe0X\x02\xfe\x1b\x02\x90\xb3\xbbGvDz\xa6\xb6\x9e=z\x9f\x02d\x94\xac\xb5\xca(\x85\xf9`,\x02\x90\xe3\xc8\x16?\xb2\x03{\x12\xf8\xd8\x0e\x94\x07\xf2\xd1\x13;P\xf6\xf9\xe8\xa9\x1d\x08\xb3\xf8\x1b;P\xe2\xfc\xa3\x7fm\x07\xca\x85y\xf4?\xda\x81\x12#\x1f\xfd\x1b\nL2\xb9\x02\xbf\xb2A\xc6r\x8e\x0f\x08]\x01\x18L\xe3\xaf(0\x05\xfc\xbfGhE8HEo\x9f\xfc\x84\x02\xee8\x89\xc0\xe7g\xff\xfc?`T\x8c\x06\xd2\xee\xfa)9\xd0\x1a\x80[[\x8c\xe2>\x1c\xf5\x7fO\xaa(\xc8\xcf\xff%\x86\x88S\xf0\xec\xfe=\xf2Y\x10>\x89\x88d\xe9bID\x1fcJ\xe6\x00F\xdf\x7f@\xbe\xfbr\xc1\xee?$\x80(]`\xado\xe3Y\xc4qpxN1#+\xa9s\xe28\x89\x0ej\xc6-@\xfc\xb6u$\x8b\x89\xf4\xac\xb2l\x83\x06|\x80k\xa4.\x10\xcf\x7fI\x0e\xb1\x81\xfco\xa4N\xea\x0f\xe4\xc0\xef\xff\x8cT\x12X\xf0\x07\xe4\xeb\xe1\xa8f\x17\x04DM\xe6\x9f\xe3n2?\xf0$\x8d&L\xd1@\xfe\x07\\'\x17\x02G\xeb\x13\x82Q\xea;!!\xfbn\x14\xfa!\x1c\x14\xcc2\x9d}\x05\xf9\x08S\xf5\x9e\xe3\xee\xb9\x11\xd0\xab\xfb\xefZ\x80Z\xcf\xee\xbdG\xa0\x89\xa4\xbaO1}\xef9\xc9\x98\xcb\xb1<\xc0\xfd\x9du\x92}.1\xfb]\xcc\xbb{\x05\x08\xa3\x1a\x80\x80dS`/\xd9\x13\x80?%\xf3\xee%{\x99\x06\x92%\xab]\xeb\xb3 s\x90\xfd\x81\xcf\x98\xe7\xf6\xbc\xdby$\x97\x1dK\n=\xee:y*W\x0e\x8f\xec\xac\x04q+\xac\xd7\x08\x1b\xc5\xd9\xa1\\\xf4G\x98\x92\xf4\x04~X\x91\x83'a\x94\x8b:oc>qV\x82\x82\xc0Ok\xc0\x99\x9430\xf9\xeb\xa9\xef\xff\x0b\xfd\x0e\xa2\x0c\x1dB\xb6\xcf9\x1co\xd2\x89\x96\xb4\xc8\xbej\x00f6=\x7f\xe0\x02\x05~\x88\x05O\x01\x02\xd1\xf3\xd9/0 \x16\xb0\x1c\xaa\xe1\xc3\xdf\xf3\x07\x91\x17\xc1\xb9\xc4\xb2\x93\x80\xc5\x01l\xe4GX~\x12\xc0\xcc\x1fq\x80ZF\x93\xdeV}~D\xd0\xdd\x1f\xa4\x99#\xb9\xc5_\x90\xa9\xfb\x83,\xf1\xa5,\"\xf4&Q\xe6=rr\x8b2\xd0\xc3{\x98\xd6\xf4\xfcAnF\x8e\xa9W\xcf\x1f\xa83\xfa\xd02)s\xda\x1e\x92\xe5\xd8s\x92h_\x80\xde\xc7\xd4\xa2\x178\xee^\x10\xdd\xe1J\xb8\xfa\x10\xcb,\xb2@z;w\x12 \x7f\x0f\x0b<\x12\xae'%K`5\xa1R\xc2,\x0d\x968*\xa5\x02\xb8\xb5}\xf6\x0b\xb2;\xe5R\x89\xbaT~\xf6\x1e\x96\x02\xa4\xae- \xff\x023\x86^\xb077/\xeb\x90\x03\x12\xec\xcd\x9d\x94\x10BE\x82\xbd\x13\x00\xc1\xc2\xb2LO !\x98\xa1\xf5B\xb1\x18g\x9e\xfd\x183\xda^\xc8o\xe7\xbe$\x07\xf7\xff\xda\x02^\x07\x94~\x8a%\xc0^\x08\x80w\xb1\xbau\xd6\xc8B\xff\x07\xaebd!2nh\xeb\x01\xe9]_i\xdb@\xfb\x99\x0f\xe8E\xe6\x1a\x1d\xf4@J\xf9\xf0>\x05-\xaf \xc8\xcf\x7fa\x81\x04\x12\x82YT/:\xf0\xa0\x0eV4\x04D\xd6\xf9\x19^\x04\xd1\xda\x96\xac\x83%\x11\x01\x91\x07\xd6\xb2\x08\x07\x1e\xd4!\xa8\x10\x1dx\xb2\xce\xcf\x08O\x8f\x0e.\xc8*\x96\x01H2\xfa3r\xf6\xa2\x83\x0b\xcb\xb2\nVo\x05D\xb2\xce\x9fciD4\x06u\xe8.\x1c\x0ce\x9d\x9fa\x92,Z\xdb\x95u\xb0\xbe\" \x92\x95\xfc\x9c\xf0\xfc\xe8`\x08u\xb0\x02$ \xb2\xce\xcf\xc8i\x8e\x0eF~\x08\x04\xea\x01\xa1\xf2\xd1\x81&^\x0f\x08k\x8d\x0e\x0c\xd5}\x80\x15\xb5^t\xb0\x0b{\x8e\x95\x0d\x01\x01<\xc1\x82i/:\xc8\xa1\xce\x7fk\x81\x00\x9e`\xa5S\xb4\x06{\x8e\xb5N\x01\x01<\xf9\xa5\xa55\xa8ci-\x07<\xb1`\xddeY\x85\xd0\x92\xe8@\x9e\xfd\x9f\x11\xca\x16\x1d\\\x06\xd4\xb2\xec\xece\x89[?'\xb49:\x18C\x1dB\x95\xa3\x831\xe0#V\xb6Dk\xb0j\x844F\x07\x97a\xa5\xb1V'Z\x83:XA\x11\x10Xi\x0b\x0e_\x86U\xb3\xec\xf5eXi\x0b\xfa\x8c\xa1\x8e\x05y\xc6\xb0\xd2\x04\x0b\xeae\xe8\xb3\xca\x98\xf6k\xb2o\xf5\x80qO\xb2\xf7\x8f\xf1a=\x0bZ\x10\x95\xb7zF=\xfa\xdf \x84\x8f\x84p\xf7\xec\xad?#\x90:\xc9>Us!R}/\x8d\xc4:\xff\xe0\x07\x96\xefR\x85\xff\x90\xc8#i\x14\x0c\xd3\\\x02\x7fEHv\x1e\xc8m{\x93lu\x1e@j1\x1bH)o\x7fj\x01HM\xf9 \xb6L\x08\x08\xe8\xcax \xce\xe6F\xdf\xb35\xa7@\xb8\xd6\x92\xb6E~\x8a%3\xd7@~J\xea\x80\xfc\x88\x89\xbc\x12G\xefar\xe9:\xb16ta\xf9\xcbu\xe2^\xa2d\xc3\xc7\x98\xd5\xb9N\xac\x9a|\x8c\xf5\x7f\x01R\xb5\xf0\xe8\\'VB\xecc\xcc9\x96\x9c\xd8\xcf\x9c`\xd9\xef\xf7y\xc2\xc3\xccw\x02\xc9\x14~\x82w\xdaubPY\x1e\xff\xe7\x7f\x8f\x1bq\x9d\x04\xb6\xf3-,1\xbaN\"\x15\xd3_\xd3\x05;\x0c\xf8!h\x17X\nqu_\x8f1\x82.\xe9\xf6>\xc5<\xd35\x10Z\x87{\xbe\xd4\xc7\xc9\xb2\x18\x08\xe6YKJW\xf8\x14\xa3\xb4\xab\x01xc\x96J\xaa=V\xc0\\7W\xf3\xa1\xa3\xce\xe34\x95\xc7\xf41f\xf6K\xb0e\x9fb\xb3\x8b\xab\xbe\x93\xfdW\x93\xf9\x18\xcb\xa9K\x02\x1086\x90[R\x1b\xb1\xce\xe6J\x7f\x86\xd6\xc7\xf8\x84.\xf10\xe3\xc9\xb2\x1c\xc4\xc7\x98\x1c\xb9\x12\xe8\xd9\x81K\xfd\xc4\xbe\xdfZ\x9f\xc3D|\xe9\x02\xa8\xd6x{\xdc\xa1\xfc\xfe\x0fdC\x87\x1c$\xe5\xbf\xc4b\x98\x84\x8c\x9c\xc4\x0e]\x1a\n\x12\xfa9\xedF\xaa\xcd\xa4\x17\xb0\xe4\xfd\x82l\x00\xa0\xc6\xaf \xd5\xf0\x13W\x91\x1a,\x9f\nP\xc0\x9d$\x89\xf6\xb56\xf2\xce\xffY_\xc6\xe8\"\xef\xfc_\xd6B\x1eX\xc4\x9e=\xc0\xb2\x8a\x02k\x0d\xf8\x01\x96K\x14\xdcS\x06\x9d\x07X>Z\x92\xf0e%\xd0c\xd9E\xd5\x16L\xf5cL\x9c\x15l[T\xfcs|\x9a\xa0\xd9KF\xd2\xc3B:\xc07\xb5\xb0\x87%u\x00\xef\x18y\xcf\xb2\xba\x92c|\x88\xb5z\xd7\x07=\xd3\xb6\x1f}}\x8c?\xc2\x07\xd2\xf5\x93\x11\xd8^\x9fb\x0b\x82\xeb'\xa9B\x8b\x0f\xb1\xcc\xb5$\xd4\xb7}?\xe5KQ\x98Ey\xb2\x1af|\x908\x923\xde\xc3\x87n)\x88R\xbe\x94'\xc1\xe1r\x94\xf7\x02\xfez\x1ee w\x90-1%\x8b2dc\x82\xbc'\x97\xe6\x97X\x0c\x93\x90\xdc\xcf\xac\xc0\xa5\x08\xac\x89\xcf\xee\x91\xe3\xad \x0b\xb6\x1ap\x03\x83Ey\xd7\x80\x88\xfd\x16@\xb7k`\xa3\x91 Y]\xdbw1\xec\xff\x8a\x02\x80\xd5\x12\x16\x14\x8d\xe2>L\x07Kb\xae|\x19a\xc4\x15\xdd\xb6\xd5\x0c\xf8\x01`\xd7\xdbx_\x8d\x99\x90p\xca(\x1chv\x8bI\xddR\x14\x0e\x92\\ux\x1f\x0b\xbaK\x05\x0f!\x18V\x80\xf0\x11\xb3\xe1\x15-#\xb5t\xdb,\xb4\xfaNw N\"\xb8\xd6\"\xacI\x82r7\xb3C76\xaf\nR@d\x9e(>\xac\xfb\x9e\x02g\xc0\xe7q)\xca\x05?i%\xa2e\xa6\x90\xec!\x99M\xee9I\"W\xe7}26 \x93\xeb\xf3>^\x1f7\xe7\xb1\x84<$s\xcdy*9\xc7C\xacM\xb9y\xa0\x97\x1b\xdbv\x01$\xa7\xf5>\xd6A\x96\x94\xbd\x95\xf0i\xf8~\x0f\xab\x9an.\x84b%\xf9\x126\x92\xc7J\xfe&\xd7:nn\xe4e\xc2\x96s#/\x13\x11+\xd7\xf2\xf2\x03K\x83\x11\\\xe4\x91c\xaf\x84\xbc{O,\x02rn\x90\x92\x90T \x92\"\xe0\xfbX\x8dv\x05y\xe7\xb7\xe3\x84\xbb5\xdb\"\xe1i\xee\xd6mN\x12\x1cjc.\xd6\x80$\xb00\xe7\x12\\\xcd\x93D\x1a\xe6?\xc6J\xb7\x9b'c$\xb3\xd0\xad\xd7E\n\x91\x85N\xbc~d\xea\xba\x87\x0e\xaa|\x83F\x04V}\x83v\x0f_\xc5\xb8\x87\x81\x9b \xda\xf3\xec]L\x90\x97e\xaep\x01z\x13Sc\xaf\x00a\xc1\xd4s\x02}\xa3\x81\x0f\xd8\xb2\xdeh\xd2\xdc\"\x00~\x8aq\xde\xd35(\x00\xc4\xb171QXv\xd2!\\\xb0\xe1\xbd\xf14\xe4\x01f\xea^\xc9>\x8f\x97\xd5\xeb\x05\xd2\xd3\xe0\xd7X\xc8X6Z\x15\xde#\xcf@pc\xcb \xb3cv\xe2\xc1g,\x1e,\xdb\xb5M\xf0\xf5\xf8 >\xb3\x9e\xd7\xb0]z\x1d\x7f\x8a\x8f\xf3\xf2r\x94%\x0e\x984\xdf\xc7\x94\xd7\xf3\xa2,\x05!\xe41FQ\x8f\x0b\x0e\xff1\xd6\xe7\x969p\x1e\xac\x18,\xf3\x00\xae\xbf\xc8\xdc5\x00\xcf\xde+\xe9_\x18i\xbd\xbe\x9f\xc2\xd1\xf9\x00\xbb\xe0,k\x85 \x8f\xc0\xd3\x00\xb28\x17\xe0B\xe9\x03l\xeb\xf5\x86\x0ep\x8a\x9fb!Y@`=\xb1\xcc\xb0\xec;n\xe2g\xbe\xeb\x04\x8bun[\xa52\xa06\xfc\x1a\x0b\xa7\x95\x12B\xd6\xd5mQ,,J\x9eW\x9eT?\xac/\xb2\xa3\xae\xeb\x7f\x8d\x8dx\x9e\xefH2\xfb\x10[\\\x96}g\x14\x815\x86\xc0\xbc\xc90#Gcs\x9e\x80\xa75\x10\xb9h\xd8 N\xad0\xe4\x00\xf8\x03\x07\x04\xe3\xdf\xe0U\xf2\xfc\xd4\x97b\xeeCL\x18=y\x13\xf4 \xc1n\x7f\xec\x83c\x83\x1d\x12\x85\xc6\x94\xfe\x90 \x9a?\x8e\xc2\x03+h\xf9\"\x9ct\x8c5\xde-P\xda\xb1\x1c\xe3\x05n\x94\xc8\x81\xbf\x8b\xf9\x9b\x17\xb8\x89|b\xe0\xd9\xbb\x98\x0f{Q\x10H\x94\xfe}\xdc\xbd\xb9\xa9\xc2:\xb2gD]\xacH*c\x06\xde\x0e\xaf\x06q\xa3Li\xc2?&(\x16eJ\x9f\xc1$[B\x94Pq\x1f\xd3\xa0\xe5([\xb9\x9d\x83>8+:f\x01S\x0c\xae\x01\xd8Z\xc1\xb5\x9d\xf4\xd9}\x8c\x1f+\xb0hX\x0d\xe5\xb0fX\xca\xe1\xcbJ\xd2 \xaa\xc9\x8a\xba\x05\xc2\x83\xd5Fz\"cpU\x01\x1fR8\x9f?\xc1R\x1c\xef\xeb\x860cZ\xd1:\x066\xc3p\x0d\xc07FR\x8bz\xf6\x04o\xc5\x8a \x8b -\x19\x08fy| \x89\xf7\x132\xedA\xaa\x8e\xca\x13l\xe4\x05e\xed \x96\xe2VJ\x86_\xd2\x7f\xe0\x87\x19OdW\x7f\x86 \x13\x87K\xed\xb71\x93\xe2\x01\x0c\x0d\xef8\x0f\xcc\xd0\xf0\xda\xaf\xe8\xe8\x0b\xbc\xc6\\\x03H'B_\x94c\xc6\x04IBR\xb8\x86%@\x99ky{\xe4\x04\xc1\xb6\x91\x08\x7f\x81\xe5\xe3B\x17\xb5\xd7\xbf\xcc\x13\xdc\xc6{\xd8Y\x84\x8fRI{\xdf\xc4\x9cS\x00\xe6NH\x10V\xa3$H\xba\xbe\xbdI\xfa]?\xbf\xc0Z\x9f\x91\x83'-\xef\x9f\xe1\x0b8\x1e\xaa\xce1G^\xd1.\xfe\x0474\x80`\x87\xd1\"\xb0M\x8e\x1b-\x82\xe0`\x0cT\xf4!\xc1\x80\xd8IR\xe0\n\xd8*\xc3\xb5\xf4\xfe\x18Sx\xe5\xb4\xfb9&\xd6+\xc6\xd9\xfbs\xda\x8f\x01\xe1Z\x02$\xb6\xf67\x04p[_\n\x12\xba\xc7o\xd7\x931~[y\x97\xdc\xc7k\xcdo\xa7\x81\x13f\x83,\xb1\x1fT\x00\x07<\xb5\x9f\x16\xa3\x07=\xa6#\xcd\x1dy\xc4\xce\xd8\xaah\xad\xdf6\xa0\x9c\xc3\xb5\xe8}\xcc\x92Vn\xe7~\xe0\xf7\x12?\x97s\xf9)\x16\x18JN\x946\x08\xd8\xae\x1ec\xa5\x81\xdf\x1e\x17\x1b\x8e\xa5h\xaeY\xe0\x07d\xc3\x13Mq\xf1\xa1_\xd1nA\xd8\x10\xc55\x00\xf3m\xaeI\x0e\xd1&W\xd4\xbe=\xc6\xd7&\xbcnCW\xc0tE\xf8\x06|&|i\xe7\x82\xa0\xdb\xb8[\xb0\x96~\x82'\xb0\xa2\"%\xc8IV\xdf y\xc9\x13\xe9R\xff'\xd8A\x8a\x1f\xb8\xa2\xc2\x11\xf2\xd9\x87\xad\xbf\x87\xe9\xd1\x8a\x80\xa4V\x10?\x88\xb9\x9b9:^\x86\xac\xfa\xca\x01${\xf0\x9d@^/S\xdeY\x14\xb03\xd7\xbe\x13\x04\xbe\xbc$T\x96G\xc2d\xcf\x81\x98\x80\xa5\xe6>\x88 \x98\x82\xf6\xf9Hu\xf5K|\xf3\xd0\xef\xfb\x10\xf8\xf8\x9f\xff\x06\xcf\xb3\xdf\xd7\x10Z)\xd0 \xdc\xd59\xcd\xe4\xb1\x9c\xd6\xd7\x00L\xe2\x8a\x01`5\xe2\x9c\x1f\x04\xdc\xc3l \x13\\(ec>X\xec\xea\xdf\x82\x9e\xfa\xb70 p\xc0B\x87\xc5\xaeb\x9e\x18\xeb\xfbA\x16J\xf4x\x0f\x9f\xd3~\x18 \x06\xf0\x9f\xc8\x96\x19\x96\x81\xf5\xb3\xbea\x19\xf8\x10\x9d\x8b\x92E\x10'\xee\x91=\x88\x12\xa7\x1e$\xfdX\x1eb\xc3\x87\x00\xc0\xbd\x00\xe6g\xe7\xa2<\xf1y\x92%p\x0bL\xe6\x14;I\xa6\xfd\x1e\xb0\x10\xdaO\x1cW\xba\xb3\x7fL&& \x92\xa9\xff\x04\xd3, \x12L\xfdc\xbc\x9f\x12rJV\xc2\xc4_\x82^\x96 <\x01 zE\x82\xb0\xe0.@\xf30\n\xb2 \x02\x04}aF$@\xd2\xe1\xfec\xac(I\x08T\xc2\xfb%A0\nl\xfa\x13\xa0\x93P\x0bK\x19\x02t\n\xa6\x85e` \x82\x06\xb1=W\x80\xbe\x03 l\x13\xe8'\x0e\xb0\x97\xb7\x08%HT\xe8\xc3\xbbX\x08?\xa7y\x05\xd9{\xa3\xfbb\x81p\xa0U\xaf\xff\x07\xf3\xe2\xf3\xca\x08\xfd9\xdevm\x9d\xfe\x1c\xb3\x17Y\xc3\x13\x12\x08^\xb8\x81\x81\xe0\x15\x18\xc0\xcd\xed\x13l\x970\xa2\xc9\x13L\xd6\x00$\xf9\xfb\x13L\x8e\x15\x0c\xe6\x8a\x91~\xc0S5Yz\xf3.`0\xc8'\x988\x9c\xd7\x1c\x0b\xab\x17\x03\x0d\xc0\xec\xf7\xbcTd\x1fb\xda4\x00? ,\xac\x0c\x065\xc5\xfd\x11l\xce\xdbXx:\xaf\xaeN0\xa7\x1e\xa8\xab\x13\x82qpc\x80\x9b\x19Hg\xcfgO\xc8\x1e\x83\xbc\xf2\x04s\xaeApK~\xc7\xd3\x1d\x84\xea\x00\x92\x05\n\x8b\x98a\x0b\x10\x10\x98\xec\xc5\x9ckud]\x96U}\xaf\x82\xcf\xb4\xaf\x01X\xc6\xf0G\x0eh^\xb6\xb6\x06~\xe8$\x87\xab\xf6\xd5\x199\x83@\x9d\xe8\xb71j\x0b`\xec@\xca$\xbaw#\x99\xc5\xb4\xf5)\xd6\xd4\xfd\x91\xb4<={\x80Y\xb8?\x8a\xa5\xc3\xec\x7f\xc2\xf8\xb4:\x8a\x03\x1f\xd4\x1f\xe2`\xe2\x87l\xc1v\xf9\xe5\x87\xae2\xb0\xbd\x8d\xafc\xcc\xde\xdd\xc3\x8a\xb7\x84\xa8\xd0\xfd\x0f\xb1\xbe\xec\x87*\x87\x06\x99\xd1\xaa\xc2\x12\x82q\xea;\xd9\x8d0s\x81\xc6<\xc0B\x9c\xca\x08\x0d\xb1\x1a\x98\x81V\x9c\x97,\x8d\xf2\xa4\xae\xd9Uy\x11\xc8M\xf6$\x92X\xc4\x0f\xb3\xc0I\x86\xd2 \xf7\x11\x16\xda\xfc0\xd3A\x14\x1fa!q5\x1c\xfb\xa9/\x1d\xac\xc0fb![\xba\x88\x89qz\x0bK\xe5\xab\x1b@I\xb0m\xd5\x8f@\xf4!X\xabo\xbc0\xc1\xf35\x00\xdf%\xac\x1a\xae\x86\xf9\x92o \xd8\xac\xb5\n'\xf9s\xcc\x07\xd5 \xff\x1c\x0b\x16~\xed*\xf9Z\xca\xfe\x18\xb3\xf9U\xcd\x15\xc9\xe12\\\x11k?\xdaC\x92\xe2|\xea\x87Z\xf0&49\xf5A\xc8}HF\x9d\xfa`#~\x88\xbd_%DZb\x1fb\xca$@c\xfb 2\xfb\x0e\xeb\xfcS\x9f\xe2\xcbp\xdf@\x08\xc1\xcc\xf7\x00-\xb0\xee\xe1+\xc0?`s\xe8\xaa\xbaq\xc1\xac\xdbW\xdf1V\\\xd4\")\x9e\xfa-\x0d\xc0\xeb\xa8l\x1b\x18%\xc0\xb4\xf1\xf7xm/j\x06\x86y\xff-\x0d\xc02\xca-E6\xff_L\x1d/\x1a4\xc5\x87\xe4\x96\x81`}\xea\xa2\xc1!,\x94\xde2\x10\x8c\x90\x17S\x9e\xc0d\xf0\xce\xde\xd2\x90\x7f\xc0\xf2\xc4E\xbdQ\xd8\xa6uKo\x14\xe6\xf8\xdfw\xe2X\x9e!|\xe6\xf64\x00\x930 \x90\x97\xbfX<\xf9\xbe1\x8abo\xa5=\x03\xc1\xab\xf9}\x18/\xe9\x1d>\xe3\xbe\xbf\xafw\x0b\x0b^{\x1a\x80\x91zo\x90@B\xa8O\xb1\x90\xf5}\x15\x0d\x8cwdOE\x03cn\xf5}\x85qX8\xd9S\xd64,\x7f|\xdf`\x03\xa6\xf1{\x06B\xea\x18l\xc0\x82\xd6\x9e\x86\xfc9&\x9b\xc1\xa2\xd6\\\xf0\"\xae\x99\xfc\x02\xf88\x04\x06\x82W8pJ1\x04\xf80\x06\xce q\xe0\x16\x13\xb3\xff5g\xd4\xf3$\xbe`\xdc\x0f\x0c\x04\xabOk*k\xe6\xaf\xb0\xf8\x14h\x00\xdeM\x01\x80\xfc\x8e\x98\x11\x05\xc6\xb3\xccR \xcc\x8exC\xd7\x1c\xf9\xe2\x9a\xbe\xc4\xc23\n\x1cH\xb8\xf61f\xf0kZ\xab\xc7RK\xa0\xed\x00\x98\x85\x98\x986\x1b@\xc6\xf6\xfd\x14\x8b\x18\x12\xd2\x97\xec\xe0}|\xf9 `\n\x84e#\x01\x02\xe1\x81\xa8\xa2\x02\x14\xc8\x95x\x07\xcfH\x06\xd6I\x81\xe5}\x8a)\x89\xb6\xe7|\x80y\x8f\x80e\xb2\xda;\x98\xcb\xa8\x1b\xd2'\xa4\xa7\xc5\xcc\xf1\xa1'\x8a'\x06\x84\x89z\xe0@D\xf2\x13,\xfe\x0b\x00\x98\xa8\xfe5\xb5\x18\x05g\xd5\xb2\xbf\x8f\xa9E\xd0\xd3\x10|\x98\x03\x9d\xe4\xef\xaf\xb0n\x10\xf4\x12\xb0:\xfc\x91\x0d \xea\\\xa7\x80=9\xecGX\xd1\x16\x904\x00D\xc6\x1c\x12`2\x8f\xd1#\xcc\xac\xd6\x8c\xb7!V\xd0\x03\x03\xc1B\xca\x9a!\xbd\xf8\xf8\x05\x06\x82\xa5\xa4\xc0\xe5\xb0\x13\xefb\xd6\x13\xb82\x16\x15\xaf\xc1\x1a\x90F\xb2\xa5\xf0\x99t\xec\xb9R@}\x1f\xb3\x89\xc0\xe48\xc4\x84QB\xc0\xe2AN\x9d\x97x\xda\xe1\x143\xf1\xc0K\xf2T\x03\xc9.x`\xd2x\x87l5\x18!1 \x06\xf2r\x1f\x9fT\xe9\xf2/\x88\xcfY\x81\x07\xe01GhP%.\x80\x90\x81\xb5\xb2\x0d\x89R\x8f\x8a\x85\xc9V\xb7\xec\xedN(\x89)\x80\"\x04\xb0,g\xba\xd1\xc7\x90\x1cj\xd1\xd2\x12\xf7\x03H\xc7J\x91C\xc0\xc1\xf9\xbf\xbc\x14x\x19\xa1\x94t\xd7.\xf9\x8dc\x0b\x85.Ur\x1b\xc7\xb6\x9ej\x11\xed5\x8ei\x87(u.\x88\xa0\x8dw\xb1\xe9VLZy\xe0\xeb,\x7f\xc4\x1f\xbeT\x06\x02|\xdf!\xe7\x85\xf73\xb3|\xa0\x1ec+5\x0d\xf8 FaQ\xa4j+$\xf6\x99\x80\x14!\xadT\x8b\xa4\xb5[-\xcb\xa8iA)r>t\xa9\xf4v\xee\x0f\x8a\x1e1\x11\xb6\x05'`\x8a[\x8a\x9e!\xa1\xa4\nV,\x8c\x0d\x83\xab\xd8\x82%\x1d1\xd4l\x98p^\x84\x98\xe1\xd9\xc8FJ)\x1f\x1f\xe0S_.\xa0\x90\xe9CL\x9c\xcbe\x8c}\xf2\x01\x16\x93D)\x08\x92)\x0d\x19\x0b,P\xa8:-|\xa7\x0feJ\xa1\x1aXG(\x17\xd0\x07\x00\xeb\x04(\xda\x03\xe3.\x8d\xf4 \x82\xd0\n8\\S\xfc\x80\x0bi\xba\x19p\xc1CD\x1a}\xf3C k\xc9'\x80\x9e\xbe\xb4\xee\xbb\xba\x99#\xf2\x9e\xf1 x\x8c\xd7+(\xf9\x04`\xedM\xc1\xe4\x1a<\xc1\xb4&\xe0\xa9\x9a\xacE\xce\xe0\xa9r\\x\x82o\xd4\x03\x9e\xa6\xa5\xab;,\x81\n\xb0\xb6\x13`\x0dZ\xc0\xf8m\xe5\xf7jYc\x01\xd5`\xb25kO\xaa*\x14\xa1U\xa2\x08\x12\xb0 \xe1\x8a\xeeHrA\x94\x80\"\x95\xb8\x0d&\xcdC$\xc7x\x00k\xd9\xb6|\x06\xd7\x92GD\x18\xd0~:T\x1eOJ\x04\x92X{\x12\xa5\xc0R\x01=1\xb4\x91\xec\x00\xa4\x00z\x93X>\x12E3\x1f\x10\xca\x98:Z\xf9\xc6\xf8\xb9\xa6\xafF\x88dh\x8c\x92X\x98ZS\xaa5\xa1\x95\xb5\xdfk\xa4\x81\xc08}ac\x88\x80\x80`J8vz\xbbg\xb3\xc7\xa4z\x82\x041Rc] B\x92vb\xf8\x8c\xc8\x8b\x06\x82\xed\xbbk;\x0b\xac\xf5]\xfcQ\"\x05\xe5\x9a\x99\xa5l\xa0\x9d\xce\x08\xdd6Ng\x84\x86d\xb5\x82\xa4T\x8c\x16l:QP\xa8K\x84=e\x9a\x9d\x7f@hQ\xc9U\x8d\x98v4K&t$K\xe0:\x97hK\x81\x0e1&\x89\xf3\x83,\xd1\xeerdRy\xe2\x19\xc3\x0e9\xb3ybB\x90\xc9\nV|\xd0>\xb2H\xf3\xda\x07\xcd\x02S\xb7\xfa\x1f\xe3\xdb+\x13.\x83g0r\x80\x16\xfc%\xd6\xec\x04\x80\xc3\xe3\x1b\x04v \xc4\x89\xf71\x91\x1e\xc1\xf7w\xf0\x94\n\xfeT\x032\x96\x0dl\x1e\x03\xb0a)Xa\x03\xb0\xb2y\xe0k\x92\x91\x93\xec\x01\xc5z\x0f\xdf\xfd\x8et\xb6\xc5g\x1fa\x99\xf9\x12H\xa0\xd8\xbc7\x82\xcf\x98\xbd\x8eL\xca*l\xe5\x18\xe9H\xe6{\x98\xb1\x8f\xb8\x93\xe6 \xf7\x8a\x07\xb6\xb0\xf2q\x89{~>2Ndoa\x82{\x89\x07\x81\x1f\xeak\x01l\xf4\xbe\xa4\xd5\x01l\x88\x1bi\x00>\xe2\xa3\xa1\xdc\x9c\xb7\xc9\xea\xfb\xae\x0c?\xfb\x18K:*-\xe8=l(\x19\xf9\x9e\xfd\x8d\xa2\x91\xef)\xba\xf0\x14\x13\xd6\x91\xef\xd5\xa4\xcf-\xb2\xc0`\xb2.!\xf0\xc6\x16^\x1b \x82\xd1a \x0e@R]\xf9\x08/\x81\xcc\xc9\xaa\x13\xaf\xde\xc3\x8cq\x14\xb8\x90\xad\x10\xdb\x8fG\x01\xb3\xb4g\x1e\x1a\xa3\xb0\x0c\x1e9\xf8%\xa6M\x12\x02f\x85:\x18\xf8\xfc`\x1f\xbb\xb0'\x9d\x8c?\xc6\xd4:,R\xcc\xd3\xb1\x97r\xc9S\xa0\xce$\x89\x97}]\xdf\xe5|\x86\xb7*4\x10lz_\xd7w9\x9fa\xae\x11\x1a\x08\x96:C\x93r\x96\xf6S\xce9k\x19\xb9Jt\x89Q|\x1d\xc88\xd6\x14B\xf8\x8c\x15\xca\xd0Pw|\xbaT\x82_\xb2\xd4\\{F\xbd\x8fYU\xc8\xf5\xdd+V*D% y\xc7\nQ\xaa\x02\x85\x99\x88g2\xfdu>p2\x7f\xcc\x11\x1fy\x13KW\xba\xdc\xce\xd0w\xf7\xa6*\x16N.u\x99'\x87\xcd%Ko\xf5`KS\xc8S\xaer\"a[AX\x04l[&\x9cf\xdc\xa3A%$\x82\x02\n\x96-\x7fD\xde]\xe7\xfb\xca1\xf9\x07!\x19\x82 \xaf&\xf4\x86\x17\xf1\xd5\x18\xb6\xae\xf9.6\xb8\x85\x1a\x80\x87\x19\xea\x988\x8a\xd9*,\x0e;\x16\x86:\xce\xcd\x06\xb8]\xdfX9\xd6\xcd\x06O\xeb@:4\xccRI\xef\x13\x96\x1aB\x1d\xd6b!\xc9\x03\x00a\xb95\xd4\xc6[\x028\x9f\x01\x06=\xa5\x030\xd1\x0eX\xb7\x0cM\xb8\x03!\xacCexx\x8a\xd5\xbbPj\x0b\xf7\x08\x0e\xc3Cq\x0f1\xf3\x0b}\x10>\x1eb\xa9/\x04\x8c'\x0d\xad+\x93'V\x11Be\xf2\xc4\xea^h|8\xb0\xba\x19\x1a'\x0eZGI)XD\x0e\xf5E2]Du\x97\x8c\xa5\xb5\xb0z\x13L\xc7P\xb9\n&\x03\xb1\xdc \x92M\xb2\\!\x92\xed\xd278dx\xc5\x15\x8emJ\xe5[\x1c\x1b\x19jM\xdbr\x0e@\x1b\xa3\xddh\xb5\xf5!&W\xa1\xd1[\x1fbkZ\xb8\xa6\xce\xc8\x13:8-\xc1c6\xb5\x1e\x9dM\xb8#Y\xd8[\x98\xbb\xadG\xa1\x04\xfa\xe1@\x13w\"l\xac\xebX\x11\"\x9d\x18\x01\x16K\xec\xfam62|\xd0\n\xf0\xe7\xf5(\xab&\x95\xc7\x86\xc9_\x01.\x06\x81)\x7fQ\x06\xc5b\xda\x86b\xe3\x9d\x0d\xe5\x0c\xf7\xc4V\x9e\xa2\x08\x0e\xcclh\xadX&\xcc2\xd6\xa3\x8c\x86\xe2\xd8ZB\xf18\x14\xe1\xa3L\xb9B\x13I\\@\x8c/\xb4\xbd\xa2r\x87\xb6\x03\xc7N}\xbb\xf0\x10\xf4C\xac\xd9\x02\x0cr\x98c\xe3\xd5z\x94aO\x00r\xe8Q\x19\xe3\x0c`[\x19\xabG\x00\xa1\x15\xb2`\x0d\x8dS\xb0by1\xd5U\x05\xca\xc8c\x1dHY\xea\xb2\x0f\x95^\xac\xd6\x95+p\x06\x93\xd7\xf5(\xab\x93\x07\x9f\xfc+[sT(|\xf2\xd7\xb6\xadV\xa2\x00\xf6\xc8\x93\x10\x85\x04v\x18 \x01\xd6\xa9\x01\x06H\x805\x8f\xf5(\xdbL\xb8\xcb=\xf5\xd2\x0b\xb6\xf3\x95\xe0f\xad\x9e\xfc\x1b\xdb\xe4t\xb1\xea\xba>\xb4P\xac->\xe6I\xca\xcbD\x0fOG\x94\x92\x195\xcb\xc8IdlTHc\xa7EOA%\x8b\xe1Y\xa86\xe4\xc1\xd9\xce{*\xe7\xdb\x03+\xb6\x97K\x15\xcdYX\x84.\x18\x8b9C\x83\xd6\x01V\xcb\x15Mb\xd3\x97(Z\x8c\xedO(k7\x05\n\xb7\x1c\xa2#\x8b\"\xae\xcb\xb9\x07\xbb\x8e\x0d\xfa%x\xb1\xeb\xd4XQ*\x86v\x1d\x1b\x1aK%\x8b\xf3\xf4\x1f\xed\x0d\x96\x16\xea\xc75\xb3Ck\xf4\xc0\xc23\x8bn,\x93\x93\xc0\x82\xccXx\xa2,Qeg\xc4Z\xa4J\x15=Y\x86\x81\x99?\xd1\xd6\xe3\x1a\xa9@\x00\x9c P \xf1mPH\xcd\xf1\xf4o\xe9+\xb4\xa1\x8e\x80\xbbG\xa5\x810\x8e\x02\x1d\\\x88M\xc9!?}\xc7Z &Id\xcc4\x8f\x1b\x88\xb2\x02\xabI\xd6T\xd6\x93\xb4\xf4\x9b\xa9|;D\xc8\xd7qx\x9f\x10\x8b\x96\x81\x10;T\xa6\xbc\xd1h/\xe8yr\xaa\xe2\x96K\xc0d\xa8\xaeK\x9e/\xa7\x07\xbfRD\xb5C\x04\x0dy\xa5A\xec\xc3\xf2+1\x0f\xcb,\x9a\xbfG\xbfrH\xda\xf86\xbe\x13\x0es\x9d-\x96\xd8\xb3\xc7\xfa='\xcb.^^\xd6\xcf\x14\x12+\xd8e\xf3\x82!\xb1\x18\x8cM-B\xe6\xc6\xa6\x16Y\xc6\xb1N\xbbe\x19\xc7\x18\xf2\xcf\xd8 \x17t\xb8\n9\xbc\xe3\"\xfe\x1d\xdf\\\x85cm\xcbz\x1f\xdb\xe9\xc3\xb1\x8ee\xb0\xf5\x06. v\x88\xb9\xc4\xb7\x815\x0b{\x9f\xd0\xdd\xb1\xe1\n\x0f\xfe\x9d\xad\xa6~[\xf8?X\x80\xfb\xc6\xe8Oh\xda\xbe\xe6\x99\x04\x15\xf65\xcf\xb4B\x14W\xa3\xb0P\x9b\xc7\xf1\xd5\xe1\x86I\x11\x81\xef*\"\x03\xc1W\x81Q\xdd\xf3\x99\x91\xba\xac%\xeffn\xe8\xf4\x11XF\x894\x00kc*\\\x1b\xef=Dk\xff=\xd6\x89\xa2\xda\x1797\xf4\x9bM\x9f\xe1k\xed\xc8@05\x8a\xe0!\x98g\x1fa\x9a\x13\xe9\xd7\xce\xb0\x93V\xe4\xa5\x91\n{\xc2\x96\xdd\x8d\x15H\xbd\xf0\x19\xde\xff\x88+\x00Y\xf8\xbeZ\xc6G\xd8\x95iC\x1b\xfeI[\x1a\x80\x0f\xa6\nV\xff5\xde\xa9\x0d\x93\xc4\x824e \xd8\xa4\x1d\x81\xb1\xfdC\xcc\xba\"\x9d\xa8\xe7\x116\xc3DC\x81\xfd\x9fc9&\xaa{\xa112\xa6hl\x06\x8f\x02\xbd&d\xeb\x03\xf3(\xe1#\xec\xb4\x13\xe9\xc4\x12o\xd2Z0\x17,\xcbn(O\x98\xcf\xb0\n\x1bi\x006]o\x8c\xf8\xc0\xb1\xceR\x01~\x83\x19\xe8\x86\xf4\x8f\x90\xe9\xa7\xb1M3*@x\xef#%R=\xc2\x86\x9fhT\xfb.\xec\x861\x9e\xe2+\xd2\xc8@\xb0\n`\\)\xb1\xf1i#\xe6\xa1\xf5\xc5U|\xbdo\n\x16E\xb0_Z\x14sx\xf0\xf0\x11\x96\x11\x8c\xef%y\xc5vC\x0e\xeb1\xa1 N\xe2k\xbf\xc8(\x17\x04)\xc0\xb3\xf01\xa6\x14Q\xe2\x81\xb5\xe7mL\x8b$\x04R\x8a\xd8`2\x13\x17\x16>\xa2\xc4\x13\xb8\xff1A\xe4\xc4\x1f\xa8\xec$d#\x13\xf5b\"\xde\xc6(I\x83\x08D\xb9\xc7\xf8>7J$\xa9zLH\xb1\xfd%\xe1\x0d\xa3\\\x90\x01k\xc7\x0fB\x89u\x8a\xa4O\xc8.\x1a\x08!\x94\xeau\x8f\x07\xb8\xca\x86\x11\xf4\xf0\xf6F\x06\x82\xa9\xc8F\xe1s\x8bq\xb2p\xc7%\x8f\x1a\x03\xc8\x81zx\xa97T\xb6\x06\xb2\xd2\xea;\xd9\x9a\xb1\"q\xefbanc\xccu|\x11!2\x12\xa6\x82k\x9f\xfd\x19fe\x1a\xaa\xc2 \xff\x94\xac\xfb\x98'\x9bN\xc2\xc3l\xc8S\xb86\xfc3|\xd4\xb42\x85M\x06B\xd7\x13\xd8\x87\xe7Q\xd1\x01-\x95\x94\xb8\xf2\x14s\xfc\x92}\x82B\x94m\x02\x016\x9d\xc4<\xcfF\x81\xc0\xc61\xf9\x8b\xe13&}1O\\\xc91\xfe\x19\x05\xf82\x1f\xca\x0c\x05\x8c \xd6\xf3Mlt\xd6\x94\xe7\x01\x99>O2\x1eJ\x81\xecM\xac\x85lj\xfe\x8ayu\xac\x01XX\xde\x84\xa7\xd2\xb1\x96\x1b\xc3S\xe9\x98\x1c\xc7Cxu\x00\x1f\x8ax\xa8^q\xa6\xfeX\xf1P=\x17\xfd\x17\xf8&tS\xf6\x8c\xe9z,;\xc6\xfc.\xf63wX\x9b';\x86Q\xe1S\x12\x07N\x08\xef\xc7\x93\xa4i\x00\x82\x84jx\\\x02\x06i\xb7-\xd5$\xd1?j\xf9\xec(\xc6\xff\x11\x16\x92\x05\x104\x7f|\xb2\x04D\xd7\xc2\xa6\x04\x01\xf3\xa4\x9aE\xde\x81\x93 p\xf3#\xb8\x11\xe4\xe0\xd3\xfa\x18\x0bE\x9bA\x9e\xea\x87\xd9?\xc6h#\xaa\x8d\xc2:\x88:l\x1f\x11\x1c \xf24\xdb\x97c\xfc\x08\x8b\xeb\xf1\xc8\xd6\xdaf\x04\xc9\xa8\xc4\n\xcba\x92\xcc\x83\xb1\x90\xb9\xb4\xa1\x10c\xd9\xa6\xbe|\xc5bml\xa4\x04l\xbf\x8a\xa3\\>\xf6\xf81\xde\x95M\xb9\xecO0\xd3\x05S\xe4}\xcc\x0d\xe3DE\x18a\xc2nL\x94\xf7\xb1<\x1d\xc3[\xf5O\xc8y\xd0\x96K\xfa\xdd\xad\xe9\x9b\xbb\xa50&:\x02\xee\xaaw\x83\xad\xe3(\xdf\xb3\x90\xb6-\x97,5%\xaa\x96\xf6\xda^\n\xab4f2e\xe3\xab\x05T\x8e\xd4\xc2\xb2\x96\x84+;\xce\x13\xccu%P\x87Ya\xe9J\x00\xb5\xc5\x10\x0fh3Q\x16\xc37\xe9\x16i\x08>E\x12\x92\xdaq0\xd1Qht\xf8p\xc1j\x19z\xc3\xc0\xd5S\xed\x98\x02m\x96\x1ej'\xd4)\x89\xfaN\xa0\x04\x00\xac\xb3\x08\xa0V3\xde\xc5\xca\x94\x00\xa698\\\xbfKx\x87z\x7f\xed\x1e\x96D7\x93(\x8e\x12\x9dI\xed\x1e\xc6\xcc\x02\xac\x12\xb5\xe1\xfa\xa2a\xf0\x9b\xb7\x80\xea\xb6-N\xf2\x04\x04\x83\x07\x98en\x1a\xa1\x11\xdb\xc6bc\x91\xc6\x86\xc9Mx\x95\x87\xac\xbf\xfc\xfc\x1b,\x96\xc6y\xe8*\x13\x17\x06\xbd\xae9,&\xd7\xb75\x00\xef\xc8\xed\xbal\x8b\xafk:\x87\xcd\x13\xb7\x0d\x9d\xc3\xec\xe2\xb6\xc1\xd9\xb7\xb0\x80\xf9\xbaY\x15\xact\xdf6\xab\x82\xf9\xfc\xed\xdc\xc9x\x12\xfa*3\x01\xc9\x8c*\xe0z\xf4\x98\xeb\xea\xd8\x94\xd7l\xdf\x15\x91\xc2\x02\xd5\xeb\xbb\x1b;\x0b\xec\xdb\xado\xe3*Qf\xf9\x9c\x98\x84KX\x9b\xd0B\xec\xbd\xbf\xfd;\xcc{\xb6\x8c/5\xde\xa0\xc4@0\xc3I\x1c\x0f\x12\x90\xde\xc3;\x91\x94\xb34a\xfa\xb1\xa5c;1\x1a&\x1a\x80u\xf0\xc4\xa4U\xc2'S@\xe4\x94\x1ea^\x9f\x14 \x97hs*s\x12fo[Z\xd9\xc4R\x97\xb9\xfc\xa2\xfd\xab\x1a6\x00\x10\xbc\x0f0]KLR%:\xe6\"\xa9\x12\x19Bq\x97f\x81\xa8JX\x84J\x8atKXQL\x8atK\x18\xf1\x13\x93n\xe9\x03L\x0f\x92R\xba%\xac\xe9l\x99tK\xefc\xa4O\x8aLLX\xd2(]\x03\x92E7 \x97\xb0\xc2\x94\x14\xb9\x98(\xeae>\x10M\xac5IH\xa8\xfd\xe7q\xbd-\x93\x8d [\x18\x13\x03\xc1\x1c%1y\x9a0\x05HL\x9e&\xb2[:O\xd3]\x1b@\xd4\xb9A\x01*O\x13\xa6\x84I)O\x13\x16\xd3\x93R\x9e&<\xa3-\xe3\xa7\x8f\x15\xfb\xc4@0\x03\xdf2~\xfads\x0d\x04\xd3\xd6\xc4\xe4i\xc2\xc6\xb3\x04\xf24\xe15\xd8\x02\xcd\x91\xe0>8\xc3b\xad'\xd1y\x9a0kM\xbc\xc0\xa4\\\"\x87\xdf\xe4p\"\xf8V\xe4p\xa2 \x15\x17Jh\x19\xc8\xe9\x04?9\xf0t+@g\xc9%\xd4\x99;\x81\xc9\x92k\xab\x08\x88K\xc6\xc6A\xdey\x0f\xeb\xae[+\xe7\x05\x91\xc3|5\x81W\xfe\xf1g\x8b\xff\x0fvV\xd6E\xd03r5\xc5vcT\x90<\xb7\x9a\x14\x890\xb0=\")\x12a\x90\xe6U\x0eh\xb2BZ\x90 \xdd\xe8\xc4\x16\xf8\x16\xdb\x84'\x93\x17\x7f\x13\x9d\xd8\xe2\xa7\x04\xe7\x8a\xc4\x16\x98ln\xc98\xba\xcf\xb1\x8e\x95\xc8\xcf\xbf\xa1]DR+'\x8cX\xc6\x88\xe3|]\x18\x8bQ$9\xe6>\xc8}\x820\xa7\xaa\xf7\x84\xb5v%g\x17fTE\x89J\xd4\xfbO\xf1\xfd_\xd1\x91I\xda\x85\xe9\xbfl\xaa\x9c\xb5\x0b\x93\nY\x80\xa6\xed\xc2*\xb5*\x86\xf3v\xe1\xd3b\x8a\x95\x12wa\xb3\x16*\xa3\xf3\x0ea\xf1G\x16;W\x8b\xa7\xe5\x04V:\xc2\x95\"Z\xa9\x10\xf8\x06P\x8c\x13EP\xf6.\xeb:\x97\xf2\x80A)\xc2.D)\x9c{\x8bPf\x9ff\xd4\xb2.\xa2N\x97\x85em\x0d,\xb0\x13[F,\xcfr\x13Z(\x8a\xa0\x8cYx:\xc4\x17\xf1\x01\xa1\xceVG\xc4\xa6B\x85\xf7\x1a\x96\xdad1\x925\x0bK\x04\xaaTur\x98R\xa9B\xa5\xa4WX\x8b\xab\x94\xd0\xf8\x87\x05s\x94\xd3\x8c N \xae\x9b\xc0\xbak\x02\x87\xee\xd7D\x88\xf2\xd3\xea\x83\x8d\xa4\xa2I\xa6CP1\xd0\xe9 \x08\xfa\x05\x90\xf3\x81HQEf\x1bL\x0c\x93jf\x1b\x02\xd6\x81\x0cO \x933 d0WLL\x02\x19\xbc\xe8\x89I \x83iKbn\xd3\xb0&\xb8\xa5uQ\xc2\x95\x8d.J\x04\xde\"/ \x1duqGB\xf0/\xcaC\xaf\x94\xe0\xfe\x03\xac\xde'0\xc6\x8e\xe53\xdc\xf8>\"\x9a]\\r;$<\xc2d\x03!\x04\x19\x85\xf0\x90\xb3[d\xea\xc0\x06\xb5-};E\xebh]\x1b\xfb\xc6l)\xc9\x8b\xec}\xedw\x99\\\x83\x08\xd1&\xb9\x06\x16l\x93\"\xb9\x06\x01\x15\xa9)\x082\x17t \xc7ni\xdf\xc3\xf7\xb0\xa5\xab\xe4db\x81H\xc2zE:\xe2\xc5\x93\xf7d\xbc\xb5\xe8:\xf2a0\xefR\x88\xdc\xc9'd'G*\xaf<65\x08\x00\x84\xaa\xfd\x0d\xcd\x02\xb5\xbdqn\x07\xce*\xa9\x16\xf538\xadX\x9c\x01G\x9f\xe3\xf4\xab$\xe3\x1fb!_\x00\xd4E\x1aa!F\xf0\xc5rQj d\xc9bG]\xc1\xfe\x92\xa0\x99\x04\xe9w\xfd,\xd0\xc4z\xf0\xd3\xdbJ\x96x@\x98\x9f\x80\x80\xaf\xd1\x9f\xd3\xb5Ko\xab\xdc!\x0f\xb0\xb0,!P\xefg\x965\xbf\xad\xfcg\x88\xd4t[\x076`\xb5\xa7\x08\x94x@(\xce\xedR\xf8\x82\xb5^\xe1\xd7o\xab\x0b3 \xb4\xd4D_<\xc04P\x82L \\\x0dPuH\xebJK\xd9{\x98\xd5\x97^\xae'R@=\x08j\xe1g\xa8\xc8.\xd2p\xc0\x86\x02\x85R\x8f\x17\xcb\x16\x06\xd8X\xa4h\x8a\xb0\x11Yn7\xd4#\xa6\xf8\x93;p\x83L\x1e\xf2Oo\xe75\x80\xda\xeb\xa5msk\x89u\xc8\xd4hR\x98#\xa7\x0d\x02I\x03mJ35\xee\x87\x98jogp\xfa\x08 U\x80\xbf\xb0\x01d[\x7fAD\xc6,q\x04\x9f\xe6q\xea\x07r \x7f\x83\x95$]D9_as\\\x9a%\xd2\xeeE\xb2\xdfm\xc3\x01|H\xf0Z\x1dL\xc2r\xf3\x9e~\xb3\x9b\xa8\x0e&\x16\x89\x02\xe0d\x91\x19\xe7=\x9d\xaa\xe7)\xe1\xbayo\x94\x83\x07\xf3S\"[\xe7=\x90\xfa\x9fb\xbb\xa2\x80@_\x84\xc0\xe6=\xcdE\x9f`\xb2\x9c\xe6=\xc3E\xb1^Z\x1c#\xdb\x1a\x990*+H\x11\x05\xcb\xb4\xcb\x11T\xd6\x0e\x8b\xb3d\xaf\xad\x12\n\xdb\xa6 \xd0\xdbu\xeb\xa3\xfd\x1f\xb1-A\x80`\xd3\x9f\x12\xec\x11 \xc8\xf2F8\x86\n\xf6\xa2\xfaj\xee\x96]\x8f\xb0\xd6*\xc0e\xd7#\x8cL\xe5`_\xd2\xb6%\xd2\xb7\xa6\x04r=\xaa\xeb\xa5\x14\xe1k\x19\xa7\x0eY\xb3\x80\xca\xaeGD5\x15p\xedzD\xd4S\x01\xacUPs\xb7^\x0b\xcd\xdd\xe1\xce\xd0\xb1_Bm\xc3e\xd2=\xc2\xf7j\xbf\x83!\xf0\x97\x98\xb8n\xc3v?\xa4\x15\x80}\xd2\xd3\x1a\xcf \xf2\x82OO\x9a\xc7\xf3\xe2;\x91M\xf3\xf8\x84\xf8N\x84\xc7<\xd6\xe4\x05[ \x05H#(\x11XM\x84 \x05\x009\xa0\xd8\x1e\x1b\xd2\x83\x05\xb8j@w\x0d\xb08\xa0\x96\xa6\x87\xca7\xfcWXQ\x9405 |!\x9c\xe6\xb1I\xdbJOSl\xa8!\xa55\xb1\xa2\x86Dp\xcdcE\x0d)\x1d\x8855|J\xc45#\xed\xd8\xb6\xbfn]*b\x90eI\xca\xe1\x94V\xa8\xa6h\x96\xa1\x96)\x9ae\x8e\x9a\xa2\x11\x9e\x9e\xc7z\xad\x89\xc0!@@\xd1\x08\xbb/b\xd6\x88\x19\xc6\xc4\xacachjb\xd6\xac\x90\x9a\xbc\xd7\xe9~\xa8\x8d'D\xba\xb9\x03\x91S\x9f`=q\xc7\x113\xfaA\x86>gN2\x80\x9dy\x17Oh\xc7\x91!\x9aX\xaf\xc8\xe4\xe7\xdf`\xe4\xcf\x94\x9d\x9f\xf8\xea\xef\x18k\"i\xc9@\xb0\xa6\xb1cl\x80\xd8\xfe\x92\x19\x08\x96\xa9\x94zF+H\xdd\x0c#\xbf\xce\x9c\xfcclw\xcdx\xa0\xbcb\xdf\xc5\xeclG\xdb\x8b\xf0 \xcc4\x00\xdb\xcd\xb3!O\xf8I\xd1\xd8=\xb2,\x02\xd4\x8f@b'\xd0\xac\x11\xba3\xe4\xf0\x06*\xa6g\x99\x06`\xb6)\x01\xe9\xa1\xc0\xf7\xdf\xe0\xc3)ac;\xc4w\xf7J\x197\xf1A\x91\xf0:cJ5\x03\xe2[\xbf\xa2/\xf5gC?T\x9e\x8d\x98\xdeU\xb3\x1dbh6\xdcS\xb1\xbdtD\xf5\xe3\xb9\xb0\xb1\xb5.N\x066\xc7d\xc3(\x11X\xf8 \xe6\x1c\x86\xbb\x93\xb6t<\xce\xaf\xb1%\x1a\xa5\xdb\xc0\xc4\xce\x92k\x03\x8bq(\xd1\x06\x99\xa0\xba!\xf9\x84\xe0\xa0\x00\x80\xec\x8d\x15z\x00\x01\xc1\xf8\x88\xa0\xa8\x00\xc2\xbb\xb9XP\xc9\xea\x1e\xe0\xce\"\x0e>B\xd8n\x99\x81\xd7\xee\x03r\xd2\xa3\xb8\x07\xe7\xed],\xd0dQ\xac\xd3\x18\xe3\xa1\xed\x18\xdb\x06\xa6\xed\x99\x81`\xca! *d\xe3)6\x1bdQ\n\xc3\xc6rSVx_\x93\xa3\xb6\xb5\xb8,\x99\xe4\xdb\x84\xb0$\x0e\xec\x91\x05R\\\x9f\xbf\x87\x15.\x0d\xd4\xde\x0b\xefaA\x0d\xc7\xee\x93\xac\xea4t\x9f\xa4W\xd7E@F\xc6HJ\xe2\xfa\xc9\xa5\x9a%\xac\x9f\\\xafe\x89zU\xe5\xd9/\xb0IL_\xc9\xd9z6\xb6\xc1\x8f\xb0\xdc\xbb\x93\xf8q\xc0\x97\xeb\xe8\xb2\x80\xaa\x9a\x96\xe1\x02\xea\x7f\x88]\x06\xb3\xc4\xcf\xd4\xd6~\x84e\xa3,\x89\xf9\x1d\xe5F\xf5gx\x0fw\x8c-\x00k\xbe\x99\xb1\x05\x10\xa2\xa5nz0\xfb\xcf\xd4U\x0f\x96_v\xb4\xf9\x9f\xa0\xb7\xb6\xff\xe3E\xd81\xcf\x0f\xd0>4\x04_\xc0d\xfb>\\\x8c\xdc'\xdb\xb4\x1f\x0d\xb9\xe3U\xf3K\x12\xea\x08\x85\x90w\x13&1\xbb& \x1e\x1f\xba\xdc@\xf0~\xefj\xd1\x07\x8b*\xb9\x96\x960?\xcau\x0d\x0c\x10M\xe9\x00\xfb\x0f\xf0\xb6\xec\xf6\xd4\x93\xca\xf8\xa67W\x80\x7f\xc0s\xde\xed%\\\xc6y\x7f\x86\x97,7\x10L\x13wu\xb4>\xde\xb3\\\x030\xfe\xed\xc2\xa8\xb0\x1c\x93\xc3\x98\xf0\xa9\xcf=\xed:\x809\xc6\xae \xd6\xc7\x04<7\x10LZs\xe3\xca\x89M]y\xe1?\x88\xf9\xe1\xae\x16s\xb0\xd8\x91k\x00V\xd7vM\xc0<\x16as\x03\xc1\x879\xd7\x9e\x85da\x86N\x02\xeen\x98d\xe6& -\x1ern\xde\xc5\xc2\xdaJ.\xdf\xa7\x12\xa0w1\x95\xca\xcbOWY\x80*6\xe5]l\x1e\xcd\xcdC\x18X\xfc\xda\xd5\x11\xf2X\\\xcf5\x00\xbb\xedC\xb0\xed\xc7\x98\xc1\xee\x86\x9e\x8e\xa9\xc5\xef\xe5\x00\xc8\x84\xd4\xe2Ce\xc0:\xa6\x16\xd3sY\x00\x07\xd5\xe2{(c\x8a}\x88\xf1SBt\xb6\xff\x07\xf8\xa8\xed\xaad\x0b\x9fa\x0c\xc95\x00k\xf4\xbb\x86\xc5c\xcd-7\x10L\x04\x9b.\x1cw\xe3\xc2\xb9\x86\xd0\x95\x02f\xa9Wv\xda|\x1f\xdb\x8c\x15\xb8r'KOh\\\xbd\xb3\xc5\x8a\xc5n,\xa4\x81b|\x18\x9eW\xe1\x96\xfa\xd8+\x98\x9c\xeaX91\x9aw?\xc8\x19\xd2%\x8a\xa7\xa4\xc8a\x8ak\xb77\x8e\xf1[MX\x9b\x94E\xd0\xad1\x96awU\x08\x14^\xe4\\}\xc7\xeb*\xbe\x0fm\x15v\x8d\xc1\xfbs, \xe6\x85-\x9cn\x93v\xbf\xc4\x95$\xa4\x187mSa\x10x\x7fb\x99=O\x0c\xa9\xc1\xe7)/?\x02e\x01jRC\x16\\9\x19~F6Z\x03\xb0\xd8\x92k\x0f\xaa_`\x82\xbbkD\x1d\xc2?\x8c\xa8\x83U\xb7\xdc\xbc<\x84\xeb\xecj\xdd\xe83L\xbbr\x03\xc1\xf2w\xae\x9d\xbb0M\xca\x8d\x0b\x17\x96ps-\x0b\x90\xd5\xdeUy\n\x08\xe1V\xdf\xb1.\x97\xef\x1ba\xfd\x11\x96\x9d\xc6N8\x80;\xc8G\xb8\xb9\xb1\x934\\\xab\x8c\x9dD(\xce\xd2c\x01\xaf\xd0\xd8I\xc2H\xe8\xbe\xf0\x9a\x06\xc6\xc2\xb1\x93\xd4\\\xc6\x08\x88o\x0b:\x17\x80\xfa\xb8\xc6\xb1\x16\xa7,\xed%Vz\"\x00\xe0`\x8f\xe5\x86\xb1\x93\x18O\x0clR\x11\xb0\xea\x1d\x03\xbd\xd2-\x97Q7\x0d5\x85*\xa6\xbd\xe62\xca\xc0g-\xa4-\"\xc4\xb6!`H\xd3\"\xaf\x03\x97\xca\x18\xaaH\xfc\xa1/+\xcd\xfa)f\xe1c\xc53\x9e\xe2\x83 \x002\x8a\xef)>\x08\x97A$\xc4\xe4l\x0c\x9f\xf1\xf0\x8a$f\xb8\xeb\"\x87\x19\xee\xa1HaFFe\xea`]H\xb6&%\xaf\xa7\x98\xe3^V\x9e\x9c\xf8\xa6m\x0c\xdfI\xea\x991\xe7j\xb9\x1e`qx\xcc\xb9\xd2W\xb1\n1\xe6A\xe0\xc3\xbd\x02&w\x97y\xa2\xda{\x93\x1c\n\x0d\xfa\x11\xad\x93\xd5\xd5\xc8j\xca\x97\x13\x9bb\xb9T\xc3\xd5\x13\x17u\xd5\xb7y\xec$\x8e\xf2+\xff+,B\xebR\x85\xe5\x07#3}\x04\x04\x13\xe5\xcbZ\x0c\xc7\xc2\xf6X\x030\xee\x8e\xb5\xc4JQ\xdf\xe4\x8e\xb4dz\x1c\x9b\x9c\x8b\x96\x0c\x89\x97\x8dx\x86\x95\xf1\xb1\x81\x10:[\x1b\xef=6o\x17\x92sg\xd8\x16!R\x86ma\xc5z\\\xba\x01\xb6\x90\x8b\xd2-\xb0\x15j\xeeKj\xa0\xbc\x8eZ].\x0e\x17\xd6\x00\xc6w\xfc\xc1\x1dG\xb2\x82G\x18\xf1\xafh\xbfV\xcc\xfd\xf65\x00\xf3\x9d}\xee\xa9\xf3\xf0\x18+\x00W\xb8\x07Q\xbd\x0f\xf1\xe8\xf65\xe4\x1e\xde\x17 \x81C\x89qj\x9f\xfb*[\xcc\xdb\x18\x97\xafht\xc3\xf3\xd9\xd7\x00<\x9f+\x063\xb0\xa0\xb3o \x98\x94\xec\xdb;\xdfO\xac\xa7g?\xe1N6\xb4\x82\xae\x18D\xc2\x87`\xdf \x12\xd6A\x0e\x94'\xd4C\xcc\x04\x0f\xd4\xce<\xfb\x05\x16\xc0\x0e\x94\x13\x14\xd1\x9c\x0e<-\xfe\xe0k\xe67\xf4za\x9b\xc2\x81\x06\xe0\xfd?\xd0\x0f\xb5\x90\xb7o\x0f\xb4\x8eL\x9e\xbb}Cf#\xc06\x90\x03\xf9\x15\xab\x00\x07:\xbd$y\xcb\xf7@\xdfA\x927|\x0f\xd4\xf3d\xe4!\xdd\x03\xfd\xe2\x0bf\x05\x07:\x99\xe0Gx\xaf\xde0\xe8\x80\x95\xef\x03\x03\xc1,\xef\xa0\x88\x0d\xc1l\xea 2\xd6A\xb2\x91:<\x9d\xbc\xdc{\xa0}>\xc8\x83\xbdo\x18L\xc2\xc4\xea\xc0`\x12&\x8a\x07\xc6;\xee#l\x1f<0\n\xd7G\xf8\xb6\xed\xc0\x88\xcc\xa4\xa7q\x0dK>\xd8\xaf%\x00W\x8d\x8d\x0e\x93\xdfC\x03\xc1\xb8yu\x11\x84\x12\x8c\xe6\x87\x0e\xd8\xaf\xf0\xfe\\\xd5$\x0b/\xda\xa1\x06`\xbc\xbc\n\x1d`\xd9\xe6\x10\xda\xc7\xa4\xfd\x90\xcbdBX5\xbb\xaaO\n\x96\xdf\x0f5\x00\x8f\xe7\xea*\xf4\x8b\xef\xa2\x0f}\xe8\x18+\xadW\x0d\xe2a?\x9fC\x03\xc1D\xff\xaaA\x14L \x0f\x0d\xa2`JxU\xd9\x0b\xb1\x08t\xa8\x0c\x86\xa4<\xe8;\x9f\xe1\x83z\xa8\xf4 l\x00\xb8fBQ0\xc2\xdf1\x10LT\xae\x99\x1b\\\x8c\x1ew\x0c\x04\x93\x90k0\x0d\xbc\x8cw\xe03F\x82k\xea\xe5vL\"\xee\xa8\xef\x98\xa6\xdc\xe1\\?\xe2\x89\x19\xc65\x9eDW|/\x1b\xd6?\xa3vM]\x9fb\xc9\xf0\x8e\xfa\x8eq\xe5\x9a\n\x9b\xc6]\xdd\xd1\xc8E\xa6\xa3,\xfe\xa4\x030\xf8\xff=\xee\xe0\x8e?0!c\xf8l^\xd3ar\xf8\xb6\xed\x8e\xc1;|v\xae\x19\xbc\xc3D\xfa\x8e\xc1;|p\xef\xec\xdf\x92k\x85 \xd7\x9d\xfd\x10\x00\xef\xb6\xcc\xf7\xbb\xf2\xaf\xbb]\xd6\xcfC\xe9g\xda\xe6]\x96uY\xd8a\x7fd\n\xb5\xf2\x94\xb34K|7k\xbdj\xbe\x8e\x9d\x84%\xec\x0c\x0b\xdb'\xe7^\xe9T\xbb\x8a\xe4\xf7\xf9\xeftf\xf2\x90\xa7\xae\x13\xf3K^Q\x93\xcf\xf0\x838J\xb2\x94\x9d\xa9\xf6[\xeeTw\x11v\x99\xdfeN\x97\xe5\xec\x0c\xcb\xaa\xdd\x88\x9fh\x84\xcf\xc4Qz\xc99x\xb5\x02\xf5\xfb\xac\xfd\xf2,;sF\x14H\x13w\xc6\x1d:\xc9R\xe4\xf1\xc5\xac\x9dup_\xe2\xd7\x8f\x12\xd6\xce\x8e\x1e}\x95e\xec\xbb,}\xd5VF\xb7<\x07-\xb7Cfo\xbe\xc3\x12\x9e\xe5I\xc8\x8e\xcc\xbdZ\xdb\xc8\xcb\xf3\xb2\x91\xd0\x14v\xd8\x19\x96\xb4\xa36\xb4\x98\x06\xbe\xcb\xdb9;\xca\xe6\xc4\xeat:]v\xe4\x08\x9f\x89\x9d$\xe5\xc9\xcc\xd8 |\xcf\xc9\xf8\x9a\x1f\xee\xb5\x9d\x0e{\xe9%\xd6\x96+!\x16\n\xea\xf0\x99\xc0\x0f\xf7\x96\xa20\xe3a\xc6\xce\x88e<2\xdb\xb1\x8f\xe7\xb4\x1a\x8bhGV\x17K\xc0^\x13\x7f\x9fa\xf3l\x81eG\x8f\x92\x8aw\xc9\x173\xebo\xd5\x97\x93\xeb\xec\xb33lV\xad\xb4\xe8\xf3\xc4<;\xd2\xb4\xa0\xa2\xcc\x91v\xc8\xbe\xc7^\x11\x7f\x86\xec\xbbl\xeed\xe7\xd5\x0e\x19\x81XX\xebd:j.t\xfe\xfe\x83\xf4\xe8\xf1A\x97\xb5X\xab3\x93E\xf2\x0eg\xc9Iy\xfb\x85\xe0\xf0F\xef\x16w\xb3\x19\x8f\xf7\xfd\x90o&Q\xcc\x93\xec\xb0\x9duY\xeb\xe6M\x9e^\x8a\xbc<\xe0\xad.\xc1\xd6 \xe7\x0b\xec\xc8l1\x82N\x97\xc9V\x9c<\xc8\xca\xd3\xac\x99%\xc5\x147\x1a\xc5Q\xc8\xc3,]`\x8en\x89\"\xfb~\xe2\xc4K\xa5\xa2y}\xd14s2\xbe\x19\xe4\x03?L\x17jXA\x1as\xb7\x0e\xc6Tw\xdb<\x90\xb9&\xd2\x05\x96\xd0^\xf4/-J\xf9\xd6Bw\xedu\x9d<\x1b>\xc7\x08\xa2\xe7i;r\xd2\x13Mm;r\x8f\xd2\x05\x96\xd6\xcf+\xe1^\xeer\xd1\xb5[\xbf\xd4\xfaWZ\x84\xc0>P\xf2\xf5n\xcd)\xbcK\xe9l\xdc\x0e\xdb'\xe7\xe7;\x16\xc9\x14@'0\xc87\xa0\x93\x18$\x88W_\x82NaP\xaeA'H\xadT58\x7f\xe2e\x0c\nt_'\xc9\x08]\xdd\xe0\xc9\x13\x9d\xce\xab\xdf20}JX\xbf\x9e\x1c\x08\x02\xc6g\x8a\xc3\xc8^c\x9c\xd96Um\xce\x02\xe3u+j\xe98\xa6\x1d\x0b\x92Mz-\x88t\x95\xd4j\x0e\xfeGw)\xbb \xf3 `G\xce0N\xe59\xc9P$\xcfc~\xc8xG\x93\xa18\x89\xb2(;\x8c\xf9\xcc\xd0I7\xf6CM\x90f\\'\x08\x04Q\x0bA\xd6\xc9\xae\x877\x04S\xb9\x1e\xde@|N\x0d\xb3L\x8b\x04-,-\x02\xfbF\x90J?\xdd\xdew\x06\x03\x9e\xcc\x0b\x8e7\xe3\xa7\x1b\x8b\xdb'\xe4\x9f)O\xc6\xb7\x1b(\x82\x103y\x91\x942\xc5#KtY.\xddJ\xa4\xec\xaa\x93\xe6\xc7\x03&\"\x99\xb0\x90\x00\n\x17^l\xb1\x97{fz\xaek\xcd\x03\xcc\x9f9o0\xefp\xde\xa4=/2+vD\x00\x01 \"\x80$)Y\xd5}\xb0\x96\xad$\"\x10\xd7\x1d;\xf6}'a\x00\x9b*\xfaf\xe7\xbe\x92\x1bl\xbf\x0d\xf1\xed\xd6\x8e\x12\xc6}-\x8cW[\xd1\xde\x07]=\x1d\x13W\x0d\xd8;#\xc5\xe1U^\x10z\x91R\x1c_aP\xfc\xeb\xbb\x9c6\xa2&\xday_\xf6\xa6\x0b!\xdf\x16\xc7\xce\x1cz\xec\xcb\x85\xcdc\xa7\x851\xd5\xf8\xec\xa3\xcc\x94\xf7t\xc8\xb0/\x9fq\x03\xf4\xc5L\xd94s\xb7\x89\x85\xf1o E\xe3\xdf\x12\xfe\xc6\xbfk\xdc\xce\xfe\xac\xd0\xfe\xddLI,e\xffvUw\x8f\x91C\x1d\x82\x83)\x84\x13\xbcXn\x86\x7f\x95\xb8\x17\x87\xed\x85\xf9K\x1f\x89\x15F\xfe\x18\xcee=\xbd\xce=\xfb\xb9MP\x0c\xed6\x93\xc4_\xbf?=#\xe1\x9f\xa3\xe4IY,\x92,\xfc\x99\x18\x88\x8a\x9cR\xd1JZ\x9e\x96\x8c\x1e\xa8Hy\x05!\xe2+ \x91\xd2D\x88\xe4\x9f\x86\xd8\x16\xbf\xe8\x84#\x0d\xaan.\x95-\xee\xceP\x7f7k\x87.\x83}\x7f\xed6\xccvq\xab\x8c'\xdc\x01\xc2+>t\xdf{\x11\xe6\x85\xd3\x06\xfe\xeav#q\x91]\x1d\x92\xbf\xdb\x8e7O\xb2\x03\x7f\xb60\xcc\x0d\xa4[\x93\x1d\x06\xbe\xee\x0e\x1d\xc7\xd8Q3\xa2\x14R\x8a\xe9\xe6\xb1\xba\x14u\x0e\xd3\x91\xa6\x94\xe2\xdf\x92Q\x01\x94\x0d\xb1\x14g\xd8J(\xcb>\xb6P\xbe\x84bn\xfe\xc1c\x7f\xf6}D\xf7|\xd2\x04\x00m\xfdk\x0d\x03\x11#\x03\x92\x96\xf9\xc2\x8e\xc9\x05\xf8\x14\x81\xf3\x1b\xbd\xda\xd6_\xaeQ\x056\xf3\xe6aT\x90l\x00|@}\x88\x18FE\x91-Q\xd6\xbdv\x1cG\xc1v8.X\x8b\xa2H-\xfc\x14!\xd7\xf2\xd3\xf0\xcf\xe4J\xbc\xa1\x84\xc2\n\xc3/;\xfd\xd0>\xe2?\xc8\x7f\xadt\xe5*\x99\xbfJV@o\x8d\x8a\xad\xf2\"\x12\x9f\x15\x0b&2\x7f\x92e\xfe\x95\x9d\xc1c\x18\xc1>d\xb0\x01#\x98\xc0\xa6\xe3\".\x18=\x82\x10\xbe\x82\xec\x11\x84\xeb\xeb\x0e$\xd3\x90V8\x96[\x9b\x86\xc7\xdd\xcd\xa4}\xfaws\xd9\x97\x155\xe3\xd3\xcb=j1\x8b\xd3\xe2\x98\x92\x8b3\xbf\xb0\x13\x87r\x93mV3\xd1^\xff\xac\xe0\xf7\xbf\xff[\xf2\x8c\x9a\x9a\xbdK\xa1\x82\xdc\x06W\x1f\x0f\xe3\xebVe\x91\xef\x84\x8d\\\x99\x81\xbd3\xd6y \x03+\x13%\xf5\x86\xa1Z\xa7GB\xa0\xd5\xe4E\x1d\xde\xd6\xc8\xd7\xe6m\xbev\x18\xf1\xb2\x12\x8f\xe3\xf6*#\xccK[\xe1\x9fB\x89\x7f\xe2\n\xff\x14\x1c\xff\x14\x12\xfe\xc9\x18\xfe\xc9\xe0+(\x1eAF\xf1O<\xcd\xba\xf8'\xd3\xe0\x9f\x04Ug\xb7\xc6?\x127E\xf1\x8f\xdfB/1\xc59]\xd1\x8e\xe9\x88\xaf\x84\xd7?)+E>gV\xa9\x8b\x07\x99\x0e\xa2\xa3MH\xaa\xa2\xfb*N\x88\x15u\x98\xa4Z\xa9\xf1P\xaf\xd4\xd8T)5X\xd1H%\xcdcEz\xa5\xc6\xd6\xef\xab\xd4\x10\xbfd\x91\x7f\xb3\xa1\xa7~\x14\x9d\xfa\xb3\xf7\xf9\xa4&b\x9as\xf9\xb6(\xd2'\xa8\x88\x8b\xd4\x15\xde\x12Lc\xf5u\x12\\Mj\xfa\xbcY\xe7\x90a#\xad\xfa\x92\x97?M\xe2\xc2\x0f\xd1\xdfL\xa3\xbc\x94:;\x08B\xf4V\xc8\xd55_\xa7\x84%\xff\xa9\xfa\xd6(\xe9\x12Q\xf1E\x18\xbf\x9f@(j}\xe6\x87\xc3\xb7c\xbb\xab\x9fKxI\x07\x90C\xbc\xbe\xec\xd8\xa6p\x8cUF\x14l\x91\xa8XQ'\xf1\xd1A\xb4\xff.%\xa8\xf5B\xc0\xedr-\xb1\xb8\x18*ex\xb7\x0e7\x0cI\xc9\xec\x8d_,\xba\xe5LJbU@TA\xa6\xa5\xb0)\x0b\xe7`\xaf\x15\x95\x1e\xb0:\x03\x9cH\xe0\xe9ul+O}J\xf5\xd0\xdb\xc4\x05\xebU\x02\xd5$\xda\xcc4\x9d'SI-\xfd\xb4\xa6-z\x94@\xda\x8e\x83\xf0\xbc\x03e\xe2yO\xae&\x12c\"\x9ekW\xdf\xdcb\\\xcd\"\xc6\xeb\xaf=\xc8\\\xc7\xaa\xf1\x81Z_|\x91\x91\xb9\x10\x13\xecc[0\xb9\xd9\xf8A\xcc!W\x16_\xab\xc6\x17\x99XI\xba\x9b\xf2\x00\xa3jc\xe90\xd5\x8c-\xf0=\x9bUR\xaaa\x02\x83\n\xf7LZ\n\x0c\xf9\xd1q\xd3\xd0\xbf\xf3\xa5\x0b\n\xfe\x94\x98\xd6\x12pX\x13\x98\x99\xc5\x01\xb8\xe4Q\x8f\xc8\x00\xfd\x86,s\xa5%)\x16I\xd0\xdbV\x8a\xee1=\xa2\x15q\x9e\xe9=\xc3\xd8t\x17r\xba\xdd=\x12\x99(J.\x8e\xb2\xab\xe7\xc5\xeb\xb2\x98\xb4\x8d9\xe5\xe7Z!<\xd0\xbdo\xbfko\xe3\xb0C\xcb\x8eY\xfey\x194uo\xa3Pu\xe7\xd0\xcb\xc8\x0e\xc5\x9d\x13\xf6\xdf9\xe1\xe7}\xe7d5\xf1\xa1\xbbu\xa4*\xdf\xd3\x85\xeb\xd6\x0b\x07\xdfNX'\x9e\x87g\n\xa8/\xab\xfb\xabb \xba\x95\x98\xb1\xf8<\xee\x96D\xec\x0ee\x06\x84GW\xa9b\x9c3\xac\x12\xe6\x07\x97dV\x16\x8a\n\xf3\x9e+4\xc5\xf2$~\xba\xf0\xe33\xc5\xf7\x01\x82\x8d\xf5\xd2\xcf\xde\x07\xc9E\xac\x92?.X\x95e\x12\x90\xe8\xe0\xd2_\xa6\x11QU;g\xd5:\xb4\xa1\xaa\xee\x12\xb85q\xc1\xe4\x01\x01\xc9gY\x98\xd2\xad\xb7*]f\xf7\xb3\xb3\xd6g|\xe9\xf8'\xe4\x02\x12\xefu\x16\x90\x8c\x04/\xfd\xb4y\xce\xe9ZG\xb4\xda\x99\xf7\x9e\x08\xe1w\x98\xe5E\x9bu\xa3\x80v\x05{p\x86]\xa8\x90\xd6)\xec\x81\x95\xe0)fw\xd3U\xcd\xef\xa3\n\xdar\x81\xc9f\xdb\xb6?H\xa2\\\x19n2\xbc\xf5(\xeb\x1b\xce\xf0B\xba\x97\xcc\nRl\xe4EF\xfc%\xbf\x08\xe9$\x98\x91k\xe4\x85q@._\xcfm+\\\xfag\xe4\x1e[\x88N\xa1_\x06a\xa2+<\x0f\x03B\x0bu,\xf0 \xdb\xd6\xe7qZ\x16*m\x03\x9f\xcb\x0c\xf6\xeb\x0b\xae\x85DOt7\x1d\x93f[\xf3\x90b\xecK\xf3;\xc1\x0e\xa1\x82V\x98t\n\xb5\xa3)\\lL;(.'\xd0\x8f*/\xae\"b\xb2^\x07\xf4\x1a\x880\x98\x07\x1d\x9d\xb6b\xf72\x026F\xeb\xdf\xfe\xf5\x8f\x96\x90}\xdf\x14\x07\x81\x0e:NN\xf0p\xea:/]\x88(\xc0\xdf|\x85\x1a\xbdfI\xba\xc1O\xb8v\xba\xf6\x17\xfc^p,\xe7#L7 iFf~\xa1\xdb\x0b\xca\x95\x0b\xbcQ\xd5\xa4\x97\x82\xfc\xb7\xd8\x0d\xd3\xf8nw\x88dj\xb8w\x9c\x12\xe1\xec\x1a\xa9\xb0\x06+\xab\xabta\x1a\xf6<6\xf2\xfeA\x98\xa7~1[<\x8f\xc3\"\xf4\xa3\xef9\xcb\xaa`J\xc4\xc3n\xff (\xf8\x12\xf1H\x13\x9c\xa0\x9f\x94\x05\x1b`\xc1\xbaz\x01\xb4\xcd\xc8\x9c\xde\x04B}E\xcehs\x13\x06\x8a\xcf\xe7\xb0\x0f\x01L`\xae\xffhU*\x15\x18\xa5\x8azu\x83\xfd\x86z\xef\x9d\n\x1f(\xa5\x1dZC<\x18p\x07\xc9 \xb24\x9d\xfd@\x05'yRf32\x81es\x04\x86\x83\xb2P5\xd3\xbbW5K>\x01_\xc1p\xcb\xfc\xf8\x04\xcan\x0dr\x99\xfaq\xf0\x8c\xa4\xc5b\x02#\x85t@\xf0\xdbJ\x01\x9c\x80\xda+a\xb8\x83$\xac\x02\xf8jA\xd8\x9c \xc2d\xe2WQ\x9f\x13&z.\xe4\\w:3Y\xfb\xa3!\x12j M\xd5\x15\x90\xd58B\x96L#\x06\xec\xdd\x19\xe8]\xe9 \xefz\x8c\xa7\x15\xe9\xa2\xad\xd2\x90\xbc\xc5\x14\xeb\x95\xb0\xaf\xad\x9e\x18g\xcc\x89\x9d\xee\xed\x05B\x98\xc8\x996\xedh\xd2L\x12\x03VJn\xf8\x17\x0b\x8dW-\xfa\xaf~\xb2\x19\xff\xd4\xd4\x81\\\xc9zS\x818X=f\xaf\xf2\x83\"i!\x04Y\xdbCQd2\x87Z\xd1nY\xbd\x8a\xd1\xc2\xcb\xd3(,l\xeb\xc7\xd8r\x86)\xd3\x15\xad\xc4\xf0\x186a\x9f\x1b\xb3\x11X\x87\x91\xe3\xfd\x94\x84\xb1m\x81\xe5\xc0:\x14`V\xe0\xf2\xcat\x10\xeaM\xa3\xb8\xaa\xa5\xa9\xf5\xc5\x06\x8d\x1d&/\xfa\xe5z\xd8\xb6\xa8\xa8\xf3\xe6=q\xdc4,\xb4#\xafF\x91\xb2\xe5#\xef\n\xf6 \xc5\xb7\x9f\x1b\xf13S\x918 /\xe8\x908!/\xe8\x908>/Pz\xbb\xcfT$N\xce\x0b:*\xcf\x88\xdb\xe9\xd6c\x9d *gf\xa0rf\x9f\x9e\xca1;e\xf6P9x\xa5\xbb=\xc2\x90U\xa1'L\xce\x18\xd3\xd3k\x88M\x9f\xd0\xcbI\xc1\xbe\xaa\xd5Hx\x06\x14gY\xee\xe3{?\x0b\xfd\xd3\x88\xa0\xc8c\x85\x0e\x85R;\xec#\xc8bn\xb3^(\xfa\xd3\x7f\x951O\xfc2\xcbH\xcc\xbf4\xd3j\xd5\xa4\xcfH\xf1\xa4(\xb2\xf0\xb4,\x88m\x05~\xe1o\x9c\xf3>\xfb\xe8\xac\xe6\xc2\xa9\xaf\x06K,\x8d\x05{\xd5\x8d\x82\x91pb\x83\xa9\x0e3\xa66\xc68AZ9\xd1\x97\x9f\xfb\xd1\x04|e\xf1\xb5f\x8f\xabE\x1f\xb4\xa3\x8c\xe3\xc0\xddd_R.\x97\x04\xac\x85\x8e\xe9/\xef\x04\xcd\xdc:\xdc\x00\xfa\xafh\x90\x08\xb4\xbd7T\x9cE8\x8c\xb3\xa8\\\x8b\x9f\x85\xc1\xcb\xa4\x8c\xdb\xc9\xff\xe0\xa32\x19\xdcB^\x0d'\xa4 \xbcH\xf9\xd3\x96\xebcZ\x08%>#\xc7\xcb,\xb2\xfa/^\x15Y\xd7Z\x8b\x1f\xc2(zKf$<\xc7\xcb2\x1f\xb0&\xbd\xa7|\xc8\xa2\xc4\xb2sJ\xdf\xc9^\x15\x1f$\x955{\xe3+\xf5\xdaS\xba\xaf\x1eqk#\xd0\xb5\xab\xf9\xceD\xc4\xd1\x15@/\x19o\x1e\xc6\x81D\xfc\x0d\xa4\xfc\niwyl\xc5F\xdf\xda6LF{h\x8c\x11Vdl\x0b\xb0b\x15`\xe9\x1b\xb3CVO`\xc9\xdc\xaa<>\xa2\x96:zu\xfa7\xb1[\xf3\xc5o>|\x80\xac\xc7\xb0\x11$\xac\xd9n\xa2\xf7Cf\x92\xda_\x0fqj\xa1P\xb7Zz\xe6\x0e\xd4\x08\xb7\xa7Ha\xb31\xf4`\xdf\xa9\xf8\xc4\x8c\xd3\xee\xfc\x98\x0f\xdc7\xcd\xe9\x1e `9\x98\xcf\xc9\xac\x08\xcf\x89\xf8\xd2\x88E\xd0\xfb\xaa}\x92{\xd5\x1d\xb2k\x94|\x92MgW{\x82\x06\x1e5\xb3\x04\x87\xc7\x14\xf4\xf2\xf0g\x0d\n\xe4c\xceo*\x14\x91\xd5|\xc2\x13L\x0d\xd8\xae\xbe\x93\xc8?%\x91\xb1\x9bE\xb1\x8c\xbeA%\xf3\x8d;aa\xd1\x8c\xbd\xd4\xea\x03\x04\xf0&y\xad\xeb0fT 3\xb7k\xda\xa2\x98\x00\xa6o\xe1\x13&p\xeb3\xa0\xe6g[\x8693:C\\!W\xd7\x03\xa7\xdb\xa8\xa7\xb3G\xf6\x8a\x841N\x8e\x905\xf5\x00\x1374\xbe\x0b\x88\xa3\xb4LY\x90`\x83\x8eP\xb7A\xd6S^\x0b\xde\xbd}1\xb1\x0c]7Dg\xa1\x9d\xe1\x8c\xb4\xb5\x17\xdb\xb5d\x8b\xd3\x0c\xd2y5|\xd8\xb4s\xd2Wk\xd89\xf9\xab\xdd\xa9}\xe0\xd5c\x89\x03z\x7f\x0d\xf1\x98\xce\x1a\xda\x06\xd4~\x1bC\xea\xf1\xdb\x95\xc4\xe5\x12\xcd\x11ns\x8e\xe9\xd3\xe2\xe8z\xaf\xf9\xfa\xec\x13\x13\xcfkZ\x8e\xc6\x14V@\x050`\xbf\x06\xa2\x03\xa8\xe2?\x92`B/\xf3\xbd=Hl$\xa6\xfa\xa9\x1c\x86\x1a\xfa\xeb \x9cc\xacH\xb1\x87\x89\xfaq`\xa2\x9fm\x88\x96\xb8}\x93\xe5\xa6\xb5\x05\xb9T\xf1s\xf2\xc3G\xccW\xa2\xcf&\x0e\x86\x83\x83\xb9\x91.\x0c\x9a\x16D\xeb\xf0Q[Ctj\xf4\x88[\xeb\x05\xee\x13\xbb\xce\xf1\xed\xe7&v\x8dtb\xd7H'v\x8dtb\xd7H'v\x8dtb\xd7\x88\x89]\xebQEL\xc0\xaa\x12\xabF\x9f^\xac:\xbb\x8dXU\x12\xac(\xa4\xa7]\xad\xadVy\xdc\x92Z\xdeJy|+\x11\xcf\x9dr?}\xbcM1\xc4)F\x19\xe9\xa3\xa6Q4\xb7\xa5\xeb\xb5\x10\xb2\xa5\x98\x81I\xdbMk\x1f\xa1w\xee1+\xa4p~\xe5\xd8\xed:\x15\xd2\x17\xb0>GI8\x962\x0fE4\xe5a\xf3\xe8\xe3\x9d\xb9\x8b\xdb\x0fYX\x90\xd7qt\xd5\xc0\xbc\xedG\xa7\xabp%\xb0\x1f\x0c\x08\x83\xa1\xb7W\xcc\xc0\x80\x96\xe9\xee\xaa\xd3g\x02\xd9\x85\x1f\x07\x11y\xbd\xea\x88[\xa0;\x14\xd0(\x10\xdf\xfb)O\xe2{\xa1W\x90\xbc\xb0\x0b\x16\xc0^\xb6\x1d\xe0yf`2\xc8\xa6\x00VY\xbe\xf6\xe17m\xaf\xbc\x91vlX\xc1\"9;\x8b\xc8\xf3\xfc \x08\x8b\xaf\x93K0$\x99\x91\x1f\x19\xbf\xb2\xb1\x0f[y\xe9\xdb~\xb9W(F5\x815\x8c'\xc0\xfe2~\xa7\xb6\xc0\x84\x1e\x98\xc7\xa46\x9d\x08W\xf2#\x8fE\xe1|!\x9e\x0e\x82\xd6W\xe5\xa7A\xa3p\xa4\xc3\xea\x14t'w{f\x1bV\xb2\xa9\x80\x15\xf8o\xfa\x08\x05u\xe3\x16\xaa/\xf1\xc1*S\x1d\xf6[\xdd\x02\x02V\xb1\x82\x001\x85\x16\x9e\xe0\xb6\x04\xf5\xdf_~\xa9\x9e\xaa-Ur\\X\x93\x1a\xab\\N\x18\x11\xd8\xf8\xb3\xd2\xeb\x0f@\x0b2d\xae\x8e\xf1o\xbc\xd4\xcf\xc2\xe0]\x1a\xf8\x85.\x08\xc2M\xd7X\xa2\x11\xf8*\xcbo\xb4\xeb\xac\xda\xa5;\x9a\xb2V\x10\x05+\x1e\x86a\xeaxXA%\x0f\x15ie\x88\xb6\"?\x99P\x9f\x0f\x101A\xa5\x9f\x1fx?\x86\x98O\xce\xfa\xba,\n\xb3c#p\xba+\xb3\xad#rY<\xc9\x88\xd2\x15M~JV}\x11\x9e-\xa2\xf0lQ0\xb0\x9a\xf4T\xe1\xee\xab\x97\x9ef\\zz\x13W\xe0\x81\xd2\xd3\x94U\xcc\x0c\xa3@\xf2\xad\x8f\"\x1f\xaa\xf0\xd5SK\x91M\xcer!9\xee\xd9'\xc7\x85s\x13\xa3a-vk\xab\xe7*o^`\x19XS\xbfo\x99fC\xe6%b\x11\xa8\x82R\xf4\xcf\xe9\xc6c\xab|\x13\xf8\x94\xdfqH\x9bX\xb8Rz\xfe\xb4\x15\x01\x15,\x17\xce\xf1_\n\xa2\x06 \x83y8\xbd|\x1e\xacd\x17\x0b\x9ck 3\x12\xe0\xed&\"b\xf6~\xc5\x08\xa2\xfa\xe0\xf5\x7f\xd1q\xae\xe8\x91\xc7\x00\xdb\xbb\xbb\xdc\xbc7~\x9e_$Y\xb0\xf2\xe6\xfd\x11\x9fO\xb1w7\xdb\x0d\xbf,\x12z\xddG\xa4\xa0\xbb\x12\x93\x8b\x8d\x94\xcfu\xc0\xd7\xb1\x08\"8\xf8\x0b\x0ea+|q\xf3\xdd_\xe8\xfdkz\xc2z\x88\xa7\x07\xdd\xe7C\xf6\x85>\x84^\x9e\x83,\xe4\xa1\nf\xda[\xd5\xe0\"\xc8\x8a\x0dF\xf4\xda\x12\x11\xb6\xe4\x94\xf8\x19\xc9\xf8\xbdj\x82\xf7\xdf\xe9\xc6\xc3\xe1\xdd\xea\xca\xbb\xf1u\x87\xd7B\xf0\xd9]u7\xba\xe6\xee\xf6\x8ac\x16\x89\x16.\xcf\xe7\x86\"\x87_m\xab\"\x9c\xbb@6w\x81h\x86#\x99\x01\x08\xc6\xe8\x7fl\xda\xa9a\x08\x81,\xfb\xeb\xd4\x11\xab\x12\x0c\xf6\xfe\xed\xd1\xd1\x1b\xccLK\xe2\x82\xcbR'P\xc6y\x99\xa6IV\x90\x80IR\x08\xa5\x97\xac\xffh\xc1:\xa4\xb0N\x7f\xddN\xfc[\x0f\xaf\x16\x017W8\xed\xb3e\x919\xf6.{\xd1\x002\xb9)c4r\xc6\xab7-\x98\xf4\x1b\xcf\xb4\xab\xccLH_+D\x0b\xb5\x1e\xd5$3c33\xf1e\x95\x82\x92\xaf\x1d\xcf\xe9\xc3\xc4e\xfd\x02$w\xb3\x00\x9d\x99\xa8\xb2\x92\x1b\xb3\xbe\xd1;'O}J\xe3\xd6\xab\xa7\x96\x1e*s\x9d\xd1\x01\x9d\x99\x00\xca\xb4\x9cd\xc8r2Q\xbby9\xd9\xc5=h9\xd9\xeau\x86l\x17\xd5\xec\x15\x06\xb7\xf54\xe5\x15\x87\x9e\x94\xbf\xe2\x11\xa4E\xefT3\x96g\xbe\x17r\xe2\x95\xa7*\x0f\xdbp\xdbK\xd0\x90\xd5\xd0\xa0\x1fL\x15\xe9G\x0d0tM\xb4k\xa9r\xbc\xfa\xf4\x07q\x05LT-\xa7j\xe4\x03\x82\xc8\x19h;\xe5)T\xc7\xa9Q\x07\x8d\xcb\xebxn\xd2\xd5\xe17\x12\x08B\x87\xa0\xba\xbd\xfa\xf2ws\xf6MZY~\xfbp\x03\x85\x82\xde\xaaYGW\xa7\x06 \x96\xf7\x95R>k\xf1\x80$\xa1\xe7\xbc\x8d+u\xe5;pKo\xea\xa2\x11[p\xb8;t\xdb\xa1\xba\x9eT6(\xc2\x9b\xd6\xa3Z4\xa4*U\xef\xfe\x8d\xe2Yw\xe5J\xffhB\x83\xed-\xbd\xd4`\xab\xc3\xd3\x87UQ\xc7\xad\xd9\xaf\x8a\x1e\xe8d\x07\xdb[\x0fu\xd2\x83\xedme\x8ckV\xf4yX\xf2\xc9\xfb\xd9lHX\x8dHym\x9aSyR\x16\x8b\xe7\x05YJ\xb9\xc7\x9b\x15\xea\xec\x0c\x93ZR\xd0\xacR\xa7\xa26\xa6<%3\x1e\xb6\xd0\x9ba?\x98\x90\xeb\xeb\xab\xe7\x01\x89\x8b\xb0\xc0\xa06b\x08\x7f&W\xa8*\xc2\xbe;\x8db`mQ\xf5i\x12\xe7\xe5\x92\xe4?0\x01\xd1JB\xfb\xdea\x17\x8aa\x8b\x0eQX\xe0\xd8Ek\xd0\x9a\xe12_\xcf#\xfft\xd0\x00\x05\n\x97\xd2\xf2\xb1\xbc\x0f\xb0\x8f\xd1\xe0z-%\xea\x0f\xbf\x0f\xf3\x10\x85'k\x9bj*\x8d>\x14FN\xfd\xd9\xfb\xba\xb2:\x1c\x14\xa2QK\xd4^uP\xdd^\x0cCR\xcd\xc00(FO\xab\xd7\xde\xec\xc2\xa5\x98\xbbzT\xca5U\xf6\xa8A\x1f\xf0\xb9j9\xf4\xbb04z\x04\xd3n%\xf1Qv\x95\x94\x05:\x07\xeb+'\xbc2\xf3g\xee\xa9\x1cr\xbd\x99X{}M\x96\xe5\xd2\x8f\xa2\xe4\xe2(\xbbz^\xbc.\x0d\x96P,\x87e\xc1\xeb\x1d\xc4\xfei\xa4\"\xd5\xc4\x83\xf1\x1f\xbc\xb9A\x0b\x12\xad\x10\x0e#\xa8\xebb\x1ag}\xcd\x05\xd6\x1c\x18L\xf6\xbc\xaa\xdc\x1b\x1fv\xc9\xb6`H(\xd9\xb3\xaa\xea\x80!\\UZ\xce\x97\xa8\xc5\xd4\xd7<\xad\x06\xfb\xc6\xa8\x13=a\xdd\x0b\xad\x8e\xbe\xe2\x05\x86e\xaeQf\x8f\xc3\xd8\x01\xab. \xa5?\xd2\xc8%\xfb\x80\x07\x85;BZZ_\xfb\x90\xd5~Z\xa1\xca\x1e\x0f\xb0\xa7\xac\xfe\xdb\xdaM\xbc\xef\x8b\xf7\xb0\x07%\xa5m\x0c>\x7fO(Q\xe5\x859e\xbe\xf4\xb5^\xc3\x1e\x9c0\x16ArS7\xcd\xee\x0d\xec\xc1\xa9\x97G\xe1\x8cP\x9c\xb51rx\x82\xef\xc6\xf7F\xe5\xdf\x8dS\xad\x1a\xb4oZ\xcd\xcd\xc7\xe8\xacO\x05w'}\x0eP\xf5\xdd\xb8\x9f\xd5\x838T>~\x155\xd3\xcc\x1c\xac\xfdX# \x02\xc5l\xc3\x82,\xc1\x82u\x9e}\x8b\xd9\x93v\xae^\n\xf7\x96\x8f\xaa\x1b]2S\xc3\xca\xac\xa0\x13\x1c\xa6\x04\xd5\xf6\xc4#2W>F\xf5ZQv\x86\x1f\xba\x9a\x9er\x0c\xd9x?\xd1~J\x83\xf9h\xdb\xd9\"\xb9\xfe17\xb3F\xedR\xcce\x17\xcd\x9bu-\x1c\x98\x06J\x18\x0d\xa2\x14\x8b\x88\xa7A3\x193=6H1]r 9K\xb3\xf1\xb4\xdd\x02*\xe5\xf5\xaf\x1b\x1e\x10r=\xf4fI\x19\x17\xf6\xad\xceD\x0b\x1c#2\xa0cmg\"7\xcf\xb0\xee$\xc4\xb8zO\x14\xe7W\xa0\xa6\xaf\x96\x0d\xa8\xb3\x18<\xe2Y\x12\xc1,\x89N\xd8\x85\x03\x8d\xdd\x8aN\xd0IK7\x13\xeb\x15\xbap}\x8aq\xc8nO\xda\xe1<\x93}\xa3\x1c\xe3\xb8\x1a\x99\x94\x06\x99P\x82\x8c:%\x9f \xee7\x9fV]\xbd\xf4S/\xcc_\xfa)\xf3\x17R\xd8\x1f\xd2\xe7\xda\x0e\xa5\x8e\x07&o\xd2\xcd\xe7\xa2\xcf\x8fh\x1e\x1bc\x95@G\xcaj\x88ZB\x1fA\xc1O\xe0\x94\xd1\x80}\xd9\x84j\xb6g\x02\x06\xfe\x80>\x99\x7f\x81W\xe6\x04z\xe2T\xa4\xac\xd6\xa2F]?\x84\xc8\x82\xf8\xb5|\xc9\xbe\xc2\xf4%\xc6v\x98\xdb\x94\xec\x94h\xae\xdf\xcc\x04\xd4\xe7\xa3#\x7f!\xa4H\xf2\x97-QV\xff\xbaK\xb2t\x03\x07%jsNo\x02\xe7}\x8b)\xb8\xb7 \xf4\x04\xd7\xaeBEN\xe0\xbd\xb6\xa2.^h#;\x1c\x06\xd8\xbb\x0b,\x7f\x13\xe31m\xc7i}\xdd\xbfJ m\x90o0\x01\xcbj\xdc\x9bm\xb2\xe6\x8e\xee\xad\x8a\"\xab\xef.\xb8\xcbY\x1e\x1a\x07\":\x9f\xf0\xb0\xe2\x98Z\xb2K\xb8\x1a\x0e\x8a\x8c!\x14,c\x1f\xc1y]-\xf5\x13\xdb\xa1\xa4\xe2\xeb:t\xab\x9e9\xb8\x93\x95\xff\x87d/oJ\x0f\xd7\xe0}\x82w=\xa3\xda_\xd7r\x01\x8c7\x80; \xfd\xa9\xbd\x81\xb9$\x03#%\x1a \x83\xa6\x87\xb1\xae\xda\xa5iN\\\xe6y&\xe2\xfb>\xade4\xdc\xff\xe8\xccmk\x8a\xafL + y\xf2 \xf05\x10\xe9\x00\x1c\xef=\xb9\xc2\x1b\xdfH\xa8\xf3\x8b\xa1_\xd8/\x9e\xa5\x97\x93\xe2mg\x06\x03r\x1c\x8bh\xf8fd\x0dm\xdcn\xacmr\x0f\x1e\xc6\xfeI\xd1<\xf9\xd2m\xa0\x06Zw\xcaM@r\x93\x83t\x17\xb8\xf1\xa9\xd1,\xb7Blo\xf4+\xd2\x08\xfc\xf8zP\xbd\xef[\xe0\\\xbd3\x01s\x9d\xf8\xa1/\xf9\xaf|i\xaf\x06\xc1\x03\xdc\xdc\xb5\xa6T\xedG\xa85W\x9be?\x84\x03W0\xcck\xea\xdb\x8e)\x0f\x19C\xe3\n3D\x9d\x12\x0f'\xb5\xe5sY\x0dr\xc0\xa9\x84\xd5h)\xf1\xf0\xc3\x9c\xd0^\x9f\xc7L5\xd4\xfba_\xa4\x90\xc1\x88g\x95 ~Fh\xa7F\x97\xab_\x03Z|t\x03\x8bo\x95\xa5\xf7\xb9\xe8M\x1dD\xb6%\xa9\xe9\xcb\xb5\xd4\x12\x01\xf5Uoi\xb8\xba\xda\xcd\x86\xbe\xac\xab\x92\x95\x94\xdb\x13\x98\xd6!SZ\xf1h\xe9\xaa\x06\x06\x1b\xaf\xf3\xcf\xd0\xa8\xc6e\xa6\x0b\x1d\x03\x16\xcc)\x95\xc1\x1e$H\xecdM\xd3\x91\xccl:\xd2\xf4\x93k\x81\xac_[\xe8\x89W\xab\x98)\x0e4\x94SZ\x83\x85\x83\x84\x9a\xbaZ\\?\xadod\xe9G\xea$\xedyq\x15\x11\x9de)%\xfb\xcf\xb2\xa4\x8c\x83\xa7I\x84\x19\xdc\xff\x7f\x0f\x1e\x9e\xce7\xb7\xbb\xf7t\xeb\xe4\x19\xc6\x92fj\x19\x9dL\"\x9c3\x1bx\xab\xdd\xa8E\x17\xdf\x92O\xfegj\x0d\xd6\x03E\xd9\x10(\xd2\xd8K5\x0dj?\xcf\xe9\x07\xdax\x16\x81\xce\x18.\xd0\x19\xc3\x05:c\xb8@g\x0c\x17\xacf\x0c\x17\xa8\x8d\xe1\x82\xda\x18\xae\xebd\x93r\x0f\x81-\xa5\xb1[\xf0\xe9\x8d\xdd\xcc)\xfe$c7\x15\xed'\x19\xbd(L\xde:\x9e\xc2\x83M\xdbn\x95Q\xf8\xf31\xbf\xe93\xae)jO\xe0\x1es\x11JPO-t\xde\xd98M.\xadc\x03}O!L\xeb%\xcc\xd7i\x8d\xf9M\x88\xe0\xc2\"\xeeX\x9a\x91\x99_\x08i\x80\x1dsI\x8e\\\xc0.\xd7>U\xda0\x86\x8e\xcd\xa7n}\xe3\xc2\xcf\xe20>3\x89\xffE\xdd\x89uW|e\xec\xfd\x94\x84\xb1m\x81^\xe8\x91\xe8{J\xbd\x97t\x16\x1d\xfa\xf3\x97kW\x86\x01\xc3Pd\xb9\xb9\xc9\xb6\x88\xa4\x94#5d\x0b#\x97\xa9\x1f\x07\xcfX\xbd\xbaoOzO\xcf\x9b:\x01\xd4\xcd\x1c!\xfb\x1c \x19_\xa6\xbf\xb3\x16\x9f\xe75\xf4\xef\x0e\x1a\x9f\xad\x83\x86\xc15C\xaf\xa8\x890\x91c\x97\x89\x02~\x93\x87\xde<\xc9\x96\xbe\xa2_\xee\x92\xc1\x03\x9a\xab\xfd1\x84K\xd7\xda\xde\x1eD\x18\xd9\xfb4\x8c\xfd\xec\x8a\xbd\xc1\xecB\xd6\xa9\x9f\x93\xddm\xf1F\xef\xa9\xc1@_\xef\xd2\xa0\xf4\xe4\xe0\x01\x12\xe7\xa12\xdd\x90\x84\xeaJ\x1eS\n\xf6\xc1\n\xe3s?\n\x03\x8b\xc9\xe0\xbbm\x86E\xd4\xfc\xa2\xd4\xd4\\E$\x9a\xdbU\xcaK:\xda|\xba\xa9\x08\xd2\xaf\x90\x07\x04a\xce\xd9\xdc\xc2\x0b\xf3g\xfc\xaf\xe6a\xf8\xcch{\xb7\xca\xbd\xdfL\xef\x0duR~\xe1\xe8\x9e+\xde\xd5u3\x92\xa7I\x9c\x13I\xea\x01R\xa6\\\xcd\xebJ\xde\xc3\xdbnEN\xd2\xb9\xcb\xc6\xf6}\x05\xd6\xd3\"\xb7P\x8b\xdc\x8c\x84R\x15\xf0\xacP\x06<\x8b\xab\x80g\x94\x88\xccX\xc0\xb3\x0c\xbe\x82\xe2\x11d\xeb\xeb\x0e\xc4\xd3\xac\x19\xf0,\xd3\x07<\xab\x15\xf0&\x92\xadJzwx\x95\x17di;M\xdb\\\xfc\xeb\xbb\x9cN\xc7HW1Z\x96\xd9e:v\xc6r\xbf2j\x96\xad8?\xde\x0d^L<\xad\xdb\xf6\x0f\xdd_\x8a\x8d\x0c\xcd\xd1J\x854\xb6\x80}\xc0\xd4\x18\xcd\x06\xacc`\x81t\x9b/\x95x\x0e)\xd5\xe7\xb1\x1d\xf3\xec\x05-XW\xc0]kl\n\x03\x88V\xd3Sag\xfa\xcc/|\x8b}\xe22\x85\x03\xcbZr\x8c}\xb78YWw\x18\xee\xaa\xffn\xe3\xa6\x81\xa8N\xeb\xdd\x8d\xa4\xd3\xba~(j\x84\xd2?\x14q\x1eT\xae\xcc\x98\xb8\xa1\xbe\xf0\x84\x0f\xb3\xd6\xc9:\x91P\x9b\x9are~\x00Ul*\xc59\xc6\x80\xa2\xfb0\x0d\x11|;s\xc2\x98\xcf.\xc4\x02\x94\xf5\x15\x9a\xe7\x0bH\x94\x13\x15S\x8b\xbc\x96\xa6\x9d\xa2\xdb\x8ei\x1b\xb3a{\x93\x0f?\xc8\x9f\xc9\xa6\xc4C6\xc5\xbc#\x03\xb7#6n\xc7\n{\x11W\xaa\xb4\xcc{\x9dq\x17\xf5\xd4\xb1\x1d\xe5\xd6t.\xed!\xfb\xe3Br\xbb\x9d {w\xc6\xef\xdb\x99\x84\xc5\xddeq>\xf7k\x84\xe2\x9b6\x8a%#\x17\xa8G_M\xb5e\x08Mn\x9d\x82\xa8\xa7\x89G\x9de\xa3\xb4}\xa2\xbcrl\xdah\xac\xd9\xb6\x81\xb1\xbai\xeb\xa5\x97\x914\xf2g\xc4\x8e\xc9\x05\xbc%g\x07\x97\xa9m\xfdb\xc1:`D\xc6k\xcb\x05\xeb\xccr:*9\n\x11\xa5\x04\x1f\xf8\xf3\xf7\xa5+\x95\xca\x8e\xd2\x8e\xedqG\n\x1a\xf2\x92Q'4\x0fSX\x8c\xb7v\x95T]\xf9;\xb2\xac\x14\xfb\xfer\xed\xb6\xa5\x82\x99\x0b\xbe\xf7\xee\xcd\xb3'G\x07'\x87\x07/\x0e\x9e\x1e\x1d<;9}\xfd\xea\xe8\xe0\xd5\xd1\xc9\xd1\xdf\xde\xfc\xfbZ\xaa\x88\xe0\xd5\x16\xf5\xf0\xcd\xebW\x87\x07\xbf\xcf\xaa\xeadR\xaa\x98\xac=\xeb\x91\xb8\x10\xeaH\xf1U\x16\x84a\xaf\x93\xef\x9f\xbc}\xfe\xe4\xeb\x17\x07w{du$\xc4 \x0c\x16{\xef\x89\xc2\xa8\xc5\x17K\xad\x069 \xef)\xef\xfe\xcc\x85\xd0H\x11b\x05\xe3V\x94.\xf8\xcd\xf5\xcdnq%\xd72\x8fQ[\xbd\x97\xf0\xd7;\x0f\xa4\xfb6\xa1\xcb\x82y\xf4\x92\xec\xc0\x9f-l\xbdh\x01\xe9>\xef^\x18\x07\xe4\xd2\xfb)gr?-\xd5Gw4\xb1U1\"\x88G.\xd3$+\xf2)#\x80R?\x9f\xf9\xd1S?'\xdf\x84\x11\xa1\xdb\xe8\xd8\x85s\x8c\x1b#.\xd1}\xe9w\xdbAH\xba~\x07-\\loo\xefR\xb2H\x8c\x03\xd7eg\xb43\xe8k\xc3\xb2\x0b\x1b\x8d\xad\xb1L\xd0\xd4\x11\xbd\xecU\x0c5*Z#\x93\xa6W P\xdfd\xc92\xcc\x91r\x89\xed\xed\x9d\xfb\x8e\x0b\x87H\x91\xd7\xa65^^\xf8Y\x91\xff\x102\x0dIlo?\xd8\x1d4\xc3\xd8~8FM\xef\xc3\x07\x9dU\xda\xde\x19\xd6F\x1fpno?TB\xe7\xf6\x8e\xca\xc0%\xb6\xef\xb7_3b\xef\xfeHZ\xe9\xe6H\xc7[\xf7\x1d\x1b\x05n.X\xf8\xaf\xd5\x83\x87P\xbbt\x82\xd2;\x9b\x08'\xb3\x13\xda\xff\xa6\xf8\xe3=ES\xf5~\x18\x92x4T\xa6'\n!|\x15\xac\xe0Da\xd7\x18W\x85\xe1\xfa\xba\x12{\xac\x11\xdcTxL\x19\x94J\x9cm\xd7s\x10\xa2\xb9\xc4\x1e\xa1MzB\x0f\x9bE\x0f;\x8b\xd3\xc6\x8d\x0cYZ\xd9\xfa\x1d\x992\x99C\xec\xe2O\x89;\xbav\xab\xcah]\xf3D\x08*Q\xd7\xc0W:\xb3Y\x17\x0e\xfe\xac\xabg\xb6E\xe2\"\x0b\x890\x9co\xc3\x8f\xbc~\xf2F\xca\x0b\xac\x8e\xd0\xd8\xfb\xa5j\xaf\xf9*\xaaP\x17\x8b\xb9\xda\xdd\x93 \x89)\xdb\xb2f\xa6\xfdoy.F;\xeas\xf1\xb0\x1d\x95\x91\x1d\x8b\x87m\xc1\xb6\x8f\x9c\xc6#\xe9,\xeflb4\xf3\xd8\x1e=tl+,H\xe6\x17\x98CV\x0f\xbb|q(,\xd5\xb3k\xa1\x82>y\x1b\xa9\x11\x11\xc6\xef\xf6U:\x9e\x98\\\x16\x142Gn;u\x00\xed.\xc4\xb6)+\x0b\xcf\xaba\xaf\xb6\xdc\x12\xc2Q\xdf\x86[\xbb\xeau\xdd\xd5\xe2\x95\xedm\x07\xf6\x95\x9coHr\xe81@N\xecv\xa2\xa1Jk\x10\xbb\xb8y!\xaa\x07\x90\xda\xadT\x079S\x16\x94\xf0\x18\xf2G\x0ed\xde\xdc&\\\x182\xcd\xd7\xd7\x8f](\xa6q[\x08!\xa8\x8c\x9b.\xd8\xfd\x91\x9a|\x18\xa9!q{g[\xb3duw\x1a8\xab)\x0e\x96wFGQ\x94l%\xf4q-#$9\x84\xcaES U\xa3\x14\x1c#\x05iBI\x1cv\xa9\xc2\xda\x9e\xde\xb5\x117\xed\x11D\xf0\x18f\x8f\xf46\xc0\xb45\x9bne>\x9d\xad\xaf\x1f;\xb4\xcd\xd2\xa9\xcdU:\x1f2\xe1S\x7f\x970[_\xef\xe9\x16\xaf\x87\x19\x841\xe4Ho\xe4\xd3\xd91\x0b+\xea\xd4r\x0f\xac\xf2\xe1\x03j\xa2\xaak\xe5\xcb/a\xa3\x19\xbbhE\x1c'a\xb3]\xd5\xa9{\xe9\x17\x0bo\xe9_v\xc1\x88\x95\x84q\x1f \xe9\x11\xba\xcd\xb0\x0dq\x1c\xf8\n6a\x9f\x9e8X\xa7C\xdc\xa4\x97 C)7F\"\xea\xf9P\xac\xbds'\xc0\xaf\x83\xfc\x10\x83\xb8SHbD\x9eM k\x0d|\xb3#\xa2\xf3k\x8dPp\xc8\x0e\x88B+\xc1\xc6\x94\xe3\xda}\xf8\x009%/\"\x14\x87\xf1X\xb4\x9c\x9a\x9d\x80\x8dr8o\xb6\xf0\xb3\xa7I@\x9e\x14v\x8ek\xbe\xb33~\xb8K\xbf\x0d\xe11\xec\xecn\x8d\x1e\xb2\x86\xd6a\x84\xe0\x87\xb6\x04\xb6\xdf\xf9\x98V`\x0d\xecn\x8d\xb1s\x9f6p\x7fk{\x8b\xf7\xcf\xeacGt'a\xc2\xdf2/\xbd\xdc\xc5N\xc6\xb4\xcc\x87\x0d\xde\xcc:\x1d\xe7\x06\x1f\xd4W_\xc1h\xd3\x81u\xd8\xdd\xd9\xd9\xda\xbd\x1b\x08\xef\xdc\x1f\x1c vu\xd8\x90\x02\x8b\x83\x12e~\xa5\x0d\x8a*\xdc\xbd7\x90\x19\x13\x1f\xb6\xc4\xf0\xc5\"K.\x802\xef\x98%\x1dO\x80\x05a\x0eqR\x00R\x00\xa7\x11Y\xd3X~dv\xc1\xa2\xf0\x11g\xc5sB/\x81\x07\xc88\x8c\xb7\xb7\xf1\xdf\xed\xdd\x87\xec\xdf\xfb[\xec\xdf\x07\xfc\xfd\x83\x9d\x0eg\xb1\xbb\xe9\x08\xaefHg\xbd\x84\xd4\xaejgd\xd2(\x99\xc6\xf6\xe8\xbec[E\xc2N\xd5\x91\x7ff!\xdbi\xfdlQVn\x9d\x82\xfc\xda\x1eX\xd3\x04o{\xf8\xf9\xd8b\x0c\xd7\xfd-\xc7\xe6\x14@\xed\xc9\x00UCV?mU\xb5\x89\xe9j\x90l\xa7\x90i\x1dK\x1ah\x0c\xa94d-\xe4\x85\\\xa3\x1c\xfe\xa6\xc32\xac\xd8\xa3\xcdQ\xbf\x0d\xf5}:I\xb5(\x9f\xae\xe3\x03\x87Y\x1e:.X\xbe\xd2\xfe\x10\x83ik{i\xf7\xd6)l\x99\x088\x9e_\xaf\xc1\xa0\xf9KDK?\x11\xa2\xb8;0)\x0d\xbb4\xc4\xd5\xf8\xa8s\x0c\xd5z0Le#\x9d\xc3*\x02\xb6\xcdTG\x02$\xd8\x86d6\x13U\x89\xf3U\xf5\xa7\xd2\xb0\xe9\x1bE\x1e\xe5\xf5|\xf56\xd7>\xcep\xdb\xf8\xc6z\xea\xc7\xff\xb1\x80Y\x12\x9f\x93\xac\x00\x0e\xe9E\x02i\x16.\xc3\"<'\x8c\xcdZ\x95\x9a\xef;\xf3\xdb\xbbm\xc91\xc3\xc6\xe3\xed-%\xcd:RJ\x15Z\xec\xd3\x03\xc1>\xdd\xff\xef\x99}\xd2\xb0\xa5\xdb\xbb\xea\x95\x1dw\xc48>\xc7\xca\x94 }~p\xf2\xe6\xed\xeb\xa3\xd7\xed\x80\x15e\x9b\xdfo\x16\xb7\xc5\x01\x9d\xf58g\xb9+\x0b\xde\x15E\\\xe1<3D\xc6@+\x0c-5\x84$w\xe1\xa1S\x90\x17\x84y\x1a\xf9W\xf4v\x88\x93\x18\xf3E\xdb\xe3\x9d\x11\x9a\xf5\x938x\xba\x08\xa3\x00Y\xb7\xc2\xcb3\xcacX?\xf9\xe7>\xf3\xe9\x9dXU\x16J\xee\xfb\xf7C\x18\x07\xc9\x85\x17$3\x14\xa18^\x92\x92\xd8F\x18\xb9\xc8\xc2\x82\xd8\xd6W\xec\xd3\xc7\xa2\x8a\xf7\xcd\x1eC\xd1_\xfdx\x8f\x17\xa1j\xd7\x9bEI\x8e\xe9\x0ds<\xc1\xdf<\x82lc\xe3\x91\x03\x01\x89HA \xaf\x01i\x1aN\xb3c\xbdMYn\xb7`H\x8dI\xf9E\xc1,8)\x9dfD\xad\x889\x95tF\\F\x11J\x90)\x15g\x97-x'\x0ecpcrA\xf9\xbef1s\xff\x8aYZ^\x82\xa6g\x98\xd5\xc2qei\xab\x90p%v|+\x9a\x7f\xa46\x1e\xec\x9c\x08\x0e\xf9\xdb\x0f\xf4\x94\x1f\xbd\x98\xff{\x90\x1d\x8cF\x0f\xd4d\xf1\xb8\x8d\xa0\xb9\xf0`w\xd7\xb1\xd7\xda\x02\x075\xca\xb8\xc1\xfd\xce\x97\xa8\xe4\x84t\x17\x17\xe0\"u_Sfiz\xacX\xf3\x98\xf2\xd5\xa5\xc3\xa4\x04>\x8a\xf31%<^\x9b\x91\x88,\xa4\xf8\xf0\x11\x14BX\xcb\xf7\x03\xbf\xa3\xa8\x01w\x83\xb9\xa8\xfc\xa7\xd0\x8e\xb0\xb5\x0f\x1f\xea\xd6\xd4[\x14\xddt\x8b\x1e>\xd4\xac$\x83N\xdb\xfa\xd9r\xd0\xd5\x82\xd2\x81\xcf\xf3\x83\xb8\\2\xbe\xc1\x96`\x18L\xe6\xd1\x82\xd2=\xac\x93\x83\xd0s\x8d\xe6;y\x1a\x85\x85ma\x8e}\xde!\xb9\xf9 \xed@\x95\xd0ti.\xa7m\xdd\xdc{'\xd3\xe0\xd6\xff]T\xf5\xdf\x92\xa8J\x83\xb2\xb6w\xdb\xef\xc3\x01\x94\x8c__\x94\xd5\xc5e\xbcN\xcfH\xf1FT|=o^\xab\x1aX$\x02\x9d\x01fp\x0e\xf1dMQ\x1b\xad\xa2\xf0)\xa9\x90\xc4y\x91\x95\xb3\"\xc9\xd0\xe4 \xc28/\xfcx\xd6-\xddo\xfe-\xdd\xbe\x93\xe6g\x1c\x0f\xec\x83\xdf6\x00_q\xfdw\xb6nz&9\xfe\xc8V\x17XT\xf7'g\x1f(;P\xb1\x0c\x0f( \xcd\x98\xca-\xc7\x15\xde\xf0[\xfc\x82E\xc6\x80'\x8f\xb5G\x9bc\xc7\xe5>\xb5\x94Z\xc0\x83\x1b\xb5\xb8\x05\xf6\xaa!kp\xd1s6\x17\xba\xb3\xa0\x13m\xe1\xe9\xe1\xe1\xdb2\"/\xc2\\\x11\xec\xe0\xe9\xe1\xe1!%M\x9f\x91Y\xe4\xb3x\xd3\xdd\x80 O\x0f\x0f\xd1\x14\x817\xd1.\x8dB\x12\x17o\xc9\xacP\x97?{\xfd\xd2X\xc8\xe6\xa2->J\xde\x93X=\xf8g~\xe1\x1fe~\x9c\xcfI\xf6\xbc Ku\x1b\xdf\x84\x91f\xe4\xdf\x1e\xbd|\xf1$\x8a\x9e&Q\xc4\"P\xa9\xab\xf4\x95\x7f\x93dK\xee\x85\xa4\xae\xc0\x9c%\xb4U^\x92 \xf4\xd53|\x19. e\x89qs\xbb_\xbe\xf2\x97$x\x95\x04\xe4\xa5\x9f*J\x93@\xb3\xebo\xfc0\x16\xe1O\xd4K\xf3&*\xcfB\xc5|\xd9{\xcdp\x0e\xbf\xff\xd3\x0b\xbc\x8a\xd4m\x1e~\xff\xa7W\xe5\xf2\x94d\xda\xe27\x98%X\x03\x0b\xb4< c\xcd\x80\x0f\xbf\xff\x93 \x90\x0e\xbf\xff\x13\x83\x94$\xd3\x80\xc9!f\\\xfb\xba\x9c\xcf\xb5\x03\xa4\x07\xe5pAH\xa1^\xd5#rY\x1ce\xfe\xec\xfdS\xddQ\xa9jh\x8a\x93rV\xad]Ur\xed\xa2+zb\x07\x945a\x94\xf89|\x05\x0b\xc1s\xc2\xf9\xfa\xba\x8aZ]\xba\x18\xc9~1=W\x18\xbcQ&4\x98\x9e)JN\x91\xacW\x95\x9c\xc0\x1e\x9cR\xa4\x7f\xaa\xba\x90\x80_\xc5'H~\x9e\xd0\xfb\xf7\xc3\x07(\xed\x13\x17f.\xa4\x8e\x0b'\xd3y\xfdn\xee\xc2\x19E~\xd33\xca\x80\xa5.\xa8\xe2\xd2 r]\xd2[=s\xe0d\xba\xc4\xcfC\xfa\xf9\xd2\x85l\xba<\xae\xc5\x9b0\x14a\xf7\n\x804J\xcb\xed\xfbj\xbe\x03\x11w\xe3\xbd_Q\x94:&n\xbc\xbd\xfb\xefv%\xff8v%z\x82\xef\xbec[e\x9c\xcf\x92\x14\xbdU\xda$\\\"\xfc\xf5T\x07\xa6\x123@2\xcd\x8e\x99R`\xe7\x01\x1a\xaff.\xfc\xa2\x97\xf6u\x98\xfaiv<%\xf4\x18\xc9\xf6\xf0\xca\x99\xe8$\xfeF\xd8\xfb\x0c\xed\\\x84\xb1\xa9/(\xa9\xf1v[\xc2\x92W\xc4V\xe35\xa7\xb0\xc6\xaa\xb8%*\x8d\xcf\x9c5\xdf\x16\xd4\xb0p%\xf7\xb7[\xaf\x03\xdez\x1b\x85,8\ni\xd7?\xe7\xef\xdb\xf6\x10K\xd6\xebN\x1b\xb5\x9c\xf1\xf7[\x8e\x97\x93\xd6\xba_\xb1\xb6\x1elvb\xe1\x9dr`m\x8f\xea\x84\xb7\xd6\x1e\xd5\x05\x7f\xdf\x1e\xd5\x01R\x9a\x95\x8c\xbeYx\x89\x85i\x96\xccH\xde\xf2D?\xc4\"\xae\x98k\x16=\x85=\xb0\xf8Gx\xceg\xf6e\xab\xd7\xf7f\x89\xee\x13\xb4\xb0\xdd\x83So\xde,xM\x0f\xc4\x9aY\xda[dW\x1a\x9eW\xe0\xc8C/#y\x12\x9d\x13\xbb\xbdz\xf2\x83\x1e\x1aM\xf6g\x8f\x1ea\xa1\x1e\xccS2C\xfcr<(\x1b\x96x\x88\xfd\xde\x85\xf7z\xd6\xf7\xba\xcb\xd2\x83d\xc7\xf0\x14\xfdQU|\x1c\xdf\x8b\xb7\xe4'F\xd9\x1e\x9c\x93\xb8p\x98\x0fK\xb1 \xb1\xfd\xde\x919\xb4\xa2\xd3\xcd5\xcc\xfcb\xb6\x00\x9cCK\xf9\xd6\x06\xbf7\xbdsF\x15\xb5V\xa8\xbcf\xaf\xa5\xf4\xbb\xe6d*m\xb5\xcd\xe21\xd0a;8\x85\xe6h[\xe0r\xd4\x87\xed@\xe8\xb9\x88w\xa2\x95\x88\xd02\xc4\xb7\xea\x0d8\xe7\xb6\xcb\xc4;\x99\xa9k\\\xe95\xaa\xf2\xd3\xe0.\x89wr\xcex\xcb\x11`\x8c\x9a\x93\x9c\xb1\x97\x9b\x8c\xb5\xac\x05K}p\xc5\x85\x995\x02M`\x1f\n/y\x0f\x13(\xbc\xb9\x1f\xf6\x84@\x87*A\x14?\x1c\xfd\xd5#^\x9d\x02\\\x7fm\x9649H\x96~\x18\xab\x17P<\xfa\x13,?%\xa5?\x124\x1b\x19\xf3\xb5[PP\xf9 \x89)\xfck\x0fF\x8e+\xe2\xff\x94H\x81\xec\xa1I\xb5\x8d\x81*f\x1e\x89\x0b\x92\xd9\\\xa7P\xda\x19\xf2\xe8\x98\xa1\xd8#\x97aas\x06\x7fm\xd3au\xf6\xd0\x1b\x81\xdbX\xefCd\x1f\xd8\x16?w\x1b\xb3\x85\x1f\xc60\xbb\x9aE\xc4B\n\x08Ma\xde\xd8\x14\x82\xf7!d\xda\xd2\x18\xfdK\"Z\x9cc\xc9\x04\"[\x91\x1dP~\x1a\xe7\xb2wYp\xfck>\x9f\x1f\x9fDd\xf7\x84\xdf\xbc6\xe0#\x88k\xd9t\xf8\xc8\x01\xdf\x8e\xa7\xe1\xfaz[9 ?\xf4\x90\xa0\x90\xdc\xad\x8e\xd5\xc8\x05\xd42\xaf\x89}z\xa9\x1b\x93\"z\xe6\xb5\xe9\xf8\xbf\xec\xc5Egl\xf1s\x03\xfd,\x1eD[(\xc4\xe5f\xfbxB\xb5\x13\xa5[\xfc\xbc\xa3\x80\xa9J\xe7\x14\x08(|\xc0C\xe0\xf0\xa3c\xea\xed\xa7\xde\xdeV\x85_54\xca\x80U-\xfa\xb7l7,\x01S\x05\x87\xa9\xaa\x02\xdf.v\x0b\x9b\x92u\x0e\x00'\x01J\xf4L\x0d>\xfa\xc6\x9dz\xd5\xbbv\xc2T\x8er\xaa\xddu)\xbc\x93\x00\xaf\x10\xfcA1\xbd\xcb\xd6\xa0\xf0N.hA\xe1x'\x94\xa2\xa7d\x85wB/\xc81\xfe\xf2\xc5W\xccG\xfdd\xc6\xed\x0d\xe9Eqd\x17(\xc40\x8e\xfc\xed\xb0\x91\xbb\x15o\xaeV\xf5\xac\xc5\xdeI\xa0\x03\x86\xb8\x9e\x14*\xcd\xf9\x9c4\xd7\xaf\xf9\xda\xa5\x9d\xb1\x1b\xb0:X\xf5\xe5\x073\xb4\xec9\xa5\xa7\x19\x89\x87\x00\xc2\"'\xd1\\\x97?\x8f>\xb8\xceo\xd0\xbcj\x7f(\xf1\x04\x12\xaf\xde\x7f\x17\x9e\\L\xc0\x90l\xb1\xaa\x16h\xd3\xb2\x8aGC\x95\x8bg\x18\xc5\"\x0c(\xe9}\xfc\x16/\x98\x11\xde\xcd\xaf\xf8\xef\xbb$\x03^\xb1\xbe\xb2\xde\xc0\xdb\x86\x9b\xdf\xa1wL\x05\xfe1\x03\xff\x11\x85\xef\xd8\x855\xddx\x87\x8d\x93\x8f\xcf<\x91\x01\xfb\xd7\xb3w\xd7\xda\xf9w\xe7\xdd\"2\xea\x1d\x7f\x8dg\xfd\xd0x`\x17<\x82\xe7\xa1\x0b\xe2PX.X'\x0b\xcbq1\xd4\xa9\x0bY\x9d\xc5\xbau*\xd4\xe0Cl\x04\x13\xd6n\x05)\xe2\xcf\x16r1.\xfa\xabf\xfe\xec\xe6\x97\xd5_\xd7.\xbb\xc4\xf5\x93d\xd2>A\xd9\xb1\xbf\xe4\x9b\x97\xbd\xc9e f h?\xfc\xeb\xbcSy!Wf\x84b= \xa7i\xdeco?\x189\xf6\xa1l[\xdb\x1e\x1f\x89\x07\x84\xfa\x17\xac\xdc\x13{)v\xcd\x9cS\xfc=\xec)\xd9T\xa6\x7f\xc6\xb3A\x19\xacf\xad\x9a3G\xba\x97br\xce\xfd \x19C\xefb\xfe\xe7\xa4\xb5&\xb3*\x07U\xb5\xc6\"Y\xcc\x89\xdf.\xcbi\xd9\x11\x9f\xc7\x1a\x05\x93Xp(\xcd}n\x9e#\x04\x97\xbe(v\x92\xc5\"\x13!\x88q\xeaa\x88kG{\xe5\xd41\xb9\x80\xecQ\x17\xba\x04U\xc8n\\\xfa\x86\xdf(\xa8'}\x8b \xd5GNU\x84Z\xe6=v2\xb0D\x86\xe6SoNwy\x88\xb2\x98\xe0\xcdv\x88\xdb\x89?}JA\x93\x0b\x16\xf4m\x82\n\xf5\xc6$\xe7\xf6\xdc\xfb\x13\xac\xc3\xdc\xfb\x01\xff\xff\x0d\xfc\x11\xd6^\xb7\x01\xf2\x8d \x8a\x0e\x1b\x1f3\x13S[\xc6\x15\xdc\xfe}\xec\xd8\xf2+\xa6v\x90L\xe0Y\xc7\x87\x8d.%|\xd3\x9e\x1b]\x9e\xbeM\x16\x04\xd2\x13\x15f\x02I\xf4\xb4\xe9V\xdc\xbe\xc3\x14\x16j@\xeb\xacS=\\\xbb\xa4+\xbc\xf6\xda1\x8e\x1a\xf7\xbbo\xd8|T\x17v)\x0eG\xb5o\x870\x81>\\\xd7\x19\xda\x9a\xfd\x9a\xc9\xeb\xb7\x1fl\x99\xa2\x85\x1ez\xcc\xea\xd9\xc3\x13d\xbf\x97\xc1\xc24-?\x8a\xfa\xa6$\x93\xaa\xea[\x8fa-\x9d\xf1\x10\x8b\x86`\x14\xdf$\xbc\x8a^d\x13\x0e\xe7T\x05\x1e\x9d\x1a\"4\x03o\xd2\x90$\x1f\xb8~m\xa4\xa7\xb1\xce).\xa7\xd7\xc8p9\xeb9\x0f\xb6\x14\xae\xaf\xf7S\x80\xe8!a\xe8\x1f\x90\x98F\xcc\xcbP =\x9b\xeb\xebn--\xa3\x10\x81(r\xf8\x08\x01;\xa6\xa4E.\x88\xf4iy\xcc0\xdf\xc6\x062\x18\x99\x1d\xf7Q\x85Z\xa6\x198\x98KM)\xeb]\xeb\x8f|\xe8\xa1-Ub\x87\xde\xf9\xd0\x8b%\xf3g\xbdg\xf7\xae\x00]\x0f\xc5\xc9\nP\xbc:luw\xbd>v`\x90\xe6i\x93\x08jw a;\x90\xd9\x89i\x07$\x14\x84?o\xa4\"dB\xaf\xf6\xd4\x91\xc7\xb4\x1b\xb6]\x05\x8a\xed\xb9\xaasmo\x0f\x98\x84\x07\xc2\xb8f\x0dk\xa7\x8f\x18\xd6\xc1\x9a@\x18\xcf\x92,\xa3\xb7u\x18\x9f'34K\xd2\xb9\x9a\xdd\xdc\xbe\xb8\xa3\x02\x14z~\xb5;\xf7\xf6}\x95\x9f\xbc\xc2\x86\xbb\xe4f\x01m\xcdc\xce\x9bi\xdb\x02F,\xb0W\xe3\xdd\xac\xe5C\xc2u\x1c\xa6\xdd\x98\xbb\x90\xaa\x08\xa8\xc0\x85\x85\x0b\xe7\xae\xb0\x07Ia\xbf_2\xd4Y\\\xf1\\\xa30Ze\xff|\xc5|Fq E-p\xeb\xd4;E\x13\x96\x0e\xdc(I\xe6\xb3\x9b\xfa!\xa20\xd5>sT\xf3C\x9dJ\x802|a\x9d\xe0<\x82\x00\x1e\xc3\xe9#8\xd5Y\x9a\xa2\x95\xe9\x92\x07\x8c\xbd\xb2}\x9b2#dzz\xecL7\x8f]XLG\x18+\xf0\xca\xc6wN\xed\xa7\xba\xc4\x9f\xb3\xca\x0cu\xd9<\x8ej\x13X\xa6\xf7\xc1da\xdcq\xea\x11\xaca\x97\xe7^L.\x0b\xdbq\xbc \x89\x89\xc6\x1a\xb7\x1alb\x9f\xbbp\xe5\xc2\x82\x07\x82\x82b\xd8\xd0\xae\x1d\xef\xeb\xb7\x07O\xfeL\xc9ezq\xbd=8z\xf7\xf6\x15\xec\xc1l\xb5C\xb6\xd3o%-\xe07\xe90\x90JFW\xe0:\xd8\x87\xc2\xa6\xf7\x14.\x7f\xcc\x97\xbfh_\\\x15\xafk\x8c,I<\xd6\xacB\xe6\x87\xe0'\xe1\xaf\x90\xa1\xd8\xb0rhs\xdb\xfa\xc6?4\x7f\x0d^\xab\xae!QR\x1b\x99Hf\xa0M@7Y\x98\x0c3\x1f\xe1+*\xcd\x11\xaf\x11;cv3L\x8c\x87\x86W\xd3\xe4\x98\x0b\xf5n&:\x8d\x1c/a\x98\xc3NuY\xa1f\x0b?\xf3g\x05\xc9\x9e\xf9\x85?Q\xba\x94q\xfb\x9c\xde\x85H\xbd\xc0/\xd0j\x8aNe\xde\x03\xdfJ$\\\xf5\xa1\x9a\x85'\xde\xdc.\xd0TOA\xf0a\x82\xb4\x12\xb9\xe0\xaeK\n\xac\x1aX\xa5\x90\xe3M\x88\xa7u\x14nLo\x18\x89\xfc\xa4%U\xed\xde\x7f\x82Y\x9b\xde?\x9ef\xc7m,\x1br\x16\xae\xef\xec'M3y`\x13`,\xd4\xac\xd3q H\x04\xe3\xaaB:\x1d\x1c\xc5\xd3\x12t\xfc\x01\xb8\xf3C#t\\fg\xde\x1bX\x87\xcc{kP1\xcd\xc3\xd8\x8f\xa2\xab\xa1\xd2w\x9f+\x8d\x93*j0\xe5\x88\xc5\x1f\x1a\xd1{\xacSr\xab\x92\xd9\xb4\xd5\xc7\xb1,\xa7\xd4\x1ab\xf3\xcfJ\xcchj;m\xbd\x8a\x89\xcc\xeal\xb4\xfc\xa8\x8c\xcb(\xebF\xa9\x8b\x8f<.\x86`V\x1b\x96^u\xf9\x11\x81\xb7\xebP\"\x02\xf7l\xb7\xc0\xf1\xd0\x00\x88E6\x18\x08\xf1\"\\\x84\xb9\x01\xdcB\xa5}\xad\xd0J\xc7\x1eACwn\x0b0\xa9\x953\x8e\x1d\xa3\xd2\xa4_M=dAc{\xfb\xc1}\xae\xa5\x7f\xc0\xff}\xd8\x8cj\xc7\xc3co?\xe4Q\xed\x1e\x8a\xf7;\xfc_\xfe\xfdC\xfe\xfdC\xf6\xfd\x0e%G\xf0\xdf\x11\xffw\xcc\xff\xdd\xe2\xffn\xf3\x7fw\xf8\xbf\xbb\xfc\xdf\xfb\xfc\xdf\x07\xfc_\xde\xde\x88\xb77\xe2\xed\x8dx{#\xde\xdeh[\x19e\x8f9\xdb\x0eY\x8b^0\x1aw\xc2x\x87U\x90J\xbc\x92\x9f\xf2\x10\x8f]\x94(WJ\x02\x82\xfe\xc1-\xc8CD\x88\xe6\x04k\xcc\xd0}\x84\xf1V\xaa\xa0\x19Ul\x91\x0e\x82\x94\x1b\xed\x83\xd0:o\x9f+\xb4\xdc8\xe9n\n?_$\xed{\x0c\xbeVL\xc0\xa2\xc2\xed\xc1z\x9d\xc8\xcf\xc78; \xc5'\xa3\xd1h{4\x1a9\"v>C\x18o\xfd\xf8\x8c\xebH\nYG\xe2\x03\xa6\xb3\x84Y\x12\x10H\xe9dtv\x96\\i]\xc0W,\xba%\xecc4 \x0cy\xca\xa2_\xae\x83m\x17\xb0\xb1\xc7\xca\x1dx\xfc\x18\x10~\n\xf8\x0f0\xda\x1co\xc3:\x8b\x99\xd9\x9b1\x17$\xfc\xcb\xb3\x0c[\xb7\xc3a\xbd`\xa6\x8b\x1b4\xda\xdcR`+\x0dPd\xfe\xc5pP`\xb15\xbc\xcc\xbf\xe0LiX\xcbnM\xe0A\x81\xa7d`\x12\xc3c(\x1f9\xc0-\xb9x\xe4\xd6bZ\xae\xaf\x1f;\x18F\xe2+&kiV\xa8\xc1\xa6<6X\xab\xf9w\xb3\xf4\xea\xeb\x83\xe2\xacM\xc7\xb6\x8a,\\Z&\x85y\x9b\x9bV-\xaa`\x059\x15\xb2u\xbb\x01\xf7\xc2\xca\x8e&\xd6\xdf\xa6:\xbc\xd4\xf6\xc3\xf6{\xba}\xd6\xd4\x82u\xf0YD\xce\xaeXS$\xdb\xfa\xff\xd3Z%\xff\xcf\xfac\x9b/\x8a\xea\xaau\xa5/\xda\xb5f\x03\xb8o\x90\x85\x12\x8aT\xb2\xc0\xc7\x1d\x0e#S\x04k\xb2\xe6O\xc9\xb1\xcd\xbc\xf3~\xfb\xf5\xff\xf8\xb7\xff\xc2\xe2\x9d\xf2\x9fX\xa6l\xe3Zs\x8b\xd3\xb5I\x98;s\x89J\xbe9\x86\xe3\xed0\xca\x807\xfe\x97_\x82\x9dLcZ;GWnA\xfbR\x94_\xca\x07\xb9e\xf9\xd2Z\x809\xec\xc1\xcc\xa3\xb0\xda\xc7\xa0\x81\x04\x8er0eT\x05\x8e\x803\xef6\xe1jE\x96]-w\xc1\xc2\xbc\xeccM\x85HTh\x11\x1ej\xc1\x82Z\x0b+\x8fT\xaem\xfdX\xfc\x18\xffx\xfe\xe3\xfc\xc7\x0c\xfe\xed_\xff\xeb\xff\xf5\xeb\x7f\xfd\xd7\xff\xf3\xb7_\x7f\xfd\xed\xd7\xff\xfc\xdb\xaf\xff\xc3o\xbf\xfe\x8f\xbf\xfd\xfa?\xfd\xf6\xeb\x7f\xf9\xed\xd7\xff\xf9\xb7_\xff\x97\xdf~\xfd_\x7f\xfb\xf5\x7f\xfb\xed\xd7\xff\xfd\xb7_\xff\x9f\xdf\xfe\xf3\xff\xfd\xff\xfe\xfa\xeb\x8f\xe5xs\xfc\x00\xff\xff\xf0\xc7rN\xe6sk\xc8\x19\xbb!M9\xde\xde\xc1(n-vF\x8f\x91g\xe2\x8a~\xd2{I\x0b\xd5q\xafm\xf3 $r\xc3 \xea\x02\x8a\x8d:\xe1%(n\xb1,\x8f\xc4\x01\xe6_Q1x\x14\xc8\xe9\xa7[\x8em\x89z\x96\x81\xa6\x11u\xfaVJ\\_\xa1X*\x17\xe4\xf6\x95\xe76V\xdcg\xf0\x18F\xb0/\xa5#\x1e\x1d\xd7\x06\xcc\xcaV2\x96\xf1\xc7\x1c\xd3\xacl\xe9Iy\xee\x1b\x11\xf9\xddN\xd0\xe493 \x18~j\x0d\xbc\x82O\xc7\xcdM\xe1\xd1\x0f\xb3DM \xf7\xdc)a\x03\xeaK\xbbd6\x15\xf9\xef\x02O\xf7\xc7J\xde_\x06\x8d0\x9eEe\xc0\x82]\xe8@C\xd4\xe9\x03\x8d\n\xed\xff\xa7D\x02\x8e\xba\x07\x0fS;\xbd\xc6\x08\x91\xab\x80\xc3\xed\x0ecc\x99\x06\xe3\x8e\x8c\xa4\xc4/&x\x83\xef:+v\xd9\xb7_\xa3\x91\x96\xb6\xb8\xa9\xb4\xb8\x0e\xdcO\x99`\x05x\xa3\xc0E\x91\x89>\xe4\xf1P[\"S\xf48\xe5a\xfaC\xd8\xdb\x83\x11\xdc\x83M\x05Ca=M\xca\xb8\xa8\x1d\xb7br\xe6\x17\xe19is\x12\x0f/\xc9\xdd\x0f\xbd(>\xc9\xd8\x93\xb8\x98%\xd1\xc78\xb2\xb4i:|\xd1\xfc\xc7<\xb6\xb4\xaf<\xfc\x99|\xbcY\xf0\xd6?\xe6$\xc2\xc2\x8f\xc2Y\xbe\xd2\x1c\x86L!\xfc\x14\x80\xb42\xf2\x19\xb4\xfa\x88\xf6\x17\x19\x99\x7f\xe4\xa5\xcf\x97~\x14\xad4\xfc!\xa3\x17\xad~\xf4\xc5\xa7\xef\xdf\xaf\x06\xfc\x83\xc6/\x9a\xfd\xf8\x13(O\xef~\xf4\xe5'\xc1\xfey\x99~\x84\xa1\xa7w4\xf4\xd8\x1e\x8d)\xb9\xbc\xf4\x8b\xd9\xc2rad\xae.\x0dfZ\xd5S\x8a?\xd5k\"\x1e\xc1\x19\x10\x93\x921\x91e\x0f(z\xa8\xd2\x99\xc5\xd3B\x9f\x19C2\xafO`_\xd8\xe11/\xaa \x9a\xc0q)o\xecL\x8bc!\xc8\xcf:qA >\xbe\xe1jrQ\xa3\xe5\xc2\xf8\x06\xeb\x99)<4`\xd0\x92\x86}K\xea7\x964\x93\x974\x1b\xb8\xa4\x12?\x91a\\\xb3\x04W\x95\xbd\xe1k\x19:,N\xd3\xdd\xadhN\xfc\xec\xdf\x01\xf4\xee\x963\x8d\xc2B \x9e\x1d\x03K\xfd: \x0dGl\x8fw\xda\xbe& D!\xdd\xd7L\xef\x86J\xb4\xae\x90\xc4\x9a\xa1\xf1\x8a\xe5\x9f\x9e\xce,\x9ew\xe2\x9e}\xea\xfc\xf1\x9eC\x99\xe3\x0f\x1f`\x1bu\x1e\x05\xc9\x8b\xba|\x7f\xe2\xdcsac$\xc2:\xd1zc\xac\xe7\x9f\xca\xb5|lH\xaa\xc4\x1a\xf3\xea:\xde\xbeC\xffkT\x92\xcb\x1d[*\xa3\xdc;-\xaf\x8a\xbd\xfd\xaaP\x05r\xe7\xdc\xf7Y\x12\xa8\xde\xb3\x9d\xfd\xfd{\x1e\xb9$3\xdb\xb2\xe8\x1c\x15P3DO\x02\x92\xad\x9a\xd0]\xaa\xe3\x06@\xd3'gOx!\xf14<\x95%\\;\x95\x8a\xfc\xedZ\"\xa7_\xab\x83\xe8\xe1\xe8\xd4\x9f\x9d3K\xff\xdc\x85\x08\xc3T\xcfY8}\x93\x93z\xc0B}\x86gq\x92\x91\xa7>\xc6\xf6\xb3B\x0b&\xf4\xda\x83uZ\xb6,\xa3\"\x8c\xc2\x18\x8b\x96\x8d\xa22\x0eQ\x11\xbf\x0fV\xd9(\xc8\x8bp\xf6\xfe\x8a\xbe\xbf\xe2\xef\xf5CX\x98}\xe4\xcf\x9b\xbbY\xc0>l\x8f\x1fn?\xdc\xbd?~\xb8\x83\xe6\xfe\x8f\x1f?65\x80\xd1g\xeb\x03O\xbc\x1c\x83\xa3\xbb\x10\xc0:Xg:\xfb\x01\x94\xfea\xd0\x06t\x8e\x90Z`J\xce%o\x876\xf2\x85\xbd\xbf\xf6\xe3\x8f\xb9c\xb9\x10\xa84\xd4\xd5\x83\xfe\xeeK\x06\x8b<\xbe\xe7\x9amG\x18y\x0cE\xcd\xb0\x0e\xf9t\xf3\xb8\x82\xf0\xc7\x80\xf1\xd5\xec\x94\x07?\xe12\xa5\x85+>p\x1c\x17\xd6\xd0\xb6\xbf!\xf1\xc2\xa4!\x9b\xc7\x95F.s\xcd\xe4O\xe3\xc1\xa9\xcf1.\x01\xcc\xe1\xab\xae\xe4{\x03\xc6\x8f`\xbe\xbe\xee\xc8;S\x8b\xd8\xe6h\xe8k\xe3\x8f=\xa5D\xbc\xf1\\;nw\xf0|9\xbe\xaaC0\xa2]\x00s\x14J\xe9\x07l%F\x0e\xcf.!-\x1b\x8b1\x1f\xb9\x90V\xad\xee\xc1\xb9\xe3|\x00\xbec,\xa3O{\xfb\xe8\xa0\xeb\xc1\xc19\xecC\xca\xcb6]8\xc7O:#hY.3\x8f\x06kS\xa0F!\xd3\xdct\xa4\x15\xb3\x07a\xb6\xe6\xa5\xd9FW\xb0\x0f\xd3c\x98\x08\x1cT g\xdb\xdc\xa0Z\xcc-\xd1\x08\x1a\xa2\xeb\x06d\xd5\x8d\x08\x01\x89\xac\x8ak\xb2*\xeb\x90U\xb1\x8a\xac\xcaV\xa5\x03\xcc\xf2\xfa\xd4\x8e\xed\xedQ[\xec\x9c\x88\x92q\xbb$\x14%;\xed\x12\x9f\x97\x8c\xee?h\x17\x95\xbchgk\xb3]\x94\xf3\xa2\xadNO\x11/\xb9?\xden\x17\xcdz\x03\xf7U)\x98\x88wrB\xf2\x97IPFD\x97C\x14$\x99\xff/\nW\x10\x8c\xbb\xc7r\xe2\xe9B\x99\xd5\xf9\xdex\x0c\x86v\x8a!o\xe1\xe7\xaf/b\x91\xbe\xb5\nC\x17s\x95\x0d3\xb6 \xdd\x84oP\x83\x10&\xa6\xf3\xcb\xa8\xe0\xa1\x99\x9a\xa0A7e\xbb\xb3Ts\xae|q\x1e\xfd\xa1z/\x96\x0eR-\x8b\xdaY;\xcc\xf4<\x18Y\xa3.E\x92\xd6Y0\xde\xdd\xd9\xdd\x1c\x05-E\x1b\xbdv\xad-o\xf4\xc0\x1b\xb7J\xe8}j\x9d\xfa\xf1OI\xab\xe0\x8c\x16\x1c\xfa\x85\x0b\xe3\x1dxR\x9e\xc1xs\xf4\x006\xefOv\xc6\x93\xf1.\xfc\xe9\xe5\x91t\x10\x86\xe9\ns\xb1\xf4\xde9\xc9\xf20\x89s\xbc*;/?|\x80_\xae]E\x89\x97_\xf8gg${\x17*\x9d\x97x\xb5 (\x02\xdd\x9e\x85\xc5[r\x1e\xb2\xf2\x85\xb2\xfcY\x98\x15W\x13\x08\xba\x85\xa7e\x18\x05G\xe1\x92\xe4\x85\xbfL'p\xd6\xad\xb2\xf4g\x8b0&\x93v\x0c\x85.\x07Ph\x1d\xaf\x82dy\x12\x06,\xcf\x94\x1ao\x06\xc9\xf2U\x12\x10S\x95<%\xb3\x89\xde\x88*\x8b&J5,/\xccMMG\xfeUR\x16\x13\xb0\xbe\xf6s\xf2\x02\xff\xd0\xb4\x14$\xb3\x83\xcb\xd4\x8f\xd9r[Q\x98\xebj.\xfd\xcbg,\xf5( \x8e\xfc3c\xff\xf30*Hf\xaa\x81\xe6\xa4~\x91d\xefp\x9e\x8b\xa2H\xf3\xc9\xbd{IL)^\x01=^\x98\xdc\xab*j\x86\xc5|\x97r\xfdB\xce\xca\xbcH\x96\xfar\x9eO\xf5uJX\xea\xaa\xe7A7\xa9N\xab.\xcfz\xf4\xac\xd4%\xbb\xaa\xea\x13\x92\xbe\x08\xe3\xf7a|\xa6\xaf\x94\xb1\xd6\x9e\xc7\x05\xc9f$-\x92\xacOc[\x7f\xc9\xb0\x97\xb2\x82f\xba\x19\xc9\xd3$\xce\xc9'\xea._$\x17\xe8\xd3M\x02\xbejj\x073\xa8q\xeb\xcb$ \xd1[\x12\x07$\xc3u\xb3\xc8\xa5\xbfL#\xa2\x83`\xe9+\x04\xe5\xe0\x19I\x8b\xc5\x04\xb4{R\xd7\xcf\x87|@\xa7ppY\x10<#\xb9~\x1fi\xbd\xa7\xc9r\x99\xc4\x83j\x97)\xc5\xc3$8,O\x97a\xc1\xa2M\xe4\x13\x98Zg\x04\xd5.i\xc9\xfeIr\xfc\x97e\xd1\xa5\xbf\x92\x94nU\x8e\xfa\x01\xe2\x07X\x89\xcb8\xad\"\xf3g\xc4\xd20\x9eiFrR\xd0>\"\x81\xb0u51C\x17\xad\xa9\xa9\x10\xc6a\x11\xfa\xd1!\xddX\xfd\xd1\x9a\xc7\x86c\x99,\xd3$\xa6|\xcb\xa4\xed<\x05jp\xa2\xfc?%\xd3\xe7^\xeag99D\xb9Y'M p\x82\x89x\x1c\x057\xf1:OF\xac)\xa5X?\xe5\xdd\xf8b\x8d\x1c\x9b\xdeq\x05\xd2\xde\xb1\xa2\xb7+\xed5\x91_\xe5\x05Y\xaa\xc8\x08\xf1T\xd8+\xf5\xf8\xcfU\x0eW\xb5M\xa9\xc7\xf7V\x03kl\x9b\xda\xb3\xd2\x8eJ\\\x1ff~U\xd4J=\xf6K\xdd\xb7x\xc4\x95\x90z\xec\x97\xb6\xb2f\xaeP\xdf\x98\xc6~X\x1d\xdd\xc5)\x1e\xbc]S\xaf\xcc\"\xfd84;\x01\xa9'C\x7f\x97@V\xc4&\xe8\xfb\xa4\xa2\xa7O)=\xdd\xaa\xdd\xfa\xbbEZ\xdb\xa7HRK\xfdS\x15\x9a\x078`\xb2\xdc#\xa5\xc0\x86\xb0\x073\xc7\x85\x13/'\x05\x1bCn\x97\x8e\x0b\x17\x02;=\xc1\x99\xe7^\x94\xf8\x01 0\x8fI\x9d=\x9d6\xb5\x16\xd3CE\x7fZ \xf2\x84\x16KQ\xb0\xe9BX\x8f\xb2\xc4y3^p\xd3\x85\xa4S\"%|ck$:.\xd3\xc0/\xc8\xbb,\xb2-\x0b\x07\xd6-|\x91\xf8A\x18\x9fQ\xe8/s\xdb\xca\xcb\x19\x06~\xd1\xd4>L\xc9\xcc\xa6\x83\xc8:\x83\xc0d)\xcdo\x82\xe4\"\xa6s\x07\x0c\xea\xc1g\xaa\x1d\"\xd6\xe8\xf4+\xda\xe0\xc5\xe8\x81#6\xc0\x81\x0b/C\xd2\xa7\xde\x14\x17\xac'i\xaa\x93\x97V\x91J\xb0\xfeI\xa8\x0d\xcd\x0f\x1c0s9\xb2\xc6\xdfK\x92] \xf8\xab\x9b\xd0\x8bR\xab\xe1\xe5bXj4\xc9\xa3\x89P\xe0\xc0T8\xbceL\x06\xd0x\x89`\xf7\xe1\x03\xf04\x1e\"k\xc7\xe1\xfb0MI\x00YM\x07\xc6 \xfc\x0bk\xe5_ \xc9\xf07\xfd\xf8_\xe0\xc2\xcf\x11\xed\x87\xf3\x90\x04\xbau\xe2x\xe8\xa2\x8b\x18\xba\xe7\xeb\x92bB\x0e\xf2L\xa6\xc8~\xbf\xcb\"\xa5\xac\x0d\xe5\x98\x8dM\xee\xbc\xa0G\x9b\x9d\xa8\xaf\xaf\xdeq\xb0Y3\xd6\xf8\xf0\xc1\xd8\x82\xe2\xfa\xc6K\xed\xb2;\x1d\nlo\xc92)\x08\xfb^M\x81\xab\xd8\x90\xd4\xeb\xbeU}\xa9`)\xe8\xa7\x9d\xd7M\x1c\xec\xc2\x01fb\xb0\x8d\xf3\xbc\xa4\xd5\\\xb8\xa0\x87\xf1@r\x03\xba\x96\x91,\xe9\xa5E\x1c2\xe1\xd8\xde\x19=\xe88\xf0\x8ev\x1c\x8f\x8b\xfd\xde\x93\xab|HC\xf5\xcau\xac\xa0\x99\xb6\xf5\xe1\xae4\xe1\xd8\x1e\xef\xdcwx\xbaM\x03\x95\xd1631\xbb\xed4\xb3s\x03\xacnX\"/C\xb3\xa3J8\x18\xdb;\x9d\xc0\xb0\xb5pq\xd2\x9fb\xb3\xb3\x03\xdc\x83\x1b\x1d\xbe[\xfbp\x7f\xdb\xf1\xe6rL\x94!-\x0e\x9cD{\x9bn7\x89\x9d1\xf3\x07\x1f\xdd\xe7~\xe4c\xeeW>\xbe\xaf\x04\xaf\xc3\xab\xe5i\x12\x0di\xbb\xd7J_\x9d\x8e\xb7\x13\n\x83G\xe9m\xe7\xb2\xe4\x913\xda[\xca\x83\xf4\xee\xb4\x83\xf1\xf2\x19\x8c\xb7\x1d\xef\xcf\x07\x7fk\x96\xb1\xd4\xa1;\xed\xf1\x88\xcc\xa1\xed\x011\x81\xf6\xc3vX\xa1\x94{\x87\xb4\x8d\x13x\xea\xd0\xb6O\xc2\xa2\x82\x94\xe6\xfbs\xfe^\x9d9tg\xdc\xae/2\x87\xb6'\xcc\xb2\x86n\xb5G\xc3R\x86\x8e\xdb\xb5Y\xc6\xd0N\xdc\x87\x0b\xbe\x9a\xed\xb9\x1e\xb0%h\x8f\xf1\x92Wo\xcf\xf5\x90\x8f\xbd]\xff)\x1bL'X\xca{\xb6\xe5\xed\xd7O\x04Bj\xbe~\x0d{\xf0\xb4\x9d$\xf4\x0d\xec\xc1\xfb\xf6\xcb#\xcc\xfb\xd9z\xf9\x12/\x08\x06\xd7\xcd\x92\xe7\xd5\xd5\xd1|\xff\x13\xec\xc1sJ.<\xafQz\xb3\x06\xbd`\x02\xdb:Y\x84A@\xe2\xb6\xca\xff-+-\x927Y\xb8\x0c\x99\xbfM\xb3\xc63\xd4\x03y)g(\x9f\xe7\x07q\xb9d!\x91\x9b\x15_\xd0\x1b\xd2\xb6r\x1c\xfd\x06c\x05\xb3\xabvs\xef\xe4Z\x9dd\xc6\x7fg\xa5I\xba\xa1\xa9\xf0\x0d\xecu\xb4I\xcd\x1a?\xeb\x02\xc2\xbcl\xd6\xfb\x1aW\xf4/\xac\xb1f\xd1\xf7\xb0\x07k_cf\x88\xaf\xa5\x8c/\xad\xbf\xbdy\x18\x07O\x17a\xd4R4|\x0b<\x82odvr\xe6w\xce}X\xdb\x83K\xfb\x0d\xf2fh\xd7\xab&\xd0\x87\xc5\xd8\x82\xba\xe17\xb2\xad\xb0Y*\xc2\x93,\xdf\xd7V\xbav\xbcn\xd0#P\x8aA\xae\x9dv\xddkG\x0eg\xa3\xb1]\x03 !\xbf\xb6\xbfQ\x9b\xd3d\x92\xac\xe2\x9biq\xec\xc2\x9b\xaa=\x1e\x10\x92 \xb7\xf9\x0d\xfd\xf9\x06\x9b\xe9\x04\xc0\xbf\x86 \xbcin\xd9\x0f\xbd|\xbb\xe0\xd9\xdf1\xaf\xf1K\xfbe\x0d\x08&\x1d%fL\xef\xaa'\x9b\xdd\x7f\x07{\xf032\xc5\x0c\xea\x1bP\xeb\x89\x9b\xbb\xb1\x88\x06\x80R4B:\x0b0\xa8\xa5F\x94\xfd\x97\xa6\x19\xfcm`l\x80\xaa\xe1=\xb1I\x7f\xb3\xff^m\xe0\x15\xcb\xe2\x02{p\xc13\xd6\xd1w\xb4$\xb1\xdf\xa1\x91\xc4>\xc6\xd7\xa9\x10\x10f\\\xa5\xfd\xbdby\x85\xa7\xaf\x8e\xa7\x053s\x11\xbf\xf7x\x0e\"\xdc\xb4Xw\x10\xea&)\x17\xb1\x89\x89\x8bT\x90\x0d\x93\xba\xc3\x0f\x1f\x18\xf4\xbdr\xe1\xc0\x1ea6uJ\xa6\xd4\xfd\xd2\xe1\x7f[\xad\x06\xfd\xb6\x86V\xd3b\xfey\x88q\xc8\x95\xd2\xf5\xad\xd6\xbc\xb3\xe0\x1fK\x9e\xe8\xb3\xa0CKXj+\x16e\x97IP\x98\x1fe\xf2\xc8\x81\xbf\xa1\xfe\x1d\xc3\x05&\x18\x06\xa60j\xdf\x8d)7\xfe4\xf88=k\x18\xaf\xe0\xc6\x13\x96\xaaP\xdb\xf3\x1a\xd6\xae\x01\x08A\x83\xe5\xf7\\K(0\x11f\xc1e\xaf\xd9\x05\xa2\xec\xda\x17\x9f\xff\xf9N\xfc\x16%\x0cz\xe8o\xbay\xe4\x18\x0b\xdbv4\xcd)~1d\x8f\x98\xdd\x05]\xff.\\\x0b)\x11\x89\xa9\x9e\x94\xff\xc8\x11{\x82\x87\xcd\x17\xb3\x8a9\x04\x7f#v+dSz7-\x0c\xe70l\xce\xaa\xae\xf73nmi\xdb/M\x81\x0d1\x08\x14=N2\xa2\xef&\xc4\xb0\x18IZ\x87{\x92\x92\xd0w\xf2b\x9c\xf3\x8cj\xa9\xca\xebw\xb3\xe1\xf5\xbb)\xf9\xe6\xbb\x9d)6\"B*\xaf\x13\xe0Y\xdajl\xc0SZ\xfe\x9d](\xcd\x03\xce\xfe\x9a\xbe:\x16\xf8\xc2\xae\x8f\xbc\xb8'\xbe\xad\x0d\xe9\x10\xa9\xab\xd2\x1d]+\xa5|H\xf2}O\xff\xf7-\xdd\xc3N.@\x18\x14I5\xa7T^\x8bXp\\\xf8\xa1\x99\xeeM\xce8h\x15I\xe5\xe3\xdd'\x04)0C\xdf\xfb?\xc8M?\xc5\xa4t_\xb8\x94E\x81=\xf8\x1bF\x90\xdby\xe8\xe0_\x87\xf8\xff\x7fF\xae|\xbc\xc3\xde\xfd\x89\xf1\xe8\xbb\xec\xaf\xbf\xf2\xfc\xc6k\x94\xdf\xdc\xc6e-\xe9\xfc-\x15\xc3`\xb9\xf4kD0\x0b\xfc\xbaWR\xf5\x83\x1d4$2t\xc4\xbe\xedc\xaa;\x1fS\xdd\xf9,[\xda\xcf\xed\xf5f ;\x91\xe8\x16Y\\V\x1d\xe7\xbfPva\xe1\xe7\xcf\xf9\x01p\xc3\xfci\x12\xcf\xfc\xe20\xcd\x88\x1f \x9b#(0\x17\x9d\x85\\n\xbd\xeb2\xd7\x0c\x97\x07\xe8u\xd1\xde\xd3\x958)W\xec\xcc\x91\x7f\xe6\x96q>KR\xda\\.LC-\xd7\xa2\x17\x01a8\xe2/\xf5!!\xe4\x91\x03\x81\xfd\x97)!\xcd\xb4\xe65\x12\"\x98\x8f*\xf0\xf2\"\xc9\xe8\xe5\x12\xf3V\nR7\x13\xd3f\xce\xed\x82L\xe3V;t\x05\x0f\x1bk\xc7Ox7B]\xbf\xfdG%;{Ao\xb5\xf5=\xb47\xdf\x87\x17\xf4TM\xd8?{\xdd\xe4\xea-\x04\xfc\x9e\\}\xd3\xdf\x15Z\xe0\x7f\x87\x16\xf8\xc6\x9c=>0\x1a\xb8\x83\x9b\xa0\x19<-\x8c\xe1\x85ZCA{z\x81t\xdc\x9e\x9c\xba\xc3H\xc6\x9799$\x05\xaa\xb1\x8d|\xda\xf7\xaa\xf0\xc0\x9d\x96\xc2e\x1a\x91!-5\x93\xcd^w\x8eJk\xa3\x19\xc3\xdb\x8dq\x84A\xd4\x07$+\xedZ%\x17\xb0\x0f\x976\xa6\xa5\xfc\xb3}\xc9h\x1d\xe3f\x07d\x1e\xc6D\xa8\xa8'\xf07CqH\xf2 \xfc\xb9Y\xe1\x8c\x14\x92\x8a\xfb\x19\xc9gY\xc8\xd4\n_\x98*\xbe\xf2\x97\xb4\xb1\x7f6\xd5a\xc7 \x9f\xc0_\x1b\xeb\x88\"\x96\xe6b\xdakx\xc5\x1a\x98|q\x11\xbel\xc7<\x16\x8c\xda4.\xa3\xe8\x18c\x99\xfdd\x0b\xba\xd3\xfa\xe5\x9a\xbf\xe9\xae\xbd\xdf1,m}\xc26\xb7\x851\x1d\x17\xac\xef\x0e_\xbfR\x04\x01\xa9\xb4\x0c+\x10?\x9cd#\xc7\x8c\xa3\x18=R\xc5\xe0\xa1,\x05\xa7\xc9\xea\xeb>ib!\xf1\xf0L\xde\x9c \x1a\x1d\xbb`\x9f\xda\x9d\xa4n\x9c\xc4\xffN\xf6\xbf9\xe3\xd5\xecb\x089.\xfaRJ\x87X\x987\xa44;\x06\xf5\x8eK\xfb-\x1c\x0d\x1a\x00\x0e$t\xect\x1a.\xfc\xc4\xb5*\xcf\xbb\xc2\x87\x06XIB\x84\xe9[$\xc6c{g\xd3\x91\x85\x0b.\xbcm\xd4cI\xb6^\xcf1_\xe8\xcb\x1aq\xb3\xbf\xfdb\xe1\x82E\xff\xb1\xf8=;\xe7j\xa6\x1a\x06\xd66\x07\xa9\x00j\xe9xG\xca)\xa2B\xa9\x93\xd8QBaU\xbd\x94\xe0\x073e\xda\xb7\x98\xc5\xe5\xed\x1a\xce(2HV\xa0\xea\xbb\\\x00O\xf1\x11\xed=\xf4\xe6,/\xcb\xe6#(kH\x8d\x1e9\x90W\x16\xe8\x94`/\xa7\x11\x12\xe5HN2\x10V\x1f`Ia\xb8\xda\x8av\x84\xdb\xc2\x9b\x90\x92]\xdd5\xfd\xe5\xda\x13\xa4D\xb3\x10\x83\x03\xd5\x86\x14\x02\x96/\xc28H.P\xc9\\\xfd\xe2BS\x05F\x84}C\xa1\xcdZ\xa0\xb8]v\x8b\xab\xb5\xa3\x83\xa88\x0c\x8akM\xd9H\xe1\x07l\xf2\x18G\\\xe58\xeb\x95n\xe9\x93\xd5T\x04\x88\xca\xda\xaa7\xf9\xbb\x18\"w\xf4Q4\xd1<\xc06\xcf\xbf\xdc\xd4\x14\x0e\x02\x00\xa6K\xb1-?\xbf\x8ag\xcfWR\xc8\x89OY\xfa\x12\xa4\xa5\x07}\xa7\xd6|\x15\xde\xe9UA^\xb0#0\xe4\\F\xdas\x89\xe9\xa5:%\x19\x96\xb4}:\xf9Ro\xd1\xdb\x13\x83/9p\x0f\xb6aC\xe2\xcd\xaf](\xbc\"\xf9\xfa\xaa <3\x9catm\x9e\xfd\xa4\xb0\xe7\xce1|\xf5\x15\x8c\x1e\xc0\x87N\x11\xac\xc3\x88\x17\x8f\xd5\xc5cV\xbc\xab.\xddr\xe8JL\xf3\xf5u\xbc\xa60\xb2\xf2.| \xe3\x9d\x9d\xf6\xfb\x07\x9d\xd7\xe3\x9d\x1d\xf8\x12Z\x89\xa4\xc6<\xc5\xb5\xb8:\xd5\x93\xd1\x0c\x96\xce\xe5\xf1c\xd8\xeev\xd2\xc2\xb6\xa3A\xbd\x8c6\x8dK\xb6\xad_\xb1\xc7\x8fa\xa6\x87wZ\xb0u\xfd\x12v\xb7\xe8\x0bko\xcfB)\xf7\x98\xb7\"\xf6\xcbf\xed\x8cq\x1f\x1e8\xb0\xaemx\xb4)Z\xa6\x80Q\xb5\xcc\xbb\x1aK]Y\xed\xa1\x0b)L7\xdc\xf4\xb5\x82\x7f\x16B\xc7D\x12>Ze\xcc8\x8f@N\x0f\xfb.\x8c\x8b\x07l\x1f\xf7\xe5?&,\x9f\x0b\xdb\x14\xeb\xc9\xd7O\x9f\x1d|\xf3\xa7o\x9f\x7f\xf7\xe7\x17/_\xbd~\xf3\x97\xb7\x87G\xef\xbe\xff\xe1\xaf\x7f\xfbg\xfft\x16\x90\xf9\xd9\"\xfc\xe9}\xb4\x8c\x93\xf4\xefY^\x94\xe7\x17\x97W?o\x8e\xc6[\xdb;\xbb\xf7\x1f<\\\xbfg\xf1h\xdc\x0c\x8f\xf8\x95t\xbe\x84\xaf \x7f\x04\xeb\xeb\xa5\x03\x19K\xc6\xedOK:\xf0\xa9/\x83r\xe9`,c\x95[[\xa4\xc7\xea\x02\xd8\xba\x84U\x01\xff\x01\xb6)\x1a\x13\x8c6E\x9e\\\x16\xf8\xc1vn\xc2\x84!f:^9mfw\x1df:\x8c_g\x8cB\xf7S9:z\xc1v \xa6\xff\xac\xef\xc1\x96\x83\x00c\x13\xba\x13\x14\xe5P\xec9\xda\xbd?\x1a\xed>\xd8d>\xf6\xd3\x92\x9e-\x06\xe9\x14\\w\xc6\xbc\x84\xa1\x0fV>>\xa6\xac\xb9\x80|;\xc4\x8cZ\x08\xff\x0f$\x98\x0f\xf1\xcd\xb8\xfdfWz\xb1\xbb\x05_B\xd8\xe6\xa9*\x8a\xa6{\x14\xaa_\xc9\xd4\xda\xb0d\x08\xdaD\x08\xda\x1dS\xd0\xb2NTE[JzC^\xcd\xc2\xcb\x88\x1f(T\x81<(\x8a\x02\x0cCW\x10\xea\x0f\xe0\x8f\x90PZ\x80b\x06\x85`\x94.\xfc\x88\xaek\xe9\xa8k\xa0\xbf>\xaeY\xb7\x8c^\xcb\x1b\xf7\xbb\xef\xd1~\x06\xf6\xb1\xe3\x11LT\x01\x0bR^e\x83\x96+\x9a\x0e\x10QR2a\xde\"w\xb8\xc3\xfe\xfa\x1e\xa4\x0c\xc3\x04\xf0%\x9f\xc3\xc6\x8cM\x02\x02x\xfcx\x0f6f\x94rX\xa7'\x18f\x18\xd8\x14\xeb\x8fwv\xe1\x8f\x10\"\xc2d\x1d\xb8 \xda\x9b\xc1\xc6\x1e\xcc_\xf9\xaf\xb8\x8c\xa7\xc0\xb6\x18x\xec\x83\x8dY\x04D1o\x92!\xef\x19j\xe9}\xd1\xd6R5\xcf?\x85\x0dX\x1c\xc3\x87=\x18\x8d\xe9\xc1:o\xddp7b\x8a\xb9\x10\xa4)\x9c\xb6\x0b\x17\xac\xda\xac\xb5#B\xe5\x96S\xb2\xb1\xab4bAj^)\xa3G$\xbcd\xac\x8c+\x81%[\xaa\xb8\x12X\xa2\x8a*A\x0b:_\xe4\xbc\xa0\x13l\x82\x99\x9a\x8e\xef\xb7U\xaf\xcc\xd6\xb4mf9\xc7ff\xad\xb7)o\\\x11\xe6\x82\xd9\x9a\xee\xec\xb6\x03]/\xaaO\x1e\xb6?\xe1\xf6\xa6\xe3v\xdfK1\xb7\xce\xac\x99\xc5\xa9&\xa0\xc3\xd5\xa7\x0f\xe8p:D\x1a&%\x1bm\x82\xca\x89IU_M\x8b(UA\x92t\x9e\xb15J\xe5{\xed\n\xb8\xd6\x88\x0d\xb4y\xdc\xd5\xcb\xab\x82\x7f\xb4\xdc\xc9\x84a\x8d\x8b\x05i\xbb@-p\xcb\xcd^\xc1\xbd\xce\xc5+\xb8\xcd\x9a\xbc\xe3L\xde\xc7\xd0\xf1@\xd6\xd7\xcb\x92\xa4x\x1eS\xd4\xd1S\x11\xe7\xfdF\xccN\xe1\xd4\x0c]M\x99xN\x932\x0e\x0e\xc5\xc45\x95\x8a$\x89N\x93K\x8d\xc34bz4\x00\xa8\\\x18\xe9\x1d\x81\x16\x01\xd5\x1b\xef4\x8c\x03\x1e\xf0\x87\x95\xa1\x82\x99\xdd<{p\xeaVn\xd63\x14r|w\xc8\xf6\x9ayUr\xe1[\xb3\x93\xfe\xb0\x85\xe2\xa9\x18s\xda\xfe\x99\xc7\xf6\xf9hQ\xc6\xef_\x86A\x10\x91\x0b?#\x8e\x1d;\x86\xc0i \x06\xf2\x12\xe1FNN\xde\x1e<{\xf7\xd7\x93g\x07\xdf\x1f\xbd~\xfd\xe2\xf0\xe4\xe0\xafG\x07\xaf\x0e\x9f\xbf~u\xf2\xf4\xf5\xcb7\xaf\x0f\x0fNNP\x87\xc7\xbcGsE$\x1c\x90\xc8\xc6M\x97\xd6D=\xe9!\xaa\xdd\xf9\x84\x12;b\xfa\x9ez\x98\\\xffS\xa5*wTf$6?\xaf\x8eXk\x0cO\xc2\xbdK\xd1\x1a\x05\xdfVN\xb5\xf8\x17?\x1e:\xadRk\xbce}$\x89\x0b\xd3\xee\xba\xbf'W\x13\xb0\xe8f\xd1\x19)\xdc\xa2\xf9\x05gTCC\xcb\xc2\x04a\xa6;\xdf\xe6\x90U\xe8\x81\x8dFLx\xc0hz}l\xd7\xd4\xa9\x07txp\xc4t\xb0\xf2\x0b=\xb0\xc9y\x80\x81\xd8&\xd0\x16\x0f\xe5}\x18t\x879\xa37\x1cJ\x91b\xc09\xfe\x1a\xc5JNC\xdb\xa8\x06KU\x9b\xdf\x94\xf1\xac\xf1-\xb1\x0b4\xa0\xd5y\xf9\xaa\x1aQ\x8c\xc0[\xfai-:\xd7jW\xe5\xa7\x1e@\xc7\xde\xb5\xfd\\;^F\x82rF\xec\x0b4\xa35\x0f\x957\xacA\xa0\xc0t4mTg\xeb\x02\x00^p\xfc\xc5qU\x8c,\x01\xb7\x06m\x1cH\x85\xfe\x03\x9a\xd7r\x1f\x00\x08\xfcF\x9b\xd6O\xf1\x9c\x07\x17U\xc0\xedX\x0b\xb7\xe3\xe6\xfd=>\xeeq\x0d\x07Nd&\xde\xc2\xcf_\xa0\xb7\xb6yD(T\xd0W\x19\n\xd3\xa8\x07T\xa9\xdf\x0b\xcf\x9f\x17${\xc1\x9d\xa7\x91\x83X\xdbt\xe1\xc0\x96J\x1cY3\x1f\x9bB:\x9a\xcf\x84\xdc\x0c?\x1e}\x1e\x12\xd52M\x14\xd9\x9f\xc5c\x82\xdc\xbb=`\xcd\x99dB\x18\xd1\x7f*\x07\xcd\x03\x00TY\x80\xeb\"\xfd4\x85\x95\x18\xb0z\xd3\xc5\xbb\xa1\xad\xf0\x18T\xba\xe3\xd13\x02\xceG\x16\x82K\xe2o\x06u\xfe|9\x81\xb9XZ}\xb5\xb7\xc4\x9f\x15\x93:H\xa2\x1as\nn\x8cqi\x12\xcf \x18\xc6\xe5\x96p\xce\xa7u{p\x92\x07\xa9\x8bX5xdw9\xb0\x01\xc2\x82!c\x87\xce\xf8\xbbo\x0c3\xcaW\x99\x91\x96\xb7Q\x0c\x14\xf6\x14q\xf7\x06\x0f\xab\x894\x07\x0c\xcdxE2b\xc4p\xef {(b`\x0bLmW\x97\x18\x9f\x99,.a\xbea\x8c|JN\x7fz\xe9\xa7\x0e\xbdA\xfa\x97\ndZ\x89\xf1\x18\x99fW\xb9\x87V+\xd6\x0f\xa9X\x93\x9a8\x1bB\xe6\xf7RH<\xc6-F\x82&\xd3\xf8x\x85H\xe0\x82\x10Y\x91\x0c\xe9J\xf8br\x013\xef\xa5\x9f\x9a\x19\x05\xe0\x84\x89\xcc\x15\xf7s\x93k\x99)\xc2\xb0\xfc\x08\x93\x80lZx\x94\x1d\x18\xd0x/\xa3\x0d\x12'u`\xc7\x8e\xc9_N~\xf8\x88\xab D \x97\x0c'\xc6/\xf5\xac(\xa8\xc4\xbe\xed\x07aO\x0d\x95\xc8\x0f\xbbm\xa8,\xe4\x08X\x9b.\x04\xde,Y\x9e\x86\xb18M\xb9\xc3r\xea\x9f\xf6&\xc97\xa3\xdf\xa3\xabt\x88L\xa8W\nC\xa6\x9b\xc7^\x91\xbcKS\x92=\xf5sb\xa3\x11P\x15+\xbeW\xec\x86\xa7\x9e\xcd\xcd\xb1\xf5H\xa2\x1aP\xacH\xe7!?\xe7<\xb6y\xac\xcc\xf8-\x1eTT;\xf28\x92&}\x9c\xc1:\xc5u\xa1\x9aU\xba\xcd\xa5L\xc9\x13A+\x0f\xd8\x80!\xb72\xdfN\xdb\xca\xab\x86o7@N\xef\xdfbx\x02\x915\xc7\xe7\xf3v\x07\x82\x05^\x06d\xc5\xcb\xa0\x03T\xc4`\xd6\xa2z\x1a\x02\x06\x8a^\x1c\x13\xa0\x14\x9dL\xe0\xf2\xa3a\xb5o ?j\xeel\xc0n\xf5\x9ef\xba]\xc3\x98\xd1\x06_\xa8\xf2W\x07\xdd\x86\xc6\xcd\xfd\xe8\xbfpi\xaf*\xac0\x8d\xeb\x0c\x0e\x1b\xf7\x9dc\xef\"\xf3S>\xa4\xdeK:\xe3\xf8U\x03h\x03\x04\xbe\xe2\x0e\xca\xa6q\xcf\xb5\xc6\xbbD\xe3K\x14\x10 A\x91\x9d0\x1f\x17\xb4UL\x8e\x1d\n]m\x9ad\xc8P@Z\xaa\xde\xa3\xd9~\xc4\xbd\x88\x87\xa3!\xaci\xa9:\x14Q\xc4t\x8fB\xbf\xd8~\x90\x90\x90\xcfY\xe6\xc8\x16\x89\x92\x87\xb2\xb4\xad\x10\x13\x12\xe4P$\x954\xaa\x96\xd2\x16\x0b\xbf\xe0\xafs\xf0\xb1\x91\xaa\xcc\x0e \x14\x0b\x02\x17\xec\xe4\x00CD\x8e\x0e\x11\xc9\x0f\xef\xe8\xc0\xcez$\xdd<\xf0\xe67\xbcO)\x88\x08\xbd\xafM$\x82\xb6\xf8n\xf1\xc4*\xd7\x8e Q\n\xa2\xce\x8c,\xb26\xb2\xa8%D\xfd\x01\x0e\x9a'S\xce\xa5\xa3J\xe7%?\xe2TN3 9<4)\x16A\xb87)qL\xc2\xd0J5\xf8^\xc4\x12v\x10K\xb1\xc2\xf0A\x16\xcaO\xb3a\x88\xc5\xef\"\x16\x9f!\x16\xb4x\xf5\x99M\xaa\x82\xd9\xe9\x1d\nH\x14\xd5\xca\x88\xa5\xb2\xbe\x0d\x15\x1c\x0d3Mb\x83\x0d\x1dn#\xcdlr\xc3GP\xae\xaf;h\x0e\xdd\xe0M\xca\x9e\xe5\x10\x8f@\xf1\xc8\xcf\x990\xda\x94\xcb\x8b\x9e\xc7v\xe2\x1cS\x8e{\xe6\x17\xb6\xaf \xad\xdb\xcfM\x10\\hBp\x02\xc0~?\x0c\x17\xf6\xa1\xb7\xc2\x80\xde\xd4<\x0e\x08\xf4\xa6a\x81n\x87\xdeP\xca7\x08\x99\x0d\x90\x94fM\x0b\x17\x15.X]^\xd0\x14\x08\x10\njL\xec\xad^\x0e\xf7v\xe2\xbe\xa6|\xfd\x1fg]\x06#\x16\xc1m\xb3C\xabr\x11\x15\xcf\xf5G\\\xe3o\xe2\x01K{c\x99\xe5\xc4+\x93\xc7z\xeaV\x83\x92\xaa\xb05<\xb6\xf9\xbe~\xf4\xd0\x96,\x8b\xb2[m\xce\x9d\xd2jJz\xaa\xd2\x98T\x14\x99\xb3\xa2\x84EEa\xf5RFz6\xb0\x97\xc1\xe1-\xf4\x1e/\xf9ix\x84u\xc9\x8f\xb0\"?2\xa7\x8a\xe6\xe4\xc3W\x90=\x02\x9f\x92\x1f\xe1\xd4o\x92\x1f\xfe\x00\xf2\xe3\x9c\xa7C=\xb0cAl`*$\x0d\xa9\x11\x1a\x93W\xf2\x87O^i\\\x81\x89(m\xd6c\xe9\xd8\x85\xcd\xa2\xca\x1b\xdb4X\xd7|\x14q\xc5] )\x08\xc6\xe6\xfa\xf0\xa1\xa3\xf1\x13jt\xf5R\xcah\xca\xab\x85[\xed\xc8\x1d\xe2Q\x9f\x18\x99\x84\x1f\x80nl4(<\x0d\xc5\xbc\x9ff\xc4\xa7\x07\xcd\xa9\x10\x17\x90\xc1\xa6 \xd2\xc6\xd7\xce\x8b\x85\x99\xcd\xe8k\x1a\xe4\xeb\xb4\xe8\xb3\xe1\x82\x017\x9b\xfc\x08\xe9\x1f\x05\xfd~\xf8\xd6\xbb\xff\xb7\x1f\x94(\xdeB*!\"\x06\x0cZ\x1e\xe0\x1d\x0e\xabI\x1f\xba5\x138\xf7^\x1d\xfcpr\xf4\xed\xdb\xd7?\xbc:9x\xfb\xb6_\x03#\x1e\xcc\x80\xa0\xcf\x92\xa5zR\xff*J\xfc\x80\xa5\xf8Y\xc8j\x84AM\x98\xb5\x1bX\x03\xe6a\xecG\xd1\xd0-\x12@\xd5[\xd9\xdc\xb5\xc9\x02\xb0p\xb42\xd7[b\xaa\x97~\xca(\xe8\xe4M\x96\xa4C\x90\xd5\x10\xf9\xb7\x11\xcf\xf4\xb6\x04M\xac\xd2\xb2\xe3!\x03H\x9a\xdb.\xc93\x8e^\x87\xaf\xca \x92q\xd8\xb2\x0c!\xee\xec\xa6\x87\x02\x8a\xe5\x0dVL\xc8\x81\xd5VG:P\xea[\xb6c\xfam\xf5\xea\xdaV:\xaa\\hCG\xddZ\xc5\xab2\x02-\xd4\x0d\x9b\xac\xa2\x1b\x0d\x8fT\xde!\x0dA\x860\x03\x95\xb4\"\x83\xea\xcbF\x9a\xcd\xea\x05\n\xd8j\x96\x04)\x9a\xd6\xd5\xd6\xaa2\x80Z\x15T*\x91\xc8r\xe6\x1a$\x91\xf0*\xf9\x1a\x067\xe8H\xe9\xf7\xc1n}\x89&\xb6\x9c\x8c\x9b\xc6\x14\x18x\xf4\xea\xf6`\xa7\xd91\x86\x95\xc1yu\x1b\x99&.\xc4\xc7\xc6\xaf\x9bp\xa7\xd0\x19\xb7\xbe\x91\x13\xfdk\x9a\xd5\xba\xee\xcb\x8c}w[\xdb\xbb\xaa\x8a\xa1Y;\xddC\x18\x9b]B\x98\xa261$\xe5ow\x18V\xa9\xa3\x1aoe\xd5\x8f6\xc2.\xc8\xb2\xd5a\xca\xa2j.%\x9d\x8b\xdfG6\x9c\xf3,K~\xaf\xa8\xb2 `9\x93\xd6\xd2O\xa7\xf9\xb1+$\x9fye\xb1\xde\xd8\x96\xee\x9bir\xac|)O\xb2\xb7\x02\xed\x13\xe3z\xf4Ub\xf3\x13\xb0\xdfW\xdd LU_\xf2}\x88W\x8d\xf4I#2\xa1*J\xc4\x81>Z\xc6\xaa\x9e$*\x9c\xe9xQr\x86\x02]\x850$\x96\x93\xa9\xef1Ij\xcb\xf7\xc3D\xec\x0b'F#\xb1\xa0'\xa3\xa5\xb0\x98*N8\xab8\xe1B\x84\x12\x7f\x04 |\x05\xc5#H('\x9cQ\xf8\x92W@wb\x05\x82GcpN\xa7\x13\x17\xa6\xf4\xba\xaf\x00&SY\xae\x0c\x8d\xe5\x85\x11C\x9a\x19\xc3\x08\xcfE\xd7\x036\xd7\x7f\xe8\xfe\x92\x13\x8d\x9f\xe0\xdb\xdeX];[c\x85\x17\xb0\x9c\x14\xa9.U\x07\xc8S{\xca \x9dE\xdbI\x99\xb4\xa3\xca_\x0f\x19g=\xae\xf1\xa64\xdc\xcc\xce0\xcce\xc6b\x86\xb2|7\xda\xb8\xa1\xedX\x9e\x98+\xc5\x9b\xd7#q\x86\x0c\x85.\xd9\xb6)\x87\x94\x9f\xe7\xe1Y<\xa4\xa9\xfeY\xe9'\xc3z\x99`\"\x98-g\xc59\x98\x93\x0c\xc9\xa7\xf2Z\xbd\xfb\xd9\xed{\xa1\xeb\xd8\xf6\x9ef\xb1\x055\xc1\x1a\xb7\xd4\xb9\x8cv\xb6\xdaYyJ\xcc\x1aP\\$O\xf8\x01\x7f\x93$\x11i\xa5{\xc3Yx\xf3\xa4\xccL\xb5\"\xd8\x83{?\xde[\xbfw\xa6\"\x86gZ\xbfi\xdb\xb2`\x1d\xd0\"\x13MG\xed\xc8\x05\xeb\x8b/\xefYf\x94>W\xca>Q\xd0C\xeb\xf0\xfc\x1c\xf4\xcfY\x12\x17\xe4\xb2`1<\xf9\x9b2\xa6\x7fo\x1a{Hu\xe7Ul\x0b\xc1\x9e\xba\x18_\xd0\x9e\xd8m\x0b\xd33_\x99\x84\x19\x0f\xb1\x81\xac\xaf\x9bg\x1aHaI\x94\xf3\xcdH\xce\xf0\x98\x98\xf1{r\xf5&#\xf3\xf0R\x9a3_\x94\xb8\xb3(\xd9J\x8b\xb2\xe8_\x146\x9c\xee\xb2\xf8XZ\x8d\xad[\xa14\xaci.\xafi\xb7\x98\x02_\xc9\xd66o\xadms\x03\x9a\xc4WD\xa9\xfbs\nq\x19\xaeo\xe8\x15\x0b\xbfx\xcb\xd4\xac\x02\xd8)\x05\xcf\x13\x9e\x02\xcb\xe1\x98xa\xfe\xbd\x1f\x85\xc1ADh\x0d\xda\x0e}\x1f1\xc6 Jb\xf2$\x0e\xde2x\xfe3\xb9\xa2\x1d\xf8\xb0\x0e\xf6ZD\xe7\xcf\xe2\x9e MF\xff\xa2T\x01{\xbf\x0f\x96\x05\x13\x98\xd9\xf8\xa7\x03\xeb`\xdd\xb3\x1c\x0cU\xe8\xb8\"\xf0n\xe4\x98\xc1\xe5\xdc\xee\x0f\xcf\x04{`Y\xcd\x85\x113dq\xb9h\x8d\x19e\xc0\xd9\x10\xba\x1c\x03\xdd\xab\x802\xd2\x88\n\x02\xbb\xc0([\xd8a\xb3\xb2O\x87\xb3p\xa1\xa4\\\x92\x97\x91\x88\xf89\xb1K\xf3\x1c\x96=We\xe3\xce\xaf\xef\xf4\xb9\x14P7 \"\x95\x81I\xcd\xd88\x1a(\xaco\x9d\x8e\xc6\xcb\xce\x01\xa1\x9b\xe2\x07\x01]\x830>;J\xec\xb9\x98\xe8\x8d\x06R\x1dd\xa9W\xf9,K\xaf\xefp\xcc\x81\x0by\x8b\xae9\xeb\xc8>\xe7Iv\xe0\xcf\x16\x93^b\x06\x84-7\xb3\xb5\x96\xa2\xac+\xec\xc5\xabk\xb4 I*\xb7f\x84\xa3\x94\x85\x84\x9aWp\xd4\x8e\xc3\xdc\xc4\x0cK?\xfdH\x03\x9e*\xa8`\xfe\x15\x9e\xbf\xcc\x15\xbb\xc0\x9c\x8f\x8diJ\x96~\xfa<.\x92\x1f\xc2b\xf1g\xb1\xdb\x98?5\xf6\xa3 \x9c7+\xe3\x8e\x0e\xd0\x00\xf2\xd1\xe0\xb2-\xd9h\x8ckU$\x88\x12\xfb$y\x82\x95\xe8[\x80B,\x80\x1a\xa5vRg\xd5\xf0\xa9\xa6\xa2\xce\xf0\xed-\xa9\xa8\xd1f\x9b.\xc2\xc0\x7f\xb1\xfd\xc0\xe9\xb34\x16)U<\x91R\x85B+g\xa3\x86H<\x9b\xdf\xa5I\xda\xa3\x83b\xa7\x17\xfdjY(\x16Epr\xdd\x06\xc4\xe4\x02\xbf\xef$gP\xd0\x8a\xe6Y7R\x85\xd1&1)\x8fm\x8dw0\xc7\x85\x84\xdb*\x1fN\xc5\xfaPv\x92\x16\xa5I\x12\x1d\x86?\xd7n\x9d\xcd5\xa1\x97\x9b9\x9d\x04\xa5 \x92.\x01\xdb\x1d\xb7\x8c\xdf\x06\x9c\x15\x90\xc5`\xc6m\x89\x1bc\xe61%\xe3\x1a{\x01g\xf0}\xfa\xb6\x9a/K\xc7T\xfd\xb9\x07#L\xc6$\xb0\x18\xec\xd1\xbbS\x91\x9bIAZ\xc6\xa4I\x83O\xda\x0bB\x9f\x0e=?p\x0dn\x02\xe4 \xad\xddJ\x80\x0e*`\x8fyl~\xd5r\x80\x12\xe6A\x05\xf7\x9dT\x15\xa0^\xceb\x91\x91\xce\x82\x0e\xb90\xe0\x96\xab\x95\xdd\xc9je\xae\xf0\xcb\xeb\\1\xe2\x19\xbe`\xcax\x1e\x8a5\xeb\xf2\x81\xdd%3\x98\x91\xdcf\xd5\x92;Y\xb5\xa4Z5FM\xa8\x9d\xc0VZ\xb8NB\x88n\x0b\x9a{\x8d\x99k|\xac{m\x9b\xa5Z\x1e\xef\xdeW\xc5\xa2\x8b\xed\x9d\xadv\"]\xbf\xbe\x10c{g\xbb\x13^\xaed\xe5\x0f\x1d\x17,\xaf\x9d\xc6\x95N\xc8\x9aX\x9ax\xc5\n\xc4#\x08-\x0c \xd2\xcdx\x80\xef\x05cB8\x8b\xe4{$\x9f\xf9)\xb1 c\x92&\x18Z\x9e\xe5Q\xb0\xb7v\xdb\xd22\xb8\x990\xae\xa2\x06y\xdc\xccj\"\x84\xc7w\x9a\xb90\xd7\x11H\xa9\x8bq\xf2\x84\xb9F\x1761_I#05\x86\x91\xfd\x12\xacSz\xa2\xfcX\xbc\x12YP\x90|sk\x07F\xbcd,\x16\xab\xd9\xc27X\xd7\x8a\xcb\xe5)\xc9\xe47\xf5\xaa\xf2.\n\xef\x8b/\xf8\xc8\xd0\x15\xb2\"wg\x94{)\\\xca\x83\xb2\x00\xcd\xfbP\xc2: \x05\xb2\x89L\xb0\xe3\xc2HM\x13/0\xc6\xa5\xf2\xc8\x9c#\xb3)59\x81\x18\xd6A\xa1y\xa1\xab\xd2\xe4\xcf\x0b\x8d\x06\xa1\x92j/\x99\xc4zII\x8c*\xbc\xf6r}\xdd\x81\x05\xac\xef\x01\xb1S\xba\x0f\xd3\xe5\xb1\x0b\xe78\x97\xd4\x85\xa5\xc3w\xaf;\x02Ml[\x90\xd8\xa2P\x99\x8d\x10\xf8\xf0\xcf\xfaP\xd8\x95\x8b\xd1\x04\xcf8m\xd7\x13Z\xe6\x0c\xc1\xa0\xf0H\\d!\xe91s\xa9\x16\xe5\x84-\xca\x9a}\x05{p\xea\xc5\xe4\xb2\xb0\x1d\xc7\x0b\x12L\x1d&-\xcc\x15K;#\xad\xcd\xc9\xfa\xba~u\xc4CW\xa9\x7f$\xda\x01\xe8\x17H\x91i\xd2\x8e\xe1\xae\xcdSU(\x92P\xdd\xc1\xca4\xc7\xca\x0e\xc2P\x0e_\x0d\xc6\xd6\x9e5\x01koS\x03\xc1\xd6\x04\x8b\xc7V\x17J\xb4\xf2\x02\xeb\x0b\n\x93\x1d5\xc0\xbd\xe9\xde\xe4\xf8\xdeY\x1fc.5TL\xc9q\xb7_#GY\xc6w\xb3(\x9b8m\xdd\xa2\xec\x8di\xf1d\x95Ea\xcba[\x1e;\xccd\xba\x89\x1az\xbaV\xeco\xd4D\x13//O\x19\x15`\x8f\xd1\x97Pz1r\x1ci5\xed\xbd\xcd\x0f{c\xe7\xee\x17\xb4\x86W\xf5\xd9\xb9\x13\xfd\xd7\xfd]\x87\xc7\xe8\xfc\xc6\x9f\x15Iv\xd5=\xc5\n)\xc0\x84\xa2H\xbfM\xa5b\xd1\xe9i\xc6JOO3e\x85 \xc8H\x9e\xb3:\xec\xb7\xb2ZFx/\x19Qw\x94\x15\xe1,\"\xbc\x0e\xfeVV\xcb\xc3\x80W\xa2\xbf\x94U\xca LX\x15\xfaKU\xe5\x14\x8bO\x95E~\xce\xda\xa7?\x94\x15\x82\x90\x95\x07\xa1\xba8\xe1\xc5\xea\x9e\xc33V\x1c\x9e)\x8b\xa3d\xf6\xfe\xefeR\xf01T\x7f*+'\xc1\x15\xab\x96\x04W\xca\nl\xeb\xd4\x1bwZ\x16E\x12\xb3\n\xf8SUi\xe6\xc7\xe7>\xdb\\\xf6S])\xa5\xe0\xcak\xe1oe\xb5\x90\xcf\x8a\xfePVH\xf8\xd6\xd2\x1f\xea\n\x11/\x8f4\xc5gYR\xa6\xa2\x0e\xfe\xa1\xaa\x18\xf8\x05\x03F\xfaCW!\n\xf3\xa2\xaaD\xffPV\x0cX\x95@YH\xd8p\x03\xa2\x1cn@\n?\x8cr^\x05\x7f+\xab\xcd\xd9\xca\x06s\xe5\xaa\x06\xa1\x1f%\x0c\xa6\xd8Ou\xa5s^\xe3\\Y\xcc\xc7\xa9\x1e&_\x05\xe5\xfc\xc9\x12\x0b\xc9R]xJ\x02^~J\x94K4\x0fI\x14`\xd2\xe7\xcc\xb6\xc4\x1f\xea\x8ag2\x98\xd5\x7fj*\x97\x19\x11\x15\xcbL L\xf3$\xc1\\\xb5\xff\x1f{o\xda\x1d7\x92$\x08\xbe\xdd\x8f\xf5+\x9c\xf1\xaa% \x03\x0c1H\x89\x94B\xa2\xd8J%\xb3[\xdd\x99\x92FRVMw0\x8a Fx0PB\x00Q8xdQ\xef\xf5\xcc\xec\xdc\xf7\xee\\=\xf7\xd9\xb3;\xf7\xb1\xc7\xec\xce\xf4\xf4\x87\xce\xfc#\xf3\x07\xf6/\xecs3w\xc0\x017\x07\x10$\x95U\xbbo\xf1\x81D\xf8\x05wssss3s3Q\x08^\xe9B\xc9R\x16I\xc81.\x86\x90\xbd\x18\x92\x99\xdb\x98\xb9Mf\xee`\xe6\x0e\x99y\x1f3\xef\x93\x99\x0f0\xf3\x01\x99\xb9\x8b\x99\xbbd&\xf7qB\xc4\x8b\xad\x80\x04\n\xbe\x92\x85\xcaU\xb6\xb0\xae\xb1\x85l\x85n![\"\xca\x89\x17\xaa\x00\x92X\x92\xc0\x06\xf3\xc4_\xe2\xe4\xe2+Yh\x89K\"X\x92\xeb!\x88V9\xe2\x1c\xbc\xd1ERY\x80\\\x95\xefO\x10\x90\xefOH8\xbe\xe7\x97\xa7\x1cQ\x15_\xa9B\xa1\x7f\")\x04\xbc\x91E\xf8)\x8f\xf0K\xf8J\x16Bh\x85$\xb8\xc2 z/\xb3\xa3\xf7T\x81\xa5\x1f`G\xc5\x0b]`%\xf3\xc9\x89^\xfa\xc9{\x99\x9f\xd0\x1f\xe0Q\x8e\x05x\x94\xdb\n\x04\x99$%\xea\x07]P\xd2m\xf1b) \xb1\x17\xde\xa8\"\x91\x8f\xa40\xf2IR\x18\xc5\x18M\x19\xcb\xc8\x1fTA<0B1y\xac\xa5\n\xe1\xf4\xd2\xdbU\xbc\xca\xca\x85\xa4~X\n*\xba\x17[i^\x9cg\n\xa7\xf1\x95*\x84\xdf\"?\xb2\xf2\x13\x1fg\x00\xde\xc8\"\xc14StU\xbe\x93\xc5T\x11[v|Zp\x8c\xea\x07U\xf0gP\xe2gTV\x82\x03I\xc8\x91$\x08\x85\x84\x84@\x92\x9f \xcf$^\xa8\x02\xd8/\xb2C\xa9\xbf\xc4\xef\x8a\x17\xb2@\x89:v\xc4I\xf9\xb4\x98N\xf9N\x17\x0b\x15~\xe1+Yh\xe9\x87\x88b\xf0F\x16\x89\xf3d\x8a\x13\x82\xafd\xa1\x95/;\xb4\xf2\xe9\xdedI\x1c!I\xc5W\xba\xd0\xa5d\xe0\xe1\x8d,\x92#\xeb\x9d\xe6$\xf3\x9d\xe6\xcb\xa5\x9f\\\xca\"\xf0N\x17\x93\xf3@\xaf\x97\xcc?\x91\xfd\xc80R,Q\xa4\xe0\x9d3\x1b\xf3\x9c!\xd9\xcdH\x92\x9b\xf1\x8b\xac8\xd2\xa8\x1fdA\xc1[`)\xf1F\x16Y`\xfe\x82\xceT[vf\xdb\xb3\xb3@n\x87\xe2\x85.\x90)x\x887\xb2\x08R\xcd\x8c$\x99Y\xe2O\xdf\xcb|\x7fJ\xd2x$\xf0$u\xcf\x11As\x12;\xcf|\xfc\xf0\x99O~\xf9,\x98qW\xfc\xfa\x9c$\x11<\x0c\x83\x95<@\xcaw\xaa\x18\xae$\x9a5Y\xfa\xa7\x92\xbb\x11oT\x910\x88\xb0\x84x\xb1\x15\xf0\x93_K\xfcY\xc0\xa3\xac(Z&Q\x95\x96~\xaa\xf6\xf1\x94\x9c\xe3\x95\x82\xd0\xca\x02\x9d\x95\x9fe<\x89T\x19\xf1N\x16\x8b\xc3\xcbSI\x00\xe5\xbb\xadX1R\xf5\x83*(\xc6\xe4\x87\x95\xd1V\x93\xc8J\x8a\xb8&6\xd2\x9a\xc5\x92\xc8d1M\xec\xcf$=<#\xe7Q\x10\x85\x82:\x90\x05\n\xa2\x9b!\xd5\xad\x94\xb0\xc8\x88P\x05{\x0b2\xa2\xaa]f\xb5w2\x1a\xfb\xae\x1e|\xac\xd2 eMv\xc3~\x18\xc6\xd7\xf8\xe1\xba\xe95j`)\xfdk\xe4\x0c\xeb\xe1\xb5r\xd9\xf7zq\xb4\xa8\x7fp\xff\xbeeL\x8df\x1f\xcal\xe3&\xf2s&\x8doi\x19\xba\xfa\xcaT\x94x\xf2\xc4\x8f\xe2\xe8r\x19\xe7\xe9\xd3\xa7\x84\xa8tn\x95\xaf\xfah\x99v\xe6\xf4\xe0\x8dB;\x06\x82#\xc1\x98\x9e9\x85\x12\xd5RN\x0c\x17\xca\x15\xe3\xb6\x14Dm*\x14\x95\x8aUKA\xc55\x9f5q\xcd\x0c\x19\x8e@0\x1cg\x8eR\xde\xda\n\x02\xd0\xb1 \xbc\xda\n\xfa\xd1\xe5\x88-\x9cD7\xb3{ \xdab;(_\xcd\xdb\xe4\xdd\xeaQ\x9a\x9c\xaa\x7f\x1fk|\xcc\xfaS\xd3wh\xb7\x9a\\\xdd\x94b\xe6\xf4\xd4U\x13\xf6u\x8f\xf5!8j\xefk\x16\xcf\xcbx]\x98\x91`\xc6\xc2OY \x03\x16\x8b\x9a\xef.W\x9cEq\xe6\x83\x8a>\x88\xd2`\xc6\xd5P\x07m~\xb0\xce\xe4\xbd\xc0\xac\xd5\x99#\xdcn\xad;[k\x83\x01\x93\x9f\x00+F\xc7\xef\xee\xf4CBF\x05f\x16\xc3\x8f\xc5\xf0\xeb \x12 \xc5\xb4\x14\xd3\xd2|\xb5\n\x03>cY\xacC\xcdc\xfcb\xc5\xa7\x19\x9f1?B\xe8\x0c\x08g\xb1\xfa\xd3|Q\xbfP8\x87\xa8p\x0e\xd9\x13-\xc8u\xd8\xefw\x05\x0d\xdc\xd6p|\x8f\x85\x05f\x89\x1e\x8fE\xdfC\xf16\xe9y,\xef\x0091AS\xddf\x11.\xe5\x95\x16\x0e7\x18,ey^\x7fl>T\xe8\xa5\xc8q\x93\xea\xe0Q\x80\xdd|%\xae\x89\xe4|\x0d\xc4\xce?>b\xe7\x9d\x11\x9b\xa5At\x1ar\x8c\xbf \xd9\x80\x9ba\xf9M&\xde\x16^Ja\xe8\xf7J\x887\x1cp\xba\xa6\xad\x0e\xdey\x8e\xf1\xeeN\xe4/\xc1\x98\x95\xb8\x9fC=y\xab}\xb1\xedA\x1c\x1cL\xe3\xa8\xb8;qu\xc5\xaa)\xd0\x9bri\xb7c\x9fz\x94\xd1\x99\xd1X\xa7\x16>\x00\x14\x7f)\x90]\xcd\xa4\xa8\x0e%|(\xf1\x8bCw\x0b\x17\x05\xfa\xafk\x12\xb9\xc6\xbbL\xf5\x07\xd0f\xe9\xf0q6q\xeb\x0c\x86>\x01I9\x01\xb1\x05\xd8\x91IY\x80\xa4\xbc\x8cg\xbc\x95\xa3\xb8 \x0cm$\x03\xf9\xca\xef\x95`\xfc\xc2875\xd6V@\xeb\xbbZ;M\xea\xc6\x81UL\xba6*\xf1\xec\xd7_\xcb\xebpd\xf8\xcd\xd61k\\\x17\xf8\xa5h\x1d\xb6\x18\x90?X\xf8\xe9\xab\xf3\xa8\xb8[\x1ev\"\xfd\xac\x99A\x1b\x00\x83\xd6\x8d5c7e\xcf\xd8/\x80t\xc5\xd1\x1a[4q:\xd0<\xe5\x18\x07\xb4\x06\xbb\xbe\x9b-\xdd\x02A\x8a\x95\xa1{X\xe6\x05\x83\x9e\xeb\x17\x8fm\x8f\x18\xd4J\xcc<\x07\x7f\x1e:\x8c\xdb\x97\xa6Xp\xbf\xf1\xf6\xd5\xcb\x01\x9eu\x83\xf9\xa55\\\x80z\xd6\\i`\x1f\xaao~\x1d\x96Z\x1c\xc1\x8eY,\xcf\xa6\xfd\xf2\x1a\xe8\xf2\xee\xb2\xdd\x9cL=\xb7\x862\x157\x1f[\x8fYV\x99\xe9\xac\xfd(\xa6dAb\xef\xec@\x1f\xa9\x9d!*:\x1e8\x1bC\x8f\x15\xb3\xa7\x9c\x87T\xe6\xa6\x80\xd5\x80\x1d\xd6\x8f\xa5\xb0},\xf8\xf4}\x01\xc6\xd4c'y\xc6\x12>\xe5\xc1\x19\x9f\xb1_I\x99\x9f\xb1 \x9a\xf1\x0b\xf6+\xe9\xa0\xe7\xb1\x13\xf4\xed\x05\xf7\xa4k`\xb3\xcf\xee\xf7\xb2\x04\xa5o\xd1r:\xfc\xf6\xe9`\xda\n\xe2\x9d\xbc\x8f\xeaWX\xd3jo\x05\x81v;QG\xd6\x99\xc6vY\x9f\x96\xa5x{\xeb-]t0\xddT\xcf\x0d\xa7\xf4\xff;\xac\xc6\xd7\xf8\xc5\xaf\xd7\xe44:\x1d\xe0\nfa\x1cv\xc4\xd9i\x97f\x99lz\x0en n\x85\x0f\x99\x17\xa0\x9e\xb7\xd6i^\x12\xdd\x16\xcc\xed1%\xfc\x02BK~oX\x9fv\xc6\xfa\x10\xb0\xbe\xee`\xae\xfe\x18X\x1f\xde\x00\xeb\xc3[\xc7z\x85\xc2>:\x93\x04\xfe\xa9\x8dk)V\xca\\\xac\x94N(-J\xaf`\xa5\xcc;\xae\x94\x8d\xd5zpz\xcf\xe5\x99l\xdeL\x8e\x8f\xa2O\xfdY\xa1\xc2\x10\x195\x9e\x0da\x80\xd7\xf9{L^\x139\x8a@\xd3\x06\xb7J\xc8Z\xfa%\x13\xe5\xa7K\xd6\xef\xb0L\xcf\xe4\xa5\xb2\x95\x93zln\xae\xf6y\xb7\xd5.\xe0\xb6(\xc0\xb6\xf8\x05\xadc#\xf5\x83vE\x92\x99>\x87(\xfcQR+y\xfd\xef\xa0pR\x7fu\xc5\x86\xec\x1ed\xc0K\xc6F\x8c\xc3\x85I\xb8\xed\x07\x0cZ\xa5\xb5\x0f\x96o\xcfhJ\x02\x17g\x97J\"\x81\xe8\x84\xe2=\xf0\xd8\x1c`\x92\xa37\x1ep\xb1\x13#+\xfa\xdc\x0f\xc3 :-D\x0e)\x83\x95\x03\x8e\xb9\xd9,H\xf84\x0b/Y\x90\xb2(F65N\x04\xd18\xb9\x84\xc0*_\xaf\x92x\xb5)\x88N\xfa5[\xf9\xd3\xf7\xfe)\x1f\xb0\xafR\xce\xbe.\x1a\x1c\x00\xc3Z\xfct\xdc\xaf\xc5:\x9b\xfaa(\x9aX\x0e\xd8\x1b\xee\xcf\xd82N\xb8\xe0\\\x17Y\xb6\x1a\xdd\xbb7?\x19,\xf9\xbd<\xe5\x9bP{\xb3\xfc\x8eu\x91hx(f<\x19\x07\x13v\x007+\x8b\xcb\xa1*\x0d\x89\xc4\xbb\x05/\xcf:\x15\xa2\x19\xa4`\xe5(\x18\xef\x94%\xfcgy\x90\x80TQ?O!\xdf\x1dd\xa9$\x067b\xdc\xa9\xe0H\xdb\xa5k\xa6+\xe61\xbc3\x92\xa1\x0d*\xb4^\xba\xd6B\x1co\x10\xd7\xdd\xd5#\xc6\x10c,\x91\xa4\xdbm\xee\xa4v\x9b\xbb\x8b\x10\xe11\xdb\x80\x10\x91A\xed\x16ucMV\xeaBb\xbcB\xadM\xe4\xd0\x0e\x9a5nvS}\xea\xc8\xf5\x82\x17\x9f\xae7\xbbAx-\xf0cc\xe9\xf8\xe3\xe1\xa4\xd3@X\x17\xd9\x8e\x0d\xa3\xa5[\xd8\xf6\x05k~\xbf\xeeu\x96&s\xa7\xcdWL\x95\x9e\xc5\xba?\xd5\xe5\x85\xec\x80I\xbb(\xe0\xfc4\xf1\xfa\x1b~zx\xb1*\xef\x81\xf7XGG@\xf2K\xca\xf4\x08\xaf\x9c\x82;\x89\xb7ZJ6\xee\xfd\xea\xaf*\xd7\x1b\xef\xfc\xd3\x1e,\xe0\x16k\xb2L\xef &\x9bpD\xa7W\xa2\xe3\xaa\x07\xf58r6\xe0^\xda\xddwiN\x98a,\x05\xb5+UZx\x07\xd9\x84\xbc\x9a\x9bSR~m8\x01ht\xb0T\x99\xa1\xcf\xfcL\xfb\xfa\xcc\xcfx\x8f\xc6J\xa3&\xcemY7\xe1\xa7\xfcbE\\1\xb6\xa1Q7x\x9e4#+-\xd0/v\xec\xe6\xad\x1a\x91\xb6i\x1bn\xdd\xf6\xd4\xe8\xfd\x088\x9b\xc6=\xb4y+\xc620\x03M\x05$\x98;\xf4\xa8\xa9C]iL\x9b\xd3\xb7\xea/YIs>\xc9\xf6Q\xc5V\xa6xl^;\xa9\xb0}\xc1J\xcf\x07z\xc2\xdc\xd3\xa4b7\xf0C\xd0\xe4x\xa7P\xe9\xdfR\xfb\xbd\xe1\x83\xc1\xee@z\x1e\xb8Vkg\xa5\x8f\xe9\xdd\xfb\xee\xa0\x88\x98@Y\xf3\xb6\x19\x1b\x07\xb2\x9d\x07\xa4}\xef\x83\xfb{\x16\x83]\xdfQ\x92\xb9\xdb\x18\x87aG\x8c\x9d\x1fn\xd3n\xa3\xeb&\xca\xa2\xb3\xbdep\x11Di\xc7I\xad/xuf\x19\x13\xd2\xc3\xd4j\xef\x8b\x9f\x1c\xb1\xdeg\x87\x9f\xbfxyx\xfc\xe5\xb3\x97\xbfe\xf1\xad\x90f~\x16L\xbb\x95])\x0c\xefTZ\xfaS]\xa3\xc2\"\x08g\xcf\xd7\xadu\xca\xb3\xcf\x90\x1a@\x84\x9dj\x9d\xe3/\x0f\xdf\xfc\xda\xe1g\xf6\xaa/\xa2 \x0b\xfc\x10\"\x17\xadY\xf5\xb9\xd6\xddu\xaa&<\x82\xbb\xb4\xaa\xc6\xab\x97\xcf\x0f\xad \x94+\xe8\xc7A\x18~\x89\x8eK;\x80\xa4\xa8\xf6Y0\xbbF-\xf1\xb17\xa8($@j\xc3\xa3E\x9c\x0bp\xc86\xbeZ\xcd*\x10\xed:\xc8z\xbd.\xfd\xfd,\x98]\xa7\x1a|.Zv\x86\xcfW/\xdf>\xfb\xfc\xf0\xf8\x9asB\xd5^\x1b\xc8T#k\x0c=\x87\xa2\xc5\x1c\x8dX\xef\xd5\x8f\x0e\xdf\xbcy\xf1\xd9\xe1\xf1\xa7\xcf\xde\x1e\x12\xbc\x8f\xd9Nh%:\xb0\x10\x93\xe0\x8c\xcf`5}\x9e\xc4\xcb\x86\x15\xd9\xe5[S\xeb\xb7fA\xba\n\xfd\xcb\x97p\xe3\xbb\x13G\xce\x80\xf0j\xf5X]\xac\xab\x1e\x8b\xd6H\xd1\xd4\xce_\x13\x1cgK(\xb9B\xed\x11\xa1\x9a;\xaa\xb8a\x8b\xfa}W\n\xb4\xc7\xd1d-\x15\x17AJ;\xf7\x9b\x0f\x8c\xda\xe2\x88.C\xa6\x19y\xa4\xabP\xd6\xd0\xb5k\xf7\xca\xd2\xa1\x1b\xf4\xc5\xd8;\xd6\xe8N\xad.8\x13\xaa\xa7\xed\xb3\x85c\xa4B\xcb#\xb2\xf4Z\x08\xa9\xed\xc6kt{\xa5q\xa9\n\x84E\xda\xba\xf0+\x98\x87\xce\x1d\xd8\xe8^\x94u[C\xac\xba\x8e\x82\xa8\xbdU\xf5(>\xaf\xdd\xa6_=\xd0\x9f\xba)`\xd4\xd9\x14\x90)\xb1\x97\xe0\x16A\xd3\xd9\xed\xb3\xe2 \x9c\x8d\xd8cw\xc1\x88\xf6y\xe8\xa7\xe9\x88\xfdV\x9c3\x1f\xf4!\x19_\xae\xb2 :eY,C\xcf0\x9f%<\xe5\xc9\x19\x9f\x01\xa6\x88\x9ez\xec\xeb_I\xbf\xf60\x16>n\xd8\xd1\xd1\xdd\x8c\x9dp\x06\x11\xf2A\xb4\x0b3\xdac\xef\xf9\xe5\x80}\x86M\x05\x19\xf3S\xe6G\xa5\xc1\xb4j\x11R\xb8?{,\xca\x9c\x07a\xc8\xd2L\xfc=\xe1\xcc\x9fNy\x9a\x06'a\xd1\xb8n.~\x97vRo{\x94\xd8\x0b\x80\xd6A\xea\xa5\x1e\x90~\xad3;L\xe3\xb9Cs\xa2\xd9\x01\x0b\xc7\xd1D\xca\xe9\xbb\xf7\x83\x95\xa7\xcb\xc0\xa1\xb6C\x10{\xe4\x1e\xebu\x9e_1\x95\x02\xb2\x97q\x9eh\xb6\xc2\xa0 \xcb\x16~\xc4\xe2h\xca\x07\xec\xdd\"H\x05\xe4\xe7a0\xcd\xd8\xd2\xbf\x14s3\xcb\xb9h\xc9\xc7Mm\xd0C\x07\xc8gq0s8\xc6\x95_\xc0\x8b\xc7\xa8\x80S\xb6\xa7Y\xff\xab?\xf2#\xb4\xc7\xe5\xfa\xd3\xde\xac\xbd\xc4\x07\xa42\xeb\xd04?\xcf\xe2\x93 \x9aU-\xee\xd7PA\xd3\x81u\x98f#\x98\xd6\x11+\x13\x88\x95\x8e3;b\x9d\x10U\xee\xdc\x11\xc8Te\xe1\xd0Ml\x05\x8f \x12\xc2\xdc\x9fr\x1bB\xc5g`\x87Q\x9a#\x86eXj\xc9\xb3ENDg\x9f\xe5Y\xfci\x10\xcd^\xfbAb\x89TY\x8dR\x19\xd5\x97\x99\x0f\xcbl:@\xee\x1f\xa6T\xbe\xbb\xa4\xbfw\xf5\xc0\x1c\xd7\x1bC\xbb\x8a\x1cC\"\xb6\xedJg\xf2^h4\xce;X\x8e\xad`\xd8\xc6\xf7\xda\xf5\x80sg\x85!w\xa6fm\x97M\xc7\xf9D\x0c:li\xa9\xc1\xef\xb3\xfe\x881\xcd(\x02\xd8\xd6S\xd6d7\x0d\xc6+\xe0\xac{\x05\xb7\xdc\x86H*\x06\x8a\x92w\xdb\xc1\xc0P\xbfmR\xf4\xe7L\xba\xcfN[\x03\x96\xeaO\xe0\x80\x13q;\x13\xb0\xac\x13@\x99\\_\x81_E\x85\x11\x81 \xd1l\x15\x87\xc1\xf4\x92\xfdJ\n(\xfd\x9e\xc3\xeb\xf9\x82G\xb8\x02O\x81\xdd,\x96\xa6\xa8\x02\xc4x\x89\xb3\xdf\xd0\x9d\x03\x96`\xe4\xd2\x85#^\x042\xb0\x11\xd5C\xf4\xe0\x8be\xcf\x8a\xb2\xdd\xa0/\xddA\xcb\xda\x1d8+(\x1ec\xd0\x93\\|\xc7+*7\xd6m\xe0\x15\xcc-\xbe\x13\xa1\x9fY\xf7\xfb\xea\xb1$p\xa4AY\x83\xaf~\"=\xf3Xo\xc9\x93S\xaeB\x1c\xbd\x8c?\xcbW\xa1\xd8\x90\xf9o\xf2\xcb\xd4qG\xec\xb9\x1f\x89m\x17\x8a\xb1(\x8e6\xb1\x99\x14\x08x\xe62\xe2\xc8\x82Q\xca*:=`\xf8Z\xbf\xf5.\x91\x06-\xf8\xb5\xec<\x96\xf4;\xc5\xed^p\xfa\xa9\xbf\xe4\x18\x06]l\xbd\x9dv\xd6\xc7\x02D+\xf0\xf0*\xf6\x044\x92SE\xa7~\x9eJk\xb2\xf3\xb8.\xb6u\\\xb1\xc5\xd5\x0e\xd3\x8e\xab8\x0e\xc9w\x8b\x15P\xe9\xa7\xd8\x1c\x17\"\xf5=\xbfL\x15\x0b,\x19S\xcb\x0dUeB\xd8 -\x16m\x96\x88:{i\xdd\xf70\xb04F\x83\x15\x10\xf1\xcaH\xb2\x96{\x8e\xe2\x81C\xad\xa5\x96]=\xaaL\xe2\xca{(I{\xe1\xd2\xd6#\xb2\xef\xde\xe0^\x98\xf0\xd5\xcc4\xa5\x9b\x13\xe3\x14\xc0\x0b\x1dV\xa4\xdbz<\xbb1\xe0\xad\x00\xb7\x02\xf5\x9a]]\xb6\x1e\x1524\x9e\xa3\x94\xc4\n\xec\xb5/\xd5[1C\xd1\xa9\x87P\x13\xb4\x82\x86)\x83\xd6\xe3\xe3 \x85J`\xe3\xb7\xb1E\x96&H\xaa\x89\xb4\x97\xed\x1d\xac\x88\xea\xaf\xddG\xda\xde\xa5S\x1fO\xac}\x94\xfe\xc1\xa5\x02\xa9\xb3p\x0b\xfa\x87\xf2\xf8d\xc0\xa3\x9f\xe5<\xe7o\xb4\xa6$\x86\xad}z-\x06\xdc\x11N\xca\x16g\xa3\x0e\xb0\xeb\xc3\xea\xd8\x1e\xd6\x97iF\xa2\xce\xb1\xaeT\xd7y{vB\x90\xb6\x12\xb2M\xe42\xab\xa9T\x93\x06sPV\xa2\x89yXP\x91\xd7\xee\xdc\xe9\xf0e\xf5T.\x11r\xb2]\xcf\"\xeag\xfd}\xb6\xdd\xd6>\xab\xc9,\xdb\x8f\x05L\x9e\x88\xb2q\xc4\xfal\xd8\x81O\x85\xe0\x0b\xfbH\x99\xe2\xeb\xfaA\xf8\x00\xe8\xab\"\xda\xad\xa4t\x9b[C\xe7&|\x0e\x0e\xc4\xbc\xca\xbaP6\xeaQi1\x9fq\x19\xcb\xc7>\x90\xc2\xcaWT\xa9\xb1\n\xec\x80Lv\xdcV\x81^\xe0\x10\xacY\x0evuUs2`\xa6\x7f\x85\xf8\xc4\x88-\xc5\xc9W\xa2\x7fq]]\xf0.\xe2\xd3=\xb1\xb9\xe8\xea)q\n@~_P\xc14\xd0\x14w=\xb7\x06\x91\x9c^\xad-'\xde\x04\x84\xe5\x15c\x97\x88\x9f\xb3cOO\xac\xf8\x10\xc1h\xc8Z&\x85\xe22\xa8_>\x90!O\x9d\x95n\x00\x9e\xb9\xae\xc7VN\xe6\xb1S\xf5\xc2\xd5\xcb%\xec\xb0u\xb5\x08\\EP\xc1\xe6\x0bMI\xbd\x98\xe3\x82\xacB\xef\x1c*\xda=\xd6\xc3\xc0\x07pnr\x06\x83\x81`\x98M\xd1\x16NO\xb0\\\xa15\n\xf3\xd9\xd7\xd8\xc0\xd7\x92\x93\x04f:u\xf5\xf1\xcb@%N-I\x86\x9bj\xe4w\x9a,\x93n`\xd0s\xd6\x12\xd3\x0c\x0co\xca\xe2\x91cs\xe6g\xa7zr\x00F\x0cg\xee\xca\xe0\x96\xc3\xfb;\x10\xdd\xf2v\xc7\xb3\xbdG\xdb\xe2)\x1b\x00\xb1\xd5\xc5.Ek\xfd\x12*5Z\x0b\xc1X\x1f\xeby\x96#$\x8f\xf2%O\xd0\x01\xfe\x86%\xd0\xe8)\xef*]Q[\xf3\x80\x96\xb5\x13b\x82\xc6\xbe\x07\xdf{\xbf\x83[\xe9\xb7D\x93\x8e\x9d'\x1b\xcf\xea\x08\xc4\xf6\xd9\xd0Bv\x18uz\xb8\xc1\xfao\xa3E\x80\xb7\x9e\x14A\xe3M\xa3*\xca\x927\x95\xe0&\xf5 >Iyr&\x86.\xce\xdcp\x0bXK\x1a\xc9\xa0\xbc\xe2P\xad\x12{\x10\xd1]+\xb4\x8fvr\x19:\xc7\xd6\n\x92;\xf0\xf7\x02\x91\x8a\x80\xc7\xf0\xcf\x00Bn\xa4\x98[\x8fYP\x11\xf0\x04\xb4\xcb\xa2\xb3\xc2)N@\xc8f\xb6<\x1a\xc4|\xecO\xf0\xe2\xa7xA\x07G\xb6\xbd\x8ai\"\x11\xbd\xc7u\xeb\xab-\x93\xd8\xa6\x16F\x8a\xe6\xbc6:\x08\xca\xaa +\x04\x04E\xc5F\x91\xe9\x99\xe6a\xabY\xf2\x85\x07C\xec\xbamm\xeaO\x06\x1e\xc7\x04;\xfb\xe2\xe5\x8bw\x8d\xc5?\xb4\\Q\xd5No\xb1\xcb\xb2E\x12\x9f\x83P\x05n\x119w\xdf\xf0Y>\xe5 \xeb\xdde}\x96\x81\x1b\x90\x9e\xc4`>c\xc5V\xc9fy\x82*[\x90 \x05\xdfH\xe3\x9b\x17sT\xaf\x81\xd8g\xe5\xa7)j\xe2DZ\"[\x0e\xd2\xb2\x19\x8f]\xc69\xca5\xf8\xc5*\x0c\xa6A\x16^\x16\x0bf\xc1U\xfb\xd8\xe0\x80\xbd\xab'\x81\xfe-\x8a\xc1B\xb0h\x15\xba!\x1a\x9e\xc5\xd1\xdd\x8c\x9d\xfbQ&:\x91\xf2\x8c\xf9\xd2\x01\x81X'\xa0\xbf\x93\xbd\xc2\x8eL\xfd\x08\x0c?\x80\xb9\x91\x86\x83,\x9ek-7\xb9\x96\x11\xd3\x1f -\x10\xad^\xdc{\xfd\xe6\xd5\xa7\x87\xc7_\xbd\xfc\xcd\x97\xaf~\xfc\xf2\xf8\xd9\xf3w/^\xbd<\xee\xb1>\xfb\xd2\xcf\x16\x83\xc4\x8ff\xf1\xd2q+\xa1\xcd\xb5\xe0\x9e{\xee ]\x85A\xe6\xf4z*\x80o\xe3\xe7k\x93\xdb\x15\xbd\x10\xb5\xe8\xed\x86\x01>\xdd\x00K@\xbb\xbfJ\xe2\x13\xf1\x1ed\x0b\xe63\x1c6|v\xc0>\x83 \x12\xcb5\x8b\xd9\xc2\x8ff!z\x99P\x98\xce\xfa\xec.\x8b\x13\x16g\x0b\x9e0\x1f\xd6 \x88\x18z\x08\xe1Ozh\xd6\xb5\xf2\xd1<\x8a_\x82\x8d\xd54\x06/\xa3 X\x96\x06g\x80:\x85yO\x81q\x1a\x9aM\xf3$\x01\xa3\x03\xc0)\x81\x1c~t\xc9\xf2\xe8}\x14\x9fG\xea\xbb\x1e\xcb\xa3\x90\xa7)\x0b\xb2\x1a\x12\x07\x11;_\x04\xd3\x05\xde \xa4>PAZ\x8f%\xfc\xd4Of\xd0X\x8c+\x06\xbf!\xc1\xd2\x0d\xcd\xd1\xa9\x86\xc0\xd9\x13D\xd9\xc1]\x8b&\x86\xd0\xfe95\xd3\xa0\xca\x01\xd3(\x0e\xc2\xf1\x06\xfa\xddEo)\x96\x87\xd83\x0b\x9d\xa4\xd2`\xc6\xb2\x12\x14\xc9\x80\x8f\xb2\xf8*/\xbd\xbc\x88\xceb4\xdcz\xed'>\x84u\xff\xb2\xf0\xb1\x9b\x15\xac\x84\xf4\xf4@\x124\xf0\x16$\xb6\xae]\x97\xd8\xbbD\xd6\x83]#+(\xb2\xf6\\\xf2X\xeb[\x95\xba\xd2v\xa4\xb2\xfey\xf3\xfa\xb7\x1e\xc0\xb5\x05_\x1bj\xa2\xe6\xd8[\x0bd\xb1^\x8d\x82\xff/1\xe9\x15\xbds\x04\xe5%\xa61P3L\xcdU\xf0}\xcf\x15E\x9c\xed\x8e\x9f\x82\x1a\x89\xa6\x0e\xb5\x1b\x81\xa4\xb9\xa5'\xbb\xb7Y\x9cp6\x8b9zc^\xf8g\x1c%\xf3\xc1L\xc9\x1c\x06\xecK\xff=g\xf2*//#\x8c\x94J\x85\xfa\xe6\x1b\xa4\xday\xf7|\x11\xa7\x1c\xa7&\x05\x99\xb0l7\x1d\x10\xc1k}I'\x0b\x14s\x0d\xed\x13\xba\x0d-\xb6\x84\x17\x19\xaaM\x07A\xaa^\xf5\xb8.\x85\xbbd\x1f$\xd8A\x8aB\x91\xe2\\\x9e\xd5\xa2\xa2\xa8\xc1e18&\x88*\x81\xdf^,\x979\xc4\x83/\xbeZ\xdec\x9a\xc7a\x18\x9f\x07\xd1\xa9rx\x10\x80S\xaa\xbb\xac\xcf\x02T\x1a\xdc\xedy\xacw\x17eL\x83\xbb\xe6\xd8\xe1\xc0%f\xef-\xff\x19(#\xf0\\\xe8\x0e\xe6A\x98\xf1\xa4\xe5\xa8 \xc7\xbba\xdc\xdf\xaa\x1da\xeaZ)Y/\xd7e\xc0\x07\xac\xa7]\x19\x04\x81\x04^\x94,J\x1d\xb0\x9e\xf2\xeb\xd0c\xa3\xe2G\xc0S\x14\x97\xe1\xc0ss\xe0l\x1e\xe7\x118\xa5\xbe\xab&E\x03\x7f\x16\xb3y\x10\x15a\x83\x04\\Q\xf0\xaf\xe4_\x853 \xbcC.\xc5\x1a\x0dp\xd6\xef>\x96\x9dD\xff\x13'\\J\xeaf\x83\xbbuw\xca\xb7\xbf\x1b\xde\x1aE\xf3\xd6\"\x0euo\x9c]tH\xa4d\x13UH\xa0\x1a\x12X\xaed\xa7\x97+)\x0bEQ\xe7\xad\xc8?\xeb\x02(M\xb6y+\x13\xa4W\xacB\xab\xa0\xd0b\xd7\xae\x07\x00/\xe7\xa9:#]>\x199\x8fP\xc4\xfd\xe8\xa1[\xedy\xe4<\xd8\xdb\xead\xe0Y\x1e\xa1\x87\x86\xafC\xe9l\xf0\x91\xeb\xf4\x8a\xd8\xe0\xa4\xad\xf3\xde\x96\xc5\x8a;r\x86\x0f\\\x8d\x8a\xaeq*\xb0\x1d\x084ER6\x8e\xd1c\xad\x16\xbb\x1c\xee\x14@4\x81:\xcdJ\x1c]~\xd7 \xc0\xcdV\x86\xf7~\xe2\xfc\xca\xf6\xd6\xd5Q\xea~\xe2\xfc\xd4?\xf3\xd3i\x12\xac\xb2\xab\x99\x9f\xf9\xee\xbd`i\xc2\xf2\xde\xf8'G\x17\xdb[\x9bG\x17{\x87\x93{\xa7\xf5\"\x01\xb69\xfe\xc9h\xd2wG\xf7N\x97\xe6qk\xdc\x1b\x08Bt\xaf7\xa1\xe1]\x05h\xeaGA\x16|\xc3\xbfJ\xc26a\xd5\x99\xb4\xb5\xf1\xe4\x8e!\xaf\x95\x89cA\x8fRKw\x12\x10j\x05\xfd\x010\xec\xaf\xe6\x0e\x1foM\\\xf6\x94m\x12\xee\x97\x9d\xdc\x95&\xe7N\x04\x12\xc0\xa5\x9fM\x17N\xe0\x8ad4\xd9\x11\x873\x96\x0c2\x9ef\xe8\xb6\xa4\xe7\x9f\xc4y6: \xfd\xe8\xbd\xd86r\xb8\x1d\xae'V\xbe\xb3\xa6\x15e\xb9<\x1e\xd8\xec\xff\x1f\x0e]#\xdci\xc3f\n.\xa2\x07Y\xfcE|\xce\x93\xe7~\xca\x1dpG\x02\xfa\xa3\x03&\x90\x94\x8d\x0c\x1f\x1f\x96\xe5\x15\xaf7\x84]\xca\x9e>r\xb6\x1f\xda\x96\xaf}z\x95\xb0\xdbI\x1c\xeeVG\xb3\xe6\x1a+\xbb\xb7W\x17]|/\xa6\xe4`H\xdelF\xde\x0d$g\xff\xbf1y1\xc7\xf5 \x8e\xba\xd9\x8cw\x03t!d\xb9\x96\xe5\xb8\xbe\xa2)\x84\x13\xeb\xc1r\xa3g\x8f\xf2\xaf\x0b\xcb\xea\x9aCh\x96\xf5\x80\xc5\x03\x19\x94@\x814F\x12\x18 \xd1\x90\xe2y\xa34\x93\xa8\x0e\x96\x91hd\x91\x0d\xa6\x0b?y\x969[\x16%L*\xcb'N\xe4\xb1\xa1\xb2P\x82\x08!\xd9 \x0d\x83)w\x1a\"\xb0\xe4c>\x01\xc5wU\xd8\x7fm\xda\xbb\xfd\xb0\x1d\xc4\xf6cl\x0c;\x9a\x14\xdf\x93\x98T,2\xe9\x02\xea\x80\xc5\x82w\xf7\xd8\x06\x98\x01D\xec\xe9>\x8b\x95Ux\xf1\xa9\xeb\x8e\xe6\xc1^\x9d l\xc1\xbb\x9b\xd0g\x8e\x08\x02\x97\xb4\x92\xf6\xc5b\xe3h[\xbf\xc4Ks\xb65>\xa1\x10\xb97>:\xcag\x0f\xb7\xb66\xc5\xff\xf9|^\xbf\xf4\x96\xa8B[;Xhkgw~t\x94\xcf\xf96\xfc\x9c\xf3m\xf1s{k\x06?\xb7\xb7\xcc&\xe0\xc6\x00|fg:\xc6\xcf\x9c\xd8>\x07\x86~\xe3\x9f\xb4t\n.\xf49\x07#\xbd\xd1\x19\xdf\x85\xe2\xb3\xf9|\xe2\xfe|\xfb\x03y\xc5Oo\xf7d>\x9f@\xc2\xd4\xfe\xa1T~\xa8\x08\xe1sU\x84\x01r\xc5[\xef\xa0V!T\x9f\x99\xf3-\x8e\xff\xe6\x93\x03\x15\xe1\xc9\x91\x9d\xde\xde\xda\x9a\xc9V\xc7\x18\x93)\x9f\xc8\x95~\x85A\xe2\\k\x1b=\xf7\x93\xfaY`\xaa\xf5r\x1c\xa8\xae\x1e\xf4\xf0\x1a<(\x08\xa3z\xfb\xb5~\xcf\xd9\xbe\x0c\x8c\xe0\xc0\xe8\x9c\x83\xfdr\xa40\xe8)F\x8a\xec\x9d\xf6\xae\xbb&\xb8\xe4*\xe7p_t<\xb9\xee2\xde~hc\x08m\xcb\x98\xf2%/G\xdb\x1b\xdf\xfdo\xbf\xf3\xbb\x93\xde\x8dF\xd6\xbc\x9d\xa8\xdd\xdd \x1c\xb1o\x14,\xbe\x0f,\xbe\x0b\xce\x1ez\xbd\x1b\xdd9\xd2h\x9c\x058\x06\x0b\n\x87\x9e\xf1\xd1\xc5T\x1c\x8bf\xbbG\x17\xb3\x87\x9bG\x17\xf3\xdd\xa3\x8b9\xbc\xcc\x8f\xf2\xad\xa1X\x19\xf9\xd6po>\xb9w\xda\x00\xc2u\xc9\xc3M`\xed\x80\xd0\x1a\xa4\x82 \xa9U\xd0\x0c<\x96\xd4a{} \xdew\x9d\xea\xd7{\x7f\xf8;\xbd\x11\xeb=\xab\xad\x9b\xde\x1f\xfe1:\xf9\x8f\xd3\xc9\x7f\x82N\xfe\x1f\xe8\xe4?I'\xffC\x91\xec\x1b\xc9\xff\x88N\xfe\xc7t\xf2?\xa1\x93\xff)\x9d\xfc\xcf\xe8\xe4?-\x92\x9f\x1b\xc9\xff\\$O\x8d\xe4\xbf\"\x92\xeb\xde\xf1{\x7f\xf8\xefD\xf2\xccH\xfe3\"\xb9\xee;\xbe\xf7\x87\x7f\x96N\xfest\xf2\x9f\xa7\x93\xffg\x91\xcc\x8d\xe4\xff\x85N\xfe\x17t\xf2\xbf\xa4\x93\xff\x82H~a$\xffE:\xf9/\xd1\xc9\x7f\x99N\xfeW\"90\x92\xff5\x9d\xfco\xe8\xe4\x7fK'\xffU\x91\xfc\xd2H\xfe\xf7\"92\x92\xffG\x91\xfc\xcaH\xfe\x9f\xe8\xe4\xbfF'\xffu:\xf9o\xd0\xc9\x7f\x8bN\xfe\x0f\"96\x92\xff#\x9d\xfc\xbf\xd2\xc9\xff\x1b\x9d\xfc\xbf\xd3\xc9\xff\x89N\xfe]\x91\xfc\x95\x91\xfc\xb7\xe9\xe4\xbfC'\xff]:\xf9\xff\x14\xc9\xb9\x91\xfc\x7f\xd1\xc9\xff\x99N\xfe/t\xf2\xdf\x13\xc9\xf5\xd8\x01\xbd?\xfc}\x91|i$\xff\x01\x9d\xfc\xa7D\xf23s9\xfc\x9eH\xf7\xcd\xf4\xbf/\xd2\xdf-\x8c\xf4\xff*\xd233\xfd\x1f\x88\xf44\xad\xa7\x7fK\x93\xe5oi\xfa\xfb-Mh\xbf\x05\"n\x90\xb7o\xff\x04\x9d\xfc'\xe9d\x80\x80A\x0c\xbf\xfd3t\xf2\x9f\xa3\x93\xff\x02\x9d\x0c\x84\xd6\xa0\xa8\xdf\xfeY:\xf9\xcf\xd3\xc9\x7f\x91N\x06\x12d\x90\xe5oij\xfd-P&\x83Z\x7f\xfbW\xe9d \x13\x06\xfd\xfd\xf6\xaf\xd1\xc9\x7f\x83N\xfe[t\xf2\xdf\xa6\x93\x81\x04\x19\xf8\xf6\xed_\xa7\x93\xff&\x9d\xfc\xbbt\xf2\xdf\xa1\x93a\xcd\xfe\x9a\x91\xfc\xf7\xe9\xe4\x7fH'\xffc:\x19\x16\xe7\xa9\x91\xfc\x0f\xe8\xe4\x7fD'\xff\x13:\x196\xfb_7\x92\x7f\x8fN\x06\x1e\xc0X\x98\xdf\xfes:\x19\xb6Xc\x07\xfb\xf6_\xd0\xc9\xff\x8aN\xfe7t\xf2\xbf\xa3\x93a\xfb66\xb6o\xff%\x9dLo\x9a\xdf\xd2\xbb\xe3\xb7\xff\x9eN\x86\xed\xe47\x8cd\xd8N~j$\xc3v\xf2\x9bF\xf2\xff!\x92\xdf\x1b\xc9\xff\x89N\x86\x9d\xe0\x0b#\xf9?\xd3\xc9\xbfO'\xff\x01\x99\xfc\xdd\x1f\xa3K\xc3.\x13\x1a\xc9\xff\x85N\xfe\xafd\xf2w\xbfC'\xffq:\x19H\xaf\xc1\x8d|\xf7'\xe9\xe4?M'\xff9:\x196\x01\x83\xa5\xf9\xeeO\xd1\xc9\x7f\x86N\xfe\xf3t2\xd0o\x83I\xf9\xee/\xd1\xc9\x7f\x85N\x06Bm\xf0\x17\xdf\xfde:\xf9\xaf\xd2\xc9@c\xdf\x18\xc9\x7f\x83N\xfe[t2P\xcd\xc4H\xfe\x9bt\xf2\xef\xd2\xc9@\xa8\xdf\x1a\xc9\x7f\x97N\xfe\xfbt\xf2?\xa4\x93\x81\"\x1b\\\xc1w\x7f\x8fN\xfe\x07t\xf2?\xa2\x93\x81\"\xbf3\x92\xff)\x9d\xfc{t2\x90\xde\xccH\xfegt\xf2?\xa7\x93\x81\x98\x1aL\xe1w\xff\x82N\xfeWt\xf2\xbf\xa1\x93\xff\x1d\x9d\xfc\x1f\xe8d\xa0\xb1\x06\x0b\xf9\xdd\xbf\xa4\x93\xff5\x9d\xfco\xe9\xe4\x7fO'\xffG:\x19H\xef\x8f\x8dd \xbd\xe7F2\x90^\x83\xc7\xfd\x0eH\xaf\xc1\xcc~\xf7\x9f\xe8\xd2@z\x7f\xdbH\xfe\xcft\xf2\xef\xd3\xc9@L\xbf1\x92\xff\x0b\x9d\xfc_\xc9\xe4oav^\x98\x1b\x0f\xc0*0v\x9e\xef\xf0\xb8fp.\xdf\x01\xb3\x14\x9b\xe9\xc0X\xde5\xc9\x1b\xec\x1bi\xa9\xd9\xb5)Hi\x8f>\xd7\x16rw\x12\xb0\x11\xce\xd4F`\xa3[\xa9p\x03\xc9Z=\xf6\xa3\x12;R\x96\xdf\x84\xc4M\x9am?l\xf7\xbcG\xabT\n\x0b\xc5}\xd0+x\xba\xea\x04u\xf4\xfa\xc0AA%\xd5\x10~\xa9\x86\x80\x00T(\x87\xcd\xba\xc9a)\xb5\x01\x18Tlmm\x1e]l\xcf\x8f.v\xfc\xcd\xa3\x8b\xfb[G\x17\x0fN6\x8f.v\xb7\x8e.\xf6\xc4\xcb\xde|\xd2\xbfw]%\xa3\xeadt\x93N\xfa\x9b\xdfL\xc6\xcf6\x7f{r\x05\x7f\x7f\xbe\xed}\x80\xb4\xab\xf1\xd6\xe6\xa3\x89x\xc5L\xf9\x02\xa9W\xe3\x9f\xe0\xcf\xad\xcdGlr\xef\x9a\xdd\x8f\xd0Pb-\xb5O\xa1\x939:\xba\xf0\xa7GG\x17'\xc3\xa3\xa3\x8b\xd9\xde\xd1\xd1\xc5\\\xfc\x01\x01\xab\x008B\x1c@\x8e0\x07\xa0#\xd4\x8f.NP\xe0\xba%\x05\xae\xbbsvt\x94\x89\xea'GG\xa2\xae\xbf\x05r\xd9\xf9\xfc\xe8(::J\xa0\xd0\xf6C\xfc\xf7\xe8\xe8(\x1f\xee>\x14%\x86\x0fA\xf9 \x1a\xc2\x7fC\xfc\xb7\x8d\xffv\xf0\xdf}\xfc\xf7\x00\xff\xed\xe2\xbf=\xfc\x87mn=\xc2\x7f>~\x01;\xf7@\xfc\xdb\xd9\xda\xda\xaa\x11\x18\xd46\xf5X\x9fE\xac\xcfz\x16M\xd2\xac\xdf3\x17\x1cH\xa1\xb7\xf7\xe4\xb0\xf7Nh\xa5\x91\x98j\x01\xd4\xb9\x80\xd4|\xf7\x08\xa5\xddG\x17\xa6\xea''5Q\xaak\xa0\x18\xa9}\xd0\xda\xf4\xb3\xcd\xdf>BA;H\xdaQ\xd4~t1\xe36u\xd3\x1az\xad\xf0Zz-\xd0\x18\x8d;\xf7k\xae)\x98\xfcB\x0d\x96S\x8a\xa4\x95Vt\xda\\t&\x8b\xae\xa9>\xb8\xb2\xa9\x12\xdd\xba2naU\xc6\xcd,\xca8R\xf5\xc8R\x8f\x85\x9d\xf4s3Z?wV\xd1\xcf\xd1\xed\x89\xbc\xda}\xcbe\xa9b\x19OQ\xa3\xa7\xe0\xdf\x17`\x03\xc5\x95s0\x9a]\x85\xe1\xd5\xf2*\xe1W\xe9Uvu\xc6]\xf7@\xaa\xef\xc6\x89\xc7\xa6\x1e\xeb\xfd\xb0g\xaa\xff\xd8\xcah\xe8\xb3\xab/\xbe\xb8\xfa\xf2\xea\xcd\xe1\xd5\xdb\xabwW?:\xac5\xc4\xfalnk\xac\xec\xdf\xbcK\xffT\x8d\xb6\xcf\xf79\xc0\x1d\xeb\x87\xd7\xa6\xec\x1b\xce\x06\xd8t \xea\xa6l\x10\xc0\x14\x97\x1d\xb0\x15\x18A#\xe3\xef\x17\x0eG\xd9Z\xa8S\xdc\xb5~d\xbdk}o\xfc\x93\xc1\xa4\xff\xc3{\x03~\xc1\xa7N,z\x10\xc35\xb1\xf2m\xf0\xe2\xf0\xf8\xf5\x9bW\xef^\x81\x91~\x0f\xac\xb8{\xe8\xc8\xd1I\x93\xa9{<\x1c\xa0E\xd3\x88\xf5z\xd7\x85\xc4F >\x18@`\xd6k\x8c\x14\x91~\xcf\x1d\xf7\x8e\x8f\xa7q\xc27\x7f\x9a\x1e\xa7\x0b?\xe1\xb3\xe3c\x9b\x95\xfdu\xa5\nv\xdf6\xed2\x83\xf6s[7\xb0\xa9\xad\x01\x88\xcb\xc2\x87\xcd\xe3\xce\x1de\xde[!JcN{\x05)\xe9\xd2\xe6>\xcb\xd8\x01\x1b\xb2\x11l\xda\xd7\x05\xbf\xa0\x9e\xc4 \xeb\xf88\x8cg~\xba8\x16{\xfdqqg\xe8\xf8\x988v\xb5\xb8OX\x17\xb9*PR\xf0\xa8\x02#\x983\xc7pZ\xcc\xb4\xf3sf\xc0\x8fULN\xf7\xd1\xa6\xb4\x98\xee\xa6@J\xb2VPx\x15\x86\x95.\xbeP\xd8\xfd\xde.\xf0\xbf\x7fx\x16\xc6\xe7\x07\xd5+>0\xc4X\x1b\xf8\xed\x0e\xb4\x01\xcb\xda\x06\xd9\xe4=\xacu\x9c\xe5\"\xeaW\x17#rdC\x8fEb\xe8\xfbh\x8d\xaf\x89\xd82i\x9d\x9c!\x83pS\x02\xd1\xc6\x96\x8c'\xb7\xc4\x88\x0cw(\xf6\x18\x83\xd7h\xcc\xd8*\x0c\xa6\xbc\x0d\xf2\x9d\xd0\x8bf}\x13D\"rN6\x9c\x88=A\xc7\x11N\x04\x9e\xa0\xd4\xd5\xd4M6\x14\xebm\xb0\x8a\xd1WD\x89\x8f`\x1e\xef\xb1\xcd\xcd\x02H\x1e\xdb\xba\xd6\x9e[@\xe9\x174z\x1c\xbb.\xba\x1dG\x93\xf1\xb0m\x0b\xba\xd5\xa1\x146\xaa\xd5\xb1\x08rW\xb91\xf6\x11\xba\xd2u5\x9b\x80\x8d\x01\xb0\x91\x15\xb0\xb1\x04\xac\xd3\xefkH\x12a\xec\xd0\xb1\xf8\xf0\xc4\x85\x08P\xe3X\xc0[F9j_\xdb\x0d\xc3\xddn\x1d\xae\x0d\x89\x12\x15\xf9\xcd\x95G+\xdb-\xa1\xebr\x01\xad\x14\xc9\x8e\xdf\xd2S\x1d\xd9\x9d\x1e\x9e\xe8\xd1\x81\x1b\xf0\x9bQ\xbe<\xe1\x89\x96\x90\x02\xe7\xa9%\x9c\xc4q\xc8}\xe9\xf4M\xf0\xa6\xc7\xc7@\x89\x8e\x8f{2\x10\xc0Hs\xce\xf7}\xceFe\x1d\xc0d\x9c\xf2\x0eb\xfc\x8f\xdc\x07\xdc\xa1>f\x1f\x1a\x16a\xd9\x0fz\x05F\x80\x8c4e\x03\xc1\x034\xeeU7\xdeHnk\xc8\x8a\xc9\x8d\xf7fK\x8f\xb6{7\xae\x8eI\xe5\xdc\xfdV\x90X\xa6\xa5(\x80{\x10\xe9u\xef\xac\xe2w\x9d\xbcI\x06\x8e/b's\xa9\xfa\xaa\x8dT\x11\xb8\x1d\xa2\x05&o\xaa\x05\xe0{(j\xec\xbb\xfe\xc8q\xa4N>\xe6\x13\xb8|\x90wu3k\xa6\x9cI\x8f\xbc\xbc\x00\x87\x95\xf3\x0ea'a\x07,\x1f\xa7\xc0C\x87\x82\xc1\x0c F\x9a\xb1\x1bH\x03w\x87\xf5[ \xf2\x02\x84!`AL\xd8~\xd4*A\xb2\x12\xc6\xd8F\xa3\x87\x15&\xe6\xce\x1d\x96\x8d\xb7&\xe3\xed \xde\x19\x14\xef[\x82\xbd\x13/\xc3\x89\xd8\x82\x8ao5\xdd`\x8e\xa4\x13Q\x88\xb6\x16QAB\xaf\x0d\xb5\xa1qwF]\x8d\xa3\xa064%U\xdbm0\xc4\xaf\x0bd#\x80\x99\x02\x1d\x91n4\x8d\xe1\x0b\x04K\xcd\xe4)\xdbg\x1b\xb9y8,\xce\xf4\x85\xdf\x98\x8dZ\xfc\n\x10\xb0\xf2\x8a\xc7\x03\x96nnZ\xa5\xabs\xd1\xbdqjq}=\x85`\xa18\xbbs\xc1G\xc0\x166\x9e\x8f\xb7&\x02\xb97\x1c\xf1\x06b\x92\xd2\x93\xcdFS\xac\x0f\xe8\xdec\xd6\xef\xa7\xec \x0b\xad\xbdZ\xb1}\xe6\xa8\xae\xb9V\xe7i3\x10\x0d\xaf,\xb9\x0b1IV\xaf\xde\xc5\xd0l\x04\xa5\xe6\x90\x04B\xdco8\xab\xe6\xd1\x8aG\xc6}\xb7\xd3\xbe3\x86Q)\x1bBQ\xe7.\x94\\\xb2}\x96;3\x8f-<\xb6\xc2U\xe1\xb13\x0b\xc5\x04\xba\xabwy f\x12\x0b\x8f\xcd<\x16\xb0+y_\xeeL,\xcae\xf3\x08\x1afP\xd5\xba\xc1\xa1\xad\xf5\xeai}J\xea\x07HT\xd1\xacu\x86\xbc\x01\x8b\xd8~\x04\xca:\xf3\xb5\xa2\xac\xe4\xd5o\xbd\xc3\xfa\xc7T\x7f\xbb\xf1x\xb7\xf4\xad\x9b\xf2r\x16\x8d\xe0C\xea~\x9fH\xaf\x97\x07b\xbd\xd5\xead\xa1\xeb\xa9\x8c \xbfLy\xd9\x8a\xe7ft1\xa6\xb1G\x91\xa5\x15V\xf0Gb\xab+\xdcT=a>\xdbd\xc3bM\xe6\x95\x83\\\x15\xd3\xfb\xfdH\xa2\x90H5\x9b7\xc6!\x17L\xe0\xe4\x1d\\M[\xf8Z\xc5\xd6\xde\x90\x93\xb5n\xc5u1\x9ade\xb7\xa9x\xa7\"\x9d\xd2\x1c \x14\xaa\xab?Sl\xbf\xaeq\x08ew\xea\xcdL%\xdfTO\x9f\x9b\x9c\xc1J\x0f\xac\xfaLy\xf0\xac\x9b\x97\xcc\xaa\xa5\x12\xff\xb2^b\xa1\x97\xc0M\xbb^\xe4\xec\xe6\xc2S\xc5\xa2,=v\xea\xb1K\n\xffO\x04+\xe2PG\xa1c\xc8\xc9\x88\x9cs\xb6\xcfN\xd8\x01\x9b\xb1\x11\xcb\xc9\xba\x87l\x9f\x1d\x17%\xa86.\xc4^/\x1a:\x17\x9c\xcd\x8a\x1d\xb0\x05\x1b\xb1sW\xfc\"8\xa6\xb7\xa2\xb8h\xf5P/~h+\xfe\\5|h.\xe7\xe7bK\x0fA\xd7e\xaedX\xa5!\x9cb\x8a\x8d\xd2\\l'\xe0+\xc5\x83A42>\xc5\xf76.\x8a\x06/A*x\xa964\xd7c'\"e\x8a\"\xdb\x98\x98\xb5\x11\x0bd\xeay%\xc3\x1c\xdb\x86\x13\xb1;lN\x0eM\xcc\xf6{\xb6\xcf.@\x0c\\\xb8\x96\xe9\x1d\x1f\x9f'\xfej\x05\x82jb\xa2\xc4\xf3\x8c\xed\xb3\xb7Z\xb5\xac^\x8d&w\xef\xc5\xb8\x9e5\x9d\x07_\xb1}\xf6\x9e\x1d0>\x00Wr \x11mp\x9a\xfe\x9a\xed\xb3g >-\x8bg4[d\x05\xf6\xa9\xf3\xcac\xaf\x15\x1c/\xdb|^\xd3l\xd0\x06L\xaac\xb6\xee\x9b\xd3w\xfd\xad\xd1\xd8\xea\xe4\xc1o\x9b6\x96\xd9\xdd\x1ev\xf5\xe3zv\xcbf\x1du.M\xb7\xef\x80\x02\xfel\xe6\x80w\xe1\x1a0\xc4\xe3k\xf4\xcd\x9f\xcd\xc0\xabP\x99\"\xb6D4\xca\xf0\x0d\xfb\x8b\xa0jj\xe1\x93\xf0\xad\x037\xba\x99\xae\xa6\x13O$w\xd3\xc8\xed\xb4s~\x9f\x8cX\xfb\xb7\xec\xbae\x00\xbb\x93\xb5}\xc2\x8a\xd06/I\x86\xb9\x93d\xf5\xb6(7\x17\x14\xdf\x90K\xfc\xafo\xf8\xa9L\xaf\xb7\x13\x9a\x1b\xbb\xe0\x01\xb6\xcd\xed\xbf\xd8\xa3?E o}\x93\xae\xf0\x03\x9f\xf9\x99aiZa\x05\xc0\xa3e#+\xf0\xa5\xbf\xa2\xf8\x00-\xd8\xfb\xf2\x84\x1bM,\xf5\"h\x97R/r\xaa\x17y\xcb\x0dn\xe3\xb2\x92\x0f\x12\xf0z\x91\x93J\x11\x10\x81\xd7\x8b\x1c\x1b\x8c\xcf\xa7\xf9|nv\xf8\xbc\x066\xffG\x01?\xaf\x17:,\x9c\xaa\x15\xeb\xde\xe2\x9b\xea\x02\x18\x83\x03v\x88\xfb\xc2\xabyg\xd7k\x8aX'\x1e;\xf4\xd8[\x8f=\xaf\xe3~z\x1e\x80\x0f4R\x8e\x05q\xdc\xceGF:\x93; \x1f\x9c\\f\xfc\x0bd\xf77\xc41P\xfb}u\xc50\xff\xd5|\x9e\xf2\xac\xcc\xc7\xdf\x8d\x1c\x88x8x\xa3:\x01\x00{\xd2\x1b \xfe2\xcbCG\x8f\xe9\x8e\x16:\xcb\xb6\xden\xbcu\x04u\x8f1\x18\x0c\xbce\xaeKl\xfe\xf0\xb5\xb9\xf95H_Y\xd2\xcf\x1a{\x178}\xee\xb1>%y\x86\xda\xb3\xc6\xda|\x10\x81Oq1&x\x03O+K\xe53\x1c\xc2\x9d\xe0\x0fK\xf3KK\xa7/\x9b?\x8b\xfa\xa0~\xc5(\xa9R\x7fA\xd7W\xbcZn\xa9vj\xaf\xf6\x0c5\xfd,\xb4\x8b\x8b\x80/sD\xfb)x{\x85\xb3\xde\x86\x12R\x00\xbb\xfa\xac\x15\xfb\x14\xfb\xf6\\\n\x1b\xec\x9f{U\xb4\xf5\n\xe0aa\xd8\xd8\xd5>\x9bz\xecyy\x14\xb5\x7f\xf858\xb4{\x0f\x88\xf8\x1eC\x15\x94\x0b\xb8\x91!|^\nm<\xf6\xda\x02\xde\x13\xfb\x8a.\xf9\xf8\x0b\xe55P\x0cJ\xfe\xb0J\xaf\x99\xb6\xce\xda\x94\xcf\xed[\xf4\xba\xec\x9c\x0c\xe1\x04\xd3K\xcb\xaa\xb8\x195\x82\n\xa5\x0e\x0d\x8e\xfb\xfdl\xc2\xf6\xc1\x86\x9e\xd7\xee\xa2\xb9\x1fC\xc4\xf5q\x86\xd786\xbe\xf6\xb0\xecv\xb3\x8f(\xf1\xc7\xd0\xe4xn\xe9\xb0\x8f\xf2\xde\x94\x02\"\x08@\xd8\x1d\x16\x9bp\x9c\x82f\x8e:\xcb\x0b6hJ\xf2\xffb=\xcc\x05\xe1H\x9c\xcc\xd5tC\x1b\xa1\x95z\x14\xd1\x8a\x04\xe34\x7f\xccV\x0dJ\n\xc1:M\xc7+\x8b$\x7f\xc3 A\xc0\x00^\x9aG\x9aA\xdb\xcc\xed\xa8\x95\x10\xdfX\x80\x190E\xc1\xc47`4\xa9\x0c\x87R4\xba \xa8\x98\x12\xf0o\xd4\xbc\xab\xa6\xba`-U\xf1P\xea\xdf*\xa0\"\x18\xb9P\x1c\x9eV\xec \x9b[!s\n\x1a\x10\x05\x1f\x8b\"\xe4\x12,\x07g\x16\xf0\xf9n!\xfe \xe1B\xe5%\x1cWg\x80E\x1c\xf0g\xc4|G\x9c`!\x15\xd1+\xb5)~u\x05\xc4 ;\x10=\xdc\xdf\xc7\xd3w.\x1bA\xd4\x84vO\xecJb\x90\xa8\xd0\x14\xfc$\xe1\xfe{#\xc7T\xe1.a{\x03\x9exZ\x1a\x92\x83m\xc6\xac\x89>\x83\xea\x07\xf0wi\x03\xfc1\xb0\\Z\xab4\xe8\xcf\x81\x17\xd3\x8a\x99\x03:\x16\xeb\xe6\\|\xad\xda\xc9@F\xec0R3\xd4D\x91\x01\x06\x8fE\xde\xb1.\xa6\x86\x14\xb2,|\xf3\\/{\x8eF\xdf\x08\xfa\x0e\x1bX\xaao\xa1\xc5\x0f\x81\xe0g?\xa8V\\\x9f\xf4\x13\x87\xcfJ|\xc7\xcd!F\x83\xb5 (\xd0\xdc|\x0b\x03>\x8e'b)E\xec K\xacK\xc9\x87\xa5T\x8fZ(\x9e\xcc\xf1\x01i\xd1\xac\xd9 \xc6q\xbf\x0f\xb1\x0e;\x80(\xf8\xde\x00\xa1\xa23\xaa\x91\xf2\xc7.K0(cf\x04'\x91\xbdKZzg7E\xa0\x05\xf9\xf7\xa9\xfb\xe2\x94\x94\xbcm\x0b\xb3\xc8\x1dbiZ\x9eHf\xeb\xc6\xd0\xb5|\xa7\x953[\x170C\xcbMz\x03`>\x84)-\xc1\xe3\x8f\x0b\xf0}\x1e\xc6~\xb6\xb3-\xb5\x08\x80\x80\xb5\xcc\xdd\xfbt\xe6\x8b({h\xcd\x19\xeeZ\xb3l\x1f\xfb*\xb06\x08Y\xcfC\x7f\xb9\xe23{ \xdb7E^\xe5\xa3\x1b[\x9e\x9e\xafaP\xad&\xdd^E\xf0P\xcb+\xe48\xb5\xf4R\x08afp#Q\nr\xea\xb3!q\xc5\xc8\x00\xa9N-MIrj\xc9J\x17TKVB\x9dZ2\x08r\xeaiRxSK\xfe1\xf7\xdf\x17\xfd\xd8\x18z\xeb-\xc1@.\xc1\xd8\xe1E\x94&\xb1\x1fm\xf8c\xb1*o`\xdaK\xfb\xa0\xd85\xac\xdfn\x81C\xae\x8f\x0dc5\xe9\xf1\x98L\xfb'u\xf6\x18O,,[$6\xe7\xc2\xec\xc6\xd5\x9c\xf6G\xae\xb9\x91o\x00\x03~\x87e\xa8\xea\xb5\x10\xe86\xcb\xd7\x86\xb3\xc6\x9e\xebh\x81\xb6<\xd93\x8b\xe9\x05}\xfd\xc8N\xe5v\\\x07\xae8y\xac\xa7\xd6\x8b\xed\xe2\xd9\x0d\x9a~\x9d\xc4\xcb \xe5\x1f\xa1\xe5\xb7<\xfb\x08\xad\xca\x95uK-o\x1b\x97v\xe5\x8aX\xdf\xc0\xb3\x12\x856.B8gE\x00\xda\xa8\xe1\xf4\x15\xc0\xf1!\xb2\x1c.\x90m\n(\xb6 \x99\x0f\xe9\x06\x96\x95\xd2E0\xcf\x9c\x06D\xd5.\xfe\x03k\xd1\xb64E\xf9\xc0\x89\x8b\xbd\xcb\xde\xb2x\x00\xf8q\xc3\xa2\xa2)-\x99\x8aS\xe1$\xec\xa9\xf4%\xa6\xf6\xbc\x91\xd8\xc0Y\x9f9\xd2\xc8\xfd\x80\xf5\x9e\xdc\x13TM\xfe\xee\xb3\xde\xd3\x9e^Jn\xa0\x82\xa1\x8aD\xe9\xa3Hf\x83\xa6\x10\xe4\xa0\xd4\xc2\xb3\xcfb`\xdf\xc2\xd4)kC\xc7\x138J\x96\xbf\x07\xfej\xc5#\xf0\xef\xe0\xe9\xf84\xc0\xc4\xb8\x92\xa8\xcc\x18\x9c\x0dq\x06\xdd\xd8\xeaB\"\xe0N\x06br\x01\xb5*\xbc4pi\x80*W\xbf2s=`=\x86e\xb5\x072\x0e\xd6\xabN/\x8a3\xe6\xa7ip\x1a\xf1\x19\xcbb\xe6\xb3\x95\x9f\xf0(\xdb\xa0\xf8\x07\xf5\x9ci\xfe\x91\xe8^\xaa\xa7\xf4H\xa3 f\xec\x0d\xe7\x8e\xd6[IT#\xaf\xd2\x02\x8a\x80\xfa\x82\xc1P\x94\xd6\xf5\x9agE\x7f\x14{\xe9P\xbc\xa2zlT\xca\xc2f\x08\x9a\xd7uJ\xb4\x0d\x17\x0d<\xc4\xd0\xe0\x84\xcb\x95\xd7\x1d\xc1\xe7\xaa\x1c\xd1\xd3\xce$\xd3*\xfa\xac]d+~}pK\xc7\xc3\xce\x83\x07\xf2\x80\xdd$\xe8W\xdbyu\x80\xbd;\xbd\x11\xeb\xdd\xf1\x97\xab\xc75\xa2x\xb7wW\xe4\xfc,\x8f\xb3zV\xef.VZ\xc5\xa9\x91\xf5\x04\xb2B\xb3\xceS\xc88\xcd\x1ek\xc1\xfa\xda\x04\xe3\x16\xa9\xb8$^\x92\xb2\x01\xf1*\xc4=\xce\xf8N\xef\xc9\xd3\xbb\x18c\xa1U\xd8\xa6\x04\xccFP>\xe0\xd9\xca\x8e\x92\xd0\xad\x91G}\x08\xf1\xe3\n\xdc\xa5\x19\xc1\xa3\x1dwpx\xc6\xa3\xecp\x19d\x19O(o\x1f\xe6A:\x913\xbd\x08\x0cu\xb5x\"\xe7\xe1\xd0ub\x0f\xfc\x97\xc4\x837%\xc5\x14_\xbc\x0f\x89?N\x82\xacH\xdc\xdd}\x00\x89\x9f\xe5\xab\x90_\xc8\xa4]Hz\x97\xf8Q:\x8f\x93\xa5L\xdd\x83\xd4\xd7~\x9a\xbe[$q~\xba\x90\xe9\x0f!\x1de\xe2x\xb0\x8bu\x97\x1f\xc1\x8a\xb7\xe97\xce4\xdf]6\xc9yL\x9fF\xf9\xe0\\\x0d\x07U \xb8\xd5\x88D.j\x80\xd5\xd8\xca\xcfS\xae\xbd\x1a\xc7&\xfa\x93\x01I\x85\xa2r\x1f\x82\x16\x13\x9e\xe6\xcb\xca{\xe3\xa9,\x1a\xc4Q\xc1\x92\xc5`,\x08 \x89\x1fD=\x8f\x05\x90r\x1c\xa4o\xb3Y\x00r\xfcL\x1b\x18\x1e\x9e\xc1\x119\xd4\x12l\x9c\xc7r`\x88\xc4od\xdb<\x96\xd6\xa5xg\xd2Ztch\x83oN\x0e\xd6\x87\x8f\xf9r\xc7\xe5H\xc7\xbaA/\xed\xd0 y\xa9\x8d\x0ff<\xcd\x92\xf8\x12\x17\xb6\xfc\xd1\xf5\xb3!M\xb7\xc5\x16:u\\OZ\x02$\x830H3\x1e\xf1\xe4\xb9\xd8\x87\xa4\x13\xe1\x1e\x17\x9bi\xcfU\xfbk\x9d\xde\xd2_\x9cZ\xd1d\x19\x9f\xf1/\xe4wjsndj\xf3oV\xd5\xe7\xb9\x9eW\xce9Y\x13F$\x98%\xea\xabz\xae\xed\xab\xd3\xc6\xafN\xc9v\xcb\xdc\x86\x95\xa0\xc8-br\xa5\x9f\xf5\x14\x1d\xdb\xa7\x06\xb6O\x8b:\xd5\x14<\xca\x08\x02\x04gL\xaf\x95\x86\xbb\x10`\xa9\x89\xac\xf7\x04!I\xb3$\x98f=\x92\xaa\xdf\x1f\xba\x03\xbc\xadDZ\x08\xec\xb6z\x9c\xaf\xe3R\x81f\x9cD\xb3\x8d\xf6m\x8d\x15\xa6\x91\x9ci7E3Wg#\xdf]\xae\xb8d%\x9f\xfb\x91\xe0&\xc5>\xc3|6\x0d\xfd4e~\xca\xfc\xe2K\xc4\xb9\xf0C\xe9\x86\x1b\x19\x9e\x05\xf7g\xd2LK\xa6d~\x10VS\xe4y`\xdf\xea\\\x99i\xbb\xbc\xe9E\xaa\x99QS\xbc\xad\xe5h\xe9g\xbe\xd5;Y\xc4/2\x94G\x99\xe34y3}(O\xc1\x16\xa9\x18.\x88}@Q>\xaa@%\xab\x82$\xf3\x98\x8c\x01\x80\xcdT\xa1\xe1U\xc6\x9eG \xfc\xfe\xf8\xc3/\xfa\xdb\x05\x062\x06\x89\x06 \x10\x06\xebc\xac!\xc6:c6Fl#\xf0R\x00V\xb6\xdat`\xe5\xeaH#z4\x10\x10\xa1\xcf3\x12\x01\x87\xc6\x10\x0f\xaa\x03\xaa\xe1x}\xca\x8b/ \xf0\x16\x91A\x949\x05a\xce\xde\x04\x11\x15\xf5\xae\x11\"M\xbdkY\x81\xd5\xaf\xfd4\x0e\xda\x1d\xb8#\xfc\xf7\xeb\xf0\x97\xd0\xa3|\xe6Tn4\x15\x9d\xc5kM=\x14\xc7\xc3\xacHoH\x02n\x8f]\x16\xb1\xfe>\xe8\xc03\xcb\x9c\xd1f\"5\xf8\xc5\xd1\xd4o_D\xcdcJ\x06~\x18\xc6Sg\xcbb\x8an`LQ\xb3\x0d\xedJ\xc8\xc0\xb19F\xb3)\xf9\xbd\xaf\xa2\xd4\x9fs\x87\xb3\xa7O\x9f\x82x\xd2\xaf\x82/\x17\xd3\xf9\x98\xf9\x8f]\x00\x9c\x0f\xdf@\xa8\x06x\xa3>\xf7@\x97\xb6\xbaD\x9b\x1fQ\xa5\xaf\nV\x0c||\x04\xba\x0d\xc4\x81\x01\xe2\"\xe1\x83`\xb5d\xf4\xb7 JW|\x9aU~\x0c\xa6y\x9a\xc5K \x13\xa5t\xa6\x98\xa0q\xbd\xe0\xa4 \xd9\xd5j.*\x11r5\x1c\xd6\x88YI\x8e\xe5\xf2\xa6(\xae]\xfa,to\xa0/\xd2\xc6k=rw6H\xa2\xb6\xef\xea\xeeN+nH\x8eD=\xb0\xefC0\xcb\x17\xcb%\x9f\x05~f\x95jH\x05\x0d\x1a\x19I\xbf3\xe6}7\xfd \xe1\xa2\xbb=\x7f\xda\xa0\x9baRw\xc3\x07\xb3x\n\x922{\xb9Uitt\xca\xb3\xd7\nI^\x81R\x83\xcc\xb0\xba\xb0\x12M\xad\xc0\x92D\xc0\xe4]\xb0\xe4q\x9e\xc9\xe8\x88\xdc+\xfd\x1c\xac\x92x\xca\xd3t\xd2\x835\xfc\xf3\x0fEpIy!x \x0b\xa0\xb1m\x1b\x1dQ\x8f\xa6\x07j\xa4\xdc\xfa\xb3p\x88\x0b_\xea\xb1 \xb8\xd8HG\x9d\xa6O\x80\x12u\xb0\x8a\xd3\xecK\xe9@M\x9c6\xf9 X\x8a%\xf9v\x9a\x04\xab\xccj\xef\xa3\x1eE\xc47\xb6\x9a\xa5\x88LJ\x12\x05\xb3nu\xd1\xa6?\x05\xf3W\x94o\xdb\xf4\xeaOF\xeb\x10\xf4\x07\xf7\x86\x12\x02N\xaf\xe7\xb1\xde'=y\xaa(?\x1c\xd5o\xd9UZ\xa1g\xc2qA\"%\x9b~\xbe\xf0\xa3\x88\x838\xdb\x01{J~\xce\xaaY\xee@\xc0}H\x0f\xb8\x11\xb9\x16\x0e\x07\nn\x93y\xae\x81\xa7\x01tb\xbb\x02\x14\x0b\x16\x82l\x0c\x16b/\x8e\x12\xee\xcf.\xd3\xcc\xcf\xf8t\xe1G\xa7\x1c|\xdd\xcc\x07\xd3\x84\xfb\x19\x97\xa2w\xa7\x97\x02R\xf5\x04`\xc0\x8eq^\x90\x00Yd\x9d\xae*\xd4\xb3~\xc5\x8e`\xd9\xc0\xec\xf1:\xe8%E\xbdt+\xc8d\xc5\xf2d\xfc|\x11\x8430s\xced\x9e\x1d\x8fD-\x94m\xabZv\xc0w\x87SI\xed\x9c\x85\xc7\xb6\x8c\x1bF\xea\x11\xa4\x03\xc43=}\xcf\xf8\xa1\xd8\xed\xe0\x16P\xe2G\xb3x\xe9\xc8@\xb5\xc8m\x14=h4a\xcc\x06i\x9c'S.ob\x08\x8c\xd1\x83sI\x1b\xa5\x812\xe9\x93|\x172%A4\xe3\x17\xaf\xe6\x8e\x0f\x02\xbd\x85\xd3\x97\xe9\xa0pq\x14\xd3b3q\x14\xeb\xd8\x9f\xcd@\xd8\xaad\x14\xb0*\xeb\x89NO.\xba\x1el\x7f\x1bC\x10\xfc\x0e\xfc,\xf3\xa7\x0b(\xe9\xf4\x8a\x85)\x052Ig\x00T\x89\x8c/XX\xa43\x96\xf9\xf5p\x93*&\xa1\xf3\\kR\xb5\x8d\x9a\x19/\x97DGy7q\x80\xd1\xe6MF\x7f\x156\xbd48.\x14\\\xea\x10\xb1 \x11\x0f#\xe4>#\xf6DwM\xd0\xef\xbb\xca\x97@Qo\x0c\xaaA\x8b\xdd>\xd3\xec\xbe\x9aW\xa1\xd8\x8fO\xfc\xe9\xfbF_\xe3\xe2\xf1\x93\xd3\x942\xb8S\x0fq\xacU\x8f\xdc\x86\xc2q:A\x01w\xe2\xa4\xae\xc7\xd2~\xdf\x86p+<\xa2\xe9sG\x1c\xa4\x1b\x8c\x08f\x0d\x16%\x18\x947\xac\xdfhd-M6\x18\xa9\x80t\xd4\xa5\x88\x04\x0d\x94\x86\xe88L#\xca!\x19\xebV=p\x85\xad\x8d\xc8N ?|\xf5'K.;p\x02\x1b\x1dW\x8f\xfe\xa8\x81\xa0RW\xa0Y;\x83\xa3\x9e\x04\xea \xack\xee\xbdz\x94\x91u\xd2\"\xbb\xa0\x1e0\xbc\xde\xb2\x1b\xdfRO\xa3\x01%\xf5\xb4\x98i\xd7\x1f\xe8\xd3p\xdd>%\xe3-\xeajw\xd3s\x9d~m_\xa7_\x1eK\xc6\xc3\xef\xa3w;\xd7\xef\x9d\xf8\xbb\xfd\x91\xfb\xd8j\xebM=\xa0\xb0\x0fA\xe4@\xd8{P\x0f\xcdQWJ\xd8\x98\xa3\xa2\x00\x9b\x07\x91\x1f\x86]\xe8\xc3\x0c\xd8\xb9i\x87\xf3\x825\xb7\xab\xe1oM\xb6\xe7\xf4\x8a\x98\x05:/\x94\xf2p^^aW\xf7W\xb3E\x90\xc2\x0d\xd7\x11\x14\xd0\x94\xc0\xba\x11\xc0\x0e\xec\xc5v[\x80\xee\xd7\xa2\x8a\xed\xc3B6\xed\xc4\x17\xadV\x06a<\xf5\xc3\xb7Y\x9c\xf8\xa7\xbc9\xe6\xda\xd4\x07\x02\xd8\xe6\x15\xa45\xda\x19\xd3U\xca\x95\xef7\xc6^\x97>#\xc0\x9c\xac\x97%9\xc7\xc3?\x9e\xfb\x9d\xc8\x1dd\xf1\x17\xf19O\x9e\xfb\x84\x06Y\xff\xd5\xf9^\x1fS\x97a\x9c^\x14\x7f\xc6W \x9f\x82\xe9ZO\xbb\x97g\xf6Wi\x9b(\xd7\xaa\xf5\x9b\x82M\x1b\xfe\x06ycS/\x119=\xd0\x10\xd5\xbaV7>\xb29\xf7f`\x90\xd0\xcb\x12\x7f\xca+M\xb0\x036\x8d\xa34\x0e\xf9\x002\x1d\xf0w\xa4\x92\xce\xfd$B7\xe0\xb0\xf7w\\SL\x17\x17 \xa9\xc9@%UZb\xb5\xadC\xebR\xea\xb4\x86hA\\\xc5\xf9N\x99\\j\x0cw\x86\x96+\xe5[\xbbd\x00\x98\xc0\\\x1f\xa8\xdc\x03\xc2\xa0\xe9\xf7\x82\x12\x890v\x98\xe1N\xbb4%!\x02\xe8\x8b'\x1e\x04\xd1\x82'A&\x1d\xc1\x0c\xc1\xd2C\xa59\x01\x9a\x99\x04\x9a`\xfd8\xd3\x8cF\x9a\xa0\xc5\x007\xf0\x94\xdc\xea/\xa4\xc1\xb6&r\x86\x8f\x1et\x9a\x9fj\xad\xdd\xebT\x1a>\xba\xef\x96f1\xd7\xac\xaf\x19\xd0ti\xa1M\xe3\xbc3\xa4\x02\xe8\x8bt\x8bK\x82\xbd\xf6[\xea\xf5\x89\x92\xaa\x08\xbc\xac]\x1e\xe0\x0c^H\xa2\x9b?\x88\xe2d\xe9\x87\xc17<\x81k\xa9\xa0\x96s2\xed\x8678.+\x95\x0d\xa5G\x0c\x7f\xe0\xa7\x97\xd1\xd4E\xcf\x04\xfe`\x95\x04\xcb \x0b\xce\xc4\xd6\xa7\x8c`\xd8A\xf5\x13p\xb1z\x0b\x0e\xeb\x19\\\xb3\xc0\xaaF\x89m\x17<\x7f\x8f\xea\xb5\xb5vE\xb1\x1d\x17bQU\x13\xf70Q\xbc>\x84f\x8a\xae\x82\xe5\x8f\xb3\xb7\xf5\xc8\x95Q\x8d\x96\x8146r\xf6\x86\xa0\x9f\x19\xcc\x82t\x15\x97\x89\xbb\x90\xb8\xf4/\x9e\x9d\x16i{*M&lc\xcd\x84\xcf\xc1@\x85'*}[\xac8\x81(\xfe\x9a\xab\xa6\x0d\x91v\xf7(D\x02\xa1\x8f\x7f\x92\x9a\xa8\x049\xf30\xd6\x1dbwC'\xa5>J_\xfa/\xd1_\x05\xba\xe8\x00,\x11Get\xa7\nN?\xee\xdcaA\xfay\x10\x05\xe0\xa2\x1a\x1c\x0dq\xf0\xf2\xe1\xc4\xd2\xdfP\x9bQG'0\xd4\x88\xc3\xde\xb6\x0b\x82[\x18c\x1a\x9cF0\xf5\xbb{;\x9d\x88F\xfb'\xac\xfb\xb3Re\x15\x1f&\x17\x18m6\x05h/\x0d\xe0\x9c!z\xa5\xdbT\xbf7\xb7\xb7\xd6u\xe7\xb1\xc60\xec\xb6\x99\xdadz\xe5\x8c\x03Q\xd0=\xb2pi:\x81>pn\xa3\x9f%b?\xa0\xbd\xd2\x0e\xef\xd7\xfd\xdaH\x02Y\xf7\x98$\x03V\xee\xd1\x01+\x05\x9dm\x86\x0e\xe3\xb4\xb3\x81\x08oCUgX\xec\xe5\xe8\x10\x03n^I\x97\n\x15\x9a\xebjtG\xd1\x1b\xc2\"\xfc\xd5J|\x1d\xf3 l\xe8\xca\x9f\xf4\xb4\xe6\xce\xa8\xe5\xcc\x9bbEt\xd8z\xa0\xda =6\xf7X4\xe6\x13\x88\xe9\x81Nx\xc8K\xe5\xb6\xe3\xea\xad\xe0\xf2\xae%\x16\xe0\xce\x90\xf6K9\xbco\x89 \xfcp\xcf\x1d,y\xb6\x88g)Ejw\x0d\xff\xc0\xa9\xe4\xec\xeaG\xa8\x90^\x0cp,\xac\x96\x9cv]6\xf3re\xa0\xa6\xb1\x9a\xad\xd9(\xa0(G\x12\xcb\x80\xd7\x86\x82!1\xe3\x9a\xdf\x80\x05\xa4\xf2e\x90uXX\xc4Q\n\xec\xbb=vVD*\xf5\xd8\x89\xc7\x8e!\xc8\xec\xa1\xc7.0\x9a\x96\xc7\xde{\xec\x99\xc7^y\x10tk\x0e\xe7/\x9a\xe2c\x00\x11y\xa1\x14i\xb9\xdc\xbd\x0b\xf14\xee\xd6\\#\xe8\x1aW-\x10\xff\x02\x9cu\xea\xc9\xae\x07Qq.\x06\xa7<\xf3 \xf2\xcd\xc5 \x15\xaf\x97\xf0\x8a\x9a\x0d\x0f\x02\xd9\\\xa0\x06\xc5\xf5J\xc1\xcc \xe1i\x1c\x9e\xf1$\x85\xe6_\xc9\xad\xa5H\x15\x8b\xfa\x19SA\xf3\xed\"-Vn\xc0\xd2\xb4\xaa\xa0 &\xf9\x10\x1b\xf2+\xf8\x1e\xf8\xbeq\x02\xb7\xec\xd2>n\xd2K\x91\x08\x8aIb\x9b|-f\xab8\x89C\xe0]_Z&\x9f\xf2\xac\x07\xab6@s<\xd7c\xaf\xc9\xe8%\xa2\x0f\xe8tO\xf0LAi\x808-\xe8 \x9e\xe2\x83\xf1\xd6DP\x80\xb0\x9e\xae\xfa\xbc\x8f\x9e\xa1\xecB!bd\x8a\xb7H\x9c\xde\xf3 \x99\xe6\xa1\x9f\xb0 :\x8b\xa54\xc7c\xbd\xe7/\xde<\xff\xea\x8bgo\x8e_\xbc\xfc\xd1\xab\xe7\xcf\xde\xbdx\xf5\xd2\xa6x\x17\xad\x9e:\x01!\x8bA\xa5\x92\xe8C\x03\x18o\xa9'r6^\xa3J2\xf6\xd8s}^R5/R\x89/\xf8\x90*\xfd\xf4\xd8\x99[x\x15\x14\xeb\xa3Q\xe0\x06\xc7gzV-C\xc5\xbb\x02\x8dh\xa3\xae\x13\x14\xa8[\xe2\x90\xc5\xaa\x10\xf4m:\xb2\x97xT\xc7\x97Rf\xc6F5$s=\x1b\x9a\x17\x9d\xbe\xe5IB\x93\x000\x19&\xa6\xa9\xb8C\x8eV\xad\xa6'l\xdd\x93\xfa\xed\x92\x02\xfd\x8e'lyRT\x0c\xab\xd0\n\xa6\xb8qZ\xe3*5\xa0\xfc\xda\xc12\xbd)5h\xe8\xdc-O\xdf8\x16k,\"'/V\xf3\x16U\x82\xf21\\c>\xa9\xfc\x8f\x93\xe04\x88\xfc\x90T\xf8+n}\xc4\x9e\x99\x99\x92\xd5\x7f \xde\x83`\xb7W?\xcd\xb2\xa7<\xebr\x15T\x0e\xf2U\xc1\xe8\xbdr\xb8\x0b\xbb\xdc\x01[\xa2\xb3\x07\x89\x14\\L\x86I\xf5\xcc//\xfct\x8d/[\xe6\x91r\x12o~\n\xf7\xdb._\xb3\x900\x86\xfd\xa5{\xc00\xaa\xfa\x9d;\xec\x12-\xa5\xd8>{\x0d\xbc\xaa\xb4`\xc0\x1f\xefu\xb4\xc0\x9c\x1e\x86\xa8\xa3\x1cE\x99\x83\x006a\xd4\xae\xf2P\xa2\x15\"N(\x83\x80\xc8w\xee\xb0\x13q\xe6\xd3X#\xaf\xe8\x18|\xa5\xd7\x15\xb0q4j?\xb52M\xa0#\x16\x7f!\x10y\x0bz\x0f6\x02\x1b\xac2\xf9y\x91,\xa1TZRA\xfcW\xf0\xe41\xab\x08\xf5i\xdf\x15f\x7f\xc5\x18Glaf\x14\x87\xe1\x0e\x00\xe6\xc8\xd9\xca\xe5i~\xb6\xbe\xbc\x8fMV\xcd~\x95\x05-\x8b\x1a\x883.A8\xe5\xe1\xf1\xae\xe4d2\xe0d\"\xe4\xd1\xfc2\xc6]\xbdC\xeb\xec\xe9\x85\xa8[\xb6&7\xbfj\x93\xacmi\x11\xe4\xa3\xdcTp\x17\xf1\xcb\x00}\xf5\xfe\x9e\x83\x14\xbd\x95\xf5\xe0\xad\xb0\x93\xdd(\x87.\xf7\xdc\x91\xda\xef4\xb0r9k\x02\xa0%u\x8b\xb0\xb3bE\x9b\x82\x97\xc3\x8f\xd6O\x1f\x82\xd8K\xd8\x93\xdd-\xb1\xa0\xa1\xe3\x1210\xe6\xbe\xd9\xff\x95\xf3\xcc#\xfa\xac\x0b\xbfF,\x00\xd7UV\x12\x1b8\xc7D\xae\xa4]\x81\xe3\xab\xd3\x8e\xf9\x15\xd8\x89\x02\xe7\x9c\xca\x83\xbd\"p\x0e\xcd>\xfbE\xca\xad\x1c\xf1w\x86T \x10q$\xb7h\x99\xea\xe2-\xb1\x97\x83`r0\xf5WY\x9e\xf0\xb7\x99?}\xff.\xf1\xa7\x9a(\xa9\xe2\xab\xa3U#\x15I{D\x94wR\xd1n\xf3\x8aphH\x88\x90\xd2\x9a\x90\x89<\x0b\x07N*\xddm\xe5\xb8\xa9I\x8f\xa4\xca\xa9=hdR\x19\xd50\xc2\x9b\xb8\x81*\x1b\x0d\xa6\xf1L\xe0^\x0eWu \x08D\x84\x8c\xea\x9a\x0e\xa8\xd7\x90\xc7\x93j\x05\xdc\x81\xa5\x90\x02}\x85t\xd7.H\xf7n\x0e\xed\x15e\x1e\xc7#\xd6K\xfcozu\x1ae\x96=\x11\x18\xdf\x9b\x9d\xfb\x1d\xcaf\xc97\x97#\xd6\x13\xffz\x06\x8a\xf3\xc1<\x8eY\x9f\xf1\xc1\x89\x9f\xc0\x7fQ\x0eh\x83\xe8\xca\xec\xdc\x87z\xb7,\xb8\xdd5\xa2B5Hn\xd7\x08\x9c`\xd1\x10\x94\x17q\x02\xc3\xe4\xd6c\xdb5\xbe\x1blu\xb9.\xe9\x04n\xb4b\xa4M\x8a\x1a\xedV<|\x9c@\xfc\xd1qBX\x9b\xb6\x9a\xecD\xe8\xac@\xac\xebV\xf3\x0bd\xf8\x87\x8f\x99\xcf\x9e\xb0\xf41\xeb\xf7}y\x85\xadX\xa0\xfe\xc4\xc3\xf8\xd4\xca=Q\xee\x9a\xea\x13\xcd5KT\xe8EHL\xff\x18\xaa\xc3\x87CT\x1dj\"vT\x1e>\xdc\xfe\xd8\xcaCz\x12\x15\x8f\xa1\xf9\x96\xed\x15Z\xf5\x1ex[\xac\xceC\xe3\xa4\xd26X\xb7-P\xa6\x94#\xda\x00\xda\x96S\xbd\xe3\xb2\xd31x\xc3-\xe6\x06\x8fg\xeb\x1a\x9f\\\xab\xef\x04\xc5\x94\x9f\x18\x91\x97\xa6\xf0\x16\xda\xc8\x98\x9ak\x0e\x1c\x86}\xe7\x0e\x8b\xc7J11\x11\xebr\xdd\x10\xb9\xed\xa8)\xd0\xfc\x01\xe2\xbf\xbc.W\xb9s\x9b\xf9A\xa4V\xc3\xee\x0dV\x83\x82\xb6N\xe6\xd7\\+M{]R\xf6Ulz\x1b\xcae\x88Ju`\xf7R\xbe\xeb\xeby\xf38\xee\xdd\x8e\xaa]\x0d\xd3\x00\xa5\xbc\x0es]l\xa8\x1d\x11+\xcae\xf6\xf46\xf5\xef\xb5\xeb\xa4\x9er\xc8N\xe9\x80\xe6\xb4^t\xd5Y\x953\xeb\xaa\xcaY4\xabr\xce,\xaa\x9c\xda\xe7\x96]5>\xa7\xed\xc1n\xab\x15.I\x8a1\x8d\xa3yp\x9a\x83\xf6\x95\xa6\x1a\xbc\xd0\xce\xd2\xae\xaf\x95\xa7\xa4&\xba\x92\x1b\xdf\x164*i\xe3V\x98\xe2X\xac\x87\xb69\x185\x9c\xea\xb8\xd7;>\xe6\x1c\x0c\x07\x0e4\x07s\x90&\xcer\"\xe9rp\xe6\x87\xb9\xe0h\x16J\"sV\xab\xed\xb1K\xd7\xd3\n\xcab\xd1\x98O\xd8\x01\xe5t]\xe6\x88\x7f\xe8\xb1\x0d\xacO!u\x9f\x8dQ\x9b\x9aM\xca$\xe9\xad\xa3\n\xb1\x1a\x8d\x8f\xa6|\x04\x94\xbe\x1b\x94<\xdd'\x98z*\x80\x8a\x95[>c\xb9F]\xee(J5u\x8c5\xe0*\x992\xdah\xb7\x8a\x05\x07;\x02\xba\xaf\xa2i\xe1\xd4\xe7\xf8\xb8#(\xe6\xf3\x11\xf0\xbe]!!\x89\x04-\xe7F`l\xd0hS\xf1\xa7@\xd7\x97q\x80J\xc4r\xc7|\xd2\xa1\x9e\x896\xe8`T\xd46!\xc6\x14\xeb\x1d\xe0\xed71y\xc98\x98\x08\x1e6pY\\\xfa\xe5\x8d)\xb8b\xae`\x94\xb7\x95s*%\xd2\x97(\x98\x8c\x03i%7\x14\x88\x99\x0c\xd2\x15\xdc|\x0c<6\xa4\xee\xee\x81*-)?\x9b4~V\x8ac\xa3&\xeb\xf8\xb6iG \xa2\xdfzG\xf1\xac\xf0j\xd18\xef\x16:!\xb6\xe3\xb8:\xa1\xf6\x19\xa1\xe7\xb1\xd9\x19<\xccbD(\xc9d\xac6-\xde\n\xdew\xcc\xf0\xc8\x92\xb1',\x12\xd3\x9d\xb9,\x18g\"\xb3z\xd91k\xb8\x08\x07\x1f\x8d\xc1\x81\x05^h\x95\xedn=\x06\xc2\x1b\x8b\xca\xd8\xb4\\\xc5I\xa9\xc9!\x1b\x95\xbaTu\xa3\xac>\x96&\x00t\xb9\xb55+\x88\x0b\xe8\xa9\xec\x03c\xedw\x8b\xba\xdc\xc6\xaa~\xaf\xc6\xb0\xdc\xfc\xeb-\xb7\xad\x9a\xbe\xeeU\x84G7\xebK\xa7[U\xbf\x10\xfc\x14\xcf\xaa\x06\x05\x1b\xe6\xfd\x80\xfe\xf5\x81\xf2\xc6,8\x8b\xa9S\x17z\xe2^:u\xe2z\xba\xd8X\xa6N\xe0R\x84g\xea\xe8\xe6\xd0hG\xb8t~\xfe\x01\x85q:{\xdc\xec\xf5G\x19\x8bi\xa1*\x17N\x88\xce\x88\x8bSc5T\xa4\xc72e\xb4\xc4\xf6Y\xfe\x03vS\x8eY\x9e\xa3\xea\xb1~\x1b\x04\xab\x04\xdb,\xf88\xd2=q\xf9\xbdf\xe7\x01\x1a\xdd\x1f,\xfdU\xbb#hU\x81\x1d\xb0\xcc\xe1\xe3\x08T\xcf\xe2\x7f\x15%\\\xe9|\xc9\xc9+Zi\xf3\n\xff\x07o\xbdc\x0d\xc8\xbd@\xe0\xd516O O\xc5\xbe\xa1Zq\x05\xd7u\x12D\xb3\xf6P\xb6\xddg\x16\x8f=\x8f(S9\x9c\xa8 \x85\xff\xd7<\xd5\xc5(\xda\xe0\x10\xce\xfdv\xba\xdd\xe9 \xadD\xcb\xc8\x98\xe2H\xe6I\\\x0b\xc8\xd5t\xdcF\xff\xed\xe0]\x00\xe6p\x0c\x82d\x0fe\xc4\x13\xd7c\x9f\xc6q\xc8\xfd\xc8\x01V&+}.C\x01\xd4\x05\x81]\xf4m\x8cY\x13\xe4<\xdav\x07A\xc6\x13?\x8big\x8e\xc6\\\xca%\xfa\xc8fAN\x1a\x90\x1bK7\xa5\xe5\xc9!\xbd\xfe\xa7\xf2\x9bur1\xaf\xe3U\xa7c\xb5yX\x9e\xdd\xc6a\x94\xc8\xd7\x0f\xa3f.\x1c\xe6\x08\x1f\x8c\x1f\xac'\xf9\xeaQ}\xddET\xb2\xa5V\x13\xcaV]\xd2\xdbF]\x128Z*%\xf3)J\xe6C\xe7B\x06\x08\xbf\x90\x0e\x12\x99t\x19\x0eh\x0e\x13'R\x02\xf4\xf8\xec\x16\xbe\xf2\xaa\x8d[\xfc1\xc0 \xe8\xc2zF\x9c3y\x89F\xaeN4\xf7tN\xb5\x10\xc5\x82\xa4 \x16\xc9\xdb\xdb\xf2\xc2\x9e8\x9f;\xcb\n\xc71t!b\xd9>\xe3p\x19}i\xe1\x86\xf0T'\xbe\xda\xc2\x85W[\xaft\xaa\xe2f\xe4T\xb05\x91\xcb\x96h\xcc\xc7I\x0bJ\xf5\xc8\x91.\xc9\x02\xe6\xa5R3e !\x03\x7f`/\x040\x9f\x1bzdf*'\x9cs\xe8n2\xb1\xc2\x02\xe0p\x02f\xae\xe7\xf2J*\x1a\xd2\x08\x82\xa9\xe0#\x0e\xc8\xe2l~\x02\xce\xc5\x9c\x128\x1b\xc7\x83Y\x1c\xf1\xc7.(\xe0/\xd8\x81b\xe2\xd0\x1a\xf8\x18%&\xd2\x90\xbd\xf8%\xf6ogVHS\x0e=\xb6p\x96\xb02fp\xddJ\x82\xf9\xb0\xfe\xd1~\xdf\x125K\xcc\x1c\x11\"\xa84\xf7\x9c6`\x03@\xe0\xb4\x123\xdb\x1c=\x8c\xd7\x03\xb9]\x0d'\x0e%B\xc8Py\"GZ%\xed\xb3\xc3\xc1t\xe1'\xcf\xe3\x19\x7f\x969[\xae\xcb\x9e\xee\xb3\x07\x0f\xb6\x1f\xed\x82\xc5\x12{\xb2\xcf\x1e\xec\xee\x0c\x1fA\xf9Cp:9\xee\xf7\xa3\x89\xb4g0\xc0y(\xedG\x0e\xad <+Ax&A\xd8\xef\x9f\xd9\x81v\xd6\x82\x8e\x1a:\x89=\xf0\xd4D\xb8\x02z\xbe\xa3\xad\x9d\x1a\x00\x9dS\x97^P\xe40%4\x15o\xd7\x1d_H~\x00\xbb2\xab\xc8\xee<\xb6,/\x89B\x8c\x90\xa2\xe6\x0d\xf6\xf5\x9a\x96\xe2\xd1\x8e\xd4R\\.O\xe2\x10U\x12\x8f\xee\xdf\x82J\xa2v\xc2)\xf48\xb5-\x1e>[\x91\xc3\xb6\xe9vH\xbe\xcb\xdcb\xc8{(8J\xcd\xf9Bm\xf7`\xfb\xb2\x88\xd3\xcbx\x9a\xc9\xee\xd5\x8d:i\xf5\xa22o\xac\x9b>\xddD\x89\xa8\x97\xd9H\xc6\x95Q\x14,\xd9\x04\x953F~\x16\xbfV\xdaM(B\x95\xc0N\xbf\xf3O'\xb7\xc74\xea\xba\x0e\x8b\x8aC!_\xfdZL\xd8\xac\x90\x98v\xd54\xcc\xbbi.V\x84B\xc2d\xfa\xc2\xfa\xed\x90\x1az\xed\x1b\xe8U;\x97\x14X\xb5\x06\x1a%\x8e+=\xda6i\xa5\xeb\xeaf&\xe7`\x81\x9b\x80\xb3(\xbb\xef50}57\xbb \x92\xc0\xc5\x98c\xac?\x8c\xa1q-wF\xe3\xca)\xb4z\x98\x8f\xbb\\\x8f5\x89[\xbd\xb3\xfc\xd6:\xeb\xc3\xcdrP\x04\x01\xf4CG\xf3j!\xc5h\xda^\x0b\x01\x1a{\xa5\x15\xa1\xe0B\xa6ND[ \xce8\xfa\xa2\x0c\xe2\xe8\xf8x\xc4r\xf0/\x9aQ\xe6|\xc7\x91\xbf\xe4e\x993\xa7n\x02\xfd\xa1*\x1f\x99:q\xfd\x93\xf38\x11\xd5\x9b\xb1L\x0ez\x86\x8a0\xf87\xc2\x7f\xfb,v\n\x8anHE*\xbf\xdf\xf3\xcb\xcf\xbb|\xccb:\x0e\x8b/cA\xc4R`jgv!\xfel\x9cM\xd0\xd6\xb9\xd4\xdc4vm\xe1\xa7/$\x96(X&\xa8\x06\xd1r\xd0\xa2\xaf\xa7\xa5\x18\x01\xd3\x83\xf49\xc8\xaa\xde\xaeT\xc8\x97Zsf\x01\xd9\xaa\x99a6.\xf7\xb1z\x932Y5$\x7f\x1a\xd5\x97\x82\x1c\xd6\xeaB\x9a\xac\x08\xefF-\x19\x19\xa9VO\xc5N\xc2\x9a\xf2\x97Q7\xe5~b|\x12\x13eM\xfcaV\\\xf1i\xc0\xd3zMLUU\xf1\x17Q7\x0c2\xa3f\x18dE\xbd0\xc8\x8cZ\x1a\x0fP\xab\xab\xe5\xc8\x16\xb4\x14\xa2\x9d\x82S0\xda)r\x8av\x8a\x14\xa3\x9dW\xddS\xdfoT!\xeb\xc2_E\x95j+\xae\xd6\xb1\xd8\xde1\xfd\xcb]\xbe\xaa\xc8\xb7\x031\xdcQ\xf01\xa8\x91Q\xd6g=\xd70 \xad\xfc\x863\xc5\xaby\xd7\xaf\xa6\xb5\x98Z\xcc\x1c\xe5\xbc:\xcaXG&\xaf\x0d\xac\xea\xfa\x89\xfc\x0e-\x1e\x95\x8cw-B<8\xc8(0\xce\xd1;E\xf7\xaa@D\xe8\xd5\xb4\xe7)\x98\xf6\xb0B\xd0^!\xae8\xe3\xafp\xcct\x13UHPM\x94l\xf9M\x1cj\xe9\x02\xda\xdd\xb5=\x19\xa1\xdf3\x108P\x9c\x03\xba\xf6/\xf8\x06\xfa\x1c$'\xeb\xd6\x8dG[E\xfc\x1b\x1bx\xd9\x87D\x93\xab+\x91\xaf\xc7*\xc0\xb2o\x8b\xb2\xe0\xc6\xb4\x1e\xca\xe0\xce\x1dV-2\xae\x16\xaa\xce\xfcm\x0cYM\xa0a\x12\xa5>U]\xc6`K\x81\x12\x88.\xcb\xb8\x10\xc0V\x17\xb2\xe3\xae\x8d*Uk9\xee\x02x\xe2_,\x04\"gg\xb8}\xed\xa1\xd8\xdd\x06\xfdR\x0d\xb2\x12\xf2|\xbd\x01\xa6\x86CqX\x18\x88\xe6\xa6)\x88\xf2\xcf\xa1\x1d)\xb0o\xa2R\x0d&\xee\xedY\xcc\x9e\xe9^`\xd6\x1d*\xc1N7O\xef\x01\xb1XR\x9e\x91\xd7g\xe1\xaeQ-\xea\x9d8\x12\xd1\x91\xa4\xa0t\xe2\xf0\xc1)'.\xd3i\x01R\x07)\x071a\x06/\xfbP'\xe5\x10\x9d\\\xdenC\x15\xa0\xfa\x81%\xf0\x07\xdc9\x93\x01\x8f\xb0\x90\n~$\xca\xe0\xad)\x88\xd1\x0d\xfd\x94\x1f\xc8\xd0\xc1Dv;\x14k\x8d\x89)\x04 J\xdej\x1eb\xb5\xa0\xff\xbd\xff\xbeW\xcd\x97\x87\xa2\xfd\xf2\xd20\xc8e'\xeec\xb6\xb9\x99@D\x9f\xfe>\xeb\xfdw V\x00q4\x89 \xd9\xf77j\xb5\x19\xea\xf7%Ik\xbfB\xd8\x12\x95\xc3\xcb\xf0\xd6`\x82\xf2{A\x02\xb8\x18h\xac\xc2<\xe1@\xb3q\xbf\x9f48\xf61\xd0\xb5\xcb>Q\x8b'\x7f\xcb\x17\x18\x86\x86\n8\xae\x8b\xf8Z\x00mc\x1f ]i\x06*)3=\x82\xd3\xbc\xdd\xc5\x8beA7\x9f\xe6\x99f\xc2JwG=\x01\xd8\x8bZ\xb3}\xeb\"QOPD\xdf\xf2\x8b\x15\x13\x8c}\xb8\xba Fe\xaf%>-J\xda\x06\xc0\x14>>f1{\xc2|\xb6\xc9\x86\x8f\x9b\n3\xd9\xb0t\xa7\x07\"\"\xb9?\x04\xa0\xed\xe4\xe3x\xe2j\x0eW\xad\xdd+Z\x83.\x0e'\xa0C\xe9\xf7ckaS\x05\xa9\x1e\xf9\xad\x96>\xb1\x03\x15\x8eN~N\x81\x8fl\x97\xfe\x9a6*#\x9f\xb8M\x9eV\xd0\xc8jo)\xd0(@ao\x03\x1a\xe5\xcdh\x04\xd2\xc4\x8eh\x94\xba,\xc7\x10\x0e\xfd\xbe%\xf0PK`\x03@\x1ah\xe3\xeaJ\xbe\xec\xb3q\xe3DS+\xb3\x9ao\xcd\x9e\xc8\xab{\xe2;\xf2V\x9c\xc4\xd4M\xe9\xfc\xc3 \xcaI\xcfa\xd2c\x81\xf6h(\x1b@\xd5-i\xe4\x0e\x19\xa2\xa2\xc7\xf2\xf1P&~\xc4\xae\x17}\x1fN\xc6\x01\xe0\xb8\xff\xf8F\xfdv=\xd5\x18N\xe05\xf0WJ8\xc9p\x8b\xe6P\xd7\xf3\x8e!\xdd\xc74`\xb2\xdf\x8c\xc9\xb9\xb4/o\xc6\xf5\\\xe9\xc1\xad\xa5B\xd8\x0e:\xac\x05\xc9l\xf9\x02\xbb\xec\x8bAT\x81X\x80\xe3\xb4\x0b=\x0d4,\xedNO5\xee\xdf\x07t\xc8\xc7\x81FO\x9bIi\x88\x88\xe2\xa3\xa7&\xec\xebp2\x8e\x01\xe9\x82k\x10\xd6[\xe9Yq\x15\xb7\xe8\x8c\xa8\xaf\x0c\xf7c\x0f\x10Z\xe4U\x92\x1e\xb3\x0d(&\x15\xe0w\xee\xb0P\x117\x176\xdcp\xb0\x8aW\x8e\xeb\xe1\xa4\xc8_n\x87\x96\xd7X.\xda}\x80.\xeb\xa4\xab\x03\x16\xc9\xa7\xe8|\x89\xd9\xfc\x0f\xe8_7\xe0\xca\xaa\x9a\xff\xbd-y?\x11\xdd\xd2\x0e\xc0\xa9\x9dt\xec|\x93+\x89k1q\xfa\xb7\xd79\xca\x81\xc2\x9b;?\xff\x00\x84\x92;/\xfd\x97x\x0b\x91;;\xf7\xbf\xcf\xb3N\xc1\xf5o\xec\xdf\x8e\x1c\xac\xca:_\x13\xack\xf2\xc6u\"y\x1bl\xb1F.2\x0f,\xe1,fpU\xe6-.\xb9\xb4h\x1cwZuU&\xab\xcd\x7fh\x8642\xc1\x03W\x84\xbf\xfa}\xee~\x9c\xbdP\x93XA\x10)\xd8\xf87`\xa0x\x86\xaf\x12\xab\xa8\xf2\x9b\xa0\n\xb7Ct\x08~\xe5#\xd0\x9b\xdb<\x05\xd2B\x06\x1a\xd5#++j\xe3\xe3\x08x\x10%\x83\x1b\x1e#\xad\xbe\xaf\n\x89@\xc1:\xa1\xa142\x11\xbc\x95\x89h\xdc\xa6\xb3\xca6\xddr \xeb\xc434\xb2\x96-\xfd(\x97\xb7\xfc\x8c\xf5\x10\xd6\xba\xd2\xad\xc7\xa9\x02\x9c\xd2\x00i\x0b\xaf\xdcD\x8fY\xae\x81\xb3\xe0\xc0\xfd\xb2\xa7\xa9\xe4\xc0s\xc5\x81\x8b\xbcT\xe3\xc0surH;\x9c\x1c\x9aN\x0d\x96\x13\x03\x9c\x16R\xf8\xe8p\x02N>\xfa\xfd\xbc\x0b\xdd\xbc\xce(\\O}\x06\xce\x11\x99\xc7\x02\xb0/\x10hHxN\xee@\x0b;a8\x1es\x91\xcb\xc7\xc1\n\xb2\x14\x82\x18 \x93\xc7\xbbk\xe3<\x9e\xa1B8C\xb5\xb3\xa6)B$W\xc1\xbf\xe5)\x0d\x91\xdf_\x03\xf9eo6\x1a{\xd3rd\xc8\xf4\xcf\xe7&#\x9b\x13,r^e\x91\xd3*\x8b\x9c\x16,r^\xfe\"Xd\xb3ekO%G,f\xaa#xn\xb0e\xd9 9\xbb\xe6\xf2\xf2t\"nv\xf5\x07\xf4\xaf[\xda\x03m\xbe\xc1\xe9\xcb3;C\xfa\x82\x9b\xe9K\\\x1aY\x1a\x17_R\xdb\xcd\xb7j\xb1\xf5\\\x84[6m\x88\x16!\xe3\x18\xb4\xdcx\x97B\xd3\xb9\xc7V\x1e\xd8WN\xa5\x81\xa21\x1f\x8b\xa6\xcc3\xd0n(\xc7sf\xfe\x12\xf2\x95\x13\xc6*F\x97\xf5\xc0$\xbc\x99\x97S\x9cF\xe9_\x98\xc4\xad\x04|C\xa9\xa8\x0ep\xaf\xd4*\xa9\xa7\x9d\xad0\xe5\xb1/A3\xbb\xb4`\x9f\xb7<\xb69\x14[\xc3\x99\xbc}2/\x9c\"\xac\xc4\x9b\xa9s\xead\xb1\x1c8\x1a\x00\xd9Y\x83\xe1\xf2\x87\x1a\xf8\xe2H\xb9\xe9m\x87]\xe3\xf5v\xf2\x02%+\xcc\xdd4\x17\x05$\xcct\xc3\xbd}6\x9e\x81\xcb\x8aH\x19\xf1!u\x8f\\\xd4\xc1\x01h \xeeM= nH`\x91\x89tb%}L@\xa8|e\x93\xdfbD\xa3\x1e\xe0?\xect\x94\xf2\x15\xbb\x901\x0d`\xbf^\xa0\xf7\x8d\xd2%2\xac-\xf4\x07\x1b\xe0~%\xbd\x19'\x10M!\x8e2~\x91A,\xa6\xe44u\x0b\xfb\xcd\x04\xe3G\xc4\x88)A\x89BbNlq\xa2[I#\x86\xfb\x96k\xab\xcd\x0d\xc7\x19^\x8c\x94F\xe1\xd6E\x11\x89\xa1\xf3jd-\xe9\xffC5\xcf\xb8\x1da\x14\xff\x8c,\x05\x1f\x043\xbb\xe4O\xfa\xc2d\x8d\xf1\xfc\x01\x03q\xbb\x13\xadaOf\xe3\xb4t\xdb\x8b?\xe2R'ct>\x03W\x9a\xa9t\x80\xc8\x0e\x98\xd2\xec:\xe0P\xdcY\xa0\xe0\xdc\xde \x86\xf6lbnG\xb8\xe2\x1b\x8bbh\xe7\x06Q_\x89Ri\x89R\xa9G\xaf\xaeXF6\x88\x8b;\xc9nCI\x14\xc3\xd5/\xc7C\xf5n\xd7\x90\xf5Gk\x8c\xb7\xdc\xb4gr\\\xe8)\xdc\xc2\xb5\xa1\x087wBy\x9b\xd9\xf4\xfeB\x1d\xb6q+\xa6\xa8\x00\x97\xbc\xb4\x94\xb3\xca\xae.U\xb3\x1c\xe2\x03NOp\xc9E\xb8\x00}\xcd\x05\xf9\xb2\xc5\xfd\xcc\x07OR\xd9\xb4\x03\x95\x85\x95#I\xe1\x1adr0=\xa9Q\xca\xc1\xf4\xc4-\x0d\xa0\xc5\xcf\x02\xd7\xf1G4\x08\xc4\x96)\x9d\xef\x001e\xa3\x12\xa9\x89\xeb\xe38\x8a\xc2\x9bu\xfbvA\xb0\xeb\x14\xb1\x9c\x01\xb1\xbc\xba\x02BY\xec\x9c\x0b\xdd\xabv\x95\x84b\xa2FEU$\x19 \x98 n\xb1\xf5^\xb9\xbcn\xa7r\xa2\x0bD\xff5>\xa6\xe8\x0f4\xaa\xba\x13\x0b\x8cl_\x1d\x92\xce\xc8\x9e\xf3\xa2\xe7&\xea\x1ac)~\xde\n3k2\xad\xc8\xcc\xee\x191\x18\x03\x99^\xbf\xc4\xed\xcb\xf4\xba7]\x15K\x8c\x0epc2\xb9\x1dn\x0c\xc5N/[p\xf0\xd8/\xfe\x8fd$d\xb8X\x1fG\\\xfd/\xd2\xdd:[\xabB\x19val\xb5\x0b7\xc6\xac\xc4M\x99s\xea\xa6\x11S\xa62[\xca\xec_]\x0e\xac\x96)\x14T\x1c\xfc\xa3\n\xf2\xb3\x01\x91\x96\xe8k!w{\xac\x0f\xde\x1eX\x9f\xf5\xee*3\xcf3?\x0cfL\x0dv\x19\xcf\xb8q\xf1\x8d\"I \xee\xeb\xb65\x11Z\x02\xf4\xc2\xb0r\xc7/ES1:X\xf5\xa5\xc9\x14\xb1Q%\xf4\xe14\xc2\x8aC\x8f\xcde\x13f\x19\xd1\x95i\xabS&\xbd4`\xee\x98\xb2\xb7Q\x8f\x18BH\x04\x9c\xfb\x12yj\xce\xb8\xf8=b\x9f\xf1\x8cO3>cy\x14'3\x9e\xf0\x19\x13\x88x%\xb0\x8e\xdd)\"sC\xf8\x9e\\t\xcec\xe7\x8b`\xba`A\xc4\x002K\xff=O\x19F\x1fc3hMpC\xf1\x9c\xa5\xf9t\xca\xd3\xf4\xde\xdc\x0f\xc2<\xe1,X\xae\xe24\x0dNB\xce\x9c\xf3\x05\x8fD\x13wu\xec\xbe\x0b\x13\xeb\x1eE\xcf\xe3(\x0df\x80N\x04m3*?\x1c7\x1f\x1b\xc6 \x15\xbd\xc8\x02\x89\xb5N\x0e\x84'T\x9dc\xac\xf0\x96:\xbbh9S$k\x9d)H\x13\x97\x8fz\x8a\xa8\x8b\xa6\xa5\x90\xe0#\xe9\x89\x9b\x14\xb7JOY\x06\x90k\x06[\x86\xe7\xe3\xfa\xc5\xfc\xea\xe5\xf3\x9b\x03\x88p}\xa5NYm\x91\x96\xad\x86*\xe8\xf9\xfdV\xe7Q\x9c\xca\xd6\xbf\xbd\xd1\xe8\xa2\x1f\xaf\xe28\xe5\x15\x19p\xe8\xa6]\xfc\xd3\xa2\x895H\xad\xcd\x89\xa3\x0eC\xaf\xfd4\xe5\xb3B\x10\xa3\x05\x84\xc6K4\xc1\x9c\xcf\xea\xf1\x8cn\x17~{\x86JG\xcc\xf3\xbd\xf1Qt\x94\x1c\xe5\xdb[\xdb\x0f\xe1\xef\xa3\xc9\xbd\xd3u\xc1\xac\xd0_\xcc:\x89\xfb\x85\xc2\xe2)\x1bnm1\xe5\x80.\x93\x0eX\xb7<\xf6\xe8\x11\x1c\x13\xff\xdb\xef\xfc^O\xde\xff\xcf\xd4=iAq\x9b\x97\x8a\xfc\xcao\xbc}\xf5r\xa0\xc0y\xe9pW6?\x04\xc5Fm\x19\xdd.p\xff_\x83\x9cJ\xcf1~\x19G\x9b\xd3\x98'S<\xc6e\xb1DD\x17o\xf2N>\xea\x85\x8d\xdb\x88\x11o\xd3&\x96\xdf\x0b\x06\xb3 ]\xc5\xa6L\x85p\xa9)\xfaV\xb3\x81\x08 6\xa5\xa2\x9dg\xa7]W\xe0\xcc\x03\xa7B\x1e\xab\xf93\x05\x89#\xf8\xe4AY\x0b\xdbg+\xc5\x96.@\x89P,\xd0\xd4\xb2@\xd3\xe2\xc7\x01\xeb\xe1za#\x06\xbea\ny#\xeb\x8b\xcf\x17\x1d%\xf1u\x86\x0e\xd6R\x9e\xbd\x0b\x96<\xce\xb3\xf6sO!\x00\x8aH\xe1\n\xb7\xe9\xbb\xc4\xa7\x06y\x94\xf0\xb9\x18@\xf9\xcb\x81\x88\xa7\xe0UNt\xe6\xce\x1d\xd6\x8b\xf8E\xf6.\x98\xbe\xef\x81u\x90J\x86\x05\xa4\xba)\x12E\xc5\xf5\xfb/\x8f,\xcb\xbasa\xd9\xff3[\xff\x97\x95\xfe/\xb5\xfe\xb7hpj\xf3@.\xfb\xca\xd8f\x18\xef\xbf\xd0\x98\x8a\xb3\x15B\xc8\x80\x0c\xa7 \xa3\xd7^\x92A\x15\x05.\xf1\xcf\xb9\xd8XE\xb3g\x18\x1ct\x7f\x7f_\xcf\xb9\xba\x92Q\xdb\xcb4\xb1m\x0fvvv\xd8\x88M\x9d\xb9\x83\xa6\xe8z>\x1aGmI\xcc^\xb2}\xf6\xf3\x0f\xd2\xaf\xd6\x90m\xb23\x97}\x82\xd2M%\xaa\xa8\x03\x07t\xde9\x05\"\x18\xec\xd5\x15\x83\x01\xb2}\x0dK<\x16\xb4O\xbbE\xda!\x1e\x0d\xaa\xfb\x1aT\x1d\x0d\x84\x9e\xae\xb0\xabl\xa1h\xbb\xe6\xc4\xae\x8b\nA\x08\xe8W\xb1\xb3\x91\xc6\x03\xd2b\xae\xb2\x8c}'@Hu\x12O\x84\x1e\x0b5 \x05\xfc\xa4$\x9c\xa6\xdf\xa7\xea\x1eT\x839\xbd\x0d\xcd\xdaP\x96\xd5\xd1\x96\xdc\x8b\xd0\\I \x01bp\xec,\xbb4\\Ctn`\xb9\xe5c\x88q\xc6\xf8\x8b\xdf\xb7\xb2\x05\x1a\xbe\x98\xd5\x11\xf3\xd1\xda\\\xb3\xe0\xca\xa4\x01\x87\xd8\x0e\x9e\xb2\xb8\xc9\xb7\x08\xbf\x98r>K\xd9\xd2\xbf\x08\x96\xf9\x92\x15z\x8b\x0c\xa1\xf2}9\x1b\xd9\x1e\xde\xdf\xbb\xffpg\xf7\xfe\xde\xf5\xdbk\x07\xe76\xad\x17\xdd\xd5\xafx\x04bG\xee\xb8\x1d\xcb8R\xc4^\x9c\x14{q.\xdd\xc0Kk\xf258\xe5\xe6\x8d\xd8G\x13\x9bf\xc4\xd7\xdd\xfb\x02\x8b0X\x04\x99\xeaZ\xbb\xc1\xc0i\xf9)b\x0b\x12\xa3W^\x11\x0cr\x00\x99\xd2\x1d\xc2m K\xcb\xe46(\x9f\x83\xf6xW\xeb\xae\xb1\xb32\x044q\xf3\x01\xc2F\x9a\xc9y)\xff23\xd3\xa6\xcc\x10\xda*R\x1f\xed\x15\xa9\xc3\xedm\xb8\x0f\np\x02\x18 \n\x8e]\xae&\x02\xdcz\xff\xf7\x1f\xfc~\xafq\x1d\x9av\xef\x84\x1d\x85\x8e\xb1 \x82\xc178j{\x15D\x96a>\xabK\xb5\xea\xbe;\xd1\x05\x87\x1f\xdc\xe2\xc2N\xe4\xec\x0co\xe2\xdb\x93\xf4]/\x1a\xee\x1d\x1f\xf3\xf4\xcbx\x96\x87\xbcW\xa7\xda2T\x90\x1eJ\xc1EY\x0f\xc4\xd3k\xb2UQF\x00\x89*\xec\xb1X\xbd\x96\x1b\xd0\x07\x93\xdd\x08\x1cq\xb8}Pw\xf3\x1b\xcb\xac\xfb\xdb\x10\x95\xb3\xc8S\x1d\xc0\x90cd\x1f8\x12\x99r\x9c\xd2\xef+\xb5Ca\x9c\xc0\xba\x9f\xbe\xf5\x88\xe9/\xc7\x04\xa8}\x87&\x8b\xd3x\xb9\x8a#A\x0e)8\xa8\xe7\xd9j5b\x97\xc5\x0cZ\xcb\xf9y\xb6\x88\x93\xe0\x1b_\xf4\xe4u\xbc\xcaW#v\xd2\xbd\x1a\xff4\x8bF\xecx\x8d\n\xafV<\x81\x8fA\xcd\xf3n5\xd3\x11;l/\xf9,\xcf\x16/2\xbe\x1c\xb1\x8b\xf6\xc2\xa2\xd9C4{{\xdb^:\x16\xc5\xb7G\xecY{Q\x7f\x15\xfc&\xbf\x14}\x19\xb1\xe7\xed\xc5O\xfc4\x98b\xe9\xf7\xed\xa5\xe5\x91\xe4U{\xc908\xe3ox\xba\x8a\xa3\x94\x8f\xd8\xeb\xf6\nA4\x8fG\xec\x8f\xb4\x17|\x11\xcd\xe3\xe7\x18\xd8\x9d'#\xc6y{\x95\xdf\xc8\x97\xabw\xf1k_\x8c2\xebP>\x8e\xc2 \xe2?\xf2\xc3`\xe6gq\xf2\xa9?;\xe5#\xf6\xaeCE\x85]\xe9\x88}\xb9F\xf1\x11\xfbi{\xe9\x02u\xdf\xe6\xcb\xa5\x9f\\\x8e\xd8\xcb\xf5+} A1G\xec\xcd\xfaU\x11~\x9f\xb5W\\\x04\xa7\x8b08]d\x82\xe1\x18\xb1\x9f\xb5\xd7H$\xa6\xa4#\xf6y\xf7\xd2#\xf6M\xf7\xc2\x9f\xc6\xb3\xcb\x11\xfb\xb4\xbd\xc2\xcaO\xfc%\xcfx\x92\x8e\xd8\x8f\xd6(\xfe&>\x1f\xb1\xdfh\xaf\xc0/\xf84\xcf\xf8\x88\xfdV{\xd9\x05\xf7g\xd0\x91\xdfl/\x0bF\xb4\xe9\x88\xfdZ{Q\xb8\xc5\x17e\x82y\x1d\xb1\x1f\xb6\x97\x8f\xcfxr\x16\xf0\xf3\x11\xfb\xed\xf6\xc2\xf38\xce\xc4\xc2\x8c:,\xb4\xcf\x830\xe3\x89\xb6\x9a\x93\x0e\x95^\x0b\x88\xe3t\xc6\x1d\x8aO\xf3$\x1c\xb1\xa0C\xc9t\xba\xe0K\x81\x83~\x87\xc2o\xb1\xb0\xd6\xf7\xbcC\xade<\xe3\xe1\xe1\x85\xbf\\\x85|\xc4\xc2\x0e5\xbe\x145~\x9c\xf8\xab\x95\xf8\xc6\xb4k\x8d\xe7q\x18\xfa+\xb1F\xd2\xaeUFl\xde\xb5h:b\xab\x0ee\x0f\xa3|)\x9b\x9eu(\x8e\x8c\x8e\xac\xb0\xe8P\x01\xcc6e\xf9\xb3\x0e\xe5\x0bg\xf7\xb2\xce\xb2S\x1dd\xb8F\xec\xb4C\xe9w\xc9\xe5\x8b\xecU\x9e}\x9ag\x99 \xeb\x97\x1d\xea|\xe9'\xefg\xf1y4b\x17\x1dJ\x7f\xea\xa7\xfc\x0b\xff2\xce\xb3\x11{\xdb\xa1\xfc\x8fx\x92\n\xde*\xf1O\x97>\xae\xb7\x11;\xe9^\xf1m\xe6/W#v\xdc\xa1F\xb1a\x1c^d#\xf6\xc5z\x15\x80|~\xd5^\xe7\xb5\xa2\xb7\xf0\x91__\xa3\xc2\x8bh\x1a\xe63~\xb8\\\x89\xd9\xfcq{\xcd\xa2{\x10i\xe4\xc5\x1a\x154\xaap\xda^\xed3\xceW_\x04\xd1\xfb\x11;\xef\x00e\xc1\xff|%H\xda\x1f\x1d\xc8\xd7\xe6\xb2\x02ap\xeb\xc6\n\xeaw\x03i;;}\x96\xa6\\p\xf8\x87E\x87\xc8\xd2\x9d\xe4\xd8\xb4\x9frV;K<\xef\xa4F\x88:\xb5\xf5\x9eh\x8b\xd4\x1c\x8dg\x05\xbc\xd9\xbc|M\xcbW\xbf|\x0d\xcaW\xeal\x8az@\xf9\x8a\x87\xbb\xb0L\x88<6-\x7f\xad\xca\xd7E\xf9zV\xbe.\xd5k\xe3\x89\xf7\x15\x87\xe0\x03\x8f\xa8#/\xe6m\xef\x1a\x11\x8e\x8a\xbc\x9d\xedz\x9e_\xe4\xdd\xdf3\xa2\xe5\x14y\x0f\xef\x1b\xf1\x80\xca<\xe3\xf8\x1d\x96yF_\xa6E\xde\xa3\x9dz\xde\xbc\xcc3\xfa\xb2*\xf3\x1e\xd6\xf3fe\x9e\x01\x97\x85\xca\xbb\xbfe|\xef\xac\xcc3\xda\\\x16y\xc3\xadz\xde\xa9\xca{\xb4c\x8c\xef\xb2\xcc3\xc6pR\xe6\x19\xdf;.\xf3\x8c1\x9c\x17y\xf7\x8d\xbe\x1c\x96y\xc3z\xdeE\x99g\xcc\xfb\xdb2\xcf\x80\xcb\xf32\xcf\x98\xf7\xf7e\x9e1\xef\xcf\xca<\x03.\xaf\xca\xdaq\x07\xdc\xebv\x11G\xab6\xcd5\xd9\x1amW\xc7\xceQzs\xa8\xc5\xe8=}\x10\xa0\xad\x1a\x04D\x10\xa0\xadj3b\x1a5w\xc9\x807\xbfU5\xb2\xf5x\xfd]ugDN48\x81\x1eD\x837\xf0\x03tX7#\xd7\x12\x8e\xa3\x00X)\x8d\xb3\xdb\x87.>\xaa\xdd\x02\xb2\xaaM\xf1\xc1\xaf\xf3\x14Y\x11\x8f\x84)\xc3\xf6\xd4j\x82\x10\xaf\xb4F\xf5\x98\x06z\xc2\xff\x8c\xf9H\xf5-\\j6\xaf\xbe&\x13\xc9\xd0\x19\x14&\xc5\x1b\xd3\xd1\x0c\xc6\xc2\x82D\xff\xda\xaalar\xad\xaf\xb54\xe7\x05ab\x9b\xe7\xac5\xd6\x1a\xec\xe4Y\xe5\xae\x1d\xb1s\xdd\xc7\x01n\x96\x06\xb8\xa9\x0c\x106]\xb7_$\xa9\x86;\xb8\xbfg0\x14.\xe7\xac\xa9\xcc\xb93D|\xc1\x83\x0c\x83\x9b\xd1\x1b\x98\xa3!G\xe2\xac\xf3\x00x\xcf!\x85\x97\xb0|\x0e\xcb^\xcf\x05\x8c\xea\xbe\xec\xc3\n&p\xed\xac\xa7\xcbY\x1f\x96\x8c\x8c\xb0\xaf\x86\x10+\xe6^\x99\xf4-\x0e\xc6\xb5p\xf7\xc7A<\x87\x0e:f,\x06!\xbdM\x1d\xd7E\x0f\n\xcd\x10\x88\xb3@\x17\xadi4\xc0\xab\xe8>\xb0\x01q\x8b)Q\xa4\x19\x944b\x924}\x9f5W\xc9%\xa6\xe0\xfd7!\x1b\xd5\x8d\xcd\xc9\xc6\xb3\x9d/<\xc10{6;\xc9\xe3\xc1B\xd4\x89\x9c!\xab\xc8\xa6NyT\xeb\x07\x12\xef\xd0\x19\xed\xed!)\x15\x14\xf5\xd9\xa6 \xac[\xe2\xef\x9e\xf8\xfbTKh?p\xf3\xc46]Y\xc0\x95\x87\xcd\xec\xcb0\xbf\xb5\x88i\xbc\xcb\x9a\x83A\xa0'\xd0\x92$VI\xe8BO\xb8\xd7\x82u\xa9\x14\xcf\xf9zU\x87r)\x1a\xa9\x96_\xf3N\xb7\xab\xe5+A\xe7\xab\xe5KQ\xbe\xe3\x0e\x12ZQ\xcb\xde Z\xbf\xe3:U^_\xf4^\x9d\xda\xb9h\xad*Y\xde\x88\xf2*;u\x88\xb1ws+\xb3\xf2\xc3[\x1eI;\x8e<\x9aT\x82q\x9e\xe0#\xb1\xee\xe5G\xaf\x18\x05\x17/!\x01\xf7\x9c\xdb*w_1\x0f\xa9(b\x0f`\x1fw\xc9\xc5`Q~p\xcc\xd8\x97\x8e\xdd\x04T\xef\xcf\x0e\x8a\xdd\xc9\xc9\x00\xa3\x8f]S\xa7\x8aG\xea\x87QC\xa7\x9cZ\x17\xed\xa6\xa6\xa13z\xe6*\xb9\xcbg\xad\xac\xfd\xe4\x87:W}\xb82\x1b\xc3\x1b\xa2\xe1\x08\xc2\xe5\xbcb\xf4]{>\x8a\xb5\xf8H\xff\xe0\x11\xd3\x0e\xafi\xc8M\xdb(w;\xbbr\xd5\x94\xa7\x9a\xa0\xf7\xe6 \xc8\x9f\xab\xe8\xf7\xa1q\xce\xd7\xf5\x8c\xa5P\xcc\xa3\xe3t\xd6\x0e\x8fi\xa9\x8b\xea\x84G\x11\x1f\xb6p\xa2)\x0f\xa7<\x98\xd3\xa6`\x85 M\xf0\xe9\xe0\\\xebM\x0bH\x83\xcfCt\xa7\xd4/\xc0\xb5\x08xH\x07\xe7\x9e\xbe\xc6]\xb3\xc5-\xa8\xd2#O\x18z~\xcd\xcd.\xd1\xd0\x91\x0e\xce\x93RZ\x8c\xbcE\xa37\xb9\xfc\x08c\xd8\x82|F\x18\x817\xba\xc2\x98\xa5\x0b\xe2[nq\xe4'\x11\xf1.ps4W\x0fDu\x86p\xcd\xb5=\xac=\x8fV\xc4oH\xede\xde\xc1\xea'c\xf2\x0c\x1at:\x9b\x02v\xe8\x14\xfb\x07\xda\xb5\xe2\xaf}tj\x15\x0e\xb2\xac>\x97\x83\xc6\xe0\xa0\xb9\xbd7\xa0aJcG\xf0\x1f\x19\xba\xbap\xdfPo@o\xfd\xd4\x11\xeed\x9d\xa1\xcb\xeb\xb0\xdd\xa6\xd8\xe2\x07\xce\xa1\xd3\x15\xfbn\xc3\xbb$~\x08\xde\x9d\x17\xd0.\x0fI\xcd\xd6\xf1\x83\x13rk\xd8<1N\"\x9cA\x13\x87\x9f\xd8\x81\x13\x9b\xa9\x01T\xf7e#Xp\xfc\x1d\"\xe6'&\x11\xe8\xdc.\xd5\x8f\xde\x95\x07\x9f\xd4\xf8\x8d\xc8\xb7\x08\xaf\xec\x89 O\xec\xa08uR\x94D\xad#\xff\xd8n\xe4\xfch\xd2\x0f\x9e{\x15\x0e\xce\x8d\x01=\xc3bR(`\x8b9\x19\x8e_\xfb\xb1\x8b:q\x19\x98\x99o\xac\xe2\xf0\x03\x8f\x84\x8f1\x8c\x98`\x1e\xe6\xe0\xa7 \x0d\x16\xb60\xba\x08\xe7\x0f\xe8&=i\xcb<\x81\"Z7\x9f\x85\xe77c\x08\x9b9\x93\xf3\xf9X\xcd\xf1\xaf\xfb\x18\xb8r\xf9i\xc7\xb1\xa4\xf9E@\xe0|\x14\x01\x9e\xd9\xf7#\xf1\xfd[\xb2\x01Gy\xbe\x8c/?\xf9]v\xc6\xe4\xe8\x1fr\xf4\x1f1\xfc\x0e\xfb\xd01\x8d\xb7\xdd8\xc5\xf8\xec\x13i\xb1~\x0dk\xf7\xd98\x7f\x8deQy\xbb*\xfe\x11\xb8\xd7O\xac\x1b\xf6RD.>\xe9\x83\xdc\x14\xdd>t\xcf/\xbbn\x1f\xe6\xdc\xd5Jx\xcc\\\xfaU\x17;=\xfaP\x07\xd1\x84\xb7\x9bc\x8a\xfcY!.V\xa0\x1f\x15=\xd7\xe0\xa1\xa8\xbb\xfa\xfc\x107O\x925Ppv\xfc\x97z\xf2\xf2\x92\x84\x8b/\xfc\xc7\\\xf2~\xf8\xeb\xbaV\xf9R\xad\xcc\x19\xc5b@nq\xa5&\xd4\x1d\xbb\xaes\xa2\xc4\x8c\xaa\x8d\x8f\x86\xe3fQP\x8ar\x07\xceJ\xae\x9ak\xd3\x15FWe\x9dtGI\xce\xca\xcey\xb67\x98\x80e\xd4\\\xe3\xd9\xc9jq\xe9\x07\xd9\x18v\x16\x8b\x9f\xe3\nL\xbc\"\x97\x8f\x841k\x80\x7f\xad>K\xd8\xb3S1\x8f\xceH\x0dTS^\xe7\xf2>Bti\xd2\xdc\xcb\xebH\xd6\x11\xaa\x10\xe48\xcd8$\x82\xe8\x18\x89\xb9\xd4\xc1\x84\xf4\xa6\xea\xb8\x89\xdd\x14\xe9\x07\xa8\x98\xa18Q0\x04\xecG\xbc\xaf\x1a\xb9\xf9#\xc6\xa4\xe0\x93#\xf1D\xc5\xe6\x8b\xc1\x82\xad\xb2\x15\xa5\x8b\x08\x0f\xfb\xfb\x80>r\xfc+a\x1c4\xbd\xe1\xbe[c\x0c-R\x9a\xe4\xc2Y\x0c~\x82\x1e,\x06\xbf\xe1\xffx\xbfr\\E\xc8\x0f\x92):)\xbd\x1c:\xcf\xf6\\G%\x15B\xbb\xba\xeb:j\x11\xa9*Xy\xbf'\xa5\x1e\x15rS\x9d\x1a\x83N\xd3\x1aK\xfe\xe8@G\x98@\xd1<1\xf4\x14\x10w\x1d\x1e\x8aD\x8bg50\x15\xc3u2\x06\xe0\xce\xb1k\x1d5.w\xd3\xb0\xc5\xa8n\x9cL\xee\x8d|\xd9Nro_+\x9aV \xe9\x1c\xb3\x86\x1ao\xc8N\x06x\x84\xbb\x03\xdc@\xce\x95\x8a\x15\xb6i\x91 h\x9a\x92\xca\xa9\xea\x0f=N\xb4R\x83\xd2\x92\xbb\xf2Z\xb57\x91\xa8b\xd6\xd8\xf8\xed\x05UIFm\xb9 A4iI\x90\x0f2\x96\x8b\x99\xc5\xbaf\xa4\x9c\x9d\"\xed\xd5\xac\x18|\x01\xf6\xc1\xef\xf5\x9a\x19\xc0\xc4\x90\xb6C\xfd\x88\xec\xc9\x9c\x02\xb2\xbd\xd9\xeb\xf5\x0be\x19\xc3\x88\x96\xa9\x0e\xd4O\x82\x9cE\x92'q\xc8D\x12\x89\x8d\x0d\x94/b'lb\n\x8d23\x084W\x9a\xd2\xd6\xd3eG\x90.\xc6\x03\x1e}\xc2\xf1\x07\xd7m\xcf\x95\x98x\x8d{\xf7[!\xba\x19\x8b\xa3\x07`\xf1\xc3q\xab\xbe\xea\xc5\xb6\x03\x8b2O#\xdd\x82}\x05\xa2\x81\x08\xc0\x1b\xd9V@!A\xf8\xf5KmMtgu\\\xdcuc\x94\xc1\xf2P\x93\x1b\x1f\xb9\xce4\x8f\\P\x87\x9cG\x12\n\xc3\xb1~%e\xb8\xa1 P\x8c%L\x85\x9aT\x03\x12lg\xd4\xa2\x9dt:\x9c\xa9m\xf5!\xd5gd\xc7\x167[\xb6\xc8Z\x19i\xda\x15\xe5\x86\xd6\xb7\x1e\xd4:\xfb\x7f\xd3\xd8\x87xj\xe8i\xfb\x0bzb\xffo5\xf4'\xea\x180N\xe9B\xc4=\xc66\x94SQ\x8b\x91f\xbb\xb1\xea\x8d\\d\xb9\x1d\xc5\x14\x84\x83\xf7Y\x8a.1\xc7\x17 \x8d\xaf)\x06v\x88\x07\xbf\xd1\x8b_\xfc\xb4\xfa\xac\xfc>O#\xad\xbd\xde\xcc\xf0\x91\xf6z3\xa9^o\x86\xce\xb3-\xd7!M\xd7\xf9ZNX\x1ay\xb5\xca+\x19\xf7ui\x13\xf0> \xa5\x00\x94\xde\x88\x90*\xa4\x06\x16o\x00\x9e\x035&\x98\xe6J\xeeE\xd8G\xbe\x9c\xa2\xdd\xc5\x97(\x88\"M\xd2\x0cPEScl4\xc8\xa3\xd5cl\x1c$\x04\xa9\")\xb6\x8d>V/)\xb5\"\x00\xc2\xaf|\xca\xf8\\\x9e\xaf\xbf\x00'qy\"D\xdb\x9a\x90\x81\x0cv\xe9\x04\xd6\x06\xf3D\x1e\x1d\x9fcgH\xae\xfd%I\xa5n<\xff9HR\x12\xceI\x10\x85\x1a\xad\x05\xc6\x7fC\x83\x1ey\xda\x98\x00z-\xf2\x7f\xe5\x15\x1d\x83\x1a\xaeq\x8a\xf2\xe3\x89\xc8\xa5\xadu)|\xce\xad\xda\x8frU\x95.M\xb5\x06\x92\xfa\xdd\xb1\xe0\\\x94\xb6\x8b5\xec\xc3<\xf2x\x94\x1c\x1e\xff\xeb\x94\xde\xa6G\xd1\x9c:]\x9d\x8e\x92\x8b~\x81;\x888\xe5p\xd6\xba\xb0Q\xec\xe3]\x92\x98x)\x8d_\x93\x94\x8c\xaby2@J|m\x00\xb1\x1e\xccI\x8a\xb7\xbel*\x8b\x06\xfc\xd6\x12\xe1\xbc\x0f\xedf\xbb\x16A\x08\xf5\xdd/\xc21\xc4\x06~\x0cS\xb2\xf2\x9d\xd4\xb4D\x80\xfb\x8e\xc7\xb2b\xef\xc1>\x86\xcf\xa5<\xfe\x0c\xcf\x0e\x1a\xa2\x9e\x1c\x1f\x19\xe6\xd4\xea\xdch2\xbd2\x9c&5\x93J_o\xa8\xc5\xc5\xef\x9a!\x8fLA\xae\xda\x804\xd0\xfe\xdaN\x95,\xb0>\xc1,\x8f\xa8\x15\xf1\x88Zq-D!W\x07\xe1ej\xcaD\x06\x8cf\xbapR\x0c\x93\xaaa\xc0\xa2p\xe1/\xb3\x98\\p#\xdb\xfa\x12/i\xda\"\x0c\xa0\xa2\x0djB\xcd\x07\x9e\xff\x8d\xeb\xa87\xa13\xaccm\xd5\x89\xc1\xf2*\xcbm\xa2\x8aNc'\x1e|\x80\x1e\xc4\x83\x8f\x16i^\xa4\xf7j+\xe8\x10\xa1\x9e\x8b$G\xc1\xf6\x82/\x7f\x18\xa4\x9c\xd0\x84\x1e\x9a\xa0c5E]\x08\x93blF\x93\x17\xf1\x1aOH\xe0\xb8U\x11\xd6v H\xe5\xa8\xb6\x82\xee\x1a\x8f1\x99}\xf8\xee\xe3\x12\x91\xd3\x1e4,\xb3\x96\xe8;\"o\xddt\xcf\xcfM\xf7\xca\xe8xbA\xc44n\x8d\x84\x11#\x11\x987\xda\x88n\xbe\xd6\x92A*\x00\xc3\x01E\x93\"\xa1u\x1d\x17r\xb0\xeb\x84(\x9f6k\x04\xdb\x00T\x82\xce\xba\xde&b\xf4\xd9A\xa32\x99_\xc2\xe9*\x15\xbb5+J\x0c\x01?\x88\xe9\x92\x864f\x0c\xd8\xc7,L\xfd\x15\n\xdd\xc2\xa9gIS\xc5\x95\xe7\x88\xach\xe2\xc4\xee\xc0\x0f\xe7\xf4\xf6x\xc1\xda\xaf\xbe\xdcu\xe1eM\xe3\xe5\x83\x08c\xa7\xeb\xae\x809&{\xd1\x0d\xa8\xe0c\xcb\xd6\xb7{\xec\xd4\xc2\xb4\xec\xfa\xb7\x94\xc8\xf9\xc8;\xd5yx\x11}S\xf7~\xb1p\xc6\xeb%\xeb`\x8b\xf7\xb5\xeb\xae\xb6\xa5\x18u\xd6\xeel\xf4;\x0c\n\xa37tU\xaf\xf8`\xd5\xb1\x9c/v\xd95\xab^\xcb7\x91\xdd\x93\xbb\xd5E\x14\xc0D~\x19\xd7\xccVA\x9c5\xfe\xc0O9@\xd0\xbe\xf1?\xffS\xfe\xec\xd6\xeb\xa3\x8e\x92\x87}}[~\xa9T\xa6y3\xc17e\xb0\xc3S\xb2\x14\xef)%\x9a\xb7\xf0\x92*BX\x95\xce\x94zMOX\xf7\x99\x91\x15\x04\xc2z.\x04\xc8\xf0\xa9\xa8\xe9\xb9\xad8w\xc7\xd4\x0d\xecC\x80\xb9\xa6d\x93\x0c\xde\xee\xe0&&\x8c\x99?\xaf\x93))\x03t\x93,Y\xd3pN\xe7')\x89S\x0d\x0c@H\x04E\xcd\xbf\xfa4\x98\x1bj\xa2C\n\x8f\xa9\xe4\x87:\x90\x820\x06\xefz\xd1j\xcd\xf6\x92\xa9\xa5k\x9ePA\xfbl\xa5qC\xc4\xf2)\x995\xd1Bhb\xce\xf4\xc0Z\x16\xbbfI\xd3\x0fr\xe3\x1c/\xf4#\xbc\x83}X\xb2e^:K\xe7\xbd3\x9d\xb9\xbaKS\xf48\xb9C\xb3(\x14n\x85pw\x87I\xb3ej\x91;\xcd\x8blD\x17h\x9c\xad\xde\xf9\x1e\x96~\x95\x028;+M+\xb7\xa5\xfa\x17\x15\xeb\xed\x93>\x9cT\x8an\xfbp2M\x18\x88o1MW@\x90\xc6\xb3\xe5\xfcIb\xa4(\xbf\xf8\xa5\xcf\xd7mp6\xc3\x83\xd2\x19\xb2\x0fW8m\x8c'\xaeu+\xb5!j$n\xe8\xaf\x9cs\xf5\x0d{dh\xed\xde`\xa7\xf9\x04\"t\xca\xe2\x1e]\x0f\xb9'\xcbU\xcb\"\x9f\x0e\xe5\x8e]Jk\xfa%\xd0\"\xf7+\xc4\x8f\x8b*vuY\xd97 \xb2}\xb8\xc8O\xe3\x074\xd6\x9d\xf2\xd3\x18\xf2\x01Ur\x1e\x82\\\xe0+z\xd7\x9c\x8a\x04\x14R35\xa46\xa8\xf9\xaf\xa7\xd2\xa8\xc4\xba\xbe\xec\x94\xbe\xa6qB\xab\\\xb4\xfa\x91\xa3\x83f;>\x91\xd9@\xde\x1d\x19\x15\xd4\xeaG\xca\x06\xe9`\x1d\xadMZM\xf5\x83\x0c\xb5\x98fn\xd0\xc3\x91\x08\xd3h\x84\x1c\xb5\xb8\x91\x92^l\x94\x1f\xb3\xa5\x1c(\x02q\xde\xde\xd0\xd6\x9e\x96Hx|`l\x91\xdf\xf7\xe1\xb4D\xe8\xf4\xa0Q\x0e\x8c1\x9c\xeaW%\xa6 m\xb4\x02\x91\x1f\xccz\xc1\xedp\xe8\xb5b\x9a%\x14y\xf2gBCy\x81;8\x17?B\xf1L\x81'\xffM\x03\xba$\x18\xa5\x84'\x92\xc4\xd2\x15\x86 \x95\xd9\xc0\xba\xa2\x94\xc4K\xa5\xa54\xbe;\x0c\xd3\xd8\xa7\x89\xcc\x97\xec|p\xfb\xd0i\xb0h,\xa2\x9d\xb3uG\x91\x17\xbaiWxo\x88P\xdbCW\xe1N\xb8v\x86;Kux\xea\xb4\x9eL\n;\x12 \x86X\x1d\xe1[i :z\xf0'i\xb4n\xa1\\\x03i\x00\x95\xa3\x8f\x19\xb7\xa5\x0dU\x05H\xd3\xe1l XP?\xb2\xb8\xd8`*}\xd4\x93p\x98\xd0\x01\x1eJ\xf2\n\x86-\x82\xf9eU\xd3\x14_\x93zb\x020\x83\x821\"L\x8c<\xbc\xf5\xe8:\xc5\xa8\xb4\x0f\xc4J\x06\x9c|\xa0v\x00\x156\xdf\xcd\xb4*vL\xa9\xf6\xd5\x8f\xd4J\x0d\xc4\x96\x140\xecC&\xf0\x16m\xc4\xc5NA\xef\x11\xae\x04\xaf\xa3\xba\xc4s\x86\xcc\x1d\x8b_\x85y\xe4\x12\xc5\xfd:\x1aHg\x9d\x0d\x18=\x07\x1fU\x11\xcfacC\x1b\x17B\xfd\\\x8b\x1c\xffU\xac\xf2\x1b\xcc{@H\xb1\xa4\x15\xf2\x81D\xc08\x8a\xc4\x9e$\xac\xb7w\x91\x97\x13\xe8\xd8\xe9\xd2pn3\x1d\x97\xad\xc8W\xe1\xc5>\xe4d\xabi\xa2 &\x8b\xb9kD6\xf4>tQ\xc3\xf1.\xf2\xba\x96\xd3M\xfd\x04\xe5\xd7\x85J\x18\x1bhw,\xe1\x9dm\xd0f\xb4P\xa3\xcc/0=/\x1f\xb0\x02\xb7\xa2\x10\x1d\x10\x9a\xc7\x01\xda\x96\x8b\xb9\x94\xdaV\x8a\x1b\x1b\xfe\\\\z&\xdfs\x8a\x8d\x0d\x7f6i\x1et\x1f\xbc\xa3\x0d\xd4\xfc\x1b\"\xf7F\x1a\xdfA\x92\x92\x94b\xd6\xf4\x1b?\xbd\x8c\xb2T(\xc5\xa2X\xde\x07\xb4Yy\xf8n\x10\xb7\xd6\xb0\x98\xf9?\x84\x84\x93\x8b8[\xa7-l\xac\xe5G\xe15\xed\x94*\xcc)\x95\xf1Z@~r&\xb0B\xa9B\x03\xbf+?\\\xb9\xaa\xa1\x18\n+\x10W\xb6rny-\x96*.-U3VI\"m\x10\xe8\xd5\xcfEL\xc9\xd57]D@}&\xa6)\xc5\xc6\xc5y\x8f\xfa\x02\x99>\xac+}z\xf0\x16Q\x01\x0e\xc8\xd4%\xbe2el\xcc\x17\xac\x9c\x05\xdb\xe5a\xe2s\xd7\xd7\xfc`@-^#wA\xe4\x11K\xfb@\xc4a\x99\xf6\xb11\xc7\xc2=\x8a\xa3W\x1do\x1f\xae]a\x0e,GA\x1d\xf2 \x06N\xbe\xf6\x00\xa4\xff\x16\x1cVi\xc58<4\xcb\xc6\x1fLJ\xf3\xc7\xf6a\x0c\xe2\xea\xa3R\xd3\xc9Y7\xb9\x83\x04\xf3\xc2\xfe\xd6\x98s\xd1D\x19\xc0\xfctf=\x84Q\xbc\"A\xa9\x07y5\xed\xa8o\xa4n\x1f\x0c\x1e\x7fz\xa0/\xfc\xd0O\x1a\xfd\x13\xf2\xda\x05\xc7o'2iNd\xda\xf9\xd3k\x88L\xda\x82\xc8\x84\xea\x8e\x11\xdbKe\x9csL\x0c\x95\xad\x81\xc9\x89\x17)\x8d\x19e\xe9\xa3\xe3\xb8 h\xf0P\xb2\xdd\xca\xdbC~\xfe\xfd\xa0)\xa8\x92\x80d;\xa2\xcb\x8d\x84\xdb\xb2\xa4\xa0\xd9\xb5\xb1\xd8\xb5\xcd\xfd\x81\xa26\x8b\xed\xbb[\xfd|0\xd9d\xab\x1f\xfb\xb1\x0e\x05\xc10\xcb\x11\xf0\x85GG\x8d\x0b\xf2\x03&\xca\x07\x82\xef!iJW\xeb\xb4\xfb j*\xb5\x01x\xe32\xae\xea%\xad&\x82\xea\x0eR\x94\n\xf6\xe5\x91Woc\x8c7`\xe7\xecc\x9adAzDVt\x0c\x0d\x01-\x18]{\x17yc\x83m\"p\x85\x0e?\x9d\xb8\xe2A\xa1\xab9u,\xc4@\x03q\xac\x95VM\xc0J?sy\xf6\xbcA\xcd+q\x95\x9f\xf1\x8a\x9eI\x89\x0fs(\xf2\xe6\x1d\xea\x01Q\xcb\xa7\xe9D\xaa\x82[\xfb\x0e\x11Z\xe5S\x07\xef8\xa7:[f\xb1\xc8\xfe\xe0\xdc\x0f\xaf#\x8c\x02j\xb3\x15P?\xb9\xdd\x80U\x8b\x99\xb7f\x8a\x95(?\\s\xc8\xd6n\xae\x11\x08rm-\xf8 \x90 \xa6d~\x07q\x16\x86~\xb8\xb4\x89\x01E\xabZc\xf9jU\x95\x1e\xe5\x19\xc6\x0d\xd9\xf0\xe5GL\xf4\xadA9\x0e\xcd\x9a\x85\xb0\xe0\x00\"<\x96\x10O\xfd\xe7\x8d*Z\xc9\xf6\x85\xf9\x06m&\xef\xa4\xa9Q\x10\x0dg\xe8\x14B\x18\x064\xd3W4\x96m\xd32\xc8\xca\x08\xe3\xeb\"\xafns\x1f\xa0(\x85\x1a+\x7f\xa9x\x06\x12\x13\nZ\"\x97\xc7\x85Pjb\xc3B\x0d\xdb|\xfe\xe4\x92\xb9\x8a]E\xa3\xcd0+\x90x!q\x92m\xbc\xcb~\x9b\xde\x01\x9d\xa9j\xba@\x07_m\xf0v\xe2C/1\xb6\xa1BU\xc3\x01\x97O\x9d\x82o\xe5\xad6l\x18\xd8\x87\xb9\xbd\x8a\xd4\x17\xdd\xe4D\xa8\x19\xb1K\xdcq\xd2\x9a\x99\x10\xc0\x957 \x13\xb8\x841\xac\xfb \x8e\x8b\x87\"i\xe3u\xa6\xfa\x11I\xfd\xb0\xabvZ06\xc6\xb1\x18k\xe3\x0b_\xb3\x07T\\MrQ\xc3\xc9\xf1\xae\x90Y\xa4ZV\xd2\xad\xc4\x8eX\x06F\xbaV\xfa\x99-}\xd8\x07\xe2\xf6+\xc97M\xc7\xf0\x8d\xed\xc42;S4\xaeX\x8ai\xb5$z\x99\xd7\x89\xc4\xcb\xdc\xb3\x07\x87\xd1v\xa6\x8d\x11\x1c\xda\x0eQ,E\xc3\x08\xdb\x0e\xab\x15\xd0\x0f1\x9e\xa0\xe1\xe1\xad\xed\xe1\x89\xed\xe1+=0\xa6R\x01\x91c\x9d$=\xb3\xfc\xce\xcal\xd8&?\"hg;\xf1Le\x83\x05\x93\x84v\xb2\xadW\xb7j\xee\xaa\x9f\xf0\x95\xc5\x9a\xb4Nu\xd4\xd1\xa83\xb1\x19\x1a\xe4]\xf9\xad,\x8d\xe9\x8dt\xa7W \xda\xc0\xc3A\xc9\xb2\x90\x07\xbc\x8ey\x90\xbc\xa6\xd7@\xe1:n\x1c:\x0dg\x18a n\xc9{Hr\xd5\xd9\xdf\x177Fm:\x04\xe5\xa8\xc9\xda\x13a\x10\xd7\x11 \xbf@n\x1e!\x14pE\xcb=\x8dE`\xa0(E\x03L\x05\x8bV/]\x17&r\x1dr\xef\xa2` \x9e>\xc8\xb8\xa3\xfaI\x1d\xb9\x99\xa8X\xa2V\xaf~~\x88\xeb\xae\xfaI\x9d|\xd3>\xacC\x17\xc6u\x10|\xd5\xd4\x93\xdc$\x01C\xc9'-\x07\xd2j\xc8\xcd\n\x04\xe2d-x/\xb1w\xd2Z\xb0\xf8R\xad\xb6T\x08\x14J\x06\"K;\x87\xa0\x8f{z\xcc\xa8B\x9dv\xb5\"]\x07\xd6\xc8/<\xec\xa6\xd4\x0bL\xe5\xfd\xacF\x11U\xb0\xb9F\x99\x13or\xea&\x0e*\xb3\x92\xb6`\xac}L:/\xc74\x10\x80\xa9^\x1f\x17\xca\xd8\xc2PB\xcc\xd5\xd0e\xaev\xbc6\xd3\x84T\xc3:\xe5\x1d\x943\xd0\x9f^\xd2\\\xa1\x02\xf3\x88&\x10F)\xac\xe3\xe8\xda\x9fS \xf0\x18\xdf\x7f\x0c\xbcA\x93b\xc8\x86\x0b\x9aH}\xdaE\x8c\x90*\xc7}e%\xc5\xa85\xf4\xb9&H\x0bz,\xf1\xcf\x02\x80Hh\xc5\xebK\xac\x81\xa8\xbc\xeb\x89\xf4B\x90Tm\xe0\x95\x88\xe0\xed\x9dt\x8a4D\xe8\x9dfx}!\xe2\x99\xa7\x85B_\xa8\x9b\n\xee\x02\xcf\x95\xb4\xa4P\xb2\xdb\x19\xe8f\xc0\xb3\xcd\x8f\xcb\xef6\xa0@\xbe\xfc|\xd0\xe0s\x1c !\x88#\xc4\xd4W\xab\x9d{lwa\xd1o \xae\x1d\x1e\x03\x9d\x0egu\xf4\xa9\xaf\xc3\x88\x9b\x9ar\xa0\xc9\xcbd\xcc\xc72\x9a\xb9}\xd8T\x1f\xabz|\xa0\xdc\x1d>\xd7\xd2c\xd1\xd6\xcc\xad\x9b+\xa19]\xdan\xce\x1f\xecs\xa6\xea\xed\xd9\xfd\xbd\xf6\xfa,\xcdMR\xa4L \xbd:R\x8e\xbf\xa5F\xf6\xab\xd1\x94\x0d\x03;\xd5\x0f\xac2W\xd8\x87\xa9}]\xb8\xa9G}e08\xacd\x92\x8f9\x10\x8b\xc8N M\x9d\xea\xfd\xbei\xa4\xef\xf5#E\xaaj\xd3\x16\"|\xa7\xc4p\x07\x81\xb4]\xa1\x12|\x7f R\x9fom\x8fJ\xcf_\x1d\x7f<,?/eU\x1a\xbc>|s\xf0\xe9\xdd\xe9y\xb5\x9fQ\xa5\x1fY\xef\xcd\xa7w\xefJ\xf5\xb6wJ\xf5\x82\x88\xcc\xf1\xc2\x94}\xa9>8\x08\x82\xfc\xd9\x01\xe3 \x8a\xc7 Y\xd0w\xf2]\xf9CWA\xb6\xa1\xfcV\xab\xcd\xb3\xd5\x1a\xb95\xf6\xa5\xfa\xfek\xf9P\xfeP+\xfc\xf5\xe0\xfd\xbb\\q-`\xb0W\x9a\xdb\xfb\xb7Go\xdf\x1f\xbc\xb3-G[0Z \x98x\x84\xbb\xedv\xd9\xb7n\xe9\xd9\x9a\xc4\x18F\xd1w\xba\xf8\xb5\xfc\x14\x93\x19\xcb\xe7\xe2G\xb9\x06\x99\xcf_\x95<\xa5|\xa7[.\xeb~\x93M\xfc\xb4\xea\x06\x1d\x15\x00-\x95\x8b\xb4Z\xdb\xfaDq\x08\xbdRyV\x80\xacT\x9eh\x9cE\xad^\xa1\x01F\xbd-\x15y\x18\x07\xbaL\xaba\x1f\xb6\xcaE\x0c\x81\xb6\xcbE\xf3z[\x97\xf5\xb6\xae\xebm\xad`\x1f\x9eL\xcfn\x87\xc3\x8d\xb3\xdb\xe1\xd3\xb3\xdb\xe1\x8fg\xb7\xc3Wg\xb7\xc3\xc3\x8d\xb3\xdb\xd1\x9b\xb3\xdb\xbd7\x1bg\xb7O\xb7\xcfn\x9f\xeen\x9c\xdd>{s\x96\xbdy\xf3\xe6\x10\xff\x7f3\xbb\x9f\x9ee\xaf\x9f\xb2\x97\xb3\xd7?\xbey3s&\x1dV\xf2\x8a\x97\xb0\x1a\xee\xbd3\x19O\x7f/W\xbb\xff\xdd\xadT{R\x1e\xd6R\x0c\xeb\xe9\xceY\xb69\xdc|\x8a\xff?\xab\xd6\xba\xc3Z\xfd\xb3\xe9\xd9\xec\xec\x1fg\x9f\xab\x8f/\xd8\xe3\xdf\x9d\xc9\xb8s\xdf\xe9\xdcw\xa6d\xe3\xefg\x1b\xb3^\xc7\xfd\xf3\x13\xbf\\\xf3\xbc\xa89\xfd\xbdh\xcfu&\xe3\xff\x98\x0e7\x9e\x91\x8d\xc5\xec\x1f\x9b\x9f\xef\xf9\xf7\xbf\x9fm\xfc_\xcf\xcf\x9e\x9cM\xc6\xff\xf9h\xff\xacw\xf6\xe7\xfe\xf9\xd9\xa0\xf3?g?<>s\xce\\\xf6\xf6\xcc\xfd\xe1\xcfO|\xddYqc<+F\xc3\xc2\x8an\xb4\xc5\xbf+\xd4\xbc\xde\xd4\xa1\xb1\xa9gEK[\x9b-Z\xba}HK8\xbe\x87\x8e\xf5\xc4\xd8\xc3\xf6v\xd1\xd4\xb3\x91\xf2}K\xe9b\xb3\xf4c\xa7E\x87\x1a\xbd\xbaF\xc5,\xc7\xf0\x14^\xec\x0bgI\xf6mg\x0f\x13Zn\xb0\x07cx\xb6\xc7\xca0\xaa\xf8\xd6&\xdc\x0b\x9bF4a\x1c\x0d7\xd1\x9ca\x83U\xea1\xb0\x8cacd\x1d\x98F\xff]\x8c\x82Or\x02\xdd\xb3a\x97\xf7\x9c\x97\xfc\xff\xb0@\xadr\xc1JF\xa3]\xa5(\xc5J\xd5\x82Q\xbe\\\xac(\xe4EjK\xd7X4\xdcT\x8a\x16\xbc\xd6\xb6R\x14\xf3Z\xa3\xa2\xe8\xff\xcfJ\xb6\x94\xd7\x00\x0b\x8a\x97\x1ew\x1f\xc3\x18\xb6\x95i<\xc1\x11\xaa=\x9d\xb1\x92=e8\xff\xe7\x7fc\x9d\x1d\xa5\xe4\xff\xc6:\xeaL\x91*\xb0\xd2\xa7\xc3J\xe93V\xda\xedZ\x17\xe1\xc0\xb8\x08\xb8\xfe\xbb;;[;0\x01\xeet\x87y\x0b_]\x92\xf8U4\xc7\x9c\xa8c\xed\x83\x9d\x9d\xcdg\xbb\xd0\x03\x87!\x0eka\x17^\xbe\x84\x11\xe3uvv\xb76\x87\xe5G\x8f\x18\xbc\xb7\x14o\xd9\x82_\xcb\xed\xe4\x8e\x85\x9a\x043\xee9\x9b;\x8c5\xfb\xa0);\x054\x97;\x85\x17\xb0\xb9\xb3\xfb\x1cN{=\x17\x8e\xa7\xa73\xd8\x87+\xe7\xd4\x85 \x8c`\x0c\xc3>|(\nu\xc4\xe9\xbdV\xc1\xa9\\\x94Dx\xdf\xc7\xc3\x17\x0f\x16~@C\xb2\xa2\xa8,\x0b\xd7Y\x8aN\xb4Q\xe2\xa7huH\x07\x81\x1fR\xb5\x0c6D!:\xd0\x97\xe6^\x1f\xcb[\xedX8\xcf,\xc6i}\xff\x0f\xed\xfbt\x10\x85\xbf\x918\xf4\xc3%w\x8d\xce\x7f\x8a@\x85\xa8U\x12\xed\xeb\x16\x87\xad\xcbQMe\xc4\x18\xb7\x9a\xd1\x99V\xb9{]$\xa4\xab\xcb\x8e\"7\xf0>\xd0\xc15\x8d\x136\x8dG\x8f8$\xba\xf3l\x1d\xf8\x1eF\x1d\x84h\x01\xff\xc1\xba\x84\xb9\x1fS/\xf5\xaf\x91\xc7\xe2IC\xf2\xa4:\xf9\x9b\xe5\x9a@<\xc6`&@o\x89\x97\x06w\xc0d]\x99\x03\x12\xe3E\xb3A\xb0-\x85w\xe0O~w\xd8\xa17\xeb\xb9g\x03\xf9\xed\xcfO\x06\xf4\x96zN8\x1d\xce\xb8\x17\x1b\xef\xc8\x0f\x82\x8dE\x14\xaf\x98\xa4\"\x1a\x04L\xb0I\xa1>Z\xc6\x8e!\x03\xf96L\x9d\x18\xc3B\xe2^\xf1\xcb\xe5\x9b\xb2\x9c\xcf.*z\xcbB>\x13r\x11\x88\xf6%\xccD\x9f20\x1b\xe7?\xe5\xc3}\x081\x12%\x1dx\x97\xd4\xbbz\xe7\x87\xf4\xc7\x98\x92+\x0c{\xc1v\x90\xec\n\x0d\xdc7\x8b\xaf\x7f\x88^\x93l\xcd8Y:o\xe8\xb4\xb4\xba\xd5\xccb\x07?=\x0c]\xea\xb8\xb2iX\xed\xd3\x83\x9f,\x8b\x9d\xdeDE\xc2O\x06\x988\x07\x08\xf2\xc7\xb8\x0e\x17\x83\x94&\xa9\x13\xa3\xa8][\xda\x94,\x81'o\x01g\xe1\xc7I\x9a7\xe8J \x94\xc6\xc0zI\x84\xeef\x90\x92\xe5{\xb2\xc6\xcb[9\xe2\xc7\xe9%\x8d)\x9a\xbb\xc1:\xa6\xd7~\x94%\xc1\x1d\xcc\xa9\x17\x90\x98\xce!\xc9\x16\x0b\xff\x16\xa9b\xf71\xf4 \x86\x1e<\xee*\xc3x\xec\xf6\xe1\x9c\x0f92\x0fy\x1dS\xd6\x8c\x93P/\n\xe7-\xc6,\x07;\x8dg\xb6xr::\xfa\xd1b'\x89\xb7\x0cy>\xb5\xf2\xba\xa2f\x10^\xe8QA\x18\x93Ib+\xdcH\x11q\x8c\xd1\x81\xf1(\x89\xb8\x83\xad\x8fw\xbfB\xed\x06\x11\xbc\x00\x9f\xfd\xe9\xed\xc3\xc8\x15<\x83C\xb0\x8e'\x8e\xb4\x03\x06PW\xf0~/\xf6y|8\x82|\xcfh\xb4=\x1a\x8d\n`\xd3\xdb5\xf5\xd8\x9e\xb8&\x81?\x87\xbf\x9c\x1c\x1f\x15\x11\x0cuv\x8bhp\xb5\xe2\xab\x96)4\x84-E\x92\xc6\x94\xac\xd0\x16\x89\xf8a\x02a\x14n\xacc?\xe4[=o6\xd1\xb6+n=\xd8\xbc2\xd3\x9ai\x96\xecu\xb1d5\x87M\xbc\x7f\xe1\xeb\xd5\x87\xa0\xdc'B8\x1e\xf8 \x17\xfd\x9cP\xc1@\xa1\xaaY\xd1xIaE\xd6k?\\&\xcf\x11\xdb\xc4\xdd\xd6\x1c\x92(\x8b=*.9\xd8&P\xc9\x1aC\xc3\x8c\xaf\x1e\x13\x16\x1d\xc58\xf6\x8a\xdea\xa2\xb7|A3x\x01\x01\xfb\xc3\x17\x14\x9dd\xa6\xd9,\xdf{)\xda&`r!\x1e\x95 \x9c\x12\xb6\xeb\xf9\x0fU#\xae\x03\xcf;\x05\xa3\xd5t\xaa:P\x05}\xf0\xeax\xcd\xb0\x90\xb3MN\xa4\x9e2y\xc4\x11\xf8\x07\xe6\x83N\xc9r|GV\xc1 \x8a\x97\xfd\xcd\xe1ps\x8c\xf0\x13\xa6\xf3u4gm\xf3\xf4\xd2~\xc2\x99\"\xdf\x96\x958\xe0\xe0\xf4\xf0BL\xc2.\x80\x17\xe0\xb1?\x1cv\x12\x17\xfci0\xd3\x9b\xe4!\xf6\xe6\xd5\xeau\xf09\x1d\xfc\x91\xf0\xbb\x95$\x8f\x82\xcc T\xa7X\x13^\xe0p\xbe\x08\xd8\x1e\xc3\x0c_5\xd6i\x1f2\xfe\xa4`\xb0\xca|\x01\x9dK\x14\x83+z\x87!M\xd2i\x84\x17\x7f\xf9\xadM8\x8dfZ\x01(\xb5.\xfe\xa7V\xb2\x94\x102D\x8aMN\xa3\x14JR\x8c\x1c\xf32\x15?{=&Vl d\x98\x80\xa3>\xea\xe7\xa2\xa6\xb5E\xce\xcb\x15\xaf1\x1e\x9d\x83\x87\x00\x02\x16\x9d\x9e\xd8\xf6\x92\x84\x8aSx|\xd6\xc3\xe4C\ng\x8a\x13\x90\x8dY!\xf37\xd3\xd9]J\xc69\x94\x19\xfflSx.\xb2~GZchqyr\xe8D\xees\xd7\xd4Z\xaf\xa7\xb6\xa7\xdd)\xb8\xdb\xb6\xb8he\x08\xf0?\x8f,\x979mz\xd6\xbe\xfc\x19n.}\xc62\x8c\x86\x05#7\xda*\xbe\x8bb\xc3\xb8;7x\x14\xe12\xd6k t>a\xf2\x90f@\xf7!fx\xc5\xd7\xfbm8\xe7\xe6\xcd\xc3\xe7R\x90e\x0b\xa0>d\x95\x1f<\xed\xcf\xba]\xb6!8\xf4b\xba1G\\e$/\xf8c\xcel\xce\xe9\xc2\xf7|V\xec\xe3S\xe4\xfe\x91k\xb3b\xe5\x1b\xc3~\xed\x8bD\xb3r\xc8ZR\xd0q\xb6wpl\xa6\x8d,2\xe7n\xefr[\x01\x0c\xfd$\x84\x96z]\xe81\x82\xdaTe\x93\x13\xc1\x90m\xc5\xad\xbe\x80MC\xff\x9d['u\x1bd\xc8\xbfke\xc0QNjTf\x81\xeb.R\xcc\xda\xcfc\xce\x15\xcf\xe2AL\xd7\x94\xa4N\xf7\x0c\xcdd`\xa3\x94(K\xd7\xf5\x8f\xda\xae\xafE\\A\x89Q)\xd1X\xe2\xf9\xdck2\xf4.\xaby\xb3A\xa8\xa5u\x99Q2M\xae\x11\xeetQ\x08\x95\xbcM1=\xfe\x831\xb8\xf2;;,\x88\x90 \xda\x11+lk\x9b\x93\x13\xfc~\xebX_Dtp5\x97\xbe\x92\xb9\xed\x0c\xfbP\xa6\xffHbY\xf1\xc6\xc8\xad\xef\x96}\x06c\x99\xbb*\x0b\x82v\xa3\xafu\x9f{.\xf0\x0d\xc2O\xdf\xdf\x04q_\xf0<\x1e\x1d\xcc\xce\xc2\xbb\x92\xc8\xe1\x96\xc7\xd7\xa6\xf3~q\xd8#-\xc8\x8f{1\xa5\x97\"^\x8c\x00\xb0+\xce\xb1\x0b2W\x89\x00\x93Z\x08$\xf4o\x19\x0d=\n4Lcm\x94\x80|b\x15\"\x93ji\xa9$\x01\x9dL\xe0\x08\x13\x9c\xd0W'\xc7\x1dd'\xe8\xe0\xca\x0f\xd1\xaaG\x8e\xa0\xdb/6\xd3>\xe3\x0c\x9b\x18\xca_\xcd4*g1\xf95\xbev\x07T1\x9dMq\x8b\x9f&N\xf3\x11P\xd8\x0f\xe8\xdaQ6\x0c\x9b\xbfI\x03C\x84X\xc9\xafv\x18U\xde\x15\x1cP\x9b\xd3\x82\xf1@\xc8\xcfw\xcc\xdcA\xe5\x851lq.)b\xef\x12%\x01g\xb7\xd3\xe9\xb6o\x85\xbf\xd1\xedC\x99\xd11\x98<\x1b\xd9\x816\xdd\xd5^\xcc\xd9\x00\x85\x0b\xd8\xdd4\x1e\xfd\n\xe5(lF\xd8\xecc\x9d \\\xdaem\x86W\xb0\x89Y\x98K\xb04\x9cK\x9d\x80\x10Do\xfc\xf4\xd2\x0f\x81\xc05\x8d/H\xea\xaf\xd8\xcaW\x15<\xa6p \x82sS\xe6\xdb\xb9\xe5\\\\\xbe\x9al\xaf\x11\x98H \x98,\xa5\xceC\x08\x90B\x10\x06z\xeb\x05d\xc5\x11pE\xe2\xab\xa4\x9b\xa7k\xae\xc0\x82\x1dP%\xf1\xa1\x87\xc9\xed\x84bG\x95QCR\xd1\xe9T\xfaL2\xef\xb2$r\xcb\xcc\xe5U\xf4\xe1\xa4\xbd\x1d\xdc\xeb\x0b\xdd\xbc\x9ew\xb9R\xaa\xd0\x15\x18!\xb5\x08\xa2\x1bF.\xd9v\x8d\xe2\xd2\xf8\xcb\xab\xa6#\x7fx\x90u\xce\xf5\xfd1x5\xc0h\x8c\xf6\x1b\xb1\xcb\x03KH\"\x1a\xc3\xb8\xae\x06\x0b]\xa5F\xaep\ng\xa8\xe6\x1a\xb3]*N\x89\xa2\x16+\x93Ou\x8f\xeb\xf2\xb3\xac\xcf\xb5mY\x98k\xd6\x94UG\xcdZ\x88\x9a\xb5\xc7\x98\xda\xdeJ\xbc\x7f6\x13o\x0dY~\xca\xc9r\xf8\x15d\xd9\xcc\xc8\xe8Is\x08\xa2\x86J\x9e\x0d\x03(af\x15\xab\xe5\xc6\x0d\xc5\xc6\xe5\xa2f\xe7\xc4 \xd9\x0en\xd3\xa2\xf6\x84U\xb6M\xae\x03)\xf6cy\na4\xa7\xb0\xca\x92\x02\xdfH\n\x01%I\x8a\xaa{E\xcbV:\xa6\xed\xbb\xa9a\x81\x7fS\xb4a\x9as\x01\xddqQ\x1b\xb6\xea\xc3\xb2\x0fw}\xb8\xe8\xc3y\x1f\xae\xf8e\x94\xe6\xd0~o8\xcc\xff0\x1c\xe6\xcab\x07~\x92\xd2\x90\xe6\xb2\x12\xff\xe5t\xa35\x0d1\xbfx?\xc7~~}\xa3@A\x16\x08~E\xfe\xcc9\x15^\x80jO\xd8Gc\x88u\xc1\x97-\xf8W\x11q\xad\xca\x88:\xefs~\xb5\xcc\xbe\xc1\x84\x03\x01\xd3_\xa9B\xa6\x90:\xf0\xba\xae\xfa\xf0\x85P\x84\x9d\xa2\xf1\xa5\x8b\x17\x1e\xec\x85\xd3\xfa\x19*N\x14\xe4\xa0\xee\xefq3>w\xcb\xc3\x9b\x14\xa3[q~\xec\xbb\x0c\x12\xc6\xd8\xbcn\xfdV \x832\xbfg\x83\xf4\xf3\x1b\x9cS\xf6`-6\x15\x93\xfa\xce1\"w\x0et/'i\x98\n\x80\x1d+}\xb8*\x1f5\xa5{\xc4\x1cR0\x01\xde+\xca^W\x08\x9c\x87\xdc\xb1\xf4\x0b%ob\x96\xce@X\xee\x98%4\xf6YXBr\xcf-\xcf.%Nj\x9f^[\x9f\xae\xacO\x97\x86\x0d\x08\xc2\x8eF\x97\xa7\xf2\x0b\xe4\xc7\x85PY\xb7\x93\x1f3\xa3\xe7\xbf\xf4Vn\x16'\xfbB`\xe6B\x1b\xa9\xf0\xb4\xbb\\(@\x81f\xe7\xa9\xf8~\x7f\xcfhyl\xb5\x84F\xad\x13\xd2\xc1\xb0\x0f^.\x02\x1auP\xea{\x8a\x80\xd7\xe8F\x880n\x03\xb1C'c\xfb\xdcP\xb5\x81\xbfR?l\x84;\xdc\xde\"s\xe1\xd6\xd4y\x85S\xce9F\xc2X\xf8\x94&k\xe2)\xa7\x8f\xaa[\x05td@\x0e\xfa\x8a\xdemp\xd3\xea\x84\xae \xf7\xf0\xc8\xd9\xe9\x8b \xf2\xae\xa4\xd6\x9a\x1d_(l9x\xd7\xb0\xe8\xc3\xbc\x0f\x97}\xb8\xe6w\x05n\x1f\xf7\xc6\xb5\xa0\xd2\xa2\xe8N\x109\x81\xdc\xc8|\xb2\xbf\x97\xf9\xfe\xc57$\xc1\xb7\xc3\xa5e\xf2+\xa6\x04\x88\x97vF\xe9\xba\x91Q2\xe5'a\x80\x17\xe6\xa0\xce\xba\x19\x17\xf8\x9d\xd8\xb3\xad\xbe\xd0\x83sM\xac.P\xbd\x85\xf2\xb1>G\x9b\x9caX\x1beQ\xf9a\x1d\x8e6wD\x8fC\xde\xe3?\xda8\xf4|\x01[\x15\xbb}0\x80\xa1|\xf2\x0b\xfc_[\x19\xab|\xab\xb1\xbd\xda\x06\xbc\xe2\xbe\xb0.\xbe\xf2\x9b4\x8e\xbb\x97%\xdc\xbdVp\x97\xd1\xdb\x1c\x7falR\x1b\xc7\xe6\xc3d^\xf0\x1f\x9c>\x82\x17\xadV\x04.hzC\xa9P\xf8xQ\x10P.\xc0R\xeeD\xc8H\xa3\xc7\xb6\x95H~\xc9\xc5=\x1f\xef\xd99\x9a\x88\x13a\x0dm//@F*%\xf6\xeb\x8a\xd4\xcdU\x0e\xe5\xeb\x84@\xb9N\xf0\n>%Q(h\xa9\x19\xe3\xc2\x97\x05z\x02\xf9\xe5H!\\ \x8ew\x8d\xe4Xj\x9b\xdb\xe0Qe\x04\xba\xb1/\xca$\x9f\xad1\xd2\xb8\x18\xe9\xbc\x874d\xc1]\x81'\x10\xf3{\x13\xac\xc0\x17A\xa9\xc3*\x89\nI\xb5ga\x1e\xde\nI'\xe0\xcc\x1f0G\xd6-\xd6\x1f\xb5\xd8\xb3\x0fQ\x13W\x90\xb1\xaasd-\x9d\xb3\xd1\xa2\xee\x83 \xd9<\xfdn[R]\x15T\xe7f!\xd5$\xf0y\x96g\x0b\x0c\x8a\xab}\xb4\x86Z\xfe9\xf9\xd1\xe9\x01 \xa7\xa9b\x11I\xf3\"\xba\x82\x87\x7f0\xe1\x16\xb7\x08\xa4\x15\xddntP\x04I\xa6\x95\xab.\x8f\x04$.S\xacnW\x12\\b\xf0deC\xdb\xde\xb2N\xbf.h\x89\x1bU\xe22\xfc\xdcg\xe4k\x82+-\x1a\"\xc8\x7f\x8d1\x80\x17\xc7K~=\xcd\x99\x1b\xef2Z!w\xb3B\x86\x92q-\xfe\xc2\xd7[\xe1A\xb3\xd8\x83b\x80\x83\xc4\x83\xbbI\xa0\xbc\xc8\x93ne\xb9\xb3D&\x9d%6F\xbfF\xf1`\xdf\x18\x11\xbe\x8e5\x0c^\x87\x0e1\xea\x16\xac\xe65m0D?\x0ey\xaf\x86]\x9b\xf9\xfe-\x89Y\xc6!X\xc7\x07_3FP\xc7\xd9\xb9q\x88r\xcf\xad\x19\x90aC*\x1b\xce0P\xc5\x1a\xa8j\xe4\xd37\x8d\xbe\x9d\xf2\xc4\xe9x5Y\xe9\x05;\xe4\x1e=\x92\xd6CDc=\xd4\x06b\xe6%\xebxP5{x \x0bdC\x169{\xc1\x1f\xb8}\xb8A\xd4[\xf7z_\xbc\xd9\xeb\xb3\xb3\xe3C\x82\xf3\xbe\xae\x98\xd3TLf\x02\xf4A\xe9\xc1\x1a\xc6\x8c\xb5\x1e\x8b\xb70\xc4\x88\xcc\xf1\xa8\xd8\xe2\x9c\x85M)\x0f\xecA\xed\xcd\xaa\x0fa\x11=\x01\xb6Q\x18\xc7\xb0\xca\xd9\xb8\x96\x83\xe7Zo\xf9\xe6\xc8\xfa\xe6Z\xf0\x8ccA\xed\xd60\xd1M\x17\x90\xee\xd8\xdaix^\x1e!\xb7\x16\xee\x0c%\xe9\xea\x8b\x83\xbbj\xfe\x05\xd5M\xf8\xdc\xfd\n\\e\x9f\x8fB_\xaaj`;\xa3\xb6\xa4\xd3(@W\x8ek\xc9A=P\xbc\xd53'[\xcf\xbe\xfez\x12\xdar\x0bUi!\xc6\xec\xbd\xfb\x9a\x0b\xc76\xe3\xb1\xb0\x1c[\xdc\xa0\xdf\x9a\xf2\x82\xd5\xfb(8\xf6\xd2\x821\xee\xbe\x01,e\x9e\xa5\x00\x8cE\x17\x18\x97\xe6Y\x85D\x19\n\x863\x0e\xa9\xd7\x8d\x83\xb7\xe6\xf9\xd0#1b4\xf6\xe3\xb2\xc3H\x88_u\xf0\xf2}\x94Kt\xfb\xfb\xfb%\xc3\xdfG\x8f\xb8\xf1\xe4\xc4\xca\xefK\x1f\x9f\x82\xe3O\xfcp\x19P\xf8[\x16\xb1\xaab\xedEBJ\xf3,5\x1b\xe9!b\x86\xbe\xd3o\xb1ST\x01\xc3\xb0k\xb69z\xb4P\xd3}\xfb]\x13\xa29\x85v\xd7\xb4\x18\x8fU3\"|W\xb3|\xd0Z\x8a6t\xabC2!>\xaa\xb16e\x9b-\xf6\xa2\xae\xab\x9bvW4\xae\x8a\xfd\xe6}\x98\xeb53\xee/\xca\x90\xfex\x9a\xcd\xdc\xd2\x01\xf3\x01}G\xd4I\xb6h\x11%\x9c\xd1\xa60\x83\xc3`\x93l/m\xa2+\xf1^.\xcal\xc3\x18\x9e\xee\xe4?\x99\xd80t\xe1%\xfb\xaf\xc5]Y\xc4/\xb4}n\xb4\x1d\xb1\xf7\x9eC\xb4\xb1\xe1b\xef\xaf\xda\xc2\x8a )0\xc1f\x1c\x1f^\xbc\x80m\x17z@r\x91*\xdf\x81\x97\xf4\x96\xcc\xa9\xe7\xafH`wiR?*(\x0f\x1c\xbf\x82/f\xbe\x85\xc3RR\x81\xab0\xba \x81&\x1eY\xd3\xdc\xd8\xd3\xd6u}g\xd8)iVPR\xbe\xf5M\x94\xb4\xde\xf0w\xa2\xa4\xf3(\xbbhCI+\x83i\xc1K<\x84\xb4\xeaG\xa1%\xad\x8a\x1aG\xc95o\x0e\xbd\xc6!\xad\xa7\xaa\xdb\\\x87\xd1|\xf1\xdd\x86\xaa\x1a\x1aie\xee\xc4M\xe0n\x85\xf5[\xe7\xc4\x89\x19\xd9l\xd3b}0\x0f2y\n|\x92<\xc8\xe2Ic\xfc\xd8/\x9b:)*\xf5J8\x16\xd5\x10\xf2q\x16\xe6j\x80\xb9\x18G\xc5(N9\x93T5}8\xab\xde]\xd5\xd9U\x86&_j\x8a\x82ZWO\xea[\xd9IiV\xce\x99/\xba\x19z\xdd:^3b1\x88\x9c8\x1ew\xfb\xe4D\x1a\x85\xde\xad\xa7\xc5\xf7\xedM\xa5|\xab\xf8.\x15}\xf8cW\xad\xf4L\xf9\xae\xd4\xd9\xdaS\xea+\xe5\xcfx\xa8\x07\xcf\x8a\xe5x\xe2\xec*\xdd\x0b\xb5\x99\xc7u\xf4\xb7\xcd\xdbHHg\xf7\xf7\xdc\xbe\x8f\xa1y\x8b\x8d\xd5\xcc\xaeD\xe8K^fw\x85\xd5\xba\xd8`\x9e\x95\x0b\x11\xd6\x19\xd6Dp|A\xbfh\x8a\x16\xe1YI\xaf\xb8\xb5\xd3v\x10\xf6\x01\xa0\xafL\x8b>\x9b\xb4\x12\x8dGM1G\xafY\xfb\xc8\xda\xbc\xc1\x8a\xcdV\x10Y\xaef\x91\xd74\x8a\xf1Y\x90\x17p\x95\x89rrn\x8cjw\xd4\xfb\xf6\x04o\xf2C\x14\xf9\xfd\x8b\xb5U\xe2#S:X+\xda\x839\xab\xc0\xe7\xfe\x1f\xdcx\x80\xd1'u%\xc4\xfduI\xe7\x16|{=\x8e\xbe\x14/\xc08/\xc3\xe9gg$y\x191\xde\x0d\xc8\\\xdb\xe6t\xfbp((\x9fS\xae!\x0c\xcd\x0c\xcb\xd1\xe0\xf2`:\x11\xabC\xedtr2\xc2]\x82\x05\x99Y\x94\xe8\xcb\xba\xaeQ\xe1\xacH_ZQr\xf2\xf7\x87@\xa1\xdc\xd1:\xf7f\xc9\x8d\x0d\xba\x93.\xea\xa6,u\x95\x12q\xb3[\xd8\x81\x15gur\x19e\xc1\x1cmu.\xc95\x05\x12\xdeI\xcbk\xbc\x84\x95\xfe\xde\xad\xaf\xbb\xf3{\xc5Buv\x9a\xcf\n\x8d<\x85\x8dg\xa5i1\xean\xa7[\x14\xe8\x9d\xcd\xba\x93n1S\xab&y\xc9ugw|\xed\x85\x11\xd2\xe9\xdd:OZ\xf7\x1c\x96\xf0\x02\xee\xd8\x1f\xf4\x1f\xb7\xd2\x1c\xe7\xa2\xde\xcet9s\x072\xe0\xbb2u;\x9dPp\xe2b\x90'lW]\xd3\xe4:_\xf0\x1b\xe6/\\\x82o\xbb\x7f\x05\xb1/\xb1t\xe7\xb6`T\x0b\x86N\x19\x13\xbfw\x16\xc7\xdb\x91\xf0\xf0;\x9a\x863\xa9cc\xf4\xf4\x0f\xa1q\xe0\xf44W\x82\x15hZ\xd2<\xfc\xc9\xdcy\x99\x1e\x0c\x15\xd1H\xec\xf7\xc2=\xdfN(\xdaV\xe4\xf1\x1c\xdaW\xdet\xcb\x11]D\x84\x07u\xdc\x0c D\xb3W\x13T\xd0\xadH\\\x8b\xdb\xf2[\xc1\xd3\x8bi\xa2\x9d\xc6Z1N+\x03\xa6N\xa4\x1f=\x82%w\xf0,\xaf\xbd_^{\xc8Cq\x84Q\xb8qp\xf2\xea\xed[%\x9eL\x02$\xa6\xe0\x87)\x8d\xd71E\xc7\x87\x04\xc5\xad<\xe8\x9c\\\xda\xa4\x166\xa0\x85<;\x81\xed\xddf \xbb\x82\x15h\x80\xb0RA\xf1\xa4\xdeP\xa9d]\x1f\x1a\xc5\xa8\x0b\x15\xe8Yxp\x94\xd6\xc3z\x18\xff\xd5\xd1Fa,bAQqv\xa0\xcc\xc3\xce\xc8\xa1\xe4\x17\xf2\xb8v2d\x0c-\x03\xa0\x98\x02\x82@\xc4\x92\xb1Wrhn^\xd0\x87\xdd\x9d\xcd=\x11+U}i(k\xb2r\x8e\x15#\xb7J\xfb\xaeE\xde\xe9\x90\xde4\xdf\xaca\xe6 \\B\xc0DL\xf8[F\xcfds/~\x08\x96G\xd4Id\\\xf6T~\xbd\xbfg27>,\x02Y\xb2\xe7\xc5\xafr\x13\x9c\x13\xc1*\xe2\xeb\xfd=W\xeb\xb3\xa7\x18\xa0\x8a=\x93\x91\xaa\xf2'9\xbb\x86o\xca\x1f\xe5\xb6KB\x8cL\xc2\xcd\x07\x8a\x81\xc0\xfd\x80\xce\xdf\x8a:2\x97 \xe7\xdf\x0d\x95O\xf9\xd3|\xe8\xb8v\x052\x88rE\x171\xccG\x8b\xea\x08\xf5\xa7\xd4H\xa8e\xaa!\x10O\xf7,\xf7'\xf2\x17eB\xcb\x97S\xc3\x04\x86b-\x11\x93\x86\xdd\xaev\xe5\x97s\x93t\xf2\xdc$EZ\x12_3#%$V\x11\x82-\x86\x17\x10\xb1?<\x04[\xea\xf8\xd3xf\xa7-?i7\x9c\xdc\x99\x7f\xd5\xad\x1f\x1b\xb1p\xe8\x96\xd9P4\xfb\x95\xd5\x1a\x89%\x95\xb5$X\xa7C\x8dOA\x91\xc9!r\x8a\x8b\xc3\xfc\x86>\xa7\xa0~\xa8P\xd7>\\d),\xa2\x8c\x9drQL\x1f\x94\xc9\xa1He\xf0K\xbf\x9e\xfa\xe0\xa7\xbe1kA\xd3-D\x8b5E\x94\x89\x07\xf46\xa5\xe1\xdc\xa9\x83\x8fo\xea1\x90\xf2|Xg\x95\xe5\x90\xc8\xf7\x85\x8d\xfdI\xf9\xa9M\xe3`\xa5\xccb6?}\xe9l\xea\xf1\x81\xbf>c\x81.\x98h\xe4\x94B/V\xa7\x81tL\x1c$\xf2l\xb9\xc8\x16\x0bN\xba\xeb$3,\x93\xccX\xfc\xf4\xa2 [\x85\xa5@\xa7\x05\xde))\xd8\x07K\x9a\x9e\x84\xfezM\xd3&\x00\xd7\xcc\xd5\xeb{\xb1\xa3\x0c\xd7U\x95\x06:\xd9\x1bD\x00\xf8m\x85c\xd8\xdb\x11\x11p\xc4\xadKi\xb6\xc2:\x80\x1d\xe7\x1b|?w\xcf\x86g\xf1Y\xf8\x7f\xfe\xb7\x9aU\xa0;\xf0\xc39\xbd=^8\xcah\x90\x8a\x1f\xa4N\xc4\xef/\x0c!\xab\"\xd8@2^\x06\xf2\x06\xf6\x9b\xc2\x13\xd8\xe4\x9c\x87^X\xc3q\xc3`0\x00\x1c|o\x1fv\xf4RJ\x1bw3\x04\x91/ A\xea\x90 \xf0B\xc5\x0d\x85\xbd\xfab\xd0\x10#X\x1c\"\xc8\xf8F\x052-\xa0\xe2\xabP!\x0c\xbe_\x01\x15\x81Q\x99\x84\x87\x98\x00\xe7\xea\"\xee\x8aX\x98R\x02\xaa\xa1\x84\xe4\x95\xa1\x01x\x8f\x07\xcc\xefUkAO\xb3\xe6=\xe5\xbc\xe8A\xf7\xf7\xaeJ\xa0\xd4=\x94F\x9c\xfb\xb5\xe6\xe6UB\xf6u\xbb\xda3\xbe\xd8\xfa\x8caE\x0e\xe2\xb1\x1fr\xe1\xb1x\x86\xd1\x92\x1f\xe3U9\xe3XH\xca%\x186)\xa7\xa0\x04(\xd7\xf5\xd8\xdc\x04%(\x9e\x8b\x02~\x05\x82;\x10\x85r|VP\x03G\xa8\xa8x/c\x0e5\xd4]j\xc9tNi\xbe\x92h\x8ev\x953Em\x9d\x9d\xc6\xb1\xa3 \x87\x93\xa4q\xb7_\x81\xf5\x95\x1f\xce\xc7\xc5}n\xe9Y\xae\x90\x1d7\x98w\xd4t\x9e\x98D\xa2\x94\x8b\x00\xca\x07\xbb\xfb/\x82\x00\xfd\x9b\x11\x02\xb9c\xde\xb7\x85A\x95\xb9\xfe\x97\xc3`E\xd6&\x18\xe4\x8e\xb6\xdf\x16\x04\x15\xd7\xd0\x7f=\x08\xd8\x08\x1f\xb4\x13\xc4\xedA\x13\x00|\x19\xbe\x07Ek\xabm\xf0u\x9e\x8cR\xc8\x01&h\xca\x98\x9d\x8f\x1eA\xf7\x7f\xc4\xcd\x1d\xf2\x02E\xb9\xd3\xc5 \x15\xcf\xbaG\xd5\xdf\x9f\xde\xbd\x13\xbf+\xbcv\xf3R7\xac\xb4\xad\xb9uL1\x10Y#\xe0T\xcc\xc1Q\xdaZ\x8d\xe9:\xa6 \x0d\xd3\xb1\xa6%\x8f\x84Q\xe8{$h\x98\x01\x14\xbdv\xffG\x93J\xb3~5\x12D74\xf6HB\x1f\xd02\xaeK\x9b\xc6\xb3\xf5\xfa\xc1\x8d\xe3\xa2\xb6i\xdc#+\x1a<\xb4q\xfd\xc8m\xeb2\xa7\x0b\x92\x05\xe9Iz\x17\xd01tsxu\xff\xe5\xfb\xfd\"\x8a\xfe\xa9\xfb]c?\xd5z\xbf\x97\xf6u\x1agT\xdd\xc7\xa7\xd5\xdf\x1f?\x1d\xca}\xcd\nv\xd4\x97\x17$HJ\xb5\xdf\xd4\n\x0e\xde\x9d\x1c~)]\xb0m\xe4\x87\x0c\xfc[\x12\x90\xeeT\xa4\x13\xf81\x8a\x02J\xc2\x19\xef\xa3\x96\x9cN\xb2\xa12\x03\xed\x17\x93\x1b\x1dQ0&\xc8\x95\xf6\xa00\x91\x00\x1a\x83X\xa56\xdbXG#Z\xf5\xc5\x81=\x96\xeb\xdd\xa6/\x1d\xc9h\xd7\x97\x9c\xd7\x1b\xc3\xbc\xfe\x1d(\x88)C\xe2\xee\x03\x93\x9c\xd6\xb2\xa7\xed\x14\x03\xd54D\xda7\xb4\xa74$\xbfUI]\xa4#u~\x98\xfe;P:\xae\xb4Q5\xd8Z\xcc\x89\xccn\xf5\xba\xa8\xde \x95'q\xa3ylw\x83\x1bB\xf1[\xd4i4C\x19\xad\xdb\x13y\xdesY\x8eN{\xbdh\xe6\xf6\xa1;\x14\x99\xfe\x8d\xe29j=z\x82!\x8b\x1b=\xbfp\x14\x17\xbcQ\xb5+S\xfb\x90\xbby\xf4z\xa4\x9fb\xe6\xb7\x959\x8ev\xddA\x1a}b\x02\xe9+\x92PG@\xa2\xb1\x9a\x0526\x1c\xab\xc8\x85b*\x15I&aO\x0f\x02\x9f$4\xb1\xe1\xe2t\xb3\x0f\xdd\x0b?\xecjR \xe4\x98>\xedC7\xf2R]\x95\x1c\x8e\xd3\xd1\x10\x13Uy\xbaZ%\x88OG\xbb}\xe8^\xd2\xdb\xee\xf7\xbd\x0b0\x8b\xb5\xe5b_\x08\x90\x1f\xe9\xf2\xf0v\xedt\x7fw&\xe3\xe9Fo6q&\xe3\xe1\xfdt\xb4\xf1l\xc6\x8e\xd8\xf3\xd9\x0f\xae3\x19\x9f\x9d\x0d\xe4/VaJ\x0fgXY\xa4\xc4\x9d\xdc\xe7\x15z\xda\xc7\xc5/\xd1\x8c3\x19\x97\x0f\xf2\xa2\x07^\xf9\xecl\xe0L\xc6~\xb8\xb8\x7f\xcb\xfe\x1d\xbdq\xefyQH\xc2\xfb#rt\x7ftp\xe4\xba\x7fV-\xef1.?&\xedU:\xa7O\xcczB\xad\xf0\xbc\x08\"\xf2]\xc4gU\xbf\xcdoF\x18\xa5u:\xbe\xe0`\\\x95\xf9\xa1S\xd5zo\xf6\xcdy\x1am@\x189B\xd8\x07\xc9G\x08\x03\xe4\x1a;2H\xa3w\xd1\x8d\xdc\xd2\x8c\x97\x80 ;\xc8\xc7 b\x00Og}\xe8\xf66\x94+tdX^\x8a\x13\x86\xdf\xa1\x16\xccH\x1fX\xcdE\xc1{\x08\x0b$\x98\x88\xc3l\xf0\xe1\xf8\xe4\xed\xe9\xdb_\x0f\xcf\xdf\x1e\xbdy{\xf4\xf6\xf4\xaf0\x96\x8f\x8e\x0e\x7f:\xa8>\xea\x0eB\x12\x16\xcd\x1d\x91#\x18CZf1\x04is\xd2/\xe33\xa22\x9f\xf1\x86!\x8e\x95\xd3\x10\xb6w1\xe74\xa2\x07t\x95JN#f\xaf\x9b9\x8d\x10~`|\xf3\x18\xbf(\xa3J\xff\x9dx\x0d\x873\x1b\x9d}\xee\x8d\xa1\xe15\xda2\x1b%Bi\xc2\xf8P\xaf\x1c\xf2\x93#r\xc4\xfa\x82\xe4\xc6O\xbdKp\x8c\xca\x03\x8f$T\xd5D\x8e\xb5\xb5@\x01\x0e\"\x9f^<\xe2\x8d\xe5z\xdc6\x8d\x1d\x1d\x1cY\x1b\xcb\x15\xb5\xad\x1a#G\x1a\x8dl\xe1\xf8l\xdcnB\xeb\xf7=\xa0\xc5v\xfe7\x83\xd6\xdb\xa37\xdf\x0eZo\xc3E\x1bh\xd5)\xd0\xf7\x83\xd6\xc67\x05\xd7\xc67\x85\xd7F#\xc0t\xbb\xbdx}8\x18j\xc6\xa2\x9cKe\xbe\xb7\x0f$\xcf\xe95\x810?\xa6\xba\xb4\xcb\x0e\x14\x1e\x083\xb4\x11\x93\x7f\xd6mC\x8d\xff\x8aj\xfcW\xce\x1e)\xff\xb9\x1b\x8e\xe9\xc7\x9f\xbb\x8d\x1c]c\x8b\x93\xca/\xc6\xbb\x9d\xa6\xb3\xfb)\x9c\x9d\xa5\xb3\x9e[z8V{/\xfd\xe0\x0c\"/\xf9\xc1\xe5\x1c\"\xb6\xf0\x83\xf3\xdf\xf7\x0ec\xc6\xdcj7\xa5\xf7\xdd\x89\xebNJ\xac\\\xab\x1b\xdd\xd4_\xd1$%+\xa3)\xcb7\xe7\xd6\x8a\xb0\xe5\xd1\x80\xdeRO0my\xa9/K\xbf\x03\xbf\xa6\x89\x87b\xb85Y\x0b\xf7L\xfd\xb9\x97\xdf\xe0 \x0b\x96\xcf\xc3\xcd\xb9\xb2b\x12j\x9erW1\xf3>\x8c\xe3(v\xba\xafIJs\x9fZ\xca\xcat\xc1\x99|\x91W\xb4\x97NG3\xce\xfc\xf4\xd2\xe9\xe6\x8c{-\x11\xfesk\xd6\x87N:\xdd\x9e\x15f\xb0\xf4\x06X\x07\x0e\xfbo\xf0\xe9\xf4\x95#\xc0\xa0\xf3\xc3\xf3E\x98\x8a\x1ek\x82G\xa9\xe8\xa5\xd3\x9d\x19\x8fO\xd1K\xa7\xbb\xb3>\xa4\xd3\xbd\x99\x89\n\xa3\xca\x15\x03\xdfN\xf7f\x82+\x1d\xf6a\xcb}\x0e\x8b\xc2\xa7r\xeb\xb9\x0b\x0b4\xf0\xd3Q)l\x87u\xb7\xa8\xd3?\x13z\xa5\xd3g3\x04<[\xb3]\xba\x0d?\x80\xb3;\x84\x1f\x10Z\xc3\x19\xf4\xa0\xe7\xa4\xd3\xd1h\xc6\xd0l(\x95\x80\xb8 \xea\x9b\x1bkW\xc4g0\x82M\xc1\x9e\x85\x8bQ\xd5\x1f=\x02o\x90\xd0\xf4\xd4_Q\xc7\x1b,\xc57\x1760\x88\xa6gCa?LR\x12z\xf4x1\xc6\xeeZph\x96M\xc6\x88\xfa\xdb\x93cA\xd7\x8d\x8e\x00\xdf\x8a\x10?\x90\xcc\xf0\x04\xfc\xdf\x8f\xc4t_\xbcP\xac\"L\xe6O\xdf\x0e\x0c\xc5\xcf4\xbe\xab\x0c\x8b\xc3hg\xdb\x1d\xfc\x88\xb6\xc2E\xaf\xe0\x11dd\xd8L>\x97\x1a\xb4(\x18\xba\x07?\xbez}\xf8\xe6\xa7\x9f\xdf\xfe\xe5\x97w\xef\x8f\x8e?\xfc\xd7\xc7\x93\xd3O\xbf\xfe\xf6\xbf\xfe\xfa\xdf\xe4\xc2\x9b\xd3\xc5\xf2\xd2\xff\xe3*X\x85\xd1\xfaoq\x92f\xd77\xb7w\x7f\x1f\x8e6\xb7\xb6wv\xf7\x9e>\xeb=\xd9?\x0b\xcf\xe2\xee\x03%x\xae\xe4\xf9\x1e+\xf6\xc57\xe0\x06J\x1d5^\x8e3\xfa\xe8\x1b\xae\x88B\x1e\x030\xe4\xbeC\xa1\xed\x9e\xa8\xe3 i'\xb9\xfcK\xa5\x19;\x8f\x06\x08\xbb\xdb\x8d7G)\xbc\x80a\xab\xdb\x1f\xd4\x8b\xefj\x1f\x1b)a\x0c\xff\x01OQ\x01]\xc6\xfb\xaf>:\xa3\xb2\x02cz\x16\x9f\x85\xfb3\xa1\xc60\x03=\xb2.K\x86\x91\x80\xb4\x8f\x12\xf3r\x07\x86;\xa1\xdc\xd3{\xf8\x1c\x18\x94\xc9sH{=\x17R\xf8\x0f4\x05\xe3*\x13~\xa5\x13\x88L\x11\xf0\xf2%\x8cv\xe1\x11l\xee\xec\xb8}P\x8b\x9fVK7wv\xe0\x11$\x8c\xec'\x98\x0e\xe4\xc5\x0b\xd8\x85{\xc8rt\x88$:\xa4\xba\xe3U,\xd1\x10dH\\\x82\x03\xfb\x01v\xf1\x9a\xe6\xab\x86\x04c\x18=\xcdu=\xe5\xb6\x86\xda\xb66E)\xbe*|\x0f\x19h\xd4:\xdb\xf9\x9b1\xa6\xdfX\xc4\xd1*\xff\xe2\x04(\x16 \xbd\xc7\xaf\xdf\xd4~\x15C|0)\x87S\xd0\xf67'm\x11:\xe6n.F\x82b@>\xd2Hk2\x0b\xad1`\xe7V\x05;q\xe7g\xd3\x08\x97\x8f-\xfa\xee\x16\xf2|J\xe9\xa6\xaet\xb7R\xb8\xbb\x05\x8f\x00Mr\xd8\x8c\x9c\x88a\xecS\x17z@\xa7\xa9\xf9R\xb5\x8c\xa0[\xfc\x0e\xf1\x1b\x8f\x08\xc6\xb0Y\xa0k\xa9\x9d\xa1\xae\x9d\xedZ\xe1\x8b\x17P\xedqw\x1b\x1b\x1e\x15\xc8\\j\xb9>\xc0\x17/j\x0d\xefn\x97\xdb\xebC\\F\xbc\xfc\xd7Ws\x10f\x89\xb6\xa6\xff+\x87\x9c\xacs\x08F\x85\xe1\x03\x99\xb4\xc8\xe2\xd1`\xf0\xea\xf8\xca3\xdfd\xcf_\x91\xd7\xb8*\xdcx\x1cP\xdb~\xe3\x97\xd2A\xee%\xccv_\xf8\x9c+\x83\xcd\x1ed\"uh0MgE>\xb0\\]\xcb\x01>\xeb\ny\x15\xd5\xb2q\xb3Q\x87\x88\x89\xe3\x87\x10\xdb\xadx\"\xd1$Jj\x16\x8eB\xd6\xcf\x1a\xbb\x96\x9f/\xb2\xd6A\xe6\xa7\xb9\x0fVM\x98!$\xf9\xa1H\x9a\xc1\"\"[\xb4\xca\xdf\x91#Ny[~!\x83S\xd7O\xfc\xb3\\\x8dZ\xec\xfa/\xdc\xc4k\xe2\xc7\xc9\xbf\xd7.\x16\xbe\xbb\x96\x9dJ\xc4\x8c\x0e\xe2\x98\xdc9\x99t\x81\xcco{\xd8\x16\xce\xbel\x0bg\xb8\x85\xf5[7j\xbdu}\xf4\xe7G\xc3!\x85\xe2^\xd1\xbb\x84\xbd]u\xf17\xb5B\xa6\xe9\x8c\xd12\x7f:d\xe7\x0c\xfe\x9d\xcd\xfe\xe9hoXG\x1dW}]\x0d{&R\xd1\x18\xd6\xd1/\xad#\xd1\xae#1\xad#[-\x82\xab\x15\xd5@\xdc\x07_\xc0.\x12\xb0\x8b\x10vF6\xc6\xff7\xd8\xc1\xe5s\xfb\x81\xfb8\xa1\xc6\x0bt\xbdw\xe1\xf7\xdb\xc4\xd6#\xd6\x0f\xc1\x10\x08L9\xc9\xc2\xbe\xb0D\xccIm8Mg\xd6\xfd\xf2mQ\xdeD\xe9\xff\xed<*\xffH\x9ed\xe1\x9c.\xfc\x90\xce\xbfR\xfbb\x81\xc3\xc3\xa1\xea\xd6\xf2\xcd?T\xa6\xbb\x8e\xfc\xb9\x8c/f\xeb]'\xcd\xd94\x7f\xffn\xae\xd1\x7f$Ob\xba\xa4\xb7\xdf\xe5F\xe5\x01\xca3\x1f\x03\xd5`\xbd6\xe7S\xeeW\xa7\xe7\xb3\x19\x11xr\xf6\xc4\x99.\xfd\xd5\xec\x07\xf7\xcfO\xe4\x05\x87\xbez\xac 9\x00\xd2z\xfa\x89\xd4\xbe\x0f\x8dw \xfc\xc2C\x9a\xf2\x86\xd3\x11\xcab\xf2\x16\xe1%\x93K[\x9c\xd8\xac'4\xeb\x9d\xa6\x85!P\\\xb2 *\x9a\xa9\xb5\xf2\xbd\x8f\xe1\x7f\x0e\xc4\xe56Q\x80\xceo\xe1\xaa\xd0-\x19\x13\xf5\xc1\x001\xbc\xd0*.H\xd3~U\x96\xf9J*\x913j\xbc\x83\xb6&1\x0f%(\xd6\x05a\xb0\xea\x01\x1d$Q\x16{\x14z\xac\xc0\x08X:X\x06\xd1\x05 \xc4\xd5_o\x1f\xbaK\x1e\xb9\xaf\xc8D_\x11\xf5\x9fV\xca3\x9b\xd2\xaf\\5i\xd6.\x94_\x08`\x1f\x9eU\xc8 \xec\xc3\xa8r\xad\xb5\x80}\xd8\xda\xac`\x03+\xdb*\x97\xcdY\xd9v\xb9\xec\x92\x95\xed\x94\xcb\xaeY\xd9^\xb9l\xc5\xca\x9e\x96\xcb\x96\xac\xac2\xbe;\xd8\x87\xed\xcaX.XY\xa5\xdfsVV\xe9\xf7\x06\xf6a\xa7\xd2\xc7!\xec\xc3n\xa5\xbd[VV\x99\xdb +\xab\xf4\xf1\x8a\x81\xaf\xe2\x93x\xc5\xca*\xef\x1e\xb0\xb2\xddr\xd91\xe6/\xacT\xfc\x80\x85\x95^N\xb1\xb02\x95\xf7\xb0\xafA\xfa\xe1\x18\xbaggC\xcdQ\xb4\x87O\x88\xe6\xc9S|r\xa1y\xf2\x0c\x9f\xa4\x9a'#\xdeQ\xa8{4\xc2G\xd7\xbaG\x9b\xf8h\xa1{\xb4\x85\x8f\xaa\x0c\x1d\xfbl\xf2\xa1Wu\xd1\xec\xb3\xb5=\x86\xc7gg\xdd\xc7\x9a\xb1\xf3\xbe\xce\xce\xb4\x9d\xf1\xde\x8et\xcfv\xf9\xd4\xceu\x90\xda\xdc\xe2\xad\xbe\xd3?\xe4\xad~\xa8(\x1a\xcaU\xdf\xb2\xf3\xba{\xd7\xedC\xf7\xaf\xec\xbf;\x9a\xe0w\xf1\xe7\xf0\x84\xfdA\xb6\xb7{\xcc\xff?b\xff\xe3W\xfe-\xc2\xaf\xfc\xffc\xac\xbdX`E\xf1\xe7\xcd\x9b\xeeL\x17U\xe3\x8f:\x9d,\xb4\xb6\x95\xabhn\x82\xb2ou-\xeb\xf3\xc8\x19\x9b;;.\xe7\x85n\xbb<\x80\xeff\xb9\xad\xdc\x1a\x19\xab\xef\xee\xecl\xc9\x172\xf1\xc2\xb6\xe6\x05=\xd7\xde\xe1\x8dlo>\xdb~\xb6\xbb\xb7\xf9l\xc7u\xcb\x11q\xbdhNa\x1d\xf9\xa5\x8c\xb9<\x00\xe2\x8a\xdc\xc9L\x0c\xcb\x98\x92\x94\xc6<\x19\xc3\xf0\xf6\x8d\xf8\xe8X\x07\x1c\xe8'1\xd0\xa7\xe5\x95-\xfd\x92\x87\xde\xd9YW\x84u,\xe28\x0e\xf1\xfd\x8d\\Vv\xa1\xa7\x08p\xba\xc8%G\xf5\xc5R\xa2X\xf3x\xe1y\x98n_\x06\xc9\x961\xa7\xdf\x93\xf4r\xb0\"\xb7\x0e\xa6\x0c\x17\xc5\xf7\xf7\xb0\xe9\xcah\xdfW\xfe\xfamxM\x02\x7f\xce\xdbR~\xab\xa1\xb9\x17At\xf3\x8e^\xd3\x00\x99X?9\x8a\x18L\x97\x0e-\x9e\xb8\xd2\x17I)\x93\xbd\xa4w\x81\x08\xc1]:YMLu=%p\x93Ym\xe1\xdb\xff\x8f\xcf\x06\xcds(\x12\xa2pk\x0d\x9e\x845\xae\xdc\x1b\xa4\xf9\xd5\x0c\x8f\x04\xe0?\xe7ARG\x90\x89\x86X?\xac=\x91\xe4!\x18\xa8>\x97}\xc8xg\x19^\\\xab\x8f\xa6\x19\x1b_8%3\xd8\xaf\x06\xc3\x05E\xcd]\xc6gGA1\x868\xd8b\"\x0d%s\xdc\x89\xe2\xf4\x17z\xc7\xb3\xcf\xe4?\xca\x01\xddC\xfa\x9b?\x97\x01\xd5\xf3_\xf7\xf7\xf0T\x86C\x0f\xa3\x8ft\xc1\xdb\x10_\xd5\x16\xc2\xe8U\xb4Z\x93\xf4=\xdb\xce\xbc\x8eR\xa0\xd6\xf4\"\x86\xdd\xe8zu#@\xa9\x14\xa85\xbf \x84\xbcLOd{\xe5\xf0\xb6\x1cu\x1e\xd3`\x85E\xe4\xfaR\xb6F,\x99g\xec\x0d\x92Ra\xaf\xc0K\xb3\x84\xce_\xabOJ\xb1\xfet4\xe2\xa3v3!\xd2\x8b\xdd\x14\xc1~%\x9al\xea\x8at\xc6\xfc~nc\xc4\xf1\x9a\x8d-Q\x83\xa5\x81\x0f/ y\xeeb\xda\x064`\x97\xd9\xfa\x85K\x1f;\xfb\xc1w\xd1\xec\x87\xfb\x8a\x88\xac\x16\xa2\x83\x04\xb3\xbd\x95\x9e\xb0.ydW\x1f\xad\x86\xf8\xf7P\xd5C\x9c Q0\x14x\xdd\xdb\x87\xc8eC\xec\xedW]\xcb\x04\ngV\x10\xbd\xb6\x85\xe3\xd6\x87\xdb\x95\xe4\xf2\x07H]k\xdb\xef\xea$Z\xca\x1c\x08\xb1\x05\xc3>\xfe\xd5\xbe\x8e\x9f\x8c\x0dmm\x96\xa3T\x8d6wQ~\xdf\x1dU\xc3`m>\xdba\xbf\x18\x87RxP0\x96D\xfc\xba\xbf\x87\x9d\xbd\xad\xed\xed\xf2{\xec0\xdeb\xbfx~\x8a\xbc*+\xdf\xadt=\x1am\x8fF#\xebD\xfef\x9c\x08N\xb1\xd2\x0f\xb6\xcc\xbe^\x14__\x15_\xaf\x8a\xaf\xc7\xc5\xd7\xd3\xe2\xebM\xf1\xf5\xd2:\xac7\xc6a=\xf9\xfd,\xfc\x01dT\x13u\xb9\xe57\xb6\x91\xfe^\x0f<\xf2#cs\xcaE\xbf2Y\xa5\\\xf43\xe3m\xcaE\xbf\x01\x06\x99\xae\x0f\xf2/\xf6\xd0\xebl\x1c\xbej\xe7\xd4\xd1\x84B \x0c\xe5\x0b\xdc\xe9<\xeeG\xfd\xe9{N\x07j\xe5\x8cS\xfd$\x12\x92\x96r\x96TV\x12\x83\xf3t\xde9\xfc0\xca\xb0\xec\xbc\xf8z[|\xbd)\xbe^\x14__\x15_\xaf\x8a\xaf\xc7\xc5\xd7\xd3\xe2\xebe\xf1uU|\xbd+\xbe\xae\x8b\xaf\x1f\x8a\xaf\x87\xc5\xd7e\xf1u^|\xbd.\xbe\x9e\x14_\x0f\xc4\xcc\xcc\x89^49\x1f\xd2\xbaJ(7y\x18r\xba\xaaP\xd9^\xcfv\xb3\xd5\xf9$\xc8\xae\xd2\xbf\xafD\x05\xfaM\xaf\x04f+\xf7\x96\x8d\xfdoZc)\x13\x83\xfd\xc5\xc3\xd4\x0e\x12 \x9f\xe7rd\x1d\xf6a\x01hQ\xcdX\x15\xe4Ya\x03\xde\xe3\xe9\xf2\x92[\xf1vA$\xd2\x9c\xbeg'\xc3\xac\x8f\x88\xe9\x1b\xf4\xdc\xb9P\xc1@\xf4\xb5\x00\xd1n$\x1c%\x0e\xbaq\xa8\x7f2\xb7&\xc6\x85\xdcM\x00\x13\x08\xe1%<\x83\"\xed\xd2o0\xc6\xf2\x9fa\x0c\xbf\xc2\x98\x8f\xb2\x13\xf1\x87\x7f\x871\xfch%m\x7fU\xa8Fu\x85\xe8`\x9e\xadJ\xbc\xb7\xe9.\x84\xdf\xfe\xa6\xd5\xdb\xdf\xee\xe3\xc7\x86\x9b\xd9N\x85!\xe3\xa1\xfd\x19H\xde\x16!\x08\x14W\xd3\xc7\x18\xa0\x1dz\xec\x9b\xfeF\xd9\xcf\xb9\x0b;\xe9\x94\xfc\x17'\xed\xf3$\xc6\xbeH\xdeL\x14\x85\xa3\xd1eY\x80\xb0Q~\x92\x1f)G\xe97\x02\x94\xdcYd\xc0H}\xa6\xd9\x90\x87D\xe3\xd9\x82\xccv\xa8 p\xa2\x9ah6\x9c\xe5\x19H\x15T0\xc5n\x04\xeb\xbd\x0d@\x9e$\xa9\xbe{\x8d\x96\xaf\xe8Q\xfd\xf7F?jM\x06{\x90o\xff\xd8\xf8\xb6\xc0\xed\xc2\xe7\xe51z\xbb<~\xdcuM\xf8\x0e\xb2\xf5_\x9b[\xbfg\xad\xff\xc2\xf3\x04r\xbca\xcd\xfe\xe4|dE\xbe)M\"\xb6\xfess\xeb/\x8d\xad\xb7\xc67(\xcb\xee\xb0\x0fO\x9c\xb3\xb0\xe7:\xd3\xdf\xcf\xc2\xd9\x0f\xee\x93\xa5~W\xa9\x1f\x94\xc9\xb3\x9a|\xe1r\xd9DP\x96\x0c&\x90\xa1\x9aA\xb8U@4\x08H\x92\xbeeo\xf0\xfc\xe0\x7f\xce#\xd3\x0d\xfb\x98\x7f;u\x0d{Z\xfd\xa0\xa8~\x16\xcaP0Ct\xffd$^\xfe6c,\x88\xc9k$l\xf5#b\x0c\xc6\xaa\x0b\xb01\xc1\xa7\xfaam'\xc0\xc3\xbc5O\x04\xc4\xc9\x15O7\x1b\xc6\x0cyJ\x18>\xcb\x00o\x80|\xb6\xd3\x13\xe81Y\x0f\x13\xdc38\x88\n0a_\xc7<\x9f\x1d\xf4\xe0\xcfN\xc0\x85I\xbc\xb5\xb0vf\x8ey \x05*\xfa\xc6J\x9f\x19z\x12\xb7 \xdb\x7fk\xc4\xf6\xc7\x98\xac\xa4\xf9~O~rA\xba\xe0\xca\x85\xa4l\xe4\x91\x84\xce\xb4\xc2\x08\xbd\xe4\x02\xda.\xa0\xe7\x0e\x13\xd7v\xb7F\xc8\x04\xd4\x83\x95\xfa(\x15\xf3wv\xb76\x87PD.\xdd\xda\xdeb\xc26*\xa6\xfepF\xc3Mt`Na\x83\xb7\xce\x93\xc9l\x88\xd7z\\\x86c`c\xbc\xdb\x98\xeb\xbc\xde\x0b\xab\xd9\xde>t\x90\x93\xf9\xe4`Zh:\xf5g0\xe6\xa7\xdc\x1fz\xb74\xf5#\xafSmk\xe6\xf2\x8c\xa2\xfa\x86D \x08\xf3\x92\x95t\xba\xfej\x1d%\x89\x7f\x11\x08\xc7\xf71\xf8BU\xc9\x8d@x \xb2n\x13c\xf7\xd9\xb1\xcb\xf3\xbf\x983K\xc1\xbe\xe4\xd7\xa4\x02\x10\xe3\xafin\x01\xe221)\xc5\x95\xd2\xea/B\xb6\xdfx\x8em\xfd{\x9b\x9c\x1e\xe5\xcf\xd8(\xba\xbd..\x97\xdc\x94\x1b\xfc\xb09\x0b\xbb\xd6\x19\xfed\x14\x84MCf\xb8Q\x90\xd4\x8d\x11\xa6\xf7\xb4\xf6\xf1g-\x14\xd1\x1aAq\xbcV\xc9k\xce\x1bTl\x87UE\x96\xe2CY+:\xae2\x90\x85*\x9d\xc0\x0b\x08\xd8\x1f=\x07\x89\xa2\xa3\xe31)oJf\xee\xa0\x88s\xc0P\xc4\x1b\xe4\xf6\x06\\\xcb\xdd\xf1*5\xba\xdc\xbc\x80aR\x9e9\x90\xd3XY/Z\x80\xfaR\xdeN\xder\xa5#F\xfal\x82.\x95\xea]\x98\x80\x87\xdf\xc7\xd0\x9dt\xfb\xe0\x0dr\xbb\x04\xdb\xb1\xc2\xdaXp\x95\xa8\xb8\x1a\x99b33>\x0e5>N\xdfh>\x91\xf1\xbb\x00\xb5K\xee\x13\xa1\x94\xb03sa\xa1\xe2\x06\x0d\x80\xfaA9/\xa9\xf5\x85\x11-\xca\xf4\x99'\xe8\xf7D\x82\xfe\xc7/1k\xbf\xe0\xfdc \x9eG\xd7i\x82Wo\xfc\x04\xe6i\xc2\x10\x02\x8f\x9bN\x9a\xf2\xb4\xa6\x8b\x19\x9f\x99\xf9\xe41OY\x8a\xc3\xb1\xb6\x8a5\xfe\xb4\xc6&K+\xe6w\xec\xfa\xd1\xffU\xd2\xf1\xf1M_\x95\xd9\xd5\xfb\x83|\xc8a\x9fo\xe5\xb0\x0f\x9d\x11F\xc1\xc9\x7f\x0e5\xd9\x82\x13\xc8\xb1\x847Q\xcd\xdb\x9a\x13?U\xa4}\xc1#\xc4\x95\xa5\xdcjVS\xd6|\xd0\x87E\x1f\xed?\xea\xdeR\x0cAQ\xd9\x91?B\x17\x1f\xf9\xa4\xae.C\x85\x9d\xa3h(\xc5\x8dXqI\x92\xcb\x04\xa1\x8b7f\x85o\x06\x02\xeb\xd1#\xb6\x05\x95\x02T\xdb\xdc\xdf\x83P\x84K\xa5\x02\x12\x86\x97 R.\xfb\xa8*u\x85Z\x8aVn_\xa6\xc1\xcc-\xa0\xdf\xfd!\xa6\x8bs\x86\xe3\x15\xf1\xderQ\x8d\xd3\xc2\xb6;\x9a\xc6q\x08\xba\xf2}\x9eR\xdc\x00W\x97\xaf\x1c\xcf*\xab\xde_\x8aU\x96\xc7\xcd\x04\x9cN\xcd\x96I\xa3!\x92\x9f\xb2r\xb9\xaf.\xb0\xc5\xa2\x95\xdf\x1c\xa7\xc4\"\xe0]V\xeeYM\xb9\xf1\x91\xd6H\x1f\x04y\xa5\xe8\xc2%~w\x9aT\x80J\x0e\xd9\xe2$\xd0\xb4\xa3\x145\xb4\xa8\xbe\\\"u\xf9u\xe7*K\xd0\x92\x80\xc0\x05O|\xc3\x13\x98\xdb\x8c\x10\xa1\xa4b\xe5,\xc4e\xe9\xbe\x8d<\xe72\xd8\xc8E\x95=\x135\xc4\x823\xc8\xf8\x0c\xa9\x1d\x0c\x89$\xae\xb5D\x88\x89p\xca\x18\x9c\xcb\xa9?\x9b\xf5\x05\x8d\xe1\x96\x80\x19O\xcb\xce\xffq\xbc\xc7\xdd\xd5b\x07 \xe4\xc7\xbd\xc1\xbe\x15\x1e\x15L\xf0\x90\x89\xe0e\x1dO,\x1d\xd6,\xe77\x9f\x88 N\x13\xc6\xa8\x8a\xaf\xd0\xc5\x8d\xd7\x93\xaf0\x0e\x83S\x81\xd2\xdc\xd4\xa9$|\x1a\xc1\x17\xf4<.z\x1eC\x97\xe1uo_\xed\xdd$\xedHZk\xa2\xee\x89}&g\xe4K\xda\xe2\x14t\xe4QNG\x90\xc9\xe3\x9d3\xd9\xac\xbe[m[\xb5b#\x914\xec\xd3\xa0y\x9fz-\xf7i5\xa7\xb6\x97\xa3o%\xa7vV\xbf\x8a\x9f\xa0\x00\x8eR\x93\xa0`\xfc\x18\xc2\xbb\xddn\x1fq\x02\x95 S\xb6?\xbci\\`3N\xb63\xe2\x87_\x01\xd22N*\x8dq\x04\xcb\x8a%f2\x96q8\xc8x\xa3eF\xbd\x0e\x17\xaf\xb099\x14R\x1e\n\xb2\xe6Y{lR\x8f\xf5\xee?X\xaf \xeb\xbf\x11\xa3\x9a\xd0\xa9\x0b]\x05\xa9\xeac(\xa8\xa5\xf6`.\x1d-e\xf0~\xc9iRx\x00\xdb03\x93\x98i\xc16\xc5l'4\xd9\xe8\xa8\x84\"D[\x1d\x95\xe4)$4B\x12J\xcad\xa6%1\xc1\xb7\xba\x1b\x0c!\xc4W\x9e5\xb8Xy\xfb\xc2g\xca\xc2\x13\xce!\xcd\x9a\x16\xfd\x9fAF\x1a\xd6\x88\xb4X#\x85\"\x84&\x8a\x90\xf3\xbe\xd3xV\xdeA*1\xf091h\xd8\x8c\xae\xd0U\xb6\x82;Q7\xdc\xb4+S-7\xc2\xbe \xf0\xad6\x9cY\x94\xcc\xb7!\xd7(\x89@\x03I\x93\xf4X2\xd5k\xf4m\x84\xaa*-\x0b\xb98F.\x02\x8a\x9eT\x10-\x801/|,i\x048W$Kz!K/'\x95\xf9\x87G\x8f\xf8\xc5\xa4DbT\xe0\xd6\xc1]+i\xe2K\xca\xab\xc1\xc5N*\xc4\xce\xeeKu=\xfed\xee\xa8.\xd2\xe9D\xb5\xff2+\x03sm\x94.\xd4\x8c\xce\x1d\x87\xc7\xbb\x94-\xa3\xfb\x97\x89~*\xb4\xb3\xbe\xa2\xb9\xe5c'O \xa6\xd1\x80\x98}\xec7\x94\xc0\x14\xa1zO[Xy\x15ia|\xdc\x9c1\xf7ui\xbc\x85\x0fy\xbd\xd4\xed\xf3ce\xe0'<\xb4C\xaa\x89\xce.?Uf851\xc3\xd4I\xa7\xfeL@\xcd<\x12{G\xd5X\x11\x15K\xb8\xc8\xd6y\xc4y\xeb\xb0\xee\xc4\xca\xd0$\xe2dZ\xb9R\xf5\x0d\x97\xa8\x90\xaar-\x82,\x9a\xfa\xd3p6\xabL+\xd5\x98\x03\xe6\xe12b\xbb\xd2\x8fR\xab\"\x9b\xb5s\xc43\x02\xb0S\xe8\x1fUOB\xa9\x97V\xcc2q3\x84\xc8\x03\x85}6GZ\x9c\xb0\x13\x08%\x8b\x85\xda\xcbR\x0e\xf2b\xe7\xe5n\x9fr\xfbR\xaadh\x1f$dA_W\xac\x15,\x96{|\x8a\xf1\x80\xde\xa64\x9c;\xf5}\xc4m4\xc7@\xca\xab\x85'~et_\xe4\xf6\xa3z\xb1Z\x07,\x0d\xe9\xd5\xac\x07x\xd9\xd6q(\xecC\x8f\x9aC\xcaX\xa3\x99\xf3h\xe1\x97i\xba\xd6\x04\n\xe7\x0fo\x12C\x0cq\xd1\xdfS\xc1\xec\xd57T\xd1\xb8\xae \xd9zC\xf3\xdb\xdb[\xf6\xf6\x17\xda\xb1+-l\x8e\xec\x0d,\xa3\xf5%\x8d\xedm\xec5Lr\xe1\x07\xa6P\xebzs\x04\xeda\":\xf9\x16\x98%\x1d\xca\x1a\x83\xc4\xd47~d\xbc\xde\x99S/\x9a\xd3O\x1f\xdf\xbe\x8aV\xeb(\xa4a\xea(Q:\xcfzh\xb2\xc0\x18+\xcd\xceM\x07\xdc\x7f\xc2_\xdc5!{NT\xaa\xf1\x05$\xed\xd1\x9e\x8c\xdcQ\xdc\x0f\xa1\xcb;R\x9d\xcd\xf95\x0dZOO\xd0#\xde\x85X(6\xd1H\xf2\xd1#\x10G\x0f\x0dkS\x8cP\xb2\xdbG\xb6\xa0\xfe\x94'\xf03\xd0\xbe\\\xf4I\xd1O\xf2\x8f\xc8\x0f\x9d\xee\xa3\xae[!o}H\xb9go 2U\xb0\x94.\x92\xd1@b\xfa\xfb\xfe\xe4\xd1\xac\xe7\xeeO\x9c\xe9\xef\x8f\xb8\x95\x04\xae\xfa?>?G(\x86V3\x01i0\x159\xe8\xb4i6\x8fb\x156\xabg\x0b \x9b\xe2\x87\xfc\xba\xd7\x89\xa7\xfe\x8c\xb1\xc9-x\xa6\xf8a\x08^\xf8FnU}\x1a\xb9o\xe4\xde\xee\xb6\xd67rk\xb8\xa9\xf1\x8d\xec\x1e\xde\xae\xa9\x97\xd2\xb9\xaag+W\xcb\x14\xdf\x97\xf2\x93$\x7f\xe2\x87-\xc8\xb8\xe1\xcaL\xdc\x94\xf5a\xdd\x87y\x1f.\xfb\xe8\xc9\xa8\x89\x01\xba2X\xe2.\x0d\xe5w\xa8\xf9-\xafSE\xb5Yl\x8a\x92?\xf4\xe9\xdd\x9ar\x9fh\xa2\xe6R\x06\x950\\\xe8\xcf\x10\xb9+\x03=\x02\xe1\xddK\x1du\x04.\x04\xec)\xec\x8bh=\x1c\x10)W\x1a\xd3\x01Y\xaf\x83;'\xeeW#>}6\x0c\xf0\xdc\xech\x8f\x16\x12\xb0\x01\xe6\xfc\xedJ\xbc\xa0Kn\xb7\xf2R\x90\xa1P\xdei\xa0\xe8\xc0Z\xb9f\xcf\x16\xad\xc6t\xa35\x97dC\xa2\xb8\xb3t\xbbj\x01\xce\xb9\x9ac\xe3\x90\xed\xe0Z\xb59\xec\x83\x08\x05\x1fe\xa9s\xd3oa\x94\"A\x91\xc2\x068\x08\x0f{\x00\x88%L a\xdc\xdaB\xbep\xed\xd6\xf3s\x00ga\xabn\xdf\x06\x88\x1cZ\x1d\xad\xe7\n2\xa0Av\x00\x13\xb8`\xaf\x8c\xf9\x9d\x8e\x8a-5 M\xdf\xe3m\xd3\x1a\xe81\x97\x01\xea\\\x0bz\xb6Bl,$^f+\x1a\xa6 \x0f\xe4\x9f^\xfaI\x1fo+\xa8Ei\xc2^V\x90\xad\x10\xbf\x9b\x97\x0f\x14t\xe5\xbd\xd4\x91\x80 $\xab\x02fkmC\x9f\x1d\xd3\xc2\xb3\xd1-]u5\xea\xcd_8\x97m\xe4\xf0\xfa\xc6BSyG\xd7\xa8\xdb\xaf\x8cT{r`\xaa\x0bF\x85\xee\xefQFrB\xae\xfbA:\xd9a\xe7-\x99\xfb\xe1\x92g\xdap\x18\x95\xec\xae\xc8\xedo\xc4O\xbbty\xbb\xb5PS\xe5~p\xa2{#\x97u\xff@ *\xdd\xeb9\xe1-]B\x0f\xab\xac\x05\x82\xe43\xa1\xaf\x0f\x9d\xd8\xa9\xc4\xcd\xccs\x08\x15\x0c\":`\x8c\xc1#\xe1\xe3\x94\xcd\x0dH\x02\xb9|\xd9\xa9\xd8O~\xd6\xef\xd0\x1a\x80\xc6\xa0]\x14\x14-\xba\xe7\xe7\xd8\xfe\xf99R\xe4\x7f|\x86I\x15LZ-\xa89\xe8\x16\x8fC\xe7l?s\x1di\x15\x85\xe2`\x9f\x81vw\xe8\x0e\x16NUp\xee\x832\x0c\\\xbc>l\xba.\xeb\x7f*\xc3\xd9u\x1c\xaa\xda\x8c\xa1\x9aM\xe78\xd5\x14y*\xd5G\xcd6\x9e\xb0*0\x8cl\x87\xa8\xebK%\\\x8aFx\xf9\x9c\xd0\x1cM\xd0@\xf6\xb8\xae\x06\xad\x9a\xc1\xfe\xe33\xbf|\x19\x8b\x83\xa6\x82z\xde%\xf5\xae\xc6\x8aEv\xebM\xab\x92\xf5\x02\xe5\x8b\x8d\xdb\x82\xe8\x1b\x8f\x1d\x0fC6\xf0:\x0f\x1b\xd9\x97\xed}\xde\xdf\x18\xc7\xff\xcc}\xe0~oV\x1a2p\xed|E[\nx\xab2\xb4\x90\xad\xf7\xb4I\x88\x9d\xad\xbd-m\xdc\xa1\xa7\xba\xb0C\xa1\xb3]\xad\xcd\x07\xfft\xbbZ=\x10\xe5\xd5\x83\xc0\x13\xbdVG\xb9\xe0\xf5w\x86\xa5\xd3\xf0\x99\xf2+\x1a\xf8![\x1a\xa7\x82U\xeb\x1a\x19Z\xf8\xe1\xfc\xf5\xf1\xfb\xa3hN\xc7Ui6\xa6\xe1\x9c\xc6c\xf0\x07\xfc[e\x92\xe1*\xca\xc24\xd7\n\x1d\xa4\xbc\x11\x7f\xa0\x7fR~\xfb\x9a\xc6\x89\x1f\x85cH\xaa\xad&x\xc3v~\xc1\xe8\x05\x9d\x7fZ\xcfIJ\x931d\x83r\x89\xe15>\xd2\x93\xec\"\x8d)}\x1b\xa6\xd1\xab(L\x89\x1f\xb2y\x14\xc2\xabB\xa1\xf5\x91\x1a\xcf\xcf?\x1e\x1e\xbc:=\x7f}\xf8\xeb\xe9\xf1\xf1\xbb\x93\xf3\x9f\xde\x1d\xffx\xf0\xee\xfc\xe7\xe3\xe3_\xce\xd1CWk9e\x7fM,\n{\xbbU\xc5\x8ar>\x87\xe7iL\xa9.i\xf8\x92\xa6\xaf\x82(\xa1I\xfaV\x10\xe47q\xb4\xe2\xab\x12\x0f\xccO5\xba\x16\x8aK\xc6*\xc8\xcaM1\xc3@\xb9b\x18\x88e\xa0\xf3|\xcc\xfc\x02\x921\xfbR/\n=?`\xcb_\\h|\xaepH\xeboAL\xf6\xf6\xaa\xd1\xca$5\xa9\xeewNM\xf6\x9e\xea4u\xac\xbc\x1a\xdd,\x13\xe5U\xaa$\x88\xe1\xd3j\xbf\x81(\xaf\xf6\xcb\xe9\xc9\xde3==\xa9\x11\xc35'3\xa3*Y\x9a\xf3\xf2\xcd\xea\xe1w)\xcaG\x95\xf2kQ^\x9d\xeeJ\x94W\xc9\xe4R\x94W\xc1p'\xca\xab`\xb8\xe0\xe5[\xd5\xf6\xcfEy\xb5\xfd\x1bQ^\x9d\xef!*\x18\xdb\xf0n|{6\xc4\xce>D>\xeeP\xb8p/\x07\x87\xd74L\x0fW~\x9a\xd2Xl\xf0\x8f\x94x)\x96\xbf\xf3\x93\x94\x864vVn^\xf7C\x90-\xfd\xf0\xe7\xecB\xd4V\n\x8f\xe39\x8d\x1dR\xad\xfb)\xf5\x83D\xd4.Q\x0bga\xab\xcaj\x9c\xc6\x84\x91d\x12\xa0\x80\xde<\x82\xe4\xc7\xbb#\xb2\xa2\x9a\xfbC\xf69\xf1W\xeb\x80*\xd5\xc7pS\xa72\xecs\x18\xa64~G\xc9u\xb9v\xa6\xaf\xfd\xea\x92\x84\xcbrMCv\xb3\x13\x1a\x94\x07<\x86s}\xcd\x1f\xe9\"\x8a\xe9\xdbp\x9d\x95\xab\xd7]\xb4>#d~\x8e\x92\x02\xb8\x020?\xb1\xb5\xf3\xbd\xbc\xf8U@\x92\xc4\xf1\x8c\xf5O\xe9mZ\xa9|\x89\x95_\x1f\xbf\x97\xd7T\xa2\xaaR\xf2*\n\x17\xfe\x1235\xb4\xab\x99\xb4\xaey\xc1\x17}\xb5f%\xe5\xb1\x96\x0b\xdf\x10/\x8d\xe2\xbb\x16\xb1>\xa5\xc2\x81\xde\xc0\xba\x1a\x98\xb2\x80\xa68\xcd\xf3\x0d!\xc8\xf5iL\xc2\x84\xf0\x1e\xee4\x15\x7fd\xbc\x80\x1f.O\xd2\x98\xa4ty\xe7\\c\xa5\xda\xd8\xc3k?\x8e\xc2\x15\x0dS'0K\xf3\xf8\xed\x8b\xc8\xbf\x99F\x08\x00\xfb\x8cw\xa9\x03\xa8Kb\x9flxY\x1c\xd30\xed\x8eu\xf7 \xbc\xca\x9c\xa6\xc4\x0f\x12k\x15?a\xac\xcf\xdcV\xe7\xd2\x9f\xcfih\xab!\xfc\x02mU\xae\xe8]r\x19\xc5\xa9\x97\xa5\xd6\x01\x05\xe4\x82\x06\xb6\nq\x14\xd09M\xbc\xd8_#\x07e\xa9J\xb24\xf2\"FMRj\xab\x87\x92\x97\x1d\x06\xf4vM\xc2y\x03\x9cH\xb2\x8e\xd6\xd9\xda:=zm\x9f\xde*\x9a\x13{\x05\x19\xb5\xbc\xb1R\x82d\x8c-\xaf\xadj\x14\xfb4LI\x13,\xf1\xce\xfa2\n\xe64\xb6V\x8bi\x92\xd8\xc1\x14S2\x8f\xc2\xe0\xce^\xe7o\x99\x1f\xdb\xdb\xe1\xd3k\xa8\x13\xc5\xd6\x1drM\x82\x8c\xae\xc8ms\x1d\xdf\n\x1d\xac\x13F7\x8duRzk\x1d\x10I\xa3\x95\xef\xd9j\\d\x89\x15t\x81\x7fm]\xef\x98\x06\xf4\x9a4\x10\x0eF\x7f\x16\x0b&\x9f[j-crqa\x87?\xa3\xc2\xd7\xb8]i8o\xe8\xd4\x8b\x02\x8f\xf1\xe1\x0du\xd0P\xae\xa1N\xb2&\xd6\xe5\xf2\xa20\x8d\xa3\x06\xca\x884\xe6\x82\xce/\xac\xe0F\xcf\xe8\x15M\x12\xb2\xb4\x82}\x11D7id]8F\xf9\x82\xa6\xfe\xa2\x9b\xd0:\xecu\x94\xf8aB\xadP\x8c\xa3\x9bFH\xc7\xd1M#\xa4\xe3\xe8\xa6 \xd2 M\x13\xff\xef\x08\x99R\x8d\x8a\x00\xf6\xfa\xf8\xfdA\x9a\xc6\xfeE\x96R\xc6\x1a\xb2s\xaf^E\xf2\x1dy\x8d\xbc\xc2W\x9c\xc2\x8aFgX\x95V\xc4\xd5\x81^\xa3\xb3\xb7W\xad.e\xb0\xaap#e\xb0\xaap\x83q\x08\x9f\xf5a\xb4\xd5\x87\xcd\xbd>lmV,[\x990\xb6\xb9\xa9 \x14\x1d\x0d<\x12~J\xe8\xeb\xe3\xf7\xa8O@\xde%\xf1\xd9\xcc\x91\x0fE\xbd/O\x11Q~\x19\xc5\xb5R\xda\xfcjS\xf3\xc8\xc3+\xda\xf7\xd1\x9cb3\xb2\x00\xa4\xc3\xa0,\x18\xa8U\xab\xca\"~\xd3Zm\x9c\xf1\xae\xd5\x01\xb2\x07\x1d\xee\xb2\xe7\xd4\x0dk1\xf5\xbbHv\xc1V\x9f\xb8F\x05\xcaz \x14C\xac\x06\x9a\x07\xbd\x0dS'/u\xdc>\x8c\x86.\x8f\xe7\xa7\x11?+cu:\x1e\xc8HT\x0b\xc0\xec\xbe\xec\x0b\x86\xe4\xabL\xf6Z\x13\xa6{\x95G-\xc5t\xbc\xaf\x84W\x03\xe35K\xf5\x96\xdax\xd2\x17\x85\\\xa1\xe3\x00\xd9g}I\x12:\xffH\x97~\xc2\xf8X?\n\xe5\xb6\xd0Vg\x9f\x8b\xec\x82\xf1zc\xe8F\xa1\"\xb9X\xbc\x10<\xb2N\xb3\xb8\xfe\xca+^^\xb7\xe5\x87\xfa\xde\x96\x9f9]\xd3pNC\x0f\xd9\xdai7\x8d\xd6*\xda\x86\xf3n\x1fX\xe1/\xf4\xee\x03\xe3\"\xc4O\x862b\x98\xf8\xfb\x03IR\xda\xd5$\xe5\xab\xf7\xea\x95\x9a\xffN\x80\xac\xce\xa1\x1d,\xcbo}#p\xfe\x18d\xb1\x80\x92 \xb2\xaf\xa3\x9bP\x0f\xe7_\xe8\xdd\xa7\xb5\xf8\xfe>\xca\x12\x8aU\x1f\n\xe7\x93\x94\xc4\xdf\x0be_U\xba\xf9\x02X\xe3{\xdf\x15\xdabd\xff,xs\xc9\xf6\xfb\x03\x9c\xf7\xf3\x05\x10\xe7/~W\x90\xcb\xb1}C\x98\x97J*\xe3\xbb\x13\xaa\xbe\xbc07\x9b\xba\xd0^\xa5I{r\xad\xb2\x83[C\xe7C\xb3ZD\xd7r\xf7\xa2G\xc5\xab\xf2\xe1\xabk\x18gim:o {\xd0D\xd3S\x9b\xe3\x105\x19\xa8\x97@k\xa9\x84ki\xb7\x00\xd7\xc4\xac\xb3F0j\xb2\x1c\xd7ymhL \xafe\xde\xb7\x01W\xa0\x94G!:1\x05A\xe9\xceIJ\x90\xbbIa\x02\xe9\x80\xfd\xac\xdeI\x14#b]\xdd\xe4,Y}t\x87\x92\x8f5\x84\xa6\xcd\xfa\xba\xd8\x0e\x1e\x86l\xb3\x99FC\x13^\x82\xbaT5\xf2\xd6\x18\xf3k9\xa8\x9e z\xe39]\x17\xec\xbczX\x07\x87\xe1\xbc}\xf3\x82Z<\xac\x07\xfeR\x13\x9d\xe0\xd7O7\xdc\x96\x10\x85\x8fG\"J|u\xb8h=\xd7df\"1M\xd9\xc4\"\x92\xd3\xa3G\xca\x8e-\x07\xba\x16\x031\xf7\x8e\xab\xe1\xf6AI\x18^\x16\x08\x00\xf9a\xf6.\xc6q\x17\xe1{kMp\x1c\xab>:\x0c\xd1j\x8f\xe7\xa9c\xf2\xcd\xcd`I\xd3\xd7$%\x8e\xcb\x81\xb3\x0f>\xdawEQ@\xe7NTu\x05`X\xbd\xc0,\xc4E\xa5\xac\xd8\x03udO\\X\xf0]V\x8bsbp\x05\x95\x97\xd9\xe7Z\x7f\xfb\xdc\x92GDH\x91m\xb7qn\x8c\x07\xc4\xf3\xb2U\x16\x90\x94\x9e\xdeD\x1f\xd8\xf1\xfb\xdaO\xd6x\xf9\x9c\xe0E\xca\xc2J\x8dn\x1b\xf6;\xa9\xcf\xbf\x83\xd1\xa2\xe6U\x13\x9fo\xb6\xe3[m\xc7s\xa7\x1a\xb0F~\xda\x1c\x1c\xf2\x93\x1fF7\x97\xbew\x89\x8bp\x0d\x13\xbe\"cp\xee\xc4u\xd8\xaa\xa9\xabBd0\xf7\x95\x1bv\xe3\xfa\xea\x1b\x04\xe5&\x02Q\x1dc_\xdf\x15C\n\xf5\xef5\x86\xd9S\xf6]3M\xc1\xad\xdc\x82\\0d\xb81\xad,:5\xd4\x17\xb6\x88\x0c\xd7\xf1\xd8\xdc\x04\x07cj\x05\x14\xc0)\x1b\xbb\x11z\xfe \xa6\x01% un\xdc~~\xe0\xf5\x0d\x01,\xf5\xae\xce\xeda\x06\x0fBu.O\xb6Z\xabo\x8e\xe1\x8f\x1eA\xa7\x85iD\xe5m\x87\x0e\xbc4\x0e~\xa1w\xb8\x1ayJ~\xd8\xd0\xd1\xa2\xcf\xd1s\x80\xf2\x83\xf7\xba\xf9\xbe\xb9t<]XD\xa8\xb1\xa8\xf8*\x1b \xba1\x8b\xdcQ\x1a\xda\xd6HX\x01J\x810\xc1\xaa\xac\x96\xbc\x0d\x1d\x9c\xdf\xc4d\xbd\xa6\xf1I*\xb2~\xa4\xe5\"\xf3\xd5\x01gT0\xd0\x980\xd7\x0d8\xaf\xd3\x0d\xb3\xd5\x05\x8d\xf3\x95c\x0b`\x19\x0b(\xacw\x97\xe7\x8c\xc3\x03\xcc\xdc3`\xf4\xb5%Ms\x93TG\x9cyn\x112\x17\x1d\xefk\x15\xb4+\"?\xfa{\x8dz)\x9eB\x81\xd1\xe1D\xafp}\x8f\xa5_)*\xef=\xd595\xab)\xde#q\xa4\x8a$\xe2V\xb4i\x197\xd5@\xe0\xf8\xe5\\L\x17\xf5\x85\x928\x18\xd60\xd7\xe2\xce\xaf\xcfV\x00\x13\xa0\x0e\x0f8\x92]\x04\xbe\x97SMd\x02\xe2\x01\x99\x17n\xa8\x07\xc9G\xba8\x8d0m_\xbf\x1ab\x0bp\xe1B.\xc8\x0d\xce\xa3\x9b\x90Vc\x96\x16K\xc8\xc4\xb7\xe42\xca\x02!\x06\xb5\x81\xa6\x84I]r\x03\xa9\xae\xac]a\xe4\xd0\xa7\x06\xe8c\xb9\xc8\x86\x16\xd3\x85LL)\x86_\xbf\x0f\x89\x8c\x03\xf0\xb5\x03P.W\xecX\x90\x13\xcb\x94\x8f\xc3\xc7\xafb\x1c}\x08\xf1m\x0c#\x9eG+,\xde\x8e\x90\xc0\xf1\xbdY\x062g\x89\xdb\x80\xf7\xff5\xc8\x8a<;\xe2fLW\xd15-\xa3';\xf9\xbf \x82~\x075\\)\xe2\x80Q\x03iP\x8a\xfc\xe6\xc1^\x0b\x13G\xedR\xa7\x91Xh\xf3\xfb\x1e\xe6\\\x9a@d\x89\xfc\xe2\xac\x8d\xc1V\xd8\xe73_\x81 W8z\xe6!\x8b\xf0\xa0\xfb\xfb\xe0\xb5\xc4\x94\xb9h\x16D\x92\xe4\x04\xc6|\xb05\xf5G`\xb8\x96\x07\x19uD\xb4\xe2Y[\xf1,\xad\\WlZ\xc9\xa0 P\x88\xd0\xb8S\x0ds\xc9ov\xf0\x9d\x80S'V\xcc\x17\x0c\xd3`]WVq_\x17\x95\x17\x04dV\xfa\xd1 \x81\xc60\xca\x96\xd1\x08\xd0\xaf\xca\x83\xa2\x9c\xb6\xb3\xe2\xbc\x7f\xf6\xab:\xa8y\xd9\xce\xa98D\x95{\xa9\xeb>\xac\xf8&w\xfb0e\xbf\x1a \xa9\xfe\x8c\xcf\xb0\xf4+\x0f\xd2Z\xf4\x1bv\x8e\xca\x00+~\x14\x0e\xde\x7f:9=\xfftrx\xfe\xe1\xe3\xf1\x87\xc3\x8f\xa7\x7f\xad\x9f\xafj\xf5\x9f\x0fN\xce\x7f<>~wxpt\xfe\xeb\xc1\xbbO\x87\xf5c\xb7Z\xfd\xe8\xd3\xfb\xc3\x8fo_\xe9\xaag\x9a\xea\x1f\x8eO\xde\x9e\xbe\xfd\xf5\xd0\xf6^\xa2y\xef\xf8\xd7\xc3\x8f\xef\x8e\x0f^\x1f\xbe\xb6\x0d0\xd0\x9eR~\xf2*K\xd2h\x95k;\xc6\xf0\x91.\x0fo\xd7J\x94\xfc\x94&\xe9\xe0\xc2\x0f\xe7NHo\xc4c\xa7\xfb\xbb3')\xb9'\xb1O\xdc\x0d\xcc\x01\x14\x0f\x0eNO?\xbe\xfd\xf1\xd3\xe9\xe1\xf9\xd1\xc1\xfb\xc3\xf3W?\x1f|\xc4\xbc@?\xfc\xb9\xab\xcb\x1ao\x0f\x85\xc1><\xb3\x8e\xd6\x07\xb9x\xfc\xea\x92\xc4\x185\xd1R+I~\xa1w\x96\x1a)\xc6\x1c3=\x0e\x82\xe8\xe6M\x16\x04'^L\xa99\xb6\x0c\xd6\xc3\x08%xjx\x96\x0e\x03\xcbp\x13\xcb\xa3\xbb\xd03w\x9f\xa5\xd1+\x11\x12\xc3\xdcD\x96F\x1f\x02rglE\\\xec\x9b\x9f\xd3 \xf8@\xe6s?\\\x1a;auN\xd6\xc4\xb3\xd6\xb9$\xf1\x89e\xd5\xbcK\x12\x04\x14-\x1c\x8c50\xb4\xc7\x18\"\xb87\x8e\xd6\xb7\xc0\xc2\x0bH\x92\xbc}m\x7f\xceYLS\x8d(H\x8cA\x89\xbc\x88\x01\xc1\x8cV^\x14\xa64\xb4@\x80??\x9c\xfb\x18\xe8\xc3^\xef6}O\xc3\xccZ'\xc6\xc1\x9a\x00%*\xbc\xf3\x13\xdb\x88\xa2xnFO/\x8e\x92\xe48\xf61L\x92\xa1\x0e\xb7\x0c2?\xa4\xa7\xbe\x05\xdey|\\\xc3,\xe6t\x81\x81 \x0dO\xfd\xd8\xdc\xb2\x08\x96c~9\xba \x83\x88\xcck\x91 \xf3\n1Y.\xad\x0bEC\x8f \x04\xc6\xe7\x8b(^Y\x1f\x1e\xd8\xe9\x14\xabr\xd8\xa2\x8f\xf74\xbd\x8c\xe6\xd6*G\xd1\xaf$\xf0\xb9\xff\xa9\x01 \xac\x1a\xe7\x0f\xcc-\xc5dE\x7f\x8cb\x8c\x16i\xa8sI\xc9\x9c\xc6f\xa4\xba\xa4\xfe\xf2\xd2\xdc\x05\x0f`d\x1c\xe4\xa5\xbf\xbc4\xbf\x1b\xd3\x85\xf5\xe1;b!`\x97\xe9*x\x13Y&\x96\xa6\xeb\xc3\xbfe\xfe\xb5\xb1\x86\xefY\x16\xd37/\x10\xden\xbd\xc7\xf0\x8d\xc6\x1a)]\xc6~j>\x81|3\xc4\xaf\xe8\xdd\x07\x12\x93\x95\xb5\x86\x15\xc9\xae\xfc\xd0d\xeet83ov*nd\xd9$e\xba]D(4\x7f2\xec\"~]\x19\x95\xea3\x08a\x08|\xda\xd7\xed\xbe\xca>3$WK\xbe\x052\xd5\xd0C\xe4\x87xVE2\x11\x9b\xf4\x99>?\x84.\xd9L\xac\xac\xe8\xa40\x9d\xe7\x89x\x04\x85r\xbas\xff\xfa\xffa\xefM\xdb\xdb\xc6\x91E\xe1\xef\xf3+`\xde9ij,)\x96\x9d\xc5Q\xe2\xf6u;\xce\xe9\xdc\xc9\xf6\xc6N/\xa3\xf6\xf8\xc0$$\xf1\x84\"8\\d\xbb;\xf9\xef\xef\x83\x02@\x82d\x81\xa4lgf\xeey.?\xd8\"P\x00\xb1\x16\xaa\n\xb58\xfa\xbe\xb7\xb9\xf2\x1e\xfe\xfd\xb7\xf4//\xdc\xdf\xae\xb6\x07\x0f\xf1Q\xe8\xa5\xdbX\xbb\xca\xcf\xc5\x9a\xa2\xee\xd6\x04\xd1DL:\xfd[\x91\x8ab\xf8\x8af\xde\xd2M\xdb/>\x01Ug\xb3\xc9yU\x1f\xbc9\xf1\xa8yVH\x94np\xe0\xd6u'\xe1\x82\x1bkd4\x0e\xa2\x88%b\xbb\x08\x9c<\x9b\x9c\x93m\xc2\xc86 g\xbb\xc8\n/B\x1a{\x00\xbds\xfe\x9cx\xa3\xd1\xf3\x81\xd4\x0c\x1d\x874\xcd`\xe1V\x17\xa6\\\xda\xd5O\xb1\xe6\x90\xce\xb5B\x98\x9a\xf4\xf4\x87\x9b3\xba\x80H\x0d\x8e\xf4\xb7^?a\xe7:`\xb3\x8c\x16\xadgkH\xb8;\x1f\x8c\xe7<9\xa1\xde\xd2\xcd\xeaF\x80E/br \x83~\x81\xfa\x89\x1b\x8d=\xd1x\xb1m\xd3\xc1s\xb3?\xa2\x87Z\xdfQn\xe42\x0f7\x99,\xf1\xfc\xd7\xfb\xd8\x7f\xfb\x96\xcdm_\x82\xaa\x1d\xedkT+7nI\xcd\x1cTC\xb7\xaa\xd0x`\x86#~\xf0\x808r\x06\xc05\x03T\xb2\xe5:)\xcb^G\x19K\xd64\x94\xe9\x83\x8a\xde\xbc\xa9\x13)p\xb3 \xcd\xe1\xf3r*\x82\x14\xfe\x8b\x06\x8bO{4\x0c\x19S\xf5\x83\xa9G\xc6V\xaa\xda\xea2\x13%\x0eI\xa3\x12 \xa2\xc0\xf6\xbf\xdb\x98\xa3\xdc\xaf6\x7f b'\xe1\x0d\xd5c\xb7U\xd5n\xb6\x85r\x86\xc3\x08\x16+20\x99\x91\xad\x0c.\xc1x\x81\x8c\xc8\xa4\x18 ]\x1c\x9d\x9c\xb1\x1c7\xa3\x9ez(\xf9AK\xbc=\xb5.d?\xcb[v\x18F\x15\x87\x1d\xc1Jf\x9c\xbc&UX\xec\xbaH\xef:7\x13[U\xfa\x9e\xe0\xe4\x05\xc9\x9e\x13\xbe\xbd= \xd1\x8c\x9f\x8bI\x98q\x04\x05i\xf5\x9c\xe6\xdcO\xc9\x8c\x9d\xdf\xef\xb6\xb3\x1c{XP\xa4\xbb\x1ec\xa0\x13\x89h\xed\xcd&C\xf2\xdd\x0b\xc9\x1f\x16\x02\xec\x03'Kr\xe6|\xff\xdd\x908/\x1e\xca\xcc\xef\x9d\xf3\xe6\xc1(J;/\x80\xb1\xfc\xde\x01`\xf5\x1b\xf1\xf4=\xdb+a_d\x97\xdc\xbf\xf9\xfeE\x96\xe8b\xc9\xf7/\x1e\xaaDK\x1d^\xd9\xda\xf5\x82\\\xaf\xc2(=\x00\x8eo\xfa\xf0\xe1\xd5\xd5\xd5\xf8jo\xcc\x93\xc5\xc3\xdd\x9d\x9d\x9d\x87\xe9zQ\xb4~\xbdhT5G\xa9x\xe7/\xceT\xf6\xe8\xf0\x85\x1f\xacU\xcb\xe0\xd7y\xf38\xa4 \xa3\n\xfc\xc5\x8a\xc6\n\x1a~!\xd0\x1e\x0f\xa7d\xb6\xdb\x1c\x01\xddi\x8f\x87\x8b\x84\xe7\xba\x9e\xe2\xd56\x1a\xe2 \xd9\x82E\xben\xc4<`\xa1\x9f\xb2L\xd5P\xbe\"%c\x9a\xd0\x95.(1\x8b*\xa6_\x90BY\x82vAM`\xeb\xdc\x11y\xb7\xb0\x90\"wDn\xcacy\xad\x8bdyT\xe5!l\x92\x1e&4\x13\x9a\x84\xe7\xcc9\xcf\xf0\x9c%\xb3\xdcog~#\x08\xa0,0\xad\xbb\xa7,w\xfa\xcc\xf1\x82\xc4\x0b\x81\xc5\xf5\xc2 \xfe@\xb3\xa5\xf8\xed\xb39\xb8n`a\x18\xc4)d/\xc4\x9f`E\xa5\xaf\x07\x08\x80\xa2\xfe\xd3\xe4?\x13\xea\x07,\x02-\xdd\x15M\xc1\x03D\xac\xaaR72\xf0\x93\x877\x0b^\xfc\xd4u\x88\xc244\xebHddJ'\xcd\xb8\xf4\x0d\xc1\xae\xa5\x060\x84;8/(\x1b\xfba6\x07\x0f>\xc4\x1b\x12*\x7f\x99\xc1xk^N:i\x88@\x9c6\\\x9e\"\xf3\xda)\xa2N?p!\xe4\xfcEpV\xd4\x02\x11T\xe8?\xe7/\xa5m\xb5\xf3\"\x0c\xa2\xcf\xe4\xe1\xf7\x0e\x99\x12\xe7\x85\xa3HP\xe7\xfb\x17\x0f\xcb\xdfN\xd9\x95`<\x0f\x12M}\xa9\xe4C\xd9e\xd4\xd3\xed]\x0f\x01T\xc8`Qwoe~q\xe1BO\xeeW\x1f\x9d\xb8\x82(\xe6\x83\x99\x80\xab\n%\xfb\xd0\x0e/\xa2>\xac$Nl\xde\xc1<\xa2S,\xd1p@\xa3\x19\xc9z$=-\x97\xa8\xcfI\x8eK7R5\x85x\x9c\xc1\x86\x02\xa6\n[\xfa\xa4\xce\xbe\xaa0\x83\x0dW>\xb1\xaa\xbe\x9e.\xe3\x0cN\x1e\xd7;+\xe3\x0c\xee=\xae\xc3\xaf\xf1\x15\xa5\xc2\x0c\xee\xd4;\xab\xc2\x0c\xee\xd4 \x91\x1b\xd5\xfc\xfa`\xaa0\x83\x0d\xbb\x8d\x0b)\xb5\xd9{6\x18B\xb8\xc4\x9d\xba\n\xa4\x8a7\xd8\x18\xbe\x13U\xf0\x11\x14\x9c\xf8\xeb\xebB\xa2`r\x0b\xa2\x85\x16{\xf7\xa8\x10\xf9;\xe4l\x19\xa4D\xd0\xf6\x82c%W4%:L,\xb9\xbc!\xff%\xce\xa9H\x9cS\xff5Fn6\xfed\x7f\xd3\x1f(Ka./\xde\xa1'\x83\xb4Z\xfd?36\xbe\xc8\xe8\xe2\\\x1a\xd7(s\xcfl\xac\x97\x85\x1e)\x99jY\x0c\x8a\x1fu&{O\x1dA\x1d\x88\n\x87\xf6\xc1?$\x0e\x81\x0btA\x8f\xa9\x91P\xaa;\x84\xcf \x9c\xda\x96\xb2\xe5\xc0\x8b\xe1\x1a\xc3\x91\x0f\xf6\x89]M\xb4uO6\xfc\xc9\x0eHu\x11\x9b\xd9\xb6\xfa\xce\xc0\xa3\xa4\x15B\x8a\x94\x9fL\x9cA\xa5\x81p\xcf^1\xd158\xf72W\x14\xddu\x86\xb0\xec\x07\xed.M>\xb6x\xdc\x90N\xb6\x133P\xfd\x15\xea!\x19\xf1\x88\xa8m\xa6\xd9\xf8b \xa1!\xda[\xe4\x05\xac\xf2\x07\x0f\xf4\xcfRN#h\xb6\xd7`\x99#a\xa6\xe2W\x87 \xd3\x91\x9b\x0dI\x00>\xb2\x16L\x06\x8e\x85\x88\xc7\x1f\x19\xf5o\xdc\x81v\xa6\xe5\xbe\xc4\xee\x0e\xa0QQ\x9aM \x12\xeb\x99\xa0\xb6v\x16\x97\x9a\xa1:3\xa6\x88\xdf\xe7\xafVKQd\xb6^6\\ \xcd\xc7q^\xc6\xc1\x05\xe7\x92\xa2\xcd\xca\xcfd\xbd\x85*Y\xb7\xa7}i\xbci|l5\x8ey*G\xf0g\xe9\xca\x02\xbe\xd8^\xcd\xa7F5\x97\xb7\xa9\xe6\x1f\x8dj\x16\xdd\xd5\xe8_b5\xbej\x1ca\x19\x8f\x8f.y\x02w\xd3\xe2\x7f\xed\xcc\xcbx|L#i\x0e\xe0x4\x8aCzc\x05)\xfc\xe1h\xc8L&4\x0b\xbc\xcc\xe5|\x1c+\x0f\x85\x8e\xaf\x12<\xcc\xab`\xc6\xe3\x93U\x9c\x05\xe0K\x90\xc9_\x08H\xe4%7q&\x81\xf4o\x0c\xccW >\x9a\x9d$p\xa3\x0e\x91\xfd\x9a\xd9o8\xf5\x99/\xfd\xd6:!\xbc@\xc8\x0f\x0b\xe0[\x96Q\xdf\x04^\xa9\x04\xbc\x80\x8a\x9f\x04\xb0)\x12\xe4\x08\x1c\x96\xe7\xa9\x18\xb0X\xfcG\xb2\xe5L\xe1\xd3$2\x81\x88\x80\xfc Z _$\xa0X\xe6\xc4\xeag\x13\xe8#\xcdX1s \xcd\x98m\xd6N\x19\x03\xf3\x0b'\x85\x1f8\x80lQ*\x7f! \x19\x0d\xa5\xcf\xc9T\xfeB@\xf24\x06I\x8f\x93\xca_M\x90\xb3`\xc5t\xb4$'\x0bV,\xc7B\x1ae<\xfe\x89\x87\xf9\xaa\xec\xdd\x1a^m\xfd\xfb\x99\x06\x99l\xfe\x95\xfce\xd0\x11\x18 \xf6{c\xff^\x8f\xb3\x84z\x9f{\xec\xfd\x1f\x1aeK_\xcb\x82\xe0~\xfdR\x1f\x98{\xf5\x8b\x1a\xb1\xf3\x199 \xea3\xd5\xcc\xc2W\xbe.\xfe\xc8)<\xf4ft\x81\x1du\xd2\xd3{\x00\xba\xfb\xd6 ?\xeap\xc6\xdd\xb5\xcb\xeaMW@\x05>\x06\xb9\xa9/\x86%\xfeA\xba\x1bU\x0e\xdc\xd4\x1e\x01\xb9\x8f\xfc\xcf\x06\x96k\xe0\xcb\x84\xd1\xcf\xcd,\xd9\xb0u\xe03nm6\xcd\xfd\x00\xcb%\xa6\x0c=+]a\xdb\xfbp>$\xaf\x06\xe4U]\x1e\x93\x01\xb1\xd7Vx\x1c\xe7\xe9\xd2E\x86 \x1b\x92W\xb3\xec\\t\xdcB7\xb7v\\j\xac\xdd\xef\x8c\x9cH4Y\xe0\xcb[\xceI\xb0Z|\xf3v\x0d\xc9\xb7\\Us\x9e\xac\xee\xb7\x0b\x1f\x19h\x88\x11'Q?Z\xbap\x9a_\xae\x02)\xb4\xd4\xbfn\xd7\x8d\xc0\x128E\xad \xe9*\xce\x1a\xd7\x8b]g4a\xf4~\xc7\xe1\xb5\n/>\x14\xad\xd3?\x99=$\x01\x82;\x7fj\xe0\xce\x1b\xa0\x9b\xe4\x89\xd0\x87p\xfa\x11\xe5\xfd\xe5%\x07&k\xb8\xa4\xe2\x94Fs\x12<\x1d\xae@\xb0\x0c\xb6\xba\x14\xc7\x1f\x96\xb5\xb4\xd4\x15\xac,\"\x90@\xc6\x14\xc5\xb2>\xb3\x9b\x05\x8b\xf0\xbc0\x88>\xe39\x82\x9e\xc1s\xd4\x1d\n\x96\xa5Ug\xb1<8\x0e\xf1\xac\xab\xcbN\xe1\xcd\xcf\xe84\x89Uf\x95\n\xc5\x89\xad%j5w}\xf3\xff\x80\xff\xbe\xe6WW,\xca\x83\x8c\xad\x90\xf2\xe4\xc7\x9ap\xedW\xd0\xa2\x99\xd1\xd1\xefG\xa3\xbf\x9d\xab\xff\xd3\x8b\xdf\xc6\xbf\x8d~\xf3\xcf\xff\xf2\xe7\x87U\xf0\xbf\"\xb7\x95\xff i\xb5\xd3\x06#B\xfe\x8cJ3\n\xedJ\x1d^\xd0\x199\x03\xf2\xfd\x01\xd9\xa9J0\x02[\xa4\x92\xbfA\xb0\x01\xe4{\xbf\xb4\xc5\xd8\x13|{\x15\x17u\x85\xc4\xf9Oy\x03\xfeW\xf03\xfb\xe5\x0bq\x7f\x05\xf3su\xcf!\x08\x98\xc7\nW\xfeU\xdf\xbd4\xdc\xbc\x16\x04NUFb\x86\x03\xc9\xe8\x824\\C\xea\xcc\x88\xaeX\x1aS\x8f}\xfa\xf8\x9aT\xe3ph\xb9\x94\xbee\xa8e\xc7 [\x07r\x9e\xb9e\x9dRZ[\x1a\xa4\x05,u%\xa99\x17\xb4\xbe\xa5\x9d*\xbcv\xee\xc6\x16\x08\xd5s\x18\x92\xd7Q\x90\x054\xd4t\xbb\xa0%\xe7C\x92\x0c\xc9\xd5@\xfa\xd8o\xfa\xf4\xfb\xda\xe6fP|\xfd\xa4\\\x98\xf0\x8d\xf71\x8b\xce\xe8B\x9a\xdd\x1cE\xfe\x87\xf2\xda*\x85\x0f\xb6,\xf6\xebZ]JA@\xd6\xa5[k\xe9\xa7h\xfe\xd6\xb5@)?\xce\x8a]yN\x0e\xc9\x89X\xdeR\xf3\xebD\xaet\xb2M\xae\xc5/\xb9\xfc\xadKC\x02\xf7@\xe0\x1b\x92\xaf]\x14O\xc7\xc9\xf2\xa68\x82\xe6c\x9ag\x1c\xc2\x88H\xd3\xba\xd6r\xc1x. M\xfe\xe3\x9fr\x14w4\xeb\xd3\xbfSwZ\xa9\" r\x99gY+-\xf7o\xd0\x8dNz\xb3\xa3Q\xff\xe8O\xbc(\x99J\xab\xbeN\x0f\xcc\xd0CCQ+\xd6\xc8\x03l\x83\xb3\xb0\xb8\xd2H\xe0J\x03?\xc7@\xa7\xa7~\x8f\x91t\xc6\x89\x06/\xee\xb3\xa4\xc5T\xcf\x0c)\x11\xd8\xcfP\x0d\xfa\x1ek\x03x\xa7\xfe\xa8N\xa1\x04\xe2\xa2\xd8\x0e\x04\xfdt8\x87\xd5\x8f\x03\xba$\x92\x96\x01\xcb.7P\x7f5&\xc6$6\xdc\xfd\xe3\xebP+\xa2\x08\xa2-\x80x\xf6r\x9a\xe5\xfc\xbe\xe2 \x94H\xdd@-\xa6\x8e\x06\x135\xa29\xc1\xdc\xeccOA'\x9b\xf4\xe4\x9fK,\x0c\xeb\xe8\x90\xbcm\x8e(\xc8\xd4\xc4\x87\xbcz\x9bk~ ]1\xd8\x10(\x01\x85.\xab\x94\xda'\xb9\xd4 \"\xdb\x07\xc4\x01\x15\xa5\xbc}\xc2\xfb\xc6\xcb0\xcc\xc2#\x9f%g\\\xf0\xf9\x81'\xdbA\x0eID\xa6\xfa\xf4\xa9\xd2\x1cf[\x1a\xad\x07\xfa\x03\xf4\x8eZ\x80^\xbfT\x15\x83\xech\xd0\xea\xd3\x1d;\xb5\xfb\xf9s_\x17\xe1Kp\xe2\x80\x93\x16\xb5\xad\xe6J1\xf7\x1c\x1f\x14\x0b\x85\x8f\xa5\xce#\xccRB\xca\x04divP=b\xc1\x7f\x98\x15\x1aYZUL\xd0\x1b\x86\xe2\x98M\x01R?T\xadu\xc0\x0df\x84p]\x83\x9d_)Q\n\x0c\xdc\x89\x1b\xb4\xd1\xc5f \xda\x86\xd3\x12\xbd\xef\xa5\xfcQ\x13\x8aT\xc5[\x18\xff7\x0f\"\xd7qng\xa7O\xca\xa5\xfc\xb3I\xa3 \xce\xf37\x15\x02,\x19{K\x9a\x1ce\xee\x8e\xd8\xbb\x90\xbcM\x1225\xe2^\x10\xeb\xca\xab\xd1\xb7\xbd\xa5\xa6Z\x89\xed~\x97X>\x86\xd3T\x94\x17\x08\xe2\x7f\xc6bs\xa4\x83\x89\xc0\xe8 \x84\x86\x06\x0c\xd8{\x05Z\x1bY\x9c\xd5i\xfbB\x94\xec\xca\xces\x12\x92\x17$\xd5\xb6\x94$\xdc\xde\x1e\xe8fI\x0e6\x19\x92t\x16\x9ew\x912\x8d\xe8\x14\x1e\x0b\x8c\xf0\x14\x9ba1\x8c6i\x0e\x0d\x06e\xdc\xceHv\xb0h\x81\x9b\xc1\xc9\xdf\x8czR7\xe8\xab\x16\xbb\xc5\x16\x00\x19=\xbe\x8c\x82o+\xd7\xefb\x8c\xb8M\xdc\xcb\x15 \x82f\xda\x96%\xb9\x17J\x9a\xdb\xa4\xb3\xbaMh\xe6\x9d\xda\xd4)\xba\xe56\xf1\xacn\x13\x9ay\xa76\xf5\xe0\x03\xb9M\xec\xaa[\x85f\"$\xb3\x9d\x01\x7fW\x14j\x13\xaapE@7`\n,\xa3 \xc4V\x19v\x8b\xf8\xfa-\xde\x95\xda\xd1\x15M\x8c!\xb9\xc6\x83\xe3\xde\x95\x03\xec1\x1f\x97X\x83\xee\xf0\xc9\xcee\xd9\xc1t\xfe\xd4\x8f\xe9\xac\x9f\xfc\xc8\x0co\x80\xade\x8cI\x0b\xcf\x98 >\x00\xf4\x03:\xf3\x08\xc3(Y~4Y\x1f\x7fl\x96 \xe7\x91Yq\x85+\xeb#YN\xed\xecZ;\x1f\x05\xfd\x0cD?\xd3\x01I\xeb\xed\x0e\xa4\xec\x1fX%pU\xf2\xc7\xd7\xc1,8\x07B\xbd\x83\x9d\xb33\x8f\xedW\x8e\x92Z@\xb8`r\x08\x03G L\xad\xdc\xe6\x89`\xcc*\x0c\x1fka\xf8f\xd8A\xecB\x11\xd1\xed9\x90\x81q\xc5dfn\xaa\xd1\xc4\x83M\xd6x\xebZ\x12\xe0\x10\x98\xa6\x87Pb.\xa6\xb0}\xf1\x0dI\xdc\xb5\xa7Hek\xc4\x03\xb2\x15#{\xe3\xcb\x172\x87\xb1\xc0\xf3n\xb5o\xaa_\x9e\x0f\xd0\xca\x1f< \xb1\xa8OL\xc1\\\xfc\xb0\xecR\x91\xd7!\x81\x90\xfbM\x14E\"\xfb\xe9\xa7\xa0\xe0Q\xe9\x94\x98\x1aC85\x07|;\x95k\xa3\xdc\xaa=j\xaf\xc9n\x06\xf6\x9d\x9c\xb2\xacm\x1b\xb7\xdf\x8d\x17\xdf\xdb`\xa3w\xa3`\xdf\xa6|^\x7f\xca\xddrX\xedI\xd1K_u\x81L\xed\xd8\xc5\xdf0\x10k3\x05\x84U\xd4l\x80\x12\xd8\x15\xe3\x98c'\xb2\xf5\xfc\xbd5\xd7]\xb0\xb6\xac\xc2\xda\xb2~\xac\xed\xdd\x99c\nZz-6|\xd6L\xc5\xd1\xe3\xd5\xe6m\x02\x05\xd0\x8f\xbfU\xb5\xa9\xc1\xc6\xf3\x92\x8d/G\x0b/\x16vq\xffx1\xaf\xf25\x03\xbd[\xbc\x07\xcf+\x9f1\xe0\x11\x1aKg\xa5\x05q\xa4B]e\x06\xff\xabIr\x89\xb8#uF{\xa2\xc8\x16 _\x03\xf8\x8c]gJ\xf8\xe8V,>\x03PF(\xe4\x16\xd6\"d\x9b\x04\x03\xe3\x98\xcc\xc9!\xa1P.\xaf\x95SW\x92\x8e\x14\xf2\x1aE\xc2\x1a`\xd1\x81\x10\x0bg]\xdbL\x8a\xffy\x07\x0e\x85\x8b]\x84\xed\x1d%F\xab\x1b\xd5 u\xe6\x91]\x95\x10\xabyC\x9e\xfd\xff\xe9\xe2\x19\x8f\xd6\xf9\x95c\x87[\x01\xd8\x0f\x07iV\xdezvT<\\\xed<'\x11yA\xb2B\xfa\x15mo\x0fH6\x8b\xce\x95\x0e\x87\xcd\xf2\x9c\xf4a\xe7\xda\xf8\xd9\xde<\xe6\xf58\xcdx|\x96P\xefs\x10-\xbaN\xc7\xce6\x81\xc3\x82\xb6&-\x19\xf5\xdboo\xb9\x7f\xd3\xd2\xde\xc4u\x9e6\x1f\xe93\\\xf6\xd9i*C\xea\xa7\x8f&\x8bA6\xe0\x07\xa2\xf4h|\xc7\x03\xf1\xe9\xb3\xba\xcb2\x0e\x86\x87\xa3U:\xea\xf4\xdc]_\xeaj\xeb&n\xe1e\xdd\xe5C\xe2\xac\xd2\x913\xa8\xe3\xda;\xb5\xfb\xe1\xc8\x1d\x0f\x1e.n\xd9\xbe\xb2u\xc9\xb0\x1b\x85kW\xe0\xe3\x8c\x7f\x12\x14$\xe2\x02\xfc\xeb\xbdv\xceF\xa5(\xaa!\x19\x07\xe9\xa7(\xc8B\x96\xa6\xef\xc0\x7f\xd9\xa0k\x1cZ]\x19iQ\x02h@9\x97\x9c\x87\x8cV\\\x17\xcb\x0c\xa5\xc0_z\xe0\xaa\xed\x04\xady\x11\xa4\xef\xe8;7\xab\xa1\x07\xbd2DU \xe80\x9c(s\xc4?\xe5\x83\x07\x84K/\x922\xd2\x05\x99\x82\x08\xbc\x11!\x80HG\xe3`\x96\x99\x04+\xd0\xcf\xca\xc4y\x13_7N\xf7;N\xca\xfe\x0e6)\x0f\xff~\xb7\x8d2\xa8\xec\x94\x11l\x95\xfbl\xf7Cwv4\xfa\xdb\xf9=m\x16g\xf4\xe7\x893\xb08\xc3\xbfCk\xfb\xb5H\xcb\x0b\xfe\xf8\x8a.\xae\xa2 z\xe6\x17\xdb\xb8\xb6\xd8\"y\xf9\x90\xcd\"pq-M\x89\xa5\x14>\x82\xd54\x8b\xec~\x05\xc8m;lpg\x8fw:\xf7\xafej\xbes\xbe#\xdb\xb0\x88\xc8\xb6x\xb9\xe7\x86M\xcc\x86i\x92\xa9\xda\x10q\x08\x87\xecL\xd9\xfcb\xa2l\x8e\xcdE\x97A7\x01?\xa9\xea\xa6\x1b\xdc>\xa4 !(|\xa7B\xda\xff\x07\xf7\xe0[\x13\x84\x9ft\x931\xbb\xce\x12\xeae\xbat\xd9\x1e+s\x8e\xcf\xc2\xbd\x84~\xd9}2\xc0\xec\xe09z\xe8h\x9e\xc1\xb2\xcc\xa3\x19\xabn\xc0s\xcc*=\x9a9?\xb3\xcb\xcfA\x06\xae\xff\x80\x1c\xb9*\xde3\xc8\x7f\xcb\x7f/3W\xf2E\xe6\xac\xd22\xe3\xedi\x99\xfe\xbeL\xe6\x90\xda\xf8jm \x12\xe3`hN3\x8d\x82\x15\xb8\xf8\x02OM\xdcu\x8et\x823$\xe5\xcbI\xe4c|KQ:\xc8\x98\xf4\x14\xd6R\xc7k\x0d\xd3Z\x93\n\xf5g\xad\x05\x9cqa5d\x89\xa0?\xcd\xae\x9c\x15)\xa2\x86\xf2\x0d:S]\x81My\x02\xe6v\xde\\\x0d\xa6k{q\x00\xe6\xfd\x18\xf6\xca\xa0\x8a}\x01Q\x1b\xae\x82\xc8\xe7W\x80\x04\xa5\xa8\x8d\x04csf\xca\x97!i\x02\x14\x83\xdf\x0e\x06#[\xbe\x0e\xaac\x82\xb4\xa5\xa8\xa22\xb4\xc6[o\x9f\xd9\x82\xc6\xa13v^P.\xe2\xe5y\x03d+0a\x90h(\xe2\xe4 \x1aE\x0d\x113\xce)\xa2\\b$5\\D\x91\xbc\xd2.P`\x88\xce\xd1\x8d_qIJ\xee\x8e\x946s\xfc\xdct\xc1,%_\xbb\x93\xba\x0f\xe3\x1c\x97:J\xc7\xcf\x8f\xf6\x8cCE\xbb#~\x86b\xc7\xb0\xdb\xbd\x19h\x13 zY\xc6@5\xeb\xf5\xac\x07\xaa\xe3-\x99\xf7\xf9\x92_\xebHU:,\x1c\xb8\x84\xe7\x95\xd4\xc3R;d\x0c\xc5\x98oj\x8c\x8c!R\x9b\x05\x1d6\xa3)\x98\xaa|\x1b\x88\x95\xe8x\xa1$ nf\x11\xed$\x1a\xecX6\xb2A\x9a\x93\xb2\xff\x98\xcf\x1a\xf1\xc8\xb0\x9aR\xe8f\xb9f\x850\xa8m\x10\x10(\xba\x15\x80^k\x80F\xfeWX\xddx\xe3Tx\x7f\xd5\xbd\xf6o(\xd8\x9fd\xd8\xc16H\x15\x99P\xcfg\xa4\xccFX\xed\x9e*\x90*\xf4P!^\x91\xa7\xdb\xa5\xabJ\xc8!h\xe8[\xaaR\xfd\xc0++\xddc\xd6K\xeb\x9c\xe6\xd0\xb5\x9e6\xa6\xd9\xff\x06\xeb.\x1b\x9b#\xd9\\O\xac\xa7\x8b\x8dj\x9f\xcb1\xca\x8a-uh\xfc\x9e\x96\xdfm\x1d%sR\xcc:aN\xa1F\xf9kJl\xb7\xffU\x8f\x1f]s\xd1M\xcc\x92\xc6m'\xa6\x11\xde.\x9b\x95\xfb\x9d]3/\xcf\xd8{\xf5q7k\xb7mK\xc74\xa5\xb1\x1bv\x1aI\xae\x0b\x85\xf6\x88\xaeZ,\xe4Azh`Ce\xfbk\xe8k\xa2\x14\xbf\xf9\x14G\xa68Xr\xfb=\xd1\x10\xee0\x82\xe7\xc43\xc2\xf7=\x1f@j%\xa9\xdf\xd7\xe6P\xec\x1f9KnNA\xf7\x96'Ga\xe8\xca\x9b\xdb\x99\xe8\xf5\x81\xa0i\xff\xcf\xe9\xfbwc)i\x08\xe67Re\x01D\xd8\xdf\x9d\x83\xda\xcc\x81\xea\xfd\xf9w\x03\xe9\x02`\xe79\x89\xc9\x8b\"\xf4\xd9s\x12oow\x0d\x01Q#\xee\x83\xd6Y\xdc!\xb3$j\xdc\xfdR'\xc3\x1f\xcfy\xb2\x82\x19\x08\xe0g\x9f/\x12\xf5\xd5\xa5\x1ew=\xdeb\xec\xe1\xd2\xb5\x1e;\xcd\xf6,\x95c\xadg\xe0\xe4\xbb\\d\xcbn\xc9*.\xfa\xec\xce\xb5\xe7\xa0\x01\xa8\xf4\xf3u|\x19D>\x1a\x9eO<\x1e\x8f\xb2\x84Ko\xb2\x1e\xa6N\xd0\xaaM]\xa1<\xba\xf0\xc0\xda\xea@\xbfe\xf3Kd\xab\x10`sn\xca\xe3\xe9\xc1\x03\x12\xa0\xdaq\xf8\x06\x13\xdc\xb4\xa3\xaa\x85;\x1b\x88}\x8b\xcc\xbe&\x17\xad\xd5\xe0\xb8\xb1N\x9b4+\xaeZ\x84\xe1x|N\\)'\xe4pG\xa1M\xde\x00{\x0f\xf4\x0f\xc1\x8d\xeeX\xc4\xf2\xc5MD\x11\xd2\xad\xc4Y]\xb8\x1aD\xec4I\xe5]\xa1\xab\xbe6$\x93\x1d\x90\x18\xb5\xdc\xc9\xb8\\\xeai)\x8f1RcK\xb7VbH0\xa9,\xdb/\x91\x0c\xbe\x80e'\xca\xe2\x1a\x1c\xaf\x039\x8b!\xd6\xa3\x16\xf2*x\x03_W\xcfr\xd9\xd4JJ\xf1\xc9&\xa4[\x03E\x01\xb5f\xd9\x81y\xaec\x0d8.\xf3\xca\x8au\xe2\x01\xd9\xda\xaaC\xb6\x926u/\xe8\xdfl\x7f\xda\xb6Fs*\ne\xb1\xd6\x05\xa8\xf4\xab\xa4\xd7\xd66\xed\x1c\xe9\x05\xb6\xc5d\xa5KA\x08\x02\xbd\xb7~\x02\x9a\x06\x1a\x85\xdc\xa3\xed*I+\x1ee\xcbv=\xaa\xae\xaf]1f\xd3n#\x10a\xb5\xdc2C\xe3-\xea\xa0i\xf5\xd32\xaa\xaa\x82>\xdf\x8ej\x0c\xa2~\x9a\xc7\\\xc1\xb0[(3eb*\xdd\x11H \xa99?,\xbbdl\xa2zZ_(\xfc3u\x05\xcd\xe2\xcd\"M\x9dC\xea\xad\x04\x17f5\xce\xe9\xc9\xf1\xc7\x93\xb3\x8b\x97\xef/\xde\xbd?\xbb\xf8ptzzq\xf6\xe3\xeb\xd3\x8b\xf7\x1f/~}\xff\xe9\xe2\xe7\xd7o\xde\\\xfcpr\xf1\xea\xf5\xc7\x93\x97\xce\xed\xbfi\x08K\xeaR\x11\x15o\xb9\x1e\x0d+\xc0\x85\x1f\x94\xe0q\xa0\xf2\xf2^\x0f\x8e\xdf\"\xb3\x90V\xa4\xf6{\x90\xfa\x15\x9c\xe6\xe2\xc7Z\xad\xae\x88K\xc7\x86\x1d\xc8\xaf\x90[\x10\xe9\x9f\xacq\xd3&\xc5 \xe5)Z\xa6\x1f\x92\x8cl\x8b\x92SiN\x01\xd2\xc8\xad\x9d\xba\x9c}0$Y\xb9:*#\x1c\xe2\xee\xd9\xb8\xe9K\xc2\xd0\xa5\x96\x94\x8b2\xf6\xab\x17,d3\x92!\x01\xc4\x03\xea\xd5\xd7\x99[\xbf\xa8 V\xe4\x10\x0c[\xbc\x80\x98=\xb7X@\x08\x90\xc0PDo2\xca\xdbb\xf7OI\xea\x96\xfa\xef\x03\xf9\xd1\xad\xc9\xb0\x16\xe0\xb7]7\xa9\xe0\xc6\x0c{\xf4\xa4b\x8fn-J4\xf7 .\x0ef\xe1\xb9\xe4~\xfa0>rEv\xb36\x80\xda[\xa1,\x8a\x1b\xa5Y\x90l\x9dl\xda\xed\xe5\"r\xbd\x08\xa6$\xefX\x04\xdf\x96\xe8\xb1s\x1c\x06!\x19X\xe8\x9f\x8a\x037\xd7\x01xg\xa8K\xb6\xd2n\xb7\x14\x87&\x16\xf9e9\x9cm\"\xbf2l[\x8b\x14\x12\xa1\xeaJ\x99oU$\xa7\xbf\xaaN\xcc\xe2\xd5\x0ei\xe1\xbf\xc0\xe7\xa3\xb9\xf7\xec\x02\\\xf5-\xaft5\xcd+\xd7r\xa4\xcf!-U\xee\xeez`nt\xbb\xd0\xbcE\xa0\xf8A\x9aoz\x8b\x90\xf6\xbaE\x08;n\x11\xf4/\xfc\xb8\xdap\xb9j\x81E\xc9\xff\xd8\xad\x9e\x12\xd7y6q \x82\xfe\x1fmRp%\xaf\xbe\x1f\xe1w\xb9\x13\x1c\x159nC\xa1\xf7\xbf\x8b\x9c:\xe8\xbe\x1f\xb1\x9c\xf8\xa6fT+\xc5@\x1b\xe2p\xbb\x187$\x07\x9d\x0ed*\x96QnE\xd7V\xac\x85]\xb1\x16\xaa'n(\xc5 \xa1:F\xc9\x8b\x032\xd1\xf2\xb9=G\xf9~ g;\xe7\x03\xe9\xdc\x16\xe644\xb8r\xa9\xc8K5\xd7\x00\xc2\x9b\xe6\xfc4R\xfa\x1efUq\xbc\x94S\xfc_&w\x0f6\x95\xbb\xab-\x9eK\xc9hZ8m\xec\x10Rv\x8c\xfa\xbfD\xfcH7\x92\xfc%\xf5]\xd7E\x92v\x10\xe3\x92\x9e\xc2\x07Z\xda(F%%\xe2\x96\xfc5\xafH\x9d\x1ar\xab\xa8.\xb7B\xa4o\xcd\x15o\x17\x995+\xac\xc9\xc0\xda\xe6\xf1\xb6D\xdbf3#E\xc9Yi\xc1\x89P2\xea\x82\xdb\x8e\xee\xa1\xafY)\xc5\xd8\x90\xfd\xff\x96\x94\xc5\xee.f\xcf\xe4\n\xf8]\x19\xe4X\xda\xf2l\xaeg\xa3A\x9f*v\xc3\xa85\xfd\x90\xf0\xa1\x9dQ\x04Y\xbfv\x90\xd6\xd6\xec\x14\x1cGgC8;i\xdd`\x99\x0dE-\xc5\xe7\xa4\x06\xa9\xbd\x86\xf28B\x17V\xc7\xaa\xe0bU\xd0\x86\x05q\x04\x12T\xd8\x0fQ}M\xf0\"\x9a\xf6d\xdffg\xa5\x95\xbeg\xaer+h_DR\x1d\xca9;\xf9\xe5\xec\xe2\xf8\xfd\xbb\xb3\x93wg\x16G\xacD]1\xc3\xd0X\xa2 \x8bg\x0e\x07\xb8\xcf\xae\xbb\xbcR\xce\xd5M}\x17\\\xc6{UG\xe7\x19K\xca\xfaP\xb8\xaf\x03\xcc\x1d\xa4m14\xdd\xd8\xfe\x8f_\x07\xa7'g\x17o\x8f>\xfe\xf5\xd3\x87\xff\xb7\nH\xdeq\x1c\xdbVCf\xf8\x16\xbc\x1dIp\xdb/\xd7\xcf\xc9\xea\"\xb4\x8f\x1aG\x14\xb5\xcd\x87v\x9c\x809r6W\x89\x19Wz0\xa5\x92\xa0\xb0\x9f\xcf\xe2\x1c\x84\xab\x97V\xe7wp\x0c\x0d\x0b\x973\xed'\x1f(6\xb5\x83\xf8\xdd \xcbn\x90\xb5\xf5\xe6B?\xb0\xe1=\xa9*\xddZ\x15\x0cC}\xcb{\x9d\xe4\x00Qc\xb3\"\xeav3\x99y=\xe8\x02\xf1,\x04E8\xf3z\xa8oIU\xad\x059$\xee\x1c\xa4\xb9su\xe4\x97\xc1cVC\xb2\x1eB$\x9e\xc1@\x86\xe3yK\xb3\xe5xE\xaf\xdd\x95y\xc0\x0b\x80!Y\xd5\xce\xfc\x18|\xf1\xad\x80\xb1h/\xabB:\x95M\xb8(\x11\xe8\x91\x04s\x17CBg\xcbs\xdd\xa2L\xd9B-\xb7\xb7\x07C\x12\x0b\xf2b\xad\xf9|\xed\x81\xc7E\x9c\x7f\x98\x8f]\x7f\xab\x9c`>h\x1a\x03zR\xbaUk\xb2\x89\xf5]\x980\xc2g\xde\xf9\xa0\xcdm>\xf8?\xd2\xe8}^\xfa\x0fi\xd2\xb5\xcdK\x17\x82\xf6\x00\xc3\x7f\x91\x95\\o=\x087<\x05\x9b\xe7^f\xfah\xb5\x84\x9c\xec\xd3\x81bA\xf6vLF\n7\x05\xe6\x92|!\x80\xeb\x96y\x1d\xa8\x98\x94\xf4g\xfb\x9eU'\xef\xdb\xf7?\x9d\\\x9c\xfc\xf2\xfa\xf4\xec\xf5\xbb\xffl9|\x89y\x00w#?\xe3\x1c\xae\xf4\xa9\xbb\x94{\xcd\xae\x11\xaf\xac\xc7E\n\xb1L\xed}\xcd\xeb\xc7\x13\xd8\xc3\xef\xde\xbf<\xe9;\xab\xdd\xe3\x7f\xd7\xfd\xdbB\xa2\x93\xfeT5\xe9IY\x93\x8em\xdbkV\x9bg\xf8-$a\x85\xc5w\x95\xb4H\xd4\xa9b\xe0\x05Qe\xd4\xbbm\xe6Q\xd5s\xcd\xe9\x0b<\xf8\xb0\x19b\x8f\xe1w\xf0\xc4\xde\xfcH\xbaBl\xb6\xf4O\xf8\x9bEt\xedA\xea\xadD\xd7\xa5\x9b'\xd4\xd6W\xb9\x17\xa8\xfb\xe1 \x86\xa7\xae\xfa-8)\xa5\xdb\xbb\xbb{ \x97\xde\xdd\xdd\xad\x0b\xb4\x89\xa1x\xb6_\x1b\xb4\xdau91\x85\xccy\xc7\x81\xbfV\xb6\x1b\x86\x17&\xd60Z$\xe6} \xa8\x89H\xa1\xb7\xb4\xb3\xe7\x82^i*\x89U\xc7FV\xbfu\xa0*x\x0fN \x11\x15\x0f\x81=.N\xde\xfd4%N\x9cp?\x87^ \xe8\xe4\xe7\x93\x1f>\x1c\x1d\xff\xf5\xe2\xf5\xbb7\xaf\xdf\x9d\\\x9c\x9e\xfd\xfa\xe6\xe4tJ\xb6&\xd5F\xd4FJ\x8b\x0b\x9b\xdfE\xa4\xd8\x1b\x13M\xfa\x8e\x8a\x0dL\xb5\x80v\xb9j\xdd0\\?Z\xbc.>\x9d\xcb@\x01\x1b\x88\xf1\xda\xba@\xa1\xc2\x14\xa2U{\xe0k\xd7\xde#\xf0\xe9\xd1y#+\xf8\x9c\x0e\x9e/n\xf1\xbd\xa4\x1f\xd4\xba6\xee\xcd\xf3 \x06\x15\xd8%\xb8\xd8b\xb3\xf8\x1c\xb8\x0d\xbf~G\xda\x8f\x1d\\\x83\xf5n_k\x1e\xbd9@?(p\x97C\xb2\x1e\x0cH2\xae\x07Sq}`\xc3\xf2!\xf8b\xca\xa4\x1f\xa2\x96\xb1\xd3O\x0f\xbfJ\xfa\x91*JTV\x9dT\xa8W\x1f\xdc.\xd4\xbd\xa2\x8a6mM\xfa\xc4(#\x06w\xcd\xdd5l\xfa~\xa5TOW\xfd\xa0\xc57\x16\xd0\xfaZKW\xf5\xa5\xdb\xaf\xbeH\x8a\xcf;\x98Z\xd2\xca\xd8\xb6\xe7\x96k\x9c\x0d\xc8V\xc3\xc7[\x0cV&\x80\xf8\x90\x05.\xcd\xf5\xc1[[|.\x98\xf5\x8d\xa7\x0em\xd7]Y\xdc\x96\x13\xbdj(o\xf1vG\x88\xc5\xe3]\xd4\xb9\xa55r\xc4O\"\xf3A\xc6\x84\xa3\xb4\x8c~\x90Q\xa9\xa4\xd4\xd0\xb1I5\x94\x17|_\x07\xca\xb5\x8c8\xac\x1f?V\x13p+z\xa2\xf3*\xdc\xa2d\xd7PV\xa7\x96\x8bs\xa5dW\xf7\x89\x99*U\xbd\xba#\x80P\xb5\xa5\x9e\xeeU|h\xee=y\\'P\xe68\xe5\x13\xcb\xfa\x1a>9}Y\xdf\xbe\xa2w&\xf5\xea\x96\xaa;\xf5v\xacK%\xfbzO\x05Z\xaa9\xce\x14Xd\x17\xbb\xd2\x07\xc7T\x7f`\xb7\xf2\x97\xe8\xca/\x15H\xcb\xe5rS:\x7fU\xd1 M\xdf\x15\x18u\xc8\xc8\x01 \xc5\xbe\x96:\x89xX\xe8\xc6\x02\x85\xbb\x0b\xe9\x94Z\xaa\xf7(\x12^*\x97Wbf\xd5c\x0d(*B\xf5\xa9\xa2\xb5_]\x82\x17\xcd\xb1\xbbB\xe9$\x8fGi\x96\xe4^\xaf\xebALM\xcb\x88\xf3eq\xf7\xeb\x89\xad\x9c\x06\x19;\xbb\x89YA\xf4\xcb\xbc@i\xc6\xd4\x92\x8d\xd0\x8f\xcd\x8c\xca%l-_\x0e\xdb\x0f4\xf3\x96\xd2\xffZ-?f\x91\x1fD\x8b\xb2\xedH&h\xd6\x80\x03#<\xff\xa3\xf4\xb9\xa5\x15\xeb\xb6&\xb5\xfcW<\xf1\x98\xbc-\xa8dk\xc1\x9f\x18!d(\n\xb9\xa0\xc6|\xb5|\xb5>j\xa9\x80,\xdf'r\xb1\x16C\x9e)\xafOJi \xef\xc71\x0d\xc3K\xea}N\xeb\x1f\xa2ah4\xe3\xe7 \x0c?I\xa4\x0c\xddi\xac\x0c\xabZD[\xe46\xab%z\xbd\xb3\x1c\xed\xe9\xc5\xf66\xbaV\xb2\xd6\x85b'\xdd\xe9\xd0\xb8\xf3\xe9\xaf\x83G\x14\xe6U\xe3\xaa\x14}\n+\x11{!\xcf\xf61\x1ce\xe8g\x0eJ\x82\x0b\x96\xc9\xe5%\xbdl\xb5|\xc6o\xf5\xbeS\x7f\x14v\xd9r\xb7X\x89\n\xc1\xfa\xd8x\x1f\x07)\x04\xbe*f\xb7\xe5lv\xbd\x96\xb6-\xcb!\xd08\xa8B\x08I\xca\xd0F\x13\xfafD\x86%1LV\x97\x1ay\x1f\xf6\xf2eF6\xe8\xf8\x87\x9d\xe9\xb3tl\xb2\xeb\xb6N\x05\xd2\xb8!\x91\x1e\x06b\x1eD\x99-\xa0\x07\xee\xaa^?E\xd4Vl\xa5V\x9b\x83#f\xed\xda>o=\x0e\xc6 \x97\xa4\x91K\x07u\x1c\x86\xee=7o\xd9\xf9\xa0\x96]\xadC#\xa7\n\xdd\xf0\xc1(Y/`2\ne\xaa\xc2\xc2\x83\x016\xbeV\xba\xb2\xc9bo\xed\x808\xa2\xd2\xeb;\x0fu\xdbZ\x0dn\xb9\x1ao\xb5\xf8\x8aq\xd6\xe3f\xa7IZ4_\x83\x12\x83 \x8a\xb8@|.\x96\xe1v,\x87\xa0\xc7\n\x08\xf4\xa4\x07\xe5<\x0f\x86\x15\xc1~\xa1\xaan\xce4\x90\x0543&\xdc\xb5 \x03\xd7\xca\xe5\xbd'\x90\xb78\xecQ\xcf\x18\xa4\xa1flp0H0,b\x08\xe6\xcd\x81\x07a|\x95|\x02i8\xdc\"x\xe3\x93\xb7\x1f\xce~m\xbf>\xb2,hI\x85\xcc\x11\x15\xdeD/\x92*\x81\xbe\x0cB\xdf\xa0\xd2\xb1(\xde\xc8z\xec\x1f\xd2\x8a\x187\xb3\x15\xb1\x9f\xa5\x03\xbd>\xbfi\xf4+\xa2E\xf0\x96ov\\\x02d\x8dmc\x97\xdcII\xbf\x87q\x8c\x0f\x1e\x90\xad\xac\x8d\xa7\xecs\x87\xd0\xc1\x92\xee\x0c\xdb\xef4\xf4S\xb9\xb8, \xbam\xe2\xa0mw\x07\x1d\x01\x05\x08\xe8w\x07\xd1\x9a\x7ff\xff\x99\xd3\xc4g\xbe\xe6\xa9A\x05\x00\xadU\x9a\x93e-!E )\xac\xd6\xf1*\xda\x82a\xd9\xb6\x08\xe8i51\xbf\x05\x1c\xd3W\xba\xa5\xd8\xa2&\xe1\xf9\xf6\x14r%\xdb&\xe3h\x95\x03\xe1\x92\x16\\\xb8e\x93\xb4\x84:p\x99\x8dE\xec\xb3\xe5/V4\xfd\xac\x10U\x9f\xed\xben3\xa7\x04\x1eVuM\xcc\xa3%\xec\x07\xf8\xdb-C \xc4v\xfc\x8e\xf9\xc1\xd6O5~N6 \xd1,9o\x0d`c\xf5\x14\x87\x8dKU\xd2\xb2\xf9\xd0\x18\xe3j=\xf2\xf4\x99\xb3Q\x83\x8c\x93\xa5w\xabL=\xfb\x8d\xa4AM\xca\xc6>\xa5\x81t3[6\x8f\xe8\xe8\x0c\x8d\x1c\x19\xa8\xa1\x0d\xa1VC\xf0 \\\xb5\xf2rpl\xac\xb6\x82\xa5~\xba9K=\x90\x1f\xc2j\xd5B\x8f\xfd\xcdj\x15g\xbe\x1d\x89\x96.w\xbf\x02\xdf\xdb{\x0f\x13\x83\x1d\xeb\xb5n\x80`7;\xd4_\xab\x0f\xf3\x81\xd1H\xaa_X\xf7\xaf~]Q\xbd\xef{\xe5\xceM\xa1\x9e\xe8T\x1b9\xd9\x86\x84\x95\xdeCyP\x011\xc7@I\xaa\x9f\xaa\xa4b\x1f\xe4\xd9\xf0z\xfe\x8e\x89\x0dJ\x93\x9b>\xfb\xb2P\x8e\xc1\xdayH\xe6ME\x80\xcc\xb0\x14\xab\xc2\x0f\xcb\xfb\x11M\xc7\x97\xce\xa8\x0f\xac\xa7\xe1\x97/\xf6\x83\xee\x10\x1f\xa3\xf2;\xd5\xd9jO\xad\\;\x99M\x94 \xb6\x1b\x95>SPk z\x0f\xd0a\xfdI{\xe2\xb8\xc8\xf4\x97 0\xc2\xde\xa6\xa2\xbb\x16\x16i\x08\xbc\xcc\xd6\xa4m1\x17D\xc3\x81\x0c\xd2\x9b\x83\x11\xb8N\x9dJ\xd7[jF\xab\xf7\x04\xc1@\xd5o\xd3\xbeX+\xc7&\x9dW\x11\x10\xe2\xd8\xe6\x1d\x88\xc0\xd5#X\xe5\x03\xeeW\x9f\x1cJ\x17\x98\xb4Ji~\x94\xeb\x1b\xbc\xa6td\xbb\x9e=\xa6\xd9Z\x07\xfe7\xfb]\xe1r\xa1\xb0\xbdGq\x8bw(\xeb\xf6\x80\xf8h\xe3t\xc9\xf3\xb0$K\x8b\xad\x13\xc3\xc4\xa0\xb9\xa25\xf3\xa1\x8c\x82\xacg\xb5\"\n?8 \xd2\x8c\x03\xda\xe5\xbb\xe1\x90x\xb0\xac\xb6|\xf1E\xd1\xa3!\x99\x03\x9f\xde\xbe{\x86$&\x87\x9a7\xeb$e\x01\x91\xd5\xdb\x1aI\x9d\x19\xb8(ab\x17\x81\x95 \xb6\xd5\xc57\x9b\xb4m0$\xb4\x10\xea{\xe2E\xcb$\xe6Cc\xe5\x1e`\xa6=-$\x909\xbb=\xd5O*|Y\x0f)My,5\xd0f\x1fb \xe1,\xect\x93\xb5\x08\xc6m \xcc\xccVii\x11\xb5]dHGo\x0f\x1e\x90\x89r\xa4+\x1d\xc6\x14\x85\x93\xd9\x8e\x85p6\x88\xb1\x03E\xb2\x08\xfc#\n\x88sF~T\xb9\x84\x13\x19\x132%;\xcfI^\xf1\xee\x96\xb7\xfb\xc5^\x1bf\xd9v\xb2\x89\xbbtH\x1c=\xe5\xa6'\xc2\x94\x1c\x92T\xea\xd8H\x8dE\xb9\x1c\xa6$\xbd\x05e\x85\xf8\xbf\xc1\x96#\xbakn\xa1y\xad\xaf\x87\x87\xda\x13A\xdfe*\xb0\xf1\x0f2d\x9b\x1bV\xee?d[,8\xd3#\xda\xe3O\xa8%\x809\xbc(\xf4\x02\xbe:\n\x91\xe0\x90\x845\x19\x81D \xe07\x0b\xc9(\xee\x03p\xaa\xc0\xd4\xe6\xa8\xa0\x8a\xb0@\x15\xd9P\xb7E\xe2\x95\xd0@\x15I\x15\xef}\xac\xcb\x06\\\x18\xe8\xa1\xec#o\xbf2\xc2\x86L\nO\xc2B\xe9Ut\xbf\x1fv\xb24\xe8V\x18\xaa).iEU\xd1m\xc8g\xbb,\xb7\x1d\xc5\xd9\xa4\xd7s\xe2.]\x10\x95\x0f0\xf2URb\xacMP\x9a\xd9\xa4\xc8\x1d\xca\xac\x1a5U%\xa16{Y\xf1 r\xaah\x88\xbb@\xd7OS\x92\x8d\xb9\xdb\xd6Ou\x1a\xbb\xa5\xd9d\x03\x896\xef'\xd1&-\xb2\xba\xd6\x90\xac\x9a\x18\xc4\xc4\xdd\xc5\xfc\x95:1fJ\xcd{E\xdbT\x8bm\xda\xddp8\x0d\xc5\xf0\xfd\x1cdK\xe9]@\x1c\x01!\xca\xa2\x91\xdeR/\xb4\xe2\xfe\x9c+\x1d\xe3-c\x1b\xd8\xd9Y\xf7\x9fy\xb9\xfb>i\x8az\xda0\x08\xeb\xc9\xcb\x14\xc62\xb2\x11\xee\xddZ\xdc\xb7q]4P\x95\x14\x16+|\xd1F2\xe4c\x85\xf4T\xa7[VS\xeb\x95\xafx\xba\xaf\xb8\xd0iA\x06N?_\xc9<\x88h\x18v}\xd9\xec\x05\xca\xf5\xea\xa7\xd5\xf9\xec\xad\xdb\xdf.*\xd5\xdaA\xcc\xd0\x0eb\xa8v\x10+\xb5\x83\x9em\xc8\x16\x0f\xfbI\xb2h\x96Qo\xf9\x91\xcdos\xa2.X\xf6!\xbf\x0c\x03\xafp\x94f\xe9\xb9\xe6\xf2#\xcd\xe5Ov\xda\x18w\x194\xa7w\xedn\xa4\x14\x99\x0e\x0e\x80=\xd3\xaf\xe4\x8f\xaf@I\x8b\xb7\x81\x0c\x04\xd7\xcbv\xc7g\xc8\x98\xd8\x06D\x05\xd5\xb3\x8d\x07||\xc6\xce\xfb|W\xcdl\xdf\x8d\x7f;\xe1s\xf3~\x10\xcc!*)\xe3B9\x86[\xdcQ\x15\xa8\xae\xa6\xae\xa6l+j\xa9\xacPbS\xf9\xfa\xb5\xaf@\xaa1\xb0\x1b\x8fQ/\xcc\x8d!L\xedc\x02\x96\xf0\xb4\xdf\xa6\xb2\x93\x19\x88\xcd\xaa\xc56R*X\xdd\xc9\x96a\x82\xd7l\x1d9\xcd\xb2no\x17\xc9_\xef\xde\n\x94\xb1<\xbdY]rp\xc7*\x7f\x8d\x057\\ys\x9dD\x8c\xdc\x98\xc9U\xed\x00\xba{\xb23\xd9\xd9\xc3{\x95\xfc\xb3Z*\xa3s\xf2\xa4:\xed\xe0W\xf3\x7f\xffo\x9dy\xeb8\xcc*\x04\x0c\xa8\xe6\xcd\x92s\xd8=3~^\xc3|\xe0\xb3\x1dkmy\x01X\x0f\x0cp\xab\x91i\xb1\xb2\x95V\xb2\xcf\x1b\x9d\x90F4\x9b\x19\xc7\xf2\x0e%;0_\x12CR\\Y\x19\xc1\x12\xda\xf6?\x18/\xb53^\x86^\x0e\xb7\x9a9\xed\x0c\xa5\xa9md\x1a\xdf\xba\\\xda\xddvG\xb8\xaa\x0e\xd2\xbf\xca\x04\xd7\x16\xdc\xd5r\xda\xe3\x96\xb4\x08\x02m\xbbS\xd6(\xc5\xd57@-\x8e\xd3\xbf\x891\x17\x1eb\xe4I\xdd3\xba\x0e1\xf2\x14\xb1\xe6*\xcd\xad\xf6'\x0d\x07\xa79x\xa4\xaa~\xbai\xd9\xacd#\xd5S\xabb\x1e_\xfc.6E\xd8D\x12p>%L9\x8f\x0d~g\x10\xef\x97\xaa\x1a\x87:_\x90\xaag\xfc4\xa3Y\xe0I\x1e\xca\x10\x0f\xe5);6\xa3\x19\x9b\xf2\xd0\xbc\xb4NP\xea\xe5\xb4\xd5k{\xd3\xdd\xa9\xe0\xe2\xcb6)\xe5\x8a\xb4\xe3\xb4V\x8b\xa4\xea!\xa8v\xac6EN\xfd*M;*5\x0c2\xfaUX\x1f\xa8\xb6\xfa}\xa6\xa9\xa8\xda\xccW\xc1J\xed\xcfV0\xad\xe6\xd9\xb2\x8a\nP7,\x0d \xc03\xaa7\x18\x12>\xa6\xbe\xff\x81\xf30\x88\x16g\xdc\x0dk\x18\xe1^\x1c \xef\xee>2\x10\xbfD\xfa&\x14o#@\x8a\xb5\xcf\x9a\xe7\x0d\xa9\xc5\xb8o\xe1Q@\x15\xc6eD\xd3|p.\x0eH\xb6L\xf8\x15\xacjA\xd8I\xfd_\xe7\x98F\x11\xcf\x88\xc0<\x84\x12/\xa4iJhJh\xf1%\x07\xc1\xee\xea\xd6\xb8\xd0\xb5\xca\xca%/\xce\x83\xea\x92\xa8\xce\xa1\xa6\x9bM\xf3\x14X\xd3\xac\xdb\xe6G\x9b\xbb\xd4\x10\xfb\xb0R\x9dB5Z\x81\xaa\x8e\xe9-\xf2\x97z7\xc6A\xfa:\xaa`\x17\xe0\xdc\xea\xb5\xe3\xb2\x19\xbcE\xd5k\xb2\xf6\x9en\xd8\x1c\xa3\xea\xba\xc3w\xbc-\xb5\x0b\xa1\xceU\xb5a{\xcc\xea\xdd\xa6\x1e\n\xde\xa6S\x96}\xab\xf6\xe8\xaa-m)1\x88\xc9a\x9b\xa8\x81\xdf\x07j\xb0\x9c\xc5\xfb\xb6\xb3\x189\x8a{\xac\x1a\xe4\x0e\xb5f\x87\xfa\x8e\xfbu\xa5\xc5[\xdb\xad\xfa|%\xf5\n\xab\x83jbbjb\xe2j\xa3\xbb\xcd-\xad\xbeb\xa8\xbc\xa0\x08\xfcc@\x1e\xc9\xf6v\x93\xf8\xaa6\x91\xa2\x9d\xdd\xd4\xf0R\x0b\xec\x1d\x02\xec\xd9\x88\xad\xe2\xecfJ B\xa5\xf1\xb9m\xe2\x10D\x0bW\xfa!\xa8\x93 m\x14|*\xfb\xc9\xaf\"\x96\xbc\xe4^\x0e\x12\x0e\xe55\x89\xaf@HfSb\xd06\x0b\xe38a\x1e\xf5\x96\xacP\xe5\x967P\xdcEn1\x9b\xf2\xc0\x9aT\xb7FX\x1d\xca0^\xceo\xd7{\xde\xd6h$\xc6!\x17\xbd\x1f\x8d~\xbb\xdecNm\xaf\xd5\xce\x02\xab\x8eW\xf3\xf0\xef\xaf\xc4^t\xdb\x1a\x04\xba\xadQ-\xda\xea(\x930\xce\xa3\xea\xd8\xd6j/qK\x8d\xda\xa0\xf7\x82R&\x15b\x03\x0f\x1b\xc0Q4\xea\x14\xb8\xc0\x01\xe7\x19J\xd0\xba\x07\xd1]j\x99\x99\x91Y]k\x86\x07\x0eP.\x06\x86\xf39\xe1\xcfI3\x80\x1d\x89\xea\x9b\xb4\x12\xb5{G\x1a\x03e\xcf }\x0e\xbfh\xb5t\x80\x96~N\"2\"\x01\xf9\x9e\xec<\x1f\x80\xbc\x8bU\xaf\x91\xa2\xd1\x08-\x16\x90\x11\x89T1@\x04\xd5b\x01ZL\xef\xfe\xe89\xc9G\xa3\xe7v^\x1dB\x02\xb71\x8dHK\x1b\xad\xb0\xac$R\x15\xa5\xff\xa9 a\xae\xb3j\x0b\x83\xf4(\xf2XZ\xa5\xc8m\xa7\xacm\x89$\xc9lr\xbe\x89\x96W\xdb\xdc\xf5gIk\xea\n\x06\xea\xb5\x88\x08\xda8\x07i\xe8\x88\xec\x0e\xbcS\x05\xd1\x01*\xf1v\xa6x\x1c\xb1\xeb\xec4\xb8\x0c\x83h\xf1\xdcJ\xa7\x93\xda\xc5X\xa6\x14Z\x9e\x14\xd6q\x12\xe9\x0e\x86d_2A\xe3H\xab)>x@j\xf8\xcc\x80\x90\x11\x0d[\xbeJ\xcaE\\\xc7 \x16c-\xfd\xb4G\xe0\xb6;\xd3\x94\x04\x981,=\x17\x8d\x9e:A\xe1U\x0fx\x1c\xab\x9d[\xcedVWa\xba\x9b\xa8\xe2vD\x81\xc0\xd0\xb7\x15q\xdc\xcb\x85\x8aEj\xfa\x08'\x07\xf1\x1bL\x19h\xb1:x\x16\xef\xcb\xfafqJh\xf3\xb0\x15\x83\xd7\xb5\xd7 (\x02\x07)\xd8\xce\x04\xd1B\x85M\xb4\xb8\xa0k\x9b_Qfv\xdb6\xf2\xf1<\xcc\xd3%\xb4\x82)-\xf4T\xaa\xa1\xf3\x86\x04Gv%+\xbb!e0\xc9`\x08\x85A\x17m\xee\xd6<\x91}%W\xcb d\xc4\xadKT\x8cX\x82 \x97\xe1\xe4E\xa5n-b\xe1 \xa1\x81\xc5Qd\xce\xf8\xf9\x90,\xc7\xcaC\xd7\x99\x9a\x03\x97U\xa6C:\xb53\x87j\xd8\x18;\x1c\x17\xc7v.\xde\xa6\xa9\xd1\x18&lu\x18$Du\x81\x18\x19\xf5\x01h\xde\x19\x96M\x06n\xb1\xa2\xaa!\xf8\xc5qv\xc5\x8f\x92\x05\xf0\xb5\"\xa7\xe2dx\xad\x1c\xefW\x1b|\xc1\"z\x192\x7f*0d5\xa7:\xc4X\xdc\x95\x9f_\xbf{\xf9\xfe\xe7\x8b\x1f\x8f\xde\xbd|s2%\xc1\xd8\xa3\xd1\xa7\x94\xbd|\xff\x96\x1c\x92\xab \xf2\xf9\x15\xc1\xca\xa5,\xfb\xb1Vy\xbb\xe4\xa81\xe1bQT\xc7\xa6\xf1\x85\x13\xdd\xb1\xce\xaa\xd5\x10\x88Sb\xab\xb5\xd6 mV\xdar\xfc\x96U\xb7U\x9a%4\xfeAJ\x1faQ\xf4\x13V\xeb\xdb\x0drH\xf8X\x06\xf0W\xb1\x89\x96\xa0Z-\x0e@\xa8N\x124r\x99\xb1\x81\x16\xd7v5\xe8X\x892o\xdb\"%\n\xbd\xaf&\xadx\x14d<9\xf5\x12\x1e\xca\x88\xe8]\xd3\xaaQf;\x94x\x98\xeb\xb9r\xad\"\x8e\x9b\xbeV\xdb\xda$<\x8a\xc1\x97U\x0c\x89\x93B#\x1dD\x8d\xa2\x8aN\xcc\x11\xe9)\xd3(\x17T\x1b\xd1$0f\x0c\x86\x06\x02\x05\xb4\xc6\xeei\xb7\xcfI\xc7U\"\xce\xf5\xedr\x81\x1eF7\xf18a!\xa3)so+\\(\xde,$\xd7\x12RoEr\xf5S\xc1.\xc4`?K\xe4\x067\x1d\x86\x0eY\x91q\x88\x8c\x03\xc4\xc5\x8a\xe9\x82\xfd\xf2~>O\x99\x0c\xd82\xf6\xb5\xc6\x82\xfe\xa1m4\xe4:z\xc3\xe6\x88\x00\xf5FW\xf5\xeb\x06U\x9d\xf1\xaaX\xf0+\xc1\x82\xceC+;\xbfm\xa9\xf1O\xd5_\xb7\x9a\x89\x92\xf8\xdd\xaf3\xaa\xea\x9acb!~\x1b\xd7\"\xed\x81\x16\xf6\x9e\xe0\x91\x16&\x8f\xeb\xf5\x84\n\xbe\xde\x1e\x0f\xa7\x97q\xbe\xc9\x10B\xd0q\x10\xfd7\x83qi\x8e\xef\xcb\xf7ou\xfc\x8d)I\xda OVqvcT\x9b\xb7\x02\x0b<\xf3!\xcc\x17A\xf4c~)\xb8\xdf~\xc0\x9f\xb2 L\xc5\xd9\xde\x05~\xb2\n\xb2\x8c%S\xf0\x9bg\x05\xfd\x11t\x88\x8a&\x87m\xb0\x05\xef\xe8\x95P\xd5\xf5\xf6/\xe0\xbc\x1e\xd7\x99\xa6\x00g\xb1\xa8e-\xa9\xb5\xf7\xb4\x9e\x9eV\xd4\xc8'\x8f\x9e\xd6\xd5\xc8\x15\x17\xb6[\xff\xbe\xd7-\x03\x01\x8e\xe0\x94\x85r\x08_G\x82\xd9\xa5\xf8\x98+\xd9H>N\x80\x16eE\xa9\xea\xc0c\xf1\xb9\xcd/v\xca\x7f\xb4\xbc\x97\x8e\x0b\xa2\xaa\xc3&\x92\x8eK\xa2\xce\x85X\xe3\xbd\x0c\xad\xea\x02)+\x1dP\xa9\x1f \x94S\x17D\xddu\x04\x94\xa4\xa8\xa2\xb0.F\x9da\xc6\xad=:\xb6\xd1w\"\x9e\x05\xf3\x9b\xa30\xc4\xbeU\xed(*\xf8B\x98\xfbv\xc9W\xbb\xe5Aa^Pk'\xa8Q\x94\x94Ldx\x99D\x8c\x14\x0c-\xd5\xca\x86\x8e\xef\xd5\x06\xc1\xab\xad\x83z\xc5\xb7\xb2A\xc0:\xdf\xf1\x9d\x8d\xcd\x12Z)l\x9b\x81\xc1&\x0d\xae\xf8\xa8n\xfb\x18b\xa6`W\x18hl\x11\xed\xca\xba\xa1\xc6]y\xed\xcd\xae\xf3\x82,\xc5>7\xb0.\xcc&\xcfR.\xbf\x12\x91%\xee\xdc\x14)\xa4C\x12\x0f\x86$\xa8\xf2\xee\xf3\xba\xe1\x15\x14\xbf\xe3\x01\xd6\x90\x05*]\xea\xddz\xdc\xa7@\x1dl{\xa8\x18\x8f\xb6h)\x94\xd78\xdap[*\xa8%\x96\x8d\x98KO\xe6\x85\x90\xe0\xc1\x03\xe2\xa4\xfa\x80\x01\x85/M\xb9\x8a\xac-\xd71\x8f-\xc8W\x8cZ\xf3\xe8l\xce\xeb\x82e\x928N\xa7$'\x87=N\x00\xcd3\x16tt\xd16u}\xff\x91F\x8b\xd6\xa0,`\xdb1\xce\xd8u\xa6d8vP\xb8\xb3\x1d\xfby\x1c\x06\x1e\xcd\xac\xd7\xb5 \x84\xaa?\xe3\n\xcb\x9dI\xb7\xa6C\x92\xc8\xd3\xca\xff\x00\xbb\xcd9\x89|@\xaaI\xe6\xd8\xb9=-rK\xcc\x16\xb6\x9e\xb9-\xbc\xa1\xf8VC\xed\xcf|X\xe4OA\x03\xa5\xe9\xf7\x95\xe0\xcc\x1e\xe9\xc2\x07\xc4\x98$\xb9\x12*\x84\x8dX4H\xb2mh\xe5-\xb1`\x9dv\xd4-k\"\xe6\x174mz\x86\x05\x95\xf3M#o\xc9!\xdep\xd7tKH\xb9,\xed\xb0\xd2\xb7\xc1\x9c{y\xda^iP\x02v\xd5\x99k\x7f \xb0\x86\x8f2\xd7\xe6\x91\xb0]$\x90\x8fa\xe2\x0b+\x80\xe2\xeazH\xf21\x8b\xfcf\x06>\xf9:XC\x9f\xd8=\xa8\x07\x00\x82.!b\x98\x04P\xb723\xf5\xd1\xaf\x8cpu\x14\x07\xe4\x90\xec\x10A\x04g\xfc\x14\xd40\xdcA\xe7~\x0eA\xf2\xee\x85<\xd2h\x02\x1f\xdfPa\x15\xf1]p\x06\x12e)\xec\xe8P\xedh\xb7>\xc6C=\xea\xaau\xf6\xe5\xe8)\x0d\xa7z\xf9\xd0,/^\xcd\x99R\xef\xd5\xae\x87\x9bt]\xf0\xbb\x1e\xd9&-\xee+c\x13\xadV\x90)\xde\x9bX\x0c\x06\xe03W\xb94\x8b\xf5\xf0p\xbb\x03#\xad\xd2\x14\x8f=\x1e\x864N\x99%`k_\xf4\xe6\x8bs\x83L\x89\xd7\x81\xe6\x04\x9c'\xd0W\xcfu\x8a\x90\xf3\xa9\xf5\xb8\xear\xb52\xd4\n\xcb]\xe7V\xf7icX\xbagbQ\x90CIL\x00\xf2\x801!\xd3\xe2\xd7\xf7\x05\x8c+\x01X\xe4\x0f\x15\xa2\x03\x08\xf0Zi\x94\xd5\x99,\xf2\xc1\xd4\x14?\xd9d\xba\x9c{\xc7[\xd2\x84z\x19K\x1ci\x19\xce[\x8e=^\x14\x16\xcb\xa4R4!\xa3\xa2\xb8\x18\x1a\x8c\xeb!=\x84\xb0D\x1d\x1b\xc8)\xd3\x86\xc8\xf4Q\x81\x1eN\xf6\xa5E\xd4\xb9\xc1f\x81;8\xef\xdc\x86DI\x1d\xde\xd2l9^\x05\x91[\x0e{\xc7G\xf2\xaa\x93\x03=\xad\x94L\xcd\xca\xe4\xf4\xb6\xa9\x95\x89\x035\x1a\xb3\xebL\x94\x7f\xf0\x80P\xf2=i\x0d\xc7C\x0c|\xdd\xe2\xa0\x8d\xa86Ri\xff\x92Z\x01\xed\x9aJZ9\x15\xb4\xd6i\xc7xx\x1a\xd0f7FTo\xc1\xe9\x87\xd7\xa7\x87\xf3\x0d\x11\xa0~\xe6%\"\x0c\xe1L\x15\xe8\x9aK\\=\x04\xc7Eb\xc1\x1f\x85!\xd4\x96\xba\x10/\xe8{\xc0 n$\xb8\x0c\xf9\x959\x00\xcb\x99q=U\x91\xa7+\x82\x8d:\xd7\x08\xb6\x91-\x8a\x1a5\xe1\xc2{b\x1d\xfeN\xb1>.\xc5\x93\xb3\xbc\x11\x13T$\x17\xdcKbWB\x00\xe1\xfdx\x1e$\xa9t\x91_(\"\x18I\x95\x82\x9a\xdb)\x12\xb1\xdb{n\xff\xa0\xdd\x16\xca\xd4\xa0+\xf5\x1a+\xea\x86\x8d\x82\xb2\xad\xa5\xeaCuH\xff\xd4\xfc\xd5\xdb\xb3G\xc5`-\x01\x9cl\x18\x9f\xed<'\x91\xb5'{\x92\x13,\x88\xbf6\x1cJ\xc1i\xed6\x89\x80\x1bQ\xa4\x90Fr$ /\x94\xea$%\xdf\x9b\x86b\xf6\xad\x16\x81\x96)\"\xd3\xd4\x8f\\\xceS\x92\x91\x11\x12\xa6\x8a\x90FHi\xfd\x04\x851b\x05\xb8\x91\"\x07\x8c\xbb\xd1\xe0\x9b\x9a\x7f\xec\xef\xedX\x8c\xb0\x8be(\xd5\x9c,\xfc\xfa\x96b{\xb6\"\xb0\x01WVe\x11$%n&\x13\x137\x1a\x14\xfaR\xc6:\x13\xb8\xc2\xf1$\xf1\x98*\xbb\xb6C\x88f#\x93D\xb1)\xd9\xda\x92\xf1mhR(\xda\x7f\xe0i\xa0\xb9\xb4\xad-w\xf2\x84< V 1\x84\x0d\x15\x8d;\x0f\xdb\xa4c\xd8\xac\x17~\x80F\x1e< {\xe0\xe9\xa6\xc9\xdb\xdc\xa1}\xfd\xda\xa1\xb9^\x97\x899\x19W\xec+\xe0\xf2\x8fL\x8b\xe3e0\xf6\xd9\x9c\xe6a\xf6S\xc0\xaeD\xa6$;Pd\xb6\xe5nI\x17\x83\x16_Qc0\xba9\xac\xder\xaa\xd4)\xeak \x84:\x118D\xaf\xa4W\x95\x9c\xa5v{\x13\xe0\x1d]\xb1\xfb\x9dwg\x99e\xf1\xf4\xe1\xc3\xab\xab\xab\xf1\xd5\xde\x98'\x8b\x87\x93g\xcf\x9e=\xbc\x0e\x83\xe8\xb3\xd3\x94\x90!\xf0\xbf\xbc}#\xca\xec?\x8c\xe8\x8a\xa51\xf5\x98\xd3\x94\xa05\xf1\x12\xf5<\x16e?\xb2`\xb1\xcc\xa6\xc4\x91\xaf\xa3%\xbc#>\x9a\xa8\xe7\xe5\xab<\x04O\xd6;H\xb6\xef\x07Y\xb0\xb6d\x86\xc1\"\x12s\xff\x03MY\x18DL|O\xa7\x8d.U\"\xf6\xd10\xe4W\x1f\x19O|\x96@\x99\xf2\x15\x85\x8e\x97\xf4\x92e\x81\x87\xb7b\x15\x87A\x96\xfb\x966&\xf42\xf0^\xf1d%>\x04/\xa39OV\xd8wR\x0fn\x07\xb1Z\xb2, .\xf3\x8cI7\x88N\xe5\x1d\xabJ\xe7\x8b\xa5g\xc2\x8bw\x0c>\xcf\xf8G\x06\xc6\x92\x02\xba|\xc3`\x7f\x0fVy\xb6D\xdb)\xc6\xfcU\xc2\xfe\x91\xb3\xc8\xbb\x99\x12\xa7\xf2\x8e\xd4%\xf2?$|\x1e\x84LA\xab7\x0b\xac\x98\xcf\xd3e0\xcf\x14\xb4x\x1f\xa5\"\x01+p\xc9\xaf\xf1V\xb2E\x10\xe19\x01M\xf1\x8c\x1b4\xd9\xa3\xa1\xf7\x16\x0e`G\xffD\x1a\xe2\xd1\xb8\xd8\x0f\x1e\x8d\xed\x9b\xc1\x0b\x83\x18\xffN\x18\xc4\x1f\xa8\x18tG\xfc\x1c\xc54[Z\xca\x7f\xcca,\x01,\xc9\xd1\x91\xd4\xb5}\x8a\x02\xc1w;\x95w\x0c\x9e\x87\xb3#\x1b?\x98\xcf\xf3\x94\x1ds\xe9\xabsJ\x9cZ\n\xd2\x1b?H$go\xa9\x11\xbc\x9eZ\xf2\xd6\x81m |\xbe\n\"Z\xc1\xef:\xa9\x0d\xbd\xfb\xb9\xa5:|\\}\xbca\xcc_0\xb5\xb7\xf5O\xe4[,dkj\xed\xb8\xd4[\xfb\x81z\x9f\x17 \xcf#_\xd4\x05I\xa3\xcb\"\x0d\xab4\xc2'U\xd0L\x91m\xda\x04\x9b\x9bD4\xfc\xc8R\x9e'\x1eK?\xb2\x7f\xe4A\xc2\xe0\xa3\xb6<\xe4\xe3\xf3 \x0c\xd1\x0f\x88\x8c\xf71\xf5\x02\xf0k#\xdeF\\\xbeZjQ\xa8\x08 -\xa8H\xeew\xdb\xe72\x96|d\xa9\xacB\xfe\xb6V\xa1q\x99\xf1\x86\xc1\x86\x9c\xfb\xc7\x02\x13\x08P\xf12\x02\xbc`\x035\xba\x0b\xc0-\xfd\xe5^\x9e\x8a\x99\xc5\xfb\xc2\xa3\xec\x15]\x05!T\xc5\xa3l4\x877\xb4\xa2(;\x05]\n \x98\x06\xbf\xa3\x03\xa7\xc0\x8e\xfc\xff\xce\xd3\xcc\x04\x1eQH\xb2\x95\xc9\x12\x96y\xcb\xa2\x80|\xb5\x02\xdf\x84eC\xc4\x8b\x05\xf0'\x9a\x04\x12U\x00\xe8Z\xbeZ\x80\x7f\xd6g!\xc0^\xd9\x0eC\xa9\xae\x83\x0fg\xc2Wx\x06\xbe\xc3\xe7\xf8\x0e_L\xf0\xe4]<9\xbc\x89\x97\x8a\xfe\x82\xdf\xa3\x08'\xbe \xf3}\x12\xb0(\x03\xcc\xf0#O\x82\xdf\x05\x9f\x18\x16%y\x99;Z\x16\xd9=\xea\xfa\x89%Y\xe0YjZ\xabL[=\xe0\xb8\xdb\xd1?1\xa8\x84\xfa\xa2:\xd0\x12\x99K\x9a\xb5\x91\xd6RNo\xc2\xca;\x02\xbf\xa4\xd1\x02Ned\x98a8\x8e\xfc\xf5/S\xe2\xc0\xef\x11\xf5\xd7\xa3k\xac\x16\x91\xfb> \x16AT\x02sxG\xe1\x03\x9f\xf1EB\xe3\xa5\x85\x90\x0fVt\xc1L\x92\x01\x12ZI\x86 \"xU\x11\xbe\x86\x80\xd8\xf1X\x8c/\xeb\xcfx*\xbeJ?\xe3_\xf8\xbc\x87'?\xc2\x93Y\x12\xb1\xf0-\xcd\x92\xe0zJ\x1c\xf3\x15\xe9\xad\xcc\x16\x93\xfa\x06\xe4UE\x892\xc9R\xca6\xd9\x9f\xd9\x0d\xdci\xa4P\x95\xfa\x8d\xd6qs\x1a\x8b\xd3^\x01\xaa\x17\x1c\xf2,Xi8\xf8\x89@Iy[\x81;\xcdW\x14:\xcbXr*p?\xac\x0b\xf9>Je\x02V@\xa040\xa6\x95'\x8d~\xb7\x1e6`\x8f\x0e\x05\"v\x14-\x00\xe96\xd2\xb0r\x1cp\x012\xb2+\x9a|f\xc9 \x90\x1c\xf2\xf7\x88\xa1\xb4\x86\xcc|\x1b\x18\x80\xab\xc0\x0ex*\xaf\x085h*o\xa1,\xc0\x05\xd7c\xbeZ\xa15\xf60\xde\xac\xb0?\x07>\xac?\xe3\x0d\x85M\xf1=U\x84\xcb-qV=\xc9R\x9d n\x87\xcb\x96lE\x15\xa2\xc6>\xcf-\xd2\x82(_\xbd\xf72\xba\x86\xf5[\xbe \xdf\xd0R]\xa4\x12\xae\x89\x164O\xbaa\xc73\xa5<\x04\xcd ld\xa7q\x00\xd9\xf2m\xdc6_\xb3d\x1e\xf2+k\xa6\xd8\xe4Z6:%\x8eN\x1a\xc5*\x0d\x1b\x17\x05s\xb6\x0c\xbc\xcf\x11KS\xb3\\\xa6\x13\x91\x821\x0d\xa2\xec\xbd\x92\x08\xc1\xcb\xc8&\x10\x8ai\xc4S6\x018\xf1k4A\x81\xb2e\x81&\xcb\x17\x1cRP\xe7\xb5\xf5\x88\xa4\xda\xcb\x9a\x07v=\xc9^\xaa\xf6)\xeb78\x1c[\xa0\xee\x0e\xe0\xf2}\xc4 \xc1V\x00\x97\xa3\xc8\xac\xa3\xec\x17]\x8f\xf8m\xad\xe2(\xfb\xd5\x80\xfb\xb5\x05\xeeo\x06\xdc\xdf0\xb8\x84\xa5,Y\xb3\xa30^R\xf0\x1bo\xbc\xb7\xc1\xa71\xf3\xb2\x8fby\x9b\xa5\xcaT\xb4,`\xee5+\xc6\xb7\x92\x80\x94\xc07\x9d \xa2r|\x18\x136\x17#(\xfea\xd5\xb1\xf9\xaf2\x17\x1b\xb2\x82\x9ey\x0d+\x0b\x00U\n\x08cP\xba=a1\xa3\x19(\x89A\x81\xe2\xcd\n\xfbR0\xe1N\xf1\x1b\x85\x93<\xe8\xc9u\xc6\xa24\xe0Q\n\x05\xea\x89-%_1\x9a\xe5 3\xcb\xe9$\xb4\x94\xd2oA\x074\xcdCK\x16\xcflR\x94\x04g7\x12\x1c\xf7\xa6\x1e\xb5\xb0\x87)c8\xc3\x9f.i\\!I!\xa1\x95$MC\x1e[\xbe\xa2 \x184\x8fyyH\x13C\xe8SO\xc2\xbe\xa5@N\n\xb9\x84SO\xc2K\xd9\xba\x1b'\x8c\xfaoY\xb6\xe4>\xd4U\xbeb\xf5\x94\xda]\x02\xb8|Ca\xfd\x97l\x1dh\xe1\xa5\xf9\x8aB\xb3\x15.\xe0\x169kKN\x90y\xcb\xb3 \x84\xe5h\xbc\xa1\xf5\xf3X\xd3\x86\xe2\xb7\x95.\x14\x99\xa5\x0c\x02@\xed\"\x884K\x82\xcf,[&<_,\x8dc\xb3\x92\xdevvV\x00\xcd\x03\xb4ZC\xdb)*o\xb8,\x03\x94\xf0\xcf\x96\x95 Y/i\xba\xa4IBeWE\xca\xc8\xd7I\xf8\xa7T!^\xae\x81\xa2\x14\xb7\xaf\x04\x01\xf3&\x88\x98G\xe3\xb2L(\x13Z\x0b\xfc7\x0f\xa2j \x91b-\xf26\xc8\x04\xdd\xb1\n\x8c\xa6\xad\x8a4k1s\xbe\xa1L\xeb\x8c\xf3\xcfL\xd3\xc2\n\xfc\xcaB\x0c\xa7y2\xa7\x1e;\x95X\xc81_1\xe8\x1b\xb1\xd4\xdf\xd0h\x91\xd3\x05\xc0W\x12\x90\x12\x19\xbd\x0c\xa5\xb7&\xb1d\x8c7\x146Y0 \x02\xd4/+\xcc\xaf\x05\x0cv\x96e\xec:;\x02\xfdV\x01\xc6\xae\xb3\x91\xd4v\xb5\x80\xbed\x1eO4\x0e\x00p\xbfH\xb1\x141\x91/\x94h\xc3\xbd\x02\xa0\xa0\xf9\xca\x17\x0c\x92\xa3\x1b!+\xe98$7\xc7%\x019. \xc8E;k\x14t\x91\xd6\x86\x06\n \x13\x05\x94%\xdb\xb6\x7f\x1e\x05\x9e\x8d\xb7Qy?\x04~\x00\xf5\xc1\xdb\xe82\xf0\x03{E\xa0|e@\x83\xaa:\x0e\x9e\xa5\x1fXr\xb2\x92\xc0Y:\x8a\x05\x85\x8a\x11\xbf\xeb#\xe3>\xd7Y\x8f\xca\xeb]\x0c\xf8G-\xaar\xd6#%\xb6\xc2\xc0^\x9b\xb2%g=2dM\x18\xf8\xdb\n\x87\xe8\xacG&\xcb\x88\x15P\xdb\n\x19\xd65\xf32\x9e\x9c\xcc\xe7\xcc\x13xF\xbe\x8e\x18\xbcc5\xb1$\xb5\xb1jk\x96dG\xfe\xfaW\xa8&\xc9@\xf0\x86\xa1\x1d\x91Y\xca\xdd\x00\xb4E\xecVB\xffZ\x83F\xeb\x0e\xd8\xd5\x0f\xfcZ@\xca_\x16\x983\xc0 \nL\xbe\xa0\x90ip\x19\x846n\x18P%>\xacW<\xf1K\x89\x8fxk\x91\xf7\\% \xa9Q\xb7E\xeam\xb4\xc2o\x8cp\x9a\xf1\xba\x90\x95\\\xdb\xef\x87\xafq\x04p\x8d#\x80\xeb\xe3%\x8d\"\x16J\xad[@\x91\xf5$\xec\x1ba\x10}>\xf2\xb2\x1c\x88^\x07^\xa7T\xbe[\xc1\x13/\xe1\xa1\x01.\xdfm\xe0?& \x88\x96\xb0\xcb\x04\x15EC\xe6G\xb3\xd2\xb6\x1aO\x97\xfc\xaa\x00L\x97\xfc\xca\x06x\x16dF\x95\x99x\xb3\x82\xca\xab\\\x05\x89_\xe2^\xaf\xc2\x1f\xc0\xd3\xb6s\xbd\n\xa7\x97\x14U\x98\xb8^\x85\x11\xbe\xc8 \xe7\x17\xf8\x00\xd4\x10\xa5SLAG\x81\x8a\xb3W})\xa4\xe8:\xbc^\x85b\xcd\xea\xf6`J;D\xfa2@\x1as\x83/\xae\x1b|q\xdd4\x17W= \xf9\xf2\xefh]\xbfs\xbe:\x8a\xfc\x0fT\x1cQ\xe5K\xab\x7fT\x8a*\x1f)\x17\x02\x81\xc0\x95\xf5@\x11Dz\x1982Ug`\x84R\xcc!\x04il\x85\xa4Y\x1dil\x806 \xb9\xec\xdb >v\xd6!\x17z\x1b\x84Z\xe1\xad \xb0\xb2m\x10zI[\x8c\xdc\x8a\x85h\xcfWk\xb0WH\xd9\xc6\x8cL\xcd\xc8]\xa4\xaa\x9d*#\x02\x8e?\xb3\x9b\xd4\x0d\x06\xe39ON\xa8\xb7t\xed\n\x84t\\\xae\x08\x19\xe7vgH\x02\xf1\xeb\xc1\x03\xe2\xd2q\xe3\xeb\x12H@\x18\xeax\xdf$@\xc7N\xddu\x02\xc7\xedW[\x82\xfe`\x0e\x15\xa4\xa3\x85Guk\xd7T\x81\xef\xe2>>\x1e\xe3>>vw\xeb\xd5\xcf\xc16\xbdj\xcb\xaa50\xdf\xea\xf8\x05\xa69k\xc3;\x8b\x80\"/\x0e\xc8\xa4\xe6=\xb1i\xaeN@2\x12\x02]\x83o\xd0xIS\xe6\x7fd\x8b \xcd$\x15\xaf\x97\x10\n.\x1e\xe5\xf1~J\x1c\x1eID\x85\xa0)\xfdh\xd7\xf6\x06\xb4r\x11\xe5\xa0e\x90\xf5M@\xd9&\x16LC\xe4\x01^\x9a9\x19\x8f\x7f\x08\xf3\xc4\x19\x12\x07\x04\x01\x10\x1b\xfb-\x8br\x95\xf2\x8a{y\xaa~\xff\x95\xdd\xbc\xe4WQ\xf9\xf6)V\xbf\xdf\xf2\x06\xe8I\xe47'\xab\xa9\xa2\xbf\xa1EV\x8b\x05q\x87\x0b\x12\xfbf*\x0dM\xa7=\x0d\x82Mc\xd4io\xd3\xe0\xc2du\xda\xcfB\xd8\xb0j\x9dV\x8d\\\xf1m\xdb\xb17\x88\x1a\xed\xa6\xa5a\xab\x85b\x0f\xdb\xc4[\x8e\xbb\xb4KP&\x84\xd3\xc2PA\x07\xc7o\xb1\xf3\x92Q\x12\xa4\xf1I\x0b\x14\x8f\x05\xd0%\xcf#\x1f|5\xc4v\xd8\x90\xcd3\x13\xf8\x0d\x9b\xdfn\x94\xbf\xba~m<\xc0\xb2n\x0d\x8a\xfa\x9e\xbb\x16\x07,6\xde\x80~\x9a\x03\xa9\xcd\xfes\xc3\x93J\xac\xe6aH\x96Cbq\x10\xa7\x06\x9fC\xb4xr\xa0]58C\x91\x04|\xa6\x98\xd7!I\xc6\xa5\xea\xba\x8e\xb8\xf3Ry\xb7c\xa9\x0bf\x99\xd5\xfe\xfd \xf9\x8c%N\x93h\xfce3X\xee\x9aE\xa0\x84\x9aNImF\xd8u\x96P/\xd3wtu\xca\xa4%|\xf4\xd6\xa2\xc3\xea_\x0fdF\x0em\xb1\xd3\x06d\x8a\x9a[\x88'\xbd\n\xdam\xde=\x9a2\xe3\xd8\x9bZW\x9a\x1b\xba\x1c\x82\x9d;Y\x923\xe9#\x9e\x8f\x95\xaa\xed\x89\x1f\x80\xc8Q\x9a\xf1\xf82\xb6\xc7R\xfa\xa2\xd5\x07T\x8b\xd1!\xb8\x82\xc7\xb3\x8b\xf6\xc1\x99mo^qd\x96\xc7d\xf1\xe5\xbb}\xb8<\xe9\xed_\x87\xe3\xd6\x12\x17\x8b\xf4\xfc\x8eI\x89\xe0_\xaa6\xe9S\xdc\xd2 \xb5\xa6\x14\x19@n\xa4E{G\x0b\xeaT\x8b\xbdz\xb1t\xe7\x83^\xdd\xd2$TG\x97$m\xd5\xd9!\xd5\x91\x0edFZ\x1c94\\b\xfa\x1f\xf2\xec\x0d\xf8\xd3d\xf5\xe8k\x16\xaf\xa3%\xf1*M\x97a\xd1\x03u\xb5c\xb5\xc1\xc3\x8d\xaf.!\xf5\xae\xcc\x0c\x1e\x99\xc9\xe6\xaf\xbb\xc9\xfbP\x9c\xc9\xc9\x95\x05\xdbc\x94\x9b\xd9\xdf\xab\xf3J!\xce\xfc(\x8f\xdd{u&g\xae\xd2\xeb\xf0\xb1jM=\xdd\x97\xf0\x8f\xea\xbdZ\xaa\xf4\xfa(\xacUz\x9d\xe9Z\xa9A\xab\xc3/\x14|\xdd\x07\xdf\x8d\x1c\xcd\xfa\xe8\\*\x1e\xad>\n\x17e\x84\xaa?\xbe\xd6\xf2\xaej\xe1\xe8g\x0e\xbd\xe4\xe0G\xc0\xa1Q \xdd\xe3\x9dD~\xe5\xfdu\xc6\xf4\x15\x89\x91\xaa\xfd\x0f8\x97\x8a\x95\xf1h\xf4!\xa47\xc6\xcf3ya\x08)a\xe0}\x86\x1fUn\xc7\xe3\xb1,\x91C]>\xcf/Cv\xac\x81\xfd\x84.\xf4\x7f\xd5*\xf9S\xfa7\x90/\xd7A\xa6\x7fC\x8c7\xfd\xf2~]\x02\x15\x8d\xf5\x13\x0e\x1c\x92\x9f\xcb.)<3$\x0e[\xc5Y\x00Q\xcc\x1c\x16y\xc9M\x9c\xe9\x17_\xfdH\x12\x0e\x15\xce5{\x16D\xb1lv\x10\xadi\x18\x00\xd4\xe7\x92_\xfb\xccn>$pO\x02\xbf%k\x16r\xea\xeb\xff\xcc\x7fI3Z\xbe\xbde\x19\xf5\x8d\x94\xa2\xd5+\x93\xd5\x83\x97\xb7\\v\x14^\xde\xe7%\x94\xee\xf5\xaa\xe4\x06c\x9afL\xfe\xc8S\xf9C\xcd\x93\xf8\x0f\x12m\xe2\xc4 _\xe8\xc6&4c\xe5\xc0\x80s>\xc7t\xf1\xeb\xa4\x8c}\x96\x83\"~\xa9\x1a\xd2\x8c\x86\xa1J\xcd/WrV\xd2<\x8d\x99\x9c\xb9,X\xa9P\xd4\xf0\xc6soy,\xc8\x87\xb0xUS\x0c\xbfu\x07\xe1\xa5\x18\x08\xb8\x1f\x0b\x8cE\xba\xe6a\xbe2\x1a{EA\xf6\x0e?\x97\x8c\x85\xcey\x0f)\x91f\x8d\xd8l\xe7|\x9c\xf1Oq\xcc\x92c\x9a2w@\xb6\x05c\x16\x06\x1es\xeb\x9b\x95(\xcbg\x87G\x10\xe3\xb7\x99\x0bv\x98\x19\x8f-\xd9\x1c\x15x\x90;\x8a5Z\x0c\xc1KiFD\xb6\x89s\x0f\x92\x8c\x04\x91*T\x0f\xe3\x0b)P\xe3Cr5K\xce\x8b\x80\xd9\x00Y\xf3\xd2~\xa2PS\x91X\x08\x07\xae\xad\x16\xca\xce\x18\xe2P\x8d/\x12\xce\x81.}\xfd\xb2\xac\x1f\xa9\xe9\xd4^\xd3e\x9ee\xd2\x0c\xf8@\x06\xe0T\xdb\xdbHH\x8d#W\xa6\x08TF\x13FU\x9a\xf1m\xfdK\xf4\xec\xb8\x95\x92\xbf\xd8\x90\x92\xe7(\x13D\x13B\x87pR\\\xcd\xd89.-\xd8\xba\xe9 \xf5\xfb\xd3\xeaGpjtPT\xc7\xeaD\xe8\x07\xa6O\x8b\x0e\xe8\x97U\xcc\xdd\x01}\xa2\xb0z\x17X\x81\xf1;\x01\xfd\x1e@pRt\x00\xbd\x86\xd5\xd5 $\x0f\x96\x0e\xb07\xe2P\xe9\x01\xa3\x0e\x9c^\x90\xc5a\xd4\x03Z\xe2\xe7\x0e\xc0\x0fp\xfat\x01\xf5X/\x1f\xd4\xa9\xd5\x05\xa6O\xb4\x0e\xb8\x8f\xe5i\xd7\x05 'a\x07\xd0\xa9<\x1b{@\xf5\xe8\xc3\xa9:S\xbb\xc0\xe4y\xdb %\xcf\xe2\x0e\xb0\xb3\xf2\x9c\xee\x80\xfc\xc9<|;`\x7fV\x07\xb3\x9d\xbf\x12<\xc0\x1d\x19\xe5\xbfj\x8a\xab\x9do\x94\xfe\x9e.\xdd\xa8M\x82\xac\x9f\xfbf#!\xb8\xd3\xdd\xba\xd9\"\x88(`\xba\x84)\xa2\x19\xde\xdd\x9a!\xc9\xf4\xf6\xa1\xdeU\xaeq\xe4\xe9\xba\xc9p\xbf4X\x81\x8e\xbev\xc9G\xaa\x80@Y\xf6\x01\xb4Nc\x15\xec}7\x1a\x7f[P\xe6\x1d\x80\xdd\x12\x18\xa2\xe6.\xbe\xdb\xdc\xbd\x14\x9cUGc^*\xae\xab\x17X\xd6\xdd\xb9\x97\x9a[\xeb\x01'9\xb9\x1e\x80}F\xf5e\xc1\x01v\x02\xf2\xae\xadkq\xadHz\x8e\xfb\x99\xc1\xf6t\xe1a\xcd\x12\xf5\x81\xeb\xb3\xa8\xcfJV\xaa\xbd\x8f\x16\xef\xb8\xa4g\x1f\x8fLABG\x9b\x8e\x9aB\x86\xbe%\xfa\xf4\xa4\xc5\xbb^\x9f\x9e\x9cU\xd8\xcd\xf6O\xad\xef\xf6)\x19\xe4\xa7\xe3\x1b\xab\xbb}\xe3g\xe0\x88\xdb?\x81\xf8\\\xd3O\x9fO\x1c\xf3\xb8\x93~;\xeeF\x98\x1f@d\xd1\xde\xd2\xa6?\xc4\xa6\x08\x96\n.-q\x9d\xfd'\x0e\x1e\xc8H\xf0M\x17\x10\x90\xa1\xbc%\xba)9\xadf\x01u\x80\x05\xed\xb7?\x17\x83!\xb9\xa8\x94\xbd\x07\xa1/\xdcV\xf3H\x1e\x89\xa5\xdcw\xeb\xd4e\xe3\x8b\x8c.\xd0\xdb1b\x08j\x05\x1fm\x17\x0f\x04z\x18\x90`\x83\xf8\xac\x9f\x08\x96\xfe\xcb\x17\xe2\x9e(\xde^G\x85\n\x0c\x89\xdf\x0d\x16_\xaamh\xae\x820|\xc9B\x961\xcb\xf0\xdc\xfb\xd8Djll\xbd\x8c\xce\x95\xc3Iw0$>4\x0dR\xbb\xfaU\xbcYd\xef\xc7\x90zG\xd9\xfb\xa3}\xd4\x81=o\x11\x18h\xf7nc\x8f\x86\xa1\x8a\xacn@\x97\xcd.~%c\x9aC\xbc\xf8\xe3\x90\xa6\xa9\xcb\xeba@\n\xa9\xb0\xf4\x8f\xd0\xd4\x06a\xd2/\xb1\xe0-\xb0\xec8e\xb9\xcf\xcb\x0b\xed\xca\xadhM\xfd\x8a\xdf\xd3\xa85o,\x9a+\xc4\x0b\x83\xf8\x92\xd3\x04\xf8\xe6>~\xda\xb54\xa9RP\xe9\x94\x1c\x126\xae\xa4\x17\xb7\xa6\xd5\xe4\xaee\x85Mw\xf0-\xa7;\x90^\x86\xcdI\x08\xeec\x12&\x93\xc9\xbf\xc1\xdaM\x98@\xe2\xbeV(\xff\xf6k\xafy\xf1\xc3-79\xb8\x87\xbd\xcf\xecf\n\xf7V\xf5[4\xa2<\x02d\xa0\xe0\xdf\xdce\xe2\xf1\xb2$\xfc+T\x80f\x83/\xb5\x96|\x1a\xb6\xe5\xaeXF[\xb2\xa51\xa8-\x17|\x19\xa0\xd8\x81\xc8\xb8\x16o\xb9\x1f\xcc\x03pA\x90 8wwR\xbf\x18\x14\x8f\xb7\xa4\xc9q5\xf4~\xe7v\xfd\xccnb\x10\x1cH9\xae\xd4\xfd8\x94nm\xa7\xb5x\xa4\x04\x17\x8f\x7ff7\xb7\xf8\xaa/\xb8V\xf3\xa3_\xbe@z\x1e\xd7\x9a\xc2\xc6\xea\x03}\xdbs\xb5\x0c\xbc\xe5\x86\xadi\x19\x83\xfbll%\x05Eg\xf4[b\x00:$\xc1\xb7P\xe9m\xee_\xfcP9I\xbd)qNR\x8f\xa26\x05\xa0=}I\x93)q\x08\x92\xfd\x06\xf4\xad\x9c\xa3$\xe1W\xe27\x02\xf2)\xd6\x00\x9f0\x83\xc6\x8f\xca\xd0\x04 >ZLM^\xf2\xabH\xc3\xc8\x9b\xc7&\x08\x0b\xa7\xc4\x91\xa4\x1a\x92\xfd3\x18K\xbe?E\xb2\xde\xb2(\x9f\x12\xa7\xa2\xf9\xda\x00:\x8a\xe3\xb4\x13H\xb2MS\xe2\xc8\x1fo\xb8\x87\x19O\xbc\xe5\xbf\x7fH\x82\x08\x14\x84\x00?9\x9f\xa2\xc0gQ&\xf0\x89\xdfjg\x80\xa3\xe0\xfd)q~\xa0\xdeg\x9b\x85\xc5\xb3)q\xce\xe8%\x923\xd9\x15}\n\x19\xc5\xcc#&{ba\xc8\xdb\xedf\xe6\x13\xd1M\x8b\xaf\xcb\xc9S5T \xc7\xec\xc7&\xa2\xc1G!ZR\xb4U\xca\xe6\x9b\x99\xbb;S\xb8(L-\x03\xbb\xfb\xb4m%\xef\xedZ\xd6\xf0\xde\x1e|s\xc1\xd0\xf5\xb9\xf7H\xe5Z\xd6\xdd\xdec\x18%\xcc$|O\x8c\xd1\x8f\x1cu\xcb\xb5\xf7\xb4c\xdb\xec\xed\xb7n\x9b\xbdg]{\xe6\xd1N\xc7\x8ey$Z\xfe:J\x19\xea3\xe7\xd1\x93\xb6\xed4\x81\x95\xf3\ns52\x81u\xf3j\x17\xcd\x12\x83\xf9j\x0f\xcd\x12\xady\xf5\x08\xcd\x12My\xf5\x18\xcd\x12\xc3\xf8\xea \x9a%\x06\xf0\xd5S4K\x0c\xde\xab}tC\x88Q{\xf5\x0c\xcd\x9a@\x97w\xd0<9\x1c\xe8x\xec\xc2xL\xd0\x01y$\x06\xe4]\xbe\xb2\xac\xe8 \xccQ+6\xd9\xdd\x15U\xbce\x19\xada\x0e\x9c\xcb\xb3\x9f\xc0\xd2\x0b\xfegvc\xbb\xd1\xcd\x04\xc99\x03\x90s\x19\xec\xf63\xbbir\xa9\xc0\xfcV0\x1ah\xc8\x97\xde\xe3\xab\n\xb9_\x1b\x8d@\xcf~[\xa3\xb4\x7f|\xabld\xa2\xfc\xe1\x93C\x8d\xcc\xc8\x94\xc8\xb0:\xe3y\xc2W\xc7\x8a@\xab\x07DF\x15d7\xa2;\x82YAy\xc0x\xd5\x06eJ\x9cr\xc6\xee\xc1\xc9\xb6\xd4\x11\xfb\xd7s0>\xcd\xa8t\xf7\xc3\x92\x7f\x1d\x03\xd3\\-\xa0\xbb\xc3R\x1bI/\xb5\xa9\xcf\xda\x81<\xb8]\xf4;\xa0\xee\xc4\x96\xdc\x91%\xb2q&\xd5\xb5\xfd?\x86i\xff\xb7X\xf1\xb1\n\x15\xfd\x7f\x8b\xb8\xe9\xdf\x04O\xb00\xa3\xbft\xf1\x84\x1a\xf1JhCv%\x13\x04\x16\x05\xd5\xba\x97\xd5\xfc\x11\x1b\x1b\xc9\x0d\xc6\xaf\x11\xa74\xcc\xe8\xaf\x1b5\xe5\xd7zS~\xad6\xe5W\xbc)5(\x1c\xa8Ws\xff\x86-%\xc8\x91\x86\xff\xdfj\x19 \xce\xf2\xf1\xa0\xb9\xac\x9eu\xd1\x1b\x88\xac\\\x1f\xe0\xcd\xb1\xbe\xc8x\xfc\x86\xadY\xa8\xe2\x02O b`u\x11\xf8\xe0\xf5KdO\x90\xecJ\x84\x8e\xa9\x8a\x91R\x84\xc0\x80 \xa9\" \xc2\xa9U\xa3y\xd8\xb0\xeb\x85\x8co\x83\xe8O^dta~B\xe0\x82q\xc6\xdf\xf0\xabB{\xd3^\xa9\xb6\xfd\xfe\xf4\xf1uQ\x87\x91F\xa6\x88\xda\xfesl{F\xb5}x\xab\x196\xa7\xaf:3\xf5x\xcfS\xb2U3\xa0\xcfS\xf6*\xb8\x14\x13\xb25\xb9\x8f\xb6\x18\x91c\x1e\xd5\x15\xe6\xc51\xff\xf0\xb7\x87\x87\xdf?\xac\xa6\x0b&\xf9\xe1\xdf_\xfc\xb6\xf5\xdb\xe8\xb7Q-\x0f7\xd4?\xfe\xf1\xe4\xf8\xaf\xa7\x9f\xde^\x1c\x9d\x9d}\xbcxw\xf4\xf6dJ\x1cA\xc7\x8c \xe4\xf0\x08b*\xa79\x1a&\xc3\xf7\x8fU\xee\x19\x97\xb1\xb4\xbb\xf0\x081\xe8i\x9ct%\xe6\xd5^\xc6\xd2LTt\x08\x01f\xd88aqH=&\x10\xaaC\x1c\xb2M\xe8\xb8\xd9~\xb2M\xbe;p\xbe#\xdb$\x13?\x9d??\xf8\xae_@s\x1a}dy\xca\x9a=\xe9\x8a\x80\xa8c\x9b\x16\x16\xec.\xd6\xae\xf6\xce\x8aJ 6QL\x93\x94\xbd\x8e \xf0\xe4dg0\x94\xc1\x7f\x80\x8eo\xf6\xc2\xb6/\xeeY\xa4\xf6\xe4\xf1\xe3\xddI\x17\x92\xab\x0fQ\x11\xc7KL\xf6d\x08=\xdc\x91\x91\"wdH/V\x84\xdb\x12ks\xf4\x88< \xc1s\xc2\xc9\x0bB\xd1\x10_E\x8d\xb9\x19f\x90\x93m\xf2h\xe7\xd9\x93!\xa1\x03Y:\x17\xff\xb6\x0f\xc8\xa3\x01\x89\xc4\x7f7\x13\x7f\xd9X\x0b\xa4\x8f2\x97\x0f\x06d\x1b\xcd \xdbd\xd2\x96\xb9\xdb\x96\xb97@f9#\xffq@\x121\x00\xffa\xc6\xa6&\x8d T\x91\xdaD\x17\xc48lo\xab\xf6c\xcdGq\xa0+?5 _\x88\x1b\xa9\x9f/^\x90\xc9\x93\xfb\xc0G\xe6\xac;\x93\xc7\xe3'\xe3]\xe7\xf6\xb5u\xd8,\xb9\x91\xfb\xe8\xc9`(m\x91p\xdb\xa5I\xdd\x9aG{bx40\x8f\xec}\xa8\xe5\xd9\xc6\xa1\xb7\x04;\x1e)kw\xd6\xa2/'\xe0&\x8a\xfb-\xe3\xce)pV\x85\xd5\xbb\x01\xac7\x1b\xe8O\xd4T\x8a\n\xdcL\x06\x11\x1e\x08\xf4\xc7\xed\xe6\x9e\xcd\x16\xa1\xa1\xb4\x04\xf2\x8c|&N\xfd\xc4u\x1e=rDY\xf1\xeb\xb13\xac\xb8\xf3\xb8\xe7\xf8WbB\xf6,\x83\x9f\xa86\x9d\xe6\x97Y\xc2\x04\xd2\xe3EX\xe0\xdb\x7f9\x1b_\\\xb0\xf4-\xf7\xf3\x90\x81!\xdeP\x86\x87\x8b\x98\x97\x01\xa6\xfe\x90\xf0u \x86BG\x1dm\xb6:p#w\xff\xf1n}\xe5\xf1\"\xeb\xd1\x00e#\x02\xabY\x83\x8a\xf7h4M\x1ejM,\xa7\xa2\xa7MIwL\xc5J_\x12\x1dw\xad\xda_\xae\x93\xefyDU\xad-\x83\x18\xb9u\xfb<\x0eK:r'\xd8\x96\x16\x19{O\x1f\x9b\x18T&=\xc1\xc7\x9a\xfes\xc7Z\x9f;-\x07\x9en\x99\n\x1a\x8d|o\xab\x1fU\x016\"n5\xe8\xdd`@\xb2e\xc2\xafH\xc4\xae\x88@2`\xdc\xe0:\xc74\x8axF\x04oJ(\xf1\x04\xc3IhJh\xf1%\x07\xa1~\x14\x17\x8b\x99\xdd\xaf\x95\x95y\xff\x862\xb3e\x1f\xd9\x9c%,\xf2t\xf3\xc4\x87\xc8\x92\xa6\xd1w\x19\xb9d,\"A\x14d\x01\x0d\x83\x94\xf9dD\xd2\xd3\x05\x1b\x93O)+\xeb\x1b\x83\xb4\xa2xu\x07$\xe3\xf2d\xcc\x96l5&\x1f\x19\xf5\xc9J`m\x9a\x11\x15hu~9^\xb1\x87y\xca\xa4\xa8cT~\xc5\xa9\xdf\x8a\xe1\xa3\x91\xb5-~\x1b]A`\xd0\xcb\x95 \xb8\xe1&\xaf\x80\x0b\x08\x95kn\x04C^r\x1e\xa2\x19\xa2\xb1h\x86\x8c\x94\x8bf\xc9\xa3\x15\xcd\xd2\xce\xc5\xb1\xac\x9b\xd5\xa5\xa5\x114\xc2[\x0d\xfdy?Ge\x8bLK\xdb\x90r\x9a:\xb2\x14\x95\xf2Jk\xc7,\xa5xd\xab\x0fr\xa4\xc7F$\x17\xe2\x01\xe0]\xb8\xa6b\x18kW\xbf(\xff\x1e\xd5\x160\x91r\x83\xb1\x99 \x0e\xec\xa2\xec\x1d\xf0F\x83\xa8o\xa2\x14u\x82\xd14\x0d\x16\x10\x9e\xbb\xaf\xb0\xe79\xc9\xc8\x0bB\x93\x05\x88\x94S%\xe6yN\xb2\xedml\xaf\xe8\xa5^\x14\x98e\x88\xe1t\xf1\x89\x84\x04\x91\xe8\xa1j^y,-i\xfa\xfe*R\x8e&o$-')qqN3\xa9\x1b\x1f\xcd\x92\xf3\x1e\xd7\xdd\x86 9~\xe8\xb4\x8d8Q\x9d\xf2\xccN\xa9Q \xdf\x93=\xd1\x1e\xc95\x01\x8e,\xfb\xbdwN\x0e\xab\xaf\xb8\xfb\xd4\x159 ?p\x1e2\x1a\xa1\xa6\x04\x0b\xa2\x0c\xe3\xe7\xcd\xbc\x1b\x84e\xd3\xe9x\x14n}S@\x0e\x89\xbb#\x0e=5\n\x03)\x81\x88\x9b\x88\x0b<\xa2\x80\x8b\xc0\xe6\xf7\x05\xbd\xe3\x8d\xe3H\xf2z\x1dNb\xdc\x99^u\xcd]Y\x8a\xe6\xd58\x00\xe5\xdb\xbdp\xd4\xeeJ\xcb\xd3\xe8\xcb\x17\xb2%\xe8oZ\xd2\xdf\xba\xce\x12j e$\xf5\xb2\x07\x82\x0d\xa8\xbb\xb2\xd5\x0f: \x95\x11\xbd\x8f1\xa9N\xd1\x1d\x87\xc5\xaf\xe0\xad\x96\x91\xa9\x00\x9a\x83\xe3\xd70\xdf\xa6\xe3\xf3\x96%\x0b\xe6\xdfit\xba$OX9\xb1_/\x8b\x02\xed\xacf\x8b\xf3j\xd2\x85\xa1H\xc1N\x1a\xcb\x08\x1b\xd3\xcd\xa6oKV\xb9*\x07O\xcc\xc8)L\x0b>\x81\x06\xa89}f\x0d\x9bL^\x90\x9e\xe6\x97\xa9\x97\x04\x97\xfd\xe7K\xb5\x1d\x97\xa9\x89\xc6\xe4Q\xaa+\xed\xd3\x86,\xb9)\x1a\xd1\xb7\x0d+p\xbeQ\xffZ9\x1ef\xe2\x81q\x1f8.\x92%\xdc\x92F~\xa8\xa8\xe2\xf1e\x10\xf9\x90<\x18\x0cI#\xdbE\xfc\x8c\x10\xb47\x9f*\x1f\xef\xd5\x9f^=qu\xb3\xaa\xbd\x13\xecd\xaf\xa6\x15\x92\x83\x97\x81\xff\x96\xe7Q\xe7]\xab~\xe0\xa3\xe64\xb9\x9b}\xef\xe7 \x0c?2\x8f\x05k\x84\x93h\xfb\xf0U\xcbN\x90[\x0c\xdc\xc3\xa8\xb9j\xf2@M\x7f\xe5\xfaik\xea\xa7hu\x9b\xd1\xf9\x84\xcc\x94)\xb3\xe8\xd5\x8e\x02~\xa3\xaf\xd7\xb17h\xa5\xd7\xcf\xc2jz\x15c\x18\x19\xb6q,\xb2\x9b\xecd5\x7fm\x9c\xf7?0\x16}H\x98GC\x0f\\\x19\xf9\xca[\x7f\xadi\x06H\xc0#\x10\xa3T\x1b%o\xe6\x99\xaf\xb4\xd4\xab\x99v\xa2\x0b\x01\xaa\xf1%\x0d-|\xfd\xd4&\xc6\xc4\x04}\xa7\x06\x14\x1fk\xfb\xb5\xcf\xa1VCY}\xf9[\x02:\xb9\x07\xc6\xd8\x8eK\xe9Z\xfb\xd9\x07\xec\x8b\x14'\x00\xd1\xd9\xd9L]\xe8\xaa\xc4\xc3m\x1c]\x9f\xea\x08&\xcd\xef\xa2\xf2\xebO\x96\xdcl\x00M\xcc\xab \x1a\xc7\xe1\x8dk\x11\xe2`\xcfW\xe2\xd1vo\xc6\xb6G}s9\x06y\x9a<\xb0\x97\xbdk\xb0\xcb\xb3\xccGQ+6r^\xee\x8a\x0e\x8aI?\xb0<\n\xe7\x9a\xfd\xcaDp\xd3\xb5\xc4\xc8o|\xb7\xab\xd1\x18\xf4\xc7#\xedb?\xd2k\xa8z\xe1\xb4T\xef\xc0~\xd3l\xca\xb4q\n\xc8|\xbe\xb6\xaf\xb8\x16\xe9e\x1f\xbc\xb5`\x99\xb4\xb7\xf2\xb5zu_\xec\xa59\x8c\xea\x15\xc7\xf5\x908g\x9cP\xcfci\n\x97\x12W\xb2\xfa\xe2\xf6kHnxN\"\xc6|\x92q\x88\xe0\x1f\xcco\xc8\x1fD]kNI\x96\xe4\x8c|%T\x16\x9f\xf3<\xc9\x96\xc5\xe50\x01\"\x12\xeeF\xe0~q\x00\xf7HcgP\x1c\x04\xf3t|U\xedQ\x9fq\xe8\xa7\xda\xa5\x1f}\xcdi;\x10\xdb\x11qT\x96l\xae\xab\xf6\xa2\x81\xf9\xd1\x96\xe5\xdf^\x0b\xad\x9c\x02\xb6=\xd7^G\xae\xeb\xa8\x1d\xbd\xf6\xdd_\x1cw\x16\nb\xd2AAL\xfa\xef\xfc\xcd(\x08\xaa\xefih\xbb`-\x95{\xbeuX\xc2\x8e0Hp \xe6\x80\xf5R\xad, /e\xba\xce\xc8!\xd4m\xc2\xb6\n\x88:\x84\x84\x1e\x12\x1d\xb1\xfe\xccU\xb4D[~@\x0ee=;dJ\x803u=\xbd*l\xe7\x8a+x\xa7\x10`\xe7UXT\x82\xe2\xb6]\xc5\x16L\xf2\xd6\x96\xeb\x81\xd6\x07\x8c\xe6\xa0\x18\"\xab\xe8\xc1\x95\xbcqN\x0eIN\xa6jY6i\xc8k\xa5\xf9\xc1\xd5\xf5\x99\xca\x01\x1e#q\xff\xf8\xda$\x95\xbb\xee\xd3d\xe0\xe9\x1a~\xc2#`\x10\xc0\xfd\x03\xd1\x88TX\xc7j\xc5\xd5U\xb4l\xac^um^\xb5\xdf\xaf\x16Z\x93\x03\xe5!\xe0~\xb4\x1e\x87v\xa5\xbez'\xc1K\x90ti[\xdcR\xd5\x8f8\xcd\x98U-\xea\x9a\xc7KR\x83\xa9#\x19\xb0>\xd4\x1a\x83\x82\xd3L\xd4K\xf9\xe5\xda\x81T\xa8G\xf2\xb2j\x9bj\xa44\xbf\xddyN\x02\xf2\x82D\x85zf\xb0\xbd\xdd\xc4\x91\xc0\xd3p\xa5\x194$\xd1,8\x07a\x12\x9b\x89\x9f\xe7\xf2\xeeE\xfe\xb6\xb6\xad\x18\xac\xda\x0e\xf9\xb6Sh\xd9\xe7\x05\x00\xca0\x1b\xd4|\x02\x82\xce#\x00\x06\xdb\x7f\x9e\xa4\xf2\xbc\xe9\x89&\x957\xc2\xa7J\xb4\xd6\xd1[(QV\xd0J\x83\xe3#C\x0c\xb9\x08\x8e\x04\x1a\xd6\nv5\x12\xaf\x17\x94\x1aw8v[\xa0\xcaS\xd2\x0e\xb4`\xd9\xcb^\xb5\x01`\x12\xac\x99\x0fd\xd5\xab\x84\xaf:J\xac\x82\xeb j\xc9/\xceS;H\x06\x8a\xdf\x08+\x8dh\xe7f\xd6\xf1\x8fZG@\xee\xc3\xd6f\xca\xed\xdc2k4\x0c\xc1\x05E[~K\xf9B\xf7\xb8\x0d$\xc8n\xfa\x0e\x85\x81\x0b}6\x0f\"V\xa0\xa0\xe6\xce+A\x17,3\xb0\x15\xc4\\k\xc2s\x1b\xfc)\x98 %\x02[\x89\x97,\xf5\x92 \xce0^\x8fV\n\x19\xdaMMPA\xcaPAEP\xa5'\x85[\xe9\x17\xb4H\xea\x86C\xe2\x0d\xc9\x1cCD\xa0['\x0d-L\xcd:\xcf\xc6\x8e\x0bx\xd4\x0eG?\x023\xc4`g\xeb\xb5\xf0\x12\xb1h\x7f\x0cX\x1d\xb83hc,\xda\x88\x16\xc1e+\xe2S>\xb8\xf8\xb0}\x8a\x13\x1d\x1d\xd8\x17\x84\xb1G3\x97\xbb\xde\xc0\xc6\xe5\x14\x87\xdbR\x9e[K\xf2\x82\xf8\xc5\xb9\xb5\xbd\xbd\xec\xea\xb8 \x1b\xfc\xd9\x121+\xd0\x8fRN\x9e\xad\xc1a]\xa6\xfe\xcfE;\xe7\xb3\xf5\xb9\xd5o\xbd~\xc4WV`\x1f\xee\x0d\xc9\xbaC`\xd8O\xfc\x1a\x89\xb1_\x0f\xc9\xaaC\xf2e\xcaW7\x16\x83\xa1\xa9j\xa56%\xfeMp\x14\xd48\x12\xab\xde\x97\x12\xb7\xd7Y\xd8\xed\x81\xa2^\x1aL\xd1\xf8\x90\x04\xb8A\x9a\xd6\xdcn\x0e:\x084\x9a\xb3%\n\x18\x96\x08\xd9@\xc6\xbaeWD)\xaf\xbe\x0d\"\xf0fH\xd8\xb5\xc7b\xd8\xcf\xdc\xf3\xf2$a\xfes\"\x9a\x9f-\x19\x89x4Zi@\x9f\xad \x8b\xd6A\xc2#\xe0\xab\xc5\xa2\x06\xc9^\x1e\x86\x04\x82\x9a\x92\x15KS\xba`\x84F>\xa1\xbe\x0f\x11OhH\x96,\x8c\xe7yH\xaeh\x12\x05\xd1\"\x1dc\xda\xe2,L\x99eQ\x89>\n\xcehV\x1f\xa6s\xbb\xe0\xc3\x83\x9d\x86f\xbb\xd5\xa1\xc8\n\xbf<\x0f\xff#}\xb8\x18\xf6\x13\x1d\xeau3\xf3\xb6\xb7\x9b\x01\x1c\x88d\xfa\x07\xd2\xee\xe1\x808\xaf\xa35M\x02\x1ae\xe4\xa7\x80K\xe1\x15b\x00\xd1H\x91\xf2\xact\xd2\xec\xcc\x1f_\xf1\x1d\x828Hi\x02\xea\xd5\x87\x89\xd0\xa4#\xa8l\xd8A\x95\x13C}L\xbaE\x91\xf6\xd1!\\k\x83<\xb04\xaf\x9a\x0c\x86\x98\x8d\xff`Hr\xd1QO0d\xa0h,\xc5o\xa2\x7f\xdc\x8d\x86\xe4\xe9\x90\xa4\xd8\x01T\x1c>s\xe3;\xcf\xc9|4z> \x01\xa8\xfc\xcd\xe6\xe7-R\xa2\xeaR\xb3\x99\xdd\xa2\x0b\xcf\x1c\x8c\xde\xbe\xe5\x8a\x06\x8b\xae\x8d&C\xa2E\xbc0U\xe4\x90\xec\x80Nvy|F\xe4\x05I\xe0\x86R\xe9\xd2\xb9l\x16\x9dK.~\xf0\x1c\xa7b\xea1V{o\x99\xc6\x9a\x96;\xe6\xc9\xa3.{d\xac\xab\xa6\xec\x06\xd6\x11w\xb3AE\x90u?\xad\xdb{\xba\xffo\xd1\xbcF\x88t\xd9\xbcI#\x02\xbbB7O\xea\x88\x82vK\x07\xba\xfa\x89\x9e\xad\x89\xcb\xca \x8eA\xc3\xb7\x91\xbe(\xe2\xa84D\xac\xd3\xd9\xb9E\x9e\x91\x835\xd0\xc0u\x0c\x1b\x0c\xa0\x88sP\xe0\x83\x8b\x00*\xe5\x13L\x9c\xfc \xd1\x8e\xc6q\x9e.\xdd\x1c_\xbb]\x06\xb4\xdd\xbb\xae>\x06\xba\x7f\xf5^\x14Hr\xeb\xa0.]%\xd5\x9d\x1aDj^` 3\xd9\xfe\xba\xaa\x9e\xc6\x81\x9b-\x9f\x8e\x88\xdb\xdaM\x1321\x1c\xe2j+c\xb3\x83\xaay\x8f\x8c\xebdx\x95\x14i8\xd3\x05\xd4>R\x8f\x14\xb9B=\xacR\x0ff%N\x943\x81\xa0\x9c\x90\x03Q\xf5!I\xc6?\xe4\xf39K\xc8T\x99}\xdaX\xb3CB\xc74\x0c\xb9\xf7)J\xe9\x9c\x15\xf0\xd5A\xee\xbd\xbb \xa9;\xed\xd21\xca\x91\xc3`]h\xa4+e\xe4\x06\x04QL0\xdc\xc6\xb8\x11h\"\xb3+\x02z\xdez\xe1\xa3\xba\xe3\xc5\xc7=\x1e\xdf\xb8\xc9`h\xf52\xf7uP\n\xf2\xdc\xc9\xde\xa3A\xe1\xeek\xf3-\x80\x0c\x88q\xe64\x1bi\xf4\x1d\xd9\xe9\x99TP#\x07\xe4(I\xa8\xe8\xc5\xa08\x99\x9e\x0fH6\x8b\xce!0|t~\x1f;\xa2\x13\xdfO\xf6\xefr\x1c%\"\x13P\x9d)+\xbc\x9f\x96\xed=\xedt\xdcqO-\xab7+\xba\xff\xa3C\xa3M\xfb\xa6H\x14\xabQ\xdd\x05\x16\xc9\x8a4\x82\xd5B\x13\x03\xcf\xccv\xce\xe5\xa9\xa0\x8f '\x88|v\xedH\xcd\xe0d\x0co\xd0\x0e\xf85$\")\xce3\x95\x14\xe7YeSm8\x93\xbb\xbb8\x93\xb0\xff\xb4N\xae\xabS\xfb)\xee\xdap\xff\xe9\x1e\xca%\xec?\xad\x9f\xf2b\xd4\x9d\x99D\xb8\xdaQ\xc0\xb9\xd3d\x19\n\x98\x974cu\x00\xcf\x04xK\xe3z\xfe\xdc\xcc\x7f\x07\x8eD\xea \xb1 \xf2\x91-N\xae\x1b\xb5\xf8&\xc8)\xcb\xea\xf9\xcbJ>Lm\x1dd]\x01\x01\xe9_\x1dde\x82\x00\x86\x91GF\x1dnQ\x1b\x14\xfaS\xc0\xae\xea@7&\xd0\xab\x90\xd3lo\x17\xea\xac\x03^6\x00\x9f\x01\xd4\xb1\xbbA\x1d\xe2\xef\xc4Z\xd3\xde\xc65\x89\xbf\xbb\xbd\xbc\xe7j+a1\xd6\xb7]\xa9\xfb\xb6\x1b\x90G\xf8R\x9d<\xc3tk\x04\x1b\xdbzH\x90\x9aL\xcd\xc9\xb8\x143;-\x91\x0c*^\xf5\x9aHH<}<\xfb)\x83\x07\xc1~\xe0\x00\xa6\xbb\xbf\x06@\xcd\"V\xb0i\x01\xbe\xf3\xf0\x18`\xdd\xbb\xc5\xb2O[93\xbd\x04,\xab\xa4{\xe3j\xd6h\x7f\xa76\xb2bYL\x9e4\x97\xc4K\x9a\xb1q\xc4\xaf6\xc5:\x9a\xdeA&0hj\xbf\xf5\xe9\xfbZ;\x02\xb5\xf9 \xc8\x01{\x8e\x88K\xc9\x08\xf5O+\x98L\x88\x86#\x0e\xa7\xef\xc9\x0e\xf6\x15\x0d\xb7\xbd\x9d\x91\xef\x0fHapnx\x8e\xdei\xaa\xd4}\x95\x1a\x82\x19\xae\xd7W\xdb\xb8\x9a\xcd,j\xbc'\x89\xe1\xe4\x11.\xe3hluEn?\xc3\xc9\xed\x06S\x9a\x93\x03T\x0d&\x85\xf4\x86\x16L\xd8}\x95Y-\xe0\x011\xde\x89G@ \xdb\xcd\xe0\xf0\x92\xb1\xbb\x80\xc6L\x95\xd6Os\xd8\xc5\x94\xa0\xf3[\xd5\x0c\xc9\x06$,\xf1\xb1\xe6|\x80D\xcafQ\x1d#[\xa8+o\xb3\xa9\xda\x7f\x86\xc7\x93\xd8\xdb\xe9\xbe\x1a\xb7R\xbc\x05\x08v\n\x13\xe3\xfb\x18iG\xf4\xbahU\xa1\x90\xfc\xaf$\xbf\xa2YPeL\xec\xbbR\x14\xd9\x85\"\xbb\xe7\x16\xc5\x10\xa2\xe7\x85\x1aW\xd6\xda\x9f;\xea\xe6Ip\xdan0\x1a\x81mu\xd1\x06\xa9Y\xcf]\xf3`\xcd\xe5U\xb4l\xfc\x0b\xb2g2\x06T\xdak\x81^c\xb1p\x05\x95A\xb6\xb7\x13\x08\x16h\xc3\x12\x9aP\x8ef\x89E\xf5\x1d\xcc\x95\x81\xdcNe4\x8f\xa6\x92\x92U\xb8V\x0bip\xeb\x83\xbeyp\xab\x95fa\xc2\xf7\xf6m\x11\xe5\xfap\x83\x81\xab\x83='bS\x92m\xe28\x1b6\xbd+\x12\xcb\xfe3\x1c\xcb\xed?{j \x1bWo+\xd8/\x03j\xf2xH\xaa\x8e\x8aB\x9a.e(\x882\x91\xe6\xd9\xb2\x9a\xb2\xe4i\xcd\xfd\x8f\x18\xa4&\x8cR\xb0\xae86Jku\xa5\x8c&^-\xed\x1f9Knj\x1f\xa0\xd9\xb2Y\x9dH\xad} asRs)T.\xb2l\x0c!P\xc9\x01\xb9\x1c\x92l\x9c\xb0\x94\x87\xebN\x97\xaejr\xc1\xc7\xdd\xd6\x04\xfc\xba\xe9\xa2\xa6\xaf\x9a\xafF\x95r\x1f\xf5\xac\x98\x91C\xb4\xf2b3V<\xac\xc3g\xe6\x0eRIl*y\x16H}.\xad\xd7D\x15\xdf\xf9\x01D\xe0\x96_\x81\x18\xcb\xa6\x1f\x0f\x99\xac\xafZ\xaa\x0d\xfb\x94\x88%\x15TW.\x85\xd0\xc1\xee\x8c\x8e~\xdf\x19=\x1bo\x8f\xce\xb7\xa7\x83\x87A\xf3\x98}8\x9d\xed\x8c\x9e\x9d\xff\xe5\xcf\x0f\x9bG\xed\xc3\xbf\xbb\xbf=\xfc\xed\xe1\xa1{\xb8\xf5\xdb\xc3\xc1\xec\xef\xbf\x1d\xfe\x96\x9e\xffe\xe0\xfev8\xfb;\xfc:\xac\x97\x02\xb3\x04\xe7\x0fgH\x9c\xaf\xe2\xcf\x17\xf1\xe7\xb7\xdf\xc4\xdf\xbf\x8b?\xff\xe5\x9ck\x03\xa1\x99\xf3B\xa4|\xef\x0c\xc9w\xcew\x90\x07q\x80E\x81\x04\xfeF\xf07s\xce\x07\xcd\xd3{\xe6|WV\x15\xd6\x00\xe6\x00\xf0\x1f\xa2\xf8C\xf1\xe7P\xfcy.\xfe\xfc\xaf\xb2\x90W+\x14C\xa1\x12\xfe\x7f95s\n\x1fFd\xb6-\x87\xf4h\xf4\xb7\x8b\xd1\xf9\x1f;\xc3'{_\xeb\xa3\xb0T\x83\x8f\x80\x0e\xdc\xf1_\x06u\xf85ja\xf8\xdftM\xa5!\x1b\xce\x958\x06\x80\xd3\xe0(j\xd6{\xabo\xff\x89\x05\xfa \x88\xcb\x84V.r,\x86\x89s[\x99\x05\x8f\x976\x83\xc8y`\xe3\xdf\x1ch\x84\xd3\x92\x99Zs\xe7-%Uk\xacEE\x83:\x87\xedF\x9d%\xfb\xe8Yri\x93q\xfc\xff\xec\xbd\xeb~\xdbF\x928\xfa}\x9e\xa2\x84\xec8@\x08R\xa4\xe4+mZ\xeb\xc8\xcaF3\x89\xedc\xd93\xbb\x87V\xf4\x87\xc8&\x89\x18\x048\x00\xa8K\xc6\xdeg9\xcfr\x9e\xec\xff\xeb\xaa\xeeF\x03\xe8\x06@\xdb\xc9dv\x07\x1fl\x11\xe8{\xd7\xbd\xab\xab\xe8\xfa:\x17<\x06a\xa6\\\x8d\xc9\xbc\xa2S\x95\xa6\xe4\xb5\xd2\x1b/4R\xa7\x94(\xb7\x1a@\xdde\x0e\xc7\xa1Q)I\xe9\xdb\xec3\xe2\x12\xbaF,-)\x05^\x05i\xb0f9K\xe1\xebm\x1a}M\x19\x05.\x19\x04\"gU-\x81\x80\xc9Q=,<\x01_.\\\xe7\xc81(s[\x94Q\x8b\x14g\\h\xd3\xea|\xe5xp\xc4\xe9\x02\x8c9a\xa8\xd7\x8f(S\xc6&\n\xf3\x9a\x97z4\x1d\x9e\xc3\x04\xff+\xaeV\xbd{\xb7\xbfD\xf2d\x18\xf0%\xa6\xfb\x99@4\xf89 \xe3Z{|\xf5x\x91\xcbA\x9e\x86k\xd7\xf3a\x0fS\x8d\xcb\xb4\xc54\n>\xe6\x06\xf3\x17\xef\xe7\x02&\x90\x91#\xc3\xa5Ew\xbd(\x07\xf0\x16\xcc\xff\xb2\xcc\xf9/\xeb\x02\xc3\x05J\xc1\x17\\\xf8>\x92\x81\xd0\xa4\xd4\xc1\xdfV\xa4\x8e\x1c\x8e\xe0V\x80\x9bV\x18\xc3\x96\xe6\xa9;\xf2T\x10n\xe3\x07(\xa2\xad\xc9N\x1c\xa7\xd2\xc5\xdf?\x8a82e\\\xac-\xfe5\xd7\xd6\xcd\x8b\x82\x91\xffl\x8by\x02\x13py\xe5\xeb\xe9\xf0\xdc\x1b\xe4\xc9\x0f\xc95K\x8f\x83\xcc\xe8>^\x15\x08O|\xa0-\x15\x13\xbb\xaey\x1f@m\xb4x\x19\x81\xab\xa6\x18\xc1\xf0r\xb0\xc6H\xea\xfb?q\x96=\xfd\xe9\xdf\xdf\xed\x9f\xf7\xfe]\xfc\xbfo\xbc\xef\xca\x87\x8dn\x83\xfb\xfb\x0e\xc2\x8e\xea~\xe8\xc3\x81a\xd4{7\xd4\xdd\x9d;\xb0\x9e^\xe3\x8dZ\xb74\xec\x03\xaf&\xd5V#\x91\xd6\xe7\xb0\x87m\xf1-,\x9a\xdf[N\xaf\xcd\x97t\x95&}\xe6\xc3\xb1\x8f\x9e\x87\xfd\x91\x8f\xde\x82\xc3\xc7\xf0\x0c\x9e\xc0F]\x85zfNP\xc6\x1f\x81\xec\xeeK\x1c\xbeD\xf4\xcd\xf4\xd9\xb9\x88/\xdc'tz\xcf\x87\xf4\x12\x9e\xc0{z\xcd\xfb{iP\xaa\xb8^J-\x1e\x13)\xa1\xcaGpY8\xffpJ\xf2\xef\x98\xa9\xbb\xf6\xd2\x87\xf7\xa2\xdf3ZO\xbcw0\xf4\xe1\xd8S\x90\x81\xaf\x8e1\xa1}YM\x98\xb3Y2go_\x9f\xaa E\xee\x99\xe7\xc9\xb5\xb1(\xbd\xda\x82-\xba,\x18_\xf2\x97\x8f\x8bi\x96\x17n\xf1y\x0bG\x15d\xb1K \xfce\xddG[\x95\xf7\x95Uy\xef)\x12\x94f\xec\xfb$\xcb]\xaf\xae\x14\x95\x7f\x7f\xf8\x00\x8e%\xb3\xd6+<\xd7&\x9c(U\x12\x8e\xe7\xce\xb9\xe9[\xe9\x974'\xf4adP\xd5\x11\xec_\x99\xef\x81+\x00\x7fS\x1d\xb2\xa0\xec\xfb\xef\x06\xfb\x9e\x0f?r\x82\x83\xbb\xe8\xc3\x1b\xb9b\xb4\xa1?6\xee$\x88Y\x9e\xc2\x04\xdeL\x9f\xb5\\\xa2?Et<\x15\xd4e\xdezq^\x0d\xffgA\x85_\xd0\x10_\xc3\x04N\x15\xa0\xbd\x80'\xf0\xfa1\xbc\xe0\xa3<\x1d\xccVAz\x9c\xcc\xd9\xb3\xdc}\xe1\xc1S\x18\x1d<\x80#\xf8\x19z\x13pn8\xcf\xc5?O\xa7/\x1a\xc6\nrY\x7f\xee\x97\x8b~ \x19\xc2\x198\x1e\xf4\xe0\xd2\x80\x15\xcf\x8b\x12\xedc\xb9LY\xf0\xbe\xb1T\xdd\xbc\xd4\xfc\xa5\xfe\xd6\x88GO\xe1\xe0\xde=\x99\xeeA\x1b\xbd\xe3H\xc9\xc0\x86\xe8eV\xec\xc3+-vvQ%\x1d\xe4\xc9\xb3\xb3\xe3\xd3\xd3\xf2\x17\xd3\x05b\x0e2\x7f\x93\xbd\xa0\x15\xe6\x08\x9c1\n\xa1\xea\xcd\x98\x83\xbeq\xbe\xdfu%D:\xe9\xfb\x0ez\xf07]\xe8\xeai\x8d\xf0))\x01\xc8\xba\nRb\xf2\xcd\xeb\xdb\x07\xce\xbb9\xccp\xea~)\x08\x9d\x06H\x97^+\x1f\xbf\x9a\x9e\x9c[.E\n:\xc5i\xd6\xac\xe06\xad\xa4\x8a/\xf5/\xbc\x8e\x95L\xf1\x8e\x05//\xb8\xd1/\x8d\xa8\xcf\x1b\xfd\x96\x8b\xd8q\x8dm\xfe\xd2\x80\x02\xdf\"\xc9\xff\x05\x97\x05\xabg\xb3`\xc3x_\x8a\x17!y\xfe\xc5#\x84\xfa\xd6L\xde\xeb\xf0^\x97A\xffR\xe2\xad\\\x92/\x18\xef_\xb4\xbd&\xcb\x9e\x92\xbe\xfeR\xe1\x8aC\x1f\xfeR\x05`\xde\xfc\xf7\xe5\xe6\x8f\xaa\x88\xaf\xad\xe9\xf7u\xf1]u\xf7\xbdW\x11\xb1\x8b/RH)\xc6*\xcb\x94\xa4||\xe9\xd5G\xfd\xfd\x8eb\xfdeQR\xd3A8\xb1[NO\x10\x90\xcb\xb8\xa1\x82w\xab\xd2\xa6\xfa\\9\xabj62\xbb\x18\x0d\xc8\x04e\x05e\xd0\xea\xd8\x04\x8d\xbf\xaa\x88\xb54\xc1&R t\xaf\xbfA\x0f\xfe\xda\x80\x89\xba\xba&\xf43\xfc[\x1a\x16+JP%^p\xdd\xc8i:eU\xd4\x05\x05P\xc3\xa0\x992~\xe2?\x06Lc\x9e\xa7\xc5\x199|\xb6\x1f\xfa\x9c\x88\x92 \x7f\x02\\N\xae\x03\xae\x8aM\xac4'\xec\xbbNhc\xf3&\xd4\x0b\xa6Z\xcc\xe2\x95\xadPh *\x1b @\x96\x87YP\xed#2\xcb\xdd!\xf5\x14+\xe6\x18#\xc1*\x9c\xd1\xb0.\x86\xe0p\xberD\xc0\xc7r]\x0ex\xfc[\x0f\x8f\xad\xb6r\xe2\x18\xa8\xabR\x94/\x14-\xca\x16ij\x0fB>Ht7/phz\xf4\xd5y)ZOSLQ#B\x96\x89\x8a\xc7\xe5E\xec{\xab:q\xber|p\xfexp\xe8\xe0\xd7\xd4FEL\x87<\x96\x83\x18\xdc\xa2\xf2\xe1\x8b~.\xe3)\xba\xd5\xd2\x97\xe1\xf4\xc7du\xac\x18\x1d\xcd6\x91\xdcl\x16\x85\xe24K\x1b\xa1O\xd4\xb0\x81\"\x97\xe2\xb7`\xbb\x14\xc2\xa5\x8aQ\x9e\x8f\x14e\xf8\x18\x02x\xa2\"\x84>\x86\xc0\x9ef\x1d\xfdO\xa6\x81\xc9\x83q\xba=\x17\x086\xdd\x9e7\x8c\x8eB\x93\nQ\x02\xbd&V>\x97\xaa\xc9\x96\xc89H\x11\x0cH\x1d\xf5i\xdc$\xae\xcb\x0eL\xe1\x1c\x85\x82\x90\xd4\xba\xd1\x9c\x93\xd5\xc3\xac\xa2Uu\xf8\x18\"x\x02E\xd6\xf9\xa8Y\\\x9c\xc1\x04\xb2id\x11\x17\x1d9\x16B\xb5\x19\xe1\xf1tF\xd1\x08f\x06\xf1\xd5z\\\xbe\x9c\xc6jf\xe2:zI\xc0\x88\xcb\xd2E\xacNN\xeb2\x86ya[6\xadXW@g_\xf5\x8bHU\xd3\xa2\xa3\xb4\xbe\x9c\x16u\xcem+Z\n\x96T\xdd\x9e\x0dm\xcf\xa6dB\xda\xb4\x1b\x1e0\x04\xf1t\xd3\xa0\xcc\xc7\xd39\xed\xc8\xdc\x12K\xcc\xf8\xb6\x11L;l,\xa1\x82f\x95-\x16\xc8\xe7\xb8\xc09\xf8\x87\x0f\xb0./\\i?\x99\xfaQ\x9f\\CD\xb7R@D\x97U\xc4\x16O\x9a\xf4\xf7\xb9\"\xb0\xd2X\xee\x9e\xcb\xa4\x8a\xb8\x1a\x90=\xc0\xabEx\x92O1\x83\xa2\x162*V\xd2E]V\xd6\xaf=$\x07\x1c\xa8VB+\\)\xe3\x03~]\xe9\xfe\xf8\xf5\xcf\xa5\xf5Y c\xc3\xbe!\xdf\xbbmC\x94\xf0\xcf\xc4\x9f\xbcM)\xff3\xfa\xcb\x17\xd8G4LL\x93+\x0b\xb14\x922\xfc\xc3\xd7\xb1tR\x999\x13\xeat,}+\x18\xfeQ\x9a\xc2\x87\x0f\x107H\xff @\xfc\xaa\x8c\xe8\x16\xc1R>x\x04\xd8\xa2\x03\xf0G\xd1\x90+\xe8\xc1m\x87\x05T\x18\xa1y\x99\xe8\x02\x91\xa2\xd4\x9f@\x83\xe4IU\x99\xce9\xe2(\xa1x[H3\xf5\x05\xb8(\xed\x173\xb6\xc4:\xb5t\x0d\x13\xb8\xe0\x8d\\\xd2\x16a\x9bD\x17E\xedz\x9d\x13\x98\xc0u\xfd\xf5MmR\xdad\nL\xe4\xfdL\x0d\x11\x17\xcf8\n\xafJ\xb4\xa0<\x90z\x1b\x1a\xb9\x06:\xfc\xd0X\x8bA9?\x13\x1c\xa5\x84\xa7\x1a\xdc\x92sN\xb1\x08\xae\xe0\xe77\x1c\x81\x8f\xe8\xbf\x89\xfc>\x86\x1b\x85\xb0\xf4\xca\xf34t\xe2\x0d\x97YM\x99@P_\xac\xdc5\xabu\xbd\xa2\xaeW\xd45\x93]\x17\xb4\x82\xa9\xae\x15q\xc2\x0c\x7f>n\xedu\xad-D\x135+^\xef\xc23\x13\x01)\xca\x90R\xa6\xba\x8e\x15\xb6[ B\xa9.\xbe<\xd2\x7f\x8c\xb5\xba>t%T\x1c\xbc*WY\x903\xf0\x8d]\xa9\x13[<\nso\xe8*\x8b\x0f7\x83M\xb2\xe1\x18\xc9\xdf\xdcH\x17\x96\x95\xd7\xb5[K\x7fx\x08\xffb\x1bE/\xd3\xb71Et\x9e\xbb\xb2\x19\xa3|\x8c\xe0\xe7\x95\x17M\xad\xfa\x8d\xe4A>\xb8\xaf\xb8\xd2\xbc\xe7\x16@H\x7f\x15\n\xed\xbf;\x1eyD\x17\xdf\x04b\xfc\xbb#\x8e\x92\x14\xf1~U4\xac:+\x0d\xe1U\xc1\xfd\x1a\x88`\x87\x85\xf2A.\x89[`=\x8eF{/\xe9?\xdf\"E\x93\xb5\xf2p\xa4\x13\x901g\xa2\xa8\xb1\xc9\x11\x1c\x15\x83\xc1\x8f\x9f*\x02\xee\xdd(xQ\x93\xdcT\xbd\xf6J\xbd\x8a\xb1\n\xad\xb5\x18D!\x9dJ\xd2\xd1*\xe9+\x99\xe5\x98v\x1e\x8dw\xfd\x91\x87^\xb0\xefiA\n\xca.\xff\xba)\x0c\xfaB_w\x06\x84e\xc7\x88q\x03\xf9\xcb\xd3\x10\xf0X\x9c\xef\xfa\xf0\x12\xfb\x92\xb2\xe6Kx\x8a\x12\xe8\xcb~\xdf\x03\xd9\x0e\x1e\xc0\xdeL_\x9e{\x9c\xd4!L\xcd\x98\xfbR\xdc\x7f+:\xe0J\x7f\xf9\xb3O\xa6\xe81<\xc3\x81\xd5>\xf6\xfb\x06Z\xbcG\xe7\xd5'\x16\xc3\xf7c^\xed1<\xf34*\xcb\xc7Pi\x89\xb2\x10\xead\x9a\xaf\x95\xb8\xfb\xf0\xf0\xfe\xdd\x07fM\x8ck\xfc\x87\xf7\xcd\xdff\x18f\xdc\xf8\x89\x83\xf9\x81\xa5\xda\x867\xf9\xd0\xfcm\x0e\x13xP\xbd\x13'\x1f\x8ez\x0f\x0e\xcc\xdf\xb8n9:\xb0\xb4\x8a\x91\xf1\xfa\x16]s\x89~\xc97q\xbf\xbfo.\xc0\x05\xa1\xfd\xe9O\xefn\x0e\x86\xfdw7\x0fN\xce-\xe5.\xb1\xdc\xbb\x9b\x83\x93w\xdb\xc3\xe1\xf0\xe0\xdd\xf6\xbb\xef\x86'\xfc\xdf\xfb\xa3\xf3\xfd\xa5\xb9\xd2\x855\x8f\n\x7f\x92+\x96.\xa2\xe4z\x0c\xceK\xf5'Em\x8c\x19\x9bgp\x1d\xceY\na\x9c\xb3%K3\xc8\x13\xd8\xa4\xc9\x8ceY\x83b\xed\xc4I\xde\xbf\x0c\xb2p\xe6\x8c\xc19\x8d\"\xb6\x0c\"\xd1*\x17\x1dn\x1e\x0e\xc1\x8d\x93\x1c\x02\xc0R\x80h\xb4I\xc28\xf7\x9a\x9a\x0d\xe3\xab \n\xe7}l \x9b\xa6\x17\xd4\xb49\xf1\x9d!\x9d\n\x08\xc55\x82>\xcc\xcc\x9f\xb9\x8e\xfac\x90\xaf\x06\x8b(\xb1\xe5\xae\xe4:\x01\x19\xb5\x07\x8b4Y\x1f\x0bo\x1a\xcd\x9dX>\xca\xad\xf8\xcc|<\x00*\xc6\xfe\xeb ^\n/\xdc\x8b)3\xdaE\xed\xad\x1f[o\xd4A\xd5\x1e\xaeB\x85\xa2I|z\xfe\x18b\x0c\xc4\x9eR\x84X\n]n1hI?\xe5\x9d\xc6\xf6\xbeql\xc5\xb0\n\x89\xc2\x0e\x07\xa9\xe1\x00P}\x93\x02y!\xef\x82<\xf8\x89\xb98\xd5\x03\xf4\xfbC\xceON=)\xf4\xe0\xd8\xa5\x13Su\xe6r\xe9s\xc9\xd6S6@\xca \xeb\x15N;;\xcd\xfe\x99}\xdf\xd5\xb6P\xac\x06\xda\x0e\x1f\xaf:\x0d}\xe1D-\x05\xef\x84\xae\xa9\xb9\xa4jk\xee[I\xaf\xe7y\x1c\xb5\xee\xdd;xt\x9f8\xc7\x93 \xdc\xbb\x7f8z\x84R\x0b\xaf\x08G\xfc\xc5\xc1\x10\xe3\xa2\xdc\xbf{ot\x00\xe24\xad\xde\x96G\x01\xce\xb8\xbc\xea\xba\xa3\xe1\xc1!\xdc\xe1\xbb\xf7\xe4 \x8c\x86(\xc5\x88w1\xffq\xff\xde\xbd\xc3\xfb(X\x89*9\x17\xa0\xb8r0\x06\xf5\xe6\x0b\xc2\xd2K\xfbj\x8a\xf6\x10\x13\x9a\x8f\xe4\xe4#O\x9el\x00\x05\xfa\xbd\xa1\xa78\xd7{\xa0\x0e}\n\xa3!\xdc\x01\\\x9e\x0f\xb4\x1dB\xa0\xa1\xb5\xff\x00b\xe5\x18\x1d*\xf2&\x0c!\xcd\x01\xcf\x02\x05\xb4\xed\x08l\xaf\x1aQM\xcd\xa5\x07\x07\x07\xd0\x83\x07\xf7\xe0\x1bp\x19<\x81\x83\xfb\x1e\xf4\xc1u\x87\x18\xcd\x0c7\xfb\xden=\xbf\xb1\xdd<\x90\xcf\x95\xb8\xfd`I\x89\x82\xb8\x80\x98 Gp\xe22\xd8\x879\x06\x95\x03\xbe\xae\xc2G\x81\xde\xe7\xdec\xdc\x8fk\xf8\x06\x16\xf8\xf91G\xe4 D\x1e\xae6\x95\xban\x06\xbb\x13\x97\xe3\xbe{\x8d~3\xf0\x0d\xf0*._\x99\x8d\xb7\xdb\xc4\x7f\xb4\xc3\x98\x86\xdaz\xce\x18L\x075\xf7a\xe9\xc3-9\xe2\x98\x8c\x9a\xf2\xb9\xd0I\xb6\xb5\xd4\xb5\xf9\x16\xbe|8\xbf\xba\xb2\x7f>\xae\x1b\xc8\xe4\x83\xfb\"(\x85\xeeA\xbd\xf6f\x82\x82\xd0\xf3\xe1\xc4\xbdF<\x86\xa7\xc0'xc\xe8\xea\x86\xf0\x9d\xca\xf1\x89\xfe\x11\xb3\x03_J\x0b\xd1u\xaf\x87\xa1\xa7n\xba\xfa\xfcA\x81\xfb/\xdd\xcb\xddp\xfc\xf4sq\xdc\x87\x0b\x9fC\x9b\xb8>QMr!\x1f\x04\xccK\xe9\xc3\xf5\x0c]\xb6\xa4\xb0\x96#\n\xa3\xa8$\x84\x83U\xc9{\xe1\x92c\\\xe0\x11tN\x83s\x8e\x9e\x02\xd5\xde\x13j\xdd\xb85\xaf\xa0R\xc7)\x06{\x99\xc0{\xd5g\xa2\xd5^{\x84\xd9\x97\xed\xa8\xc5\x91)k\x19\xdcS\x91\x81\xfc\x16\x9e\x88,\xe6\xbc\xd6m\x837\xa8h\xba\x0fy\x81\x1a1G\x0d\xf7\x02c\x82pBn\x02\xda\x98C\x12U\xe4\x84\xfe\x82\x96rk\x1a\x9f\xb5o\x10\xa6\xc7\xd2\xea\xe2\xf8{\xbd\x18\xa1\xb8\xde\xef-P\xda3\xfbb\xc9\x07g\xc6IK\xec\xa3\x8e\x1a=\x96\xc8\xcc\xd1q\xce\x919\x14\xc8<\xe7\x0b\x17j\xc8<\xc70(\xdec\x98\x0bd\xe68\xb8\x81>\x87<\xa9\xe8,\xfd\x02\x04^\xb9K.\xf3\xc2\x1f98\x0e=O8\x15\x9c\xb8\xc7\x0dF(O\xf9\xb4\x13OAj\xafW\x97\xf0\xf4\xe7c\xaf\x17\xf3R\xf5\x84S\xd0\x86\xc7\xef\x9b\x84\xa4\xea\x9b\xadU\x17\xbebi\x16&\xf1\x18\x1c4\xe6X\xb4\xd0\xed,;0\xe5\xb2\x96\x0f] \x1a\xc33;\x9b%\x1f\xb01\xbc4O\xd5b\xb4\x10\xed\xfeh\xfe,\xdb<5\x7f\x16.\xf6\xe3\x8e\x12\xb1\\\xd8\xee2\xb4V\xebv\x90\xb3,\xa7\x98|\xceM\xdc\xef;\xd0#\xd2iJ\x99-\x9f\x8f\x16\x02n\x9b\xcf\xdb8\xa4\x19w\x1b\xdfg\xcdh\xa9\xcd\xe8GW\xe6\xa6\xb9[\xb9k\xf8i\xf3\xab\x83\xac\x0fZ\xbeD\x94n\xac\xa6Y\xf9\x88qn\xeb\x8d\x15\xc1nP,g\x14\x02\xd3\xd5c}$\x15\xffC\xdd\xe3\xcf\x90\xe6\x86\xffy8\xb2d\xbb\xe9\x14\xdfC\xef\xbc<\x1f\xe9\"\xd8\xb6\xabb\xbe\xa6\x0c%\xe5\xb9\xf8\x95\xe6\xc9\x91\xaak\xf3\x16K\xab\x88\xf58i\xeb\xec\xc56\x8a:v%\"\x85vjR;1\xde\xad\xf5\x1dC\x89u\xda\xcb|@\x84 \x0d\xf8\xf2\x16z\xec>|\xf4\x88+\xb7\x03\"Kd\xdd\x97\xde\xc9@q\xaa\xba%\xf3.\xf7\xaa^+\x91,m\x8a5\xd2\x12\x99J%\xb1\xa9e\xf0\x81\x96\xb0\x87>\xd4l\xf8x\x84\x81G\x89w\x1cbzxC\xd8\x99\x18\xf2\x8a\x07\x86L\x90\xa19M1zC\x0c\x853D\xe5\xc89\xa8\xb7\x8cqE\xde\xf5\xf6+\xc29\xd3\x0ckU;\x8ct\x01\x1d\xb1\xc3\xca\x888\xac;1\xe6\xa3\xd1q \x1c\xac\x83\x9b?\xb3[\x14v0\x85\xa9zch:\xd2\xcdW\xa5\xaf\x99\x0c\xf5\x19I\xc9 \x13PV\x1bQ\xd61J\xa4\n3\x8c,\n\xbd\x9e1\x833zLJ\xa9{\xe5\xa3\xc9\x9eMg\xc5\xfd\xff-\xfaQ\x0fm\xc6\xc55\x17\xaf\xd5\x81\xa7)5\xc6\x1a\xed\xd7p\x04\xee\x02\xcb\x16gTk!D\xa9wk!\x8c\x8eEY\xfa\x8c\xc7\x94s\xf3\xed\xe1\x85\xe7\x83\xe5b\xf1\x86k\xd6n\xe0\xc3\xdc\xa3\xb0\xd3\xd39\x1e\xb4\xf3\xffI\x16[a\x1cTr\xe0\x9c\xf2\xff}X\x9d\x17\xafV\x16\xec\x87\x02a\x82\x02\x0f\x8a\x89\xe3\xf9\x97\xcc'6\x083\xfc\x9f\x83e\xab\x8by9Q\x90\xb8\xba[CJ\x19&\xb2\x1ecgw\x02\xa1\x8f9m\xf4IWYld\xf8\n\x030atO\x89\x94\xcdA>\xebpB\x95/)gTKm.)\xe5\xe9\x96a\x94\x8bE\x10e\xcc`\x8a\xa4\x06\x05>6\xe7B\xc9\xbe\x0b\xe30g$\xb1\xd0\xc1s\xbd\xbd9[\x04\xdb(ol\xc9q,@\xf3\xd1\xcc\xce\xeb\x84\xb2\x16sX\xb4l\xa7\x97\xbe\xc6\x0dA\xdef\"\x91\xc8\xb3\x1c\x7f\x1eA\xe8\x06(\x9b\xa8\x01\x046\xea\xc0I\xa4\xe1\x16F\xea\x06x\xb5\xc2\x90wW\x8c8qI\xe3\xe3\x9d\xf1\xbf\xba\x08\x92R0\x83\x9e\xb9Of\xb22\n\xa3/\x86\xc2\xb2\xd7\xe4c\xa9\xde\x1c)U<2W\xdc\xd24\x1bF\x84\xf0\xf2\xfb\xa2\x04\xe6`o&\xd6O\x0e\xfa\xeb`\xa3\xe5\x92\\\x07\x9b\x1a\xdb+\x9d\x85M\xcfKV\xcb\xe2\xb8%\xed\xf5<\x99\x035w\xd94\xe5\x05-\xfe*\xd5d\xa8\xa0q{\xcd\x81\xbfy\xbd\xae,\xf9O\xcba,\x99\xd7Y\xb6\xa1 \x97\xbfR\x1a\xd4\xda\xea\xef5\xeb*fb-\x9fn!0\xe5#\xc6\xee\x96\x82.\xe5\x82\xde\xc5\xec\x1ar\xb7\x80(\x97S\x8e\xcb0\x0e\xd2[\xc7\xf3\x8a\xd7\xcee\x90\xb1\xfbw[-\x07V\xa5\xe8\xde]O$M\xed$\xce^iY)\xcdA\xdd\x0f, \xcf\x0f\x87\xe6\x84\xe7\xf7;\x05\xf47\x1c\xc8(\xde3\x01\"\x9d1\x14\x19\x0bb\x91\xb1 uC7\xf6\xd0\xc2\xaa\xc4O_$ \xc6P\xacB\x17\x8e\xd1\xbeV\xb8\xe6 un\x81*}@\x9f6p\xc9 \x84\xbe\x8c\xd7o\x14\xc7`\xf0\x84\xe6\x81\xf0\xe0)\xad\x1a\xaf.j\xa5\x9eN\x14\xd4\x90\x13\xf4n\xc8p\xa5%\xfe5E\x84\x1f\xd57\xf3n\xdb\x86YfL\xb9\x16\xe0\x03\x84m2\x92\xde\xc0^C\xc3\x16\xed\nt2\x9b\x9bQ\xd0\xaa\xaf\xc8\x95-.\xfb\xf9\xb0?\xfd\x89\x02\xf2\xbd\xeb\x7f\xf5o\x7f\xbc\xf3\xf57\xbd\xc1\xbb\x9f.\xfe\xcf\x87\xff>\xdf\x0f\xa5m\xc5\x12\x88L\xfaw\xccVA\x1a\xccrtD\x81\x15\x0b\xe6,\x85E\xc8\xa29\xc4\xc1\x9a\x99\"h(\xf2_\xb2\xd2\x94\xd1\xda2\xe7\x8ef\x87\xb6iW\xf5msg\xa9\xb93\xc9 \xcc\xd4/f7\xba\x19\xc3F$Ak\x88I\x7fK\xbbqWL\xd0\xde\x16\x7f\xe6I\xcc\xc6\xba\x8d\xca\xe0\x10\xa8?\"6\xbb\xd9\xb0\x0b5Rk\x7fkH'%\x06\xbc\x1a\x849\x85\x88\xa7s\xf9)%/\xa5\xb7y\x92\x9e\xef`D\xab\x8f\x13\xe3\x97u\xda\xca\xc4\xbc\x95\xe8\x9f\xb8\x0e6\xa8\xf6\xfb\xe50\x81\x89\x0c>z\x12\xccV\xed\x81\xb1Us\xc1f\xc3\xe29%\xbb\xa9\x8f\x98n`\xa3G\xb5.\xab \x85\xc0\xd0]\x97\xbe\x18:\x98\xb3\xe9\xc8\xe4\x94T\xf4\x88{ \xc4\x93%\xcb5\xa1\xe4E\xb0f\x99\xcb\xbcz\xff\x9d\xe7:\xcd\x1b:\xef\xb4G\xa1\x9d\x9e\xb1\xc1e2\xbf}\x9b\xb1\xb9\x12\x1e_\xa5\xc9:\xcc\xd8 exC\xbaB\x9c\x9eE)\x0b\xe6\xb7\xc0\xffuL\x87jE\x8b\x18\x90\xad\xd3\x00\x83f[\x1e\xbb\x96\x83j\x0f\x02\x0e8\x84$\x8e\x92`\xde\x05\x05\xf8\xc3\xc5\xa6\x94e\xdb(\xb7Y\xe4\xb1I\xc6W\xa0k\x9b\xb1\xcb\x06X\xa1\xb3\x11\xbc\xdb^n\x9bI'_\xab\xef\xc2\x88\xbdFva\xa6R1\xca?&\xe7$I\x0f\x06|w\x9feZ\xb2c\x12\x97:\x8d0k\x826\x94\x9dj9\xef\xabn\xfdP\x99Q\x91b\xd8-\xa5\xe9l\x98A\xc6\x08t\xf5\xaa\x18\x82B\xa4j\xec4\x95\xa8)K\x05\xe2\xa9\x0e\xeb2\xdc\xd1E\x18\x87\xf9\xb7\xc9\xfc\xb6\x93P\xcf\xd7\x85\xaa\xf1\xb6N\xe3\x10\x19\x97\x91\xc6\xe9UL\x07\x01\x1e\x14\x0d\xbda7\xd8\x90\x9d\xf3i\x17\xc1.\xa3\x04\xc3\xda|\x1b%\x97\x9a~\x15f\xaf\xe4\xdf/\x17B^\x91\xed\xf3\xa2\x9d\xdb_$\xe9\xfay\x90\xa3\xf3\xf4w\xe2\xef\x8e\xfd\xc8\xe2\x9d\xfb\xa2\xcb\x05\x18\xcc\x15-\xaco_\xffp\xa6\xbd\xea\xd8\xad\\>M\x9d\xea\xd4{P\xa0\x0c\xe0\xf5d\xb9\xb4\xebJ\x07\x1an\xc1\x84\xe3\x8cL'\xeaC\x0d\x1a8\x1c\xf3\xf5v\xa7\xc6\xfa6\x97Uh\xbe\x07.\x1f\xbcXT\x1e\xf9\x87\x0f\xb0\xa7u\xd0\xb0f\x80WH+\xb2\xac`\x15\xdb8\xdbn\xb8\xa8\xcf\xe6\xf0\xad\x9c\x0d\xaf\xd9\x16\xfc\xada\x95\xecH!s\x94T\xb7\xd0\xe6\xe2H7(\x90Lf\x9ci\xbb\xce,\x89s\x16\xe7}\x1a\"\x1e\x1a\x9a\xb0LE\xc6\x11u\xb3Z]\x1f\x9c\x9c\xdd\xe4\xfb\x9b(\x08\xe3\xc7\\\x8c\xcfX>y\xfb\xe6\xbb\xfeCG\x05\x97-\xb0H\x86\x8cRo\x06\xbc\x95.\xdd\x18\xaayx\xd1\xf5\xd3\x91@\x8d\xa6qz\xc1f\x13\x85\xb3\x80S\xb6\xfd\x9b\xfe\xf5\xf5u\x9f\xa3x\x7f\x9bFda\x9bWgm\x94`\n\xec \nxI4\xa5\x95\xbf\xca\xeb9!\x8521\xef/\xf2\x1b[@j\xbdPy\x11\x0db\x90\xc8\x04P.\xd6\xa5=\x0dz\xad\xcd\xb6\xe2v\xa7\x9e$\x954`\xe1,\xd9r\x8d1\xc9QdS\xe4\x17x5\x082\xe0\x8bnC\xc8\x1d\xc6\xcc\xb1\xadj\x9d\x85BP-\x91\x97\x0e[\xac\xf3\xd8\x1a%8\x92;\xcfq\xd4\xbeO\xa5\xe5\x17X\xc7g\xebz\x83|\xc5bwk2D\x8b\xe1\xe6D\xfeZh\xd2m \x8ak\x05\x06\xc1Q\xda\xfb\xd85i\x88n^\x98\xf74Kx^\xb1\x84OQ\x956\\yq\xf3i#\xeb\x95\xda\x8b\xddU\x0b*+\xa6/D\xa7\x95\xfb\x0c\xb4\xe7\x00\xbe#\xda\x97\x91\xddB\xd1uQ\x8fj,\n \xae\x15\x9dt\xb4\xe7#\x94\xa8\xbah@\xd5\x9f\xb3$\xfe\x9c\xb6\xfft\xf6\xf2\x05\xf9qX\xa9W\xe9\xbdMY\x98Y-\x18\xf2\xcc\xc5U'\x80\x7f\xff\xe8\xa1\xeaP_\x7f\xa4\x15\xba\xb5\xc4x\xe6\x0f\x06\xf5\xddhK,\xab\xeb\x0d\x92\xd06%\xb7\x85m*S\xed\xccR6gq\x1e\x06QFn\xdf\xc5o\xaeF \xf9\x00\x8a\x00\xb7\xe2\x05\xa1X\xe22\xf9FE\xfe[\xb3|\x95\xcc\xb11\xfaS\xbe'\x87\x19\x86\x7f\xf8t*\xaa\x1cx4I\x18\xef\x1cC\xe9\x9d_\xb57\x18\xf6P\x13\x0ci\x96\xca`i^~\xc3\xec\xf3\xd2o\x19\x98\xb3\xf2\xceI\xd6a\xee\xf8\xb0W,NE\x98\xb2/Vn_\xacv\xd2W\x98;\xf3\xe4\xedfc\xcf\x04\x00\x05\x1a\xdc*\x8f\x0ftF\xef\x8f\xb8\xbcit\xe7\xfb\xe8\xe6r0r\xe2\xc5O\xe7?N\xde\xa8\xe8\x87k\xe9\xf8\x84\x7f\xa8\xc2\xe2\x87\x96\xc5)e\x0b\x96\xa6( \xd0[\x17\xdb)BRj\x1d|\x7f\xf2\xecy\xed\x0b]\xc7\xb7\xc0<\xaa\xdex\xd12\x8a\x92k6G\xb6\xf0\x1f'o I\x81\xb7\x06)\xfb\xdb\x96eyfB\x08\"rR\x83w\xe3nV\x99E\x07\xab\x8c \x83MV{L\xb1!/\xdf\xddq\x0cV\xc3F3B\xabxP\xbam8i\xbam\xc8\x9f\x94.\xdd\x93\x05]\xcb&\xd2\xc3l\"\xd0V\x1d\x0f\xf7\x04\xf3\x9b8\xc6\x06\xec\xcc3\x97\x16P\x83[\x10\xd7\x91\x0d\xaf\x13\x83\xf4 \x16S[W\xeb\xf6\xa6}_\x93\x86\x0d\x951\xf4\xd3\xa3w\xf1\xfe.\xbbY\xdb\xacq\xdb\xd5\xd0b\xa3\x08\x8a\xec\xe2C\xed\xb6\xbf\xfeH\x7f\x07\xb9qc\xa7\xb9A\xd0\xf7*\xf5\xab\x9e\xb5\xf2\xf9\x9c=\x98[\xf9*q\x84\\O\xb8B\xaa\xf3\x04\x1c\xe1\xea#\x95\xe4,\x0f\xf2-'\xb7\x0e\xfd\xe5`jLN\xf3\xe4\xa71\x1c\x0c\x87\xa2t\xf2^\xc5\x8b\xa5\x8fO'\xfc\xab\"\xe7\xe2\xed\x138TU\xe8\x95\xb49\x14\xbfj\x1da\x9118/\xff,\xc7f\xe7\x05\xbe\xce\xb5r\xfc_\x84\x9a\xab\x90\xa9j@\xd5\xd2/4\xf0\xb0\xc1\x82\xe5\xe68rW\"\x16\xa0\x19*tS\xc2\x18\x9c\x8a%\x01\xa7g\x08w\xc6\x1fy@5\x06\x87\x0e\xa7\xa80\xfaX\xcac*|E_\xcd\x8dp\x85m\x0cN\xa1\xd0h\x8dp\x0d\xa3\xf8\xd9*\x00\xf2'Oo[\xcca\xda\xa1\x03o\xdf7eO\x96\xcfG\x98\x05\xe8R\xd7\xd5\xad~odo\xcb\x8c8\xb6l\xc0R\xaa\xe6k#\xfel\xda\x0bM\xfd\x1e\x83\xa3)\x1aT\xa9\x8e\x9ef\xd1\xa8d&\xf4\x10r\xae0\x95\x9dtv:\x95\xfa\xd6\xb9\xe3\x17.P\x85\x1aV\x7f}\x1c\x05\xeb\x0d\x9b\xd7\xbf\x9e\xc6\xf9\xe8\xbe\xb9\x92\xe9\xfdi\x9c\x1f\x1e\x98\x8b\x9b\xde\x7f\x17%\x81\xfd\xc3\xfd\xbb\xe2\x83\xe5z\xea\xba\x93\\\x06\xba\xeb\xc6\x9d;\xc07\xe9/!\xbbn0\xbf\x99\x81\xc0<\x88\xa5\xf4K\x13V\xda0\xe3\x8d7;[\xe9\x8f>\xb4\xc2\x01\xb8\xd5E\x8d\xc4E\xf3@\xebP\x93h-\x11\x9b\xa8\xf8\xbbX\xd9\x11\xa3\x90\x0cB;\x8f\xdd\xd4\xc2\x82$\xcb\"\xf10\xd8L\x99\xe5\x8e\xa1V@$wO\xa0\x07\x8e\x8f\x81\xb1al\xba\x8f\xef\x97\xc6?g\x11\xcbY\xa7\xad\x17EU\x97|\"\x86\xbc\xda\xe5\xf6\x97,\xef\xd4\xb8\xda8\xb9@\xc4F\x82\x8c\x0e\xbb\xf5y\x8e\xcb\xa9R-\x1d\xaf\x82\x9d\x1c\xd0d\x07\x15\x07<77;w\x96\xfb\xca*\x93l\x80\x80\xf2\xea hk_\x08Ym\xb9Y\xe5SI\x96-z\xf4\xacs$\xe7B\xa6\xfc\xe1\xd4\x18\xe3s\xbaqT;\x957\x8c\x11\x9d\";\x98,\xa4u\xd1vkV\xdf\x8f\xba\x83A\xc3 9\xe0)\xb9p\x904\xa32\xfa\xde\x9bM\"\xfaT\xd0\xd5\xe57\x98L\x87\x99\xd8N\xef;\xce\x84\xc5y\x1a\xfe\x16S\xe9\xb6/S\x0eL\x06\xcf\x0fh\x99R\xc51H\x9b\xa1\xc9E\xc8\xb0\x00\x96\xb3\xf8[\xe4\xf3\xcfO~8ys\xc2\xf9%W\xd8}\xa1\x9e\xfb\xe0\xbc|\xf5\xe6\xf4\xe5\x8b3\xfe\xe7\xab\x97g\xf8\xe9\xd5\xdb7\x8ea\x81fZ\x97\xb3(\x89Y\x97\x15\xd7\xa4\xb2\x19ZP\xfc\x86\x15\xbcL\xe6\xb7\xfa)\xdbi\x1cZ\xee\xd8\x1aWP\xa4\xcb\xd7\xc6\xe9\xa9\x97\xf3\xd2\xcb\xf9gNe^9\xf9o\x9a\x14i\x0fc]\xdb\xb0k\x84\x85\xaa1\xae\xaa'\xf6JB\xeb\x18K5D\xd3M\x1a\x94\xcfm\x1a\x8d\x95\x9a\xb2\xc3*\xcf\x07\x9d\xfdi$\xba\xd1\x92\x91\xc5\xa8}\xa1\x1a\x82\x82\xe8\xcb\xe3X\"h5\x9b\xcf\x98R4q\x16N\xd5\xf3\x11\xcc\xd2\xd0\x95\x88c==\x1c\x8e|8\x1c\x1e\xf0\x7f\x0e\xf9?\x0f\xf8?\x0f\x0d\xe82\x1f\xa4l\x1e\xa6\x1d\xd2\x8d\xcb'\\\xa8\xfc.\x97\x9a\x95O\xb7\x96i\x11\xb7\x94\xbb\xa9Pjg\xc9\xdcz@_\x02\xdd\xae\xfb\xd0\x05\xe2\x9a\x95\xa7(\xa1\xa3\xe6\xc6\xcb\xc6;\x80\x1e\x1b|\xafT\xee\x84\xff|M\x06A\x98\xc0\x8c~f\x9b$\xc6{\x9ds\xfe\x1b5\xe7\xae\xab\xaf\xadQ\xcdi-n\x10v@\xb7\xbe \x99\xc3^\x9aml\xa1(\xfc\x9f?\xfe\xf0}\x9eo\xc4<\xec\xa6\x9apG\xcf8\xd0\xb0\xaf\xb9\x14h;\x1e\xb6\xd2\xa7r\x0dB\xc4\xb0\x13\x91\x92\x8f\x02\x9d\x8d\x1br\xc1\xf9Y\x14\xc9m\x13\x9b\xeb\x8a\xa8\xbev\x97\x110#\xa9\xfe0a|qR\xd1\xf8\xdb\xd7?\xa0\xca\x1c\xc2\x11\x84\x03\xed-\x8c\x81\x95\xfdI\xfe\xb3/\xf6\xa3\xcf+\xb5\xf8\xbcH\x93\xa2\xea\xc8\xd0\x0b\xe6\xe9\x97?\xf8257\x19\xbb\x82\xc7\xe0%x;\xe6\xf8\x08\x16\x9d\xa9\xb1|\xd2\xaak\xe8\x0b\x96_'\xe9{i^\x87E\x10Fln\xf2\xfd\x90\x8f\xe8:\x0f\xd7,\xd9v:o\x97\xcf\x17\xeb|\xc3b7Q\xc7Q \x9d\x7fa\xaa\x1d'\x8cg\xd1v\xce\xe8\xf0!)\x9d\xf6p\xc9*\x1c\\\x87\xf9\xea\xb8tND\x15\xd5\x16\xddn\xe46\x96|\xc1\\m\x17\x05\x17!/\x0c>\x00 B;\xf9G\xcb'\xe4\xea\x95\x80:B\x03\x8b\xbb\xb4|\xb8$\xc9+\xc5sWsoO\xb4C\xb7#:\x8a\x1b\xeb/mR\xa9\x99\xd8\"\xf9\x1cl\x92\xe8v\x11F\x91\xc9+X\xfd\xe5:[y\xd1_\xbfk\x90\xb1h\x01G\xf4\xdfXS\xb1>\xeb\xa2l\xec>\x1a\x9a\xae\xaf\xf0\xf7\x0f\xcd\x17\x92\x1e>\xb2\xdc<*\xef\n\x85!\xe6\x84\xb0\xdc\n\x1e2\x8f!)\xbfUQ\x02\xc6\xb5\x9c\xf7\x9f9\xbf\xc3\x87\xd5y$j\x1e\xf5\xf9\xd5!\xeb2\x0df\xef\x19\x9fHg\xd3\x00f\x84\x9b\x9e\xd7e*\x83\x0d+\x8c\xe7\xe1\x8c\x95Zo\xe7\xab\xd4\x01f\x96\xa3\xe4s]zJ\xd9\x86\x05\xad10@\xeb\xa5\xdej\x19d\xeb\xf7\xd2\x9e\x079+Y\xcdN\xcf^\x92\xe1\xac\\\xd6\x1c\x8dg\xce\xa2p\xcd\x15\xb31\xde\x0e\xae}\x97\xc1n\xf6\x0cR-}K\xc7\x90\x8a\xe0\x13\xb6\"\x7fA]\xfde\x1c\xdd\x8e\x8d9\x063\x96\x86A\x14\xfe\xc2\xf8\\vX\xad\xa0v{U>\x86\xbd\xc8\xde\x87\x9b\x17\xdb(\xca,c@p\xe6\x05\xbe\x0f\xe2y\x84\x91Q*V\xf3J\xa3\xba\xc6\x0eL\x04~Q\xf1\xc82\x1f\"\x9f\x8buE\x88\x04\xd3l\xa4%\xdb\xc0R\xd1\xdbZv\xa0{\x82F\x1eV\x89\xb8Xwe\xba !\xdd\x82\xaft\x7f\x0e\xbe\xb6Tq\xe36\xd6RW\xc2\xaf\x9a\x04\xfdP\xb9LQ\x06\xb4\x15\xa7\x93|D[\x01\x0c\xe8\xfbf\xb8\xe2\xcd\x9f+\xf4\x8fm\x81u\xb0{\x9c_\xa1\x84U\x8f\x97A\xefe \x80\xea\x87t\x10f\xe2V\xc1\x95\xa7\x0d\xff\x08\xa6s\x17#\xc4\xc3\xb8:\x07\x8f#\xfb\x84\xa3\xfd\xdc\xcd\xdc\xab\xd2\xa7s\x18\xf3\x9a\xb1^F\xb8x\\y\x9eA\xa5\xe2\x9b\xbd\xf6\xd1~n\xb2\xe0\xe0\x96\x15\xcc\xf0J\x0d\xd1\x10\xff\x8f\x97-\xdf7\x8a<\x0f\x8f\x07\"\xcb\xd6\xdaU\xdc\xdbJ\xda3\x13t\x808|\x98\xc1\x11\xdc\x0e\xb2$\xcd\xdd\x19\xdf\xe0. \x9a\x94\xa9\xf3\x92\xbc\xdd.\xe1 \xac\x95\xb7[\xafw\xd9\xa4\x7f_\xc0\x04\xd6\xd3K\x8b\xc1\x0b\xdd\xbd\n\x80\x9d^`&\x07wY\xbd9\xef^yp\x04K\x99S\x86\xb9\xbc\xa8\x0f FP\xf3Z\xd0\x96\xcf\xb3V5\x86\x1e\xb8\\8p\x06|\xe7/T\x9e\xd2\x0b\x95\x9b\xb4\xb9Q\x03\xd1\xaa\xbd\x91\xfb_&CfQ\xa0\x91\x99\xa9s\xfd:\xe1\x0b\x80n\xe5\xa6\x83 \xcb\xc2e\xec\xfe\xfd#606\xc6\xcdQ\x01\x99\x02\x89\x07x\x8aS\xdc\xf7-\xbd\xd7\xc8W!T\x05\x05\x810\xba\xd1\x9c\x88\xfa\xab\x00\x03\xa0_2\x08\xd4\xe4j9E\xaeD\xdc\x1b\x0do\x82\x81bjp\x04[\xed\xd7X\xffV_\x89\x19\n\xc4u\xe2\x11\x0c\xea\xcc\x01\x8e\xcc\xaf\xc7\xb05\xbc\xae\xf7\xb5\xb0\xf7%\xf9\x14u\xa1~a\xcb\xf2W\xbd\xc1\x8d\xb5A\x11\x18\xea\xa8\xf8s\xac\xa8X\xbd\x1d\xae\xa2\x1b\xb9N\xb1\xb1G\xda\xdfES\x86\x05]\xd9\xdb\xca(\xa5\xbc\xf8\x83N\x8b\xea\x0d\\\x15;K\xb0\x85\x9eU\xcf\x93\x1cy\x8e\xf6\xb3^u\xdd\xd0\xb7.n\xd0 Jop\xa5\xf57\xf5\xd6\x97-\xab]H<\xdaji/\x8be+^\xd6\x91\xad\x04\xd4$\xdc{\xea/4\xa2\x0bo\x93r\xd5\"\xf3U\xa7\xc8\x15\x89h0gi\xe6\x17\x1dY\xb0\xf3m\xfc>N\xaec\xa1k@\xb2A\xf1g\x93&W\xe1\x9c\xcd\x8d\xf8)\xc2\xb1\xe2\x80\x8b\xae\xa6\xb2\xa7\ni\xb7l\xda\"\x8c\x08\xa1\xd1\xa1\x95s\x12\xf9\xces1/\\\xfd\x06\xae*\x80\xba/&o\xd7\xab\xd5\x07z\xedc*\x82*oF!D\xc6\xc2)\xe8\x98\xee.:\xe1\xfd\x0bj]\xbd\xf8s\x8d\x9d\xa2\xff\xc2w\xb4h\xc2\xc0R~9\xe6\x8a?*&\xa8\xba\x07X@\xbc\xe1lF}\x1csE\x9f\xeb\x15\x8e^\xa7>\x9b\x1b\x98@8\xbd\xaeL\x06\x83\xc8\xb8U\x96\x1f{\x18\x0d\xeb\xce\x1d\xc9\xdc\xabw\x1c\x15\x0f?#\x1e~\x06O\xe0V\xe3\xe1g6\xe1\xf6\x18&p;=3\xf0\xefE\x89w\xc7\xd3c\xe2\xdd|\x07N$\xb7\xcd\\\xfe\x1e\xa3\xf8\xde(\x0e\nG0\x97$\x83C\xd6\xca\x87+\x9f\x0bV\x17>,\xab\x8c\xf5cm]\xdec\x07\xe8f\x16\x19\xcc\x9c\xcf\xd0P \x90.\x98\xcf\xff\x9f-Ko_\xa5l\x11\xde\xf0m8r\x0c1\x9e\xc4\xce\xbf/\xf2 \x0c\xe1\x08\x9eA\x0f\xdeW\"\xfc\xe0_\xbf\x8az\xdd\x82\xeb]\xf4nEN\xcd*\x12~Vn#\xb6B\x1c\xa4\x7f\xe0,v\x0c\x07\x06\xa5\x91\x1c(Qi\xa4?ME\x9au\xd29\xdb\xe4\xab1\xdc30\xc1 \x0d\xd6,g\xa9\x18\xc0\x88\x1d\x1a\nEA\x18\xd3j}1]0\xe8\x10L\x05\xda\xbce\xd5\x0ekl\xeeH\xcb\x92\xb1\xffn\xe0N\x7f\x1aL\xcf{\x1e:\xb2N\xffmt\x8e\xf7\xfa,\xbeW 6z\xdf}7\x9d\xfe4}w~\xfe\xcd\xb9gK\\\x03b\x16\xe5\xc2\x94h*m:\x86\xe3\xd4\x0d\xc5Gq\xa5\xda'\xb2\xc5n0!\x85\xbdb\xd6p\x8e\xcd\x97\xa9\x16\xcd\xacZ`/\x1e\xe8[ \x98/\x0c9Z\x15\x1504\x1a\xa5\xab\xae\xc0\xb0$\xdav\x83vF\xa7\xe2\x86;[`=\xfdQ\xc4R\xe4\xf6VB\xb3\x1b`\x08G\xb1\xa88\xa6\x08\x9e@<@\x90n\x0c\xf3\xcdg\x1cA\x0fC\xe7\xef2\xf3`::\x17[3\xf2\xa1/\x02v\x7f\xc6J\x04\xc6\xa0\x14`]\x0ci\xab\xe1\xdd\x8a&HQ\x92\x10\xa3\xc0E\xe8M\xd6\x01tA\xb0Ry\xb9\x0d\x1c\xa9r\xca\xf2\xa2%7\x1b\x89\xe4\x03\xc3\xc7\xd0\xef'm\x8d\x81@\xd0\x90\xa2\x98\xb3i\xd2\x90\xda[>(9LE\x0c\xb6\xc0Cl\xc44\x08\xd3sO\xb28\x9b{\x99\xfet\xb8M-\x1f\xb4\x18\x97\xc1\xe3H\xf2\x86Y\xca\x82\x9c\xa1\x0eg\xd2\xefl\xcf\x95\x08\xe5\xc7\xb7\x8d\xd8b\x91\x9f\x91+y\xe7\x95\xd7\x81\xb6\xc6\x1e\xc9\xd7\x1a\xfcq-\xcc\xbe\xc7\xd5\x87S 4_\x9f\xc6\xb9\xbb\xf5ad\n\xd9`z\xf6\xc2\xecE\xf0\xc2\xcdp\x88\x01b\x1f\x06\xbd\x17\x06\x9a\xcc\xc31\xe3\xab\x8c\xc2\x8c\x8a\x1c\xc8i\xc6P|\xcc\xe8\xd3\x13\xa4\xc7\x8a\xa9\xc1\x91\xda\xc0iv\x8eQ\xf0\xc7\x10N\xb7\xf8g\xeb\xc0\xcc\x18\xa2?\x1cT\xc3\xc6R\xcdm\x08l\xb3\x0f\xe5\xa3\x9b \xec\xa9\x15\xa9\x98\x9a?\xc3\xcc\xf0 \xf6\x84X\x88\x03U{B\xe9\xbd\xd1\x9e\xa0JX4\x96\xe7l\x07{\x02\x8ei\x10.\xe3$e\xba\xe4\xa7dB\xc3G\x1f\x87 \x8d\x0c\x13S\xacl\xbd\x80\xb0D\xbef\xcb\x93\x9b\x8d\xab}\xf10I\xa5n\xae\x085s\x85\xe4\x12\xbc\x83\xba\xe5S~\xc3?eI\x8c\x83=\x11\x9eZ\xc1\xa0\xf8\xe9#f\xb1\xcd\xb1\xf0B\x0e\x06\x17\xea'f\xa5\xc8f\xc1\x86\xbd\n\xf2\x95\xba0\x8b\xa5\x0c\xefy\xf1ml\xab`\xfcR\x1e\xfe\xd6\x90\xd7\xaf\xd5\xad^\xc0c\xbb\xcf\x01]\xd0\xbc\xccXzE\x1e\x9c\xd3syk\xf3\xf2g\xa8f\xfc\x80\xba<]\xbdQ\x17\xed<\xb4\xb6@\x95\x9cv]\x06\xb3\xf7\x14\xc8\xad4`\x98\x98\xa2mV\x07h\x8a\xfd=\xab/I)\x8b*\xe5\x9cJ1-\xb9\xa471<\x81\xf41\xc4\xbd^]\xcb@\xdb\xce4>\xa7e\xc3H\x0bd[\xb7N\x0d\x19VlQ\xb7/S\x16\xbco\x99\xd9\xc2\xcd\xe9\xbe\x88\xaf:\xe3\x7fm8\x14s\x11\x0b\xd3D\xa8\xdfR{E\xabJ\x81\xaaz\x1b\xa2\xa4\xe1\x08\x81R\xc8\x8a\xefF#q\xa8\x1b\x891\x94\xad,.`\x8a\x15\xfb\xa8n\xfc\xf0_n\x88\x89\xbf4jY\xdf\xac\x85\xab\xb2\x01\xd4,\x1a\x18b\x82\x92\xe9\x98\x96\xda(\xa4\xe7\x83<\xf9\xd3\xd9\xcb\x17@9X'\xea\x85k\n\x14\xa3\xe0\"D\x9epAK\xfdg\xce\x9ar\x8f\x84\xa1\xf2[\xe6\x91\x98\xb37\"\xde\x17\x94\xac3\x99\xb0\xced\xfd~\xa3X\x83\xe6\x18\xe4T\xd3\xec\xbc\xc1\xa2\xb8\x97\xd6.\x8e\xf9\xb0\xf1*\xd2g>\xdd\x9cWt\xd0\x08Mf$\xc0\x94\x8f\x98rO\xc5\xac\xb7\x9bg\x92\x0d\x1e\xd9\xac\x93+\xd6\x90o{\x13\xe4\xab1\xdd\x0c\xdc'\xf3\x98\x81\xe0\xb9\x1b\xfb\xc5\x1c\\HK\xae\xd7\x16\x03\xd2\x95\xc8\xf9\xc2\xe7n7\xaf\x18\xf2ADP$i\xa2\x1f\x86B3\xbd\xd0\x8c\x0b\x89.\x89\xa2\x1cJ[\xe7\xcb\x85\x1d2\x11`;\xee\xde\xd0o_r(\x96\x1d\x05\xf3\x86u\x87\x1d\xd6\xbe\xb9\x15\x11}9\xd5X\xa0;kr\x81\xedjF5\xfbEm9\xe0*j\xb2W`\x8f\xb9YDNMm\x08\x15\xb5\xcez\xbd&\xeb'\x07\x8e\x0d\x9e%f\x0d\xc0Q\xc3-f\xc3-\xae\xfau\xde\xbf`>\xff\x87\xed\x1d\x1fm\xd3\xf6u\xd8=\xcd\xc5X\xfd\xc5\xa5\x1c\xc1\x96\xdb\xeciZQ=+\x02\x97\x94:\xb6\x80\n,\x99\xbe\x9bE\x9cR\x08\xb3!\xf1\xf5\x82\xa1\xe7\x94`871tPL=\xd7\x98\xba\xd2\xe1\xf9\xeb\xf2\x9a\xd4\x02 \xf1\xda\x898\xdao\x95vJz\xb9\x90?\xb9bq\xfeC\x98\xe5,F\xfb\xa3\xed\x93\xeb\xac\x93m\xc6\xb6\x1b\x87\xac.\xd6b\xef\xd9m{!lk\x9e\\\xc7m\x05\xdf\xb3\xdb.\xc5f\xab ^2,\x85\x807Of\xdb5\x8b\xf3\x81\xfc\xe3$b\xf8;\xc8\xf3`\xb6\xc2\xda\xae\x93\xc4\xe59u\xad\xa5O\xb1k\x9d\xea\x8c\xbb\xd6+/@\xd7Z\xfazt0A\xc4\x15\xb9;\x16\xaa\x01iO\xb1\x99J\x9b\x80z\x86y[\x8c m\x84\xddV\x12\xa7\n~!R'\x1f\x03\xc9+\xf4\xc3\x12\xc9C\x9e\xadw%r\x80\xc7>\x8c,\x08\xc9 _\x87\xaehH\x02\xb1\x0d\x13\x0d_-\xc8h,i\xc0G{\x8bu\\\xb3\xb5\xa9J6\xe3\xdb\x9c}\n\xbeUju\xc27SO]0\xa7\xdeW1\xb5\n\xeap\x8eT\xc0\x01\x85n`\xd7@I\x99\xbcRD\xd6\x8fd\xad\x8aYJ&\xa8\x19\xff\x8dv\xbe\xb4\x9b\xa0bp \x91F\x90B\xb1Em\xbd\x9a\x01\xac\xc9h\xa8\xb4\xe3\xcfI\x02\xd69\xadW)\xe1\xafQ\xa9\xd63\x94\x1d\x95~\x8d!\xf6\x06\xd9*\\s\xf6\xdd:/\xb9dZ\xc6\xb7%\xeer\x86'\xf2v\xa2%\x06\xdd\x12q'\x90\xadi\x92\xa7\xd9DdH\xab#}!-Ck\x0d\xf6\xa3mo\xbd?C\xee\x17uK\xcb\xac\x82\xd2\xfb\xfa\xb1\x19\xd3\x8c=\x9d\x9ce\x99\x0f\x0e\xff\x831\x87\x1cij\xb56\xa2\xfciv\x12o\xd7\x14\x11\xc3P\xf7\xc3\x07\xdd\xa5\xec\xa3Kq4\x0b\xc8\x89\xe1\x08}\x0b\x12oPD\xb3\x9f@JVR\xfdUb\x04\x94\x9d|\n\x8d`JQ;p\xe12\x11F\xad\xfaQ\x85\xf4(\x1d\xa8Y\xf6F.y1ih\xba\xebU\xda\xd1\xe6\xf1\xb1\xc1,\x89\xb3<\xdd\xce\xd0\xc0=\x99\xe8\xdf\xd0t \x86\xabv \x8e\x8aI\x8d\x0d#3A\xb9\x1d\xea\xb4\x93\xcc#\x0ee\x11\xb6\xaa\x9fh\xf2\xf7\x1a_\x1c\xeb0:)9z\xd7\x8bR\xa2\xc8#Sz!\x07\xcf\xe5K\xed\xb5\xf4\x9b\xb6\xe1\x96!g\x8f\xc4e}\xc8 \x0d\x00\xb3\xc2\x8c\xd58\xb4/\x81[\xc9Bo\xea\xcc\x90\x7fG\xe9\\\xeb`\xe3\x86\xcdc5\xe4\xa4\x91\xf4\xdcz$,\xe9y\x15\xbdE\x80%7\x9f\xc6\xe7\x18W\x9dM\xe3Z\x10\xfc:\xb57\x8c\xca\x90\x87\xa6\xa4\\+\xbaZ\x18\x82G\x15\x83\xa3*2\x1d\x9d\xf3\xb5\xd4\x7f\x8eIX5;\xf0bT6\xb6\n\xae\xc2d\x9b\x8e\xc15\xf4u`\xed\xeb\xa0\xdc\xd7\xc19\x1e3z\x83r\xabx\xc5N\x9a\xd5J#Pg\xe4|\xeb\x9a\xad\x0d\n\xb91&u\xb9\x15\xcf'+:}\xf3\xa5\x13e\xc4\x85\\%\xf2F&Y\xb7\x94\xbf:\x9dF\xe7t\xda\xad\x1f\x91\xceD\xe2\xe8\xe1c\xd8\xc0\x13X\xa8\x067v#\x18o\x11#WL7\x0d\xa7\xe6+.\xf0L\xe7\x0d%\xae0\x97\xe3\xaa\xc1\x12\xb5\xc6\x12\xe1tn\x8b\xef^\xba\x8a\x80W\xde\xec\x12?\x96- \xe3\x13X7\xa9\x1b \xe6\x8a\x0e z'k8\x02>\xa8\x0e>\x83!%\xc0\xce\xd0\xebk\xba\xf4a\xeb\xae\xbcs\xa3\xbb\x99|D\x9clQs[\xbbz \x1fu\xadE\xa76m\xf3\xd7\x8av\x9a\xfb-\x1ex\xdb\x86 \x1f1V\x07O\xbd\x1d\xe1\x17VA\x13Z2\xe9+pk\xbe,)\x9f\xf2\x1a\xd8\x07\xa0\x97Z\xd5J\x18\xd5\\\xfd\xc0H5\xd3)\x17f#\xd5\"\x12$NA\x90\x84\x1dA\x8en\x1ecL\x1e\xcd)\xc1Hd6(R\x1a\xf0\x02\xe7zk\xd3\xd4,\xefg\xe4\x16Q\x8c\xdd/\x06=\x88\x93\x1f\xb7y\x907*\xe6j\xf0\xcc8\xf8\\\x0d^\xe6g\x18\x92\x1e\xcdH\x8f\x06\xc1\x07\x8a\x81V\x0f \xd5@\xc9\xbf\xd1<\xd2\xeb0_\xbd\xc4+R5\xdfI{\xba\xd5L}\xafl]\x8b\x8cg\x0f\x0c!\xf3\x8fC\xec>\x1a\xdd\xab\x10\xa0\x8b\x0b\x96\xfd\x98\xcc\xb7\x11^\xf3\xdf\xad\xcb\xd8\x1d=x\xc0\x17\xd0}t@\xff\x8d\xee\x8b\x9f#\xf1\xff\xa1\xe7\x97\x05[wt\xcf\x1b\xfc\x95\x05\xef\x7f\x0c6]\xfah\x10]}\x99\xc9\xf7p\xe4\xb9U?\x8ePtV\xbd,C^\x0e\xa3\x83\xbb\x95\xf7[j\xea~5Y0\x0d\xfa\xd1\xa8\x1a\xbb\"\xa2\xf2\xd5\xe6g\xf8\xfa^\xd5{d!\xbcG\x0e*\xef\xf1\xdcr\xb0d9_\x91\xf2\xa7y\xc1\xbb\xc2\xec\xe4&gq\x16^F\x95\xcb\x1e\x9c\xedd\x83\xed\"\xcb\x93\xb4\xf2\xe9\x8a,\xca\xa5w\xed\x01d\xab^\x076\xaa)Y\xb8\x88\x8ag\x904\x86%qbx\xaed\xd3V\xd7\xe3\xf2\x98\x97FYg\xc9:\x05\xd6\xc0{\x13(A\xdb\x89\xbf\xa4q\x1bcj\x06\xf9\x88 \x0b?\xe0\x1c\x8e`\xe5.\xc4\xec\x1d\x01\xcf\x8e\xe7a\x0c&\x94}1\xfa\xb6HU\x14\x16\xb37v`8\xf4\xab\x8b Yy\xca\xedAK\xb2\xc1\x9c-\x0c\x83\xf4\xd1?d\xc7m\xb8\xadj\xa8\xee\xa3\x83\xa1\xe7\xaaV\xf1\n\xde\x12o\xbb\xef\x0d1\x96Q\xb1\x963\xb7\xcd\x18\xf1\x00\xf6&\x80\x96\xa5[\x0fs\x7f\xc9\xbb,\x8b\x94\xb1_P\x18\xa4\x17\x9e{\xe5\xf9\xf0\x80\xd6Yc\xff\x1fI~\xdf\xba.\xa6l\xe3\x9f\x8f\x0b\xad\xd0]\x977I\xbb!\xb3\xf4|\x08\x06/NN\x9e\xe3\x01\xba\x0f\x89;u(\x8e\xae\xe3\x83\xb3\n2\xfe\xdf\x92\xe5\xfc\xbf\x8c\xe5\xce\xb9\xdf\x00w\x12\x96n\xb5.j\xeb\x8c>\xf2\xb5x\xc1!\xc6L\xd2\x1a\xcf\x0d^\x1c\xa0`:'\x03\xc4\x1c\x9d\x10\xcc`@\xb0\xb7(\xd2\x7f\\,\xc4\xe1TSP\xe3P\x065\xbeXL\xd99\x8d\xc2\\Zj\x86|U@\xe8\x9b\xbc&\x8c\x0d\x97\x18\xec\x0e\x91\"\xa8-\x02i^\x8b\xe5\xffQ\xdfc\xfa\xbbs\xa2\xf0G\xa3\x87\x96\xc8I\x8dh$\x07\xc6\xae]\xd4\xbe\xf5\x10\xaf\x9d\xf8b1\x82\x1a\x7f\x10\x1c\xab\xc6\x96\x04\xbbz\xe4\xb9N\xb6a\xb3\x90\x95\xd2\x84t\x93\xd8\x10\xf8\x8cb\nj\xe5\x1c?LW(\x84\xf1I3\xa2\xa0}\x8a\x9c\x85PJBHK\\\xcd\xce\xe5\xa9\x1c\x08\x82\xa6\xfb\x90\n\x90T\xe6\x10\xf2\x18\x9a\x86\xe7\x9e\xf2\x1f\x12\x85\x8b\x1c\xf1\x92\x96R7\xe3\xd6T\xf6\xdd\x85\x03Z\xe7\xe1}\xe3\xfas\xf6o\xe6\xba\xc2\xcd\xb3Z-0\xef\xa6\x10\x1a\x86UaBH:w\xab\xef#%\xaf\x18\xa5\x86\xaat\xd0$5DnU\x92\x9b\xe3\xdb\xea\xc8WxxT\x86\x93\xaeR\x00\x1b\\`\xea\x07\x17\xff \xd2\xb1\xae\x1e\x10\x94~\xae\xdbN\xcb\x90\xb2\x04hrojg\xd9\x86\xa3P\x8cr\xe3\xb2A\xd0D\x94+\xe5\x19\x17F\x10\xf0j\xa5\xaa\xd9\x90\x0b\x98Zk\xd6\xc3\xaa<\xd2A\x16\x91|a)\xe8\x9c5 \x94:\x83\xcb\xa7\xa3\xc6\x15Z\x05\xad\x01\xd2\xa4\xc8\xb2W\xf4\xda\xd4b7\xf9B\x1e;4\xcd$F\xe7yT\xf5r\x99\x021\x10\xf1\xa5Y=\xbete\x1c\xc4|\xdb&'WT\x043\xd6\x01\xa0M.\xca%\x00\x18\x9cv\x0d\xb3\x11\xb5\xfe;\x07\x99\x88%\x90\x07\xa2\xb9\x8f\x97\x08\xf6\xf6\xfe\xbb\x9aTF\xfd\xe57(fe!e\\#u>\x84\xb6\xa9\xa3\xdbc)J\xa35\xc4\xeb\x96\x7f\x8d\xb0E\xe7\"$g\xd7\x8b\x9c\xdcE\xd8\xe0\x82S\xbcU\xaf\xe7\x83@r\xa2\xcc~a$\x04\xbc|\x97\xb9)\x8e\x88M\xc3ss*|\xfb\xd2\xa5n\xa4\x8b\\\xe6av\xdbv\xf9\xa0Gg\x80\x92\xbd\x04\xf3\x91]x\x97@\x9b\xec \xe2s \xbeR\xd2s\xeey\"\x11\x03I\xf71_\x93\x99\x1b\xab\x9c8\xc8\xe4D\xfe\x85X\x89\xfd\xc6\xbe,\xee3\x1d0Z>\xff\x88\xd9\x8bD\x0f\xa6\xa9\x9bgi\x80\x10\x1f\xa2f\xcc_\xd4\x91\xc0\x86\x01)YK\xd1\xb7x\xcft/\xb8<\xa1\x14'\xc4H\xbb\xc8\xc5\xa5\x9bt\xcaP9\x9b d7\x0dM\xa8\xd8c\xb8*P\xfb\x0f\xf0\x05$\x94\xaa( \x04D\x8b9\xa3f\xb6\x08\xcc\xf6\x06\x12L\xeeU[\xc9,RQd\x91Wf\x16\xf9fa\x16\x876$uW\xc3\x9b\xce\xf1\xf5\xdd\xa17X\xd4e\x13\x8b\xf9\xe6\x8a\xea\xdcm\x15\x82%\xa5$\xed\xf3\xd6$\x13_\xe2y\x003\xd8\xe6/`\x02\x97\xf5\xd7\xd7\x9c\xbf\xe1!!\xa30;f?\xd4\x13\x98\xc0\x05G\x86\x8b&m\xef\xc6p\x1e%@\xf3\xcaz\xba\x89\xcd\xba\x18\xad\xe7D\xe5\x16\xe1Rx`W\xa5\xf9\x83*\xf4\x85'\x93*\xb8\x1ez\"\xb9U\x95\xca\x83#p/0\x91\x8b\xaen\x1aqm\xc6\xbf\\\xa0j\xea\\\xcc0\xeb\xe2\xe0b&\xa4\xc1K\x9dO a\xc0\xebsK\x1f\xf2\xe9\xf5y\xcd\xca\xc0)\xc0\xca\xe5\xcb\xe9\xa3\xc3\x94O\x04\xd3\x173\xf4\x97,\xf7WA\xe6g,\xf7\xdf\xb3\xdb\xcc\xa7<\x1f\xbe\x98\x8eO\xb7\x0f\x1c\x99\x9e\xce\xe7\xa3\xe9&&\xe0\x16\x82\xbcnZ\xa8\xacu\xb2\xc1 \x8c\xe1\x84\x9c\xcdq\x03\x1c\x1c**L\xa4Em]}\xc3K:{S\xa8uN\xb4e\x16 \xbe\x9e\x9cn\xa1LA\xfa\xd5\xc2\x8d\x0br\x8e\x06\x07\x1a\xae:\xaf\xb3\xab\xec*\x0f\xd1\xc5\x8c\xab\xec\x05\x05\x1frr\xed[\xd5})\x0f\x15z{R+W\x15\x89=\x9f\x82H\xcd\xcb\x8b\xe0d\xe1/\xcc1\xf1\xf6\xb2t\xdc&\x9a\xd1,\x06\xbc\xb5\xfaPjP<&(^W\xcd=dIY\xfap\xed\xf9\x90\x95G\x1a\xe3\xadOe\xf0\xf1|\xd8\xb8b;n(G\xd3\x85\x0f\x89\x9b\x0c\xfe\x03z\x90\x0c\xfe\x8a\xff~\xe7\xc3\x8d\x9c\xf9\x9a\xb3\x90\xb3\xc9J\x98\xa4\xcd\xb0\x16\xa1\x1eTy\xaf\xec#\xe72=O\xb5\xe7\xc3\xfe\xf4\xa7\xa0\xff\xcb\xb0\xff\xe8]\xff\xab\x7f\xfb\xe3\x9d\xaf\xbf\xe9\x0d\xde\xfdt\xf1\x7f>\xfc\xf7\xf9~8\xc8Y\x86\xb9\xd7\xcc\x81Wd\x82\x97\xd9*H\x83Y\xceR\xceW)\xcd\x00,B\x16\xcd!\x0e\xd6\xc6\x9c/\xca\xfa\x94'?$\xd72\xaftyq-sn\xb6\x84t\x9e6\xeb\xd4\x99\xc1\xf1\x11t'$#p\xc5\x98u\xa4\x95\xac\x82\xd6\x10\x93Iv[\x957{[\xfc\x99'1+9\x88\xb5$<\x11\xb7\xa2\xccI\xac\xc0\xa8\xe2\x99\xdf\x1a\xbcF\xc4\x80+i\xc3rS\xb2\xb0\xd6\xb5\x92\xb2C\xbd\xdf\xce\xd9~\x0d\xde}\xa0\xa5\x02\x14\x97sJ\x19\xf2\x13\x0c\xfd\xb1S\xbe\x0c2\x1eQ\xd6bs\x82\x0c\x91\xf9\xbf\x1e\xcd\x14\xbd\xeaL\xddu\xe9\x8bM\x87\xe7>0c\xe86\xadG\xdc\x03q\xee\xb6d\xb9\xe6\x1e\xf7\"X3\xae\xfd\xef\x90!\xaf:\xd7\xa9)\xab\xdcGS\xe6B\xdb\x1e\x19|\x13A]k\x90\xd9\xf8\x95\x04-\xb2 \x0dR\xc6\xe7S\xcd\xdb\xf2,JY0\xbf\x05\xfe\xafc\xba\xcc\\\xc9\xef\xdfi\x80\x06\x7fF(K0\xb5\xd4LM\x81\xec\xd8\x8eY\x93r\x97\xcf6\xdbF\xb6D)x\xff}\xb7\x8c;\xb1\xcb(aZw\x1bO\xa7\xa52\xf8n\x82F\xf1\xf8Z\x15\xb9\x97\xcdT*FW\xa9\xdc\xce?\xf2\x01\xdf\xddg\x99\x96\xac\x96\xdc}:\x8d\xd0\xe0\xc7 \n\xda0\x86\x8cvCP\x04\x9f1\x8cE\x9fQ\x91\x8f\x98\x03\xecm\xce~\xa0\x0b\xbb\x0d3\xc8\x18\x81\xae^\xd5C\x15\xfc\x12'\xd4i*QS| \xc4S\x1d\xd6G\xd54\xdf\xad\xa7E \x0f/JY\x05\xe9\"UC\x12\xa0\xd0\x9c\xdd\x81yZ\x0eE\x91\xd9\xdc\xa0\xa6\xcbG\xf9\x05\x16\x89\x8e\xbe\x8d\x92K\xcd%\xbf\x9a\xecXo\x9f\x17\xed\xdc\xbeL~\xcd\xfb\x90\xe1g:\xf6#\x8bw\xeeK\xcf\x7f\xce\xfb\xab$@\xef\xd8\xad\\>u\xc1\xa2I\x86\xd0z\xd7\xd2mC)\x87\xd4\xba\xd2\x81\x86[\xe8\xf7\xc9\x04\\\xca\xec\xc0:4\xc4\"\xb7\xb9;5\xd6\xb79\xbdB{\x00\x03\x90&\xf1\xf2\xc8?|\x80==S\xb5}\xcd\xd0\x00\xb3\xac\xc8\xb2\x82U\xe8\xd7-\xbe\x95\xb3\xe15\xdbr\xab5\xac\x92\x1d)\x84+hm\x0b\xab1\xa7\xe5\x83\x05K\xf9\xdffI\x9c\xb38\xef\xd3\x10\xf1\xf8\xd6\x12\x04\xadT7\xab\xd5\xf5\xc1\xc9\xd9M\xbe\x8f\x01\xa9\x1es1>c\xf9\xe4\xed\x9b\xef\xfa\x0f1\x04W\x05\x8b\xe4\xe1\x98z3\x10W-Z\xbb1T\xe3\xed\x7f\x0e\x12\xa8\xd14N/\xd8l\xa2\x90\x92<\xee\xdf\xf4\xaf\xaf\xaf\xfb\x1c\xc5\xfb\xdb4\xa2\xe8\xfc\xf3\xea\xac\x8d\x12\x8c\x96a\x8d\x88)\xd1\x94V\xfe*\x8d&!i\xcc\xe6\xfd\x0d)d\xb4\xe44\xf6B\xe5E4\x88AY\x12]\xb1j\xb1.\xedi\xd0km\xb6\x15\xb7;\xf5$\xa9\xa4\x01\x0bg\xc9\x96k\x8cI\x8e\"\x9b\"\xbf\x98t\x17\x82\x0c(\x93]\xa3e\xa2\xcb\x989\xb6\x9d\x9b\xb7\x99\x04\xda\x12&\xb7nq\xc9\xaaY\xa5\x04Gr\xe79\x8e\xda\xf7\xa9\xb4\xfc\x02\xeb\xf8l]o\x90\xafXl\x8aM\xfdQ\x92\xdf\x9c\x88G\xeb8\x7f\x13Pl\x17\"`G\x11P>vQP>\x15\x91\x90o\xb3A\x16\x94\xcf\xc7_\x0bM\xba-A\xc9\xf3\xbe&\xfd\x91\xbfzaS\xcde\xdc\x17\xf2\xba\x1f\n\xaf{u\xb5E:\xdf\x9f+\x1b\xc7`\x91&\xeb\xe3U\x90\x1e's\xe6\xe6\xd3F\xd6+\xb5\x17J\x99`\xcbk\xfa\xd1\xb2\x10\x9dV\xee3\xd0\x9e\x03\xf8\x8eh_Fv\x0bE\xd7E=\xaa\xb1($\xb8Vt\xd2\xd1>\xc7\xf37B\xd5E\x03\xaa\xfe\x9c%\xf1\xe7\xb4\xfd\xa7\xb3\x97/(\x06\xaf\x95z\x95\xde\xdb\x94\x85Y\xab\xe7\x0f\xf9\xf5\xd1\xfd,\x0fU\x87\xfa\xfa#\xad\xd0\xad%\xc6\x08\x94`P\xdf\x8d\xb6\xc4\xb2\xba\xde Q\xda\\F\xf9T\xf1\xcd\xac\x94)\x95\xe9\xbf\xb9\x1a%\xe4\x83\xc2Gv\xa5r4\xc7\x98\x8f\\e\xd7\xf5\xe4NQ\xd6VlL&p\xa5\xf7\xc9\x9c\xd1\xdbd\xce\xfcR\x82\x18`\x9a$\xcc\xbb\xc2l\\z\x06\xf6\x8a\xbd\xc1\xb0\x87\x9a`H\xb3T\x06K\xf3\xf2\x1bf\x9f\x97~\x7f\xf8P_\xa1\x0f\x1f\xc0I\xd6a\xee\xf8\xb0W,NE\x98\xb2/Vn_\xacv\xd2W\x98;\xf3\xe4\xedf#\xed\xbe\x8d\xc8}\xabe\x1a\x87\xa7\xd0\xa7{H\xa6\x8c\xdd\x1f\xdd\\\x0eFN\xbc\xf8\xe9\xfc\xc7\xc9\x1b\xc7+\xefcN\x7f\xa8\xc2\xe2\x07\xe5\x9d\xc1W)[\xb04EI\x80\xde\xba\xd8\x0e\x99V+\x1d|\x7f\xf2\xecy\xed\x0b\xf9\xcbZ`\x1eUoN\xf90&4\x9b#[\xf8\x8f\x937\x90\xa4\xc0[\x939\x873\x13B\x10\x91\x93\x1a|5\x8e\x8f\x0d\xf7\x17\x1d\xac2\x82\x0c6Y\xed\xd3p\xedz\xf2\x8c\xfe\x8ec\xb0\x1a6\x9a\x11Z\xc5\x03B\x1e\xd1~cxb\xfe\xe0\xf6H\x0b\xba\x96M\xa5\x87YT\xa0\xad:\x1e\xdc \xe67q\x8c\x0d\xd8\x99g.-\xa0\x14d\xf8\xed\xeb\xd3\"&\x19\xd7\x91\x0d\xaf\x93\xeeq\xe1:[\xb77\xed\xfb\x9a4l(\xad\xf4\xfe\xbb\xf4\xe8]\xbc\xbf\xcbn\xd66k\xdc\xb4\xda\xe5\x8d\"(\xb2\x8b\x0f\xdd2\xda\x8b\x8d\x1b;\xcd\x0d\x82\xbeWi\xed\x0e\x82|>g\x0f\xe6V\xbe\x9a+_\xfa\xbf\x17\x82\xbbH\xd0-\xae\xeeI%\x99R\xd5SXs\xfe\x17\xe6\nC\xf7\x0d\xf9i\x0c\x07\xc3\xa1\x8c\xfe\xfa^\xfa\x85\x88\x8fO'\xfc\xab\"\xe7\xe2\xed\x138TU\x8a\\\xf8E'\xfcW\xad#,2\x06\xe7\xe5\x9f\xe5\xd8\xec\xbc\xc0\xd7\xb9V\x8e\xffc\x8a\xfc\xaa\xa1\xb1j\x17)/7\x1axDZo\x1b4\xaf\xac\xc7n\xba)a\x0cN\xc5\x92\x80\xd3\xb3\xe4Q\x92\x07Tcp\xceD\xcc\x88P\x06\xa6\x90\xc7T\xf8\x8a\xbe\x9a\x1b\xe1\n\xdb\x18\x9cB\xa1\xd1\x1a\xe1\x1aF\xf1\xb3U\x00\xe4O\x9e\xde\xb6\x98\xc3\xb4C\x07\xde\xbe_=\xc3\xd0\x9f\x8f0\xc3\xe0\xd4\xcd\x94\x174\x97\xca\x91\xbd-3\xe2T\xa3\x1f\xcbGJ\xd5|m\xc4\x9fM{\xa1\xa9\xdfcp4E\x83*\xd5\xd1\xd3,\x1a\x95\xcc\x84\x1eB\xce\x15L`\xaa\xe2\xd5\x9cJ}\xeb\xdc\xf1\x8b(6\x85\x1aV\x7f}\x1c\x05\xeb\x0d\x9b\xd7\xbf\x9e\xc6\xf9\xe8\xbe\xb9\x92\xe9\xfdi\x9c\x1f\x1e\x98\x8b\x9b\xde\x7f\x17%\x81\xfd\xc3\xfd\xbb\xe2\x83%,A\xfbuP\xf9H^\xc0!\x94o\xd2_Bv\xdd`~3\x03\x81y\x10*[\xaf\xb0\xd2\x86\x19o\x9cS\x88\xdd\x87v\xa5\xc4\xc1\xd6\x10C$.\x9a\x07Z\x87\x9aDk\x89\xd8D\xc5 \xd5\xca\x8eP\x94D\xb5\x9d<\x83\x9a\xae\xde)?\xbeu\xb0\xb1:Di\x05`\x82\xa7\xd0\x18\xfd\xd4\xc7\xe8\xa706$\xff\xc1 ^\xc5\xf8\x85\x93z\x97\xad\x17EU\x97|\"u\x9f\xf6J\xfbK\x96wj\\m\x9c\\ b#\xe4f~T\x9a'\xa5{l\xebx\x154\xfbFU:\x96\x1d\xd4\xc2Bs\xe8h\xeb+\xabL\xb2\x01\x02\xca\xab'\x80\xa0\xad}\xe9\xf3\xdb\xe1\x1a\x14\xd4\x02\xdc\xc8\x1e=\xeb\x1c)\xdc\x8d\x88L\x95\xfb\xc5\x18\xe3st\xfc\xcak\xa7\xf2\x861b\xd0\xb2\x0e&\x0bi]\xb4\xe5\xfb\xd3\xf7\xa3\xee`\xd0\x92\xea\x8d\xc9\xc8lfT\xc6\x8b\x89f\x93\x88>\x15\xf23\xfe\xf5'\xd3a&\xb6\xd3\xfb\x8e3\x11\xae\xd2\xbf\xfeT\xba\xed\xcb4\xae\xdf\xf7\x92O\xd3\x94*\x8eA\xda\x0cM.B\x86\x05\xb0\x9c\xc5\xdf\"\x9f\x7f~\xf2\xc3\xc9\x9b\x13\xce/\xb9\xc2\xee\x0b\xf5\xdc\x07\xe7\xe5\xab7\xa7/_\x9c\xf1?_\xbd<\xc3O\xaf\xde\xbeq\x0c\x0b4\xd3\xba\x9c\x89\xf4\x17\xad+\xaeIe\xd2\x13\xdc\xbe\x82\x97\xc9\xfcV?e;\x8dC\xb3+\x96!\x16\xf5G\x1f\"Bnm\x9c\x9ez9/\xbd\x9c\x7f\xe6T\xe6\x95\x93\xff\xa6I\x91\xf60\xd6\xb5\x0d\xbbFX\xa8\x1a\xe3\xaazb\xaf$\xb4\x8e\xb1TC4\xdd\xa4A\xf9\xdc\xa6\xd1X\xa9);\xac\xf2|\xd0\xd9\x9fF\xa2\x1b-\x19Y\x8c\xda\x17\xca\x90D\xb7\\\x84\x96\xc7q,\x83nDm\xa6\x14M\x9c\x85S\xf5|\x04\xb34$/\xd5L\x0f\x87#\x1f\x0e\x87\x07\xfc\x9fC\xfe\xcf\x03\xfe\xcfC\x03\xba\xcc\x07)\x9b\x87)\x05\xd8\xed\xc4\xd2\xb8\xa0.RK]jV>\xddZ\xf6:\x88\x97UwS\xa1\xd4\xce\x92\xb9\xf5\x80\xbe\x04\xba]\xf7\xa1\x0b\xc45+OQBG\xcd&\xeb\xa4|,\xea\x93\x11\xf4\xd8\xe0{\xa5r'\xfc\xe7k2\x08\x02\x86^\xe5?\xb3M\x12g|{\xe7\xfc7j\xce]W_[\xa3\x9a\xd3Z\xd3%\x17\xd0\xad/H\xe6\xb0\x97f\x1b[(\n\xff\xe7\x8f?|\x9f\xe7\x1b1\x0f\xbb\xa9&\xdc\xd13\x0e4\xeck.\x05\xda\x8e\x87\xad\xf4\xa9\\\x83\x101\xecD\xa4\xe4\xa3@g\xe3bN\xa7gQ$\xb7Ml\xae\xeb\x91\xb1\xc4\xee2\x02f$\xd5\x1f&\x8c/N*\x1a\x7f\xfb\xfa\x07G&\xa2\x0f\x07\xda[\x18\x03+\xfb\x93\xfcg_\xecG\x9fWj\xf1y\x91&E\xd5\x91\xa1\x17L\x0f(\x7f\xf0ejn2v\x05\x8f\xf1\xc1$\x97\xcb\xe7\xa3\x8f`\xd1\x99\x1a\xcb'\xad\xba\x86\xbe`\xf9u\x92\xbe\x97\xe6uX\x04a\xc4\xe6&\xdf\x0f\xf9\x88\xaes\x8a\xfe\xfd\x0f\xe9|\xc3b7Q\xc7Q \x9d\x7f\xe1\xe5&'\x8cg\xd1v.\xe2\xd4%\xa5\xd3\x1e.Y\x85\x18\xa5\xec\xb8tND\x15\xd5\x16\xddn\xe46\x96|\xc1\\m\x17\x05\x17!/\x0c>\x00 B;\xf9G\xcb'\xe4\xea\x95\x80:B\x03\x8b\xbb\xb4|0j\xe4 c\xf1\\\x0f\xa6\x9ah\x87n*}\xa0\xf6\xd2&\x95\x9a\x89-\x92\xcf\xc1&\x89n\x17a\x14\x99\xbc\x82\xd5_\xae\x9e\xc1\x163[\x90lQ\x8d\x85\xf6\x07\xd1xiqv\xbai\x94\x9bn\x19\xdd\xbb\xeb\x0d\xc8\x98b\nd\x1b\x1a\xb7\xc0lQ\x14\\\xc0pLQ5\xd5J\x13\xa2Q'\x10\xcd\xa4*\x8d\x9b\xf4\xc6\xe5\x03\xd1|\x13m\xeb\xa9\xfe\xaa\xb6\xd0\xc6\xcd\n\xb5\x18\xef2\x89\xec\xdd\xf2`W\xf9Ml\xe9\x9eQF\xffE*KN\x910\xdc\x9a&\xe7J\xc4\x1b\xcd\xe0I\x11N\xfa\x88k\xd6\xc2\xbf\xe2Y\xee\xa2s\xfd\x8b\xe0E\x9d\xcee\xd7!\xae\x9a5\xdb\xfd,\xc8\x18\x0c\xc7V\xc0\x97\x0dX\x8f\xd7\xe5\x83\x0d\x1d>\xb0\xb7$\x1f-\xd9\x80\xb8z\xd5\x10Y@>\x98\x86\xad\xb9\x18\x0e\xe0\xeea\xfb\x00\xf0J\xac\xcb\xd7\xf4\xf0\xa0\x85\xdb\xc8\xc0\x86\xadm\x06\xd3\xa8\xd73'\xea\x94\x8fY\xf2\x82\xe6\xc9\xe1\xa4F\xf6\xfe\xb9\x0c\x1b\x92<6\x83\xa7\x13\xb8\xfb\x90On\xc6!\xeb\xde\x03\x0f\xd7z\x06}\xb8\xfb\xd0>O\xe5\x95\x8b\x0d\xdc\xbf\xa7\x1ax0,\x1a\xb8\x7f\x0fz0\xb2\xdc\x10\x86\x1d\x1ch\xa9\x97G\x0fT/\xa3\xe1Ac\xf0<\xf9\xa8\x15>|\xe0k\xcb-p\xab#\x045\x96\xb2o\x10\x08\xb0\xe5+\xf1\xe8\x01\xae\xc4'l3\x1f\xe8\x81}\xa0mPp\xd0\x0c\x05\x82\xc4\x98\xa0 \xfd\\(H\x7f\xe7P\x10\xea\x10\xf1\xeb\x83B\xfa\xd9\xa0\xa0F;\xba\x0f\xdf@\x0c=\x93Q\xfd\x0f\xf6_\x82\xdf\x05ER\xe2\x08\xfaz\xea\x94\x8f\xbe\xc6\xca\xf8\n\x15\xab\xa2XVP\xf2\xf2;\xb8w_2\xaa\xc7\xb0\x85'pp\xef\xfec\xe8\xf5\xb6\x1e\x04\xd3-\x86#\xfe\xa3\x03=p]\xfeqt\x1f\x8e\xc0\x19:\"]r\x0f\xb6\x05\x97\x1d\xdd\xf7<\x9b\x87\x8d\xcc\x9e\xd6hFo\xb8E\xd9\x9b\xf0\xfe\xca[\\\xf2ft\x9cR\xceP\xe1\xac\xc8\xb4T\xc5F\xcdRj\x94%\xb6j:I!\xf0=<$\xf9\x8fkNw\xefi\x7f\xdf/\xfe~\xa4\xbd\x1f\x1dh\x1f\x12\x0e\xfb\x87\x8f\xf8\x8c\x12\x0e\xfbw\x0f\xd4[B\xdc\x84\x10W\xbd%l\xc4\xb7\x8f\x86\xea-a\x0f\xbe\x1d\x1d\x1cX\x04xtd\x80>\xc4*\x1dh\xce\xd7P^(BE\x9b\x8b\xd3|K\x0f\x1e\x12\xbdO9T\xfb\x80\x05\x83ib\xb1\xdd*\x82\xc1\xeb\x1e\x0c\xef\x1a+\x8f\x1e\x1d\x00\x0e\xf7)\xdc?\x87\x1e\x7fs\xf0\x10>\xc0\xfdC\xb8\x03\x9dZ\xbew\xef\xe0\xd1}5\xe7{\x0f\x0e\xef\xde5utppWv4:\xd0{\xa2\xbe\xe1\x0e\xdc?\xdcm\x00\xcd\xd6\x87\xb0\xc1v\x80\x10\xd2\xeb\xe9pW2*\xbd}}*\x94\xb1\xb7\xafOa\x1dD\x8b$]3\xab\xdb!\x08\xfb\xc5hx\xc0\x07]\x81P\xdf\xb4\x18w\x87\xf0\x81\x12\xc5\xdd\xbfw\xef\xf0>b\xad\xa8\x9ex\xf0\xe4 \x8cx\x81\xd0\xf3p\xbd\x1e\xd6\xd6ktP[\xb0\xe6u4\x0e\xbc\x03\x01+\x02\x890\x8c\xfbT\x12qs\xe8\x15\x80\xea\x95c7\x96\x15\x95\x96\x88\x05\xd4\x97\xe5\x8e\n\xef\xd8\x94\xb9\x85#K\x98}\x17\xc6!E\xe4:\x02\x87\x93?,~\x99$\x11\x0b\xe2zSG\xe0\xe4\xe9\x96!Y\\\x04QF\x7f9\xfa\xb8\x0b:,\xf5\xa5hw}\xc9\xae\x1e5\xc51,8\x02F\x1e\x18vQ\x87h\xd1\xc2\xc5-&\x0c\xa4[+U\xa5\xc8\x9c\x0fX9\xf1:w\x04MF\x87UgR\xb9ht\xa5\x12\xfa\xd2\xd8\xca_\x89\x0e\xd8\xa2\x18%bD\xba\xe6H\x96\x03<\xb3\xa9\x7f\xe4\xf8B\x99b'\xf6d>\xa6%,qM=\xe3\x83\xcc1\x1c\xa8\x88$\\\xbd\xdbrvL\xd9\xf29GZ\x10+Z\xc0\x13\xd8r\x1e\xb4h2\xe1S\xaa\xe1EC\xa6\x879\xa5$n\xc9\x16\x11\xba\x19\xe6\xb7\xedU\xd3A\xca\x87\xafm\xf9\x12\xf8\xbcQ\x08Skp\x05\x13\x98\xab\xf9\xaea\x02W4\xdf%\xcds O\xe0\x8a\xcfs\xe9\xc1\x8c\xd3\xa4\x15\xf4p8\xf3\xe9\xf2\x9c\xf3\x1b^`-\xd4\xb0\xde\x04\x9a.V`\x08+\xbep\x91^\xdeLp\x88r\x97{\xe4\xdd\xb5W\xaf\x8bj\x02gf\xedDL\xc7o.v\xa1\x8f<\x024\x995\xbe<\xba\x04\x86\x88_\xa1-\xea\xc6\x87\x0f2[\x8fdFJ|,\xb7`\xa8\x9d\x17\"CM\xec\xba\x12)\xf1c \x08\xb5%$\x8fp\xdbW\x8e\x1b#vXn\x94P\xbdN\x8e\x93\xc1:\xb8\xf93\xbb\xcd\x94\xee\xae\xde\x18\x86\xc5\xd1m\x04\xfbU\xb5p\xa6\x84 ^`f\xa8\xb8\xc1m\x93T\xd2443\x15\xaa\xdb\xaf\xb0\x9b\x0d\x8e\xb3\xfe\xd1&\xc0r\xbc\xde m\n}D\xe1\xe9\xb9\x8f\xc86$,\x1b\n\x0c\xf3\xf1\x94\x99\x13\x96K\xf1\xff\x05\x9d\xc1\\\xd3\x7f'T\xe8\x86\xb0\xf1\xa6\"\x00\xdf\xd8\x04\xe0\xb3\xaa\x00|c\x11\x80\xcfp\x8c\xb9^tm\xa5\x1c\xbc\x82\x18<:]\xb9\x87\x0f\x10\x1c\xcf\xe0\x08\x07:\x821\x9c\xa8\x9d9+\xc4\xe0\xb3B\x0c>+\xc4\xe03RJ\xd5[\x12\x83\xcf\xa4\x12 G\xc0es\xe8\xf5(\xc2\xda5Y\x9b\xb1\x8f \x86\x91\xe6\xb4\xc7j\x0e\x035CJ\xba\xa2\xcdp\xd9\xaa\xa0\xf2\x8a\xbd\xde\x12\xabn=\xb8\x82'\xe0\xbe\x87 \xdc@\x1f\x96\\B\xa38\xd5\xb7\xba\x04~\xe5\xc3{N\xa2\xc4\x96]a\xf1^\x9bIl\x96\xc4y\x18ow=\xe6\x03\xe1\x0d7\xe4\x00\xf3\x9bo\xc5Ee+\xcc4\xdc\xf8\xf6\xee\xa1\x18'o\x077\x10\x8e\xc0\xe5\xebz\xa5\x86[]\xd6\x1b\x0f\xe3\xa9q\xd2\xf5\xc7\x83\xa1\xc0\x11\xea\xbfR\xf3\xd2T\xf3R\xaby-\x8f,\xd4\xf6\x188H\xa1\xb7\xf4zk\x1cn\xd6\xc4\xe5\x8f}\x90\xb0\xb1\xb6o8oN\xce\x97\xc3\xd3{\x1b\x04\xc1X\xfb^\x9d\x10B\x98\x8c\xf88\x81\xc8\xbd\xf5a\xc3\xdf]\x8b\xe2\xfc\xdd\xa5x'\x8e\xc4W\xeaH\xfc\xd6\xf3 \x98\xde\x9ec(KXMW\x82\x96\xf0\x17\x86\x9bY 4(\xf7\x18\xe5\x98\xdbsO\xbf\xa6\x85r\x06\x1c\xc1\xf1\xf4Xk\xe6\x12\xc6\xb2\x8b\xe9\xb1\x0f\x97\x16\xc5\x8c\xaf\x06\x06\xf5\xea\xf7\x17^\x93\xc1\x8cou\x99\x16\xdeb/D,\xd5.\x12UE\x8c\xa8\xef\xe7\x1f\xec\xbf\x16\nt\xaet\x95\xe5\xc3\x07X\xf2/^\xfd\x93\x0e\xb7\xe5\xdd\xe3;\xb7\x86'\x90\x19v\xce\xfb\xcc}\xe3Hb\xdd9D\x84\xcf\xd9\xa3\ns\x90B\xc5\x1f\xcak\xd69\x93\xc1#K*\x83\xc3\x87#\xaf\xfdtO\xba\x13\xc8\xebpp\x04\x7f\xffH \x0dAB\x8b\x91\xeb\xc7e\x9d2]\xea\x03\xaeF\xd5\x13\x03\x1e\xb6GI\xb4'\x85HE\xa7\xad~p\xa2|\xe2\xb2Z\xfa\xb3\xd6\xc8p\xd69\x8d\x0e-s\xba[M[D\x81\x05\x1f<\xea2U\xc3\x0cJ\xfaT\x7fD:\x94\x12\x16Qt\xfc\xfbG.\xad\x04\xa83\xd9D\x16\xbc\xf01\x0d,\x9a\x10\xe6\xe9\xe3#\x88\x0c\x82L\xec\xce\xf8\x07\xa0\x98\x81>\x84nDA:g6\xbd\x18\x8aU\xcfv[`\xf3\x19\xeb\xfe7{E\xdb\xdf\xc0,I\xde\x87L\x7fs\x9cln\xd3p\xb9\xca\xdd\x99\x07\x07\xc3\xd1A\xff`8\xba\x0b\xaf\x93u\x10\xc3\xd9*\xbf\x8d\xd6A\xdcT\xe1\x1e\x1d\x9e#\x0f\x99\xa3*O\xfcf\xc4\x99H)w\n\xc4\xd3\x0d\x95\xc3?&\xb0u\xe7>d\xed\xa1)M8SI\xe4\x9d\xb14\x0c\xa2\xf0\x17\x93~\\],E\xa0\xc4v\xd7WZ7O}\xf8P\xbdm\x88pY\xa8n\x05d\x86\x16\xc8L0\xa9\x1e\x88\x06\xc3\x0cB\xf2\xfe\xab\xee2\xeep\xd0\x12\xa8R\x81y\x1c\xac\x9b\x1a\x93\x1auX\x8b4A\x07|\x18\x9e\x9b\xfa\xda\xb6\xf6u\x15D-]\xe1uu\xe8\x813q\xa0\x07\xdbz\x8f\xc2R\x06)W\xb5\x9f-\xadW<#(\xca@\xdft\x18\x8b\xc7\xd4\xd9\x8b\xe0\x85\x1b\x99\" \x89\xaa\xd9\n\x831 \x0dxA&\x00\x03\x14g(\x98?\x86\x1f\x83\x9b\xfe\xb3%\xc3\xc1\xff\x18\xe4\xab\xc1\"J\x92\xd4\x8d\x9a\xa87\x1e\x87\x0c\xe6\xc9:\x08\x8d=\xe8o\xb0\xd7\xe4\x15$'(\xfa\x98\x9cUe\x9b\xea\xd3\xe6\xdd\xe0D\xc1\x8d\xb3C\x87?\x047\x9f\xd3\x9b\x90\xc5v\xe8\xf0sf\xd8\xeaF\xd4\x04\xf4j\xbfu\xa8\xaf\xb5\xd4\x81\xffj2k1L\xc9Y\xebF\xca\xba\x1aP?N\xa9\xab\x04\xfb\x8f\xe1\x9b\xfd\xf2k.\x9a\xed\xff4}\xb7\x1d\x0e\x87\x8f\xf8\xbf\x07\xc3>\xff\xef\x01\xe3\xff>\xa4\x1f\x8b\xc5y\xef\xdf\xf6M\xc7c\xdb\xdf\xeax\xac\x1a\x93\xb9\xfc\xd7'I\xf8\x1dC\xaa\x8b\xfek\xcb\xeb2-\x1c\xc4t\xefk\xd7\xfb\xe6|\x7f\xd9\x16\x8b\\\x1eK\xa0\xbbF\xc9\x9e;\xf4J^\x1ae'\x8d\xf2\xec\xdb4H\xbd\xe3n\xb3,\xb9i\xc8\x1c\xf32+\xb2\x92\xc7c\xbb<\x9eV\xcd\xd3\xb1E\xe4N\xd1U\x00\x1d\x07\xee\xdc\x81\x14m\x97\xf7\x0fG\xe8q\x11C\x0fF\xfa\xc9|\x83X^s\x08\xc1\xca\x16\xc1\x9a\x0e*\x9fbW\x07h\x1c\x12n\x1c\\un0\x1c\xcb\xe3\xcf\xd1\xf0\xe0.|C\xde\x1a8v\x0fz\x90\xf0\x1f\xd8^\x8f\x8e\xf2\xed\xe4'\xa7\xebp\x07w\x87ey(\x84}\xb8\x7f\xb7\xf8\xc7\xf3at\xf0\xd0Z\xc6\x83?\xc2\xfd\xbb\xd62\xe5\xcf!\xfeB\x1f\x84^\xa3\x1bg\xa3\xbd\xban\xf25\x9c\xc6Qh\x89\xbb\x0f1B\x04\xcd\xf4\xe0ny\x84i\xf3$S\xc3\x04R\x9a\x00\xe7\x97\xbc\x03\xfeR\xb5?zt`l\xa0^WTH;\xd8\x0d\xda\xd2O\xea\x90\xb2gw\xf3\xe7@\xc3la\xf9\xedF\xb2J\x91\x86\x0b\x96(\\\xa6z\xfe/\xcb\x19\xb2\xc4\x93\x86[d\xa1\xddAs\x9e\xb4`F\x80V!v\xc3f\x8d\xa9\xc5\x94\xb62\x99L h4\x0d\x83\xd2\xcbCx\x02\\\xbao)\x9c\x90S\xcd\xf0\\\x19\xa7\xc2^\xcf\x0c\xc8p\xbd\n#\xa6\x14'>\x14s\xbb\xd2v\xc7\x81N\xf3x\xe9\x8f\xcc\x19r\xfe`\xdfIK\x8a\x00\xd0\x9d\x04\x85v\xbaS\xbb\xc2\xach\xa3\x8eZz\x8d;\"\xbd\xc1\xd4\x99\xfet\xee\x9c\x97\xcd\x07d;\xe0\xa2l\xcd\x9e\xa3\xda\x12\xa4\xbd\xed\x92\xf0\x0ea\x81\xb0\x1a!%\x1bd\xc96\x9d\xd9\"Fx\xbe,\x18\xca\x82\xe48\x98\x0efI<\x0bD\x10Gv\x0d\xaf\xd9\xf2\xe4f\xe3\xa6\"\xe0\xcf\x07\xc7\xab\x99]\xc1H\xba\xd8`\x11\xc6\xf3\xe3U\x90\x9e\xc6sv\xd3fB\x93\x0f\x87\xd1\\\x87\x0f\x85\x89\xfd\x86\xb3\xa22\xceZ.>\x95,i\x89\xeb\xf9\x02E\x0b\xd7\x98X\xa2\x1c\xda\x1c\xdcx\x10\x05YN\xc3\x7f\n\xb9\xf7\xd8\xe38\xd0\xb8]\x86\xfc\xcc\xbeX\x8aoos\xb6\xd3R\xc8\xd9\xf0\xd5\xc0\x1b\xb4\xb4 \xe4\x95\x858\x83\xf5q&\xe6x\x8b\xc4\xc5\x9fu\xbe\x1a*\x17\x87n\xa6\xebc\xa6j\xf6\x0d\xe0\xd2\x0c\x9e\x88\xc6\xc6\xbd\xb3EY.\xe4\x1b\xe5\x98\xc9\x85\x8d\xea\x89\x88\xfe$\xe8t\x84\xfb\xd4\x92~KQ\xc6\x84\xeb\x8c\x94)?\x99\x0e\x8dq6tyg\x97\xd5j\xbd)\xa3?r\\Hc\n\xdc\x92(\xe8#\xb50\xee%\x7f>\xb6\xedA\x8a\x06W\xd9\x8b\xf1^\x0c\xd8D\xbc\x96\xa5$\xa9\xf2\xc9\x84\xbcA\x92B\xb4+\xcd\x89\x8f\x15}?\x87\x9e\xafdN\xe95\xca<\xa7\xd0=\xa8\x07\xee\xa2Q\xe0\x10\xde$\x9c\xf4\xbdJ\xc2\xb8\xc5\xe6!\x9f.\xb6\x0f\\\xdb\x99lW\xae\xb1\xc6=DjIU\xc4\x13\xd6\x12\xa1~j\xef\x1b\xa7o\xe1\xfajBo\x84\x85\xe8\x8bM\xac?\xb9\xcf\xd7\xf2\xf9w\xdf\x9d\x1b_\xeek\xbb\xfeQ\x1c\x16t=\x13\xf8\xba\xdf\xef\xbf\x8b1\x00\x96\xb3\xca\xf3M6\xde\xdf\xdf\xb0\x1c\xf3\xdd\x0f\xb2\xeb`\xb9d\xe9 L\xf6\xaf\x0e\xf6\xe5\xaf\x9f\xb3$v\xde\xc5\xf3d}\x11\xce\xc7\xe0|%>\xf4\xb7\xa1\xf3\x8e\x0e\xc1\x82\xd2>\xab\xa60\xf2\xc15-\x07\xf4a\xe6\xc1>$\x1dg\xa5?ie{\xb4\xa3\xc0\x0cz\x10\xc17d\xee\x1d\xdc\x83#8\xc08\x0e\xdf`$&\xfe\xbf{\x17\xfa\xf4\xd2C\x95\xd2\xa6\xe0\xd8\x9e\x02Py\x17#\x0e\xac\x08\\\xdf3t\xef\xf5\xf0\x00\xf2 \x10`\x0f\x88L\xd37.\xb1\xa0\x0b\x90\xbe\xd2\x81\x0f\x8f\x1eiPo\xc7\xce\xea\xf3\xd1\x87G\x1d\x8b\x7ft\x9b\xcb\xd9/%5\x90\x84h\x07S\x85|2wK\xf1\x9e\x8dG4\xf2\xb1\x84\xb4\x93\x8c\xc8N\xa4X\xbe\xdd\x8c\xbb[\xbb\xa1h\xd4\x1571\x91*y\xeap\x8c\x8fU|B\x87\xe6\xdcS\xc6\x9d\xdck\x8a\x1d)\x1f\xe1`\xf4|\x9b\x8a\x00\x90q;\xb8\xb3\xf9\x92\xbd\\,2\x96\x9bBz\xeb\xcf'\xed[\x9e\x8c\xc1\x92\xab\x80>\xff\xd7\xb8\x89\xd6\x85q\x9e\xfc%d\xd7\xe5u6]\x9c\xad>\x92Wc\x9c\xf0o\x93m<\x0f\xe3\xe5q\x14\xb28\x7f\xcdf\xb9\xeb\x0dV\x88'\xed+\x14H\x8a\xae\xf8Z\x0f\xc2\xf6j3YM\xe2j{\x95\xc5N\xbcc\xc3Q\x02zm\xa1n0\x05\xf2\x13Xp\x88\n\x91^<\x85\x19\x1cQ\xbc\x01Z\xc91\x04\xe2\xc3\x06\x8e s\x03N/\xf9\x9b\xa2\x00\xb1\xd2\x06\xccn\x80\x81\x19\x8bs\x96\xd6\xb60\xed\xb0\x8b\x99\xdb$]\x94I\xe1>\x1c@\x8f\xa3\x0b\xc7\xaa\x96]\xe7\x85=OL\xefS\xe6\x94\xe5\xc9f\x0c\x81\xbd\xc0:\xb9\n\xe3e\xc7\x0c\xfcP\xd0\x86\xbd\xbd\xfa!\x90|\x1a\xc6\xc3\x81f,\x80\xa7\xb1\x14.\xdfX[Jca\x833N\xbdUN\xb3\xa4\x14?\x90\x7f\x9cDl]s \x04\xc1G[\x17C,\x82\xd0E\x88\x9f\xfd\x17\x1a\x91\xc5\x8f7\xc9\xa6\xcb\xd0\xd0j\xef\x9a\xfb\xa0x\xd7j\xe0\xd4n\x18/\xc5\xc8yo\xea#/k^N\xa4\\\xddd\xe5\xd2l\xde$\x1c\x92wL]\x81\x9bkIN\xa9P\xa0#\xac\x95\x978\x8cc\x96\n\x89\x01\x97y\x86\xc8Bov\x1c\xa3\x00\xadn\x8b\"\xf5T+\xa2\xe6\xc9\x86\x93 \x14\xde\xe2A\x82,\xca\xb4\xfb`\x06W\x83\xb75\x06%\x0drv\x86\x1bQ\x8b\xeah\xa3G\xd2N\xd5\x08N\x96D2e(i \xcb\xaf \x9c\x03\xef\x8ek\xff_\xbb\xed>k@'h\xec\xe8S`M\xc9\xe7\xac\x04^~' \xdc\x15S>\x0d\nw\x86/\x01/\x7f\xa8\xbct\x82\xf9\xfc\xe4\x8a\xc5\xf9\x0fa\x96\xb3Xd\x0c*L.{b\xcaq\xf2\xff\xb2\x98\xcc/\xf8\x9a\xb9%\x9ac\xbc'&E\x1ag\x15fy\x92\xdeV\xad9\x9bm\xb6:\xcb\x83\x9c\xcc<\xa2\x90y\x9d\xb8L\x13\x92 \x08\xe1\xe05\xe3\x85Qj\xd4+\xd7%\x0b\xcaT*>\x0fj\x95\xf9\xe8\x82m\x9e8\x9e\xda\xdc\xea\x82\xb8N\x94\x04s\xc7o\x87 \xeakWE\xb1ql\xeb \xde\x06\x91%\x86=Wq\x1a\x86\xbdI6\x19\xaen\x9b\xe7\xb5|\x18\x86\xe8&K\xdc/,\x16\xdc\x8cRH\x15\x9f\x12T\xf1\xc4\x8bAQ\xce\x06\xf7\xb0\x87\x97\xf3\xc40e\xb0\xf7\xc1*\xc8\x10\x92v].iUL\x06\xa8\xd0\xb8\xde\xa0\xd0\x08\x9aO\x0dZ\xedC\xd2h\xa7 {\xc9\xa4x\xf0\xed\xed\xe9\xdc\xadM!e\x0b\x99\xc1\xef+\xc7\x9b\x8e\x9a\xf2\x05\x83t\x8ek\x1b\x05\xd4\x0c\x05$L&\x850\x99s\x1e\xc3:\x88\xdc \xe4\x98D\x08\xe9\x9c5\xb5+\xf4Cx2\x81\x14\xc8 \x1d\xd0\xff\xdc \x124\xa8\xa8\xd0\xac}\xd9\xa1\xd9D\xb6\xf6L\xae\xebW2\x8aO\xe1\x86\xe5\xb8?}x\xf7.\xf34J\xe5\xbe{\x97}\xf87\xcf\xe4\xc2i\xc5\x9aY\x14\xce\xdewB\x99\xd2\xb1!\x1b\xe4A\xbad\xf9c:\x89q\x9e9\"\xd8L\x1e,_\x04k\xf6\xd8\x13G\x9f\x9b eq\xfe\"\x997$\n\xdfs\xf7\x90\xb1\x8c(\xe0\xd7\xe0z\x15\xceV\xa4&`\x1a\xc8?\xb3[\xfa\xb5fy\xa0~\xcc\xf24R?\x82\x88\x97j\x8c\xfd\x82\x16\xc86h\x94\x90\xa8\xa8\x94\xa2\x10\xf5\x08d\xe52G\x95\xdf\xe3\x9a\x91\xbc\xfa\xc4\x1a5\xd1\x80\xb6\xb9R{\xca?\xd0\x88\xac\xb8\x96\x82\\\xc7\x8d\xeb\xe7k\xd5\xa7\x94\x02pW\x90\x06\xdd\xc5\x0b\xb3\x18\xe4y\x1a^ns\xe6:\x9cv8\"\x85A3\xd9\x12\xc6\xfe\xe2\xce\xf6W\x0e\xf9\xb7n\xc9C:\x1f\xcc\xa2 \xcb8\x90\xb5\x86\xfa\x91\x06\xdf\x06\xb7w\xf9D\x0d\x840-\xdcZ\xdcQ\x9b\x89\x10\x8fW\xber\xc4\xd1j\x87\xbdB\x0c\x88\xe4\xd1J;\xb9\xca$\xac\x10q\x8c>\x95.\x01egJ\x19'\x08\xcf\xc94\xd5\x06}W\xe2\xcac'\xd6\xa5?\x15^\x02\x93\x16c\x164\xab\xd3\xf2Y\xec\xcc\x19\xa9\x16]\xff,3\x9c\x0c\xfa\xb0@/\xeb;\"x\xd9N\xb3\x94(\xa7\xa4<\xf7\xef\\\xdet\x8c>^\xfa\xf3\x11C\xbb\xa2\x94\x91\xf9\"\x83\xf4\xac\xc1\xe8af'\x16V\xf2\x07{!\xe9\x07\xa7^~t\xcb\xdea\x18\x9e\xd1\x18J-\xc5[\xad\xc1f\x13\xdd\x92\xa7 \x8c9\xac\x7f\xf8\x00\xae~\xa2\x1c\x9a\x0f\xa0;\xdd\xc9\x13\xc1\x1b\xe9\x94\xb2\xc8\xc9\xe7\x83sq\xc1\xb2\x1f\x93\xf96\xe2\x92^y_0}\xdbX\xcf\xc8\xa0\xeb\x99\x926m\xdc\xd8\xbd\xeb\x19\x02\xa8\xf0\x0f\x07\xd5\x0f\xa1\xf8pX\xfd\x10\x88\x0f\xf7\xaa\x1f\xb6\xe2\xc3\xfd\xea\x07L\xf6\xe0\x0e+o#,^MJ\x85'G\xbc\x15\x94&\xf1\x0f\xb2\x88\xb9\x87\x0f\x1fT\x1b^P\x94\x17\xcft1\xd3\x90\xf4Y?\x83f\x83b=E\x9c\xd5:\xac\xcb\x9b\xb1-\x97/A,2E\xbdX\xb1h\xc3\xd2l\x90lN\xe7\xe5\xe1\xb6;\x02\xaa\xd1\x0b\x7f:\x0b\xfe\x91\x9c(F\xe7\x89Lj6\xcf:\xa9\x9e\xf1JA\xb5\x92\x9b\x0f..0\xfd\xd9\x05\xc5\\\x1b\xfa\x18\x19R\x16\xf2<\x91#\x11K\x93{g\xe3\xc1D8\xc8\x93\xe52bg\xab\xe4:\xeeJK\xa4\xb0\x1f\x0e6i\xb2i9c\xcc\x85\xd3\xeem\xb2\xcd\x9fa\xdb-\x15b!\xb7-\x9b\x8b\x91\x97\x1cG8$\xd5\xd5\xcd\xab>\xc25;\xc3\x896\x17E\xad\x96s\xae\xd7,K\xa2+6?\xdb^\xe6)k<\x0f\xc53P\xcd?'@;\xf9@$\xc6\xa95\x84!KV\xc9\xb5;u\xd4\x0c2\x87\xec\xd9\xe7>\xec\xd9\x9c\x9a)u\xcfq\x10\xcfXt\xccE\xe2\xae[\x869j\x04\xbdo\xde\xae\xf4\xf64\x7f\xb9\xcdO\xe2\xe02b\xf31\xec\x85B\xa7\xac|\xb1\xb6b\xc8H\x03\xc5\xd8\xdf\xa4\x1c\x10v\x1a\xfb'\x80[\xb6a\xb3\x1d\x80m\x13\x98b\x8a\xea\x0fA\x1be,j\x10\x0c\x7f\xcbU\xe60\x84.\x1b\x7f!\xbf$F\xc9\xc11\x87ejs\xab\xa3M8\xb9a\xb3m\xde)q\"\xec2-F\xed\x9e\xc6\xaf\xd2d\x99\xb2,\x1b7&\xf2n\x18c\x1d\xfb\xba\x0e\xf6\x13\xa1\xe5\x8cEl\x96'\xe9\xaf\x00/]\x08\x13\x1f\xc2\xab _\xd9aK\xdd\x07\xc0\xac\xf6\x1b6\xab\x12\x15.\x9b\xfd\xe9\xcc\xf5\xe8\x12\xb1\xa9\xc4\xd4\xe1\x03Wt\xa6a\xf9\xcdt\xebW\xde\x82_\x0da\x7f\x85\x0d\xb0\x10\xf6\xf2\x1eX\nu\xdf\x06R\xd1\x9b\xb2\x00\xd6 \xc9\xc8>[\x13zZr\x8a\xfb\xa6;\x97\xb57\xca\x11\xc1\x87\xad&\x85\xf8\xc2\x07\x81OA\x7f;5\xcf\xe3=\xbb\x1d\x83\xb3\x0e6Hb\xde$\\\x8c\xce\x1c\xf34\x84\xe8\xdc\xd9]B\x1aJ\xf2A\xb2i\x07\x98\\\xc8)\x1d\x89A\"\xc4\xb4\x9c\xdc\x1d\xe3E\xb8\xcc\xbc\xb63w\n&?Of'7\x9b \xce\xc2\xa4\x834\xc2\x85G\xb6\xf9!\x8c\xdf\x87q\x8bX\xb4\xa5\xe2a\xb6\x89\x82\xdb\x97]\xa5\xa3L\xaf%R\xd9I\xff\x8f\xe6\x9a\x11\xa9\xb6\xdb\x0d\xd7\xa6\x10\xc6\xd7a\xfe#\xa2]\xcb\xeaa'OO\x16\x83\x1f\x83M\xab\xd2\xfe\xb3\xd0\xf4\x17x\x13\xfcOg^\x0b\x8b\x03T4\xc6p\xda\xdc,\x7f\xf2`\xd9\xe9\x86\x05\xa7\xdfV\xef]\xfd\xc9\xa4\xee\x91[\x14-\xfa.\xf4,\xc7\xc2\xdd\xf4g\xce6)\x9b\x059\x17\xf1OI\xf3-^9B]3\xf6\xa5\x15\xa3\xee\x9a\xccS\xf2!\x0e4\x86\xa4\xbdh\xa1\xa7t\xb8JQ\xd6UZTi\xa8\xaa\x8a-j\x19\x96\xaf\xdb \xc4\x82u\xb7X\xb4\xf7R\xd2/;\\\xf0SzU\x8b.\ne\x15\xaaE\xf6\x80\xbaN\xd9B\xf2AW\x81Z\xf4O\xb0\xe8\xc6-\xda(4\xe8\xc7-B\x12X\xd5\xfd\x16\xce\x0ff\x89\x96\x04b<\xd2\xa9}mo\xb0f\xd6\xd5\x9a\xebzB\x04P\xf7_\xd7\x1fa-\x89\xa4\x89V\xb8\xb5\x0b\x8f\"\xf7\xc7\xb6\xabb\n\x9c\xc7\xf0s\xf3\x8c\nm\xba\xcdh\xdf\x11<\xba\x82\xb4v\xb6-\x96P{\xd3\\\xb5tR)*\x97\xde\xb5U\xd7\x0eiUu\xed][uqD\xa7\xaa\x8a\xdf\xcd\xd5\xa4<5\x86\xcb\xf6\x82\x82\x95\x8f\xe1\xba\xbd\xac\xe2\xe3c\xb8h\x19y!$\x8c\xe1e{Y\xad\xe5W\xcd\xa5K\xf2\xd0\x18\x8e\xbb\x94\xd6Z?k.\xaf Och\xd9\x9d\x92\xe44\x86g\xcd\xa5u\xc1r\x0c'\x1d\n\xa3T9\x86\x9b\xe6\xa2\x8bx\x0co\xac%l\x87\xab\xb5\xb7\x1f\xcf=\xbfrO\xe4\xa3\x9b\x0d^mSfJ1\xb9\x92\xe4\x02-\x1d\xb5\xb3\xa9\x12s\xda\xab84\x16t\x00\xdd\xc7J\xdf*\xbc\xa4Z\xd5\xc4\x0c\xaa\xb2\x84\x8d\xf2k\xc6\x05\xcc\x15#&\x00\x13\xa0\\\x14\xbf7\xc7\xaf\xc8\xe6\xf8\x15\xd9\x1c\xbf\"\x9b\xe3Wds\xfc\x8al\x8e_\xfc\xc3Pw\x1a\x8a\xc8\xb9\xcb\x92k\xfa\xb7\xf6\xd9\x9a5\xfadi\xfeX&k\x8cv\\ip\xc7\xf2?\xd9\xe5Jx\x18bq\x992\xa7\x9a\xd6\xc8\xe8\xd4\xf8\x19\x07\xa7d\xa0Z\xb2\xfc\x07$t\x06)\xbe\xab}j\x17\xdbT\xbe\x83\xaa\x1c\x9b\x14\xdf\xc1l\x9b\xa6\\\xbch\x10t\xd1>\xe9\xc6\x98T\xbc\xd1y\x0d\xef\xe8\xb6\xceO\xab\x90Yd\x1dg5r\xa4O\xeb\xd7\xf0\"\x11\xdc\x03D\xf0\x19\xbcS\xe0|\x8d\xe7\xf5_;\xf0ug\xd2Z\x86\x00\x93@\xd5bg\xfc\xa4=T@a\xb3\xe6\xb6\xac\x06\xa3\xa50\\\xfb(\xcf\xa7\xcc88\xd3\x90\xed\x99\x18\x87Nwg>\xccj|\x84Z\xff\x171\x16\xcf\xfftb\x8c \x8b(\x15\xfa\xd5|a\xb0\x8b\xd3\xac\xba\xf0\xc3WL\x91_\x15_?\x82 \xe5 u3\x8fr\xe8\x0f\x1f\xc3\x0c\x9e@\xf6\x18f\xbd\x9e\x07\xd1tv\xae\xd7\x9c\xce\x0ca\x01\xc5R\xc6x\xe1\xd1\xe6\x9c\x8b\x18\xd8\xca-fA\x14 \x96\xc1|\x98\xf2\xba\xe72\xf4b\x84IZ\xc3\xc1,J\xb2N\xeeV\xc2\xc5J\xb7\xfd\xa11\xfc9G\x85\x10\x7f\xbbU\xffz 4\xc3\x8bZ5\xa6\xc77\xe3\xb7\xe0\\_\x96\xe4ub[\x1d\x0d\x9eqwcj\xba\x03;\xa4\xd3\x15\x96\xa6\x1d\x86\x10\xeeb\xf1\x0e\x84\xf1t\xf0\xec\xec\x8d\xbd\x14\xdfm\xed\x04-\x90)m\x1b\xcc`\x98\x0e\x15\xa1)\xd6\xc1\xa9\x81sS\x8aT\x87\xaf]f\xcb\xd0\xd0\xc6\x8a\xe7\xe1U\x8dT\xeb\x8f\xbaV5\x06g\x1e\x06Q\xb2\xecoo\xacWq\xbfH7\x97\xc1\xec\xfd\x1f\xea\xe57Z<9\xa5>^\xcf\xff\x8d\xfaZ\xb1`\xfe)\x9d\xad\x0e\x95\x1c\xe8<\xbb\n\xc2(\xb8\x8c\x18\xea\xfbI\x1a\xfe\"\\\xb8\x9a6\xfbr\x9b\xe7h\xe0\xb5\x0f8\xbf\xdd P\x89\x92\x9d&\x86\xfc\xa0\x8f\xd3k\xa8\x91\xc4\xba\xb9 \xeb\xec\xbc\x02\xd9\xd5\xb2q\xf4\xd7\xe1<_\x8d\xc19\x186\x0cd%\xa2;\xf0R;\x8f`\x9b\xd5e5\xfdY\xa5l1\x06\xe7+\x9c_\xc3 n\xa20~\xff}\xa9\xb0\x05y\x91\xe9~Y\x00\x9c%q\xce\xe2\xdc:\xfbh\x80|\xee\x8c\xfd\xcd\xf5\x06\xeb`S\xcaI\xdex\xfd\xb7\x85~\xce\xda\xcc\xb6\xc8~[\x0e?\x9e\x9d\xbdi=\xf0\x98\x17,\xc1\x1a\xb7D>e\x13X\xcb\x19\x96\xce\"[\x0f\x81*\xa6\xb8\x96\x93\xdb\x92\x91\xaf\xc5\x00\\1{\xd6\xdd\xa1\xe5c\xb3\xb4y\xf8\xd4\xbe}9%\n\xdf\xfeK_\x12\xcf\xbf\xf4\xa5\xff\xc5\xfa\x92\xe0|]4\xa6\xce\x97S\xf2\xeez@\\\xd7/\x06\x1a}|\x93\xa8\x83g\x9bI&\xafim\xe6\xd4\x15\xffR\xda\xccO,\x80\xac\xac\x8dy\xa4\x8b(\xd9\xedU\xb2\xd9n\x1c4,6+u{{\xbb)>\x89\xa8\x13\x14\xee\xce\xde \x0b\x7f\xb1D\x13\xf9\x92:\x10\xef\xb2\x7f\x9d\x06\x9b\xcd\xa7\x08\xbc\x1d\xe4U\xad\xb3\x04\x8e\xc0\xb9\xccc%\x113\x88\x92\xd9{6w`\\\xfd\xb0\x8d\xc5\xa7\xae\xf2\xaa\xf8\xb5\xf3\x14\xb2M\x10kR\xbb\x1c@\xa3\x98\xfe\xcf\"\xe5\xe2\x82\x7f\xa5\xad\xf1W\x1d\x96U\x13|\x1b\xea\x9bG\x8c\xf4\x14\xddkm#\x8f\x85u\xf8_\x92\x0d\xfcK\xb2\x81\x7fI6\xbf\xbddc\xbd7\xc0\x06Y\x9el8\xd4\x07\xcb\x80\xf8\xb0\x99\xff\xc8\xcb\x05\xd2z,:\xb1\x88&\xe8lop\xa9\xff\x9f(\x8e\x94\x1c\xd5?\x8dy\xef\xc6R9\n\x96\x85\x94\x8b\x0b\xceH5\x9am\xf8\xda\x81\x0b8A\x1a\x06\xfd(\xb8d\x91c\xea\x06h\x9c\xd6\x8e\xe4\xf7\x0e]}!>\xfeO\xc2\x93\xd9g\xf2\xe4\x86\xfa\xe6\x11\xff/\xb4\"\xcc8K\xad\xf1\xd4D|\xa9q\xe1PV11\xdb\x99\x89\x0bo\xc5\x87\x1a\x17\xce\xc4\x87\x1a\x17\x8e\xc4\x87\x12\x17\x9e\xc9\xc8G3\x11\xf9\xc8\xc4\x8fg\xbf=?^t\xe5\xc7\xb6\xb0EU*l\xe5\xb9W\"\xafz\x95\x98[}g\x92:\x0fl W$\x16+\x18$1\xa7\xcd\xc7\xab ^\xb6g0\x02\x8d\xcf\xb1A\x1c\xac-\xbaXP\\[\xab\xb0\xe8\xbf\x7fDL`&\xf4\xe3\xfc.\xc3\xbb\xee|H\x9d\x06S\x0fb\xc7\x1b\xa9\x1f\xdf*\x15\xca\x0d\xc8\xe3\xd7\xd2}\x94,M\x91tv\xe8\xbfY8\x08\xda\x14t\x8a\xab\xd0\xc9@B\xc1\x154\x93H\xcd\xe6\xdd\x1a\x80U@\x819\xa25 \x1d\x19\xe4 \xc9w\x96\x99\xc5b\xcd\\s:\xd3\xa0~\xec\xbe\xc3b\x9a7\xb3\xe3Y|P\x84\xfa\xe0\xbf,8\x0ee\xd9)3\xcaN\xc1?@vj6\xe2t1\xf6\xc4U\x00i\x83\xa5\xee\x87\xeeyW\x1bR\x88\x85\xbb\x9d\xd0\x07t\xd2\xcd\x91\xff4g\xeb\xa6\xabH[*Jy\xe0\xda\x8cO\x19\x15\xfe\x96d\xc8\x96\xa3\xf6\xa4do\xb2\x97\xa5\xc0\x19\x8b0\xcaY\xfaIH\xb7\xb77\xc3k?\x96(\xea\x80\xd8g\xef\x7fc\xee\xbfc\xe7r\xe5D\xd4]\xbc~\x94\xdfnXC\x8c\xd8\xa6\xc1\xcc\xbf\xcc`&;\x0c\xa6Q\x8f\xb0\xdd\xbf\xd8\xdd\x088K\xe2<\x08\x9b\x0e\xd9\xf7\xf66h\x95\xe4b\x87\xb5\xdfE\x92\xae\x1b;Nb\x8a\xf2\"o\xa5(6h\xebvS\xa6\xf6mI\x97Z\x16&\xe8t\xc2\xd9v\xba7[\xb1u\xd0z`\x18\xe3\xf2\xb6\xb4\xb5\xd3\xe9\xa6.\xc3\x8c\x81\x95d\x9a\xe6\x9a\x81vy\xad\xe5\xdeK\xf9\x08\xf5\x13\x8e.\x0bN\xea\x7fA\x00\xbd\xcc\xe3VK\xb5\x00P\x8e^\x0b\xfa\xf3\xc8:\x82\xack\xef\\e\xa6\xa3yi\xa3\xee\xac\xcdjR\x96m\xc8\xce\x0fX\xc6\xf1`\xfciC\x15\x1e!\x84H\x1d=B\xeaS*\x00\xc4\xba\xb8e\xeb\xf8'\x8d\xb5e\x0c|\x8b\xe7I\xdc\xe4\x97\xb1\x83\x97\x8as\x8cn\x1bh\n\x9bs\xa25o\x03 \x01\x94t\x18\xf0E 7\x9b%\x1b\xd6\x9f\xb3E\x83/\x87\xa5\x9bMq,q\xc6[\xc9 H\x19l36\x87<\x81e\x1a\xc49\x041\x04\x9bM\x14\x8a\x80\xd3\xf3p\xb1`)\x8bs\x88\xd8\x15\x8b2H\x16\x10\xccf,\xcbx\x95y\x90\x07\x90\xc4p\xc9VA\xb4\xe0\xdf\xf2\x15\x03\x16\xcfy\xa3\xe9\x00N\x82\xd9\n\x9e\xbd:\x85up\x0bs6\x8bx\x7fI\xcc Ia\x9d\xa4\x0cp2\xd9\xa0i\xf7\xf5Q\xf3\xa6R\xf6\xb7m\x98\xb2\x0c\xbbZ$Q\x94\\\x87\xf1R\xb6\x04Dg\x80b\xe1'1\xcb\xe06\xd9\xc25\x9f\x9a\x9ac\x9e\xc0\x19\xa5\xd1\x85\xb7\xa7\x03\x07\xe3\x03\xef\xc6\x81?\x8d\xfb~\xac\xbb\xd64J<\x9f\xcb\x91A2\x9f\x06%\xc5\xbe\xf0\xdb\xb6\xa6w`\x00\x92\xbd\xb5\x05\x8dA\x10oR\xa9\xda\x19\x04\xa7z\x9ft] \xeal\xa3\xa2\xe4b\xbf7\x1b\xd5\xef\xf2<\xc8\xa7?,\x96\xa8\x7f\xb6\x93\xa1\xffy\x17\xb6\xbe\xa8\xda\xdd\xa6T\x8b\xd0\xaaH\x0b\x9aUo2\x905\xeb\xdc\xbb9\xbaw\x93kC\xe5\xe3\xd1\x16\x1a(\xd8\xc1}^h\xdc\xc1&\xfc3\xbb\xe5\xc3hR\xa4#*|\x19d\xe1\xac\xad\xecL9\xd17+\xdb\xb9\xce\x9a\xcc\xda_v\x1db\x06\x93E\x13C\x9a\x05\x19\x031\x0fgl-\x06bh\xb6\x83\x8dV\xce\x02\x1d\xb5&\xe8\xae9AW\xed j\xfaJ\x87\xc8\x1c:+\xec\x10\xf9c'\x0d\x0dHF\x15\x1a\x9a=\x8d&4\xe8\xf6\xf2\xb9LY`9V\x05\xb5\xbf\x08z\x9f\xb1\xbd\xd1\xbf\xb6\xf7\xf7\xb9\xbd\x92U~\xf2\xcev\x928A\xedn\xf3\\|p\xde\xc6\xef\xe3\xe4:Vas4'nTB\xc1\xf1a\xd1\xf5v+t8\x0bo\x1b?\x8d\x1bz\xe0\xf4\x7f\xde\xae7V\x15\xcb\x90h\xe6\x7f\xf8 \xe8\xefR\xba\xfc\x97L\xf9\xbfD\xa6\xe4\x82V\xd2@HU\x1c\x00\xd7A;E\x93\xd0\x14\x17e\xd7,\xcb\x82%k*\x9d\x16\xa5\xb3d\x9b\xce\xac\x02\xd4\xe7\x92\x1e\xdd\xc6\x83\xb3\xb5\x85m\x05\xcc\xd3}\x1b1\x13\xe4\xea\xcfe0{\xbfL\x93m\xd4)\xd5\xe7\xfbm\x80\x1e\xf5\x07\x97\xe7\x1f\x16\x98\xbay\xa7\xa1t#\xaa\xc9\x95\x16t\x7f\xea;w\x8a\xd4\x10\x9c\xe0\xe14\x1c[z\x9c\xfa\x92\xdbX\xd8\xef\"\x94w\x1b\xdc\x83.(u0\xb2\x81\x12\x95\xba\x99\xc4@\x19\xe6\xda\xf7.\xc44\x8d\xcei\xbc\xd9\xe6m1v\x03*\xfb:\xb9n+\xb9\xa5\x92\xc7I\xa3\xb0\x08*\xff$\x1e\x19\x9fp\xc1\xac\xad\xfc\x8c\xca\xff\x18\xa4\xef\xe7\xc9ukX`\xcaB\xe9\xfc C\x9d\xbe\n\xf2U\x9bO\x0e\x08\x17\x96\\\x04W\x12\xa4\xa9\xb9\xc2\x1c Y\x10E8\x85\xcc\xf5v;\xf0\x92\x8fdo$\x11\xf3%9\x9d;\x1e\x9e\x7f}\xba\xe9\xa2\xdb9W\xcb\x19\xea\xean{\x99Y2g\xaaT\xa2\xe2\x04\xbb\x0e\x07B<\x07t\xfe\xff\xff\x0f\\2pz\x8e\xbd\xa5E\x9b\x11\x84\xa2#OU\x16\x19\xcd\xe7\xce\xf1!9\xb7V\xc6\xb4\xb6\x9bF\x87\x98\xd5}\xc3\xf5\xb2y\xd3\x19j\xd0\xb62\xad\xb7\xf4I\xf7\x19\xcb\xf5\x9a\xb3l\x96\x86\x9b\x1c\xa3^7\xcf\xe5\x93\xc7\xa4\x1f\xfc\n\xbd\xa8\xeb\xd6\x96w\xf5\x8b\x8d\xe24\xde}\x0ca\xfc\xd9#\xa0;\x13j\x14\x88\xeec\x07\xc1\xa4\xc1\xf1\xa04\x18\x07\xbe\xc1\x07\x1a\x9dB\xb6mC \xdb\xc0Dx\x8ep\xe5\xabE\xcd*L\x9e\xf2\x92\x06\xfel\x82%\xcf\x87yS\x98\x8a\xae\xde\x83\x9f\xe4g\"\x1fT\xcd[\x0f\xb2\xa1\xfd\xe4\x1d\xc0\xea\xefD\x9f:\x0b\x1a\xa6\x80\xa9\xa6\xc3\xec\xf2\x907m\x97\xd3u\xc1\xa2N\xbbK\xbb\xa67e\xdd\x85+\x91\xfa\x8e\x15\x97\xbcZN\xe3\xc8[6\x0f\xd2%\xcbi\xe3\xede\xe5\xdd\xb7\x8a\xbf<#\x91\xbcmg\x85\xc0ega6\xf6\xc5\no\xfd\x10\xd3L\x87\xadz\xfc\xbf|\n\x8a\xe7\x93\xac\xbe\xffd>\x05\xb0\x9bN\xde\xe9f)\x88\x9e\x7f\x83\xc4\xdc\x0b*\x186\x8cb\xdb%|\x05\xdf\xd1m\xab\xde\x11a\xa9f\x9d`&\xf3a\x0b\xc1w\xb0\xcdXj\xbfP#v\xbfK\xf6RR\xce\x1b4o\xa9\x9c7\xccS*\xe7p\xd4Bs\xe4\xa8m\x8a<\x7f>r\xf0\xb4\x9a\x19\x7f\xeb\x94\xa8\xffp=\xbf\x8bc\x06\x94\\HZ\x95\x0e\xbaM,\xf5\xfcX\xd3\xf39\xda\xd8\xd6\xbe\xbe\xf0\xffK\xb5\xfdv\xed}\x978\x93\xf0;\xd0\xf6\xa3O\xd3\xf6wS\xdf\x17\xbb\x99\x08\x0c\xda\xbe\"z\xedj\x7f\xf2\xab\xaa\xfduc\xa3\xfetP\xfb[N\xccH#\xb1GH,\xd4~\xe7\xdb \x0bg\xe5\xe8\x88\x8e\xbdj\xab\xce\xdb\xac\xc3\xa7]tx\xfb\xb0\xad:\xbc\xadJ\xd0\xb6\x14\xad6\x89O\xd7\xe1?yLU\xdd\xf5\xad\xe4yR}\xb5V\xac\xa8\xaf\x8e\x0f\x1b\xfc\x9f\xeb\xaf\x0d~e\xcd\xc3\xf9\x82\xfa\xabpC\x9f#q\xa7?[j\x10\xafw$\xde\xfe*\xfa\xf1\x17\xdb\xa8WA\x96]'\xe9|\xe7\x8d\xd2\xed\x0c\xbf\xde>\xed\xbe\xfa\xc16O8g\x8bX\xcew!f\xd7\xfd\x8d\x98c\xb7}\xebXZ@P\xc7\xd2\x9f\xb6\xcb_\xc4\n\xf2Y\xde{\xff$V\x10\xd3\x11yy\xc8\x8b\xdf\xbf\x15$\xd5\xac \xf6R \xda\xf7;\x18I\xd2\x16\x99\x8d\x1c\x9b)\xb5\x176gf\xe0\xc14<\xe7\xb2\x85\xaf\x9b@\x9a\xe4V\x94q\x03\xf3n\xa2\xe5\x84Y\xa3\x0b\x94w\xf5\x9f\xc9\xc7aa\x8d\x1b\xb2\xb0\xf98,l>\x0e\x0b\x9b\x8f\xc3\xc2\xe6\xe3\xb0\xb0\xf98,\xc8\xb2R\xfe\xc0\x05Yw!M,\xfc\x8fGw\x1fxf#\xcb\xe2\xb77\xb2l\xbe\xa4\x91\xe5\xf7\xe6\xf80\xff]:>\x04\x9d\x14\xee\x85*\xd9A\xc3\xe3\xbb8\xe3 B\x17\xf8\xb3\x06\xc5\x07\xa3\x98\x0c\x8a\x04d\xae\xd0\xc8\xed5\xae`Bb\xf7\x86$\\%j\xb5f\x16]Wj\xce\xa2\x90\xc5\xf9\xa9H&\xba\x1a\xc8\xdfm\xed,\x8d\xed\x9c\xb1Y\xca\xf2r[\xf4\xae\xad\xbd\xdbJ{R\xacx\x8379\xb0\xb6\xc8Q\xd8\xbfL\xe6\xb7\xceg\xbb\xa7\x04\x9b\x0d\x9d\xb5\xad\x06\xe2O\xfb\xe0\xbe\x84+\x0b]\xdb\x1c\xc3\xf4\xbc\x01\x14\xc5\xe27\xa6\xdb\xd4W\xb51\xb9favkH\xea(\xd7y\xdc\xb8;\xfan\x8c\xe1\xd6X\xee\x1f\xe0\x8e\xf3\xab\x18\x9b\x9a%\xbd\xaeaU@\x85Vi\xa3?\x00\xbbEV\x81]\xa3\xab\xc0\x8e\x11V@\xb0\xe1\xbc\x83\xcdkKS\xec\x96/\x05\x8a0+\x9d\x8c^\"\xa9I\x07\xa3\xd7\x82Jv0zm\xba\x86y\x01\xe9J\xb2\x83\x85lE\xe5w\xb3\x90]Q\xa5\xae\x16\xb25\x9e\x1b\x84\xd9\xcbgg\x87\xcd%9\x89^\xbb^-\xfe\xe01\xd7c1\xea ^o\xc7\x9f\xcd-\xdd\x16-\x11\xf59N\xd9\x9c\xc5y\x18D\x19\xb5T\\\xa4oi\xea\xff\xb2\xf7\xef\xebm\x1b\xc9\xa28\xfa\xffz\x8a\x12fN\x06\x1c\x93\xb0(\xdf\x99(>\x89-\xef8c\xc7\xde\x96\x9d\xcc\xda\x1ao} \xd0$\x11\x83\x00\x02\x80\x944\x89\xdfe?\xcbz\xb2\xdf\xd7\xd5\xdd\xb8\xf6\x0d\x94l\xcb\x19c\xd6r(\xa0\x80\xbeUW\xd7\xbd\xe6\x98\x04\x06I\xfc\"6/\xeci\x0d\x8eu*I\xc8\xe2\xf9\xd9\x91\xc0\x9f\x14\xfc\x96\xfeSg\x98)\xba\x9d\xb9\x07\xdf\xf7\x0d/\x1e\xa1\x15\xe6Cj\x16\xe5\xc2\x82\xb8t9u\x80W\xc5\xdf;\xbaT\xa7\x9c\xad\x1fG![\xbff\x88\xbf\x08\x040\xf4\x0fsC\xe8;y\\/dK\x1dgT\x9a^\x99\xaf\x94?\x06\x07\xdc\x17\xdfm\xca\xd5\xc1\x18\xe8\xed\x16\x1a\x823\xd2\xb9\xbc\xacL\xca\x02\xbd\x0e\xd57\xe8P\xcb\xba\xca4\xe7Ft\x1e/\xab;\x0d\x9dj\xbd\xf5\xd0g\xa7\xff\xa5J\x9b\xc8\xde8\xd6\xb9\\mM\xc3\x14\xaaU\xd9Zj\x868\x86\xb3\x1d=\xbd\\'Z\xd3\x11F%\xc3\xcc9\xdd\xf8s\xfc\xb9\x1ci\xbf\x99\xf5?\xc9R}\xbcy\xf5l\x80{SRo\xd8\xea\x13o\xf2\x98\xe5F\xa9\x19\xd5~\xef\xea\x9f\x17\xd6\x1d}\x9d\xbe#\xac\x83\xd6\xfds\x1a\xb8\\\xd2\xd7\xab\xcei\x1b\xd4/s3F\x077\x88zm\xc7\xe0<\x89\xd3\xb3\xe13\xca6\x1e\xfa\"\xd6\x93\xb8\x87\x93\xf8\x10!5\x0e\\\x81i\xe7\x1b\x01*=\xb0~\"V\xe5:~\x82AB\x98\x01\xe5\xb4\x92\xb4\xb4\x13\xb2ij\xff\xcf\x068\xaf\xb57pe\xf9\x12;X\xf5\x19\xa3E\xa4\xf4\xe71\x15\x17\xa6\x9a\xf8y@UE\xf1\xaeL3\n\xa8\x1b\xa0r8\x11\xf2u\xa6\xdeDa\x7f>\x0dl\xb7\xb5\xb9\xc2 \xfd\xd2\x9f\xe0'/a\x83@\xfe\xd4JE\xfd\xb1\x11\xb0\xda*Z\x04\xcc\x9aV\x8d!\x08h\xe3=\xf9\xf9b\x9b\xa5\xb1b\x98i\xa3\x8dq\x96/}\x16\x18'\xc6r\x8a\xf94\xb4\x08\x87S6\x14\xd9\xda\xd4\xae\xa9d\xf8|(^\x81r\xafqR\x11 \xdb\xf3\xb9\x0bV\xbd6\xbf\xb8\x1bfiF\x98f\xdc\xbf@?B\xaeoi\xab\xe9\xb48\xf3\x8aA\x02B\xea\xf8\x95\x81=`i=\xb4M\xd7\x0e\x14W\xd9\xf0o\x1b\x92\x1b\xc6\xfc\xbf)\x08d~\xee\xafII\xf2\x02}\xe6)#\xc99E\xd4t\xaa9^|\xdce9\xbf\xfaJ\x8c\x19\xd9'\xc5\x96B\x1e\xd4\xdd;\xa3\x9f@f\xbc\x01'\x14\x8fZ>\xf5\xea\xe9\x0bk\xf642\x1cf\x15\xd8`\x02\xf3g=\xcd\xea\x89\xb3:\xc8,\xd8\xa6\x86\x9fA\x07\xbd\x0c\xda+\x86\xfa\x12\\\x1aB\xde*+\xc4\x87 m\xbd\xfduE{\xe9\xa3\xef\x93\x82YWl\xf6\n\x03\xfd\xb2_\xda\xfb\x85O\xe0n\x18\xcd,.W\xb5\xdfd\xf8\x7fl\xd3\xbdK\xec\x81=$\xfb\xa7\xf8\x8fe:W{-\x01W\xc2\xee\xb4\x92\x98\x9d\x9d\xe3 \xd3\xef\"\xe6\x9e\x0e\xcb^\x0df\xa5\xa1\xd1\x13\x12\xacS:]j\xe2\xa03y\xc1\x8a\x04\xef\xe6\xa9\xa2 \xb8\xb84\xadZEt1\x9cc^\xdfV\xe9\xc3\xe8\xdea9\xa2\x1c\xb8\x01s\xfc%\xba\x8a\xb7\x84\xfb\x8c\xd9PD\xaf0*(i\x08gpf\x06\xe6[\xa9\x9a\x19\xf3\x1b\xf5\xce ^\x9a \x1e\x19\xb6\x05p\xdd\xe4% 54\x89\xb5\xf5|\xed\xba\xd4\"\x9d\x8a\xb9OM\x0c\x8bJ]~\x170M\xc4.H\x8dTp\xe7Q\x9au\x94\xd0iO\xaf\x96\x03\xd6^r9\xbd(t\xdal\xea\xbfMM\x97\xf2\xb2\xd4\x15\x84$\xb5\xef\x18\x8e\xae\xc2\x03R5\xe0\xd0f\xb8\x1f\xcf\x03\xf2\x92\xf87<\xeb=\xb0\x859G\xc9H\xc7'eC\xda\xd6&\x887\x1e\xee\xbd\x0c\xf8\xba\x9e\xdb$\xc0\xff4}\xaf\xde\xd2v\xbf\x91\x15_\xb3\xfa\x97\x1d\x81Ej|\x18\x90\x1e\x1fx\xe7\xab\x14\xf9R(K\xc7\xddz\xcc*\xc7\xdd\xf0\n\x1cw{\xe5\x95\x94\x94\xa3\x94\x94W\"\xbb\x97Wj\xe3\x82i$\xc0GS\xd6n\xc3\xea%\x1b\\\x04\x8b\xe4\xb9\x112\xad\x1dq\xd0\x15O\x0d\x19\x0dq\xc1\xf1\xe1\x10R]\xe2\x92\x8d\x88\xf4\xac\\\x00\x15\x0en^\x10\x13?\xd7\xf8\x1f3\xc7\x82\x19\xe8Y2\xce]\xf9\xfa\x82\x1c\xc2\xd8\xcb\xe0\xe4h\xce\xbd\xb6\x02\x81\xc7#C\xdffU\xa4\xba\x16\x8c\xaf\x94\x96M\xad\x17T\x9b{6`S\xaa\xcd\x7fK\x9b|$\xe06\x8a\x91*\x11\xbc\xc5mZm3\xe1\x1covw\xcf\xd1q\x02\xb9H\x9doj\x8a`\x94\xc1/D\n\x019\x06E\x0bp\xb1\xcc\xf4d\xca==\x18K\xca\xcbJDIH\xce_,\xdctd\xf2\x97\x8b\xa0\xf72\xaf\xa0{\x92\xbe\xd5\xf8uXy\xd1C\xc3crx\x15\x1d qA`/g\x1e\xda\x8a\xf1\xc1\xb7t\n\x18\x84\xb9C\xa23\x9d\xcf\x0dv\xba\xa9\x9c\xc7\xf7\xb4\x89\x84\x94\xf5\x8148\xd8P\x04\\1\x0e\xb6\x91KOY0\xaa\xd5\x14\x9e\xe1\xcbsX\xa4cPE\xdf7\x16\xc9WO\x02\xe3\x98\xacF\xdf?\xe8\xd4\x1e\xe9\x89\xcdy\xc46\xaa\xd5y\xc4\xe6\xd3\xe6_\xfb\xe7\xca\xbf\xbe\xf2\xb2M\xb1r\x9d\x9c\x14Y\x9a\x14\x04\xed\xca\x87\xa8\xd3WP3E\xde|\xd6^ev\x1c\xd2\x1a\xba\x9c\xed\xd4\\\xdf\x95\xf8C\xcca\xcf\xf3y\xc8\xe0\xd8T\xb6^hS0\x87R\xa0d\xe9\xc0\xe1!\x92\xd1t\xc1\xa2X\xc4\xe7*C\xdd!\xaa\xff\x12\xfa\xc17\xaf\x9eV\xb2\x9e\x9bu\x03\xa5(A\xd9b.\x03Vr\xeb\x15 \xa3\x9c\x04\xe5\x9bZ\x9f\xd1\x13\xe8t\x0c+\xfe\xd1\xaf\x9c\xd1[\xf6\x93\x8bS\xa7\x95\x84\xe1\x8b\"9\xa6@\xb09\x8b\xe5\xd4\x19\x89\xba\x06\xa2y\x99Lp\xee \xcd\xe6q\x1a\xbc\xc3\x12\xeey\x1a\x9f\x9e\xceK]\x08c\xdbF\xc4\xff\x92B3\x0b\x11\xf1sI\\\x94\xb1\xde\x89\xa9\xce\xc9\xf5\xcc\xa1\x8aD_\x9a\x03\xe4Z\xd69\x19\xb3\x1f\x07X\x15\xd9\xbd\xf7y\x9c\x05\xd0\xd29\xad\x88\x1f\x92\\b\xf53\xed\x19\xbb\xe0\xc9F\x98\xa1\xa0=\xc0\x9b\xd4\x17\xb2\xce\x1b\xd9\xc1\xbb\x12L{\x81\xcc\xc9N\xea\xd1\x86\\d\xfc(\xc3e\xae\xe9\xa2I\xfb\xe1\x8e\xc1\x81u\xe1\xe8G\x1d\x1aGm8\xf3\xa1M\xa0%Y^\xc6;gr\xb1\xa9\xa7\x06=*\x06W\x9c\xdb\xa1X\xa5\x9b8\xac\x08\xe1\x9b,\xf4K\xdb|\xac6\x15\xcd\xeb$\x0e\x9e\xd0\xf9\xa0tI\xea?\xff\xf8\xa3 E\x0fq\x0e\x81?\xdbO\xd9\xf1\xcd\x9f\xf3?\xda\x10aTd\xb1\x7f\xc11\xeb\xb1P\x7f\xb07\xe4\x0f\xa5c\xf8\xdcR\xb2\x8a\xe9\xd4\xc3\x0eM\xca\x9a\xd6\xf0\x06C=T\xd5\x8e\xe5\x93\xac\x7f\xd3\xafx=\x0b3?T\xcax=\xc7\x07\xfc\xc8\x12\x98\xa2\x87\x0c\x98\xf3\x00\xba\\<\xdfPi8\x14\xe4\xe9!\xf8\xde\xbau\xebI\x9a\xbb\x9b1\x14#\x98\x81\xef\xe5\x9d\x9b\xfa\x86B\xa8\n(S\xa1{cL\xa9\xb0\xa2\xa7+\xcf@$\xd7\x974\xafm\xfd\xf9\xea\x10\xf1\xca\xf4\xc7cSE\x97u\xfdb\x92\x96\x8f\xd3\x00I\x12\x86\x87k\xdf[\xd6\xef\x11\x9b\xf4\x1d\x175<\xfa.\x1a\xc0\xe75x\xe3\x98\xd0\xber\xda\xb7{n-\xd2VlO\x1c\xca\x9f\x92\xa4\x9c`\xe4\xd8[JZ\xb6'\xce#~\x13\xa3\xc24y\x85\x80\xeb\x94\x12\xd7 ,\x16\xea\x9c\x81\x8a\x8d\xfb=\x0b\xcf\xd2\xber\x0c\x87]wm\xa3)\x1c,\x0enk_W\xe8p\xf9\x0c\xc3\xe2\xc8\xe8\xf5%.\xa4\x95z\xa7\\\xe0l=8\x98\xe3\xcc\xc1\x90\xf7\xed y\xcb\xa2\x15\xb5\xef\x9a\x92x<\xa2\xe24\x1e\x06\xc7\\\xe0\x96\x8b\x82`1iMn'\xd0E\xaa\x1c\x99f\x96\xd3\x0fm\xe2\xf6\xd1\x18V\xda\xf4\x06v\xcc\xd7\xed>\xf3\xf5\xe6\xd53-\xdf5\xd4)TD&\xd2-\xa0\x1e\x8f%\xa3\xb7\xd2\xa7Xh\x8e\xe7\x98\xe4[\x92\x83\xd8O\xda1a\xf0\xcc\xc0Q\xb1\xcf\x16\x13\xf6\xeeN#+\xe9~1\xafR\x99\xef\xd85\xb6\x1dw\xec[8\xa8\xd1 \x8d!H\xe3S\xd6d5\xeb\x13z\x8f\x1fk\xban8h$\xd4.\xd1\xd5\xf5\xc7\xca}\x9cv\xea1)\xfd(.\x0cy=J\x8c\xa4\xfdP\xab\xf8\xd1Vo\xe8\x92\x85cX_e(S\xd5\xfe& kfc\xa7\xd1G\x8d\xe0\xba7\x8d\xaf\x81S\xf9\xf8_1\xaa\xed\x84_K\xdd\xf4\xb5\xca\xf7\xb6\n\x8e\xc1\x0d<\x04\xe1\x86\xb8]\x95\x99\xae\x03\x18.4\x9f>7\x0e\x8e183\xb80\xb0\xc8\x0c\x8e\xa5'4\x04\x17m\xf2x\x06\x06\xe6\x9c\xf3\xa7\xda\xcc\x89\xf4j\xca+\xba\x98\xb1\xf7\xf5|<\xd2\xcc\x871\xb4\xb2\xea\xd7\xb1MS\x11=\x96\xe7\x97 k\x10|\xed\x0c\xe6\xe6\x06\xd5\xe1-\x97\xf0\x85\x97\xeb?C\xbc{\xdd\xf4\x9f+\xa5\xfe\x13\x9f\xf4\xb4\x96\x91x\"S\x80\xaed\x9a\xd1\x0d\x7f\xd0\xd3\x8c\x16\xfcA\xaf\x8d\x98?\xe8iF\x03\xfe\xa0\x97\x1dy!\x1a\xdf\x7f\xd0}\x94Q\xf1e%\xb4\xa7h}\xec@\x84\xa2\x83\x8a\x9aU\xab\x8f\xafO\xdd\xda\xda\xd6T\xa9\x94\xa5&*\x99\xfd\xac\x99B\xb9\xb0Q\xbcEm\xc5\x9bE\ne\xac\xd0\\\xc7]\xbc\xc9\xe3!\x96-\x9eU\xb9\xad\xce\x90\xcb\x19\xc2LG\xce`!z\xe9\x12o\x93\xc7.\xe6\xe5\x17;5N\x99\xa3\x00\x95\xe4\x99;\x87+\xd1\x14\xca\xe7*\xe5s\xd5\xd4\xe3\x8c\xdc\x91\xc7\x1d\x8f\xd2\xbc\xe7\xf3\x04`\x9d\xe3\x17\xc9|\x7f\xbaT\xba\x86f\x9b\xb3\xa6\xabd\n\x0f\xc1Y\x95eV\xccn\xdeL\x13*Q\n\xbf\x06/JoV\xef9 \xab\xaa\xd7K\x8a\xab\xb4\xb1\xc5\x0d\\\xa8\x15\xa6m\xcb\x9b\xd2\xc6\x16\x08z\xf9K\x14\xc7\xafH@\xa2-\xd2\xb6\xc2\xc2\xec\xa6\x94\xd3\x85\xe2}\xf8\x12\x81\x88;\xb2p\xac\xc7uB`\xdb\xa5\x02\xddr\x95\x03\x96K\x1eZ'\xf3\xb1o/\xa1\xec\xd4\xbc\"[\xa7\xd8\xa9t\xce\x1b\xba\xe3\xf6\xe4\xd3\xed\xab\x9e\x1a\xb1d\x99W\xf8t.\xffM\xde\xe41\xa3Bu\xb1\x83j\xf2TqF^\xb0\xc9s\x92\x94OXj\x08s\x85\x93-%I{\xcc\xf9\x03\x7f\xbb\x1b,4\x97f\x05\xff\xc6f\x0c\x18\x9f\x88~\x16{Q\xf1\x93\xff\x93\xbbB\xfd\xca\x8a)0\xc4K\x1b\xaf\x88\xa3\x80\xd0M\xb2\xd2U\xc9m\xf9dlzy\xc5|\x13\x9fDw\xc3F \x87\xeb\xa4\xd5:\xea\n\xba@=dU\xbf\xac\x12\x92\xb1\x9d]\xb5\x89\x89\xf5\x0c\xf5\xb5\x00\xb5 \xcb\x17\xf3_\xad\x12\x99\x95\xfeR\x9b-F\\\x9d\xdd\xa7\xcdB\xd3~\xa7\xca[\x93\x9a\xdf\xa8\xf7\x9f6\x8bC\x0b\xdc\xc2& \x8c\xe7\xe8\xae\xbei\xe9\xa1!,\xf0\xe5\xcf|L\xa3m|\x0d*\xb2\xc5\x8d\xc5\xe5*5:\xf1\x89+\xc5@M\x816\xcf\xa2\x82\x9e\x8b\xb4ez\x98&c\xc8u9g\xc4\xc5\xd1\x8f\xc7j\xba%\xaf\xa3\x85\xa5\xad2\x98\xc1bTi \xf3Q\xad\x16\xdc\xb9\xb0\xba\xb8XJ\xd1*3\xa4\x05\x9a\xd0\x8b\x9e\x1e/\xb1\xac\x90\x05\x96\xd0+\xcd\xac\xd0\x1b\xaarE\x169@\x01\x83\xb9\xe9JY\xa17T\xdb\xc7\x08\xaa\x91\x8c\xd8\xe3F>D%d\x13\x8a\"3\xa6\xb5\xfd\x06\xa6\xbaB\xde\xab[\x0d\xaf\x8c\x9fR\xa8\xc9\x17p\x856D \xce\xfe^]8\xe9R\x96mYy\xe6\xcf\xc9\xb2-\xad\xe1\x9b\xaaj\xf8F\xaa\x1a\xbe\xbe\xaa\x86\xefFU\xc3\xb7P\xd5\xf0\x8d{5|Y \xcf\x82K\x05m\xe8@\x04\xcb~\x16%~\x0d\\\xfb\xa7\xe4\xd8\xafi\x88\xe0\x10\xee\x9cq\xe6\x8c\x1bPC%\x02J\x0d\xc2\x8e\xb2`\x15\xc5aN4\x944\x1d\xc6\xa9GC\xb8t\xdf\x9aC\xdf\x0c\x90/\xb0p\xb2\x8e%_\xb0\xc38\x0d\x8e\xce3?)\xb4Q\x14\x19?\xb8I\xf6,J\xdeE\x89fFCQ\x04\xd8Y\xf8qAX\n\xfeL\x0dO\xb9\xf4\x0d\x96\xfd\x8c\xfd\x0c\x1dk\x95\xa0[\x06jSes\xcd@\x1f\xf3\x1e\xeb@\x97\x0c\xd4\x04V\x05\x164\xa1\x1aJ1\x9cb\xab\xb7\x15\xb5r\xc8\xe7yz\xa6\x19\xdcY\x14R\xd2\xe0\x1c\xec\xeb\xbccH\xb4\\\x95\x0cjpo7\x85>\x14\x88\xed\x08\\\xab\xbf\xc4\x14\xcf&\xd8\xe7 r8t\xa9\x9aw5\x9d<\x8f\xa3\xe4\xdd\x0f\x83>\xa6\"6:\xad\xa3\xb6\x86rT\xbc\xc8HB \xf6\x91j\x9er\xa3\xf9@\x92JC'xg\xe2)\x1a\xe6{\xce'BcX\xab\x9d\x16y\xba\xfe\xf1\xd8\xfd\xbd\x1b\xcd\x87\x1a\x0f\xa7\x9e\x94\xf7\xe3k\x97\xd0\xb4/\xd4g*\xa1>S \xf5\x99J\xa8\xcfTB}6,GS\xe6vc\x94\xa9\xe4\xeef:\x97\xf3\x05~\xed^sY\xb96@&\xecg\x1f_\xd8\xd7\x9b\xe9\xbe\x08\xfb\xe2\xfap\xc2\xbeP\xa4\xaa\xe1r\xcbT\x05)\x87\xc3@R\x0dc\xc9\xb4\x07\xe9r\x19\x13d1\xd5\xa0L\x82O\x93\xd79\x15\xf8\xf1\xb8T\x03o8\xf0#? Hl\x00.8\xf0\xd19 6\xba|\xfb\x0b\xa3\xe1.\x1b\xa0<\x08\xadU\x12\xabjq\x8cz\x8e\xed\x10s\xea\x1a\x81\xad2q/+P\x8b\xef^\xb0 \xf5\x8b[\xc6\xef\xce+P\x8b\xef\x9e\xb6\xdd\xce*\xc6J\xc3z`\xb8\xbd)w\x02\x15\x9f\xcf\xbc\x90d9 \xfcRW=\xe0\x1c!\xb98\xa4\x06;F0}n\x8bG\x08c\xcak\xf1\x0e\xa1R\x8dn\xe7;\x84\xd0*\xe0^\xf0\x8f\xf0\xe9\xd2\x95\x9c|\x89\xa0~\x1c\xa7g\xaf\xf3\x8b\xa7\xe5\x8b\x8d\x06\x83_\xb3y\x1b\x98-\xe49\xeb0\xff\xfa\x11\x13?\xd5\xe0O\x11\x9c\xb0\xbd\xf94y\x99\xa7\xcb\x9c\x14\x1a,\xf9\x15\x0e\xe1\x9d\xd7P\xea\xa8A\x7fB\xd0\xa6\xeeF\x0d\xfb\na1\xdd\xb7,\xa3\xb7\xb8\x1e#\xc6 %Q\x9ai\xb5@\xcf\xe0\x10\x1e3#_\x15\x02\xae\xd3\x8f\xbd\xa9\xe1\xb3<\x0d7\x81\x1e\xfc7\xee\x8f\x8c\xa9G\x9eEE9r\x1f\x8f\xe1\xc4iT\xd5\xd5\xf5\xee \x1c\xc2\xb6F\x9bc\x1c\xba{<\x86G\x9a\x97\xfe\xddQl9c\xf8n\x0c/4\xca\xab\xef\x9b\xbd<:/ \xeaI\x8b\x91\xfbX\xd3\xcc\xcf\xc8\x04\xd9\xcd\xda\x0f\x0c\xb6YKX\x0d\xfc\x0b\x03\xe6\xf8\xa6\x83\xfc\x91A\x06,w\x9d\x1a\xee\xbf\x19\x9c\x8d\xf2\xf5\x1f\x0c\xd4F\xf9\xfa\xbf\x18(\xc7G\x1d\xe4_\x19d\xe5\xd5\xc1\xb2,h_\xf9?\x9dW\x8e\xf4I^\xfe\xd9ma\xb3^\xfb\xb96\x17\xca\xfff\xaf\x98\x14\xc2\x84\xf2/!\xcf\xe9S\xe3\x86\xda\xa5\xf7\x19f\x8fe)d\xd1\xc4\xf9-\xec\x9b\xdc\x95\xd0\x9d~\xef\x19\xee+\x1e\x9a\x97{\xad\xec>,F\x87\x838\x9c{\xd3\xb9p\xe4\xe8\xe0R\xf43\xf1\x8c\xa1$\xb6\x16R\x10\x1e\x04\xb4\x7f't\xdfI\xd2\x84\x02\xd8\xe69\xb1\x12\xe6\x9b\xaa\xdb*\xe7c}2R\xf9\xf6\\\x06\xe2\xc0\x0dx\x047\xc0\x91\xe9x\xdbP\xea\xd5\x8e\xc2\x99F\x03\xfe\xefZ\x01\xaa\xd4\x80\xaa\xa6\xe0\x9fZ-\xb1\xc0[\x94ngp\xaa\xeea\x83S\xd5\xfa\x98\xb4}K4\xa7w\xab\x84\xd3Z\x0f\xd7\xf0\x9f\xd1\x1c\xf6\xb53\x84\xca!W=M\xffm\xa7x8\x1f:\xfdC0\xb0R\x8d\xab\xeb\xe2\xbf\x1f\xc3c\xba!\x1f\xb3-\xfe\xc7\x1f\xcc\xff\xe4\xf0\xf0\x10\x1e\xd7\xce(\xea\\\x13\x06?\xe8J\x15u\xeb \xd3\xd5S\x15z-\x03\x18\xbaU'\xee\xed\xe9TC\xe8d\x13\x10\xa7~\x18%\xcb\x89\x9fDk_c\x1f\x19\x8d\xe1H\x9bX\xc8`%\x91\xb5\x8d\xea\xcd\xd3$\xcd\xd7\xbe\"\x07\x10&x\xfa\xc5\xcf\x93(Y\xce\xe0qM\"Fc\xf8\xd5\"\xcf\xd1\xb0\xfe4\xd89}\xa9\xca\xab\xc6Bcf\x10M\x83\xff\xb01G\xfc\xaaX\xd4\xd1h\x0c?\xd1y\xfc \xc3=/\x91\xb6E6,\xc1\xf3N\xc24(v\x9f\xd1\x0f\x86YO\xa2$\x84u\x9a\x13\x08EF\x9f+^\xd8\xd6\x0c\x0c\x1f\xb91\xd0\xd5\xd8\xe6\xa99\xeb\xcceq\xeb\xa7\xa6\x18\xa4\xc23u\x1b\xff[\xd7\x86}\xb0\xac\xc5L\xc4\x91\xf6\x0bJ\x8b\xd6O\xda\xe8X\xf6\xb4\x91c\xa7yj\xa87\xd4\x0f\xbaa\xd7R\xc4\x0c~\xb3:\x85yA\x10;\xf1\xa3\xe2Ef\xf0X\x03\xc5+x\xff\x03\xdd%uj\xb8\xa6\xbaL\xeb\xaa\xdb\xd2\x95I\xeb]\x89\xab#\xb9\xcf\xe0\xb9\x86mi*\x12f\xf0R\x0d\xb9H\xa4Ev\xc4e\xcdP5\xb4d\xda\xecE-\x15\x996\x7fQ\xe6\x97\xab\xe7\xdc\xb1\x93q\xe1\x86nr\x17\xe4P\xb1\xe1*l|\xae\xc1\xc1\xbf\xeap\xd0z2\x98M\xfeX\x0d \x1cV5Ly\xda\x91\x1bgB\x03Q\x98\xe5H\xda~\xf5\xda\x16\x15b\x85;\x12\xda\x91\xe31T\x1f\xd1\xe9!\x96\x84\xbb\x83\x91\x90}l\x06s\xafh\xdd\xd1\xacs\xff\xe5\x0b\xafw\xd3\xf0>\x05\xf9\xd9\xcf#\x8a\xf0?3\xed;\xffH\xef\x89a\x18Mx6\x8ca_8Z,HPF[\">\x85\x9d\x11\xdf\xa9\x9e\xe2}3\xfe}\xf5\x15\xbc\xa4\xff\xbc\xc2\x7fLtq\xa7cV((T4Z\xd5\xd8\xff\xd2\x9eo\xec\xa33x\xf5aq\xdf\x96\x98\xf0H\x16\xa6!\x9b\xc1\x13\xc5\xcc\xd7S\x7f\x15S\xfc\xbcRu\xbc\xa4\x12\xf9\xbcL&\xcb<\xddd(ys\xfd\x95\x91\xb3{.\xdeW\xf5\xe8\x17+\xc9Y{Z\xd9\xce\xe20\x92|\xd9\xb5\xad\xec=3(\xacvJn\x9a\xaa\x1f\xb5(k9 \xf6C\xd3wz4\x86\xa7W\xb5\x97\x85 \x1aT\xc1dCw\xf3.\xcd)]'\xaaey\xa6\x19\xe0\xcf\xba\xd6*\xb5\xf1\x0c\x9e\xa9g\xbaJ\xea\xab\x89*\x11\xcc\x90(\xfb\xa0\x8d\xfd\xb0>\xb7[l\xc4Ul\x98\x86-N\x9b#\xd2\x1aK\xb9\xf5a\x06o\xcc@\xfc\x90\xda\x8a\x80\xbf\x97\xfc\xfe\x934w\x19C\xa59\xfc\xfb\x8c\xb4\x95\xce\xdf~\x1b\xa9A\xe4\x86\xad\x19\xbcV\xbf\x82\\\xac\x89\x9a\x10\xf4\xa0\xf8\xdet\xdc\xfe\x1f\x1d\x06\x93J\x17>\x83\xef\xad1\xce@2vq\x1bz\xb9\xc9\x89\xcce\xa8\xca|'w\x19j\x9c\x1c8)\xad\x87y\xb5\x99d\xcf\xf8\xa6\xec?\xaaQ\x85J\x8a\x0b\x8fY\xbc\xba>5\xcc6\xa1\xf3B\xfa\x12Z\xd4\x9e1\xa5\x17\xd2B\xee\x85\xb4\xa8\xbd\x90\xee5S\x19-4\xeeF_b\x8b\xfe\x03\xdd\x8d\xac\xfc~\x86\xc4\xfb\xe7\xf6\x0e-\xe9\x10\x87\x16\xe6\xa6\xd4\xb6\x13\xa9\xa1}K_\xaa\x0d\xd6\xd039\xa7\x14,\\\x9d\x91-5X\x80`QQ\x95=\xd5\xf0\x0d\x0b\x845\xb9\x9ed\x08\xa5s= Y\xd7V\xe9\xd9\xb1\xa9{+\xfe1\x0b\x17\x94-\x03\xcd\xa3e\x94\xf8\xf1\x0b\x9bW0\x12I8\xa2X\xbd\xb1\x84C\xc8\xcc\xb3z\x81K\xc4\xd5\x1d\xc1&\x8fJ\xadU{\xce\x12(Tu`\xab\xae|_j\x8d\xf9\xa7\x9d\xc4\x0b|:\x9f\x1b\x03\xbf\xcf\xe4/\xbe4\x04\x9a\xf3\x1a'?n\xd6\xd9\xeb\x14\x811;\xc4\x07\xb7.\xd7Z\x01\xd6O\xe8\xfc\x8d\x06b\x8d\x16\xb0\xae*(\x05\xd1\x08 \xa7\xba\x1e\n^P\xc5\xb9\xa9?{f\xaf\xa6\xd3\x05>v\x0c\xd0\x1a\xc3r\xcd\xe3\xc8\xe3\xc6ig\xc3\xab\x92\xfb\xba\xabcc\xafX\xd2\x83\xad\xa8\x99],\x8a\xedn\xe9\xdd\xd5\xc8\"{\xfen=\xab\x93\\D\x8a\x02\x04\xef\xc7 :Qg\xdc\xff\xea+\xb8\xf0\x82t\x93\x94\xae\xaeos\xbdY\xbc&\xb93\xd0d\xcc\x1a\x1e\xe3!N\xd4\x941\x94\x98\xef\x97JMT\"\x89r\xec[\xe1^\x982\x89 \x81\xae\x13\x06\x17\xae\xc2\x01\x05z\xacEu\xd7\xac\xb8\xd2V\xc8\xc9\xb4\x08{\x85B\x87!N\xa1\xbb\xcfL\"D\xb0\xb3\x08q=\x03\x19>i\xa6\xb2\x01\xc5\xa6?\xa32\xa3_\xc4\x04q\xed.&hK:\x9b\xb8\x8fK\x1d\x1b<\xb3\x8e\xf4\xdd\xf7c\x94P\xded\x19\xc9\x1f\xf9\x05\x91%W\xd9\x99P-\x86\x13\xaa\xfa\xbb\xe3\xcf\xa0\xc4\xf1g\xaa\xad\x10\x91S_\x94\x16\xff\xb1\xd4H\xcd\xc0\x95\x034\x11\x89Dc`\x14\xf5\xe9\xc6I\xac\xe2PR\x844\xc6\xa1D\x08\xa6\x8fC\xf1\x11F\x1b?\x82u\xf1\xed\x84\xf7\x82w\xecq\x9d\xc6\xc4\x18\xe1AO\xd8\xb2\x99G\xe4\xc3\x9f\x04y3'\x838\x0d\xe8<\x9d\x9e\xb6\x9d\x9d\xa5@\x83\xcd_\xdazUU\x02\x06\x9d\x02J$`\xd0\x98\xa2\xb2\x06\xdf\xca\x9ao\xfbO\xfbXy\x80J\xd8\x1b\x0d\x0e\xb2,\x0d\x91|\x84Wy\x04^7v\x99\x9e\xaa\xcd\x80\x078\xe4\xe5R\xfa\x87[D\xcf\x84\xfb\xb2\xd3-\xea\x96\xd0\x8f\xd8\xe9\";=\xa2\x8f\x7fz\xf8\x98\xc1\xa63J\xf5q\xb2\xad*\xca\xd7\xe6\xa6>\xe6$\xed\xd27b\xa5\xdb\xe1#\xaf\xd2\xb3\xee\xbe\xe6\x83M\x87j*\xa4\x0c\x9d,\x81\xcc\xfb\xf1\x95~\\Z\x9bS\xd7F\xb3\xb4i\x1d\xbb\xe2P^\xe3R\xfd\xc2\xf2\xa5*c\xbc\xaeC\xa2f*\xeb\x93\x1a\xacU\xe3T\x0d\x96[\xc0\xc8\xeb2\xaa\xcb~\xf6\x06\xe3<\x89H\x8cN\xe5\x1f\xb2\x114Q\xb3\xa2\xa1\xeafZECK\x8f$e~qL~\xc3\xec\xb7\xa6\xcc\xa0\xdbF\x8d\xa8f\x9d\x9f1\x1c(\x881=\xbb\xcb\x93}\x85\xb3!\xee\xe4\x93\xa9$ \xc8\xb0\xad\x12\xd5Q\x84\x0cUT\xa5\xdeT\xb8\x8a\x9e\xa3\xcb\xa9BAy\xfe\xb3\x1f\xcb\xf4<\x9d\x04\x96\xef\xdb\x05\x10\xdf\xcb\xcf\x04\xf6\x99\xebu&\xbcJ\xcf\x0c\xc7\xc2\xed\xe9\x9f\xe2X`\x03\xb59\x19(B\xc8\xcf\x04\xe2Q|\xe8?C\xa6\x14\x1eR\xa63\xfd\xf1\xb8\xfa\xe1\xa2\x92\x91+\x1a\x87\x9d\x14\xd6\x94\x88o]#1ap\x9d\xbd\x1a}&H\xdbG\xcc?Q\x02\x13\n\xf0\xe0\xee\xfe\x9f#g \n\x9f\x98\x949\x1a\xc3\xa6O\xca\x15\x82z\x1fp\x91\xe6\xe0\xd2\xaf\xd1 \xaf$p^Bn\x8c\x13\xceR\xff\x16\xa31N\xf4\xfe\xd7\x10\xc07P|\x0d\xc1\x8d\x1b#\x88O\x82\xb7\xcd7O\x02\xf5\xc1B\xb7v\xc4O\xb2\xbe\xb2\x00ei\xa3\xc2 \xf0\xe3\x98k\x0d\xc8\x18N\xe8\xbboE\x11\x87\x18O\xe1\xc8Cs\x85\x1fG\xff\xae\xa5\x07c\x19\x07zE\x1e\xa1\xe3\xed{?\xbfG\xadBz\x865y^\x936\xef\xab\xfa\x1a\xf3$\xaai\x00\xd7X\xe2\xbe\xa3\xdfc\x7f.\xa2\x98PN\x03S-\n\xef%\xaf|\x0b)Z\x0dY E\xac\xce\x9c\xc07\xacVa\n7 \x82o\x0f\x99;n\xc2\xe2\xbbqs\xf39}\xcc\xd6JV]u\xcc4\x19=E\x17\xdd}\x1fC[u\x95\xb5\xcf\x98\x9c\xbf\x8a\x96\xab\x98\xce9\xaf[I$\xc1P\x1d ]\xc6\xff\xf5\xbb\xf7&\x0b\xfd\x92\\\xaf\xfe}\x02e\xdfV\x1f\x90\xc1vV%h\xe87\x14\xa9\x88\x0f\x15\xc3\xb4:.,0\x86\xc4\xc4\xb9\"\x9f\xeaj!&A\x1a\xaa\xca2\x8eQ/v%\xed\x89\xa1Nx\xc5yY57q\xd5^\x1dt]\x9a\x14Z\xd5M\xe71\x07r\xcc\x96i'\xcb\xf5\xc9\x01YYN\xda\xb4\xe4\xc8\xd1\xf5\xfa\x97\x15!qU\x04KG\xd0\xd5_i\xcc\x19\x96=\x80uD\xbf\xa0\xae{\xfa\x9er\x00\xc6M\xd4W\xc3\x99Tpr\xa7\xd7\xe6N\"\x1e9\xcf\xd2\xbc,Z\xc7S\x9f\xbd\x85\x06\xe7\x99\x903\xf8>N\xe7\xee y+[\x83\xf2\"\xc3\x91ST\xa7\xfc@\xc4\x8ad\xdfL\x83\x92\x94\x93\xa2\xcc\x89\xbf\xeeH\xeb\x1d\xf6'ZT\xf5v\xf7\x0e\x0f\xe1,J\xc2\xf4\xccK\xfcm\xb4\xf4\xcb4\xf7\xd6\xc5\xb1\xbf%\xb4\x0f#\xddC7\xefsV$.\x88\x82k\xa3\x87\x1e\xff\xda\x9bW\xcf8\xc61\x0e\xfe\xcd\xabgn\xae\x91\xe9C\x9e\x0c\xa4\x8b\xa6\xbeL\xef\x1dyX/W\xb8\xb6\xc1!8I\x9aP|\x8e\xbcUN(G\x9c\xd2\xdf\x05)\xbf+\xcb<\x9aoJ\xe2V\x9b\xcfa\xb2N\xa3\x1cq\xcd\x00\xd13\xb3\xfb\x1ec$\x9cq\x15\xd3;\x1a\xd7\xdd\x9d\xa7\xe1\x05\xe5\xd9H\x12>ZEq\xe8F\xc8\xa6\x05t\xeb\xba=\xc0\x9c\xac\xd3-\xa9\x01\x1b\x93\x95\x93m\xfa\xae1Y\xa9\xea\xe8}/E\xc9\xeb L\xc9\x95\xbfR1+R\x89Y\xbeJ\xcc\xda\xa8\xc4\xacB%f\xc5\xfcAOb\nx\xca\xc7\xbe\x1cUKZYU\x12B\x98>+\xe0?\x81`\x95\x8f\xc1\x97\x0bV\xd1u\x14\xacr.Xml\x05\xabt\xa8`\x95{\"x\\\x84\xe1\xfc\xc2B\x04\xad\x84\x0e\xde\xd5\\T\x88\xac\xc3\x85\xbc\xa0\xf5QT\xa8\xba'\x02\x10M\x90\xd5k\xcc\xed\xe2-\xe5\x9f{\xad\xbcg]\x14\xf1T\x8f\x18\xfb\xf0\xfa\"#\xac\xd7V\xdd\xace#\xca~\xe4i\\|\x17\x04$+\x7f@\xf5\xaf\x89\x9f30})\xe6v2\xb0\x8f\x11\xba\xedY\xa5@\xf4\x11To\xa4\xdd \x8c\xceO\xa6\xac\x08\xbad\xea4EZ9\xd1\xd3\xe5\xb4d\xde{j\x00\xe1>\xbb\x91BH\xaa\x17\xbd\x1f3\xabs\xafp4\xdd\xad\x96\x82X!\x15\xc4|;A\xacX\xa5\x9b8\xacX\"ka\xc7\xb4/\x1a>M\xdd\xc0@\xe4NH\xff\xb6(\xbf\xcf\xde\xaab\xdb8x\xfdw\x1bN\x84\xd6q\xb0\xeaO9\x14n\xc6\x0e(\xbb\xd7\x86\x97\x07\xbc\xf1\x17\x15\x0f;-\xfa\xe5J4D\x7f\xb6\x9f2D\xe1\xcf\xd9\x1f}\xdch/\xffG\x92\x06\xf5$\xc1F^d\x1e\x19\xd5z\xe9)C\xd2\xc3\x03=yH,\xbdN65\xac!\xa5,\xf3\xd3\xb0\xcc\x13\x8bl\x841\xefm\xd2\xc6-5p\xc8\xdc\\\x06\xa6\x0d]U=\xd6G\xd5l\xf9\x11Zi\xed\x8e1\x89\xdf\xa34$#7\xd5x>\xac\xb1\x98\x8f\x13\xd4d\xd3T\xd1\xc6w\x9d8\xda\x12\xb1\x86\xa6\xca6~\x1d\xbbj\n\"\x91m\xf5\xaf\xbe\x92\xdd\x16Q\xa4\xb27f\xb5\x84\xf7\xb2\xf5D\xdd\xf8)\x1cB\xd1\xac\xf6\xc7\xa6rIJv\x82>b\xe7)\x95p\xc5\xb0\xe9\xacJ\xcd6\xe229\xee\x0c\xd1+T\x1b\xcc\x98\xd9\xe0J\x9a\xb3q\x01\x10\x971O\x16w\x05x\xd5\x88_n\xcf\xb5)q]\xec\xcfI]3\xc4\xe4\x08\xd5i\x0e8b\xa3\xcc\xad\xcb\xa6\xa5\xad\x16\xc3\x89\xab&(L\xb0\x97\\1\xa2\xe065\xc4\xa6\xde\x7f\xc5\x0c\xe6\x1a\xc0\xc6:\x89t\x17\xfc\xe5 \x8eQ\xbeJ#]\xc6\xabA\xc8Q\xe3b\x94\xe8\x92\"Df\xa5\x9a~E\xb5\xd5^\xea`i\xeb|\x94\x1a^\xae\x99y@\x93\x03\xaa\x93y@CP\x18\xf7\xd8a\x11\xcc\xbcd\x8fk\xd0\x1c'\x8a0}U\xfe\xa5\xe1\xdb\xd4B\xc9(\\k\x86b\x0e{o0=i\xbb\xe8\xa8\xc1\xf2\x1d\xba\xb4+\x8dS\xb8\xe1\x88K\xed\x8eS\xa1\xf0\x84\xde\xe39wU\xcd;\xf4 \xd7&\x03\xbc\xa2~\xd8\x04\xbb9\x8f\x1b@]j\xfe\xa1;\x18G\xc9;\xcd<=\xc3\xc7un\x07\xdd\x8c\xb5<\x9bR\xa5gS\xa9b\xa5\x81\xb3\xd3I\xdf\xc3\xa9T{8\x89\x0bYg\xa5\xa7\x93\xb8\xb0|\xc9\xc9\xd4\x00\x15\x027\x18F\xed\x0c\xcepx\x08)<\xac\xf1\xfc\x94'#A'_G\xce\xb8\x80\x99y\xb9\xd0\xad$\x08a\xc5P\x96\xb8\x8e:[\xb1\x1c':6\x15\xd0\x1d\xf8\xb1\xd0\xa6mQ\xafkh`\x91h#\x13\xa1\x8du\x1aZ\x8b\x90iH\x8cC\xaaO%M8/\x0c:I\x803\x07]u\xce\x8c\xa2\xc6\xe1\xa1.m30\xbe\xa4\xabK\x9aa\xd9\x0f\xa5\xaa\xc9\xdc\x15\x0e\xae\xe5\x87\xc0\xfeT\x85\xfeI\xad\x84U\x14\x85n\x15\x83\xde!\xa1K\x8d\xe7;$u\xe9'C\xeaGX\xd6\x99\x83\x98\x85\x98U\x8a\x1a\xb9'-\xfb\xcf\xaf\x85\xa4\x16\xa7\xea\xa0\xdf\x9b\xd6\x03\xf8\x1c2\xb9\x84*w\xacP\xe5\x8e\x15\xaa\xdc\xb1B\x95;V\xa8r\xc7\n\xa5\xe6\x8b\x98?\x91Z\x10\xdcP\xd8\n\xc2\xcaV\x80\xbf\xa6\xb7z\x05\xa4\x17R\x8b\x03\xaa\x07Te\xa5\xc3\x8fo\\X\xd9\x1a\x17\x88\xc4\xb6 C<\xb3hkjo);O)\x0e\x8d}\x914\xc1'+\xf2N%$n\x90\xba<2)\xb9\x12\xe6\xeb\xd3oF\xfd\ns%\x92\xd1m\xf9\x99\x8b*\xec\xe3\xd2/uJ\xeb\xbcO\xb2\xbbK/\xae\xf7h\xd82\n\xb4\x9a\x11\xc8\xcf\x9c\\\xd1Z\xef6\xfa{Q6\x84\xf4\xe8\xa5\xb8\xa4\xc3q\xfa\xac\x1d\xfd\x94\x02\xbf\xe1\n\xdd\x94\xaeF\xb3\xca\x08-Z\xe0RK\x1d*3\x9aP\xfeB\x0d\xc3\xac%\xe6\x02d\xccbb\xe1\x9a\x13\"\xa0Y\xaf\xb8B8\x9d\x12t\x8b\x10v\x9a\xdau\x0dk\xd0\xd4.\xab\xfeYhj/\xf8\x0cVx\xa4\x06\x9dW\xa0\xf6\xf6\xb1S8\x84\x95\x17%\x0b\x92c\xaeS\x8d\"\xe1\x0c\x0ea\xc9\xc5!5\xd4\x11\x1c\x82\xcf8u&\xe2h\x93\xfa\x9d\xd7\xd0\xe4\xdc_g\xb1>\x07\xe0q\x0d\xced%\x0d\xec#8\x84\xadU'\xdeqH\xe1P\xc5\xe5Q%\xfcw\x0c~\x9d\x86$>b\xbd\xd6\x81\xbf`\xe06%\x80^2\xd0*.\xd3TL\xe75\x83\xb7Tp?\x17\x9b\x16i\x97'\xa1Q\xf4\xc8\xbaPP\xf1\x05\xb8g\xee\xc8$/>\x15+\x84\xc5\xb2x\xc7\x9c1<\x7f;\xe6\x8a\xe7\xe7~6r\x7f\x7f\xdfe3\xba\xd7\xafp\x08O\xb9\xc4\x87\x88\xe9\xf4>\xa0\x16\xf1\xeaP?4M=ma\x98#\x94\xe0\x99W`m\xa0hq1r\xbb0T\xccf@KR\x1e\xe3M\xb6AF\xee\xaf\"\xec\xd70\x9b&A2J\x82x\x13\x92W\xc4\x0f_$\xf1E\x8b\xcb\xec^\xf4\xd0\xa3\xc7\xcd\xaf\xf0\x10\xcaJy\x95\xf0;\xa7U\x9fj\xc5V\xce\x9f\xb9\x8d\xcc\x89\xcd\x151\xf5]L\xfb[\xfaI\x85\xe6\x8d9T\xd1^\x9c\xba\xbe\xe8\x01k\xda\xf7V~Q\xad\x1d\x9d\xf2\x90g\xfb\xacnQ\xb9\x14\x07\x95T\x0b\xd2\x9b\xebd\x0c\xcfu\xf3(\x99C\xcdi\xc4\x80\x7f\xc9\xa3\x92hg\xfc\xbd\xde\xfcq\x8e\xbe\xcc\x94v\x9d[\x04\x8a\x89K\xb0\xc0\x94\x1d\xa2l/+&\xf5\xd7\xbf\xe6d\xe1\x08\x97.\xda\xae\x8a\xebQ\xe0;\xddu?Y8\xf05/a\xdcF\x0bTeo\x1a\x16\xff\xd6\xbc\x9a\xb1p\x0d3\xbe&\x16\xaey\xe5\xda\xb8\xb8\xe6\x95\xf2\x1893\xa4\xe0\xd0[{<5%V\xba\xa4YK\\\xc8t\xc9\xd9IqiMKw*\xcd]\xaeQ\xf2)\xe3\xfe\x9aW\xdb\xa4\xc2h\x9by\xf68[(\x8f\x19\x17\x97,v\xbc~V+-(J_\xd6^b\x1c\xeb\xf0q\n1A3\x06A\x05\xe4\x1b\x92\xa2\xf7\xf9\x18\xde\xed\x98\xdc`\x07M>8p\x03\xdc\x0ds#\xd7l,'\xf4K\x9f\xb9\x85+\x03\xff\xafN\xdd>D\xd7\x1f]\xa1\x9a\x7f\xb0n\x7f\xe7}-[\x8bn\xab\xa7\xa7z\x93\xa1\xaa\xf1\x17\xba\x86E\xd5\x1f_\x94)l\xd8&T\xa7\xc4\x18\xce\xcc\xbb\xcdj\xacL\x9dWQ\xf3\xe6\xd0\x1b6Y\xd3\xcet\x84@2\xf1Q\"\x11\xd6\xa8\x19\xcc5[o\xe84\xbe\xb60q\x1b8\x1e\xf5\x94\xb4\xec\xd7|-\x04#E9\x9b\xee-\xef\x1da\xc7(\x88\xc4\xd5\xc7\xe4\xb7^\xd2\xb9\xe6\xd51\xb1\xcb\xf4>\x8a\xf5\x1e\xc3\\\x9b\x83q\xed\xc7\xb5\x83\x81\xc3\x9d=\n\xd0E\xa1 \xe1\xa8^ar\xa43\x1a\x83\x03l\xe9\xbc\xda\x06Uq\x9b?i:\xf1\x9d\x16\xc5+K\x89u\x9a}MV\xfc\xa6Z^S{\xb1c\xa2\xd0\xd5^D>T\x88\x02L\xb5\xfd\"\x0fIN\xc2\x91\x9bhV\x94\x1fB3\xf8I\xb1p\xd5\xd4\x1di\xa6\xee\x91n\xea\xb8h;\x83#\xeb\x99\xd3\xf7e4\xae\x04\xfc+\xb5w\x0e0r\x1e\xc3C8\xf6\xcaT\xc6\x85v\xa2W\xba\x97\xe1\xc0}i\"T\xc8\xb5i\x14<\xf4JpP\x06 :B\xad\xfe\x11,\x17\x064\xa4p\xa4\xad\x87Yo\xdf\x9fR\xe0\xaa\x92j\x95{\x1f\xbc\x94\x05i\xa5\xb7 \xd5fCF \x85u\xe8\xf7\xf7]s\x89\xcc\x9a\xd7TL6T\xffm\x9b\xd0\xea\xbf\xf8\xcdke\x13Z)sG\xacTQ%+UT\xc9J\x15U\xb2RE\x95\xacTQ%+\xa5Mh%lB+\x8c\xc8\xbf-\xb5\x04\xb1g\xbd/W\xe6\xa0\xf6\xedP\xf4]\x91no\xf5\xf1\x0dE[[C\xd1\x97(\x94\x8e\xd1\xca\x14\x85\xa2\xb7\x88d~^\x90\x90oq\x85X\x85\x91\"\x1bt\xdd\x7f\xd9\x04\x1fd\xf2\x12!)\x9c\x1bSk3\x99\xff|\xa9\x16b)\x10S\x91@\x94\x14\xa5\x9f\x04$]\x00\x0b<4\xebC\x12\x1e,\xf9$\x8aQ=\xa52\x8f\x89+\xf1R\x16\xc6g\x91\xc3\xa0y\xe56\xe6\xb5\xe6\xd5] \xca\x0cobydn\xf3R\x9cD\xd5\xe31~\xca\x0f\xbf+^\x93\xf3\xd2\xd5L,\xd7\x1bZ\xf7\xbc\xd3\xe3\x92\xf2\x07\xac\xaa\xbbN\x03!C\xafO\x1b\xa4r\x95\xd9\x02PN\x90\xec\x15\xd7\xea\x88W\x07a\xec\x942@\xb9)\x95\xbd$b\x7f^\xa2\xabWc\xd5\xb4\xb4d\xd6\xc1g\x16YB\xad\xccu\xac^\xc9&\x97$T\x12\x17\xabR\xc2\xf9|5\x98_\x9b;Xz\x8d\x87\xf0\xfb{\xd0\xba\x0fo\x06d>-\xdav\xa3\xd6nT\xbf\x85\xf5A\x06X\xd5\xe8\xc1\\\xfb\xf2\xa1\xa6\x8b\x92\xcf\xc7~I\xb0\xbe\xe8\xebhMt\"\xf4\xba\x9a\x04\x8d4$\xc9\xf5\xd5\xbc(\xc5\xa7\xcb\x92\x8aL\x0d7\xffo\xc3\x87\xe9_\xad \xf6\x9b\x91W\x92\xa2t\x93\x11\x05\xf6O\x1c>#\x93\xc7Q\x91\xa5\x05f\xe6w\xde\xd2\xe3\xe3\xa6_\x96~\xb0\xa2\x07\xb5xI\x05.\xbe%4,\xa1\xdd\xb7\xa4\xe0\xbd~5\xb4G\xec[\xf4h\x82\xd7\xb9\x9f\x14\x0b\x92\xcb\xba\xd6|\xa3\xd75\xeb\xcfI\xdf\xd0(\x8f\xe9*8\xf4\x98u Jx\x9c\xb9\xe9$\xa4[\xf9\xa2\xca\xb1Q\x92\xf3\xf2\xe6\xaa\\\xc7\x16\xban\x0c\xce\xe9\x1e\xf0\xc2\xcaV%;(\xa5\xc9\x0ed\x17K\x80pa\x84\xed\xca?\xb2\xebT\x9f\x94`n\xf1\x8938\x84\x93\x0b\xca\xd0\x15\x9byQ\xe6n\xea\xc5~Q>MBr\xfeb\xe1:7\x9d\x11\xdc\x80\xe9h\x0c\xa7o\xbd_\xd3(q\x9d\x99n\x9b\x8a\x0b\xed\xfc*D\xd5l\x08=\x13\xd4\xc9\xfdpdZv\xe0K\x7f^\x99{\xc8y\x99\xfbA\xf9\x84\xe7oz\x92\xa7k\xde\x8fF7\x98W\xc4\xc8=2\x18\x84\xe8\x85!<\xb43\xcc\xeaG\xe7\xf3\xdc\xc0 i\x9fR\x1aTy]\xd6\x99+\xe8\xc7%\xb7yB\x8b\x17\xf9\x8b\x8c$\x1c3/eIq|\xa3\xc6\x16\xaa\xfa\xec\x06\x07\\\xd8\xa9\x06\x8a\xb88We3hw>\x863\xfd\xa4\x83q\xe2\x9bYf`\x11 #\xff\xb5\x9aM\x91\xcbc\x06g\x83\xc7\xa2|\x81\xb3\xdb\x14\xf1\x94\xe3`)u\xb8\xce\xa8\xfa2\xe7< $%\x96\xd6\x86\xf9\xa6\x84\x8bt\x93\xc3\xd7r/\xda\x99f\x96k\xda\xe7\x06'\x84\xa2\x81\xdbN~\xc8x\xd7\x9b\x14\xe8_7\xb3\xd8\x8f\x92\x9b\x8d\xd9\xff\xc8\x036\xf0k\xc2\x88\xa7\x181\xcc\xe0\xe6\xff\x8d\xd6\xfe\x92\xfc\xebf\x0b\x87\x12\x8f\xbb\xfd\x14\xaeSl\x97\x8e\xd6\xb0\xd1\xa4\xf9\x0e8\xa8Fv\xc0\xd1+\xdb\xd7K\xed!\x80\xf9\x9ed\x9a\xcb\xe6\xb5\xf6\xcf\x7f\x89\xc2r5\x03g\xba\xbf\xff\xff\x93c\" \xe5W7\x94\x073\x1d\xbb\xa8\xd0\xc8\xf0\xb9\xf37a\x94v\xe6\xce\xea\xb8P\x9f\x8d\xf4\x8bzC\x117G\xaa\x1d\xb1tA\xd1h\x1c\xd7O=\x9d\x11]\xado\x96\xacL\xb5\x89\xe8\xc48\xcc\x7f\x88n\x1f\x04O\x17P~\xfc\xbdQ\x9e\xcbtE\xe22o\x0d\xee\xe4\xf5-\xec\xc3C(lw\x80z\xf9\xad\xcd\x7f\x91:\x9c\xf1M\x92\x93 ]&\xd1\xbfIX\x99\x89p\x8e\xbf\x16\x81A\x94\x89\x10A\xee~\x81\xd4\xdd\xd3E\x8a~\xca\xd9/4\xa4\xf8\xd3M\xe4\x06K\x91@\x99\x8a)\xad\x8d\xf7Z\xb7\xa5\xe5\xa5q\xa4\xe1\xc5Vg,\xc0\xb0Tz\x9e*]\xab\xacm\x916UH\x98Yu'\xcb`\x95\xef\xd0}p\xf7\x8e\xc4\x88\xa7\xd7}\xd6\xbe\x9eY\x1c\x95\xeeM\xf7\x9b\x7f\xdd|x\xf2\x7f\xbf}{\xe3\xdb\xd1\xcd\xe5\xc8[DqIr\x0b\x0fK\xfe!\xc7\xa9\xb2\x0dEkY\"\xdc\x8e\xfa\xba\xdd\xdf\xc8\xb6\xbf7\xbf\xf9\xd7\xcd\x1b\xac\x9b\x9c\x11 \xda\x0f\xfb\xf6\x1f\xc6\xaf\xfe\xeb\xa6\xddw7\xb6\xdf\xb5\x9e@\xec\xc0\x9er\\\x80\xc8E0\xef\xf0^$~\xf8\xbdn\xd6\xf8!\xcf\x9d\xd9\xed\x850JuM|\xf0-Li\x13\x0d]Gm\xcb\x9b\xbe\x85\x87\xed?g\xf0\xbb\xe4\xdcg\xb1[\x82\x83\xed?G\xbd\xad'a\x89\xfb\xa01\x1c\xca\xf4\xa6\x01\x1c\xc2IGeSg\xb2\xa5\x7fu\xe2\xac\xe9x\x17c4\x07\xbb\x0b8\x042\x86\xd4]\xd8\xb8\x13\xf3uR)\xeau!]\xec\x14wK\xd6^\xe4\x96\x94uq\x1e\xc5i\x11%\xcb\xd7\xfe\xd2\x81\x19l\xf8\xdd\x17\x19I\xea\xbb>\xbf{L\xe2E\x1b\xdeyM\xe4\xb9\xbe\xe5\x01\x81\xed\xa3\xf7\xfdH\xe2\xba2\x86TeR\x8eLI\xeaX\xfdq\xa4\xe8\xbd\xe7\xad\x81R\x1e\xdf\xa7\x88\x15O&\xf2\x9e\xd2\xad\x95\xbb\xc9\x18b\x85\x92\x0fK\x89\xc3\x0d\x88\xfa\xef\xa3b\xb69\x83us7n\x8c\xa1\xd0\xd9Y(J\xa4'%L@\xe7\xbe\x1dVP\x07\nM\xa1|\xb8l\xb9\xf0\xef\x0c\xe7 ov\xbb\x1aV\x8f\x109\x1d\xac\x9c\x057 ds\x0f7 \xab~ET\xe8\xc4\x80\x05\xec\xcd\x18\xb0\xeb\xc6\xf0kh\xd0\xa6\x0eN\xb4\xc7\xc3\x81\x02o\x91\xe6G~\xb0\xb2\xdb\x1e\xd9 yK\xf7_\xf7\xe4\xa42jfw\xaa\xf0/\xed\xedu\xfc%F\\\xfb\xfb\xaf\xa6o\xe9%\x12\xb6\xde\xfc\xfb^\xdd\xc0\xdf!'\x19\xf1\xd1vB\x99\xbaoVe\x99\x15\xb3\x9b7\x97Q\xb9\xda\xcc\xbd ]\xdf\xfc5M\x8a`\x15G\xc9;\x92\x977[\xf0\xdf6\xbe\xd4\xfc\xe8\xa34\xbb\xc8\xa3\xe5\xaa\x047\x18\xc1\xc1\xfe\xf4\xf6\xe4`\x7fzg\x0c?\xa6 \x1cW\x1f\xf3\x9a\xef<\x8b\x02\x92\x14$\x84M\x12\x92\x1c\xca\x15\x81\xe7O_\x8b\xdbM\xd0\x9b\xd5od\x06X\xd4c3\xb3\x842\x7frw\xdeq\xe3\x08Ab\xaf\x12$\xc8\x08\xcaU\x9e\x9e\xa1\x9d\xe1\xf5EF\x8e\xf2<\xcd]\x87\x9cgL\xdd\xe6\x03\x7fI\x92\"y\x8a(]\x8e*^\xa3\x0fr\xd0\x05\x81\x1b]0\xe1\xa9@\xc4\xc1\xf4w(\xfb\x1f\xca\x19\xf7A\xa9~\xc3\xce\x98\x8fX\x16\xf4\xfe\xc4@S\x9d\x97Vg\xde!\xc5\x1b\xde\x97\xca\x1e\xb1O\xb1\xa9\xfd*z\xc7|\x8d\xa5\x00\xaa\x97\xd1\x0d\xe3[\x98~=\xa2''\x0b]qS\xb8q\x88F\xf8\x12\xbe\xfd\xf6\x10\xa6c:\xc4\xc3\xee\x18E\x8b\xf4P\xe2o\xb4\x1a\x1f\x86\xed5cxw:2\xe1\x82\xc2\xbb)w\xc9\xc8+\xd3g\xe9\x99\xa8D;\xac\x0f\x1f\xdd\x99\xed3,\xfe\xba\xa82\x1b\xd0_\xf7F\x7f\x8e\x82\xaf\xdb/\x05f\xd4\x05f\x84\x17\xfd\x80h8\x81\xe0\xb9\xaa\x8a\xf6\xa8\xe2\xa8\x8e\xceKM1\xef\xb4[\xb2;U\x97\xecN?\xbeZ\x88 t\x9d\xb1\x98-\x8b\xe6z\xddReh>t\xb7Jy\xa7\xd3Sr^\x92\xa4\xe8\x1d\xf6\xef\x99\xe7\xd4\x0c\x9c1\xf0\xa3)1\xd7\xda\x8e\xae\x1bB=e\x9ecG\xeb\xac\xbc0\x94\x89\xef\xc5\xd4\x8a*\xf1\x98S\xb5~'\x12\xfa\xc9\x88\xeb'\xafU\xc5x\xd5\xc8m\xf0\x10\xb1B\x85\x88Q\xc1\xbf(9\xea\x98\xf9S}\x02\xfb\xfc\x0b\x8f\xa3\x02)\x9d\x14\xa1\xf9\xb9\x8f4\x0f{\x8d\xda-\xf4\xf6\xbb\x0c\xaew\xf4\xa9-\xd4\xa7\xad\x9c\"\x0e\x9d\x96\xe9r\xa9\x11>B\xdesY\xfa\xe7\x9e\xeb\x86\xba\xbfQ\x92mJi#\xcc\x04\xee\x04+\x12\xbc\x9b\xa7\xe7\x12MY\xa3\x0b\xfd\x87\xf8\x1e\x1e!\xa8t\x90(tj^\xc9\xac\x9c\x8c\\Q\xc1\xda\xe3\x1f6\x1e\xb7\xa318\xc7$ \x01'\x95mL\xa7\xe7#\xf4Y\x95\xe8\xff\xa49\xa1\xe5&\x93Pj2Q\x94\x93T\xa4\x88\xbeu\xd0\xcb\x0b\xf0%\x17\xb4\xdc\xb0ag\xd4\xb0\xcd\x05-v\xe0.f\x82\xa1\xeeG_}\xd5\xfa[-F$&\x1bD\xc3\x02\x90TC\x18\xb9\x89'$\xc618\xcc9\x03\xad\xcb\x88\x13\xcc\xbaLD^\xc2\x84\xd5PB\x91\xbfOG\x9a\x96\x14\xebCK\\\xdbai\xb2\xad\x94\xc8y\xad\xc2W\x03\xa5\xd6\x9af\x1fS\x1aX\xc9\xb4\x9b\x1a\x94\x8a\xc4\xda\x05IxT6\xce\x15.\x04N\x1e\xe5\xe4\xdct\x0c\xfe\x186*S\x10\xe6\xf3\xe6\xd5*X\xcdA\x8b\x8c\x05\xc2\x00c\x9ci\xc6KX\xea\xf6\x13\x10u M\xd3\xc8\xca\xb5WHg\\\x18\xb5r\"\x19C\xae\x98\xdbF\xf4\"\x96\xf0`k!\x0e\xb3\xaf\xbe\x02\x07\xb5Y\xb8\xdf\xd2z\xa1t\xfa$\xc1\x9a\xe9\xa2\x96\x01\xcf\xc3\xa88>\xf3\x97K\x92\x1f\xa0N\xd6\x87\xaa\x8d\xf3I\x9d\xf9\xf6\x8f?\xd8]L\xcf\xcbi\x11\x8f\xed\xad\xefW w\xabT\x8aj\x88\xc67f\xd8\x0b\x9e=\xea\xab\xaf\xc0m\xf4A\xd1\x83\xddZ\xaa+`\xef \x07\xb0\x1e}tY8h\xb2Y\xcfI\xfe\x9a\xeb\xc7F\xae\xaf\x88\x93\xeb{q\xc90\xdd\x1d}\x9c|\xedU\x12\x86_\xa28~E\x02\x12m\x91;\x91\xd5\xdc\xb7\xce\xc5Ps\xea\x9fxw\x99R\x88G\x97\xda\x83Hd\xa2\x02 \x1b\xee\x84\x1cf*3\x9a\xcd\xeeJ\xab\xed\xe4F\xad|\xd4#q\xa8\x07,%\xf5h\xc4Q=\xd9\xac\x91w\xf5\x81\xe5b\x88:\xf7u\xad \x17\xcd\xc6{53lJoP\x18\x86\xd2\xd84\x1b\x8c\x03\xa1\xff\x9d\x893#'\xbfm\xa2\x9c\x84\x8cT\xe1\xae\xf2\xd9\x19L\xf72\xba\x89x\x8b(/J\xb7\xb3\x01\xb1\x90e\xc1?+jZ\xdam\xc7bTe\xd1\xee\xee\xb4\xfe\x86lo<\x99\x18\xf4\x01\xbc\x05\xec\xce+\xc3q\x9fX\xee\x8f|@V\x8e\xb4\x865\x98\xcb#.?sm\xaf\x9e\xd7 Z{\xfe\xa6%\xaa\x0b\x95\xb7\x1e#\xad\xe9M`Mo\xc2\xea\xb3\xe6\n\x0f\x85\x91\xde`\x95\x07cj\x11\xafX\xa5gGB\xdde(\xef\xc0\xa0\x1f\xa5\xebu\x9a\xd8\xbcs\x81^\xd9\xce\x8fE\x9a\xb0\xcc\xe7O\xd2|m*)\x9b\xbb\xcc\x98\xfc=\x0b\xaaQ\xc2\x9e\n\xc7\n\xc6n\xa8\x01\xcf\xe0\xb0\xc9\xa2\x9c\x9a\x0b\x98\xceM\xf6\xac\xb6\xc1\xc9`\x15Y$Zk6\xd4\xf6#\x83\x95)\xa8\xec3\x85W\x15S\x10\xd8\xea\x06\x06\xbbP\xd0\xf4\x8f\xa2\x9fh\xa4\xf3\xc1{\xf4\x135\xcd$E\xd9\xc8\\hot\x92\x91I\xbbwk\xf3\x93\xa1\xf4X\xc3\xc2\xa3\xc9\x05\x04\x83\x8b\xb65\x8dL\x81\x12R\x97\xe1\xe4\x88\xe1\xafm\x0d\x8ds\x06nSC\xe3\xb8\xb13\xb8\"\xddT&\xa4 \xde\x94!MEC\n-\x93\x12P\x89^\xfd\x81\xef\xea]\xb9H\xf3\xb5\xaf\xed\xe5\x0b8\x04\xf4\x81^!7Rv\x18\x11\xed\x86x \x87\xf0\x82\xbdP\x1a\x10\xf45%\x00\xb47\x8f\xfd\xd2wL5\xf8\x9eS\xe8'\x15t\x94\xd4\xa1\xe5\xea\x97\x9e\xd6\xc3\xae\x19\x0e5\xf8\xaf\xa2\xf3(\x0cD%Y\x17T\x16\xc0\x81t\xab\xc95\xaf\x9f\xe0\x10\xde\xc1Cx\xd7\xe5\xa1\x1cM$\xe7+8\xc4\xc0GW\xd4\xa2\xe8\x12\xf0\x91[Vy{\x95_y\x0c\x87\xb0n~e\xe0\xfb\xcf,\x12Y\xbd\xb1\x80\xf9\xcd\x02\xe6 \x1c\xc2\xdeT\xab)h0z\xcc\xe9\xfeY\x8dOl=:\xec\xe03:v\xda\xc1gM\xbew\x8c\xfd\xe1\xb7\x84(\x87\x86\xe37\xf5\xf7\x04h\xe3koh\x9bo\xea\xf0e\xda\x03\xec\xf5~\x1b\x8e\xf5\xed\xb7\xfa[U\x1b\xe3f\xccB\xd9\x15G\xb1\x02FWL\xd6z\xa4\xe8\xf3\xf6\xb3\xdc\xfbH\x17&\xa8\xb0\x99\xd9\xba$4\xdf\x8c\x12\xa7\xe5\xde }\xe9\ns\xf8\x0fq&\xba\nC\xffSx\xd82#\xd2\x06\xa1\xa2\x070\xeb=T\xf6\xa6=\xb9\xf8au\xc6\x00VF]\xddC\xabT\x0dA\x1ac\xbe\x10\xdaS\xf5\xd9\xa7\xea\xaf\xf3?\xff\xef\xefN\xc3\x8f\xee*f\xb39Y\x9a:\xe9cx9\x86_Q\x0fu\xe2\xc0\x0d\xf8\x15n\x80\xf3\xd6\x19\xc3w\x18\xc2\xb7\xf3\xac\xb5z\x92\xa7\xd9\x84\x9fg\xca)p\xffJ\x1b\x1d\x833\xd2o\xb5\x1d\xa7 $YN\x02\xbfT\xad\xcf\xfbq}\x96\xd6\xdb\xbf\xf1\x16\xc6\x846\xfe\xfep\xab\x15i\x9c\xe4\\g\xdcb\xdbq\xba\xc6\xb0\xa4}~%\x94\xe3\xaf\xae4G\xfa\xb1\x89\x9dgnW\x14o&\x14\x83\x0c\xeeR\xe7\xff\xb0H\xa9~\xfe\xb3\x1f\xeb\xcb\xb0\xc8g\xa8N\xa0\xbf\xa63\xf2X\xcc\xc8\xe3\xff\xf8\x19\xb9\xc2\x1a+;8wV\xdb\xa9\xe1\xe2\xa9!\xca\xe7Zz\xcc\xeb\x9f\xc8\xbei\xc2\x8a\xbd3\xd4\x0b\xc3\x1f\x7f\xc0\xde\x13\xb3$\xab\xed\x87\xca\xf9\x85\xb2+\xea\xb5\x14\xbdw\xbe\x89\xbe\xfdn\xebG1\xa6\xe2@V\xb4\xf8\xe6f\xf4-=\xe6\xe0\x06\xbc\xb1\x88\x8eo^\xc2|\xaa\xc1\x8f\xda7\x8f\x07\xf5\x8eU\xc9\xcd\xde\x8fZ3\xd5\xe0\x94~\xfb0s&\xd82\xbbi\xe3*A6i\x8d9\xfbM9\x98\xd7t,{\xcf\xb5'Z+\xcb\x13\xc6\xdc\xce\x0cY\xed*)\x07\xcb\xebP\x94\x8a\xcc\xd3\xa3\xad$o\xd0uX\xebM\xb8N\xf3'5\x84`\xabf\xf0T\x0d\xd4\xd8Z\xf2\xedVK\x9d\x8c\xd5\xa2\x14\x0f&\xd0p\xb9m\x83\xcfXx\xbd%\xef\xbb\xabV\x84\xd0\xc5+fB\xccc\x7f\xea\x1a\x12\xf5\\^(\x11\x087\xc3\x0b\x0d\xc5:\xd2-\xab\xf5\xba\xd5\x0e\x96\xdd\xba\x88\x06\xa4\xe0\x0e\xd9\x9a\xacVvZ\x1f{\x8d\x8f\x98\xb3\x8e\xd6A\xb3*\xa2\xf6\x8d<\x89\xa5\x84H\xefX\x01G\x816M\x1d\x8en\x9a\x84K\xda\xac\xa9\xc9\xa9\xec\xe0\xc7\xa4,\xa3d\xf9$\xcd\xdd\xa0'g4\x183\xcdD\xd4>k3\xf8\x89\xb96PY\xf5'\xe4U\xd4\xaf %\xa7~\xf6\xae\xca\x89\xf9\xfa\x97R T\xaeT\x81\xca\x95*P\xb9R\x05*W\xaa`\x98+U\xe0\x16\x8d\x8e\x06jO\xe2\xe0\xe3\xfb?-l\xfd\x9f\xbe\x04\x98\x0b@\xfb\x00\xf38\n\xde}j\x87\x17k?$R[?4goevS\xc30\xcb\xe0\x1aU\xferma\xe2m\xfd8\xe2\x85\x1e\xfcu\xe1\x9e\xa4c\xf0\x91\x02UO\xbe'\x8b4'\xfcp\x12\x00\xa8\xb7\xe3\xb3\xe4\xa5 \x7f\xca|::7\xdd\xd1\x18\x12\x8f\xf0?4\xc7\x82\x18\xb4\xf6\x04\xce\xf0\xf4\xd5\x9c\xa3kn\xe1\xe8\xfb\xec\x02\x12*\x837\xda\xcb<\x0d7\xc1\xb0\xb8\xfe\xca\xdb\x8f\x8d\\\x92r\x80\x7f\x94\x19\xc9O\x04 \xae^\xf5\x1a\xeb\xf8\xdb?i,\xbf)\xf6y\xce\xa2\xabme\x93y\x99\x00G)\x10\xe1G\xfc\xd8f\xa9\xa6\xae\xdb\xb1\x8d\x19X\xee\xab\xb2\xc6H+\xa0I\xd3\xc9\xf8\xaat2\x1bU:\x99B\x95N&\xe6\x0f\xe4\x15\xd0Z\xb9c\xaeY\xc6\x98\xfeG\x84\x1e\xfa/\x0f\x1e<\x90 \xe9\"M\xcac\xa6\xcfv\xa2\xd2\x8f\xa3\xa0\x1b\xa2\xd3\xfa34\xd2'\x03\xe3\x00m\x1a!)\x83\xd6\xab\xbb\xa4\xf6\x93\xee\x94\x1fc\xc72\x03\xaf\x18\x02#\xff\xdb\xe9\xd1\x8e\xa5\x9b\xc0L\xb9`\x00\xf5\x82\x81\xfeEP\xb1\x08\xc62@\xc0\x19\x04:\xac\xb6\x17\xd1\xc8u\xc4\xd6V\xf9\x05C#\x94\x06\x9ae\xe1wVyC\x87\xd0\xf2\xfe\xeb\xe39\x01\xf46&C>\x06\x90\xb7yz\xaaI\xca\x00\x9c>\xff\xc0\xcb\xa9\xea\xe3\xe4\x8dI\x06@\xde\x85\xdd\x86;$\xd3\xc0\xd0.M\xf2\xf4l\xd7^\xed\xd2\\\x90\xc6\xfa\x05\xb8l\x92\x02\xd8\xb1\xddV6\x82\x8f\xdf<\xf3\x1a\x1a\x90\x05\xa1\xf4HR\xe6\x17\xb2\x12\xb9&\xdd\xb1\xf0\x01\xee\xc8?d\x0c\x07\x06\xbf%\x10\xee\xbb'\xfb\x9ax\x10q\xa1\x0b\xef\xc9\xd4\xa2\xda\xcf\x9e$\x1f\x83\x1b\x8d\xaa<\x81\xeaL\xd5\xe2\x12N\xbc\x91\xd7\xf1\x19\x7f;\x12N\xb4\x1dOr\xee=\x02\xb3\xc6S\xa3G\x89\xb86\xb2\xa6Z\x0e\xec\xfa\xee\x9a\xd8W\x8b\xbd\x0c\xe2HJ\xb5`\x97\xf0\x0f\x10\xd7P|\x06\xd6lz \x13\x94\xb8vl:\x92(\xa3?]o|^Fb\xa39H\x13\x9b\xf6)\x97\x80\xb6CGx\xcb\x991\x95\xbe\x83\xa6D\x83\x97\xa0\x80\xe5\xdcb\xa6\x1f\x94F\xfdX\xc3t\x93CHS\xbd\x83\x94c\xeb\x88?x\xcbP\x82\xba)\n\x85x\xf7\xba\x89B\x9fT\x83\x19\xc8\x04\x1e* \xb9\x81\x10xP\xdc\xf93\xa8/\x1b\xfc\xbeDK\xd9g\xf9m#5m$\x90k\xaa/\x19\"m0I\x83\x84Q\x99\xe6F\x0d#SF\x92<\xb7P\\2md\xec_\xa4\x9b\xd2\x02\xbf\xb3p\xb9#\xcc \x884\xdcH\x18\xe55\xf8\xf3\xd5\x07\x84\xcaL\x04\x82gv\x8a\x8c\x04\xe6\xe1\x84W9\x9c+\xeb<\xf3\x0b\x93#\xc8h\xa7tj\xb6\xfc\xfc\xa2\xcdL\xeb\x93\xa7C+\xcc\x19gA>\x05\x0c?u\xc7;\x9e\x95\xa5\xe1h\x14\xec}\xd9<\xa2\x94V\xea\x9d\xf6jo\x9f\xaa\x8f\x9f\xf7c,Mgh\x86\xe9\x90\xf4\xa7\x87\xd031\x7f\x1fVg\xaf\xe9+\xcd\x99\x0fx\x08+\xb7\x03\xc5\x1c\xc3\x1a\xae_\x02\x16Co\xc4\xcd\xcc/W\xf8\xbe\xb2\x1f\xc5\xda\x8f\xe3F-F\xbf\x84\xee\xeb\x0d\x7fW\xf5gt\xce\xebFw\xff\xb3UT\x92\xe3\xcc\x0f\x98k;\x99\xe0\n\xabw\x95U\x15Gi\xaa\x01>\xb05)\n\x7fI\xb4\x07\x8b\x16]\x8cC\xc2\x8a\xa0\x93\x90\x04)3\x91;3p\xb0\x12\x8aah\xc1&/\xd0\xdc\x94\xa5QR*\xb9\x1f\xd9\xd8\xb0\xb6\xb5\x8e\xe6i\xaa(W\x07\x7f\xe2\xcd\xa3$t\x19:\xe4R\xbb\xb6\xf3\xe3f\x9dA\x99\x02\x1d\n\xc5\x96\xbc\xd6U\x88\x1fm\xb24\xd4\x04\xb6\x13m\x91C\xe5\xbc\x8c\x8f\x92ZtwJ\x8e%h\x9fEE\xe9E\x05\xfd\x8f\xdb\xd9\x0c\xf6\x9bI\xb2\x97\xb8\x9f\xb0\xc7v\xd5%>\xc4\xd2\x804\xc8!\xfa\xe3&\xe8\xe5\x91c\xcc\xa4\xdd\xa7\xd3\xa4Z\xc6\xd6\xe7v\xde\x19\x9f\x90\x90Z\x13I\x0c\x0fB\xc4\xfd\xc8$\xcd~3\xff\x99 \xd5\x95\xd2\xa86\xd6Z\xd1\xab\xf6+\x06\xda%\xd3\xd6\xad\x94\xda:\x17\xd3k9\xce\x88W\xa4t\xc0\xb1\xb1\x1d \x11\xfcd\xff\xadW\xa6o\xe8va\xf5\x8a\xe0\x06\x10\xaf\x88\xa3\x80\xb8\xd3N\xc7\x04-\x81^\x1d10\xa7\xccm\xf2\xa4-\xa51\xfb\xc2\x17\xbd.\xbf,\xf5\xbaA\x95\xbb\xefO\xa3\xe1\xfd\xe2\xa0jQ\x01\xe9\x12>\x87\xe2\x13u\x12O\xdc\n\xd7\xd0\x93\xb0\xca\x92\xf58\n\x9f\xa7\x9bD\x16Td\xab$\xaf\x95\xe3\xcdl\x1fE\x95\xce\xa837\n\xf0*?R\x7f\xb2\xda\xf3!;J>`\xea/\xd2\x1bT\xfbN\x9d\xe6\xa9s\xbf*\x9d\xcf+)0\x9dH\x13G\xa4\xc3\xbf\xc4\xf8?\x81\xb9\xa39\x04\x93\xb5\xa3\xe2\"M\xa6\x0e\xec\xaeV%\xddv\xb3\xda\x89\x89\x82^\xc8&\x8edR^dD\xb0\xb7\xc8f\xba ?\xfe\xa5\x9f\xd1\xe9\x11\x0b4\xd6\xec\xd4\x03s\xcd\xf4\x9c\xf5J\xab\xf7\xd5\xc4\x85\xa9\x06SZp6\xe22\xe9fR\xe6C`\xa5\x953\xe8\xdb\xf8\xa05\x81\x9bR\x8fm\x80\xaeE}\xc7\xda\xe9z\xa5\xdbB\xcf\x98I\x12@\x8fzU\xa9\xf9\x08\x93^~\x93\xe6\x16cI\xb5co\x91\xa7\xeb\x1f\x8fG\xee\x89C\x0f\xb5(@.\xff\xe6\xafE\x9a8o\x1b\x9c\xe3\xf8\xday:\xd3\x1e\xbd\x10!\x06\xcf\xa2\xe4\x9d&5\xfcug\x10\x13\xf7\xb6* \xfdg\xc9\x18^\x05?\x98H\xf9\xc1\xa8\xe2\x07\x93\x11\xe3|\xf6\xbf\x86\x0d|\x03\xc9\xd7\xb0\xa1\xfc`t\xb2i\xf3\x83\x1b ?(\xf8\xcd\x0f\xc5\x08F#M\x12i\xcc\xb2\xf8\xda_\xa2\x05\x17u1\xa7\x8d\x1bLx\xa5\xccn\xa1X,\xb8B\xe6\xad\xd9\xb2\xc5i\xaf3:5\x98\xb1\x96\xc7\x003\xfd)\xf2F\xb7\x87\xa8\xe6G\xe87^d\xd7\xb9\x87\x9f\x80c\x1a\x14\xadf\xed\xf4\x91\x0fq\xfaH\x07\xa4\xcad eK\x7f\xb9$aE\xb8\x0b]\xc6G\xcc\\lv 11\x0f\xf6\x8aB;\xee*\xdd\x92|\x1b\x913S\x8d\xc1\x17\x1c\xceA\xa1p\xb0\xf56\xad\xad\xb7U(\x9d6\xaa\x1e\xf8$\x9f4z\xe8/\x0bg\x0c\xa5\xc1Y\x98y\xcf\x08\xa7\x92\x08\x1dI\x8c\xb6\xe2\x9dye\xa86M\xd5OT\xc2*_\xb8\x84\x9f\x05\xec\xe4\xb6\x00\xf5(sF\x1d\xe8\x9cl\xd4\xee\n\x00=;F\xf7jbPL\xd9\x95\xe6\"\xe9}\xd3\x85\xef\xaa3A\xa7\x87\x1b\x0e\xf3\xa2S\xcd\x89o\x9a\x90\xda\xef\xc1\xe0\x93j\xf4}\x00\xd6\xc3t\x00\xab\x0f-\x0bN\x992\x86PG\x06\xc4U\xa7\xeb7\xc32b\xb36d\xb0\x15\x17\xf33\x8b, \xe9N1$G\x05\xce\xde%\x0d/\xad\xc6\x06\x1e\xc3\xc6\xd29}g_\x0b\x10\x1b\xcc\xa2\xa7\xc6\xf8[q\x898\\C\nSzE\xe1\x0c\xd2*\x19\x93\xc5\x0bt\x8b%Z/\x9c&\xe4\x8b\xec\xa9\x19u\x9b\xc0/s\xb2\x88\xce\xb1\xb0]\xbd\x0c\xc6\xb7W9Y\xcc\xc0\xf9K\xf5\x12\x8e\xc6\xa2\xd9\x8a\xde0\xda\xa1'\x1a\xb6\xfe\xdbR\xb0&\x08&\xca\x8f\xfeM\xe0\x1bVUDM1o5\x0c\xfa?\xa5u\x9cv\x01L*\x0b!J01\xc9\x1eHm&\xad;\x03\xe5[\x83SI_\xa4\xb3\x12D\xa4\x04\xc7Z\xe4\x10\xd2\xc6\xae^\xc9\xcd\xfa1\x1a\xbe?i$.H\xbcS\xfe\x077VQ!\xb0=\xaf\xff%\xf9\xc4\xe5\xf9}\xde\xea\xc7\xe5S\xf964\xb1\xa8\xed\xed*'\x91\xcc\xc3\x98\x8fb\xe4\x9e$\xc8\xdc\xc0\x1e{[V\xe4\xbf=\xab\xd7\x8a\x81\xd7\x1d8I#\xd7\x83\x89Y\xc7\xa1\x9b\x98tJ\xcev\xe2\x9fc\x8fnE\xdd\x99\xc3(\xa5\xe6\x0c1\x9a\x99\x81\x87J\xffB\xa2\xe5\xaa\x9cAN\xb9\x9dy\x1a\xb3,\xa4I\x9a\xaf}m\xfc\x9ez\xec\xb2\xe4\x00j\xf0\x96wl\x9c\x06\xef\xaad\x04\x94e\x1b\xee\x05l%z\x08\x9f\x0b;\xe9\x83\xce\xca$\xf6\xe7$\xc6\xf3HQ#|\x0cI\xdbT\xbc\xb3/\x03(\xdbW'\x1f\xb4\xb0=\xd8\x1c\x1b\xff\x05\xd7B\xcb\xf84Y\xa4o\xf2\x18\x8f'\xfa\xfb{\xbf /\xfdr\xa5Q8JS+\xa4\xaa\xd4\n\x91*\xb5\x82\xafJ\xad\xb0Q\xa5V(T\xa9\x15\xe2Vj\x05\xb4C\xb7\x01\xea\xdc\x0b\xdcR=\xdd\xbf\x16\xa9\x17zsn\xc5\x11h\xdc(\xbeD%5\xe1\x86\x9eY\xab\xb4\xd0\xe8x\xd8\xa95\xe7\x8b\xb5\xd3q3(\x16\x84\xb64\xd9\xe4jR\xe4\x9c\x00E\x1dx\xf3\xea\x19\x96\xc1-\xd1g\xc1\x81\xb7\xbb$\x80\xd11\xb6vn\xd1\x06\x0c\x85O\x8c\xa5\xd0\x9b\x05\xb8\x12l\x053\xc6\xc2\x00\xac\x85\x81\x98\x0b\x15\xf6\x86~i\x90\x89\x93\x01\x1aM\x00h:\x9e\xf3\x94\x9c\x7f\xfc\x01N\xb9\"\x10\x92-\x89\xe9\xc9c\x905\xd3\xfa\x0b\x14\x93-\x14|\x1c\x9a\xac\xfd\xc8\x08\xefc\xf2<\x87\xb2p\x16\xf1\x1fV\x8cL\xaa\x15/mX\x1e\xa3\x86\x8aq\x94.\x96\xf5*\xfc$*\xa3\x7f\x937y\x99%r\x90\xfb\xbb\x9d8\xc5\x14\x9e\x945\xd4\xb1\xf3L\xb5\xb9\xc9c\x1d\x10\xb3\xd3\x08\xee\xc4\xe4\xe5^\xa2\x0c\xa9\x83bR[S\xca\xd3A\xc7\xcc\xea\x83L\xee\x15x\xcdc\xee\x98\xbc\xcaV\xa8\xa6\xe1\xb1\x8e\x86\xd3\xdeh\xf99\xe4\x984\x829c\x085\x06\xbc\x9a\x19\xd4\x9cZ\xcd9\xd4\xba\x91\xb6\xcfA\x85\xa3\x8d\xfa\xa4\xb8\x949\xb9y8\xb0\xda\xfe\xd7\xedp(T\x87C\xa1:\x1c\n\xd5\xe1P\xa8\x0e\x87\x82\x1d\x0e2\x92_||\x92\xaf\xd7\xa0\x7f!\xf9\xe2\xb2%\xf9\xc2/v\x97 Z\xc6\x1cXo\xa1\xf8Zn\xa1\xeb\xc1_\xf5\xf7\xd6\x17v\xea\xcf\xb2\xb7v\xd6/4u\x0b\x8b4Ugp\xfa\x8f;\xf7\xae\xc7\xa6\x157\xffDB\xd1\x97\x94B\xda\x94BO0\x9f9K\xff`4\xe5\x03\x9fO\x1ed\xd7\xc8 $\x17\x06\"i\\\xf4&\x0b\xfd\x92\xb0\x86e\xc6\xdbO\x9e{\xe8\xd2d\xf2\x03K\x9d\x83\x82\xae\xa5\x96\xfdG\xa9\xd6\x90B\xe9\x8e\x13\xa7~\x18%K\x96\xd5\xb8\xf4\xf8\x9f\xc7\xa5_n\xb4B\"\xc5[g\xe1G1 \x07\xbf\x8bn\x85^\xb0\xc9s\x92\x94\x1cC\x0c\xd2\xeb\xef\xef\xb5\x82(\xba\xde\xb9\x1b\x0f\x0b\xea\xd1\x9e\xe5$tF\xdc\xdb\xb0y\xff/\xbe\xefk\xb3\xa07%W\xfa/\x8e\x0dmw{S\xfe\xbb\xaa\x1a\x7f5\x07$\x8e\x1f\xebU\xfaQ\xb2CN\xfa|XK rf\xaa'|\x9d\xce\xa3\x98\xcc`z0\xb4/N\x94d\x1b\xfbTCut$\x9f\x05\xfe\xba\xf2\xe5,\xf6\x03\xb2J\xe3\x90\xe43p\x18\xea\xc0\xfc\x02J\x7f\xa9y\xab\xbc\xc8\xd0\xbeE\xceu\xdf\xee%*j\x12M\xf5k\xd5\xc1_c\x8aS\xe6\x1b\xe2T\xd8\xe28\xa0U<\x84U\x81qs\x14\x94\xdcn\xf6\x81\x13x_O^*S\xf1R\x99\x8a\x97\xcaT\xbcT\xa6\xe2\xa5\xb2a%\xc53\xca\x15\xb4\xeeb`L\xa6\x89\x9cY\xe0\xc7\xa6\xfbR.,\xfb\xf8\\X\x08\x87\xf0\x84\xb7\xef!\xebAwO\xbb\xcf\xfa@\x1a\xe8\x84\xd7v\xf0\xa4yYse\xc0{\xa7\xe6\x96\xec8%\x11iK\xfb\xa4Wmn\x19|\xc4B\xa3K\xbf$\xd2\n\xae\xe2\x8a\x8a\xa30*\xbfO\xcfg\xb075\x12\x0bGI\xe4#\xc3.\x86+a\x80`P\x02F\x18\xc0\x13\x81H\x95\xc3\xd8?\xacq]4\xa7\xbef\x96\xac\xcdc\xaa\xd3dx\xb6E\x90\x8cD\x9boB;\x14U\xa2\xb7\xa1#\xf8d\xfel\x8c\xcf\x14\xe7\xde\xa34)6k]\xfeD\xa8\x9c\xd62?\xf7\xd7z@\xe6\xb5\x16\x15\xbcf\xb6\x1e8\x1a\xc2\x1eC\xe5\xb7\x96\xf9\xe5\xea\xb9E\x9a\x8e\xcd\x003\x0ep\n\xbfq\x9d\xefYE\x1c\x0dk\n\x9c\x82o\\\xe759/\xbf\xcb\x89o\x02\xcf\x18\xf8*Z\xae\xe2h\xb9*\x1f\xa5\xa1\xd1\x81,d\xef4R\xf0\x99\xde@\xef\xed\x08\x8bg\xe2Z\x91\x92\xe4\xbfD8[\xfe\xf7\x17OC\x92\x94Qy\xe1\xfa\xdc\xe7<\x1fyu\xd9\x94\xc2\x19s\xd3\xf7\xb3\xa8(Gn\xf7\xc8\xea^[,\xa7\xd9\xe8\x1c\xdb*\xae\xcf?\x9a\x93\xdf6\xa4(\x1f\xd9\xf7~\xddBb\xfai\xc4\xccN*Wq[\xf8,\xc8\xde\x98\xd5\x8c\x0c%\n\xd5\x03}\xfbK\xd1>\x12~=\xec\x05\x1c\xc2\x92\x89\xc7z\xc09\x02V\x07\x85\xd1[\xed\xca\xaa6\xcf\xd3\xf0b\x82X`\xf0zpB\xbf\xf4\x19\xe4\x04c6f\x907#8\xec\xdf\x8e\x92\xfa\xdd(\xd1\xd5\xfc\x1a\xc3\x9c.k\xaa\xa9\xae\xb9\xd8m\xb0\xa7\xa7\xc8\xf0\xc3\x0dpW\x0d\xeb\xa3\x03Q\xb2\xf5\xe3\x88e\x070\x0d\x8a\x93\xdf\x0b\x03\xadk\x8b\x0e+? c\xf2\x82\xdfT\x8f\x9d\xee\xbc\x0b:z\xd5\xc8\x8d\xce@\xaa\x91\x13\xab\n\xa3bp\x9a\x1ej\xca\xae\xee\x8e\x86\x13\x96\x91U_P[\x87\x11\x97i\x9b\x84Q\xa9mX\xd5h1\xa0\xc19\xa6\xa0(\x13\x08\xfc$ 1H\xd6\x86u\x04D%\xb50*\xd5PF\xeck\xa4\xa9(\xd3\xe52&O\x05\x99\xd1\xef\xbc\x87\xe0<\xc2\x1ebG\xe8+u\xd5\x02\xcd\xd2\xb3\x0c\x0e\xa6\xf9X\x95\xeb\xf8 \xd6q\xd8i\xbe\xdb\xf1N\xceKq\x8c\x89L\xb4\xc0\xca\x92\xa9?`\xf4U\xe3\xf8\xbf\xd5Oo;\xf1\xad\x89\xeb\xa9(\x81\xc1\xf9Z\x81\x9d\xad\xe4\xcb\x9a}\xa9L\xea\xd4\xbb\xab\xf0.k\xc7\x9c\xd4\x87\xd1\xaay\\\xf6D\x1eq|\n\xdf8m\x02\xe0\xf6\x04\xe0\xf8\xba\xef\xfd\xfe\xbe+\xbfW\xf3\x17\xca\x1f<\xaaz\x10V\xcf\xdf\xb7\x95\x03\xdb\xa6x\xda\xe5\x97\x9b\x98y\x05\x89\xd9\xfdY\xcdLDU\xde\x10T/\xa5B\xbd\xa4\xd0\x1cQ6\xf9\xe6\xf9:\xbe\x19y%)J*\xceJ\xe1(\x83\x8c\xcbf\x02D\xab\x08<\x84\x84\xc7\x80\xd0\x9e\x9e\x9e\xafYu\xb0\xe6M\x99\xe7P\xb4\x00\x97w~\xef\xf0\x10\n\x9db=\x86C\xd8C\x8e\x0f\x93\x17\xfe\xfe\x9e\x8e\xb2\x903M\xc4+HyLY5W'\x1c\xe1fW\xd4\xb0\x1e\x8d\x9b9\xf1\xf5\x9eH\xc5?\xd7\xb1V\xa1\xd7P\x06(\x12\x9cK\x94u@\xe2\x82\xe0\xdc\xb6\x92\xf3\x17x\x0c\xb8\x0e\xce\xb1\xaa[\xfa.i\xbb\x83L\x88\xacEMc\xda\xcf\xb5)\x0d\x17\xf8\xd97\xad7\x14\xd1I\xafXvK\xb7\xe3R\xae$J\xbcE\xe2E\xc9\x82\xe4\xc7X\xe2\x7f\xe4\xe6<\xdaF\x9dg\x8d\xbe\xb7\xa0h|\x8c=\x16/\xa6\xa8\xefT\xcc\x07+\xb0\xf0K\x1e\x95\xe4E\x12_H\xf3]*\xe6EL{kf\x14\n3\xa1\xf7Lj\x19B=~\n\xf4\xcf\xb5\xa44\x99q\xaf\xf0}\xa2\x90\x90\x0d\x8bOw\xd1i]bc\x0c\xa9|\xdc\xa7C\x06\xee\x92N\xed\x0e\xf8\xe3\x0f\x08G\x0c^\xfa\xf96\x03>\x14\xedl\xe8p\xde%\x98\x89\x82`\xa6\x1d\n\xac\x82\xa3\x84=\xa7Bl\xcb\xe0\xea\x95y\xb4vYA6\xbd!\xb6\xb1\x85\x95ek9\x99\xe8\xc7\xba(\xb0\xb3\xc3J\xea\x8eUh\xa8\xa6k\x0c3+\xd9\xf8;v\x8aURc\xbe\x14^\xc2\xfc\xa8\x0c\xc9\xef\xe5\x96\x8e\xeb\xe9J\x7f\xdd+\x10\xd0\x1f\x0f\xee\xdf\x1a\xfd9\x8a\x10\xfc\xf9\x1c\xc2\x189|\x92\x06\x9bK\x96 \xe2$\x88\x15\x94\xa1\x1cB\x98\x068\x0e\x8f\x9c\x93\xe0Q\xba^\xfbI\xe8:A\x9a]\x98Sd\xc9\xa8\xd4\x07\xf3\xcc\xf0\xb8\x12R\xcd\xb4\x95\x9ck\x88\xeb9%W\xe0\xfd\xae\x0e\xce\xac\x8bK:\x8fX\xee&\xd3\x17\xd5T\xb2]\xbf'\xa3\xd2dQ\xaa\xb3\xcb+\xdb)\xc9y\xe9\xe7D](\x11P\x14CTj)\xbb\xf0\x8ezrs\xe2\x87\x8c7b\xb6q5dk$tZ\xd4\xa0V\x89A[\xc52/\x91\x0bT\xb0E\xf2)\xfd\xa0\xe6\xf7\xebP0\xa7\x7f(m\xe8\xa14\x95\x9dJ\xf4\xc9\xf4\xbe\xecX\xa2O\x1eLUqlj\n$\xbc\xd1N$\xa5\x08(\xe3&\xab?U\xd9|\\gE\xfc\x90\xe4EW$\xa5\xe2h\xe9e\x9bb\xe52T\xc3\x84\x9d\xec\xef\xc9?\x9d\xb1x\x9d\xe5\xd1\xc5\x18N\xfe\xf8o\xce\xdf\xb0zf\x9d\xa1\x08n\xc0\xdf\x9c\xbf\x8dx|\xf4\x06M\x12*V\x93\x9e\xaa{\xfbrTC\xb1Wa@\x0e$9C\xc5U\xe6\x17\x8a\x8dP94.\xc6h{\xea\x9c\x1b\xdd)\xf2HR\xe6\x11)\xa8\x90\x04{.\x16\xba\xa1\xc7i\xe6%\xe4\xbctG#/L\x132\xfa\x9a\x8f\xc2d\x8e\xc4L`6\xd6\x91\x15\xefZ\xe3\xc8\x0d\xc7p`R\xcfS\x9e\xedd\xdfP\xa1b\x8dPS\x89#\xa6\xb8(\x12\xad\x1b\xab\xff\x038\xdd\xd5\xde\xc2\x0dpf\x98?m\xcdW[N\x0b\xfa\x84\x00\x02\xbf\x0cV\xa0>Yc\x86\x11\xb8\xc2}{\xc1{XD\x89\x1f\xc7\xaa\x15V\xaf=\xbd\x98\x12%\xf3\xf8\xa1\xd5\xf8\xed*\x06`h\x0e\xf8\xd6\x89GP\xae\xf2\xf4\x8c\xbb\x07u/\xc9<\xfc\x97\xfa/\xfaA\x8e\x8a\xf34\xbc\x90\xa5\xd6\xa1 \xcez\x13\x97Q\xe6\xe7\xe5\xcdE\x9a\xaf'\xa1_\xfa\xcc\xd1\nG\xe6\xbc|q\xfc\x9a\xfd\xdd\xdd\xbb\x1aNa\xa9\xd9\x8f\xc0-|:\xa7\x8e\xb9f_\x82q}\xaa\xfdy:\xc6\x8c\x1c\xf2\xfd\xc9&\x057\xe7\xc51\xf9\x8d\xefN\xdas\xf7\x14\x0e\xe1\xac\xbb;\x97\xc6\xdd |\xf4G\xfd\x8dw\xca7\xacq\xfb\x01\xcf\xf5qd\xdc\x82\xc0\xb7\xe1\x91v\x1b\x02\x9e\x08|\x0f>q0h>J\x8a\xd2O\x02\x92.j\xae\xdb{\x12\xa1\xb0\xd0\xda\xa0\xe7t\x83\x1e\xfe\xffq\x83z\x89\xbf&\xf4\xef\xaf\xcb\x8b\x8c\x1c\xb2{\xf4'\xdf\xb9(P\xf7\xde5\xeem\x90\xe25X\xedq\x10\x98\xb4?F\x8c\x91\xdb\x05m6\x9f\x1e\x9f\xe8\xb5\x87\xc1\xfcg\x8d=\x7f\xa6\xdf\xf3`\xd94\xf0}x!\xf6\xfe|\xe8\xabe\x0f\x1b\x94\xb7#E\xb5 \x84\x97\x13t\x07uo\xfe\xeb_\xc9\xcd\xe5\x18\x1c\xa7\xab\xd8\xe3\xe3/e\xe5\xac\xdb\x1c\x8d\xcf\xb9\x93[\x8aJz\x9b\x8f'\xc4^7F\xefK\xcc\xca\x97\x98\x95O\x11\xb32 Z%B\x95c\xb0\"k\xab\x9a\xd7\x0dp\xab\xcf\x0b\xf1#29\xd5 c\xa0.K\x1b\xb3\x072\xbeD\xc1/\xa0#\\U_\xb0\x1e\x19\xe2J~\x0dCiZ>\x98\x97\xad\xe3-Q\xde\x148\x01\n\xeb\x1f305\xd6\xff\x9aV\xf0n\xba\xa7\xb1\xd0\x17\x8e\x82H\x9b\xf8\x10\xebr\xdd*p\xcc\xa3\xdb\x1b\xb3x\xfd\xf2c\xff\x00\xca7\xbd\xd2\xad\xea\xbc~_\x91\xf64\xec\xa6\x993;\xae\xd4N+\xbcW\xc3\x95h\xc6\x94\xa3M\x1d\x17o\xc5T\x0e\xf2\x98wF[\x89\xc5\\\xe7[Q\x8c\xdb\xa8\xf6R\x16\x8a\xe1d\x16E\x92\x01u\xfcL\xebdY\xb2\x9b\xf7\xce\xa0Z`\x85\xbd\x95 \xb6%\xbbM[jw\x05\xdf\xf5\x8c\xaf\xf9\xc2\xf7} \xbe\xef\xcfg`\xfa\x14gF\xcd\"\x99\xce\x0d\xcb\xb0\x82|@\x90\x00s\xb1\xa8\xc2\x17\xf91\xac\xd1\x96D\xf8\x02'\xf6\xe6\xd8\xd8\x82\x04\x9b<*/\x1e\xd3}\x1d\x95\xa6Z\xc7t+\xe5\xc6x\xdf\x98A\xf9\x9br\x95\xe6\xd1\xbf\xc9\xf7%\xa5\xb0{\xdd@\xb6\xe6\x15\xb0W\xc4Qx\x05\xf60\x8c\xd4\xe5\xc5&\xff\xf8\x03\xfd\x9d\xae\xc4\xea\xc5\xbax\x890\xda\xcd\xb0\x96\x8a+\x89\xa3m\xce\x86z\"\x02m\xd7\x9a\\\x91>\x84\x94u\\\x9b\xdf\xaa\xb1\xad\xd4\xc6\xae\xcaAX\xb7z<~\xbaJq\xf5\x1f\x9b\xeb\xea\x93zo\xc8\xe3T\x03\xb7ht4P\x1f\xad\xd7\xd9wC\x15Xj\xad6\xd9~\xf8\x80\xd2\x88\xfbP\x89*\xf4\xa1\xc9\x87\n\x1a\xf94\xd2\xe45\xbe\xcchD\xfb\x9e+n\xac\xd3\x90\xc4\x942\x8da\x8f\x07\xaaz\xe4<\xf3\x93\x90\x84#\xa1\xea0\xb8\xc6\n\xf8Y\xff\x13\n\n\xd0\xdf\xc3\xf2\xe9\xdd\x98\xb4&\x18iW\xb5&\x87\x89\x11&\x10S\xc8\xe3\xc8\x94\x1a*S\xb8n=ZE\x9f\xba-\xcd F\x99[\xac\xfeK\xee$\xd8\x86\xeaOI7\x9a\xf7\xc3\xf0^6\x11\xbc\x1f\x8e\x0d[E!9&\xf1\xe2Er\x84\xd3j\xe2\xc5\xf4+\x0d\x15\x1bV\xa1\xb5B\xe7C\xf7D\xd2\x89\x07\xac\xf6F\xdes\x0c\x85!\x1a\x90\x0f\xad\xfd\x11s\x80N\xf0\xf5\x94T\xa3\x19\xb4cw\xd8\xaa\xb6\xf3\xf0 \xb8z\xd4\x82\x98p\x08\x991\x956P\x98|\xaa\xe8\xcd\xfe\xfc\xb2U\xe8b\xae.\xdcl\x88F'\xc1\x0c \xea\xf2\xb6\x0d\xb5\xde*\x8a\xc3\x9c$\x943\xfa(M\xebB\x0d\xcd\x0d\xc9\xc2\xcc\xaasM\xc3Q\xdaxi\x05\x9b\xbc@\xa5[\x96F\x892_\x1c\xf4\xb0\xb7\xba\xcb$\xe7?\xed\xe0v\x1fX\xab\x92\x04%\xaa\x1368\x8c\x8b\x95\xed\x12\x1eP\xe4\xd4\xc7\xa0\"|\x17S\xf6\xcb\xbf Ar\x985a\xbb\x87\xa7\x91J\xf5\x85\x02\x990\xb0h\x1d\xd1\x92\xe8\xb5\xee\xc1\xee\xfc\xeey\xde\xfb\x0e\x89k\xb0C\x1d\xaf\x0f$O\\\xf8i=\x10GO\x9b(v\xdc \xbb\x14\x87~\xbf\x1e\xd2\xf83\xf0\xf9\xbb\x96*\xc11\xfb\xa10\xdc_g\xe5\xe0\xe7!\xc1\xf8A\x19m\xc9k\x7f>\xc8VZ\x99aC\xbf\xf4\x0bR\xa2G\x8e\xfc\xc8\xb6\x92Q\xaa^\xa8\xd5\x12\xbd\xdb\x97\x13JP\x13\x98,\xa2\xa5\x02\x8a\x89%\x86\xc0\xce\x00\x13QW\xb9\x86\x9fS\n\xfc\n\xf9\xaa(Y*E\x18G\xc4\xef#\x8b\x18\xa0k\x1b\x12\xef\xc6\x0d\x97~\xba\x02\xb4HS\xd4\x98\xc1\x98R\xf9\xaa\x8d\x99\xc4\x83\xefc\x0b/W\xc9j7\xb2\xce\xb0-^\xffIg\xafq8\xb5\xe0ly\xef\xc6XG\xee\xc4\xd1\x90\xefG%Y#\x9fY\xd3\x9a\xc3\xc3ff\x9d\xc6\xd9\xf2\x10\x1c\xbe\xb3x^\x96\xc1}\xd3\x07\xadt\xba\x16G\xc9;U\x860\xa8\x92\xd9\xf0$8\x8e9\x9dJ[~\xa8\x86\xa5\x1aDD\xc7{\x14F%`\x8c)\xcb\xbe\xc1\x1a\xe1wX\x154\x8dqd\xd7\xa5\xe0\xe7\xc8\xf5Z\x08\xda\xb3\x88'\xe7i5n\xbbBlTW\xb6>l\xc7\xd6\xb9P\xcc\xb1Y<\x92\xcb\x8c\xe8_}\x05\xe9\x18\x8c\xcb\xa0\xa9\x84\xa65\x071b\xab\xad\x94\xd2.M\xa2\xa1\xf55 \xd5\xa6;h\x1d\x06\xda\xc4'\xa4\xa6\x993\xd0\x14\xb3\x14\x14Y\x97\xef\xb4\xf7\xc0(1~\xdef\xa4\x05\x15\xb1z\x12S\xca\x9f\xf4\xa4\xb2H\xbc\"\x13\xbe\x162\xa9l\xc3\x1f\xf4\xda(\xf8\x83\x9eT\x16K\x0dL(\xfe\xb8qS,W\x1b\x98\x16\x1f_<\xcbl\xc53\xbd\xcfn>\x06\xbf\x7f\x92wy\xdfk\xe3\xb3+\x92\x84ozb\xa2\xc2g7\xed\x8b\x8az\x9f\xdd\xbc6X\x1d\xb6\xb7\x8e\x8aG\xcde\x89\xe3\x01\xabE\xc92\xca\x17\xab\xf4\xcc=a\x94\xb3p\xc6@\xde\xd2o\xf7\xe9\xc0\x989Q\x8c\xbb\xe3\xa5+f\xe9\x0dSH\x85\x1a\xdfN\xa8\xb9\xe6\xbc\xbb\x0dc\x9c6\xf8V\xdd!\x1c\x19B\x9f\x9a\xda\xf8\xe6\x92V\xc7\x05J\xb2Q\xdb\xdb\xb7\x03\xe2E\xc5\xf1*=K\x9aK\xdf\x80\xa6\x1c\xc0[\xccB\xa0?\xa0\xed8\x12\xa6\"\x9d\xa7\xe7J\xdeX\xd5L:\xeejX~o\xa9\xfbu=h\x1e\xb4\xc6\xe3\x93\x84Z\x0f\x8e\x90\x9d\xae\x9ax\xb5ZYY2'P\xf6\xa7\xa9]~l\x97]C\x16\xde\xa7T\xa3\x9f\xf5\x06v<\xabc\xe3\x19\x9d\xe1]\xc3\x19\xed\xea\x1e\x82\xf2\x10\x07\xbe\xad\xd0^\xe2\xf06)g\n%\xc6\x9c\x89^\xcc\xa0c\x84\x16G5\xe7\x02\xfc\xa2\x88\x96h\x931\xeb,\xaa\xe3\x806<\xfd\x1aJ\xf8\xa6w*|\x0d%\xa5\xfcj4\xda\xf2<6\xf5\xa1Pj\x82\xed\xaa&s:\xb4d$\xba]%\xfd\xf6V~\xf1\xe2,\x11l\x0c\xd3\x16b\x04\x02\xeeZr\x92\xd3\x13(9\xc9\xdf\xdaF\xc2B\xe3x\xef\xe3D\x1f\x01S\x1bw\x89\xea\xc4&\xda\xc3\x06\x9aCN\xd8\x81\x9a\xc07PV\xb3\x9b\xe8g\x17\x1a+\\\x9e$\x860\xc6\xdc#\xc9fMr\x7f\x8e\xe7a\xebO,&1\xc6\x9a\x88t\xd3o\x04\xd0\xde\xfe\x18x\xf64\xba$X8\xd1\xcd\xbd\xb3<*+\x88\xd1X\xc1d\x12\xfa\xc1w\xe4B\x1a!\".\xdb\xa0<\xa8\x17\xaa\x9a\xff\x92\x87\x9fh\xa6\xa8\xe27(\xeb\xe66P\x89\xee=^ \x12\xd3B\xe5\xbd\x9c\x84\xe2\xea\xf7\xe5\xbd;\xeao\xb3\xc8\xa8\x8c\xae\xd0\"2\xd5\xb9\xb2\xe2U\x80G>\xee\xb9\xa4\x19\x92Z\x8eD$dB\xce\xe0\xf5EF\x8e\xf2<\xcd]\xe7\x91\x9f$i t\xcf\x80\xcf\x8e\x18\xf0\x0b\xf0\xab\xd6T\x825g\xcbT \xf8\xa014c\x87At\x9a4{\xf9\x8a,HN\x92@t\x956\x08+\xbfH\xfeV\xc2\x9c\x90\x04\xd0\xe5\xd4\x8f\xa3\x82\x840\x81b\x93\x91\xdc\x1d\xb5 \xe8\xb0H\xa8+\xb9\x0f\xf5\xfc\xee\x95h\x97N\x11m\x1d\xd8;\xc4\xcc\x9dt\xf2\x90\xc0V\x13\xd2z\xc2\x98}9\x8e@c\x9e\xdc\xa8\xcd\xba\xf2\xcd\xb1$\xe5K\x81|/\x16nd\xe9\x1e\x0dR\x0c\x1c\x82'\x18\xa5.\x1f\xd2W_\xb1\xc21\xa8\x84V\xa0\xcd1\x9dlz\xe0\xe6\xa4((\xf6\xae7E $*W$\x879a\x1fH\xf3\x06\x1e\x8d\x81\xe2\x99\x037\xaa\x86\x14\xabB\xea\xedX\x9fQ\x8c\x87q\xb1s\xad\xfd\xaaa\x97\xd2\xa4(\xf3\x0d\xe5\xcdL\x96o\xbb\xf8\x8c\x9a2\xea\x8b'\xd0K\xd0\xc2\x996b\x1fX7+\xda*M\xc9'.\x05M\x1cq\x87 \x97\xcfT\xd1\xc2(x\x08\xd2\xfb\x1c7f(\xb9\n\xb4<\x94\x8a)n4\x86\xa62b\x0c)\xbd\xa5-\xd7P\xac\xd2M\x1cV\xef\xbc\xc1l\xa5\x96\x95\x03\xb4\x019\x82\xf5\xc0\xed\xa1\x9d\xd7T\"\xaf\xc2\xb70\xa5s\xd5H\xeeY\xf3 \xd3\xb7\xf0\xb0\xfd\xe7\xacg\x1a\xef^Q+\x01;\xdd\xd7\xaa\x02P\xd0\xa03\xcc\x9f\x81\xa5p}\x910\x1f\x80\x9a$\xbc#\x17\x85\x9b#WNZu(F#\x8flI~Q\xb3\x8b\xdaC\xae\xd1b\xe2E\x05\xf2Ac\xb6y\xb2B\xc9\x0c\x01\xe2\x14\x1e\xfd\xedn\xa2\xb9I\xd1\xcf\x94\x9e\x03\xfd\xeeiW\x12:\xddKO\xa8\x9c\x1c\x9d\x10m\xc7\xe4{\xa0\x8f\xb4\x94S\xef\x18\x06\xbb\xc73\xf1\x9e\xae\xd7\x1b\xdc\xa5\xad$\xc3p\x08\xd1\x18H\x83\x89\x8f4\xbc\x8cNa\x06R\xa5\x19\xb4\x07\xf2\x9e%\x88t\xf7E\xdd\x1d|r\xdd\xb4z\xa14WR\xca\x9f\xdc\xef)\xe9\"\xfe\xa4\xa7\xef\xf3\xf9\x83\x9e\xbeo\xc3\x1f\xf4>U\xf0\x07=}_\xcc\x1f\xf4\xf4}\x81T\xdf\xb7@\xf0\xa0s7\xe3\x1f\xb9\xd7t*\x08\xd5\x8a\xc0\xf0\xe3+\x02\xf5e\x8c\x86(\x02\x15\xc1\xfb=\x97\x0c\xad\"0\x96*\x02\x83J\x11\x18\x8f\xc68\xd7\xfb_\xc3\x02\xbe\x81\xf8kXP\x81%8Y\xb4\x15\x81\x0b;E`a\xab\x08\x8c\xec\x15\x81\x01W\x04.yd\xb2\xff=\xaf\xa9n#\xc7\xf1>\n\xdd_\xcb\xaa\xe0E\xc5\x8b\xef\x8eoa\x01\x87\x93\xdak\xa0p\xc6<\x1e\xc7/\x1cz\xae\x9c8a\x1d1\xe5\xbc\xed\xb5\xf3\x9e\xf7\xeeQ\xc7\x13l@\xff\x1c\xe8\xab\x86\xf0\xb3,\x11\xde\x15h@\x15\x8aN\xce\x8f4\xe7G\xbc\xc0\x93\x1b\xbe\"E\x1aoIx\xbc\x99\x979!\xeeI\xb50\x1d\x85\xaed\x85\\\xbar\xf4\x900\xa5\x17(Z\nU\xdb\xf4\x02\xb1T\xa1\xba\xf9\x04\nU\xbd*\xd5F\xe5\xca\xb2\x1d:\xfaa3<\xcf\xfd\x80\xa0\x8d\x18\xb8#\xb9\xaa=F\xb8,\xa9\x90\x1dE\xb4\xebb\x94$$\x9f\x18z\xa7l\n\x1d&\xad\xdb\xda\x0d\xe1\x9c\x12k' z}\xa4\x99#\xa7\xcc\xb5\x9d\xb1\xcb|\x96\xc6\x98\xf8\xec/w\xef\xde5h\\\x17iR\x1e\xb3o:Q\xe9\xc7Q\xb0C\x9a4\xf5`\xc2\xfa\x90jp\x893GG\x99\x1a/\xa9`^h\xa7(\xdd\xe4\x01\x99\xc1\x91\xbc\xbb\xa3Q\x8d\x80\xe7\x94H\x9f\x8b<\xd0\xe7J\xc3\xb4\x95\x0fw\xc7i\xcf\xa2\x8e\x1b\x0bi2\xd9\xae\xd1=\xe9dj\x80\xa2\xf2\xe4\xa9\x8b\xa7\x8e/\xd8\xf2,'\x81_\xea\x99X\xe0\x02\xe6\nm\xa9^T\xa0I\xf5\x1d~\xe8\x9d\xc7\xad&\x85\x9b\x1b>\x91)\xf3\x1f5\xaf-\xe5\xdc\x03?\xfe.\x8e\x96\xc9\x0c\x9c2\xcd\x0c\xf8I\xaf\x8cr\xff\xc9\xf2\x15\xf7\x9c\xd8\xf7\x0e\xc8\xda\xc03\x1amQ,\x026\xf3(\xfe\xff\x82>\x19p\x08\xce<\x8dC=n\xeaw'\x08\xad\x84&\x0d\x04\xb4I\xca\x86G;Vk\xa5\xde~\xa6=\xa3\xef\x17\xa7\x1c\x99\xee\xfb9\xe7dv'\xcc`K\xa3\xa0A\xa7r\xdd\xb0AIy\x80\x1f<\x7f\xd7s:\xf6sc\xee\xb1\x0c\x81w\xef\xb9\xaa\xcb/\xc7\xddT\x00\x16(\xc7\x03\xbd\xd0V\x99\xc0\x0dp\xf0WN\x7f\x9d\xd2_\xbe\xae'F7\x07!\x0f\x1b-\xf1m\xbf\x00\x83\xd5\xab!\x9b\xf1:\x84\x0d\xcd\x00\x86+\x9a\xdb\xe2\x0e\x02\x81\xa1%\xeeIa\xf0 \xe0Q\xdc\x0b\xb8\xa1\xb3\xa8\x8dd\xd62\xf6\xa46\xa8U\x87\xcc\x99\xf1\xb8\xe7'\xe4\xff\xfc?\xa7\xfdV\xf9\xb1\x0f\xa4\xc4\xea@J\xf9\x81\xa4&\xb2\x18\x8dw>\xe1%b\xbd\"\x8e\x02B{s\xa0,\x08+\xae-/\n\x99\xc2CH\xbd2\xfd\xf1\xb8\xfa\x81S\x9a\xf2 \xb2\x8a\x80\xbc\x0c\x19\x07\xb1\xaf,\x1cU\xac\xc9\x074\x99\xb3{\xf7\xee\xe9i\x07h\xe9\x07\xd8\x1c \x0c\x97\x92K\x92G\x18:\xc6\xc1d\x12l\x86\xda\xf1\xfc\xf3U\xbb\x10\xd4\xbc\xaal\x7f\x1e\xd3\x13\xefX0\x816;\xd5f\xce\x9do\xe0\xef\xf0\xed\xa59]\xc9Q`\"\xd75\xa9\xd6EuZ\xd3\xe9>\x8d\x1e\xaa\x8c\xb5$\xd3\x82D\x1f\xabA\x8c\xe4\x19Is\xb5\xb2\xbf^\xe5z\xa2\x0e\x0c&\xdf\xda\xae\xe8\xaf\x1d\x8am\x88\x197\x91,\x1b\x1f)\xa4W\x9a\xd8\xed+E3\xb0F5\x18\x82n G9T@\xa2\x89\xd2\xdc\x8c\x19\xd5\xa0\x81n\x06\xa7 #\xca\x01(\x92\xad@W\xda\xfc\xe9*\xd1\x11U\xaa\x03\xd0\xf1\xa7/\xe8\xd8\xb8.\x89\x8eL\x9f\xfd\x99\xa3\xe3\xab\xabD\xc7$-\x07 \xa3\x01\xad>\xbf#\x11\x0d\x14Wv\x02\xbe\xba\xec XW\xff\xba\x94 \xa0\xaf\x08\x0e\xe2\xb4\xd0\x94K}\xef\xec\xe0G\x98\x19\xfd\x08\x99\xe1\xee\xba9Pe\xca\xcc\x90\x99\xd4M*\xe2O\xa41\xe4\x99*\x86^z\x971\xa8\xdc\xbc\xac\xdc\xc6\xa0\xf2\xf42\xbbR\x01W\xe1G\x83E\xffd&\xf4\xb7^\x94\x84\xe4\xfc\xc5\xc2\x95\xa4\x12j^\xa6\xd8\xa0%\xcf\xeci\xe1\xfa\x03\xdci\xac\x1c\xe0\xd6\x03\xdcw\xcc&y(p\xe7\xb1\xd2u\xc4\x81h\x02?\x83C\xd8R\xd2~\xb98\x17\xd8\xc5\xbb\x02\xe0\n\"l`wg\x06`\xedo/\x13\xe0d\xd5GK;3\xe8\xe7C\x1b\x9d\x0b\xb5\xeb\x82!\xc4\xaf\xf6L\xf0\xe1\x9bC\xd8\x18\xc8L\xbf\xc2\xd3\x89\xe7yo\xb5#pN\x9c1\xac\x85\xdem\xbd\x9b\xae\x1b:\xfa\xeef\x90\xa9Y\xdf\x0d\xd6:o\xa8\xcc\xb5:\xbd7\x98q\xc1\x18\x97\x05\x95\xe2\xb96\xe2\x98\xfbF\x8f\xd0\x7fX\xaa\xab)\xec\xcf~l\xb4R\nX\xceB\xc9+\x1d\x8aK\x91\xcb\x8a=\xaad\xce\x0c\x1e\xee\x1ej+\x0c\xfb\x1a\x13&m\xa9B\xa9K\xc5\x1b\xb6v\xa3\xa0\xda6C4\x11\x01=\xd4\xfc\x12\xe9\x8c\xc1>\xa51\xb4\xa4\xd8\x80K\xb1V\x078\x0bvN\xb4\x9ex\xd0\x10f\x0d\\\x87\x9dh\x0e\xb5\xe8\xeb\x1bU\x1fcpZ\xf17\xad\xe7\xbd\xbb\x1dy\x14o}\xb6\xb1mr\xc93UI\x9e\x91J\xf2\xf4U\x92\xe7F%y\x16*\xc9S]\xad \xeb\xc5qRy\xd4\xcd\xea0\x9c\xe9\xfe\xe7\"\x80\xde\x9d\xd3\xff]?\x19TR\x14\xa1/\xf4)e\xd0\xf4\x03\xc8\xa0;\xe6\xf8\x87\xeb\"\x83\xdaH\x89\xc9@i5\xddAZ5\xcb\x8a\xfe0Yqc+\xda\x16\x18D\xdb\x0d\x15\xd1{\x03\xb0d\xc4{\xe8\x9f\\E\xa4\x18J\x07\xa0\x06S\x9f\x0d$n\xc4yP\x81\xce\xc2K\x8d\x83/\xd2|\xedk\x95\xb6\xc0\xb7#\x7f\xe1|m\x94\xaa\xb654F\xaa\x1a\xc0\xd7\xd2 \x15\x9f\xfec\xc8\xa7\xb1\x1c\x1c|\x03\\\xa8d\xe1vKR\xd6\x0bG\xf7\xb6\xfeE\x94,\xafL\xf2\xc6\xa9\x19C%\x81\xf3\x95\xb8\x02\x11\x9cw\xf1\xa7\xb4\xdc\xb9\x97\x17\xde\xca/\xcc-\xe9\xe7\xeb\x14\x8fe\x18\x83i.)Y<_\xc7\xe8\xfa\xb7\xfa\x0f\xd9\x13vS\x07;m\x0c\xe3\x84\x83\x81\xf1h\xae\xbd\xf3?\xff\x8f\xfe\xcf\xc1\x14\xe2\xce\x0c\x9c1\x1c\x97y\x94,\xddT\xe7M\xdaL\x94T!\xe8Vw\xe6\x9e\x99&\x83K\xaa[\x03\xa7\xdf\xf2II4=\xbc\x9c\xc2\xcb\\\xfa\xeb:(\xbc\xc6Pz\xe2}I <}\x86\xa7k\x91\xe0I\x14Qj\x8d\xc3&\xd3\x13?\x1e\xfa\xd8\x92T\x8f\x7f\xf6%*\xd9\xb4z\x8c\x87\xc0\x15ef\xe2{\xb2\x97\x0d\xc9*\x05S\xd9\xd9yI3W\x92\x1c\xf9\xa2k\x80|}<\x8be:\xd5\x94?\xe8\xe9T#\xfe\xa0\xa7S\xf5\xf9\x83\x9eNu\xc3\x1f\xf4t\xaa\x05\x7f\xd0B\xf2X\x8d\xe4\xf1\xc7G\xf2\xe0\x8a\xb2\x14\xa5*\x05f\xcf\xbbF\xa6\xc0\xcc\x87+0\x95Y\x8a6R\xc5edR\\~\xb2,Ei\xf2:\xbfH7%\xa6\xdfV\x03'\x1c\xf8\x91\x9f\x04$6\x00\xe7\xcc\xab%\xf1\xe71 \xb5\x01\xfe\x86\xba\xdd\xea\xb3\xb1U\xa8<\xbf\x98\xa4\x1buT\xb7\xb6R\xfb|S\x96\xf6Y\xd1\x9dy\x99\x00o\xef\xf4\x94\xfe\x11\xe0\x84\xd8\x147\x97\x1f\xcb\x94\x0fd\x93\x8aa]\x1f\xaa\x9f6\x1dT\xd4\xfc\x1b\x83\xf3:\xbf\x80\xa8\x84tS\x82\xccdfp\xdd\xd4\x17\xf7\xaeX#V\x12\xaak?i\xe1\xe7\x0c\x9e\xf0\x1d\xd0\xa8\x86\xd6\x01o`\xa8\x19\x9c\xe3\xe8\x0c\xf6jc!&\xc8\xa8\x0f\x95\xebYp\xfc\xcb\xa1\xf2\xe5P\xb9\xbe\x87\xca\xfc\"\xf3\x0bC\x91\x16\xe2E\xc5\xf1\x99\xbf\\\x92\xfc\xc0t\x94\xb0\\?\x1a\x12\x86P~\\\xa4\xc7\xab\xf4L{\xe2\x94\xba\xc3\xa0\x19XP\x8f\xd6\x0bVQ\x1c\xe6$A\xa1\x0e\xcb\xfc\x98?bG\xa6\xb7$/\xa24\x99d\xb9\xbf\\\xfb\xca\x13,\x1d\x7f\x88\xe6NO\xd7\xa4(\xfc%\x01\xc5\xfd\xc9\xc4_\xcf\xa3\xe5&\xdd\xa8\x0b~X\xcd\xa5\x12hu\xab\x0e\x0ey\x83\xb4\x18\xca\x14\x18\xc6\xe2\n@]\xea\x06\x13\xc7\xa8>\x94\x99\xdb\n\xd2\x90\xd4\xad\x15\x0c\xf5X\"V? \xa9\xa4a\xf9j\x9a\x91\xc4\xcf\"\xf6\xea\"\"qXP6 IK\x98\x13\xc8rR\x90\xa4\xc4\x8a\xd4+\x02\x85\xbf&\xc0\xf1\x1c\xd2\x1c^d$\xf9\xee\xe5\xd3\xc6\xb8\xeeY\x8e\xdc9\xdedY\x9a\x97$\x14\x0b*z\xe7\xe7d\xc0\xf8\xf8\xd4\xa0\xf0\xf57\xe7\xc0\xdbw\xfeV\xcdR\xb9J\x0b\x02\xe5\xca/a\xed\x97\xc1j\xc0g\xf9\xb4\xcd\xe0\x96\xb7\xef%l\xf6\xdcE\x9a\x039\xf7\xd7YL\xc6\xbb~k\x1f\xbf5\xf2\x1c\x11\xd3BI\xb0\xc5\x16\xd5\xee\xf3\x0f\xb0\xdf\xae\xdf\xf6^GE\x11%\xcb\xcfgs;\xafWt\x87\xa5\xdb($a\xe3u\x08SR`\xad\xdd\"#A\xb4\xb8\x00\x9f\x1eoQg'X\xef$\xbe#\xa3$\x8c\x02\xbf$\xd5\xd7$\x1b\xb9\xdd\x00|\xd9\x83\x97\x11\x10Z5I\xed\x85\x04q\xf2\xcb<\x0e\xc5\xa6\x96=c|\xca\xe7\xc7\xfd_c\xd5\xe5\xe0\xdc\xf4l\x97\x0c\xd48\xae\xfd8\xae0Q \x96\xe5\xf2\x9cm\x12\x9a\xd9u\xb7\x03\x07\x13\xb6\xe3\x7f\xafY\x92v\x8a\xa0\x8f \xc9\x9eE\xc9\xbb\xcf]\xbd\xdd\x18\x87\x0d\xb2pq]\xa9\xde\x96F/1\xe1\xa0$\xe7\xe50$\xf3\x8d\xb8\x93\xa4\xa8\xe1\x96\x88V\xb5N\x05\x1e\x1a<5\xa11\xd9^\x96\x93-I\xca\xc7\xacG\xae\x84\x92*\xf3\x9b\xae\xb0\xa2[\x89\x15\xddn\xb2\xf4N\x0c\xb4\x8b\xd9&=>\xdbT\xe9g\xa9n\x1f\xe3j\xf7\x1d\x89)\xb6\xb9\xb8+F\xacLk\x0b\xa1s=B\xe7\xed\x19\x94O\x86R\x8a\xe6k\x1b\xd9\xb0RJ UU\xc1\xf3u\x9c\x143pVe\x99\xcdn\xde<;;\xf3\xcenyi\xbe\xbcy\xb0\xbf\xbf\x7f\x13_\x93\xbf\xf4\xcf8J\xdeI\xdf\x9c>x\xf0\xe0&\x16 \x94\xbc\xabM\xf0\x93\xa5\x05rc3p\xfcy\x91\xc6\x1be\xf9{^\x05QQ\xbcF\x94?\xdc\xef\xa3\x7f\x17\x99\xd5\xd3J\x16\x85\xc5\xbc^\xac\xe7i,\x9d\xdamD\xce\xbeO\xcfg\xe0\xec\xc3>\x1c\xd0\xff\x93\x0c\x06\x0bNm\x928\x0d\xdeu\xd3\xd3\xe9z\x97\xb1<\xe0\x12\xa4\x9b\x81\xf3|z\xc7\xbb\x0f\xf7\x7f\x98\xde\xfe\xf9\x8ew\xf7\xd1\xf46\x1cx\xf7\xf6o\xc1\xf4\xc0\xbb{\xf7\x0eLa\xba\x0fS\xb8\xe7\xdd\xbau\x1b\xa6p\x97?\xbd\x0bw\xbc\xbb?\xdf]\x1dl'\xde\xfd\xfd\xe9\xa3\xfbp\xcb\xbbw\xe76\xdc\xf7\xee=\xb8\x07\xb7\xe8K\xb7\x82\xa9w\xb0\x7f\x8b\x0e\x07\xf0\xd9\x01\x1cx\xd3\x07\x0f~\xbe\xff\xc3\xed`\xe2\xdd\xb9s\x0b\xf6'S\xf0\xee\xde\xbe;\x99\xc2\x14\x1fM\xef\x05\xfb\xe0\xdd\xb9\xfd\xc0\xbb}p\x9f\xde\xbb\xf5\xc0{p\x87>\xbd\xb5\x7f/\xa60\xf7\xbc[\xf7\xef=\xba\xe3\xdd\xbdw\x00\xd3\xfb\xde\xfd\xbbS\xb8\xeb\xdd\xb9\x03\xd3\x07p\xcf\x9b\xc2\xf4\xc1\xea\x8ew?\xa0\x9f\x80}\x98\xd2\xcfL\xe8W`J\xbf3\xa9>swB\xbf\x13xw\x0enO\xbc\xe9\xdd{\xde\x83;\xb7&\xde\xbd;\xec\x07m\xee\xee\xcf\x0fh\x97\x1eM\xef\xc1}\xdaG\x98\xde\xf5n\xdd9\x80\xfb\xc0&\xec\xdf\x9d\xf9\x1f\x8d>\xf8\xca_\x9bu\xff\x93\xac\xe0\xf3\xe9\x01\xdc\xff\xe1\xfe\xcfw\x10l\x10\n\x7f\x82\xd5\x97\xe4\xb9\xb8\xc4\xe2\xdf\xf6n\xdd\xbe\x0f\xd3\xdb\xde\xfd\xdb\x0f\x82\x89w\xfb\xee\x03\xfa\xff\x93\xa9wp ~\xdd}p\x0f\xf6\x9fQ4\x98z\xf7\xa7\x0f\xe2\xc9\x81w\xf7\xce\x94\n`\x07\xdaW\xf0Q\xe3\x1f\x04\xa0\x98B\x1f\xc7\x07\xde\xbd;\xf7'\xb7\xbc\xe9\x9d \xfd\xf9\x00\x7f\x1e\x04\xb2\x97\xee\x8b\x97\xaa\xdb\x80\xb7\xc5\xcf\xaa\x83\xf7\xbd\xe9\xfd[1vor\xcb\xdb\xbf5\x0dto\x80\xe8z\xf5\x9ca\x1a\xed\x1d\xf6\x89b\xc2\xf4\x0e]k\xf1;P\xbe\xf2)0AY,\xf7\x12\xf8p\xcb;\xb8\x03\xd3\xfdgw\xbd\xe9\xfe\x038\xf0\xee\xdc\x0f&\xde\xc1\xdd\xfb\x13\xef\xe0\x1e\xffqo\x1f\x17\xf7\xc1\xbd\x07\xe2\x81wo\x7f\x8a\xff}p\xf7\x01\xec\xc7\xf7\xbc\xfb\xb7\xe0\x9e\xf7`\xff~@!\xbc\x83{S\xfc\xef\xbd}:[\xf4\xc5x\xd2\x80\x99\x08 \xfa\xe9)\xb6\x83\xdf\x11\xed\xd2\x15\xec4\xfcL\xf4\xf3\xd3\xce\xfa\xa4\x1fyy\x89\xa9\xbf\xe7\xdd\x9e\xde\x07\x9c\xf8\xc0;\xb8w0\x11\x93\xc6~<\xb8\xf7\x00\xf6\x0b\x9c\xcc{\xfbS\x9c\xc8\xbb8\x91\x0f\xf6\xef\x03\x9d\xce\x00\x97@\xcc\x14\xfb\x81/q\xa0I\x05\xd4XQ\xfc\x14N8[\x81~\x93\xb8\xf3\xe9t\xc7\xd8\xc1\xc9=oz{\xfa\x81\xe6\xfd6\x1c\xdcV\xcd;/\xcbqe\xd3\xfd\x00\xeemo\xffp\xc7\xbb\x7f+\xbe\xe5!)\xba\xf3\xe0\xd9}\xb8\x1bO\xee\x02\xfb\xdf\xd4\xbb=\x9d\xd0\x7f\x9eQ(\x98\xde\xfa\xe1`\xfa\xf3\xbdO0t\x16\xf1~e#\xdf\x87\xe9\xfd\xd5\xed\xed\xe4`5\xb9\xbd=\xf8\xf7\xf3[pw{\xb0\x9a\xde\xff\xf9\xee\x0f\xb7\xfe\xbd\xbe\x05\xf7V\xd3\x83\xed\xe4\xe0\x87\xbb\xdb\xff\x8f\xbdw[r\xe4F\x16\x04\xdf\xfb+\x90l\x9d*\xb2x\xc9d\xd6E\x123\xb3\xb2\xd5j\xe9\xb4\xd6T\xdd2\xa9\xfa\xcc\xce\x90\xacj0\x08\x92\xa1\x8c\x9b\x10\x08ff 5\xd6\x0fk\xfb\x03\xbb\x0f;f\xbb/\xfb0k\xf3\xb2f\xfb\x0b\xf3)\xfd%kp\x07\x107D0\x98U\xea\xd3\xe7LS\xb2\xca\x08\x04.\x0e\xc0\xe1\xeep8\xdc\xcf\xeb\x9d\x1d|\x1c\xc5\x84Q\x18D\xfd\xf3O\x07\x13\x9a\xa6\xfe6\xaa\x9f+G\xfd\xe9\xd9Y\xd5\xa6\xd47\x1f\x9e9\xce\x95\xd5\x87\xe9s\xc7\xb9\xb2\xfa\xf0\xb4\xbaCK\xf1\xc3\xf3j\x13\x81\xf3F\xa5\xdd\x9b\xa9\xba\x9e}\xee0u\xdddA\x80\x9f\x9f\xbb\x82\xedxq\x18\xc6QH\xf9\x8d\xce4\xad\x1c\xc5\xba\xd4$\x9ekP\xd5\x0f\xce\x10R\xee\x91+\xf5\x19\xdeX\x04\xd1\xbb\xf5[\x0c\xd7\x95\xd0}\x8b~\xd6_D|\xc3\xe0\xc3|\xa9S\xfc(\xf0#\xf6*^3rEN\xa6\xa5T<\x0d\x85G\x9d\xbeR\"(\x1e\xba\xaa'\x9d\x8aJv\x86\xa7\xa7\xe6\xc5\xb4x\x9f\xc4[N\x93\x9d\xfe\\x/\xa0S\xbd\xf7\x1b\xe7-\xa9^\n\xe6y=rrE\xc4}\xc2\xe2\x0d\xea\x8c\xfa\xa0\xb1\x19\xc1\xc1qOOWoP\xedL\xc4nIV\xe9\x89J\xa3:\xcd\x8b\xb9\xc9\xe6\xd7\xbb\xa6\x92c\x93\x9c\x056-\xad\x8d\xba\xbd\x1e\xef\xc1\xd5\xc9\x8c\xb3~0gK\x03O\xcaD\x1f\xae\x1e\xfe\xfc\xbe\xba\xa4`\x08r\xf3\x11\x95\xb5UY\xc5\xfb\xc5\xa6G\x84\x15*\x1c\x95j\xb2\xa0tR~\xa9Z\xcb\xfa+\xb80\xc9\x06D\xecx|\x0b\xfd\xfe\x8a\xf3\x98\xf7{\xff\x81\xc7\xd1\x96\xfc\x993\x85\xdet\x15\xb0?\xe3\xa1\xa4\x18\x11o\xc7\xbc\x1b\xb8\x9c\x7f\xea\xa1\x13\x8e\xea\xbd0\x8b\x9f\x18\xabF\x8d\x8cM\x1a\x8c\x88\x02[\xab\xe7!\x87V\xe4\xdc\xb0\xfb\xb4_\xfc6\x98lb\xfe\x15\xf5v\xb9-{m\xd5`sy\x99y\xb4\x84i\xc4\xa6\xcd\x1b\xd7Z\xbf\xbe3+\xc4\xd2\xaa\x10\xc6\xa6\x01W\xd4\xef\x8a\xb4\xde\xf93\x8a\xb8\x82\xc1\x87zj\xaa1\xa1\xfcp\x9dj\x06#\x8d\x99\x9e\xae\x18\xf29\xd5\x91\x16\xedU3\x1eK\xd3~4\x18\x91H\xd3\x89&@\xf4\xa1Z\xb7\xde\x01:!\xb6W\xd6\x94~@\x14\x86\xcea=\xe5\xf5\xa4RZG\xe4\x1b\xb3\xbc?\xe2\xb8D\x15\xbax6\xfa\xa0\xa1\xea\x06\xe2\x03\x06\x0c+\xee2l\xe0\xf7+\xe6B\xd1\xa7M\xe1u\x92 ?H\x0dC\xfe\x15\xf9(|\xbd\x81\xa1?u\x1e\x07\xf85%\xa6%\xb1)D\xfeE!\x01\x9c\x8e\xc4\xa6\x97[&~\xcb\x19U\x14<\xb6/\x0ebZ\xec\xb6\xaf$\xa7nS\xe3\xe0\xba\x9b\x98\x93\xbe\xe9e\x0e\xe1Hk\xfc\x03\x16m\xc5n\x04B\xca\xd9\x08D\x92^\xef\x82\xc4\xe3\xf1\xc5\x80P2\xbc\"|\xce\xe6\xfeR1@\xb6T\x8d\xf8\xc3!\xb6\x84]r#\"-\xcea\x1d\xfa\x8f\x0b\xf7x\x9a\x03>\x1c\xfa\xe4\x92\xc4\x17\x03\xd2\xc3\xa5\x80\x8e\xf3m\x17\xc85\xf6\xaa\x80\xa0\x06\x19U\x16s\x0ej`\x9a5\x8c\xc1Q#\xf0\x91\xb0s\xb2\xa3\xa9\x0bC\xd5\xa7,b\xa9G\x13\xf6j\xed\x92=U\x0e\xce\x92\x80z\xec\xabH\xf8\xc2g\xa9K\x12U\xd9\xb0\x9a\xdf\x8b0\xa8\x8b\xa4?\x17\xb4\xfa\x19J\"?e\xb1`o!\xa6\xd5a\xed~\xef2/\xf3rQ\xd8\x88\xbe\x1f\x95\xeb\x03\x95QG\xb2\xd3\xbb<-\xd4\xda#C\x92b\xf6r\xed\x1eR\xc4.5\xb2\xb9Xj9\xeb\x9a\xf4.\x13\xce^^\xaa\xe2P9\xed\xc3g-\x17\xc0u\xe6\xcbS\xf8zy\xaar\x16\x00 3\xd2\xebR\xb02\x0e\x1b\x16y\xae\x85=R2`\xe0\xe2\x0f\xdeH\x91F\x08\x1d;\x17\x8ekjkX\x1b\x8e\xc305\xeb\x93\x80F\xdb\xef8\xdb\xf8wu\xc9)Q\xe4\x9a\x86\xa9K(Q\xdf\xc1\xc9\x0c\xf8\x9f\xd1\x19'i\x12\xf8\xa2\x7f\xbaH\x87\xa7\xdb\xc1@\x87\xf2\x86H\xde\xbc\x1f\xe0\x12\xc6\x1e\xbe\xf5\xb2T\xc4\xe1\x88x\xf3\xb3\xe5\xc0\xfa\xb1p\xe5\x99\xab,\xcb\xca8\xd4\xed\x17U7\x1f\xe3\xd1\xe3U\xef1\x19\x92\x1d\x0c\xbb\xdf\x8f\xfb\x9b\xc1@\x8d\xf8\xe3\xde\xe3R)\xa7)ia\xc6\xd5\xbc\xad\xd5L\xc1\x0c\xf6\xa3\xc9\xce\xdf\xee\x02\x88p\xf4\xe8\x11)\xbcj\xc3\xd5B\xca\x88\xcc\x133\xd90\xeb\x1e\x15}o\x80n)\xfa\xf6\xd3\xa0\x15\x83\x1c\x88\xa1\x87DK\xeb\xd9d\xc7\xe8\xda\x8f\xb6\xb5%\xd8\xbabv\xaa\x0d@\xc7\xdd\xb7l\xcf\x02\xecb\xb95S\xf1\x91k\xd1Yum\xad\xef\xbap\x00c\xda\x1bM\xeev\"\x0c\xfe\x98\xc1\xb1\xed\xe5\x8e\x93\xd3\x97=X\\;\xfe\x12<\n8\x87k\x95\x05\x01\x13o\x03?\x15\xdd T\x168\x08S\xa1\xa2#G#\x0b\x9a\xa7\x13\xea\xf3\x05\x0b\xbbC\x17\xf8\xd5Y\xca+\xa9A\xd6\x0cU\xe0\xd7;\x19s%\xaa\xad\xdd\xc3\xd5&\x98\xaa\xb9v2\xc0\xdee\x1c\xe8e\x03\x95\x93\x97dJ\xae\xc9c\x92\n\xca\x05\xaeP\xf3 \x96&FTu#L \xbc#'!n\x99\x04E\xb5`[\xdf\xa9\xcfE\x06!\x80\x0c\\\x93\x1e\xa2bR\x9d\x99\xbc\xe6N\xe0\x9a\xe1<\xe9\x17jW;\xe659\x07\xe1\xf1%\x05\x1b\x10\x03\x07R*\xce6\x06\x06\x0c\xf3\x15\xbb(\"\x8c\xc1\x11\xcb\x8cV+\xf0C\xba\xed\"\xb2\x9b\x01|LR\xee\x95 M\xb9\xa7\x01\xad\x8fS\xf6\xd0!oX\xbd~\xb85Q\xcf\xfa\x8f \x0d\xf4hc-4P\xf3\x80\xcc\xd5$\xa0]1.\xe1\xc7\xbd\xc7\xeaO\x86\xeb\xbfH\xbf\xc9i\xaf\xb0\xd0+#\x04\x11D\xbb\xd3C\xc8^'\x16X\xcb\x113\xd5T\x8f\xe2\x81G@\xa3\xb27\xd5r\x0c4\x0d\xf5\xac\xe2\xf5\xfd\x11\xd0\xa8\xecM\xb5\x1c\x03MC=\xfc\x08Pxm\x9e\xf9Q p\xd7\xa8v\xa2\xd8\x1d\xb8\x94\xd8i.E\x03\x7f\x1bi\x0eu\xaf\xd6\x8d`wb\x0c\xa93\xa43\x98\xa3\xca\xac\xea\x90\x1d\xd3\xb7]\xad|\x1d\xe5\x1e\xda\xb3\xf5G\xee\xd9qh\xbc\xae\x96O\x05\x8f\x1d\xa2jc\x15\x98\xbf\xa1\x96# q\xd7s\x8c\xe0\xc5BG\xe9# \xa8\x97_\xb3\xa0{\xf3k\x16\xb8\xca\x1f\x01\x80\xa3\x06?J\xbbC\xe0G\xa9\xab\xfc\x11\x108j\x08)\xaf\x0b\x15\x8d5\xa8\xdc\xce\x1a\x8e\x00\xc2UG\x9a\xad\x0e\xad\xb5\x1c#\xb3U\xf3f\x1e>V\xebN\x8e\xa8;i\xab\xbb&`\xee(_\xaf\xb4.\xf1\x90D\xa1\x1b\xa9\xec\xa4Vj'\xb5\x88P\x12\\9\x88l\x1ao\xc4\xd1M@\x81\x94\\whM=\xd6);\xbb\x13\x1d\x07\xad2T\x95\xf1\x11a`N\xcb\xbaTV\xac\xaa^\x93\xa0\xdb\x0f\xae\x87\xaeVu\xae\xd9R\xd3\xe3KU\xe2\xa0\x14\xf7\xf2\xb1\xa3\x99#\x16\x85\xca_SB\xc5\xb1\x88b\xc1\xder\xb69\x04\xad\xe1D\x7f\xc8\xc2\x15\xe3\x08\x9f\xbf&C2\x1dLD\xac\x1d\x938N\x97\x95\x88\xdb\xdbD\x9cm\xc0\x10\xdb\xc9\xc4P\xea\xcdV\xdf\xac\xc9Kr\x06G\xa6\x9c\x0c\xafHof\xf5\x0c\xf0u0\"\x8f\xd5\n2\xea\x1f\x03\xffX\xd5\xfe\xd2\n\xfd\xbf\xdeD\x8fuL\xdf\xc7=\xe2\xaf\xaf\xac\xc4\xff\xb8\xf7rn>\xf5\x96Jxw.:;.\x80Y]wD\xba3eI\xf8\xf1\xe5\x8eW\xc1M\xc7)Kz\xb0N\x14\x1fn\xce\xa22\xc0\xec_\xa6\x0c\x9a\xaeeSY.\xe3\xa0^\\m\xa1\xa1|k\xcf\x8e\xc0\x9f8PM\x9dj@\xeaT\xc4\xd6|\x14\xea\x07>\xcc\x0fNX;j\xe1l\xd6\xa6\xde\x17,\xac-\x0e\x0b\xcc\x11\x1dt\xe9Kl=4\xf2v\xf1\xc1CE\xb3Fr|o\xefR\xd7\xc5\x105-\x06\x92\xe3|\x01\xe3\xabC\xb4\xa2\xde\x0d\xac\x90\xbf\xfe\xaf\xffM\xe1|e\xb0\xd6\xc7\xc8(\x0e\xcd\xd9\xfa\x08\xcd\xdbZ\xd4D\x9c#\xf6^\xeb\x9a\xb0\xb9>N>rC\x7fL\x0d\xc2Q\xc3Q\x02\xf3\xba\xb2\xe9+\x1f\x03\xa5\xe4\x8ad\xc5\xf3\xc3.\xcb\xa8_\xe4\xa4\x84\xf5]\xc4\xa9\x90}8\x8c\xc8\xcb+\"\xf4\xe9\x1a\x19\x93s\xc5\xc7\x15\x9b.+\xcaP\x13\x05\xd6\x07F\x0b\x85/FmU\xd2X\x89\xb9B\xbf\x82\xc6\xea\xac\x9c\xac\x99\xa5iU\x15\xafh\xcf\x8a\xf5\x9c\x97\xda\xd4 Z\xab\x85=Tip\xc5\xb9\xd4\xcf\xf78P\x03ri\x8f\x0f\xa1\xa9\x8a\n\xd5*\xd9\xecya\xaf.\xa7\xe4SS<\xa8\xcd \xf5\x03\x0f\xfa\xea\xc6]1\xb9\"\xf3\xda\x94\xcd{@\xa8{\xe8\xdb\xff\xec\xf9\xc0q\xf03\xef)\xden\xb2\xbcpg\xe1l\xc38\x8b<\x08\x13\x0f\x19?ug\xd4S\xaa3}\xe6\xced\xe9\xa2\xa0~`\xf2~\xde\x0c\xdc\xb9\xce3=k\x82\x0e\x8e-C\x16 \x03\xdft\xea\xce\x9a\x86\x94\x0b8\x06\xb49\xcf\xdd9\x03?\xba\xf17\xf7&\xd7\xd3\xc1\xb2\x94iy\xc4q\xbf\xc3z\xaahd\xc5\xcb\x84\xdc\x1ej+\x92pvA\x18\xb9$\xb1F\xc6\x0b\xc2\x86\xc3A\xa1\n\x8c$\x12\xcf\xd9r~\xb6\x1c\x11x\x98.]\xa6W\xc5\x03vm\xe5Q\"\x10.n\x84Gi.\xf8\x04\x9a\x02D\xe66X\x01\xa2-\x13\xdfg\x01K\xfb\xbd\xde``\xe1\x16\xe4\x92D\x17D(\xf0\xf9\\,\xfb\xac\xd1\x84\xe3\x03n\xc3\x95,A\x1a\xbb\xc6\x8a\x160\xd7\x84i;\x17\x1c\xcb:\xe1SC6\xb3\xd4\xcae\x01\xa9\x830\xb1I\xca=s\x88\xde?]D\xa7[\xbc\xf6:\x11\xdc\x0f]\xe2m\xc0\xf6,p\xde\xdeRm\xa532?\x1b\x91\xa9\x03?\xf3\xbb\xd8\xf32^\x82CWm\xc2h\x0c\x8f\x14X\xa3\xa2\xbd$\x9b\xb0h?\xb2\x1d\xff\xd8\xc6\xafO\xab\xb6\xaa\xdaJ\xe6y\x93\x91\x0c3\xa7\xb6\xbe\x0b\x0b)\x9c\xe6\xa6#\x12\x8c\xe0\x18\xbb~\x04\xfd\xec\x9c\x9c(\x82<\xf1v\x94\x7f\x19\xaf\xd9\x17\xa2\x7f\x96\x9f\x17\x8f\xa7\xf5\"\x9fO\xebE\xa6\xedE\xb4G}f\x1d\xe4\xf7\x96\xb3^{\x11j\x96x\xa1\x8b#2_\x0eF\xa4\x9f\xc1\xd5b:\"S\xe07gDJ\xf2\xfc\xb3:T\x19\xc8}\x8d\xcd\xc0r\x0c\xc8\x15\xa1\x93$N_\xd1\xbb\x11\x8a\x01\x8a\xc1]\x90\x94\\\x92@\xb1\xb0\xe9\x19\xd4L\x01E\x0b\xb5\xa7\x83\x0b\x92\x0e\x87naR\x873\x0c|\x8f\xf5\xcfG$\x1b\x8c4[\x86C}\xf3\x05\x9a\x1a\x91\xd4\xa0\xb9Y\xf4\xe4\x9a\x8c\xa7dF\xfa>l7\xd9\xde\xa7H\x07\xa5\xac\xa7)\xda8\x18\xe9;\xd8\xd0F%\xc7\x1c%Xo 2m\xe3\xc7+\xb2\x19(X\x1c\x14\xb0\x1bq(\xd0=\xf0'\x82Q=p\xa1\xb8\xccF\x0b\xb4\xa4~\xc9\xd8\xd2\xca)\xd2J\x9aKM\xd3\x12M\xac\x954\x0d8\x85*Z=\xde+\x89R\xd4\xca%\x8dR\x92\xaa\xc0J[.a\xcf\xfc\xa0\x03jY\xd3\x82\xc6\xe2\x82\xf0\x82pt\xd2\xef\xab\xf5\xed\xf7\xf9\xa8`R]\xa56\x88\xe3\x83\x8b\x01\x10 \xaeQ'68S\xb7\xd40\xbfb\xc3\xaa\xe4(o\\\xe1Q>\x14 \xde\xa1=c\xde=\x9bx\xc8[\xef/N\xf9\\6W\xcf\xa6U{B\xaa\xd3\xab\x86\xf8h\xed\xff\xec\xfc\xccIA\xd3\x9c\xbc\xd4\xccp\x14t\x9apB\xe4\x80\xf5\x88\xecFd?\"\xe1\x88l\xbb\xd1\xc5\x03\xa4\xf4\x01t1\xa8\xd3\xc5\xd4\xd0E\x0f\xe8b0\"g\xedt\xd1\xeb@\x17\x13rE\x02K\x17\x15\xd1\xf2\x90.n\xc8%\xc6p\xe8?=G\x8a\xb6\x86\xac\x15\xea\xb8Ac\x9c)R\xa4\xf5\xe0\x82lj\xb4\x12\xc8\x80\xaf\x00\xde\x1c\x80f\x0fM(\xc1R\xc7m\x1ca\xfc)\x03\xa4\x82px\xa5(\xc3G\x04\x0fZ\xb6\xf5\xed`\x1c7\xea\x91\"\xc8\xe4\x9a\xf4\xc3:`\x16(%O@\x86^\x0fSw\x83\x02|\x1a<\x07d\x17\x03\x05\x8c\x93\xad\xd8\xd2\x9a)9J[\xde\xb1U\xbc\xacoX\xcdtD\xbcA\x99M\xa4\x93|s2\xdf\"w\xa8\xa6\xb9.\xbe\xe8\xb8\x9c\xa1\xc3\xe4\x0d\xfc?\xecK\xe9\x8a7m>\x1eS\xf1[\x99\n\x10\xccB\x17\xb4\xc7\x8eR\x92\xb6\xa1>\x92\xff\xf8\xc7\xf3\x9f\"g\xf1\x1b8K\xce\x99\xfc\x1agr\xf2\x1f\xffh\xfe\xe3\x1f\xe2?\xe9/\xc4\x7f\xfcv\xfe\xe3\xbb\xf8\x8f\xff7\xe5?\x0fA\xc1F\xfc\x83\x01\x8fpw\x07n>\xec\x0e.\"\x97\x84_\x90H\xed\xe0JX\x01\x08\x16\xcf\xa3\xe5\xc0\xce\xba\x99\x07\xbd\x03\x11f\x00]\xbb\x10\x91{\x8b\xfb\xd7\x1a\x0d\x90\xcaK\xdb\x0c\x18\x80\xfar\xc2{d\xb5\xf4\xa4b\xf8LJ\x0b\xd9\xaa\xd5\x816\xb1\xfc\xa2\x9a\xddx\xd6B}\xb5\xe8\xdfz\xc5c\x17\xa4\x06\x85\xf5\xc7\x8cB\n$t\x85\x8b\xe6F\x1cF2\x0f\xe8\x8a\x05#r2\x053\x1cGUE\xfdV\xb9\xae\xe9\x88$Z\xce\x0e\x14IMM5}`'z\xfb\xcc\x06#r\xb2\xa9^$\xd2\x93\x9d\x0f\x05\x18%\x0e\\\xdd\x04\x04\xa4\x96\xe4\x95K\x8c\x0en\xd6I\xbeaw\x9c\xc348Q\xd1\xdbpo8\xac}\x06/Q\xb9\xb2\x83:\x15\x1an0\xa0']\xe0%\x0e\x98[\xa0%\xfa\nmK\x90\xc3\x96\x0e\x11\xdd)\xdc% *^\x93>lG\xe7\xcbAG8+\xb4\xbf\x19\x12\x81\x0eh\xda\x82\xcdv\x006\xeb\x08V\xa3\x8e\xc6\xfc\xac\xae\xc6eEh~\x06\xa0\x96j\xac\xfa\xa50\x8c\x1f\x0c}\x95U~\x8cQ\x1d\x8f\xbd\x06\xb8\xe0\xe2\x8a\x82\x1eh\x02\xd0&\x886\xab\xd7x\xfei9\xc8\x97]\x91ji\x83\xf5l\x80\xf2\x8c\x9b\xd3\x9b\xdcs[,\x97@\xac\xf6<_$q\xd2\xcf\x03\xbe\xc4\xf9\xbe3\x8b\x04\x9cg]\x17\x13fJ\xac\xe1\xa8%\xe5p\xa3\x87p\xb5\x1c\x1f\xba\xe6\xf0\x98\xee\xe1\xab\x0e\x0e\xd6Z\xc3|\x1b\xccj\x98\x12\xb7\x14\xe2#G-\xf6\xc9\x1ft\xa3\x84\xc4\xd1\xcbC\xb8u\x10q\xea4\xb2\x96\xd2\x0567\x95n\x83\xae\x05\xb2\nT\x1f$W\xd9d\xbb\xbf\xe6\xcd^\xfdruo\x7f>\xee\x0f\x16\xf3\xc5\xf2\xe7\xf7\xc3\xeb'\x93O\x16o\xe4h\xf6\xeb\xcb\x93\xc5b9\x00E\xf0b\xf1\xc9\xb4\xf71\xf6\x10\x0ey\xa5\xb8\xbb\xef\xb0\xb7()\xcf\x1a\xb6\x0dy\xce\xef\xd9\xf6\xab\xbb\x04\xc4]\xb8&\xd4\x7f#\xe7=\x08\xd2\xb8\x88\xfa\x83\xf9\xf2\xf1\xa27\x19\x9d\\\x8f{\xfafO\xaf\x87\xc1\xb7\xb8\xb9\xdb\x83\xa6\x82\xcbA_\x95*_t\xaeC\xd31n\x97\x9d\x804[\xa5\x82\xf7\xa7\x0e\xbc\x1cL\xd2\x98w\x0cN\xaa\xeb+\x9ck\x9a\x13@W\xbd\xa5\xeeI\xec\xdf\xa0\xff\xc9\x03\xc7\xa5g\xe4\xa3\xc2h\xa3\x82\x04_\xfa\xeb\x11\xe9m{j\xe7\xbb\xb1\x92Q\x9e\x17E\x933$\x98\xbb\x92\xc0\x1e\xa3\xc0\xee\xa6+\xd5\xed\xdd\xce\x9c\xd5\xba\xf3\x93\xe2\x86\xb2\xafH>\x14\xb0\xd2{eo\xf9\x12\xe8\xb2\x18\x8f\x9bk#\x06\n\xc1\xee\x84\xdeLP\xbd\xd9\x1b\x1c\xdc\x1b\x9a\x9f\xd5\x80\x9f\x8d@OF\xf3\xdd\xc6f\x12\xd0T|\x13\xad\xd9\x1d~\xf7\xb4\x0c\xb7g\x81\x11\x8d/@|\xdfL\xd8\x1d\xf3\xfa\x19\xe8-\n\xa5^\xa2\xfa\xfc \x95-\xfe4e\x83N5\xd3\xd9\xe2\xcf\x8a%\x99\xde\x98\x06#\x92\xa0>\x8d\x0cI2\x9f.\xf5\xe0v\x08EG\x0e\xf1\x99\xe2\xef=\xb8q>\xbeo\xd6L\xadc\x07\xb5\xb6\xc5\xb1\xde\xb5\xb8\x91\xcc\xcf\x97\x1d\xa2\xe7\x91\xc3\xf2b\xf1\xf7\xd0\xee=d\xeaT\x0f\xba\x15\xf9\xdb\xcc\xce!>_\xfc\x1d\xe0\xf9\xc5\x9f\x82)\x80\x05\x93/\x921I\xe6O\x0d\x8a6\xabR\xcc/-ho\xfa\x01\xb9$Y!\xe1!\xfd}\xc8t\xd9\x95\xf6K,\xa9\x12aT\x04\x0d(\x8d\x91\x98}\xdd\xf4\xd9\x08\\\x1b\xa4#bR\x04\xea\xb4\xdb)\xe6\x07 7&\xd5\x1cZ\x9c.\x86c\xb9\x98,&rq\x8d\xff\xc9\x93\x93\x93\x139\x1a\xc9\xf1\xf8\xb4~\x98q\xba\xe8\xf7=)B\xc9e2X\x0cN\xb7~\xfd`\xa3>w\xde\x8c\xf4\xfe\xfb\x7fsL\x11W\x1f\xfe_\xc7\x87D}\xf8\x7f\x1c\x1fD8#\xbd\xbf\xfe/\xffw\xaf\xf4\xa5\xc1\xda\xa6\x8b4\x95\xcbQ.iIk\xab\x8a\xbe}\x1a\xe4\xa5\xd2\xde\xa8\xc8\nS\xcd\n\xd3&VXc\xc4v\xd3\x94v\xe7\xc7\x19)\x97;\xcc\x96I\x91\xed*,\xcd,\xdb\x85\x95 gQ9/U\xafx\xd0<\xc8Oz\xfa=<\xa3\xb9&\x01\x99\x91\xc0J\xc3\xf1\xa8\xdd\xf6\xac\xfa\xd3\xd2\x97?\x17\x13\x11\x7f\x1b\xdf2\xfe%MY\xbfbtS\xfc\xa9e\xc6'\x82\xa5\xa2O\x07\x16^Z0\xbf\x18\x8eA\xec\xfe\xef\xff_oPH\x9d\xfc|>z\x0f\x1f\xfe\xfa\x97\xffZ\xfc\xd2\x9f_\x9f,\x07\x7f\xfd\xcb\x7f\x85\x8f\x9fL'\x93\xfa\xd7\x9f\x9f\xe9\xb2\x9fL\xd5\x7f\xc5\x0c#[\xef\xa8T\xee\x8d\x9c\xbf\x19/\x07\xe3\xf1\xb8\xaf\x1e\xe4'\x83\xd3m\x085\xfc\xf5/\xff\xfb'\xe7\x95\xbc\x8bt0\x1e\xf7\x17i)\xdb\xffV\xcb6\x7f3^\xa4\xaa\xd2>>\xd5\xb3\x83\xff\x96\\mM?\x8an\xd5\x12\x8d\xf9\xe3\xde\xd2E\x1c }[\xa7\x08\xa7\xf3\xf1\"\xc5\xdd\xd1\xf2\xd4\xb5\xc3\xa2m\x16\x8a'}a\x0e\x02\x01\x7f\x8d`\x0e\xd3~\xe2#\x120\x85\xbc\x85N\xd6\xdb\xc8\x0e\x98^\xdb\xad\x04\xd0em\x10k\x13\x914WF\x91<\x80\xde\xf8\xceM\x9b=\x92\x1d\x91\xfb\x11Y\x8d\xc8\xdb\x11\xb9\xfd0\x82t\xab5\xbf\xab&\xc2\xb4\xd2\xc4`u.\xc5\x9a\xccFaK\xaer\x88a\xe8\xb60tx\xfct;\xdf\xea\x9c\xe4\xf2\x8al\x06\x17d;\x1e\xb7\x9c(\x99_a\x0c\xb6\n\xb9P\xae\xd2\x9b\x14\xd8_\xd9\x15<\xe8,[\xb1\x19v\xe1\x82(\xc1\xca\x03\xc2\x18\x97vAz\xe3\x13\xe3\x86\xc7\x1f\x0c.\xda\x87\xd9\xfc\xc0\xd7\x07\xb9\"'\xb4\xafPX\xefN\xc6d\xaa\x05\xc2\xd4\xeeW\xa6#rO\xaeH\xef1NL\n\xa6\x89\xa0:\xc0\xb2\x01\x1e[']\xe6\xc3\xfcT\xeb{U\xc3zDB\xf57\xe9\x06\xb5\xf9\xc1\xa0\xb4\xcdc_\xcd\x83\x9a\xcaQeJ\xc9f\xa0\xa7\xf4\xa8\x06\x89\x06z7I\xfdh\x1b0\x18\x8a{\xd5R\xa1r\x95\xb69f\x18\x8a\xbf\x1c\xe0{rM\xfao\xe7;\\j\xc5\xe3\xca\xcc\x91<\";\xb46\xc8\x89 Z\xc4\xce\xcf\x97\x15\xb6\x91\xf5\x0b\x02\x80\x9e`G\xb9\xa7K\xd0&\x7f\x0c\x10\xce\x1e\x08\xc2t\xa9X^qI\x1d^+\xae\x9fj\xca\x8f2V \xbe\xd1\xe5WW\x836\xfd\xf6\xe4\x9a\xdc\x1e\xb3\xcf1?\x18\xc5V\x1d\xb4\xeb\x97\xc4\xe9\xcc\x0e\xddQ%\x11ug\xc4\x11\x07\xbb\xed\xa7\xf7J\x9b\xce\x85\xc0j5T\x8b\x03VH\xff0\x02\xf4\xfe\xfa\x97\xff\xe2\x8a\xa0\xea\xfa\xbd',H\xd9G\xad\xfa\xa3\xee\xc1\xc0\xc0\xbc\xea\xf8\x15\xe4\xa9\xdb\xdb[\xf9\x1b\xb9\x98-N\x17\xa7N\xb9\xc9o\xd4L\x9f\xbe\xb9\\\x9c\xd2E\xfa\xe4\xe5\xa9\x91\x90\xda\xc5#Z3^7F\xe8s\x87^CX\x0b.7\x06\xab\xce&\xe82\xaa\xf9\x9c*\xe3\xc1\x8c\x9c4\xc4\xae`!\xf5[>\x8b[_\x08\xc6\x9b+\xd7\xf2\xf2\xd7Q!0g\xd3\xdd\x16\xf3Ko}\xe1\xed\x14\x92l\x99x}\x9f\xb0\xfeA\xa1\xc1\xa3)#\xbd\x8c\x07\xbd\xd9Add\xc7\xacy%\xb2\xccH4\x81\xc8dl\xfd\x9a\xddu\\\xf60\xaa\xd0\x83?\xf1\xc0\x11\xf9\xa6\xfak:w*\xfe\xe0\xc2n{6\x1c\x08\x98\xb5\xbf\xaf\xa1\xe8)\x90D\x0cjF\x18\x96\xafTB\xbf\xb0\xa3z\xa3s\x9c\xfa\xa3\x92[\x9b\xa6\x9f\xe3\x0c\xcc~j\xfcb63Sg\x8ez\xb9\xea\xb4\xe8\xf2\xf5\x11\x0b\xfc\xe8&\x9d\x11V\x1f\x12\x9a\x89X}U\xcb\xa4\x1c\x93\xda\x15L\xea\xd8\x8d\x0co:\x80*\xeee\n;\x80:|jg\x12eA\xab\xe2E\xdf\xc3i\xd8\xe3\x14,\x95\xee]\x96J\xce\xb1\xaemk\xee;\x1e|\x14\xb6+\xa0o\xb9\xffX\xe7\x1f\xb9\xdb\xa0\x1eXD\x822);\xea\x14\x04\xea\xd1\xb7\xd0\xb5\xdc\x9d\xabr\xb6 \x9f[Vw\xfa\xe6\x92\xce_.\xd2\xa5a\x0d\xdb\x01\x1a\x87\xea+\xa3\xbb\xf1xD\xfc~\x9a;\x18P\x89\xc3\xe1@\xc9\xc6\x90\x0bR\n\x9b\xaf\xbc\xad\x18k\xcc\xcbv\x01\x9e\xe8\x0e\xac\xe0\x90Q\xc9\xf9}\x85\x1b\x14.\x13(\xf4F\xa1\x7f5\xc91\xda\xee:l\xaf\xf6\xa5=e\x08\x05\xfb\x81\x82yo\x15\x06F\xbc;L\xf1\x88\x99tOo\xa3\xd7\xd0\x9a\xde\x11np\xc7\xba!\x97\xb6Y4\xbe\xcdM\xdf \xce%\x15\xec[\x05\xc6~\xbeYN2\x1e\xa0\xa6J\xdb%\x1b-\x1a|\xd4;T\xf5Y\xb5\xb4\x1e\x11\xef\x18\x12I\x1e\xa4\x0d'E\x8dx\x90\xab\xa5\x93\x8eJq\x92\x0b{\xebN\x05 \xb2\xc0C;f\x1d\x8c\x1d\xd1;m\xcc\xab\x87\xbf{9}`\xd5f&T\xfd\x99\x81\xe8p.E\xb4\x02\xf3\xa1#\xf1\xd0)\xb6\x98\xd6\xbd\xec\x91\xd3\xfb\xf0>\x15h\xe0\xd1\xd0\x8d\xc7\xdd\xe1\x0b\xd0\x92\x1eP=!\xc3|L\x0c\x91\xe8 \x0e\xa9_P8\xb4zh\x9f\x1f:\x8fG \xf2\xd1\xf3w_9\xbb\xcaJgWY\xf9\xec\xca\x1b\xd9\x834}vu\xb0\x9d\xf6m2\xee\xd5\x0eV\x82\xe7\x1e\xe3\xf1\x05pI\xadM9\xb9\xb2\x14\x9a\xe0\xadmC/\xe0Sf\xac\xd7/\x06\x8a-\xdb6:\xed\xe0\xf6:(\xe2\x88\xf89z\xc4\xfa\xe6+\x1a\xc0\xd9\xe2U\x8ew\xfa\xe4\xa4\xdc\xa1'\xe4\x0b\xcb\xc7&?\xa6\xd5\x8fg\x93\xe9\xf3\xc9\xd3Jj5\xd3\x97qr\xcf\xfd\xedN\xf4\xbd\x019?\x9b>'\xff\xcc\xd96\xe6\xf7\xe4\x7f\xa2^\xbcJ\xc9\xe5\x96\xb3\xedo\xd4?\xe3\x1f!e\xe2\xc5\xe1\xcbj5\xaf\xbeyM\xbe\xf5=\x16\xa5l=!\x85\x18\x86j\xdc\xd28\xe3\x1e\x83X\x86\x01\xe6IOC_\x8c\xf5\xcb$\xd9%\x07\xa0T\x15\xa6\xb3\xd3\xd3\xad/v\xd9JAp\xaa B\x80N\xdbF\xe1\xb4\xf4\x0e[\xd1Q\xd9\x80\xbd\xddF(\x9e\xfcI\xf8\x81q\xb0\xae\x9d\xe2W\xac\xc4\x9c\x02v\x9c_\x94v\x9fe\xc6Q*x\xe6\x89\x98\xcfH\\_\x88\x19\x0fR\xf7\xb6\xb5eG\x9b\xeff\x1d\x1f#v\xfb\x1f\xfch\x1d\xdf\xba?\x97\xb7\xda\xae\xcay\xa6\xd6.\x9b\xe9{3\xf5\x1c\xc5X\xac.'\xd0\"\x0c\xbe\xa3\x14\x9d\xf8\xe9\x97A\x9c\xa2\x13\x9ck\x18\x89WT\xec&!\xbd\xebGj\xaf2R\xd2\xfc\x0cvK#\xa2\x1d\nT\xfd\xd5\x17\x7f\xa0KC0\"\xe1\x8b{\x0b\xc51e\xf1\xeeV\xab.\x86\x98\xcb\x8bfz\xf5N\xf0\x07\xc1[\xdbP?\x0dJ\xd0\xb2OGX,\xcc\xce\x8cnV\xa5\xe9\x04\xb7F|\xb5\\\xef\xddX\x8d\xc0w\xc1mc\x8c\xa8\xb1\xfaU\xbe\xb6\nj\x0bf\x02w@\xa0,\xc8\xf3=\x94\xfb\x17\x1a\xe8\xa8\x03] s\x15\xef\x02#,=\xf74\x14\xc1\xb7j8bb\x19\x95\x93'\x1e\x0d\x02\x13%FS\xe9\xc1(\x8f\x86te\xa3! rM\x04\x99\x91\x13\xbco\n\xbe\\\xec\xe8\xa0V\x08\x8c\xc7\x05\xf1\xa3T\xd0\xc8S\x85\xe2\x89\" \xaf\xe9V\x15.\xfa\x83\x9a\xd9\xd1}m\x89R\x7f0Y\xa9\xa7>+\xfaY\xea2\x88%\xd23k\x16\x05\xcc\xcf\xa8V\x01\x86\x9c\xbc\xb6\x0e'\x83\xcd\xb1\xa3\x94 \xe0TH\x9a\xe4\xd0\x0cF\x8e\xb3\x0cw\x17^\x15i\xf8q}(\x90\xffc:Q(f{QH\x9b\x141\xbf\x99T \xcb\x85\n\xd5c3\xa9\xd5\x1c\x18r\xc2ssV\xcb\x91!\xb3~k\xce^b\xc2P\xa4\x90\xe2&.\x83#f\xe6u\x81q\x1e719\xcb=f^\xf2RvZ\xbe\x80\xdb\x11\x85\xc5\xd2<\x1f\x05\x81\x05j\xb3\xef-\xc3me\x14l_\xbf6\x17(\x88,H\x05\xcd\xfbQ\x83]Jy?\"1p\x99C\x9e\xb3H>n06}\x81j\xaa~U\xc0\x1c\x19t\xd6\xbe\x7f\xe2\xf2\xaa\xfd9\xcfPIS\xb2\xabS\xfa\xa4\xabTp\xea\x89WL\xec\xe2u\x07d\xc0\xa0f=S\xae\xd7\x05\xe1Ph\x9e\x1d\x1e\x04R\x94\xc3\"\xe2G*\x9b\x98\xech\xfa\xc7\xdb\xc8F\xa3\x8fP\x14a\xf3hI\xd0#X\x03\xfb6\xb8\xd8\x05Fv'X\xb4\xee\x08#\x80\x87\xf2\x1f\xcb\xc5\xfbf\xe4\xaan\xe7\xde7\xdc\xcc)m\x15\x1a\x16\x98\x91\x18AW]\x1b\x9b^a;\xd1\x1b\x00\x93*\xa4\x90\x0e\x13L@\xde)\x14\xd2\x81F\x90\x99R\xbe\xcd\xc01V\x83\x843(u\x01\xc2\x03\xb6\xce\x0d-\x81\x07q\x19\xe9$\xcd\x12\xc6a\x01\xe2\x0d\xe95\x0b\x98`\xe5\xae\x8c*;2\x8a\n\x84\xa8\xd3\\\x07\x81\x9f\xa4~:k\xdd\xa2\x17\x7f\xd6\xa4K\xebh^b\x90\x04\x98\x83(\x0b\x02%VD\xe4\x9a\xf4&\x93\x9e\x12~1\xbc\xa21\xf6Rl\x1f\xf4\xfcc\x12Y\xd5\xf1\x90D] \xb6V\xecvDN%\x0f\x7f\xc19\xbd/x\xe8\xd25\x0c\xf2\x8e\x18eq5r\x83\xf9\x15\x96\xa1\xdd\xeb\xb0\xceG\"\xc4\x9c\xbb\xc0\x1aU\xd2\x95m:j\xc5\x87q\xfd8\xcb1 p\xff\xe5\x8bh\xfd%MD\xc6\xd9\x11\x03s\"&\xdb ^\xd1\xc0\x11\x9e\xf1\xcfP\xed\xf7l\xcb\xee\xfeL\xc2,\x15dG\xf7\x8c\x88\x1d#\x8f\xb7\x8f\xc9&\xa0[\x92\xb2Z`F\xf3\xcbG\xac\xb23\xbc \xb8T\xc1@\x8a\x81\xcf\x00}\xb9\xb9\x80\x1f\xf1\x08\"\xe9\xad\xd9\xdd \xdf7Eh\xbf\x82\xe1(\x8c9\x94Jl\xb5\xdf\xb2\x1b\x8az#Pw}\x84\xeb\\\xc6H\xb9Wf\x99!}\xec\xe3m+W\xdc\xdc\xdb\x9d/X\x9aP\x8f\xc1\x08\xce\x08\x04dr\xec\x0f\x8a\xfa\x8e\xc3\xdb\x02\xb7\xde\xc5\x86+\x8d\x18W\xa0\x1a9#O\x90\xb2\x98\xf2\xfa\xd5\xb7\x9d\xf0\xcanw\xbb\x80V\xdc\x96\x08,\x86\xa1UE12\xa5\xf95\nb\x95\xe6\x8eiMJ\xd2\xeb\xc4\x81S&\xbe\x10\xe5\xbdb\x87\xbbkzC\xa3J\xa6\xfd\xc1\x9c-\xf30\xba]\x1a\xdd\xd6\x1b=\xba\xc5.\xed\xe8\xce\xa5]\x1a\xaa*xtK\xad\x0b\xa9\x82\x829\xfeu\x01n[\x07\xae\xcb PU\x06d\xe8\xc2\xebU)\x0c\xae\xf9\xb9G\xe4K\xc5>\xbb\x8cH\xb1U=\x92\xfd\x1e0\xdf^M\xc3I\x1a\xe4\xbb\xf5\xbass\xb9\x9a\x0d\xd5hf\"\xa0\x82\xfe`\x94\xc7^\xac\x10\x14\xd4\xaf\xe9\xb9\xd0\xdc\x0bo\x11D\xe0\xf8\x1d\xefDr\xb5\x13W\x94\x17\xef/\x98\xc4\x0b\x98\xf4l\x92\xee\xfc\x8d\xe8+\x12<&\xb8\xed\xf7QrP\xdc\x9c\"\xc1l\xe2\x88n\x1c\x9d\x189\x85\x16\x03\xcfu\xc5\x0e\xce\xc2x\xcf\xfe\xee\x07\x8f\x16oX\x95FR\x0de\xbbv\x13\\p\xe2 _\xc0\xa8\xc3\xb1\n\x8e\xb7j\xc1c\xfdtD\x1c\xd7m\xc9!\x8d\xd9G\x9d\x89m}\xc9tY1\xb5\xe6;\x93\xe4\x1dM;\xcf\xbb\x15\x8e\xd0\x9a\xa3GzdX\x9d|\xb8(\xdc+\xdc\xa5\x81LL'w\x81(e\xe2\x1b\xc3?\x8f\x80\xaa\xc6\x89\x8f\xe3\x80\xae&\x8fk\xb1\xf3\x90\x1b\x1d\\\x87\x96J:\x8f\xa2\x16\xbcE\xe5`\xb2\x83\xce\x0f\xb0\xe2\x07\xc1\x0f\xf0\x96y\xef\xb2\x87\xd1\x95 \xaa \xf5\xdcb`2\xd2{\xd9\xcb\xa3\xf8\xda\x91R+\xbdwy\x8a\x05{/{\xcb\xa3T\xc7%\xf0:\x0c\x05\x8a\xcd\x96\x0bYA\xbe\x1a\xc5\xcb\xfc\xaaC\xa7\xd7G\xfb\xc0\xcd\x97\x87\x84j\xe2G\x84\x0d\x08sk\x03\x84\x16\x98\xc9\x90<\xc6\x08\x0b\xb0\xf5\xc0\xa8`\xed\xf4<\xa7\x16\xf5\xd1+\xa5\xbcW\xa2xMou\x84\x88\xfcQD\xdf\xceS\xdc\xa5\x89\xa2\xd6\xc9\xc8\xfcm\xbe?\x8c\xb4\xda\xa3-f\x06\x14\xe5\x1d\x98\x7f<\x0d@\x14`\x85\xd3+T\xb5\xe3X\xfe\x9e\xb3M\x7f\xd0\x82 ~N\"\xa0R\xedoZ\xcf\x04\xbb\x13\xfdBm\xa8\xb7oROt\x19\xbd\x02\xcc\x1d\x05f\xb3On\x1e9bm\x87Dc\x1e\x07(\xe6g\xf9:\xc2\xf6e\x8a\xbcC\xed&\xdb\xe6\x95\x1b\x13u\xa3K1\x1b'\xabA\xd5\x190\xb6!\xb9\"\xbd\xb7\xab\x80F7\xbd\xae\xaa\x942<]P\xae$\x81[-k\xfb\x12\x85\x93\x9a\xa1\xa5\x8dC\xd2\x1b#s\x9bu\xa4\xfc5\x8c\xe9\x02\xa9Uek`\xd7\xf1k\xadF\xae*f\x89\xbb\xd5\xbc\xc0\x11\xcd\x19b\xa2uT\xf6X\xce\xa8\xb0\x15\xbb\xc3@\x1e\x93\xef\xfe\xf8\xc37\xaf\xbf\xf9\x97\xaf\xde~\xf3\x87\xaf\xbf\xf9\xc37\xaf\xffc7\n\xe6<\xd69\x82\x8c\xa9\xf2z\x8f\x0f\x1a\xfe\xd3\xfe\xf5\xac7\x7f\xd3[>\xb9\xee\xc9\xc7\xf37\x8f\x97O\xae\x1f\xcb\xf9\x9b\xc7\xbd\xab\xcb\x97\x7f^\xa4\xcb\xe1\xe0\x14\x19\xdc\xe9\xfc\xcd\"]\x9c\xf5\x1e\xbf\\\x9c^-\xee\xce\xa6\xe3\xc5\xdd\xf4\xeb\xc5\xdd\xa7_/\x87\xa7\x134\x0fQ\xb3\xdb\xbf\x9e-\x16\xe9\x93+\xf5O\x0foM\xdao\x83\xeb\xde\xa8\xe8\xcbd\xaer+Vy\xd9?\xf9\xdd\x1f\xbf|\xfd\x1f\xbf\xfbj\xa0^u\xeab\x91\x0e\xf3W1\"= \xeeQ\n\x15\xaa\xcf\x83'\x86\xdb\xe2\xbb,Tq\xd9?\x85F{\xe0o\xe6t~6\xfe\x9c\x8e\xdf}1\xfeO\xcb\xfcq\xb6|rZ\xad\xb3\x0c\x81\xb0\xad\xa8^\x9d^\x17\xda\xcb\xf9\xf7\x88\xf4\xb6~\xcfE\x0b\xd5\xa0\x7f\xb9\xa3\x9cz\x82q\x13Q\xddhZ\xfa\x8f\xa2U\x9a\\\xc8G\xbf\x9e\xbe8\xbb\x90\x8f\x02\xa1\x9e\xe1q\x8b\x8f\xe7\x17\xf2\xd1OY\x0c/O\x9f\xc1\xbf\x9f_\xd4\xaf\xdb\xab\x1f\x989tA\xd8\xd2n\xa4\xb0\xf7\xb0\xf8Q\xb2\x8c\x98//PUzb|]\x82\xf2g\xfe\xf4@nE\x10ON\xc4A7\x1bAE\x93\x1b\x8f\x88\xd0\x9a\xbaf\xab\x81\xc0\xaa\x87\x91c\xa91Ut\xe7\x8bh\x0d\x93w\xff\x87x\xcdR0'\xf6At\xd1Zv\x7fD\xa2\x81M\xec\x17h\xfeWh\xa4\xa1\xca\xf5\xb5\x8f\x81\x81\xd6\x0d\n\xab\x1b\xa4M>\x86H\xe3fJ\x89wq!@\xc9\xa1\xa9\xf0\xaa\xc3\xd12\n^\xb7Q\xf0\xdc\xa3pD'4\xed\xf4\xbbP\xe5\x06(\x8e\xc3x\xad\xdf\x8dr\xb2Y\xd1I[\xba\xdd\xbcp\xf5~]\xaf\x8f\xc8*\xd79Z\x0eA\xd0\xb1\xf3C\xd3\x01{\xf89\xef\xb02\xa29\x07/\xb2\xcd\xd3E\x0b\x92t\x01\xf3\xd4X!\xda)\x84\xcb\xdc\x99\xf2\x91\xecg\x0f\x99\xba\xbaX\xd4(m\x14V\xc2\xd1'85\xc3\x86\xe2\xb2j\x11|Adh9\xe1\xb3\x92q\xc5\xe1Ds \x0f\xad\xa8\xaa!\x83\xcc\xef\x18Q5\x1f\xfb.H\xdc8\x12\xf9\x0c\x1e\x1c\x88\x0f\x06\xd9\xe0\xd4\x87\x00l\xf1\xf2\xe3\x81\xfb\xabr\x06\x87\xb4\xa4\x1a^\x9e\x8e\xb4S\xb0I\xffz\xe6G\x82\xf1\x08\xbc\xf4\xd1@Z\xf2\xe7\xc7\x91z\x01\x92\x14\xf3T2\x95-\xe1~\xcaR\x99\xecb\x81^i\xeee\xc2\xe35fO\xe5&\xce\xa25\xd4$\xfd0\x8cW~\xe0\xb3H\xfa\xd1:S}`\xa9\x0ciD\xb7\xb0VU\xb9\x84q%tI\xc1\xbc]\x14\x07\xf1\xf6^z;\xee\xa7\"\xa4\xa9\xf4\xe20\xcc\"_\xdc\xcb\xb5\xcf\x99\x82\xe1^\xb2u\xe6a\xf5\xec\xa7\xccO\xa0\x1e?J\x85/2\xc1dH\xf9\x0d\x13~\xb4\x95i\x1cd\x08\xd1\x9eb\x81T\xae(\xdfR_=\xc4\x99\xf0\x7f\xca\x98\\\xa1\xa20\x95j\xfb\xaedf\xe9\x05\x8cF\xf8\x10\x8b\x1d<\xc4a\x92 \xc6\xe5\x9a\x85\xb1\xc7\xa9\x90k\x9f\x86q\xb4N%\xf4\xdf\xf7R\xb9\x8b\x83\xb5\x1fmS\x19\xf8\xdb\x1d\xb4\x9fP.\"Us\x12d\xe1\n \xca\x92$\x80\xber\xeaC\x13{\x16)y4\x95\xd4\xa3k\x16\xdeK\x8fr\x06\xd0\xc4aB\xa3{\xe9\xf1\x0c\x06{\x1d\x87\x007\xbbK\xe2\x94\xad\xe5\x06\x9aI\xe5&\x88\xd5X\xc9-\x0d\x02\xc6\xef\xe56\xf3\x05\xe5\x00\x8e\xbf\xa6\xf7\xf2\xc6WX\x11\xc9\x88e\xa9\xa0\\\xc67~Do\xa9\xe4\xcc\xf3\x13\x96J\xce\"A\x03\xf5w\xef\xb3\xdbT\xa6;\xff&\xddQ\x89\xce R\x009\xe6B\xa6\xf7\xa9`a*\xe9\x96E\xde\xbd\\1\x1e\xf8\x91\xf4h\xc88\x95\x1e\xa0\x85\xf4\xe2\xcd\x861\x85/\xeb8\x95\n\x05\xa2\xadd\xa9\xa0\x82I\xa6z\n\xe03.\xe4&\x13\xab8\x9074\xdb\xb0H\x06\xd9]\xc6\xefeH\xfd4\x8ed\x18G4\xdd\xc90KY\x16\xca\x88n\xe3{\x8a\xb8\xa6\xa0L\xa8\xcf\xd5\x1f\x80)\xf6|\x1a\xe0\xa8\xdeKA\x85\x88c)|\x16\xad\xa9\x1a\xe1=\x0b\xe4\xde\xa7?\xb2T\xee\xfd \xa0\xeaO\xaa\xd0f\x1f\x03d\xfb\xf8\x9en\x99\x04\xccF4P\xa3\xbfN\xa5\xb7c4\x91\x9e\xdaw\xc85\x8d<&a\xd1\xcam@S5\xb2Y\xaa\xd0,\xda\xc62\xf2\xa3\x1f)L\xb4^\x0e2\xdd\xc5j\xd4\xe2\x80r)b5\x03\"\xbe\xb9\x8f\xa5\x88\xe3 \x95\xb7j\x8d\xca\xdb\x98\xdf\xa4\x922\x1eK\xca\x13*i\xeaS\xb9b\xa9\x90+\xff\x86\xc9U\x00h\xf9\xee\x9d\x1a\xdeDzA\xb6\x92^\x1c\xabU\x19'rCy(7~\xba\x93[\x7f#\xe46\xe3\x99\xf4\xa3M,\x7f\x8cW\xa9\xbc\xf1o}y\xc3\xd9Z\x064Z\xcb\xc0\x0fc\x19\xf8\xd1\x8d\x0cY\x94I\xb5\x18e\x18\xaf\xa9\x8ch\xc8d\xa2\xf06Q_\x938\x15\xf2\xa7$\x8e$\xf7\xbd\x9d\xe4\xd9\x8e\xcb\x94\xdd\xddK\xe1'\xa9\x1a/\xa6\xfe\x89\xe5-\x8d\xb6\xf2V-\xe7[\xff\xc6\x97\xef\xe2\x88\xa9%%W\xfeZ\xae|\x05\xf0J\xad#\xe9\xb1Xa\xb0Z\xaar\x1b\xef\xa5\x1f y\xe3\x872\xf4\x03\x191!\xe3(\x901\xdf\xaa\xe5/\x93l%\x15\xc0\x82\x052\x8bby\xcb\xd6\xf2\xee\xeeN\xde\xdd\xbf\x93\xd4\x93t-)\x93t#\xe9VR_\xd2@\xd2P\xd2H\xd2X\xd2\x9f$\xe5\x92\xa6\x92\nI3Io%\xbd\x93\xf4\x9d\\Q\xb9Z\xc9\xd5Z\xae\x98\\m\xe4j+W;\xb9\xf2\xe5\xeaG\xb9\n\xe5*\x92\xabX\xae\xb8\\\xa5r%\xe4j/W\xb7ru/W\n|\xe9y\xd2[Ko#\xbd\xad\xf4v\xd2\xf3\xa5w#\xbd@z\xa1\xf4\x14)\x94\x1e\x97^&\xbd\xbd\xf4n\xa5w'\xbd{\xe9\xbd\x93k&\xd7?\xca\xf5\x8d\\\x87r\x1d\xcb\xf5;\xc9<\xc9\x98d[\xc9\xb8d\xa9dB\xb2Ln|\xb9\xf9Qnn\xe4&\x94\x9bXn\xb8\xdcR\xb9]\xc9\xedZn\x99\xdcn\xe4v+\xb7jb\xe56\x90\xdbPn#\xb9M\xe4\xf6'\xb9\xe5r\x9b\xca\xad\x9an\xb9\xbd\x95\xdb{\xb9\xbb\x91\xbbP\xee\"\xb9\xe3r'\xe4.\x93\xfeZ\xfaL\xfa\x81\xf4C\xe9G\xd2\x8f\xa5\xff\x93\xf4\xb9\xf4S\xe9\x0b\xf9#\x93?\x86\xf2\xc7X\xfe\x98\xc8\x1b&o\xb6\xf2f'o|y\x13\xca\x9bH\xde$\xf2\x86\xcb\x9b[ys/o\xde\xc9\x80\xca`%\x03O\x06\xbe\x0cnd\xc0e\x90\xca@\xc8 \x93\xc1^\x06j\xa9\xca\xd0\x93\xe1Z\x86L\x86[\x19\xeedx#\xc3@\x86\xa1\x0c\xd5\n\x96a\"\xc3\x9fd\xc8e\x98\xcaP\xc80\x93\xe1^\x86\xb72\xbc\x93\xe1\xbd\x0c\xdf\xc9\x88\xca\xc8\x93\x11\x93\xd1FF[\x19\xf92\nd\x14\xcb(\x91\x11\x97Q&\xa3w2\x0eeBe\xc2d\xb2\x91\xc9V&;\x99\xdc\xc8$\x90I(\x93H&\\&\xa9L\x84Lner/\x7fR4M\xf2X\xf2T\xf2L\xf2[\x99R\x99\xaed\xea\xc9t-S&\xd3\xadLw2\xf5e\xfa\xa3Lod\x1a\xc84\x94i$\xd3X\xa6\\\xa6B\xa6\x99L\xf72\xbd\x93\xe9\xbdL\xdfI\xe1I\xb1\x96b#\xc5V\x8a\x9d\x14?Jq#E E(E$E,E\"\x05\x97BH\xb1\x97\xe2V\x8aw2\xa32\xdb\xca\xecFf\xa9\xcc\xeee\xf6N\xee\xa9\xdc{r\xcf\xe4~+\xf7\xbe\xdcGr\x9f\xc9\xdb\x8d\xbcM\xe5=\x93\xf7B\xbe\xa3\xf2](\xdf\xdd\x0e\x16\xab\xd3\xaa\xe6\xb47\"\xe8\xffoq\xbb\x1c\xfc\xa6\xbf\xb8\xfdy:\x9a>\x7f?0\xba\xcc\xb2:\x14r_\xcf\xe6\x8b\xf1\xc5\xec\xd1\xd5b\xb8\xf8d\xb4\xb8]L\x96\xc3\xdf\x14\nD\xf6\x897Ub4\xa3\xb6B\x94\x19\x96\xf3\xf1dh\xc5\x87\xe5p\xd6\xbf>i\xfa\xb48]\x9c\x0e\xfa\xd7'\x8b\xf5pqz=\xe8_c\xca\xb5\x13\x90\xbaJ\xb7?\xb9>E\xa5\xaej\xff\xf6\xf6v19\xbadsG\xad\xf6\x17\xd4\xc5\x8b\xb1\x05|\xf8\xe87\xbf^\x9c\xfe\xd3\xd5\x7f~\xdb\x1f\xc8\xc7\x9f\x80@Tg\xe1O\xbc\x0du\xc8\x11\xb3@\x8c\x0f\xaf\x03y\x12=\x1a\x7f\xe2\x81&-''Y\xb7\"\xdf\xb3\x80\n\x7f\xcfl\xb9\xcd\x81S\xc8\xa3/\xfa\x117\x99$\x87NX\x9a\x87\xd0\xd2\xf7\x19I\x9a\xa1\xb54\x7fF\x1cZc\xf3\x0b\xb1\xdf\x0d\xc1~\xba\x10\xf7vj\xd4E\x08\x81\xdb\xe4\x03\xe3bX!\xf9\x17\xa2_\"W\x87\xf8\xb4\x00$\xc6\x95r\xba\xe8\x9fn\x0f\xdc\xb7\x8fJ\xf9\x07\xa7\xdb\x03<\x1b\xb9\x80\x0d\x0e#%9\x1b\x90K\xd2\x07\xf2\x14\x95\x92-!?9\xeb8\xa6$\x9fs\x87w8\x976\xf2UU0\xeb\xaa\x84\xf4#pK\xd5(X\xce\x17\xb7\xcb\x06\xc1rG\xd3\xaf\xb3 \xc8\x8b\x9a\"-\x12\xbf\xa3\x9a\x8c\xfb?x;\x16\xb2\x83\x15\xb8a\xf8\x0f1_\x7f\xa90d#\x18\xaf\x023\x9b\xbfY\xa4\xcb'\xd7\xa6JG\x15E\xe6\xdb]\x1e5\xd3S\x94\x06tM\x7f2\x1dR\xec\xca\xdcb\xc94!\xfa]\xcc\xd2?\xc4\xe2\xf7to)\xf6\x1f\xf9\xefb\xa1\xad\xd3Z\xb2\x7f!\xbee4\x15\x7f\x8c\x98\xe9q\xa5\x8c\x9f~S\x9b\xcc\x9c\x92\xf5]\xe7\xf1\xce\x13\x89r'\xba,\xd7\xea\x82\xd3](\xce\xeb`~\xb6,\x1f\xac\xb6J\xf1\xbd\x1f\xe9\x9e\xa6\x1e\xf7\x131Cg=0\xce\xbd\xfd\xaa\x9c\xd8\xa5G\x87\x86\xbe\xa3\x89\xa0\x9d\xf1\x13\x86\x8e\xe7\xd5\xfa\x07\xfb\x00\xc7:@\x9fw89c\x13A\xdb\x1avO\\\xded\xbbA^\xc7\x82\x87\x81\x7f\x827&NL\x0f\x9aWQ\xcdW\xac\xf99\x91\xa7\x0d\x05\xbb\xa0\x92\x01\xf3\x84\xd9\xf1m#Q\xcd\xc09\x88$\n#P\xf8\x08\n\xf9Q\xf6\xcf]\x06\xef\x01\xc7\xbc\xaf\x8abS\xd7C\xae\xc2\xbe\x18Jv\x84-7\xf5=\x06\xc2\xa2\xc1\xa6\xb3T\xe3<\xc1\x8e\xc3q\xf6W\x98\xc5\x8fs\xe6\x87\x1ej;\x8e\xc2W\xb8\x7f\xe9Zy\xbe\x1f\xecX\x7fq\x94\xbb6R\xf4g\xfb\xc0\x06\x1f\x80A\x0d\x8d4\xce\xa7\xde\x8a\xfd-fT\xef\xd5\xba\xce\xe9\xeb\xf2\xd6\xaek3E\x0d\x00\x96\xed\xd8\xde\x83\xe6\xd88N\xd3\x0d\x82\xe74;\xe1\x0f\x87\xe2\xb8\x89\xef\xfd\xa6k\x93\x8dh\xf0'\xfe\x80E\x9d\xf1\x00\xf7S\xb9\xc2\x13\xc6\xc3(\x8d\xfb\xa8\x00\xbe>uY\xc3VX\x91\xad\xa2A\x1e5\xf9\xbf\xe3,a\xd1\x9a\xad?\x96\xedI\xc6;S\x99?\xf1.4\xa6tO'\xe3\x0dJ\xa2\"\xb6:\xf7\xb8V\x80\xacn\x9ak\x1f\xec\x90\x94}\xc3d0\xa5=\xed+\x10\xcc\xbdGM\x05!\xf4}G\xaf \x0f\\*\xd0\xb2qv\x9e\xfb\xf4~D\xc3\xe4\x02\xe21=\xeav\xcd\xea\xd85R\xbd6\x05\xed?tN\x8c\xbe\xae\xa8P(\xe7\xc3\x05\xd1\x07\xe7XU\xb5\x83\xa3\xf8\x9f\xcc\x12\xc2\x12\xf6#^`}\xcd\xa9\x1f\xf8\xd1\xf6\x87\x80B\xcc\xf6.\xe3S\xae\xb6\x8bl\xe4V\xd1\x97\x17\xb7\xdb\xe1zS\xf3\xeeAy8,Nb\xd1\x19$\xc7X\x1e\x01J\xef\xb4M\xe1Q\xd4\xe0\x1a\x87\xab\xe3i'/F\x8a\xfa\xda\x94\xf7#\xedh\x11c$\xf16?\xa5\x1a\xb0x\x92\xfb\xe5\x84\xbb\xc0\xf9`\xbc7\xbeeFd\xbe\xc4(>\xfd\xa2\xdbx\x1d\x8a\xeaC\xa3a\x1b\x8c\xc8<\x0fa\xde\x1b\x91\x1e\x04\xa4\x86\xf02\xea-\xf0S\xd1s\x85(\x9d\x973Bm\x9f\x7f@m;\xaek9?\xfb\x80Z\xe0\x93\xaeg\xdaZ\x8f\xbb\xbc \xcbm\xea8\xaf\xd4\xd1\x00;\xa3k?\xda\x9aBO\x1f\xd0pP\xa9\xe3\x99{\xf6v\"\x0c\xa0.\x93\xef\xf9\x03\xda\x12t\x15\xd8\x1e~\xda\xa9\x87k\xb6)\x0em\x15m\xdc\x85\x8aPA\xb1\xcf+\x81\x0d\x97\xee\x98x\xd5\x05\x8a\x14<\x0b\xacW\xb6\x8a\xcb){\xdd\x81\xa1\x1b\x1bF.\x89o\xaf)\xb0\xe1pP\xa8BG\x92\x9f\xb3%\xc4\xe7\x82\x87\xe9\xd2%\x8e\xd1@\xcc\x08\xe6<\x87\xf3\x85\xf9r\xa0\xa9\xd2\xa0BzrJa\x9fh\xc1\xad\x11\x04\x82\xf0\xdf\xb1\xaa\x835\x87\xe6\xcd\xf6E{\xfb-\x00\xbee\xe2\xfb,`)\x1e\xa3\xa3\xa3\x04\xec$\xbaH\x10\xe8\x10\xe1dzA(\xb9\xd4GHl\x12\xf8\x91j\x98\"Q\xbd\xf1\x93\xaf\xc2D\xdc\x7f\xebG,\xedS\x08m@\xc9\xcb+\x12\xa1\x17\xfe\x93>\x9b\x88\x1fv\xfeF\xcc\xe9\x12\xae\xdb\xac\x82\x9bo\xa25\x8b\x84\xfb\xfa\x13\x00\xccq\xe0\xe1F\x08\xd4\x12\xcf\xf9Ru\x91\xc2\xf1\xe6\xc9tpA\xf8p\xe8\x90\x130\xea\x85\xf0\xb7;\xa1`\xcfF\x84M\xfc\x14@4\xb0[\xbe\x90\x19\xb9\xaa\x8f\x9dQ_\x07\xa6\xa7y1\xda\xa86W\x8da%#2\x1c\xdaAB\xaa\xa1\xb9RB9\x8b@\xe8\xad\xd7\xda\x12\x0e&\x1f\xe7\xda\xe7\n\x9f\xcaq\xa5\xcc\x0420S]D\x0bQ\x8b%\x99\x82q*W\x1f\xb3\xb3\xb3\xcf\x9e/\xe5|\x91\x9d?;\x7f\xb6\xc8\xce\xcf\xce?\xd3\x89\xd5R\x01\x94\xca\xce\xce\xe8\xd9i!,X\x111\xe1\x8e\x91\x03+G\x84W\xc7P\x81\xe8#\xa2\xb9<)\x03\x02\x94\x92\xe1>>\xb3\xc7\x02\xd5\x9b\xf3\xc0\xe55\xab7\xc2I0\x02'\x10\xb98\x9b\x8eHo\x11\xa9\x14\xabU\\\x88\xde \x8f^W.\x9f\x15\x18p\x93Z\x1b\xd6V}\x0e5\x94\xd3\xb3\x82p\xf2e\xbcf_\x88~4 \xd7:,,F\xf9\xf3t<\x14\x08\xfe\xa6P\xbf\xa7j\xe8i\xda\x00\xee\x85)\x19\x13o@\xfe\x89<3\xc7\xb5\x90\x08\xc5y\x95z\xe8\xd5\x8c>\x15\x99\xf1\x07k\xe6\xc1\xdc\xab\xd54\xa4\xef\x8f\x14q\xf3#f\xfe\xbe\xa2w\x05\x024*\x05\xb4Al\x1fz\x1epZ\x86U?@e\x18kM\x9a\xeb\xae\xae\x96\xab\xdf\x8a\x00\x9c\x0dj\xa8X\xac;\xdf7\xfd\xaa\x0e\x08/\xbaUD\x1e\xd6\x1a<\xa0\xb8Y\xc7\xfa\xe7li\xd5`(\x11\xb0\xa5\xa2\xbc\x85.\x14=\x9f\xbd\x1f\x95\xda,K\x1a\xadM\xd7]\xda\xeb\xfe\xa2(\x87g\x8f\xfdC\x90]V\x00\x1b\xa0\xe8w\xe1\xea%k\x83\xfa\x87\x84zGC\x9cr/\x978\x0d\xd0z\x15\xd9\x0c\x85%\xc8\x1e\x0c\xde\x97;\xca\xd3C\xaezKn1\x9d\x00F\xf6\xe4\xa9\x06\x19\x02\xfdA\xf0\xfd\x96z5w\xc2\x0e\x86\x0c\xd2\x1f\xb9\x04\x97\xf8\xa6n\x07\xdfP\x10\xbf$\x91#b/Z\xaa\x9d4\x0c\xf2x\xccr\xbb\x04\xa6\x96\xedq\xdd\xd92Q\xc7\xdeV \xa9j\x19\xa98]],b\xb0\x8c\x1a=\x14\xa9,\x81\x82\xb6\xe2\x92\xd4/\xaf\xffy\xa0V\x01F5\xf0\xf1\x10\xce,\x87`9\x02\xb7\xad\x8acpr]Z\x19Pjj\x1c\xc1\xdb\xc4Q>\x82(\xc7\xa8~\x0c\x1c\x93\x91iQ\x05|\xb7\xf6\x05\x19\x83\xe1\xac\xf6 \x1a(\xd4\xbf \x81\xa2\xbc\xf1p8\x80\x88ne\xc8\x06j*Ax\x03&?\x18\x01\x07;\xb3)gZ\x1c\xaa\xf54\xc5\xfe\xe0\xc8\xa8\x15&e\xf7\xcee\xf3xY\\\n\x8d}\xd4c\x9d\xd5}UUD+\xb4\x8d;J\xb42\xa9\xee\x90\x83\xee%b\xf6\x82\x0e,2c*\x96j\x12\n\"\xcd%y\x96\x9b\xe3L\x1ds\x18\x03^\\\x81\x8f\x9a)\xee\xdb\x9aVW\xbe\x03\xe2j-\xb9x~\x8b\xdd\x1fl\x02rHy\x15\xd2\x97W\xe4Y\xfb\xc6J\x81:\x1c\x1er\x06k\xf5\x9cZ\x86\xe3\xa3<\xf6{C\x8c*\x1d\x8b\nUf\xb5\xaf6\xe6TN\x05\xd4\x96\"\x1e\x91g\xe0\xe8\xc5va\x04[\xd2ZyP\xc2\xb8\xaf'*\x10\xd3\x19\x99\x8b\x91\x86\xd7\xa1<\xd1\xe1\xab\x18\xca\x8c\xa5\xcf\xef\x95\xf0\x96\x8bI\xef\x7f\x194\xecN\xdf\\\xc7F\xe8|C/^\xb1\x84\x11\xb3\xc8Z\xcf\xbe\x81\xec\xccd\xaf\xa3\xbaG\x86\xe4)yI6\x8dh\xadrM\xcf_\xa0\xd7\x96\x18u\x1def\xe0\xa1\x82\xe3s\xcc\x13\xb7\xd6\x04\x92\xf7\x08%\xe7\xbeg5'\xc0\xda\xfa\x9e\xda\x03\x0d\xc8\x98\xa4\x03rI\x9e\xb6V\xa45\x159\xc5\x01C\xf9\x89\xe0~\xd8/\xeej\xff\xac7\xb5\xad\x95\xf1\x82\x8d]\x03a\x16\x17\xe4\xa4?\x1cf\xa8\xd1A\xc1 :\x90\x16g$+\xcdH\xb6\x04\x9b\xbe\xd2$\xa84P\x7f\xd8<5]P\x03\xb5\xa8\x8d:0\xb1\xb8\xa2[\xca\\\x84\x00\x04\xf8\xe6\xd1\x06\xe5R9\x0b\x8aj0\xb5\x10\xb0\xbe\x81\n\x01\x9a\x9e\xb9\xe9\x0b\x90\x9en\xd4\xc5\x87vs<\xce\xc9MF\x86\x8ae_\x03\xeb\x81\x93\xbfn\xc4\x07\x94\xf1\x0e\xea\x93PN\xc3tFhG\xc2\x84\x8a\x85\x0c\x16\xa7\x93\x1c\xfd{\xa29\xf5\xb0\xbb\xc7Q\x9b\xf0\x10\xb5\xd9\x93\x97$l]\x89/\xce\xb5\xb1[\x05\xdb\xf7\xc3\xe1\xa0\xb5\xa0\x1e\\\x85\xeey\xac\xdf\x90\xde\xfd\x81\xa5\xc2\x8f\xb6\x1f\xb2\xfc\xf5f\xa3\x0e\x13\xac\xe4\xbd\x92\xc84\x11\xc8Y\x17\xab\xeaA \xeaaa,\x01\xc9\xf3\x91\xbd\"{\x14\xce X\xed\x9e\\\x92\x10\xc2\x11\x15\xd6\xe2~@fd\x0f\xd4,D\x81m^\x98\x0d\xa8/\x17[T\x1d\xe3b\x0b#\xcd\x0bP-TS|\x17\x8e6\x8cO)\x94`b\xb3\xa39\xe9\xf7K\xe8\x10\x97\xd0!^\x02`\xfd\x12\n\xc4\xcb\xc1\x00\x03\xa09IZ\xfb\\7\x8b=~\xabXc\x03+\x9fLGpW\xe7\x0c\xaf\xa6l\xec&-!\x97d}A\x92C\xb1\x0b6\xf3d\xa9/eE\xb0\xfa\xdbt6\x04\xaeA4SC\xf3sSE\xf3k\xf6\xd0\xb5k\xedtf\\\xfd\xdb\xc9Q{\x14\x93\x98\xcf\xd1\xa88c\xa0A{\xfa\xf4\xd3:\x8dF\xc1\xb3\x03\xde;\xdb-\xa2\xc8\xf1x}\x18\xe8\x12f\xc7K\xc7\x8a\x0dH\xf9\xc0aT>~\xb8\xaa\x9c{v\xe4)y\x99\xa6\xa0\xc1\x9a\x19@\x84g1\".wue^P \xed\xfb~0\xca\x97\xa8\xd5K#\x11\x8f\xbb3\xbf\x02\xa0M\xf1om\x9c\xdb&\xa6T\x190\xc5\x1b\xe6\xd3\xa5=\x1d\xd2K\x0b\x17\x13\xcd\x97\x16F\xac\xd6s\x93\x90!\x01Z\x94\xcd\x93\"}\xb2\xe9t\x9e,\xdd\x8a\x83\x12\xf9L\xff.xd\x99\x17:\x0cJ\x0eq\xbf~F\x86%9Gm\xd8\xd3V\xce\xf4\xec\xbcE\xee\xce\x80N>zD\x9e=G\xc9\x1b\xa4\xf0\xe7\x07\xa4pX jEN/HF.I\xea<|\xac\x88\xd8\xb5Vm{O\x11B\xda\xd8\x1e\x01\xbfrVT\xf5\xab(\xef\x9a\xfe\x93\xbe\x8f\x1b\x80G\x8fH\xff\xe4\x84k\xbb\x10-\x13j\xa1\xac\xe3b\xd8\xf1\xe6\x85\xfaaR\xdb\xa0z:}\x14N\xda\xe4\xcai\x90\x0b \xf5\xf9\x90s\xa9\xf4y\x9b\x90\x86\\9.\xa3\xe6\x80\\\x93\xb1\x12\xa8\x0dzE\xae\x89\xe6\x15\xf4\x02)\xe0\xd9S\xfd\xack\xe0\xe4\xb2\x84\x07\xf5Zlc\xbc0Z\xf5\xce\xc7\xad\x9d?N\x0e\x8d\x0f\xadD\xf0\x83\xa8F&_&c\xd7\x1e\xb3e\\.\xc9\xb3\xcf\x14ZF\xe4%y\xfeic5\xa8em\\b\xbc\x1d\x08b\x15=m\xa0\xa8\x1d\xdegj\x0e\"ry\xa5\x80i\x13\x9e\x9e\xa1\xee3R\xb0?{a\xa2\xa6\xb6\x88\x16\x16\xb4\xda\xd7\xa6\xe3\xf7B\xa9\x07\xa2\x87yj\xa7\xd7\xb534p\x87\xd9\xb2\x9b\x19)\x01c;\"\xf7#\xb2\x1a\x91\xb7#r;\"_\x8d\xc8\xdd\x88\xfc0\"_\x8e\xc8\xcd\x88|\xe1\x10\xe1\x00\x15\x94\x08\xa9q\xd4(\x14\xb6\x8e\xbc\x0d\x1a;=\x89\xaa\x12^\xaa\xa4\x95lB\x03\xd3\x96Q\xfe\xd0\x8dO\xe8B\xaa\xb5\xbe\xcf\xed\xb7\xef\x8aV\xb8gG\x12l\xace\xb6\xe4\x1a\xef\x017\xafV\xd8T\xa2\xffj\xad\xd4\xd07\xca\xd5<\x911I\xf0~fg\xfa\x1e\xf35\xe3l\xfd6\xf0S\xd1$\x97A\x9e\x19\xd972\x82\xdb\x87KlJz\xed\x08\xea*\x0b\x02&Z!\xfdpx\xac\xc9\xd2[\xbd\x07\xbak\xdb\xf7\x81\x81\xce\xe0\x82\x9c\xf4O\xfa`\xb6\x836\x98\xb0\x81\xea\xdfW\xd5AkD[K[\xe9Rkf\xee\xc9\x98\xac\x958\xf3\x0cX\xb6*\xadPhG.\xc9\xb4\x94\xa2\xa4\xa8uQ~\xa7\n?v\x9dg\x1b\xc6\xce\x17,<0\x80_}\xc8\x00\x06\xd5\xdd<\xea\xc5\xc0H\xc1\xec\xf5\x0b\x08\xbdq\xec6\x8a;\xf1\xfb\xeaN\xbc,\xdd\x82e\x965\x808\xab\xefU\xb4}`\xd3\xc6\x00\xf7\xa6y%j\xaf\xfe\x16f\x11\x88\x99\x1a\xf5\xb7Vn'c\"\xc8K\x9c\x14\xa7=X\x15\xba\xa0\xda\x9b\xb4\x08\xaeW\x83v\xf3\x80\xa9|\xf0&\x050\xbd\xb0'\xf9\n\xb7(tD\xee+\xd2:\xd1\xa6xj\\\x8a\xa6g\xf8~\xbc]\xde\x8d^\\?\xa0\x82\xe1KrE\xee\xec.\xe8\x07rI\xbe\xbc ?4)\x18\x14\xe9\xbd\x9b\xffP\xb4\xe3kW.\xdc\x1cP,4+\x15\xea\n\x05\xd5\xf8M#\xc7W_\xb7m\xf2C\xce\x08)HAg\x83&Eo\xeev#\xe7{\xe52\xee\xe6C\xb7\xa4\xb0\xd6\xf7\xf6\xeb\xad5\x1cXuAB\xc5\xaf\xca\x1c\x04q\x91T\xa8\xf5\x831\xf4\xd6bdn\xc7\xa8\xa4\x8cG\x8f\xda\xcd\x0cHY\xf2G\x1c\x07>?$\xe7\xf5q\x03\x9c\x8c\xf4\xde\xe8\xdc\x08\xcc%\xe6L\xc6\xe4\xbc\x14\xb7\xd3f\x98GKcAevi\xb9\x851\xd2Y\xad\x08\xca\xf3\x0bm\xc6\xd9\xcf\x13U\xcb\xcb\n!+\x14(\xa4G\xe8\xd8\xbc1k\x97\x82\xa1\x7fO\x9b\x8bv$\x08\x99\xb6g\x1b\x92sT+\xf43\xb3\x0b\xf4\x14\x17x\xfe\x99{\x08\x87\xc3lPVDd\xc3\xa1\xc2m\x16\xed'\xe6VCjn\xae\x94\xd2 \\c-\xeb\x84\xb3\x8d3?~\xd0\x85R+\x9a\xe3\xf1f\x80\x0b;S\xcb\xb8\xa1\xcey\x0f\xae\xf0\xa6Km\x1a\xd9\x8d\x04\xda\x9b\x19o9\xdb0\xce\"\xafY\xbdIW\x8a\xda9\xe2\xe1\x1f\x14\xa9\xe2*?\xae\x1d\xf9\xd1\x03RTI\x10\xcd\x06d\x8c\x82S\xf1\x08%+\x0b/\xc3+\xf2\xac.M\x15.\xa2\x14\x1b(1~C\xd9\xec\xd7\xe1U\xedx\xc7\xb6;.}k\xd1\xe0\xe6\x82Z \"Z\x86z\xac\xa1.\xf6\xdd\xaf\xf64\xfe\x90\xd9}03SR\xca\x07\xe9\xbcL\xea\x07Q\xe7\xe3\xe8\xf2A\xad,\x9c\xe8\xb7ka\x9f>o\xd3\xc2\xe2\xb5\xb5\x03\xd5\xe4ZW\xb3\x16\x1cd\xe6\x82<}\x9e\xf3`P\xce\x82\xca\x94\\^\x91\x17\x17\x03\xe2\x83\xf1Wci\x17\xd5;\xe9\xfb\xe4%y\x81\x10\xea\xfa\xb4.&.S\xb5\xd4\xae1kg\xd8OG\xe4\xa9\":\xf9\xcd\x90\xfa\xf7\xe7\xea\xbb\xda\xfae$7\xcc\xac\x01H\xf3\xcb&`=?(\x08DG\xeas\xf1:W\x13\x8d\xda}\x8bX\xec\xb8\xc9\xfd\x11\x94\xbev\x0c;\x02\xebG\xaa\x9dv+\xa8\x9c\xc6CH\x1fm\xc2r\x084\x18\xb3\x07u\xd1\xdb\xf9\xc1\x1a\x1ci\xcd\x97\xb5\x0ev\xec\x97\x99\x84&R\xd26\x0b\xbf\xacZ\xdd\xa4>\xc4\x12pd\xee\xe1\x88F\x8bV{\xa7K\xcb\x10\xcd{GG\x86\x8aa\x8e=\xe0\xe8\xf7K\xec\x91\x96\x88\x1a\xd5:|\xbfH\xc8\xe8R\xcb$\xfdg\xcf\xf3\x8b\xb8\xb5U\x17#mz\x81:_\x8eE\xe2\xf2B\xee\xc7x\x17\xc6BQ`\xb31l\xd7\xfcb\xb9F\xb5^\xe1>\xdc/\xb0\x9cM\x17\xb4\xbe\xe9\xfca\xa8\x7f\x00\xf7:\x82|\xdc\xa2\x06V\x9d\x1f\xbd|\xdc\xe5\xad\xa8\xea\xbf\xf2\x12\xef03\x87W\xfc\xe0# \x16\x85;\xdfg\xe7\xd5\xbb\xdd\n\x81O\xdf\\\xf6\xe7:x\x9fvu=_\xa4\x8b\xd3\x97U\xd7n>f^\x9c:\xb2\xbf\\\x9ev#4#B]\xb4&?\xa0\xa8H\xc5\xb5\xa1\xab\xd8o\xd63$e1\xba.\xbbxJvMF\xe4$\xdf\xdc\xedD\x18\xb4\xca;\x89\xa2M\x8apx\xb0[zyu\xc0<\xf4\xc5\x99{\xeb\xe4\xb5\xef<\x9f\xe2\xa6\xae\x9f\xb9H\x97\xa7w\xae\x8a|a\xbe\xaci_Y8{._rz\xdfv\x1c\xf3\xecS\x00\x1a\xa4\x96\x93\x96\x1b)\xe6g.\xa5<='\xb2z\xf5\xc0\xfc4\x18`t\xf9\xf9\xa7\xaaf\xa1d\xb7\xe9\xf9y-\xfb\xfb.\xdb\xdeg\x9f6\xf7\x9c\xd8c\xa5\xeaV\x11-a\xd1\x95\x9e?(\xb6R\x87\"W\xd2\xb5\xd7\x13\x0f\x0eC{\x82h\xc0\xe7\xe9|Zq\xd6\xb7o\x0b\xd5m\xfcm\xc6\xa1U\xb5\xb3e\x1c\x9fx\xa8\xfe\xee\xa6\xf0\xef9\xfc\xfb\x14\xfe}\x06\xff>\x87\x7f_\xc0\xbf\x8c\xae\xb1\xd4\xce\xc2\x03\x1e2z\xfe\x86\xd3P\xbb\xc1P\xff\x86\x14>\xc6\xe0\xd9\x0f\x9e\x00\xd28\x13I\x06\xef\xf09A`\x12\x1eo9K\xa1\xf3\xe8b\x12\x9e\x98g\xe0N\xc5=\x8e\xa6\xf1\x11\xd1\x13f\xd8\x04tY\xb0;A9\xa3\xf0\xbc\xc1\x0b\xaf=\x01~'\x04\xc7gF!g\x06p\xec\xfd5\x8b{\xcb\xc9&\xe6_Qo\xd7o\xb9\x808g\xcb\xf2\x0dP\xad\x95\xfa\x90\x1b76\xb9\x8b\xf9\x8aCr\xcc\x95)\xb5u\xc0\xdb\xb6\xecv\xf9\x16N\x8e\xc1BdL\"\x97\xb7\x88v\xf6\xdc\xf5\xcau\xd1\x8a\xa0\xce\xc8\x04\xb2\xc9\xc2];\x17\xbb\x0bJ[]\xe4\xd8Am\xd7\xd0RA\xbf\xa4\xfa\x08J\x12x\xb0,\x9f\xcc\x06\xcd\x14\xd7\x87\x0b\x1d\xa80\xd6\xbb\n\x87J#\xb7\xfb\x81\x1b\xbfZ;\xea\xb7\xd6J\xady\x030\xef\x1199}3\x1f\xcf$Y\x0e?9EW\x9b\xb4]$\x80\x1b\x08\x14C\xa9\xf6{\xb2\xa7\xf6\x1f\x10\x03\xb5M\xad\x92\xe8\xeb\xe7)Z$\xa6\xe4\x92\xe472[no\x9f\xc0\xb9\x947O\x97\xe6\xdaH\x1b\x9fE\xff\x05\xa0\xb8M\xe1\xd1+\xb9W2\xd7\xb2[\x05\x83\x83\xde\x98\x89\x01\xed\xf4\xcd\xecz<\x9c]\x9bq[\xb7\xb3\xdf\xe7\x9f\x01H\xeb\xd2\x81Y \xbek\x92 {se=S\xdf{\x18b\x0b\xce\xbe\xb8\xbf\xdd\x89\xde\x80\xcc\x9c5\x9f\x15\xaa\xeb\x05l\x839MB\xaf\xed\x06\xb7\xea\xdc\x18w\x0c\x05tq\xdc\xdb\x81\xb9o\xc1\x14D\x14\xeb\x9d\xed\xcdB\xca\x85\xfc\x04\xfc\xb3\xf5\x06\x05\x04\x1a\x91\xc4\x8c\xc3Ia\xd2Z\xeb\x8e\xdb-_:\x8a\x0b@\xe8\x0f\x98)\xec>\xc4L\xa1+\x1c\x8ao\x1c\x80C\xc1\x00\x8b\xf6\x97\x84\x83\xff\x92@4/\xfe\xae\xe0\xed\x9a\xc0\xa3\x81\xbf\x8df$\x99\xa7.\xc0>\x02\xec\x1d!<\xacw(\xd0\xb2\x8f\x00\xe9/\xa3W\x10\xbb\x87\x1e@|\xc0R\xe4\x0fm\xf3\x88n\xa9U\xf6\x8b\xb7\xa2d\xc6\x03\xcbh\x0f4\x05\x8f\x0b\x1fDW\x8c\xa0r\x8e\xdb+}\xfb\xa7Efy\xf4\xc88)\xcfiz\xe0\xa6\xe9p\x83\xbd\xd1\xaa\xa6;Q?4^\xa4\x0b\xdd!\x87F\x83|0q!\x058\x1a\x8909DdHW@7F\xa0\xc9\xc3\xf3+Q\x0f\xc4\x15\x95\\e\xe2p\xabrD\x9a\xf2\xc0{Y\x8a\xa8$\x91Y1\xc5j7\x8f\x19\x97F\xb2F\x8a\xa4\xad!\x8a\xca!\x8aE\xda\xa8\x16\xe9\xb8\xf8Hi\x12\x9b\xd689\xb4\xce\x89\x83\x8a\x11\xd8\xa2to\xbe\x99\x90\x91n\xcd\x97W{\xe9\xcdn\xad\x8e E\xbf8\xc1\x03!\xea\xc1\xad\xec\xd0\xfcj\x8f\x7f\x82QI\xed\xf3a\xea\x13\x9b\xdce\x03\\\xb0\xe2\xea|r\xedw\xd8\x06\xc7j\xd3\xe7\x1b\x13z{M\xdf}\x18d\xees\xe8\xbd\x1c7\xc5b\x14\xc7#\xd7\xe9\x8f\xce\x12\x95\xda\x89*\xe3F~\x91}\xb6\xb5\xd6o\x15\xd0\xfb,\xf7\x08\x06\x96\x85\x8f\x1e\xd9\x89x\xe9t\x9d\xb7)\xee\xc3\x8d\xaep\x03\x05\x87\xc3\xcd\xc1m\xbc\x9d\xb3\xcdQ{w\xdf0\xc6\x8d1\x81lm\x03\xd0\xf9h\x9b,m\xa7\\4\xfb\xeb\xbc\xd2\xd6\xc1\x01\xb9\"\xf8\x90\xbdJ\x866\xe9J<\xa8\xf8\xafc\xb3\xb6K2\xf0\xe9^\xdb\x0dn\xb5\xd1\xed\xa1\x1e\x91B\xaf\x1a-\xedIA$\xceF$\xfb\x10\xb6{\x04@\xdd\xb8]A\x03\xac`3\xd8Z\xf4\x8d2m>J$\x1d\x8f\x13I\xb7!\xf8\x98\xfcs\xddlKK\x0e\x11t\x82\xfc\xd3\x89'$_\x9d\x07A!\x05pZe2\x92\x8f\x8f\"k\xf3\x8d\x1b\xf9m\xd6C\xa8B\xf4x\xe1\xb5\x1b}\x9d`\x0d/\x86\x86\x8d\xf4\x89^a\xa6\xf7\xc5#>\xba\x1c\x81\xd2\xa0j)W4\xd9gE\x1f\x89E\xfb\x03\xd8\x12\x14\x13\x14M/\xdd\xc5\x18\x91\xf6\xab\x08\xb9\xb7b\xa7\x91\x1bu\xdfF\xd8\x82\x81\xd1\xbd\xb9\x8d\xb0\x05\xb0\xf4\xf15=x\x1b\xa1\x08\xee\xbe\x08`X\x83oW\x1d\x8adT\x1e\x8du7d%%\x0ciCX\xd2\x05i\x89\xd9F\xa0\x18\xb2\xb1\xfdW\x02\xfb\xcb\xfc\x02^\xd3\xb1\xe2\x01\xb6s\xb0\xac\x83\xf9\xb4\\\xf8\x03\x1a]_x\xb5\x14\xe4\xa5/\xdb\xee\x0f\xfa\xda-\xf0\xa6\xc8j\xb3f\xb7T\xa5\x8e\xd6<\xe3\xb4\x95\x82\x8d'\xd0\xc9\xc1a\x90J\x17@\x1e=\"t8\xcc/\x88t\x01\xadn\xec\xd3\x06\x9a\xef\xbe\xfdP\xca\xfc!\x92\xf8:x\xb8\x80\x1ch\x94,H\xc6\x9b\x11\xb9\xff\xc7\xfd\x04\xe7\xfd\x04\xef\xa3\x1d\xba6\x8a\xcb-\xdb\x87\xe2\xfd\x04\xb7\x91\x9a\x0f\x1e\xb6.\x8d,\xaf\x8f\xc5\x07\x95s\xf1\xd4\x11=\xceZ\xf37\xde\x14\xcc}\xce\x0fP\x13\x12\xd5\xaaE\x9dH#\x19*\xe8\x90R\x971\\\xdb\x0d(\xeb\\O\xc9\x7f>^\xba\x82%o\xd51>\xb9$\xf4\x82\xf8m^]\x88\xa1Is\x1f._\xa5]._\x99_\xdc\xc1\xbb\x0b9\xe8\xe1\x858i\xa9\xf9\xe9\xcdM\xd7\xfb\\\x9aN\xe0j*\xda\x0c\xa4\xcd\xd2b\xbe\xd0\xd3\x11\xe1f\xf1\x15\x97\xca\x01rSYzu\xa2\x03K\xc9\x1d\xf5\xa8\x8b\x19DY\x8c\xaaQ\xac\x8eP\x1eV\x96\xf3CMw\xb4\xc1\xfb\x85\xec\xef\xf2an\"\xeem\xe3\xdc6\x86\x1f\x8d\x88\x1d\x8e\xb0r\xfe\xf4\xb9#\xc0J\xd4?\xff\xb4\x92L\x1b\xe2\xae\x08vgbc<\x9d\xba#wD\xec\x16\xa7\x1as\x9d\xbbs\xb1\xd4\xa3\x89\xcd\xf4\xd4\x9diE\xbd\x1b\xe1{7&\x8a\xcb\xd3\x86`!k\x16\x98\x1c\xcf\xdd9\xfc\xc8\xd6\xf1\xc2\x9d#\xa4\xdc\xc4\x1ay\xda\x10Q\x86\x85\xc9\x8e\xa6\xbe\xad\xe93w\xb64[\x99\x1c\x9f7\xe5Ht\x8egg\xee\x1c\x81\x1f\xd9^?k\x18h{\x95\xc4\xac-\xcc\xdd0\xe0\xc5\x8b'&k\xc3\xb0S\x1d\x1e\xc8dk \xd1\"\xa8 \xe4\xf2\xaca\\Y$|qo2}\xd6%0J\xf6Q\x02\xa3\xe4^\x90\x9c\x81Q\xa8 \x8cB10JE\x11\x0c\xd9\xf7\x18\x81\x99}\xebG7\x8a@\x17\x16i\x1d\xea\xb4n\xe9\xb3\xb7\x81t\x91\xd8\xb7E\xcc\xd5\xbc\xc3\x1c\xc6\xabb\xbe9z\xf9J\x8d\xa1\xafXI\xf1\xf8f\xd63\xf1hU\x89\xb9\x0d\xa6\xdb\x1b\x15\xe3\xed\xf6\xc0H\x0bM\x9c\xd6T\xd0\xde\xd2\xd6 \xcc\x11\xce\xac7\x98\x9f-]\xe6:Y\xc5\xe7\xf5kE*[=\x86C\x9fG\xc6KLa\xd4KQ]j\x88\x02\x8ez\x8d\x8e\xac\xf6\x15u\xafI\x9c:4y([y\xd4\xdb\xb1\x7ff\xa2\xef\xc3\xe5\x97\xb3\x01\xe6W\xe8R\xd1o\xb9MP1l\x03b\x8f \x97$\xbe \xa2Mx\xe2s\x01\"\xcbI\xc1g\x08\x04\xe2\xd2\xa0\xfc\xa0@\x19!\x10\xce3\x86$N\xf1\xdeb={)w>\x17\xefG\xa5\xe90\x1b\xfd\x8e\xfe\xdb\x0fNIy\n\xf2!G\xf7\xf40\x98\x97\xc4o\xd6\nF8x\x91q1s\x02\xc3\xc9\xe7\x11\x8e\xd3t0\xc0}\x84{W\xd6\x18\xe8\x187z\xaa\xf5\x97`\xef\xd4z\xbb\x9dM\x12\x16\xad\xfdh\x8b7\x04S\xee\xcd\xf5H/\x1b\x06\x95\xe0d\xe8R\xa0\xf7P\xe4\xe1;L\xe8\x0f\x9aF\xff\xd8\x802\xcdaO\x1ct\xc7\xeap\xfcF\xa7\xdc\xd9\xaf\xc8\xb1bB\x9dd\xf1:\xc2\xa4\xb7\xbe\xf0v\xc4mw\xed\xd1\x94\x91\xe9\xd9\xcc\xfd\xe1\xf3\xf3\xa6\x0f/\x1a>m\x1a\xad\xa7\x9f65\xdf4(\xd3\xf3\xc6\x91o\x82\xebE\xd38>w\x8c\n)\x98\xd29vbk\xb6\xa1Y \xda\xcb5\xf9S\xeap\x94\xd5H\xec\"\xcb.\x80\x1c\x192\x06T\x89\xd7]7G\x83\xc1\xc5@\xd1&'G\x8e\xf4e\nE\x82\xd4\xb6L\xe8\xbb\xe2UJ\xa3\xad\xf4!\xa3Z\x87\x83Q\xce\x82\xca\xf6\xe2\x1f \xe2w\x1e\x8b\xaa2\xc8\xc9;\xa7\x0d\x17E\xe2v[?=\xbc\xd8\xff\x82\xf1\x81\xd1#\xe1h\x8f\xc8\x89p;\x9a\x85\xd3\xcb\xb3\xd2\xf5TSYyV\x9c\x88ck\x98\x1e\xacA\xbb(9\xa0\xc6\xb0\xf4\x19U^>\x9eS\x12\x7f<>\xac\xb9\xb0~\xd4\x1c\xcd\xfb\x9d\xd4\x189\"\x15\xab\xc9\xedE\xce\x14+\x1e\x92iC\xe8\xd9\xe2\xefC4\x1d\xec\x90\xfe\x9d\xe4[\xe1\x1d\xe5kh\xabE O\xdaw\xbd\xc5\xdf{\xf70\xd7Xzi|\n1SG\x87\x81\xd7\x80\xa7\xf1F\x1c\x02\xbc\x03\xd0N\xa3\x11\x0d\xeb\xc1\x13\xb7C0\x1ch\xdfiv\x17\x0f\x87\xe8\x19\x9a\x93\x96;\xdf\xb1\xa2rq\xe3\xfd\x1b$U\xf1\xc7RF\xd8\xa5\xc5\xb59\xb8\x0e\x9c\xa2\xc0<\x7f\xfe\x02\xfdP\x13\xbd\x19;+\xf4\xaa\xb7X\x9c,z\xbf\xfe\xe4\x9f\x1e=\xee\x0f\x9e\x0cG\x93\xd3\xd9\xc5\xe5\xd5\xcb\xeb\xdf\xcc\x97o\xde\xfe\xf9g\xf9\xfe?\x8f{f\xe3\xd2\x1bt\xbboQ6\xb4Z\x92\xabb$\xa9\xca\xe5\x8b.d\xd5\xd2\xd4\x96\xad\x8a\x92\x9bk\xa4\xf3\xf3\x06\xbf\x8b\x07(\xeep\x18\xe3\xc5\xdf:j\xf9\x8d\x8e1\xf1\xb6\xf0\xf9\xf3\x17\n)\xcc]\xb0(\xbf\x88\xd0\xc4\xc8\x8c\x8fg\x85\x10\xc3+r>r2w\xcd?\xb4\xc3J7\xca\xebM\x15\xf8\xf4\xea\xb6B\xbb\x90\x96N+\x14\xa2\xf2 \xb6\xf9\xc7/\n\xf3k]\x1c\xb6\xb1_5\xbf5\x0fuo\xb1\xe8\x99aV\x1b\xc1\x8f\xb3\xea\x8eE\xe4\xd29F\xb3\xa0\xa0c\x89\x1c\xe3*\xc8\xee \xb3\x11\x01\x0f=\xbc\xb4\xa1\xcc\x0c\xb5\xfa\xfcE\x93+\xa1\x8b\x81*\xe8\"w\xa4,rE\xe8\x12\xc3\xd7\xc1_\xb3\x0b\xb0\x84\xac\xdc\xa7)D \x81\x93\xbf\xe6\x8d,\x85sx\xb8\xceH\x0fAIU=\xd4\x85>>\\\xc0\x19+\xa8\xae\xf2\x00\xb6\xe5\xc5\xd7\x85_4\x84\xed!\xa4\xd9i\x85_\x08\x93?'\x8bh9\x04\x93]\xd2k7Q1\x91|\x9a,S\x0e1\xa6\\\xde\xa5\xb5u\xd2uU\xc4E\xca\x93G\xfd\xfd;Z\x1cJ\xb2\xadu>m\x91\xb1\xcf\x1b\xd6N\xdaN\xf2\xdb\xed\xd7R\xf4^\x06w\x91[\xb257\xfe\xcb9\"\xf3u \xce\x94\xbc$g\x18\\\xa0\xda6\xd8.\xcf\xc0)\x96\xd3\xa7\xb9\x82\xee|0\x02\x03\xca\xab\x83\xd7\xdcL\xaef\x9f\xe7~\xee\xed\x8c*\x9c\xd3|\xab\xb9\x00\xd0\x01\xaeC`\x9ec\xdc0\xb8\x99n\xda\xaa\x81\xcc\x15!\xa8\x05\x0d\xf3\xd1\xa74T\x93\xc7O\xb2\x08\xce\xc9\x98\xa4\xa3FF\xacWt:\"\x1c\x0f\x89\x1c@\x9a%\x97\xe2A~\x8c\x8e\xe4u\x0b\x10>.k\xf4v\xdd\xd8\x19TC\xb6\xf6\xd7\xb6\x80\xceH\x9c\xf7\x161\x0f\xda\x0dY[Xj\x96\n\\\xd2T\xc3\xea@\x11\x9b\x01\xd1\xc4\x82b\xef?\x9a\x8d\x17\xbc\xd8P\xa8\xd7$\x1e\x8f\xc9\xcc:\xc1/|\x84\xe7\x18\x1d6]\x82\xa7\xe7&\xa1%\xfa\xc0\x18J\x04wSxjou\xe6}\xd6\xc1\xd4;\"\xd7zF1\x06\xaa\xd6%T\xe6\xd8\xa2K\xbb\x15\nk6 m3\x8c{\xef\xf6\x98\xd6\xb6\xcb*\xb4\xf8@\xc3\x97\x02\xef\xb0\xdd\xd7\xd6qv02P\xa2\x90Y\x01\xe7A\xad\xfco\x963h\xdf\xfd\xff*\x8c\xa1\xb1\xed\x7f\x13|\xe1\xd9\xd3\x0elAg\xfa[p\x85g\x0d\xee0\xdb\x98\xc2\xc9\x95\xae\xe7\xef\x8e-4\xf5&\xe7\n\xad9\x8e`\n\x1a\x0b\x1f\xce\x13t\x05\xff` \x9dX\x82\x1f\xa5\x7fc\x96\xa0Z\xfc\x07K\xa8\xfcZX\xc2\x8b\x06w\xc3\x7f\x0b\x96\xd0\xd8\xf6\xbf \x96\xa0\xdd\x9e\xb5\xb3\x04\x9d\xe9o\xc1\x12tS\xffNXBSor\x96\xd0\x9a\xe3\x08\x96\xf0b\xfa\x81,AW\xf0\x0f\x96\xd0\x89%\x84\x94\xdf\xfc\x8dy\x024\xf9o\x8c)\xd8\xe46\xd3 \xb3f\x89\x0d\x00\xc50\x00\x14\xa8\xfaT\xea\x8b\xe76\xf5\xf33\x9b\x8a\x9e\xe9X\xd53\xdd\xd1Q\xb9\n\xfeR\xeb\x03\x9b\xa1-}-=mH\x0fZY\x98\xe7Z\xc6\xc2u4\x85\x97\x0c\x1a\xc8\xbb\xc8\xc9;\xeaZ\x03\x18\x89j6\x8a\xa1\x95=\x97\xaaU\x0f:\xdc\x16\x81\xd2`5\x0f\xf7\x9a\xfa\xa8\x10\x1e\xeb\xab\xa7\xcf\xc85\x8c\x02\xf4x\xaa\xf0\xe3i!\x9a\x1f\xb6\xee\x80\x91\x16U\x10H%bt;o\xda\xd1\xd5D\x85\x1c\x91u\xe1\x0c9>G\xa7\xb0\x1e\xc0\xc7\xfb\xda[\xad\xad\x80\xf7\xe3\xdc\x15\xf3\xc9t\xa0\xd0\xbc\xbe|<\x1a\xc1J\x9d\x91\xcc1!4\xc25\xe5t\x07\xbff\x81\x1f\xa63\xe27\x10\x97\x07\xd8Z\xe4RO\xf5\xdap+\xe2l\x9a\x0f\xce\x12\x17Nm\x06uF\xa9C*&\xb0\x01\xc0\xb1O>@\\\xfb\xbb\xdcW>z\x84\xfd\xd3s\xa4\xbax]7\xb7\xb0\x01\x05\x90\xad\xa3C\xea\xd3\xfe\x1b9\x7f\xb3X,\x07\xfd\xc5b\xb1\x18\x00\x83>9\xcc\xf9U\xb6(?K\xd5\xb1\xf8\x80\xcc\x18s\x08\xe3\xdc\xd4\xde\x07}p\xfc\xe1\xc0O\x9du\xe0\x87+2_\x0e\xcc\xee\xac\xfe\xbd\xe0V\xd4E\x0e\xe2\xc3\xe8Xv\x0cR\xa7\xcb\xeb\x87\x84\x8d\xac\xac\x1b\xdc=\xd6\x1c\xa1\xba\x17S\xbd\x93s\x7f\xa9\x06\xaf\xde\x03\xa8p\x96W\x9d&\xb8\x9d\xa9H\xfe\x95%ZXCqm\x07\x90\xd9\x08x\x1fc1\x1d\xbbhJa/\x9b\x17M\xcbU\x1d\xc5\xba\x9e\x92\x97\x07\x8c\\N\x1c\xf8ZM\x83 \xd6\xad\xb54EGo\xb9\x16\xd4\xa60\xc8~9K#k\xa7\x93\xe5v:\xf4\x82\xf0\xe3\xa3\xa3\xf3\xc3\x81\xd7\xa6\x0d\x02}\x87\xa2M\x81\xd5y\xf7\xc0\xeahG\x04\xfd\xd4\xe4\x8e\xab\xe1B\xd7\x8a}\xae\x96cT\x11k2\xe3\x05\x10\x05#-\x12\xe1\x1c5\xc65\x8f\x96\xcd\xe4\xaf\x1bMk\xaf\xfc\x12D9\xad\xaah%|\x0e\x82\x11\xbb \x86\x8e\x98\x1e\xb9\xb4\x08Y$f\xe4\xacN8\xda`\x84\xa8\xcd3\xe2\x82\xb1\x94\xb1\x99~\xcf\xe3\xe5\x04\xdan\xec\x08~\xd6\xd2\xc7\x87R\xf2\xd8\xc1\x80\xb3\xd57\x0f\xa0\xf1\x05\"\xcaK\x04\x94~\xc4\xc0\xe4\x05Y\xe4\xecY\xd5u\x99\xd1\x99|\xe6\xd0\x99\x14\xe2\x8a\x9e\x8d?\x9f\x9c\x80\xf2\xf4\xc9pqzum\x15\xa6\xc3\xdf\xe49\x96\xfd\xebY\xfe6^\xfe|6z1}_\xf8>\xb8\xee_\xcf\x16\x93\xa3J\x0c\x9e\x0c^\x9e\xd6\xf56\x05\xd8&\x8b\xf1\xf2\xe7\xe9\xe8\xfc\xf9\xfb\xc1\xac?\x7fs\xf9rqwv6^\xdc\x9d\x9f-U\xd9\x87\xf3\x91\x92n\xa7U\xc2z\xd1\xa8}\xd0\xd4\xa3_\xa5\x16\x9b\xa2\x13\xaa\x97\xbd\x82(\x04\xaa\x90H\xab\x0f)\xb8\xab?\xe9s\x9b9\xab\xc5\xa1,\x94U\xbb\xa1l~\xb6\xd4\x8dL\xf5\xd5~\x0f\xac\x08\x02\xb5\xe7:\xb1\x02C\xd1/W?(\x8ba\x1dd\xef\xd6\xfd\xc3\xc1]Be\x1d\x1c^\x96\x02|\xe69(\x8e\xd6[\xba\xc2S\xb2\xaa\xe3\xc3\xa3[\xed\xb2\xcb8\xb0\xb2\x87zF\xf2[\x98\x03E\xedN04i\x94\x874\xb5\x13\x986M`/\xa4~ b \x87m\x93\xe9\xfdc2K\xbf\x8f:\x99iu2?\x0e\x91.\xd2\xa6y\xcf\x8b1N\xe7:\xf6\xeb\x8e\xe8(\xa5\xfa\x0fD\xe6\xa4\xab\x18CwR\x0f\x0b\x99?>\x04\xd6\xf48\xfe\x05\xb7u\xf0\x17#\x94\xfa\x18\xffs\x0d>\x1d\xads\xbb\x8d\x80\xb2[\x16\xc3\x1f\xfdo\xb2\xd3\xd1E\x9f\x9ec\x04R\x81\xd9\xd4_(\xee\xd3;\xf8\xa3\x9b\xf6C\xfcW\xbfE\x1b\xa8\xc7O\xf0\x95\xfb\xa9\xf9;Y1f\x13'w\x89W|\xces\x05\xb7\xef\xd4s\xb0\xc6\nq\x19\xc0\x13\xf6-Lyb\xfeB\xa9P\xfc\x84 Y\xa2V\x85z\x8c\xd8-|\x8a6\xf8\xc7\xc7\x7f!\x16i\x14a\x7f\xe2\x84\xfe\x94\xb1 \xf6n`+\xa4\x92\x92\xd8DD\x85b\\\xa4\xf0\x9e2\xbe\xf7=\x86\x8fij\xe2\xa1\x9a\x81I}\xb6\xc7\x8f\xbe~G\xb8\xd2\x10\xffD!&\xc74\xb1C`_ \x0b\xfa\x84\xec p\xca\xa9\xfeD\x188V\xe8\x19\x12;?\x0dY\x9a\x82\x06\x8a\xf4D\xf4\xf4\xfc\xd33x\xc2\x16\x05\xccr\xc6\x01\xae=\x0bC\xe8/\x0e\xc1-\x86t\xbd\xf3\x10j\xf5w\x9c\xa5L#\xca]\x18\xf0\xc4\xb3`\x15^\xb1T\x88\xd3\xf8\xee\xe9\xe7\x93\xe7g<\x7fDd\\\xfbYx'8b\xe8&\xc1?\xf8 \xb1\x82j$\x16\x82z\xbb\x90E\xf8v\xab\xfe]\xb1tG1\xf4\xec\xca\x17^\xeccX\xde8\x80\xb9\xf6h\xa0g\xdd\xdb\xf1\x18\x83\xda\xe2\xd3\x98\xdd \x16\xa566o8f{\x16\x89\x15\xf7\x05\x1bS!X\xb4f\x98\x1d \x0c<\xee\x01\xa8u\x10\xd1q\x12\xd0\xfb\xd4\x8f\xb6\xda\xbf\xa3IR\xb9\xa9\x1f!\xea\xaf\x05T\xbe\xde\xaf\xd4\x1f\xb6>\xbfQ\x7f7\xd4c\xc2GX6\xcc\x84\xf9\x8d\xb6:\x84\xaf\x9f\x02zma*\xb7\xbe\xc0?\xef\xc28\xe1\xb1 \xc0\xbb\x154\x80\xbav\x1e\xae\x04=+~\x82\x7f\xb8^\x13\xde\x0b\xfd\x17\x97\x85@L\xfa\x91BK?\xe2\xdb\x0d\xbbO(\x16\x08h*60\xe0j\xd5\xe0\xa2\xa0[\x8dD\xa1M\xe17:%G\xa5\x10\xeb\n\xd3\xf1\x8e\x05zYE8wa\x16\xea8\xbf\xe1\x1e\xa0\x03\x19[=\xc4\x88; \x0dB\xfc\x9bPN\xdf\xbd\x03\xa4K\x02*L4\xe3\x84\xc7w\x10\x1f8I\xef\x01\xce\x9f2\xc6!\xc1,0\x96\xc6\x19\xc7\x95\xc5\x11iyz\x1fA^.\xf4\xb2a^\x1c\xad\x03\x7f\x83KL\xaf\x88t\x8bk\xf0\xe6>\xc1\xf4\x10\xa6*\x8d\x835\xc5\xc0\xc5I,\xfc\x0d4\x96\xe2\xc4\xa4\x82Q\x00+\xc5\xee\xa8\xd74\x01\xc7)\xb0\xc2\xa2-\xc0\x94\xad\xa1\x81,\xe2\x8c\xc2r\xcc\xc4\xf9\xd9\x19DaVx\xc6}D\xd0\xbd\xcfn\xc79\xf4\xb7l\xe5a\xf6[Aq\xf5\xdd{\xfe\xed= \xc3\xdd\xc6GD\xbf\xe3\xf0\xe9>L\xb7\xbc\xb7|8\xff( \xf9\x9f\x0e&\xbf\x7f\xfd\xea\xdb\xb7\xaf\xbf\xf8\xe7\xb7\xdf\x7f\xf5p\x01\xb8\xa2Eq+\x17+A\xf8I~CE+^\xc8Ic0}\n\xc7\x1aE3\x05\x14\x97\x9f\xea;\x8dN\x97\x0e\x06\x17\xa7\x15\x8d\\\x8a\xe5@u\x04\x98\xac3?\x9d\xbeW\x99\x1f\xce*\x8b\x97v\x1c\x04\xab\xc0\x0f\xeb\xfa\xf8\xa7\x9f\xb9\xb9\xa3w(Z8\xde8\xdd\xb8/\xa9<}\xee\xd6Iy\x9a}\xbai\xa6\xbf1f(9\x93\xf1\x0c'+\x1cI\xa0rA\xf1\xe7\xde\x1dF\xaa \xe6\xd3\xa5b %\xdd\x14\xb9&\xa0\xa1\xf8&\x12}\x95\xc1\xe85\x06#2}\x01\x01\xd6\x8b_Gd\x8aa\xb6\n\x97\x81\xfc~\xa4j\xa1}\xa0\xcc\xb4\xff\xe2\xf9\xf3\xa7OK;\xf2\xa0\xcc\xb6\xea\xc4\x1am6\xc0p\xa8\xb1k)2\xe9X\xf1\x01\x05J\xb5\xa7%\x98\xf8\\eY\xb6\x00\xe1\x14\x95\\\x0e\xec\x1e\xfd\xc2\xfe\xeb\xca\xb3\xac\x05\xb5\x99c\xf2\x95\xe0\xe1\xf6[v\xa7>\xfd1k\x88\xca\x01\x07*iC\xc4\x0e\x1am\xbf\xe3l\xe3\xdf\xcd\xd4\x8e$\xdaft\xcb\xc6.\xed\x8b\x1f\xdd\xf8\x9b\xfb\xc6\xf8*7\xaf)\xdf21sJ\x03\xe2>\x89!\xa8\x08\xe3\xee\n\x809\xa63\xd2\xfb\xeb_\xfe\xcf\xbf\xfe\xe5\xff\xfa\xeb_\xfe\x8f\xbf\xfe\xe5\xbf\xb8\xd4]\xfev\x17`\xfc\x91(\x0b\x1cJ\xa8\xfc\x8clF\xce\xab\xa7\x1c\xa5W/\x0e\x938b\x91p\x8e\xb5\x17s\xe6JW?\x9e\x05\x10\x8a\xa5\x07\x9e\xe4z\xa3<\xea\x8b\xda\x1c\x19+\x19|\x03\xc9E1\"x\xd7\x83\x88{\x1f\xca\x05v\xbb^\x8e\xaeV\xfc\\=\xd8\xa3\x0eA\xfd\xa0\xe7\x08\x83\xe8\x98mto\xd7\x05th\xbe72\xce\xf7\xd4\x06\xd9@`\x1aV\xcf;F\xd7\xc8 {;T2\x890\xb0}\x0f\n\x9fu\x90\xbeB\xd0\xa6\x91\x8e\xa5\xdb\x0dv\x1c\xc7\x83\xc0\x17\x02w\x94b\xa7\xe8\x00)\xc5\x00&y\\\x8e<\x14K5FH!\xc2\x87\x0dHR\x08\xef\x82\xbaP\x07\xfc\xbfr\xbf\xfd\x83,\x14?\xfe\xbb$\x0b-\xcb\xae\x0d\xab\xff\xce0\xc6q\x1d\xbe\x801\x8e\xaf\xff\xc0\x18\xf8=\x04cj\xe9\xe4(F\x82\x0c\xa1\x13\x0d\xfd8\xf4\xffCh~'0?\x94\xd4\x1f\xa2\xf1\xff\n4\x1d\xb6]\xf9\xd2\xe4\xc5}IU\x98w\xaffS\x0b\x83#&jf\x1e\xfez<\x8e\xeeQ?\xbf^s\x86\x07\x04\x943\xcc\xc5\x85\xef\xa1\xde\x97\xa6>N&\xcd\xd6>h=A\xc9\xbaZ\xfb\xf8\x07\x93|\x18\x99\x95\x1d\xda\x12:\xac\xe25\x8c&\xb6\xbc\xca\x84\xd0z{\x1a\xed\xf1D\xcb\xa3\x890\xca|\x16 T\xa6{~\x19\x9b\xbc8\xd0\x7f\xb6<\xce\xf0\xc4+W\xef\xe7\xa7]\x82\x1a\x1cZ\xe39\x18\xf3bNE\x8cZ}d\xe9k\xa6$ d\xf2\x1b\xd4\xf3\xfb\xf8\xdd\xc7\xc32\xcc\x05\xb5\xb0\x80\x99S\x0b\x06\x03\xb6\xf1Y\xb0N\x99\x8e\x11\xb5-\x00\xbf\xf1\xb7\x19\xd72\x01\x96P\xb2\x81>\x1b\xd0\n\xf1\xdd\x14\xfe\x05yl\x87\x87k\xa0X\xde=\x87\x7fA\xe9\xaf\xd6\x83\xf9\xab\x0f\xe2l\x9f\xf3\xf5\xa3\xfe\xc2,\xf8!\x0c\xbf\x1f%x.\x88a\xdbz7+\xa8\x04\xacw\xe0\x81mY\x84IP,\xa4x\xde\x12\x9aC6\x08\xe5\xa6\xfe\xfe\x94\xe1\xf1I\xc8\xa2\xcc\xfc\xf5\x05\xf6>d\xbaC\x11\x9e+F1\xce+\xceN\x9c\x08\x0bil\xc7%\xce\x84\x06\xcd\x9c\xad\xe1\x9fxk0\xef'\xf5\x0f\x9e\xe9q\xc8\xc8\xb3\x15\n\xb6\xf0\x0f\xb5\xe7\x00\xa6\xca\x94\x05\xfa<%\xdd\xd1u\x0c\xc7IiH\x03\x80\"\xd7\xc9\xa7 \xf5\x10\xdc4\xa1XPp\xff\x86\xe9\xa7\x18\x89N*\xee\x11\xdb1\x08]/\xcd\xc2\x90\xe2)\x05\x06\x9d\xd3R\xa7z0\xd8,`$\x05\x0b\x93@\x1f8*\"`V\x90P\x13\x0f\x0f(\xb4\x9a\x195gG\x82\xe3\xbf\x14)\xa0\x80\xbc0\xd6\x19\xf4`\x8f\xc7<{\x7f\x8d\x07\xb3\xb7+\xdes\x04\x8a\x03\xa3\xb0^\xba\x87^\xe0\xd2\x0d\xc46\xb8GQ\xd9<\xafQ.5\xaff&i\xe4\x87T0/\x0epm\xe8\xf706c\xac\x13\x04\xa7Qj\xd0\xd7\x92\x81\xc2\xea\xf5\xb9&\x16^\xe0' \xc5.\xaf\xd9F\x0b\xd1)\x9c\xe5\xb0 \xf0\x93\x14\x17\x87\x1f\xd8E\x81\xcb\x04\xcf\xcb\x0c\xdc\xf0`\x84\xe9\x1b\x86G\x9a\xda\xf6\x1e\xe8\xaf\xfdK\xf9\x96\xd3\xb5\xaf\x97'\x9cnq|J\x11\x97\x99\xa0\x862\x84\x06\xb2\xc2_\xa1+O\xe2\xe0~\x1b\xdbG\xcb5\xe9\xda\xa7A\xb1 n\x90N\xe01q\x8e9\x10\x01\n\x9e\xee\xc3U\xac\x0fq\xef\x84\xf9k\x1a\x05\xabzx\xd0\x1d\x14\x061\xed\\\xef}\x06\xe8\xbc\x87\xae;f=\x82Y\xdf\xb0\xdf\x06z=o\xd8\x97j\x12_Q\xc1\xfd;\x93\xa0\xc5\x88\xd70{z\xb819\xd5\x94U\xbdF\xfb8\xd8\xb3b\xc9\xdf\xf9\x9bM\x96\xb2o\x958\xa3\x99\xb2JL\xed\xde\xf3\x15\xd2\x0bH\x144\x12\x90\x13S\xbe\x0e\xe2XC\xf4u\x16y_\xe4\x8f\xbf\xcd\x1f\xff9\x7f\xfc\x1e\x1f\xff\x99fi\xea\xd3\xe8\xb7A\xa6\xe1|\xc5\xf8\x96\x15\x1e\xff`E\x8aW1Ovq\x10o\xef\xf1\xfd\x8f\x9b\x8d\xa1\xc5\xa87,\x80\xf3C\xc2\xbc,\xa0\xbc\xdc\x97\x1f\x92\xb8\x98\xe9\xb5\xb1\x84`\xaf3\xbe\xca\x02%\xb4\xb8F\x1d\"r\xf4B=\x8f!\x8b\xb4e\x89z\xe6\x1c\x97P\x08\"\x0f\x9a(l8\x05\xc4\x0f-^\xe3\xe9f\x08\x04\x99\xad\x91\x04\x84a\x16\xf8h\xea\x81\xa7\xb0H\x92\xd1\xd8!\xdektN\xe8z\xad\xabMv4\x121\x92b\xae\x89L\xc8\x91\x00\xea\x83\xdc\x04\xa8\x1e&\xfc\x84\xe44\xbc\xb7\x98\x1aj\"\x17j\xd2\xa6\xde\xcd\xa3%s!\x92\xb7\xd0\xa0p\xa8\xa1\xcd\"\xcd\x90\xf0 \x00t\x8cU\x0cc\xf5k\x14\x8b\x1c\xd2\x1a\n$\x9e\xc7\xb4m\x80%\xeb4\xf0\xb7\xfa\x01\xbfd\"V\x12q\xc0\xb4,A\xbd\x1b\xc5`\x10\xefW[K\xbcV1\xd7\x90y,\x08\xd4x\xe9\xf9V\xafj<\xcc\xeb\x8ey78\x94V\xc0\x08(2!/`Hvm\xad^\x8cB\x82\xfa\xab\x97\xa9\x17\xc7|\x8d\x89\x9a:A3\x8a!\x8cW4e\x86g\xd2\xd436>\xe6L\xcf \x84M00\xd3w~\x98!`\xaa\x8a\x8d\x9a \x16y\xf7&A\xd59Nw\xfe\x06\xea[1\xbd\xd2V>\n\x1e(!\x16\x96/ZB\xa9\xbfc\xc3o\xe1E\xed\xffz\x95u\x1d\xf3\xb1Z <\x89\x03j7\x1f\xf5\xe41\n+i\xfe9\xe1\xb11\x9e\xc3\x04\xce\x14)4\xf4\x05f\x07\xbb\x80\x8b\x1d\x12Pf\\#k\xf5\xe2\x08\x18'&\xf1\\\xa8]\x03\x97\xd5Y\xf7~\xaa\xf7,\xc8\x14\xd9z\xcbB\xcd\x06Y\xc0\xf6\x16j#\x04\xf8(\xfc\xaa\xbf\xe3XQ<\\\xf9\xf0nF\xa0 z)V=\xb6#\x82\xaf\xc5bq$\xc6\x1b\x1a\xfaA\xfejP\xdb\xbe\x8c\xe9\xfa\xc7,\x15y\x9a\xe0L\x8bA\xfa]c1\xbc\xed)\xf7i\x94\xe7\xbe\xb5h\xb6A\xd9\x03Z\xda\xc2\x06i\x0b\x1b$`\x9dc\x83?E\xb9\xd0\x08eY\xe4#\xe34 %i\xb5@8u9M\x1a\x950Y\x9e8D-?\x82va\x99\xdf\x00 7\x98\x00;\xb5\x1b\xd8\xa9)\xb1L\x17\xbaa\xf7\x89\x929R\xfd\x92&\x10X]\xbf)n\x00\xcf\x96\xd4\x02%\xcd\xc7,`\x8a\xd6\x8d\x0b\xecI\xd5\xcd\x82\xd0\x8ac\xf8\xae:\x99S\xe1@K3\xf9\xe4\x05\xb16P\x1c\xb3\x84\xef\xbc\x1d\x8d\"\x16\xa0\x00\x84=\xbdw\xa4Asw\xd0\x8f;\xe8\x07\xca\x1f*7\xfc\x03_\xee\xe1\x0b\x18|\xbf\x8b\xe3\x90Fk%09d\x94\xac \xa3\xf4P8\x81U\xaa\x97\xb4\x15{Vl\xcf\x02-k\xdbM\x9a\x17\x07Y\x18\xa56\x13\xbe[r\xad?kQm\xcd\xa28\xb4Y\xd7,\xd1:\x0d+\xcb\xe7l\x1a\x1es>\x07\xbbG\xf5\xc05ykbA\x81\xc2\x1f-q\x17H{\xc4\xc4\xce\xf7n\"\xad\x17\x0b\xecV.\xb0\xfaT\xb5\x05-\xef\x83T\x8a]g\xea\xc50j\xf5\\\xe0\xba!\xbd\xb3_\xfc\xc8>\xc6{\xb55\x81U\x03\x8dFqNL\xa3,\x1f\x07#\xad\xf3\xf8\xd6\xa6\xf1\xf8\xd6\x8e!\n\xcc\x06w\n\xe23\xb7\xbd\xe0\xb6\x17\xb8\xe7\x05\x03\xc5\xfc\xb5\x00\x95\xde\x13\xfb\xef\x98\xde[\xf8Z\x8f\x07\xe8e\xb5\x80 \xb5L\xc2\xbeh\xe2\x03\xa2\x88V\xe2\xe9 \xffV\x96L\xb3\xa4\x9ar\x1f\x86Lp\x1f\xe4\xf1}N}\x0e\x8b\xcex\x83\xe3.\xf0\xa3\x9b\x99\x99\xe3\xbb0\x98i\xebzH\xb7\xe2\xba\xfa`G\x03\xaa\x9cA\x8e\xde\xb2`?I\x8a&\x8f\x81\xd3\n\x89T#7\x9b\xab\x9d\x17$\x1a\x8f/\x06\xa8\xe8\x8c\xb6=ru\x05\xa6\xa6\xf1\x86\x88\xb9\xb9}:\x87[\x98\xeaO\xe5f\xd9\x88\xb0\xb9J^6x\xdf2\xa6\x9b\x95\x83\x0d7\xe4^\xbb-\xae\xebp\x93h\xf5\x16^\xa6\xad\xb7\xaf\xbdc\xfb\x11a\x03\xf2\xc7\xd5\x8f\xcc\x13\x85\xf0\xf2;\x9a\xfe\xf16\xfa\x8e+\xd1A\xdcO<\x1a\xc0\xe0i\xcf\xd1\xba\xd7l\x1e-\x1d\x9eT\x8c\xc9N\xc3\x91\x0d\xd1\x80o\xc0\xbb\xdc\xcf\x8b\x9f\xe7\x8bt\xf1\xc3\xf2\x89\xd4\x7f\x17\xef\x17\xefO\xb7a\xbdG\x89*p\xf9O\x95\xec\xff\xf4\xd2\x99y\x0d\xd6jk*\xe8x\xbe\x18/n'\x8b\xec\xec\xec\xb7\x9f\x8e\x17\xd9\xd7_\x7f\xfd\xf5\xf2\xd4q\xf2\x08%\xd4\x12\xc7\x12\xcb\xe1'\x8e\\{\xc8\xd5\xbf\x9e\xe1\xff\x1b\xb9\x13\x03\x91\xa4\xd7\x12o\xd6H\xc1\x02\x89\xd7-\xa4\xe7\xaf\xe5]\x98$\x83\x99\x9c\xbf\xa1\xe3wK9\xa7\xe3w\xc3\xc9b\xbc\x1c\xf6\xafg\x90\xa6\xdefK\xf9\xc9`P5\xb7#\xda\xb3\x154\xb6\xb8\x1d\xe2\"\x93`\x829se\xde\xaa\xccs\xd5\xcd\xb3\xb3\xb1\xfas~\xa6\xfe\xfd\xe2l\x91M_|\xa6\xfe\xfd\xec\xec\xabEv\x8e\x9f\xcf\xcf\xce?W\xff>\xdf,\xb2\xa7ggg\xcb\xd3m\xbd\xca{rEz\x06 \x8b\xf8\xff\x03hf\x15.\x18%m\xed\xe3D\xc9\x0f\x8a\x86\x90\xeb\x03\x16\xe5\xa4\x803XC\xdd\xa9\xee{2\xeb^\x0b\x03\xc0\xda\xe1f\x13\x10\xd1x\xa6\x18,\x18\xe1\x15\xbe\x81M\xa1\xee\x86]\x13\xe4:\xef\xec\xac\x05\xd2&\xea\xb3r\xc3\xedoH\xff\x0b%\xb5M\xfc\x14\xfe\xf6Y\xa3\x85\xa1%Sj\xd1\x9f\xe1=z]\xc6\x98\xb0_\x10\x01\x11\xe7\x0d \x13\xc3\xe1\x80Ds\x81\xebU,\xeb\xcb\x95\x14\xdc\xf5\xd5{\xd3\xb4\xba\x11\xe4\x0d\x8f\xc3vG\x80\n\xda\xb7m\x07\xae\x85:{J\x00\xd9\xf8\x11[\x17\xe7\xec\xd6\x8f\xd6\xf1-\xb9\x06{\x002\xd3\xef\xe5&\x9d6\x83v\xe4o\x9d\x8d*\xc8\xbe\"W\x84\xf2m\x06\x86`&\x92\xfcK\x8c\x0d_\xf0B`\xb3\xcc\xcf\x96\xe4\xba\xfc:#o\x9b\x02\x9a\xde\x95\x0c`\x9b&\x95\xe4\x10\xdfV\xc7\xd2\xfc\xde\xbb\xbd5\xdcM\xf6\x8c\xa7\xaa\x8bW\xa47\x9d\x9cM\xd4\xae\xfan\xc2Y\x18\xef\xd9Z\xc7\xbd>\xf9\n\x9ck|5Y\xc7\x1e\x80\xad^?\x87~\xe5i\x93(^\xb3\xd7\xf7 \xb3\xb6\x9bw\x13?\xfd!K\x92\x98\x0b\xa8\xead:\"wu0\xd4(\xfe@\x8aU\xb9\xc7\xe2\xcb\x06\xbf~\xeaw\xd3\xf2\xed\x8b\x0eu\xff\x11\xf2\xfcN\xe7\xf9\x9a\xd3ms\xde\xef \xef\xef_\xbf\xfa\xf6\xb5>p\xfc\nO\xa5\xdd\xd9_C\xf6?\xd4,\xad\xcd\xef\x95\xfd\xfe5\xe8\x83\xdc\xb9\xbe\xc1\\4dk\x95\xf5\x15M\xdc\xf9~\xb4\xfc\x1a(\xd27\xe4\xbaRLM\xddW\x93W\xf1;H\xfcB\x08\xae\x12g\xe4\x1bw}\x7f\x80v_\xb3\xbb\x86\xde}\x0f\xdf\xbfD\x8b|w\x96\xdf\xe1\xd8\xfe\xf1\xd5wp[\xda\x9d\xe9[\xc8\xf4?\xbf\xfa\xf6\xf7B$\xdf\xb3\x9f2\x966T\xf7\xa7r\x0f\xbf\x85\x1e\x96\x0b\x92\x19\xf9\xd6]\xf8'h\x86Ej\xff\xf6\xa7\xef\x1b\xfa\xfcu\xb9\x85\x9f\xa0\x05[\x86\xcc\xc8O\xee\xb5\xe4\xe4\x17\xdf5-Z\x85\xf6\xef\x14\xf5\xfd\xff\xd9\xfb\xda\xae\xb8m%\xe0\xef\xf7W\x0c~zR\xfb\xe05\x90\xa4\xb7\xed\x06\xc2!\xb0ii\x03\xe4\x02i\xdaK\xf3p\xcc\xaev\xd7\xc1k\xed\xe3\x17^z\xcb\x7f\x7f\x8eF\x92-\xdb\x92\xec%iz?\\\x7fHXk$K\xa3\x91\xe6E\xa3\x99`\x9c\x92\x8a\x88\xdc\xea\x18\xdb\x10\xc4\xff\x8f@\x98D\xd8\x16S\xfe\x08\xe8mBRI\xc1(c1\xc27\x94\xdb.\xd5\xc8\x87u\xf0\x15\xeb\xa0\x1eK\xbf\xc0\x0e\xbc\n\xa2\xc5\x92\xf7\x1b\x95\x14=\xe4\x8f\x08\xc9G\xc9\xa8\xf0P\xb0u=\xf4{\x84\x9e\x91\\ ${u\x7f\x1e\xce\x18\xb5\xea\xe1\x7fRZ\xef\xb7\x80\x7f\x83\x1d8c=\xa7in^\x97?\xa3T\xdc\x9e\x82\xe6\xae\xf6Kc\xa7\xffE\xf4\x85m\x10\xeat\xf0\xfdr\xaf\xdc\x88\x8e\xe8Ds\xf7\x8d!\xfd\x07\x8c\x8c\xa6\xed\xd4W\xb0\x03\x86\x95\xffo\xd8\x81\x89\xbe\xe8W\xd8\x81\xb9\xbe\xe8_\x18wM[D\x08\xec\x80F\xa4cON0(\xa0\xb6,aez\xcf;@F\x05;\x10\xbb\xffy\xf0\xe1\xe2\x03\xa3\xceq\x98\xbbW\x188\xeb\xca\xcd\xf1\xdf\x04\xffM\xf1_\xeay\x06\xdeH\xed\xdf\x89\xf4\xdf\x89\xb0\xd5\x10\xff-\xf0\xdf\xcc\xf8\x85\xd0\xfe\x85\xc2^\x9c\x11Cb\"\xc0[\x81\x96\xc21\xb1\xb0\xb3\xa9\xadpi+\x9c\xd8\n\xe7\xb6\xc2\x1b[\xe1\xc2V8\xb3\x15\xde\xdb\n\xafl\x18\xba\xb4\x15\xde\x12\x8bB;R\xc8\xa2r\xa0\x91.A\xd2\xa3\xa0\x8a\xf7PZ\x93T\xef\"\xe1\xe4\xc3\xbdD>\x98d7\xed\x97J\xcf\x12\xe1(V\xb9Gq\xa7\x1aSkg\xb5\xd6\xb8a\xb99}uh\xf8\x98R\xc6*\xb1\x97\x85ZI\xfb)\xa5LVB\xfaw\xde\x9d\x8d.\xdf\x9e\x9e\xbc>|3\x92\x9fz\xf2\x04\xa6\x81\xfa\xde\x17\x9b\x14\x0f\x82'\xfa}\xb9wz\xb8\x87\x0d\xfab\x9b\xaa\x17\x1f\xec\x9d\xcbb\xdc\xa8\xe4\xfbw\xc7?\x1f\x9f\xbc?f\x8d\x9f\x9f\xec\x9f\xbc9C\xa5a\xcb\xe7;\xd648\xdb{=\xba|}rz\xf9\xd3\xbf\xde\x8dN\x7f\x93\xa5\xcbF\xe9\xf9\xe8\xe8\xed\x9b\xbd\xf3QY}\xc2\x01\xde\xffx\xf2ftyp\xb2\xff\xeeht|.\x0b\x17\xbc\xf0tt\xfe\xee\xf4\xf8\xf2\xe0\xe4H\x16\xcc\x9a\x05\x97\xafO\xf7~P\xab\xde\xb7 \x0e\x8f\xde\x9e\x9c\x96\xe57\xbc\xfc\xf5\xc9\xe9\xfe\xe8\xf2\xd5\xc9A\xd9\xe3\xab\x1aR\xce\xf6\x8e\x0f\xcf\x0f\xff\xcd\xbav\xe4\x8b\x8dI\x96\xfd<\x1a\xbd\xbd\xdc?9>\x1f\x1d\x9f\xfb\x9ciV\xc4\xf1\xee\xf4\xf0\xf2t\xf4\xc3\xe8\xd7\xb7\xac\xe1\x9c *0\x0c\x11\x91i\xd5f\xfc\x05\xdfa7=\x9cZ\x0c\xecI\xb4\xbc\x0dy%\xa7OT\xdb\xf8Z\xb8%Uh\x80\xd8M\x88\x0f\x8c\xd7\xc6.%>D<\xb3\x97\x84\xcbnf\nX^\x82\x85\xe5_Y\xab\x02\xd7Z2\xa5^\xd2]\x8f\xed\xb3Gj\x97\xd2\x12\xb2P\xebx\xb8\x9a\x0e\xf8\xa2(\x87\xbe\xb3\xc3\xa4\x88\x12\x11c7!\x1e\xd6b-U\xf0UmF\xad\x08Oy\xed\x88\x94\xbf`\xecRQ\x9b\x12\x15\xbe\xaa\xcd&\n\xc9S6\x13\xbbgD[\xe8!\x01\xf0\x8e\x95.Wr\xee\xb8\x85\x94\x1b\x96RB\xfe \xb8*\xab\xb7\xc2\x82\xca\xcb\xdc\xa9\xe7\xf3\xadu\xaa\xdd\xfd\x0c\xdc\xed\x84\xf46\x18\x94J\xbe)&\x82\xfa\x08\xbf\xeb\xa1\xc6Z%\x9f\x07K\xce\xb1<\xbd\xb7\xf4\x04dv\x08\x92\xa0<.:\xb6?\x8f\xe2\x89\xc9\x9c\x01h\xd1\x1b\x87\xf9x\x8ey8\xbaZ\xa7ENR&\x92c\xe8rs\x93\xab \xfb-\xe9\xba\x9e\xac>\xdd8XiF\xd8S\xfa\xf0\x0c!g\x1a\xd3\x9e\xfc\xcd\xb0\xc8$\xea\xce\x16\xa6)]\x0c\x1bv\xf6\xe6\xf3\xd0c\x06\xac\x94\x06\x9f86\xb3p\xa1>\x9f:\x14\xf3\xc4\x89\xae\x97\xd85\x9a\xd8\xf4\x9d<\xef\xbf&\xa5a\x96K2\xf61\xdbNf\xe4\x13M\xc1\xbd\xe1\x1b\x12\xca\x04\xdb|$/\xb77\xc4\x1f\x0e\xac#7\xb8\xee\x9a\xbfn\xeae\x0f\xfb\xc8k\xdb\x92\x85&\xd1\x98\xd1\x0ej\xb4\x03r\x0b\xef\xcc\xc3dO\x1a\xa4$[\xd2$C\x1b$\x1b\xacT\xb4\x1d\x1f\xd2\x80.I\xe2:?\x8c\xce\x1dq/e\xc86\xe7\x0d\xc6\x18_\x8c\xe7a\x9a\x91|\xa7\xc8\xa7\x83\xef|D\x89/\xd2\x9a\x06\x19I&.#@\x8fGE\xa9>\xf3\x08Jb\xd3\xb1\xef\xf5\xc0%\xfb\x92\xcb\x06}\xe0\xf1\x18\x83\xafS\xba8\xc33D\xb6\xcf8e\xdf\x9d\x9ek\xd3\xdc\xa7\xf2v\xfc\x93'\x90\x97\xc6 !\xa8\xe3\x95y\x9e^\x94uIg\xdap\x1d\xc7\xf3\x82+:\xb9\xf7L[x\xa2\x16L\xa34\x93\xcdc1\x13\xc4k\xdb3\xa3\xc7\xf7\xfc\xbc0G\xe9oW\\\xb1\x81\xa1\xb8\xbf\xe4]l\xb6\xefw\x81\xde\xc8]7\xd70 \xd8v\x8c\x00\xca-\xads\xe2~\xbd\x9d\xdd\xcc^n\xcf\x80\xa2\x8f\xf0\x0e\x06~k\x0f\xd3\xf5\x9c\x97\xdb\x1b\xb3\x97\xdb\x1b\x0c\xfck\x03#$\x01\x86\xdb:\x13.\x19.j\x91\x18\x82\xc9\xbd\xe62\x82\xbe\x9e\x9d\\\xdczW\x97/\xb7Qo{\xb9\x1d-f\x90\xa5\xe3\x1dg{\xa3\xf1\xe6\x0eh\x82^\xf2;aL\xd2\xdc\xdd\xf266\x9c\x97_{\x9e\xa6\x83\xc0\xd4T\xae7\xed\xf3N\xea\x11o'\xb6\x07W36\x86\xe7\xa3\xfe{\xa3 \xd4\x1f\xc5Ir\xc3\xde\xf9\xe7\x9fl\xd1\x12\x1f\x8e\x82\xb3\x1fO\xde_\x8e\xde\x8c\xb8\xac/_\xec\x9f\x1c\xd5_\x9c\x8f~=\xf7\xbb\xa9\xa1\xf1\xf9\xa3\xe0\xf5\xe1\x9b\xf3\xd1\xe9\xe5\xde\xfe\xfe\xe8\xed\xb9y\xf5\xd5s.\xd5\x8b\xb4\xaf\x0fWFE\xa9\xfd\xee4\xb4\xdfs\x8d\xf6{\x8e\xb1l D\xe8U6&t\n\xe70\x14\x07\x9d\xa6\x86\x88\xa6!\xc2\xd5h')\x16W$UM\xdd\xa4<\x02\xe2\xc7\xba-\x9f\x07\x0ep\x1c.\x0c)O\xf5\x88\xf9\xd8\x12\xb3\x1a\x973\x9b\xcf\xcf\x17\x04]+\xd8\xff\xc1\x94\xa6\xa3pN<\x95\x0c\x8eQ\xfdT\xdf\x9cb\xe8/\x8d\xcfJ9\x7f\x86 \xce\x03\xc6\x99\xf6\xab\xe3 \xed\x91H\xaer\x07\xcewJi/S\xfb\xf1\xb1\xb3\x89R&\xb3@f\x8a`\\\x05\x969\xe1\xb9\x1al\xf9\x7f\xa5\xf4Q\x91m\xddA\xa7{J\x8a%M\x1a\x13\xc2\xe7\xa3\x83\xfd\xf3\xf3\x8e!\x18\x8eH\xe4\x13\xc61\xbd%\x93\xf3p\x96\x0d!\xb1\xa9f>\xac%\xe4\"\xfd\x80\x01\xff\xd8\x1f]\x8b\x80\x8d\x80\xab\xb2k#\xach\xc2/ \xa2$#i\xbe7\xf9\x18\x8eI\x923&\xdeG\xc4\x01\\i\xed\xba\xae\xb37\xcdI:Bg:\x06\x90p\xc1\xe0\xb3\xc9\x94\xcd\xf97c\xadk\xff]\x9b\x12\x1eT\xb0%\xd3\xf0\xd7\xca1]\xf9C\x0f\xbb\xb6\xb1\xbd1\x0br\x92\xe5.Q\x97\x10\x97\x0eV\xd2\x9d*M=\x18\xc74\xe1\xaa\xa0m\x03\xaba\x99'9\xa9:P\x06\xe8c\x1d\xf4\xc1y\x12\xe7/\x1c\xcf\x93\xa6*\x99\xeaA\xdd\xf7\xb9\xb8X\xfeS\x1fO\xd9\xde\x0f>8\xc0$G\xf9\xe2+\xfe\xc2\xafW\xa8\x82J~\x01,\xa8\xdf\xdd\x81\x84\x0d\x93-\xe2\x90\xd1\xa3}[\xddZ\x85\x0b\x9c\xae\xc8\x05V\xd6\x07\xedpiO8\xda\x13.\xea \x17\xf6\x84+\x1e\xcd\xf2\xca]\xbe>;<\x82j\xc5a\xba\xb6>\x86\xf4v\xcc\x15\xdd\xc3\xda\xe4\x1b\xb5.\xa0\x89\x0e\xfa\x970.z\x82_\x13\xb2d#\xd2\xc7ki>\x82\x15T(\x18\x0253\x04\xd0\xebJ\xea\x83\x8ebl.\xc2\xd2\x11\xac@_\xd6n\xb4\xc8\xec\x92(k\x84\x17\xc5\x07/H\xc2\x05\xf1\x91\xf4\xf2\x00\x0f\x98\x82<\x8d\x16\xae\xe7\xf3\xa0\x85u\xbe\xeaC\x16H\xd4\xf2\x04P\xfc7\"\x8f'\xeb\xc8\x02\x89\x1e\x91J\xb3\xc9m\xf7\x94\x18\x96hJ\xe6_W\x1a\x92\x07d\xb8\x85Q\xe4o\x87G?8\xca\x8e&\x05\x9d0\x88&\x1e\xd29\xfb\x8b\x13\x14w^\xab\xbc]1\xa0]\x10.\x97\xf1=\x1e.\xbf%.?\x8e#\xfcG\xc2\xff\n\xcbL\x12\x91\x07/\xa1\xe0\xbcA\x95PD\xb5\x88\xa3\xc9\"c\xc8\xc7\x90\x12Q\xf7\xa0\x93\xca\xe1\xf1\xdbw\xe7\xbaa\xf2\xbb\x0e\n:\xf0f\x1d\xb7\xb6\x0bs\xf9\x05E b\xad`\x7fy\x1eF\xc5\x8d\x92B\xe3\xc7\xa0{\xd8\xc8\xb0\xb9D3\xec\xc4\x07\xc7Qp\xd5\xd9\xa2\x9d\xcb\x83\x18\xaeB(\x18)\xf8\nY6\xf6d\xad\x1c(\xa7\x03\xfe\x9b\x0d\xcfM!J`\x8f\xfd\x8d\x7f]\x13\xcf\xe8P\xd9|\xd8G\x05#d\x04\x87\xff\xa4\x9dl\xcf\xc3\xa3\xb6'O\xe0\xdf\\\n\xa0^\x8f\x99\x079\xfb8P\xac\xfe\xebc\xaa\xf7\x1b\x18\x88\xc1\xad\x95d\xc0\xa9`E\"\x00\xd1\xcc\x19V\xee_\xa7\x1chN\xf8\x18+\xa4\x12\x82\xb4\xd3w\xcc\xa0\xb6\x86\x97~\x15RPn\x0eT\x04\xc1\x1d{\xaa,0\xdc\x80\xc8m7kw\xe4\xc2\xa4 |\xe8\xa6b\xf5\xc1\xb0\xa2\\\xe6\xfe\xd7g\x18#\xa8\xe3L\xaby\xea\xd5@\xf7\xea\x82N\xd3T\xf3i\xaf\xf8\xd4\xf3\xd5\x93\x01\xba\xb4\xc8h\xea\xb3\x82\xb8\x0f\x9d\x83\xb1\x97\xb6$@\xad\x94alb\xa5\x03\xa5\x03U2\x04b?\xd7\x92wM\xfa\xc8Tl\x13:b\xed\x99\xa9\x07\xf9}[\xa6:\xc3\x80>\x07'G\x0e7\x87\xb0\xc1\xbe\xc0\xef\xa6AB\xeer.X\xbf\xf0Z\x0c\x98W\x14\xa1B\x92R\x18;&n\xc2\xb5\x9a\xa4\xd4\x8f\x14\x8d\xff\x049CU\xe6\xf9p\xcajX:\xde\x9a ]\x97\xf5\xb3`\xbcxr\x17d\xa2\xb1\xbe'|}g\xa3\x8f\xf4\xddG\xf2\xee#u\x87\x1d\x924f#\xe4Qqa\x07\x9c\xdf\xef\x9e\x8d\xd7\x06\x83\xdf\xef\x9e\x11\xc6\x88K\xf3\xceZ\xa5\xeb\xe3\xdetH,\xf7\x0b\xa0\xed\x0b\xab\xd4\x0fr\xcaO1<\xc8\xe7)\xbd\xc5\x83\x1d\xa68\x8e\xd2\x94\xa6\xae#\x8b!\xca \xa19\x84%\xf2M\xce\xb0\xe5\xf7Z\xbd\xc5AU_t\x19\x0b\xd7~t\x12\xa5\xf9}\xf5E\xde\x90\x0f\xe1\x15M1N\x8d\x81x\x8c(]\xab\x1d9t\"J\xb5\xbd\xde\xbb#\xecp\x98GcnHa\xc2\x8a\xce\xec\xd2\x84\xeb\xb6\xe6\xe8\xec\xb1\xa55\xac\xde\x9c\xdb%w\xb2\xf6\x04\x19\x18\x1a\xa8NtV\xdd\x1b\xc1t\xb3M>f\xcc\xcf\x91\x9a\xf7\x08\xba\x916/1\xd4M\xdf\x1e\xf0,\xbb\\HK\xf8\x19J} x\xf5#\x06\xc5a\x98\xed\x04k\x9b\x9eW\xb7w\xbf:9\xf8M\x88\xcb\x95\\\xbd\xcb\xf7J\x18B\xc2\xb4\x03\x92L\xf8\x99Xj:$\xb2\x0bdH_\\\\_\x9b\xe0\x7f\x03\x99-\xb8\x14N\xb6\x1d%\x7f\xb7}\xd5\xac\xc9\x91\xa3\x80+\xea\xf0^\xf3\x9b2\x06W \xfd\x14\xf0\x93\xe6\x13\xb6}\xa3\x95\x8b\x1f\xef\xe9{P\xdeC*8kJ\xbc\x17\xb8\xef\x15u\xae\xc2\x0dL\xb4\x86h\xca]x\xd8T\x1f\x13\x97rnB\x8d\xdc\xe4\x80T\x85\x9c\x9dP\x91\x8c\x98\x1a\xfa\xc60\xb3\xb0\xdae\x18\xc4\xacCG\xc1\x11\xb2-\xf8'~\x9e\x904<\xf0_\x80\x8a\xa6\x17\x1e\x845\x02\xe9\x81C\x90\xf4\x82A\xfb\xcd0b^\xef\xb9V\xc2\x80\x7f\xe3]:\xf3e\xaaK\x1f\xc2\x15&Z4\x88G\xb3\xea\xd9-#\xf2\xd2\x94\xd8\xaa\xf9\xc0\xd6dF\xf2}\x9aL\xa3Y/\x1b\xd8\x1e7\xd2r\xdfdMly\xd6\"\x06\x8aj\xb7ij\xb2rW\x95.\xcf\xfaf\xc3\xc9\xe4GJ\xaf\xfb\xf2\x7f\xfd\xd9\x03\"\x1c\x8f\xa3v\xf8\xa9\xd4\x9f\x7f\xe2^\x84'Sh\xc6\xcc=\xcdU\x8cj\xf3ju\xc1\xf4\xfd\xda\x99\x97^\x90n4\x9b\xad\xd4\xae\x1c\xc5\x85F\xa7Q\x1a\xde\x8b\xe3V\xdb\xc6\xa6\xd1\x0fW\xdbZ\xed\xe5\x832\x16\x9e\xce\xb6\x0c\x8b\x9c\x8a\xa2G\xc5W\x16\xfev\xfcpS\xdeSvs\x1f\x9c\xcbK\x92\x1d\xd1 \x0f\xd3S\xef\xfc\x0d7\xe0\xa9\xa9\x02\x94\xd5)O\x8cb7q\x9f7o\x15PQ\xf0\xb4Y\x10\x89\x82g\xcd\x82P\x14|\xd3,(D\xc1?\x9b\x05\x99(\xd8T%f\xf6b\x8b\xbd(\xdf\x94:F\xdc\x9ey\xf5\x06, *T\xe0\xe9\xb1.\xa8\xaf\x88\xaf\xd6\xf4\x0dlF\xd8\x05\x81\x9f\xb1\x95\xee\xca\x9e\xe5\xb6k\x9e\xee\xa6\x0f4\x10\x1f\xf6\xdc|\x1ee\xdc]\x95\x15\x84\xcd\x027\x0f./\xd1Twy\x89\xccb\xd3\x87T\x01\xf2;\xd3\x88P\xd0%\xbb>\xba\xaf\xab\xe0\xc5\x82\x93\xb4\xb4\x88\x99 \"[/\xaa\x8554]\xc3\xe4`lM\x0dM7<\x01\x0f\x0e3z6\xa7\xb7f\x92[Zmh\xe6\x01,;\x87\x18\xf7Et\x94Li\xba\xe01 ;\x88\xc2\xd2\xa1\xb1\xeds\x0bz\x15\xc5d\x08[OWm\x96\x8aqz\x96\x91N:q1\xed\x84\x98wB\xc4rg\xf8D\x0cXx\x08\xc9\xaes\xba|\x0c\x9a\xc2\x1eh\xfa\xaf\x1e@Q\x0e@\xa7\xb3\xd5\xde<|\xf0|\xe5*\xc2\x83[\xb5Y\nS\n\xa3\xcbe)\xec\xc0\x18\xdf\xfe\xbd\n\x8d\x0fy\xf0SF\x13\x14\x15\xc2Kn\xa1D&\xad\xbc\xbd\xa24&a\xd2|\x8d\xe1\x03\x9b/\xb9\xe9\xb1\xf1\xf65M\x17\x1a.-u\xa8{\xa6*\xb5T\"*KZ:Q$JZzW(\xab\xe8\xb4\xa8{\x9d\xde\x95\x89\x82\xd67bQ\xd0\xd2\xbb\xb8\x94\xd7\x14\x88\xa6\x08>n\xbc]\x8aF\xb6\x9a\x8dp\x01\xed\xdb\xc6\xdb\xb9\x04\xdfj\xf5\xf3F\x16\xb5\x86\xb6\x90%\x9b\xdf\xb4\x061\x13\x89\x8a\xb5\n\xe1\xfd\x97U\x08\x97\xe5\xba`=\x08\xa2\xecT\x84\x85\xf6\x95\xa20\xb9\xf7\x1b\x90\x96bN\xad\x86\xa6x\xa1\x0f7\xe5\x9b8\xcar\x15\x82\x91\xb5\xedw\x98\xdc\xd7i\xf5\xaa\xe5*t\xa3w\xf2\xa1\xc9\xfe\xf9\x86\xb6]\xcd:\xff\x1c:\x7fK\xb5\x97:\x7f\xd6,\xd0\xe9\xfc\xaaF\xfe\xa9:\x7f\xac\xb4U\xe9\xfcuK\x80Q\xe7/\xd3J\x1dD\x93#\x1eG\xb6\x05\xf9\xd7\xa9\xff\x93([\x86\xf9x~\xc8t\x860\xe6\xceP\xc6:\xdc\npc\x07\xe2^\xd2\x92\xc0\xf5\x1a\x17\x1aCS7\xe9\xe4\x9d:\x16\xff\xf7\xd9J\x90\x84\xbb\xd0\xc3\x97Z\x17~:\x90\x18\xd5\x90h\x91\xd8W\xb0\xcb\x14\x08;5\x1c\x0e\xe4AN\x7f\xe2\xd7\xaa9{g?]\xd3a\xbb\xf4\x8b\xb4|.F\x17\xbb\xfc~i\xe9\xfe\x18a\xb8\x9a\xbf\xe0\xa6\x80>*\xa9\x0f\xb4=\xe3\x06\xc6\xd3\x06\xac\x9di6c\x02\xfa\xb88x\xa8\xc5\xc2\xe3\xf9\xaa7_\xc0\x18\xb6\xa1x\x01\xe3\xf5u\x0f\xe2\x8b\xf1\x07\xb5\xe6\xc5X\x13kQ\xc6Y\xc4S\xe5\x1d\x03\xf3\xc3=\xae\x93\x01\x8e\xc38\x16\\\x90\xf8p\xc1\xea\x96\xc1$\xb8\x9e\x96\x96\xdbQ\xaf\xc3\"\xe9\xae\xaez\x8er\x92\x17\xfbh \xa2`\x92\x80G\xec\x0e\x18\xa0\x88\x81X\xbeC\xba4,<\xd1\x9a\xec\x15\xe3\xb2\xf2\x9d\x90\x90\xb4\xc7Sl\x1c\xa3\xa4X\xac0\x16\x81\xe7\xd6\x17\xf5\x1f@\x9bvK\x14a\xf4\xf4%\xe4\x89\xbf\x81/\xf6c?+\x08\x0f]\x8c\x96\xf6b\xb4\x9c\x87J\x99\xb8\x8b\x87N\x08\x8f\xf3d\x8c\\\x07\x82\x85\xa6\x01I\x8a\x85\xd92\xcd:G93\xdd\x15\x7f\xb8\x1e\x0c\xf1\xac\xb7\xe82U#Ou\x1d~\"c\xf3s\xea`;V\xbe\x02u\x8b\x1a\x95\x91Jw\xc1\x89\x12\xcc\x07\x84\xd7\xab;\xee%`\x90\xa8Zm\xda\xa3\x96\xb8\x9b\x80\x82ff\xe5]P\xd1\xaceF@\xb69Z,\xf3{q\xa5b\xcd\xc2\xa2\xa0\xc6\xcb\x90\xc8\xd5\xfd\xc0X\xcft\xbb\xd3\xb8\x86b\xdc\xfch\xba8\x08\xf3Pn\x80\x11\xba\xbb\xaf\xb9\xce\xeb\xb2 JD\x0c\xda\x8e\x83\xa3\xdcu\x0e1\x91\xa4]\x10\xa9\xed\xb7b\x8b5Q\x89\xd5\x82\xc6\xea\x0eEs\x96\x9e}\x12\x1d\xadNC\xad\xa9\xeb\x92\x90e~\xaf!\xc4\xfa dk\xd3\x84\xa0\x85|\xdf\x03Q\xcb0\xcbni:\x91\xb8\xe7R-CFU2\x94\xb9\x07\xffk\xf0\xd9\xbd\xc2\x16Q\xf2\x06[\x1b\xda\xfcK'\xe4\x8a\x16\xc9\x98\x9cG\x0bB\x8b|\x08\xcf\xbe\xb1@+\xa1\xe7\xacb\xe9_0\xdb\xad\xd7\x9fU\x02\x95\x16\xcf^\x02(1\xdc]\xef-dJ\xf3\xe8c\xad\x1e<\xae\x06Bc_\xcc\xd1\xf7\xf5\xc2\xdf\xaa\xf2R\x1ady\x98\x0b!\xc0(\x9c\x1d\xe6D'\x9cY\x1c\xae\xd2 #\xf9\x19k\xba\xba\xdao\x8d\n :hg\x91ri\x88Kj\x19\xc9\xb98f\xacd\xf2\xefW\xb0g\x184w\x98b\x03\xef'\x8fj\xc6k\xbd\x1f\xb0\xcax\xe5\xa5<\x11\xce\xe4/\x19o8\x994\x07\xbb\xcaX\xfb\x04\xc4\x10T\x06;p\xe9J\x8a\xeb\x12\x8a\x04\x06\x048w\xcaslau\x1e\x8d\x80\xd5U\x10\x0d\x1az`\xa1\xdfx\xff\x82\x01\xe2B7^\x9c\x15\x1f\xaefF\xdbH\xed\xe5_\xa3-\x95\xd6\xd7\xf7Q\x1c\x9f\x921\x89n\xf0\xb4,\xeb\xa1@\x19\xe7J\x92\xde\xda\x8e\xd0\xa2\x94]\x8f\x89\x7f\xfc\x9d\x9cN\x9bB\xa0\x92\xa3~*:\xf9\xd9\x17\xb2\xa0\xdau\xc4>\xba$?=\xec\xa7KR\x84\xedV\xed\"\x84\xebR'C\x84\xeaR'\x0b\x842\x99OC\xbc\x11,\xb4\xbeP\xd5\xfa\xec\x06\xd4\"\x88\x92)I\xb9\xf8\xe0FA\x94\x93E\xd6\xedhV?Q\xe9\xe1s\xf6\x8ag\xf7\xef\xf0\x1f\xcbP\xb7\xb5\x88W\xd0\xa6h\xb3&\xbc\xec\xd2v\xe7\xd2\xd3\xed\x13\xb5\xddy\xd7\xc6\xaeH\xd5\xe1\xeaR5T\x92\xb5R;\xecQKf\xdf\xed\xbe\xb7/\xd6\x9c\x85\x96\xa1\xad=\x1b\xa2\xbf\xd7\xa0kz1\xfd\x9b\xf5\xe2\x8ey\x14\x0eW\xdc\xedc\x8dGC\x99\x04\x98]\x91\xfd-\xfet=\xd8\x86\xad\xea^\xca$X\x84KE\x10\xf2\x81v\x11^$\x84\xe6\xb4n\x96\xcf:.\x96\xc9\xd9\xb75\x0f\xe2\x13K\xdc\x10xZ\xd7\x9e\x92\x8b|J \x06\xaf\xf1\xf0[/\xd6J\xb6p\xab\x80'\xeb\x82j\xe5\x9d\x8f\x8b\xe5\xc5\xe6\x07\xbe\xe3\xc1:P\xcb\xdd\xe4\xce{Y\x1dsi\x1f-2\xa2\x0e\xa2T}\xbf>f4\x19\xf0\xed|\xc0\xf4\xeb\x01\xdb.\xad\x0e\x81\xa6\xeeY\xdd\xcd\xa0\xfbd\x05Z\xa7+\x1dF*)]\xf7]\x81\xfd\x04{\xf9\x94$\xa3\xaaO|)\xd8)\xc7\xde\x1dy\x9e\x13Y\x96\xbf\x19\xc7V\xf3\x124\xa6\xf6*O\xe0*O\x06\xd9\x02\xb4\xb3<\xe0\xfaH\xc7\x86K\x93\xfd8\x1a_\xf7\x10^\xd4\xa7\xc4^\xa5\x87\xb9]\x88\xb3\x11\x9d\x03\x03pL\x9e\xa8^\x90S~\xf4\xf3X\xd4\xad\x84\xb6p2\x01\x07\xd6\xab\xcd\xab\xc1\xf8\xb8\x1b\xa1\xf1[%B\x91#\x08\xbdM?06\xee\xbd\xc9\x04\xd8g\xb5\xc3\xef\xb4\xb4\xbc-R\xb2\x8a\xb5\xa5r;\xebeo\xf9\xdf\x81\xdf\xca\x07~\xabj\xa9\xff;(\xd3?\x7f\xd1AY\x97\xceB{\x1d\xa7\xd5\x0f\xca\x0c\xa7\x0bx\xf2%\xf4\x9b\xb4\x9f~\x13\xf69\xcc\xea\x10#\xc2\x9e\x1ba\xba\xbaX/Dz\xa5f\xda\xcfX.\x82\x08$\xb6\xdbFuA\x9d\xbb\xc6MS\xba\xf8\xe9\xccs)jYx\xff\xd3\xc9S\x9e`e\x1a\xc6\x999\xe1\x0b\xe8\xa5\xf9\xb2\x1d\xdb\x81\xd7\xaaB}\xb7I\xe1\xd3L\xe4\xa5\x07\xf1\xa3\xf7\xec\xde{\xb2\\\xa1\x9fl\x1f\xb7X\xc6\xd9\xc2\xc9H\x8esrN\xcf\xc2\xc52\xeee#\xaf\xbc\xbb\\\xf6\xe5\x19\xdb\x1cxm\x8e'\xcf%5w \xfd\xdd`\xa2\xb5\xcb\x1bEF\xd2\xf2\x990\xb4:\x0f\x93ILNVi\xfb\xa6\xccw\xdc\xed\xbb\xa1\x0c^\xe7\x03\xe8\x1b\xbd\x85\xe132\x80\xcf\xe9y\xb9V1\x81\x86\x9dO\x9d\xc3\xf2e\x9bdtw\xb4\xeb8\xf8B\x86\xbc\xffbN\x96\xbb\xce9\xb9\xcb\xf7R\x12>\x92\x9b\xd4\x0c\x0c& \xda\x93\xe50R\x9b+\x06\x04c\x1d\xf6\x08\x9e\xc4\xd8M\x16\xfda\x0d\xcfkF\xbddX\xac\x05d\xc3\x1fi\x94\xb8\x8c}x\xfd8\x97EGm\xb0\x89\xfa\x06\xa0\xad\xf5(w\xbe.\x11\x1f\x81\x1fu\xe3E\x1e\x86\xe2E\x87\x7fz\xc1\x818\x91F\xa7\x89\n,\xad\x17\xf0\x10\x92\xb58\x02\x8f\xef\xc2g\xbdt\xd3\xec\xa6\xe9n\x8c\xf8h\x98e\xd1,a\x8c\xcc.\xa6\xd7\x92>o\xf1\xfc\xceMuE\xe4y\xb6\xef\xf3\x95\xa6bJ\x03]~\n\x03'&=\xf3\xc2c(8\xb4Ta\xac\xe9\x1dH.R]\xa0\x89\xd6\x1b\xc9\x90\xeb$X\xa7x\xda\xc5\x9aK\xd1\x83XO\x9ck\x19\xfe7_@\x02\xdbj\xa2\x7f3\xf6@\x99\xb9\xfc\"1`\x0e\x90P\x99tG\xd2\xf0\n\x05\x8a\xdaO\x91|,e\n\xdb4\x9a\x15\x12hm\xb3L\xda\xc7P\xce\xe3\\\xa6\xc1m\x1a\xe5%D\x99}\xaaI\xa7\x845xM\xee\x19\xfe\xf5\x0b\xbe\xff$\xa8\xd6X>\xa1V\x85\x91\x07\x01u\x15\xd2\xe0\x99\xc3R\xf1\x9eG\x07l{\x157\xb6\x9b\xe6\xc5r\xa6\xd8\x14<\x02F\xbd \x14\x05[\x9b\xdf|\xab\x0f\x86Q|\x91\xbbOn{\x99\xf7\x92\x8a\xb5+{\xad\x9f\xb3\x04\x8f\xf5T\x8b\x80\x95\x9b\xc2\xa1\xed\x87IBs`\xeb\x12B\xce\xfb \xccj\xa1\xd8\xdas\xd2!\x90'}\xbd:\xb0\xa3D\xed\xd9)\x99\x92\x94$\xe32D\xdc<\xca`\x1ef\xc9\xd79\\\x11\x92@\xc4\xaf\xb1D\x19\x99\xc0\x00\xb2bIR\xd7\xabA\xb0\xa1\x90I\x87\xf8\xb0\x86\xc7\x0dJB\xc9Z\x10\x1fm8\xbb\\P\x81\x86F\x0d\xfa\x86X\x843\xc2\x98\x1f'\xfa\x93i\xcb-\xc7\xa2y$\xab9d\x93`I\xd2,\xcarSX\x05\xc9\x14\x92\xee\xd3\xbdd\xa5\xe3kU\x1f\xd0o,=s\xaf\xb0\x1e\xd2~=dO\xe9\x06\xf7\x92U\xe1\x82x\xe9\xcd\x86\xe1\xaa\x12\x9aGS\xbc\xe68,\xb7oxYU|\xf2\xa4\x02J\xf1\x88\xa8G\xbe\x066\xd8!\x08p1\xf8\xaeZP\xe1\xcb\x92\x91\x0e\xf4\xeayUd29\xb7\x89\x12\x13-%?\x93\xfb\x03zk7\xa0\xca\xa7\"\x0f\xa9C\x8a\xda\xfa pFI\xceS\xc20\xf1\xfe\x9a\xdcsdNi:&\xc7\x12\xed\xbe\xc85e0\x10\xb2.\xbe\x8a\x8b\xf4\x91\xfdcUM\xf4\xbbb?\xb8\x86\x80\xf0\x11\xe9\xd7\x1f\x1eQs\x1b6\xbd\x92\x86\xba\x84\x0f\xf9\xc8\x05^\xc4\x06/F\x83V-\x03\xfc\x8a\x84=\xb5\x0f'\xc1\x84\xf2\xf1Z*\xdb\x97^.L)\x8a\xed\xa5\x1b\x0d\xf2I\x82(\x13\xbc\x8e\xdf\xd1a\x02L\xd5)\xab\x9f\x19\xdb\x07\xcd\xcb\\\x87\xddGtg\xd3\xd7\xcf\xbf|\x90\x0e\xa6q\x91\xcd\xfbN#TS\x99\xf3\x9a\xb6\xb4\x13Hf\x8c!\xc7\xab\xb4\xafEk.\x1a\xb2}NOXz\xea\x97\x93\xd4\xa7cI\xc3\xc4$\xce\x18D|Z\xe5r\xad\xfeS\xca\xba\xec5\x9f\x98_\xa0\x86\x03\x1b\xc6J\x0c\xe3^$\x91d&--K\xec8\x81\x04\x0d\xb31\x7f!Wx\x14E\x9e\xa4\xac\x08\x0c\xa2X\xfe\xfeR\x0c\xe8\xf1i3{\x07\xdf\xc1\xa9\xee\xe5\"(\xdd\xe6\x98<\xd6f\x8c\xd8\x8en_\xa9Aj\xcd\x87\x9d\"\xa81r1\xb2\n\xf4=A\x07?\x83\xe8|\xc6\x84O w\xcb\x94d\x19\x93\xda\x17E\x96\x03\x89\xf29I\xe1\x8a\xf0\x06h\xaa\xc8\xd2>\x06\x1dv`\xbd\xfc\x90\x862I\xa5\"U\xba?\xe7N\xae\xc8\xdb\xa8\xe8Pz\xd4\x8ei\x92\xe5i1\xcei\xaaS[\xe4#g\xc0L\xef\x95F\xda\x8e8\xa0>R\xff\xb4\xbbA\xa9\xba\xec\xd0\x94\x8cICK\x92{\xbb\x02\x1bYM\xa2\x86]\xd0\xbe\x17\xf3>DUN\x8a\xe5l:\xeb\xa4\xc3t\xcf\xf2T\xa0a\xbd\xf2\x81\xf630\xbf\x8f\xe2\xf8S-\xcch\x95\xab\x8b!\xaeb`n\xdc\xbf\xe8\xb2\x97X\xac\xc9\x7f\x89K\xac\xdcH;\xb7\xd0D\\\xc6\xab\x8dF\xbf}\xe2\xe8k\x8b\xff\xcf?\xcb\x8c\x85\xb84+g[\xc5\x01\xb7Q\xd2[\x8f1\xddi\xf6!\xa9<}\xb5\x93Q~\xac1}I\xb7\x01\xb5\xe74\xbdK\x16\x9f\x83\xbc\xb8t#{k\x92Xzw\xf1o8\x97\x10\xb9\xbe\xec\xf4\xe5*\x91\x15J\x8a\x04R\xb1k\xbfM\x82\xec\x95\"\x9b\xbc\xbaG\xf5\xc6\xe68\xc3\xa3-TUNP\x1f\xb1\x9c\xef\x8a\x90\x0fB\xab2\x03\x16\x02\xd0\xde\\\x86PQ\xb2,\xf2S25\xc3\xc5}\xcd1\xf2\x916\x9c\xff\xf4I\x1aUZ\x7f\x89\x07y\x19\x96<\xf5\x98\xb8\xb3\xa9XA\xec&aR\x9a\x84\x13n\x12\xc6\xac\x85\xf6\xcfK\x1d\xca\x08\xf4\x80~/\x8e\xa0\x18\xc7\x07G\x12\x85S\x1aQ}pJ\xa2\xc0d\xd1u\xa2\xc0\x83\xfb\x16Q4\xde\xf2y\xe7\xed\x8b\xb9\xe5?\xe4k9G\xd6\xd3\xffqG\x0cKt\xf3\x86]\xcb\xdc\x95_/\x1d\x01\xc4o\xfd\xbe\x06C\x08\xfb\xb6g\x88\x17\x0eC#\x910\xba\x98v\x0c\x89\x95\xd3\x8e.0\x1c\x96\xe3a?\x8c=)z\xb5T\xadB\x99\xba\xb4(r\xaeueb\xe8\xba\"\xf3=\xd8\xd6\xdd\xd7\xad\xcd\x06D{\x93h\x8b\xc2\xad-\xa3\x0d\"w\n\xd9\xc1\n\x97\xf8W\xc7\x99\xa5\xe5\xae\xa0\xdc\xd3\x9d\xd1\xdd\x92\x8cs2QM\xfcmBIa\x07\x8e\xc3\xe3v\x01cz\xce\x85\xf0\xf09\xbb_\\\xd1\xf8\x83\xa6~\x04;\xb0\xf1\x7f\x7f\xcf\xd6\xff\xfc=[\xffjc\xd6\x86\x08\x11\xe2b\xb0\xfea\xf3\xeebs\xf0}8\x98~X\xffjC\xe3\xe6T \xe4\xe6\xd5\xc5\xe6\x96\x01\"\xe3\x10\xf4bs\xf0\xad\x01\x841A\xcc\xad\x7f\xa8\x93\x1d\xd8\xde\xaa\xa4f\xa9\xe9\x81B\xe7:\x11NM;R'\xc3\xd7\xed\xa6\xa6\xfa\xa62\x12OY\x0d\xf5\x7f}\x9b\xac\xa4\xdd,\xdb\x80\xc6x\xf6\xcb\xfey-\xe7\xd9\x91\xd6\xa7y\x949\x9e.\xec\xf2\xa4R\"+\x16,\xd3\xe4\xb4\xc1\xe7\xb0\x03Ga>\x0f\x16\xe1\x9dF\xac+K#\x8d\xf8\xd2\xef\xb6'\xef\xf028`\xdbNBou\xf2\xa7r^\x07\xea\xb9\xd8L\xaf\x7fH\xddC&\xba1\x1e\xa8\xac\xad\xf1\xac\x18\xb5 \xd2d\xddiz\xa7\xea{\xa3\x89\x9e\x08\xd2\xac\xa0\xc9\x97nK\xd3\xc2\xeat\xebX\xa2\xbe\x93\xe1\xba\xab5\xde\xed\x16\xd0hD\xa0BC\xaa\x066\xc0Z}\xf2\x04&B`\xf3@{i\xe5AM\x13\xa4\xb1\xcdc.\x15KF\xa9\x9b2\xa8PmBdF)\xdc\xbdQ\xe5/\xffF'U\x93\x17\x1a\xec\xc0\x8cm\x86\xbb\x90\xc3:\x8f)\xd6u\xc6\x0c\xcd\x0cJk\x9a)\xac\x12\xe6\x13\x18\xc2\xba\xe6\xf3D\xb8\xdc\xf2\x84~\x11\xe6\xf33\x1f\x97\x16\"\x1d\xb4\xe5,\x90\xcdp&\xc1`\x17bW\xe4!u\x9f\xa2\x86\xba\x0bOa\x08\xdf1l\x84\nX\x8a\xfdk\xd0\xb3\xfaK\xf5\x8ci0\x17\xed\xa1>\x1e\xd1\xf9\x10a6\x99\xc2\x87\x0c\x85\x13\xf4w\xd7\x0b\x1cSn\xb2\xd3\x96--e\x13\xb4\xd9\xebIH\x9fpLo\xa8K\xbc\xc6v\x02\xea\"\xbe\xea\xf6w\xb4\\_b|2\xb2Jv\x8ca*\xe9\xdbx\xa0\x17_\xa8x\xdcr\x9e26\xae\xa1Js\xa75\x91;\xe5#;M`\x00\xb1\xb5gJ\xc0\xbd\x98\x11W\xc2T\xb6\x9c\xff\xb5\xcdu\xb7%zB\xc0\x00\xc6\xac\xac\xad\x04\xd8\xfax\xdb\xa9\xf4/l\xe1\xff/k\xf9\xc6\x8c9\xca\x18\xd5f$\x17\x82\x99{\xeb\xf7\xdc\x05K_V\x18\x80\x8b\xb8\xea\xbe\x9c\xba\x84]\xb8q\x13\x1fBYi\xec\xa1\x05\xdf\xb8a\xae6\xab\xa3\xce\x9d?S\x08i\x02\x98\x1dk\x17\xae\xf89\x82\xdb\xa4\xb4b\xb5\xaf\xdf\xf5\x99/\xf3JHx\x1c\x06\xcb\x8cR\xd5\xa5\x8c\xe7\xe4\xe2.\x10L63EJQ\x1bP\x086\xf3\xdaV\xfe.\xb3\x86\xa80\xe6_k\x13N\xee\xf90\xad\xf0\xa9W\x14\x01g\xd6F,\xe2^\xb42c\xed\xcf\\\xb9\xa6\x00\xfb=\x17l\x86b\x8c\xaeq\xcf\xd7\xf4\xdc\xe8\xc5\x95c\xe4\xe8\x1ccbn\xfa0s\x85\x15\x06\xf7\xec\xb54\x88 \xe6f\xe0Y\xb0]\xb6[;\x8b\xf0\xee}\x18\xe5\xdc\xfd\x8cq\x98\xb9{\xef\xa6\x81x-[B\xc3{\xe8\xe3&\xee\xe4i\x18\xc5\xc8K\xd1em\x17\x9b\x96/a\x08\x13L\xe0\xd7\xffhT\xb1\x00#\"0)\x98\xc4B&o_\xf1\xebG\xb1X\x15\xd5\xd2ic\x87}\xbd\xf7\xb9\xafn2v\xa1\x80!\x8c\xdc\x85kH\xf0U{\xa9\xb8\x87IW \x1f\x12\xf7\xd9\x96\xa8\xdc\xa1\xe5I\xe7\xc2z\xf7\x9c`#\x8c\xe3\xe0c\xe6\x0c\xe1\xf9\xf3\xe7~\xab\xb0\xc8\xe7\x1b!6\x9aq\xa8\xa7\xcf\x9e\xea\xa1\xd0\x88\xc7a\x9e}\xffL\x0f\x93\x92I1&i&\xc1\x0c\x1f\xccd\xe2! \xf7\x8d\x01nI\xc6\x83\xdb4\\\x0ej]|\xf6\xfd?[\xf0\xfc\x10)k\x8e\xa5\xdd\x01 8'\xf1\xb2\xec\xe9\xd3g\xed\x01I\xc0\xda\xb8\xbf7\x82\xd5\x87\xfe|\xb3\x8dE \xd9\x18\xfd\xf3\xcd-3(C@mH\xcf\x9b&\x06'\xd8\x98\x10\xb2\x1c\xc4Qr\x1d%\xb3\xfa\xb8\x9eo\xb61[\x83V\x06\xf7|\xb3\x8d\x83\x1al\x1c\xde\xd3\"\x97\xc0m\xcc\xd6\x80\xcb|K\x83<\x9c\xe1\x1c.I\x1a|\xcc\xee\xb0\xf2\xb7}+7+\xb6'~Bo\x93\x98\x86\x93A\x91\xc6r\x96\xbekA\x914\xad\x93\xc6\xd6\xd3v\x1f\x18\x10\xdeG\x18\xe4i\x98dS\x9a.H\x9am\xcc)\xbd\x16-?mO\x95\xa1R\xedGB\xf3\x01\x9d\x0eP\xc9\x16\x0d\xb5\xc9\xa3OC\xcb0\x0d\x17$'\xe9\x80&\x84Nec\xed\x89\xeb\xd3\x18\xd3d\x96\x03\xe9\x0e*\xdbj\xcf+kK]\x04[\xedE\xc0@\x1ak\xffi\x9bN\x19Ts\xe9?m\x13(\x8f\x9dP'\xcd\xf6\x8c\n(\xba\xccxV* \xd9\xee\x1c\xa7\xdb\xc6\xce\xa0YF\x02N\x1d\xea\xd36\xbd \xa8\xe6h\xdb\xd4$\x00[\x03n\x0f%\xa6\x8dm\xe6\xbb6Rh\x98=knn\xed\xceq\xa8\"\x9f\x0f\xc8]N\x92\x8cAo\xe0\x06\xda\xdct44\x83\x95\xcb\xe3\xc5l\x83\xf1\xa0\xabp|\x9d\xc9\xd5\xa7\xc1F\xb3\xce<\xcf\x97\x03\xd6\x01YG\xc3M\x9au\xd4\x89\xd6\x90C\x13\xbc\xda\x1c\xd8vQ\xf6\xad\x8dVs\xc5\x8c\xa7X+\xfb\xd8\x8d\x8b\x94\xfc\xbf\x82d\xf9\xe0\x8aN\xee\x07d\x12\xe5\xb4\xdc\x93\x9e\xb5\xf7\x04[\xed\xb2\xc3m\x8aiV\x13\xdd\xac\xb2\x1d\x95\x9fl\x13\xaf\xa1n\xf9\xb5\xf6\xb2\xc0\x1a5n\xf1\xcc\x80\xfc\xda\x04\x19F\xdb`\x7f\xcf\x0d(m\x92\xe1s\x03y \xe3Sh\xb8E\xbe\xedmJ[OO\xfb\x86\x8f\"\xb0\x82C\\HQN\x16%\xde\x0d\x0b\xa0YQE\x98F\x04\xd1\xd6Q\xa38p\x1b\x93D\x91\x01\xe3\xcd\x06\x16az\xcd\x98\xa1\xfc\xaea2[\xd5\xe8\x84\xc4r\x80\xcf\x0d\x84\xd5\xacD\x938J\xc8\x00\xaf\xb6\x859M\x07W\xe1dF\xe4\x97\x0d\xb4\xd6l\xa4df\xd5B4\xac\x89f\xcd\x1b\x9e\x02r\x90\xe5\xe1bYV\xd6\xec\x00 \xd6\x8aINjs\xb2\xd5\x1ef\x86\xb71\xb3\x8d\xa9\xc0\xdf\xd6\xf7m\"\x910\xb5\xad\xba=\xbd\x8c\x06\x9b\xdcF\xd3\x18\x83R[\xd2\xec\x94\x08\xd3\xe04\x9a\xcd\n\xc1\x1aD\xfeT#U\"\x9cF\x9c~\xde&k\x99\xd5\xeecc\xb4m\xc8\"\x8f\xe2\xba\x8c\xdc\x9e\xc4\x9b\x88\xdc\xd6`\x9e\x1b`RJ\xf3A\x94|$\xe3\xbc\xec\xdcw%\xa46]\x0d5^\xd8I\xdc\xa8fly\xd0\xd4\x8e\xda\xb5\xa5\xad9\xbd \x8d[Z\xfc\x06M\x0e\xeb\xb0U\xbb8S\xbf43\x8d\x92 ,\xf8\x0d\xa1\xaf\x1dX\x07\x02\xeb\xe0|\x1d4\x0d\xbdR\xd7V\xfa'\xff\xa2\xc15\xb9\xb7\xe6O\x16\x95\xc5\x11\x0e\x83v\x95\xcb[\x0f>\xd0 %\x19\x8do\x08St\xeb\x17\x1d)+\x8d\x98\n\xbe\xb5\xf9\x0d\xc7\xee\xc3\x07\xef\x1f\x0f\xde\x8b\x7fll\xfc\x1f\xc8h\x91\x8e\xc9Q\xb8\\F\xc9\xec\xdd\xe9\x9b\x9d*\xc3\xe1\xe0\xaaH&1[\xe7\xc1\"\\\xfe\xe3\xff\x07\x00\x00\xff\xffPK\x07\x08\x05\xef\x9fw>9\x05\x00\xf8\x0c\x1b\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1f\x00 \x00swagger-ui-standalone-preset.jsUT\x05\x00\x01\x80Cm8\xec\xbdys\xdc6\x9a0\xfe\xff|\x8aG|w\x152M\xd1\xdd\xad\xc3:,k\x1d\xc7\x9e\xf5\xbb\xf1Q\x963\xf3\x9b\xb7\xa3UQl\xb4\x9a1\x9b\xec\xe1!Y\x13i?\xfb\xaf\xf0\x00 \x01\x10 \xd9\xb2\xb33\xbb5\xacT\xac\x06A\xdcx\xeec\x0b\x16U\x1a\x95q\x96\xba\xa5\x0f\xc4\x83\xdf\xfe\x00\x00\xe0dW\xbf\x92\xa8t\xe0\xf4\x14\xca\xbb5\xc9\x16@\xbe\xac\xb3\xbc,`{\xdb\xf4v\x95\xcd\xab\x84\xc0\x19\xff#\x10\xb5O\x81\xb8\x1e\x1c\x83#\xba\x91?\x9a\x93E\x9c\x12\xda\"\xfb+\x08Ws8\xe3?\xdc\xd9\x05\x0e\xe8\xb8k0g\xe2\xaf\xe0\xfc6\xbc\xbe&\xf9\xcfo\xce\xcb0\x9d\x87I\x96\x92\x0f9)HY\x0f\xa1\xec\xab\xf3\x87\x07\xb7\\\xc6\x85\xdf,\x89X\x8e\x9c\x94U\x9eJK%^\xd0\xe7&\xcc\x81\xc0)\xfc\xf6p\xf2\x87\xbaPT\x85\xd4\xcd\xe5\xca\xf4\x89\x17\xe0\x92Y~\xe1\x89v\xe9\x0f\xb1b'JU\xdavLG7\xcb/h\x17\xcaKl\xeb\x18r\xbfU\x9a\x1c\xc3\xd6\xa4]\xcc\xbb8\x86\xdf\x1e\x94w\x0fj\xa7|T%\x1dU\x14&\x89\x1b\x8b\xc1\xf9\x10\xfb \xfdJ=\xfa3\x81S\xd8\x1aK/\xea\xd6\x9anx\x9bi\xb0\x82S(}H\x83\x88N\x8b\xfe1\x87S\xf5\x10\xfa\xd0Z\xb24\xc8\xf8\xf9\xbc\xbf\x87\xf7x\x1c\x02vL>\xe4\xd9\x9a\xe4\xe5\x1d\xff\xb2\xbdBQ\x96.\xe2\xeb*\x0f\xaf\x12bY\x96\xb4Z\x11\xf1~\xdc~\x7fM\xcac\xc8\xd5\x15\xf3\x9a9\xd29\xa4\xca\x1c\xf4\xd1\x8b\x13R\xd2\xa3^\x06\x97\x97\xa4x+\xeeK\xeb\xac\xc9\x8f\xd8 :\xd7\xb0JJu\x0cp<\xec\xeb\x01{\x9d\x06s\x97\xf8\xe0\x84\x0e]d\x1f\x88:\xbdL\xdf\"\xbd;\xde\x0c\xdf\x99u\x9e\x95\x19\xbd\xa9\xc12,\xde\xdf\xa6b\x8f\xd8i\xc2\xef\xd5\xf6\xd7p\n\xce\x93y\\\x94\x8e\x0f\xa9\x9b\x06\x14pL\xc7\x07\xac\xda\x83;\xd3\xceG*\xf7\xefT\x05\x81\xa2\xcc\xe3\xa8tN\x94[\x99\xc3)\xa4\xee\xfe\xd4S\xf7\x94^\xa8\x99\xf39N\xe7\x8e\x0fNN\x8a,\xb9!\xf4\xcf(K\x8b2\xaf\":\n'N\x8b2L#\xf2~A\x7f\xads2\x8f\xa3\xb0$\xec\x935\x05\x1b)\xd6\xe3[s^\xde%\xf8\xb2\xa0\x7f\xbcH\xe2\xb0 \x85s\xa1\xf6\x9ca\xcfE\x14&a\x8eu\xc9_+\x92F\xf8\xdd*\\\xaf\xe3\xf4\xda\xb9h\xe6PJ`\xb4s\xf9\xe9dS\x1f\xaa\x936\x9c\xa1\xb7\x8c^\x9a\xdf\x1e|\xb1=\x9f\xc9]\xe1\x12/Xd\xf9\xab0Z\xbau\xd3\xadvE+;\x138==\x858\x88\xd39\xf9\xf2~\xe1\x12\xcf\x83r\x99g\xb7\x90\x92[\xc8\xdd\xef~N?\xa7\xd9m\n\xd9\x1a\xa1\x9e\xf3\x1d\x8c\x80\xc0\x08\xbes .`EJ\x88S\x06\xd8c\xac\x90-X\x9d\x92\xd5\xf9\xcb\x8b\xb7?!l\x0f\xbe\xf3\xb4\x8b\xe6\x03\x05\xcaA\x19^3\xc8\x81\xbf\xe8\xe6\xd1\x99\xb1?\xee\xef!\xad\x92\x84\xbf\xe3\x1b\x8a\xaf\xc5\xdf\xf7\xf7\x83\xae\xca\xd6X\xed\x9c\xb7X\x9f\x0bl\xb3\xf9%\xb7\xda\xba\xf4`\xbd\x81\xbc\xd5\xe6\x80a\xb3\xd2Ou>\xf5\xd1\xc3j\xcd/}\xd6\xfcL\xf2y\x8b_j-\xf9\xb0bE\xa5@\xad+\x1fd8\x057\xc5\x0f\x94\xd2\xfa\x83\n\xf1\x9f\x8f\xbf`\xeb\xf4\x14R\n\xea\xe4\xf3\x96\x1a\xce\x9bq\xcd\xd2Yy1\xf0h\xd2\xa7\x9a\x9d\x97y\x9c^\xbb\xc4\xa3\x18\xb2lUzh\x1f\xa8\xca\xf3\x81\x1f\xe9\xac>\xd2\xf5\xb9\xb2\x1dm\xd0F%\x1e:\xba\xc8\x87\x85\x0f\x89\x0fk\x1f\x96\x8c\x06\x81\"x\xdd\xa6r\xe83\xaf+\xfc\xd1\\\xe1\xa6\xaepn\xaepWW\xf8`\xaep]W\xf8\xc1\\\x81\x12\x88\x94\x0b\xc8\xe1\x18n\xe8\xbf3\"N\x17A\x1a\xf8\x81\x12\xf3\xae(\xfe\xed\xc1k\xe8\x0ds\x8b\x97\xbc\xc5\x98\x9eB\xd1Z\\\xb7f\xfe\xe8\nN\xe1\xb2i\x19\xbf\x91\x7f\xe3\xa7'\xadO\xe9\xf5w#Dvx\x98\x10hz\xb8?\x94Lv]\n\xec\xb7\x96\xf4\xdd\x8a\xfe\xef&\x8b\xe70F\x90\xb9\x9aE\x17\x1e\xe5\xa0\xe0\x18Ro\x16]\xf8@\xe9\xa2kZm\x01g\x10\xba R\xc6\xc7p\x87L\x98\xe9\x0e'X\xef5\x7f\x83\xf4\x96\x0f \xfd&\xf1Y\x87\x95\xbb\xf2\xe9\xa1\xa0P\x1e\xb7\xe1g\xcf\x87\xcbYt\x01[\xa7\x90\xe0\xcdu/\xb1\xc6\xda\xf3YOW\xf2[\x17\x7f\x9dB\xa2\x81\xd5f)\xf2 bw9\xf6\xe9I\x83S\x98\xd0?\xfeHI:\xfa\xc79\x9c\xc2\x1e\xfd\xe3\x03\x9c\xc2!\xfd\xe3\x07Z\xe7\x80\xfe\xf5g8\x85]\xac\xf53\x9c\xc2\x01V\xfbH\xdfN\x0f}\xe5\xc6\x17\x9b\xdd\xce]\xe3\xed\xdc\xd3\x8b\xf9\xed\xd4\xef\x1b\xbd\x9dO\x9c'\xd7\xed\xcb\xa9\xf7n`]@b\xe38\xaa\xca\xdc\xd2\xb3\x1c;\xda\xa8\xf3\x8c\x02H\xd2>\\\x1c\xde:N\x83b\xdd\x10F\xa7\xe0\x00\xfd\"\xa5\x18\xe7\x14\x91\x0f\xef(\xf7(%\x90\x84\x11q+\x1f\x9c\xed\xbfVYy\xe2x\x88\x99\xbe\xf3|\x08a\x04\xces\xfamL\xffz\xf6\xc4\xe1d\x9b\xf3\xdc\xb1m\xeffD)\xe7\x8b\xe5\xf2\x94a \xe2\x86\x9e\x0f\xb9\x9b\x07\x1f`\x04y\xf0\x1a\xbe\x87\xd8\xed\xa4\xd2\x04\x1f\xe580+/\\:\x07\xeb\"\x11\\#\x12\x94\xd9O\xd9-\xc9_\x86\x05q\x91{$A\xb1N\xe2\x12\xbf\x0e\x12\x92^\x97Kx\x0e\xbb\xeat=\x1f\x1c\xb6\x86\x94!\xe9C\xdc}\xe8\xc9\xa9R\xc6\xac\xce\xe9\xce\x89\xbbz\x1b\xa7\xf3\xec\x96n\"\xfb+x\x1b\x96Kz\x97\xf1\xdf3\xf1\xfe\xd8\xf2yA\x92\x05\xfd\x98\xfe\xab\x7f\x8a\xef\x8eA\xc0\x01\xd7\x11\x84\xe82.\x1c\xcf\xf5z\xf0\xe05\xc7\x83\xd7\x8f\xc0\x83G\x9d\xa4\xca\xbe\x8e&\xd9\x8d;\xfa\xdfC\xaa\xd8\x89\xb8\x03\x9d\x16\xa0Kb\x90m\xc9\x1b[o0#\xa5\x91d\xe5\x7f\xf27\xed\xe5\xcc\xe9\\b\xfa\xbf\x01\xfb/\xaf^6\xf8p\xbf\xc8\xf3\xf0.\x88\x0b\xfc\xd7\xdcX:\xb8\xb1\xff\xe57E\x9e\xf2\xb0\xb3J9nN\x17\xd0\xbe\x04;\xf2\xe9nM^\xe5y\x96\xbb\xce\xcb0\xfd\xae\x04\x8a\xdd)k\xbd\xcc\xe6\x90\xa5\x00\xec\xac\x9aey\x9bB\xb0\xa6\x15E\xb4e\xb9Vt\xb5\x9a\x1e\x94\xf3\x95\xdfi\x9f\xd0\xf6\xd2\xce\xd3\x89wq\xec\x03\xb9 \x13\xcfuXq\xd3\xfee\xd9\xc7\xbf\xcc\xfb\xf8\x97\x9b>\xfe\xe5\xae\x8f\x7fi\x18\x9c?\xdb\x19\x9c\xe5\xa6\xec\x08\xe5aV}\x8c\xce\x15o\x99\xb2Ns\xc1:\xd9x\xa5.\xdee\xa9\xf1.\x8ckY#3\xa0q-W\xc8\xb5loC\x88\x8c\x05\xbb\xbc\x94\xd5\xa1,\x0b\xf2\n\xc7\x90\"3\xb3b\x8c\xc3Rc^\x9a\xd3\x8f\xb5\xcf\xb0\xb6`rh#Y\xcd\xf7\\\xd7\xdc\xc8\xe9)\xb2:\xdd\x92$\x90H\xc6F\x90d\xa7\xd2\xc5C\xaf'\x05: Dr\xecf\xda?\xa0Oq\x1b#T\n\xf3\xebjE\xd2\xb2\xe0\xb4e\xdfw\xf4\x89\xc2\x82\xc0\xf8\xb8\xb7\x1eH\x02{r\x0be{\x0b\xf5\x07[\x9el\xde\xb2K\x0c\x94\xb5\xfe`\xe3\xd3\xc74\xae\xd0\xd4\xa6\xe7\xa1\xf3m\xab1\xba\xa1\xd6/\xecm\xd5\xea\x95p\xbdN\xee\xb8\xf2\xaf\xde@s\x8b\x0f\xe6u\x11\\\x87\"!\x904!\xb2J\xa5n\xcaE\xce\xfc\xa6\x93\x9b\xcfl\xdc<~\xe6\xba\xab\xe0&\xce\xcb*L\xf0\xe25\xbf\x10\x96x\x9cW\x17\xbc\xfeG\xfa\xcd%\xfd\xdf\x16\xb2\xfc(\x0f`\xdc~\xe2yV\x8e\xfe\x1f\x85\x8b\x9f\xeab3.dk\x953\x1cu\xa8#4\x8a\xa2\x8c\xca\xc3f\xaa$X\xb06\xf7=83W\x96\xd5n\x16\xccE!H\xee\x96\x9e\x8f\xb0'\xa3gtk\x8c\xdc.jL=\x03Y\x04\xcd!\xaa\xeaf\xd5\x0d\x91 \x9f\x87V\x7f\xce5)\x1d\n\xbc\x91\xb8r\n\xf1\xcb@>\xbe\x88\"R\x14Y\xce\x08\x8a\xa2Z\xd3\xfd \xf3-\x0bA\xe1\xdc\x84IEx\xdb\xf4\xd0\x95\x0cY\xa5\x01\xbe\xf0\xfcMI\x0e\xf9\x08l\xa5\xee\xf4\xc8\xb3\xf3\xfd|\x0cO)\x9e0+~\x7f{\xe0\x8a\xcb\xf6\x82\xa2\xe6\xb6S\xa4 w\xd1\xbe\xa0\xea\xfa{A\xd8\xcc\xb3\x9f\xd8o\xe4\x1f\x9a\x1a\xb4\x8f\\\xb4\xebWS\xa3\x06u\xc8\x92K\x82j\xcb%\xda\xdd\xb3\xb0\x85\xa9\xbb7\xf5\x14dk>\xf4\x82\xc5\x0e\x16\xbcF\xecNh5\x99t\xef\xbf:\xb5\xf1\x01;b\x1b\x9f-I\xe67\xb1L\xa8\x9b0\xdf\xa2\x17\xb7}iT\x1a<\x05\xc6k\xd8\xaeL\xdf\xa0\xfb\xf8`uX\xff\x8d\n\x8dne\xba\xb2rCd\x82\x88\x9bc\x1f2\x1f*\x1fB\x1f\n3\xa8\xa4@d\xcbHc!\x03\xd0\xc6\xb9\n\x8fL\xc9T\x88\xe8\x1c\xc9-p\x18\xf76N\x99B\x8e|\x89\x08SJgQT\xe59\x99\x9f\x00\x9dd\xb9$\x90f\xe9\xceJT\x9c\x93\x1b \xe9M\x9cg)\xc5\xffH\x0e\xd3J\x8b*I\x80\xd0VaE\x8a\"\xbc&\x10\xa6s\x08\xe7sTe\x87 ,I\xb2^T \xdc\x86y\x1a\xa7\xd7E\xa0\x9f\n\xfa\x90\xa4 \x1dD*E;3}\xb1.\xcct>}(\x86\x1f\x9bi\x11W]\nR\xcb\x80\x9f\xfck\xf1\xe4\xda`\xdedz\xf8A^\xcc\x92\xd1\xe8\xc2X\xeb\xc1\xf3\xbc \x0dW(\x91}\x93\xde\x84y\x1c\xa6%\xfc)\xce\x92\x10)\x99\xd6WmJ\x8c\xdd\xb2(X\xe4\xe1\x8a\x14\x9f\xb2\x0f\xd9\x9aQ\x1a\xd1\x1f\xcc\x1f\x0e\x82\x01}\x16!OM\x9c\xae\xa4\xac\xeeW\xec\x0b\xb6bvaa\xa3\xd8\xa5\x8eS\xca8\x90`]\x15K7\xed\x10V\xab\xb35_\xacD\x9d\nW\xf2\xca@.\x0b\xe2tI\xf2\x98\x83\xed\xdd}O\xfd\x84\xb1\xe8\x93C\x1d\x03p\x1e}\xf2\xd4\xd8\x16e\xbf*\xe9M=?\xdaK\xec\x86\x0d\x91\xeb\xf9x\x0b\xc7'\x10\xc13\x10\x1c\xd0 D\xa3\x91\xbe\x88\xe2\xc8\x17\xb3H[\xc2\xa4io\xb6`\xcc\xb1Vt\n\xa1R \xa3\xc2f\x94|\xff \xb1\x80\xf9\x16\x8b\x97x\x9e\xccY\xd0\xef\xd4\x91U\x1c\xfb\"\x9b@\x89\xbbP/@\xa9\xec\x16\xb3,(\x83\x9c\x84\xf3\xf0*a@\x98\x1bi\xf0\x92S\xd8\x9a\xb4\xea\xdf\xe6q\xa9\xd6\xafKD}Z\x18&Iv\xfb\xefa\xb2x\xbf&)7\xbdS\x1bRk\xd4\xad\xb5>\xac\x9b\xcc\xd2\x88\xb8\x0eA\x83\xa8u\xf7r\xae[P\xc3\xd0\xf6\xfd=+\xbd\x14\x138/\xc3\x92\x04$\x9d\x13\xb4\xd6\xc9\x83\x94|)?\xc5\xd1gw\xc9\x86\xd0\xdd\xe9\xb2\xbd\x87%m\xcd5\x89\xf2\xccTb\"\xf3b\x8e\x18\xd7\xbf\xc7\xd7\xcb?\x87%\xc9\xdf\x86\xf9\xe7\x16 \xa9\x18\x06j\x86\x83\xfd\xa4\xa5$\xd5\xd4\x17b)w\xab\xde\xfdfB\x9e?h*sR\x94yvG\xe6\xad\xe1\x0f\x1e\xa2$\xcea\xa3\x15\xe7\x14G\xab |\x0c\xf3i\x8e\x98\xfaeP\x8f\x8d\xd60-D]Acu4a\xa12\x113@\xfe\xfd\xa7\xd0X\x9f\xd9&A\xabx\x1d\xdb)m\\p\xc9\xbf\xea\xa3\xfc\xb1C\x86?\xaa$\x11\x17\x16\xcf\xbe/\xdf#\xe2\xcb}\x7f\x13499\xda\xb3\xea\x8a\xec\xbb!\x8e=\xaetN\xd7\xb56\n\xeb\xa3\x8a7\x1c\xdf\xde\xc1\x9e\x01\x8f\xbf\x0d\xcbe\xb0\n\xbfv\xeds7\xde|\x02\xd2\x80\xcc\xe3\xd9\xb73\x88LZ2\x90\xb5\xfb\x87a\x10\xa7\x87\x1b/\xf0\xdf\x85A\x1c64!\xaci+\xc1J8\x93\xee\xa0\xcd\x19\xe3\xdb\x8f\xa8S\xc8\xb5\xb5U\xba\x1d\xf2-\xebg\x9a\x85\xeec\xf7\xdeb\xaeg\x16$\xee\xeb\x06\x96\x8c\x90>:\xf4\\\xa7\xc8#\xdd\xd4\x81\x92\xd3\xb5\xd0\xb6\xcc\x98\x1dI[\xfd\xe5:\x0e\x8c \xf4\xb8=\x8a#j\xca'\x06-\x08\x838-\xd6$*\xcf\xb3*\x8f\xc8\x90C \x08S\xe9f\xf96K \xc1\xa5\x87&\x12=\xb2Y`\xa4\xea\xa9\x8e\x10\x7ffn\xea\x83CYB\x07\xf5@q\xf3\x9b\x1e \x8a\xbc\xe8\xadm\x8c\x97\xa4\xcf\xaa\xe6\x8b\x8a\xd7;\x03\\\xa1\x92i\xb1\x8a\xe0\xd7,N\xdd\xda\xda\xd7\xc3\xf6\x90\xe2\xcd\xe1\xac\x86\x07p\x0c\xa1\xf8\xa9\x94\xc6\xcd\x818\x06wN\x12R\x12|\xefK\xaf\x14K\x8fF\xf2.\xd3[\xf56u0\xd2\xe2.\x1a\xef\x19e;894\xab\x90\xc1\x91\xf8\x08\xb9\xffot\x0d\x7fo\xc0\xb01\xd66_\xbd\x03\x93\xa2\xd9M\xdd\x83\x03\xcf\xc7\xf7\xe3\x86 \xb69\x98\x18\xaf\xe9\xe4@7\xf3\x0b\x8d\xaeT\x9f\xc9\x9d\xd9\xff''\x0b\xf3\x8b\xcb\xcb\x82$\xf6wx]\x8f[ \xcb\xe4%VX\xb7M&[\x83\x9c,\xa4\xcdh7\x13\x0dk\xe63\xb9\xd3\xf6\x14$\x96\xbc\x0d\x1ar!\x962\xc2\x88\xb6\xbc\x92>\xff\xf2/\xec\xf8\x1cC\xd5^\x1c\xfa\xea\x18\xca\xf6\x0b\xdc\x03\x83v\x1b\xb7 m\x97\xaf\xf3l]\x1cChX\xff\xec6%\xf917j\x12\x8f\xd9\xfbI\xb2]\x91\xc4\x1cA\x94\x93\xb0$\xaf\x12\xb2bn\x15}\x94 \x9e\xf1\xda\x17\xa25\xa2\x84\x9e\xc6*I\x0c\xb3\xe0o\xd4\xc1QZ\x83\xdfNY\xdc/\x1e\x14\xc3\xe4\x10\xd3\xc3CP\x03\xef\xae\xb9\xef\xc7\xc2\xf3!\x12\x85 3\x98\x1c\x01\xa1\xfb\xee\xf9 \x8bM\x03v\x84\x05\x1c8\xaeK\xda\xd5\x18\xf2Q+b\x19\x02\xa5\x8c\x810\xe6\xbb\xb7\xbd\x0d[\xa1v5]V\xeeV\xcc\x93\x11\xfd\x1fOZ\xcb\xb7\x84S\xd05\xe8\xb0\x03\xd3\xf6\xca0Y\xc7\xd2\x83*\x88\x96q2\xcfQ\xa4\xa1\xa1%\x94\xb9\xd2\xdaKx\x0e\x13\x13YQ\x0b\xb3\xe6\xc2\xac\xcd]\xd25bb\xac\x1bx\x06\xcb\x13\xb8\x19\x8d<\x98\xcfn.\xe4\xd1\xcdn`\x04S\x83\xfco\xec\xabc\x9a\xab'\xb05\x13\xee\x15\xc8=q\xe8z\xb5\x84\xe4\xc0\x97\x07\x8dO\x94\x9a\x16\xf1#\x9e\x8b;O\xdeD\\xi\x07\xee\xe8\x0et\x0cM\x08\x80\xe9ig\xee\x03c\xfc/\x0eP\x8a\x9e\x96\x14g7\x17\xc7\xaf/\xcc\xeb0*\xb3\xfcn\x90G\xa4v\xc9\x82\xab8\x9d\xbb\xdc\x07\xc9L8\x93@(\xd75/\xc5E\x10%YJ^\xa4\xf3\x8fL\xdc\xfd\x1f\xa4\x97\xb9n\xe6\x18p%\xbd\xcf\xa0,\xfd\x87\xdf\x03\xfa\x07?\xe7e\xc0\xa0\x8a\xcf4\xfb\xebB\x9f?\x1d\xc0f\xf0\xa2\xaa\x0d\x9brTd\x8a\x86\xdb@\x02m\x9b\xe8\x15n\xbfB\xc1\x03\x0e\xbb}j(\x12\xed\x9a\x8b\xb79\xd0\xa9\x14\xa03\x17@\x87\xdd\x9a\xfax\xc80h\xa9\xc3 \xb6\xde\xec\xe0#\x1e\x97\xcft\x0d\xb6\x0c\xef<\x0d\xdaT\x16h\xc3\xca\x15\x15\x11%\xb6T9P\x02g\xb0\xa6\xc5\xa7\x90\xd0\x7f\x8e\xc5/Z\xd7\x00\x9d\xee6\x84Nw\x1e\xac\x87@\xa7\xbb^\xe8t]C'\xbaz+\x06\x9dV\xf0\x0c\xeeN`E\xa1\xd3\xf5l\xa5B\xa7\x95\x05:)\x03\xba\x1et\xff\xf9\xddX\xfa0\x17@\xe0F\x95\x13\xd3\xc3\x1f\x17\x7f\n\x93xn:\xfe\x9bP\xa4\x8a\xbc\x88\x1d\x10AJ00&\xf7\xaa\x10\xc0\x7f\x80~\xe2T\xd2\x0e\x1f\x98Y\xc0\xdd\x83~\xa9@\x87\xb3\x03c%\xcc\xa0+wS\x8f\"P8\xe6\x87\xb0\x99\x8aq\xec\xfa\xc09%\xa6\xab\x8a\x8d\x04ef\x10\xd3\x0b\xc3R\xae!-H\xf9)^\x91\xac*a\x192\xb1\xc5\x15!\xdcK\x97\xcc\x9dn\x91|\xd5\xdfA\x94\x900\xff\x8a.B\xb3\xfc%\xc5s\xd0\x8c\xbe\xd6\xda4Et\xf9\xc6\x06\xc8\xc6\xbf\xcd(\xd3\xb5\x95\"\x880\xb4C\xf7\xb1)\xf6{\xda\xed\x94r\xa4\xec\x0b\xf5\x9a 9\x87\xd1\xa7\xd5\xdc\x1c\xb4l@8\x92l\xb5\x0e\xbd=\xb4\xdb\xe2\n,s[\x16\x10\xf1\xb0eg\x7f\xcdsHm\xb2\x04\xe9 \x9e\xc9?Z\xc4{\xa7\x80(\xad=\x18\xea\xfa\x03\x06\x95\xdb\x06\xa5\x1c\xde3\xf5\xe7\xb1\x04\x85\xa0w`\xb4\x8b\xca\xb6\x8a\xae\xa6\xa2-\x98\nu\xa6i\xfe\xd1\xfeV\xd3@Q\x0c\xb931]\xfe\xb6\x8e\x8e\xf9? J\xe4M\xd5\xeaY:9z\xe0\x83(K\xa3\xb0t#\xb4/\xc4\xb6}\x88D\xa5\xedmX\xba^\x9f\x96\xcet]\xb7\x166j\x96\"\x89\xd0]\x1b\xd4\xe28F\x83uC\x8d\x0f)\x01\x18\xd5\xfaerb;\xe7\xf8\x01\x85\x92\x91X\xd7\x13\x18\x8d\x12x\x86\xdf\xe0\x82\x14\xb3\xe4\"\xc8\xab\xd4\xb5X\xbc\x8a\xa5\x90\xbb\xec\xb9%\xc0%|\xec\x8e\x9a\xf6N\x865\xbc\x92\x0b[Jk\xbd\x1d\xdeP\x85 \x90\xf1d\xc6F\xe9\xa9\x95_\xf8\xc3\xbb\xb1\x830\xf1\xe4n\xd9\x864\xe2\xe9\x87^\xe2\xe9\xef\x08d\xb5\x83\x0c7\xed\xdd\xc3FC\x80V\x07\xc2\x1a\xa0\xbb\x03\xfb\xec\x8do\x1e\xf4\x05{\xe8\xbc\x89s\xbb*qQ\xa5\x92&3\xa44%%x;\x9b\xbbq\x15\x8b\xd3\xb8\xd6:\x0e\xe2\xf1(E\xc0hW\x03\xed<1`\xe9V5J\x1d\xdba\x01\x9d\xcf\xe4\x04Rx\xd6\"\xceO \xa5\xc41\x99\xa5\xb4+\x95@N5\xe28\xe2ZVr+\x96\xcf\xf3a\x82th\x0d\x05\xef\xef\x01\xa3s\x84\xeeR\xa1~\xe7\x92D2\xaf:=\xa6\xc4&p\x9bs)\xde\x06\xee\x85\xd2l\x1c\x94q\x89\xd6\x1f\xceU\x9e\xdd\x16$wh!\xff\xbb\x89\xba\x94\xde\xf0\xf0\x1bq\x10\xe6\xd77\x0c\x7f@\x1cp\xbbAd\xbe\xa4\xdfE]\x1b\xdf\xdd\xe0w\xf3\xf9OqQ\x92\x14\xdb\xbda/Q\xd9\xc0\xfe^,\xc4\x9f9Ye7D\xaf\xccJ_$\x89xQ\x887d\x15\x97\xe2\xefuN\xd6$m\xf5\xc4\x8b\xdf\xa7Q\xab\xddDj\xae\x97\xa1\x98]\xa8\xabw\x15\xa7\xf38\xbd\xeeVR\xe9T\xeb:\xcf\"R\x14\xf5\xc7\xb1f%\xedh[\x14\xdd\xce\x07x\xc89O\x1c\xed\xb3\xe5\x0f\x18\xd9&\\\x88\x91R\xe22y&\xc8\x81\xb3\xe1\xbd\xf9\xd3\xab\xcb7\xef^\xbfy\xf7\xe6\xd3_\xb0\xc6\x04\x9e\xd8V\x9a|)I\xda\x8a\x8bh[\x02\xa6\x9dk\xd3Q6\xf9-.\x0d[:7S-\x9f]\xe2y\x0d\xed\x04\xcf o\xd6\xae\x9c\xc5\x94\xc5\x9e\xa5\x17LD\x1a_|\xfb+$J%9\x9d\xd9]\xa5\x15\xd4\x8fYj\x8c=\xd35\xac:5v\x063n1\x95 N\xa3\xa4\x9a\x93\xa1\xa1\xcb(\xa7_\xf7\xa5\xbc~\xe0\xc6\x0fC[2D@3\x8c_<\x84\x85\xc7C\xe5.\xfdk{[\x84\xc6ce\xf8\xe7\xf66\xe4\xc2\x12\xbd\xd5\n\x1d_\xca\xde\xea\x9c\x06\xbeY\xc4IIr\xb7\xf3-IN(\x11\x17\xa2\x17\n\xfb\x06\xc11z\x0d, \xd4\xe3\xa740d\x0b\x08\xa1\x88\x96d\x15\x06\xf0F\xbcb\xf1\x0d)>\xc8\x16PT\xd1\x12[(Z\xc4a\xe0\x18\x8e\xe3\x12C\x1b\xae\xd6qB\xe6o\x9a\x95\xab8\x0b\xeb\x88\x018>\xcc.\xf4\x0f^}i\x7f \xd6\xd3\xf8\x01E\xcco\xc3u\x17E\nB0\xc4n\x90\xd1\xae\x80>l\xb1\x8e\x8dZv|\xcf\xc3j\xdak\xf0`\x9b\xf6\n\x8b0I\xae\xc2\xe8s+V.}d\x89{\xfdA\x07\xce\x17O:cW\xf1b\x86\xd7\x94\xf9P\x8a\x9e\x9a2C\x0c\xc3vw\x14\x90\x97\x0c\x90\x13\x83Z\xea\x04J\x86\xf9J\x0e\xbd\x1b\xc6W\n\xaf\xa8k\xff@\x12\x0d\xab\xe7\xc55\x9e\x16\xcb\x99\x90/\xb7\xf8+\x0c~|\xf5\xfa\xc5\xcf?}\xaa\xe5b\xa1`\x19:N\x848\x0d\xea07\xf1\xb5\xef\xf2\x80G\x01\xa4\x18\x97\xb6\x8e\xb3\xb1AyF\x9f\xab\x9c\x84\x9f\xdb\xaf\xba\x9c\xe1K\xada\xbd\xab\xc9f]q}\xa8\xa5/\x19\xc8\xfc9\xcf\xd2k`\x9e\x81\x08AD\x97x~\xce\x194\xe1\xbbP\xb3v]F\x01\xcc^\x81\x02vN\x0c\xd6N\xceM \xf3\xe5\x0b\xc8\x0d\xc9\xefz\x80\xa7\xc0\xb3\xb2\x1bN\xa8\x01*\x0dn\x9e\xd7\x916\x05XDn\x88\x83\xc6\x02\xdc,\xa7\x802N\xaf\x13\xc2g\xc8Mq=\xca\xa0\x95a\x9c\n\x98\xab\xbcm\xf9\xec!wA\x1e=\x8dl\xd3i\xd4\x81B\xb59P\xb8i\x9b\x81\xf4\xae5~q\x8f\xc9-\x84\xae\x01o1\xf4id\x89\x05\x1c?\xd6\x1d\xd3\x14\x11\x83\xcc\xa4\xb1M\x1bj\xab\xf8\xdb \xcaP2Ho\x05\xc6\xe4\x81Om\x16\xe9\x83}\xf9j\xcdl\xe9C\xac\x83\xad^},s\xee\x16\x06\xa1\x9b\xb2\xaf\x9a\x0e\xce\x0b\x8a$\x8e\x88{\xe8\xc3\xce\xa4o(\xdd\x0e\xf5{\xbb\xff+\x1d\xea\x87-\xeb?\x80\xd5\xf9\xb7:\xf7\xfb&?U\xe6\xdf\x12\xa7\x8f\xa3\xec\xb3\x9eC:@/+\xb7=\\7+\xf5\xf1\xa3&F\x1d4z\xfaQ\xcf\xd8\x91\x86\xda\xb8a\xfcJj\x19\xc3\xc1\xc8\xb21\xac`\xeaO8\xdc\x0e\xeeR\x81\x9e]G\xe6C\x1e\xaf\xe22\xbe\x19\xbcL*\xa1i\x04\x1d\xf8\xc2p\xbdX\xfc\xc5\xf6\x05a\xe5\xed#\xaeS\xb2FPW-\x16x\xe9\xcb\xfaG]\xed\xc1\xab\xddaR\xf7\xe0\xd0\x0b\xd8{\xb3@es\x0b\x06\x03\xe9\x8e\x1b(9-s=\x80\x08\x06\xf6\x97\x17o\x7fz%\xc2\xae9u\x82\xaa\xb0\xc8d\xdb\xc3U\x98\x7f\xe6\xa6?\xf8\x93\xc7V;mb%\xd1\xfat\xcd\xdc\x8a\xa7`be\x1ef\xb0p\x9bF\xcex\x02\x8c\xba\xa4\xc6b,\xf7\xa4\xe3\xf9\xf5\x90\xd7e\x95\x93\xf32\x8c>\x7f\xcaCth\xb4\xbc\x11\x86\x9cK9\x01X\x86q\x88\xb1\xac\xa05\xd1EYXhy\xbc\x8c\x0eY\xb2\xf6\xaa\xff\xca;,\x9c\xd8 \xe4HZ\xb9\xd5\xf2&W_\x8a\xb9\x0e\xa3U\xea}\x1a\x81s\x0c\x8e\x91f!h%\xd1\xb7 >l1\x07\x9dz\x1f(\x85C\x9a|$\xa6\xed\xd0s\x0b\xca\x94\xd6\xa0\x84\n\xbd\xf6\x026\xf7\x1d\x96\xcdK]\x95Z\x08>K\xdd\xe9x\xeaiV\xf7B\x01\x8a\xef\xf7w'\xe8\x88\xbe\xbf\xdb\xaa\xd7\xc8\xcb\xb1\xde.\xaf\xb7\xc7\xff\xdd\xe7\xff\x1ex\x92\xc5\xcbc\xc5\x9dv/\xc66(S\xcc\xda\xdc lCip,\xd4\xcc\xd6\xdc\xa9\xa5\x9ed\x00\xe7\xeeY\xeap3;Mm\xa0\xdd\x85!ru\xcd\xc4.\x17\x82\xcf\xb8\xa3Q\n#\xc8\xbd\xe6\x00\xef\x1e<>\xae\xce\xe3\x03\xfapV\xea\x11a\x89$%\x8a\x1e\xc4\x84\x87\xf7oE\x1f\xcax\xb9\xce\xb0n\x10=\x99\x05\x8c\xfdg\xf4\xe4\xea\x9bDO6\xdd\x8f\xbfOPa\xd3H\xf0ZF$N,7v\x91dY\xde7:\xcb\xd0\xe2\xe2]\xf8\x0e\x15\xce#\x14#\x8c\xe1\x18\\\xa1\xc1\xc81OZ\xbfD\xc1.\xaa\xe9\x0f\x10\xdcw@\xd5\x10\xb4|\xd4\x9a @X+\x18\xad\xb7\xba\xcc\x13xs\xf5h\xac\xe6_R\xe5\xb2!\x05\xdb\xf27\xfa\x18D\xd7]\xa6\x0b\xad1\xf4\xe4Nh\x0f\xc3\x1a\x9b\xdf6\x92\xdd\xe1#Ah\xb0\xe1`\x14E\xaf\xfc\x0c\x90N\xd6\x9dw0\x0e\"\x9b\x00\xb1\xa6\x12\xd8\x04\x1f\x0e\xbb.qoB\x99\xded2\x8f\x0dTf\x8f\xaefQ\xdaO\xc6\xbd\xb7\xce\x02\x0d\x1e\x15\xd6\xae\x8f^l\x85\xfc\xe2\xf2Z}\xf0\x0c+\xb62\x06VbNm\x19m\xea>\x16\xbe\xdc\xf0\xa8:\xa1k\xa4\xd7\xb0\xed\xca\x87\xc2\xe7\x99\xf0\x0c\x95(\x1e\x8efcC\x00\xe9\x04\xdf\xe8&G\xd9\xb0\xcc{\x1d\x9a/2+.\xba4\x9fZu\x83q\x80\xcf\x8c\x12xv\xbf\x96\xc5(\"\xcf\x98\x07\x00S\x1c\x17|X y\xc0\xe41\xf2\xab\xc2\x87)\x93\xb5\x9eu\xe3BhF\x96\xd4\xf8\x90q\x80\xfa@\xa0/\x16\xa9\xb1\x1d}6}\xc7Xn\x98\x91U\xbf=\x18\x15\xd0\x8f\xbf\x04\xc3.\x9f\xa2\xeb5y\xf01\xedo\x13p\xfd# \xa3\x92\x07L\xff?\x0e\xcf\x84\xec\x9c\xc0M\\\xc4%,\xcbr}\xfc\xe4\xc9\"\x8c\xc8U\x96}\x0e\xae\xe3rY]\x05q\xf6$\xa7\xdf=\x99gQ\xf1\x04?\xde\x99\x93(\x9b\x93>\x81\x9c\x999\xe6\xa3\x91\xc7,\xd5\x9d\xed0\xbf.f\x17X\x8f\xa4\xb4\x89\x9f?\xbey\x99\xad\xd6YJRY\xaf\x96\xc3\x08&\xba\xf2\x8c\xb5\xa1\x06\x7f\x17\xa2\x89,\x1f\x1e9\xbe\x89\x1a_\xf4\x87\x8b?i]\xff\x18\xe4\x10\xee\xba\xaa\x8e\xc1\xf4\xb83\xfa\xba\x0fq;\xacz\xdcs\xea\x06\x9d\x1b\x89\x82\xb2q4\x8f`\xe5\xebb\xf1I\x87\xf7\xcc <\xac^\xb8?\xb4\xff\x12\xeb,\xb7&\xc1\xb78(\x97a\xf9\x11[+\x98\xd8E)z\x1d&\x05Z>\xba\x18H[y\xf7)\xaf\xf8\xab\xb1\xfe\x8a+\x17r\x11\xcfW\xfdn\x19w\x9a\x8f\x88\xb9)\xf9\xf6\xb46^\xf0\x03>\x04\xa5\x9a\xfdO\xe0\x94\x1f\x94\x8d6P\x94v(\xa5\x9e|\xbf\xa5n\xd7\xf7\xf0iI\xe0\x8a 7W\xd9\xbcJ\x08,\xf2l\x05i6'\xc1\xaf\x85__D\xee\xf4\x1ah\xdf\xeb\xcd\xfd[X\x95\xcb,\x07\x80\xd7$\xcf\x8a\x02^\\e\xd5\xe7e8\x8f\x7f%Kx\xb6\xc0\xc2\x7fc\xff\x04Y~\xfd\x1c\x9e \x88\xd4\x94\xb5\x1a\x15\xf6H\x8aA\x12{\xf9\xa4uu\xb9\x1c\xaa\xc5?CC\\\xb4\xb2\xe4A\x93X\x0f\xef\x94\xf2\xb2\xbe\x10\xed\x98+\xd0le\x11|\xfa\xcb\x87W?^\xbe\xf8\xf8\xf1\xc5_.\xcf\x7f\xfe\xf0\xe1\xfd\xc7Op\x06\xd3\xc9\xde\xd3\xbd\xc3\xdd\x83\xbd\xa7p\x0c\x93\xf1\xd3\xdd\xa7{\x93\xc3\xa9\x96\xef\xd6\xd2ah\xc5\x95\x94\xe2\xa4\xc3yF_7\x86\x17\x1f\xc3\xf4Z\xf0\xc9\x14(%\xf1\x1cI\xd190Os\x865:\xcc+l\xb3p\x85\xbd\xd3\xcfqZ\x1e\nCc/\xb8\xbcDl\x7fy\x89!,\x1a\xf9\xea\xb1b*\x82l7o\x00}\x9c\xe8a\xe7\x18\x8c\xe5\xb8\xd3\xa1\x85y=\n\x1b\xc5\x06\xc2\x88\xcb5O\x80\x07\xc4\x97\x95 \x85\x9an\xa0i\xba\xbd6H\xde\x1b\x14\x0d6\x12\x0b\xeb\xb7\x15\x10\xcaN\x89MZ0\x1c\xc9=\x9d\x8b\xda,\xb9\\\x12\xe6\x86\xb2\x88\xf3\xa2\xac\x11?\xac\xaa\x02\xedgB(Z\xd1j\xe5G\x10A\xf6x\x08\x0f\xb63\x105\x01i\x0cr\x1c\xcb\xd6Db\xfd,\x0c\xaae\x0d\x89\xd9l\xe8;!\xb5Q\xe7\xcdm\x87BnR\xdf\x91~\xda\x9c\x89\x16\xcf-W\xe5lo\x03\x91\xcf\x83\xfc\xae\x1dK\xbb\x83\xedFW\xbf\xe0\xea\xae$?\xe1\x89\xf6\xd1\x0co\x0c\x98\xeb\xba)\x86g\x8d4K\xbf\xaa\xdfe\x8bEA\xca\xef\xe8\x11\xc8*4G\xbf\xca\xaat^\xd8vW\xef\x936\x0e#p1\xf7\xf0\xd8\xb3\xf6\xc3\xee\xdc\xf0~0\x00A#cI\xa5\x00n\xa7<\xf0o\x0b(\xd4F.\xd6*x\x81\x8fM\xc5t\x99\xcd#\xe9\x04L\xa4\x0b\x10\xd1\nk\x06H;\xaf\x8a\xc1\xd0O\xd9\xfdc\x93R\xb1\xc5\xd8tx \x1a>\xc7\x05\xad\xf3\xc9\xdf\xdf3\xe7P\xa7*\x17\x87][\xbfU\x04q\xf1\x8a\xc3\x0d7\xb58`\x7f\xe7\x08\xd0\xe2H`\x83!\x056\x94\x1a\xf6\x98n\x12H\xf8t\x0c\xf70g\x1bg\xf6\xd7\x02\x8e\\]\x16T\xa8d\x86\x8e\xb7y\\\x12\xd7\x02U\xd9'u\x96\x02\x97\xf9\x042#\xfc\xb1\x0f\xb1\xf7\xe8\xed\xf2\xfaL\x1f\xc5C\xd7\xb2\xa8\x15\xba\x141uH\xb3j\xd5\x08\xdc\xc3\xd2%\xc2\xe7\xc9\x166c\x08\x906\x9a]Iu\x82\xb8\xf8SLX\xda\xfdv\xb1\xc9\"L\xaa%\x8f\xb4!0\xdb\xa3\xad\xa9\x99-\xd5R\x0e\x11\x1dK\x1caX\xe2\x9b:\xd9f\xd7*pj\xb3\x1eIW(\xc2\x1c\xc3\xfb\x9d\x9cx\xb5\xa2\xcf\x8a Q\xbd\xe5\x84E\x14\xc7\x8eY\xc9\xc5j$a\x19\xa7\x93\xce*Wq\x1a\xe6w\x96* )w\xcd\xe8\x845\x82d^W/U\xb9\xd8\xe9\xac\xc1\x08\xed\xdeQ\xfc\xec\x96\x9eu\xc1\xa1\xe9.*\xa6\xdd\xe3\x89\x8a\x9d\x9e\x1a\xe5br\x90\x90\xbe:;\x1d\x95\xa0\x19\xf7\x14\xbe\xef^\xc1%\xf9\xd2\xdfJ\n\xcf\x9f?\x07\x83?\x114\xdb\x19\x16\xe4`\xaf\xbf\xa9\x1f\xfa\x16\xb2\xd37\x1c\xa0v\x0c\x19\xba1\xc0\x990\x96\xac\x86Ph\xf6SvK\xf2\x97aA0\x03\x19F\xa1k}\xaa\xebR\xcd\xe0\xeb\xa6\x8bc\x11w\xab\x9c\x11\x03\xec\xe7F\x14\x14\xfd\xf9\x02 \xe6\x83:\xbd\x93\x98*\x8b\xfe\xb8\x01\x01eM1\xf2\x05\xdb1l\xa3E\xdc\x92R\xee\x10\x85\x81\xdc?\x0eyNx.K\xe4\xce\xf0\x8d\"\xa2\xa3\xd8}\xa7.9D\x90F+Ie\x1ekp\x94\xfa\xdcB\x82\x852\xc6j1G\xce\xa5\x1ccQ\x88\x04D\xa5\xfa\xe5\x08i\xfd\x94\"\xc0\xb2#\x88\x82\x98e\xdc\xb9\x0e\xc0C\xe0\xc8]\xb7OF\x13\xf6h\\\x99\xc2J\x91\x86}\xda\x99\xc01\\k'\xcarB\x8c\xc2'\xde0\x81m\xa4u|\x8b\x9c\xc1\x86t\x1b\xf1\x85d\x10\xcac\xee\xc0\x19\x1e\x86\xae*\x8d\xe5\x0f\xe7Z\x8d\x95\x93\xb0(\xdfX>\xc0\xb9c\x12%\xfb\xec\x8d\xbc\xcbM\x98\xd4\x84\xbd`WD\xa0\x8a\x9c\x93W\xadP\x14\xe6\x1b\xad\xaf\xbf\x05\x98d,5\x8b%\xbc_(\x1d\\s\x8dB\xa2\x82\xcd[,\xa5\x16`\"\x05\x86\xd1\x18\xffM!\x01'\x04s\x0d\x8c\"=\xc4\x91\x1b\x17Za\x01\xc7ej\xd1\x8eTf\x95\x17\xc4,*\x91\xa0\xd8\xa7L\x18\xd8\xfc\xee\xbdWt\xa5\xa6>\x84\xf0\x04\xff-\xf8\xbf)\xfek\xb8o\xad\"M0k\x1b(\x1f\x06\x0b\x17U\x89\x8c]\xc7<{\xee\xcfo\xd2rr\xf0\xc3+\x97\xc0\xf7r\xb6\x11\xf1\x98\xef\xb9\xd5&H85\xda&\x8d4\x1d\xaaaN \x83g\x10\x9e@6\x1a\x99\x992\xe0\x9d\xe1\xf42\x0f\xc7\x1fQ\xf0\xc1C_-8\x1c\xce`\x07\x16\x9dr\x1d\xd1R\xfd\xa1\x88\xd2\x9dy>\xfb\x1cF|\x81\x8az\xdf\x16tA\xacMr \xbb\xc3\xc2\xd7\xb2\x163\xd89\xe5\xa3\xf1\xf9*X\x80\xb3}mR\x18A\x01\xcf!\xac1I\x08;P\xe08\xf9\xaa=Gf.\xdb\xd9\xe9\x9arM<'<\x88\xed\x9a\xf1\x80kx\x06\xc5 \xac\xbb\x16\x1d\x94\x85\x87\x11\xac=\x16\xa4\x97.\xfe\xbaw\xa5\x81\x9b\xc0\x98\xfc\xbb\xf5\x07\xe3\xeft\xd62\xcbq\x80\x0f1\xa9\xb7+3\xd6\xb3j@vt7k3\xe0[\xf5h\x07\xe8\x061o1J!\xdc\xdf\x9b\xf8\x18\xa1\x04\x97\x90\xb6\x81\xe2\xcd\x05-\xc3\x9b\xa3\x90\xe79\xc4x\x0chqLq\x01\xfea\xee!\xeb\x85\x9d\x19\xfc+L)/7\xb68r\x0bu\xe2\x92|\xe9P=\xe5\xf0\x1c2x\x02\xd3zh\xf8\xabK\xfeP\xb1\xb3W\xb1h\x87\xa3Q\xd5\x05>(\x9aX\x87yA\xde\xa4\xa5K\x82\xa2\xba*\xca\xdc\xa5|B\xe5\xc3\xd4\xf3ar\xd0!7g\xd4\x9a$(\xac\xccu\xcb\x19\xbdi\x98\x8a&\x1c\x00\xf4Dc\x83\x0e\xcde\xcf\xa1\xe1\x8d\xfd\xd5\xfd\x19s\nK\xc7\xc2C\x95\\\xdb\xa0\xd3\xd6\xd3\xd5\xd0\x9e\xec\x06\x03u\x9b\xb2\x11\xd2\xecB 8Q\xb3\xf2L\"\xc6\xb3\xed3\xc1Q\x19D<\xe4\xc4\x8b\xd2M{$\xfam\xc0\xf7\xc0dy\x9bL\xfav\xd8\xa4\x95\xb5\x19\xd4\xf0\x97a\x0d\xff\xd5\xfda\xf3A\x9f\x0fm{\x90VC\x0e\xec\xc0\x83\x93\xf2]\x93\xaeZ}\xb0\xb6\xb7a\xcbu \xc5NS\x0f9\x02~ \x19+!\xed_\xc5\xf9M\xcaO\xc3!\xcb\x84\x93R\xb0\xb1\x7f\xe0C\xc6\xb6=\xf6\xea?m\x9a<+H~\xf8\xda\x03\xff\xaa\x8b\x9fUY\x08\xf4\xe9TXL\xf4\xd5\xa7<\xc8\x0fw%\x91<\xa2[\x85\\E\x85\xfd\x0c\x1b\xd7\x8b\xaeq\xa5RL\xa1\x9af\x1c \xb2\xc5\x10\xf3\x18\x83\x1ab\x14\xddv\x81\xcd\x8c\x85\xf8\xf0E~\x93r\x16\x1bLS\xc5\x83N$\xc6L\x89\xe2A#V\xcaJ\xef\x1e\xc1\x19\xec\xc11\xfb5\xdd\x853\xd8\xe5\xbf&G\x138\x83)\x1c\xdbD/\x08\x91a\x04 \xad\x87[|\x83\xe1Z\x8c\xf8\xc5#\x8f\x8f\x81\x05\xf6kz\xe1kS\xc9p\xf4jY%\xcdh\xb2_\xcfh2\x85{p\xc5\x9c\xe4)Vt\x8a\xd3\xf1\xdeS\xfe\xdd3\xd8\xdf\x9f\x1e\x1dP\x92\x88\x92\xb3\xfbOw\xf7v\xbdo:\xff\xbd\xc7\xcf?\xac\x7f\xedn\xb0\x1ajYhY\xa1Cm\x85\xa4%\xab\xd4%\x0b\xe9\x92\x1d\xec\xef\xef\xee\x03\x06\xf4x\x06\x93\xc9do2\x99J\xcbd\x9c\xa2\x99$\xae\x8d\xb1(_\x84\x9f\xd3\xb6w}\xbc\xc9\x18tl!\xf7\xe7.(>\xa0?\x0f|\x11\xb5x\xc1\xc4\xa8c\xd8\x86\xc9x\xba\x0b\xf7l\x1397\xb3\x7f\xb0;\x1d\xc3={\xb5\xcd\x0c\xc2\xf9w\x1e\x05T\xa3SH\xda\x10\xdf\x06\xa5\xfb)\x12A\x8c\xd8\x15 \x14\xe3\x14\xbc\xbc\xafI>C8,\xee1\xc2\x13\x85\x1b\xf5\x16 \xe9.\x1c\xc7\x0e\x18s\xb32\x10\x04\xf4\x16\x06\xd3\xdcXz\xc0`8\xba\xc9}\xa6\x9a{\xdfCD\xa5\xedEv[\xe8S\xfeE\x82\xda\xb7\xbd\xf0\x81\x04\xe7Iv[\x97t\xef\xc3\xa8l\"\xab`,\xdc.\xbbBT\xdd\xb9#S\xa0\x837\xef\xce?\xbcz\xf9\xe9\xf2\xed\x8b\xff\xef\xf2\x87\xbf|zuN\xcf\xd3\xd8&\x8b;U\x93)\x9b\xcd\x82\xcc\xe5=\xb1\x13\xed\xf9\x8cn\xa4\x88o\x92\xc9\x92\x9e=G<\xb5\x02M\xb6J\xb2\xe3\xb4\xba\x96Y\x00\xd8\x81\xa8\xb3l@8H\xf1\xf0Q\xed\xb5\xe5G\xe21\xc3\x8e\x07\x1f\xf6\xa6\x9cVZd\x99\xebY\xc5\xa1%e\xc8\x98\xa5\xe9\xf6\xb6p\xeb\xad\xcb\xdc\x89\x0f\x13OR*\xb6\x8fjg\x0c4h\xe6\xb0e\x90\x9d\xa8\xe7\xca\xf5\xe8\xc9\xfa\xfc6\xfc\xc2-\xe4P\xc5L\xcf\xd4:\xcb\x92\xf3\xf8o\x14x\x1cN\x8e\xa6\xb4\xe82\xac\xae{M\xb6\xc1\xb6\xb1\x85\xe2\x0c\xa3\x1fo&\xd8\x1e\xe0u$\xb5\x1f5\xe9\x05\x0d\x16\x98\x1dBjW\x1a\x8b2F\xe3\xb9\xa237\xd6\xf1-\xf6\x93<\x9c\xcc\xf66\xff+@{U\xc2\xf3\xb8\xa9e\x17LbF_\x99\xc3\x9c\x16\xbe\xd6\x8a)\xe0)wh7S\xa3\x9d _\x1e\x98\x1a\x01\xc1\xcef\xab\xbf\x81\xed\xa7\xf8\x02Y>D4ca\xd6$\x1bB2\xf3\xbe3\x93\x05`\xde\xd4\x0f\x161\x0b\xea\x86\xc6\x86j\xa1Tb\x00\xf0}\xa7\x05\x17\xe1\xe7\xb4\x08\x17\x83\xe3\xafX2\xb5\xe9\xcdQl\xf1-\x9a\x94\"\xac\x0cjk\xcbmb\xa1\xdd\xdf\xc3V\x19\\\x8a&\x0c\xadG\xd9j\x1d\xe6\xa4\xcf!\x1bd\xf3\xca\xdar\x03\xdb\xd7\xf4QF \xd9\x8b:\xba\xb7P\xac\xb0/\x8c\xb6&\xcc\xf0Eu\\\xee2s\x90\x15{\x8c\x0d'\xf5\xaf\x98\xc5\xa1\xcfdN\x92\x99\xd2\"k\x98Q\x86\xde\xe2t\x8b\xc3\x98\xc5\x17xD\xc9,\xbe\xe8B\"\xa9\xe0\x1cY\xff\xad\x0c$\xf2c\x97\xddZ\x89>\xccw\"\x94zh\x8e\x04g0Q\xe2\xe1Bs^\x84\xf9k\xef\x89\x11l%W\xfe\x94-\xe5\x8fy\xc2}\x06\x06\xdf\xca\x84\xe3\xbf\xc1\x1ee\x80\x8d\xc3?\xa8\x01\x88) )\x0c1\xb3\x18L'\xf8u\xe6\xd5\xc1\xd0!\xb3\xa6\xbc\xfa\xceI\xe2\xa24\x99N\xf2\xe0{\x90-\x04P\xb0YQZ\x0c\x1f\x04\x01m\xa2\xb1\x11>\x98[S\x02$\x18W\x0b!\x0ca\x10\xa4C\xaa\x8b!\x89f\xe9\x85\x95\xdd\x12r)\x05=P\xbch\x86;f>IO\x1d\xa5\x8d\xc2N\x9cW\xdc\x18\xc5\xce\x06\xca \xbc\xfa\x9d\xf6\x8f>\x153\xe6FM8g|E\xf4\xd6\x9e\xb3\x08\xcd\xb9mEg+dg\x8fS\x98\xfb\xa0Pz\x12\xfa\xdc\x1a\xab\xef\x8a\xdbp=9\xe8\xf3\x0c\x17\x0c\x0e\xc6\x8c\xea\xd2\x13\x95F=\x91l\xae\xc9GRP\x12\xbb1\x1d^UI\x19\xaf\x13BWpr\xb0s\x15\x97F\xb4\xa8(\x1a\xc6'h\xbe[\x9e\xb0\xe37\xf5\xe0\x86\xbb&\x11Jm\x8dZ\xd9KA\"\xd1e\x17M\x10\x8b\xa8.\xcb\xee\xf4\x9b.\xcb\xdeW.\xcb\xee\xf4Q\xcb\xb2\xd7Z\x96]\xcfo\x8a\xe82\xb1\x7fLZ\xb8\x0dV\xeb`\xef\x9b\xae\xd6\xe1W\xae\xd6\xc1\xde\xa3V\xeb\xb0\xb5ZO\xcd\xabu\xa0\x15O\xd9?\xfbZ\xf1.\xfbg\xef\xf1kk\x8a\x1f\xd7\xb5\xbah\x9e\xdc\xb5\xc2\x8a\xa6\xa3\x8e\xaa\xc5~\xb6\x02\x08\x9c\xc1\x0b>\x9b1\xa5\xcc\x07\x84\x87\x92\xc7\x93wh\xf2\xe9F+\xf8\x07\x8d`\x98\xcd\x99\xb0\xfa\x1a#\xdb\xf4\\\x9eO\xe3Q\xe2\x0ck\x17\xfd\xa6R\xbd\x91\xda\xd4N*D3<\x8a7\xcda\xb69Y\xc1\x10j\x15\x06Q\xac\xe2\xe1\x9d\xbf\xd8\xa4\xf3.:W<\xbc\xdd_7i\xb7\x93:\x86a\x14\xb2xx\xff\x9f7\xe9\xbf\xd7v\x18\x9a\x86_m\xd2p\x075\x0e\x83(r\x18H\x95\xc3&\x9494\xb3y;l6\xbd\xc4:4v\xd1F\xc6\xfag\x1e\xf9Rx+\x1e\x83\xcd\xbd@~J\xe6\x8e8\x02\xc7\x19j6\x0dF\x9a\xec\x81\x8b\xe4\xd9dmA\xa5T\xa0N\xfeZ\x85Iw`\x170J\x1bzd\x0b\x122\x146\x9a\x9d\x88\x87\xe3\x80\xfb{\x0e,kY\x88\xd9/\\\x9bE\x9c\x16k-xr\x17f\xb2)F\x98\xffRK\xca\xdf9p\x81\x9f\x9es\xb3\xe9\x9a\xae\xa8\xddy\x10Fr\x7f\xc9`\x15\x96\xd1\xd2}\x12\xfc6}xr-2l\x80#\"\xe3\xd6\x8d\xf1\x10\x80,\xc8L\x10\x04\xe0x\x9e\x0f\xce3No\xd4\xe1r\x9e;]\xebb\x91'\xf5\x1a\xb5\x7f\xfb\xad\xd6y<\x05\xb3\xea\x9e\xdb\x0c!\xa2v\x84/\xc8\xb1^/\xaf\xed\xb6\xb4\x17\xcc\xd6,naT\"|\xdd\x11\x03\x8bv\xef\xefQ\x80\x83/b\x1d5\x9b)>\xee\x8f\x9e\xd3\"@\xfbh\xdb|sx\xce\xc7C\xe8_\x9dnBM\xfd^\x17\x02\xad1{-\xa4\x03|H\xeb\xbf\xf2\xfa\xaf\xb8\xfe\xab\xb9|\x83\xc4{\x19\xba\x0e\xec\xd0\xd3\x83!\xcd`\x87\x1e\xa7P\x96\xe8e>T\x1e7\xdf\xc0\x00\xc8B/\x18s\x15\xacb\x99\xc24\xbb\xe3\x13H\x98!\xedh\x94\xd8%\x80\xd1,a\x12\xc0\xc5,\xe9\x94\x00f\x18\xbc,\xe1:sZ\xdb\x0e\x83\x1f!\x01\xcc\xe0\x19\x1a!\xa3\x04\xb0\x82g\x90\xd9%\x802\x94\xc2(\xc2C\"\xbbI}q\xe3\\\\J\x91%\xd7.Ao[\xf7o\xd4\xd9\x9d\x1aR\x03\x03\xaavu\"\x99\xfc\x7fmG\x93\xce\x8e\xd0C\xdf\x0c\xc7l@L\x8b\xb9Y\x93\xb8L|$\xddt\x9f\xf3_\xadVj\x0f\x14\x1d@\x99\x83\xa6\xe4,J\xf9F\xad\x9b\x8f0\xc2\xe0\xb8x\x1d\xa7\x18\x97\xc03\x04d\xe1\xae\x92,r\x81p\x8c\x10\x84\x87\x0f,P\xc7\xcc\xe7\x91t.<\x16\xc9\x11\x92,\xbd\xa6\xfc\xaa\x88Fk\x0f\xa8q\xcf\x00\x85\x18D\xea\xc1\x19\x05\xcc\xac\xd8\x08\x899\x07Ay3\xd9\x9f\x89\xd5\x1db\x94_\xdb\x18K\xa8pGO\xea\n]\xacU,98\xc9\xc1{\x9e\xd7NM\"\xe2 \xe3\xef\xf0\xafA`_r\xeeeg1\xab\xca\"\x9e\xd7A\xa9\xec\xf1I\xf2:\xae\x805^\x86\x02^U'Q\xabJo\x08\xff\xc5/\xdbJ\x0b\x94c\xde\xf2^\xd6k\x18\xdb\xc5\xfb\xbc\xdc\xa0\xcf>\x8e\x8b7y\xb5A\x93_\xab\x8a\x80\xa6\xdb\xdb\x0d\xba\xed\xe5\xb1x\x9b_6h\xf3\x1fN\xd9q>h\xf0\xbd\xdc\x14Z\xf3o\xc4I\xd9,u\x01\x98A\x13s>\xd5\xbd\xa6\x98\xc2\xb1\xdf\xf9T\x97v\xfd\xdf\xf3\xf7\xef\xfa8\n\xbe\"\xe6\x1bJ\xdb9\x06\x11\x0c\xc4\xccr\xcc\xc32<\x06\xdd\x93\x0e\xe9\xa3&oFp\x19\xe6\xb9\x88\x0d\xe6\xf7\xc3R-\xf8*\x05,\xef\xe1\x14\xf6\xc6G\x07\xb6\x90q\xbfv\xe1l!A3I\x92\x1ec\x16\xac\x98\x03\xa3\xce\x97\xd9\x8c\x992@\xa2\xc1)js\xed\x0c\xe40\x87\xde\xcf\xff\xa8S\xfc\x16\x93{3drv\x1bDw\xcb&\xf5t\xb78r\x95\xd8\xa7\xbc\xc1\xb2\xa6+\xa9,\x82\xe3\xb0\xfbG\x98\xab\x1c.F\xe61}\xd3k\xb7\x9ce\x1dS\x8f\x07M\xfdm\xd7\xd4\x15St\x8d\xf1\x90\x877f\xc3\xcbk=^\xc659\xb1m\xd7\xf2Yv\x01#\x98\xee\x1f\xc0\xf7\x90\xcf2S\x90X\xd8t.\x9f\xba\xe6\"4\x12\x13\xd4H\xb0\xd8\x18\xf6H6\x0e#\x01E\x04\xef*NK\xbb}\xc7\x08\xc9 k\xdc\xb7O\xf9]\x9c^c`\x13Lj\x00W\xe4.K\xe7\x82\xf6ak6\xd0\x0b\xf7\xa5*\x82@\xa7\xc8\xc7K!\xbes\xd8\x18\x8ca\x80\xb8\xb0D\xc4\x0f\xb1i\xb2 \xba\xa8\xf1\xe3\x9fY\x03\x03\xe9\x91\xfe\xf4\xd8t\xb6\xe615\x88$t\xb0\xc7\xc1\x9c\x93/ \x8b\x17\x06\xae\xe8\x87\x1ef\x88\xd4>\xfd\x84\xdbS\xef\xe3\x86\x9b\xf5\x92\xca\xed\xd5\xadud\xaf\x17\x1f\xa6\xaa\xe1\x0ewG\x8b/\x00\xf5\x10\xdb\x18\x94\xe7\xd938\x84\xef)\xfd{\x061\x1c\xc3\x04v \xf6<\xb4\xd16\xbc\x184\xe1\x8f\x1bMxoz\xb4wt\xf0tz\xf4\x8df\xbdg\x9f5iOk\x17\xa7\xc5\x16c\xd0\xe4\xde\x0d\xbe\x1f_s\xb0lG\xb5\x03\x9e<\xfa|\xfe\xa4\xcc\xc88\x9dZ\xaer\x7f\xcf\x16`\xec\xb3\xa5\xf6!\xe6<\xae\xdc\xc6t\x97\xbd\xa3+\xb07h\x0c?>z\x0c\x87\x961\xecO\xd9;:\x86Cm\x0c\xf2\xafB\xa7\xeb\x86\xd8\xef\x08\xaf\xb8aJ\xeaS\xf8\xaf\xff*}=\x08&\xe1\xb9O\xfe\xeb\xbf\x88\xcf0\x05\x0bC9\xa2X\xbb\xbe!\xa5\x888RR\xc4^\x17\xe5^\x13\x92\x8c\xe5\xea\x92\xbe!\xe2\x1bR\x7fC\xa4o\xca\xba\x04\x93\x1d\x1b\x03\x985:\xcf\xda\xea\x1a\xd7\xc2\x1a s#\xf9IM\x81\xc1\x8e\x9eeE3\x86\x11\xec\xec\x101\xef\x13<\xda\xe3\x9e\xe9\xd2\x0f\xbe~\xc2\x87C\x00\x02o\x90\xd4s\x9c\xf8\x9a\x82\x83o\xdc\x90\x1e'\x07\xedc5\xa8\xd3\xa9\xa5Sn\xe9\x81\x8b2\xb9@\x9c?l\x1c\xed\xcd\xfe\xbaq \xb5\xa1\x0cf\xc88v\xa7\x8f\\\x8f=}\x1c\xae}A\xe4\xa2)\x16\xb18\x7f\x93\x83\xa7O\x9fN'\x94\x8b\xa8\xdf\xef\x0e\x1c\xf6#\x97\xaf5\xec\xd6\x18.D\xe2Li\x06\x93\x83\xf6\x14\x94Y\xed^t\x8a\xf0\xe9\xb0\xff\xd7A4x~\xca?\x9fL\x0f=.\n\xdf\xe1\xb4\xe3:\xbbu)\x95\x00\xdf\x03\x06\xf3\xec\x05\x07\x7f\x0f\xf0G\x94\x85\x91`[~q\x82\xe4e\x1b\nf\x1a\x14\xcc\xbb\x17)3,Rf]\xa4l\xc0\"}#\x90\x89\xbe\xd7\xf5\x89Gu\xde\xf7\x80\x11!v\xa4{0\x11\xa9\\\x07@\xd7\x0d\x80\xab\x15\x9a\xb5\xd7\xf1F\xf8UX\x81\x8bu\xedw\xa7O\x0f\xe8$S8c\x8c\xd0x\xf2\xf4`\x0c\xf7\x90\xc2q?\x05\xb2\x01\x8c~\xf4t\xd8$\xee\x15\x10\xfe\xfbM\xe7\xdb\x81\xfa\xcd \xbd\n'i\xd9to\xd0p\x87\xad\xfe\xf0\xe1b\xcf\xedA\x0f\x00\xee}\xc3}\x9dd\xa1\x01\xba?n\xb816\xd9(\x1a\xb6\xc6\x82\xeb\x1b4\x8co\xb5j\xadaL\x86\x0e\xe3\xc7\xac\xbaJ\xc8#\x97\xe3\xb0w\x1cc\xc1\x80\x0e\x1b\xc7#\xd7\xa3\x7f\x1c\x93!\xe3@\xe6\xd9\xca\xcdX\x848<\x9d\xa7\x82\xe0\x98\x15\x0b\xaam_\xea\x06\x04:2I=\x96t\xcc\xe6\x88\x12\xdbc\xfce\x1dN\x1fx!H\x13r\xba\x14\x94D\xdaB\x93\xac*#\"N\xa1\x84'\x1039\x90\x15\xbc\xd1\xca\x9dP\xac^I#\x99\xf0w\\\xc9\x14\xabXW\xd3`\xa4$\xad\xa6\x10\x9f\xd5+\xba\xb3\x13c\x808N*\x18\x964\x16K\x9a}\xb3%m\x11\x15\xdd\x16,\x86E\xd5\xd7\x92\x02\x8b\xfd}\x1f\xf5(\xd6|?\xb8;M\x06\\\xb7\xf4\x04\xb4\x96O\x197\xf9\x1f4\x11\x13\x05\xf2\xd5s\x99\xfaLr\xdc5\x9b3\xc3\xf5\xf0\x9b=\x9b\xb0=C\x11)\xa5\xa9>(\x1dl1\x1b\xfb\x91\x166\xd2>\xc9\xc1\x94\xf2\xef8I>\x1b}\x92|\xee\x86IN6\x9a\xa4\x89Z\xf9\xeaI\xee\xf9\x92H|\xd0L\x19\xcd\"f;\xdd\x93\xa6;m\xca'\x07\x96\xbd6\x1cg\xba2\x1f\xcd\xdb\xdfI\x16I+\xf3;l\xff\xe6+cY\x95\x89eU\xa6\xe63\xb3\xdb\xbd2\x93\xc1+\xb3!\x8a\x15\xd2cyY\xb6\xac\x06G\x02\xd4\xb7\xd0\x03\x86\x8e6\xcbN[\xb8%f\xa8d\xc7\xe0\xe6m\xb6\x07C\\lF,=Qz\x1f\x89\xc1+\x19\xdd\x08\x917wJb\x7f\nsL\x86\xdb\xe9\x84.\xf0\xcb\x10C\x14\xf9\x1a\xdew)\x96\xaa\xe0\xf9s\x18S<\x1a~\x13|\xb5!\x05\xf0?e\xa3;\xa8\x88\xaf\xdal\xb1\x17\x12\x81\x915\x04\xc6\xc6;>\xfa\xfb\xec\xf8\xefB\xa0L\xa6O}\xd8\x99L\x0f7\xa7Q\x14\x1d\x12]Z\xe6\x930\xf9\x1a\xfa\xe5w$_v\xa7O\x0f\xe8\\Q\x860\x0c\xb4\xff\x8e4\xcc\xefH\xc2\x04_K{0`\xca\xdd{;\x80\xc4QH\xa2\xaf\"h~Gz\xc6\xbeD\xea\xf5U\x8c$\xc4-\x1e\xb0\x8a\xff@\xc4\x8fE\xfe\xd4\xbd\x8a?i{\xd6\xe7U\xd1\xf4\xb4\xe9~i=M\x06\xf5d\x93\"uw\xf5\xe3c&e\x13\x14m\xd4U\xef\xac\xa2l}\xb7\x19\xdd\xd2\xa4\x9b\x1c\xa3Cd\xed\"\xd8\xd8\xd5\x97\x9a\xa7\x97\x94\xa5\xa41E\x90+\xd0\x0fI\xdd\"Wq\xe45 \x88\xce\x0b\xcc\xfb\xb2/\xbdS\xdc\x8a\x84\xd2\x0cP\x1eVO\x13\xa4\xcb\xf0\xa6\x0c\xf3kR\x9e\x97a^\xf6gC\xad\xcdx\x80\x19kj\xc30\xf7PdU\x1e\x91\x0dz\xc8\xbb\xc6\xcbZ{\x95\xce\xfb\xdb\xcaU\xe7\x8bz\xf5\xd5\x1d\x95\xec\xaf\x08\xc6^\xda\x916Jy92Z\xe5\"A\xcb\xf4[\xb99n=\x12\xc8\x8d\x1b*\x06]\xe6\xcaA\xec\xb1#$M\x0c,]\xc2\xe4\x04b\x9e\xd5`g\x07\xcd\xc2b\x18\x01\x03\x92\x14\xd6\xd1_\xa6\xb8/\xb5\x93\x11eA&d\x17X\x18\xaf\xcd\xb2\xfe\xb105\x9aY\xda\x06\xfd\x1b\xf3\xb9\x14\xa4\xac\xf3\xb8\x94\x8a\xa9N\xca\xcc\x9e2\xcf\x9c\x0bS\xe8\xfd\xba\x00\xc1\"\xc6\xf4\xf6\x1b\x00\x02\x83\xd3\xd5\xc6\x99\xadEz\x02\x0c\xa9\xc1\xd1\xa6vC\x8c\xe9s%\xb8\xd0\xfe\xc4\xe7Y7\xfa2#\x81\xec\xe2$\x07,\xb7Y\x1e\xd1\x87n\xe9t\xff\xa0F\xd4\x96\xf8h\xf6|\xabz\xb2\x19C><\x9b?{\x9d\xf1{h2o\xcb\xb2c\xbfj.\xe0\xdc\xe6Ul\xf3\xfch\xf5\xc7s\x97\x98\xf2\x9d\xf3\xc5b\xa9\x92\xacF\xbf\x1cF\xca\xe0\xe7\x19\xc3\x0dj\x91\xd5*\xfa\xfd`O`\x0c\xe7\xd1\xc4\xcf\xa3\xed\x9b\xa1Tf\x1bl\xe3\xcc\xab%\xba>SF{\xcc\x93\xc8\x8d}h\"{P,gL\x0bo\x87'\x06\x8b}\x04\"L\x93a\x01\"viB\x85\xb6|r\xacB\x96Q\xf8g7\x15)\xeds)\x01\xa6\xd7\x91\xbc\x99\xb2\xdc\"N\x95\xf9\x10\xd6\x13\xe0\xb6z\xe8\xa3\xacLB\xc0\xc5j\x96\xc1\xbfB\xb8\x81\xcd^\xd9\x8a\x91\xa3\x8e\x81N\xf6op\nOf\xff9\xfa\xe5\xc9x\xe7\xe8\xc5\xce\xff\x0bw\xfe\xb6sy\xf1\xe4\xda\xe6z\xf3\xba;\x84+\xa0r\xf6\x0c\x9c1:\xfd\xabiB\x8f\xb5\x02ul\x96\x0e\x7f\xb6*\x00o\xcc\x01\xda\x08\xf0\xa88\x13x\xd2\x9b\xe3\xb2q\x90\x89Ex~S^\x87\xee\x14*1\x0bl\xd3J\xec\xe0\xc1s\x8c\xe6\xbd/P\xf4\xfe\xd3\xdd\xbd\xbd.\x80\x1b\xf3\xfcp\xf6\x1aP_\xd2\xe7\xb0\x7f\xb0;9\xea\xabL\x1f\x96\x88b\x97\x8eggB\x07\xc3\x93ILw\x8f|\x98\x1cM|\x98\x1c\x1eu\x80u\xf1DYZ\xc6ie\xce\xa5$\x1e{\xf6 \xe0c\xaf@\xa4~\xb2J\xf5\xe4\xe7\x1fi\xf4\x98\x10\xaa\xb3Jo/\xdd\xd9\x95\xf0\x98\x1c\xecN\xad)\x04\xc53lU\xfc\xdfy\xc8)\xf7\xd18\x80\x11\xa5\xebvx\n\x82g\xcf`\xc2\x0c]v\xf8l\x8c-\x88\xb4\x89\x9c\xef\x190\x1f;&o\xeeo\xca\x12U\xf4\xdd3\xd6\xe1\x84eg\xe9K\x7f\xc0\x07\x93v\xcf\x83\xef\xdft\xbc7\xb0\xf7\xe9f\xbd\xc3\xf3\xe7\x98\xcb\x00\x03lcB\x83\x94\xfe\x9a\x1e\x0e\x1a\x16\xee\xd3\xb0q\xedn>.L\xba0\x9d\xee\xb1\x10\x1ep\x00\xdbt\x848\xba\x0d\xc6\xda\x03\x1aq\x1e(\x14!\x92\xb4&V\xd2\xdar\xf6\x99p\x86\x19X(i+\x93\xab\xfbu\xd6\x7fy\x8cw\xa6\xe3t'\x13>\xb5\x07\xbfS\xb8&h\xa8\xd4}\xea\x05,\xe8|\xd3q\x19\x90/\xeb,/\x8b:\x85\xf1\xe0\xd6\xf6\x0e5\x8a:f\xc5GZ1\xa5\xd3\x9cY\x86a\xf0y\xd0\xfb\x0b\xc7<\x02\xfb\x89\x15'\xa7\xc0\xefU\xc6\x8c\xae6\xfdb{\x1b\x90\x0d8=\x95\xee\xdd\xc3f\x93\xda\xdd\xf5\\\x16\xb1\xdf\x07'\xcaIX*~m_\xb1\\\xbbOw\x8d\xeb\xb5\xfbt\xcf\xb0`\xb4|_+\xafx\xf9\x81V\x1e\xf2\xf2\xa7\x9e\xc4\x0d\xd4\x07\xbbh/\xe6\x0d\x8f\x0e\xbac\xd0}\xa6\x1c?\x03\x0f\x9f)\xa7sV\xcfk\xad\n\x0d\xa2\x84\x84\xb9\x8b\x87\x9cX\xb3q\xddt\xa7\xd4FQ\x10)\xdd|6\xbe\xf0!\x9fMt\xbb\xff?\xb4\xffRd\xc0t\x0ctWT\x89\xd0\x9c$\x04c\xfc\xc4j\xf95\xa1\x102S\x0b\x97!\xdd\xd7J-,\xb0f\xe8+{_l\xb6\xf7O\xf7,gH\xf9\\_5c\xf8\xfb\x13HwvN\xda\xf0\x17\x05\xa8n9K/p\x01\xa5\xbc\xd1\x1aU\xc9K\xa5,\x9f\xe6+\"\x8ff\xf0\x90\x1b5\x92\x88y\xdad\xc9!\xf4/\xf2\xe8\x8b\xf9\xf4\xe81k\xd8,\xdf\xe5\xe5<,\xc3\xcbK\xe3j\xe4.\xf1\xe0\x0c\xd2\x99E\xbeW\x17\x1f\x83\xb3\x0c\x8b\xa5s\x01\xc7\x90\x06\xabp\xfd\xd8\xf9\xec\x8d-\xe0s\xa2_{\x06\x0e\xf0v\x8b\xa2\x8d`f\xc6D#9\xcb\xe8G!\xe5c\xc7<\xb1\x80\xb0\xc9d\xf7\xb1\x83CP#NH\xec6\xd2N\x8aY\xf3\xaf\x18\xeb\xd3\xb1a\xa8\x9a\xa8a\xd8Hmbbz\xbaY\x0c\x01q\xea\xdbb\x1bT\x12a\x14N\xe3\xb1s\xc6\xd8\"\xaa\x04\xe8\xd8\xe8\xbd\x81\x9d\x98\x1e\xb8\x9d1=l\x1b^\x17\xa7*XB\xf3\xa8\x94:lh\xc6\xd6\xf5\xd8\"\xc1\x0d\xc9\x0b\x8a'j\x0dS]TG\x86sn\xc6\x81\xe3u\xd7\x98\xd0\x1a\xb5]\x8b\xb9\xc6!\xads\xa6,{\x1bO\xa4\xe4K\xf9)\x8e>\xab\xb1\x98;bK\x82\xd8#Q_\x96B\x97\xb6\x08\x0f\x94\x8e\xba\n\xa3\xcf\xc6\x18\x0f\xa2%[\x98\xfb\x9b&\xab$\xb4\xc3J\x9b\xbf\x11\xb1\xb7\xc2.b\x1c\xa3&\x8d{\x02\xd5\xf6$\x80\x14\x16@\x81XI\xb7+X,\xb6\xd8\x93\xdf\xb1\xddb\xbd5}\xe2\x0f\xc0k\x86D+\xe7\xfa\xcd\xac\x83x\x1e\xfa\x86\xda\x93\xdb\xf1\x9b\x0e\xb5\x95{U\x7fzG\xdb\x93\x89\xf1[\x8f\xd6\xb7ir\xc4\xd35\xe0\xde\xd8Z \xcb\xc1\xe9}b\x1ci\x88\x16|\x8a\x1c6\x137\xc1\x83lV\x8dF\x17\xf2-\x99U\x1dq3\xe1[\xac\n\x8bX\xcc\xa5\xc4}\x0bb|\xdd\xc7\xe2? U\xdc\x801 N\xcb,\xda\xee\xde\xa6,\xda\x81\x89*\xc8y\x96B\x13y\x9f\xf5\x91\x8eqJ\x81 \x99q\xae3m\x14\x13\x0f\x86\xe6*\x9by\x86\xe0L\xeb\xf7R3\xe2\xaf\x98e{\xa3\x98\x9c\xa7\x1ek\xfe\xe4 \xb8\xf4\x02L\xa1\xa5\xa2\x84\x1c\x8e\xc1\xcd\xdc\x9cN\xcb\x9734V\x9e\x0f\x99\x1b\xb3H\xb0\xd5\xd0\xccr\x88\x1aL\x8a\xaa!\x01\x88\xd3\x8cc\x04\xde\x80gD\xe3\xa6E\xa1#\x1c\x9a~M\x19b/\xee2\xc5H6\x0fO\x1c\xab\xb8\x85\x01\xf8\xc0%5.1ghKYf\xe8\x98\x9fh\x9e\x13\x1a\x7fJ\x7f\x8f\x15?\xe4f\xee\x03\xb2\xae\xfd^so\xb6\xc6\xb4)\x03\xf3\xb7\xfd\xce\x83\xcb\xa5|\xa3\x1b\x93\xbafZO\xbeH\xa9\xbbwp\xe4\xb9\xce\"\xcb_\x85\x91\x08\xa5\xf5\xa8f%\x1e\xe0H\x17?p\x1e\xe0H\xe7\x0d2\xce\x1b\xe8\x10\x8d\x891\xf6\x9e\x1eJ\x8b\xe2n\xc6\xd0\xf9\x94\xfa\xe2 \xbd\x8d+\xdb\xca\xf4\xf1\x0c\xa6\x94~5\xd8)\x94p\xc6r\x15s\xf3\x8d\xd2g\xc9N\xab$\xa1'\xbcPP\xd7\xf4\xc2W\xa4#\xa8N\x0cy\xe2!\x16g\x15#\xd5\xa6\xa8P\x16v.N\xe4\xf0\x80\x91R\x19\xa1e\xa1Zv\x8b\x01\xd9##]\xcc\x93A\x1a\x12\xa2\xaa\x99 \xd3v\x05\x92V+\xc2_g\xed\xd7\xb7y\\\xb2\x97\xa1\xf2\xee\xc1\x87\x02\x19\xc7\xd8-\xe8\xb0\xe8\xcc\xa2\xe6\x90z\xc1\xf5\x90\xa8\xd3t\xc3\xf8V\xf9\xb00\xb3A\x96]\x89\x1a\xd3\x18\xf3\xe6D\xca\xe6\xecJ\x9bC\xc1\x99\x14\xba\xe8\x182\xce\xe1\xf3\xf7\x14\xae\xa5\xea\xfb\x149\x1c\xb9S\x1e\xc1\x87nh\xd4\x8cAz\xa3\x1d\x06q\x10\x8a\xe6 \x84\x86\x83P\xb4\x0e\x02\x8fa\xde\xde\xf4kR\x1a\xb7\xbc\xa0\xe5\x86\x9dV\x8fB\xd8}\x14Z\x89y\"\xbe\xdb\x11\x1d\x0ff\xc3\xf9\x16 I\x92\xe1\x1c\xdaD\xa9\xc1\x8f\xaf^\xbf\xf8\xf9\xa7O\x9c\xb0\xcc]\x0d\x0e\xb3 \xe7\xc70K\xdd\xfd]O\xcb\xdeO\xbe\xac\x938\x8aK\xfe\xfa)\xdd\x16w\x7f\xf7\x90\xff{\xe4I$\xcf \x18hgP\x05\x8d\x0c\xa9;m p./I\xf16\x9bWZ>\xd6AKG\xdb\x93\x05\\\x8a\xf5C\xea\xd6\x1abwz\xc0AI\xea\xee\x1eq\xaa;u\x0f<\xd7\x11&\x1b\x9f\xc2k\x01Z\x9c\x97\xe7\xe7\x1f\xab\x84\xfc\x14\x17\xa5\xff\xf2\xfc\xfc\xbc\xbcK\xc8\x8f$J\xc2<\xa4#\xa1e\x7f\xa2p\x85UHb\x92\x96\x1fIT\xe2\xcf\x1f\xdf\xbf\x95\xfff\x8d\x8b_\x9f\xb2\xcf$e?\xc22\xfc\x94\x87i\xb1 \xf9\x9b\x92\xac\xb0\xf0u\xcc;\xfd\xf7Oo\x7fz\x91$/\xb3$!8y,\xd1~\xbe\xce\xf2\xd5\xab\x84\xd0[\x8c\xbf\xcf }+J\xde\x92y\x1cbco\xe3\x15\xa1\xe8\x96\xa5\xe9}\x17\xae\xc8\xfc]6'o\xc3\xb5O\xff\xc5:\x1f\xc2\x98\xce\xe1\xaf\x15)\xd8\xd0?$\xd5u\x9c\xf2\x7f\xd8\x97\xe7\x7f\xfa#K&\x87\x15\xce\xff\xf4\xc7w\x88\xa5\xc5\xaf\x0fa\xb9<'\xd7\xf5\xcf,NK\xf1CZ\x85\xf3?\xfd\x91\xcd;\xcb\xd9\xa4\xcf\xd1D\x95\xa1sV@\x97\xfb|I\x08\xfb\xfc\x13eg\xf20\xfa\xfc\x92/x]\xc0~eU\x84#r\x82b\x9d\xc4\xa5\xeb\xf8\x02Z\x8cO0 ~X\xcb\x80\x8b\xd1\xc8\x04g\x11\x1e\xce\x8a\x8b\xf6\xbd\xa7\xe0%\x9fE\x867h0I\xe9\xf2E#\xf4V\xa14\xe6<\xdeJf\xd5\x05\x13\xd2%(\xf9\xa0@\"\x9bE\x94\xab\xc8\x02\\\xd7\x9e\x13\xaf3<\x14\x8e\xfe\xf6P[\x1am*\x96\x13\x02D\x0eH=\x1e\x86\xf5\xd0\x87\x9dI\x1f)e\xbb\xec\xdd\x94`m\"\xd7\x10\x80\x12\xf1\xf72L\xbf+\x81\x0e\x06V\xa4\\fs\xc8R0\xe6\xeaii+7\x1b$\x07-\x83Y\xca\xa9\x0d\xeav\xd2Y\xa8\xc7\xef\x13o\xa6\xbe\x1e\xa1\x87\x19\x16ZR\xa4s\xe3+\xb1\xe3B\xc8\x8b\x80Mlc\xd3\x9f\xa1\xe5\x8eF\x91\xbe\xff\xf4\xde1h\x1aeY\xcc\x83\xfa\xba\xd0^\xb7`\x0d\x1dl\xc9\xa9(w2=\xf4\\'^\xe4\xe1\x8a\xe8\x1d\x89'G\xe8b\x13\xab\"\x92$AA\xc1l0\x8f\x8bu\x12\xdeQ\xac\x97f)q|\x9c\xfb\xa1\x17\x84\xeb5I\xe7/\x97q2g\x99\xca\x83\"\xa7\x80\xd2\xf95\xbc \x8b(\x8f\xd7\xe5\xb1\xe33\xabV\x12DYZ\x92\xb4\xfcs\x9c\xce\xb3\xdb`\x9eEH\\zA\xb6&\xa9\x8bn\x03,j\xa7\xf3\x8c}\xfa\\T ^\x9f2\xc5\xf1\xb3_\x9e\xf0W\x98\x81)\x88\x92\x8cE\x8c/\xf08\xbd>\x81|g\xe7\xc4\x03\xae\x9a\x94t\x8d\xb3l\x96_\xd8\xad\x02\nWS\x89\x9a\xaf5O8\xcf\x94\xd7\x94\xa4\xed\xe7\xa7\x8c\xf0\x89\xabf\x04m\xdb\x0c\x93\xa2\x12\xb7\xf4\xfc:\xdce\xe8\x83\xfa\x9aK$)\xc68e\x0eX\xb4j\xe1\xaaY\x95\x08\xd2\xe0\xc7\x10\xbb\xa9/'\xe8\xed\x07\x87\x02}\xa0\xf7hDb-=~\xae8\x96\xf6\x01?\x9b\xa4\xabx\x17\xbe\xe3\x0e\xce\x1eW\x84\xbb%\xfa\xf5\xb0\x10\xa8\xa9\xb71\xcf.\x11t\xbb\x9e\xeb|&w\x85~\xf2\xd9\xa5U,\xcc7\x1av\x8e\xe1\xa3\xee\xc1\xc5?\x98\xec\xe7\xf1\xa34 #g\xce\xe5e\x94\xe5d\xe7\xd7\xe2\xb2X\x869\x99_^:\xa2O\xf3;\x8a\xe8\x1f;\xa1XL(f\x13\xfa\xed\xa1o:6\xc4\xe9DYZ\x94y\x15\x95Y\xee/\xc3\xe2\xfdm\xfa!\xcf\xd6$/\xef\xfc\xb8\xf8 \xce\xef\xfb\x85\xbf\xe6\xc5o\x8aW5\xbf\xe4\x97\xd9OY\x14&\x84a\x03_\xa0\x05\x9fc\x1e\x99j\xdbl\x95'{^\xb00\xcaTtQKf&\xf6\xfbV\xd6\xcc\x98\xa3\xcau+\xc6#\x9er\xdb\xf9\xb2\xb9\xc6\x18\xd0\x98\x99\xd4\xa0\xb8\xa5\x0d\xcdUfs\xcb\x10PA\xc8,\x94\x17\xbd\xfb\xb7!W9\x9d\x1cy\xee\x96\xec\xeeBq\xcb\xbe\xc7s\xde\xfb\xe0\xb0?\x1c\xbf\xe3\xb0\xa1\xfd\xc9%]\x8a:S>\xf7O\xbaD\x83\xaff\xc8\xbe\x1d\xc5I\xe8\x8d\xb7g\xb6\xaf\xe1\xed\x9a\xa1\xaebHvf\x17\x041@\xda\xee`\x9e\xa5*\xffI\x9f\x07\x06\xbc(\xe0\xc6\xe5m\xe66\x92\x8d\xeb\xad\x9d\x19&\xc2\xfb\x99X\xf7v\xc3[\xb071\xcb\x15[\x9cm\xebF\xd4r\xd7\x02\x89\xb7\xbc[]\xa4K\x08\xd5\xf1\xbb^\xefm2\xed:A\xfd[\xd5%d\xaf\xf3\x11\xff\x9c\xce\xc9\"N\xc9\xdc\xa1H\x84\xc9\x8f\xf8\xabwU\x928Fg1\xa4E;\x119\x0e8\xbf3\x94Jc)g\xc4\xe0\x98\x02QX\xa7\xe6\xd5\xf4\\\xe8\xd1\xca(\n\xbc\x12\xb1\xe7q\xac\x9d\xa1\xb0\x08\xb5\x00\x0e\xab\x80\xc3u+v\xca<\xcfFV\x03KBCP\xe3 m\xdd1T=\x80\xc1D\x02\x8c-\xa8?\x0f\xd3y\xb6r7\xdeM!\x92d\x86\x8a\xaeC \xc2(,]}\x17\xe9xK\x1f\x1c\xef\x92\xd2\x8e\xa3Q*\x92\x04q\xf8\xb1{\xf0x\xb4\xbbk\xbe\n\xfb^M\x8f\xb6/A\xee\xc6\x1c\\\xc7\x9c\xf4\xe3\xf2\x93\xc7\xae\x00\xdd_\xad)fA\xf4\x9bn\x8a7x^\x93\xddn\xaa\xe7\xa8\x9fS\xfd\xef\xa0z\xf6\x9fZ\xf0\xf1\xbe.\xf1\xcb\xcc \xaao\x12\xff\xbb\xf1\xf1\xc1\xc4\xb4\x00\xc1b\xc8>Rn\xc2^ $h\xdb\xe6\x92\x10\xa3\xad\xf3l\x15\x17\x843&\xa5+O\xc4\xea\xc5\xa4y\xb4\"\xd3$\xfdN\x0d\xd2\x9e\x1f\xc29|\xe0}Id\xa5=\xf3!\xea.\xd2\xdalX~\x1e\x04:\xceI\x91%7\x84\x03\xd0\xba\xf0W\x96\x858\xd7\xddZ\x1e\xbe\x82\xff\x98\xec\x99\xa5\x05\x93\xf1#O/\xb3?m\xb2JJk\xc5n\xc6\xffq\xd0L~\x04\x0e\xcc3R\xa4\xdf\x95\x98\xf7g]BN\xae\xc9\x97-\x8b\x8e\x94\x83\xd3\xaf\xba\xd0\xf4\x82b\x8e\xe4\xfe\xabiD\xeep\nO\x82'\x9a|\xc7\x88j\x9d'\xc1\x13\x07f\xe5\x85K\xb4\xbd\x128\xb6\xb5p0\x04o\x93Y~\x81J%\x1f\xb6\xac}@\x0f.7-\xef\xa6z\n\xf3\xe5'A\xa3\xfb@ e\x1b.Tn\xeaN\x0f\x0ft/\xdc\xb8~u\xa8\xbfB\xd2\xceD?\xc4\x01W\xc3 \x85\xd1\xf6\x08\xc8\xeb\xf7g=\xc0DPE\\\xe7\xa8\xed\xd8\xf1\xc0\xaf\xad\x84\x8e2\xd02\x90\xe0\x04\xcb*\xad\xbcFPS\x17I\xe2\x94\xb3f\x8e\xc7\x96\xa1\x9a\x0c\x83*+\x90\xe5\xc3\x91\xb6\x8c!\x9b\xf6\x0ckuWi9I\x0f\xd2\x11\x10\x93\xd9p\xd7N!s\xeb\x1d\xf3:\xb7\xccBPW2A\x9d)@\xb1s\x0f\xff\x1e\xfb\xb7\xc1\xd8\x87\\G\x82h5u\x0f6d\xb6L\x82\x9d\xd4\x9d\x1a\xc9\x9bC\xb3\x01\xc7dl\xf6CAi\xc6c\xc1l\xcc\x1d\x94\x98\xc0G\xfc8Eb\xf4\xb7\x0748j*\xfc\xa6[3:\x97l\xf7\xd0\xbd\x1bC`0\x0f\x84\x98\x87\x9f\x0e)\xf3[v\xb0\xb9U\xb0p\xb5\x08\x06\xbd\xd4Q{;\xb8\x00\xf6\x9a\x94\x92\x84\x89\x0d{C\xbf\x91\xdd\x03}K\x84\xcf\x90\x99\x12\xdd=\xd4\xad\xde\xb9\xcf\xd0\xa1\xceQp\x9f\xa1\xc3\xe9?}\x86\xfeA}\x86(\xaf\x94\xbaO=\x1f\x9c\xb7\xe1\xfa[9\xa1\x1d\xea\xde%\xdc\xebdj\xf6:\xd9\xdb\xd5\x0f ;P\xfa\xf1\x0by\xedG\xfb\x81\x18\xe1o\xc9\x11\x93|\xb628\x06'k\xe4\x0dR\xd5\x8a9\xba\xc4n\x89\xe7\xa1\xa4\xe7\x81\x82\x0c\xc6\xb6\x86\xfd\xc0U_3z\xae\x8f\xc6\xe3\xa7\x93\xa3\xa3\xe9\xfe\xde\xd3\xbd\xf1\xd1\xd1\xa4-nx\xf2\x9f\xee\xd9\xf1\xf8~6\xd99\xba\xf8e\xfe\xbd\xf7/O\xfa\xd6\xc0\xa2\x86\xc1\x10>|:FZxk\xcb%\xd2U\x13\xfa\x13\xc2\xb2\x9f\xc8F\xae13v\xe3hg\xeb\x94\xf9\xee\xe7AI\x8a\x12u\xba\x88\xb1\x84\x0b?\xcb\xffy\xcaC\x97\x96\xf0\xac\xd7\xefd\xc8J\xf5\xad\x82\xed$Xb\xeft\x0c\xf7T\nu:\x08m6\x17\xc2\xec\x84\xd5r\x1e\xa2\xb7\xe1\xc9/\xc1\xfd/3\xf7\xecx\xf6\x9f\xb3_..\xbe\xbfwg\xcew\x17\x9e{v\xec\x9em\xfd2\xf1f\xff\xf9\xcb/\x17\xf7\xbf\xfc\x12x\xdf\x9f\xfd2\xf1~\xb9x\xd2\xbe9O\xfe\xf3\x97\xdb\xef\x1fu@\xb8\x7f_\xa3o\xde\xd2\xc2\xdf\x8bm\xe8>A\x8a9k\xaa\x90bu\xc1U\x96%$L\x9b\x12\xc5Ik\x0bY1z\xbe*q\x9c0\xbaX&\xff\x12_\x10\xb6Cq*d\x88\x1b\xa9\xf9j|\xd4\x96\xe42\xf15\xb9!).\x9d\xf2\x13I\x03!\xe1^\x85_~\x8a\x8b\x92\xa4$o**\x855\xb3/\x8d\xac=\x84|C\xd0\xd5\xd9Xlo\xcc\x04\xda\x9a-8\xedi8\x1bD4k[\x00\xda9L}H\x83Wt-_\xad\xe2\xb2D\xdb{,k\x10\\\xb3\xf2\\\x0d\xa1\xbe\xd5\x16\xbd\xa9\xc3\xa9\xe3\xb7\xea\xfb\x89\xf6}A\xf4\x1av\xa8a3\xd1\x06\x91\xc9\x18\xdd\xc3\x99.\xd7$\x9cH%c\xeduV0K\x8cN\xabm\xf3\xb9\xf2\xd50N\x0f\xea\x8c\xc8*\xee\x8e\xc8 )\x11,\x96\xcd1\x8f&(\x1fsW\xbb\x06\xbf=Pr\x81\xd0\x999M\xd4AwK\xae\x16\xe0k\xee4\xdf*gF.\xedr\xe1\x97i\xa2\xd2x|\x0e\xd9\x14\x97b^\x91!9[\xb0\xb0\x1fb\xf1\x0dY7\xe9\xec\x17\\f\xc7\x1d\xf4~N\xa3\xb0\xba^\x96>Ti\xb1&Q\xbc\x88\xc9\xbc\x9e\x1b\x0e-\x00\xf7;\x9e}\xd7\xf1L\x927\xd6\xdf\x82\xd9t|)\x99 \xefB\xa9\xf6\xd0Z\xe3\xac\xc9\"\xcaW`V^\xd8\xc1.\x83\xcb\xa9\xe75\x0e~\x9a\xed\xb9i\xc9\xba\xfc\xf8\xd2&G\xbfE\x9ah \x7f\xd2\xe5\xca'5\xea\xab\xfb\xb4y\x17\x16\x17r\x82\xde\xb8\xaa}\x92\xb7,\"\xdcD4\xdb\xf6\x91\xed\x84\x92=\xa0J\x813)\xb9\xadG\xbf\xcd2\xe8!\xdct\x1d\xe9\x8d\x83\x0c|\xee\x92@\x0c\x89\x92\xfc\xcd/$\x87}\xfd\xfa2\xae@\xbb\xd2\"\xcaaS\xc4\xc2\x06\x11\x91\x9aOn\xe0\x14fZ\x91\x0f\xe4\xc2X\x91\xf8\xa6\xcet\xb0J\xbb\xbb\x0d\xf3\x94\xcc\x81\xa5\x0b8\xa5\xc8\xbb\x85ZP\xdbjD\x9b\xc7\x06D\x84\xddT\"\xf6\xb0\xde\x1d\xb7)x\x0e\x15vi\x19\x0dsa\x88\xb2\xb4\xc8\x12\xc2\x80\xbf\xeb\xb8i6'\x1e\xd0*\x18>s\x9d\x15E|\x95\x10P\xc8\x84\x15Ye\xf9\x1d$$\xfc\x0csR\x92\xa8$\xf3\x00\xfeu\x0eI=\xeap>\xa7e?\x17\x04\x08\xfbJ\xc7\xf6\xae\x07e\x06q\x1a\xe5\x84\x02\x9b$^\xc5e\xe0\xb4\xb6\xb4\x89\x93j\xa4\xbf\xc4\xf8\xcb<\x8c\x90\x08U\n\\\x91\x0e\xc9v\x932\x14i\x98\xaf\x96^\xb3?\xf9\xf67\xbaY\x82\xc2\xa7(Hy!\xd1\x95&dS25\xd2*\xbb!b\x0et\x98\xb1\xc7\xe3\xbb#\xc2\xa3\x9bNT\xf0#\xa0Y+\x82\x92\xfcKXi57\x10o\x00\xf6\xc9\x96#\xeeYkud}kyS\xfb\x7fQB\xe9w\x81`\xd8\x8c\x0e\xbf\xf4\xcb\xdb\x11w5^\xb0\xfbl$$j\x0c\x901a\x1a\xddQ\xa1s\xcc\xddT\x02k\x94\xea\x97V\xf5\x14\x83\xbdr\xd9T\x0b\x16)\x90T[Q\x15\x98\xaa/\x19<\xd5\xe3-\xab\xb8\xd0p\xa4jlX\x9d@\xb8\xb3C!\x8e!&\x0d\xf0\xc5Hg\xe1E3K\xfa\xab\x99\x17\x9d\xa5R\xc0'\xda\xeeS\xf5\xdf\xc4\xfe\xab\xf6\"I\x86\xf1Vf]{\xebz\xf4\\\x85\xad\x8e97!\xecYf\x1c\xddm\xf3Lg\xf4Q \xa0\xe3\xdc\xed\xed\xce{\xd1\x1e\x92\xb97\xebA'\xe8D\xaf\xccX\xdf\x1en8 \xb6\xb0\xbd\xd0nGLs\xdb'z'\xda\xf9\xc1\xe5\xd0`+\x18y\x9a\xdc\xc2\xd3X0\x83\x1e\xee\xbe Oi\xa1\x8bO\xea\xbbqbotV\xdf\x99\x1dh\xf1\x1d|%\xba\xb6\xd1v\xa8\x93Ag\xd9D\x96\xb6i$\x16'I\xbf\xc6g-\xe2\xcf@\xf9 \x1a\x1f\x8eav\xd17\xd6\x97Y\x95v\x0b\x04tv\xdf\xa6\x1e!\xed\x8dm\x9f\xb3\xc68\x83/\x83!u&z\xee\xd4\x15\x84\x05j?\xbc\xd1\xb8\x11\xfb\x0c;\xc2\x85\xa9_\xf5\x0b 5q.\xcf\xc5!{\xbeO\x0e\x9fz^p^\xe6$\\q\xd7\xdd\xe0# \xe7\xe1\x15Z(\xe0\xef?s\xbfg\xf6\xc1\xe4)\xfa\x86\xfcX\xad\x13\xf2\x85\xa9C1MLP;\xf9\xb1zGS,\xfd\x10\x16\xc5\xa7e\x9eU\xd7K\xa6\xfb\xd8?\x1c\xa4\x83\xed\x0d\xd1d\x0ett#\x92\x99\xb9\x18\x07MyW\x93\x7f\x06\x95?h\xc7\xc4$$\x89\x0b\x8c\xb4\x02\xc2o\x83!\xa1\xb4\xcc\xef\xd4\xa2E\x9c\xc6\xc5\xb2\xcf\xc7\x87>[\x9dK\xa0?\xb5\x96\x8fujG\xed\xa52*{=\x0e\x93r\xa3NQ~\x84\xd6%\x0fD8({\xa3\x80\xfa\xdd5I\xe7qz\x1d]\xed\xecP6\x8f't\x81\x1cW\xd0\xfam\x9b\xf2\x10\x0f \xa2,\xffL\xe6\xdcc\xb5x\x9d\xa3]\xac\xa9XlRIy\\\xd3g\xa7\x86\x00\xa8\xf4y@\xb5\xb7\xc1V\xa8\xe3r\xcb\xb7i\xd5fCB\xee\xe4N\x82\xab<\xbb-\x18\xf12sn\xc6\xc1d\xec\xf8@\xff8\n\x9c\x8b:\xfaW\x13\x0f\x8cA\xc9\xb1\x0f\xfb\x1e\x8f!\xcd\xbci\xb2:\xda\x8f\xda\xdb\xaa\xbe\xa6\xe7e\x88Z\xd9\xeb\xf6pP\xc8\xe2\xee\xeby\x04\xa3 N\x97$\x8f9L\xd8\xd5\xd36\x08\xb1\xa3\xf9\x90\xcc\xc9:'QX\x92c\xbc\xdeO\x0d\x0b\xd8V\x85'\x1c\xfa\xe8z%\xfa\xac\x99\xc6i\xec\xf1\x906\xed\x1aK4\x81h\xf2\xa6(\xde[\x1e\xfcfH\x0c0\xf7\xe1\x86\xf7i\x07\x0cw\xf8\xb1\xe5\xe5\xb5\x114\x03\x97\xaf\x85H\xb23X\xc8N\x1f\xaaW\xda\xf7D\xdcb\"\x0b~\x0dt:\x82\x12\xa6\xe5x\x9b\xcd\xd1\\l\xab\x94\n|\x16V\xd7m\xd7\xd3K(W\xb6\xc5\xfc\xf1\xe8\xf9x_\xbf1PZ\xb5~5X\xc6\xd7\xcb?\x87%\xc9\xdf\x86\xf9\xe7\xf6\x16\xd0'\xc2\x8a\xa2\xdd\x7f\xef\xff`a\x18\xdd\x19L\x0e\xe0\x18&\x07\xbb\x87{\x96UP\x86\x02\\k\xcbh\xd3\x18\xce \x86c\xbe\x16Q\xf3\"\xa2\xe4H\x04\xc7\xb0\xf0\xcd\x8d\xc8\x19\x15[\xef\xbd\x06\x94\x87\xc9\xcb0I\x98\xc0g\xe2\x0b4@\xe6?\xe6a\x9c\xca\x85\x0c\xe2i%\xeaw\x0c3\xa8esR\x94yv\xc7\x0b\xcd;\x92\xe0;\x9e\xe7fN\xa2l\xce\xbd\xablxJ\xa9C?N\xea\xdePB&R\xc1\x00kP-\xbb\xbf\x07\xa7*\x17\x87B\x98$spX@w\\\x9b*\x03\xb3R\x9d\xe2.\x8d\xb8\xb8\x04\x7f_\xe1U\xfe\x90g\x11)\n\xed\xe3,E_\xd1N:O<[\xdd\x94\x92\xfc\xdc41Moe\xd8h>\x9b\xe2\xc9\x99 \xfa.\x8d\xba\xeb1\xf7f\x1cxteG\x87\x94\\\xec\x9f\x95xJ}mE\x07\x0d\x85Q3\x07\xe2\xee\x91\x84\xa4\xbe\xf4\xb7\xe2\x86\xa5?\x0f\x88\x8a\x89g =\xba#G\x8aggGB\xee>\x1a\xe0\xbb\x0dNrc\x1fr\xcf\x97\xb0\x94\xfb\x8as\xe4~k\x1f\x98\xd0\x94 E\x85<\xb5\xe4\\=\xd3_\xd1\xc60f\xbfO\xc5\x1b\xcf\xf3!\x91T\xc5\x83\xf6\xf4R\x05\x8aL\x8en\xdae\"\x1f{\n>\xa4\xbbQ\x89\x9f\x1c\x9e\xa3\xe6@\xc2\x8b\xe8\xbc$V\x8aBN\"0!K*\xc1\xde\xb8\xac\xf7\xe6\x9d\xdc\xcad\xd0l\xae\xa4\xd9\x98&\x91B_\xf4\x03\xf1\x88\xb8\xc6\x1c\x07moc\xf4QA\x0ca\xda\x9b6q\xc4!\xf2\x9c\x969\x06(\xfc\xe0\x96\"\x86\xa5\xc26\xe6n\x03\xbb\x07\xcd\xf3\xd6:vb\xa4?\x0c\xd9\xb4\x04\xcd@t\xd0a\x16\x04\xd5\xdb\x87\xf2y\xa6\x8a\xa0\x98\xcf\xb6~5\xf1o\x84Lv\x82#\x069\x92ln\x89\x02\x02\\\xeao\xe2z\xcd\x98(k$\x05\xe6\nu|\xad\x90\x81\xcd\x82\xad\x1b\xda!\xc7\xa8\xae`&O\x98^\x0e\x95d\x05\x0b\xea\xc6\xa3^\xe0j\xf8\x10\xc2\xe8\xd4$L\xa3\x0f\xc69e\x88\x00\xcd\x7f\xfd\xfa\xf6\xb1\x1bSg4\xf3\xc1q(i\xc1\x10\x80z^F#\xac\xda\x81R\x18IB\xc9\x15\x8bP \xe3c\xcdd)\x8fg\x17\"0<\xc1\xce\xad\x0d\xcf\xb4\xcfz\x17\x05!d\xc4\x9d\xf2\x98\x9a\x8f\x0f\xa2e\x95Z\x18-\xf1\xa0\xb1P \xd29v\xd7M@\xc4\xeb\xe9\x16\xf0\xd0s_\xef\xd0\x04!\x93\xc2\xcd\xc11D\xf5\xa6E>e\xc0\x12\xed8\x98\x17\x8c\xde\xf9\x1a`z\x1b)\xa8\xe8S\xbb\x88\x0b@d?\x0d}2\x1e\x90@\x86\xf2\xado\x81$\xc3\xe0\xf0\x97n\xff(\xc1Abtx%\xab\xb10ld\x85\xfa\xb8\xd0d\xa2\xe1-\xd9O\xbe\x8c\x83\xc6un\x85\x9b%G\xa7\x0d\x0bc\x95Pj\xc0\x1b7A'\xc6SviU\x1aN\"\xda\xeb7\x8e\x05\xf2\xd3\xe7a\x182xe\x9d\x94\x80\xf1_\xbatM\xec\x10\x0d\xe46\xd59\xdd\xdf\x03Q$\x07\x14,Z\x88\x17N\xad T\xd2\x80\x99&{\x18+\\\xd59\xe7\xaa\x90;\x1a\xb8\xa4]\xa8W \xf6\x86\xe6fw\xc8\xd2j\xd3\xa4/\xd9\x94C\xeb\"5\x92EJ\xf2R0p\xad:\x8a\xd4A\xab;e\xe55\x16*\x85\x00I\xbb\x03,\x98\xc8\xec\xe2\x04\xca\x13\x8fN\xa3*\x96,4 \x12\x82t\xd9\xac;\xadyy\xb7\x81d\xaf\x18\xdf\xee\x96J\x1f\xee\xe6\xc4\xfc\xd7\x84\x9b\x93{-{\xac;l:\x8e\xc9\xe5J~0\xcc\xe9\"\xa8%\xae\x9b\x05|\x97U{\xf5\xd2\xbbv\xde\x10\x18\xc7\xe7hL7\x1b+\xc4E#\xf9\xe5\x96JZ\xc5f{)wC\xc2y\xe0\xf8\xe0\xfc\xf8\xea\xc3x<\xde\xb5\xa4F\x83\xf6\x05\xaf\x8b\xed.\xbb\xf8\xda\xb5\xb1\x08\xdc\x13n{\x9b\xff\x15,\xc3\xe2\x0d\xe7\xb7\xc0\xe6\xd3\xf8\x9a\x97IQ\xc7\xda__\xd0\x8bK\xef\xc6\xb0\xda\xbe\xe5,\xac|\xc3\xc8:\xdc\xef\xfa\xe5I\xb5#\xcc\\66-\x1b~\x93\xde\xf6\x15\xf0T\xcd\xdb-\xc9\x8a\xcc\x8f^\xf7a\xcb\x07\x84B\xf3^\xf1]\xedG*5^\xb6\x94\xf2>\xac$\x10\xb1\x8e\xd7\xa4\x0f:0 \x80\x8ah\x9a\x1c\x8a/\xc34\xcdJ\xa0\x0d\xf9\x18\xa7>\xe7\xeaM\x9d\x15\xd1zn\x8b$\xed\x1a:$\xebY\xe4Y\x03cn&\xbb*\xc6\x1e\x19\xdfa\x80\xe4X\xa6\xab\xea\x84\xfb>\xac\x9b\\\xce9nh./\xe8\xd2\x8e\xd2B$\x0d\xd6J*h\x91\xd9|\xf0\x91Zc>\x01\xdd\xfb\x13\x80\xe7\x10\xb4\\A6\x81T\n\x0eM\xa90\xca\x17\xb0\xf0\xd3\x02\x00Rj\x1b\xd1%sr\xd5$\xd3j\xeb[R\xf0}\xd1\xfa\x9d\xe7C\xcc\xe5\xeeg\xc3p\xb7\xa0\x06\xa4#\xc3\xb6>\\\x94$\x07\x92\xcem\xc1*L\xd4\x8d\x84\xa2\xf1\xb0\x98V \xefb\xca\xc3^\xeb\x9c\xb7\x9dK\x07I=c\nZ\"\x9e\xca\xa2H\x00\x89\xb8iH\xe53\xe6\xa9\xa8\x06\xe8\x7f\x1b\xde\xe1Ua\x0b\x81\xb5\x11\xf4\x14PfP\xa0\xb1\x80cM\xd6\xdf\x04\x05a= 9\xa4\xaa\xa3\\C\x9f\"\xd7i\x9a\xa5;\xac\xd9'\x1c\xd3 \x9f\x83\xc1\xbf\xb9A\xae\xb6\xee\x95\xba\xee9+\x89\x05\x1f\x1a[\xf7 f2S\xe6\xe6\xe7\xc6*\x01V\x19\xee~-\x0d\xb2\xed\x0f\xdaq\xf5*\xf1MM\xf7!\xf0R\xd7\xe8\x19\xd5A`\x8e\xdd\xdf\xdc)~}\xb1\xc7\x1e\xe9\xb4\x91<\x92\x9f\x87\xda\x08\xc3\xdeP\x8e\x06_U}A)\x11\x19K\x17\x9e\x99\x05T\x16\x8co\xbd\x03!J9Z|g\xde\x99Y\xaa\x16[\x8d\xac\x86\x91\xb4\xed\x02$ \xd73 \xaaf\xd0\xfc\x1d3\xdd\xd7d_c\xcb\xba\xa0\x05Q-\x18\xc4\xeb\xc1\x04\x0c}\xe7&b#k\xb3\xb5\x1d\xfa\n\x0b\x17\xdc}\xd8\xf0\xc6\x1d\x83A\xf3.?B\xacp\x0cq\x8f\xaa\x8c\"\x1cc\x1c~\xf9\x11\x92\x07c\xee\x05\xf9\xa17\x9d9;\xdb\x8f&\x0b\xd2\x1f Q\x8ey\x19\x8e\x8dL\xbe\xb1\xaeU\xc83:\x85\x89\xf9\xf02I\x8f,) \x1b\xf8\xd1 \x9e\x8b.\x88\x152\xce\x0f/\xb0/\x85\x82\x836 CO\xd5 \xe2I#\xdc\xd9i\x1c\x8d\xba\xda\xae\xd2!\xad+<\x9b\xda\x8bA\xa7!4a\x0c\xc8\xb3\x1f;;\xbe\xa4\x15\xa5\xe4\xab\xa4/\x93\xa4\x1e\xf8\xcb\xa8=k\x0bL\x98\xf6\x8c\x93\xc4\x9dD`A\xca\x1f[\x1a\xf3nZ)\xb6\xa5A\x14\xa4V\x19\x94\xd9O\xd9-\xc9_\x86\x05\xf3\xb0\xd8rg\xce\x92|\xa1\xdc\x11\xd7\xbb\xd3\x7fw\xf0\x8f\xb0\x88\xe2\x98\xfeq\x15\xa7a~\x87\x7f\x85\x059\xd8\xc3ZQ1\xe5\xff\xeeL\xf9g\x93\x83\x84\x88\x16\xc4\xdfyx+\x19\x19\xb9,\xd3\xa2\xa7\x8d\x03\xad\x8cp0\xb59\xe2\x90\xbbm\x8d[\xc1,\xae\x9bt5\x12{@ \xccM\x98 )\x10\xf7\xf6\xb6\x1c\x98\x8e\xb1\xb8\xb5\x8eZ\xc8\xbcr\x19\xde\xe4\x8d \x8bP\x1e3\x10\x8774\x17\xb2Y\xcan)@g\xc8J\x01\"\xe2\xc6>h\\\x0b7\xfdZX]\xb7y&\xd3\xb2)\xd3\x04fiDj\xa1[\x07\xe9F\x1a\x93\xa3\xb1/\x99f\xb5E\xd4 !\x95\xbc\xc5\xa8\x0c\xbc\x82\xb5\xe9\x92\xf1\xdamt\xad\xe4\xdd2\xa8\xb6k\x0bt\x1d\xa0\xf0\x01\xb4\xe7\xd6\xbe\xe6\x852\x1e+\x9fk\xe9\xde\xed\xec\x9f\x9e\xe1~1\x89z\xd3\x1a%\xf7\x8d\xf8[\xbb\xa6U*\xd7\xa9\x7fi\xb5\x9a:\xbd\xfc.\x93\x94\xa4s\xd7\xf3\x81\xb4\"8\xfd\xa1\x19\xa9\x9a\x9b\x11\xb3\xe8\x1f\x8d=\x8a\x0e\xdf\xacVd\x1e\x87%\xd9$\xb5~\x7f\x0e6\xfb\xbe\xf0\x03\xd2\x1b=\xe2\x9b\x0c#u\xf7\x0e\xf7<\xd7\x833\xee\xbf\x8c\xc9\x13\xd1\xb0\xf5p\xff+\xa6z\xd3\x84o>2\x87R\x99\x9a\xd3\xc2\xed\xea\xc1\xc3*\x83k5G\xec\xedPC\xfc\x1275\xb5h\xee\xca\x07\x850\x8a\x0c\xaf\n\xf5M\xf4Uy\x02n\xea\x90\x0d\x0b\x1f4k\xf4\xb8\x95=\xa5\xb2\xf8V\xaa\xdf\xa1B \xc5\x00\xb6\xcc\x1b\xd8k\xfc\\\x17Z\x84\x05\x86#h)\x0bo\xb1\x10Y\n\x16\xf0\xfc\x14\xb3\x14D\xee\x82\xa7\xfc^\xc6\x8d\x93\xd3\x0eDn\xe1.<\xef\x04X\xe4-\x18\x8d\x0c\xea(\xb4\xf3\x91\xa5\xac<\xccP\xc2Q\xe3\x8c\\\xf8\x90\xbb\x89\x94\x02E\xc3\x8f\xbc\xb47\xd3\xfc\xa0\x93\xa6xH\xb4\xb0\x91\x10Tj\x03\x18F\xd4\x9aDo\x96\x14\x8fHa\n\xc2\xc4\xeeA\n\x12]\xa5\xbcx`R\x82\xeeA5\x07\x8b\xd6\xad\xf3\x8b\xb0P\xcc\x9f\xc8\x97\xf2]6'\xaec\xcb\x99\x92ah\x01\xdbx\xb4\xb0\xb8]\x029\x0b\xfb\xcd\x1d\x858\x82g\xcau\x16#\x9bX\xf1w\xb7u\xa1\x90.\xb1!v0\xfdp\xaai\xe5\xc4c\x96\xa8\xa0\xcb\x9aJNY\xe4\xb8i\xe3\xc3\x08u\xfa?V\x1f1x\xe9Zf\x86\x176\x0e\xe6a\x19b\x98\xc2S\x18\x8d2\xf8W\x982s\x07l-(\x96\xf1\xa2t1\x04\x05\x17\xbf\x08\xafkN\xe1\x95\x06m\xd5\x83\x17dW\x05\xc9o\xd0R\xca\xbcx\xd12\xcc\xc3\xa8$\xf9\x8fa\x19\xb6\x82\xfe\xb3V,\x16\xeb\xbd\xf4\x02}X\x9a\x17\x0cai&X\x99\x94{F|(/P\xec\xc0\x15\x94\xa8\xbde\x04\xb0iq\x86\x88\xc5\x1e|3\x1c\xb6^\xe3v\xe4$$p\xec\xaa\xb0&\xc1\xb4\xe4\xf6f\xf6B\xe9\xe8D\xdcO\xdaM\x9d.\xa8C\x8cj\x1c\xca\xdb\xaa\xc4\x84|\xef\xd9\x8e7~\xb1\xb1\xdbze\xbf\x95\xc6\xa6\xffL\xae\xfe#.;:\xb0Th\x1f%\x1bH1\xdf\xa8\xde\xe0\xbb\x80\x8c_\xee\xea\xa2\n\x00\x16\xb8\xd5\xd8lA\xcaO\xf1\x8ad\x15J;\x0c\xdb!U\x182\x80\xa6\xba\xcb\x0e\xfb\xd8<\x98\x96T\xeeA\xba\xb2\x83\xe8\xcaoBeY3h\x9a\xb2f\xaay1\xa7l\\\xfb\xd3}\xfe\xef\xc1\xc6y1;F'\xd2S\x1e\x9a\x92\x8d\xa1\x86\x8f\xa7'P\xc3\x0e\xe7\xdda\x87\xd5X\xe9\x96|WV\xc8 \x84t\xed\x0e\x92,\xc2\xc3~\xdcJaF\x9fe\\\x94Y~g~\x99\xadI\xaa\xb2\x7f\x86J\x98\xf2\xab\xb7\xd6\xeb8\xd1+\xd9\xe6\x0b\xe2\x86K\xf1\x82\x9b3\x7f\x8b\xc9\xcal\x89\xfa\xccV\x1cta\xd8wmxr\xc3\x1dFm\xda\xb8\xb4C\xc5\x9b\xd7\xf1\xde\x0c\x82P\xab=Im\x08\x13\xf3\xb0Ih\x15$\x82B\xbb3\x87\xae\x95\xe3\x83\xf3C\x92]\xd1\x7f_g\xf9\x8a\"=\xe7\xc2;\x01\x16\x16\x13\x13\xf3U\x08\xc0]\xcf\x0b\xe6YJ\x90\xc4E\x8dE\x07\x92\x13z\x97\x98\xe5\x10\xb4\x93\x1f!\xc4)_3\xc693;QV2\x0b/\x86`5,\x91\x0d>\xec\x0b\x93;\x8c\xee\xe0P`\xe0\xd0k\xcb\x0b]=\xc9@\xaf;\xbb$\x1eW\xcf\\\x9f\xb8@h\xd6\xe7>\xdc\xf8p\xe7\xc3\xb5\xde|\x81y\x0f}\x98\x1b\xdc\x92W>\\\xfap\xe5\xc3m/\xbb\x08\x82\x83Z\x83\x08\xb6\xfa\xa2\xc6\x05/\x8c\xf1 \xe8#\xc2\x15v2\x00\x18\xef\x8fe\xec1\x87\xe0k*1C\x8a\x8ej\xd0\xacf/\xfbi\xf8\x86R8i\xad\xdd\xea\xfc\xca\xe2\xfce,\xdddD\xc3Gb\x00vmt\xf9\x05\xbd\xa5G\xe0\xc0\x1bq\xa0\xdb\x95\xce\xe1\xb4^[\n&n\xdaU^Y\xd0\xf1\x0bT\xca5\x82\xedV\x85\xf7p\n/f fNz1s\xfe\xed\xdf\xea\x8b\x85E\xe8\xfc\xf1bvcH\x1a\xfd+\x05\x86L\xdfxc\xe00?S\"\x00\xce\xe0\x1c\xce\xe0\xd6uHZ\xe61)\x10\xa2\xfd\n\xf6\xd4uoX2\xb7<\xbc\xc3\xa9\"\xa2z\x11\xf0\xafio\xef\xdb\x14\xd1\x1bD\xc5W\xf4\x96\xb8o\x18\x19\x8e\"\x0e\xcf\xf3P\xea\xae\x8b\ni\xf5+\xa6>G\xcfj\xf7\xca\x87/>%\x11(\xba\xa5<\x85\x89\xed\xb8\xe2\xabT\xd1\xea\x89\x0fK\xcf\xf3\xe1\x9c\xb6\xf0\x1e\xe1\x8c\xd8 \xec1H\xc3\x15\x93\xad\xbf\xe2x\xfc\xd7\x81P\xe6\xbd\xd5\x9f\xcb\xe3n\xf1[L\xf7\x8bW}\xeb\x15\xdb 1\xb4\x178\xb4_=\x1f\xc2\x19\xa1\x94\xc9\xaf\xf4\xaf/\xf4\xaf\xa5\x0f7f\x11\xdf\xcaj4\xc1\xe6t\x8c\x9bHw\xed\xd6\x15\xd3\xb4\xc8\x14(\x988\x86\xbb\xa6\xba)\xd3\x97x\xf8\xae\x1e\x83A\xb1\xe8\x9bl3A\x90\x89\x97\x14\xc2\xad<\xc0\x7f_\xd0\xa9gt\xea\x97>\xacf\x97\xa6\xf0\xa2,|\x91\x1b\x07\x1f`\x04q\xf0\x1a\xbe\x07wM\xbf{\xe5!\xfc]\x99c\x11\xad\xea\xc2A8\xf7FJH9\xb5\xd0\x0f]\xdfC\x1d\xa7\xa7\xd4\xd2\xe4\xda\x08{\x01\xc1\x8d\xba\xb9\xae\x08\xb3:\xcc\xeb4\xd2\x12}7,\xae\x05\xe4\xb5\x17\xbe+ mk\x0c\x1d\xd6\x81`\x1c\x06\xfd`\xa3\x91X\xe2\xd6\x9aF\xd2\xe30n\x1c\x8c\xd5\x1f\xb9+\xce\xca\x10\xf4S\xf7\xc64\x08DV\x1fX\x9a\x1etb\xe5\x93\xb9\x95\xba\x93}\x16\xa54u\xa7G\x9e]B\xccG\xf3\x14\xb6N-\xcaT\x91\xda{\x1e\xdf8\x9e\x0fN\xf8\xf5j\xd4\xa7m \xa1\xce\xdc\x0b\xc2f\xf2\x1b\x92\xfbS35|\xf4?3\xdd\xa2\xaa\xf6\x9bn\x9a\x19\xa8\x95s\x98\xab\xf1\xcc\xf9A\xa6\x93}\xcf\xdd\xd2)uc&\xf9\xbeu\xb1\xc7\xfa\x0cyB\xc76\")\xda @\x813\x163\x8d\xec\xe5\x9a\xb58\x85\xd0\x83\x94\x1e\xde\x8a\xed_\x88K\xb1\xbd\x0d\x11\x13^\xeb\xc1\x0d\xb8\xf3\"i\xc2\xe7\x16'\x1e\xff\x8e\x12p\xb3b4b\xf1}\xdd\xff\xca\xdc\x08[\xbb\xbfoZ3#\x97h\xb3M\xed\xdd\x9f}s\xaa\xe8\xcel\xfe\x95A\x93\xda\xc5\xf7\x06\xd7\xa4\x94\xb2d\xabV\"\x96c]\x8a\xbd\xe3y+\x91\xc5\x9de\x176\xf9\xae\x9ae\x8b\xf33\x8dW\x85\xf2\xf6L\xfd-\xd1x\xc7\xeag\x9c!?\x83J\x97\xe4n\xb8\xf8\x87\xe6\xc5o%\xe4no\xc5?s\x14\xd7\x03\xee\xcbu\xf8?;G\xb1\xf5\xec\x98\x12/\xfd\xcf\xcd\xa5\xdf\xb9\xcd\xbc\xb7\xf6.+\x16\x8b\xee\x04\xb6\xc1\x04\xd5\xb5<\xb6\xee\xd4RO\xd8,\xd1:{\x96:\xe6\x8c\xb7\x9b\xeda\x9f4m\xb2{\xd0N@\xbf\xfb\xf4\x9f \xe8\xa5\xe7\x7f@\x02\xfa}sR\xc4\x01\x19q-\xe7\xbf\xae`\xb3\x9f\xa4}\xf3@\xe6\xcd\xbe\xc7\x14.\x99y\xe6\x82g\x016\xbf\xa5TOhu\x14\xe1c*DJ\x9c\x82ns\x84 \xd6x6s\x8e\x03\x8e\xc1\xc5\x08\xdb\x98D\xf1e6'/J\xb7\xf0\xe4\xee\x9d\xe7\xc3\xdd\x1f\xa4\xa2e\xe7t\xa5\xdd\x91?r\xf8\x15\xc0!\xa4\xee\xde\xc4s\x13\x0f-i\xbb\x1aK\x1a\xd7\xcb\n\x83\xf4\xfa0\x91\xcc\xae\x1f(eI\xf7\xe1&H\xb3\xdb\xde\xd6\xb0\x96\xb5\xa19\x86\xce\x16\x06\x99\x94\xa2\x9c{\x01\x05zS\x1fb\xfcc\x12d\xe9\x8a]68\xa5\xd4\x07\xc6\xcap\xb3`\x9d\x15%\xbf\x85\x08h&\x18\x81i\x11\x84\xf39&\x1a\x94Se\x197Cj\x00\xc9\xbcE\x10\xafh\x8f\xe7Q\x1e\xaf\xcb\x82\x8e\xac{j\x0by\x0c\xdc\xa1\xdc\x07\xe7{)\xac\x17\x85\x94\xad\x11\xb9\x0e\x9f\x90\x83\xe4\xd4\x16\x1b9\xed\xcb\xc9\xd2\x9c\x84\xf3\xbb\xa2\x0cK\x12-\xc3\xf4\x9a [\x1d\xb9N\x81\xa3r\xbcNK\xf5\"\x08\xd7k\x92\xce_.\xe3d\xeeJ_yA\xbb\xe5\xbe3,\x123\xb1\xc6J\x16MY\xdcS\xab2\xb9\xd3\x94Q\xb2\xa0oN\x84bG\x8f\x99>%\xc4\xd7\xfa\xfe\x18\xd6\x1af\xa0\xb0\xfa\x18\x9a\xecC\x9b\xd1)\xf6\xc1\x9a\x95\x0fVy5},\xce\xf5\xf4\xb996{\xee\xa8\xeb\xd8i\xd7\xda\xdb\xb5\xc5\x04\x9bv\xdd\xd7q\xcf\xeamJ\xe9\xb4\x0c29\xa53\x1ed\xed\xa2O\xbe1u\x89]\xe6YH\x14\xe5\x1e\xea\x9bl\x9e\x857<\xb6U\x16,ZQ\xc4\x05!\x8c9\xc5sRd\xc9\x0d\xf10\x9c-F\xb1[\xc5\x05y\xec\xc2\xb4V\x80-\xcc\x9e\x9d\x04\\\xd1\xad\xef'\x00M\xd4\x9f\xd9\x99\xb2\x0en&9\x963O+N\xdemmQ\x02\xcf\xf9H\xae_}Y#h\x8c\x15\x0f\x9bAS\xb6\xdf\xd6\xda5#u\xa7\x87:A\xd7\xb8v(\xf2\xffA]\xca\x12V\xe3*\xeb\x9dq\x03\x84\xa3\xde\xc5\xb5Q\xd7\x88\xa1\x02\xae\x1b\xc6\xa46\x1eW\x8f\xb12J\x16\xb5\xaeX\x85\x84\x9d\xba5\x15\xcf\xfb\xcb\xb2A\xb9yp\x0e#\xc8\x91Y\xce\xba\xf5\xbc\xf4\x90(\x85\x98\xbf\x9dk*}9|\xd4\xa054\xcb\xae\x89\xecr#\xc2\xb5\xf3}\xec[(\x14\x8e\xba\x8a2\x9d\xd8B\xa9\xf0\x80\x84\x14\x97@\x08Q\x12\x16\x05\x84\x85\xe2%\xfb\xbbLG\x93\xd2\x0bO\xa4\xc9\xbe\xe9\xc4|{W$\xe3Z\xb6\xc8\n\xfe\x02J\xab^\xbc&oS\x96\x1a<\xc5\x18]\\\x9d\x03\xe9h\xd4E\xe8\xe7h\x89\x92Z\x08\xfd\"\xd2\x84\xac\xa0s\x01\x0f\xad\xaeB\xf6\x89\xe4\x95\xbd\x95\x07\x0b\xce\x97\xb1\x80J\xe5\x8c\\l\xb8_\x8f\x03%8WJY\x1d\xea\x1a\xdf\x98\xbf\xda\x1dO\xf5W\x19\x7fE\xe1\x8f\x9c\x86\xb0F|\x86\xdc\xa4\xb5\x89 \x0b\xd4,\x83\xa5\xb2\x1b,iA5\xfe\xd0\xfek#\xf8d\xb9\xea\";\xc1\x163\xc27\x12=\xe7\x14:\x01\xf9\xb2\xceIQ`\xd6\xa4\xaa(\x81\xc4\xe5\x92\xe4p\xc5c\xccf\xb9D\x05\xb1`\xcd\x0e\x8c6\x86J\x1a\xb8\x935s\xccc6\x96\xaa3\x8eJ\xc2\x8d\xed\xe5\x94\xd8-\xd3jC\xa7\xf5\x0d\x0c\x08@\x07\xaa\x91\x96\x85\x95\xd5\xcc\xbd\x0c1,\xd4\xdd\xc6\xfb\xc8\xa8\x11\xb1\xc7g8\xfd\\\xa1CD\xb2\xa1K\\\x83\xcbKJ!}\x93\xfb\xa3\x1aX\xef\x8e\xbfM\xfc\xa4\x03\x93}`\xea\xee\x99\xedz'-\xc5\x12zMS\xe09f\xe1\x07\x0e&\x9eb\x906e\xe5\xbb\xe3\x03\xe3\xf5\x0cMc\x06a\x97\xb6\xce\xb3u\xd1\x845\xa4\x98\xaa\xe4\x01HyIN\x16\x05K\x0d\xc5B\xcc\xad\xe7a\x89\xf9\x0f0Nr&\xad{\xbb\xef\xe2\xef\xd8w\xa4\xba\xdd\x87r\xf4\xa9\xe2# \xa3\xf2e\xb6Zg)\xc1\xbc7\xbf=\xf8J\x95\x82\x94\"EY'\x90\x91\x88\x11%n\xa69\xf4\x90\x04x\xd8\x8f\xdcu\x0e\xf7\xeb\xec\xef|~\x01I\xffZ\x91\x8a\x9c\xf31\xd4V\x15\xbe\x94\x87^\xab\xfb\x92\x87\xa2\x15\x11\x9d|p\xc4\x14T\x01\xa7<\xc9E\x96G\xe4gl\xa8[\xb6f\xe8\xf0u\xf3\xad\x906\x96\x03\x07W\xfa\xe0H]\xab\xe3\x8b\x14\xd8\x17\xcap\xaeP^Qp\x1d)\x85\xaa\x94 \n\x1fb\xb7\x90\x1b\x90Z\xf3\xd4/\xe3\xe2C\x95\x93\xd6\xa9\xe0 D,\x8cB]\xf3\x18B\xf5\xca\xd2\xc6\xa4\xb7\xc5\xb7\x00N\xa9{ ;\xaf\x0b\xf8\xa2\xe1\xbc\xe2mV\xa5%\x99\xf7\xc5\x0d\x14\x14\xb5fc\xa9NC\xdb\xbe6ae\xae/\x1d\x0dm\x18\xe6\xfa\x1f\xc9: #\x16\xa0ph\x1f\xe2n\x18\xea7\x8bm\x86\xec\xf9\xe3\xf7@,\xba\x1c\xac\xfe\x1b7\xfd\xdb\xb7\x1f\xb5\xfd\x04GU\x9e\xe3 \xdd\xdcu\xa2{\x16\xc3\xb2\x9a,\x98#H\xf3\xcburz\x05\x03\xc2\xd4\xf8\x0e\xfa\xdb\x1c\x8c'\xe3\xdd\xdfuQ\x9c\xf3W/?\xbe\xfat\xf9\xe3\xfb\xcbw\xef?]~xq~~\xf9\xe9\xdf\xdf\x9c_\xbe\xffx\xf9\x97\xf7?_\xfe\xf9\xcdO?]\xfe\xf0\xea\xf2\xf5\x9b\x8f\xaf~t\x86\xf4\xa9Q\x12\xd3\x897L*\xd1\x17!\xafu\x97\xcd~z\x14\xfc7T\xb7\xd1I\x8f\xd3\x7f\xba17\xa6\xbb\xba&\x14\n\xae\xb2\xf4\xd5\x97\x92\xa4\x94\xf8-0\xca\xf85)\xb5\x12RD\xe1\x9a\xfcH\xc8\xfa\xa78\xfd\xfc!\xc4\xa4\xcb\x84;\xbb\xb5\x8a\x8be\x98$\xd9\xed\xab\xbfVa\xf2\x1f\xe4\xae\xe0i\x05\xe3d.\x82\xbe\xb0jY^\xb2\xccz$\xb8*3^H\xf28L\xe2\xbf\x91s\x12\xe6\x11ko\x1d\xe6\x85\xfc\xfb\x9a\x94\xe7\xe1j\x9d\x90\xf3hIV\xec;L\xd1\x10\x96\xe4C\x98\x87+\xad\xa4,I\x9e*eo\xe3\xf4'\x91;Z*\x0d\xbf\x18J\xffX\xc5s\xa5\xe0\xc7\xb0$\x9f\xe2\x15Q\n\x99%\x8cR\xf4C\x96%$T;~\x1d'\xeawo\xd2\x92\\#\xad\xd3\x94\xbd\xabVWZ\xd1\xdb8\x8dW\xd5J\x1fn]Fi\xac\x97K\x12}\xe6\xdf\xad\xc8*\x8b\xff\xc6\xba\x8a\x8b7\xabU%\x84~\xa6\xd0>\xe2:_Q\xd6p\xfa\xd4d\xbd\x1e\xd7\xaf\x8fL\xaf3\xfe\xfap\xcf\xf4\xb6\x12\x1f\xef\xee\x9a^\x87\xf5kc\xd7\x05\x7f\xcd9S\xf9\x15\x9d\xdc\xff=\x7f\xff\x8e\xeb\x00\xfa\xec\x19\xec\x9eK\xc2*\x816\xc6\xce\x9b1\xb9-p~\x93\x85\xa4kb\x97\x0d\x11P\x15*+X+\xc6Z\x9d\xf4\xa4\x93\xb2\xa1\xf4:\xedD\xbc\xb8\xeb] \xde\xc8+\x17C\xd6|qy\xe4\x9a2\xfb\xbf\xe7.\xb2]\xaa\xdfj\xdd\xc3\xff\xcf\xde\x9fw\xb7\x8d#\x0f\xa3\xf0\xff\xcf\xa7(\xeb\xc9/C\xb6i\xc5r\x96N\x9c(\x9et\xe2\xa4\xdd\xd9z\xb2\xf42\x8a\xc6\x87\x96 \x8b\x1d\x89TH\xd0\xb62\xf2\xfb\xd9\xdf\x83\x02@\x82$\x00\x82\x8e\xbbg~\xf7^\x9e\xd3\x1d\x8b\x0b\x96B\xa1P{\x85i\x1a\xae;t@E\xb3\xe8\xd8\xaa\xfe\x8d\xbd\xbc\xf70@v4nv4K\x93\xe5O\xef\xdf\xa6S\x92\x125\xef7PO\xab|g\xabr\xe1\x11c*S(VN\xb1\x84,\xe5\x92\xf4\xd9\xbe\xb4}Z\xc0\x8b\x94\x19x\xa3\x8c\xcf\x04oM\x8a\xa6\xde\x93/\x1e\xf1\xfb\xcbp\xe5Q\xccd\x1fe\x14g[\xbe\"\xa6\xf5:\\\x95oB#\xc6 +;D\xf1\xf4C\xe2$\xa2\x80b\x16\xab\x1b\xb8\xa0jV\x0d\x159\xdb\xef\xcf\xa2\x05%J<\xa3\xb1 \x91hA\xefD\xa3\x8d\xf9\xf3\xd9i\x7f\x18N\xe6e\xeb\xc6\x1c\x01\xd2*0J\xc7h\x0dM\xc78{O\xe4^\xd7X#\x9a%\xfe\x18\xc8\xe2$]\xe2 \xc2qn\x08\xef\x03\xa4\x13\xcfcW\xa4m\xc9\xe8\\\xf4\x14e\x05\xdd9\x14}\xe4X\xfd\xf8\x9a{\x91\x13qj\xb6\x8a\x9bu\x97\x10A%^\x87+\x17t2\xa2LJ\xa6\xf9D)\xf2g\xcb\xfdP]W\xe2\xb1\x95\xe5\xa6\x9df&\xd8\xcb\xa0\x12\xd1\x08\xca\x90\xdfa\x97\x7f\xd9\xa8\xcfD=\xabr\xbc\x06\xcb\x9cP\xf7Z\x0f\x84\xa8\xed@\x88D\xa5\xa7\xdd\x00\xf2\xf2n\x1c@\xd4 L\xd9:\xa3d\xf9a\x9e\xc7\x9f_G\xd3\xe9\x82\x9c\x87\xa9]\xe4\x07\x9d\xe5\xce\x04\x13\xd2\x9fJ\xf7I\xc1\x85\xe9K*@\x97Fu/7\xf4H\x86\x0f\x8cyKc\x8fz\xe8\xbfE\x9c$\x8b\xe9\xc3\x1e/_\x8f\xff\xa9\xaf\xe2\xbd\xf1h\x05\x07\xb8v\xb7\xe1\x00\xf6`\x1f!|\x0f\x0e\xe0\x8e\xf8\x9b\xdd\xbf\x0d\xfb\xb0}\xeb_^\xe8\x9dd4\x0d't\xb3\x88\xc2l\x13O7\xd2y{\xc3\xf6\xec&\xf3\x96\x9b\x8c\xa4\xd4?\xd8\xe44\xf17'^\x98\x91\x0d9\x8d\xe2M\x92,<\x12\xc6\xfe\xc1&%\xe1\xe7\xcd\x9a\x12\x7f3\xc1\xc7\xec\xc0\xd9\xcc\xc3t\x83\xf2\xedt\xb3\x08\xb3l\xb3Hb\xb2I\x96\xab\xc5&\x893\xbaIb\x1a\xc59\xf17S\xe2\x9d\xe4\xa7\xa7$\xddL\xa2e\xb8\xd8L\x16aJ63\x8f\xed\xf1\x0dI\xfd\x83M\x14Gt\xb3\xf0\xc8iH\xc9\x86P\xe2\x1f\xf8\x9bi\xb2\x99&\xf9\xc9\x82l\x887\x99'\x9bEv\x10\xcd6\x8b\x8cx\xd1\xcc?`\xf3\x88\xb3<%\x9b8_n\xceHL7\x17\xde\x84\xac\xe8\x86L6+\x0fS4o\x92\x94\xfa\x1bJ\xbcx\x9amPs\xb2Ic\xdf\xf7Y\xd7\x8b\x05\x9d\xa7I~:\xdf\x84\x8b\x8cl\xb0l\xf9b\xcd\x86r\xc1\xa6\x93\x84\xeck\x8f\x84\x939\x9b}D\x18\xd8\x92\xe5&\x8f'\x1e\xdb\xbdl\x80\xa7\x8b\xe4$\\lN\x13\x9alN\xf30\x9dn\"o\xb6Y\xae<\x8e\x03\xd9F\x19D\xecEt3Y\xe4S\xe2\x1d'\xf1\x84\xf8\x07\x9bE\xc4\xa0\x95\xd3\x8d\x14}6\xd4#\xe9,\x9c\x90\x0dI\xe3p\xe1\x1f\xf8\x07\x9b\xcc\xdf,\xbcpy2\x0d7\x84n\x92\xc9\xe7M\x12\x9f\xfa\x9b\xa5\x17M\xd2\x04I\xe0\x06\xf5L\x1b\xaeK\xf07o\xc27\x9b\xd8\x0b\x97$[\xb1\x96B\x1a\x9d\x91\x0d\xb9\xa0\x1br\xbe\x89\x16\x9b\x84n\xf2\xc5\xc2\xdf$\x1e\xb2E\x9b\x15\x8f\xaf\xdc\xa4\x9b\x9cn\xceH\x9aFS\xe2oV^8\xf9\x1c\x9e\x92M\x98\x86\xcbl\x93Fgl]\xd2\x84\x92 %\x0c\x104\x99$\x8bM~\xb2\x88&\xfe&\xf5\xc2\x88a\x8c\x17N\x93x\xb1f\x0b7\xdb\x9cF\x19%\xe9fEB\xba\xf9\x92Gi9\xefl\x92\x93\x0d\xd7\xb3mh\xba\xde0\xaa\xe8\xfb\x9b\xcc;Y\xb3\xc5\x0f\x17d\xba!\x8b\xd9f\x9e\xa4t\x13\x9d\xc6d\xba\x89\xbe\"xB\x1aM6\xa8\xd3\xd9\xa0\xa9a\x93\x9fp\x97\x84M\xbe\"\xe9f\x1dO\xe6i\x12G_\xc9t\x83\xb1\xc4>\x83\xe8r\xb5`\x83\x9f\x93x3\x8f\xb2\xcd\xf7|L\xd1\xce\x06\x87\x11^\xf3z\x8a\xf6\xcc)E\xfb\x14\xab\xfc\xa2AB\xefGR\xbc\xdc\xf4\x86\x99\x06Pw\x06\xae_X\x8b\x8c1\xa6\xd6\xb7N\xf1\xadA\xcb[K\xc6\xd3z\xa7\x01\xc4\"\x83\xc9\x00K\xede\x84za\x00k[\x81\xe2&*H\xa1c\xc9\x84\x8e\\: .1\x19\n\x0fq[\xea\xb9A\x0d\xb1hMU\xdb(\x9a([0\x11\xa7\xc2\x9b\x8d{\x87\x95\x84\xbe$U\xa3\x81\x86\xb8H%\\\xa3\x08J\x80\xf6\xb5l\x12.\x9e\x86\x19\x1b\xd6\x93\xea\x9d\xe7b\x90\xad\xa0\x91\xeaG\x8f\xf6Sn\xe8\xf7n}\xea\x8f\xfe\xd5\xbf5\xfe\xee\xc6-&J4K\x7f\x92~\x16\xc6\x11\x8d\xbe\x92\x8f\xe9\xa2\xb5\x87H\xad_\xabz\xdb0a\xadW\x8b7\xd2\xc9\xd6\x8abp\xa6\xf6\xeck\x8f\xe0SB\x9fL\x18\x97\xcf\xb0%M\x16\x8b(>}G\xb2U\x12g\xed\xd0\xa8\x9dd\xa5\xc2\xbf\x1fe\x8a\xf6_Q\x87\xb0\xa51i\x0c\xaa\xc7\x9e\xfe\xcdR\xbf4\x8b\xe2\xa9\xd7\xaa\xac\x91Wq\xc2e4Li\xf6kD\xe7^o\xafW\xe8#U\x15*\x83\x89\xd7\x9b\xf0\xdd\xc3\xad\xf6\xff\xbe\xf4K,lz\xfe\x01\x98+X\x15\xaa\x1d\xaf'\xba\xe8\x89\xc4\x9b\x1a;\x89\xa1\x8d\x14\x9d\xe64\xe3\xd27\xe2\x17\xca7a\xea*\xb3\xa4\xc5\"O\xa2Y+\xc7\x9aM\x9bx2%d\xb5X\xbf\xa7i\xb4zI\xd65~\xcd\x927\xecZX\xaab\x99[\x94\x81:\xa7L=\xb6ut\xbb\xafZ51\x99N]K\xb7\xd9\xa8\xe4\x8f\xf1q\xb1\xcd\xd4&5\xef5e\xf8\xbf\x19\xb05d\xb1\x86\xa3\x91\xc6\xe4dVh\xe3\x98b\xee\xa1\x17a=D\xd4*\x8a\xc8mv\x87 5<\xa1\x0c\x15o\xe8\xd3V_\x9aU\x90\x91\x86\xec!\x15s\xb1\xa3F\x86\xa2\xdd\xa6\x94\xe2\x80^)\x0c\xb9A-\xeb\xcdp\xddp\xa6\x18\xad\x16\xb4m\xc1)\xb7Z\x94\xd5\x8dMn\xf5P%\xbeU7_n\xdf\xd3T\x94+\x98\x9d6\x83d\x91o\xb1\xd9\x84iM\x18L\xc4g\x1a\xd2\x1f\xa3\x03\xc6\x87\xa4p\xeapX#\xfe\x8da\x8d\x94\xde\x8chR3\xfdU\xdfc\x9bb\"\xfd \xee5\xfc\xfa\xa1\xc8\xbaq\xfbN=<\x05D\xee\x0d\xf4\xb0\xb83\xd0}\xba\x92-\x7f\xbf\xab{\xaa\x0f\x89\xaf\x16_e\x0f\xcf*\x07\x89\n-\xa3\x05\x19\xb3\x16\xf4\xa3\x18\xf5\xe3\x99\x17\x97\x0c\xb8N\xb7\x02\xaa'\x809:\xd7m\xa3\xc1\x01(\"A\x84A\x13\x11\x16Z5\xf2\\.hm\x8d\x95t\xf1<\xc0C\x9c\xe2\xa7Q\x93\x18p\xfe\xad\x9f%K\xd5s\xa2\x8d\xddd\xbd\xac\x95a\x8eb\xc6[\x8db\x8d\xdd\xeb\xb2\xbe%\x9a'\xdf[\x83\xdfc\xeb\xfe\x80\"\x10\xf01\x94\x02T\xef\x97p\x91\x13\x1e\xe8uB`A\xb2\x0c\xe8<\x8cA\xb4\xdck\x8e\xb1\xb9;\xfe0\xf8gv\x18\xd3#\xf3\x98NQ\xe5\x9e\x8aa\xf1\xc6\x9d\x86\xf5Y\xefI\xda~Z\xa0\xa4y\xeb_;\x07\x9f\xa6\xdb\xde\xa7>\xfb\xc7?\x90\xb6\x01EN\xad\x0d4\x04\xc1\xf8\xb8\x0c\xee\xc8\xe0\xfa\xdamt\x0e\x83\x8a!\xe2\x8d;\x0d\xeb\xb5\xceE\xd7mLx*\xd5\xf2+\xd4\xbc\n\xcd\x90\x9bE\x0b\xe24\xc0\x0f\x06\xbfb\xb71\xf6h\x9a\x13N\x1aD\xccR\xb8\xc8\xd4\x1b[\xbb\xca\xdf\x03\xc9\xca\x9bF}\xc2\xbbw\x1a\xf8S\xbd\x8f\xb4\xdb\xb8\xf9`5\n\x1f\xf3\xd8\xc4\xcb.C\xfb\xd9\xe4\xd3\xed68^\xb1\x9f}V\xb8\x0b[VZ6\xef4\xb2w:\xf7s\xb7QIqO\n\x1b}\x9a\xbcJ\xceI\xfa4\xcc\x88\xe7\x07\xb0u\xeb_\xa3\x7f{\xe3\x83\xd1\xee\xce\x83pg6\xfe\xf7\xfd\xcb\x9d\xe2\xef;\x0e\x7f\x0f\xf6.G\xfe\xe5\xd8\x890\xb0\x91;M\xf8\x8d\xd1\x0b\xdf\x9d\x98\x96\xbc\x89\x1b\x9d\xe7]8\x0d\xef\x951t\xa0\xfb\xf0:\x90\xfc\x0e#|f\x08xp\x1e\xdf\x16O\xebpzx\x81\x1e\xc9\xb6\xa5\x9d%\x8bEr\x0e+\xd1I\x0f\xb6u.\xec\xd53\xbc\x19\x9e\xd1:\xb2\xabr\xb67oV~\x9b\xb9Z\x13\xc7\x8b\xac\x1eR\x9e\x93d\xba\x16je\xae`\x8c\xe2\x1ew\x93\xc7_h\xc8:\xbeX.z\xc7\xd0\xf9LyS\xb0\x1e\x867\x17\xe5\x9b<\xc9\x85\xfe\xb5U\xf9\xda,I\x97!5\xbd8\xaf\x8cQ\xec\x00\xc3\xbb\xd3\xca(\xed\xef\x9e\x95\xef\n\xc4\xad\xa7\x1e\x01\x01G\xeet\x950\xa67\xb2f\xe6\\3\x91\xbdT\xcc\x0d\x01\xbf\x8c\xf4\xfd\x83Pe\xf4B\x99\xe0[\xbc_\x15\x9ay\x82\x97H\x16\xd306u\xackJot\x94MN\x92<\xa6&-:\xbbN0\x9c\x8fq$\xcal\xccl\x8d\xb9!\xd4eH&\xa1l\xcb\x8bx\xa6\".\x96X\x06r\xc1\xbe/\xb5i\x95\xcfw[\xbf\xc6\x94\xf1\x92\xf9\xeb\xfe\xf9\xa1\xc1\xc8\x0e\xd2\x00\xd7\xd0B,\xcc\x9e|V\xed\xaa\x9bdvhp\x08\x90\x17O\xef\xad\xd7\x11G6u\xac\xbc\x94\x80\xa7\xc8\x0fD\x7f\xc6/\xda\xed\xcf\xf2\x92\xb4\x88\x1b\xb8{H\xf7 ;\xde\xf88y\\bq\xf6\xe1\xf1\x80c\xe9\xf9\x81\xa1\xfc8h\xf5\xb9 \xb6\xe3\x13F\xd2\xd7\x01\x9c\x16\xb5#0\xb5\xfd\xfb\x00\x0e\xc75\xe1\xd5:\xf6R\xdf\xa4}E\xa7\xe6\x07\xb1\xd4 \xf2\xcfe\xf9 9\xf7w\x82\xd6\xc3,\"\x8b)D\x19\xe6\x0fY\xa5\xc9Y4\xc5\x13@G\xb1e\xa3g\xb6\xc1\xb2\x89\x7f\x85!<\xf3\xa2\x00\xce,N _\xd1\xc4\xc1\xc7\xf3\xd5\xd5\xd9\x00\xc4\x10\xe6\xe5\xd6\x99\xb7\x8d\xe69\x0c\xe1\x0d\x1b\xcd\xdc2\x9a\xe7\xcah\x9ew\x1d\xcd\xb4m\x08\x1fa\x08\xaf\xd8\x10\xea\xa5E\xd4\xeb\xa32\x84\x8f]\x87\x10\x96\x00 \xdbF\xf3\x03\x0c\xe1-\x1bMh\x19\xcd\x0f\xcah~\xe8:\x9aY9\x9aY\xdbh\xbe\xc0\x10\xfe`\xa3\x99YF\xf3E\x19\xcd\x97\xae\xa3\xa9\x1e\x89m\xe3\xf9\xdd\xe2\xb7$/\xe4n\xbc\xdfQC\x1eR\xb2C\x99\x1c\x85\xcd\xaf\xe0\x00~\xf6P\x85\xd6\xcb\x99\xb0Q\xdc}\xc7\xef>\xe5D\xd4\xcc\x17\xc9K\xcc\xf6w\x93\x1bKIf\xab\x07[\xdb\xfc~\x85!|\xf0\"\x0b\xb0qv\xbfv\x18\xe3\xaf\xedc\xac\x1c\x9emC\xfc\x05\x86\xf0\xb9}\x88\xbft\x18\xe2/\xedC\xac\x9e\xd0mc| C8j\x1f\xe3\xcb\x0ec|\xd9>F\x95\xc1j\x1b\xe1\x8b\x96\xa1\x1d#\xf3S\xb0a.\x03}!y\xd6\xa3\xd8\x1b\xf5\"J\x96Y/\x00\xceg\x8f\xfd\x00\xa2\xa6\xa1\xbb\xcd\xd7\x03\x14\xc1\xaam\xdb\xb1\xab\x82I/\xd0I\x82!\x0b\x06\xabV\x97P><\x12\x0fU*\xf0\x02\x190\xf6\xf4)\x13*\x03ap\xe7\xeb`\x1f,\xbb\xa2xJ.\xf6\xa1\xc5g\x90]$M\x93t_\x13/\xa7^\x97\x96x\xb0v\x9cP\x18\xe46\x94\xb8\x01Cx\xdd\x8e\xb47\\pA\x00\xeb\x86+56\xda\xbd5\xfe+\xcdl\nvNI:\x1a}\xbb\xbb\xb1\xc6\xd2 \xc2/\xa8\xab\xd8\xdf0h\xe9\"\xa0\x19\xbco],\x17BwE\x8c\xf2]\xc4\xbd\xae.\x96\x0b\xdc\xb6\xf8\x17\x166\xb2\xad9\xd7\xf3\xb0o\x98\x94/\xbe\xfd\xf7e\xc0\xbe\xbfq#%3\xd5\x1d`\xbdBO\x18\xda\xc7}\xcd\xff\x14%WD\xb9'\xda\x0f\xa7S\xf4M\x0c\x17?\x97O\x0e\xe0o\x8f\x0eX\xe3g$\xcd\xa2$\x1e\xf6\x06\xfd\xdd\x1e\x90x\x92L\xa3\xf8t\xd8\xfb\xf8\xe1\xf9\xce\xfd\xde\xc1\xe3O\xb1pl\x87\xdf^\xbf\x02r\x81K\x0c\x13\x9e\xe2\xf7\x84\xc0)\x89I\x1aR2\x05\x1e\xa4\xf47\xa3\xff\x93\xbc\xa4!LL\xa7\x8f\xa9\xb1\xbd[\x9f\xde\x7f\xf7\xe9\x96\xf7\xe9\xfd\xb6\x7f\xe3\x96\x05\xd9K \xc2\x10\xa2\xd1\xa0\x19\x8c\x08F\xc6B1\x16\x9eJK\xed\xf4)\xea\xcb~{\xfd\xea\x90\xcf\x8d;\x93\xb8\xf8\x80\xb0\x89$\xc2\xc3\xa8l\x8fo\x82\xe7i\xb2\xe4\x1bA\xb4\xd7\x9c\x91T\x8a\x99$\xbb\xa4M\xb2K\xb0\xbcm\xcd\x13&)=a`_\xc9y\x06Pxi\xaaYP\xac\x8e_g\xa2\x0eI=\xa9\x92\xbc\xd8\x12\x94\xe2\xfc\"\x99\x84\xac\xa9~\x86\x8d\x1b\xf4K\xa5\xde\xd2\xb4\xb5z\xa8\xa47\xee\x11y\xf0\x90~\x96\x9fd4\xf5\x06\xbe\xac\x17tS\xa7\x8d\x01\xd5C=\x85(\x86\xd8\x87\xb8^>%\xe5\x8e\x8a\x18g8J\xc7\xb2\xc5!&[\x1bM\xc9$\x99\x92\x8f\xef\x8e\x8a,]^:\xda\x1d\xfbc,\xdd;@u\xa1\xf6\x9d\xc1\x98\xdbU{.\xf8$\xb7us\xcd\x9a\xd9l\xec\xb4\xd5h\x15_\x86+\x07\x7f6\xf19\x12\x83\xea\x8c\x88\x0f\xdb\xd0\x1b\xa2\xb6\xb6\xf9\xb4\x9a\x99T^\x97~\xff\x8f$\x8aqy\x9aS\x13\x19{\xec\x83\x92\xf3\xa9d\xdd\xa0\"n\x17K\xd5yD1W\x04\xd0\xcb\xe9l\xe7~\xcf\xf7\xcb\xbb\xbd\x930#\xf7\xee\xe8\xc6Pf\x10jv\x9d`\xb8Y\x94\xc4\xd9{|\xcb\xe4\xb5\x13.V\xf3\xb0%\x97\xacz\x154\\j\x13\xe7=\x1f\xb7\xd0\x02S\xc1\x85)\xf1\x88\xfa\xccpd\xeb7\xe6\x92\xd0y2\xbd\xf2h\xf8\xe7\xa6\xf1\xc8\xa7\xceLDs\x8c4<\xfd\xb3\xc0Y\x1b\xb2\xf3 5\x98Y\xcb4\xe5\xc6\xce\xe8\x9cT\x94\x8c\xeeQ\x0cF\xbd\x91\xf4\xe6\xa5F\x0f\x11\x85m\xe1\xa5oz\xe5\xdf\xa2\xcc\xd1(\x0e\xd8\x06\x0dt\xfb3\xf5K\x9f\xfa\xff\xd9\xdb\xbdu\x1a@o\xbb\xe7\x8f\xc5\xfe\xd4-\xa9\x91J\x11\xdb\xa6\xd6d\xee\xaa\xac\xa4\xc1\xb1\xa6P\x9a1\xc25- W\xac8\xe5\xb4\xb9\x8ct\xf2\x18\xa9\x8e\xbc\ns\xa9\x143\xa4's\"\xc0:\x8f[d\xcaT:&\xcc\xd9\x98\xd4(\x8d\x96\x9e\xb2H\x9f2\\\xa3c\xb4\xd8\xf4z\xb6\xe1\x1a\x92\xab9\x0d\x93\xc1\xec\xb8\x84\xd9\xd7\xa6{Y\xa0I\xe7\xe6\xd44m\xe6\x9b\xb0\xecd\xf1\xd1\xad\x7f]\xec\x14\xccu\xeb\xb2\x05\xc6\x14t\x7f\xe6\x08\x85\xfdgS\xd8\x976\x85\xf5h#\xecb\x1ba\xf5r\x9f\xca\xff)\x1f\xf0\x94\xdfl\xa7x\xf7\xee\xfb\xfd\x1f\xf2\xd9\x8c\x08\x7fq[\xf5\xa3\xb3\"sSq\xf2\x95x\xa2\xa6\x19\xacX\x8c\xc0%S|o\xc49U\xfe\xe9\x18\x91:nT\x8cr\xca\x06\x89\x94\xae\x1cWjcD\xf59\x0eAaO\xf9T\x94d\xbc\x8bhBL^\x97\xc4\xb8\xbc<\xa4\xaa\x9aL[\xe4K\xe4\x14@-1\xe1c)+S.\xd9zZr\xfdP\xecx\x99\x97\xbe\xaf/\x9b%\xb9\xf4-\xa6\xd6\x16\xc3\xb2\xc5\x17\xae-F\xd6\x16\xb3\xb2\xc5\x1b\xae-&\xed\xb3\xbey\x13\xb6&e\xd3?\xba6\xadI-\xaf4\xbd\xe5mQ.\x87\x8f\x16c\xb7\x06C\xd7\x06\xeb\x898L\x0df\xae\x0d\xce\x1d\x1b\x9c\xb4\xaf\xf8f\x83\xdd:57s\x1d\xdf\xb41>\xf5\x17\xf1R^\x83\x85x\x91\xfc#\xe1\x7f\xc4\x8a3+\xcf\xd5\xcd\xee\xbc$kL\xcf\x17\x8a\x17\xe2)\xb9\xc0\x1b\x19\xbf\xf1$\xcb\x92I\x84\x99!\x00s\xb8\xc4e\x00\x1c`x~\xdc\x97m\xb0\xae\xfbe\x0bl\x00\xfd\xf7\x04k84\xe9\x07\xa6\x19\xf8\xfb\xdf\x8f\x8f\x8f^\xbf\xfe\xf8\xe1\xc9\x0f\xaf\x0e\x8f\x8f>\x1c\xbe\xc3?\x8e\xff\xfew\x8dji\xd5\xfc\xe2\xe5\xe1\xef\x87\xcf\x0c\xaf\xcf5\x1d\xbcyv\xf8\x9b\xf1\x83i\xf3\x83\xb7\xef\x9e\x1d\xbe3~p\x06C\xb8\xdb\xbc\xbd\x86!\x0c\xe0\xd1#]\xb5\xf3S\x18\xc2\x1av@\x93\xaa\x7fi\x90\xf7\x8f\xed5\xae\xf7\xeb\x89$A\xcf\xf9\x9f\\\xa5\x19\x13-?o9\xd8\xb9q\x18\x0b\xbb;\x92\xe4\x0b}\x8bT\x1c\x0dE\x83\xbbn\xdb\xe9=O*\xaf\x7fxh9\x89D\x84\x9bF\xaf^\xa9\x0e%\x0bH{\x98x\\\xa88w\xb0JH*r\x9e\xcb\x94\x05<\xd3\xc6\xeeCLw\x11?\x84h{\xdb\x87t\x14\xf1$\x89\x11\x13\xe8\xcd\xee\xf5\xa9\xd3l\xed\x01\x0d\xaa;:\x06\xa2\n\x98f<\\\x82\xf6\x8f\x8fy\xe9|\xe2\xfd\xc1OW\xf6\xc4\xa9\xe3\xb7\xd6Tb\x85\xf5A)\xe9a\x13\xc1P\xb9\x04\x8f\x1f?6\x995\x84\x92j\x1bb\x11C\xbd\xd9\xc0\x9d\xbd\x07w\x1e\xdc\xfb~\xef\xc1]\x9ca\x19\x99\xf8&|\xa3o\x85MZ\x93\x92\xcf\x04>\"\xcax#\x90\xb7Q\xf1\xe1\x06\x9c?l\xc5\xf2\xeb\xf9\x9c\x0dm|v\x90\xda<\x19jP\x16\x9d\xde\x92Q\x91\x14\x1e\x0da'\xae\x14,\x1cJ\xd0\xd5_&\xf0xXW\xc0\x9a\x06v\xd4\x96\xbd\xf1\x83\x18\xb9\xe3\x86}\xed\xda^\xbd\xaa\x8f\xa1\xbd\x0f\x0e\x80\xab\xc5i\xc4\x986\x97/\xb6\xba\xbf l\x03\x1a\xc5j\xb1\xb4\x8cC\x92\xe5\xe2\x99\xbc`\xac\xde\n\x02\xbf\x9f6\xabT\x83pd\xd6\x9c\x07\xef`\x08{\xcd\xdbo\x9c\xb3\xb6\xf3M\x9d\xa4\xcd6^\xf1\x93N\xbe\xa09\xda\x9e\xc1\x10\xde0\x1cye:\x02\xbe\x1a\x08\xf6<\xca0\xbb\x8833\xfe\\\xae\x94!\x99\xa7\xb4Z\x94\x0b\xc5\xb6\xe0\xa0\xb2l#\xf6\xbd\x85\x8a\xc2\x01\xa4\xc5\x19\x12\x89\xb2\xc0\xd6\xd3\xd0\xe0\x078Mb\xd3\x89\xebH\xab?\xda\xa8\x82uH\x1c\xfd\xac\xe3j\xad\xdcc\x18\xd4\x0fv\xees\xebWW6\xf6\x8b\x9d1\x00S\xd5h\x8a8\xe3\xd4\xc5\xefv5\xe0\xaf\xda\xf4\x1d\x05-\xe7Un\xb5\xc5\x96\xf5\xdd\xfdj\xef\x8e3(o\x90\xd6\x8e\xde`\xedR:ze\xcaM\xa4\x9d\xbb\x92\xb7\xdaiD\xbf8\xc0X\x13\xcc,\xb8\x14\xa7.^Z\xbb(\x92\x01\xa8G\x8e\xdc\x8e \xcf\x95-\x85\xe8>M0]\x83\xb5\x80\xb5\xbc$P\xd1y\xbd\x12\x167\xac\xd5\xe6!\xe7@\xa85\xc3\xfb\x96\xa9^\xd8\xe1\xc5\n3\xd3q\x06\x0d\x92\x14\")\x15 5K2\xe3[.\x0b\xd8\xd3\xcf(\xdd\xf0G\xfb\xe8.o\xeaV\xbb\x8a\xecj\xa6\x083\xc0\xfd\xc5\xb7\xc1\xbdO\x13\x94\xc5$\xc4\xc5\"\x84\xcd\xb5\xa0\x98\x9f\xfd0\xa6\xe9\xbax\x99\xba\x8e\xf2\xc6\xb7\x8dR30\xa2\x0e\x84\x8dSH\x91\xf2V\xe8<\xb6\x1f\xadc\xf3\xbe}pr4h\xe0\"\x14\xef\xd7F\xa6\xfe\xfa\xaa\xa8\xaa\xa8&\x1f\x81e\xb0\xbd\xd1\x918\xa0\xc75\x05t\x00_\xfb/\x0f\x7f\x7f\x0fCx\xca\xfe\xfe\xe5\xc9\xab\x8f\x87\xec\xd7\xcf\xec\xd7\xe1\x9b\x0f\xef\x8e\xf0\xe7\xbb\xa0\xd2\x7f\x14g+\x9e\xed\xbc6\xaa$O\xab\x99\xb9m\xf4\x85\x1d\xf0\xe6\xdc\x0bJ\xcb\xa3g\xe3\x0em\xd6\x1b\"\xdeK\xae\xb7x\xd9Of\x8e\xed\xbc\xf4\n'\x92\xc6\xc0^V\xa7L\xbe8\xb6\xa9\x1b\xdb\xcb\xab/*\x82\xef\xf8\xb84\x8e\xb2\x91\xfc\xbb\x17@\xef\xb2i\xcfQ\xfb\x99\x84\x939yG\xb2\x962\xc7JW[\xbc/\xfc\x10d\xc5\xafB\xd6\xfb\x18\xe3\x83)\x17\x06\x957\x87\xfc\xc5\x12\xeb\xcb\x8a\x0f\xa2\xfc\x99\x14\x1c\xcb\x8f\xc4\xd9\"^\xb0M\xa3\xe8\xdf%\x86HLdB\xcb\x82d\xbc\x02\xa8K\x0f\x89S\x00\xbe\xe8b\xd6\xda\x05\xf1^\x04\xf0\xd2\x0f\xe0Ee\xf1%\xbdu\\\x13=\xa6\xdf\xe0-\xdfp\xc7\xf4\x1b\x16L\xbfQ\x19`II\x1d\x9b\xd6\x0d\xf1\xc65#\xfc\x88!\xfc\xb8\x89\xf07\xae\x19S\xea\xb5\xdd\xf5=|\x13\xa64\xbb \xde\x8f|=\x7ft_\xcf\x1f-\xeb\xf9c\x8dr\xd1o[\xcb\x97\xfd(\xe3-D\x94\xfd\x92\xda[\x86\xdeB]\xcb\xc6\xaf(ro4\xb5\xb7?\x05\xf0\xcf\x00~\x0b\xe0\x1fM\xa5\xe9\xfb\xc3\x7f\xa0\xc2\xd4$9Rj\x11\x1d\x8fCQ+\x83\xd6\x88M\x17\xf6\x95\x18z\x90\xfc\xa50.}&\xebL\xcbC\xf2\x91$\xb26\x88\x1c\xca\xf1gQ\x0b\xab:4\xd2eh\xb1u\xf2Q\xa9\x9f7\xcc\x9f{\x16:+\xe8\xd2\xf6\xee\x84\xe1,\xa8\xdd{*\x0e\x83zm\x1fCG\x91\xa1#y\x16\x95\x06\x8c\x7f8\x1aX\x90\x1b36\xf8\x13k\xcd\xfbI\xe8Z)\xf5F\xe3Ff\x16}\xbby\x0brh\xd2\xe0\x88.\xa8\xdf\xe4\x9a\xbf\x94o\xa4\xfa7~(\xdf\x88\xf5oh\xa5\x9c\x83R\xc8)TOf\xcf\xbe\xabK:\xa3\xcf\x01\x9c\x8dAd\x8a\xed \xf1t\x92Y\xc3\x16\xa0gza\xee\xdb\xa7\xc7\x05\xb9k\x9aEfG\xf2_j\xd8\xa2A\x0f\x0d>\x14\xab\xeb4\x04v\xc29\xa9\xcb\xa8`\xcd\xf4@\x8dL\"xa\xe5H\xd8\x01QZ6\x06\x01\x864\xef>\x84\x1c\x1e\x0d!y\x08\xf9\xf6\xb6\xa9\x11\x10\xe3\x08\xd1S8f\xa2\x15\xec@\xced+\x83\x7f\x15\xc8\xc5\xe6z=\xe2\x85\xa3\xc18@\xc5]8\xda\x1d\xb3/\x03P\x02\xdas\xd8\x86\xa6\x12\x0e\x1a\xe2\x97\xbc\xe4g\x8d\x87\x96\x04s\x0dV\x99g\x83tZ\xa6\xd9\x9f\xbcL\xda\x152B\x96\xaf\x9c\x0d0\x0c\x1b\xbfzV\x96B^\xd2\xf9\xc3}a%\xf0\xb7\xb7\xe11:W\x9b\x1b\x077u\xa7\xbc\x8cjOy]\xc2>\xc7\xcc\xb9P\x1f\xa9i8s\xfbp\xa4E\xbe\xe2w5\x94r}\x8e\xf4z\xa8\xe9\x93j\xbe,\x03\xb8\x05\xbb\x85?\x8b\xf0{\xf1\x03\x89\xce\xf2C\xdb\xc1\xf6\xcfbh\xff\xd4#\xce?\x85\xcd\xa0e\xab\x99\xa0u\xda\x02-\xaa\xaa \xb8\x8a\xc0\xd1WhIm\xceB\xfa\xa5X\xd6\x96BiC\xbf\x1a\xa7\xd4\x13\xaeV\x01\xf4\x9e\xf2(\xde\x8c\x92\x15\x84\xf0.\x8cO \x9c\xaca\x17\x83\x1eAX'w\x83\xea*\xc9\xba#\xb8V~\xa0$\x01\xe0\x9eo\xa2\x1a#.ax\x92\xa1\xeb!\x81G\x82cco\xef\xc4\xd2\x84s\x8c\xc5\"T\xbd\x1f\x89\xa7\x8aj\xf3\x18\x87\x86\x83U\xb1FE\x0f\xfc{B\xa2\x85\xe7\x11\xd8a\x04\xf8\x16\xc4L\xb4\xf2\x99l\xde\x0dw~+`\xf9\x9b\x1ew~\xfb6\xdc9\xd6\xeb\x129\xbe(*\xa5'\xa2\xfaa\xdd2ah\xf6\x84\xda\xdcL\xcf\xadO/\xc4S\xf5\xa1b\xc6\x1a\xfdc,\n\x01\x11\x8f\xd2\x00n\xb0\x95S\xe3\x1eN\x89SIW\xc9\xb5\xb3U`\xe4\x91\xdb\xb4KM\xfb\xe8\xad4g\xf8c]\x05\xf3J\x9f\x9dL2\x15\x7fY\xa5G\xe1![Q-\x95\x1e\xb2CH\xb9\x8b\xac\x11W\x84\x8a\x88z\xf1\x88Q\xae\x14v\xd0\xa3+\x1a\xa3\xf0\xc7:*wf\xc4P\xd1H\xb5\x1bu\x1d\xb4\x93u\xb3\x0e\xe9&\xaa\x9dBc\xf2\xfa\x89\xea56\xdd\xb45\x05\x10\x1e\xa3\xfa\xc3\xc6\x819i\\\xac\xda\x16\xaei\xa1\\\x02/Wf{\x9b\xad\xcd\xf6\xb6C\x14 CuB\x03x\xc1\xe8\xd6\xd5Q\xbd\xee\xe5\xaaC}\xae\x1f\x1eQ-\xcaW\xfa\x9e\x87\xee\xf1lJ\xd3\xf5(wM}\xa2\xeb\xdcX\xbcS\xbe\xb3JSU \xd8ju\xa7%|\xa7%l\xa7E\x0f!1+q\xcfDY\xbc\x14\x173\x82\x1dH`\x1f\x12\x83\x9e\xaf\xb63\xf31V!\xae\xee\xc6D\xab\xb45\n\xa3\xcd\x14\n\xd7\xb5=\x05\xb8\x8c\xfbS\x01\xa1qw\xa6\xad{8\xb9\x8e=\xdcm\x15$\xe4P\xd3\x1a\xfdu{>g{>w\xdb\xe3\xca\"\x8e\xa6\xe5!\x17\x8bC.\xd6\xee\x8b\xc2[\xc5a\xad\x19*\x96\x121\xaeeEhR\x84\x0c\x03\xf7,\xb1\xe5w\xafj\x96\xb5\xd4\xb02\xe8$\xbex\xb1A\x06-vq\xf4\x10\xb6\xbc\x08O\x05\xb5*#(\xb9\xbc\xbdHT]\x84t{[\xec*]\xfdR1\xe5F\x8e -LK}\xf5\xb5\x025I;C\xd5\xa0\xce\xf9\xa2j\x89\xf9v\xf9hh\xd6\xb0\x02\xdd\xb7\x1aQ\xd6\xa1E\xcb\x81\x8b\xc4\x9d\xd1q\x0f\xe0\xd2\x08\x15\x9e\xd3F\xf0R\x81\xf2\xe9\x7f\x01\xcaW\xea\xc8\x17$\xb0\x08!\xe0\xb6\xaa\xa6\x83\x80z\xa0\x14\xc6\xa8\x87\x0e\xcc[4J\xc6\x01#T\x8dC\xc206\xb6KbEK\xc4w\x89\xb1\xf2\xbc\xa4\x9b\xb1M\x9b\x84&\xb6Q2\xe6\xe1\x90\xc5\xd8\xf2\xea\xc0NR\x12~n.\xa8 \xdb\x1a\xc7\x96vy\xffc\xbb\xaf\xb6\xb0F\x82\xa6[l=\x10\xafc\xef\xe1J\xc0\xe3\xf2XmS\x18\xb6oT\x90p\xe3En\x8b\x8dkQ,\xf2\xa0<\xb1\x87\xb5\xafY\xad\xcb\x92\xfdMG\xee\x0c\xefZ\xd0\x805\xbd\xba\x8b]M\xd0\x86\x03\xe8\xbd#+\x12R\x18\x8d{\xb0_\xfe\xe2^\x10\x8aZh\x1bz\xe5=\xfc\x96\xdd\xa1\xd1\x92d\xd0t:^_\x9d)\xd71\xe1|\x08\x1a\x06\xbc\xd2\x8f\xac\xf4\xe3\xca\x85O\xa9\xaa\xf8jFe\xd5\x9a\xc7\x94\x05.\x13\xa9\xec\x1f\x06*#\xca+1{|\xaa\"U\xd2\xba6\xb2\xd7\xa2\xba\xe4\x0e\x0f\xa6\xab3\n\xf5\x91\xa6\xe4\x8c\xa4Y\x177\xed\x16\xb8N\xc9\xc5\xdb\xd9\xd5\xc1\n\x07\xa81\xdc\x19X\xbbY\x84\x19=\xba\x86\xaeJ\x0cm\xed\xf2\xea\xc2\xd4\xeeC\x88\xe1\x91\xb2\xc4\x10;i\"*\xc3\x8d\xeb'ZlUB\xc4Ns\xe9.\xe5tbU\xbb\x11k\xc9f\xc2#\x88%\xc5)Y\xa0X@\xc27\xd6\xd9\x83\xeb\x12?\x1c(l\x05\x9a\xc2H\xe9\x88\x87\xb4\xaaz\x87\x83&f*S=k\xda\xfb\x19}_\n\xfa\xbe\xbcf\xfa\x8e*cI\xde\xf9\x0f\x85\xbas\xed\xee6\xf4\xfa\xfd~y\x97\xc4S\xd8\x06O\x08\x15\xf3B\xcd{\x00=8YW>'+\xcc{\x84I\xe74'\xc1\xf2zO\x029\xdcR\x17 \xdfU\x87\xd28#\x96W:#$\xe7\xe0Q\xd8Q\xfb\xf6\xe1\x96\xd2\x9fq\x7f`\x80\xf4.7\xc8+d\x82\xdf`k\x84:\xf1\xd9\"\xd1\xd8\x1ejCv>wj\x87J\xd1\xa9r\xb8\xa0K\x01\x9e!\xe5\xd3\x80\xdb\n\xf0\x8c)\xef\xfa\xf0hX\xf8\x96.\xa9\xb7\x1b\xc0\xae/\x8e\xa7\xa5@\xeeSB=\xd5* M\x06\xec>\xd1\xdcG\x905\xcf\xae\xe5U\x0e\x9b\xb3\"\xaa\xb2\xb2B\x0d\x85/\x18\x031.\xc3\x1c\xd4r\x07V\x87\x03\xe1Z\x89N\x96\xece\xeeSa\x19((x\xba\x0b\x1b\x93s\x14\x1e\xa1qY\x8d\xd3\x8b\xe1_C5G\xd1w@\xfd\x87\x0c1\x94\x9b\x0f}\xc0\xd7(\xdcR\xdf\xb5\x12\xdcC\xea9\xa5J\x8f\xea%]\x145b\x99\x9a\xffg\xaax\x99\xeb1\x0d\x94UxEG\xd4\x9e(\xb7\xea\xb1\xf2\x96ao\x00o8\xac\xdf\x89\x9c\x19\x14\xd3\xe1\xc0+\x9e\xe8\x1c\x9f3*\x8e\x8d\xb3\x83\xef*Y\x16`\x9fw\xd6 \xc7\xe7a6\x7f\x9aLU\xc8\xc8[:\xe5bT\xaf\nV~\xe8\x08B3\xe3\xf9\x9a\xd6\\M\x11~G\xdccM\xadPji\xa3\xfe5\x1d=\xa5c\xa7/\xb7>\x1b\xc7\x0d\xa6\xc6\xfb\xa2\xea\xc1\xfa(;\x8c\xf3\xa5\x08\xc0Bw8\xdd\x13\xa7\xb1\x98:k\x07\xaf\xfa\xb5p\x98\x8c\x93)\xf9\xb0^\x11@\xd2\x9e\x9dG\xbc\xfeYq\xbf\xad)vM\xc2\x8c\xc0`\xbf\xf5=Ph\x7f?\x8f\xa3/99zf\x9e\xa3\xbc\xb0\xf9\x07\x1d\x9b\x9f&\x13\x0c\x18>\\\x10\xf6\x0f\x9fl\xedf1\x06k\xd3z\xa56\x88-\xa5\xac\x96\xf6=\xfd\xd7l\xb9\xb6\xb7?\xd0@=\xfan\xc2\x07\xbe\xf7?\xe0\xde\xb7\x84\x88\xbc\xa6>\xc3\xfa\x8c\x18=\x1c\xc1\xc1\xd1\xb5\x8aB\x7f\xc8\xfa\xc8C\xfc\x81.\xcfu\x8f\xc1\xde\x9b$\xde!<\x95q\x19H\x98A\x98\x12,\xfa\x86\xd9\xb5\xc9\x14\xc2\x0c>\x93u\xd67\xd5=\x90\xdd\xb3\x0d%\xa2\x8dy9\x89\xd2#$\x80\xa7\xd4\x14W\"/R\xec\x9b}\xd8\xb2\x04x\xb1k\x92\xc4\xb3\xe84w|\xfb<\x8d\xa8\xdb\x9b\x82O\xd7/>\x80\xb9\xa4\x1e\xa8\xe5\x0d+N\xf5\xddH\x86`\x93\x95H\x12\x85\x83\xd7}\xe0\x1b\x1b\xb2\xab\xdb\xd4K\x95\xb5\xdd{\xee\x87\xab\xd5b-\xd8xCD\xbfz]\x06\x162\xc9\xce\xc0\x16\xc8\xb6\x13\xc1\x8aSzI\xf2\x1ax\xff1F\x08\xd1\x042B!\x84\x98\xed\x83\x12rr\x8c\x90\xc4bOXQ\x9f]T\xce\xc1<\xfb\x0e\xf4\xc4z\xeaw:\xed\xa5\xf2\xb5 k\x8caP2\xdah\xf3\x01\xd4\xa0\xc5\xcb)\xb3&y\xfddT\x93\x96\xa5y\x18\xf7@\xa6}G/\xd2\xb7\x06\xde\xbeP\xc7\x10\xce(\xa9\x16\niiG\x03\x05\xbep{\x00\xdf\xf1T\x85\xfd\xc9\x829\xf3Ld\x15\x16\xd6\x97)\xdc\xbdu\x9d\x11\xfcW6_r\x85\xa7\x92\x01\xeau\xb82\xa6<\xfb\xfa\x8d\x96\xc5\xe34IJ\xcd,\xfb\x81\xa2s\x11K\xc3\xf36\xf9:\x93b\xa5\xeb\xacS\xd7\xffP\x93B\xd9\xe7\x94\x11z\x14wh\x1a'\x92\xaf\xa6!%G\xf8\xf22h?c\xcd\xdc\x92}p)Y&g\xed\x92\xb6f\xd6K{\xc3S\xb2 l\x02\xaeM7f\xed:\xe5e\xd7)\xf3N\xea\x0bbO\x1c\xcdE\xc8F\x89\xcb\x03\xe1\n\xe2K\xe3L1\x81\x11\x1d\x8bF\x1d\xc6\xd2D\x0f\xc3h0\xd8\x15\x9d\"E,&Gq\x8b\x8flA\xa2]\x12I\x9c\x898P.\x80-\xcd:\xd1\xbc\xd5\x17\x8f\x91\xbb\\\xf8\xe1\x99\x89\xe2\x99H\x19\x93`\xf0Hk\xc5\xd8\x0c\x86\x10y\xb6\xb2\xdcb\xb92\xbe\\\xc2Y\xb7\x19C\x06F\xa9\xe3\x94z \x03\xb2\xc8\x1b\x9c\x11\x1a@/\x8ay\xb5\xfb\xcfd\xfd3V\x883Cf\x82%\x80-\x1e\xa8\xec\xa5\x99\x98\xf2\x92M\x19\xa9\xd5\x84\xed'\xf3\x07X\xa0\xd4\x9b\x95\x0bhU\x94r\xd6e&f\xcf\x7f-\xd9/\xb1\xdb\xbd \xc3W/)y\x19\xe2\xe3\xd91 `\xa1\xe1\x01\xc4\x9e\x8fc\xd4\xe9\x1a\"\x1eE\xdfi\xd1\x9b\xe0\x9a\xea\x96\xd9\xfa\x0e\x98,Hh-J\xa44\xdet\x8b\xa1\xdc\x1fB\x1c8\xc9yL\xd2\xa3gp BaE\x0c\xe3n\xa0\x9e\x14CQ\xb4S|\x83\xc1\xfb\xc3\xf2\xac\xe0w\xc3\x05\x15\xf5N\xb6\xc4M_pw\xd6\xc9,Iz\xda\xaat\x90\x90\"\x02\xae\xb2ks>\xc0f\x1f\xbfF\xd5\x92c\xb6\xf3\xa4\xe8\x08\xfd\x97\xea|\xd2\xa0\xe9\xc8\xd1\xec\xaeJ\xa0\xec\x86pM\x0fFl\xa9\xd2L\x12 \x84\x03\x07\xad\xaf\xf8\xde \xf0\xf3e8\x90\x7fI\x1d\x0d\x12\xd5}\x88Gj4^\xb3\xa8m\xcb\xf1\x81M>#\x18,\xdbi\x9d#\xd2m\x8dY\x1fN\xeb|%\xd0\x17\xc3J\x88\x87b\x85\xe3\x88\xfe7\xa2\x02\xae\xd6\x81\xfa\xebzQ\"KR\xea\xca\xe7\x1c\x11\xef\x17R\x98\xfd\xdb\xdb\xfda\xdd\x81uT\x1b'\xed\xedWd\xa0\xd6 \x14\xb2\x16[\xa90{\xcdu\x11:\x06@.)\"\x16\xe9\x9f\x87\xd9\x13NO=\x1f\x8f\xa1\xe3c\x12gyJ\xde2z\xedU\x89\xb7d\xa5\xac\x03/zw\xdc\x83\x8d\xf3\xa1zn\xa8\xa3a\xa2\xd8{;\xd8\xc2\xecHjb\xba\xf5\xaf\xf6\xd3\xb22\x05\xc8\xba\xf5 \xce-k\xdb\xdd\x1c\x9c\xa4F\x84\x9c\xc3\x0dw\x99\xa7\x93\x17\xda\xb7:1+\x87{\xe1m\x83r`3\xb3H\x0b\x11\xe1\xc1v\x1e\xc1\x043\x043\xca\xe8l\xee\x01/\xfb\xd4\x02\x01e\xb5[\xf7\x96\x9cI\xc9\xe0\xe8\xb0\x15\x0e\xe0\x9f\xb4dmT\xb6&(\xf3: K\x83\x1c^\xad!%\xf7\x83\xca\xe0\x0c\x04\x83\xa3\x99N\x941\xc9}\x08\xcf5\x9eC\x1fi\x00?\xd0f2\xe0\xd7O~6TO\xfb\xc2\xdeV\x81dR\x0f\xfenN\xfc\x81\xc3oNH$*j\x18\x1f\x8c5>\xac @\x0c\x9d\x9cDt\x89\xe0\x90\x90\x8f\x13\xee\x82\x1c;\xf5\xf9\xcbU\xfa\x9c$yL\xaf\xdc\xe5\xcb\xabt\xf9\x99\xac\x7f\xe4L1i@\xd7\xad\xdb\x17\xd7\xd7\xed\xda\xb9\xd3\x1b\xed\x9d\x1eS^j\xb4\xdc9E\x84M\\\xfa6\x87\x93\xcf\xc8\xbc\x14\x14\xe5'\xea\x89_n\xda\xd0\x1f[S<\xf2\nH\xa6}\xac\x0b\x025!\x0f\xad\xa9,$fGAA}\x10u\xa9FM\xd1\xd4Q\xf8X\xe4\x0c9\x84\x08w\x9bN_a\xc0G\x11%^\xe8\x97\xf8\x82\x06\x10Zy\x15&Qq\x89\xcd\xd3~\xba\xcf\x10Q\xac'e\xfc\xc8\x85\x17\xfa\x01\\x\x0cU\x18\xc4_\xc8\x1c\xae#\xf6\x99k:wB\xec;\xbeVy6\xf74\x9eEF\xf2\x92K\xa0En@\x8e\xac@.v=zm\x95j\x95\x9b7\x01\xb3\xb0V\xd4+<'c\x91\xd8\x97o\x7f7\xce<\xb1\xef\xeeR\x9433\x15\x002\\\x0cu\xf8Ue\x1a\x8e\xb7\x92\x8c\xba\xf2\x9c\xab\x84\xcc\x9ax<\xb9\x8a\xce\xadjx\x9e\x8d2\xf2\x85\x1e>jY9\x13@r\x97e\xe1\xdb\x1c-Cq\x7f\x16\xb1\x93\xc1\x01\xfd\x8a\x8f\xcb\xc4\xb9\xcdA\xfa\xbeb\xedb\x07\xb2\x9af\x17\xe9jy\x8am\x18\xa9\xc0\x94\x87\xca7W7\xb5\xa7\"\x1a\xaa\xf8\xc4\xb6\xe2\x80&pq\x1e\xa5U\xabi\xab\xf7pE\xfe^\x8a\x1a\xa3\x08x\xec\xd2\xf8\xad\xc6e\x02o\xabA0\xa6\xa5\x93\x17\x95n\x19\x86\xf4\xb1\x97\xd5z\xd2\x05A\xc3\xb2\xd2\xf1(\x1a\x17\x0e!\x9a\x81bf\xf2\xca\xd1\xe7\xc5\xa3]G\x89#l9iA\x84\x86x\xf7\xef\xde\x7f\xf0\xe0\xf6\x9d\xbb\x0fx,\xcf\xce\x10\x03ax\x1c\xcc\x9d\xdb\x83{w\xef~\x7f\xef\xae\xef3f\x0f\x1f\xec\xc1M(\xbeQ\xee\xdfa'\xd3\xde\xdd\xbd{w\xee\x0en\xdf\x0d\x80\xc2\xb6h\xea~\x00\x83\xbd\xefy\xf3\xf2\xde\xe0\x9e\xdb42\xe2(\x85\xa4\x02\xc5\x0fm\x15E\xa3\x11\x19\x0b\x01\xa3\xd6\xbb\xfa\xeb\x0b\xba\xba\x08\xde\xec\x0b\x15\xe6p\x18\xb2\xbf\xb9\x15.(\xffD\x9dz\xf1\xd2Q\x1c\xc0\xef-N\x11\xe6\xb9T\x0eCUz\x17\xc7\"g.\xa2\xf2X\x84G\x90\xf3\xd3\xd1HH\xa7\x88\x9e\xd1(\x193\xd4)s-\xb2\x1b\x03\xe7R\xe6\xb5Y\x19\xcd\xf0*\x1fi\x9d!\x16\x1b\xe1;6\xc0\xd3\xb9:\xdd \x9f\xee\x0c\xcfc9\xdd <\x02\x8cm\xda\x9abB\xe0l4\xc1I=\x84\xc9\xf6\xb6\x81![\xc0\x90\x7f\xa7\x17\xc8\x16p\xc0\x9b\x19\x8cq0\x11\xec3\xeeWQN\xea\xbf\xe3|\xb0\x17\xa2g\xd4\x02]\xc9.\xbc\x84IQaIH\xb3\x96\xec8\x18\xc4\x81\x0e~[!\xfb\x7f\xe1\x9a\xf0x\x08\x13]\x98\x8a\x15y\xe4\xc5\xa5Z\xe9\xb1\xf8\xdebp\xaf\xa0\x9b\xe0\xfah\x00\xe8\x88\x1a\xc0\x88u4\xf6+\x1c\x19q\xe1\xc8\xe4%\x9d\x0d\xc8\xc8\x94\x00O^\x11b\xb5 \xff\xb4\"\xa2\xe6\xa8h\xc9\x8d\xd5?@\xcbE\xc9K\"\xbb\x9e6\xb3\xae2\xabQ\x9eMa\x05\":LQ\xf0J9\xd3\xd81\x93\xf7V\x0c\xb7\x90\"em6\xff\x03\xe4\xaf'\xc2\xf6\xbf\x03\x038\x80y\x7f\x95\xf0J\x10\xf3\xd1\x84Q\xa3\xc6\x8d\x11\x1b9\xe3\xc7\xe7\x9c\xc1\xe4\xbf\xfd\x00{\xf6j\xda\xbfyi\n\x97\x02s\x00\xf36\x96\xf42\x80_\xafL\xce\xb4\xd1e\x88]\x86\xcd\x8aB=\x13W<\xafZ?\x9cG~R\x94}\x0c\x9a\x91D\xd2\x10\xae\xe95\x126\xd60\x93snr\xee\xae\x08\xcdF\xe5\xec($\xfc\x11fF\x1e\xf38..#\x11\x1d;Q\x07\xcf\x95\xe9b%3\xb4L\x00\xfd\x84z\xa9 T\x8a\x80H\x04\xcb\x13#\x90\x88E\xaa\xcc$|C\xfd\xf3I\x15\x86\xfa\x97f\x18S\xb95\x04o\x027A\x87\xdaH\xd7\x90PGue\x8e\x96\xa0J:\x1d\x12\xde$\x02_\xdf\xf9J\x8e\x10\x97K\xff\x0e\x1a\xdd\xe1\x00V\xa3\xc5\x18Z\n\xb1sE\xd9\x9c\x9b\xc5\xf8BW\xd7J?;\x1e%>w8(8\x1c0\x94|\xa5\x90\xf7\x99\x95\xbc[\xdc\xbc*\x15\xbf\x04C\xc0\xf63\xaf7\xb3\xf6\x03\xc4\x8c\xdd\x87\x82\xd5\x8f\x1fB\x88i~\x18n\x0ca\xe0C>\n\xc7\x88\x067Q\xb3@F\xc9\xf6\xf6\xd8R\xb3\x0e\x14\xa1t\x94\x8e\xb9\x8a\x8b\xf5\xc8M\"\x98\xe3A\x1f\xcc\xcf\x1e\xaf\x02\x98\x04\x10\x0605@R\x9c\xe7\xec\xffj\xb9z\xb5H\x7f\x93*\x11\xb4x\xb2\x04\xb6\"\x12\x0df\x81c\\\xeaWxS^q\x0eRQp.W\x88?{k\xe03V4\x1fc\x9ck\x0e\xdb\xc6\xd4\xb8\xd0~xs\xa8iA\xd6\xc2!\x15\x1c\xb6\x84\x9a1M \x14\nu\x84\xda\xb6@\xaa\xa8\x84\\!P\xb8\x80.\xa9\x80\x8e\xab\xd6\x10tb\xcf\x86\xf0\x08\"\xdc\xb1>\xbb%h\xbb\x97\xf0-\x1b\xf3\xd7w\x06\xa8\x9d\xe5\xf7\xe8(\x84m\x97rn\x86\xc2\x1f*\xee\x19\x8f\xcc\xe3\x82\x9d(\xac\xa8'5\x93\xe6y\x95\xbb\xe0&\xda\x93\x00\xce\x1b\xe7\xe5/\x7f-;aa$Z\xf8\x08\xce\x10Df\x11)\x81\x03Ht,\x82\xceo\xf2\x97\xffel\x82\x94\xcd\xb4/L\x1cNa\xc6&LF\xa1\x81Lg<\xf8\xc6\x911\xa0\xc4\x9bu=\xa2\x85#\xadC\x0f\x05O\x81\xf6z\xc3\xb1\xd2.\xc3\xed\xec\xac\xe0\x11,\xae,\xb7U\x08\xecn\xa0?\xe0cy\xc0s\xa1y\xc0%\xe5R,c\x14d\"\xce\xfc\x0c\x1e=\xc2#\xbf]L\x9b\xa1\x98\xa6[\xac\xca\x9beT0\x1e\xb3!\xfe\x89\xb4\xd1\x8b`3d\xc2T\xce\xf9 \x06yc[\xad\xf2ZIB\"-k\x01\x92\xbd\x98 \x87\x11\x1a\xcd\x8c\xab\xedm\xfd\x9a\xcf\xbb\x9e\xf2\x8cS\xcc\x88\xc7\x99\x99\x05\x93\x9c\x8cta^\x90K\xe9\x00\xb2\xaaQ\xcbi\x95ZrNj\xc5\x98\xa4:\xd9xyej\xf9\xdf\xacKz\xf9\x9f#\x86\x82\xae\xe9wy\\\xe6Z\x14\x86\xbab\x8e\xa1\x92\xc0\x8f+\x7f\xb8\xbe'&\x8a_\x1d\x0eZH\xe1\x9a1\x14K\xf2\xff }WXr\xee\xb3\x8a\xd5\xf4E\x99\x97P\xc0\x92M\x80\xb1\xee\x13\x93\xf1\xb4\xb3\xa6\xa5]\xcb\xf2\x1f\xd4\xb0\xbc\xd4\x00`\xde\xd8\xe0/\xae\xbc\xc1\xa5\x18\xc3\xa3B\x0b\x9f+\x86 2\xa2\x8e\xdf\x18\x8cu\x0c\xc9\x8b\xeb\xd9\x835U\xaev\x99\x90\xe4!\x06W\x87i\\./\xc3\xea\x19\x05\x12(\xf3\x08\xfd\xc6F\x0ce\xc0\n\xc3H\xd8\x87\x0c-\x01Z4\xaa\xac\x1a\xb68,\xca\x10\x89e\xd3\xe1\xadXv\xde\xa5f\xd7#\xd1)w~c\x91+\xba\xf3\xd2\xb9\xf6\xa5\xfeve\x0d\xac\xa4=n\xd0\x91\x94\xd3\x91\xa8V\xb6\xe8!\xa4\xa2\x84L\xea\x94\"9.\xea\x97\xa0\xe7\xc1X\xadwY\x9f\xdc\xaf\xfaY\xfcrm\x93\xe3L\xa6\xdb\xd4\x0c\xbcN!|\xd5\xe6\xa5\xe7w\x18(\x12(\xb3\xcf$\xfdJ9\x06\x13,@\xa7=}qE0H\x8a\xac\xa0k\x03\xad\x88w\x83\x06\xf0\xd5\x0f\xe0\x86\xdaKL.ZS;\x14P\xa6\x12\xca\xe8_\x19\x94A\x02\xdc\x99\xf2!\xd8\x8b6\x88\xfa\x13\x04\x17\xc9\xac\x0e\xc7\xd4\x98<\x0b\xaa\x8e#\x03)f\x8b\x89Z8\xd6\xa8\xa8\xadZ\n\xe1\xdcg3\xd5AI^\x97en\x9bT\xee\x96\xb6n\xb0\xbe\x99\xa8b!>Q\xf0\xce\xd7v\x1f\x91l\xc4\xc1'\xddS\x0f\xb0\xcc\x1e\xafy\xd6:6\xb5KD\xfbj\x87v\x95FR~f\x19\x83]\xd1\x91\xb4I\x0b\xf8\x92\\\xa6\n\x00\xe4]\xbb\x0cQ\xc3/\x18\xc2O\xd4K\x8c\xf6s\xb0\x8a\x0b\x93$\xa6Q\xdc\xa9\xf8C\xb3\x7f\xe5W\x9f\xfb\xcc\xb6\xecj(\xb7\xa7ic\xb4\xe6J5\xe6I\xad\x11\x90*0\xd9*c\x1e\xea5\xdc\x82;\xcd\x96g\xf2\xd9^\xf3\xd9\xa2\xf8\xce\xe4\xb9\xbf2x\x0c\x9c\x89\xd8\xa1\x0bc~=\x87<\x96\x9a\x88Z\xf6\xe5\x9cxJ\xcaI\x8d\xf0-O\x82\xc8\xa3\x96\x0c\xa3\xb1\xbd\xc6\x03\x1fL*t@\xde3~\\\xa7\xf0\x98g\x8dN\xe1\x11\xac\xe1\x00\xce\x89\xb7\x8b\x0c\xcfY \xe2L\xb1\x10\x04\xf1\xe2>M\xb8\xfc\xedcYZ\xd2\xd9-\x06\xfdD\xdeG_ \xf6\xacI\x03\xd2\xa6\xe9-4\xb5-\xfe&:/\x127O\x8b\xb9\xddaD\xc9\x032%-y@\xd8ArN\x19\x9bL\x1c\xf2\x80(\xc2\x87g\x8e\xb1\xe49\xbc\xc4\x11\xf7\xad9-^E\x19\x85Q/\x80\xde\xb8\x99\xd4\xa2\xd2\x93cR\x8bH\xd6\x8a/\x93\xe2\xfbEVrZ\xcdJn9M\x99\x00[\xb0\x96\xe8+\x83#O\xd2\xe842y\xb6I\x99\x8b\xf5\x14\xf7y\x99P\n7\xe1T\x13\ni\x02P#\xbbF\x05\x06\xdd\xb2k\xb8\xda/\x10d\x84\x83\x8c\xb3U\x95\xaa\xf9&\xbfo\xf4\x0d|\xac:\xb1\x11x\xa4d\x83\xed\xee\xb2\x06x,<\x82]8\x80\xb7\x82\xc7\xc3m\xb6+\"L\xdfJ\xa7\x04\xb4\x00\xf0gD\x1b]\x06`N\xb0Gp=\xe5b\xea\xdf)\xed9\xc74\x8c\x16v\x86J\xba\xf7\x1b_J\xac\x81\x02\x08\xc5\xcf\x18%0 W\xe1$\xa2kn\x10\x1f\xc2{t\xc2\xabG\x0dpy\x10E\xac\x88\xbf\x14\xd5^\xa2\xfd\xe3\x059#\x8b\xf2]\xf3\"n%\x8e\xe1\x06Q\xfa\xd0Z\xee\x00\xf8\xd8\xd6\xba\xd0\x13\x8e\xc6\xec$\xd3w\x13 \xbf\x0b\xae\x8a\xd4\xf7\"\xaa^\x98)y\x0e\xea(F6\x03\x16\x16\xa9\xcf\x19\xdd\xca+`F\xd8\xc2\x0e\xea8}\x1fG\x83o%\x15P5\xa9\xb2v\xc0\xdcJ\x169@9\x84!\x1c\x96\xb9\xb3\xf4\xf3\xdfJ\xf4*\x95\x8a\xe3\xc4\xeeC\xc8\xb8\x8bi\x86~\x92\x02\x16\xd9\xb8\x10\xbf\x8c\x049B7\x91\xb0\x80\x1e\xa3\xf1~\x00a\x9d\x82ip\xf4\xc9\x8c\x92\xc6\xf1\xde\x8a\xa2^\x15G1\xc8\xf8\x1b0UX?Q\xa8oA\xd8\xc8\x8e\xb0\xfaN\x9cp0\xa9\xe2\xa0\xc9\xa2\x848\x98b\xb2L\x86]*\x185(\x88/Ez\xc8\xa0\xf1\xab#r\xca\xcdbE9\xd1d.z\x13\xca\x8a\x08\x95|\x81\xf0k\xcb\x8bi2&\xca\x0f \xaf\"K\xf3x;%\x01,I\xc0\x98\x06[\x1a\xf5\x13\xf3iU\xf2\xea\xf2\x10\xd7BX(\n\x8b\x93]\xbf\x0c\x80J\xbe\xd4\x165\xc3\x0f}3|*\x89D\x04\xe3\xb0\xeb\xd7&\x06\x95\xb8g6\xb70\x00\xa3\x8d\xb5\xa2\xc7 +\xe5\xac\x0c\x9e&\xf2\x92\xc4$\x17\xfeK\x07\x12\xc1\xf8\xf1\xbe/\xa3\xdc\xf1\xa7\x99G\x05\xe1\x97\x92\x8b\xca\x87\xbb\xe8\x19\xbb\x03\xb9\xfd\x93 F\x9a\xee@n\xe0\x1b\xf1\x95\xc7\xb0F\xdca/\xdb\xec\xa1\x02\x08\xad<\xbc\xbc\"t\x9ce\xd3\x9e\x14\xfb\xe1\xd8Rt\x04\x14\xb5\x04V{\xdc\x99\xc0>\xa3\x9a\xf6OD\xcb\xe8\xd9\x15\x8e\xa8>W\nh\xb7\x1d\x80\x0c\xab\xab\xbb\xe5G\xa89nYV\x11 \xea\xbc\x80\x13$/\xd5\x05L\xe0\xf1c\x88\xec\xdf\xcd0\x00f\x9b\x1d\xeb\xf2\x03\xcb2\xcd\x8a\x05\x9d]\xf3\x82\xe2\xb9\xf6\xd0\xe8`\xa1^l\xed\xb5\x19]tW\xa1\x8b2 }\xf5+\x12E\xf6\x98\xa8\xd3\xa6\x90\xaf_\xa1P\x85\xb6\xbel\xb6\xe3\xcb\x8b\x0dcR\xf3%lCpP\x08&G\xf2\x19\xec\xc3\xa4\x0d\xc9A\x8c<\xe7\xae\xe8\x19f\xde\x8f\xf8\xa1\x940\xd4\x88\xd9\xa9\x1d\xf9f\xb7\x04\xb0N\xc9\xb27\x90.6\x1e\xbb%\x948\xd7&\xfb1\x1d\"a#;\xd7\x99E\xa3\x10J59;\x9b\xd98UU9\xfeTT\xe5\x04oH=y\x8c\xbf\xca\xacGa\xa1$\x8f\xf0\x87\"5&\xfc\x86\xd0\x97\xe7\xfcW5\xb9W\xe8\x04\x8a\x0bb\xd3\xa8\x9d\xa2i\xd0C\xc5\"\xb7\xeb3\xf1\xcd\xd1\x14\xfe\xbe e\x13\x88s\xee\x8f/\x92\xf3\xd8c*(w\x9a\x7f$\x89\x9bT\xcc6>@^\x18\xf1R\xf1\xa5\x88l\x1b\x93\xb3\x9c-\x9c\xdb\xa4F\\G\xa1%c\xce\x8c\x9b\xf8&\x1c\x0e|cHXX5I3~B\xc9\xbcQ\x9ed\xc3\xd0\xc6[t\xccXi}\xd8\xa0iE\xb3\xea\xc8\x8b\xe3\x9f\x96n\x99jWA\x05v\x1c\xf2(\xec4xK8(nJ\x13Y\xae\x8e\xb3\x19\x83`\xc2\x9bC3OW\xa8\xd9\xd0\x1f\xa0\x88\xc1\xa3\x8ag*\x15\x1e\xa8k\xe2\xf1\xfc\\\x82-E\xae\x94\x8d\x8a\x89\x97\x8d\x02P\xfa\x91<1\x8f\xa4\xb0\xa0\xd7l\xbf\xaaeU\xcf\x0f\xf2/\x1fq\x81F\xb2\x82\xb0\x0dg&\xa4\xab\xfarJ&R\xf0\xad\xf8\xf5C\xee\xb7\x80\xae8XXuX\xf80\xf0P\xad\x14=\x19\xd8G;C8\xb3\"^[\x99wcE/k\x92\x1e%\xe8EF\x9d\xf1r\xc7\xea\x13\x19\x7f`(o\xac\x98\xf5\xd5t;\x98\x9f\xc1\xcc\xb6\xb7\xb0\xff\x89\x0b\xfb\x8f1\x1e\xb0m*\xce\x10\x1623bc\x8c\xdc\xf4>\x9a\x8dv\xf1\xefm\x0c\x19c-h<\x16\x18>\xe4\xf5\xfd\x95\xb4\x91\xa9\x9c\xe1\x9e\x12s\xc0\x0d\xbf:N\xa5\x1a/Q\x88\x1e\x13\x15\x99f2\xe8t\x1bfl\xd4\x0f}|.\xf6\xd1\x84\x8dkR\xdd\xf1\x070\x92\xc6\xa3\xc9X\xec*&\xd8\xcd`[f\x1f\xc8\xd8\x9fg\xba\x11q\x99\x90=\x9e\x05\xbc\x8c\xfa\x8c\x1d\x00\xfc\xdf\x04\xff\xb5Md\xc1\xa5\xb1\x04#\x08\xf0\xcf\xd0\x7f\x08+\x06\x11\xec9c\xbb\xc9i\n\x95\xa1\xf3\xf1\xea\xf1n\xde\xe6N2\xc5 \x8aG\x18#\xc1\xc9F\xc8%\xee}60\xbc\xad\xa8\xb70\xba\xd1pda\x905\xff\xe6\xe6M\x8c\x03F\xd1l^SA\xb4\xd0\x8a5F\xb0 !\x9f\xf0\xe9-a\x08\xd9CX\xc2c8c\xff0J\xd0&K\x1c\xc3\x10\x16HA\x96z%\x89\xbcXwkAr\x8e\xc7\xbc\xdf\xf2\xb71\x81\x94\x9e\xbf\x93\x1f\xf2\x9e\xcf\x90v\xc1\x10\xe6-\x94 $\x83/A\xe6\xb1E\xc1(\xf6iEq\x92\"\x1b\x13\xfax\xd6=\x1e\xc2\xca\x87\x9c\x81c\x85\x8b\x86\xfff\xdcmaR8(4\x9a\x12z@\xde\x96.|\xb2pGf\xc2q\xc4(\x15\xe2\x87u\xe5\xc4>\x9cX\x85\x19\xb60'\\\xe8~\xfc\x98\x1d\xe8\xb6\x85a\x038A\xea\xba*_\xf7\xe1$%\xe1g\xf3W'BP\xdb\x1e\x82\xc7\xb7\x94\x0f\xdf\xc1 n\x92\x9d\x022b?\x8dN\xf4\xc2\xad~q'\x1c\xab\x1f\x0b5\"o\xa7\x0e\xd2\x8c\xad\xcc\x0e\xcc\xd8\x12M\xf8~x\xc4\xf7C\xe5\x83b93F \xc4\xfb\x92\xba\xec\x08\xaa\xb2\xa3\x8d\xa2\xec\x9c\x924D\xb5Fy\x9cp\xb6\x9bV\xd8\xf9\xb0\xd4\xed\x00\xc6q\x96\xeeU\x13\xd5\xbdj\xea\xea^\xc5\xc8\xc49\xf1r.\xee`\xa4f=\xba\xd1p\x1c\xff\xe1\x96/2U\xf3EV\"\xe8\xcb,k\xa1=\"\x04\x93b[\x99\xe0 Z\x01M\xe9{&\x1c\xc2\x8f\xc5\x9eMp}E\xa5\xbf\xdc\xcbxJI\xbe\xea\xd7\x9dR2\xe5\xf1h\x93\x0e\xe8\x91\xc0c\xe94y\xf3&O\x10Uz%'HR$\xe4\xebYn\x0c+\xf5\xb9-\xc5\x1cw\xab\xdeE\xa5\x9c\xd4Y\x9f\xb1My\xe6\xd4\xfe\x91\xbd}k\xa1\xc7\xa7\x9ce~M\xca\xfa\x8e\xecVg\xbf\x9b\xb3\xff\xf5\xf5\x1d_\xdb\xa1X\x94\xc2\x9c\xd5\x11\xce\xd4\xe0\x07\xd7\x94|U\xd5\xc3\x91bT1+!\xca\x14\xe1(\x02\xe1\x8f}\xb4\xdb\xf7\x8fy\xea \x9e;|\xc1\xed\xcb\x0e\xb9\xc3\x9d\xe6\xf4\xd4\xaaLXre\xc2\x92\x8d\xeb\x03\xf1xu\x9b\x0b\xe25B\xfd\x0c\xad\xffl\x970\x84i'\x90,\xbd1\xf5R.\xf8\xe0(3x\xfdb=6LIA\x0c\n\xff\xac\xe4\xf8\xd9\xd1\x1a\x9aT C\x9e\xb7I\x8f\xb7\\?\xd1\xa6(\xcc\x05y\x1cr\xedi\xf9s\x0f\xbe\x83D:n\xa2\x8d\x88\x1b+\x9b\xc9O\x0d\"\xac\xbcD\xff\xca|\x84\x8a\x05\xa55\xc3>\xf2\xfb4yI\xd6d\xfa\x9e|\xf1\xfc\xee\x94\x99\x8ev\x0d\\\x83\xdf\x9f-\xa2\x95\xc7:x\x1d\xf2|:\nn2\xa2\x9bVp\xb5\x8a\xb9\xaa\x933:\\\xa0\xf1L\x96}c\xd4%\xc2\xc3\x9c+1\x14\xe7\xde\\Q[0\"\x12J\xd1T\xa3\xbcTb\xcd\x8c\xb6\x99\x12\x01rD\xa5\xd0\x1f\x0d\xc6m\x8b\x9dr\xd5\x1e_G1\n\x9ej\xdd8\x08>?\xe1L\x9fK\x12Z\xb6\x90\x8bB)\xa2\x19#\xc90\xf1=\xa9,\xb4\")\x07\xf7\x0d\x17\x94#\xd2s2\x0c\x8c\x1f\x90\x93s\xcc\xbc\xfc\xae\xc5\xeb\x04\xdd\x95\x14\xaf\x93\xe3<#/\xc9:SJYH\x8a\xd7L\xe2k\xea\xf4\x8d\x81\xa6k{\xec\xde\xfc\xab?\xb7\xf9g\x7fn\xf3_[\xe2\xd8\xfeAl)b\x89:\x02R\xed\x9e\xdd`[\xbc\xcd\xabSi\x8e6\xb1?\xc0b\x8e\xb2xIkCgE\x99d\xf1\x91\xac\x7f\x86\xdeg\xb6\xbe\xdd\x07\x0b\xean\x12\xddx\x06F$\xd0U\x14as\x9a\x87Y\xab\x1b*\xa8\x1dE\xf1d\x91OIV\xafj_\xb4(_\xe8\xd6\xec<4\xb78 's\xf2\x8ed\xf9\x02\xf9\xdf8\x00\xc5\xa3\xf0c\x8c\x8f+e\xbbl\x11L\x85ZO\xebL\x01U\n\xd5\xa8g\xe5\xc8\x18\n\xafC\xf4\xb5\xa7fu\x84\xb1\xd8\x95\xe2\x9d\xdau~\\\xdf\xcb\x0e\x82wmR\xbd\xd4n\xca\xaex\xbbf1]\xb2\xf0nN\xac\xf2\x92v\xcd\xd4Z\xbeV^\xc8\xa5\xd0\xd6:\xb6\xf2*\xf7\x19\xba\xb9\x8ev[\xb2!\x01\x86u\xcaw\x95\x0f\x07\xe3@\xf9\xbb\xe1^X\xbf\xecfQ#\x19\x91\x97)\x8b\xb9\x1b>\xb2\x95\xc2\x15\xfe\x99\xc9L\xb0\x0f?\x1b\x11\xa9r\xd3D{\x9f\xb7s\xba\xad\x148\xad\x13\xdd\xb4;i1\xd3\x80\xb4\x1e\xd2\xe9RT\x99\x97%O\xcd\x85~\x0b\x19{(r\xd0G\x18&\x8c\xbe\xf6\xbc\xc4N\xaa\x15\xedp@V\x02\xe44\xbc\xab\x12\xa0\xa8\xc5\xd9\xa6J\x83R\xaf\x9c\x91\xfcXX\x04MD)j\x99\xb2\x9e(9\xcdY\xc5\xe1w\xe6\x14\xce\xdd)\x8d\x14_\x93V*\x83\x8ev\x82\xc0H\xf9\xd5\xfc\xf6\x99\xf0I\x8b8m\xb0\xbb\xa8\xa0o\x82\x95\x06I\xf9\x9dA+\x0c\x14d\xcb\x91\x02\x85\x0c\xdf\xb4\x0b\x00\x06uB\xa3*\xa2a\x8f\x7fl\xf7\\\xb3o\xf0Xe\xb1\xe2\xfan\x8f\xbb0G6.\x8br\xf6\x07-s\xce\x9c\x90<\x05\xbe\xeag\x00*w\xd5a\x9c\xa0\xeeE.%\x9a\xb6\x8c\xae\x8c\x07\x83J\x8dl\xd9\xd2 \x16=\xa1&@\xe4}\xdc\x19\xc0\x8e&\x855\x08\xee\xa1Nc\x8d\\A\x95\xc6V\x1a7\xb4|56\xae\x85;\x8c5\xbc\\\xac\x8f\x0e\xf9\x8f\xf3p-\xc5H.\x03\xd82\xc1N\x1f[d\x9b\x91\xf6\x8c7\xf7\xe0\xb4\xe5\x7fpU\xf9\xb5\x9c\xec\xb8\x19\xa3:\xaa\x19\xf1\xf8\xacH\xd4\xebv\xfcFxL-Y/[[%A\x8c,\xa7o\xf4\xe7\xb2\x03\xc5x\x9a\xbc\x80\xb0\xb5kJ\x0b\xf9\\\x87ia\nl\xde\x94gJ\x9c\x80\xf9\x8c \xf5Uy\xa1\x1d\xe1\x13\x8b[/H\xa9A\xe5\x13\xf0\x832\x91\xe2\xf6v\x00\x91\x87~ \x1c\x02hn6\xe7\xf9dS\xad\xfb\x84\x81\\<;\x1f\xe1\x04\xa6\x1a\x1f\x91X*/\xb6\x03\xad\x03\x9b\xe1\xe8\xfc)q.o\xe5F@\x06eT9\x92\xc4\xfe\x854\x84%.\\ \x08\x9bX6\xda\xb5X\xcd\xe4\x85\xd9,\xb5\x89A\xd5\xab\x8a/34\x15*9\x81\x9ecED\x91[\x1d\x91gfd8\xc1(\xf8\xe8\xf9\x1d7\xdb\xc0\x17W\xe2G\x0d\x11\xa7l\x86\x9d\xdc\x88\x98\x101\x80[\xe8\x83\x83\x81\x88\xe8\x93#\xde\xff,*\x98E\xady\x93\x18\xda\x1c\xf1:ff{\xc2k\xa4\x90\x86\x80\x1cF\xc0 \x81\xcd\x06r\xf6W^\xf4\xc8`\xd2\xa7 W\xa1+\x07\xb1\xe7\x97\x90\xd2\x0fJ8y\xe7\xb0\xa3\xc3\xcc\x0c\x86C\xee\xe9\xe7\xb1\xcd\x96 G\xa4]\xd8\xd7V\x9a8\x13^\x8d\xf6cg\"Y\xcc2\xdc \xc4\xcaZ\xd2\x18\x1a\x96\x06\xc4\x00\xb6\xf0\x94\x8a\xa4Y,,\xd2\xf8x\x93\xfaY\xe1p\x0c\xcb\x0c7\"\xdc\xb4L\nDDQE\xc9\xa4m3:\x89\xe9f4~l~\x00\x93o\xd3SEV\x1e'*\xb2\xea\x95\x8eY\x06B\x87\xd6\x81J8Nu\xfd\x95S\xc3\xa2\x03\x92\xd4\xd7\x12E\x9cqW\x02\xe3\xf3I+1\xbe\x12\xcb&|o7\x1b\xd8\xc2r\x90\xf9\xf66<\x82\xa4\xdcl\x13F\x83\n\xad\x9c8\xc7b,\xf8\x80\xe7X\x84h3\xe1\xe65\x031\n`\xa2\xa3G\x93oT\xd6 \x9b\x1e\xeb\xdfi\x89\xecz:\x896J\xabM\x15\x9fy}\x1c\x96\xf7\x9a\xcfR\xb9V\x0f}\x88ZOK\x06\xaf\xed\xed\x0c\x1e+(\xdfv\x12;E\xbfC[\x04<\xbb.\xedj\x024P\xb5N\xa1\xe0\xaa1 \x96\xd4\xe2Q\x0c\xb0'\x01\xaf\xa3\x13\x88'Oe\x92\\\xf4\xc6P5\x95]\x14\x04U\xac5\x1d\x98\xbf\xbb\x1e\x98v\xb2}M<\xb0\x99\x8c%.{\x84x\x16\x97\xf73\x11da\xa3S\xed\x88n\xe1\xb4'\xad\xa4\x8a\xa7\xe4\xc6\xd3\xb2\xceuO\xfc\x92je\x0d\xb6;\xb3\xb3\xdd~\x00\x9a@\xcbk\xe2\xb9\xbf}Y\x92\xd4e]\xba0\xf7\xdf~\xdet X\xb8\xc9q\x914\x89\xda\xe55MZ(R$\xb3\x0e\x86\x82V\xf8U\xd6\x1f)CT\xa3\x0cQ\xc0\x8f\xb0\xa8\x8d.\xb4\xcb\x0d\x8b\xd2\xeaa\x7f\x99q\xa2\x0b\xac\xe47\xc3\xbfX\x07\x9c\xcb\xcb*x;\x13\xf1L\x16\xf6\x1e\xce\xe7\xd1\x82\x80\xd1)\x0fTu\x00\xda\xae\xd4\x99'\xd8G'\x9a\xe7&$\xfcz-\x86\x8fo\xb6\x04X\xf0\x17\xe9\x94\xa1\xce\x91\x18@1\x1b\xeae-\xb4\xe7LT\x0d1oeve:\xca\x16\xb5(\x10@\xe1\x9e\xb7\xd0\xf3j\x02\x8f\xb0`\xcdM\xc8=\xac\xda\x87e\xf2'\x18\xa8\x0d\xfb2M7R\x84X\x94\x03HPR\xf4\x0bIbk\x17\x8bs\x9a\xf1\xca\xac*g\x0b\xcb\xben\x96P\xfa3L\x19\xa9Y\\\x03\xb1\x8a\xa3\x96B\xe7\xd7F\xa5\x04[\x958))\xa8\x93\xc9\x04\xe4\xb9%R\xcdw2\xcfN\\\xe9\x0d\x88^RA\x01\n\xf7\xeb\xd1`\xcc$T\xd4\x10z\xa1\x8c\xa7@\xecb\xc7h\xeeM\xca#3.\x08G\x1a\xf0\xf3s\xd2N\x16\xd9\x15r\xe7\xdcD\x94F\x9b4\x96\xd7\xda\x82\xf0\x8eJ\x90\xac\xa3g\x97\x19i\xdb(`\xdb\xaa]#C\xdb\x81\xa2\xba\x99\x99~\xb1RT\xee\x91\x89\xd1\xaa:\xf9E\x12\xdc\xd0\x986:2SK\xbe'\xa5v\xa3\xe2 HZ\x8a8 \xb8\x8fR\x1cy\xc4K/\x1e\x00\xffP\xb8\x97\x11\xa3\xfb`\x91e\xdaxD$\xfd,I\xa9\x9b4+>!\x1e\x1d\xdd\x1e\x07\x10\x8fn\x8f\x11\xcb\xe9ho\x0c;\x10\x8f\xf64\x19\x82\xfd\xb2 y-+\x83q\x97\x96;i\x08{\xcd6\xeb\x15\xfal\x0d1\xd0\x8f\x06\xba\x81q\xce\xf5\x85\xa8\xf1\xc1\xdd\xbao\xf0_?z5\x85\xa0 \xa7^Zq\x8a\xfb\xbb(x\xe5b7\xfa6\xed\x82,u\xe0\xdcRG\xe0\xcaK\x02\x99\xad\x0f;\x99\xe0w\x0fC\xd8K\x9fK\x86\xef\x96\x03\xff\xea\xfa6\x07\xf6\xbf\x03g\x88\xab\xd9*\x80\xa1n\x02\x973\xb9\"\xa0\x04\x16\xd8\x00\xc2\x13\x90\xf4\xb3dI\xae\xd2\x01C/K\xf3\xa2\xbe\xd4_\xc8H\xc9\xfc\x989\xe6\xc7\x14\xce\xbe\xa2\x1c\xc5U\xa1\x88\x03\xb4\xcd\xf2\xfa\x05\xe2\x1f[s!p\x13\x0b\xaf\xc9A\xfb\x93$\xceh\x9aOP\xb3\xecF\xdf\x7f28zGE6\x1b\x1e\x81\x84%F\xe8(6j\x0d\x810\x01\xc9\xcd\x818mI\x9c\xcc9\x88\x82\x04Zs\x8aq\x0bv\x14g4\x8c'$\x99)\x15\xcf-N\x11\x089D\x8f\xea\xa7\x95d\x9f\xa9gR=\x17MX9tv\xc5\xa8\x96j\xd7\xb2\xe6e(\xe5g\xb2\xce\x8c~\x89\xf2\xdar\xe3\xca\xd4\x8b\xa6k\x87\xb7\xd8E\xb4\x11\xaeN\x9d\xc8K\xcceJfQL~N\x93\x15I\xe9Zp\xbe\xee\xad\xb0\xeb\x94PE\xb4\xec2\x06y\xa9$\x88\x87Mvj\xe2\xb2\xdd F\xbd\xb2\xcax[\x8fo\xdduJk\x89\x98\x03\xe8=\x0d\xe38\xa1\xacuHb\x08c\x88\x8a\xf4\xbc)\x99$\xe9\xb4\xdf+H&\x8f\xb6\xb3\xb0\x98\xba\xab=s\x9b\xbc\x0c\xd1\x08\xf5\xeb\xb2\x7f\x12\xc5S\xaf\x8c\xbak\xff\xec\x12&!\x9d\xcc\x01\xc1f\x1f\xd0\xa5']\xd3\xe5\x11\x91\x0b\xfd\x04r\xfdq\x88\x81\xbcK\x93\xe5aL\xd35\xd7\x95*\xca\x9fv\\\xe9V(\x81\x0b\x7f\xc3F\x95\x04\x87\xfc\xda\xa4B\x14*\xdd\x1a\xcd\x08%!\x11KT\xfd\xc8\xbc\xacp\x00\x1f\x88p\xe5\xecPmA\x1e-D\xdd\xd9<\xef\x85F\xa2AHF\x99BH\x87\xf0\x9aT\xe1;\x9a\xca\xea\x06\x15\xa8\x17u\x0e4\xfb6\x00\xe2\xbd#\x01\xbc\xf0\x03xw\x05\n\xdc\x14\xfc\x90\x02\xeb0\xa1\xd2|-n\xa0\xb5\\\x1ao\x9b\x17M\xb36\x8c\xfa\x91\xf7\xe4K'\x9a\x81\x8d\xcb/\x9bt\xe1]\x15nN\xa1BgJEf=\xbe\xb1&>Jr\xb8\xa5K6X\x19\xa3L6\x80F\x0d\xe7i\xaa\xcd\x88yJ+\x8798\xfc\xd2o\x04\x89\xd6\x80\xc01\xb7\x15;T\xb2\xa8\x07\x02\xa3\x02\xcf+\x87M\x070\xa4W\x01C\\\x03\xc32\\i\xf0\x15\x04\x18\x1a\x85_\xde}\xdb\x19\x11XB\x94\x9a(Y\x1e\x13\xd5\xc9+\xe6<\x07\xc7e\xea\x11S\xcc\xd2%#P2\xdf\xf2?y7>\xcf\xd2S\xf4`T\x9d\x17\xcdG\x81\xc8\xd7\x1c\xc3>/\x06\xa4\xeb\xcao%\n\xdd\x8e&<\x1eT\xb0\xf8\x16\x08\xca\xe3I\x7f\\\xc4U\xddS\xc3\xa0aD\xdd:\xd8\x8c\x8b\xea\xa8\x90\x97\x96\xa1\xd8\xea}Q\x88 hP\xe1JCT4\xf3U\xc0\x82\xf8\xe8\x17V\x98Wt\xcba[\x8a\xf2$!\xde\x1b\x12\xc0\x0d?\x807\xeaR\xe9\x02\x01\x1d\x89x\x11\x0d\xd8\xa4\xe4o\xbems\xb5R\x1a\xf3\xfah7\x9d3o\x86;\x0cA\xee\xca\x92ig\xea\x86\xf7\xdf\x84\xb0\xd7\x82\xa1\xc4\x15C\x89\xc4P\"14\xe5\xa6\x10\x81\x97N5\xc3\x88\xf7\x8a\x04\xf0\xa3\x1f\xc0\xabo\xe7 ,\xc8\xf7\xeaZ\x90\xef\xcf\xc40\xe2\x8e_\xda\xc9\\\x1b~\xfd\x87\x91\xa8\xc4\x9f\x8e\x88\xf4Lp\xba\xcfT\xe8\x10!\xcc\xb4\xf1\x10\xcdu\x14,D\xbd\x9fg\xff\x95\x88\x84.1\xa6\x87\xec\xfa\x89x\xc6\"z\x8a\x93En}\xab@W,\xd1\x8f\xc2\x00:vr\xb1\xb5\xbc\xb9\xcbo\x1a\xa4Xv5\xf5rZD\xd7\x02\xfb\xbf\x06\xd1\x1d\"C\xdd\xf6\x02\x14\xe1\x95\x15\xb7p\x8b\xf3\xa4\\/\xd2\xe6e\x89\xde\x95\xb6\x11\x02G\x0e]\x18\xa0zI\xde%o}S\x0c\x1e\xf7r\x04\x07<\x91\x0bG\x89\x14Q\xa2\xbc9\xe07\x07\xcd|\xf9\xeaepYt\xa0 \x95s\xb8\x9a\x86\xe0\x9d\xf9\xd1+\xf3\xa3g\xe6G\x98\xa3\xcaK\xe3\x00N(\x13-b\xe5\xcdoT\xb0\x86\xb1\xe0A\xb7\xa1g\xd4\xb0V:\xec||V4\xea\xec\xf3\xb7\xe7qi\xf2\xb1w\xe6\xa8L\xe0i\x9e\xe6Eut\x1b\x9aW7oep#\xaa\x89S\xae\xcc\x85\x89\xaf\x07\xe5\xdfRg\xa1\x89\xd9\xac\xcf\xc4I\xf9[J&Z\x95\x15\xef\xff\xe6Me\x00\x15}\xae~\xb2R\x99\xa0\xda\x06\xcc\xd3\xec\x1f\x93\xe5\x8a\xaeQL.~\x0c!\x8f\x85\xa8\xfd\x1bm\xa6<\xadM\xd5Qc\xdc\\\xb4\xd2J\xcd-\xd4\x7fS\xacZy\xfc9N\xcec\xf8L\xd6\xd0\xfb\x1bl\x03\x85m\xf8[\x0f\x92\x18\xd8/\x89\xc7\x06#y\x05z[%\xf8D1\xfd\xb2\x16\x87\x16)\x1c\xf4\x86\x15cBu\x892\xa9\xd7j\xc1\xadJY\x08e4%\xce\xc1~\xb9\x0e\xcd:\xcc\x955pT\xae\x1b7\x8ey\xa6\xc48\xfb({\x8f\x9a\xf8I\xdcT\x01\xcd\xe2\x00\x16\x0c\xc7z\x7f\xff\xfb\xf1\xf1\xd1\xeb\xd7\x1f?<\xf9\xe1\xd5\xe1\xf1\xfb\xc3\x0f\xc7\xc7\x7f\xff{\xaf\xe9\x08\xb2bog\x0eJ\xa3y;\"\x18\xaa5\x91z\xb5& \x05Y([j\x88\x91\xcd\xe5\x87\xa6\xf4\x8eg\xa0^\xae\xe8\x9a\x87O\x17`tSDL\xdb\xf7bU\xc9\xb5\xb2\x04a\x94\xd9\xeck\xe5\xebb9-\xca\xb3z\x97kJ\\\x93p\x9fY\xe9\xd2\x0c\xf3\x0ex36\xdei\xec\xe9L5\x86v\xd7\xdf\xa0\xd2:\xe7*\xad\xd3\xb8\xd4d\x9d\xff\xbfM\x93uj\x87_\xa1\xee\xd3\x14XT\x7f\xad\xe2\xd1\"\x96\x0et+E\xa9\xb5*\x95Z\xab\xaa\x82I\xfe\xac>\x10\xac\xc1*VuV+\x17\x85\xcf\xca\xa6\xf0Y\xb5)|V\xb1\xdc\x870\x84\xb3X\xdc`[\x11Q2\x00\xe2\xadcF\x9c\xfc\x00\xd6\xd7\xa7\x11Z\xff)\x1a\xa1\xf5uj\x84\x84\xff\xbdM1\xb4\x8eK?}N\xb9O5\x94{\x19\x07p\xcc\xf6\xc9\xda\x81\x16\x9ft%l\xc7\xff!\xc2vn\x85\xe6\x92\x13\xb6%\x1b\xefI\xec=u/\xbby\xf1\x0d\x84\xed3'l\xef\x15\xc2\xc6n\xf5\xf38\x9bG3\xfad\xb1p\x8d\xe6\x7f\xef\xac\xe8~bWt\x1f\xc7\xa5\x83\xed\xb1\xba\xd7\xcecqC\xec\xb5\x13\xdck\x17q\x00\xe7\xd4\x0f\xe0\xe2\xfa\xf6\xda\xc5u\xee\x8a\xf74\x9c|\x86\x11\xdb\x10\xe3\xe6\x86\xb8\xb8\x82+H\xd5\x18?'\xe1\xb4\x89\xcf\xa8\xb7\xa2JRn\xea?\xe4\x89\xd7\xe9\xce\xceC\x1f\xbf\xe7^U\xe6\xbd\x00\x07 \x92\xd0\xe8\xe2\xfe*#_\x11\xf2\xb9\x13\x80\xd8\xa8K\xc3!\xfb\xa5\xc9\xde\xd1\xe8%\xcf\xe6m\xbd(9\xbe\xe5\xfa\xbai\x1d\nM_\xe1L\x82\xbb\x7f\xbb\xd1N\xa00\xc0l\xe0\x01\x02\xb3\xfe\x16\xec\xc0\x80A\xfc1W\x1b\xee\xec\xf8\xf8\x99\x89/\xc0\xcc*E\x1b\xa3\xd8\x90\xfb\x90-X}-\xd8\xa5I\xb4\\\xc5GC0e\xc1i\xe3z(\xf1V\x8d\x8a\xa1\xfcn\xad\xfc\xb9p\xed\xff#\xd6\x8b'\x8d\xc5{\xc2H\x91\x83`\"\xd4\xc9\x98\x1f\xda\xa3\xbe\xcf9\"\xfb\xfa\x959HZ\xa4\x16d\xc0\xf5\xd0m\xd9T\x05o_\x84\x07u\xe0\xd0\x08\xcf\x92gB\x01(\xd1\xc0P\xf5\x18\x8a\xf5o\xa6\xce\x87\x06\x19\xc5;E`\xaci\xfdIm\xfd\xe3\xab\xae\x7f\xd3\xfd\xba\xb1\xfeIke*\x15e\xb3E4!\xde\xc0\xde\xa68\xa6\xba\xb4\xcb\xd0\xd0Q\x1d\xa5\xeb\xca\x05\x83\xeb\xdd\xe9N\xd1Z\xeb\xdd\xa7\x91\xac\xae2\x8b.V\xa6o\x8d\xcf\x16(U\xc3\xa0.x\xc5X\x11;\xd8\x18\x92\xb8\x1c\x99\x8c\xa8|\x16\x8e\x1e\xc5`]\\\xc1b,.\xa2V\xe95h\xb8_{\x95\xa6\xab\x16\xaa\xa2\xa3sZ\x1f}\x99\xa6\xc7\x18\xe3W\x9cLi\xe5d\xc22gQ\x95d\xb1\x83\xe6\xa1\x8fw#\xfb\xe9n_\xc4\xb4\xb6\x88\xd1\x95\xd6\xef\x8fXWa\xba\xb6\x86\xdd\xd4V\x85.\xa9\xa9\xb9R\x10\x14\x0e\xf0L*\xa8\xbd2\x99\x8ea\xc8\xea\xcc\x06\x06=\xd4\xc5\x95\xb5\xa0\"\xee@]\x92\xf2hQ<\xbflH\x11\xf3=\x97\xd6\x10!\xad$\x13Le0H\xac$\x13\xc4o\xd2\x16&\xd0i\xb2n:R\xa7\xd9&z\x1db9S\xed\xd9\x97\xba\x9d\xdc\x8e\x91 \xad^\xff\x92\x9fH\xdb\xe2\x07D\xbf%\xa0\x03\xee\xd9\x8f\xcb`\xb2\xfa\xeag\xc8[je\x1e\xda\xb2\xf3Y3\xf3\xb9D\x05\\\xa0\xd6\x15\x85\x9a!\xbc\xd7H\xef\x87q\x00Otz\xd7\x0fO\x9e\xbe4h^\xdf\xb2\xf7/\x1c\xa4\xfd?\nw\xbd\x96\xfc\xa15\x8f=kF\x99\x92\x19\x8eTN8\xaa;\xeaE%\xfdK\xf9\xaf*upK\x19\xf8\xd9z\xea\x1er=\xc0!\x03\xc8\x1f\xb1\xd7pO14z\xd4..\x16ho4K*\x87\xd3\x08ut\xec\x9f&J\x18!\xa9\xa6\xef\"%o\x1c\xfb\x01\x94.\x93Jh\xc4\xfb\xf5\xf2$Y`\x85\x04\xdb\xf3z[\xb4\x06\x11\xf5\xd7\xdbx\xf4\xa4P/\xbeu\xd1\x06\xbe\xb5i\x03\xdf\xb6i\x03Y\x17\xaam\xed\x8b\x9aE%\x80\xb8\x7fT\x12\xc8\xaf\x01[\xa6X\x97\xfeK\xa4\xc4vH\xf3\xf5\x8cz6V\x04\xc4\x82S\x91\x1b\x97g\xda.\x8f\xf6\xcdFk\xa3\x87\x1acP\xe6{0\x98\xde\xac\xa6m*\xb0GOc\x1a+\x88w\x9b4\x81&G\xf1\x94\\\x90\xe9{\xf2\xc5\x010\n\x89\x7f#\xa2\xce\xddz\xf9\xe9\xbd{\xeb\x08\x1cm*l\x17\xcd\"W\x87pa\x84p\xefn\x1d{!\xa7,\xd2\x94]\xd2I!\x17;\xf6\xde\xa9\xdb\xec:\xbb\xed\xbcI^u\"\xa6\x9d\x9a\xcf\xaa\xb3R >\xce,\xac?/WY\xaa!\xe4\x9c\\ \x052\xae\xee#\xbc\xb86\xd0\xbf\x8a\xb2\x0eK\xbe\"\xd7\xd5/7C\xb8\xf7\xdc\x1b!\xc7r\xb2 \xe3\x9eK\x0f\xa5\xa9\xc3\xb1\xfc\x85Y\xbb\x04\xdb&\xc6\xf2\xba\x9f\xbe\xf2\x12\xc3\xcc\xb91\x8f\x97\xd9e\x94?\xc5\xb0\xc7}\xce\x14\xc2\x01\xe4\x98\x92|\x1fB\xea!\x7f\xd8\x8f2\xc1'J#\xe0\x88\x8e\xb5\x94[\xbd.}wOo\xf5*\x10\xc0\xe2\xf5\xad^\xa6\x8a\x1dP1\x16D\x0d+\x8f\xfd\xabA\xed+\xfb\xb8\xcfD%\x84h\xb4\xebP\xe79)\xed\xad\xb8\x08\xa1\x97\xa0\xc7\xae\x0c\xc4\xcd<\xa5\xd0j\xb3\xde\x96\xbc\xcc\xd9W\xcfD\x95(Q\xfdBW\xd7X^\x92\x92ci\xe9!L\xeaT\x14\xc7\xc4$N\xf9T\xd2S?\x90\xf7f\x8b\x90R\x12{[\xbb\xc2\x12\x83\xdaEM\xd1\x13\xebV\x00\x01\x1c%\xcd\xa8\x13\xba\xc8-\xc4\xfd\xa0\xec\xc0\x87f\x1fJ\x85X\xd86XN\xe4e\x06\xf8%\xaf\x8d\xd6,g\x8b\x0f\xa5\xfaV\xe3\x0e\xed\xc6\x8eH\x8f^\x97\xb4\xc9*\xbbV\xf5 v\x897\x98\xda\x12#k\x0b!4n\x91\x98\xa6Qe\xac.CU\xf4{\xef\xdc\xba9#\xe9\xda\xf1Lq\xe4\x82cK*\xf2\x16.8\x0d\xc0V\xf2\x13\x8a@s\x8e\x03\xbc\xd6\x11~\xa1\x14Z\xe3Z\xa2\xad\x81\x01\xf8uG\x12\xd0\x03\x86\x13]G\xc8\xd4O\xae\x1f\xd4|\x82\x9a\xf0'0\xf5\x19Ok=\xbaT\x8db\xc0d\x9fbNT\xcf`\xde\x00UOz\x80 M\xf4\xe5\xc15\xc3\xe2Z\xa1n\xb0\xa8 KP_q\xeei\x89y\xbb\x89\xaf/S\xa3\x19\x08\xe3@\\6o\xbd\xef\xc2\x92\xc2\xe9!\x1c@\x0f\x19\x1f\xd8\x87^\xd03c2#\xc1=\x8d\x1eU^\xdf\x82\xe96\x1c\x8fE\xa9\xfe\xad\x01\xba\xacn\xa3\xd2\x14\xffE7\xa3-YBJ\x99\x14\xaei\xe1E\x83gN\xaf\xc9Y\x82\xd8\x01N|\xdbg\xb2\xfe\x06\xf2\xf3\xd4iE\x97\x159\xd4\x01\xad\x8a-VM\xd9\xe9\xd4\x19?K;n\xb0\x00\"\xeb\x02\xd7p\xad\xe1\xa0\xf2\x08\xf60?\"\xc3\x14\xd8\xe7\xf9\x90\x1a\xdbAU\x03`\xcdZ\x1b\x01\x84\x03\xf0\"A\xe5\xb09_\xb4K\x8b\xd2\xb7\xbcb`b-\xc8\x9c\xba\x83\xec]t:\xa7\x1d\xe1& \x93\xca\x08\x95\x86(;}\x12\\\x8f0\xbd\xa7F\xbb;\x98\x06\x8d\xbd\xb8\xe3n\x81Tj2\\\xa7\xae\xd0\xb8|E\x0c\xfer\xb5C\x82q#\xddz\xe4yYx\xac\xdc\xbb\x18K\x85\xe9\xb2`\xe8\xbaJ\x9djL\xd4gf\x0c\xc8\x01}?(u\x7f\x03\xad\xf9\xd9\xa9\x97\x93\x9c\xbe\n\xbb\xa8\x07\xf8\xbeF\x0f\x99\xdd\x00v\x06N\xbdD\xd9\xe1rE]l\x0c\xa2\x17\xf5dR\xe4\xf4\xba\xe4\xbe/\x96\xb1\xca\x8c:\xf0\xa2&#\xa4\xd3l&I\x1e\xd7w~\xcb|\x9ex\xb4T%\xf1m/\x04X\xfeq\x07\xbd\n\xf6\xfe\x83+{*\xfaw\xa5R\xa0P\xaa\xaf\xd4\xf3K\x83\x94-\x03\x9eD\x0d\x1d\xf1nc]\xf1{\x917\xc1+\xeb\x94\xf3J\xe2lW\xaa9\x8f\x9d\xa46E\xe6\xd2\xb3\xbb\xf2\xb2\x94R\xc1\xb3@5\xb7\x19*\xe4]\xaa\xe7\xad\xcb\xea\x91/y\xb8\xe8\"l\x9d\xd1\x82l8\xb5/\xb2f:l5\xd5\xe1T\xbf\xb6\x18\xa8\xd5?\xc6ty\x95\xe2L\x94\x96\xf7\xed\x9cb\xb5z\xeb\xcf\xb1_S\xb5Z\xcf$\x0e\xc6A\x0b\x1d3\xc3@\xa2\xa0\x1b\x05\x8e\xaa\x94\xb7\xd5\xfc\xa4P\xb0\x00\x12OG\"\xe5e\x18\x7fgQc\x1ev\x913\x90\x0e\x89\x84\xcbK\x1eC\xb0t\xec\xe5\xa8\x0b\x0d\x97\xfdp\xaf\xd1.=E\xd9\xfb\xfc\xc4\xb1\xc0g!\x03\x0eM>aE\xa5\x14nu\xe6<\xba\xa2\x13r[\xda\xe2<.\x12\xe3t\xc8\xa7\xa5\x9f\xe2\x8a\xf1B]&\xe9\xd9f)`\xa6\xcc\xd2/n\xba\x9fj\x9f\xc9\xfa\xed\xac\xc3\x90\x8aC\x8d1s\x9d y\x0dFB\x1eq\xee~\xc4W\xb42lW?mH\xa9.\xdd.\xba\xab\xd1\x1a%\xbf\xfa\xc8\xcf\xba\xf7\xf7\xf2*\xebb\xe0\xbdq\x8d\xb5\xb9\xac\x9a}/\xc3\x8b\x0e\xbd\xbe$\x9dT\x18\xcb\xf0\xa2\xeb\x99\xfa\xb2\x92\x8f\xc8\xa9\x137\xa3Yc\x06p\x00ob\xee\xc2\xf2\xd5MPZF\xf1\xd5\xa7\xc3\xbb#\xbc;\xd7\xb9\xa5\xa43&jC\x1eA\xdf|\xf69Zu\x80\x9d\xd2\xfe\xeb\x90\xce\xfb\xcb\xf0\xc23T$6tV\x17\xbe]\xa5\x04\xc3\x1ecMzT\xb9\xe3<\x90_\xe7\xd1\xa2\xa3\x99\xa1\x18\xcc\xefW4l|\x8eV\x1fc\x1a-\xbau\xcb\x81.\x87\xdcM\x05\xc5\x13\x82u\xeb\xafi\xe5\xd0d\x06\x03}\x7f4\xfcL:,/\xad\x18 \xae\x80R\xac\xbfkF)\xd6dw\x94b_}\x0bJ]E\x92\xf8\x87\x13w\xab\x940\xfa\x18\xa3\x9a\xb7\x92\xbc\x0d#+[\x18^\xc9NS\xa3vY^L\xa4\x8b\xaa\xb1yJ\x81\x96J\x18\x08vlo\xedL\xd4\xf3o)\xfb_0n\x1a\xc1\x87\xa2J$l\x9b\xa1\xd2L)\xfd\x14\xdf\xde\xbc \xdb\xdb9\n\xa9\xa2AC\xa1ry]\xfa\x01\xe4\xc67.\x03P\xcb \xfd\x17\xadJ\x92vY\x16Z\xf1\xc6b\xdf\xd9\xe5Zv\x85\x16\x8f\x12y\x89q:FY\xaa\x17\xfaN\x85\xc5L\xdb?\x00\xf7\x88G\xf5\xb2F?\xaa\x97!VB\xbd\xa4\xe9&o-N%/\xae\xc3\xaf\x14\xa9\xb2x\xa9\xcaKF4R\x11\xc3\xdb\xfa\x01\xbb2\xe1\xac\xea\xf6\xf6\x04\xdf\x1e\xb4\xb8\xb6\x82n\xafM\x02\xc8P\xe3y\xc0H\xdbp\x08\xef\x84\x98\xf3\x9cad\x86/\xf04\x7f\xa1\xf0\x0c\xf9/X\xdc6\"`\xa5\x00\xda\x87\xdd5\xaf\xec\xe0\xb9*SQ\x1cZ\xdd\x98\n\x19C\xd0\x91/\xed.\x86\xcd\xc3l\xfe4\x99vpt\xa1\xf32\xbb\x00\xd6e\x9a\xab\xd9\x06\xday\x04(\xb6\x17wP\x1e\x0ea\x00\xb7`\xb7\xd8h\x16\xd2%\xcd\xa4\xb3V\x05\x9f\x9b+\x7f*\x8a\xdf\x0e\xf4Uo\x8b\xd7\xf8\xc0\x9c\x16\xbf\xf6\x0d\x1b\xed{\x14\xd2o\xdf\xb9\xbd\xf7`p\xff\xf6\xdd\xdb~P\xdc\x86G\x8f`p\x176@\xe0\xf1\xe3\xc7\xb03\xb8\x1b\xc0\x9d{\x83\xfbw\xee>\xd8\xfd\xbe\xfe\xdem\xe5\xbd\xdb\x01\xdc-\x9fc:w\x8f\xc06\xdc\xbe\x7f\xef\xce\xde\x83\xbd\xc1\x83{\xb0a0\xfd\x17\xdb\xd2\xff\x12\x9f\x0d\xee\x05\xb0\xb7w\xe7\xde\xfd\xbd\xbd\xbbE\xf3\x87\xe2s\xec\xa6x\xf3v\x00\xb7\xf7\xee\xdd\xbbs\xff\xc1\x83\xdd\x07\xbe\xda\x84e\xcby*\x7f\x10c\xad\xcb\x83\x8eP\x83!\xdc\x1e\xc0w\x90\xc26<\x8f\xbd'\x147\xcd\x13\xea\x11\xdfg32w\x0e\x8e\xbbS^\\+~\x85^\xaa\x93r\xe9\xa6\x98\x11v\xd4\xdaA\xb7\xc6\x1d\xdb\xf5\xb5\xe5\xac\xa1 \x88:RX\xb9SW\x06\xb3\xbd\xf8\x9a''Sr\x01\xa8o\xbc\x8eG\x0b\x19\xe0\xfd:\x1e=c\x7f\xbf\x16&\x8b\x8c\xdd\x12\xa1\xa3\xfc\xb6\x08\xac.\xee\xab\x81C0\x84W1>\x89\xe2l\xc5s\xe3\xe3'\xef\x93<\xad\xe6\x95\xd1\x81\xac\xa6D\x12\xee\xad\xd5\xd9a\xeb\x93y\x18\xc5\xbcma\xcb\xe4\xb7\x93\x98\x86\x11F\xa5\xe3\x10\xb8\xee\x12c\xc4S\xdd)9[D\x1dB#\x0b\x01\xe5+1\xae\x84N\xed\xb3:l\xb8\xf7\xbbZ\xff\xcdT15\xcb\x02V\xe1\xae\x93a\xb5\x90&\xa4\x93\xc4( \x1a\x9b\x8bO\x03p\xa3\xaab\x93t\x14\x1a\x97\xe1\xeae\xd5\x07\xd9\x15FW\x00\x02[\xf7:,\xda\xc4\x8c\x06,x4\x82\x05\x08\xd8\xc9Uv\xeb\x87\x18\x93\x9b\xb4f\xeexj\x06\x92<\xd5\xaa}\x19\xda\xf9\xb9\xb5\x9d\x11 \x80\x8e\x9d\x1a{g \x87\xf5\xb3\xb9e\xb3mQ\x97d\\\xd0\x84\xa7aXo\xaegX;\xd7<\xacW\xf6a\xf52\xa4\x81\x15\xe3\x07\x1c\xc0O\xef\xdf\xbe\xe9\xf3G\xd1l\xcd\xd5\xb6\x82Z:\xe6\x16}f%\xc0\x87\xc6L\x9e\x86\xe6\xbe\xb6b\x10\x85G\x05\x07G\xe11\xfe\xbd\x83\xec\x9cS\x07\xcf\x1d:`\xac\xcf6\xec\xdd\xbb{\xe7\xce\xed\xbb\xdf\xdf{\x00\xdb\xe0Q\xc6\x90\xdd\xf3\xf9\x9f\x8f\x1f\xc3^\xf3\xf4\xad.\x94h\xedCT\xaf\xc2h`\x95\xcb\xe5\x95|\xb3\xad\xaeu@J\x1b\xdeV\x82\xa5\x00\xf8\xba\xf2\xd0R&\xa2G\xbe\xaf$-\xc5f\xc5}k\xcb\x97\xac\xf7\xc0\x96GC\x85\xa8\xdel\xe7\x0c\xd2\x80[\xee*1~\xd8\x7f\xeb\xe4\xdd\xed\xa1W\xb0\x9f\x15\x90\x8d\x18ds\xf8\x1f&;\xb0\xad\xc7p \xa9\xb8\x00c\xcc\xef>\x7f\x07\x0e\xe09\x9b{\xce\xd3\x91\xa2\xd5F\xfe\x8cd\xca\xd86\xf0[\xad%\x86T\xe5%\x95p\xde\xc6\x0b\x12\x9e\xb9p^\xd2,7b]\x8c5\x87\xb2oY,\xb6/op\x02 \xf5/\x01\xdc\xe8'3t\xa65~\xc6\xf3\x93(\xde\xf9\xd6s\x96\x14\x1b\xdf+\x88\x81\xb8\xc7\xe8\x80\xc8H\x13\x94\x94\xc8\xcd\xc7\xa9\xab\xcb\xdd\x92z\xbbj\xcaj\x97>\xae\xe0_\xc7\x0e|\xc7\x08\xd5\xebv\xefq<\xf9\xbf^I\xafzC\xfe\xf1,\x0el\xc8\xe6<\x86_#:w9\xa7\xa4\xcc\xa3\xf6b\xc77\xc6\xd3\xc9\x00\x81\xe6\xf8M&\xcb\xca\x9dK\x9fQ\x842=\xec\\\xea\x1b\xd4\x9bE\xdd\x96#t\\o\x0e\xbf3\x8f\x85\x18\xc4kA\x0b\xb3\xb2\x93\x9cv\xd5|:\x9a\xaa\xd3p=\x9b\x0d\x9b/s\xb89@;Q\xf2l\xf3\x12\xda\x15+\x81\xfaX\xb1$\xa8\xb7+&\x85\x17\x81\xaa\xa4\xf5\xf1\xde\x8d\xca\xf2\xf1{?V\x9a\xe6\xf7N\xa8\xe6\xe3s\xaa\xf9\xfa\x82\xd6?oBE\xe6\x97\xdb\x87\xb8 W\x04\xea\xcb\xe6\xfd\xa7\xc9bA\x10\xd2\xfbp\xac)\x90\x81\x01b_5\x0f\xd4\xb4\x92G\x1a\xe7 \x9e\x97o\xa5y\"R\x05^hGI\xf7!\xd3\xe5{\xbb\xbb\xd3O\x9f\xf2\xe9\xfd\xdd\xdd\x1d\xf6\xefl6\xfb\xf4)\xdf\xbd\xcd\x7f\xee\xde\xbe\xc7~\xce\xc8\x1e\xfe\x9c\x91\xbd\x19~3\xc5\x9f{\xbb3\xfet\x97\xf0\x7ffc\xd3\xe0\xcc\x14\xad\x100(\xc9\xa8J\xc7.\xbb\xc1i\xb0\xfb\xa0\xc6\xeb0.\xb2wx\xb1\"\x13J\xa6\x10\x16\xed\xf4\x14c\x8f\xbc\x07\x89\x96\xb0G3\xf0\x94\xf8\x88-\xc5D\xb0\xd9\xc8\xecA\x1cE\xb4\xaf\x11\x1f\xe8\x9e\x864<>\x16\xd9F\x9bX\xa9h\xf1\x84\x14[\x83\x0c\xbb&\x9a\x1aTQP\xb9]\x14\x82M\xaa\xf7yQ\xc4\xbcz\x933\xc4a\xf5f\x86ofUB4\xe9\xb6:\xb7\x1f\xe8\x97\xe7\xce\x83\x96\xe3\x18\xa8\xc8\xcb\xc1Co\x1b\x8e\xeb\xca\xe6\x15\xc6\x0eOT\xe6\x04R\x9c\x80\xf2\xd1V\xc4\xb8\xab\x9b7\xd9\x1f\xb1\x8fJay8\xc6\xec\xaf\x98\x1dA\x95\xfe(\xeb\xf2\xca'\xfe\xed\x07\xb7\xb5\xb3\x1e|_G>\x81\x94\x0f\xeei\x90r\xd0\xc4\xc7\xbd6\xd2!k\xb9pG\xe1\x99\x0e\x15\x17\x98\xb5\xf8&\xe4\xcd\x03\x17\x0b\xb2\xca\xb2\x8c\x8d\xa7s\xc4H\x9dY\x8a\x11\xa8\x15\x03\xe4\x1c\x81\xec-\xd8?sx\x0c+;]F\x9d!\x0f\xd0\xf5\x9b-bAK\xfeX\xa9-6\xc5%n\xb6u\x06C\xd8\x194G\xbd\xe62t\xe3\xfe\xa9\x00C\x08\x07|'\x82\xf4\x8e\xae\xb6\x8dy\x01fx\xfc#\xa9\x0f\x80\xff \xbc\x06\xe8\xf6\xf6\x19<\x82\x956\x11\x00\x1b\xd6\x92\x81ttf\xe0n\x8e\xb1(\xcc\x99\xc6Q\x9c\x01 \xf3\xb1\x89\x13\x18\xc2\x02\x0e \xf3\x8e\x03X\x06p\xc6\x03\x91py\xf7!\xf3\x96\x01\x1c\xe3]\xbe\xfa3\x0d?SK\xe2{b\x92\xae\xd9{'>0\x018\x8aM)\x0b\x10\xa2\x03\xfd\xb3\x93\x94\x84\x9f\x1bO\x9a\xe7\n\xeb\xe8\xd46\n\xb6e;\xd8\x0c\xf0\x93\xc4;\xc5\xd7n\xde\x04oY\xe6\x8c\x9e0\x08Q\xb9-f~\x89K\xa7<\x16\xdf\x18\xdel\xeb\xd1\x06\x050B\x02\xb4\xd0\xb8\x04\xb2\xc8\x08Nb\x89\x0bt\x8c\xfbh\"\x96\xb6\x18\xb8a8\xdf\xba \xda\x13y&N\x10t\xba-~0\xfc_\xff\x9f\xea\x876n\xc8H\xa5\xeas\xa9\xd4_\xdb\x11 /%\x11\xa7\x98&o\xbf\xa0Ml\xdb\xc5\xf0\x08\xd2\x87\xcd\x95C\xd3\xb8GG\xf1\x18\x01\xa7r\x86\xbbZ\xfeOI\xef\xd4\x91\xcc\xdf\x19\xd4y\x83\xe2pkRyQ\x91\xa98^\x9b\xf4\x1e%\x19\xa5\\S\x93\xfc\xa3*\x08\x9f\x1de\x87q\xbe\xe4\x8a\x9f&{\x92\xda\xad\x1db\xe2\x85\xb8VE\x06\xcf\xf7\x85 \xde\xae\xec\x13\xad0\xe6\x9bak.X\xcc\x00z\xec\x0fBz\xfc\xc4\x0d\x9b\xf7\xab\xfd\xe9\x8f\xb4\xcce),\x99\xf2\x15\x06Qch\x10\xeb4\x18h\x9e%m*\x97-\xd2\x8f\x93)aB3\xdek6\x81\xab\x89\xa2w\xb3\x1d\xca\x8d\xd4\xac\x1dZiG\xa3sbk\x9es\xe0\x16\x90A\xc1\xe4\x00\xd2\xfe\x0f\xf9lF\xcaS\xab\xf95\x03\xa3\xc7\x8e\xb7\xb0\x1fe\xb5\xb7Q\x8a\x8d\xccJ\"E\xe2\xa9(\x89\xee\x0f\xfc\xc2X\xdc}\xdf\x1b\x988\xda?''\xabp\xf2\xf9\xe7d\xb1\x9eE\x8b\x05\x0fY\xe9O\xc9*%\x93Z\xedG&O0\x96t\x15\xd29k}4\xc6L\xf1\xf3h1MI,\xbe,~\xb2\xe7e\xb9\xb4)\x99E1\x91\xfb\x0bqr\x91\x84S2\xed\xe9\x14\xab\xa4\xd8a\xfbz\x0e\xa2K\xd1\x19\xda_4\x1e7\x95\xd4\xe6qF\x7f\xc9\x18#\x8716Wk\x08\x83J\x02\x9b\xced\xd4 #\x0c\xea\\t\"\xee\xdf\xd1p\xcb\xb8\xdf\x92~\x94\xb1\xfd4\xe5Q\n\x95\x97\xf8f:\x80\xc8\xcbQ\xe5\xa4\xa7;a\xb7\xb1\xdf\xdd\xbd\xaaZ\x91\xf2\x83\x8d\xd1\x81\xb4]\xb9\xd8\xbe\xb74g\xaa<\xc9\xe5;Z\x87\x17\xa9!\x10\xfa\x05\x91E\x90\x8e\x85;_\xcd\xdf\x84p\x8f\x92H\x16'\xf4\xe2\x9a\xa9\xeb\xf2\xaaX0\xb8_\x97\x818\x16|\x7f\xbf\x15\xc2m\xec\xc4.\xf72\xf0\xb8\x1a\x88\x07\xf1\x17\x9cD\xa1X\xe1\xd2\xe0#H\x1e\xfa<\x85\xe8(\xf2\xc8(\xde\xde\x1e\xfbc\xbdv\x8f\x7f!\x082-h\xebU!\xa0\xd7\xd9\x0d\x1a\xd8.v\xc1^\xfd`\xe3\x8a\x8c;\xdf_\x05^bJii\x18\x8c\xc4{\x07\xc0\x90a\x1f\x12/\xaf\xb8 9M\xae\x97g\x042\x9aF\x13\xaa\xa8\xf6*^X\x0d?\x11\xe9j\x13{\xdf?\xa8\xebF\x94\xe9\x1c7E@&\xbas\x98\xdd\xfb\xbe\xf6\xe5q\xff\x1d \xa7\x8cN\xbe\xa7\xfc@YV_`\x80\xbe\xeb\xf7\x0f\xcfHL\x0f\x97\x11\xa5$mv\x10\xb6\x81Q^%\xd1\x8f2Jb\x92b\xd1M\x8er\x8d\x0ft\x96{\xb1%\xea(\x01\"\xb88\xf6\xee\xef\xfa\x82\x03h\xbe1CA\xfdc\x14\xd3\xfbH\x07\xd9\x9e\xad\x9c\x9f\xcd\x99-85\x1b\xd4\xc0\xb6\xe8G\xf1\x9c\xa4\x11\x15J\xaf\xbb\x1a\xf3\xc0\x8a\xa3\xdd\xdd:\xb1\x06\xa12\xd0 \xd5\xec\xfe\x8am\x9fU\x7fJN\xf2\xd3Er\n\x07\xca\x0f\xaf\x97\xd1\x94\x84\xcb\x9e\x0f\xfbmC\x9f\x06(\xfb\xb3!\xd4w\n\x08\xe1\x88\x81\xb2\x8eK\xe5\xd4\x98X]7\xf9\xb3\x86O\x19\xf7\xd0#i\x9a\xa4=\xc6\xbd.\x92\x8c\xb0?\xa6$\xa3i\xb2f\x7f\xae\xc2\x9c\xdfKI\x96/Iol\x8a\xd6Y\x1a\xd1%\x01\xa1i\x8e\xbd\xbd\x81\xa8a\x81b\xab\xae\xbe\xa0$\x16\x04\xa28\xa3a\x94w\x86\xe5S\xdf\x0f \x13j\x85F\xb6?\x13 OJ\xe5\xb8)\xdaS\xe1!h\x0d\"M\xb0 \xdd\x147i{ym\x8f9q \xa8\xaa\xe2{X\xae\x93^\x89\xc7_\x14xfSJ\x9e\x15\xc5\xdd\xc4\xcb\xacu[*\x15\xce\xc3J\xaa\xc4\xa0N\x04\xdd\xe2\xaa\xd1\xd8\x0f\n\x9d?l\xb3\x86\xab\xd4\x17\xf6\x8b\xaf\x0dJT\xed]RR\xae\xdd\x00\x0e\xb5\x86I\x06\xba\x1c\xeb,zH\xb3\x11\xdf\x9d\xe0\x8aP\xd0\xcf9\xe5Uy&\x85F\xc4KQ\x15\x92\xaa\xdbf\x86\x94\xa6\x19}I\x94\xb8\x83a!\x0c\xd5NK\xcc\x12\\u\xaa\xe8\x1d\xc5g\xe1\"\x9aB\x9c\xc4;\xbc\xd9[\xe2p\x98\xcc\xf3\xf8s\xcf\xb7\xc5\xd3\x18&\"\xb6\xb5\x06n9: \x06\\*A\x02\xee\x15\\L\xc2\xe0\x99\xd7\x86,\x1c\x89\xc4*?\xc6\xc8\x1f\xcf4\xff\xfa\xc7e\xa5\xf9\x9f\xa5j\xf3\xed\xcc#<]\xb1bND\xd8\x10\xa7\xe4#bn\x13\x0c%\xd7\xe3\x06N0e\xa7\xb4z\xe45\xe7\xcb\x16B,\x02\xe7(\xfby\x9c\xcd\xa3\x19\xf5|\x08g\x94\xa4@\xe2)\x10\xc6\xf5\xf7\x10\xd7\xce\x11\xedd:;\x04\x16GU\x97\xb6q\xcb\xc8\x86\x0f\xdf>\xe7M6\x88C^\x1c\x19L\xfa\x8f\x19\xb4 &>\x92\x9b\xf6<\x8d\x84\xae\xbd\x0em!\x85\xcb\xb5:\xa8\x8cw\xc0z{[\xee\x9b\xea3\x9fW\x8fb\xcbP\x1d\x90\x0e\xfb\xea\xaa\x83\xb6\xb5\xda\xa2\x02LH\xb8\xab\xdc\x04n\x92\xa2HV\x8d9,\x99.j\xa4#\x97^\xeeF\xe3\xcf\x15\x1a\xaf\x1b0)\xb8\xa8\x9b7\xe5\x1eVh\xdf\x16\xe1l\xd1\x01\x9b\x02_\xebiHC\xb6\xd4\xa8\xf7b@\xf3v\xf9\x9a:\x12E\x8e\xa4\x05M\x95\xc8\x17\xb36t\x94\xb6\x02\xb8\xff?{\xff\xbe\xdc6\x924\n\xe2\xff\x7fO\x91\xc2o\xc6\x03|\x84h\x92\xba\xd8\xa6M\xeb\x93e\xb9\xc7\xd3\xed\xcbH\xb6\xbb{\xd8\xfa\xa9!\xb2H\xa2\x05\x02l\\(\xab\xc7:\xd1gw\xcf^#\xf6\x01\xf6\x9f=o\xb0O\xb0\xb1\x11\xe7MN\xef\x03\xec+lTV\x15P(T\x01\xa0,\xf7\xec9\xdf\x87\x88nS\xa8B]\xb2\xb2\xb22\xb3\xf2r\xef\x1e\x92F\xc7e\x8bJL\x9a\x16\xfa\xe85\x87\xe7\xd2}C.\xb8\x18\xd4\x9d\x1b\xa9\nU\x17$\x85\x7f\xb8wO\xf7\xba\xe0\xfc\xaaK\xac\x91\x81\xdb\x05\x0c6to\xd7\xf6OO\xf86F\xc3\xe7%\x83\n\xc1\x88\\\x8b\xdf\xe5\n\xe7Y(\xd7\xc9\xffRj\x15u\x1a\x0f3&\x0d vdA@\x11D\xe3\x06.7N\xeb\xb6ix]\x8es\xdf\xc8\xec\x08\xf5P\x19\xd1C\x91\xebN\x1b\xa9\x80.\x02\xd25f\xf1\xa6r\xf3,Hv\\f\xb8\xa9\xc0#\xc8>\xbbl'\x98\x99\xd1qyg\x8eK\x19\xb9\x92SB\xc5\x9fC\x81 \xdfs\x8d'\x0f\x9f\xa3\xd4<\x93 (\x87\xa2z\xc4+]\xf8\xc9[/K\xca.P5]l\xf5\x8b\x94_\n\x86r\xfaT\xd7YBd)\xa9\xd5\x9c\xda\xc91\x95\xcd\xa2\x885\x86z\xb2p\xc3j\x94G_U\xac|\x84\x11<\xdcy\xf8p\xbf\xf7\xd0\xa4/95\xa2n\xae>\x7f2b\xfe\x8dU:N\xf2#\xbb\x87d\xb6B\x9dS\xa6\xf0=(\x1f\x08\xd2\xa9\x9a\x93\xe6\x05\xf1\xa6]z\x08\x88\xb2aQm\x88a%\x80(\x07\x1ac\xa2U\x8dA3!\xcb'\xf6t\x04\x1fQ K\xff\xa5\x9dloSY\xeb\x13\x1d2F\xf7*\xfd5(\xfd\xb5[\xfa\xeba\xf9\xbb}\x17\xd2NG\x9bk\xe0\x86\x9d3\x08U \x0e\xe8!\x92CS\x9e9\xa9h\x0cz\x98\x9f\xb9\xd59}\xac\x87Bn(\xd7H\x8f\xaa\xbd\xf7\xe9\xe9\xa9*+(\xd6/l\x8b\xbe\x16\xef,\xb7XtG\xf7\x0d\x9bI\xce \xb0|\x1f\xef\xfc\xc9\xa5}\xc8#/\x1eV\xdceM\xf3<\xd4\xcf\x93\x0f \xc4$-\xe4.\x18\xc3!\xbf{\xd56\xa0\xcb\x1b\xe3n!%}\x08\xb2\xe0\xaa\x86\x04\x9d\x8e\xf2I\xfe\xa4u`2u\xfc\x93\xb1\xe3\xd2\x05Ln5FY,\xc1z2\x86K\xda\x7f[\xa4\xe0!I\xc10\xea\xf6\xd7\xc2\xb6\x96\xde\xf5\x05\xa1\xab\x86\xf3@\xf5B\xcf\x92\xd94\x17m\xfb\x8a\xce\x9d\xc7Ny0\x0d\xc0\x1a\xa9\x89\xbfL@\xb84\xaer\xae/\xa1\xe0M\xfd\xc9\xa5n\x9c\xad\xfax\xd9\xbc\xc2\x02\xdb\x99\xe6M\xd7\x13\xe2\xbb^1G\xaa\xca\xb4\x1c!Q\xb3\xcd\xd1\xd1\x05u\xc9\xa4\xe5\xdclJ\xaf>\x97\x08 \x8a-l\x8b\x8e\xa7\xb4\xad\x1f\x97\x07\x99\xa7R\xe6\xe3s\x1e+\x02\x8fi\x84\xef\x9a\x0e!\xe5\xe89`]!u\xac0J\xf9\x91\"\xc4\xcf!l\xa5\xec6\xf5i\xa9\x0d\xbb\xa4\xc0\x91\x0f\xa3\x9f\"?\xb4-\xbc\x13\xe9\xf3\x9eyI\xcd\xc1%\x0b\x1a\xdc\x9f\x92\x14>\xb1EQ@\xbc\xd8F\xd9&\xd4X\x94\xd6\xa9Z\x0c\x1a\x8a\x94\xed]\xf5\x00=\x00Lu$\x97H\x91B\\\xb9@[-u\xf2,\xc8\x1c\x06\x9a.\x88\x04\xe5p\x93\xf0\x96\x05\xc5\xa2\xad\xea/\"\xc4\x13Wmt\xd5\x07\xef1qlf\x15\\\n\xdb#\xf0\x8dDI<\x88\xed\x8f\x81\xc5r\xa4\xf4\xa46\xf7\x14\x08uf>\x80\xfa\x81\x82\xb8\x91\x81\xa7\x10\x15p\x8c\x8a\x13\xbf!\xb2\xb2?\x03;c\xd6I\xc5\xe7>\x95\x8e#\x18\xf2\x1f\xe5\x85f\x9b\xc7\xc6\xe9g\xb5\xa6\x96\xe2\xa9\xb4ow:\xb1\xcb\xc1\x81\xab\xbe`Zf\xfefX\xbc!\xdd\xd4\xf3\x03\xae\xe7\xe7\x02\xbc\xa8\xecr\x08A1\xc4\xcc\xa4\x91\x93\x1f\xb3\x85\xa7xn:\x1d}xc0jFA\xb2m\x17\x13\xddFw\xa0\xaam\x0e\x085)q6\x89\xab*p|\xd2\xf5\x82 \x9a\xbc\x0f\x13oF\xdaE\xe1m\xb1+(\xca\xd7\x98\xc5\xc6l\xa7N\xa2\xd55\xaa\xde\x04\xe7c\x97\x83\xe4\x8b\xe0\xbc\x1eSaS\x9c\xf7k\xc2]\xb8M\xc1\x974\xb9\xee\xf0+~\xde\xb9\xc5 K\x19E\xc3ev\xb9{\x13\x9bp\xf4\xb9\x8c\x0c\xbb\xde\xe1\x13\x7f\n=\xd95\x93)\x98\xffd\x910\x17Ql\xc7\x024\xa5\x9dB\x14\xe2\x9d\x02Y\xae\xd2k`J\xe8?i\xe6Bd%9\x13\x02\xe4\xfb\x17\x89\xfd\x7f\xabMrb\x8c\x1dj\xd6\\)=rU\xa1\x98$\xb3\xd2,_V\xf7\\\xce\xcbVD:\x9b\xce\xdej9\xa6\x93v\"I\x8fk\xbfr\xc9\x84\xd9\x93C\xd8\xe9\xe8/\xb20\x1a\xfa8\xe4vq\xc5\xbd\xaaQY\xb6\xadJ\x0f\xf2_\xb2B'f{\xb2^C\xc0\xa5 \x8b\x9d\x9d)\x8c`\xe5\xc5 y\x19\xa2[J_\x17\"e]\xf2;+\xe1\xa0\x9e\x12b\xa43=z\xf2\xf5\xe3\xca\x0d\x9dQ@N\xdd\x98\xffyE\x93-a\xf8\xa8\"\xd3}\xfa$\xd4\x0c\xc5\x8d5\x9f\xf1\x10*\xe2;k\xc7\xcd?qku@G\xec\x92\x18\x86pl\xf3\xcblJ\x10M\xf3\xe4\x04z$TP\x8e\xd4\x9ac`\xfc\xef\xdd\x13\xbd\x98\xdaF>\x99\xa5\x13-\x83\xc6\x88>\x0b\xdb\xa2\xf5\n%\x01\xe6\x15\x11#$\xd2N\"\xd2IS\x95\x97q\xfc\x0b\xdb\xe2u\x02\x92$\x90.\xbc\x10\xaeh\x8d\xa5\x17_Zl\\\xa8\\\x15`\xc3f\x85hw \xd6\x82\xfe\x11\xe1\x95\x19\xde!\xf8l\xe1\x91\xbf\xe3R\xf94\xc2\x01[\x8e+}_R\xa9pMQ\x05\x80:\x8dRI\xe3\xa8*\xd5\x1c\xb9\xc9\xbe\xab\x08\xc2l\x05C\\A\xbe*lic~\xc4\xf7\xe0 \x17\xf0\x86\xfc\x88<0\xe8\xb5\xd0\x0e\xc7\x91u\x7f\xdb\xa8\xec\xd4\xce\"\x07\xa0aFa\xb1\x95$\x85\x07\xc7\x1f1T\xd4\x8d\xe7\xd7(\xa5\xbb\xa8\xb8\x92w\\Q\x10\x9f\xb7\"(R\xc3\x9a\x0bM\x06q\x07\xfc\x04\xc2(\x05\x7f\xb9\n\xc8\x92\x84)\xa9\xd2a\xe5\x06\xc2_\x91\xd67\x10\xb5\x01\xd5\xa2\xb6\x97\x13\xc9\x95\x8f\xae\xc6\x91d8eb\xad&^B\xa07\xd4\x96\x01:\xe0\x0b{\xac\x1af\x0f\x99 }1\xb6\xdfo\xd3\xfe\x98\xfft!\xad\xc9\x13S\xd3\x15\xbfOi\xec\x8b] 5^wI_0\xd3\xb3\x0e\x95n\xe9\xce\xc7%\xc5 \xa0\xa3?N!Z\xa5\xc9\xe8\x8f?Yn\xa9\xb6\x9e\x1f\xa3\x8b\x8c^([\xcc\x90\xb0\xcf\x15r$\x9c\"YJ\xf9\x1dP\x92N\xa3,U\xde\x908\xa6\x92;\x0c\xe1\\\xb9%\x80\xb2\xc3\xb5\xce\x88X<\x0b\xdb\x8a\xc2,\xa4\x03\xb5\xd8m\x92\x08\x88\xca.\xdf\x99\x1e%\xee.\xbc\xe4=\xd6b7\xd8\xa5\x17\x8c\x06,lk\x12\x10/\xccVB\xa7\xb6\x8c\xd6\xdc\xf6\x8d\xc4vn\x1e:\xd7\x96\xce\xfc\xd0O\x16\x96\x0bKm\xf14\xf6\xfc\xd0r!\xd0\x96\x8a\xfdy\xad-\xe5\xb3saB\x89G\xf5\xe3\x90\x92\xeaYM\xd9\xb9\xb6\x8cS\x9b\xb5\xe3\xa2\x85/\xde\x82E\xb2\x96\x10\xaf\xf5\xcf\xafb?-]\xbcn\xa9/\x91\x08\xe6\x9f\x04\xfa\xa8\xf8\xe6\xf5\x9d\x19\xaf\xa2qm\x913d\x86{\xd3\xc68P\x808^2\x18\x91x_\xe4\x11\xc2n\x14N\x88\x00\x0dZ\xbeu\xa3\xb0\x04e=\x9e\x07\x8d\x14\x174v\x15Mrz;\x01B<|\xb3\xbe \x9fs|\x92\xd5\xba\x8e\xa2\xe5\xc5\xf3\xa7\xf8{{\xbb8\xcf\xca\xb58\xfc\x8c+\x8cQ1m\x886~(h\xc1\x7fc\xeb\x84-\x06\xe3b\x17\xe8A\x8cx\xa8\xd1-\xac\xb9+9-3#\xd2\xda\x9c\xab\x171\x89M\xd0\x05\xa1\x12\xe7\xd4*\xcd\xadq(\xfa\xb2\x83\xdd\xees\xa9\\\"\x97\xe8}\xc4\x89\xbb\xf0<.Ux\n}Z\x89\x87_=\xb1\x0b\xfa\xcf\xe3t\xae\x04\x135\xf3\x82\x84\x00v\x0b1IVQ\x98\x10\x17\x84\xady\xa8^\xc0\x96\x96\xb8\xa6\xb4\xd3\xe1\x93C.\xa4\x8b\xedm\xba\x1b\xaf\x1b\x80(H\x15q\\8\xb7\x1b\xa9\x19C8\x86`\xec=;\x17\x14\xc6D\x17L\xb1f\x90s\xe3\xb6j \xcc\xe7Z\nb\xeehYO\x9bx\xdb\x8d\xc7\xc5\xa6\xdd\x9e\xd7u[\x1cva\x97\xfdnw\xf6\x0by\x96\xed\xc4\x9c\xf8k\xbbi{;\x00P T%\x1b\xfb\xaeb\xb2\"\xe1T\x00\xa5\x08P\xae\x96\xb0h\xcd5*\xf4\xee9\x9a\xf0%\x0cy\xf8\x1fcr\x06\x07\x90\xd9\xf2\x0b\xf4n\x92\xfe.[d\x95>\x1d\xc18tK\xaf\xce\xb0\x8a\x08\x1e\xad'x\x12*\x8b\x03\x9b\x1d(e\xfe\x80\xbdS\xb8\x02\x86\xf4\xfc\x9c 1f\xa1 \xb4\xfcn\x0fY\xb1\xe2F.\xe4\xb7y\xb6S\xb9\xd4\xaf\x18\xc1T\x18\xf3Z\x9d\xd5&*\x03\xf3\xda\x17L\xd4P\xbdL\x15\x8f\xc6\xc9\xa5\x90\xc3I\x89\xa3\x17\xd8\xa1\x0d_O?\xea\xd7|T0\x97\xbc\x9c\x07\xccfV\x1cBb\xe4exT\x96\x1d3H\xc5+\xa3t\n\xf6\xb95\xbcX\xc4\x9c]Hy\xc4YnH\xaf\x1f\xf8Vmp\xd2\xb8\x18\x98Y\x83\xedCy\xe6\xfa\xcd\xb2\xe9\xac\xf4\xad\xe4\x8a4\x16\xe7\x1a\"x\x02\xfec\x88:\x1d\x07\xe2qtf\x82A\xad\xc2\xb6b8\x04Z2\xb5\xe61\xdcNlR\x9c\x9f5:8D\x89LZl\xfeY\x97eg\xb03\x17\x9d\x97K\x80\xd8F\xc9\xa7\x8aM\x9c\xf9\x11 \xe4\xbf\xc6\xbd3i\xf7\x9a\x16\xbensF\x95\x1b\xd7:\x899)}Y\xb8Ap\xc3\x0d=\x861\x8a\xce8\x13'gm\xcc\x06h\xb9\xeaA\x10\x18\x8dRY\x84,)lVD\xfb\xf5\xb8\xdcJ\xa8\x07\xbc+*+\x91c\x8d\xcb\x11\xdd\xb9\xba\xf7\xecB\xa4\xa2\xc9\x89\x0d\x0eM\xb1\xa4\xec\x8a%}\xceq\xae<\x94\x04\x85K\xbe\xa6\x9b\x1c\xabu\xeb\xefM\xf3\x93\x0eF\nf\xb8\x8a\xaa\x18m;Z\xc4cL\xdb\x02:?s\x95\xa3\xa68eR\x85\xddo\xc4T\xe0f)eC\x13a|T1?)\xdf@\xbc4GP.\xa2\x9c\xeb\xec\x0c\x15=\x14\xe5n\x9b\x00U\xa8Z\xe9.b\x1c6\xf0\xc92\x1dG\xcd\x16q\xdc\x96\xfb\x08\x0fnd\xde\x0d\x16\x94\xca9R(\xe6\xf8W-\xa6{\x15{\xab\x8dN\xf7\x9a\x1b\x80\xb6g\x7fl8\"\xf2\xe3\xc1\x07?\xe4\xa2\x1d\xd7B4\x89\xbd\x94\x9c,l\x8b\xcefE\xa6\xc0\x85\xfb\xb0\xec/!t\xf1\xf5\x92s\xca,\x1f\xda\xb9A\xf1\xb3[\xbe>0i\xcd\xc0x\x8dI$S\xed*\xf2\xe6\x9a\x04\xce[\xe7\xb00&\x1e\x94!!\x84\xd3\x12(l\xbf4G&\xa7\xfa\x14]\xb6B\xc5o$W*\xa3\xa6^\xb2\xde\xf7\x99Ho\xab\x1f`=a\x95\"\xc4~\x9c\x9f\xef0\xa2+t\xe3\xb9 \xa9\xdb\xb2\x0e\xdaLJ>S\x14\xbb\xc6\xfe\x19\x94\xe3\xd2JR\x01/\xb4EE \xa9\x9b\xdc\xed\x1b\xd1K\xaa\x9bR\xe6\x9f\x87\x81\xadM\xe5\x07\x065\x86\xaf\xbb.\xd7qF\xf3\xfc\x8a\x11\x19$D\x82\xf98:\x93vz\xf7\xc2\x0f\xa7\x9c\xba\xd1\xa2\x1a\x8f\x9cT\xf6\xa6l\x86\x8c\x84B\xe7\xfc\xfe\x908\xc2\xfb;\x16\x14\xa7\x10#\xaa\x13\xd5\xd3\x9e6\xee&\x82\x84\x94|\xbb\x9b\xa3\xd8hL\xaa6rM\xd1Q\xd8\xd2\xc5Qu\x8e\xe5\xd9\xa1\xdf\xc7\xf9,\x8e\x96\xf4T\x86\x11\xbc\xfb\xa7\xa2\xac\x1c1\xdb\xc50\xd8\xed\x02g\x97bpW\xa3M\xb4iB\x1fNc]\x84\xbaz\xa4\x8dI\xeakO\xea\x1a%\xcb\x8dv\xd0\xe5\xcf\xb9\x1bK\x0b\xbb\xa3[_\xf5@\x93\x1bQMd\x01\xfc\xac\xa2\x9c\xd6\xbc.Z3\xee9t\xb2\xce\x98\x9b\xde\x01\xfa\xe0\x14\xc6\x9b\xed\xfbA8\x97\xb8\xd9\x9c\xe7\xf1\x85\xb8 |,\xd0Z\xc7\x00\x91F\xcf&\xe9\xde\xb420\xbb\x16\x02\xe5\x8f\xf9k;\x8f(\xee\xb6Ppo\xf1$\\\x07\x94-\x97'\x18\xb2\xd9\x85\xbaA\xa9/\xcb\xb0\xc2A\xe1\xed+\x9e\xccZu\x96A\xcc*\xfd\x99;d5\xd0\x92[\xc3\xbd\xafg\xef\xe2j\xf4\x85\x8a\x0b\xcd\xb4\xb6\x05%\xaa\xc3\xe7,o_\xfb\xadf\x04\x95ru\n\xe5\nL\x95U\xdf\x86\xb2\xa8\xaaO\x95B~>?\xf6\x9f\xec\xa4\xc8\xb0\x12#H\x84\xec\xd4\x9a\xca\xe1\xf0\x13\x12\xcch\x15\xfc\xf7\xd3'\xb8\xf2\xc3itU\xa5/\xbe>\xb272\x12&_&}\x00\x7f\xc81\xcd\x9f\x16\xaeS\xdds4\xc4~\x816\xc8\x06\xf0\x00\xf2\x9a I\xdf\xf9K\x12eiK)'$W\x10\xd9>;\xc0\x8a\xaf1\x1cB\xc1\xff\xb8\x80\x03\xe0\x85\x15\xb5\x05\xf6\xfb2LI\xbc\xf6\x82[v,>\xd7\xf7,J5]\xcb#C\xfdK\xe9\x83F\xf1\x873\xf9\xa8\x88\xad&\x96\x8fJ\xda\xd2\x98\xcc\x94\xec/\xec\x8d<_\xe5#l\xb7 $\xa55f\x10\x89\xdd\x1c\x0f4s&a\x1c\x05A\x1b\xfd\x90\x0c\x1d;\xa5\xcd\x05\x84\xff\xf9r\x8a\xd2\x87\xfc\xaa\x8a_\xb4\xb7,\xd4\xf4w'\x9d\xa9\xd6p\xb4\xb7s\x84\xf3\xe1$\xf5\xd7\xe8'\xda\xf5\xc4\xcf\xcf\xe9\\\x7f?\xc8/R\xa5\xaa\x1a\x8dV\x91bQm\x15FPl\x99\xe6\\ri\xf7<\n\xc5\xe4\xd9\x9dD\xfe\xb7\xee\xb2G\xe3q\xe5bD\xab}G\xec\xb9\xe5\x92L}\x16\x9b\xa5\x99\x84\x95\xbfP\xb2e\xb2\x01\xa95(\x0e\xe6\xac\x8b\\\x98\xef\xbc\x0d\x87\xa0|\xa3\x1dD\xb5Ni\x18\xe5\xe2\xe2|\xb8M\xde\x9a&\xde\xd9\x14P\xcdGU\xa2\x9f\xc8Q\x88\xea\xd1S\xd8#\xe1\x8d\x82eA\x07R~\xab\x99F\xdfDW,W\x8em\xb4\xfeF\x13\"kA>Zz\xd3\x1eV\x8eq\x90\x1a*l\xd7\xd7\xf0\x92\x89\xef\xd7\xd6\xb8\xf0C/\xbe\xae\xaf\xe2%d\x7f\xb7~$\x93d\xd0Ta\xbb\xa1F:\xeb\xef\x07\xa4\xa9\xcevc\xa5\xd8\xbb2\x94\x83\xe4\x9fm\xc8+\xd9hq\x95\xfbwWwxys\x1b\xf2\xfc\xe8\x18\x19Ee+\x90\x0b\xf7\x07i\xeb\x07.(`3\xff.\xae\xa3\xf8T\x18\x9e5\\\x03\x91\xc7\x8f\x9db`u\xca\x97F\xdc\x85V\xf8+\x9e\x16\x83\x846h\x08\xadP\x11Z\xa2#\xb4EI\xf1H\xd3\xc0\xdaM3 \xbc\xd4\x0f\xfb\x8d\xbd\xd7\xee^\xf1\x88\xbey\x9bM]\xd7nwhEZ\xa0\x05\x8d\x13\x8fP\xe9\x98\x87\xd5\xb8'A8X\xd4\x87\xd8\x12\x0f\xa5\xd96'\xdaez\xcdbQl\xf5\xb4\x9f\xeb4\x84\xba{I\xbc/\x13\xd12\xb6\xca\xc1\xc5\xed\xd213\x1a\xf1X\x85,\xbdQ\xd5'\xc4z\x1f^\x86\xd1U\x08\x82\n\x0c\x81\x0d\xdb\xa8\xc7`\x07l\x99\x12\x15a\x1d\xf2\xb8t:\x8e\xab\x05\xdac#)\xf9(\x92\xc6\xb06)\xe74a\xa0\xd3Dh\x04\xb3\x89k#\xa9\xc0\x0ef~\x10|\xe3\xa1\x96\xce\xbb}/\xb5X-\xcfkV\x9aW\xc0z\xdc\xd9\xa8\xc7Z\x84\x95U\x98\xcc\xfek\x04+\x96f\xdc\x96:^\x98$g\x10\xe3\x0d\xbc$}MP\xce\x16\x81\x11\xe9\xabwQ\x8a\x82\x92\xfc\xeeh\xe11\x8f:\xd9\x1b\xb0\xa4\x0c\xcc\x7f\xe6gUV\x13\xd6\xfa\xc9\x08\xfa\x83\x07\"c\x03<}\n{0\x1a\xc1>\x1c\xc0@\xbc\xd9\xa5o\xfa\xbbp\x00;\xe2\xd5\x0e}\xb5\xd3\x83\x03\xd8\x15\xaf\xf6\xe9\xab\x01\x1c\xc0v\x1f\x86\xb0=\xa8\x1d\x92g8>\x852\xb0\x98\xfev\x19DU!\x7f\x13\x07h\xb4;\x19<\xa4{\xd9\xee?\x1a\xc0=L\x0f\xebH\xb6L\xe5\xa5\xb0\xfe\x9f\xff\xeb\xff4PY\xf40*\xaas{A\xc91\xac_w\xb4\xea\x06\xd27\x0d\xa4_;\x10\xd0\x0df\xa0\x0c\x06\xffV;\x1c\x98:\x1c\xf0\x0e\xdb\x13O\xae\x0f}\xacC2I\x90\x08\xd1\xbd~\xa8`\xfd\x13\xc9\xd7\x0c\xa3y\xa1Wf \xe5qY\xe5}@?t\x94}\x91\xa7l+\xf3[nuS\xb1\xa8`\xb5\x1d\x89\xcb4y?\xe7#\xde\x96\x02\xa0\xd5\xef\xbdD\xab\x01\xa0\xebe\xa7\x85'\x10q0!\xf9\x08\x1dWjt\xf2\xc5\x0cs\xf2n\xb6\"\xa9\x0f\x03\x80\x97\x91\x93\x85\x17\x1fESr\x98\xda\x92\x07\xac\x1aWZ<\xb4\xd1\x98J\xdd{{\x83G\xfb\x80f\xf9OF\xb0\xb7\xbf\xd3\x7fT2\xf8Rp\xa9B\xd0v\x95\x85\xe3)\x9a\xc7\x12D\x06gj\x9d~\xa5N\xff\xcc\x85\xb0pS\xd7\xe6\xd9\xae\xbc\xd1\x9bxh\x89\xa32\x93\xbef&\x83\xe6\x99\xf41\xe5\x85v\xe1\n4C\xa8\xd7\"R]\xaa:\x90\xef\xc3\x0f\xa4\x03\x89]~X\n\xe5@jQ\xdaH\x0d\xf7@fr\\\xc3\xbdtL\x9bS\x82@\xaf\x1a\x0eL\xb7\x12\xa4\x1623\xed\x16\x13\xe3\xafl\xb3\x1d-\x91\xeaq_\x93\x83\xd2ZqV\x83\xbb\x9d\xd9*F\xec\xc06\xde\x94\xa8X\xb1#\xec\xd1B\xb1\x1a\xb5\xf8Qj\xfa\xb3\xf6\x83\xe3\x1a\x86_\xc2\xb4\xb0\x81f\x05w\x87j\xda\xadtP\x8b\x1d\xf9\xa0{.\x02X\xc1\xd4a\x036\xac\xcc\xcc\x8e\xe1|\xa8\x07\xc6\xa2\x86yj\x82\x85\xd4\xb0\xf8E\xca\xd1\xdcX\xc6\xc7\xa8d\x1b\xe4\xa7\xf5\xc2\x7faq\x9b\x9fA\xb9`\xa8\x80\x1f\x97\xcdU\xdd\x9e[\xed\x7f\xbfHB\x87\x9e\x989k&\x98x&\xe7\x18:\x06\xd9\xba\xf12u\xbd\x84\x02>\x1e}\xae\x9a\xdeJ4\xb2\xbd\x8d\x83\xa1\xab\xb7=`bv\xdd\xc0\x90\xb1\x92F\xe6\xb4\x1e\xc3\xe0\xf7\x1f\x03o\x0bC\xef\x8cD\xca\xbc\xf2\xa8v\xf4\xa3\x12\x9d\x97\xb7\x8f\xd9\xb0\x98\xe9 \xcb[\xbeJ\x15E\xb8~\xf5\xeb\xca\xf9\x16V\xa9\x8c\x1c\x9e\x01\xb6\xc1\x0e+\x94[\xbf1\xb4,x\x8f\xf9M\xeb\x86FKL\x1bFR/\xd4S\xcf\xf2v|\xa2!\xa4\xfaq\xd5\xf3Bw*\xa0(+p\xeb\xe1\x14bLy\xd2\x92\x04\xa3\x9cR\xb7\xba\x99)e?/^\x17\x176\x035y\x1f\xcfq\xae\xcf\xcb\xac\xd1\xae#\n#\x04J\xd9T\xca9\x13\xa2j\xda\xf0\x92\xc9}n\x8b\x91\xc6^\x98\xcc\xa2x\xc9\x8c1tn1\x18\x17\xfc\x9d\xa8\xd7\xc2r\nT\xaeY\xe9E/T\x85\xdd\xbcV\xbd\x1fG!\xb5\xe1y3\xb90\x0bi[qY\x1c3\x06\x0e`\xcc\x06\x85\xd0\x857\xb9\x14qj\x96Y\x90\xfa\xab\x80@\xea/Ib\x8cw/\x06\xb2\xc8\xc2\xcb\xdcG%\x1f]\xf1\x86\xa7\xec*L\xadx\x1aWW\x93O[<\xe2\x80apl\xe1}\xe0+\x86;\xb6_ k.\xecc\xe1 \xf8\x9a\xa8\x1bEW\xb6Z\\\xe9\xf1\xa6\xb0\x01\xd58\xdd\xd1\x8e%\xc4\xd1\xd9H\xcak\xae\xaf\xc1\xc1\xc8\x82]\x98\x8a)\xe8kk\x14\xdafZ\xa9|\\\xe8\xad\x97t\x0154\xd5\xa4P\x1e\xb5\x89E\xf2\x89J\x06O\xc5\xbb\x91\\\xc3\x9cgd\x16d\xc9Bj\x80\xfd=\x12%\xc2\xe4\x1e\x0d\xb6W1\xc9\x1d\xf5\xb2&\xbd\xa8\x8e\x9d\x12\xbe\x18e<\xd3\x8fL\x1a\xcd\x81\xfcW)g\x9a\x96\x19\xf3r\xdaZ^\x14\xcaDz\x9c\\\x15\xfb\xa7~\x1e\x9e\x89\xeb+\xdd\xa4hLH\xabLB)\xb1`Z\xc4\xba\xaf\x84 \x10\xe7e\xe5\x9e\xe3\xc8\x0b\x02\xba\x0d\x8bE\x9eF!\x81\xab\x05 \xe1*\xcf\xa8\xb45\x82\x9e\xa5\xe9?U\x89f\x89:n\xd8]\x92\xfaAP\xdajj\x979d4\xbe\x00\x85\xcc\xe6W\xf2\xaa\xb9\xd2;;b\xdcJ\xb4adw\x99@\xab\x93.Q\x90\xdc\xe9\xa9\xdc~\xc5\x97\xac\x18yy0\xa5\xfd\xd6$(T\x00\\|m\x080c\xec\xb6*\xc9\xea\xbb,{\x9a\xd5\x9d\x99(\x9b\xc8\x07\x0c\x85J\xe9\x10J\xf37\xd2m;qa+V\x10I/\x1e\xb5>r\xecXY#<_\xbe\xd0\x89sc\x04\xb1\xeaYP\x7f\xa9R\x0b\xdb\xdc\xe7\x84\xc8\x10\xc5[\x04\x01p\x16B\xb8\xc4\xae`\x0c&\x95\x81\xe9U\xb8,[n\xd4\x15M\x16\xfc/\xe9\x96\xb9-f@\\\xdd\x06=#$Z\xe6i\x90\xf93\x95Q\xac\xb6\xa6l\xb1z{\x0c\x96{=\xe4D\x969\x90\xab\xc4]!.\xb7b\xb5%\x9eZ\x97\x89\x17sH\xcaBQ\x14\x1f{\x93E\xb9\xa2\x94\xe2|\x12\x93\x12.\xb4K\x8b+\xf0*bDSKU\xb9\x0din3\xda\x04@Lgz\xef\xde\x06\x8c\xb6\x9e\x15DK\x97\x10\xbd\xd9\x1c \x18\x04\x10\xd2qxV\xa9|c\xf3\xb4\xb8\x18\xc9X]+\xb7\xa4h\x84\xdb.\x97\x16\x9e\x0e\xfc\xfd3\x9a\x940`\xc7iZ93\xcd\xf5\xf5\xab\x96\xbc\xf6^\xdb\x98X\x16\x95\x18\x84\xa9/\xf0\xe2\xee\xde=\xae\xad\xd8\xc6\xc4\x0c>\x86\xb6\x1e\xe6\x8e\x95x#\xd4\x9c\x1d\xb9\xd5\x1c\xcb\xfe7\xbb\x0f\x06\x8eM\x87\xc4\x91\xd6K\x12\x7f\x1e\xc2\x10\x8bv>\xd7\xa2\xd0\x05\xdf\xc5Tr.x.\xcf\xe6:P\x13\xa4N\x9aH\x0b\xe8\xee+\xe8#\xe7\xcc\x8f\xaf\x95\xaf\xf4\xaeY\x13\x17x\x08@\xad\x07\xd6$\ng\xfe<\xab\xc9$.\x985\xbdl\xd1\xe4\xc1\xb5\xf6\x82\x8c\x0cA1\x02\x96\xd6\x15&^n>V\x9cN\xec\xcec\"]\xe5\xc6\x15\xc9\xba~\xe8\xe6a\x97\x87\\\x8c\x84\xc55\xd4B\xd1\xdd8\xa12\xa5h J\xa6\xb9*k\xc4s\x06\xa60\xa4\x87>B\x86\xb1\x14\xe8\xa7U\xacR,_\xaa\xe0m\x11\xcfn\xfc\xe8\xa1\xe3b:\xd4\xf1\x19\xcbl\xdd@U]\x9d\x02\x9cr>\xde8=\xcb\x99y\xfaG\xb9\n\x92=\x82\xfd<\x86t{\xfb\xb1#|\\-\xcf\x82\x0e\xd8\x9dN\xe8\x14\x1a\xa8\x9d}U\xae\x97\xf4(\xc2i\xc2\xb6f!K\x98\x8bE\xb9\xc4a\xd3\x06 \x0fq\xef\x82\xe5@\x87\xfe\xef\xef\xa2\x8dY(\xbc5\xf1\xec,\xdc\x06\x1e\xc3\xcd\xe32\xcb\xd8z\x8d4\x14\x1f\xe5\x1b\xc3\x9a\x15b\x8f\xc2\xe7\xe0\xa9E\x9c\x8a\xea\xa1\xba7\xe9\x93\xd9\xe8\nU\xde z\xf4\x07\xdd\xed\xf2\xcd\xe7\x12'&r\xe8\xb2\xad\xeb\x91\xbeTM:\xe7\xe7$}s\x15\x8aj\xcfI2\x89\xfdU\x1a)\xf6\xd3\x99\xe9\x83\xd7\xdeR\x0dh\xe2\x99\xea\x9e^//\xa2 iq2i\xd7\x98\x91`~4\xc76Q\xf1\x14\xe5D\xb9\x06\x86\x18\xc8\xec\xc4\x11\xccN!~kC\x0d\xeaW\x1a\x9b\xb6\x99\x87M\xc4\xc2\x14j\x14?\xf2\xd2k\x9b@\xee\xb2\xfa]\x19\x81L\xaa\x0e\x0f0\x82\xdb\x7fY3\x91\xed{r ]/g\xffS\xb9\x95\xcf\xdc\x15}\x1d\xff\x1b\xda\x0fUUs\xa4w\x03\xa3\xdc\xe9mq\x94\x9ek\x9a,xt\xfb\xe4\xc4n<8\xd3B!Fj\x85\x0b$w\xc4\xd8\x10O\xb7\x1a\xe18>C\x07'\xe1H\x91\xa1<\"\xbe\xa8\xacH\xd8\x00g\xb9\x8fv\xfc>\x1f\xfa\xd6\x16W\xf6\xb1\xf0\x03\xe5\x14r\x9f>\x19\xb4d\xc8\xd5\x9b\xf4\x83\x0b\xd24\xdaVX\xa1\xe7\xa3\x88\x0b\xd6\xf99I^E\xd3\x0c\x0dN\xd4\xa5D>G\x16+Yt!/N\xc8\xf7\xde28BnE\x93\x16\x7f]D\x88\x0e\xed\xbdAO\x83q\xc8\xfc\xb0\x80\x0dq\xb7\x18\x04\x1c@\x0cC\xcd\"\x0bSS5\\p\xd1\xa9n`\xb5\xa8\xaa'\x0f|-#\x91\xe3\xaf\x9bx3\xf2M\xe4M+ \xacjID\xce3\xb1\xd0\xc8q|\x88\x03I\xba!\xb9zG\x89@x\x1c\xc7v\xa1IB*\xad\x1c\x97\x1bz\x916\x11\x84\x9d\x87\x06q\x88\x8e\"\xb6\xcbs\xf0\xc3I\x90M\xc9\x10\xc6\xa1=\xe8\xed8g\x12\x12\xfcC\x07\xd3\x1f\x0c\x9c3\x85\xb0-W\x81?\xf1S,\xdf\x1b<\xc0P\x06{\x83\x87\xfc\xdfG\xec\xdf\x9d\xde\x1dM\xe2N7S\x10y\xcc[\x99t\xdf\xbd\xf9\xea\xabo\x8e\xcf\x8f\xde\xbc~\xf1\xf2\xabS|\xf5\xfe\xed\xf3\xc3w\xf2\xab\xda\x9d6\xe8\xed\xfdN;-[M\xbd\xaa\xf6\xd2@\x165\x07\xf3\xf5\x8a\x0c!\xab\x9e\x10+\xef\x9a\x02d\x08v\xcf-\xb6\xa0c\xff\xfdF\xd5\xe2\x02(\x9a?\xd2M\xa3\xf9<\xa87\x0ej\x18\x91&\xabJ>\xa2\xd4\xd4uy12\xfd\xbaYL\xb2K\xce\x19\xe4\xac*\xaf\xa8Y\xff\xfc#63K^\x81\x1cod\xad\x89n\xaeU\xad\n|\x1eA!2\x12\x8dJ\x0ef%l\xec\xef\xa9\x0c\xc8\x97\xc2F^\xa7\x85b'\xa7\xca~\xc8\xe2:\x94\xd1\x8c}U\x1d\x04\xdf\xbca\x83\xae@\xa3i\xd8H\x17\xa1\x18\xac\xa0\xa9\x16\x8b\xde\x19\xba\x9br\x87\x94\x1a\x10\xf9\x1c\x18\xdeQy\xa1\x8f\xb7\">\xdd\xd1\xd6%\xb9N\x90\x91&\xdc\xa3\xc2\xc2\x1d\\\xbc\xc3\xe47C\x16\x14w\x1c\x9e\x9d\x95t.\xa22\xdeZ\x1e\ny\x05%\x0c\x0e\xe9\xd8f]\xa0\x91\x86T\x1d\xc3\xd0\xa7\xb1O\xff\xd2\xe2O\xa3haT}7~\xb9\xd1\x01\xcc \x9a&\x18\xde4\n))\xda2\x1ew\xb7\x1c\x9d:4\xbf\x1cJyK\x96\x87\x98\x90\xfc\xeezE8o\x0c\x1d\xb0\xc4\xed\xaa\x977\xbae\xba\xafn\x18\xec\x86\x9b\xf8\x91~\x0f\xef\xedj\xb7\xf0#\x95\x05\xcbP\x18.\x1a\x0e\xed\xc1\xbecg\x94\xf2\xec;\xb6\xe5\xa7$\xf6\xd2(\xa6\xe8\xd3t\x94\xa7r\xf0\xb2\x1b\xa7F;\xa8\xbb\xba.h&\x8c \xa6#\xa8\xe2EH>\xa6t\x13i\x12\x91\xd3\xdd\x80m\xe3b\xbc\xcc\x87\xbd\x19\xb0%\xf5\x84\n?N\x1a\x1fh\xc1\xba\xdb3\x93\xc0=\xe9\xea\xa3\xc4\x94\xfb$i\xca%\xe8W\x14\x9dEf-\x17\xd7.B}\x04\xe5\xd02N\x81\x98\x06\xae\xf7\x18\x85\xbd\x07;\xbb;\xbc\x7fV\x1f;\xa2\xc8\x82\xce\xdf\xf4-\xf3\xc2L\\\xecd@\xcb2\xd8\xe6\xcdt\xe88\xb7\xf9\xa0\x9e<\x81~\xcf\x81\x0e\xec\xef\xed\xed\xec\xdf\xcd\xa6\xaf\x1c\xa9\xfc\xe0\x18\xf4\x8dg\xea\xc0\xe9\xceI*\x0e\xf9\xe6[Y\xa4\xf3\xeaIjd\xf1H\x03\x8b\x87<\xd1E@L\x0c^l\x13n{\xe4\xdcz'\xf6w\xf4\xd7#\nOV\xa10(\xa4\xb5\x03\xdb+\x92.\xa2z\x034\xc9\x8dl\x0b\xa3\xcd\x0b\x9a:\xf6\xcf0\xc0\xc5\xd8\xfa\x97\x7f\xc9\x87\x83\xaf\xa21\xa5Ng\x9b\xcd\x9b\xae\xf6\x0eJ\xbb\xfd\x1d&\xf5\x0evv\xf9\xbfLM:\xd8ej\xd2\xc1^\xaf\"\x0e\xf7\x1f9B\x14o\xd3Y#C\xad\xc3G\x99E\xf6\xc7\xa1\xddwlK\xdc\xc6\xbf\xf3\xe6\x96s\x06#\xb0~\xc1L\x8d\x1d\xba\xcf\xb7F`\x8d\xd9E\x0b\xfcrf1\x1d\xc1N\xcf\xe1VK\xa5\xe8\xbd\xa2\xa1\xba\xb0\xdd\x1c\xf2y\x9b\x16t\xe89\x80\x01L;`\x9d\x95\x9c\xe3\xb6\xda\xe9\x07d0n\x85\xf6\xee\x80%G\n\xed\xdd\x1d\xc7\x1cx\x8d\x8f\xe4\x01\x9d\xa2^\xd7\x1c\xda\x8f\x1e9\xb65\xf5\xd7Tl\xb0<\xad\x19\xccF\x81\x86\x1fT\n\xd5\x9b\xcc\xaeW\x00\xa0\xd5\xe4%]\xbf\x89\xd0\xd4\xb3\xe6\xe8\xaa\x81'\xb1\xdeV\x813\xe9~\x95\xea\x10\xd3\x95\x9a]\x8e\x13\xc0\x96#\xe6\xb1\xc7\x05I)|\xd1j\xe9\x99\xda(\xca\xd4of\x9b\xb7\xb9\xf5e\x86\xab\x92X\xeb\xc8\x0b\xff\x94\xc2$\n\xd7$N\x81\xa3y\x1a\xc1*\xf6\x97>\x06+\xc4)l*\xd25m\xf7\x81\xe1\xfc\xe9\xef\xe8%\xe8~O\xe5_\xaa\"t\xff\x01\x17\xa1\xfb\xff\xaaE\xe8\x87\x86\x83]}\xcf\x01\xbb\xab\x03,\x05x\xcf\xb1\xad\x97\xc7\xe7oO\xde\xbc{\xa3\x1ez\x9e\xaa\x9e*\x17\xab\xda\xab\n\x15U\xba/F\x8c>?\xf9\xe1>/b9FxXV&\x1e\xa7\xdd\x17\x8f!F\x8b\xb3) HJ\xe4\xac7\xe3h\x1c\x9fir\xa6\n.W\x8d\xed\xaa\xa7\xa3%c\xe5rP\xc7v\xa6b\xbc\xbb\xdc\xca\x1d\xefF<\x05\xdd\xd1\x80\x1b\xd8\x0d\xad\xe7B\xb9\x98{\xe3\x8c3\xb4'\xc6\xec\x93hzVX\xc0\x8c$}\xac\xcf\xb2\x19\xdf\x16\xf1\xf7\x0c\x14\xc5\x80\xf75\x1c\x1b=\x92\xff5(\x8f\xf6\xf4\xa4b_wEG\x99\xc2\xbeco\xb5\xa3\x16\xb78\xd99\x80<.5T\xe9\x00\x82\xa8\xfaz\xc2\xcc7\xab\x10Gsv\xcfaJ\xa2\x8c\x19Z{\x08\x8b{\xf7`\"\xfc\xb44\x1f>\x96\xa3@\xe1j\xe0w\x94,\xe0Z\xb0d!\xff.\xb2'\xd8\xda\xa7OEk\xfa\x05\x9a\xdcv\x81vM<\x12\xb7\xe3\xb3~\xb1\x1c\xba\xe1\x90\x01|\x99\x1c\xe7\xf7\x8ev\xaf\xc0\xe0\x12\xc2\x9a\x18\\\xce\nS.#f\x96\xec)&\x10Km\xcb\xa2\xfb6\xb7\xfa\xbf\xedT*H\xc5pmWg\x9c@ \xb6I\xb5\xdb8\x95\x92^\xe2\xdf\xf4\x94\xff\x15\xe9)\x0d\xe4j\xb0\xa3\xfa\x1dD-8\x18\xc9j7?\xb1j\xcf\xd19I\xdf\x8a\x8aof\xf5A\x92s\x90pZF\xf7\x94\x0b\x11n\xabqt\x06C\x93i\xdf$\n\x934\xce&i\xc4r\xe3\x83\xe4\xb7_.=(\xff-\x1d\xbb\xc3\xf2g\x9c\x08\x1c@\x06\x8aG\xf3\x86\xe0\xef\xdfzK\xcaV\xc7\x9b\xf5\x9e\x1f\x9d\xc2w\x07\xfdH\xf3\x03\xdc\x15\xda\x97\x9e\xe3\xf2\x93h\x8f\x1f\xad(\x0e\x08\xcf\x94\xdd]\xc7\xc5\xfdLe\x03\x177\xed\xa4,\"\x04\xecUI\xb9\xc0\xf2\x82'\xe2~wQq\xcc8:==\xc9XN\xbe\xaa\x19\xc7\xd1\xe9\xe9)eH\x9f\x93I\xe0\xc5\x1e\x9da\xd5E\xe3\xe8\xf4\xf4\x03\x15\xafx\x13ji\xe0\x930=!\x93T_\xfe\xfc\xcd\xab\xdaB6\x17c\xf1\xbb\xe8\x92\x84\xfa\xc1?\xf7R\x8fy\x11\x92\xf8eJ\x96\xfa6^\xf8\x81a\xe4\x7f~\xf7\xea\x9b\xc3 8\x8a\x82\x80L\xf4S\xa7U\x9a\xca_D\xf1\x92k\xbb\xf5\x15N \xfd\xdeX\xe5\x15\x99\xfa\x9e~\x86\xaf\xfc%\xa1b0.n\xf5\xcb\xd7\xde\x92L_GS\xf2\xca[iJ\xa3\xa9a\xd5\xdfz>]\xb1\x9f3\x92\x18\xd6\xe5m\x90\xcd}\xcd|\xd9{\xc3pN?|\xf5\x0d\x1eC\xfa6O?|\xf5:[^\x90\xd8X\xfc\xd6K\x17\xa7\xc4\x80\x0b\xb4<\xf2C\xc3\x80O?|U\x87H\xa7\x1f\xbe\xca\xfdM\x0d5\xa2,\x9e\x10\x16z\xdeP\x83n\x94\xd3\x05!\xa9\x1e\xaa\xef\xc8\xc7\xf4]\xecM.\x8fL[%\xafa(\x8e\xb2I\x0e\xbb\xbc\xe4\x86\xa5\x0b\xf7m\x0cY\xc98\xf05<\x81\xa9\x904a\xdd\xe9\xe8\xf8\xd4k\x17\xe60\x82\xe9x\xad\x18\x9d\xd2g #X\x8c\xe7\x9a\x92sd\xe7u%\x170\x82sJ\xf1\xcfu\xa7\x11\xf0c\x18\xdd\x89\xed\x0bz\xf6~\xfa\x04\x9e}\xe1\xc2\xcc\x85\x95\xe3\xc2\xc58(\xde\x05,\x07s2\x9e\x9f\xb1\xe8\xbaK\x8d/\x03R\xd6kz\xa2\xc7\x0e\\\x8c\xaf\x99\x1a\x99~~\xedB<\xbe>+\xf4\x99\xd0\x96Z7*}\xb4>9\xf4\xbd\xe1~_\xd5\x05e\x82\x954In\xfd\x9d\x07\xfff\xf9\xf4_\x8e\xe5\x93\x99\xd7pl+\x0b\x93I\xb4\xa2\xd2L\xa22o\x1a\xa7m \xdf\x84f\x01\xfcq|\xc6\xae\x00\xfa\x0f\x1c\xdbG\xef\x8f\xbf\x9b\xf5{\x15I~\x1c\x9f\x8d\xd33\xc5\x89^;\x11\x93~\xbf\x16\xf5\xf8\xa2\xea\xc4\x93\xbb5\xc4j\xbfMe\xb7^\xbe\xa1T\xa6;\x11lV\xe9-c\xae\xf6U\xab\xa8\x19\xbe\xae\xdc\xed\x04\x8ckS\xde\xae\xd8[U\xc3\xb0`M\xab\xaf\xa7\x9ct\xa8\xd6\x91k\xf6~W\x1d\xca5\x17,\xd5^\xe7\xfc\xfd\xae\xd3M\x88\xb2e\x97\xbc\xad=\xc7V\xbe:\xe7,\xb1*\xd5^\xf0\xd6T\xf8\\\xf1\xf7*\x01\xfc\x88\x1cf\xae\x8fW\x8eE\x91\x0c{B\x12\xc5\x91\xf0\x18\x8b\xf8\xfd[\xb9\xe8\x10F`\xf1\x8fp\x87\xcf\xecS\xa5\xd77\xf5\xea\xdb\x9f0\x92\xde\x08\xce\xbb\xb3r\x01\xa5\x84[[\xf5\xaa]\xb3\x7f\x9d\xa0\x8e\xc7\xdd\x98$Q\xb0&\xb6\xba\xa6\xf2CX ZY\xe6\x19\xd1\xdd\xcb\xaf\x01\x93\x15\x99 a9\xab\xdd\xc3\xea\x93\xdao\\xc\x96v5\xd9\xfaA\xb2\x0394zl\xf1\xa58!?1\x86\x163_\x8a\xac8\x0b\x12\xdao\x1cY*\xab\x8a\xe55\x1e\xb27*\xf6\xbdl\x9c\xf3\xba\x9aX\x05\xa4s\xc4\xde\xc2\x98\xaf\xe5\xc9\xe4w\xf1,p)\x0e\xdb\xc1)\xa8\x89\xb4J\x7f\xbej\xa2s \xae\xb4\xd2\xee\xb9Q B\xcb\x14\xc7\x01\xf9Y\xe7\xe1\xbc\xcf'\xfa\x1a\xcb\xe6\xa4U\xa0J\x94i\xf7|\xcd\xe4\xc9>.e\xf7\x1c\x00\xe9F\x97\x18\x94e\xe6\xf9\x9ahc\xea\x93\xe0\xc5\x03\xdf\x1b\xcd\xd5'\xbc:E\xb8\xe6\xda3\xac=\x8d\x96\x9e\xdf\x94 \xc4\xb8\x81\xe5\xc7c\xc1.>}b19)\xec0\xdc\xd8[\xc6E\xd1\xbfF\x18\xa4t\x8b)\xf9=d=Fh\xedoc\x0e\xadY\x97\x84)\x89m~\x81\xe0\xd91\x8a\xe6\x94\xc5\x9du\xc9G?\xb5\xb9P\xbf\xd5sX\x1d\x8c\xb4\xb3\xe2\xe6\xff\x070\xb1?\xda\x16\xdfw\xdb\x93\x85\xe7\x870\xb9\x9e\x04\xc4b\xa1\xea\xe9:\xbe\xb4)\x06\x1f\x087\xd0\xd0\x85\xc4\x85 -N\xb0d\x08\x13;6S\x03P\xf7e#Xp\xfc[\x19\x9f\x1f\x9f\xc4\xc4\x94f[<75\xf4\x08\xc2B\x19\x1d=v \xb3\xc3q\xd4\xe9\xe8\"\xc8\x8a\x87n\x12\x1e\xe1&p\xd4p\xad\x9a\xde\xde6\xf6\xb6)\xfe\xea\xb1QF\xac\x1c\xe8\x7ff\xaba \x9c\"\x1c\xa7\xf2\n|\xb9\xd8)\\\x83Rm\xd0I\xa0\x12\xddS\xad\xb7~\xedJ\x9d4\xc2n-\x05S\xab\xc2\x85t\xcf1S\xb4\x8d?X\x184\x84\x01\xe9\x9e_\xd1\x02\xe2t\xcf\xd7,F\x1d\xe9\x9e',{\x04\xe1+l\x13\x86y\xa4{>\xe1\xc6\x94\xf4\xa0xe\x13\xd4]\xd4\x8e\xfcu\xbb\x91\xbb\x86\xc8g X\x9a\xb0{\xae\x0d\x05\x0f\x18\xec5\x9f\x14\xde\x90\xf39\x19\x8e\xdf\xfac\x17\x03M\xb2\x00\xf6bc\x15\x87\x1fL\xd0\x88\xe7\x82\xeefd\x1e\xa6\xe0\xa7 f\xaa\xa9\xa4\xfc \x9c_\xa2%\xd5A[\xe6 $!\xbd\xf9,<\xbf\xd2zGV\xaaM\x87\xba\x84\x82\xf2c\xe0\xca\xc5\xd3\x8ec\x11\xe6\xa1\xf4<~\x8d\x07L\x1f\xcf\xe6\x13\xfe\xfb.\xd9\x80\x93\"\xf3\xed\xadO~g\x88y\xc39\xfa\x87\x0c\xfd\xfb\x14\xbfC\x17\xb6L\xe3m7N>\xbe\xfa\x89\xb4X\xbf\x86\xb5\xbb1\xce\xbf:o\x85\xc9(V\xfc\x12\xf7\xfaq\xed\x86\x9d\xf2\xa8I\xc7.\x88Ma\xb9`\x9d/,\xc7\xc5t\x14\xae\x1c\xd5\xbaU\x14\xa3\xd4F4a\xed\xe6\x98\"\xfeT\x88K-\xd0O\xca\xf1\xb4\xcb_\xe6\x7f\xdd\xb8\xec\x107O\x92\xa9\xf9r\xce\x0e\xff\x92O^\xf6&\x91U\x97\xe5l\xe5\xebJ\xe5\x85\\\x991\x8a\xc5\x80\x9c\xb2-\x8f=\xd8\xddw\xecc\xd9\x86V\x1d\x1f [\xc4\xfc\x16\xa2\xdcO\xb6\x88uu\xac\x0b\x97-\xac\x8f\xa8\x0c5\xd2\x8a\xa9\xec\xca\x19\xf7\x06\x15\xb0\xca\xb5F\xe5\xd4\x83\x94\x92s\xe9\x07\xd9\x18z\x16\xf3?\x87\nL&R\x08_\x0e\xe3<\xf0\xa8\xa7\x96a*\xdfW|\x1e\x98\xb8>\x14\x12Jy\x9d\xcb\xfb\x08\xd1\xa5\xce.\x03\xca\xd6\x89L\x85\x90\x8f\xd3\x88C\x8e\x12.\xcd\xa4\xa0\xc6x\x1a\x8f\xab\xd8%\xb8\xc2\"];?Q\xf0z\xf45\xc6[\xc8\xb3\xf33&\x05KNx\x89\x8c\xcd\xe7]*s\xfe\xd4\xe6\x828\xc5\x93\xed\x18\x97\x13\x7ff\x94\x83\xe6\xc1\xe9Q\x8d-\x1b\x9e8.\x04v\xd0\xfd\n:\x10t\xbf\xc5\xff\xbf\x80\x7f\x86\xadK\x15!\xdf\n\xa6\xe8\xb8\xf41\xb3&\xb5eZ\xc1\xad\xdd\x1f8\xb6\xfcJD\xa3\xcb\x0d\xddY\xc7\xa7\xa5.%z\xa3\xce\x8d\x82\xa7i\x91\x05\x83\xf4\x93\x8e2\x81\xa4z\xea\xb9\xb9\xb4\xef\xb0\xe8\x9bzD\xab\xc0\xa9\x18\xae\x8dl\xd3\xd6\xa5S;j\\\xef\xa6a\xf3Q]\xd9\xf9\xe6\xc8\xd7\xed\x98'\x93i\xc0S\x05\x92\xf6%\xd3\xd4\x0fv\x1fJV\xf0\x95\xbe\x8f\xbb\xcc\xc0\xb9\x8b;\xc8~#\xa3E\xdd\xb4\xbc h\x9a\x92\xcc\xaa\xeaO=F\xb5L\xf6BxsQ\xaf\xbe\xf1y\x15\xb3\xca&j/\xa9\n::\xd6\xdc'\xcaO\xa4\xb7\x9b\x93\x1f\x8a\xe8\x86\x14\n\xf4YSZN\x8f\x91\xf6zV\xb4\xb0\x82\x11D\x9dN3\x07\x98\xd4\xa4p\x10O\xc8(/#\x81tov:n\xa1-\xa3\x18\x81$\xb2\xfd\x08\x01;\xa6\xacE\"\x98\xf4\xb1w\xc6(\xdf\xf6vFKb;l\xe2\n\x8dB3p4\x97\x9a\xd2\xd6\xbb1o\xf9\xa8\x8bG\x97oG\xddu\xdb\x83%\xf6&\x8d{\xf7\xae\x10\xdd\x8c\xc5\xfe\x06X\xbc9nUW\xbd\xd8vP\xa3\xcd\xd3\x88\xb7P\xbf\x02>[\x81\xd8\xf6\xebV@\"A\xf8\xf3V\x97\x83L\xe9\xa5N\x9dgp)\xdd\x1c\xa0\xda^\n \xc84<S l\xc4\xe5\xb6\xa6m\xef\x97m\xe2\x81\x8d\x9fIN\xb38Z\xdaQ\x83\xad\x0c;7\x07F\x90\xe8ma[[\xd6\x17\x01T\xb6\x8a\xb4\xe3\xaa\x86Y\xe8\xcf\xd5\xf7z~A\x02\x9c\x9e\xd8\xa0g\xbf\x06\xa6\x90\x1f\xb9MP\x85:\x9f\x00\xf10\x0f\x80\xb0\xba\x00\xe2\xd1\x9cj.\x0el\x83\xee3]\x1b\xa9\x1d\xd5\xdczk\xe9\xfa\x9d\xa4\xa9\x90\xc8\xa5\x9e\xcbV=\x00\"-u\xe2\xf4\xa6\xa2.\xe4~\x0e\xbb\xfb\xd2\xba\xc5v\xdc}\x0b\x1d\x88\xbb'5wJ3?\xf4\x82\xe0\xba\xad\xba=\xe3\xb7\xc4~\x1e\xc1\x9aJ\xc2\xe2\x0f\x83\xae=4\xddjk\x98\xdd\xca}q(\xab&\x8d\x96\xd7\xfc3\x8fRGT\x84\x95/R\xea\xf8\xab\xca2\xcb\x8f\xce\x9a\x8c\x8al\x94\xad\xf8\xc2\xe3\xe2 u6\x1a\x96\xf9\xae\xf2\x0b\xa2n\xc5\x7fD\x84?\xd8S\xb0\xf1\xb4\x06\x0f\xd3\xb85\x0e\xd2C0\xd5g\xe0\x86<\xd1\x97\xce\x9eV\xdcB\x87]\x82\x86\xed\xfc\xee\x7fX\\\xc68v\x88\x97$\xcd\xd7\xd2m\xe0\x19\xda\x83\xbd\x01\x8f=\xb7\xc3\xff\xdd-\xc7\xaa\xdb{\xc0\xff\xe5\xb1\xea\xf6x\xac\xba\xfd\x1e\xff\x97\x7f\xbf\xcf\xbf\xdf\xe7\xb1\xed\xf6\xf9\xf7\xfb\xfb\xfc_\xde\xce>og\x9f\xb7\xf3\x80\xb7\xf3\xa0\xcf\xff\xe5\xed=\xe0\xed=\xe0\xed=\xe0\xed=\xe0\xed=\xe0\xed=\xe0\xed=x\xa4\x8d\x9d\xc7|j\xdb\xc0\xa2\x11\x8b*\xbeNQ\x1ep\x13\x8f\xe3#\x1e\xae\xb2J\x10\xe5J\xd1\x94\xa0\x17\xb0\x82xH\x06\xd1z`\x8b\xd9\xb5\xf71\x9eJ\x1e\x16#\x8f\x1dR!\x8fr\xa3M\x08\x9a3\xb4\xdc\xe4r|\xe6\xe2\x9c\xf3\xccPy\xa4\x9c\x8c\xf9\xe9\xc6\xf0\x142\xb3v\x80g\xb9\xeb\x14\x99\xa52\x8c\xa2\xe3Sj\xd2\xef\xf7w\xfb\xfd\xbe\xc3r\xf7\x8a;\x91\x13/\x9c\xf3K\x11R\x8e-\xbe\xf6\x02\x7f\n\x93hJ`E'c2\xab\xe4w\xd4\x04\x9e\xb0H\x9dp\x80\xb1~0B,\x8b\xe4\xd9\x01\xdb&\xb0=b\xe5\x0e<}\n\xfd\x1e\xca\x14\x7f\x84~o\xb0\x0b\x1d\x16\xffS\x97|\xcc\xb4'C\x9eSP\xcd\x9c\xbb\xe1\x8ek\xc22CT -\xa52`D\xec]\xb5\xc7\x03\x16;\xa3\x1b{W\\\x10\x8d\num\x1dnP\xcc\xf1\x18\x8e\x84\xf0\x14\xbc\xc7\x0edl]x\x08Z2\xf6:\x9d3\x07\xe3D\xdc\x87\x9eF\x8a\xb0\x8e\xa2,L\x0b\xe7\xac\x90\xcc\xbd\xd4_\x13U|\xe0\xc1\xf8\"x\xaa\x1ar\xf1\xc7\x8e\xe0\xe9\xd3\xa7#\xe8;\xdc\x9b\xb53B\xc3#zb2\x07\xd7\x90\xbdz\xac\xac\xd3\xef\xa7\x84\xdb\x948\x17 \xda\x9a6aQ\xb3n\x1b\x16\xb5\x9a6\xa2\x8eD\x97\xfa\xd0\xad\x00\xe2\x88o\xe7\x84r\x93\x1d\xea\xe6\xe1DM\x99/\xe2[\x10\xd6\x18\x97\xad \xac!\x15\x92(\xec\x84E\x0b%\xac\xf1g\x11\x07\x93dBW\xc5\x0b'\x8b(\xdeH2\xa9\xe5\x06\xf9b`\xd4z+\xf4\x96\xc4\xaaK\xec\xf9\xd9\xc3\xbf\xf0\xe7\x1b\x8d\xbd\xcd\xd0Y\x9b\x16\xfe\xf7\x05G\x1e\xf8\xe1\xe5\xdd\x8f\x9d\xb7\xfa\xc5G\x1f\x05\xd3\xbb\x1f\xfc\xef0\xf0\x99\xff\x91\xdc\xfd\xc8\xd3\xf4\xf7\x18z\x14\xa6\x93(\xf8\x12\xbb\x956MG/\x9a\xff\x82;\x96v\x95\xf8\xbf\x90/7 \xde\xfa\x17\x9c\x83\x9fz\x81?I6\x9aB\x9b\x19\xf8\xbf\x03\x16mLvZ\xc1\x1e\xc9\xfd\"&\xb3/\x0b\xf8d\xe9\x05\xc1F\xa3o3x\xd1\xea\x97\x06=}}\xb9\x19\xe2\xb7\x1a\xbeh\xf6\x8b\x8f?\xbb\xb8\xfb\xc1g\xbf\x07\xd5O\xb2\xd5\x17\x18\xf9\xea\x8eF\x1e\xda\xfb;\x8em-\xbdt\xb2\xb0\\\xe8\xd7\xd7\x96\xc62\xce\xebi\x15\x9dz\x88\x88GH\x02i\xddE\xa2/+\x1aP\xcf\x90\xe7_\x0b\xc7\xc4\x9c\xdaB2\x9b\xf7\xe1@\xd8\xd81\xcf\xa8!\x9a\xb7q}n\xe8\x8c\xc9\x99P\xd8\xc7\x95X\x1f\x10n\x9a\xd5\x9f\x03\x93\xeb\x14-\x17\x06\xb7\x00g\xecV\xdd.\xa0\x15D\xa3&\x88f%\x88\xc62D\xe3\x96\x10\x95\x04\x88\x18C\x95\xf9\x08T\xf6\x86\x832rX\xe8\xa5;\x03hB\xbc\xf8\xdf\xd0\xf3\xce\xa0\xb9\n\xfcT\x8b\x9c\x15\xcbI3\x98\xc4EFh\xf7wUc=\x10z\x8f\xeakv\xb9\x867eU\x8d\x885A\xe3\x14\xcb\xbb\xb8\x98X\x92\x89mYt\x8e\x1a\xa4is\x1d\x02\x92%\x9a\xd0\x01\xe8\x03\x01@\xd9\xd7f$\\\x8bx\x12\x9d\xdc\xceMM\x86\"\x7f\xbb\xe5\xcb\xa9\xd3\x8a\xa8x8:\xfdgkf\xc2\x9f\xb80\xc1p\xd3\x01\x0b\x8b_\xe7u\xbe`\xa1;\xfdy\x18\xc5\xe4\xc8\xc3`}\x96o\xc1\x90\x1ey\xd0\xa1e\xcb,H\xfd\xc0\x0f\xb1hY*\xcaB\x1f\xaf\xda\x0f\xc0\xcaJ\x05I\xeaO.\xaf\xe9\xfbk\xfe\xde<\x84i\xbd\xd3\xfb\xba\xbc\x9a\xb4\xb3\xdd\xc1\xa3\xddG\xfb\x0f\x06\x8f\xf6\xd0\x8e\xff\xe9\xd3\xa7u\x0d`4\xd9b\xbf\xa7\xdd\x04\x83\x9c\xbb\xb0\x80\x0eXs\x93\x85\x00\xaa\xfaX\xf0\xaa\xb8\xdc\x02\xbb\xcb\xbc\xe6\xed\xd0F\xfe`\x1fl\xfd\xf0C\xe2X.,t\xd7\xd0\xf9\x83\x0e\xec\xd7\x0c\x17y\xc0\xce-\xdb\x9e`(1\xd4*C\x07\x92q\xef,\xc7\xf0\xa70E\xad\xe1\x8aG3\xe1*\xa4\xa9+>p\x1c\x17\xb6\xd0h\xbf\xa4\xe0\xc2\xc4\x1f\xbd\xb3\xfc\xe2-v\xebY\x9f\xd2\x83S\x0f0\xd0\x00\x04\xf0\xa4\xaa\xe4\xde\x86\xc1c\x08:\x1dG^\x99B\xa3\x16\xa0\x15\xaf\x8d?FZ\xe5w\xe9\xb9q\xdc\xea\xe098\x9e\x141\x15\xf1\xf2\x9f9\x00\xad\xe8\x07\x0c\x12}\x87g\x89\x90\xc0\xc6b\xc5O\\X\xe5\xad\x8e`\xed8\x8f\x1d\xb8\xee\x06^\x92\xbe\xc4\xb6\xf1>\x83\xf7s\xef\x9e\\\xa4\xc6\xf4\x16\x0f\xdf\x8cSv%S\x84\xf5\xde\x9a\xb1\x06(\xc9\xc4,<\x9f>\x01_1\x96\x93G]>:\xe8bp\xb0\x86\x03X\xf1\xb2\x9e\x0bk\xfc\xa42\x02\xc5,\x99\xb9*X=A\x1a\x85\n\xb3\xe7H\x10\xb3[Q\xb6\xf2\x99\xa9\x92+8\x80\xf1\x19\x0c\x05\x0d\xcau\xb1\xaa\x14\xa8\xd7iK,\x82\x81\xe5\xba\x05Su+>@b\xaa\xc2\x82\xa9\x8a+LU\xa8c\xaa\xe2M\xd9\x80z\xe5|f\x87\xf6\xe0a_U3\xfb\xbchg0P\x8b\"^\xb4\xd7\x7fHIL^&\xc6\x80A\xf1\xf5\\\x1a.f\xda=?'\xc9\xabh\x9a\x05\x18G\x1e\x86\x9a\xa5\x98\x92\x99\x97\x05\xe9P\xbd\x9f\xff\xa7\xea/q\xd2\x8e\xfd.\xff\xca\x85\xa8\xf8i\xa46|L\xd5\xbe'\xd1r\x15\x85\x94\x80\xe8F\x06\x98{B\xf8.}\xe3]GYJ\x17\x8fw\xd8\xb4Y\x8a H\xa8\"_Ny\xb7_S}\x8eW\xe2\x82U@\xbcr\x0b\xc2\x03\xc7\xcb\xe1\xea\x9d*\x9aLl\xca\xf9=\xd4\xa1 \x16\xed\xf5th\xc2\x8a*\xc8\x95\xe5E;j\x91\x97\x17\xed\xabEI^\xf4@>\xda\xf0\xd5\xfe\x9e\x1e\x15'\xbf?*\xcej/\x18\xf3\x91\x91:\xc1\x9f\xd2\xde\x1c\x9b\x1dN\xe8\x88\xe3bA\xa6\x16\xd8\xa4{~\x8e\xce\xe7\xe7\xe7\xc8&\xf4\xdc\x02\x1f\x1d\x9b8\x0e?\xadX\xf5\xfcxTE\x0c\x1d\x98h[\x9e\xd4\x96\x0b)\x1fFTz;\xae\xce\xe5\x92\\\x0f\xc1\x8aI8%\xb1\xe6\xa6\x94\xe3]#3\xb0\x96\xf3c\xac\xe2he\x88?\x03\"UFwN\xd2#\xb1\x85\xcduYd\xf0dE&,!P\x14\xd74\x1c\xb3\xd0\x1fq\xdc\xa2.\xdd\x13\xc4\xb6\x8e\xa20\xf5\xfc\x90T\x1cn\xe4'buO\xa2\xab\xbaZ\x99h1\xa8\xab\xe5\xb1Z\x18\xb57\xb10\x9c\xa9\xb9\xf2\x84U~\x17\xad.\xbc\xb8\xa9\xf2\x8cU~\xe6%\x9c\xde5}\x10\xb0\x0f\xa2\x90r\xeb\x1f\xbc\xc0\x9fzi\x14?\xf3\xa6s\xd2\xf4)&t\xe8\x06\x917\xf5\xc3\xf9i\xea\xa5Y\xa2F\xb2\x97\x9f\x05z/S~\x89\xdd\x9f7\xb0\xf7\x94GZP\x04\xb1\xad%I\x12oN\x90+\xb24J\x01(6A\"P\x9d;T\xf2\xdcQ\xb6o\xf2\x94\xa4\xcf$\xf0\x92\xe4\xb5\xb7$C\xb0\x92+o>'\xf1v\xe6[\xda\xfa7.L\xe0\xc0\xd8\xcf\xc4\xc5$l\x0eO\xc6\xe6\x82\xc5\xe1c!_\xb4b|\xaa\xfe[\xcc\xed\xddv\x9c~8\x8b\x8c#\xbc\x93\x1e\xf8\xc0\xb7'\xf9\xee\xf8=\xba3t\xe2`\xf8\xb7\x99\xe7\x07d\xfa\xaf\x12\x94\x8b\xdd\xd6\xbd\xa5~\x1a\x10c\x0f\xd6\x0b\x04\"\xa4\x11\xd0a\xc1\xe1\xdb\x97\x80l\x88Oi{\xd7r\xcc\x83\xf08rKkq\x84\xae\x95_dE\xcc\xe4\x013A\x9b\x18>\xf1,\xbd\x8f\xdf\xfa\xd3t1\x04\xeb\xe1\xc3\xde\xeacM{\xacz<\xf7\xc3o\xc8,\x1d\x82\xe5ei]\xffE\xfd\x13\x7f\xbeh\xf9AJ>\xa6\x87\x81?\x0f\x87`M\xd0\xdf_\xbfDP9\xdf\xf3\xb7\xff\n\xb01&\xcb(%\x85\xc7n#NZ+\xcb\xe5\xa4v\x8a\x88\xb9\xb5B\xe5_\x92MD,\x8c\x06\xcc\x9cq\xac6\xf7\x11\x89\x1eL\x15\xb2\xa6\nA\xbes\xaa:\x0dE\xea8+\x85H\xba\xb1\x8b&sNIb\xa9\x89(m\x1bl\x8a\x8a\x90;\x15\x8f\xa5\x81\xd3\xd5\xe6Am\xd3\xa2d\xdc\xa7\xcf\xff\xd6\xdf\x91\xad\x96\xa9p\xf2\xc8\xb1\xadrGV\xb3\xf4g\xe6\xd4\xa5J\xbe\x92\x86\x14\xe06\x17o\x83\x87{\x1a\xc1J\x02\x93^\x1ely\x01\x12\xabb\x9f\xa8^\x8c\xb3\xcd0\x8ba\xf5U\xeb\xce\xc2\xabk\x8b\na\x94\\\xb3qWvmy$C\\\x1d\xa7;\xdb\x10b2\x10*\xed3\x89\x8c\x02U\xbd\x8d($\xbaas\x0e\xb6\xca\"=b\x0ey\x0f\xf7\xaa\xfew\xbd}\xa7;\x93\xfd\xe8\xdb\xb4\xd8r\x12\xaa\x01\xeb\xe7Mb\xf0\x88\xbb!>\xe2n\x86|V\x83G\x0ft\x9b\xf4\xf4zy\x11\x05m\x9an\xb2\xf34\xd8\xe1\xaa;\x98\xdby\x1a\xbc\xad\x0d\xce\xd6\x03\xb5q>\xfeG}\xa7\xfb\xf5\xf1\xf7\xe5\xb2 /S>\xe1\xa9\xe5\xd4\x1eXj\xb9G\xeaxXn\xb9=\xf55\xcf-\xa7\xbc\x9d\xe6HR~\xbf\xe6\xefU4\xbd\xe6#T=\xe4\xe6\xfc\xbd:F\x9eV\xae\x82\xed\xec\xb5\x1a\xfe\x92\xa5\x94\x1b\xe83\xcaU\xb0\xed#\x9b\xa8\x1a\xfb\xee\x94\x81E\x95\xd6\x8e\xf9\x08\xd5\xea\x87|U\xd5N\xdf\xb0\xf7j\xf5\x9f\xf0u\xc5\x0d\xf5\x12Fp\xa8\xe6\x90{ #x\xa3\xbe|\x85i\xe1\x94\x97\xefP\x1ed\x18].9\xc2\x92\xbf\x9c\xbey]~\xff\x16FpD\x8f\xf2\xa3n\x82\xaaW\x7fv]\xaeqB\x05G\xdb:_\xf8\xd3) U\x11\xfc5+M\xa3\xb7\xb1\xbf\xf4\x99\xadv\xb9\xc67\xe8\x00\xa6\xcd\xb9_\xae\xf8\x9c\x92{\xdbJp\xf4\xdb1\x99\xfbI\x1a_\xab\xcd\xfd\"\xd7\xaa\xa4\xb9|\xc1J\xa3\xd5\xb6\xa1\xc2{M\x12\xf3r\x8dg\xa6\xf8\x01\xef\xca\xf5~F\x88\xfe\x955V.\xfa\x1eF\xb0\xf53F\x0e\xffY\xca\x08\xa0\xfc\xdd\x9d\xf9\xe1\xf4h\xe1\x07\xd3\xf2\xd7\xdf\x02\x8f\xf18\xa9w\x8d\xe3G\xdf\x03\xd8\x1a\xc1\xa9\xfd\xd2\xfe\xfb\x0d7\x0f\xd33\x91\xed\xe2\xb1@\xd1\xf0K\xd9\xe4\xac^0\xe0\xda\xac\x07\xc6J7N\xd7\xd3\x16V\xd9\xf2\x1bG\xad{\xe3\xc8\xd1\x0f\x0c\x8c\x00H\xa4\xf8\xd2~\xaf\xbf\x9dE\xd7\xd5) HJ\xe0\xfd\x98\x9c\xb9t\x92\xbc=\x1e8,\xc5;\x8a\xf7\xf4\xe7Kl\xa6\x12 \xf9\x06\x86\xf0\xb2\xbcd\x1fj\xb5\x9e \xd9\xd0\xff\xc2|\x0dO\xedw\x05\"\x98\x0d\xd8 K\xa5\x9bV\"|\x96\xbb\xff\x1aF\xf0\x8c\x8e\x98o\x8b\x12\xd6v\xc5\x91]\x02b\x0dBi\x1aI+\x00h\xd5R)\n\xf3\xbb\xba\x19|\xd5\x82\xd5+5<\x12\x8b\xf4\x95\xfd\"_\xc0%\x8b\xf2\x0f#\xb8\xe2\x19\x8d\xe8;Z\xe2\xdb\xbf\xe0\x9d\xdb\x01\xc6c\xc8 \x10f\xe4\xa3\xfd\x9d\xb0\xbc\x93\xe3\x93\xb31a\xb7\xa6\xe2\xf7\x88\xe7\xa8\xc0E\x0bM\x1b\xa1hr\x08\x1f\xed\x1e&\xb6\xd0a6\x0c\x8b\x0e?}b\xd8w\xe2\xc2G\xbb\x8fyv)\x7fR\xf4K\x87\xffm\x0e\x0d\xfa\xed\xcb*_\x0bU`\xfe\xa1\xcd]\xe3R\xeb8\x91;\x93\x87\xcca\xfc\x9a'\x82#th>K}\xc2\xa21\x8a|\xdf\x11<\x05\xff\xb1\x03_\xd9)\x83R<\xf61n\x00\x19\x87\xba\x10\x96b\x05\xeb&\xf0\xe7\xd6\xdb\xe9\x9b\xd2](.|\xcaRY\x19{\xde\xc2\xda\x05\x02!j\xb0\xbc\xa3[>E\xa6\x94\x19\x04\xd8[6#\xd9\x85\x0b'\xff\xf3\x17\xf1[\x94p\xecY\xf8 ]\xbc\xf4\x0c\x0b\xd5k\xd9\xf2\x14\xff\xd2f\x8d\xfc\x19s\xdc\xbd\xd0\xe0\xb5\xa0S\xf9\x90\x08\x1f\xd2\x0b\x16bY\x8f\xa7\xc2n\xe6\xd2\xae\xb1_\x11\x80\n\xab\x8dW\xb6\xca\xa7O\xca\x8e\xe2x[\x8d$sS\x07\x8e\xbf5\xae\xb8\x1a\xee\xe2\x95}\xc1\x9c\xa0c\x1e\xc1 \xe2\x11\x0c\xba\xa5\xdc\x8fl\xf4\x94\xd9b) qe(e;\xc9\x7f%,T#\x0bDa\xc6\x9b\xb8n\xfc\xdfm<~N\xc2\xd8\xf8_a\xe0\xa1\x170\x04>\xa9\x88OJ\x84\xee(&\x95=v\xc4\x9a\xe0f\xcb\xc4\xacB\x8e\xc1\xef\xc5jElJ\xbf\x8cI\xcd>\x8c\xca\xb3*\xea=\xc3\xa5\xf5l\xfb]]\x14,\xc4P\xba\x9ddB_\x0d\x99n1\x96\xb4\x88\x0f\"\xe5(\xaeDN\x17W^+\x9d\xcfX\xaf\xe43\xd6\x93\xbc:\xdd\xca\x14\x89\x94\xd3\x01\xc9\x19\xa9\xac4\xca=\x04\x9b\xf4E)K\xc4\xffOr\xd3\x87\x98\xb4\xe8/.\x15Q`\x04_a\xc4\xa1\xbd]\x07\xff:\xc6\xff\xff\x8d\xbe\xdb\xe7\xaf\xfe\x8c\x15z\x0f\xd9_\xdf\xf1\xf4\x97[\xa1\xfd\xf0!\x02\xd5\xa3\xb3\xb7t\xe2\x82\xe5\xd2\x8f\x91\xbcL\xbb\xf5\x17\xcd|\xbc\x1f\xecEIuE\xc7\x9b\xd9\x19&B\xca0\x11R\xc6T:\xcfTh3\x84\x1dJ\\\x8bl\x17\x90o\xe6\xbfRaa\xe1%/9\xfa\xbb~r\x14\x85\x13/=]\xc5\xc4\x9b\xa2\x90#\xf8/\x17\xcd\xce]n\n\xe623_\x97\x87rt\xd1x\xc8\x95\xe4(W\xac\xcb;o\xee\xca\x99\xfd\xb9\x9d\x91\xe5Z\xf4\x18H\x19\x85\xf8k\xb1E\xd2\xf4\xb1\x03\x0b\xfb\xaf\xe34-'\xbd-HP\x8a\xd9J\x16\xdd$\x8dbB\xa95o\x85\xa4E3!mfm\x93t\x1c*\xedP\x08\x9e\x96`\xc7\xf7w5\xa0Q\x14\xb7d\x15}\xfb9=\xd3:#4^<\x80\xe7tO\x0d\xd9?\xa3j\xea]\x85\xfc^\x92\xeb\x17\xcd]\xa19\xe7\xd7h\xceY\x9b\xd3\xc1\x03\xc6\x01W(\x13\x94\xc3\xed\xf8!<\xd7\xdb\xd3\xd1\x9e\x9e#\x177\x92\xe3\xbb\xd72\xf1YBNI\x9a\x92\xb8AJ\xfb^\x17I\xb2\xd2\x92\xbf\\\x05M\xf6\x05\xdf\x97\xb3\xd7\x01\x94\xf5\xba\xaen\xa1\x0d:O\xa6\x9ao\x91\xca\xaej\xe2F\x99\xf0S\x1b\x93\x96\xfd\xc1>e\x9cN\xedb\xab\xfa\xd5\xafj\x8a}\x92\x0c\xe1\x0f\xe5\ns\x92\xbe\xb9\n\xc5\xf7\xcfI2\x89\xfdUJ\xd1\xe7/u\x15_{K\xda\xd8\xdf\xea\xea\xb0m\x90\x0c\xe1\xbb\x12\x1cQ\xc1R\x06\xa6\xbd\x85\x07l\x8d\x88/\x8e\xc1wjxL!\xa6\x8d\xc3,\x08\xce0\xfe\xcd[[p\x9d\xd6\xdfo\xf8\x9b*\xec\xbd\x8a\x11\x8f\xf2 [\\\x85b:.X\x7f9}\xf3Z\xe3@\xce\xf5EM\xfb\xae\xc4\xfap\x86-=\xe3Y\xe4\x1f\xebb7P\x81\x82sd\xc5a\xef\xebSx\xf3<\xaf\x9c\x1d\xea\x9f\xb9`\x9f\xdb\x95\x94?\x9c\xc1\xffZ6\xe6\x9e\xf3j6i\xc3\x8c\x8b\xbe\xb4\xba!\x16\x1a\x08\xf9\xcc\x8au\xa6\xe3\xd2~\x89c \x03\xc0\x91\x84\x8e\x9dN\xc3\x85\xb7\xdc`\xe9\xa8\xaaz(\xa1\x95\xa4B\x18\xbfFV<\xb4\x07\xfb\x8e\xacZp\xe1u\xa9\x1eK\xc2\xf2f\x86\xd9\xe4\xde\x15\x84\x1b\xff~\xe5\xa5\x0b\x17,\xfa\x0f\xb7S\x81\xc0\xe6J\xc3\x1c\x07\xb6z\xad4\xff\xd2\x0d\xd6\x9ec[K\x92z\xba\xd0\xbb\x1a\xe5m\xa4\xd7\x9a\x8b`\xa4\x8e\xaa\xf3\xf4\xaav\xebI\xa1\xe4\xf3\x93\xe3\x8f) \x13\x9f\xca&\x9f>\xd5\x13D!\xf8\xd4R\xd7 \xa5\x9a\xa8]o\xa5\x9eK\xec\\\xddH\xd6$L\xf9p\xa20\xb1\xa9\xc0\xaf\xec\xc7rW\xf5<\x0e\xe0Q\x9c\xa2\xf7\x91I\xdaC\xb5\x9c\xbe\x90>\xfe\x10\xac7\x16t\xa0\xd3\xf1\xaa\xbc\xa4x\xae\x86j\xb0Z\xf1\xe8\xb4wu\xb0\x0b\x94\x1cR\xd5\x91}}\xfc\xbd68\xf9\xeb\xe3\xe3\xe7C\xd8\xeaWKf^\x92~M\xae[\x9c=\xa0u\xe9\xd0\xa9\xbb\xb85$s$e\x86Fr\x99u\x8a\xde\x14o\xd1\xcd\xc2\x90C\x81e\x01\xc0\xe51J\xe3y\xbd\xa44\xa0\x17\x06{\xac\xbcz\xe1\xb9b\x1d\xd7\xd4\x9d\xa9\\\x93x\xf4\x8b)x\xfcq|\xd6\xad\xe6\xce\xd7\x84p\x9b\x93\xf4[\xe2]n\x02\xf9[\x01dK\x1f\xe3\xa5\xa8M\x8c\x11\xab\xe5\xe73\xc0q\xd5\x06\x1cQ\xf8\"&\xe4\x97\xc6d\x82P4>\xa1\xc7F\xd0\xa5\xc8\x8d\xe6\x146?\xa68\x98\xe8\xef\x19rD\xed\x0c\xab[\xd3\xe4\xca\xbd\x93\x08\x19\xa4'\xc6\xfb\xa6\xe4G\xe6\x89\n\x05]\xac\xcd\xd4\x16\xb2\xc0\xba\xe5\xb5\xc2\x83\xbc\xbaB9\xf7\x90\xb9\xfc2\x94\x02\x84\xf6\x1eug,\xa1J\xef1x\x05\xf30y\xec@\x92g.\xa7\xe7\x867\x9e\xa0\x96\x04\xe5{\xe4*2=O%\x19\x89l\x06\xd0\x87\xfb\x06\x08\xb1\x08\xef~\xc2RY\xc9\x07\x90If\xb5\xb0*\x92\x9c\xd8\xbe}\xa6\xab\xca\xed'_\xe2\xbd\xea \x1a\xb1\x1b:!oV\xcf]+b\\\xbfD\x06\xaf\xfcp\x1a]Q\x88\x16\xbf\ns\x17\x95m\x86\x83\x9aB\x9b\xb5@\x05\x80\xb1\xce+\xa0\x9d\xa8\x8f\x81v\xad1\x1b)|\x8bM\x9e\xe1\x88\xf3Di\x8d\x17 \xe6\xbc7\xb9\x94\xaa!!\xcd\xf9\xe3\xc5\x10\xb9kQ\xa3\xbd\x92\xcdS8\x97\xedn\xf4\x08\xe0\xc0\xdf\x1b-\"\xfa\xbd\x07\x8emy\xc9u8y\xb9\x91\xfd\x86\xf8\x94%GA\x1dL\xab\xef\xda\xd9}<\xba[\xbb\x8f\x9d^\xaf\xc6\x08+\xf9\x0c#\xac\xaa1\x90Y\x12.\xf73\xc4q\xf51\xa7U1\x9fV0\x94\xb6\xb2J\x95}\xbd5D\xd4F\x8c\xa1T\xd6G\x12\xba\x15S\xf9\xe7\xde=4\xa3+\x07v.\x14#\x84eCe\x11\xd9\x12\x92\x82\x97@.Ml\xa9\xe1\x18\xf44\xb0\x02\xa0!h\x17\x05e1+w\xe6\xb0\xc0\x0f\xe1\xef7\xd5\xbb_m\xca\x1b\xf3\xde\xb5\xf9\"R\xd1\xe8\x05o I\x82\xcb\x0d6\xba3\xbbb\x12\x00\xd28XF2\x188\x0e\x1d\xc0\xf8\x8c\xdf\xc5(Yf\x91l\xdf\x86:\x10}f\x8a*W\xc2\xc9\x88\x0c\x0d\xa3V[(\x95Y%\x96\x0f5\x95\x1ceF\x10\xc2\x90\xe5\xc0 \xdb\xf0\x17h]\xb0\xd5wL\xfa\xf6\xc9\x82L.\x87\xd2uB\xabM\xdb\x8aN\xecT\"\xe2}.\x9d\xd8\xfdlKD\xc3!\x14s\x1bUVg\xb3\x81\xdd\x8e\xdc\x08\xc5\x1bZ*\x15\x1d\xb6\xa20M\xf6l\xbb\x06\xdb\xd3==\x97\xb8S\xb1\xf2b2\xfbN_\xb5\xf2bl\xdc\x8e\xfa:\xe1\xd5u\xe9\x89\xe9{\xb5\xf9\x19\x7f\xaf\x0e'\xe0\xcd\xab8\xba\xc2Li%+\xe2r\x85\x85T\xe1\x857I\xa3X\xb1\x85\x9a\xb2\nA\x14\xea\x1bXW\xe3@\\7\xca\xf0mn\xc4\xe7Za\x19\x8d\x87b\x12\x9aD\xfc\xa5\xb7\x1aB\xd4]z+\xbdp?\x8b\xe2co\xb2\xa0u\xf8O}\xbdI\x94\x85):\x1e\xd3\x1f\xfa:i\x84\x04\x90\xd6\xe2?\xf5\xf5\xa20\xb8\x1e\x82&\xe7Y\xb5zn\x9c=\x04\xbf[\xe3\xd3\xf66\x8bI\xa9n\xe9E\xb5~ \x03\x86\xa0\x01\x8e\xbc\xc2C\x98V+\xf8 \xfau\xe5U\xbcn\xf9\x8df\x90q\xb4\xa2\xc7j2\x04\x8d\xf7\x1c\x1b\xd2Q\xe0%\xc9\x10f\xa6r\x8e\x93C\xd0\xac\x13\xab\xf1\xca\xff\xe8\x87C\xd0\xc0\xfe\xf9\x9bWC\xc8\xaa\xef\xd7$N\xfc(\x1c\xc2\xa4Zv~\x9e\xe05\xd6\x10\xd6e\xe4\xd4S\xc8V\xa99\xea\x89\x8e\xacQ3\xf4\x12\x7f~/\x94V\xe9y\xaa\nM\xe2\x02\xb0\x81\xb2\xf5T\x0e\x96\xa5\x13M\xaf\xa2C\xae\xb6~\x1bE\x81\x9a\x8e\x14g\xd1\x9dEY\\W\x8bR\xbd\xfb?\xdc\xef\xdc\x9f\xeb\\{gFA\xc8\xb6,\xe8@\xea\x94\x82\xbd\xff\xe1\xde}K>\x8f\xaa\x0d\x06\xdas\x0d/|i\x1df\x85\x86\x7fN\xa20e\xb9\xb9H\xfe&c7\x88\xb5=\xact\x0b\x05\xd2\xb2\xa4\xd8\x93f\xb3a\x19\xefV\x91\xdb\x99l\xe7c\xc3)\x1b\x88\x9c?]7\x8e\x85\x18\x87\x86\x93\xc4\xe9\xc4$a\xde\x1fb\xc6\x97\xe4\xfamLf\xfeGi\xce\x1c(a\x05(\xf1F@\x996\x03\x85\x0d\xa7\n\x96\x0cK\xf3\xb1U+x50Md\x98j\xa8 ;\xe8(l\x13\x05\xb6\xe5\x05(\xe97\xec \x95\xb1\xd7\x14\xe3b\x84o\xd4M\x17^z\x82\x88\x99\x08d\x17\x8e\x9c\xb05b\n0\xdbW\xa8'm\x87\xbe\x9f\xa0\x9a\x08\x89\xf1a8=a\xf8\xfc5\xb9\xa6\x1dd\xd0\x01{kB\xe7\xcf,yP\xb9C\xff\xc2\xe4\xf2\xf8\xeb\x00,\x0b\x860\xb3\xf1O\x87\x8a2\xf7Qg\x1b\xa2\xe1\x10S\x05M\x9cztYK\xe8\xe2V#g\xacy\xd4\x0c\xd5\x89V\xcc\x90\xdd\x0c\xa1hf\x87b\x08U\x83\x17\xbaV\xe8\x9a\x8b\xa4`j\x13\x8c\x8c\x81\x1d\x96+\xa3\xc6\x7f\xea\x82\xe7\xb8\xb0\xe8\xc6$ ^Bl\xaf~\x0e\xd7&,\xe34\x83\x0eVj@\xfc\n\xa4\x8b\xa3)\x11\x06;u\xf6@\xa5\xad\x81\xee[\xca\xee(\xbd\xacl\x10\xba(\xdetJa\xe0\x87\xf3w\x91\x1d\x88\x89\xdej \xf9F\x96z\x95\xf7\xb2\xf4\xfa\x0e\xc7\xbcp!Q\x04\x8c*\xfb\x96\xb3^u\xa7\x98xP3J\xf1\xa9dM\xa0\xb9x\x10D#(c\x92.\xc9:\xe2\xd1\nS\x17@\x90\xe3\x91z\xdfX\xa6\x0c\xc8O~\x91\x01\xeb\"p S\x01\x9b]q\xb1U\x10\xa6\xda\x0d\xc3|\x19\xa6\xd1\xb7~\xba\xf8Z\xac\xf6\xcb0%q\xe8\x05CX+\xc7,\xe3m\x1b\xf5&B\x87G+\\s\xd7\xc3\xbaA\xe4\xfcp=\xf3/\xf4\xe4M\x00 \x02\x00z\x92Z1\x10/\xf0\xf3\x8b\xf1j\xa1\xbd\xaf\xd31\xdb\xa1M%\xaf\x86y\x0b\xc3\xc1\xae\xd0\xa0Pl\xad (\x07\x12\xac\xaa\xdf\xad\xa2\x95)\xf3\xb5\xc0=\xdc\xbd<\x12|\x15^P\xa7p \xc9\x15~_1B\xaa\xd5\xbfi\x95T\xb2\xc2\x08\x0d\x0f?}\x82\xd8\xb6\x06{h\xcb%\xd16\xdbq5\xf3\xe4w\x1cOx8\x90(\nN\xfd_\x880>V`B\x0f\xb7z\xb3\xa9\x0c\x934\x97^yZAS\xa6o-\xf6\nH\x96\xc6\x86\xebQ\x01\xda\xd2\x98\xb9\xd1kXP/\xb4\xeb\xf8\xf4 2\xfa6\x9f/3:\xce\xff\x1c\xb1\x8cp\xa1\xa0b0\xa2g\xa7\xc6\x02\xb9\xca\xe7P\xce\xa2\xc4\x83\x0fU\x80\xd0\xa7\xc2\xcf\xb7\x84\xc1m\x90\x1cd\xd8m\x82\xe8\xa0Cv\x11\xa8P\x07\x0e\xd0\xe2<\xe8\xf0\xbeb\x92\x05zp\xa6\x8b\x98T\x00\xda\xe6\xc0\x80\xcf\x84V|'\xd0\x8a\x19\xb4tG\x8cx\xda\x03\xac\xe2\xa5\x01z\x98U\xe5\xc0*\xc8\x0c:o\xf8L\xa8\xf9w\x025?\x87\x1a\xe3&\xaa\xb6\x03\xb0)\xe0*\x86O\xd5\x16\x0c\xe7\xdag\xc4\x0fk>\xd7\xfa\x05\x1f\x15?f${\x1f^\xd7\n\xb3\xe5\x05\x89\xe57\x05Ty\x17\xa4\xfb\x87?\xf0\x91\xd1wE\xfe\xf4\x99\xcd8V\xcb\xca\x93\x87y\xd0\x81 \x9dp\x0f\xc5`\xc7\x05\x8d\xc5\n\x9dqM8\xd65\x8a\x9bR\x93CLd\x93\xe8\xa1R\x96\xd0\x89\xc6\x1f\x01d+\x8bkfOq\x0dO\xf2$<\x8f\xe1\xba\xd3q`\n\x9d\x11\xa4\xf6\x8a\x9e\xc9\xe3\xeb3\x17\xd68\x97\x95\x0b\xd7\x0e_\xbd\xea\x0808\xa6\x99C\x98\xb3,\xa5\x06rC\x87?o\"bK\x17\xdd\xc0\xe7\x9c\xbb\xab\xa1\\\xd8\x1c\xbb\xe8\xec\x920\x8d}\x92\xe8\x81!\x9e\x1c(\x17\x0c([\xf6\x12Fp\x8e\xa9\xe9m\xc7\xe9N\xa3\x90<.\x01f\xc9\x0c,%\xd8\\t:f\xe8\x88\x87B\xa9y$\xc6\x01\x98\x01$\x1e:\x89\xabb|\xe6\x91\x88\x07\x0d:lifWhZ\xbbF\x03fN.\xae\xc6\xbd3\x87\"\x9e\x98kO\xcc\xb4\x1e\xac\x06[B\x86+\xb8\x91K[\xac \x01>\x1a\x92\x91\xc9\xcfi\x11+\xba\x0eCb\xdb\xda\xe9[naG\xc2n\xdd\xce\xd8HN\xe1@\xec~\xb8\xf2\xd3\x05\\\x92\xeb\x04\xfenAG\xdcg\xd3\x176qx\x9a[\x17P\xd9d\xddX0\x84S\x17>\xb65?3J\"\xd3R\xc1\x0d\xa5\xb8\x96\xa5\xf2\x1a\xadn\x1b\xeb\x8f@\xad\x8d3\xf7\xe1\xbaw\x8f\xff\xca\x1d\x8b\xabg\xa5\xf5/\xff\x92\x07\n\xd1\x9f\xd3f9)\x97\xf2\x80\xc5\xcdEg\xc3\x18\xcd\x9b\xd3\xb1\xafZ\x80\x1b-\xb2\x89\xc6\xdc\xfa\x0e S\x1e+\xdb\x08me|=\x1a[#k\x08\xd6\xa8g\xc0`k\x88\xc5\x83j\xb8\xa7\x1b\xa3\xc6\xc0\xfa\x03\xc5\xc9\xcaE\xc0\xfd\xf1hxv\x7f\xde$\x9aK\x0d\x91qzV\xed\xb7^\xa6\x0c\xef\x06(=\x9c\xb6 (\xa3\x01-\x1en\x02\x14\x06\x0e\xdb\xea\xb2\xcd\x9c\x8e{\xe8\xe8Ma\xc5\xfe\xee\x9f\xa1\x8dD\x92]0.\xc0\x1e\xd0#Z~\xd1w\x1c \x9a\xf6\xa8\xf7i4p\xee\x1e\xa0\x05\xbe\xea\xf7\xce\xdd\xdc\x80\x0d\x9c\xba\x9bn_\xaf\x07\x18R\x12Y\xb1\xe4\xc7\xa2\x8b\x8b\x98\x95^\\h\x83~z\xd3iL\x92\x84\xd5a\xbf\xb5\xd5b\xc2{\x89\x89\xbe\xa38\xf5'\x01\xe1u\xf0\xb7\xb6Z\xe2Oy%\xfaK[%\x9b\xfa\x11\xabB\x7f\xe9\xaa\\`\xf1\x85\xb6\xc8KX\xfb\xf4\x87\xb6\xc2\xd4g\xe5S__\x1c\xf1b}\xcf\xfe\x9c\x15\xfbsmq\x10M.\x7f\xce\xa2\x94\x8f!\xffS[9\x9a^\xb3j\xd1\xb4\x12P\x05+\xb0\xa5\xd3/\xdcE\x96\xa6Q\xc8*\xe0O]\xa5\x89\x17\xae=\xb6\xb8\xec\xa7\xbe\xd2*\xf5yS\xfc\xb7\xb6\x9a\xcfgE\x7fh+D|i\xe9\x0f}\x85\x80\x97kc\xc6N\xa2`\x1eG\xd9J\xd4\xc1?t\x15\xa7^\xca\x90\x91\xfe0U\x08\xfc$\xcd+\xd1?\xb4\x15\xa7\xac\xcaT[H\xd8p\xa7D;\xdc)I=?Hx\x15\xfc\xad\xad6c\x90\x9d\xce\xb4P\x9d\xfa^\x101\x9cb?\xf5\x95\xd6\xbc\xc6Z[\xcc\xc7\xa9\x1f&\x87\x82v\xfed\x89\x85d\xa9/\xbc S^~A\xb4 \x9a\xf9$\x98\xa2\xe9`l[\xe2\x0f}\xc5\xb9\x8cf\xc5\x9f\x86\xcaYLD\xc5,\xd6\"\xd3,\x8a\xd0+\x93V\xc2\x9f\xfaJ\xf1\x92W\x89\xb5s\\\xf4\xb1x\xd1\xd7\x16\x0eX\xe1@[\xb8\xc3\nw\xb4\x85\xbb\xacpW[\xb8\xc7\n\xf7\xb4\x85\xfb\xacp_[\x88V\x1f\xb4\x98x\xda\xf5\xa0\xef9P\xd8Om\xa5b\x97-\x8c{l\xc1[\xd1\xb7\x90.\x19\xca\xd1\x1f\xba\n\x8c\xc4j \xac?\x8b1\\&-\xc7\x9f\xdaJK\xb6%\xfc\xa5v?\xf8\xe1*c8\x87\xbf\xf4U\x12^A\xbb+//\x18 //\xb4p\xbc$\xd7s\xc2P\x95\xfd\xd4U\n\xbc\x0bN!\xf0\x97\xb6\n\x99\x93\x90\xf5\xc4~j+1h\x05Zp\x05~x\xc9\x8b\xc3K]\x85\xa5\xe7\xb3\x81\xd2\x1f\xfa\n+^\xae]\xe8\xa5\x17_\xf2\xf2X\xdf\x01 3V\x81\x84\x99\xa9\x82\x9frR\"\xfe\xd0W\xe4t[\xe7w\xc8+p\xec\xc5_\xba*\xa1\xc7Ha\xe8iIa\x181\xbfaV\x87\xff\xa1\xab\xc8\x04F\xac\xc6\xc5Z]%\xb6\xbc\xfa\xe3*Z\xa5\xc5F\x12\x7f\x18*\n\xba\x17\x19i^\x94\xa5\x02\xa7\xd9O]%\xd6\x97\xb6\x93\x95\x17{l\x05\xf0\x97\xb6\x8a?I\x05]\xe5\xbf\xb5\xd5D\x15Sq4\xcf9F\xf1\x87\xae\xe2\xcfX\xe3g]Q\xcc&\x12kg\x123(\xc4Z\x08\xc4\xd9\x05\xe3\x99\xe8\x0f]\x056.\xed\x80\x12o\xc9\xfa\xa5?\xb4\x15\n\xd41#NB&\xf9r\xf2\xdf\xfaj\x81\xc0/\xf6S[i\xe9\x05\x0c\xc5X\nN]\x15L\xa3\xc4\xea\xe0Om\xa5\x95\xc7\x07\xb4\xf2\xf4\xa3I\xe3(d$\x95\xfd\xd4W\xba\xe6\x0c<\xfe\xd2V\xc9\x18\xeb\x9ddZ\xe6;\xc9\x96K/\xbe\xe6U\xf0\xb7\xbe\x1a_\x07\xfd~IY\x1c\x95\xd8\xb6R\xe6\xdb\xa2\xa9\x92\xf3\xce\xa9\x89yN\x19\xd9M\xb5$7%\x1f\xd3\\\xa4\x11\x7fh+R\xde\x82\xd5\xa2\xbf\xb4U\x16\xac\\\x9br=\xcd\x8f\xec\xd4tf\xa7>?\x0e\xe9\x0f}\x85T\xc0\x03#L\xeb\xaa0\xaa\x99jIf\x1a{\x93K^\xeeM\xb44\x9e\x11x-u\xcf\x18\x82fZ\xec\\{\xac\xe3\xb5\xa7\xedy\xedO \x13\xa7\xf0\x97\xae\xca\x15\x17r\xae\xf4R\xce\xc4\x8f\x85T\xc9~j+\x05\xfe\xea\xad\xc7\xd7A\xfc\xa1\xab8%3\xc1\xaf\xcf\xb4$\x82\x04\x81\xbf\xe2\x02$\xff\xad\xab\xc6v\x92\x9e5Yzs\xce\xdd,1\x93C\xb5J\xe0\x87\xac\x06\xfda\xaa\xe0\xc5_\xc5\xde\xd4G3f^\xb5x\xa5\xfbh\xe9%\xe2\x1cO\xb4k\xbc\x12\x10Z\x19\xa0\xb3\xf2\xd2\x94\xc4\xa1\xa8C\x7fk\xabE\xc1\xf5\x9c\x13@\xfe\xdbT-\x9f\xa9\xf8CW\x91\xce\xc9\x0bJ\xb3-\xbf\xd2~$\x88kl\"\xadi\xc4\x89L\x1a\xe9\x89\xfd\x9a\xd3\xc3\xb5v\x1d)Q\xc8\xa9\x83\xb6BNtSFuK5\x0c:\"v {\x07:\xa2:\xbbvn3\xdd7\xb9\x07\xfb\xc2\x9e\xecs\xc7\xd1\xdf\xdb\xd8\x01Yx\xe4\xd0\xfe\xe4`\x8cw\xa0\x03\xd6\xd8\x83s\x8f<\xf5\xf6\x97[\x8f\xebcYT\xdckx\xa8\xe7}5V\xb0\xf0\x8b1\xf9\x18\xd7\xda\xa2\x08[\x92\xcfQ\xe9\x03\xb7\x08\xd6\xab\xf5E/3Z\xe3\xc9\x13/\x8c\xc2\xebe\x94%O\x9fj\xb4\xb7\x81Q\xe5\xeb1s\xb9\xb5m\xe1/\xddN\x00\xd4eQ^ym\xe7\xf7\xba\x86zt\xbaX/\x9f\xb7\xa1\"\xbb\xe0\xc5\xaa\xfc\xae\xd7PQ0\xf2\xeb:F\x1e\xf2\xc08X\x91\xdf'\x9b*\xf2 ck\x11\xcf\xd8T\xd1\x0b\xaf\x870\xb5c\xd9\xf6\xef5^`\x9bA\xf9f\xd6\xa4\x82\x17\x8f\xb8\\*\xe2\x99\x14\xe6\xce.DM\xf7\x8b\xca\x15\xccVal\xe0\xc8\xf6\x1d\x0b\xdb\x12n\xdf\xf0\xa3\x05\x1d\x88\xa0\x03\xd6\x8f\x10\xcd\x8a\x94s\xac f\x05\x0b/\x01?\\S\xea\x93{\xcf@\x18\xa5\x98\xc0\x82\x8a\xdd\xfe\x94\x88\xa9vM\xe9C\xc5C\x11\x14\x13I\x8dCC\xb2W\xf1`D\x89\xf2\xa5yV\x1b\xb0B<\xb4\x0b4\xad\xacD\x17\xd0=e\xc8\xbc\xe4\xf3\xa4\xd3\xf71\x16\x99\x02\"\x0c \x8d\xef\x12\xf6.\xc9V\xab\xc0gi>$\xa8\xb9@>\xae\xc8$%S\xf0B\x06\x9d\xaeu\x9b\xebX\xf1\xe4w\xe0<\xd0\xc2\x04\x9e@\x96\x1b\x06L:\x9d\xb6\xa0\x99aj\xc9\x0c\x93\xe2r\xcc\xa2#\x1e\xd3\xb1O\xe8\xaf3\xcb\x05\xaf\x05\xe4\xe8\x02\xcddCJ\xf4T.\x8c.>c\xb2:sx\xf5\xb91\xdc\xe2\xea\xb7\"\x11\x1eb\xf9\xde\xfa\x82;qC$O7@l\xef\xcb#\xb6\xd7\x1a\xb1!\xf1\xc3y@\xe0\x84x\x93\x94s&\x9f\x87\xe5\x9f\xb3\xf0\xa6\xack\x02C\x7fWB\xbce\xd3\xc5/\x99\x19\xb7^c\xe6P\x14zK\x16)K?+\xf5\xf1\x1a\x8d\x9eM\x0f\xc3\xc1\xae\x14\n\x16\xe3\x0d\x97\xde\xe0h\x8a\xad\xdd\x8c}\xe2\x11vp\x95\xc6Z\xb5pc\x1b\xa2W\xab\xcf\x97Gv\xb1\x92\xf4s\xac\x91a\x8d\x7f\x1c\xba\x1b\xb8(\xbc\x92\xbb%\x91\xabu\xb0R\x1fD\x9bk;\x1d\x933Ge0\xe4\x05\x88\x8b\x05\xf0\x0d\xc0\x0e\xab\x94\x05I\xca\xebhJ\x1a9\x8a\xcf\x81\xa1\x89d0\xbe\xf2w%\x18\xff0\xceM\xcc\xb5\x11\xd0\xf2\xa9\xd6L\x93\xdaq`%+\xb3\xad\xd1\x08\x92:T\xbaC\x8e\x8c\xf5\xd98g\x89\xeb\xf2C\xc8\xea\xf7:\xf0 e\xdd\x85\x97H\xd1\x95\xecI+\xd2\x0f\xf5\x0cZ\x17\x19\xb4v\xac\x19|.{\x06\xff\x00\xd2\x15\x85\x1b\x1c\xd1\x1a\xe9@\x8aTW\x11\xd0jL\x0d?o\xeb\x16Q\xd1\xc4\xce`\x810\x1f\x83\x07O \xcd\x19tO\xf6\x866=tR+\xba\xf2\xe9\xd8\x93\x89j\xed\x04@\x12y\xfer\xfa\xe6u\x91?H\x9bYB~6\xdcih\xb2*\x1f~-\xb6Z\x14\xe2\x89\x99o\xcf\xba\xf3\xf2\x16\xe8B)\xda\xef\x8e2R\xe8i\x16\xad\xbb\xb4\xd2\xa4Y\x14\x13\xba\xa0T\x9b\xa9_~\x8c'C\x98\x0f<\xb2\xb7\xfa.\xe4\xab'\xe2\xf4\x96\xd6&\x87U\x17\x8eU\xb1\x14\x8f\x8f\x05\x99\\\xe6`L\\\xb8\xc8R\x88\xc9\x84\xf8k2\x85?&\xe0\xa5\xe0\x87S\xf2\x11\xfe\x98t-\x17\xce1\x99\x0bA\xe7m\x05l\xe6\xd5\xfd]\xb6`\xef1d\xa5\xe5\xc8\x9a\x97\x03\xa4\x1d\x94\x8e\xb3\x86%\x01(\xfb\xd5&\xe5\xd1R\x02\xed\xb4\xa2\x8e\xd0\x9a\xc6\xb6\xd9\x9f\x86\xadxw\xfb-Y\xb4\xb0&\x15\xcfg.\xe9\x7f=\xac\xc6\x8f\xac\xc7\x1f7\xe44Z p9\xb30\x9e\xb4\xc4\xd9Y\x9bf\x817\x1d`\xac\x84;\xe1C\x82\x1c\xd4\xf5\xdb\x01\x1a\xb7D\xbb\x0dswL \xf9\xe8M\xd2\xdf\x11\xeb\x93\xd6X?A\xacO6\xc5\xfa\xc9g`\xfd\xe4\xce\xb1^\xa0p\x86q\xed\x18\xff\xd4\xc4\xb5\xe4;%\xa0;\xa5\x15J\xd3\xda+\xdc)A\xcb\x9d\xb2\xb5\xda\x0cN\x97\x84\xcbdA=9\xfe!|\xe6M\xf3+\x0cZ\xa0\xf0l\x0c\x06,\xc6\x80\x05\xdcs\xe5\x87\x10/\xff\xd0\xd1E\xfb\x95\xec\xf7\x92:\xa5\xef[l\xd35\xf7s[\xd9\x89\x0bAu\xb7\x07\xedv;\x85\xdb4\x07\xdb\xf4\x1f\xb4\x8f+oo$\xafM\xa8\x06B\xd2\xe1\x8f\xd0Z\xe5\x891x\xf2\x02\xf8\xf4 \xfap\x1f\x0b\xf0\x07\x81!f\x00c^2\x84\xfeR\x03@\xe8\xfb^\x18\x02\x13,\xfc\xa4\xbb$I\xe2\xcd\x89\x14\xf8(I\xbd\xc9%\xbaW\xb5j|j\xc8\xff \xcaC\x9b\x11\xa5\xc8\x85\xcc\x85\x04)\xbc\xd6\xe5\x93>6=\x883\xa6\x89D\xa23\xc1\xa4V.\xb0X\xa5\x9e\xc3S.`b&dE\x8f\xbc \xf0\xc3y\x11j\x0dp\xe7xi\x14'0\xf5c2I\x83k\x91\xe4\x85n\x94(\xa6D\xe3\xe2\x1a\xd2\x05\x81\x1fWq\xb4\xda\xa6D'\xf9\x11V\xde\xe4\xd2\x9b\x93.\xbcO\x08\xfc\x987\xd8E\x865\xff\xd3v~\xa4\xfbl\xe2\x05\x01mb\xd9\x85\x13\xe2Ma\x19\xc5\x84r\xae\x8b4]\x0d\xef\xdf\x9f]t\x97\xe4~\x96\x90m\xfcz\xbb\xe8\xc7\xb8I$<\xc48\xd0\xe3\xe8\x0c\x0e\xd0\xd93\xf7W\x15\xef\x18\x91x\xb7 \x85\xacS\"\x9a~\x82\x86\x97\x94\xf1N &?g~\x8cZEY\x9eb|\xb7\x9f&\\\xd4\xf2\x13\xf8\x91vD\xe9(\x0c\xbf\\\x1f\xb9\xbf\xae\xe8\x88Nn\x08\xa9]\xc2\x91&Op\x90\xaf\xe6\xbb\x17~8\xb5\x19\x19\xda\xeak\xc0\x9b\x8b]~r\"F\xaa~\xd7\xabF\x981`\xfc\xba6\xa4\xa3\xe9@v!3a\xbd\xb8k1_\xe1\xf0\xb6\xe7\xb6\xe7p\xe2p\xd0\xee\xa8(\x1d\xa9K\xfay\xdbS\x95\xbeM\x05[\xcf\xd7\xa9\xba(\xaa\x17\x93\x1eb\xd7\xb6\x96\xf2%W>\x8b\x92\x9b{\xef\xe9\xe13\xf1\x12\x92;e\x0fk\xaa\xf0\x9b\xf7\xba*\x85\xbb\xb8\xbe\x16\x14\xd06\xa5 `\x0d S\x84\xe6f\x0c\x9e\xb7\xac\x19\xce.\x99[\xd1\xbas\x8b\xb6I\x97\xacI|m_7x@\x97=\xdeS\xb9\x89\xbaD\x0bk5Bc\xa3\xa8\xb0.9r\x86\xcc\x913\xe4\x8e\x9c\x93\xa6\xdb\x95\x8d\x1c;\xd5\xe7\xa6\xd1\x0f|+n\x953\x82\xce\xc1\x17)O[9\x98\xc7\x8a\x83y\x1b%\xc2c\xd8\xb2}LhPv\xec\xae\xfd\x12\x8a\xbb\x10\x9fyuK\x0b\xd97\x83f\x03gs\xdd\x98Zr\xbd\x18Z\xa8\xad\xb39*\xaf1\xf1\xc5\xb5\x9d\x8d\xfbg\xad&\x02mt;&\x8c\x16\xe1\xa5\x1b\xbf\xaf\xf6\x7f\xd3\x8a\xcc\xcd\xeb\xbd^\xc5=\x8b\xf1|R\xf5\x85p\x00\xdc.\n9?I\xbd~B\xe6\xc7\x1fW\x85k\xba\x05-\xa3\x13\xf1\x9e\xa4\xfc7\x9c\xd3\x14I\xa1\x18\x95\x18[\xff\xf2/R*B\x0b7p\x835\x19\x91\x07\xc8^W\xe1\xc8\"q\xd1\x81\x8b\x11T2W\x1a\x80\xbb4\xc7\x14\x93\x12\xcb\xe1\\rjW\\i1\xb7\xe8*\xe4\xc5\xda\xcc\xb5\xfa\xebJ\\\x82\xfa\xa8O2\x00\x9e{\xa9\x94\xb1g\xea\xa5\xc4\x90\xb4\xa7\xf2%[\xdb\xe2\xdb\x98\xcc\xc9\xc7\x95\xc6\xeb\xd9\x84F\xed\xe0y^\x8f\xac\xfaT\xd1\xe2\xc4n8\xaa\x19\xd2\xd6\x1d\xc3\x8d\xc7\x9e\x98\xbd\x17\"gS{\x86\xd6\x1f\xc5\xac\x0e\xae@]\x05\x0e\xe6\x16#\xaa\x1bP[\x1a\xd3\x14\x89\xae\xfc\x17\xffH\x8a\x88 #v\xc5&g/\x08\x14I\x05F\x94\x95\x0e\xba\xf2\x8b\xc0\x055\xe8\xe7\xad\xccb\xebb\x01\xe5W\xfaw\xd4\xbe\xd5\xdf\xeb\xeewy0\x84[\xb5\xb6.\xc2\xec\xef=tLa\xc5\xfdV\xf6\xcf>\x7fu\xf8\xfa{C\xbc\x87$\xf5R\x7f\xd2\xae\xee\xaa\x08\xb4\xde\xa26\x8f\xf2\xba\xc1\x07\x0b?\x98\x1em\xfa\xd5\x9c\xa4\xcf\x199\xa0;P\xf9\xe6\xfc\xd5\xf1\xc9W\xc7\xcf\xcd\x9f\xbe\x0c\xfd\xd4\xf7\x82\xd3\x14S=l\xf4\xe9\x914\xdcM>\x8dI\x88\xfe\xbd\xe2\x8b7\xaf\x8f\x8e\x8d \xe4[\xe8[?\x08^\xb1p\xaa-@\x92\x7f\xf6\xdc\x9f\xde\xe2+\xda\xd9 \xbb)\xd4\x80\xd4\x84G\x8b(\xa3\xe0\xe0m\xbc_MK\x10m;I\xf5\xbb6\xe3}\xeeOo\xf3\x19v\x17.[\xc3\xe7\xfd\xeb\xd3\xc3\x17\xc7\xe7\xb7\\\x13\xdd\xd7\x1b\x03Y\xd7\xc8\x06S\xcf\xb0\xaa\x94\xcf\xc1z\xf3\xe1\xf8\xe4\xe4\xe5\xf3\xe3\xf3g\x87\xa7\xc7\x1a\xe6\xa7\xda\xce\xc4Htp#\xc6\xfe\x9aLq7\xbd\x88\xa3e\xcd\x8el\xd3\xd7\xcc\xd8\xd7\xd4OV\x81\x87I\xceZ\xb2\xe4\x80\x84W\xfa\x0eT\xbd\xaex\x0c\xd7F\x82\xa6\xb6\xee\x8d\xb2\x9c\x9a\xd8\x9e\xf2\x93\xdf{\x84\xec\x9e;,\x85\x86\x0b;\x1d\x87k\xb4\xc7\xe1\xd9Fw\\\x1aR\xdaz\xdci\xb7\xf25f\x1b\xfc\xfb\x8d\xab+\xd3\x060\x85\x9a\xa1\xddzT\x86\x01}\xc6X*g\xc7\x06\xc3Q\xbe\xc5\x00G\xea\xbb\x11L\xed\xca[ly\xa8\xad\xbd\x11BJ\xa7\xf1\x06\xc3^Il\xaa\x00a\xfenS\xf8\xe5\xccC\xeb\x01l\xb5\xaf\n\xed\xf6\x10\x94\xf7\x91\x1f6\xb7*\x1e\xc1\xe85\x1b\xf5\x8b\x07\xc7\xa3\xda\x02\x86\xadm\x01A\xe8\xbd(\xbb\x88W\x9d\xed\xba\xa5Odo\xf9.\xfc \xadhy6\x9b\xef\xa3\x0c<\xbc\x10I\xc9r\x95\xfa\xe1\x1c\xd2\x88gi\x07\x0fb\x92\x90xM\xa6\x88)t\xa4.\xfc\xf8\xc7\xe4G\x17\xd2\x85\x97\xf2\x03;\xfc\xe1O)\\\x10\x88B\xbc\xa9\xb1\xf8\x8aZpI\xae\xbb\xf0\x9c5\xe5cn:/,,\xa6E\x8b\xf8\x86x\xd3\xc7\xb4\xce\x95\x1f\x04\x90\xa4\xf4\xff\x17\x04\xbc\xc9\x84$,94o\\\xb6\x17\xff\x93>t\xbe\xe9\x11z/\x04\x9a!\xee\xb5\xeeA\xf5\xd7&\xab\x03\x12\xcf=\xa9.4\x1c\xc0d\x1c\x9eqE}\xfbq@!^F\xb6\xee8D\xbd\x87\xe7\x82\xd5z}\xe9RR\xc8^GY,\x19\x0b\xe3\x0dY\xba\xf0B\x88\xc2 \xe9\xc2\xbb\x85\x9fP\xc8\xcf\x02\x7f\x92\xc2\xd2\xbb\xa6k3\xcd\x08m\xc9c\x87Z\xd7ba\x99\xd7\x91?\xb5Q\x8f\x8ct\x0bo\xad\xe3\x86\x80\x93\xf2S\x7f\x01,?\xbc\x13}\x1ch\xf5in\xd6\\\xe3\x86Q\x99Mh\x9a\x97\xa5\xd1\x85\x1fN\xcb&\xf7\x1b\xdcA\xeb\xd3\xfd\x80d$\x98\xa8\x88E(b%cbF\xacs\xcd'\xf7\xeeQd*\xb3p,tm \x8f0?\xc3\xcc\x9b\x10\x13BEk\x12\xc7\xfe\x94\xa3\xd4,\x8e\x96\x1c\xa9\xe8\xd7\x90\xac\xc8\xc4\x9f\xf9\x13\xb40\xef\xc2q\x98d\x0c\xc3RVkI\xd2E4\x85\x10\x93\xd1N#\xbc\x01\xa6-\x06\xde\x8a\x85\xf2\xc4\x91\xf0jhjH\x1c\x97\xdd\\\x94\xb7\x82\x08\xbb\xfb\xe9\x93\x96a\xbc\xcd\xcc\xbe\xc8V!\xedn\xe3\x90q3\xa7\xf00\x11\xa5\xc8`\x1cZ%\x0d\x7f\xaaL7K(\xd9/&\xc8\x160\x8a\x8bAQ2\xceg\x02/\x19\xe9v\xe1\xa7,I\xf9\xb71\x99g\x81\x17\x17\xb6\xf4.=w\x08\xda\x86n\xde\xff\xc6\xbd\xe9 \xea:\xcf\xd7T\xa8\xe1\x8c;\xde\xc7\xfb\xa4\xf3\xf3\x98\x0e\xf60K\xa3g~8}\xeb\xf9\xb1&\x863\xc8\xac\x83G\x8f\x96P\xddf\x19\xcb\x14\xdee\xdc?.)\xff\xedh\xa3\xd0\x8b\x07\xd7Xm\x8c\x19Vxx\x8d\xd5x*\xad\xb9ch8\xf6Z\x98\x8e\xadp\xda\x95\xfe\x9a/\x02\x03{\xc5\x12\x01\xcd\xaa_;0\x1b{gt\xd2\x93\x86\x96jbQ\xcb\x0f\x9d\xd3BG\x00\x9bF\nu\x86\xd3h\xbd\x82\x01\xc4W\xe8\xe6\xd6g\xa4\xa2+(y\xbb\x13\x0c-\xf5\x9b\x16E~\xd6<\xa4w2\xf6Zr\x8f\x80\xfb\x1b\x03\x9b\x9b\x99\x80k\x95\x00\xf2\xd7\xea\x0e|\x1f\xe6V\x04\x94D\xc3*\n\xfc\xc95\xfc1A\x94\xbe$\xf8\xf3jAB\xb6\x03\xe7\x14\xbd\x8b\xadI?Ab|\xcdV\xbff8\x07\x10\x8f=\xc6\x13\xd0\x1f\x14\x19`\xa8\x1b!\x8b*\xcc\xea\xae\xf3\xba\xed\xa0\xcfCT\xf3\xaf'\xcd\xf0d\x11\xadY*\x16\x8f\xf6\xe3\xe6\x1f\xd7~[\xc3+T\x8f\xf8V\x84~a<\xef\xcbbIds\x8b\xb2\x9a\xfc\x01\x9a\xf7\xc4\x05kI\xe29\x11\x89\x97^G\xcf\xb3U@\x0fd\xf25\xb9Nlg\x08G^H\x8f]\xac\x06a\x14n\xb3f\x12$\xe0\xc4\x01\x8d\xc8\xc2r\xa7\x95.\xf5\x90\xe1k\xec\xeb]\xcc-ZXo\xe9U\xc4\xe9w\xc2\x8e{\xca\xe9'\xde\x92P\x14\x1c\xe2\xd1\xdb\xead}LA\xb4\xc2\xa8\xb3\xf4L`Vr\xa2\xea\xc4\xcb\x12nNv\x15\xa9j[\xdb\xa1G\x9c\"L\xdb\x8e\xe088\xdfMw@i\x9c\xf4p\\\xd0\xb7\x97\xe4:\x11,0gL\x0d.\xaa\xc2\x86\xb0\x15ZL\x9bL\x11e\xf6\xd2x\xee\xa1OI\xd7[\xad\x82k\xccE\xe2\xe6\xde \x89\xc1\xd1\x91>(\xd4\x1a\xbe2\xdf\x8f\n\x9b\xb8\xc2\x11%n\xae\\\x18{\x84\xe6\xd3\x1bC\x1ek\xe2G\x83t\xebf\xfbl \xf0\x87>\xd9I\xbb\xfd\xb8\xfel\xc0\x1b\x01n\x04\xea-\x87z\xdd(*\x10f=\xa7\xbb%\x16`WzR[\xd1\xe77\x06\xfd5A#h@X\xb4\x9e\x9f\xfb ~\x84F~\x9a$\xeb\xa0'\xa9U\xa4]6\x0f\xb0\xa4\xaa\xbf\xf5\x18\xf5\x06/\xad\xc6xn\x1c#\x8fY\xce/\x90Z+\xb7p|L\x1f\x1fwI\xf8sF2r\"5\xc51lc\xe95\x9fpK8 c\x9c-\x15`\xb7\x87\xd5\x859\xd90HV\xa2\xf6\x85|\xab.\xf3\xf6p\xae!m\x05d\xeb\xc8%Q\xaeT\xe3\x1a{P(\xd0\xa4*,\x88|p\x94\xf9o\xecY<%/\xc2T\xdb\xaekP\xf5Cg\x04\x83\xa6\xf6A\xd1Y6\x8b\x05\xc0%\"2\x0e\xa1\x03\xfd\x16|*&\x84\x181\xca\xe4\xdf6\x10\xc2\x0d\xa2\xaf\xc8\xb3\xb7\xe2\xda\xedj\x96c\x91\xd07&3\x0cj\xe6\x96\xf6\x850R\x0f\x0b\x93\xf9T\xe4\x172ODh\xef\xf0\x13\x85U\x80\x03\xedk\xdbiT\xe8E\xb6\x865\xf3\xd0\xb0\xaelO\x86\xcc\xf4\x1f5]\x0caI%_\x8e\xfe\xb9\xbf:\xe5]h\xd7\x16=\\\xe4\xeb)*\x050~\x9fR\xc1\xc4\x97.\xee,G\x81\x88\xa7\xdf\xad\x0d\x12o\x8c\xca\xf2\x92\xb5KH\xae\xe0\xc2\x95_\x96\x82\x88`\x8ef\xb9P\x87\xe2<\xd5\xa0'\x12\xdf\xdb+\xd9\x02\x9c8\x8e\x0b+\x9b\xb80\x17?R\xf1c\x89'\xacz-\x82\xbe\x08\xdd\xa9rS\xa2V\xb3\x1d\xd4U\xc8\x83c\x17\xed.XR\nx\xbb\xdb\xedR\x86\xb9\xaa\xdab\xcb\xe3/W\xcc\x1c\x05<\xf8\x915\xf0#\xe7$\x91\x99N\x1cy\xfe\xd3E\xa64'\x13\x8fJ\xb4\xfc\x83A\x14\x92\xffJ\xcb~ \xca\xad\x8d`p5\x80e\xd1\n5\xa9\xd3Y\x80BM\xc1\x0c#\x12j\nD\x04BM\x91p\xd8\xd3\x14\x89(\x83\xba\"\x1eWPS\x84\x91\x04u\xefE\xc8@\x8d\xd62\x8fa\xa6\xf9N\x0er\xa5\xf9\x94\x85\x052N\xcc\xf0\x15\x8f\xc8a*a\xc1\x174\xa5\xdcU\\7\x05\xe6N\xab\x98\xc3jy\xbe\xb0j:\x19\xbb\x10\x96L'C9\x9f\xeag\x10\x0e\xee>\xc9n\x00\x8a[\x13\x17\xac\xf3s\x92\xbc\x8a\xa6Y@,WA?4\xaa\x1f\xca\xd2\xcc\x0d\x1eI\xfc\xf0\xa9\xa3\x1e|\x8aUt\xce\x85\x98dh`\xef\xdeE\xab\x0b/\x1eB$\xfa\xa9\xd42Y\xad\xde(\x84\xd2\xcd\x89\xfc\x8e\x86*\xda\x94\x90\xfa\xa8\xf9\x89\xbb\x05\x14\xe0\x00b\xd0\x8dMX\xd9V\x1c\xb6\xe0\x1f\xbe(\xd5\x03be\x87v\x7f\xf7\xa1\x9a\x03\xd4\x17E{=]^QVT\xc9\x1c\x9a\xe5E\x95l\xa4^^\xb4\xaf\x16%\xdcfU=\xa8&\xcc\x0fWy;\xa3+\x82-\xed\xef1\x9e\x88\xae\xdb\xae\xa3\xb6\x1a\xf0\xf3l\xdf\xd1\xa5*]\x19\xcfg\xd4'\xa6\xe5uN\xeb\xd7\xd9D\xcdoJ\xd0^\xd4r\x07\xd2\xb9a\xba\xff\xb2{.\xf8\x02\xd7\x1d.\xe9\xea\x9c\x7fho\x88\xb8=\x172\xf5\x03\x9br\x9f\xc8v\x9d\x9f#\x13\xd6s!.*\x11\xc7a^E\xb9 \x1d\xea\\B\xc5\xa5|7\n\xdf\xc7\xc1\xd1\xc2\x0b\xe7\xa4\x95+V!\xe6\xa5^<'i\x9dCN\xd4MH\xca\xc4\x00\xb3\x80\x97\xc5\x81JE\xc5\xa3\xf1\x8b\xbeq!\xea\x06\x917=]\x91I\xab\x01GL\x0e\xebR\xa6\xf7\x10\xeb\nA\xeb}\x1c\xa0\x87\xb9\xae\xc64\xba\ni7j\xba\xf3|\x0c\x08\xb7S\xcc\x8e\xd0j\x18z\xb8\xa1\xe7\x9ax\xb3\x88\x89\xc1.\xa6\x98\xb2Mp\xc0\x14\xae\xd87\x99\xd2Y\xe0\xcdrw\x15\x935 \x85t`\x1b\x06.f\xf6>\x0eZ\x0d\\\xea;b\x82W7\x8b\x83\x0d:\xc4\xb1z\xf1\xa4~\xff\x88G\xc0\x89\xa2u\xd0]yqB\xd8\xd7\x8e)\x834\x19[Y\x1cPq\xdb_z1\n\x91\xd6Y\x1ew\xd2\xac\x9c\xa5\\\xd8\x95\x1fN\xa3\xabn\x10\xf1k~\xdcW\x93\x08#\x1f\xdc\xbfoA\xa7Rc\x11%\xa9\xe6\xf5\xcaK\x17\xe6\xeeXmJ\x98\xf8w\x0b?I\xa3\xf8\xba\xfa\x06/v\x98\xcc^-\x93un\\\xac\xb4,\x97\xc5\x1c<\xa0\x83e@KH\xec{\x81\xffK\x0e8]\x86\xde\x9b*\x1am\xb4>b\xd3\xccIz\x14\x853\x7f\x9e\xd8\x0eE\x8c\x84\xa2\xf4\xd8\xa0p\xc1I\x11I\xc7\xc4n\x86r\x899\xef^\xe7\x12Pj\x88v\xc5]\xb2\xf0B\xa7\x0d\xa5\x81<\xb5 \x99\xbe\x0c\xa7\xe4\xe3\xd0\x90\xc2\x1e8\x03$\xe1\xae1\xcb\xb1\x89FE\xe1\x0b?HI\xfc\xc5H+\x03\x7f\xe0]GYZ\xa6k\xacc\x9d\xfd [t\xae<\xd1\x0f\x02\xc9q\x8a\xb4\x90\xa1F\x14'\x14\xd8\xa6\xf8\x92\n@\xab\xfap\xdag\xe9\xa5\xd6\xf9\x88b\xae'\x9dbL;B\xdfF\xa5\xb7\xe3\xea\xa8\xf1\xbe\xcd2\x1a\x98kl\xc29g\xd5\xbc\"L\xd9\xd4\x8cYf\xa0\xb5\xc6\x992\x88T^\x10\xf4\xf3D\x9du\x8b \xd6a\\\xcau\x86f\xa5*\x11Z\xc5\xea\x8e7\x7f\xc4.q\x9a\x08\x02\xde\xa8\xd1\x1d\x1cr\xa2P\xb7\xe9\x0b\x15\xb0\x86\xe0\x9bU\x981k\x7fc\x1a\x03Hg0v1F\xc7`|e\x0bl\x10OkZ\x03z\x9ch(j\xbc\xb7o\x81D\xe2\x06\xec\x8ep\xe86g\x02\xe7\xd7\xa53\x816\x94\xf3\x1c\xe9\xb8\xd0\xf8vK\x10=C>\xe4\xf6@`Z\xce;\x9dy\xc3\x1eb\x80\xd1z\x07\xca\x0f\xbb\xfb.\x11\x13s\xe5\xb8h\x18!n\xae\x89\xf7!\xb6\xf5\xcc\x98pU<\x11\xab\xf8\x8d!i\x9fx\xd0\xc9\x8f\xae\x93\x1f\xce\xb9\x95b\x97\xffIwHVK\x1e\xbc\x9a\x9bqk\xe6\xf9\x01\x99\x1a\xda\xc4\xf3\xde\xebN\xa2\x00\x15\xf3V\x8c\xd9=!S\xdf\xff\xff<\xcf\xab\xb3\xac\x0b\xd0\x11\x80\xe1\xa7y\x9c+\x83\x0f\xa2x\x16\xb5\xf72<`\\=I\x9bb\x17f\xfa\x15TIW\xd3-+}\xa6\xccFh\"\x8eO\x9e\x9aYh\xadE:?\xdd\xfeP\x1f\xdc/5\xb6\x87\xe2\xe1\x1b'\xa50\xad'v.\xe7\xcek\xac\xa4(\x03\xb6j\x98\x03\xcb]\xd94\x054\x07e.S<\x9f\xdd6\xff\xb0\xf6\xb3E\xba\x0c^Dq\xfeQ\xd5uK<7.\x18\x87\x88\xf9\x95\xf2(f\\`\xf4\xf0\n\x86\xa2\xad\xf9;\xd6g\xd3\xdc\xfci1\xbe\xfa\xe9L\xfd\xc4\xbb\x08\xc8t\x08Y}\xc5(d<\xeb\x90\x116I\xd0\xad\xff\x8e\xaf~PO\xb0\xeb\x808uLL63{[\x08b+\xc9\xb0\xcdH\xc2\xd2\xac\xd6\x01RF\x10\xd1\xf4v\x16\x07\xdb\xfcS\xe3\x87)\xaa\x8dY\x9a\xad\x1az\xaa\x01({c\xfeFl\xa5\x02\x94Y\x1c\x98\xab\xb7Z\\\x9e#\xd1pi\xea4\xef7\xffV@\xe4\x19\xbek\xe1\x13\xf8\x93\xcbaem\xf5\x03u\xc1:\xfe\xb8\n\xa2\x984\x05;3\xa2\xc4\xd4_\xb7F\x88\x14\xb5\xd4\xfa\xcd_\xb7\xf17\xe9\xe3*\xf6V+\xf2\x85;a\x13\xd9\xbem_\x91 b\xe6\x8d\xb6\x9c\xd7\x0efA\xfc\xf9\"\x1d\x82\xb5\xd3\xab\xc1\x86+\x7f\x9a.\x9a*%\xf1d\x0831\x90\x1a6#\xa0\xfd\x9d^y\xf39\x89\xe1\xfdK\xc3\xack q\x89\x80'\xac)\xcb\xa9\xfb\x04\x13v\xb7]\x96\xd2^\x11\x8bS\xb7YN\xb3\x8b\xa5\x9f\x0eaaZ\xc1Uw\xe9\xad\xda3\x0b\x92\x04\x9et'A\x14\x8a\x898\xf4\xd3\xfa\xe3\x87q\x06f\x9an\x92\x7f\x1d\x1d\xa5W8\xf73\xc7\x95\x9a\xbe\x91\xa8R\xceCK\xdb_\xbe\xacb\x90Qojd\x18\x94\x02\x80`J~\xccxy\x7f\x15\xce\x1f_x \xd9\xdfu\xfd\x0f\xcf\xde\x9c\\\xf5\xbe\xfej\x1e\x1d\x1e\x1e\x1e\xbe>}\xbf8~??<<|\xb6K\xff&G\x87\xaf\xe8\xbf\xaf\x1e\x04\xfb\x7f\xa5?\xbe\x7f\xf1\xec\xd5\x87\xe3\xf7\xb4\xc2\xfb\xd9\xd5\xad\xfe\xeb\x05\xbf<\xbb\x1f\xf6\x9e\xcd\x16\x1f\x9f\xad~\xba>\xea}\xdc\xbd\x7f\xff\xfe\xfd\xce\xcf\xeb\xdd\xa3\xbf\xac\xfa\xcf{\x8f:\x9dY\xbast\xff\x97\xbd\xfb_\xf7\xf7\xef\xbf\xdfy\xf0\xe8\xfd\xec\xea\xf9l\xef\xe1\xfd\x9f\x1f<\xea\xbc\x8f\x07\xcf\x07'G\x97\x8f\xe8x\xfe\xfc\xdd\xc9\xe9\xbb\xe0\xd5\xe1\xf1\xf1\xe1U\xf8\xe8\xfe\xfd_v\x0e\xe7\xeb\xdd\xfb\xeb\xef_>\xbf\xaf>\xef_\x91\x9f\xfc\xfe\xe5\xe1\xe1\xe1\xf3\x87\xa7\xefO\x9e}\xf8\xf3\xfcY\xf0\xb7W/\x0e\xa3\xbf^=?|w\xf2\xf1\xe2\xbbg\x0ff\x9d\xf5\xdb\xaf\xc3\xe0\xbb\xc3\xbf\x85\xfb\x97\x83\xc9l\xe7\xf0\xd1/\xf7\xdf\xce\xde\x1c=|\xf9\xf2\xfb\xd0\xdf{\xb1\\\x1e>{\xf5\xf0\xc5\xab\xc5\xd5\xbb\xfe\x83\xc9\xa3E\xb8\xf0\xff\xf6M\xff\xe8j}\xfcM?]\xbe}\xde\xfb\xf9\xf4\xeb\x9f\xf7\xe7\xdei\xfa\xed\xfd\xcbW\xdfy\xe1\x87\xe5\xe1\x87\x93\xe7\xef\x83?\xf7\xdf\xac\xb3\xec\xdd\xcb\xd7\xd1\xfe\xe5\xa3\xde\xe9\xc7\xd9\xc3\x9f\x937\xe9\x8b\xfd\xf9\xeel\xd6\x8f\x92\xb7;o\xc2W\x93\x0f\x0f\xa6\xbb\xab_\xa6/\xdf\xa7Y?:\xdc\xfd\xd0{\xfe\xb7\xe8\xeb\xe5\xc7ep\xfc\xfd:}\xfe\xfe\xa7\x9fNw\xd2\xe5\xd7\xcb\x9f\x9fuV\xdf_?\\=\xef\x7fx;{\xf0\xd3\xdb\xe3\xde\xcb\xdd\xde\x9f\xff<\xf1\x9e]\x85\x19\xd9\x9f}\xf5\xcb\xfc\xfat/\xfd\xee\xe5\xfbG\xfbo?<\x88/\x9f\x7f\xfb\xe7\xd7\xdf|\xe8=\xffz\xf7\xc5e\xf4\xf5\xf2\xc5\xea\xf5^\xf4>\\\xfb\x0f\xbf\x8e\xc8\xe1\xe0\xfe_\xbeK\x96\xdf\xfd5\x8b.?\xf6\x12\xff\xa4\xff\xd5\xc3\xf4\x9b\xcb\xd7\xfb\xe4\xd9\xa3\xe4\x9b\xab\xbf\xac\xee__/'\xd7\xde\xdb\xfb\xef\xe2\xb7\x9d\x93\xb7\xcb\x8bW\xaf\xfc\x8f\x93\xbf|\x98\xbf;\xe9{\xef\xff\xf6h'\xfa\xea\xbbd\xfe\xdd_\x0f\xbd\xaf\xf6\x8f\xaf\xe8\xb2\x1c\x9e\xbe\xff\xf0\xe6\xe4\xeb\xbd\xa3\xef_\xbe\x1c}F\xd0\x19\xd2\xbd\xb8N\xc97Lj\xae\xd3.\n\xad\xe2\xc4N5\xf2\x18\xaai\xc6=\x8d\x84\xc34-\xaa\xe9\x1c'\x16;\xf0\xcf`\x87\xd0\x81\xd8\x81\xfb\xb0\x0b\xdb\xd2]\xe9\x8d\x0b\xa4\x9bF\xcf\xaeS\x82\xa6a\xf5\xd7f\xb9\xe9 \xb3\x10\xc4Q2\xcb\x17:*\xe6\xfc:\xee\xf3\\\x14!\xb9\x82\xa8\x92\xe4\xa7\xc6N\x03\xc7I\xa0C+\xb1q*f\xc3x{\xe6BF\xe99%\x06=\x97\x05q\x86\xa7\xd0\xc3\x0b\xe2m\xd8\x85!\xad\x120\xfb\xc5\x00\x9e\xc0\x8c\xfe\xd3\x19\xc1\xae\x83\x90\xf5\xc7iw\xb2\xf0\xe2\xa3hJ\x0eS;p\xce\xe0\xc9\x13\xe8?\x84O\x95\"\xe8@\x9f\x17\x0f\xf4\xc5\x03V\xbc\xaf/\xddq($\xc6I\xa7\x83\xe6\xfa\xf0\xf4)\xf4\xf7\xe1\x1e\x0c\xf6\xf6\xd4\xf7\x0f+\xaf\x07{{pO\x0d-5@)\x9bI\xcf\xe6\xc9\x18\x06K\xe7\xf2\xf4)\xecV;Q\x18\xb3~\xab^\xfa\xbdZ\x90\xed\x9a!\xf6\xf4)\x0cZ\x03\xc0\xd1\xa2\xb4WF\xe0Y\x1c-o\x87\xc2B\x97\xc5\x8d\x12\xe0\x8f\xb0\xc3\xc2=\x8e9>\xf782\xc36\xf8,\xc7\x83G\xff\xe9\x8c\xa0\xbf\xbf\xf3p\xc7\x81\x88\xb1\xe13\x8a\xe0\x99\x8b\xd1n\xb1\x04\x9e\x82\x07\x07\xe0\xc1\xb0x\xa7\xb2\xc0\x0c\xd2>\x1c0@\xa7c\xda\x0d\xdd?\xbc\xd1x\x8c\xc0\x19\x9c\xd1\xcd;&\x0c\xae\xf7`\x7f\x87\xbe\xb0F#\xcbq`\xc8\xb1\xc2\xcf\xd7\xcbf\xed\x0cp\x1d\x1e:\xd016\xdc\xef\x89\x96)b\xe4-\xf3\xae\x06RW\x15\xee=\xbf\x93\xfe)\xf2C\xdb\x92\xec\xb4$E\x91d\xc5\xc9 \xea\xf3\x7f)\x84\xa5\xf8\xab\x92\x9f\xdc{?L\x1f\xb2u<\x90\xff\x18\xb2\x90\x88lQ\xac\xc3gG\xcf\x8f_|\xf5\xe7\x97\x7f\xf9\xfa\x9bW\xaf\xdf\xbc\xfd\xeb\xc9\xe9\xbb\xf7\x1f\xbe\xfd\xee\xfb\xbfy\x17\x93)\x99\xcd\x17\xfeO\x97\xc12\x8cV?\xc7I\x9a\xad\xaf\xfe_\xea\xde\xb4\xc9\x91d9\x0c\xb4\xdd/k\xf6\xfe\xc2~q\xa4\x86\xdd\x99\x83\x04\n@\xdd\xa8F\xd7\xeb\xd7\xd3#55\xd3\xfdl\xaa\x1f\x9fH\x00S\xcaJ\x04\n9\x0dd\x82yTW\xcdT\xafQ\xd2R\xa2H]\xdc\x95(R\x07\x0f\x1d\xe4.IQ\xa4\xb4\x07wy\x99\xed\x9b\xf9#\xfa\x03\xfb\x17\xd6\xc2#\"32#\"\x13\xa8\xaay\xd4\xc2\xac\xbb\x00\xcf\xc88=\xdc=\xdc=\xdc\xafo\xbe\xec\xf5\x07\xbb{\xfb\x07\x87G\xc7\xed\x1d\x8b\xa7\xcbat\xa4\xc8g\xe9\xc1\x13HN\xa0\xdd\xf6\x1cqS+\xc3+b\xc18\x93Q\xd9s\xe8#O\xe7\xec\xe0\x9b\xa9z\x9e\x1d\xa4\xf4\x14\xc35\xc0O\xc0\x1e%c\x0e\xa4\x8b8z\x87\xc4\x13\xa3\xba\x15Q}\x99\xc3W\x178\x1bAO\xd0\x0b\x02\x1e\xac\xb2e\x1a\xac\x97\x98\xf0f\xaf\xaaE\xbb\xca\xef\xe7`\"\x95\xd7s\x9b.\xa6v-;\xfcN\"\xb0x\xad#\xbc\x03=\x0eq\xa3\xe4\xf1\xc8\x87\x8c0\xd3\xfeN\x8b%\xd7\xcc\xc3\xdcD\xf1s\xa4\xe0\xa1\x90\x85+.m\x90\xad@H\xff\xb4G\xb0\xeb \xc2\xd8)] Jr(\xf5\xec\x1f\x1c\xf6\xfb\x07G=\x8a\xd7\xf4 \xba\x8c#\xa6St\xdd\x1f\xf0'\x8c|\xb0\xe7\x03*\x9df\x02\xf3\xed\x88y\x18Q\xfc?\x92p>B\xc8\xa0\n9\x90\x00\x07\xbb\xf0\x08\xa2\xea\xad+>}\x99f+\xe4\xdf\x82\xb1\xd5\xb1d\x0c\xea!\x06\x1d\x0c(jY\xe7\xbaG\xbbZyC\x9eM\xd2\x8d\x897\xab\x0b\xbb\xa7\xa0\x02\x0b\xabM\xe7\xfa\x08>\x84\x80\xca\x02\x942\xa8\x12\x05\xdd\x17v\x9f\xce\xab\xe7\xe8K\xf80\x82\x04\xe7L}F\xd9r\xe7P\x85\xa3\x9f\x10\x9cb\xc3}\x18BO-\xb2\xe6E:\xf4\xb9\xa6\xea\x05K`\x04m\xa8\xe6T@\xc4B^\xbff\x14f\x01\x8f\xf8\x18:s6\x08X\xc0\xd3\xa7#\xe8\xcc\xa9\xe4\xd0\xa6;\x18\xe6t\xdb\x9d`\xf9\xc1\xfe\x01|\x88\xe1\xb2E\x03.\x88\xfa\xe6\xd0\x19\xc1\x91\xa3i\x91\"p\xa4\xb6\x14\x95[\x8a\xf3\x96\xb2\xbc\xa5l\xf3\x96(\x91`7 #\x07\xfb\xda\x87N\xf5\x06\xaa\xe1~3}5\xc2W\x8b\xcc3\x19\x9c\xc2+\xef\x15\x9da\xd8\x81\x1e\x15\xbc\x16\xf9\x9ck\xf44\xc8\xf0>\xf5\xd2Ew\x1d\xbd\xb3\x07\xec\xee[D;Z\xbe\xc8\xaa7\x17KU\xe3\xa8?,U\x15Q$\x94\xf6\x0ce\xe8\xef\xe2 \xad^\x93\xa9\xcdiBq\x9b\"6\x0b\x19\xcf\xd1\x9b\xd6\x1c\xe8\x91w\x9e\xa3\xb7o@o\xf4\xb00\xa07\xc5\xd1\xc1n\xce\xbc\xe5\xd1t\x06{\xb4\xc2\x12\xe8\xf0\xd0\xd1\xe3:\xc5\xe5\x98\x93\xd5H\xdf\x8d\x19/B\xa7\xaf\xa3y~\x85\x12\xd4\x13\xe8\xc1\xed-\xbf#\x8b\x8e\x1b,K\xc4\x13\x14\x8cq\xa7i0\x97\xce0v\xd4\xbbH\xd0-)H^y\xafl\x82>\xf2\xcc\x90\xca\xd0\xe3\x14lJ2\xf2\xc7\xbcJF\xbc\xe7tp\xb8\x0b\xb0\xae\xf92\x8ab\x1b\xbf.\xa3KZz\x87=\xf8\xe4\xd5\xc0q\x81P\\K\xa0\x8cM\x9d\xccq\xe0 \xf4\x91\xf3d\x9d\x0ee\xcb\x1f\x8e\x80\x96\xa7\x07\x82\x11\xee\x94%<\xa5\xfd9\x855\xec@\x02CXW\x10\x89n\x89\xa5CQ,\xa1E\x07\xac\xb6v\x9b\xd6\xb6\xc3j\xcb\xeb\x99\x8b1\xc9\x83(\xb5\x82Om\x82\xb5u\x18\xe6\xca\x8d\x05\xac\xb6\x11,q\xf8\xc8\xbd*E\x96\xe6\xf7F\xd0s\x9c\x13\x08hcG'(\x9f\xb5aQ\x88\xbd\x1e\xa5T\xed\x11\xcc(\xad\xdeAzA\x85\xa7:\x12\x94Qd\x0e\xe0\x96\xbe\xeb\xd3w\x83\x13\xf0\x19\xc5Q\xaa\xcf\x8a\xea\xb3\xbcz_W=\x7f\x15:0\x9b\xc2\xed\x08\xfa\x03\xba\xb1\xae*\x1c\xae\xe1P,+p\xca\xdb6\xf7\xea\x0c\xed\xdd\xc1Q\xe5\xc8[x\x85\x96\x1dk7i\xb2\xb8\x921\xd08\xdb\xc6\xdd\x9f<{\xfd\n\x1d2\xf9W\x9d\x87M\x9e\xe6fXI{S&yMW8\xccwS\xf2\n\xf9\x85\xdd@{[w\xa3\xf1\x9a\xf4\x0e\x92g\xed\xa8\x14\x0d]LPd\x87\xf6\xee\xae\xe2w\x1c\xf0GG{\x8e\xd6\xa57\xfa\xf1\xba\xf4n\xe3\xdd\xde\xa8KU\xd3(H\xf9\x185q\xbbh\xf9\x8a\xe3.\xf3\x11\xa7\xef9\x1b7\x0b\x924^g\xa5\x8eq\xa5j\x94\xcaxM\xd8\xfc\x9c\x12\x03\x161\xc1\xe0\xc3\x11\xdf\xd4(\x8a\x8bP3\xeclT\xf5\x83vN\xa0\x85>\xfaH\xf2\x92Rv\x00f\xee\x0fy\xbc\x0b\x9e\x94\xc0\x85\x16z\xce\n\xa7!\x96\x1f\xc19\xe1\xe34\x18\x85\xde\x83\xef\xb1\x84 u\xda\xf0\x88M\x15\xcb\\n\xa8g\x1e\x84\xderY7\xe4\xfa \xa1\x9f\x16\xfa\x13%]\xbe\xd4\xd2w\x83\xd3\x18l\xd84\x08\xf9L\x9c\xfb2su\xfa\xf1i\xa1\xda[\xf7X\x9ca\xa7:\xe7\xc5\xa9\xf3\xcd\xcd\x9aTN\x9e<\x80\x12\x0bV\xc5\xeeYf1\x8b\xe1\x11\xa4$\xf6.\x96E\xc0\x7f\xe5\xc2V\xd14{\xf2 \xbcb\xb7\x1a\xdb\xfa>\xbc\"\xb4\x8f\xf6\x1d\x17B\xfb\xf8\x00=\xa5\x8b\x0e\xd0\x96\x06\x1bu\xbb\xe07\xfd]\x1d\xc7 \xed\x03\xc7\xb6p\xb6\xd2(\xaez\xea\xb0\xeb\x80\xbb\xa6x\xe1\x94\x89u\x83\xe4\xa5\x98\xebM4\xc89\x85\xd2\x9eUyD\x15\xdc\x8a\xe3\x80\xa5t\xf8\xeew\xf3\xee\xe1\x9d[L\xb7U\x8d\xc9\x12\x97|k7\x9a\xde\x0dWt\xefAWtww_Y\xcb\x81\xd3\xe5w{\xbc$ .\xc3Mj\x92\xd7U\x9a\xca\xd8\x8e\xbbg\xd0\x86\xb8\xfb\xb1\x0b\x16\xabU1\"\xb2V\xd8\xe8\x0e\xa4I\xdb\x08\xa1\x9an\x9a\xeeU\xaf\x94\xf2\xa8\xef\xbd\xaa\x14\xc5p\xeb\xa0:\xbd,F\xfd~5v\xbc\xc7j\x19T\x8b'9J\xf1\xc9\xd3cj\x0b\xbd\x07C{p\xec\xd8F>-\\\xf1\xbe\xd2\xc4e \x068e\x9a,\x91\x88\xceQ\x0d}\xc8t\x9a?K\x8b\xfd<\x80\xce!e\xe9\xc9z\x19\xa4\xb6e9\x1a\xc7-\x1d\xeb!\xe3t\xaap\x9b\xf7\x8e\x0b\x87\xd0\x1aA\xc2\x82\xd5:<\xcf\x91\x9c\x1e\x91=\"\x8e\x93\xab\x89\xe8\x0b\x92%\x86\x1e\xabj\x85\x88R \xe6\x0cm/t\xces\x911We\xd3\xf3o\x9f\xd9F\x82\xee\x9cYC\xa2\xee\xfc\x84\x9e\x8b\xc0\xd7\xe4\x15\xcak^\xbbx&\xf5\xec\xbc\xd2\xb1\xdfnO\x1d\x17\xcf\xa1\xf4\xd0\x14\xdb\x0b\xa7\xebG\xa1\xef\xa5\xf6\xdc^\xa0\x02\x9a\xc2\\<\x89\xce\xf2>\xdc0\x0b\xcc\x15<\x85\x9b\x13\x07\x96\xec\x9e\xd3\xc2\xc5\xb3\xf3l|Cke\xe2\xc2xM't1^\x1b\xf4j\xd2MK\x18B\xb2\xc9\xe6\xd9\x90\xe4<\xe4\x81\x83\xd6w\\Cr(\x0elRO\xb1\xc3\x95\xbd\x19\x88\x8d\x7f\"\xb5\xda\xdf;vl\x8b\xd6n\xb9[\x88\xc65f\xb8\xc0\x8e\xa9`[Fp M7\x19E=\xf5\xda\xf9\xdc\xfe\x89A\xefv\x928\x1f\xda_xW^\xe2\xc7\xc1:\xbd\x9dy\xa9\xe7\xec\x04+u\xd4;\xe3\xcf'\xd7\x83^gr}\xf8b\xbasY-\x12\xb1:\xc7\x9f\x0f\xa7mg\xb8s\xb9RI\xdd\xd8\xeaZ.X;\xb2\xef\xb9\x19K\x12/\x0c\xd2\xe0K\xf2\x83x\xd9t\xf3@\xd8\x92\x98R5\x15\xd7~\xe8Y\xce\xd2y\xb4n\xb4\x12 k\x95\x85\xde>\x1d\xf7\xa6\x0e<\x85\x8e&'\x95\xed9\xdc\xd6\x84\x8a{\xaf\xbb\xa2\xd2\xb3\x1d9\x8e\xb0-1\x0bm\xdcMI\x922\x15\x8e\xe5]DY:\xbcXz\xe1[\x0b\x86\xe0a\xc4<\x19hB\x81M0\xa0\xc0\xe3\xdd=\xbd@\xb4\xbb\xbf\xeblc\x1e\xc6`\xf8\xdd4\xfa$zG\xe2\xe7^Bl\x0c\xd1\xda\xa6C\xa6t \x03\x96W\xe3\x9e\x1a$\xaa`\xbb!\xec\xe9\xc3:\xf4\x0f\xef\x1e\x98\x027Yy4[\xcaUE\xf7\x0e\xaa h\xf8\x04\xefU\xb98\x93\x05\xaad\x8f\x89\x02\x87U\x81\xc2\x03\xae\xfeS%\x81\x98N\xb8\x14\x93e\xc8\x05\xcarIf 8\x85\xa4+\xf2\x87\xe5\x05\xebg\x0d\xb3\x12V\xe6\x0d\x03k\xf2\xa4\x8e\xfal\x80\xaa\xc2<\x92\x93\x1b\x06<\xdfX\x1b,K-\x9a\xc9E}8\x05_\xa4\xfb\xa3\x9b\xa2\xf2\x82\xe0\xc1DS\x19\xaf\xc2\xeaa/\xc3B\x15;\x1aA\xc7\xa3\xdb\xae\xd3\xa3\xbb\xad)~\x80\x89\x9dm.!t\xfa\xdc7\x83\x07\xc1K\xb9\xa2\xb9l\xf2f\n\x90\xd89\x81v;\x84'\x10\x9f8\x10\xf0\x00\x83<\xbcv\xa8\xe6\xc6\x16s\xfa\xa0\x18\xcb9\xa5!~.Z\xed*\xc7\x11\x15\x8f\x83\x1c\xd7TdfX+\xe5\xb2\xdb\x10\x1d\xcd\x87\xac\x88\xdf\xde\xc6\xf0\xa4\xa5\x12 \xae\x86(qW\xf5\xda\x86\x94G$5\xe8m\xc4\xccUB\xd8\x95\xb4$\xef\x95.\x06h\xdbf]\xd4/`\xcc\x9d\x06NE\x07B\x18\xc2\x8c,IJ\x10R\x8ap\xd8\x8c\xa8\x02\xf5\xaa+\x99O\xfa\xb6\x13-D@1\x88\xbb\xe2\xdb\xee^\x95\xe8 \n\xaeO\x92\xb5\xbb\xaf\xcb\x92\x85\x8c\xe0\x8eC\xc8\x0bhu\x83\x04%zSx\x01:\xa5\x01c\xda\x11\xa3H:r+>\xcc]\xe5\x149>\xe5\x88hZF\xb3\xb2\xbe|\xc2\xcb\xc7v\xe8B_:\x9e\xd0w\x93e\xe0\x13\xbb&\x91\xb27N\xa76\xa5\xaaI\x193\xef\xbeR&-H\x93\xa8 0^\xefe!0)\xdfd\xdc\xd7\xe1\x14\x02J\x8dQK\xf9\xe8\x11\x84\xf0\x94\xd9\xf4R<\xd7\x88\xa6\xb6\xd8\x03\xdbv9f\xa4Z\x99_\xf3P\x98YOx\xfbt\x08<\xc5\x1eS\xda\x1e@\x1b\xbd6P\n\x0c\xf9\x03\x1c\xa0\x93\xbf\x84a\xfc\x02\x87\x91\x7f\xfar\xc8_\x0e\xa1\x83\xceXO\xa1\xe7\xb2/#\xad\xd9\xf0\x8aG\xbc`\xac#@\xd6\x11\xc3\x13\x08N\x1c\x88Xh\xb1t\x1c\xd3\x9e\xe8\xfd\x11\xa3;\xe3\xc6~u\xb76\xed\xe2A#.\x19\xe5\xb3\x94m\xb7\x94\x1dp\x1bIO3\n\x18ZJ\x0b\x15\xc4\x16M\x08\xb2`\x8d'\x93lv\xd4\xebu\xe8\xdf\xf9|>\xad\xb8\xa3\xc7\xa2Po\x97\x15\xea\xed\x1e\xcc'\x93lN\x06\xf8sN\x06\xf4\xe7\xa07\xc3\x9f\x83\x9eZ\x05\x9dd\x0b\x9b\xd9\xf5\xc7\xac\x99\x0bSs\xe8\xd85\xfe\xbc\xa1S\xe8\xc3e\x9f\x0e\xe5Jg\xe4\x00\x8b\xcf\xe6\xf3\xa9\xf3\xd5\xe0\xbd\xa52\xf0\xf2`/\xe6\xf3)\x02|sC o(\xcfk~\x9b\xe7Fw,\x16\x89A\x95Y\xb1\x999\xe9\x11\xf6g>=\x15i\xefm\xde\xe9A\xaf7\xe3\xb5\x8e\xb9G\xcd\x94\xd3\xcd[\x0bEL\xc7X\x87\xe5|XU\xff\xce\xa5^\x8e#\xd1\xd5S+\x0f\xed\xe6BX\xad\xbf\xd2\xef%\x8cx\xb6X\x1bGg\x9f\x8e\x8a\x91\xe2\xa0\xe7\xd0\x06\xdf\x05\xeb\xd2\xba\xeb\x9eH\xf9\xa9r\xe9\xb0+\xc2w\xdf\xc6\xd5s\x898\x10V\xa3\x01\x8am\xac;\xb1\xf0\xd1Z\xe3\xc7\xff\xe5\xe7~mj\xddkd\xf5\xccY\xc8JvdS.\x9c\x1f\xf13<\xe2;\x18\xb7\xc72\xdb=\x1a\xf7rC\x02U\x13\x9f\xd31\x8d\xa8F\xde\xd7Pr\x14\xff\xa2\xdc\xdf/\x1d\xb7\xdb\xc1\x14\xe9y\x00O :q\xd81\x87\n\x06\xe98\x98\xa2\xeb\x8dA\x92l:\xcf\xd4`\x83A\xcfU=s\xa3\x96g<\xb9\xf6{\x9d\xc9\xf5\xec`r=;\xeaL\xae\xe7\x07\x93\xeb9~\x99O\xb2^\x9f\x92\x82\xac\xd7?\x9cOw.kpf[zx\x1f\xe4\xb2S\x14\xdfR\xc7a\x96q\x81>\x11]\xdb\n2\xdd}\x12\x0f\x9dJ\x90\x03\xebG?g\x0d\xc1zV!\x14\xd6\x8f\xfe\x96\x1e\xfc\xb7\xf5\xe0\xbf\xa3\x07\xff\x8fz\xf0\xcf\xeb\xc1\xbfI\xc1\x9e\x02\xfe-=\xf8\xdf\xe8\xc1\xffV\x0f\xfewz\xf0\xbf\xd7\x83\xff\x1e\x05?W\xc0\xbfC\xc1\xbe\x02\xfe'\x14\\M\x91j\xfd\xe8\x0f)x\xa6\x80\x7f\x81\x82\xab D\xad\x1f\xfd}=\xf8\x17\xf5\xe0_\xd2\x83\xff\x17\n&\n\xf8\x7f\xd5\x83\x7fW\x0f\xfe==\xf8\x1fP\xf0K\x05\xfc\x0f\xf5\xe0\x7f\xa4\x07\xffc=\xf8\xf7)8P\xc0\xffA\x0f\xfe\x03=\xf8?\xea\xc1\xbfL\xc1\xaf\x14\xf0\x1fQp\xf5\n\xab\xf5\xa3\xff\x89\x82_+\xe0\xffY\x0f\xfe\xa7z\xf0?\xd3\x83\x7fE\x0f\xfeU=\xf8?Qp\xa4\x80\xff\xb3\x1e\xfc\xbf\xe9\xc1\xff\xbb\x1e\xfc\x7f\xe8\xc1\x7f\xac\x07\xff\x1a\x05\xff@\x01\xff\x0b=\xf8_\xea\xc1\xffJ\x0f\xfe\xbf(8S\xc0\xff\xb7\x1e\xfc'z\xf0\x9f\xea\xc1\xff\x9a\x82\xab d\xad\x1f\xfd\x19\x05\xdf(\xe0\xbf\xd0\x83\xff.\x05?S\xb7\xc3oS\xb8\xa7\xc2\x7f\x9d\xc2\xdf,\x14\xf8\x9fSx\xaa\xc2\x7f\x83\xc2\x93jH#\xebk=Y\xfeZO\x7f\xbf\xd6\x13\xda\xaf\x91\x88+\xe4\xed\xeb\xbf\xa3\x07\xff\xbc\x1e\x8c3\xa0\x10\xc3\xaf\x7fA\x0f\xfeE=\xf8\x1f\xe8\xc1Hh\x15\x8a\xfa\xf5\xdf\xd7\x83\x7fI\x0f\xfe\x87z0\x92 \x85,\x7f\xad\xa7\xd6_#eR\xa8\xf5\xd7\xbf\xac\x07#\x99P\xe8\xef\xd7\xffT\x0f\xfe\x15=\xf8W\xf5\xe0\x7f\xa1\x07# R\xf0\xed\xeb\x7f\xa6\x07\xffs=\xf8\xd7\xf4\xe0\x7f\xa9\x07\xe3\x9e\xfd\xab\n\xf8\xd7\xf5\xe0\xdf\xd4\x83\xff\x8d\x1e\x8c\x9b\xf3R\x01\xff\x86\x1e\xfc[z\xf0\xbf\xd5\x83\x91\xd9\xff5\x05\xfc\xdbz0\xca\x00\xca\xc6\xfc\xfaw\xf4`d\xb1\n\x07\xfb\xfaw\xf5\xe0\xdf\xd7\x83\xff@\x0f\xfeC=\x18\xd9\xb7\xc2\xd8\xbe\xfe==X\xcf4\xbf\xd6s\xc7\xaf\xffH\x0fFv\xf2\x93\n\x18\xd9\xc9\x17\n\x18\xd9\xc9_W\xc0\xff'\x05\xbfU\xc0\x7f\xac\x07#'\xf8D\x01\xff\x89\x1e\xfcgz\xf0_h\xc1\xdf\xfc-}i\xe42\xd5\x981\xd6\xd7\x7f\xaa\x07\xff\xb9\x16\xfc\xcd\xcf\xe9\xc1\x7f[\x0fF\xd2\xabH#\xdf\xfc\xbc\x1e\xfc\xf7\xf4\xe0_\xd4\x83\x91 (\"\xcd7\x7fW\x0f\xfe\x05=\xf8\x97\xf4`\xa4\xdf\x8a\x90\xf2\xcd?\xd2\x83\xff\x89\x1e\x8c\x84Z\x91/\xbe\xf9\xc7z\xf0/\xeb\xc1Hc?S\xc0\xbf\xa2\x07\xff\xaa\x1e\x8cT\xb3\x1a\x93\xc1\xfa\xe6\x9f\xeb\xc1\xbf\xa6\x07#\xa1>S\xc0\xffJ\x0f\xfeu=\xf87\xf5`\xa4\xc8\x8aT\xf0\xcd\xbf\xd6\x83\x7fC\x0f\xfe-=\x18)\xf2\x1b\x05\xfc\xef\xf4\xe0\xdf\xd6\x83\x91\xf4VC\xe4X\xdf\xfc{=\xf8w\xf4`$\xa6\x8aP\xf8\xcd\xef\xea\xc1\xbf\xaf\x07\xff\x81\x1e\xfc\x87z\xf0\x7f\xd2\x83\x91\xc6*\"\xe47\xbf\xa7\x07\xff\x07=\xf8?\xea\xc1\x7f\xa4\x07\xffg=\x18I\xef\x0f\x150\x92\xdew\n\x18I\xaf\"\xe3~\x83\xa4W\x11f\xbf\xf9c}i$\xbd?\xa3\x80\xffD\x0f\xfe3=\x18\x89\xe9\x97\n\xf8O\xf5\xe0?\xd7\x82\xbf\xc6\xd5y\xa92\x1e\x9c\xab@\xe1<\xdf\xb0\xe3\x9a\"\xb9|\x83\xc2R\xa4\xc2Q\xb0|\xac\x927\xe4\x1bI\xe1\xcab\xf2\x08a\x8ex\xdb\xab\xe9\xee\xa3Q\x945u\xdc(5\x84tL\xa6\xa5\x17\x9aT\x895J!\x83_\xc8\x81>\x1d\x89\xa2q\xcbx\xf1~\xa3\xeaKo\xde\x12zc\xbcK\x92\xf2\xe4\xdd\xdc\xf2\xc6\x9c\x92\xe4\x81\xa3}\x93\xdb]\xb2\xc2\xee\x82\x1aL\xa6x&\x9b)\x9euv\x12\xf4 \xeb\xf5:\x93\xeb\xc1|r\xbd\xebu&\xd7{\xbd\xc9\xf5\xfeEgr}\xd0\x9b\\\x1f\xd2/\x87\xf3i{\xe7\xae6j\xd1\xc9\xf0>\x9d\xf4:_N\xc7\xcf:?3\xbd\xc5\xff\xbf\x1a\xb8\xef\x11v;\xeeu\x8e\xa7\xf4+{\xc8\xbf \xf4v\xfc9\xfb\xd9\xeb\x1c\xc3t\xe7\x8e\xdd\x0f\x99g\xd8Vv\xae\xdc\x085\x99\\{\xfedr}\xd1\x9fL\xaeg\x87\x93\xc9\xf5\x9c\xfe\x87\nV:\xe1l\xc6q\xca\xd9\x9c\xe3\xa4\xb3Y\x9f\\_0\x85k\x8f+\\\x0f\xe60\x99\xa4\xf4\xf5\x8b\xc9\x84\xbe\xeb\xf5P/;\x9fO&\xe1d\x12c\xa1\xc1\x11\xfbs<\x99d\xfd\x83#Z\xa2\x7f\x84\xd6\x16Z\x11\xfb\xd3g\x7f\x06\xec\xcf.\xfb\xb3\xc7\xfe\xec\xb3?\x07\xec\xcf!\xfb\xc3\xea\xec\x1d\xb3?\x1ek\x81un\x9f\xfe\xd9\xed\xf5\xaaq\xae\x98y\xcd\x826\x0b\xecm0\x9d\xcd\xda\x96\xba\xe1P\x0b=8\xe4\xc3>\xbc\xd0[\xc9\xe8R\xd3I\x9d\xd3\x99\x9a\x1fL\x98\xb6{r\xad\xda\xba<\xad\xe9Mt\x0d-A\x95\x06\x8dU?\xeb\xfc\xcc\x84)\xdaQ\xd3\xceT\xed\x93\xeb\x191\xd9\xd7\xb60\xe4\xf9w2\xe4\xa1\x89l\xbcq\xbf\x96\x92E-\xcb\xed~\x9e\xcer\xb6\x96\x8a\xce\xeb\x8b.x\xd1-\xcd\x07\xb7&\xdb\xa9S\xb5>\xce\x8c\xd6\xc7\x85\xc1\xfa\xa8\xb5\xb5\xe2\x1d\xe8\x8d\x0c\x92\x0b\xbdA\xf2\xaad\x90\xd4\xd7G\x9f\xcd\xca\xaf\xdd\x14&\x96\xf1<\x8fs\x8f\xf3\xdf\xa6\xd3\x86\x96:\xfbt8\xbb].oW\xb71\xb9Mn\xd3\xdb+\xe28\xa7\xdc^9\x8e]\x98\xbb`}`\xa9\xf6NX+\x15}t\xfb\xc9'\xb7\x9f\xde~\xf6\xe2\xf6\xec\xf6\xcd\xedO\xbd\xa8T\x04mX\x9a*+\xfa\xb7\xdc\xa4\x7f\xe2\x8d\xa6\xe6-\x17\xf7\xfb\x87\xf6\xe9\xb0\x7f\xf6\xe6v\xf0\xea\xa3\xdb\xdd\xcf>\xba\xb5O[\xe3\xfe`w\xeaL&\xb37\x7f\xcd\xb1OG\x93\xc9\x05\x92\xf1\xf3\xa9#\xbf\x93\xa4\xb7\x83pv\xbb\x1b\xcfJ\xef\xa4\x8b\xfc\x9dg\x9d\x9fa\xef\x04.\\I\x03\xbb\x97\x8dJ0\xaf\x9b\xcd\x98\x97Y\xe48\xa8\xe6\xf4a\"\xc7a\xd5\x05\x98'@\xeb7:\xd0V;\xcc\x82l\x06_\x12vw\x9b\xe7\xc6\x9cy\xa9w\xae\xcf\x7f\xba\xf0\x92\xc5\x10o\xb6\xc5\xae\xf2p\xe5\xad\xf1\x99\x1d\xd1q\x07\x1a\x0f)\x91f\x0b+(=\xbd\xbb\\\xa6\\\xc6\x11rYU^\xe3\xf6o\xc55\x97\x0bf\x8a\xdb\x8b\xc7\xe1\x03\xed\x9d\xdd\xc4\xec\xc8\xa8\xb3%\x87\xdb\xd9\x92Y\xd6\xcc%\xf1b\x1b-\xc8\x04\x03\xb9\xe8\xa4_1\x13T\xd2U\xfd\xcaD\x18\x7f;f\x1e\xeb\xe3\xfe\xb4\xde\xb4N?\x89\x9c\x0b\x92\xf6\x81e\xed\x92\xc1\xdc\xab\x11\x13x\xca\xf0K\x82\xf2i\x19\xb8\xf0(\x12fe`\x82%\xbd\xf2\x1d\x8f-/u\x1c6\xca\xd2Z\x84\x970\xb5\x9d\xf1d\xfa\xd5\xfb\xdb\xe9\xce%\xd2\xf1\x0f\x1eYR\xb1r3\xb7\xf9}\x07\xa7\xfb\xe1)R\xf4\x89\xed\xdc\xe2\x06\xea\xb69`\xea`M\x1f\xf4\xbb\x1f\x9e2~\xf5\xc1\x9d\xe9z\xcbn\xa1\x0b\x1b%n\xc2\x03\x01o\x1e`\x18\x8d!x\x0e\x13\xfb\xb3\xd2\x8d\x9f\xcdQ'\xcf\xe5\xa6$\xbe\xccs\xb9\xed\x8c?\xefN\xdb\x1f\xect\xc95\xf1m\x8cR\x16\xe0m\xa8\xe2[\xf7\xe5\x8b\xf3\xef\x7f\xf6\xfa\xcdk\xbc\x87j\xe1\xa5\x15\x8b\xdf\xf6Kb\xdf9\xefw\x99\x03W\xd9\x15\x7f\xbb\x99hE\xcc\xd9%\x08\xb7M\xfa)\xed^gl\x9d\x9f\xfbQL:_$\xe7\xc9\xc2\x8b\xc9\xec\xfc\xdct\xa7\xe8\xae*\x05\x8dc\xff\xc6\n\x83\xe6C\xdbf\xb3&\x18\x03\xd2\x96\x85\x87\xac\xe3\xd1\xa3\xdc5\\\xa6I\xe3T\xef\xe6Y\x90\xa5\x0e\x0b\x1e\xc6c\xc6\x90;\xcf\xbe\xce\xfb\xd3:?_F3/Y\x9cSF\x7f\x9e\xc7\x94;?\xd7\x1c\xb9\x14\xbf\xf4\xf2\xf6\xdc\x16\xb5J\x93$\xa6\xa3<\x17\xc1\x1cl\xc5\x83\x0b\xa4\xb33Q\xa6\x0fJ\xde\xca<\xc4P\xbe\xdau\x99\xf4\x85\x7f-\xbf\xba\x82\xd7]N\xd9\x8dU\xe12\xfe\xa0s\xff\xe3\x9f\xce\xfc\xda\xc2i\xf9\n;\x8e0\x90\xc6\xfd\xa0\xe3\xac\xc1\xb1\xa61j\xf6\xb2X\xf9\xe6a\x16;\xa8]\xde\x89L\x18\xeb\xbb\x10\xb2\xdb\xc8\xe8\xc7')\xd7\x08\xf7\xfa&L8\xb8/uh\x12I\xc6\xd3\x07\x12B\xb42\x08\x0b\xd5\"\x89a\xebe\xe0\x93\xa6\x89\xdf\x08\xb9\xf4Bo\xccPH\xbb$-;\x14\xc1\xb6l\xba;\x8b\x04i\x1d\x8c\x1aE\xba\xebh\x8d\xa9\xda\x0bl\xc4k\x15.t:\xf9\x1c\xb9\xd0\xbb\x13\xbb\x15\x93\xf4\x974\xf8\x90\xc7\x13+T\xb6\xe3p:\xee7q\x9f\x87\x1cI\xee\x8b[\x1e\n\xa5t\xa5\x9b\xb1\x0f\xdf\x93Mw\xb2:\xad\x18q\xca\xae\xb9E\xc7\xa7\xd5n\xb7%\x0c\xe1at\xc6\xb4\xe1)^\xb3\x0f\xc7\x01\x9dm\x96\xe0~\x83}m\x1e\xed~\xe3hM\x18\x14\x8bT\xa5\x0e?P\x99n\x96\xdd\x95\xfb7\x12#3r\xb3\x1b\xa1\xa9\xb6;\xf2\xd5Q\x8clb\xb1\xac\xdb\x12\x80e\xcd\x96\x00\x17Q\xb4$^\xc8!\xa7\x94\x0d\xf0T\xae\x16\xb2\x9d\x94\xae \x93\xc8F\xf7\x90)\xb7_\x8c\xd2&\xc0\xb5\xb8$\x1b\xa8\xee\xbf\xdd.0\xd6\xf4-v\xa1f\x03\x16\xdd\xd0\xef\xbe\x101QO\xd3P\xd7\x80\x95\xbbe\x86\x1brv6\xcaoW\xf5\xef\xb7\xedv\x8f\xf6\x1c;\xb4\xf7v\x0f\x9c\xad\x8c\x90\xe63{_\x7f\x1f\xeaPw\x18\x0b\xed\xc3\x83\xc696,s^\x80q\xb3\xcc$\xd0zE\xe0!\xdd]F*\x0c\xb7\x02\xbci\xad\xbe/\xeaH\x04\xb5\xdc\xd5\xd4\x00\xfc\xaed\x84\xe1*\xc3\xda\xbe\xcb\x1f>\x8e\xc4\xf6\xc6\xe9\x14/lx\x86l\x17\nT\x85\xd0^\xfa\x94\xe0\xe4\xd3a\x14\xe0}\xe4Jp\n\xde8AQ\xdc\xa7\x82\xaa\xaf\x91\xc7\x01\xee\xa3Q<2\xdc\xa1P\xe2\xf8p\xbd\xeb\xd1\xde\xd6\xa8 \xc8l`\xa2\xf8\xfd\x928\xf4\xe8\x11\xa6*\x18\x0f\xa6\xec\xd6*\xfd\xde\x9b\xba\x0c\xd8\x9fR~\x96\xb7\xa5\x18\x8e\xa1z\x04J)Af<\xd4Ub<\xdcu\xd6\xfa\x87\xd5\xfbF\xe2:\xa1N\xe5\xd5W\xd5]\x83\xa69\x14wx<\xddd&H\x98\xf8]|e\xf8\x18\xba+`i3b=\xe5\xa3\x0d{\x0e\x96\xbc\xc1(M\x0b\x17f.\xac\xd9\xaep\xe1\xca@1\x91\xee\xca]\xbeAO\x8b\x99\x0b\x0b\x17\"\xb8\xe5w\x0c\xaf\xe8\xa6\xbc\xa9\x1fA\xcd\n\x8a\xb7\xee~\xfak\xbc\xad[]\x91\xeaA\x94Yy\xb6:\x8b\xdeC\xdel>L\x91\x8d\x85dZ\x96\xcb\xfd\x0f\xdea\xb91\xd1\xdf\xcd$\xc6\x07j\xeb\x9e\xa2\xa1>|P\xbf\xaf\xf7b\xea\xf7\xaaV4$\xd5\xbd\xc6 \x1f\x9b\x1e\xf04\xc4\x17D\xf4\xcbh\xae\xde\xd7\x04I8\n\x0d\xb5@.\x1dQF\xe7 &\xfa\x042\x16C\x9aO\xabW:\x13\x96\x11\xbd\xdd\x0e9\x06Q\xa8Z\xbd2\x0e\x10)z<\x13?\x85F1YH\xc9\xf7\x13\x8c\xcd\x8cX/\xc8\xee\x1e\xeb=\xd5\xf6zz\x83\xe8^\xbf\x8a\x12\xc8{\x95@H>\x17\x8e\xaa\x885\xe7\xf0*\".U\xb1\x00\xbdI\x84\xad\xeb\x99\x08\xa2WuOY\x94K\xc5\xdeM\xb5\xc4L.\xc18v\xb5\xc8\xd5\xfd5\xb0B>\xb9q\xe1\xd2\x85\x95\x0e\xfd)\x9a$\xdalT\x17\xf8\x84h\x9e\xbc\x83\x11\x9c\xc3),`\x08\x9e\xf6\xddk\x18\xc1E^BW\xc7\x19e\xf4\xb4\xa2wT\xacY\xc3)\xcc`\x08\xef\x1c\xfak\xa6\x16\x7fA\x8b\xd3Z\xaf\xe5\xe2\xd7\xa6\xe2\xcfD\xc5\xd7\xean~F\xf9\xb9\x8f\xd62u#\xe3&\xf5\xe5`Q\xad\xbe\xba\xd7\xcey\\\xe23\x0c\xd5\\\xb3\xbb\xf2\xf6Zgy\x85+T.\xae\x04;s\\8\xa7\x909S\xfc\x06\x9aU\x1bB\xc4\xa1\xefJ\x0f\xd4\xb1\xb5\xec\x10\x1ea\x90|=\x8dz\x0d#8Cer\x1e\xd9\xc8:?g\x89\x0eg\xe7\xe7\xa6\x0c\xd3_\xc0\x08^H\xaf\x91\xeakzj\x87\xf6\xbe/\xea\x0e\x83o)\x8e\xc3)\xa4,\x984*Vk2H\xbe\x84\x11|\x81Z\xd8\xa28\xd1\xcbD\xc6\xc9\xbe\xb4\xdf\xba\xf0R\xcc\xe3J=&n\"\x03\xb5pQm\xb5\xf6L]\xbe;3F\x95\xd3qc\xec\xb1\xfe\xd4\xb7{\xbc\xaf\xf5\x0b\xc9\xbe}\xbf\x90\xaa\x8c&;\x88`\x01o6\xb3\xd31\x99V'\x83~2\x89\xbey\xb3\x19\x06\xb5* \x94#2\xaf\x8eLq\xe0\x88\xca\xbe\x1a\x99v~\xab\x93\x1b\xde\xcf\xe2\xb3\x91D\xc4\x99i\xe8l\xc48\x7f\x9cbXs[f\xf3t\x8aM\x90\xa6&\x8c\x08m\x8acx\xac\x8fi\xac\xb8\x9ad\x06\xa9\x81\xbbE\x1d\xeb\xa5\x80\xbd^\x95\xdf\xfb*_\xa7\"\xc0@\xe5\xfe9\x8b\xfe\x1e\xd3\x15WytI\x1c\xf8\xc8K\x15G\xd5\x92$\x80a\xd7k%\x81O\xbd\xb5N\x0c\xc8\x9f\xbfB\xa5v\xb5\xc8\x8d\\\x849\xb6T\x8b\\\xcaE\xce\x88\"l\xacJ\xcfQ\x97^-r^*\x82\xca\xf4j\x91\x0bE\xee\xf9^6\x9f\xab\x1d~W\x996\xef\xa7\x02\xf2\xaeZ\xe8z\xe3@\x94g(\x17\x9c\xc25c\x0b\xaf\xe7\x1b\x07\xfe\x13\xb4:v\xe1\xda\x85\x17.<\xab\xa2~\xf2.\xc0\x08|Z\x1d\x96\xef%\x04\xde\x0d\x158p\x06\x98\xcayA[\xa3r\x9e\xd0\xdb[`\xcf_\xcf\xe7 I\x8b\xe7\xecw\xad\x00B?)\x06\x10\xbb\xc0 vy\xf4T\xf6K-\x8f\x1d\xbd\xd0w4\xb7|6\xf5\xb6\xf5\xc2\xa6\xc4=\xc0\xab\x1e\xec\x1bqtY\xbf\xb1\xb5\xa5\xda\x1a\xc2\xd7\x06\xf8Um\xef\"\xbb\x9d\xba\xd0\xd6i\x9d\xf1\xedE\xed\xdbi7\xf4V\x84\xe9/\xf1\x1b\x06jY\x91$\xf1.9\x98\xff0T\x7fc\xe8\xf4\xaa\xbeYfYR\x83\x88\xe6\xef\xcf\xf4\xef\x0bQ\xcd3\xbcvi~\xed\x0b\xe6.P\xcd\x1d&>\xb9Xf\xd3\xfa\x13\x0ch\x8d'\xbd\x96\xd0P\xa0\xb4\xfaE#\xf6 \xe9\xed\x19\xd74\x98\x9b{\x9b\xd7\xf5\x16\xe7\xc3 \xaf\xc1\xed\x08\xe6.<+\x0e\xa2\xe6\x86_b8\xc5\xd7\x88\x88\xaf\xd1T m\xe0Zy\xf0Y\xa1\xb1q\xe1\xa5az\xcf\xcd;\xba\x10\xe3\xcfD\xccJ:\xa83\x11M\xb6\xf4\xa2^v\xbc\xbb\x11\xdb\xe9\x16 3\xf5\x94\xed\xae.i\xdb\xca\x87<\xad\x0e\"\x8cA\xf5\xa5\x89\xb7\xaf v\x85\x15\x8e\xdbm2\x85\x11:\xf5\xa7\x95\xcbq\xce\xb7\xa11\xfbv\x86W;65\xa1@\xd3\xb0\x8cx\xb0\xd7\xd3i\xcc\xfa\xaa\x08\xf5@\xda\x03\x9ewO7\x89\xa8Q\x81G\x10\xa8\xf38gv[\xcd\x89\x123\xef\x19S\xa5.1m\x82M\x1c\xc9\xd2\xd4\xf2\x8d\xf4\xa8Hm\x00#X\x9e\xc0\xba\xc6\xe4\x81\xb9\xb9\xc7k\x83]\xa0e\xfb\xa8\xb1\xc0\xdc(C\xc9\xcbn\xe1lh\xe3\xa0m\xcc\xd03YG\x13i\x1b3\x96[\x88>\x96T\x0c3\x0d]\x14\xe6\x82V%Bg\"+\xea\xd8\x0f\x8dCO>+T4\xf4\xe9il\x0dO`i\x9c\x99K\xb4\xa7\x88\xf91\x98UV\xe8\xce\xb80L_\xe6\xe4\xfa$\x1fox\xae\xf0\xfc\xbb@,J\x11\x7f\x86\x90\xd9\xf4H\x8cP\x86^\x89\xc9\x8c,\x9b3\xce\xe1\x94\xf6p4b\xc7y\x8fW\xc2P\x13\xeb=7\x9b\x9cQE\xa3\xe7 \x171\xf1\xde*OT\x83\xf0\x0d2L\x94\xb2\xfd\xc2\xb7\x1d\xfdF\x16u\x14\x1f\x0dI\x88\xbf7\xa6\x89\xbf@!N\xaaU?\xf5\xefP\xba\x93\x8a\xa9\x03\xba\xa0\xfb\xe6\x1dm\xad\xdc\xc9\x80\xa7lS\xa0\x8c\xd3\xdb\x96\xd8\xf0r\xd8\xf5\x0b\xfa\xecBV{#D[\x16\xdb|'\x97}\xc7\xfc\xd0\xd9\xd4o\xc0\x12\x13\x99)\xe7?(\x82o\x99\x88P\xa6\x91\xfa\xeb\x0e{=}\x0c\xca\xbb\xfbN`\x10\xe1\xc8\x85\xe0\xce\xc7\xe2\xbd\x9e\xfe\xbe\xd0Qc\x97\xd4ZE\xcd\x11\x8b\xefnpHc\xaa\xc6\x08o`G.\x84\x1b\xdc\x0ehf\xb2\x1a\xbd\x816^=)\xc5\xa7\xcf5KR|\xfat\x1c@\x1bX\x8c\xfaqh\xf0>\xbf\xfbl\x9b\xf2\xae\xe8\x8c\x11\n\x0b]s\xe6\xf92y\x11f+\x96\xb0K\xd5R\xf0\xd7.I*\xf1[vfNT\xddEV\xca\x0c\xa4#\x15\xc2J#\xa9\xe5\xc6S\x18V\x0c\xfe.\xc46\xcb\x1b\x94\xd7\xa6\x0dO \xd5XD\xb8'\x1aMh5K\x0c\x0c!\xd0\xe3\xa4\xf7-#M}\x92\x83\x9e\xc8\xe9/c\x91\x9e\xe0f,\x0f\xbf\x86\x89a\x8cN\xf4\xe2D\xea\x15\x8d\x83v\x1b\x13\xc4o@\xc1\x9aB^7N\x84\x81\xb8\xdc\xfd\xa6\xe6\x9eAy\xdc?\xd4_B\xd4'\x0dQme<\x81X\xbf*\x82&\x06\x1b\x9a\xee.\xd7\xf6r\xa8\x8e\xc4\x85\"\xec\x84\xb2\x92\xe8D\x83\xa99\x02\xa3\x00\xca\x9e\xb7\xd0\x19$\xd3\x96ZWJ\xb5\x96(\xbci\xcb.P\x0e\xbe\xbd\x859\xfdoI\xff[\xab\xa5f\x98\xb3\xfc\x94\xb2\x8c\x1c}\x99\xae\x8d\xca0\xba\x9c\xa1r\xce-\xa3\x84\x87~)<\xbe}\xcb\xcf74\xbb\xeb\x8b\xf2\xb3m\xb1*\x90m\xdf\xb0.\"8BUS\x01\xb6\xd6^LB\x0e\xc0\xf7\xd7\xac S,I\x05\x0b\xd5P\x05\xf8Z\xaa\xd2a\xe2\xda\x8d\x0bW\x0e~\x9f1\x03\xf7\x8d\x9e/\xcd\xee\xbb\x8b6&'\"-\xac\xa0\x17\xe9\x89\x03\xb1\xc8\x8a\x12\xea{\x17\xdfy+\xeasS\xec\xe96\xa2\xce\xb6\xdc\xb4?\x0c\xb4#\xe0w\xbab\xae\xa3\xf8\xb6h\xd4\xdd\x15\x1a\xa6\xa4\x1d\xfd\xaa\xec\x16\xe9',\xc3d\x82\xc5\xf4d\xe3|\xfa>^F^\xba;\xe0\xb6w$\xe3\x95\x87\x07{\xfa\x87/\x85\x86E\xf7\xa4\x7f`|dj\xacP\xd9\xe8\x1f=_z\xab5\x99\x99K\x98\xda\xa4\xcfJ\x8db\xa6\xdc\xb1\x0e\x83*o\xea\xeb+\xe9\xeb+\xcfr\xf3G\x05^\xe8\xee\xd5\x07D\x01r\xfbGu58\xae(\x0f\xd0\x18R\x81 \x03H\x05,<(*`a\x0b\xa9\x80\xd1\xfeQ\x85q\x9bG\x05\xfcC\xe2\xbd\xcd\xfb\xd1\xea\xbb\xdbm\xc1\x88o\xc1 '\xf8\xf8\xb3\xd5\xca\xc6tW61\xf7\xc6\x1d\xd9\xec\xcf]#L\xa6fu\xe5F\xfb\xb8F\xf3Ul\xf1\xbeb\xf3\x03\xbe\xcf-6\xc3\xa5d_tr\x18\x1b#\xdd0\x9a\x9177k\x06S\xab\xc0tQx&U\xeba)\xca\xb1\x9e\xb4T\x8f\xc6\xb5\x80\xd2\x10vs\xb8\x98\xe0\x11\xaf\x1a-O>I4~\xba^\x1da\x14\x9f\xfa\xc4\xd3W\xb6+\\Q\x95\xfe\xb1\x98S\\\x8b\xb3\xfbG}'?Zn\xce\x15\xfa\x86\x03Z\x7f\xa3\x03\xdav\xb2eu\xe9P\xf7\x14\xcb \xe3U\x7fx\xa1=\x1eO\x0d\"YHE\xb2\"\x85\xbct\xc8\nq\xff\x97U1-\x9eF\x8e\xb9:\x98\xa4\x8fm\xeeU]\x19\xd2tm;\x19b\xa0<\xe5\xbfQ\xfd$\x99\xbbF\xa0W(\x11>\xc2\xdc\x92{{\xdb\x9cv\xa9\x06E\x8eD\x8e~\x0c0\xe0\xf2\xa1nu\xed\xa6\x99\xba\x9a=!\xf22uW\x1bR\x9b\xca\x92\xf7\xa2\xb1\xd2\x90\x07\x86\x84\xd0\x067\xd9\xbdA\xd5W\x92\xfbP\x0e\xaa'4\xeeC9\xa8\n]\x89^F\xe3N\x94\x8as\x06=t\xf9v\\\x81b0\x0e\xbb\x1axg\x8d\xd0\xa8\x02] 4\xab@g\x08\xad\xe6\xdf\xa3\x07#\x89 \xb2L'\x1a\xb1\x84\xee\xae+4[\xc7\xf8\xbf$\xe4\xd8}\x87\x1dJ\x82\xd2\xbb\xc8\xed\x8b\xd7\x02,\x12\x95\x8a|?\x8eVABD1J\xae\x93hyElV_V*\x8c\xc2FQ_\xc6\xceD\xa5\"\xb9\x90Q\x14\xf3\x9cB\x87\xda\xbcA\xf5\x87\xd2P\xe7c*.;\x96\xb6sM\xc69\xc4>8\x05\x9f\xa2\xba\x9a*\x93\xc7?\x10^\x12Z\xfb\x1e\xdaT\xe7\xb5\x96r\xcd\xca\xa9\xdc\xce\xe4V\xa0\xab\x07\xa7\xd3P\x85\xc6\x03AWE\xbe\xca\x86j\xea]\x0e\xca\xebo\xa8\xc2`\xfe\xafV\x91\xe3\x87\x81\x94\x80\x96MT\x92U_mGovw\x1d;\xb4\x0f\x1d\x17,\xb1&\xa6(5[\xdej\x94j\xe6S\xfc\xf0\x15\x9f\x91\xf4\xe1+\xe5\xcb\xf0@\x15\xf7\x8f\x0c\xa1\xd4\xb6\xb7D\xe4\x82\x87\xb8\xbf\xe7\xf2\xdb)B\xb5\x1e\xd6\x18E#\xaeeW\xb7>p\xa6\x91\x8e#\x9d\xba\x94\xa9Kx~\xb4\xd8\xce\x1cSX[\xd8\\\x8a\xa9\xb9B`\xba\x01\xa9\x0f_\xb57\xd0)\x0b(\xbb\xd4\xc5\xaf\xd2\xad\x86PhV\xcb3\xfewXe\x8bs\xd5\x04\xbf\xdc\xf0\n\xa1A\xc6\xc8\xf8\xe1\xd1c\x99A\x13\xdb\xc7\x95%\xcdW+\x85\x9e;\xd0\x05%\x90Z\x90L\xac\xec\xd4\x90\x07\x17\x89\xd8\x9bh \"\xb8\xc0s\xb8\x85\xe5\x03\xc92\xfd\xa3\x8dn\x83\x1bL[\xb8\xf0\xba@I,\x9d\xa7^|\x96\x86\x1a\xc0)\xa6\xc1mJ|k\xe8\xfe\xce\xf8\xf3\xeex2\x9d\xb6o'c\xfbthwN'\xb3\xb6}:\x9ct'\xb3\xb6s\xea\xdc\xdac\xeb\xf1\xd4\xb1\xe9\xb3\xd3\xd6d\xe0\x8c?\x9fL\xa6\xb7\x93I\xd7\xf9\xf0\xd4\x99\x0c\x9c\xc9\xf4\xd6>\x1d\xe1\x1b\xb7\x93\xf1d\xea\x14_o?p\x9cj^3:\xdc\x9d\xc9\xc4\x9eL\x9c\xd3\xea3\x81\xebGN\x83\x1b\x8a\xe9\xc8\x02\xc5\x0c\xed\x1d\xb0\x9b\xb8\x98N\xf6y4#\x98RV:\x98X\x16r\x14\x11\xfa,.O\x17s\xa2\x8cLGa^GLq\xab\x94C\xff\x83>f\xa2E\xe5y\xaa3A\xc9!%\x18D\x8f:\xd16\x8bH \x8a\xce\x89f\xbf\xf9\x1a\x99I\x06C\xec\xab_\x05\x90,y\"\xf8\x00W5\x84\"\xb4\xa2[\xf1\x14\x026 \n\x8c\x11x\xdf\xf3\x17\xfa\xb8\x07w\xa6\xb4{\xbb\xfa\x83\xc6\xdench\xc3\x1ab\x86\x1b\xb6\xc5\x8f\x92\xe2\x8eK\xdct\x00\xbc\xcf\x11\xad\xd4\")\x9d\xc8\xef:5}\xc35\xfc-mj\x8a\xedL\xd8\xd4\xf4,\xe8\xf0\xae~\x00\xb9X\xe0s\xcb\x07\xe5Q6)\x82\x009\xb9\x15j\xc9\xbcd\xa0\xdd\xf6\xe1 \xcck\xafg'6\x19\xfbS\xa3\xdf\xceR\x90g1\xf7\xd8\xbf5=k\xa1\xbf\x8d\xfa^\xca/s\x97\x1eh\xc5\x074\xac\xd1>\xb6F0\x87SX\xc2\x10Z-{\x0ef\x031g\xa1s\xfc\x9b\xd9k\x17\xe6\xdc\xbekKq\x13\xef\x8d\x87\x06$\xbc\xbb\x97\xc2\xae\xde'doW\xef\xbf\xa2\xca5\xd9\xa6\xc8c\xe8z\xc4\x9cD\x98G\x01\x06\xbcj\xde9w\x9e\xa7\xbc@\x9d\xc2Z,1)\x87\xa8\xaaz\x8c\xdeu\xca7\x91J\xee\xd3\xfd\xb8\x12\xb9\x0e\xee\xd3\xd9\xbd\xdd\xaa2T\xa8\x83\xf4\xa9\xb2\xf7vu\xc4\xe8S/]tW\xdeu\xd3\xb0\xcd\xc2\x98W\xb3\xf5TMA\xcb\xcb\xd5\xaa\x9d\x8aO\xde\x95\x88\x98\xc1+\x13I\xcb#\x93B4\xc9\x13\x9e'\xe8\x0d\xeeA\x1b\x12\x0c\xbc\xe62^\x1c\xd0\xf9\xdeu\\H\xee\x8f\xb6\xc2\x15V\xd1o\xe44V\xf6eb\xde(!\xb4\x01\x05\x9e>\x0c\xa1\xd3wN\xf06K\xd4\xe9\xc0\x10\xda\xed\x88%TW\x90\x85N\x13\xb1\xe9\x91\x0b\xbd\xca$Et\xa4\x9d\x86\xbb\xc7D\xdb\xdbm\xce\xc4_#\xec\x98d\x12\xf8 \xe8\xeb%\x12\xb1w\xe9\xd2\x12\xe8\xa0\x10N`\xd8\x18\xc2\xc1<\x82=\x9d\xa8\xd2\x87\x9d\xaa\"\x0b\xe3\xbbt\x0f\x8f\x0f\x0f\x8ew\xfb\xbb{G\x07\x83\xdd\xfe\xfe!\xd9\xed\x1dm;\x01\xb9\xaa\xfb\x94\xf9^1S\x01\x13\xe3\xa8\x04\x8b_;\x01{\xcc\xc2\xbeu\xe8\xfa\xf7\x1d\xf8\x10\x1d\xeeR\xb1SR:r\xfc7\x92!w\x9d\x0b%^3\xd7&\xe8\xb4\xc3\xaf\xbcW*-\xd8\xf9|\x92\xb4o'I\xfb\x83\xea)\x83Ex\x1ew\xda\xd3\xde\xf5\xb8\xd79\xf6:\xf3i\xfb\x83\x9d@\x15Vv>\xef]\x8c{}\xcdS\x9f=\x8d\xc6\xbd\xce\xa1\xe61\xe5\xe0k/N\xc8\xcb0\xddvI\xe8\x8e\x91\xa3\xbd #`\xbeqR\x95\x10\x05\xb6yc\xa1J\xd3p=\\\xe0\xbf\xd6\xc6\x91\xe6\xd7\xcfN\x8b\xef\xecJ\xb3^\xe8\x89\xd9\xc9\x9e\xdd\x10\xa2\x9b\xa1T\xea\xbd:J\x11\xe4\xae\xa5\x19e\x19\x8f\xda\x95&\xd9e\xb1r2j\x95\x00\x87,\xac6K\x14\xa3\xdd\xc4xN\xf3E\x118\x85\xb9\x9dv\x93e\xe0\x13{\x80j\xa7S\x18\xc0\x10\x8e\xe8\xa8=\xa9X\x84}\xba+r\xf7\x15uK\x03\xb7\xdb\xab\x8a\xd8\x99V \xe7\xa6\x8f\xbdf!\xc9\xcc\x01\x19\xf7a\xb2\x12\xe5W\x86iC)4\xaf\x86\xb2-\x8aGL\x8c\xa1VE\xf1\xfcc\xd3\x172.\xdaf\xf0\x04\"\xe6\xe8\xd4\xc7\xb8q\x81\xed\x8d\xb3)\xbbH\xe6\x9c\x98\xf5\xd1\xa6\xd8\xe7\xdb\xae\x84\x9eN\x18\x82\x0d\xa9\xea\x98L\x08T\x1b\xac\xa7\x86)\xe0\nd\xf2\nT\xef\x1f\x89\x83\x93\xf0\x8d\xd0\xd2\xdeV\xab$\xd5x\x18\x1b\x86\xb1\x8e\x08\xf7e\xae\xe0\x18\x96\xa2\xdfz\xb9\xbe+\xe4\xee\x9f\xe1\x98L\xb7\x8f\x99ne \xc1\xec8~*\x99/\xb9\xd3\x05\x0b\x97!\x9clx<\x18\x92|\x1a\xcd\xb2%\xb1\\\x85\xc1,32,E\x8es\\\xbcs\xbd\x8a\x82/\xc9\xec\xcc[\xad\x97\xe4\xe38Z\x9d\xf9\x0b\xb2\xf2`$=|\x1e\x13/%\x7f\xe3\xd3O^\\c1\x16J\x0d\xbf\xfe\x8d\xd5\xb2\xf2R\x10\xceI,\xfdN\xd4\x9a\xb9\xa1\x1bH\xd7Wk^\x9eh\xf0\xa9\xaf\xa4H \x90\xe7\x87\xf6\xde>=n*H\x85\x8f\x0ev\x9dM\xa3\xb1\xc8|\"\xed\x16\x13\xc9e9\x95\x1a\xcc\xc8\xdc\xcb\x96\xe9\xb0z\xab\xf4;\xea7\x81kj%\"\xf3Q\x8e\x04&\xaa\xcc\xbb'\x90L)\xf3^= \xb2\xa2\xe7d\xe5\x05\xcb-Z\xc8\x12\x12\x7f\x97\xb0\xd5\xe8\xfa\xd1j\xa3\xb6x\xbf\xceg^J:i\xb0\"\xd6\xe6-\xa2\xaf\xc5G^J\x9cn\x1a\xbd<{\xcd\xbc@m\x8d\x1dBs\xda\xc5\xcd\xb9y[\xbd\xcd+=\x9f/#/}\xe0\xaa\x830%\x97\x0f\xdea\x1eD{X#T\x88\x8fX\xe5<\xee\xb6t\x8c\xe9r\x94fQ1\xf8\x0f\xb5\xfd2\xba\xab\x07\xd0\xfaN\\\xe5\xfel#\xb0{.\xc4]\xe6`\x11\xcco\x1c\xadB\x03rC\x8b\x9a\x82H|\x02|>\x8f\xe2\x95g\x88\\EI\x827\xc6\xfc\x91\xe7\x16\xb4!\x98\xa2\x0b\x90\xf6\x12\x92\xc0K\xec]\x90|\x9c\x85\xbecGx\x82\xb2\xd1\x1ek\xfd |\x1bF\xefBxs\xb3&C\xa0\xf5\xa5\xd8\xbb\xba\xa9\xf1M\xc40\xa7J\xa9^u)\x0e\x85\x9e\xf0%\x17\x97\xb2\x9fB\x1f\x8a\x9c\x14\x94\xc9\xe7E\xc6\xfd)\x15\xde\xe4\x9f\x98\xc7\xca8{\xcaR\xe8\xe2\xc5\x81\xf0\xf9\xadY\n\xb4yw9\xfd\xd0\x17\xf1\xb0\x08\xbf\xc4\x17\x10\x8dg/\xf0\xf9\n\xba\xdel\x16\xd0\xc9\xf1\x96\xdfo(?\xc7\xf2AJV\x86\x02h\x14\xe9\x06\xa1\xbf\xccf\xe43\xe2\xcd^\x87\xcb\x1b}\xd1\xb5\\\xf4\x87q\x90\x12ZV/\xe8I\xd3\x9f9e\xdc\x99\x11\xb2^\xdePz\xb6\xfe\xeb\xe4\xc6\xc1#\xff\x07\x1f\xc4dnma\xa5\x94\xe5\x8a\x92ou7\x08g\xe4\xfa\xf5\xdc\xb6\xfe\x8aU\xc9\xcc >\xefM\x16\xa2H\xef\x7f\x1c\xb0\xe0\xb7\x91\xe4\x1a\xae\x176kb\xec\x82hc.f\xc3 \xaf\x8a\xdb6^\x1c{7*\x97\x01\xedy\x01U0\x85\xb7\xf9\xc8l\xed\xbe\xe2\xc1\x06\x14\xcc\xae\xba1\xca\x9fY\xe56\x8b\xfc\xc9E\xf5+*\xd8-\x1cX\x8c\xaf\xa6t%\xe8\xdf\xee\x8c\xacc\xe2{)\x99\xe1\x8d/\xf9Q\xccq\x0d\xd8\x05\xb6\xea\xe3w\x02\xbf\xf0\xf9\x1a\xef\xb9\xcfh\x81\x11\xa46-A\x85B\x83\xd0\x8f\x13\xcd\xb4N\xbe\x03\xb3\xcav\xe9\xd7\x8c\x06W\x90\xbe\xee\xebQ\x01\xaa\x11\x0c\x94y\xf4\x1d\x97\xc5,\xb0o\\\x8c\xb2\xb6\x82\x11\xf4O`\x05O`\xef\x04V\xed\xb6\x03\xb3\xb1U\xee\x12\xa5\x95+:\xb4K}\xb78\xd2\xcfTT6\x91i\x8e?\x0c\x19\xe0\x94\xa7\xb2 \x12v\xbdl\xde\xf5\xc2\x9b\xd7s\xd4\x92\xb1\xaf\xdd\x95\xb7.<5\x9a\xee\xe6\xb2\xf8\xf3:\x9f\x08\x18*ME!\x11M\xe1\xd7\x07lj\x9c\xdas\xfa\x94\xd2q\xd2%a\xb6\xc2\x10\x8c\x82c\xcb\xdf\x87|\xa9B\xca\x0e\x97\xc1\x97\x04\xbb\xe7\xd8\xec5g\xdc\xa3uX\xf3`IX\x8a\x8d\x08\x1d\x9b\xd0\xa5I\x17/_U\x12\xdbU\x19\xbf\x9e\x96\x89\xe1u\x13V\xfe\xd1#\xa6\xb6\x17\x00\xf4h)\xb8\x01{\x8e\x1cF\"C\x8aO\xc6{\xd7x\x04\xd9\x88\xa1\xb2K\xcb\xdf\x1aO\x8d\xb6\xe1\xa9x\xff\xa5\x86\xa7z\xf8|\x13\x86\x19m\xc90\xa3&\x86\x19\xd5\xb3\xf25c\xba\x9b\xf0\xd4\x85\\4\xe7\xa9\xfa\xb23l\x99#\xb4\xbe\xc8\x15\xd26\xfd\xb3\x9b\x9ag\x97(\x86]\xaf\x96\xfa\xc7\x94\x86]b|2\xfd\xf3s|\xbe\x8e\xc9<\xb8\xd6\x97\xb8\xc8kH\xd6\x9eo\xa8\xe6\x1d\x9b\xda0[\xe9\x9f_\xe7\x87d\x03\x03\xcfj\x188\x9a\x07\x1c\x96\xda\xfc\xc7\xc1\xc5\xb3&.\x8e\xd1Y1l\x8c\x15F\xa9wI'\xc7b\xfe\xb1\xf69\x9c\xc29\x15\xcb\x87\x16\xba\xb6;\x94A\xb8p\xc1\xf4\xf37c\xfa\xdc\xba^-\xc3\x043e\x9f\xd3B\xf8\x13o\x03^\x18\x04\x1c\x99)\xa0[\xe5\xdcD|i\xe99\xc5\x07J8\xf0\xef\xed-\\\xd2\xff\xbez\xef2\x08\x0f\\'\xff\xa0e\x18\x96\xc0e\x97\xc7\xe0\xcd\x85\xbf+\xee\x95;u+\x1cbIy\xc3R\x8dZe\xe4\x0c\xf43\x17;\x90\xe5\xa4\xa2\x953?>\xe4\x08U\xfd\xbe\xf8h\xf8\xd3\x8c\xb6>\xdb\xbau\xc1V\xb6n]L\x03/9u\x01%\x9c\xa2\ns\xab\xe7^\x9a\xc6C\xb81T\xee\xc2\x95\x1e\x1b)e?3\xb8XB\xc1\x8a4\xabb\xdfsY\xce6\x9a\x15\x17\xce\x0c\xebb\xdfsa\xb6j\x9f\x97R\nm nk\xd3\x12\x01\x9f\xfa\x17zq\xbbA\x9c~F\xc5ii\xcf\xd0\x9d\xb8\x14\x1b\xf0\x85Y:\xa5}{Q\xb9jh?ct\xa3\xf5b\xfcL\x12\xbcooa-?(Dn*\x8c\x1b\xa6\xab\xd4\x0e}\x8b\x11\x89\xfc\xab\xe8!\xff\xdd\xa58\x1b\\di\xed\xb2\x89\xcf\x15\x8f.YF\x05\xac\x0b\xa54\xda\xd9\xfc\x971\x05K\xf5\xf3\x85\xe8_-\xd3\xae~\xde\x8a\xb78F\x99)\xbd\xf8\xdc\x8c\xf3Q\x0br\xf8l\x9a\xb3,\x14\x9b\xbe\xa0#\xf8\x82>\x91\x80\xcb\xf13<\xf7\xe0\xdf\xf2\xa3\xb7\x14\xfe\x96\x0214f\x82sQ\xbf0\xb5\xa9^\xe4O\xb9\xb3#P;\xef\xca\xce\xe9\xf2\x0cV\x84A1\x00\xbbT\x86\xc1Mv\x19\xe9s\xc5\xe3f\xa6lt\xcd/\x94\xd1\xe3%\xa5\x14|\xa7 \x19\xf5\xa3\xd0\xf7R\n\x1fJt\xf5e\xc3\xb4\xd5\x91Fq\x98\xe4\x0d5\x11\xea\xb2\xb49\x04\xebYx\x93.\x82\xf0\x12|/\x84\x0b\x02\x0b\x12\x13\x83T@;\xedo\xca\x11\xaa\x0d%\xa6s+%r\x0f\xc8g6\xa0\x91|\xe6\xae\xcb\xf8\xbf\xe4\xae\xb1\x12h\xc63&\x94\x17\xf5\x1d]\xd4w\xecT\x96\xb0\x80kl\x85o\xe0\x14\xc6\xfa\xbe\x1b\xfb\xfd\xde\x85kZ\xd1u\xb5\xeb\xef\xb5v\x90\xa5\xd9\x17\x81\xca;\xeci\x19K\xd1\x08Z\xd2s\x05\x82n8vX\xb5:\x01\x1aJ\xfc\xa5\x17{\xb4\xc1!\xb44\xd7\x1b\x83pF\xc2t\x08\xd6$\xad\xdc\xae\xab\x9a\xcb\x00o1\xd4X\xa5h\x7f\xa2\xa2?\xcb&\x13W\xa5<\xc7\xa9\x06\xab\\\x0d\x87\x96<\x05\xf6\xabn1PxK\xec\x0f\x9c\xeeY\x1a\x13O#\xfe\xa3N\x8c~\xb1\xa4\x15\x83\x8a\xf5Jo\xf5\x04\x919\x80\xd24\xcd\xc9\x01=\x05\xd0\xa5\x11\xc7\x1e0\xd1!\xbf\x92k\xb3\xf7\x9c\xee\x17Q\x10\xda\xe8KgYU\xdb\x9a\xf8$\x94\x8c\x19\x84oC4\x08\x1b\xbdD\xd3\xb1\x142\xe0-\xb9I\xec\xd4\x19\xf7\xa6SdyI\xf7\x9c,\xc9\xaa0\xdbr\x80\xa0\xdc\x91\x9bC\x02?\xcaB*\xfd\x84\x12\x0c1\x89\x0d\xab\x0c\xa3-{20%q\x9c\xadS\xcc\x00'\xc0\xfa\x19\xf3\x99\xd3\xbe.4\x14\xf0S2\x957\x95\x87\xf9z\xad\xcd:\xde\xf24l-\x02\"y\xab\xf5m\xa8~r3g\x1b\x1e\x8f\xac\xc7\xd0f\x0epmxl=6\xbe\xf8\x1e\xbd\xa6\xc7dj\x14,7 \x93\xe2z2\xc7\x08%\x94\xad\xf8\xe0\xa5\\\x81B\xfa\xbb\xb9Pv\xc6\x18\xd1\xca\x0c\xf7\x1a\xc4'\xe9\"\xcd\xa48\xb6\xb6\xf9\x0f\x0cty\xee\xcf\xbc\x14\x95RK6\x9d\xb6\xf5\xa45~\xfe\xd1\xb37\xcf\xc6\xf4\xc0)J8\xb9\xe3\xde\xced:\x99>\xdd\xb9t\xc1\x9aN\xa7\xd3\xa7y\xf1\xa7xx\xb5\xa6\xd3\xa7\x16V\xcdW\x13Q\xdf\xe7\xa1k\x96\xd2=\xaed\xc3\xf8\xc5\xf2G\xbb\xb7N\xc1\xc2\x01!T\xd9YpJ1\x90\x0f\x19\x86\xa2\x0b9\x15\x816\xf4\xf1r\x81\xbdd\x89\xb5]T%\xb5zyo\xd1\x13\xd3,T\xbc\xc77no\xa5\xc1\xd5\x8865\x0b%L\xea\xc6w\xf3\xfe$\x9a\xee\x189\xb3~F)E\x19B\xa4\xdf\xd49}\x18\xd2U\xd3\x16\xc9\xc5\xfdd\x08s\x83F.\nS\xe4l\x06e\x13#aC\x08M\x9d@\xca5\x04\xaf\xeey\xd5e\x15\x94\xa9xo\xe0#^\x1d\x1f)\x11\xf2\xc2HL$\x97&\x8a\xcf\xba\x08\xf1\x82 \x12\x89\xcc2\x0f|\x0c\x9fK\xa7$\xbf\x9d`\xa6\x9a\x81\xd14\xce\xd3X*\x95\xd5\xed\x1d\xe1$W\xbc\x94,\x82yZ\x0d\xa8#\x7f*\xc6=\xadKX\xb5|d\x07N\xb3\xc2\x8c~p\xf25gp\xf1\xd1K\xe9z([\n;F\xed\xf5)\xce;\xe3yB\xa1f\xf3\x94\x0b\xa7`=\xd9\xa1T\x8d\xffn\x83\xf5\xd4\x92Kq\x06\xfa\xe8\x11\xb4BZz\x12\xf2\xc7\xe8W\x8c\x17\xc9t\x1b\xcf\xbc\x8aQ\xa3\xd9\xa3\xd5\x92\xf1\x04\x9dr\x8b\xdf]o\xbd&\xe1\x8c\x8a\x0d\xae\x8cO]\x06\x0cJ@\x11\x1d\xccn\xf5\x1c\x17Z\xbdMH\x04]4\x8e\xc9\xf9\xac\x95\xe7K\x9a.i\xa2\x8a\xdd/,\x07\xa7`\x01++=CI\xca\x02\xcb)\xde\x8dq\x85D\xf5|\xfaqo\x08\xd8\x8eiM\xc4\x02\x97\x96\xa5\x15W\xb7\xa4xC.\xa8\"#\xae\x0c\xde\xbd3]\x87\x82\x1a\xa7;-\xcd\xd0\xd0\x0bD\x1a\xf4H6\xa8_9\x0d\x0b\xd5\xb52Q\x16\xf41\xc5\x08\x00\xdd\x04eh8e\x99Px\xaax\xb3\xb5\xc3\xb2\xcc\"\x9c\x89\xcc\x0bW\x00>\xa3\xfc|,A\"\xda\xac\xf894\xb6\xb1\xe0q\xe4\xcd[ef\xe6\xfe\x0b\x863\xe4:}\x13\xf8o\x99\x13J\xba\xe5N\xbc\xaa\x95\x0f+\xc4\x0e\xf5\x1e\xf6\x1c\xda#\x96\x8c\x12\xf2\xd8\xab(\xc9 \xb7\xc79\xe7\xd7V{\xa2\xd0\xb2\x89\x08\xe3\xc1\xd2L\x1agv\xa3g\x94\xf8\xf8]\xb2\nR\xdb\xa2\xd2\x99\xa5\xb5\x9c\x8a\x0f\x15P\xd8\xfaoHT\xeb\xe6\xf1\xa6v\x1e=\xfb\x8a'\xa0[\xbb\x98\"\x91\xb2\xbd\x9e\xa3\x0f\xed\\\xd3\xca\xa5q\xf8\xccf\xdf0\xcb\xe9\xb75\xcb)\x95\xf58\x88\x843\x0b\x7f\xc6\xc4\x9by\x17x\x00\xa7\x04H<\xf7\x97QB\x0c\x91\xee@\x7fl\x00\xc3rT!\xc2M\xa0y\x1c\x0b5=$p\x94\x08\xbb\x92j\x02q\x1b\x8f\xee2\xd4\xc5s\xae\xbe\xe6+\x12'\xa8\xd3\xb0\xfa\xdd\x9ea\xd7\x93\xd0\x8ff\xe8\xe1\x19w\xc5wFr)\xbd\xfa^\x8a\xd9\xd4%K\xb2b*\x85\x02\xf6\"\x87\xd5b\x9f\xd8\x87\xfa\xe1\xa2\xc2a\x08\x99\xcd\xb4\x81E\xecD\xbc\xc8\xc5\x82\x15\xe6\xbe\x06&%\x0c=\x0dm\xe2\xf5 \xc2\x9a\xcb\xf2@\xa2L\xe5@\xba\x88\xa3wH\xc61(\xacm\x85Q\n^\x92\x04\x97!\x99A\x1a\x81\x07,\x14uK'?\x88\xcf\x95\x94\xaa\xbb\xde\xdePdG\x96\x143\xe6\x8a=[\xea-'\xaa\xa1[\xaa\x81\xa9\x80\xdaT\xc0\x10\x94V\x0e\xbc\xdfD\xdb\x08\xaf\xdc\xd6\xc9\x8a\xe2c\xa2R\x86#\x1f\xa5y\x9b.\x89\xc4p\xd9\xee\xa1Ccv<\x91\x01\x9a\xca\xb9\xe2 \xed\xe9\xc6$S\x9dW!$\x96\x91=\xffU\x8a\x1a\xba\xbbg\x88\x18*\x0fG\xb0\xf3\xf2\x00\xadG\xd6\x10\xacG\xdej}R!\x8a\x8f\xad\xc7\xf4\xc9\xcffQZ}d=f/\xad\xa3Dy\xf4\x04\x1f-\xd5w\x9e\xe2\x83\xcb\xf4\xa4\xa0\xa3\xd2\xb0\xb7\xbal\xc5\x89\x17\xa7lH\xbcru\x8f=~d=y\xfax\xea\xec\\\xd6LF\xa5\xc2pL\xaaI\xb4`\xb8m(\x8a\xd2%\xba\x93\xd2\xbc\xf3[\x11\xfd}\xa7\xfb\xe2\x8a\x84\xe9\x8bU\x90\xa6$\xd6)\xf9\xd5\x83t\xccc\xa1.\x02\xe5Z>\xfd\x84\xf6\xee\xbec\x07.&\xd3\x0d\xba\x9f\x15\x14\x93\xb6x\x80\xc0\x1f\xc6A\x9a\x03\xf7\xf6\x8f\x11\xf8Q\xb6^\x92k\x06:\xe8!\xe8M\xec\x85\xc9<\x8aW\x1c\xdaG\xe8\xf7\xbd$y\xb3\x88\xa3\xecr\xc1\xe1\x03\x843\x9d8;\xd8\x05r\xc2\x8f\x00\x9d\xc1j'\xffJ\xca#o\xd2\x9c\x07\xfa\xd3h\x8a\x06a\x1c\x0e\xbb0\xc5X\x0dZ\x89\xe9\x1b\x18\x1bh\xede \x91\xbe*\xc7&}\x93\x91\x96\n\x85\x05\x1f\xc2\x1ac\x92d\xab\xd2\xf7\xdaSY\xd8\x8d\xc2\\$\x0b\xd0\x81\x0e\x01\xb1\x17\x84\x96\x0b\x11B\xce\x83\xe4,\x9d\x05\x11\x957\xe4\x81\x11$*\xb7\xb7`\xb3j\xa8\x18\xe7\x82\x87\x02\x11\xfd\xcd\xc46\x17\x92\xaa\x16\xef\x8a\x874k\xf5M\xf3\xebi\x07\x9bac\x19\xe7\xb8)\xa3c\x9b\xcd^\xb2A\x85\x86{\xe03\x92\xa4qt\xc366\xff\xb1i\xb3\xbe\x9en\xa3\xaf\x90\xed\xb8\xdcN\x1cw\x97A\x92\x92\x90\xc4\xcf)\x1f\xc2\xfd\xe4\x82E(3\xb5\x1c\xc1_\xab\xf4V\xdf\xe2\xdc\x88&\xab\xe8\x8a|\xc2\xdb\xa9\xac\xb9\xf2PZ\x7f\xf5Uy\x9d\xab\xcf\x8a5\xd7\xbe\x89#\xa2\xc2\x92\xaeU\xf9\xa9\xa9\xd5ym\xabsm\xbd\xc5\xd3\x9a\x9d \xc8-\xc3\xe4R?\xab\x10\x19\xdb\xe7\n\xb6\xcf\xf3w\xca\x10v\x94\xa1\x04\xc8b^\xceM4\xdca\x8ec5d]\x7f\xab\xaf\xa0\xeaG=\xa7\xcb\xc2\xe3\x96\x19\x9e0\x1e6\x86\xc8\xa9\xa2R\x8ee\xa9\x16\xcbZ\xcd\\\x0d\x84\x00i\xa7 %\x19#\x8e,E\xbe\xb9Y\x13.I>\xf7B*LR6\x03\x1e\xf8K/I\xc0K\xc0\xcb[\xd2\x1c\x0b\xdf\xf3\x0d\x94\xcb>\x0b\xe2\xcd\x80E\xa3\xe1\x90\xd4\x0b\x96e\x08?\x0e\x8c\xaa^\xcb:$I\xd5\x8c\xe6\xf5r\x9a\x10m\xf5\xf3A\xb7\xa21S~H\xaeS\xa6\x8eR\xc7\xa9\x8af\xf2P\x9eb\xc0\x92|\xb8\xa8\xf5\xc1\xdb\xc0\xc3\xd2\xac\x90\xf2\x94\x10\x17\xdam\xa9\x9a\xf2l\xb8\xa5\xb1g!\xea\xbe\xbf\xfd\xe1\xe7\xfd\xddd\x0ex\xec\x0ci&\xd0\x11\\\x1ec\x051\xb6\x19\xb32b\x13}\xe7\xe2xQk\xddy5\x15'\x1a\xda\xa3.\x9d\x91Z\xbf\xc3\xbe2\xc4\xd3\xd2\x80\xaa8^Y\xf2\xa2%:\xbd.t:RU\xda\x98\x85u3\x82\xb1\x0e\x9bf\xa4\xaew\x0d;\xb0\xdc\xda\x17Q\x106\"\x1c\x9b\xffQu\xfe\xc5E\x0f\x8d\x17s)\xean\xdeY\xe6Zl1m<\xae\nO\xcdM\xe7\xed\xc4\x81\x10\xda#4\x81\x13\xc3\x9a \xaeR;\x7f\xe8{u\xcf1\xc5]o\xb9\x8c|\xbbg\xf0cV0\xa6\xd0\xf57\xa0]13xj\x0eXl\x08\xde\xde\x0f\xc2\xc4\x9b\x13;\x85\xa7O\x9f\xa2v2+O\x9fG\x97\xf3\x04\xb2\x13\x07'.\xc36\xd8\xacF\xfc\xe2\x04^\xde\x8e\xd67,\xb0\x01}\xa5-\n\x96\xa2\x18dl\xd2MS\x1c)S\x9c\x03\xdeSI\x0b\x03s\x06\xdd L\xd6\xc4OK?\xba~\x96\xa4\xd1\x8a\x91\x89\\9\x93/\xd0\xb8ZpZ\x87\xecb7\xe7/i\xd4jlXC0\x92\x1c}\xb8\x1e,.\x05z\xcfMo\xec\xe2h1^\xe3\x89{c\x7f$\x1d\xfb.sw\xbd\xddF+\x90\x88\x0fS\x1cu\x13\x92\xbe\\\xad\xc8,\xf0\xcc\x1e\xae\xdc>\xc3|\x8cx\xcab5&\xb3\xfc\xf1k\xaej\x007\xdb\x98L3\xc0M7iw\x16\xf9\xa8(3\x97[\x97\x12B~_ \xc9k\xcc*\xa7}`\xcc\xa7N\xab\xc2\x8clk:'o\x82\x15\x89\xb2\x14NaM\xc9\xb5[D\x8c\xe7yk\xa6\xccq\xfa\xab\xf7\xdd4bW\xdb\xf9\xe9[$\xb6aQ\x8b\x9a\xe8\x88\xf8Hf\xa0Z\xca-\x7ff\xb6&\xaa\xaf\xf8\x98\xf4[0\x94Q\xa7\xae \xb4\xa1v\xd7Q\x92~\xca\xb3\xf9\xb3\xac?\xc1\x8an\xc93?\x0e\xd6\xa9\xd1\xddG|\x04\x11\xd79\x08V?x\xcc\xefF\xe1\x8a5Woh\xcf\x85\xbf\xbc|\x13\xd3\xab~\x88\xde\x84 \x7f\x18o(f\xc0\xb6,\x17\xac\x0f-~\xa8(\x1a\x0e\xab\xa1\x94K\xb5\xe8W\xc2vP!\xc5\xab~\xbe\xf0\xc2\x90,\xe1\x14l\x1b\xa3\xa7\x90wP~\xe4t\xe9\xbc\xf7\xf5\x03\xaeE\xae\x99\x9d\"\x057\xa9<\xb7\xc0\xd3\x08;1(M\x8a\x01\x0bQ5\x86\xc6E+\nc\xe2\xcdn\x92\xd4K\x89\xbf\xf0\xc2K\x82i\x92\x97\xa3\xddvD\xbe\x8b\xe2\x0e.Z\x06\x0d\x97\xbd@r\xfb\xaa\xdf\x85\x94\x1f_x\xfe[\xe3qV|\xbc\xf82\xd1\xf9\xdb\x89\x8f\xe1\xae=\x14l\xc8\x1f'S\xa6\xdf\x8e\xed\xc4q!i\xb7M\x08\xb7fG4y\xed\x16J\xd9:\x1f\x82\x85y\x89Yzw\xf0\xab\x81\x9b\xa1\xa1\xca\x1a\x1f\x15T\x8e::\"\xa1\x9f\x94\x86\xbb;\x02[h\x17\xeb}\xf4\x1a}\x9e\xe7\xdc\xf5\xa6\xaeL}\x9a@\xf1im\xb8{\xe4O~:\xed\n4k\x16p\xc4'\xc6\xf7(\xd6\xd5\xf7^|\xf2\x14P\x0d\xba\x0b\xdd\x07\xfd\xae{f\xdf[\xdd\x87\xd4\xf9O\xea>\x0d^\xda\xd5\x0f\xf6\xa9\xbfm\x9f\xe2qo\x93\xbbU\xf2\xe7.\xfd\x1a\xdc\xa5_.\xc4\xe3\xfe\x8f\xa3w\xbbw\xef\x1d\xfd\x7f\xf0-\xf7\xb1\xd1\xd5[\xf7A{\xfd\x12U\x0e\x1aw\x0f\xddG/Q\x97J\x98\x84\xa3\xbc\x00\xcc\x83\xd0[.7\xa1\x0f\xccp?\xdf\xe0\xbc`|\xba\xa9\xdfoE\xb7g[Y\xc8\x02\x02\xcedY(!\xcby\x11\xa9?\x0fN\xbc\x08\x12\x0c\x83=\xc4\x02\x92\x0d\xb8\x949\x14y\xb1\xd9\x15`\xf3[Q9\xfb0\x90M3\xf1E\xdd\x03\xe9.#\xdf[\x9e\xa5Q\xec]\x12)\xa2\xa3:)r\xfeTm\x855\xef*\x10aQ.\xb7\xaf\xe5GBa\xc8sn\xa07\x99\x95\xc6\x19a\x87\x7f\x1e\xd2.t\xbai\xf4I\xf4\x8e\xc4\xcf=\x8d\x01Y\xfe\xb5q\xf0R\x10wal+\x8c>\xe2A\x88\xd0\xc0b\x8a\xbd\x0d\x92\xb1\xa9\x1a\x15\x13\x8a\xb14\x9eapm\xb4ai\xe5\x12\xa1m\xa1\x85\xa8\xd2\xb5\xaa\xef\x91\xee\x1e\x81\xf8\xd0*b\xcf'\xa5*\xe0\x14\xfc(L\xa2%\xe9\xe2C\x16\xc0F\x80\xdeyq\x88g%\x1c\xa4\x1aD\x0f\x8c;-W\x170R\x93\xa2I\xaap\xc4j\xda\x87\xc6\xad\xb4\xd1\x1e\xd2+\xe2J\x19\x96\n\xb0\xe4\x06r\xac\xcb\xa3\x14\xda\xfb}\xed\xad\xcfH\xdd\x1e\xdc\xb6G\xe9\x82d\xde\x8b\n\x1c\xa2+\x15\xa9\x01\xc9\x0bG\x12MpS\xac\xb8\x1b\x84\x0b\x12\x07\xd8yt,q%\x98\x1d1'\x93H\xd2\xab\x9f\xa7\x92\xcbH\xddd\x01\xa2\x06\xb7DT\xdb\xde\xc2\xb3\x86.\xcf\xe1F\xcbS~k\xd0\xbf\xc3K\xfd\xfe\x81S8\xc5\xdc\xf1}\xc9}f\x93\x1a\x9a\xec\xcd\xfdc}\x16\xc4\xfe\xb1>\xcf\xcd\xdeAs\xac\xf6\xeaBqK\x04\x0bH-\xc7P\xd2\xeb\xcc\xb3\"zU\x8c\x97R\xd1*g\x13)\x8a5\xe6\xd6\xcb\n\xebWau\xe8z\xc9M\xe8\xf3\xe4\xadYw\x1d\x07\xab \x0d\xae\x08\x9c\xe6.0pZn\x02\x87u\xbc\xef`6\x0c\x1e\x03\xca\xd6\x948pl\x82w\xe5*\xcf\xa4zi\xb1C\x07S\x0e\xc8\xc0\xfd^\x9f\x01\xe9\xd7\x01V\x93w\x15\xfd~\xec\xfd\xde.\x82\xd6,!\xa7\x00\xee!p\x16$\xeb(\x07\xf6\xd1f\xd3]y\xd7\xcf.sX_\xc0\x04\x80\xbd\x19\x939\xba\xa7\x90X\xc0\x0f\xe8\x8e\xa3\x88\x92m\xb9k\x9a\x10i\xef@\x17\xb9\x1du>\xdeE\xa2\xa2\x12>\x99/#9\x97\xf5f\xe8\xc4\xd1$H^y\xafl\x8c\xfb\xcf\xd2x \x96\xa40\x82W\x18\xc3\x153H\x0d\xd8\x9e\x92\x07\xc6\xcb\xc9l\xfd\xe4\xe8\x02\xd9]\xb1 v\x89\x0b~y\x81\x03L\x9dBe\x1f\xbb\xc8?_&\xb9\x8eDv\x04\xb9\xd1\xb8\x83\xbf^\xd3\xc6\x13x\x8c\xa5\x1f\x83\x17\xce\xe01/\xfe\x18|\xe6\xe2sA K\xd0]\xfc\x92\xa4\x0b\x12W\xb5\xe5|\x19\xcbazr\xd1\xc8:?\x17\xd1\x19\xce\xcf-\x16\xaf>\xec\xce\xa3\x18\x9dp \x0cYf)\xcf.B\xe3\x93\xfc[X\x0c#\xe24\x9f]\x0c\xcbh\xd5 s\xd7\n\xa8\x8c\xd1(A\x87c\x82q]R\x1e\xa8\xddW\xee\x13\xb1T\xce\xe7\xe7\xeb8\x9a\x07K\x12\x9f\x9f\x03\x8f\x14^@0$\xa6\xdf\xcd\xd63/%/\xc2+\xbcJ\x9d\x87\x9fx\x90\xbd\xd3\x88\x93\xbb\xba\\\xbcBU+\x89Y\x17A8S\xb1TS\x90.\x95\x8a\xb6r\xe2\xff\xd2\xc3\xa4x(y[\xf1u\x7f\x99\xbc\x08\xb3\x15\x89\xbd\x8b%i\xa2\x07\x9b%j\xd0\xde\x84\xa2\x934g7\xd3\n\xbc\x1f\x18\xe27\xacK\xa5vk\x0ew\xc5n\n\xec\x90\xa58\xf3\xf9q\xdf\xb3)\xae\xa1Ux\xdeM\xa28\xb5\xb5\x04v\x8d\xa9W\x11\xf9\xd7\xb8\xdc\xc3\"\xfbL\x83\xc6}>N\xa7\xc8\xcf\x99\xc4\xed\xd2\x01\xca\x93e<\x88\xf1\xde'\xecE\x96R\xf8T\xd4\xe3\xbb\xb0t!\x1c\xa7S\x17R\x91gD{\xa3\xdctX}\x10\\\xde;\xacRR!\x81\xea\xf3E\x1c\xe9\xd3E\xec\x1d\xf5\x9d\xee\x8a\xa4\x8bh\x96\xe8(\xed\x9e\xf2\x1eg\xd6\xc7\xba\x04\xd3\x9a\xbd\x80g\xc2r\xc9\xf9\xa6\xbbfYl\x0cff,?\x96\x1c\x14J\x89\x1d\x94\xf0\x9d\x0b\x94\x81\xa3J\xcc\x80\x19B\xc9*hL\xdd\xa5?H\xa1o\xb7\x0bW.\xdc\xb8p\xe9\xc2\xca\x85s\x17.\\x\xe7\xc2\xb5\x0bg.\xbcp\xe1\x99\x0b\xaf]\xf8\xc2\x85\xb7.\x86\xb1Z\xe2\xe9KO\xf0\xaf\x98T\xdc\xe2\x020%\xe5\x9cw\xe7\xbai\xc6\xabS\x89\x9eK25\xc5\xfb3\xcct*\x831\xb8\xd3\x08\xce\xba\x97$e\xd1\x87\xcf\xba \xfd\xba\xc2\xaf\xcc\xac\xe1b\x94\xce3f>q\xdcB+\xd3\x8dI\x12-\xafH\xcc\x82\xcc\xbe\xe5\x9c%\x87\xd2=\xfd\x05\x8f\xbc\x144\x04a\xe1\xfc\x97\xfbU\xe5\x04D\xa5\x1e\x94\x1fcp3\xb4\xd6\xbf\xb5#\xa7\xe8\xd2\x88\xf1\xe8\x1b\n\xa4Et\\\xf2%]\xad\xfc\x1c\xfe\x82\x16\xcb\xb8W\xf2%I-\xdc\xb4\x11\xf3\xc5s\\x\xa9\x8dhO\xfb\xc0\xd2\xf2a\x94\xe4\xc2\xfbp\x9e\x93\x13v\x86\x8f\xc6\xbd)\xeaQ\xaap\xd1\xe7\x11\xcb}c\xd6\x08iF&D\x8b\xd8\xb6\x9e\x07\xb1\x9f-\xbd\x18\x82\xf0*\xe2\xaa\x1c\x17\xac\xe7/?{\xfe\x83O\x9e}v\xfe\xf2\xd5O\xbd~\xfe\xec\xcd\xcb\xd7\xafLVwZ\xeb\xa5\xad\x89_\xfe\xbe\x08i]3\x8d\x0f\xd4\x13\xbe\x1a/\x99=2p\xe1\x99\xbc.\x89X\x17n\xc1\xa7bH\x99|\xbap\xe5\xe4y\x07\xe9\xfe\xa8\xd5\xb6\xe1\xe1Y\xbf\xaa\x86\xa1\xb2{\x02\xb5h#\xae\x12\xe4\xa8[\xe0\x90\xc1\xa5\x10\x8dm\xba\xa0\xc9\xa7\n\xbe\x14\n3\x18V\x90\xccqMh\x9ew\xfa\x81\x17\x89\xf9\x03\xa0\xbf\xb0f\x99\xf2\xfb\xe3\xb8VD\xcdu.\xa7\xfa\x7fXR \xdf\xefD\x8e\xc7\xf5\xc4\xb8\x0b\x8d\xd3\x14\xd4.kP\xa6\x06\xba\xcc]\xb8M\xefK\x0dj:\xf7\xc0\xcb7\x0e\xe8\x1e\x0b\xb5\x8b\x17\x88u\xa3\xe2\x97\xe2\xae\x9bi-\xffQ\x1c\\\x06\xa1\xb7\xd4Z\xfb\x85\xb0>\x84/\xd4\x87\\\xd2\x7f\x85\x91\x83\x90\xdb\x8b\x9fj\xd9K\x92nr\x0d\x94\x0f\xf2m.\xe7\xbd\xb5S\x07\xb9\xdc)\xdc\xb0@\x0f\x1c)R\xba\x18*\xd5S[^x\xc9\x16-\x1b\xd6Q\xe3\xda\xa3i\x8a\xf1\xdbMZ3\x900`\xfd\xd5\xf7\x00\xe7\x04\xfd{W\xccM\nF\xf0\x12EU\xee\xbe\xc0~\xbc\x96\xd1\x82=\xb1P\x9a%\xba Q\xea PL\xd8 #\x8fP\xac\xbc\xd4\x0f\x03\xcf\x83\xe7\xf4\xc8'\x89Fn\xde1l\xc5\xdatb\xa3R2\x9f\x9aK9B\x9dC7\x7f\xae\x0ey\x81F\x0f\xccI&\x83\x9f\xe5`>K\x85\x1b\x95\xfdZD\xf1X\x94T\xfa\xfa\xb8\x15j\x7f\xe9\x18\x870S\x1f\xe4g\xe1\x0d&8e\x92-\xdf\x9ej\xb3\xd5\xed}\xa1\x8aj\xe6{,n9\x87\x8e\xba\x86l\x0b\x86\xb8\x05\xc3\xb2\x8cFP\x92 \x99\x8c\x96q)\xb3j7\xde\x92\xa7\xe7\x8an^\x1bg~\xe5*\xa1iki\xc8G\xc1T\x18\x17\xc9[\xa8\xa6=w1\n}P\xefF\x8cH\xdf8w\xbc\x1b\xc5\xd09\xcf\x1d\n~'Mk\xcaW\x8dNhA\xddB\xd6Y\xba\xa3U\xbd\xcb\xf5\xb7\xd6\xcf\xac\xbb\xf0\x121\xf7\xda\xee\x16XP\xd3q\x8e\x18\xb4\xaeT\x93pum\x7f\xa1\x0b\x8c*\xeb\xbe\x86\x10a\xd8*#\x89\x8d\xec\x0b\xcdSN\xbb\";\x13\xa7\x1d\xb5\x15\xe4D\x91\xfdN\xf7\x0cyEd_\xab}\xcer\xc8\x83\x9c\xf0\xfb\xc7\xba\xfc}\xf4\xe4\xaf?\xe1\x0ft'|\xd4Kv}o\x9df19K=\xff\xed\x9b\xd8\xf3%\xb6B\xe48\x1d\x8d\xf6\xa8\x90;#2u\xa7.\xf7\x98\x07\xe5\xfc\x1fj\x89\xa4\xa2c\xd2\x9e\x85#;\xe1\xa1\xb6<\xc6\xd4x4R\x91\xb8\x1f\xed1\x89\xc8\x14\xc9n\xe1F\xa2l\xd8\xf5\xa3\x19\x8a\xddxO\x87\"\x1a-CJ\x02\xcf=\xd6hs\xa3\x02\xe3\xc0\\I\xc1\xe2\x84ln[`\xb1l\x88\xad\x8f\x882\x8f\xa2!X\xb1\xf7\xa5U\xa5Qj\xd9\x0b\x8a\xf1\xd6\xec\x9d\xb7A\xd94\xfe\xf2f\x08\x16\xfdS\x0d-\xecb\x80\x9a\x08s\xb7]x1\xcb\xe1\x16\x7fy\x83\xb4\x81ve\xf6\xce\xc3\xf7\x1eXo\xbbgH\x8d\xaaU\xdc\xa2\x11g\xe5]o\xa0\xd41\x18\x08\x8a[8\x91\xe2o\xeb\xc2\xa0\"w\xa3\xa3n*+:Q\x1a-yhk5\x8df\x17\x9et\x1cS\xf9\x9d\x8cc\x8d\xabi\xa3\xbfN\xc8\x02\x15\xd0}\xdd\xe8{\xc1\x04\xfe\xfe d\xf0\x04\x92\x13h\xb73v\x7f\xad\xd8\xa0\xd9\xd4\xc5\x80\xb7yh\xa2jv\x82J\x1c\xb407\x8bh1\xfd\xdb0\x1c\x1e\xee3\xc3\xa1\xa4ag\xa6\xc3\xc3\x83o\xdbt\xa8_D>V9\xae\xac\x95\xdb\xd4-\x8c\xb4X^\x87\xdaE\xd5;`=\xb0>Y\xe1\x1eA\xd9d\xd1\xb4\x9d\xaa\x1d\x17\xe6f\x8c\x84\x9b\xaf\x0d;\x9em\xebzr\xa7\xbek(&oB\x1fR\x9d]A\x1b*Ks\xc7\x81\xe3\xb0\x1f=\x82`,\xec\x12\x98\xbe\xa1\xf5 f\xd6*\xfe\x1f3\xfc\xe7w\xe5J\x17nS/\x08\xf9n8\xea\xddc7\x88\xd9\x96\xc9\xfc\x96{\xa5\x8e\xd7\xc5E_1\xe7\x88\x08\x17\"\xa06r/\x91\x9d\xbb\xfal\x1eE\xd6\xc3\x18\xda\xc50\x95\xa9\xe4wa\xee\x8a\x0d\x95#b\xc9\xb6\\NDy\xdf\xceW\xee\x92\xba\"\x18\xbb\xc6\x04\xb4\xd4[E\xd7\x1b[r\x16\x9bZrf\xf5\x96\x9c+\x83%\xa7\xd2\xdc\xcd\xa6\x06\x9fK\x9dE\xb5\xac4)\xbf\xb0\xd2\x12\x0c?\n\xe7\xc1e\x86\xb6W=\xd1 \xb9mV\x1f\xf5Z\x04I\xaa#+j\x9akJ\xa2\xe2&a\x05\x84\xc0b<\xb3-\xd1\xa5\xe1RF=\xeb\xfc\x9c\x10t\x1b8\x95b\xcb!\x8c\x1e\xe5(h\xd5\xc5\xbc\xe70\x82\x99P\xc8\\U\xdeva\xe5\xb8RA^,\x1c\xa7S8\xd5\xc5[\xe7O\xe8\x1f\x16\xac\x0d=O\x11:\x821\xb3\xa5\x92i\x01\xe2\x91:\xca3V\x11\xf5B\x9f\x0c\x91\xd0o6K\xae\x1c\x0eL|J\x13\x15\x88\x88|\xcan\x0d7\xb9\x9f\xc8\x8d\xd4\x01{\x03\xaf\x91 \x97\x8df\x8fX\x8c\xadCg\xf7u\xe8\xe7\xf1|\xce\xcf7\x9c\x8a\xf9|\x88\xa2\xef\xa63\xc1i\x84^\xcd\xcd&\xa3\xa5G\x9bR,\x05\xfd\xfb-\xbb\x82X\xce8\x9dn\xf0\x9e\x8a6,\xb6(}[\x9d1\x10\x92w\xc4n\xbe\xd1\xc5\x8b\xc7\xd1\x94\x8a\xb0\x91\x03A\x11\x927\xd0\xcd+{J\xe5\xe4\x81\x88K%4\xfa\x1c\x05\xe3q\xc4]\xe40ie\xdcM\xd6x\xeb1r\xa1\xaf\xbb\xb7\x87\x96\xb4\xb8h6\xaem\x96kc\xc3:\xcf\xf8\xa6eg\n\xc4\xac\xf1~\xe2U\x1e\xd1\xa2v\xdd\x0dt\x82r\xe3\xa0\xbc\xa0\xe6\x15\xd1\xafc}\x1cx\\\xc5Pc#c\xb6!9\xd5\n\xbb\xebH\xd8\x89\x85\xc0\x13\x08\xe9r\x13\x07\xa21\xa1\x0f\xcb\x17\x1dI\xcd%8l4\xc0\xe0\x15\xec2+\xaf\xb7w\x82\x847\xa0/\xb3\xaa\xf9.\x8e\x0bC\x8e\xb6RnJ\x15\xb7\xc9\xaac\xa9\x9b\x80Mnl-\n\xe2\xb2\x08\x92\x86{F\x0d\xf7\x8a6\xb9\x89Un\xaf\"\xaf\xdc\xbf\xf5\x86\x9bVu\xad\xbb%\xdd\xd1\xfd\xfa\xb2\xd1\x8d\xaa\xbf\x14\xfc\xa4\x9fue\x16L\x98\xf7\x1d\xfd\xaf\xf7\xba@\xcch$\xb1\xab:O\xc6K\xe7vP\x85S\xc62\xb7#GGx\xe6\xb6\xec\x0b\xcd\xbc\x08o\xec\xaf\xde3]\x9c,\x1d\xd7_\xa1\x16\xaeb\xccU\x02\xad.3\xdbgq\x88\xf3C#\xadTn\x8c\x08\x9f%:\xa3\xdf\x81\xfb\n\xcc\xdc\xd5\xa9\xea\xd3_\xa3W\xd5\x88\xcd^\x9e\x9b\xb0\x12\x99\xb8h\xaf>p\x80D\xf7+i\xb05\xdeG\xd2\x0b\xe8,d\xa7\xe3\x10-\xcf\xf4o\x19%\x1c\x91\xf4\xce+\x19\xa5\xd5\xeb\xfb\xef\xdd\xedN5\xa8\xf6B}\xd7\x86iy\"~(\xce\x14\xcb\x8aC\xa5\xae\x8b ,\xc5]\xb9\xefQ\x88\xadS\xffX\xa3\x1d(%\x94\xbb\xe3\xa1.`\x9a\x8d\x94\x8a\x07\x0f\xd4\xed\x8d\xce\xd1B\xb3\xcc\x04S6\x92y\x1cUrq\xd5\x9d\xb6Y\xe8v\x14\xddq\x0d\xc7\xa8Gv\x99\x8ax\xea\xb8\xf0\xbd(Z\x12/\xb4Q\x94!E\xb8e,\xc0LA\xe8\x15\xfd\x10c\x96\xf4\xbcG\x07N7HI\xec\xa5\x91>\x90\xe3\xb1\xde}|O\xb9\xcd\xc5\xf6\xe8\xa0\xba\xa3=\xfd\xd6M\xf4\xead_\xbf\xff\xe7\xbc\xcdj\xe5\xcb*^mt\xacV\x0f\xcb\x8b\x878\x8cj\x9e\xcb\x87Q\xf5)\x1e\xe64\xf1\x17\xdf\x1bO\xf2\xe5\xa3\xfa\xb6\x9b\xa8\x10K\x8d\x1e\x94\x8d\xa6\xa4\x17\xb5\xa6$\x0c\xb2T(\xe6\x13\xa6\x98\xf7\xed3\xa4A\x9e}\xc6\x83#\x02\x8f\x16\x8eh\x8e\x0bG!\x11\x0b\xf6\xec\xe4q\xf2\xca\x95\x1bb1\xe0 \xe8\xcc$\xee\xa1S!\xde\xa0\xe1\xbb\x93y{\xda\x97P\xc4\xe9\xa7$\x85a\x11\xbf\xb9\xcdo\xeb\xd1\xf3\xb9}S\x928\xfa\x0e&+\x1bA\x8a\x17\xd1o\x0c\xd2\x10;\xd5\xd1V\x1b\xa4\xf0r\xed\xa5N\x95B\x8c\\R\xb1&t\xe0\x86\xf9\xf2\xa5Z\x07J\xf1\xe1#5$\x0cU\xa0*\xe4\x06\xb3\x05~\xc7\\\x08\xe7|\xa9\x98\x91A\xb5M\xd8\xef\xb0\xbb\xf1\xd48\x178\x0f\xe7\xe8\xe5\xfa\x8e_Ge~4\x94`\x8a\xf9\xa1\x07\xe4\x0b\x18\xc19\x06\x16\xb3\x8b\xc9i]tgQHN\x1c\xb4\xbf\x9f\xc1\xa9\x10\xe2\x983\xf0\x05\xd3\x98p7\xf6\xfc\x17\xe5\xdf\xf6\"\xd7\xa6\\\xbb0\xb3opg,\xf0\xae\x15\x9f\xe6\xebj\xa3\xed\xb6!a\x16]9Mv\xa0\xc2\xdbs^\x83\x0d8\x03\xf2\xda\xebF\x8f\xe3uQoW\xc1\x89k\x8e\x10\xbfz7\xa4\x82]#\x05\xbb*\xc7\x92\x1c\xa9\xb6\xc0\xa2\xd8vx0\xdb:\x9bt\xd5\xd8\x0c| f\x8c\x07\xd8\xb3\xa2\xfbn\x8d\xccW\x89\xb0\x1b3\n8\x1b\xa7,\xcb\x1f\xcb\x9e<=q\xa0\xdd\x8e\xb5\xd4\x0b\x8b\x8e\x80\x17\x9d\x8a\x9c\xab\xf6\x9a\xa9]\xac\xef~\x17\x03\xab\xb9\xe0u/\x13.:\xd5\x1fI\x0bo V\x13\xd3\xb5\x10\x17<&.\xe2\x93~\xf5\xb4Zry\x97\x83\xd8F\xb52/J\xa4J\xc4\x08}y\xfa\xf9\xf9\x8c\xb00\x94A\x14\x9e\x9f\x0f\xc1\xc3\xd0\xa2D\xe7\xccw\x1ez+R\x94\xb9\xb2\xab\x0e\xd0\xef\xcb\xea\x91\xb9\x1dT\x9b\x9cG1}\xbd\x1e\xcb\xf8\xa0\x17\xcc\x0e\x86\x7f\x86\xec\xcf\x08\x02;'\xe8\x8aR\xa4\xf4\xfb-\xb9\xf9x\x93\xc6\x0c\x8e\xe3\xb8\xf9\x08\x04!$(\xd3.\xcc:\xfc\xc5\x98L\x99\xa7s\xce\xc1Hm\xd7\x16^\xf2\x92c\x89\x98\xcb\x98YA\xa4'\xcc\x9f\xcf\x92 J\xaa\xf4 y\x8e\xaa\xaa\xb3\xb5H\xf6R\xa9N-\xc0kU\x1f\xa8\x95s6V\xad\x92\x83EE\xfc\xa7\xf2\xfa\x8a\x92\xc3\xca\xbb\x08\xe3/\xe2w\xe5-\x9e\x13\xa9\xf2\x9e\xc8\x9a\xc4\xde\xe4\xbf\x94w\x13\xe2\xc5J\x93\x0c\xc8\xdfd?\xd4\x17\xd7\xc4\x0fHR}\x93A\xc5\xab\xec\x97\xe6\xdde\x90*o.\x834\x7fo\x19\xa4\xca[\x92\x08PyWz\xc2k\x90 \x9azrAA\xa9'\x7f\x92\xd7\x93C\x94z\xb20\xf1\xa35E\x83\xea,HOx=\x12\xa4\xe4E\x82$F\xa2J\xd5\x9d/\x119\xdaFU{.\xba'\xda\xaf\xb5 \xcb\xba_A\x95*;\xae\xd2\xb1\xc0\xdc1\xb9\xe5MZ\x15\xe4\xdb\xc6\xec\xedL\xef\xd1\xad\x90Qh\x83\xe5(\x0e\xa1\xa5\xdfx\xa4x=\xdf\xb4\xd5\xa4\x92M\x0b\xd4Q.\xcb\xa3\x0cddr\x9b\xa6U\\>\xe1\xed\xe8\xb5\xa3\\\xee\xae\xe4\x86\xc7\xe0\x189\xc6\xd9r\xa7\xf4\xbd\xca\x11\x11{\xe5[\xae\x98S\x8b\xbd\x105\xbf\x10\x94\xe2\xf0\x97\x04f}\x15\xe5\x99\xd0UQH\xe5\xf7\x89\xa5%\xe9g\x8f{[G1b!\xcfP\xdf\xa0\x93\x1cR\x8c\xea\x9f\xcb\x0d\xfac\x90\xd8\x1c\xc52\xdc}4\x9b\xf5:?\n\xb1\xab>Z4\xb9\xbd\xa5\xcf\xe54\x05\xac\xecY^\x16#\x98V\xb3\x18\x9e\xf2\x8b{\xb4\x1d~'\x8ecj\x87\x87\xfe\xb0\xa3b\xd1=\\\xf4\x80\xa2=\xf3\x93\xc5X&\xe3\x1e\xf7q\xc7\x07\xf4E\x17\xbcq\x9f\x03\xbf\xc5\xae\xe7}\xefO\xc7\x11\xe2xvr\xaf~;\xae\xa8\x8c-\xe0\x1d\xf0\x97k8\xb5\x99\x16\xd5\xa1n\x17\x1b\x83\x07\x8f\xa9\xc1\xe4\xac\x1e\x93=\xee^^\x8f\xebyn>c)\x1f\xd9\xc1\x06{\x81\x0b[\x19\xc5.\xf3f\xa0\xaf`\x1a\xc0q\xb2 =\x8d$,\xdd\x9c\x9eJ\xd2\x7f\x86\xe8\xe0\x8d#\x89\x9e\xd6\x93R\x9f!J\xc6\xe24\xb1\xbe\xf6\xa7\xe3\x00\x91.\xba\x03a}\x90\x9e\xe5\x17q\xf3\xce\xd0\xf7\x85\xdf~\xe0\"B\xd3g%\xd0 \xb4\xb0\x18\xb7\x7f?z\x04\xbe n\x0e2\\\xbf\xbb\x8e\xd6\xb6\xe3\xb2E\xe1\xbf\x9c\x0dj\xdeb\xbbH\xd7\x016\xd9'\x9b\x86_\xe1r\x8a,\x97\xa8\xd5\x7fG\xff\xeb\x1eRY\xc5\xf0\x7f\xcco'\xb2\x90\xb4]\x0ci\xc7\x83:\xdf\xe7B\xe2VB\x9c\xdc\xf66G9\xb4w\xa7\xf6W\xef\x91P\xa6\xf6+\xef\x15\xbb\x83\x98\x16I\x1e\xe0\xe1fk\x03\xa9\xbf5z\x18=XYt\xbe\xe3\xb4n)\x1bW\x89\xe4C\x88\xc5\x12\xb9 .:\xc2\x19\xbc\xe0\xca\xc2[PHi\xe18\xd8h\xd7\x95\x85\xac\xa6\xe0\xa1,_6K\xac\xe3B\xc8~\xb5\xdb\xa9\xf3\xed\xf0BIc\x85\xf9\xa3\x90\xf1\xb7p\xa0\xec\x0c_&Va\xe9\xb7\x86*<\x0c\xd1\xd1\xc8+\xdf\x02\xbdy\xc8S\xa0^\xc9\xa0G\xf5\xd0(\x8a\x9a\xe48\xcd|hJF\xf7\n\xc7\x15\xcd\xe09\x82\xb8\x10\xa1\x7f\x01ECM\xd8\xe4\x0dh\xe1F\x18\xce\x8e\xb9L\xcag\x83\xa5d\xc9G5\x00\xe1\xc7\xbb;\xe3<;C\xf9x\x86j\x16M\x136#\x9e\xcb\xf3~\xf3S\x1aC\xfel\x0b\xe4\xe7\xbdi\xd5\xf6\xa6\xe1\xc8@\xe4\xe6=U\x90\xf54\"\xb2W\x16\x91\x93\xb2\x88\x9c\xe4\"\xb2W\xfc\xd2\x88\xc8j\xcd\xc6\x9er\x89\x98\xae\xd4\x86\xd3s\x0f\x96e&\xe4p\xc7\xed\xe5\xcaD\\\xed\xeaw\xf4\xbf\x1e\x86\x07j\xef;\x85v\xff\xb8\n\x8f8\xfcH\x7f\xbfM $..\xcfT\xef\xe0$\xa6\x8bo\xe5b\xdb\x05\x0870mL\x15\xc1\x93\x184\\x\xe7J\xd3\xa5\x0bk\x17\xfd+\xe7\xdcAQ\xa5/u\x0f\xaf\xd0\xba!\xc2\xce\xa9\xcfo\xf0\xb9\x08\xc1X\xc6\xe8\xe2=\xf4\x08\xaf\x97\xe5\x84\xa4QD\x17\xd6\xe2V\x8c\x91\xa1DJ\x07\xbcVj\xd4\xd4\xebC\xad\x80\x88\xd7\x1737\xbb$\x17\x9f{.t\xfa\x945\\\xf1\xcb'\xcb<&\xc2\x9a6\xab\xda\x9c6rX\x8eli\x02\xe1\xaa\xc6o\xf9}e\xfa\xa2P\x04\xe9m\x9e\xbb\xda\xdb\xed\xda\xfb\x93\x90\xbb\xbbI\x11\n\xb4s&;\xee\x8d`\xbc\xc0\x88\x15\xa1p\xe2c\xd4=t\x98\x0d\x0e\xa7V#\xbd\x89O\xcc\x18\x12\xdd\x95KF'\xd6LZ^b\x96|\xe1\x92\xdf\xe0D#>(\x7f\x98\xe9\xa8.R\xec\x8c'4@~=c\xc17\x8a\x80\xc8\xb8\xb7X4\xd8\x88\xf1+\x1e\xcb8\xc6T\nQ\x98\x92\xeb\x14\xf30\xc5\x97\x89\x93\xfbo\xc6,yD\xc00%*P\x88\xae\x89)Et#id\x99\xbe\xf9\xdej\x8a\xc2q\xc5\xeeEr\x9fp\xe3\xa6\x08\xe9\xd0\xd3rV-\x1e\xfeCT\x0f\xa9\x19a\x84\xfc\xccD\x8a\xb4\x1b\xcc\xcc\x9a?\x1e \x13jS\xf9\xd3\x82\x9c\xdd\xd1\xdaXO\x16\xe3\xa4\x08\xda\xcb~\x04\x85MF\xe9>\xbf3\x86X\xa1\xf4\x8a\xffX\xe2\x8f\x9cq\xc5\xdb\xf5e\x81\x0eZZ\x94\xc6\x1b 6-\xc0\x88\x8e\xc3\xa9\x0es*^8\x90u\xe9\xcf\x0dD\xa1\xc4\x9esa\x85\x8b\x14Z \xa5qJ\x12{\xad\xe3\x0fj\xefs\x1a\xc2\xa8\xa2\xe8\xaf\xf9x\xa6\xbd`\x9b\xe1M\xfb\x0d6\xc5g$\x8d\x03rE\n\x8a3\x8b\x08#D\xc1j\xbd$T(\x12h(\x90\xf8\xb1\x96*\x89\x0fk\xda\x9e\xbb\xa0\x1bqe|9\xb5\xff\xafq\x9c\xe5\xcdj\x1aoM\xdf\xf8\xfb\x0f\xd6\xbd\xbc?\xdb\xf5P\xac\x08\xe6n\xe0oh\xd1\xb1\x04)\x04\xaf\xaa\x8a\x81\x85\xca3q\x1a\x93\x8a\x01\xf9`\xbb\xad\x0f\xeaW\xe3\xe7D\x19\xc0R\xfb\x12\x88\x03\xfe\xa64I\x7f\x8e\xc7\xc1\xe8\xe9\x8e\xbeM\xcf\x8e\x1c\x93\x8c\x1f\xe1\\cVF\x9ct\x84x\xb3\x03I\x1elH\xf2\x7f\xd5\xefa\xe9\"\x1asj*\xee\x84y\xccO\xb1\xd5\xe9x\xe2\xe4R:\xac\xb4z\x98\x9fP{]L\xc3\xbf.I\xfa\x19G\xd0\x1f\xd38z\xc5 <\x16LV\xb3\xfd\xef\xa7\xd4\x92\xd2\x0f\xe96X\xe8B%DsXD\xecm\xf1\x88\xbd\x04\x86\"\xa5b#s@\xaf\xb2\xee\xf3\xb33\xba\x1c\xf8\xa5K\x12\xdf[\x17\xfaT\x19\xa8N\x95`,\xcd,H\xc4dP2z\x19\xbc\xd8\xfef\xd1\xec\xdf\x84\x98\xfcl\x16\xc4$\x01\xaf\x08}g\xf4X*\xc5\xbb\x96\x82L\xf1\x10La\x9ea\x81\x12\xcfN\x9f\x1d\x83)ya\xa2t)[\xc2 \xb4\xdb\x01<\x81\xf8\xc4\xc1\x19\xe6\xf9{\xe4B\x01\xde{\x8c\xa0Mg\xff\xe9\x08\xfa(\x05S\x01d\xb7\x8ftgp\x08\"\x03!N@\xc0\n<\x1d\xc1\xdeQ^v\xff\x10\xcb\xd6=\x7f\xf4\x08\xf6\xf6i\x81\x8c\x12\xc6\xc9\x04\x83F\x15\x96\x89\xfe\x01Zr\x80\x12K\x1b\xfb\x1a\xb0*[\xfdJ\xd8\x01\x82uup\xc4\x1f\x88\x0e\x1e\x17_\xf5=D\xe8\xc1~\x0e=\xee\xe5\xd0\xe3\xc3\x1c\xda\x1f\x0c\xf02(\xce\x13\xce\x11\xa5\xe0\xac\xcbe \xce\x9b\xf5\xff\xfe\xc5\x9fY\xb5\xfbPuz\xd78Q\xc8\x18\x8b\x1a\x18\xf6\x0dO\xdan \x91Y\x8a\xcfJt\xe5r\xec\xeeX\xd6\x1b\xbew\xf2\xdb:\xa1\xdd\xef\xdf'\xb0\xa76p=\xad\xd8:?'\xc9\xa7\xd1,[\x12\xabJ\xb5y\x9a 9\x8d\x82\xc3T=\x98K\xaf\xceQ\xc5x}9I\xbd\x94|\x7f\x99]\x06a24l\xdadM|\xd33\xfa\xf1\xb0\xcdd\x08\x99Y\xc8O\xc8\x92\xf8i\x14'C0\x04c\xd2\xbf\xcbR/\x19\xbb\x068\xb6Y\xe6\x13Zs\"\xa6\xc2\xdc\x8f\xbc\xaf\xd1F}\xf5\xf4}U\xf1\xf0;\xfa_\xefU\xf9mn\x87\xf6~\xffX\x89\x90\xcd\xed\x0c:\xbb\x84o\xd3'{J\xa0e\xfeh\x7f\xaf_}\xe4\xe5\x8f\x06J\x90i\xd1\x87\xbd]\xc79\xf9N\xfeL\xe0\x0e\xf8z\xc5O\xca\x98C\x81\x9f\x05s8\xa9\xa0)\xe3\x06_U6\xa7|+G\xa3\x10\x93b\xe6\x05!=\xb65\x1c\xac\x0bC\x1d\xa7eEF$\x93\x19\xbc\xd8(i\xd9\x8fC\x9d\x84\xb9\xd1\xbdB\x99\x07\x1e\xb4X'a\xb1\x1c\x97\xd5 \x93\xdfQ\xbf\xd1q/\x95[B\x97$\xfd$\xf2\xbd\xe5s\xdc\x04\x9b\xc5\xfa\xb3{\x18\x8c\xd8\x8b\x13\xf2\xd3\xde\x8a\xbf\xea\xd8\xb1\x18\xfcv^\x0erC2]|\xdc\xe9t&a\x16/\x87`-\xd2t\x9d\x0cwv\xd6$M\xd2(&\xdd\xe4\x9dwyI\xe2n\x10\xed\\\x0dv\xc4\xaf/\x92(\xb4&\xe1,Z\x9d\x07\xb3!X\x7f\x85?\xe8d\x815 \xd11\xddK\xa3\xf8\x07\xa5:\xa3p\x19\x84\xe5\x1aEAk\x12F^\x96.\x06\x9f\x91Y\x10\x13?-\xde\x1c\xee\xec,\xe9\xbc-\xa2$\x1d\xee\x0ez\xbd\x1dV\xb2\x13\xf3\xa2\xddE\xbaZZ\x93\xf0\xb1v\xd0\x1bQp\xc9\xb5c\xd07hR\xe3\x87\xa9^\x7f\xdc\xdb\xdf\xebi\xb7od\xc4\xdcZ\xf4Q\xbcH\x85\xb5\x120\xfe\xa6\x88\x15=#\xeb\x98\xf8^Jf\xe0\x853\xc9\x91&K\xc8\xac\xdb\xe0C\x03\xf2\xfct\xa9\x98\x87#\xe9\xc9IK\xbbg\xfe\x82\xac\x98uu\xf7\xa8\xf4\xe4\xe3g/?9{\xf6\xf1\x8b\xf3\xb3\xe7\x7f\xed\xc5\xa7\xcf\xb8\xc1vP*\xf3\x93g\xaf_\xc9\xcf\x07\xbd\xdd\xd2\xf3\xe7\xaf?{Q~^~\xff\xa3\x17\x1f?\xfb\xc1'o\xce\xab\xed\xec\xefj\x8b}\xfc\x83O>\x91\x8b\x1d\x95\x8b-#o\x86\xa1\x02\xe8\x97\xea\x83g\xf4P\xc1\x9f=c\x17\xce\xc4\xe3\xc4\x9b\x93O\xc4\xbb\xe2\x87\xae\x80\xa8C\xfa-\x17\x9be\xab5\xc6\x0c\xa4_\xaa\xef\x7f$\x1e\x8a\x1fr\x81\x9f~\xf6\xe9'/\xae}\x82!\xe89\x1e\x96\x86\xf6\xe9\xcbW/?}\xf6I\xddZl8\x87\xe6\xe9K|/D\xd5\x81E\xbfY\xa5gH\xe1\xd8C\xfcZ~\xeaG+\xee{\x12\xd9\x16\xffQ.\xe1\xcdf\xcf\xa5\xf0\xe1X\xb0\x0c\xb3\xee!\xdfI\xfe}\xd5\xab\xfcA>\x9b%0\xbfD\xa5h\xa0\xb3|\xeaJ`/\x9f\xaf\x128iVH\x97_\xf0U\x85\xf2\x1cF0(\x83(\x92\xed\x96A\x14u\xf6\xca\xa0\x85Z\xd7L\xad\xebJ\xad\xeb\x86\xb9\xc2]\xf7z\x9d\xc9u\xefhr\xdd\xfb\xde\xe4\xba\xf7|r\xdd{\xd1\x99\\\xf7?\x9e\\\x1f~\xdc\x99\\\x1f\xedM\xae\x8f\x0e:\x93\xeb\xe3\x8f'\xd9\xc7\x1f\x7f\xfc\x02\xff\xffxz;\x9ed\x1f\x1d\xd1\x97\xb3\x8f\xbe\xf7\xf1\xc7S\xfb\xb4E!\xcf\x19\x84\x96pn\xed\xd3\xe1\xf8\xf3r\xb1\xdb\xcf\x9dJ\xb1\x9dr\xb7.y\xb7\x8e\xf6\xcb\x1ez\xe5R+,\xe5N\xc6\x93\xe9\xe4\xab\xc9\xfb\xea\xe3s\xfa\xf8s\xfbt\xd8\xbam\xb5n[c\xaf\xf3\xe5\xa43m\xb7\x9c\x0fv\x82r\xc9\x8b\xa2\xe4\xf8\xf3\xa2>\xc7>\x1d\xfe\xc4\xb8\xd79\xf6:\xf3\xe9W\x83\xf7\xb7\xec\xfb\x97\x93\xce_9\x99\xecLN\x87\xdf}4\x9a\xb4'\x1f\xb8\xe7\x93n\xeb\x7f\x98|\xf8xbO\x1c\xfa\xf6\xd4\xf9\xf0\x83\x9d@\xc7\"\xde\x19YD\x9f_B\xc33\xe3.\xfb.\x11q\xb5\xaakcU\xc7EM\xbb\x83\x0dj:\xdb\xa6&\xec\xdf\xb6}}alao\xaf\xa8\xea\xb8/}\xdf\x95\x9a\x18\x94~\xeco\xd0\xe03\x83yG+\x9e\xee\x1d\xa1\xb9\x02\xa5K~\xd2>\xc5 9{G0\xa4\xc7\xea'\\\xef\xb0;\x80[`\xc9\x9c\xd91\xbb7@}O\x87\x16j\xd3i\x19B\xa7_\xdb\xb1\xd7\xe6\x998\xca\x15]\xd6\xa4g\xb1\x96s\xc8\x7f\x87\x00\xb9\xc8\x05\x85\xf4\xfb\x07\x12(\xc5BU@?_.\n\n\x19H\xae\xe9\nA\xbd\x81\x04\x9a\xb3R{\x12(f\xa5\xfa\x05\xe8\xbf\xa7\x90]\xe95\xd4}\xec\x16/=\xb6\x1e\xc3\x10\xf6\xa4a\xec`\x0f\xe5\x96&\x14r(u\xe7\xff\xf9y,\xb3/A~\x13\xcb\xc8#E\xaa@\xa1G\xbd\n\xf4\x98)\xabk\x17\xe1\x8b\x9a#\xc6\x93\x11\x1c\xec\xef\xef\xee\xc3)W\\a\x96\xe9\xe7\\\xdfd\xa7\x85\x03j\xf9\x01K\xe9\xd9\xa6\xa7\xb5\x0e\xd6p\x00O\x9fB\x9fJX\xfb\x07\xbb\x83^\xf9\xd1#:\xdf\xbb\x8a\x11\x15\xe4\xd3\xd8[\x90\x13\xd3\x0e\xf6\x0f\x1c\x17^j`\x9f\xb2\x84r\x9f\xc2\x13\x18\xec\x1f\x9c\xc0\xa7\xed\xb6\x03o\xc7\x9f\xd23\xd9k\xfbS\x87\xc7\x19\xe8\xb9\xf0\xb2\x00\xea\x88\xd3\x1b\xad\x1e_hb\xc9;\x08P\x01C\xdeQI\xb7;\x0f\x96$\xf4V\x84\xb2\xf6 \\g)\xde\xdb\x8f\x92 \xc5;\x96i\x97\x9e\x1fd\x18t8\xf0,\xf5\xe2\xb2\x9b\xbc\xda\x97\xe7\xda\xbe0Q\x99\xf7\xb3\xf6\xfd\xef\xeb\xdf\xefF\xe1\x0f\xbd8\x0c\xc2Kv\x96\xcc\x7f\xf2\xeb\xea\xe8y\xca\xeb\xd7-\x0e]\x97\xcf\x94\xd3\"\x15\xd9\x86\x8d\x16\x1a\xf1\xbe1d\x0b?\xa2\x8f \xed^\x918\xa1\xc3x\xf4\x88\xcd\x845\xcb\xd6\xcb\xc0\xf7R~3\xf5'h\x93\xc0\x8eT\x98Q\xca\xe5\x91\x0fC)`\x15{\xb3\\\x12<\x9f\x8a\x96 \x90k\xcfO\xf1b*\xc9U\xba\xb4\x9a\\\xe3n\xc7\x8c+R\xa67m;\x93\xae\xf8\xf6\xc1N\x97\\\x13\xdf\x0e\xc7=\x1e\x03\x8d5\x14,\x97\x9dy\x14\xafdw\xffh\x0e\xe9\x82\x80\xda[*\x8b\xa1\xf4\xf82L\xedx\xdc\x9f\xbal\xafDe\xf8@\xc0\xa5\xb8\x8e\xac\xb5,d#\xc1lhX\xbf\x983\xde\xe6,\xf2\xf3A\x15\x13:\x82\x90E-\xef\xfa\x0b\xe2\xbf\xfd$\x08\xc9\xf7b\xe2\xbd\xa5\xe2[Dw\x90h\n\xef\xdc\x0e\x8a\xaf\xdf\xe7\xad&\xd9\x9a\x8a\xb1d\xd6\xd0hiu+*\xb67\xcf\xfe\xeav\xe8\xa2\xe2\xca\xc0\xb0\xdao\x9e\xfd\xd5\x9a\xc5N\xdfE\x85\xfe\xdf\x12\ny\x16\xd1\x0e\xbf\xd1u8\xef\xa6$I\xed\x18\x03@(K\x9bz\x97\xb0\xf0\xc2\xd9\x92\x80=\x0f\xe2$\xcd+t\xc4$\x94\xfa@[\xc9C*\xa4\xde\xe5\xa7\xde\xda\x85\xb8@\x9b\xc7\xe9\x82\xc4\x84\x1ep=X\xc7\xe4*\x88\xb2dy\x033\xe2/\xbd\x98\xcc \xc9\xe6\xf3\xe0\x1a\xa9\xa2\xf5\x18\xda\x10C\x1b\x1e[R7\x1e;.\\\xb0.\x07\xe6.\xafcB\xab\xb1\x13\xe2G\xe1l\x83>\x8b\xce2\xbf\x87r\xe0\xfc\x92\x96Q\xa5=\xaf\xc4\x92\xe2@U)\xa4\xc8\xdf\xaa\xaa\xe9\x08<\xd1\xa3\x02\xbac\xb0\xd8;\x94\xd8\xf2+\x1e\x888\xb4\x19\xa5<\x08V\x120sz$E\xf5f\xf9\x08\"\xfa\xa7=\x82\xbe\xc3e\x06t\x0e\xf0\xaa\xb6\x15&\xfb=\x19AF\xd7,C\xb9\xa7\xdf\xdf\xeb\xf7\xfb\xc5d\x93\xeb5\xbb\x83\xcf\xa2\x1c\xfc\xe4\xd9\xebW@\xab\xf1\xfc\x94(\xb90A\xdc4\xbca\xab\xe6I4\x84.E\x92\xc6\xc4[\xa1\xc3\x81\x17\x84 \x84Q\xd8Y\xc7A\xc8\xb6z^m\xa2\xab7\xed\xc6$\xc9\x96\x98/\xd53\xad\x99f\xc9>)\x96Lqo\xb9\xe2 \x04\xd0-\xac\xe2,\x833\x1cw\x83\x84\xa7\xdb\x0f%\x0c\xe4\x1a\x9a\x15\x89/ \xac\xbc\xf5:\x08/\x93\x13\xc4\xb6u\x1c]\x053\x8a\xddQ\x16\xfb\x84\xe7o\xa6\x9b@&k\x96\x93\x87\xd8\xa4\x87E[\xf2*xKn\x12;t\x9c|A=x\x02>\xfd\xc3\x164\xc3\x80\x8f\xde\xd4\x95\xe2\x9ce\xd87\x9b\xb0\x90\x94!\xfa\xdb\x04\xecG\xabW\xcfM?\x920Z\xce?\xac\x9b*\xdf\x85\xb9\x8a\xd7Aa\x08\x0cd.\xc3S\xf2\x08#\x91\x95z\x97\xc3\x1bo\xb5\xecF\xf1\xa5;\xe8\xf5\x06C\x9c?\xe6q\xabAsZ7\xbb\xeb\x18$L(2E>\xc0\xa5\xe2\xae0\xf4\xa0\x1d\xe5s\xe7\xc3\x13\x98\xd3?l\xee\x04.Dc\x1fS\x90\x1b\xb07/\xa6\x96\xc1\xe7)\xea]\xe9\x94'y\x8cb\x9e\xde\xa9X\x13\x06\xb0\x99\\\x04t\x8f\xdd\xde\xeaD\xa7\x11x\xecI!`\x95\xe5\x022\x13(\x06o\xc9\x0d&\xe0#\xe3`\xcaB$\xe5\x97~\x83\xe6D>\xea\xe2\x7f\xb9\xd1Y\x8a\x1f2p)\x05\x8d\x92(I\xd1s\x87\xdd\xe8\x12?\xdbmz\xac\xd8\xe5\xc8p\n\xb6\xfc\xc8\xcd\x8f\x9a\xb552Y\xaex\x8d\xca\xe8lz<\xc0\x89\xbd\xa0,\x9en/A\xa8\x18\x85\xc7gmt3\x92$S\x1c\x80\xa8\xacvf>6\xf1\xee\\\x86\x97s\x0e\xd5\x0e\xe1\x84;\x10\x04\xda\xb8\xac\xdc+\xeb\xda\x0e\x1c\x1e}TS[\xbb-\xd7\xa7\xdd)\xb8\xdbv\xd9\xd1\xca\xe0!7\x8bj\x0c~\x9b\xb4\xac}\xf9=\xbc[\x04Td\xe8\xf7\nA\xae\xbf[|\xe7`C\xbf[\xef\x90\x15\xe12\xaa%pv\xbeD\x07\x83\xe6\x89v!\xa6x\xc5\xd6\xfbe8\xa3R*\x9e\x9f\xf8A\x96.\x80\xfc\x90\x16\xdez\xd8\xefu\xbb\x8c\x87\xb0\x0d\x8b\xe1\xc6\x0cq\xa5\x9e\xcd\x0c\x99\x06\x8f{\xc16\x08\xe3\xbe?\xc5\x89\xfb\xd2\x85V\x1f\xbd\xe3\\\xd1\x94@\x0e\xa7\xdc\xbfM\x1aw\x0bf\x8f\xb4 g\xf7|HO\xb9\x83\x10\x9f`\x87\xf3\xb1\x0bo&\x13\x01zj\xf1 !?\x9b\x91\xd0'@\xc24\xbe1\x8a\xd9\xcc\xc7\xacDd\x88\x96\x96\n\x12\xd0\xf28\x8e\xd0\x83\x13Kd$p\x07\xc5\x89\xb4\xfb6\x08g0\x02K\xf4\xc0r\x8b\xcd\x841\xc6\x9a\x04\xca\x9f6\xd3\xa8\\\xc4D\x8c\xd6\xef\x80*\xa6\xd3!\xee\xee\x16\x11\xc2\x1b\x04\x90\xdc\x7fBW\x8f\xb4a\xe8\xf8M\x1a\x18\x8f\x1f+\x99i\x87R\xe5\x03.\x01m\xc2-0\x12m\xc41~\xb3\x17\x86\xb0\xcb\xa4\xa4@D\xb1\xc58\\t\x19Z-k\xf3Z\xd8\x1b\x16\x0b6 \x0b\x94\x91N\xf20\x8a\x03\x9b4\xa7\xbc\x98\x8b\x01\x92\x14p00\xb2~\x89r<\xc9\xb3\xf8\xd1\xd1\xc7\xba\x83pi\x97m\xd2\xbdBL\xcc\xc2\xfc\x04K\xc2\x99\xd0 \xf0\x83\xe8\xbb ]\x04!xpE\xe2\x0b/\x0dVt\xe5\xab\n\x1eS\xa8#.\xb9I\xe3m\x9d1)._M\x96D\xe0T\x9c\x80\xbdK\xa1\xf3\xe0\x07H~\x10\x06r\xed/\xbd\x15C\xc0\x95\x17\xbfM\xac<\x0eqe.X\x16\x85\n\xdd\xcd\x15;\xf2\x195\xf4*:\x9dJ\x9bI\xe6/JGn\xe6\xa5I1\xaf\x8c>\x8c\xb4o6\xef\xeaB7\xaf\xe7*WJ\x15\xba\x02\xe3L\xcd\x97\xd1;J.\xe9v\x8d\xe2R\xff\xcb\xab\xa6#\x7f\xc8\xc8Z\x17\xfa\xf60\x99u\xfd\x1c\x0d\xd1m#F]\xe6)\x08\"\x1a\xc3PU\x83\x85\x8eT\"W8\x85STs\x0d\xe9.\xe5\\\xa2(Ea\xe2\xa9\xee\xb1z~\x16\xe5\x99\xb6-\x0bs\xcd\x9a\xb4\xea\xa8Y\x0bQ\xb3\xf6\x18=\xc1k\x89\xf7\x0f\xcd\xc4[C\x96\x8f\x18Y\x0e\xefA\x96\xcd\x82\x8c\x9e4\x87\xc0K\xc8\xe4\xd9\xd0\x81\x12fV\xb1Zl\xdc\x90o\\v\xd4l\xbd\xb0C\x07\x93\xc76\xd7\xa8\xe5\xb0\xd2\xb6\xc9u \xc5~,\x0f!\x8cf\x04VYR\xe0\x9b\x97\xc2\x92xI\x8a\xaa{I\xcbVb\xd3\xf5\xbb\xa9a\x81\x7fJ\xd2\x86i\xf8\xc2U~I\xf2\xc6\x85K\x17V.\x9c\xbbp\xe1\xc2kf\x8c\xd20\xed7\x06f\xfe}\x033\x97\x16{\x19$) I~Vb\xbfl+Zc\xd4\xd9T\xe8j\xa1\x88\x1e\x9d\xcf\x82\x00pyE\xfc\xcc%\x15\x06@\xb5'\x8c\xd0\x19b]\xc8eLA\x85A\xeb\x1f=R\x04Q\xfbM.\xaf\x96\xc578e\x93\x00\xc3\xca!\x93\x9f:\xd0\\W}\xf8\x84+\xc2>E\x97x\x07\x0d\x1e\xf4\x85O\x0d\xde\x9a'L\x82\xba\xbd\xc5\xcdx\xe2\x94\xbbwZ\xf4\xee\x86\xc9c\xdfJ'a\x88\xd5\xeb\xd6\x8f\x07j\x80\x11\xbc\xa1\x9d\x8cr\x0b\xce\xa7\xf4\xc1\x9ao*z\xea\xbb\x80\x11\xf8\xc5\xa4\xcfs\x92F\xf0<\xd6\xa6\x9c\xecu\x99\xd5\x94\xec\x88\xf9L\xc1)\xbf:\x8eg\xaf\xd789\xdb\xd8X\xdcB\xc9\x9b\x98Og\xc0=w\xcc'4\xe0^;_\xd5\x8475=\xcb\x91T\xfb\xf4\xaa\xf6\xe9M\xed\xd3K\xc3\x06\x04\xeeG\xa3\x0b\"|\x87\xf3\xe3\x92\xab\xac7;?z\xc6$D\x18\x84\xa8\xa9\x1e.\xd6D\xd2\xa1-\xab\xc8\xb4\x07\xecP\x80\x07\x9a\xfd#\xfe\xfd\xf6\x96\xd2\xf2\xb8\xf9\n%\xd2\xc1\xd0\xc5[\xaf\xec\x08h\xd4A\xc9\xefI\x07<\xadL-\x7fX\xaa\xdf\xa6\x91:'pm{t\x9f\x1b\x8a6\xc8W\xf2\x87\xf6p\x9f\xf9[x\x0e\x9c\x99\x1a\xafH\xca\xb9\xc4\xe8Q\x11\xfe\xffc\xee[\xbb\xdb\xb6\x95E\xbf\xf7W\x8cx{\x1c2\x92\x15I~$Qlk\xa5i\xd2z7ur\x9a\xa4\xfbt\xcbj\x16-A6\x1b\x89T\xf9\x88\xed\xbd\xdd\xf3\xed\xfe\xb1\xfb\xcb\xee\xc2\x0c\x00\x82$@\xd2N\xd2\xd6k\xb5\xa1@\x10\xcf\xc1`\xde\x93\xb2d\xe3\xcf\xb5\xdbG\x97\xad\x82\xbf\xe4%\x9c\x82\xfe\xc0\xae\xb7\xd1w\x02\x12\xb6\xf1c\xa4\xc6\x149}\xb6\x8a\xe6\x1f\xa4\xd4\x9a__\xc8l\xb9\xa8kX\xf5\xf2\xa88Z\xc4\x9b\x8f\x02K\x8b\xa2\xb5@r\x02\xb8\x91\xf8\xe4\xff.\xd4\xf9\xc5/$\xc2\xaf_\x97\x86\x9c\xcc\xf2\x0f\x01c\xad\xb9g\xd1\xd5\x93\x14\xee\x9d9\x07\x96\xfa\xee\xf8\x9f\xd2\x13aD\xd8\x98\xf9\x0b~\xf1\x07kN\xcd\x04\xa9\x12\xe8o\xfc ~\x02>\xcc\xa3U\x14\xf2\x95^\x07IR \x9bW\xfe3\xbbKC\x1d\xb3\xa2\xff}\xaey\x9a\xe6X\xdcz\x12_\xf0 \xae\xb3U\x1a\xe0\xd9\xf9\xc0\xaea\xed_\x830q\xd6W\x05\xd5\x1b\xf6\xb9\x19\xdf\x88\x19\xef\x13\xcb\xe5\xf3\x0b\xf2\xd3\x80Mp\xed\xe42yN\xedi08\xc8Y\xcb \x9cG\xeb\x0d\xea_\xd8\x95ec\xf9l\x91\xceS{\xfb\x04\xa2\x18\x96\xd1j\x15]\xb2\x05\x9c]\x83\x8fj\xd0\xd4?\xcbV\xa8\xeca\xebMz\x8d\xca\x0d\"\xfcr\x9c\xa8\xbc\xa6c\xf3\xc6P(\x11\x0dEYeP\xae\xa4\x037DZ\x04T\xca\xa7\xab\x1f+A\x06hB\xb1s\xbc\xd9+k{-b\xd9\x1b\x97\xb7(Hk\xc6\x88\x9e\x81\xa8Qr3\xbfVnV\x80;\x9b\x17c\x93\xe8\xac\xf2Q\x15\xf2\xc4\xd1AH\xb3\x01\xda\xba j\xab\x9c\xae\\\xd4&\xf1d\x81~\xc5\x16\n\xfd\xfe\x81\xc4O\x0f\xce\xbc*\x01d\xa3~\xcaZ]\xccY\xb3\xd4\x93\x88u,\xf9\xc6\x17\xf5\x84\xd2\xc7FB\xe9\xda\xe0\xad\x04\x02H\x859\xa8\xbbi\x86\x05\xd2\x89=\xde\xe9 98IbM\xe9\xc9k0\x1f\xefs8\"\x82ac\xe5EUmN>\x8f\xf6D\x8f\x03\xea\xf1?M\xfeip7\xb2*\xf6(\xc3T\xd3=- \xabM-a\xa5\x8e\x1a\xf3z\xad\x96W\xe8\x0b\xab\xec+i\xd2\x08v\x17\x05\xd8\xfd\xa8\xc1.\xc7\xb7\n~al\x13\x1b\xc7\xf6\xcb\xe4\"\xa7?\x08?\xc2>9\xc5\x9f\x04\xe1\xf9\x8a\xc1\xefY\xc4\xab\x8a\xbdGZ\xa2n\x96\x86\x83t\x1b6\xc3\xdc\xe9\xe78):\x83a95\xbb\x04\x1e-\xc4t\x9f\xff\xd4`\xe2m\xf3\xa9i1\x9eZ\xc9\x88\xf0]\xf5\xd5\xa0\x8d\x18m\xe0\x95\x87d\x03|\x14c\x8dd\x9b-\xce\xa2\xa9\xab\xcbv*\x1aO\x87~\xfb9TrM\x9f\xfcE9\xd0\x7f\x98\xfa3\xafp\xc1\x1c\xa3\xef\x88>\xc9\x16-Rp\xd1\x910\x83\xe3\x1c\x8b\xcf\xcf\xd2\x08]\x89\x1f*Vf\x17\xc6\xf0hO\xfd\xe4l\xc3\xc0\x83#\xfe\xbf\x16\xba\xb2\x80\x14\xda\x11\x19m\x07\xfc\xbb'\x10lo{\xd8\xfb\xd3\xb6k\xc5\x99\x14\x0c\x1b\x87~5\x07\x07\xb0\xebA\x172\xc5R\xa9\x13x\xc1\xae\xfc\x05\x9b\x07k\x7fU\xef\xd2\xa4\xff\xe9K\xf9\x9b\x1b\x95\xe0\xc5N\xb7\xd0ZJ,\xf0!\x8c.C\x10\x11\xd3\x94\xcc\xac\xa6\xeb\xea\xc9\xa8\xc7\xa4~\x8eI\xe9\xe8\xdb0i\xb5\xe1/\x84I\x17Qv\xd6\x06\x93\x96\x06\xd3\x82\x96\xb8\x0dj5\x8f\xc2\x88Z51NGC\xb26\x0c+\x0c\\\xcdXu\x97d\x18\xcd\x8a\xef6X\xd5\xd2H+s'2\x81{#\xac\xdf:\xcf\xdd\x98\xa3\xcd6-V\x07s+\x93\xa7U\xe0'\xb7\xb2x2\x18?\xf6\x8a\xa6N\x9aH\xbd\x14\x8eE7\x84\xbc\x97\x85J\x0c\xb0\x10\xe3(\x19\xc5iw\x92.\xa6\x0fge\xddU\x95\\\xe5`rWS\x14\x94\xba.\xa5\xbc\x95\xdf\x94v\xe1\x9c]\xd1\xcd\xc1\xeb\x8d\xbbl\x06,\xbe\"\xcf\xdd%\xb9}\x12\x92F\xa6w\xe7Q\xfe\xbc;\xd2\xcaw\xf2g)\xe8\xc3\x1f\xfbz\xa5\xc7\xda\xb3Vg\xe7\xa1V_+\x7fL\xa1\x1e\x96\xb5P\x8e7\xce\xbe\xd6\xbd\x10\x9b-IF\xff\xa6\xf9\x18 \xee\xec\xe6\x86\xec\xfb8\x98\xb78X\xcd\xe4J\x80\xbe\xe4ErWX\xad\x8b\x03\xb6\xac\xa5B\x84u\xc6\xb2\x89b\xb8\xe3\x14k\x98g-\x8f\xef\xce^\xdbA\xd4\x0f\x00}eZ\xf4\xd9$\x95h\xbcj\xf29.\x9b\xa5\x8f\xbc\xcdK\xac\xd8l\x05\xe1+1\x8bT\xd3h\xc6gsU@\"\x13\xed\xe6DdP\x14\xdc\x1c\xda\xb3t\xe9\x7f\x99\xc6\xbf\xdfYZ%\xfej\xe3\xb6\xcb?\xbb\xc0\x04\x8af\xf8\xc2\xff\x83\x8c\x078~\xd2wB\xe8\xaf\x0b27Kr\x01\xf9w\x179\x8e\xb9\x14\x15`D\xcb\x10\xfe\xec\x0c%-#\xc6\xbb\x0d\xbeWw8\xbd\x1e\\ \xcc\xe7\x16k\x08C3\xcbv4\xb8<\xd8n\xc4\xf2P;\x1d\x85F\xc8%X\xa0\x99\xa2\xc5\xea\xa6*Q!R\xa4'\xad( \xfd\xbd\x16 \x94\x07\xd0\x96\xde,\xca\xd8\xc0\x998(\x9b\xaa\xa9\xab\x95\x08\xcdnn\x07\x96\xdf\xd5\xc9E\x94\xad\x16h\xabs\xe1\x7fd\xe0\x87\xd7\xd2\xf2\x1a\x95\xb0\xd2\xdf\xbb\xb5\xba[\xe9\x15s\xd1\xd9\x8fjVh\xe4)l\xe1h\xf5\x91\xb9\xda\xd4\xeb\xf1\x84\x06\x13\xef\xfbs\x19;OwM\x93\xfb\xfc\x9e4\xccw\xdc\x82\xcf{~\x05\xb2\xcf=!\xae7\x8c\xbaFh\xbf\xb9\x01g\xe9\xafVg\xfe\xfc\x833\xeb\xc9\xed\x99\x80X\xb7\xda\xeaS\xac=+\xccT\xac\xd1\xd6\x16\xbc\xa7O\xa8\x18\x1f\xcd\xa1d\x10\xa2\xf1=\xdf\xfe\xce\x01\xc6\xe0\xc4\x95\xec\xc2\xbd#H\xfds\xd4< \x98?\x13\xbe\x13\xa2uN+\xf6\xf0 `i\x9a\x97\xdeC\xff\x9b\xca.\x93\xc3{\xd3N\xdeq\xebr#4\xa1'\x13\xdd\xa31\xd9\x82!\xbfS\x9a\xa1s\x94+\xe1\xd0\xcbI\xf7\x91\"~\x94W,\x7fdI(\xd5\xc2\x8a\x7f\xbe\x8a\x12&\xcc\xf8K'\x99_\xe8\x95\x89\xdf\xdc\xc0\xeb\xafr\xf8R\x8f\xcaw\xe1\x87v\x9e\x85\x1a\xfa\xaf\x00\xa9\xc9\xc3P\x90~Z\x18!\xe1KP\x0d#\x94\xf6W\xec\xdc\x9f_\xf7\x94K\x8f\xc8l\xa6m\x18\x99=I\xb1U\x0b\x97E\xdc\xf1\"\x9f\xd1\xfcU\x0f:nIs4\x10tw\x07-z\xcc\xd20\x9ck\x06\xed\x9d\x13m|d\xc1\xdf\xadMC5\xbc\xect\xd63\xfa\xba\x15\xd8=\x19\x0f\x05\x0e\xc8\x8d[\xb8\x07\xa9xH\xc8k\"kiR\x1b\xeb\xe6\xcc!PKNCd\x06\xf8L\xd1\x19\xa0\xa8\xa1\xad\xcd\xb1\xd4\xa8\xa3m3\x04;\xd26\xf8hR\xfc\x05\xfbUPC\xdd[gZ\x1b\xd2\x01\xe4\xb2~1\xc0\xe2\x7f\xb1t\xe7\xae\x81\xa8\x16\x04\x9d6&\xd2;\x8b\xeb\xed'\xe1\xe1\xf7\xd34\x9cI\x19\x1b\xc7\xa7\xaf\x85\xc4\x81\xf0\xa9\x12\x82\xe5`Z\x90<|e\xef\xbc\x88\x0f\x06\x1ak$\xce{\xee\x9e_\x8f(\xdaV\xa4x\x0e\xed+\x8f\xbcbD\x17\x11\xe1A\x1f7_\x90\xccpV\x13\x14\xd0\xad\xfd\xb8\x12\xb7\xe5\xe7\x9c\xa6\x17\xd3D;\x8d\x8df\x9cV\\\x98*\x92\xde\xda\x82sr\xf0,\xee}T\xdc{P\xa18\xc2(\xdc~\xfa\xe6\xd9\xf1\xb1\x16O&\x01?f\x10\x84)\x8b71C\xc7\x87\x04\xd9-\x15tNnmR \x1b\xd0\x82\x9f\x9d\xc0\xee~\xf3\"{\x82\x14hXa\xad\x82\xe6I\xbd\xadc\xc9\xaa<4\x8aQ\x16*\xc03\xf7\xe0(\xecG\xede\xfc\x9dk\x8c\xc2XL\n\xc3d\x86(~G\x0e$\xbd\xa0\xe2\xda\xc9\x901\xa5\x05\xc8\xa7\x80K b\xc9\xd4Wrs\xf3\x82\x1e\xec\xef\x8d\x1e\x8aX\xa9\xfaG\x03Y\x93\x97\x8b<\xfa^\x19\xf7Q\xb2\x04\n\xc5\xd9\xa8YK/\x82\x84\xb6\x100\xfd\x01\xfe\x96\xd131!\x92\xfa!H\x1eQ'\x91\xf1\xd8\x99|\xbc\xb9A\x9e\x9b\xbf\xcc\x03Y\x1eb\xda*\xf9\xab\xd8\x04Q\"XE<\xde\xdc\x90\xd5\x02\x7f\x8b\x01\xaa\xf8;\x19\xa9J\xbdQ\xe4\x1a~)\x7f\x14\xdb.01|j\xf9\x981\nx\xb0b\x8bcQG|\"\xe8wK\xe5\xb7\xf4V\x0d\x1d\xf7.\x07\x06Q\xae\xc9\"\x06j\xb4(\x8e\xd0\x7fJ\x89\x84^\xa6\x1b\x02a\xa1:\x9fH_\x14\x11-m\xa7\x81\x08\x0c\xc5^\"$\x0d\x1c\x158(\xac\x1e\xd3P\xbb\x80<\x08\xf5A\x90\x9bFX8\xb7&\x92\xf3\x89^\xe7 \x0f\xf8\xb8\x0d\xc3'\x1e\xfc\xe0Z<\x8c\xc3|n\xb5\x07\xf4k\x9b8Z\x13E\xc3!\x9d\xe3rW\xc8G\xcb\x96\x1c\xcc-B\xf9\x88\xf3\xfc$\x91aFZH\xac<\x04[\x0c\x07\x10\xf0\x7f(\x04\x1bs\xa3i<\xab\xc7-\xdf\x1b\x0f\x9c<\x99\xdf\x99\xf6/XJ\xaa&T\xc9\xaf\xaa\xe7\x95\xd7\x1a\x8a-\x95\xb5\xe4\xb2N\x07\x06\x9f\x82<\x81C\xe0\xe6\x8aC\xa5\xa1W\x184\x085\xec\xda\x83\xb3,\x85e\x94\xf1[.\x8a\xd9\xad\x128\xe4I\x0c\xbe\xeeU\x93\x1e|\xdf\xb3\xe6+h\xd2B\xb4\xd8S\x04\x99\xb8\xcf\xaeR\x16.\xdc\xea\xf2\xd1\xa1\x1eCV\x9c\x0f\xef\xac\xb4\x1d\x12\xf8\xee\xd8\xd8W\xdaOc\x02\x87Z\xcc,f\xf3\xfd]gS\x8d\x0f\xfc\xe9\xe9\nL\xc1D\x03\xb7\x10z\xb1r\x97r<&.\x12\x89e\xcf\xb2\xe5\x92Pw\x15e\x86E\x94\x19\x8b\x9f\xf3h\x95\xad\xc3B\xa0\xd3\x1c\xee\x02-\xa3\xc19K\xdf\x84\xc1f\xc3\xd2\xa6\x05\xae\x98\xabW\xcfbG\x1b\xae\xa7\x0b\x0dL\xbc7\x88\x00\xf0\xbb\x1a\xc5\xf0pOD\xc0\x91\xf1o\xf4\xd9\n\xeb\x00~\x9do\xd3yvN\x07\xa7\xf1i\xf8\xff\xfe\xaf\x9eU\xc0\xe9\x07\xe1\x82]\xbdZ\xba\xdah\x10\x8b?M\xdd\x80\xf4\x17\x96\x90U\x01lS\xf0\xc0\xc2\"oc\xbf\x0c\x1e\xc0\x88(\x0f3\xb3\x86\xe3\x86~\xbf\x0f8\xf8\xee!\xec\x99\xb9\x946\xeef\xb8Dz\x1e\xbd\xd2Jd\x9c\xec\xd3\xa6\x97\x93Ww^\x9a\xcc\xba,n&\xd0\xf8vieZ\xacJ\xa4\xafJ\xc6\xd7\xf7\x13VE@\x94/\xd7CL\x80\xa8\xba\x80\\\x11sSJ@1\x94\xe0\xbc|4\x00\xefR\xc0\xfcn\xb9\x16t\x0d{\xde\xd5\xee\x8b.8\xbf::\x82\xd2\xcf\x90L\x19\xd86\x1b\xb5\xe3\x18\xef\xf8\xfc\xe8s\x82\x15)\x88{A($\x8f\xea\x1dFK\xbe\x87\xaarN\xb1\xf8)q0\x0e\xc6\xa3W\x98\x00\xf9\xba.\x9f\x9b\xc0\x04\xf9{Q@*\x10\xd2M0\xb9\xa096p\x85\x88\x8az\x19\xd3\xaa1\xde\xad\x11M+L\xf3\x89Hs\xa0])z\xe3\xfc2\x8e]C4\x9c$\x8d+\xd9\xfd>\x04\xe1b\x9c\xabs\x0b\xef\x94\xf7\xd7lu\xdb\xc6\xcd#\xaf\xdb\x17\x91\xe7\xf1Mz\xbdbcp\xd4z9\x7f\xf5q?\x8b\xa2?\xf5\xb8\x1bL\xa7Z\x1f\xf7\xc2\xb1N\xe3\x8c\xe9\xc7\xf8m\xf9\xf7O\xef\x9e\xcbc\xcd\x0b\xf6\xf4\x8f\x97\xfe*)\xd4~Q)x\xfa\xf2\xcd\xf3\xbb\xa2\x85\xbas|\x9b\x81\x7fN\xfc\xe1LE&\x81o\xa2h\xc5\xfcpF}T\xf2\xd2I\nT\xa8\xe1k\xe7^\x8bmL8\xc1\x9a\x82\\\xd2\xad0\x91\x0b4\x06\xb1KmN\xb1 E\xb4\xea\x8b\x16{,\xf7\xbbM_&\x8c\xd1\xae/9\xaf\x17\x96y\xfd\x1d\x10\x88%3\xe2m\xb3\x9aV\xf2\xa6\xed\xe5\xe344\x94\xb5o\xe8\xa1\xd6\x90|*c\xba\xc0\x84\xe9\x820\xfd; :\x12\xd7\xe8\xb2k#\xe0\x04v\x87zS\xc3\xca\"\x17\xee\xe4FU\xe8\x1a_\xe7\xbfD3\xeed\\\xbc\xc7\xf3\x1e\xa8\xf2\xe9i\xdf\x9d\x8c\x83pys\xcc\xff;y\xe1\xddPQ\xe8\x877'\xfe\xc9\xcd\xc9\xd3\x13\xcf\xfbZ7\xb9\xc7\x80\xfc\x98\xadW\xeb\x9c=\xb0K \x8d\xbc\xf3r\x15\xf9_\x84{\xd6\x85\xdb\xa4\x15\xe1\x88\xd6\xedD\x82\x80\xf1t\xda'\x9d\xeaf{\xb3\xcfN\xd2\x18#\xc1\xc8\x11\xc2!H2BX\x1eW\xa8\x91~\x1a\xbd\x8c.\xe5\x89\xe6\xa4\x04L\xf8=>\x06\x11\xfcw:\xeb\x81\xd3\xdd\xceu\xe7\x0c\xe9\x95#q\xc1\xb8d\xf2\xa7h\x91\x1e\xf0\x9a\xcb\x9c\xf4\x10\xa6G0\x11wY\xff\xf5\xab7\xc7o\x8f\x7f~\xfe\xfe\xf8\xe4\xc5\xf1\xc9\xf1\xdb_`,_\x9d<\xff\xeei\xf9\x95\xd3\x0f\xfd0o\xee\xc4?\x811\xb0\"\x85!0\x9b\xcb\xeeFf\x04E2\xe3\x05\x07\x9cZBCX\xe7\xc5Dh\x04\xb7\xe8\x8aIB#\xe6\x9f\xdb \x8d\x10\xees\xb2y\x8c\x0f\xda\xa8\xd8\xdf\x89\xd4p\x89\xd6\xe8\x1c\x92\x1b\x86\x81\xd4hKk\x14\xf0\xa4\x0d\xe2C\xb3l(HN\xfc\x13\xde\x17$\x97A:\xbf\x00\xd7*;\x98\xfb \xd3\xe5\x90cc-\xd0\x16\x07\x81\xcf\xcc\x1dQcJ\x8a\xdb\xa6\xb1\x93\xa7'\xb5\x8d)1m\xab\xc6\xfc\x13\x83<6\xf7x\xb6\x1e7!\xf4\xfb\x12\xab\xc5O\xfeg[\xad\xe3\x93\x17\x9fo\xb5\x8e\xc3e\x9b\xd5\xaab\xa0/\xb7Z\xdb\x9fu\xb9\xb6?\xebzm7.\x98\xe9\xb4\xe7\x9f\x0f\xfa\x03\xc3X\xb4{\xa9H\xf6\xf6 S\xc9\xbc&\x10\xaak\xcaa\x0e\xbfP(\x02fX\x87L\xfe,]C\x99\xfc\n*\xe4\x97\xa2\x8e\xb4\xffy\xdb\xae\xed\xc7\xd7N#A\xd7\xd8\xe2\xa4\xf4\x8b\x93no\xd3\xd9\xcd\x14NO\xd3Y\xd7+\xbc\x1c\xeb\xbd\x17~\x10}H%\xf7=\"\x10\xb1\x85\xfb\xee\xbfn\\N\x8by\xe5n\n\xdf{\x13\xcf\x9b\x14(\xb9V\xea\xdc4X\xb3$\xf5\xd7V+\x96\xcfN\xac\xe5\xe1\xca\x83>\xbbbsA\xb3\xa9\xd2H\x96~\x01r\xcd\x10\x07\xc5\xa23\xd9\x08\xb7L\xf3\xb5\xa7\xf47H\x81\xa9yx\x8a(\xcb'\xa1\xe7'\xf74\xf3\xee\xe7q\x1c\xc5\xae\xf3\xad\x9f2\xe5K\xcbx\x99)(S \xf2\x89v\xd9t8#\xda\xa7\xcb\xa6\xa3\x19y+e\xf4sg\xd6\x83\x0e\x9b\xee\xcer\xf3Wv \xbc\x03\x97\xff\xaf\xff\xee\xed3W,\x83\xc9\xff.\x10\xe1)\xba\xbc \x8aN\xd1e\xd3\xbd\x19\xc5\xa5\xe8\xb2\xe9\xfe\xac\x07l\xfapfC\xc2(p\xc5\x80\xb7\xd3\x873A\x94\x0ez\xb0\xe3=\x81U\xeeK\xb9\xf3\xc4\x83\x15\x1a\xf6\x99\x90\x14\x88\xa8\xd1\xddU\x15\xfd\xd9\xc0\x8bM\x1f\xcfp\xe1\xf9\x9e\xed\xb3]\xb8\x0f\xee\xfe\x00\xee\xe3j\x0df\xd0\x85\xae\xcb\xa6\xc3\xe1\x8c\x83\xd9@\x8a\x00qC\xf4/\xb77\x9e\x88\xcb`]6\x0dzV\x1eFS\xdf\xda\x82e?a\xe9\xdb`\xcd\xdce\xff\\\x93?\n\x0d\xda\xa5\x0b\xce\xd3o\x9e}\xfb\xfc\xc5w\xdf\x1f\xff\xe3\x87\x97?\x9e\xbcz\xfd\xdf?\xbdy\xfb\xee\xe7\x7f\xfe\xcf/\xff\xf2\xcf\xe6\x0b\xb6<\xbf\x08~\xfb\xb0Z\x87\xd1\xe6\xf78I\xb3\x8f\x97W\xd7\xff\x1e\x0cG;\xbb{\xfb\x0f\x1f=\xee>8<\x0dOc\xe7\x96\xec; x\xbe\xc4\x86\xddY\xfbm\xc1\xd3A\xa3b\x9cc\xc7\xc8\xa2\x1e\n)\xf2_H\x1eCa\x9d\x8e\xa8\xe3\"b\xcfr3vi\xbcN1\x00a\x7f\xb7Qk\xc4\xe0\x00\x06\xad4?(\x13\xdf7\xbe\xb6\xe2\xc1\x18\xfe\x0b\x1e\xa1\xf0\xb9\x08\xf6\x9f|q\x06E\xe9\xc5\xf44>\x0d\x0fgB\x86a_\xf4\xa0v[|\x8c\xffc|\x95\xd8\xb7{n\xd1\x07)\xff\xee\xc1\x13\xe0\xab\x9c=\x01\xd6\xedz\xc0\xe0\xbf\xd0\n\x8c\xe4%\xa4\xce\x99\x8b\xfc\x10pt\x04\xc3}\xd8\x82\xd1\xde\x9e\xd7\x03\xbd\xf8Q\xb9t\xb4\xb7\x07[\x90p\xa4\x9f`\x12\x90\x83\x03\xd8\x87\x1b\xf0\x158\x04\x12\x1c\x98\xe9r\x15[4\x00\x19\x087\xc3\x81\xdd\x87}T\xd1|\xd2\x90`\x0c\xc3GJ\xd0Slk`lk$J\xf1S\xe1q\xc8\x97F\xaf\xb3\xab\xbe\x8c1\xe9\xc62\x8e\xd6\xea\xc1\x9d#O\x80\xe8\x1e\x1f\xe7u w[\xa9\x08\x06\xf6\xe0,\x0e!\xd0\xf6Z\x93\xb6\x00\x1d\x93s\x8b\x15\xa1X\x80/k\xc45~\x0d\xae\xb1@\xe7N :\xf1\xe4\xfb\xd3\x00\xb7\x8fo\xfa\xfe\x0eR|Z\xe9\xc8T\xba_*\xdc\xdf\x81-@s\x1c>#7\xe0\x10\xfb\xc8\x83.\xa4SfW\xa8\x16\x01t\x87\xf4\x87\x9fyD0\x86Q\x0e\xae\x85v\x06\xa6vv+\x85\x07\x07P\xeeq\x7f\x17\x1b\x1e\xe6\xc0\\h\xb9:\xc0\x83\x83J\xc3\xfb\xbb\xc5\xf6z\x10\x17\x01O\xfd\xfad\x02\xc2\xca\xceVd\x7f\xc58\x93U\x02\xc1*,\xbc%\x89\x16\xd5x2X\x9c9>\xf1\xca\xb7\x19\xf2\x97\x985\x12\x83[o\x03C\x80\xca\xfc\xb8\x91>z\xae\\\x83\xf9\xe1\x0b\x9f\x90 \xd8\xea6\x16\x88|\xa1\xf3)\x9b\xe5I\xc0\x94\xa8\x96\x16|\xe6\x08f\x15E\xb2q\xb3=\x87\x08\x84\x13\x84\x10\xd7\x1b\xf0\x04\xa2Id\xd3j\x08\nY\xdfo\xecZ\xfe\xdd\xc9P\x07i\x9f\xe6>x5a\x81\x90\xa8;1k^\x16\x11\xce\xa2U\xd2\x0e\x058\xc5SyG\xfa\xa6*\x9c\xf8\x93<\x8cZ\x1c\xfa;\x9e\xe1\x8d\x1f\xc4\xc9\xdf\xeb\x10\x0b\x7f\xdd\x9a\x83\x9a\x89\x19=\x8dc\xff\xda\xf5\xa5\xdb\xa3R\xf4\xf0\x13\xec\xdf\xed\x04\xfbx\x82\xcd'7h}r\x03\xf4\xe1G\x93!\x0d\xe1~`\xd7 \xff\xba\xec\xd6ok%\x9b\xb2\x19Ge\xd1t\xc0o\x19\xfcw6\xfb\xd3\xa1\xde\xb2\x8f&\x9a\xfac9\xd4\x99\xf0\x06\xb6\xeccT\xd8\xc7\xcc\xb8\x8f\x99m\x1f\xf9ne\xb8[Ae\x89{\x10\x89\xb5\x0b\xc4\xda\x05\xb8vV\"&\xfa\xeb\x0fp\xf1\xd6\xbe\xe51N\x98Uun\xf6)\xfcrg\xb8\xf6\x82\x0dB\xb0\xc4\xfe\xd2\xee\xb1\xb0'L\x10\x15\xa2\x0d\xa7lV{\\>/\xc4\xdb\xf0\xfc\xdf\xcd\x8f\xf2\xb7\xe4A\x16.\xd82\x08\xd9\xe2\x13%/5\xcbp\xfbE\xf5*\x19\xe6o\xcb\xcf}\x8c\x82\x85\x8c(V\xd7\xbb\x89\x93\xab\x13\xfa\xfd\xcd\xbc\xa1\x7fK\x1e\xc4\xec\x9c]}\x11U\xca-\xe4f\x01F\xa6\xc1zm.'\xe5Mg\xa6\xb19\nxp\xfa\xc0\x9d\x9e\x07\xeb\xd9}\xef\xeb\x07R\xb3a\xae\x1e\x1bb\x0c\x80\x18\x94\xf3@\x8a\xdd\x07V%\x02i:\xa4\x05o8\x1d\"\x1b&\xd5\x07G\x9c%mq]\xf3\x9e\xd0\x9aw\xcar\x03\xa0\xb8`\x0b\x947Si\xe5K\xdf\xc1\x7f\xce\x8a\xcbS\xa2-:\xa9\xdf\xca\xab[0\"\xea\x81e\xc5P\x93\x95kFY\xaf\xcc\xc7|\"\x92PT\x1au\xd0\xd6\x14\xe6\xb6\xf8\xa4vC\xf8Zu!\xed'Q\x16\xcf\x19ty\x81ua\xd3\xfe\xf9*:\xf3WB\xe7\xd7=\x04\xe7\x9cB\xf5\xe5\xa9\xe7\xf3Wkz\x15\x9c\x87Q\xcc\x9e\xf9\x89\xfe.\xe0\xef\xd8\x97BfO\xb4J\xea~\xd1\xa21]\x06\xe1\"\xbaT@A?\xfb,\xd9\xc4\xc1\xda/\x19\x06\x06\x8d\x98\xd1\xa8N\xf8-y \x07\xff\x17\xe3\xc6\xaa\xbaF\xfe)\x18p\x11\x06\xf8\xe6{\x16\x11!\xc8\xf48}4\x0e\xe3g\xa1\x9eM\x8f\xfd\xf0\x9c\x8dkyo[TQq8^\xc7\xd1y\xec\xaf\xe9P\x84\x18\xfb\x8e\xef\x98\x0c-v\x16-\xae\xb58<\xce\xf3+\x0e\xf9I\x10\x85oR?ek\x16\xa6\x8eVu:\x98\xa9&\\\xe7i\x1cG\x97/\xc4\n\xe7_\x96?`\xea\x0d}\x8bN\xcf\xb7\xfd\xca\xc0\xe6\xebZ\xb1\xba5hD\xd4\x9f\x84\x8eEt\x9c\xe6\xcd\x0f\xb4\x8d\x0f\xeb6\xbe~\xd3\xff\xb0`s\x9b\xc3\x0b\xdej\n\n\x88\x81\x95\xdb0\x14\xbfu(\xe0\xbbc\x84\x82\xbc\xaa\x82\x02^\xd7\n\x04\xc5\xfae \xe0\xc0v\xeb\xaf\x0cf\x10/\xfc`\xc5\x16\x90F\xca\x16B!\x0c\xbb6\xc5\xd8\xc1\xc6\x8f\xfdur\x0b\xab\xd0H\x06T\x0d\xfd\xb5 >\xc5\x0di\xec\x0cW\x1c7\xba\x07\xce7\xabh\xfe\xa1t\xde\xec_\xe1\xf2Mp\x0d\xe4\x02\xbaQ\x0fB\x199x\x8a\x96\x0b\xfc>\x9e\x0egt\x01\x0b\x95\x8b^\xdd\x91\x08\x02#F\xe5\x9f\xd2g\xf5&4w\xbe\xa1\xe5\x00\xfe\xd4;Z\xdd\xba\xcat\xed\xcb\xda8X<\x00\xf6F&\x8b1\xf7\xd1N\xa98\xa3\xda\xe5b\xbfN\xdaW\xac\x9a4\xcb\x15J\x08\x0f\x0e\xe1q\xb1h \x870,i\xb3Vp\x08;\xa3\x12(\xf0\xb2\x9db\xd9\x05/\xdb-\x96-x\xd9^\xb1\xec#/{X,\xbb\xe6e\x8f\x8ae\xe7\xbc\xac4\xbe5\x1c\xc2ni,\xefyY\xa9\xdf3^V\xea\xf7\x12\x0ea\xaf\xd4\xc7\x15\x1c\xc2~\xa9\xbd7\xbc\xac4\xb7\xe7\xbc\xac\xd4\xc7S\xbe|%7\xc4W\xbc\xac\xf4\xedo\xbcl\xbfX\xf6\x01\x93\x15\x96*\x1eca\xa9\x97\x1f\xb1\xb04\x95\xb7ph\x80\xf8\xc1\x18\x9c\xd3\xd3\x81\xe1\x1ez\x88o|\xc3\x9bG\xf8\xe6\xcc\xf0\xe61\xbeI\x0do\x86\xd4Qhz5\xc4W\x1fM\xafF\xf8jiz\xb5\x83\xaf\xca\xd4\x1c\xff\x1b\xd1\xd0\xcbBh\xfe\xb7\xb3;\x86{\xa7\xa7\xce=\xc3\xd8\xa9\xaf\xd3Scg\xd4\xdb\x89\xe9\xdd>M\xed\xbdi\xa5F;\xd4\xeaK\xf3Kj\xf5uI\xc6P\xac\xfa\x8c_\xd6\xce\xb5\xd3\x03\xe7\x17\xfe\xbfk\x96\xe0\xb3\xf8\xe7\xf9\x1b\xfe\x0f\xd2\xbc\xce+\xfa\xff \xff?>\xd2S\x84\x8f\xf4\xffWX{\xb9\xc4\x8a\xe2\x9f\x17/\x9c\x99)\x90\xc6\xeb*\x92\xcc\xc5\xb5%\x0d4Y\x9e\x1c\xd6z\x93\xf5(X\xc6ho\xcf#B\xe8\xca\xa1h\xbd\xa3b[\xca\x02\x19\xab\xef\xef\xed\xed\xc8\x0f2\xf1\xc1\xae\xe1\x033\xc9\xde\xa1FvG\x8fw\x1f\xef?\x1c=\xde\xf3\xbcb\xf8\xdby\xb4`\xb0\x89\x82Bz\\\x8av\xb8\xf6\xafe\xda\x85\xf3\x98\xf9)\x8b)\xf3\xc2\xe0\xea\x85\xf83\xd1\x0d8\xd0wb\xa0\x8f\x8a;[\xf8%o\xbc\xd3SG\xc4p\xcc\x836\x0e\xf0\xfbm\xc5'{\xd0\xd5\x987S\xb0\x92\x9f\xaa\x9b\xa5\x85\xac\xc6\x9d\xc9crG2\"\xb6\x0c0\xfd\xa3\x9f^\xf4\xd7\xfe\x95\x8b\xf9\xc1E\xf1\xcd\x0d\x8c<\x19\xda\xfbC\xb09\x0e?\xfa\xab`Ami\xbf\xf58\xdc\xcbUt\xf9\x92}d+\xa4`\x83\xe4$\xe2kz\xee\xa6\xf9\x1bO\xfa\x1fie\xb2\x97\xf4z%\xe2m\x17\xaeU\x1bE]\xcd\xffkH\xdfU\xe0\xdcrw\xfe\xff\xfca\x919\x87\"\xfb \x19iP\xc6\xd5\xb8\xa40`J'C\xce\xff\xd1\x13\x8a\x88:\xa4\x8c\xe4\xf14\x10Z]q\x16\xd84C\x0f\xeeN\x87\xc8\x99,7]\x1d\x91A/\xff\xcc\xc0\xd5r\xd0\xc8\x94\xff\xb6\xd7\x03\x97\x12\xb8\x95B\x90\xf7eV!\xde\x0foOdt\x98\xf7u7\xcb\x1e\xf8\xd4\x99\x8f\nk\xfd\xd5\xd4\xe7\xe3\x0b\xa7\xd9\x0c\x0e\xcb\x91oA\x13p\x17\xe1\xd9\xd5@\x8c\x03\x0e\xb6\x98H\xf3H\x05;Q\x9c\xfe\xc0\xae)\xd5\x8c\xfaQ\x8c\xde\x1e\xb2\x7f\x06\x0b\x19=]\xfd\xba\xb9\x81G2\xf6y\x18\xfd\xc4\x96\xd4\x86x\xd4[\x08\xa3g\xd1z\xe3\xa7?\xf2\xe3Lu\xb4\x02\xbd\xe6<\xe2\xd0\x8d\xeeV\x97b)\xb5\x02\xbd\xe6\x1d\xe2\xc5\xcb\\Du\x9f<\xbf*\x86\x98\xc7\x9cWa\x1e\xa6\xbe\x98I\x9a\x97,2\xfe\x85\x9f2a\xa7@\xa5Y\xc2\x16\xdf\xeao\n\xc1\xfdL8\xe2\xc4x\x98\x10\xe8\xc5i\n\xe0\xb0\x14:\x96y\"w1)\xe6\xb6\x87\x04\xd7|l\x89f\xaa\xf4\x04\"8\x80\xe4\x89\x879\x1a\xd0j]\xa6\xe6\x17n|\x98\xf8?\xf2\xd0\xda\x87\xfcCD\n\x0b\xd1A\x82\xa9\xdd\nox\x97\x14\xc65Bc!z\x0eu!\xc4\xa9\xe0\x03C\x01\xd7\xddC\x08<>\xc4\xeea\xd9\x9dL\x80\xb0_\xbbD/\xebbo\x9bc\xebJty\x1f4\xce\xce\xd4\xf6\xb7U\x14-\x19\x0e\\\xb1\x15\x87>z\x9c\xd76\xf4okC;\xa3b`\xaa\xe1h\x1f\x99\xf7\xfda9\xf2\xd5\xe8\xf1\x1e\xff\xc5)\x94\xdcm\x82\x93$\xe2\xd7\xcd\x0d\xec=\xdc\xd9\xdd-~\xc7/\xe3\x1d\xfe\x8b\x92Q\xa8\xaa\xbc|\xbf\xd4\xf5p\xb8;\x1c\x0ek'\xf2\xc2:\x11\x9cb\xa9\x1fl\x99?\xbe\xcf\x1f\x9f\xe6\x8f\xaf\xf2\xc7\x0f\xf9\xe3\x8f\xf9\xe3e\xfe\xb8\xa8\x1d\xd6;\xeb\xb0\x1e\xfcz\x1a\xde\x07\x19\xc8D\xdfn\xf9\xc4\x0f\xd27\xd5X#\xbfs2\xa7X\xf4\x0b\xe7U\x8aE\xff\xe4\xb4M\xb1\xe8g\xc0\x88\xd2\xd5A\xfeP\x1fg\x9d\x8f#\xd2\xed\x9b:\x86\xe8'sK\xf9\nO:\x85\xfa\xa8\xbe}Kx\xa0R\xce)\xd5\x7f\x8b\xec\xa3\x85\x04%\xa5\x9d\xc4x<\x9do]\xba\x8c|,;\xcb\x1f\xdf\xe4\x8f\x97\xf9\xe3\xfb\xfc\xf1i\xfe\xf8*\x7f\xfc\x90?\xfe\x98?.\xf2\xc7\xeb\xfcq\x9d?n\xf2\xc7\xe3\xfc\xf1*\x7f<\xcf\x1f/\xf2\xc7\x8f\xf9\xe3\xf3\xfc\xf1713{V\x17C\x82\x07\x839\x8a\x97\xbf\xed\x10\x0bb\xf2\x06\x0e[\xff\x13a\x05c\xdd\xef\xd7\x9a\xcdS\xff\xe3m'@\x91\xdd\x9a'\x02\xe2\xe6\x8a\xa7\xa3\x861\x83\xca\xffB\xb3\x9c\xa3\xfa'\xe2'=\x81.\xe7\xf50\x9b=_\x07Q\x01&\xfcqL\xc9\xeb\xa0\x0b\xffp\xe7\xc4L\xa2\xd2\xa2\xb63{\x98K\xc8A1\xb2V\xfa\x83\x83g\xe65A\xfb\xcf\x8d\xd0~\x0f3\x934+\xf7\xe4\x9fb\xa4s\xaa\\p\xcaV\x1aI\xc8LK\x84\xd0\x111h\xfb\x80\x0e;\x9c]\xdb\xdf\x19\"\x11P\x8dO\x1a!WL\xdf\xec\xef\x8c\x06\x90\x07+\xdd\xd9\xdd\xe1\xcc6\n\xa6^\xbb\xc3\xc1\x08\xbd\x96\x19lS\xeb\x949f[|\xd6%\x1e\x8e/\x1b\xa7\xdd\xc6$\xf3z+\xcce\xbb\x87\xd0AJ\xe6\xdf\xfc\xe2\x99@:\x8df0\xa6[\xee\xb5\xd9\x1bM\xff\x93\xba\xd4\xba=\xf3(}\xa8\xb9!\x11\xfc\xc1\xbee\x05\x99n\xb0\xdeDI\x12\x9c\xad\x84\xb7\xfb\x18\x02!\xaa$\x0b\x10\x8a=\xe64\x11v\x7f\xb8\xf5\xfc\xfc\xd7\xf64Rp(\xe95)\x00\xc4\x90k\x06-@\\D&\x85XRF\xf9E\xc8\xcf\x1b%\xd46\x7f7\"|\xa4\xde\xf1Q8]\x07\xb7K\x1e\xcam\xbalNC\xa7v\x86\xdf[\x19a\xdb\x909l\xe4(u{\x88\xb9/\xa9\xf4\x85a,\x8a\xf8\x99\xb2\xf1/E6\xfe{G\x98\xa2_\xd0\xfe1\xf8\xf39\xdb\xa4 \xaa\xde\xf0\x06^QN0\\\x81{M7MqZ\xd3\xd5\x8cff\xbfy\xecW\x8ad\x87cc\x95\xda\x90\xd3\x06\x83,#\x9b\xdf\xa9\x97\x8f\xfeOA\xc6G\x87\xbe\xcc\xb3\x17\xf4\x07r\xc8a\x8f\x8er\xd8\x83\xce\x10C\xdf\xa8\x9f\x03Cj\xe0\x04\x14\x94P\x13\xe5$\xad\n\xf9\xe9,\xed\x01E\x85+r\xb9\xe5\x14\xa6\xbc\xf9y\x0fV=\xb4\xff\xa8\xbaIq\x00Ea\x87z\x85\xbe=\xf2MU\\\x86\x02;W\x93P\n\x8dX\xae$Q\xbbM\"@-al~\x13\x18\xda\xd1\x8a\x1aZ\xd4?.\xa0:\xa5\xee\\g Z\x12\xf8pF\xa9n([y\x9d\x05\"\x14D\xacDB,\n\xfa\xb6\xec \xf1`C\x0fE\xf6\x9c\xd5\x10\x1b\xceW&\xe2@\xedb\x1c$\xa1\xd6\x12\x91%\xc2)'p\x16\xd3h6\xeb \x1cCf\x80>\xe5`\xa7\xff\x08\xee\xf1t\xb58A\x02\xf8\xf1l\xf0\xa7\xdc\x9b\x823\x1e2\xeb\xbb\xac\xb3\x14[\x875\x8b\xc9\xcc'\"r\xd3\x84\x13\xaa\xe2\x11\x1c\xe5\xf1MS-\x1d{?\xf1\x97\xec\xdb\x92\xb5B\x8d\xe5\x1eM1\xee\xb3\xab\x94\x85\x0b\xb7z\x8e\xc8Fs\x0cYq\xb7\xf0\xc6/\x8d\xeeN>?\x02\x90\xc85V\xba\xd6\xf0\x83\xed\xbc\x7f\xcf\x92\x1f\xa3E\xb6\xaa\xc6.\xfd\xe8\xaf\xb2\xa2w\x1f:\x8a\xf5\xcfY\xfa,\n\x97\xc1\xf97\xd7\xefb\x0c\x86\xdb_D\x97\xe1*\xf2\x17T\x0e\x87\"\x1eB>\x80\xdc\xe9h4\x18j;h\xf8\xd4\xae\xf1*\xdb\x16\x18\x15\xbd\xa2\x92;\xe0C]\x86\xfd%K\xe7\x17^\xc5E+\x9f\x93qJmvU\xd51\x92-\xca\x97\xb8\x9fl\xd8\xfc)\xd6L\xccH2\xf7\xe7\x0dJ\xcb\xe1\xa6^?\xbd`\xe8\x07\x17\xe9\xe9F\xe5\x9f:E\x91y\x14\x80\x9aSM\xbe\x8c\xce\x88\xa8.\xed'\xa9\x9ff \x1c\x1d\xc2\xee\x00\xd3[\x04\xfdl\xb3\xf0S\xf62\xf2\x17Ax\xfe\x06\xdf\xbb\xce\x12\x1d\x17i@\x9c\xb3\xb8e\xb5w\xf1\xcaux\xc1<\n\x93h\xc5\xfa\xa8\x14se\xffo\xd9U\xaa\x91'Y\xbc\xe2@\x86\x17\x07R\x89\xcc\xe5[)\xdcQ\x7f\xf1\xd7+\xea\xc1s\xc3~\xca\xae\xca!\xb4\xa1\xaaF\xfb[\x9d\x1f\x1d\xf2\xcfY\xda\x12\xd2R^\xf78t\xcbw\x15L\x80\xc1\x18\xa6l\xf6\xf7\xc2\x12\xa5s\xaf\x08w~\xfa\xf7\x0c^\x84H\x91\xcb\x1b<\xef\x0b&\x10\x83)9\x93\xd4\xc7\x96\x83\x17\x16[F5\x9a;\xdc\x7fT\xea1\x11#\xd9-\xe2!j\x93\x02I\x92\x0b\x06\x07\xbcL\xbe\xf0\xdc\xa0\x07I\xff\xdd\xebo\x9f\xbe}\xfe\xfe\xd9\xab\x93\x17\xc7\xdf\xbd\xe9\xb5\xdc>\x0c\x0e\x8d\x80\xeccp\xd1\x7f\xbc\xf1\\\xd6\xdf\xf8\xd7\xfc\xa8\xeb(\xde3\xf7\xfa\xf6\xd5w\xdf\xbdl\xdb\xab\xbc9U\x07f\xb5/\x02UEt\xa2\x86\x9c\xf0\x97=\xe8\xc4\xc5\xd1\x05\xc2\xf3t\xe6}\xc5\xf7\xf9\xc1\x83\xff\x03\x14J\xe2G\n\xdb\xf4\xee\xa7\x97\x87\xc9\xa5\x7f~\xce\xe2\xed,\xd8\xe6xg\xe1\xaf\xa2\x90m\xa3N$\xed\xff\x96\xf4\xd7\xfe\xe6\xff\x07\x00\x00\xff\xffPK\x07\x08v\xf2\x8aA\x86\xba\x01\x00\xc5\x87\x08\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00 \x00swagger-ui.cssUT\x05\x00\x01\x80Cm8\xec\xfd{s\xdb8\xb27\x8e\xff\xff\xbc\n=\xbb\x95\x9a\x99\x1dS!EQ\x17\xabf\xeb\xc8\xb1\x93q6r\xc6\xcem\x92\xad\xad)\x8a\x84$\xda\xe0\xe5\x90\xd4\xcdz\xf6\xbd\xff\x8aw\\\x1a $;s\xf6\xf7\xad\xb3\xd9dl\xe2\xd3\x8dFw\x03h4\x00\xb2\x9bl\xed\xe5\x12\xc5\xda\xda;\xfc\x9fN\xe7\xe5\xdf\xfeo'\x08c\xdf\xc6\xde#\xea:I\xd2\xd9\x0c\xbbzW\xef\xfc\xbf\xce\xec\xfac\xe7\x9d\xe7\xa0 A\x9d\xff\xd7Yz\xe9j=\xef:\xa1\xff2@N\x88\xed\xe4%M\xf7\xb7\x97\x8b0H\xb5\x85\xed{x\x7f\x9e\xd8A\xa2%(\xf6\x16\x13'\xc4a|\xfeWs\xde7,\xe3\xdfD\xfd\x9dU\xea\xe3\x03\xf6\x02\xa4\xad\x90\xb7\\\xa5\xe7F\xd7\xb0&\x9a\x9fh)\xda\xa5Z\xe2=\"\xcdv\xef\xd7Izn\xe8\xfa\x8b\x89\xb6E\xf3\x07/\x85K)\xce\xf3\xd0\xdd\x1f|;^z\xc1\xb9N\x95\xd8q\xea9\x18\x9dQ\xcf\x12\xcf\xa5\x9f,\xc20E1\xf5h\x85l\x97y\x14\xd8\x1b\xea\xf7\x049\xa9\x17\x06\x07\xd7K\"l\xef\xcf\xe78t\x1e\xe8\x16\x1b\x87\\K\x99\xf0\xe7=\xe4OJ\x19\xbb\x83!\xf2;\xb4\xa4\x0bo\xe9\xd8Q\xc6\xf0\x8cy\xbc\x8eii}\xdb\x93UZPT\xea0\x90\xdf\xe9\xeb\xd1\x8e\x96+>T\xca\x9d\x87\xbbL\xe4\xdd2\x1f:\x16a\xec\xf3\xca\xfbg\xba\x8f\xd0/1JP\xfa\xaf3\xbe Y\xcf}\x8f)\x01*\xcbf\xb5\x92\xa2(\xfdW=\xb6\xdaQ\x84\xec\xd8\x0e\x1ct^\x14\x01\xd5\x974\xe7\xe7\x9a\x1f>j\x8b\xd0Y'\x9a\x17\x04\xcc\xd4C\x8a\xaa\x04-\x85o\xc1\x16\x95\xf3 \xde\xeb&\x91\xed\xba\xd9l\xa0K\xda\xd0\xb0\x89\xbd`)n@+\xae\x92^\x02,E\xa7\x11\x87p\x9df\xbevnD\xbbr\xec\xed\\\xe4\xc0\x8fh\x972\xb3$\xc2n\x82\xd2C\xd5\xb0\xaei!\xbf\xd3\x1d\xe6\xff\x0e\xb8a\x01\xa3%\n\\h\xda\xac\xe7\x14j\xd6$\x9e\x16\x83a5\xacW\xdd>\xb5\xe7\x18M|{\xa7m=7]\x15\x1d\xa5\xd6\xf2d\xbb\xf2R\xa4\xe5\x83\xf4y\x11y1Sl\xb8\x8cQ\x92\x80\x83\x8f\xd2(Xw\xe1\xbaw\xd9\xeb4\x04\xac\xeb\xac\x90\xf30\x0fwP\x1f\x89m\xd7\x0b\xffu\x92Vd\x0e\x15\xac\xfd9\x8a3\xef-\x19\xe7^\xa9%\x91\x17h@\x17\x14\x10\x85\xeb\x94&:\x94C\x90\xa0\xa1 \xb2cg\x05v\xdfLY\xb9\xc7LJ\x0f\xd3\xc2\xc5\"A\xe9\xb9\xd6cB+\x8aU#K\xf1@s2nX\xdc\x06\x11]\x13\\@\xd2q#[C\xbf\xf00\xd2\xd6\x11\x0em\xb7R\x82pt\xcaG\xed\xcaO\xe9X\x00\xa5\xb6\x87\x13:\nE\xc1Z\x12\x85&k\xdf\xb7\xe3}\x8d\xc0^\x92j^\xca\xf4*\xc7\x0e66\xec\xc4\xb4V\x8b \xed_\xcc$\xe4G\xd8N\x115\x93Rd]\x17\xcd\xd7\xcb\xce\xdf\xa8q! \xb1\xe7v\x96!v\x01\xac\x96\xf7;\x90\xe2\xaf\x8b\xc5\x02\xa2\x98c\xdby\x80)\xd8\xf8\xa7\xa4X\xc6\x9eK\x04Ndx\xdbY\xc7\xf8G\xd7N\xeds\xcf\xb7\x97\xe8e\x14,'Y\xf7\x1d\xf4\xcf\xbc\xcf\x17\xef\xef\xb6\xfa?\xde,\xc3\xe9t:\xbd\xf9\xf0iu\xf5i\x99\xfd\x98\xffs\xfdj\xfau:\x9d^^]\x0e\x07\xef\xb2\x07o~\xbf{\xfd\xe5\xd7\xbb\x8f\xf3\xde7\xdd\xed\xbd\xde\x7f\xbb\xbd\xb8\xf8\xf6f\xec}\xfbp\xf1v\xfe\xe5u\xf0\xed\xf3[\xfc\xf5\xcb\x9d\xe58\x18\xff\x96\x11\xecW\xd1\xe7\xd7+\xfd\xcb\x951{\xef\xdfl\xe6\x1f\xacU\x81\xb7\xfa\xf3\xdf\xa7\xc5\xff.\xb7/\xd1\xaf\x17\xab\xaf\xbd\x14\xbb\xaf.\xbco_\xdch~\xaf{\xc3\xe1\xfa\xe5\xb5w\x11}\xbb\xd4\xbd\xcf\x8f\x9fofW\xc6\xf6\xb6\xf79\xb4?\xad\x06\x8e\xff\xf9#z\xb0>}5\xa3\xf8\xeb#~\xb8\xbe\x1f\xfd|}\xb9\xeb\xbf\x0fV\xa9\xf3\xc6\xc0\xee\x9b\xab%zc$\xf3`6@\x97\xba\xf7\xf5\xcb\xdd\xe6\xab\xffi\x90\xfd>\xff\xf2Y\xff\xfaa\xe4]\xff\xba\x1c\xa07\xc6\xd6}\x93\x8c\xaf\x1f^?\xcc{o\xf1\xf5\xeb\xd5\xcd\xa7W\x17\x97s\xf3-\xbe\xbe\xfc\xb4\xbe\xf1\x8c\xfb\xd9\xc7\xab\xdd\xf5\xa5c\xbd\xbb\xbf2\xde_\xce\xf67\x1f\xb6\xcb\xd9\xfdtw\xf3a\xb4}\xffa\xb4\x9b\xbd\xd2\xb7\xb3\x8f\xe1nv\x19\xeeg\xaf\xa6\xcb\xeb\xea\xef}\x7f\xf9\xdb\xafo\x1f\xbe\xddG\x1f\xee\xae\xbe\xd6\xf28\xfe\x9d\xff\xdb\x87\xb7\xa1\xfb\xeb\xdd\xf6\xbd7\xda\xb8\xa6k\xbe\x0b\x9c\xc7w\xfex\xffm?\xda\xbd\xff\xf8`\xbd{\x9c\xee\xdf=^\xef\xdf\xfd\xfe\xf6\xe1\x9bg<\xa2/\x96\xfe\xf5\xf7e:\x0ff\xf7\x04\xdf\xabo\xbf\xdf\xdc;>\xde\xbao\xf0f\xee]\xec\xbf\xbd\xf9:\xf8\xfa\xe5\xed\xc6\xfd\xfdv|\xed]7:xcl?~\xd2\xc7\xd7\xfeJw\x7f\x9d\x0e\xde\xed\xc7kg_\xdb\xe2~\xde\xd37\xe8\xcd\xeb\xed\xbb\xc7\xab\xf5\xec\xd58\x9d\xe7\xfaY\xa5\xf37\xd6\xe3\xfb\xe0F\xff\xe4\x7f\xa6d\x9e\x07\xb3u\xa9\xd3\xf5\xd7\xde8}g\xaeV\xce\xab\xd1\xee\xdd\xfdt\xe3\x18w\x96\xf3\xe6\xd3\xe6\x93\xff\xf9qn~\xde\x7f\xed}\xfe\xf0\xed\xcb\xd7\xfbk\xef\xa2?\xff\xb2[;\x8fQf{EY\n9\x9c+\xe3\xe6\xfd\xc3\xdd\xe6\xab\xf99\xfd\xf6\xc5\xd2?|\xba\x1d_g\xb6~e=\xd8_n\x07\xb3\x8fw\x97\xef?~\xed\xdf\xe8\x9fz7\xfa\xe7\xd7\xb3\x8f\xaf_\xdf\xdc/{\xb3\xc7o\x97\xb7\xf7\x0f\xdb\x9b\x87\xdb\xfe\xec~\xb9\x9d]]\x13\xfc\xf0\xda1\xefVs\xff\x06\x13\xfc\"\x9a\xdf\xad\x1a\xbf\xcb\xe8\xd2\xf1?\xaf\xdc7\xe3\xfd\xe77\xe3\xcd\xfcR\xf7n\x0b\xfd,?\xbdYm\xdc7\xe3G\xfb\xcdx{}usy}y\xbd\x9d}\xfc\xb4\xfc\xc7\x95\xb1\xfa\xda\xc3\xeb\xbc\xec\xd5\x83\xf7\x9b7\x1d\x95v\x1a\xdc\xbd\xf9\xbc\xb7\x7f\xff\x86\xbf]}\xdb\xcf{\xfa\xd21\xef2\x1d\x0e\xec/\xd6\xa3\xfb\xe6\xf5\xfak\xef\xf3\xdb\xbbK\xdd\xcb\xf0\xef|\x1c}\xbb\x0c\xcd\x9b{g\x7f\xfbpk\xde\xdc\x7f5o\x1f?\xedf\x9f>\xf5n\xef\xdf\xbe\xba\xd5?\xedo.\xa7\xfd\xd9\xc7\xe9vv\x7fe\xce>\\\xd7\xfc\xbe\xbd\x19\xdf\xbb_\x0c<\x0f\xee\x08~w4\xbf\xc7V~\x9bL\xf6w&\xe0\x93\x99\xaf\xbe\x1a\xe7~\xf9\xe9\xe1\xeeM\x81+\xfa]\xde\x0f?\xf6\x97\xbf]\x8e\xfb\xce\x9b\xd7\xf7v\xef\xb3~\xfd\xe6\xf3:\xeb\xef\x8ew\xfd\xf2\xb7\xe4\xe2\xc3\xcfof\xd9\x08q\xff\xe1\xd3\xdd\xc5\xe7_\xef\xed\xaf\x9b\xc7\x97/\x1fG\x97\xef\x92\xcb\xfe\xd2y\xf3\xbb\xf7\xf5j\xfa\xe6\xe2\xfa\x1fo.\x02\xf4\xf2\xe5\xe2u\xb4\x9d.\xb7\xd3\x8b\xf1hj\xbf\xeeE\xf7\xf8\xd3mF~\xf1\xf6\xee\x93u\x15?\xbc].\x97\xbf\xfc\xf2S'F\x11\xb2\xd3\x8e\xde\x11\x8e\xa4\x9a1x\xc6\xc1\xf4\"\x1f\xe6n\x8b\xc1t\xba\x18\xbd\x1c\xaf\xfew0\xfd\xdf\xc1\xf4?u0}\x7f\xf9u\x7fw\xbf\xba\xba\xbb\xcc\x06\xd3\xaf\xfb\xd6\xc1\xafe0m\xf8\xdd\xaa\xf1\xfb\x0f\x1aLo?\xb6\x0e~G\x0d\xa6\xb7\xed\x83\xf3\xf7\x19L7\xaf>\xe8\xc6u6\x18\xcd\xea\xc1\xd4\xbf\xeb\xbf\xb4~\xbex\xfd\xdb\xc5b:{\xed\xbf\x9c],w\xa3\xbb\xe9\x9b/\xaf\x02c:\xf5?,\xcd\xfe\xed\xe0\xe1\xe2\xf2\x1f\xb37\xb3\xcbW\xdb\xebWhv\x8d\xfc\xd7/\xad[{{\xe5E\xd3/\xdbO\xab\xed\xd5\xfd\xecr3\x9f~\xc1_\x1e6\x9f/\xb6\xeb\xd1\xe6\xf6zz1\xbd\xda^\xbc\x8aV\xa3O\x03G\xcf\xc7\xa5+\xfc\xfa\xe3\xc3\x87\xf5\xad\xff\xea\x95\xd2\x00<\xd2\xf2x\x97\x1c\x85\xb3`\x99\x1d~\xef#T\x8f\xbf/\xc7\xf7/\xfb\xb7\xd3\xafw\xbf\xaf\xa2o\xcb\xe9\xf4\xc3\xa7\x87\xff.\x03\xd9\xe6\x7f\xbf\xbdL\xa6\x17\xaf\xaf\xdc/71\xba\xcdF\xe6\xdbj\xe0|\xd9\xbf\x9d\xed\xec_\xeft\xe72\xdc\xbc\xebY\x8f\xef\xfcb\x1c{\x97\x8f\xb5\xe3\xfe\xd7\xdf\xa7\x9b\xd9\x87\xfe\xf6\xddv:\xfa\xcd\\m\xbf~\xb9\x89\xbf\xfd~\xbb\xfc\xea\x7f\x0e\xec/\xfd\xf1\xf5\xfa\xe7\xe1f\x7f\xbd\xb4\xbf\xdc\x8e\xaf\xb1c|\xfcxq\xe3\\\xdd`\xfb\x0d\xbeF\xc1[\xfc\xc9\x8c\xde\x7f~s3\xb0{3\xeb\xdb\xab\xeb\x97\xb9\x8f^f\xfd\xf7\"\xfd\xf6\xfb\xdd\xaa\x19#\x96\xe3\xeb\xb2\xee\xf7\xbe\xf5\xf8\xde\xcf\xc7\xe0M\xd6\xe7\xf31\xf9\xd7\xbb\xf8\xb7\x0fo\xab\xb9\xe2\xeb\xc7\xcf\xd3\xe5mo\xbc\xff\xf6aj\xbc\xbb\xff\x9a~}\xbc\xda\xcd>L\xcd\xf7\x1f\xfa\xbb\x9b\x8f\xcb\xc7\xd9\xfd\xa7\xa4\xec'\x9b\xd9\xe5\xc3f\xf6q\x9a\xce.\xaf\x06\xb3\x8f\xd3\xc1\xec\x9e\x18c_]g\xe3~\xed_\x8d<\x99/\xea^\xad\x1b\xd35\xdd\xbde\xce\xf6\xd6\xc6\xf1\x9d\xcd\xec\xe3\x83\xf5\xfe\xc3h;\xf3F\xfb\x99gd\xf4\xa9cf}\xf1u\xff\xdd\x17\xeb\xf1z\xdf\xf0\xbd{\xf3\xf9\xf1\xab\xf96r~\xbd\x8b\xe6\xbd\xfe2\x1b\xbf\xdf\xfb\xaf\xbd\xb9\xf9Y\xff\xed\xc351Nf\xe3\x00Q\xa7\xcc\x1e\xfb\xff\xc0\xb1\xf9\xf7\xe9\xe0\xd6|\x8b\xbf\xfe~\xb7q\xf0\xddf\xde\xdb\x12\xf3\xe2E87\xef6No\xb5q^]\\\xde\xee\xa7\xfb\xd9\xe5\x95q\xfdju\xf3\xf5\xcbM4\x0f\xb2\xb2eT\xf0\xb9\xb8\xf9\xf81z;\x0fn\xf4\xaf_\xac\xfbo\x9f\xf0\xd5o\x1f\xdef\xfc\xd7\xf6\x17\xfc\xf0\xfe\xe1z7\xbb\xbf\xd6\xdf\x7ft\x1eo\xee\xddW\xb3\xc7\xab\xdd\xdd\xc7o\xaff\x0fo/\xef>^\xeb\xb3\xcb\xe5nv9\xdd\xcf>:;\x82\xdf\xd5\xbcwc\xcc\xbf|^\xbbW\x0d\xbfoo(~z+\xbf|\xee\xac\xe7\x13\xec\xf8\xb8\xf7\xed\xcb\xdd\x1b\xc7\x1f\xa7\xd7\xbf\x16\xba|\xef\x8b\xe7\x85\xdb\xfb\xab\xfd\xec\xfe\xd6\xbay\xbc\xea\xdd\xe8\xd7\x8f\xf9\xbc\xf0p\xbd\xbf}\xb8y=\xbb\xbf\xdd\xbe\xbf\xbc\xda\xce.\xafw7\x8fW^\xc3O\xde\xfa7\x97\xa3\xf0\x1f\x97\xe3_\x7f{\xfc\xf4\xb2\x8d\xa6\xfd\xef\xe2\xe5v:\xbd{5\x9d^O\xa7\xcb\xcb\xe9\x87\xeb\xe9tuu1\xdd]]\xbc\x1c\xddN\xbfd\xe3\xe6\xed\x14\xf8\xdf\xd7\x8b\xe9\xed\x15\xf0\xfc\xfa\xeajzu1\x9d\xce.\x98\x82\x8b\xe9\xe5\xd5\xab\xa9~u7\x9d^]^\xf0<\xef\xae?\xbe\xbe\xf8\xf4\xe5\xea\xc3\xf5\xe6\xa5=\x9dn/\xa7\xb7\xd3WW\xb7\xb3\xbb\xe9\xe5h\x1a\xbe\x0f>~6n?^\x0e\xdf\xbeMV\xbf\x99\x9b\x0f3\xf3\xb7\x97/\xbf)\xcd/\xc6@m\x829*\xbe\xcf\xe6\xd7W\xb7\x0f_\x96\xbd\xe9\xff\xc6\xf7\xff\x7f\x1d\xdf\xab\xce\x01t\x1c\x9e\x8d\xad\x8asV\xcfH\xc9y\xab\x8c!U\xe7\xad\xc7\xcf\xbf\xe2\xed\xb7\x0f\xe3\x0f\xdf~\xbf\xd9\xb8\xbf\xbf\xbd\xcf|\xe9\x9b7{\xb6\xf8Y%\xae\xbfy\xfcj\xce\x1e\xde^\x15I\x97\x99!\x1f\xbf\xdb\xd7\x1d\x0d\xbf\xaf\xad\xfc\x9e-\xbeoOn\x1c\x15\xdf\xdf]\xb6\xf2\xfbN\xf1=\x1a\xbc5\x1f\xb2\x11\xe2\x91M\x96\xe8\x9f.\x93\xd9vv\xff\xe1.\xfc\xfa\x9b\xf5\xe6\xbf\xfb\x1f~\xbb\x99\xdf\xdd\x7f\x9e]\xdd\x1a\x8bWw\x97\xcb\x9f\xbd\xe0\xe5\xe0\xe7\xb7\xc6\xf4\xed\xa7]\xb2\x9c^\xbd\x99NM\xe3b\xfav\xf6A\x7f\xf3\xb5\x18\xcf?|\xfa\xfc\xfe\xee\x1f\xd6\xab\xaf\xd7\xd7\x92\x04J\xb3\x15C\x1f\x8e\xa1\x7f\x03\x8e\xcf\xccCwO=\xe0N\"\xb8\xf4A\x04\xd7\xa3\xcf\xcd\xb8\x98\xfe\x95\xdeZ\xae6\xe6\xe8\x87\xfc\x01\x9dE\x18\xfb\xf4F\xacA\xff\xda\xa3\x7f5\xe9_\xfb\xf4\xaf\x16\xfd\xeb\x80\xfe\x95?\x0b\xb4J}\xba\x15\xf9Nu\xb1\x89\x83|\xdb\xc3\xff\x12\x95\x96\xdbT\xa2\xe2\xc8N\x92m\x18\xbbB@\x8a\xc4\xbcS\xb4K\x85\x85\xeb\x98!,\xb64\xe9G\x1e\xbd\xc7c{\xf4.UH7\x9a>'\x101\xe7\x94\xca\xf3Q\xd4\xb3|\xd7\x93~BKPmK\xd2\x0fW\xf4\xaf\xb4-\xd6\xf8\x94\x0dH\xba7\xd8I\x84\x9cT\xcb\xf7\xd8\x0e\xe2\xf3%b\"M3\x06\xbbq\xb5\x9b\\\x9d0\xb2\x06\xdd\x9e\xf5BF5\xde\x19\x03\x96\xca\x18\x0e\xbb\xc3\xa1\x94\xac\xbf3Y\xaa\xa1\xbc\"s\xd7\xe7\xea1\xcd\xaeiJ\xa9\x06<\xd5`\xd0\x1d\xb4\xc8\xc6\xb7\xc8\xd2\xa5$\xa3\x9d\xc5U\xd3\xeb\xca\x1bd\xedF\\5\x03y5C\xbe\x9a\xa1\xd1\xed\xf7Z\xea\x19r\xf5\xf4\xe5\xf5\x18;\x83#a\xcf,2$\xc5\xc9\xb5C\xedq\xf6< \xf1:E\x934\x8c\xce\xf5I\\zd\xc9M\x9f`\xb4\xc8~'\xce\x0eT\xe7k\xb2\x9f\x1f5/p\xd1.\xfb\xe5\xdf\xff\xe5#\xd7\xb3;\x89\x13#\x14t\xec\xc0\xed\xfc\xe8{Ay\xea\xc0\xd4\x91\xff\xd3A,W\x90<\xa17d\xd4'u\x08\x80P\xadO\x00\x84\xed\xdd\x02\xaaM\xa9g\x00\x84*\x9d\x03\xaa\xaf\xbd\x7f@\x95)t\x11\xa8\xb2\xf6^\x02\xe9Q\xa5\xa3@\xb5\xb5\xf7\x15\x88J\xa9\xbb\xe4\x84\xcf\xdfc\x14\xbaL\xf9\xb0>\xbd3h\xe9G\xfeS\xba\x91\x7fb/\xe2\xe8\x14;\x11G\xa7\xd0\x87\xf8\xba\xd4\xba\x10G\xa7\xd4\x83\xf8\xda\x14:\x10_\x95J\xff\xe1\xabR\xe8>\xbc\x06\x95z\x0f_\x97B\xe7\xe1\x89\xd4\xfa\x8e\xff\xe7w\x9d\xb6^\x82\x9f\xd2K\xf0\x89\xbd\x84\xa3S\xec%\x1c\x9dB/\xe1\xebR\xeb%\x1c\x9dR/\xe1kS\xe8%|U*\xbd\x84\xafJ\xa1\x97\xf0\x1aT\xea%|]\n\xbd\x84'R\xeb%\xf8\xbb\xf4\x12\xb2^\xcf_\x1e\xe8c\xa0\xb4XN\xb8A1y\xce>?W\x9d?\xfd\xbf\x9e\x1f\x85qj\x07)K\x12\xa4\xb6\x17\x00D\xf9s\x82\xac}\xa6;\xf0\xc2d\xd3\xee)\xf2\xc0t\xacH\n2)\xcc\xbe\x85\xa0\xfeirBd\xc7\x89)\x94\x08\x9f&\x11D\xc6IDQ\xce\x97\x9a\x83\x82\x94v\x9d\"\x19t\x1e\x84\xe5O\x13\xa2\xac\xf6sn\x90\x98/\xb54\x8c\x8e\xe6\x93\x86\x11\xc7'\xef4Gs\xe2;\xc5\xbc\xea\xc7G\xf3*\xc88nY\xe7=\x9a\xd7\xf1\x8b\xab\xda*L_P\xaaN`\x98SX ms\n3\x89yNa'\xb1\xd0)\xec\xda\x82\x12\xd5\x11\xa51\xdd\xf1N'\xb2\xdc\xf1\x9c\xc4\x86;\x9e\x97\xccn\xc7s\x93\x99\xedxnmV\x93\x1a\x08\x1f]\x9d\xc8@\xc7s\x12\x1b\xe8x^2\x03\x1d\xcfMf\xa0\xe3\xb91QL\xb7<\xfe\xce\x1f\x83\x07a\x1aqL\x1389O\x94\xc2\xe4zMt\xfc\x18\\\xf1\x08\x92\x13\x84\x05\xa9\x14\xe4%\xe9\xda|[uD\xaa\x98\xfb\xa7\xb4\x03 Ri\x86\xaf\xdc\n\x89\xc0\xf8\x14\x81\x01\"\x15\x811)0\xed\xfb6}\xcf-g9)\x1f\x95\xd18s\xbb\xa7;O+\x9alt\x00\xe8\xb2\xc7\"\xda\xfa^]1\x1e\x00\xd4E\x81\x88~N\xdf_\x86\x18\x94%\"\x0e\xb8\xe2\x90wz\x80>\x7f.\xa2\x0e\x80{\x81\x94\xba\x8e\xef\x8bs;\x9f\xd2\x8f7\x03Av\x8a%\x08\xf2S\x8dA\xb08\xdd\x1e\x04\x93\xd3L\xc2\xa9\x0f\xb2\x8a\x82Y\x14\x86\x9b\xb9\x9d\xcd\xe3'\x98\xca\x7f\x92\xa5\xfc'\x1b\xca\x7f\x06;\xf9O4\x93\xffT+\xc1\x06\xc1'\x19\x04?\xc9 \xf8\xc9\x06\xc1\xcf`\x90'\x0ee\xac\xe6@\x83\xd04Zq\xd5\xaf\xa2\x13\xbc\xe3 \xc3\x05\xc8\x8eA\xb0a\x18\x1c\xd8\xb5\xe3\x07m\x19\xdb{\x06k\x9a&\x87\xf5=\x17\x82Z\x96\xc5A\x01\xd8p8\xe4`\x89\x877\xcd\x85\xef\x128\x1e\x8f9 .\x8c\x0d\xc1m\xdb\xe6%\x0d\xc3\x00\x92\xc1q\x1c\x01k\x00\x8c\x10\x82u\x9b\xdf\xd2d\xc0\x8b~\xf6\x87\xc3\x83P\xf6&g\x85\xd3\xc6:\x0d]%\xd8\xfeQ?\xd3_\x9ce\xb1\xf8Yw\xfc\x93\x80p\xd4B8\x12\x11\x0e[\x08\x87\"\xc2A\x0b\xe1@Dh\xb5\x10Z\"\xc2~\x0ba_Dh\xb6\x10\x9a\"\xc2^\x0baODh\xb4\x10\x1a\"B\xdd\x92\x13\xeaB\xed\xe8\xbd6\xd2\x9e\x98\xd6h%6 \xea|\x8c\xe1\x9c6^\xces\xda3\x1dt\xd8\x82\x88uX\x92\x08p\xd6\x82\x88uV\x92\x08p\xd4\x82\x88uT\x92\x08p\xd2\x82\x88uR\x92H\xa8\x08\xd6AI\"\xc09\x0b\"\xd69I\"\xc01\x0b\"\xd61I\"\xc0)\x0b\"\xd6)I\"\xc0!\x0b\"\xd6!I\"\xc8\x19K*\xd6\x9f(2\xb1+\xf1\x8eH\x11\x82N\x98O`1r\xd9\xc1{\xa8\xf7u~\x9c\xe5\x81\x8bE\xdf0\x07\x82Y\x01\x82\x0f{\x16?\x89\x84\xb1\x1d,\xf9\x81~`\x02\xf3\xf32\xc4<\xd7\xf9\x10@\xee\x11\xc6\xe1\x96\xc6\xf2\xaf\x0e\xa8\xa5\x85\xe0\x7f]\xcc\x17\x86\xcdO\xa8\xd1:\x8e0+\xb0\x85z\x8e\xcdO\xe6\x05w\x90\xc2\xee\x0f\xccE\x0f6J\xe4\x05l\x04\xe2Z\xba>\xe2\xad\xb2\nS\x08\x9d\x99f\xce\xcf\xa9 r\xa4\x0b\xa7v\x10o\x9b.\x1f\x8e\x94\xc1\x10B\x01\x837\xcc\xe1\xd0\xe2\x9b B\xc7\xf6x\xc8\x0b]E\x19<\xc1\x18\xa1\xb9\xc3\xeb$\xb07l@\xa2\xeb\xc6\xbc\xcf\xb3\xce\xa5\x9e\xe35k\x1b]\xef\xf7\xc7|\x08\x03 Mk\x88\\\x91W\x01\xf8\xf1\xc0q\x80 &\xc7\xa3\x04$q\\\x04\x91l\xedd\x85\\\x88`1X,\x16\xbc\xf4%\x01\xa4H4Z\xb8\x0b\xde{K\n\xb8s,\x16\x0e\x9a\x8bH\xa0\xde\xef.\\\xbe\x15d:\x91\"\x10f\x88\xe6\x9aV\xbe\xea\x84&\x80\xde\x7f\xd2\x9d\xc7\xf5\xd0\x1d\xdb\xae\xb7N\xce\xd9\xa1\"6\x18@\xd7\xe8Y1b\xd3\xadq\x8f\x85\x81(\x93EA\xa0>\x032\x00\x8cf\xe8\xac\xe4@R9\xd6\"\x0fc\x067\x1e\x8f\xc7\xc0\xea\xaf\xdew+\xc0y\x92<[iUz!\xd7\x90\xc5:P\xa41\xad\xd8U,\xe0UV\x1bbU\x96\xb5q+\xf7\x16[\xe4\x82*\xe2y\x15\xdb\x81\xa2\x96\xc8\x05kO\xb6\x1cX\xe7\"\xd3Q\"\xff\xe21\"\x17\x03\x90\xb0\x97\x01@\xd0\xd1x\x9c\xc8\xd7\x00\xa4\xc8\xddx\xa8\xdc\xe3\x98\x8c\xdfS\x9c\x8eO\xdd=\xd9\xefT\xa4Sw=\x86\xdb1\xde\xa7\xe0~*\xb9\xbeX'\x12oB\x97d!B\x8f\xe4\x80\x02\x87\xe4p\xb0?\xb20\xa1;r@\xa17\xb2\xc8\x16g|\xb6\x01\x90\xcbN>\xdd\x15\xdbe;\xc2\x13\xfd\xef\xe3\x88\x02\x9fc'!\xc0\xe7X\x88\xd0\xe78\xa0\xc0\xe78\x1c\xecs,L\xe8s\x1cP\xe8s\xc7M\xb9,\xbc6oc \xa2\xa0<\x9e\x06\xfb\x1c\x9b\x80}\xba\xcf\xe1\xe7\xf49|\xb2\xcf\xd1\xfc4\xadx d\xc5\xaeH\xf5\x02/\xe5-\x82\xf8,\xe4d\xa0\xf93\x0eZ\xdeF&\x91\xc0&f\xb6\x84\x08\x03D\xe3\xf2w\xd4\xb5\x0f\xd1\x07\xb8!\xdcn\x8f\xb4-\xd8\x92a\xb5\xc8(\x1cDd\x17\x1e\x08\x9b\x86\xc7\x81\xd6\xe1`\xa0\x818\x14l#&\xee\x15\x9a\x89\xdb\xbe\x17Z\x8a\x0f\xf5\x85\xc6b\xf7\xe2\xebm\xc0v\x83\xa9\x0cl[\"\x1a\x15\x1a\xd1W\xb4!\x8b\x13\x98\x90\x85\xc1\x16\xf4U\x0c\xe8+\xd9\xcfW3\x9f\xafj=68\x16\x1b\xcf?\xc1v\x023\xe1V3aE3\xb18\x81\x99X\x18l&\xacb&\xacd&\xacf&\xacj&6\x9e\x14\x9b \xc3f\xa2\x80\xc9\xcav\xc3\xadf\xd0\xd7\xba\xf3\x87\xe7zG\xef\xf4\xa3]\xa7\x17\xed:\xf4\xa6\xcbD \x05\xd6\xd4\x13\xd54R\xaa F\x815\x99PM\xbd\x92\xbe\xbd]r$Xc_Vc&\xb9\xaeP\x1f\x84\x03k\xb3\xa0\xda\xfa\xa5\xc4m\xb5\xc9p\n\x83\xf0\x01t\xa2lT\xff\xd3\xfcHR\xd9\xf3\xbb\x92\xa0\xb2\xef\xebM-\x95\xb6\x99\xf8x\x87\x12T\xf8,>\xa5\xe0T\n3{\xedi\xfe\x9f\xe8h\xc2\xba\xbe\x83\x9f\x81u}g7\x93\xd6\xd9f\xf4\x13\xbc\x0c\xac\xefOp2\x99?\xe1?\xd1\x9f\x84u}\x07\x7f\x02\xeb\xfa\xce\xfe$\xad\xb3\xcd\xbe'\xf8\x13X\xdf\xf3\xf8\x13Ua\x14\xa3\xfa\x0b\x1e\xda.\xff\xb4E\xfdq.m_~\x08\xa8\xf9\\W\xe2\xc4!\xa6?%\xd2\xcdb@=\xff\xe6\x11\x13\xb0\x15Q\x9f~\x80S\x89E\xa4\xa7W\x9fRb\x8a\xf3\xf0N?\x14\xe9I\xbe>#\xaf\x8f\x0fa\x8b*\x8d\xb2J \xc4-j5\xaaZyD^\xb1QT\xcc\x97fu\xf7\xf2\xba\xf9\xc8\xb8\xa8\xbbW\xd6\x0dD\xceE\xdd\xbd\xaan\x1e\x91\xd7\xdd+\xea\xe6K\xb3\xba\xcb\x86k\xa2\x96\xd7M\x07\x10e\xfdM\xe3\x01L.A\xd5|\xa0<\x97\xa1P\x80&\xd2@\xad\x02\x00Q\xc9P+\x01\xc0\x142\x94j\x00\xca\xab{\xd4\x9a\xb6\xf00>HoS+\xcc\xd0\x07\xde\x99\xb3\x98\x01\xf0\xe7\xc2'\xb3B\xc8-Ko\xcf\x8a\xa5\x0e_\xa4 \x9f\xcf\x1d\xbb\xaa[\xe4\x99u\xf5B\xe7o$\x10\xfb?!\x84\xc0\xc9+9D^Z\xcb!\xec\x08\x8d\x1c\xe2\xbe@\xc8!r\xf8J\x10\x89\xcf75\xc9\xdc\x9e\xa8K\xec\xf9u\xb3\x84\xce_\xcb#\xf6\x7fB\x1eI\x17 \xe5\x11\xf6\x82F\x9e\xb6\x8eP;\xad\xb0/(t\x06\x85p\xb5\xe8!\xbe\xa4\x83\xf8\xd2\xfe\xe1\xb7t\x0f_\xda;|y\xe7\xf0\xdb\xfa\x86\xdf\xde5\xfc\xb6\x9e\xe1\xcb;\x86\xdf\xd6/\xfc\xf6n\xe1\xb7\xf6\n\xbf\xb5S\xf8*}\xc2W\xe8\x12~[\x8f\xf0[;\x84\xaf\xd2\x1f|\x85\xee\xe0\xab\xf6\x06\xffI\x9dA\xe8\xf7X\xe2\xf7X\xea\xf7\xb8\xc5\xef\xb1\xd4\xef\xb1\xdc\xefq\x9b\xdf\xe3v\xbf\xc7m~\x8f\xe5~\x8f\xdb\xfc\x1e\xb7\xfb=n\xf5{\xdc\xea\xf7X\xc5\xef\xb1\x82\xdf\xe36\xbf\xc7\xad~\x8fU\xfc\x1e+\xf8=V\xf5\xfb\xb6\x80\x88&v\x16\xe7\xf6\x82}5j\xf6t\x8e\x16a\x8c\x0e\xe5\xc7{\xcf\xff\xd2\xf9\x0b\xfd\xe5A\x98\xcd\xc1\xc1\xc8\x8e\xcf\xe7a\xbab\x01\x87\xbf=\x86\x99o1\xcfqI\x92I\xc7\x14U\xdc\xf2\x960esqMAYt\xd2N\xb9\x93O\xa3b\x91\x9aRP\xaa\xa6\x18\x12\xac)U\xd8 V\x9d\x8e\x9dl\xa8\x93\x08\xecK\xe5\xf5e\xe2\xfa\xea\xd2\xc2\x82\xc9\x8c[\x17\xc2\x82a\x99`\x98\x12\x8c*u\x03\xd9\xe7\xfc<\xe6S\x81L\xf1\\\xf2A\xc2\xae\xeb\xcd\xdb?4\xd8u\xbd\x94E\x01\xfd\xc5m@`\xa9C\x17k\x0eb\x17\xddn\xaa\xc5\xe1\x96\x81\xc5\xe1\x16Bi\xcb8\\G<\xb6x\xceQ8!^\xfb\x01+A\xfeP\x80\x05+ \x8b8:m\xe1\xed\x90{(\x90\xd8\xde\x87\xeb\xf4<\x7fD\xbc\xfeJ\xa1\x7f\x1c\x18\xdbg=Lf~\xb2\x1c\xf6\x00\x12\x01;\x01\xcfC\xe0\x07\x00\x1046\x89\x83\xbd\x81C\x08\x1d\x82GJ}\x02\x84K\xdd\x02\x10\xa5\xdd3DDR\xe7\xc8\xd73R\xffPp\x10\x85\x01\xd4\xcd\x06:\xa9\xd3\xf8m>\xe3\xb7\xb9\x0c\xcbA\xe41\x1c\x0ev\x18\xbf\xcd_|Uwa\x81ro\x01\xd0rg\xe1\xe4P\xf0\x15\x98F\xee*\xfe\x93<\x05v\n,w\n\xdc\xe6\x14\xb8\xcd)X\x0e\"\xa7\xe0p\xb0S\xe06\xa7\xc0\xaaN\xc1\x02\xe5N\x01\xa0\xe5N\xc1\xc9\xa1\xe0\x140\x8d\xdc)p\x9bSPt\x0b\x8cvu%D\xee\xbd\x0e{5?\xd12\x10\xf9,\xfb\x9dfS\x9a\x08\xe4V\x99\x99aJ\x90\x90E\xc4c^R\xcd^\xa7!\xb5E\x90==7&\x95\x94\xe7F\xc7\xe8\xe4\xd9|\xfa\xb7\xc6\xeb\xf5\xfc\xe7\xea\x85\xa9@\x15\xf9\xe1S\xae\n\xbd\xa9\"\x7f\xe7A\xfd\x13\xc0\xa1\x8c$H\x1ea\xece\xeb\x89\xea\x0b\xe3\x13\xb2\xcc\xf5\xe2\xe2\x95\xff\xe5\x17\xcb\xeb\x9a\x88\x92\x82\xe5\x04|\nH\x90\xc5H@\xf5\xab0\xf6\x1e\xc3 =A\x808\xdc\xb2\xb5s\xfd#/\xdf\xc6vt\xa8\x19d\xbf\x9dg\xffL\xe8_A\xbd\x03\xa4\xc5\xc3 \xfb@P\xaf\x16\xa3\x0d\x8a\x13\x04\xd4_\x15M\xe0\xc7B+6,\x8f\xb6fU\xa3\xd0\x9c\xb4L\xa2R\xd8\xbc2\xb9Z\xcd,\x91\x8c`\x0d\xd8\x1b\x96\xc9K\x91\x9fhIj\xc7)%N\xf1\x19\xfd\xfcyS\x15\xf90\xff9\xff\xbcy\x92\x8f)\x05\x0f\x889\n\\\x805\n\\\x96q\xf6\x88c\x8b\x02\x17bZ\xbe\xe8\x93\xe7[\x14\xb0\xac\xcb\xa7$\xf7\xe2\x11\xc4{n'(\x1b\xc8\x00\xeeU\x11\xcb\xbf~N\xd6P=\x845\x1e\xa3\xd4Y\x81:\xcfKx\xad\x17\x8f\xc9\n\xcag4\xff\x04\xe1Ee\xd0\x8aE\x06\x07\xac\x97A\x85\xc6\xcb\xf9\xe4\xb6\x03\xb84\xa6jxp\x96\xca9T\x86\x02\x98PF\xc9\xf9@6\xc9\xb94&\x01\xf80\xca\xcf9\xc1\xba/uS\xaa\x1e\xd4\x0e\xa9\xe5\x9c\x13\xa8\xe4\xfbu\x92z\x8b=\xd0q\"\xdby`\xfb\x0d\xf1\xac\"\xac\xb2T\"\xedW8\xb6\xf3\xe4\xac\xa8\xbeS?\x01YsF\xa9Q|\x07\xca9\xb1\xfd\x87|\xc8\xd6\x00\x99\xab\xc2\xccQ\xbaE(\xe0+(\x01L\x0d\xd5S\xb6\x8a$\xb2\x1dT1\x83k\xb2\xf3\xd74\x1eh~\xae\x97\xa4\xb17_\xa7H\xc0\xb2\xa0\xa29\x96\x08\xb6\xf7\xe4A\x0da\xc3\xc29\xda,X1\xa3\xbaP\xc3\xaa\xe9Ar{Ul\xd8~\xd4p\xa2\xba\x91\xcc4\x15\xab\xda4<\xaf\xca\x0c43\x89\x11*\x9e\xac\x11\x1a\x96\x84% \xaer;0=\x95\xb4\x04\xd9Qk\x96P_-\x0e\xdf\xea\xccl\xebz\x81\x8d\x8bh\x9c\x88A\xb5\x1c|\xaeO\xca\xffB\x9c\x0c \xa7\x1e\xcb\xc9(9\x19\x10\xa7\x9e\x84\x93\xc9r\xea\x95\x9cz\x10'S\xc2\xa9\xcfr2KN&\xc4\xa9/\xe1d\xb1\x9c\xfa%\xa7>\xc4\xc9\x92p\x1a\xb0\x9c\xac\x92\x93\x05q\x1aH8\x0dYN\x83\x92\xd3\x00\xe24\x94p\x1a\xb1\x9c\x86%\xa7!\xc4i$\xe14f9\x8dJN#\x88\x13\xb6\x93T\xe6\x9cz\xf6?\x96\xe38\xfb\xdf\x84\xf8\x19\x085\x97Y\xd4\xa7\xcb\xd6C\xe5\xbbm7\xe8\\\x9f\xd4$\xe0\xca*\xe7e\xc8\x96o\x0d/\x83\xe0e\x00\xbc\x92U\xec\x05\x0f\x99d\x15i\x80\x966)F\x81\x00\x05)\x89\x0d\x80\xd8\xa0\x88\x0d\x85\\\xdb\x81\xe7O\xe4\xfd\x88\xc6\x9e\xbe\xa4\x86\x18>\xf7\xaaZc\x0e\x0c/\xbe\xcb\xc2\x1a\xac\xe5\xf8\xb55\xcbFmA\xf6\x9c\xcbk\x81\x04\xadK\xafgZa\xe7\xd5W<\x8e^d\xf3\xd4\xa7\xad\xb3a)\x9e\xba\xd4>\xcd\xb8\x7f\xcaj\xfbT\xab\x7f\xbf\x057+\xd1\xf3\xae\xb9a\xee\xcf\xb2\xec\x86Y?\xe3\xca\x1b\xae\xe0\xb9\x17\xdf\"\xfd?\xd7\xfa\x9b\xeabOY\x82\x8b\x18\x1d\xbb\n\x17\xf19a!.bu\xdaZ\\\xac\xa9\x13\x96\xe3\xacY\x9f\x7fE\x0e\xd6\xf0|\x8br\x90\xfd3\xaf\xcb\xc1:\xbe\xd3\xd2\x9c\xb2\xee3\xad\xce)\x9eO^\xa0\x0b\xb8\x9d\xb6F\x170;u\x99.`\xf7\xc4\x95\xba\x80\xeb\xd3\x17\xebB\xc3\x1c\xbb^\xe7\xe7\xeb',\xd9\xe5\xcc\x8e\\\xb5\xcb\x99\x1d\xb9p\x973;r\xed.gv\xe4\xf2]\xce\xec\xc8\x15\xbc\x9c\xd9\x91\x8bx9\xb3#\xd7\xf1rf\xc7/\xe5[\xfc\xf6\x89\xaby\x96\xfb\xe2i\x0bz\x90\xddS\xd6\xf4T\xf7?aY\x0f\xd3\xb3+{\x85\xa5\xbd\xc21\x9a\x9c\xa7\xff\xcc\xcb}\x9e\xdf\xb3\xaf\xf6\xfd?c\xb1\x0fTr\xc2Z\xdf?a5\xf8\xacK}P\x80\xd65\xdfs\xad\xf4\xfd\xa7,\xf4Y\xe2\x13\xd7\xf9\x90\x0cO^\xe6\x9fb\xd7?g\x95\x7f\x9a\xc1\xbf\xe3\"\xdf\xff\x9ek|\x88\xf9\xf3,\xf1!\xce\xcf\xb9\xc2\x87\xf8?\xfb\x02\x1f\xd6\xfd\xb3\xad\xef\xfdgZ\xde\xc3|\x8e^\xdd\xc3lNY\xdc\xc3\x9cN\\\xdb\x8b\xb4t\xca\xd2\xde\xff\xde+{\xa0\x82g\\\xd8\x03\xdc\x9f{]\x0fT\xf1\xbd\x96\xf5\xfe\xf3\xaf\xea\xfd\xe7\\\xd4\x83\xccN\\\xd3\x83\xbcN^\xd2\x83\xdc\x9e\xba\xa2\x07\x99>\xc3\x82^`\x93\xa3\xd7\xf3\xec\xcc\xfc\x94\xe5\xbc\x8c\xd7\xb1\xaby\x19\xafc\x17\xf32^\xc7\xae\xe5e\xbc\x8e]\xca\xcbx\x1d\xbb\x92\x97\xf1:v!/\xe3u\xec:^\xc6\xeb\x84e\xbc\xd4]\x9f\xba\x8a\x97\xae\xae\x8e^\xc4K\x17\x84'\xac\xe1\xfd\xa7-\xe1!\xf2\xe3V\xf0\xa2\xc5:~\xe6\xc5:\xcf\xef\xd9\x17\xeb\xf8\xcfX\xac\x03\x95\x9c\xb0X\xc7',\xea\x9eu\xb1\x0e\n\xd0\xbav{\xae\xc5:~\xcab\x9d%>q\xb1\x0e\xc9\xf0\xe4\xc5\xfa)v\xfds\x16\xeb\xa7\x19\xfc;.\xd6\xf1\xf7\\\xacC\xcc\x9fg\xb1\x0eq~\xce\xc5:\xc4\xff\xd9\x17\xeb\xb0\xee\x9fm\xb1\x8e\x9fi\xb1\x0e\xf39z\xb1\x0e\xb39e\xb1\x0es:q\xb1.\xd2\xd2)\x8bu\xfc\xbd\x17\xeb@\x05\xcf\xb8X\x07\xb8?\xf7b\x1d\xa8\xe2{-\xd6\xf1\xf3/\xd6\xf1s.\xd6Af'.\xd6A^'/\xd6AnO]\xac\x83L\x9fa\xb1.\xb0\xc9\xd1\x8buvf~\xcab]\xc6\xeb\xd8\xc5\xba\x8c\xd7\xb1\x8bu\x19\xafc\x17\xeb2^\xc7.\xd6e\xbc\x8e]\xac\xcbx\x1d\xbbX\x97\xf1:v\xb1.\xe3u\xc2b]\xea\xaeO]\xacKWWG/\xd6\xa5\x0b\xc2\x13\x16\xeb\xf8i\x8bu\x88\x9c[\xac3\xf4\x87\x05\x0e\xed4\x7fG\xce\xe4\x0fz-\xcc@\xe3\x12\x9a\xbf1\xa7\x05\x1b\x94\xd8\x93\xde\x82\xb4\xc8\xdf\x82\xa4.W\x83V\x12\xad\x81+\xbcYH\xfd\xfc\x81\xe6\x1f#\xb2\x7f\x94\xc4\xbe\xba\xc0\xb0l\xc7\x98\xb9\x06\xab\xc9\x86)\xd9\xa8\xd2\xc4\x0e\x12-A\xb1\xb78,\xc2 \xd5\x16\xb6\xef\xe1\xfd\xb9fG\x11FZ\xb2OR\xe4\x9f]`/x\x98\xd9\xce\x87\xfc\xd7\xd7a\x90\x9e\xd9\x1b\x14xq'@\xbb\xea\xe7\xb3\x15\xc2\x1b\x94-r\x9b\x9f:\x01Z\xa3\xb3\xf5|\x1d\xa4\xeb\xb38\x9c\x87ix\x16d\xff$h\x19\xa2\xce\xda;\xb3c\xcf\xc6g\x8d\x14\x8ct\x9c`K\x14\xc6K\xcf>\x83\xc0\xb9t\x9a\xa0E\xc2*J*\x9e\x80\xc7:\xa1\x8b\xa8\xf7\xa0e\x0f(\xa2Wa\x90\x84\xd8N\xce\xfc0\xb0\x9d0\xfbO\x98G\x13,\xa3u\xec\xa1\x98!\xcd\x9fun2\x95\x96\x00\x11}\xad`\x8a\x03\xa3\xf6\xc6\x1e\xa2\xb6\x17\x86\xa3x\x00v\x15R\xa7+\x84\xed\x84&/\x9e\x9dI\xccT\x16\xa9Z5\xf5|D\xd7\x91?\x81\xa0\xf3\xd0\x0d\x03\x8f\xc2^\xe4\x8f:\xb3\x8f\x10\xde\xb1\xb1\x97\xa4!m\x85\xe2\x99\x80bi\xc7\xb6\x1f\x06.-|\xf9\x10\x14\xc9N\x1eP\xbc\xf10\xa6\xfd\x84x\x0e\x91\x95\x8d(>\xa1\xe5\xa56\xf6\x98\x0f_/\x12\xad\xc8\xc3\x91\xc0\xe2\x89\xc2`I\x8f=\xf9;\xafT\xebc\xb0e\x95\nu*\x0c\xd0^6\x88\xaa\xca\xe1\x1f-\x06X#V\xaf\x11\xd25\x8d%M\xb2-r\xc8}\xee\x93\xefT1\xf7E\xf8\xc5\xd6\xa0\x00\x06\x0f\xe8Q\x80\x1e\x0f0)\x00\xf7y\xfa\xc5\xb6/\x17q\xb1\xb5(\x80\xc5\x03\x06\x14`\xc0\x03\x86m\xcd\x1cQ\x80\x11\x0f\x18S\x80\xb1~\xfc\x9b\xba\x19\x8f\x15Z\x84E@Fa1\x90]X\x0cd\x1a\x16\x03Y\xa7U\xe2E\xf1\xb9\xb36\x1b\xb1\x18\xc8L\nm\x1f\xb1\x18\xc8X,&\xb3\x97\x82\xc1\x14F\x05\xba\xbf\x8b\x8d\xe8\xb7\xb5\xc3` \xa0 \xfdv\x0b\xfa\xed\x06l\x11v\x91\x7f\xed\xac\xd5|~\xbb\xf5Z\x1b=b \xa0\xed\xfc#M'\xb6R\xdb\xe0\xc7\x00@+\xe1v+\xe1v+\xe1v+\xb5\x08\xbb\xc8?v\xd6j%\xdcn\xa5\xd6F\x8f\x18\x08h%\xcc[\x89\xc2xA\xb4N\xb5\x18%\xa8\xb9\xdfnG\x11\xb2c;p\x8a/qN4?|d\x1f2&Z\xa7i\x18\x14l\xce\xcfs\xfc\"t\xd6\x89\xe6\x05\x01\xfb\x16`\xa2F\x1eZ~\x86\xed\\\x9fD\xb6\xebz\xc1\x92]\x18\xaf\x8cC\xb9\xd1\xca\xbf>y\xd5\xab\xca\xf8\xd7\x19\xaf\xcc\xaa\xac\xcf\x97\xf5\xab\xb2\x11_f\xd5\xf5\x0d\xf8B\xadW\x17\xf7\xac\x17l\xa1\xa5W\x85\x16\xfb\xa9\xe5\x956\xac)\x87<\xa5\xa1\xd7\xa4\xfcg\x9a\xf3\xcd\xe6\x1cBl;\xf3\xb0\x0d-\xddf\xc5\x15\x93\xf2\x01\xc5\xa4\x84@1-#\x0b\xc8D\xdb@R\xb2\xc0U\xf1\xce\xb9\x12\x90\xfd\xcc\x96{\xc1\n\xc5^ZA\xca_\x15\xe6\x89\x03\xe39\xd9t#q\x1e\xa2\x18\xf2\x1f\xa2\x18r!\xa2\x18\xf2\"\xb2n\xd8\x91\xc8\xea!_\"\xcaAw\"\xcaa\x8f\"E\x10;U\x86j\xf7+JX\xd0\xb5(qA\xef\xa2\x04\x86\x1d\x8c\x16Y\xecc\xbc\xd0\xb0\x9b\x11\xfc$\x9eF\xa0*gS\xf06\x85\xa8d\x95E\x132\x0f\xf4\xa5\x0e\xe8K\xfd\xcf\x97\xba\x9f\xdf\xe6}\xbe\xdc\xf9|\xb9\xef\xf9-\xae\xe7\xabx\x9e\xaf\xe2x~\x9b\xdf\xf9mn\xe7\xb7z\x9d\xaf\xe6t\xac\xbc\x02\x9f\xf3U\\\xce?\xce\xe3`\xe7\xc2R\xe7\xc2R\xe7\xc2R\xe7\xc2R\xe7\xc2m\xce\x85\xe5\xce\x85\xe5\xce\x85[\x9c\x0b\xab8\x17Vq.\xdc\xe6\\\xb8\xcd\xb9p\xabsa5\xe7b\xe5\x158\x17Vq.\xcc9\x17\x05Lc\xdby@\xee\x01\xa34E\xb1\x96D\xb6\x93E^]\x83\xfb>E\x01\xd4\xd2\x8c\x19\x0b\xd7\xba\xba%\"\xf0\xd1\xd2\xe6\xd8\xf72x\xfb\xb8z\x009\xe6\xdf/:F\\\x80\xa2Mb\xa8\x92\\h\x05\xa9\x15f\x83\xba\xaac[\xc2\x11\xb46\x84\xafB\xa1\x1d\x12\x91\xf1\xb1\"s\x04\xad\"\xf3U\x14\"S\x14x\xa5%!\xf6\xdcC\xbe\x8f^u\x16\x0e\x93z)F4\xa6\xdb\xb38\x98\x13F{\x06e)\x98\xfa\x00\x8a\x94;O\xbbT\x1cL$\x18\x0f\xb4\x9e\xc9\x0fk\x89}%\x81}EyY\\\x9b\xb82\xc9\xb0\x92dXQ2\x16g\xb1^\xe5\x05\x0f\x87\x14\xedR\xcdEN\x18\xdb\xe5 Vv\xd1\x9b\xc1\xce\xb8'\xe7\xb6\x93z\x1b\x04\x14\xe4\xcb\\\xe0\xf9*\xdc\xb0k\xe4\xfc\xb9\x80\xff\xc6K\xbc\x145o\x1cMc;H\xbc\xea\\g\x18w\xba\x86\x95t\x90\x9d \xcd\x0b&\xd2R\xbe=\x85\x90\x87p\x9df*:7\xa2]\xc7\x0d\xd3\x14\xb9\x1dg\x1d\xc7(H_eLX\xba$=d\xff\x14Yn-\xddGP\x8e\xc0\xdf\x16\xab\xc1\xda\x15\x81\xd9zk\x90\xe5\\,\xe1o{D9\x1f\xc6\xf8[\x93(\xe7\x03\x19\x7f\xdb'\xca\xf9P\xc6\xdfZd\xfd|0\xe3o\x07\x04\xc0\x84$\x18\x92\x12@U\x8c\x08\xc0\x00\x92qL\x00\xc6\x90\x0c\xc5+\xd4\x1b\xd0I\x9b\xf1\x859\xf2\x85\x93\xdc\"\x0c\x042\n\x0d\x01\xedBC@\xd3\xd0\x10\xd0:\x8c,\xa0\x81h\x0cl#F\x1a\xd0L4\x06\xb6\x14\x8d\x11\x1b\x8b\xc6)\xec\xf6\xab\x8e\xdd\xa5\x15\xfdV#\xfa\xad6\xf4[M\xe8\xb7Z\xd0o5\xa0\xdfn?\xbf\xdd|~\xbb\xf5\xfcv\xe3\xf9j\xb6\xf3\x8f3\x9d\xd8J\xb8\xd5J\xb8\xd5J\xb8\xd5J\xb8\xd5J\xb8\xd5J\xb8\xddJ\xb8\xddJ\xb8\xddJ\xb8\xddJX\xcdJ\x98\xb3\x12\x05\xdb\x1a\x07\x91Z\xb7\xbd\x83H\x9f[\xf3 R\xe4\xb6\x7f\x10ipk\x1d\x84\xaa\xcb<\xa1*e=`\xab\xf5\xaa\xb2\x1ePVq\xe5\xd6\xd0[\xcd\xac\xe8L\x9e\xce\xac\xda`\x9a|Y\xd5\x08\xb3\xcf\x95\xf5+\x9e}\x9e\xa7U\x95q\x0b\xf6\xad6\xa8\xca\x06|\xd9\xb0*\x1b\x02eU\xfb\xb8U\xfeV\x1bUt#\x9en\\\x95\x8d\xf9\xb2,\xe0\x10\xf5\xb7\xad\x96\xae\xbc\xd8\xad\x95\xd35\xb3\xff\xf1\xa0mX\x00\x93\xaaY\x83\xee`0\x18\x0c9d\x9e\xc7.0\xf9b\xbc}\x80?0.\x9aM\x13b/mJ!GmJ!_mJ!w%\xea\x85=\x96\x00@NKH\x06\xf9-Q\x0c\xb9nS\x0cz/Q\x0c90Q\x0c\xf90\xa1\x16\xc8\x8d\x9bb\xd0\x93\x9bb\xd0\x99\x9bb\xd0\x9f\x89b\xc8\xa5 \x9b@^\xdd\x14\xc3\x8eM\xdaD\xe0\xdb\xa4\xeaZ\xdd\x9bh\xab\xcc\xc3\x1bX\xee\xe4\n^\xae\x10\xc6\xe4\x01\x8a\xc4\xf3}\x99\xe3\xfb2\xbf\xf7en\xef\xb7x\xbd/uz_\xea\xf3\xbe\xd4\xe5}\xa9\xc7\xfbR\x87\xf7\xa5\xfe\xeeK\xdd\xdd\x97z\xbb/uv_\xea\xeb\xbe\xd4\xd5}\xa9\xa7\xfbrG\xf7[\xfd\xdc?\xc2\xcd}%/\xf7\xd5\x9d\x1c\xf6g,\xf3g,\xf3g,\xf3g,\xf3g\xdc\xe2\xcfX\xea\xcfX\xea\xcfX\xea\xcfX\xea\xcfX\xea\xcfX\xea\xcfX\xea\xcfX\xea\xcfX\xea\xcfX\xea\xcfX\xea\xcfX\xea\xcfX\xee\xcf\xb8\xd5\x9f\xf1\x11\xfe\x8c\x95\xfc\x19S\xfeL!\xc2\x0d\x8a\x178\xdcj\x1b/\xf1\xe6\x18\x1d\xaa\x07\xe7\xe5\x03\x01|\xe5\xb9.\n\x1at\xf1\xbb\x00\x9c8q\x88q\x03.~\x17\x80\xf3H\xaa\x86\xf2;\x1b5p\xc7\xc9\xac\xedZ\xa4\xde\xb1rk;\xb9\xe4;Vvm'\x97~G\xcb\xaf\xedd-\xd8\xf3-\xd8\xb7\xb4`\xcf\xb5`/o\xc1\x9ek\xc1^\xde\x82=\xd3\x82\xfdi\x01-\xebXY\xe8p\x94oQ\x04\n\xeeE\xe1[=\x8cB\xab8\x19I\xa0\xecg\x0c\x91\x92\xab14\n\xde\xc6P\xa88\x1cE\xa2\xeas\x0c\x91\x92\xdb14\n\x9e\xc7P(\xcc\xc1\xaa\x81&\xe7\x92\xfe\x91\x1e\xe9\x1f\xe7\x90\xfe1\xfe\xe8\x1f\xe9\x8e\xfe \xde\xe8\x1f\xef\x8c\xfe\xb1\xbe\xe8\x1f\xed\x8a\xfe \x9e\xe8\x1f\xef\x88\xfe\xb1~\xe8\x1f\xe9\x86*\x1e\x87\x8f\xf48|\x9c\xc7\x1d3\xc7\x92`%\x8f\xc3'x\x1c>\xde\xe3\x8e\x9dki\x02%\x8f\xc3'x\x1c>\xde\xe3\x8e\x9dsi\x02 XKR;\xf5\x9cCq\x055\xcc\xdf\x8d\x91\xb2\xb7Ob\x84\xf3;\xa2\x0d\xaazB\xe3\xecy\x12\xe2uJ\xe0\xaa'4\xae\xf8\xa8~\x0d\xca\x7fU\x18\x8e\x0f\x80\xe0\xd9\xc8\xae$;\x05\x94\x8bOA%-\xa0pE#\x14Z\xa10\xa9\x94M\xf3\x15[\xe6+7\xccWk\x97\x7f\\\xb3\xc4-\xc0\x8a-\xc0\xca-\xc0j-\xc0\\\x0b\xe8N\x92'r\xc3\xc8v\xbct\xcf\xbdu@\x1b7e\xdd1[8\"\n\xd9\xbb\xe9\xda\x90(d/\xc1k\x03\xa2\x90\xbdm\xafYD!{\xad_\xeb\x13\x85\xec\xfb\x034\x93(d_T\xa0\xf5\x88B\xf6\x8d\x08\x9aA\x14rJ\xd0\xad\xa6P\xe7$\xd2{d1{0\"\xd4\x1a\xce\xccy\xfb8L\xed\x14i}\x8b>o\xb0\x08c\xff\xbc(\xfb\xb1o\xb9h\xf9\xd3D\xf0\x1cd7\xd6\xc5\xec\xc6:\xcc\xaex\x0e\xb23L\x89x\x86)\x90\xaf,\x809\x8e$\x12\x1a#\x81\x88e\x01\xc8\xb1\xd7\x93\xc8\xd8\xeb d,\x0b`\x8eC\x89\x8c\xbd\xa1@\xc6\xb2\x00\xe4h\x1a\x12\x19MC cY\xa00\x96\x1e`\xd7\xd2\x88\x0f\x1c<\x8fwI9\x9e\xe6`R\x96\xa7\xfa\x98\x9c\xe9\x89n&ez\xaa\xa7\xc9\x99\x9e\xe8lR\xa6\xad\xfe\xa6\xe0p\n\x93w\xe3\x85\xfes;\xa1\x84\xe1\x89>(\xe1x\xb2\x0b\xcax\x9e\xea\x81\x12\x9e';\xa0\x8c\xe7\xa9\xfe'\xe1\xf9D\xf7\x93z\x1a~nO\x930<\xd1\xd3$\x1cO\xf64\x19\xcfS=M\xc2\xf3dO\x93\xf1<\xd5\xd3$<\xdb=\x8db:\xc7\xb6\xf3\x90EP\xf9y\xce\xf3x9\xb7\x7f\xd4\xcf\xb2?\xdd\xf1O\x10t\x04AG t\x08A\x87 t\x00A\x07 \xd4\x82\xa0\x16\x08\xedC\xd0>\x085!\xa8 B{\x10\xb4\x07B\x0d\x08j\x80P\xdd\x02\xa0:\xdb\xae\xed\xca+\x02\xde\x02\xbbJp\x8e}qf\xe8\xfa\x0b\xded\x05|$\x82\xb3f+\xe0C\x11\x9c5]\x01\x1f\x88\xe0\xac\xf9\n\xb8%\x82\xc3M\xed\x8b\xe0\xac\x19\x0b\xb8)\x82\xb3\xa6,\xe0=\x11\x9c5g\x017Dp\xd0\xa4%\xf6\xaf:{\x93:@v\xacQ\x10\xc3`V`\xae\x1d?h\xcb\xd8\xdeW\x08\xd3dVw\xbe\xe7R\x00\xcbb\x96ad\xe1p\xc8\xacG\x13\x0foP\\\x15s\xefB\xc3\xf95\x0b\x1ad\xdb6#A\x18\x06\x94\x08\x8e\xe3@lH\x08B\x08\xd0E\xae\xdd\n\xb2\xe8g\x7f\x00\xf5\xd7\x80\xc5\x02PV\x8c\xdc\xba\x92\xa1\xde\xd7\x19\x0cQ\xbcX\xf4\x0ds\x00IJ\x81\x86=\x8biN\x18\xdb\xc1\x92\x10c\xc0]\xe9_\x86\x98\xe00\xe7\xae\xd9\xef\x11\xc6\xe1\xb6Dd`H\n\n\xf4\xd7\xc5|a\xd8\x8cy\xa2u\x1c\xe1Z\x10\x0b\xf5\x1c\x9b\xbd\x9c\x90s\xa2qv\x7f`.z\x80\xea\"/\xa8=\xd1\xb5t}\xc4\xe8n\x15\xa6\x14&S\xe0\x9c\xb1\x10]>\xd2aW\xa0Q\xb6\xe9\x0eA\xb7G(\xa8{\x869\x1cZ=\xd6\xb3I\xc0\xd8\x1e\x0f\xfb\xb0\xdf\x11\xb01Bs\x87iW`o\xf6M'5\xe6\xfd> \xcd\x1c\xafQ\x03\xea\xf7\xc7\xec\xcb\n\x88r\xd3\x1a\"\x17\xb4)\x89\x1a\x0f\x1c\x87u\xe1\x1c\x85\x12\x1a\xe8\xb8\x88\x03n\xedd\x85\\\n\xb6\x18,\x16\x0b\x04\xc2(\x15\xa0\xd1\xc2]X \x8eq\xb9\xc5\xc2As\x10H\xf5\x10w\xe1ro'\xc3a\\_\xb1/\x80\xd5-AZkK\xad\x8e<\xe6\xb6\xf3\xb0,\xde\x91ZPH\x83\x90\x8ap\xd4B\xc8\x85$\x15\xe1\xb0\x85\x90\x0bP*\xc2A\x0b!\x17\xaeT\x84V\x0b!\x17\xbcT\x84\xfd\x16B.\x94\xa9\x08\xcd\x16B.\xb0\xa9\x08{-\x84\\\x98S\x11\x1a-\x84\xdc\x0cY\x11\xea\x96\x9c\x90\x0b\x81\xe6K\xad\x8e\x828\xca\xb6\x80\xa8&\x86\xdc\xa7-<\xaa\x89!\x17j\x0b\x96jb\xc8\x8d\xdaB\xa7\x9a\x18r\xa5\xb6@\xaa&\x86\xdc\xa9-\xac\xaa\x89!\x97j\x0b\xb2jb\xc8\xad\xdaB\xae\x9a\x18r\xad\xd6\x00\xact/\x9e\x92\x0f\xc7\xe6K\x8d\x88\xc8x\x02.8\x9b/\xb5&>\xe3\xf1\\\xa86_ju\xb4\xc6\xc3\xb9\xc0m\xbe\x14A\xb90n\xbe\xac\x824\x1e\xcc\x05u\xf3\xa5F\xc5u< \x17\xe2e\x92\xd7Q\x1e\x8f\xe7\x02\xbe\xba\n\x01\x01\x17\xfeU\xba/\x02<\x9e\x00\n\x06+\xc7\x80\xe0\xect9_\x16+\xe4\xc8\x8eQ\x90\xf2\x14D!l\xe3l\xc2\x03\xda\x01D\x98\xf3\xa5\x00\x0c\xc5\x9b\xb5\xa2D$|\xf49_je\x00\n\xe1\xf9X4s\xa3,\x1c\x85\xd0|d:_VA\x00\x87\xe7\xe3\xd4Zz\x11 \x18\xb5\xce\x97U@\nt\x02 \x86\xadk\x11RA\x11me\xb8<\xd4\xe4I\xa0\xf8v\xbe\xd4\xea\x10\x176\x1f\x1b\xedfM\x11\xa1\xf9\xd8\xb7i\x88\x88\x86\x8f\x84\x9b1&\x8b\xe0\x80A \x88\x8b\xf3\x81C\x00\x07\xa2d\xa2\xb3\xc2DP\xcc\x9cu\xd8,l\x86\xc6U>\x82\xaeZ\x91\x87\xab\x10 \x10O/Eh(\xba\xae\xdb \xa0\x81b\xed\x8a\xa6\x0e\xb7\x81\x81\x0d\x88\xbc\xb3a\x87\x08\xbe\x013\x02qxC$R2\x14\x957T\xe2\x0e\x06\xc4\xe8\x0d\x99hT\xe1#\xf6\xf9\xb2\x0e\xd79\x020r\xcf\xef\x97\x17s%t\x07\x9d,\xce\x7fn\xd6N\xec\xbb\xd7rd3\xf3\x8a\xb9\x11\x18\x8a%71\x17\xf0zn\x16sl \x14Cn\xe6.\xd0\xd5\xe4-\xe6W#(v\xdc\xcc^\x80\xe5\xacx6\xdc\xac_\x00\x8bY\\\xcc\xa8,\xa7Xq1A\x01%\xc3\x021C\nE\xb1\xe5\xe2\x86R+U\xe8 Q\\\x0d\xa1\x18r\x81\x05)\x81\x9c#\x81\xa1Xr\xa1\x07\xe1[y8\xd1\xe2\x7f\x05\x86b \x05'\x05E\x0bC\x88\x17;\xdc\x10\x1dI\x1b\xeb-]-C\x90\xecd+h\x92l\xd4\xcax$f\xcc.\x8fH\xb2a+\xe3\xa1\x981\xbbt\"\xc9\x06\xad\x8c\x07b\xc6\xec\xb2\x8a$\xb3Z\x19[b\xc6\xec\x92\x8b$\xeb\xb72\xee\x8b\x19\xb3\xcb1\x92\xcclel\x8a\x19\xb3K5\x92\xac\xd7\xca\xb8'f\xcc.\xe3H2\xa3\x95\xb1!f\xcc.\xf1\x88\xae$\xed 5\x82d\xdc\x96' Ie\x9d\xa4F\xc8\x98\xc3\x1d\xa5J%\xb41\x1f\xca\x99\xc3\x9d\xa5J5\xb41\x1f\xc8\x99\xc3\x1d\xa6JE\xb41\xb7\xe4\xcc\xe1NS\xa5*\xda\x98\xf7\xe5\xcc\xe1\x8eS\xa52\xda\x98\x9br\xe6p\xe7\xa9R\x1dm\xcc{r\xe6p\x07\xaaR!m\xcc\x0d9s\xb8\x13\x95\x81\x9e\x98w\x05 Y\xcb\xa2\xc3e[HW#\n\x8e\xd0\xd2\x00\x0c\x17\xa9\\\x8d\x94=\x174\x02\x8b\"8~$\xd3;\xd2*\xd8(\x12X\xb2\xc0\x01%\x91\x10\x92V\xc0\x84\x95\xc0\xb2\x19\x8e0\xcb\x0c\x92\x94\xb7\x94\xaf \xe4\xac\xd3MR\xceT\x84\x08,\xc9\xe0\x18\x94\xc9NIk\x00\"Q 9\x00\x07\xa5dJK\xae|&4\x05V\x89p\x94J%\xc1\x14\xda!\xadC\x10\xb6Ry\xb3\xf6~@\x06\x9c\xc0\xbaP\x18\xc7V\xa96i\x0d-\xcc\x05\x81-\x95\x98\x93\xf2'q\x82Z\x84i\xbc\x9a\x89B \xbddci\xae\x1a\x85\xb0z\xa9\x12Y/\xd9\xe0ZZ\x93 \xce^\xaa\x84\xdaK6\xda\x96\xd6$\x08\xbc\x97*\xb1\xf7\x92\x0d\xbf\xa55 \"\xf1\xa5J0\xbed\xe3qiM\x82\xd0|\xa9\x12\x9d/\xd9\x00]Z\x93 V_\xaa\x84\xebK6b\x97\xd6$\x08\xde\x97*\xf1\xfb\x92\x0d\xe1\xa55 \xa2\xf9\xa5J@\xbfdcziMpdBl\xf6\xb5\x8fA\x92\x9e\xab\x16\xef\x13\xbb\x83\n\xb5\x89{\xaf\xda\x02\x80\xd8NT\xa8M\xdc\x83\xd5V\x04\xc4\xfe\xa3Bm\xe2^\xac\xb6D 6,\x15j\x13\xf7d\xb55\x03\xb1\xc3\xa9P\x9b\xb87\xab-\"\x88-Q\x85\xda\xc4=ZmUA\xec\xa1*\xd4&\xee\xd5j\xcb\x0cb\xd3U\xa16q\xcfV[wT;l\xe2\xaajDQO\x15\x14\x01\xdbo\x05^\xca\x8c\xe3\x03\xed\xcc\x15\xd0zsN\xcc\xad\x810<\xf9\xad\xbb\x82\xa0\xd8\xbd\x133,\xcb\x19n\xfc\xc6^\x81^\x86X\"\\^\xcap\xe27\xfd\nl\xb1\xc7 \xe6U\x96\x93\xdc\xf8-AR'm\x0c)\x14-$\xb0mX\xd0\x14{\x80b\x9ee9\xc5\x0d\xdaT$%h\xe3I\xa1(\xce\xd0\xc6#\xe1\xb0\x91\xe0\x05\xbd,\x84\xe2 \x9f\xbc\xcb\x08\xaa\xcdI1\xcb\x1a\xc1\xb97\xbbsYjK\xca\x0d\xe2\xc4\xefjR:\x92\xf2#0\x0cW~\xdf\x93PQ\xbec\xd6\xa2\xc6\x02Cq\x85vF\xcbN!g\x08\xf1\x02\xb6M\xc96\xb5p$A\x14_hg\xb5 \xec\x8dd\xcd\x98\x97R\x9c\xa0]WB?s\xbc\x968x\x03ax\xf2\xdb\xb2\x05\x81\x9c\x1d\xcf \xda\xb2%U#\xe7G`h\xed\x01\x9b\xba\x04E\xb5\xaf\xdb\xc2\xb8\x86Q\xbc\xa1\x9d\xdf\x82\x88\xd8\xfc\x15s&A\xb4\xaf\x03\x9b\xc3\x14I\x8b+Q(\x8a3\xb4\x81L\xd1\xb4\x0d\xc74\x8c\x96\x1a\xd8e\xa6\x88\xa43$\x81a\xb8\xf2\xfb\xd0\xa5\x07-\x15b\x02\x12T\xf0\x05\xd2&\xc2\x08\xa18\xa6#\xe5.c,\x0e\x19\xc8#=R\xf6l\xe0\x00U\"\x8a!\xeaC@\xd2\x1a\xa8H\x02b/\n*\xca3CR\xe6Dh\x01\xb1\x16E\x19\xf5\x01#)s\xca 9\xf6\xa2\xb0\x839\x8f\xa4\xa0}y=\x928\xa4>\xc4$\xad\x84\x8a\x19x\xf6\xe2\xc0\x849\xf3\xa4\xd0\x92\x96\xaa\xc4\x91\nyP\xaa\xbd\xb3\x11\xb37_\x898t!\x8eVI\xeb`\x02\x18\xb8\xdf\xc1\xb1Ly\x16Kn\x0f9kQpC\x1d\xdcR\xb1\x85\xbc\x1aQ\xb4C\x9d\xf5j7\x059\x07\xf0\xd5\x88\xc3\x9f\xeax\x98\xbcw\xcb\x99\x0b\xe3!\xfa0\x99\x82\xae\xe4\x15\x89\x03\xa4\xf2\x00\x9a\xb4\x06\"L\xe2Y\x8b#&\xf2\xb4Z\xbb\x19\x889\x1e\xaaD\x18B-\xdb\xf9KY\x8bc*\xea0\x9c\x82 \xa4\xd5\x88\x83,\xf6\xfc\\{ML\xa8\xc5W&\x8e\xba\xe8Sw\xd2\xaa\xf8\xd8\x0b\xe8\x84\xc20\x8c9\xa9\xa7R\x93\xdc\x85\xc5q\x19{\xbcO\xa5\xae\xb6 K\x18\xa8Q\x87\x02Uj\x92\x07&\x92\xc8\xadu\x17\x99\xc0\x08*\x00\xf7\x94#[?\x08\xbe\xdf\x1a\xd9F]\xd4\xedY\xdc{j#\xbb\xd7\x94C\xc5f]\xcc\xbfY7\xb2\xfbu)\xffj\xdd\xc8\xb6\xeaR\xfe\xdd\xba\x91=\xa8K\xf9\x97\xebF\xf6\xb0\xa9\x97\x7f\xbbn\x84\xeb\x06k\x18-R\xae\xd5\xd8\xa0\xcb\xc1\xa6\xe3\x1e\x03\x820&\x8d\x01\x94\x80\xfb4\x04\xd0\x04\xb6h\x08\xa0\x0e<\xa0!\x80N\xf0\x90\x91\x05PL\xdc(&\xce\x06\x16N3\xb1\xc1\x00@\xd5\xc4=\x16\x05\x81L\x06\x04('\xee3\x18@;\xb1\xc5`\x00\xf5\xc4\x03\x06\x03\xe8'\x1e\xb2\xf2\x00\n\x9a7\n\x9a\x87i\x1a\xfa\x9c\x86\xe6\x06\x8b\x00U4\xefq0\x08e\xb2(@I\xf3>\x0b\x02\xb44\xb7X\x10\xa0\xa6\xf9\x80\x05\x01z\x9a\x0f9\x99\x00E\xa5\x8d\xa2\xd20\xe2\xb4\x94\x1aT1\xa8\xa2\xb4Gc \x88IA\x00\xe5\xa4}\n\x01h&\xb5(\x04\xa0\x96t@!\x00\x9d\xa4CZ\x0e@!\x1bF!\x93\x16?\xda@\x1ab\x89@\xbdm\x00\xbdq\x84\x10\x1d\xafL\x96\x0cP\xf0\x86W0K\x05(}\xc3+\x9d\xa5\x02\x0c\xb1\xe1\x0d\xc1R\x01\xc6\xd9\x00\xc6\xe1\x1a\x06Xl\xc5\xce\x125\x11<6\xae\xc0Y\x83!\x02-\xb6\x82\xa6\x12\x96\x10\xa2\x03\xa6\x17\x86\x0c\xb0\xd8\n\x98q\x18*\xc0b+`\x12b\xa8\x00\x8b\xad\x80y\x89\xa1\x02,\xb6\x82\xa6*\xb6a\xc0\xc7\x85l\xfd\xe0\xdb\xf1\xd2\x0bX\xdb\xf8\xb6Q\x95@\x06\xf0\xed^]\x0c\x95\x9aU)\xf0\x95'\xbb_\x15\x02\x9fU\xb2\xad\xaa\x10\xf8Z\x92=\xa8\n\x81\xaf-\xd9\xc3\xbaN\xa0\xa1\xb8j(\x18\xbf\xf8\xd8\xa0\x8a\xc1&\xe3\x1e\x8d\x81 &\x05\x01\x1a\x8f\xfb\x14\x02\xd0\x00\xb6(\x04\xa0\x06<\xa0\x10\x80.\xf0\x90\x96\x03PH\\+\x04\xec\x9b~l\xd0\xe5\xa0J\xe2\x1e\x03\x820&\x8d\x01\x94\x12\xf7i\x08\xa0\x95\xd8\xa2!\x80Z\xe2\x01\x0d\x01\xf4\x12\x0f\x19Y\x00\xc5\xcck\xc5\xc0\xf3\x8c?7\x18\x00\xa8\x9ay\x8fEA \x93\x01\x01\xca\x99\xf7\x19\x0c\xa0\x9d\xb9\xc5`\x00\xf5\xcc\x07\x0c\x06\xd0\xcf|\xc8\xca\x03((\xad\x15\x04\xc4)~j\x90\xa5\xa0j\xd2\x1e\x05\x81\x10&\x89\x00\x94\x92\xf6I\x00\xa0\x91\xd4\"\x01\x80:\xd2\x01 \x00t\x91\x0e)\x19\x00ElhEL\xe4n\xb3\x01\x143Qp\xa4\x0d\xaf-\x96\x0c\xa2\xe248i\xf5\xb4\x0d\xa7\xd4I\xab\xe7m8=OZ=q\xc3\xa9~\xd2\xea\x99\x1b\xde\x1al\x83\x00\x0b\xad\x98Q\xbf\"\x81\x87\xbc\x154 \xd0$\xa0\x85V\xc0\xc4\xc0\x90AT\xfc\\A\x13\x01\x16Z\xf1\xb3\x07M\x03Xh\xc5\xcf'4\x0d`\xa1\x15?\xc3\xd04\x80\x85V\xc0\x9c\xc34(\xb7P\xfb[-\xe9\xd7\nFv\xfer\xce2\x96\x01\xf2-d\xa9 \xe5BA \x84I\"\xc0\xc4\x0b \x00s/$\x00L\xbf\x90\x000\x03C\xc9\x00&a\x08\x84(\x0f\xc3A\x04\xa9\x18\x1e\x07\xc1L\x0e\x06&d8\x14\x98\x93\xe1P`Z\x86C\x81\x99\x19^.09C\xc2D\xf9\x19\x1e#H\xd1\x00@\x08g\xf280Q\xc3\xc3\xc0\\\x0d\x0f\x03\xd35<\x0c\xcc\xd8\x00\xb2\x81I\x1b\x12'\xcc\xdb\x00 A\xea\x06BB@\x13\x00\x82 \x1c\x00\x07\xe6p\x00\x1c\x98\xc6\x01p`&\x07\x92\x0fL\xe6\x90@8\x9f\xc3\"\x04)\x1d\x0e\x06\xa1L\x16\x05&vX\x10\x98\xdbaA`z\x87\x05\x81\x19\x1eN&0\xc9\xc3)\xaa=\xcf\x03kN1\xd5\x03\xeaS-\xdb\x03)Y)\xe1\x03)^)\xe7\x03\x19C)\xed\x03\x19H)\xf3\x03\x1aM-\xf9C\x92*\xe6\x7f8\x92cR@<1D\x0b\x91\xc2\xd3\x9aJ\"\x88#T\xcd\x05q\x84\xaa\xe9 \x8eP5#\xc4\xb7Q9)\xa4\xe5\xdfs\x8f\xe1\xbc\x10Q(H\x0d\x91\x08\x08`\x12\x000AD\x94\x839\"\xa2\x1cL\x13\x11\xe5`\xa6\x88\xac\x1fL\x165\x00Q\xbe\x88E\x08RF\x1c\x0cB\x99,\nL\x1c\xb1 0w\xc4\x82\xc0\xf4\x11\x0b\x023H\x9cL`\x12\x89@\x89\xf2H\x1cD\x90J\xe2q\x10\xcc\xe4``B\x89C\x819%\x0e\x05\xa6\x958\x14\x98Y\xe2\xe5\x02\x93K\x04L\x98_\xe21\x82\x14\x13\x00\x84p&\x8f\x03\x13M<\x0c\xcc5\xf100\xdd\xc4\xc3\xc0\x8c\x13 \x1b\x98t\"pp\xde\x89\x01\x08RO,\n\x02\x99\x0c\x08L@1\x180\x07\xc5`\xc04\x14\x83\x013Q\xac<`2\x8aUPk>\nT\x98ZJ\n\xd2\xa2RV\n\xd0\xacJb\nP\xb6Jn\n\xd0\xbfJz\n0\x89J\x86\n\xb2\x92R\x92\x8a T\xcbS\xb1\x04G\xa4\xaa8R\x80\x12\"\x04\xe7(\x85\x84\x15K\xa6\x98\xb3b\xc9\x14\xd3V,\x99b\xe6\x8ak\x9b(y\xa5\x90\xbdR\xf8&Kd\xeb\x9a_\xc5fPF\xab)\x14%\xb4\x08\x04\x040 \x00\x9c\xcej\xca\xe1lVS\x0e'\xb3\x9ar8\x97E\xd4\x0f\xa7\xb2|f\xad\xc0\"\x0c\x16!Jd\xb10\x08e\xb2(8\x8d\xe5\xf3\xb1=\x0b\xb2X\x10\x9c\xc4\xf2\xf9\x98\x9d\x05\x0d9\x99\xe0\x14V\x83\x12f\xb0X\x88(\x81\xc5\xe1 \x98\xc9\xc1\xe0\xf4\x15\x8b\x82\xb3W,\nN^\xb1(8w\xc5\xc9\x05\xa7\xae\x1a\x988s\xc5aD\x89+\x1e\x08\xe1L\x1e\x07\xa7\xad8\x18\x9c\xb5\xe2`p\xd2\x8a\x83\xc19+^68e\xd5\xe0\x04\x19+\x1a JX1(\x08d2 8]Ec\xe0l\x15\x8d\x81\x93U4\x06\xceU1\xf2\xc0\xa9*FA\n\x99*Hc\xaa\x89*@\x8f\x8ay*^\xb9ji*^\xe1jY*\xde\x08jI*\xde0j9*\xc0X\x8a)\xaa\x86R5C\xc5P\x1c\x95\xa0bi!R\x88\x12\x9c\xae\x94\xd2S\x0c\x9drv\x8a\xa1SNN1t\xca\xb9)\xb6}\xea\xa9)\xbf\x8c\xd4\xa0\xccT]&JL5\x00\xa8\xdcl\xca\xe1\xb4T]\x0cg\xa5\xeab8)U\x17\xc39\xa9\xa6n8%\xe5\xd3k\x04\x16`0\x00QB\xca\xe7\xc3\x7f\x16d2 8\x1d\xe5sq=\x8b\xb1\x18\x0c\x9c\x8c\xf2\xb9\x88\x9d\xc5\x0cYy\xe0TT\x0d\x12f\xa2\x18\x84(\x11\xc5\xc2 \x94\xc9\xa2\xe04\x14\x03\x82\xb3P\x0c\x08NB1 8\x07\xc5\xca\x04\xa7\xa0j\x948\x03\xc5BD (\x0e\x07\xc1L\x0e\x06\xa7\x9fX\x14\x9c}bQp\xf2\x89E\xc1\xb9'N.8\xf5T\xc3\x04\x99'\xaa\\\x94x\xa2A\x10\xc6\xa41p\xda\x89\x82\xc0Y'\n\x02'\x9d(\x08\x9cs\xa2e\x81SN\xb4b\xda3N\x80\xa2\x14\x13N\xbc\xf6\xd4\xf2M\x9cF\x95\xd2M\x9c\x92\x95\xb2M\x9c\xde\x95\x92M\x9c)\x94rM\xbcu\xd4RM5\x9db\xa6\x89\xc6\x1f\x93hb(\x01B\x88\x0e\x9a{T\xd2L4\x95j\x96\x89\xa6RM2\xd1T\xaa9&\xa6]\xa7\xa5\x98\x04\xd9$\\\x85SP6\xa9)\x14e\x93\x08\x04\x040 \x00\x9cMj\xca\xe1lRS\x0eg\x93\x9ar8\x9bD\xd4\x0fg\x930\x13\xd7\xb3\x08\x83E\x88\xb2I,\x0cB\x99,\n\xce&a>\x16gA\x16\x0b\x82\xb3I\x98\x8f\xb2Y\xd0\x90\x93 \xce&5(a6\x89\x85\x88\xb2I\x1c\x0e\x82\x99\x1c\x0c\xce&\xb1(8\x9b\xc4\xa2\xe0l\x12\x8b\x82\xb3I\x9c\\p6\xa9\x81\x89\xb3I\x1cF\x94M\xe2\x81\x10\xce\xe4qp6\x89\x83\xc1\xd9$\x0e\x06g\x938\x18\x9cM\xe2e\x83\xb3I\x0dN\x90M\xa2\x01\xa2l\x12\x83\x82@&\x03\x82\xb3I4\x06\xce&\xd1\x188\x9bDc\xe0l\x12#\x0f\x9cMb\x14\xa4\x90M\x824\xa6\x9aM\x02\xf4\xa8\x98M\xe2\x95\xab\x96M\xe2\x15\xae\x96M\xe2\x8d\xa0\x96M\xe2\x0d\xa3\x96M\x02\x8c\xa5\x98Mj(U\xb3I\x0c\xc5Q\xd9$\x96\x16\"\x85(\xc1\xe9J)\x9b\xc4\xd0)g\x93\x18:\xe5l\x12C\xa7\x9cMb\xdb\xa7\x9eM\xc2eP\x06e\x93\xea2Q6\xa9\x01@\xe5fS\x0eg\x93\xeab8\x9bT\x17\xc3\xd9\xa4\xba\x18\xce&5u\xc3\xd9$L\xaf\x03X\x80\xc1\x00D\xd9$\xcc\x07\xf9,\xc8d@p6 s\xf1;\x8b\xb1\x18\x0c\x9cM\xc2\\l\xceb\x86\xac{U\x1fl?w\x15\x1fV\x00w\x17\x1f\xd4\x00w\x19\x1fR\x01w\x1b\x1f\xd2\x01w\x1d\x1fR\x02w\x1f\x1f\xd2\x02w!\x1fT\x03}\xe7\x1e\xd6\x01}\xe9\x1eT\x00}\xeb\x1ej=}\xed\x1ej:}\xef\x1ej7}\xf1\x1ej4}\xf3\xbelq\xfb\xc1\xcb\x033f\x90\x17UD\xa3\x1d\x05\x01\x07<\x12\x01\x8ey$\x00\x1c\xf6H\x008\xf2\x91\x00p\xf0\xa3d\x00\xc7?\xf6\x00\xabh\x08\xe4q\xe0(\xc8\xc1\xc0\x81\x90C\x81c!\x87\x02\x87C\x0e\x05\x8e\x88\xbc\\\xe0\xa0H\xc0\xe4\xe3\"\x00\x04\x87F\x1e\x07\x8e\x8e<\x0c\x1c y\x188F\xf20p\x98\x04d\x03GJ\x02\xd72XBHp\xbc\x04\x80\xe0\x90 \xe0\xc0Q\x13\xc0\x81\x03'\x80\x03\xc7NH>p\xf8$\x80\xb2\x11\x94\x83\x81\x83(\x8b\x02\xc7Q\x16\x04\x0e\xa5,\x08\x1cMY\x108\xa0r2)l5\xaa\x9ef\x0f\xc8\x83W\xc2\x81\x96@\xc0\xe3l\x03\x80\x87\xd9\xa6\x1c\x1ee\x9brx\x90m\xca\xe11\x96\xa8\x1f\x1eb\xe9\xfd[\xe1\x08\xcb\xc2\xe0\x01\x96A\xc1\xe3+\x03\x82\x87W\x06\x04\x8f\xae\x0c\x08\x1e\\Y\x99\xe0\xb1\xd5gF\x1b\xd1\xd0\xca\xe1\xe0\x91\x95\x85\xc1\x03+\x8b\x82\xc7U\x16\x05\x0f\xab,\n\x1eU9\xb9\xe0A\xd5g\x07\x18\xd1\x98\xca\x03\xe1!\x95\xc3\xc1#*\x07\x83\x07T\x0e\x06\x8f\xa7\x1c\x0c\x1eNy\xd9\xe0\xd1\xd4\xa7\xc6\x1a\xd1`\xca\xa0\xe0\xb1\x94\x06\xc1C)\x8d\x81GR\x1a\x03\x0f\xa44\x06\x1eG\x19y\x14\x86Q\xc1\x88\x89\xeb\xe1F4b\x12\x08x\xc4l\x00\xf0\x88\xd9\x94\xc3#fS\x0e\x8f\x98M9\x96\xdc\xca\x05\xfajr\xc1\xa8\x10\xa6\x95C\xdb7\x12Kf\xae\x1d?\xb4\xf2\x92}I5\xe3\xf3\x80\x0e)\xda\xa5\x9a\x8b\x9c0\xb6S/\x0c\xce\xb1\x17 -]\xc5\xe1z\xb9\xa2 \xd6\x81\x8b\xe2\xac\x98\xa3\xa9K\x18\xc7\x0b51M\x10\x06Ha\xe9s\x00d\xce\xd6Q'\x88\x0d\x91)H\x0e\x91\xe5\xc2+H\xaf\xb0p+\x9b\xe4\x9f\xd4\"\x9eJ\xa5A<\x95B{\xc4\xa2\xe3\x93D\xe7\xa9TD\xe7\xa9\n\xd1)\x8a\xb4D\xd9\xd8[\x06\xe7YT\xc0\x94\xc7dy>Q2\x00\x87\x048(HQ\xac`\xed\x03#E\xed9bA\x18\x08(\x0b\x83)\xc5Q\x90G\xc1\xfbR\\y\x83DF\xbf]D\xffh aaZ-G#`a0$\x0c\x0d\xaa,\x9c\x7f!~\x11\xc6\xfe\xb9cG^jc\xef\x11\xb1P\xccBq\xb8E\xb1c'\x1cr\xcd\"\xd7Q\x04#\x03\x16y\xd2p\x98\x12\xce\xa1\xd4\x12\x00-n\x0c\x00\x16\xb7\x07\x00+\x0c*\xcan\xda\xb8\x98Z;9\xb0\xa4\x99\x1cV\xd2J\x0e\xab\xd0HA{8\xb7\x92\xb5\xe7\x08\x1f\xe4\xb1\x92\xf6pX`8]h\x833\xe6\xc1\n\xd9n>\xab/\xc2 \x8b\xf5\x1e\xd19\x1fR/4\x8b\xa5K\xd6s\x80\x94\x0f\xa1\x17\x06Ql\xf2\xc5=\xa2\xb8\x07\x05\xea\x0b\x93@\x18@\x90\xbe\xe8S\x00\x88\x85E\"\xf8\xe2\x01Q\xdc\x1d\x0d\x01\x06C\x12Q\x00\xda{\xc3\x81\xd5\xbd\x16$\"\xf5g\x9d\xae\xc5\x02\x005a\x04\x9a\x01d\x07\x1a\x01\x99\x82F\x08\xacA\x83`\x83\xb0\x18\xd0&\x0c\x080\x0b\x8d\x10X\x86\x01\x15\x18\x05\xeb(\x8cU\x99\xc9|\xa1\xc5\xfcV\x83q\xb4\xa4\xbd\xfc6s\xf9m\xd6\xf2\x15\x8c\xe5\xb7\xdb\xcaW0\x95\xdff)_\xc1P\xfe\xb1v\x12\x98\x04\x0bM\x82[M\xc2\xd1\x92&\xc1m&\xc1m&\xc1\n&\xc1\xed&\xc1\n&\xc1m&\xc1\n&\xc1\x80I(\x8c\x8f\xecd\x1d\xa3C\xd3O\xb2\xce\x03b\xb2r\n\xd8\x17\x01\x03;\x8e\xc3-\x01\xedq<\xbd\xc0EAZLi\xc5\xcf\xe7Fs\"+m?\xcf\x98\xf86\xc6\x9acG\xe5\xe8\xb0\xb1c\xcf\x0e\xd2\xf3\xe69\x8dO\xe3u\xe0\xd8):\xe4\xc9\x81<5\x82\xce\x83p\x1b\xdb\xd1$\xdc\xa0x\x91\x7f\x9c\xcfs]\x14Lr\xa9\xea\x87\x08c/J\xbcDa\xcc9\xc0\xeaH\x94\xd5\xcb`[4L\xa3EJ\xae\xe3\xbd'\xea\xb9\x1e\x88UU\x9d\x11\x9c\xaem\x05u+\x0c\xf1\x95\xc2|u\x13\xf8\xc7X\xc0W1\x80\xff<\xfa\xf7\x8fT\xbf\xff\xdd\xb4/Q4VW4>F\xd1XE\xd1\xf8y\x14\x8d\x8fT4~\x8a\xa2)\x96U\xb9\xe6\x84Aj{\x01\x8a\x0f\xf5\xa3\xfdy\xe2\xc4!\xc64E\xb1h\xa6\xb7\x12\xecu\x1aN\xc8\x9d\x96\xec\x01\xa3\xddX\xcb\x1e\xf2t\x0c\x0cS\xb0\x86Y{\xe7<\x00bj\xec\xd9\x1buIARPX\x8d9\xf4\x94\x03\x15\x04V\x18M\xcaV\xf8'7\x02\xa0\x84\xdb\xe0\x1f\xdb\x04\xb1\xb4\xf8di\x01JXZ\x0cHK\x8b\x82\xbd\xe8\x10\x85\x89\x97'\x02\x17\xde\x0e\xb9\xff\xd7\xf3\xa30N\xed \x9d\xfcQ\x97\xd8\xf3$\xc4\xeb\x14\x11\x85\x19\xe9y\x8c\x9c\xf4G#\xdau\x88\xbf?\xd1Eg\xc4\xdf\x9f\x14\xcc}\xe0\x04\xcc\x1c\xe7\xcf\x94QAH\x15\x9f\xcc$\xf7\xff\x83\x04\x17\xc9\x88\xff\\\x19)\x01\xb6\x89\x16\x84\xb1o\xb3#u\xf6\x88F\x16\xa370\xa0\xd3\xb0(\xa6#\xc9(>>'X\x0b\xc5\x07J\"\xb9\xe0\x90\x8a\x13\x8d\x85e\xd2)\x88\xa7\xe0m\x8d\xcclt!\x14\x19\nCx\x89\xfd#\x05\x96\xca\xa6jfp\xe6\xe6e\xc3\xbcl\x14f\xa3\xcd\xed\x04\x1d6(N=\xc7\xc6e:;{\xc6\xef\x91l4\xdfsY\xa8\xef\xb9.\xe6\x80i\x18\xb1\xc04\x8c\xb8\xaaS\x9f\xab9\x0fp\x14\x0c~\x00\x9a\x91\xf9\x8ezK\x00\xb4\xb01\x00\x16n\x0f$B\xd1$\x856)8q\xd9P^o\x92vr`q39\xa8\xa0\x95\"\xbb\x1d\xed\xf8e{\xf01\xed\xe1\xc0\xe2\xf6pPA{\xf8\xfa\xcb\xf6PX\xd7\xf3\x0fad;^\xba?7\xb8\xa23\xf6\x01\xf41\xfa\xecq\xf1\xfdym\x8b\xe6\x0f^\x99\x15/f\x90\x92w\xa7kXI\x07ez\xf1\x82IK9'\x86\xbc\xd6J\xfc\xae\xc5\x13\xdaN\xeamP\x03\x19M\x94d\x0c\xd7\xa9\\\xc8p\xcd\xec\x9e-q\xb8=\xe3\x9e@\x82\xe7\xcf\xbf\xa3\xbe\x14\xea\x15\x18|\x95-\x03\xf3S\x11\x9dn\xfe\x9f\x1a\xa8\xab\xa9\xedXQ\x9b\nKC\x95\xf5\x9e\x89Py\xb3\xda@y\x1b\xd9\x16\x18\xdf\xa7\x05\xcd\x06{^+\xa4w\x16R\x98 _\x7f\xb6\xef\xe1/\xe3p{\xd0\xfc\xf0Q\x0b\x93\x9dVd\x0f\xfd0LW^\xb0<_\xc6\xf6>ql\x8c\xea\xb6\xcdm\xe7aa;H\xdbx\x897\xf7p\xd6\xf2r\xc1+)\xa24\x93of\xe5?a;E\xdf~\xd4\x7f\x9a\x88\x9e\x03\x1a\xe5Xu\xba=A\xa7:\x02z:\xe4\xac\xa5\x16^\xdb`\xd7\x89\xe1.\x9b\xeb$\xb7\xc0\x8fFW\xb7HM\x11O\x81:\xcaaI\xc4\xac;\xe6Yu\xc7\x00#\x0d\xdb\xf1\x12\xfd\x7f\xc5A\xbc\xe0\x18\x1f\xe1\xd1OEI\x9d\xa5\x80\x88L \xf2\x9a\xb2\xb4\xcdwz\x90\xeb\xf4\x84\x06o\xf7\x1f\xc0\x17\xb3\x87L0\x1dzAZ\x8fH\xce:N\xc2\xf8\xbc|H#\x93\x95\xed\x86[\x0d\x02N\xea\xc5b\x8c\xb0\x9d\x89\x05\x99\xdd\xc6\xb8\xd3\xb5\x92\x8e\xb3\x9e{\x8e6G\x8f\x1e\x8a\x7f\xec\x1a\x03\xeb\xac;\xea\x9fu\xfb\xfd3\xe3\xa7\xc9\x91x\xb1\x88\xe7\xf6\"\xcd\x04\x0d\x83\x14\x05\xe9\xf9_\xfe\xd2\xf8\x7f\xb8\xd3\n\xe4\xb9\xde\xd1;\xc6 \xdauz\xd1\xaeC\x9e\xf7\xeb\xfd4Q\x86\xe5\x07;c\xdb\xf5\xd6\xc9\xb9\x17\xacP\xec\xa5\x93f\xd2\xe4\xd6\xd1\x93\"\xf3\x99\xe7e\xf4I\x11A\x1a\xba\xfeb\xb2ByN'\xff\xf91\xcf\x98\xee\xce5\xf9\x9cu\x846Ui$\x1a\xcd\xfd\xbb\xd0\xeb\x99\x18Ej_\x10d\xcc\x97\x9a\x1dx\xbe\x9d\xa23\xc1s\xa8/\x11\xa5\xc2\xd0\x89=\xc4IM\xdb\xec(\xd0\n\xa6\xa5~\xd4\xf4Ce\x17\x9d-2\xea\"\x83-\xea\xd5E=\xb6\xc8\xac\x8bL\xb6\xa8_\x17\xf5\xd9\"\xab.\xb2\xd8\xa2\xf1x\\\x17\x8e\xc7c\xa0\x98*\xe7\x00\xbe\xbdk\xa45\xfa\xc3\xfe\xc8\x1c\xf4\x87,\xaa\xf4\xf2\x1aY\xfe\xce\xc3\xbc\xd4\xb3q\x0d\xe3\xb3\x95\x8f\xda:HP\xc3(\xff\x8d\x86\x04(IQf\xa0h\xaf\x15\x11T\xdeM:!\xb3\xaf,\xc2Ej\xb05>\x10\xbf\x9e\x1b\xecB\xa2\xa4k6\xae \xda\x95\x01\xd6\x01c{G`\xcd#\xb0\xfd#\xb0\xd6\x11\xd8\x01\xa3\x17\xe8`\x7fA\x8f\xbd$\xd5b\x94 \xa1q\x08\xc4\x9a{\xf1\x1c\x99\xaf\xd6'94I\xf7\x18i\xe9>B\xc5\xd1*\xa1%\x8b\xed\xa5N\xf4sDm7u\x8f\xdbo\"9&(B\xb1\x9d\x86q\xce\x94\xe0at-A\xfb=\x7f\xd9\xf1\xfc\xe5\x81\x18\xd2\x9b\x9cG\xfe\xab\xeb%\x11\xb6\xf7\xe7s\x1c:\x0f\x02\x1d\x06\x0fI\xc7>\x94\xe7\xe1Mk\x88\\\x17\x9a\x02\xf8\x01k\"-\x95\xd5\x06\x0d\xb6\x0c\xa2\x9c\xf5\x0b\xa9\xc6\x03\xc7Y,\x9e_\xaamlG\x11\x8a\x05\n\xec\x0f\xf4hW\x1a\xf0\\\xef\xe4\x9b&\xa5\x0b\x9d\xeb\x9d^VH\xcd\xf0\xdecVRN\xcf\xf3p7\x01\x9f\xd2\x12\x84Qn\x1a-\xb5\x97Z\x82\x9cL\xeaCe4\x82ymH\xcdO\xb4\x05F;\xf2Y\xf6;%I\x18{\x993V\x99\x18\xaa\xcc\xf5\xe2\xa2\x9a2%:\xa98\x12%N\x88\xd7~0\x01\x9f\n\xc5\x7f\xba\xd8\xe4 \xe0F,\xeai\xfe\x8b\xe6\xa5\xc8O\xaaG\x95E\x0c=\x0b\x97\xb2\x7f\x8c\xea\x9f \x134\x8aB\xc4^\xc2E\x81\xbddR\x9b,\xef\xb9F\xb4\xeb$!\xf6\xdc\"\x1c\xb3\xc6g\x03\xebld\x9cu\xcd\x9f\x84*)\x9d\xb8\x99\xf5\xa9\x1b\x1e:\x1bj\x93\xca$\x8e\x18\xf5I'\xd4;V\xb4\x9b\xe4\xa5\x0b\xdb\xf7\xf0\xfe<\xb1\x83DKP\xec-&U\x1f\x9e\xf7\x0d\xcb\x10\xf2\xee\x06\xa1\xe6\xa2\xc4\xe9$\x91\x1d\x1cH\x03d\xfa>7j\xd5\x9f\x1b\x93\xe2?BV\x9dd\xb3\x84\x82\xa2\\\x85}^\xab\xfdD\xc2\xca\xb71u\xde\xa9_5t[\xcc\x04}]\x9f\xa8HK\xf4\xd1\xdc \x8eWVd\xc7\xb6\x8fR\x14\xff\xf1G6\x15\x90B\xf5\xa2]\xcd\xdf\x8av\x1d\x9db\xef\x87A\x98o\x10P\x82\x0ft]V\xdb\xc6C[\xad\x9a\x06\x1f\x0e\xfc\xca&\x9b\x04\xcch7\xa9\x0e>\x90\xfe`\xa9{\xb9\xc5\xdb\xc3\x82\xedq \xdc\xcd\xc8j(\xba\x02\xd1\x07\xfe\xaa\xeb:\xb3\x10\xe9\xb3\xc3a\xb3\x921\x99E\x8c1\xe6\x16;\x00\x04\x14\xad\xd3M\xedy\x1e8\xa0\xf8\xe9#\xceQ\x0eOV]\xfc\x9c\x8dC\x87\xc6\xdb\xfa\xfc\x90s\x04\xa3\xf3\x85\x17'\xa9\x16.\xf2\xf0\x83a\xdb\xd1;\xfa\x11\xbc\xbaebs\xd5/:9\xe7S\xa7\xf3*\xd7Y\xfc\"\xb3\xbe\xad\x999L\x1eSY\xfa\x8bj\xb5\xd9kV\x9b\x99\x9f\x00kd \x9b\xf3\xfb\x8f\x9a\xa5\xbf\x00\x13=U\x111\xb4.c{\x0f6\xab\xeb%Z\x18\xa1\xa0\x19n\x92\xb5\xef\xdb\xf1\xfe \x1a\xe13\xef\x16h\xa8fQL\x8a\x95'V\xd6\x1a\x95s\xd0\xc4\xf7\x82*\x82\xb5\xb2\xdf A\xd9\x1b\x83\xa3\x9f\xe0~c\x00\xcb\x7f\x83\xe980\xe6(\xd9\xcf\x8e\x01w\xb0=G\xf8\xe9\x1d\xef\xa4\xa9\xfe\xa8f\x95\x922C79,\x0fu\xbd\x1eG\xb9\xc30'\xcc\x1aJ\x02\x95\xfd\x91\x9a\xa1$\x9d[\xc0j\xd5g'J\x95Q\xadi\xeds4\xae\xe8C\x9a\x8f\xd2U\xe8\xca\xe6\xed\\\xcf\xf5\xd6\xe5H'f\xd0A\x16\xa8e\xe3\x05w\x03\x8c\x99\\L\xba\x0b\xe5\xd3ONC\xf5\x04\x9d\xed+\xf2v.\x16\x0b\xc5F\x86\xf9\xd2,3\x80\xe7\xb6\xf5\x97\x92$\xb2\xd3\xd5\x11\xd0?\xfepQ\x14#\xc7N\x11\xa5\xccAD\xf4\xacS{[n~\xbdq\x08\xbdc\x16\xab\x19\xfa\xb7'w\xd0\xc96\x8c]m\x1e#\xfb\xe1<\xffW\xb31\x96\x85c\xaa\xf1R\xb9\x19N\xec\xe8\x0f\x07\xa3h\xc7l\x81\xff\x07\x9a\xaf\x17\xed\xd8\xd3\x9d\xcal\xd8\xcd:,\xbc\xa6\xab\xd4p\xa6\x8b*r\xc8\x16\n\xb1\x17\xe5\xebR\x82\x81\xa9:\xe4<\xdfH\xf3?4\xe9\x90\xd1\xbeZp\xc7\xc8\xad\x18\xe0\xf7\xea\x00\x9f\x98\x95\x9e=\xb2\xe7\xa4\xab\xf6\xad\x19\x19\xcb\xb0m\xc4,5\xe0\xf8\xaab\x19\x85IJ\xbc\x8f\"3p\x7f\xec8c}\xc2\xae\x80\x87\xe6YO\xef\x9f\x19\xfd\xbe0\\\xa1\xb8\n\xa7\x1drN(\xea:\x81\x19(\xb3\n\x1f\xf5p\xf9h9\xd7\xac&\x17\x8em\x98\xbc&{V\xef\xcc\x18\x18g\xfd\x91\x82&\xd7j\x8a,\xaa:\x9e\x17(\xb1\x02\x9b\xd3\xd4\xa8\xc2\xdeE\x18\xa5\x88\x95kl\"\x13\xf1\x9a\xec\x8f\xcf\x06\xbd\xec\xff\xad\x8a,\xd8\xaa\xe92\xaf\xec$v\xa0\xd8j\x9cN\xd4\xa8B\x0dK\xc4:\xe6\xc0\xb0\x17\x0b^\x9d\xe3\xe1\x991\xb4\xcez\x96B\x17_\"5\xc7,\xaa:\x9e\x17(\xb1\x02\x9b\xd3\xd4\xa8\xc2>\xb2Sg\xc5\x88e\xe9\xc8tz\x9c\"G\xfaY\xaf7<3\xc6\n\x8a\xcc\xd9*\xa9\xb2\xa8\xec\x14n\xa0\xd4J\x8cNS\xa7J\x05\x19WF\xae\xb1n\xf4\x00\xb7\xcc\xa6\x1cc\xa4\xe6\x96\x19W%e\x16u\x9d\xc0\x0c\x94Y\x85\xcfi\xaaT\xe1\x1f\xe6\xb1^\xc2H\xa6\xbb\x96m\x0fym\x9agc\xfd\xcc\x18\x0c\xdb\x95Y\xf2U\xd2gQ\xdbi\xfc@\xc1\x15Y\x9d\xa6U\x95*\x88\xb0\xbe>\x15:\x98\xd0\xa2\xa2y\xf6\x07\xce\x14\x8d{\xc0\xab\xa5\xc4\x95(i\xb9\xa8\xefd\x96\x07Hzun\xa7\xe9ZR\x0b!\xa0\xb3B>J\xb8\xa4\x9c\x1aY\xa7[\xfe\xa0\xa5^\x8aQk\xaef\xe1\xe14kD\xb3\xd6*\x9eh^\x90Eq\xd4\xd6b\x1eI\xe7{T:\xb5oU%\xd8{M\n\xd2\x1d\xb9.b\xbc*\xb5\xe7\xa7\xad\x82\xa8\x9a\x8bex\xdd,b\xe3\x1b\xd8\xf3N\xedy\x07{l\x1a\x8d<\x89N\xf1b\x16,\xc7\xaf\xfe\x8a\xfa\xd8\\8\xb7bbv\xf2\x99\xcf\x96\xf5X[C\\\x85\x89\xecb\xdf\xbe`5\xa8WeF\xb4\xa3\xceK\x11)l\xc1\xfe\x1e\xbb\xbdW\x08Q\xfa\xf8\x81\xc9\x90\x81\xbeI\xae\xbe\xb5r\xaf\x1aLJhh\x97\xa28\xb0\xb1\xe6\x86N\"\x87\xe6^\xfdGy\x13\x8a\xb5+\xbd\xcdX\xbb\xa8U\xa5\xb5\x8f7\xa8\xa4)\xdc\x11\x12ik\x84h\xb2ALf\x14h\xd3\xf3\xb6 :\xa6\x01\x020%\x7f\xc4fR\x9f\x9e\xb3\x15\xaa\x939\x0fC\x13\xa3\x1dr\xd6)\xaa\xe0\xf50\x98\xbb\x81\xfc\x9d^\x0ci\xa7;O\x03r\x1c$\xc7\xe5>7.\xcfCw\xaf\xe5;\xb0u,r\xd2\x98\xf7?s \x82\x97\x9ez\x86\\/=P'\x16\xf4V\xfab#\x83T\x9a\"M'A\x189i\xb5\x9bkB\xb3W\x8c\x92(\x0c\x12\x94h^\x100f\x96\"\xb9\xee\xc8\x95[\x82\x9eXN\xa3\xa7u\xc6\xaa\x96,\xec\xf8#I\xedt\x9d\x80{\x0fOeJ<\\\x07n\xe8\xac}\x140\xb9]\xe3\xd8d\xf6X\xcf\xfeH\xaa\xce\xcf>1\x9f\x0f\xcd\xcf\x93UY\xef\xbe\x8e\xfc\xc9\xf36\xb78o\xf5?\xd1Zb<\xfd\xe3\x8f\xc2g\\o\xd3\xf5\xed\xf8\xc1\x0d\xb7\x01\xec]2\xca\x18\x05.\x8a\x91;+9\x80\x9b\x7fE\xa0\x93\xbf\xb9\xcd\xa1\x8f\xc75C-\x10\x9a\x91\xa7\x1c\xa8d\x9e\xd1\xef\xf7\xd1q\x9a\xe1\xf6\x9dT\x1aW\xa9\x85\x9dEThY\xc5t\xa2\x038\xad|g\xc9\xedg\x90\xdc>\x1c%\xf0h<_\xe8\xfd\x89\xe2\xbd'\x15\x89\x9a\xd6\x14\xa9\xf3\xe7h\x13}\xd8qd\xcc\x0d\xddy\x82d\xec\xce\x95\n1'T\xba:N\xd3\x8b\xc5BxbN\xb8\xd3\xaaeSW\xf3\x1b\x0e\xed|\xe4+\x0e\xdd\x93G!\xa9\x0ej6gl\x9b\xfd\xfa\x96\xb7TP\x15F1w\xa6\x0b\xee\xfb\xcc\x95\xef<\xa2)69\xb3\x9f\xca=\xce\xecwx\xe7\x93{\x98C\xab\xe0c\xb5\x8fV(H\n\xf1\xb3\xa0\x83z@\xfd\xa24\x06\xd5/\x89ae;\xd6\x8er\xcd\x15'\x18\x1at\xf3\x96\x86\x16\xban\xb1\xdc\xcf\xba\xddAr.y\xe5-W\xc5{\xc0\x9d\xd0\x05\xd6~2\xf4\xdf\xbb\xbe\xe7\xc4a\xfe\x80|iN\xe9!\xbb\xeaHN_g\xce\xe8\x0c\xd8\x13\xd6Y\x1f\xc8\xdcQ+\xd7y\x89\xf8\xc4S\xee)\xe5\xca\x138tJZj\xe8\x8ezc\x138\xed@n2\xf2\xc6&\x0d\xf8\xd1K=\x8c\xbd\xb5\xdf\xf9\x82\xe6g\xc4\x84/\xe9\x97L\xc4P\xb6\xd9\xd4\xeb\xc5\xed\x90\xdb\xdb+r \xc4+\x88\x88eT\x8f\\\xf3\x9bE6\x83\xdaG \x8ej\x83\xa7\x95\x98s\x1a\x96\xe0P\x13\x07\x93\x8bX'n\x9e\xbe^8i\xa7XQ\xba\xbf+\x1dLzr\x13\xbe\xe7\x92\xa7\x1a-\xb5\xe2\xb8\xb5U,,N\x88D[\x94T/`\xeat\x93a\xd6\xcb\xcf\xe6T\xa0\xe0\x85\xb9\xd5l\xd2\xf8p\xe5\xb3\xe5\x89J\xe2x\x7fq\xd1\"\x9bW\x9a1\xc1x\x8e\xa37\x91\xed\xbc_'\xa9\xb7\xd8W\xe3L\x8d}\xaa7\xfei\xce\xd0\xa2\xf4\xfaQ\xdbH.\xa6,3uD\x8f\xd1\x81\x1e\x03'\xf2,\xfdEs\x18\xb5\xce\xd9\x95\x8c\xa5\xa7O\xf3\x13\xa6g\xc2\x13\xa8T\xb1\xc0\x1fO\xe8\x11\x12-\xcc\xd1\"\x8c\x91 aI\xb5\x93\x8e\x9a\x88Dm5\xdb\x11G\xc8\xb5\xbcG\x01\x07r\xeb \xec<\x0e\xd3\xfc\x87\x8e\x91t\xbc`\xe1\x05^\x8a:\xd94n\xc7g\xc4%\xcf\xc9\xf1\x14\xcd{\x12\xb8\x04x\xb1\xf7i\x9d\x15\xff/\x0e\xbe\xe6\xf3b\x1aF\xe5\x9e\x039;\x0c\xd8{\xb1y\xa6\xa9\xf6\xf3S.\xa0\xff\xfb\xbf*\xf2\x07\xb4_\xc4\xb6\x8f\x92N\xd5\xb0C\x1a\x02\xf7\xa0\xf3R\xf4\xa3\x91\xae\xe3\x80t\x1a\xea\xf9\xbf\xff\xfd_\xcf\xccO\x14\xec\xe7&\xa5N\x93W\xc3\x9c\x02I7\xfb%\x0eq\xa2\xd9\x8e\x83\xa2\xb4\xda\xac)\x87dj\xf3g\x19#\x14<\x85g~\xf5\x83\xe0ED,\xdd!\xf2!K\xcc\xb1\x17<\xa0\xf8`\xe9/\x9a\x17\x86P\xba\x15 H1\xcbc\xb5\x9d\x95y8\xba\xab\xda\xdd \xcc\x93 u\xb8\xe1\x05\xdc\x92\xb2\x06\x9d\x81O\xcf3\xa7\x83\xce\xfaU\xb7\xba\x8b\xea\xeb\xdf$\xc7\xcf6(N\xbc0\xd0\xa2\xd8^\xfa\xf6\x81\xdc\xaa\xa8\x83K\xe4\xb3\xe9?\x9a\xea\x8f?|\x94$\xf6\x12==\x82:u\xde#\xe5&\x06\xfcn\x0f\xf9@\xd8\xcc\\\xa0E>q\xd8\xb4\xcb\xc5\xf4\x82\xc6\xfe\xdd\xf56\xc4\x8bE-\xcbY)\x9dmTb\xde\xc9\x171Mt\\m\x97\xba(\xfbS\x8b\xdb\x8fv\x9d~\x11\xf6\xb2\x8bN\xba\x9ay\x1a\xb4\x9d\xb5&\xaf'\xf5\xc8\x83\x9a\xec\x19A\x93?6h&\xfcH\xbc\x8c\xed\xbd|\x05\x9as\x89\xec\x18\x05\xe9s_e8a\n\x9d\xa7A\xf6WK|\xd1\xc5\xad~\xa9\x19\x8e\xee\x9f\xae\x97\xd8s\x8c\xdc\x7fU\xef\x9b\x08\xc2\xcc\xe5p\xb8En=[uM\x8e\x90y?\x00s\xb9\xc9b\x9aer\xd7\x9fx\x04\xdf&\xc7\x0e\x1c\x84\xd9Sa\x8b\x81> \x97_e\x01i\x12\xb9\n\x0b\x0e|u\xf6:]\x85\xb1\xf7\x88\xe8\xeb\xd8\x13z\xb4\xab\xb8T\x07=\xe5\xa7?y\xe1$\xf5\x16\x89\x86\x05\x0e\xed4\xff\xb6\x0cm>p/\x9e\xa1\xdf,\x0f\x0b\x0fc\xf8\xc8e\x86-w\xaa\x80\xfe\xd9\x1f\x8fu\xd4\x03\x92[T9\xc7Q\xcb\xb8D\xa7\x0d\x9f\xe4\x8aZ\xc0\xb8\xe8\xff\xc7\x0fN4\x83r\x1f\xbcxU\x15\xd7\xb13\xadv\xb8\x03\xe2\x0c\x07l\x0b\x18\xe4\xa4\xf9_F\xdd\x95Y\xec\"\xf3\x98\xb5\x83\xb9\x18P\x0e\x0e\xca\xa2\xd3\\3\x0f\x95s\xce}\x98\xb8\xf7Y\xf6B~w\x8ef\xcc\xa8V\x06-\x0f\x80\x13}E\xcf\xfe\xb4\x89-\xbc\xf5\x0bO*\x05\xeb\xa1\x9e\xfd\xa1X\xcf\xd7i\x1a\x06\xec\xdb}\xc2u\x9a\x0d.\xbc\x02\x0bx\xd7\x0b66\xf6\xdc\x03\xbfVIV\xf6\x03\xeat\xfbI\xc7\x98\xc0O\xdb\x0e\x03\xffu\x81\xb83Fe\xd0{\xc4\xc4\x9b\xa7\x18\xac\xea\x1e:\x7f\xbc\xa7\xcc\xd9\xca\x13\xbb\x8ba\xf6\xa7\xb3\x8e\xf1\x8f\xae\x9d\xda\xe7\x9eo/\xd1\xcbd\xb3\xfcy\xe7\xe3\xc9\xdcN\xd0\xa0\x7f\xf6\xdb\xaf7\xbdo\xfb\x8b\xfe\xfc\xcbn\xed<\xea\x9e\xfd\xeb\x9d\xee\\\x86\x9bw\xa6k\xba{\xcb\x9c\xed\xad\x8d\xe3;\x9b\xd9\xfdt;{5~t}\xc7\xbb\xfe\xf5[\xf4\xedw\xf7\xd5\xdc\\\x8e\xaf\xef\xa7\xcb\xd9\xab\xe9\xbe\xf8{\xfd\xf3\xf5\xab\xe9\xf2\xfar\xb7\xfd\xfa\xfb]x\xfd\xe6v|\xfd\xa0\xeff\xfb\xbe>\xfb\xb8\\\xde\xec\xfb\xfd\x9b\x8f\xf8\xfe\xdd\xfd\xb59\xfb\xa0\xafg\xf7_\xfb\xef\xee\x9d\xed\xfb\xfa\xe7\x07\xf3\xfd\xab\xe9\xf6\xfaU\x7f\x7f\xb3\xef\xefo\xee\x97\xeb\xd9\xbd\xb3\xcf0\xb3\x0f\xf9s\xeb\xe6\x1e'\xef>\xce\xd6\xef?N\xfb\xd7\x97\xb3\xf5\xfb\xcb\x9b\xfbw\x1fj|\x9aa\x9b\x9f\x1f\xcc\xf7\x1f\xa6\xdb\xf9+\xfd\xf1\xdd\xfd\xc3\xf6}\xfe\xdf\xe5\xe3\xd7}V\x9f\x93\xbe\xbb\xbf\xee\xdd\xd4?\x17u\xbc\xfb\x90\xd5\xf1\x90=\xdb\xe5|\xef\x97\xeb\x9b\xc7\xa9U\xfd\xfc\xfe\xa3\xd3\xbf\xbe\xbc\x98\xcd>N\x97\xb3\x8f\xaf\x93\xb2m\xe9l\xdf\xdf\xdd\\\xbe\x1e\\{\xa3\x9f\x7f+\xf4\xf4\xf3O\x9d<\xaf[\x9c\xfc*b\xceN\x10j1\x8a\x90\x9d\x92\xf3ZqS\x9f{#\x84<\xa3\xd9SK|f0\x95(\xa8Y\xb9G\x11\xb2\xe3,Z(F\xa4\xfcEm\xecC\xe6w\xc0\xdd\xff\xe9\xafq\xeaE\x18\xfd\xabJ\xfeZ\xd4\xc15\x0b\xf4V\x80\xd1\x9f\xde]\xe9\xbd\x07.\x89\xd8\xcbg\xd8\xa3\xee\x94 8\x19#\x9d\xbd\xe0\xa5\x94\xdd}\xea\x99\xa4\xfch\xe1?\xb3%\xf5/\xc8\xb7=\xfc\xaf3A\xe9\xc2\xc3HX\x18\xd9I\xb2\x0dcW\x08H\x90\x1d;+aq\xb6\x1e\xa3\x0b\xb3'v\x8clRE:\x91l\xa2\x1dh\xc4\x0c\x8f\xc4\x86\xa1;\xce\xfe\xb4\x0d\x8f\x8b\x85\x9a\x15\xff\xf3\xd5\xd5\xbct&\xdf\x8a\x91\x1b\xbb\xeaO\xd2V\xb4\x81\xea\xd6\xb4\x01\xcbV\xb5\xc1\xf2\xd6\x81\xa0\xaa\x95\x7f\xca0\x00d\x8ar6\x07C\x7fq6\xd6_\x00Y\xb6:\xa5k\xba?jF\xb4\xcbF]0\xe5K\x96\xff\xbb\xa7\xbf8\x1b\xb5\xf2\xeb\xc9\xd9U\xc5\xff6\xf5\x17g\x96\xfe\xe2l\xd8\xcaQ\xeb\xb7HX\x95\xff\xbb\xaf\xbf8\x1b\xb4\xf2kaWs#3k\xff\xab\xd1g\xd1(8\x1403\x07y|\xbc\xd9\x9a\xeaQ\xb7\xe8\xf9\xd5\x137l\x92\x01u\xcb\xbb(\x8e:-\x00\xccMUK\x8aw|\x1d\xf8\xd0\x17\xb8\x1fU\x0f\x11\xce:\xe6\x0f%\x13[r\xe4d\xc2\x9c\xd5\x88QN\"P\xc0\xb3\x9f\xd9rV\xc8y\x98\x87\xbb\x03\x19\xf5\x97+Y`mD\xeez\x08\x1eW*\xd5\xb3?peOx\xfd\x86\x80aD\x1dD\xef\xeb:\xf1\xd1\x8d\xc2\x0e\xe4y\xb9J\xf3,HU\x8bP\xba\xae\x16\x85\x98L\xaag\xff\xaa\x9b\xca/\xa5\xa5t?\xe7\x8a\xfa{\xb7xC\x8f\xf0\x8dJt.K#\xf7\xcb\xf27/Tn7 \xcf\x91\x8f\xca\xedn2\x0ef\xcf|\xd0[Q\x8c\xff\xa1Q\xf6G\xf4\xb2$=_\x02T i!\x97\x08\"\xde\xf1\x90\xf7\x83\xfa\xa7\x13U\xd7\xfe\xca_\x85WFKk;\xcf\x7fB.e0^Y\xf9\x1a\xf8/\xc0\"\xd8Y\xd9q\x82\xd2_\xd6\xe9B\x1b\x9d\xbd0_%\x9be'\xb7\xe0/?\x18\xfa\x0f\x9d\xc2\x82\xbf\xfc0\xfa\xa1\xb3\xf1\xd0\xf6\"\xdc\xfd\xf2\x83\xd9\x19v\x0c\xbd3\xfa\xa1\xb3\xf3q\x90\xfc\xf2\xc3*M\xa3\xf3\x97/\xb7\xdbmwkv\xc3x\xf9\xb2\xa7\xebzV\xc7\x0f/\xcc\xab\x17\xe6\xab\xc8NW\x9d\x85\x87\xf1/?\xbc\xe8\x99}\xa3?\xec_\xfd\x90?\xd0\xe25F\xbf\xfc\x806(\x08]\xf7\x87\x8e\xfb\xcb\x0f\xb3A\xd74\xcd\x8ea\xbd3;\x86\xd1\x1d\x0c\x86\xd8\xc8\x9eh\xd9\xbf\xfdN\xaf\xd3{W<\xce\xc40;\xa3\xac\xec\xf1\x87\x97EMY\xa5/\xcc\xab\xbf\xfc\xd4\xb1\xf4\x17\xcdZ\x93\xd6\xa8\xeb\xd98\\j\xeb\x1d\xf35\x9d \xf9\xa2U\xea\x1e\x8b^\x1dV\xaa^\x03,`\xd8\xe9f\xbaw\xe30\x02\xb8K\x19\x8an\xc1\x8c~\x12V\xe5\x87\xae\x8d\xa9z\xea-m\xae!\xd4\xfe63)\x16\xbf\x9a\xe5\xdcP\x7f\xf3\xc3\xe2\x86\xe2\x937\xf8\xf9\x05JuY\xafm\x81\"\xc8\x07\xe8\xd1\xaeS\x9c\x9c\x92\xbe\x04Z\x8ckUj\xb5\xb1&;\x06g\xf5\xc90\x82O*J\xd8\xd2\x17U\x80{6U\x9e\x9c\x9fk\x95V\xb8\xd2\xba\xe9K>#f\x81=h\x16\xd8O8\x9a\x04\xd5\xff\x94\xd7\xce\xd5\xb1J\xaf8/':*[:\x16\xe96'\x9d\xffQmM\xa7\xeb\xe00AZ\xfe\xf8\x88\x94\xfc\xf3e\x9bd\xc2\xad\xc8\x0f\x83\xf7\xd8c?\x03\xf2\x0d^\x8d\xe8\\\x1eN\xb4Ir\x82[\xf8\xa1+O\xef\x98\xfa\x91g\xea\x85\xb5t\xba\xc4}\xd9$\xb2\x99\x1b\x11<&u\xabc\xb9\xb6\x9e\xfd\x11\x9d\xcc\xe5(\xff\x9e\xba\xcc\x8dK\xf5w\x0f\xe5\xcc\xb44\\.1b\x8fh\xc1\x81\xd7@\x14x\x95\xa6\xccF\xa9N\xd7D\xbe\xc2\xebo\xb8\xe1]\xf8*`u\xe4\xa9\x08\xe8C\x0e$\x03~**\xcf\xf1\x8cu\x17-\x81\xf3=\xe5s\x8eN\x0bc/\xcf\xa6\xe9/\xb2(a\"*\x10\x1b\xaa\xeb\x84\x18\xdbQ\x82\\\xf1\xa9#\x81P\xf9c1\xe7\xf2\xac\x1et\x02\x8d\xdd\xc0\x12\\\xa1=*\xd2k\x0f\xe0\xaa`\xb0\xd7o\x82\xc1\xec\xe7:\x1a\xcc\x83\xea~\xa7\xd7'c\xbd,\x8c3\xf4\xce\xe0\xdd\xa8k\x8d;\xc3n\xdf\xe8\x18f\xd7\x18v\x8c\x1e\xd6\xfa]k\xd4\xe9w\xad\xf1;C\xef\x18#<\xd0\x06m\xf1\x1b\xb7W\x90\x05/\x90\x16\xef\xd7~\xa4\xa5a\xfe60`\xe1\";\x01\xc43\x10\xbfz\x8a:;\xa8u\xfb\\g\x03-\\\xdc\x87\x97\x1f\xe3$\xa0\xd5\xbb\xa5\x8aG+/H\x0f\xc4!\xbb\xfcG\xf6cc\x04T \xab\xd1\x1d!\x7f\xc2\x9f\xe3\xab\x86\xff\xae\x81\xfcN~\x14\x08\xf8\x1eo9<\xaa\x04od\xb85\x84\x1c\x9e\xb8D\x95\xad\xfb\x99\xc3F\xe5\xc9\xb2\x02\x9a\xd4W0ub\xf2\x97\xbdR\x9a\x97M\xc2\xbdz\xc1)1{\xeb\xfc\x0b\x0f`\x9a,\x96b\"7Qh\"\x7f\xef5\xcd\x9e \xd1\x9e\xe5-\x86'\x85Ap\xb2\xe8Y\xdf\x13.\x0f\"\x06:w\xbc\x86S\xd5\x13_\xa3\x0d\xf0;\xe9\xcd\xde\x1c\x9f\xe3\xde_\xce\x92[\xac\x07\x90\xddEo\xdd\xf6\x02\x0e\x0b05\xa8\x0d\x99\xf9\xeaQ\xda\x17*F\xc0e\x97\xfa\x82\xc3Q\x1f\x1c\x02\xde\xc6\xa7>\xd8\xb0\xdf\xeej\x91\xb5\xc5F\xc3\xe3\x98\xd1Q \xf1\xda\x90\xa3\xb8\xe4\xa7\x83\x18&\xad#\x12\xc7\xa6|\x90\x08\x0cLM\x0b\xa3\xfa\nVf\xab\xe6\x15;\x96B\x85\xf3pw\x90\x1e\xdai`T\xc2\x19\x8ca\x95\xcd\xcc\xbe\xcc\xa7\xae\xe4\x08\xb7\xe6Ni\xd5L\xba\xd0\x0b\x87,\xf1\xa4\xce\xf4Ty\xcf\xb4\xf4\xec\x0f\xc4\xac\xa9U\xdb\xdaq\xe0\x05K\x903\xb7|\xab^\xdcR\xddn\x17\x1fV\xe4_Q\x97\x8du\x7f\xcf\xfe)\xa7\xe5\xee<\xb6\x1d\xa4\xe5\xabZjF\x84\xceBEq\x18i\x81\xed\xb3\x87\xb8\xa9\x15I#\x1d@\x9c\xfbx\xa5\x18\xcb\x06\x10(X\xfb\xb2\x0b\x8f9(\x0b\xb1\xed\xf4 \x9e4\xba \x8a7(\x16\\\x1f{\xb6\x0bYd%\xa2\xebW\xf47f@\x06\x9dU\xbf[\x9d%\xaf\xee\x1e\x94\x01E\x8fUcE\x92\xdas\x8c:i\xf55\x16So\x01\xba\"\x9b\xd5\xd2eQ \xf8\x85\xdb u\x1f\x82H\x82i\xc4\x9dNy\xe5\xf0\xeb\xfaKWik\xa3\xdb\xe1^\x0eE\x1c|\x87I\xbbN\xe8G\xeb\xack\xadc\\\x0f\xcd\xfc\x91~\x10_\x1cC\x07\xf5E\x9c\xaa\x9d\x88&l\xce\xf5\x978\x9c\xdbX+\xea\xfa\x8f\xbe%*\x90\xb4\xd6S9\x00\x92g\x9c{\xd50$~=S\xf5\xaa/\xc0\xdd\xcb1C\xe0\xed\xb9\x03@/\xc3\xa12nZ\xb5>?\xaf~\xe0\x99\x94\xc3]\x9a\x9fLJ\xe3\xac?\xd4\xbcX\xafg?\xd6,`\xc0\xf8tu\"\xa5O\xbe\xe2\xab\xd8\x84\x82ZU\xde\xefN2IZ\x12dp\xa7|j\xda\xac\xec\\\x80B\xaa7\xb7)\xe9E\xa2\x91fl\xe9Q{\x0f\x03\xe2\xe6 \xf0V\x9f\x92m\xfe\xea\xc6\x9c\xed\x99\xact\xd5vz\x8cI%\x13\xd7b\xf2c\xf2\x8a\xeb\xb7\x9e\xda\xa9Bf\xae\xaa\xbe\x8c\x93\xb0/\x93\xe0\xce\x02\xc1\x1f\xd52\xf9\x17>Ix\xd2\x97\xcdJ\x86B\xfa?\xfe\xc8grI\xc4\xd1\xd7O\x99\x14\x99\n\xba1\xfa\xef\xb5\x17W\xaf\xc7\x11\x0d\x12\"*\xf86+\x1c\xe0i\x03\xfasCM\xca\xac\xe2\xf6\x97R\xf0\xf2e\xd0V1\n\x0e\xd8o\xae6\xb2\xa0]\x8a\x82\xc4\x0b\x99l2\x81\xf0\x14^\x9csLW\xe5?\xccBT&|m\xfe\x13+\x8d\x91+V\x81\x1f\xa5\xfb?66^\xa3?\xf8\xc4\xb5ID\x03\xe5\xda\x91\x8b\x0e\xb8\x17\x0cJ\xb9\x97\x93=\x15L\x0e\x8f\xe2\xd0\xad\xee%5\xc1<\xffjH\x8c\x80\xab\xee\xfc\xa6^\x1aFs\x9b\xfeb\x0dpE\xa7|s\x0eDZ\xfd\x17~\xcd`\x89\xb1O\xdb%{r\xbe\x07\x14\x98:U\x95\xe7\x06\xd9!U%WB\x8eb\xf9^3\xbbIR\x1c\xb9\x90\xaf_\xd8cD\x95\x84E\xca\x06\xd8\xcc\xe2#\xd1\xca\n\xf5+J\xd61\xae_\xd3\xf7d\xad\xe7m5\x9b\xd6\x9b\x93\xea \x01\xca/r\xa2\xc0e\xaevfO\xd8{\x9dy)\n\\\xf56\xb4\xcc$\xa5\x86\xf8seV\x7f\xb8\x80\xbeJV]h\x12\xdf*\x91\x8b\xd3-f!\xed\xf4\xb3WOw\xeb 8\x99\x0e\xa8\xe3p\xa76\xa9\xbcgG\xcf\x9aJ\x1d\x82\xf6\xd2<\xc0\x92\xbf\x19\xf2\x18\xa1\x8a\xa9\x9f\x93\xa3\xd7\xc8\xd1\x9b\x94\xff!\x94#t\x0b\xea\x04$\xb0\xee(\xcf\x0dR\xbf\x1f#<\xf5\xb4\xbc\xd5$\x89D\xc88\xae_\x1e\xf2\x90\x9c\xe1$\xae\xd5Q\x8b\xa8\xb2qG\x0e:^\xb0\x08\xeb;\x1d\xc0K(\xb3\xf2\xce*\xbf\xee\xd7\xf5m/`\x97urt\x87=\xc4\n\xc0\xb1w\xc6?\x8c\x80g\xc5z\x89\xe0w\xda+\x0f\x0b\x19\x0d\xa0\x02\xf6\xf3\xc8\xc5C\x13z\xd8\x87\x1eZ\xc7\xbf9\xa0\xa0,\xdenU\xad\x8f\x8b\xdbb\xea\xe9C\xdd:\xf2\xa4.\xf4\xee\xf7\\\x0e\x9b\xd5\xeeQ\x1b\x11-\xb6\x80\xae\xc9\x16\xb5\xd2\xef\xbc3\x16\x83\xb1\x03xay7\x9f\xdc\x9f\x02\x98u\xe7v\x824\xe0\xe80\xa9\x0b\x93:\xdbZ\xcf#G)Qh\xcc.\x9bF5\x07O{w/\xc1\x95\xff2\xaad\xc1`\xb5\x1c\xae(\xd6\xef\xe4\xcb\x9d{\xc5\xc0\xc2.\x8d\x93u\xc4\x1dd\xb5\x86\xcc\x01\xb7\xa1;\xea\x8f!\xf3\x92\x92\xe7\xaf\xdbST\x057T\xd9\xebt\xa5\xcd\xd3\xe0i\x01\x0e\xbd6\x7f\x8e\x17U\xc8\xa5,\xeeK\xbba\x80\x0e\xf2\x14rN\xf8\xa4\xa6)M\xd4\xcf\x1a\xbb\x912w\x88\xd7\x040)\xd0&4\xd1\x9a\x97\xe3\x01\x9c\xc0\xe4\xa1\xc1\xdeo(\xd2\x89-\xa7\xe6d\xdc\xe1M)a\x1dl8E3#v\xcd\xcbc\xffV\xb4\x13\x1d\xb7bH\xeb\x8f\x8e\xf3\xc1\xbe\x94\xae\xf5&\x9a\x84\xa0\x08\xa3\xd9\x1b\x90R)Q\x1c\x87q\xc2\x0e\xa8\xd4\x06\x18?Y=y0M\x9c0BIg\xd5{\xfa\x94\x9f\xb3\xd2\\\xb4\x90\x1f\x8b(\x1b\xaa1V\xe9\xc1\x0eXu$\xe2\x92\x9acc\xf4)b^\x80E>\xe5C\xd2\xea\xfaZ\xebd/\xf9&\x15-v\xf9;\xdb\nx\xd3\x0b$e\x8fl\x08\xdf=\x7f\x92]\x05U&\xc4\x8b\x9f\xc0M/\x86\xae\x882\x9f>P\x9e\xb4\x06S\x90\x8c\xd6a\x8f\xba\xac\xa44P+\xb99t\xc7\xb1\xf0\xb7\x03x9\xad\xbc\x971\x02\xeej\x8c~\x9a4\xaf\xc6\x02\xdfAV\x00\x0d\x9e\xd6hH\x0d\xfav\xe0\xff\xb4,\x94\x9d\xee\xf2kaq\xb7\no\x9aTZ\xe5\x1d\xf9J\xef\xff\xbc\xfc\xdb_;I\xb8\x8e\x1d4\xb3\xa3\xc8\x0b\x96\x9f\xee\xde\xfd\xd20\xea:I\xd2\xf5\xed\xe8o/\xff\x7f\x01\x00\x00\xff\xffPK\x07\x08_;\x94/\xe8Y\x00\x00\xa8X\x02\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0c\x00 \x00swagger.yamlUT\x05\x00\x01\x80Cm8\xec\xfd{w\xdc6\x96(\x8a\xff\xefO\xb1\x8f~\xbf\xd5\xb2;r\xe9a\xf99\xe3\xb9#\xbf\x12w\xe2Xm\xcb\xe9\x99\xee\xdb\xab\x8c\"QU\x8cXD\x99\x00%\x95s\xf2\xdd\xef\x02@\xb2H\x16\xf1\"Y\x92\x9c`\x9f\xb3\xa6\x1d\x15\x01ll\x00\xfb\x8d\x0dz\x89f3\x9c>\x83\xdd\xa3\xd1\xc1\xee\x9d(\x99\x92gw\x00X\xc4b\xfc\x0c^\x12\xba \x14>\xbe\xfa\x11\xee\xc3Ox\x86\x82\x15|x\xfd\xf1\x0cP\x12\xc2\xec\xc3\xe9K\xf8\x1e1|\x89V\x10\x92\x80\xde\x01\x081\x0d\xd2h\xc9\"\x92<\x83\xdd\x13\xf9q\x940\x9cNQ\x80aJR\xa0\x0c1\x0c_2\x9cF\x98\xeeA,{e)J(\nxC\xba{\x07\xe0\x02\xa7Ttr8:\x18\x1d\xdcY\"6\xa7\x1c\xb1\xfd\x84\x84x\\\xa0 0\xc3L\xfe\xa31\xf6\xdbdJ\xd2\x05\xe2\xff\x01hB2\x06l\x8e! I\x82\x03\x86C\xe0\xdd\xe4\xedh\xb6X\xa0t\xf5\x0c\xce\xe6\x18\x96)Y\xe2\x94E\x98\x02\x99\xaa\xdb04\xa3\xc5\xb8\x00\xf7\xe1{\x14!1\xd9\xfco\xcb\x94\x84Y\x80k\xdf\xa0\xe52\x8e\x02\x81\xd2\xfe\xaf\x94$\xf9O)\xa6K\x92\xd0\xea\xb7\xbbG\x07\x07\xbb\xeb\xfflL\xedg\x12bA\xc5\x8cV>\xa1\xc1\x1c/P\xb5\x11\x00[-\xf13 \x93_q\xc0j?\xacgYo\x00U$\xc7\xc5\x1a4>\xd15\xe70\xc9\xa28\x1c\xd7)T\x05\x89\x15ei\x94\xccZ>\x08\xe2\x08'l\x9c\xa0\x05\xee\xd6\x9e,\x16\x11\xeb\xd4tF:5\xeb\x8c*\xc5\xe9\x05N\xbbOU\xb9@\x86\xb6\x8d3T\x05\xfd\xd2F\xa1\xf3X\x1c\x16$\x89\xceq\xda\xa9-\x00\xbeB\x8b%\xe7F\x17(\x8eB\xc4Hz\x9fS\xac\xe5\xdbeJ\x18 H\xac\xde\xb9`\x9c\xa2\xf8\xe2h\xa9\xfa\xc9\x02_\xa8\xe2\xfcX\xf1\xc9$&\xc1\xf9P\x83\x1c\x1e(\xbeA\xcb\xc1&\xd26D\x82\xd9%I\x15\xd30v_v=C\x11\xba\x7f\xd4v\x94\xe7(Ip\xdc\x8d\x8f\xc4\x11e8\x19\xa30\xec\xbd\xf1v\x0f\x9f\x1e\x8d\x0e\x1f=\x19=|4:|v\xf4\xe8\xd1\xc3G\xbb\xae\xc7\xb1\xc6\xc2\xcfp\x12\xe2t\x11%\xach\xd4\x13\xc3\x83\xd1\xe1\xc3Q\xdb\x12\x116W\x1d\xbc\x1aF\x0b\x92b\x88*B\x93$\x05jT\x83[\x8bl)\xc0|\xcc\xd8\xd58JB|5\xd4\x16\xdd%I\xdb\xb2pH\x97\x81\xd8 \x98*\xb1q\x1e\x8d\x05\xcbg\xfb\xfb\x07#\xf1\xff\xc4\xaex\xbc\x1e~\xf7\xa1N\x84\xbfAQ\x8cC`D\xe8A+\xc1\x90\xd7\"}\x9f\xae\x92 Jf\xb2yE\xc3)5\x95\x8f\xf2\x83\\\x97\"S\x9djR\xd9k\x1fN_\xdei\xc1\xe6{\xcc \x92\xca\x8e@$\xa2\x10di\x8a\x13\x16\xaf\x80\xae\x12>\xd2e\xc4\xe6r3\x89o\x8a=\xb1}=\xa72\xd3m\xe8;5RWA\xf65!$\xc6(\xb1\\\xd6\x8fB\x9eK}7A1\xe04%)_P\xc1\xed\xe9~\x8c\x18\xa6L\xbd\xac|!\xf8*\xc8\xef\xa4\x8cpY\xd5m\xae\xc6Y;^0\xdcR\x88n\xc7\x0b\xcc\x90j5\x14\xdcF\xcfi\xe6\x18\x85z\xdd\xa3\x17\x13\x0b\xe6(J\xc6*\xc5\x08\x9c\xd9J L\xaey6i\x95\x88 &\x14\xcd\xe6\n\x05\x17\xca\xf1\x92l1\xc1\xa9y\xbcC\xc5',R)\xa5\xe0<\xa7\xdd\xa3\x83\xc3\xc7\xf7\x0f\x8f\xee?88;x\xf8\xec\xe1\x83g\x07OGGO\x1e\x7fwp\xf8\xec\xe0@\xc5\xb3\x93l1fWF~m;Q\x95\x8e\x14#\xca\xc6r\xef\x99WQ\xb3U\xc0j\xbbp\x98#:\xd7\xfdnI^\xa8\xce\xee\xf5\xeb\x87o\x1e\x1c\x1f\x1c\x1f<8~\xf9\xf0\xe8\xf8\xe1\xc1\xe1\xa3\xa3\xa7/\x1e>z}\xf0\xea\xd5\xcb\x07O\xde\x9c\xbcz\xf4\xf0\xf0\xcd\xc1\xb1\xa6\xb7%J\x99\x16oK\"\x805!80\xc2Pl\xfa\xc8r\xad\x0b0\xaey\x01\xe6\x95\x00\x97\xd5\x80\x01WD\xd0e\xc8\xfd\xff\xe0\xa1\xee\x00H\xaby\xac'\x88\x15!\x86\"@\x88\x18\xbaM\xf8\x94\xd6'\xbdMX%\xf8\x8a\x8do'j\x01\xd7/\x12\x9a\xdd*\xa4\xd0ry\x9b\xd0\x11g/\xc54\x8b\xd9\xad\"\x13\xbe\x88B\x9c\x04\xf86\xe1\xc4e\n\xa18\x1d\xc8\x90\xabi\xb7\x13\x1c\xcc\x1f\x1c\x01N\x02\x12\xe2\x10\xf2\x11\xccS\x92\xda\xdaa\x88\x97\xe7\x0f\x8f\x83\x0c\xfd:;\xff\x8a\xd1\xa3\xaf\xcb\xd9\xf9\x97\x07\x8fX\xf2\xebe\xf8\xf5\xe2\x18M\x83\x07\xe1\x91\xca\x15\xa4u\x1b\x80\xad\xd4\xb5\x93\xb8\x06\xb7\x13\xd8\x12\x0f\xac\xdcO`rAA\xa7\xf1\xda\x86\xd3+pF\n\x9a\xa9w\x9b\x0e\x82^Q3N\x16\xac&\x0cv\xca\x99\x95\x12\x02\xa6\xe5+\xc0\xac\x90YQ\x1a\x06\xa0\xb6\xe2\xa8xKt\x0d\xde\x12\xcd\xc1m\xa2\xde\x12\xf5\x96h\x13\xcc+\x01.\xab\x01\x03\xae\x88\xb7D\xbd%j\x81\x95\xb7D\xdd\x90\xf2\x96\xa8\x15^\xde\x12\xf5\x96\xa8I\xda\xdd*KT)(e\xf7(M\xd1\xaa\xf5\xf7\x88\xe1\x85:V\xae\xc7\xad8%\xd7?rEfo\xcd\xb2\xf1:\xb1\xd7\x89\x95`\xbd\x1a0\xe0\x8a,S,\xf7\xbc\x91\xf7\xabO\x1d\x98N\x1e\xd8\xaf\xa9\xed\x8a\x96\xfa\x99YtI\xb0\xa6\xee\xbagCN\x8f\x04\xeb~\xab\xc6\xbb\xd2@\x97`rGH\xd8\xc6\xc8)\xc9\x12\x0dw\x92\xb0\x8d\x81Y\xb4\xc0\x94\xa1\x85A\xb2u\x1c\xbc\x93\xb3D\x82\x18\xcf\n'+\xaeQ\xe2\xa4rEI0\x0b\n \x96\xa7\n\x1cN\x16X3,\xa7\xc5\x80\x01\x99\xd6\x1a,\x84\x89\x04\x07B\x81#\xb1\xc0^\xbcHp\xd8.\x05X\x8b\x1a \xb6\xeb\x07\xeek\x08\x83\xaf#\x8df bYjy\xcc\xac0-1\xfc\xaf\xfb\xc69=\xce\xce^>>\xfe{|\x9e|\xf9\xdf\x7f\xbc\xbe\x9c=\xfe%y\xf4\xee\xc9\xfb\xc5\xe37\xd9?\x0f^\xbf?\x9e\xfcz\x91\xfd\xfa(\xbd\xfc\xe1pq\xf6\xe9o\xe9\x87\xec\xdd\xbb\x7f^\x9c\x9c|9{\xfa\xcb\xaf?\xcfN\x0f>\x9c\xec\x9f\xbdZ>\xca\xf6\x9f\x1e\x9d|I\xff9\xfd\x9f\xbf}\\\xbe\xf8\xfb\xf3\xe7\xe5\xc0\xddr\xedv\x8bd\xbb\xdf\xa48\xf8=\xefB\x95o\x87$\xd3\x00\xc4\xff\x19\xe0\x94\xa1(\xc9%I\xfe\xf9\xd0\xa9wK\x94\xa2\x05f8\xad}\x1c%\xcf`\x89\xd8\xbc2_q/\xa0\x8e\x0b4\xc9\xf0B \xbf\xf1M\x8a\xbfdQ\x8a\xc3g\xc0\xd2\xac\x9a*\xaf8DW\xf77\xdc\xf0\x9d2\x04+\xb4\xa4K\x1cD\xd3(\xd8D\xce\xe7\x0bZ\xd82\xb6\xae\x0c\x1f\xa5)\xc0Gi\xcc,~H\x11d\xa1DX\x11\x01\xac \x01\xf6*\x83\xd5Z\x17`\\\xf3\x02\xcc+\x01.\xab\x01\x03\xae\x88\x8f\xd2\xf8(\x8d\x05V>J\xe3\x86\x94\x8f\xd2X\xe1\xe5\xa34>Jc\x92v\xb7*J\xe3\xf3\x05K0N\x16\xac&\x0cv\xca\x99\x95\x12\x02\xa6\xe5+\xc0\xac\x90YQ\x1a\x06\xa0\xb6\xcf\x17\xf4\x96h\x0e\xde\x12\xdd\xfeq\xab\x82\xb7D\x15`\xbd\x1a0\xe0\x8axK\xd4[\xa2\x16XyK\xd4\x0d)o\x89Z\xe1\xe5-Qo\x89\x9a\xa4\xdd\xad\xb2D}\xbe`[\xfb^\x96\x8d\xd7\x89\xbdN\xac\x04\xeb\xd5\x80\x01W\xc4\xe7\x0b6\xc1\xe7\x0b\xde\xc4\xc0>_\xb0\x06fA!\xc1\xf2T\x81\xc3\xc9\x02k\x86\xe5\xb4\x180 \xd3Z\x83\x850\x91\xe0@(p$\x16\xd8\x8b\x17 \x0e\xdb\xa5\x00kQ#\xc1v\xfd\xc0}\x0da\xf0u\xfc\xe3\xe7\x0b\x1e\xeb\xb2\xd3\xde&B\xe24\xb3\xd1v\x8f\x0f\x8e\xd5\x8d>\xe0/YY\xf1.o\n!\xc14\xd9\xadt\xd1)Oq\x7f\xed\xfa\xc0\xcc\xb94`\xd9\x18(\xdeV\x9eb\xa7\x04\xc0\x1ab\x806\xeb\x19n9\x1dP%\xd35\x9bz\xbd\x10\xaaf\xed:\x99R\x1730A\x13\xd33hZ\x16\xc7\xb3\xbb\x83\xa0\xe1\x1e\xb8@1\xc7\xf5\xf0\xd1\xd5\n/\x96x\xb1\\>=\xbaz:_}\xfd\xfa\xf42\x9dM\x9f\x1e\xa7\x8f~}:\x7f8=\xba\x97\xd9d|\x8eW=fc\xc3dJt\x03\x92\xd0e69\xfc\x1a\xfc\x1afx\xf9\xe5\xe0\";\xfa:;\x9f\x9d\x1f?\xc5St\x90|\xb9\xfc\x9a\x84(\xf9\xf2pq\x1c<^\xa2\x07\xd91Z~=\x9e\x1d\xa5Ogt\xf9e\xf6h\xf64\xa0\x0f\xce\x9f\x06\xd9\xb4u\xac\x0b\xc2\xa2d6^\x92KU`\xcemJ\xbb\x87\x07*\xcd\xa8t\x1a-\xd3\x88\xa4\x11\x1b\x84\x84\x8d\xf1\xba\xb1\xae\xdd\x06\xef\xb2\xce\xb4n0\x07\x9fn\xdd7\xddz\x83\xdbV\xd2\xae=\xb7\x15\xe0\xb9m\x05,f\xe3\xb9\xed\xf6\xb8\xed\xf0\n\xea\x8b\xe2\xbeE\xae\x9b&\x84\x01\xba@Q\x8c&\xf1\x9a\x0fue\xf3\xec\x8a3wD\xe7-\xac=\xc4\xcb\x14\x07\x885\x98^\x83\xe3\x9f]\xc1d%\xec\xa4\xfc\xf7\x0d\xee^y\xf7\xe5N\x0br\x1f0K#|\x81\x01U\x9f\x88\x81\x8cF\xc9\x0c\"FE\xdf\xa3\xbc\xe5\x16\xa5\xc2z\x06\x1b(\x9e]5\x7f6\x88\x83\x8d\xcdS\x11\x07/^\xbex}t\xf0\xfa\xc9\xab\xe3G\x8f\x1f>y\xf1\xf4\xd1\xc9\xeb\x87O\x9e:yy\xf0\xe8\xf5\xc3\xc3\xe3\x07\x0f\x8f\x9f\x1e\xbcy\xf1\xea\xe5\xc9\xeb\xa3\x87'\x8f\x8f^x\xf2\xea\xe9\xe1\x83\xa7O\x1f<=|z\xf4\xf4\xe1\x9b7\xc7/\x0eN\x9e\x1e\x1e<~s\xf8\xe6\xe8\xe5\xab\xd7\x07\xaf\x1e<>y\xf2\xf8\xe5\xeb\x83G\xc7\xc7\xaf\x8f\x0e\x1f\xbf|\xf1\xe6\xc1\x8b\xe3\xa7\x8f\x1e>j\xe2\xa7\x15j\n\x7fB\x89\xe1\x83GO\x1a?\xb2\x16\xe7\xa6Vh\xe9E\xd6\x82\xb6T\xab\x07\x83\xf4\x04\x93\xef\xd8\xc0\xd6\xa6X\x1b*\xea\x15\xad\x99!\xa3S\\\xcbn\xd1\x82d\x891\xab\xecv\xf9\xd5C\x9c\x90\x85\xfe\x13\xab\xb9\x17Pn?\xca\xd0y\xdb\xd38k0\x91KB\x97\xb1w\x1f\xb6\n\xd7\x05^t{W\xc9\xe0\xb12.\x89y1,|bV\x84\xb0Q\x9a\x00\xde\xbd\xfe\xf4\xf2\xed\xdf_\x1d\x1cM\xe9\xab\xd3\x14=y\xc7&\x1f\xe8\xea\xc5\xe1\xe5\xe3\xc9\x97\xb3w\x0f\x1f\xfe#;|\xf0\xe4\xeb\xdf'o\x82\x7f\\\x1d\x7f\xf7\xf2\xcd\xea\xe4\xed\x0c?\xfc\xc7\xcf\xa7\xd3\x1f\xdff\x17__\xfc\xf3\xd1\xd3w\xab/?\xd0/\xaf\x9e|<|{\x19\xbd^~\x17}\x9a<\xfa\xe5c\xc8\xe2\xe5\xec\x7f\x9f+\x866\xe8\x84\x16\x84\x04+bB\xd1\x95v\xbfX\xd1\x13\xaa4e\xa5\x01\xb8\x7f\x9aM~\xc4\xab\x8f8X\x1e=|t\xaeJ\x00\x05ifd\x83crr\xf1\xf5\xe0\xf8\x979\xfb\xf1o\xf3''/_\xfe\xf25~\xfb\x04\x9d\x11\xfa\xfd\xea :\x7f\xf3??\xbe\xfd\xe5\x87\xbf?\xf8\xf5\xc7w)\xa1?\xa8\x98U\x10\xf0\xe37\x96b\xc4\xb4&\xb6\xdbN\x1d\xf6\xa1\xf8K\xa6\x0e\xf4\xc3\x00#\xc9\x1c\xa0AE\\L\xb4\"N\x89\xeb\x0c\xd1\xf1%J\xb8N\xda\xa5y=\x94u\xa0\xb0\x15\xf8 \x19\x1db\x88G\x0f\x1e\x1e\xb7\x8d`z:\xaf\x97\x88\xd7\x1es\x9bC\xaee%\x16\x04\x00\x9b\xd3\xd9\xda\x8b\xde\x8cy[\xd8/\xb9=\xf3\xbap\xb4\x97 6f\xeb\xc5\xc2:Y\xbf\xc1\x84Q\x1a\xcck\x0fW\xdeiA\xab\xe53n\x12\xe1\x0b\x9c0:\xa8\xe1\"\x9e\x92\xaaPGZ.\x0bL)\x9a\xe1\x91\x1c\xbb\xf2\xb3b\xa1j\xc87\xc4Y\xd5\x02\x93\x13\x00\x9a\x05s@\x14v\xeb\xe3<\xa78 w\xe1r\x1e\x05\xf3\x9cCP\x88\xea\xaf\x9cqScJ\xe2\x98\\r[\x0e'\xe1\x92D {\x06\xbb\xdf\xbf>\x13\xab\xf6\xff\xb4\xf59\xe26.\x066G\xf5M\x8cQ0\x87\x05 \xb3\x18CH\x82l!\xd0\xe3\x16\"\xb9,\xb0\x1dAL\xc8\xb9x\x85\xf4\xeaj\x9c\xffm\x11B\x94pdj\xdd\x05$\x956T\xc8\x91\x93\x0e\x8f\xfb4<\xdf\x0fI@\xf7\xe9\x12\x07\x10F)\x0e\x18\xa9\xd1\xbcb\xc9ql\x9dV\x88\n97\xdc\n\xf1\xcd,\x8d:\xd9\xb3\xa4l\xeds\x15\x95\xffR\xc7\xe9y\x9e,hrL\x1d<\x90\xa9\xe4\xcb\xb0\xc4i\x13\xe7\xc1\x10bW\xa3E\x94lx{U\xfd\xd7\xf0\xad\xf1&\x92H\xdfn\xbeur\xbf\xd2,\xc5\x88\xf1\xb9\xa4\x80\xbfd(\x066\x8f\xa8d\xe3\xedX\x1f=\xb4F\x1b]m\x0d\xed\x18S\xcaYEb\x8f\xf8\x13!\xf8\xf3\xdf\x9c\xdd('q\x0c\xec\x8a\xc2\x02\xb1`\xce9G\xcd\x9f\"9N\xa5\xed@\x1e\x15y\xe3\"h\xb7\xebd\x7f&\xb7ES\x97\x1e\xb43\xbe\xe9\x95\x1ao\x8f.\x15\xe9 \xddz\x14G\xbakg\x0f\x9a #\xadY\xbd:\xf5m[\xf1\x0d]\x8e\x8a\x85\xaefc\xd9\x0e\xec\x7f\x93\xa0O\xce\xd3\xae\x8a\x04\x8dGNB\x9b_.\xffe\x18MY\xe9\xa9\x93`R\xe6%\x18=SV\xcb\xa8\xf1\xe0I\xb0\x982XN\x1bL>= VX\x83\xa3\xc3\xcaDM\xb0\xa3(\xd8SD\x82-]$Xy\xff$XS\xa9\x00\x07O\xa0\x04;\xf2J\xe8\x8e\x8d\xc27(A\xed!\x94`5\xac\x85/\xcfzQm\x97\xd3jL\xb0\x9d\x81\x04\x1b\x8e[\xc0\x0dy\x14%\x18\xfd\x8a\x12,I\x0e\x0ed\x87\xa2[\xe3WN\x94\x87\xde^G F\xefF\x01]q\x1b\xc0\x0f)\xc1\xd6\x1b)\xc1\x01]\x0b\xcf\xa4\x04\xb3\x7fR\xc2\x90c\xab<\x96\x12,\xf6\xab\xcd>U\xfa0%X\xcd\xc7\xe4\xcf\x94`\xd5\x95\x9doS\x82\xde\xc3)\xc1}P\x95\xb7S\x82\xda\xe7\x99\xffn%\xde-D\xbb\xc5\xf2J\xb0Yd \x16L\xd0\x9a``\xcf?Z{\xb4\xcb1\xa1\xd2)\xd9\xb0G\xbb\xf9W\x01\x96\x84\x96\xa7\xc9\xc5\x83\xfa\"%(\x0c\x10\x15ik\xd1,\xc1!\xb0\xab;-C\xb7~\x08\x8c\x00\x82i\x16\xc7\xd5\xd7\xef\x03\x92\xd0la\xe7I\x1d\xc2\xe9:!a\x9bW\xa3\xc4XE\xcd\x86p?\x9bc>\xa5EF\x19L\xf0z\x9a\x1fYxv5\x12?\xd3l\xb9$)\xc3!LJr,H\x88)DI\x10ga]\xd7\xfb\xbc#\xdc!;\x9f\xef\xa6\x98ei\x02h\xcap\xca\xc7\x90\xf7\xd0\xee\xed\xc1\xe7\x1d\xbaJ\x82\xea\x178\x85\x97s\x1c\x9c\x9f]\xdd\x03T\xf1^\xca\x0eQ\xfd\xf3TxX\xd0%Z\xdd\x1bU\xbeT\xe6\xbe\x0c\xe5\xeb\xf0\xd9\x14>\x9b\xa2\x01V\xf6\x94\xc5\xdc\x0bp\xb0\xa1L\xe4\x92\xd0el\x9fM\xe1\xb3)\x8c6\x8e\x15=\xa1\xb7]c\xa1\x91\xb8c2\x80\x15ck\xbfX!g\xb4\x1bl\xac\x95\xbe#q\x89\xae\x12p\x8a^\xcb\xde\x84\xc4\xcf\x7fv\x8e\\\x9c]\xad\xf5\x8a(\x99\xe5FR\xe5\xeb\x81\xe4w\xc0\x15\x8c\xf1\xc0R\xf7::V8\xd0_\xd5h\x1e\xa8n\xfe-q\x0bJ\xde\xe7\x93m\xab\xee\xae\x01\xf2\x08_\x8b\xae\x1b\xf7\x9b\x18\x11\x99#'\x8b(!p\x19\xa5\x18\xa6$]\x94)o*WRk_ws_\x12I!!\xec\x1eLS\xb2\x80\xbf}|\xff3\x1fe\x82(~t|\xbf\xb8\xaf(\x06,\xbb\xa38\x8dP\x1c}\xc5!LV\x0c\x17\xa8\xdf\x12\x1f\x9bj!s_\x1a#\xf9-\xcc\xcaw\xde9e:\x91\xde9e\x9e\xa7\x04\xf3l%x\xe7\x14\x98\x07\xf1\xce)\xef\x9c\xf2\xce)\x9bmw\x13\xce)wg\x92\x14\xc1\x97H\\\x10\x080\xa5\xd3,\x8eW\x10\xe2\xbc,B\x12B\x8a\x0b\xad\xa3\xd2\xcb\xd6\xe5\xb0I\x11\x15\x8f\x18\xb6\xe8D\xf7\x9b\xba\x90\xb8E\xc0\xc4<\xd7D\xd1\x06_+DY\xa0X\xeas\x95\xc9w\xbb\xa4/\xb4SIV\xd9v`\xed\xf4\x15n\xd1(\x85\x06\xd9E?m\xed\xadU?u\xd2K\xb9\xae\xc7\x15\xda\xfc\x83oF?\x95\xebV\xf9\xee\xe6\xf4S\xd3\xb9h\x95v\x1f/^D\xff\x83\x8f\x7f<\xfd\x12\xfd\xfa\xbf\xff$?\xbey\xf3\xc3\xeb\xaf\x7f{\x12\x1c\xfdpz2\xbd8z\xfd\xe6S\xf0v~u\xb0:E\xb3\xcb\xd7\xf3\xb3\xd5\xc1\xc5\xe9\xc9w\xdf\x7f?\x7f\xf9\x9a\xc6?\xfe\x0f:>\x99\x1ed/\xbe[L?\xce\xc9\xbb\x97\xb3_\xbe\x86\xdf\xbfI\xff\xf9\xe1\xed\xabwg'\x97\xafg\x7f\xff\xfb\xe5\xdf\xc8\xbb|\xd8\xa1Y\xd0\xf0\xb4mU\xd6u\n\xa9!\xe3\xbbuEZ\x95\xf3\x1e\x16\x86R!7\x88\n\x9dfiR\xc2-\x8c\x93\xde.\"\xa3\xd2m%\n\xad\x95m\xb3\xa2\xed:^\x8b\x82\xdd\xae\\k:\xd6\xa8\xbc=\xb6\x8c\x95\xaa\xae\x99\xa8Y\x81\xbe\x01\xe5Y\xab8\x1b\xf7\xa4yG\xea\x95e#\xcd\xa0\x97\x92lP\x90\xddF\xef\xa9\x18\xdb(\xc5F\x84\x0c\xca\xb0^\x11\xee\xd6\xfb\x0d\xa8v\xbb\xfb\x13\x94\x9c\xefOP\x8c\x92\x00\xd3\xfd\xdf\xf2bb\x1d\x8b1q}-\xa7>\x14}\xe6\xdf5\x15\xc2\x17()\xe2\xc8\x83(H\xad%\x956K\xa3\xd5o\xd2\xe5\xa8\xe6\x9fA\x94\x14\xb5\xd5j\x9a&\xf4+\xb7\xd4\xe5R\xaa\xb3*r\xd2Nu\xd0\xea\x1e\x9b\xf2\xb3Unjx\x93\x8e+)\xe5\xa3\xe1t\x18\xe4\xa1Z\x0e\xda\xf6[\x93{\xbd\xceM\xbe\xd7+\xe7f_X\x1dS\x9c\xd2\xbcS\x0b[\xa9r\xdd? ! QB\xa5\x81B\x92\xf5qb\x04PB\xd8\xbc\x8c5h\x0e\xd4u\x1b'\x7f\xac\xb3\xa75\xb9\xf2\xe5P\xcdJ$\xd1\n\xd9)\xfc\x0f\xecJ\x84\xc3\xf8|\xea\x85\x11\xb6m\x84q\xd3v\x9c\xe2/\x83je|O\xf6\x95w\xf9\x82\xcc\x9e\xa2y\xfa\xe8j>g\x0f\xd3\xc5\x97\x0b\x9c<:z\x92\x9c\xc7Wq\xf6uu\xf1\xe4\xeb\xd3_\xbf\xfc\x1a,\x82\xd6\xae\x1a\xe7S\xd2:\xdfD$\x85\x1f\xf1\x8aO^,\x17?43\x9c\xe0\x14\xb1\x86C\xa0\xa5\xe7\xce~\xe5\xca\xecv>\xe2\x84\xc1E\x84\xe0\xa5\x98'\xfcBVh\x86S\xf8\x7f?\x1d\x1c\x1c\x1c\xbey\xf4\xe4`\xa7\xa5\x07\xfd+\x99\xf6\xc3\xcbA\xef\xff\x90MZ\xbe\xfb\xa6\xb4\xa2CEU\x9c\xde\x1d\xebk\xee\xa0\xf0\xd7\x8c\xb2\x05\xd6\x9b\x9dV\x03\x1d\x8e\x8e\xdaF\x99b\x95\x02\xefM\xda\x16p\x1dO\x113\xa2\xd1\"\x8b\x11\xd3\xee\xcb !1Fm\x9c\xa1\xd2\xff\x14\xc5\xb4}>\xba\x9b\x17kxMY\xc4\xf5v\xbe\xdb\x84w\xb7\xe1\xa6\x0cP\x92\x10q=#\xa38lV\xb3YC@\x92_\xb3D6\x12\xc5(\n67&I\xbc\xba\xd7h\xa5\xa2\xb3n\xcbm\xabV\x80v\x8bY,\xb7\xc5\xd6\xd2o+\x971*\xdb\xa9]#?\xd2W;-\x1d\x83\xd2/X,\x92\xf7\x0cJ\xe8\xca\xd0\xbdg\xb0\x06\xd7\xc2F\xbdg\xd0{\x06\xbdg\x10\xaeQ\x07\xb6\xf6\x0c\x167nS\xf9\x92\xd0\xbaUG\xd7\x06\xca\xd8\xbc\xc5\xb5\xd1\xdf%X\xb1\x85\xcbbZ\xc2\xf6\xc9\x1b6]\x1a'Y\xe9W\xb8-~\x8a\xcag\xd7\xec\x96\xe8\xec\x12lP\x9d/\xc8\x06\xe5a8M\xa4\x9d\xd9h\xf6\xbd\x82A\xf4\x10\x12\x03\x1cs\xed\x93\x1d\x86\xb6\xc2\x83\xe7\xb5\x93\x1c\xaeE;\x01)E\xe3(\xb8\xdd\x82\xb4\x9f0\xec Z\x1cd\x00\xae\xca\x00\xbe\xa6Q2\xdb\x0fq\x8cg\xe2)\x9d\xfd\xdf\xca\x7f\x9f\x84a\xfa{\xf1SD\x92\xd2\xd7\xbd\xc1y[\xf8\xae\xe4\xba\xb5\xbe\xee\xb4\"\xf7B\xba\x83O\x82\xe0\xa4p\xefM\xe1U\xd1\xael\xa3`\xc3\xad\xd4\xe8\xc5\x82\x1d\x05\x1f\x8ac\xa8\x90Hz\xf4\xd1z\xe2y\x9b\xa6\xcc\xfb( \x9f\xff\xc5A\xec9\xcb\x87\xf7?V~\xb9\xb9 QN\x0e\xdd\xe3\xbf\xdaca\xf5|\xb0\xb6\x07:Gi\xfb\x99\xd76\xcbCm\xeav\x7f:\x1f\x89\xad\xa2Z.\xfa\x86V\xd5\xed\xfaL=\xca\xb6\x0e\xa7e\x93E\xc4*\x87\xb08TnYv\x1b\xed7\xf0:\x9bcX\"J/I\x1ar&U\xd5y\x19\x81\x14/\xc8\x05^g4\xfe\xf8\xee\xa3\xd5\xc9sR\xbb|\xc4\xc7G|\x1a0\x80\x1a|}\xd6\xae\x8f\xf8l\x807\x06\xd4\x9f\x99\x8c\x81?y\xc4\xc7B\xad\xd2\x12\xba67\xcb\xf7&\x9b\x1c?\xc4\xcb\xf3\x87\xc7A\x86~\x9d\x9d\x7f\xc5\xe8\xd1\xd7\xe5\xec\xfc\xcb\x83G,\xf9\xf52\xfczq\x8c\xa6\xc1\x83\xf0\xe8q\xa3\x1b\x0bmn\xdb\x88\xf7z\"s\xad,\x0c*\x885\xc7\xd4x`\x8cG\xd3\x1cN\xb1\xe9\xbdr\x10\xf56\xcdv\xb2\x93\xb6e\xfe8)a>\nWk\xeaE[\x0d\\\xc7\xf3Q8\x1f\x85\xab\x83\x8f\xc2\x95p]vI\x7f\xe7\x06\xb7Q\xd7jA\x11\xa5\xab\xfb\x1av\x8f\x0f\x0e\xd5]\xff\x88Wk\xffBD\xe12%\xd6.^\x95\xcf\xc4\xd5\xc5\xbb\xff[\xa9\x9a\x89\xdf\xfe\x14._\xcdlj\xd4\xd0\xce\xe6\xfd\x92\xeb\xe9\xf2\xc3|Je\xe3a\xa6\xd4Acupf\xff=\xc3\xe9J8\xae\x82,MqR\xf5\xa8\xc1\x04\xb3K\x8c\x93\xaac[d>\xa3\x8d9\xdezG\xb7\x93\xa6\xd7\xcf\xc0\xeag\xe5\xa8\xfc\xd5\x9a&J_u\x0f%\xe0\xdb\xb2Iz\xb1\xefr\xbd\x06rX[1\xdf,\x99\xc8\xa7\x01\xc7>\xd2f\x8c\xb4\x95\xc4\xf217\x01\xb7=\xe6\x16%\x11\x8bP<6\x06\xd1\x14\xed\xbb\xb6\x0bR,Vq\xac~\xfbK\xb6WUJ\\D\xc9\x98E\x0b\xcd\xc8\x1b%\xe1\xba\xf1\x9du\xfbN,F\x1f\x13CI\xeb\x89)N\x80\x0f\x90\x95\xe0\x03dm#\xda\xcf\xce\x07\xc8\x062D}\x80l\x03\xbc\x17Q\xfd\x99\x0f\x90\xf9\x00\xd9\x96\x10\xef\xe0nXC\x07\xe3\xb5\xc6C\x0e|\x94\xc9G\x99jM\xbd|\xa8\x81\xebx>\xca\xe4\xa3Lu\xf0Q\xa6\x12\xaeK\xb9\x1f\xc6M\xd9f\xd2\x7fS\xf1\xa6V\x97\xa7\x8f<\xd5g\xf3g\x8b<\xa9\xdd\xbb>\xf8\xd4\xc5\x06\xe8gA\xe0\x84\xa5\xad\xe2\xa7\x87\x02\xda\xf9\xa2\x84\x85\x17\x19l\x18q\xdf\xf6\x16^e\xb0\xe9G\xe7\\\x06U\x07=\x04\xc6\xd0q\xad\x92\xc7\xa7\xb8rN\xf5\xfc\xfa\x0b?\xe4\xe5@\x0d\x86}\xa7uxgf]\xf7Q\xb4PQ\x8d\xca\xfa\xb4LS\xb2\xd0\xe2\xf3\x0b\x8a+\xf8|L\x83_4\xccv\x10\x94\x18q@\xe8\x15e=\x10r`\xdbEL\xae\xb6 \xe0\xee4\x8a\x19Na\xb2\x92\x93\x92\x1b\x82\x16\x8e\x99[\xcf\xa1-cr\xff\xff\x14O\x9f\xc1\xee\xffo?\xc4S\xc1\x9e\xb8\x06\xf3\xa1B \xdb\xd2\x83\xbd\x14\xa9\x1a\xe9\xff\x14\n\x93S\x9d\xc5<\x08V\xdb\xa1\xc5N\xdbF\xec\xcb\xa6$\xe0@\xba\x81\x0fs\xf90W\x03\xbe)K\xd8\x87\xb96\xc0\xbb1\xd5\x9f\xf90\xd7\x1f=\xccE\xd3\xa0@\xfeF\xf0\xef\xe0\xe2X\xc3z\x1a!e7\xb7\x06\xbd\xe6\xf0'\x8b\xd8\xf9\xba\x8dF\x91\xd1U\x1c\xfbX^\x0d\xaeE\x08\xfaX\x9e\x8f\xe5\xf9X\x1e\\\xa3\x053L,\xaf\xea\x9aP\xc4\xf0\xb6\xe7>*\xd5\x96?\x87\xef\xc8\xc1\xb7\xb9\x0eI\xadi\x04l\x8eX-\x08\x15Q\x98\x90\x84+h\xa5\x87\xf6\x8f\xe2\xdf\xd4\xb05\x1dC#y(\xb2\xf3\x85\x81nz\xf0\xb0\x9a\xb0\xd4QqB3:^f\x13\x05\xeb7L\xc3$\xc9J<\xf9X\xcblr\xf85\xf85\xcc\xf0\xf2\xcb\xc1Ev\xf4uv>;?~\x8a\xa7\xe8 \xf9r\xf95 Q\xf2\xe5\xe1\xe28x\xbcD\x0f\xb2c\xb4\xfcz<;J\x9f\xce\xe8\xf2\xcb\xec\xd1\xeci@\x1f\x9c?\x0d\xb2\xe9\xc68\xbf\xa2(\xc6\xadN'\xbdEL\x19b\x99f\xedT\x97&\x189\xc7\xed%1\x0d\x96Oa\xbdv,\xd1V\xdd2\xca\xb6\x9d\xa3\x8f\x0b\x92D\xe7\xeaWw\x8d\"#\nq\xc2\"\xa6|J\xd9\xd8\xc1%\x9e\xd0H\xe5\xdb\xb0hOq\x90\xa5\x11[\x8d\x03\x920\x14t\x8f[\x86\x98\xa1(6\xa8\xe7\x8a\xf6\x9cQ\x1ao\xe3\x98OS\x9bP\x17]G K\xd1\x98]\x8d\x85\n\xd1\xbe\\\xfa\xdd[\x19\xe5`\xe3\xc7u\xca\xcav\xe6\xb0\xee_\x7f\xeb\xc8\xa2\xf7\xc3\xa7\x8f\x0f\xee\x1f\x1c\xde?8<;8x&\xfe\xff?7\x07\x0c\xc8b\x11Q\xba\x9d#\x93*]q\xc6y\x80\x89R\x1c\x16\xe8j|\x1dc\x04s\x94\xcc\xf0\xd6\x87\xca\x96!b\xd8=%\xa0\x0e\xb6;\xa0\xa3\xb6\xban\x7f\x1d\n\xa9\xcf\x06\xab\xcf\xc6>\x1b\xac\x91\x0d0\xecl:\xe8U\xeeZw%_\xe5\x0f\xa1r;y\n\xcd\x1a\xb4\xb5*d\xab=\xf7_\xe35\x985g-\xfaz\xady\xfb:\xb3Jc\xd6\xe9\xcb*mY\xa7m\xa84e\x0dq\xccZ\xb2\xb6\xb1FC\xd6\n{\xbd\xa8\xd7\xea\xc6\x06\x99\xa5\xd7\x8b\x0d\x8d\xb5:\xb1\xa1\xad\x9d>l\xe8D\xab\x0bk\xdaj\xf5`\xbb\xb3\xb1\xa9FXj\xc0z\xfdW\xa9\xfd\x9au\xdf\xaex\x9b\xb4^\xcb~m4^\x9d\xbe\xdb\xe3\x00\xa8UC\xa3\xc6fP\x0b\xf5:\xee\x10\xbd\x1b\xb5\xdb\xbe\x83\x18\xf5Z\x87\x01\xb6\xa2\xd3n59v\xad\xcc\xca>\x1c\x14\xa1\x8a\xf4+\xb2,\xd7h\x06( \xf9?1\x1d\xc1\x8b\x15\x84x\x8a\xb2\x98A\xc4 \xc5,K\x13\n$\x89e%'\xa9*\x95}\xad1\x1a\xe5\x7fS\xa7\xc1\xd53R\x0b5T\xca\xba\xca\x9f\x15+\xa8K\x968\x9b\xe3\xcal8\x8ay\xb7#x\x97Q\x91\x1b\x81#6\xc7)\xecJ\xfcw\xf7`Wr\n\xf1oRg]\xbb%\x13\xd9\x1dU~\xa8\xa8\xae\x0d*\xe8\xe6\xb7D3\xac\x9a\x86\xacn1\xc3 \xc3\x13\xa3\x0d*l2\xd6\n\x12\x87V\xe3\xc7\xd1\"b:\x04\x16\xe8*Zd\x8b\x1c\x07\xae\xe1\x0b\xf7-,q*\x90\xeb\x88\xd5\xad\xd7\xa1\xbd\xdb\xda\xa8z\xdb(\xdf\xc6ix\xb7\xf5f;\xa5\xa9eR\xc8\x8d\x1dx\xb7\xb5\xa6\xbd\x9d\x9an\xd1\x91w[{\xb7\xb5\x00\xd3\x91\xd9\xb6\x9f\xd7\xbb\xad[\xc0v\x07t\xd3\xc6w[\xd4\xf1\xfe\xbee{o\xec\x1f\xe3n.\xb7%\xaa\xefK\xe6\x05\x17i\x94\xccb\xfc\x07\xbf\x85k\xd6\x0d\xad\x85\xbc\xad^\xd8\x7f\x85\xd7`\xd6 \xb5\xe8{\x87\xac\x928f\xfdO\xdb\xd8;dK\xb0\xd3\xf4\x0c\x9dx\x87l\x05\xba\xe2m\xd2\xe7,\xfb\xb5\xd1\xe5\xbcC\xb6\x06Vz[\xdfA\x8c\x1a\x9b\xc3\x00C8d\x87\xf6\xbd\xdah{\xfd\x1e\xb4\xfd\xf3h~\x9a\xc7m\xbf9\x85o\xbb\xdeC\x8b\xdbw\x86\x93\xb5\xbe?\xd6\xb5\x87\x8e.(c}\xed\xce\xb6\xf4\x1f\xfdq\xdb\x1ba]\x03\xbd\x15\xf0\xe7cb\xdaw\x03<;\xab\xc1m`g\x16\x15\x9f\xfa\xf15E;\x8b\nOz\x9d}[\xef\x06\x0c\xcdnJn\xb3$$~\xd6\xe5XU_\n\xe2\x167.*\xfe\xe7=\x03\xef\xf9[9QN\x1e\xa1\x98\x10\x8a\xc7\x1d<\x062\x10\xdd\xa5e\x94Lc\xb91cD\x99\xbbqV\xb6wj%\x8c\x051\xe0\xdaX\x1b\xa7\x98b7\x8bs\x99\xe2\x8bq>w'WI\xdf\xad\xdd\x90\x88\xfd6\xb8\xdc\xd3E\x97\xf2\xde$\xfdC\xee\xef\xf5f\x13\x05'\xa4Uj\xb9d\xcd\x1e\x16\xe8\xaak\xcb\xc8m\xb3\xce\x08\x97\x17b\x979\xb5\xeb\xe1\xf2\xe06{3\xcbg\xb3i\xbb\xa8\x10\x1e\"\x85\x92<\xe8a\x88\x11\x9d\xf3\xd3@\xa3Y\xc2g\x19%S\xd2\xed@\xf0\x1eD\x18\x80s\xfaYt\x81\x93\xc6\x0d\xc9;-\x88m4lm\xe2pD6\xceZ>\xc1\xa2'\xc7\x8c&]\xc6\xcf\xe9:\xdb\xa7\xf2\x89jU\x15j\xf0\xd0Y@\xef\x0c\x19@\x03a\xfa\xf0N\xf1\xedv8\xd2vuX\xcaP\xca\x8cJ\x9cR\xf9\x0c\xf1\xd5\x98L\xa7\xad\x82\xce\xd0X\x06,\xc6Y\xc2\xa2\xd8\xb91\x97\xb18\x1cOb\x12\x9cSsJ@\x93C8j\x92\xcbl\x12G\x01\x9c\xe3\x95\xa8TD\x92R\x85\xdb8\x9f]\xd9\xcf\xee\x9a\xffh\xcdZN\xb5\xc2\x8eu\xa8\xf0\xf7I4\x04\x94S}\xc3\x92\xab\xe1\xf8\x11'a\xad\x18\x13#\x90\x19:\xd8N\xb1\x9aN,L\xb1q\xda\xacv\xb5\xb1\xa0\xf7\x00h8\xc3\x86'a\x18S\x1e\xc4\xd4js\xd8\xdd\xdd\xc0V.\xf3\x8bza\xc6\x96Z\x8dJ\xec\x07R\x8c\xb6Rt\xb1\xb54\x10h\xf8d\x01\x16\xa5r\x94\xde\xaf\xd6RA`\x9a\x08\x18'\x03\xba\xb2A`\xc6\x0b\x8cn=3]\xc0D\x1b\xb0\x99\xa7\x04\xf3l%\x18K\n\x81\xdd\xdc\x0b\xb0\xf0~\x16`\"\x97\x84.c+j\xedu\xae\xa3iU\x1c\xa8\xd7\xd63\x8c\x00f\x1c%\x98\xb2`%\xdc@)\"\x0e\xdarD`CH\xb0\"&\x14]i\xf7\x8b\x15=\xa1JS\xe7\x12E`.S\x04\x9d0\xe9Y\xae\x08,K\x16\x81-r\xc6\x8c;S\xf9\"\xe81\x92\xb3\xa2\xef+\xe8\x19\x8f\x91\xaf\xa0\xa7?\x8b\x96b\xce,\xe2\\\xc7\xf3\x15\xf4\xaeUl\xf9\nz\xb6\xa3\xf7\x14I6\xe2\xc8\x88\x90A\x0c\xdd\\\x05\xbd\x0d\xbb\x16HZ\x1ae\xeb\xbe:y*\xd6\x8e\x8a!\xc3\x06y\x9f\x15\x93>obr\x01\xd8;\x13\x9c\xe5\xb6\xa5\x83\xceM:\xa3\xab1\xbe\x88B\xbe/\xc6\xc81Z\xc0Y\xde\xda\xebu\x19%!\xb9t\xea`\x11%\xe3\xbc\x93%N\xbb\xf4\x10\x92l\x12c\xd1\xc9X\x06\x04\xc6a\x96v\x88\x98\x91\xcb\x84E\x0b\xdc\xab\x13\xb1k\xc6\xd3T\xba\xa9\xc6\x15\xdc\xfau#Q\xb3\xec\xa3\xe3)\x9a\x91\x8b}\xbeM\x08EE.\xae\x8bC\xaf|\xb2\xa3\xe8\xe3N\xcb\xe0m\x8e<\xaahx=\x0e\xbc\xef\xc9\x05'G\x12\x14\x13jw\xe1\xd5f\xd1\x90\xcf%\x87\xcb\x84\x17\xf6\xf3N1\x911_\x9e\x9d\xcf\x10\xa0\x04&\x18>\xef0|\xc5v>\xef\xd5Z\x7f\xde)G\xcc\xe3u;\x9f\xf7\xe0\xf3\x0e%Sv\x89R<\xce\x96\xb3\x14\x85x\xe7s\xa5Y\x1e\x00!\x94\x8d\xcb\xc1&\x7fL'\x9b\x7f\xd9\xc44;\xff\xb2\xc9@Z\x8d\x7f\xd9d\x03\xbcI\xaa\xfe\xcc\xe4m\xfd\x93\xbfl\xc2\"\x16\xdb\xaa,\x12\xaa\xb3qiW\x93\xb7N-k\xc6\xe3U[\x98\x9aP\xf5\xed\x1fE\x97\xb5E\xe9vo\xb0\xdb\x93,E\xeae\x88\x97\x84F\xcaL\xafNN\xb7?]6\xb9\xb3q\xe6\x9d\xaa\xc6\xdd\xd0U\x96z\xa7j\x0d\xaeE\x82y\xa7\xaaw\xaaz\xa7*\\\xa3\xf9\xe1\xecT-\xf4\x9e!^\x1dqr\x96\xca\xd2\x12\xa5\xb3\xe8N\xcb8\x8dOj5(\x84\xee\xb8\xe1W\xdd\xbe\x13G\x9d\xb6yAX-\xcd\xb26\x15\xf1c\x8b\xe6\xa6z\x99Y\xb1\xe8\xba\xf1s\x8d\x8d(q(?\xd8.\x1e\x1bE\x02u\x06F\xb9\xfdd\xab\xbd\xaa#\x8c\xae\x9d^9\xea\xe3%N#\x12n\xba\xbf.\x08\x8b\x92\xd9\xfag\xe1\x11\xa3\x14\xe7\xffN1g\x84\xfc\xbf\xbaN\xd9Y\x93\xb3t\xb3o7\x0f\xb64j\xda=4\xb2We]\xb4v\xdb\xcb\xc1pqmk\xb0\xc1l[\x9b\n\xc1)\xdaO\xa3\x84\x0f\x8d\xe2x5N1\xcdbM\xf6ogKfw\x85\xe9\xae^\x93\xb4\xb42\x0eF\x07%\xb4\xa7\x8b\xa0 e\xa8\xed\x1a\x85\x84\x81G\xdbM\xc8uM,!c\xce\xfe\xc7\x17\x98)\x1c\x9f\x83\x0e)\x83\x0b\xddJ\x9c1\xc2t\xc6\xb4\xc9\xf4\xd0\x18\x1e\x03\xa8x\x06\x93\xc3\x82\x84\x96\xe6\x86\xc9\xd8p\x1b\xa9\xd5U\x96K\x00\x99\xf9\xef\xb4Tvz\xd2\x17\xa9\x8b4\x15\x8e\xae\xaaR=R&\x83\xce\xb5\xabV.a\xb3\xef\xd7\x91\x82\xf5\x0d5\xd9\xd9Z\xc0n\xc6\x10\x1a\x17u:\xf5\xf1\xcd\x04\xd8d\xf9^\xd5\xc4\xb8\xf2+_\x9b\x105\x88\xa2\x84\x8a\x8bJe\x83ZW\xb2\xf1fV\xbd\x0f\xa5YZ)>\x94\xd6\xd2\x83\x0f\xa5I\xf0\xa14\xef\x88\xac\x83\xebx>\x946L(\xadv\xc7\xeb\x94\x8bBx)D_\xe3\xbb\xae!\xb7Z\xff\x9fDm2X\xa0\xab\xb6\xeb\x87\x12\xbe\xb5X\x9a\x8f\xa1U\xc1e\x8c\x96#\x9ck]\xb7\x83\x984\x9b\xd0%R\xdf\xc3p\x99+\xadU\x8b\xa8\x83\xe6\xa2\x8f\xcb\x10\xef\xd0\xd5/\xaaC%\x81*_\x0c\x00\xc7\xb1v\xdbmv\xadG\xbfe5\x9c\x1dn\\\xc1\xaf\xb2Q\x1fG\xf5q\xd4V\xb0\xd8\xcc`\xc7\xef\xc0\xc8\xf3\xa0\xc3x>\x8e\xea\xe3\xa8u\xf0q\xd4\x12\xae\xcb\xf6\xbc\xd18\xean\xc3;\xf8[\xf1\xcf\xb7a\xf1Z\x81s\xa0U\x9fS\xdf\xfc\x06&+\x88\nI\xb9}\xc7\x9dbar\xb7Z9\xf9\xcaO\x1d+U\xec\x1euN\xcd\xb2\x0c\xe89)\x0e\xda\xf8\x9c\xecOQ\xaf\xde\xd9\x98\xebj\xa4\x19br6-\xf5\x05\xf9\xdb\x95\x1d\x8bX\\\x0fA\xa6\x89\xc2\xb9\xf0\x08C\xa0J\x1b\x7f\x1bp\x1cu\xe4m\xc0A\xcc1\xb7\x81\x06\xd3F\xdb4c\x18\"m=\xd4\xf1\xceV\xe2\xb7nr[\xc4\xd4ZGp\x94\x98\xd1\x9a\xb1\x0f//\xf7\x0b\xa7QW\xc1Y\xb4\xbf\xd3\x82\x90\xfcb*^*\xc7\xe5\x97\xb9O\xaf!o\xbd\x14\xbdA)\xaa\x11P\xd6\xeeD\xc7]\xfd\xf6\xd56wu\xce\xe7h\xd7]]\xb4W\xef\xea\xe2\x0b\xae\nnl\x1e\xbf\x99\x1d6\xf3vs\xbc\xd4\x12@'\xf2|jI\x15\xf4\xa1#-\x7f1\x8cP\xe6\\:\xb7\xec\x16\xb7\xe8\x1d\xb9p\xe4r\xbde\xb7[\xa6\xcb+I\xce\xfc\xbd.`\xa4\xc3]\xf1\xd0\xdc\xc7\xad\xcajQ\xec\x92\xda<\xdb\xd6c\xbb\xcc\xd2\xa6p\xa3H\x88)Rw}>L\x13\x9a'\xd5\xe7\xc3T\xc1\xe7\xc3HX\xf7\xee\xf3a6\xc0\x07\x94\xd4\x9f\xe9\x95\x9a?}>\x8cF33ht\xeeZYO\x9dL\x82jc\xe8\xce\x88\xf7l\xe1~\x17\xb2-M<'=\xc4\xa7\x0b\xd4\x9az\xee^\x03\xd7\xf1|\xba\x80O\x17\xa8CI7\x9f.p]\xaay\xf7t\x81(\xe4\x06Z\xe1\x93\xa8'\x0f\x1c\x1f\x1c\xaa{\xfa\x11\xaf`\x89(\xbd$i\x08\x11\x85\xcb\x94T\x9d\xd5\x9d\x9c1V.\xe7\xfd\xdfJ\xd5\xa9s6B\xde\xc3\x9d\x16\xdcj\x1f\xd4\x9d\xcf\x80\x92Py\x8b\xf9\xcf\xec\x88\xb1\xc1,\x7f\x1cDw \\}\x8f\xbc#\x96\xb9\xbakz\x11\xe4\xe0\xd1\xf2\xea\xea\xe2N1\xd4-P\xd1\xbc\xae]\x01\x971Z\xb4\x91\xae\xe1\xb9o\xc8@\xeb\xc3\xf3\xdb\xde\xf4<>8Vw\xf7\x86dI\x08 i0\xd1\xad\xf0\xfc\x0b\xc2p\xe7\x18\xa3\xa8y\xa1\x890\xca\xdfkU=nU\xac\xf1\x86\x19\xfb\xb6\x18\xe1v\xc3\x91bQ\xd5\\Pqf\xfb\x84\xd8\x88\x9c\xbem3\xe7\xb3\xban\xd9\xe9|\xb9\x05\xb8~!\xf2\n\xb6cL\xeb\xa2\xb5\x99\x0fc\x19\x0f\x99\xe9\xda\xf8F]f\xb9\xdbv>\xc34\xc2q\xb8\xaeP\xb3\xc2T\xd6\x9aI\xc8fy\x9aj\xf2\xdc\xceg\xa1\xc6~\xde\xc9\xd3\x03U5\x99\xf9\x92\xfa\xa0\xd9\x06\xf8\xa0\x99\x0f\x9a\xb9\xf4\xee\x83f\x1b\xe0\xdd\xaa\xea\xcf|\xd0L\x1b4Shw\xb7\xcd\x1e\x93\xa0R\x0c\xb5\xd8\xae7\xc0\n\xd3m\xab\xe2N\x92\xd8\x87\x8djM=\x7f\xab\x81\xebx>l\xe4\xc3Fu\xf0a\xa3\x12\xaeK9\xed\x1b6\x12f\xffm\x8e\x19 \xff\xe1\xfeoBm\xe8\x1c,\xe2\xad\xef\xb4`\xb4\xfeU\xe5C\x84\xdc5\x1a\xe2\xa4\xccvf&\x9dc\x11\x953\xba\x15F\"\xae\x02\xbb3\x90\xefq\xf5Q\xb8]\n\xa2\x1f\x90W\x8a\x01\xd5\x9fkd\xd1\xa2\x95\xcfT\xf4\x88\xef1\xa3n\x1d\x8e\xe0\xed\xb4r;\x90S{M\xdc%N\xc2(\x99\xad\xefZ\xdd\x8dF8/\x85\x0d\xbb\xf9e\x87SQ\xd4z\xf7\x1eD\x0cR\xcc\xb24\xa1\x80\x12\xc0\x8b%[\xc9\xe1\xcb\xfe$\x1a\xa3\xfc\xbf\xff\xac\x1c\xeeVp\x06\xc5\x15sK\xdbSwAZy\xad|\x80\xbe\xdb\xaf\x92\x0f\xd0\xb1\xfe\xfax\xaf\x01\x9c\x99\xdd\xbae'>%\xd9Ty\x1e\xf6kW\xce\x1dx\x93T_f\xe5I+s^6\x8a\x0c\xab\xb8\x91E\x0f#Q\x17k\x81\xae\xc6\xf5\x12\xfa\x90%\x9c\xdf\xa0\x14W]C J\x08\xc5\x01IB\xba\x0d&r+\x0e\xe6\"J|\x95\x80\x1a\xb8\x8c\xd1\xe66\xd8\xd8\\\x9d\x0f\xf8\x93G\xc7\x07\xeeG\xfc? \x9b\xe3t\xccE\xc3\x7fq\xab&!\\\xe8W\xcbvs\x91\x82)\xabK\x0fK\xcdFy*\x87\xe2\x1fB\x84G\xc9\xac?\x03\x91\xba\x88\x9e}\xd86\xba\xdd\xe7^}\xa6\xd8<\xc5tN\xe2\xee\x9b\xf0`\xf4P)\xc6z\x8a\xaf\x07\x0f\x8e\x15\x1d\xaf\x17d\xbc\xc4 \x8aY\x8b\xab\xc8z\x98\x83\xc3\xdbu\x84\x14[l\xa8\x03$\xcb\x94\xf4?>\xb2\x9f\x1e\xe2w\xa3\x03)}k\x8f\xd3\xfcA\x04\xaf\xd6$^\xcf\xb6\xf3&\xbe\x8d\x92@\xb5?\xba\xee\xe3\xdd\xfd0\xe2\x84\x98dbAC\x1c\xe3\x99\xa8\xd0\xba\xff[\xf9\xef\x930L\x7f\xdfO\xf1%J\xc3\xc2\x9e\xd8\xb4\xc5\xeeo\xdaFE.o\xa5\x9f;\xad\xd8\xe5~\x9e\x93 8)r\x1f\xa6\xf0\xaahW\xb6QXe\xad\xcb\xd9\xe2\xd9y|\xf9\xf4\x11\x0b/\x16\xe8+:\x0f/\xcf/\x8f\xb2\x87\x8f\x8f\x8e\x1e\xe30\xcbbt\x14\xac\x1e>>\x8a\xa7\xae'\x98[\xf7\xdc\xb4\x16\xa5\x9f '\x12LP,N\xe34%\x0b\xf1\x8aCN\x84\x88$\xa6\x13]tH\xb3\x05\xa7\x02o\xcc\xff\xb3\xe8\x19\xa34\xc1!LV\xd5.\xf9\x7f\"\xa0Q2\x8bq\x85\xc2u\xfa\xf58\xcc\xaf*{dk\xc7\xb9\x83\x1e\x9d\x13Eu\xc2\xafW\x87.K\x86\x8fs\xffU\xfbgV\xban\x8dr\x96\xf1j \x8d]\x7f\x81b\x8e\xb5\xd1\xadyty\x9c\x1c\xc5\xad}J\"\xeb'\xa3\x0e\x84\x1aB\xa1F\xaaK0\xd1^\x821 jE{ \x16\x16\x8d\x04sX\xb4\xcb\xa8-6\x8e\xe00\xb7c\xab\x7f\xbb\xe6\xa2\x9d\xa3\xa6d\x9d\x9b\xae\xe8NR\xd6-\xff\xf6\x1f\x11\x9b\x87)\xba,y\x7f\x89\xce.\xadp\xfd\x82\xfb\xddiA\xa4[\x17\x16l\x7f;\xe9\xbc\xeag.\x1b\x99\xa6R\xa3(gWhR\x8d\xaf\xdc\x94E\x9f]\xea\xb3K\x1b\xf0M\x05\xf0}v\xe9\x06\xf8\xec+\xf5g:\x15\x03\xfe\xbc\xd9\xa5\xb7\xc2\x9e\xf1\xe9\x95\xb5\xa6\xfe\x80\xd7\xc0u<\x9f^\xe9\xd3+\xebP\xd2\xcd\xa7W^\x97v6\xa4\xedy\x03y\x95\x8e\xde\xe1\xfd\xdfJ/\x98\xf8\xfb7\xec-v\xc9\x03T\xce\xa6F\x0d\xedl\xde/\xb9N\"?\xcc\xa7T6\x1efJ\x1d\\\x81\x0e~\xf0\xe2\xf5\x96\x0d\xe7\xc2\x9d\x969\x17\x1fK\x8f\xf5f\x1b\xe9\xcfn:\xb0-\xdc\x13\x0e>\x87m)|\xdb\xbd\xda\xaeTJ\x0c,\xc9\xa0\x84\x98\nx\x9b\xfb\xfd\x86\xbdlv{v\xf3\xfbvgZ\x1e\xf3)\xf6v\xf3\x10[lb\xefc+\xc0\xfb\xd8\xdaF\xb4\x9f\x9d\xf7\xb1\x0d\xa4\xc5y\x1f\xdb\x06x\x13\\\xfd\x99\xf7\xb1y\x1f\xdb\xa0\xa2\xae+\xab\xf1>\xb6\x1a\\\xcb\x01\xf7>6\xefc\xf3>6\xb8F\xed\xac\xbf\xe5)k!\x96\x96\xdc\x8d_g\xb6u\xbb]\xe6VZ\x91r\xf6\x0d\xfb\xdb\xb6\x9a\x9dYdO\x16\xf4Bq\xc3\xe7`\xca\xc6\xac$[\xeejz\x1b\xc1\xd9<\xa2|\x1f\xf0F\xc5\xe6\xaa\xa8M\x97\xf3(\x98\x8b\x1f3\x8aS\xb8\x8c\xe2\x18R\x1c\xe0\xe8\x02W\x10\x85i\x96\xb8d\xe58\xb8\x01\xb6\xa5\x83\xb5\x1cT\xd7$\xc6\xe6\x96p,\xb8\xd3\xf1\xe8\xf7<\xabnN\xa7\x0fx\x19\xa3\x00w\xd8\x93\xd5\x96\x96\x9b1W\xe8\x13| $\xc1#\xfb\xed\xe4\x1dP\x05x\x07T\xdb\x88\xf6\xb3\xf3\x0e\xa8\x81T\x1c\xef\x80\xda\x00o\x9f\xaa?\xf3\x0e(m \xc1\xa6\xda\xac\x92\n\n:\xbb*6\xd0W\xb9\xd9\x96\xd2\xe6\x1dg\xdeqv{\x18\x93w\x9cy\xc7\x99w\x9c\xc15j\x95=\x1cg$-\xa5\xe8\xedKT+\x93.\x06HH\xfb\xf3\xa4p\xfdR \x0bUbV\xeb\x1a\xdei\x99\xbc\xcc\xe5\x12n E+q\x8d\xb9G>\x8c\x83\x8f\xe1V(J$\xdf\x077\xa7]v\xd8'k\xa08\x9e\x8e'$ \xc7\xb7\xeaz\xf5\xb7{\xe7T\xc2\x05\x8a\xc7\x01Y,\"J#u\x11EO\xd3&\xb4\xd3\xd4N\\\x95\xccf g\xaf\xb5\x98\xd9'\x19\xa3\x0c\x89\xca\x8a\xe3\xce\x953\xfe<\xa2\xe7\x0dn\x88\x8f\n\xfdJ\x0f\xf7\xb7/F|n\xf0\xf6O\x9e?m\xc6\xd3\xf6\xb2\x14C\xa225\x17\xf8\xf77\x8b\x02h\xcf\x9bB\x05\x0c\xac{.;t\x88K\xf9\x13l:i\xd7s\x82oD\xf6\xba\x05Z\xcb\xe8!\xdf\x95%*\xbb\xd4\xaahF\xb3Ms\x1b\xf3\xad\xbd\xde\xe9\xcd>-6\xb2\x0f\xb0\x16\xe0\x03\xacm#\xda\xcf\xce\x07X\x07r\x85\xf9\x00\xeb\x06\xf88\x86\xfa3\x1f`\xf5\x19\xfe\x83\x8a\xba\xae\xac\xc6\x07*kp-\x07\xdc\x07*}\xa0\xd2\x07*\xe1\x1a\xb5\xb3!\xad\xcfk\x0fN\xd6]W\xdcp\xcc\x92\x88\xad\xc6KB\xf2z\x9e\x8e\xbe\x1b\xd1\x1cx\xf3\xcdB\xd0\x16\xd6\xa7\x83I\xb9-y\xee\xdd(\xc3l\xa6\xa6\xc9\xef\xb0\x916\\\xee\xdf\xdcV28#\x96\xe2\xb5\x1d\x9c\x8eU\x05\x8c5\xab6!IF{\xf5\xb0>\xe6\x0c]Y\xb6\xec\xb8#\xb8\x00\x8a\x92Y\x9f\xcd\xf0Nv\x01\x0b\x12f16o\x05\xfe\xfd\xed\xde\x02\x9c(c\x05#\xd0,[\x94Lc\x81\xf7X\xd86\xc1\x1c%3\xa5\xd6f\xe8aa\xbd\xf0\x1b-\x1d\x9f\xd6\x9a\x11\x14\x8b\x90=v\xdb\xa4\x93\x98\x04\xe7t\xbc\xc4\xe9x\x85\x91\xed#\x82=\xb7i9M\xe7]\xfa2\x7f\xd3.\xefiM0\xa9X\xdd\xf2\xbd\xba\x0dZ\xa2$\xc9P|\x7f\x99\x92\x8bH\xf8\xa2{\xd3T\xf6\x08\xeb\x1e\xfft\xb4\xa5\xd9r\x19\xaf\xf6+\xe5\xd6\x1d\xc8y&\x9e\x81\x90]\x00\x99B@\xa2\x84B\x94\xc8\xe8\xd8\x1c\x95\xfe\x95&%?\x8a&\xb7\x87\x96N\x1e\x17_\x9a~\x0d.c\x0c\xa0\x0f\xee\xd6\xf6\xeb\xfeob\xfeQ\"\xf6I\x87l\xc7j\xf3;\xad\x88\xbc$Q\xd2\xfeY\xc7\x88w\x86\x18Y\x88\x1fz\x9c\xb32P\x1d(\xd0\xbb\xed\xe7\xad\xc9\xbb\xac\xac\\\xd5d\xbbo&\x19-\xdbG\x19\x9b\xef_\x1cN0C\x87\xfb\xb9\xa7\x80\xee\xff\x96\xdb\xd2-\xafh\x97\x0bs\"?^\xbf\x12\x9b\xffw\x88\x19\x8ab*T\xf3\x10HR\xde\x98\xce;\x90I\x93\x11I\xde\x86e']I~\x024\x0b\x02L\xe94\x8b\xcb\xd6#\xabepb{\xf9\xdc69A\x0d\x9b5\x05\xa6Q\x82\xf3\x9b\xe1\xf9\xdf\xc84O\x9bH%\x9a\"\xdf\xa9A\x995\xf4\xf0\x15\xf2\xa6\xe3,ma\xd2`\xc3\xb3\xecb\x0d'\xf0\xe9\xc3O\xfb)\xa6$K\x83\" :G\x0c\xb2$\xfa\x92\xe1x\x05Q\x88\x13\x16M\xa3\x9c\x0c|\\ SEw\xe2\x15$\x9cF(\x8e\xbe\xe2\xf0\x8e\xe2\xabeJ\x18 H\x0c\x93l:\xc5),0\xa5h\x86\xf3\x9b\xf8rN\xb0\xc8(\x83\x80$\x0cE \x061F\x94\xa9z$ \x86\x9d\xfd\x1d.\xaeS\x140\x9c\xca'\xd4bD\x19P<[\xe0\xf5\xc2}\xfa\xf0\xd3.\x15|T\x0c\xa1\xe80\xe5\xcc\x8c\xe2D9\"\xefj\x9a\xc5\xf1\n\xbed(\xe6\xf4 %\xf5\xf2a\x04\x9d\xee\"QI@\xd1\xc5g\x8e\xc4\xfe\x8c\x90Y\x8cG\x82&\x93l:z\x95\xc9C\xf5\xf9\x9e\x9c\x83\xe8\x94\xceI\x16\x870\xc1\\/A\x8a\xfe\x02\x94\x90$\nP\x0cS\x92.T\xa3\xde\xc5\xa3\xd9h\x8f\x93S\xec\xdc\x9d\xd1N\xf9\xe4Y\x10\xe0%\xc3\xe1\xbd\xd1\x1dU\xe3\xb7 ,9\x81\xa3\x00\xef\x01\xc3hA!\xa3\x99|\xa7/\xc5\x01Y,\xa3\x98\xe3\xc8\x88 \xc2$JP\xba\x02\x14\xb7?S$w1\x95\x1b\x8e\xcd\xf1J5,\xbeZ\xe2\x80A\xc4\x80\x11\xc8(.\xb53\x920|%\x96\xf6$Y\x8d\xe0\x07r\x89/p\xba'\xa2f\x9f>\xfc\xa4zqI\x96t\xe0\x1d\xb19V\x0d*8\x0e\x86\xcfs\xc6\x96\x9f\xf7\xe4\xff\xd2\xcf{@RHH\xfe\xeb\x9e\xd8y\x01J\xf2\x87\xd6k\xcfj7\xba\xc3\x0c\xb2% 1g\xe5\x98\x92\xb9\x0b\x82,\xd0\x92\xcam\xc4g\xc2g\x9e\x9f\x13\xc9\x96\"&T}\xa4\x9a\xe3\x94\xc41\xb9\xa4\xcf\x94k\xf9Wx;]\xcf\x84o\x02aA\x848,'\xcb\xff\x88(\xcd\x168\x1c\xa9\xbb9I\xe0\x87\xb3\xb3S\xf8\xfe\xf5\x19\x97\x12\xf9!\x93\x07x\x15\xe18T\xee\xd8\x7f57\xff\xd9j\x89\xff\xfd\xaf\x7f+>\xcf\xbd\xf1|\xf5\xf3\x9d%/,\x885\xc9\x15\x02\xf1\xc69\x97\x8d\x9b\xbcX\xc2_\xe1d\xad&\xc8\x17\x15\x11\xa7\x14\x0e9\x89\x03\x14p\xbeA\xc8y\xb6\xcc\xdfE\xcf\x05\xa0\x92\xf3\x88=\xd4\xfe#pB\x08\xec\xe6HV\x0bYT\xceI(\x0f\n*&\xc3\xff}A\xa2\x10P\xa2\xdaD\x90\xa3&XC\x8a\xa7$\xc5{Es\xde+b\xd1$\x8a#\xb6\x82\x04\xe3Pl\x9a \x06\xc1\xca\xd2\x0b\xe5\x1c\xc4,\xa4\xdfD4\x11\xa7r\x04w?Q\x0c\x178\xe56%\xa7\x0e\xdf\x8a\x9c\x1b\xc9\xbd\x88\x124S\xcf{\x92bt\xce\xf9K\xde\xed\xe8\x9ej\xff\xfcL\x18~\x06\x8cs\xfei\x1e\xadFb\x069W\xca_\xc5\x8fW\x80.P\x14\xa3I\\\x1c\x7f\xd5\x8aL\xa7Q\x10\xa1X+}&\xd9\x14R\xcce\n\xde\x13\xc9a\x11+\x06\x14Au\xce@\xca\xb3\xa7\xe8h\x82gQ\x92\xf0I^Fl\xae\x14\x14\xab%\x1e\xc9}\x8e\x96\x11\x1d\x05d\xa1\xe6\xaf\x1f\xc5Y\xa4 \x1e\xa4\xe4l i\xf2\x1f\xb8\xcb1\x9b\xe3\xfc!\x7fyx\x9b\x97\xa5\x0bXD\xb39\x83\x89\x92\xdd\x88\xa9\x8a\xd4\x80\x88+\xf6\\LJ\xe7\x0c]\xe2 \x9aF\x01P\xbc@ \x8b\x82\x16\xd5F\x1b\x1b3\xaa'\xf2\xe4>\x83\xc9\x8a\xf5\xc9\x95x\xc7\x99\xcc\x04\x97\xcfu\xae\x95\x8f\x0d-#\x17\xcchB.T['\x9fv\xbe\xd9\xebS\xd6\xe3#\xf2is\x1d\xf8C\xae\xbe\x165\x85\nuVn\xa8i\xbe~\xa2\xc5~]m.\xe0\xc3\xe9KX`6'\xe1\x1a\x87\x10OQ\x163\xb5\x06\x9d@\x96HA\x89C\xc9\x02\xb7\xa9H\x8b\x01T\xfe\x03\x85{=T\xbae\xa3\x84\xe1\x19N7~-vI\x94\xb0\x07G\x8d_si\xe8\x84Cn\xd2\xdc\x0e\xbf\x87^\xc1\xb78C\xa6M\xb9\x86\x81\xd5|[E\xbf\x9b\xaa\xaf\xecLk\x02t4\x02\x94\xbd \xa4\x8cf\xc0 \x86@gS@\xd9\x1f\xb24\x06z\x9a\x03\x1d\x0d\x025\xdaqlk\x12t3\n\x94\x9d \x15\xdb\xca,\x18\xdc0\xb04\x0d\x065\x0e,\xcc\x83\xc1\x0c\x84~&B\x07#a\x103apC\xc1h*l\xc1X\xd8\x96\xb9\xb0\x05\x83\xc1\xc5d\xe8j4hy\xb8\xc9l\x18\xd0p\xb05\x1d\x1c\x8d\x87\xc1\xcd\x07\xb3\x01\xd1\xdb\x840$\xd8Y\xa8@FC\xc2^K\x1a\xd6\x98\xd0\x9b\x13\x12l0\xfb|\x92\xac>\x17\xea\x11\xe5\x8c\x0b\xa5\x93\x88\xa5\xfc\x10\xab1l\xed\xaa\x90\x11(&\xf9\xd6\x03\xd4\xbe\xb4\x9c;\x0bA#1\x9c\xd4\xd5\xc2\x86\xfaWju\x8a\xadyZ\x1c\x9c8\x9a\x08\xb4s9BE4\x88\xa4B\x82/Qp\xbe\x9f%\xfc\x7f\xb8\xdc\x96\xfb\xa2\xfd\x04\xe5\x82^\xad\xd8\x90)dL2\xb6\x82=\x88{?(\x0c#\xc9+\xca\\\xf807\xb4h>\xad\xd6\xfe8>r \xdb\xc7{-\x03cp\xf8\x0cN9\xfe\x9c/\xe4SA%\xd1\xa3\x04^~\xf7\x9dFL\xbe!\x04\xa6\x84\xc0s\x18\x8dF\xff\xa1\xfc\x8c#\x83\x92\x95\xfa\x03\x94\xacF\x1c\x8d7)Y\xdc\x9d\x12rO\xfd\xe9h\xa4\x96\x7f\xd1\x14\xee\xf2\xae>\x89\x89\x9c\x91\xbb\x7f\xe1}\xdd\x83\xdf4<\\\xd7\xdf\xefz\xda\x1d\x19h\xf77t\x81\x06#\x1e<\x17\xba!\x1fe\x00\nE\xf4\xee\x1bBFA\x8c(5\x10H\xa2\xc8\x1b\xc99V\x1a\xaaqPP\xae$\xdd\x03\x03\xe9NWlN\x12\x0d\xf1$Vo\x08\xb9;\x1a\x8d\xd4\xd2\xa0$\xdc]\xed7b\xf3 \xb2v\xa5*\xef\xe4\xad$\xea\xab\xd7\x1f_~x{z\xf6\xfe\xc3=\x95\x90\x80|X\xb9Q\xf5\x03\xcb\xa1\xf5\xe4<6\x90\xf3{\xa2\xa6\xa4 \xe5\xb3\xe7\xf0\x97\xe5d\xf4\x86\x90\xdfF\xa3\xd1\xef\xea\x8fQ\xb2\xda\xe3j(o\xb1\x94J\xd4;\x94\xd29\x8a9\x91\xf5\x13\xd1\x91\xb0\x89\x85\x06\x85h\xda@\xe0S\xb2X\xa3 \x10\x14\x07D|\xf5\x7f\x9eC\x12\xc5\xda\x0d\xae\xc7K\xb1\x93\xb9q+\xe8\\\xf0\xe2\xc2\xd0\x80\xc9j\xadv\x15\xd2CT\xe0\x9e\xb4k\xbd\xb9\x97\x8c\xab%\xedC\xed\xb6\xa8T\xfb\xdc~\x1f\x89\x1f\xb8\xba\xba\x0b\xa8\"\xed\xb8$\xe4;A%\x1b\xe4\x0ei\x1f\xac\x14-I\xbc*\xec\xca\x0dgA\xa9&\x03\x9a2\xa1\xb6\xb5\x0f$\xfc\x18\xbb\xfb\xbb\xedC\xe52\xb1@Y\x86\xc0\xf2\x84\x0d\xd8\x99\x122\x9a\xa0TL\xf6j\x7f5\xfa\xba#\xa9(l\xaf\xd6\xfe\xd4\xa6\xa8@u\x87\xf7\xc1\xc5a\xeb'\x7f\xfb\xf8\xfe\xe7\xf6_\x9e?\x7f\xfe\\\xbd\x07x\xbb\xb5\xcfE\xea\x91\x84\xb3\x83\\ \x92v]Fq\xe1X\x9de1J\xdb\xfb\xdb\xec\x86\x89:\xdck\xb5e\x0f\xf0b\x82\xc3p\xad\xc0\xecIu\xbc\xad;\xa4\xf0\xdeTT\x8a\xa90d?\xff7'\xdd\xe7\xdc\x99P\xaam\xd5\xc5i? 9\xfby\xa61@Pp\xcey\xd0\xda \x9eF1V\xcb\x8d\x82g\x9d\xe2\x94\x92D{lsO\xdc4J)\x1b\x8b\x15~\x0e\x87\xea\x9e\xcb\x06|S\x16\xdf\x1f\xb9K0\x00-V;\x82\x96;\xcf`\xa7\xed\xd4\xd6\xc90\x92\xb3\xdc\xd9\xd3\xf5'\xe6\xf73Z\xf0>\xffSN\xe1\xbf\xb4\x0d\xf8\xfc\x1a\xdf\xbbN\xf2\xed47\xb8\xea{M\xee\x86\x88\xc2%\x8e\xe3\xfb\xe7 \xb9\x94U\n\xe6\x88\x02\x82 \xa3E\x8aU\x13\xd4\x87\xab\xbe\xe5\xf7\xa4\x02\xdf8\x07\x92yV\xd0\xe1\x1bXa\\!\xb9\xa5\xdb\x07\xfb,\x0ec\xb1\xcf\xe7$\x0e\xe5&\x97\x98\xcb\xa3\x1c%\xe5\xf9\x00\xe9\x01l\xefJ\x1e\x99\xf6q\x04\n\xa3R8\xdf\xe5|\xad \xe1\x86k\xa8\xf0\x98\xfe\xfb_\xff\xbe\xa79HC\xec\xb9\xfa\x80\xfam'H\xc5\xbb<\x1c\x1d\x1d\x1e\xd1\xb6\xeb\xfd\x12\nA\xdd^\x17B\xe6\xfbm\x16\x94\xab\xe7.\xe5e\x0ej\xb9K\xf9\xdf\x18\x81/\xa2\xf0\xcb\xb4\xee\xf8\xda\xc8,Tf\x06\xb6\x9a\xe4\xcdD=\x11\xda\xba\x03\xd0\x9a\x9a&\xa6\xb6\x99\xf4\\f\xa3\x9d\x8a\xdf\x05\x9e\x11\xa6\xc2%\xbc\xa6F{\xeaY\xc6\xe6\xb2\xd5\x9d\x02\xf7[\x9a}V\x9d{\x15j\xc8\xc8\x8fj\xeb\xb7&@!\xc7\xe4\xad\x8fA\xf3\xcd\x16\xe8j\xbc\xc0\x0b2.\xe3'\x9a\xb8\x95Ul7\x8b\x12\xf6\xe8\xb8\xe5\x13v5\xa6\xd1l\x1cG\x8b\xa8k\x11\x05\xbb1\xbe\xe2q@(\x13\xd7%&+\xfd\xdd\xfe>\x83\xf1\xd9\\\xe04\x9a\xae\xe4x8\xe8-\xc0\x07\xbd}\xd0\xdb\x07\xbd}\xd0[\x82\x0fz\xfb\xa0\xb7\x0fz\xfb\xa0\xb7\n|\xd0\xdb\x07\xbd}\xd0\xdb\x07\xbd+0D\x00\xd2\x07\xbd\x05\xf8\xa0\xf7\x1f%\xe8\xad\n#\x97%N&(9/\xe3\xc8\x13\x14\xa3$\xc0\x96%N\xe2\xf8E\xfe}\x19Y\x16\xaeY\xf9G\xc1o\xe38/\xfd$Kn\xe7\xc5i\xf2\xb2\x1f\xed\x81\xe7u\xaf\xf9\xcf\xb76\xf2\\P\xebv\x04\x81\xfaU|\xeaU\xcc\xc9\xc6\xf9\x90\xd7K\x92\xf1w\x04\x8c\x9c\xe3\xbc\x82:\xaa\x95\xee\x11\xac\x0b%9B*;\xf9\xe7\xf7g\xaf\x9f I/\xbf\xcbEf$\xbc\x1ao\x13\x963\x93\xd2\x93T\xe5(\xad\x1dJ\x05\xab}\xb0\xb2\xc04-38\xb8:9#3\"\x8e\xef\xa6\x14\xae\x11\xa4\xd8&E\x10\xb7\xfc\xef\xfc\x80\xc8PC\x94l\xb8\xb5\x96h\x96\x13\xc5\x98\xddP|\xd8\xc8p(\xff\x9c+um\x87A\x82v\xf3\xe9\xb7^\x82\xaf\x98\xa9V\xb5E\x9c\\\xe9vc\x11\x8b\xf13\xf8\xbf*w[1~A_\xfe\xcf\xdc\xff\x8c(\x95N\xf6S4\xc3\x1f\xe4\xfb.#\xf9\xbb\xa2\xb3/\xe5\x1bN\xbc[NB\x0c\x0bB\x19`\xe1\xd5\x15\xae\xe0\xb6\xb3\xdb^\xf9\x0d\\\x08\xa0\xccL(I\xa0\xf48\x8a\xe1\xc5\xfc\xc5?d-k\xbe\xbf\x8axB\xc5y\xad\n\xc5VI$Kb\x8b\xceT\xb2\xef\x12Q\xa0\x98\xedA\xc4h\x11&\xa1\x90%r\x03\x86\xd2s|\x195\x1em\xb0\xc8|\xa8\x08\x00\xab\xf4\x87\xb6>\xf6\xab\xb2\xe9\xc3\xe9\xcb\xe6$|J\x84O\x890\x9c\xca-D\x13\x06H@\x8c\x14\xb9\x87\xa5L\x196 q\x8d\xdfZ\x96p\xfe\xa9B\xb3\xc1\xa3s\xa6\x8cr\xfe k\xe1\x89\x00d\xcem\xf2\x13Trp\xc1\xb6g\x8d\xf8\x9a\x98!7\x11\xf5\\y\x04\xef\x93x%\xa2\xe5d\nd:\xa5\x98\x01I\xa1\x8e.T\xd2\x1e(fMZ}\xc9\xd5\xe3\x02\xd6\xc4j>@\xa3\xd8\x02\xad\xd2\xac\x85\x88\x12?\x15\x1d\x1b\x9c1\x9f\x8c e\x92-p\x1a\x05\xc5\xdf\x84e\x16\xa0\xa4|\xb9\xe6r\x8e\x93\x82\xf0YR\xf2\xfd\x86\xab\xf2\xad\xe8-\xe6{\xa8$\xa1\x0c\xf3e\\G\xe7\x1d\xb8\xd1\xb3\xde\xfd\x96\x89\xdb\x90\x94-\xe4\x15Y\x90\x96\xd4\x15\xdf\x16'K%@\xa5BQ\xdd\xc1\xb9@\xca\xe2\x06W\x97\xe1\xab\xea\x9f\xdeN!\xc6S\x96GJ#&M\xe7\xc2\xc1(b\xf1\xf2\x80\xc8A8\x9d'+\xc0(\x98\x03Z.o\x90\x8aU5`\xdd^G\xcbJ\x0bNQ\xb1C\x89`4\\I\x81( \xa3\x001\\f\xe5\xe4\x14\x14\x1f\xe6\x1b\xa9\xda]\x94\x04q\x166\xdc\x87\x08jE#\x9b+&$JE\xe1\xe1jBM\x13\xaeu\xf6\xe9-m\xacVc\n\xc2\xe3\xcae\xbd\x94\xfd\xe2x\xad\xcf#?r\xa3\xfc4E\xb3\x84\xa4\x8d\\\x87\xe24\xd6\x87\x90\x94\xe9\xbb\xb0\xf5w\xb3\xfa\x1a\xfay\xc9\\\x9d\xc1\x9fkTJc\xbfV{\xd6\xda\xe0\xcf{\xbdSL\xfav\x1b\xfb\x06K\xac G\xb4A\x9d\xc2\xca\x1b\xd4\xf4\xd2\xd8\xfc\x06\x15\xc5\xfc^VKS\x0b\xed=_M+\xcd=\xd7\xd5\xeb\x1b\xa0\x00_\xae+\x07\xaf\xa6{5\xdd(\xd5\xefW\xeb\x96\xab\xb0\x13?\x16\xb8\xadkfo\x1d=\xd3U\xa6\x9adr\xbc\xca\xc46n\xf2\\\x89\xfe\x1a\x97y\x1a\x12'9\xff\xb6\xef6\xf5\x10\x19\x14'\xe1\x18'\\5\xd2>{\xfbGx.Q;M m\xaaT\x13l\xdc\xdb\x1c>\xe2$|-\x87\x94i\xd5\xf53\x86j\xb4\x07\xca\x10\xcb\xd4\x89\x9dw/\xe7X$_\xa2\xf2\xdc\xaa\xc3P\xbcc\xde\xeb\xbd\xf6\xd4@!5\xc7\xb6+\xaf\"F\x8d\x0c\xa7\xda\x0bu\x85\x80o9\x89-}Y\xdd\x80\xaa\x8e\xb4\xa9M\x94>\x02y\xfa\xdb\x8eQ\xed\xae\xa3\xd7%\xbc.\xb1\x01[\xd0%\x9cD\x9f|\xc6C-\xfa\xc4c\x1f\xf2\xc1\x8e\x9a\xfcc\xcdG@\x8a\xa8k\xab\xf4\xab\xf4\x92\xff|k\xc5_\x95 U\xb8\x89\xdd\xe5\xc3\xab\xb7'\xbc\x9a\x87\xc3\xf2\x1d\x9f+\xb4\xeb\xfd_\x06T\xef\xb44j\x176\x95Cae\xba\xb6\xf5\xb1_=\x9f\xca\xa0S\xf9G/\x806\xe8\xe3\x05\xd0\xb5 \xa0v\xb7`\xfe\x86\x96\xd9\x15(w\xf9\xfbiM\x0e)\x9e\xa1j\x95BE\x07\xf9o\xb7V\x04\xa9\x18w\xdd\xec\x97LR\xc9\x88\xfe\xe0>\xbfb-\xad8g\xce+\x1b\xeb_\x80\xf7\xfa\xe5\xe0\x19\xe553J\x9d\xd7\xef\x1b\xf5\xaaQ\xbc_y\x9a\xbf\x0c\xfd\x88\xc7n\xf7c\xc40ej\x0e\xff=f?\x89O^\xf0\xef\xcbw\xec\x98\xa8\x83\xc0\xff._\xcdme\xee\xf5\xb6w\x8a\xb9\xddR\x16/\xe61\x8e\x94O\x06w\xe2\xd2sD\xe7\x8e\x9c\xb6\x00CB\xdc\x12\xa5lL1\x1b\xcf1\nq\x0b'\x02\x13\xe6`\xc4\x9e\x83&\xa5\x0d\x8c\xec\xab\x80\n\x1bS\xa4\xb6\xe9H\x056\xe4\x023\xc9J\xe5\xff\x14\xa5\x8cb\xf6\x83\xa0\xdc\xe6r\xcb\x8f\xc4\xa6}\xfb\xaam\x97\x0c\xbbE\xb6\xbb~\xf9\xf5y\x0de\xe5t'\x88F\x81\x9c\x1eD\xc9T\x95\x18i\x81\x13X\xe1\x05jbV\xc1j\xdd\xc1.}R\x02Z.\xafwH\x1b\xbb]\xc2K\xce\xda\x12\x9aQ\x08\xd0R\x9a\xc2R\x9a\x14\x7fN\xb3X\n\x10N`\xce\x13\xf5(\xa2r=\xa5\x1b\x96\xff\x87xuyOs\xe10\xcf\xb6\x10Oo\xc6q\xa5\x11\x84\x88!N\x97,\x90\xb8\xe5\xb7\xd8$V\x9a\x0e\x8b\xbb\xed\xeb\xea\x17\xbb\x1a'6\x08\x978\x06\x96\xa2\x84\xca\xab\x1e\x0b\x14\xcc\xa3\xa4\xf5\xc2;\x07\x81]+\xe7.\xc0bI\xe78\x9a\xcd\x95\xae\x19\xab.\xec\xf8\x1c\x8b\x16J\x9d\xc5q\x98\x101|\x9f\xf7\xa7\xf8R\\\xa6R\xcb\xb5\x02r\x0e\xb0L\xf1\xc553\x00=\xcf\x07[z\x80\x0d\xef\x97`%6\x0b\xb0\x9a)X\xcf\x16\xcc\xe2\xb4\xfc\xccJ\xac\x16`\xb3\xed\n0\x93\x1c\\\xc8\x0e\xf6\xa4\xb7\x14\xbf\x12\xc4\xd6\x0d\xc8b\x11\xb1\xf1uh\x06\xb0F\x8f\x0f'\xafe\xc8\xc3\xc0\xd9\x9e\xa2\x0d\xff\xe9\x9a\xd0\x13\x15D\x10#)\xbd\xa6\x01\x9b\xf4\x98\xa6\xdc\x9a\x91|\x1cH\xc6\x96\x19[\xffm\xcd;\x14\xbd\x89\xdc\xdek\x9fC)9\xafi<\xb4\\^\xd3H\xe2|\xe4Y\xa9\xd74$\xbe\x88B\x9c\x04\xf8\x9a\x86+\xf7\xdfZ\xfd\xd1\x88%\xce\x81 \xc5\xe98O\xb6\xd96~5\xa5Nr\xb2Zl\xbaT\x93\xa4\x1f\xf4\xac4\xc0s\xa6\"\xc5Ok\x9c\x1e1\xb45k\x80]\x19)\xa3\xce\xf8\x00S\xd6\x07\xd8\x92\xd7\x82\xc0\xe0\xa49\x9f]Q\x99L\\\\G\x16\xca\xa6\x8c Iu\xf2\xbfsG\xc5\x0fB\xcf\xfb\xeePS\xbd\xa4\x08|\x89\xa2\x85q\xcc\x89\x06s\x9cbQ\xb2M\xf0\xb0\x11\xc0?\xf0n\x8a\xe1\xd7\x8c2@\xb3\x14c\xfdt\xf3\x1au$\xe5\xfbD\\\x1a\xd7\x8e/\x8aY.0J\xf2YI\xd4O\x96\xcb\x1f\x10\x9dCH\xb0,\x10\x96\xe7E\xf3\xae\xa9N\xf2\xb2+E\xad,\xd3\x85\xb2W\\\xe3\xaf\x95\x1c\x10\xd9\xffS\xa9\x9c\xa3\xbc\x10R\x8eF\xa8\x7f;X%\x1d\n\xb6\xb2\xb5=\xaf\x1f\x00\x86\xdd\xf8Fe\xd1\x8c\xaf\x840\x93\xd6\x12\x1e_\x10\x86\xc7\xe6IH\xb0\xc4\x02\x1c0\xe1 pP\xb0\xa5:8 \x00\x8eH@\xd1\xbd\xd5\x97\xd6\xac\xa8\n8\xc9\xb4\xf9fu\xb8\x0f\x1f\xdf~\xff\xf3\xebW\xe3w\x1f\xbf\x1f\x9f\xfd\xef\xe9\xeb\xf1\xa7\x9f\x7f\xfc\xf9\xfd?~\xee\xd1\xc3\xe9\x87\xd7\xbf\xbc?{\xdd\xaf\x87\x97\xef\xdf\xbd{{\xd6\xab\x8f\xf7\xa7\xef?\x9e\xfcd\xd9E\x11\x9b\xe9I\x0f{~_\x87\x8f\xd1,\xc1\xe1;:;\xcbK`\xc8\xca\xa7\x9cQQ\xf1\x93uO\x95\xaaL5\xcf\x8b\x96[7@\xb9\xa6\xcf\xe0\x17\xc2\xb4\x9e\x92\x06\xa8\xd7\xe5\x19\x9c\n\x85\x07\xc5v\xdd\x99\xbc\x1bu\xe8pp\\LP )\xc9\x12mNf\x15\xdc\xeca \xba\xd8Y;\x98]%up\xe4u\xd0\x81\xdf\x81\xb5\xc9\xbe\x86\x0e\xcb\x07\xb6*Y\x13\x9c\xfc)u\xe8@=\xe8HA\x0e\x96\x9e\x97:t\xd9w\x05\xb8\x1f\x89\x02\\\x17\x1c\xba/:t]x'oN\x13\xb4!\x96v`\xd1\x02S\x86\x16\x06\xe7\xfd\x1a:\x10\xc4\xd6\xafZ\x87\xd2\xaba\xb6=\xeb\xd0\x03C\xeb\xa5Z#\x17%!\xberC\xcdm\xdf\xbb\xf3\xdb2\xe5\xcf\x0d\xadmR\xac\x8b\n\xc2\xa5\xfa\xba,\x16\xd7>\x96)\xe6\x1a\xf3^^o{\x11\x89Z\xe1V\x9d\xc9\xcf\x85\xc2-\xddkk\xa7\x19\x9f\x8b\x9d\x1eR\xd1[L\x9f\n\xcd~b\xb3\x00\x8e\xfc\xda\x95O{\xcd\xbe\x01^\xb3\xf7\x9a\xbd\x19\xbcfo\xfa\x1a\xbcf\xef&\x03%x\xcd^ \xeeG\xa2\x00\xd7\x05\x87\xee\x8b\x0e]\x17\xdek\xf6\x05x\xcd^\x82;\xbf\xf5\x9a\xfd&\\\xb7f/\xd8\xe2\xf8\x82\xb0(\x99\x8d\x97\xe4\xd2\x8e\x87;.\x84\x1b+\\\xef\xd9\xdb\x81\x8f\x13\xeb\xe9\x88\x89-\xcbq\xdd\x9f\xaf\x8a\x00\x11\xdf\xa4\xaf\xf3\xf0\xd0:XW\x04\x8cD\xfc\xd9\xd8Y\xb90\xb9Z\x0d\xec\x92\xf0\xbe\xa6q\x14\xf0\xfd#v\xada\xcf\xc5\\\x11\x1d\x07q\x84\x136F\x8c\xa1\xe0\xfc\xa6\xc3V\x95\x19\x8c-\x92M%8\xe0\x02\x8e\xf8@\xce\x1aq\xe8\xa8U9\xe2\x04\x1d\xf0\x02C.r;t@\x0c:\"\x076\xd9\xcc\xed\xe0\x9a\xe3\xdc\x0e\x1d\xe7\n=\xe6\x0bvY\xd2\xed\xe0\xc8\xb0\x9aP00cFu;\x18\xf3\xac\xdb\xe1&\x91ve\xc1M\xb0\xcb\xdfv\xee\xb6\x9e\xef\xdd\xc8\xeav\xee\xcd2\x0b\xbc\x1dls\xc3\x9d;\xae\xe5\x92;g\x8c\xb7\x83k\x1ey;\x98\xb3\xcb\xdb\xa1\xf3Fv\xf3\xe8\x14\xd0y8W\x9d\xa9\n\xfa\\\xf6v\x18\x00Q[\x95\xaa\x0e\x96\xd9\xf0\xed\xe0\x98#\xdf\x0e7$@\xba8\x1d\xa0\xdfJ\x81\xbb}V\x87\x1e\xde\xa7\x02zP\x1bzR\x1c\xbaz\xa5\n\xe8b\xa57\xa1\xfb\xb1.\xa0\xeb\xc6\x81\xfe\x9b\x07\xfan\xa0^^, \xf6w\x10\xda\xa1\x07 zL\xdd\xfd\x16C;X\xdcmh\x87\x9b\x98\xb6\xf5\xcd\x82v\xb8 \x94\xcd\xd9\xb7j\xb0\xbd\x92\xe1\xdc\xb1\xee\nG;\xb8]\xech\x87\x9b \xbf\xed\xd5\x90v\xb8 \x8c\xcd\x97K\xda\xe1&pu\xb8\x9e\xd2\x0e7\x81\xb4\xe5\x05\x97v\xb8 \x84\xdd\xae\xc8\xb4\x83\xfd\xc5\x99v\xb8\xfey\xf7\xb1\xd2\x8d7u\x9czs\xb8\xd5\xd3\x0eR\xb9p!yG\xa5\xb6\xab2\xfb\x0d\xd9\xa2NY\x07\x05\xf4\xd1\xb3\xdd\xa3b\x05t6B\xbb->\xf4\xd8\x00\xd0\xc3\x0c\xe8\xb1\x0d\xa0;{\x90\xe0\xed\xc7\xce\xfb\xba\x80\xeeG\xb1\x80\xae\x1b\x07\xfao\x1e\xe8\xbb\x81\x06\xb0\x1f;eC\x14\xb0.\x87\xe9JAI9\xfdm\xb6v0\xdeqk\x87^\x07\xa5\xdf1)8\xe9x\x1a\xa3Y\x97\x0e\x06\xd8hn\x99\xa5u\xb8\x0f/~z\xff\xf2\xc7\xf1\xdbW\xe37?\x9d|\xef\x98U\xd9\x84fo'/>\xbe\xfe\xd9>Y\xb4\x0e\xcd\xce\x1c3O\xeb\xd0\xec\xec\xe7\xb7\xb6 \xa8u(\xd3Q\x87#[w+\\\x82<\xdc\xe1\x9b\x18\xcd\xca\x87\x8dh^\x19\xf7E\x1c\x90\xf3\xb7\xaf:\xc5i$\x94l\x00\"\x99%bj\xb0 \x9d\xb3\x98\xea\xd0\xfb\x9c\xf4f\xc7\x0e\xb9\x1a\x9b0\x18\xfa\xdd\x82\x0f\x12\x9c\xd3\xa2\xea0\xd8\x1c:-A\x1f\xbbK\xc2Ka\xee|\x8cf2\x93\x9b\xebhE\xa8OdZ\x15\x17\xc9;t\x1d%\x80\xf2\xfe\xed\xcd\xaf~s\x92\xa3\xd5\xaf\xc7\x97Y7\xe2\xda\xbe\x9b5)M\xc8KDs\xb3\x90\xc9\xf2\x05(\xbfs\xef\xd4\xd7\xda!gG\x8d5\x8f\xa0\xd8\xda\xdc\xeb \xf7\xbbH\xfb\xf5\\\xec\xdbt\xd5\x82:h@\x1d\xa8 \xa1\x0b-$t\xe6\xe3\xbd\x18H\x0f\xe6\xb1\xcc&\xea\xa7\xa1u\xd0\x99\xb8\xd0\x8b\xc0\x1cpx\xf4\xf0\xe1\xe1\xd3.M{\x12\x1a\xfa\x11\x1b\xc4K0\xc1\xf2\xe8\xe1\xa3\xf3\xc3o\x11\xfd>\x1a\xd9i6\x89\xa3\xe0G\xbc\xaa\xf9\xf8\xce\xf1\xaa\xf1\x16d\x87\xae3\x8a\xe5S\n\x15\xb7\xdf/%or\xec\xd05-\xb7\x0e\xbd\xd6\xa7\x8f]_z\x8b\x97iD\xd2\x88u>\xd2\xd7\x8a{\x81\xb5\x0b\xb2\x1d9OW\x9e\xd3\x91\xa5\xf7 f\xe7#\xda\x91\x99w$(\xf4 *\xf4c\xe3=\x88\x0b}\x08\x0c}\x19\xf8\xcd!\xde\x9duo\x8dq\x0f\xc8\xb6\xfb0\xed\x1ek\xd2\x8d\xe9\xc1\x10\xec\xfa\xda\xb1\xeevi\xa5\x80\x8e\xe8\xba\xa1\xca\xad3\x92\x8c\xedCc\x8eX\xb9a3Y}E \x8b\x12+\xde\xaa\xf9\xf4\xe1'y\xc6V\x11\x8eC\x8d\xe6\xf0\xaf\xe6\xb18[-\xf1\xbf\xff\xf5oe\x83\xfc\xe1f\xbe\x1f\xe4~\xcb\xc5\x88X\xa1eJ\xc2,\xc0\x80\x12)\xc2\xd4\xf9k\x7f\x85\x93u}\x10*\x1e\xe7A\x9cf8\xe4\xe4\x0eP\xc0y\x0b!\xe7\xd9\x12\xf2\x9b\x880AT\x93]HL\x05U>}\xf8I\xe08G\x17b\x0b.*g(\x94\x87\x08\x15S\xe2\xff\xbe Q\x08(\xd1\x05X$\x82\x82}\xa4xJR\xbcWt\xc0\xfbE,\x9aDq\xc4V\x90`\x1c\x8am4\x117{\xc5V\xd3\xe5I\x92\x84\xb3\xd9d\x86E#qfGp\xf7\x13\xc5E %N%\xbe=9\xcf\x92\xfb\x13%h\xa6\x9b\xfd$\xc5\xe8\x9c\xf3\xa0\xbc\xe3\xd1=\xf5\x8e\xfa\x990\xfc\x0c\x18\x97!\xd3, \xe4 \xe3\xf3\xc8yW\x90\xa5)NX\xbc\xaax\xbf5\xecR\xbc\x9d4\x9dFA\x84b\x83,\x9bdSH1\x97DxOT\x95\x89X1hFq(\xb5\xbc\xe2\\*\xbb\x9a\xe0Y\x94$|\xb2\x97\x11\x9bk\x84\xcbj\x89Gr\xff\xa3eDG\x01Y\xe8\xb8\xf1GqR)\x106\x97\x8c\"ir)\xb8\x9b\xbf\x8f\x8f\x17K\xb6\xca\x8f\xf6=\xb5\x10\x8cfs\x06\x13\x0dS\x12\x93\x16a\x82h\xb1\x8c1\x17\xb2\xe2\xc0\x00]\xe2 \x9aF\x01P\xbc@ \x8b\x02E\xaa\xe8\x16\x1eYo\x82\xad\x96\xf4\x8e\xb3\xa3 \x06$\xad\x81\x8a\x82\xb3\xa1\xc7\x14\x15\x84&\xe4B\xbd\xa7s\x12\xe4G\xa1\xf516\x0b\xcc>\x9f$\xab\xcfk\x93\x07%\x80\xd2I\xc4R~\x88\xd5\x18\xb6vU\xc8\x08\x14\x93|\xeb\x01j_Z\xce\x9d\x85\xa0\x91\x18N\xeajaC\xfd+\xb5:\xc5\xd6<-\x0eN\x1cM\x04\xda\xb9\x1c\xa1@\xb3\xe5\x92\xa4B\x82/Qp\xbe\x9f%\xfc\x7f\xb8\xdc\x96\xfb\xa2\xfd\x04\xe5\x82^\xad\xd8\x90)dL2\xb6\x82=P\xceXQ\x18F\x92W\xc0\x0c'8EL \xcf\x0d\xad\xa2(Tk\x7f\x1c\x1f\xb9\x84\xed\xe3\xbd\xbeB|\xf3\xc3\xe138\xe5\xf8s\xbe\x90O\x05U+\x83\xbf\xfc\xee;\x8d\x98|C\x08L \x81\xe70\x1a\x8d\xfeC\xf9\x19G\x06%+\xf5\x07(Y\x8d8\x1aoR\xb2\xb8;%\xe4\x9e\xfa\xd3\xd1H-\xff\xa2)\xdc\xe5]}\x12\x139#w\xff\xc2\xfb\xba\x07\xbfix\xb8\xae\xbf\xdf\xf5\xb4;2\xd0\xeeo\xe8\x02\x0dF\xca\x00\x14\x8a\xe8\xdd7\x84\x8c\x82\x18Qj \x90D\x917\x92s\xac4T\xe3\xa0\xa0\\I\xba\x07\x06\xd2\x9d\xae\xd8\x9c$\x1a\xe2I\xac\xde\x10rw4\x1a\xa9\xa5AI\xb8\xbb\xdao\xc4\xe6\x13d\xedJU\xde\xc9[I\xd4W\xaf?\xbe\xfc\xf0\xf6\xf4\xec\xfd\x87{:7\xd9z\xa3\xea\x07\x96C\xeb\xc9yl \xe7\xf7DS+\x8e\x93\xf2\xd9s\xf8\xcbr2zC\xc8o\xa3\xd1\xe8w\xf5\xc7(Y\xedq5\x94\xb7XJ%\xea\x1dJ\xe9\x1c\xc5\x9c\xc8\xfa\x89\xe8H\xd8\xc4B\x83B4m \xf0)Y\xacQ\x10\x08\x8a\x03\"\xbe\xfa?\xcf!\x89b\xed\x06\xd7\xe3\xa5\xd8\xc9\xdc\xb8\x15t.xqah\xc0d\xb5V\xbb\n\xe9!\xdf\xe0l\xd7zs/\x19WK\xda\x87\xdamQ\xa9\xf6\xb9\xfd>\x12?puu\x17PE\xdaqI\x98W\x0fl\xedP\xee\x90\xf6\xc1J\xd1\x92\xc4\xab\xc2\xae\xdcp\x16\x94j2\xa0)\xc3m>B \xc2\x8f\xb1\xbb\xbf\xdb>T.\x13\x0b\x94\x85\xb5\x0b8\xdf\xd1;SBF\x13\x94\x8a\xc9^\xed\xafF_w$\x15\x85\xed\xd5\xda\x9f\xda\x14\x15\xa8\xee\xf0>\xb88l\xfd\xe4o\x1f\xdf\xff\xdc\xfe\xcb\xf3\xe7\xcf\x9f\xab\xf7\x00o\xb7\xf6\xb9H=\x92pv\x90+A\xd2\xae\xcb(.\xfc\xab\xb3,F\x8a\xca\xd6\x9b\xdd\xf0&!^\xab-{\x80\x17\x13\x1c\x86k\x05fO\xaa\xe3m\xdd!\x85\xf7\xa6\xa2RL\x85!\xfb\xf9\xbf9\xe9>\xe7\xce\x84\x9a\xa7\xbaX\x9c\xf6\x03\x92\xb3\x9fg\x1a\x03\x04\x05\xe7\x9c\x07\xad\x0d\xe2i\x14c\xb5\xdc(x\xd6)N)I\xb4\xc76\xf7\xc4\x89\xa7c\xc7b\x85\x9f\xc3\xa1\xba\xe7\xb2\x81HL\xc8\xbf?r\x97`\x00Z\xacv\x04-w\x9e\xc1N\xdb\xa9\xad\x93a$g\xb9\xb3\xa7\xebO\xcc\xefg\xb4\xe0}\xfe\xa7\x9c\xc2\x7fi\x1b\xf0\xf95\xbew\x9d\xe4\xdbinp\xd5\xf7\x9a\xdc\x0d\x11\x85K\x1c\xc7\xf7\xcf\x13r\x99\x08>3G\x14\x10\x04\x19ed\xe1x\xb8\xea[~O*\xf0\x8dsP<`\\\xa2\xc37\xb0\xc2\xb8BrK\xb7\x0f\xf6Y\x1c\xc6b\x9f\xcfI\x1c\xe6\xd5h\x05\xe6\xf2(GIy>@z\x00\xdb\xbb\x92G\xa6}\x1c\x81\xc2\xa8\x14\xcew9_+H\xb8\xe1\x1a*<\xa6\xff\xfe\xd7\xbf\xefi\x0e\xd2\x10{\xae>\xa0~\xdb R\xf1.\x0fGG\x87GtG\xb3\x85\xe4\xff24\xab\x04\x0d\xee\xc3G\x9c^D\x01\xa7\xde\xee~@\xe8\x82\xd0\xfd \xa2x\x9f\x95\xa9y\xfb\x17\x87\x13\xcc\xd0\xe1\xbe\x08\x7f\xd1\xfd\xdfd:\xcf\xef\xbb\xb2\x9b\xd9\xfa\xda%\xcd\x16\x0b\x94\xae\x9e\xc1\xf7X\x86\x9b^\xac\xe4\xa3\xd5\xf0%\xc3i\x84i\x1eA\xe3\x84\x9eE\x178\xc93\x83\n\xaeE\x96X\xce\xf9m\xb8\xd9G\xfeM\x11x\xaaLb\xf7\xe8\xe0`W\x1d\xbd\x02\x9a\x05\x01\xa6t\x9a\xc5\xdb\x0c[\xa9S\x82\x94\x9d\x811\x94\xa3\xceC1\xfa/\x0c\xde\x0b\xab\x14\x1f-\xe6`\xc4\x1e\xcc\xa9<\xcc*\x85\xc7&u\xe7:\xde\xf6\xb7J\xcd\xd1\xa6\xe4(J\xa2\xf7\xd9\"\xdb]?c\xddz\xd7\n\xf5F\x9c\xc0\n/\xb0\xab/o\xb5\xeePY{c\xf9ucu\xf8\xa1\x87\xb4\xf1\xe4I\xb0\xab\xe2\x0e\xf5\xaa\xec\xba\xa9\xd6\xea\xb5\xdb\xd6_\xb7\xad\xb4^\xaf\x9c\xae\xe9\xd0\xb5\xa6\xbak\xf5ts\x9dt\x8b%\xbd\xb6\x1cW}\xe5r\xa7aL\xc9D\x96u\xc7\x1d+\x8c\x0f\xc8\x00\xcci\x9aV\xf4\x00\x1b\xde/\xc1Jl\x16`5S\xb0\x9e-\x98\xc5i\xf9\x99\x95X-\xc0f\xdb\x15`&9\xb8\x90\x1d\xecIo)~%\xd8W\xc0\xb6B\xd5\nE\xf7\xfa\xd5\x16\x95\xaa\x87B\xcf\xba\xd0\xf1P\x036\xe9a,\xf9\xac-\xe1\xecV\xacy\xa89\xd8\x96Z\x1ej\xf4\xd8\x00\xd0\xc3\x0c\xe8\xb1\x0d\xa0;{\x90\xe0\xed\xc7\xce\xfb\xba\x80\xeeG\xb1\x80\xae\x1b\x07\xfao\x1e\xe8\xbb\x81\x06\xb0\x1f;eC\x14`\xf3\xe6S;H\xca\xd9\xbe\xafZ\x05\xe3\x1d\xb7v\xe8uP\xfa\x1d\x93\x82\x93Z\xbd0\xd5\x0e\xbd7\x9a[fi\x1d\xba\xbeQ\xd5\x0e\x1d_\xaej\x87\x8e\xefY\xb5\x83\xfb+W\xed\xd0\xeb\xed\xabv\xe8n\x85K\x18\xea\x9d\xacvpz=\xab\x1d:g1\xd5\xa1\xf79\xe9\xcd\x8e\x1dr56a0\xf4\xbb\x05\x1f$8\xa7E\xd5a\xb09tZ\x82>v\x97\x04\xdb\xf7\xc2:t\x1d%\x80\xb4\xaf\x88\xb5C\x9f9Y\xbc8\xe6\xd4\x9f4!\x9b\xaf\x93\x95\xef\x909\xf5\xa5z\xb3L\x05k\x1eA\xb1\xb5\xb9\xd7A\xeew\x91\xf6n\xaf\xcb\x17\xd0M\x0b\xea\xa0\x01u\xa0\x82\x84.\xb4\x90\xd0\x99\x8f\xf7b =\x98\x87\xf3\xeb\xf4\x05t&.\xf4\"0t}\xb5\xbe\x80^\x84\x86~\xc4\x86\xee\xaf\xd9\x17p\xb3\xe8\xf7\xd1\xc8\xb6\xf0\xda}\x01\x83\xbcz_\x80kZn\x1dz\xadO\x1f\xbb~\xd9\xfdU\xfc\x02n\x00\xf7\x02k\x17d;r\x9e\xae<\xa7#K\xefA\xcc\xceG\xb4#3\xefHP\xe8AT\xe8\xc7\xc6{\x10\x17\xfa\x10\x18\xfa2\xf0\x9bC\xbc;\xeb\xde\x1a\xe3\x1e\x90m\xf7a\xda=\xd6\xa4\x1b\xd3\x83!\xd8\xf5\xb5c\xdd\xed\xd2J\x01\x1d\xd1uC\x95[g$\x19\xdb\x87\xc6\x1c\xb1r\xc3f\xb2\xfa\x8a\x12\x16%x\xecf'\xb9\xd9G\x0ev\x913\x9fw\xe7\xee\xce\xc2\xd2q\x05$t`\x83\xce\xa2\xd1\x99X\xd0\x89`\xd0U\x10v\"\x1ct#\x1et\x17{\xd7\x8bf\x17!\xb7\x05\xf16\x88`\xeb\xc6i;\xd1\xdb\x8d\xafI\xe8!\xc0\xae\x01\xc7n\xc2\xca\x111G\x94\\\xbc\xe4\x1d1\xb1\xf5\x80\xbb:W\x7f\xe2\x02\xf5\xa5\xb8?x\"\xae\x0f\xf6\xbd\xd5\x98\x17+\xad\xdc\xb3E\x8c\xe1\xc5R\xdchd\x04\x16\x11\x8d1\n\x01\xc9\xbb\x8b\xc6\xfe\xe4\xdd\xc66\x8fj%U\xb8\x9d\xf0FFof\xea&\x85\xc3j5mv\x93!\x93F\x8ec\xca-\xb0\xc9\x8e1\xe7\xc1\x18\xc9\x06V\xa4\x03\xabd\x04+\x02\x82\xbd\xd4p\xcaA\xb1\x9a)X\xcf\x16\xc0:\x83\xc4n=\x0b\xb0\xd9@\x05\x98I\x0e.d\x07{\xd2;foX\xe5i\xd8dd\xd8h\xd5F]\xdar+\xd8n\x04\xa7\x1c \x87\xc5\xb0\xcb{\xe8\x9a\xe1\xd01\x97\xa1c\xd6\x82{~B\xafL\x04{\x0dr\xa8\xec\x02\xa7<\x02\xe7\x8c\x01\x87]\xe3p\x80-5\x99\x0e\x83\xdbi0\xd6\xd1\xfa\x0e\x18\x18\xa6\xef\xa2:\xd9F\xd5E\x8c\xdc\xa2\xa7\xf6\x88\xb1\x1dF\x161qE\x9c[\xd1!\xdaT\xe2\xea\xf8\xe9\xf1j>B\xf8!\x7f?\x90\x93J\xbe\x13\x9b\xff7_B\xbe8-\x87\xe9\xef\x19NW\xfb\x1bO\"~8}\x99\xbf\xe2\xbbF\xa8`\n\x95\x1e\xeao\x19&\x90%\xf8j\x89\x03>i\x9c\xa6$\xdd\xe6\x93\x86b\x80\xcd\xcd\xab\xd9\xae\x01 [v\xbb^C\xd0izy\xd5='\x1cB\xccP\x14\xb7\xf0\x1c\x9dpU\nU\x8305 Q\xde|\x9c\xa5J5\xca\xe2\xe8\xdb\x9d\x1c\x80\x13\xf8\xf4\xe1\xa7\xfd\x14S\x92\xa5A\xfe\xee\xb382Y\x12}\xc9p\xbc\x02~\x8eX4\x8dp\xe5\xd1`Mb\x88|\xaf\xa1x\xd3X\xf3xpJ\x18 H\x0c\x93l:\xc5\xe5\x1b\xaa#\xf9\x0c\x85\x9c\x1b,2Z\x9ek@j\xbd$\xc6\x882\xf5X$\xc1\xb0\xb3\xbf\x03\xc1\x1c\xa5(`8\x1d\x89\xe7\x9d\xc5\x0b\xd6\x14\xcf\x168)\x99\xd7\xa7\x0f?\xedRX\"\xc5\xb3\xcb\x1c\x04Re}&\xf5\xa8\xac\xe5qmA\xdf|(A\xc9\xbb\x88B\xa4x\xcb\x99\xc3g\x8e\x8a\xf2\x99\xd7\xcf\xf7\xe4LD\xb7tN\xb28\x84 g\xbe\xca\xfe\x10\x04(!I\x14\xa0X\x9c!\xf5\xc8w\xf1h6\xda\xe3\xa4\x15\xa5\x17vF;\x9c\x7f\x89\xe7I\x82\x00/\x19\x0e\xef\x8d\x14\xefmsx\x9b\xc0\x92\x13;\n\xf0\x1e0\x8c\x16\x142\x9a!N\x0eY\xc5j\x19\xc5\x1cS\xf9\x0e/L\xa2\x04\xa5j\xf5U\xbc\x88\xb2Z\xe2\xfci\x126\xc7+\xf5\xd0\x92\xd7A\xc4\xb8\xb9\x9d\xd1j\xf9M\x86\xaf\xc4R\x9f$\xab\x11\xfc@.\xf1\x05N\xf7\xb4\xaa\xc9\xa7\x0f?\x15\xaaO\xfeb\xbaz`\xc1A1|\x9e3\xb6\xfc\xbc'\xff\x97~\xde\x03\x92BB\xf2_\xf7\xc4n\x0cP\x02d)\x1f\xea\x8e\xd5\xd3\xe6b([\xe6\xf5G5\xe3\xe2\xf4B\xbc\xd4\x8e\x18,\xd0\x92\xca\xad%0g\xa4,B*|\x80\x91|=\x05\xa9]uS\x12\xc7\xe4\x92>\xd3\xac\xed_\xe1\xedt=#\xbe-\x8a\x07\xf2\xcbI\x0b\xb5\x80\xd2l\x81CM\xb1\xd3\xbfr\xe1\xf4\xc3\xd9\xd9)|\xff\xfa\xacx\xaf\xe6\xd3\x87\x9f\xe4\x19\x13\xaf\xc1k\xb4\x87\x8d\xe7\x96\xcfVK\xfc\xef\x7f\xfd[\xd9\x00\xf2\x17\xdb\xa3$\xdfo\xb9\x18\x11+\xb4LI\x98\x05\x18P\"E\x98:\x87\xed\xafp\xb2\xae\x11B\xc5\x03=\x88\xd3\x0c\x87\x9c\xdc\x01\n8o!\xe4<[B~\x1b\x11&\x88j2\x0c\x89\xa9\xa8\x8axA\x9f\xa40G\x17b\x0b.*g(\x94\x87\x08\x15S\xe2\xff\xbe Q\x08(\xd1\x05Y$\x82\x82}\xa4xJR\xbcWt\xc0\xfbE,\x9aDq\xc4V\x90`\x1c\x8am4\x11\xb7{\xc5V\xd3\xe5J\x92\x84\xb3\xd9d\x86E#qfGp\xf7\x13\xc5E\x19%N%\xbe=9\xcf\x92\xfb\x13%h\xa6\x9b\xfd$\xc5\xe8\x9c\xf3\xa0\xbc\xe3\xd1=\xf5\x8e\xfa\x990\xfc\x0c\x18\x97!\xd3, \xe4 \xe3\xf3\xc8yW\x90\xa5)NX\xbc\xaax\xc05\xecR\xbc\x9f4\x9dFA\x84b\x83,\x9bdSH1\x97DxOT\x96\x89X1hFq(\xf5\xbc\xe2\\*\xbb\x9a\xe0Y\x94$|\xb2\xe2\xe9\x7f5b\x9b\x8f\x81\xeb\xb8\xf1GqR)\x106\x97\x8c\"ir)\xb8+\xf5P\xc0\x8b%[\xe5G\xfb\x9eZ\x08\nut\xa2aJb\xd2\"T\x10-\x961^\x94O\xbe\xd3%\x0e\xa2i\x14\x00\xc5\x0b\x94\xb0(P\xa4\x8b\x8a\xb3\xdaC\x05\xb2\xb0zl\xb5\xa4w\x9c\x1dM0 i\x11T\x14\x9c\x0d=\xa6\xa8\"4!\x17\xea=\x9d\x93 ?\n\xad\x0f\xb2Y`\xf6\xf9$Y}^\x9b=(\x01\x94N\"\x96\xf2C\xac\xc6\xb0\xb5\xabBF\xa0\x98\xe4[\x0fP\xfb\xd2r\xee,\x04\x8d\xc4pRW\x0b\x1b\xea_\xa9\xd5)\xb6\xe6iqp\xe2h\"\xd0\xce\xe5\x08\x05\x9a-\x97$\x15\x12|\x89\x82\xf3\xfd,\xe1\xff\xc3\xe5\xb6\xdc\x17\xed'(\x17\xf4j\xc5\x86L!c\x92\xb1\x15\xec\x81r\xc6\x8a\xc20\x92\xbc\x02f8\xc1)b\x02ynh\x15\x85\xa1Z\xfb\xe3\xf8\xc8%l\x1f\xef\xf5\x15\xe2\x9b\x1f\x0e\x9f\xc1)\xc7\x9f\xf3\x85|*\xa8Z\x1d\xfc\xe5w\xdfi\xc4\xe4\x1bB`J\x08<\x87\xd1h\xf4\x1f\xca\xcf82(Y\xa9?@\xc9j\xc4\xd1x\x93\x92\xc5\xdd)!\xf7\xd4\x9f\x8eFj\xf9\x17M\xe1.\xef\xea\x93\x98\xc8\x19\xb9\xfb\x17\xde\xd7=\xf8M\xc3\xc3u\xfd\xfd\xae\xa7\xdd\x91\x81v\x7fC\x17h0\xe2\xc1s\xa1\x1b\xf2Q\x06\xa0PD\xef\xbe!d\x14\xc4\x88R\x03\x81$\x8a\xbc\x91\x9cc\xa5\xa1\x1a\x07\x05\xe5J\xd2=0\x90\xeet\xc5\xe6$\xd1\x10Ob\xf5\x86\x90\xbb\xa3\xd1H-\x0dJ\xc2\xdd\xd5~#6\x9f kW\xaa\xf2N\xdeJ\xa2\xbez\xfd\xf1\xe5\x87\xb7\xa7g\xef?\xdc\xd3\xb9\xca\xd6\x1bU?\xb0\x1cZO\xcec\x039\xbf'\x9azq\x9c\x94\xcf\x9e\xc3_\x96\x93\xd1\x1bB~\x1b\x8dF\xbf\xab?F\xc9j\x8f\xab\xa1\xbc\xc5R*Q\xefPJ\xe7(\xe6D\xd6ODG\xc2&\x16\x1a\x14\xa2i\x03\x81O\xc9b\x8d\x82@P\x1c\x10\xf1\xd5\xffy\x0eI\x14k7\xb8\x1e/\xc5N\xe6\xc6\xad\xa0s\xc1\x8b\x0bC\x03&\xab\xb5\xdaUH\x0f\xf9\x0eg\xbb\xd6\x9b{\xc9\xb8Z\xd2>\xd4n\x8bJ\xb5\xcf\xed\xf7\x91\xf8\x81\xab\xab\xbb\x80*\xd2\x8eK\xc2\xbc\x82`k\x87r\x87\xb4\x0fV\x8a\x96$^\x15v\xe5\x86\xb3\xa0T\x93\x01M\x19n\xf3\x12J\x10~\x8c\xdd\xfd\xdd\xf6\xa1r\x99X\xa0,\xac]\xc0\xf9\x8e\xde\x99\x122\x9a\xa0TL\xf6j\x7f5\xfa\xba#\xa9(l\xaf\xd6\xfe\xd4\xa6\xa8@u\x87\xf7\xc1\xc5a\xeb'\x7f\xfb\xf8\xfe\xe7\xf6_\x9e?\x7f\xfe\\\xbd\x07x\xbb\xb5\xcfE\xea\x91\x84\xb3\x83\\ \x92v]Fq\xe1a\x9de1RT\xb7\xde\xec\x867 \xf1Zm\xd9\x03\xbc\x98\xe00\\+0{R\x1do\xeb\x0e)\xbc7\x15\x95b*\x0c\xd9\xcf\xff\xcdI\xf79w&\xd4\xbc\xd5\xc5\xe2\xb4\x1f\x90\x9c\xfd<\xd3\x18 (8\xe7#6\xec\xd90z\x88\x97\xda\xd1\xd5y\x81\xda\x9c@\xe3\x9e7m\x86\xfc\x1b\xc4\xb4\xd9\x98\x16\xbb^|&s\xd7\x16$\xccb\xac\x0f\xcf[\xbc\xd6\xd1i\xd0\xbc_\xe5\xf7T\x9f\x98\xe86f0\xc7\xc19\xcd\xda\xf5\xfc\xf2\xabw\x12\xb3\xa8bDr%\xf8\x17\x89\xe9\xdb\xb6\xaa\x9c5U\xa7\xf2\xe1F'\xfc?*\xdaT\x99\xc3Tz\xf4\x95\xbd\xb6\xe5CmtS\xa6B}\xc90e\xf5a\xcb\xdc\xa7\x86*W\x80O\x82\xca\xc1'A\xf9$\xa85\xf8$(\x9f\x04\xb5\x06\x9f\x04\xc5|\x12T;\xf8$\xa8\x02|\x12\x94O\x82\xf2IP\x96Z\x92O\x82*\xc1'AU\xc1'A\xf9$\xa8\x16\xf0IP\xad\xdf\xf8$(\x9f\x04\xa5\x00\x9f\x04\xe5\x93\xa0|\x12\x94O\x82\xaa\xc0\x10 )> J\x80O\x82\xfa\xa3$AuO@\xa2\xab$\x88\x92\xbc \x89\"\xfd\xe8\xa3\xfc\xa6\xcc>\x12\x19GyCU\xd2Q\xde&\xff\xf5\xd6\xe6\x1c\xd5\xa6_\x05\xd9\xd7\x84\x90\x18\xa3\xba#\xc8\x18\xda\xcb\xa7nU\xe4`\x1d\xda\xab\x13\xac\x00\x1f\xd9\xcb\xc1G\xf6|do\x0d>\xb2\xe7#{k\xf0\x91=\xe6#{\xed\xe0#{\x05\xf8\xc8\x9e\x8f\xec\xf9\xc8\x9e\xa5\x96\xe4#{%\xf8\xc8^\x15|d\xcfG\xf6Z\xc0G\xf6Z\xbf\xf1\x91=\x1f\xd9S\x80\x8f\xec\xf9\xc8\x9e\x8f\xec\xf9\xc8^\x05\x86\x88\xb2\xf8\xc8\x9e\x00\x1f\xd9\xf3\x91\xbdu\xa9n\xcc\xe8~\x8c\x18\xa6L\x1b\xe6\xfbI|R\xbe]\xf4\x11\xb32\xe2'[\xaf\xab\x7f\xdf\xa7\x98\xa9\"\x7f\x9b\xdd\xe4\x1f\xde\xda \xa0|\x9aA\xf5\xb0\x8b\xd6\xf3\xa0{\x87C\xf7\x12\x1c\xbb\x81(\x93\xe1\xa2\xb4\xd1\xc3bxV\xcd\x80\x1dX`\x08\x16\xb10\xb0AU\x82\x8dO\xa5\x00\xd7\xb8\x98\xb6\xb3v\xe7\x88\xc6V\x18:>\x06\xe6\x18\x19t\x88\x93\xe9'\x80\xd8\xdc:V\x06C\xc5\xcb\xa0c\xccL\xdb!'\xaeu\xdc\x0c\xfa\xc7\xce\xc09~\xa6\xed*\xf7\xeb;\xc5\xd0`\xe88\x1a8\xc6\xd2\xc05\x9e\xa6\xdf\xd9e\xac\xcd6\xa6\x06C\xc7\xd5\xc0.\xb6\x06C\xc6\xd7\xa0w\x8c\x0d\xba\xc5\xd9`\xa8X\x1bt\x8a\xb7\xe9\x8f\x03\xa284\xc7\xdc`;q7\xd8b\xec\x0d\xb6\x13\x7f\x03\xc7\x18\x1ct\x8b\xc3\x99X\xb0],\x0e\x86\x8d\xc7\x81CL\x0e\xdc\xe3r\xd0!6g\xc12\xefY\xc4\xe7`\x88\x18\x1d\x98\xe2t`\xaf\x9eY\xc4\xeb\xc0Q\x8bs\x8e\xdbi{\x131=\x8b\xd8\x1d8`9`\x0c\x0f\x9c\xe2x0t,\x0f:\xc6\xf3\xf4\xfb\x8a\x9acz\xd0=\xae\xa7\xec\x8f\x8fh\x8a\xed\xc1`\xf1=\xb0\x0fS\x81M\x9c\x0f\xdcb}`r\xcew\x8c\xf9\x81E\xbf\x1a\xff\xdf@\xf1?\xe8D\\\xfb8 X\xcc\xb2C<\x10\xba\xc6\x04AO\xd5\xe1b\x83`\x1f\x1f\x04\xcb\x18!X\xc7 \xc1\x8e\xea\xee\xf1Bp\x8a\x19\x826n\x08C\xc5\x0e\xc15~\x08=c\x88`A^\x87X\"l#\x9e\x0868jN\xc2p\xb1E\xb0\x89/B\x8f\x18\xa3\xb2C\xfe\xa1.\xce\x08C\xc7\x1a\xc1\x18o\x84\xae1Geo\xd2F\xd5\x9b\xeb\x16\xb1G\xd0\x86H@\x1b\x83\x84NqHeW\xda\xf8$t\x8dQ*{\x93z\xa0\xc6k6\\\xac\x12\xac\xe2\x95\xd0!f nqK\xe8\x12\xbb\x04\xe7\xf8%\x18\xa4\xad!\xa6\x04\x0eq%\xdbX&t\x89g\x82kL\x13\xf4\x13\xef\x12\xdbTvV\x89\x1c\xda\x1e\x19\xbb\x18\xa7\xf6@$3}\x9c\x13\x86\x8du\x82)\xde \xfa\x98\xa7\xb2M\xd7X(\x0c\xb8w\x1db\xa2\xe0\x14\x17\x85Jl\xb4\x0e\x17\x84E\xc9l\xbc$\x97\xeaG\xfe-<\x13\xe6\x97\xf5\x97)Y\x12\x8a\xd3\xf12\x8dH\x1a1CD\xac\xd7h\xf5\xea\xa4E@\xb1\xb56ikp\xb6\x80%\x9aE\x89X\x8bMdkc\xac?\x94~n,|\x14\x95\xbf\x16\xc3\xb5\xc5c%0] \xd0P/\x19_1u\x8c\xd1HO\xa3G)/\x13\xfb\x7fU\xfe\x99b\xfc\x82\xc0\xfc\x9f\xb9;\x16Q*\xfd\xcf\xa7h\x86?\xc8*\xad#\xf9\xbb\xa2\xb3/\x19NW\xa2\x1b\xde-\xa7!\x86\x05\xa1\x0c\xb0pj\nohKSF\x18RD?\xad \xa0)\xe8nz\xf4^\x0c/\xe6/\xfe\x91d\x8b\x89\xf4\x96\x15W[*\xf7(T\xfe\x94*\x89\x02\x92%l,:S\xb1\x9eKD\x81b\xb6\x07\x11\xa3E\x14\x81B\x96\xc8\x0d\x18JG\xe9eD\xebkj\xbc\x87\xbb\x99\x88`u%\xb7\xd1QyA\xb7\xda\x91\x7f~\xbc\xf9\xab\xbf\x9f\xeb\xef\xe7\xae\xc1\xdf\xcf\xf5\xf7s\xd70h^\x81KN\x81S>\x81\xbf\x9f\xdb7w\xa0C\xde\xc0 9\x03\xee\xf9\x02\xfe~n\x9f\xfc\x00\x97\xdc\x80\x0ey\x01\xfe~\xae\xbf\x9f\xeb\xef\xe7\xda\xc6\xf5\x07\x8d\xe9w\x89\xe7\xfb\xfb\xb9\xaa\xcf\x8cq{\x87\x98\xbd\xcd\xedS\x97X\xbd\xbf\x9f\xeb\xef\xe7\xda\xc4\xdd\xfd\xfd\\\x01}b\xeb\xfe~n[O\xc6\xf8y\xd7\xd8\xb9R6\xf8\xfb\xb9\x9b\xe0\xef\xe7v\x88y\x9b\xe3\xdd\xae\xb1n\x878\xb7s\x8c\xdb-\xbe\xed\xef\xe7\xba\xc5\xb0\xfd\xfd\xdc\x12\xfe\x94\xf7su\xcf\x8f\xaf\xa3\xa6\xa3s\\\x95\x825c\xb2\x11\x8c\xcc\xa3\x8f(g\xa1)fY\x9a\x08\xa7R\x1eV\xcb\x03Ee\xa8R\xb8\x82f\x0d\x9f\x89\x88=\xf2c\xaf\x0f?\x8e\xe0=\x17x$\x11\xb6\"\x99N)f\xdc\xfc\xaa\xa3\x0b\x15Wv#\xb6\x1c%\xcf\xe4X\x95\xbf\xad_T\x9f\xa2\xb8\x16\xb4S8 Z\x1d\x03-D\x94\xf8\xa9\xe8\xd80\xca\xf3\xc9\x08R&\xd9\x02\xa7QP\xfcM\x9c\xb6\x00%|>\xd2+2\xc7IA\xf8,)\x1dQ\x0d\xf5\xf3\xad\xe8-\xc6\x94\xaeI(]7\x19\xe5\xa4>\xc7\x8e\xf4\xacw\xbfe\xe26B\xc2-\xe4\x8d\xa3EdK]\xf1m\x99\x86\xa0\x88\x14K'eu\x07\xe7A\xd7,n\x04/\xa5K\xa2\xfa\xa7\xb7S\x88\xf1\x94\xe5\xde\xaf\x88IvX(\x8d\xc2\xbf*\x0f\x88\x1c\x84\xd3y\xb2\x02\x8c\x829\xa0\xe5\xf2\x06\xa9X\x8dw\xaf\xdb\xebhYi\xc1)*v(\x01\x96f\x18\xf8?\xa2$\x8c\x02\xc4p\x19i\xc9)(>\xcc7R\xb5\xbb( \xe2,l\xa8\x84H\x8eR\x86\xba\x1a+&\x02\xa7\x15\x0f,g\xdd\x95\x9c\x8f\x06s\xf9\xf4\x966V\xab1\x05\xa1E\xa7\x98\xe6!nq\xbc\xd6\xe7\x91\x1f\xb9Q~\x9a\xa2YB\xd2\x86\xff\xba8\x8d\xf5!$e\xfa.l\xbd\xa0\xb7\xba\xb8\xc2\xae[u\x85\xdfd\xf1\x80\xdf\xf3Z\x06\x8a\x02\x0b\xad\x19\x04E\x89\x85Z\xfa\x0e \x06\x08f\xd1\x05N@v\xad\xaa\xb6\xd0\xd6\xe7\x9d\x82\x16\xbe\xdeB\x01\xec\x06\xb2\x06|\xbd\x05\x0d\xb8\xe69h;kwvk|?C\xe7;\x809\xe7\x01:\xe4=\xe8'\xe0\xeb-t\xcd\x85\x00\xe7|\x08mW\xbe\xde\x82\xaf\xb7\xd05g\x02\xba\xe5M\xc0P\xb9\x13\xd0)\x7fB\x7f\x1c|\xbd\x05\xb7|\np\xcc\xa9\x80ny\x15&\x16l\x97[\x01\xc3\xe6W\x80C\x8e\x05\xb8\xe7Y@\x87\\\x0b\x0b\x96\xe9\xeb-Hp\xce\xc3\xd0\xf6\xe6\xeb-\xf8z\x0b\x0d\x18&_\x03\xec\xd3\x0e\xc0&o\x03\xdcr7\xc0\x14l\xed\x98\xc3\x01\x16\xfd\xfaz\x0b\x1a\xe8\x94\xe3\x01\xbe\xdeB\x0e\x9d\xf2?\xc0)\x07\x04|\xbd\x05\x9b\xdc\x10\xd8F~\x08\xd8\xe0\xe8\xeb-\x0c\x9b;\x02\xc6\xfc\x11\xe8\x9aC\xa2\xec\xcd\xd7[\xb0\xcb9Q\xf6\xe6\xeb-X\xe6\xa2\x80s>\n\xf8z\x0b\xad\xd0%WE\xd9\x99\xaf\xb7P\x80\xaf\xb7\xd0\x02\xbe\xde\x82\xaf\xb7\xd0\xfa\x81\xd1\xa3\xe4\xeb-\xfc\x89\xea-\xb4\xa5\"\xf8\x8a\x0bk\xd0\xec&_q\xa1\xa5\xb9\xaf\xb8\xe0\x90\x81\xe0+.\xf8\x8a\x0bk\x184\xb3\xc0%\xab\xc0)\xa3\xc0W\\\xe8\x9b=\xd0!s`\x90\xac\x01\xf7\x8c\x01_q\xa1O\x86\x80Kv@\x87\xcc\x00_q\xc1W\\\xf0\x15\x17l#\xfb\x83F\xf5\xbbD\xf4}\xc5\x05\xd5g\xc6\xc8\xbdC\xd4\xde\xa6\x9e\x80K\xb4\xdeW\\\xf0\x15\x17l\"\xef\xbe\xe2\x82\x80>\xd1u_q\xa1\xad'c\x04\xbdk\xf4\\)\x1b|\xc5\x85M\xf0\x15\x17:D\xbd\xcd\x11o\xd7h\xb7C\xa4\xdb9\xca\xed\x16\xe1\xf6\x15\x17\xdc\xa2\xd8\xbe\xe2B \xbe\xe2B\x0e\xc5=\xecy\xf5\xfe+\xe4w\x84\x1b\xae\xec\xf5\x15a\x96f\x0eW\xbf\x8d7\xbf}\x8d\x070S\xd1\xd7x\xd8\"q\xcd\xd5 |\x8d\x87!\xa8\xe8k<\xfc\x11j<\x14%\x1e\xc2\x88o\x85I\xc6\xc9P\xd6w\x08\xc8b\x91%\x11[\x8d\x97\x84\xe4a\xe8\xb6\xb2\x0e/\x8b\xefN \x89\xcbb\x0e2\xd6\x96\xff\x02\xbc\x07\x08H\x94\xd0\xd6*\x0e\xb5.\xee\x14s\xbc\xa5\xb5\x1b\xd6\xd4\xa8\x02\xbb\x81\x14\x81\x10'd\xd1\xd99\x8e\x16|;wln\xe3\x9a~\x85\x83\x97$\xaadu\x01#\xe78\xc9=\xcb\x12\xfb\xe2\xecq\xdd\x96\xff)\x88\x16\xa8=M[\xa2\xab\xf2\xb1\xfe\xfc\xfe\xec\xf53a%\xca\xefrs+\x12\x1e\xf1W8\xc8\x15\xd12\nQ\xd5F[;\x94\xc6y\xfb`4\x9a%\x88e)\xa6\xe5I\xe4lyFfD\xa8~\x9b\x16\\=\xe1\x8d\x1f\x86\x82(\xf53\xb2K\xeb\xa7\xa4\xa5\xf5\x06\xb1E\xb2P\xed\x04uO9\xaa\x1f\xc4\xc6'>\xef(\x07\x9fw\xa4\xe3+[\x08\xd95%\xd8\xdfsy\xb8\xab\x15`!\x8e\xf1LT\xc3\xd9\xff\xad\xfc\xf78\xafI\xf3\xfb~\x8a/Q\x1aRM\xc1\xa2\x8a\xcd\xf2J\xb6\x8fHr\xc6\xc5\xff\x07\xd9\xb6&\xed\xa4^\x90\xf7\n(\x08\xd2L\xf2\x05$\x14\xb6\xb2\xab2k\xb6U\x14\xb6\x0f\x94\x7fykeb>\xeb\xdb\xb1\x83K\x02\x8f\xfb\xd6\x1f\x92\xd3\xd27o\x9f\x9b\x04\xe5\x0c%\x18\xe6)\xc14[ ZU@\x82q\xb6\x12\xf4j\x81\x04\xab\xaelT\x04 \xce\x8a\x82\x96\x10B\x850\xa8\x0b\x12:)\x0d\x9a\xfer\xe7\x96Nu\x90\xe0\xae@\xe8\xbd)\x05\xac\x99\xc7\xab\x82\xdfI\x06\xb2\xf6\xf3I^\xb5\xdeT\xad\xfd\x90\xa9 {\xde\xc5.-\xfe\xcd\x17@\x9e \x83\x8aSp\xc1rE\xe38\xd7DZ\xb8c9P\xb3SE^\xfaM\xf0\x14\xafj\x97\xd0\xe9\xd4\xdc\x90\xaa-erA\x15\x91\x97\x92-\xc4\xf6\xaeoH\x8d\xbe\xbdq\xd4\x84\xf2\xd1.\xa6\xbb+\xde\n\xfd\xc2\xab\xdc9x\x95\xfb\x9aUn]\x8caC\x99Vm\xc5\x8d\x0fkG\xb1\xfc\xb5\xa8\x13 \x8c\xe4W\x98\xa6ua\xd03\x86\xb1M\xf3a\xff\xb7\x0duSW\x03u}\xce\x1dM\x88\xb5\x046\x98\x0d\xdeb\xd8\xfc\xd9t\x00\xbdt/\xe1[\x92\xeeM-\xd3\xa4aV\x0eOKo&A?\xa0\x8c\xf7\xe2\xbd\x01^\xbc{\xf1\xdeY\xbc\xaf1\xdf\x10\xc5*\xcc7>\xaca^\xfe\xbam\xcc\xb7\xa2\x98\xac\x8b\x80\x9b\xf5\x10\x92\x967\x8c\xeb\x9a\xc8\xba\x93\x863@\xa7}T{\xbbSP\xe3\x96\xea\x1f[*\x95\xae8\x87f)_!x\xebV\xa4\xd5E\xe0\xb2\xa7\x90i\xad\xa7~\xdat\xa6\xd8K\xba\xea\"\xf6\x96u\xb5\xfd\xe5\xa5]\x0e^\xdayiw\xbbd\x06\xb7$\xc2\x14]\x16\x7f\xb1\x91\x1c\xff\xc8\xdb\x9c\xe4\xf3-\xc4G\xd1WI\x08\x17\x01\xd2\xe8\xf4NA\x9f[*E\x9ats:\xb6\x0d\x9c\x9b}u\xdc^n\xbc\xbeA\xef\x01\x18~s[x\xae\x9f\x83\xe7\xfa\x9e\xeb\x0f\xce\xf5\xb5L_\x10\x80\xaaY\xf9\xa9\xf8\xbdd\xdc\xf2\xf3\xf2.L\xa5GX\x900\x8bq;\xeb\xae|';\xbcSL\xef\x962\xed*Y\xaaPO\xd2\x92\xc4\xa8.\xf6z?\x154\xaa\x93e\x0d\xda\xc3\xa4?J\xeb\xacK\x86\xae\xd4gMs\x1a&\x88\xe2qY1N\x97\xc2`\xea\x88$\x19\x1d\xa4\xa7\x9ah\x1b\xe3\x04Mb\xac\xed\xa9\x9e\xc0*\xc1\"\x0bN\xee?+!\x96\x8b\xad\xfc\x08|8}\xd9\xe8\xcf\x8b,/\xb2\xae_duS\xee\xd7N\x82\xb6h\x94H\xe4\x8e(\x8dH\xa2Q\xebK;\xfde\xf9u)\x18P\x10d\x8b,\x16\xf5\x10\xd6\x9d\x89\x93\x84\x0c\xe9l-\xdd\xe6\x9f\xddZ\xf1\xb0\x9e\xa1ADTHQ\x15\x13\xf2\xcfQ^\xc8h\xedKLq\x80\xa3\x0b\xdc\x92:\xd3S\\\xa8\x90\x05\xc3\xc1\x02S\x86\x9a\xe1\x80\x81\x11; \xc6\xdc4\x8b\xb3b\x8a\xb2\x81]7f?\x9c\x04\xe7\x88\x9bf\xf2\xb6\xf9h\x9d\"o\xca\xde,s\xd1\xdc\"p\xaab\xa6\x82M\xb5\x1cu+I\xdc\xd6\xd7~\x1b;Z[\x92e\x13/\x95\x1b\xbfz\xa9\xbc\x05\xa9\xac3$\xff\x1c!'\x83\x86A2F\x19J\xc2(\x99\x8d\xcdi\xf5\xe5\xd9~\xbfn\xd6\xcc\x86)\xc2\xf8\xc2w\xb8A\x1c\xbd\xaa\xb1\xd9\xed\x9d\x82N\xb7T\xe50$\xc3t\xd2\x0c\x94}\x82W\x0b\x9a\xe0\xd5\x82\x06\xb8\xa9\x05`EB\xdd\xb1\xaf\xa4\xa7WxIK'w\xb3\xe4~\xe1MH\xee\x15\x9b\xbcm\"\x0d\xeb\x04\"\xa1\x07$4\xba\xc0\xf2\xe21\n\xce\xf7d\xcdN\nT\x90\x0f(J\xa2\xd6\xd7\x0f\x839\x0e\xce\xddo\xe5i\xa6lT\x8d\x1a\xfd\xb5\xd4\x9cmhJ-d\xf5\xbe\xf7\x1c\xbc\xca\xe4U\xa6\xdb\xa52\xd1\x18\xd19\xb6R\x93>\xcaOK\xddH4\x05|!\xd9\xe5\xd4\xde\x07\x93wt\xa7 \xc1-\xd5\x86r\xd2\xdc\x8e\xc3\xb5^\xba%N#b\xb8\x0chuL4OeLE\xb5t\x953\xc78\x8aY\x08Cc7\xbc\xe6\xbb\xa8*~\xab\"\xb3\xb2\xd1\x14U\x11\xf3\x17)\"*\xf4\x8f(\x10\x15L\xd8<\xaf\x81B\x19I\xc5\x8b&\x8a\xd6\xa2\xca\x7fDEy\xe9\xa2nv\x1c\x08G#\xa0%_\x994\x12\xff^\x14U=(\x13E\xa0[{\x13\xaaX\xab* \x95\x81u\x12pQ\xcb\x1d\xa5\xb8\x0cM$y}=\x94\xcfz\xae\xa8\x8eN\x02Q=\xdat\x01.\xdf\xc3\xf5\xabG\xf9\xdf\xec\xdc\x82}\xde\xcf\x91\xd1\xaaJa\x93\x9a\x8a1\xa8\x03\xd2\xbf\x9f\xe3\xdf\xcf\xe9\xf4~\x8e\xc1\x89\x98\xcb*\xa3\x9al\xf6 \x16\xe2\xd3+\xc39xe\xd8+\xc3\x9d\x95\xe15\xe6\x94\xa1T\xbc\x7f\xb7QrP\xa7\x864Z\xd5&Q<\x86R~\x94W3\\\xcf\xa5y\xd8s\x91\xda\x9c\x9fk\xbd\xac\x8d\x055\x14B\xc3\xd2\xd59\xfc\xc4e\xc7\xb7u\xda\xbe\xd2\xa3\x1b\x19}\xa5\xc7-\x12\xd7\xbcG}\xa5\xc7!\xa8\xe8+=~\xbb\x95\x1e\x9bY\xa2\xf8\"\nq\x12\xe0\xd2IU\xfcA\xed\x85:\x89\xe3\xd7\xf9G\xeb|\xa08\x86\xa2e\xab\xc7\xa9\xd2\xe8N1\x8f[\xeal\xaaS\xa0\n\xdf\xa4\xf6j\xe7\x03\x02\xff\xe8\xa3\x7f\xf4Q\xf9\xa5\x7f\xf4Q\x80\x7f\xf4q\x13\xfc\xa3\x8f\xfe\xd1G\x15\xf8G\x1f\xfd\xa3\x8f\x02\xfc\xa3\x8f\xea=\xed\x1f}\x94\xe0\x1f}\xf4\x8f>\xfaG\x1f\x05\xf8G\x1f\x05\xf8G\x1f\x05\xf8G\x1f%\xf8G\x1f\xfd\xa3\x8f\xfe\xd1G\xff\xe8c\x13l\x1f\xe0\xf3\x8f>\n\xf0\x8f>\xfeQ\x1e}\\C\xcdB,\xe2\x17yX\xb2\x1e\x9c\xd9\xb0\xaf}R\xa1\x00\x9fT\xf8\x07M*l\xbf\x86S Gv\xcf'\xac\x06B?\x9c\xbelN\xc2g\x16\xfa\xccB\xa3c\xd2\xc6\xb7\x07>6\xebc\xb3\xca/}lV\x80\x8f\xcdn\x82\x8f\xcd\xfa\xd8\xac\n|l\xd6\xc7f\x05\xf8\xd8\xac\x8f\xcd\xfa\xd8\xac\x8f\xcdJ\xf0\xb1Y\x1f\x9b\xf5\xb1Y\x1f\x9bU\x81\x8f\xcd\xfa\xd8\xac\x8f\xcd\xfa\xd8l\x05\x86\x88\x93\xf9\xd8\xac\x00\x1f\x9b\xfd\xa3\xc4fu\x17\xfc\xfd\xa5i\xb7\x1b\xa9\xfe\xd2\xf4\x16\x89k\xbe\xee\xeb/M\x0fAE\x7fi\xfa\xdb\xbf4\xbdk\xbc5\xbd\xff[\xf1\xaf\xf1\x1c\xd1\xb9\xee\xdd\xef\x8d;\xd4e\xde\x8e\x08B\x00I\xd6\x7f\xe1}\xb5^\xab\xfe\xf6\xefT\xebS\x97\xe4\xb6\x16\xf9\"8\xdc\xb8a\xbe\x06%J`\x0c\xe33m\x10\xdf\xe8\xbf\xb6q\x00\x0f\x1e\xbe\xb7\x0b\xdew \xdd\xebC\xf4\x9d\x02\xf4b\x08E\x87\xc6\xf0\xfc\x00\xc1\xf9\x8e\xa1ye@\xd3.0\xdf+,\xdf)(\x0f(n\x7f\xde\x1dlC\xf2]\x02\xf2\xba0\x99U8~\xe0`\xbcU(~\xc0@\xbc1\x0c?P\x10\xbeO\x08\xde9\x00?@\xf8}\xe0\xe0\xbb!\xf4>x\xe0};a\xf7\xc1\x83\xee\xf6!\xf7n\x01w\x0d\xd1M\xe1\xf6\xc1\x82\xedv\xa1\xf6\x16[_\xcd_\x07\x0e\xb3\x9b\x82\xec=C\xec\x9a\x00\xbbQ=1\x06\xd7\xed\xf4\x97a\x03\xeb\xba\xb0\xbaE\xf2\xaeS\xe6n\x9e\xab\xdbP\x94\x0b\xf0\x15@s\xf0y\xba>Ow\x0d>O\xd7\xe7\xe9\xae\xa1\x8bY\xa0\xec\xcc\xe7\xe9n\xc2@&B?#\xa1\x83\x990\x88\xa10\xb8\xa9`4\x16\xb6`.l\xcb`\xd8\x82\xc9\xe0b4t5\x1b\xb4<\xdcd8\x0ch:\xd8\x1a\x0f\x8e\xe6\xc3\xe0\x06\x84\xd9\x84\xe8mD\xf8<]#f>O\xb7 >O\xd7\xe7\xe96\xc1\x8dx>O\xb7\x06>O\x17|\x9e\xae\xcf\xd3\xf5y\xbakP\x9b\xa2>O\xb7\xf6w\x9f\xa7\xeb\xf3t%\xf8<]\xe6\xf3t\xff?\xf6\xfe\xaeGn\x1c\xdb\xf7\x84\xef\xfd)\x16\xfay\x00\xef\x06\xd2\xe9\xd9\x18\xcc\x8d\x813\x80\x9dvU\xe7L\xb5\xed\xe3\xb4\xab\xb1\xcfM@\x19\xc1\x8cTg\x84\x14-1\xf2\xe5\xd4\xee\xef>\xe0\x9bD)\xf8\xb2\xc8`\xb8\xb2\xcak]t\x973\xa4%\x92\xa2(\x8a\xff\xdfZt\xba,\xca\xe9NP.\xcb\x93\x13Y\x92\x07M2#\xc9?\xe8\xd10\xcc0\x1d\xbd\x01\x97\xf3\xe3te\xe5\x1e\x94\xfby\xc1Wl\xd7\xf65\xc7\xb5\xd5\xf4`Dc\xe9\x13\x8a\xb6\xd6\xb6n\x16\xdao\xa8\xad\xdc\x82%\x84DK\x88\x15LYL\xbc\x04\xd9lM\xbb\x0d}\x95Eo\xa80\xb5i\xee\x91n0\x0bi\xc2.\xdazL\x14W\xa9\xadx\xf5B\x98\xaa\x8e\x81\x88\xc5\xab\xb8jt\xe1Bk\xae\x1f?}\xfd\xf0F\xce^\xf5\xee\xbfj\x1aX\xcb\x95\xba\xcb\x86\xeb\x17\xe4\xb0:\xda\x07E\x00\xfd\xf6T\x1f\x0e\xfe\x8b\xf6\xf5\xba\xa9\xf8\xbec\xfd0$\x8bO\xa5u\xbbn\xe5\xab\xc9=\xc3\x9c4\xd2\xdf\xeb\xa6\xde\xee\xb7\xa6\xf7\xca\xef\x85J\xde\xf6\xb6\xaf6\xa2_\xb3F|\x8e\x04\x1f,a\xdb\xeaq1<3\xc5\x9en?\xf3Q=\xcar\xabK\xc9b\xbf\x15M&f \xe2\xc1\x1c\x1fH\x10\xb7q\xa8\x91\xef\xab\xf4\xb2\xa9y]m\xf4:4\xcc)\x83\xc1\xb6m\xc3o\x0f\xd6\xb0y\xb5\xd9<\xe1\xc6\x15\xfbP\xc4\xa8\"\x0f/:\xa6\xfck\xdfv{\xcf\xf3\x1a\xbd9\xd1ev\xe4\xdd\xd3\xbdn\xc7\xba\xa5\x98\x93\xae\xd5r\xb2D\xf1{^\xdd1k\x8f\xed\xfb\x96+^\xc6\xa7\x0d\xea\xc8\x02\xa9Z\xf9n\xdb\xb2m\xfaz\xc5\xc4\x03\"\x17\xf5]\xdd\x80\xdfv\xac\x17\xfd\xe7\x99\xb4\x8d\xe8\xb1\x9d\xf9j\xfd/\xd6\xcb\x96\xe8U\x98\x83\xf5|\xee\xaa\xde\xa3\xa9\x00\xbc\xd7\xeb \xbaW\xff\x1f\xe7\xff\x97\x13\xe1b\xbc]<\xb3\xda\xabo\xfc\xf6\x06~e\xba\x0f\xc8g\xfa\xab\xec\"\xea\x9fr\xb2\x16\x90\xf3\xedF\xf2\xf7\x0cQy\xb6:\x9f7\xd5\x7f\xbe\xfe?\x93\xd1/5aL\x01\xbf\xf4L\xf5\xcb\xe7\x8b\x99?\xc2\xbe\x08\xfb*6\xdb!\xec\x8b\xb0/\xb7\x11\xf6%\x8d\xb0\xafC#\xec\x8b\xb0/\x9f\x11\xf6E\xd8\x974\xc2\xbe\x08\xfb\"\xec\x8b\xb0/e\x84}\x11\xf6E\xd8\x17a_>#\xec\x8b\xb0/\xc2\xbe\x08\xfb\xb2\xac\x04\x82C\xd8\x974\xc2\xbe~\x04\xec\xcbB\xa0,?\xa1/I\xeb\x8cAoV\xb7\xcdR\x9cy\xab\xf7}\xbbi\xbb3\x93fPe\x04\x9c8\xfb\x8b\xe2\x00\xfer6m\xde\xbfH\x99Z\xfc >\xb4\xfe\xa2\x95\xf7\xbf\x14\xc4\xc8|\xbc\x98\x13\x17\xd3\xc2\x9f>\xc1\x89\x88\x99C\xa6\x94\xd8\xf0\xd7!\xcb\xd9\xba\xbeg\x0d\xf4\xbc\xe2\xfb\xde \x8a\x0d\x9e^\x98J=SPl\xd6*\xb6\xf1\xdfA\xff2\xc5Y\xd4\x1e\xc59i\xfd'\xb0s\xa0T\x04\xfcdQ\xa4\x1a\x80\xa8\n \xe4<\xc0\xd5\x07\x90\xcbB\xc6R\xa5\xbd\xa03\xf7\xfaN\xe0s\xa7\xb4\xc4\x07q\x99\x0f2\xa4\xbep\x05L\x128\x8c\xdc\x07\xa5$?\xc8\x94\xfd\x82\x0eE\xe3\xa2\xa5?8^\xfe\x83d 0\xe8jL\x14\x87\x97\x01\xa1\xb4\x14\x08\x89r \xa4J\x82\xe1\x9e=\xc8\x85XY\x10JK\x83\x80\x93\x07\xa1\xa4D\x08G\xcb\x84\x90'\x15B)\xb9\x10\xb2$\xc3\xf0\xe3`\xa6 \xb1\xe7\xe6$\xd2!\x9cP>\x84\xd3H\x88\x90(#B\x9e\x94\x18\x1b\x82qr\"\x94\x95\x14!AV\x84ti\x112\xe4E\xc4\x90\xf9W\x84\xc4\x08%dF\x88I\x8d\x80\x9f\x9e!$GH\x9c\xc5%K\x8fAoR\x96D\xc8\x8f\x90P\xca\x822$$I\x91PZ\x8e\x84LI2\xdc\xaf\xfa\xb8, \xf9\xd2\xa4\xd7\x9f\xb8bL\x9e\x84b\x12%\xe0\x956\xc0H\x95\x90&WBL_\xc8\x94-\x01\xe17\xb0\x84YH\xc2\x84\xac\xc6\xc5K\x99\x80\xa8e\x86\xa4 \xb9\xb2&\x84[\xb5\x9c\xbc x\x89\x13\x902'\xa0\xa5N\xc0\xb5z\xba\xe4 I\xb2'\x04\xa5O(%\x7fB\xaa\x04\nG\xca\xa0\x80h\xde\x049\x14N!\x89\x02\xa6\x8c\x81'\xa1\x9c<\n\x18\x89\x14\x8e\x90I\xbd\x0e\xc5\x81!\xa9\x14J\xcb\xa5\x10\x95L!W6\xf5zS\xdf\xa8\xe1\xcfu\x84|\nA\x95\x07\x822*dI\xa9^WA\x89\x15reV\xaf75\x0f\x0c\xac\x9a\x95\x93[\x01%\xb9B\x86\xec\ni\xd2+\xe4\xc8\xaf\x90,\xc1B\xe4m\x1b\x91\xc5 A\x1a\xc3\xca\xb1\x90#\xc9B\xaa,\x0b\xe1\x8a\xe7\xc8\xb3^g\x96\xf8\x89}dp2m\xf0\x81h\xd6a\xa9\x16\xca\xca\xb5\x10\x93l!,\xdbz\xcf\xc9\x95s\xa1`\xdfM\x90u!I\xda\x05K\xde\x9d\x9a\x92\x16\x8f\x90\xc0X\xe3\x8b\xe6\x05\xa9\x94~\xfe\xf2\xe9\xf3\xa7\xab\xb7\xbf,\xae\xbe\xbe\xfd\xfa\xedj\xf1\xed\xe3\xd5\xe7\x0f\x17\x97?]~x\x9fp\xd6\xfb\x0f\x9f?]]~]|\xfe\xf0\xe5\xf2S\xca\x89\xbf~\xfaz\xf9\xf1\xe7\xf4\xf3>\xbf\xbd\xbaJ*\xe1\x97\x0f\xff\xcf\x87\x8b\xafI\xa7\xfc\xf4\xf6\xf2\x17\xef &\xe42\xa3\x01\xb1\xab*F;\xbe\x92}@\xdeI\xf9\xed\xaf\x1eN\xbd\x16$\x7fc\x92P\xf6\x0f=cx\xbb\xbf\x0b\x06\xbbB\xb0\x9a\x938u3\x83\x94\x97\xdc\xf5*b\xdbR\xc7QW\x9ev\xa7\xc3\x8bO\x7f\xb7R5\x0cA\xbd\xea\xa2\xb0\xdawf\xc7HM\x1d\xf8\xdb\xc8\x9b\xbb@[\xa4\xf3\x1e\x96r\xf23\xae\x90\x8a\x9f(YF\xf5\xa0\x1c\x16N\xfd=P*\xd1\xa1\xac i\xf1\x1e\xba\x0d\x08C\xbb\xaa\xefYZ\xd1\xcc#yX8\xf3K\xb9\xe2]3\xd6@\xc7\xfe)#\xa0\x93J\xa9F\x81\xc32\xaa\xbf\x97+\xe1MUo|E\xbb\xa9\x9bj\xb3P\xb9!\x948tb^\xe1\xe5\x13\xeb_\x1e\xbd\x1a^]\xf7b\xc6}\xb4\x9f\x97M{|a\x9av!\xbe \x16\xf7\x8c\xb7G:\xc3\x0e\xe0_\xc5\x0d\xfb\xa2\xf2O\x8c\xfd\xa4\xe7U\xb3\xaa\xba\x95J\xde\xa1S\xaa\xac\xdb{\xd65\xd5\xe1./\xa3\x85s\x94\xf4\xfb\xebm\xcd\x17\xbc\xde\x96\x08\x98ZU\x9c\xbd\x12\xbe\x9c\xc7\x99D.\xacY}\x9f\x0b\xca\xd4\x1f\xe1TGaLIY0\xdd\x11\xea\xd9\xc1==\x88\xa4G\xa8\xc6\x01T\xe2#\xa4+l\xa7MN\x7f\x14-|X:,\x9b\x1a \x9d\x1c)7=\x92\xceP\xd6\xf3\xaa\xfbNO\x9b\xbe\xe2wz\xd80\xdd\xc4LL'\x13\xbfe\xdb1}\xef\xb6\xe2\xcb\xb4\xd3o\xc0\xc8\xc8\xe6\x1b\xd5\xc6\xadz\x0f+<)\xa3\xb5\xa7\xef4_\x92\xb5\xd5/p+\xd3\xca\xe1}\x0d>\xf8\xe1\x07\xdelY\xee\xbe+\xd1{\x12U\x8by\xcd7\xec`C\xf5\xd1\x86-\xd3u:\x99a\xf7t=!\x13\xffP{\xac\xcb$\x8e\xe7\xeaw\x8f3\xc5\xf8\xf2\xe0\xf6\xea\x8eS\xe5\xe8|d\x03\x04\x08M\xdd\x04\xde!k\xd8\xa2\xd9\xb7g\xb7\x15\xe6\xed\xd3J\xed&\xb2w\xbb\xf6\x1c\xfeP\xc9\x9d\x9b\xcf\xa0\xe6\xbd!\x84z\xd87\xaa\x03\xae\x14\x04\xf1P\xf7\xd3{\x8a\xc9\x11d(\\T\x9a \x97\x87\xd7#\xbb\xfc\xe5\xf3\xc5\xbc\x02\x948\x88\x12\x07E_\x13\x98W\x00d\xd0\xc5\xaa\xefR\xe2 \x04I\\\x84\"\xce!\x88)qPAZ8\x85\x14N\xa2\x84)q\xd0\xb1Dp\x06\x0d\\\x84\x04N\xa7\x80)q\xd01\xd4o\n\xf1\x9bA\xfbR\xe2 J\x1cD\x89\x83\xb0\xb4nQR7\x87\xd2\xa5\xc4A\xbe\xc3\xa24n\x02\x89\x8bI\x8b\x93B\xe0R\xe2 J\x1c\x84\xa1i)q\x90\xb4c\x88YJ\x1c\xe4\xf2\x14\xa5bs\x89X\xef\xbb\x81\x12\x07\x1d\x1a%\x0e\xca Y\xe3\x14k*\xc1\x9a@\xaf&\x93\xabi\xd4*%\x0eJ#S)q\xd0`\x948H\xdb\x908\xc8\xe4[Q\xf0\x92\xe5k\xf259\xd3!ggM\x04\xd8\x91\x82\x92r\xacQ\xa5\xe6\xf3\xa4\xef\x8b\x1d\xfe~\xa8\xa1\x13\xdd\xfb\x9d\x90BdYN\x89\x0e:q\xc1\xef\x8f\x08\x86\xb0\xc0\xef\x8b\x02\x1e\xe2\x7fu\xf3F)\xf2\xd6\xdf\xc6\x9cX7\xd5\xa6\x8f$\xc5\x02'\xfe\x8dG\xbec\x0fK\xe4`?\xda\x8d\xc2\xb9\x91\x087\x02\xdbNB\xb5\xcd\x80x\xdf\xf2\xc9z\xd7d\x18\x94?N\xc6\x1f\xf5\x97j\xb5\xeaX\xdf\x1b}\xde\x1e\xf5FO\x05\xee\xab)\xa4\x1ehZoA\x87\x03f\x83\xa5\xda\xfaL\x17\x97\xf5p\xd3\xb5\xdb\xefR\xe2\x11\xcb9\xbfcO\xbeb\xcf^3\x9ao\xa9\xf4T\xbdc|\xdf5R\xbc\xd0\xe0\x86\x06\x12\x06\x18FJ\x0e\xeb\xd9\xda\xbc\xac\x81\x19\x15\xfd\x80\xcb9|\x12\x1fV*\xbb\x1d\xb477=\xe3\xd0v0-.X\x92i\xcfx\xe1\xd6\xf2,@;\x1aQ\x95\xcf\xd7\x8e\xb3\xc5_]\x19\xd9\x942\x98\xa0^\x9a\xbf\xc91I'\xf6S\xab\xef\xb7\xac1\x0d\xbfo\x06\xc1c\xf6\xfa\xbe\x94\xde6\xa2\xcf\x0fM\xa8$\x82}/\x9a\xfa\x8e%\xb6\xe7\xd4\xfd\x89\x1bw\x06\x1d9\x9awSokl\xeb\xcac\x0d\xaf\xe3c\x91\x94\x18f\xf7`\xf5\xcd)~\x9dx\xdb\xa9\xa5o\xfbO\x977\xb0a7\\\xab,5W\xd3n3\xf3\x91:\x9ez@\xd4ED;_?\x01\xab\x96\xb7P\xedv\xbfc+\xdaD\xd5x~\xa8-\xad3D\x8b\xca\x1e\xda\xca<\x90 \xfe\xa3nV\xf5\xb2\xe2lP\xf4\xcd.\x7f\xe2@\xdd\x91lwu\xb3\xdc\xecW\xb3\xa5\x87J]e@*fwL\x02:\x96\xd2'7\xd6\xb3\xa1\xc2\x89\xb3o\x97\xf3\x99\xed\xac\nr\xb5\xa6c\xbdF\xa9\xe4\xe35>\x8f\xe2\x91;\xd7OS\xbdn\xdan\xa6\x93\x9a\xa7qz \xd52\xc7\xde\xd8\xeb\xb6\xdd\xb0\x01\xe3M\xdby\xd9\xbc-^\xff\xb6\x1b\x136\x067_6\x93 \x93Xs7\xb2\xa4\x92\xa2\x1a\x13[\x99C/\xdf\x9b\x1a:3k\xbe0\xb5|\xe6\x895}xX\x16vj\xb5\xf6\xa9\xc0\xcb`b\xcc`\xd1!Z|@\x80j\x88:\x00R\xecT\x96\x85\xab\x05\xfc%\xa5\xc2,\x8a\xacE\xa1\xb5\xd2\xd8\x1a\x1e\\+\x84\xae\xe5\xc1k\x01w\x89\xc9/\x8f\x04\xd8J#l\x89\x10[a\x8c-\x0ddKD\xd9B}8#\xddeQ\x9c\x0d\x05\xb4\x15D\xda\x8e\x85\xda\xb2\xb0\xb6B`[\x0e\xda\x16p\x86Noy\x02\xbc\xedt\x80\xdbI\x10\xb74\xc8\xad8\xe6\x86\x05\xdd\x8a\xa2nx\xd8-\x19wK\x07\xde\xa2C!.\x91\xe5\xd1\xd0[4\x89%jB\x85@\xdfRf]\xc9\xf8[\xe8%\x88N]\x89+_A\x08.\x05\x83+\x0c\xc2\xe5\xa1p\xa1\x1e\x84JW\x99\x89\xc3y\xbcqT\xaa\xca2H\x1c\x9a\xebB`qI`\\,\xd3[\x0e\x1c\x17\xf3\xe9\x15\xc9\x0b!r\xe9\x8d\x89\xc7\xe4bu\xcb@\xe52a\xb9\x10lP\x0c\x98C#s8h\x0e\x8b\xcd!Z9\x1d\x9dK\x81\xe7\xc2\xc9'\x8b\x00t\x89\x08\xddq\x10]\xacA\x13@\xba\x13\xa0t\xd1\xd2y{z9\xa0\x0e\x81\xd4\xe5Cu\x1ew<\x9ad\xb2(X\x17C\xeb2\xe1:\x8f\xafxrI\x04`\x17N,\x19J+Y\x1a\xb3+\x0e\xda\xf9Q\xbb\x92\xb0\x1d\x06\xb7K\x07\xee\x92\x90\xbb\x0c\xe8.\x15\xbb\x8b\xa4\x8a\x0c\x97\x0e\x0bBa\xe1\xbb\x0c\xfc.\x11\xc0\x0bT7\x07\xc2\xf3\xb8B$\x87\xcc\x01\xf1\x02]>\x9e\x18\xb2 \x8c\x17M\ny\n \xafT_L\x80\xf2R\xb0\x0f\x98'\x02\x91\x8e1\xda\x18\x80J\xc5\x88p\x83\xeb\x90\xc9I\x18\x11\xa9\x16\xcb&ZD\xa6Y\xccI\xb2\x88L\xb1\x18mlL\x07F%W,p\xa5\xf8m/\x97T\xd1=\x02%d\x9fC%\x9f\x9b\xa5\x9b\x9b\xf9\xfb\xf2\xf9\x82\x92\xcd\x01%\x9b+6\x1ef\xd1{\x94l\x0e\xc3\xec\x15!\xf6rx=J6W\x90\xd2Ka\xf4\x92\x08=J6w,\x97\x97A\xe5\x15a\xf2\xd2\x89J[\x93\x95hE\xda\x9a\xec\xc7\xda\x9al\xc0/_\xff6\xf0w\xa1\xfd\xca\xac\x9bo8&\x03ej\x04\xd3l\xa6Y7\xaa\xd7\x89;\xa0v/1\xd7\xbd|?\xbe\x86\xf5\xd1oW\xab.\xc4l\xea\x9f\x9e;\xb2\x19\x01\xa9V3\xf2K=\x0d\x92\x89a+\xf3kQx*\noF\x97\xee\xa3\xf8P\x04\xdb\x8c\\ \x84/\xf2\x08\xb0I\x99\xb2\x9c\x96\x88g\" \xcc\xb2\x08&\x12\xc0L\xc3/\xf1\xe4W\x06\xf85\xf3F\xdc\x976\xe2\xbe\xca<\xb1\xc4}\x11\xf7\xe56\xe2\xbe\xa4\x11\xf7uh\xc4}\x11\xf7\xe53\xe2\xbe\x88\xfb\x92F\xdc\x17q_\xc4}\x11\xf7\xa5\x8c\xb8/\xe2\xbe\x88\xfb\"\xee\xcbg\xc4}\x11\xf7E\xdc\x17q_\x96\x95`p\x88\xfb\x92F\xdc\x17q_\x7f\x04\xeek\x10t}\xe5\x1f\x0e\x98\xed\x88\xa7\xc4m\x9d\xac\x84\xf5p\xd3\xb5\xdbI=\xfa\x82\x15)\x02?\xc8\x8d\xac\x02\xb4\x83\xbd\x0f\x96\xc1\x1c\xe4\xabB.\xa1O\xf7B\xbbo9s\"\x0c\x96\x93\x17\xa6\x9e\xcf\x14c\x90\xf5\x8a@\x0c\xaa\xeen\x84A\xfeV\x14`\x08\xec\xde\x16Y}\n\xee\xda\x169\xd7\xbf[[\xe4\xc4\xf8.m^\x07\x08\x05\xdb\xeaI)*\xf6W\x87\xbcA\x1a\xb66\xd2\xb0I\xc3\x1e\x8d4l\xd2\xb0G#\x0d\x9b\x93\x86\xed6\xd2\xb0\x8d\x91\x86M\x1a6i\xd8\xc8Y\x12i\xd8\x83\x91\x86m\x1bi\xd8\xa4a;\x8c4l\xe71\xa4a\x93\x86\xed1\xd2\xb0I\xc3&\x0d\x9b4l\xcbJ\xe8\x89\xa4aK#\x0d\x9b4\xec\xe7\xaba\x17\xd1\x84\xef[\xceB\x9b\x11\xfd*~\x1f\xd4`y\xb4R\x82\xd7\xf5=k\x0e\xea;\x91\x82\xe5\xb9/L\x8d\x9f\xa9\x08,\xab\xf4<\xf4\xabh\xf8z\xd2\xfaM`\x07\x0cQ\xe7\xfc}\x87\xd4\x02|\xf6\xe9\x00\xac\xd9\x07\x82\xcc_\xc1\xaf\x9f\xbe~X|\xfa\xfc\xf5\xf2\xd3\xc7\xc5\xb7\x8fW\x9f?\\\\\xfet\xf9\xe1=\xf2\x8c\xff\xfap\x85<\xf2\xed\xbb\xab\xafo/?\"\x8f\xfe\xf8 }\xe0\xe2\x1f\x97_\xff\xb6\xf8\xf5\xc3W\xdf)F{N\xac*fuK\x98x\xf0>\xc9\xc3d[\xcbu\x195`\xa9u8q\xff\xf5m\xec\xe5\xbcV?\xce^\x87\xeb\xf6\x9euM\xd5,\xed\x11\xce{\xb4\xff\x16z+lE\xf07\xed\xabvg\x171\xf0\xf9sp\xe7\xdf\xcc\xff`9~\xd2\x03X\xaa[\xddM\xde\xb8\xfe8\xd9\xd6H!\x18Y\xd7\xf8\xf8\xe9\xcd\xec\xdf\x93\x16\xc9\xf49\xf6\xc3\xb9\xf7\xf1\x97\xe9u\xe4\x12\xe6=\xe3\xd1+b\xba\xa2\xe8\x86\x96{\xe5\xb1\x11\x9d\x0d\xdd\x9d\xde*'\xcb\xb6\xe9\xeb\xde\xec~7@H\x97\xef\xcfT\xaf\x16\xe3\xd9\x99\xf9\xaa\x94\xff\x0c\x8c\\\x87\xd5\x99TF\xbd\xe3\xcc\xce;\xc2\x9fz\xfb\xa9\xc7\xe6`\xd1\x9d\xf6\x95\x92F\xfbJ\xfdP\xfbJ\xc9\xa9]\n\x95\xa5\xe6\x91_>_\xcc\xbc\x11\x95ETVt\xc2\x88y\xd9\x00QYDey\x8f$*K\x1aQY\x87FT\x16QY>#*\x8b\xa8,iDe\x11\x95ET\x16QY\xca\x88\xca\"*\x8b\xa8,\xa2\xb2|FT\x16QYDe\x11\x95eY B\x86\xa8,iDe\x11\x95\xf5|\xa9,\xdaQ*w\xbb\x1e\xdaQ\xea\x84\x8d\x1b\xef\xa3\xb4\xa3T\x89V\xa4\x1d\xa5~\xb0\x1d\xa5$\x14\xf4\xfa7\x89 \x85\xb6\x92z)A&\x1b\xa4]96\x8djG\xa4\xf6\xf2\xfd\x99\x02\x9b\xe4nQ/\xb5\xbf\x03\xc0\xf6\x85\xa9\xf93\xe6k#d\xd4\xfd\xc8\x89\x1d\x02WE)\xa8(a\x1b]\x89\x8fr@\x01\xb66\xe2<\xc4\xd5F\xcb\x15bjS\x89Z,O\x9bB\xd3\"Y\xdaD\x926\x8b\xa3\xc5\xa8\x11\xc5\x19Z<\xf2\xf8\xfd\xf8\xd9\x93\xd0\xb3\xa7gg\xcb\x93\xb3\xdf\x85\x9bERu\xa9P\x1d1u\xc4\xd49\x7f'\xa6\xce2b\xea\x88\xa9\x1b\x8d\x98:NL\x9d\xdb\x88\xa93FL\x1d1u\xc4\xd4!gI\xc4\xd4\x0dFL\x9dm\xc4\xd4\x11S\xe70b\xea\x9c\xc7\x10SGL\x9d\xc7\x88\xa9#\xa6\x8e\x98:b\xea,+\xc17\x11S'\x8d\x98:b\xea\xfe\x08L\x9dT\xd7}e\x97?NJ-\xff\xa0\xb7\xe8\x1a\xb4\xb3\xddw\xdc\x9f\xcb\x90$\xdb\xba\xe1\x03JR5\xcd\xbe\xda,\xe4L\xa5\x17\x1f\x98~j\xe4\xad<\xf4\xf3p\xa4Y\x9e\x02\xe1P\x8c\xa2\xca\x17\x8c\xbe\xd4\x9b\xceTm\x82\x8b\xcc\x9d\xbd0\xf5|\xa6\xe8\x88\xa7\x9dl\x0b\xae\xf2\x04\xd7w\xe2\xeb'\x07\x977\x92l\xf4\x1e8\x9cM\xee\x8a\xb2\x10\x06\xaa\x05\xe1\xf9\x1dC\x89\xc3.G\xaf\x0f:\x12m\x89\xa5\x8d\x84\xe2\xd0*\xe9 \xd6X\x93\xc6\xca\xba\xb9\xd9X\xd9\xb5\\c\xe4\xa59D\xb3\xa6\xee\x87tp\x14\x18 \x07O\xfa\xc7g;2\xceZ\xc5\xb6B#\xe2\xd8\\\x9eA\xcf\xd3\x9e\x0eWn\xd6eh\xeb\xfc1m\xbc\xf1_>_\xcc\xa7l4\xb6\xd1\xd8\xf6\xcc\xc769U\x0fL\xfe>\xcb\xdf'\xa3\x9ab\xaceX\xc1\xcd\xf0(\x8eS~\xe7\xa8\xf6\xf7\xba\xe1\xca\x95\xfe\xf5\xd9\x0ekv\x83\xd86\xcb\xa3([e\x9aC\xd14\x80\xf9:\xd9\xb6\xab\xfd\xa6,;,Z{\xb1bM\xeb\xe1l\xa3\x1dF\xe7\x07\xe4Z\x08[\xb6\xb5\xfc\xb4\x15~\x1d\xc7\x0f\xe3\xeb\xa2\xab8[(e\xfb\xb8+o\xab\xc7z\xbb\xdf\x9a\xf9\xaar)\xbe\xb4\xc7\xb1\\\\+X\x98m\xf5X\xa6\x10)\xd7\xcc\xdc\xd7v\xbcf\xdd\xe0\xae\xb9n\xab\xcd\xe2\xbamV,\x97\x0f\xd7W\x14\x8e\xc4M\xde\xb1n)\xde\x9a\xca'T\xbc\xdd\xba\xbe\x0e\xae7\xed\xf2\xae_\xecX\xb7xbU\x1e>\x8e`\xd3\x87\xe2\x0d\xef9uaQL\x10\x17\x9e\x9c\x83x\x89\xaba\x05\xf5\x06\xd7\xefl=\xa6\x11\xb4J\xefk\xd7\xef\xcf\xed}\xad^6\xe87\xb6\xf5\x15\xaf;\xba \xf8\xa9F\xaaex[\xa9l\xc6\xeaUu\xa6\x13\xea\xd7\xbc\x87~\x7f\xdd\xef*I\x9a\x8d\xebtw\xec\xc9\xf9v\xff\x03\xbd\xd91/\xf6\xc9{\xdd\xc4\x01\x0d-V\xf4\x85n\x9a9k\xb4\xcdM\xa5\x1c\xe8\xc3\xde3\xb3\x06b\x1a\x84\x81\x06a\xf7\xe9\xcfm\x10\x0eI\x16\xe6!\xf5\xf5\xc0a\xac\xb4\xc7\x0d5\xa4\x8a\xc9\xf5\x98)|\x1cuo\xa6\xe8nN\x1c\xe9\xac\x86\xa6\xb0\x810\xff;\xf64)\xa2\xf8\xb7QR\x86\x92i%\xde\xd4\xa9h)co\xba~S\xf5\xb7u\xb3F\xbf\xebf/\xb8\xc3\xef0\xe3Q\xdf\x0e}\xfe\xe4\xe5u\xa5\x0f\xf9\x03\xbd\xc4\xbc\xcfq\xde;\xa8^7l\xb5\xd0\xf3\xff\x87\xbaY\xb5\x0f\x89o\x07c\xd6\xb0\xe5\x9c\xfco\xebf\xa1/'\xbe3\x8a\\\xcbC\xce\xae\xda\x87\x86\xd7[\xb6\xf8gUo\x16+-tf]Kv\xa2\xc5\x8d\x0c\x14i\x9b\xc5\xaa\xdd_o\x98\xacG\x96\xbbh\xd1\x0f\xae\xa7jr\x8a\x8b\xc5\x15\xa8a\x01H\xeb\xf0\x07O\xd9\xc0\x8d_\xabA\xce\xcb\x8d\xfe\xfd\xd9\xbe\xf8D\xad\x9eGG\xd3,GvO\xe9y\xd5\xf1\xc5-\xab\xd7\xb7<\xdbI\xfc]\x0b\x81\xc1u4U\x0c\xa8\xb8&\xa1\x86\x0e#\xf7m\x91\xc0\x99\n\xc7\\\x89?3\xf8\xf4E\xfc\xe0u\xb7o\xc4\xeb\xd6\x13{U7+\xf6\xb8PYX\xbeO\xc5\xe5\x15\x87\xbc/\x0do\xf5dG\xad9\xc2u\xcd=}G\x98\xaa\xc9b\xdf\xf0:\x7fP\x19\x8b+\x9a\xef\x95x\x8f\x87\x8b,\x8e\xe8y\xb5\xddY\xb7bY5M+c{L\xfb\x82,\x95\xd3\x13o\xb7\xd7=o\x1b\xdf\xf2\xb1)\xf44\x0f\xcd\xc11\xd1\x9e\xf3p\xcbd\x9c\x96\x8c\x1b\xe5&\xeaH\x96\xf7\xb6\xea\xe1\x9a\xb1\xc6*\x0b\xfc\xc7]\xbd\xf1u\x0ca\xed^\xeaI\x83\x13?\xfe\xd63\xee\x06\xcb\xb7u\xdf\x8f\x13Y\x99\x10\xe8\x88-\x06\x93:Z\xa0\x9dT\xa9\xcc*\xb7.\x15\xfc\xc7\x10\x01\xd9\x8b\xbbk\xf2\xa4\xc9\xde\x08\xec\x9e\x05\xc2\x8cE\x0fq5@|.\x07\xf0\xabi^k\xe8\xb7\xb7G3?\xbf\x9c\xbdN|\xc1\xc7\xdb\xb6\xa9y\xdb\xe9\xe2\xd7\x9e\xbb\xb6\xa9\xefY\xc3\xfa\x1e\xc4\x8c\xf6\xbe\xe6O\x8e54\xf3\xc0\xde\xb4f\x9a\x87z\x9f\x19\x0bm\x81v\xc4\xb7\x11mYF[\x96a\xb7,\x03\xd43hgPT\xb5\x9a\xf0\xccu\x03\xeb/\x9f/\xc6o\x1c=/\xef\xc5x\xdb\xb9:\x91'\xd8\x7f\xd9v\xca\x87L\x8c\xd0\xa9\xca\x0f\xe8\xb1\x18\xa1\xe5\x87\x9b\xdd2\xce\xe60g\\\xb5\xdb\xb1\xdc\xc1\x10\x9a\x8e\xed\x98\x0cM|Wu\xc3M\x8a\xf0\xf8\xd3f\x91=\xd3G\xe4O\xa3\x81\x82\x9f\x8f\xf6\xfc\x16\xf5\x11\xe9r\xf2z2\xd9\xf6R>\xc3\x1f\xe9\xcb\xf2\xa0}\xe8\xcb\xb2\xf8\x97e\x10\xb1\xa7\xa4\xaf\xd1\xa5h\xf0\xbd\x9d)\xe9k\xd9\xc6\x8d\xa7+\xa5\xa4\xaf%Z\x91\x92\xbe\xfe\x89\x92\xbe\x86\xd7\x05_\xff\xb6l\x9b~\xa1\xd7\xa1B _\xed\xaf<[$\x9b\x7fZ)\xeec)\x13\x05)\xaf\xda\x93o\xb9\xf0\x85\xa9\xf63]-\xbc\xaf6\x0b\xbb\xcd\x1c\x13\x89\xc0g\xc7\xfcl\xdf\x17\xa9\x9eU\xb3\x958C6\x9f\xc3\xd9\xb4AG;\xe2\xab4\xb8\x02\x19\x99O\xc4W\x1f\xa3\x13\x92\xf8\xbaH\xec\x9b\xae\xe8\xaac`\xcd1\xbe\xe2X\xae\xb2G\xac5\xc6W\x1a\xd1\xc5\x0c\xaf2\x96Yc\x8c\xad0\xc6\xd7\x17c\xfd#om\x11\xda\xbd/\xfb\"fe\xd1\xb3\xae\x98\xb0\xaa\x88\xbeK\xd1\xce\xe4m\x99\xc2\xab\x89\xee\xb5\xc4\xf8*F\xd9uD\xcc*bd\x0d\x11\xbb\x0ePd\x19\x80V\x01h\x15\xc0\xf9\xfbsZ\x05\xb0\xe7\x88\xbe^h\x1fc\x9e\x08\xf3\xcf\x81\\\x9b\xcdz,_'\nX\x1f\xa7\xc1\\\xa6T\x1cf\xc1+\xb6ak9\x1d\xed_\xff\xa6\xff\xd1v\xb2\x02\xa1Y\xb05(\xbc7'\xbd\x1f]\x8d|\xb4\xfc\xd2\x1b\xff.\xd1h55\x1e.6x\xd2\xcd\xe4\xe4\xa1]W\xd1\xc7=\xdb\x19\xf3X\xf1\x85\xa3\x8c\xc6~\x8f\x07o,Y\xf8\xe1\xf1^\x00\x10\x17\x81\xf1B\xbaG\x05$~\xc0=\xb00\xbe\x07\x8by\xeco\xab.T\x07\x94\x9b\xf8\xfb]\xd9\xd8}\xe7\xfc\xd7u\xdb\xe8\xbc\x99\xbc\xbdcM\x0f\xb7l#\xd3]y\x05e\x80j)\xa7+\xfa\x13\xdc\xaf\xef\xb6\x0f\x8dJ\x9d\xd56l\xbc':]\xa9L\xd8\xdb.k)0\xa8\x02\x04\x92\xd2\xde\xb7*8\xb1}P\xeb\x0dm\x13\xc8\x05:\xdc\xacCuR\xd8u\xb5\xa9\x1a\x1f\xa9_\xb0\x0fz\x83\xfb\x94!n/@\xb5\x15-}\xa4\x1bl/\xb9h\xeb\xc6\x9a\xfb\xc9\x0e\xa1\xb3s\xaa\xea\x98\xe5\x1cq\x03\xabF\x17.\x94\x08\xf6\xe3\xa7\xaf\x1f\xde\xc8\x94Z\xeaX\x9d\x9b\xaa\x96\xe9C/\x1b\xf3\xd58\xa4l\xed\x83\x9d@\xa7\xf4\xd1\x134\xff\x93U\xaf\x9b\x8a\xef;\xd6\x0f/1\xd1 \xd7\xed\xba\x95\xf9r\\\xbd\x02\xd3D\xe3Cd\xcf=\xc5\x15\xee\xab\x8d\\\xcam\xed\x07\x8d=.\xd9N\xad\x15;\xdd\xd5\xdcJ\xa6\xea\xae\x8d\xee\xa9\xf3\xfcEj\xe80m\xd7\xc3\xb6\xed\x18\xf4\xfb\x9a\x9b\xa57\xa7\xb3\xe5F\xae7\x0f\xef\x84\xc3f\x887\x82\xeb\xdd2\xf6\x98\xcdF\x0e)\xd6\x9b\xf7\xe5\xa8\xf9\xfb\xbd\x1d>\xa7!\x06`\x16\xe53,1NCx\xad\x95\xc7\xc9\xd7A\xd1\x98\x1fb\n\x88)\xc02\x05!\xc5N\x7f\x98\xba&\x9b\xd1 ,\x97\xa3\xd7\xce\xc91\xe5\xe8\xd1F\x1f\xb7e\xa6\x0b\xb4\x99\x0bm\xe6\xe26\xda\xccE\x1am\xe6rh\xb4\x99\x0bm\xe6\xe23\xda\xcc\x856s\x91F\x9b\xb9\xf8\xfb4m\xe6\xa2\x8c6s\xa1\xcd\\h3\x17i\xb4\x99\x8b4\xda\xccE\x1am\xe6\xa2\x8c6s\xa1\xcd\\h3\x17\xda\xccen\xd8\x8d5h3\x17i\xb4\x99\xcb\x8f\xb0\x99\xcb\x94\x98\xb1\\M>&\xa7GM$\xd7\xe1\xa7C\xec\xcc\x91\"\xed\x08\xd6\x8c\xa2\xe3rC\x8f(:\xee\x84\x8d\x1b\x8f\xeb\xa2\xe8\xb8\x12\xadH\xd1q\x7f\xa6\xe887\x16\xdcv\x87T\xf0\xeb\x8e\xd9\\\x91r\xebb\x84\xbf\xd8\xc7\x0dD\xf0\xe4\xec1P.\xc4\xfeN\x1c\xbd0\xf5\x7f\xa6\xd0\xaf]\xbf\xe7\x86\xfd\xdae;9ty:\xf0\xb7\xef\x96'\xf0\xba\xeay1\xaf\xac\xe1]\xb0y\xc2\xf7\x7f4oO\x18\x0dq\xc3\x94an\x9b\xb2e\xc7T\xff\x0dgT\x1b\x0d\xd5(\xc6\xe2\x11[\xa3-[\xf1Y \xcb\xe2\xcf\xd7i[VIby\xc4\x8cI\xe5\xbd\xda,\"\xdc\xf2h \xa5Q(\xa9\xe8\x85\x05\xddb\x04\xa8\xd1\xecq\xf6C\xc3\xbb'\x0bA\xb6\x87\x0eLg\x03\xa5?ul\xc3\xee\xab\x86\xc3\x96\xf1jU\xf1\xca\xb7z\x88-\xa9]\xc6\xe9\xf2\xcb\xa6\xee\xb9\x8a/\xd9U\x1d\xaf\x97r\xed\xc8\xe7f\x18\x9e^\xdao\xa4f-)\xfc\x00H\x7f\xd3\xb5\xdb\xc9\x15@3Wc4\xa5\x9c\xb2\xa1\x8a\xd0s3\xef\x88p\xf2\x91\xe1$>\x94D\x86\x11\xd4\x10\x82\x1b>&\xaf?Qn\x0f\x93k\x0cui@_\x1eh\xf4\xf2\x1a\x8d^'\x1b\xbd \x1e\xcc\xa2\x0cUw|\xbd\x0f\xea\xec\x8f\x87\xf0\x13X\xae\xa6\xb3B&\xa0\x0e\xe0\x91`\x91\x0b)A\x12\x01\x87v\xf8\x84\x0e\x95\x08]?\x10E\x81kI\xbb\xf2\x81\xe6\x9b\xbeyT\xfb8\xfd\xe96\xeb\xcd\xa8\xed.\xfc\xc0\xc3\x1e\xddj\xe8\xf6\xf2\xb6\x14\x05yH\xa3 \x8f?i\x90\x87;\x83\xc1dU!/\xbac\xba\xc2A\xbb\x95R\x94\x87\xf3w\x8a\xf2\xb0\x8c\xa2<(\xcac4\x8a\xf2\xe0\x14\xe5\xe16\x8a\xf20FQ\x1e\x14\xe5AQ\x1e\xc8Y\x12Ey\x0cFQ\x1e\xb6Q\x94\x07Ey8\x8c\xa2<\x9c\xc7P\x94\x07Eyx\x8c\xa2<(\xca\x83\xa2<(\xca\xc3\xb2\x12\xc4=EyH\xa3(\x0f\x8a\xf2x\x9eQ\x1e}\xb7\\L\xb3\xaf\xfa\xca}x\xe4\xa4\xec#+e\x95}@4\x98\x84\xac\x8e\xe5\x9f=uX\xf5\x1cY\x87\xc3#\x93\xea0MnY\xb0\x06\x14k\x83i-\x8a\xb5Qv\xe2\xc6\x8dG\x89P\xacM\x89V\xa4X\x9b\x1f4\xd6f\xdf\\\xab\xedF\x17\xb8\x98\x1bW^\xfeo\xc6\x87/A\xffp\x91\x83T\xfd\x833\x19\xa43\xb6\xdd\xc1\xec\xc3\x19\xb7\x13,\x81>\xe1\xd9\xc6\xf1\x8c-\xff\xcc\x82x\xd0\x915Q\xdd\x05\x9dJ?\xea\xe9\x0f\x04\xa8'\xd1\xe1\xd1\x8a\x1b\xc3R\xe1IDx\xf2\xd51$x\x12\x05\x8e,A9_\x18-M\x99cL\x99Q\xdf\x8d5\xb0E\x99o<\xef\x8d)\xa2\xa3p\xd0\xf3\xb6\xd3\x03\xae\x8cR\x11\xd3\xbb\x0d\xb3#Q\x9c\xae\xc6:\x04BS\xc4\xabu\xf08~\x9a\x88O\xf7FnH\xf5\xaa\xedV\xacc+\x19%C\xfc\xaf\xdb\x03\xf1\xbf?\x12\xff;\x7fF\xf1\xd9\xdeg\xde\x1c\x9c\x99\xc2\x83\x83W\xa0,\xf0\xc6\x88\x0f&>x4\xe2\x83\x89\x0f\x1e\x8d\xf8`N|\xb0\xdb\x88\x0f6F|0\xf1\xc1\xc4\x07#gI\xc4\x07\x0fF|\xb0m\xc4\x07\x13\x1f\xec0\xe2\x83\x9d\xc7\x10\x1fL|\xb0\xc7\x88\x0f&>\x98\xf8`\xe2\x83-+\xc1j\x12\x1f,\x8d\xf8`\xe2\x83\x9f'\x1fLdj\x1a\xf6Gd\xea \x1b7\xceT\x12\x99Z\xa2\x15\x89L\xfdA\xc9\xd4\x812\n\xe1\xa8\xff\xed\xc0Q\x7f\x1dN\x9c@\xa8\xa3?\xa8\x9b\x9bV\xde\x13\x95\x1a~\xb8\xf2\xe0+\x04\x9d^\xa9:8.\xa7\x8f~\xb6\xc4\xe9\xd8\x02\xcf\x03]P\xcdZ\x80\x0e]\x8a\x06k\xfa}\xbf\xd8\xed\xaf\xbd\x00W\xb4\xbc\x80(3 \x90\x0b\xc0\x94Y\x19f\xe9\xdeX*~\x11t\xe6^\x83\x0f,I\x95\xc60 \x8eb@\x06\x8e\x11\xae@\xc5o\xd1H\x06\x94\xc22 \x13\xcd\x08:\x94\x99]\xb1x\x06\x1c\x8fh@2\xa6\x11t\xa5\xe5\xe3$T\x03J\xe3\x1a\x90\x88l@*\xb6\x11\xee\xd9\x03\xd2\x81E7\xa04\xbe\x018\x84\x03Jb\x1cp4\xca\x01y8\x07\x94B: \x0b\xeb\x08?\x0e\x95\xf8l\x8a\xa2\x1dp\x1a\xbc\x03N\x88x\xc0i0\x0fHD= \x0f\xf7\x88\x0d\xc18\xe4\x03\xcab\x1f\x90\x80~@:\xfe\x01\x19\x08\x08b\xc8\xfc+\x02\x03\x81\x12(\x08\xc4p\x10\xc0O\xcf\x10X\x08$\xce\xe2\x92\xf1\x90\xa07\x89\x8e \x10\x11H(eAT\x04\x92p\x11(\x8d\x8c@&6\x12\xeeW}\x1c\x1d\x81||\xc4\xebO\\1\x86\x90@1\x8c\x04\xf04\x04`p\x12HCJ \xa6\x01g\xa2%\x80\xf0\x1b\x90\x99\na&\x90\xd5\xb8x\xdc\x04\x10\xb5\xcc\xc0N \x17=\x81p\xab\x96CP\x00\x8f\xa1\x00\x12E\x014\x8e\x02\xb8VO\xc7R M\x81 \x9e\x02\xa5\x10\x15H\xc5T\xe0HT\x05\x10\xcd\x9b\x80\xac\xc0)\xb0\x15\xc0\x941\xf0$\x94CX\x00\x83\xb1\xc0\x11(\x8b\xd7\xa180\x84\xb3@i\xa4\x05\xa2X\x0b\xe4\xa2-^o\xea\x1b5\xfc\xb9\x8e@\\ \xa8\xc4C\x10u\x81,\xdc\xc5\xeb*\x88\xc1@.\n\xe3\xf5\xa6\xe6\x81\x81U\xb3rH\x0c\xa0\xb0\x18\xc8@c \x0d\x8f\x81\x1cD\x06\x921\x19\x88\xbcm#\xe8\x02$\xe0\x0bXd\x06r\xb0\x19HEg \\\xf1\x1c\x84\xc6\xeb\xcc\x02T\xb0\x8f\x0c\x0e\xa5 >\x10\xcd:\x8c\xd3@Y\xa4\x06bX\x0d\x84\xd1\x1a\xef9\xb9\xc8\x0d\x14\xec\xbb \xe8\x0d$\xe17`!8S\xfbgUo\xd8*\xacNM\x15\xd5\xa9\xf5\xbc\xe2\xfb|\x99\x0c\x805\xfb\xad\x7f\xa6\xf9\n\xde}\xfa\xf8~q\xf5\xf5\xed\xd7oW\x8bo\x1f\xaf>\x7f\xb8\xb8\xfc\xe9\xf2\xc3{\xf4\x19\xe2_\x89\x87_~\xfc\x19y|\xd0\xb9 lO\xacB\x88\x1c\xb2\xed]\xdb\xac\xaed\xeb\x1bHC\xdd\x0b\x95i\xc3\xda]\xd5\xdf+\xbc\xad\xfb\x06\xac\x7f\xd8\xd9E\xeaF-\x11\x8d\xf96\xd4E\x03\xf3K\xf7\x0d\x11WP\xffemYim(+7\x14T\xeb\x90\xd7m\xb3b\xab\xc4+\\~\xfc\xd9\\\xe2\xf2\xe3\xcf\xc1k\x0c\xd9F\xd0\x970U@T Tx\xde\xde\xb1&\xff\xd9\x19\xe9\x04\xb5o\xe2\x11\x8e\xc6\x1e\x17\xf4q\xb4L\xbdm\x9b\xfa\x8e9\xd2+\x8c\x16-\xad0\xa5*\xf3\xe0>\xbb(G\x0f\xec\xba\xaf\xf9\xf1\xeb\xb2=[\xee\xbb\x9a?-\xe4$p\x19L\xb1\x84r\xe8M\xe80\x1a\xc2\xcfd,y?\xfe\xc3\xd9e\xad\x83\xdd\xfduL\x0f\x16\xce#\x85(X,\x8d]\x94\xc4\xce\xa1\xb0)y\x9f\xef\xb0(m\x9d@ZcR\xd3\xa5\x10\xd6\x94\xbc\x8f\x92\xf7ahiJ\xde'\xed\x18\"\x9a\x92\xf7\xb9y\xdf\xeb\xdf\xa6\xbb\x00\xff;7\x9b\xdf\x90\xcc\xcf\xde~\xd4\x9d\xc7o#\x91\xd0\x08\xf5\xe1\x8c,}E)\x0d\x14\xa7Q\x90\xd48\x96\xd5\xc8\xa25\n\xf1\x1a9\xc4F\xc0\x19:+\xdf \xa8\x8d\xd3q\x1b'!7\xd2\xd8\x8d\xe2\xf4\x06\x96\xdf(Jp\xe0\x19\x8ed\x8a#\x9d\xe3\x88\x0e\x85\xb8\xfc{G\xb3\x1c\xd1\xdc{\xa8 \x15\x82\xe8H\x99u%S\x1d\xa1\x97 :\xe3\x1e\xae|\x05\xd9\x8e\x14\xba\xa30\xdf\x91Gx\x84z\x10*\xcb^&\xe5\xe1\xf1\xc6Q\x19\xf6\xca\x90\x1eh\\\x01A{$\xf1\x1e\xb1\x04U9\xccG\xcc\xa7W\xfb)D~\xa47&\x9e\xfe\x88\xd5-\x83\x00\xc9d@B\x1aZ1\x0e\x04M\x82\xe0X\x10,\x0d\x82h\xe5t\"$\x85 \xe7\xcc+\xc2\x85$\x92!\xc7\xb1!\xb1\x06M\xe0CN@\x88DK\xe7\xed\xe9\xe58\x11\x04)\x92\xcf\x8ax\xdc\xf1hn\xbc\xa2\xbcH\x8c\x18\xc9dF<\xbe\xe29\xf1\x10\xdcH8\x1f^(\x1b^iz\xa48?\xe2'HJ2$\x18\x8a$\x9d#I\"I2X\x92T\x9a$\x92\xe1.\\:\xac\xbe\x8feJ2\xa8\x92D\xae$P\xdd\x1c\xb6\xc4\xe3\n\x91\xd3.\x87/ t\xf9x>\xbb\x82\x8cI4\x97\xdd)8\x93R}1\x815I\xa1M\xdc\x99\xeaBy\xea\xb8C:\xb4-\x94\xa3.\xfa\xed\x1f\xcaO\x97\x9a\x9d.)7]Zf:t^\xba\xac\xact\xb8\x9ctGg\xa4\xfb\x0e\xf9\xe8N\x9d\x8d\xee\xe4\xb9\xe8N\x90\x89.\x94\x87.\xf2|\xe0r\xd0E\x9dD\xf2\xcf\xf1\xe3e\xd5h\xe6\xb9\xe8@\x80\xc9:\x87p\x12\xcd8\x87\xf0\x81\xcf6\x87p\x16\xcd4\x17\xf5Q2\xcb\x1c.\xc7\\\xb4H\xb1\xfcr\x98\xecr\xe8\x8b\x84\xd2f\xc5\xf2\xca\x15\xe8\xda\xf8\x8cr\xd1\x8b\x01\xea\x82\x80\xca%\x17m>e\xb8q+\xe6P>{\\F\xee8D\xe68T\xde8T\xc3`:?\xb6\xf9\n\xe6\x8b\x0b\xb6\x00:W\x9c\xb7\x05\xb2r\xf0\x0c)x\x8e\xc9\xbfC\xe9w\x8cQ\xfa\x9d\xd8\x0b\x1d\xf3\xcce\x82_\x94~\x07\x83{\x15\x81\xbdrP/J\xbfS\x10\xf0J\xc1\xbb\x92\xe0.J\xbfs,\xd2\x95\x01t\x15\xc1\xb9\xd2a.J\xbfs\x0c\xc4\x95\x82p\x15\x06\xb8p\xf8VAx\x0b\x8bn\xf14p+\x15\xdb\xa2\xf4;\x13K\x06\xb5(\xfd\x0e\n\xcf\xca\x81\xb3(\xfd\x8e\xef\xb0(\x90\x95\x80ca\x92\xcb\xa4\xa0X\x94~\x87\xd2\xef`\x80+J\xbf#\xed\x18\xc4\x8a\xd2\xef\xb84\x0b\xf0\x9d.\xc9\xee\xeb\x15k\x96\xec;]n\xe8\x7f\xe3\xf4'\xf0Z\x12#p\xdb\xb3H66(V\xbe\xc9\xa4N\x8dd\x93\xaf\x88a\x9a\xa4\xa2T\xbe\xb2f\xc5\xbam\xddp=\xa8\xa8\xd7\x8fkFs_mz\x16\x04\xd4\xdd\xe8 \x84\xf0A\xc0\xbd\xcd0\xef1\\\xde;e\xa8\xb6\xc6\xe5\xc0S\x86\xa8\x03 \xeb\x01\xda]8+\xdex\\\xb4\x1e\xca\xf0\xb3}e\xa9\xb8d\xd4!w\xea\xe6\xa1\xf9\xb624>\x19\xf54\xe2\x951\x8c\xd2X*N\x19u\xb8\xab\xf8-\x1a\xab4\xe6RL\x92\xf1Jcx\xcc2\xea\xca\xc60\x13pKcGb\x97\xc6\xd2\xf0\xcb\xa8;\x8d\x86%a\x98\xc6Rq\xcc\xa8C\xf1E\x9d\x82e\x1aK\xc23\xa3\xder2\xf0)C\xe1\x9aQ/S\x9c\x13\x83m\x1a+\x86o\x8e\x0e\x8f\xc18\x8de\xe0\x9c\xc6\x8a`\x9d\xc6\xf0xg\xd4\xd5\x04\xff\x8cc\x9e\xc6N\x80{\x1a;\x15\xf6i\xec\x04\xf8\xa7\xb1\x14\x0c\xd4\x18\x1a\x07\x8dz\xb2qQ\xc0a\xa1\xc6\x92\xf0\xd0\xa879N`1Qc<\x0d\x175\x96\x8a\x8dF\x1d\xa6\xe4\xfcSv4Fj,\x92\xffOY\xc2\xd41\xfa\xd11Z\xea,3 7\x8dz\x1bpT\x04vj,\xa5\xc4\x89\x18j\xd0\xd7t6\x8b\xc0Q\x8d%a\xa9AO\xd1\x8c\x82\xcar\xd0\xd5x\xffDe\x17T\x96\x83\xb2\xc6\x1crT\xa6Aee\xd0VcHJ\xd3X\x14u5\x96\x80\xbc\x1a\x8b\xa4\x00\x93\x96\x83\xc0\x1a\xc3\xf8\x0ff\x11*\x86\xc6\x1a\xcbk|<*k\x0cS\xf3\x0ct\xd6X\x16Bk,\xd2\xe2\xe5\x90ZcH\xb4\xd6\x18\x06\xb1\xb5\x8eE\xa0\xb6\xc6\x90w%\x1d\xbd5\x86Gp\x8d\x85r\x1e*+\x82\xe4\x1aKBs\x8d\x1d\x83\xe8\x1a\xc34}\x02\xb2k\xac8\xbak\x0cU\xde\xc8\x93\x94\x8e\xf4\x06\xdd]?\xc5\xd1^c9\x88o\xd0\xa1\xd1\xd4\xc3\xb9\x13\x95\xe5 \xbfA\x87\xdc\xac\xb9\x05\xf2(*KE\x80\x83\xceF<\x18\xb1\xdc\x81@\x82\x8d\x85\xd2\xbb)\x0beYT\x96\x8e\n\x07\xddE\xf20\x9a\x83\xf08q\xa4\x83X\xa8q '\xa3\xb2T\xbc8\xe8\xec\xdb\x97_\xce\x11\x98\xb1\xb1T\xdc\xd8X\x02vl,\x19?\x9e\x9d\x88\xc4\x90\x8d\xc5f\x01\xd1\xbcy\xca\xb0\xa8(\x16O\x1e\xfc\xa6b\xca\xc3\x89)\xb8\xb2\xb1Hc\xe4\xe0\xcbA\x87\x88<\x8f\xcarp\xe6\xe8\xc3\x14\xcf\xf9\xa8,\x1do\x8e\x8e\xe2\x91\xfc\x8f\xca\x02\xb8s\xf0\xbc\\\x14\xdaX\xc9\xfe\x9e\x80F\x0f\xae\xd1\x88\xb41\xff\x04)\x94?R\x99Z\xff\xf1g\x91T\x16\xca%\xa9\x0c\xb9\x8e\x14\xca+\xa9,5\xbb\xa4\xfb\xac`\x8eI\xff)\xfeL\x93\xaes\xa2\x17\xc9\xca:iN\xc5\xe4\x9eTvt\x06Je\xdf!\x0f\xa5\xfbB\xa5\xb3Q\xfa\xafR4'\xa5\xeb2E2S*\x0b\xe5\xa7\xd4G`\x9e9\\\xaeJeH\x87\x91\xbc\x95\xcaxY\x14\"\x9a\xc9R\x19\xaa\x06\x80\xcaj\xa9\x0c\xed0\x9a\xe1R\x19\xda\x1f>\xdb\xa52\xb4\xe3h\xe6KeH\x7f%\xb3`*\xc3\xe5\xc2T\x86,$\x0e@\xc5d\xc7T\x96x\xd9\x18\x07\x1d\xcf\x97\xa9\xac\xf0#\x85\xcf\xa0\xa9\x0cyyH(\x02\xa0rj*C6\xba2\\~Me\xc9\x8e\xd1\xb96\x95%\xf8OQ\xa1 9\xfbf\xd4\x9d\xec\x06998\x95!2q*C\xe5\xe3T\x96\xd0x\xf8\xc7-\xad\xa1\x0b\xe6\xe9T\x86h%t\xceNe\x88V\xc2\xd6\xf8\xd7\x83\xcd\x8a\xad\xdbz\x06\xbc]3\xa9\x8d\xcb5\x1bnv\xed\xf6\xba\xab\xb6\xd6\x0e\xdf\xfe.4\\\xf5\xa5\x9a\x18\x81\x9a\xac\x98\xf5\xc6\xba\x03\xf6\xa8\x1e;\xd9IC\xdf\x98\xcb\xb6n\xfas\xb8\xdaT\xfd\xad\xf8\xc65HJ\x88\x8a\xab`\xc5D?\x1fY\xad\xc9\xe5\xce\x14\x0f#Q\x8c\xb6\xebB\xe3\xdf\xb2\xda,\xf7\x9bae\xecf\xcf\xf7](gT3\xde\xe0^\xb6i\xbb\xe7Ps\x19\xd2\xd8\xac\xa1\xbd\x97\xe0\xae\xd9\xdf\xfb\x1c\xfeq\x1b\xe8\\\xb2\xea\x92\xdf\xd1\xa7H\x82\xc7\x7fu\x89\x89\xd87w\xba%u/\x9e\xfdU\xcd\x0d\x8f\xe0_\xcc\x18+\x01\x0f\xb7m\xcf\xc6M\xdc\xfd\x17\xb7os=%\x86\xac^\xa3\xaa4T\xc7_\x82zXRWk\x13\x12s\xf1_}r\x7f\xcf\xe1\xd7V6\xf7\xae}`\x9d\xccUx\xcd\x86[\xc9Vr\x89<\xd8\xcd\xd5d^W\xc7\x7f\xd5\xed~\xc3\xeb\xdd\xa6V\x05\x9d\x96arR\xf8i\x95\x91\xb8\xd3P\xd7!\xdbn\xdd'$\xdc\x9d\x85\xdf~\xf9|1/;\xe5\xde\x05\xca\xbd[\xea\xdd\x92\n\x93\xab\x0eL\xb9w\x11\x90x\x118\x1c\x0f\x85S\xee]c\xa9\xb07P\xee]\xcb\x10\x10w1x\xfb8h;\x03\xd6.\x02i\xe3\xe1l\xca\xbd[\x02\xbeN\x81\xae\xd1\xb05\xe5\xde\xa5\xdc\xbb\xe8YR\x12\x0c\x0d\x9cr\xefR\xee]ee\x00e$\x1b\x1b\x05\x92\x13@dLf\xd9\x14\xf0\x98r\xefR\xee]\x0c\x10L\xb9w\xa5\x1d\x03\xf6R\xee]\x97\xa7(\xa0\x9b\x03\xe6R\xee]\xdb\x10\xa0-\xe5\xde\xa5\xdc\xbb\x13\xa3\xdc\xbbi\xf0*\xe5\xde\x1d\x8cr\xefj3yl\x15\x9cc\xb9\x98\xa6-\x95\xbf\x8e\x12277H\xfd}\xc8X\xcb\x0f3\x9a\xda\xc3\xd2\x91\x19l\xc1\xc3\xfe\xf82\xdb\xfa\x12\xdb\xcav\xd0g\xb8\xb2\xd8~\x1e\x19\x00;\x83\xadvc5\xa3\xa9\xdb$g\xed\x95:L:1_\x9a\xcf6e\xad\xdd\x14\xb6M\n\xa3\x0e\xd2O\xa3\\M\x973\xab\xa1\x91\xe4[\xb0\xeea\xdb\xae\xf6\x1b\xc7\x8a\x84\xb7\\\x10\xd5\xb30\x10Wd9g[=Z\xa9\xe0B.B \x10c\xcc\x99\xb8\nkx\x17\xd4\xe5\x8e\xbb\x84\x95\x8f\xf9\xc4W\x12m\xbeX\xb1\xa6\xf5\xc0\xdd\xde\x16G\xe8\xdc\xea\xb9\x88\xea\xdbZ\xd1VGK%{\xea\x8b\x84l\x12\xb2\xa3\xab\xb8\x98\x85P !\x9b\x84l\xef\x91$dK#!\xfb\xd0H\xc8&!\xdbg$d\x93\x90-\x8d\x84l\x12\xb2I\xc8&![\x19 \xd9$d\x93\x90MB\xb6\xcfH\xc8&!\x9b\x84l\x12\xb2-+!*\x92\x90-\x8d\x84\xec?\x8b\x90\x9d,\xf8\xb6\xed& \xf7\xb6\xedf\"\xf4\x8a\xc3'\xda\xf5D\xdf\x15\x87\xeb\xbf?_Yw\xa8\xb0mSQWT\xd2N0pP\xeb\xd1\xbc%\x80\xa8\x8e\xd3\xb4|\xa1\xa2i\x17\xa1\x0c8\x91\x95\x8cc_\x90\xe0\x08$8FW\xdb0\x0bV@\x82# \x8e\xde#Ip\x94F\x82\xe3\xa1\x91\xe0H\x82\xa3\xcfHp$\xc1Q\x1a \x8e$8\x92\xe0H\x82\xa32\x12\x1cIp$\xc1\x91\x04G\x9f\x91\xe0H\x82# \x8e$8ZVB\xfc!\xc1Q\x1a \x8e?\xaa\xe08\x8f7t\xc9\x8eC\x8e\xe41\xca\xb4\xdal\xc6\x84\xbd\xbdYY\xe4K\x95\x99Yf\xa2\x9em\xc91Q&G\x8f\xfa\xd7g\xabO\x86\xe21\xf9\xef \xfd\xa8fl\xbbE\xb5Zu\xac\xf7\x1c\x85X\xffX\x8a\x06k\xfa}\xbf\xd8\xed\xaf\xef\x98w?\x8aHy\x01Qf@HV\x80)\xb32\xcc\xd2\x87\xb1T\xf9*\xe8\xcc\xbd\x86\x11\x98\xd2\x97\x96\xb1 .eA\x86\x9c\x15\xae@\xc5o\xd1\x92\x16\x94\x92\xb5 S\xda\n:\x14\x8d\x8b\x96\xb7\xe0x\x89\x0b\x92e\xae\xa0+\xbd\xfc\x9e$uAi\xb9\x0b\x12%/H\x95\xbd\xc2={\x90\xc4\xb0\xd2\x17\x94\x96\xbf\x00'\x81AI\x19\x0c\x8e\x96\xc2 O\x0e\x83R\x92\x18d\xc9b\xe1\xc7\xc1\xca\xdb\x1f\xa9\xc2 \xe418\xa1D\x06\xa7\x91\xc9 Q*\x83<\xb9,6\x04\xe3$3(+\x9bA\x82t\x06\xe9\xf2\x19dHh\x88!\xf3\xaf\x08\x19\x0dJHi\x10\x93\xd3\x00?=C\xc8j\x908\x8bK\x96\xd7\x82\xde\xa4\xf4\x86\x90\xd8 \xa1\x94\x05\xa56H\x92\xdb\xa0\xb4\xe4\x06\x99\xb2[\xb8_\xf5q\xe9\x0d\xf2\xe57\xaf?q\xc5\x98\x04\x07\xc5d8\xc0\xabI\x80\x91\xe3 M\x92\x83\xd8\x1az\xa64\x07\x08\xbf\x81e\xbaB2\x1dd5.^\xae\x03D-3d;\xc8\x95\xee \xb2-t1 \x0f\xf02\x1e \xa5<@\xcby\x80k\xf5tY\x0f\x92\xa4=\x08\xca{PJ\xe2\x83T\x99\x0f\x8e\x94\xfa\x00\xd1\xbc \x92\x1f\x9cB\xf6\x03L\x19\x03OB9 \x1002 \x1c!\x05z\x1d\x8a\x03Cr \x94\x96\x04!*\x0bB\xae4\xe8\xf5\xa6\xbeQ\xc3\x9f\xeb\x08\x89\x10\x82J\x06\x04\xa5B\xc8\x92\x0b\xbd\xae\x822\"\xe4J\x89^oj\x1e\x18\xdaM\xb0\x98\xa4\x08(Y\x112\xa4EH\x93\x17!Gb\x84d\x99\x11\"o[\xc4\xee\xfcX\xf9\x07+9B\x8e\xec\x08\xa9\xd2#\x84+\x9e#Az\x9dY\x02\x1f\xf6\x91\xc1I\x91\xc1\x07\xa2Y\x87\xe5H(+IBL\x96\x84\xb04\xe9='W\xb2\x84\x82}7A\xba\x84$\xf9\x12, sj\xff\xac\xea\x0d[\x85\xd5\xa9\xeb\xb6\xdd0\xcf\xd2\xb1R!\xb3e2\x00\xd6\xec=\xc9E\xc1\xb1\xd9\xff\xd5\xe7\x0f\x17\x97?]~x\x8f>C\xed\xd8\x9ft\xf8\xe5\xc7\x9f\x91\xc7\x07\x9d\x9b\xc0\xc0\xc4*L\xd6D\xfe\xdb\xbf&\xf2\xaemVW\xb2\xf5\xc5H\xc1U^b\xf1/\xf1\xa6\xb5\xf7\"\xf6\xf7\no\xeb\xbe\x01\xeb\x1fc\xb6\xe7\x06\xeaF-\x11\x8d\xbb\xc9Neh\xc4ET\x9b\x89+\xa8\xffr\xee(/\x87%\xbd\x0e\xa9b>\x13\xafp\xf9\xf1gs\x89\xcb\x8f?\x07\xaf1\xa4\x16F_\xc2T\x01Q\x81P\xe1CQ\xac\x88gg\xd8>x\xa1\xb6\xa7=\xc2\xd1\xd8\xe3\x82>\x8e\x96\xa9\xb7mS\xdf1Gx\xeah\xd1\xd2\nS\xaa2\xf7\xaa\xea\x80u\xf4\xc0\xae\xfb:\xbc\xdd;\xcaO\xcf\x96\xfb\xae\xe6O\x0b9 \\\xf2\xa3\x1dz\x03bGC\xf8\x99\x8c%\xef\xc7\x7f8\xbb\xacu\xb0\xbb\xbf\x8e9\xb8U\xba\xf7\xec\x0e\x17O<\x8dK\xf8\x9dt\xa9\xf0\xf6\xf1\xe3\xce\xef'~\x04\xc6\x0b-\xe4\xb6\xfc\xf1;\x1c\xbc$ /+L\\/\xb6\xa8\x83hPe\xdb\xeaqQ\xdc\xa1\x92\xcdJ\xfa\xc5*\x0c\xc2.\x86[\xf3E\xdc\x99IR\x04\xa9]W\x1b\xeb\xf6\xc9\xe6\x0cKbJ\x93\x1ct\xb4e\xc7\xe4\xee\xef\xe1\xc9\xe4\xe4\xdd\xed;h\xbf\x13\xdd9\xf8h\x00\xbe\x91p\x8f\x08\xbe1\xc7\x86\x1c\xda\xd0j7k\xc3\x00\xd1*\x95\xe2\xd9\xbc\xce\"\xad\xb1\xad\x9bE\xcf67\x8bq\xaf\xfa\xcc\xc1\x02S\xbb_\xad\xd1\xf2`\x04=\x03\xde\xae\x99\xd4'\xe5Z\x82\\\x07\xf0n/?\xee\x85\xef%<\x86\xab\xbd\xec'\xdb\xeak\xec\xbd\xee\xa6[\xcdK\x9d\xbf\xad\x1b\xcfl\xecjS\xf5\xb7\xe2{\xcdD\xc5\xfa\x08\xa1\nVL\xf4\xd5\x91e\x99\\\xe6Lq\x05R\xe6n\xbb\xce76\x99m\xf6\xf5\xca\xcc\xcd\x9e\xef;O=\xf7\xcdx\xf3z\xd9v\xed\x9eC\xcd%\xd2\xd8\xac\xa1\xbdg\xdd8\xdd\xe9\xcf\xe1\x1f\xb7\xacQUuW\xa0c\xe6pI?\xb8\xaf*ew\xfb\xe6\xdd2\xebmX\xf7\xe2y]\xd5\xdch\xbf\x15\x8c\x85t\xfa{\xb8m{\x06\xcd~{-\x85R\xf7E\xed\xdbX\xf7\x13\xca\xc2\xea\x11\xb2jc\x15\x9c\x9eV\xf5\xb0\x0c\xab\xbe\xa5%*\xe0\xbe\xea\xe4\xfe\x9d\xc3\xaf\xadl\xd6]\xfb\xc0:\x19\x0b\x7f\xcd\x86\xdb\xc5Vri\xd5\xdbm\xd5\x84VW\xc1}\xb5\xed~\xc3\xeb\xdd\xa6V\x85\x9b^\xfb\xe0\x84\xc9Sg1\xaf\xa3\xd8\xab\xf7\x19Ql\xac\xf5\xe9q\xd0\xcdw\xd5\xban<#\xc0l\x1f\x13s\xe04\xf1\xcd\xf8g\xdd\xef]\xe4\xab\xb2\xe0\xab9\x92 \x87=\xf2\x85\x17 \x8d\x0e\xd9Q\x00\x80\xd7|\xc3\x02\x9f\x8e\xe6\xfa\xe6\xb3Q\xfc\xa7\xa6g\xaa\xbeW\xb8\xd0\xe7j\xcd\xbe\xb0\x7f\xedY\xcf\xcf\xd5\xef\x1eg\xe3v?\xc2\xadhB\x06\xdb\xb6\xe7\xc0$\x83\"\xe1\x15\xc7\xa9\xb2\x7f\x1d\xd9\x00{\xff\xe4Q7\x81\xf7\x15%//\xeb/\xffcxf\x87\xa1\xd1\x8aN\xf7\xc9\xdfv\x13-\xc5\x83\xbbP\x0f\x8d\xe7\xf0\x87\xaa\x87\x9e\xf13\xa8yo\xa0\xaf^\x8e|\xa2\x03\xae\x14\xd7\xf2P\xf7\xd3{\xea\xab\x88\xe4\xceG\xcc\x1b\x9b\xc4\xe8\x00\x0c76&6\x1a~\xa0\xbcF\xb3_)\xaf\x11n\x8e\x04\x19`\xb8\xea\xac\x94\xd7\x08\x01\x81\xbbt\xc9d\x00<\x07\xfe\xa6\xbcF\x05A\xef\x14\xc8; \xf0\xa6\xbcF\xc7\xc2\xdc\x19 w\x11\x88;\x1d\xe0\xa6\xbcF\xc7\x00\xdb)\xb0v\x06\xa8My\x8d(\xaf\x11\xe55\xc2\x82\xd6E!\xeb\x1c\xc0\x9a\xf2\x1a\xf9\x0e\x8b\x82\xd4 \x105&kO\n\x8f\xe2\x91;\xd7OS\xbdn\xdan\xb6\xe4n\x9e\xc6\xe9%T\xcb\x1c{c\xa7A$\xbee\xb8\xccn \xce\xd0Y\xddP>q+\xe6P>\x9f[F67D.7T&7T\xc3`:?\xb6\xf9\nfp\x0b\xb6\x00:{\x9b\xb7\x05p\x19r\x92\x13\xe4\xcc\xbcQ~\x1ce\x94\x1f'\xf6\xea\xc6<]\x99\x88\x17\xe5\xc7\xc1\x80]E\xb0\xae\x1c\xa8\x8b\xf2\xe3\x14D\xb9R@\xae$\x8c\x8b\xf2\xe3\x1c\x0boe\xa0[E\xc0\xadtl\x8b\xf2\xe3\x1c\x83k\xa5\xc0Z\x85Q-\x1c\xa8U\x10\xd3\xc2BZ<\x0d\xd1J\x05\xb4(?\xce\xc4\x92\x91,\xca\x8f\x83\x02\xb1r0,\xca\x8f\xe3;,\x8a^%\x80W\x98\xec/)\xd0\x15\xe5\xc7\xa1\xfc8\x18\xb4\x8a\xf2\xe3H;\x06\xa6\xa2\xfc8.OQ|*\x17\x9e\xf2\xbe\x1b(?\xce\xa1Q~\x9c\x0cH*\x8eH\xa5\x02R xT2\x1c\x95\x86FQ~\x9c4\x18\x8a\xf2\xe3\x0cv\n\x00\xaaD\x9fK\x80\x9f\xf0\xe8\x13&?\xce4\x1d\x81\xe5\xca\x1dh/\x8f\x9ah\x91\x07\xa9\x07&Yt\xe6\x89\x17f\x8b\xe4c\xde\x05\xde\xed#\xf94Jf]xmm\xd9\x83\xc9\xc0\xf0\xde\xda\xe1\xc7$c0\x1b\xdcxs1\x84s0X._\x98\xc6x\xa6\xe9\x18\xc6\xc6Z8\xcah\x8c\xff\x0e\xa2WLx\x8d^\x00\x10\x17\x81 \x98\x14\xcc\xfa\xa0\x0c\xb1\xce\x04\xb3G\xaa\x84\xc7\xf0F\x9a\x80s\x83YC\x126v\xdf\xf1\x9d\xa0\x06\x04\xb9I\x94\xdaBL\x82`p+&2\xd7\xe2K\xd9\xeb\xadZ\xcaT0:\xbd\x8b\x7f\xa8m\x1f\x1a5\x8do\x1b6\xde\x13\xbdt*\xc5\x83vYW\xc3\xaeW\xa1\x05\xf2{{\x1b\xa9\xf6Fx\xf4_7\x02B\\W\x9b\xaaYF\xd6\x1d\x0b\xf4\xc1\xa6\x0d\xec6\x8c\xba\xbdf\xe7\xb6#\xdd`{\xc9E[\xdb\xd8\x96\xec\x10\xe3\x86dM\xbb5\xa9\x82\xc4\x0d\xac\x1a]\xb8\xd0\xa2\xf4\xc7O_?\xbc\x91\xd3{\xbd\xe1\x98\x9a'\xd7r)\xf3\xb2\xe1z\x061,\x1f\xf7\xc1N\xa0\xa7\x17\x1a\x8e\xf0?Y\xf5\xba\xa9\xf8\xbec\xfd\xf0\xc6\x12\x9dp\xdd\xae[\xf9\xee\xce]\x8c\x1d\x1f\"\x1b\xf1\x10W\xb8\xaf62MXk?h\xecq\xc9v*\x0f\x99\xd3]\xcd\xad\x85]wmtO\x9d\xcf\xa5\xf4\x9en\xba\xedz\xd8\xb6\x1d\x83~_s\x93\xd6\xc9\xe9l\xb9\x91\xb9\xcc\x86w\xc2\xbc\x19hK3i\xb4\xa5\xd9\x9fnK\xb3\x83{9\x05\xb6\xac\xb9]\x94\xddr9z\xed\x9cx\x12\xc6\xa5\x8c0\xae2/g\xc2\xb8\x08\xe3r\x1ba\\\xd2\x08\xe3:4\xc2\xb8\x08\xe3\xf2\x19a\\\x84qI#\x8c\x8b0.\xc2\xb8\x08\xe3RF\x18\x17a\\\x84q\x11\xc6\xe53\xc2\xb8\x08\xe3\"\x8c\x8b0.\xcbJ 5\x84qI#\x8c\x8b0\xae\xe7\x84q\xd1>g\xb9\x9bH\xd1>g'l\xdc\xf8\x0e]\xb4\xcfY\x89V\xa4}\xce~\xcc}\xcel\xe2\xf6\xf5oS\x9c2\xb4 \x9a\x85?\xa1\xc1\xdb\x91\x0c\x84]U\xbb9\xdc\xd1\xef\x0b\xd34\x7f\x1c\xfa6\x82S9\xd7\x8c]\x10\xefd\x060\x1e\xa0\x1aV|c\x05\xfd\x14\x85\xb0b$o\xd05D\xddC\x1a\xc3\x8b\x90\x18\x12\xf8]\x84\xb7\x18\xbb\x1bu\x11\xef\x00P\x98\xda\xc51\xbb\xe9\xc4\xae&s=\xfe0\xbcn\x90\xd6\x0d\xb2\xbaEzY\x90\xd2\x8d\xde\xc88\xa1\x1bu\x81\xeb\x0b\xa5\xd9\xdc\x92d.\x8a\xcbM\xa3r\xc3\x8d\"_mn\x1c7\x94q\xed\xe0-bld\xf5\xc6R\x10\xac7\xfb\x95`\xbdX\xb7\x1c\x8d`=\x82\xf5\xdcF\xb0\x9e4\x82\xf5\x0e\x8d`=\x82\xf5|F\xb0\x1e\xc1z\xd2\x08\xd6#X\x8f`=\x82\xf5\x94\x11\xacG\xb0\x1e\xc1z\x04\xeb\xf9\x8c`=\x82\xf5\x08\xd6#X\xcf\xb2\x12\xe0\x14\xc1z\xd2\x08\xd6#X\xefy\xc2zS\xf1\xdcW\xe6\xe9Q.\xbc\xe0\xf4e\xfen\xd4\xca\xebq\xd7\xb7\xf1\xb0\x00\xcab\x91\x8c\xdf\xcc\x99\x0e\xbce\xf0\x8a\xe0[\x06\x87^\xce\xc5q%}\xd8\xb3\x05^T\x03D\x18\x17u\xd0\xa4\x87M\x1b\xae\xdb\x8e\xb3\x8f\x13C+1\x06$\xb2\x06\x86$I\"^X\xc3\xbb\xa0P\xe9\x13G!$\x90B\xac\x81\x94\xc5\x84Raj\xcb\xb9\xb6 \xee\xc4\xa8\x0c\xb1h\x08\x88]\x19\x95-[\xf1\xda\x91W\x0e\xefS\x97|\xdd\xf0^u \x872\xb9Q\xdf\"\x92 \x0e\xb0\xd7.\xe3\x07\xb3f \xeeQ\xeaC\xc3\xbb'{\xc7\xdc\xf1\xa1\x8b\xec\x03)\xd7*;\xb6a\xf7U\xc3\xc5wU\xb5\xaaxuJF\xc3u\xfak\xd7x8;\x90\xd8\x0dm\xc4n\x94y\x8e\x88\xdd v\xc3m\xc4nH#v\xe3\xd0\x88\xdd v\xc3g\xc4n\x10\xbb!\x8d\xd8\x0db7\x88\xdd vC\x19\xb1\x1b\xc4n\x10\xbbA\xec\x86\xcf\x88\xdd v\x83\xd8\x0db7,+\xa1\xa3\x13\xbb!\x8d\xd8\x0db7\x88\xdd8\xae\xccE\xd9\x0d\x17\x9e\x11\xda\xed\xcfZ\x01\x18\xf6_q\xc8\x85\xbd\x83\xd4\xb0.0\xcd\x9b\x81\xdc\x0c\xd0u\x19}\xc23\xc74D\xf3>\xcfM\x01c<\x05b}\x0bIf <\x05\xe9\x8c8\x9f\x11!4\xa2M\xa6,\xd6p\xca\x128\x0dD\xc5\x8d\xe1X\x8d$Z#\xe3\xeaqb#\x89\xd9@\x97\xa0\x9c/\xcc\x9a\xa5\xb2\xa2\xf4\x06\x8e\xdfP\x86)\xa2\x0b\x80\xeby\xdb\x89bm6\n\xda\xea\xebf\xbd\xb1^>/\xdd\xeb\x91c\x1d\xc4\xff{\x12\xd1\x88y\xcb\xe0q|\x05\x8b)R\x03\xa2C\xbcj\xbb\x15\xeb\xd8\n6u\xcf\xe7\xb5\xa2\x8d\xec\xa4\xd1Fv\x7f\x9e\x8d\xec\x10\xa8Upv\x12\xa4\xaff\xde\x1cz\xfel\x9b;\xe74\x8b8,m\xc4a\x11\x875\x1aqX\xc4a\x8dF\x1c\x16'\x0e\xcbm\xc4a\x19#\x0e\x8b8,\xe2\xb0\x90\xb3$\xe2\xb0\x06#\x0e\xcb6\xe2\xb0\x88\xc3r\x18qX\xcec\x88\xc3\"\x0e\xcbc\xc4a\x11\x87E\x1c\x16qX\x96\x95`b\x88\xc3\x92F\x1c\x16qX\xcf\x93\xc3\xa2\x0d\xef\xd2v\x13\xa3\x0d\xefN\xd8\xb8\xf1\xad\xdah\xc3\xbb\x12\xadH\x1b\xde\xfd\xf17\xbc3\xf4)\x7f\x1c\xc0\xd3\xbe\xde\xee7\x15\xd7k\xb6\xbb\xb6?\xe4I\xaf\xf4!`\x8e\xed\x81=\xb2\xe5\x9e\x8b\xc1\xa1\x02\xdeUM_\xc9e9\xf5\x99\xd2\xf3z[\xc9\x1f\xd7\x95h\x15\xf9\x10(\x9f\x13j\xd4\xf8}a\xaa\xf8L\x01\xd1u\xd5/\xea\xe6\xa6\x8d0S\xe603z\xd8\xc9\xbb\xaa\xebv\xcfus\x8c#\x86n\xcf\xd2\xd9\xbcDA\x1e\xaa\x863G\xee1\xc0,\xc3#\xf8!\xccR7\xc0\xcfU\xff\x0fY\x10\xd3&\xdb\xea\xb1\xde\xee\xb7\xb0oj.\xd7h\x1f\xda\xee\x0e\x1e\xb4\x16\xa7$ \xfe\xe8\x87\xa9v\xac\x13\x85s}r\x89Z\x8b\xc6\xfdNu\xfe\xb9\xea\xbf\xf5c\xc5\xf4Va\xed\x8d\xbc\xc9\xd5\x92+\xd5|\xd96ZN\x9d\xbaR#]\xa4C\xe9\xe1\xb0\xee\xed\xc1\xd1,\xd7\x9f\xa6\xeb\xac*^\x1d\xd9\x80^\xe5\x06\xd7e\xdeW\xbc\x92\x93\x9b\xe6I\x96f|\xcd\xdetr'5\xf5\xad u\xd5f\xb5\xf1H#`F\xa8\xb6\x91#\xf2\xdf\xbf]}\x0d\x08_\x1b\xd6\xac\xf9-\xec:vS?\xaa\xe7Sb\x94\xe25\xd531}\xe7L\x95F\x15b\xbf\xe1\xf5n\xe3\x93\x8aL\x19\x87\"8\xb5\xb2M\xbb\xceli\\C\xfe\xd2\xae\xa7\xeb\x15\x9bv\x9aP0\xb7=\x1d\x07\xb0{\xd6\xf0g\x9c\xb2O\xba\xf1\xfe\x8ahra\x15\xe7]}\xbd\xe7a\xea\xf4\xa3\x05\x95\xe1\xd1Nu\xf9\xbaY\xb1G\xec\xe5\xa7\xb3)\xb7\xe1\x9eBc\x1f\xc4\x13\xf2\xd6\xf4 \xf5\xf5\xa6)\xee;\xf6\xf4JM\xf9wU\xdd\x85V\x1e\x84\xcd7\x1a\xad\x1a\xf5\xf4\xf9\x96\xe9\xb1\xc5\x94\x05T\xaf\xe1^|i\x18T\x06V\xec\x9emD\x0f\x93\xdf=\x15\xe7\xf2SdX'\xf5:\xb4\x87\x1a\x1e\xd0X\xcc\x87\xff;\xf1\xad\xffn\xd3.\xef\xce\x86\xbf}hV\xb3\xbf\\\xdc\xb2\xe5\xdd\xd7G\xffC\xda\xac\x86c\xdf\xb3M}\xcf\xba\xaf\x8f\x01\xad\xec\x97\x8a\xb3\xee\xcc\x9e\xc3\xf6\xb0\xad\x9e\xc4\xa7\x97\x8a\x8eZ\xe9\x8f`~\xcbz\xa6\x07:w[\xe3ZZ\xb6so\x01\x00\xd0o\xea\xa5\xfc\xacV\xb7@=\xf1\x9a\x99{`\x1d\x03\xb6\xad9\xf7\xf2;\xab\xbd\xa2.\xd5@\xee\xab\xe98\xbe\xfbF\xf2\xd0\xda\x0d\x0csu\x1b\x97\xe6\x16\xff\xaf\xd6?\xdd +\xafXw_/\xd9\xf9\xe0\x83xhe\xc4C\x13\x0f=\x1a\xf1\xd0\xc4C\x8fF<4'\x1e\xdam\xc4C\x1b#\x1e\x9axh\xe2\xa1\x91\xb3$\xe2\xa1\x07#\x1e\xda6\xe2\xa1\x89\x87v\x18\xf1\xd0\xcec\x88\x87&\x1e\xdac\xc4C\x13\x0fM<4\xf1\xd0\x96\x95`S\x89\x87\x96F<\xf4\x8f\xc0C_\xb7+\xfb\xddW7\x07\x7f\xf22\xcb.\xed\xe7\xff\xdf\xb1\x9b7\xf0\xf2\xff\xf7\xdaZ8\xd4\x14\xdc9\x7f<\xd7\x14\xdc(M\xa9tE/\xb5\x8f9G\xa7\x95,7I\xc7\x1f\xf5\xb1\xae\x9c\x8c?3\xfe\xf5\xb1W\n\xdf\x0d\xe3\xcb[1\xc8?\xf6\x92\xed\xb4\xe5\xdb g\x9d\xa4\x7f\xfe>\x8c\x1c\xb2\xd1\xac\xe2\x19Y\xf0\xe5\x8b\xb1\x14$\xe8M\x8c\x04=\xdc\x82\x10\x90\xa0G\x82\x9e\xf7H\x12\xf4\xa4\x91\xa0wh$\xe8\x91\xa0\xe73\x12\xf4H\xd0\x93F\x82\x1e z$\xe8\x91\xa0\xa7\x8c\x04=\x12\xf4H\xd0#A\xcfg$\xe8\x91\xa0G\x82\x1e z\x96\x95\x10WH\xd0\x93F\x82\xde\x8f \xe8\xa9\x909\xcb\xc5\xe4#R\xfdj\xa2\xc96u\xaf\xd6\xbc\xad\x94\x12\xf2\x88\x83/\xd2\x9c\x1c\x19s\xb9\xc4!\x94x>\xe0\x97\xedf\xc3dq~\xd2\x9f\xef2\x04\xfc\xa0\xae\x94\x18)-\xeb\x0c%F:a\xe3\xc6S\xfaPb\xa4\x12\xadH\x89\x91\xfe\xb8\x89\x91F\xa0\xc3\x93\xfb\xe8]\xd7V\xabe\xd5\xf3\xaf\x8fpm\xfe\xdb~?9\xc1\x0d\xeb\xac\x17\xa6\x98\xdf\x03\xdc\xe0\xe9`\x04\x7f\x1c\xb6\xbd<\\\xb0\x98\x94\xc8:\xd2\x8c\x03&D\xfe\xeb\xa3yK9V\xcd\xbd\x85\x82(t\x10\xda\xb91\xba\xd6~\x13\xdd\xa9Qo\x82&>\xe5\xae7\xed\xf2N_\xcfq,\x7f\xbc\xad\xfa\xdb\xcc\x82LZQ\\\xcc\x9e\xde\x08\xbf\xae\x0f\xace\xbbb\xfd\xae\xf2\xed\xb5\x18\xbd\xa8\xae\x9b\xf8\x18\x90nLl>\\\xb4+\xd7\xb4\xd6\x8d\xbb@\x14y\x01TKO\x9a`\xc8! \xae\xe9\x94\x19\xf2\xb3\x10M.\xf4\xf2\x8b\x1a7\xc54\xa3?3+u/\x1d'v\xd5\xc3\xe2\xd4 y\xc4\x9do\xf7|\xb7\x1f\x06e+\xcd\xc6\xcb\x1e6\xedz\xcd:\xf8\x8f\xaez\xd0\x17\xfb\xeb9\xfc\xdd\x9bF\xc6\xafr5m\xf3j%f\xe3\xdb\xba\xa9{^/]m\xbci\xd7\xcf8a\xcf\xb6_/\xa2\x19[\xe2\x1dSY\xbc{B(\x1f\x93\xb2h'\x80H\x1e$e\xb1\xc6U\xf6\xfb\xa4\x07\x92.#\xc7 \x1bB\x19.c\x922\\\xc3(C4\x8f2t#)\xc37\x952T>%e \xad\xa6\x0c\x99.IY\xa2w\xdcx5\xb51w\x91\xb5\xed\xeep\x83\xe1\xa1\xabv;\xd6\x89\xa9\\\x17K\xc5\xa4\x8c\xeb\x8dU\xabf\xa5'\xf6U\x17\x10\xeemS\x15\xed\xa1nz\xce\xaa\x95\xfc\x02\xa9\x1e\xd40\x1fX\xcdO\xae\xf9\x95\xbc\x8e\x82vM\xadY3\xc9\xd3\x93Tq\xc9\x8b\x89q\x7fx.b\xf55\x94\xe1\x1d{z=\xe6\x88\xd2\xbcY\xd5\xb1ySD\xdca\x1b*\xa5\x99\xd2\x13\x1a\x05\xdd\xe9dG&\xadQ\xdfn#\x9d\"\x98\x98\x0e\x12*\xf3\xf6\xdd\xc5\xe5\xdf\xd5J\xdd/\xedz\xec\xe6\xa2\x8d\xf7K\xbe\xef\x98\xa9\xa4\xcc{\xda\xa8\x94b\x01\xec\x88?J\x9f\xc3\xf2\xdf\xa6]\xbb\xcb\x88+!v\xfe \x06\x83\x95\x9a:\x88I\x82\xdb\x19j\x8e\xe0Nz\n\x98\x01g\xfa-3\x8a\x0eVV0SB\\Y\x8a%5ENR\xdfN\x12zv*.\xc0\x00S\x87\x9f\x7f\xb6\x15\xcaD\x9aUP\x93p\x14\xae\x9fb\xc5\xe4\x9e\xc9\xd5\xc1\xe7\x8a\xae\xfc\xe4\xb3%0\x84D_\xba\xf1\xd7,\x8f\xa0\xe6\x88V\x04\xf4s\x05\xb9\xc0y\xc0\xdf\x01s\x14\x1a\xc3\x8aB\xe7Q\xec\xbc4x\x8eG\xcf\x0b\xc1\xe7y\xf8y\xc0\x9dhP4\x80~4\x82^\x1aBO\xc4\xd0\x0b\x83\xe8i(z\"\x8c\x1e\xea\xc3\x03\xa6\x8e\xc5\xd1\x0b\x03\xe9($\xbd \x94~,\x96\x9e\x05\xa6\x17B\xd3s\xe0\xf4\x803\x89\xad\xc7\xf1\xf4\x93\x00\xea\xa7C\xd4O\x02\xa9\xa7a\xea\xc5Au,\xaa^\x14V\xc7\xe3\xeaj\x1a\x91\x00\xac\xa7#\xeb\xd1\xa1\xf0\xaf\x08h\xbd\x00\xb6\x1e]P@M\xa8\x10\xf0z\xca\xac+\x19`\x0f\xbd\x04\xaf\xdb{\x86@\xd8y\xbde=\xaf\xb6\xbb\xcc\xd99\xaev_\xebqR\xb3\xeb\xd8}\xdd\xee{\xa51\x9c\xc3ObD\x92BC\x0f\xff7\xfc\xe7\x19\xd4\xfce\x1f\xa8\xdd\x83\xe6;/\xe5+\xaf\xf07\x1e\xee\x0b\xaf\xe0\xf7\x1d\xf6\xeb.\xf1\xdb.\xf5\xcb\x8e\x82\x91'\x96\xfc-G\xc1\xc8\x14\x8c\x0c\x14\x8c<\x1a\x05#S02\x05#S0\xb2\xcf(\x18\x99\x82\x91)\x18\xd9\xfd\x80P0\xf2\x81a\x03C)\x18Y\x1a\x05#\xff\x08\xc1\xc8\x85\xb3\x0b{E\x8c`\xbc\x95d\xe7\x92\xa4\x97\xc8\x97\xfa^`\x8e{\xeb<\xd0\x88\x81)\xa5\x8d\xaf5\x0c\xf2\xe3\xdf\xdb\xd5\xa8C\xab[0\x06\x0e\x8a\xd6\xf6\xe8\x98\xc2\xbe>\x1e\xa8\x99`\xef\x96\xea\xea\xfb\xa1V\x7f\x03\xff\x9bu\xad\xde]X>\xfc\xe2\xfarks\xcf\xb8\xe5\xbe)\x07m%\xffj!\xd2\xdc\x8a\x8e\x94\xaa\x94\xb8\x8eD\xe2\xd5\xb8\xb6\x91\xa1\xd3\x0fU\xcd{\x8f\x94 \xdf\xf1\x8fz\x15u)Ui\xaeB\x88+-W\xa3\x8a+\xee\xf8Ai\xc5\x1f\x8b\x16\xb6\x02\xbd\x0f\xf1H\x9f\x8fZ\xb5\x98\xb0\xe2\n\xfb\xd6Y\xda\xb7Y\xc5UA\xd7\xae5\x9fz+\xc1\x01\xce\xe6\xc5\nw\xea\x89,\xaf\x00\xe0A\x95\xd7^\xdb\xdd\xe1\xcb\xe7\x8b\xf93OA\xe2\xa4\xa2F\x97\x101\xabp@**\xa9\xa8\xde#IE\x95F*\xea\xa1\x91\x8aJ*\xaa\xcfHE%\x15U\x1a\xa9\xa8\xa4\xa2\x92\x8aJ*\xaa2RQIE%\x15\x95TT\x9f\x91\x8aJ**\xa9\xa8\xa4\xa2ZVB\xd1\"\x15U\x1a\xa9\xa8?\x82\x8a*\xfe\xd7r0\xf9\x84\x94O\xa2V\xa2\xecEh\xa3,J\xe5\xcb\xa8\xaa\xe2\x15a\x0fE\x85\xf5\xd3\xff\xa9\xb7B\xf5\x89\xa7z\x8dF\x8a\xa7~\xd1\xf4B\x1d5\x11MU7\x93\x7f\x9fh\xa5N}\xd4r\xf0\xc2T\xea\x99\xea\xa3cK\xd86)\x8a\xbc\x81u\xbc F\xf3\x96\x03\xa2\x12\x95\xeco\xce\xbe\x1a]\x97\xc1,l\x00\\1n\xf5U\xb3\x05\xa8\xae\x8f\xd6\x88\xe4Of\xd4\x92\xabM\x9e\xa9\x1f\xd8'{%)\xbd<9,b\xb47\xfc\xa1\xea\xe4\xb6\xcd\xe2!Q_\x87r\xe1\xa6\xda\xc0_\xda\xe6\x95v\xe8{f\x97\xedv[5\xab^\xef\x08\xe6\xbb\xac\x9c\xf8\x89\x97\x0f\xbcc\xeb\xbay'\xb5i5=\x1c\xa7}\xc3\x9d\xac=\xd2\xf4hj\xb7\xe2j\xd3K\xe9\xc3[[\xde\xc2\x8aq\xb9\x11\xdc-\x93\x8b\x82\xd5Xe\xd3\x14\xcb\xaa\x81\xdb\xaaYm\x18T\xb0\xae\xef\x99o\xa1t\xb81R\x17\xf0]\xd3TB\xb9\xec\xd42\x13\x1fn\xa5x\xbf]3\xd6H\xd5\xa3\x0e-\x89\x9b\x82\x9e\x0d\xdbm\xfb\x17\"\xb5\x081\xeeI=\xd4\xb2\xee\xa1\xdd\xf3W\xed\xcd\xabU\xc5\x99\xda\xcc\xd9jk\x8f?\x95!\xbf\x83\xbf\x19\xa4\xc0w\xe1\x8eU\xcb[\xf1\x1aU\x9f\x08\xe3ue\x81\xd9\xa3;{=\xaf\xb3\x9f,\xb3\xde)j\xf3J\xf89\xe2\xf9\xfb\xaa3\xf2\xeb.8\x12\x12\xe6\x1en\xf5\x8a\xe8\x8eu\xe2\xba\x01\x95\xe7\x17V\xdd3\xb3Wx\xcd{\x99\xdaa\xdc\x12]|\xfcH\xd6\xe5\x95\xca\x1c\xb0\xd2-\xeb\xf1\xa6\xf7\x0bt5\xdd\x897]\x0eo\x06`L4\x9c\x8b, \xb4\x9b\xdb\xd1'\xfde\xb8\x12\x1f\xe2\xb2\xd3i1a\xb6\xb7\xb8\xb1#\xf6\xbc\xd3[.{;\x83\\\x1a\x1b\x15\xafq\x01\x7f\x18\x95\x9a\x9bVKDzOw\x9fB\xd46\xaf\x96\xb7\x95_\xf0\xee\xf7\xcb[\x85r\xadk\xae\xd3i\xa8GW.\xbcW\xbc\xedzXJ\x9d\xbb\xda\xf3v[\xf1z\x19PPM\x01y\xeb8\xc0\xbc\x10\x16*\x13\xc5\xa2\xe7\x15\xf7={\x91\x16\xba|w\xf1\x8a5\xd5\xf5\x86\xad@\xd6\xaf7\n\xef\xabZN\xabT\xb3\x88\xef\xa2\xc9\xab\xc8\xedMg\xc6\x90\xe5\x11\x03\xa1xh\xecW\xb9\xaf\xf1\xe4[Q\x8e.\xdb\xeaN'\xd9\x10\x85\x19\xdaQI\xed\xcb\xb6\xeb\xc4\xc0\x1f)\xc5\x7f\xf4ls\xf3\xd7ia\xae\xa5R8\xe9\xd0\xedr\xb9\xefz\xef\x0e\x1b}\xabn\xdf\xb2m\x1a\xb6\xe4Z\xc53\x0dt\xcf\xba\xfa\xe6i\x1c\x9b\x1b\xf6\x10+\x96.O\xddk)\xe6\xfaI{\x91\x9b[\x8ayK{c\x04U\x8f\x8bac\x93\xd9+_\x16\xcc;\x8e\x8d\xad+\xc5^q\xcf\x87Z\xb5\x8dT2w\xc2_\xcf\xa1\xdf\xb6-\xbf\x15S\x86e\xd7\xf6>\xb1O\xdc\xca\xc6t\x18Sm\xf7\xc1\xc1\xa9\x1aD\xa7k\x80`\x8a\x10\xe3\x04\xa0_\x1f\x90K\x16\x05\xfc\xd1\xd6\x84Ns-\x1c&SFy\x9cQ\xc0\x1dmM\xa8\x87\xda\x0c\xe2(\x8d9J\xa4\x8eB}x\xe0\x91\xb0\xdcQa\xf2\x08\xc5\x1e\x15\xa4\x8f\x8e\xe5\x8f\xb2\x08\xa4B\x0cR\x0e\x85\x14pF[\x13\xa2i\xa44\x1e\xa98\x91\x84e\x92\x8aRIx.)\x99LJg\x93\xa2C!mM\x98@*\x85^\x82\xc8\xad \xb1\xe5+\xc8+\xa5\x10K\x85\x99\xa5\xbdzf!\x9a)\xbd1\xf1DS\xacn\x19TS&\xd7\x14\xd2\x85\x8b\xb1Mh\xba \xc77a 'D+\xa7SN)\x9cS\x88t*\xc4:%\xd2N\xc7\xf1N\xb1\x06M`\x9eN@=EK\xe7\xed\xe9\xe5\xd8'\x04\xfd\x94\xcf?y\xdc\xc95\xc2\x00\x01U\x98\x81\x8aQP\x99\x1c\x94\xc7\x97\xfa2\x0c}\x1c#X\xa8\x10\xb0\x11\xe2\xa1\xca\x13Q\xc5\x99(?\x15U\x92\x8b\xc2\x90Q\xe9lT\x12\x1d\x95\xc1G\xa5\x12RAF*L\xac\xe0\x99\x15,'\x95AJ%\xb2R\x81\xea\xe6\xf0R\x1eW\x16\x8b\x84{$p\xccT\xa0\xcbKu\"@M\x15\xe5\xa6\"\xe4\xd4i\xd8\xa9R}1\x81\x9fJ!\xa8F\x86J\x19\"\x9a\xdf\"\x84\xf2\xa3\xf9mN\x89\xa2\xf9)\x9a\xdf\xf9;E\xf3[F\xd1\xfc\x14\xcd?ZQm-EYK\xd2\xd5(\x9a\xffX5-CK+\xa2\xa4\xa5\xebh\x14\xcd\x7f\x8c~\x96\xa2\x9e\x15\xd6\xcep\xcaYA\xdd\x0c\xab\x9a9&\xc4\x14\xcd?5\x84N\x86\x9d%%kd\x14\xcd\x8fR\xc6rt1\x8a\xe6\xf7\x1d\x16\xd5\xc2\x12\x940L\xacz\x8a\nF\xd1\xfc\x14\xcd\x8f\xd1\xba(\x9a_\xda1\xea\x16E\xf3\xbb\xa1*\xf20\x94j\xdc\n\\\xfc\xa6}]\x18WW2\xc6k\x12Ko~\xd2\xf1_\xb2\xa7\xc9\xae%W\x8e\x06W\xb2/\xf3n\xdf\x8b\x0f\xad;\xd65l3\x04m7\xec\x91O#\xad\xea^\x87Z\xc1\xa5\xf6&_\x9cV@I\xcf\xdbN\xf4Y\x15\x15&\xdf\x88:\xa8r\xea V\x97/\x9f/T\xcc\xa4\xfa\xfe4K\x18\x1b\xb6\xae\x96O\xba\xa6\xe6\x13z\x92\x1b\xc0\xedO\x1f\xf9l\xd3\x04\xf8z\x87O\x07\xcb\x8a\xfd\xe7A9+\xba\x92\x83Y\n).d\xe1d\xac\x1c\x11+,VeIU\xf2\x12\x1e\x87Q\xa1\xaa\x80L\x95)R\xf9Y\x0b\x94Du\x94@\x95%OA\xe5\xe5\xbb8N\x9c\xca\x91\xa6B\x0b\xc6(a\xaa\xb0,\x85\x12\xa5\nJRQA\xaa\x90\x1cu\x8c\x18\x95,E\x15\x10\xa2\n\xcbP\x11\x11\xaa\xb8\x04u\x1a\x01\xaa\xb8\xfc\x84\x17\x9f\xf2\xa4\xa7@\xa3\xc7\x84\xa7b\xb2\x13Ntr\xccz\xfd\xe3ka\xc1)&7\x1d)6\x05\xa4\xa6\xe8\xf4$*3\xe1\xe6/e%\xa6\x98\xc0\x14/S\x9e\xb8dFv\x87\xc3\x98\xb4TPX:BVr\x8b\xc1!Q\xa9\xac\xa4\x14\x16\x94J\xc8I(=$\"%\xa1\x85$\xff\x9ao\xba\x88\xe4\xf7\xe5\\_)\"\x1f\xa54\x16V:\x8a\xb7 Z6\xca\x10\x8d\xdckQ\x85\x04#\x94\\\x14\x17\x8b0RQ\xb0\x15Se\"\xacH\xe4\x93\x88\n\x08D \xf2P\xbe8\x14\x90`\xb0\xc2PaY(P\"gO\xcd\x12\x84\x8c\xf8\xe3\xf0\xe7\x91\x83\n\x8bA~)(W\x08\x92+\x02\xae\x82\xbbe\xa0\xb2\"\x90\xef\xc3/*\x00\xf9V\xa8}\xe2OY\xe9'_\xf8\xf1\x88\xee\x85\xa9\xeb3\x8d,\x9a6\x87m\xfcw\x90\xc7\x02;\xb5\x0d{\xb5\x99n\xac\xfa\xda\xb8\xc3\x97\xa8\x060\x7f\xda\xe2\xf8\xb2\x12k\xf6[\xff\x07\xc7+\xb8\xfa\xfa\xf6\xeb\x87\xc5\xb7\x8f\x97\x1f/\xbf^\xbe\xfd\xe5\xf2\x7f}x\xbf\xf8\xf6\xf1\xea\xf3\x87\x8b\xcb\x9f.?\xbc\x8f\x9e)\xce\x8b\x1e\xf4\xf5\xcb\x7f}\xfa\xfc\xe1c\xf48\xd4A\x17\xbf|\xba\xf2\x16\xcc\xa8\xcb\x99\xf5\xc2\xacc S\x01{j\x0f\xc8^~\xe9\x0dw\xab\x96\x1b$\xb4\xcdp\x1b\x95B\x11\xdaUC\xde\xf5>0\xce\xab*\x9f\x81\xa8\xcc\x19\xe8\xd6<\x03\xf1\xbf\xd0v0\xa9e(\x87|\xf4v\xbf\x81\xf7\xfa\xc3\xc3\x0e!\x0cx\x12~\xc4\x83mj/\xde\xfa\xff\x14\xa3p\xcf+\x19\xc2(\x97\xa4wL\xae\x11\xdfV\xcd\xaa\xbf\xad\xee<\xfbrL\x1c\xebJ\xce}WK1\xc3\xd8\xb0\xd5Z\xfb\x1e|B\xcf\xd9\xce\x882\xcbv\xdfp\xd6\xed\xaa\x8e?\xcd\xa3/\xbd\x97t]o\xd9\x8a\xb75\x9f_\xec\x1c>\xedX3\x0e\x9cU\xe7o\xab\x8eU+\xa9s\xf4\xacQ\x1b\xacvl\xc9\xea{\xf5\xa9\xc8\xb8w\xc3\x96\x83>?/\x9c\xdc\x7fv\xb9i{\xbdq\xeb\xb2j\xa0ia\xd36k\xd6\x0d\xfb\x0c\x9b+K\x8eB^\xd8{\xbd`\x81\xdan\xc5\xc4@\x13\x19\xca\xcc\x0e\xbd\xf6\x08V\xf7\xeal&K\xb1o\xf4?N7\xaa}\xfa\xf2\xfe\xc3\x97\xc5\xc7O\x1f? \x1e\xfa\xf1\x84o\x1f\xe5\xff#\x8e\x0c\x1f7\x8cBI\xe5\xc0\x0e>\xbe\xea\xbd\x91\x9b\xd5\xbeR\x1f\x97bz\xa9\x9b\xdf\xeb\xc8\xdc\xd1P\xff\x9b5\xcc\x1b\xd3Gdg\xbb\x16c\xe0\xa6\xbe\x97wVL\x92\x9b'\xe5\xf4LO\xa5\xb6\xd5\x13\xacj\xa94\xdct\xedV\x8d\x06\xe2\x80\x90\x8a5\xecC\xfb\x04\x0f\xacS\xb3\xb9\xe032\xb9%c \xab\xce.\x1e{\xac\x96|\xf3d\x16\x18T)\\\x97r^\xc9\x1ePb\xef\xf2\xd9\xd8\x83z\x87\x07v\xcb\x8c\xcf0\xe41m\xc7\x17\xf5*\xb4\xb6\x88x\xae \xa1\x1b\x82\xbe\xaa\x7f\xcc\xd5\xcd\xdb>\xe8u\x03)\xe7\x05\xfd\xc9qj2\xfb\xf1\xdfx}@\x99J\x9b{7\xde.\x7f\xb5<\x1d\xc4l\xae\xba\xb8mw\xc1\x8dM}\x13Pe\xdei\xa82D}b\xfb\xff\x02l\xea^~A\x8d\x85\x1e\xb9\xa9\xae?\x93\x13\x18\xf5\x18k\x85M\xdcG\x7f\xd7\xd3\xcf\x9b\xfc\xeaj\x03t\x90\xc9\x85 \x9bX~\xc0\xf3\xae\xba\xf7\x0cPZ\x7f?BQ\x8d\xb7C\xbb\xab\xfe\xb5\x1f_S\xfa\x92f\xf0\xaa{\xa8\xd6\x1dc+\xd8\xef\xdaF\xef\x8c\xef\xfd\xf8\x176\xcc\x0f\x9cGD\x1eQ|\x8d\xe4S7\xde0w\x7f\x8c>\x1d\xf8\xeb\x0d\xaf\xf1\xd0%1\xc3\xc6\xa5q\xb0\xd2\x9f\x92\xc3\x14\xba\xb2\xfa\x05\xbf\xb5W#ee};\xb7\x987\x9c\xf3\xc7\xb1\xb8j\xf1\xc51\xaf\x99\x14\xda<\x15:\x9f\x87\xfdU\xcc\xc7\x0d\x97\xa7\x0ev\xd5\xban\xe4\x07\xb2\xe3cS\xdf\xad\xe1\x90\xe1\x9b\xf7\xf0\xd0\xfc\x0c\x17\x0d{\xe4\x8b;\xe6y+Eor\x14;\xd0\xb5\xf0\xee!o\xaeo\x16T\xc4\x7fj\xfe\xa6\xea\xf5\xfc\xf3s\xb5f_\xd4Z\xcc\xb9\xfa\xdd\xe3\xec_{\xd6=I7r\x11fW\xad\x19l\xdb\x9e\x03\x93T\x8bDa\x1c\xa7\xf2\x96W\xb9)>L\x03\xec\xfd\x9b\xe9\xc7\x06\x12yyY\x7f\xf9\x1f\xcd~{\xad\xd0\n\xc3SY\xf0\x8e\x0fE\xb5\x9bH\xber\x16\xd2\x99o0}\xa8\xc4x\xcb\xcf\xe4v\xeb\x1a\x13\xeb\xe5*\x96x\x9eV\xeaU\xfbP;\xbaZ\xfc9UE\xb1\xc8\xf0v\xb2\xd0Z7\xb0\xfe\xf2\xf9b\x84\xc5\xf5*f/\xa6\xfe\xce\xef \x0f\x85(\xb7v\x17>$\xb1\xa9\xd7\xea\x865Q\xf1\x81#\xbf_\xec\x96q6\x879\xe3\xaa\xdd\x8e\xe5\x0ej{\x1d\xdb1\xc9L\xbc\xab\xba\xe1&\xc5v\xc2\x994\x8b\xec\x99>\xa9`.S\xaa5F\xef\x00\xa1:\xfd\xf5\xa6]\xde\xc1\xc1z\xa8>2\x7f|\xe8\xd8}-\xdej\x0b\xd5-O\xfe\x94(AK]s\xdc+\x7f\xdc\x08\x7fD\xdaZ\xd7Lj(\xae\xaf\xd1\xa0|q\xf5\x1a\xb0x\xf3\xe8\xaf\x83u}\xcf\x9a\xa1,\x19\xcf\xd0GQ\x80\xcdF\x8de_\xb4\x9f\xbf\xa9\xeb\xc8\x15\xa2e'\x193\x957\x8aU\xcb[\xdf\xad\x97\xdfC\x1b1\xae\xb2\x9dxN\x8c\xb3\x8f\xf2v\xba\x1e\x08q\xc9\xbe\xda\xb2\x01\x19\x86\xbe\xdd\xda\xe9\xb1\xaa\xcd\xba\xedj~\xbb\xed\xe5\x07\xda\xf2\xb6m{\xe6\x1e\x94;\xd63\xee{\x80u\xbb\xd5\x0d,Y'\xa1\xf7\xa5x\x98\x15\xa6\xc4\xce\xd7\xe7p[u\x12%\xbc\xeb\xcf\xd4*\xd7\xabm\xb5\xbc\xad\x1b\xd7(1\xe7&]W\xbc\x94\xb7\xa7g\xb0\xacz\xd6\x9fMZW5\xc8\xbcu\xfbVvB\x7f\xe9\x97m\xc3\xebf/\xe1N\xd7%\xaf\xc5\x1b\xa8\xa9\xb9\xa2\xd0\xe5\x07\xe4\xb2cU/J\xcaD/\xd1\"\xfb\xec&\xaf\x99s\x0bk\xd9\x9e\x93\xbf#\x82w\xcc\xba;*\\\xc7l\xe43]\xab7F\x119\xda(\"\x87\"rF\xa3\x88\x1c\x8a\xc8\x19\x8d\"r8E\xe4\xb8\x8d\"r\x8cQD\x0eE\xe4PD\x0er\x96D\x119\x83QD\x8em\x14\x91C\x119\x0e\xa3\x88\x1c\xe71\x14\x91C\x119\x1e\xa3\x88\x1c\x8a\xc8\xa1\x88\x1c\x8a\xc8\xb1\xacDt\x04E\xe4H\xa3\x88\x9c\x1f!\"g$U\xce\xef\x98\xfd\x16\x0c\x05\xe5h\xf4\xa3\xd2Ch\xc7\xf8\xbek\x14&`+\xe6\xe7\x03'\"\x97\x82\xd6\xb35\x13\xa9\x81k\xbc*\xc0~\x9c\xc3\xa7F*\xc7\xf2[\xb1\xbd\xb9\xe9\x19\x17\x9f_\xd3\xe2\x82\xb5\x94\xdd\xb3 ;Z7Zo\xb7\xfe6\xc6\xec\xdcT\x9b>!hg\xb20\xe0hDU>_;\xce>\xcauedS6\xfb-\xeb\xea\xa5\xf9\x9b|\xda4o\xabVEnYc\x1a~\xdf\x0c\x0bQ\xb3\xe9\xe7\xa5\xf4\xb6a}?6\xa1Z\xba\xd9K\xf5\xf2\x8e%\xb6\xe7\xd4\xfd\x89\x1bw&\xdd;\x9awSokl\xeb\xcac\x8dn\xea\xc3t\xd4\"\xa5\xdd\x83\xb5\xca:\xcf\xdf\xbbSK\x12\xf6\x9f.o`\xc3n\xb8^\xfd\xaa\xf5VQf\xd2(\xd7W\xd5\x03\xa2.\"\xda\xf9\xfaI \xff\xd5n\xf7;\xb6\xa2\x0d\x1b\x8d\xe7\x87\xda\xd2:C\x86\xc51Y?\xde\xed\x19\x88\xff\xa8\x9bU\xbd\x1c\xf6\xdf\x1a[P\x1e\xa8;\x92\xed\xaen\x96\x9b\xfdj6%\xac\xd4U\x06\xa9kv\xc7\xa4pj\xad\xc0\x8a\xa1\xdb\xe2\xecf\x83\xcb\xb7\xcb~v\xb7fU\x90\xb3\xe8\x8e\xf5Z\xe2\x96\x8f\xd7\xf8<\x8aG\xee\\?M\xf5\xbai\xe7\x91\x0b\xe6i\x9c^B\xb5\xcc\xb17\xf6\xbam7\xac2\xd5\xf1\xef\xc0\x16\x0d\x0d|\xfd\xdbH\x84\xfe\xfb\xf5\xae\xedx\xff\xfa7M\xa4\x86\xb6`3\xa0\xe6\x107\xd8\xc8\x90\xc1\x8b)\x9d\xed\n\x13|aj\xf8\xbc\xa3\x04\xbdX\x96\x01R\xab\xbeo\x97u5\xec\xc7\xa6z\xb4\x82\xd5,j\xfa\xd0M>\xb3\x15\x08\x19<&`0\xba\xe6\x1d\n\xab\x89\xc6\x8eE\xce\x0b\x04\n\xe2\xc2\x04\x11A\x82\x88\x10\xc1\xa3\x02\x041\x8b\xeae\x83\x03#\xa1\x81e\x02\x03\xa3\xb7\x16\x19\x16x\xa2\xa0\xc0\xef\x1e\x12x\xd2\x80\xc0\xfcp\xc0\xef\x1a\x0c\x18(L8\x10\xb0P\x18\xe0\x91cUR\xe0\x1d6\xfc\x0f\x13\xfc\x97\x13\xfa\x17\xfa\xbc\x1a-5\xec/\x1a\xde\xf7;\x04\xf7%\x85\xf6}\x87\xc0\xbexX_NP_\xf0\xcd\x0f\xd1\xb7?\xc4c\x85\x10\xcf\x07\xa0\xdfWP<\x90\x0f\x1f\xc6\x17\x0fSBV\xf5\xc8\x00>T\xf8\x1e\x8f\x04\xef\x05C\xf7\xa2\xb5\x88E\x99\x94\x0c\xdaC\x86\xec%\x04\xec\x05\xc3\xf5\x8e\xae{\xd9@=\x7f\x98^\xfc\x81\x99\x07\xae\xed\xea\x1d\xdb\xd4\x0d3\xaa\x88\x18\x8a^\xb5\xcd\xd2\xbc\xce\xcd@\xe5\xea1\xd7\x8c?\x88\xb7\xb6\x01Z\\\xb7a\xdb\xae\xf6\x1b&>Q\xa1g\xbb\xaa\x13SK\x19*\"{ro\x9a@N\x84\xf4\xfe\xber~\xe9\x1e\x9b\x96\xd5N~/\xb77\xaek\x89\x99\x81h\xb9a\x9c\x95\x0f\x91\xf4e\x9d\xa9'\x0e\xd6\x81\x07Aq]\xdb\xde$\xd1\xd3\x11\xd8Fw\x8f-\xeb\xee6L\xb9\x17\x05a\x8fu\xcfY\xb3\x9c\x9f \x0f\xf0\x06\x90hg\x1a\xff\xaf\xf8\xf8\xae\xd0\x9e\x1f\xaa\x1e:\xc6\xbb\x9a\xb9H\xb5#>\xeb(\x14'Z\\\n\xc5\xa1P\x9c?@(NF$\xce\xcc\x9b\x1d\x883\xfb\xe9\x1d\xeb%\xc2&\\\\\x8c\xf3\x993 \x84\xaa\xc5\xd2\x1e*=Xi\x80\xc04\xa1\x98\x88\xcf\xdc\x0d\xc3\xdb\xfc:\x8e\xd1\x8e\x82\x82((\x88\x82\x82\xb4QP\x10\x05\x05\x8dFAA\x9c\x82\x82\xdcFAA\xc6((\x88\x82\x82((\x089K\xa2\xa0\xa0\xc1((\xc86\n\n\xa2\xa0 \x87QP\x90\xf3\x18\n\n\xa2\xa0 \x8fQP\x10\x05\x05QP\x10\x05\x05YV\"@\x83\x82\x82\xa4QP\xd0\x8f\x10\x144\x12:\x96\x9b\xc9\x87\xa4\xa12\xd4\xe2\xbe;K\xf0\xd1[\xe5\x0c\x91\x0b\n\x8c\xf2\x95E~\xde\x9d\xb0 \xa7\"\xf0_+U~!\x95\xd9\x00\x8eo}\xb4ki\xf0B\x9e\xa8\x98c\x03\xe9\x1b\x01RK\xfd\n\x12\x1f\xfe8\xd3#G\xbe}\xec\xc1\x03\xe8>\xcc\x8c\x06\x86sD\x8eB\xf0\xbfU*}\xd4\xb3\x8d\x03\x18j\xb4Z\xd87\xc1\x0b\x8eL\x1a\xd5\x15\x1c0o\xe0\xe1\xfc|rD\x17\xccG\xc9E\xd7\xad\xa6E\x0f\xe6\xf1\x0e\xb7\xc1\xa1\xb3\xdeK\x84\x07\xeb\x0b\xd1:\x03B\xb3DT\x1d\x90\xeb^\xca\xb2\x94\xcb\x80\xbf\x83\xc5\xab\xc0\xb7\\Y\xf52\xaa_\x96V0\xf1\x1af!\x153O\xc7\x0c\xb8\x13\x0d\x8aV2\x8f\xd62K\xab\x99\x89zfaE3M\xd3LT5C}x\xd0;\xb1\xbafae\x13\xa5m\x16T7\x8f\xd57\xb3\x14\xceB\x1ag\x8e\xca\x19p&\xf5\xcf\xb8\xcey\x12\xa5\xf3tZ\xe7I\xd4\xce4\xbd\xb3\xb8\xe2\x89\xd5<\x8b\xaa\x9ex\xdd3Y\xf9L\xd7>\xa3C\xe1_\x11\xeag\x01\xfd3\xa2\x80\"'T\x08\x154e\xd6\x95\xac\x84\x86^\x82\xd7\xed=Ch\xa1\xd8\xf2\x15\xd4CS\x14\xd1\xc2\x9ah\x9e*\x1a\xeaA}\\\x17\xcdVF=\xde\xc4\xd5b\xdah)u\x14-\xf1!\x14\xd2$\x8d4\"id\xe9\xa41\x9f\xde\xf5\xd2Bjizc\xe2\x15\xd3X\xdd2T\xd3L\xdd4\xb4\xee\\L;E\xab\xa78\xfd\x14\xab\xa0\"Z9]EM\xd1QCJj!-5QM=NO\x8d5h\x82\xa6z\x02U5Z:oO/\xa7\xad\"\xd4\xd5|}\xd5\xe3N\x1c\x16RX\x0bk\xac1\x955Sg\xf5\xf8R_\x86\xa1\x8fc\x84\xd6\x1a\x12\x84Bzky\xc5\xb5\xb8\xe6\xeaW]K\xea\xae\x18\xe55]{MR_3\xf4\xd7T\x056\xa8\xc1\x86\x151\xbc&\x86\xd5a3\x94\xd8D-6P\xdd\x1c=\xd6\xe3\xca\xd2:q\x8f\x04N\x93\x0dt\xf9f\x1dVe\x8b\xea\xb2\x11e\xf64\xdal\xa9\xbe\x98\xa0\xcf\xa6(\xb4\x87\x9b b\xbe[\xad}V-u\xd0\xdak\xd5\x96\xb0\xd4W\xa8k\xed\xc6\x1a\xf4\xd4\x19\xaef\x9c\xef\xb2J\xc1\xe0\xc6(\x18\xfc\xc0\xd2\x8aK\xc1\xe0\x14\x0c\xfe\xbb\x05\x83\xfb\xf6=\xb6\xc3\xc0\xad\xd1u\x1e\x11\xfe\xc5\x15\x11\xeer\xf5\xda\xe3\xd0\x8a\x10\x1fN\xa3\xa0\xec\xd9\xaf\x14\x94\x8d\x19\xf4\x94e\xa1\x0d\x14\x94\x8d\x01\x1a\\k\x00\xc98C\x0e\xcc@A\xd9\x05\x11\x86\x14\x80! _\xa0\xa0\xecc\xa1\x85\x0cd\xa1\x08\xb0\x90\x8e+PP\xf61\x98B\n\xa4P\x18Q\xe0(@\xa1 \x9e\x80\x85\x13\x1c\xeb\x0e\x14\x94=5\x04\x8e\x80\x9d%%\xa3\x08\x14\x94\x8d\x02\x10r\xf0\x03\n\xca\xf6\x1d\x16E\x0e\x12\x80\x03L\xc8q\nl@A\xd9\x14\x94\x8dA\n(([\xda1\x10\x01\x05e\xbb\xe6[\xc0\xf7ice\x95\xb1|]\xcc\xa3\x81e)`Q\xb5+M\xebB+]\x89:W\x8a\xca\xe5\xd5\xb8\xfc\xa5\xc1j\x0d8}+Q\xddJ\xd0\xb6\x9cU+\xabk\xf9\x1e\x8a#4-\xe7:\x85W\xd1\xca\xd3\xb3B\xdaUy\xe5\xea\xf8\x9e\x84V\xad\xb0\x9a\xd5\xfc\x15\x19\xc8V\x1a\xfc\x88\x9c&\x16\xbd|\xef^\x96\x9f.\xdd\xcf\x9cP\xb4)E\x9b\x0e\x96V\\\x8a6\xa5hS\x8a6\xa5hS\x8a6\xa5hSc\x14mJ\xd1\xa6\xa3\xe5h\xd6^g\x14mzh\x85\xf4\xeb\xe3\x14\xec\x0c\x0d\xbb\x88\x8a]\\\xc7\x8e*\xd9'\xd0\xb2O\xa5f\x9f@\xcfNQ\xb4s5\xed\xe0\x18\x1eS\xb5\x0b\xea\xdaXe;Q\xdb.\xaen\xc7\xf5\xed\xa3\x15n\x8a6\x8d\x96,O\xf1v\xba\xa2h\xd3\x1c\xed;\xa6~\x97\xd1\xbf\x91\xa2nT\x03OP\xc1\xa3Q\x7f\x89J8E\x9bR\xb4)F#\x8f\xb6j\xaaN\x8eW\xca)\xdatf\x85us\x8a6\xb5-WEw:\xa3h\xd3\x04M\xfd\x18U\xdd\xe9\x8e\xa2M\x9d'\xa0tx\x8a6-\xa7\xcaS\xb4\xe9\xd1\x9a}\x99>\x87\xd6\xed\xf1\xca=E\x9b*\xcb+\xc8LT\xf7\x15h\xd0\xc1\xd5a\xe6\xc5\xe0\x07\x19\x8e.\xa0W\xfa>(\xf9\x81\xdc\xec.\xb9VI\x7f\xb7\x92\x9f,\xc2\xb7a\x8f|\xd1\xb3\x7f\xedY\xb3D\xee\xbb\xfc\x91=\xf2+}\xc6\x17\xb6d\xf5\xbd\x98\x17\xf0}\xa7\xdf\xb9\xc2%t\xfa\x07\xe3ZN\x8e*E\x14\x0c\x9et\xc1\x9c\xe1\xb7\x8e\xab\xe8\xc3\x9em\xf0\xed\xa4-\x17\xba\x05\x92\xc4\xd2(\xb2\xa1er\xd9\xc4C\xd3\x9a\xb6>x\n\x81\x80 \x02\x82lK+.\x01A\x04\x04=O h|1L1 \xf1\xaee=W\x13\xfd(\x05\xe4x\xc5\x0c\x0e \x07RF8\x10\xe1@\xa3\x11\x0eD8\xd0h\x84\x03q\xc2\x81\xdcF8\x901\xc2\x81\x08\x07\"\x1c\x089K\"\x1ch0\xc2\x81l#\x1c\x88p \x87\x11\x0e\xe4<\x86p \xc2\x81[~e\xde\n\xcfC\xa4\xd3\xfd\xe1\x88\x05*\xe7\xa3)\x1f\x8b\xf1yp\xcf\x08\xc6\xeeY\xfa\xf2\x07\x0f\xa4\xbb\x00\x86\xf19\xe2\xf2\x08\xe6c>b\xa8\x87\xc2\\\xdb]\xb2U\xc5\xab\x02\xa5\xc2.\x1a\x0eoKq\xdd\xd9{\xb5\x1fJ\xcc+\x9e\xbd\xca\xa7\x9eY\x95\x0cDJ8z\x8e+\xd7\xa9\xea\xa5\xfeJ`\xe29\xd4\xcb\xff\x86Kr\xba\x133\x89\x9e\xb7\x9dg\x0e\xafK\xbcl\xb7\xdb\x9a\xcb\xa7\xed\xec\xe0\xf9S\xcb\xdb\x92\xee\xda\xf1\xde\xf3\xd1|Qm6\n\xef\xd0#C}\xbdQ\xec\x83p&f\x88\xb6$g\x97\xdf\xe9\xaen8\xebv\x9d\x84[j'k\x02\xc3\x96\x11b\x10\x1c\xca\x7fP|)\xa4T\xa6\xf8\xf3\xbb\xb2\xab\xd6u#\xc7K/\x146\x1e2\x0cz\x9e\x01)\x0b\x00\x93\xb4\xde\x1d{:\x12\xa5\xf2v`\x1f\xc0b\xcc\\\xdf\xb0+\xe2?\xb5\xfcS\xf5\xbd\xd2\xb8>Wk\xf6E1-\xe7\xeaw\x8f\xb3\x7f\x89\x97\xaet#\xd1\xc0\x9d\x98\x9bm\xdb\x9e\x03\x93\xa2\x8aTb\x1c\xa7\xf2\x96W\xb9\x9bq \xc6\x15\xdd\x04\xde\x05\x7fyyY\x7f\xf9\x1f#\x1el\xe4\xc0x\x7f\x1c-\xea\xf9\xa2$PT\x19\x81\xa2 _\x81\x04\x8a\x12(\xaa\x8d@Q\x02E \x14%P\x94@Q\x02E \x14\xc5\xce\x92\x08\x14\x1d\x8c@Q\xdb\x08\x14%P\xd4a\x04\x8a:\x8f!P\x94@Q\x8f\x11(J\xa0(\x81\xa2\x04\x8aZV\x02\xda#PT\x1a\x81\xa2\x04\x8a\xfeh\xa0\xa8U\x90\x81\xec9\xbfcO\xbe\xf2\xcc\x94=\x8d\xcaT\xfa\xd5\xa2HN\x85U\xd8\x84\xc1\xf9\xc0\xd5\xc8%\xb2\xf5l-I2\x03\x86\x8a\xf2\xb32\xe7\xf0\xa9\x91J\xbb\xfc\x86nonz\xc6\xc5g\xe9\xb4\xb8`-\xf1\xf7l\xc28\x89\xb6\xfa\x97&a\x8d\x8d\x8duSm\xfahky\x16L\x1c\x8d\xa8\xca\xe7k\xc7\xd9b\x85\xae\x8cl\xcaf\xbf\x95l\x9b\xfe\x9b\x1c\x85\x96U#\xea\xa3V\x8bnYc\x1a~\xdf\x0c\x0bt\xb3i\xf9\xa5\xf4\xb6a}?6\xa1Z\xd2\xdaK\xb5\xf7\x8e%\xb6\xe7\xd4\xfd\x89\x1b\xd7\x93!\xd0j\xdeM\xbd\xad\xb1\xad+\x8f5\x02\xb3\x0fkR\x8b\xb7v\x0fVs\xa4~\xbe3\xf1N-\xd5\xd8\x7f\xba\xbc\x81\x0d\xbb\xe1zU\xb0\xe6\xea5a&\xd3r\xddY= \xea\"\xa2\x9d\xaf\x9f\x14(Q\xedv\xbfc+\xdap\xd6x~\xa8-\xad3D\x8b\xca\x1e\xda\xca\x81\x06\xc4\x7f\xd4\xcd\xaa^V\x9c\x8d\xb0\x8cjAy\xa0\xeeH\xb6\xbb\xbaYn\xf6\xab\xd9T\xb9RW\x19$\xc0\xd9\x1d\x93\x82\xb2\xb52-^i\x16\x978\x1b\\\xbe]\xce)\xcdY\x15\xe4\xd7E\xc7z-\xfd\xcb\xc7k|\x1e\xc5#w\xae\x9f\xa6z\xdd\xb4\xddl]\xdf<\x8d\xd3K\xa8\x969\xf6\xc6^\xb7\xed\x86U\xa6:\xdf\x81\xe9\xef_\xfff\x00\xe3\x7f\x07\x90~'u!kW31\x82I\xc4v\xe5\xe1\xf8\xc5\x0c\xed\x16\x0f\xe8\xbf0M\xf5\xc7\xe0\xf3\x93p\n\\RG\xd3\x8c\x8emg\x0d,#'y\xf3\xc5^J2I\x0c\xe1`i\xc5%\x86\x90\x18\xc2\xdf\x9b!<\xe8E~\xe0o`\x08\xed\x10\x11\xfd\x80\xcd\xdf\xb9`\xbdL\xe4\xcc\xe1@\xc1\xd3\xe3\xad\x1a\x8f\xaaM\xdf\x9aI\x8ax\xb5\xa9\xb1I/h\x9a\x16\xbb\xe9\xda\xed8~\x1d\xf8\x0b\x0cgD%\xce~%*\x113\x98*#*\x91\xa8D\xb7\x11\x95(\x8d\xa8\xc4C#*\x91\xa8D\x9f\x11\x95HT\xa24\xa2\x12\x89J$*\x91\xa8DeD%\x12\x95HT\"Q\x89>#*\x91\xa8D\xa2\x12\x89J\xb4\xac\x04!FT\xa24\xa2\x12\x89J\xfcq\xa9D\x83\xa3xK2M\x8bW\xb2\x08\x1e\xd1\xfc\xd4\x18\x8e\x95}.\x80\xe0\xfc\xf7<\xab\xe6\xc5x\x9a/\xa1\xa6\xe5YB8\xac\xb7Si\x1aw\xe8L\x9a\xd6\x15\xf5A\xcf\x16\xd2\xb1j\xfegr\x06\x87G\xb29\xba\x14\xfa \xc2s\x94e\xe39\xbbi\xc6H\xa2r\x88\xca!*\x87\xa8\x1c_{N\x87E\x1c\x95\xa3G\xec\x12`\x0ee\xf3\"J\xc7\xf3;Q:\x96\x11\xa5C\x94\xcehD\xe9p\xa2t\xdcF\x94\x8e1\xa2t\x88\xd2!J\x079K\"Jg0\xa2tl#J\x87(\x1d\x87\x11\xa5\xe3<\x86(\x1d\xa2tp8b\xe2\xade\xfcY[\xc9A\xe9\x9aI}_gX\xb1$~\xf1\xd4+\x1f+\xd1\xf5\x86u6\x07\xb0\xa3/\xa9\x0fx\xb6\xb4\x8e\xa9\xa5O'\x9c\xeeRf\xfd\xaa\x84i]H\xb8\xd9Tk9\x0f\xabo@\xdf+\xc5\xc2\x10\x88c\x8c@\x9c\x03K+.\x818\x04\xe2\xbc_|\xfbx\xf5\xf9\xc3\xc5\xe5O\x97\x1f\xdeG\xcf\x14\xe7E\x0f\xfa\xfa\xe5\xbf>}\xfe\xf01z\x1c\xea\xa0\x8b_>]y\x0bf$\xf4\xccza\x16\xeb\x84]\xc9\xfbd\xb8\x03 \xb9\x99\xbb%y\x0b)\x0d\xe9\xdb\xa8d\x18\xff\x1d\xd2=\xa4\x0f\xbc\xccT\x95\xcf@T\xe6\x0ctk\x9e\x81\xf8_h;\x98\xd42\xb0\x06\x10\xbf\xddo\xe0\xbd\xfe\xba\x925\x8c{\x12~\xc4\x83mj/\xa66\xff\xdc\xf7\xb2'wb\xbc\x91\xeb\xee;&\x17\xc2o\xabf\xd5\xdfVw\xceu\xd2\x99c]\xc9\xb9ok\x0bD\x8d`\x18\x9f\xd0s\xb63\xca\xd3\xb2\xdd7\x9cu\xbb\xaa\xe3O\x8a\x1fD\\\xd2u\xbde+\xa6$|~\xb1s\xf8\xb4c\x8d5\xc0v\xfe\xb6\xeaX\xb5\x92bN\xcf\x9a\x95\x9c\xffi\x14\xd0\xec\xff\x87(\x9a\xea\x00\xf3\xc2Izr\xb9i{\xa6\xfc.\xab\x06\x9a\x166m\xb3f\x9d\x98\x01\xca\x95{se \x8b\xc8\x0b{\xaf\x17,P\xdb\xad\x98\x18h\"C\xd9\xc3-\xd3\xd2\x04\xb3\x9f y6\x93\xa5\xd87\xfa\x1f\xa7\x1b\xd5>}y\xff\xe1\xcb\xe2\xe3\xa7\x8f\x1f\x10\x0f\xfdx\xc2\xb7\x8f\xf2\xff\x11G\x86\x8f\x1bF\xa1\xa4r`\x07\x1f_\xf5\xde\xc0\xfff]\xfbJ}A\x8b9\xb4n~\xaf#sGC\xfdo\xd60o\x86M+Eg\xbb\x16c\xe0\xa6\xbe\x97wV| 4O\xca\xe9\x99\xfef\xd8VO\xb0\xaa\xa5\x9c\"!)9\x1a\x88\x03BR\xdd@R=\xc1\x03\xeb\x98\xe8\xbd<\xf8\x8cLn\xc9X\xc2\xaa\xb3\x8b\xc7\x1e\xab%\x97\xb8\x9aU\n\xd7\xa5\x9cW\xb2\x07\x94\xd8\xbb|6\xf6\xa0\xde\xe1\xde\xd9\x05 f\x18\xf2\x185G\x0f-\xa0\"\x9e+H\xe8\x86\xa0\xaf\xea\x1fsu\xf3\xb6\x0fzqDj\x96A\x7fr\x9c\x9a\xcc~\xfc7~\xfcH*Pis\xef\xc6\xdb\xe5\xaf\x96\xa7\x83\x98Y\xf2\xe2\xb6\xddyoTh\x02\xaa\xcc;\x0dU\x86\xa8\x8f\x8f\xa0\x1c\xcd\xe4(\x1d\x0bm}\xb8\xf5gr\x02\xa3\x1ec-#\x8a\xfb\xe8\xefz\xfay\xeb%}\x15@\xa0\xa4\x98o\x9aX\xaeR\xf0\xae\xba\xf7\x0cP\x1a28B6\x8e\xb7C\xbb\xab\xc4G\xab)\x92\xbe\xa4\x19\xbc\xea\x1e\xaau\xc7\xd8\n\xf6\xbb\xb6\x81\xd5^.\x87\x85\xf8\x8ea~\xe0<\"\xf2\x88\xe2k$\x9f:\xe7\x97\xf6h\xf1\xa7\x03\x7f\xbd\xe15\x1e\xba$f\xd8\xb84\x0eV\xfaSr\x98BWV\xbf\x10\x1f\xa8\xe3\x92\xab\xacl\xe5\x19>\xcd\x1b\xce\xf9\xe3X\\\x9d\xaa\xf4p,qf\xeeE}6\xcf}\xed\xaau\xdd\xc8of\xc7W\xa7I\xa9j\x0e\xf1\xa5\x07<*\xb0\xa1a\x8f|q\xc7<\xaf\xa7\xe8\xdd\x8eB\x16\xbe=L\x8d\x99\xeb\x9b]K\xc5\x7fj\xda\xa8\xea\xf5D\xf4s\xb5f_T\xfa\xd8s\xf5\xbb\xc7\x99\xe2\xb7\x85\x1b\xe1V4\x1d\x83m\xdbs`\x92\xe1\x91\xe0\x8f\xe3T\xde\xf2\xca\x03\xdb\xa2\x1b \x1e#\xe1\x1dQ\xe4\xe5e\xfd\xe5\x7f\xa8\x08\x13\xd1\xa5\x0c=f\xa1J>\xf0\xd6n\"\xf9\xeeYHg\xbeQ\xf5\xa1\x12\x03/?\x83\x9a\xf7\x06\x8a\xeba\xdf\xa8\x07k\xa5\xde\xb9\x0f\xb5\xa3\xab\xc5\x1fXU\x14k/\xdav\xb2\xac\\7\xb0\xfe\xf2\xf9b\xa4\xec\xf5\x9am/\xbe\x01\x9c\x1fD\x1e\xe6r\xd9v\xca\x87\xe4SMza\xb3\x02,\xbet\xe4\x87\x8c\xdd2\xce\xe60g\\\xb5\xdb\xb1\xdcA%\xb3c;&\x9f\xefwU7\xdc\xa4\x88,2m\x16\xd93}\xc2\xc8\\\x94\xa5=\xc2)\xf0\x89\x02\x9f(\xf0)\x14\xf8\xe4\xde#\xfcp\x11~\xbeI\xf8\x17\xf4&\xe1\x1e\x87\xb4A\xb86\x8aH\xa2\x88\xa4\xd1(\"\x89\"\x92F\xa3\x88$N\x11In\xa3\x88$c\x14\x91D\x11I\x14\x91\x84\x9c%QD\xd2`\x14\x91d\x1bE$QD\x92\xc3(\"\xc9y\x0cE$QD\x92\xc7(\"\x89\"\x92(\"\x89\"\x92,+\x11\x1dB\x11I\xd2(\"\xe9\x87\x88H:\x8c\x17\x99G$\x8d,\xd9w\x89\x05\x1ai\x9a\xf3;\xf6\xe4+\xd5LM\xd3xJ\xa5\x07\xf5\x8e\xf1}\xd7(\x94\xc1V\xf5\xcf\x07\x96E.N\xadg\xab8R\xa7\xd7,X\x80O9\x87O\x8dT\xb7\xe5\xd7k{s\xd33.>\x08\xa7\xc5\x05kq\xbdg\x13\xd0U\xb4\xd5\xbft@\x91\xb1\xb1\xb1n\xaaM\x1fm-\xcfR\x85\xa3\x11U\xf9|\xed8[&\xd0\x95\x91M\xd9\xec\xb7\xac\xab\x97\xe6o\xf2\xf9\xd7p\xb0Z\xa7\xb9e\x8di\xf8}3,\x8d\xcd&\xc4\x97\xd2\xdb\x86\xf5\xfd\xd8\x84j1i/\x15\xd6;\x96\xd8\x9eS\xf7'n\xdc\x19^\xe0h\xdeM\xbd\xad\xb1\xad+\x8f5\xba\xae\x0f%R\xcb\xa6v\x0fV\xb3\x13\xf1\xeb\xc4\xdbN-\x92\xd8\x7f\xba\xbc\x81\x0d\xbb\xe1z=\xae\xe6j\x806\xd3X\xb9\xe2\xab\x1e\x10u\x11\xd1\xce\xd7O\nN\xa8v\xbb\xdf\xb1\x15m j#^\x87x\x1d\xe2u\x88\xd7\xb1\xac\x04;A\xbc\x8e4\xe2u\xfe,\xbcNX`\x95\xa9g\xa7*\xab\xfa\xe7\xc2\xa4\x9b\x84\xa0\xd8*\x13@\x1e\xe6\x94\xbd|w\x01\x1b\x15/\xaf\xf5\xb4Vg\xbf\x1cs,:\x04W\xe5M\xff\xfel\x05WG\x03\xd9\xc6\x7f\x07\xfdG\x17\xa9H\x1a'\x9dz#\x928\xcaj\x03\xef5'\x0ecji\x81\xecv<\xa2\x82\x01\xae!\x00\xb9\x9ab,U\x11\x0b:s/\x8b\x04\xbe\x12J+c\x10W\xc7 C!\x0bW\xa0\xe2\xb7h\x95\x0cJ)e\x90\xa9\x96\x05\x1d\x8a\xc6E+fp\xbcj\x06\xc9\xcaY\xd0\x95^\xd1OR\xcf\xa0\xb4\x82\x06\x89*\x1a\xa4*i\xe1\x9e=\xa8lX5\x0dJ+j\x80S\xd5\xa0\xa4\xb2\x06G\xabk\x90\xa7\xb0A)\x95\x0d\xb2\x94\xb6\xf0\xe3P\xf5l\x15W\xdb\xe04\x8a\x1b\x9cPu\x83\xd3(o\x90\xa8\xbeA\x9e\x02\x17\x1b\x82q*\x1c\x94U\xe2 A\x8d\x83tE\x0e2T9\xc4\x90\xf9W\x842\x07%\xd49\x88)t\x80\x9f\x9e!\x94:H\x9c\xc5%+vAoR\xcdC\xa8v\x90P\xca\x82\xea\x1d$)xPZ\xc5\x83L%/\xdc\xaf\xfa\xb8\x9a\x07\xf9\x8a\x9e\xd7\x9f\xb8bL\xd5\x83b\xca\x1e\xe0\x05*\xc0(|\x90\xa6\xf2AlY>S\xed\x03\x84\xdf\xc0\xca_!\xe5\x0f\xb2\x1a\x17\xaf\x00\x02\xa2\x96\x19J \xe4\xaa\x81\x10n\xd5r\xaa \xe0\x95A@\xaa\x83\x80V\x08\x01\xd7\xea\xe9J!$\xa9\x85\x10T\x0c\xa1\x94j\x08\xa9\xca!\x1c\xa9\x1e\x02\xa2y\x13TD8\x85\x92\x08\x982\x06\x9e\x84r\xaa\"`\x94E8B]\xf4:\x14\x07\x86\x14F(\xad2BTi\x84\\\xb5\xd1\xebM}\xa3\x86?\xd7\x11\xaa#\x04\xc5\x11\x08\xaa\x8f\x90\xa5@z]\x05\x95I\xc8U'\xbd\xde\xd4<0\xb0jVN\xa5\x04\x94R \x19j%\xa4)\x96\x90\xa3ZB\xb2r \x91\xb7mDM\x82\x04E \xabbB\x8e\x92 \xa9j&\x84+\x9e\xa3jz\x9dY\x9a!\xf6\x91\xc1\xa9\x9b\xc1\x07\xa2Y\x87\x15N(\xabrBL\xe9\x84\xb0\xda\xe9='W\x05\x85\x82}7A\x0d\x85$E\x14\x1c\xb9\xf6\x01\xf9\xfdm\xedI2*\x95\xf6\xbe$\x96\xc85\x8c\xa1.G\xd6\xf0\xa9\xceq7\xea|W\x92\xc3\x11\xd4\xb9)I\xcf\xdb\x8e\xad\xa6\xda\xec\xb8S\xd2\xe1\xfev\xb4\x1f \xedGB\xfb\x91\xc81\x91\xf6#16\x1d#\xd1a\xcbj\xb896lY\x0fZ_>_\xcc\x1b\x8b\xa2\x98)\x8a9*\x0e\xc4\x87\x07e\xa9\xcc\x86Y\xe8\xf6:\xc4\xf2\x1aEY\x0d\x8ab\xa6(\xe6\xd1\x8a2\x18)\xfcE\x12{AQ\xcc\xc7r\x16\x19\x8cE\x11\xbe\"\x9d\xad\xa0(\xe6cX\x8a\x14\x8e\"\x83\xa1\xa0(f\x8ab\xa6(f,\x03Q\x94\x7f\xc8a\x1f(\x8a\xd9wX\x94qH\xe0\x1b01\xba)\\\x03E1S\x143\x86Q\xa0(fi\xc7p\x08\x14\xc5\xec\xf2\x14e\x0dr9\x03\xef\xbb\x81\xa2\x98\x0f\x8d\xa2\x983\xf8\x808\x1b\x90\xca\x05$0\x01\xc9<@\x1a\x0b@Q\xcciz?E1\x0f\xf6CF1\x87v\x1d\xa0\x1c\xffi \xd4)\xc7\xff \x1b7\x9e\x9d\x9er\xfc\x97hE\xca\xf1\xff\xc7\xcf\xf1\xff\x12\x97\x83\xe2\xf5oCz\x83\x7f\xeb\xec\x0f\x91\x84\x14c>\x8a\xe6 \x15E,\xfd\xc4\x0bS\xc3?@\xf6 /\xb45\xc1\xd1\xaa\xbeo\x97\xb5\\\xda\x93+\x9c\xaao+\\%\x90\xe6\xc1[6\x88J\xf9<(\xe4G\xd7\xb01\x8b\xc0\xc5%|\x9c\x80\x9f#\xdf\x87e\xfa,\x91^^\xc2\xe30*\xd1\x17\x10\xe83\xe5y\xaf\xa8\x89\x13\xe7\x8f\x92\xe6\xb3\x84y\xa8\xbc\xb1\x06\x1c'\xcb\xe7\x88\xf2!\xa9\x0c%\xc9\x17\x16\xe4Qr|A1>*\xc5\x17\x12\xe2\x8f\x91\xe1\x93E\xf8\x02\x12|a\x01>\"\xbf\x17\x17\xdfO#\xbd\x17\x17\xde\xf1\xb2{\x9e\xe8\x1eh\xf4\x98\xe4^Lp\xc7\xc9\xed\x8e\xef}\xff\xf8ZXj\x8f \xedG\xca\xec\x01\x91=:=\x89\n\xec\xb8\xf9KYq=&\xad\xc7\xcb\x94'\xab\x07BJb\xa2zAI\xfd\x08A\xdd\x8d\xc1\x84\xe4\xf4\xb2bzXJ/!\xa4\xa3\x94\xe0\x88\x88\x8e\x96\xd0\xfdjW\xba|\xee\xf7\xe5\\Y.\"\x9c\xa74\x16V4\x8f\xb7 Z0\xcf\x90\xcb\xdd\xab\xf0\x85\xa4r\x94P\x1e\x97\xc91\"y\xb0\x15S\x05r\xac<\xee\x13\xc7\x0bH\xe3 \xc2x\xbe,\x1e\x10\x9f\xb1\x92xaA\xbe'\xa1\x05i\xac\x1c=\x7fE\xee\xba\xb6\xbdI\n\xb7\x8b|<\xea\xd5\xfb-\xeb\xee6L\xb9\x17\x83\x16{\xac{\xce\x9a\xe5\xfc\x04y\xc0\xe2\x96\x89Oe\xaf\x14\xa0~\x86\x8a\xeb\xbb-n\xa4\xf2\xfcP\xf5\xd01\xde\xd5\xcc\xb5\xbe\xc2\xf3\x97\xff;v_\xf7u\xdb,\x94\xf2u\xe4gv<\xb2Y\xbd\x05\xd45G\xf9\xce$\xb2\xee\xadu\x98\xd6\xf5\xad7\x14\xd7\xd7\x92P\xbe\xb8\xfa\xae\x88W\x8d~S\xaf\xeb{\xd6\x0ce98?\xfe\xfd\xfeQ\x14@L#\x84\xb7/\xda\xcf\xdf\xd4uj\xf1\x99\xbb\xec\xe42\x89\x183\xb8\x92pU)\x1c\xbe\x1en\xeb\x0d\x83;\xc6vbl1\xce>\xca\xdb\xe9z`\xe5\xb7z\xb5e\xc3:6\xf4\xedV.r\xf7\xac\xe9\xf7=T\x9bu\xdb\xd5\xfcv\xdb\xc3\xb6z\x82\xe5m\xdb\x8a\xa9\x8f+\x90^\x8cv\xdc\xb7\xba\xad\xdb\xadn`\xc9:\xa9\xaf,\xdbf\xa5\x17\x94\xd9\xf9\xfa\x1cn\xabN\xae\x81\xdd\xf5gJ\xffz\xb5\xad\x96\xb7u\xe3\x9a\xa5\xcd\x97\xfa\x9cC\xbf\xbc==\x83e\xd5\xb3\xfel\xd2\xba\xaaA\xe6\xad\xdb\xb7\xb2\x13\xfaK/\xa6 u\xb3\x97\xab\x91\xaeK^3\xd8\xb6M\xcd\x95$\xb2yR\xde+I?0\xd1K\xf4\xb3\xc2\xea9\x85\x93\xdb\x96\xab\xa5;\x9dQ8y\x82\xb2~\x8c\xb6\xeetG\xe1\xe4\xce\x13Pj<\x85\x93\x97\xd3\xe6)\x9c\xfch\xe5\xbeL\x9fC\xab\xf7x\xfd\x1e\x17N>\x04\x1bZ^&\xdf\x91\x93\xe0:\xb5\xc0\xef\x8e\xa3\xab\x9b7\xf35\xf01p\x92w\xfbH@lF\xd8\xa4\xd1[\xd3\"'\xad\xd0\xf8\x0b\xe3\xc1\xb3\xb1\xf7\xa8\xe8\xbac\x0b+\xa5c\x0f\xfeB1\x97\xd3K\xe9C\x9eo\xdc\xe5\xacm\x9f\x87\xc6\x15B\x16\xc6h\xd0\xd9M\xf3\xca\xfe\x10/\x10 \n\x05X\x06D\x19b\x11\np\x80\x85\xb22T\x882\x14\x1b\xa2\xec\x84\xd5H\xa6E\x94aV\xbf \x8b\x1c\xf1\xba2%M\xe4G\x94\xf1,\x8a\xc4\xef\xae\x0d\xb3$\xca\x92\x88\x12\xaf\x97 i\x82\xe2J\x94\xe5\xd0%\x81\xf6\xab8\x961Q\x96G\x9ax\xdd\xad\x19\xef\x1d\xbc\x89\xb1\xd9\x10\x9a6j\x9dv\xb8\xe2\x11V\x00\xf0\x0f8\xf6\xa9\x83\x0cn \xe8\xcc\xbdx\x1cXK)\xcd\x0f@\x9c!\x80\x0c\x8e \\\x01\x13\x0d\x8fa \xa0\x14O\x00\x99LA\xd0\xa1h\\4W\x00\xc7\xb3\x05\x90\xcc\x17\x04]\x8d\x11\xf3x\xc6\x00Js\x06\x90\xc8\x1a@*o\x10\xee\xd9\x03\x8b\x80e\x0e\xa04w\x008\xf6\x00J\xf2\x07p4\x83\x00y\x1c\x02\x94b\x11 \x8bG\x08?\x0eU\xcfVq&\x01N\xc3%\xc0 \xd9\x048\x0d\x9f\x00\x89\x8c\x02\xe4q\n\xb1!\x18\xc7*@Y^\x01\x12\x98\x05H\xe7\x16 \x83]@\x0c\x99\x7fE\xf0\x0bP\x82a\x80\x18\xc7\x00\xf8\xe9\x19\x82g\x80\xc4Y\\2\xd7\x10\xf4&\x99\x07\x04\xdb\x00 \xa5,\xc88@\x12\xe7\x00\xa5Y\x07\xc8\xe4\x1d\xc2\xfd\xaa\x8f3\x0f\x90\xcf=x\xfd\x89+\xc6\xd8\x07(\xc6?\x00^\xc6\x07\x0c\x07\x01i,\x04\xc4\xc4\xcbL&\x02\x10~\x03\xfaH!>\x02\xb2\x1a\x17\xcfI\x00\xa2\x96\x19\xbc\x04\xe42\x13\x10\xd9\xcc\xb8\x18;\x01x~\x02\x90\x0c\x05\xa09\n\xc0\xb5z:O\x01IL\x05\x04\xb9\n(\xc5V@*_\x01G2\x16\x80h\xde\x04\xd6\x02N\xc1[\x00\xa6\x8c\x81'\xa1\x1c{\x01\x18\xfe\x02\x8e`0\xbc\x0e\xc5\x81!\x0e\x03J\xb3\x18\x10\xe51 \x97\xc9\xf0zS\xdf\xa8\xe1\xcfu\x04\x9b\x01A \x19\x82\x8c\x06dq\x1a^WA~\x03r\x19\x0e\xaf\xb7@\xde\x04e\xe5X\x0e@\xf1\x1c\x90\xc1t@\x1a\xd7\x019l\x07$\xf3\x1d\x10y\xdb\x16\xdc~\x1d\xcbz@\x0e\xef\x01\xa9\xcc\x07\x84+\x9e\xc3~x\x9dYd\x05\xf6\x91\xc11 \xc1\x07\xa2Y\x879\x10(\xcb\x82@\x8c\x07\x810\x13\xe2='\x97\x15\x81\x82}7\x81\x19\x81$n\x04\x1c\xd9\x1f\x00\xf9\xfd=\xe5\x1c\xfeQ\xf3[-\xad\xaa\xcd\xce%\x8d4\x13\xe8\xcdH\xearg\x0d\xa2&\xe8Y\xde\xad\x83\x83\xdd2Z\xefL\x07\xedM\x03=f'w\xf0\x0e\xea\x02V\x02s\x83_\x1c\x1e\x9a\x9fL\xc2l\xc0\xe0\x8f\xf1E\xa5e\xf0.\xf7\xe8Z\xfc\xb7o\xf1d\xd8\x00B\x87\xbf\x0f{A\xc0\xae\xea{\xb58l\xef\xf1\xae~\xf78\x93y\xd4\xa5\x1b\xfff\x11\x8eSe\xc6\xf7#\x1b \x9e\x97\xc2\xbb~4$\x9c\xf7\xed@`\x05\x81\xf9\x16;\xec&\xb2s\xf7{\x0e\x7f\xa8d\x1e\xfa3\xa8yo\x96\xf8{\xd87\xea\x99Y\xa9U\xcc\x87\xda\xd1\xd5\xe2\x8f\xe4d'\xfc\xda\xac|\x0f\xef\x90\xba\x81\xf5\x97\xcf\x17c\x9e\x03=\xf2\xf5\xf0p\xcb:W'\xf2(L\xcb\xb6S>\xe4 o2\xae\x9bW\x94x\x17\xc9\x85Q\xbbe\x9c\xcda\xce\xb8j\xb7c\xb9\x83Cf\xc7vL>\xe0\xef\xaan\xb8I\xb1I\xc9\xa4Yd\xcf\xf4MI\xa6#\xa1\xef\x01\xfa\xff\xd8{\xf7\xee\xb8m$q\xf4\xff|\x8a\xfa\xf9\xde3\xb6w\x94\xb6\xe5Wb\xefz\xcf\xca\xb2\x9ch\x12\xdb\x1aI\xce\xfcf\xe6\xe6\xb4\xd1lt7#6I\xf3!\xb9=\x9b\xef~\x0f\x00\x82O<\n$\xdbq2\xac\xb3g\xc7Q\x93\x05\xa0PU(\xd4\x8b\xa2\x8fD3\xc9k@/\x89Vb\x1a\xdb!q\xe5(\x1f\x9f:8\xb4~\x9d:8`\xd4\x81\x00\xd7L\x0c\xe9\xbe\xd6\"\xc4fa\x8c\x9a\x811up\x98:8T0jf\x85KV\x85SF\xc5\xd4\xc1ah\xf6D\x8f\xcc\x89Q\xb2&\xdc3&\xa6\x0e\x0eC2$\\\xb2#zdFL\x1d\x1c\xa6\x0e\x0eS\x07\x07lf\xc3\xa8Y\x0d}2\x1a\xa6\x0e\x0e\xba\xc7\xac\x99\x0b\x0eY\x0b\x98\xfe\x04.\xd9\nS\x07\x87\xa9\x83\x03&\xf3`\xea\xe0\xc0aHv\xc1\xd4\xc1A\x85\xc9\x9aA\xd07{@{6L\x1d\x1c\xba0up\xe8\x11\xf5\xb7G\xfc]\xa3\xfd\x0e\x91~\xe7(\xbf[\x84\x7f\xea\xe0\xe0\x16\xc5\x9f:8\x940up(\xc0\xb5\x83\xc3>\x9a6(?V\xde\xfc.}c*\xad\xb0Y\x11h\x96_]\xaf\x7f\xd4\xbd\x1e\x9f\x9b\x95Qi\xee\x90Z\xb7<7<\xcc\xcc\x94\x8f9\xd2\xec\xf6\x19\xfd}\x7f9\xbf\xe1\x9eP\x10Q\xccOG\xc7\x96k\xa0\xfa\x0c:\x810\xdf\xd2\xc4\xf7\xe4\xdf\xb8\xcc{$d\xeb\x11\xbe\x99\xe2C\xe8\"\xc2\\\xba\xc3\xda_\xca\xe7\xd8\x02\x9a\xa6\x15 \x85\x03)\xe7\xe5\xd2W\xd4\x91\x9eM\xf4{&\xae\xfd\x83\xfa\x81\xbf\xf5\xb1\xd4\xe5\xcf\xca\x18\xae.)@\xb8J\xeb\x1c\x9c\x95\x1f\xd5o`\x8b\x85c\xa4\xfe\xa7\xd3\x15\x04t\x95\x15>8?\x13JY\x9a\xae\xdc\xcb+\x04D\x0c\xc2\xe8\xbc\xd8\x89oZ\x908\xfe\x0d\xa9XOm\xa8\xde7\xd1\xb2\xf5M\x7f\xce\xa1\x11W4\xbc\x83\x81\x1f.}\x8fd\xb4\xea`!(\xc8\x1f,\x18\xa9\x8e\xae\xf8^B\x93\x9cD\x8cR\x06\xdcZ;\xc6\xc3\xb75?0;@jY=-\xe5\xf2\xee4m\xedVk \xdc\x96OhZ\x04\xda\xb9xU\xf2\xc8DnVH\x93\xbf\x0e\xa3\xa4\xe5E\x97\xd2\xd8\x1cBPf\xe8\xc6.\xa2(\xa0e^\xd5\xb8\xfdu\xee\xc9f\x1c\xf7\xfe\xd5\xea}\xf2\xeb=\x91\xa8U\xfbA\xfc\xc1\xd4\x93\xe7\xbfu=y\xaa\x96<\x88f<\xf5VE%>R\x8b\xd5\x16\xfdz\x8aT2D\x9f\x9e\xe2\x89\xdfK\x9b\x1em\xd6\x9a\xd2\x95l#hVk S\xda\x0e \xe4R\x81\xaeN\xda\xee<\xfa\xa7\xc4e\xc6\xb4\x08kD\x00\xe3R\x1f=!\x02\x97\x0e\xd1'\x19\xc2\x9c\xf4\xd0+\xe5\x81\x0f\xa1AhMx\x18!\xdd\xa1g\xb2\x836D\x8cKu\x18\x94\xe8\xd0+\xcd\x01\x88\xb6\x1e#\xc3%9\xf4Iq0\x05\x1eQ \x0e#\xa77\xa0\x92\x1bFLm\xb0&6\x8c\x94\xd60$\xa9\xc19\xa5a\x84\x84\x86\x91\xd3\x19,\xc9\x0c\xa3\xa72\xec'\x91a\xf44\x06|\x12C\xbf\x14\x06\x03\xd1m \x0c\xa3\xa5/\xe0\x92\x17\x14\xde\x13\xbd~\x1d9q\xc1\x96\xb600i\xc1\x90\xb2`5O\xac\xe9\n8\xfbe\xdcT\x05[\xa2\x82}N\xfd\x92\x14\x0ce7\xb6\x14\x85\x11\x13\x14\x06\xa4'\xa8\x93\x8aL\xc9 \xe3\xa6&\x98\x13\x13\xc6HK@\xc5\xd5-) \xe8\x84\x04\xe3G\xf0\x1d\x93\x11\xf4\xb8\x94~\xfaQ\xd2\x10\\\x88\x85MA\xb0\xd3\x04\x9d~\xd0#\xf9@\x1d\xd3\x18)\xf1\x00\x95v`O:\xc0\xa4\x1c\x18\xa9\xe8\x9an\x80M6\xd0\xa5\x1a\x8c\x90h\xe0\x90f\xd0?\xc9\xc0\x10\xca\xc7&\x18\x8c\x9c^`\x98\x91\x92S{%\x16HO\xac\x02\x9f&\xad`\xe4\xa4\x02}JA\xdf\x84\x02\xee\x11PM\\\x9dN0n2\x81\xee\xe2gM$\xd0E:uI\x04\xe3\xa6\x10\xf4O \xd0$\x0b\xf4J\x15\xb0\xa6\x05\xb8%\x05\xa0S\x02\x1c\x13\x02\\\xd2\x01\xb4\xc9\x00\xc3?\x8a\x8fK\x04pL\x03pH\x02P.m\xdc\x04\x00\x9dP\x0c\x08\xfe+\xfd\x14\xda\xd0\x7f\xbf\xc0\xbf)\xc8?~\x88\x7f8'\xa1\xc3\xfb\xd8\xe0~\xfb\x88\xe4\x9f\xebv*^\xb4\\\x1e\x0b\xd7\xff\x96&W\x81\xfc\x1ax\xb4\x02\xfa\xd1O3\x1az\xed\x17\xf8\x03\xda\xc6\xef\x05\xb2\xa2\x06\x9fd\xe6\xef\x8ckV\xd1\xcb\xfd\x8fj\xad\x8f\xbef\xdb\xeb\xc2\xb3a\x8d\xf4Q-\xf4G\x9e\xaes\xc3|\xfb\xfd\xdd\xbdI\xbe\xfe;\x0b\xae\xed\xf1\xb3^\x8d\xf1\xd5m\x08\x8c-\xf1\x9d\x9a\xe17\x9b\xde+\xb0a\xda\xe0\xf7i\x80\xcf\x99P?{[\xeb\xfb~M\xefys{\x1d=\x1b\x7f\xd7E\x18\x15\x05\xf1c\xd5\xc3\xb7\x979U\xc7\x0b\x98\xaa\xe3\xa7\xea\xf8\n\xa6\xea\xf8\xa9:\xbe\x82>\xa1c-\xb2\xa9:\xbe\x0b#\x85\x91\x87\x05\x92{\x84\x92G &\x8f\x1eN\xb6\x06\x94\xf7\x10R\xdeWPy\x0fae\x97\xc0r\xdf\xd0\xb2Q\x87\xdb\x82\xcb#\x86\x97\xb1\x01f\xc7\x10\xf3\xe8Af{\x98yp\xa0y\xaa\x8e\xb7\xce\xac_\xe0Y\x89j\xaa\x8e\xef\x13\x82\xb6\x05\xa1\xc7 C#c\xab\xd6P\xb4C0\xdaZ\xa5\xec\x18\x90\x9e\xaa\xe3\xa7\xeaxL\xa8\xdaJU\xd7p5>`=U\xc7\xb7`\xe4\xf0\xf5T\x1d_\x87\xbe\xc1l%\xb2\xa9:\xde!\xb4=$\xb8\xadD7U\xc7+_@\x85\xc3\xa7\xea\xf8\xf1\x82\xe3Su\xfc\xe0\xd0\xf98<\x87\x0e\x9f\xe3\x03\xe8\xbf\xa7\xea\xf8V\x10[;\x97VE^\x19\x87\xee\xbc6xf\xd62\xdfV \xdby\xca\x9d\xd7\xf6?\xe5\x80d4\xcd,\x13n\x17w\xd7\xdf\x81\xe8\x9a&I\xc2/\xdb\xb5\xc0\xba8\xaa\x98\xba\x91\xd5\xa8\x19\x8f\x94\xb07\x1b\xc8\xd2\x8c\x17\xf86\xfe\xd6\x0c]~\xfe\x9a\xde(\x0c)\xbf\xd3Wu\xbdB$\xaa_\x1a\x95\xbd\x86*\xddZ\xf7\x86c\xfe\xfcq\x85\xa2A\x9a\n5\xdf\xf1\xeeW\x18d\xadn\x89/\xad\x13\xa7Y\x90\xdb\x1e\xa9x\xe8K\xae\xc9-\xa6:\xe7\x8b\x1f5|\xaaq\xee5\x16\x9a\x06\xbe\xc7\xfdN<@\xe4\xb2\x1dmS\xeb\x0f\x90\x93Tz\xae4\xab\x98r\x92\xe4P\xe3Nw\xcaI\x9ar\x92~\xeb\x9c$\xcdG:\xda\x07\xca\x80\xb4\xa4\xce)8\xa5\" \x98R\x91\xa6T\xa4\n\xa6T\xa4)\x15\xa9\x82)\x15)\x9bR\x91\xd40\xa5\"I\x98R\x91\xa6T\xa4)\x15 i%M\xa9H%L\xa9Hu\x98R\x91\xa6T$\x05L\xa9H\xcag\xa6T\xa4)\x15I\x03S*\xd2\x94\x8a4\xa5\"M\xa9H5\x18#-dJE\xe20\xa5\"M\xa9H\xaaT$U\xa0\xbe\x0c6\xd5\xb0\x0cL\xad\xd1\xa5\x91\x98\xb3H\xaa\xa8\x97>cD\x95 \"\xb3\x12N_\x1c\xd7V\xc3\xafq\x04\xbc\x0d\xf1Cu\x1e\xc8\xef1\x03\xe4\x0b X\xf9\xcb\x01~\x9av\xba\x97L%\xa9\xd8T},\x96\xec>\xda\xd8B<\xbam\xea\xfd\xb46/\x8d\xb3J875\xf41\xef\x8a\x00\xed\xde\x08\xb0\xec\x90\x00\xdb> \xa8\x08kz\nE\xbf\xe2A\x11\x0e\x17!CI\nu\xc6c\x1bV\x94dyb\x9e/\x86z\x02,4\x14\xe0\xba,\x83_P@\xe0\xa7<\xa8$\xd7Rz\xd0\x03Z}\xe8\xa0t\xf9Y\x90!\xa8\x86\xf1\x0d\n\xf8\xa9\xd8\n\x1e\xfa)l\xe3b{\x98\x8dV\xc4o\xb8\xa7V\x99I\"!\xa4\xeb(\xf3\xc5wS\x84b\xbd\xa6\x89\x9f\x8a\xaf\x99\x18\xde\xcb\x9a\xc9a\x1b\x12.\xd3\x0d\xb9Rz<\x01E\xf1bl\xbe\xaa\xc2\x90.\xbe=\x94\xf9\x81/\x16\x02Kv@n\xfd\x90\x02\x0d\xbd\x88Y1z\x87\xbb\x88\xfcp\x07i\xca\x03\x81\xda'\xbd\x0d C\x1ap\x7f!3\xb8i\x96\x16\xa3\x8aoC5\xb4\x84\x12\x8b\xe6\x1b\x1a\x02\x9a\xaaH\x84)\x8a\x9c\xd7\xe2\x8aR\xa3$\x0d\x97Z\x1a\xda\xd9\x9b\x86\xf9V/%_\xc3\xc5\xe5\xd1\xe5\xc9\xfc\xdd\x9b\xd37\xa7\x97\xa7G?\x9e\xfe\xe3\xe4\xe5\xfc\xdd\x9b\x8b\xb3\x93\xe3\xd3W\xa7'/\xado\xb2\xf7\xac\x0f]\x9e\xff\xfd\xed\xd9\xc9\x1b\xebs\x86\x87d\xe6K\xaf \xf3\xcf\xec\xd0$&I\xb6\xc3\xedI\xed\x05aG\xf4;*P\xba\x1c\xa3\xc9\xad\x07 \xe0\xd8\x01\x9ct\n\xb43B\x8ac3\x92A\xf66\x95\x8c\xb8\xba\x06(O\xe33)\x15@P\xb8\x91%\xfb\x9b\x13\xa8!\xb7*B\x99W\xabd5MxF\x82H\x86\xc4\x10*N\xe8\xca\xffh\xa2PK\n\xb6[?\xe3)3e\x96-CP)\xa9\xf6\xfe\x1b\xbc~\x18I\x00\xa44\x80\xf8\xde\xdf\xdc\xbe\x1e\xc0\xef:\xe0\xe2\x88\x80:\xbb\x18\xbc\xe64;\x13$\xf3\xd3\x92\x86$\xdb\x14\x84\x14G\x18#\xe5\x15\xdd\x19\\\xf3P\xb8\xc6\xbc(L\xb3$\xe7\xc9}Wt\x07\xab$\xda\xf2\xd7\xcf\x08\xef\x0c\xbb\x94\xb8\xf8\x0d\xdf\x88nA\x81\xc41\x0d\x97w\xd8\xbb\xb3\x1f\xe8\x8e\xfd\xef\x81y\x0e\xed7\xf8\"\x0e\xf8\xe4g\xb3\xbbj?\xf5\x92\x06d7\x8fi\xe2GC\xacwD\xc6p\x8b{\xf9\xc0 \x06\xee\xa3\xbd1Z\xe0TJ\xff\xb2\xbaR\x96\x16X\xfd\x82]\x08r\xe9'Tb\xab\x99\x14\xca\xdfk\x97y\xe1\x10\xe9<\xd5\x98\xb3\xb4UE%I\xfb~\xcc\x05X%\xb3\xd5\xf7\xeb\x14\x17N\xc1\xf8\xb5O\xdc\xc9\xabo\xf7\xd1\xfe)\xf1\xf2\x13\x9djv\xb12\x8bU\x88u)\xbd\x12\xcaO\x84\x16I\xbc\xe5\xd7B!&iaw\x8ao\x8a~\xc8i\x9a\xcd\xc4\xef\x1ad\xbc*\x87\xa3\xd1\x7fNT\xf1*\xff&\xe0@\x02\xd8\xb3\xeb\xb5\x1a\xac\xfc$\xa1\xee\x1b\x95\xb5\x94\x1a]\x82h\x9dD\xf5\xaf;j\x1e\xbf!\xfcK\x85\x07\xe0g\xa9L\xdeJ!\x0f\x858-E>\xcb\x8d\xaf`5\xbb\xa4\xd6\xbf\x00+V\xd5p\x7f\xfa!\xac\xcf\xcf\x8e\xabl\xed\xc2\xb7\x98\xc2\xcd\x86&*&\xd2\xe4\x06zQ\"p\xf0<\xcaD,\xbe\xf4Tn\x88\xf8\x88c\x832Jr\xc87.\xa2m5oc\xc4-\xa11\xe5\xea\xed\x05I\xcaM\xb2\xb8\xef\x9bd\xe1\x9c\xa9s\xe0\xb7\x83\x87\x96:\x1a\xc1\xf4\x8b \xf2\xae\xf6\xf0\x15\xbf\xa9d\xc6:\xdd\xa9df*\x99\xf9\xcdJf\xcc\xbc$\x9b\xf9\x8eP2\xd3,\x96i/U\x04\xde+\xf3f*\x9e\xe9\x10h*\x9e\xb1\xeb=\x01S\xf1\xccT<\xa3\x86\xa9x\x86\xc3T<\xd3\x85\xa9xf*\x9e\xd1\xc1T<3\x15\xcfp\x98\x8ag\xa6\xe2\x99\xa9xf*\x9e\x110\x15\xcfL\xc53S\xf1\xccT<\xa3\x83\xa9xf*\x9e\x99\x8ag\xa6\xe2\x99\x1a\x8cQ\xc80\x15\xcfp\x98\x8ag\xfe\x1d\x8ag\xaa\xf4\x95\xd9\x15\xad\x9f\x82\x8d\xcbd+=\xa4\xc8\x07!\x85\nMh\x96'\xa1\xc8\x1d\xa8\x87\xd1ge\xf2\x08w\x05\xad[>\x13\x1e\x18\x179\xc4\xa6\x84\x90\x19\xbc\x0dy8\x99\xdf\x15\xa3\xd5*\xa5\x19\xbb~5\xa7\x0b5WvJ\x1b\x1d7\xfb\xf4\x83\xed8 \x94\x8e\x01\x05\x11\xc5\xfcttl]\xca\x8b\xc5pR\x86\xf9\x96&\xbe'\xff\xc6\xa5M\xe6xs\xaf\xc8\x86\x86\x92\xf0yX:\xa2Z\xe6\xe7)\xc7\x16\xd04\xadH(\\79\x0fi^QGz6\xd1\xef\x99\xb8\x9a\xfe\xc35\xf2\x06\xfe\xd6\xc7R\x97?+#\xa9\xba\xdc\x1d\xe1\xa4\xacsp\x11w\xcd\x83V\xf0R\xb8$\xea\x7f:]A@WY\xe1\xfd\xf23\xa1\x0e\xa5\xd1\xc8\xfd\xabB@\xc4 \x8c\xce\x8b\x9d\xc8\x06 q\xfc\x1bR\xb1\x9e\x81T\xbdo\xa2e\xed\x0dFQ\xce\xa1\x11/\x81\x03\xf6\x0f?\\\xfa\x9e\xa8\x93(2B\x04\x05\xf9\x83\x05#\xd5\xd1\xf9\xa1\x17\xe4\xcb\x96IH\xc4(e\xa8\xab\xb5c\xb7\xc5X\xb2\xf2G\xac\xe0\xb3\xd2 \x13\x9c\x00\xd7\xda\xbd\xaaBO\x8b/s\xa8\xdc\xcb\x9c\xea\xf6p+\x1a\xb9r\x0f[\xb7\xe7T\xb5\xa7Z\x9f\xa1ho\x9c\x92=+'\x9b\xca\xf5\xfa\x16\xeb!J\xf5p\x85z\xd62\xbd\x01Ez\xf6\x12\xbd\xbd\x14\xe8Y\x95\xb2]%#J\xf3\xac\xdb\x0eh\xd1\x82Q\x8b\xf2z\x94\xe4\xd9(\x8a.\xc7\xdb3Q\x86\x14\xe2\xf5(\xc3\xc3\x16\xe1\xd9J\xd6\xf6V\x80g\xe5t@q;8\x94\xde\xa1v\x18p\x19\x08\xb8\xe3}\xcc\x92;\xf7\x82;X\x98\xb2s\\\xcb\xed\xdc\x8b\xed\xec\xa5v\xd6\x1dAT\x19\xe0D\xb2Q}'\x12\xee\xf24\xe3\x05T\xb0\xe0yT\xa2>\xae\xf1\xc1'\x8f\xe8\x94\x95\xf4\x08\xad\xca\xa3\xfdkf\xdc\xac\x8a\xe42\x1d\x1d\xdf\xbc\xbd\xca\x9a\xc6\xa8j2\x145\xc1\x0b\x9a\x96\x9f\x16l\xda\xba\x07<\xa1V8\x9b\xd9)#\xb4\x96:\x01C~\x940\x89:y\x80F\xb57\x15UMEUSQU\x01SQ\xd5TTU\xc1TT\x95MEUj\x98\x8a\xaa$LEUSQ\xd5TT\x85\xb4\x92\xa6\xa2\xaa\x12\xa6\xa2\xaa:LEUSQ\x95\x02\xa6\xa2*\xe53SQ\xd5TT\xa5\x81\xa9\xa8j*\xaa\x9a\x8a\xaa\xa6\xa2\xaa\x1a\x8cQ\xe02\x15Uq\x98\x8a\xaa\xfe\x1d\x8a\xaa\x1aY_5L\xad\x84\xa62RU\xe4\x1c+sh\xf7\xf4\x0d\xa2\xde\xe5\x03\xf7\x8a\x1c?\x1e\x185\xd4\x12\xd4J\xc6\xaa(\xde1\x7f\xf7\x82'\xb8\xc8\n\x83Z\xa0]d\xbe(\x12\xeeKT\xdd\xa42M\x0dBm\xa4\xe2\xc1/\xb6\x1c\xa1\xdc\xf6\xe5\xbcN[m:\x86\x8dX2\xf7\xb7\xfb~\xff|\x8c\xa1% \xcd\xa9\x1b\x93\xc5\xcd4\xe8\"K3]\xfa\xb7q\xbd`]3 \x02\x80\x88\xa5\x03\xd2\x89$\xa0W\x18\xd0\x80\xaf\xe3 2\\\x8c\xc6\x0d\x05Z\x83\x81c\x87\x03\xf1\x01\xc1\x91B\x82\xfd\x82\x82\x06t~\xe8\x10\x16\x1c\x1c\x18\x1c;4\xe8\x18\x1c\x1c9<\xe8\x16 t\x0c\x11\x9ax\xb8\x0c\x1eb\x83\x84#\x87 Q\x81\xc2\x11C\x85C\x83\x85\xbd\xc2\x85#\x05\x0c\xfb\x84\x0c\x0d\xc8x0\xd1\x1e4\xdcK\xd8p\x7f\x81\xc3\xbd\x84\x0e\xdd\x82\x87\xa3\x87\x0f\xb1\x01\xc4QC\x88\xf8 \xa2s\x18\xd1=\x90hU\x85w\x11\xa1\xc4\x11\x82\x89\x96p\"\xd2\xa0B\x84\x14]\xac.\xe7\xb0\xa2\xe9\x10\\D\xd7\x14\x11X\xc4\xceo\xc4\xe0\xa2Kxq\xe4\x00c\xbf\x10\xa3\x89\x83R{\x90\xb1w\x98Q\x83\x8d\x8df\x0b4\x8e\x15jD\xc7\xcb\x10\xe1F\xa7\x80\xa3%>\xd0+\xe8h\xc3\xa9u>\x8e\x14zt'&>\xfch[[\x8f\x10d\xcf \xa4\xc9\x89;Z \x12\x1d\x8a\xc4\x05#\xb1\xe1H\x04\x95\xddC\x92.AISXr\xa4\xc0\xa4chrXp\xd2FP\x87\x00\xe5\x1eB\x94\xd6\xd9i9}\xbc@%\"T\xd9?X\xa9A\xc7\x1e3\x85+G\x0eX\xdaB\x96=\x83\x96\x1a\\\xe2fh\xba\x1c#\x02\x97\xa6\xe8\x8a)x9~\xf8r\xf4\x00\xa6>\x849f\x10\x13\x13\xc6t\x0fd:\x852{\x043]\xc3\x99\xc6\x80\xa69\xbc\x84\x0f0a\x83\x9a=\xc2\x9a\x8e\x81M\xc3r\xfb\x0475\xa8j\x81C\x9cH\xe0\x02\x9c\x06\x96\x0f\xd7\xe6\x10\xe7\xa8ANK\x98s?\x81\xce\xb1x\xd1!\xd8\xe9\x12\xee\xec~\xee\x10so\xad}\x0b\xb6\x16\xf1\xab}\x0c\xb6\x1e\xc2\x12\xb7P\x95\xef\xa6\xa6\xf4\xc4\x1b*2\xda\xbe\x04;\x95XO%\xd6%\xb8Mw*\xb1\x9eJ\xac\x7f\xb3\x12k\xdd\x97\x99[\xc5\xd55\x05;F\x9du]_\x9f\x9f\x1d\x17\xd7\x8d\xf2\xa5\xa9\xc4\xb9\xf5\xebT\xe2\x8c\xd1z\x02z\xe56L%\xce\x98\x8c\x06\x95\x13\xc09\x9f\xa1O6\xc3T\xe2\xf9\x07S\x89\xb3\xee1k\xce\x81C\xc6\x01\xa6\x80\xd7%\xdb`*q\x9eJ\x9c19\x05S\x893\x87!Y\x04S\x89\xb3\n\x935o\xa0o\xd6\x80\xf6l\x98J\x9c\xbb0\x958\xf7\xc8\x0e\xb0\xe7\x06\xb8f\x068\xe4\x058g\x05\xb8\xe5\x04L%\xcenY\x00S\x89s \xfb\x88\xfc\x8f\xc1s\x0eQ\x7f|\xcc\x7f\x1f%\xce\xbf\x93\xdaf\x19\n\x15\xe5\xa7\xf7d\xa0\xf7\xde\xbfZ\xd1\xf2_\xef\x89(a\xed\x07\xf1\x07\xd3\xe7\xd5\xd4%\xd1rHEUt\xeb\x93\x00\xe3\x14F7\xc6+\x9e\xfdbk\xa3[\x1b\xa2\xcd\x9f@\x90j\x1fe\xd1\x991xf\xf5\x1ba\x1c/\xa3\x87\xcdpA\xb3>!3sh\xacW`\x8c\x0f\xa1Ah\x0d\x8b\x8d\x10\x14\xeb\x19\x12\xd3g\xd0\xa1\x02b\x83\xc2a\xbd\x82a@\xb4Y\xbb\x19.\x14\xd6'\x10frO\xa3\xc2`#\x07\xc1P!\xb0\x11\x03`\xd6\xf0\xd7H\xc1\xaf!\xa1/\xe7\xc0\xd7\x08a\xaf\x91\x83^\x96\x90\xd7\xe8\x01\xaf\xfd\x84\xbbF\x0fv\xe1C]\xfd\x02]\x06\xa2\xdb\xc2\\\xa3\x05\xb9p!.\x85\x8d\xad\xd7\xaf#\x87\xb7l\xc1\xad\x81\xa1-C`\xcbj\x9eX\x83Z8\xfbe\xdc\x80\x96-\x9ce\x9fS\xbfP\x96\xd4\xec\n\x84\xb6@\xd6\x88a\xac\x01A,u\xe8\xd9\x14\xc2\x1a7\x80e\x0e_\x8d\x11\xbcBE_,\x81+t\xd8J\xefav\x0fY\xe9q)\xbd9\xa3\x04\xab\\\x88\x85\x0dT\xd9i\x82\x0eR\xf5\x08Q\xa9=_#\x85\xa7P\xc1){h\n\x13\x982R\xd15(\x85\x0dI\xe9\x02R#\x84\xa3\x1c\x82Q\xfdCQ\x86\x80\x0f6\x0c5r\x10\xca0#%\xa7\xf6\n?\xc9P\x93\x02\x9f&\xf84r\xe8I\x1fx\xea\x1bv\xe2\x1e\x01\xd5\xc4\xd5A\xa7qCN\xba\x8b\x9f5\xdc\xa4\xf3\x87\xebBM\xe3\x06\x9a\xfa\x87\x994!\xa5^\x01%k\xf0\xc8-t\x84\x0e\x1c9\x86\x8d\\\x82F\xda\x90\x91~6X\xd7=.\\\xe4\x18,r\x08\x15)\x976n\x98H'\x14\x03BDJ?\x856@\xd4/\"\x0d\xdd?\x8d\x97\xc8f\xa3\xce\xd3\x97j\xb7|\xd3u\xdfB2UoN\xd5\x9b%\xb8Mw\xaa\xde\x9c\xaa7\xbf\xf8\xea\xcdF4v\x94\x02\xcef\xd5pN5\x9c\x98P\xb9\x95\xaa\xae\xe1r|\xc0|\xaa\xe1l\xc1\xc8\xe1\xf3\xa9\x86\xb3\x0e}\x83\xe9JdS\x0d\xa7Ch}Hp]\x89n\xaa\xe1T\xbe\x80\n\xc7O5\x9c\xe3\x05\xe7\xa7\x1a\xce\xc1\xa1\xfbqx\x0e\x1d\xbe\xc7\x07\xf0\x7f?5\x9c\xd5lZ\x11\xed1\x87\xd0F\x8e;cw\xa2\xb5\xfb\x1a[W\xbb\xcaKWI\xcd]x/KH\x98\xaehR\x16\xb0.i\x18m\xe7YB<\x19\x0fR\x15\x9b\xbedO]\xf2\x87\xca\xa2R\x12\x04\xc0\xdf\xf6C!\xc3\x02\x89\xb2b\xb4\xf6\xfeWr\xdd_h\x91h\x97 u\xc8~\x83\x80\x1c\xe3\x98\x01\x9e(\x8c3\x07\x8aa\xca\xae\xea\x99(q\xf5\xb9\x85\x12GIv\xaf(x\xad\xc9m\xca\xbdlZ|\xdc\xe5\x98\x10\x8f\x9d\xc7\xe6\xc0\x85\x88\xfe\x15\xa6\xd0*\x0f\xd7\xfe\"\xa0\x90EW4T\xdb$\x0b\x92\xd29\xdf\xa8\xb1\xe8\xc206\xb9\xb9\x98NB\x03\xb2\xa3K\xc4\xb40t\xae\xe4\xa0i\x82u\x87g\xd4;=\xbexp\xbf\x1cY\x89\x90\xcf&-o\x02\xcag\n\xfa\xca\xbd\xf0C\xa1C\xd8(l\xcf-U/uy\x80\x84fy\x12ve?\x15\xc2_\xc7\xddF\x1b\x93u\xf1pw\xcf\x1a\x03V\x0f6\xb8\xb1\xf6\xe7\xe2R\xa1R\x02\x02\x8c\x02g\x16\xb7\x90~\xcc\xe6Wt70\xa9H\xeb\xf6\xd5\xa5rH\x90\xe3\xcb\xac\x0d\xf6\xcf\"\xfeA\xd2T\x04y\xce\xc8\x9a\x9e\xd3\x0f9M\xb3\x99\xf8]\x83\x8c\xa9j\x91^\xc4\xd02\x12R\xd8Fi\x06\x94G\x15x(B\xa5\xaf\xa2\x8c\xf4\xadB\xc7gUiU\x11\x1f\x9e\xaf\x9f\xffC\x9c\xe0L\x1ee<\xab\x16<\xd1\xa5\x02\xd4I\xe4Ey\x98\xcd92\x9d\x12\xba!)\xa44;\x00?Ke\x98.\x85<\x14\x0c\xb8\x14\x91\x8b\x1b?m\xee\xa9Y\xe2[\xc99i\xff|\x9c\xfa\xe9{~v\xdc^\x84\xb8\xceWR0\xa5\xe4t\x08\xf4\xef\x9e\x92\xb3\x87h\x96\xe9.P\xe9j\xa6\x9ft|\xd8\xd2\x81\x85\xd2#\x85\xfc\x89\xa3\x86\x07\x98\x0bi.8\xb4\xd4\x90\\-\xae[\xf1S\xae\xf2\n\x93\xc3\xa0\xf5f\xf06\xe4\xe9\xa5\xdc\xee\x88V\xab\x94f\x10%\xd0\x9c.\xd4\xd2ZR\x9a\xd5\x85\x83\x99\xf2\x1f\n3[Be\xcb\xafH\x90:\x18\xf3\x8d\xd3BAD1?\x1d\x1d[\x9a\xa7X\x0c'e\x98oi\xe2{\xf2o\xfc\xe6\xed\x91\x90\xadGDH74\x94\x84\xcf\xc3R\xaf\xb6\\\xd1\xa7\x1c[@\xd3\xb4\"\xa1\x08\xe3\xe6<\xc5\xf1\x8a:\xd2\xb3\x89~\xcf\xc4\xd5\xdc\xd2j\xe4\x0d\xfc\xad\x8f\xa5.\x7fV\xaap\xdd\x01%\x0e\xec:\x07\x17\n\xbf]\\\x15\x8b\xf0d\xfdO\xa7+\x08\xe8*+\"\xe1~&\\#\xd2\x81\xccs-\x84\x80\x88A\x18\x9d\x17;\x91\x1dL\xe2\xf87\xa4b\xfd\x98\xad\xde7\xd1\xb2\xf6\x06\xa3(\xe7\xd0\x88\xdf\x83\x99\x11\x00~\xb8d\xf7VZe\x88\x0b\n\xf2\x07\x0bF\xaa\xa3\xf3C/\xc8\x97-#\x98\x88Q\xca\xb4\xb7\xd6\x8eq\x8d]3(\xd81\xdc\xb04\x1b\xc8\xde\x9d\xa6\xad\xddj-\x81{\xd4\xd9Y*\xceV.^\x95<2\x91\x9b\x15\xd2\xe4\xaf\xc3(i\xdd\x9e\xa446\x87\x10\x94\x19\xba\xb1\x8b(\nh\xf9],s\xb3+\xbc\xc7\xe0\xde\xbf6$\xdd\x98\xdaT\xd5n<\xa5\xe3@\xe16P\xdd\x1c4\x1e\x84\xaf\xe4\x82\xbf|\x07\x82\xe5\xa6\xa3\xb4\x80k\xaf\x97\xd7-\xc1\xfb\xdc\x9a\xa5K\x05\xf5\x14h\x0c7\xb1A\xf7#\xbd3\xc2jF\xd8\xd7\x0e\xa3\xbb!\x90N\x08W\x17\x84\xcd\x01\xe1F\x8bA\xce\x07\xc4%\xa4\x92\x9d1\xee \xd3\x15d\xba\x82\xa8\x7f\xff\x92\xae \xec\\\xd2q\x1f\xfb\x0d\xee\xf8!l\xe8\xc7\x02\xef\xdd*\x12\x8b9\x9a`\xb83\x7f\x80\xcf\x9e\xaf\xdb\xe0\xad?\xe3\xbf7\x1c\xf5\x15\xa9\xe4B\xfd\x85\xf7\xb5\xc4\x0c\xdbh\x99\x07Ty\xf0\x9e\xbe8\xbe,\x1e\x13x\xbf\x92k\xfdB\xcf\xdf:u\xea\xd0r2r\x125\x1d\x8cm\x125\xa9R\xc1\x80\xe33\xa5\xe1rNCfk*\xea_Ac\xae5\x01w\x8e\xd6G\x02\xf1\xbf<\xd9p\xe9\xa7\xe2\xdf\x8c-\xbc$J\xd3\xaf\xc5 \xcb\xcf\x16\x9d|\x16\x1c\x90\xc2*\x89\xb6<\xc3Yw\x94rd\xaa33\xa1\x1e\xf5\xaf\xe9\xe7Y}k\xb0\x11 \xc0\x03\xc6N\xcbG\x9c\xd0B\xb2P\xa7sq\x1e\x172\xce\xce\xe2&\xbe\xe9(\x9e\x8e\xe2\xcf\x7f\x14\xabO\xb3\x94zy\xe2g\xbb\x97U\xf1\x0f{\xe8J\x92\xa5\x90v\x92\xfa\xdeW\xcb\xe63\xc7\x1b\xea]]~<\xe77\xfe\xfa\xd35\xb2u \xd5\xe4\x15\x15\x8f,IF\xdaO4\x16\xbb&\xe9\x9c](\xcch\xd8S7$\xccl\xcf1\xdb\xc18\\\x10\xad\x8d\xbf7 \xabb\xb7\x0e\x9bi\xd8K\xc7V\x8a`\x97\x96\x07\x94\x9c\xd3y\x9a\xca\x941\xf1;\xdf\x14\xb8_\xdf\x00\xfe\xffk\x14`\xff\xafM\x7fx|\xff\xfe\xfd.\xb9\xe1\xf0~\xf5wN^\xfe\xff\x95\xe4\xfa\x1an\xdfn\xff\xc7K\x1a\xf8\xd74\x99X\xeb\x8f\xc3Z\x8f\xeb\x1b\xf0\x1b\xb2\xd6\x8b$\"K\x8f\xa4\xd9\xe5\xc7\xe3h\xbb\xf53W\x16c:o\x9e}loJ\x8b\xdejjw\x8fI\xdd\x11\xd9\xe4S\xd0oJ\x97_MhU|kz\xbe\xc9\xbf\xa0\x9fF\x83\x8f\x0d\xcf57\x084<\x0d\xba\x93Y\xc3\xdb`9\x915\xb9\x02Z>\x07\xd3\x01\xac|\xab\xc5\xf3\xd0Q\xa9\xa0\xe2}\xe8\xf2?\xe8d\x00\x0cr\x00*Y\x00%\xb9\x1b2\xd1\xfa\xc3R\xa8\xdd\x89\xbb'\xeeFr\xf7\xe3\xf6\xa6~\xc1\xdc\xbd!\xe9\xa6\xcd\xd7\x9au\xc2\xc9\xc9\xe3W\x0f\x1f\xdd\x7ft\xff\xe1\xa3\xe3\xc7\x0f\x1e=\xbe\x7f\xf8\xe4\xc1\xd3\x17\x8f\x9f\x9c\xdc\x7f\xf9\xf2\xf8\xe1\xb7\xaf\x8e^>y|\xf8\xea\xbe\x8c\xb5\xb5{\x1c\xb5\x19\xee\x87\x9f\xce\x88_\xdc\xa8\x10gLcC\x15\x13mm^\xeb\x89\xd7\xe9\xba>R\xf9\xf7\xa3\xe52\xa1i\xaa\xfc\xad\xed\xec\xa6\xde\xe6\xe1\x03\xa0!\xdbe\x9e\xe7\xcd\xde\xfc\xaaA\"/J\xb7Qz\xb8\xa4\xf1\xd5\xe3G^N~Y_}\xa2\xe4\xc9\xa7x}\xf5\xe1\xe1\x93,\xfc\xe5f\xf9\xe9\xfa\x11Yy\x0f\x97\x0f\xbe\xf9\n\xe0'\x12\xf8K\x92E\xc9^\xe6qM\x02F\xc5\xc3'\x1fwt\x1b\xd3m\x1c?}\xf0\xf1\xe9f\xf7\xe9\xd3\xd3\x9bd\xbdz\xfa(y\xf2\xcb\xd3\xcd\xe3\xd5\x83\x9bG\xe1\x83\x80\xdd]\"?DoH+\x8a`\xe6\x9d4#W\xf2\xcaE\xb6Q\x1ev\x18C\xf7\xe6\xed\xc7\xf7\x19\xb3~_2j\xe7\xf1>\x0cz\xf9\x91_\xf4\xd0\x8bu\x91\x93\x97\xf7\xbf}|\xf8\xf0\xdb\x97O\x0f\x1f>}\xfa\xf0\xe9\xe1\xd3\x07O\x1f\xbfz\xf5\xe8\xc5\xfd\xa3\xa7\x87\xf7\xbfyu\xf8\xea\xc1\xf1\xcb\x93\xfb/\x1f~s\xf4\xed7\xc7'\xf7\x9f|\xf2m\xf1\xc7\x9e\x07\xd56U\xaas'-\xdd\xd1\xab+\xaa<\xfc\x9c\x1c/k\xa2P\xef\x06=\xdef\xaf\xe6+\x9f\xd7\xe314\xd5W)?M\xd0-W\x80\xcb\x18\x85\xa4I\xd8\xd2-\xce\x10H\xfduH\xb2<\x19\xbe\xd5\x1aL`[H\xb9\x04\xa5[\xf5\xf5\xc9\xbb\xe3\xd3\xbf\xbe\xbc\xff`\x95\xbe\xfc\xf6\xd3_\x17\xaf\xbc\xbf}|\xf4\xe7\xe3W\xbb\xa3\xd35}\xfc\xb77g\xab\x1fN\xf3\xebO/\xfe\xf1\xe4\xe9\xeb\xdd\x87\xef\xd3\x0f/\xbf\xbd8<\xbd\xf1O\xe2?\xfb\xef\x16O~\xbaXfA\xbc\xfe\xfb\xf3\xd6\x90q\xbeP\xe7\xe1\x1ay\xc9\xccI\xfcU\xe5\xfeY7\xb8\xa4MF\xc3%M\xb6~\x98\xdd;\xcb\x17?\xd0\xdd\x05\xf5\xe2\x07\x8f\x9f\\\x1d*\xde\x1b\xf2\xc1\x84r\xc4\xa3\xebO\xf7\x1f\xfd\xb4\xc9~\xf8\xcb\xe6\xdb\xa3\xe3\xe3\x9f>\x05\xa7\xdf\x92\xcb(\xfdnw\xdf\xbfz\xf5\x7f\x7f8\xfd\xe9\xfb\xbf>\xfc\xe5\x87\xd7I\x94~\xdf\x16bO$\xa8\xe8\xfa:\xe2\xd8\xe1\xf6\xfd\xdbm\x0e\xa3\x1fr\x1a\xaa\x12\x1c\\1&\xb5+2\xb8\xa9Z\xac\xe5l6\xdd\x15S\xad\xa6\xf9\x80\x99\x8a\x8d\xd5\x9bn\x0dfTO\x1e>~T\xc7\xf4\xc73\xe8\xcfD\xe2\x14]r\xa3\xe0\xf2c\xc3\x0e3\xda\x05<\x81j\xee\xa9\x0c\x1a\xddI-\xc5\xad\xd7K1Y\xd3\x8eP8\xbc\xda\xca\x90\xc7\xbd\xc9S\x07\xb1/=\x947\x94\xecc\xda~g\\']\xd3&\xab\xa3P\xb2\xc3\xd8\xf6Y1 e'W%\x89Z\xd3\xa8,\xb6\xe2\x9d\x8f#IJ\xc7\x92\x13`\xb2\x7f\x0c\x16\x90E\xc4:\x16^\xfd\x9d\xdev\x93\xd2\xe6\x13`=~0\x06\x91\x8e\n`\xa6\x04\xd8W&\xc0\xb6>\x01F\xebP\x80u\xb5\x12\x10\x96\xa2\x003y\x04\xb8\x8f\xda\xb2\x1d\x05t-H\x01F\xf4\x06\x1b\xd0J|\x1b\xd9\x8d\xb8\xc163\x01f[S\xc0g\xb68\x05h\xedN\x01\x08\xbe\xb5\x91\x0f$\x1a\x03O (\x08\xbd\xadR\x01\xc6(0\xf4\x98\xc3\x00;U\x80\xcdZ\x15\x80\x98\x96\xc1r\x15\xa0\xb7_\x05\x0c\x19\xa3m\xd1\n\xe8y\x08ul\\\x01\xc6\xf9\xe9\xec]\xc4\xabf\xdbW\x80\xda\x02\x16\x80G\xde\xb6\x86\x8b\xf7;6q\xf1\xf7a\x87\xaeA\\\xed\xc2jP\x06\xd6\x05\x83]\xceZ\x18.\xb2\xe5ea\xc1t\xe6\xde\x9dk\xc3Fq0\x0e\x1b\x13n\xd8\x1eJ\x82\xa9\x89\xd4\xb1.4\xc4P\x1d\x95\xba\x0d\x1d\xf3\xaa\xa3\xb5\x0b\xb0\\\xaa\xb6\x01\xf4'?\x16o\xed\x94o\x9e\xed\n\x04\x8a\xb3\xd6a\x8b\x8c>%\xd3u\xb5s*\x7f\xc6\xb3Xy\x02ky@\xcf\x01\xea3\xd6\xb8I\xee\xe7\xa9F\xbaq\xa3\xf4<1M\xe7\xa4}k\x9b\xe7\x95\xfa$\xc4by\x11D\xde\xd5\xe9K\xb4\xber\xf1\xff;\x84!\xf8`$\xc9:7e\x94\x90(\xca\xdd\xc5\xdb\x8a\x8bg9\xbbz\x00\xb1{\x83\xb6\xd3\xcfau\x9c\xc8\xdfS\xb2\xa4\xf80\x1fOCm|c\xc7Ll\x11\xe9\xda\xe4\x8b\xafe\xba\xa4[\xdcD\x8aE\xe6o\xf5\xd1\xc3\xd6;\xb7\x1f\xdc?\xfc\xe6\xeb\xc3\x07_?\xbc\x7fy\xff\xf1\xb3\xc7\x0f\x9f\xdd\x7f:{\xf0\xed7\x7f\xbe\x7f\xf8\xac2<\xc2|;W\xf8@t\x13\x91\xfb\xc2;\x80-\x18\xe5\x14T@\xb1\xc5\x9ew\xb5\x1c\xbc\xc9\xb7\xd0S\xd7\xa9[6h\xf9\x18t\xbc\x0c\x1a\x8f\x10V\xa59R@8\xfe\x1c\xf6\xf7\xe1\xe3\xfa\x06{<\xcdj\xbeG\xb5\xb2$\x19\xd9'\xfek\x19\xbaN\xf79\n\xaf\x99\xff\xc7`:#Ji2'\xf5\xdc\x08\xed0\xd8\x1c \xe8\x9e\x1e\xf8|\x0d\x06EC\xfe^\xaa\x99\xebuW\xdd|XWs$\x8e]\xdf\xbf/\x8fb\xf4!\xbc\xa9\x9d\xd9\xcaW\xd4\xaf\x81\xf2\xfc\x06\xd4$\xbb\xe78h\xbc\xebv\x13\xa7n\xea6\xcfu@\xcd\x05w\xbe\x83\xea\x8c\x07\xd4\x04\xeb\x1b\xaa9\xef\xa1\xdfq\xfa\x19O@ \n;\x00L\x93\x07\xab\xf3\xc2\xda\xc6Ic\x17\x80\xc96\x00-u\xc0F!\x18H%\x85\xad\x00(>y\xf8\xb8\xcd(J\xbb\x01P\\\xddc\xe2\n\x1bboci\x0f\xf9\xbd\x8dh\xb6-\xf66\xac\xce\xce\xd8\xdb\x80]\x9bcoC\x19\xec\x8f\xbd\x8d\xa9\xb1E\xf66\x9e\xde.1\x0e\xe9b\x9f\xc0P\x1b\x05Tv\n\xf4;R\x146\x0b\xd84\xa6\xdav\x01\x95\xfd\x02h\\C\x13\x0b\x1a\xf8%\xd7\x0c\xc7T\xd3\xcb\xbd,\xa6\xe9\xeco\xbc\xfa\x07;\xfb\xc5\x17\xc7\xb6\xbe\xdaU\xb2\xdf8By\xb6\xa9U\x95\x00\xe3\xea+\x0c~\xb8\xa4\x9d\x04\x15\xeb\xfbu\xa3Z\x11\x91\xd3\x7f\x06y\x08\xd6$\xca\xc3aA>\x05Rv\x8fH3\xb2Uh/\x07\xc4\xe8\x8bE\x0d\xafv<\xad$\x94\xe3\xb5+\xc8u\xcaF\x80Qjmrk\x120+\x81`\xa0\x90U\xa0QH\x02,\x0b\x04\xc4\"\xc1\xac\xa2\x8a\x07l\x8aJ\x80Q] 0\xd1\x14pt\x85Qh\x8b\xc8\xca\xb1\xb3\xbf&c\xe6\x9b\xfc\xf2\xf8\x9bG\x7f\x0d\xae\xc2\x0f\x7f\xff\xdb\xc9\xcd\xfa\x9b\x9f\xc2'\xaf\xbf}\xbb\xfd\xe6U\xfe\x8f\xfb'o\x1f-~\xb9\xce\x7fy\x92\xdc|\x7f\xb8\xbd|\xf7\x97\xe4<\x7f\xfd\xfa\x1f\xd7GG\x1f.\x9f\xfe\xf4\xcb\x9b\xf5\xd9\xfd\xf3\xa3{\x97/\xe3'\xf9\xbd\xa7\x0f\x8e>$\xffX\xfd\xdf\xbf\\\xc4/\xfe\xfa\xfc\xb9t{\xb8Uz\x08 \xd9\xd2nI4\xea4o\xbbN\xb4\xaf\xebQ\x80\xd6\x8d\x026b[\xdc)`\xd0\xb9F\xa6U\xbaV\x00T\xee\x15@\xcf\xd1M\x1b*]-\x80\x9ex[\xc6\x0cn\x17\xb0\xa9\n\xb3\x92\xf8\x8d\x0c\x0d \x06\x0dh\xd5\x7fv\xedg\xd1}(\xcdg\xd5{f\xadg\xa5\"\x8c@I\x8d\xcb\x06lkT\xbbn\xc0\xea\xbe\x01\xdb\xc2\x86.H\xe3\xca\x81}\x8fk\xf4\xaf\xc0\xbeG\xb7\xbbx`\xdfS0\xb9{`\xdf\x83\xab]?\xb0\xefa-n \xd8\xf7\xf8\x06\x97\x10\xec{l\xb3{\x08l\xc3\xbb\xba\x89\xa0{\xea\xbb\xbb\x8a@\xe7.\x02\xdb\xa9a>14\xae#\xb0\x11\x01\xc0\xe4B\x02\x9d\x1b \x9c\xf0\xd6\xd1N>\x98\xc6\xab\x7f \x1fL\x8b\x05'K~\xb2\xe4k0Y\xf2\xea\x1f\x11\x82\x0e6a\x87\xc9\x92\xdf\x8b\xbe\x9f,\xf9\xdfh\n\x93%\xff\xf9\xc7\x9f,\xf9\xc9\x92\xb7\xe2\xad\xa3\xd5d\xd98\x05\xda:cv\x83\xc50\x12fe\xf0\x18\xfaY\x9a\x93\x0d\xd4\x84\xc9\x06\x92\xa0\x0bB\x83\x81\x8ba\x8fm\x91P\x81i\xc0P\x07\x11\xa0\x06\x0c\x9e\xfaeFSz\xab\x0fV\xc3H#h\x03\xd70\xd2\x00\xc6 6\xb8\x0e\xe2t\xe9\x13\xc0\xf1\x1b\xc76J[9v7\xb0\x0d\x96\xe06\xd8\xb9\x16\x10\x9c\x0bV\x81F\x11\x11F\x10\xea\n\x8cAo\xc0-\x1c\x90\x8b\x07\xbb\xda,\x1e\xb2o\xa7\x04\xab\n\x15`\xa3;\xe0i\x0f\xa3\xd1\xffs\xb5\x94\xd8c\x90\xfc%\x0d\xe8\x9a\x7f6\xa5\xf8W\x94\x9c\xd3\x1b\x92\x14r\xd4a\x9e.\x9b\x18\xf4\xb9r\xf9.\xa6q\xcb$v\xeei \xbc\xb3A\xb5\x1c\xd0\x9cyC\xbb\x11)\x8b\xb6\x0d\x9b_\xae\xab[\xac\xad.\xd4\xc6\xe0*\n\xb4\xcb}\xbcd\x92*63E\xeffR\x7f\x1e\xf6D.\xab `X\xae\x0b\xfb\x08\x18\x83\x89\x04\xb4YI\x80\xde\x88\xd2\x98P\x03,\xf2!_o30\x9d\x00Sw <\xf6Z\x9f\x00e\xc3\xb1qY\xe9K\x92\xbc\x17$\xa5\xe7\xf4\x03Z\xd6V \xbe\x87n\xe1\x13X?%\x9b\xe4\xc9\xc7\xcd&{\x9cl?\\\xd3\xf0\xc9\x83o\xc3\xab\xe0c\x90\x7f\xda]\x7f\xfb\xe9\xe9/\x1f~\xf1\xb6^\xf9zCX.h\xb8\xa4\x89\x14\x12\x88\x12\xf8\x81\xee\xf8W\xfcB\xb2\xe5_f]\xd3\x90&$\xa3@\xc4\xa7\x83\x08\xff\x06x\x81\xcd\xda\xf4\xa16\xdb[\x174\xcc\xe0\xda'p\xcc\xe7\x0d?E;\xb2\xa6 \xfc\x7f\xef\xee\xdf\xbf\x7f\xf8\xea\xc9\xb7\xf7o\x15o\xb9\xd6|\x0b\x84_\x7f\x9f/\x8a\xdft}\x05\xcch*+\xb9\xdbK\xc0\xf2\xe6\xa1|\xb3\xd1J\xc4\xf2R\xb3/\xcd\x9a\xa4s\xb2\xfc%O\xb3-u\xe8\x86|8{ 1\xac(\xdd\xb3\x92\xfe\x92$\x0b\xb8\xb1\xb5\xcd\x03\x92u\xf6\xa9\xfd\xd9\xad\xf2\xdd\xe6'e\xf5\xdf\xb3:I3\x7f\xcb\xb8~MR\xfe\xbd\xaa\x06\xf7\xc3\x1d\x8f\x84a\x94\x95_\x9f\xf6C\xf0\xa2\xf0\x97<\x14?\xdf\xf8\x8d\x8f\xe9I\x11\x9aGa\xb0\xbb\xfb\x15\xc0%\x95=9\xca~\xdfh\x05\xf1e\x1aT\x9dN'f\xaem\xd0\xba\x1c\xd6\x8b\xc24\xce\x17\x87\x9f\xbc_\x969\x8d?\xdc\xbf\xce\x1f|Z_\xad\xaf\x1e=\xa5+r?\xfcp\xf3)\\\x92\xf0\xc3\xe3\xed#\xef\x9b\x98<\xcc\x1f\x91\xf8\xd3\xa3\xf5\x83\xe4\xe9:\x8d?\xac\x9f\xac\x9fz\xe9\xc3\xab\xa7^\xbe*\xb0_G\x99\x1f\xae\xe7qt\xe3\xa0\x04\x0ek2Yz|\xe3\xc4\x8f\x12?C/\xb0\xc4rI?fg\x1c\x8b<\xf5\x10{\x1c\x17/(T`\xf3\xfb\x0c\x99\x9f\x05f%Ug\x04\xd3s\xe5\x90\xfc7\xd4\x93iF\xb2\xdc\xcc\x88+?d(I\x10\xec\xe6\x03\xfa\xe3\xde\xde\xd1\xf4vSUh\x15EM\x9b\xcf\xee\x97P\xf7>\x90E\x9a\x11_Y\x07\xd5\x0b\xdf\xed0\x1aora4g\xdac~M3\\\xb3m\x1b\xd24_l\xfdlnmg\"\xc2\xa2K\x1aGi\xb7n\xe9\x8f}\x8a\x14j\"\xcdHb!\xd4Y\xa1\x0f\xc6\x90d\x85P\x19\xb4\xd4\xcb\xfa\xc6 \x06V\x7fS\xe1\x8f\xbd\x8fXb\x17L\x1e\xd9\xce\x84\x01\x87(>Pw\xc9\x94\xa3\xe3\xe7\xb5Z\xfa\xd0r\x14\xa9\xb4BG\x07\xf6\xc0\xd1\xd4{=\x10\xa8u\x9d#\xa2\x9f\"i\xfe!\x08w\x1de\x16K\x00\xcbC\x91\xf9Hu\xb7\xeb\"\xfe\xa9\xe2/\xd6cV\xe5:\xc4\xf9\xe2\xcb\xb3\xf4~!~\xd0\xfd\xcc`\xf3\x1a\xa0\xb6WZ\x06UtEC3\xed\x97\xd2\x976O7$\xe9\xde\xb8\xb0\xe6\x17\xca\xf2\xd9F\xa1\x7f\x85\xec\x8c\xe7/i\x985lT\xc3\xc37t\x91\xfa\x19\xae\x13\x8a\xfc\xf8\xe9\xdc\x8b\xc2\x8cx\xca\xc0t\xe7%\xe5\x87f\x15\xcf.\xa2p9W\xb7h\xd3\xeb\x80\xdb\xf5\x97\xfd0K\xc8<\xfb(\xba\xeew\xe5\xbb\xfdI\xb3\x12\x8f\x8c.\xe4!\xc3\xc3L\x80\xbe\xf3\xa80X\xed\xac\xc6%\xe1\xe97\xf7\xbf\xbe\x7f\xf8\xf5\xfd\xc3\xcb\xfb\xf7\x9f\xf1\xff\xfb\x87D\xc9\xe3\xb3i\xef\xc6B An\xaer=\x0c\xb6\xe4\xe3|\x1c,\xde\x86\x84k:\x02\xb2<^\xb2kt\xaf\x16>:ZW\xc1\x0e\xb4\xaa\xae4\x00FW\xbb\xc5B\x10:eA\x02\xa2\xf0M\xa1\xd8Ba\xb2\xd9i\xd76\xd7\xf4mp\x8d; \x0c\xb5wRT*\xc2;}\xf6m\x9f\xc4\xa7a\x96\xf8\xfb\xf6\xa1\xf1oC\x93`\xde\xd9\xc6:6\x05!]\x9f\xf7\x12\xca\xa9\xdbQj\x96\xf7\xb6~\xa8\x90\xb0\xce\x0b\xe5>\x9e\xd4\x89\x86\xd8@\xed\xfa\xf1\xac\xdexF\xbbN\xc5\xb3\xdd\xb5\xe9V\xf5\x85\xa9\x85\xcfL\xb4\xe6\x91\xa9\xa3Z\xf5\xd49]~>z\xa5\x89\xe7\xf8\xc62\xcdPo\xf4\x93\xff\xff7\xa1\xabgp\xfb\xff\xb9W\xfb\xf0\xfb\xbd:En\xb7(\xc4$\x06_\x7f\xee\xb4U^\xc4\x94-\x7f\xdc\xbcc\xb0\x07\xa6\x12g\x17\xa3\xb6\xf6\xb1\xf2^\xf4\xd2O\xb3\xd3\xf2\xcb\xb2\x082|\xe1\xf7\xa3\x94\x06\xab97G?K\xb4\xfcKs\xbd\\\xf3\x8f^\xe9,\xd6?\xee\xda\xcf\xf2E\xe0{?P\xbc8\xf3GL\xbck\xfen\xed\x85\xbf\x0e\xfdp\xed$:\xc2\xb1\x898\x1ey\xca\xe4|:\x06\xaaT~,\xc2\x1dY\xe3\x04\x16;\x04\xdcB\xa2)d\x1b\n1\xfb\x13e\xc4\xe7\x01v\xf6'\xb6\xa9\xb0\x8d\x96y@g\x9a\xad\xe6\xbd{\x8eDz\xc79M\xe3(L\xf1\xba\xa2H\x0b\xa9\xd6\xd2\x98c\xf1kc\x92\xf2o\xd1\x8a\xff\xa7\x17% \x1f\x94]\x11\xa4\x1d1k\x91\x06u\x11g\x8f\xce\xf3D\xf9\xb5\x06\x85\x1c\xe83\x15\x18\x1c\xc1\xbb\xf3\x1f\xef%4\x8d\xf2\xc4\x93\xa9;\x1b\x92A\x1e\xfa\x1fr\x1a\xec\n\xdf\xe0\xca/\x96\xc5\xc6)\xd6\xd4B\x95\xd2\xc4'\x81\xff\x89.\xbfj\xfd\x12'Q\x16yQ\x00\x8b|\xb5\xa2 li\x9a\x925\x9d\xc1\xe5\xc6O\x8b9\xc36O3\xe0nB?\x04\x92A@I\x9a\xb51E!\x85[\xf7nA)~\x0c\x07\xe5\xa5/\x90\xd2\xf5\x96V\x04\x7fw\xfe\xe3\xed\x14b\xc2\xf8\"O\xb3\x16\xa2\x84\xc6 Mi\xd8\x19\x81\xbd\xba\xca\x83`\x07\x1fr\x12\xb0u/\x05U\n\xb4|\xfdwH\n~\xd8~\xf5=\x1b\xec\xde:\x8a\xd6\x01\x9d\xf15/\xf2\xd5\xece\x9ep#\xfc\xfd]1W\x8e,\xddDy\xb0\x84\x05\x05\xb6\xd8\x16\x1e\x8f\x84Q\xe8{$\xe0\xb2\xd1\x1e\xe5\x0e\x9d\xadg\x07\x8c<\x9c\x93n\xcdn\x81\x9fB\x18e\x8c\xe3h\x9c\xd1\xe5\xdd\xd9W\xed\x97NC\x88\x19\xc1|\x8f\x1e@F\x99@\xe5iN\xd82EAG\xec\x07l.Y\xc4\x17\xb9\xf0C\x92\xec\x80\x04\x01_o;\x05\x923H\xb6\xa1\xbb\xf60\xf4cL\xbd\x0c\xfc\x0c\xb2\x08\xf2\x94\xafN0\x7f\x98\xd1\x8f|k\x8e\xc2\xdd\x0c\xbe\x8fn\xe85M\x0e\xb8\xf8\xbe;\xff1\x85\x9b\x8d\xefmZ\xd8\x18\x02\xc6fm>\xf36tK\xe1\xfd&\xcb\xe2\xf7\x07\xe2\x7f\xd3\xf7\x07\x10%\x10F\xc5\xaf\x07\x9cS<\x12\x16\xd1\x16\xbe\xd2\x94f\x90\xc7\x1dr\xb3\x15v\xc6\xa0\xc95M\xc4B\xb7$N\xc5\xb6\xf3\x99f\x91\xe4_\xa8\xdd\xda\x80'\xfb\x04At\x93>\xebP\xff?\xe0tU\xcd\x8dmW\x9cD\xd7\xfe\x92.\xcb\xe9\xb3?\x924\xcd\xb7t9\xeb\xbe~\x14\xc2\xf7\x97\x97g\xf0\xdd\xc9%D\xa1do!2;\x9f\x06K \xf0\xcf6\xe3]\xeeb\xfa\xf3?\x7fn!+L\x08\xb63\xc5.\x0b\x05\xcc\xe9\x17'\xd12\xf7(\x90\x10h\x92D\xc9\xac;\x938\x0e|\x8f\x14kN(\xe3\x91\xe8\x86.\x19Y<\xe21Y\x8c\xa2\xab<.\xbe\x00\x97\xc2\x82\xa4tYL\xba3\x95w\xe7?\xf2q7\xe4\x9ao\xf5\xb6\xc6\x8dK\xc1\x8eDN\x93\xfd\xfb:\xf2\x97@\xc2nu\x91\x18\x94\x0bXBWQB\x0f\xe4k\x0c\x1b\xc9\xfc\x85\x1f\xf8\xd9\x0eBJ\x97|\x0b\x17\x14\xb8\x02H\xae\xe9\xb2\x83-\nA8\x9e\xf9\xa3\\\x02fp\xe7]Je=$[/c\x08&\xcb\x82#HH\xd6\xdd\xf5-\x12\xcaMF\x89nv\xb7\xbd\xb7o\xa2\x8c>\x83\x8c\xe9\xc1U\x91\x03F\xf8L\x0b\x99\xf6\xf2$\xa1a\x16\xec\x80\\\x13? \x8b@\nU[3\xaeV\xbe\xe7\x93@\xa9{\x17\xf9\n\x12\xca4*=\x00\x12.\x99\x84\x16\x03\xf0$4~\x8a\x96\x1c\xbe\xa0k?dW\x05\x91\x8d\xa6\x10\x97\x99\xe05\x12\xfb\xe9\xcc\x8b\xb6]}s\xc19=\x85(\xdb\x081\n\xdb\xf2\nw\x8a\x93\x9bn\xe3lW\x88\xc6]\xd8\xb2\x9b\x06,:\x02\xc9\xa7\xc9\xa6\x03>\xb3\xe9\x98\xa2\xe7L\x08iL=\x7f\xe5{\x90\xd2- 3\xdfK\xebL\xab\xf82\x95\xf6\xa0\x94\x86\x08\xb3\xa5\x1a?\x98O\xd0\xd7L\x08\x17\x14\x88\xf0\x1a\xd5\x8e\xc1\xce\xb9W\x1c!d\x11]S9\xf1\x0e\xfbq\xfa~\xa5\x1fWe\xc6\xb0\xcdd\x98\x13\xf9\xdf|3\xa5m\xc4\xdf\xb8W\xbc\x02\xe7g\xc7\x05\xa6-\xcd6\xd1\xd2h. \xe3\xcb\xd9Z\x8akVug%\xb1\xd1\xa0+hT\x99r\x15U\x90\xf6\x91\xd1F\x07\x0c\x074\xecZ\xd0\xda\xeb\x03p\xe9m\xf7~H\xadv\xfc8h\x156\xbd+\xe2\x06+(x\x0c\xc3\xca\xc5\x95\xe0\xfc\xec\xb8\xc6\xc3\xed\xe3\xef(t\xb8\x08wLj\xe5\x92\xf4\x8a`$3ZmB\x8fc>\xf77\x9d\xd5\xc6rOC\xb9\xb7\x91\\\x99\xc55lm\x03\xd9\xd98\x1eh\x18\xf3Mn\x12\xa5a\x14\x0f4\x88\xd9+M\xecu\xe4\x83\x0d\xe1\x8e\xe9;\x9e\xd9;\xc0\xe4\x1d\xd1\xdc\xedi\xea\x8ei\xe6\x8eb\xe2\x8eg\xde\x8eb\xda\x9a\xcd\xda\xfe&\xad\xd2\x88\x1d\xd5\x80\xb5\x1a\xaf\xa3\x1a\xae=\x8cV\xb3\x0b_\x80\xd2P\xd5\x9fMc\x1a\xa86\xe3\xf4\xfdQ\xb8{/\x8f\xa1\x94 \x17I\x16~\x960V5\x8c+5\x0b \"\xb9i\x02\x1f\x91\xe4d\xf2\xcf\xd5\x92\x18w\xd1=F\xeb\xf8\xe5 Yn\xed\x99d\xa2\xc0_\xf0\xc9\x14\xda(\x854\x8f\xe3(\xe1\xfa9&\xde\xd5\xbd\x83366\xe3\xefb\x1a\xa4$\x8d\x1f\xc2\xf1\x9f\xff\xdcP\x94\xaf\xa2\x08VQ\x04\xcfa6\x9b\xfdg\xed\x076\x04 w\xf5?\x91p7c\xc8_%\xd1\xf6\xce*\x8a\xee\xd6\x7f\x9c\xcd\xea\xda\xcf_\xc1\x1d\xf6\xf8;>\x85\xcb\xe8\xce\x9f\xd8\xf3w\xe1_\x0d\x1d\xd0|\xe7\xd7\xf6Z\x1eX\xd6\xf2\x17rM\x9c\x16\x03\xcf\xf9I\xc90!\xe7\xef\xa7w^E\xd1\xcc\x0bH\x9av\xa6/\x86b\x8f\x89\xd9\xd5\x1e\xfdO\xd5\xba\xca\x85=\xb4,\xecl\x97m\xa2\xb0\xb141\xd6\xab(\xba3\x9b\xcd\xee67E,\xeb\xce]\xc5V\xf1e\x9aV\xc9\x1e<\x15\x8b|yrq|~zv\xf9\xf6\xfcn\xd34\xaf6\xb2\x8dN l/\xef\x91ey\xdfE\x8d\x9b9[\xda\xb3\xe7\xf0\xa7x1{\x15E\xff\x9a\xcdf\xbf~\xd5\x1c\xfd\x80\x1d\xaf\xec\x99X\x1c6\xafI\x92nH\xc0\x16\xdd\x9ePs\x81m\xdc\x0d\xc4\xfe\xaa\x85\xf6]\xb8\xad\x10\xf3a9\x93\xf0\xa7\xfe\xcfs\x08\xfd\xa0\xc5\x00\xed\xd1\xca\x9d\xbe\xe4\xf7Q\xef\xaa\x94[i\xb8\xc0bW\x1dFR\x8f\xdc\xf8A\xc0~X\xd2\x15\xc9\x03~\x1aID\xb7\x15\x87\xcd=f1\xcf\xf8\x0f\xec\x80\xbd\xcd\xec\xa7R\x8f1\x1d\xc7\xe8\xce\xfe h/Q\x95*$\x0cv\xd2-\xda1\xbe\xcbc\x1b\xc8*\xa3\xe2\x8c\xe2\xd6\xfd\xed{\xb7%\xa2B\x97\xc9\xe1\x84\xbdY\xc4\xc9\xe0\xd6*\x8af\x0b\x92\xf0\x89~\xbc\xb7\x9b}\xba%\xd6'l\xae\xba\xb1\xc8\x87\xb9\xc5\x9e`j\xac\xf8\xe3_.\xde\xbe\x91\xff~\xfe\xfc\xf9\xf3:E\xd9o\xd5=B\x9c\x82\x11c\xe1\xe2\xc8\x10\x96Z\x9eRy\xfb[\xe7\x01I$\x86\xee\x8b\xec\xa1%\xadT\xfe\x01\xd0\xed\x82.\x97\x95\xf2?\x10'/)o\x1f5\xe5\xbc\xe2\x0bz\xff?lI\xef\x0bS\xbb<\xb4\xea\x04\x9aI\xc1x\xd60I\x88w\xc5\xe4\xa12AW~@\xebzCJ\xcc\x19M\xd2(l\xb1^qc[\xf9I\x9a\xcd9%\x9f\xc3\xe1\x7f\xaa\x1e\xe1-\xbd\x8a'\x1e\xa8\xf5\x12@\x0b\xfb-\xbe\xaa[\xcf\xe0\x96\x8a\xff\x9aS\x9e\x89\xf9\xdd:hb\xe03{C\xb6\x0c\xcb\x7f\x89\xa9\xfcw\xeb\x116\xb3\xd6\x13\xaa\xe9\x9d\xae\nS\xa9\xb97\x82\xbe~\n74\x08\xbe\xbe\n\xa3\x9b\x90s\xfe\x86\xa4\xec\xa2\x97\xa7Y\xb4m\xb0S\x93\x01\x0e\x84)\xd0\xe2\n!\x8a\xb5\xc1\xd8\x86\x87k b\xbb%\xaa\xf7\x9c\xd5\xe4\xaeo\xa2`)\xb6\xbc6*\xbfo\x16\xdc\x02\xc5\xcd\xaf`\x16\x89\x85\xa3,\xb9\x03\xee09\x92\x8b\xeb\\M\xe4\xed\xf6\xe7\x7f\xfe|\xf7\xd9\xf0\x9dk\"mo\x1e_\x1eCr8{p\xf8 \xbd\xd5\xd8\x16\x80u\x12{\xb35\xc9\xe8\x0d\xd9\xcd\x92<\xcc\xfc-\x9d\x9d\xb0\x1b\x10\xda[B\xab\xa7Am\xa3z\xd1\xd2\x92@VY\xb1~\x98=\x94=\x98\n\n\x1aqw\xaa\x03\xb2=\xa4-d\xca\x18\xab\xc1\xd3e\xf3\x12\x8f\xe6\"\x12\xa0\x8f\xb5\x8e\xe5.\x12\xd0\xdfi\xd4A\xa5\x8d\xb8\xf6v% \xe8\xedP\xea`2\xc7]{8\x97\x04\x0ct1)\xa8\xa5\x89\xbe\x0ev7u\xf0i\"\xb0\x83]O\x1d|]WT1\xceh\x0e)\x01\x03\xdcR\x12\xc1h\xce)\x01=]T\xe5lFsT \x18\xc5]%`<\xa7\x95\x80Q\\W\x02\xecq\xd9!n\xac\xae\x16\xd5\xc4f\x879\xb7:\xc8T\xd1Z\x84\xcbK\xc00\xc7W\x07]7\x82\xdb\xcb\x1d&@\x11\xc55\x1e\xc5\xdaH\xae\xfd\x94\xee\xe9,\xeb*.\xe9<\xab\xb9\xcc\x04\x98f0\x86\xfb\xac\x81P\\\x81\x9a[1\xd0\x95&`\xb8C\xad\x81\xae{\xe0\x0et\xb15pe\x0dw\x9b\x80\xbeN7\x01Zo\x95\x00\x85\x03N\x80\xd1\x0d'\xa0\xe5\x97\xe0\x80s\xc9\xe9\xdf\xffU\xbdvg'\x9d\x00\xdc\xe2M\x0e;\x01\xa6\x95\x1a\x9dw\x02\x90.<\x01-\n\x0cq\xe7 \xd0:\xf5\x04\xa8]{\xe5oJ\x07\x9f\x00\x0dU0\xce>\x01&\x97\x9f\x80\xba\xe3O@O\xf7\x9f\x00\x8b\x13P\x80\x9b+P\x80\x8a\x14F\xb7\xa0\x80\x11\x9c\x83\x02\x94\xe3\xb78i4w\xa1\x80\x11\x9d\x86\x02Fs\x1d\n\x18\xcb\x81(@\xe9F\x14P\xf7\xfe\x08\xa8\xbb\x14\x05\x0cw,\n\x18\xc5\xbd(`<'\xa3\x00\xbb\xabQ\x80\xd1\xe1(\x00\xe1vl<\xa8u>\nhk\xd4\x8e;K\x00\xd6\xa9\xa5wG\x16x\xecN\xc9\xe2A\xb3kR@k\xf2c\xb9)\x05\x8c\xe8\xac\x140\x8e\xcbR\xc08\x8eK\x01C\xf6\xdb\xe8\xc4,P\x19\\\x99\x02~\xadr\x17\x17$\xbc\xea[\xd5\x93\xd2p9\xa7!\xbb\xc2}Q\x9d\x9d;S\xaa?\xdfnTi\xbeY\\\xd0py\"\xd0 G\x8a\x17\xf9\xa1\x98\x0e\xbf\xc77hP\xf4\xbb\x81;7\x1b\xca\xaf\x83\xa4\xbb\x08\xf0\xd3&C0\x04\xec\xed\xbb\xf2\xcc,\xce\xb8\xb9\x89\xba\xf5E\xf4\xa8\xfaa\x9b\xde\xad\xfai\xb0\x82H\x97\x0d\x82\x17\xa2\n\xd9=\x97\xb5(_\xde\xb3\xc3\xd9\x8d1\x9cJ\xe1\x1at\xfd\xdf&[\x1c\x0b.\x10D&\xa2\x87Qq\xb0\x89)\xf9\xa1\xd0WL\xed\xb1\xeb(\x1f\xb8e=\xbey{y\xf2\x8c\x1f\xc6\xe2\xe7\xe2\xe4\xf3\xf9\x05\xf64\xcc\n\xbdU^\xfa\x1b\xcaK\xd8'MN\x92}\xf0SH\xe8\x87\xdcO\x841\xb5\x8e\xd6\x11W\x1c\x95Q\xd6,\xd5.6Jf\x90\x96\xff\xcd\xcc\x81 (\x1c\xa1~X:\x17b\xb2.\x96\xf7L\x8d\xb1z\xa0\xc5\x88\xe5\x9f\x0bsH&\xab\xf6\xcaW\xe6\x9f#k\xd4\x82\x82i\xef\xb5\xce\x0d\xd1\xd1\xb3\xbd\xc3\x15~I\x17\xf6\xcf\xc2\xdbF\xd2T\xb8\n\xcf\xc8\x9a\x9e\xd3\x0f9M\xb3\x99\xf8\xbd\x85\xe4\x03\x13#\xfe:C\xc7H@a\x1b\xa5\x19P\xee\xdb\xe2\x8e\xb0:\xf7w?\xeb`]P'\xfb\xb8\\R\xc7O\xc3\xd1\xf3\xf5\xf0\x7f\x88^\xcdl\x9f\xa5\x97\xb3\xe6\x92[\xb5\xde\xad/U\xb4z\xe6H\xda\xa7\xdb\x0dI!\xa5\xd9\x01\xf8Y*\x9d\xb4)\xe4\xa1`\x84\xa5\xf0\x93\xdd\xf8E~\xa6)U\xbf\xab{09\xce\xb5\xd7\nl\xe7g\xc7r\x92\x9d\xcc\xfd\xae\xca+^\xee\xab\xee4\x12Q\xfc\xda\x12\xb1\xaa\xc6\xd1\x0f{\x89\x00\xbe\xb7\x10\xaa\x81\x90a7Zd\xc1\xecD\xf1\x8a\xa9p\xa2K\xfe\x91\n'\x1ch\xa8>fAs^\x81\xee{\x02\x9as\x0b\x0cg\x17\xe8\xce/0\xbbi\xb5\x06\x0e\x18\x8c\x1c@8q\xc74v@k\xf0\x80\xca\xe8\x01\xab\xe1\x03\xda\xc5\x0d7\x80\x8c\xac\xdf\xaa\xb3\xa8c\xee\xb2?\xd7\xf7\xecB\xf2\xf1\x1e\x1b\xa3\xce\x9e|\x06F\xe6\x17m\x08\xde\xae\x9c\xd9\xbf-\xdd\xcd\"ka\\\x14\x12\x9b\xf21~G\x9a\xa7M\x14\x8c\xea\x91\xef\xb8\xe9\x1e\xfe\xa5\x16\xf1\xaa\xf3\x0e\xa4\xb5\x0e\x120\xd9\xba_\x90\xad[\xd8B\x05\xdfk\xa5@X\x0bm\xc3I\xc7\x17\x18&\xac\xbdV`\xebX\"\x1an\xac\xe9a4\x03\xb6\x98C\xb1\xcf\xaeW\xc9\x92\x0d\x06\x1e\x0b\xd51 \xd05t\x7f\xb9\xfc\x94\xce\xb8\xee\xac\xf9\"J{\x13M\x04{g\x18{\x0d@\x83\xfb\x0b\xf3\x9f\x14\x96lB\xb3< \xc5\xd7'\xc4\xfc\x8a\xfbKyW\xe0\x17\x84\xb5_?y\xcb#\xc1|\x0b\x98\xc1\xdb\x90\xb1d\xc8\xcdB\xd1\x11\x08\xa2\x84M\xa1\x86\xacJ\xc5Ii&\x99\x1c\xd1>H{]\xd0\xaf\xbd\x98\x02_~\x98oi\xe2{\xf2o\xdc3\xe7\x91\xb0\xfc\x1a\xc7\xcd\x86\x86\x92XyX\xde\"\xea\xa7\xfb)G\x15\xd04\xadV-\xe2\xe5y\xca\xa8sEM$(\x16^\xc3\xd7$A\xef\x960&\xab\x88#\x95\xa2\xae\xbb2\x89+a\x9d3\n\xc5\x90\x07\x0d\xa5.\x82\xc1\xd5\x1fNW\x10\xd0UVd\x05\xf8\x99pm\xca\x00\x07\x97+\xc1tb\x00F\x8a\xc5\x0e(\xf16@\xe2X\xae\xbbv\x133 6\x18\xd7YC\xc2V\xcbw8\x82,\xc9)\xbb2\x82\x1f.}\x8fd\xb4\xcc\xa0*V\xc7\x1f\xec\xec\x8b\x1fzA\xbel\x04,\x084Z\xba\xb4)\xc9\xcf\xc5\xda\xd5\x93\xa9\xd1\xa6\xaf\xe0\xddi\xda\xa0]k\xc2\x12>\x14\xb5\xcd\x0f\xc8\xf4O\xf1\xed\x11\xf0H,\xc4_\\\x94\xe5\x9f\x93<(L\x898\x89<\x9a\xa6\"\x08\xcf\xe9\xa1\xc0WX\xc5\xfcg\xfe\xa9\xc9\x03E>Ta:rLAP{\x18\x96$#l\xbd\xb9'\xe6\"\x13w\xc4,4\xb5\x1e\x9c\x802\xc9\xfb\xb6\xc2 )\xbeOB\xc5g\x06E\x06\xc0\x96x\x1b?\xa4\xed\xf4\xa5\xee\xd71%\x18\xb6B\xf7\xb1z\x94`\xaa6N\xd5\"\x1e\x89nI2\xfa5{\xbf\xf5\x04\xcfU\xd1\x7f\xb3\xbd\x90\xa08\xa1\xd7{\x12 \xfd\x07\xc5\xd1L\xae\xc8V\x06\x9b\xda\x96`\x9c9Xg\x0fzu^\xfelT\xeb\x12L\xdb.\xc1\xfc\xedu+\xb9\xc0N2\x8b\xfa\x17\xc0Y\x867\x9e\xce\xe6c\x9e\xa1>\x1bq:\x92\x91\xc1V[\xf6Q\xbbB\xd57\xdc\xb5_q\xb7j>\xe3\xc6\xd8-\xa1\xcb\x8f\xa2YU\x99y\xc8\x8d\nq\x0b\x12\xe6\xc3\xff\x08B\xcd\xc4\xed\xe6\xcf\x87\x8a\xa4wy#\xe35\x8fA\xc0\x16\x0f\xfc\xe2L\x12*\xf4\xce\x0c\xe0o\xf4vB\xe1\x97<\xcd\x80\xac\x13J\x99\x1d\xa4\xad7\x8b\x12\xb6\x8f<\xb7S9\x1e\xafY\xddR\x12\x16\xb3\x17S<\x8a\xe3\xefI\xba\x81eDE\x9dT\xe1\xacc\x83\xa4\x94M\xabi\xf9\x14|\xfb\x92\x99_\x8d\x14\\\xee\x98]\xd5?\xd0\x9cJ\\\xcb\x86\xb1WC'\xa5k0\xeb\xa8\x11\xc10\xfe\xd1\xda\x006\x0b`\x99\x0b#\x93\xce\xaf\xa3\x8c\xce\xf5\x93\x13`\xb58\xec#B\xf1Y\xc59\xd1\xff\x8e\x1a\x08\x90\x83\x81Dg|\xc2*\x89u\xa0a\xaeL{h\xc2\xd7pq\xfa\xdd\x9b\x93\x97\xf3\xd7\x17\xdf\xcd/\xff~v2\x7f\xf7\xe6\x877o\xff\xf6\xa6\xc7\x9bg\xe7'?\xbd\xbd<\xe9\xf7\xe6\xf1\xdb\xd7\xafO/{\xbd\xfb\xf6\xec\xed\xc5\xd1\x8f\x96W\x0b\xb7\xff\xb3\x9e\xeb\xb5\xab\xb1&\\\xf8\xeb\x90._\xa7\xeb\xcb\"Q[\xd4\x113\x91N\xf9O\xf5\xda\x15\xb5\x02jBy\xb2)\x95Q\x0b\xb4{\xf3\x8c\x7fZ\xb4[\xb9\x8d\xc2 \xe8\xfc\x0c\xe4\xa7\xbf\xcdht\x97\xb3&804\xc6\x82\x17\x90Dy\xa8L\xdd\xa9\x03\xee\xda `\xa5\xe8\x08\xa1\x06\xfdM\xaf H\xdd\x01\x0e\xfa\x03\xac7\x98\n\x1c\xc8\x0e\xb6\x13\xbe\x0d\xa8ka\x13\x1c\xa8\x01\x8e\x14a`\xb9@6\xc1\x85/$\xe0YS\x02v\xa3\xc0}\xb3\xc0u\xc3P\x97R\xcd+MO\xa5\xee\xd1-M3\xb2\xd5\xf8\xdaj\x0f\xe2\x17js\xbb4\xc1\xf0]:5\xf4\x98\x89\x95\xd4\xd5$\xf8'\x89pS\xc0\xf1!^?\x95\xd1\x06\xdc\xf0cR\xc0\xe5\x08e\xa7TU\x98\xc4NOvk\x8f2zPt}\xd8\xfa\xa2\x13\x85\xf8'7\xd6\x8c\x08\xf9\xed\xbf\xba\xdb\xb39\x9b\xcf\xd1\xday\xab{\x84[\x88\x8b\xc9B\xc4\xbf9Y\x88\x15L\x16\xe2d!\x9a\x00\xa9;\xc0A\x7f\x80\x83\xe1\xe1@v\xc0\x9f\x01\x02&\x0b\x11\x01\xd8\x8d\x02\xf7\xcd\x02\xd7\x0d\x9b,\xc4\x0e\xf4\x98\x89\x95\xd4\x93\x85\x88?B\x7f\x17\x16\"W+\xf3\xeb(\xf3\xc3\xf5<\x8en\xcc\xba\x0eIP\x9c*\xa9x\xe9\xf3\x8e\x8b\x12e\xc7\x11m\"\x8c\xe5\x9b\x97\xd2\x91\xcc\x98\xe7\xa4p#Wnw\xe9X\x16a\x9a\x92\x80Zt\x85\x99\x96\xddD\x0c\xc7*\xf0=\xb6\xcf\x9c\xd34<\x110\x83g\xee\x05>\x0d\xb39\xc92\xe2]}.wvm\x86sCN\x8d\x00\xc4\x98\x80\x1c\x17JB!O{\xe4\xd8\xe00>hR\xa1\xd4\xe00\x01p\x9c\x04\x98\x92\xa9\xd4\x80M\xb1R\x83\xe3Z\xa0\xc7z\xc0\x9c\xa4\xa5\x06\xa4\x02h\x83T\x08\xda\x84.5h\xd3\xbc\xd4\xf09'\x87U]m\xc0\xa5\x8f\xa1\xd1\xa9\xd3\xcc\xb07O \x96\xe435`S\xd2\xd0\x08U\xa9k\xf6D55`\xd3\xd7\xd4\xa0OjS\x833\xe3\xe1n\xd0\x12\x9c\xd1c\xcf\xfc:\xa8S\xe8\xd40`B6\x93\xa0 \x96$<5 S\xf3\xd4\xf0\x99\x14\xaf\xcb%\x11\xfaQ\x1c\xf0\xf6{\x13z\xdc\xf2%\xf4\xa0\x1e\xf4\xa4 \xb8\xde\xfe%\xb8\xdc\xbe\xda\xe0.V\x12\\7\x1c\xfao:\xf4\xdd\xf8^\xde\x02\x01\xf6\xd4G5\xf4Xb\x8f\xa5\xe1\x93'\xd5`H\xa9T\xc3\xe7X\x965\xe1Q\x0d\x9fcj\xfa6;z\xc0f\x80\xa2\x11\xea\x12\xee\xbb\x80\xcb\x1fU\xc3\xe7 \xa7-\x03U\x0d\x9fcf\xfa\x1cV5|\x8e9!\xb2`\xd5\xf09&g\xc9\xa3U\xc3\xe7\x98\x18.\x13W\x0d\xf6\xfc\\5\xec\x7f]}ni.\x89\xc0(\x84\xbada5\x88C\x14CBGc\xcb\xd5\xc8\xfa\x02\xef(\xa8\xe8\x9f\x84>v\x1e\xde\xdb.\xc1\xf9r\xe2\xb6i\xd0c\xe3\xa0\x87\xb9\xd9c\xfb\xc0]\x1c\x05L\xf7\x0b-\xb8\x8b\x84\x04\xd7\x0d\x87\xfe\x9b\x0e}7~\xc0\xfd\xc2)*)\xa1\xaa\xd0\xc6RFPD\x9d%\xaf\x06m\xee\xbc\x1az1p?\xf6\x95\x9ai\xbe\n\xc8\xda\xe5\xc5\x01\x8c\x81\xcbLj\xc2\xd7\xf0\xe2\xc7\xb7\xc7?\xccO_\xce_\xfdx\xf4\x1d2k\xa7\x0dm,G/.N\xde\xd8\x93\x8e\x9a\xd0F\x82\xcc\\jB\x1b\xc9\x9bS[\x02S\x13\xcat\xa6\xe1dq\xbf\x85 \x10B\xb6|\x15\x90u\xd9\xe2F~?\xfeE\xe0EW\xa7/\x9d\xfc\xcb\x02Jq\x04_Dim/T\xe0\x1c\xe5oBo~\xee\xad\xe6\x10\xb1\xd4.\x0c\x9e\xa6\x9bsU\x00:m\xa0 \x83\xe7\xeaD\xd2>v\xbc\x80cnN_\xf8k\x91\xa9\xc7l\x0f\x19Z\xe0\x99\x08\xb24\xcb\x01\xa5\x1f\x02)\xf0\xda\xcd\xf9~s\x17\xd8\x9b\x85ee\x94\x9bW\xad\xe9\x1b\nt\xe1\x86\xa4\xc5\xb5\"\x13\xd5yDV\xa9UN\x0f\xf3J*\xf9ktSS\x83\xc3\x19\xe7r\xb2Us\xb5?\xebz\x92;\x9c\xe2\x0e\xab\x13\xe0\xb2F\x01\xce:\xae\x970\xf6\x10\xc48_t\xdb\x8a\x9b\xc0\x99X\xd0\x8b`\x0c\xe8\xf2\xc1\xe3\xc7\x87O]^\xe9I8\xe8G<\xe0\x0d\x1e\xbd\xf8\xc1\xe3'W\x87_\xf24\xfbX\x0dg\xf9\"\xf0\xbd\x1f\xe8\xae\xe17\xb9\xa2\xbbV\xf7:\x07\x94yJE_\xa7Z\xdd\xf5O\xa5\x0e@\"\xc2\xa6p5\xa1\x17\xbd\xfb\xdc\xddJ\xcfY\x9c\xf8Q\xe2g\xce\xa2\xb5\xd79\xca\xd9a&\xe5(\xe9\xae2\xee\xa8\x12{\x10\xc7YT\x1c\x95\xa1#\x81\xa0\x07\x91\xa0\x9f\x1a\xecA,\xe8C0\xe8\xab\x00?\xdf\x04\xddU\xdf\xe8\x8ao\x04\xb5\xd7G\xe9\xf5\xa0\xb1\x9b2\x81!\xean\xef\xb3sK\xf8-\xdfr\x9b\x16nJ\xccR\x8f\xc2\xb9\xdd\xfd\x8e\x1c\x1d7\xeab\xf7\x89\x84\x99\x1f\xd29\xce\xce\xc6\xd9\xd7\x08\xbb\x1a\xad\x17\xf1\xda\x10}X )(\xc0A\x9d\xa0\x8f\x06\xf4\xe2\xc1\x89\x00\xe0z\x108\x11\x02\xdc\x88\x01\xeej\x7f\xbf\xd3qQ\xf2X\xf5\xce?\xbbiC\x06\xfd\x15\xbb\x9bfr\xa2\x1fN?\x08\xe8\xa1\xc0\xf70\x177e\x8d\x9c\x00rh\x8cg\xcfqD\x9b\xd7\x0e\xeb@\xfa\x91\x1d\x18\xc7\xbcF\xe1\x88\x97(\xd8*%\x84\x13H\x8b\xafVSC\xb2\x8cnc^%\x91E\xb0\xf5\xd3\x80\x92%\x10Q\x17\x01\xa2.\xa2\xeeA\xaa\xa5\x835 \xa5Uxz\xe56z\xb3HM\x14Y\xe0Ct\x99\xedD\x86\x0d]\"M\xfa\xdd\xac\xcf\xa7\xf6\x8f\x1c0b\xf9\x85\xb4\x7f\xb4\xc4(M\xd1H\x935\xb5\xaf\xee\\\xa8\xf8 \x82x\xe6\x98\x9fkt\xcf1\x8e\xe7\x18\xb1\xc3\xc7\xe6zE\xe1\x1a\xfbo\x0d\x9f\xe1\x02b\xe8\xd0\x17b\xab\x10\\n9\xde\x1c\x061\x1fk\xd6\xb0\x93\xc3H\x9a\xe54\xceMl\x1cH\x1f\xdd1\x1f\xc3\xe8\x88\x8d&\x1a\xd3B\xa7\x88\xcd\xa8\xc7\xd7\xb5\x907~\x86\xa9xW|\x8c\xa9\x8d\x01\xce\xcf\x8eU\xdf\x04\xd3\xb6\xb0\xff\x91\xb1\xb7\xc015\xb0\x9f\x1a\xd8s\x18\x89\x9eS\x03\xfb\x0eXP\xdb/\x0b\xb8\nD\x98\x1a\xd8\x1b\xb6b\xf4;\xc9\xd4\xc0\xbe\x01\xd3\x0d\xa6\x0eVr\x81\x9dd\xa8\x1b\x8c\xbd\x8a\x0b\xc5\x91\xca)\xe0k\xb0\xa6\x06\xf6\xe3\xce\xd1V>\xd4\x17\xef\xd4\xc0\x1e\x00W6c/\x90\xe97\xfe\xd4\xc0\xde\xb01vKhj`?5\xb07Z\x00S\x03\xfb\xe636\x1bD\x00\xae\x08`jO\x8a[\xaf]\x8d5ajOj\xcf\x9c\x007\x86\xc6X\xf0\x02P\x05\x8a\xb8k\x83\x00S\xd8\xa9 \xd8BD\xa4\xee\x00\x07\xfd\x01\xd6\x1bL\x05\x0ed\x07\xdb \xdf\x06\xd4\xb5\xb0 \x0e\xd4\x00G\x8a0p* t\xe1\x0b x\xd6\x94\x80\xdd(p\xdf,p\xdd0\xd4\xa5T\xf3\n\xa6\x10\xd0\x1a\xce(\x1f\xc4/\xd4\xe6vi\x02:z#\xa1\xc7L\xac\xa4\x9e\xda\x93\xe2\x8f\xd0\xdfE{\xd2\xa9\x81\xbd\xeb\x9b\x93\x85X\xc1d!N\x16\xa2 \x90\xba\x03\x1c\xf4\x078\x18\x1e\x0ed\x07\xfc\x19 `\xb2\x10\x11\x80\xdd(p\xdf,p\xdd\xb0\xc9B\xec@\x8f\x99XI=Y\x88\xf8#\xf4wa!\xfe\x86)\xd2S\x03\xfb.L\x0d\xec\xa7\x06\xf6\xb6\xe7\x9c&\x00\x8e\x93\x80\xa9\x81\xbd\x00\xa4\x02h\x83T\x08N=\xe2\xa7\x06\xf6v\x98\x1a\xd8\xab\x01\x9b\xbe\xa6\x86\xa9\x81\xbd\x19\x06L\xc8f\x124aj`_@\x0f\x8a\x03\xde~oB\x8f[\xbe\x84\x1e\xd4\x83\x9e\x14\x04\xd7\xdb\xbf\x04\x97\xdbW\x1b\xdc\xc5J\x82\xeb\x86C\xffM\x87\xbe\x1b\xdf\xcb[ \xc0\x9e\xfa\xa8\x86\x1eK\xec\xb14|\xf2\xa4\x1a\xa6\x06\xf6nSs+\x12\x17\x80\xcd\x00E#\xc47x\xc3\xe5\x8f\xaa\xe1s\x90\xd3\x96\x81\xaa\x86\xcf1\xb3\xa9\x81\xbd\xe3\xe4\xa6\x06\xf65\xd8\xff\xba\xfa\xdc\xd2\\\x12\x81Q\x08u\xc9\xc2j\x98\x1a\xd8\xeb\x01\x15\xfd\x93\xd0\xc7\xce\xc3{\xdb%8_N\xdc6\x0dzl\x1c\xf407{l\x1f\xb8\x8b\xa3\x80\xe9~\xa1\x05w\x91\x90\xe0\xba\xe1\xd0\x7f\xd3\xa1\xef\xc6\x0f\xb8_8E%%L\x0d\xec\xad\x0d*\xd4\xd0\x9b1p\x99IMpmq\xa1\x06\xc7\xc6\x17jpl\x87\xa1\x06|\x93\x0c5\xf4j\x9d\xa1\x06\xf7[\x98\x00d\x07\x0eG\xac\xa8~\x1djp\x8e\xf27\xa17?\xf7Vs\x88Xj\x17\x06O\xd3\xcd\xb9*\x00\x9d6\xd0\x84\xc1su\"i\x1f;^\x00\xb6q\x89\x03\xca\xa9\x81\xbd\xe9Q\xa73\xce\xe5d\xc35\xd6\x94\xe0v\x92;\x9c\xe2\x0e\xab\x13\xe0\xb2F\x01\xce:\xae\x970\xf6\x10DtcN \xce\xc4\x82^\x04\x03\xd7\x86\x9d\x12z\x11\x0e\xfa\x11\x0f\xdc\x1byJ\xf8\xbc\xd3\xecc5`\x1b}:\xa0\x1c\xa1\x93\xb3k\xe3O \xbd\xe8\xdd\xe7\xee\x16\xbb7\x04\x95\xf0\x19\xe6\x18O\x0d\xec\x0d\xe0\xa8\x0c\x1d \x04=\x88\x04\xfd\xd4`\x0fbA\x1f\x82A_\x05\xf8\xf9&\xe8\xae\xfaFW|#\xa8\xbd>J\xaf\x07\x8d\xdd\x94 \x0cQw{\x9f\x9d[\xc2o\xf9\x96\xdb\xb4pS\x9a\x1a\xd8\xab\x01\xaf\x0d\xd1\x87\x05\x92\x82\x02\x1c\xd4 \xfah@/\x1e\x9c\x08\x00\xae\x07\x81\x13!\xc0\x8d\x18\xe0\xae\xf6\xf7;\x1d\x17%\x8fU\xefS\x03{\x1d\xeca.n\xca\x1a9\x01\xe4\xd0\x18\xcf\x9e\xe3\x886\xaf\x1d\xd6\x8145\xb0\xaf\xc0\xb4\x9bS\x03{D\xfc\xd5z2\xd9O\xa3\x7f\xb7\xf6\x8f\x96\x18\xe5\xd4\xc0\x1e\x13\xc6r\x8c\xe39F\xec\xf0\xb1\xb9^Q\xb8\xa9\x81=\xfaX\xb3\x86\x9d\x1cF\xd2,\xe7\xdf\xa5\x81\xbd\xa2\x81\xbc\xb1}}\xd5\xb8\xbe\xf6f\x81\xae_\xf3\xfa\xd2\x8c\xbd\xa0Y\xcf\x1e\xf6\xedS^\xb9\xfd\xaa\xc3@u]U\xa9\xd3\x8e\x1a\xd5\xa8O\x9d\xda\xd4H\x9f\x96M5w@\x83\xd26)l\xf6\xda\xc3\xac\n\x1d\xddAG\x82(\\\x8b\x1d!\xdd-cZ\x93+}1\xabE\xd7\x9c\xaa\x8f)\xad\"\x05\x9b\x9dI\xc6\x0f\xfc\x05\x9fj\xa1\xd7SH\xf38\x8e\x12~r\xc6\xc4\xbb\xba\x97\x87\xec\x7f\xd8y)\xf6\x9b[%mt\xdc\xa2Q\x1a\x0f\xd1\n\xf2L(\x1f)\xce)S|d\xb9\xf4\x85l\xc3\x9a\x864!\x19\x9f0\xbb:\x94\xc5\xfbG\n}'\xb6\xa8;\xce\xc9G\xc2\x18\x18\x0e\x9f\xc1\x19\x9b/\x93\xe3b\xea\xa4\xdeQ\xef\xf8\xcf\x7f\xd6\x1cS\xaf\xa2\x08VQ\x04\xcfa6\x9b\xfd\xa7\xf2\x11F\x04\x12\xee\xd4?\x92p7cC\xbfJ\xa2\xed\x9dU\x14\xddU?6\x9b\xa9\xcf\x1e\x7f\x05w\x18\x8aw|\xd2\x97\xd1\x9d?1\x1cw\xe1_\x1a}\xaa\xc3\xf3\xab\x9e6\x0f,\xb4\xf9\x0b\xb9&\x83\x89\x03\xcf\xb9m\xc5\xb0\x0f\xa0\x82\x9f\xdey\x15E3/ ij \x82\x98\x12{A\xac\xa7\xf6\x92z\\\x05uJ\xf2<\xb4\x90\xe7l\x97m\xa2PC 1\x93WQtg6\x9b\xa95qI\x9c;\xda\xdf9\x03q\xb2\xb9R\x8d\xbd|*\x88\xf6\xf2\xe4\xe2\xf8\xfc\xf4\xec\xf2\xed\xf9]\x9dw\xa4b4\xfd`b8=\xb9\x1eY\xc8\xf5]\xa4\xe9\xb7\xc1H\xf5\xec9\xfc)^\xcc^E\xd1\xbff\xb3\xd9\xaf\xea\x07I\xb8;`\xe6\x1a{:\x16\x06\xc8k\x92\xa4\x1b\x120\"\xea'\xae#S{d\xcd\xb0\xfe\xaa5\xe8\xbbp[\x0d\xcb'\xc5\x19\x9b?\xf5\x7f\x9eC\xe8\x07Z\x06\xd5\xcfE\xc1\x89\xec\xd2\xc6\xe9(\xf5\xa04\xb6a\xb1\xabL\x15\xa9\xb1\xc5g3v\xd2\xd5\xd8\xc1\x96\xa7\x8a3\xff\xb6\xc2\x0c\xb9\xc7\xee\xa23\xfe\x033\xe5n\x03\xa9\x9d*\xec\xc4):\xabtG\xe0\xbb\xde\x1d\xa4T\xe3a\xb0\x93\xf7\xa6\xce\x85\xb74\x1d\x81\xac2*\xac\x19v\xdf\xeeN\xf9\xde\xed\xee\x10\xc5\x85NNQ\xdc\xe0h\xc1\x99\xb7VQ4[\x90\x84/\xee\xe3\xbd\xdd\xec\xd3-A-q\xd7P_\xab\xf8Tn\xb1g\xd9\xf1\xd2\xf9\xf9/\x17o\xdft\xff\xfa\xfc\xf9\xf3\xe7\xea}d\xcfW~\x00aSELL\x0b\x83A\xdcU\xf2\x94JO\xdb:\x0f\x88\xa2\xf3\\\x17\x05{|I\xabc\xfe\x00\xe8vA\x97\xcb\xea\xc0?(\xec\x07\x85\xf7\xa0v\xec\xae81\xde\xff\x0f#\xc7\xfb\xe2\x92\xdb\xf0?J\xe2\xce\xa4\xc8?\xd3\x18\xd1\xc4\xbbb2_]\xd6V~@\xd5\xfaW\xea\x873\x9a\xa4Q\xa8\x15\x9b\xc2\x83\xc3\xbf\xc22\xe7;\xf3\x1c\x0e\xd5\x18\xcb\x87y\xd0\xb0x\xf6\x01^\xfb\x03hgq\x8b\xd3\xe6\xd63\xb8\xa5\x92\x9a\xe6rgbE\xb7\x0et\xb8\xf8Z\xde\x90-\xc3\xf7_b\xca\xff\xad}\x98\xad\xa5\xf5,vA\xa7\xab\xe2b\xd0\xe4 \xb1\x9b~\n74\x08\xbe\xbe\n\xa3\x9b\x90\xcb\xf5\x86\xa4@\xc0\xcb\xd3,\xdaj\x98\xbc\xc9\x82\x07\xc2\x00m\xf1\xa5\xfc\x86O9,c\xb4p\xad\xb8\xd7s\xb6\xeb\x0e\xf2\x9e\x0b\x84\xe4\xc3M\x14,\x8b\xceV\xd5\xcc\xb8\x07\xab\xe0_(\xbcE\x05\xfbv\xf1\xf1aJ\xce\x85;L?HRt\xdc\n\xd2s\xf6\xf3?\x7f\xbe\xaba\xf2\xa1<\xd2\x1cH\xcf&\x9c\x0c\x0c\xdd\xe1\xec\xc1\xe1\x83\xf4\x96f\xdb\xeb\xffe\xcad0\xdc\xc4\xf4\xa1Qk\x9aF\x0f\xac\x8dkT\xe9\xf0\x97\x81\x86\xac\x1e_(]\xf2_\xa7\xb4\x0c\xa2\xc4d\xed\x87\x9cv\xd5d\x1a8\xab\x07\xca\\\x1b\x12\xd6\xff*\xd1\xcb\xa0Fu.g*\xa7\xba\xda\x9d\xce{}t\xfc\xf2Zzho\xbaE\xa8\xef\x7f\xdb\xf7I\x89_\x12\x86\xfd\xb3p\xd7\x904\x15~\xa83\xb2\xa6\xe7\xf4CN\xd3l&~o!\xf9\x90\xd3d\xc7_g\xe8\x18\x0d(l\xa34\x03\xca\x9d!\xdc{R{E\x11h\xb7.H\xd1\xecN\x97\x17\xc5\xd1\xf3\xf5\xf0\x7f\x84\xf9v!n\xe5\xd2\x85V\xf3\xe3\xb4\xb3I\xeaK\xf5\xa2<\xcc\xe6\x1cI[DoH\n)\xcd\x0e\xc0\xcfR\xe9\x05L!\x0f\x05#,\x85#\xe5\xc6/r\xac,\x910U4\xca\xe9{\xceu\x04\xbd?\xeb\xfc&Z\xd2\xd3p\x159\xc7\xc3\nsp\x1eFK:\xf7\xc3U\xd4\x8ek\xa1\xf8\\\xba+\xe6\xca\xb6\x95JDzd\xfc\x97\x07\x8a\xa0\xb0\xd1Od`5m\xe7\xc9\xfe\x08\x95\xbd\"\xfb\xa1k\xee\xc0\x12%Y\x81\x9ff4\xe41z\xd4\xf3!\xcdn\xa2\xe4\n\xf5\xaca\x0b;\xcfz\x1b\x12\x864HQ\x0fk\xf5\xdb6\n\xfd+\xf5\x07\xa8;H\xb8l\x0ef\xaf\xec\xa3\xaew\xb6a\x0f\x93\xd8s\xfa&d\xad\x99dW.\x1c\x84\x8b\x19\xa9(\xda\x908\x9e\xa3\x1fv\xd9\xe6\xb5o\xca\xaf\xeb<\xbe\xc8\xfd`9\xcf\xc8\x1a\xc7\x17\xeb\xc8\xa464\xd8\x974Vb\xeff5)3\x9a\xb4\xb06^Hm\xb4`\x9a6\x8c6 \x806V\xe8\xcc\x1c4\xeb\x15.\xeb\x1d(\xe3\xebm\xc7w\xb4!\xb2\xde\xc11a\x9b\xb5\xb0i\xc2bC\x02b<\xf8\xd5^\x8d\xe2\xce\xd6'\x08\xa6\x0fx\x0d\x0cu\xa1\x82\\\xf8\x80\xd6\x80P\xd6\x80 \x96\xf2\x96?Z\xa8j\xdc \xd5h\xe1){`j\xb4\x90\x94.\x185$\x0c\xa5\x0c9)\xee\"]}\xd37\xcc\xa4\x0d)\xf5\x0c&)\xc2HV\xfb\xb3cP\x9bO\xd0\x9e\xe1\xa2*4\xa4\xa2\xefW\xf6\xb1\x87\x05\x87D0\xa8\x86\xae\x1b\x16\x1a! 4,\x14\xd4\xe2\xf2\xf6a80\xfcS\x10\xba\x8eqH\xa0\xc7\x18\xc5\xd0\x04w\xaca\x9d\xae\x87\x17\x1f\xca\xe9\xbe\xfb\xabj\xad\xbd\x027\x98\xc5\xda\x825\xfa\xb5Y\x034\x0e\xa1\x99\xa6\x17k`8\xc6\x18\x88\xd1\x87`L\xc1\x17%\x15\xb0\x01\x17[\xa8\xa5\x1dd\x19\x10^A\x04V\xdcC*\x8a\x00\x86-\x8c2R\x00E1r\x83S\x06\x85K\xda\xe1\x91!\x81\x11E dP\x08\xa4\x1d\xf2\x183\xd8\xa1\x0ds\xb4}\xbf\xed\xd0\xc68A\x8d\xd1\xc2\x19\xe3\x062p!\x0ck\xf0\x02\x19\xb6\xc0\x04,:\x9e\xfd\xeehX\xd7\xb39<\x81\x0cL B\x12\x8d)\x8f\x19\x86\x18\x14\x80\xe8\x06\x1c\xc6\x0b5\x8c\x17d\xe8\xbf\xbb\xd6\xc0\x82-\xa4 \xd5\xb7:\x8c\xa0\xb4\xc4UN~C\xd0\x00\x89cH\x88\xc0\xe6 \xac\xbc\x89h\x17a\xb3\xfeI\xb1\x86n\x91\x94\xe2!\x8cwUU\x14\xa5xLU\x0c\xa5\xc2\xa6(\x82\xd2bk\x16?e{(|P\x15:i\xafw\xd6\x02'Mq\x13\x1a\xa1\xaa\xa8IQ\xd0d\xc7\xa7(drqh\x8f[\xc0T\xe3x/\xd9\xc5Y4+\xbf\xff\x80f\xf7\xcew7\x8cR[\xbb\x7f+\xbe\x91\x81{U\xb6&w\xf8T\x85\xf9C\x1452\xc4\x0f\xe2\xd9Ka\xe9I\xc2\xa1)\xa1/AV\xb2\xbe\xa6\x8e\xb9]v\xace)mHMQj\xec\x8e\xa4S^\xec\x86B[R\xac@\xa3,%V<\xd7)!\xee\xa96\xbb%\xc38\xbeS\x94 +^l\x95\x07;l\xbd\xba$XCwm)p\xeby3o\xbf\xad&\x8b`\xf0\xee\x04\x15\x93SN\xcc<\xa9\xb3Bp~\xaao\x1eb>\x0dY1\xeea\x837[\xf2\x81\x7f\xb1!\x13\xb8\xd7j+\xcd\xf8\x95\xf6E58b\x85\xed/V8p\x93\xba\xa0Y\xa8\xce\x05I}\xafh\xcf\xee\xd7\xabc\xb5c\x80\xb1P\xf0Knn`s\xf1\x1e\xb3C1L\xf3\x14<\x12\xf3\xcfU\xc8\xa8V\xf1\xe7$\x0f(\xff\\\x01#\x80G\xd3T\\\x0f$\xf5Z\xe8x\x84\x8d\xfd\xe4m\x88\x1f\x1e\xb4\xedu\xd1v\x9fc`\xf7\x8e\xf2AX\x92\x8c\xb0\xb5\xe5\x9e\x98\x83t\x11\x88\xd1\x951\xd9Zu\xff\xed\xb4=P\x9a\x91\x8cB\x96\x900\x15\xb7\x91-\xf16~\xd8(S\xe0#c\x1b>\xa8>Kc=\x13\xda\x9b\x91\xf9\xc8\xde\x00\x15\n\xd5g\x15\xf8\x0dX\xfd\x15\x9a\x82\xc3\xe3\x84^\x8f\xc8\xe0\xea/\xae\xa0\x18RQ\xacb\xfd \x8dv\x86`\x9c%\x7fU\xff\x11\x1a\x81\xd5\xf4\x01\x1a}j\x97\x80}}\xa3\xc7\xf2\xb1\x99\xda\xd7\x95\xe6\xdd)X9H\x97D\xc5P \xd9\x12\x8c\xc2D\xb0\xf6\x1c\xfb\xcf\x11\x86\xab\n\xc5G@\xd6\x9e\xfb*\x89\xb6\"\xec\x14\xc7\x10\xe5Y\x9cg\xd5\xdf*\x19\xa8a\xe0\x89b\xa3\xce\xa9\xd4\x94#\xe0bW\xe3\xe1X8\xbf\x141\xea\x11\xd0\xc9\xcf\x9a\x8c\x80\xaa\xba\x06\x96\xc7KK=\x95\xee\x10\x8cqW\x81r\xbc\xc6\xc1'\xa4\xaaqW*\x8f\x1b\xee\x8c\xad_\x8f\x84@\x08\xf5$O\x0c&\x0f\xbd,\x91\xec\xa3r\x15N}R\x94\x9a\xa5gP\xf7\xf2cQ\x08.}\x7f\xfc \x15\xee\x7fql\xfe\x8f \xc0Ld\xe0\xfd\xf9\xb0\x13,z\xf3\xf6\xf2\xe4\x99\xc8\xcb \x02\xb6@\xd8\xd0\x84\xf2\x9c .[3\x80\xbf\xd1\xdb \x85_\xf24\x03\xb2N(eg\xbe2S\"J\xd8\xbepojg\x1c\x9eC\xb5\xa5$,f,\xa6u\x14\xc7\xdf\x93t\x03\xcb\x88\x8a8\x7f\xf11\x1f\x86<\xa5l:\xb5\x1cU\xc1o/\x99y\xd1pn\x8b\x8f\xe1 \x0b\x81\x14\x01\xd6\xfaG\x81JC\xa6@%\xa5\xa0\x17\x0bt_\x86~|\xe0\xdc\xc1b\x99\x0b#\x89\xce\xaf\xa3\x8c\xce\xd5\x13\x11`\xf3\x07\x9c5_\xb5\xac\xc0n\xee\n\xa8\x0d\xd7\xf9\xd2e\x05\xfao^V\x80\x90q@\xca9X?\xf3(\x00IR\xb0Y\xe0u\xb0^O\x9a\x80\\58\xac\x9c\x81\xe5k\x9a\xb5\x07\x91\xfb,\x01\xc7^\x120\x9b\x00n\x1b\x01.\x9ba\xbd\x1ci\x1eW\x7f\x93\xb3\xfe\xd8\xe7\xff\xb0\xaf\xc3\xc7\x1d\xc1}t#)\xab\x815]\x17+\xc0\xf2\x13NoX\xbf\xfb\x08\xa3\xae\x14{D\xf1o@\x96\xa1p\xfe\x85\xc8\x842\x0b\xe6\xa0\xc8\xd2\xdd\xfa\"kX\xfc\x93\x1b7Zd\xfc\xc6Y\xfbz\xf2*R\x14\xa4J\xa8\x9de\xaa\x9f\xb9\x15\xb5\x98\xac\xa8\xc9\x8a\x82\xc9\x8aR\x02\x929q\xc7\xdcdE\x01\x9e\xa4\x80\xd3\xc1\x02&+\xaa\x06\x98M\x00\xb7\x8d\x00\x97\xcd\x98\xac(\xec\xe8\x93\x15\xe5pD}\xb1V\x14\x17\xfb\xb9\xa9\xc0\xbf|\xd2N4\xbb\xa8W|\xb1\xff\xb1\xac\"\xe70\x8aI\xd40<\xf0R:\x17\x19#\x9c\xc8\xaf\x9f\x97n\xd6\xf2{\xe8\xdc\xbd^\x12I\x89\xaa0g\xb2\x9b\x88\xbd\xbf\n|\x8f\xed\x1d\xe7\x18\xc5\x1e\x07\xccH\x98{\x81O\xc3lN\xb2\x8cxW\xfbtm\xd6f4\xd7\xc4\xfa\x05 N1\xdbXP\x12\x03qr\"\xc6\x03\xe4\x98\xa0H\xb7P\x03rPp\x18\x18\xcc\xfd\xd7\xdb\x80I\xe3\xd0\xbc\x89\x9f;8\xce\x1f\xf4\x89 j@\x08j\x1b\xa4\xe0*\x93F\xd4\xa0L%Q\xc3\xe7\x98\x10F\xad\xb4\x01\x9f\xa2\x82B\xa7Lc\xb1%\xae\xa8\xc1%\x9d\x05\x85\xb0\x9d\xf2bNrQ\x03&\xf5E\x0d\xea\x84\x18581\x8b\xfdV'\xc1 -\xe6\xbc\xacC7\xfdF\xf3\\\xbfI\xd8-W \x86\x04\x1e5 \xd2z4/\xeeW\xe1a/6\xe0NU\xc0\xd9\xaaMp\xbcuJp\xa4\x12\xf4\xa0\x14\xb8\xdcF%`o\x11mp\x13\x0b .\x9b \xfd6\x14\xfal\xaa\xf3\xedU\x809mJ\x0d\x8eKr\\\n.\xf1J\x0d\x9at,5\xecs\x19\xc6\xe4)5\xecs:\xfa\x06Zj\xc0f\x8e\xa1\x90\xb5\xb3\xcb\xd4`\xcf9S\xc3>\xc9f\xcaZS\xc3>g\xa3\xce{S\xc3>\xe7a\xc9\x9cS\xc3>'d\xc8\xbdS\xc3>'c\xcf\xdeS\x839\xa7O\x0d\xfb[\x87\xeb\x0d\xc4%q\xd0\x8aL\x95X\xa8\x06\xd5\xd7\xde\xba\xe0`\xb8\xb8\x18,_\x88\xbdn\x8d\xceHp\xb5\x93p^W N\x86:~C\xc0qS\xc0\xd1Ds\xdc\x1ap\x13#\x01\x93\xbd\xcd\xc1\x8d\xad%\xb8l&\xf4\xdbP\xe8\xb3\xa9=\xedmt\xd4HB\x19\xd5@m\xa9X}7[V\x0d\xca\x1cZ583\xa3;+J\x0d2_\x05d\x8d}\xa9\xe7\x86\xdb\xb32\x9a\xf05\xbc\xf8\xf1\xed\xf1\x0f\xf3\xd3\x97\xf3W?\x1e}\x87\xc8`hC\x1b\xc3\xd1\x8b\x8b\x937\xe6\xa4\x8b&\xb4\x11 \xb26\x9a\xd0F\xf0\xe6\xd4\x94\xbc\xd1\x842\x95c\x18\x19\xdcn!\x02\x84\xa0,_\x05d\x0d~\xb8\xe4\xa1\x94\xa2]$\xbc\x08\xbc\xe8\xea\xf4\xa55\xab\xa3 \xa5H\x81\x8fw\x88:FT\x9b\xd0\x8bG{\xa9$D\xa8\xb9 \x83\xa6\x86w\xe6 @\x85h\x9b0h~h\xd2\xb9\xda\xbb\x02\x8e\xb9\xf9y\xe1\xafE\xd6\x11;\xe7\xa5K\x9aG}e\xa9\x04\x12\x9d\x1f\x02)p\xda\xdc\xd0\xae\xf3\x15X\x9b\xc5\x1de\xe4\x91W\x8dH/\xff\x8d\xe6c~u\x10fw&\xaaa\x88\xac\x12\xa9.\xef\xfa\xd9W2\x94RD\x02\x93\xf5\xbc\xc1\x9e2\xaa/\xb1\xaa\x01\x7f\x82\"OO\xe4J\x04`\xd7#\xc0I\x0f9\x0b\x92\xa3\x10i>*\xab\x06'\xa2\x803a@\xd5s\xc4\x06\xce\x04\x02w\"\x81\xba\xa7\x89\x0d>\xcf\xd4\\Ogls\x15$:k\x0b\x16\x1b`RY\x9a\xe0LW\xd7;Ll\xfb\xda\x85\x1a\xf68/9#\xdbD\x1c$\xd4E6\x1dT\x96#\x11\x9c\xd8\xddAY9\x10\x02\x1c\x89\x01\xeej\xca\x91(\xe0J\x18\xe8\xa3\xa0\xf6?)7\xd5\x84UL\xbcO\xa7\x0d\x19\xc8\xde\xc8\xfd\xd4\x92\xabRr\xa4%^\xf0\xa1\xaf:\xda\xdb\x8c\xf0 \x88\xe5\x1b\xf8\xa9\xd8\xa7\xc1\xac\xd8(\xec|\xdd\xbf \x88\x11\xed#-v\x9fH\x98\xf9!\x9d\xdb\xedP\xbb\xfdi\xb1;Q\xfa\n\xa7\xa5P\xca\x1aA!\x01H\x91G\xa9f\xd4\"\x01\xbdPpQ\xc4\xe8\x05\x03~\xd1\xe0\xa6v\xf73\x05\xac\x92uQ\xaf\xe2\x0b\x02f|\xae\x8a\x15\xaf1\xd0t\xb2\xcb\xb0\x00G\x05:\xe2\xf8xe\x89\x18\x141\x9c\xcd\x93\xe40\xca\xd0\x0c\xea\x1f\x99\x82>\xe6y\xccG<\x8d\xd9\x96E-\x1c\x12J\\\xb5\xdcy\x92et\x1b\xf3\x0c\xea,\x82\xad\x9f\x06\x94,\x81\x88\xbci\x10y\xd3\xd2\x93QK\x93\xa9\x08\xa2TBj\x853Jc,E\xa4O\xe0P\xc5bt\xd1;MG,\x9d>\xd5\xeb\xcf\xa9\xdd\x15\x87\xdf\xa8\xdd\x95!\x8e\xa4\x8b\x18\xe9,\x8b1;\xa9Xc8\x16\xa2\xe8\xe32.\x11\x18\x87X\x8bCT\x05\x17?q\x8e\x944\xf6\xd1\x1a\xe6\xb0\x07/Pa\n\xcb6X8\xd3p4 \x11\xeb\x8f\x04c\x88\x00\x89]1\xed\xc69\x83\xf5\xdb\xab=\xf2\xfa#\xcb\xc9\xcb\xae\xf6\xa2\xd7\xb05\xfd\xe9\xea&\xa1\xa7/\x05\x99:\xe2\xda\x15\xd2\xa6\xa2RRRA?\xad^v8\xfc\xb4\xdf\x00\xb5\x9c[\x0d};\xb4\xaf\x9aV\x9fv\xf4\xa8\x8e\xd2\xafJ\x95\xd6\x19\xb9\xae\xb6\xcc\x8a\xca\xa8\x9a\x8c\xcaH\xa7~\x10\ng\xb8\x8a\xe9\xd0\xe4\xb8f\x0ba\x98\xafe\xff\x18\xd9\xaf\xbe\xf5-\x9bG\xcd7*[\xa7k\xe78p\xecPf\xb3\xd83=\xac-\x8d\x0dc\xb6_L\xb6\xcb\x98\xe6\x9b\xd1VQ\xda)*\x1bEe\x9f\x0c\xfd@\x80\xd1\x1e1,Vm\x87`m\x10\xa4\xfd\x81\xb4=\xecv\x07B\x05T0\\\x19T`\xb55\x0c$6p\x93\xc6\xbe@ S\xdb\x15Z\x9b\x02\x81\xb15\xbd\x91\xec\x08\xb5\x0d1\x9e\xfd`\xb1\x1d\xca\x89\xa3\x15\xb8F\x90\x94\x04l\x0b\x8f]l\xac\x02c\x15\x15\x93\x90 \xc5c\x1c\xc10\x88\x04\xd6\xe6R\x08\x80\xf1\xd56\xd3+\xd8\x1d7\xf4(\xcc\xdda\xb6\x97eOX\x04\x9f5\xfa\xc0:\x9c\x08\x1d\x19V\xca\xaf\xdet\x1f\xd8\xefuP\xafW\xd1\xdd\xb5>\xf7N\x9f\xd7a=^G\xe9\xef\xda\xddWUc\x03\xf4F\xb7;\xa1:Xg\xfc\xd1\xda\x7f\x1b\xf4\xb8\xea\x1c\xc7\xf6\xdb\xc2v\xd8\xc2\xf7\xd4Bv\xd1r\xea\x9b\xd5`\xe9\xffm;P]{c\x99\xfa_\xb9v\xbcr\xedq5\xf9Ha\xf2\x91\xb6aO>R\x8d\x8die7\x95}i1\x82\xad8[K3\xf6Or\xe7e\x8d\xed\xeb6+\xfd\xb9\xd9\xa7\xbbQ\xbb\x8b\xd1W\x8d\xd1\xebz\xa7\xd3\xc1\xa8\xdd\xf9q:5J\x98N\x8d\x12\xac\xcc=\x9d\x1a5\x98N\x8d\xe9\xd4\xf8c\x9f\x1a\xa6\xdc \xe5\x92T\xac\xa9\xed_\x87\xc60\xec^\xaf\xa6f\xbf\xeer\xb5Nr\x05\x1ee?\xb9\xce\x95\xcf\xf9\x96g\xfd\xb2\x86\xc3\x01\xae\xfavF\x0f\xed\xda\xb5\x03\xc0\xa6RtQi\xacM\xa0~V\xdf\xaf\x19o\x1b\xe8\x9e\xd6\xf4fv\xb2\x11\xc0j'\xc0\xc8\xb6\x02\xf4\xb0\x17t\xef\xd8\xba)\xeb\xd2>Q\xc7\xac\xea\xc8\xd2\xd4\xe1\x9b\xcfA\x9d\xfe\x05cE\xfd\x80\x13{_\x87*\xc2\xce\x00\xdb\xcc\xc1:{0\xdb\x1c`\xa5\xb7\x04\x9b\xed\x01\xd6\xcas+\xb9\xc0N2\x84-\x02&{\x04\xf46 \xd8\xa6h\x8e\x98X\xed\x13\xc0\xe2W,\xdd\xda!\xb8\xbf\xcc\x18\xb2G\xfa\xcd\xd6\x9c\x9f\xd8\xdb\x8e\xd1QD\xd9\xd1W\xd9\xc7W\xf5\x0d\x84\xe94\x9cN\xc3\xe94l\xc0t\x1aN\xa7a\xf1\x13\x86\x95\xa7\xd3\x10~\x97\xa7\xa1\xad:B\xbb\\\x1d\xeb\x1b\xbb\xd5;c\x1b\xcfq\xa4\xdf\x81\xb1<\x01\xa0\xf3\x06\x00\xba\xa7\xbcR\xaf\xa9u\x99\xa5k|\x0f\x8b\xc6\xd2\x17~\xc8i\xb1_Un\xed\xed\xee\xda\xd1\xdd:'@\xcd\x0bp=\xdbQG\x00\xd4\x98\xdb\xda\x0e\xdd\xda\x95}\xec!1\xc5H\x02\xf0\xdd\xd6\xa1\xea\xa4nZj\xaf\x1e\xeb.\x9d\xd5\xab\xae\xe9\x06\x84\xae\xfd\xd4]\xbb\xa8\xdb{\xa7#\xb6\xd4\xd6w\x11\x81\x02g\xf2\x98;\xa1;\x0dck\x94\x84\xecu\xee\xd8\xe1|D\x05`o\xc3\x87\xa2\x07`\xcc@\x01(\x0bZ\x02j\xa5\x80^-\xd8-\xeb\xf21\x94\x85-\x01\xc3v\x12\xec$\x07\x17\xb2\x03\x9e\xf4HK\\\x00\xbe\x838j\xaa\xa8)\xba\xf7\x08Gt\x06\x1fkz\xe8&\xd6c\x0d\xd8\xa6\x87\xb5m\xb7\xb1%\xb7[#\xee\xb1\xd6\x80m\xb5=\xd6x\xf6f\xdac\x8d\xe4\xd0.{\xac!\x91\x0d\xb1\xc7\x1a\x0e\x9cZ^\xc7\xe8F\xd7\xe3\xcc\xafa\xd4\xb9\xf4\xa9\xb6\xf6\xa16u\x9f\xb6\x1eH\xf6\x83\xe8\xb3\xd99\x96\x0e\xd2\xb8\x13\xce\xe4\x87\x90\x800pld\x03\x14\xe9\x00u|\xa2\x08\x08\x18\x1e\x130Y,V\x92\x83\x0b\xd9\x01Oz'\x8b\xc5\xe2C\x94\x80\xe9\xbc,\xd6b\xee\x16i\xed\x13\x89d\x05,#Xk\xf0\xeb\xe0\xb0\x19\xb8\x9e\xc9\xf6b\x1f\xdc{\xc8\xfe\xc8\xd6\xc2 \xdck\xf6^\xc8\xc8\"\"5`;\xeb\x8c\xd7\xed\xd8\xda&\xa0\x0e\x08\xefv\x13\x1c\xb8\xc6A\x80\x91\xbd\x8b{\x0cn\xbb~\x0b@w'\xee1\x03\xcb\xf2\xf1\x9e'|\xd7a^\x98\x85\xc0\xa4v\xd6\xe0f\xd4\xbfbQ\x83\x10\xd1M\xd8\xd2C\xd8\xa8M\xcd:\xd4\xd6\x9d\xcd\xa6\xed\x8d\x9a\x1e\xa1\xe51\x1a\x1e!\xa1H\xf6D\xb1&\xa2\x1b\x1bba\x80\\\x1c\xe0\xfb\xb0!\x17 \xd8\x85\x82K\x07\xb6\xf1\x07\xc7\x9d\x10\xe3v^s\xeb\xbb\x86i=\x06x\xda\xe0\xec\xca\xd8\xa5\xdf\xdaH#\xc7\xc6\x0e\xb9Vn\xb7\xf3\xb9U\x84Q\x0bA0\x96Ux\xad\x8b\x01\xd4\x82\x00+\xb6\xa8\x85\x01nq\x80\x17\xd8q\x87\xc5\x88\xea\x98\x82\xea\"\xa68!E\xd1\xc3&&\xe0&\x9e\xa3\x8ci\x0b\xf3\x97\xcf\xd9\x06\xd3\x0dd\xe8 \xab\xc5\xa9\xc3e\xef\xfa\xaa\xb3'\xc6\xec\xc8\xb6\xa7&`\x06\xd5bQ*6ubQ$\xd6\xadEH\xb1Um\x0c\x1f\xc4\xac$\x9c\xd5\x83\xed\xf3y\x06\xc5`\x93\x16$\x17\xa8E\x12\xa5\x00z\x8e`\x13vg\x81\xfc\x1cY8={\x95\xaa\xeb\x9a\xb0\x1dJ\xb5u:?\xfa)\xbeG\x97.\x8f\x07\xd5\x7f\xa3#\xee:1\xb7V\x04\x19\xb1\x9a0\x83\xa6FH\xc0@\xad\xc4_W\xfeb\xe5o\xb0\xfa\xce\\2\xa7uo\xe8\xf3\xa7\x0doX\xbce\x0e\xb9\xd4\x02\x9c3\xaa\xe5k\x18_\x83{v\xb5\x16\x91%\xebZ@\x9f\xdck\xfd\x9b\xb6\x0cl\x01\x9f\xa1\x19\xbd1\xda#F0\xc7\x06\xec\x91\x1e[\x9c\x07q\xed\xb0\xc9# \xc2\x0d\x08r\x81\xfd$\x17\xe0\x10\xdbA\xac\x0e\x90+\x04@Fu0\xfb&\xc1\xce\"\x12l\x04\x06<\x91\x01Kh\xa7H\x0e\"\x8ecu+#\x16\x80s#\xa3\xbd\xe8\x0e#jIe\xcd\x1a\x17\x80\xe1\x0b\xbb<[\x1d\xe3\xc3W\x849\x02\xc6\xca/\x17`\xce2\x17\xa0\xcc5/^W\xd4_ \x98,\x8d\xc9\xd2(a\xb24\xf6\xaa\x99&Kc\xb24\x14\x80\"\xf4di\x00\x86T\x93\xa5\xf1\x1b[\x1a6?X\xf1\x94\x990fQ4V\xbb \x18\x84\x7f\x9f\x9f\x8c\xb0\xed\xe7\xa0\xba\xb8\xeeJn\"}u\x9c\x00\\\x8d\\\x81\xae\x9f\x9b\xcbR5'`\xa0\x1dj\xa9\xa3\x13\x808\x81l\xe3\x80\xa5\xb2N\x00b @\x0e\x06\x98Z;\x01\xae\x15w\xc5[\xb8\xb9\x82\xc3|\x01W\x83'\x00\xa1#\xeb \x05\xccZ\x8f'\xc0Z\x95'`\x9f\x93\xb0\x89|\x1b\xf0\xd5zVTU5_\xcf\x9a=\x01\xae\x95{V\x84b\x05\xae\xf5{\x02\\\xab\xf8\x04\xd8k\xf9\x04\xa0\x19\xc1\x96\xef.\x00\x8d\xcev&\xd5\xc1\\\xe9W<\xe3>0.\xed\x10Y\xfb'\xc0\xb1\x02\xb0xi?\n c\xb4\x83\x1b\xe5\xc0n\xbf5\xc1\xe1\xb6$\xc1\x81\x1a\xe0H\x11\xc0\xde\xa2$`\xac\xe66\xe0\xd9Z\x02v\xa3\xc0}\xb3\xc0u\xc3\x9cn]\x02\xf0\x15\x86\x02\x1c\x96\xe00u\xf7\x9aC\x01\x88\xcaC\x01\xfb\x986\xba\x8eO\xc0>\xa60nu\xa2\x00\xb7\x1aE\x01\xfbX\x1b\xb6jQ\xc0>f`\xafc\x14\xb0\x8f\xb1\x1d*\x1b\x05\xecc\x12\xc8ZG\x01\xfb\x98\x80[\xf5\xa3\x00|\x0d\xa4\x80\xf1\xe7\xedbB\xbb\x17M\x1a\xd1\xe9\x0b*\x05\x98\xca*\x05 Op\xec\xc9\xfd\x1b\x1a\x9e\x96\xd2K\x01.F\x82\xdd\xc5&\x01mq\xe2\x88\x0d\x0e\x04\x07\x07\x9b\xc4\x81\xec\x80g\x7f\x01\x93\xf1\x88\x00\xecF\x81\xfbf\x81\xeb\x86\xf50\x1eQ\xae{ \x98\x92O\x01b\xa5\xe6\xc2O\x01\xd6\xf2O\x01N\x8c\xe5\xc6VN\x05\xa1\x02\x9c7\x12W\x1c*\xa0o\x89\xa8\x80\x9e\x85\xa2\x02z\x96\x8b\np/\x1a\x150\xa8tT\x00\xa6\xe6\xa0\x0ec\x95\x91\np*&\x15\x80\x0eQ5\xc1\x99\xef\x9c\xd5\x07\xb2\xc8T@\xef\xe9\xe0\xd4\x95TVI`35\xcc\xf8Z[\xbc4\x89]\x96\x14.\x07\x06\xec\x86f\xac\xcc\xd3:?\x8c\x110\xed\x19\xac?w5\xf1+\x81 \xf1 \x9b\x8e\xe2SG\x9f\x8c\xfaN{T\x1abG\xfa\x14#\xe3\x8e7\x86\xb0'\x08)R\x81\xb0\xe8\xb5\xc9.X\x04\xc3\xd2p\xcc 7\xd89\xe8\xd2e\xb0\xefw\x93]\xb0o\x1aRU\xb0(4\x89&\xd8\xd7\xcdi\"\xfa\x84\x10\x1c\xfe\xf1\x9a\\w\x0e\\~\xf8\xbf\xa8\x8e:\xc4\xa1\xab)\x1dp\xd1l\xe3\xa8#m\x9a\xbf\xcd\n(\x9f3]C\xcc\xd7\x0fC\xba\xbe\xd5\xe2\xd4Z\x0b\x12\xb4I\xf8CQ\xdbL\xc1\x81V\x85\x02\x1f.}~,+C\x825E\xdefuH\xd0\xa7\xc1\x1b\xb6b\xf4\xcf-\xaa\x13\xd8Q\xe8t\x97\x02KZ:2\x11}\x80\x00\xe9\x13O\xd0L\xae\xb9-\xa3\xf2~\x8c3\x07\xeb\xecAo\x0d\x95?\x1b\xad\" \x98\xdb\xae9G\xc7J.\xb0\x93\x0c\x95ycO\xd4Fq\xa4r\nv\xebJ\x82!\xe1\xba\xef\xf0\xd6T\xe3\xbe\x88\x87Ye\x12p\xe9\xd0}\xe7hKr\xee\x8bW\x9f\xba\xdc\x17#\"!\xb9/jK\x9aq_\xb4\xb8\xe4a{\xbap\xbf\xf1\xc7\xb3\x1a%\xa8rw{\xd8m\xa3\x9f\x8f\xd3\xe7\x88\xa7\x13\xaf\x0dc\x9cx\x96\xecRS>\xa9\x98\xa3:\xce\xa3\x8d\xf2X\xb6\xc8\xb6A\xa8LP\x04\xf1lM\x86\xdc\x12\x1d\x1d3:\x1ds8\xf1Y\x9b\xbd\xf24\x1b\xfboM\xb8\xc4\xa5R\xa2\x93'\x11[\x85\xe0\xf2\xcf\xd5\xb6\xc4\x9a\xe8\xe80\x92f9\x8d\x13\xcd)3Q\x99wh\xbe\x0d;\xe5\x16*\xf2\x07[\xe8\x94\xd9\x84\x9a\xfcA\xa5\x1ePK\xff\xd4|\xba\xfe\xa6EAN\xcd\xa7\xa7\xe6\xd3\x1c\xd4\x99j=L\xd9\x91Mv\x03\xf3\x0f0<\x8dlo\xe5G\x0b7Z\x18~\x18z\x13\xab\x8f\xcc\xe8Z6739j\x9fU\x0c\x8e`\xef^\xb8m\xc9\nZ\xa4m\x84\xeaP\x81*O@\x0c\xd0a\xd0.S\x1a\x1a\x1b9\x1cy\x86\xd6E=$Xwe\x1a o\xc6\xf6C\xd8\xd8\x04\xd8\xe6\x00\xd6y\x80\xbd\xad\x90U<\xa1\xc6\x19\xc6\xee=\xc6\xc6Ac\x0dc\x8f_@\xff\x18\x86\x89\x82\xc88\x06\x0c\x89eh\xf0\xa1[\xfe`c\x1a`m\xefc\xd9.SE\xb5u\xa7m\xd7\x7f}\xb3\x1e4j\xd3=\x05\xd1\x8e\x07\x19\xfb\x80q\x04\xf4s\xb8:\x90\x1e\"\xc0\xac\x08P\xab\x02\xb0z\x8b\xa0\x1c\xcd\xe61\x02\x04\xdbH\xb0\xd73\xa3H\n8\xb2\"\xbdH\x98\xd8 `\xa6f\x9d\x12>\x8e\x02\xf6\xe65C\xa7c\x8dY\xc0\x08\x83\x8c\x13c\x01t\x9c\x05F\x98\xb3-\xe6\x02#\x8can\x1d3\x14;\"\x16\x03#\x0c\x83h\xff2t\x08\\\x8c\x06Pq\x1a\x18<\x9f\xf1c6`\xe8\xb92\xc0\xc6\xdd\xab\x0d`\xe8\x9bb?1j\xc8\x95=R,\x87\xbf\xed\xfc\xb3\x9f}\xd3\x89\xfe\xefp\xa2[bC\x80\xe87\"\xe6\xfd\xdb~p\x18\x153\x02<\x91\xed\x9dB\\\xe3G\xaaw\x10]A\x1c\xe3H\xaaW\xcc\x1d@z\xc5\x93\x00l\xfe[ }BN6\xe6\xd7\xfe\x8e\x0eI\x01\x9e\x13\x90\xc2\x86\xe8\xd8\xe18\xa0\xbd;\x875T\x05\xee\xa3\x1a\x969r\xd8\xaa\x83R\x93\xc8\xd9?|\xa5\xd2e\xa6\x86\x18\x866\x18Z5eH\xeb5\x14P\x9aT\xe6\xbe\xc2\xea\x9f!Jk)\x98\x1cI\xd7#J%\x11\x8b\x01\xcc\x82\xc0\x1e\x19\x100\xde\x80v\xb5\xea\x1c1\xd0b\xc2\x97F\xdaBd\x80\xa3\x81\xddXB\xc4\x13\x04\x0c\x1cM\x1d:\x03\x1b\x97\x9a\xf9s\x8f7*\x8bpYE\xcb.XV\xb1\xb2.\x00\xec\x8b\x00\x9c@\x8d3\x94M\x94\xc6\x12$\xac\x18\xd9\x85\xc8\xban\x9b\x00!\xc5g\xd08\xb6\xd0\x1c\xd8\x06P!\xd7\xb45P\xe2Q\xbdon\\\xa0:o\x87~#X#\xec\x86\x95k\x19V#\xda\x06\xa16\x89\xb3A\x90-\xfbn\x94(\xa3\xd8\xf6G\xac\x17Rg\xf14E\xc65\x82i\xe2b\xc4Nv\xc5\xc3*\x80\x8eXM\xc2\x86\x16\x0e\xc5\xf5\xc4\xf8n\xf3\xea\xa16\xd2{\x96\xdbw\xbf!\xde\xbb\xc8\xfe\x8c$\xd9\x85tm\x88\x95u$\xa6+'-\xe7\x8fx\xa3\xed\xe8Q\x11\xb1OE\xa5\xc6 \xd3Y\x8a\xf8\x92\xa3\xe3J\x06T.*C\xfb\x98\x90\xbeV%\xe9\x15\x92&t\x8f:!\x941te\x88\xbe/:[\xf2d\xaf\x10|I\xbd\x16:K\xe8\xbdw\xc8]Q>h\x0c\xb5cB\xec\xea\xd0\xba\x86\xcc*7\xbavGt\xca\xb3\x1b2\xb7\xa2P\xf9H\x0c\xa1qDH\xbc\x07\x83\x8f[lcu\x88\x1bM}\xb3\x99op|\xab\xf5`\x1dl\xa6\xe7\xbeb[\x16G\xb69$m\xe5\xa0\xce\x90\xb8\xd0\xb3&\xe4\xec:\x9c1L\xeb\x8alx\x08\xd9\x1e:v\x9d\x93)D\xec\x8aK\x1d\nv\xc5b \xf9\xba\xa23\x84v]Q\xd9C\xb8\xe6\xd0\xad\xdbx\xe3\x86h\xdb\xa1Y\x07[d\x94\xb3C\x11j\xd5k\xb4\x1a\x92FhUshL'\xc2\xef\xebD0\x844u\xa1L1\x9f\xfd\x96\x99XC\x94\x16\xa2\xe8C\x92.\xa1H\x87\x10\xa4C\xe8\x11\x17rt\x0e5\x8e]\xb6\x86\x8a\x0fZ\xb6\xc1\xc2\x99\xfb\xeb\x7fg\x89\xf7!\xb1+\xa6=b\\\xcf\xd4\xe6\xad\x7f\x1c\xaf\xdb\xa9\xaf\x19\xbf\xd3\\\xa7_\xa7\xebKF\x14\xfe^\x87\x15\xa1\xd51B\xaa\xcaP\xaa)\x84\xeaE\xe96Jg\x0b\x92\xd2\xd9\xf5\xe1\x82f\xe4p\xf6\x92z\xc7\x91\x1f\xa2\xb7fI\xc3hk\xa41\xd9FyhR\xc1j\xa6,&R\x1a5\x04\xb2\xe8\x8a\x86\xc2\x82!b\\?\xe4\xab\xe5Da\x7f\xf2\xfc- \x8a\x01\xcb\xf3\xe5\x0d?E.7\xb4\xf8\x01V>\x0d\x96\xfc\xac\n\xd9(\x85\x83\xce\xdf\xc6\x01\xddr\xfe\xe7\xfb\x9a\xa7Y\xb4\x85-\xcd6\xd1\xb2-v)$\xf4C\xee'\xc2\xef\xb3\x8e\xd6Q\x9cDYT\xa3\xe9\xd2g\x0b\\\xe4lz5\xda\x06t\xcdg\\\xfc+J\xce\xe9\x0dI\x96hj\xbb\xa9\x9f\xa4\x86\xbczd\xdc{fk\xff\xeb8\x14\xda\xbc\xcd\x0b\xc6\xc7\xf5V\xc7\x88\xdc!`<\x1e\x11\x80\xe1\x14=\xe3k\xb8\xa4\xae\xa2EhTnI\xf1&\x0f\x80-\xe5K\xb7S\xf9oF\x04\xc1\x0b6\x0e=# \xd9\xe2\xf52;\x0f\xf2\xd0\xcfv\xf3\x8ct\x0e\xb2\xc6~2\x1d3/\xcd\x7f5c6_\x88\xc2 \xfcOTqA\xe7\xb2\xefE\x01,\xf2\xd5\x8a&\xb2\x8cb&\x98C\xcc\x1d\xb6yZ\x96*\xb3##\xa0$\xcd\xba\xb8\xa2\x90\xc2\xad{\xb7\xc0\xdb\x10\xc6\xff4\x99q\xfd\x15\x904\x83\x94\xae\x99\x96\x92\xee\xf5w\xe7?\xdeN!&\xd9\x86#\xef\xa0*y\xbe;\n{}\x95\x07\xc1\x0e>\xe4$`\x14X\n\xfa\x14\xa89%\xee\x90\x14\xfc\xb0\xfb\xf2{6\xe4\xbdu\x14\xad\x03:\xe3k_\xe4\xab\xd9\xcb<\xe1\xbc\xfb\xfe\xae\x981G\x97n\xa2\xfbBU\x91\x14V\x11?f\x9e)\xf6\xe2?\xe0tU\xcd\x90m_\x9cDL\xa3,\xcbE\xf0\xf38M\xf3-Sd\n\x04G!|\x7fyy\x06\xdf\x9d\\B\x11@xw\xfe\xa3\x10\xa8\x1d?\xd0 \xfc\xb3\xcd\x8e\x97\xbb\x98\xfe\xfc\xcf\x9f;\xe8@\xdeuB\xb9\xef\xe2\xf0\xe1\x94\x8c\x93h\x99{\x94Y\x074I\xa2\xce\xc7B\xf8l\xaa\xcc\xfd\x94+h~\xc4J\xd5\xef1Y\x8d\xa2\xab<.\xafj\x0b\xc2\xee\xa0Q\xa8T+\xc0\x96\xc2\xc7\xde\x90k\xbe\xf5\xdb\x1a\x8f.\x05\x93\x129U\xf6\xef\xeb\xc8_2{S\x81J\x0c\xcc\xc5/\xa1\xab(\xa1\x07\xf2E\x86\x8fd\xfe\xc2\x0f\xd8\xf9\xcf\xce\xaaT^\x91\x99\x8aH\xae\xe9R\x81/\n\x99\x1a\n\xd7\x94?\xccec\x06w\xde\xa5T\xf6\xfac\xabf\xec\xc1d]\xf0\x07 \xc9Z\xb5\xcaEB\xc5\xa9W \x9c\xddU8S\xa3\x8c>\x83\x8c\xe9\xccU\x1ez\x82\x83\xd9|\x0b\x99\xe7g\x1d\xbb\x87\xd7o\xbfj\xb2F\xfc\xd2\xde\xbd\xf4\x16\xbaz\x91\xb3\x9b4\xd3\xc0\xf4\x80\xdb\x91~&\x07\xc9\xd9f\xf1Kj\xc9\xf7\x0b\xba\xf6\xf9\x1d\xa0\x83\x8c\xf7\xef\xed\xaa\x8b]Lg\x82\x1fI\xec\xa73/\xda\xaa\xb4\xd4\x05\x97\x88T\\\xb4\x99\xc0\x85m\xe9\x86;E\xd4\x8fn\xe3lW\x88\xd0]\xd82\x03\xa5\x83n\xa1\x10f\xbe\x18n;\x97&\xae\xb0\x9d\xd3\x98z\xfe\xca\xf7 \xa5[\x12f\xbe\x976Y\x9d\xcb\x88\xc3Ql\xa8\xad\xb5\x9d\xd2\xaf\x99\x18/\xa84\xcbj\x07m\xe7\\-\x0e'\xb2\x88\xae\x15\x07\xb4XR\xc1\x92\xda\x9c\xaa\xd6\x0c\xde\x1f\x85\xbb\xf7U\x07\x11\x12\x02I\x16~\x960\xa11\xccD\xeaA\x12D-Z\x88\x9bJs+\x98\xb6\xe2\nU\xccd\xd157\xeacI\xeb\xa1\xc52g\x92q\x03\x7f\xc1\xa7W\xe8\xd1\x14\xd2<\x8e\xa3\x84\x9f@1\xf1\xae\xee\xe5!\xfb\x1fv\xee\x88}LUR\xd2=p\xa3\x15\xe4\x99P\x10R\xfcR\x10Y\x10\xbe\x90EX\xd3\x90&\xfc\x02-.Ge\xa4\xff\xa8\xa5\x8f\xc4\x164\xf1\x9f|$\xfc\x12r\xf8\x0c\xce\xd8\xfc\x98\xdc\x15S%\xf5\xca\xd3\xe3?\xffYq\x0c\xbc\x8a\"XE\x11<\x87\xd9l\xf6\x9f\x9d\x9f\xd9bI\xb8\xeb\xfe@\xc2\xdd\x8c\x0d\xf7*\x89\xb6wVQt\xb7\xfb\xc8l\xd6\xd5\xf3\xfe\n\xee\xb0W\xdf\xf1 ^Fw\xfe\xc4\xde\xbd\x0b\xffR\xe86\xd5\xfb\xbf\xaa\xd7\xfe\xc0\xb2\xf6\xbf\x90k\xd2{\xf1\xf0\x9c\xdb\x1a\x0ck\x8f\x95\xfa\xe9\x9dWQ4\xf3\x02\x92\xa6\x9a\x85\x8a)\xb0\x87\xc5\xdck/t\xc7jQ\xa0$\xc1C\x0b \xcev\xd9&\n\x15D\x10\xa3\xbf\x8a\xa2;\xb3\xd9\xec\xaej\xa3\x05\x01\xee(\x7f\xe3L\xc0\xc9\x82\xa5\n{\xe9T\x10\xe5\xe5\xc9\xc5\xf1\xf9\xe9\xd9\xe5\xdb\xf3\xbbm\xa5\x08\x05z\xc1(\xea\x01\xc4\x10jr<\xb2\x90\xe3\xbb\xa8K N\x8ag\xcf\xe1O\xf1b\xf6*\x8a\xfe5\x9b\xcd~\xed>D\xc2\xdd\x013c\xd8\x93\xb18\xbc_\x93$\xdd\x90\x80\x11I=Q\x15)\xda\xa3)\x86\xf2W\xad\x81\xde\x85\xdbj(>\x11\xce\x90\xfc\xa9\xff\xf3\x1cB?P2\x98z\xfc\x16']\xf2\x08\x85wU\xea iP\xc2bW\x1d\xefRK\xde\xf8A\xc0~(\xea\xe7\xd9\x91\xd8Dw[q\\\xdfcw#\xdei`\xc6L\x9b\xdb\xcc\xc6-56\xd3\xe6\xb2\xb2S\xecX\x13a\xa9\x1a\xc3`'\xed\xf9\xcee\xab4\x9b\x8a[}&\xefx\xb7\xef\xddn\xa2+.\x14rhq\x83\xa0\x05\xf7\xdcZE\xd1lA\x12>\xe9\x8f\xf7v\xb3O\xb7\xc4\x8a\x85]\xdc5\xf1\xf9\x90\xb7\xd8sL=7~\xfa\xcb\xc5\xdb7\xcd\xbf<\x7f\xfe\xfcy\x97\xf6\xec\xb9\xean)\xec\x89\x88\x89Kq\x98\n\xfb:O\xcbz\x84u\x1e\x90\xa4\x89\xa7\xfbz\xc63\xef\xaac\xf0\x00\xe8vA\x97\xcb\xea@<(\xce\xd6\xd6\x8d\xb4v< \xef\xde\xfb\xffa\xcb~_\xb8P\x1a\xcd\xc1$\x11gR\xfc\x9e)\x0cD\xe2]1\xd9\xab.\x14+?\xa0]\xfd&e\xf4\x8c&i\x14*\xd9\xb9\xb8\xf9\xaf\xfc$\xcd\xe6\x9c\xf2\xcf\xe1\xb0\x8b\xa9|\x90\xb7\x11-\x9e{`\xd7\xa8\x00\xcaQo\xf1\xf5\xdfz\x06\xb7T\x9c\xdd\\\xd6L\xcc\xfe\xd6\x81\n\x0f\x9f\xf7\x1b\xb2e\xb8\xfeKL\xf1\xbf\x95\x0f\xb2y\xb7\x9e\xb3M\xfetU\x18\xb6\xcd=\x16;\xe4\xa7pC\x83\xe0\xeb\xab0\xba\x11~\xde\x0dw\xc5\x17\x8e\xd9.\xa36\xd9\xe9@\x18[-\x1e\x13\x8a\xa06$c\x1c^\xf5\xcd\xd9\xa6\x89\xf0=gb\xc9C\x9b(X6\\\xc3\\\x04\xfc\xb0\xe4=(< \x05\xeb5qq\xf4%\xc7\xc1\x1d&\xbfr\xb9\x9dk\xab\xf4\xa2\xfc\xfc\xcf\x9f\xef*\x98s\xc8~7\x07Po9_6Cu8{p\xf8 \xbd\xa5\xd8F\xf9\xaf\x86U]v\xddKh\x96'\xa1(\x11\x90\x7fL\xa7x\xf4\x14\x8f\xdeg<\xbaY\x8b\xa9\xf0ucrjk\xaf\x15\xd8\xfe\x7f\xf6\xde\xf6=\x8e\xdc\xc8\x13\xfc\xee\xbf\"Vw\xcfH=CU\xaf={_t\xdb~V\xa2\xd4m\xcevK<\x91\xf2\x9cw\xceOu\xb2\n$sT\x95Y\xceDQ\xa4\xe7\xfc\xbf\xef\x83\xb7L$\x10x\xc9\x04Jn\x8f\x81\x0fv\x8b\x95\x19xI \x10\x88\xf8\xfd\x02\x1f/\xcfU#\xad`4\xeef\xcf\xe8c\xf7//\xd1\x19>\xa6d;\xfc\xbch5P\xd4\xf1\xee\x9c<\xfe\xe3|F\x97\xbb\xdb\xe1\x9e\xcf\xdd\x9e\xcd\xd9\xeet\xb5'8\xdas\xb9\xd9\xfdN\xf6E.\xf6\xbc\x0ev\xa7{=\xafs\xdd\xe1ZOt\xac[\xc3m\xdb\xdc\xb9\x9d\xea\x89.\xf5\xcc\x0e\xf5\x04wzngz6Wz^Gz67z\xd8\x89\x9e\xcd\x85\xeer\xa0\xa7\xb8\xcfQw9b\xb3\xda\xfa&\xcdU\x8e\xb8\xc6\x17:\xc6\x11\xb7x\xd0\xca\xb2\xccF\xff\x0e\xba\xd0\x1d>\xba\xbf\xb1\xf1\xfd\x95\xbb^\xd4n\x89\xb1\x97\x86\xab\xb9\x98\x99$dYV\xd2]\xfb\xa0%T:\xb4}\x1d\x0f!9\xc8\xec\x80Hz\xbe\x18\xf4\xc8VT\xd7\xfa3M\xe2\xf9\xae\xf2\"\x1b\xfeJP\xaay8\xaaf\x01\x80\xea\xa2\xa1_\x13@%'\xd0\xd8'\xd5f\xf5\xad%\x03\xbda\x96\x0b\xff\xbb\xc6\xdf\xe4\x7f\xa5\xf5\x107R\xb3\xcb?Yg\xa6X\xda\xd7\xcdz\xabOs(S\xea\x172\xa5\xac\xae\xfdT7\xf5\xfe\xb8WsG\xc2\xe9\xd4\xb4`S\x864\x94t2\xa3.\x08\x18\x9b\x92\xb5\xaf\x1e\xd5\x87\x8e\x03\xb8\xb9u\xfeO\xd5#o\x87\x10\xc3\x9b\xf1\x9a\xf5\xf4\xbe\xddmI\xc7\xe7\xaej\"\x1b\xd8q\xe2\xc2\x05\xb3\x15'l%\xb1=\x81~\xfd\x0c\xec\xdb\x86\xdec\xf4\x9a\xc9\x14\xb7\x89\xbc\xbd\x84\xa4\xf1\x87zV\xf7]\xfb@\xba\xa6b*_5\xa2w,\x1f\x95\xd95z\xe5$*{~ \xb0\xf5x9\xff\x96\xf3o9\xff\xaaR\xce\xbf\xea\xf5r\xfe-\xe7\xdfr\xfe\xfd{;\xff\xfa\xeb\xce\x0c\x04\xb3a`\x19@`Y!`\xe6f\x98\x08\xff\x92\x03\xadKL\x01|y\x11O\x0e\xb0W\x10\xeae\xa3K\xe2a^\xf6\xbb\x7f\xc1\xfa\xba\x08\xe0\x15\xd3\xd9\x10\xb8\xcb\xdd\xb7 \xb0k\x06\xack\x1a\xc5O\x84ty\x01]n8\x97\x0f\xcc\x85\x8eB,\x90+\x04\xe32A\\ \x10\xae\x08\x00\xd7|\xf8\x16\x02\x9e\nA\xb72\x01\xb7\x90\x9a'3%+d+3`++\\+'X\xcb \xd52\xf1/&L+\x0fH+\x1bD+/@+\x0e\x9e\x15\x04gEB\xb3b\x80Y\x16,\xcb\xae-\x16\xa2\xe3\x87dE\x02\xb2\"\xe0X\x93&\xe7\x84be\x06b\xe5\x83a\xe5\x03a-\xff\xbaA\x00V\x08~\xa5\xd4wO+z\xb4\x08\xe0\x86\x0dn\xdfh\xa5n^Z_]\xbf\xbe\xfet\xb5\xfe\xf4\xfe\xea\xf2\xdd\xf9\xc5\xf7\x17\xef\xdez\x9f{\xfb\xee\xf2\xc3\xd5\xc5\xf5\xfa\xf2\xdd\xc7\x8b\x0f\xfeG\x7f\xff\xe1\xfa\xe2\xfd\x0f1O^\xbe\xbe\xba\n\xd4\xfb\xf1\xdd\xbf\xbc;\xbf\x0e<\xf4\xfd\xeb\x8b\x1f\xb5G\x86k\xb2b:\xeb\xf6u+\x07\xe6\x15\x1fi>\x96\xdc\xf2\xd52\xae\xc8\xaf .v\xd1\xfc\xb2\x93\xf9\xe2\x1dto#\x8d\x94\x94b'\xe4\x95\x1c\xfaj'+_\xf9\xeb\x9a~8\xbb\xba\xe9\xef\x9ag\x7fp\x83\x8bj`{\xe4jP4\x85{\x84\xb5\x8a\xa7\xaeqGS&\x13\xc3n\xc9\xe4\xe7\xb8\x86\x08\xc7\xfc\xdcv\x88ig7@\xfc\xddS\xf3\xe4#\x0b\xbdv_\xe9\x9e<\x81\xed\x0bT\xaf\xa6\xb4\xdd\x00\xf5KJ\x13n\x08i\xa0#\xffN64\xd8\x12\xb1n\xecv\x88\xbf\xa7\xb4\xe2\xb6\xaawc\xf5\xb7uS\xed\xd6\xb4\xda\xed\x9e\xd6\xc2\x89\xb5\xc8K\xff\xfc\x89\xf4\xcf\xa3<\x0f\xd5M\xcf\xec\x89\xa8g\x9f7m\x9c\xd0\xa6]3\xcbf\xfd@h\x1b\xf1\xc2D\xb1\\\xb3\xbe\x7f\xe4]\xd7\x86\x95'y\xa8\xba-\xf0\xa1\x91\xe1'$\xc4\xa2\xc6\xb1?\xde\xeck\xba\xa6\xf5>\xf6\"1\xf3:4\x15\xb0\"\xcd6E\x8c\xb8\xcb\xb1\x849\x7f\xa1aNy\xc9fO\xab.i\xb6H9I\x93e2\xc8jK5\xd2\xc2vD\x8e\xcc\x9e\xd9\x83\x9d\xd4/\x8e\x85\xe0 5^i6\x91\xd5\xc4\xe9\xbd\xeca\xd3 \xb4\x95:\x1f\xc3\xec\x9f\x80\xed\x13\xb4{\xbc6O\xb4\xbd\x83O\xf8\x1cv\xce\xd7\xb2qB\x1f\xe5\x14\xf6\x8daS|u\xbb&X\xffi\xec\x19\xc3\x96\xf9\x9av\x0cn\xc3|-\xfbe\xb4]\x10U#\xd3\xbb\xf3\xf91\x1b\xe1om\x98\x93\x05\xb95\xb0Mt\x82\xef\x97\xbf\xae\x0c\x1d\x1ce8\xa1\xc8\n\x88 \xdcX\xf4\x10\x04R\xe7\x11\x84m\xc7\x98\x91\x00\xffy3\x10/6$,I)\xd6\x84%,-\xcf\xb0\x07Fj\xac\x8d\x18\x14\xa9\x02\xf5E\x82H\xf5j\xe6\xa7\xdaUh\xa6\xd3Z\xad\xce\x15\xe7\x9dK\x1eR\x96c\xdd-4\x85\xff\x8eo\x96\xca\xb7\x1e3\xaf\xc8\x93\xdc\x1e\xf5[3\xb5b\x12|v:\xbf\x04\x94\x16\x9d\xf6\xaa=\x85\xecY\xc8\x9e\xa7'{\x9a{\xc1\x8c=\xa7\x9f\xb5\xe9,\xbcDG\x1e\xa3\xbdw\xe9L\x9e\xb1\x91\xb8\xe2J\x9d\x8e\x88\xcc\xb5\xb4\x95\xcf/Z\x0d\xaa*$ \xbcs\x06M\xda\xfa#i\xee\xe8\xbd\x8a\x06\xa2\xe0\xe8\x01\x18\xed\xeb\xf3\xf4\xa1\x88N\xa7\xd8\xc0(.\x1f\x8a=\xba|\xff\xcb\xba\xfb\xa5\xd9\xa3\xaa\xe4C\xf7C\x00\xe1\x0f\xd1\xab\xc5F\xb7eD\xfb\x83\x03\xf1\x0f\x06\xea\x1f\x84\x8b\xd9\xbf\x1e\xf5G\"V#\x7f|\xd1Z\xfc\xd3\xb1\xed\x8e\xfb\xc8\xc1\\\x8a!\x94_\xff@\xba\x0di(\xdbM\x99\xc2\xe2\xbbYO\xab\xcfD\xcb\xd6\xfb\xd0R\"\xa7\x87\xd8\xde\xec\xdd\xf9\xc6B\xa2n\xda\xa6\xaf\xb7\x84MH\xee#\xd3g\x0e\xbd\xefH\xcf\xbe\xe7W\xea#\x9b!\x1d\x95\x10\x8d?\x90\x9e\xf7H\xb07\xf4\xf9\xce\xac\x91\x15\xbc\x15N6|\x16\xfd\xd7\xd5\xff\xa5w\xe4\x81\xd0v\xfd\x95{#L\x81\xf6\x16~O\xe4\xb7\xe1k\x82\xdf\xfb(\xff\xc9\xa3\xe7f\xf7\x82_\x8cu\x86l\x87\x01P]\xfe\xf5\xb7\xff\x8c\x9cjOp+\x9bmO\xc8\xc6\xcf\xb6(T\xaf_-Y}\x19\xbdA\x16\xe7\x06|{\xa4{\x87\xa4\x8e\xc4\xcf\xc9\xa7\xbd\x8c\\\x1c\x08$\x80\xce\xc9\xc9\x81\x9c\xbc\x1c\xf0\xa7\x81N\xe2\xe7@F\x8e\x0e\x04y:\xb0\x94\xab\x03)|\x1dl\xc4\x9e\x0e|\xbe8SB'\xf0v\x10Y\xc2\x90r\xa6\x85N\xe3\xef \xe2\x8e\x07gj\xe8\xdc<\x1eH\xe7\xf2@~>\x0f\xa4qz \x8d\xd7\x83/Q\xb4\x91\xd9\xd8>\x90\x9d\xf1\x039Y?\x10\xc5\xfc\x81\x9c\xec\x1f\xf0\xa6\x90Nc\x01ak\x1cM#-TM\x90\x1b\x04\xc9\xfc D \x96Lz1k\x08\\ \xa5\x03[\xbc'\xa9t\xcc\xfe\xbf\x90I\x84\xa9=gj\xe9P;\xd2XE\x860\xce1B\x13Lga\x17An\x86\x11 ,#Hg\x1a\x19\xd2(\x92j:\x8d{\x04!J\x0e\xf8\x12NG\xf0\x90\xc0\x95\xe9v\x06\x1f\xc9-\xc3\xc2\xa3'q\x93`\xc6`\x848J\x10\xecw\x90\xab\x04\xf3\xf8J\x80\xa6MM\xe4-A\x88\xbb\x04\x81t\xd4\xa1\x84\xd4\x9eQ\x8a\xe52A\x04\x9f \xd0\xc4\xd4I\xbc&\x88\xe36\xc1\"~\x138\x07&\xc8s\x82|\\'p\xb7\xc2\x9aiYyO\x90\xc8}2Da\xa9\xab3\xb3\xa1 3#\n\xfc \xac\xb1\x14\xd6X\x12\xeb\\\x0c)\xc8\xc9\x92\x82\xecL)\x88fKA\x0cc\n\xe2YS\x10\xc9\x9c\x02<\xa95\x9e\xe68\x9eg\x13Jl\x1d\xcd\xa4\x8286\x15`\xdd\xc8\xc9\xaa\x82Tf\x95!\x0bIx\x9d\x93k\x05Y\xf9V\x90<\x1f\x82\xbc+\x88\xe0^\xc1$\xf9\xb5\xcd\xc1\x02\xdfi\xc6\xe4bA\x086\x1b|\xd6\xc9\xc9\xc2\x1fw\xf1\xb2\xf0\xa7-n\x16\xfe\x18\xc2\xcf\xc2\x1f48Z0\x07\xb7<\xbe\xe0\x06\xec\xe7\xc11\xab\xf2\xb5\xf0\xcc\xee\xfaN\x8fkV\x05\xe1L\xe1M:1\xceyv{N\x83{\x1e\x9aas\xb9\xf0f\x9c\x0e\x07\xad\x8a\x9b\xd3\x85\xb7\xe84\xb8hU\xa6\xdc.\x08\xf0\xbb`YD\x08\xe1z\x81\xdfW\x84r\xbe\x02\xef\xd8\xdc\xaf\xc0\x0bn\x0e\x98\xf7\xc5\x13p\xc1\xc0\xc5\x07\xf36\xc4\xc5\xf4\x01\x0d\xb3c\xd3}\x16\x8bt\xf0\xc4\xa0\xc0n\xfe\x13\xc1n\x08\xe1\x0fr#\x102c\x10\x02(\x84d\x1cB^$B\x0c\x16!\x01\x8d\x90\x17\x8f\x10\x85H\xc8\x8bI\x88@%d\xc7%\x04\x90 \xcb\xb0 \xa8 /^!\x0bb!\x12\xb3\x80\xbe9\x0b\xc7\x90\x8cd\xc8\x8dep\xa3\x192\xe3\x19N\x81h\xc8\x8ci\x88E5d\xc65\xf8\x91\x0d\xd9\xb1\x0dnt\xc3\x0c|\xc3r\x84\x03*\xcc\x95\x15U\x94\x04\x94\x83\x13\xe7\x104)\xbcX\x878\x8b#\x1f\xde\xc1\x8fx\x08\xb7&+\xea\xc1\x8f{\xc8\x86|H\xc5>X\xe2\xb8E\x83\x1a\x0fy\xf1\x0f.\x04D:\x06\"\"\xf0\xef\xc5AD\"!\x9c\xe1\xd4\x99h\x08\xb7\x1c$\xc6\x94\x8c\x89\x98381\xb8\x88\xf0(Da#f\xa3#\xf0\x08\\\x06\x84D\x04F\"\x84\x92\x08\xe3$\xbc\xa36\x07+\x11\x87\x96\xc0\xf1\x12\xc9\x88\x89h\xcc\xc4R\xd4\x84{\x98\xa2\x90\x13Y\xb1\x13\x9e\xb6 31 AaIC\x10\x15Y1\x15.TE\"\xae\xc2n\xb2\x8d\xb3\xc8\x8f\xb4\x08`-p\xb4\x05\x8e\xb7\xc8\x89\xb8\xc8\x8c\xb98\x05\xeab\x0e\xee\"\x12y1\x0b{\x11\x8f\xbep\xe0/\\\x11\xf7\xf8\x98{\x18\x831\x0b\x85\x11\x8d\xc3@;\x94\x1b\x8b\x91\x17\x8d\xe1\xc0c\xe4Fd\xe4\xc6d\xa4\xcf\x91(\\F\x1c2c\x8a\xcd\xc0\xd1\x19\xde3\x18\x86\xd0\x98\x87\xd1\x08\x07\xf2#^\xf0\xe14\xa2\x91\x1a3\xb0\x1a\x91h\x8d\x05x\x8d\x10b#/f\xe3\xeb\xa36\xc2\x9f\xfb\x94\xb8\x0d'R\"8\xa9N\x87\xdd\x98\xd5\xa6\xd3\xe27\x9c\x08\x8e\xbf\x0e\x86#\x84\xe2\xf8\xfa8\x0e\x0c\xc9\x11\xc6r,\x8e\xb59\x10\x1d\xa1`\xbc\x0b\xd5\x11x\x0fGv\x04^\xf2\xa3;\xe2\xe3\xff\xf9\x10\x1e\x1e\x8cGT\x04\x15\x8b\xad\x87\x90\x1e \x82=x\x0f7\xe2\xa3\xa4\x1e\x9b\x8d\x01\xc9\x8c\x02\xc9\x95z,\x88\x05I\x98Z^D\xc8b\xb9'\xc0\x85\x94\xacg%\xeb\xd9i\xb2\x9e\xfd\xff(\xc8h^z\x12\xf5\xd2,\x98\x91\xb6\x9f\xcd\x06\x1a\xf1\xcd\xce\xb1\x0e\xc4F\x88\xe7\xbb]\x9e]\xe8o\xe7\x9a\x00\x0f\x84\x0c\x19\xf2\x98\xef\xcb_\x9b\xf5m\x7f\xdfR2\xfb\xa3>\xb4\x948\xbe)\xcf\xa5\xa4&3k\x18[\xe15\xd9\xf2\x1f\x16}O'\x86l\xfe\xcagm\x88\xcb\\,\xb0(Q\x8f\xba\xa8\x1d\xbf\xffp\xfdn\xfd\xe1\xf2\xfa\xe2\xc3{/\xadC\x7f\xee\x0f\xef\xae\xbc\xbf\xbf~su\xfd\xfa\xe2\xbd\xf7\x99\xf7\x1f\x02?\xaf\xff\xf5\xe2\xfaw\xeb\xdf\xbf\xbb\x9e>8\x1c\xefc\x1a\xee\xb7v\xd8\xa4\xfa\xc0\x7f\xc4\x8f\xf4|\x92\x88!\xee\x95!\\?\x103\x80\x8a\xee\xb1\xc63\xee\x81vvD\xb3\xc1\x9a\xf6e{\xd0\x9b\x83\xa0\xeb\x8d\xef\xf3\xca\xfc\x83&\xeeI\xa6\xde\x8a\x13&?\xe6+\xec\x8f\xa3\xd0F\xa9\xa9\x19\x92\xdf\x7fxe\xfc{\xd2\xe7Y\x92\xc6\xd9b\xca\x1c\x7f\x99J\xe7&\xed\x83J\xde5\xa9\xc7N\xb1\xa5\xeb\x9f\x18\x0d\xc7\x9e\x8fL\xaf\xc5\x1e\x9d\x8f\x8c\xe5\x19\xc6^\x19\x8a\xea\x17\x8e\x8aE\xf4\x9aG\x14\xa6\xdb\xbc5\xbb\x1c\xa31\x8a\xc2~\xd2\xd6qqZ.\xa8\xe7\xa25\xddL]\x17\xd2v\xd9\xf4]\xa4\xc6;\xb9\xce\xcb\xac\xf5N\xa9\xf7rj\xbe\x13\xeb>Q|\x1e\xf1\xdf\x8f\xb6\x13\x13'$41^\xa2\xd7\xe2]\x9e\x93\xb2\xa7\xa6\x03\xf0\xe2\xed\x99r\xd9\x92\xeel\xb8\x07\x15m\xa1e\xcc\xf5Nk\xae/\x07\xder\xe0=\xe5\x81\xd7\xde\xc5c-\x84\x88\x0c\x9c\xfc\xa8t\xa9\xe5\xc3\x8d\xb0\x0d\xcc\xc4\xb5\xe8\xa7@\xe7\x95{\xd9\xa7&\xaa5\x12\x9d\xba\xd2\xd2\"I\\\x17\xb6\xfe\xb7h\xeb\xbb\x05)hm\xa4\xac\x96~\xd6\x95zva\xab\xd11_\x9aj\xd6\x18\xf3Y\x89e\xb5yg(C\xfe'>\x97\xd9#us'\x9b\xd06\xd8\x06\xd0\xfb\xe6\xf5G-r\x131\xaf\x0d\x97 2\xc4\x96\xab\x04yf\xea\"A\x1e\xc0]#~\xb7Hz,\x05\x19\xa3\xdf\x0f\xfe\x8b\x88\xc1A\xadu\xef,\x9c(`\xc36G^4\xedqT\xb6}\x95o\xd8t\xf5\xd9\xdd!\x8b\xdbckGX\xd9\xd1\xf6\xb5[\xb3,\xb5\xa9\xb5i\xa0I\xc3\xad\xe9\x13\xda\xd1\xd9,\xe8\xd3\xd8\xcey\xac\xe6\x93\xda\xcb\xb8\xfa^b#\xe7\xb0\x8e\x1dZ\xe4\x83\xb6v\xadu;\xbdr\xd2\xbf\x14\\k\xd5\xb7N\x1dk4\xb0>\xa3\xd6&\xbe.\xf3\xadI{=\x9eh-fY\x87\xf9\xd7`\xfa\xfa;\xe1\xda\xc3\xe7z\xdd\xdc\xcd4\x97\x1d7\xcd\xa0\xfb\xdbd\xc2\x05o\x98\x99<\xad\xb7\xcdeRI\x19aSj_7t\xbcXv^\x7f\xd9\xbbk\x03z\x80vV\x1e\xc7\xa8\xe4'm\xda\x9a#7\xd9\xfb\xf2\x99\xba\xb9\xdd\xf1\x93\xf1\x9a\xad\xb1\xb5 \x07\xc6I\xdd\xcb\xfbE\xaa\xa69V;\xc9+d\x07\xecA&3j\x89U\xd1\xbez\x9cWAH^\xc0\\\x1c\xe5Ik\x1c\x95w\xd7V\xbb\xf5M\xdblIh\x06Ii\xec\x056\xa8\xf2<\x05\xe2]\xa8h\xbb\x1f\xee\x17\xdd\xb5\x9b\xcf=\x9b\x97\xeb'R\xf9\x8d3\xe7\xb1ZV'8\xd5d+\x85\xb2j\x81 \xb5\xa7\xa9\x9c\xa0\x02\xc3\xab]\xa9\xa2N\xaf\xec\xeb\xc3\xbe\xdd\x1ew\xc45\x1f\xf9\x01\xf75\xff\xae\x97]\xfbP\xf7L\xd1\xce\xf6p\x8b\x89\xb1>\x0c\x12\"\x07\xc0}\xb8\xb2$\xaas\xbad\xa5\xf2\xbeq\xdc\xb3\x98\x93\xda\x83\xfc\xac\xe4\xdb\xf0\xbd}\xf6\xfa\x03t\x01\xdf\x9a\x12p\x07\x81=\xda\x17jR\xce\x1e\xe6a:'\x0f\xef\xb80\x1c\xc3:>\x107\x9cV\xa7b\xfc*\xc3K\xbe\xf8\xb2=\x80\x0b/M\xf3\xdeT\xe4\xbf\xa3Hn\x1b\xe3R\xd2\x07?\xca\x93\x88)rp}?\x88R\xe8\x10V\xea15\xccS\xee\xe0V\xf0s*\x8b\x91\x1d \xa3\x88S\xfa\xe0R\xfc1\x92#6\x00\xf0m\x02\xde:\xc2>\xd6\xf8\x0d\xe1\x04W\x0c\x89\x851\xb5_\xce\xb5i\x16\xb1\xf0\xfa\xe3M\x7f\xa86~cc\xe2eG~7\x1c{\xd6\x13\xb8n\xd2\x9a\xab\xdb\xd1u\xb3\xad\x1f\xea-\xdf8\xd4*\x973_\x10\xdcD*\x13]\x08{D\x08\xba\xb4=A\xc6 %k)\x9f\x92\x9a\xe8(\x15<\x19z\xb1H9\xd9\x1f\x08\xdc366\x1c\x82\xe4,\xf0\x7f4\xc7\xe4]:q\xfb]\xd5\xdf\xd7\xcd\xddR\xd3\xbb\xaf\xef\x1a\xb2]\xcbE\xfd\xa5n\xb6\xed\x97\xc8}W_\xc9\xfb\xbaYKQL1\xcc\x92\xa3\xed\xdf\xdb\xf6KC\xeb=Y\xff{U\xef\xd6[\xc9n\xf2\xca\xe1\x03\xb0\xbe\xe5\x19\x81\xdaf\xbdm\x8f7;\xc2\xdb2\xbfzK\x96h\xcd\\A\x98\xf5:\xf0\xdb\xac]w\xc8 r#\xc2[\xea\x8b\xda&\xad\xf5\xad\x93W\xa0e\xc1\xc6-$\xef\x9c\x81\x98m\xc0\xdc\x05\x02\xf3'J\xa6\x11\x8f\x0c\xcd%\x8f\xcc\x989\xe5y\xdd\xd9\xa4\xe0\xfc\x9a/4\xfb\\\x1b\xf6\xe3\\\xbblh\xfe^\xd5wM\xdd\xdc]4\xb7\xed\xecI\xfcP\xed\xf8g\xa9\x9b\xbbu\xdd\xdc\xea\xc1\x11\xd1 \xf3\x01\xd5\x03\xf97\xe0\x7f\xe3a[\x85\x9f}`\xd6!\xcf\xd6$n\xf0^\xb2@\xe4\xabQ\xdfU@\xfe\xefI}w\x8ff\xfa\x9c\xb1\x88\x86^\x0biP)6\x03w2V\xb4\xedxP\x993\x87\xa1\x82M\xd5l\xd9\x9f |\xf8\xc8\x7f86\xff\xce\x89M\x9a\xc8\xba\xd9\x92\xc7u{{\xdb\x93l\xad\xe32A\xc8\x14\xa9\xa9\xc4\xca\x17\x86\x1f\xdc\xd4\xd4\"\xbb\x88v\xad\x8f\x0d\xad\xe7\x06\xf5\x1d\x84\x1by\xee\xa8\xf7\xa4\xa7\xd5\xfe\xa0\x0d\xd1\xa6j\x9a\x96'\x03R\xe3\x01\xbc^\xed}\xda\xeeoz\xda6\xb8\x85}\xd3\xb6;b\\\xfa\xee\xc2\x11|\xb9'<)\x13O\xecFU\xfa!\xde\x8e\xfb\xaa\x17\xd4\xb7\xb16x\xf1\xb9\xde\xb1\x06\xb5G\n\xad\x89+\x18^5\x91\x04=\xa1zf\x8b}\xdd\xf7\xa3\xfa\xe6\x08\x84Hpo\xc4\xc7\x15\xc2\x95\x0d/\x85\xc3\x8b!\xe7X\xcf\x86WQ!\xf9g\x06\xf2\xc0\x91\x1d\xb5\x9eq\xca\x13\xdeR\xbd\xd4\xf4\x86\x1e\xd7P??\xef\xa7\x8b\x9c\x13\xb6\xdb\xa6\xa6\xad\xd1)zO\xea\xc9\x90\xed\xea\x07\xd2\x90\xbe\x177\xf5\xd7\xf4i\xa2\x16\xa7psDy\xc5(I\xed5)\xed\xe3\xe5\xb9j\xc3l\xb59\x7f\xf37t%\x7f!/T\x13U\x81\x9e\x89\xe5V\x83\x9e\x97|\xf3\xf1\x04\xca\xd0\xa7\x0eS[\xb9@)\xfa\xd4bTsp\xd5\x98\xaa\x1c\xdd\xea\xd1\xa7 \xdd*2\xaf\x92\xf4\xa8IKQF\xa9\xca\xa8\x91\xf6|\xf8L\n\xd3\x8f\xb5MP\x9a\xd3\xf1\x18\x14\xa8\xad6\x9d\x8a\x13\xf4Y\xee6\xc1\xaa\xddnl\x882\xbb0\x84\xe4\x0cC\xac \x1bC^\xb7_>\xb2\x11\xbc\x884Q\xa5\xb6\xf3\xb6\x93\xb41u\x03w\xec(2l\xc62gK\xcf\x94JG`\x9a\x86j\xd3v\xe2A\x9ekF\x9e \x864/L\xd7\xf0\x03\x94\xde\xcdI\xdf\xd4\x93W\xed~l\x14\x9a\xe9\xa5#\x07\xc2S\x14\xbe\xa9\xbaad]9\x89&}\xe4\xd3\xc3\xccH$\x12\xb8\x84,\x94Y\xe78\xfd=)o\x8e\x8d\x82i\x9ch\xf3\xc42\x1e\x90 \x8e\x1b\x0c\xe8J\xc0\xb5pV\xf3\x007\x0c\xe6\xb7f\xa6\x19\x80\x1b\x00\xdej\xedM\x7f\xf9v\x8fm\xf4\xf8\x16\x8fi\x9b\\\xdb:\xba\xa1k[y`\x13\x9f\xff\x912l\xd9\x0e\x98\xd0\xf2m\xda>\xdbL6htkVk\x97\xf2D\xca\xc3\xd2}\xd36\xdb+-\x07\x945@Sx\xd6\x9b\x0f\xef\xdf\xba\x13\x1a\x99\xbf\xb3\x7fy\x7f\xbcx\xff\x03\xfa\xab\xf6\xe2\x00\xc4\xf2U\x8do\x19c\xdf\x063D\xcb\xfc2\x0c\xb0\x8e\xaerT\xf2\nPDU\x03u#1]\xc3l6\xb2 \xe1C\xc2\xe4\x89\xff\xc2\xbe\xb8\xc8E#\xb3H\x8b\xc0\x9cW\xde\xc5\xfb\x1f\x94\xc0\x8b\xf7?x%\x1e\x9b\x1b\xb1\xe19\x04\xaa\xe6E4nl\x98cj\x9d\xb7{\xb6x\x0c\xe4\x9fw/\xd8\x0c\xaf\xf0\xe0\xef2\x8f5{3\xcad\xdaW\x8f\xebY\x0f\x8bpZ\xec;n\x1b}\x1c\x99\x8f\xd5\xc8\x1d\x12S\x94'\xdd\xe7nI\xf5\x0cH\x00!7v\x94SW\x93\xb6\xe9H\xc5\xb3Li\x7f\x9bLo\xf1\xa7\xe3\x81\xed\x06\xeb\x191\x8e\xe9\xee1\xe9\xce\xd8\x83\xa1\xf1Z\x83\x0d\xdc\x8e\xc27N\x9a\x14\x9c4\x1f\xc7 \x101s\xa6\xdf\x04\xe9\x96\xfd\xb1\x1d\x0f\xa1\x1f\xd9z\x16\xff\xb8\xf9>\xac\xf9Q\xab\xa8\xd1{Kv\xe4N;AE\x0c\xdcV\xbc\xd2v\xeb\x18ClhD\xd4\xd3\xfd}\xd5\xd9\x8b\xd85\x8a\x83\xde\x1e{aF7\x98\xce\x11\x88L\x9e\x17\xa8\x87{\xb2\xe3\x99v\xaa\x06\xaa\x0d\xdf\x9cWp\xc1\xd4\x93\x14\xd5~iD*\x9e\xb6!cWe\xa6~~\xf7D\xbb\xa9\xb9m.\xa4j@\xca\xf6\x8b8\n\xb5\x0d1;\x1f\xf5\x05f\xfb\xe9\xb6\xc6\xc7C_\xc3_\x05\xff\x87\x04\xb7Z\xf3|P\xcf[\xe6\x87u>\xea>\xcbe\xfc\xc8\x90\xfbC\x83\xf9\xb1Y\xb9\xa9vUc#>\"\xbfM,J\n\xcb\xac5sd\x17g\xd0\x1aE\xa4$\xce\x1a\x8f\x8b\xaa\xc4e\xc7\n\xe9\x02\xfd<\xcb\xa4\xdae\xd5\xd1\x9e\xd0\xdf\xf1Q1?7?e\xd0\xb5\xdd\x84\xe0\x0cr\xc5C\x98(\xb1\xb6\xc4DaKP{\x8e\xfd3CucP(\x830\xb3\xed\xb7]\xbb\x17~\xba\xc3\x01\xda#=\x1c\xe9\xf8\xb7q\x0dh\x12x\xcc'k\x9b\x06M\x99AVu8d\x90\xc2\xe7\x8b\x0cKd\x10G\x1e\x98\xa1\xb2!\x19D\x0d\xdfo\xdc^\x0c\xf5$\xc8id\xde\xe9%\x06]'V\xd5\xe4\x00?l7\xc2\x7fxM\x9a-\xe98\x1fI,\x08\xa1\x9e\xd4\x8e\xf1P\xed\x90\xf0@^\xdc\x05\xfb\xab\xfb\xec\xe6\xe9\xff8 \x0f\xc7\x1b+d\xea\xd5\xa8>}J\xcbM\xb1\xe5\xa6\xd8rSl\xb9)\xd6,\xe5\xa6X\xbd\x94\x9bb\xb5Rn\x8a-7\xc5\x96\x9bb\x83\xad)7\xc5B\xb9)\x16\xcaM\xb1\xe5\xa6\xd8rSl\xb9)\xd6*\xe5\xa6\xd8rSl\xb9)v(\xe5\xa6\xd8rSl\xb9)6\xefM\xb1\x02\x12\x8e{\x8a1\x92W\xb6\x9be\xfd\x98c\xf7\x93\x13\xf4\xb1\xff\xb1\x11\x87\xecz\x0e\x15\x16\x85M\xd6\x1fwAvD\x99\x8dW\x1e\xcb \x90\xcbn\xe1\xa9\x18f\xbf\xe4$4\xb3K\xf4\"\\\xf3X\x04\x10-z.\x8fP<\x0c(\xe7}\xd1\x80\x0e\x99\xef\xcc\x0e\xc9X\xc0\xa2\xb1x\xdd'6\xd8(\xf2E\x0b\x80\x14\xf9\x9e\x1b\x94\x14)\xc0\x02*E\xbd\x97\x02^\x1a\xcb0\x11s\x92\x9aG\xa1\x19\xefr\xd41\xf6\x99\xa6\x98\x1b\xb4?\x16\x8fh\x08\x8240H\xffX\xbc\x93\x02\x9c0\xff\xb1D pB\xff\xc7\x12\x90\x13\xf2\xf0A\x12~\x1c\x157\xf8\x951\x8a\xc0X\x10\xb2\x80&\x03\xa3\x0d\x8c%\xd0\xe9\x10\xfb<3\xa9`,<\xc7\x10\xd9\xdd\xae1T\xb5(\x8e\xa6GQ\xab1\xf5p\x06\xb4\xbd\x13,\xb7\x01c,x\xb5\x12D+#\xd1\xb8\xc4\xe7b\xe7QPTy\x18\xae\xd9qS\xe6/\xec8D\xad\xe5y\x13\xfb\x15\\I\x16\xe6D\x9c\x8a\x17\x99!\xdd\n\xb6\x84M\x821H9\x11{&\x02P6\x95g\xdf\x13>\x14\xd3\x89!cI\xd3Z&\xe3\xbf\x92\xe9\x99%\x18}S5\xec\x94\xa3>\x01;\xe7(\x8a\xb6\xcc\xd3(\x9a7\x95\xb8?\xeeh}\xd8\xd5\xa2\x11S\xf9\xfcA|fO\xb1\xb6\xe3\xd9\\\xc0Y\xf8D\xd4\x86\xb8\x11+\x9a\x0d\xa8}E\x17\xc7\xc1\x0c\xe6)\x87\xe8\x03\x13.:p\xa8:>r\x12\xec+\xd3P=\xef\x05\xf8\xf2L\x9e\xc9\x0e\xa4\x13\xf9\xe7\xf9\xb9\xab\xf9Y\n\xdb\xb7#\xa8\xa2#\xd7\x82\xd1\x13a\xeco\x86})\xfc\xa6R\x82\xeeZe\xbdc\x1f\xeee\xdb\x89\xbb\xa9wuO\xcb>Y\xf6\xc9\xaf\xb7O\x9as?a\xc3\xf4\x8aZ\xb2s\x0e\xa1\xb2\xd9\xdb\xe5\xb0\xc8\x1cK\xe7\xc1\n\xeb\xf1\xd8\xdd4\xb8\xd4\xdc\xb6\x8bV\x8c\x9f\xa4\xeb\x98h~\x82\xaesGs\xeff\xd4I\xcdMT\xd9\x99I\xb9~Jn^BnV:\xae\x97\x8cK\xd3\xa8\xb89\x89\xb8a\x1a\xeeb\x12nN\n.\x0d\x13ps\xd2o\x83\xe4\xdb\xcc\xd4[/\xf1v \xed\xd6O\xb1\xcd@\xb0\x8d\xa2\xd7\xce\xa3\xd2&\x12i\xf3\xd2h]\xcc\xce\xac\x14\xda\xfc\x04\xda\xac\xf4\xd98\xf2lV\xea\xac\x8f8\x9b\x996\xeb\"\xcd\xd2X\xca\xecR\xc2\xac \xc7\"\x02q\xbal\x02Y\xd6A\x95\xf5n\xf1^\x9alx\xff\xcfG\x91\xf5\x11d\xfd\xed\xc8J\x8e\xf5Qc3\x11c\xd3h\xb1\xc8J\xc2\xb6\xf2\xbc\x94X\x8a\x12bS\xe9\xb0A\xbe\xa7\x87\n\x1bE\x84\xc5yq\xf3H\xb0\xb8\x0c\x8b\x13\x93L\x7f\x8d\x1d\x8c\x18\xea\xab\xbf\xdfQ\xb4\xd7\x99\xa4W\x9b#\x94\x81\xf0\x1a\xa4\xbb\xfa\xc9\xae!\xaa\xabs\x94\xe6\xd0\\cH\xae\x18\xc55\x91\xe0\x1aIo]Fnu\xd0Ic\x88\xad\x19i\xad\x8eVX3-\x89\xd0\x8a\x11X3\xd2Wq\xf2j\x12u\x15\xa3\xaa\xe6&\xaazi\xaa\x18\x7f\x0f\xa3\xa8\xe6#\xa8f\xa5\xa7\xe6'\xa7\xc6SS\xa3\x88\xa9\xd2\x8f\x11CK\x95\x8f\x06I\xa9(%\x15\xaf=\x96j\x18\xa6\xa3\xce \xa3FRQ\xadn\xe4\xa6\xa1\xe6$\xa1\xa2\x14\xd4\xbc\x04\xd4\xbc\xf4\xd3\xb4\xf9\x10E=\x8d!\x9e\xea\xdb\nF:\x15\xa7\x19\x9br\x8a\x11N\x9d'\x1f\x8cl\x1aK5\x8d\"\x9a\xc6\xd1L\x83$\xd3Y\x14S?\xc1t1\xbd\xf4\x84\xe4\xd2SQKOF,\xcdH+\xc5H\xa5\x8e\xf9\xea'\x94:_r\x90I\xe9\xfc\xf0\x81\x93F\xeaq-\xb8)\xa4\x9e\x97\x9c\xf4Q\xcf;a\xea\xa8\xe7e'm\xd4\xf9N\x0e\xca\xa8\x9f0\xea\xac\xda\x85$\xf0QE\x83\xc20\xc0\x80\x8b$\xba`\xea\x84\xe9\xa1N\xa1\x10\x04h\xb8\xf9\x98\x9eO\x0eARh\xc4\xcbAB\xa8WF\xd8\xaf\x96\x95\n\x1aE\x04\xf5\xd0@\xbd$PoG\xfd\xa8\x94\x13\xd1?\x83\xe4O\xab\xc91\xd01+\xfe\x1c\x11\x04\xb7_N\x8a|\xcfG\x8a\xb9)ey\x01b%\x15uJ\xd4;\x14\xf7\xce\x1d\xf9\xce\x1c\xfb.\xa9\xa8'%g\x1c<*\x12\x9e7\x16\x1e\x11\x0d\xcf\x1e\x0f/\xa9\xa8E\x99\x15?O\x8e\xa0\xe7\x8e\xa1\x97T\xd4z\x89\x8b\xa6g\x8e\xa7\x97T\xd4%\x15uIE]RQ\x87c\xef\x11\x01\xe7\x92\x8a:fpb\xe2\xf1\xe1Q\x88\x8a\xc9\xcf\x8e\xca\x97T\xd4\xb2\xc4D\xe9K*\xea\xf4\x98}IE=;\x9eo7\xb9\xa4\xa2\xce\x15\xeb?E\xb4\x7fN\xbc?2\xe2?+\xe6\x1f\x1f\xf5/\xa9\xa8\x97`\x00\xf2\xa2\x00J*j\x1f\x1e \x0e\x11PRQ\x07P\x023q\x02!\xa4@\x02V\xe0\xa4h\x81\xd3\xe1\x05N\x88\x18\xc8\x8a\x19(\xa9\xa8g\xbcXRQ\x97T\xd4\xe6\x13\x01\xb4A\x08oPRQ/\xc2\x1fD\"\x10J*\xea\xda\x89\xe0*\xa9\xa8\xe5qp\"\xac\xa4\xa2\xfe\xdbLE\x0d\xce\x14\x0c\xbd;\x07CI$V\x12\xa4\xfc\xb5\x13\xa4x0YqiQ\x10\x013 a\xd3\x9c\xe7\xb3\xd1`\xf7uO\x1d\xab\x83\xfd4Y\x17c>p\xb1\xea\x04\xfeDnu\xc2\xb6\\\xb4@D^yl6\xcd\x82\x95\xca\x90\xbcm\x08\xc8YvS\xf5\xf5Fd\xa4\xe7\xed\xb7\x9f\xf3\xd9\x81~+\x90K\xc5m\xaf\xa0\x05\xe7Y\x1f\xa2T\x87\xc3iD\x87\xad\xbes\x85\xc5\x83Mu\x10i/%\x88H\xfe\xb9;\xee\x88\xb0y\x0e]\xbb!}\xcf=^b<\x10yR\x9f\xf2\x9f7\xf7U\xdd\x9caV_\xddlvG\xe1;\xdb\xed\xb4\x87\x99\xa5V\xb1\xfe\x1e7\xa2-\xd2\x10\x91\xadp\x82\xe9\xaa\x11\xd1\xf2\x1cI\xed*\xdcA\x04hW5\xbdp\xad\xed\xab\xcd}\xddX\x81p\xde\x8aum9\x9a\xbc\x9f\xc2\x95)\xce\xfb\xf5|\x19\xe2\xb2\x83nA8\x8e\xf9@\xe3\xbd\x13+\xe8\xd0\x91\x87\x13-\xa0\xfb\xaa\xbfO\x9c\xe4\x0e(\xc5\xa1\xea\xe8\xba't\x8d\xa9\x19U\x02G\xc0P\xeb\x01\xdf\x12'?\xf3\x1a\xcc\x0b\x13\xcc\x12J\x0c\x08\xde\xa1\x82\x98\xe1\x82\xf0\x90\x0d\x1f\xfc\xb2\xeahO\xe8\xef\xf8\xc8aS\x86\x1f\x81\xe8\x1aoR\xd4\x8cD\x9b \xabgb\xc5\xba\x16\x93\x8e-\x7f\xe3Y\xf6\xa7\xcc\xd5\x8f\xd6ef\xc1f\xbfn\xbbv/\x0c\xf7\xc3\x01\xda#=\x1c\xe9\xf8\xb7q\xad\x19R\xb8\xb9w\xb26\x8e\xe0\xeb\xbcr\xab\xc3!\xb3D>\xff\xa4=\x98Y4a\xa7\xa5fC2\x8b\x1d\xbe\xff\xb8}\"j\x94i\x9a\xb6'\xcb\xae\x8d\xf0\xd4?\xd9\xec\xc5\x8a\x9eXw\xc3\xb6*NS\xd7\xa4\xd9\x92n_7T.>\xa1>\xf5\x1d\xf1\xa1\xda\xf5\x04%*\xd9\xb9X\xd1L\xac\x1e\xad\xeb\xd3\xb7!f\x01\x84\xc6(\xc40\x80\xf0\x8e\x10\xda\x0f\xa8\x87m\x00\xa1\xf6\x89\x12\xb6\xceDY\xca)\xb7\xc5[k\x01G\x1f\xcb\x84\xeb\xc3\xb1>\xc4\x8f\x93\xb51\xb8J\xf8\xb1\x98}X\x05c\xd2\x9cx\x8b\x96I\xe0d\xe5\x98^\xe39h\xce[\x1e\xcf\xc8i\x99\x9b\x11\xb6N`\xdb\xf6\xdb7\x11\x96M\xa4|\xb75\x13a\xc7x\xebX\xf6^hsG\x16\x83a\xad4\xda\xe4\xf5\xd9*\x0e+%\x9c\x01\xc7\xd8@}\xeb\x1fi\xed\xa8\x05\"\x97\xff\x10\xabx\x9b\xe0\x96\xf9\xfaN\x99_\xb4Kf\xa9\x84EX\x8a\xd0\x94\x1e\xbf\xeb\x88s\x13Z\x98\xabe\x11\xe9\xe2nB\xb8';\x1e*\xa8\x1a\xa86|\xd7\xb3M\xeb\x0b\n5r\xa4m\xbf4\"\xcc\xd06d\x1cKI\xff\xe2\x04\xc8vSWC\xb0\x86\xc7r\xb4\xa8\x87-\xef\x96I\xb2\xebq\x9cu\x1d\xda`\xf1\\\xb0\xdc\xd4\xa2x\xbf\x9e\x08\x13\xcd|-\xf4\xf5\xce\xdbZG[\xf0\x0f5\xc6\xbb\x9av\xaflL6\xd0\xec\xbb\xed\xc5g\xb3G\xee\xfd\x87\xebw\xaf8\x84X\xc6\xb3\x04\x16\xb7\xe6:\xed\xa2\xa1\xcahV\x145\x1d\xaah \x13\xba\xc5\xae\xa4\xaf\xef\x9aJ$\x15\xea\x98\xe9\xdf\x89Iq\xd7\xde\xb5\x1c\x0f\x18{\x9c\xc0u\xe1\xf40\xf1\xd6u\x90\x98H\x1aON\xbf\xc2f\xcc\xec\x03\x84:4\xe8\xb2\xca\x99\xa1\x9c\x19Nuf0\xc7>\xb8i\xc7e\xcb\xc3$hVC\xac\xd10\xdbR\x18\xf4\xb7ca`l\x80\xc0\xe3k\n\xd2\x08\xe8i\xcbSk\xecv\xc2x\xee\xeb\xe6nGt\x8a\xde\xd8\xae\x890\x84\x9b'\xb4\x99\x94\xa0\xe3MX\xef\xd8\x87{\xd9v[\xd2\x91-\xa7\x05\x16\xb0W\x01{e\x06{y\xd0\xe1Q\xdb\xd4L\xec\x17&j t|\xfe6\x89%\xbd8\xc5\xee\xe8G|yfS\xe8n+\xcf\xd6\xe5\xdb\xb8\xa8\xe7>\xab\x80v\x0f\xeb\xe8\xec\x08\xb0\x10\x06,7\n,3\x0e,\x80\x04K\xc6\x82\xe5E\x83\xc5\xe0\xc1\x12\x10ay1ab\xb6\x06\xef\xa0\xca\x89\x0b\x8b@\x86e\xc7\x86\x05\xd0a\xcb\xf0a\xa8\xa0\xc0]S\x19Pc\x91\xb81\xf4\xcdYX\xb2d4Yn<\x99\x1bQ\x96\x19Sv\nTYf\\Y,\xb2,3\xb6\xcc\x8f.\xcb\x8e/s#\xcc\x84\xe2\x8a\xc2\x98-G\x99\xa1\xc2\xfc\xf7D% \xcd<\xf7C\x05L\x8a\xc0\xbdP1\x16G>\xccY\xe8.\xa8Pk\xb2\"\xcf\xfc\xd8\xb3l\xe8\xb3T\xfc\x99%\x8e:\xef|\xca\x8bA\x93\xcb\x08\xe9P*\x0e-\x02|\x15\xb8\xdf)\n\x8d\xe6\xbe\x84e\x1e\"\xcd-\x07\x89\xf3'\xe3\xd2\xe6\x0cN\x0c6-<\nQ\xf8\xb4\xd9\x085\x1c\x05\x91\x01\xa5\x16\x81S\x0b!\xd5\xc2X5\xef\xa8\xcd\xc1\xab\xc5!\xd6\\\xf71%\xa2\xd6\xa2qkK\x91k\x9e{\x8eb\xd0kY\xf1k\x9e\xb6 31 \xc5fIC\xefY\xca\x88ks\xdf\xaf\x94\x84m\xb3\x9b\x8c\xdd\xab\x94\x1b\xed\x16\xbc; \xbf\xda\x05\xbf3)\x1f\xea-3\xee\xed\x14\xc8\xb79\xd8\xb7H\xf4\xdb,\xfc[<\x02\xcey\x0d\x90\xab\x15\xb1\xb8\xa70\x0en\x16\x12.\x1a\x0b\x87v(7\x1e./\"\xce\x81\x89\xcb\x8d\x8a\xcb\x8d\x8bK\x9f#Q\xd8\xb88t\x9cy\x17\x11~\x0f\x918\x83aw\x10\xe1\xf7\x0fy\xcel\xf8\xbdC\xb1X\xb9H\xb4\\,^.\x0217\x133\x17B\xcd%\xe0\xe6N\x8a\x9c;\x1dv\xee\x84\xe8\xb9\xac\xf89\xd7=B\xce\xb9\xecG\xd1y_t \xe9\x16\x87dg*P\x0cr\x85|\xa8\x11\x83\x8c^c\xe2}\x03\xbd\xb2\x04y\xc3B+\xd3\x13\x00\xcd\x02x\xe4\x08[\xd4\x9e\xa4\x01\xf4q\x84L\xdc\xa8\x08`\x8d\x9dr\xdd\xd7\x05,0\x14\x96\\\x080 \x87'\x92< v\x87:\x97_\xf01\xb9\xd0CJ\x9b@\x87\xd3.\xf3\x98Zg\x11\x0b\xf1\xddx\x8bF\xc4jtNK\xf4\x8baS\xd19 \xbd\x12\xcc\x89\xe7\x9cr\x88\x14l\x9aY\x8fM>s\xd2\\\x9a\xcc\x9f\xd8\x0f0\x1b\xf0\xea\xbb e\xc6\x96\xeeU3\xc1\x8d\xd0T1^\x05\x13\x94\x86)\x17\xafjqHt\xa9\x15\xf4q\xb7JI\x9a\x04\x9a\x1c\x93\x94\x10\x9e\xb2a\x953\xff\x96\x10=\xa5\xadZC\x83}\xbc\xec6\x10\xdf\xdd\x1f\x93\x0c\xb6\x11\x8b i\xfe/\x9a\xf9\x01\x9e\x93cn\x05\xec\x8b\xa87\x9dW\xa39\xde,\xd7\x02\x04\xe5\x9f\xeeZ\x00\xff\x95F\x9eWC\xce\xa7\\\xeaE\x14\x9b\xf9\x14\xa7\xd8\xe6\xd9.\x9a\x10\xff\xb5di6\x0c\xb6jT\xc7\xbe\x8a\xf1\x1d\xbef\xac\xac\xa8\xbf\xbf\x15\x05\xa1{\x01\xd2\xce+\xb3\xb6\xf3\x89(\xdfu_\x19\xb6\xf6\xa9\xbc\xf0\x15Wa\xf3%\xb6\xab\x8e\x0b\xbd\x8c\xab\xbc\xd2/\xf1Z`\xbc T\xb7h\xdbe\xa9K#\xe6\xe9\xaf\xa2\x1f\xff\x1e\x9c\x13\xf3\x9e\x9f\xc92\x8e\xa3:\xcfvO\x0c\x1e\xd5Tb\xb3\xdc\xd1\x85\xb0\xf9,\xe6\xf85\xf3\x9f\xdf\xfb\x10~\x06\x9f;\xd9fM\x84;b\xf0\xe6F\x7f 7\x0f\x16\x19\x027\xf7\x15\xd5;\xb8\xd6\xa1(\xd3\xd5\xb9|\xfd\xc6BF^\xab\x9b\xd1\x9a\x8f\xcb\x9a\x8d\xc5\xea\xe4\xafb@\xdeH\xe6j.\xce\xaa\x9f\xad\xba\x88\xa7\xba\x98\xa1\xca\xfbk\x12+\x9d\xdc\xd4\xc5\xacTa\x92\x18\xd2\x1c|\xd4\x14&*g\x9d\x9a\xbdA\xc0\xd2K\xd8\xa7n\xa6i\"\xc74\x8a]\x1a\xcf$M\xe0\x90&\xb0G\x11\x85\x91\x91#\x9a\x97\x1d\x9a\x8d\x17\x1af\x84f\xe3\x82\xbaX\xa0)\xfcO\x94\xebIcX\x9eK\xf9\x9dN.\xe7B\x16'\xc2\xdftn\x94\xce(\xbd\x7f\x07]\xc8\xd3\x1c9\x99\xd8\xf8\xfe*\\w\x1a+S\xb005q6\x1f3\x03\x133\x8d\x83i\xccrs3L\xe4]\xca\x81\xd6%\xa60,\xbd\xf4A\x07\xab2\xc8\xa7\xb4\xa9U\xf1\x1cJ\xfb\xdd\xbf`}]\xc4\x98\x8c\xe9l\x88%\xe9\xee[\x90\x199\x83\x139\xa5\x8f$\xf2 \xbd\x0cH7\xf7\xd1\xc7zDG!\x96\xe9\x18\xe28\x9a\xec\xc6\x04^c\x04\xa3q>\x97\x11a\x0e\x86\xf8\x8b\x99\x98\x8bH\xcd\x93\x99\x92\xc4S4y\x89)\x8cD\x84\x81\x98\xc4=4\xb9\x869Y\x86N~\xa1I\xba29\x85y\xd8\x84\xd9x\x84y\x19\x84q\xdc\xc1 kP\x9e\x92C|A\xf9\x98\x97)hQ\xea\xec\xdab9_~^`$#0\x82\x0b8irN\xfe_\x12\xf3\xcff\xfa\xe5\xe3\xf8\xe5c\xf7-\xff\xbaAF_\x88\xcb\xa7\xd4\xb7\xc9\xdf\x136\xf8\x94\xb9gr\xf6P;\xdd\xe4\xe9\xc50\xf4\x82\xdc\xbc0+\xcf\xcb\xc7\x8bf\xe2\xb99x\x8b\xd8w'\xe2\xdd\x9d\x82qw\x12\xae]&\x96\x9d\xc9\xafC\xe6\xdd\x18\xa629u\xe8\xc3\x08\x8f\x8e\xc6\xbbwQ\xd6\x9c\xe3\xd0\x8a3\xe5\x1c\x0f\xa3\xec8\xc7\xb3~F\x9c\xe3%\x94\x05\x87>\x9b\xca|ss\xde\xd0\xea\xb0\xf8\x87\x8b\xe1\xe6\x15`\x86?0>\xdb\x8cO\xedg\xaf\xa1\x82\xdc\xc2\xc0\xc9Us|.\xf0\xf2\xd3\x02/y9i\xcew\xfd\x9e\x94\xe5\x0c4\xee\x1e2\xa4\xf9\xb8g\x0e\xd6\x99\x93o\xe6\xec\x90;\xe2z\x02v\x99\x97Wf5\x11\x1f\xeb\x9c,\xb2t\xfe\x98\xf2\x12K\x81cH%\x953f\xf0\xc4\x12\x19b#\xd5J\xca\x1b\xb9a\xc9\xac0\xc9\x84\x91\xe2F>XF&\x98\xc1\x01\xcb\xc9\xfe\n\xf0\xbed\x94\x955~U\xddl\xea!\xce\xfa\xfa\xcd\xf9\xc5O\xc2\x9a\xfd\xb1\xbd\x8b\x0e\xb6\xee\xfb\xbbu\xddl\xc9\xa39\xef\xeb\x86\x92;2\x02t0\x8d\xbfS\x15\x01\xbe\xa2\xc9\x03i\xe8\x89\xf1\"\xfc\xf1\xc9_<\xca\xa5\xa2\xb4\xabo\x8e\x08\xad\x19k\x9a(\xf9\xef\x03@R4\x8b\xe2\xd9!\xc0\x97:1\xf0f\x08\xdc\x06\xf0Z\x8d\x8bn\xdb\x0e\x83\x05_\xba\xeap`*\xec\x9et\xc29\xf2\x99\x8ek\x80\x0b\x91p\x08\xefw\xf9\xc8-\xa3\xe8\xcf\xb2\xadh\x15\xd9\xf7I|\xd3\xadm\xdfV\xb4\xe2\xa8\x84\xe6\x89K\x87\x8e\xd0c\xd7\x90\xad\xc0\xb4+_\x14\x8f\xde7\xdb\x1d\xe9\xb4\x85\x0e\x17\x14~\xfatu\xad\x89\x9b\x86tw\xa4\xb9\xa3\xf7p\xe8\xc8m\xfd\xc8C\xfd\xc0\xa1s\x1c\xa4J\x98A\xcc\x96\x04\xabUT&\xcc\x0c\x82\xe4\x94\x1d*\x1d\x94[h\x9f7:\xcd\xd4\xcd\x14\xfb\xdf\xdeA\xdd\x88\xd1b_,\xdc])\xb8\x18\x10Y\x0d\x08OD^\x94\xa5\x16\x06\x84E\x1bF\xa6^\x84h,\xeb\x18DY/|\x13\x1d\xf5~\xdd\x8f\x90\xd2\xcf\xe4\xe9\xe5\xb8\xa7\x9fA\xd5\xf7\xed\xa6\xae\xc6\xd3\x03\x96\x83\x9d\xcf:\xa79b4A\xec\xe0\\\x99\xf6P\x8dX\x1e\xd8\x92\x07\xb2c_\x91\x9f\xa8+J\xab\xcd\xbd\x1e\x08\xd1\x16\xc4t>\x1a\xa1B\x05h\x7fC\xee\xea\xe6\xcd\xae\xdd|>\x1b\xfe\xf6\xae\xd9\x1a\x7f9\xbf'\x9b\xcf\xd7\x8flGC\xa5\xbc%\xbb\xfa\x81t\xd7\x8fF(\xf6\xc7\x8a\x12v\xd8\xea\xaa\xa6\xafd\xe4\x7f_=\xb1\xa3\x8b\xca\x1dqdc\xca\xd6sO\xe4\xc2\x8c\x01U$\x1b?\x9a,\xa5\xab\xb4?\xb9\xb5\xc7\xa4IB\xf7\xab\x0d\xe8\xd8\xc83\xad\x1a\x95\xef\xf9\x97\xe0f\x801\x90\xde\x1dE3E\xa3\xb7\x95\xa9\xbaAV\x15\xa6bN\xa1\xf7\x9c\x17\xc5 k\x1c\xd5\x0b\x8e\xa7}\xb6{6\xe3L\x94\x90\x89\xe6jL\xc6#D\xf2\xe1\xc19\xb9\xae\x1fg\x13W\x17\xbbn\x87\xdc\x1d\xd7\xf7\x04n\x98F\x91\xb2\xd4\xa4}\xbc\xaf\xfa\xfb96\x00\x13\xa4)\x13`\xef\xaf\x861\xdb\x92\xfeP\x05\xc0\xedC\x9b\xdeW{\xf18\xa8\x83\x9a>\x17\x9b\xfc\x17\xfeW\x8e\x0c\xdf\xd6\x13\xa7\xf94\xdf2\xdf\x10U\x1b\x07n\x98\xc4\xc8\xb6t \xa1\xc9\x1a\x7f\xacz\xca\x91\\T\xaf\\\x93\xf7\xddw\xf0\xeb3\xbd\x02\xde\xa2;\xd2\x90\xbe\xeeyM\xbe\x10\xf8\xe8B\x0b\xd9\xebC\x82E\xfa(\x82dlM\x98iz\xae\xc7\xad\x87Vw\xbdv\xf6\x11V\x81\"\x98\xf0pW/\xa0\xe9[\xb2i%4Vz\xfa6\xdd\xd3\x81\xb6+\x1e\x80\xeb\xeb1Q\xc29\xd3K\x1b\xfa\xa6\xa6\xaf\xd9a>\xda\xe9G\x1eiW\xadoj\xda\xafy\x1a\x0e\xcb\xd0\x8dq\x87\x91\xdd\xc4K\xe0\xb5\x90\x87\xe5\x80\xfb\xaa\x8c~\x88\x80\xa7\xb9HE\x96\x10\xee\xd4\x1br'\xc3MM\x85#c\x1c\xf0\x9aC\xb5\x8e2A3i\xfacG\x06k\x03H\xc3\x07W|1Z}&\xbd\xb8\x03\x99\x9d>\xf6:\xc6N\xca\x13\x15\n\xfa\x0e_\x8aB\x82\x06\x83V52EH\xef;v\x9a\xed\xab[\xa5#\xc5\xdf\xd9xr\xe0\x16\xc7C\xb6\x8d\xd4\xc8p\x14l\xcd\xe1C\xd3\xc7U_\xdf5z2\x8c\xab\xfa\xae\xf9i\xf0XZ\xa3\xacc\xf1_\xc2\xd5\xc5\x0f\xef\xd7?}x\xfb\x0e\x81\xbe\xeb\xbf\xbe\xbd\xf8\xf8\xee\xfc\x1a\xf9\xe1\xfa\xdd\xff{\xfd\xe9\xf5\x8f\xc8/?\xbe\xfb\xe1\xf5\xf9\x1f\xd6\xaf\x7f\xbax\xffa\xcd \x1c\xe2{J\xd8\xbd\xbbf\x87?]vk4\xa2E\x08\x8ew\x1e\xf6\xec\x17\xa1\xa9i\x0f\xed\x97f\xc0B\xc3\xdd\xb1\xea\xd8\xa9\x90\x1d|\xd4A2oZ\x91g\x930KW`\xb1\xf9jn\xb7\"\x92\xbam\xb9S\xb4\xbek*\xb9$T\x11zJ\x1c\xe5&!\xf6\xdba6\xc9\xe9R\xf7\n\xd6LzZ\xef9\x9c\xe2\xa1fjq/\x01\xe3\x8b\xfcXb\xbb\xc6\x8c\xf3\xd3\xe6\xa2\xdd\x92\xa6E\xee\xaa\x0b\x84\x1c\xb0\xd6\x06_\x0b\xb9\xbf\xcf\xdbZ\xa7\xecp&\xd5\x88so\xda\xbdJ\xc5\xce>e\xd5\xc8F`w[\xbf\xffp\xfdN8\x1b\xa5\x15$\x88\xb7\xc2\x1a\xbbh\xa8JY\xa8\xec2\x9dUi \x93\xb7/X\x7f\x1f\xa6Q?\xae\xff\x9b'\xb8k\xefZn_M\xdd\x052\x9e+\xdbc\x81\x01\x05\xf2^]\xcaQs\xa0|\xc5\xd6\x81&\xe4\xae\xea\xd7|Q\xce<\xc2\xcd\xb8Vc\xa8\xc2DP\xdeU2\xea \xe7>\xb7J\xd9\xfe2\xaa\x05{\xd2mH\xdf\xd76]\xe6\x86\xfb$\xd8\xa7h\x8f\x83G\x99{X\xa0\xddl\x8e\x9d\xaeK\x0e\xd5S$y-4\xbf\xea[86\xfc>\x0fjk/\x95\x9a\xb2V\x89+\x0f\xd5\x93\xd2\x1e\xb7\xccB\x83\x0b\xf3\x16\x91A\xd4x\x1b~\xb5\xe1\xd7\x89\x88\xdd\xe1P=\x8d\xafc~U\xde5\xf1,?0\xd3G\xd5\x9e\x17BG\x1e{\xe1\n\xe2\x7f\xddJ\xb7\x88\x98\xc8\xe6`\xab}\xfc\x1b\xab\xa6\x9eP\xa9\x07\x87\xb7\xb7-\xe9\xe1\x1f\x9b\x96\xfe\xa3\xf4\xc4\x08}\xcc69\xce^\xb9\x1d\xe6\xb3)K\xedn\xc8\x9e\xa0\xcfSn\xd6\xc6~5\xd7T\xaco\xc7!f\xfb\x81\x18\xae\x17\xa4\x96N\x14\xe3\x1b\xca& w\x1e\xea\x91\x17\x02\xf8\x10|\xa3\x82\x10*\x90\xc7k\xe0\xed\x1e\xe8_\xe6\x17k\xf9\x17e_S\x8f\xf5MZ\xf7\\X\xf823!\x9b36\xc6\xae:0m\xdc\xd5\x15%Z\xa5\xfc\x93\xb0\xf3\x15y\xe4\xa9\xa2Eg6\xf7\x15\xd3\x88\xad\x1d\x9ad\x8f\xaa\x9c7\x83\x94\xfeL|en\x06\xdeV\xf5\x8e\xbf\x84\x9fZ\xd4\x84\x91?\xablhV\x7f\xf9_\xf5m\xf8q\xec\x80v\xecS\xe8\x00\x91\xe1\x17\xbeT\xec|;&5\xe6\xea\xe1Qnh\x9c\x9c\xc8Q\x8d\"\x9b0w\x7f9\x9b\xc5\xbe\x88\xd5*\xf6\xc7\xe4FU\xa0\x10\xa2#\x80~\xb8\x8c\xa9mvO\xeeF\xbdF[\xf5zQ\xb3\x04\xf2}`)\xee\xb9[\x91\x12Q\xbdg\xfd\\?\xca[\xab\xa2Ok\xf4q\xcd\x8f\xdbs\x9d[`\xces%H\x99\x05\xec \x8fh\xff=\x02H3\xeaBR.\x84V;\xfa\x98\xbe\xe2\xd1\x07\xb4U\x8f\xfe\xfez\xf2@\xec\xea\x07\xaf\x9d\x91G\x0bh\x02?^\x9e[\x9a\x00\xed\xcdlm\x80J9\xa5F\x80YZ\x01m\xde\xe94\x03\xcc\xd2\x0eh\xe3N\xa7!\xc0\xd6\x12\xaem\xdd\xd6\x15\xc3\x8aU\xa8\x0b\xfd\xce9k\xea\x0d\xafIy\xfa\xfc\x0b\xea\xa6\x99\x80]\xfa\xb8\xee&\xefX\xdd\xd2\x9eP\xddPx\xfc\xb1\xbee\xb0\x91,\xd72\x85\x90\xc3\xfc \x03=\x0c\xd1'\x18\x1f\x8a\x18p$\xb1Wx\x0c\xa2\x18,T\xf1(\x12\xc3\xa8\xbaG&\x8c0\xe6OMP\xc6\x10=6~\xb41`\x88\xe3x\xe1\xd6\xfd\x99\xb1\x104?\xfa\x18|X4\xb0P\xc8\xf0\x95\x1c@Nd2x\xbf\xbc(\xee\xef\x0f8J\x19\xfc.\"\x17Z\x19<\x83!\x8a\x07\xea\xeb\x19\x18Q\xc20_.\xc2\xf1[\xa0C\xa2\x84\x90\xcc\x10\xec\xa0(^D3\xc4tV\x94p\x97E \xa0\x9b!\xae\xf7\xa2\x04Q\xce\x10/-\xe4K\xd4\xcb\x12\xc4\xb3W\xe0\x94\x94\xe3}t\x0e8z\xca\xf1\xb8\xcf5\xb9\x181\xa5\x0bI\x01K)p\x94./\x1e\x17\x95\x88\x89B\xf0P\xe8\x18:pP\x18\xf0$\x13\xfe \xc7>\xc5\xe2\x9e\x0c\xcc\x13\xda'\xb7\x06J\xc69q\xd8\x8d\xbe\x14\x16`\x9chF|\x13\x8emJ\xc25)$\x93&\xcf\x83i\xb2\xf0L\xe8\x17\xc1\xa6SV\x0c\xd3r\xfc\xd2b\xec\x92\x8eV\xd2\xc7j\x11ni)fi\x18Q\x8eSn6\xbb\xe3\x96\xe0\xaa\x82+\x89\xba\x11\x1dU8c\xb9\x82\x7f5*\x0d-\xc9\xb7\xccll\xa3\x9b\xf9\xc9\x17\xf8\xa9\x83\xebAr{K6\xb4\x1e\xec\x8agwU\x7f\xe8\xea\x0dy6\xec\x97BM\x0e\xf3]\xd0\xda\xda=\x81}\xbd\xaf\x9b\xe3^V\xab\xce\xb8\xe39uO\xf6\x87\xb6\xdd\xe1;\xdd\x0fdYlu\x9c\xad\x91\xb8\xfb\xebG\x07\xde\x9e>\x9a\xc1W\x94\xf1_\x82\xb9%\x98[\x82\xb9C)\xc1\xdc\x12\xcc-\xc1\xdc8ia'\xc0XJ0\xb7\x04sK07f\x03\xa3%\x98[\x82\xb9\xbeM\xa4\x04sK0\xb7\x04sK0\xd7,%\x98[\x82\xb9%\x98[\x82\xb9%\x98\xfb\xf7\x19\xcc\x9d\xb8\x9c\xbd\xd1\xdb!n\xcb_\xf1Fl\xf9\x13=?\xd1-\xf0f[\x0c\xc6<\xb9f<>\xef\x81\xea\xb8\xabEN\x11\xc4\xf9\xdd#\xde\xef\xb9-uX\xe7.\xdb\x1csu{\x97\xac\xcf\xa9\x17vx\xe3.oo\x85\xb3\xdc\xdeN\xc7\xb7\xb7\x8aX\xe77\xe6\xfe\xf6\xbbA}\xa3\x15\xe7\x04\xc7\xdc\xe0\xf1\xe3\x15v\x85;\x9c\xe1\xf1UX\x0e\xf1x\x8fB\xd8%\x1ep,`nq\x9f\xab4\xffU\x04^\x07y\xd8E\x1er\x92;\xdd\xe4A_\xa8\xdbU\x1e\xf6%\x7f\x8dk\x0e\xa8\xd7i\x1e\xec\x9e(1\x8e\xf3pwE :\xcf\xa3\xba.J\xcc\x00\x88\x12\xe1B\x8f\x1c\x0bQ\xa2\xdc\xe83$\x86M0\xbd\xccu\xa6\x87\x07g\x8e;}\x89C=\xbe\x87\x8b\x9c\xea\xee\xe9?\xbd\xff\xc8\xf9\\^\xc7\xba\xc7\xb5\x1e;\x10\x99\xdd\xeb\x11\x0ev\x8f\x8b=\xa6\xd1 nv\x874\xb7\xa3=\xdc\x9e\xd8\xad\x91\xfa\x9c\xed\xc1]\xd1v\xb8\xc7\xef\xe7)Nw\xb7\xdb}\xb1M\x99\xea|w\xb9\xdfO\xd1\xa0\x08'\xbc\xed\x86_\xee\x88\xf7nH\xbe-\x88:\xdd\xf1\xc1\x9d!4\xbf!\xbfS>\xe4\x96\xcf\xed\x98\xcf\xec\x9a\x0f8\xe7\x93\xdd\xf3y\x1d\xf41.\xfa\x04'}^7}\x94\xa3>\xaf\xab>\xc2Y\x9f\xdd]\x1fp\xd8/s\xd9\xa3\x82\xbcn\xfc,\x8e\xfcHW>\xfa\xe6,\xf7~\xb2\x83?\xb7\x8b\xdf\xed\xe4\xcf\xec\xe6?\x85\xa3?\xb3\xab?\xd6\xd9\x9f\xd9\xdd\xefw\xf8gw\xf9\xbb\x9d\xfe3\xdc\xfe\xcb\x1d\xff\xa80\xd7\x0d \xa2$8\xff=G\xcf\x80I\xe1\x0d\x01\xc4Y\x1c\xf9\xc2\x00\xbe@\x803\x14\x10o\\c'\x82\x9c\x01\x01OH sP\xc0\x1f\x16p\x06\x06D\xf1\x8dI\xda=#\x13Q\xc3\x9d#\xfam#\xa2,\xb9s\x04i\xbb\xee\xa8w9\xf8\x114\xfa\xa1\xba\x93L\xaaW\xb8\xdc\xf1\x01\xdd\x93\xa2\xfduL@/D\x8f\xedC\xcf\x04\xf8i\xa0!\x8ftmy\xa0\x9cs\xd9\xb9P\xa5\xff\xdc\xf2\x04+\xf9jd\xd8\x7f*\xfaU/s\xbf^VwD\xe6\x88[\x89\xdf\x0d!l\x18\x05\xa9\x82\x89cc@`\xdf\xf6t\xbc\xebd\xa7\xef\x83\xb4\xa5U\xec\xe5}\x0b\x12Zs\xf1\xbc?\xfc?D~\x7f\xeet\x91\x16\x80\xb6\x0d\x99\x19\x9e\xf5\xaer\xd2\xd3\x9a\x0b1\xd7\xce\x97\xaa\x17,\x9f\x9a\xf6\xca\x88\xe9\xe1\xd8\x88\x89\xb0\x15\xfb\xc0\x97\xba\x17\xdf\x00\xf7\xc5#\xd1\xb1\xb8\xc0\xdb\xf5c\xff\xe6I\xf8x\xa4\xa8P\xca\xbe\x9f\xda-\x99y\xe5Cs\xb7\xd3\xd3z\x8a\xa1\x16\x7f6o=\xe1\x7f\x13t\xa6%3|o\xd3\x15Dm\xadFhT\xd3\xd3\xbdC\x0d\x8e\x8a!\x81q\x05\x81H\xaeb\xdc\xe9WQ\xa8vl\xba>\xc94\x1bu\x03=\xad\xa8\xc8\xd2\xa1%{\x91k\xac\xe3a*\x15\xf1\x1a%\x0d\xd9O\xfe\xbf\xc9\xbe/\xaf\xe5\xdbn;\xd2\xab\xbb\x9d\xea\x1e\x0em\xcf?\n\x9f12l2\xed\xda\"\x1f\x16\x1e\xcbv\xda\\\xfe#m\xc6\xc8\xb5;f\x9d/Z\x9d-N\xed\x8cP\xd3\xe5\xb1\xe9\\Qi\x7f\x99f/\xab\xeb'Q\x7f'm\x0f/w\xe4\x81(t\x99\xcf\xd9y%.d&\xf3/\xcd\x9b=_#r\xa7\xe9\xd8P~\x85\xa6h\x9c\x7f\xb4&\x1d\x80\x98\x9b\xbc\xd4;RD(\x188V1\x93\x92wW\xf5\xc6\xd2\x9e\xf4A\xfd\xac\xda\xac!\x93\x99\x029R\x8e\xbf\x1d\x92h\xf2\x05\x9at}\xf6\xe2\xf4!H,\xd9\xaf1\x7f\xa8\xfa\x7f\xe5\x15\x81\x91\"\xf4\xd8pO\xcf-|i\xbb\xcf\xf0E\x1a\x17bw\xe4\x97\xde\x19\x82\x0e\xa4c\x8dX\x19\xbdX\x90y$\xd4\x87\x1f\xaa\xfeS?6\xb8\x9a\x80\xa0\xab\x0d\x15\xa6\xb4BC\xab\x06 \x1b\xc8\xf1\x81\xc5\x8fZ\x8c\x9a\xfdk\xd0\xb5I\x9frF\x1a\xb9\x85\x9b\xde\xdb\x8aV\xc2\x1d\xff$\xbc\xe5\xe2\xbe=fJt<\xa7\xad0\x90\xb9i\xd7lw\xa4\xd3\x18\x0dpa\x1e\xc6~\xfatu\x8d\xec\xf9;\xd2\xdc\xd1{\xa6$o\xebG1\xcfy*R\xbe\xfa\xc9\xa1\xea*JD\xed\xa2R\xb6\xc7\x1cv\xc4\xf0\x93\xa824`b ,\xcc\x89g\x0d\xc8\x8f\xed\xdd\xc8\x10\xa1\nQ\xa3\xadY\xc7\xb8\xb8\x1a\xa9\xb7\x11#\xb6a~~\xc8\x9c\n\x8f\xbff\xfd\xd53D\x10$\xa8\xb9\x9a-\xcai\x93\xd6y\x89g\xde>\xa9\x12\xc0\xedA\x98\x8d\x96\xab\x1a\x0f\x01\x13\x86jn\xdavG\xac\xeb\xb3E a\xf4D\xe1\xb0\x98\x91\xe2Vk\x08\x95\xcf\xe4\xe9\xe5H\xcf:c\x87\xd7vSWT\x9a\xe9\x0e\x81\xec`\xc9d\xce%\x11 \xa2\x15\xdf\x0ez\x9d?\x04[f\xca\xb0/\xcf\x8fa\xdc\x80\xba\xd7\xbc\xa1\x96 }INm1Q\xd46\xfe\x86\x9d\x81\xde\xec\xda\xcd\xe7\xb3\xe1o\xef\x9a\xad\xf1\x17u\xdd\xa9 \xc3\xd3%\xbd%\xbb\xfa\x81t\xd7\x8f\x08:\xfc\xc7\x8a\x92\xeeljQ\xee\x05\xebHa\xe9\x8e\xbd\xcc.\xdd\x13\xa9\x08V3\xd4\xd2r\xee\x9ad\xa9\x19\xf2\x94j5\xfe\x8c\xeay\xfeL\xc8.\x8b@j\xa9w\x0c\xfb,d\x98]?F\x9bb7\xed\x16\x89\xcc\xb7\xdb\xd1\x19-\xb2\x91\xf3\xd37\xf7e\x8dnF,}\xf9\x8c\xadZ\x0e\xe8_I\xbb\x17JT\xa1D\xa1\xd2\n%\xaaP\xa2\n%\n\xd2\\\xde\xae\x85\xeehj6g\xb8(y]\xe2\xa2ds\x8c\x8b\x12v\x8f\x8b\x92\xcdI.J\xa1D\x15J\x14\xd0\xc5\x94\xa8pk~~\xdd<\xfd\xac\x19\xdd\x0dT\xddMM;\xb6\xf8<\xad\xc2\xfd\x16\x00\xd5\xae\x95\xb1\x18\xa8\xecO\xc6\xb4&W\xfaS\x7f\xb0fN\xe9u*\xab\x08\x99f\x97j\xe2\xef\xea\x1b\xdeT\xa9\xd7\xfb\xc1\x99\xcfoA\xd9|\xfe\xf6\xd8\xb0\xffc\xfb\xa5\xf8\xde\xfd\xf4\xba\x19Q\xb8E\x83\x1a\x0f\xed-\x1c\xa9P>j9\xf70\x05\xb1\xdc\x91\x86t\xfc0)L\xfc\x011\xf8\x1a\xd1w\xe2\x13\xd9\xf5\xbc{\xac\xd8\x04\x86_\xbf\x82K\xd6^\xb6\x8ee\xd3\x070\x0d\xd3\x13\xe7\xff\xf4O\x8em\xea\xfb\xb6\x85\xdb\xb6\x85\xef`\xb5Z\xfd\xdf\xe8#l\x10\xaa\xe6 \xff\xb1j\x9eV\xac\xea\xef\xbbv\xff\xe2\xb6m\xbf\xc1\x1f[\xad\xf0\xbd\xa7\xbe\x85\x17L\xc4'\xde\xe8\xeb\xf6\xc5?0\x19\xdf\xc0\x7f8\xf4\xa9K\xce_\xdcc\xf3\x9b\xc0\xd8\xfcK\xf5P%\x0f\x0e|\xc7m+&=a\x14\xea\xfe\xc5\xf7m\xbb\xda\xec\xaa\xbe\xf7\x0c\x82h\x12{A\xf4G{ \xaf\x17\x19\x9dax\xfe90<\x97O\xf4\x9e\x1duQ\xc1\xa2%\xdf\xb7\xed\x8b\xd5j\x85k\xe2ap^8\x7f\xe7\x13\x88\x0f\xdb\xdcQc/_\x88A{\xfb\xee\xea\xfc\xe3\xc5\xe5\xf5\x87\x8f\xdf\xb8\xbcF\xe3DsW&\xaas\x0f\xd7\x7f\x0b\x0c\xd7\x0f\x88\xc7\x85\x176T\xaf\xbe\x83\x7f8\xdc\xac\xbeo\xdb\xffX\xadV\x7f\xc1\x1f\xac\x9a\xa73f\xae\xb1\xa7\x0f\xc2\x00\xf9\xa9\xea\xfa\xfbj\xc7\x06\xd1\xddp\xd70\x995;\xaa\xado\x8dJ?5\xfb\xb1Z\xde(>\xb1\xf9S\xff\xe5;h\xea\x9ds\x82\xba\xdb\x82\xcc\xc4k~\x0d\xd8\xe6\xf3\xa0\x07\x95\xb1\x0d7O\xa3\xa9\xa24\xb6\x80%>)d\xae%\xed\xd8#{\xfes\xc4\x0c\xf9\x96\x9dEW\xfc\x07f\xca=\x87J\xdbU\xd8\x8e#\x89\xa3v\x0d\xfc\xab\xdb\x95\x0cj\xbc\xd9=\xa9s\x93u\xe0\x1dLG \xa2\xa7\xf2\xbcm7\xf9\xdb\xe7v\x15\xf2@\xa7\x9a(NpD\xce\xccg\xb7m\xbb\xba\xa9:\xde\xb9\xc7o\x9fV\x7f~&FK\x9c5\xf0c\x15o\xca3\xf6,\xdb^\xac\x9f9\x18\xda\xfa\xebw\xdf}\xf7\x1d\xfe\x1d9z\xd4\xc4\xc8\xf2K\xc2\x84\xc1 \xce*\x1c\x04,\x9caw\xc7]\xd5\xd9\xb2l\x11\xec\xf1-\x19\xb7\xf93 \xfb\x1b\xb2\xdd\x8e\x1b\xfe\x99\xb4\x1f\x10\xef\x81\x89\x1d\x85\x9f\xff\x07\x1b\x8e\x9f\x07(\xbe\x16\xd5P\x83\xbbRK\xfe\x95\xc3\x88\xae6\x9f\xd9\x9a\x1f\x0fk\xb7\xf5\x8e\xe0\xfaW\xe9\x87K\xd2\xf5m\xe3\\6\xd2\x83\xc3\xaf{[\xf3/\xf3\x1d\xfc\x1a\x978<\xcc&\x8fz\xf67\xf1\xda\x1f\xc0\xd9\x8ag|l\x9e\xbd\x82g\xd8\xaa\x99vw%z\xf4\xec\xcc%\x8b\xf7\xe5}\xb5g\xf2\xfe\xbbh\xf2o\x9d\x0f\xb3\xbe\x18\xcf\xc6v\xe8\xe2V\x1e\x0c\xa6sB|\xcd\xba\x87/d\xb7{)\xd0\xefl]\xdfs\xb4\xb1\xbc\x9e\x12\x9f\xe4\xd3)x&\x0cPc^*\x8c\xf4P-\x9bh\xcd\x1dr\xae\xe7\xd3\xce\xae\xe4g\xbe \xd4<\xbcow[\xc9/\x19[\xc6=Xr\xfe\x82\xf4\x16\xc9\xe9k\xcb\xe3\xd5\x0c3\x17^0\xfd\xa0\x86\xc2r+(\xcf\xd9\x1f\xff\xed\x8f\xdf8&y\xea\x1c\x99V\xe4\x9e&|\x18\x98\xb8_\xaf~\xf3\xeb\xdf\xf4\xcf\x1c\x9f]\xff\x97\xff\x84\xa2\x9c\xce\"\xa0\xa3\xd8\xfb\xc3_\x85/@8\xf2\xc9v5$\xe8\xaa;\xcb10\xf2y\xcc!\xa2\xf7mOF\x99\x82\xca\xcd\xbf\x8f\xc4\xd4\xb0\x99&\xc2\xb9\xed-'\x91\xf1H\x85u\x90PwW>\xb7R\x06\x8a\xba%\xf5\x88I\xbb~|.\x009\xe2\xee\xd4\x15\xbc\xab6\xf7\xe6\x8d\x95\x03L\xdbb\xa4V|\x92\xdaA!:d8`{\x17\x1d\xae\x9c\xa4\xf5\x9e@M\xe5\xcd\xa3\xf6\x01\xe4\x0d\x07\x04<\x90F-\x11\xf5\xa2\xd9\xa2\x17\xca\xf7\xc9c\xc4\xc3s\xf8G\xb3\\$\xfcJ\xd2[\xd2u\xc2#U\xa9\x88E\xbd\xe7\xc7\xcd\x11\xb5u\xa8\x9e\xc4o\xb7\xc4\x8c\xad\xa8\xf2\xe5\xbe\xddY\xfb\xa0#\xaf\xdb\x9e\xecc\xaf\xb8Ql(\xb2o\x15h`<\x10\xf3\xbf\xca\x8b\x1d\xe5\x17\x00W`E\xe4#i\x8ft\xbd\xe8\xc2Bw\xd6\x03+\x91\x83\xacG\x05\x80\xf4\xe4\xce\xd28\x11ZI`S4d\x12\xd7zMk~\xbd\x9b!\x884^\x99\xc9/\xf9\xd4\x9e#\x8f\x944}\xdd6k\xe1\x0d.A\xa1\x12\x14*A\xa1\x12\x14*A\xa1\x12\x14*A!\xb3\x94\xa0P \n\x85-\x8e\x12\x14*A\xa1I)A!YJP\xa8\x04\x85JP(\xaa\xe6\x12\x14*A\xa1\xa1\x94\xa0P \n\x19%\xd6\xe1_\x82B%(\x14\x9a#'\x0c\n\xb92\xfcZ~g\xe1\xd0\x18N'\xea\xaf\xfc{n\xaaft\xd5\xdf\x98v7wi[\x91\x9a/\xf7\xa4\x91\xea\x88oA\xa0\xd7\xc3\x8e\xcf\xfdQe\xee\xe3 y\x98\x01$\x14X/.\xc1\x9a\x8as\xf8L\xd9,\xddT\xcds~\xde\x13t\x94\xad\x08\xbbX\xfey\x9e\xb9\xc9\xca\xe1\xd5\xb4\xcdz\xd3\xd5\xb4\xdeT\xbbuq\xc6\x17g\xfc\xa4\x14g|q\xc6\x17g|q\xc6\x17g\x97\xac\xf1&_\xac)g\x9c)c\x8c\xc9\x13_J\x8a-\xe5\x8b+\x85bJ\x0b\xe3I\x8bcI\xc2\x7f\x8d\x8c\x963\x8e\xb48\x86\x84^@\xe1\xbc\x82\"-v\x04\xc7\x83%\xcf\x157Z\x123\xf2\xc5\x87\x92cCQq\xa191\xa0\xa4\xf8OB\xec\x07U+Yc<\xb9\xe3;\x19c;1q\x9d\x8c1\x1dw<'k,\x07\x8f\xe3 &>\xa6\xa5\x96\xc6oD\xac\xc6\x12\x87\xc5n\x16\xc7m\xd0\x98\x8dg+\xf6\xc4jB\xbbt\xae\x18\x8d;>\xe3kAZ\\F\xc4a&\x02\xb1\x98L\x96xLZ,\xc6Z%\xf6\x86\x9b3\x06C\x91\xf8KZ\xec%\x10Zp\xc6\\\"\xe2-\x98\xf3uN\x9c\x05{\xff/x\xdf\x17\xc6V\xe2:\x1f\x8e\xa9\xf8z\x1a\x11K\x99\x15G1\x9dN\xc9\xf1\x93@\xec\xc4\x177\xf1\xc7L\x1c\xa3\x12\x1f+ \xc7I\xec\x18IR|$*6\xb2$.\x82\xc6!\xc2\xf1\x90l\xb1\x10\xb4~c&%\xc5?\xecxGJ\xac\x03\x8dm$\xc55\xec8F\xde\x18\x86'~a\xbbu\xed\xb8E\xae\x98E\xc6xE\xeeXEl\x9c\"\"F\x11\x1d\x9f\x88\x8bM n|\xac\xd6X_s(\x1e\x11\x1d\x8b\x88\x8aC\x18\x8d\xcf\x1b\x7fH\x8a=`\xb1\x86\x9cq\x86\x9c1\x86\x94\xef\x1d\x11[\x08\xc7\x15F\xe5\xef\xb6\xaa\x95\xc3pA\xb6'G~\xa7\xc5\xb9\x9d\x1c\xd9\x9crfr\xc2\xb28\xd1\x05\x19\x9c2fo\x92\x0359b'em\xb2\xf34!9\x9a\xa6\xf9\x99\xd0\xc3b\xa6\xbcL\xae\x9cLh\x9d\x8e\\LXt%g\x0e\xa6P\xfe%\x0f\xdd\x83\x16\xf7\xfa\xa4\x14\xf7zq\xaf\x17\xf7zq\xaf\x17\xf7zq\xaf\x17\xf7\xba\xf1Sh\x97.\xeeuZ\xdc\xeb\xc5\xbd^\xdc\xeb\xc5\xbd^\xdc\xeb\xc5\xbd^\xdc\xeb\xc5\xbd^\xdc\xeb\xc5\xbd\xfe\x8bw\xafcp\xfd\x14\xa8>\x02\xce\xcf\x08\xccG\x9f\x0d\x7f{\xd7l\x8d\xbf\x9c\xdf\x93\xcd\xe7\xebG6\xe9\x8d\xf7\xdf\x92]\xfd@\xba\xeb\xc7\xc1B\xfd\xb1\xa2\xa4;\x9b\xa44\x81}\xf5\xc4\x16\xc4\x9f\x8e\xa4c\xe6\xcb\xb1\xe7IO\xf8B\xe3=\xef\x9dsz\x18\xd1\xe8\xc9=\x99S\xe8$@>\xbf1\x83b_3\xe6\x8b=SN3Gdz\x98\xe3\xe1\xae\xab\xb6d\xc8\x11s\xb9\xab\x9a\xe8ab\x86B\xa0\xc3n\xcf\xc7\x15\xa1BwqsC\x11\x0eT{D\xe0\x82\xff\xa4T\xe1QC\xd4\xcb\xc7&{\xa6\xf4\x08\x0e\xfe\x8c\xf6\x96~aj\x9a\xcd\xe8\xc3a'\x0e\xa8\xdcGS\xed\xe0Y\xdb\xbc\x94B\x9e\xc1\xa6\xdd\xef\xabf\xab\xbb\xdd\xb7G\xde\x0d\xed/t f\x8c\xf3]Z\xda\x9a\x05-e\xf2\xef\xc2\x16\x18\xd9\xae\xe0\x82\xbb\xf6\xaa]\xdfj\xe2Xo&\xe2[\xd8\x12J6\x94\xed9\xdc\x1fW\x8d]P]c\x1b\x96\xd8'\xa0\x82\xbb\xfa\x814\xe3\x80q'\xb7.Q5E\xbc\xd0\x899@\x87ae\x06\xcd\x0d!\x0dw\xcfK\x13_Ux\x065\xe5\xe3\xae\x89\x9bz\xf7\xa4\xb7|\x08L\x8cm\xad{h\x8f\xf4e{\xfbr[Q2\xee\xa0\xaa9\xd7\xf5\x9e@\xab'd\xfa\x9d`Z\xd4\x93\x9d\xb7#\xd5\xe6\x9e\xd9H\xf2\x9c3\xc8\xe7\xd3\x81<\xd6T\x9d\xd3h\x1d\x9c\x85j\xd9\xb1\x16\xbdd\xcf\xe3\xf3sB\na\x07\x0d\xce\xdb\x992@\xc6\x8e\xec\xa5\xdb\xf0@:&\x9fl\xf5\x83\xe3\x8f\xa4z |hi\x0b5\xed\xe1\xcf\xa4k\xe5\xc1D\xc6i*f\x12\xbc\x14\x9c\xa6\xed0\x08MOI5\x88\x9a\xc5t\x99\x12]\xfc=S\xec\x16:\xb7c\x1f\xe4\x99r\xcb\x8e\xdc\xfc[J\xb7uO\x86/2M\x84\x86\xb6\x19\xa3\xe1p'\x92\xb6+\x0d.\xe2aQ5\xb7\x8a)T7\x9b\xddq\xcb\xa3\x1a/\xcd\xeb\xcd\xfb#\xdb\xbdz\xbeD(_\xdc5\x15\x13\x95\xfbw+\xdav=lxX\xb0:\xd2\x96\xedk\"\x17\x9a\xaa\x87\xaa\x85\xaa\xd4\xccz\xb3c&\xde\xba\xa7\x15\xd5\xe7\x1ab\x80^\xbc9\x7fI\x9a\xeafG\xb6\xd2\x9eT\xe1\xb0\x975\xb7\xd2E\xcb\xe5\xe65\xd4\x00\xa2\x06\xe05h\xe2\xea\x86\xcf\x1e\xd5\xb2\xc3nz\xf8\xe4Z\x92\xaf\x88}\xf5Y\x9c\xf3y\xa5C\xaf\xc5\xa9`\xd3v\x1dS-Cm/z\xb2\xbb\xfdFV\xaa\x0f\x1d\xab\x1enx\xe8f2'\x04s\xedL\xaf\xbbo\xa5\x15=&H\xd3:\xfc@\xba\xfa\xf6i\xd4\x0f\x0d\xf9buv\xc2\xa7\x13\xbe\xf7\x9b'\xf9\xa68\x18\x1d\xba\xb6\xbdU\x91+\xed\xe1CG\x1e\xea\xf6\xd8\x9bJ\x9f7`\x85\x8f\x90H\xe7v\xf1\xe6|h1?\x08\xb4l\x9e\xf7uO\xa1\xdf\xb7-\xbdg\x1b\xc5\xa6k\xfb\x9e\x0fv3 K\x89\xb1\x95\xdd\xe8\x8d\x19nX\xac\xb8\xbdJQ\x90\x81\xd3\xce\xf4\x87.2\xc2\x0b\xdc\xe0\x82|\xd0\x82l\xc0\x02'\xac\x00\xf3sE\x82\nrA\n\xfc\x80\x82Ep\x82\xbc`\x02'\x94 /\x90\xc0\x01#H\x04\x11X\xc3m\xfb\x17s\x03\x08\x12\xe1\x03\x99\xc1\x03 \xd0\x81\xdc\xc0\x81l\xb0\x81\xbc\xa0\x81l\x90\x810` \x1b\\\xc0\x05\x16H\x81\n\xa0\xd0\x00\xc4?g\xeb\x9b4X\x00\x02\x03X\x08\x02@\\2\xce\x8d\xd2\xe9\x8e\xf1\xef\xa0\x0bC\xffc\xa8\x1f\x1b\xdf_\x85\xeb\xce\x1c\xf4\xb7C\xfe\x19\x02\xfeY\xc3\xfd\xe6f\x98\x18\xea\x97\x03\xadKL \xee{\xa3\xdb\x8e\xc0~0\xacoG\x12\xe3C\xfa\xf6\xbb\x7f\xc1\xfa\xba(\x98\x1f\xd3\xd9P \xdf\xdd\xb7`\x10\x7fF\x08\x7f\x1a\xb1I\x0c\xdf{\x83\xf7\xee\xd0\xbd/p\x8f\x8eBl\xd0>\x14\xb27\x03\xf6 \xe1\xfa\x88`\xfd\xfcP=\x12(\x0f\x85\xe93\x05\xe9\x91\x9a\xff2=\xf2e\x0c\xcfg\x0e\xceg\x0d\xcd\xe7\x0c\xcc;\xc3\xf2f\xac\xd3\x0c\xc9\xe7 \xc8g\x0b\xc7\xe7\x0d\xc6\xc7\x85\xe2\x83\x81\xf8\xc80|L\x10\xde\n\xc1\xdb\xb5\xc5\x86c\xfd\xe1\xf7\xc8\xe0{D\xe8}\xd2\xe4\x9ca\xf7\xccA\xf7|!\xf7|\x01\xf7\xe5_7\x18l\x0f\x85\xda\x85\xfa\xc6m\xd8\xcb]5X\xef\xdc\xdc\x1b\xe3\x83\xd5M{\xa4P)\xef\xd9\xe0Ad_\x93\x07\x03j*=(R\x16w-\xae\xdc!\xa9\xff\xe7H\xba\xa7\xd7\"\x98\xc2\xeaUa\xc3\xe80U.'\xfa\xbd\x8aS\x087\xcb$K\x94\xeeGg=\x87/\xd5\x18\x01\xf2\x0c\xa4\xabs\xaa\x96N\xfd\x9b\xaf\x0f\x15%\xe3o}\xab\xbd&\xa5}\xbc\xd6\xb0\x7f5\x9bo\xb5Pd\nEf\x86\x0f\xb4Pd\x10\x0fg\x8aw3\x865R(2Z)\x14\x19(\x14\x99B\x91)\x14\x99\\~\xc3l>\xc3\xbc\xfe\xc28_a\xd0O\x18\xe9#\x8c\xf1\x0f\x16\x8a\xcc(+\xc9\xffW(2 \x14\x99\x08\xff\x9a\xd7\xc9\xa7\x8b\xf9\x16\x97\xa3F\xe2\xe3\xe5\xb9\xe6\xef\xabo6\xabM\xdb\x91\x15;\x945d\xb7z\xf8\xf5\xea\\\xfcg\xb4C\x0fOt\xa4\xa8\x1c\x02\xfc:\xa2G\x99h \xcdh\xe9\xa3g\x10\xd2\x1c\xf7\xfa\x1e\xff\x12\xae\xae__\xbf[\x7fz\x7f\xf1\xfe\xe2\xfa\xe2\xf5\x8f\x17\xff\xeb\xdd\xdb\xf5\xa7\xf7W\x97\xef\xce/\xbe\xbfx\xf7\x16y\x96=\x89\xfc\xf9\xfa\xe3\x1f>\\\xbe{\x8f\xfc\xe2\xf8\xf3\xf9\x8f\x1f\xae\xb4\n\xe4\xc6\xf6*\xbaEn\xd89\xff0\xc2s\xc2\x8c\xfc[\xb64\xe5\x08\xd5\xdc\xe8o\x9ba\xe8\x84C\x85-5>\xa2\x13/\xa8h\xe1\x19\xb0\x96\x9c\x81\xec\xe0\x19\xb0\xffe\x87\x80I\x13\xa7VPp\\_\xc1[\xb9\x91_\x19\xd9\xa6&\xe3\xfc\n^\x0fMg:\xe6\xdf\xd9A\xb0\xa7UG\x89\xd8\xba\xdb\x03\xe1\xa7\xe8\xfb\xaa\xd9\xf6\xf7\xd5\xe7)\xc4\xc5\xf86\xa6\xb4j\xc34\xd8\x8el\xef\xa4\xb4A\n\xf4\x94\x1c\x94\x1bh\xd3\x1e\x1bJ\xbaC\xd5\xd1'\x05TF*\xc1j\xd8\xb4L\xb3PS\xfc\n>\x1cH\xa3\x9e\xec\x8d,\xad\x1d\xa9\xb6\xdc\x17\xd3\x93F\xd07:\xb2!\xf5\x830\x97\x08\xed\xd1\xea\xc5\xc72\x1b\xc0\xf9*\x9b]\xdbK\"\xc8\xa6j\xa0i\x81\x1dLI7\xf0\x8aT]m\xa7\xaa\xd2j0*m\xbb-ak\xcaZ\x99\x8a\x97\xa3/\xc8\xba\x17\xcf\x13.\xfb\xd8\xc8\x7f\xcc]\xa4\x1f>\xbe}\xf7q\xfd\xfe\xc3\xfbw\xce\xb5)\x1e\xf9\xf4\x9e\xff?\xfa\x9b\xf9\xcb\xb0\xe0\x02\xd2\xdd\xeb\xcc\xd5\xb0W\x9c\x93\"\xf3`2U\xaa\x86C\x8d\xdd\xf4\xfb\x19M\x7f\xa5F\\\xe5\x06\xde\x8a\xdc\xa4\xdc[\xc7\x8f@\\\xcc\x99\xdc\x00\xf7\xd5\x13lk\xeew\xb8\xed\xda\xbdX\x15\xec\x01\x98$\xa4\x1b\x88'O\xf0\x85t\x84}o\xba\xc2\xdaa\xb5\xa2\xea\xf4&\x90\xc7jCwO\xca\xa8\x155a\xc2\xa5l}\xf1\xd8\xca\xdcXY\x0e%\x1e\x15\xb29\xb4\x1d]\xd7\xdbHG\x94\xdf\xdf\xc4\xdd&\xce\xd5/\xbb\xdb~\x91\xf6\xa9p\xc0\xf1\xf5\x83\xc5l\xd4\x16\xf8+\xebO\xf1\xcdU\xe35\x0e\x91\xbby\xc3\xc0+\x9e\xc4\xfa\xbe=,K\x80\x1c\x910qW\xf7<\xe60V7F\xb3\xba\xfe\x8c\xef6b\xbaJ\x0c \x1f;5\xb7z\x1eL\xd2\xe7)w\xd3\xaa~r\xab\x90v\xd5\x03Qpv\xe9\x1c6{\x837\xf4y{\xa8\xfet\x1c\xb5\x91|Y\xad\x9c\xba\x87\xea\xae#\x9c\x1f\xdc6\x92\xde8U\xd4H&\xe3\xa1\xf7\xd2\x9e\x19\xf6\xd9C} \xbb\xba!\xeax\xc7\x96\xc9\xcb\xb6\xd9(\xb5\xad\x16\xd1\x13\xdc\x10\xfa\x85\xf3\x08\xa5_U\n\xdc\xb7\xdb\xe3\x8e\xb0C'\xf4\xe4Pu\x9c\xdd\xb3k7\x9f\x05KG5\x9b\xef\\2v\xc7wr\xc2\xf5\xfa\x81\xfb\xad\xdb[)\x8c\xe9s\xd6\x9da\x15\xf3)c>,\xd5\xbd\xf6\xa0\xd3z\xb3\xd6q\x84 g\xadI\xf4k\xb9\xd7b\xb6uh\xacAl\xfd\xf9&R\xfc\xba\x93/\xe8\xa35L\x90j\"G\x17\xe0\x18\xf3\x0b\xb5\x90\xb6\xc5v\x9e\xfe\xb9\xd8\xce\xc5v.\xb6s\xd4\"-\xb6s\xb1\x9d\x8b\xed\xabn\xcdi\xfd\xd0Ux@}\xbbT7\xa6\xb6cT6>@\xc9\xaa\xfa+\xa8i\xaf\x8a>\x89z\x96S\x8d\x7fI\xa7\xbd(k\x14\x16\xdf\xf85\xb0)q\xc9\xdbt5\x1a\xee\x11f~\xdc\xd2\x9a|U\xd58c\xa1\xcd>\x19\xa1B\x05\xa0\x15\x11\xdb\x93?\x1dI\xb3\x89\xbd#\xe3\xe8\xc9\x80%\x0f\xd3J\xa2\xaaa[\xd1*R\xfa\x04|4\x91=D\x9f\x984#N\xd5\x0f5\xb3O\xb4\xf2\xac\x17\xedK\x0e\x13\x83M(\x8e\x94\xa97\"\xc2\xd2\x90\x0d\xe9{ \xba\xeb\x08\xedj\xf2 \x12\x94\xf5\xb4\x1dLZY\xa5H\x12\xb2g\xad8\xd3-o\xf5\x17e\xe6\x1eFS\xf3\xbc\xda\xed\xd8\x02\xe9Ud\xa7f'~\xb6J\xd9\xdbJY+\xd0\xe8\xa455\xdf\x14;B\xf9\x86\xa2\xbe \xef\x8e\x08\xf3\x0d\xad\xb1\x1a\xc3\x91\x86\x95j\x8cK\xfb \xc0\xb9\xf8\xf79\xcf,\xb2\x0c\xf2=\xcc\xb3\xc0\xe5\x18\x93|)\xe6\x8dD\x9a\xc9mL\x9f(\xd3IV<\xdb\x1a\x91\xb7O\x98;\x9d&\xd2\x9d\xd3\xc6qO\x87\xa3\xddPr\x98\xcc@\xbfCN\x04<\x94\x1c&\x90\x82\x8c\xc7F\xac\xe40\xc9\x84\x98\x87t\xd4<\xe4G\xceC\x1az\x1e\xd2\x10\xf4\xf8\x12E\x1b\x99\x0dW\x0f\xd9\xb1\xf5\x90\x13_\x0fQ\x18{\xc8\x89\xb3\x87\x92\xc3\x04\xabf!>\x1fJ\x0e\x93e\xf8}CX\xc9aRr\x98D\xc8(9L\xa6\xa5\xe40)9L \x1f\xab\x00J\x0e\x13\x1a\xc9;\x80\xcc\xdc\x03(9Lfp\x12 \x9a\x97\x001\xdc\x04\x88\xe7'@$G\x01J\x0e\x93(\xfe\x02\xa4r\x18\x0cY%\x87 \",:\x87 xa\x05Z0ot,\xeb\x01=\xdd\x15\xacn\xa4\xd7\x16\xbe\x95\xe8\xda\x0c\xe9\xa9\x9d\x87'\xb9^\x12p\x90>\xdc=\xe9>\xef\x08\xc8\\\xd9\xb7@\x1e\xeb\x9e\x92fCt\xf9k\xeb\xda\x10\xf12z\xe3\x07\x97\xf4\xa5\xea\x87h\xc2\"(@G\x1e\xea\xben\x9bus\xdc\xdf\xa8\x18\xe5T\x0er^t\x04n`l\xb2P\xe2B\xf6\x98d|\xb8\x84Ys\x0eL\xbc0Cs\x16\xe5\xea\xf77G\x8e\"\x9b\x05r\x9b\x14WF\xa8:\xf1\xe969d\xbeg\x15\xb1\xdd\x99\xbd\xfdQ\xbe7\xdc\xc8\x00u\xb3\xe9\xf89\x9d)\x03\n\xa4bK[\xd6z_\xeft\x9b\xe03!\x07\xa6,\x94\x90\xf7|\xf8\xf5\xd5\xc8\x0f\x91\xd5\x9e\x0c\x8eK\xe8\xdb=\xf7j\n:\x0eT\xbb\xbb\xb6\xab\xe9\xfd\xbe\xe7\x11\xd3\xcd}\xdb\xf6D\x84\x97\xf8u S\x07\xa6\xbaI\xa6\x81\x0d\xe9\xa8HE\xdfl\xa5\xdf\x90\xac\xeeVp_u\xdc\x8d\xf2\xb9?\x13\x0b\xe6\xe5\xbe\xda\xdc\xd7\x0d\x19\xfcA\x9a8\xe9\x19\xd2k\xb8\xe0\x83\xda\x13\xd8T=\xe9\xcf&c$\xbag\x8e\x91\xcaP/\xda\xa6Ko\x1bZ7G\xee\xa8\xd2\xab\xb8!\xb0o\x9b\x9a\n\xcf5\x8f\xddn:R\xf5l$ \xfb\x96\xd2\x183>\xcd\x1d\xa1\xbd\x18\x15.\xcb\xc4f\x04\xe2S\x8a2\xf51H\x99r\x08\xd2\xc8R1\x11\xb2\xb4\xbcH\xeetH\nG\xa4\xe6\xcfI\xe2c\xb4dRJ\x8f#\x95LJq\xf1\"\xe1\xe7\xb6\xc6\xa8dR\x9a\x13\x17J\x8c e\x8e\x07%\xc4\x82\x12\xe2@\x88\xc2\xc8\x18\xf1\xc9\x1b\xed\xc9\x16\xe9 Gy\xb2ExJ&\xa5\x92IiF$\xa6dRB\xe2,)1\x96\x98\xe4B%\x93\x92VJ&%(\x99\x94\xac\xa8C(\xee\x91)\xe6Q2)\xc9\x923\x9aQ2)\x95LJS)qQ\x89\x88\x88D\xc9\xa4\xb4<\xde\xb0\xfc\xeb\x06\xe3\x0c\xa1\x18\x83R\xdf\x08\xa4\x1b5\xc3\xa7h\xec\x8b\xb7\xb8\xebl\xea^\x93/\x97\xe8\x81\xfeC\x9c\xbb\xbeD\x0fJ\xf4\xa0D\x0f\xe6F\x0f\xe6\xc7\x0b\xc4{v\x9c@r\xbc0%\xd7\x91?\x1dI\xaf\xd3Y\xfa%\xda\xc3\xc3x\x89\xcd\\\x01\xbe\x85m\x92\xe3!&\xdb\x82\xe3y#\x93\x05x\xb3Y\x80;\xa3\x05\xb8\xb3Z\xc0\x92\xcc\x16\xe0\x0d\x8fC\xc6\x0c\x17\x90\x94\xe5\x02b\xc6\xde\x93\xe9\x02\xf2f\xbb\x80\xaf\x95\xf1\x02N\x91\xf5\x02fg\xbe\x80\xaf\x91\xfd\x02\xec\x0c\x18\x80f\xc1\x00H\xca\x84\x01\xf3\x17}0+\x06\x042c\x80';\x06D\xd2\xad\xc7g}\xeb5\x99~m\n:!\x0d[\x95`\xc6\x0c8\x15-[\x14n\x82g\x1c\xbc\xd0lv\xc7-\xc7\x1f\x8b\x05\xad\xc2%\xf2sqkjX\xf4\xbf\xd2\x95\xc5t\xed\xc7$\xd4\xe8\x97\x9e\xf8\x97\xa5\xb9\xb2\xac#\x97m\x84\x1c\xee\x97\x1d\xef\xbd\x86\x08f\xedG\x1c4\x9do \xc7\xfc\xd0A\xdf{\xd4\xf7\x1e\xf6\x17\x1e\xf7C\x07\x88\xbcG\xfe\xd4C\x7f\xc4\xd7\x08\x1c\xfb\xb3\x1f\xfc\xbf\xe2\xd1\xffD\x87\xff%\xc7\xff\xaf\xe4\x00@]\x00.'@\xb2\x1b`\x91r\x888\xa2C\x84;\xc0\xef\x10\x98\xe7\x12\x08\xaf\xe9ln\x81\xaf\xea\x18\x88t\x0d\x9c\xd49\xe0s\x0f\xccs\x10x\\\x04>'\x81\xc7M\x108e\xc7\xb8\nR\x9c\x05\xa88m\x0d\xda\x1f\xca\xe70\x08vf\xa1\xd3 \xe06p;\x0e\x1c\xae\x03o;]\xee\x83D\x07\x82%M\xa5\xf3\xb4\xdb\x16v\"8\xdc\x08\x0b\xfb\xb5\xd0\xb9`\xc9\x19\xf6\xaf\xc9/\x8e\xa9\x1fn)\x9e\x1aT\x14\xf7,\x0c\xcb\x1d\xb6\x17L\xb4O\x0bgL\x1c*\n\x9a>\x14i\x87\x9ax\xe3#\xf1\xce\x85\x86<\xd2\xf5gb\xfaYC\xc7x\x0b\xb8l\xc6QUQ\xf2\xd51\x8d\xfd\xa7\xc4\xc4W\xbd4A.\xab;\xf2Q\x04!W\xe2wC\xc8\x9f\xd8 \x89\xbf\xce\xc4\xb1\xae\xb3CfO\x81p$:wRh\xaf\xd0\x96V\xb1\x94\xa5\xb0_\xc2Zc\\<\xef\x0f\xff\x0f\xe1\x95\x11\x9e)\xc1C\xd0\xe0\xf3\xa6N\xd6\xbb\xca\xb5\xe4\x9a\x0b1\xf5\x06;7\xf6\x84\xb2\xf3g\xafH\x14=\x1c\x1b1E\xb7B\xeb\x7f\xa9\xb5O\xee\x9e\xea\xa2J\xed\xb0\xdcN\x00Fu\x03w\x1f/\xcf\xc7\xf3\xb3D\xfe\xf4\xcc\x8a\xeb\x88\xa1\x1b6m'\x1e\xe4\x9e:\x159V`!fxr\xbbR\xef\xe6\xa4o\xea\xc9\xabv?6\ne(w\xe4@x\x9c\xfaM\xd5\x0d#\xebb\xccO\xfa\xc8\xa7\x87\x89ES\xf0 \x87\xfbN\xcc0\xee\xbf4]\x1d3\x16S\xf1\xd4\x15O]\xf1\xd4\x81\xe1\xa9\xeb\x17\xb8\xeaz\xc4W\xe7\xf3\x9e\x0dF\\\xf1\xa3\x15?Z\xf1\xa3\x15?Z\xf1\xa3\xcdU\x0eQ~\xad\xe2G+~\xb4\xe2G\xb3\x1e(~\xb4\xe2G+~\xb4\xbf\x8e\x1fm4\x08\x0cl{\xa5\xcd\xc9\xe2P\x9b\x94\xe2P+\x0e\xb5\xe2P+\x0e\xb5\xe2P\xfb\xe59\xd4L\xc5\x1fpp\xcde\xa4Y\x82\"\x19i\xef\xc9#\xbd\x92\xd7v}\x14g\xdc\xd9>6\xbew\xa9\xbb\xbf\xd6\xf2\xa4l:\xdc\x1c\x88]c\xf5\xc8Q\xe2\xdb\x97\x928\x1c\xf6\x85\xb6\x90\xcf\x16X\xb0\xfeC\x9c2*\xba\xb1\xe8\xc6\xbf\x19\xdd8j%3\xcc \x8c)\xbfB\xf4\xe8\xb5H\xcd(n\x0c|=\xbdKo\xb6n4\xee\xe2KPX\x92\xcf\xe1\xa3\xfa\x8a\x83\x95\xae\xc0\x12\xea+\n\xb2(\xc8\xa2 \x7f\xc1\n\xd2\xab\xa0&\x97\x9c\xcaI,\x0eo\xc3\x01\x96\xe9N\x95\xc9T*\x17\xb1X\xab]\xdf\xce\xe5GH1\xe8\x12\x9f\xa7b\xe7\xc7x\xcd\xcbWM\xa5\x977\xd6;\xdf\xc77Y\x9d\xcay\xe6\xb8\xebW\x94E.?\xb4\x1a\xe7\xed\xbf\xa2\xd8w\x00\x07\xab\xf1\xa8.\xa3\x0d\x07\xfcV`\xf9\xe4\xe4n`Q\"jE.>\x9b\xd49\xf7\xb6`D\x84\xe1\xc8\xcars\xf0t\x06-\xb8@x\" \xc7=\xc2\x13\x81\xfcN\xe1\xe9\xc4\xa0\xcb\xae\x16\x86\xe2\x8dU\xa5xc\x8b7\xb6xc\x8bA]\x0c\xea\xbf]\x83\x9a\"(\xc7\x18\xf7\x03n\xd9\xce\xf2<\x9c\x0f\xdb\xeel\x83x\xdc\xb1\x13\xce\xff\xc5\xdf JQ\x8fE=\xfe\x9d\xaa\xc7\xdf\"\xea\xd1VK\x8b\\\x0d\xaa\xcd\x8b=\x0e\xe3\xf2V\xa2f\xb8\x1c\xc6N\xcc\xf76h\xc7\xb6\xe2h(\x8e\x86\xe2h(\x8e\x86\xa1\x14GCq4\x14GC\xb1\xa4\x8b%],\xe9\xa0\xa3\x011B\x978\x1941\xb3\xfc\x0b\x1f\xc5^:\xdb\xfe\x95h,\xeb\"\x86\x9b\xb6\xdd\x91\xaa1UG\x7f\xdc0\xab\x00nw\xd5\x1d\xefJ}\xab\xb6qq\xc4/\xfe\x83\xe5j\xa6h\xbd\xa2\xf5~\xc1Z\x0f\xf3\x1f\x18j'\xd6y\xa0\xdc\x06B\x9eT \x11N\x84\xb3\x93x\x11>5J\x0b\xbe\xde|\x9e\xefBP\x07\xd5e\x0e\x04ky\xfa\xb1\xb4\x8aPs\x1c\xdal\x1e\xae\xc6\xf6\xc8w\x8b\x15\xa8D\xa75\xa7\xe8\xc3\xa2\x0f\x85N\xc0\xac@\\\x89\x80/\x9b\x86\xfe\xfa\xb7\xd3\xf7#m\xbf\xf1%\xa1\x8e\xff\xf6\x94\x97\xe1\xec+:\xab\xe8\xac\xa2\xb3\xbe\xbe\xce2\xd4\xc7\x12\xb5\xb5\xe0\xfcz5&\xda\xb1\xe6\xb9\x9e\x01#\x98\x86\xc5xNK\x85\x83'\xc0A\xd2\xde \xc9nf\xa5\xb8\xc1}\x929\xd2\xd9,Kb\x13\x1c3G\xea\x9aL kN\x9e\xa6&kr\x9a\xf8\x944'MD\xa3U6.\x17\xbe}\xb0\xd5\xf2;m{\x88\xd8\xd9\x9d\xbb\x9c\xd7\x17\x83o\xdc\x0bv6\xe7\xae\xb6\xb0\xfa\xa8\x9d\x0c\xdf\xc5\x12w0\xb5oIi\xf8\xee\x95q\xe7\xca\xb8k\x19;V\xean5\xeeQ\xaa\xd7\xc3N\x95u\x97\x1a\xbe\xdc\xf8\x91*&\xbeE\xc5\x8b\x90\xadv\xf74o\xb1L\x07\xc4TA\xd5\xb1/{W\xd5MO\xa1jD\x16\x19)Z%\xb6;\x1c\xbbC\xdb\x13\x9e\xe1\xf5x\xd8Vt\x1c\xc4\xaa\x19\xae\xf4\xbd\xed\x08\xf93\xabSL\xfd\x1e_\xa8Z\xb6\x8d\xf1N\xc9\xe8u\xbb\xecn\\+%\x88\x14c\xe4\xb2\x9b\xbe\xd4Or\x96\xcd\xb0\xa0\xd9\xa3\xebc\x17\x1bw\xf4g\x02z\x0d\x9f>\xfe\xf8mG\xfa\xf6\xd8m\xe4%\xe5\xfc\x13\n\x10\x02\xfb\xd8\xaasb\x0eqc\x04\xbdvk\xbc\xda\xdb\x0c2\xf2\xdb\x8b7\xed\x0en\x8e<\xfb\x93\x8c\xcd\xad\xe0\xfa\xbe\xeee\x9ba\xcf\xf67y\x9d\xf7p!\x92)\x89\xed\xd8\xcf\xbe}\xc6\xd6VWm(\xe9V\xfc\xber~\x99zO\xee\xb8\x0bF\xee\xe8\x9f>\xfe\xf8\xbc\x87CE\xef\xb9hC\xd0\x0000k\xa0\xc8\xfd\xed|T\xa4X\xde\xff\x17\x15[\xa9\xe6\xab?\xb3\xca\x9c76\xff\xfc\x8dh+\x17\xd6\xdf\xb7\xc7\xdd\x96\xad\x11\xd6YC\xce\xa6j\xc4R\xe3\x9a\xd9\xac\xe5\x05\xd3Bglxxd\xf4\xd9\xea\x19[\xa2MK\xa1\xdal\xc8\x81\x92\xed7\xab_\x99/]4p`\x03Vo\xc8\x19PR\xed{8\xf6G\xbe\x98\x0f\x1da\xeb\x94\xe9\xda\xba\x91W`\xdf\xd4M\xd5=A\xb5\xdb\xf1\xfe\x9aY\x88\xd4&\xf4dVC\x1e\x0fdC\xa1\xa6L\xb7\x1e{\xa2\xf2m)XC{\x0b\xaf\x9b\xa7AM\x8b\x0b\xee?}\xfc\xb1\x17nDC\x1a\x13`\x1c*X\xe97\xf7dO\xe0\xe7{J\x0f?\x9f\x89\xff\xef\x7f\xe6\xb0\x86\xa6\x95\xbf\x9e\xf1\x99\xc2\xd4P\xcbg>\xef)S\xf5\xc7\x835\xdc\xd4\xb89\x1f\xc4\\~\xe0i\xe5*\n\xfb\xea\xd0\x8b\xcf\xce[J\xdb!\xb6\xccMK\xb97T\xbd\xb4!\xfbW\xd6\xe8\xff#\\\xdc\x8emc\x9f\xeb\xd0\xb5\x0f\xf5\x96l\x87\xe6s5\xdb\xf7\xc7=\xd9Z\xb9\x10\xff\x11^7\xf0\xbb\xeb\xebK\xf8\xe1\xdd\xb5\xb2\xce>}\xfcQ,\x19q\xfd\x7fe\xdfC~\xfdt \x7f\xfc\xb7?\x1a\xc2@E\xf9\x1b\xf5\x95\xc5\xf6\xcf\xc7\xef\xd0\xb5\xdb\xe3\x86@\xd5\x00\xe9\xba\xb63\xf3x\xfd#\xbc>\x1cv\xf5\xa6\x92}\xee\x08\x9b#\xed\x17aWm\xaa\x0d[\x8bm\xfb\xf9x\x18\x02\xe97\x15\xb3\xbaD\xa3\xad\xa6|\xfa\xf8#\xaf\xf7\xbez\xe0\x9fz\xaf\xcd\xc6\xad\x98\x8e\x95j&\xfb\xef\x87\xb6f\xb6\x9d\x99\xad\x0bd\xa5|\x81u\xe4\xb6\xed\xc8\x99z\x8d\xefA\xb4\xbe\xa9w5}\x82\x86\x90\xad\x02&p\x05\xd0=X\x99\x01\x99\x96Q\x9b7{\x94\xaf\x80\x15\xbc\xf8\xd4\x13\x95\xe4\x8a\xf5\x97C\x88\xaa\xbdxf_5\xd5\x9d\xdd?e\x11(q\xabo\xcco\xfb\xbe\xa5\xdc\xc6\xaa{\xb8=6\x1b1WYK\xe5\x9a\x1e\x8d;\x0d\xeb\x81\x0df\xcb\x01*6\xc0CM\x07\xe8\x08\xd3\xa8Dx\xf1k\xaa*\xe0F1\xdf\x88\x87\x19~C\xee\xea\x86\x1f-\x98\xc1g)H\xfb\x96z[\xdf\\\xf1\x99\xde\xcb\xa4q\xf4\xbej\xcc\xf5\n/\xe4\xe6O\xf6\x07\xfa$\x97\xc67\xb0\xe7\x86\xc1\x8d\xb5 y39j\xbaf\xc7\x0b\xa6\xe8\x05$I\xdd\xbc\x07=\xd9W\x0d\xad7\x93\x04\x92|\xaeGn\x94N\xc4\x91\x7f\x07\xfd\x89-\xc2\x1b\x02\x15\xab\xac\xdej\xdb\xa0\xb5\xef\xc9-\xa4\xbai\x1f\x88j8\x9a\x98\xd2\x91\xd0kR\xf7\xcf\xaf\x9b\xa7\x9f\xd5\x86\xd9\xb3%[u75\xed\xd8\xa4\xf7\xb4A\xe9.\x9ekN\x13'\x12\x82\xe9\xc3\xce4\x0cW\x80\xa2\x0d7\xb6\x01\xa0\xd7\xa3\xf6\xf4\xc9T\xb8T\x93oW\xdf\xf0\x86I\xbd\xd7C\x7fR5Og\xccl`\xcf\x1d\xc4\xa6\xf9S\xd5\xf5\xf7\xd5\x8e\x0d\n\xd6@\xbb\xf3f=V%\xf5\xadQ\xc5\xa7f?V\xc2\x9b\xc0'\x1b\x7f\xea\xbf|\x07M\xbd\xc3P\x7fH\xcd\x93\x99\xc2\x0cu>.Jo(\x83\x0dn\x9e\xc6-Ui5\x9em\xf3\xe6I\xf9,\xd9f\xa5\x0b{\x8el\x99\xdf\xb23\xc6\x8a\xff\xc0\x8c\x88\xe7\xea\x88\xaev\xe1!\xd6.\xbe\x8f.nPe\xcd\xeeI\xd9\xc8\xd6\x91e0O\xa0\xba\xa52A2?%=\xff\xf6\xb9.L\x1a\xe8\xaaZa\x91\x139O\x9e\xdd\xb6\xed\xea\xa6\xeax\x83\x1f\xbf}Z\xfd\xf9\x99\xe8\xab\xb09M\xc3\x99W\xf7\x8c=\xc5\xd4\xaa\xf6\xc3\xbf\\}x\xaf\xff\xfb\xbb\xef\xbe\xfb\xce\x1cm\xf6\xccx*\x13{;'.\xc8\x8dNX\xad\xc7\x9e(\xe7\xf8\xddqWM\xe2\x17\xf6\xcb\xec\xc1-\x197\xa9\xb3\x11\x8c*g\xfb\x99\xdc\xf7&g9m\x03\xe1\xb4,\xf8\xf9\x7f\xb0\xae\xfe,\xb1\x0e\xc3\x96\xab\x0f\xdcJ-\xaeW\x96\x01Vm>\xb3u5\x9a\xe7\xb7\xf5\x8e\x98zJ\xad\xbeK\xd2\xf5m\x83LYyJ\xbe\xad\xbb\x9e\xae\xf9H\xa3\x10U\xf9\x18\xfb\xd4\xea\xa9\xdf\xf8u\"\x00R\xdb3\xde\xe3g\xaf\xe0\x196w\xa7]Y\x896?;\xb3\xa5\xf0\xd6\xbe\xaf\xf6L\xd2\x7f\x17M\xfb-\xf2\x18k\xad\xf1\x94\xaf\xc9\x17\xb7\xd2p\x9c~K\xf1-\xea\x1e\xbe\x90\xdd\xee\xe5\xe7\xa6\xfd\xd2\xf0Ut/\x10\xf1\xc7\x9e\xb6{k*N'\xcd\x99\xc1>\x103I,o\xadB6A\x9a;\xa8\xc4\xf4\xd0\xc5\xfd\xcc\xa7\xa9\x9a)\xf7\xedn+\xe18c\xed\xfc\xc4/g\x18\xc8\xf3\xb6\x9c`\xba$.z\x98U\xf0\x82\xadK\xd5Q\xeb\xa8\xa7|\x0c\x7f\xfc\xb7?~cM\xc0\xe5_w*\x1c\xfb\xc0\xbc\xbbL\xd0\xafW\xbf\xf9\xf5o\xfag\xd6g\x03gt\x06u\xd4\xe9\xa9q57\x99Z\xa5\xfa\xd2\x14\xbfKafJ\\\x87\x17\xff\\y\x84ye\xffZ\xd3\xfb\x99~}Gh|\xf44\x8b\xe6\x96\xf0xDs\xa2\x82\nP\xc2\xe3\xc1@\x03\xfc\x8d\x87\xc7a\x1cD\x97\xcb|\xba\xbe\x96,,Z\xbc\xe6\xc5k^\xbc\xe6\xc5k^\xbc\xe6C)^\xf3\xe25/^\xf3\xe25/^s\xcf\xbb\xc5k^\xbc\xe6\xc5k\xceK\xf1\x9a\xcbR\xbc\xe6\xc5k\x9e\xe0W-^\xf3\xe25\x9f\xe75\x1flX\x97\x07[w\x9c\x1b\xceh\xdbw.e)\x1a\xaf\xc7a~Yu\x95\xe2\x9eY\xce6$}\xb88\xd6\xae%B\xd7\x04\xd1.\xa1\xb5M\x86\xc1\x90?a<+~\x9b:ZO\xe2\x07b\xd7\xb3\xc7U\xf4o\"\xa7'\\\xcc\xc5\x9bs\xd8 \xdc\xb5\x10t`\x8f\x12J:\x17E@\xdc\x1e\xc4\xff)\xc4\xce\xe6\x03\x1e\xb4\xd1\xb6\x9az\xb0\x9b:6I\xe9\xed}\xbb=\xee\xb4\x83\x90U)^1\xf8\xbe\x1d8\xbe\x1f\xb8\xee\xc9t\x9e\x15O\xfb-\x8d\xab\xd5\x91\x0f\xe1eV\xa9\xeb\xd5\xb5\xf7\xa4\xbc\x91J\x15\xfe\xf2|Y\xce\xfe\xf0\xd1xqo\x0eQ\xe4f\xca\x19\xdf\x9f\x16\x07yq\x90\x17\x07yq\x90\x17\x07\xf9P\x8a\x83\xbc8\xc8\x8b\x83\xbc8\xc8\x8b\x83\xdc\xf3nq\x90\x17\x07yq\x90\xf3R\x1c\xe4\xb2\x14\x07yq\x90'\xb8P\x8b\x83\xbc8\xc8\x83\x0e\xf2\x92\xe7v \xea\xba\x80\xc0\x0b\x08\xfc\x97\x08\x02\x0f\xba\xf2'\x9e\xf5xO\xbe\x9e_\xeb\xe3\xe5\xb9j\xb8\xf4\xe7\xc3\x1b\xd2\xf3\x83\xa3\xb6\x10\xf80\x9fq_F\xc45:J\xa0W D\xc6\x0d\xe6G\x8c\xf4\xc0\xc1\xb2p[\xf4\x1d:Hj\x1c]\x0e\xa2\x01\x82ir&\x82\x8d\xe0\x07&`\n\xfe\x97O\xe0\xbd\x00OO\xc0\x19\xed\x18\x7fst\x08\x82~\x1bQ2\xc6?DqGAD\xc9\x17\x0b\x11%[DD\x14g\\D\x14\xec\xa8\x11\x19\x1d\x11%W\x8cD\x14\x7f\xa4D\x94E\xf1\x12Q\x16GM\xf0\xb1c\xe7Uw\xecD\x94\xc5\x11\x14T\x9a\xd0u\x8e8\x8a()\xd1\x14T\xe0\xf1\x00\x15\x1aS\x11eId\x05\x15\xe4\x8c\xb6\x88\x92\x18sQB\"\"/\xe8\x9b\xd1\xd1\x18Q\x12b2\xa2$Df\\\x0b\xdd\xd1\xd4l1\x1bQ\xf2FnD\xc9\x16\xbf\x11%\x1c\xc5\x11%[,G\x14WDG\x94\x94\xb8\x0e\xae+\x90X\x8f(\xc8!\xd1\xa51\x97\xc6}Pa\xaeX\x90(\x0b#B\xa2 q!Q\x02&\x853F$J\x8c\xc5\xb10^\x84+S\x15C2\xa2F\xa2\x84Z\x93\x16A\xb2\xc4\xf1\x88\x12\x12G\x12%C4I\x94\xb4\x98\x92%\x8e[4\xa8\xf1\x90\x18_\xb2k\xb2\xe2M\xa2\xa4D\x9dD\xf1\x86cDqD\xa0D \xc6\xa1DA\x9c\xe6\xbc\xc4\xc7\xa4Dq\xc9\xb1\xfc\x92\x89Q*Q\xe2\x07'\x14\xb1\x12%4\n\xc1\xe8\x95(3bX\xa2 \xa3\x93\x1a\xcf\x12\xc5\x1b\xd5\x12\xc5\x1d\xdb\x1a~wF\xb8D\xf1\x8cZl\xb4K\x94P\xccK\x143\xf2%JB\xfcK\x94\x88(\x98(\xf3ca\xa2\xb8\x86)\x18\x17\x13%StL\x14g[\x90\x99\x98\x14/\xb3\xa4\x19\xf13QR\xa2hv\x0dVTM\x94\xa4\xd8\x9a\xdd\xe4i\xacM\x94\x9c\x117Q\x9cq7Q\xcc\x90\x87(f\x0cN\x94<\x918Q\xb2\xc5\xe3D\xc9\x1b\x95\x13%.6'J0B'Jd\x9cn\xf2\xb07Z'\n\xa6\xfd\xd1\xd8\x8e(\xb1\x11\x1e\x7f\xfcN\xca\x8a\x8b\xe2\xc9\x87\xc3\xb1Q\xf2\xc5\xfc\xb4j\xb2D\xfeDI\x9d#\xc1(\xa0\x14\x17\x88\x05\x8a\xa2o\\\xbe\xf3Ib\xd2\xa9\x89,\x99\x80j\xf27,\x0f\x15\xd2*\xc5o\xe0\x17\x8doA\x0f\x01(\x856\xb9p\xa3\xdc\xce\xcdK\xb9\x9d\xbb\xdc\xce\x9d\xe5v\xee\xb8`\xe3\x02\xde\x90xO\xca\xb3\xc3\x8d\xbe0\xe0\x84\xd87?\x10\x18\xc8\xa05\x99\xbd&C\x10#\x15Y1;\x90p\x01\x1e\x9f\xd7\x84-\xcfuG\x0b\xe3(=\xbeV\x18Gq\xb13\xe1\xaf\xb7\xc6\xa80\x8e\n\xe3h^\\\x0b=\xf8g\x8b^\xe5\x8d[e\x8bX\x85cU\xd9\xa2T\x85qT\x18G3\xe2E\x85q\x84D\x80Rb?1$\x9c\xc28\xd2Ja\x1cAa\x1c\x15\xc6Qa\x1c\xe5\x8asd\x8bp\xe4\x8dm\xc4E5\x82\xf1\x8c\xc8HFL\x0c\xa30\x8eFYI1\x89\xc28*\x8c\xa3\xc28*\x8c\xa3\xbf+\xc6\x91\xe9\x19\xf7\xb8\xe1\xbd\x01\x00\xfd\xf5o\xa7\xef\xabF\x8f\x19\xc4\xa2#\x00\x0b\xb8@\xd3\x10\xc0\x89\xe9@\xd8\xca\x8c\xbd\x0fG>\xbb\x8c\xb9\xe3UU\xa285\x84(\x1e=!\xdfOR^\xa2xU\x98\xac&_3\xa3\x95\x9a(!\x08o>\x05'JX\xcd\x89\x92\xa8\xec0yv% *\xd0\x92e\xfaE\xed\xda2\xaaCQ\\JQ\x94\x04\xd5\x88LasL\x9dQFQ\x02\xb7\xf5\xc8\x87\x96-{Z\x08{\x85\xb0W\x08{\xc1\x00$*\xad\x10\xf6\x96\x86,\x95\x90\x88\xc0%\xfaft0S\x94\x84\x90\xa6( \x81M\xd7Bw45[\xc8S\x94\xbc\x81OQ\xb2\x85?E \x07AE\xc9\x16\n\x15\xa5\x10\xf6\na\x8f\x8fT!\xec\xe9%-$k\x89\xa3\x85\xb0\x17\x0e\xe3\x8a\x12\xa2\xaa\x85C\xba\xa2\x14\xc2\xde\xbc\x10\xb0(\x85\xb0\xc7K(d,J!\xec\xd1\x84\xe0\xb2(\x85\xb0734m7\xb9\x10\xf6r\x84\xb3E\xc9\x1b\xd4\x16%.\xb4-J0\xc0-Jd\x98{\xf2p!\xec\xf1\x923,.JRp\xdc\x92V\x08{_\x8f\xb0\xb7\xfc\xbe\xab\x89\x18Mi\x98\xb7^\x89\x82\xbb\xae{\x94\x1ac\xe5\xb1+\xf4<^\n=\xaf\xd0\xf3\xb2\xd0\xf3\xccY\xea\x0b\x8f/\x0d\xcd\xf7\xae\xa0|\xbb\xdf\xd7t/\x03\xf3?q\xbc\xceeGn\xeb\xc7\xe8@\xfcg\xf2\xb4>h\xaf\x80kf[\xcb\xd4\xec\xb8^=\xeb\xa8\x82\x0fU\xf4\x1eD\x0dbi\xca%\xab\xd4\xd9\xb5\x08\x14\xf4\xb4;n\xd8\xb7a\xab\xf5\xb6k\xf7\xfc\xb9\xcb\x8a\xab\xc7\xed\xb0\xce\xd5\xc6W\x1d\x0e\xa4\xd9\xbe`\xbf\xaf\xfe'yb\xff\xaft\xbc\xf9\x13\xaf\xfa\x8cW\xb9Z}\xf3\xcdt\xfc\x9a\x86p' \x1b\xbf\xf3\xe1_\xef\x9am\xf4\x00\"\xa9F\xd1\xf1\x9b\xac&\x19\x97\xb7\x15v\xdd\x83\xd6(\xf9\xb2t\x00\x9f\x18$1\xee\x14V\xa8\xd4\xed_\x94\x93@\x04\x1eUC]\xc9SoIE\x8f\x9d\x1d0\xc5z#\nze_L\x83\x14i]U98\xe6wd\xdc\x1bGO$\xda`\xdfV\xff{\xd9S\xfd\"@\xd9{\xa6\xc5d\x00\xe7(w\xa3\x86\xdc\xb5\xb4\xe6\xf7\x01\xde\x13\xb8xs>\x91\xf5@\xba\x9aY\xe7f\xf8Q\x86\xd0\xe4d\x80\xfb\xaa\xd9\xf6\xf7\xd5\xe7(\x9e\xca\xc5\x9b\xf3\xe1k\xc8\xb3F\xd5\xb0\x85\xc3\xbd\x83\xb2Y[BI\xb7\xaf\x1b\x02\xa4\xd9\xb4L\xfd\xf62x\xc3}\xa7z\x08\xeb\xb6\x9d\x1c\x966\xf7U\xd3\x90\x9dx\xbc\xda|&\xb4\x97\x92Y\xef\x1d\xd3\xd8\x08\xc3O\x17\x84\x083H\xabH\xa5\x15\x18;O\x1a\xdd\xfe\xc1>?i\x8e{}\xa6\xbc\x84\xab\xeb\xd7\xd7\xef\xd6\x9f\xde_\xbc\xbf\xb8\xbex\xfd\xe3\xc5\xffz\xf7v\xfd\xe9\xfd\xd5\xe5\xbb\xf3\x8b\xef/\xde\xbdE\x9eeO\"\x7f\xbe\xfe\xf8\x87\x0f\x97\xef\xde#\xbfL\xfe,=\x03\xaf\"+\xe6{5\xe9\x0eUG\x9f\\\xa3\xa2=\"\x92,\xc4\xaa\x8cY\x06\x9b#[\xb2s\x95\xf9}\xf4\x06\xf6@\xaa\xbaV\x85\x84\x83=2\xcf0\x82\xc3m\xfc\x11\xeb\xb1\xfe\xd7Suf2#\xa3:e\x08\xc4C\x0d\x02\x00\x85w\xca\xdc\x9d\xc1\x9e%\xca\n\x18!\xbb|\x13\x1e\x96\x91\xd9\xbc\x1524\x08\xc8\xc5\x0dq\xc1\xac\x06U<\xca9l\xec\xdbD\xbf\xb9V\x85\xf1\xfe\"\xf3\xc2\x90\x81\x1a\x1b\x81gl\xab\x03\xf8w\xdbUO\xeb\x03\xe9\xea6d/8N\x11\xee\xe9\xcae\x83\x90-\xa1\n\xc7\x9e\xf23\x11\xdc\xf0(5r\xfeT\xbb\x82\x0c\xbc\xea\xd3\x8e\xab\xf5\x97ls\xba\x95!z\xbd\xcf\xef?\\\xbf{5\xads\xd7\xde\xd5\x1b\xf6\x8d\xb8#r\x08p\n\x7f\xaa\xc0\xc6q]\x80\xdd\x87;X\x91\x13#L;8\xf3\xe6\xde\x1ewr\x9e\xb2\xa5W\xc9\xb5&\x97\x8d\x98\x07U\xc3\x0f2RZO\x0eU\xc7w\x94f\xd86E\xcb)?\x89\xf0\x11\xe2\xcd\xbd!\xf0\x1bPg\xa1I#\xf8\xf1\x86\xf4\xb4\xba\xd9\xd5\xbdb\xcbW\xba*\xb8!\xf4\x0b!\x0d\xd0/\xadh\x92q\xeb\xb2ae\x9aj\xffTF\xe6dv\xe4\xd4\xca\x96F\xb6\x15\x97C\x13'6:I\xfb\xda\x9a\xd7\xa5uM\xcd\x96M\xdb\xce\xd8\x93]\x1a6\xe8u\xc0\x98\x1c\x93AM\xd1\xa8\xa9\xda4\xa4Ic\xb4(>]\xf4e5\xb1\xcac\xe6\xb66\x07\xa48io:\xd6\xb0\x96\x99k\xf8{\xf4Z\x9e\xb7\x1e\xb49?\x1eRV)j\xa1\x9c=m\xf9\xe5\xec9\xfb\xec\x89\xa9\x96_\xd2\xa9S\xbeW\x0e\x9d\xe5\xd0\x19\xd1\xa3r\xe8,\x87\xce\xb1\xa4\x98H\x90\xc1L\x82\x08S {\xe6\xab\x1c:'g\xbe(\xcd\x80\x9f\xf40#j\x1a)U\x7f\x14\xd3w\x8c\x8aZJ\x1e\xcbd\xea0\xdd\xb4\xbc\x89c\xb5\x8b\xf8\x8bj\xd1\xb3Y\xb1\xcc<\xf2Yi\xfd\xae\xde\xf0=\x89\xa7\x83\x9bj\x01^#f\xc5\n\x8e\xa6\x14\xf8\x0b\xa6\x7f\x0f\x10T\xa3uQ\x1bG\xa1\x7f\x17\xfaw\x88\xfb\xf8\x9f\x94\xfem\x04\x99]ZlF\x98\xd9\x14\xe1\x0c4\xdb:t\xf8\x13r\xe5e\xb4\x1e\x1d4\xf7v\x8d_\xad\xa8\xb0.z\xaek4\x05\xac8\x1b,Q(s-\xd1i\x93\xd0\xe3\x9b\xfb\x9aH\xa4?H\xad\xb3\xec\"\xead\x9bz\xad\xa2\x10\xd3\";\xcf\xd4\xcf2\xcd\xcb1\xcd\xca0\xf5\xf2Ki\x1a\xbb4'\xb74\xcc,]\xcc+\xcd\xc9*\xa5aNiNFi\x90O\x9a\x99M\xea\xe5\x92.a\x92\xfaY\xa3\x198\xa3Q\x8c\xd1y\xec\xd0Dnh^f\xa8\x8b\xac\x98\x95\x15\x9a\x9f\x13\x9a\x95\x11\x1a\xc7\x07\xcd\xca\x06\xf5qA33A]^\x9e\xab\x06\x0b\xe7\xc2\n\xde\x90\x9eG\xc1m[\xe7\x8cC3\x9a\xcd\xee\xb8\xe5:S\xaci\xb5\x17NF\x85m\x97J\xb0W \x04\xb30\xd9\x99K\x16\xb83\x96\xa5^\x9a\x91\x99\x12\xf7\x0b\xa0\x06\x8ea\xa7\x0d\x03lg\xee\x14\xc5i\xbdG\xd71\xdb1\xe2r\x8d\xf8\xdc\x05\xdeL\x98\x8b\x8cH\xbf\x93$\xc2\x88\x9c\xed(\xf1\xbbJB\xce\x12\xaf\xbb$\xbe\xb9\xb9\\&!\xfb\x0e\xd2\xdc&\x884\xe9\xd4p:Nb]'>\x0b?\x9f\xe3$\xe0:\x99\xe9<\x99\xbc\x8dxOR\xfd'\xde\xf9\x83\xf9P\xe6{Q\xbc~\x94\x90'\xc5\xe3KY\xe4M\xf1\xf9S2{T\x16{q=~\x95\xe0r\x0f\xaf\xcd\xcc\xde\x95\xb0\x7f\xc5\xe7a \xfaXN\xd2\xe1\xe5\x9e\x96H_K\xd8\xdb\xe2\xf6\xb7\x9c\xc0\xe3\x12\xd8.C\x1bf\xd8\xef\x12\xfcJ\x10\xf2\xbd\xf8\xbd/y\xfc/\xf9<0\xf1>\x989^\x18\x9f\x1f\xc6;\xc2\x9e\x83\x9f1\x9b\xe6\xe7OE\x84\x18\x97\"f\xcc\xa5*\x8a\x8b3i4C\x194=m;\xb2\xd5\xad\xf2am\xe8\xcb\xa1\xdc=\xc9K\xb9{\xb2\xdc=\x99\xe5\xeeI\xe5K\xb1V\x93\x98a7\xbbv\xf3\xd9ti\xccXL\xc5#W\xc9\x13\x1co\xa6\x9bM\xb6\xd5\xe3Yc\x9f\xaa\xd2\xb8\xb1+\xdaUM\x7fK:\xf6\xc1\xde\x92\xa6\xdd_w\xd5&\xde\xaf\xce\x0es\x81\xaf\xe5\xde\x01\xf9Ipr\xf7\x16\xf7]\xb4\xb7ph;\xfa\xadt\xbai\xa3\xd8k4\xd0\xae\xdaLw\x11c\x8f\x92\x99\x02\x94j86w\xfc+\xd1\xf63\x19\xe6\xfdM\xd5\x93\xf5\x96\xf5zN\x1f\xd8[\xc0\xdfR'\x10YI\xc7Nj\xac}He\xf8(\x8c#\x0e\x13\xba\x86]\x05\xeb\xf3\xc5\xf9\xd5o\xfe\xab!\xbdg\xc7\xdf_Y# {/G \xeaF\x985\xb5\xbc\x0d\"8\x15.\xab\xaeR\xcb\"b\x1a\xf4\xa4\xd9\xaeI\xc3\x8c~\x0b;\x7f\xd3\xb6;R\xc5XD\xba\x14\x10\xff\xcf=\xae\xdb\xba\x17\xff]\xedv\xb0\xe9\xda\xbe\x7f)f\n\x1f\x01P\xed\xeeE\xa8i\x94\xc7\x0e\xc7\xfa\x94\x98\xe8\xbc\x8elH\xfd@\xd2[m\x08Z\xd4\xf0\xc9\x91\xcf\xd3l\xbc\x15\xe2cMV\x123\xda\xda[\xae\x1fT-p`\x8f\x11J\xba~\xd8\xec\x04\x18\xe1\xba\x85C\xc7L\x1e\n\x150\xfbGM.\xe1h\xb9!\xdc\xc9-\xc5td{\x06\x86Mx\xad:\xf2N\x8e\xc1P\x15\xf7\xeftG\xa2\x9c4\x8dz\x15n\xaa\xe63\xec\xdb\xedqG\x9e+C\xe7\x8a4\xff\x9b\x9d\xb3\xc9u\x10\x86\x81\xf0\x9eS\xf8\x04\\\xa9\xaa\x04]U-\x02z\xff\x8a\x10\x93q~M\xc2\xa2\x8bn\x112\xc9{\xe3\xe9\xe7I\xcb`Kt\x87\xc1p%\xa6$\xd1\x16\xeb\x9b\x1e\xf7\xe7R\xf66\xc3V\xae\xddN\x1f \x9a\xa7\xdeVg\x8e\xc1\xbf\x03\xee\xa0y\\?\xf3\x8bY\xcf\x0c\x82\xe3\xe0\xad\xdc\xdc\x08\x8d\xd9{\nT\x8d\\\xd2\x7f)7\xd8\xe4S\xd7\x06/\xf6*\xb1\xe7\xc4^\x89\xa1\xf0dJ\xf82\xa9\xf7\xd6\xee\xcf\xf2\x1b\xfd\xa1j4\x18\x0f\xd6\xbe\xf1\xfb^O\xe2\xbbV\xac\xe7\x8f\xbbA\x8bu\xf8\xa3>\xef\x0e\x05\x98\x8d=K\xd1\xffu2\xcc\nQ/\xc5\xb4\x18\xf5\xfb\xac\x12d\xa4\x8e\xf7\xf7\xba\x00\x1eD=~k\xa9\xb8\xa8\x00\x89\xc8JQ\x7f\x87\x19n\x1f\x82\xb8\xac%\xed\x81\xb1\xe0W<\x00\xe2_T\x0b\\\xb6\xb1\x0c\xb7h\x95\xbb\xfe\xd3\xe1R\x16\xf6\xfb\xe9\xf0\xf5\x01\x0d\x18\xb3\xad\x96\x0ch\xf2\x0e\xbfs\xdbis\x9f\x80\xcd\x83\x1dN!\x0b:\xeec\xdf\xd9\xb1\xab\xaa%\xe2\xa4OIn\xa6\xa2\xe9\xb7R\xbfW\xce\x9e\x0dJ\x84\xa6 \xf1\xc8M\x00\xd4\xb0\x9b\xeai\xc0\xef#\x98\x0dJ\xdb\x11+\x8a(K#j;C\xb8\x9f\x16\xf6\xdd7\x00\x00\xff\xffPK\x07\x08\x96\x1f\x8bP\xea\xc6\x01\x00\xd4\x9f\x18\x00PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(\xd4`4t\xc7\x01\x00\x00\xbd\x01\x00\x00\x11\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xb4\x81\x00\x00\x00\x00favicon-16x16.pngUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(6B\xc8\xd7\x7f\x04\x00\x00u\x04\x00\x00\x11\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xb4\x81\x0f\x02\x00\x00favicon-32x32.pngUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(\xb9\xb1\xf1mT\x02\x00\x008\x05\x00\x00\n\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xb4\x81\xd6\x06\x00\x00index.htmlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(]\x12r 9\x03\x00\x00T \x00\x00\x14\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xb4\x81k \x00\x00oauth2-redirect.htmlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(\x05\xef\x9fw>9\x05\x00\xf8\x0c\x1b\x00\x14\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xef\x0c\x00\x00swagger-ui-bundle.jsUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(v\xf2\x8aA\x86\xba\x01\x00\xc5\x87\x08\x00\x1f\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xb4\x81xF\x05\x00swagger-ui-standalone-preset.jsUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(_;\x94/\xe8Y\x00\x00\xa8X\x02\x00\x0e\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xb4\x81T\x01\x07\x00swagger-ui.cssUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(\x96\x1f\x8bP\xea\xc6\x01\x00\xd4\x9f\x18\x00\x0c\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x81[\x07\x00swagger.yamlUT\x05\x00\x01\x80Cm8PK\x05\x06\x00\x00\x00\x00\x08\x00\x08\x00E\x02\x00\x00\xae\" \x00\x00\x00" - fs.Register(data) - } - \ No newline at end of file + data := "PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00 \x00favicon-16x16.pngUT\x05\x00\x01\x80Cm8\x00\xbd\x01B\xfe\x89PNG\x0d\n\x1a\n\x00\x00\x00\x0dIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\x00\x00\x01\x84IDATx\x01\x95S\x03Luq\x1c\xfd\x8c\xf1\xc3\xec0\xa7)\xcda\xb6k6\xb2\x9b\xf9\xb2k\xc85/\xdb\x8dqx\xc6\x94m\xcc{\xef\x7fO\xff\xf3l\xdc\xed\xf2\xe0\xfe\xf8\xc9\xffP\x14\x11/\x14[\xa3P\xc4\xa1\xbc?\xf1t>7\x12s\x13\x03\x85\xca7IR a\xb5j\x8f\xa71\xbe]\x88\xf6\xb9L\xf0\x1c\x93\xcf\xda\xe3)\x10\x93f\x8d\xe4\x06\x13\xcf\xde<\x9b\xd14\x95\x8a\x92\x81OA\xcfF\x89\xdd<\x9b M\xe6}L\xe4\x07\x15\xc5\xf5\xe3\xffI\x0c{\xd6\x8d\xffs\x994\xbasfh\xae?\xafk\x1aprw\x10 <\xb9\xdb\xc7\x86\xa6\xd1\x19I\n\xa8\xb1\xd7\x84y3g\x171T$\xb5c\x7fq\xfbbq\xbfk\x8e'\x1dQ\xb0\xc2,\x92\x0bx|;F\xe5\xf0\xef\x00\x83\xf2\xa1\x1fx|?q\xbd\xcb\xc2\x16\x80ZF\xf0\xc4J\xf3\xe3\xe4n1\xcc\x17k`:}\xcby\xe8\x98\xcbB\xc7|6z\x97r\xd14\x9d\x06\xd3\xf9\x8a\xe4\x94\x90\x8b\xb6\xd9\x0cP\xebc@\xd0|\xbe*\xc94\xc8\xa7\x98'\xcdh\x00\xe3\xd92\xa6vK}\x0cB\xa4\xf0+D\n\xc7\x81)\xb0\x10\x9a\xe3\xa9\xd8\x8bx\xe4(\xa2\xbb\x8dl\x0d\x01\xb6\x8a-\xf378\xbe\xdd\xc7\xa6\xb6\xc9\xd9\xc6d\xd8\\m\xf4\x0c\x92 uQ\x0e\xd2\xf5\xb3\xd1\xf1w\xdfQ\x16\xb34a$\xa1\xc4\xc4(V\xbcF\xd9\xdf\xa4\x91\xe9\xb0&,\x12+\xcd\x93\xcf\x1c\x1cb\xdc\xca\x00qt\xeb\xcc-\x14\x89\xfe\xfc\x0fm2j\x88\xec\xccs\x18\x00\x00\x00\x00IEND\xaeB`\x82\x01\x00\x00\xff\xffPK\x07\x08\xd4`4t\xc7\x01\x00\x00\xbd\x01\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00 \x00favicon-32x32.pngUT\x05\x00\x01\x80Cm8\x00u\x04\x8a\xfb\x89PNG\x0d\n\x1a\n\x00\x00\x00\x0dIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\x00\x00\x04|ID\xc4\xcf\xd0@\x04&%\xad\x1e\x16\x0f\xf7\x8d\x97AR\xfa\xca\xe7l\x87\x05\xf8\xd2\xfb\x0c\x84\x1d\x0dLVY\xdc/ju\x13\x1a\x88\xd2\xa0\xaaa\x82|nzp_\xf4\x03\xc8 \xd4;^\x8a9}\xeeu\x9a\x91 `\x04\x14s\xec\xe1\x0c\xc6]\xa3\x05``\xd1w\x12*~ \x00\xf3\xae\xd3\xa0\x9cb\x82\xa2bx(\xb3n\x1fqx\xd2\xf2\xda4\x1d\x8a}\x1ck\xd4>\x9cI+\xeb\xb3\xf4k\xc8u`L\x93\xf3]4\xb5\xd0\xc3\xe33\xd9\xee\xd7\xf2\xd9\x19\xea\x18\xc9\xc1Y:\x18\xfb(-\xadN\x82\x06e\xd5\x1f0\xa2\x1dV\xf8\xbe0\xc1\x985\x01\xf8\xd2~\\\xa6\xa5\xb5)&\xf6\x98V\x80l\xe4\x03\xf8\x03\x04\x00s\x9a^\xec\x85\x00\xf4+\x0b\x00\xe1:G\xf2p\x96\x0e\xc4,\xe46\x1e5\xbbP\xdd\x15J\x80}\xce\xa4\xe2\xc8{m\xa4\xe2\xc3\xc2\x01\x07\xc0\xdb\xa4\x18-\xa1\x931\xba\x10S\xfa%\xb6P`\x10\x19v\x99#|Gg\x9b \x10W\xf6\x8dI1\xba\x92\xd66\x17E\x12\xfa\xd9\xa8\xf3UTe\n\x1b\x95\x9d\x81f\xe5\x18\xa5umc\x81\x86\xa6\xeb\xec \x804\xcbg\x17\xa19\xfa\xc6\xf7<\xa3\xbd\xf2\x0e\x7f\x02\x80\x97Y\xc7\xac\x184$h\xa3v\xba! \xcc{\xcd\xb4!\xb1\xd8\x92%h\xe3\x93\xdc\xd3_\xda1\xe6\xaei\xcf\x83\xa6p\xbc$\xf0\xb2\xda\x94\xa2q\x14B@\x13\xdb\xff\xf3\xd7\x0d\xfaA\xb9\xc5n{\x8e\xd6Y\x08\x01u\xc1'~\x16\x8e\xe9\x04\xa2\xfbA+\xc74\x0c\x98\xab\xd7:\xfc0\xd1v\xaf$\xa2#\xb7\xf1\x08\xfdm!OXh8\x10j|g\xd1\xe0a\xb2\x99\x04\x9a[y\x9a\xbdk\xf24C$\xa0\x9e#\x9f\xa3\xa8\x001\xc6\x1a\"\xc0\xe4i\xa6\xcc0\xf3\xf7\xb7\xf5XE\xb8\xe0\xa1\xc9\xc2\x0c\x90\x83\x80$\x838\xdf\xd6\xe3\xd4\x82FNG\x0f\x876\x8a\xbf1\xa8d(\xa7@\x8cQX\x90\xdb\x19\x9f\xc5YG\xe9\x9e\x00\xa5y3]\x9aJ\xe1\"\x00\x00\x00\x00IEND\xaeB`\x82\x01\x00\x00\xff\xffPK\x07\x086B\xc8\xd7\x7f\x04\x00\x00u\x04\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00 \x00index.htmlUT\x05\x00\x01\x80Cm8\x9cT]k\xdc:\x10}\xdf_1Q\x1e\x92\\\"\xfb&\x81p\xf1\xb5\xfd\x90\xa6\xa5\x81\x94\x06\x92}(\xa5\x14\xd9\x1a{\xa7\x91\xa5E\x92\xf7#!\xff\xbdX\xf6\xae\xb7\xdd\x90BYX\x8f\xe7\x9c9\x1a\x1d\x8d\x9c\x1ep\x0e\x1f\x1f>\xddBe,8/<\x95 \xc9yKE\xeb\xc9h(Z-\x15B\xd1\x92\x92\xc0y>I\x0f\xae?\xbf{\xf8r\xf7\x1ef\xbeQ\xf9$\xed\x1e\xa0\x84\xae3\x86\x9a\xe5\x13\x80t\x86Bv\x01@\xda\xa0\x17P\xce\x84u\xe836}\xf8\xc0\xffc\x03\xe4\xc9+\xcc\xef\x97\xa2\xae\xd1\xc2\xf4&\x8d\xfbL\x8f*\xd2\x8f`Qe\xcc\xf9\xb5B7C\xf4\x0c\xfcz\x8e\x19\xf3\xb8\xf2q\xe9\x1c\x83\x99\xc5*c\xae\xd7\xe0-E!\xbb'A\xa5\xd1\x9bbjD\x8d\xf1\\\xd7\x9b\xeaJ,:\x9c_\x9c\xaf.\xce\xa3\x008zB\x97\xb1\x90a\x10\xff\x9d\xde\xd9\xe5\xea\xec\xf2\x17\xbd\x90\x19\xf5\xc2\xc6\xfa\x18\x82\x9bC\xf8<<\x01\n\xb3\xe2\x8e\x9eH\xd7 \x14\xc6J\xb4\xbc0\xab\xff\xb7\xb8Y\xa0\xad\x94Y&\xc0\x1b\xf3\xc4]i\x8dR\x85\xb0\x8e/\xd0z*\x85\xda\xe7\xf2u\x02=q\x83\xbdL\x86\xe0\x9f\xd3M\x90\x14X\x19\x8b\xe3\xbb\xa8<\xda7\xfb#=CK~O\xb40r\xbdW\xd8\x08[\x93N\xfe\x1d\xdb+D\xf9X[\xd3j\x99\xc0a%\xba\xdf(\xd5\xfd\xa7\xf1\xd6\xaf4\xee'\xac\x0b;\xf9\xc1OI\x0b \xb9;\x0e,OcI\x8b|2\x18^Z\x9a{p\xb6\xdc%\xf1~\xc6\xa3\x1f\x8e\xe5\xdd*\x81\x94\xbfY\xe1\xbc\xd0R(\xa3\x91\xcf-:\xf4o\x14\xf7/K\xd2\xd2,#\xa3\x95\x11\x122\xa8Z]v\x17\xec\xf8\x04\x9e7N\xc51\\\x85{&\xc0\xad\x9d\xc7f\xc8\x97F;\x0f-A\x06\xc3m\x99\xde\\\x85\x9e\x8fGG[\xab\x12`Q\xeb\x8c\xd8v\xfb_}K7\xd3F\xfe]\xb1\xa1\x82h%q{\x8b\x9b6\x88/\xc4i }\xc07u~}\xe5\xad\xfd\xc9\x98\xe7q\xd8_}o\xf1\x92%\x9dx\x15\x9f\xd3yO\xbdX]\x1aA\xc9>t\xd6o\x93\xd3\x92\xf2\x04l\xc5\x8d\x92jz\xc1jN\xd6\xf2\xa9\x87\xfa\xb5]\x05\xcc\xf9\x1acB\xa9,\x9f\xd0\x08\x05\xb7\x962\xec\xdb\xb6\xe2\x16b\xc6\xd5\x942H\x05KfI\x06\x7f\x9c\x98\xa8\xc0\xd5\x9c\xa2\x0c\x13\xa3\xe7U\x8e\xb55;'Nk\xe6\xd0\x9d;\xd4%^\x14\xbd\xd5\xf7\x92QN\x8e.\x1c`\x079m\xe3\x9e\x8a\xfe\xed\xa2\xad\xe0y>\xe6\xe23\xdc\xf8u\xa7=\xa3\xf6\xa1\x98\xb4\x17g\xa9\xf4\x1dA\xa8Z\xe4\xf6\x88_\xfc)\xf8\xd5N\xcf,\xea\xb4\xabS\xf2\xd2\xe0v\x10\x90\x82\xbd\xb3\xe1\xc1g\xc8>\x120\x0c{\x1d\xbd\x1c\xd1\x7fd\xb4\xbf\x82|\xf7\x9f\xd0\xa7\x1e\x82\xc5`H\xc0\x94F3p0$H.\x0f]v3\xaa\x9b\x1c\x83EW}\xba4\x12O`_\xb5!H5\xd1 \x9a\x0c\xaa\xcd\x04\x8cE\xe7M:\xe1\x08\xfe\xefQ\xab\x02\xfe\xb7A\xeb\xb6k\xbb\x05{\xef\x8e\xde\x84\xcb\x9c\xb2\x8f\x04\xd7U\xf9\x9aQ:\xbe\xf51\xf1\x1a\xaaW\x97uR\xdd\xe7\xf59\x974\xb7\xfc5s\xd0\xc4P\xdf\xdd\"\xd7\x96\xc2\xdab7x\xb8;\xfc\x01\xfa'\x00\x00\xff\xffPK\x07\x08]\x12r 9\x03\x00\x00T \x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\x00 \x00swagger-ui-bundle.jsUT\x05\x00\x01\x80Cm8\xec\xfdyw\xdb6\xf68\x8c\xff\xffy\x15\xd7\xfa\xf6\x9b!kZ\xb1\x9d\xa5\xad\x13\xc5\x93\xc5m\xb3g\xe2\xa4\xcb\xa8\x1a\x1fZ\x82,6\x14\xa8\x90\x90m\xb5\xf2\xef\xb5\xff\x0e.\x00\x12$\x01\x10r\xdc\x99\xf9<\xcf\xc3s\xdaX\\\xb0\\\\\\\xdc\xfdn\xc1tI\xc7,\xc9h@\"`!\xfc\xf9?\x00\x00\xbd\xec\xf4w2f=\x18\x0c\x80\xad\x16$\x9b\x02\xb9\\d9+\xe0\xd6-\xd3\xd3y6Y\xa6\x04\x0e\xe5\x1f}\xf5\xf6\x00X\x10\xc2\x01\xf4T7\xfaG\x132M(\xe1-\x8a\xbf\xfa\xf1|\x02\x87\xf2G0\x1c\xe1\x80\x0e\\\x839T\x7f\xf5\x8f/\xe2\xb33\x92\x7f|\xfedI'));&\xe6'\xffs\x15\xb0YRD\xd5\xf4\xd5\xd4s\xc2\x969\xd5\xc0\xa2\x1e\xf0\xeb<\xce\x81\xc1\x00\xfe\xbcz\xf0?\xe5M\xf5*\xd0 \xd7_\xe6W2\x85\x80\x0d\xf3Q\xa8\xda\xe5?\x14t\x1e\xd4^\xe5mg|t\xc3|\xc4\xbb\xa8=\xc4\xb6\x0e \x8fZw\xd3\x03\xd8\xdak\xdf\x96]\x1c\xc0\x9fW\xb5gW\xf5N\xe5\xa8\x08\x1f\xd58N\xd3 S\x83\x8b \x8b@\xfbEC\xfe3\x85\x01l\xedj\x0f\xca\xd6\xaand\x9b\xb4?\x87\x01\x90\x08h\x7f\xcc\xa7\xc5\xff\x98\xc0\xa0\x8ep\x11\xb4@F\xfb\x99\xc4\xc5\xf5\x1a\xde\xe2\xd2\xf7\x05J\xbc\xcb\xb3\x05\xc9\xd9J~\xd9\x86\xd08\xa3\xd3\xe4l\x99\xc7\xa7)\xb1\x80\x85.\xe7D=\xdfm??#\xec\x00\xf2:\xc4\xc2j\x8e|\x0e\xb46\x87\xe6\xe8\x15\x86 Z\x93\xfe\xc9 )^\xab\xbd\xd1\xc25\xfdR+\xc1\xe7\x1a/SV\x1f\x03\x1c\xf8}\xed\xb1\xd6\xb4? X\x04\xbd\xb8\xc7\x81\x1c\x01\xabO/k.Q\xb3;\xd9\x8c\\\x99E\x9e\xb1\x8c\xef\xca\xfe,.\xde^P\xb5F\x02\x9b\xf0\xfbz\xfb\x0b\x18@\xef\xf6$)X/\x02\x1a\xd0>'\x12w\xef\xde\x13\xaf]\x05\xc3\x06~P\xbd\xff\xde\xb2 P\xb0<\x19\xb3^59\x9d\xdc\xd0\xe0\x1b\xd5T\xd4D\xb5ZS\xf5\x8f\xbe\xbdw'\x0c\xbc\xbe3\x0f\x81\xe9+-\xb6\x08S+\xd9\x05PN#\xb6\x02\x02 -XL\xc7\x9c\xbe\xb10\x046\xcb\xb3\x0b\xa0\xe4\x02>\xac\x16\xe4(\xcf\xb3<\xe8=\x8d)\xcd\x18p\xe0B\x0c\xe34.\n\x88\x0b\x88\xcb\x1ezacG\xde\xcct\xaaG\x1c\xc1\xf3\x08)\x15\x0d\xf6\xef\xef\x87\xf5M\x94\xc0\x00\x82\x1c\x06\x90\x85|\x07\xe4\xf5\x1d\x90\xc3\x81\x01y%\x9cZ\x1bO\x1f\x8f\x01\x96M8\x96t\x98\x18\xc1\x8c\xafd9\x04|\x06|\x13\xef>\x00\n\x0f\x81\xf5SB\xcf\xd8\xec\x01\xd0\xedm\xd3G\xa0f\x8d\xc4\x99\x8e\x1e\x18\xdf\xc8\xfb\x15m\x81A\xfd\xe7z\xcd\x89\x11\xe4}\x9d@I4\xe9\x9d\xc7\xe9\x92\xf4 \xa1\x90s\x88\x05y\xff\"OX\xf9F\x18A\xb0\x1bA\xa2 \x10\xf2\xc9\xe5\xfdOd\xc5igk(\x0djo\xda\xb9%\x009.\x18\x08\xb0\xf6*E*\x16h\xdb\\\x1c\x04\xb9\xbc\xcf\xbf\xd6)H\xbd\xcf+\xbf\x1d\xa5\xef\xc4\xfaHJ\xc4\xa0\xc17\xf7\xef70\xadB,N\xca\xff\x9dX\x7f\xf7\xde\x7f\x0e\xe9\xad\x04\x84\xe8\x14\xe3=\x99\x92\x9c\xd0\xb1\"\x1b\x9c\xd7\x81Y\\\xd0\xbf18%\x84BB\x13\x96\xc4iR\x90 \xec@\xb1\\\x90<\x08kop\x12C&\xbd\xd0x\x86l1\x8e\xd3%c\xb65\x18@p\x9e%\x13\xd8\x85\x01\xe7\xd2\xe0\x10zK*N\xedI\x0f\x0e\x9a(\xcc\xe9\x1bg$+\xaep\xab\xe4\xed\xf8\xc7\x04\x0e\xf4s\xe9\xaf[R\x18@\x1cp\xec\xfa6l\xaci&\x1f\xdd\xb9\xfb]\xf3Q\"\x1f\xdd\xbd\x17\x86&>0n\xb3\x05\xea|6p\x05\xc4\x8d\x1e\xc4\xb6\xb9\xae\x87'\x16\x90\xdf\xba\x05t\x99\xa6\xb8\x92\xccr\xf6\x1cs,\xe1\x8ceN\x8a\x82\xcfs\xbe,\x18\x90\x84\xcdH\x0e\xa7D4\x90\xe5\xdaa\x14\x01?\xacz\xb0\xbd1v4\xd0\x8eT\x04\x88o5d@\xab\xd7\xf9\xe8k$\xca\xc8\x19\x16,_\x8eY\x96\x9b\xa0\x0d\x88\x0f\xe9\x92\x1c\x00i3\x85\xd0d\x1c\x0d\x8c%\xbf\x14\xdd6\xb3\x96\xd0fPw[/5\xc87'\xae\xf2PPk|\x88\xd3\xcfk\xc7\x01\x13\x92\xce\xc9 \xc2\xe0\xe4\x84\x1fT\x1b\xf2\x01\xb8\x1b*\xa0\xe7\xae\x83\xd6\xbc\xd5T+|\x85\x1e\xe7y\xbc\xd2x\xc3\"M\xc6D\xdb*\xa0o\x17f=\xae\xc5\xdc\xeb\x8b/\xf9\xceqNbV;\x99\xc20\xd2\xf1\xa4\xaf-9\xe7\xc7\x1b\xdb\xc8<\x14\x03C\x0f\xd5\xee\xc5}-6\xec\x8b\x80\x84^-\xe6\xce\x16\x97U\x8b\xbf\xfa\xb6\x989[,\xaa\x16_\xfa\xb6\x98t\xcf\xfa\xd6-\xd8J\xab\xa6\x7f\xf0m\xda@\n\xb5\xa6\xb7\x82-\xc1\x1c\x91\xe1t\xe4\xd7\xe0\xd2\xb7\xc1\x85g\x83\x85o\x83\x13\xcf\x06\xd3\xee\x15_\xaf\xb1[\xaf\xe6\xc6\xbe\xe3\x9b\xb5\xc6\xa7\xffbA.X7\x16d\xea\x8fD\xfcA\xfbI\xf1\x9c\x95\x9ck,\xee\xbc$+\xc2\xc5\xf5\xa5|\x81N\xc8%\xde(\xc4\x8d\xc7E\x91\x8d\x93\x98%\xe7\xfc\xa3T\xdc|\x9bOH\x8eo\x8d\xf9\x0d\xd5\x06\xef\xba_\xb5\xc0\x07\xd0?&\xfc\xbcJ\xda\xf4c\xca\x05\xc4\xbf\xff\xfd\xe4\xe4\xf9\xeb\xd7\x1f?<~\xf2\xea\xe8\xe4\xf9\x87\xa3\xf7\xf8\xc7\xc9\xdf\xff\xdekS\xd6E\xfb\x8b\x97G\xbf\x1e=\xb3\xbc>1t\xf0\xe6\xd9\xd1/\xd6\x0ff\xed\x0f\xde\xbe\x7fv\xf4\xde\xfa\xc19\x0c\xe0^\xfb\xf6\x1c\x06\xb0\x07\x0f\x1f\xc2\xb9A\xf1\x00\x03\x98\xc3\x0e\x18\x8e\x96\x15*\x9c\xda\xf7O\x8dZ\"\xa8\x8e\xb2\xad\xbd\xd6SC3'\xd7i\xc6F\xcb/\x9c\xd8J\xfa\xd8$g\xc4\xf6\"O\x92|dn\x91\xc8\xa3\xa1lp\xd7o;]\xf2\xd3\xcc\xf6\xf0\xd8q\x12q\xbee\xbd\x86\xdd\xb6\xf4W\x13*_\xc7l\xd6\x9f\xc7\x97\xfc\x90&R\xb2\x84\x1dT\xb4\xf0c\x88\xb3Tx8\x06\xa8O\x13Rh\x06\x0f\x81>\x80\x8c\x8b\x9f\xf90\x1b\xf1\xe3j\x98\xc160\x83\xac)A\x99{\xcd\xf6\xa9s94\x9e\x8c\xf4\x8b\xe4\x0f\x05S\xfcs\x80\x0cE\xc2\xe9\x02#\xc1cq\xba\xf2'^\x1d\x7f\xb2B\x12\x99P\xba\x9c\x9f\x92\xbc\xc6\x82\xba$o\x8a\xd0\x7f\xf4\xe8\x91 \xfc\xa0\x1a\xe5|&\x15\x1c,_\xa9\xbb\xfb\xdf\xdd\xfd\xee\xfe7\xfb\xdf\xdd\xc3\x19\xd2R\x05\xfb&~cn\x85/2m\xe3\xba\x0d|\x0c\x1e\xc2.\x1c\n o\x03\xab\xc9,\xe0\x00\xcec\x97\n\xaf\xc1\x14\xda\xdaxkb\xe2\x1aM\x05rm94\xe4Zs\xe8\x08\xa1\x1e\x1e\x0e`\x87\xe2\xc9^g\xce\x0d/3x\xc4\x01\xe85\xb0w\xd6\x95\x97\xa3z-G\xee\xb9a?\xf8\xb6\xc7\xfc\xda{\xed\x018}c\xc0!P\xce]\xcb\xc5\xd6\xf77\x83m \x9c\xf5n\x087\x9cC\x12\xef%\xa8di\x9d\xf4\xfa/\x8e\xdf\xcf9\x1dhS\xe6\xdf\xf9y\xd1\xbe\xfd\x06\x06\xb0\xdf\xbe\xfd\x9e\x9fR\x95tW\x19K\x8eW\xf3\xd3,\xe5\xeb(\xfe\xea\x8bM\x9d\x19\x8c \xcf\xc4I\xa7^0\x1cm\xaf`\x00\xef9\x8e<\xb3\x1d\x01\x1f\xcd4\x87\xcd\x92\xa2O\xc9%\xf3f\xc6?\xab\x95\xb2\xe8\xa8\x94\xc1\xa4Z(\xbe\x05\xf7j\xcb6\xe4\xdf;\xa8(\x1cB^\x9e!\x19\x1c \x91v\x9e\x86\x99Y\xb2\x9bd\xd4v\xe2z\xd2\xea\xef]T\xc19$\x81~\xcequJ\x9a\x96A\xfd\xe1\xe6>\xb7~\xf4ec\x9f\xb8\x19\x83\x866H\xb3\xf4!\xcexu\xf1\x93\xb9\x0be\x91\xe1C\xb5\"\x82\xd4!\x08\xa3\x85\xdf\x8c~tw'\x0e\xd3\xf7Hk\x87\xefG|\xcb\x90\xe1\xb3\x91a\x08\x0d\xb5\xcc@?\x13\xd5\xf0\xbcF\xf4\xb3\x07\x8c\xd5\xc9\xabCXp)^]\xbcpv\x81\x1a\xa0\xe6\x91\xa3\xb6cB\xd0 \xab\x84\xe8>\xcb\x8e\xc9g\xbc\xa5Z7\xb7\x0d\x1aP\x0b\"\xc5'\x93M\x18\x95X\xe4\x02\x181\xae4(M\xa9M\xbfut\xb9 cF&\x82A\x83,\x87DIE\xa27\xc8\xa6b\xcb\x15\x11\x7f\xfa \xa5\x1b\xf1\xe8\x00\xb5\\\xb6n\x8d\xab\xc8\xaf+_d\xfb\xf5\xcb\xe0\xdeg\x19\xcab\n\xe2r\x11\x96\xed\xb5 \xfdi\x9e\xcd\x8f(\xcbW\xe5\xcb\xc4w\x94/\xbfl\x94\x86\x81\x11} |\x9cR\x8aT\xb7\x96\xdec\xfb\xc19\xb6\xe0\xcb\x07\xa7F\x13\"4\x19\xdeo\x8cL\xff\xf5QSU\xb1\xec\x98\xe5 =s)\xdd\xb4\xc1\xf6\x86\xcf\xe5\x01=\xea\xd5{\x88\xe0c\xff\xe5\xd1\xaf\xc70\x80\xe7\xfc\xef\x9f\x1e\xbf\xfax\xc4\x7f\xfd\xce\x7f\x1d\xbd\xf9\xf0\xfe9\xfe|\x13\xd5\xfaOh\xc1Q\x1f\x06\xcdQe\xcb|Le\xf2\xd9\xb3M\xd3\xd8^\\\x7fQ\x11|''%\x00{|$\x7f\xf6\"\xe8]\xf5\x9cc\x1e\xc7\xe3\x19yO\x8a\x0e\xeb\xa8\xd6\xd5\x96\xe8\x0b?\xc4sOt-e\xbd\x8f\x14\x1fL\xf0\xfc\xd2\xdf\x1c\x88\x17+\xac\xef\xb3L\xc8\xb2a$\x1eI\xc1Q\xfbH\x9e-\xf2\x05\xd74\xca\xfe\xbb\xac\x18\xdaDR\"\xbdx\x04\xa3\xd8\xd2\x01\x98{\xc8\xf2\x0d\xba\x18wv\xc1\x82_#x\x11F\xf0km\xf1\x15\xbd\xf5\\\x133\xa6\xbf\x14-\xbf\xf4\xc7\xf4\x97\x0eL\x7fY\x1b`EI=\x9b6\x0d\xf1\xe5\x0d#\xfc\x90#\xfc\xa8\x8d\xf0/o\x18S\xf6\xbcz\xf8\"Liw\xc1\x82\x1f\xc4z\xfe\xe0\xbf\x9e?8\xd6\xf3\x87\x06\xe5b_\xb6\x96/\xfaI!Z\xc8\x08\xff\xa5\xb4\xb7\x1c\xbd\xa5\xba\x96\x8f_S\xe4\xbelko\xbf\x8a\xe0\x9f\x11\xfc\x12\xc1?\xdaJ\xd3\xe3\xa3\x7f\xa0\xc2\xd4&9\x12\xe2\x10\x1dOb\xe4\xca\xd0\xa3L'6\x1b\xb1\xaf\xcc\xd2\x83\xe2/\xa5q\xe9\x13Y\x15F\x1eR\x8cDr\x83\xd5PN\xf8\x07\xc2\xc7\xadF\x077\x19\x1auN>\xa9\xf4\xf3\x96\xf9\xa3\x80\xe1\xaf\xa0\xcb\xbb\xbb\x93\x86\xb3\xa8q\xef\xa9<\x0c\x86#\xaf\x8e2KG\xea,\xaa\x0c\x18\xff\xf04\xb0 7fm\xf0+\xdeZ\xf0\x95\xd4\xb5\x12\x12\x0cG\xa1_\xbbq\x07r\x08\xa3fR\x883\x0fy@\xd9\x05 \xdb\\\xf3\x93\xea\x8d\xdc\xfc\xc6\x1f\xd5\x1b\xd4\xfc\x86Q\xca9\xac\x84\x9cR\xf5d\x16*\xbfL\xd2\x19~\x8a\xe0|\x04\xfc\xb8O6\x92x6\x92Y\x97\x1d@/\xcc\xc2\xdc\x97OO\x08r74\x8b\xc2\x8d\xe4?7\xb0\xc5\x80\x1e\x06|(W\xd7k\x08)\xf1T\x97\x11\xc9\x9a\x99\x81\x9a\xd9D\xf0\xd2\xca\x91\xf0\x03\xa2\xb2l\xecE\x10\x0b3F\x0c\x0f\x07\x90<\x80\xd8\xeeF\x07r\x1cK\xde\xc6\x90r\xd1\nv \xe6\xb2\x95\xc5\xad\x0e\xd4b\x0b\xbd\x1e\x0b\x96\xc3\xbdQ\x84\x8a\xbb\xe5pw\xc4\xbf\x8c\x80\x84\xa5\xa6$\x86mh+\xe1\xa0%~\xa9K}\xd6zhU\xfb\x936\xab\x8c\x9et~Df\xfc\x17/\x93q\x85\xac\x90\x15+\xe7\x02\x0c\xc7\xc6\x8f\x81\x93\xa5P\x97r\xfe\xf0_X\x05\xfc\xedmx\x04 \x1c:\x1a\x07?u\xa7\xba\xacjOu]\xc1\x01|F\x07F.\xcaKL\x12\xe8L\x86{\x8d\x93\xa8\xfc\xa8}\xdb\x03M\xb2\xfc\x1ax2\xb5;\xb1*\xca\xa4y\x94\x0b_L\x8eR\x11XQ\x83\xe3M\xfd\x0c\xa3\xd5\xbe\x91\xba\xcf\x0c\x9bx\x19\xd0\xb0?\x8f\x17\xd5\xba\xbb\xda\x05m\xd2\x08Q\x0c\x1d\xa06\x10:Ts\x13b\x1d\xd2\xaf\xff\x81!\xa9-\xd0^t\xb4\xeaD\xd0\xeb\x99|\xcd\xf8\xd5\xeb5=\xf7\xf0;N\xd3\x17\xde*\xab\x85\xfbT1\xf0#/9\x1b\xc1\xa1\xb4 \\:\x7f\x95\x14\"\nfB\xc4\xf3_\xeb\xcf_\xc7\x0b\xa1\xbb\xf2\x1a\xce\xc4=\x1ce=\xae\xf9]\x0d\x14O\xdd\xd4\xaa\xe9\xaf\xf9Acf\xdf\x11\x1cwHe\xbe$\xb0%\xf5\xef\x0c-\xcc%Fm\xd9\x18%\xc1\x82j/\xeem\xa0\xa6\x97N\x08o\xa7V#\x06So\xb8\xb6f \xb8y\xf9f\x10\x868\xa1\x00=\x0f\xf4\xbb\x9bN\x10\xec\x93\xf4\xa7f[f\xc7Q\xd2'\x9f\x97qZ\xa0J\xde\xf4\x02\xd3^\xd8Ro\x07\xcc\x93#?\xf7Z\xf2\xee\xe5\x8d\x03\x11M\xa4\xd9\xb5+\x87\x07\xed&+o\xca\xc7\xda\xcd\xe6\xe7''\xb3\xb8\x98\xb5\x1a\xa8n\x97\xaf\xd4\x1e\xac\xd7B\x7f\xcco.\xe5\xb0\nu\xa3\x907\xc6\xea\xc6\x18=\xa5;\x90\xb2\xe9\xc1!\x0d\xd1\xf8\xdb \x1b\xe5Z\x81\x9e}\xe6\xb6\xf9H\\\xac\x06J\x88})#\x04\x1d\xe6\x8f>9'\xf9*\xe8T\xa8\xa8K\xb1B9\xda\x00\x83P\xec\x82Nv\"\xe3@\x98\x91 CNQ8/\x06\x94\xc3\x15o\xeeb\\\xa1\xed(\x00\xf4\xdf\x97\xfdq.\xc2c\x8f\xa8q\xda\x16\xa8\xe5gc\xee\xbc\xf1\xaaZ@\x0b\xcd\xd1\xd5\xbe\x88m\xda\x0d\xdbB\x90\xb4 \x0exg\x0d\x0f\xf9\xe6\xa5xK\xc7\x12\x10\xa9\x05\x81\x01$f\x08\x1b\xa17\x15\xc10\xc6/\x16 \xb6\x8frE*\xd1\xc7\x14<\xa8_\x1c\x9e\x9c\x13\xdd\xc2\xd8\xb4\x00\x9d\xa43\xfe{\x86<\x01\xe9\x9f\x11\xf4\x8a\\\x85\xfc \xbf\xab\xddB\x1cQ\x185\x95\x1ek\x06\x8a \x885V\xf1q\xaa\x11\x13\xbe\xa8\x0b/\xba7w\xd3\xbd-T4\xea\xf1bsM\x02\xe2\x1c\xbbj\xc0\x8c\x8fB\x9f\xa3\xbc\x1e\x1a\xfa\xa4\x86/\xcb\x1e\xdc\x86\xdd\xd2\x9fE\xfa\xbd\x84\x91zC}\xe8:\xd8\xfeY\x0e\xed\x9ff\xc4\xf9\xa7\xb4\x19tl5\x1b\xb4\xce:\xa0U\x8b\x8c\x11*\x02O_\xa1\x15q9\x0b\x99\x97b\xd5X\n\xad\x0d\xf3j\x9c\x91@\xbaZE\xa0\xe2\xfb\nF\x16\x10\xc3\xfb\x98\x9e\x118]\xc1n/\x8cpo\xe19\xb4\x1b\xd5W \x0d5\xe8[z\x1bv\xc3\x08i\xba\xf6\x02\xc5e\x94K\x18\x9f\x16\xe8z\xc8\xe0\xa1\xe4\xd8\xf8\xdb;T\x99pN\n\x16\xe75\xdd&\xa1\x13M\xb5y\x82C\xc3\xc1\xeaX\xa3\xa3\x07\xfe=&I\x1a\x04\x0cv8\x01\xbe\x0d\x94\x8bV!\x97\xcd7\xc3\x9d_JX\xfeb\xc6\x9d_\xbe\x0cwN\xcd\xbaD\x81/\x9aJ\xe9\xf1i\xc1\xf2x\xcc\x9a\x96 K\xb3'\xc4\xe5fz\xe1|z$\x9f\xea\x0f53\xd6\xf0\x1f#\x15`\x1a\x10\x12\xc1K\x8e\x19z\xdc\xc3\x19\xe9\x0c\x04\x82\x86\x15\x86\x93G\x94\x0f4M\xfb\xf0\x932g\x84\xa3\xb6gc\xa3\xcf\x8dL25\x7fY\xadG\xe9![S-U\x1e\xb2\x03\xc8\x85\x8b\xac\x15W\xa4\x8a\x88\x04t\xc80\xecn\x07=\xba\xb2\x11\n\x7f\xbc\xa3jgf\x1c\x15\xadT;\xf3\x9a\xac\x9fu\xc84Q\xe3\x14Z\x937\xbe\x95\x9956\x9bikJ \xaa7\xbd\\M\xa8/\xf4\xc3CbD\xf9Z\xdf\xb3\xb8p&\x02\x80\xa6\xa5S4\xdd\x08\x93o\xa9\x02\x1a\xbd|\xe9\xc6\x12\x9d\x8a\x9dU\x99\xaa\"\xc9V\xeb;-\x11;-\xe1;-{\x00\x89;\x16:\xe6\xdf\xe3bf\xb0\x03 \x1c@b\xd1\xf35vf<\x8a n\xee\xc6\xc4\xa8\xb4\xb5\n\xa3\x89\x17\xc8\xae\xb3=%\xb8\xac\xfbS\x03\xa1uw\xe6\x9d{8\xb9\x89=\xbc\xd9*(\xc8\xa1\xa65\xfb\xf7\xed\xf9\x98\xef\xf9\xd8o\x8fk\x8b8\x9cU\x87\x1c\x95\x87\x1c5\xee\x8b\xd2[\xc5c\xad\x91\xf7\x0dk\xbb\xb2&4iB\x86\x85{V\xd8\xf2SP7\xcb\x86v\x94\xb1\xe8$\x9e\x04\xd4\"\x83\x96\xbb8{\x00[\x01F\x9cKyT\x08\xa4\x18\x8b\xb7'\xb4\x10A&d\xe2\x08\xf2\xedm\xb9\xab\x1e\xd8\xa5\x91\xbc s#L+}\xf5\x8d\x025\xcb7\x86\xaaE\x9d\xf3D\xd7\x12\x8b\xed\xf2\xbd\xa5Y\xcb\nl\xbe\xd5\x98\xb6\x0e\x1dZ\x0e\\$\xe1\x8c\x8e{@,\x8dX(\xaf\x8d\x10\xe4\x12\xe5\xf3\xff\x02\x94\xaf\x0e\x15\xfd\x14)C\x08D\xca\xa2\xb6\x83\x80~\xa0\x94\xc6\xa8\x07\x1e\xcc[6LF\x11'T\xadC\xc226\xbeK\xa8\xa6%\x12\xbb\xe4A\x17\xdd\xa4.m\x12\x9a\xd8\x86\xc9H\x84C\x96c\x8b\xeb\x03;\xcdI\xfc\xa9\xbd\xa06lk\x1d[\xc6\xe5\xfd\x8f\xed\xbe\xc6\xc2Z \x9ai\xb1\x8d/\xdf\x08\xab\x8a+\x01\x8f\xaac\xb5Ka\xd8\xbdQA\xc1\x0d\x11\xa5\x02\x9eC\xb1(\x82\xf2\xe4\x1e6\xbe\xe6\xb4.+\xf67\x1f\xfa3\xbcsI\x03\xe6\xe4\xfa.v\x0dA\x1b\x0e\xa1\xf7\x9e,H\xcc`8\xea\xc1A\xf5\x0b\xbd \x98\xa6\x16\xda\x86^u\x0f\xbf\xe5wX2'\x05\xb4\x9d\x8e\xe7\xd7g\xcaML\xb8\x18\x82\x81\x01\xaf\xf5\x93\xd0q\xba\x9c\x10o.|Ft\xc5W;*\xab\xd1<\xa6,\xf0\x99Hm\xffpPYQ^\x8b\xd9\x13S\x85\x03\xa5\xad\xab\x8d\xec\x83\xb0\x13\xc3\x8e\x08\xa6k2\n\xcd\x91\xe6\xe4\x9c\xe4\xc5&n\xda\x1dp\x9d\x90\xcb\xb7\xd3\xeb\x83\x15\x0eQc\xb8\xb3\xe7\xec&\x8d\x0b\xf6\xfc\x06\xba\xaa0\xb4\xb3\xcb\xeb\x0bS*UT\xb9\xc4\x98+\xcaJ\xb0\xca\x03\xa36\\\xda<\xd1\xa8S A\xbd\xe6\xb2\xb9\x94\xb3\x11\xab\xba\x19\xb1Vl&<\x04\xaa(N\xc5\x02Q \x89\xd0\x98\xf0F]7\"~xP\xd8\x1a4\xa5\x91\xd2\x13\x0fI]\xf5\x0e\x87m\xcc\xd4\xa6z\xde\xb6\xf7s\xfa\xbe\x92\xf4}u\xc3\xf4\x1dU\xc6\x8a\xbc\x8b\x1f\x1au\x17\xda\xddm\xe8\xf5\xfb\xfd\xea.\xa1\x13\xd8\x86@\x08\x15\xeaE\xb2\xe0\xed\xc1\xe9\xaa\xf69Y\xf0\x86{!\x9e\x07\xed\x93`u\xb3'\x81\x1an\xa5\x8b\x84\xaf\xebCi\x9d\x11\xabk\x9d\x11\x8as\x08\x08\xec\xe8}\x87p[\xeb\xcf\xba?0@zW\x18\xe452!n\xf05B\x9d\xf84\xcd\x0c\xb6\x87\xc6\x90\xbd\xcf\x9d\xc6\xa1Rv\xaa\x1d.\xe8R \x02\xb2\xcb\xa7\x91\xb0\x15\xe0\x19S\xdd\x0d\xe1\xe1\xa0\xf4-]\x91`7\x82\xddP\x1eO+\x89\xdcg\x84\x05\xbaU@\x99\x0c\xf8}f\xb8\x8f k\x9f]\xab\xeb\x1c6\xe7eTemy,\xf6-\xf8\xbf:\x92\x0c\x06|.vi@d\x17p\xaf3\x94\xf6D\xb5\xd0\xb5\xf3 4\x13mp\x89\x03\xed\xc3j\xf5\x85\xe7#\x0eGB\xd4@sV7s\x16V\xd8\x8dz\xc3J$\xe0\x90\x93\xf2`k\x03S\xf8\x1a\xf3\xe0iw\xeb*G\xeaT9\xd6%\xc4\x08\x12\xa3\x06\xd1\xbcl\x19l\x8b\x11\xed\xf0\x01\xe4\xfe\x0b\xd4\x92\xd7\x8c\x00\xdc\xfc\x00\xae\x80g\x1co\x03\xa0\x969\xf9\x02\xd9\x0c\xce\x9b8\xec\x95 \x9d9\xd5!\x0d\xe8\xf3E\x7f\x84\x16\xc9\xbf\x98\x03P\xca\x17\x94\xd7c\x1f\x91kuC\x0c\xc1\x8a4\x16F\xf8}\xc8\x1fe\xb8\x1d\x9aU\xc5\x13\xfegy_\x92,\xf9 \x9eq\xe7ed\x91\x81\x8f8%*\x9d\xd3 \x89\xe0\x94\xe0\x9f\x17\xd5\x9fG\xea\xcfSRF\xf4\x887\xb5@\x1e\xf1\xbe\x0c\xf29jH0|\xa1/\x89-\xbb\x04\x9el\xc9|\x89 &v\xf6\xab\xd3\x8e\xdf\x0b\xaa$,\x11\xec\x87*\x7f\x06\xbe~\xe0\xbfk\xee\xdf\xbbw\xe7\x1e\xdc\xe2\xe7\xd9\x9a\x13s\xfb\xc6)\xdfd\xe2M;\x92\xe3^\xd9F\xb7\xbbG\x8f\x1e\xc1\xde\xfdP\xde\xe1O\x02V\xde|\xf8\x10\xf6\xee\x8b\xdc3!\xac\x9b\xce\xf8\xb6P\xa6\xe3._Il\x1en\xc1\xde\xee7w\xbe\xb9\xbb\xf7\xed\xfe]X\xc3\x9d\xfd\xfd\xbd\xfd\xfd{w\xbf\xe1O\xfc\x9c2\x9fZ:\xd2)&\xac\xd7\x8e\xe0\xeb\x92\x86Z4\xd5\xdd>\x8f\xaa\xa3\xb6\x07\xa3\xbb\xe3\xae\x9e\xb7\x9a#4Px\xc5\x18\xa8qY\xe6P\xa5=\x18\xd8}\xce\x12\xf4)\xdc\x92C\x15\x0e;\xc2\xa7\xc21P\xd0\xf0t\x17\xd66\xe7(q\xec\x8d\xe0\xbd\x80\xf5\x1b\x993\x83`:\x1cxF0\xf1\x19>\xe7T\x1c\x1b\xe7K}\x9d,\x0bp :\xdb\x08\xc7gq1{\x9aM\x88\x06\x19u\xcb\xa4\\\xc4\x96\xaa\x90-\x1d\xa4\x9e \xb43\x9e\x1f\x9a\xbe\xaa\x08\xbfw\xc2c\x8d\x84a\x97\x1a3\xa9\x9c\x0b\xcb\xaf\xc9\xf09\x19y}\xb9\xf5\xd6:n\xb05\xceOS\xb4q?/\x8e\xaaT\xd8\xe8\x0egz\xe25\x16[g\xdd\xe0\xd5\xbf\x96\xa3\xa0\xd9\x84|X-\xf8\x96\xdb\x0d\xa1\xb8H\xd8x\x06Au\xbf\xab)~\x8d\xe3\x82\xc0\xdeA\xe7{\xa0\xd1\xfe\xfe\x92&\x9f\x97\xe4\xf93\xfb\x1c\xd5\x85\xcd\x7f\xb7a\xf3\x93l\x8c\x01\xc3G)\xe1\xff\x88\xc96n\x96cp6mVj\x83\xdcR\xdaj\x19\xdf3\x7f\xcd\x97k{\xfb5\x89\xf4\xa3\xef\x16\xbc\x16{\xff5\xee}G\x88\xc8\x07\x12r\xac/\xa4,z=G\xd7\x06\n=V6\xd5\x01\xfe@\x97\xe7\xa6\xc7`\xefMFw\xc8%#\xb4H\xaa@\xc2\x02\xe2\x9c`\x92\xe38M\xb3\x0b2\x81\xb8\x80OdU\xf4\x9b\x89\xb3\x9b\xdd\xf3\x0de-n\xf1\xdc\x98\xc3X\xbf|\xd2\x11\xab\xab\xbb*\x86~iI\x8c;\xde\x94|\xbay\xf1\x01\xcc~\xb1\xea\xc2\x15j\xac\xc3\xa6$C\xb2\xc9Z$\x89\xc6\xc1\x9b>\x08\xad\x0d\xb9\xd5m\xfa\xa5\xcb\xda\xfe=\xf7\xe3\xc5\"]I6\xde\x12\xd1\xaf_W\x91\x83L\xf23\xb0\x03\xb2\xddD\xb0\xe6\x94^\x91\xbc\x16\xde\x7f\xa4\x08!\x96AA\x18\xc4@\xf9>\xa8 \xa7\xc6\x08\x19\x95{\xc2\x89\xfa\xfc*\xe7`\x9f\xfd\x06\xf4\xc4y\xeaot\xda+\xe5kI\xd68\xc3\xa0e\xb41\xe6\x03h@\xeb'4]\xf1&\x85\xd6\x14\xd5\xa4c\xe1\xd4{J\x80s\x0fd\xd2\xf7\xf4\"\xfdd\xe1\xedKu\x0c\x13\x8c\x92f\xa1 \xf5b\x16\xfc\x85;{\xf0\xb5HU\xd8\x1f\xcf\xe2\x9c3/\x8fY@Q\x98\xb1\x8aG\xc7\xa4\xed#\xad\xff\xe2\xbd?&U\xc6\x84\xa48*ic\x9bj\xbc\xf5\xdaa,_9\xf0V\xa9;\x8d4\xf3\xcf\xab\x08z\x7f\xefE\x82]\xb4\xea\x04\xc6\xb18\xe2]{\\\xf6cs\xf57\xa0Y\xd8\x16\x97\xdf\x91\x08>XE\xe6\x9fI\xfc\xe9u\xdc\xd02\n\x06/xGd\xe6\x02\xf9\x92\xa1qqF\xb6\xa1\xfc\x1c;<9I\xe6\xf3%\x92p\x8em''\x8d\x14\xed\x1d)\"\x03lE\xfc\x0e\x9e\x93&\xd2\xf3\xfe\x7f\xe7o\xec\xdd7$\xa6\xe4\x0f\xf6\xef\x192\x1f\xbf\xb7\x0cY\xb2\xf86)\xfa\x95e\x03\x9c\x91@\xc4f\xa1tV\xb9\xcd/H>\xcd\xf2\xb9P\x7f\xc7\xa2\x8d\x8b\x84\xcd \xa6\x90\xd0iB\x13F\xa0H\xfe \xbe;\xf0\xa3[\x8cw&\x0d\xfbE$\x0d\xfb\x8cMp\xfeb\x1c\x94\xf9\xd3\xf9\xb3>\x1f\xd9\xeb%\x8byO\x85\x16\xd6\xd2\xa5\xab\xce\xad\xe9\xed^\x91\x80*-?\xedO\xb3\xfc(\x1e\xcfj\xf1V\xc6@\x06u)R\x8a\xdc\x15m\xa9\x9b\xd4e\x8a\x82\xf6\x03\xe7g\xef\\ \x7f\x90\x8el\xe6\x1fI\x04'|\x9e\x1f\x89G2\x9d\xd2| B\x8a\xcb\x038r\xa9\x88\\\x8bd%!\x1d\x15\x86`{\x00\xfb]\xa2\x14\xda\x85\xe1Q\x95@\xc6p,\xbfN\x8a\"\xa1g\x82 \xc3^?\x91\x95\xc8f\xc1\x86\xd4\x94fR]\x82y\xe6/E\xfcU\xde\x97-\xdc\xbds\x9d\x11\xfc\xd76_\n\x85\xa7\x96\x01\xeau\xbc\xb0\xa6<\xfb\xf8\x85\x96\xc5\x93<\xcb*\x959\xff\x81\xa2s\x19K#\xf26\x85&\x93b\xad\xebb\xa3\xae\xff\xa1'\x85r\xcf\xa9 \xec9\xdd\xa0i\x9c\xc8r1\x89\x19y\x8e/\xaf\x0c\xd5\x0cm\xdfn\xba\xb29\x99g\xe7\xa4S\xd26\xccz\xe5nxBR\xc2'\xe0\xdbtk\xd6\xbeS^m:e\xd1IsA\xdc\x89\xa3\x85\x08Y\x92\x17\xa5G;\x94\xae \xa12\xce\x94\x13\x18\x92\x91l\xd4c,m\xf4\xb0\x8c\x06\x83]\xd1)R\xc6b\n\x14w\xf8\xc8\x96$\xda'\x91\xc4\xb9\x8c\x03\x15\xa6\x8d\x95]'\x1aw\xfa\xe2qr\x17K?<;Q<\x97)c\x12YM\xcbb\xd6RW\x01\x03\xc8\x82\xa5\x83\x06\xca\xe5*p\x02K\xe9\xac\xdb\x8e!\x03\xab\xd4qF\x82\x04cH\xd0p\xc3\xf7n\x04\xbd\x84\x9e\xc7i2\xe1\x94\xf8]\xccf69\x88\xcf&\x85\x01\xc4.\x0fT\xfe\xd2XNy\xc5\xa7\x8c\xd4*\xe5\xfb\xc9\xfe\x01?\x07I0\xae\x16\xd0\xa9(\x9d\xe2\xec\xc7r\xf6\xe2\xd7\x8a\xff\x92\xbb=H9\xbe\x06I\xc5\xcb\xb0\x10\xcf\x8e4\x82\xa9\x81\x07\x90{\x9eR\xd4\xe9Z\"\x1ee\xdfy\xd9\x9b\xe4\x9aZu\xd0\x1a;`\x9c\x92\xd8Y\x94Hk\xbc\xed\x16\xc3\x84?\x84Ym\xc0:\xea\x8d\xb3\xee\xf6k2P\xe7\x04J\x8b,_\xa9\xb8x-t\x11&\x06@\x8e\x86 b\xb1\xfeE\\<\x16\xf44@\x1f\xb6\xfe\xc9 \xa1\xc52'o9\xbd\x0e\xea\xc4[\xb1R\xce\x81\x97\xbd{\xee\xc1\xd6\xf9P?7\xf4\xd1pQ\xec\xd2\x0d\xb6\xb8x\xae41\x9b\xf5\xaf\xf7\xd3\xb12%\xc86\xebA\x9e[\xce\xb67spR\x1a\x11r\x01/\xfde\x9e\x8d\xbc\xd0\xbe\xd4\x89Y;\xdcKo\x1b\x94\x03\xdb\x99E:\x88\x08\xba3\x93\x80a\x82\x19\x86\x19eL6\xf7H\x94}\xea\x80\x80\xb6\xda\x9d{K\xed\x98\x8a\xc11`+?\xd2\xfeI*\xd6Fgk\xa2*\xaf\x03\xb24\xc8\xe15\x1a\xd2r?\xe8\x0c\xce\x9edp\x0c\xd3I\n.\xb9\x0f\xe0\xb3\xc1s\xe8{\x12\x01\xb2W\x8dd\xc0\xaf\x1f\xbf\xb3TO{\xc2\xdf\xd6\x81dS\x0f\xfedO\xfc\x81\xc3oOH&*j\x19\x1f\xac5>\x9c @,\x9d\x9c&l\x8e\xe0PN\xb14\x13.\xc8\xd4\xab\xcf\x9f\xaf\xd3\xe78[Rv\xed._\\\xa7\xcbOd\xf5\xa3`\x8aY\x0b\xba~\xdd\xfezs\xdd\xae\xbc;}\xd9\xdd\xe9 \x13\xa5FK\xa7\xe6*\xc2\x86V\xbe\xcd\xf1\xf8\x93H\xd3\xa9(\xcaW$\x90\xbf\xfc\xb4\xa1?t\xa6x\x14\x15\x90D\xc6\xaaVRJ[\xb3_u6k\xa6m\x1ce\xac\xe5o\xd1\xab\xf8\xc0\xe6\x8eyr\xb2\xc8\xc9\xb9\xc9\x14\xec\x97\x85\xe5\x9f\xbeIQ\xeb\xc5_\x9f8\xf2\xf6fJ\xaa#\x11d\xa5H\xc7\xf0\x87F\xe9\xa8\xb8!\xa5\xbb\\\xfc\xaa\x13\xbd\xcck\n\xbf8\x93R\x7f\x8fz\xed\xe0{>\xa0\x7f\x92`\xd73\xff\xdd?\x9c\xb8z.k\x92\x9b\x8d\x9c\n\x15-\xab\xadt8\x17\xc1\xa9\xc5\x9d\x12d~\xd8\x8b\xe0\xc4\xa1\xbc\xc1\x04pL\xf5\x86\x91/\n\xbc\x11h\xcaU\xb1\xb8I\x04q\x18\xc1\x96T}T~U\xe6\x0eD\x1e\\\x19~\x18$\xb2P\xd7!\xe7\x02\xa4\xf6`g\x0fK~\x1d4\xab\xc9\xf1\xeb\xcae\n\x17zvl\xc6g\x14{U\xf9\xc6\x9fp\x9bW\x93\x1cZ\xa1'\x8a\x8f\x19\x1f\x9b\x82@m\xc8C\xea*\x8b\xb2>c\x16\x95\xd4\x07Q\x97\xb4\xd5\x14\xa4\xa5\xa3@O\xb8\\p\x08\x19\xee6\x93\xbe\xc2\x82\x8f\xd2\xe9\xa6\xd4/\x89\x05\x8d`\xe9\xe4U\xb8D%$\xb6\xc0\xf8\xe9\x01GD\xb9\x9e\x84\xf3#G\xc12\x8c\xe0(\x881\xeb\xc3\x05?'D\x0e\xd7!\xff\xcc7\x9d;cn\x1e\xaa\x95\xa8\xf4W\xe1\xf6\xd9\xba\xff\xc2\xcf\x13\x976\x80c\xea[l\xcc\xf2\x08\x1b\x0c\xf8\x02h\xac\xf3\x8br\xa6\xb2\xbaP\x04\x99\xc9\x96\x83\xbbW$\xde\x0e\xaa$_U\xcb\x07\xda\xdf\x8f\x1e=\xe2\xf4\xe3\x16\x9c\x99\xf7\xf9\xb2\xde\x08\xba\xe9k\x1fY),\x1f\xef\x8f8^\xaci\x1b\xc3Z\xfc\xb1\xc4qI\xbd\xea\xb0\x82\nl\xc3\xb9\x84\xccH\xe8\x15\x07\xf5\xd5\xcdB\xfe\xe5C\xf1\x1d\xe1+\x0d\x070L\" \xbeK\x9e3\x17\xbd\xac\x12k`\xf5\x82Z\x86\x02Z\x9a\xe8:\x12\xdfph\xd1a2\xb2\xd3\xcc\x02M\xb46\xeds\x1c,\xd1-:\xe0\xaf\x15\xf5\x8c\xc6>~ \xd3V4\xa1\xba\xae\xc2\x90\x1f_\x8be1\x0b\x0c\x9eEV\xf2\x12+\xa0e~@\xce\x9c@.w=zmUj\x95[\xb7\x00\xb3\xb0\xd6\xd4+\"'c\x99\xd8Wl\x7f?\xce\x12\xc1S\x82\xc9h\x87\xbc\xa3QX\xe3\xc8\x98\x0fG\xa6.\xe5l\xc0\x86\xb6\x04x\xea\xca\x10\xab%\xf9'5\x115FEKl\xad\xfe\x01F.J]\n\xd9\xcd\xb4\x99wU8\x8d\xf2|\n\x0b\x90\xd1a\x9a\x82W\xc9\x99\xd6\x8e\xb9d\xb7\xe0\xb8\x85\x14\xa9\xe8\xb2\xf9\x1f\"\x7f\x9dJ\xdb\xff\x0e\xec\xc1!L\xfa\x8bLT\x82\x98\x0cSN\x8dZ7\x86|\xe4\x9c\x1f\x9f\x08\x06S\xfc\x0e#\xec9hh\xff&\x95)\\ \xcc\x11L\xbaX\xd2\xab\x08~\xbc693F\x97!vY6+\n\xf5\\\\ \x82z\xfdp\x11\xf9IP\xf6\xb1hF\x12EC\x84\xa6\xd7J\xd8x\xc3\\\xce\xb9%\xb8\xbb24\x1b\x95\xb3\xc3%\x13\x8f03\xf2H\xc4q \x19\x89\x99\xd8\x89&x\xaeM\x17k\x99\xa1U\x02\xe8\xa7$\xc8m\xa0\xd2\x04D&Y\x1e\x8a@b\x0e\xa9\xb2P\xf0]\x9a\x9f\xa7u\x18\x9a_\x1acL\xe5\xd6\x00\x82\x14n\x81 \xb5\x91\xae!\xa1\xce\x1a\xca\x1c3AUtz\xc9D\x93\x08|s\xe7\x0b5B\\.\xf3;|\xef\x8d\xe1\x10\x16\xc3\xe9\x08\xdc!\xeb3\xa1(\x9b\x08\x0b\x8cX\xe8\xfaZ\x99g'\xd4\x04\x13\x8f\x83B\xc0\x01E\x97\x85F\xde\xc7N\xf2\xeep\xf3\xaaU\xfc\x92\x0c\x01\xdf\xcf\xa2\xde\xcc<\x8c\x103v\x1fHV\x9f>\x80%\xa6\xf9\xe1\xb81\x80\xbd\x10\xe2\xe1r\x84hp\x0b5\x0bl\x98lo\x8f\x1c5\xeb@\x13J\x87\xf9H\xa8\xb8\x84/|\x80 \x05\xb7\xb1\xda\x98\x81\x90\xf0\xc7\x8b\x08\xd2\x08\x96\x11\xcc,\x90\x94\xe79\xff\xbf\x08S/\xa1\xc4\xe5?\x16,\x86{\xf0/\x98j\x9c\x8b\xba\xe3h\x0f?\xde357\xab\xda\x99\x99\x11\xf1tSr\x7f\"\xd1m\x86\x14\xfc\x00R\xf8\x17\x92\xfd\x14\xd6`\xc1\xd0\x0b\xed\x93\x82\x05\x8b\x08\xa6\x11\xcc\"8\x0d\x9b\x01\xf8\x1d\xe2\xc7yY\xed\xa3\xf2\x80\xb0\x1f\xb5B\xbdZ\xa6\xbf\xc9\xb5\x08Z!\xc5P\x80O\xb9\xa7\x1eb\x99=Q\xf3\xacslz\x97\x88\xf6\xf5\x0e\xdd*\x8d\xa4\xfa\xcc1\x06\xb7\xa2#\xe9\x92\x16\xf0%\xb5L5\x00\xa8\xbbn\x19\xa2\x81_0\x80\xafH\x90X\xed\xe7\xe0\x14\x17\xc6\x19e \xdd\xa8\xf8C\xbb\x7f\xedW_\xf8\xccv\xecj\xa8\xb6\xa7mct\xe6J\xb5\xe6Im\x10\x90:0\xf9*\xa7|\x06s\xb8\x0dw\xdb-\x8f\xd5\xb3\xfd\xf6\xb3i\xf9\x9d\xcds\x7fa\xf1\x188\x97\xb1CG\xc6\x80a\xe4\x9b\xbb\xf3XZ\xe4\xea \xe6\xc9+\xa9\x9d\x99/\xa4\x18:\xec\xaa\xe7D\xdd5\x1e\xc4`r\xa9\x03\n^\x89\xe3:\x87G\"kt\x0e\x0fa\x0e\x87p\x81\x99\x07\xf2\x08U\x0c\x18g\x8a\x85 X@\xfb,\x13\xf2w\x88ei\xd9\xc6n1\xe8'r\x9c\xfc!z6\xa4\x01\xe9\xd2\xf4\x96\x9a\xda\x0e\x7f\x13\x93\x17\x89\x9f\xa7\xc5\xc4\xed0\xa2\xe5\x01\x99\xb1\x8e< \x0b\x16\xc1\x05\xe1l2\xf3\xc8\x03\xa2 \x1f\x81=\xc6r\xc1\xb4#\xeeKsZ\xbcJ\n\x06\xc3^\x04\xbdQ;\xa9E\xad'\xcf\xa4\x16\x89\xaa\x15_%\xc5\x0f\xcb\xac\xe4\xa4\x9e\x95\xdcq\x9ar\x01\xb6d-1I3\x8e<\xcb\x93\xb3\xc4\xe6\xd9\xa6d.\xde\x13\xed\x8b2\xa1\x04n\xc1\x99!\x14\xd2\n '\x0c6\xcb\xae\xe1k\xbf@\x901\x04\x99d\xabjU\xf3\x1dE\xa00\xb1\x7f\xe5\xc4\xc6\xe0\xa1\x96\x0dvs\x975\xc0c\xe1!\xec\xc2!|\x92\x19\x0cq\x9b\xed\xca\x08SqsW\xa8\x1f\xf7\xc43f\x8c.\x03\xb0'\xd8c\xe8\xfb\xa4\x16\xd3\xfcNe\xcf9aq\x92\xba\x19*\xe5\xdeo})q\x06\n \x14\xdfb\x94\xc08^\xc4\xe3\x84\xad\x84A|\x00\x97Xo\xbb\x195 \xe4A\x14\xb12\xf1R\xd6x\x89\xf4ORrN\xd2\xea]\xfb\"n%~\xe1\x06\x89\x08\x9b\xa8BL\xcbuV^\xf6b\x14\x1c^\x9b\xb8\xdc;7\xd3\x05\x82E\xac\x14~\xad \xa4\xcf13z\x17^\xb9\xe2,k\xdbj\xb3\xf4-H \xcaJ\x1c\x9aU\x03 \xcb,\x992T\\h2\xaf\xcah\xaf^R\xba\x0d\xf1p\x91&c\xe4\xdb\xf6lQ\xbb\xb5\xc1&\xb4 \xf9&d\xa0\xd1\xcbn'8\xfe\x0d\xc9$tjZ\xfeTK\xab'\x9b\xc0\x15\xe6\xf8\xd3\xc8>!%%\x81j\xd7NE\xc1\x19)'(\x16\xcbb\xd6\x05 %\xbcU\x11\xfa\x96]\xae\xc1\xc9\xca \xe1\x1b\x16\xbai%\xe0\x9f\x90\x11\x91dQ\xd9R-;\xbe\xe6\x16\xbc\x8b2\xbb\x96\x16\x11%w*\xe8*l\xe3\x1e\x1e\xe6^%\xd9\xea`\xcb|\xf3:|R\x87\xecn\x04;{\xeeV\x97\x14wWW\xcb\xad\xf5\xb8\x16\xb0\xad\xa1a\x9f\xf0\xc8\xd9\xf1\x05\xb3#\xfbd\x99HnH7\x07\xb1\x17(\x9a@\xee\x00\xf0&\x89W\x1e\xfb'^i\xf7\xe1\x95\x90\xa3\xd9\x91o\xe2\x95vw\x1b\xe4\x19y\xec\x97g\xc4\xdc\x87\xd7\xb4\xce\xaf\x93\xd7\xe3qg\x9e\x91&\x9fx,\x08\xad\xd7\x89\xa6o\xc2v\x11\x8dz\xcb\xbe\xf5\x97\xce\xbf\xa8\xee_9\"Y\xe2\xaf\xac\xfa\xe7\x1e\xddfI\x19\xca\xedi\x17gOJ\xe4\xb3\xaf\xcd\x06\x05a0\x14\xb1\xabB.\x9e\xa8\xa7\xec\xdfW\x04\x86b\xd1\xd6\x8d)\xd0F\xd9)\x9aur\xa5\xfe\xd8 _\xbc\x02\xa1s@\xa1\x04\xc1\xa2\xd7w\xa6\xd7\xad\xec\xdc\x98\xc8_\x92d\xe2\x82\x05:\x9b\x135\xb8\x9c\x1a\x87\xa3s7\x91\xc6\xdcl\x94\x90\xc2\xb4\\I\x81\x12\xf6\x00&\xac\xad\xc1\x9a\xb1v\xe2\x89W\xcf\x8f?X2O\x9c\xa3\x05]\x83\x9cM\x7f5gV<\xc0\xb1\xa3h\xac%-\xa8f\xd2\x8cn\xd3\x7f\x9d\xb3\xe1\x8c\xa9`\x90sV\x05\x83\x9c\xb32\x18\xe4\x9c\x95\x89\"\x9f\xc8\x9c\x91\xda\xbbx\xbf|[\xbd\xa5~\xe1\x8b\xa5\xfd\xed\x89\xb2\xc5i\xb7\xd5\x17\xea\x17>\xaaR{=)\xf3|U\x0f\xcadOOj\xd9\x9f\xf0\x85f\xe2\xa0'\x0d\x89\x19_\xd2\x93\xf4<\xd1r\xf6\xc8\x87z\x0e\x9d'\xb5\xa4:\xa2\x0b=\x03\xce\x13=#N\x04\xf3\xb6\x08\xf4\x84L\xb3\xdcd}\xb4iZh\xe9\xd0\x84\xde\xcc\x0c#\xdb\xca\x8d\x81\xeb\\\x86^hL\x97Y\xbb\x88\xfaC\xe1\x13e\x0e\xad\x15\x0e\x80\x8f\\\xadK=\xe1p\xc4O2s7\x99\xf4\xbb\x10\xaaHs/LT\xbd\xb0S\xf2\x18\xf4Q\x0c]\x06,,R\x1fs\xba\x15\xd7\xc0\x8c\xb0\x85\x1d\xd4q\x86!\x8e\x06\xdfJj\xa0jSe\xe3\x80\x85\x95,\xf3\x80\xf2\x12\x06p\\\xe5\xce2\xcf\x7f+1\xabTj\x8e\x13\xbb\x0f\xa0\x10.\xa6\x05\xfaIJX\x14\xa3R\xfc\xb2\x12\xe4\x0c\xddD\x96%\xf48\x8d\x0f#X6)\x98\x01G\x1fO\x19i\x1d\xef\x9d(\x1a\xd4q\x14\x83\x8c\xbf\x00S\xa5\xf5\x13\x85\xfa\x0e\x84\xcd\xdc\x08k\xee\xc4\x0b\x07\x93:\x0e\xda,J\x88\x839&\xcb\xe4\xd8\xa5\x83\xd1\x80\x82\xf8Rf\x86\x0c\x1a\xbf6DN\xb5Y\x9c('\x9b\x8ceoRY\x91\xa1\x92/\x92~mq9M\xceD\x85\x11\xc4udi\x1fog,\x82\x15\x8b8\xd3\xe0J\xa3~b?\xad*^]\x1d\xe2F\x08KEay\xb2\x1b_\xc2\x04-,\xc8\x1dQ3Ryf\x87O-\x91\x88d\x1cv\xc3\xc6\xc4\xa0\x16\xf7\xcc\xe7\xb6\x8c\xc0jc\xad\xe9q\x96\xb5rV\x16O\x13u)b\x12K\xff\xa5C\x85`\xe2x?PQ\xee\xf8\xd3\xce\xa3\x82\xf4K\x89e\xe5\xc3]\xf4\x8c\xdd\x81\xd8\xfd \xaa\x18\xf9k\x16\xbe\x11_y\x04s\xc4\x1d\xfe\xf2\xdca\x0f\x95@\xe8\xe4\xe1\xd5\x95\xa0\xe3,\x9fvZ\xee\x87SG\xd1\x11\xd0\xd4\x12X\xedq'\x85\x03N5\xdd\x9f\xc8\x96\xd1\xb3k9$\xe6\\)`\xdcvx\x97/a\xd1t\xcb\xcfPs\xdc\xb1\xac\xc2\xa9\xd5\x7f\x01S$/\xf5\x05L\xe0\xd1#\xc8\xdc\xdf\x8d1\x00f\x9b\x1f\xeb\xea\x03\xc72\x8d\xcb\x05\x1d\xdf\xf0\x82\xe2\xb9\xf6\xc0\xea`\xa1_|\xed\x8d\x19]L\x97Z\xf4\xa5M\xe8k^\x89,\xb2\xc7E\x9d.\x85|\xf3ZJUh\xe7\xcbv;\xbe\xba\xf80\xd2\x86/a\x17\x82\x83.\xf5#\x92\x8f\xe1\x00\xd2.$\x079\xf2X\xb8\xa2\x17\x98y?\x13\x87R\xc2Q\x83\xf2S;\x0b\xedn \xe0\x9c\x92co ]l=\xf6K(qaL\xf6c;D\x96\xad\xec\\\xe7\x0e\x8d\xc2\xb2T\x93\xc3\x0e\x17\x92\x96\x9a\xaa\\\xfc\xd4T\xe5\x0co(=9\xc5_U\xd6\xa3e\xa9$\xcf\xf0\x87&5&\xe2\x86\xd4\x97\xc7\xe2W=\xb9\xd7\xd2\x0b\x14G\xcc\xa5Q;c\x18\x06}\xc6\x07$\xec\xfa\\|\xf34\x85_\xb6\xa1l\x03q,\xfc\xf1er\x1ewL\x05\x11N\xf3\x0f\x15qS\x8a\xd9\xd6\x07\xc8\x0b#^j\xbe\x14\x99kc\n\x96\xb3\x83sK\x1b\xc4u\xb8td\xcc\x19\x0b\x13\x9f\xb4\xe5\x89\x8d\xa1`\xe1\xd4$\x8d\xc5 \xa5\xf2F\x05\x92\x0d\x136\xde\xb2c\x18\xc0\xd8\x1c6h[\xd1\xa2>\xf2\xf2\xf8'\x95[\xa6\xdeUT\x83\x9d\x80<\n;-\xde\x12\x0e\xcb\x9b\xcaD\x16\xeb\xe3l\xc7 \xd8\xf0\xe6\xd8\xce\xd3\x95j6\xf4\x07(c\xf0\x88\xe6\x99J\xa4\x07\xea\x9c\x05\"?\x97dK\x91+\xe5\xa3\xe2\xe2\xa5g\x1a\xc3\xa7\xf6\x91\x94\x16\xf4\x86\xedW\xb7\xac\x9a\xf9A\xf1\xe5C!\xd0(V\x10\xb6\xe1\xdc\x86t5sD\xc9DJ\xbe\x15\xbf~ \xfc\x16\xd0\x15\x07\x0b\xab\x0eJ\x1f\x06\x11\xaa\x95\xa3'\x03\xffhg\x00\xe7N\xc4\xeb*\xf3n\xad\xe8\xe5L\xd2\xa3\x05\xbd\xa8\xa83Q\xeeX\x7f\xa2\xe2\x0f,\xe5\x8d5\xb3\xbe\x9en\x07\xf33\xd8\xd9\xf6\x0e\xf6?\xf1a\xff1\xc6\x03\xb6m\xc5\x19\x96\xa5\xcc\x8c\xd8H\x91\x9b>@\xb3\xd1.\xfe\xbd\x8d!c\xbc\x05\x83\xc7\x02\xc7\x87\xb8\xb9\xbf\x92.2\x15s\xdc[j\xd8\x86\x86_\x13\xa7R\x13\xfb+\xd1#\xd5\x91i\xac\x82N\xb7a\xccG\xfd \xc4\xe7r\x1fa\xf5\xac\xb4\xbe\xe3\x0fa\xa8\x8cG\xe9H\xee*.\xd8\x8da[e\x1f(\xf8\x9f\xe7\x86\x11\x8d\x85L\xc8\x1f\x8f#QF}\xcc\x0f\x00\xf1o\x82\xff\xba&2\x15\xd2X\x82\x11\x04\xf8\xe72|\x00\x0b\x0e\x11\xec\xb9\xe0\xbb\xc9k\n\xb5\xa1\x8b\xf1\x9a\xf1n\xd2\xe5N2\xc3 \x8a\x87\x18#!\xc8\xc6RH\xdc\x07|`x[Soat\xe3\xc4\xbc\xb2X0]|s\xeb\x16\xc6\x01\xa3h6i\xa8 :h\xc5\x1c#X\x90\x90\xa7bz\x9c\xdf(\x1e\xc0\n\x1e\xc19\xff\x87S\x82.Y\xe2\x14\x060E\n\xb22+I\xd4\xc5\xbb\x9bK\x92s:\x12\xfdV\xbf\xad \xa4\xcc\xfc\x9d\xfaP\xf4|\x8e\xb4\x0b\x060\xe9\xa0L\xa0\x18|\x05\xb2\x80/\n\xc6\xac\xcfj\x8a\x93\x1c\xd9\x98e\x88g\xdd\xa3\x01,B\x8898\x16\xb8h\xf8o!\xdc\x16*\x07\x85VSR\x0f(\xda2\x85O\x96\xee\xc8\\8\xce8\xa5B\xfcp\xae\x9c\xdc\x87\xa9S\x98\xe1\x0bs\"\x84\xeeG\x8f\xf8\x81\xeeZ\x18>\x80\x13\xa4\xae\x8b\xea\xf5\x10Ns\x12\x7f\xb2\x7fu\"\x05\xb5\xed\x01\x04bK\x85\xf05\x9c\xe0&\xd9)!#\xf7\xd3\xf0\xc4,\xdc\x9a\x177\x15X\xfdH\xaa\x11E;M\x90\x16|ev`\xcc\x97(\x15\xfb\xe1\xa1\xd8\x0f\xb5\x0f\xca\xe5,8%\x90\xef+\xea\xb2#\xa9\xca\x8e1\x8ar\xe3\x94\xa4KTkT\xc7\x89`\xbbI\x8d\x9d_V\xba\x1d\xc08\xce\xca\xbd*\xd5\xdd\xabf\xbe\xeeU\x9cL\\\xb0 \x16\xe2\x0eFj6\xa3\x1b-\xc7\xf1c\xbf|\x91\xb9\x9e/\xb2\x16A_eY[\xba#B0)\xb6\x93 F \xc6\x9a\xbe'\x15\x10~$\xf7l\x82\xeb++\xfd\xc5A!RJ\x8aU\xbf\xe9\x94\x92\xb9\x88GK7@\x8f\x04\x1e)\xa7\xc9[\xb7D\x82\xa8\xca+9A\x92\xa2 \xdf\xccrcY\xa9\xb7])\xe6\x84[\xf5.*\xe5\x94\xce\xfa\x9co\xcas\xaf\xf6\xdf\xb9\xdbw\x16z|.\xdc\xe1>\xb0\xaa\xbe#\xbf\xb5\xb1\xdf\xcd\xf9\xff\xfa\xfa\x8e\x1f\xdcP,Ka\x8e\x9b\x08gk\xf0\xb5oJ\xbe\xba\xea\xe1\x9dfT\xb1+!\xaa\x14\xe1(\x02\xe1\x8f\x03\xb4\xdb\xf7OD\xea \x91;<\x15\xf6e\x8f\xdc\xe1^sz\xeeT&\xac\x842a\xc5{|\xcd\x02Q\xdd\xe6\x88\x05\xadP?K\xeb\xbf\xbb%\x0ci\xda\x89\x14KoM\xbd\x14K>8)\x1c\xfc\xbcHI\xc1,\n\xff\xa2\xe2\xf8\xf9\xd1\xba\xb4\xa9\x12\x06\"o\x93\x19o\x85~\xa2KQ\x18K\xf28\x10\xda\xd3\xea\xe7>|\x0d\x89r\xdcD\x1b\x910V\xb6\x93\x9fZDXu\xc9\xfe\xb5\xf9H\x15\x0bJk\x96}\x14\xf6Y\xf6\x92\xac\xc8\xe4\x98|\x0e\xc2\xcd)3\x19\xeeZ\xb8\x86\xb0?M\x93E\xc0;x\x1d\x8b|:\x1anr\xa2\x9b\xd7p\xb5\x8e\xb9\xba\x933:\\\xa0\xf1L\x95}c\xa10\xfe)%\x86\xe6\xdc\x1bkj\x0bND\x96J45(/\xb5X3\xabm\xa6B\x80\x18Qi\x19\x0e\xf7F]\x8b\x9d\x0b\xd5\x9eXG9\n\x91j\xdd:\x081?\xe9L\x1f+\x12Z\xb5\x10\xcbB)\xb2\x19+\xc9\xb0\xf1=\xb9\xfc\x9e(\xca!|\xc3%\xe5\xc8\xcc\x9c\x0c\x07\xe3kt\x7f\xf7\xcc\xbc\xfc\xa6\xc3\xeb\x04\xdd\x954\xaf\x93\x93eA^\x92U\x01U)\x0bE\xf1\xdaI|m\x9d\xbe\xb7\xd0tc\x8f\x9b7\xff\xec\xafm\xfe\xd5_\xdb\xfc\xc7\x8e8\xb6\x7f0W\x8aXV\x1bA\xbd{~\x83o\xf1.\xafN\xad9CR\xe6\x08\x8b9\xaa\xe2%\x9d\x0d\x9d\x97e\x92\xe5G\xb2\xfe\x19\xfa^9\x15b\xfe\x83\x05}7\xc9n\x02\x0b#\x12\x99*\x8a\xf09\xcd\xe2\xa2\xd3\x0d\x15\xf4\x8e\x12:N\x97\x13R4\xab\xda\x97-\xaa\x176kv\x16\xdb[\x1c\xc7\xe3\x19yO\x8a%\x86Q\x12\x1aaE3\xe9Q\xf8\x91\xe2\xe3Z\xd9.W\x04\x93\x12C\xcc\xce\x14P\xa7P\xadzV\x9e\x8c\xa1\xf4:\x14\xbc\xa1]\x1da-v\xa5y\xa7n:?\xa1\xef\xe5\x07\xc1\x9b.\xa9^i7UW\xa2]\xbb\x98\xaeXx?'Vu)\xbbf\xee,_\xab.\xe4RHg\x1d[uU\xfb\x0c\xdd\\\x87\xbb\x1d\xd9\x90\x00\xc3:\xd5\xbb\xda\x87{\xa3H\xfb\xbb\xe5^\xd8\xbc\xdcfQ+\x19Q\x97-\x8b\xb9\x1f>\xf2\x95\xc2\x15\xfe\x9d\xcbLp\x00\xbf[\x11\xa9v\xd3F{?ws\xba\x9d\x148o\x12\xdd|s\xd2b\xa7\x01y3\xa4\xd3\xa7\xa82\xc6\x81bbz7\xc5\xadj\xa6d\x18&\x8c\xbe\xf6\xa2\xc4Nn\x14\xedp@N\x02\xe43\xbck\x13\xa0\xac\xc3\xd9\xa6N\x83\xf2\xa0\x9a\x91\xfaXZ\x04mD)\xeb\x98\xb2\x99(\xf9\xcc\xb9\x86\xc3o:\xeb*o@i\x94\xf8\x9atR\x19t\xb4\x93\x04F\xc9\xaf\xf6\xb7\xcf\xa5OZ&h\x83\xdbE\x05}\x13\x9c4H\xc9\xef\x1cZ\xcbHC\xb6\x18)\xd0\x92\xe3\x9bq\x01\xc0\xa2NhUE\xb4\xec\xf1\xef\xbb=\xd7\xdc\x1b\x9c\xea,\x16m\xeev\xba s\xe4\xe2\xb2\x88`\x7f\xd02\xe7\xcd \xa9S\xe0\xa3y\x06\xa0sW\x1b\x8c\x13\xf4\xbd(\xa4D\xdb\x961pW\xa8Yj\x90-W:\xc1\xb2'\xd4\x04\xc8\xbc\x8f;{\xb0cHa\x0d\x92{h\xd2X+WP\xa7\xb1\xb5\xc6--_\x8f\x8d\xeb\xe0\x0e\xa9\x81\x97\xa3\xe6\xe8\x90\xff8\x0f\xd7Q\x8c\xe4*\x82-\x1b\xec\xcc\xb1E\xae\x19\x19\xcfx{\x0f^[\xfe\x0f_\x95_\xc7\xc9\x8e\x9b1k\xa2\x9a\x15\x8f\xcf\xcbD\xbd~\xc7o\x86\xc7\xd4\x8a\xf7\xb2\xb5U\x11\xc4\xccq\xfaf\x7f-;P\x8e\xa7\xcd\x0bH[\xbb\xa1\xb4P(t\x98\x0e\xa6\xc0\xe5My\xae\xc5 \xd8\xcf\x98\xa5\xb9*/t#|\xe2p\xeb\x05%5\xe8|\x02~P%R\xdc\xde\x8e \xe3\x0d\xe5\x12\x02hn\xb6\xe7\xf9\xe4Sm\xfa\x84\x81Z<7\x1f\xe1\x03\xa6&\x1f\x918*/v\x03m\x036\xc3\xd3\xf9S\xe1\\\xdc\xc9\x8d\x80\n\xca\xa8s$\x89\xfb\x0be\x08K|\xb8\x12\x906\xb1b\xb8\xeb\xb0\x9a\xa9\x0b\xb3Y\x1a\x13\x83\xeaW\x1d_\xc6h*\xd4r\x02}\xc6\x8a\x882\xb7:\"\xcf\xd8\xcap\x82U\xf01\xf3;~\xb6\x81'\xbe\xc4\x8fX\"N\xf9\x0c7r#\xe2B\xc4\x1e\xdcF\x1f\x1c\x0cDD\x9f\x1c\xf9\xfe[Y\xc1,\xeb\xcc\x9b\xc4\xd1\xe6\x9d\xa8cf\xb7'|@\ni \xc8\xe1\x04\x0c\x12X\xaf!\xe6\x7f\xc5e\x8f\x1c&}\x96 \x15\xbav\x10\x07a\x05)\xf3\xa0\xa4\x93w\x0c;&\xcc,`0\x10\x9e~\x01\xdfl\x85tD\xda\x85\x03c\xa5\x89s\xe9\xd5\xe8>vR\xc5bV\xe1\x06K\xac\xac\xa5\x8c\xa1\xcb\xca\x80\x18\xc1\x16\x9eR\x992\x8b-\xcb4>A\xda<+<\x8ea\x99\xe1\x86\xc9p\xd3*)\x10\x93E\x15\x15\x93\xb6\xcd\xe9$\xa6\x9b1\xf8\xb1\x85\x11\xa4_\xa6\xa7\xca\x9c\xe09\x96!\xda\xa4\xc2\xbcf!F\x11\xb4\xdd\xe5\xaf\xf45\xbe\x9e\xb2N\xda\xf4x\xff^K\xe4\xd6\xd3)\xb4\xd1Zm\xab\xf8\xec\xeb\xe3\xb1\xbc7|\x96\xaa\xb5z\x10B\xd6yZrxmo\x17\xf0HC\xf9\xae\x93\xd8+\xfa\x1d\xba\"\xe0\xf9u\xe5V\x13\x10T\x13tM\xa1\xe4\xaa1 \x96\xd2\xe2\x11\x0c\xb0g\x91\xa8\xa3\x13\xc9'\xcfU\x92\\\xf4\xc6\xd05\x95\x9b(\x08\xeaXk;0\x7f\xf2=0\xddd\xfb\x86x`;\x19K|\xf6\x08 \x1c.\xef\xe72\xc8\xc2E\xa7\xba\x11\xdd\xc1i\xa7\x9d\xa4J\xa4\xe4\xc6\xd3\xb2\xc9u\xa7aE\xb5\x8a\x16\xdb]\xb8\xd9\xee0\x02C\xa0\xe5\xcd\xf0\xdc7\xb0,Y\xee\xb3.\x9b0\xf7_~\xdel@\xb0p\x93\xe3\"\x19\x12\xb5\xabk\x92uP\xa4De\x1d\\JZ\x11\xd6Y\x7f\xa4\x0cY\x832d\x918\xc2\xb2.\xba\xd0-7L+\xabG\x07\x8f\xcf1\x04+\xf9\x8d\xf1/\xde\x81\xe0\xf2\x8a\x1a\xde\x8ee<\x93\x83\xbd\x87\x8bY\x92\x12\xb0:\xe5\x81\xae\x0e@\xdb\x95>\xf3\x04\xfb\xd8\x88\xe6\xf9 ?\xde\x88\xe1\xe3\x8b-\x01\x0e\xfcE:e\xa9s$\x07P\xce\x86\x04E\x07\xed9WUC\xac[\x99_\x85\x89\xb2e\x1d\n\x04\xd0\xb8\xe7-\xf4\xbcJ\xe1!\x16\xac\xb9\x05q\x80U\xfb\x90(\xa7\x18\xa8\x0d\x07*M7R\x04*\xcb\x01$()\x86\xa5$\xb1\xb5\x8b\xc59\xedxeW\x95\xf3\x85\xe5_\xb7K(\xfd\x15\xa6\x8c\xdc.\xae\x81\\\xc5aG\xa1\xf3\x1b\xa3R\x92\xadJ\xbc\x94\x14\xc4\xcbd\x02\xea\xdc\x92\xa9\xe672\xcf\xa6\xbe\xf4\x06d/\xb9\xa4\x00\xa5\xfb\xf5po\xc4%T\xd4\x10\x06K\x15O\x81\xd8\xc5\x8f\xd18H\xab#\x93\x96\x84#\x8f\xc4\xf9\x99v\x93E~-\x85sn\"K\xa3\xa5\xad\xe5u\xb6\xa0\\\xb4\x90\xac\xa3g\x97\x1di\xbb(`\xd7\xaa\xdd C\xbb\x01E\xf533\xfd\xec\xa4\xa8\xc2#\x13]@M\xf2\x8b\"\xb8Kk\xda\xe8\xccN-\xc5\x9eT\xda\x8d\x9a\x83 \xeb(\xe2$\xe1>\xccq\xe4\x99(\xbdx\x08\xe2C\xe9^\xc6\xac\xee\x83e\x96i\xeb\x11\x91\xf4\x8b,g~\xd2\xacb\xa2\x022\xbc3\x8a\x80\x0e\xef\x8c\x10\xcb\xc9p\x7f\x04;@\x87\xfb\x86\x0c\xc1aU\x90\xbc\x91\x95\xc1j\xb1I\x86l\xa4v\xd2\x00\xf6\xdbm6+\xf4\xb9\x1a\xe2\xa0\x1f\xee\x99\x06&8\xd7_e\x8d\x0f\xe1\xd6\xfdR\xfc\xfa!h(\x04m8\xf5\xc2\x89S\xc2\xdfE\xc3+\x0f\xbb\xd1\x17\xe2 \x1fJ\x89\x1bV\xbc\xc8\xc9d9\xde@\x87![\xff\x15=+\x05;G\xd1\x87S(*,\xf9\xf2\xdd\xb6\x0c\xd4\x8a\xe5&\xdfWG@\xca&\x03\xaf\x0f:\x12\x89\xf9\xcc\xc3\xf5\xf4|\xff\xd5\x8b'\x13\xf5s\xec[N%\x8f\xbfu\x0b\xa8\xa6\xbf\xad\x85M\xae\xd7U4\x82\xf8\x05[\x03\xde\xedz-b[\xbd\xc6\xfb\xb2\x8a\xbf\xf8\x02\xa1Y\xea:\xf91OH\x90\xfbz8\x97k\xd6\xf2\xb3\x04\x81\x84\xf3\x84\x06u\xcb\x14\x0c\xfc\xf6u3\x0b\x9f\xf0\xf3\xac\xce\xc4\xdfE\xbcv&Bx\xb6T\xfd\x0bM\xa2\x81Z\xfa=i\xa9\x10\xe4\x95\xd9\x92\xf0\x81\x06\x94\xf6|\xba\x05Y\xe2\xc1\xb9\xe5\x9e\xc0U\x97\x022_\x1f~2\xc1O\x01\x86\xb0W>\x97\x1c\xdf\x1d\x07\xfe\xf5\xf5m\x1e\xec\xff\x06\x9c!\xaef\xa7\x00\x86\xba \\\xce\xe4\x9a\x80\x92X\xe0\x02\x88H@\xd2/\xb29\xb9N\x07\x1c\xbd\x1c\xcd\xcb\xfaR\xffFFJ\xe5\xc7\x8c\x11\xbb\xa5\xb3\xaf,Gq](\xe2\x00]\xb3\xbcy\x81\xf8\x87\xce\\\x08\xc2\xc4\"jr\x90\xfe8\xa3\x05\xcb\x97c\xd4,\xfb\xd1\xf7\xaf,\x8e\xdeI\x99\xcdFD a\x89\x116\xcb\xb3\x0bD\xf1\x0f\xab\x059\xca\xf3,\x0fzG\x97\x0b2fd\x02\xc3\x97\x11\xfc4\x02\xb6\\\xa4\xe4\x00z\xb0\xdd\xcaHk\x19\xc3?\xdd\xd1U\xaf\x88\x8cG\x08#x\xea\x1b`\xf5\x8b\xbb\xcd\xa5\x00[^\xb1A\x19\x17x\xbd\x9a\xfe\x87\xbb\xe9z\xc4V {\xfaUc\xb88\xb7\x15j\x81\\^\xbd\x12\x8f\xea\x1c\x9c\x14\xd7\\zT\xee\xf6\xd6\x13\xb41\xce\x9aY\xdd\xf1-\xe9\xa4/\xf3\xac\xbf\xd0\xb3\xcbW\xdf\x0bm\x13k\xa7.\xb5\x8c\x9eu\xe6\xba'\xf0Hf\xa3<\x10\xc5>\xe0\x10v\xf8\x0f\xbfs\x9fZ\xb6\xf2\xb9\xf4E\xfb\xc9x\xe0\xa3\x14m\xe7\xa5\xf9\xd3\x9f=0\x1f\x8f\xc0\xd3\x94@\x96\x03\x06E\xef\xa4\xc9\xa7r\x0f\x98I\xbc\x18\x14\x1f\xb5\x81@X\x97\xd9\x0b\x16yG\xe2d\xc1A\x94$\xd0\x99SLX\xb0\x13Z\xb0\x98\x8eI6\xd5*\x9e;\x9c\"\x10r\x88\x1e\xf5Ok\xc9>\xf3\xc0\xa6z.\x9bpr\xe8\xfc\xa2\xa8\x96\xea\xd6\xb2\xc6U(\xe5'\xb2*\xac~\x89\xea\xda\xf2\xe3\xca\xf4\x8b\xe5+\x8f\xb7\xf8\xc5\x8c\x11\xae^\x9d\xa8K\xceeB\xa6 %\xef\xf2lAr\xb6\x92\x9c\xaf\x7f+\xfc:#L\x13-7\x19\x83\xbat\x12$\xc2&7j\xe2\xaa\xdb F\xbf\x8a\xdax;\x8fo\xd3uF\x1a\x89\x98#\xe8=\x8d)\xcd\x18o\x1d2\n1\x85\xa4L\xcf\x9b\x93q\x96O\xfa\xbd\x92d\x8ah;\x07\x8bi\xba\xba3\xb7\xa9\xcb\x12\x8d\xd0\xbc\xae\xfa\xa7 \x9d\x04U\xd4]\xf7gW0\x8e\xd9x\x06\x086\xf7\x80\xae\x02\xe5\x9a\xae\x8e\x88X\xea'\x90\xeb\xa7\xf1\x9c\x94\xa1\xc3\x9fD(^\x8c?&d\x1a/S\xf6\x13\xe7\x960\xe7\x8c\xb5\x1b\xfb\x00\xc4\xea\x88\x80\xc3\x8f\xa4\xa9\x98P\x97\x05q2\x94)\xcaS\xab\x15C\x9d\x99t]\xa5\xe4\xa7\xb1P\"\xda\xb1\xa9h\xd3\x7f\xb1\xe0\x1d\x8b\xe0#gL\xde\xdd\\\x95\xaew7Y\xa5\xebm>!9\x99\xbc\x8e\x17\xf0g/\x82\xdeU\xbbV\xd7\xbbk\xd4\xea:\xd7k\x04\xf0\x95\x125\xfc\xed\x90\xadyh\xc9b:\x18F\x8a\x1f\xd2PT\xa6m\xd5\xd0z\xf7o\xaenS\x96\x9d\xe1S\x92I\x95\"}\xb4\xb5{\xa1\xcc\x88\xe0\x1c\xf5f\x95\xbf~g\xae\xdaG\xef\xae_\xfbHo\xb8]\x06\xb5\xd6p-\xf5\xb8\x0f\xb0+\x90U\x9f\x06\xa8\xb8\xd1 \xa7?rv\xbf\x91nDGD+\xf2i\xa30\xd8\xd2\xba\xdc\xe8E\xbe\xb9\x80\xa1\x0e\x90\xa1\x05\xd6\x12\xde\xe57/\xbf\x12\x17\xed\xa1O\xf3l~DY\xbe\x12\xbaRM\xf9\xd3\x8d+\x9b\x15J\x10\xc2\xdf\xa0U%\xc1#\xbf6\xab\x11\x85Z\xb7V3BEH\xe4\x12\xd5?\xb2.+\xdf\xd5\xaf\x99t\xe5$\xfe\xd5\x16\xd4\xd1\xc2\xf4\x9d-\xf2^\x18$\x1a\x84dRh\x84t\x00\x1fX\x1d\xbe\xc3\x99\xaanP\x83zY\xe7\xc0\xb0o#`\xc1\x1b\x16\xc1\xafa\x04o\xaeA\x81\xdb\x82\x1fR`\x13&\xd4\x9ao\xc4\x0dt\x96K\x13m\x8b\xa2i\xce\x86Q?rL>oD3\xb0q\xf5e\x9b.\xbc\xa9\xc3\xcd+T\xe8\\\xab\xc8l\xc67\x0e\xdf\xef\x159\xdc2%\x1b\xac\x8dQ%\x1b@\xa3\x86\xf74A\xd7\x1d\x89y*+\x87=8\xfc*l\x05\x896\x80 0\xb7\x13;t\xb2h\x06\x02\xa7\x02\x9fk\x87\xcd\x06`\xc8\xaf\x03\x06\xda\x00\xc3<^\x18\xf0\x15$\x18Z\x85_\xde|\xd9\x19\x119B\x94\xda(\xa99\xe0\xd6&\xaf\x99\xf3<\x1c\x97I\xc0l1KW\x9c@\xa9|\xcb\xff\x14\xeb\x10\x8a,=e\x0fV\xd5y\xd9|\x16\xc9|\xcd\x14\x0eD1 SWa'Q\xd8\xechB\x1b\x9f\x0e\x96\xd0\x01Au<\x99\x8f\x0bZ\xd7=\xb5\x0c\x1aV\xd4m\x82\xcd\xba\xa8\x9e\nye\x19\xa2N\xef\x8bRL@\x83\x8aP\x1a\xa2\xa2Y\xac\x02\x16\xc4G\xbf\xb0\xd2\xbcbZ\x0e\xd7RT' \x0b\xde\xb3\x08^\x86\x11\xbc\xd7\x97\xca\x14\x08\xe8I\xc4\xcbh\xc06%\x7f\xffe\x9b\xab\x93\xd2\xd8\xd7\xc7\xb8\xe9\xbcy3\xdca\x08r_\x96\xcc8S?\xbc\xff\"\x84\xbd\x11\x0ce\xbe\x18\xca\x14\x862\x85\xa1\xa2\xda\x96\xc2K\xaf\x9aa,x\xc6\"\xf8!\x8c\xe0\xd9\x97s\x10\x0e\xe4{v#\xc8\xf7Wb\x18\xf3\xc7/\xe3dn\x0c\xbf\xfe\xc3HT\xe1\xcf\x86\x88\xf4Jr\xba\xaft\xe8\x10)\xcct\xf1\x10\xedu\x94,D\xb3\x9fW\xff\x95\x88\x84\xc7\xa5\xed!\xbf\xbeb\x81\xb5\x88\x9e\xe6d\x11;\xdf*\xd1\x15K\xf4\xa30 \xaa\x12\xa3\xd8Z\xdd\xdc\x157-R,\xbf\xdaz9#\xa2\x1b\x81\xfd_\x83\xe8\x1e\x91\xa1~{\x01\xca\xf0\xca\x9a[\xb8\xa3\xa2\x86Z/\xd6\xe5e\x89\xde\x95\xae\x11\x82@\x0eS\x18\xa0~)\xde%\xee|S\x0e\x1e\xf7r\x06\x87\"\x91\x8b@\x89\x1cQ\xa2\xba\xb9'n\xee\xb5\xf3\xe5\xeb\x97\xc5e\xd1\x83&\xd4\xce\xe1z\x1a\x827\xf6G\xcf\xec\x8f^\xd9\x1fa\x8e\xaa \xa7\x11\x9c\x10.ZP\xed\xcd/T\xb0.\xa9\xe4A\xb7\xa1g\xd5\xb0\xd6:\xdc\xf8\xf8\xaci\xd4\xf9\xe7o/he\xf2qw\xe6\xa9L\x10v\xd0YY\x1d\xdd\x85\xe6\xf5\xcd[\x1b\xdc\x90\x18\xe2\x94ks\xe1\xe2\xeba\xf5\xb7\xd2Y\x18b6\x9b3\xf1R\xfeV\x92\x89Qe%\xfa\xbfuK\x1b@M\x9fk\x9eli\x1f\xd7l\x03v\x9dT\xff\x84\xcc\x17l\x85br\xf9c\x001\x95\xa2\xf6/\xa4\x9d\xf2\xb41UO\x8dq{\xd1*+\xb5\xb0P\xffM\xb3j-\xe9'\x9a]P\xf8DV\xd0\xfb\x1bl\x03\x81m\xf8[\x0f2\n\xfc\x97\xc2c\x8b\x91\xbc\x06\xbd\xad\n|\xb2\x98~Y\x8b\xc3\x8c\x14\x1ez\xc3\x9a1\xa1\xbeD\x85\xd2ku\xe0V\xad,\x846\x9a\n\xe7\xe0\xa0Z\x87v\x1d\xe6\xda\x1ax*\xd7\xed\x1b\xc7OCZ\x9f\xa9\xccS\xea\xca\xac\xd8\x9a)\xeb\x9ci\xfb\xe8\xae\xcd\xf4\x86\xb4\xfd\xce>\xae\xcf\x1eX!\x91\x07\x06\\k:jZ:\x00])e1Y_uk\xd8\x8dS\xbc9v\xf3\xdf8C\xe25\xc1\xff\x84 \xa1\xbeA62\x0dT\x1b@\x06\x0d\xf8\x1a\x04\x1ap\xa8w\x82\xcc\x16z\xd7j\xc0\xb1\x15\xa8\x8c\xc5\nuxO\xd7\xed\xd3\xf2\xd7\x19a\xefT\xf3o\xa7\x9c\xb4\xd8\x11E\x1b\x7f\xde\xcc\xe4\xed\x17(\xb2\xec(\x99--\xfe\xebu\xdd\xcb\xb0\xaf\xee\xf6\xde\xa3\x93D\xcf\xab\xb3\xc2\xdd\x993'\xfd9E\xff\xde\x94\xcacgk\x1c\x94\xc9\xe9\xf9\xb3k'\xa7O\xae\x9d\x9c\xde\xc5\xc1\x97\x92t<\x99\xd8\x8b\x11\x18\xb6\xa6\x17 S7 \xb7\x82-\x04\xe1\x16\x19N\x9b9\xa4\xeb,zF+[UFK\x0bUy\x1b\xeb`\x97\x0f\xda\xe5\xb73*Jdk\xd5\xb2\xab\x9b?'\x18\xd4\xa2\x1e\xf0\x9f\xd5\xc3V\xf9m\xf5\xe0\x19!\x8bF\xf1\xed\xfa\xc3F\xb3\xeaV\xfd%c\x01\xef\x8c\x1aJ\x8dg\xd4XA\xbc\xbc\xdd\xae \x9eQ\x8f:\xe0\x19\xed\xdb\xeb\x80\xe3CW\x1dp\x16\x144\x82#\x8ey\x05\xbd1\x07\x93\x82\xa2-Yf\xd0\xf6\x96D\x02Nq\xfb\x9f\x88\xb0?\x9bZ\xbd1\xa9\xaawL\x98U\x9a*\xbeH\x9a\xaa\xb8Vg\xbb\xf1d\xe2\xdb\xee\xa4\xc0\x9aq\xac\xac\xbcC\xb7\xb7CH\x026\xa4\xa3\xb0}\xec85\x8a\xe5\xb1\xcd\x8f\x1d\x8b\xfa\xc6x\xec(\x07\xa9Z$\xc1p\xb7yx4\x96>\xa1\x8c\xe4\x05\x19\xb3\x9b]\xfe*\xa3\x12\xf3\xab\xbd.0\xc4/\xbeC6\x94\x98NeS\x18\x9f\x17\xcb~-,0\xf0\x14N\xbfg\xd6'\xe7$_y\xb4\xac\xae\x12\x1dJ#\x8cE\xf5\x0b\x02 \x90\xcd\x93\xa4\xc5\xa6$\xeefZ\x1aHR,OY\x1e\xff\x7f8\xf2o\xc2\x91\xeb\xc6ry\xa2\x08&\xb2\xbai\x14Q<\xa4\xcf1\x85`\xc43G\xab\xe5\x10\x81\x93\xebi\xf4$9H7I=/K\xaf6\xd1q\xafCM\xd3\x1e\\[\xe7T\xdf!Y\xce|y\x819\x0d~.\xbdw:Nf\xde\xee\x93\x95\x8f^\xc2\xd08\xebn\xff/\xd2 \x15\x7f\xadz\x85iZ\x85\xb61\xcf#3t\x90c\xcc\xb9\xafa\xd88\x1d?\x85Xk\xc4\x9b\xea\x80L\xf9\xb0;\xd5[\xc5\x7f^\xfb\xb3\x99\xc2G\xf65\x8f?\x91\xe0\x0bu>8\xfb\xa48FM|J\xdb*\xa01\x8d`\xcaq\xac\xf7\xf7\xbf\x9f\x9c<\x7f\xfd\xfa\xe3\x87\xc7O^\x1d\x9d\x1c\x1f}89\xf9\xfb\xdf{mG\x90\x05\x7f\xbb\xf0P\x1aM:\x11\x81X\xaa5\xb1f\xb5&\x05\x05U([j\x88\xb1\x1c\x9c<4\xa5w<\xae\xf0|\xc1V\"|\xba\x04\xa3\x9f\"b\xd6\xbd\x17\xebJ\xae\x85#\x08\xa3\xcaf\xdf(_G\xd5\xb4\x88\xc8\xea]\xad)\xf3M\xc2}\xee\xa4Kc\xcc;\x10\x8c\xf9xg40\x99j,\xed\xce\xbf@\xa5u!TZg\xb4\xd2d]\xfc\xbfM\x93u\xe6\x86_\xa9\xee3\x14X\xd4\x7f-\xe8pJ\x95\x03\xddBSj-*\xa5\xd6\xa2\xae`R?\xeb\x0f$k\xb0\xa0\xba\xcej\xe1\xa3\xf0Y\xb8\x14>\x8b.\x85\xcf\x82\xaa}\x08\x038\xa7\xf2\x06\xdf\x8a\x88\x92\x11\xb0`N9q\n#\x98\xdf\x9cFh\xfe\x97h\x84\xe67\xa9\x11\x92\xfe\xf7.\xc5\xd0\x9cV~\xfa\x82r\x9f\x19(\xf7\x8aFp\xca\xf7\xc9\xdc\x83\x16\x9flJ\xd8N\xffC\x84\xed\xc2 \xcd\x95 l+>\xde\x13\x1a<\xf7/\xbby\xf4\x05\x84\xed\xad l\x97\x1aa\xe3\xb7\xfaKZ\xcc\x92){\x9c\xa6\xbe\xd1\xfc\x97\xde\x8a\xee\xa7nE\xf7)\xad\x1clO\xf5\xbdvA\xe5\x0d\xb9\xd7Np\xaf\x1d\xd1\x08.8\xb5<\xba\xb9\xbdvt\x93\xbb\xe2\x98\xc5\xe3O0\xe4\x1bb\xd4\xde\x10G\xd7p\x05\xa9\x1b\xe3g$6\x14\xaaG\xbd\x15\xd1\x92r\x93\xf0\x81H\xbcNvv\x1e\x84\xf8\xbd\xf0\xaa\xb2\xef\x058\x04\x99\x84\xc6\x14\xf7W\x1b\xf9\x82\x90O\x1b\x01\x88\x8f\xba2\x1c\xf2_\x86\xec\x1d\xad^\x96\xc5\xac\xab\x97J\xdbP\xae\xaf\x9f\xd6\xa1\xd4\xf4\x95\xce$\xb8\xfb\xb7[\xedD\x1a\x03\xcc\x07\x1e!0\x9bo\xc1\x0e\xecq\x88?\x12j\xc3\x9d\x9d\x10?\xb3\xf1\x05\x98Y\xa5lcH-\xb9\x0f\xf9\x825\xd7\x82_\x86D\xcbu|\xb4\x04S\x96\x9c6\xae\x87\x16o\xd5\xac\x18*\xef\xd6\xcb\x9f3\xe9\xda\xff\x98\x9a\xc5\x93\xd6\xe2=\xe6\xa4\xc8C0\x91\xead\xb4u\x05$\x0c\x05G\xe4^\xbf*\x07I\x87\xd4\x82\x0c\xb8\x19\xba\x1d\x9b\xaa\xe4\xed\xcb\xf0\xa0\x0d84&\xb2\xe4\xd9P\x00*4pT\xa7\x10\xeb\xdfN\x9d\x0f-2\x8aw\xca\xc0X\xdb\xfa\xb3\xc6\xfa\xd3\xeb\xae\x7f\xdb\xfd\xba\xb5\xfeYge*\x1de\x8b4\x19\x93`\xcf\xdd\xa6<\xa66i\x97\xa3\xa1\xa7:\xca\xd4\x95\x0f\x067\xbb3\x9d\xa2\x8d\xd67\x9fF\xb6\xb8\xce,6\xb12}i|\xb6D\xa9\x06\x06m\x82W\x9c\x15q\x83\x8d#\x89\xcf\x91\xc9\x89\xca[\xe9\xe8Q\x0e\xd6\xc7\x15\x8cbq\x11\xa2\x7fe\xd6p\x7f\x08jM\xd7-TeG\x17\xa49\xfa*M\x8f5\xc6\xaf<\x99\xf2\xda\xc9\x84e\xce\xb2:\xc9\xe2\x07\xcd\x83\x10\xeff\xee\xd3\xdd\xbd\x88yc\x11\xb3k\xad\xdfcj\xaa0\xddX\xc3\xcd\xd4V\xa5.\xa9\xad\xb9\xaa\x10\x94\xe3\xeacZMH\x9f\xcc\x86a\xc8\xfa\xcc\xf6,z\xa8\xa3kkAe\xdc\x81\xbe$\xd5\xd1\xa2y~\xb9\x90\x82\x8a=\x977\x10!\xaf%\x13\xccU0\x08\xd5\x92 \xe27y\x07\x13\xe85Y?\x1d\xa9\xd7l3\xb3\x0e\xb1\x9a\xa9\xf1\xec\xcb\xfdNn\xcf\xc8\x84N\xaf\x7f\xc5O\xe4]\xf1\x03\xb2\xdf\n\xd0\x91\xf0\xec\x17\xcb`Q\xd1\x98g(Z\xead\x1e\xba\xb2\xf393\xf3\xf9D\x05\x1c\xa1\xd6\x15\x85\x9a\x01\\\x1a\xa4\xf7c\x1a\xc1S\x93\xde\xf5\xc3\xe3\xa7/-\x9a\xd7O\xfc\xfd#\x0fi\xffq\xe9\xae\xd7\x91?\xb4.\xf3\x7frf\x94\xa9\x98\xe1L\xe7\x84\xb3\xa6\xa3^V\xd1\xbf\\\xfc\xaaS\x07\xbf\x94\x81o\x9d\xa7\xee\xb1\xd0\x03\x1cs\x80<\xa6A\xcb=\xc5\xd2\xe8\xbbnq\xb1D{\xabYR;\x9c\x86\xa8\xa3cCjH\x84k\x85\xa4\x9e\xbe\x8bU\xbc1\x0d#\xa8\\&\xb5\xd0\x88\xe3\xd5\xfc4K\xb1B\x82\xeby\xb3\xadf}|\xfd\xd7':|Z\xaa\x17?\xf9h\x03?\xb9\xb4\x81\x9f\xba\xb4\x81\xbc\x0b\xdd\xb6\xf6D\xb7\xb5E@\xfb\xcf+\x02\xf91\xe2\xcbDM\xe9\xbfdJl\x8f4_\xafH\xe0bE@.8\x91\xb9qE\xa6\xed\xeah_\xaf\x8d6zh0\x06U\xbe\x07\x8b\xe9\xcdi\xdaV\xd8c\xa61\xad\x15\xc4\xbbm\x9a\xc0\xb2\xe7tB.\xc9\xe4\x98|\xf6\x00\x8cF\xe2\xdf\xcb\xa8s\xbf^^\x1c\xfb\xb7\x8e\xc01\xa6\xc2\xf6\xd1\xccc\x82\xdf\x9e\xfa\xa4\x07\x9c\x85Y-H6\xc5\xfc\xda/\x8eQ\xe7\xc8\xff\x10\x16\x1e\x0b\xf8P\xbb\xc4\xdf\xf1\x9d\xde\xdb7\xff-\x13|\xfb\xa6\x9c\xe2\xdb779\xc9\x97du\x0dAC\xf8\x13\xd8\xfa\xa4\x93F\x8f\x1eU\xa3\x10\x98\xfcS\xcc\x89\x1aX\xcc\x1b\xa0\xebI\x0f1\xa1\x89\xb9<\xb8aXB+\xb4\x19,j\xc8\x125W\x9c\xa1\x84\x8ay\xbbYh.Sc\x18\x08\xe7@|6o\xa3oRZR\x04=\x84C\xe8aE\x028\x80^\xd4\xb3c2\x83\x01\xf4\x0czTu} \xa6\xbbp\x9c\xcaR\xfd[{\xe8\xb2\xba-,%\xfc_t3\xdaR%\xa4\xb4I\xe1\x9a\x96^4x\xe6\xf4\xda\x9c%\xc8\x1d\xe0\xc5\xb7}\"\xab/ ?\xcf\xbdVt^\x93C=\xd0\xaa\xdcb\xf5\x94\x9d^\x9d\x89\xb3t\xc3\x0d\x16A\xe6\\\xe0\x06\xae\xb5\x1cT\x1e\xc2>\xe6G\xe4\x98\x02\x07b\xc3\xb6\xb6\x83\xae\x06\xc0\x9a\xb5\x0e\xe4\xc8\xe0\x10\x82LR9l.\x94\xed\x92\xb2\xf4\xad\xa8\x18\x988\x0b2\xe7\xfe {\x9f\x9c\xcd\xd8\x86pS\x84Ig\x84*C\x94\x9b>I\xaeG\x9a\xdes\xab\xdd\x1dl\x83\xc6^\xfcq\xb7D*=\x19\xaeWWh\\\xbe&\x06?\xb9\xde!\xc1\xb9\x91\xcdz\x14yYD\xac\xdc\x1b\x8a\xa5\xc2LY0L]\xe5^5&\x9a3\xb3\x06\xe4\x80\xb9\x1f\x94\xba\xbf\x80\xd6\xfc\xee\xd5\xcb\xe9\x92\xbd\x8a7Q\x0f\x88}\x8d\x1e2\xbb\x11\xec\xecy\xf5\x92\x14G\xf3\x05\xf3\xb11\xc8^4\"\xae\xcb\xe9M\xc9\xfd@.c\x9d\x19\xf5\xe0EmFH\xaf\xd9\x8c\xb3%m\xee\xfc\x8e\xf9<\x0dH\xa5J\x12\xdb^\n\xb0\xe2\xe3\x0d\xf4*\xd8\xfb\x13_\xf6T\xf6\xefK\xa5@\xa3T\x1fI\x10V\x06)W\x06<%\xe5\x98\x88w\x17\xeb\x8a\xdf\xcb\xbc AU\xa7\\T\x12\xe7\xbbR\xcfy\xec%\xb5i2\x97\x99\xddU\x97\xa3\x94\n\x9e\x05\xba\xb9\xcdR!\xefJ?o}V\x8f|^\xc6\xe9&\xc2\xd69)\xc9\x86W\xfb2k\xa6\xc7V\xd3\x1dN\xcdk\x8b\x81Z\xfd\x13L\x97W+\xceDHu\xdf\xcd)\xd6\xab\xb7\xfeN\xc3\x86\xaa\xd5\xcd'\xd6\xaa\x1at\xf9\x8e5>&\xc6<\xa0\xea\xba\xf2\xe4\xf7\xc4.}\x93m\xb8\xdf\xa5\xf8\x81;|\xa3\xd3\xa5\x14Y6\xe7,,\xd5\";xn\xea']V\xc2%m\n\x97\xbc\xefa\x16\x01\x1d9\x05L/\xd6\x8aO\xff%\xf1%n5o\xf4M\x84=T\x8dQc\xa9]\xf3\x98\x1agd\xc7\x8a\xe8 7\xb3z8\xda\xb2\x99MF\xb1!rx\x0e\xa5\x02\xdc\xa6\xe3\xf1_-\xcf\xa1\xbc$r\x05\xfdF\x91o\xcc\xbc \xe8\x1f\xfb5\x9f\xc6\xec\xf5\xb5\xa51\xdf5\x02m\x13\xffb\xae\x93\xa4\xae&m\xabk\xea\xbb6\xb2\xd6Bn8k]\xc7\xa1\xae\x895o\xf1\x8d%O\xd9\xe2\x06ga \xd9\x1f5)\xc1WD\xd0\x8f\x12\x7f\x8c\xe1\xa7\xdd\xab\x0d\xcc\x90\xf5\x82y\x1e\xd8R\xa1\xa4.\xef\xfa\x14\x1f\x9fa]m\x9b>5\xaa\xfcd}\x07\xfe\x9cz\x0e\xddTnZ\xf8\x03c\xa1MUa:\xabU\x98\xee\xcc\xb6\x9c`\\\x90GV\xe4\x00}\x1a\xb1Z:\xc6-\xa9\xa4\xc4I\x04+\xceJ\xafB\x14\x13V\x95\xbf\xa7\x19D\xaee\xf1:\xad\xce\xf2l\xb9\xf8w\xb0\xe2~6\xbc@f\xbb{\xc7P\xd5\xc5\xf9wO\x06\xde\xc8\xb9w\xe9\\\xf8\x95\xb59w\xfe\x99\xe0\xdc\xbb\xf7\xb5~I\xf0\x04\"\x04r\xbd\x86\xe1(\xc4\x18\x06\xccY>\x8c#HFp\x00\x89\x87q\xd0A\xc7\xec0P(\xe8G\x81\xb3:\xe5\xed4?U\x14\x8cD\x90\x04&\x12\xa9.\xcb\xf87\x165f\xf1&r\x06\xd2!\x99py%b\x08V\x9e\xbd<\xdf\x84\x86\xab~\x9e\xd3M{J\x8a\xe3\xe5\xa9g\x81\xcfR\x06\x1c\xd8|\xc2\xcaJ)\xc2\xea,y\xf4J'\xe4\xb7\xb4\xe5y\\&\xc6\xd9 \x9f\x96y\x8a\x0b\xce\x0bm2\xc9\xc05K 3m\x96ay\xd3\xffT\xfbDVo\xa7\x1b\x0c\xa9<\xd483\xb7\x11$o\xc0H(\"\xce\xfd\x8f\xf8\x9aV\x86\xef\xea\xe7-)\xd5\xa7\xdbts5Z\xab\xe4W\x1f\xf9Y\xff\xfe^^g],\xbc7\xae\xb11\x97U\xbb\xefy|\xb9A\xaf/\xd8F*\x8cy|\xb9\xe9\x99\xfa\xa2\x96\x8f\xc8\xab\x13?\xa3Yk\x06p\x08\xef\xa9pa\xf9\xe8'(\xcd\x13z\xfd\xe9\x88\xee\x98\xe8\xcewn9\xd9\x18\x13\x8d!\x8f`n\xbe\xf8\x94,6\x80\x9d\xd6\xfe\xeb\x98\xcd\xfa\xf3\xf82\xb0T$\xb6t\xd6\x14\xbe}\xa5\x04\xcb\x1e\xe3M\x06D\xbb\xe3=\x90\x9fgI\xba\xa1\x99\xa1\x1c\xccO\xd74l|J\x16\x1f)K\xd2\xcd\xba\x15@WC\xdeL\x05%\x12\x82m\xd6_\xdb\xcaa\xc8\x0c\x06\xe6\xfeX\xfc\x89l\xb0\xbc\xacf\x80\xb8\x06J\xf1\xfen\x18\xa5x\x93\x9b\xa3\x14\xff\xeaKP\xea:\x92\xc4?\xbc\xb8[\xad\x84\xd1G\x8aj\xdeZ\xf26\x8c\xac\xec`x\x15;\xcd\xac\xdaeuq\x91.\xab\xc7\xe6i\x05Zja \xd8\xb1\xbb\xb5sY\xcf\xbf\xa3\xec\x7f\xc9\xb8\x19\x04\x1f\x82*\x91e\xd7\x0c\xb5f*\xe9\xa7\xfc\xf6\xd6-\xd8\xde\x8eQH\x95\x0dZ\n\x95\xab\xeb*\x8c \xb6\xbeq\x15\x81^\x06\xe9\xbfhU\xb2|\x93e!5o,\xfe\x9d[\xae\xe5\xd7\xd2\xe1Q\xa2.9N\xcf(K\xfdB\xdf\xa9e9\xd3\xee\x0f\xc0?\xe2Q\xbf\x9c\xd1\x8f\xfae\x89\x95\xd0/e\xba\x89;\x8bS\xa9K\xe8\xf0kE\xaa<\x1c\x1aUD\xa3\xac\xdf\xeb7\xd1B:\xab\xfa\xbd\x9d\xe2\xdb{\x1d\xae\xad`\xdaki\x04\x05j<\x0f9i\x1b\x0c\xe0\x8d\x14s>s\x8c,\xf0\x05\x91\xe6o)=C\xfe\x0b\x16\xb7\x8b\x088)\x80\xf1\xe1\xe6\x9aW~\xf0\\\x97\xa9(\x0f\xad\xcd\x98\n\x15C\xb0!_\xba\xb9\x186\x8b\x8b\xd9\xd3l\xb2\x81\xa3\x0b\x9bU\xd9\x05\xb0\x8a\xf3L\xcf6\xd0\xcd#@\xb9\xbd\x84\x83\xf2`\x00{p\x1bv\xcb\x8d\xe6 ]\xcaL:\xeeT\xf0\xf9\xb9\xf2\xa36\x16\x0ea\xcf\\\xf5\xb6|M\x0c\xcck\xf1\x1b\xdf\xf0\xd1^\xa2\x90~\xe7\xee\x9d\xfd\xef\xf6\xbe\xbds\xefN\x18\x95\xb7\xe1\xe1C\xd8\xbb\x07k`\xf0\xe8\xd1#\xd8\xd9\xbb\x17\xc1\xdd\xfb{\xdf\xde\xbd\xf7\xdd\xee7\xcd\xf7\xeeh\xef\xdd\x89\xe0^\xf5\x1c\xd3\xb9\x07\x0c\xb6\xe1\xce\xb7\xf7\xef\xee\x7f\xb7\xbf\xf7\xdd}Xs\x98\xfe\x8bo\xe9\x7f\xc9\xcf\xf6\xeeG\xb0\xbf\x7f\xf7\xfe\xb7\xfb\xfb\xf7\xca\xe6\x8f\xe5\xe7\xd8M\xf9\xe6\x9d\x08\xee\xec\xdf\xbf\x7f\xf7\xdb\xef\xbe\xdb\xfd.\xd4\x9bpl\xb9@\xe7\x0f(\xd6\xba<\xdc\x10j0\x80;{\xf05\xe4\xb0\x0d\x9fi\xf0\x94\xe0\xa6yJ\x02\x16\x86|F\xf6\xce\xc1sw\xaaKh\xc5\xaf\xd1K}R>\xdd\x943\xc2\x8e:;\xd8\xacq\xcfvCc9k( \xa2\x89\x14\xd6\xee4\x95\xc1|/~\x10\xc9\xc9\xb4\\\x00\xfa\x1b\x1f\xe8p\xaa\x02\xbc?\xd0\xe1+\xfe\xf7\x07i\xb2(\xf8-\x19:*n\xcb\xc0\xea\xf2\xbe\x1e8\x04\x03xF\xf1IB\x8b\x85\xc8\x8d\x8f\x9f\x1cg\xcb\xbc\x9eW\xc6\x04\xb2\x86\x12I\xba\xb7\xd6g\x87\xad\x8fgqBE\xdb\xd2\x96)ng\x94\xc5 F\xa5\xe3\x10\x84\xee\x12c\xc4s\xd3)9M\x93\x0dB#K\x01\xe5#\xb3\xae\x84I\xed\xb38j\xb9\xf7\xfbZ\xff\xedT1\xb7\xcb\x02N\xe1n#\xc3j)M('\x89a\x12A6\xb2\x17\x9f\x06\x10FU\xcd&\xe9)4\xce\xe3\xc5\xcb\xba\x0f\xb2/\x8c\xae\x01\x04\xbe\xeeMXt\x89\x19-X\x88h\x04\x07\x10\xb0\x93\xeb\xec\xd6\xd7\x14\x93\x9btf\xeexn\x07\x92\xdaI\xf5\xbe,\xed\xfc\xde\xd9\xce\x90E@F^\x8d\xbd\xb1\x90\xc3\xe6\xd9\xdc\xb1\xd9\xb6\x88O2.h\xc3\xd32\xac\xf773\xac\x9d\x1b\x1e\xd63\xf7\xb0z\x05\xd2\xc0\x9a\xf1\x03\x0e\xe1\xc5\xf1\xdb7}\xf1(\x99\xae\x84\xdaVRK\xcf\xdc\xa2\xaf\x9c\x04\xf8\xd8\x9a\xc9\xd3\xd2\xdc\xc7N\x0c\"\xf0\xb0\xe4\xe0\x08<\xc2\xbfw\x90\x9d\xf3\xea\xe0\xb3G\x07\x9c\xf5\xd9\x86\xfd\xfb\xf7\xee\xde\xbds\xef\x9b\xfb\xdf\xc16\x04\x843d\xf7C\xf1\xe7\xa3G\xb0\xdf>}\xeb\x0b%[{M\x87\x0bu$\xbe\xae\x8eD\x19\xa8\xc5\xef5\xceD\x91^\xa0|\xd08\x14;\x89\x9a\xec\xb6\xb1\xb0\x0c\xa3o\x0f0\xfc\x161\xa5>p<\xd82s\xf2\x93/M\xdf\xe0\xa73\xbf\xd1\xc0\xa9=\xbf\x93b\x9a\xd0 JO\x9e\xdd~\x817\xdd!:\xd3\xc1\x01\xec\xb4\xfd\xffLfN>*?\xc3\xd5\xb9\x9e>S\x99\xa8\x9c\xa3\xd1\xd2\x0c\x97{\xc7\xcb\xd53\x8d\x0b\xf6\xfc\x9a#+\x8dq\x7f\xd9\xe8n\"~\xc3\x13qn2~\xc3\xb7\xcb\xc5\x06}*Dm\x86\x15\xd9\x9d\x98\xf9:U\x96\x02.u\x8a\xa0Z\xb1\x10\x98\xf6j_\xfe\x89\x15\x8c;\xb23\xf2\x8b\xa8\xec\x8c\x9c`\xef*\xe7~t\xce\xafRDt\x04\x85VI\x15\x959\xa3\x03{J0\xef\xc9\xd1\x1eB\x0e\x07\x90\xab\xd0\xfdc=\x02x_94\x88\xd61\xc7\x81gP\xb0r\xee\xfc\"\xf2Qz\xab\xfe\x15$\xe4:\x8e\x9f\xa2\x9a\xbdW\xeb7\xe4\x9a\xe8\x89\xfd\x1b;\x0d6\xd2k\x87\x88\x82\xaa\x14]]\x0b\xa5e^\xafG\xd3\xdc\xba%\xf8\x8b\x99\x96dU\xe1\xed\xb5\xfc\x11EUmKV\xa5M\xdd\x117s^j\xc1\xe3\xd1\x00v1\x07\x85%\x90\xc8\x02(d\xbefUt\xd1\xce^\xf5\xa5<\xb4Z\xd5\x14\xc1v\xc61\x92/\xb2b\x13\xd3\xe6\xf5\x93|\xf8\x99\xf5\xaa\x12\x03%\n\xec\xc3\xd7\xea\xd7\x0e\xec\x89\x02\x03\x0e\xcb\x9f-\xf5\xa1~)\xa3\x01s\xca\xe5\xeaJ\xbe\xd8V\xd79 \xad\x8d`+\xc1R\x00b]Eh)\x17\xd1\xb30\xd4\x92\x96b\xb3\xf2\xbe\xb3\xe5+\xde{\xe4\xca\xa3\xa1C\xd4l\xb6\xf3\x06i\x84\xb0\xaa\x19\xd0~\xc7\xfe;'\xefo\x0f\xbd\x86\xfd\xac\x84l\xc6!\x1b\xc3\xff\xe5\xb2\x03\xdfz\x1c\x07\x92\x9a\x0b0\xc6\xfc\x1e\x88w\xe0\x10>\xf3\xb9\xc7\"\x1d)Zm\xd4\xcfL\xa5\x8c\xed\x02\xbf\xd3ZbIU^Q \xefm\x9c\x92\xf8\xdc\x87\xf3Rf\xb9!\xefbd8\x94C\xc7bq\x1e\xe5\xa5 \x00J\xff\x12\xc1\xcb~6EgZ\xebg\"?\x89\xe6\x9d\xef}\\\xc3\xbf\x8e\x1f\xf8\x9e\x11\xaa7\xed\xde\xe3y\xf2\xffq-\xbd\xeaK\xf5\xc7+\x1a\xb9\x90\xcd{\x0c?'l\xe6sN)\x99G\xef\xc5\x8do\x9c\xa7S\x01\x02\xed\xf1\xdbL\x96\xb5;W!\xa7\x08Uz\xd8\x89\xd27\xe87\xcb\xba-\xef\xd0q\xbd=\xfc\x8dy,\xc4 Q\x0bZ\x9a\x95\xbd\xe4\xb4\xeb\xe6\xd31T\x9d\x86\x9b\xd9l\xd8|\x95\xc3\xcd\x03\xda\x89\x96g[\x94\xd0\xaeY \xf4\xc7\x9a%A\xbf]3)\xfc\x1a\xe9J\xda\x10\xef\xbd\xac-\x9f\xb8\xf7C\xadiq\xef\x84\x18>\xbe \x86\xaf\x8fH\xf3\xf36TT~\xb9\x03\xa0m\xb8\"P_\xb4\xef?\xcd\xd2\x94 \xa4\x0f\xe0\xd4\xe0\x03\x81\x01b\x1f\x0d\x0f\xf4\xb4\x92\xefX\xfb\xb9\xc8\xcb\xb70<\x91\xa9\x02\x8f\x8c\xa3d\x07P\x18\x1e\xe8Y%\xe7\x86\xe7\xef\xc98\xcb'\x07\x90\x9b\x9e\xc5\xf4\x8c\x1c\xc0\xca0\x89\xf7dAb\xde\xa4\xe1YR\x1c\xc0\xccp\x7f\x9agsLmkK\x97|\x15\x01\xe9\x93\xcbE\x96\xb3\x02\x93\xc4 \xac\xbcr\xfb\xb4\xf5\x96\x05\x81\x82\xe5\xc9\x98i\xf9i\x94 ]\xdbn\x9a\x0f\x8d\xdeQ\xb3u\x15\xfb\x16G\xb0\x8c\xa0hn$L\xc6\x1e\xb00\x82-\xe3\x1e\xe6]\xa7m\xfa\xa7\xa5\x01C=OX&L;\xca\xf3,\x0fz\xaf\x13\x9aL\x132\x01r9&\x0b> \xc8\xc6\xe3e\x9e\x93\xc9\x03\xe0\x93d3\x024\xa3;s\xf5\xe2\x84\x9c\x03\xa1\xe7I\x9eQNu1\x02\x8b\xbf4]\xa6)\x10\xde*\xccIQ\xc4g\x04b:\x81x2Ix\xb3q\n3\x92.\xa6\xcb\x14.\xe2\x9c&\xf4\xac\xe8\xf7\x0c\x14\x9b\xa4\x05q\x90\xfc1\xe7i\x9a\xc0r\xf8\xf7L\xed\xfcfP\x07\x05\xeb\xe7d\x91\xc6c\x12\xdc\xfe\xbf\xc5\xed\xb3\xa8\x9b\xa8AE\xd8\xc6\xc3\xe9\xf6v;\x84\x17\x90\x8a\x85a\x9f\xc6s\x0c\x8dxN\xcf\xe3<\x89)\x83\x9f\x92,\xc5\xe4\xdb\x86\xfc\x92\xad;l\x96g\x17\x90\xf6\xa7y<'\xc5\x87\xec\x1dV\x91\xd9k\xa6b\xd3\xb0\xfa\xcb\x91\x98\x06w\xee\x86f\xdc\xcd\xaf\xdf\xba#K\xa2L~>!\xd3\x84\x12\x95\xfc\x9c\x8bE\xbd\x93\x13R\xbc\xce&\xcb\x94\xf4L\xa4T:I5\\\x9e0\x8f\x12\xe7\xbb\x9ef\xf3yF\x8f.\x19\xa1\x85\xcc\x7f\x8e\xf7\x1bwH1\x8e\x17XS\xf1UB?\xbd\x8b\xb1\xae\xa2J\x9d\xdf\xba]\xcc\xe24\xcd.\x8e>/\xe3TV#d\xfd\xd3e\x92N\xbe\xcf\xf2\xf9\xb3\x98\xc5\xe2\xb5,g$\x97OY&o\x92<\x89\xd3\xe4\x0frL\xe2|,\xda[\xc4y\xa1\xff>#\xec8\x9e/Rr<\x9e\x91\xb9\xf8\xee\xaf\x17\xc7o\xdf\x88\x9d\xd1\xe9\x01\xc6\xf2U\x07\xb3\x8c\xb6*D5\xab\x8eF\xe8\xa8o\xdd\x82^\x86\xbd\xf6D\x11\xb2\x86\xb1\xa0\xb7\xa4b\x9fNzp\x00\\\x82*\xf8\xc6\x8d\x97)\x0b\x03\x16\x86\x8ex\xd7+\x18\xc7l<\x03q8\xb6\x1e\xcb\xef\x1a\xd9\x1b\xae\xf8^\x16\x03J\xa6\xabNH\xc8F\x8e\x05\xc3|$\xf9f-\xa9<\x1c4\xfb\xc6\x1e\xe2<\x8fW\x1bt@d\xb3\xe8]\xa3\xff-\xeaI\n+\xefp\xd4\xeeH\xb0%\x92O\xd2z\x03b\x0eM\xe3\xabr\x84\x1eT\n\xae\xe6\xb3\x9eAB\x0b\x16\xd31\xc9\xa6\xb0RK\xd2\xe7[\xd2\xf5i /\xc6\x01U\xcf\x86\x8b\xb7\xd2\xb2)\xce\xb8\xcb\xb4\xbc$\xec\x8b\x8c\xce8\xdb\xea\x95\x8a\xd9\xac\xde4\xd5Nd\x98`\xf0Cv\xcc<\x0b\x05)\x15\xa3)\x87\xbb\xd2\xfd\xecF\xb0\xacP\x91\xb4\xb3\xf3v [\xe6\xf0\xc5!3$\xe80\x14\xbe\xeb*\xc6N\x879\x17\x0f\xc90\x1f\x89\xf4\x8at\x99\xa6fMt+\x13&\x82\x8cf\xf9\x1c\x0f\x0f\x81s\x03\xb8\x8c\x90N|O}\x91\xd6<\xc1vOIQ\xd2\x9dc\xd9\xc7\x92\x8eo\xbe\x175\x11\xaff\x9b\x99\x9a\x8dT\xe2u\xbc\xf0A'+\xca4\x93\xfa\xba\xf4\xa2\xf5ue\x01_Y\xa1\x8a5\xe5\xee\x84?\xdb\xa5\x84p\xc8\xef\xb1\xcb\x7f\xdb\xa8K\xc5x9^\xa7\xee$s\x1e\x08Y\xd7\x81 U\xda\xfcn\\\xdd\xa5\x18r\xb1\x01\x98\x8aU\xc1\xc8\xfc\xc3lI?\xbdN&\x93\x94\\\xc49\xf1E\x9c\xee\xfd\xcf\xfa\x93\xa4X\xf0\xb3I2\x8eH\x97\x9cp\xe9n\xd4\xf4\xb2\xd3\x82\x05\x1d[\x08\xcd\x93\x01 0\x959\x0b,\xbel`\x14#\xccw\x0d\xe7\xa0\\#\x0e\x80e\xf14\x9btC\xf9\xbcL\xb2\xa5\xaal[I4+55\xc1\x05?[.\xf8D\xfc\x93\xa8+\xe0\xec\xf7Ty\xd4m\xe8\xf5Bc\x06\xa5\x10\x19pK0\xf3\x95\\f~\x82\xf9l<\x8c\xce\xa9N9\xa5\xc0\xe1\xbc\xa7\xfc3\xd0\x8a)V/\x8a\x13\xb2\x0d\x0eu\x9a\x11\x99\x83\xc0p\xec2\xce>\xb0\x91\x1d\x96\xf5^\xfaI\x81\x9dQ\x91\xf8\xfe\xa05\x88\xf6\xfcg\xc9\xd9,M\xcef\xdd\xdc\xa5Z\xe1I6Fu\xab\x99\x01\xd9\xaa\xf8\x8c\x9e!s\xaf\x08N`\xe4\x92=\xcd(#\x94\xa94\xac\x8f\xe0\x1e\xb9S\xc5\x03\xe9\xafX'\xdf\x8d+\xb5\xec0\xba\xd2@\xa4\x83\xab\xfa\x88\x90\x0b\xdf\x8dP=\xb2\x1c\xee\x8e\"\xd44\xecE\xa8@ \xfd\x84R\x92\xff\xf8\xe1\xf5+\x91q\x18\x16\xa8V\x10r\xb2\xa8g\xbb\x80\x87\xf0\x0d\x92\xc9\xdf~\xc3\xfdJ\xa5\xe7\xdc\xd8\x99m\x86\x03\x84\xf7\x94\xaa\xae\xb7\xb7\x8b\x910\xafM+\xd8\xecE\xb05\x86\xf5\x1a\x16\xf0\x08\xbe\x15\xbd\x08\xaa\x80w\x87\xb7\x7f;\xbe\xddg\xa4`\xc18\x8c\xf8\xdb\xfc\x83\xdb\xc3\xaf~\xbb\x18i\xf7\x83\xdem9\xb2\xf5\xbal\x80\"iN\"\xf8[\xefo\xa0\xdcN\x92\x08z\x7f\xeb\xe9?\x97\xc3\x02v\xe0\xee\x08\xb6\xd1)\x9e\xf2g\xbd\x9d\x9d\xdf.\xefp\x99\xbc\xba\xf5\xf5\xed\xdeh\xb8\x18\xb9\x8de\xb8,SQ\x98\xa1\x1f/\x16\x84N\x9e\xce\x92t\x12\xc4\x9a\xc8}\x94\x12\x8efA\xafX\xc4\xb4\x17\x86\xfd\x82\xb0\xc7\x8c\xe5\xc9\xe9\x92\x91\xa0W\xb0\x15\xaa\x03\x86\xbdq\x96f\xf9\x01\xfc\x9f{\xf7\xee=\x80iF\xd9\xce\x05\x11 qO\xb3t\xf2\xa0\x17\xe1\x8a\xe1\x7f\xfa\xabxo4\\\xc0!\xae\xdd\x1d8\x84}8@\x08\xdf\x87C\xb8+\xff\xe6\xf7\xef\xc0\x01l\xdf\xfeW\x10\x07\xa7\x05\xcb\xe31[\xa7I\\\xac\xe9d\xadL\x0fk\xbeg\xd7E0_\x17$g\xe1\xe1z\xc9\xb2p}\x1a\xc4\x05Y\x93\xb3\x84\xae\xb3,\x0dHL\xc3\xc3uN\xe2O\xeb\x15#\xe1z\x8c\x8f\xf9\x81\xb3\x9e\xc5\xf9\x1aE\xdb\xc9:\x8d\x8bb\x9df\x94\xac\xb3\xf9\"]g\xb4`\xeb\x8c\xb2\x84.I\xb8\x9e\x90\xe0tyvF\xf2\xf58\x99\xc7\xe9z\x9c\xc69YO\x03\xbe\xc7\xd7$\x0f\x0f\xd7 M\xd8:\x0d\xc8Y\xcc\xc8\x9a0\x12\x1e\x86\xebI\xb6\x9ed\xcb\xd3\x94\xacI0\x9ee\xeb\xb48L\xa6\xeb\xb4 A2\x0d\x0f\xf9<\xb0\xf6\xe8\x9a.\xe7\xebsB\xd9\xfa2\x18\x93\x05[\x93\xf1z\x11\xa4\xc98a\xeb,g\xe1\x9a\x91\x80N\x8a5*M\xd69\x0d\xc3\x90w\x9d\xa6l\x96g\xcb\xb3\xd9:N\x0b\xb2Nh\x9c\x06\xe9\x8a\x0f\xe5\x92O'\x8b\xf9\xd7\x01\x89\xc73>\xfb\x84p\xb0e\xf3\xf5\x92\x8e\x03\xbe{\xf9\x00\xcf\xd2\xec4N\xd7g\x19\xcb\xd6g\xcb8\x9f\xac\x93`\xba\x9e/\x02\x81\x03\xc5Z\x1b\x04\x0d\x12\xb6F\x95~p\x92\xd11 \x0f\xd7i\xc2\xa1\xb5dk%\xfa\xacY@\xf2i<&k\x92\xd38\x0d\x0f\xc3\xc3u\x11\xae\xd3 \x9e\x9fN\xe25a\xebl\xfci\x9d\xd1\xb3p=\x0f\x92q\x9e! \\\xa3\x8ai-\xd4\x08\xe1\xfaM\xfcfM\x83xN\x8a\x05o)f\xc99Y\x93K\xb6&\x17\xeb$]gl\xbdL\xd3p\x9d\x05\xc8\x16\xad\x17\xc2\x10\xbe\xce\xd7K\xb6>'y\x9eLH\xb8^\x04\xf1\xf8S|F\xd6q\x1e\xcf\x8bu\x9e\x9c\xf3u\xc93F\xc6\x8cp@\xb0l\x9c\xa5\xeb\xe5i\x9a\x8c\xc3u\x1e\xc4 \xc7\x98 \x9ed4]\xf1\x85\x9b\xae\xcf\x92\x82\x91|\xbd 1[\x7f^&y5\xefb\xbc$k\xa1b[\xb3|\xb5\xe6T1\x0c\xd7Ep\xba\xe2\x8b\x1f\xa7d\xb2&\xe9t=\xcbr\xb6N\xce(\x99\xac\x93?\x10<1K\xc6kT\xe7\xacY\xbe\x1c\xb3\xf5\xf2\xb4\x18\xe7\xc9\x82\xad\x97\x0b\x92\xafWt<\xcb3\x9a\xfcA&\xeb\x8b\x84\x8dg!\x87\xe8|\x91\xf2\xc1\xcf\x08]\xcf\x92b=\xcb\xb3\x8b\xe2p\x9d\xc7\xb4H8\xd2\xe4K\xb2\xceW\xeb\xd5\x82\x041\xee\x8f \x99\xae\x93\xc9\x9a\xc6s\xb2\xce\xa6a\xb8^\x064\x18K4\x9f\x90i\xc0\xd9E\x8e'\x19]\xa7\xa4(\xd6\x85\x18#K\xd2p]\x90u\x91\xf0\x05:\x0f\xe2|\x9d\xe4l\x19\xa7\xeb,\x99\xacQm\xca\xd7\xe7\"\x18\xcf\xe2\xfc\x84\x89\x01\x91\x9c\xacgIJ\xd6 \x9b\x85\xeb\xcb,_\xaf\x12\x92N\xc2\xaf$\x01\x9cr~iw\x14r\x16T'9\x8a\xdc| \x97\xecM6!\xc14\x0cC\x91Al\xc1)\x94\xa0\xeb\x9cF\x1c\xf0\xf3c\xaa\x1d\x00{{\x0f`k\xb8\x17\xc1\xed\xe1o\xb7\xff\xbc\x1a\x06\xbf\xedl\x7f=x\xf8\xe8\xe0\xc1\xfa\xb7\xdf\xfa\xd1\xe1\xd6\xad\xbf\xff\xfft\xfa{{\xf8\xdb(\xac\xdfhPhI\xa0\xc7\xbc\xe3\x0cS\x93sR\xff\xb0\x07[x\xceH\x12=.\xa9\xf3\x98\x1fS\xdb\x90\xc26\x12\xe8m\xd8\x1b\x95\x7f\xee\x8f\x90 \xffvyg\xbc\xb5\xb3\xd3So\xf2{\xb7\xbf\xae\xff\xbc\xcdi\xe1\xff\x11-\x8e\x86;;\x8b\xd1\x03\x87\x07\xcf\x14\xb6\x070\xf6e.\x8d2\xda<^|\xc8\x1a|\x97M\xf5as\xb1\xe4\xc7b#\xc9~\xf9\xcapo\x04\x87\xf5\x9f\x07\xd0\xfbDV\x06\x96D)\x06\x0d\xed\xef[\xdb\xdf\xaf\xb7\xbf?\xaa1[\xaf\xe3\x85\x89\xe1k0\x90\xaf\xe3E?)\x84\x96\x04=\x81\x84\xf7\xc3\x06\x1cd\x9dc\xa4\xa2\x82\x0dE\x0b\x89\x89g\xe4\xfd\xd3*\xef\xfd^\xa5\x11\xea\xcfI~F\x02\x93\x14x.\xa3\xe5\xbbG\xc3\xdf\xe4\x8c\x155V\x07\xe2O\x0bK\xf4\xbc2\xecl\xed\x99\x9fM-:]p*=K\xe6o\x11\xc1\x04\x06(~&\x9a\x96RE\x06\x04!\xa6 \xe4\x83\x0b\xf8\xb6\x9e\xd4\x1c\x85\xc2\x07r\xd8..\x8e\xf72\xe3\x14\xc3'8\xfd\\\x8e%\xab\xc62C\x17Y\xe7Ws\x0e\x83\xceP\xf63|k\xaf\xe3\xad\x15\xe7i\x83\xb3\x08h\x99m'\x82\x9c3X\xc12\x82yS\x0d\xad_mTPB\xc7\x8a\x0b\x1d\xb1r\xfe\xc0\xec\x87\xb1H\x9a\xb72s\x83\x06b\xa1\xab\x86\x8d\xdf\x8c\xa5k\x05r\xe5\x86\xef\xa7\x9c\xfbHm\x18a\xc7\x15~ma \xdeI_n\n\xedo[\xe2\xe6\x8e\xee@\xf1\xf7\xa14\xe0M}\xe1\xd0\xba#\xc7\x14\xb7I)\xb9D\x8e\xf4\xfb$%o\xe29\xf9>\xcf\xe6R\xa6y\x96\x14\x8b\xac@\xe3\xeb\x8f$\x9ex\x94\x95W\"\xde\xedi\x92\x12~l\x0fz\xc1\xf0_\x0fF_\x87\x0f\x0e{\xb7\x93>\xb9$c\xa3\xe1\x00\xcb\x9e\x08\xdb\x00g\xea\xebm\x94MT-\xd8\x88\x93\xaa\x9e\x82\xcdh\xb2\xa1F\xaa\x8c\xf9\x19\x94\x12n\x99\xa6m\x08-\xe2b\x1c\xa7O\xe3\x82\xc0\x00\x9e\xd6\xef|/\x07\xd9 \x1a\xd9\xc3\xd3\x80Tf\xe2\xdf\xfa\xc3\x7f\xf5o\x8f\xbe\xfe\xea6\x17%B\x93\xc6*\xa6 K\xfe \x1f\xf3\xb4\xb3\x07\x0e\x802vlK\x8b\x1d\xe3\xc2\x9a\xd0u\xb8ekM18\xd6{\x0e\x8dG\xf0\x19a\x8f\xc7\x9c\xcb\xe7\xd8\x92gi\x9a\xd0\xb3\xf7\xa4Xd\xb4\xe8\x86F\xe3$\xab\x14\xfe\xfd\xa4\xd0\xb4\xff\x9a:\x84/\x8dMcP?\xf6\xccoV\xfa\xa5\xbaCx\x97Wry\xc2\x15,\xceY\xf1s\xc2fAo\xbfW\xea#u\x15*:\xe9\xf5\xc6b\xf7\xf4\xf04\xfd\xf3*\xac\xb0\xd0V\xa8\xc1LlK\xd5N\xd0\x93]\x88&\x8dv\x12K\x1b|\xcb\x06\xd40.s#a\xa9|\x93\xa6.5v\xa1\x0d2CVA\x887\x9b\xb7\xf1dB\xc8\"]\x1d\xb3\x8e\xbaLmJ\xf3\xdeP\x86\xffye\x0eLi\xe0hf09\xd9\x15\xdaU\x1cQ\x1edC6\xc2\xbdr\x08\x13\x92\x12F\x80\xdf\xe1B\x0d\xff\x87\xf3\x03\xe2\x0dj\xcce`\xcaV\xabl\x03\x06\xb2\xa7\xa2!\xbd\x08\x89)`\xd6\x95\x19HV We=\x95Y\xd7r\xa6X\xad\x16\xa4k\xc1\x89\xb0Z\x94\x87\x12 \x1d\x0c\x84F|s\xad\x89\x08\x84}o\xdf\x00R\xc5\xect\x19$\xcdQ\xc2\xe0\xe2\x13\x88#\x15\x03\xebS\xf4\xbd\xf8\x90\x95\xfe\x1c\x1ek$\xbe\xb1\xac\x91\xd6\x9b\x15M\x1a\xa6\xbf\xfa{\xe7\xb2\x92\xe7I@\x83oL>\x12ctH\xba\xf7\xcd\x9e\xe1\xd9T~x\xef\x1b\xa3{\xc5B\xb9f|\xbbkz<)\x1f\xdf5=\x9e\x95\x8f\x8d\xe3:\x97\x8f\xef\xdf36>W.%\xbb\xf7L\x8f\xcfpV{\xdf\x99x\xff\x95\xfc\xf4\x8eqR\xa7\nX\xfbw8\xe2\xd7\x9e\x97\x04\xfa\xa4\xc3w\xe1\xd6-\x0c\xe1P\xbeU\xd2\xb5\xd8\x8c\x8b\x12\xa5M\xa5\xea\x9bQ\xf3\xfa/\xbe\xb0\x170\x80\xf2\x08lO\xe5\xc8\xe0\xc0\xd3\xad\xd9o\xc9\xc8fsL{\xb06`]ndv\xae\n\x047&on\xfc\xd8\xd9\xf8\xd6\x16q\xdaW}(\x95c\x0dtO\xa9\x89\xfa\xc8\x06\x86\xa7\xce\x91\xf2~\x17U\xbf\xfc\xe7\xd4\x7f\x18u\x07\xaeN\x16\xce\xa1\xf8\xd9\x8c\x8b\x18Z\xc4a\x0b\x8br\xc7\xda\xf8\x9dz\xe3wD\xe3NN\xbcn\xa2\x97} \xefQ\x7f\xc8\xca\x87\xeb5 `\xcfk\xc7\x88\x0e-\xab\xfd\x18\x9d\x84\xab\xfc\xdf\xb4b\xbfM\x9a\x15\xd0\xfd\x00\x86\xd4\x92\xf6\xces\xa3\xc1!h\x02AR\x04\x182\xc5Q\xd5\xcaq\xf9\xa05\n?\xb6\x06|\xfc\x0e\xf0\x08'\xf8i\xd6&\x06\x82{k\xd4l\xeb*`\xb3\xc5{\x99k\xc3\x1cR\xceY\x0d\xa9\xc1\xeau\xd5\xdc\x12\xeds\xef\x93\xc5\xe1\xb1s\x7f\x80\xb2\xa7\xc2#\xa8\xc2\xc4{?\xc5\xe9\x92\xc0|Y08%\x90\x92\xa2\x006\x8b)\xc8\x96\xbd\xca\xd9?\xb68fn0\xa6\x87\xf61\x9d\xa1\xc2=\x97\xc3\x12\x8d{\x0d\xeb\xad\xd9\x85\xb4\xfb\xb4@9\xf3\xf6\xbfv\x0e\x7f\x9bl\x07\xbf\xf5\xf9?\xe1\xa1\xb2\x0chRjc\xa01H\xb6\xc7gp\xef,>\xaf\x9b\x8d\xcecP\x14#\x01\xcf<\x87\xf5\xc1\xe4\x9b\xeb7&<\x95\xb6\x02\xe2\xf0)\xb4Cn\x9a\xa4\xc4k\x80\xaf-\x0e\xc5~c\xec\xb1|Iz\xb2n0?D\xa7qZ\xe87\xb6v\xb5\xbf\xf7\x14#o\x1b\xf5\xa9\xe8\xdek\xe0\xcf\xcd\xce\xd1~\xe3\x16\x835\xa8{\xecc\x93/\xfb\x0c\xedw\x9b3\xb7\xdf\xe0\x92\xe2M\xfc&\xe0\x9f\x95\xce\xc2\x8e\x95V\xcd{\x8d\xec\x8d\xc9\xef\xdcoTJ\xd8S\xa2F\x9fe\xaf\xb2\x0b\x92?\x8d\x0b\x12\x84\x11l\xdd\xfe\xd7\xf0\xcf`t8\xdc\xdd\xf9.\xde\x99\x8e\xfe\xfc\xf6j\xa7\xfc\xfb\xae\xc7\xdf{\xfbW\xc3\xf0j\xe4E\x18\xf8\xc8\xbd&\xfc\xde\xea~\xefOL+\xde\xc4\x8f\xce\x8b.\xbc\x86\xf7\xcc\x1a3\xb0\xf9\xf06 \xf9\x1b\x8c\xf0\x95%\xd2\xc1{|[\x94\\\xc0{rvt\x89\xfe\xc8\xae\xa5\x9dfi\x9a]\xc0Bv\xd2\x83m\x93\x03{\xfd\x0co\xc7et\x8e\xec\xba\x9c\xed\xad[\xb5\xdfv\xae\xd6\xc6\xf1\"\xab\x87\x94\xe74\x9b\xac\xa4RY\xa8\x17\x13\xda\x13N\xf2\xf8\x0b\xcdX'\x97\xf3\xb4\x87\xee\xf2\xda\xcd\x9eEU\x99T\xea\xce\x9c\xa0\x9b\xc2\xc4\xf6j\x0c\xc2;J\xbe^`\x84\x8b\xe8\xc8\xa2\"\x8e\xcb\xd5\xca\xedv\xc7X47\x97|\x8e\xa5\xf3\xb1\xf6\xa6d=,oN\xab79q\xb6\xbd\xb6\xa8^\x9bf\xf9\x8f\xe0,\x82\xd3\x08N\"\xb8\x88\xe0(\x82\xcb\x08\x8eG\x0d\xe1\xd59\xf6J\xdfd|\xc5V\x92\x0eYB\xe4\x9f\x9f\x86\xcd\xb9\xbf\x97\xb4\x1e\xa6 I'\x90\x14@3\x06\x8b<;O&x\x02\x98(\xb6j\xf4\xdc5X>\xf1\x8f0\x80WA\x16\xc1\xb9\xc3%\xe1#\x1a8\xc4x>\xfa\xba\x1a\x80\x1c\xc2\xa4\xda:\x93\xae\xd1|\x86\x01\xbc\xe7\xa3\x998F\xf3Y\x1b\xcd\xe7MG3\xeb\x1a\xc2\xf70\x80g|\x083\xc7\x10\xbe\xd7\x86\xf0\xfd\xa6CXV\x00q\x96\x1d\xe1\xa3\xf9\x03S]a\x91\x11\xfbh\xfe\xd0F\xf3\xc7\xa6\xa3\x19W\xa3\x19w\x8d\xe6 \x0c\xe01\x1f\xcd\xd81\x9a'\xdah\x9el:\x9a\xfa\x91\xd85\x9e\x9f\x1c^K\xeaB\xee&\xf8 5\xe41#;\x8c\xcbQ\xd8\xfc\x02\x0e\xe1\xf7\x00Uh\xbd%\x176\xca\xbbo\xc4\xdd\xe7\x82\x88\xda\xf9\"u\xc9\xd9\xfedsb\xa9\xc8l\xfd`\xeb\x9a\xdf\x8f0\x80\xd7\x81\xab\xda\n\xce\xee\xc7\x0d\xc6\xf8c\xf7\x18k\x87g\xd7\x10\x7f\x86\x01\xbc\xed\x1e\xe2\xcf\x1b\x0c\xf1\xe7\xee!\xd6O\xe8\xae1\xbe\xc0\xec\x8d\x9dc|\xb1\xc1\x18_t\x8fQg\xb0\xbaF\xf8k\xc7\xd0N\x91\xf9)\xd90\x9f\x81\xfe\xaax\xd6\xe74\x18\xf6\x12F\xe6E/\x02\xc1g\x8f0\xc9N\xcb\xcc\xdd\xe5\xe9\x01\x9a`\xd5\xb5\xed\xf8U\xc3\xa4_\xd1E\x82#\x0b\x86\xaa\xd6\x97P=|'\x1f\xeaT\xe0Wd\xc0\xf8\xd3\xe7\\\xa8\x8c\xa4\xb9]\xac\x83{\xb0\xfcJDVKC\xde\x95\xe6\x85\x995\x0e,\x99\xc4\xd4\xe5\xac7\xdb\x89\x13\x1a\x83\xdc\x85\x12/a\x00\x1f\xba\x91\xf6\xa5\x0f.H`\xbd\xf4\xa5\xc6V\xab\xb7\xc1{\xa5\x9dF\xc1\xcd))7\xa3/w66X:Az\x05m*\xf6\xb7\x0cZ\xa6\xf8g\x0e\xef\xdb\x97\xf3T\xea\xae\x98U\xbeK\x84\xcf\xd5\xe5<\xc5m\x8b\x7fa~\x12\xd7\x9a\x0b=\x0f\xff\x86K\xf9\xf2\xdb?\xaf\"\xfe\xfdW_\xe5d\xaa;\x03\xac\x16\xe8\xb4F\xfa\xb8\xaf\xc5\x9f\x0b\x91\xcf#!\xf2w\x95\x16\xe6]\xf5\xe4\x10\xfe\xf6\xf0\x907~N\xf2\"\xc9\xe8\xa0\xb7\xd7\xdf\xed\x01\xa1\xe3l\x92\xd0\xb3A\xef\xe3\x87\xefw\xbe\xed\x1d>\xfa\x8dJ\xb7v\xf8\xe5\xf5+ \x97\xb8\xc40\x8e)g>O \x9c\x11\x8a\xc9\x19' B\x94\xfef\xf5~R\xd7yY^\n\xa7\xd3\x9fsQ \xb8\xfd\xdb\xf1\xd7\xbf\xdd\x0e~;\xde\x0e\xbf\xba\xed@\xf6\n\x88\xb2\x84\x94'*C\xddXx\xa6,\xb5\x93\xa7\xa8/\xfb\xe5\xf5\xab#17\xe1J\xe2\xe3\x01r.\xcb\xaa\xd5\xdb\x13\x9b\xe0\xfb<\x9b\x8b\x8d \xdbk\xcfH)\xc5l\x92]\xd2%\xd9%a\x08\x87M?\x98\xa4\xf2\x83\x81\x83F\x8eJ\xe9\xa3\xa9\xa7?q\xba}\x9d\xcb\xcc\x86\x7f\x1at\x85 \x93\x17V\xe2|\x9a\x8d1\xcbN\xbf\xc0\xc6-\xfa\xa5Joi\xdbZ=\xa1\xa4w)MD\x16\x94byZ\xb0<\xd8\x0b\xfb\xc5\"MX\xd0\xbbe\xd2\xc6\x80\xee\x9f\x9eCB\x81\x86@\xfb\xb3\xb8x{A\xcb\xdc7\xb9pS\xc4(\xc3a>R-\x0e\xb8XE\x86\x132\xce&\xe4\xe3\xfb\xe7O\xb3\xf9\"\xa3\x84\xb2 \x1f\xee\x8e\xc2\x11\x0c \xe7T\xe8\xd6-0\xbe\xb37\x12v\xd5\x9e\x0f>\xa9m\xdd^\xb3v\x1a\x1b7m\xb5Z\xc5\xfd\xca\x97\xab\x81\xd0\xd6\x8cD\xca\xfdA\x0f\xb6MO\xc9\x90\x19\x0d\xb3\xfd\xdf\xb3\x84\xe2\xf2\xb4\xa7&S\xf5\xb8\x07\xa5\xe6S\xcb\xb9\xa1r\x17Sr\x01$`\x9a\xb9\"\x82\xde\x92Mw\xbe\xed\x85au\xb7w\x1a\x17\xe4\xfe]\xd3\x18\xaa\xd4A\xed\xae3\x0c6K2Z\x1c\xe3[6\xaf\x9d8]\xccb\xcf\\\x83\xa0\xbb\x8f)m\xe2\xac\x17\xe2\x16J \x07h\x9c\xf3)i\xcf,G\xb6yc\xce \x9be\x93k\x8fF|n\x1b\x8fz\xea\xcdD\xb4\xc7\xc8\xe2\xb3\xbf\n\x9c\x8d!{\x0f\xd2\x80\x99\x8d\x14S~\xec\x8c\xc9I\xa5\x8a\x8d\xe6\xe4\xc7z\xfa+_^b\xf5\x10\xd1\xd8\x96\x1c5\x88\xbd\xeao&x\xbb!\x8d\xf8\x06\x8dL\xfb3\x0f\xb5\xc4k\xfb\xbb\xb7\xcf\"\xe8m\xf7\xc2\x91\xdc\x9f\xa6%\xb5R)\xe6\xda\xd4\x86\x94]\xb5\x95\xb48\xd6\x94J3N\xb8f\x15\xe1\xa2\x9aSN\x97\xcb\xc8F\x1e#\xf5\x91\xd7a\xae\x94b\x96\xbcd^\x04\xd8X\xa0\x063\x8ektL\x9a\xb31\xa5Q\x9e\xcc\x03m\x91~\xc3\xecx\xbd\x13\xb4\xd8\xf4z\xae\xe1Z\xb2\xaay\x0d\x93\xc3\xec\xb4\x82\xd9\xc7\xb6{Yd\xc8\xe3\xe6\xd54ig\x9b\xe8N\xc2z\xfb_\x97;%s\xdd\xb9l\x915\xf7\xdc_9Bi\xffY\x97\xf6\xa5ui=ZK\xbb\xd8ZZ\xbd\xfc\xa7\xf2?\xd5\x83\xb2\x90\x16\x0d\xee\xdd\x0d\xfbO\x96\xd3)\x91\xde\xe2\xd7\xca\x06hN\x88\xd9\x9cfI\xa9\x8c\x92\x99\xc8\x15\x0f\xff\x7f\xf2\xde\xbc\xbbm\x1cK\x14\xff\xbf?\xc55\xa7_\x8a,\xd3\xb4$\xaf\x91\xedx\xb28\xdd\x99\xc9\xf6b\xa7\xea\xd7\xa3\xf2xh\n\x92\xd8\xa1H\x15\x17;\xae\xb2\xe7\xb3\xff\x0e.\x00\x12\x04\x01\x92rR\xd3\xfd\xde\xe3\xc9\x89E\x12\xc4r\x01\\\xdc\xfd\x9e@\x15\xcb\xf2\x13\xf1\x83\x9c\xc7\xa2\xfc\x17$\x0b(\x81p\x047a\x16\xe6\xb0\xc8\xf3\xd5x{{\xe6\x07\xe4:I\xbex\xf30_\x14\xd7^\x98l\xa7\xf4\xbb\xedi\x12d\xdb\xf8\xf1\x16#\x9fRo\x91/\xa3\xd3P\xc4nd\x94\x86\xcb\xf3\xb9A\n\xc7\x90\x1fA\xba\xb9\xe9@\x0c\x9b'`=\xf1\xd3y6\xb94Q$\x157\x97\xa2\xcb\xaeB\x1f\xb2:\xeaq5ED\xcd$\xed\x1f\x94\xb3\n\xc8\x99uG\xe2l\xa2\x99\xa4\x16\x1dS\xe5\x15\x98C[\xd2\x1a\xd8\x12\xc58j\xc4\xca\xca\n\xef\xbb\xc4\xa8'\x14\xd8\xe7\xa4\x1f\xac\x932\x1a\xf1#\x9a\xacB\x19\xcbcf\x1d\xa8nz\xf5#\xcb\xfd\xe0\xcb#\xba\x80\x11\x98\xd9\xb8\xe9/:r\xfa\xb7W\x9b!\xb7\xd0}D\xb3\xc2\xb8\x17[\xd6\x18\xfd\xf6j?\xc5H\xcfk\xb5^\xd4\xb3\xbd\x88\xa8=\xad\xca\xa8\xf2\x84\xc84'\x04\x8b\xac\xc3\x8c\x102x\x06{p\n\x19l\xc1\x1e\x8c1\xf3R\x00'\xb0w\x04\x01\x1cCv\x04\x01E\xe3\xd1$\xa0\x05.\xe5\xda&AKb\xf0\x1b\xee\xa5n\xb6\xa3\x86R\xdb3\x93\xe9\xac\xd4c\xc1\xb0\x8d\xe2:q\xd1\x16\xd0\xd4\xc4\x9eux\x8a\x03\xb75 \xdb\xe5\xdf\x1c\xdcR,h\x8a\xc3\xa3p\x8afOSzb\xc2\x7f\xd1\x9f\x05\xfd\xf9_\x90\xcc\x90Zd\xcfV\xecYV\xacV\x11=\x7f\xf2\x84=O\xf0\xb9\x0b\xe4\xeb\n\x03\x9c\x80\x1fC\xe9\xd8\xe1\xfd=\xe3\xa1\xbf=\x8d\xe8A\\z)\x19\xc8\xb3\xbch\xe5X\xc4EK\xde \xe7\xb2\xe8H\xe9\xde\xa9\x8b\x16\x97\xb0\x8d\x99\x95\xd9\x03\xdb\xacN\xe4\x0b\x1d\xf3y\x1eJ\x91~h\xb2taQ\xaeo\n9\x8f\xc2pQfP\x88\xda<\xf1\xc5E;?/\xe5W\xf3\xd6\xf2f\xd8\x1a\x82\xc5\xf5\xda\xe4\xd9\xc2_\x911\xac\x9aoD\xa07\xed\xcb\xa5\xbfzY\xbe\xef\x8d\x1ef\x88\x9c\x1ew\x06F\x18\xe5>\xb3\xf5\xe7\xb6\xb6\x87X\xbc\xd9Z\xdb\xf9\x8a\x9f\xf4<+\xb5'#V\xd0<\xeb\xdaN6\xb9\xcd\xae\xb3\xcap2\xb1V\x0dg\x8d\xae\x9f\xbf\xf2~\xfe\xca\xfb\xf9+\xf6\xf3WM\xd9\x94\xc7\xfb\xcfl\x8b\xed\x7f\xcb\xed?\xe1D\x87.\x9b\xb3\xadi6,S,d\xf6\x9a\xc7\x99\xec&&z\n~\xb3\xaf\x82+\x11|t}\xbb\xf2\x11h\x9c\xc7\x84\xfeu\\\x1f\x1e\xb3R\xa5\xef\x85\xfc}\xac\x8e_\xf4\x97\x16\xaa0+r\x1ae\xcen\xbb\x14>\x03\x06F\xac\x05\xdf}\xd0\x8c\xac\xd00]\xe2]\xce\x8f\xe1\xb4\x0c\x9e\xa7\x9b\xb0\xb5N\xe0}~\x02\xefK'\xf0\xbe\xee\x04\xde\xef>\x81\x05\xd5\x00'\x80\xa6+)\x0b\x9e\xc7\x8c\x1c]\xe1\xbd\xcb\xe2\xb3\x9e\x02QQpm`2\xe2\xe5\xc9\xe8\xa5\xe3\xb14u\xa2\xc0\xf6\x1b\xe7\xe3\xad\xcfl\x9f\xb2\x15 \x18S\x16\xc6\xac@\x88\x05<\x94\x97\xb0\x86\xebk\xad\xb1\xa2\x98&A\n\x0f\xbc1t\xb4++\xf6\xc2\xac\xec\x96\xfa\xcd\xa0\x16\\U7\xed\x99\x96\xfco\xd2ar\xf4D\xed\xec\x8b\x89\xa7P6\xa9X\xec\xac\xd5\xe44B\xda\xa6#\x87\x8f\x81X \xdb\x89\x95\xa8/\xb1\xf2_\xa5\xac\xe0\xbft\x14\x8aQ\xec\xd8\x8c;\xe2\xb4\xc2=2\xc9\x1b\x9b\xa0\xaf\xe0\xaeI\n\x02\xf2\xc6\x8b\xb4\x1b/(7^\xc4I\xdfH\"}g\x8c\xf4\x9d\xc11DG0\xa3\x1b/\x98\xcc\x9a\xa4\xef\xcc\x10\xd0i\x85\xaa\xa6\xc44\xe7\xb1\xbdj\x9ds\xbaf\x0b3\xfd\x84F\xd0\xf6\xeaQKB\xa2_3\xcd\x92X\x18\x96D\xd8E\xbf\xa2K\x00#\xd5\xfa,\x10fW\xc1'S\xef\xe7\xa3\x19\x00-#\x1ce\x0d]\xc4y_\xa5\xc9\xea\xa2\x1cS\xd6\xe8{\xb9\xe2\xb4\x99V\xca\x95s\x83\x91\xab\xca\xc8\xf5.\x92\xb8\x03\x97\xd3\xac<\xa1-,\xe1\x18\xe6G\xb0\xa4\x8b\xc4<\xa5\x18ZJE\xb27.,\xcbEL{9\xa1\xfd]\xd2_\x97V\x89t\x03\x13\xb5K\x81x'\x9f\x82\x08\xae\x12\x80w\x1d\xf3\xd0\xb1\x19\x85xC\x17.\xbb\xb9\x1f[\xb7`\xa2\xdd\x82a\xb9\x05\x13\xc7\xe5 \x10\xc1\x87cH\x8e\xc0\xa7\xd0\x0c'~}\xbb\xf9\xe6s\x0eQ\x07vU\x01r\x88:]\x16\x7f \xf3\x8d\xb8r\xb7\xab!\xa2[\xae~\xfe\xcaq\x84\xdaq\xf8\xe58B\x8eJB \x95\x14\x0c\x95\x14p\x0c\xe1\x11\x14t\\\xfe\xa4h\xa2\x92\xc2\xa4E\xe2(\x8cLrC \xe3^\xca\xda\xf6\xd2\x17r\x97]H\xfb\xc9NV\\\x08\x9a\x91 \x89\xa7e\xd7\x9c\xe6V\x8bM[\xad\xc9\xe6\xb6o5\x90\xa1\x8b\xe1~\xe5H=\xe5\xbe\x9b\xb1}G\xb1jP\xee;\x8a\x9cW\x1c9\x9b9T\x81N3u\xef\x05.\xcc\xca\x99G\xa4\xb8\xf5\x8c\x02\xc5\xa6\xe3\x08&\xb3K\xfa\xcc\xa9v\xa1\xdf\xc6s2\x8bi\xe3Nl\x92\xe5\xa0\xc5\x8a\x0fNs\xf5\xea\x0f\x98l\x9d\x9d<3\xd3\xe7\x92\x05\x8bb\xb7U1\x060\xae\xbdk\x9eK\xb1\xa9\"\xb4\xd1\xd2r\x15\xb5:G\x97Z\"\xee\xff\xa5\xd3\xfe\xb1\xc7y\xd1~\x9cO\xff\x87\x8e\xf3\x9b2\xcec%\xffi=X\xbb4\xebK\xc4x7-\x18o\xd9\xb5\xeb\xe9)\xbdTw\xfd\xc2\x85\x9b\xda\x89\x8b\x1c\xe2M\xf7Y\x0b=%J\x9d\xc6\n\xed[u\xd5\xdc\xaa\x95|G\xfeT\xfc\x925\x85\xcc~\xecQ\x8a\xa3\xed\x1f\xcb\x9f\x8c\xc3\xde\xf2\xb3,\x9cWl\x92\x1d8p\x1e\xc6\xd3\x94\xc0y\x92.\x8a\n\x01\xfdk\x14\x06$\xce\x08\xbc{sQ>\xfcq\xbb\xfc)tR<\x8d\xd9\x9c\xe4\x92)\xd7\xf9\xdd\xf2:\x89\xb2\xa6\xae\x8a\x97\xae%\xb9\x94\xbek\xea\xae\x1a\x1fp\xcb\xca\xbb7\xd9Y\\,\x19\xda9\xd2\xc2\xcdH\xc4\xe8=\xa9pS\xf3\xe6\x18\x94Z\xc3\x89\xdcp\xbb<\xba\x83\x85u\x93\x7f\x1d\x98|\x11\xc9\x04\xb1\x8e5%\x96\x0b\xd6\x1e\xb34\xd4\xc2\xee\xbd\xbf$\x99M\x9c\xc9\xe0\xb2\xb5\x0355\xf1\xef\x0fL)<8\x82\x18\x8eaH\xffR\x84\x97O\xac+\xba\x15X\x0f1\x0f\xd3\xcb\x85\x9f\xbeL\xa6\xc4\x8e\xd1t.\xd6\xf7\xd7\x1a\x0cG;\xbb{\xfb\x07\x87O\x99}KK_s\xc5\xa6\xadK\xc4\x95\xabq\x84\x00$\x0b5\xab=\x8c\x8bXw-I\x91\xe8\xc9p3\xb4\xb6\xb2\xd2\xb6\xc2\x94\xd7\xc4\xbb\x9aE\xfe<\x83'PPZ\xe5\xa5\x1f,\x08K\xa5@[\xd1\xcbxo\xcaLG\x154\xe8\x17)\xd1$\x80\x06\x11\xa7\x82%m\xc2\x82M\x9c@\xc6\xb2\xb8\x02\xed\xe7\xb55!zV\xed\xea\xc3Vm\xfb\x0d\x8fx\x1fO\xc2\x8e8\xea\x19\x02\xddw\xbc\xabi\xb2|\xf3\xaa\x9d\xa2f\x16\xb2Z\xaeN\xbepTGU\xd4\xd1\xe4\x08\xa1\x91`P\xfa\xf3\xf0:\n\xe3\xb9Yy..\xda`d'\x94\x8b\xecjP\\3\xdbw\xa1\xcd\xa3K\xbe\x02\x9e\x91FC\x08\xa8\x97Y\xe7L\xaf\xd4\xb6vF\x16\xed\xa7\xb1\x98A5\xdd\\\x12bi\xde\x9f\xe8\xd7\xe6\x9f\xf4\xdf\xeb\xb6\xc0\xb4\xb9\xb5\x19\xd1\x9aU4(\xbd92\xec~&qa\x96\xd7\xb0\x81%M\xc4\x03w\x7f#\x98\xda\xdb[\xf9)\x89q\xc3:\xb2vA\xb3\x01p?U\xc5\x0d\x83\x83jI\x91\xd2U\x11\x87q\x84U\xa4\xde*Y\xd9\x8e\x83\xd8\x8a\xf6Y\x98U>y\x02+z\x96\xaa(E\x90\xac\x7fj\xb6%\xb8\xe3\xfa8\xe7$\x7f\x19%\x19\xc9rq\xc6\xbcN\x93%\xed\xf2\x18\xa6\xaeZ\xb4Y\xa6\x9d\xfc\x12\xf4\xfeT\x1b\x97^\x82 \xca\x0b\x99I\xba\x84\x13y\x18\xc2\x9c\xfb\x87\xd5\x81\xd8\xe8\x1c\xfd\x86vLt\xb2\xabsa=\xfb:\x91Z\xc6\x98\xcc\xd6\xce\x0e\xba\xf2T\xcf%7\xba\xf2Y\x07\xa7\xc3V\x98T\xdc\x11V\xf7\xa4\xaa\xfb#\xae\x13\xd4\x8f\xda\xd6\xce.\xb6\n'\xf5\xb7\x86v\x8e\xca@\xfcl\xc5\xe4b\xc5\xe01!\xf7\xdd\x08\x7f\xa9P\x1b\x84W) \xe8\x96\xadvl\xc3nD\x14\xe1KC!ub\xf9]\xafe\xd3\nf&L\xe7\xd1\xb2\xe9\xc9Y\x1b.\xdd/E\x14\x19\x8d\xa5\xf5<\xf8\x02\x9f\xaa\x04\xa4\xdc\xc5\xea\xb0\xac\xbeR\xce{\xe6\x1d9\x06k\xe4\xedy{\x96\xaeMM\xc0\xe6\xab+\x86\x01\xe8\xdf\x13q^~+);\xd0\x19\xe0N\xac/a<\xa5|}J\xb2$\xba!,\xf7Z\x9ca\xae)z#D\xc8\x1ff\xf4n\x95\x92i\x18\xf89a\x9f\xacR\x92\x91\x18\xcbq\xf3\xffs\x9e\xec\x8de}{\x1e\x85~F2\xeb\xb2I.O\xac,\xf0#?\xc5\xb2\xe4\xd7\x82\xc4\x01~\xb7\xf4W\xab0\x9e[\x97\x1d\x92\x11#y\xe5\x82__ \xe1\x8c\xe5\xb9\xc8\x85'\xac\xcc\xe1\xe6}\xc3\xb4\xd3Z\xb6x\xd8 \x0f\x9d\xc1?\xcc\xd0w\xb7b\x1bS\xfb\x87\xcf\xf1\x978\xb9\x8d\x81\xa9.\xc0\xfa\x81\x13\xa8?X\x10f\xb0$9%\x80\x90KD\x03oHf\xac\x0cae\xfe\xf6\xfc\xdd[\\\x04\xde\x0f\xcaju\\\xc8\x17a\xe6\xe5\xfe\x9c\xae8~G'\x0f7:\xfe\xe0\xf1\xed\xf9;>\xa1\xf8Z\xfc\xbe\xbf7\x8b\x96@b\xd3\x15\xb3\x07^c\xb9.\x98[Ky'\xd7\xda\xea*\xa1\xad\xb5Z`,\xbctu[\x1fO\xb9\xf4\x18f+\xef\xd4Q\xf35\xc9\xc7-\xee\xea\xa5\xe4\xc5\x8a\x05k\x0f\xeae\xe5\x85\x8c\xec\x1cs\x1e\x95\x9f\x96\x1f\xf8B\x9e%hB\x8c1 \xaf\xb7\xb8\xaf\x08'\x9e\x90\xcb\x9eK\x93^\xfe\xa4d\xc6LR\x9f\xc6\x82\xf2\x1d\x17\xf8\x92\x0e\xab%-\xd6\x95ii\xe3Rc\x0b\xbb\\\x82b\x81W\x165\xf4@\xea\\\xd9\xbdx\xf4\n\x85\x8dvG\x8em\xdd~\xc9\xd4\xf8j\x8c+\x1f\xee\x1b\xd8\xf2\x1d\xc7cR\xdd&s\xaeM\xdc+\x99\xe3\xda\xfd\xfc^\xf8\x02G\x91\xdb\xfd=\xd8\\\xf6\xe6\xd3\xd9\x0f\xc5C\x1f\xf5\xb0cH\x1c\xdbb\xfda\xc6`\x92\xb3\xd4\x83\xe3ey\x82\xa9\x92\xd3>\xb0\xd1#\xfd\\\x0e\x15_\x0f\xdc%\x80\x19\xda\xb1\xbd\xb7\x7f\xa8\x06\xacO\xf8\xab\xa7CG+7\x08\x8dC\xef\x1f\xa3\xde\x10\x9f\xfe\xe1O\xcd_\xe5\xbel\x13\x89\x0bmD\xdb\xc1\x00\x1c\x81\xab\xf6}\x15\x11\xa7\x17\x81)\xce\xf1\xa5\xf0\xae\xfa\xb0\xb3Y\x90\x08\x05S\xb0Gz\xa5,_\x96\xf1}\x88!\xe1\xcc\xef\xfd\x8e`*\xed1\xd8J:\xb5`bH%\xeb\x19\xc1\xbck\x98\xe3\xa6@\xd5u-\xef\x1a\xe3V\x18%[\xb0\xbcj\x94EbHW\x8e\xa4\x9e;G|\x9c\x06\xe6\xb5_`\xb7\x90\xa7\x16\xf3\xb5\x88\x0e\xa0_\xbe\xaf\xee\xa0t\x1b\xe8\x18\x9bIi\xc6\xb2\xf64c\xd0\xb3i\xe0\xcb+\x14(\xd67W\xa7\x1f\x9f\xf6\xa9\xe0\xa1\x1a/\x1f\xd8\xea\xd4\xd0\xcd:\x91\xb7\xd0\xe6\xfayN\x96\xab\x1c\xf2\x04\xa6\x84\x1d\xf5E\xca\xbc\xd9\x84\xbdni`\xa0*\x03\xaa\xcdl\xf7\xa2^%:u\xbf\x1d\xc9\x0f\xf7\xb5H~4\xfc\xbf\x16\xc9K\x07\xa0^\x1c=\xdc\xd3\x82d\xf7\xa9F\x1a\x1d\xdb\x0d!u\xc1\x1e\xab\xa9M\xfaz]\xa3\xf2\xc1\x05f\xbd\xb2\x02\x0c\xe0\x0d\x99\xf7Z\x8f\xaa\xa6e\x81\xbf\xe8\x0b,\xca\x02\xe7\xfa\x027e\x81\x8f\xfa\x02\xcb\xb2\xc0\x0b}\x81yY\xe0g}\x81;8\x81)\x9cB\"\x92.\xd1\x99\xe5\xd9\x97~7e\x11\xbb\xc6h&\xa5\xb6W_\xe8\x8a\xd7\x9c\xc2\x18\x16\xf4/\xcb\xecd\xa7\xbc\x95\xdf\x1f\x9c\xaa\n\x03\x9b\x8f\x9a\x9ei)\"\xca\x1d:1\x98\x9a|\x03\xf3\xe0^)\x11\x8a\xae&\x11\xd3\xb1\x14\xf6\x1d\xaa\x7f\xe8h(\xb1\x1d\xc0)\xbe\x841\xaa\x81\\\xb8c:!\xac[k\xbf\x85\xa5O\xb14\x8caI\xcb\xd1JB{\x86&yc\x98c\x07\xb0\x9a\x13\x98\xc1i\x07c\x00\x12\x83_\xd1\xb8z\x0b?\xf9B\x96n\x11f\xb5x\x1e]\xe2\xd3\x0c\xf3#\x83\xad\xea\xd6\xba\xbe\xa3W\xe0g\x04\x06\xe3\xcerP\xb7\x8f\xd1L\xa1za\xcd\xc3\xf5k\xb6u\xf8\\\xbd\xb0\xf2\xd1c*\xd7\xc60\x92\xaf\x0ea\xb1Z\x996W\x99\xb8\xccu\x95b)f5C\xe7\xdc\xad\x94\xa3\xfa\x1a5\xdau\x90\xc4\xa1\xd5\xfebr\xd9r\xc3\xea\x02\x88\xb3d\xd47\xca\x86\xa8N\x91\x19\xae\xfe\xd7\xfc\x0d\xaa5]\xc0of.\xfb\xcc\xb6\xef\xbc\x1b\x96\x14\x1b7^u\x87\xb8\xc4a[n\xe6r\x8c\xf4\x89~sM\xff\xdb\xb8\xa6\xaf\x9e<\x01\xdf\xbev\x01\xab5\xa7(\xc9\xbc\xd7\xcci;\xf3\xfe\x02'0\xa2?\xce\xe1\x04v\xe9\x8f\x8fp\x02\x87\xf4\xc7\x0bZf\x9f\xfe\xfa\x19N`\x07K}\x86\x13\xd8\xc7b\x9f\xe8\xdb\xd1\xa1[\x93\xb70Q\xfc\xbaR09\xeeT\x85=n\xc3x\x9a\xdc\xd2!\xb1_\xde;\x0c2q\x82ZL8\x15\xef\xc7\x86\xcf3\x12a\x10e\xfaW\xfd\x14\xdf\x8dAL\x84m\x89\xd9^\x84\x99\xe5\xc8\xa6_Zq\xdb\x9c\x8b\xdb\xe6\xdf(n\xeb\xe2\xbc\\~b\x8f\xf6\xd5\xd3\x16\x03\x81\xd1S\x9eE\xcaN\xeb\x9cT\xda\xceI\xa5\xa6e\xa1e\xa0\xda=\x1aPBEx`\xb0\xb0\x96\xd9(w\xb5\xc7\x7fT\x901h\xd4\x83\xa44r\x1ak9\x9b \x89g\xe1\xbch)q\x9b\x86\xb9x[\x1f\"\x86\xa0g\x07r\xec\xd6T\xb1\xd0=wfym \xd1\xd8\xde\xdb\xd9Q\xa6\xa8\x9a\x91Z\x7f\xf4M\xeavH\x8d\xfb\xd4\x8b7\xe3>\xfd\xff\xc6\xb5\xa7\x8e\xeb\x8f_z\xe52j\x17\x15\xd6\x94%\xc3#\xc8\xb5\x860\xb9\xde\x10\xe6F\xcd\xd4\xa0\xb5NoDr\xeb\xb0\xea+\x0dUx\x8072I/\xb9\xf7\x94\x89\xe3\x01\xbd\x89\x00=\xa8\xde\xef\xef\x0d\x06\x07\xec\xfd\xfe\xde\xde\xce\x1e]I\xfc\xd7\x13`\xf2&z\xb7\xaby.*\x1c\x94\x95\x1d\xb2\xe7\xc3a\x95]J\x14\x1a\xee\x96\xa5v\x86\xb5\xcf\x87\xa3\x83\xf2\xd5p\xef\xa9\x03<\xbf\xd63\x18\x0e\x87\xbb\xc3\xe1\xd0a\x97\x04\xd3&T4\xbe\xba!\xcf\x02\x87\x9d6\xa11\x8a\xfe\x18\xc06\xc1\xb6 l\x9d`\xf9}\x07\x9e=\x83\xa1\xca\xbe\x8b\x8b\"\xbf\xbd\xfd\x9d\xd1\x80~5\x1c\x8cv\x10&FM\xaf\xce\xac\xb6I\xf5k\xd1\x9a\xeeS\xad)\xf8\x0dw6\xdd~bO\xfc\xad\xdf\xfe\xe5\x92\xfe?\xd8zz\xf9\xfb\xd0\xdd\x19>8G\xdbs\xc5\xe0\x8dR\xc5\xdb\xff\xf9/\xb6}:\xfe:\xf1\xb7f\xbc\xf0\xe1\xc3\xfd\xa4\xfc\xe98\xdb\xcaW,\xe7\xec\xeep_+\xb4n7\xc5R\xc4\xa5|\x88\x89\x1d\xf0\x14\xcc\x01\xe3\xd0w\xf6PO\x92{\x01\x1f\xf1\xf3\xdc\x1e\xe0\xb2\x88Dx.F\xabc|\xab\xaf\xcc\x946\x9f\x0c/\xeb\xb9\xaf\xe0\x140\x80\xea\x9b8\xb7\xf3\xd2D\xcf\x85\xe1>\xa5h\x1a\xaf\x86\xf4\xd5\x00\xe3\xb4\x16v\x8cD\x8f\x01\xcc+\n\xb8\xc9\x93\xe3g\xd6\xe5v\x1d8S\xe9\xcd\xbc\xfe\xaai\x02B/\xeb\x895\x06\xeb\x89\xbf\\\x1diB#[\xc7\xf86\xca\xb5/\x9f\xe1\xcb\xb9\xf6\xe5\x0f\xd6\x0f\xf4\xe5\xafE\x92\x1f5b\xd15\xa7\xed\xc6\x88S\x16\xb2\x11\xb6\xac-\xe0V\xba=\x84x\x93K\x06a\x86\x1eK\x9a\xc1\x85\xe1:\xfa\xe0\xd6dVR2Lq\x0c\xe6z#c\xb4`\x149H\xf8W\x06\xe6\xbeKum\x0coH/2\x89/y\xe4\x1bm\x19]\x0c\x91\xfa<95Z\xdb\xc5l\xc0=\xd2\xe9q\xa0[\x1368\x8e@.y\x04\xf3V \x11\xff\xb4q<\nSW~\xbe5\xcd\xa9\xeb\xdd\\\xf8xN\xd3\x9fE\xcc\"\x1d\xbek\xcfgWJ\x1e\x84b\xd4\xfa\xe5\x17\xcb\x81c\x18p\xcd\x16)\xe3,\x86.X\x7f\x1eZ\x8e\n\x99\x9f\xfc(\x9c\x9e\xc5y\x98\xdf\xbddf(>}\x81x3\x99\x92\x8fI\x88j\xea\xc2e\x9ajZ\x17\x96\x0eI/A\xb4\xd4\xb5'\x86\x9ee\xae\x9c\x18\x08\xbb\xc5\x06\xff\xd7\x1c\x03\x84w\xb6\xb1\x12I\xd80\"\x83\xa8v\xea\xc2\x8d\x0e\x19\xb51Ak\xc9\xd8\xa5\xa0\xd6U\xe0\xcbS)\xc1;\x8c\xf5\xf2\x98\xae\x1e\x19E\xeb\x0dn\x8f1K\xfb\xeai\xcbD\xeb{\x87Z\xd1\xfa\x81Z \x13\xad\x0fGj-\x8f\x93\xad\xbb\x92\xf4\xdc ^_t\x89\xd7o\xba\xc4\xeb\xcb.\xf1\xfa\xbcK\xbc~\x07'L\xb6\x8d\x923.\xe3f\n\x13!A7\x8a\xbc\xcd\xa2\xf5\xc5\xba\xf2\xf8+8\x81kI\xd8G\xbf\xb9\xae \xff~\xd7\xa5Q\xaaD\xechY)\x89\xd8\xd1+\xd3f\x82v\x14\x91\xdfA]\xd0~\x87\x82\xf6S\xb8\x831\xc4\x0eJ\xd4\xe9\xb1\x8c\xc2\xa5\x00\x8fp!&G\xc9\xb9Q\xa0X\x98\x04\x8aw\x8c\xc4\xb8c\xe2@!2\xfc\xec\xb8\x80\xb2\xc2\x0d\x9ee,\xe4\x02\xc3\x15\x06\x08\x10\x02y\xf1\xd6\xbe\xe2\"G\xa301\xf5\x02\xa6\x9eJ\xdc\xffi\xc1\xa2Y\xf5\xa5*\xb3\xb8\xeak\xa0\xaa\xc4\xf8\x06Uw\"\xdd\xa0\xdb\x96J\x00\x15\x9a}hP=\xdc\xf0\xa8\x01\xdc\xcc&\xc4\x1c\"\xda\x85W``KtM0R\xdf<\xf22*\x95\xed\x82\x85\x11\x15~\xec?\x9c\xa0\xe1\x0coH\n\xba\xec\xbb%\xf9\xe4\xa0U\xcd\x0f\x0e\x8fF\xf6\xactu?\xde.}\"\x9e\x19\x03\xfe\xaegP\xa7\xf1X\x8b\x99\xea3\xb7\x0b\xc7\x85\xd4N\xbd\x8f\xb0 \xa9\xf7\x1a~\x84\xa4=\x02\x83\xe0o,\x0b&\xe4\xd2\xa6c0\x02)gF\x03\n\x05}\x7f\x0f9w\x88\xa3_K\xd9\xe0\xeb\xc3u0 #\xc6O\xae\xb15\xddG\x15\x8e\xba\xeaU\xdc\xc3\xfa$_\x84\x95\xd1\xfa\x83,on\x9a\x19\xd0\xfab:\x0c\xa3\xb4\x1aq\xd5\xc0\x05r\xe3G\x8em\xb1\xc7U\xf5F# \xcd\xb1Y\xc9\xdc\x11\x93\xb1[\x1d\xaf\xf6\x9d\xa4\x905Q\xe3S\xdd\xe6\xfc\xfe\xa2\xc6^\x9e\xb37\"\x19E\xa3\x01\x91xb\xacMT\xb1\x08\xb3SV\x160\xf1\xf0j\xb9\xd0\x84\xe7C\x91\xd89\xf6\xb2\x15 \xceIDh/2\xcd#\xbc\xfb\xb7,i\x15\xf7\x89\xa3\xcc\xf4\xad. \x8e\xb8x\xa7}\xbb\xa0\x0cmi \\\xd7\x1e\xd25\xa8XH\xff\xfe\x80\xb1lb\x9d\xa5\x80|}H\xc3\xb1\xc6\xdeF\\\x0f\x18\xd5\xd3\xd4l\xeeB\xd8\xf7x\x85j0\xe2\xd4\xb8\xf5\xd3\xd8\xb6p\x95\xde\xa6\xfejE\xd21\x04I\x11M\xe3\x1fr\x98\x13\x16\x17\xd4r\xdc\xa6\x9fa\xb3 \xad\x17\x99@dt{\x0c\xfe\xa1\x86\xf4\xcd\x86[\"\xe3\xf2\xcdGiZ\x7f\x15\xaa\x9bO0\xae\xcd\x944\xcc\xf9\xae\xbe\xc9v\xbc\x81g!\x8d\x9fW\x0c\xdan\x17\x13f\xe6\xfe\x0f\x9d.\xeeU\x1d\x15:\xc1\xa7h\xe3\xcf\x08\x91J\xde\x8eqCE\x02l?\xe6\"\xf7\x0d\xc3\x88\x1f-R\x1c\x1d\xa8RBLy\xd1\xe4\xd1d*\xa0\xa4\x06\x18\xda\x96\"\xb2\x887M\x8e*\xa5\xfcb\xd2\xcaQ\xea\xa1\xa7\x0f\xcf$\x8f\xa6\x1f\xaco\xfa\xc4V\x16\xae\xbdL\x03[\x03\x03\xed\xba\"\x0d[s\xa9tx?\xd6\xfc\xb2\xdb\xcc\x7f\xae\x8b\xf9E\x92D2\xb3\xd9\xab}I\x90\xac\xda\xa7\x0b\xab\x1bu1\x84\xdcv[uZ\xf2+k\x80\xfa\x99-\x9f\xb23\xa6\xf1\xdc\x95\xa2\xe6\xd4\x0b\xab\xd1s4\x87\x13\xba\xb4\xa3\xeb1\xda\xe8P\xb4\x8a\xe4Qj\xc7\x8ekN\xdb_\x1e\x0d\xa2\xdaZ\x89\x1a\xe1\xfe\xd0h\xcf\x9a\x93\xdcb\x91j\xe8\x9cg\xe2\xae\xb9I\xad\xe7A@\xb2\x8c\x9e\x7f\x18\xab\xb9X\xd19#S\xd36\xb5\x90d\xe1u3\x86\x8c\x99\x87\x95\x0e)kn\xe4~Vb\x0dw\x84\xb5\xac\xc4\x1e\xd7\xa4\xbab\xbe\xa5\xc9N\xb7a\x83\xcb\x81\xce\x88,\xb6w\xf6v\xb5\x8a\x91}Uz[\xf0\xe2\xaa\xe7\x02J\x9f\xecCu\xafD\xac\xd1]u\xe4L\xf1\xaf\x96\x9ei\\\xadV\x18\xb0\xb3\x0eS\xb4L\x9b\x93\xfcc\x92Dd\xaa\xe6\x87Xh\xe4\x1a7%2)\x1f\x97'\xeb\xb2\xc1\x1d\x9cy\x98\xde\xea\x13 \x928\x08#r\x91\xfaq\xe6\xb3\xd2O\x9e\xc0\x0d0'\xff\xe1h\xc72YOP\xeem\xa2l\xdb8\xccY6\xcfq;\xe3\xc5<]\xc34\xbf+i\xdb\x8ce\x18\xc3\xbc\x18\xecX\xae}\xa5\x88\xa54\x82\xabu\x1a\xd98\xa9\x9a\x81S\xb0g(\xb5\x0d\x08%\x19\xcd\x9f9.\xdc\xdaH\xfe\x95\xdf\x9e\x18\xc3\xb0?\xa8t\xe6z\xc0 \xfc(\xba\xf6\x83/\xff\xbb \x05\xf1R\x92\x91\\\x11{<\x16\"\xf5\x9a\xe3$\x0fgw\xcf\xa3H\xad\xbd\x1a\xc8\xa5nI\xdd5\xe3\xff1\x1f\xe7j\x98\xd2\x9a\xb2\x9d6\xb8\xf2\x95\xebj\xfa\xd7\xd8\x07\xa2\x19\xcd\xba=i[\xd5R%\x1b\x83v\xdb\xa8\xeb6\xe35\xe2]-\x93\"\xce1\x15\x06lA.\xdf\xb7V{\xd5F\xdej\xe1\xa2\x88G\xeb\xab\x96\xc5\xfe\x18\x8ev-\xc4\x9c\xe2\xb9C\x7ffI\x9a\xdb\xd7\x8e\x0b\xab\xcd\xcdz%Ud\xba*\xaca\xce\xa3\x1a6\xd7\x0b\x17tR\x04:\x9b\xc4\x06\x0fQ\x1f\xe7\xe8jE\xe2i\x18\xcf_\xf2\xd9\xcb\x9a\x0c\x1c\xba\x156\x0b\x96\xb3_xQ2\xbfHVo\xc9\x0d\x89>a\x88'c\xa0\xa3\x1b\x1e\xbd\xd6\x90\x9e(\xf4\xae\x82\"MI\x9cs\xc6\x0c\xf3\x89c\x9e\x03?\xc8E\x1b?3\x16\x0b\x8f\xe4\x88\x8d\xa2\x11g\xcba\n\x03\x8be\x03,VS?',\xb8WD\x97\xd4{\x7fI\xe8\xaa\x14\x0c\\\x1e.\x89\x9dt\x19\xab\x00\x87F\xe6\xadH:K\xd2\xe5g\xac\xf7\xcd\xec=\xa1\x84\x85\x9f\xde\xd9\xa1\x8bF\x0d\xcd\x85\xcct\xa7 *n\xa5F\xcf\xe2)\x8b\x0c\xae\xe7>{D\xbe#\nf \xf1\xaf\xf4\xaf\xedO\x82K\x97\xef\xc2\xe2:\n\x03\x11\xb8\xc6V}>\xfe\xd4\xfc\x95\xd8\xb2\xdf\x19D*R\x9c\x93\\\x1a\x1b\x9f\x90\xac\x03\x8d\xf1\xad8oC\x87\xc2-4I\xfb\xe0\xc4v\xb4\x14z)\x89\x88\x9f\x11\xbb\x89\xa0\x1c\x03\xd6b_\xb6!\xa4Z\x9d\xba\x99\xee@v]\xa1\x86\xf8\xd2\xea&\xb6\xa1\x02i$\x16$\xcf\xd1\x89>M\xc6N\x88\xc2-E\\\xd0\x93\xe2\xd5R\xa1k\xd6\xf3\xa7S\x8a\x9c\xc3x~\x91\xd8w\x8a8\xef\xb6M\xcc\xc9\xa3\x0b\x95h\xf1\xfe\x1e\x16\xc6(Y\xb3\x0e\xb7:\xa1\x88\xbb\x93\x8f\x1c=\x86!b\xf0\xf6\x95HKO\xd7\xc2]9\xad\xba\xd4v\xdaN\x19{\xc3\xa8<}\xf3\xe2\xe4\xd0\x04\xb5\x03-\xfd\x08\xb9|\xd4\xd7\xd6tWG\x8d\x82\xa4\xb3\x06/`\\\xed,2V}\x81^Sn\x8cL\x19\xee\xcb\x9a\xeb\xb4\xcc\x17\xd3\xb2`\x97t,7^\xbd\xaaf\x05m\xfb\x84\xe3\xb9\xcf\x1c\xb5\x97\xe75\xd1\xdbP\xf2\x16\xc3\xec\x05m3\x8c\xe7\xbcQFFb\xa0\x81\x9c\x0b\xe8PZ\xe0]\xb1C\x03\x8b\xbfGm\x08\x17Ji^\x9c`N\xbc!\xd2\x98\xdaQ\xb5\x8ed\x16\x15\xd9\xe2\x85\x02\xd5[\x85\x19\x8a)G\xceT\xca\xcd\xe5\x88/\xf5\xf3g\x16\xb1\x88\x8b\x94L\xc3\xbe\xe5\xb4\xe2>\xbd\xb6\xb0I^\xb0\xfe\x08@\x9f\xe7\xa9\x9f\x93\xf9\xddz}9\xa0}\xd1gOQ\x00\\\x92T\x87\xf8\xc95\xdd:\xbe\xf2Es\xda\xc5GO\xe9G7\xfa\x91\xb5M\x9a\x9f\xf9\xab\x1e\xa9T\x03[\xb3\xe6\\N\x97\xf0[\x8f\xd5\xf5\xd2\x8f\x7f\xc8\xc5\xb2\x06?\xc6&@\x1cP\x10\xc6\xe0c\xe8E\xf25\x87\xdb\x05II\xc1\x87\xe2c\x08\x85\x1c\xaeI\x18\xcf\xc5\xf6\xf4\xe8\xb8\xa6%5\x80\xfds\x19n2\xb2>z\x81\xd6\x19>]C\xce\xb0\x11\xdb{C\xc7l\xb4\xc3q\xc0\x01\x9d!\xbd*\xe9\xf7\x07\x17,\xbf\xa1B\x02FytP\x06r\x13]s\xeaxU\x9c\x8c\x87G\xa84\xc5\xd3.O9\xcc~@\xc1\xf2T\x17\x1f\x07_\x8d\x86\xea\xab\xd0\x14h\xa2\xd4b\xa0\xcd_\x861!\xe4\xf7\xa5\xf6\xa4\xd3[^\xc8tUSWz=@\xd7\x8e\x95\xf5\x0b\xdd\x1d%U|\xaf$\xe5Q\xcf\xe4\xd7,\xe2i\xa9\xa0\xa9\xcc*O\xab1\x8e\x0d]]\xcf\x83\xe8\xbb*D\xc4/\xd9;\xb1\x1b\x18\xd2\xac\x9d@hW\xfa\xae\xd6)\xe3\xfd\x97\xc3JR\xe8H\x86\x00c\xd4\x03U\xddk\x9d\xc3\x7f\xc4\xfc\xad\xd1\xf7\xc7oG\xb3\xd4\x93\xb3\x97J\xc4O}S&\xfc\xd6 \xd0\x9a^Bgx\xfe=\xc6( T\x0d\x86\xe6\xaa\x84\x94\x0bTu\xf2T;\xb6\x9f:.L\xaci\x98\xad\xe8\x01\xf2\x12=\xa9-\x17\xac\xab\xdcOylVz\x1b\xfbyx\xc3\xfc+1\x96c\xf6\x8a\xcd\xf7\xc7\x94\xd0gd\xca\x9eRT\xee\xcf\xd1\x08\xee\xa5\xa94B\x1f\xca\xdd%j\xd8p\xdf\x18K\xdb\x10\x1d\xad4\xfb\xd3ft\x03\\\xd4\xa7\xd8i\x96\x01\x8e{\xe3Y\x0c\x00\xec`\xf0y \x8f=D\xc5\xecX\xfa&\x9e\xf8\x9a\xdc!\x0d\xe8\x08Y\x1d\xe6B\xf5\xd4Y\x87S\xdd\xc31l\xb08\x8e1\xb7\xde\xfb\xa9i\xbc(i\x84\xbd&\"\x80\x13\xa0\xdcU\xd8\xb0\x9aR\xf6\x1bZY\x89\xc8\x9d\x1a\xc4\x81<\xb1\xbe\xfc\x9f\x9acN\xedL\x96\\\xd5\xa7l\xc5\xfa\xf6J\x9c\xea=$L\xcdAmh&\\H \xd4\xd5\xda,\xc9t\xd5\xc4\xabw\x05}\xa1\xea\x8fl\x87\xd9\xf8a\x88\xcc:7#M\x08\xafM~r\x02h\xadf\x9e\x95\xc6\x8c\xb4r\xa7Y\x9e\xac\xa4I\xe9\x00\xda\xfa\x80P\xeaGH(\xcfZ@\xc1\xb0\xea\x0bD\xbd\xbc\xc2\xda\xa3\x13\xa6\x80\xee\xbd\xb8:\xc1\xb1\"i\x86\x99\xc4\xbb\xd7N\x98}d\x85\x19\xdaj\xb4\xd3\xd6\x8c\xfc\xadv\xbf\xd4J\xf7\x96\x9a\xd6\xa6\xa7\x07\xae\x84z\x0c\x0d\x96\xd1\x0c\xf1\x0f\xd3\x84k\xa3\xd3\xeb\x94\x15\x95\xd0\x9aebB\x146\x89//\xb5\x12\xd1j_;.dU\xe7\x98kc\xe6\xf9\xc5|I\xe2\xfce\xe4g\xbd\x1dNd\xb8\xa8\xbe'5\x1f.\x84\x8d!b\xda\x0d\x8fn\x10\x93[\xf5\x18J\x99\xec\xbf\xfc\xd0\xa9\xdda\"\x16\xf9A\x9d\x98\x06\x8c\xa6.\x8f3E&\x18\xfbR>f<\x9e\x8b\x98\xa4\x19\x908H\xa6a<\xafgD\xc8\x17$\xc6\x8d\x87\xc9\xd2\xca\xc3\x0fD\xe0\x17\x1fx\x03\x06e\xb88c\xb9\xc1@/\xd57\xffF\x18\x19\x18\xcc\x04\xf4S\x13\xb5\x88\x85\xc0\x0cCC\x8c\x9b\x1f\x84}n}\xdc<\x9b\xa6\x0f\xac\xa2\x16gp\xbd\x03\x1d\xae\xdb\x17\x0c\xdb=y\x82LO\xb9\x1e\xe4w\xcdC\xbe\x85P\xc3\xd0>\xde\xf5]N\xde\xf2l\xdd1FWA\xcf\xf3\xea1\x1cWv\xcb\xeaV\xfd!\x99\xcd2\x92\xff@\x97@R\xe4\x90\xcc\xe0:)\xe2if\x9a]\xb5MZ9l\x82\x8d\xb6\xfd\x03\xc7\xd8\x0e\xdbs\xfd\xdb\xc9\xeb\x99\xd1\x99!juO!\xd5@\nuE\x80\xae\x08n\xe0\xb1\xee1\x05\xb3\xbe'\xad\x88)oCD\xb4\x00\xcf|\xd8\xbaU4J\xe2\xda\xec\x8f\xf5\xde,\xdd\x04\xa1\xb84\x9f#@\xcb\xe8\x0e\xf7\xf7\xcc\xed\xde*\xf2\xd9a\xdb\xd4od^\x98\x9dq\xbca\xc7\x8ei\x13 \xd4bIh\x83\x1d\n\xac+%\xee\xd1\xed$\x90\xce\xd3\x01\xdc\xc3\x82M\x9c\xde\xe2\x10\xf8\xe1\x8a\xd3\x81\xc7V\xea8\xdem\x1a\xe63/HX\xa7\xdcL\x8d\xe1\x98\x11\x91\x84rZ$\xb9)\x1bUJi\x08\xfag\xf3\x04\x86t`\x18\xbax\xb4\xb7\x07O \x9f\xa4\x1a=\xd7Z#\xd4$^\x85r\xdd<;\xa1\xbc\x95\x89jy^e\x96\xf1#\x0c\xbfB\xf8\xce\x82\xc8O\xe7\x842\xa8~\x0cK\xffk\xb8,\x96\x90\xa1;\xc7\xe0+\xe5\xb3}9\xcd\xf5p\xdfAWNJ6i)\x9e\x12a\xdf\xf7\x1c\xd4\xa2u%J'\x8b\x9c;JH\xcb\xf5\xdb\xb4\x0f\x92\xd6\xdasHe\xbc0\xfb)$,\xd0H\xf31\x9d\x88\xfb{ \x06\x14/\xf7\xb4\"0\x9b\xbd\xd5\xb8\xd6W\x8c\x9e\xa5\x13r\x80\xb4\x9c\xdb\xa1\xc0\xa9\xcd\xb2'\x9a\xedU[\xbe\x1b\xc3\xa3#\xa7\x14\x0d\x1bOB\x14\x88Z~\x16\x84\xa1\xa5\x17\x8b\xb2\x12\x91\x9f\x87\xf1\xb0\xb5\xc8u\x18\xfb\xe9\x9d\xa1\x08H\x12(\xfdq\xc2*A2\xaf\xad\x95\"\x9fm\xb5\x96`\x84vg/^\xdb\xc41\x02\x1c\xaa\xe6\x82l\xd4\xde\x9f \xdb\xea(\x91\xcf\x86\xfb\x11\xe9*\xb3\xd5R\x08\xaa~\x8f\xe0\xc7v\x08.\xc8\xd7\xeeZbx\xf6\xec\x19\x18\xac\xb6\xf9t\xfa\x19\xd9\xdf\xed\xae\xea\xb7.@\n\xa32cE\xa8\xedpzO\x0cp&\xcc\xc6\x1d\x95;\xf5\xe8f.\xcf\x8f\xd6\xf8T\x95\xbe\xeb\xd1\xd7M\x1b\xc7\"\xf6\x16\xd1F\xc6\xe7riz\xfc\xb9\xe2\x10L{5\xba\x94\x98*\x83\xc6\xa1B\x01\xa4\xa4\x189\xc0\xb64\xd3h\x10\xb7\xc4\x94;L\x99\xf0\x1cOn\xe49\xe1\x99,\x91;\xc575\x11\x1d=\xdd\xb7\xca'\x87 b\xa1I\xcf\x1cV\xe1f\xecB\x98\xbd\xf7\xdf\xdb\xb1S\x16K\xf8\xe1\\\xca\xb7\xb6`\xe8\x08\x91\x80(T\xbe\xdcDZ?\xa6\x07 \xe9p\x84@\xcb\x95V8\x00\x8f\xfe$7\xdd\\\x19@\xa2\x8c`m1\xa3\xd7\xcc\xcdm\xf4k\xafk\xf9A\x8bH\x8c\xd9\xdd#\xcf>K\x93%\xe5\x15S\x07\x15\xc35\xae\xac\xc6J\xe5\x15\xfb\xb45\x841\xcc\x95\x15eX!Z\xe1\x13\xaf8\x87'H\xeb\xb8\x069\x83\xe9\xd0\xad\xc4\x17\x92\xf6\x97\xc7\xd9\xc5\x08\xa4\xa7\xadE*\xf5\x04\xe7Z\xb5\x85#?\xcb\xdf\x18>\xc0\xb1O\xf2\xcb\xb6\xd1ky\x97\x1b?* {\xc1\xae0\x08Q\xce\x843Z\xfd\xe8q\x15\xfe\x06d\x12\xb2\xf0l\x86\xd8o\x85\xb4p\xf5%2\x89\n\xd6O\xb1\x14\\\x95\x89\x14\xd8\x89\xc6\xf8\xef\xb4\x8a\xc6\x99*h\x14\xe9!~\xb8q\xa1\x15>\xe0gY\xfd\xd1\x96\xf4\xcc(/@\xb2\xb6\xa2\xd8GL\x18X\xddw\xee+\x9fEO-`\x9bEQ\xe5\x7fc\xfc\xab\xd9o\x8dG\x8a`\xd6\xd4Q\xde\x8dai\x92FX\x00{\xe2\xa5\xc4\x9f~~\x13\xe7\xc3\xfd\x17gv\x0e?\xea\xdc\x18\xf5\xfb\xdc\xa8E\x16\xce\x8e\xa6A#M\x87j\x98#\x08\xe1\x18\x8a#\x0877\xf5L\x19\xf0\xc6px\xa1\x83\xfdG\xad4OQ\x1cp<\x1c\xc2\x16\x04\xadr\x1dQS\xf9!]9\xb4\x9b\xa1\xe3\xb2\xcfa\x93\x03(+\xe7-\xa0\x001V\xc9\x91\xec\x16K\"\xc1j\x0ca\xeb\x84\xf7\xc6\xe5P0 g3lb\xd8\x84\x0c\x9eAQ\x9e$\x05lA\xe60\x7f`\x84\xda3d\xe6\xc2\xad\xad\xb6!\x97\xc4\xf3\x8c\x07\x0b\\1\x1ep\x05\xc7\x90\x1d\xc1\xaa\x0d\xe8P\x03[{>\x1cCz\x04\x9b\x9b~\x1b\xfa\xa0\xc7\x84\x9c\xf7\xa2\xb8\xce\xf2\xd4\xa6|\x82\xef\x02O\x8d\xa1_X8H\xa4\xd6\x8a\x8a\xa0\xf0\xf5e\xc9\x84\xee4f\xba\xdb\x03\xe9\x89\xcaz-\x9a\xeb\x8eE\xc3+{a\xbf\xa6\x1bJ^\x16\x0e\xaa\xe4\x9a&@\xa6\x96\xae\xfa\xb6d6\x18(\xeb\x94smM.]Y\x14V\xb2\xf2L\"\x963\x87K&8\"r\x02\x94\xb8C\xa2\xafK\xa8\x98\xaf;\xe8\xdb~\x83\xae\xc1\xa6W\xc5g\xfd*~a\xff\xb6~\xa7\xbf\xf6\xad\xbb\x97V\xa3\x92W\x96\xde\xb6|\xd6\xa4\xadF\xa4\xa0\x15\x1b\xb6\x9d\xd3\xd3i\x84i!\x1c\xbe \x19+!\xcd\x9f\xcf\xf9M\xcaO\xc3!\x8f\xdaL\xd1\xc6\xde\xbe\x0b!\x9b\xf6\xc4)\x7f\x9a4yF\x94\xfc\xf0\xad\x0b\xfe\xbc\x8d\x9f\xad\xb3\x10t\xd8q\x8d\xc5\x84SH\x91\x07yq\x97\x13\x91\xf1\x9dbU\xf5!WQ\xe5u\x9b\xae\xb6~\xbdl\xeb\x17\x05\xf3;?_x\xcb0.i\xc6\x1e\"[:\x9f\xe8\x1aq\x04 \x8an\xdb\xd0&\xa5\xbd]\xb4\xafu1F\x07\x99$-\xc9\xe5\x03\x11,\xc1X\x82\x9e\xe0\x11e\xa5w\x9e\xc2)\xec\xc2\x98\xdd\x8dv\xe0\x14v\xf8\xdd\xf0\xe9\x10Na\x04c\x93\xe8\x05iE\xd8\x84\x19\x1c\xa3\xb0O\xc8\xeffm4D\x9f\x04\xb8\x11\x1c\xc3ptX\x12rQ\x8b^ \x04\x9da.\xd2'-.m\x8er\x19\xc3\xa7#x\xc2\x88X2\xa1\x83\x1b^:L8@\xd9\x17{g\x08O r\xe0\xf8\x18\xf6\xe1\x1e\xf6w\xe0 %^\x9f\x89\x0cb\xd8\xdd\xec;t\xd7`\xf6).\xb9\x7f<3>\xde\x8d.]e(!\xf6\xbe\xfe\xcc\x97F4\xdc+G4\x1c\xc1=\xd8bL\xf2\x10}:\xc4\xd1`\xf7\x80\x7fw\xcc\x13\x96\xdd\xdf#9+%x\xfb^\xe3\xdf}\xfc\xf8\x8b\xf2ng\x0dh\xd4\x9f\x15\x06\x08\x1d*\x10\x92@\xe6\xd7AV8\"\xef\x1b\xad\x89\x82\x8c\xa5\x92\x1bI`\xd2\x0eQO\x12\x97\xc6X\x94/\xc2\xcfi\xdd;.\xee\xe4!\xc5s\x81\xdc\x9e\x1d\x94i\xe4\\H\x19>\x0f\x98\x18u\x00O\x00\xf3\xc5\xdd\xb3I\xe4\xdc\x0c\xcb%w\x0f<\x95\x1cer\xc4w\x18\x1bg\xf3\x04fM\x8co\xc2\xd2\xdd\x14\xc9M\x19\xa7\xa9M|\x8a\x8aq\x8a^\xbe\x94$\x9f&\x1d\x1d\xb71>\xe7b\x10\x9d\xde\x02$\xdd\x85\xa5\xc9V&\xaeT\xaf\x0c\x04(\xc3\xa2\xa4\xa8=\xa4\xc7\xeb\xe6I\x9f\xce\xf0\xe3&u\x99j\xeeK\x07\x11\x157\x81l7\x8eO\xf9.\xf7\xb8b\xe9\x84\x1e\x0e\xb9w\x1e%\xb7\xe5\x93\xf6y\xd8$U\x84N\x82\x12V\x0dC\xc0\xba\x95y\xa8\xba\xb37\x1b\x1e8\x90{o\xde\x9f\x7f<{yq\xf5\xee\xf9\xffw\xf5\xe2o\x17g\xe7t=\x0dL\xb2\xb8\x139\x89\x0e1\x98\x05\xe9\x9fwy\xf6\x18\x83\xdf\x0b\xdf\x1a\xc5di\xd8a\xa2R\xb3J2\x9fie)\xbd\x00\xb0\xe5\x18N\x92\x1e\x01\x13\xc4\xc5{\xb5\xdb\x94\x1f\x89K\x8f;\x1e\\\xd8\x1dqZi\x96$\xb6c\x14\x87\x12\xca\x901K\xd3'O\x84'x\xf9\xcc\x1eb\xc2\xbcJ\xa9\xd8\\\xaa\x9d\xd9\x0d\xf8\x1864\xb2\x93\xfa\xbab\xf1u\xbe\xbc\xf3\xbf\x96\x91\xa3|\x1b\x05\xcb\xab$\x89\xce\xc3\xdf\xe8t\x1e\x0e\x9fb\xf2\xa1+\xeea\xd3\xb9\xe2\xb5\x13[sJT=\xbf\xb8`\xbb\x87\x1f\x8cT\x7fd\xf3\xf0EZ\x0b\xcc\x16!\xb5\xec Y\xeb\xa3v]\xd1\x91k\xcb\xb8\x06\xfb\xc9st\xf5\xa7\x0d\xb1_\x18\x1cJ+!\x13\xdetY\xa9Xa_hmM\x98\xe1K\xdd\xd5\xad\xcd\xccAV\xec16\x08\x02ZGc\xdf\xd43\xd0\xc9\xb5\xd5\\j\xb5\xd0B\x0c\x933\x0c\xd2\"\xd5\xa5\xbc\x07\x99\xc4\x97FvK\xc8\xa5j\xc7\x83\xad\xcb\xb3\x0f\xdcV\xdc\x84\xee\xcc\xbd0\x13\xe7>7F1\xb3\x812\n\xf7\xff\xa0\xf9\xa3\x97\xcf\x8c\xb9Q\x13\xce\x19_\xe1 \xdf\xb1\x16\xa1Z\xb7is\x91J\xce\x1e'\xb0p\xa1F\xe9I\xc7\xe7\xc6\xa0\xfe.\xbb\xf5W\xc3\xfd\xb6x\x9d\xa0\x06\x0fh\xd3\x13\x11\xad\x9eH6\xd7\xe4=\xc9(\x89]\x99\x0e/\x8b(\x0fW\x11\xa1\x10\x1c\xeeo]\x87\xb9\xf6X\xac)\x1a\x06Gh\xbeK\x8e\xd8\xf2\x1b9p#\xe2\x9f\xba\x98\xb4R\xc7\x7f e\x82\x1cB\x04\x04\x10\xeb`\xd9\x19}W\xb0\xec~#XvF\x8f\x02\xcbn\x03,;\x8e[=\xa2`b\x7ftZ\xb85\xa0\xb5\xbf\xfb]\xa1u\xf8\x8d\xd0\xda\xdf}\x14\xb4\x0e\x1b\xd0:\xd0Ck_y\x9d\xe8\xda\xf9\x83F0\xcc\xe6LX}a\xfc\x16x&\x8f\xa7\xf2(\xb1\xfa\xd5\x8b~S\xb1Z\x890\x90\x90\x1f\xa2\x19\x1e.\xba>M\xa0\xd9(\x96>>\xa1\xbd\xe5w\x9d\x1f\xe3\xeac \xa4\x89\xe4\xcc%\x19(\x1b\xa5\x1b\xd0\x83\xee\x14\x17\xef\xc5\xc7j1\x9b\x9c\xac\xa0\x0f\xb5\n\xbd(Vq\xf1\xc6_\xae\xd3x\x1b\x9d+.^\xef\xf3u\xeam\xa5\x8e\xa1\x1f\x85,.\xde\xfe\x87u\xda\xef\xb4\x1d\x86\xaa\xe2\xf3u*n\xa1\xc6\xa1\x17E\x0e=\xa9rX\x872\x87j4\x17\xfdF\xd3I\xac\x03\x94v\xd1Z\xc6\xfa3\x8b\x0eUz+\x8e\xb51\x14\xd4\x8b0w\xc4M\xb0\xac\xbef\xd3\xa0\xa5\xc9\x1eD\x0c\x12\x1c\xac)\x0cI\x1d\xa9\x93_\x0b?j\x8f\x1f\x01ZiC\x87lA:\x0c\x85\x8df\xeb\xc1\xc3\xcf\x80\xfb{\x8e,KY\x88\xde/\\\x19E\x18g+L+\xd6\xefd2)F\x98\xffRC\xca\xdf\xdaqq>=\xe3f\xd3%]Q\xba\xf3 \x8e\xe4\xfe\x92\xde\xd2\xcf\x83\x85\xbd\xed\xfd>z\xd8\x9e;\xde\xdf\x930\xb6-\xb0Dx\xb0\xb22\x9e\xec\x89\xa5P\xf7<\x0f,\xc7q\xc1:\xe6\xf4\x06\xae+]6\xf4:\\\x0c\xf2\xa4N\xa3\xf6\xef?\xd5*\x8fW;YU\xcfmf{\x8e\xda\x11\x0e\x90\xb1Z.-\xed\xb6\x94\x17\xcc\xd6,i\x9c\xa8\xb9\xf0u\xa7'pY\xef\xfd=\np\x06,\xd5\x9cr4\xeb)>\xee\x8f\x9e\xd2G\x80\xf6\xd1\xa6\xf1\xa6\xf0\x8c\xf7'\xa7\xbfZ\xdd\x84\xaa\xf2\x9d.\x04Je\xe6RH\x07\xb8\x10\x97\xbf\xd2\xf2WR\xfe\xaa6_/\xf1^\x88\xae\x03[t\xf5`\x0e,\xd8\xa2\xcb\xa9\x90%z\xa1\x0b\xbe\xc3\xcc7\x10\x9c\xa5^0\xe1*\xd8\x9ae\n\xd3\xec\x0e\x8e`\xc6\x0ci77gf `4\x991 `0\x99\xb5J\x00i7ia\xd6KZ\xda\x8c\x83\x1f!\x01\x0c\xe1\x18\x8d\x90Q\x02\xe8\xc31\x84f \xa0\x8c\xa5\x82\xa8\x98\x92>\xb1\xc6\xa4\xb6\xb8q.\x82\x92\x9b\xe3\xdbf z\xd3\xba\x7f\xad\xc6\x96\xf5\x90\x1a\x98:\xaf\xad\x11\xc9\xe4\xff[\x1b\x1a\xb66\x84\x1e\xfaz\x0cf=\xbdp\xdf\xd4E\x10\x86\x1cm}\xa5\x10?X\xac\x0f\xda0@\\X\"\xe2\x87\x984\xd99\xba\xa8\xf1\xe5\x1f\x1a\x03\x03\xa9\x91\xfe\xd4\xd8t\xa6\xeacz&IB\x07s\x1c\xcc)\xf9\n\xb2x\xa1'D\xff\xde\xc1\x0c\xe5\xa5O\x7f\xce\xed\xa9\xf7p\xc2\xf5z\xc9\xda\xeeU\xadud\xaf\x17\x17Fu\xc3\x1d\xee\x8e\x96\\\x02\xea!\x9e`P\x9e\xe3c8\x84\x1f)\xfd{\n \x8ca\x08[\x908\x0e\xdahk^\xf4\x1a\xf0\xfb\xb5\x06\xbc;z\xba\xfbt\xff`\xf4\xf4;\x8dz\xd7<\xea\xbc9\xac\x1d\x1c\x16\x03F\xaf\xc1}\xea\xbd?\xbeea\x99\x96j\x0b>y\xf4\xfa|U\x1bQ[J\xc6\x90\xeeB\x04\xc0\xc0e\xa0v!\xe1<\xae\\\xc7h\x87\xbd\xa3\x10\xd8\xed\xd5\x87\xb7\x8f\xee\xc3\xa1\xa1\x0f{#\xf6\x8e\xf6\xe1P\xe9\x83|\x97\xa9t]\x1f\xfb\x1d\xe1\x15\xd7OI}\x02\xff\xfd\xdf\xc4U\x83`\xe6p\x8a\xa9Z\xfe\xfb\xbfs\x97\x9d\x14,\x0c\xe5&=\xb5\xcb\x1dBD\xc4\x11B\x0f\xf6\xf2Q\xeaT!\xc9\xec\\\xf9&\x17\xdf\xe4\xe57\xb9\xf4\x0d)\x9f\x10\xc7`\x03\xecT:\xcf\xd2\xea\x1aaa\x0c\x90\xb9\x96\xfc\xa4\xa4\xc0`K\x8d\xcb/\xae\xb8\x0c\xf3\x9b\x08q\x86\x81\xbb\xa81\xe7\x9cNH8\x19\x13S\"\x80\x0d\x04)\x00\xd2\x95\n\x07\xaa\x85V\xf7\x80P\xd8\x0f\x11\xd5\xe0\xedYO\xb9\x1a\xe1\x92\x19!\xb8A\xaaM\x90\x13\xb2|\xa3\x05\xf7\x89\xe56!\xdcgoX\x12G\x9b\x9bt\xd89\x17\xae\xffxB\xe9\x1e\xe7\x88\x13\xb5\xec\x1b\xd8\x84\xf0\x12~\xd4\xb9v\xebIY\xfd\x88_\xfccF\x0c\x9b\xb0\xb5\x95\x8bq\x1f\xe1\xd2\x1et\x0c\x97~\xf0\xed\x03>\xec\x83\x10\x84\xc6\xa9\x1c\xe3\xd0U\x15\x1cl\xe2\xfa\xb48\xdco.\xab^\x8d\x8e\x0c\x8drK\x0f\x04\xca\xf0\x12\xcf\xfc~\xfdhN\xf6\xb7\xf5\x03\xa9\x8dZg\xfa\xf4cg\xf4Hx\xec\xaa\xfd\xb0\xcd\x00\x91\x1f\x8d\xf0\x11\x8b\xf37\xdc?88\x18\x0d)\x17Q\xbe\xdf\xe9\xd9\xedG\x82\xaf\xd1\xedF\x1f(gc+#\x18\xee7\x87P\x1b\xd5\xcee\xab\x08\x9fv\xfb\xff:\x8c\x06\xcfN\xf8\xe7\xc3\xd1\xa1\xc3E\xe1[\x9cv\\%\xb76\xa5\x12(X\x1d\xc7\xedF\x07\xff\x10\xf4W\x03\x8c\x84\xdb\xd2\xcb#$/\x9bX0T\xb0`\xda\x0e\xa4P\x03\xa4\xd0\x08\xa4\xb0\x07\x90\xbe\x13\xcaD\xdf\xebr\xc5\xa3:\xefG\xc0\x88\x10[\xd2>@\xaf\xd3\x9e\xd8u\x0d\xe4j\xc4fM8\xde\x88\xd8\xaaF\xe4b\x84\xfd\xce\xe8`\x9f\x0e2\x86S\xc6\x08\x0d\x86\x07\xfb\x03\xb8\x87\x18\xc6\xdd\x14\xc8\x1a8\xfa\xd1\xc3a\x83\xb8\xaf\xa1\xf0?n8\xdf\x0f\xd5\xaf\x87\xe9\xebx\x92>\x1b\xed\xf6\xean?\xe8\xf7\xef.\xb6\xdc\xect\x0f\xe4\xde\xd5\xdd\xd7Q\xe2k\xb0\xfb\xe3\xba\x9b`\x95\x95\xa2ac \xb8\xbe^\xdd\xf8^Pktc\xd8\xb7\x1b\xaf\x92\xe2:\"\x8f\x04\xc7ag?\x06\x82\x01\xed\xd7\x8fG\xc2\xa3\xbb\x1f\xc3>\xfd@\xe6\xd9\xc8\xcd\x18\x848\xc8\x86n\x92\xda\x01\xc7\xacXPm\xfbF5 P\x0f\x93\xd8\x81-\x8a\xf2M\x8e(\x899\xc6_\xd8\xe2\xf4\x81\x1b\"\xafBN\x13AI\xc4\x8dc\x92\x15eD\xc4 \x10\xd8\x86\x84\xc9\x81\x8c\xe8\x8d\x16n\xc5b%$\xb5d\xc2?\x10\x921\x161BSc\xa4$AS\x88\xcfJ\x88nm%\x18 \x8e\x93\n\x1a\x90&\x02\xa4\xe1w\x03i\x83\xa8h\xb7`\xd1\x00U\x85%E\x16{{.\xeaQ\x8c\xf9~pv\x10\xe4\xb3(IP\xd2\xcd\xb1\xb5\xbc\xca\xb8\xc9\x7f\xaf\x81\xe8(\x90o\x1e\xcb\xc8e\x92\xe3\xb6\xd1\x9cj\xb6\x87[\xcd\xd9\x90\xcd\x19\x8aH)M\xf5\xf7Z\x03,G*=|z\x0e\xb27\xa5\xfc\x07\x0e\x92\x8fF\x1d$\x1f\xbbf\x90\xc3\xb5\x06\xa9\xa3V\xbey\x90\xbb\xae$\x12\xef5RF\xb3\x88\xd1\x8ev\xa5\xe1\x8e\xaa\xe7\xc3}\xc3\\k\x963\x85\xcc{\xfd\xf4\xb7\x92E\x12d\xfe\x80\xe9_\x1f2\x06\xa8\x0c\x0dP\x19\xe9\xd7\xccN;d\x86\xbd!\xb3\xe6\x11+\xa4\xc72X6\x8c\x06G\x02\xd57\x8e\x07\x0c\x1d\xad\x97\x9d6\xce\x96\x84\x1d%[\x1a7o\xbd=\x18\x9e\xc5\xfa\x83\xa5#J\xef#Op_:n\x88\x10y3\x89z\xc1~\nsLv\xb6\xd3\x01]\xe2\x97\x05\x86(r\x95s\xdf\xa6\xa7\x94\x0f\xcf\x9e\xc1\x80\x9e\xa3\xc5w9\xaf\xd6\xa4\x00\xfeO\x99\xe8\x16*\xe2\x9b&[\xcc\x85D`\x84\x15\x81\xb1\xf6\x8co\xfecf\xfc\x0f!P\x86\xa3\x03\x17\xb6\x86\xa3\xc3\xb5i\x14R\xd3!Q\xd02\x9f\x84\xe1\xb7\xd0/\x7f \xf9\xb23:\xd8\xa7cE\x19B?\xd4\xfe\x07\xd20\x7f \xf3\x88\x81\xfe\x81t\xcc\x1fH\xc6T\xf9\x10\\%\xedA\x8f!\xb7\xcfm\x0f\x12\xa7F\x12}\x13A\xf3\x07\xd23f\x10\xd5\xb7o\xcdHB\xec\xe2\x1eP\xfc'\"~\x0c\xf2\xa7v(\xbeR\xe6\xac\xcb\xab\xa2ji\xdd\xf9RZ\x1a\xf6j\xc9$Ejo\xea\xedc\x06e\x12\x14\xad\xd5T\xe7\xa8\x82du\xb7\x1e\xddR\xa5\x9b\x1c\xa0Cd\xe9\"X\xd9\xd5\xe7\x8a\xa7\x97\x94\xa5\xa42E\x90\x0b\xd0\x0f\xf3\xb2F\xae\xe2HK\x12\x10\x9d\x17\x98\xf7eWz\xa7\xb0\x11 \xa5\xea\xa0\xdc\xad\x8e*\xf26\xc3\x9b\xdcO\xe7$?\xcf\xfd4\xef\xce\x86Z\x9a\xf1\x003\xd6T\xba\xa1o!K\x8a4 k\xb4\x90\xb6\xf5\x97\xd5v\x16O\xbb\xebJ\xeb\xce\x17%\xf4\xeb3*\xd9_\xe5\x18{iK\x9a\xa8\xda\xcbM\xadU.\x12\xb4L\xbf\x95\xea\xe3\xd6\xe3\x1cTn\xa8\x18t\x99+\x07\xb1\xc5\x96\x904 \xb0t \xc3#HxV\x83\xad-4\x0bK`\x13\x10I\"\xae\xa3w\xba\xb8/\xa5\x93\x11eA\x86d\x07X\x18\xaf\xf5\xb2\xfe\xb105\x8aY\xda\x1a\xedk\xf3\xb9d$\xaf\xf2\xb8\xd4Lubf\xf6\x14:\xfa\\\x98B\xef\xd7\x86\x08fa\x14\xad\x87\x084NWkg\xb6\x16\xe9 0\xa4\x06?6\x95\x1d\xa2M\x9f+\xe1\x85\xe6'.\xcf\xba\xd1\x95\x19 $\xde\xaa\x16\xb0\xdcdy\x04\x18\x80\xe8\x18m\x8c\xc5Am\x88\x8ff\xce\xb7\xaa&\x9b\xd1\xe4\xc33\xf9\xb3\x97\x19\xbf\xfb&\xf36\x80\x1d\xdb\xad\xe7\x02NM^\xc5&\xcf\x8fF{\x95\x12`:-\xc9\x9b)\xcb-\xe2T\xe9\x17a9\x00n\xab\x87>\xca\xb5A\x08\xbc\xe8OB\xf8_P\xaca\xb3\x977b\xe4\xd4\xfb@\x07\xfb\x19N`{\xf2\x9f\x9b\xbfl\x0f\xb6\x9e>\xdf\xfa\x0f\x7f\xeb\xb7\xad\xab\xcb\xed\xb9\xc9\xf5\xe6\xd7\xf6\x10\xae\x80\xca\xd9S\xb0\x06\xe8\xf4_O\x13:V\x1e\xd4\xfbfh\xf0\xb5Q\x01x\xa3\x0f\xd0\x96\x03\x8f\x8a3\x84\xed\xce\x1c\x97\x95\x83L\"\xc2\xf3\xeb\xf2:\xb4\xa7P Y`\x9bFb\x07\x07\x9ea4\xef=qD\xef\x1d\xec\xec\xee\xb6!\xdc\x90\xe7\x873\x97\x80r\x93>\x83\xbd\xfd\x9d\xe1\xd3\xae\xc2\xf4b\x89(vh\x7f\xb6\x86\xb43<\x99\xc4h\xe7\xa9\x0b\xc3\xa7C\x17\x86\x87O[\xd0\xba\xb8\x82$\xce\xc3\xb8\xd0\xe7R\x12\x979{\x10\xf0\xbe\xfb R?\x19\xa5z\xf2\xf5O\xd4{\\$\xed-u\xb6\xd2\x9e] \x97\xc9\xfe\xce\xc8\x98BP\\\xfd\xa0\xe2\xfe\xc1]\x8e\xb9\x8f\xc6>lR\xban\x8b\xa7 8>\x86!3t\xd9\xe2\xa3\xd1\xd6\xc0O\xc5\x84\xf3==\xc6c>\xc9\xab\xfd\x1b\xb3D\x15]\xfb\x8c58d\xd9Y\xba\xd2\x1f\xf0\xce\xc4\xad\xe3\x10\xf37\x1a\xec\xf6l}\xb4^\xeb\xf0\xec\x19\xe62\xc0\x00\xdb\x98\xd0 \xa6w\xa3\xc3^\xdd\xc2y\xea\xd7\xaf\x9d\xf5\xfb\x85I\x17F\xa3]\x16\xc2\x03\xf6\xe1 \xed!\xf6n\x8d\xbev\xa0F\x1c\x07O\xd9\xa0\x8b3 \xd2i\x05\xc9\x94\xc0*1x\x91\xc9U\xb2\xf1\xee>b\xbc\x87t\xbc\xbb\xe4\xeb*I\xf3\x0cN\xe0\xf7\x07\x89v,\xc1\x106<\xd2\x1b\x9b7#\xf9E\xb8$I\x91\xc3\xc2g~\xa0\xd7\x84\xc4 B\xe6W\xf0~\xd04\xe0w7\x10D\xc4O\xbf\xa1\x89\xa2\xb9\xe0\x19n\xc5\x18`e\xef\xab\xe8\xc2\xe5#\n>\x95o\x16T\xe3\xc9 \xf3\xe2\xda`\xf9\x8e5\xf5\xd0C\xb6z\xecv\xd4\xab\xcf\xb7!\xaab_\xd4\x97\x81\xc8\x0f\xa17\x955\xa6\xef\x10U\xb2\xa5SF\xcb\xd79\xfc\xb7\xb6\xd0\xac\xab\x94\xd2v\x07\x0f\xa8&l\xa3Z\xac\x8d\x95\xa0\x1d\x03f\x9d\x11\xdf\xc8\xbc\xa6\xb4\x10O\xe5\x9b\xb1\x8av[\x13k\xd0\xeaU4-\xdf\x19\xe6\xc9\xd4\xa9\xda\xe2=\xad\xdf\x8e\xd5,\x89\xad\x1d\xa3M\xa8Y\x15\xcb_\xb6\xb4\x9a\xe8\x1e\xe7\xa9\xcd&Jb\xb3\x00C\xbf\xd4\x9f\xcdx\x12\xda\xe6\xc6Y5f\x04\xb3\xb7b\x1a\x0b\x9bW\x05\xa5X\xe0\x14[\x14\x01\xc4\xed\x08\xc3\xa7b\xdd.D\x92\xecuj;\xed\xfbu\xdah\x16\x89\x88\xc0\xc4L\xd2\xb3\xad\xb0W\x1a\x8a\x01\xfb\xd8\xc6KR\xa6S\xf4\xed\x083\x11\xe9\xd79~@\xb1d$\xe0\x8aA\xc4x\xf6\"\x9e\xf2cv\xe9\xa5El\x9b<\xfc8(\xe4&;v \xf0D\xcfl\x8f\xea\xe6N\\\xfd\x8ev&T\xa7\x98K^\x86U\x1a_\xe9\xa1\xdd\x16P\x12Q \xab\xc8G\x14\xc8b5h+\xa5\xabV~\xe1\xf6o\xc6\x8c\xc2\xc4\x95\xda\x06\xf9\x12\xf4\xc2^\xe2\xean\x08d\xf2K\xc6\x9b\xe6\xe6a\xad.@\xa3\x01\x8eL;\x1a0\x8f^\xfb\xe6A\x05\xd8C\xebN\\h\x858(\x0b\x9c\x15(9\xe1B{\x96\xe6\xe8D\xcaZ\xaa\xab\xee\x86n\xec\xaa\xc5\xc4\x8b\xc9\xd7\xfc\"\x0c\xbe\xb4\x12\xa7b\x9fR\x8a\x80\xd1\xbc\x8d\xb8\xcdM\x93!\x94W\xa8\xc5\x9e\xc1\xb0 \xce\x12\x17\xc4\xcc'\x93\xb2*\xea\x97G\x10onRr-f\x86XR\xe8\xe8F\x98\xfd\x883\x1b\xe4V\x80\x0fe\xf7\x98\x15Z\xa2\x07\x03\xfa_aO%T\xe8\xc2B\xb6\xabG\x00\x9b\xcfF> <\x1c+[\x8e\xd5\\\xd4\xaaM\xbc<\xcc#\x0cJz\x9d&\xb7\x19I-\xfa\x90\xff\xe6a\xf2\x13\x8f\xc47H\x07\xd2\xdf~:\xbf\x11y5\xbd\x1b\x92ft\xfeX$\x93\xf2>+K\xe3\xbb\x1b\xfcn:}\x1bf9\x89\xb1\xde\x1b\xf6\x12\xdd\xd1\xd9\xef\xd9L\xfcL\xc92\xb9!ja\xf6\xf4y\x14\x89\x17\x99xC\x96a.~\xafR\xb2\"q\xa3%\xfe\xf8C\x1c4\xea\x8d\xa4\xea\xccK\x8d\xef\xc0\xc9e\x1dz\xd7a\xdc\x99\\\xa5A\xb5\xae\xd2$ YV~\xccC\xa4HA\xf1\xea\x8d\x04\xb7\xd3\xb6\xf9\x16\xac\xd2\xb6\xa5|\xb6\x98\x86\xe9\xe3z\xc6>\xed\xeaW\xb1\xf4\xb3/=z6\x90\xb6>h\xb8\x10E\xc5o\x15\x19AEO\x90KL\x9c\xcc\x90\x98G\x84\x1a\xa0\x8a\xd8\xda\x90Uu:}\x0f\x06\xb1\x15\x03\xf5\xcb\x8aU\x19C\x83k|\xc4@\x9aH/\xd5\xe2\xd0\xca\xbe\xe6\xa4\x0bk&f\x94\xd8\xc0p\xc7'0\xa4\x88E\xd2\xdeT\x98jx\xc9\x835\xc8\x8f\x9a\xf4DlLx+duZ\xb0\x19\xd7\x07\xa8\xc2{\xb5\xd7Lt\xcfP{\xea\xa8\x02|\x9fb\xdep\xe2\xd7\xb1\xaeof\x961\x17\xd6\x86\x88\xa2\x19\x0b\xd0 \xc3&\x91\xa1\xa1GnHzW\xcb\"\xdd\x95\xda\x0c\x19\xb7x\x92^j\xf8\x1bts\xb1\x19W\xcdp2\x9b\x04\x17B\xc7a:\xb5\xd05s\xf2Z\xde\xbb1\xf15\xc2\xb5 \xc7\xb8\x84cN\x0f;8\xc5\xe0\x14C\x1e\xd98e\x07\x1c\xcb\xb9 )\x85k3\xa9\x9d\xe4-\xa0\x16\x97\x00]\xfb\xa6\xef\x03}6\xc4Y\x9a,[Yv;4\xcc\xc3\x83\xf1\xb8\x8f\xbc\x94dE\x94\xbf.\xe2\x80\xae%\x17\x9f\x04\xc9rU\xe4~\xce\xd9\x94\xce\xcd&6Z\xe3\xe5\x03\xab/#\xf9\xa7GWJgH[q\xed\xa1L\x0c\x88_\xb9wuE\xb2w\xc9\xb4@\xf6\x8d\xf2i\x98:\xd6/\xa2\xfc\x1dY&,soB\x9f\"\xda$\x02\x8b\xbedH\x94\x11\x1d\xe5\xcb<-\x82\xbcH\xc9\xb4D\xb6}\x18\xefGP\x99\xbeBe6\x99s+\xc1<\xb8F\xea]\xc8\xfeM\x1dg\x87C\x06\xb30\xcd\xf2*^\";\x18\xfc\x18X\xf5p\xbb )\x01\xe2\x07\x0bX\xf1\\\xbb\x94\x11\xf0A\x9c%\x9a\xa3\xc3Gk\xb0\xb2SG\x0d\xa0\xd0\xbd\xc6\xd3\xf8~!wYC\x88UR\x8bq\x1dU\xb5\xf9\xc3\xd3\x0dY_\x0e\x8e\xdb\x93\xe4\"Z\x84\x9cW\x08\x81\xd3~\x03F\xfb\x11N\xfb\xe5\x93\xb4\x9d\xee\x03i(^J\xa6E@l\x85\x13\xea\"\x98\xc9\x84R\xcb\x97\xcc\x18R\xa3\x8es\xe1\xf7\x07E %\xb1\x9fu\x91\xb6\x8f\x04L}\x99\xd3\xf5m'z\xb5\x97\xc2\xa7 \xee#\xb6\x87\xc3\x03\xe5@D\xc6\xc6\x1e\xed\xee8zV4\xb6\x87\x83\x01\xa5\xfc\xda\x1a\x00Y\x84'\xd2'$6Z\xabK\x83\xea\x91TLZ\x12\xcc\x18tM\x96\xb4\x1a\xea\xc1\xaeaD\xed\xcc\xf5\x86\x1c\x0b\xd5\xc4G\x8b=\xb6\xf1H>Z\xedq\xac*$\xeb\xfb\x8e\xc9\x9c\xc6`\x8d\xbc=o\xcf\xd2\xad\x12\x8d\xfd\xe1\xd5\x153\xd4\xa4\x7fO\x84\xdb@o\xf0\x8d\x0e\x0e\xd6\x86\x9f\xcc\x85\xca)\xe7j\xb2\xeau\xa7Q\xbf`\xf7\x0ev\x95\xe7!\x7f\xbe\xa7<\xa7{\xc7\x9ap\x9c\xf8\xbe\x88\xa2K%Tx!\x17\xf8,\xd2\x9d\xab\xa524n?E\x13\x04f\x0fx\xe1\xcf\xcb\xcc\xde\xdf\x01R\xd2\x89Bo\x0b\xcc|2\xe6\n\x16\x08c\x8ev\x99q'\nF\xc6\xc8&?\x16\xb0{OGz\xc8>\xdd\xeb\x9cx\x0d\xbd,\x96q\xc2\xdej\xb7E\xca\xb2\\\xc4%\xd8\x1e\xdb\xf7\xd1Su\x96Y\xdf\xf7w\xd41\xb1Uqp\xd89$\xc3\x0c\x85\x0c\xde)\x83w\xb26\xbc\xf5\xb2> !\xef\x0e4#\x91NXJl\xb4\x93\xd4\x82V\x99h\xce0\x89s c\xa42\x84U\x98\xf9\xbc\xab\xbdx0\xc0\xad>\x96\x90\x1f\x14\xfbR\xb5\xa1\x17\xc6\x0b\x92\x86\xfc\x149\x1c:\xcd3-\xb6w\x06\xeaL\x16\xac\xae\xda*\xac\xea\xb2g.\xf8\xd2\x9br\x80\x19\xae\xbd\xa2\xd2\"\xf0\x14I\x83#\x88\xe0\x18*uFD \x80\xe6\xda\xa5\x04t6\x89\x14\x18\xce\xaa\xfa&\xc1%\x8a\xb9\x94G\x94)\x93\x1f\xb4\xebwg\x86C\x879\xc7\x88@\xda\xc9\x0cfU~IJ\x12\xce\x1a\x84\x96_W\x95\xb9P\xa8\x0f\x10\xfbo\x08\xd7\x89\x94\xf8S\xff:\xe2\xb1c\x17aV=9a^\x80\xf5\xf2\xb7i\x98\xd7\xcb\x97Oxy\xa6q\x89\xa2\xe4\xf6\xaf~4\xfb\xb0\"1'\xd3\xeb\x15\xd5K\x94\xb55>,\xabL\xe2\x80\xd8\x16\x89\xa7\x96\x0b\xabvp6\xb5\xf4\x9a\xba\x85\xc3\xc1\x95\x18\xc0y\xee\xe7\xc4#\xf1\x94L\xe9\xcb\xb4\xd4\xc5\xd9S\xd6\x85.\x1d}c\x0e\xb16[E\x0d\xf4\xe2;\x99\x1d*\x1f9\x19.\xaf!\x17,\xd1\xaf\xbf\x86\xf3\xc5\xcf~N\xd2w~\xfa\xc5r\xd56\xe2bIRZn\xdc\xd0\x85\xcfI>n\xa7\x98\xc5\xe6\xd6\x00b!7[\xdf\xfc\xd5\x80\x1c\xb7\xd7P\xa6$\xcb\xd3\xe4\x8eL\x1b\xdd\xef\xddE\xc9\x9f\x86\xf5V\xacS\xec-]@\x8d\x12\xb5\xf1TK\xac\xfe\xa5W\xf6\x0d\xbd\xce4\x80(\x0b(d\xb9B\x08\xd4\x06\xa2\xc7\xc8\x7f\xfc\x10*\xfd\xb3i\x10\xb4\x88Q\xe1M\x19,I\xe1z\xc5\xbf\xea:\xe4\xb1Av\x80\x14Q$6,\xae}W\xdeGyM{\xff]\x0e\xca\x9d\xe1\xc8\xb1\x1f{\x8a\x93\xca=\xabT\x91t\xd1\xe8k\xf6o\xff@w\x90\xb3\x10\xf7\xfe\xd7G\xf6;\xb1\x07.\xd2\x1e\xdf\x00\xccu\xcbk\xa9\x94\xa1flvl\x1f:]\xf2\xbe\x90;~z\xe2l\xfb\x98$\xc2\x16\xc0\xc4@\x0b\x82\xa6\xf9\x1d*8\xf4\xb2;\x19\xc1 \xc3Pz\n6\x05\xd6F\x0bez\xd0\xd2\xef\x1b\x86\"\x1a\x9a\xb2}\xd4D>\xca\xf1h\xa7\xe7\x8cm\x8d\xf6,t\xb7\xc5\xedVP.\xde\x16\x9bH\x03\x1f8\xe6\x1b.I\xa2\xf3\xf07R\xe2\xad:L\xe8vl\xa4o\xad\xdd\xfa((\xab=*\x1a\\&\x16\x9cNi\x9d\x94\xb9I\xc6\xed\xa8@\\%\xfb\xda:-q\xad\xcf\xdc\xba\"\xf6\xe6$\xa7\xf7\x88\xac\xd0\x01\xca\xa7O\xcb\xf1\xa2czu{\x02\xc3\x81C\x0b\xa4$\"~F\x98\x84\xaf)\xa1}\xd0\xa8oc\"\xd2\xa9b\x83\xe9X\x05\x08\xbd\xf2\xdbD-\xd5\x0b\x06\x8fY\xe4 \xeb\xa6\xd6Y\xe8\xa0[\xec1\x8b\x10\xe0\xe8\xc0\x01\xda5\x0f\xbauO\xab\xe8\x03\xce|\x91\x92\x06@\xbbD;\xe2\xfa\x16h\xa5\xdf\x05Zi\x19G\xa9\x114Z\\\xfd\x01\xd6\x88\xc8\x00z\x98\xcd\x92\"\xed\x02Y\x8bT\xf1[\xa0\x96|\x17\xa8%R\xf4\xa9\xd4Q\xf5\xf9\xe2Z\x0bp\xae\xd6\xf1\xb8\x8e\xca\xf4Gg\x81O\xdb\xe4ju\x03\x7fmq\xb3\x98tO\x95.%\xfcy\xb7l\xc4p\x94\xa7v\xb2\xfe9.\xf7\xe8\xd1-s\xb9\xd1#\xc8\x08\x89\xfa\xda\xd1\xcb\x8a\x0e\xb5\xe2\x96\xe1P}\xce\x98\xfd\xe1\xfe\x81c[Y\x1aX\x1a\x9e\xff5\xefH)_k\xca\xdfX\xfe\xc1\xc2\xf1\xb2U\x14\xe6\xb6%J\xcaR\xd8\xd8\xde\x1f8\"a\xf99F\xca\xe8\x03$\xce=\x93\x9a\x05\x98m\x94~\xe1\xda-tr\x84\xc8d\x0d\xafx4FH\xe4\x87\x14s[\xb1\xbf$\x16\x1a\xd1$\xd5=7\x9fDIxi\xd2cK\x9f\xf9\xd5\x17>/\x87\xf2\xd6M\xf6{\x0c\x19\xb3H\xe0\xde\xcb\xb9\xe3\xb0\xa8b,\xb6\xcbi)c\x871\x14\xe2\xb6\xf64\xa9\xd6\xc4\x18\xec)\x89HN\xf0\xbd+\xbd\x92\xd7\x94c\x97\x93(3\x85\xe54\xb5hu\xf84h!\x87\x04\x14\xa7}&>Ja$a\x87\xdc\xfeZH\xa1sM\x94z:9\xf4\xc1\xa9\xc4A\xc0\xb8\xcb^\xa5\xd76\xeb\xa4\xbe\xf5\x9bo\xb4o\x10\x81\xef\xeckw\xdf\xde\xaeJ\xc53Q\xdb\x81Z<\xe3\xc5UYj\xc4\x9f\xab\x12\xbb\x80?W\xeb\x99\xf1\xe7*2X\xa1\xd0\x8ci\xb3\xce\"B\x0f\xc4z\x81\xa9T\xe0\xb5O\xc9\xe4\xbbz\x81\x05+\x10%\xb1\xbe\x82\x1b8\x81\xb4\xfeh\xd9I\xb47t7\xd0<\xc8\xe7Z\xb2\xf9\xe5\"\x8c\xa6)\x89\xc7\x86sx\xe9\xaf\xc6\x10zK\x7f\xd5$\x0b\x80 1\xcf\xfc`A\xcb\xf0\x9f\xfarAR\xc49-\x85?\xf4e\xf2\x045\x9f\xb4\x14\xff\xa9/\x97\xc4\xd1\xdd\x18f\x8dw\x1a\xca\xe5e\xb2\\%1\xa1M'^y\xd3,\xf7\xb1HI\xadl\xedA\xb3|m\x05\x8cA\x03\x1cy\x86\xc7\xa0\x81J\x98\xfd\xe4G\xe1\xb4,Rx\xf5'\x9aN\xa6\xc9\xea\x82\x99De\xa6.\xbd\x8c\xfc,\x1bC`z\xcf\xd7\xe4\x18\xa6\xa6\x12\xef\xc2\xafa<\x86e\xf3\xfd\xab\x0f\xef\xc6\xe07\x9f\x97J>\x8d\xf1\xe9\xd5U\xb6J\x89?\x1d\xc3M}q\xea)\x829>\xfdc\x90Nc\x93\x87L\x12\xf0\x94\xb2\x1e\xf6h\x7f\xbf\x12\x14V\xe2\xa5\x85\x9f}\xb8\x8d\x85\xc8P\x8b\x9cF\xfb\xaa\x9eO\xcf\xa1~!wc\xd8\xd0XA\xa6d\xa6\x7fqu\x95\x91\xc8\xfc\x0e)\x84\xb1\x9a\xbeX\xeb\x10\x9a\x19O\nI\x9cG\xbc\x94T\xbbJ'?\x8e\xfaU\xf3\x85\xdcI\xd5\x88_BU\xa1\xe1\x1cX2C\x03Y\xd2\xd4*\xd3\xeb\xcf\x7ff'\x96vE\xe6\x98^\x994_\xe0\x1ch\xb6\x16NA\xdc|\xbeJ\x93U6\x86B\x03\xff\xe46\xa6|PhZ\xd6P\x01\xa7\x8a\x0b#\xbd\x0f\xea\xc7\x88\x060:`\xa4\xcc\xd0\xfaw\x1d\x97\x06&\x0b\xf0\x15\xe8,\xc0\xd1\x9b\x96\x11\x04:\xde\x19\xd5S)\x84t\xf1\xe4,3\xcf\nm9R2s\\\x88\xc4\xc3\x19:\x98\xc0&\xa0\xd2\xcfqky\x06=\xb6\x84\x05\xe91.\x9f4\x8b1z\xb7^\x10\x9f!\x1d\x14\x96\x921\xe6\xb5\xb6Q([\xd3\xe6\x99\x87}f\x1f\x93OR5\xe3.\x05\xdfTg\x18\xb5\x05\xa3&d\x98\x0eh\xea\x80\xef\x05\xfc\x8c\x84Fl\x8f2\xe2\xc3\x14\xbd\x944\xcb\xb4T\xf2-J\xc3\x9e)\x85\x11S\xef\xdd\xc01L\x8f\xe0fs\xd3\x81\xc5\xe4\xa6n\xd8s\x83\x811\x9b\\\xee\xc0\xad\xf7\xa9\xee\x8f\xf8\xd0\x18 \n\xdf\x88\xb0?\xa3\xf0\xcat=\xa5\x9d\\\xa21\x87\\\xb2\xd9|\xb5.\x96N\xcd\x96\x8c\x02^\x9a\x81e\xc3\xe0\xfeA\xb77\x02\xba\xdag.\xac0\xa9&z4\x05E\x9a\xd2\x03\x10\xfc\x1aK\x13\xd4\xc9\xaa^Fp\xca&C\xb7\x9e\xd2 P\xbbWs\x8f\"\x0f\xae\xa4P\x9a\xa7G\xfa\xf3x\xfa\x89\xc5F\xf8w\xd2\xa9t\xa8\xc6\xe81\x86\"w\x19\x96\xa5\x7f\xf8>\xa0?\xf8:'\x1e\xc3*\xf4\x17b\x1eu\xfc\x12M\xd1\x13_\xf8\x0c\xb8\x94\xa8\xb4\x7f\x7f\xa8*n\" \xd4\xba\xd0-\xdc|\xb5\x00~8h\xce~\x0cj\xdd2\x16\x8d\x87_\x17\xd2\xf1kHg!\x90\x0e\xdb5\xe5\xf2\x90q\xd0T\xc5A\x0c\xdel\xe1\xe39.\xaf\xe9\x12mi\xde9\n\xb6\xf1\x0d\xd8\x86=\xb7e$F\xf9\xbb\xba~\x8c\xe2\xbd\x15\xf3\x81\x99\xd1?cqG\xcbj\xb0\xd3rM\xec\xb4t`\xd5\x07;-;\xb1\xd3\xbc\xc4NK\xc7\x85;\x86\x9d\xee\xe0\x18\x96GpG\xb1\xd3|rW\xc7Nw\x06\xecT\xeb\xd0\xbc\xd7\xfe\xe7{c\xea\xc2B \x81\x9b\xba\xfe\x9c.\xfe:u\xfch&\xb8\xa6Gc\x0bD\x90\x12\x0c\x8d\xc9\xad\xca\xa4i\xf0'\xe8&M%\xb1\xd3\x81\xe3\x9d\xdf-\xaf\x93HO\xe9\xa6\xebU7:\xd4\x9b\x0d\x0d\x0f\xbf\xcd\xd6m\x83C!\xa9\x0c\xd0q\xc1\x7f\x8b\xdd\xdb\xc8 \x81|\xaa\xaa\x19\x19\xd3\xbf\xdf\xb0#bt\xf5\xfe\xb0sdf\x94+E\x12\xe4f]p\n\x13r\x89\x96g\xfe\xb7\xc8\x131\x1e~cxJ\xf8\xbb~\x13\x11\x1aB\x972\x95\x1b\xa9\xechH\x13W`\xe0b\xd8lD\xe1\x11k\x7f\xc0j\xa4\x93I\xfbF\xe8\xddV\x02\xa7`m\x0d,J_u\x8c\xbf\xc6p\xe9$E\x9cUb\xe7+F\x1c\xea9C\xc4\xcb\x8a\x15I\xaf\xb8yq\xc5lU\xd6c\xacR;\x97eqM\xec\x15$\xb1\xd0E\x9a\xc4\x17\x98\x98_\xcb @\x87]\x8a\xb8\x84\x89\x82\x9e\x0b\x03\xd6\x8dY8/D=\x1a\x9f\x81\xda\x93\x87\xbaU\xf1\xa3\xc0\xd6\\\x0e\xaa\xd7\xb9\xc2\x88\xc45(\xd7\xe0Z\x9f\x80\x98\xdc\xa2\xe9r-.w f\xf8\xfe\xb6\x07\xfb\x9d\x9b\\\xb7kj\xa6\xceJ\x98\xd8\x97~\x1c'9\xd0\x86\x11\xc5%)\x14q\x19sH\xbb[\xbe\xcb\xa0\x1a^\x1f\xcaxyt@\xfb\xa0\x81@P\x10\x91b\x04_\xba_S\xb9\"\xe6\xfb\xdb\\\xdd\x9ch\x19\xab\x99c\xe5\xfe\xf02\x9d\xd0\xec\xe3\xc9\xf4\x87x.\x89\x93\xa8>\x04\xdd\x0c\xd9\x03\x17B1 g\xed\xc3\xa9\xe7\x8c\xb9\x06\xa0\xb5\x18\x0d\xab;M\xf2\x99\x16f\xab\x18\xff\xf7\xc3\x8cr\xa8\x98X\xe6\xfe\xbeK\xceT\xc6\xd6\xe6Lm\xccX*\xd2dj\x1b\x10|\x048\xca\xc7\xa5\x9c'\xed\x92\xf30S\xef\xfb{a\x06\xde\xc4\x0b \xefg/\xcc\xde'\xf9\x82EcH\xdd\xda\x0b\x06\x8a>\x04K7=W\xf5An\x83\x0b\x93\xfb4\xa1\xee\x04NBpjbB\xc9\x079\xd5o\xad\x99\x94\xac\x88\xdfo\xdd0\xcf\x1e\xf5\xe8\xc6\xa5\x133\xda;f^\xd61lb\xd4L\xccP\x85\xc5\\\xefL\xcf\xc1\xe6F\xf4[e\x81\x1a\xcby1\x18/\x8c\x83\xa8\x98\x12\xa1\x95\xe9p\x1fG\xef\xe0\xb2\xad\xda\xeb\x07\xae\xc9\xed[S\xb3\\\x9bEM\xee\xe5\xfe\x9c\x9b[\xd3_O\x9eP\x1e>\xa4\x8b\x88\x89\x92\xe9O<\x13M!a\x1f\xd0\xaeJkJ\x86ofa\x94\x93\xd4n]\x91PAn\x8b\xc7J.\xb1v\xaeV*\xad\x93\xe6\x84i\xa2\x16r\xf3\x15\x9c\x0e\x14:\x88\xdf\xf7\xf7hK\xc6\xde/WQ\x18\x84,\x1dIy#\x97 _\xa5\x12\xe5\x8d\xae\x8e\x9e3\x85\xb2A/J\xfc\xe9\xbfs [Y\xe0G~jq1\xbex%\xd3Y\x89m]\xa0s&\xbac\xc6I\xbc\xc5\xbeA\x84LO\xbc|A\xa0\xec\x7f\x14f\x18\x07\xdf\x87,X\x90\xa5\xef\xc1\x1b\xf1*%Y\x12\xdd\xd0\x13!\x99AV\x04\x0b\xe6\xed\xdf\x08l\xe3Y\xcdIe\x86=\xc9r\x15Fd\xfa\xa6\x82\x9c\xcf]\x08,\xd1\x01\xcb\x85\xc9\xa5\xfa\xc1\xd9\xd7\xe6\x07\x02\x9e\xda\x0f(m\xf9\xce_)\x14v\x03\x9etK\xf2\x1d\xa4\xd5X\xd0\x8b\x01k\xac\x95\xdf\xe3{\xf2kA\xe2\x80\x98K,\xfd\xd5\ns\x1f\x98\n\xcc\xfc(\xba\xf6\x83/c9h\x97\xb8\x1e\x94H\xf3\xd0q\xea\x8b+\x9e\xb0\xadx9\xc1m\x8af\x16\x9eh\xa9z\xa6\xf1\x15m6GQ9a\xa8\\\xe7\xa7|\x84q\xed\xf3#\x16,v\xe8H2'R!!U\xae\x08Fj\xd2\xd6\xae\x16\xc3\x9aP\xc9Jz\x15\xde\xab\xb3\xd7\xcf?\xbf\xbd\x10\xfa\x95R\xc1\xdf\xb6\"\xc4j\xa8w3\xbb\x0d1\xb2\x9c:h\x1d\xdc\x03?#0\x1ck\xe7\x03\x83'\x8a~)p\x9c\x0c\x0c1\x02\x0c\xf1\x96\xb1\x9d\x91\xb9\x1d\xb9b\xb5)\xd5G\\\\\x86\xa6\x04\xd3\xa2\xfd\xa6\x86d~N\x93x\x0e\xcc3\x141\x88h\x12\xd7\xcf9\xc3&|\x16J\xe9D\x9b\xba!\xe4y.SA\x0e\xa2\x83u^{\x92;.l\x90^\xf1_\xc49+[K\x17\n\xa2R\xf0\xe6\xf9\x8a\x04\xe1,$\xd3\x12-\"C\xcfQc\x06v\x92RD\x19\xc6\xf3\x88\xf0\x11r_]\x07\x83\xc6\xfba,pn\xed\xad\xa72\xb5k\x84\xb1\xd1\x0d#\\w\x18\x7f{\xfe\xee-\xc7\xde\xb51P\xbci\x1a\x81\xf4\xae\xd1\x7f\xb1\x8f\xc9-\x14\xb6\xe6\xdcb\xc7\xa7V\xaa#\xf0\xf8X\xf5\x05\xac \x93\xbb\xad1\xd7$\xf6\x86\xc3\x9a\x19\xdf\xa1\x96\x96K\xda\xe4\x956\x81'\xf4\xa5\x1aXLn+\xd4\x1e+\xef>\x9f_\\}>?\xbb\xfa\xf8\xe9\xc3\xc7\xb3O\x17\x7f\x1b\xeb\x92\xa1\xfe\xf5\xf9\xf9\xd5\x8b\x0f\x1f\xde\x9e=\x7f\x7f\xf5\xd3\xf3\xb7\x9f\xcf\xc6\xb0\xab/\xf5\xfe\xf3\xbb\xb3Oo^\x8aR\x87\xfaR\x1f?\x9c\xbfA\xd6@)>2\xd4\xfa\xe1\xa7\xb3Oo?<\x7fu\xf6J\xed\xc6\xce\xa8\xf9E\x18\xd3\x85\xf1\xea\xc3;\xc1\x10\xbfD\x19[\x97\xf3\x12H\xb2\xd1P\x7f:\x02'v\x89\xc7\xab\x0e z8\x98NS\xe0\xe2h\xe2\xbd\xfa\xf0\xeey\x9e\xa7\xe1u\x91\x93\xf7\xfe\x92d+?\xe8\xfe6\xd3\x7f\xdb\xf5Y$>\x13\x00\xe8\xf5U \xbez\xc7\xe3\x9d\xbc#\xf9\"\x99\xf2\xef\xf4\x98\xba\x94W\xccP^\xe1\x85\xd9\xcb\"\xcb\x93e\xd9_J\x18\x16\xdeU\xe3\xb9\xb0\x97\xe4^U\x9a/\x9d\x16\xba\x1f\xf0`]\x95s\xa0\xea\xd7fL\x12f[\xbb\x87\x96\x0b\xb3\x16co\xdaw\xa4\xcd\xbc&Y\x98\x877\xc4X\xa7\x1e\xcb\xf5\xab\xfc\xc3\x0dI)\x07E\xa6\xc6\xe1\x9b\x90b\x93\xc9\x95/\xc3F\x06~\xf2/<\x05\xe2\xb0 \xf8L\x1e\xa5x\xa6\xefd\x19*(\xb5\xad\xbd\x01\xee?\x174[\xb4ms\x03\xdf\x9a7\xe8\x9c>\xeb\x08[\xb5\xf0j{\x02N\x14sA\xf9\xd2\xbbi\x00:\x96k\xb1\x88\xad\xd4\x8e;\x0es|\xcd(\xaf\x17\x19\xbf\x92w\x1b\x9c@\xc4\xca\x07\xc6\xf2\xf5\xcd\x06'\x10\xb0/dD7\x99]6lv\xc4\xa5\xe1\xd7jO4\xbeq\xd6\xf8\xf9\xd6\x7f\\\xf9[\xbf\xfd\xf2K1\x18\xbc\x1cl\xe1\xdfW\xfb\xec\xcf!\xbb}\xcdn_\xb3\xdb\xd1\xeb\xd7\xf4\xcf\xce\x01+\xbcs\xf0\x8a\xfdyMo\x87\xaf\xf1\xedh0x\xb9\xc5\xfe\xbe\xc2?\xac\xf0hx\x88o_\x0e\xd8\xed\xeb3z\xbb3\x18\x0c\xe9\xed\xab\x03\xfc\xf6\xf5S\xf6\xf6\xf5\xab\x97x\xfb\xea5\xbb}\xfd\xfa\x95&|Is\x05\xbdyu\xf5\xfc\xe2\xe2\xd3\x9b\x17\x9f/\xce\xae\xde?\x7fw6\x06k\xea\xe7\xfeVJ\xfc \x0f\xa7Vs\xfb}\xfa\xf0\xe1\xa2\xed\xa34Ir\xcdg\xf5/\xae\xce/\x9e\x7f\xba\xb8z\xf9\xd7\xe7\x9f\xb4F\x85Ji^\x0e6\xc1\xfa\xe5\x97-o\xb0\xf5\x14\x81\xfc\xe2\x00\xa19\xe0\xc0\xddg\xd0\xdcy\xcd\xa0\xb9;\xd0t\xa3Z\x1cz\xae\x1e]\x0d\xb3,d\x8e\xd2\xf1\xd4O\xa7\x0c\xff\xeb\x91y\xcbQ=n\xa4\x16\x00\xb4DV\xca\xf7\xa1\xb3\xea\xfa \xa6\xfai'\x13jj!3\xe2\xc00\xf5\x03\xb7\xbd\xb2I~\xe9\xc8\nr\x8d\xd6\x15\x8c\xa8B|3ln7\x13)\x8a\xe6\xcdFS\xcf\xef\xceO\x1c\x1c\xee\xd4\x18\x8a\x1df\xa3\xfc\xd4\xc0W4x\n\x8a\xef\xfc`\xf1\x89\xcc2.\xe1Bi\xc7\x157\x9d\xe264:a\x87\x9e\xcfX&E\x9cK\xf6\xf1\xea\xd8P\x98\x1f\xa2\xb5\x94^.V eZ\xaf\xc6\xae\x7fi\x94\xe7\x10\xb5\xdf\x92\xce\xa7\xf9\xd2K\xc9\x8cI\x91\xe7$\xffD7\xff;\xda\xea'\xe2O\xefl\xc7#\xf1\xaf\x05)\x08z\x04R\xcc\xdc\x86_\xe7$\xffk\x92\xe5\xef\x93i\xe7\x8e(\xbb*}c\xb7:6\x17q+P\xb5\x8dxSRN+3\xb1S&\x94>S+n\x08\xb0\xeb\xfd\xe0\xf1\xf3Z'74M+\xe3\x8c\x94^4'\x12\x95:(T\xc6\xc4\x13!\x97/_\x05I\x9c\x93\xafF\xdfdM\n\x10\x90\xd6S\xeae\x8b\xa4\x88\xa6\x9fWS?'\x08\x14_\x9ft\x18\xf0\xacA-B\x1d\x82\xbe\xc3\xec1\xeb \xb0\xc5\xa8]\xf6\xd5\xe3\x16`\xdcc\x016\x11P\xdbT\xadH:K\xd2%\x1b\xef\x9b\xd9{\x12\x90,\xf3\xd3\xbb~\xfe\xcb\xc4\xbb*\xf0\xcb\x17~\x1e,\x98\x86\x8f'\x8a\xc51\x9ajo\xac\x9f\nk\xe81`\xf8=0\xe0\xc8\x10\xedo\xb8\xfbT\xab?\x1b\x19\xfc6w\xf6\xd4\xf2\x183\xad2\x08\x91\"YN\x93\xa0\x10\xd3\xab J'^{\xe2\xc7\xbb\x84)q\xf4\xb5\xc5\xfeM8\xc7h\x9erf\xe5\x93\xe6{\xaf\xc8H\xfa|\xce\x1b\xde\xfe\xe5\xfal:'\xbfl\xff2\xdd\xf6r\x92\xe5\xb6\xa6\xa0\xf6\x1c\xd0\xf8x\xd0\x8d\xd7\xf0\xa9\x00\xd9\x82\xcc\x8b\x93\xa9\xc1:*\xe69V\x995\xa7~W\x8b8\xedz\x8e\xa5\x16?\x9e\xc7\xb1\x8cK:\x00\xc3Y\xb2,h\x93\xf4\xd2\xc5\x1d\xa5\xd9\xbch\xc5Z\xed\xb6E\xbe\x8c0\x8a\x1c\xda\x8e\xd1;\x07\xc6\xd2{\x8aP(\x1c}V\x00\xf1\x8bi\xfd\xd6\xd6]\x84Q)\xbbv\xd2p\xc8=\x16(\xdc\xf0?\x94db\x02\\\xdd\x0b:\xf7\x95\xd9B\xed=\xa5\xe1\xea2\x0bf\xeb\xc1\x03\xeb\x89\x92\x82a\xf9\xfc\xe9\x0d\xc6\x83\xd2C\xe1\x1c+\x10\x85\x84\xd2\x94A\x8e\xb7\xaf>\xbc\x93\x7f\xb3\xca\xc5\xddE\xf2\x85\xc4\xec\xc6\xcf\xfd\x8b\xd4\x8f\xb3\x19I\xdf\xe4d\x89\x0f_\x87\xbcQ\xba\x9d\x9fG\xd1\xcb$\x8a\x18\xc7\x8bO\x94\xdb\xd7I\xba\x14\x0e\xca\xf4\x9e\x85t\x16O\xde\x91i\xe8ce\xef\xc2%\x1e\x80\xcc\x8d\x9b\x9e\x03S\x8a\xce\xde\xf9+\x97\xfe\xc52\x1f\xfd\x90\x8e\xe1\xd7\x82d\xac\xeb\x1f\xa3b\x1e\xc6\xfc\x0f\xfb\xf2\xfc\xa7\xbf\xbc\xc5\xb5\x8e\x05\xce\x7f\xfa\x0b#\\\xc5\xddG?_\x9c\x93yy\x9b\x84q.n$(\x9c\xff\xf4\x176\xee$e\x83f\xd15^\x14\xb3\x99\xa8\x8b\x82\xfb|A\x08\xfb\x9c\xa2\xa1\x8b\xd4\x0f\xbe\xbc\xe4\x00/\x1f\xb0\xbb\xa4\x08\xb0G\x96\x88\xe7\xe1\xd2y\xcc\x18\x99\x93\xa1(Dl\xd1L\x1f\xb4\x93\xee\xccb\x92iv&\xddK)\xdd\x89\x8d73\xe0\xfb-\xa8,G\x15t\x81\xce\x1b3\xee\x8a\x94`\xc8Q\x17\"\xba\x10'\xd1%\xdd\xee\x1e\xc2\xb5c\xcd\xab8\x91\xa1\xa62\xbcI\x17\x024\x1c\xe9\xb1\x08T\xe2eQ\x18\x10\xfb\xd0\x85\xada\x97!\xafi\xbb\x9b[\xeb\xce3\xd5\x99c\xea{\x04\xc7\xeem\xd8o$xj\xee \xf6\x10\x9e\xd0s\xbf\xb9\\\xea\xee\x07\xf6\xc8PNrd\xb0w\x0de\xb8\xbb\x84\xa2;_\x0fAJ\xb8pG\xe5\xbd8\x0f\xb7o\x8a\xd8\xde;xp\xe5\xe5\xe3B\xd2\xb5\x84\x8c\x1d\xdc\x1d8\xdeL\xd7\xc3=},\xe6&\xee\xee\xda z&\x82E\x99M\xd0\x1e%\xe6&\xc6D\xf6\xc9\x08\xb9\xf6\x93\xa0l\xac\xb92T\x97\x93\xbe3\xb9&\xa4\xba\x98\xf4\xdd\xbd=\xc7\xde\x18\xd4D\x95\xa3\x9d\x03\x87\xc7\xedq\xc1jF\xcf\xd1\x9bG^QR\x8eG\xfb!\xc2\xfe\xee\xaa\x9e\x82\xe3\xa1%\x06\x8f\xb0\xb6\x12\xd1\xc2\xae4>\xfee\xb8\xba\xabPooRK\xfe}\xaa\xa5\xa8\x10\xa8<]L\xe3\xf54\x895\xe1\x18\x90\xdbB\xff\xdb\x9c\xf1Wbl\x9b'\xa5\xaf\x84n\x8e\xcd\xaeK\xbc\x9d\xa1qn\x1d\xed\xe4\xfe\x13!\xf5\x162n#\xb6\x87\x83\xa1c\x1b\xa7\x9a\xb7{@\x11\xbb>\xae\xef\xef\x0f.X~#\x8c/\xf4\n\xe5+7\xd1x\xa9\x88\xe7\x1c\xcf_\x07\xe8\xfd\xe0\xda\x9aQ|c\xa3!Vn\xcf>\xadU\x8ftat#\x89\xddk6e\xb3(\xdd\x01\xc0\x02\xcb\x86\xf1#\x17\x1c\x81g0@\x1e#ET\xf1t08\x18>}:\xda\xdb=\xd8\x1d<}:\xa4,\xc7\x9a4\xfd\xb7d\xb5lM\xa1\x07[0d\xe6\xc0\xd6\xbb0fVs(\x12\x06B\xc9\x0f\xf8\x17\x0cyFi\x90#\xb8 \xb30\x87E\x9e\xaf\xc6\xdb\xdb3? \xd7I\xf2\xc5\x9b\x87\xf9\xa2\xb8\xf6\xc2d\x1b\x15\x99\xdb\xd3$\xc8\xb6\xf1\xe3\xad) \x92)ar\x9f\xd30\xbe\xf1\xd3\xd0\x8f\xf3\x13\xac\xb2\x96:\xa6L\x1bHQ\x8e\xf5\xc4O\xe7\xd9\xe4\x92\x95\x8bi\x15\x9f?\xbd\xa9d\xdfRb\x19\xd8\x84\xa1\xeao\xc4\xea\xc0Qc\xae\xb6\"\x8a`I\xb2\xcc\x9f\x13t\xb4\xcb\x08>\x8f\x93xk)F<%7@\xe2\x9b0Mb\x14\xaf\xd2\x8f\xf1C\x1cG\x06~<\x05\x7f:\x0d)\x80\xfd\x08\x16$Z\xcd\x8a\x08n\xfd4\x0e\xe3y\xe6)n27<,d\x95oHM \xc0\xa8\xbc\x04\x85d\x14\xf6o\x04p\xe0\xa70\x89\x90\x9d\xc2\x8c\xb8\xb3\xd4_\x92\xec\"\xf9\x98\xac\xe0\x84\xceT\xf2\xc8\x8d\xd1\x87\xbe\xe3IC)]CJ\xb7\xeb\x1c\xc9\xd3\xf5Vk\x8bI\xa7x\x03\xedj\xaa\x86\xf7\x998\x03\x1a\x91\x04\xa1\x81\xf4r\xe1\x1d\xd5\xba+\xa4\xc6j.Up\xdat\xb1\x1aW)L\xf0\xd9%\x93\x94\xc6\xcd\xc8\xc0\xd887T\xe9\xdb\xbcu\xcd\xca\x9b\x932\xf2z\xdf\xa3\xdc\xb5_\xa5\x1a\xaf7\xa5\xa6\x0fi\x99\x8ee\xcdJMu2}M\xbf\xaa4\xda\x0bm\xadl\xd6{\xd7\xaaqU\xd7\xd6\x8aa\x0f\xfa\xd7\x8a\xc5;k]\x1b\x9e\xb2\xab\xa2\xae\xc2Od~\xf6u\xd5\xb7\xb6r\x8d\xb2\xcf:\x16i\x0f\xa7F\xb9\xee\xfe\x8e\x8dR\x1b\xaf\x14\x0f\x84^\xbd\xa7\x1fu\xf4\x1dq\xea\xda\x15\xe3WR\xcd\x0c\xcfIf\xe5X@\xd7\x9e0\xea\xe8\xdd\xa4(\xd5\xb9d>\xa6\xe1\x12\x0d\xfc\xfaV]\xedk\xd4\xeb\xe9P\x07\xbe\xd0l/|n\x88\xe5\xa0[\xe2P\xcf\xc4\xa7\xed?\x93O1\x970~S\x16{p\xca\x185\xb1\xbd\xb7\xebx\xec\xbd\x9e\n]\xdf\xfdWs\x8e\xe1\x04J\xc1K9'#\x0e\xd9\xbf=\x7f\xf7\xf6\xeck@V\xfcx\xc5\x97)\xf13\x9cY\xc2\x1f,\xfd\xf4\x0b\x0b\xfc\xc0n9\xe9pR%v\xa1\xe5)\xcc\xec\"\xfe\x12'\xb71\xb0g\x8e\xe5\xc0&/\x85\x95\x9c\x82\xc52\xfe\x89'\xe5)f\xe3\x99b9n\xd9\xe5U^\xa4\xe4<\xf7\x83/\x17\xa9\x8fQ\xc6\x0codk\x19)\xee\x01\xad\x10\x9fe\xb4$\x86\x0d\x14\xc4\x87\xc3\x9f\xd1.K\xe9\xcd\xca_iK|\x0b\xd6 9\xedOj\x8c\xbb\x90\xd6_\x8a\xb1\xb6\xae\xec\x1b9\x1b\x01\xce\xd3&Xc\xd0G\x0c\xc9)e\xd79 .lT\xc1\xfcq\x1e0\xe1\x07\xa3\nM\xd3\xe1(\xa1\xb4\xd6\x8e\x83\xd3%\x8884E\x91\xa0\xd3\x94*>$\xa5\xff\xc8$\xb6wv\x07\x8e\"h\x15\xbe\x83\xf8\xfe`o\x88\x96W\x07{#\xb5\\\xe5j\x82\xe5vx\xb9]\xfew\x8f\xff\xddw$w\xf1G\xecN\xf1T\xe6\xaat\xe9:b{\xd4Hu\x11r\x13\x08\xf5\xb90\x8dP\xa5\\E\x15\x103\xf5\xe6L\x14NX\x0c\xaf&\x92\xc8L\xd2-\xd1\xd3\xb61\xaaeso\x1af+\xca\xc82O\x0fo\xb5\xf032\xfdD\xe6a\x963\x05\x08Z\xeeNbs\x14\x89\xc2&\x8d\xa0\xec\x0f\xf4Y\xdc\xb4\nJ\x99\xaa\xdd\xbb\x12\xcd\x8a\xa1\xa2\x01\x8b\xf6\x05\x8b\x1c/\xbdy\xc3\xcf\xb6\xc6'\xe5\x0b\x17\xeaq\x86\x9a@\xd4\x04\xd4\x14\xe1\xfaz\xc1\x03\xa5\xfc^\x9e\xfa7$\xcd\xc8\xc5m\xf2\x91\x96\xb3\x89w\x95\xfb\xe9\x9c\xe4\xb4+.dJN\x9bf?\x02\xbd\x18}\xad\xbe\x98\xe6\x97\xd9\x99\xc8\x1dj\x14\x03!\x9e\xa3|=\xa6\xd6@\x05\xb8\x00$\xd3M7#X\xd2K3\xfaX\x1d1@]\xe6\xd1\x1c\xff\xcc\xb4H\xd1\xc8\x85\x99s)PH\x95\xf1\xb7-\xef\xce\x8f\xf5 \xa1\xfb\x9a\xafj\xcd\xc0\x1f\xb3\x84\x93o[\xc2\xd0 \xc8U\xdf\x05\xadB\x80\x16\x9a\xa9\x0bw\xa0I\xc6\x04\x1c\xae\xd3\x86\xce\xd7\x0f\x82bYD~^.\x85W\xbcM\x92u\x19pb\xf0\x83\xa8\xd5R\xb2\xad\xfa\xf3/\xe1\xea\x02;\xde\xab!U\x15nj\xe8U\x98\x92 _s\x14\xab\x9e\x95\x9f\xc59I\xdf\x12\xff\xc6\x00\xa6\xd2\xb4W\xd7R\xb5\xed\xaajlf\xcd;\xe3 ]L\xabF\x7fRO\xf1\xe97\x1f\x8d\x86\x93Q\x1fy\xaeyb\xf2\x88\xceC\xdd\xc9\xa8;I3\xc3I\x1aUI\xa6~Ws0a\xcc\xf9\x86\xc9\xd1\xacK\x8c\x04b+\xd9\xa1G\xbe\x92\xa0\xc8\xa5y{\x13\x7fH\xa7\x84\xd3\xedh\xfb\x95}$i\x86\x1b?\xb7\x193&\x13\x94\"\x0f\x91\xdd\xd8\xdd\xf5^\xf5f\x8f\x11\x81n\x0cZ+\xeb\xcd\xb9\xb3\xca\x86\xad\x95-\xfaVfy(\xe9\xf4\xae\xd2$A\x93\xaa7\xaf\xea\xf5\xd6\x17\xd2M\x03\xadH\x1e\x00\xcdF\xd8\xcb\xb3\x1b\x12\xe7\xccl\x01\xe7a\x0c\x89\xa7\x7f\xd3D\xf4\x8dr\xd9\x0b\xee\xde\xa7\xa9\x83\xbfk\x9d\xb2\xa2\xa4\xdb\xfa\x19\x06ku\xe51S@ZOw-\xfcR<\xd6\x1cD7\xdce`\xd1H\xf4I/;\x9a\xe4,\xfbh\xc4\"\x81\xfd\xfe\xe08\x93\x10#H\xe8\xeb\xc2\x94_\x8d\xf3\x81\xd9\xebd\xda0b>\x1a|z\xd3p\xfa\xb1\x1a\xbc\xeeY \x866\x00J\x84o\x0f\xa3|\xa1I\x8b\xb4=\xa3\xe4C\x9f9\x00)6\x84v1\x8b\x0b\x835XI\xfc2\n\x83/\x96>\x90B\xa3\xdcK\xc6\xe6\xf6(\xfe*)\xae#\xd2\xb7r\xa9t\xff&\xde%EF^%\xb7\xf1:e\xd7\xac\xfe]r\xb3V\xd95\xab\xff\xbc\xea_\xb2\xbbj\x90\xf4t\xf6\x06\x92\x8a\xfeu\xc4\x12\xbcbT\xc0\xdc\x05\xeb\xba\xc8s\xb6Cy2H+\x8cWE.?\xc8\xd0\x14K~\x92\x93\xaf\xb9\x9f\x12\x9f?sZ\xbc\xa8[#s\x88K\xf4\xb2\xe98\x05\xa0\xea \xc4\x85\x87s\xe3\xcd\x03\xb3\xceV]'DDJ\xf59\x8bY\xed\xc8b:=\xeeH\x8dx\xa8T\xf2SZ~\x92^\xb6a\x00\x96/\xe8\x11H`=\xb4\xc5\xf9\x8a\xdb0\x8a^\xd5Z4=g\xed\x9bG\xae\xc7AX\x1dO\x81\x94N(tz\x0c\xfey\x14\x95lC\x17\xd5)\x98<=\xe0\xeby\xbc\x15\x12[\\\x14O6\xfcpc\xb4\x82\x89&\xf1\xe5$\xbflC\x8ab\xfcf\xf0\xeb\xc4\x06\xe2B\xf8\xa4\x86i\xd0=\xb7\xb9\xa1<\x87)\xef`\x8f=\xf1\xa0J\x90\xf2\xd4\xe7\xc7{\x7f\xca\xbb\x84g\xe8\xf2\xa3r\xc5H\x83\x9a\xfd\xa1\xdff\x7f(.a\x87\xe8O2\x03|p^\xba@O \xda\xc8\xab\x8dF\x1e\x83\x19\xf2\xccv8D.7\xa4\\\x91~q4\x11K\xf3 \xdf\xdea+\xbc\x99\xebU\x13\xdefR;\xc0\xbe\x05\x1a.X!\xba\xd2$ Y\x86U\xffo\xdaHW\xf5b\xcf\x04M\xe8\x94\xfc\x01d\x88%\xe1\x14V0\x86\xa9\xe32\x80Q\xaa\x0c\x93\xb1\xfa^JP\xd5\xfd\xd2/\xe6\x8b\x9c\xe9\xc2[\xbbyu\xb5*\xd29\xe90\x81\x89*S\x0fc=\x12\x91\xf4\xc2\x8f\xbf\xf4\xcb\x8f\x1d\xd5\xeb,\xef\x0c,!\x0b\x01\xf0\x8d,a#\x85\x97` \xd5$A\xfa\xe8:7!\xb9\xed\x9aK(\x83\xe9\xd1\xd2U\xd0n\xbc\xd5\xaf~1\xfd\x89\x16e\x82\xf0\x99\xf4n\xc3x\x9a\xdc2\xcb\x81\xb2b\x8d\x87%H\x87P\xeea\xe2\x85W\xdcKM_\xb8<\x0eO!\x16!o\x7f\n\xc9-\xc6t\xe5\xfe'?\xb3\xc6\xc7\xc0z\xd1\xdc\x85MffJr?\x8c\xfa\x00\xac\x04\x12\xfb\x84\xb6\xdb\x199\xbb5B\xa6\x0b\x89\xda\x16oCRZIy@\x1bf\xa3\xf8\x85\xe7\x17s\n5\xcc\xa3e\xfb\xcc\x0bT^\x94\xfe\xb7/J\xb5\x93\xcb\xe4\xa6\x13_\x10\xcc\xa7\x1e\xe4o\xe2\x9c\xa4\xb1\x1f \x01\x1d\xdd&\xa8El\xdb\xae=\xc4R\xe5t\xe8\x9bi\xab}\xe1w\"\xd3\xbaF\x9e{\xff\xae\xdd\x90\x92\xbe\xde$#1C\xcah\xd7\xac\xc7?\xbdTS8\xa9\xd5\xf7\xdb?nH\x8d\xbcLVwi8_\xe4`\x07\x0e\x8c\x06\xc3}\xf872\x85\x9f\xfd\xdcT\xec\xefdz\xcb\xea\xabl\xc5\x02\xbaz\xd1E\xb0,\xff\xe3\xf6\xffQ}\xdc0\x1f(\xfa\xcd\x05u\xab\xd6:)\xa9D\xbd,\x91G3t\x02\xc8\x14\x16\xe1\xd9\xbe\xa5\x10\x17\xcdh\x95-\xe1,\xc4\x86\xafl\xeat\xf49plo\xcc\x9f\x0c\x92\x90\x85\xcbaR3Q\xa5$\x958\x81P1Y8\x81\xd0\x01\xc2\x9c\xfe\xda\xa8\xb32}L\xddb+u\xca\xaf\x13\xcf_\xad\xa2;\x9eP\xa9\x95\xbf,+\xaby\xc3\x86z\x82O\\\xe5D`F\xa0\xd4\x11\xc6\xc6\xa9\xc8\xcb\x93rG\x17\xde\x1f\xff\x9b\xe9G\xc2\xf2\xceZ\xd0\x1aKR\xc6c\xacy\x814\xeai0\x92\xd2\x85\x0eGk\xd7\xb4\xa2-x\xb2\x9e\x9e\xfa\x81C9\xc7\xd8\xb4(\xcb\xade\xf7\x95T\x9e\x0f\xf6zV\xc8\xdc.\xb8\x0f\x8a\xe3\x9e\x1b:\xd5\xf3?\x81A\xaf\xda]\x16*\xbc\xde\x9a\xe8i\xea\xc7\xd3diw\xfan\x18\xbak1\xf36\xdb\xf2\x82$\x0e\xfc\xdc\xae\x85\xc4\xc74\xc6cJeX\xce\x95\xe5\x82\xbd\xb9\x19\xc3&\xa4Ne\x0e\xb1\xb3\xff\xf8\xe43\x8dh\x06<\xb5e\xe39Sp\xec6\xe6\xcb\x07\x83\xd5|\x05\x8d\xdcc\xd9o\x87\x83\x81\x03\xa7\xfa\xd2\xd0-ZF\x94V\x06Y\x0d\xe9\xf2\xdd\x188.\xa46\xe5\x9d\x13\xa7\xdd\xd0\xdd\x14\x8c\\\xb6v\x7fh\xb4g\xcdInQ\\\xc1\xacW2q\xd7t\xfc\xb2\x9e\x07\x94aKR%\xdc\xb4\xc9\xf3\xcbBw\x0c^7\xe5\x0cE\xb2i\x0f_P\"\xf1\x11KTsP\x89\"\xeb\x9a\x17\xc7e\xce\x88F\\\x9f>=\xc1\x9d\x11\x9002l\x9aY\x94$iW\xef\x0c]\x0b\xb3\xf7\xfe{\xf4\x81\xd9\xc44\n\x03\xe6\x12\xc3v}\nc\x88\xd7O\xe8!\xe1\xa4Q\xaf\x87J\xe3>\xc3\x99\xa6\x91\x1b\xb4\xc4qn\xf4\xc1 \\R\xcaK\xddh\x98\xd6\x88\xcb\xd4\x93\x9d\xfe=\xd1\xb0n\x9aO\xea\x9d\xa91p\xf2\xa5\xf0\x8c\xba\x05\xd9\xe7\x0c&\xd5\xa9[\x92ofC\x08X\xe3\xd05\xef\x97\x7f\xa0\xe7\xaa\xd9Gr_\x9f\xc8b\xcf\xe4\xc3\xd9\x89\x0eR;Y?\xffZ\x97\x98gO/\xe69\xd0Iy\x98\x87Y\xf3\\\xc4A\xd5\x1f3\xbd\xff\xb0;\xc7\x9e\xd9\x14.cF<\x1ao[\x96\x94\xdeGk%\xcb\x82 \xb9\xd4\xb9\xf7\xa2\\\x7f`\xf0\x06\x8f\x1a\x11\xd8C\xb3\xe7\x1cH\x82']8`!^\x9ad\x97]\x84\xaaT\\\xe3%\xe72\xef<6\xa6f\x02\x0ds\xc21X\x1f,\xd8\x84\xcdMM\xf2oq\xddj\x93l@\xe3\xdc\xc1'\xad\x92\xf9\x99H\xeb\xa2\x8dfB\xaf\x7f?\xfb\xdb\x184\xf6#\xef\xcf\xce^\xe9\xd3\x17\xce\xfc,\xffw\xa2\x86\x873mg\xcc\x1a\x90\xc8A5\xb5n\x0b\xcc[]\x9f\xb6\xf2\x14\xacs\xca\xfdX\x1f\xd1X\x9f\x98e\x1d\x1b!NOk\x04a,\x97\xd5:\xf4\xdaj\x97{lT\xd4\x9bu\xd6R6P]_\xc4\xa5\x9fLq\x86N\xd2K/lNl\x13\xf2s\x92\xffL\xfc/\xeb@\xfeQ\x00\xd90\x84H\x84&<6\x86\x7f\x088zi\x05\x92\xf8uJ\xc8o\x9dBn\xa8*\x8f\xd0\x1e\xd4\xa3\x8b\x9b\xfe\xc2\xd8vO\x9e\x80\x00\x13\xfd\x1d\xd8u\xb6K\\:\x02\xb0\x8d6c\xfc\xee\xef\x0fe\xb8\xe77\xd9Y\x19yC\xfb\xf5Z\xb4\xc9\xef\xdf\"]\xd6W\xadw{\xcf]\xb0\xaa\xc8F\x0d\xf7w\x8e\xf2\xe4xG\x947\xf7^\xbe={\xfe\xe9\xea\xc5\xdfPs\x847\xf8\xeb\xfd\xd9\xcfW\xcf?_\xfc\xf5\xea\xecS\xf5\xe0\xfc\xe3\xd9K\xfa\xe0\xea\xc5\xf3\x8b\x97\x7fm<.\x1f\\\xfc\xf5\xd3\x87\x9f\xdfkJV/J\xc5\x05\xedCLn/(}\x1b\x9f\xa5\xed\x9eg|u4\x97\x0e\xc5A\xda\xa8\xcd+\xff.J\xfc\xe9\xb8%\x83$\xd4\x89y\xb5C\x18/\xf3[z\xa59@\xca^\x91\x8e^\x9c\xafH\xf0\x8d@\xc9\xbe\xbd\xf9o\x06\x81&\xbe^\xef>\xbf\xba\xa6;\xd7j2\x01\x0d\xc4]~\x9c\xadH\xa0i92\x1f\x02\x8dO\xb5\xad\x06\xbac\xa5\xfc\xd4/\xf2\x85\xa6\xd5Y\xedT\xc2\xd2\xb8\x80\x95b\xab\xaa\x18;\xc9\xaa\x92W\xd7w\xcc-\xb37_\xb6\xaf2X\\\xc6\xaeK\xdcY\xba?3\xa5\xc0\xe5\xda\xe1C\xdaH\xed\xfb{\xb4\x0fa6?\xc4\xa1\xef*\xeasMfs\x7f\xc7\xe1\xec\x96\x0b\x16s?5E\xaf\xeaE\x98H5\x0f\xf4\xee\x88\xfb\x0d\x19\x0bO\xf7?\xd03\xb0\xfb\x03\xbd\xf0e\x7f\xb0\xdb7\xdc\xb1\x10nli\x98\xa1\x98[U\x01W\xd3\x0c0\xe6\x16W\xe2\xd6\xd7\\\x92r?c\\@\xb6s\x04\x9b\x9b9\x1cCl\x0c\xb3\x99\x1a3\\3\xafa\x92\xdb)f\xcfK'\xc3\xcbv)\"\xbd2\xd9\x0b\x98\x9f@\xa9[{\xccm\x0fO \xa9?\x9f\x13\x96\xfc\xaa\xf6p\xe1\xa3\xe5J\xfda\x86%\x8b\xbauK\xb6\xde\xdc\x0f\x07{}$c*\xd8$\x93\xd0\x13)_x\xbc\xb5u\xd4\xe4C\xb8\x94~\x12_\xb2\xfc\x83\x92\x19\xb0\xf6\xac\xd8\x1a>z\x8f\x0c\xba\x93\xd1kFS\x0d\xe4\xeaj\xea\xe7\xfe\xd5\x95\xb6_\xa9\x9d;p\n\xf1D\xc3:\xe7\x94u\x16\x8f\xc7`-\xfcla\xd1\x134\xf6\x96\xfe\xea\xd1\xe31\xb8C\xed7\xe2\xf2\x89\xf0v\x06w\xa8]\xfd\xc6\xec\x11\n\xd7\x84\xeeD \x9dlA\xde\xa5!\x85\x86.:\xc6)\xf86*\x93\x12\x9b\xe0\xba tg\x89T\xddc\x94\xb8v\xc0M\xee\xdbZ\xbd'\xde-\xb9^\xf9\xc1\x97\x8fIt7\x0b\xa3\x88\xab\xe4\xa7d\x95\x92\xa0\x99\x17\x14=\xdeW~\xbe\xc8\xb8=I\x15z\x99\x7fY\xde\x9e\xb0\xf4\xb3z\x06\x8f\xb8`\xb1dM\xda\xd8f\xb5p\x91\x9a\xf0tk\xc5>#^\xd4x\xad0\xd6\xad\xfd\x0c\xffG\xfa\xa8\x11\xc64\xfa\xd8\x9c\xad\x13\x18>R_\xab\x9a&\xd4\x07@w\xdd\xf6\x7f\xda\xa7\xe3\xc1\xfdd\xb8\xf5\xf4\xf2\x97\xe9\x8f\xce\x9f\xb7\xbb\xb6\x88\x01\xa3$\x95\xb1\x8f>\xef\xfb\xc6\x86\xfd\xff\xb3\xf7\xef}q\xe3\xc8\xe20\xfe\xff\xbe\x8a\xc2\xe7\x9c\xac=\x18\x03I&\x97\xce\xb0,\x03\x9d\x1d\xce\x06\xc8\x0f\xc8\xcc\xce\xaf\xc3\x971\xb6\xba\xdb\x1b\xb7\xddk\xab\x9b\xb0\x9b<\xaf\xfd\xf9\xa8$\xd9\xb2,\xd9\x86\xb0{.\xcf\xd7\x7f@[\xd6]\xa5RU\xa9.T9\xd3\x18\n\xc9`\xc4*{\xf2\x04\\\xd5EI\xde\xf0A\xb2\xb1\xc7M\x87\x0b\x1e]\x80xX\x80\xc0\x1f`k\x97\xff\xfa\x0f\xf4e\xcfi}\x8c\xc5\xfb\x80\x99\xd2]L\xf5\xcd\x82\xed(\x17\xfa5\x8a\xe9\xa2\xf9z\x8b+\xd8\x18\xf1\n\x86\x03P\xba\x82*\xae}\xc8\xa1\x83\x90\xd2\xb1\xa1`\x1f^Y\xc8\x9dg\xfa\xfd\x99 w\x9e\xe9\x0e\xc6\x05V}\xa6\xd3\x99\xa5\x99*M\xc5%\x81^\x0d^\x18\xb9\x85\xd7&\xa4S7\xf7\xdats\xea&Zj\x8c\xa9\xa1\x96:\xc7\xd4\x95\x96\x8a\xe1\xdd\xea%q\xb9\xe1\x91\xe2m(\xfc9!\xb7W\x08vk\x97\xbb\xe3`\x7fQ\x97\x8c\xbb\xacqw=\xae\xd5\x947\xca\x9e\x84K\xb5X\xee\xf1\xd01j\x96\xf7E\xbeHJ\"\xb3%\x01\x0f*N\\^_\xd8\xc8|A\xa8Z_\x88YV\x8d,\xbf\x90\xf0\x93\xd6\xec\x8ao\x0fw=\x08ZK\xe3=_\xa62\n|c\\9r\xcf6\xfd\xbc\xd8\x9d\x8b\"\xf4\xc1>\xa4n\xc6\xdd\xdbh\xd7~\\\x81P*)\x18/\xf7\xf1Z>\xea\xbc\x967\xac\\\x9b\xa6\xc5z\xa6\xc3\xea\xc1\xe9\xb4T\xb1\x1cVE\xb5\xca\x96j\xe2a\xd5\xe0\xfa[\xaa\x98\x0f\xab\xa2\x82\x8fFn\xa3\x8a\x81\x8235\x05\xf2AV\x0d\n\x89\xfd\xecu/\x95e\xbf|\xce5\xaeG\x88nF`\xb4%\x13}W\xb4arq\xaa\xf49F\xb4v\xbf%T\xe1\xd8\xf2\xd5\xce\x90Au\xf2\x0d;\xdc\xb9>\x1e\x82\xe8[\x97x^\xcdJ\xc8x0l\xf3f\xf0\x03$o<\x94i\x91I\xee\xd2I\xb6\xb9y\xe5]\x19\x07\xcf\x8d\xf2\x90\xd7\x16\xf4\xa8\xa6_?h\x02\xccr\xfb\xfaZ\xb45\xb4\x0d\x1a\xacIQ&\xdc\xef\x92PE\x92IA\x92\xc5\xe4\xf3\xd9\xd4u\xd6;\x81\xe3u\xe7\xd8e9\x9e<\x11\x02:s\x8eW,\xcf~\xcf\x85cF>\xd3\xcb$\xd2n\xb1z\xf4u\xfaUX\x18V\xad\xd5X~\xefDa\x9a\xde\x84\xd1'\xa7\x92\x1eb\xf8Y\xb8!\x8aZ\xcb\xef-\xaa\xc5ka\x07\xc7c(\xb4\x94\xb3\x8de$\x8e4\x06F\x92\x0f\xa2\x85\x9d\x1e+_\x8b\xc2\x97|$*\x08\xe4LZ\x8d}\xa0G}K>\xed\x1a{ie\xf5\x11\x1aT\\]\xdb\xa2X&\x1f=\x10\x89\xfat\xe9w\xc9\xe7Q\xbbjU>\x93Ooo\x9f\xffk{k\xd5N\x93OW\x87\x07\xd9b#.D\x12SRS\xee\n\xb6\x90\xb3 \xb9\xb9B\xc8\xd0\x9e\xdc \x1e$\x93ps\xf3\xaaa\x8d\x10\xf6D\xe5\xfd\xe6YQ\xcd\x03zt\xfd\xbf\x0e\xbd\x81\xd68<\x14\xe3\xd5hL=wU\x07\x89\xdf{f\xcdx\xbb\xa6\xb5\x89\xcc/\x84\x97E\x93<2\xe9;\xb2\x92\x0c\x91\xe0$\xbb\xc2s(S\xfc\xc2u\xd9\xb5Y\x84\x10y\xf5]\xa9F\xfe\xca\x83i\x91/\x00\x9d\x83\x85i\x9aG\xca\xcf\x0fY\x19NI+\xe1\"\xcdo\xb5#\x81\x91\xa3n\xe2\x16\xdc\xa7\x0c\x0d*w\x94\xa1\xe7C\xe2\xe6<~b\xc8\xdb\xea\xa7G\xf0h0x\xce4\x1f\x0c\xceA\xe34\xc8rq\"\x88\n\xcc\x94\x8biRX\x0f\xf9\x1c\xdc\xb3\x8b\xbdg\x97\xd6\xc5\x8e\xeeI\xb0j\x9b{6I\xae\x0d\xc1\x14\x98\xc2\x05\xc2>\x14\xc14\x91Z\xc1\x8c\x86\x13\xaf\xcaoT\xb07\x8c],z\xaf\xf2\xe9?a\xec\xf5\xd2\x98\x16E\x01\xbe\xff\xc2\xce\x15\x01\xeb\x81`G{\x05\x87\x83h=u#e\xee\x8b\x97\xdf{\xae3\xcd\x8bq\x18\xcd\x9dA\xa8\xa8O\xe3\xf5\xd9\xaeY\x10\xf1\xcc\xe2\x06r\xf7\xb5.)\x10\x82\x88W\xaa\x18\xd7\x1dL\x8c#R\xc3\xf8$+T\xcfL\x8d3\xdb\xbaC\xfe\x01\x9e6\\\xe5n4\x84\xban)\x9c\xc3r\x97\xb1D\xb0/\x0c\xc2\xcb\xc6\xd1\xf5T\x04\x8c\x94\x8c\x0dFO[\xa1I\x13\xe7\x0b6\xd0n\x08\x93\xc3J\x7f\xd3\x89\x1c\x11\x93KI#2\x04\x97\x92v\xebx\x9e\xcf\x0d\xe1\x1b\xa3\x82Z\x91\xc6\xe0\xc6\xb0\x19\x96%kgP\xc5\x9fI\xfbs\x1d\xa2G\x8fK\x0c%\xdb\xfen\xee\x96\xac[ld\xb5x\xf6\xab\x17\xcc\x86\xf2\x83b\xa9|\xdd\xef@u\x0di^\x15\x945\xf1@\x06\xe6\xc5I\x1b\x8b\xf3LY\x1c\x86\xceh\xa5\xec\x03#H\xc4=\x88\xf8\x8e\x16\xe8\xcd\xef\x19\xb7qS\x1a\xe5\x1fqA\xd3\xba\x0f\xca\x17\x0d\x18$ \x945 \xac\x0c\x80P\xb6\x00\x01},\x98\x16\x1d\x05\xd3\x86%G\x9bd\xc3J7A\xc1\xa0\x01\xa4\x82B\xa9\xafv*V;\xf5D\x0c\xbd\xe8~(\xa9\xc6\x12\xadp\xb9\x02I<5_\x01={f2\x18\xcb\\\x8b\xb0rwW\x17nrt\xb7\xfbB\xc7M\xdc\xa7D[R\xa9\xaa\xbd\xb8TS\x82\xd5\x87\x88\xbe\x05\x97&\xb8\x8e}\x98\xfb\xb0\xf6a\xe1\xc3\x0c\xf6`\xa9\xaa\x89\xdbhU);n}dD\xa5Y\x94w\x87\xc2\x06\xde\x11\x06\xd9Oa\x04:\xbae\xcf\x0d\x92\xe0\xcd \xb6q\xc6\xb3\x1e\xe3\x8e\x84r8i\x99v\xb0\x1a\x13wf\xd4\x19E\xba3\xe6\xa6\x072F\xef\x1b\x88\xe1\x0fp\xf3\x06n67\xcd\xd46\xab\xd1]\x08G\xacwn\xe8\xce\x91T\xbd\xb9\xf2\xf0\x8em.\xee\xd8\xee\\L\xf3P\x06\x81\xb7_\x0b\x1e\x0b\xb2\xba\x9a]4!\x1a\xcd\x7f\xcd}\\\xc3\x1eTq'\xde\xc0\x066\xb9F\x8e\xc3\xf5\xbc \xce3b\xb8\x14\x06\xb5\xb3\xb9\xbb\xf6\xe1\xce\x879\xb7\xc5\xe3w\xc4\x03\xba\xf6\xd5\x0b~<\x1f\x1f\xfc\x99\xc7j\xa5\xc1\xf9\xf8\xf2\xc3\xf9)\xec\x89\xdd\xf6\x8d\xe7\xb3\xd5'u\x11\x1c\x8d\xdf\x1e|xw \xfd\xfe\xa9ww^\xf5\xf8\x9d~)\xfcL\xbf\x12\xff_\xdf\xdb\xdf\xb4BR<\xb7\xdcm\xec\xe8\xdb<1\\\xf1\xdc\xdf\x94\xd1rH\x85Fm\x8aD1pD\xee\xc5\x0d\xb1\x18\xddd\x83\x00\xad6a&\x1f\xec\x96\xd6+W\xa8\x869O_\xeaGCU\xcchc]}\xb5-\xdc\x0e\xa7}\xd9\x7f\xdep\x05\xa7\x07\x82\xc9\x8cxp\xf8\xda \xb39FQ\xde\xe2(\x10\xa6I\x16\xa6ig\xd7:;\x0eP\xb9&\xeb\xcf\x08r\xa4Q\x9a\x97b\x00\x9d\x05\x9aF\xe6\xdcu\xc5\xe0\n\x86\x0c\x0e\xba\xe6\xde\x93\xa8\x15{\x1a@\xba\xd2\xb0\xd9)\x81d-\xb0\x11s\x03a\xdbu\x8b|V\xed\xab\x05\x90\xd8\x81\xfb\x83GM?\xae\xff\x93U\xbcNh\xe7u*\xcffA$\xa0\xf8\x80\xbaa\xa7+\n\xae\x01\xd6\xa3T\xc5\x88,\xe7\xc9\xdfV9}\xd3\xe1\x8b\x83=7\x05 ?\xd9\xb3\xf0\xd6^\x0di-\\,\x1f\xa5\xb1\xd7C\x1a\xfb\xb7\xcfO_>Fk/:\x14\x0d\xa1j-}\x94i|\xd1\xa3b\xc8\xdb\x9a}k[\x83t\xd8\xa2<\xa3I\xb6j\xdf\x0c\x81\x95\xc5\xe3|0j\xf6\xbb l2\xfcX\xaen\xf8\xb5\xb5\xbb\xf2!\xf4\xe4e>\xe3@\x19+\xbc\xa9#:s\xe5b\xaf\xca\xfa\xf7Y\xc9v\xe50\xd2C\x0c<\x92\xbaH\x83\xea2\xfa\xa67\x851\x0b\x852\xb5\xd9@\xaf\xcd\\\x96\"\xbf\xce@ [\x92\x96FId\xb8\xb5\x9d\xa2p\xa1\x99\xb6l\xa3\xabvx>\xf6\xd0|yp\x93\x17t\x04N\xc8\xfe\x1b\xd0\x1f\xcb\x92%\x0b\x0c\xe11\xce\xe2\x11\x94\xae\x13\xca\x04\x92\xc5\\\xff\xb9\x99\xd4]\xcb1%<\"H\xb3\xaeD&\xeb5\xd6\x1f\xba\xeb\xbd\xa0!\x1b\x89Zg\xc9\x92\xf4\xfax\xa2\xb1\xae\x1f\xd3U1\x02\xe7&]\xe9&\xed\"\xc3a\x98\xbdO\xc3\xbb\x118Q\x98-\xd3\xf0\xae3\xdb\xe5\xbc\xc8W\xb3y\x9d\x9b\xf2\x04K\xa1y\x98\xcd\x08\xcb\x8c?,\x99RT\x01w\"\x8c e\xce\x92/\x96y\x99T\x0b\xe6Du\x82uu\x94Bb\x1e\xd5b\x1dS\xa6\x14\xfc\xb0\x8cQ&\xa0\x96\\a\x9a\xadhF\xc9gzB\xb2\x15\x16\xc2\xb7\x05\xc9V\xb6\xecK\x9c\xf8|i\x9b\xf5\x15v{e\xe9\xa9\x12\x1ek\x04N|\x93v\xcc\xe1Q\x11\xceX\xa6\"\x9c\xd93\xf0\xd9ey\xac\xd3\xca\xb3QRT\x19)\xb1\x80\x16f\xfd\x9cP\x99\xf3sb\x1bG\x11\xce0\xc0\xa3\xc8\x99\xb2\xdf\xf6\xacg\xeb\xaa\xf5|\xdd\xd5\xb8\\w\x96\xb3c\xc1\x8f\x8a|\x89\xb9\xf2\xa5%\xc3\x8ao\xd7\n\x9ec\x91\xd0\x05\xd7\xe3\xc5\x92&\x84\xcd'\xe1\xbf,\xd9\xb2\xa8\xb8[R\x9eQ\xfe\xb6e\x8dE\xb6\xd8\x9a\xa5(r67\x84\xfd7gy\x9bG\xabr\x04\xce\x94\xfd7g9\xce\x96\x08x<\x02\x981\xcb\x9f\xc9\xddQ~\x9b\x8d\xc0\xf9D\xee\xe2\xfc\xd6\x82\xca\xfeL\xee\xde\x17\xa4,y\xbe%\xfbi\xcd\xf8a\xc9s\xad,\xab\xf0\x0e-\x93\x19\x0f2\x92f\xca\x8cs\xe9\xca|Bh\x18\xab\x05\x16\"\xc1^H\xc2\x0c\xcb\xdf\x013U\xe0\xb8\x118\x0b\xf6\xdb>\x07U\x108\x99\x95qW\x1dY\xcfp\xee1gn\x9b~\x9e\x91\xef\x03\x9e\xd3\xba\x11D\x988\x99\xd16\xbb\xef\xc3\x121\xdd\x92\xfd\xb7eY\x95<\xcb\xaa\xb4e\xe1G\x89\xfd\x1ca\x19\x92l&\xf2$\x99\x05\x19\xbd/\xf2\x99\x80\x9b\xa5\xf8i\xcex\x1eRRm\xcb\"\xa4\xa4kKr \xdb\x08\x9c\x12\x7fX2\x11\xf2 \xb7Y\x89?\xec\x99\xf80J\xfe\xcb\x96-\xe5\x91=\xab.\x962\xa5\xb3\x9f4LS\xde\x07\xfe\xcb\x92mU. b\xec\x92\xff2g\xbb$\x9f\xa9\xdc\xd1T\xfe\xb6dM\x16\xa4:\xf3h\xb2 ]\x87\xdde\xbe\x8a\xe6\x87a\x16\x116\xa5\x94\xbdE\xf8\xd6\x91\x9d\x1f0\x98\xd7\xde_\xf6U\xec\x17\xcci\xdf/\x98U\xeeX\xcc\xdb\xb1e\xf1\xda/Q\xa9>Z\xa5\xd4d_3\xcdX\xd1\xcfy\xbaZ\xd4P\xb7\xc6\xd7\xae\xf5\xfc%L(\x87\x96[\xfe\xcb\x92mNp*o\xd9\x7f\xcd\x04\xb4Y`\xcex(\x1e\x85\xa6\n\xa2w|\xe4\xc0\xa6\x90\x18\xb9\x8d8\x04^P\xa6ID\xdc\xa7^\x93\x1dX\xa3j\xdb?\xbe\xa2VE\x93\x94>'2\xd2Z\x1d\xa4\xb0}\x990 p\xad\xa9\xa2~\xf99:\x8f\xf9)\xcc\xe2\x94\\\xe6\xcbwdMRw\x1d\xcc\x1b \x9e\x0f\xeb\xa0]=\xec\xf5{ll\x8e\xa2$t\x9ca@\xcc\xbe\xae\x19\xdb{\xf2\xc4\x98\x1e\xd4\xd5\xb6\\\x01j\xb3X\xb6\x9b7\xb5.5\x88\xdc\x0dc?\xbe|\x01\xe3\x87\xa0\xaa\xdf\xed\x0e1\x97b\x81\xcb|\x80S\xd1\x86\xa4\x98\xfa\xd0\xed;O>b\x00=j}\x95\x16\xde\\D\"\x99\xcc\xaf`\x0f\x96\x9b\x9b>D\x13\xf6&\x82\xfcV\xaf\xed\xe5\xe6\x11 `\x0f\x92V\xc0\xc6#\xc20%\xc9\xa2\x84\x94\x13r\xd50f\xcb\x87\x08\xb3P\xcb\x9d\xed\x1c\xabu[\xa1\xc7\x99\\\x89X2+\x1e\xa7\xd8\x91{\x9d\xcb\x86Wht/v\xbd\x07\xfbfp\xa2E\xb8\xfcqu\xc3\xd6\x11?(\xb5\xf8\x12e\x08\xb3\x9d\xd4\xe5G\xfd7\xd5\xa8\xd4 \xaa}@%Gg'H~\\\x88\xf3\x96W\xe4TGqc\x02\xe4\xa1\x0c\x1b;\x9d}\x16\x01o\x95\xf6\xaa\xea\xeb:\xee\xd9cC\x0d\xc6\xc2\xbf\x1c\x9f\x1e\x9d\xfdr\xfd\xd3\xc1\xe9\xd1\xbb\xb1\x1c\x0bR\xd4r(x\x86p\xbe\xbb\x1e\x9d\x9b\xba\x92\xde\x16\xa3s\xef1\xbc\xb7\xa2dUEf\xc1}\x96\xf2\xd8\x17_\n\x01 \xf3\x04\x90`uI\xe6\x08\x15\xd7\xc1\x93\xd5\xecO\x92\xf5\xf5\xa8U\x81\xec\x10\x96G\x1a\x97u\xca\x87\"\x10\x1f\x85N\n\xbeck\x98\xc0\xba\x1d\x9b\xf7\xd6\xb0\xb6W>\xc4\x93\xd5\x15\xef.n\xc7\xbdVHy\xe8;.\xf4Z\xfb\x03\xd5\x80b\x867\xa8\x9f-\x85bK7\x1aK\xfd8\xfdhB\xcf\x90\x8e\x88\xc86<4\xe9\xfbpF\xfe\xf2k\xcfA\x86\xb7\x17\xfa\xad\x1e+\xdd\xe9Kz-\x9c\x86\x9a\n\xba\x0e\xa2\x19\xfcm\xd2\xe3\x92\xf7$\xaa\xd3\x06UQ\xa0k|$+W\x85\xc0`?\x87\xe9\x8a\x9c\xe4YB\xf3\x02 \xba\xdeq*\xae.\x90T\xc0K\xdcu`\x984\x97\xed\x80\x0d\xcc\xb41\xed:|\xd8$\xac\x82\x82L\x0bR\xce\x95~\x95\x96\xfb@\xd3R/\xf8\x18\x94\xd2\xe8\xebzZ\x87\xecR\x1fm?To_-\x06\x08\x83<\x904\xc5\xd4Ur\xa5\xd1P\xb4\xe6\x94k\xb4^\x17\xab\x94\x94\xd7\xd7\x0d\xdd\xf0\xeb(\x8c\xe6\x04\x13-\xd7\x8b\x85Bp\\_O\x93,\xc6\xdcv\xaa\xa5\xad\xf7W5-\xc8\x04~\x8d\xb7\xb5\xfb\x06\xa8\xd5\xb1`\xb3\xe0ds3\xbbB\x85\x01\xae*s\x0fO\x83\xbe6\x82(_,\x93\x944\x07a\xbaB'\xa2\xfb\x06\x96\x83M\xa1\xe3hT\x0cQ\xc6)\xecI\xddn\xda\x8e\x04\x84\x13\x98\xfc~\xe3\xf5\x18\x07\xa8\x95\xa2\xae\xfe?\xd0\x07q\xaby[ OY\x92\xc7\xda\xe2\xae\xf3:\x86oD\xa9\xec\xc9\xd4)p\xd1!X\x86\x13!\x07G\xf9\xe0\xbe|\xd1Z\xe5#\xcd\x82if\x88M\xdd\x1a\xad\x0d\x1cB:\xd0\xf2\xa5\xa8a\x99o\x01\xa3\x11\x1a^\x12\xb1\xbe\xea>\xa3\x19Doq\xb5\x81B\xb5\x8c\x16V\xd1\xef\xc3\xa2$\x05\xb0\xe9C\xc3\xb2i\xbeB~\x1f6A7K\xd7\xf6Eq\x15L\xa5\xf1g\xebK\x98b$c\xfc\xff\xe5\xcb\x90]\xdf\x9c\x9d\x1b2\xcd\x0bb4\xf7k\xb9\xb1ZK\xcfx\xbd\x93\x94Hm\x9c\x8eI\xca\x1fs\x92\x82r\x89l|\xee\xc3\x8e\xc9\xf5!C+F\x13R\"\xd9K\x93C\xc4if4/\x0dS:\x82\xa4\x9e\xf2\xd6\xb6\xbb\xd7\n\x84SJ\x8a\xff=\x0b\xc0o~\xff\xa7-\x02\xc34\xf7@\x13F\x04\xa0M\x08\"/\xdb$\x18T[z'\xc10q8 \xc5cM\x02\xefA\x9f\xf2\x17\xcb\xd0\x0cJ\x8b\xae` \x8c\x00e\x06\xdc\xe3cs.\x86\x1dy\xf5Y\xd9\xd2\xa0\xe7\x87\xd9\xb0j4\xba\xa4\xda%fU!\xca\xce\x1e\xc3N8g]\x87E\x98\x853R\x8c \xc9\xd6a\x9a\xc4bg0\"\xc5\xb4'\xa0\x8d\xbd\xe9\x95:*=\x84\x13\xe6\xbe\xef:\xc5I\xd9Z(}\"\xdc\xeee\xf2\xfe\x17\xcc\xe5\xeec\xcc\xe5\x8cP\xde\xbb\x01jo\xc2\xcb\xc1\x9e\xdeB\x0d\xef\x15\xe1\xe9\xb6\xfa1!W\xda\x1e\xfd\xea\xdf\xdf\xf3{\xbf\xbb\x93\xce\xbd\xbb\xe6nC\nn1hq\xd6\x8e\x16\xc0\xc12/O\xc2\xcf\xed\xaf+\xf9\xb5\xfd\xa9\xc4OIy\x9c\xbd\x0boH\xda>x\x94\x8f^M\xc7\x9b\xf2\xa5,\xcf\x87l\x11\xd2hN\xe2\x8b(_\x92\xb2\x8e\x0dj\xfc\xbc\xb5\xe5\xb7*C>\x05{\x8bf\xf5x4)\x9d\x10\xa2\x14F\\\xed\xbe\xe1\xa3\x82\x1f 4z\x9ag\xfdz\xcd\x0fN7\x07\xa1\xca\xaf\xea\xecaq\xcf\xf3 \xdb\xdclCr\x15\x82\xfb\xf53\xe1\xdb\x11\xbd\x04\xb2\x9f[[V\xd2\x99\x0b{\xcc\xbc+\xea\x80\xb5\xbe\xb4u\xabP)\xb7$EP~J\x96\x97\xf9'\x92\xd9\xc3\xef\x80\xa2\x11\x0f\xfb\xdc\xc5\x19_l\xcb\xa4\xc3\x1e\xf7\x0cb\xfd\x9a\xc1\x16\x9ft\xbe\x06+}\xfeK\xff\xe1a\x15^\xdb\xa2`r)\xba\xeb\xfc\xdd\xf1\x8cq\xa5\\%\xb6r\xa7V\xaa\xd4w\xbd\xa8=B\x15\x02\x8f\"\xc1C]\xc7a\xc3\x17\x0d\xf6j\xa3\xa9\xf5\x0f\xd3\xb8m\xc8IL\xa1H\x9d\xc30\xfb=\x85(LSX\x10:\xcfc\xc830b\xd4\x96\xcb\x8d{\xcew+&\xa20S\xd8\xf5\x02)x\xd2no\xd0a\x87\x08\xe0\xe2\xe6M%\xf5^\x1f\xa4\x96\xc5H`\x1f\xb4\xaa\\\xf4:\xaf\xd8\xb1\xdd\x7f`}\x9d1 S\x14\xd5\x15jD8\xcdW\xb8\xc0\xb6y\x1b\xc1!\x8dd\xf2\x97\xedr\xedt\x19\xae\x9c\x87]+\x10\xe1\xc8\x18\xd3^\xdd\x9e\xa1\xe6\x8eJ\xd1?\xc7\xd9\xf4\xfeun\xfcs\xbak\x83\xe4<[\x93\x82\x82p\xfbKsX\x16\xc9\"\xa1\xc9\x9ap\xefON\xdf.\xd3\xd6\xb9\xe9\x0c\xec\xfb\x9d\xfb\xfa\xe5\xd0\xadpd\xd4w\xdd'\xb8\xf0\xf4\xf5B\xd7\x1f\x0dE\xfa\xae\xe7:\xc7\xe3\xeb\xf7\xe7g\x97gz\xd0\xd1U+jA\xe3s\xd9%\xc8\x02)\xcc\x12\x8e\x99\xdc\xdd\xef_x\xae\x93L\x8bpA\xf4\x86\xe4S\xe0\x05\xa0\xcdS+\x8f\xc2\x12\xa0I\x10#7\x97ix\x07{\xe0dyF\x1c\x1f\xa3R\xecx\x0d;\x17\xee\xa4\xb0,\"\x96\xed\xaf\xe1:\xe4VE#\xc7\xe7\xa4(\x0dP\xe3/\xa3\xbf$Y\x9c\xdfV\x08\xc3\x0b\xf2%\xc9\\\x1e*\xa0H(q\x9d\x1fx\xd1?T\xc2\xec\xb7{\x1c\xbf\xfe\xf0q[|r0?\x1a\xbc\xba\xc2\x95\x14 \xde\xbe\x81bk\xeb\x8d\x07\"<\x8b\x12oe\x92L\x8a+\xc3\x8d\xa4\x00\xcc\xd2\xd5\x0e\xc4\xaecE\xa0\x1eP\xa3\xb6Zi-#\x02\x16\xa2v\xe9.Kq\x8e\xcf\x8f\x17N\x91\xa0\x03t\x1f\x9a\x9f\x85\x93\xd3I\x88n,\xd1\xfe\x04=\x9fka\xd4\xa5\xe3h7\xfb\xff^D\xfa\x17O=\xd7\xf9D\xeeJs`\xdf\xdd\xdd\xfe83\x96\x8e\x17\x82\x86w\xf1\x07w(\xf9\xe0~>5\xd9$\x17\x13\x871\x11\x05\xd9\xfaky]\xce\xc3\x82\xc4\xd7\xd7\x8el\xd4\xfc\x0d\xef\xfb\x1f8\xa2\\\x8e(\xe7#\xfa\xc7\xd7\xbe\xf1\xd8\x10\xab\xa38\xd2\xf7\x9b\xd7\x90~R\xbe\x97 |6\xf5M\x04\x99O\xf3wy\x14\xa6\x84\x9f#\xbe\xe4\x9e'\xb0u\x82~\x07\xd1\xa1\xacsVG]B\xbb\xb2\x02\xcd\"-T\x18;\\\xc34%8be\xe9F\xc2\x12\x19\x1e\x008\xde5#8773\xd8\x84\xc2\xab\x18\x13F\xc4\xf7\x9dl\xd6\xbd\xf0\xd2\xe2\xea\xf7\xd9\xffx\xb6\xf7y\x0f\xa9\xf4\xe2\xe5C{\xfb\xa8\xa4\xd2\xee\xeeK/\x98\x9a\x899\x93\x07\x17\x13\x9e\xea\x1b\x87\xf9\xbe\x07\x95a6r$V3!='5A\xeeC\"\x03\x84\xa2\x03\xb6\xf6foz\xa25\xdd\xecH\x87\xc6\xcd\x8d~\xcf\xb9\xea\xf5\x80\xf3t\xd74\x03\x18{\xbdw-\x19#b\xcf\x04\n\xcem3X(\x03_\xf2\x18B\x82\xa7!\x0d\xdf\x11\xc6XI\xa0\x13L\x8c\xa5\xf9\xf2Eu\xd4\x9e\x19$a?\x86\xb1\x8cW\x04\n9ju\xcf\xc7=)g\x95\xec]}\xaa\xcb3\x11\xd5J\xa0\xd1*\x11e\x13\xe8\x8eVc\x1d\xbf\x81uy\xfa\xbdY\xd4\xf0\xbdM\xce\xd9\x07\xbe F\xefd\xc8\xbf5W|k\xfc\x9b\x03\x9b\x90\xa1\xbf\xdb8'e\xf6{\na\x14\x91%\x85\x82\xcc\xc8\xe7\x96\xd3[\x01\x11\x02\xa9~\xdb\xa6f[\x14\xa5\xc5\xfd\x9b\xd3x\xc6\xc3\x1el\x07\xdb\x9aH\xc9x\xe2:\xdb\xc1\xb6\x03\x13r\xe5jnu\xaa\xa3\xd6(\x80\xef=\xbe\xe9\xa4\xb8\xe2\xf6\xb8\xb0am\x03z\x8et\xd3\xfcn\xdc3\xe0\x11\xc5\x8d\x8c\xb4\xfd\x90\xec=L(\xb27F\xac\xda2Q\x16\xa2\xad\xd6 \xc9M\xa0\x9f\xefx\xc1\xf4\xa1k\x9b\x07\xfc\xcc\xe7\xec\xa9|\xe1\x81\xa1\xfe\xf1\x15\x83.\xd4\x19\xfe\xa1Gtq\xae\x91\xc4!xAs@\xdd\x1d\xd4\x97'\x90d\x1c\x93\xac0f\x95 c\x0b|\x1c\x06\xd3\xd65I\x1f\xac\xb7\x97DH\x8cf\x84*\xfc0\xef\xb6\xd9\x8d\x07\x0fXz\x7fT\xdf\xa1\xcd\xb5\xfd\xddFs\x90\xdf\xc1\x1fc\xc2\x05iI\x9e\xc19\x89VE\x99\xac\x89\x94\xb8\x92\xcf\x94dq\x92\xcdZ\xc5\xc2\x15\x9d\xe7\x05\xfc\x9c\x84\xd1\x9c\x94i\xb8\x86w9-\x17a\x96\xaf\xe1\x87T\xfe|\xf5\xfa\x8f\xb3E\x98\xa4A\x94/\xfe\xd0\xaa#M\"\x92\x95\x04N\x8e/\xb5oz\xd6\xcb9\xe6\x82w\xa2\x84{r|\xe9\xf5\x949\xcc\x97wE2\x9bSp#\x0f\x9e\xee\xec>\xdbz\xba\xb3\xfb\xca\xd8\xe5\x9e\xaa\xde\x93b\x91\x94\x18\x14,)aN\nrs\x07\xb3\"\xcc(\x89}\x98\x16\x84@>\x05\x06_3\xb6L9\x84\xd9\x1d,IQ\xe6\x19\xe474L\xb2$\x9bA\x08Q\xbe\xbc\x83|\xaaW\xcf\xce\x11(\xf3)\xbd\x0d\x0b\x02a\x16CX\x96y\x94\x84\x94\xc4\x95\x1e/Zf\xc04II .\x9d\x13p.D \xc7\xc36c\x12\xa6\x90d\xed\xca \xc8\x9cp\x9b\xd0y\xbeb(\x9d\x83M\x92g\xbe\xf0s\xcdz(?\xa7\xc9\"\x11\x0d\xb2\xe28\x8b%\xd0\\\xaf{U\x12\x1f\x07\xe5\xc3\"\x8f\x93)\xfbOp\x0e\x96\xab\x9b4)\xe7>\xc4 k\xe9fE\x89\x0f%K\xc4\x05\xf4\xd9(\xb7\xf3\x02J\x92\xa6\xac\x86\x84\x94\xc6\x89\xa9\xfb\x8eE\xf0\n\x80-\x06\x15\xd3\xcbz\x05\xb7\xf3|\xd1\x1cgR\xc2tUdI9'X&\xce\xa1\xcc}\xbd\xfarU\xdd+\xb0\xd2\xd3>\x1a\x1f\x81sp\x01\xc7\x17\x8e\x0f\xbf\x1c_\xfet\xf6\xe1\x12~98??8\xbd\xfc\x15\xce\xde\xc2\xc1\xe9\xaf\xf0\xe7\xe3\xd3#\x1f\xc6\x7fy\x7f>\xbe\xb8\x80\xb3s\xbd\xe6\xe3\x93\xf7\xef\x8e\xc7G>\x1c\x9f\x1e\xbe\xfbpt|\xfa'\xf8\xf1\xc3%\x9c\x9e]\xc2\xbb\xe3\x93\xe3\xcb\xf1\x11\\\x9ea\xfb\xa2\xe6\xe3\xf1\x05\xab\xfbd|~\xf8\xd3\xc1\xe9\xe5\xc1\x8f\xc7\xef\x8e/\x7f\xf5\xe1\xed\xf1\xe5\xe9\xf8\xe2B\xaf\xff\xed\xd99\x1c\xc0\xfb\x83\xf3\xcb\xe3\xc3\x0f\xef\x0e\xce\xe1\xfd\x87\xf3\xf7g\x17c88=\x82\xd3\xb3\xd3\xe3\xd3\xb7\xe7\xc7\xa7\x7f\x1a\x9f\x8cO/\x038>\x85\xd33\x18\xff<>\xbd\x84\x8b\x9f\x0e\xde\xbd\xc3\x96\x0f>\\\xfetvn\xea\xfd\xe1\xd9\xfb_\xcf\x8f\xff\xf4\xd3%\xfct\xf6\xeeh|~\x01?\x8e\xe1\xdd\xf1\xc1\x8f\xef\xc6\xbc\xe5\xd3_\xe1\xf0\xdd\xc1\xf1\x89\x0fG\x07'\x07\x7fb}?\x87\xb3\xcb\x9f\xc6\xe7\x98M\xf4\xfd\x97\x9f\xc6,\xa957\xa7pp\n\x07\x87\x97\xc7g\xa7l\xcc\x87g\xa7\x97\xe7\x07\x87\x97>\\\x9e\x9d_V5\xfdr|1\xf6\xe1\xe0\xfc\xf8\x82\xcd\xde\xdb\xf3\xb3\x13\x1f\xd8R\x9c\xbdeY\x8eO\xdb\x9d>=\x1d\xf3J\xd9\xaa5\x17\xf7\xec\x1c\xdf?\\\x8c\xeb\x9e\x1e\x8d\x0f\xde\x1d\x9f\xfe\xe9\x82uH\xcd\xacC\xcdv\xe3]\x9e%`!\xf7\xa5\xf4\x02\x92\x8c\xc1g\xc4\xe3\xfc\x8a\xf3\xb5J9\x12\x97$\x8d\xc4s2\x1b\x7fn:\xf1S\xe2oAS\xc7\xdd\xd88\xea\x874Z\xb6q\x10R&AE\x04\xaa}\xf9\xab\x0e\xca\x00#dI\xa8\x12\xa6\xc1XU\xa5x\xc26<\x1a\xd0\x19\xbc\x92\xf7w\x95M\x89\xa7\xb2U,\xc1E%\xa4\xcbdA\x1a\xd2.k%|\n\x1b\xd5\xf0$\xa3ZVK\x17\xebCF>/I\xc4N\x992\xa1+\xe1\x83e\xd0\x8a\xe4VI\x97\x14\xd3\\_#o|}\xedT\xf7PUh\x99\x96\xb0\xab9ak\xe1\x94\xcbH%\xda\x00\xc1\x10\xe0h\x17\xad\xccd\xd4\xfa:\xd0G\x1d g\xe7\xaa\xd3\x96\xc6R\xefS\xaf%\xab\x9c\xec\x18\xae\x14\xe5M,7\x9e\xec\xce+*\xe4jz\xb5N\x1aZ$\xf3\xeb\xf3\xaa\xbc\x0f\xbb\x06\x9d=k\x14M\xc3\x04\xa0\xf9]%\xe0\xc4\xb7\xa6~\xe0\nidA\xb2~\"w\xa5\xbb24iu\xa1\x0f\nc\x84\x12\x9f\x90\xfb\xa2G\xe1I\xee\xa2gz\x1e\x19$T\xc1\xc2\xd0S\xd2\xe8\xa9\x8c\x9c\xeb\x86\x93\xb2\xba\xf54h6\xaay*\x90%f\xeb\x06\xf5Y\x0b\xa5\xea\xc9\xd0x\x8cm\x03\ntN\xd5\xdd\n\xa8\x8b\xa2\x85G\xaf\xee\x83\xd9~i\x8e\x0c\xa35\xe5\xe2\xba\x97\x8bw\xb3F\xa2\x90\xf9\x8a\xb7\x04-\xd6\xd5\x94\xb6\xf7-\xf5\xf9\xea\xf9\x90[s|E\xdd\x96\x11?\x06\x9a\x13\\\x88O\x86\xd5\xa3\x8d\xd5\xa3m8\xa3ze\xbc\xd7\xbc\xc2f:\x0f,l\xec\xa0!d%\x1bMhA1\xcd\x80\x94\xcf=\x11Oq\x10\xbf|\x1f\xa5K\x9b\x00\xbb\xbd\xf4D\x89\x92\xc4\xd6\xd6b\x94\x88\xcc\xba\x01u\xb4\xd4{qZ'W(\x11n\xe7\xcf\xb8>\xba\x1et\x9a=\xea\x8e\xa7\x86\x1do\x0d7,Q6\x9d\xe4\x96\xbdc\x0c\xb9\x94\x08\xffqO\x9e\x98\xa6\x85\xf1\xf7[\xbb\\\xc6W[\x08M\xf2+6\xbcb\x92_a<\xf7\xc3\xa4\x88ViX\\90\x92\xa9\x04\xb3\xf9\x90 \x97\x0e;\x08P\xe2\xa3!\x00\xaa)\n\xac!\xf6#\xe56ih\x9f(\xcc\xd3D\xda\xd0\xf2\x0bR\x96\xe1LV!\xdf\xf6\xea/C+*i\x18}\x12\xd5\xf0\xdf{2\xd5P\x85\x14\xc57w\x04\x03\xf0 \x06\x922\xde\x06\xe1m\xca\xe4\xad\xf8\xc2-?\x84\x1f_\xe0~\xd5\xf2\xecn\x91\xafJ\xc7\x83Mpp\xfe\x1f\xacP\xf8\xfd+\xf35\xe3\x0bc\xc8#\x96n\xf2|\xcc\xd2\xf5k\x80\x95H\x7f\xed\x99\xcc'K\xbb\xd8\xc9\xa4\x10\x8d\xda8J\x84\xbb\x1d\xae\xf0j\xd0\x9d\xe2zS\xdc\x19? \x0b\xd7{\x03\x9b\x9b\x14~\x80\xcc\xa8S,g\xa2\x1do \xa4\xec\xbc$\xd4-0\xfeW1\xd9\xbd\xb2\xe9\xed\xd6\xbf\x14\xa5'\xde\x07\x86\xac\xfdF\xb2P\x8f\xc2`\x1ceS\x15\x9em\x94f\xe2{\xe9\xf9\xe0\x9c\x84K\x9b\x10x\x90V\xbc\"Un\x85\xd0\x13\x10e\xf1\xea\xf8\xc2\"\xd2|\xd1\x12\x81\n\x88\xda\xd5E\xf4\xa5H\x7fi\x84\xb4\xd4\x0ei\xc2< \x0ei\xc8\xad\x140\x1a\x99\xd1\xca\xaaL\xfe\xce\xf1\x05\xfbaX\xf4\xd4\xb0\xe8\xb9\xdfH\xae\x16=i\xa6\xf3E\x0f\x9b\x89|\xd1W\xcdD\xbe\xe8es\xd1S\xe3\xf2\xa8C\x1e\xacN\xdb\xf0\x9b\xb2\xb5\xcb\x1d\xa7\xd0\xca\x9c\x98\xeb\xdcK\x1f$\x9b\x9b\x19\xfc\x00\xc5\x1b\x0f\xc8$\x87M\xc0\xf81\xed\xb05\x92o\xd3\xe6l08\xbdx\xaa#\x1c\xa1\xf2\xfcZ\x07\x1bcL6\xa3\xaaS\x0b\xda\xba\x84\xc4m\x18\x0c\xd5\xe0\x8a]\xec\xb9\x8a\xb1\x90,@B\\Q\x1e(\xdc\x90\x1b\xb6[E\xc7Z\x8dj\x10\xb8V\xbe\xaf\xba\x03\x1dF\x83\x9a\xf7\xf4\xea\xbe\x8b`>%\x9e\xebkcZ\x83\xf6t'\x9a\x97\x8c\xf6\x14'\x03\x16\x0eq\xd37\xaa\xb6\x08u\xc7A\xab\x99\xb3\xaf<\xe8L\x15E\x15\xd56\xb8\x87\x92\x8dU;\xbd\xd9\x9ey)\x06!\xed\x0e\x1b\xb1z\x95\x9e\xe9\xab\x015\xf2m!e\x90\xbaB\x16\x8e\x08\xffl\xd0 \xcbcry\xb7D\xd2\xc9d\xfe\x88\xf7Af:\x92;\xa4\xc7zH\xa3\x1e\x83\xe9%\xdfW8\xbb\xd5\xd4\xec\xf1\xab&\x19t^\xb0&&\xbf\xe0l\x1e\xdd\x15\xec\xc3*HJ-7\xb2\xd4\x9a\xde{{\xfeAgPv\x9f=\xf7\xaa\xcb\xd5!z7\xafwv^\xee\xbe~\xfd\xf4\xfb\xe7/\x9f\xef\xbc~\xbd\xfbP6\xc5\xe4\xbf\x1d\xe7\xf1\x0f\x8c(\xc7_\xff\x81\xbe\xf1\xb93\x02\x02?\xec)\xa2\xb0\xfek\xb1{\xf5\xa6\x1b1I\xdc\xde\xba\xd4\xed\xe9\xceC\x80\xfb\xe9K\x9d\xc0\x04\x01\xdd\xdf\x08\xc1l\x13\xe4\x8f\x00\xc1\xd5NH\x1a\x10\x8cU\xa3\xb9cDJ\x83\xc5\x9env\xd0\xca\x00\x9d\xf7\xe0 \xe5]u\xeb\x05\xf9\xdb*)H\xe3\xc5uV4I\x1d/`\x03\xb3xb\x01U\xae\xfc\xe5\x8b\xdc\x8e7 \xdeD6^du\xc6zz\x02[}u=\xfbf\\=`3v(W\x99\xaf\xd6[FT\x0c\x04\xb6?\x06_>N\xdc\xfd\xd1\xe4\xffL>^]}\xf7\xc5\x9d8\xbf\xbf\xf2\xdc\xfd\x91\xbb\xbf\xf1q\xd7\x9b\xfc\x9f\x8f\x1f\xaf\xbe|\xfc\x18x\xdf\xed\x7f\xdc\xf5>\xea\x81Yx\x00\x98\x8f\xb7\xdf\xfd{oH\x07\x8b!S\xc3\x8eI\x17\x8bV\x92t\x01\x98F\"k\xc3\xad\xb0\xc7\xc6\x1ed\x08\xd4%R1JB\x158B\xa64\xdc\x0em\xa0F .?\x8f\x05\xc2\xa3\xc8n$\xea\x9b,A\xf9\xf6H\xa4\xd3<\xf7^\x86\x0e\xf7BD\xf7\xa4\x1f\xcd\xf2\"A\x99pm\xd3\xcaE\x17\xf5\xc1\xb9\xbe&\xe5I\x1e\xafR\xe2\xe8\x1a B\x1bAU\x08AC\x9b\x05Y\xe4\xc9\xdfI|\x11.\x96)y[\xe4\x8b\x8bhN\x16\xa1\x90*\xf0\x8f\x87\xa8,\xf8\x97\x93w\xe3\xcf\x98\x8d\xb3\x10\xf8\xf3/\x8bT+\x94dSR(\xefe\xbbfq\x00\x824\x81i\xd4\xac(z(\xec\x98\x89\x1b\x0b\xdd\xcc}\xf1\xfd\x0b\xcf\xb0\x0f\xf0\xd3\x8b\xd7\x9e\x91\x97\n\xed\xeb\x83\xa0\x10\xd4\xf3(T\xf5\xdaXKFF\xd0\xddZ\xfd\xae\xfdk-|\x19\xb6+\xe1\xa2\x99\xe1qm\xa5,\xa7\x95\xc7\x10F\x8bg\xbd&\x8b0I\xef\xd1\xc2\xaa$\xc5\x1f _\x8c \xca\x17\x83\xda\x12\xfdb,(\xd9\xa2\xc9\x828\xc3[t\xe5\xf5\x95\x17\xd0\xfc\xf8\xe2L\xa8\x84\x19\xf8\x02\x83<\x05\xd1\xc4\xf0\xb6\x06\xc5u\xe3\x95^O\xd3<\xa4\x8f\\u\x92Q2{\xf4\x0e\x0bT\xd8G\xff\x83\xb2\xca*\xf6\x94\xb88\x10 \x8dW\xad\xf2\xa5\xdd~\x13\xdc\xdb\xbcLw'\xa4\xcc\x82mt\x17\x9d\x0frr%\x99\xdeyF\xff3 \xc4f4h3a\xf2AO6\xc14/\x16\xa1\x812\x02\x81\x12V\x13\xd4O\xbcv`\x13\xb8\xa9\xcc\xca\x18\xd5S\xc2%\xf6.)\xdf\xae\xb2\xc8s\x13\xc6c%\\O\xda\xf9\x90}\xca\xf2\xdb\x0c\xb5 \x85K\x1b\xec]\xd7\xd4\xa46\\Xa%\xcb\x0d\x93<2[7\x89\x7f\x00\xa4\xa3\x15U\xd6\xfa\x8ep\xf7\n\xf6\x9b\xaf\xa3\x96)\xa8|r\xd3RP\xcbR \x99\xd9\xb1\x14\xca\x97\"P\xe1\x8035V\xb3Vg\xaa9\xef\x1c[\x16\x00m\xce\xb26\x844\x93\xcf\xa2\xe3\xdb\x0c\xc9\xb0\xcf\x0bC\xc0f\xf60\x1c6\xc3;j\xf3\xf7\x1b\xfc\xbe,\xc841x\xb4b\xcfuU\x03F\xab5g\xba\xe5S\x9b\xad\x16\xe6\xef\xe3\x8aG\xb6\x1c\xe0a\xc7\x01\xceN\x90\xd4C\xa8\xfa\x97\x9c\xe2a\xdf)\xee\xb2Y\xbd\xc3K\xff,\xa7\xe1\x8cM\x8e\xc3\xcd\xa5\xdc\x1b\xd8\x87\x1bF\x96\x8f\xd0>\x16u\x01\xee|\xb8\xe6\xde\xd2\x17\x13\xf6\xdd\xf9\xbcH\xb3r\xc4\xce\x8e\x1b\x96 _\xd1_\xc1\xb5\x85\xc0Q\x0f\x05\xc48\x91\x0d\xf9\xb2\xdc\x11\x83\x07\xd8\x03\xfe\xff\xcb\x17\x98qK\x10\x9f\xa7HU\x0d\xe5\x85\xe5\xe1P\x023\x11\xa9>\xae\x88\xbf\xf5$\x93nn\x9b'\x04\x9e\x0d\xd3\x81ns\xe5\x13\xc9\x1d\xc8\xfd\xb6\xb2\xca\x85\xdf^v\"\xe4V\x9d\xa6\xd6\xf94g\xad\xcf\xef\xdd\xba|\xb6\xac\x8b\xfb\x8d\x0bs\xaf\xf6E\xaeV\xa6\x01\xe4\xb6U;\x91M\xfd\x85\x99\xdc\xee!\xa7\x0f\x199\xad\xec\x19\xb4$\x95\x1b\xf0\xc2N\x9d\xb2\xbe]\xe8q\n\x0e9\xde\xd8\xb8\x98\x1c*\x84\xf7\x97/\xb0T?\xd4$7#\xc6-\xd3\xd5h\x87\x95\xe2H\xa2\xfa){(\xde\x03\x06\xb3h\xa9\xd2\xb5l\xf2a\x03\xff\xd4R\xbc\xc3\xba\x90Jc\x9d\xad\xde&;Wv\x96E}\x0ed\xff:\x0fm\xfd9\x93\xa5\x04D\xd91\xbd|\x16\x93j\xd4\x12\x1d\x1e^UG\x16\x92M\x07l\x04\x07\xd04\xb5\x9dN\x0e\x91\xef\xc1\xff\xcdOg,\xfd\x8c%~b\x7fJ\x9c\x8b\xee\x85\xf9\xdaw\x80\xc9\xa7\xd9\xd9=hw\xbe\xe1\xf3H\x9dA\x8d\x18\x94\x03p\x1byx\xba\x05\xce\xd5\x87\xad\xfa{d\x99.\x86\x15h\x82\xc7{Tw\xe5;\x05\xd1\xa8pa\xf0^\xa2[\x8e\x04\xde\xf7L[\x17j\x94\xcc\xa4h\xa8\x0fQ7\xa9\xcd\x118\x07\xd9\x1d\x9d\xa3\x0dT\x98\xc1\x0dAc7\x0bU\x80\xe1Q\x86\x9e\x08zC\xa5\x8doeH\xee\x11\xcf\x99\x018R\xcc\xdc\xb8 \xffSv\xd4W,\x15&\xcd\xd9\xf9\xdbB\xff\xb7lQo9WV\xa2]\xb8Xa\xc6\xe1M\xcc}\xb7\xf6\xfb\xab\x0fcV\xd1X\xef\xfaW\xe3=\xc8\xd4x\x89'\x05\x8e\x11\xff\xda\x84R\x86\x0d\xb3\x86\x9c+\x97x\xc3s3\x93\x19lL\xa24\x94\x81{M~\x0b\x92,\xc6\xc0*\xceG\xaa\x85c\xd3\xaf\xe1\x00\xcda;.\xa5X\x7f\x92\xba?\xd3\xbe\x1b.-\x7f\xda\xaf&Q\xcd][t\xcf\xd5\xf0\xc8\x9aq\x87\x95V\x9ex\x15\x87\x05O[\x84\x9f\xabxrU\xc6Fb\x85\x1b\x95 hw\xc1`\xd7$\x85\"2OCl\xd8YY~?\x8ds\xd5\xd8\xa0\xbb\xe2\xc4Z\xb1\xeaz\xc5\xb0\xd2\x0dGY>d\x01\x06W\x19/\x12\xca\xdd\xdcc\x9a\x12\xac\xa3\x9ayy\xbb\xd8\xf8\xaaMz\x9dG\xac\xfeI\xf3\xfb\xaeV\xbe$z\x0e\xbb\xd4\x03\xa9&\xe5\x06\x9b*\xc6(D\x06\xa8\x10\xbe\xebL\x1e\x152X\xacJ\xca\xd0g\x08<\x1e\xf2\x9a\x88[)\x8b\x1b\x05#\\\x11\x0eo\xf5\xcc6GD\x16 \xed\xb7\x9f\xe7\xfe\x8f|X\xf9P\xfa`\xf0\xc4\xac\x83\xb9\xabm\x03\x0c!'\"\xe5\n+\x1c$\xc4\xd4l\x01~F\x05'\xb7\x9d\xce\xd5\xd2\xda\xe9\xd2\xd0\xceDo\xb1\x9e\xa1\x8b#U^\xe3\xa9\xc6oc^5\x9f|\x03\xcd\xc3F\x1f eZ\xbe.\xbf\xff\x90E\xe1j6\xa7>\xac\xb2rI\xa2d\x9a\x90\xb8\x1a\x1bv-\x00\xf7\xf7\xb0\x89\x0e\xa2\x1d\xcf\xe4.\x84\xb7\x17\x05\"j5\xa7\xde\xa3&\xdak\xcdq\x82^\xa2\xd4\x19\x98\x90+\xbb\x92\x05\xd7\xc2\xc8<\x0f\xca\xdb\x04UXt9\x97i\xca\xa2\xb0$\xb0k\x8e\xf4/\\\xb0\xa2[t3\xd5\x82>\xa4\xdb\x9f\xb0\xd2\xa7\xbd\x95\xfa\xcdu\xba\x7f\x13\xcf\xee\xd9\x84\xfa\xf6\xf4\x9e\x0d\xca\x9b\x7fc\x99UE\xd4\xf7[\xe1\xb1\xfd\x18.\x97\xe9\x9d\xe8\xe0J\xd7{\xad\x84\xf4\xb9k\n\\\x83,\xd4\xfd\x1a\xc4C/\xc5\xeb-n\xda\xe2y\x95^t\xc9C4r\xc7\xe5Pnnz\x90N\xca+\xad\x8bF\xfc\xa3j\x954\xb1L\x18\xc7J\xcc\xd0N\xe5!\xb6\xe3\xc26$oX\xfc\xce\xa4\xb2\xda\x1aYV\xa7^\x17\x96\xecAU\x0d<\x93\x91[5\x02)~cx\xd3u\x94/\x0e\xfa\xff(\\\x1a\xc8.y(\x90\xaf:8\x02\xaaU\x94\x04\x08/\xa5\x9f\xf6\xae\x074\x87$\x8b\n\xc2\x90\x0d\xfa\xb7\x08\x9c\xd6\x92J\xe4\xea\x9b\xe9/\xd9\x7fZ\x84\x11\x1e\x82\x8d\x04\x0cL\xd7u^\xe7h\xe6\x00\x1b`\x15\xb9&<\xfa\x8du5\xd9\xc3\x03\x88d\x12\x83\xee\x83[\xfd\xdec\x8c\x8dyU\xd0\x08[F\xd8J8M\xf0\xad\xeb\xd4\xbf\x13\xfb\xb7\xdaA\x9a\x0e\xe3\xad\xd6F\x07\x81\xad\xed\xd1\xb3\x156:\xc6\\\x15\xe5\x9ci\xeb\x8ax_g\xf4\xd1\x87\x98~\xe6>y\xd2\xb9/\xda]2\xb7f\x05t\x8a\x0e\xc8\x1a#\xd6\x97G8\x02\x90K\xd8\x9eh\xa3\x0d\xb7J+\x19\x8a\xe8\x8dh\xf0#cC\xaa\x0b\x0eF\x9e\xa6\xb0\xf04\x96\x93!\xb3\xa1\x03\x83\xc6\x04N\xd0\x9bjo\xbc\xb1W:\xa9\xf6\xcc\x16\xb4\xf8\x0e1\x13]\xcbh\x03\xeat\x10,\x9b\xc8\xd26\x8d\xc4\xdd\xf1\xea\xdbx\xbfE\xfc\x19(?I\xe3\xc3H\x8b\x16e\xea\xeba\xbe\xca\xba\x05\x02:\xbboS\xae\xa0\xed\x85m\xc3YRy\x94\x14\xd3`q\xa0R\x87+\x96\x16\x9c\xfd\xf8F\xe3F\xec#4\x1c\xe6\x95\xbaJ\xa3T\xbfI\x80n\x0cD5\x0f4\x99\xfbl\xe7{\xcf\x0b.hA\xc2\x85\xa0H\x82s\x12\xc6\"\x02\x1b\xbe\xffR$T\xbcg\xee\xee\xeb\xefQ\x80y\xb4Z\xa6\xe437\x80\xe3)\x97E\x98\x95\xd3\xbcX\xf0\x8aww0\xf5}X\x96\x97\xf3\"_\xcd\xe6<\xf3\x8b\xe7\x83LMz\x1d\x01\xf28_&T,\xdc9>\xdf\xf1l\xf4\x9fA\xd7\x1e481II\x12\xc6|\xa1|\x84\x07\xaa\xe0\xa7PF\x8b\xbbf\xd24\xc9\x92f\xc0E\xdb9\xbd\xd19\x07\xfa#-\x0f\x08o\xd4~\xb6\x93F\xaf\xec\xf9\x04R*\x8c\xe6\xfb\xea\xb3\x16^d\nd\xe0o\xc2\xc8 \x82P\x1f\x1a,\xb9\x93\xc5\xe8fk\x8b\xf1y\x18v\x1d+`3h-k\xbe\x07\x02\xac1\xca\x8bO$>'\x7f[\x91\x92\x96o\x0b\xf4\xe9mJ\x96\x8bDP/\xcdPlO\xd3\xdb\x92\xcfW\xee\x91\xa5\xf5\xedk\xc7\xeeV\xb7\xd3]\x9b\x0fYq\x11\xc6\x06\x0dn\x8a\xfc\xb6\xe4\xd4\xcb\xc4Y\xef\x04\xbb;\x8e\x0f\xec\xc7\xeb\xc0\xb9\xaa]\x81\x04kR\x94I^y\xf9\xf0\xe1{\x8fk\xd2\n{\xda\x04\x87w\x99\xe8KpW\xed\xd3\x0b\x1a\xa2-\xfc\xac\xdd\x9dT\xd8\xad\xbc\xd0\x8e\x954H\xb29)\x12\x81\x15^\xed\x1aX\xaa\xc8h-\x02(|\x12z\xa6#\xdc\xe0\xcf\x06\x99IL\x05\xfe\xd1=\x0e\x80\xd4uvw\x9f\xefJG6\xed,\\u\xebC\x92\xd1W(i\x025`\x8d\xd7R1e\x03\x98\xfb\xa8\xa1\xc5\x1a}iE\x0d\x0b,l\xf983bg\x10\"6\xee\x82\x8a\xa3C\x0420\x84Q\x05e\x1fSU\xf6k \xd5\x11\x99\xf0\x8b\x8e\x93\xd9\x15\xfc\xeaz\x7f\xea/\x10\x19z\xb7\x0f\xbb/`\x04\xbb/\x9e\xbdzn\x99\x85FW\xd0\xaa\xf4\xcb\x17A\x0c\xe7\xb0\x0f9\x8c\xc4\\\xa4\xf5\x87\x94Q$)\x8c \xf2\xcd\x95\xd4\xb1~\xdc\xf6w\xafF\xe6az\x18\xa62,\xa7/\x0f\x02\x12\x1f\x15a\x92\xa9\x89\x1c\xe7i)\xcdr\xfclh\xa6\xc5\xa4\xa4E~'\x12\xcd+\x82\xf1\xf99\x7fE\x82\x98Dy,\xa2\xc9\xd8N\xaaF\x1eVxZ\xb5\x86B\xb2q\x16\xe5\xa2\xb7\xa4\x95\xf6\xe5\x0b8+:}%\xe5I*\x13\x87 l\xc5\xb5\xa1rD\xab\xe4)\xef\xb2HJL\xd8\xfb\x0dn\xe5\xf7\xdcZW+\x9cg\xa8\xff\xd2\xab\xb8\x0b\xedC\xb3\xef\xc4\xe4A\xdc\xaeoU\xec\xd8\xad\x84RpY\xf4]\x16u\xe7\xe3\x81\xe0\xb0\xe3\xd1\x8d\xfd@d\x14c\xff\xa8\xe4C\xb4\xb9%\xb2\x81\x8a\xc6 \x15\x7f \xf7\x1eII\xe6+\xbf\xd9\"X\x1b\xf9\x8a\x871\xf5\x0c\xc4\x87\x99\xa6\xd2\x9f\xad-\xe5x\xf71r\x80[\x9fJn\xeeC\xe1\xf9\xca9\xe5^\x08\xa6\xdco\xad\x03\x97\x9br\xb9\xa8\x14\xa9\x12\xc1\xd8\xf3+,V\x19\xe3\x15\xdc\xdc-\x1e\\\x81\x0f\x17\x1cT\xecZ(\xe89\x8aO\x00es\xd0A\\\xf5+\xf8\xe0\xad\x01\xec\xc1\xd8\xd5YD\xfd \xf1\xcc\x90{\x07\x7f\xb7\xb6 C\xde2\xb9\xa2dX\xea-gB}\x8cfZ\xba\xd78\xcd\xfcj4gsv\xed*\xef\xf6\x91\x1b\xbfXi!\x05\x01\xa8@Y'\n\xf8kl\xfa\xba\xdb\x8d\xfciX\xd2\x1f\xbb2T`\xa6\xd4\x88\x8a\xcem$\xaa\x03\xc2\xae\xb9\x03\x92\xdf\xdai`-\x8d<\xcc\xc8-\x84\xfcf\xb11\x016\xba\xe0\xce\xbc\xad\xb9\xe6s\x930\xd8p\xe7\xfc\x12\xec\x8ew\x00\x8d\xbe\xd9\x8f\x06-\xe05\x1c\xa0\xdeY|\x9f2n\xf6V#\xfaX~N\xa6(\xe1\xa2ok\x0e\x0e7\x08\x9e\x94f}\x0c\xbe\x86\xca\xc5\x87\xc4\xcb\xe2\x8b\xed\"A|^\xeb%\xd7u\xd1\xb5\xbd\xac8\x01\x95\xc22e\xaf\xfej/\x8eg\xb4R\x98\xbf\xef\xc9/\x9e\xe7\xc3T\xb9-\x1e\xb4\xa67M\xa4\xc8E\xe9\xc6k\x03\x15\xec\x19\xfaP\xf6F(_\x05>\xc7\xcb\x03\xe5\\\xc4\xa8+r\xa6\x18\xe6\xa4\xf2$\xe4a\x87\xf9\x17\x97\xb7^\x7fSk\xd9\x1d4\x9ake4\xa6Ad\xd0\x17\xf0Q>\"\x06\xa3<\x83\x9e<\x01\xaa\x10C\xb8\x06-\xe2Hb\xe4\x98\xa59\x06,\xfc\xd5\x15\x07\x84\xc68\x16n\x8d\xbb\x07\x8d\xf3\xd6\xdawj\xa4?\x0c\xb6\x0c\xeb\xca\xb1\xb2\x86:\xcc\xb2\xa0j\xf9PD\xcfo#\xd8\xc9g\x9b\xbf\x8a\xf87b&;\xc1\x91\x8b\xcd\xcd5\xf4\x8a\x0e\x83AtZi@l\xe6\x93(\xa9e\x05\xe6\x0c\x95R\xf4\x8a\xa3\xcd\x92\xcf\x1b:\xfd\xcb\xf1\xc6\x82k=\xa1w \xbc'\xc3\x1c\xbb2\xd0'\xce\x86\x0f+\xd8\xdc3\xc9\xd3\xd8\x93\x07a\x9a\xf2\x83\xa0\xe4^\xd8\xe4\xee\xe3;\xa6\xf2\x92\xe6\x83\xe30\xd2\x82\x1f\x00Mx\xd9\xdc\xc4\xac\x1dG\n'I\x18\xb9b\x11\x0b$\xa2\xaf\x89*\xe7\xf1\xecb\x04qN`?l\xe7L\x1b\xd6\xbb(\x08)&\xee\x94\xc8T\x9c|\x10\xcdW\x99\x85\xd1\x92\x0f\xea\x0b\x05DP\xf6\xddy\xb99r\xbf\x88\x87\xc1}\xb5B\xbb\x88\x99\x1a\xdc\x1c\x8c \xad\x16-\xf5\x19\x036\xd5\xc0\xc1\x0b\xae\n\xb9\xa3\x81S\xdau\xf4\xca\x83\xbd\xa6\xb9\xf9\x1e\xb2\xd4ZW\xa9\x87\x0bhn\xa4Z\xb4\xc8H^\x86\x06fM\x07\x9d\xc2\xa7\\\x8f\xb4\xbc:\x85*\xf1\x96\xb6\x07xx\xf0\xc9\xd5\x1b o<6\x0c\xb4=\x92\xa28\x9c6\xebJk\xe1\xe9\x0c\xc2\xca>A~\xb7\x171\xb3s$e\x1e|p\xf8pZ.\x92\xf4gF\xe8\x08\x0d\xad\x84\xc8\xb5\xdbI\xa3\xfe\xa8\xb7{\xd5\xd4\x1b\xdc\xda\xa8\xcfW\x1f\x1c\x8d\xe9\xe6}\x85\xa4\xacE\xbfBYI\xcbX//\xe3nH\x18\x07\x8e\x0f\xce\xd1\xf8\xfd\xce\xce\xce3\x8b\x8f3ho\xf0*\xb9\xd7\xfd\x99\x85E\x10\xb1\xb4\x9e<\x11\xbf\x82yX\x1e\x0b~\x0bl\xa1C\xa5\x9b\xe8z\x99&\xed\xd2Wh(\x07{\x03s\xfb\x16X\xb8\xf3\x0d=\xeb\x08\xe0\xd5/O\x92Z\x90\x1bsU\xdf\x94\xd4\xfc&\xdb\xed\x9c\xe3\x92\x0e\xa6\x9a\xbc\xa4\xc2\x8f\xce\xfaN\xcb\xaf\x88\x85\xe6\xbd\xe2;y\xce5\"\x9c\xb4\xee\xe5}P\x15G\x97\xc9\x92\xf4a\x07.\x01h\x1e4uP\x90\xc30\xcbr\n\xac\"\x1f\xd8\xafB\xdcp\xea\xac\x88\xd6r[$i\xbf\xa3C\xb2\x9e\x1b\xf0\x1b\x18s\xbb\x8d\xfd\x86\xc1#7\x88\x0b\x85\x8d\\\xa5\xab\xd01:W\xa1_V\xae8\xdd\x02\x17\xb4P'4\xb6\x1fi+$\x0d\x94\xe2\xdc\xed\xaa;L\xf0**Y\x06\xd3\"_\xe8\xf1\xe3\x00DH\x05\xcb\x16D\"\x85\xebWpT\x8dT\x18\xe3\x0b\xf6\xf1U\"@FmsEX\xbc\xe1\xd1$\xd3\xcd\xdak;\x86\xac\xaa}\xe1\xf9\x90\x0b\xb9\xfb\xfe\xb0\xb3[R\x03\n\xc8\xf0\xa5\x0f\xa7\x94\x14@\xb2\xd8\x16d\xd3D\xdd(G\xb4\xc5y\x86\xd8\x8b\x19\x9e\xdc\xab\x16\xe7m\xe7\xd2A\xb9\x9e1Y-\xc9'\xb4\\$\x80B\xdc\xd4\xa4\xf2>\xf7\nN\x1az\x80'\xe1\x1dn\x15>\x11\x98\x1bQ\x0fF'+Q_\xc0\xf1\x8c\xd1\xa3\xb9,A\xb1\xa3\xc989\xd4\xbc\x8er\x0dm\x1eg\xeb0Mb\xc8\xf2l\x8bW\xbb-N\x1a\xe4s\x1c\x0f\x95\xc5\xb9/\x8e\xe6\xbc\x87\xcdy/xJ.\xf9\xd0v\x10\x10\xb9\x069\x97\x99\xf2\x00\xd2n\xde$\xc0B\xc3\xde\xaf\xa4A\xb6\xf5AU\xae\xdek|S\xd5}\x078\xd1o\xf4\x8c\xd7Axw#\x17E\x8b[\x82{Jl_\xda\xe1\xc2G>F\xf2H}\xbeVz\x18\xf6\x8a\n\xee\xb2\xa4\xda\xa0\x8c\x88\xcc\x95\x0d\xcf\x15\x03,\xce#\xcc|\x9e\x94F\x18\xf8\xce\xc2\x18\xb9@>\x95\xd8j\xd3\xaa\x1b\xc9\xeaF\x0b\xb8:8\x12m\xde\x0c\x9a\xcb \xed\xfd\xa6\xeck\xa7\xc3GR-\x18\xc4\xed\xc1\x05\x0c}p\xc3=\xb6\x19\xd8Z\xfb\xfc\xdb\xb8\xe0n`\xc3\x1d7\x02\xc3\xcd\xbb\xfaH\xb1\xc2\x08\xf4P\x84\xda\x83\x07\xce\x08\xb2\x1eY\x85\x90<\x8c \xe9\xce\xc8v:\x8fgo\x07M\x1f-\x86S)\xca1O\xc3\xc8\xc8\xe4\x1b\xf3Z\x85<\x9b{\xd0vs\x06\xb5\xa4G\x95\x94\xacj\xfc\xd1\x89\x9e\xcb.\x8c\xb5\xf2A\xa2\x8cvL\xa0& \xc3\xa0j\x10\xf1\xa4\x11\xee\x1c\x1a77\xbb\xea^eCjo\xf0l\xcdV\xda3 \x1b\x16H\x9e\xbflm\xf9\xca\xad(:\x82\xac\xef\xcb\x14\xa9\x07\xbe\x19o\xcf\xda\x02\x13\xbc=\x93$q'\x11X\x12z\xd4\xba1\xef\xa6\x95\xd0\xd6\xd2\xe2\"O\xb8\x99\xa2\xf9\xbb\xfc\x96\x14\x87a\xc9\x8d,6\xdc\x893'\x9f\x19w$\xee\xdd\xd9\xff-\xfc\x11\x96Q\x92\xb0\x1f7I\x16\x16w\xf8+,\xc9\x8b\xe7\x98+*\x9f\x8a\xff[OE\xb1\xdd\x17\xe8k\x17k\x90\xbf\x8b\xf0VQ3r l\x82\xe3xZ?P\xcf\xa8\xb2\n\xd0Ng\xe9`\xb2\xde\xf3\xe8d\xb2G]W\x83+\x83\xf2\x81I3\xd7\xca&5X\xe6[\x93\xda\x89\x91\x83&U\x9c\x83\x91\x91\xe2F\xae\xba\x97\x93\xee\x18W\xe3\x80h\xef\xdd\xe6\xe8\xbc&\x84]\xdf\x87\xcf\xc8\\\x85J\x15\xd7C\x1e\xe3\xc4\x19\xb1\x96,\x96)Y\x90\x8c\x92\xb8\x87\xb5\xa9/\xe7\xb8h\\\xfdF\xb2x`g\xaa\xbb\x8c!{\xdb\x1a\x90 \xa9\x02\xc2\x055\xe2\xeeW\x11\xbd\xdf\x8b\x99\xa8\xcd\xbf\xa1\xe9$\x83{\xa8\xaf\xee\xa8\xa5\xcc\xabP\xf1MQ\xab\xb0\xc8\xcbc\x8e\xe2p\x87\x16R6\xcb\xd8\xad\x06\xd2\x192S\x80\x07q\xad\x1f\xb4S 7\xfdJX]\xd5\xb9\xaf\xd2\xb2\x19\xbf \xcc\xb3\x88TB\xb7\x0e\xd2\x8d\xd6*G;\xbe\xa2\x9a\xd5\x16Q\x83r\xa8\x14-Fe\xe0\x16\xacT\x97\x8c\xdb\xee^\xdbJY-\xd3\xd5v\xa5\x84\xae#\x14\xd1\x81\xf6\xd8\xda\xdb\xbcl\xf4\xc7\xca\xe7Z\x9aw;\xdb\xc7\xd8\x8d\xf7\xdc\xf9\xf5%\xf7Z\xfe\xd6\xb6\xe9*S\xf3ToZ\xae:O/\xbf\xcb%%Y\xecz>\xd0V\x0c\xf8\xdf\xd5=U\x03\n~\xcf\xa0\xd4}\xb6\xf3\xcac\xc7\xe1\xf1bA\xe2$\xa4\x04\x13w\x87\x85\x0ex\x8c(\x83F\x04\xf2\xbbf\xe7\xbf\xb9\x1b\x99\xfb\xe2\xf5\x8e\xe7z\x95\xdbN\xc6-a\x98\xc8\x17\xafw\xbfa\xa8\xeb\xcam\xfc\xcb\x1ds\xf0\x84\x17\xa6\x88?\x99\xfb\xea\xa9!\x86\x97n]-\x0e\xf6f\xc6\x95)jSWx\xa0R*E\x867\x9a\xff\xc5\xb4\xa1.y\xdf\x05\\W^\x1b\"_u\xa5\x0f\xb51\xa2\x12\x9f!\xb4\x98W6\xcb\xe1\x85@\x86\xc1W\xb9A\xb0W\x9b\xbaF\x9a\x93\x05~F\xa0sI\xf4p\x11y\"\xce]\x04\x7f\xd8\x83\x1d\xc6&\xb0\xb4\x914H\x96vN[\x90\xba\xa5\x1by\xde\x1b\xe0a\xee`s\xd3p\x1d\x85z>\xaa\x94\x95rq\xc2T\x1c\x8d\x13z\xe5C\xe1N\xbdz\x8c\x1a\xbf&R\x15w\xc9\xdf\x00\xcd\x0d#\x89\xd6i$\x05\x95Z\x07\x86\x11\xb5&\xd1\x1b1\xd3\x8bHaJ\xc2\xc4nD\n\x8aT\xb8\xf1\xe1+\x97\x12tw\xaa\x06,\x967\xce#\\r\x11\xc0\xe1\x92|\xa6\xa7yL\\\xc7\xe9p\x1cn\xd0\x00QT\xaf\x06\xdc\xaf \x83\xd3\xc1\xe6{\xf2\x80\xe7\x97\xeb\xdc=\x16\xb5\x9d\xdfC\xfc_f\xfd\xfe/\xb11\xe3W\xb3D\x05\xad\xd6\x9a\xe4\x94E\x8e[;Z\"B\xf3\xa3\xca\x8f'8\xd1c\xd0\xc8\x077l\x1e\xc4!\xe5\xe1|\xf6`s3\x81\xff\x80\xa7\\\xdd\x01k\x0b\xcay2\xa5.z\xa1\x10\xe2\x17ix-(\\6\x82 \xad\x96qH\xc9\xbb\xf0\x8e\xcd\xf3\x00*\xd7@\xb2cD\x0f\x83\x80u\x19\xde\xa5y\x18w\x84\xfb\xa9;\xf06I)\xe9>\xe5{:`\x10\xc9\x0e\xeb@9\xcfo\xfb\xc9C\xc6\xa0\xb6|B\xf5\xf8>\xe7\xc1\xb4\x94\x04#UE*\x17\xb0\xba\xfby\x06\xc5\xb6\xe1\xae:\x86ke\x1b\xb3\xd9\xc8\x14\xbf\x8e=l\x16\xb2\x91\xe1.\xc5f]\x88s\x17\xcd\xc3lF\x84UW\xff\x0c\xdes\xfe\xda\xbe\xe3\x1d\xe7\x11\xa70|\xe4)\\\xe41\xb9\xd7\x0c\x9a\xb8/c\xd0\xae\xf6\x06vR\xdc\xb1\xd7|\xf7\\\xf37\xa7\xcd\x9f\xb5\x91\x81Vr\x8a\x1b\xcfi\xb3p:Z\xd1\xca\xb1\xc1:m~\xae\xc2J2;\x83+\xee\xa2\xf2\xbf\x1ea\xe2\xf5mH\xc9\x8fd\x9a\x17d\xfc\x99D+\x14l\xd2 \n3\xf1\x8a~.y\"k\x0cOR%m\x1e\x96?\xe5\xe2\x12\xa6\xfa\xfeKB\xe7'\x84\xf2Y[\x86E\xb8 \x94\x14\xe6\xd4\xe3,JW%\xab\x94P\x9ad\xb3\xb7ya.\xf6\xe3\xddqL2\x9a\xd0;\xfc\x1e\xa6i~{Y\xdc\x1d\xd3\xb3\x15\x95\x85\x16\xec\xa8\xafn\x0ddj\xa1\xbf\x96\xcb<+\x89\xb9P\xa9\x16)\x1b\x05\xf8\x1b\x0dg3\x12\x9f\xc9\xb1\x96\xcd\xa1\x97\xac\xbb\x97\xe1\xac\xca{Dh\x98\xa4\xd5\xab)\xfby\x9e\xd3c\xaet\x87r)\xca\xa3Z\x88\xf6\xe6rzo\xc2\x92\xbc\x0f\xd1\xacO\x00@Rw`\x9ad\xf1Q\x95\xc6+!\xd1\xaaH\xe8\xdd\x91\x96U\xa6\xf3i.\xf2x\x15\x89\xa6\xa2<+W\xb2\xdd\xbc9\xc2eH\xe7\xb2\xfcb\xcd\xfd!I\xe3g\xfcM>SRdaz\x94G<_\x92M\xf9^M\xca\xb3\x83\x8bg\xbc\xec\x92D\xd5\x8f\xff,9\xa8\x9c\x932O\xd7$\xbeX\xdd\xd0\x82\x88\xe6Y\x06\xedC+\xbdQS\xf5r\x91\xaf\x8a\xa8\xce|Ay_WE}\x19\x8b,\xaf!>\x82\xa2\x15\x94\xb9\xafLA\xdaQ\xa5'GyA\xd1\x0c\xf1Wt\x87\xf8+\x9aH\xafn\x13cm\xbf\x97\xd0nVa\xb0\x1c\xfd\x08\x17\xecL\x9d\\1\x96bF\xe8q\xe6N\x9c\x05\xa1\xa1\xe3\x83\x83K\xe6T.\x9e5G\xb5\xd4\xf3a\xe2T\xdb\xact\xae<\x1f\x0f\x8d\x12Eh\xffy\xe1\xb9\x93+\xcfC\xc8\xea\xb1\x87\x94\x97\xa0\xc1I\xb8\x0c\x92\xf2$\\\nE%\xec\x93\xeb`\xb0\x06\xaf\xd6\xf4\x16\xc9I&\x12\xb5\xb9A2\x81\xf7\xe4$\\z*9\xea\xab\x98\xe1g\xae\xe0\xd2\x7f\xf7a\x9a\xae\xf7Bj%)\xbf \xb1O\x94\xe7\xf1\x0e+\x93%\xa7\xea]RR\xcf\xf5\xbc\xa0 l\x1f\xb9\x8d\xaet\xdd\xc1\xc8\x08\xa4\xb1\x081A\x959\xd9\x97o\x88\xb8\xaf?/R\x87[5\xd4\x89]r\x19F\x9c\xbbj}\x9b\xe0\x04\x0el\xca\n\xf8r0\xb0j\xce\xbb\xbe\xfc\xffP\xa3\xa87\xa7\xbe<\xe6AX\x8e\xb3\xff\x1a:\x87\xf1\x84|\xf2\x83\xa4d\xffT\x81$ \xca|A\xbe\x11f+\xe0\xd4\x94\x8d\xfbf\xe4\x92\x07\x1d\xba\xf49>\xa5$\xa3,\xc9\x0c\xabz\xc7\x14\x08}\xd3\x9aH6\xd5\xb1K\xbcj\x9f\xf7\xed\xef\xd6~f\x0b\xda&\xd5\xb8\x8b\x92\xfb\"\x8f\x81\x953Tz\"n\xceZ\x1fQ\xa7\xac\xb5\xb5x\\]r+vW\xbb\xd8\n\x1d\x93`1yb]\x8bM\x811\xd2\xcd_Fp\x89\xd1\xf30j\x15\xcb\xe8,V)M\x96aA\xb7\xa7y\xb1\xd8\x8aC\x1a:u\xb6\xbcX\x1c\xb1\x14\xcc\xcapE\x12\xe1q\xb8\xfdy\xeb\xf6\xf6v\x0b\x8b\xac\x8a\x14\xaf\xd7I\xecT~\xda\x8d\x04\xb96U\x06h\x14\n*\x15\xc0\x189\x1aI\x894\xf2\xe5\x9d\x00Z\x1d\xe3\x87\xf5\xe1\xde \x83&dy/\xb0c\xc7\x8a\x9c}\xc3\xa1\xd2\xc6*\xd1\xaa(HF\xdf\x0bR\x84\xd3e'\xcdS\x19A\xc5\xfd^\xbfrY\x99y\x04~1\xf4\xd2k\xd6\xc1\xce\xff\x893#\x14\xe1{\xc5\xff\xe5%\xfe\xe7\x1e\xba\xd8\xaf|\x89D\x0f\xfb9'a,\xf6B4g?\xd0\xcb\xa6\xa3E\xd2\x88z\xc5\xde\x15Wf;\xd7\x00Z\xf7\x9fS\x1e%M\xa5VX\xd1P\x08\xcb/HJ\"\x9a\x17\x9e\x1b\xf5\x05\x82\xac\xb0\"\xee\x8b\xaaBM\x9d\x9fs\x04\x9cHz\x94\x86V\x85\x1e\x15\x9d7Q\xd3d\x8f\xd2\x0c\xab\x8e\xa3\x0cG\xf7\xfc\xef\xeb\x04\xe1\xa35\xc8k\x14\xcdf9\xdd\"qB\xf3\xc2\xd6\x01A\x9e>J\xf3\x7f-\xf3\xac\xa2>8\x18\xe9\xb3\xacm\x86%\x87$\x8dp~\x94\xce\x14\xa2\xbe\x9e\x0e\xf9Vz\xbe\x97\\R\xdbC\xecSh\xccB\xf7\x11\xc5Qr\x8b\xce\x91\xcd\xca\x80\x89\xc3\xe8\x03~M\xa8\xa6d\xdc\x8f1\xce\x05\x8f\xca\x8a \"~b\x19\x9c\x151)H\xccg%X\x90bF\x18\xc3S\xd3\xa9#\xdd\x16K[\xbbx\x08\xb3\xf4mK\xd9\xdd\xd3\xa5\xdf\x00<\xcf\xd7\x97\xbeZ\x87\xf6\xaa7\xde\xe7*\xff7\xa8c\xd3\x96\xbaC\xb3\xc6\xb5\x88#)\xb9K\xf34\xcc\xfd\xee\x0b\x16\xd1\x98n\x0f\x8a0+8\xd8\xfe\x8a\xbb\x86\xf1Wi\xaf#\xc8\xcai\xde\x9e*m\xae\x16|d\x1aG\xfd\x98\xddP\xab6\xac\\\x83\xb57\xb7\xbb\x1e\xd8\xae\xda\xaa\xa8\xb3u,h\xc3\x9f \x84%\xe5\x0c\xe6\x0e,\x06v`{\xbd\xefNv\xb6^_}\xe7}\x0c\xda\xbf\xb6\x93\x80|&\x11#p\xb8\x0b\xb7]\xd3lH\xe9\x87\xb9+\xf1\xc0\xae\x10I\xeb2\x02\xaag\x12\xee\xdaB\x18s\xe3\xb3\xbe\xc6\xf1\x0e\x9a\x07\x0e \xca\xe4\xef\x04~\x80]\xaf\xb9\xfb\x05\x17\xdbf)%\x03\xd7\x93\xad\xb9\xd6\"\n\x1d\xec\x83K\xda!\xe9H\x87\xca]\xdd\xd5\x8d\xaad\xd5Uk\x18bc\x1bV\x83\x1c\x10F\xae\\\xb3\xb6\xf0d0\x15\x97K\xd9\xf0\x9a\xb7\x8f\\W\x1f\xb6\x9a\xbd\x9a\xf2\x0bB\xe7y\xdc\xab\x9f_-\xb7U\xa6.\x9f\x84U\xc6\x18\xfb-\xc6\xd8\x9bU\x07\x80\xc3\x95\xe5J\xdat/\x8f\x87\xf0\xa8\xb9\xda\xfanh\xbc\xdf\xe8r\xc3oCR\xbc\xe1\x0bB=\x974\xd9\xb8\xbe\xe3\xe5Z\x97f>vGd\xd5}\x1d\xb9\x95\xc8\xab\x12\xb2~[O$\xd5)\xeak \x9e\x0c\xc8\xca,\xf8}\xd4n(U\x1b\x89\xfc\x968\xba\x97\xd0\xab]\xbfY)=d\xd3\xeav}\xa0W\xbe\xd031\x82xS\xb0!\x08g[\x15v\xb5\"\xd4 F\x99D\xeb\xa6\xdcoI\xe2\x1fe\x96\xd5.\xda\x85\xa1P\xcd\xb6r3\xf0(\xed\xcb\xfa\x8cK+\xee#\x1e\xa5!V\x97\x99I\xac.@\x1e\xa5\x1dQ\xdd\x006\xa5\xfbf\xc6\xdc\x99;\x1fn|\xb8\xee\xbe\xceku\xac\x11\xd8\xdd\xaa\xc5Qe\xe7\xd7\x8c\xaeSu\xd0\xe9\x9b\x02\xf9\xa0\xd7\xa3\xae\x0c2\xd3FS\x18\xda\xaf\xb5\x06j\x07o\x13:\x97\xaa6\xe5\x80\x91\x19+\xd1p>'Z\xe4\xd0\xab\xf4\xa1#W\x1f\x03b\x17|\x8ekP\x11\xd5\x9f\xaf5\xe3S\x1f\x04\xcd\xdeU\xe9\x8f\xdc;\x83E\xb2\xfe|m\x85\xb6o\xe7\xb0~\xb6\xfbpnt\xca\x80|\xe4c$%\xb4\xbd\xa5\xa1h\xae\x97#\xeeC\x1fe\x8b\xb3\xbaz\x0f\xc7\xc6\xfbg\xd9\x87\xfa\x8a\xb6\xf7\x94\x92S\x82~\x81*\xc4\\]\x02q\xe5\x01W\xd9G\x83\xee\xcf\xa05\x1a\xe5\xc6\xcc\xa0?\xd1\x89\xc6\x9a\x83\xbc\xd0\xd8\x08\xe5z\xda<\xed\xb7>\x8c\xfd\xc1\x13A\x06\xdf{\x81r\xc6+`N\xab\xf3YEl|5\xaflJ\xb7\xf2d\x0e\"\xf4\xab\xcfH\xf8]\xf4\xcc'\xf7\xa2\x10\x02\xe9\xf0\xd0\x07QZ\xfdD\x06\xce\xb2@=\xc6A1\x8c\xbf\xd32\\G\xe8\xd9\x03\xfb\x08C\xfb \xf6\xed\xff\xd5\xea2\xf4^\xcbZuC\xb9w\x94w\x8c\x1d\xfb\x11TPn\xc8\x9fz6\xee!'\xb1\x0d\x8a\x18\x83\x10F\x95i\x10\x9c\xe2x\x0e\xf3l\x9a\xccJ\xb6<\xf6\x85\xc5\xcb,\x06\xb8\x17yAM>\xd0\xe5\xc3\xfd\x10\xd7{\x92\xe7\xef\x04\xf5\x0b\x94O\xe4\x05\xfd\xf1n\xd8\x9a(e\xcd\xee\x00\xba\x02\xd4\xea\x8f\x9c\x0f\xa3\xdej!t\x1fV\xd8?R\x94\xca\x1cL\nK\x14}P\xe9\xeb}\x90]\xe8\xb0\x11\xff\xea5)\xa6>\x0f\x0c\xf2\x9e\xdd\xd8g\xe9\x83\xbc\xee\xb3\xbe\x1a\x93\xbc'^z\x02{8t\x8aU\xb8\x05^\xd0\xf7\x0eV\xc1\xdb\xdd[\xbb>\x96F\xdc\xd9[\xd6\x01z\xa0\x8a\x0e\xca\x11$\xf7F\x04\x86\x9d\xd9\xdc\x82\xbe\xa6\x07e><\x86\xca\x9ck\x192\xaf\xf0~\x17\x1a\x9f\xf0LST\xb4\x1e\xa93\xbc\xbe>&\xa1\xf1~\x80]ik\x90=J\x8f\xb4j\xef\xd5\xb13\x8e#\x9b\xban\xf7\xe0O\x0e\x95\x1b_\x96U\xb2\xc9&\xa8P\xb4\xeb\xee\xd1\xc2\xa7\xc1-\x98\xb4\xfa\xee\xd1\xd0\xc1\xe0\x86\x0c:\x85U;\x1d\x0dh\xc6)M\xbd\x10\xa3\xfa\xe2\x90\xdeK\x04v\xef\xbbw\xa3JW\xf3|5\xa3\x92\xfcA\x8a \x03\x9b\xb4\xcaW\x8a\x81\x9c\xb0\x14E\xe7\xb89\xb2\x06\x9d,\x15\x9c2y\xc9\xe2\xd8\xc6\x08\xe2\xa4\x1eX\x0b\xa6\xcd\xc3r\xce\xc5\xac\xf8\xf30\x8f\x89q@\xa0\xe3y\xc3\xa5\x9aXq\x93\x11\xca\x03Y\x85JQI\xed\xb6Y\xf7NMi\xb7o^\xb7N,\xf3\x9ec\x99\x1ee^\x1d\xda-\xc2y\xe9)+\xab\x16\xc2@\x13\xa9c\x7f8\x98^'\xb2\xa3\x0c\xab\xe6\x0cf7\xf4{\x1f\xe3.\xbe\xffh\xfe\x19\xdb\xf7\x1b\x01\xa5\xb0\x80\xc7P\x90\xb0\xae\xca\x99\x98\x93\xdc0\x95&\xe5\xf0oD\x83\xbc\xd0\xd5c\xa1\xb8\x07T\x97\xd4\x9ah]\xba\xa1\x0d\x04\xd7y1\xa5N\xa4<\xac\x0c\xb8\x02p/Z\xd7\xc1\x8e}\xd0\xf7\x17\xf2i\xcd\x0e'\xfa>W\xf5\x93k\x1d\xff\x07Hj$\xdanH|\x8d:r\x06\x17<\xdc\xcc\xb1V\x1a\xc5\xf8\xcf\xce\xb6\x08K9\xd9Q\x02\x12\xaa\x11\xa2do\xe0\xd2\xde\x9f\xff\x81*\xa9lRz\x95R\x0d\xb3p\xf2\xaf\xd155\\\xa3\xa0\x99\xb2\xf4\xf1\xd2\xb9\xbd\x1f\x88\xd0\x85\xccU(y^y\x9d\xf7A\xb9T7\xe5#\xaa\xe5\xb5;\xbd\x97@x\xff\x83A\xac\x1a\xaa\xa0x\xa7\xd4\\\x8a\xdf\xb5\x7f\xb11\x1e7\xe5p\x95\x05M\x1f\nl\xcc\x8fP\xaa\x0b\x16!\x8d\xe6\xee\xf6\xffq'\xe1\xd6\xdf\xaf\xd8\x9f\x9d\xad\xd7\x9b\x1f\xb7\x82\xab\xef\xbc\xd1\xb6E\x0b\x97\xbb\xa0HJ\x19\x90\x80\xb1\xed\x1c\x92\xb3V\xd0\xc1\xd6)\xcb/P$\x8a\x14\x92\xef\xd6G\xe7Z\xac\x0f\x1f\x9e\xc33\xe6\x9ar^\xc3\xf6\xc1`h\xd47%\xa2s\x13gN\xe9\x12\xd54)]\x96\x8a\xb7\xac\xe3\xaa$\xf7\x90U\xb7\xdce\xf4\xd4)\x0d\xe9\xdd,zd\x8a\xc7\xa1S\xecF\x19-\x8d\x07\xdb\xe6Rp/z\xdf,M\x96\x03\x02\xcfJqj\xe5\xfa\xd1\xa0\x0b\x93\xa9\xeb\xd8\xc65\x7fm\xf7\xc4\x8c\xd6\xf61\xde#W\xf3> \x97\xda\xb6\xf9\xaf\xb7\x8d#\x8a5\x9c\xf8\xddp8\x98\xcf\xd4\xd7\x92p3\xf3\xa6W\xc2\x92\xd0\xd6+\xe7\xc7\xb9E\x12J\x80\xc7\x8b%\xbdC\xfb\x9f\x8az\xc6\xaf\x12N\xf1\x93\xb4\xa8\x92\x89\x9a\x16\xe0a\x18\xcd\xd5:M\x86S\x82O7\x7f\xc2\xb4\x0bi\x9c\xb5\x0c\x8b\x92\\\xe6\x95U\xd5\xc5\xf8\xf2\xfa\xe2\xf0\xa7\xf1I\xc3\x9c\xfa||q\xf6\xee\xe7\xf1\xd1\xf5\xc5\x87\x1f/\xcf\xc7\xc6oj\xda\xd9\xfb\xf1\xf9\xc1\xe5\xf1\xd9\xe9\xf5\xc9\xf8\xf2\xe0\xfa\xe7\x83w\x1fx\x99\xc3w\xe3\x83s\xf6~\x8c\xf9\xde\x1f\x9c\x1f\x9c\\(_\xce\xc7\xff\xbf\x0f\xe3\x8b\xcbF\xca\xc5\xfb\xb3\xd3\x0b^\xfc\xdd\xd9\x9f\x1aYXoO>\\\x1e\\\x8e\x8fZ\xe9\xedw\xa5\"S\x0fD\xdf\xc7'\xef/\x7f\xe5\xe9\xd7\xc7\xa7\x87\xef>\\\x1c\x9f\x9d\xaa\x19\xf0\x93\x9a\xf0\x9f\x17\xcd\x0c\x1f\xce\xdf\xa9\xaf\x17\xef\xc7\x876\x034\xd8\x83\x1b7s\x9f~\xaf\x93\x9d\xb9\xf8\xf2\xea\xb9\xfe%\x91e\x9e\xe9_B\xf1\xe5\xf9S\xfd\xcbJ\x96\xd9i\x15*\xc5\xa7g\xcf^\xe9\x9f\xd2\xea\xd3k\xfdS$\x9b\xfa\xdek\xd0\x8f\x1c&/\xfaT?%\xb6z\xc7\xe8\x8e\x82,\xd30\"\xee\xf6G\xba=\xf3\xc1\x01\xd0\xf1\x96\xcdkc\xad/\xd6Fsh/q\xdd>\x1f+3g\x8d\xaej\x9e\x1c\xcd\xbd\xf5-\xb6\xf9\xa7\x1d]\x18\xe0\x1c\xe0\x03j\xe9?\xb8\xf5\xdbok\x9d\xa1\x85\xde\xc5\xec\xe9\xc2\xf8\xa1]\xe0\x06\xf6\x88\x13\xcd\xbc\xb8! bO_>w\xf4\xc5\xcc\xa9q\x95?\x8b\x86\x9e8P,\xf7?x\xb4\x9f\x86\x0b2\x02K\xf0\xa8%?\n\xac*\x85I\xf9\x97E\xaa[\xfd\x00\x0crL\x80\xf3\xd6)\x89\xb4\x1b\x9b\xfe\x8b\xa6\x0f\x87o\x9d\x1c1\xb9\xddSS\xdcsjR\x12\x16?\xeb\xa7\xed\x83A\xfb\xf8A\xf3q\"\x14D\xdbj\x1c\x03\x96U\x9av\xa1\x91a\x1f)\xdb\xd3\xfd\xbf>\xa8\xfb}\xbb\xc1\xb2\x9c\x9f\xc8\xdd\x08tS\xbd\x87\xcc\x80\xb4\x1d\xfb\x1f:\x03\x1a\x1f{\xcf\x19`\xf0\xab\x10\x96\xdf2\xf6\xcb\xc7\x1d\xbbT{\xbe\x87\x0f\x10eD\x92r\xfe\x96\x01\x9d\xfc\xb7\x18PI\xe8}\xd9[\xdb\x80\x8e\xee= \xce\x9ew \\6^\x0bx\xca\xf1\x1ad\xc3\xb6\xf16\x89\xd9iEd\xbe4\xd9\xa5e\xaen\xd1\x19W\x05Z\xf4\xe5\\|\xda}\xd9\xfa\xb4\x96Ti\x9b\xcc]\x88O/_\xb4\xc8\xdcY\xf5\xa9Ej\xdfI\xc3R\x13\x93{c=\x14dh\x1e\xd51\x04\xe9v\x0ca%w\x1a\xf3xm`\x1e\xd0\x14Q\xfa\x9fA;\xc8\xe6\x18n\xdb\xfcG\xa3\xc8\xaaH\xb5\x12c\x03\x07\xd3(\xc2\x95\xa8\x1be>\x9b\xd8\xa0F!<\xd2\xb5R\x83\xb8\xabF-\x84\xf1\xc9\xbc\xae\xfa\xfaF\xab\xf5\xd0\xc2\xc7\xf1\x8a$\xf3l\xec\xd0'\x13O\xc8\xcb\x95\x84^\xcb\x8bt\xad\xd4\x81\x81\xb3T\x0b!\n\xd3\xca\x9cup\xa9uYq\xe9m\xa9\xe3\xbd\x81\xf3\xe5e\xd3|f)ca\xa0y1D\xb9\xb6Q\x9e\x18\x99\xf1fAS\x8b\xc7\x9d\xec\xbdZ\xbesi\xfe:@\x8a\xd0\x00\x95J\xccz\xbd 4\x14\x87j\xb3\xceS\x8b\xb4\xa2QOm\xde\xda({\xde#\x051\xd6q]r\x81\x8bV\xd7Q\x05\x0c\x95\x80\xc5a\xcb/e\xaa\x8d\xcc\xef\x86\xaa\xb8\xb9;>\xba\xa8\x16R\xc5J\xdc\xa6\x9bH\xab\\zS\xe8\xd3K\xfeV\x19:\xad9\xb8\xc5\xe7\x01\xe6,\xcdGLQe\x937J\x96\x8c\xdc\x99\x10)\x8a\xce\xea\xf8\x95\x9c027g \x85{R\x83\x1c\xd4\x1a\x16\x10\xc3@\xc0\x97/\x90\xb8\x18\xb0\n\xc1\xb6C\x87\xabD\x0bqF\xda\xb1i-\xda$\x1d{\xbez\"h\x91\\\xaa\xa0\x0c\xa7\xe4]\x1e\xc6\xc6h]j4=\xf3T\xf2\xa5a\xf4t\x9e\x8aX\xfb\xe8\xf1-\x0f2r\xcbx\xf6qq\x9fN\x9b\xa7\x8f=)Y\x93t\x042\xa0\x935\xdf\x82\x94e8c\xc4GP\x90\xb0\xcc;\xcc\xe4\xd2$\xc3|\x8b\xb0\xf8\xc4OQ\xf6+`\xc9\xa8\xdb[\xbfmb\xe4 .:\xb3\xcck{\xf2l[\x05\x03\x1d)\xde6\xf7\xc0Uba\x85\xb0\x0f\xce*\xe3\"et\xf2\xc1\xb6VTo\xad\xd0\xe3&\xe0M\xd1\x88\x1bz\xec\xd0\x1fH#}0\xc4\x95\xfb[\xa5\xbf\xa5Hf; a0\xecM\xab\x86d\xe5\x85\xa8\x7f\x7fBus6`\x8f\x82t\x83\xde\xbbO\xa1\xf2\xff2\xed\x00\x8a\x15\xecA\x18L \x8d\xe6\xf6L%f\x12S\xd5\x01`\x98\xed\xe0\xc2\xc0\xe3\xc8'\xaaD\xb2\xb8\xfa)\xec\xc3?\xbe\xc2\x08R{\x91\xa9\xbcT\x14:\xc2f\xb5\xa0\x0fh, 7\xe6mXd\xdc\x91\x84\x98\xa2\xc6:7\xc2tB\x99d\x11\x81\xf5\xb3`w'\xd8\x810\x8b\xe16IS\xb8!P\x90E\xbe&1$\x19\xac\x9f\x07;\xc1\xce\x1bX\x95\x04,r~\x11\xd0s\xc3\xf1|\x0ep\xb6XW\x0c4\x18i>\xedRv\x8e10\xd9\"\x8fI*/ZN\xc2\xa8\xe8\x88*5\xc7\x12\xd5\xcdVO\xee5\xe6\x16C9\xce()\"\xb2\xa4y\x87R\xf5B\x94\xe0\x04\x8cR\xc42\xcaz\x95\xeb8?y\xe5i\xc1\xad\x9dG\xf0\xfb\xf6\xca%x\x1e\xac\x8a\xd4\xaa\xfe\xc5&\x8fq\x15\x11\x83\x88wIFNW\x8b\x1bR\xbc\xcd\x0b\xb4\xcf\xdb\xb7}h\x86\xdd0\x84\xc2\x90\xcf]\xd5\xcd\x0bZ\xd8\\w\xcb\x1b\xb7\x0eT\x8f[\xca\xe8cH>\xac\x8dN3\xe4\x9b\xb0$Gyd\xe5\x1dA\xb8\x00mB\xc8\x08b{\xf6&x\x8c\xa0c\xd3\xb7ac\x04\xeb\xae\xec-\xc0\x18\xc1\xc2\x98\xfd\xab\x17\xd09\xc9\x06\xe8WA\xe3\x8e\x95M\x98\xbd\x03\xec\xe1\xf6\xad\xfc\x1a\xd6\xae*\x9eL\xc1Mz \x0c\xa8$\x02\x0e\xba\xf3\xcf\xcc$\x06\x082\xa3y\xfb\x9f\xe1\x1do\xa6(\xd6t\x0d\x11T\xe5\xbc\x81\xda\x9a\xeac%K\x08?\xcf\xd9\xa4LWi*\xb6\xc8\xcc\xbd\xf3\x95\x14i\x15\xc0\xd2\x96\xdc\xc8\xb5\x91\xbd~ \xfe\x9a'\x99\xeb\x04\x8eZ\x04)\x15FU\xcb\xd8\x93$\xa0\xdcE\x9b\x9c7\x1f\xb5s\x84\x8b iu\xccr\x9a\xef\x93\x89\x0f\x8e kz\xa3?\xcb\xa7\x11\xcf\xaa#\x10\xa8\xfa\x08\xb9! Dc\xbd\x85\x86X\x01\xda\xa1\x8e= #\x13/qV\xc6E\xf1#j\x99\xe4\xdf`9XhWfvS\xaaVr\xcb\xfc`r\xa5\x1dGo\x85>\xda\xa2&\xc6\xd8kZ\xbf\x96\x15Y\xcdh\xc7\nh\x81X\x03\xdfQ5b\xa8\x0f!\x0f\x80\xe2C\xec\xc3\xdc\x87\xb5\x0f\x0b\x1f*k\xdf[\x1f\xc6V\x85\xa1\xba\xed\xdbb\xd0\x86\xc1p\x0bo\xdexP\xde&\x9c\xca\x0f\x96\x05F\xfc\xe2\xc1\xd0\xbb6Z\x14\x96\x04vF\xddk;\xe5\xe7\xd7\xdf\x82\xf2\xae\xa4d1d\xe3\x12\x19\x8c\xf1y7\xdc\xb0\xe7\xa6 a;\x92\x9a\xfa\xd8\xc1\x05lH\xc2\x89\xc9\x8d\x00\x1e\xe9\x05`\x04q\x9e\xfd\x9e\xc2<\\\x13\x08\x81\x0f\x06h.\x0c`\x08\xe4\x99\x0f\xe1M^\xd0$\x9b\x05\xdcaQxS\xac\x96h\xe2\xc1\xda\xb0\x05\x07\x069\x93\xcf\xfbg2\xd3yQ\xc1\xc6\x92\xa2\xa8)d\xc1\xb1N3\x1fi\xe2\xbc\xa2\xf2\xf8P8\xef\x97#E\xaaS\x9e\xa1\xa4\xfc\xade\xee9\x04\x94\xd6\"R\xe8`\xacK\x0dw\xf3\xb6\x87U\x1eb\xe8\xd4\x14\x91\xf0\x12\x91\xf0\xa2\x1fh\xe1\x1bp\xb0\xe9\xf9\x16\xbclz\x86\xe0j\xd3S)\x14\x8au{\xeaw\x99\x1b\x9a\x1el\xf9\xe9\x83[\x0e9\x91K2\xea\x0b\xb6\xbc \xe5*\xa5'\xe1\xd2\x17\xbc5\x83\xf2_\x12:?\xe4\x0e=%\xcaV\xa0\xed\xa5\x0f\x89\x9b\xe2\xf9z\xbfi\x93O\xc5tL9\x1f6\x8c\x96\xd2\x1f\x13[r\xf7\xb0\xaat\x96\xe5\xe6a\xd5\x98\xd8\x19\x83\xa2\xd2\x90\xc7\xc8\xea\xdc\xde\xbb\xaa>bQ\x7f\x10\xbc^>\x18\xbc\"\x05\xbc\x96\x88x9\x9f\xc4\x8f\xba\x88sWP\x04a\x9a\xe2 R\xba\x1e\xf7f\x86\x8c\xcc\x10n\xc9\xf6\x0c\xe4\xa2lO\x9b\xbbZ\"w\xb5\xd4\xcc\x16\\.\xa1\xb8?\xfbdz*l`b\xa0\xe6\xee\xfa\x7f\x1b\x03ez\x1e\xc2T\x99\x9e{3Z\xa6\xa7\x9f\xf92=\xa8Pm`\xba\x16\xd2\xbd\xf6\xac>WW\x885\xe3\xf6\x87\xb4\xfa\xd0\xa2\x83\x1e:\xbd\x15f\xef\x94\x10u=\x96\xa3`\x04\xf6\x08\xf0\xb6\xe7A\x88h\xf7\xfb\xfba\",\xe4\x90,v\xeeW\x0e\xd4\xcdX\xd2|i\xf1\x91cz\xba\xa9g\xf9|\xc5\xe8\xf1&G\xb6\xc6\xdc6\xc9\xa4\xfa\xb4\xae\xf0z|)\xa8O5Xs\xd0\xcf\xde:\xba\x07\xfd\x95Q\xc3\xab\x8an\x13\xb8d\x00bW \xd6\x9d\x9a\x9c\x0d\xbb\x93\xab\xcac\xcfR\x9a\xd0\x074\xff\xcf\x8b!D\x84\x15\x9c\xa7\x8a\xc8X\xd4\xd6=\xc0\xae\xf5\xe1\x90\xdb\xc3~\x8e\x95\x83\x92{-\xafxz\x1f\xaf\x8dx0\x10I&>\xed\x06\x07\xe4\xf1\xfaz\xf4\xba\xbbG5c\xf1\x1aO\x87\x1d\xec!^V\xba\xbb\xbb\x9e\xafK\xfe\x02j\xbb{\x80\x8aL\xed\xa1Sc\xb3\xa1\x83\xcb\xc6>\xae \xd3\xdef\x9e\xd9\x9b\x19\x8a\x11\x86\xec\xfe6\xd0\xab\xbb\xda\x87\x89\xb1\xd4\x841j\xbb\xaf\xafZ\x1f\xaf\xda\x0e2\xe0\xd9\xf7\x0d\x9d{\xab\xb5\xc77^\xec\xffM\xc6\xc1\xf4+\xa8\x03\x0cC\xfaV\xf7LX\xbd}m\xdb\x02\xdc\xd3\x11x\x8fJ\xdcy{\xff~\x8b\x8e\x9fT\xd8l\xaf\x99m\x80\xfe\x10\xdb\x1c+o\xfdO\x1a\xdd\xc4\xe2\xc0F\x0cO\xc5\x83\xf7\x1bi\xcb0\xe9[\xd6\xee\xf0A\xa3\xab\xb4\xa5\xcdC\xe4.\xc1\xef\xbd\x84]\xf6X\xdf\xae'\x7f\xf1\xcf\x18\xe9#\x98\x13\xf0\xb058\xea\x9f\x85\xe9\xc2\xf0iS\xb7v\xd3\xbc\xed\xc1j\xae\x03&\xa5_=\xd7\xfc\xb9`'\xb6\xc9\xcd\x81e\xc9>uAK\xc3\xb8\xef\xbf\xe7h\xffv\xaf\xd1\x1e\xf4\x8c\xb6e\xe0\xf8\xbfa\xd0g]\x83n\x18y\xf6\x1e\x9c\x1d\xe34\x8c\x857\xff\xbe\xab\xf9\x96\xd9io\x17\x86*\xe5\xd9Tn\x8aa*{\xf9P\x95\xbd\x95&\xeb6\xe7\x12\xf1\x06\xc3\xf2YOu)\x12\x96\x0c<\x18\xca3\xe7\xe1r$qW`\xcc1\xc5\x1c\x95\x8e\xa8\x05m\xc2\x1e\xacl\x9c\xc1\xfd\xb4S\xac\x9a)\xe6\xec3\xbc0\xe0\xacD\x9b|M\xa6\xe0\xce\xe0\xc9\x13\x98)\xa1\xc7\xf4w)y\xd2\x93\x85{\xd2~\xf1\x93\xa4iY\x0d\x1bBK\x86{\xc7\xaa\xcf\x89\xf6\x1e3\x98\xa5w\xc6\x0b\xcf;\x1d\x07\xb9\x93\xd4\x87\xe8\x8am\x84\x8c\xad6\xd2X^\x17\x9bJ\xd4)\xd9k\xbe~\xf9b\x8d\x1f\x00\xca\xd6P\xcbLx\xc3\x1d\x1e\x0c\xdd\x0dt\x0e\x8e\xa1\xfcv\x84\x8b\xa52\xf9;w\xda\xe1\x9a\xea\x82=p\x0c\xbe\x97\xc0\xcc#\xa0H\x07\x83\xc8}\xa6\x1f\xaa\xc8Lq-\xfa\x91\xcaH\x01\xcd/\xd0\x12\x96\xb1\xcf\x02<*\x00?\x8eQ\xc8\xa7\xbe\xefi\xdfG\xbcP\xca\xfeD\xa2\xf3\xcd\xfcY\x90/\x8fcw\xc6\xefc<\xd4)\xe5d\x96k]\x136\xa97\xb0\x07)l\x823r`\x13\"\xf3\\2v\xb6\xe0\xb1>\xca\xa0D\x1c@\xe2\x0bLro\x90ko%w\xe8_]\x8bjX\xbe\x9f\xc3\" oR\xd2\xa5\n\x05\x18,\x9d\xe5\x1eU=\xe9\x96\x08\xb0\xa5,\x97aDFpc\xcd\xf8\xb5_\xbap\xfb\x08=\xedo\xbf{\xce\xabv+\xf7>\x15t]{\x12\x91\xec\xc35\x8c\xe0\xd6G5^=R\x1d\x0e\xa2\x9d\xec\"\xa0\xf0\"\xad\xa8u\xa2L+\x9d\x17B\x87!\xdfm\x7f\xe7\xd8\x17y\xac\xb6\xfac\x1es\x9c\xc4\x8b\x9bK\xb1\xc1\xdd\x05I\xf9\x9f\x17g\xa7\\0\xed\xb9cT\x8cW\xab\x81=`\x19\xb86\xbc;\xf6F0f\xfba\x8csi\xc8<\x16\x93\x0c\xa3\xf6\xa7\xf6\x86n\xa5\xb0\xa1|\x163\xaf\xb8\x01\xf9\x07z\xe6m\x8f\xe33\xee\xc4\x9bU\x92J2\xcc\xfd\xec\xf9P(\xc4\xa8\xab\x1c\x90\xf5A\x08\x9f\x0d\xb5\x11\xc3\x11\xa6R\x19\xbd\xfeq\xd7\x0d!\xe0\x84\xea*:\xea\x93\x9bG\x99u\xab0\x16m\xc2\xd32\xc0\xbc\xe1\x9bD>_U\xf8k\x0e\xd3p\x97\xcc\xc6u\x01{p\x14R\x12d\xf9mG\xa8\x9bLRg.\xd1\xd5\x05\xad\xd3F\x83x\xc5Qj\xa3\x0d\xd8\x82\x8bj\x0dyO-c4\xa8O}\xf5\x84\xa0\xad\xbfyuJ{\x1a\xea8c\xb9\xf6F\xd7}\x0b)\n.^\x98\xab~m\xccg\x9ei@\x8d$\x0b\xafI\xdan{\xf4aK\xf5\x04\x83\xa3\xaf\x1d\xab\xa3\xaf\x9d\xa6\xa3\xaf\x9d+T\xe37P\xef\x15%\xda\xfe\x96uR\xa0\x89\xd8\x07\xb9b\x9e\xc3}\xfeP\x0c1\xc9\xcb9Wf\x1fi\xdd\xa4\x9bT\xd2$\xc14\xebR\x9a\x0f+}\xd5\x01\xf4;\xe9\xe7\x07\xca\xea\xf6\xdf\x16\xa5\xce\xed>\x0c\xb9\xfa\x80\xe6\x1d\x8b_K\xd8\xa9\xfc\xb0\x1d_W8x\xednl\x8a\xf7\xc9\xed\x03\xcb\xce\x08D\xa6\xa3\xca\x9c\x9d\xd1J\xdb\x9f\x17\xe9v\x12P\x86\xac\xa6\x96N\xccq\x00\x15\x81\xd8\xe8\xbe\x0f\xb1\xfd\xec\x16\x80\xb0\xd2\xb8C\xd4},\x9a\xb85\xb1md\xa1\xfcm\xd1\xbf\xe7\x8a\xdf\x96\xa5\x96\xd8\xa2\xdfb\xd8V^\x92\xc4V\xednS,\xdc\xa9\xa5\xab\xc2\xb4\xd9b\x9fa\x0c\x97\xbb4\xa0\x1c+\xce\xc1_=\xce\xa8H@>/\xf3\x02\xfd>7\xe7\xbb\xb2\xf1\xcd\xdc\x97\xcf\x9ej\x90P\xdb\x087\xbdO\x19\x9b\xb4\xb57@,\x89\x91]\\n\x00\x12f\x11\xbaUD\nKA\x80\xe8\x11\xb4\x80$\x03\xe2\x01\xde\xea\x03\x9b,T\xb4p\xd1\x1f\xeb\x08\x92,\xca\x8b\x82D\x14\x92l\x9ds\x07x\x1b\x16W\x8e\xe4~3hv\xe7U\xd9(\xb9\xaf\x9f+\xcdT\xc3\x0f\xa6CD\"\x19\xb9\x1d\x805Y\x8f\xda{\x8d\xd15\xc1\xb2\xc8\x17 \x8a4YUdX\x9096\xe9\xca\xfcRm\xbe\xb3\xf6,;?\x861\xbc\x17mEyV\xd2b\xc50\xb3M\x97\x11O \x1f\x0f\x1b\x83\xbc\xd6\xf3y\xe7\xc5\x05*\xcb\x84\xbe\xe5D\"\xa3~1M\x0b.\xf3U\xb5;\x1c\xb4t\xf5\"}\xbfcZ\xa4\x01bB\xd4\xb0\xe3GW\x921\xd8D~\x9aLrv\x16\xe3\xbf=\xa0\xec\xdf\x08\nVG\xee\xe3\xeb\xbf\x04\xf2^>\xdf\xb5\x8c\xaax\x8c\xea_\xbd\xb0\xd4\xce@M\xd7g\"\x9f\x97i\x12%t\x04\x13\xd6\xb1\xe7\x8c\xe0u_>\xff^\xfc\x7f\xe1\xa9\xdeP\x1f\xde\xbb\x0eJR\x99\x97\x17\xbb\x167\x93\xec\x9b\x8e\xea@\xd0=\x9a\xc7\xca`s\xeb\xea\xbb\x91\xb7\xef~\xdc\xfe\xb8\xed\xed\xbb\x93\x8f\x17\x1fK\x0c\xc9\xd9.\x1eb\xf1\xc9\xc1\xd6\xff\x1f+\xe0\xffw\xb6^on\x05W\xdf\x8dX\x05\xdb\xedB\x8c|\xb1\\\xad:\xff\x86\x9e#\xc3r\xae\x87\xf3\xae\xb3\xec\xb3,\x7f[\x91\xe2\xce\x9eg[\xfatDG\xca\xd6l\x7fd\xd9\xc2\x15\x92x\xbb\xb6\\\xa7\xe1)\xeb\x13\x8fH.\xaf\x86w;\nl\x8f\xdc\x8f\xf1\xa6\xf7\xef\xdb\x18\xc8\xbch\x14\xebo\x04{\xac5\xd4*c\xa8\xa6}\xce\xc9\x87M\xe7\x08v\xcd-\xe3D\x8e`\xb7\xf5Q\xf5# \xaa\x9b\x8d\xd4\x8e\xaf3\xaepo\xb3\x94C\x015\xfa\x83s+\xc3m\x1a\xa4\xe2\xd4\xe2\xc2@\x8bp\xd5\xb9I\xf3\x9b\x91#d\x9e\xcb\"\xa7y\x94\xa7\x1e\x87{v\x96\xb8\xab\x8c\x94Q\xb8\x94\xbc\x13\x9bF\xcf7WH\xd2\x92\xe8\x8e\xea\xf6t\xf7\xd8\xf2A<\x981\x1cX\xb7E\xb0b\x1fJO\xeaz\x14\x93\xcc \x91\xac\x1bR-\x99\xad\xda\xd6uS\x84\xa1\xdb$\x03\x94\x90\xba\xacr6_\x93LG\xaf\xf2Ql\x14\x8a\xa0L\xc3rNP\xfc\xec\xd6o\x8c\xb0\xa5\x9cQ\x9f\x17dj\x8a\xfa\xd3J\x91\xbc\xe9\xef\x9a\xd9\xccp\x11u{;\xad\x02\xfaZ\x89g\xf3\xa4\xc8\xb5\x1e\x01\xe5\x0e\x9f\xd9\xbf\x80\xe6\xef\xf2[R\x1c\x86%A)\x8fc\xb1v\x17\xa3\x1f\xc1\xc6\x06\x9d<\xb5\xec\xbe\x82\x94\x94U\xff\xac\xbd\xd1\xf4+V\xf3\xd0\xa7\xb6C\x14*J\x8f\x1d\xf1*\xb17\xad\xbdPW0E\xcd\x82\x176\x83\xdc\xec\xa9\x94\x1a\xf7sn\xc1\xb0\x12\xc1\x91-\xdc\xcc\x02j\x97\xdd\xe6\x1c3\x96c\x9eX\xb8\x8a;\xd8\x83\x9dv\x7f\x10L+\x88f\x84\xd3\x02\xad\xf5\xe5f\xaaR\xb8=\x8e\x8f\xcb\xcf\x1d@s\"B \xfe\xb3Q\xf50\xabJ\xe4\\\xcc\xe7\xf1\x82)RH\xec\x9c\xdap\xd9q\x13\xb9\x84{.\xf6\xbc\n\x0f\xe0\x85H(A\xdd\x87Y\x03\xea\xe5\xef/_ \xe1\x1eu\x95\x8cU\x15\xc8\xf8\xc9\x17DL\xea\x9b\xe3\xf8\\l\xc1h7\xea7ku\xd7\x93\xa7l\x83N\xb6\xdd\xe0;o\xbbq\xf4xo\xe0\x0e~\x80\xb5\x10s\xbc\x81\xbb\xcdM\x0f\x91\xb5\xcbx\xd8\xf5\xe4\xee\xca\x9b\xec\\\xf9\xdc\x12{\xb2{\xe5C\xc9f\xa5\x84}\x98M\xe6\xb8\xef\x19|\xb7]j\xb2\x1c\xff\x8f\x1b\xa3,@\xfaX.=~\xc9\xe1dh\xfe\xa2f_\xb2>\xee\x83++\x15\xa0\xb3#tT\x95\xa4\x1861\xb7\x87A\x87\xb5\xfczf,\xcfs\xc6(\xfc\x15\xbb\x9c\xf7C\x14\x8eq\\z1\xdek\xcf\xf3\xe5@\xf1\x9f\\\xa5\xe5\xe4\xd9\x15\xae\x96Hd+\xb0\x9c<\xbfR\xebe\xff\x9a\xa8\xc0\xb0}8`\xcd\x02<\xe9\x90\x14\x12\xbf=\x84+\x15 @\xf1c?\xab\x8e\x91 \x9a\x87\xc5\x01uw\xc4\xdc\xea\xdfy\xef8GQ\x9f=\xa2\xd5*\xd3\x00?\x11\xa0\x92\xdd\x18\xe9\x0c9\x14g\xdb\xf1\x82r\x99&\xd4\xe5?\xe5\x0cn\xedz\xd2a5Q2x\xbep\"\xc1A\x8e\x1b\xbce\x93\x02\xb6\x18\xfd\xc1\xb7\xd2.7s\xdby\x03\xc5\xd6\xd6\x1b\x0f#{\xe0M\xd9\xa4\xb8B\xcf\x19\xac\xba\x08#\x13\xec\"~\x0d\x9a\x19\xdcf\x0e\x1fB\x06\xd6#\xee\xb7\xc3\xdd\xa9\x03Z\xb8 \xf7j\xe0C\xab\xc4\xd6V\xb7\x94\x19\xd7&\x0bVY9O\xa6\xd4u\x1c\xcf\xc7~\xb2\x89\xceq\xa9\x82\xea\xed\xcb\x17\xc8\xb8\x0e\x1cf\xcb\x84\xce\xfc\xb6)\xa2\x8a\xb2*\xbe\xbabl\xde\xd8\xb7\xbc\xa0*f\xe0\xfa\xa93\x19a\x97\xff\xe0\x85yf~{\xc8\xdeV%)\xc4b\xb36\xca\xf26/b\xfc\xcc\xbe2B\x13\xa7d\x89\xdf\xd9\xab\\\xb5Q\xab\xfcr\xb2S\x81}\xa3.\x86#\x04\x02d_\xf2\"\x99%\x19oP\xc1\x86\xa2\xbb\x88l\x93\x94\x8c*\x98\x95y\xf6\xd5\x97Mp\xb6\xb7\x1d\xd8\x94\xc5F\xe00|\x8dM3b\x01\xab\xaf/3\xb53Q}\x9b\xf2J\x85)B\x1b\xc4KBG\xbd\xac\xa7|\xf0\xe0\x13'\x94\x19R*\xeb\xaf\xae\x0bh\xae2\xca9\x86n\xa5\xd1\xdeX\x17\xd2\xdd\x84\x8b\xd4\xaa<\xa8x\xa0\x85d\x82\x17\xc9=\xe6_C4{9\xd7\xd0c\xee*Zc0K}H\x14p\xdd\x17~1\x12 \xb2I\x05\xb2\xd5\x95/\x0f(o\xc8Q\x8d\xc3\xe92\xd7\x84\xa1#\xa98\x9a\xa1\xa3I\xf8\x96\xe2\x13\xbd\xb9'\xba\xcbS\xd9$\xcb\x1e?\xc64#O7\xb4c\xdb\xa3\x8f\xf1\xe6\xbfos\x1a\x9a\xb2Yv\x85\xffxe\x0b'\x12!\xd0`\x99/\xdd\xaa\xc3bSS\x81\x96F\x8e\xa7\xcc\xbf\xfc\xa8\x14\x7f\x9c\xc9\x97 \xd17F\x95\x08\xa2\xcd\xf3\x94\xf5\xa9\xa6\xa56z\xa2N\x0f\xeb\x95\xa4\x8d\xfa\x94\xbcQ\x0c\xd0o\xf4=\xc8\xd6\x13\x0dW\xd9\xc4V\xad\x0b'3\xfbx\xe0\x8f\xc0\xf97\xcb\xb5\xb6\xfaHhP(\x82\x0da\x16\x1e\xb2M\x05&\xe5V\xf5\xf9*X\xc2\xc7@\x15R\x8c=\x08~\x8d\x99\xccF\x1f\x15\x05Rr\x02\xa1\x84\x1f`U\x91\xaf%;\xe7\xed\xf3\xcd\xca10ZM\xca\x0e\x0d\x9dT\xd2q\xc9$\x9d\xec^\xb1\x1e\x8a_\x1a5w\x8fnK\xa2\xa1>\x11\x93\xc6\x89\x98\x18O\xc4D=\x11\x13\xc3\x89\x98\xe8'b\"O\xc4\xa4\xa1\xde\xd3\x0e\xeei\xba\x9f\x14\x05F=\xb2o@\xd7vMNI\xf1\xa5\x8f\x04\x89\xf0\x8c\x84\xf5%\xd3\xbb\x0e\xcd\x1b\xca\xe5\xd1v>\x0f@\xc6\xc9\x95\xe3\xb7\xd0e\xd8%1s\x85\xdc\x04\x85<\x1c\xb7\x18\xa9\x88B\x07\x81\xb8;\xfa\xc4\xe3\xb4n\"\x1d)\xd0\xcb>\x9f\xf2\x91\x1d\xf9U\x97\xfc\x15\x9d\xc4 \xcc\xcd=%\x8d\x11\x7f\x15\xb9T}\xe7\xc7H\xfd\x05I\x7f\x96\xfeGG\xfe\xcc\xf8J\xf3\\\x92\x10\xcf\x87\x8d4X\xa6\xabY\x92\x95\x93\xec\xaa\x0biR\xb9\x86\xe35\xc9h)\xeby)\xeaQ\xab\xe9>5\xe4)G\x03\xb2\x167\xab\x1d\x1e\xad\x14D\x9fd\x10z\xb0r\xc3Iy\x85\xeb\\z\xb2\x17\xaf\x1c\x94;\x19<_\x82\x11\x17\xab\xd7\xb4\xed\x95\\\xd9h\xfe\x94w\xf94\\\x90\xa3\xa4\\\x864\x9a\x0b\xedd\xb6\x19\xcen\xb3\xcaP\x99{\xc9b]{\xed\xa0*BGY!8m\xceA\xad\x8f\xb1\x9c\x87%\x89\xcf\xc9,))\xd7q`uhS\xc6A\xcd\xb0|\xd5\xfc%l\xfe\xacR]\xaeS\xab\x0d\"\xf1<(\xdd|\x92\\\x89\xe9\xe8\xd9\xe9P\xa3?=\xae\xed\xefLy6HPh\xc3B\xfcR\xba\xed\x0f\xa2\x07>c\xd3;\x17\xaf\xb4/\x9e^'\xbfB/\x19\xf5\xc1\x17kwg\xa7\x02\xe7\x8e\xccH\x06\xb7s\x1c\x91%\xc9b\x92EI\x95M\x01\xf1Iv\x15\xc4J\x0ee\x10\xf2\x97\xa4K\x9a\xfd\x16\xfb\xaam\x95e\x83\xa7\xb6\xda\x91e,\xfd\x19\xd5!\xb5s/\xf3\xb2LnR\xd2\x82M\xe1\x01\xa0 \xa1\x19;\x9e\x10y\xbc\xc7\x11a\x8c\xc9>\"#\xafVf\x97\x9d\x81u0\xba\x8a\x83\xe7\x92&~0\xb0\x95\x0bu\xd6\xbf\xa7\x1b\xe5\x8fw\\)e\xc0M?\n\xa5,\xb2f.\x0e\xc3k\x11\xeb\x0e#m4\xd1G\xa7\xe6\xe2N\xc5\x8e!\x133\xeeI\x10\xadH\xb9\x93\x8b\xafr.\x9f\n\x9c\xc4\xf3\xe0\xad8\x17\x80\x0dD\x9fH\xa1\xf6L\xf4\x8c\x88 \xe6\xc0\xf66/p\xd2\x87\xce3 \xe2\x06T\xb7\xc7\x8flUk\x13V\x17\x16\xf6\x1d\xdc.\x84\xb2*\xb3[g]\x1b\xc3\x86\x8e\xbbNqn83\x08\x8f\xcb\xa7\x02)\xd4\xac1`^\xf9\xe0\xc9\xaeC@\xd1 V\xa0\x80\x96}\x96\xb2Iq\xd5\x01uP\x1f:b\xc2\xdbQ\x85\xe4\xd3u\xfe\xcaG\x92\xcd\xab4\xed\x82\xaa\xeb\x82\x94\xa4\xb1}Gv5Nh\x11[\xb9\xb8\xe4A\x8fg\xad\x8d\xc3\xe5\xe1\xe2\xb2\x94\x91]\xed\xe1Wd\x8e\xe4'\x8c\x97O\x12\x88\xedg~\x1f\x12\xa1\x1e\x0f\x9e\xdb\xde\xd7\xa2{\xd4\x88\x13$Yk]\xd6\x8evC\xbc>\xf6\xa0\xd0\xdb\x0d\xd5v\x8bI\xd8\xbc\x804j\xd9\xaa\xf4;_\xcf\x87S\xe9\xdc\xa3\xa2\x99VG/\xd0\xee\xd3\xdd\xa7\n\xdd+Hw\xf7\xb51\xfe\xc6\xaaC\xdd\xad\xa6\xb9P4\xfc\xe5\x0b8\xab\xecS\x96\xdff[\xb8\x8e\x9a\xf0\x85\x04\x11w\xe9p\x19\x163B\xf1biF\xe8i\x1e\x93\xb7E\xbe8\x16\xf7\xa8n\x81\x97\x84\xfb\x10\x06I\xb6\xce?\x91?\xad\xc2\"&\xf1a\x98\xa67a\xf4 }Cp\x7f\x99\xd8-\x82W\x14\xe6\xbcU\x16\xdf\xd0zc\xef4\xa9\x8a\xb6\xdeER\x8e\xb38)\xe7}\xf8X\xecK\x87\xe6\xcb\x93|U\x92\x0fK)\x94b\xd3C\xf3\xe5e\xbe\x8a\xe6\xe3,6%\x1f\xb2\xf1\xa7\xe2K\xd7\xb6N\xca\x93|M\x1e\xd0\x1dV\xcc\xd4\xb2\x92\xde\xdd\xee\x05\x0d\x0b\xfa\x80\x86\x8f\xf2\xdb\xcc\xd40\xd67\xa0e\xa1\x82{\x94\x14$\xa2\x129\xf4u\xa2>\x1c\xaf\xe5\xe9\xf8.))\xc9\x88M\x0b;k\xe6\x960i\xc0\x03M?T\x94\xd3\x10\x8cXx\xe6\x18\xa1\x8dA\xb4\x19\xde3\xcf\x18\x18\x18\x14\xfc\xc4\nS\x97\xd83J\x95<#\x90\xfb\xc6 0}\xac\xc6[},\x06-\n/M\xca\xe36\x95j\xb9\x16]WV\x80C\x97\xa6\x18\xbc4\xec\x9c\xd5\x9d0w\xe8\x01I4\xb6\xf3\x06r\xf8\xa1v\xd5\xfc\xe4 l\x90 )\x19b\x0fg\\[\x9e\xe6\xcb%\x89]\xef\x0d\xe4\x9b\x9b^\x8d\x1d'\xf9\x95\x0fE[U\x12\xa4\xc2\x10^X7\x90\xa9!\xe3\x03W\xe9!K\xc4Fr@/\x8b\xd5`J\xbe_\xbay\xff\xed\x06\xf7\xdar`\\[\xdaI\xbc)\x84!\xbf\x19\x87\x1f\x1a7\x7f\x1d+\\lnv;\x18B\x8azR\\\xb1Ue\xe4\x9f\xa2\xfd3)\xdajG\xa0\xdc\x15\xa0\x87\xe0'O\xd8\xa6\xe6\xc1\xb3e\xc1n!\xa9\xbe\xd8Xe\x97\xfaU\xe7\xde\xee\x847\xda\x05U\xf3\xb0\xac!\xaa\x0f\x80\x14\xf1E\xbb\xbd\xaeV0\x9e7\xef4C\x98\x0cq\x0el\xab\x08\x0ce\xf5@/\xed\xd6t\xd4|\x9f\xd6Zh\xbd\xbb\xb5\xa4<`k\x81\x0e#{\x91\xa5\xe4\x18\x82\xba\x14\xcf\xdb3\x9ew\xf9-Zw,\x16y\xf6\x90\xe6,U\x0cj\xfb}\xc8\xce\xa1{\xce$6\xd9,\xd93\x8f\xb4\x08\xd7\xa4(\xc9\xe5m\xfe\x9e1\x8c\xc3\x14\x11\xaa\xe6\xf4\xe2U\xa1!m\x8e3J\x8aw$\\\x1bZE\xd7\xe6FYu\xab\xed\xba\x1a\xadp'\xfc\xa0\\&\xc93\x93g\x0f\xfe\xf10_,\xf3\x8c\x11\x03\x05\xe9]\x00\x90'l\x1b\xbf\xb4Q7\xaf\x9fU{\xc9\xc7\x10\xa6C\xea\xcf\xcd\xf5\xff\xce\xfcfa\x8f8\xc6x8{\x042 U\x95\\\xf1:\xb9\x0dd\xcc\xb1\xaah\xcb\xa4\xa33j\x14kUQ\xa1\xc2\xc9\xee6\x86\x02\xe5^M\xe3FL\xccN\xcb\xca\xac\x9b}je/\x08\x1a\xca\x1c\x86\xab\xd9\x9c\n\xd7\xe1\x9d\xb2\x02v\x8aY\xcdr\xd6\xc2&\xd4\x12\x14\x86\xdb\xe4\x14\xf5Y\xf4\xadp\x91<\x1c.\xcc\x164&n\x97S7\x94\x13\xd7_\xbe\x00 \xca\"\x1a\xa7dA2|\xbfM\xb28\xbf}\xa3O+\xdb\xef4@\x9b\xaer\x99gq\x92\xcd>\x94D\x96\x93\xfaG\xd6\x1c\x9e\x0f\xcfxh\x9c \xcbc\x82F\xfd\xfb<\x8c\x1c\xc9\xf0\xe0i\xe8(|\xab5\x8e\xd0-t\x9f\xaa\x163y\x10\x85\xd9\x87\x92\x1c\x9d\x9dT\xe0\x1b\xe7\x11\x1a\xef\x06\xc9b\xc9{\xca/'\x9f<\xb1}\n\xe6a\xf9\x96\x84tUH\x7f'\x1b{\xd6z\x94\xcc\xae\xe3\xf8\xa8\x1d\xdc\x98\xd9\xed\xef\xbekB\xcdwp8'\xd1\xa7\x92Af\x98q\x81?$%\x94\xab%[_\x1e\xc0\x89\xce \x08.IP\xc7\xe82=['E\x9ea7\xb4J\xf56N\xcf.\xc7#\xb8\x9c'%\x8f\x0f\x95\xe5\x14n\xf3\xe2\x13\x08\xa3\xbd\xf4\x0e\xa9\xce,\xcf\xb6f\x8c\xc6I\"\xde\x13\xd6\x8fh\x0ea \xbf\xf1H\xca\xbf\xf9z\xd5\xbf\xa1\xb8\xee7\x1f~K\xf30f\xff\xd1\x08\xfc7\x1f\xa3Q\xfd\xc6\x1ds\xfc\xd6\xd7\xc1\x1f\xf3\xa2\xc8oK\x98\x16\xf9\x02N\xf2\x98\x14Y\xf2\xf7\xa2\xaf\xd4\x1f\xd1^\x14\xfe\xc1\xb5\x0f\xbe\xd6\xd7%\x17\xab\xe94\xf9\x0c(D\x84L\x98\xaf\xcf\x02p\xa24\x89>9z\xbdUE\xfb7y\x9e\x920chq\x89K\x8e\xab\xc3\x16\x07\xd7@$\xa2\x9c\xb7\xb1J\xed\x1a\xa51AU#c\\dE\xedenW\x90\xb036\x0b\xd3\xd6\x874\x89HV\x92z\x9a\xe0Y\xb0\x13\xec,\x0b\x02\xee\xe1\xaa\xa4\xf9\x02~\\%i\xec\xc1\x1789\xbe\xd4\xcao7\xde}\xbb-\x9e\x8eL\xd0~@\xddS_\xbe\xf0[\x82\x0d\xd7 \xe3\x18\xe7Z\xd2\xc8\x0e\x83Z\xb9GjVA\xbfY\x91\x1c\xb5\x93g\x0el\x9a\xfc`\xa1PP\xad\xecM\xbbOF\x92e-\xae\xa0\xab\x8d\x1a\x15$\xa4\x12=\xb9N\x9c\xacM\xea\x1daP\x12z@i\x91\xdc\xac(q3\x1f\x84\xb3\xe47\x8e\xd0\xfe7\xaa\xc2\x84\x93\xcc&2\x05\x85\x9d@Mb\xae\xbdr;'\x95\xd8\x0c\xa4~\xf2\x10\xac\xc2\xef\xe6\x03^\xde\x07\xe7Y\xb0\x83\xaa\xd6\xc9\xa3!\xd3\xd6\xd1}\x90\xd2\x118aJ\xffL\xee\xf4\x90\xbayF\x8b<\x1d\x81\x13\xd1\"m\x7f?!4\x1c\xa1\xdb\x82\xb0\xfd\xf1b\x9eLY\xcd\xa8W\xcd>\xd7C\xb0\xd0:\xb6\x03\x0e\x0dW\xb3\x90&k\x82\xf3\xd3\x86\x12\xf43v\x92\xc7\xc94!\xc5\x05\x0di}\x8d\xd4\xfe\xd4bO%\xa0\x16\xad\x1b\x83\x8aS\xc43dc\x83\xaa\x90PC\xc1\xb0\xf3\xbau\xcd\xf2\x08K\x99\xb9\xaf^\x1b\xd4_2\xf7e+=\xe1j1\xbb\xdcv\xf4\xd9k\xfc\xf7t\xf7\x95\x1e\xfd\x9a\x8b\xe4w\x9f\xeb\xe5W\x98\xfe\xec{\xb3X\xbe4b\x151d\x93h\x92S\x18\x93\xdd+!\\\xa7\xe8\xb5\xf8\"\xb9I\x93l\x86\x1eu\xa6IQ\xd2\xc3y\x92\xc6\x86)_\x8b\xab\xf6\xc4\xedc\xafH\x90d%)\xe8\x8fd\x9a\x17\xc2\xb1D]\xa1q0\x91\xad\xaeB\xd4\xc58\x0dQ_\x8b?3\xe94XM\xb7Z3\xb3ob\xdcl(07+\xeaTaK\xec\x840\x8fI\xa4\xcc\xb8]\xb8\x95\xba\xdc\xee\xba\xe0\xd7\xf7\xdc\x82\xbdCk4\xafh_\xf5\xd1\x88g\x1c\x1cZ$Q\xb4\xdaA\x91s:l2\x97\xd6\x03l\x88\x1c\xae\xba\xcf\x9d\xec\x1a\xee\xdfb\xac\x1b?\xef\\\xf1;v\x12\xf0`\x9b\x08\x89-\x0eK\x0355+\xed\x1eFl\x83\x89\x8e\xe5\xab\xc4\xef\xddK\x87|P\xcfR5\xfbZ\x0cc\xfc\xe6\x0861\xa3\x15\x8b|U\xa6w\xe7d\x99\x86\x11a$?\xe3\xe3N\xc2\xe2\xd3j\xd9DS\xeb\xb6k\x8c\x9e\xf2-\xef \x05\xcfuD\xd2d\x91P\x12_\x92\xcf\x03\x0d<\xe4\x84\x11\x8571K~\xf9\xbda\xe7\xb4\xe6\"\x1c\xe8>\x17\x9e\xa7n\xe1\xeb\x14\x08\xeb\x19\x8a\xf6\x18\xe4\xe4x=\x02\xfb\xe0\xae\xf0\xde\xcf\xf3!v\xf9u(E\xd5||\xeb\x95]-\x8b<\"e\xf9\x01=\x14\x97\x03\xc4e\x0d\xeb\xae\x9d7\x90)\"\xe67\x90\xd9u\xab+\xf0\xb2\xea\xabHS\x98\x02oXm\xf5@\xa5]\x7f|z1>\xbf\xbc>98\xff\xf3\x87\xf7=j\xf6\x88u\x0b\xe9\xd8\xc7\xe7GJ\x11\x84SJ\n6\xa7}\xd1\x0d\x06\xd9\x05\x9c\x9c\xfd<\xbe\x1e\xff\xe5\xf8\xe2\xf2\xf8\xf4O=\x1d\x9a\xf2\x0eL\x85\xb8\xf6\x9f\xd4\xa3\x8b\xf1\xc0\xf9 \x1b\xf3\xf3\x18M_\x8e\xffry}xvz9>\xbd\xeci|\xf5\xe8\x8d\x9f\x8fq-N\xcf\x8e\xc6=m/\x9b\xeb0T\xc9\xe9\x9e\xf2\x9a5\xa6>\x88\x1a\xb3{\x01\x9a\xd3\x05#\x9f\xe7\x94.G\xdb\xdb\xb7\xb7\xb7\xc1\xed\xb3 /f\xdb\xbb\xaf_\xbf\xde\xfe\xcc>kd\xf3\"\xa4s{\x99W\xdb'!\x9d\xe3\x9f\x93wZ\xc9r=3\x16{\xba\xb3\xb3\xb3]\xaeg\n\x01\xfe8C\xed%u\xd5\xe8\xe9\xb5\x0d\xf6\xc9\xc5\xc1r\xc9\x10(\xfe@S\xde\x0f\x19\x0f~\x1f\x85\xe9[y>*\x94P%\x826\xaa\xbfvV\xd3\x1f\xd6N^L\xa9\xad\xb4aI\x17\xac\x8e\x1e\xdb\xdb\x8cQ\x8d=s_\xed\xbc4\xd0\xf1\x99\xfb\xf4\xc5+\xcf\xcd\xdc\x97\xdf{AR\xfe\x1c\xa6I\\\xc9\xe6\x1a\xb9CE\x19\xdee4\x7f{\x12nV\x94\xe6\x99\xd9\xaf_4'\xd1\xa7\x9b\xfc\xb3\xf9k\xb2\xc0\xf8\xfe\xa6O\xf3$\x8e\x89\xa5\xd2\"\x8c\x93\xdc\xf2\x89\xa0\xed\xa6\xe9S\xb9\xbaY$t\xd4\xd2L\xb6i \xe9\xeb\x8d\xe2\xee\x0dv\xc8\xe3\xa0H\xfc.\xc9>10\xac?`x\x04\x99\\\xb8\xce\xab\x97N\xaf\xae\xb2\xde\xcc\n\x95X]\xadR\xa9\x9f\xc8\x93\xf2\xec\x10\xe5mR\xc7\xfc\xd5\xab\x9ev\x0c\xdePZ\xed\x88Q\xf5\xb4\xf4\xba\xd1\x92\xfc\xc5\xc002\x9a\xd2\x8a\x88\x11Ch-P\x18f2\xa1\xa8\x93\x19N\xb8.\xd6\x15\x17N\xcb\xee\xf0\xb7\x82\x84\xf1Y\x96\xde\xf1\xb78)\xc3\x9b\x94\xc4\x8c\xbcb\xfd\x1f\xa1\xcb\n\xe1 \xeb\xd7|%\xc3\x83\xc6\x10\xc2o\xd8\xad\xdfX\xd2\x12h\x0e!\xa3y\x160MH\x1a\xc3mB\xe7\xf9\x8aB\x98\xc1o\xb2\xc1\xdf`\x1efqJ\x8a@\x91\x93\x16$\x8bI\x01!\xb0\x8el\xe5\xac'XC\x00\xc7\\\x90\xc7\xeb+\xe7\xf9*\x8d\xe1\x86\xc0bEY\x171\xd4\xfeo\xc22\x0e\xbd\xf7\xfd\x16\xc0\x19\x9d\x93\xe26)\x19\x99@(\x90\x84\xbd\xab\x1d\xc8\x0b\xf8M\x8e\xf8\xb7\xc0d2n\xd9~$~\xf8\xfc?\xe2\x94\x8b\xbe\xfc\xb7\x98\xf4C\xd1\x97\x7f\xd2\xb4\xcb\xd2#H\x026\xf3\xbf\xeb\xc8?\xb5\xda\x13-\xdb\x9b\x16u\xc8m|\n\xbf\xcb\x99\x11\x94q\xdb\xfc\xbf\xd3J\xb0\xe5\x08\xe95\x9b31\xa9\xdc\xff\"\xe4S\xf8\x8d[~m\x82\xf3[\xd0\x0ckh\x94]::m\x00\xa2Oq\x0b) \x18\xbc/\xf2%\x1aE\x0c\x83\xcc\xa62td\x03^6\xbe\xc8\xa4\n-%\x16\xd1\xa4\xb8b\xc74\xe7\x9a\x1c\x06\x88\x8e/\xee\xeb\xf2\x0e\xcb\xa9D\xf5\x89\x83\xe0\xcd%\xdb\x89\x0c\xfb\xc7\xba5\xedV\xdb\x99T\x99\xafP\xd5\xdeN\xde.u!\x81|zI\xd4&d\xcd\x08\xfdY\xc7\xbe\xa6.V\x9a5\xf5\xf1\xb5\x8f68(\xbc\xa8\x12\xff_\xf6\xfew\xbdm\x1cY\x18\xc4\xbf\xf7U\x94\xf9;\xa7\x0f9\xa6\x15\xc9v\x9cD\x89\xe3\xe3v\xdc\xd3\x997\x89sbg\xfa\x9d\x9f\xc6G\x0f-A\x16'\x12\xa9CRv<\x93\x9c\xeb\xd8o{\x0d{\x01\xfb\xec%\xed^\xc2>(\x00$\x08\x14H\xcaq\xf7\xf4\xec;\xfc\x90X\x04\x88?\x85B\xa1\xaaP\x7f\xc4_\"X\xf5\x8d\x15\xc4\xdf\xee\xfb\xc4\xa6=\x8d\xbd\xeb\xa7\xea\x11\xaa\x8d\x84\xd9a\xf5Z\x1f\x81|\xdd4\x06i)vVn\xc6V\xc1\xb7+$T\x94Ql\xd7/\xe4\xfd\xa9\x1c^m|M\xb3q\xb4\"\xab\xc8vJ\xf2{\xa4\xfd\x10\xce.*\xf8\x1aFI\x10?\x1c;\xd5!\xb1\x08\xe8\xfd\x12|\xa7\xe4\x18\xb7\xcc2\xfb\xe2\x1f*\xf5\x8c\xa9\xc4\xb1]\x88\xa0\xd2f\xa0\xda)cI\xa9\xd5\xa0k7Z\x95T\x15N\xab\xcb\xd26|UO\xe5\x98\xb4/b*\x90\xb3@\x92L\x96\xc8h\x18\xc4\\@\x06\x8f#\x8a\xc4M\xb6\xc1\xc1\xaa\xa7\x95<\xd0X\xf0\x0dv\x06\n\x0bd\xae\xd6\xca%\xabN\x83\xdd\xa6)\x0e\xb9\x8f\x95\x8a2q\x9f\x8e\xcc\x87\x16\x0du\x00\x8f\xb0\x0e\xfeQ\xf0}\x82\xdc*\xda\x1f\xa2\xa0Xa>9\xe5FB\x80N-\xa2\xa4\xba\x9a\xec\xdbwFZl\xb1\x9a\xcf{i\x16#\xec\xc2\xedZE\xadV\xd1z\xff)\xa1\xfb\x89\xdd!%\xb2q\xdc\xa8cjW\x84\x87\x90\xb4\x10\x15\xe1\x04\xc4\x0fg\xcf\x9aK\x08*\x00#\xcd\x8a\xf89\x06Q\xb2\x071\x03\x7f+\xab\xdc\xb3G\x91H\x99\xb9\x95\xfal\xc4\x7f\xa1\xaa\x1e\xffp\xdf\xf8\x96\xd06\xd6\xef^\xc8\xd9y\xc1\x15\x9c\xeb\x0b\xb75\x10\x7f\x132\xa6^\xb7\xd0\xea\x12\x17\x8b\x18\x81'\xab\xaca\x85\xbd\x94\xbd\xceU\xd0I\xd7=\xb7B\x1e\x12b\xf5\x10\x91\x88wUl5\xfe\xe6\xa8^%\xb6\xaa\xc40\x84Z\xfcG\xbc\x8dV\xe9\x9a\xd1T\x07\xff\xc4\x97\x9f\xd8\x9d|\xf7\x89\xdd=\xc4Z\xd17\xcb\"Tf\x1bAV\xac/M\xaa\xbdCo\x08\xdea\xdf\x11y\xd1\x1bb\xf1\xae\x9d\xba\x9bH\xf8\xa3\x80\xfd/\x9c9\xf6=4J\x08\x14u\xf7\x1f\x8d\x0e\x87\x97\x8f\xae\xc3\x0e\xe7\x87\xbaZ\x1e1\"\x96c\xa3._\xc5\x0f\xfdV\xa0\xf4q\xda.\xa0\x1c\xee\xf2\xe2\xe1&@\x11\xe0\xf0U\x8466\xea\xa3\xb7)\x87\x95\xf8\x8dQ1Y/__ D\xf4w\x05\x83S\xbd\x18\x04\x81\x06M\xff\xb0\xff\xe5p7xx\x80V\xf8J\xd3\x8a\x07 \xce\xec\xe2\x8a\xf6\x0fP\x916\x18\xec\x9a\xd7\xe6\xf2z]\xde\xab\xef\xef\x05\x9d=\xda\"BN\xec\xb1\xe4\xbf\xd6l\xcd\x04\xdfP\x8f\xccm\xb7@h\xbbJ\xdb I\x94\x1a\xcf?\xfd\x14+\xe8C\x0csQ\xa9\xb8\xe4\x82\x8ah/z*B!\x11\x014\xb3\x8e@\x92\x04fF\x8a\x8e\xf2\xf7\x0b\xd8\xed\xe3\x95\xdb6x\xe0\xf3&\x86\xc0q5\x93a\xaeB\xf0\x02^\x16x\xa0g\xffs\x87\x16p\x9d\x1fh\xeb\xed\x1a^\xa2\x0e}\xad\x03\xbd\x01\xdb\xed?\xce\xdf\xa6\xeb\xa4h\x97\xa0\xd4R\xd1\xfd\x83n\x86RH3\x94\xdeXH\xfclZ\xdaT\xd77\x89!I d\xaa\xecr\xbb\x08\xed\x8b2\xd9k\xe9\xbc\x88U\xed\xe1\xa9mc\xaf-\x94\x9cEu\x84\xd2\xeeb\xbd\xf1\x8a\xa1\x95\xa9\xea,\x87#\xea\xad\x08\xbf\x88\"\x13\xf5\xcd!\x8c\x8a\xcb\x10\"\xebB\xbb\x11 \xaf\xa51^\x07\x11\x93\x91\x03%\xdej\x03\xa5\xbe)\x07\xda\xecM \x07\xfac\x9aM$-\xe8\x8aM\xf4bH\xe3\xder@Z\xc3(\x98\xf0\x11\x15fJ\x0crH\xf2\xe6\x1e-\xaa\xba!T3\x9aH#\xf4rd\xd8\xf0\x7f\xf0\x9e\x14\xac\xaa2\xbdo9l=\xc1\x82\xa6\xd4\x97\xbf|\x02\x99\x85\xf5_\xd5\x90\x17\x84\x9b\xa2a\xd2\x80\x86\xc9e \xf0\xb0\x0b0\xcfYA\x01\xd2\x05\xc5\xc4 E1[?\xa1\xc0\xf8\xe5\x0b\xd0\x05\x870\xba\x0c\x02\x85\xb0|\xd4\xa6{\"=jy\xe3\xe4\xd8=\x0e,\xa86\x8327\xc7h,\xac7\x96\xc9\x0e\xf9\xf9\xdb\xbe1\xcc\xe5\xec\x0093\xd6\x99.\xf7I]\xc0\xee\xae\x87#\xe7\x07\xea\x86l\xc77x\xc9'\xfe`/\xa0\xb8\x90\xbd}\x9a\x0b\xe1<\x86\xee\xaf\xa9\x8f#\xbd\xff8\xba\xdd\xed\xdeT\xc1\xdeP\x928I\xa7\x8c\x16j&\xf3(\xe3\xa5h/\xccP\x1b\xc0yI_(\xbaU)^M\x0d\x84?ARZ\x06\x0e\xf6\xf8\xde\x92\xc8P\xc0\xcbC\xd8\xdbE\xd5\xc1^\xa9[(`\x08\x1bJ\x9a\x15h\xad<\x15\xd2\xc5`\xf7)y\xdd\xbao\xde\xc2b\x98\xc7\x91`\xa1${si\xb0\xe3k8\x04u\x0d]\xe9V\xeaurB\xfbR\xaf\x81q\x0e\xcb \x80\xf5\xb2 \x86,\xa8+k\xec\xdb\x89\x85\x90\xeae\xde\xc3M\x97[\x18a\xf3\xf7\x18\xaa\x8b\x05|\xdfD\x8dJ\x0fdf,\xf2\x84\xe24\xa15\xe9\xd3\x0c\xe7\xa4\xd4Ex\xb5\x8c8\xa8$\xd2yO\x1a\xf7\xaam~X\x0f\xfe\x9e\xe8w\x01\xc2\x8eK\xf4\x94\x04\xbc\xea\xec\xbe\x08\xb5\xfb\xecI a\x8c>\x83j5\xcff!4\x82\xbe\x93\xbc\xa2\xf7\xe3\xcaJ\xd3\xb2eA&1\xd2a\xe7\xb3\xde\xd5]\xc1\xde\x08u\x12\xcd\xf8b6\x9a\"\xe8\xe5\xac\xf0\xc5\x0f\x0cb\xdd\xe6\xdec\x8e^\x05\x87\xc4\xf5\x9b\xc7yo*\xe6\xa5R \x0e!\xe2EJmm\x16\xba\xc1\xa0\x00\xaam\xfc\x01n\xf2G\xfa\xc6\xff\xef\xbe\xd8\xf8\xfa\xbeG\x94\xc4\xa8\x0b\xc5\xfc\x03\x9b\xac\xb3<\xc6$\x86\xebP\xf8r\xf1\xf7mWB\xb8w\x8d\x8dk\xedX\xc5\x95H\xaabs\xab\x9e\xa7|(\x84s\xb8f\x1c%\xe84z\xda\xce\xd2u\x82~\xbcY\x9a\x16\x8e\x9c\x98\xe6~\xc6I\xce\xa3\xfc\xa3BhmB\xc0\xec`\xf3q\x15\xc4\xb0\x99{\x16&B$fuq\x8e\x01\xcb{ \x94\xfe&u\xec\xc5c\x90\xfc\x1a\x14\xf4}\xe4\xc0\x02\x02\xd9\xd4\xf3\x95\xcc\\V^\x94\xb9\xc6\xa7\xae\xdbb\xdf\xb4u\xd5\x9f\x08\x15\xaar\xd4\xeeyjg|\xd4qV\xe9(\xb9l\x99\x18\xb9\xdb\xaa\xe4w_\xeb\xb2~3\xef^\xa2E\xa1\x19(;\"yH\xc3\x12\x91\x92\xbdL\xf9\xa9l\x9cD\x96,\xe1K\x89\xb9 \x12\xf9\x13\x0fl.\x89\xc8\xdfe.fyh\xf0wE\xc6\x98\xe5\xd8EN\x14\xcd\xb5Y]B\xf0q\xdbh{\xa3\xe8!w)l\xb1:\xc6\xd0\xa8d \xcb7Q\x08\xef\x83\xc7\xa6\xbeD\x08\xefOLY_\xba8\x0e\x1e\x93.\x8e\xcf\x06OZ%\xac\x86k\x04\xce\x06Q\x97\xc0\xbc\x81]G\x19\x17\xf2\xf7\x1ce\\\xc8\xdfw\x94q\xf1\xfe\xc0Q\xb6\x82Cx\x0c\xea:\x9cH\xa2<\x05y\xfd\xbd&iV9\xd9\"\xe4\xb4w\xde\xc8D\xdf\x84\xb0\x0c1\xd1\x1bnKL\xea\x96\xfa\xd7A\x08W\x98kv\x8d\xd9\xe4\xf6\x82\x10\xc6\xfcL\xf1\xef*6\xfbV\x90\x99S\xf4\x05?\x82)\xefo\xccE\xa4\\\xfd\xeaW\x06R\xcfa\x0c/\xe1\xf69\xdc\xba\xb6*\xdf\xa6\xfe\nc_p\xa2,\xa3\xe4/\xe1\x10\xae\xfc\x1b8\x84\xbb\xd1\xede\x08\xb7!\xf0\xc1\x99Z>\xb3\xa1$\x80\xd3\xd1-\xe7\xf5\x974\x11\xe1OI\xc5\x96A\xb7TA\xa0\x18\x9a\xbdf\xbf\x17\xd0\xcfjw\xff\xa0\x9a{\xdc\xb9\xb9\x9b\x0e\xad\x1dtn\xed\xb6Ck\xbb\xed\xad\x9d\ny\xe5\xc6\xbd$\xda\x891i\xe4\x7f\x14\n\xc3\x11\x17K\x86\x80\xd9\xf5&p\x04\x13\x18\xc2i\xad\xba\xe9\xeax/\xcd\xa9\x14\xdb\xc4a^j$\x8a\x10\xbc*\xd3\xb7g\xfa^H\xd3z\x9d\x0d\xe3T\x13Sv\xa5Y\xfcW\x95\xde\x1d\xcf\xdf\xf2\xe5\xf1\x04\xed\xca\xa4-\xda\x0fQ\x1eO\x8e\xd7\xc5\x9c%E\\\xa6bpV\xff1\xcd\x96\xef\xa3,Z\xe6F\xad\xd5jA~\xfe\xbeJ V\xf4V\x19;V\x05\xaf\x97\"!1\x16\x9c\x9c\xbd\xfb\xf1\xf5\xef?~8\x1d\x1f\x7f\xbc\xf8 _\xfd\xf1\xf8\xcd\xebW\xc7\x17\xa7\xf8\x83\xbf=\xfb\xf0\xfa\xff\x7f:>\xe3\x7f\xee\xe2\xcb\xf7\xb2\xbaU\xf0\xe6\xec\xf7g\x1f/\xea\x1f\xe2\xaf\xf3\x9f\xce~\xc6O\xc6\xef\xcf\xde\x7f|\x0f\x87\x8a(|W\x81T\x86\xcf\xf5\x13\x7f\xff\xb1yE\x9f\xca\x92\xdd=\xea\xf2\x1e\xbf\x19\x04\xb5C*\x9f\xa7\xb7\xaf\xf8\xa2\xc6\x1c4\x9d|\x9e\xecm_`\xea\xf9 A\xa1\xa3\xbbE\x1aM\x87\xcdbG\xb9\x16\xdf\xd2;A\xfe\xbb\xf5\xbeH\xaf\xd3u'V\xdf\xd5\xf5\xea\xbe]\x97\x13?\xe3\x7f\xed~\xcb\x18\xa6\xf7\x1d\xc3\x04\xa3=\xaf\x05\xe2\x7f\xcb\x08\xe6\xf7\x19A\x1d\xb1#\x85\xbe\xfdg&\xfe\xaee\xd1\x9ee\x96\x92\x0bV\xa7OZ\x9e\x10nEJn\x13&\x1e\x15\xf5\x92\x8a\x1c{zJ\xacv\xcf\xa26\x89\x89c'{|\xab\x8dW\xe9j\xbd\xf2\xec+\x8c:%\xf0J\xcc0\xaa\xae\xea\xf4\xc3\x13\xc8kT\x9ab\xcaK\x17\xf9\xf1V\x19\x1b\x97\xed\x8fSD=/\xa4\x89\x98gU4\xa0?\x17}i\xc4\xd0S\x17\x97\xd8\xa6E8\xbd\x12\xe1p\x10^\x8d\x1a9\xe8o+NV\x9c\x1c\xc5\x95\x94\xcay\xdcp\xc7X\xb3!\xe2m\xd1cY\xd6XKx\xd2\xf3\xc6\xe8\xf2H\xc4,K?\xb1\x84\xae ,\xa8\xa5[#]e!\xf2RM\xe6l\x19\xd15&\"\xc2E\xb4t\xf8\xfb\x8b\x9b\xb1kV\xf8\xdel\x91\xdeR\xe1\x82d\xc4\xf4uO\xe2x/\xbf\x8d\xae\xafY\xf6\xf1\xf5\x076\xc5\xb8\xcf\x822\x85\xe0E\xe51+t\x063\xcep\x88\x1c;\xbd\x84\xdd\xf2e;\xcd\xcc\xa4\xfe\xea\xe1\x8d\xbc\x9e\x92G\x04\x7f\xf2t\x9dM\xd8P\xe5\x90\xa7\xe1\xc1n\xd8b\x08\xdem\x94%qr\xed\xa8%%\xc1!x\n\x8f\xc4\x91\xbf\x8c\xee\xe0\x8a\xc1\x1a\xddgCXEy\xce\xa6\x90\xa3y\xc5m\x94\x83\x88\x0e\x86J\x8e\x9ce7,\x83\xf7F\x95\xe4\xdf\n\x89ml*\xc2|a\x1eRQ\x9b\xb0C\x0cB\x88z\x18J\x0c\xed+~M\x10a\xafm\x00\xf2\xfb!\xc4j\xdd\x03?\xa2<\x821\x13\x97qH5\x0c\xdf\no\xa8\x1e\xdc C\x88\x88.\\$U\xa7\n\x14\xaf\xf6\xeb\x92\x04\xd6\xb8\x11c\x11X\xc3\xb9\x11\x059(\x13\xab\x91u\xd62\x84\x87\x98\xa0\x9b$Tu.\xac\x8bt\xf5L\x84zu\x11\xb3\xa4x\xedhk\xa6\xd59g\x93\x8c92\x9b\xaf\x9c&\xba\xfc\xb9\xce\xa2\xa4\x18\x8b\xf3\xdfS\x03s`\x1e\x7f\xf2I\xca\xabrp\xa6+\x96K\xfbF |\x16\x01\xac+A\xf5\xa0\xc7\x9e\xa3l.}\x15\xcd\xf7JKy\xc5\xa5 A\xc0\x16p\x04\xf3^\x9dL\x1c\x82\x87\xf2\x06\x9a_\xf2\x1d\x92\xf7\xae\x8a4\n\xfc\xa8\xcc\xf8\xba\xc6\xbbM^\x96V\xbbgEy\x9d\xf3G-:\x89\xfc\xae\x8f\x14 \x87\xb0&\xe9\x8a\xcc\xc1[\xce\xc2\x9f\xa0\x06`*\x97s\x1cs\x08M\x82\x10f\xf5\xf79\xae3\xdf<\xe8\xba\xd5y\xf2\x93r\xf2\xb3\x00\xd3\xec\x99\xf2\x9b\x83&\\\xa5\xd3\xbb\xa1ji\x1d/\xa6\\8{\x15\x15Q\xe0\xaf\x1c\x8a\xcdu\xb6\x18\x8a\xe0\xce\xbe\x87T\xe3c\xb60Y\x0e\xf5\x08\xb8\xc6\x0eD`\xd1\x94e9\xc9\x96\xf2\x07AH\xb2\xcdPR3\xe2N\xdcI\xafB\xb7\xb0\xf9[\"U\xa9\xac\xc1w\xdf\xb7\x10\xb3f\xe2\xb2\xeeH\\l\x93b\xfd\xa9a\xe7\xb0\xcb\xce\xdc\x84\x8a\xd0\xc1\x00\xd4S#lr\xfbL26eI\x11G\x8b\xbc\x9d\xc4\xa5m\xb4\xcdI\xa3\x1eb{M\xee\xb3e6\xd9{r\x83\xb4\xec=\"r~\xc7\x0d\xe4\xd6\xe9\xb4\xdb\x00\xb98\xf3D\xba:\n\xc6\xf6c\xb6hV\n;m\x8f\xb3\xb2\x8fV!\xa1h\xe5\x1b\x8a\x96\xadVt\xd8j\xc57o\xb5\x1a\xbaG\xfa\xbe\x1bO8\xc7\xefF\xf7 f\x08(z\x13g\xd81\xac\xa5\x0e\xa6!8`\xa1\xd5\x12\xc7\xd4\x10\xd6\xee\x9aj\x11\xc7\xeb,\x1e\x12V\x04\xd0\xb8\xc3\xb2\x07\xd8af\xd2U\xf5\xb4\xef\xb0t\x93\x1df'\x9c\xbe\xd7\x0e\xa2\x95\xa8\xff\xdcJ\xb5\xe7a\xb6\xd2o\xe6\xd4\xfa\xbbm\xe3\xbf\xff\xe6\xbc\xff\xf1\xb7\xd9\xe6\xfc\xa5\x8e\xbf\xeaZ\xe4\xc1x\xc7\x99C\x13%\x90\xfe\x9a\x152\xeb\x1f]+\xef\xc6\x7f.:i\xcf\x84\x824\x8d\xf2\xbds\x0c\xae\x9e\xbaR\x15 \xbdh\xbeb\x93\x96\x8a\xabrx-\x15\xa7Ho8\xe68\x96\x0e\xcbQ6\xa0+\xdc\x94W2(}\xcd\xe1\x08\xfe\xf6\x15\x9cR\xc6\x12\xdb\x93\x08AW\xb9\xae\xb7\xb8T-.\xe9\xeaw-\xec\xf9\x95\xd05dD\xa4 \xfe\x8c[4\x97\xb7p\x08\xfeJ\xc3\x07\x1f\xad\xe2\xff\xf65\xe8E\xd3)\xde\x11E\x8b\xff\xe0\xf0\x11\xd6\xfa\x82-\xa3\xdb:%\xae\xaf\xf4\xb2Y/\xce\xcf\x8e\xcf\xf7\xfc\x80\xcb\xb0\xfd\x10\xa2J\xa0\xbe\na\xd2\x13\xb1\xf7\xd9\xf4\x1cul\xbe\xc8\xac\x0cC\xa2\xee\x8c\xcfXV\x08\xeb^\xe2\xbaU\xd1-\x1c\xd5\"\xf6\x89\xa6\xb2\xaa\xa9\xdb@\\\xa6\x9f\xca\xb4\xf4\x87`\x08\xfa\x7f\xfb\x1a\x82,\x0c\xe1\x96\xb2\xe3\xe3[\xee3\x1c\xc2i\xe9\xd1\xe0;\x88\xc89\xd1\xbc\x93\xa8\xf2\xf3|\x85a\xcc+\xd9\xf2\xd1_\xf24 \xa1`\x9f\x8bG\xabE\x14'!\xfc\xee\xd1\xef\x1a\xa8\xbcw\"\x82[\xee\\\xdc\xad\x98g4\xf6y\xe7\xf6\xf6vg\x96f\xcb\x9du\xb6` ?\n\xa6\xb6b\x13\x04\xb5\xba\xa6\\\xb3z3VL\xe6\x8eY }\xfd\xec\xd8'\x18\xd6i\x08\xde*\xcd\xcd\xdb\x0c\xf5\x94d\xf5\x9c.\x97\x12\xfd\x8dc_\xe0i\xe18\xf9e\x9c\x1bt\xf3\xe2`N\xb3!\xac\xfd\xa0g\xbfw}\x9f\xaf\xd2$gD\x03V\x81\xd5\xc0\xd7\xa0\xc7\xf92\xbf\x99[\x02\x8d+\xd3,KYo\xcaO<\xf7\x92#\xf5\x97.\x91B\x1b\xfd\xe5\x0bx\xaes\x0d\xd4\x15\x88\xfc\x02;9\xd5>\xa3\xed X/\xfd\x84\x0e\xcc_\xbe@\x06G\xb0hWw\x83\xa6\xf2v\xd0Z\xe8\xa8\xd2\x86\x8e\xeaqhP\x7f\x13\x16\x85\xa0T\xe0yG\x158\x94\x8c\xc1\xd8=\x00\xa9\n\xb7\xf9zP\xdd\xfd\x03\x00\x8f\xf5\xf2\"*\xd6\xf9\x05\xfb\xec\x9a\x08\x85\xe6\x98\xaai\x03<\xaf\xacQY\xa0l\xfch\x04D\xcb\xc5r\xb7\x89\x9b]\xf5K\xec\x90\x06\xae\xf9\xa6\x0c\x00P\xfb\xc4m\xf2C\xe7\xa6\xd2\x1f%\xdbh!M*\x17\xad#}\x03\x8bL\xa4\xcd\xe6E\x99\xdc\xb9\xc2sp\xfb\x10\xbc\x10\x98H\x16%\xc2\x04\xe0\x0ft\xee\xc5\xbf\xc6S\x96O\xb2x\x85b\x9e\xfe\x91\xf6\xbe\xf6\xa9\xfeA\x93m\x92\x96k\xcb\xf6\x0e\x02\xa0|\x86\x00\xfd\xec\x7f\xf3\x18\xbd\x01\x1a\xd7^\xfd\xf6l\xab\x10\xad\xfe\x14-\x17\x82\x81s\x99\x10\x95\x19\xa7\xc8\xe8\xbb\x98k*\x15!U\xeb&\x12Y\xb3\x89\x84\x91\xbb\xb6v\xb7o\x0d\xac\xd1\xd8\x94\xdedR\xea\x89\xab\x0bk\x0c\x87\x1cM-g\xea\xc6\xc4p\xb2\x19\x91\x0fT\x13X8\xa2^\xcc\xb3\xf46\xe1\xa8\xaa\xd3\x9f 4q\xfe\xb7\xb7\xf4\x8b4\x9a2a\xc8vq\xf6\xfb\xdf\xbf9\x1d\x0b\xeb\x8bs|\xf5\xf1\xfd\xab\xe3\x0b\xfdU3^\x98\x16\xc5\xbf\x14Z\xacUh\x86Flh\xb1=\"\xb4\x11\xa5\xed\x91q\xd2s\x0e\x9e\xd9 *PrH\x16\xe9\xf5\xf5\xe2\x9b\xcc\xd1\x08\xe5\xe5}\xac\xa1\x88e\x93\x064\xf9X@\x8ep\xc9&\x96\xbf\xfcH\xcc\xcc\xd3W\xa0D\x9br\xb2m\xba\x86\x1a\xfd\xbf\x07\xf6\x97\xafK;\xadL}D\x07AG\x03\xfd<\xc3\x8bmi\xae\xcf\x92\x9b\x9aA\x7f!\xcd\x17\x95\xc9?\x92\x1b\xe4e\x95}?\xe7\xbcr\xcd\xe0\x7f\x95\xe6\xc20[\xfdz\x1bq\xc1M\xf5%\xed\xb7e1\x9e\x9e\xd6Z\x90j\xe3\xf1U:\xbd\x1b#\xf6y\xb6,e5&\xb3T\x8d/\xfe\xf4\x9enN2Vx\xbfk4\x18\xd5\x1b<\x7f\x7f\xf6\xee\xfc\xb4\xa9E\xb1\xd3\x9b\x9a\\\xd7\xe1\xc5\xc14\xfe\xe3\xf1\x87\xd7\xc7?\xbc9%\xe6,\xa06\xbe\x91\x08/\xa7\x8d-\xde\xeb\xd8\xbf\xd1\x02\x95R1\xc2\x12\x7f\xb7O\xba\xc2\x0e\x1e\x9b\xf1\xad\x84/\xecc\xb3\xbap\x85}b\xbe\x16\xee$\xfb\x8f\xcd\xf0\xa8\x0b\xe19kjK&b,\xfbf\xf5\x99\x18\xcc\xb3\xc0\xf7\xe2\x82e\x11Fv\xaaWYq\xfe\xdf\x1f]b,\x14\x8c\x9c\x91p\x8e\x1a\xe2\x04\xe4K\xdf\xf4ui\x94\xd2@Sl\xcc\xe3\xbc\xbe-*\xc8:\xdd}Q\xfa\x9a\x87\xca\xd3\xd5l>\xf7\x13\xacdFQ\xe2+u\x17\xc2U\x08c\xe1\xea\xda\xae\xe0\xc50\x10\x98 \x0b\xf3R\x9c\x94\x9e\x8e'V~Z\xf5tr;\x15148\xe4\x1a\xf2\xad\x89J\x88\x9fM\xd5\x80\x96{\x1b\xebk\xdf$\xec\x16\x12\xe9\xa7\xee\xc8\xe7\xa6\x9eMT\xa9\x9b\x8c\xa8\xfbH\xec\xbe\x08\xf3\x13\xf4P\xc4\x10\xb5\xaf\x15B\xdb\x95>K\x07 \x0e[8<\xa4n\xe3\xce\x85\xd8k\xbd?\x11\xdc\x02\x1d#\x8e?\x9f\xe0\x10NF3\xcc\xfas2\xf2\xfe\xfd\xdf\xcb\x8d\x85\xafn8>\x9d\x8cn.\xed/\x8f\xe1\x10>\xa1\xc3\xb4\x7fC\xdc|\x9d\xc1!\xdc\xc0\x11|\x86#\xb8\xf5=\x96\x14Y\xccr/\x80!\x1c\x97~\xd9\xf6g\xe8\xd4\x85\xb1&\x84~\x1f\xfb\xef\xc9\xafyoF\x82@\x8e\xf5\xefQ\x1f?\x86C\x98\xf8\xefeT6v\x0b,\x08\x02\x8c\xe5i\x86\xbc\xe2\xd5\xc7\x98\xb3\x13?\\\xf8\xe3\x10N\xe55\xb7\xb8\x93S\xa8\xa0\xdf1\x8c%\x94\"^}\x16\xc24\x08B\xf8\xcc[\xc0\xbc_\xe5\x02\xf1\x1e?\x89X \xbc\xf5s\x19i\xf4\xb8#\x95\xf9T\x05c0\xb4i8\xba\xef\xbf\x87\xadk\x0c>\x8f[}\xeb\\,\x90\x1a\xda \x0e\xed8\x08a=*\xb8\xa8z\xcc\xff:\xe5\x7fMC |\xa49\xfc\xee\x9c\xf6ObNC\\D\xbej\xb7\xbe\x9a\xa6\xe3\xaeS\xc4Y^V\xd5\x91n8*\xcbU\x1d\xc2\x19\xb1U\xe0\x9a\xdeV(\xd8_I\x1f}\xfc\xff\x84O=\xe6S\xbf\n\xe1ntuI\\\xa8\xa2\x03x\xea\xa7\xbd\xf7\xb0\x0di\xefG\xf8\x1d\x08o\xff\xf3\x00\xe9\xef\x1d\x1d\x80e\xc3(\xf7\xfa)\xb0\x95\xf8\xfb\xfb\xa8\xd5\xddJ\xfc\xc7\x83\xc0\x9dQP\xf6\xf5\x04\xb6\x0e\x1d\x829?\x80\x0f\x02\x99\x9f>\x04/\xb2ds\x10\xc9w\x86\xedDL\xf5f\x83\xdc\xc0\xb6^\xe5\\!\xefg:\x07\xdaxLG\xc9|B\xe5\x85\xe1l\xc1^\xe0[9cd\xb0\x8d\x83A\xe0{\xafO\xc7\xef?\x9c]\x9cy\xf7\x0e\xb0\x11\"g\x92\x92\x894\x84\xc2\xd2z\xbdp\xc5M\xc3P\x82\xeb\x00\x12\x0ci\x89z{\x7f\x8d\xb0\xc0\xa8\x902\xc4/\xf1\xe1\xf32 \x0e\xbc\x84\xfcy \xbf\xe3G\xc0(\xdf\xde\xbe\x14f2\xff\x1d\xfb\x0bl\xed\xcb\x97\xaa5\x1a=\xcd\xa8\xe2\x9d\x17hw\x10\xf4T\nb\x1a\xa4\x99\xb8\x8fP\x95d\xd0\xdd\xcdzq\xa1\x01u\x0bb/\xb5\x8d\x0e&\x1d\xa7GN\x06\xd3\xac\x07\x8btj\xe4$\x8a\x08\xcdy\x8ca\xe8F\xf1%\x0c\xe9\x13\xc1\x0en\xaf\x07 \xad\x97\x1e\x19\x91\xef\xab\xc3hX\xffL\x86\x88:\x82\x08\x86T\xe4\xf8\xce\xd0\xdf\xdb#\xa0\x9f\x8d\xbc\xf1x\x92fl\xe7/\xf98\x9fG\x19\x9b\x8e\xc7\xe2\xa8\xf7]e\x87\xf0\xb7\xaf\xad\x1b\xcf\x01\xd2t$r8\xfa\xa9\xd0\x9c\xfe\xedk\xd02\x1f\x17=\xbd\x9fF\x91%\xeb%\xcb\xb8\xf04\x84-\x7f\x00\xdf\x03E\x01\x94\xf7\xb4\xaa\xb7\xeb\xa8w\x9b\xc5\x85\xaa\xb3\xef\xa8\xa3\x14#\xb5\x82o\xba\xd8\xa9Z.\xb7\xef\xfe\xe3\xc0\xdf\xd2\xb5\xd4\xfc\xddA\xe0\xcbh\xbf\xe0\x89?\xbc\xa6$\x1a\xa8g\x1e\x17p\x08\xd2\xa2\xaeT\xca\x8f\xe3\xfa\xcdG\xe8>U\xf8\x98\x98L}/\xda\xb3!Rj\xe0\xc71I\xc5\x12xyXQ\xc6#b\x15%L]<\xe34M\x98\x9d\xe0\x15\x86\x18\xcc\x0d2\x91\x7f\xa0\x9a\xdb\xf6a\x19V\x8f:Feg\x04\xaf,\xfb\x19\xd4\xfb\xd1\x10z\xc3cr0\xa0\x03R=\xde\xbb\xefv++4\x05\xd3\x8fC\x88\xc4y(\x17>\xf5\x0bS&V\x0f\x1e\x05~\xe2(\x15A\xa6]\xd1\xd2\xe4\x98rx\x01}\xe1\xd7\xfeR\xb8V28\x02\xcf+\x85\x00\xbeP1\xb6\xa4\x05/\xcc\x83\x00^\xc0\xe3\xc7\xbb\xcf\x0e\x90\xbd\x83\x97\xf0\xf8`o\xf0L4\xb4\x0d\x03\xe9\xa8\xc9iKd}\xcc+\x88\x06\x0e\xf6v\xb1\xf3\x887\xf0do\x7fO\xf6/\xeacG0\xc44H\xe2m\xbe\x88'\xcc\xcfC\xec\x04s\xd5D\xb0#\x9b\xd9\xe6\xe3\xdc\x91\x83z\xf1\x02\x06\xfd\x00\xb6\xe1\xe0\xf1\xe3\xbd\x83_v\xb7\x9b\xfa\x11\xa9\xab1\xb1G\x86-3\xe9\xbeT\xd5\x98\x1a\x9c\xb5\x0c\xf1a\x9e\xc6RWs@\xebj\x06\x96ng\"\xeb\x9b\x83\x94\xca\x9a'\xffT\xd6\x10\xcf?\x955\xfa\xf3Oe\x0d>\xffT\xd6\xfcSY\xf3Oe\xcd/\xa6\xacqjj\x06duw\x18\xd1\x03\xc7\xdd\xc9\xe3\xbe\x83o\xd3\xc2\xb3w\x12DQ\xfcL\xdb$\xa5\x0d\xf9\xca\xb7Q1\xef-\xa3\xcf6\xcf J\xe2\xa4\xc3 \xe9\x18\xb0d\xb4\x19\xf2\\}8\xe2b4l\x83\n\xc2\x19\xfb\xcc\x88\xc9\x0f\x1b\xac\x8f\x9e\xc8#4\xb2\x96\xc4\xb9\x9e1c%_\xbf\xceOK\xb9/,\xd27\xe9$Z0)\x1b\x95)Qpo\x9c\xcd\xbc^\xbeZ\xc4\x85\xef\x85\xde\x86\xec\xfb\xde\xde\xaf\xa2Dq\x04\xad\xdd\xa5\x95i\xc8o\xe5+6A\xfa}\x8f\x15\x95\xea\xb2H.hk\xca\x14\xcd\x13,\xc2CH\xfd\x16Q\x923?\nF\xf1e \x13\xef\xa4z\x92\xf3\xeeh-b\x17\x87J)h\xddR\n^v\xff\x89 \xab\\nL\x07/{`\xf2\xc4\x13Zs\xc2Y\xd9\x89\xca\xcdl\xb3\xb0\x93^\xce\x8a\xd7\xcb%\x9b\xc6Q\xc1l~u\xd2\x9b,X\x949j\xcc\xb1\xc6[a4\x7f2\x8f\x92\x84\x19~\x867X\xe3U\x9c\xaf\xa2bb\x98},m\xe5\xe55\x11\xca\xe7\xae\xed@CA\x1e\x0ea\x9b\x9fe6I\xe6'\xcf\xb5\x99:\x85\xce\x90\x01\x9a\xe1\xc5\xb5\x93\x9b\x95A\xd2x\x85\x10\n\x9f\xf0 \xa8\xbd1\xa6s\xd5\xcad\xdf\xc9\\ \xc2Q\xa5\xdeV5\"<\x96\xa7(D\xae\x1a\x9b\xac\xa5\xfd\x18]\n\xad\xed\xe09D\xd95n\xed\xbcR\xec&\xcf\x03\x95C\xa3,\x1d%\xdb\xdb\xe6I'\xf7\xcf\xf5h{{y\xd9\xb6\xd0\x02(\x7f\xe5\x0c&_\x87\x9b^\x92\xde\xb6\xb6\x86\xb5\x9c\x0d\xcd\xe1H(\x13|$\x93\xec\x16\xe6A\x8f\xd3\xbd\xdd\x10R\xfcc\xd0K\x93*\xb4\xf9\x95\x08T\x1f\xf9qo\x95\xe6\x85\xdc\x85Hk\x06\x18\xcfi\xd2\x8b\xa6\xd3\xd3\x1b\x96\x14o\xe2\xbc` C\x9aN.\x86\xd6\x00r{\x93^\xbc\xe4=\x9e\xa3\x17P\xceG\xd6<\xb5\x89>\x06<@=/\x04\xefw\xf54\x07\xf6\x88|ON\xc8C\xaejK\x8c\x1c]\xa5\xd2$c\xd1\xf4\x0e\x03\xee\x89p|(]/|O\xf8&a\xaa\x15\xf7\x88\xf2^\xb4Z\xb1d\x8a\xf9\xe8}\xed\xab\xa0g\xb7\xdc\x86\xc3y/c\xcb\xf4\x86\x89\xc6\x90g\x0e\xcb}\xea\xf4\x1c\x80\xa6\xcc\x959+.\xe2%K\xd7\x85\x86\x11\x9c\xe9\xa8\xbe\x0f\xeaF\xb3\xd6\xf7V\xa4Y\xa4\xd5C\x98VM\xe0_]\xb9\x15\xf7`\x1b\x9doh:\x8a\xeaF\x9a\x1f\xbf\x19\x02k'\x9b]\x1cv\xdc]\x13\"\x1f\xc8\xae\xdb:n\x81\xde\xa6\xec\xce\x13:D\xff\xe0I{V3G\x9e\x8f\x0cie\xea\x17vj8\x91\x90\xa8-\xb5q\xdc\x9b\xb9\xb2\xfe\xfa\xfd\x10\x92^\xc6\xf2tq\xc3\x02\x8cl\x8f\xa9\xfc\x96\xb1\x96\xdfjC\xc0X\x10\x10\x80yF+\x01\x91\x0dDg\x86v&\x90\xe2\x00\xe9|\xf3\x98\xc7\x8f\xcb\xc9Z\xdaT\x91wF\xb2x[[\x9c\xc9\xf3>\xb0\xeb\xd3\xcf+\xa4\x8di-%\xe6\x86s\xb6\xf8<\x95\xb0\x81\x9c\xf3\xe3{\xe1\x82ZN?\xed\xc9\xab7\x11\x9aA^\\\x89w\x9cK\xb10>\"\xc2\"F\xd2A\xc0O\xf0\x161\xeb\x9d\xa3C(\x17ac\xb7\x05\x00\x88l\x9e\xb6\nA&\x8c\xf1B\x88\xee\x0d\xc4g\xae\xdb\x84Zf\x97Nr\xa9\xa6\xeb\xc9\xea\xc9\xc57\x1a\xd1\xee\x9eC\xa69\xd8Cyc\x12\x15\xbe'\xf8)O0\x1dB\xc2\xab\x875\x9e\xd5\xeez5\xbe\xf4]\xb4d\xbf\x8e\x9c\xbdk\"\xa2\xdc\x934~Z\xe6\x0fR\x9aylj\xce\x854c\xdd\x9eKaf\xcf\x14Z\x16.@\xbc\x92\x0e\xc8\xba\xe4&\xe0&lS\x8e`\x01- peF$\xcc\x98'\xae\xf9\"\xbf\x90\xda\xb7\xd2\xccL|`\x1eH_\xad\xaedN\xa5\x92\xf4\xa6\xfeV\xd6\x9bii\xfdB`\xa3\xe2\xb2m\xc5\xcc\xe5Jp\xa7\x96\xb1C\x1el;\xa8D\xae\xf8\xc9\xa5\xe0\x8a-~\xa6\x13R\xb9Y\x94\xd2\xdd3\xf1\x1f\xef\x99\x18Ty\xeb\xd4\xfdr\xbat\xd9v\xed\xf4\xec\x80\xde\xa4O\xcc\xf7\xb1c3\x08\xf4\xb6\xac=\xe4\xbd\x93\x95tGS\x94Ey\x1e_;\xd4Q[\xb8\xb5[L\xaa\x944KE\xb4-\x1c\xef9\x92\x9c\xdf-\xaf\xd2\x05\x15[\x06\xb9\xe9\xe8j2e\xb3\xeby\xfc\x97O\x8be\x92\xae\xfe+\xcb\x0b\x8f<)e:\xd1'!dJ\xbf\xe4\x05\xbdY\x9a\x9dF\xad\xd1\x1a\nq\x86\x18\x0e\xadA(,\xc4r\xe1l\x1b\xf0\x0e\xca\xf3I\xdc\x95\x89\xa2\"\x08d\x98L\x0f\x93\xeeVn\x16_\xeb\xcc~\x9b\xd7\\\x84{\x9e\xc3\xdc\x94rC\xa49\x83PFK\x9f\x85\xa8!\x89{\xb3\xe7\x90\xc3KX<\xb7\xf9\xd2\xb2\xe5\x95\x90=\xd7\x9ap\xbc\xe0\xc2q(\x14!\\\xfe\xf3\xa7\xe510\xf1\xa7B\x98\xf1\xa7A\x88\x8a\x90y9\x86\xa5H\xc2u\x03/a\xf9<\x00I&\xa6!\xead\xe6\xa3eiQ\x95\x8cV\xa8S\x1f\xad\x1c2\xb8\x96a\x0d\x86\xdd\xb2J\xb5\xed\x9eA\x9f\xe6\xd7\x06\xa6nI\xec\x9e\xdd\x03j\xf7\xf8\xbc\xe0\x80s\x8f\xfe`\xf7 \xa8\xd9{<\xc5\xd7\x8f\xf7\x1e\x93)\x1a\xd6\xd4\x98\xa1t\xd7\xcc\xd2U\xae\xb9\xfdV)\xd4\x95_o\xc6f\xb9\xcc\xe2\xc7\x7f\n\xafh\x9c\x19\xea\xef5Jc\xf7\x9d\xff\x1d\xfb^\xd4\xdd\xa8\xd7\x9aof\x9c\x7f`\xd1\xa4\xd0\xf3\x10\xf2\xed\xa2W\xc9e>\xfd6\x9e\xb1\x8c\x85e\xe4\x82wg\x89\xc7\xbc\xbe[\x87e\xca\xf8\xa7\x8f\xbd\xa0>\xbf\x9e\x91\xd3\xbf\xbc\xaf\x0ceD\x05\xa2\xae\xcab\xafR\xb7\x85\xe0\xa9)\xd4u\x06\xfa$gi6a\x1f\xed\x00\x01\xe4j\x19\x1d\xfeX}\xab\x04x\xd6qp,\x04O\xeb\xba>\xbeE-\xab\xf1Z\xcfj\x9c\xd7\xf3#\xb3[X\xd4^\x1a)\x97s.\xd3\xe5z\x03ZkA\xfd\xcb8\x7f\xbf\xce\x98\x85\x15[\xfd&\x95AY\xd3r\xe5\xe2\x8di\xa5\xb9\x86\xa8p_\x82\x92\xf8\xcf\x02\x9b\xbc\x18\x0bc\xf5l\xfe\x90\xae\xafa\x861\x0c\xba\xfe\x07\x91\xcb\x13q\xb5k\x1fjk\x10\xf5+X;nb\xee\xbf\x04\n\xe8z\xc2\xb0\x07n\x9aT'\n^\x84\xef.\xf1\x17\xdf\xb8\xf5_\xbe\x97q\xdc\xed1q\xaf\xe4\xa1\xc9\xf0A\x7f\xd0\xdf\xfb\xc5F\x9a\xf8\x8f\xf7\xefm\x9d\x86\xe2\xd6\xd6`C\xd6\x98\x1eP\xed\x82\xf0\xfc\xf4\xe4\xc3\xe9\xc5\xf8\xd5\xd9\xf8\xdd\xd9\xc5\xf8\xfd\xf1\xf9\xf9\xf8\xe2\xa7\xd7\xe7\xe3\xb3\x0f\xe3?\x9d}\x1c\xff\xfc\xfa\xcd\x9b\xf1\x0f\xa7\xe3\x1f_\x7f8}\xf5\x0d\xees\x0f\xe65O\xc1u\xd7\x12\x0f\xa51\xe0\x01\xed\x92\xf7\xd82\xd0\x92v^\x074\xc3\xbd\xfb\xe4q\xdd^\xf4\xc9\xbe\xfe\xbb\x87)\x13=\x91k\xfe\xbcH3\xe65\x98}\xaa\x05\xed]i\xb3\n\xabV\xd2\xe5U\x9c\xb0\x0fl\xba\x9e\xa0\xd7gkKi\xcd\xdb\xa0j\xe9*N\xa6\"\x8c\xd0 \x1fY\xda\xa9\xb1\xd8\xd1X\xb4Z-\xee\xde\xc6\xd3\xe9\x82\xddF\x9d&\x189Z\x9ap2\x9fwia\xbd\xb1\x1b\x85\xe3 Ps\xe8\xd0g\\\x1bs\xd1\xd3o\xcb\x80\xc9|\xb0V\xf46\x8e\x8aFJO\x92.a\xf4\xb3\xda\xad/\xe7\xb1\x11\xf9\xc4\xb5\x98(38m-\x15\xf1\x16\xff\x88:\x9f0\xa5/\xc5BED*\xe5\xd3\xcf+\x8c\xf9\x00\xc5\x9c\x01K\xe6Q2a\x19\x14)\\1\x88\xca\xe9\xf6\xa8\xe8\x8ajq}\x16\x08C\xd9Z\x0d[+A\x8e\xa9h\x1bS&\xb0\xbf}H72\x99/\xa1g\xc6{j\xfb\xf5\x84pM\xe1\xef\xf1\x9e\xda~\xbd\x92\xa7W\xad\xa0D\x88)\xa9\x8e\x9c\xe1\xda\x8a\x1c(\xe2\xfa[X\xc6\x06&\xb0\xe8F\xe7MVS\x8bNM\xdc\xd0L\x8csAX\xd3\x82,\xd4\xe5]\xebj\x80v}M\xa5O\x95s\x98\xfaA\x08\xb32\x9a\x8dU\x0d\xb4\xa94\xda(\x8a\xd4\xdb\x0d\x15@\xea,\xb6\x06!\xef\xd5\x1e\x91\xfe(\xd9}&\xb23\x9f\xd9W\x14\xe63C\xfd\xc4\x84\xf9I\x08\x03\xda\x8a\x0b\xac]A\xbfu\xad\xe4\xd2\xbd\x92[Y/B;\x02k\xe9d\xf08X\xae\xf3\x82/\x19\xc6\xe2\x05!x\xe5=\xf8\x983\x98\xac\xf3\"]\xc2\xb2\xa4\xe8\xa8e\x88\xf2\xbbd\x02\x91\xf8\x9c\\^#-:\xeb\xa1l`\x0d\xe1\xdf\xca!Dw\x98\xb2}\x1e\xdd0\x88\x12(\x83\x1d\x83\x87jiPvG=\xf8\x89W\xb9K\xd7\xb0\x8c\xf3|\xc5\x16\x0b6\x85\x08PD\x89\x92\xe2\xe8\xdf\x1c\xa3Y\x11\x00P\xa7g\xd9\xfdT\x1a\x804\xce\xcd\x1dFs%E\x1bNSr\x7fA\x9a\xc2~\x85Y\x9cD\x8bEc\x1b\x03\xfb3\x9b|\xe8\xf6\x12\x9c\\\xcd\xc4\xd9 \x93\xa6k\x89\xe1\xb7\xb7]\xc8\x7f#3\xb6\x17\xa3\xc4aD\x92\xb6^\x80\x82\xa6\x92\xfb\xce]m\xe9\x0c\xc8\x15\xf7^\xbf{}Q\xff\x94V\"\xadI\xc3L\xb5hd\xec\xf1|}\x95O\xb2\xf8\x8a\x91\x11\x96\xafKq\x87\n\xf5\"\xe4'\x89$m\x92\x1f\xdc\x9bp\xf2\x93,a\x9f\x8b\x0f]O3\xf5H\x1d\x0f\x05Y\xf58!\xac\x1e*Th})BX\x8f\xd2^\xd4j?sS\xf9)\x11I\xacu+Fz\xb8\xdaJ\xb5C\x1a\x14\xb4 5\x91\x0e\xeb\x8b\xbb\x15\xa3\xe0\x9d^\xc9t\x89\x12\xd8\x8a\xec!\xac\x9d=\x96\xe4\xb6\xddJ\x9f\x95\xf6\xd4\xe2/\x7fn\x9e\xeb\xfaC\x93~@)\xa2\xe1pQ\xa2Ma9\xc3\xeaO\xa3\x0d\x82z\xd6\x89\x06\x7f;l\x90z\xba\x9cQ\xf8&\xe8\x843P\x0d\xcf\xf2&\x01\x81|\xcc\xc2\xc6\xf2\x05\x11)\x87\x0b]\xb4K\xecc\xeb\x0e0&Q\x91\xef\x94!x\xff\xfe\xef\x9c\xb9\xfc\xfc\x88\xff\xac\x07\x93\xff\x06\x89Z\x17\xf1\x1d~i\xd6\x9d\x8d\x14E\x1f\x9bWB\\\x1a(o\xc7\x84\xd8|I\x84\xc2Qfk.\x9f\x87\x9cp\xfa\xad\xd7\x10\x1eh\xa5Mo\xad\x8c\x1f;\xb9a\xb3X\xaf!\x92\xb9\xe2\xb5\x81\xe8\xa6v\xc1\x1c5\xea4\x90{\x89\x91{\x01\xcc\xd7\x8a\x7fm\xa1hS*\xdal^\xbc\xc0\x1b\x93\xc8b\xcbxs\xa8$\xe6\x1cIQ5\xd1\xb7\x9bH\x90\x1d\x17\x8e\x07a\xcd:\xda\xb3mY\xc8\xa3\xca-\xd7%\xba+2\xbe\x91\xf0I\x02^uV\xa1\xf7\x83 \xda\xe3~\xd0\x8bzB\xa3e\x82~cm\xd5\xa6\xf5\x9dkm.u\xc9\xcc0\xf2.\xacP\x97\xc7x_\xa6q9exIq\x19\xa8Y\x83^\xda\x8b/xQ\xc5\x18\x95\x08\xd0|\xda\xd0\xac\x8d\xdd\xf8\x80n\xbc\x18\xf5/I\x04)zBz\xf5k\xb0l\x18AWB\xca\xfc\xa2\x87j\x18\xc9\x80\x87\x15T\x88\x13\xc88\xec\x1fDq\xf8`J\xbc\x10\n\x15\x00\xb9\x8b\xf2S\\\x10\xd5(\xb7&}\xc0\x11xq\x12\x17q\xb4\x107P\n,*\xabr\x91\x82\xae\x9b\x83!\xa6\x1c\xbf\x89\xd3u.\xd3)gl\xc2\xe2\x1b6\x85\xab;]\xffP\x8b\xec\xaakM\xcb\xd1w\x81e\xb5g\x9f8\x9cQ-\xdb{y\xb1i\x1e\x19\xca\x84\x9frG\x1d\xc0#\xd3\x98]\xb8Q\x1cA=b\x02\xe5\x90\x86r\x0d\x1cA^\x1e\x07e\xc5j\xf5)}5GJ\x8a\xba\x13y\x06\n\x97Q \xaf\x1f\xfb5\xcb\x95\x82KXh\xc3kW\x8d\xf4\xaa\x0bL\xee!\xe8y\xc0\x17\xd6\xa3i~A4\xa6\x08z_\x18\x9fp\x1c\xe3@,\xf8\xaf\x9d5\xc7\xaa\x9d>G\x96d\xb3\xadS\xed{\xa7\xbd\x9c\x96\x0f\xa8\x84\x0e\x9e>\xe2\x08\x92\xb6t\x87\xa5G\x1f\xbe\xae\x0f^_\x0cm\x80Ay\xb6%\xfe\x9e2\xf0\xde\xdc\xfc\xb6\xcd\xbcag l\xbf\xe5\xa9\x8b\xb6\xf4}\x18j\xb1\x01\xd2\x92\xb0g\xc1s\xd8\xde\xe64={\x1e@*\xe8y\xe1\xb3Qr\x89\xcaT\x87\x1dh\xba\x19\xd4\xb5\x83\xf1\xc9A\xe0{E\xfaq\xb5b\xd9I\x943\x97\x15'}Hv\x02\x0eqA\xaf\x06\xb0C\xd8\x1c\x8bh\x97\x94\xaf\x7f\x81>_\"%\xc6!\xec\x14\xf0\x12R \xcb\x14\xb6\xd1h\x0b]\x81\x12Y\x90r|\x0c\xca\x8f\x12\xd8>\x844\x10\xe0\xe6\x1f'\xf2\xe3\x04v\xf8\xef\x97/1v7\xff\xe3\xd0\xcczU.h\\.U\x8aK\x95\xc1\x0bH\x9f\x07\x10\x8f2\xb4\xa5\x19e|$\xf4a\x17\xb7\xac\x92\xb9D|.\xc2\xc2\xd5\xf7F\x7f\xfe\xf3z\xb7\xdf\x9f\xfe\xf9\xcf\xeb\xe9\xd3~\x7f\x87\xff?\x9b\xcd\xfe\xfc\xe7u\x7fO\xfc\xec\xef\x1d\xf0\x9f3\xb6\x8b?glw\x86\xdfL\xf1\xe7n\x7f&J\xfbL\xfc7\xbb\xdc\xdc`W\xce#\xe9\x15,/\xdaM\xcf\xbabG\x08\x19\x85 \xa9\x03A\xe2\x86\xbdD\xac\x1a\xdee\xc6\x12\x03\xf8\nmo\xa7\x97\xb8v)\xbc\x80\xf8y h\x9e\xcfw\xd7(\xbdD\x0f0\xc76\xdb\x90\xb8U\xdbl\xf0\x9420\xae\x84\xf1J\xcdA\xc6\xd7\x8fI\"\xe3\xd6\xb3\xa0\xe1\x9a4\x04)\x9c\xf6\"\x05\xad\"H\x89[\x83\xa4M\x84US-\x99,ZQ-v\xde\x11(\xdeLXldhx5\xea\x13\xa6\xcf\xa0\xd6[\x04*\xb7\xc5{<\x0f\xb9\xec\xe5\xa7\xd5A\x17c\x1eHs\" \xc7)r`\xd7\x07`\xd7,q]e\x00\x88{9o\x14/\xb4\xbe|A'\xc1\xdaG_i\x94)\xbfO\xd8\xad\x1f\xf7N\xf0\x17\x97\xe38\x0bo\xe0\x13\x7fT\x15\xcc\x8e\xa0\xef\x9ax3\x94\xb3ng\x05\xfbd\x19\xf5\xc6\xba\x04}\x9c\xdf%\x13%,\x9b\x82tM\xd6vUZ\xeb\x95~\xcf\x12\x116\xc0U;\xd7k\xbf\xcf\xd2\xcfw\x97\x8e\xab\xf7\x16\xf9\x18\xad\xff\xdb\xc4\xe1\xcc\xe5F\x81\\\x0c:\x95\xe2_\xeb\xf2\xaf\xb8\xfc\xab\xcd\xc8\x86\xa2\xdd\xb6\xd6\xa1\xc52\xb8y\x92\xa5i\x17\xb5\x01\xdd\xeax\x0d\x11m\xff'\xfe\xb4d\x86jmY\xf8\x8fm\xd2\xecWj\x11\xf4\xd4\x10\x1b\xa2\xfa\xa0\x1f\xf8\x89\x7f\xb0\xff$\xd8\x88{ih\xd0\xdc%b\xf3\xec?i92\xcbKo\x19\xfa\xc8q\x80\nv\x15\xad\x0c\x95.\x06\x8a\x92h\xab\xa2-\xe53\xb4\x95\xfa\x89\xf0kV\xf4\x1c#\x02&h\xae\xaa\xf7\xc7x\x97m\xa7r\xc3\xacim\xdc\xee3\xda0\xe4\xc0\xca2\x14\xa1\xb1n\xed\x15\xa7\x07\xbbm\xd8\xae\xd8\x80<\x84E\x08\x13\x8a\x19@g\x02\xf8\x9e\x0c \xaf1\x8cv\xa9\xc8\xa8Dq\x07x\x1f\xc6\x019E \xfb3@\x1f\xdd\x97\xb0j&%\xc2\x8f\x9a\x9f0\x94nm\xce[\x11\xc5\x9a\xe85\xc7%\xb6\xdb\xbaq\xf08Kq\x87f\xbd\xbf\x96`\xe0\x12\x17?\xb63B\xf4\x04\xc5\xf9\xa0\xbb\xb8\xa0N\"!k!dE\xce\xfb\xdc\xc0\x0bX=w\x1d\xe5\x98\xa7\x96\x8c\xef\x02\xd2)\xba\x18\xdd\x10we\x1c\x00y\x80M\x8c\xf9\ns)\xd9\xbf\n\xe1\x0eC\x1d\x15\x88\xa1\x13\xcc\xca\xe8\x8b8F7\"\x9d\x13\x7fK\xb7\xa6\x99r\x8c]*\x1f^o\x1c`\xea\x9a8Y;\x92\x0c.\x0d\xcb:\xfd\xb9\xcaX\xf4\xc9*\xb1I!:\xa77\x8db\x0b\xa5\xf1V]V\xed\x93\xd8\xbf\xc6j\x9cA\xbd\x13\x9a\x1a\xbe\xfb\x17\xd2\xcdTl\x8bIP\xe1\xd2\xb50\x06p&\xbdl\xea\xb1 \n\xe0\x84\x04\x90\xd0\xf8*\xe2\xa7\xc4\x18+\x86/\xd0\x15\xee\xa3\x85\\\xdar\xe0\x8e\xe1|\xeb\x82\x90\x87\xc8\xa4'<\xcaQCZ\xfe(\xeaN\xe9\xf8\xd7\xbd\x84\x95o\x92\xf35\xc9\x9e\xc4\xac\x9a\x98\xefT\xcc\x97\x84\xa9e>N2\xbf\xf7$\xe8}\x8c\x93\xe2)\x8a\xb1\x0fr^\xee>\xa3B\x80r\xb1\x87\xbe\xc79\xd8\xbf\xaf\xe8)\xe2\xa5~\x93/\xddSz\xac\xbb\xedcr\xeb2b\xa1\xa5q(g\xf8l\x8e0\xf4_\xe6\xc7!$\x1dp\xa4D8x\xfc8\xf03\xc7\xd6M7\xebc\xd0\xa7\xa3RqN\xcd\xbf\n!'&v\x0d\x870\xf2X\x96\xa5\x99\x17\x827Y\x08\x7f5o\xca\xf2\"K\xef0\xb0N\xb4\x16\xef2\x96\xaf\x97\xcc\xbbt\xb9\x08\xdd9\x11&\x06y\x1b\xc3a\x88\xde\xe0ROf\xce\x154\x1aU\xe8F\x86\xb1]\x0f\xbd\xc9\xc5\xed\xd3\xdbt\xca\x9b\xdc\xdab\xda\x0b\x19Z\xd9\xb7\xeb\x99o\xbe|\xc1O3\xb9\x7f\xce\xca\x12\xc7\x1d\xa40r\x98\xc7\xd7\xf3\x9f\xa3\x82eo\xa3\xec\x93\xbd& id\xd5\xeeO\xed\x1f\xac\x89\xd1\x1d\xc1\xe0\x00\x8608\xd8{\xba\xef\x80Bm(\xfc,\xe0S\x12'\xa42\xa5\x10\xb0\x88\xaa\x82(\x90\xd9c\xd6!\xdd\x08\xc6\xfb\x9d-\xd24\xf3\xedr\x15\x96@\x08\x8a \\\xeeo\xca\x84\xed\x18\xe4R\xcb\xd8\x1e\x8b<\xe9\x9c\x8f\xd5_\x9d\xa4k\xf4\xa5W\xf5f\x8b\xf4V\xa4\x1a\xd7j\xb2D\xa4\xc8/\xf3\xb5\xb3d*\xe8W\xed-\x87\xb2\xf8\xb6|\x85.>\xc2\x9d\x05\x7f'\x8cM\x15\x91\xac5(Z\xa3\x8a\xd4\xda\x89 \x8aF\xfbbC\x9cO\xe6l\xba^\xd4G#\xf7\x8f\xf9\x12-\xe9N\x93I*\x87\xca\xacw\\\xae^\x17\xb3\xa7*\xe3|t\x1b\xc5\xc5\xab,\x8a\x13\x0dNr\xaeo\xd3\x8c\xd5\xdb\x9f\xa4S\x96\x99\xe0+{\x13oY\xf5\x8a\xa3\xc4\x1c/\xb2\xe6\x92\x82<\x0bzBE\xf1J\xb4\x15\xd8M\xb3[\x98\xfbU#\x81\xdd\x8fVX\xc3W\x97\xe7\xd7\x95\xdb\xf3\xcb\xa4\x1c[\x88\x8b:e\xb8\xaa8\x08>\xb4+\xd2\x95\x0dG8\xce\x8c\x03\x92\xd7\x17DK\x04\xa9\xa8\xad\xb8\n\xf1 \x14\"4\x03\xcc\xebV4\x06\xdb/w|\x10\xba\xd8f\x89\x1b\xda\x87\xea\xcdaU\x1a`\x14\nW\xdcx\x07 \xc7\xd5m\\\x16B\xeab\xe9%\x17\xc1\x0c\x88\xd8`\xabL\xcd\xe1\x08\xfc\xc8\xd8c\x9d\xf8\x04\xd4\x8d\x8b=\xac\xd6\xc9\xee\xa7\xaa(\xf1\xcc\xd5\x1ah\x9c{Y\x99\xb7\xde\xe4b\"\x94\x01\x8a*!\xd4%\xddRy\xd3\xc2*\xb1\xd06o\xb8N}aX\xb1\x91d'\xf6\xed\n\xa0\xb9xI\xb9\xfa!\x9c\x93\x97\xf7\x1ct\x11\x86.\xf2\x91f#\xbew\x82+B\x81\x9es&\xa2\xe4,zq.\xd8'?\x13\xce\x07\xfa\xb6A\xcd%e\xbb\nztn\xa5*1NKa\xa8W\xf7Mz\x9d\xdcD\x8bx\nI\x9a\xec\x88f\x1f\xc9\xc3a2_'\x9f<39\x9dz\xf0\xb8wLDnk\x02n\x11F\xb0\n!F\xe1\x93\x13p\xbf\xe4bb\xcc\xc7c\x0cY\x1a\x9c\x96\xf1\x97\xfb\x1c\xa3]\xf37?&\x93\xc5qi\x16\xb3\x0bi6\xc7\x1c6\xcdv\xde\xc6\xdc\x16\xbdY\x96.i\xdc\xc0 f\xfc\x94\xd6\x8f<{\xbe\x9aC\x9e\xe0({\xeb$\x9f\xc7\xb3\xc2\x0f \x9a\x15,\x03\x96L\x81\xdd`\xf0\x8f\x00s80\xb48\x10!\xfa\x10X\x02U\xbb\xb4\x8d[F5|z\xf6\xa3h\xd2\"\x0eQyd`nK\x0em\x8c\x0bXn\xda\xdb,\x96\x97{&\xb4\xa5\x8e\xaeJ\xf5\xa5\x8fw\xc0{\xfbT\xed\x9bz\x99\x0ci\x8c\xe9\x9ej\x03\xa2\xb0\xcfT,\xb6\xad\xd5\x16\x93`\xe2$\x84\xd5\xb9 \xdc$r\xc0/L\xe6\xb0b\xba\x98\x93\x8e|\xf5\xcd\xf8\xe3\x0e\x1a\x7f\xab\xd1xj\xc0E\xc9E}\xff=\xd4\xddEp)\n\xc1\x16\x1d\xf1)\x88\xb5\x9eFE\xc4\x97\x1ac s\xa0\xf9}\xb1\xa6\x1d\x89\xa2@\xd2\x92\xa6*\xe4Kx\x1b\x14\xa5\xad\x01\xee\xfb\xef\x914\x06\xa1XT3\x10d\xed\x17\xed\x94q\xa5\x87q\xf2J\xc6\xeb\xdb\x93\x9f\xea\nc\x82\x7fP\x01\xad\xea\xaf+\xce\xcf^bB\n\xae\x8d\xc7\x89\x80\x8e\xee\xfd\xc6\xfe\xf9 \xdf\xee,\x13\x82\x06\xbf^\xc5\x88,\xd5\xdf\xf5\n\xe3u\xa2\xd7)\x7f\x19\xb5\xaa:\xad\x87\x99\x90\x06\x10;\xd6\x8b\x05G\x10+\xccw\xbdq^\xb7K\xc37\"EE\x06\xe4\xf29\xc9AVG\xf4\x04\xcfoC{Th1\xdb|\xa4kxld&7/r\x15eu\x86\x9b\xa1;\xa1 \xfb\xc2\xba\x07U\xac\x9e\xf4\n\xc3\xa0\xa9\xe3*\x1c\x1a\x126;\xfcH\x1d&r\xcf\xb5\x9e\xe4\x97/_\xc2\xa0\xf6k\xb7\xf6k\xbf\xf6\xebi\xfd\xbb\x83\x10\xd8\xf6v`:]\x83\xe0\xb6\x03T>\xbd\xa8q\x17\x0c\xe7\xab\xa0\xa9\xcf\xbc\xb04\x06\xfd\x10\xfa\x1dc\xdb\x9c\xd3PPW*\xed\xc2\x97\xdd;\x97\xf3-e\x05\xc7\xfa\xa9\xef\xf1\xd7\xea\x9d\x17V\x8b\x1eP\xdfH\x9d\x88\xe2\x04\xd2*\xf5\xc6 \xba\xa3\x0d\xe1\xa4f\xe6\x02\x0d\xf3<\xa1\xe7)\x87\x04j\x92\x9e\xc8\xb0\x80\x0c\x87\xfe\xee\xc2N\xea@\xf7\xf3\xc9}\x82\xd4\xf4!\xc8\x82\x9b\x1a\x92~\xa8O\xf2X\x10\xd6\x8e\x13\xbb\xca!\x864\"\x01\x0bXV\x9c\x16\x17\x10\xce\x9c\xab\\\xeaK8x\x8bx\xf2\x89\x1ag\xa7>\xde\xb7\xaf\xb0\xc2v\xa1y\xa3zB|w(\xe6,eZ\x85\x90\xa8\xd9\x96\xe8\x18\x82\xb9d\xdarn6\xa5\x8bo%\x02\x88bS\xdf\xe3\xe3\xa9m\xeb\xe7\xf5AJ\x0b\x01\xa5|\xf2\x83\xe7\x86\xc0\xe3\x1a\xe1\xdb\xb6C\xc88z\x8eDWH\x1d-F\xa9{\xaf\xe3\x98\xdeu\x13I\xfaB\xfbU\xb9\xb0\x08\x07\x16\x0c7D\xe2\x15_$\x91\x93\xa4\x16^\x8a\xb8g\x92%;\xa6\xf4\xa0\xff\xd2\x15:\x99\xd8\x93\xcd\x1a\x02)Mx\xe2\xecd\x9a\x91$\x9f\xef\xc0\xb4\x95\x02\x0d\x01 \xa5\x0dM 1\x8a\x00\x8d\x9er\xfd\xa4r\x832\n(\xa9\x9b\xd0\xfeZ\x9al\x0d\xc3\x0f-\x99\xee\xcb\x17\xa5f\xa8n\xac\xe5\x8c\x87`\x89\xef\xa2\x9d\xb0\xfc$l\xd4\x01\xbd\x16\x97\xc40\x84s\x95q\x81\x13D\xd7<%\x81>T*\xa8@k-p0\xfe\xdf\x7f\xafzq\xb5\x8d|\xb2\x0c\xd0Q\x03\x8d\x13}\xa6\xbe\xc7\xebUJ\x82\x10C|\x18Q\xae\x04\xe4\xaa\x93\xc6\x96\x97q\xfcS\xe5\xf6\x00\x0b\x96\xe7P\xcc\xa3\x04ny\x8de\x94}\xf2\xc4\xb8P\xb9\xaa\xc0\x86\xcd*\xd1\xeeH\xad\x05\xff\x91\xe2\x95\x19\xde!\xa4b\xe1\x91\xbf\x93R\xf94\xc5\x01{A\xa8}_S\xa9HM\x91\x05@J\xa3T\xd38\x9aJ\xb5@or\x10\x1a\x82\xb0X\xc1\x04WP\xae\x8aX\xdaL\x1e\xf1}8*\x05\xbc\xa1<\"\x8f\x1cz-\xfe\x7f?\xd0u\x7f;\xa8\xec$gQ\x02\xd01\xa3\xa4\xdaJ\x9a\xc2C\xe2\x8f\x1a*\xea\xc6\xcbk\x94\xda]\x14?\xb0\xea\xa7\x9b\xa1 \x1ew\"(Z\xc3\xc4\x85\xa6\x80x\x00q\x8e\x81s\xe3\xe5JdH`6\x1d6n b\xcc2\xd2\xca\x8c\x96\x82\xd6\xf7B\xb8#\x8b\xa7Y\x14'^\x083\xb2T\xed\xcf%Y*g\x17\xc2\"\x109S\x8d\x8f\x13N\xaa'\x0deWd\x99\xa467AX\xc6\xbd\xde\x8au-!^\xeb\x8fo\xb3\xb8\xa8]\xbcn\x99/\x91\x08\x96\x9f\xcc\xa88\xb9_\x1b\xd6w\xe2\xbc\x8a\xc6\xb5E\xceP\x18\xeeM;\xc5\xb2\x8e\xeb\x06#\x1a\xef\x8b\x04\xf2\x8c\xab\x8cQ9^\\X\x17\"\xea!|\xeb\xc9X\xc6\x02\xc6\xd5.\xa0A\xac\xb20Pes 24\x00\xd4\xb2!8O\x05\xc4$1\xc1P\xb6\x14*j\xc5Jk\x1c\x8e\xbeBt\x91\xd1@k\xe4\x12\x1d&%qW\xa1\x0ej\x15^\xc2\x80W\xda\x11\xcd\xbe\xf3+\xfa/x\xcc\xad\x95b\xa2f\xd1\"g\x80\xddB\xc6\xf2U\x9a\xe4,\x04ek\x9e\x98\x17\xb0\xb5%n(\xdd\xde\x96\x93\xeb\x8bl\xca\xbc\xbdMw\xe3\xb2\x05\x88\x8aT\x15A\x08W~+5\x13\x08'\x10L\xbc\x17\xe7\x82\xc1\x98\x10\x11!\x9a\x06y\xed\xdcV-\x84\xf9\x8a\xa4 \xee\x8e\xee\x9ai\x93l\xbb\xf5\xb8\xd8\xb4\xdb\xab\xa6n\xab\xc3.\xe9\x89\xbf\xbb\x9d\xfdJ\x9e\x15;\xb1$\xfed7]o\x07\x00\xac`n\xba\xb1\xef*c+\x96L\x15P*/=\xb3D\xe4\x98iP\xa1\xf7\xc6h\xc2\x97\x0b\xe4\x91?F\xc5%\x1cA\xe4\xeb/\x02\xb4\xe3\xab~\xd7-\xb2j\x9f\x1e\xc2( k\xaf.\xb1\x8a\xf0\\J\x1c\x04OCeu`\x8b\x03\xa5\xce\x1f\x88w\x06W \x90^\x9e3|3\xc7%\xa1\x95w{\xc8\x8aU7r\x89\xbc\xcd\xf3\x03\xebR\xdf2\x82\xb1\x18\xf3&\x9d\xd5F*\x03\xf7\xdaWL\xd4\x90Jz\xc1\x1f\xc2\xc9%\xd6b9\xeb\x1c\xbdR\x11\xce\xe3\x9c\xfeh\xe0\xfe\x88U\xcc\xa5,\x87#lIXq(\x89Q\x96\xe1Qi8f\xd8^\x19\xfa)8\x90\xd6\xf0j\x11KvA\x18\x13%R\x92%p\x18\x9d\xfd\x9c\xfcB\xe9\xf0#\x0f\x0b'\xa8S\xa8\xcf\x9c\xde,\x9b\xce\x8an\xa5\x163\xb4\xff\x1cb\x0c\x15\n\xf1\xf6v\x00\xd9(\xbet\xc1\xa0Qak\x19\x0e\x01I\xa6nd\x9c\xc3w~Q\x9d\x9f\x0d:8D\x89H[l\xf9\x99\xca\xd9\x13\x850\x08\x0c@\xec\xa0\xe4cc\x93d~\x14\x08\xe5_\xa3\xfe\xa5\xb6{]\x0b\xdf\xb49S\xeb\xc6\xb5Ib\xcek_Vn\x10\xd2p\x83\xc60A\xd1\x05g\x12\x94\x82\x98\xdb\x00\xadT=(\x02C\xf0l*FRe\xb3\xa2\xdao\xc1\xe5.B=\xe0]Q]\x89\x9c\x11.G|\xe7R\xef\xc5\x85\x88\xa5\xc9\xc9\x1c\x0eM\x99\xa6\xec\xca4}\xcey\xa9<\xd4\x04\x853\xb9\xa6\x9b\x1c\xabM\xeb\x1fM\xcb\x93\x0e\x0e\x0d\xcc\x08\x0dU1\xdav\xb4\x98\x19\xde\xc8@\xfb\x9d\x00]\x9e\xb9\xc6QS\x9d2\xcc`\xf7[1\x15\xa4YJ\xdd\xd0D\x19\x1fY\xe6'\xf5\x1b\x88\xf7\xa4\x01\x12\xe0\xd9*\xd1<\x08(;CC\x0f\xc5\xb9\xdb6@U\xaaV\xbe\x8b\x04\x87\x0dr\xb2B\xc7\xd1\xb0E\x82\xb0\xe3>\xc2\x83\x1b\x99w\x87\x05e\xfd\x1c\xd1\x14s\xf2\xab\x0e\xd3\xbd\xcd\xa2\xd5F\xa7\xbb\xfb8\xef|\xf6g\x8e#\xa2<\x1eR\x8c\xc7\x83\x0c\xa5\x10\xa7[\xc5^NN\xa6\xbe\xc7g\xb3bS\x90\xc2}R\xf7\x97P\xba\xf8f\xc9\x99 \xcb\x87nnP\xf2\xec\xd6\xaf\x0f\\Z3p^c\x16\x9a\xa9\xb6\x8d\xbc\xa5&A\xf2\xd6%,HW4\xfe\xe8\x90P\xc2i\x0d\x14~Z\x9b\xa3\x90SS\x8e.[\x89\xe17R*\x95QS\xafY\xef\xa7B\xa4\xf7\xcd\x0f\xb0\x9e\xb2JQb?\xce/\x0d\x04\xd1U\xba\xf1R\x90\xa4\xb6l\x806\x93\xba\xcf\xd4<\xceG\xe9%\xd4c7kR\x81,\xf4UE\x0d\xa9\xdb\x1c\xee[\xd1K\xab\xcb8\xf3/B%3=\x85F\xc7\xf5\xfe\xca\xe1\xdc\x80\xfa\x1agt]^1\"\x83\x84Hp=\x8a/\xb5\x9d\xde\xbb\x8a\x93\xa9\xa4n\xbc\xa8\xc1#\xa7\xd0\xbd)\xdb!\xa3\xa1\xd0X\xde\x1f\x16\x81\xf2\xfe\xce\x14\xe7Z\x89\x11\xf6Di\xda\xd3\xc5\xddD\x91\x90\x9ao7\xe9z\xc2\x92\xf5\x92e\xbc.\x97\x13lj\xb3\x91k\nEak\x17G\xf6\x1c\xeb\xb3C\xbf\x8f\xf1,K\x97\xfcT\x86Cx\xfb]UV\xcf\xac\x10b\n\x1eG\x82\x05C0\xae\xe5j\xb0\xe3Mti\xa2-\x1b\x90\x88\x99Q\x16\x94\n\x83\x94<\xaa\x1b\xb4,_\xc9Q\xd7?\x97~,\x1d\x0c\x8f\xee}\xd7\x03m~D\xee\xd0\x02\xe23K;M\xbc\xaeZsn:\xf4\xb2\x8e\x84\x9f\xde\x11:\xe1\x94\xd6\x9b\x1b\xf4\x83p\xae\xb1\xb3%\xd3\x93*yA9Y\x08s\x9d{\xba6i\x17\xa7\xd6\xc0\xfcF\x08\xd4?\x96\xaf\xfd\xf2\x04 ;h\xb8\xb7\xe4=\xce\x11\xe7\xcb\xf5 &bv 5(\xf3e\x1dV8(\xbc~E\xd0\x92\xfa,\x87\x9cU\xfbYzd\xb5\x10\x93{\xc3}@\xf3w\x99\x1d~\xc1\xf2\xa1\x996\xb6`\x84u\xf8\x96\xe5\x1d\x90\xdf\x12#\xb0\xca\xcd)\xd4+\x08]Vs\x1b\xc6\xa2\x9aNU\x06\xf9\xe9\x9ca\x87\x0c\xc8\x96\x95\xa1g\xaa\xfbvDd\xafL>\xabG\xcf\xca\xd9B\x04\xb5\xe4\xff\x7f\xf9\x02\xb7q2Mom\xfa\x92\xd2\xe1\xef\x91\x93p93\xd1Y.\xa0\xc4\xb4xZ\xf9N\xf5\xc6h\x89\xfd#\xd2K\x07x\xf0\xcb^\xce\x8a\x8bx\xc9\xd2u\xd1Q\xccI\xd8-\xc4~*N\xb0\xeak\x8c\x87P1@!\xe0\x00d\xa1\xa5\xb7\xc0~_'\x05\xcbn\xa2\xc5=;V\x9f\xd3=\xabR\xa2k}d\xa8\x80\xa9}\xd0*\xffH.\x1f5\xb1\xbe\xd5|\\S\x97fl\x86\xb6\x91\xba\xec=3\xe6k|\x84\xed\xb6\x81\xa4\xb6\xc6\x02\"YX\xe2\x011g\x96d\xe9b\xd1EA\xa4C\xc7g\xbc\xb9\x05\x93?_OQ\xfc\xd0_\xd9\xf8\xc5{['D\x7f\x0f\xd2\x99i\x0e\xc7{\x1b#\x9c\x8f'E|#\xb4\xaf\x91\xfa\xf3[:\xa7/\x08\xe5M\xaaV\xd5\xaeW\xc0\xcbC\x99S\xc9l\x15\x0e\xa1\xda2~+/\xcaz\xe34Q\x93\x17\x97\x12\xe5o\xea\xb6\x87p\xb9\n1\xa4\xd5n\xa0\xf6\xdcr\xc9\xa6\xb1\x08\xce\xd2N\xc2\xea_Ta+*Rh\xd5\xe08X\xb2.za\xb9\xf36\x1c\x82\xf1\x0d9\x08\xbbNm\x18\xf5\xe2\xea|\xe8\x94\xe0lc\xe6\xd9\x11S-Eeb\x9c\xebq\x88\x9a\xf1SY$\xe1\x9d\x82\xe7\xc16\x17\x82q\xbeE\xfa&\xbd\x15 \xc9|\xa7\xfd7\x1a\x11ys\xf6\xd9\xa3\x8d{D9FBj\xa9\xb0\xd3\\#\xca'q\xdcX\xe3*N\xa2\xec\xae\xb9J\x94\xb3\x83\xfd\xe6\x91L\xf2\xdd\xb6\n;-5\x8a\xd9\xe0`\xc1\xda\xea\xec\xb4V\xca\xa2[G9h\x1e\xda\xfd{\xda\\\x95\x1e\xde\xf6\x16\xaf\xefnG6,\x8a\x931\x08\x95B.\xdc \xac\xab'\xb8\"\x81\xed\x0c\xbc\xba\x90\x92S\x11x\xd6r\x11T<\x7f\x1e\x94\x03s\xb6\x0c]p\x17:\xe1\xafz:\x0c\x12\xba\xa0!tBE\xe8\x88\x8e\xd0\x15%\xd5\xa3M\x03k\xb7\xcdd\x11\x15q2h\xed\xbdq\xf7\xaaG\xf5-\xdbl\xeb\xbaq\xbbC'\xd2\x02\x1dh\x9cz\x94\xba\xae\xc1\xe8\xa9mO\x82r\xb1h\x0e\xb2\xa5\x1eN\xb3}I\xb4\xeb\xf4ZD\xa3\xd0R\xd8\xea\x0f\xa5#\xa4n&\x1d\xd1{\xc5\xe5b\xed\x989<\x94\xd1\nE\x120\xdb+\xc4\xfb\x98|J\xd2\xdb\x04\x14\x15\x18\x82\x18\xb6[{\x88V{uJT\x05v(#\xd3Q,W\x07\xb4\xc7F\n\xf6\x99C)/\xdb\xe4\xac\xd3B\x80\x8e\x88\xd1\x08n#\xd7VR\x81\x1d\xcc\xe2\xc5\xe2M\x84z\xba\xf5\xfd{i\xc4j}^\x93\xda\xbcf\xa2\xc7\xbd\x8dzlDX]\x89),\xc0\x0ea\x15\"\xe7\xe4k\x1d\x9b\x92B\xed\x17\xd6[Dy\xf1\x8e\xa1\xa0\xadB#\xf2W\x17i\x81\x92\x92\xfe\xeed\x1e \x9f:\xdd\x1f\xb0\xa6\x0d,\xff,\xcf\xaa\xc8&\xf3\xa5\xa9\xc5\x8bC\x18\xec>QIb\xe0\xe5Kx\x0c\x87\x87p #B\xe3\x9b}\xfef\xb0\x0fG\xb0\xa7^\xed\xf1W{}8\x82}\xf5\xea\x80\xbf\xda\x85#\xd8\x19\xc0\x10vv\x1b\x87\xb4v\x1c\x9fJ\x1bXM\x7f\xa7\x0e\"[\xca\xdf\xc4\x05\x1a-Ov\x9f\xf2\xbd\xec\x0f\x9e\xed\xc2\xf7\x98\x14<\xd0\xac\x99\xeaK\xe1\xfd\xdf\xff\xd7\xff\xe9\xa0\xb2\xe8cTU\x97\x16\x83\x9ak\xd8\xa0\xe9h\xa5\x062p\x0dd\xd08\x10\xa0\x06\xb3k\x0c\x06\x7f\x9b\x1d\xee\xba:\xdc\x95\x1dv&\x9e\x85T\x88>\xa7\x90L\x93$\x12t\xb0\x1f\x1aX\xffB\xf36\xc3x^\xe8\x97YCy\\V}\x1f\xf0\x0f\x03c_\x94\x89\x0d\xeb\xfcVho*\x11\x17\xac\xa9\xa32\xc2\x99\xbe\x9f\xcb\x11\xefh!\xd0\x9a\xf7^N\xaa\x00\xf8z\x95\xd9T8\x8a\x07\xf0\xaf\xb0\xcb7P\xbfI)_\xa5n\xf4K\xf2\xee\xb6#i\x0e\x04\x80\xd7\x91\x93y\x94\x9d\xa4Sv\\\xf8\x9a\x0f\xac\x199Z=\x18b\x9f\x8b\xdd\x8f\x1f\xef>;\x004\xcc\x7fq\x08\x8f\x0f\xf6\x06\xcfj&_\x06.Y\x04m\xdfX\xb8Q_\xa4-\xd6 \xb2{i\xd6\x19Xu\x06\x97!$\x95\xa3\xfa\xce\xe0\xfeF\x1e\x14\xde\x9a3\x19\x103\xd9m\x9f \x1f\xa5c\xe1*4C\xa87\"\xd2\xc2M1\xeb7\xe2G\xda\x81$n?\xa8\x9c\xec\xf5\x8d\xd4r\x11\xe4&\xc7\x0d\xdc\xcb\xb6ksj\x10\xe8\xdb\x01\xc1\xc8\x95h\x84\xcc\x84\xdcbj\xfc\xd66\xdb#\x89T_z\x9b\x1c\xd5\xd6J\xb2\x1a\xd2\xf1\xcc71b\x0fv !\xb0bOY\xa4%j5\x1a\xf1\xa3\xd6\xf47\xed\x87 t\x0c\xbf\x86iI\x0b\xcd\x9a=\x1c\xaa\x91[\xe9\xa8\x11;\xcaA\xf7C\x04\xb0\x81\xa9\xc3\x16lX\xb9\x99\x1d\xc7\xf9\xd0\x0c\x8ci\x03\xf3\xd4\x06\x0b\xada\xf5WQ\x8f\xe7\x06\x87\x10\xd75\xd3\x8a\x91t\x0b\xff\x95\xcdmy\x06\x95\x82\xa1\x01~\\\xb6\xd0t|\xee\xb4\xff\xe3*\xef%\xfab\x96\xac\x99b\xe2\x85\x9c\xe3\xe8\x18t\x03%\xd5Mhs\xbb\xf5\xbd/\xec\x14\xd1\xe5\x9bD\xa3\x04c\x92V\x00\xd71\x89\xf3\xfc\x9c\x10$\x81\xe2/\xeao\xf0:I[\x91:\xd4\xa5\x88\xd0xK\xf5\xc0\xf8\x8f\x1cV\x1d\x9d\xebc\x92RL\xe3]\xc2\x8d\x99\x17\xbd\x81\x01\xae\xec\x93+\x8aAs\x0e\x19\xbc\xe0M(\xd2hW\xba\x91\xd9\x03\"\xbf\x18e\x97\x0e\xfe#E\x0d}\xd9L\x8a\x8e\xbcB_\xaf\xa1@\x8aG_\x08)\xdd\xc8\xce\x0e\x0e\x86\xaf\xde\xce\xae\x10\xb3\x9b\x06\x86\x8c\x956\xb2\xa0\xf3\x18v\x7f\xfd1\xc8\xb60\xf8\xce\xa1\xca\xd2Y\x1f\xd5\x1e=*\xd5y}\xfb\xb8M\x8bQOhly\x9b*\x96\x01\xfb\x8d\xaf\xad\xf3-\xb1\xa9\x8c\x1e\xa0\x01v\xc0O,\xcaMn\x0c\x9a\x05\xef\x0b\xcfijh\xf5|a\xf5\x0d\xa3\xa9\x17\x9a\xa9g};\xbe \x08\xa9C4h\xe4\x85\x1eT@\xa9C\xeb\xde\xc3\xd1\xc4\x98\xfa\xa45 \xc68\xa5\xeeu5\xa3\x9b\x1ei9Nn\xb4\\Pt\xa63LcS\x164\xa9\xd7\x11\x87\x11\x04\xb5\x84*\xf5\xb4 \xb1\x9d\x01\xabfu_Zc\x14Y\x94\xe4\xb34[\ns\x0c\xca3\x06C\x83_\xa8z\x1dl\xa7\xc0d\x9b\x8d^h\xa9*\xe9\x95\xb5\x9a]9*\xb1\x0d\x0f\x9c\xc9\x95[J\xdb\xca\xea\xf2\x983v\x80\xe068\x84\xae\xa2\xc9'\x15\xaaf\xb9^\x14\xf1j\xc1\xa0\x88\x97,w\x86\xbcW\x03\x99\xaf\x93O\xa5\x9bJ9\xba\xea\x8d\xcc\xfaW\x94W\x852ut\x88Y\xf8\xdc\x93M\xbb\xda\xc5\xf3'5Lw\xfc\xd4\x8al\xaeLd\xe1\x05\xa4D\xe0\x8d\xaa+\xdf,\xb6z\xfcZ\x99\x81Ri\x04\x19\x9bj\x88C\x99I\xeakN\xd7\x90`\x14\xf1.\\\xc5\x1c\xf4\x8d5*u3\xafT?/h\xfb%\xc2\x13\x83\xaa\xa6E\xf3h\xcc-RNT3y\xaa\xde\x1d\xea5\xdc\xa9Ff\x8bu>\xd7\x1a\x10\xbf\x0fU\x89\xb2\xbaG\x9b\xedU\xc6J_\xbd\xa8M1J\xf1S\xca\x1d\xa3\x8eg\xe4\xc8\xf4\xd1\x1c\xe9\xbfj\x99\xd3Hnl]\x12\xd7\xfa\xa2p.r-\xc9U\xb5\x7f\x9a\xe7\xb1v\xb1}\xb5\xab\x14\xc2\x88\xd4\xe6\x12j\x99GY\x15\xee\xde\x8a\x14\xa0\x0eL\xeb\xa2\xe3$Z,\xf86\xac\x16y\x9a&\x0cn\xe7,\x81\xdb2\xa9\xd2\xd6!\xf4\xcd\\\x86B\x8bi\x10\xcd\x1au\xdc\xb0\xbb\xbc\x88\x17\x8b\xdaV3\xbb,!C\xb8\x03TB[j\xa5V\x0b\xb5w~,\xd8\x95x\xc3\xe0\xee:\x816']\xa3 \xa5\xdfS\xbd}\xcb\x9d\xac\x1ay}0\xb5\xfd\xd6&)X\x00\xae\xbev\xc4\x98qvk\x8b\xb2t\x97ug\xb3\xa63\x13\x85\x13\xfd\x80\xe1P\xa9\x1dB\xac|\xa3]\xb7\x17!le\x06\"\xd1\xf2Q\xe7#\xc7\xcf\x8c5\xc2\xf3\xe5\x17:q\xbe:Al:\x174\xdf\xaa4\xc2\xb6t;)t\x88\xe25\x82\x02\xb8\x88\"\\cW0\x0c\x93\xc9\xc0\xf4-.\xcb\xd7\x1b\x0dU\x93\x15\x03\\\xf4\xea\xdc\x960!\xb6\xb7A\xdf \x89\x8e\xa9\x1at\xfe\xccd\x14\xed\xd6\x8c-\xd6l\x90Q\xf8\xc2fZ\x10Y\xe1Cn\x12w\x83\xb8\xdc\x8b\xd7\xd6\x98j3\xeb$G_\xcc#\xa9KEiv\x1aM\xe6\xf5\x8aq\x95\xdf~\x92\xb1\x1a.tK\xdf\xab\xf0*\x16D\x93\xa4\xaa\xd2\x8a\xb4\xb4\x1am\x03 \xe7\x069\x8eug\xb4iV\x10M]\x12\x99`\xbe\xc08\x80\xc0F\xc9\xa5U\xf9\xab/\xf3f\xa3\\`\xaeUX\xd34\xc2}\x97\x8b\x84g\x00\x7f\xfb\x86&5\x0c\xd0Sen\x92\xb7\x16\x89\x1d\xb9jq\xfe.z\xe7c\xfa_\xd4b\x14B\x7f\x817w\xdf\x7f/\xd5\x15;\x98\x9b!\xc5\xe8\xd6\xc32\xfc\n^ \xb5\xa7O\xef4\xc7\xba\x0b\xce\xc1\x93\xa7\x81\xcf\x87$\x916\xca\xf3\xf8:\x81!\x16=\xfbV\x9b\xc2\x10\xd2\x10\xb3\xc9\x85\xb0\x0eA\xf5h\xec\xadNv\xbd\xd6\x85\x05\x7f\xb4\xb8 Evg|E{g-B\x90Q\x00I'\xacI\x9a\xcc\xe2\xeb\xb5r\xc3\xea\xd3\xcc\x7f\xe4t\xd2js\xe2\xc2,\xd8C0\xcc\x80\xb5u\x85IT\xda\x8fU\xa7\x93\xb8\xf4Xhw\xb9\x99%Y7\x0f\xdd=\xec\xfa\x90\xab\x91\x88\xd0\x86$\x14\xc3\x8d\x13\xd4\xa35\x0cJ\xa6\xa5.\x0b\x1d!ez\x0d?\x13\xf9\xc1\x05K\x81\x9eZ\xd5*e\xfa\xad\n^\x17\xc9\xd4\xd2\x83\x83 \xc4\x8c\xa8\xa3\xcb\x10\xe2v\xaa\x1aR\x1ap\xce\xf9\xacG\xec\xb2d\xe6\xf9\x8fz\x15${\x05\xf6\xf3\x1c\xd8\xce\xce\xf3@\xb9\xb9z\x91\x07\xdb\xe0oo'A\xa5\x82\xda;0\xe5zM\x8f\xa2\xdc&|o\x96\x88\x9c\xb9XTJ\x1c>o\xb0\x90Q\xeeC\xf0\x02\xd8\xe6\xff\xfcM\xb51K\xa4\xc3\xa68;+\xc7\x81\xe7\xf0\xf5y\x9de\xec\xbcF\x04\xc5G\xf9\xc6\xb1f\xaeD\xf2 \x9eZE`\xa9\x1e\xec\xbd\xc9\x9f\xc8OB3\x01\x95\x03\xfd\x81\xba^\xfe\xfa\xad\xc4I\x88\x1cT&u\x1a\xe9\xeb\x00\xaa\xaa]\xb3\xe2\xec6Q\xd5^\xb1|\x92\xc5\xab\"5\x0c\xa8#\xd7\x07\xef\xa2\xa5\x19\xd3d\xed\xaa{~\xb7\xbcJ\x17y\x87\x93\x89\\cA\x82\xe5\xd1\x9c\xf9\x85\x89\xa7('\xea50\xca@\xe4\xe7\x81bv*\xf1\x9b\xce-G\xae4\x7fpOg\xa1H\xba\x9eQ>\xb6\xfa\xd2\x93M\xa0\xa1\x86\xfd]\x1d\x81\\\xaa\x0e\xcc\xe7\xbe\xfe\x07\x9b\x89n\xe0SJ\xe8\xb4\x9c\xfd]\xbd\x95o\xdc\x15\x8f)\xfe7\xf1\x07\xfb\xe6n\x89iO0\xce\x9e\xde\x17I\xf9\xc1Fd\xc2\xe3\xfb\xa7\xa4v\xa3\xddK\x12\x0c\x19\x92+\\!\xbd#\xc1\x87\xac\xa9\xe5HF\xd9%\xfa8)_\x8a\x08\x05\x12\xf5\x85\xb5$I\x0b\xa0\xf5>\xba1\xfcr\xe8[[R\xdb'B\x10\xd4\xd3\xc8}\xf9\xe2P\xe0![\xefR\x10\xceY\xdbh;\xa1\x05\xcdH\x15!x\xe31\xcb\xdf\xa6\xd35\x9a\x9c\x98K\x89\x8c\x8e.W\x06\"\xde<\xda}v\x81\x88\xbdX9\x17\xae\xdf/\xd6\xd7q\x92\x0f\x1d{\x8be\x99\xab\x08\xb0\xed\xe9z\xc2\xb2|\x08~\x9f\x0b\xbar\xe9\xcd\xe2E\xc1\xb2\xee\xc4\x80\xf5>\xb1\xbbs\xf6_~\xd0c7,\xd3\xc8\xb4\x13\xb4`u_\xb4d\x0bD\xa9mT4d6Q\xb2?z\xb8f\"\x16aw\xb2\xefDg\xd6[\xb2\xec\x9a\xf9N \x19\xc5T\";\xdc\x06X0\xfe\xe1O\x0f\x8d\x08\x9a\x1e\xa3\xf2 N~\x0dtH\xe8pZ\xbf\x06\x805)\xb2.\xc2\xc5B\xe5\xb6k^\x97\x89\xcb\x0f\xf3m%\x94\x0f:\x0b\xe5j2\xa6\\./e\xec\xc9\x95\xaa\x03\xc3{\xfa;\xfb/>\x83\x85uG\xc5\x19\x9b!\x18WS\x0bv\xc3\x16\xc32`|\xadl\xc9\xf2<\xba\xe6Go\xe9\xe6\x8d\xb5\x8c\x1e\xff\xbe\xa2\xb7K\xaf\xd5\xa4\xe1\xb4`\xfb\x97\xfc|\xc5&C(z\x9c\xc98W\xda$\xfc\xf5\x87\x04\xd6\x91\xb28f\xf35\xe8\xc0\xb1\xaaok\xa2\x80\xd8\xa1\xf8b\x15 \xbe\xc4l\xba\xc2G\x87\xf6\xf0\xc9\xae\xa9\xd4\x7fH\xed!Er\x08\xf7\xf8\xff\x15\xf4\x80 \x87\x8e7\xd3\x11\xd2\xe4]q\x8f\xc6\xff\xdc\xab\xfe\xdc\x0f\x02a:\xf3\xf7'_\xb4!\xa3\xeb\xc0\xe8\x80\xc67e\xb41\xc4ZI\xc7\xbd\xa0\x17'S\xf6\xf9l\xe6{\xd2\xe21\x9dA\x84g\xbd\x9f\x07\xa6\x11)\x947\xd1/a\xc7\xe9\xf6\x7fS:q\x1b] \x07ft \xa3:S\x96\xb6\x98\x05\xa1\xf0\xbd\x90\xea\x1e\xf4i\xe7z\xfb\xa1\xab\xc3>\x92\xd8\xed\x0ebB\xadqq3\xe1\x9b\x88\xd0\x90\xd7\xcdh\"\x91i\xdc*'4\xb1\xab\xe5\xef\x970\xc0\x83}\x1b\xbc4\xc3\x18)\x05\x0c!\x1b%\xb0\x0d\x83K\xa3\xea\xae\xac\x8a\xc0\x0b\xc1\xd3kj%X\x80\xbf\x9c\x03\xfc\x1a\x82\x97\xcf\xd3\xf5b\nW\x0c\"\x97Z\xc3O6\xc9$\xe0&~\xbf\xe9\xfdD\x9c\xbdEO\x1c\xfc$\xa1\xd1nu\x1dD}\xb0\xf7TCZ\x071\x0f\x91_\xfcMC\xe6\x1b(\x8dkw\xfa\x14\xf9\x11&@\x9e\xf2s\xeay\"e\xeaj\x11M\x98\x9f\xb0[\xf8\xc0\xaeO?\xaf\xfc$\x04\xef\x9aW\xf7\xbc\x80\xd2\x1b({\xa2\xdf:\x1e.\xa2\xbc@ss\x11Yr\xb1\xc0\x1fy\x19\x16\xd6@+R\xb4\x10\x98\xf6\xd8|\x1d[M\n\xa5\x8b0{U\x0cl\xd0q\xf5\xea\x80l\xd3\xb1\x94k\xae\x8b}JXU\x9a\x16cm\xaa\xa9\xd6\xc1B\x8f:n\x1aB\xd9=oG\xe3\xc8\xbf\xc5$\xe9A\x97\x9d\x90F\x1cs\xb0a\xdb\xe5\x92}\x11\xdd\xa5\xeb\xa2\xdb={)\x88\xfc\x03\xdc\xafS8\xfeP\x1c2}\xbf\xbe\xdb\xef\xbb\xef\xd7\x9fv\x16\xe5\xffW\xe0\xab\xff\xbe\xdb\xca\xc6\x99P\xaahvM\xa3\xa8HaM\xfc\xd0X\xb3& \xb4\xb0\xab\xe6\x98\xa4\xd3\xb8\n\x96hm\xaen\xe7\xa3J/\x90\x86\x90\xf7>\xbe\x7fu|q:~s\xfc\xa7\xb3\x8f\x17-\x8a\x82\xfaQ+\x88\x00\x9e\xa0R\xb9\xa7S\xc2\xc6\xde~|\xfd\xe6\xe2\xb4M\x91\\\xefM\x08\xde\x9b\xf5v\xfe\xd3\xd9\xcf-\x9dX\n\xca^>Oo\x13\x9b\x0e\xa9\xa3b]j\xed\xabO\x8ay\x9c\\\xbb\x1c\xe0\x94\x16\x1f\xdb\x95\x87T\xd5\xc8\xdf\xf8\xd8;\x1ev\x1c\x0e\x19\xe1\xd8\xd8\n\x07 \xf5\xb7g\xafN7\x06\x07\xce\x8d\x06GUi\x99N\x99c\xfa\x18\xea\xdc\x1fy\xbcJ\xee]\xaa\xfb\xab\x84\x0f5\x13\xb1C\xd0\xc6\xd9\xabO#\xfd\xad\x1c\xa5|\xd9\xce\xd7\xcbe\x94\xdd\xe1\x94o\xe7\x91\xc8\x0f\xc4\x7f\xc4\xf99_U\x11\x86}\x9de,)~D<\xd5\xdf\xb8\x98-u\xec<\xdd\xfbUO\x1d\x82\x95\x13de`Z\x97\xe5\x92\xda\xe8T\xa5\x9aS\x07\xf6\xe8Z#\x13\xda\xf2\x86\x04\xb4\xba\xb6&\xc9\x80S\xdd\xb50\xd6\xa5 {\xb4\xd6\x8brw'i\xb6\x8c\x16\xf1_\x19\xba{\x05\xd2\xfe\x1d\xfb\xd6wp\xae\xef\xe0\x00\xcb\xeb\xaf\xf9w 9\xcc\x1a\x0eu\xda\x8d\xa5\xdd\xab.\xa0\xd7SX\xe9\xa6\xb1pT\xff\xe9\x8e\x9e\xd3>kj\xef\x1a\xea\xe5\"0\xa6jo\x1bA\x94\xbaK\x06\xb6\xfc\xdb\x81\x1d\xdfBf\xc3c\xd3\xb8Hk\x18\xd2\x89\x94T\xf2\xcf\xdeAG\xd7/N\xa5\x8c\xa1\xd0jt9\xc0\x14\xf3\xe6d~\x12\x8c\xfa\x97!$\xa3\xc1%zc\xfa&EoTm\xab\xbb!\xd6\x13\xcd\xda\xc2\xa90\x14\xd7\x90#\x16\xfec\xd2\xc8Y\xa4\x0e\xac\xf7\xf8]\xfd\xaf\xce\xb0zb\xd2\x0c\xa9\x96x\x16\xf8^\\\xb0,\xc2\xa5\xb0\xc9\x9b\xe1K\xd9\x06o\xc7\x8a\x9b\xa1\xf4\xfd\xac\x87\x0dk\xc9\xc71{\xdaa\x8d\x9f\xddp\x8a\x8dsI\x8d\xb0\"\xf6\xfa\xab\xe5\x1a=\xb9\x1ce\x97f\xfe\xbdX.b\x93\xa4\x06\xaa\x1f#*Q(\xa1\xc8)NM^\xa5\x1a\x108\xb1[oA\x83 \xedx\xd3\xd9r_\xc4AB?\xe6*\x84\x93\x19oE\x913\xf3=\xbdi4\xc0\xd1R!?\xccb\x02\xa6X\x86Y\x97\xda\xa0\nMr\xb0z\xa6i\xc2\x86b\xdc\x9d\x83^\x878\xb0\x0d\xba\x8f\xa86\x98\x1f;\x08\x03\xeb\xe0\x1e\xd5\x05\xcb\x7f\x05\xfe\xe9\x97VE\xe4xk\xea^\xbe\xdb,Z\x1d+\xfdBC\xee\xe8\x7fH\x85\xc5\xde\xaf\xcb:.Paa\x99\x94\xaf\xcb\xa2\x81Y\x94\xcb\xa2\xbd\xfd\x03Z\x97AD_\xfd\xa7.\xe3\x97\xde\x97$:\xadHw\x81X\x95\xec\x99%\x91,yj\x954i),!c!\x9b\xd9\xb3\xba\x9eH\xb5\xc6\xc0x?\x93\xefwI\x84j\x08S\xfaK\xd8\xb9\xd4\xf4,\x99\xa6g\xd1\xac\x0f\xb3\x10fJ\x06?\x7f\x7fz\xd2M\xefQ\xe6G\xd0\xa2\")\x81\x1b\xa3\xe9\xa2Z\x04-Ru\xa5\x08\xe8\xa3V\n\x01\xc7`>~x\xd3m,\xb2\xb3u\xb6\xd0\xfb\"\xc4\xf6\x86\xce\xfep~\xf6n\xa3\xde\xfe\x92\xa7\xa6\xb4u\x96MY\xc6\xa6\x9a\xee%\xe8\xdc\xff\x87\xd3\xf3\xb37\x7f<}\xb5\xc1\x18P\xf8\xc9X\x9e.n\xd8\xd4\xbb|\xf8\xb1\x8c\xcf?\xfep\xf1\xe1tc\xad\x0c\xad\x8fI\x84\x13\xbd]\x98J\x13\xdab\xde\xa2\xa4Qs=__\x15\x193e>]\xad\x14\x04\x0ehd\xdd\xa1\xf0\xfe\xf8\xc3\xf1\xdb\x87\x9a:\x9f\x9d{\xe6Y\xb4|\x17- \xd0\xc4U\x85\xd7\x84\xd6o]\x15\xdb\x85y\x13\xcc1\x9cg/\xce\xff\xe7\x92\x88 7!tB\xea\xbd\xf0T\xe6\xe7\xcf\xfc$\x9d\"\xd1\xda\x8a\x05g\x0dG\xb0\x16\xaa\x88$Z2\xa17\xeby\xb0\xad\xde\xc6\x89|\xc7?\xde\x11\x05\xaa\x1d\x1f\xf3\xf7\x97_\xc4\xf61\xca\xe9\xea\x02\x8e\xc0\xc3\x19\x8d?/\x17\x1e\x0c\xe5/Z\x7f\xa0i\xf7\x18\xe6\xf3F\xeb$7\xd6dA\x08#\x0f\xa1\xc9\n\x86Wv\x93\x10f\x97A\x08yg\xac9}\xfb\xfe\xe2O\x02w\xc6\xaf\xdf\x9d\xbc\xf9x\xfe\xba\x95\xb0l\x84EoY1O\x89\x1a\x0f\x83Kq2Y\xac\xa7\xect\xb9*\xee\xfe\xc8Ak\xf3-\xc2\x1cx+.y\x1ee\xc2v\x1be\x89\xef\xfd\x1ce \x06\x1el\x02\x08L\xd0\xe4\"I\x0b\xb8f \x17^\x19D\x80c\xfb\x1f\xec\xae\x87\x16d6\n\xe4\x18\x1d\xd7\x81#\x0f\xb3\xe8c\x04@\xce\xd9g/\x84\x9c\xaf\xfd\xba}\xed\xffx\xfc\xe6uE3\xce\x7f\xbd\xe5\x8e\xf3\xb3\xe3\xf3=z\xad5\x05YGH\x04\x84\xfa\x9f0\"\xe7\xb4\xe3\xd1\xe7\xe5\xe2Q\xdc+X^\xf8\xb1\xd8\xde\x1c\x0d\xd6K\x96\x8f\xc5\x96\xa4\xbe\xe4{x\xd2\xe3\x9ca\xc4\xa1\xf3s\x8c\xf3\x8bd\xcc\x10ArB\x18\xb1\x86!6\xdfcl4]c\xb7_R\xd3\xefx\xfb1S\xd6\x8f\x1a\xed\x10m\x95\x8e\x15\x94\x01\x95K\xecV\x18\"\x8e\xb0\x9bh\x11\xf3\xc9\xbd\xe7\xad\xa3\x91\xfb\"\x84\xb4\x835\x18\x87FAR\xe4\xa2\xa2\xc8!(\x0b\x85Ks\xfe\xa4\xd1\x93\x1d\x15\xa5}\x7f\x08\x93\xfco\xdc%\xdavx(\x1cH\xdaq`t\xd9\x15\x07\xbaX\x03\x81\xc5F\xd6\xacCj\xdd\x12\xb0\xdf\x18\xf0\xe7\xa7\x17\x9c\x9b{\x7f\xf6\xee\xfc\xc1\xb8\xb8\xcc\x8c\x07\x035\x1e\xce.\xc3k\x9d\xde\xd2A\xc8\xd6\x0ef\xc3_\xa3\x13\x1d\xc2\x07\x8e\xc0\xd0\xea\xdb\xa0\x15\xd6\xd2dP,\x8e\xfcC\xd1V/!\xcf\xc6\xd2\x90_T\x92? \x9e\xaa\x88\x8au\xce\x19\x16U\xb5zS_\x9bP\x96g,_\xa5I\x8eY\x02\xb2\xa07g\xd1\x94\xa19\xd2\xba\xfc\xfb\xcb\x17K?\xc0\x17c\x824\\\xe3}\xb1\x1d\x8e*i\x08\x91\x8b\xdd_;(\xe4B\xc1\xae\xf7\xc3\"\xbd\x12\xda\x97iTDzPm\xbb\x8e?A\x8a\xed\x1aD\x08^\xc1>\x17\x9cr\x88\xd6\xf8\x112\xe9\x88\x95\xff\xf1\xf1\xf4\xbc\xedJ\x7f\x03\xa4\xfc\xaf\xcd\x902\xd6\x90\xb2U\xec\xf8\xaf5\xcb\x0b9\xe9\xd8\x05\xf9.\xa2\x05\x9f\xf9\xdb\x8f\x17\xc7\x17\xa7\xaf\xfe\x91 \xb0\\\x17Q\xc1\xa6\x1f\x1e\x0e\x10\x929<{\x7f\xfa\xe1\xf8\xe2\xf5\xd9\xbb\xf1\xdb\xd3\x8bc~B||0:\xd5$r9\xa4\"\x01\x92O\xec\x8e\x96\xa6F\xad,\x85\x83[\xeaz\x1eYN\xa0\xe5J(V\x0e\xb5\x0e\xae\xcf\xf3 \x080{dY\xbd\xd2\x0el\xfcI\xab\x90\x8d\x9f\x1eUX\xe2\xaa\xb7\xe0\x87ll\x9f\xaci\xd0M\x1b$\x98\x87\x87>\xc5\x9a\xb0\xa3qOL\xd9\x82I&C'\x87Y\x08\xe9e;\xde\xab\xc9<\xe8\xd6\x7f\x98\xb9\x94{\xbb\xe3T8-;?\xf9\xe9\xf4\xed\x83\xadI>\x993\xeat\xfe&*\x96\xf2s,\xd6\x11\xd5\x13\xfdTT,\x13\xca\x87/_\xb0\x9e\xbc\xb6\x1dR\x1fxc \x83s\xf1\xe6\xb2\x9e\x97$(\x7fv\xbe\xbf\xdd\xa3c\x99=\xdb'4\xdd\xf2\xb67_\xb1I\xccr\xaf\x8b\x1d\x00\xb9\x16!\xb2d\x99\xcf\xd0_?/\xb2\xf5\xa4H3\x12zZ*\xa8HK\x0f\x7fx\x08~\x82mD\x01\xdf\xdb\x98\xdbh\x08\xa9n+\xd0\xe9*\xe1\xa6\x16\x87\x15\xe7\xb8\xff\x8cV\xd8\xef\x99 \x91\x86\x85\xfb\x94\xce>\xf1\x07V\x948\xa9\xb1\xa7\x14\xf6\x93\xde*K',78\xdbU\xc9\xfd\x94\x89\xf6k\xe5S,\xafg\xc0\xaf\xd7\x98c\x8d\xb7\x82\x9f<\x99GI\xc2\x0c\x85\xdb\x0d\xd6x\x15\xe7\xab\xa80\xc35/1\x1di\xed\xd55\x11\x80\xee\xae\xed*\xf7F\xa67\xd8\xb6\xc3_\x83\xd4\xea\\\x1bWJ>s\xe6\xbeW\x97Z\xd7V(R\xf5\x08\xba\x82\x15B(|B\x92\xa9\xbd1\xa6s\xd5h\\\xc1\x1fu\xe1%x\xcez[\xd5\x88V|\xe7O1\xc6\xc1\xaa\xb1\xc9*G\xba\x8c\xd6\xcaQ{\xf0\x9c2lJ\xaa\xe8\xaa\x95\x11S\xb2\xbd\xed\xb8g\xbb\x1emo/[o\xda\xd7\x8e$\x1a\xf2\x06\xe8\xc7j\xe0\xa1\x15\xae:\x84\xcc_\x06!,\xbf\xd3^5\xc7\x86\xd7VG\xff\xc8\x93[\x00\x87\x90\xf8\xcf\xf6\x02\x7f\x16\xe0\xb5l#\xec\xd0\x94\xe1\"\x9e|\xf2#\xff\x0e\xe3\x94\x0ct\xfe\x0f\x86p\x83\xc6`\xbd$\xbdmm\x0dk9\x1b\xc2\xd0\xc2\xb12\x19N\xd8-\xcc\x83\x1e'{\xbb\xfct\xe2\x7f\x0czi\"\x8578\x84\xab\x10\xbb\x8b\xfc\xb8\xb7J\xf3B\xeeB$5\x03d>&\xbdh:=\xbdaI\xf1&\xce\x0b\x96\xb0\x0c\\\x01\x0b\xb5\x06P\xdb=\xe9\xc5K\xde\xe39\x86S\xcdU\xd0c\xf7\xd4&\xfa\x18|tt\xe3\x07\xca\xef\xea\xa6\x87\xf6\x88t\xa7\xa1\xab\x10\xb6\xc4\xc8y_^\x9ad,\x9a\xde\xa1\x1d\xc2d\x1e%\xd7\xcc\x838\x81\x85\xef\x89 \xaf\x1e_>\xf7\x88\xf2^\xb4Z\xb1dz2\x8f\x17S_\xfb*\xe8\xd9-\xb7\xe1p\xde\xcb\xd82\xbda\xa21\x91 \xa7\xdc\xa7\x06\xce\xd6\x16\xb5a|\xac\xb8\x88\x97,]\x17\x1aF\x84\xd0\xaf\x1f\xb8\xfa\xd1g}?\x84\x95q\x06pZ=\x84i\xd5\x04\xfe\xf5\xedq2\x1bM\xebh:\xea\x08\xc2\xcd\x9f\x9b!\xb0v\xb2\xd9\x18\xc9\xb5\xb5kBQ\x02\xb2\xeb\xb6\x8e[\xa0\xb7)\xb3\xb3\xfb\x94dvv\xfb\x8f\xef\xc3\xe2`\xb2\x10\xa4\x95\xa9_\x88|\x1b:\x9b#\xed\xedJK\x08[\xf1\x82\x91\xa2{3;\xa5\x98\xf8\x82\xf3\xc2\xa8\x05\xe3b\x92\xb4\xa4\xe5\xec\xc32\xce7\x8cs[\x8fu\xffd\xef[\x02\xda\x17\xba\xe5\xc0!l\xb9\xcc\xb9w\xfb\xbf\xa4Q\x8e>\x1eY\xa7\x8b\xa5d+\xf3\"\x9c%\x1d\xa1\xc5]\xa8\x8f\x89\xe1\xd40j\x8aw2\x9a\x13\xd8\xe3\x81\xccOC\x88\\\xb5\xa112\x85zn\xa4\xb3}1J/\xfd\x88\xd0\x10\x98\x8f\xd0\x0e\xa2\x8a\xc2Y\xb7=\x8a\xb3ztF\x9e\x0c$\xa3\x1e\xdb\xe0K=x\xeb\xb7\xeeM\xd3\xa4\xda7%`\xd5N\xf0\xf3\x00c\xfav\xd0\x80\xab'\xf3=\xce\x15\xcb\xc8\x1b\x89\x88\xd7 \xd2'\\\xb6exq\x918\xc2^\nM\xc0\xb7R_\x84\xc9\x8e\xe5\xff\x98\x0d\x87\x8b\xdb\x9b\xa1Q5\xe9\xc1>}\xca>1\xe5j\xa9R\xd83St\xca\xfc\x15\xe6\xa1,\xc4\xf0\xa7\xfd.g2\xba\x1f\xe4\xd4\xc9\xbc\x15\xa1d\xa9TP\xf5\x8dX\nb\\\x84\xdf\x19\x84(\xb2\xa3\xa7|\x8aQ\xe2\x82@Jb\xa1\x90\xdaa\x07\x06!J\xe9\xecy\x99o\x12\xc5\xbe\xed\xed\x05\xbc\x80\xc9s\xd7\x81\xc2%\xa4\xb5_\x8c\x16\x97\x0e\x82\xcc\x05w\xc2y\x81O\x01{\x995I\xc7\\\xa6_\x8d\xa6\x0e\xe9XO\xaf\xcd\xbb\xe1\xc2C\xee\xdf\x840\x0da\xc5\x99{QA\x98r\xceQ\x80\xb9\xe1\x9c\xfc\x0d\x0c!\xe6c\xc6@\x17\xfc\xcd\xe8\x92\x9f\xceT\xf8!\xebM\xe6\xaf\xb0\x83y \x00\xc6\x87\xf7\x9d\xfb\x13\xb5>\xf7E\xc2\xbd\xfdN\xbc\x1bq\x14{\xe31\x9a\xb9\x8e\xc7b\xaf\xe0\x9e\xe0\x8c\x88\xfc\xc0\x86z{V\x9cZ\x12\x19\xa2\\Z\xa1\x12V1Zb\x1a\xc3\xbf\x01\x95\xd7\xa3\x82\x0b\xf7\x1b\x9a\xb5k\xf4\xc9\xe4\xc5\xd261\xab9\x10\x16C\x95\x9c0\xc4\x0d\xc1\xab\x9b\xe2\xb6\xc5\x8f\xc10\x94\\&E\xb3\x07B\x06p\x9b\xf7\x7f\xf5\x1d\x8b\x9dv\x81\xc7/lN\x1cBQ7\xa1\xc8Q\x17\xcd>\xb3\xc9\xba`\xf2N\x0b_ \xfb\x81?\xe4ir\xbeb\x13\xed\x95\xfc\xe9\nJ\x11\xfb\x89\xbfO\x862\xe7%\x83=\x87\xa3<\x91\xecX\xad\xc5/c\x0b\\\x9bL\xa3\x0cU\xa9\xec\xf3\x15\x9bH\x07\x05R\x1aj\xc4VfX\xf6TL{(L\xd1rv\x91rx\xcbz\x89^\xc55\xa1\x90Z\xa9_c655\xa1\xa9\x1b\x0c+\xc71\x14 #\xcc\xe5\x04\x11\xbc\x80\xe29D\xdb\xdb\x01\xc4\xa3\xe8\xb2\x96&$\"\x0e\x08\x13d1\x82*N\x14\x06\x7f\xa8_\xcf\x9dD\x939\xa3\\\x8c\x94\xd4\x11\x8f\xfa\x0e\x07\xa5\xdc\x0eP\xbf\x0e\xab;\xce\x80\xb2K\xe0\x8f_\x8f\xb9I\xe5\xacq\xf2\xe9F\x7f9\x1a{\x05\xbd\x7f\xc9\xd8\x8c\xa3<\xdeb\xf3\xedh\xcc\xd2W\xa3\n\x81]n\xc2\x80\x87\xd4F\x7fh\\!\xcd\xb8\x94\x0c\xda[\xa4\xd7\xb2k\xe1\xb6\xea\x9b\x1a\xdc\xfah-J\xb5\xc1h\xcb\xb0\x8c\xf7\x1f/\xc3`\xc7\xd2\xae\xd0\x8aRcP\x95\xbf?]\xef\xa2c\xb8\xd1c\xbd\x9d\xa4\xcbU\x9a`VJ\x0b\x04e\x94\xb6\xf3\"\xcd\x1c\xd6\x01Z\xa0b\xbb\x02\xde\xaa\xd5z\xb1\xeb\x08\xab\xa6\x8c%S\x96\xd9\xa5\xb9\x0c\x1c\xfe\x89\xbd\x8dV+6=I\x93\"\x8a\x13\xaa\xea\xa2\xdc\xbeK\xb6L\xe3\xbf\xb2\xc0\x8fDvr\x91>:F\x1e\xdcJ\xa2\xe5T\x0bfiZ\xbcN\xf8\xda8\x9d\xd9\xf4\x99\x0d\x810\x1c\xe7\x0f1\xf8\xa19\xd0\xdc\x1e\xe8\x02\xc7J7)\xa05\x84\xb5\xfdYd\xdd\x88\x80\xc5\xcb\xba=\xd5Z/\x9a6r\xf6\x02\x0d\xd9(\xc2\xd9\xe2\xf4\x05\xbf\xa8\xe3\x17Tk\xeft\xfe\x02d\xe58\xf3\xfe\x94bf\xd0=\xea7\xb2\xf1uTD\xfa'p\x04\xff$0\xb0\x81y\xbb\xe6\xcc\xdbcj\xbe\xd7$[\x17\xcb\x12\xda\xe5\x0cK\xac\xd6\xd6\xaa5\xca\x01\x11?1\x0b\x16\xb2\xc0\xead\"\x0b\xac>f\xb2\xe0\xc0,X\xe1\xd2\x99\x97\xe4S\xac\xbe2\xde\xcee#O\x9eXC\xbd\x11\xe2\xffc\xf3\xfa|)?y\xfa\xf8\x19\xcd\xe6^\xff\xbal._W+\x1d\xb4C\xe5k\x13\x81\x06\xa3l \x8eR\xa7\"Y=\x9a&\xb9\xad*\xd4\xaf\x18\xf2\x8aM\x12\x1a\xefL\xda\xe1L\xcc\x02?\xeb\x952\xb3\x8a\xe8\xbf\xae\x19\x9594\xe7n\x0d)\x90:\x04\xfd\xd1F:\xab\x19\x06%r\x98\x8b\xda\xdbQ\xfb\xdc?\xb1\xbb!xb\x1f{\xf4A\xa0?\x9224r\xec\xd4#\x07>-\xf5\xd7\"\xee\xc7\xa9Hl\xcf\xe9\x91a\xbf\xf67\xf4u\x0fdn\xf3U\x96\xaer\xf9\xf7$M\n\xf6\xb9h\x81#\xb4\xc2\xf2\xebe\x10\x12\xe1\xd8\xcbb\x7f\xd5+\x89\x9dK9\x8d\x98KC-\x95\x9c\xc2\x0d\x1fp\xc2&\x85\x16\xdb\xa4-\x80\xeb\x8dL\x8eo\x9a_\x7fE31\xe6S\xd1'\xd5\xa3PD?\xbe\x96\xd1\ns\xd0_\xa4\xfc\x04@\xdb\xe7v\xa9\xc1h\xb0}\x9d\xf1\xde\x9a\xba\xc7\xd4\x1f\xf7\x9a|\x0d\xfc\xa4\x8c\xf1D\x146d\xf6Ij7\xee\x0d\xd4d#J\xb2\x01\x15\xf9\xadP\x107t\x1f\x96rl@5\xeeC1Z\xa8\xc5M\xef}\x96\xde\xc4\x9c\x97\xef\xd0\x18 j\xa6Y+j\x82\xe0\xb16\xa3Qn\xf2t_:\xdf@\x97Zh\xd2W\xb1\x81`h$\x0ci\xb4\xf4j\x8c(]r\xc6)\xe7\x8c\x1b=\xa7by\xd9JS&\xd2\xba'\x1670\xc9(\xbd\x0c!\xc3\x7f\x19\x99\x88\xa6i6c\xbc\xacp\xb0\x9f\xc44\x85\xcdc\x830\xde,\xb1C\x9d0\xb8x\x1c\xf58(\x82\x9b|\xeb\xa4\xff>\x14C\xa4\xac\xc5\xda8\xb6\xf6\x93\xe2\x8a\x03'\x12Z~\x8c\xb2G\xa3^\x13=\xb5\xa9J\xb1)U\x11\x14e\xa2\x90\xfb\xe7x\xb1\xf8\xc0&,\xbeA\xa1%o 2&\x81id%\xf9\xa3M\xb8\xda\xbd\x9b\xd2\xd4\xafM\xa4\xa7#y\xdc\x944\xaa\xcb\x06\x0e\xd8e\x1d7\x14 \x8a\xa4\xd3\x96\xa6\xee\x8b8A\x18\xb9n\xdc\xf4\xa7@a#\x0e\xc1\xcb\xd2\xb4p\xdd\\\xa8\xa7\x9d\xa5\xdb\xd8\xec\xc1A\xfa\x1a\xc8\xde\xd7P\x97B\xc9\xedn\xc5c\x03\x8db\xa9\xaaY\x08\xde\xf1j\xe55\xcc}\xde\xabl/x\x7f\xbek\xe6q\x88\xb7\xa2\x81\xc5\xcc\xb4\x1aUTJ\xb3$Z\x12z\x8e\x16\x90{\xd3\xf8\xc6\x92\xe5\xd5\x93\x17w\x0b\xd6\x14\x14i\x15M\xa7\xe8B\xee\x0d\xd8\xb2\x01k'\xe9\"\xcd\x86\xe0\xfd\xff\xa2(r\xe4\xbd\xb3W0\x04\xef\xff\xf9\xdf\xff\xb7\xff\x03<\xf7\xf9\xea\xc5\x9e\x00\\\x08\xdeI\xe9\xa8.\xd7\x96/\x0c\xe6\xbf>\x84\x02\x8e\xc0\xe38\x0f%\xb5\xf0`\xc8\x17\xd1\x0b!g\x0c\x8a9+\xbd\xe3=+\xe4w}b\xb7\xad\xca(\xb5&\xdd\x18f\xb9B[>\xab\xd8o!oW\xdcx\x9c\x7f`\xd1\xa4h\x17.\x9a\x0dI\xf5\xa7\xf3\xd1\xa5\x9e\xf2\x08k\xa7:\xd0\xc2\xdf&N\xfe6i<\xad\x92{\xf0\xb7\xd0*\xd5\xd1'RB\x9eHI+\x9f\x0b\xdd\x89\xb9z6%\xea\xea\xa9\xae\x02:\x9cI\xea\xe9 \xe1&n\x1a\xdcI\xc2\xc5\x1bwz\xda\xd2\xbd\xa8Dl\x01\xa3\x06\x0d\xa8Y\xb5\xed\xde\x1dZM\xfdJ\x06\x95\x91\xb7\x83Yy;\x88\x96\xa9\xe2v0\x85\x17\xc0\x9eC\xba\xbd\x1d \xd7Y\xbb\x1dt1\xb0\xa0\xdf.\xe9h\x9b9 \xd7\xc9TP\xb6XOG\xc5\x87\xea\"\x92\xe36\x89G:d;VL=\xc27\xbb\xc0c\xc6\x8d\x1f\x8e\x99Q\xd4\xddPgW0\xb4\x94\xc6\xf6\x19\x9d\x86\x10\x9b@\x8ag\xe0\x97\xc6[U\xe2\xbf4\x90A+\x13v\x0b\x17w+v*\x12x\xbdcl\n\x11\x88\x0fB(R\x981\x0e\xfd\xa8:#z\xf0s\x94\xc3u|\xc3\x12\x880\xd5\x8d\xaf\x99\x04\xa5\xfcPY'BM>\xe5\xe7\x89q\xe1\x9aZA08\xd6 \xa3-3*\x84\\U\xce\x8b\xc5\xbc]\xe4(\xb0\x1b\xfe\xf3N\xb1\x9f>\xfa\x14\xe0\xcf[?\xc2\x1f\xb7\x82[\xf3\x99\x1f\xf4\x16\xe9\xb5\x0c\xeeR\x9d\x86\xb38\x99j\xc7\x1e\xe70$\xb3Q\x0e\xa0\xd3%\xa1\xdb|_Nx\x08\x89\xff\xe4\x89i\xc8W\xe9\x8c\xeb\x97\x03]\xba\xa4\xaf'\xdc\x03\x99G9^\xb3\x0bG\x89w\xe9\x94\xe5C\x18\xddX\x12\xc2:\x04\xe1V\xa4\x90\xd5w\x10T4\xdb\x16\xb1\x93\x1c'\x838\x94\xd7x\n$x\np\xc4Jz\xf2,\x80\xa1\x8a_\x87\xb1\x89\x9d:\xee\x05\xca\x11\x92\xfd\xec)\xa4\xc6hl[\xfd\xc6\x03\xd0\x81\x8e\x8dwR4,\x0b\xa1U\xd1\x1b4\xb8@\xd26[g\xd0\x84\x1b\xec7\xf1\\\xf5Q\xcbKC\x93\xceO\xd1b\x8cz[\xc4K\xa2\xc4SE;\x8bt\x12-<\xbb\x06[F\xf1\xc2~\xbdL\x93bn\xbfN\xd6\xcb+F\x8ck\x15\xe5\xf9m\x9aM\xed\x92\x8c\xef\x07\xfbu\xce\xa2lBtP0b0\x9c\xef'\xde\x923^gD\x03\xb7\x8c}\xaak`\xdb\x94tN.W\\N*v\xb6\xfe\xab\xce\xb5\x92\xac\xae\xce\xe5\x16p\x04[[\xd9Hp\xce\x98b\x8e\xcf4\xcaX$+T\xe3}p\xfc\x12\xa9\x03\xcf'\\\x8c|\xc3f\xc5\xd0\x0c\xe1U\xabq\x91\xae\xac\n\x19\x9be,\x9f\x8b\n\xb8m\xf3\xb6}\x98\xf5\xac~Q:\xf8\x1c\x9aE\x17)\xfaK\xf7\xeejm\xb4\xee\xc3\xec\xdb\xe1\xe4R\x83\xfa\x83\xc7\xa6u\xbatM\xb7B\xc1E]\xd4W\x9c\x82\xb7\x86\xd6f\xbdY\x9c\xe5\x05\xaa\xf4\xddZ\x1b\x94\x9f\x12\x112\x06\xd3ic}\xferO\x8aS\x1cC/\xeeV\xd5\x89s\x93\xc6S_\xbc\xc7\xa5\x83\xc3v\x0f\x15@`k\xeaX\x8bU\xd2V\xc5T\xfbvW\xf9r\xae\xba\x15\x82{\"a]918\xe2\xc4]\x04\xd3AMy}j\x15\xde\x04F0\xa6o\xa0\xdc\xdd(\x07}\x1f\xcbz\xb3t\xb2\xce\xcds\x86v^~\xf0\xdd\x1f%\xf1\x12c\xdb\xbf.d\x90\xfb\x93t\x9d\x104\xf6*\xcd\xa6,{\xbd\x8c\xae\xd9\xd9\xba@\x06\xbf\xa1\xca\xf9\"\x9e\x10$Y\xab\xf1s<\xa5\x8e\x95\xab\xf4\xf3\x8f\x0b\xf6\xd9Y\xf0\xfb,]\xaf\xc8\xd2\xb3l\x1a'\xd1\xc2Qa\x92.\xd6K\xd7\xdcDan\x17\xcc\xc8\xa1\xcc\xc48n\xe9\x92\xf7i\x1e\x17\xf1\x0d1{^z>\xcf\xe2\xe4\x13]\xf6\x8e]G\xee/1\\\xb1]t\x9d\xc5\xd3\x0f\xd4Xd\xc1iB\x1c\xc5\xb2\xec|\x15%\xee\xc2\"\xca\x08X\xf1\xd2\x13\x84WS\x99\xb3WQ\xec\xeeX\x96\xd3}\xcf\xd2\xa4\xf8\x99\xc5\xd7s\xa2l\x11'\xecd\x11-\x89\xb5\xe7E?9>KW\xd1$.\xee\x88\x02\x1a\xdci\xb6\x9aG\x14\xaa\x14\xd1\xd5y\xfcWb\xedn\xe3izK|\xf0\xd7\xd7\xc9\x94\xc2\xae\xbf\xa6\xe9\x92\x98z\xbcX\x9c\xb9\xc6:[\xa4\xe9\xd4Y\xca\xb9\xd9\x86\xc2,\xfd\xc4^E\xf9<\xca\xb2\xa8\xb1B:\x9b\x91\xdb^\xd4x\x1b\x17,[\xc4\xcb\xd8Y\xa3e\x0c%A(\xcb\xbe\xda\x17p#\xefgv\xf5).\xbc\x10\xbce\xce\xff}\x9b\xfe\x95\xffw\xe6i\x9a\x1e\xa9\x89\xf9\xc4\xeer?\xeb\xe2\xee\x9d\xdauh\xa7\xe3Q\xeba\x0e\x9a:\x11\x13WL\xe6Qv\\\xf8\xfd\xa0W\xa4\x1f\xb90+5\x99\xbc,__ \xc3\x0b\x7f@\xd9\xa4\xa3!\xe8%gf\xf4\xd0\x97X\xa6\xa98\x8d{\xca\xd8\xa2\xf1q\xfe1\x89\x8b\x05\xcb\xf3w\x92i7\xdcs\xf3y\x9a\x15\xf3(\x99*\xad\xd5\xe9\xe7U\x94\xe4\"'\xa3=\xc5\xabh\xf2\xe9:K\xd7|\x8f\xd3\x00\xa8j\x1c\x17E4\x99/\x19Ev\xed\xda'\xb4\xaccW\xc4#\xa4KEA\x8d\xd3\xe4\x7fnR\xf9O]*\x7f`+\x16\x15C*\x8d)\xa1:\xb1;i\x87\xdd\xfd\xc7\xdeiD\x92\xc29F\x81\xa5\x8eC\xba^\xe9\\\x98\xc76W*W\xb6\xfb\xd0~H\x8b\x82\x93\xc2\xa6\x01\x8a:\x9d\x86)\xaav\x1a\xac\xa8z\x8f!\x0b\xf1\xa9i\xc0\xbcF\xa7\xe1\xf2\x8a\x9d\x06\xcb+\xdec\xa8\x1f\xc4y\xd84V\xac\xd2i\xb0X\xb3\xd3h\xb1\xe6=\x86\x8bbg\xd3`/\xd2U\xa7\xa1^\xa4\xabN\x03\xbdHW\x1b\x0d\x93\xf3&\xae\x11\xf2\xb2\x96Ny\x95?FY\x1c5\x11\xca&\xfeG\xafC3\"\xeaib\x87\xd4\xc3[\xf91Z\xc6\x8b\xbb\xae\xf3O\xd7\x05o\xd8\x05\x02Y\xdc\xb2D\xb2V\x0b\xacd\xad\x86\xe5\xf9\x8e\xfe\xe5P\x15\xc4\xf8\xf6\x9b\x84\xaa\xc4\x7fj\x06\xe3K\x85a\xd0`\x1f\xe3\x02\xee\x89\xf0\x80O\xfb\x96\x83\xbc4 \xc2rv\x0b\x1f\xd8\xf5\xe9\xe7\x95\xef\xfd\xe7\xc8\x83m\xc8z\xc7\x17\x17\x1f^\xff\xf0\xf1\xe2t\xfc\xee\xf8\xed\xe9\xf8\xfc\xe2\xf8\xc3\xc5\xf8\xe4\xa7\xe3\x0f\xb0\x0d\xde%]\xa9,\xfe\xdd\xbfXi\xcd\"\"\x1e\xfbZ\x06\x80(_\x96w\xa5\xb9\xf3\xaetkkmG`\xc7\x00\x81\x11\xf1\x9e\xcb\xfd2\xfb\x1a\x1a\xb4\xf9\xeb\x11\xbb\xc4\xb0\xaf\xa8\xdd\x85!\xf8\x91\xf6\xa6\x16H\x9bNs\xdc\xc5\x9e\x10\xf3\x84\xcc\xa3\xfc\x874]\xb0(\x11:\x80\xef\xbf\x87\xad\xaa\xe8\xddz\xc9\xb2xR\x16\xc5\xf9\xbb\xe8\x1dg\xfeT\x05%\xce\x99\x15\x0bx\x01\x83\xb2\xd6\xd9\x0d\xcb\x16i4eS\xab\xaf\x01\xa9\xc0\x03\x89<\x13[\x1f\x87V\xcbo\xa3\xec\xd3z\xf5c\x9a\xbd~\xd5\xaaJ\x13\xd3\xcez\xaf_\x8d\xeb\x88\xc0q\xe0\x90cHj\x85\xb4\xae#@\xce\x8a\xe3\xa2\xc8\xe2\xabu\xc1\xac>\x1d\x8c.f\x9b(\xbf\xf2\x89\xee\x89\xe0\xefM3\xfd\x90\xa6m\xd7\x95\xe5T?\x9c\x9d]\xd8\x93\xfd\xb7C\xcf\xfb\xb7\x0d\xe6i\xf4HB\xd7\x9a&\xd1uXK\xdcK\xf4k\xccT\xed\x8c\x0ePV\xea?\xbc\xfc\xe6\x1f\xc5,'\xf6\xd7Q\xad\xc2\x08U\xc8\xb4Q\x15j ]\x82\x0bF\x8b\x14.\x1f\xa5~\xd0\xf3huc\xe9\x07\xd6\x8b\x14tl\xb3\x0e\xf5\x94\xf6\xff\xe6n\xfc\xf2E\xbcl\xd8@\xfdRE\x1e\xab5\x86!\xfe\xad\x90\xbb\x93\xbe\xb2\xc4\x9d8?Y\xe7E\xba\xac\x16\x15\x01X\x91\x0d\xbc\xc1\x1a\xa2\xf8V\xf5 \x01\xba\xc1*\x1b\xbdtXl9\xc4\\RL\x15{\xa7\xc00#\xc6`<\xaf\x05\xd1\x11\x80ndk\x880\x92\xb6\xe0[a\xe1[\xd1\x8co\xa4\x1f!h8\x94\xf60cW\x9c&T\xbeD\xf5\xf0\xa6\xe2@hw]\x06~l\x913GgP\"x\x8a\xee\xbd\xba\x02\\\x98}\x89\xabb\x13pb\xb9\xe8\xeeT\x9b|\x02y\xf11/\xed>\xd0$Q\x81\xe8\x8eo\x8cK:@\xabzZ\x06\x0e\x9a\xbdQZ\xdfq4\x93\xa4?k\xfb\xa3|\x15M\x1c{\xb5\xfa\xea\xc8\xa0~\xef\xce\xfd\xb5\xc8\xa2\x877\xbc\xe8.O\xed\xe8\xb4\xd3\x8eN\xac\xf6}l:P\xa9\x8c\x8c\xf7\xd8\xa5s\xc4\x8e+|\x9b0\x08Hc\xd0}\x82\x14\x14\x06^Lz\xdaV\xd2(\x86\xdcA\x1d\xf7\xa0\x8b\x0886a.\xf3\x00\xf8\x8a& P\x89\x84\x15\xfaXmH\x15%\xa4\x1a\xc7V\xc7\xf4Mh\x145\x8c\xee==\xf0\xc9\xb71%r\x9e|\xa5\x85\x7fgJ\x94\x06\x9c\xad\nU\xf0\xe3\x06r\x84\x1d\xdb\x04\xc2\xbd\xd9\xab\xa3U' \xee\xddj\x1f\xabG\xc0F1\xb2\xd3\x03\x0c\xfb\x8b\x7f{\x0e\x9fc1J{a\x8d\x93\x9d8d\xc5\x97\xf4>\x12\x17\xe2m\xc8R\xfer\xc8f\"9\xe77\xcaf\x03*lq\xe2\xef\x0e\x1c\x11\xc6\xcdp\xeb2\xcf\x97\xd9\xca\xba\x92\xdc\xb6\x06\xa4\x91lnq\xb1x\xd7\x8bV\xccY\x9a\xa25\xcd\xebW\x95\x0dv\xcd\xdci\xc5\x92i\x9c\\\x7fD\xa3\"\n]\xda\xbe\xc1\xe5\xb7\xb1\xc6\xf0.\x10w\xed\xf2\xcaU\x06C \xf1\x04\xc3\x9aW\xf6B\x94\xfdL\xc5\xb1|\xff=(\x03>\x89\x98>\xeb-\xd7\x8b\"^-\xa8\xb4P\x15\x1e8\xc5=\x82X\xde\x94\xd9\xd8\"\xcc\x81B\x1b(\xf5\xd2UaGEu\xde\xba\xa3\xbbA&\xc4d\xdd\xe5 \xa9\xbb\x1cd#AhG\xe9\xe5\xff\xcb\xde\xbbv\xc7\x8d\x1b\x0d\xc2\xdf\xf3+J\xcc\xacCF4\xad\x8b\xc7c\xb7G\xd1\xeb\xb1\xe5\x8d\xb3\xe3\xcbZ\x9e\xe4\xeci+Z\xaa\x1b\xdd\xcd\x11\x9bdH\xb6de\xac\xe7\xb7\xbf\x07\x85\x0bA\x12 \xc0\xb6<\x93d\x1f|\xb0\xd5$\x88K\xa1P\xa8*\xd4\xe5\xac\x93\xc0\xa4\xd5\x92\xd2B\xdcn\xc1L\x89X\xd0\xcd\x0e\xb1\x8b\xa7\xf9\x197\xa4\xd2\x93\x02\xacPaLU2\xc7[\xf1\x0d\x9e\"\xed\xe7Gj\x82xQ:\x1a\x13\x137\"A\xc3\xa6\xde\x02O{r\xda\x01R\x907\xb3@&\xa0l\xdb!t\x87\xba\xa3#\xac\xb1\xe2k\xe2\xc7\xd3\xbd\xee\x17F\xcc\x12\x7f\xe9\x05\xef%\xa9\xff\x9cW5\x06Mq8\x9f\x84<\xc1b\x19\x99\xecA\xf3\x8c\xd9\x01Nz\xd6\x8c\xe2\x8d~\xb3q_xv\xb8\xf4\x97k\xf0\xc8]\xe7\x9b\xac\xfe\x1b\xeb\xcba\"\xe2\xa0U\xf6\xb6\x8e\xdd\xed\x8c\xbf\x07>QZ$\xc8\x9c1*\xc9\x92:\x89Sn\xb9*\x08\x07et2\x984!?\xf1\xbdI\x8f\xc9\x12\x8eU\xecs\x83\xaeP\xc2\x7fX\xcc\x17EXw\x8d%\x8e\xa20@\xf2\x10\xceoy\xe7\xec\"\xcf|~\xeb\x0e\x04\xdf\x85\xba\x9b\xd8\x0eP\xcd\xb9\xe3*.|\x1ec\xcb\x18\xd5\xe0\x96\x85\xaa5\xd9\xf9_\xc7\xd5kN\xbc'\x92\xa0\xd7\x0dA\xefch\xa8\xa6\x8d\xa8\xf9\x8eW\x13r\x1eu\x16\x99\xbe\xdc\xa0\xc9\xcfF\xb7\x8d\xc3\xee^e\xc1\xa3\xf1\xd3\xe7\xcc!\xc8\xb6\xc6\x06/\x0f\x15\x13\x87\xfa,\xf2\xaaf\xa0\xd7\xec-\xd3\xc6bVmZD\xb2n\xb1\xd6\xc8\x0cY\xe7\xa1e\"\xd6\xfe\\Y4{_Je8\xd2-\xb1\xbe\xdf\xd2N8\xc4\xde.\x99\x7f\xb6\x8da \xd9q\xaf\x19A\x08%Ztex\xb6i*42\xd3N\x0f\xbb\x8e\x07\x9amW\xa5]\x0c\xd5\x15?D>\x13\xaf\x17)G\xfe\xfa\xaaLm7\xb0m\xae\xe7u\x19O\xfbx\xbf\x1b\x91\x80g\xcdy\xd45q\xdc\xf0\xe7\xdd\xfb\x8c\x8a;:\xd3\x0e\x809<3\xdewx\x13 \x19\x93N<==\xb4\x96m\xd6\xab\xf7\x11\xcd\xfb<\x1c\x97\x91\x8fxz\xa2}\x91/\x8f\xee\x88\x98\xc7\x00\xf1\xd3\x0e^J\xb9\xccc\xd9\x92Zi\x8e\x86\xf4b\x86\xb3\x88)\xb1h\x03z\xb9S\xeb:\x84A\xfc4\xa1:z!=D\x11|\x8bI%\xbb\x17\xc2\x0cv]\xbc@Ax\xf9\x0eU\x80\x16\x0d\xa3\xbcu\xbc\xd6\xe6nP\x0bg\xab\x85\xf2\x18\x9e\xaf\xc8\xec\x12\x03K\xf1\xc05,\xf55\xe4\x0b\xf8\xbf\xe8\xa3\x05\xbb\xe0\xfd\xdfH/\x9a\x82Q\xb1\x03\x8a!\xb5A\xac\xf5\xf3\xe8<\xbf\xceHI \x87\xef\xed\x1f\xeeyMX\x89\x04\xd5\xc9\x13 \xf2\x10f6\xae\x98\x16MV,\xb6\xec\xc8\xb7\x1c\xc1\x86#\xdc\xab\xac&e\x16\xa72|\x8b\x8f\xc1%]<`\xc4\xac\x1a\x8cQ3p\xdd\xbb'NPf\xf5\xda\n\x95\xa5\xffF\x8dfK9\xc3&\xa4\x8c\xcb'%\x0b%(?\xea\x03\xc9g\x10\x088\x082r\x0d\x15\x9b\xae/~\xb3\x1a~\x1e\x04\x11\xe7\xb2)\xa3\x83\x87}\xd6zr\x04\x19C4\xbcr\xcb\xe7]r\xc16\xae)7\x99\xc7\x9c\x12\xba9\x89\xdb\x0b\xc3\x9d+s\x0c\x1c\xe1#\xb5G\xec\xd8\xf7\xc2\x86\x02\xb4q\\\xde^\x9c#\x00\xd1p\x8fy\x8f\xcbGk\x96\xc1\x97\xb9)w\xf3+\xd1\x92\xfb\x95\xea\xbf\x98t\x05\x86s\x16\xc9\xa1N0g\x8a\x1a\xe4l\x02\xcd\xadC7\x81,{\xf3uN\x92\xef\xbay\xd6\x94P\x17}\xd4\xfd\xf3\xdb\xd3\x0f=\xc7\x00Z\x9e\xbf}\xfd\xee\xed\xe9\xab\x0f'\x13\xd0\x88\x02'\xaf\xdf}\xf8?\x138\xe8\xbfY\x92\xfa\xc3M\xe1\xc4\xb8\xb7/~;'\x01\xdd\xe8\x11v\x83\xea\xea\xa4\xfak\x9c&s\x11\x15\n\xd1\xd6\xb0 \xf8\xbeN\"9\x05\x98@\x12\xd1\x99\x8a\xa4g\xa5\xef\x1d<\xd2'o\xec\x88\xd4\x067\xf1/\xb5=`\"x\x1f, f\xc68Y\x17\xf5\x8dD\xa4\x97\xf1\xac\xce\xcb\x1b'\x88R\x92o\x9bR\x1f;\xfa\x8d\xb1]\xe7\xd4\xa5\x90\xa7\xed\xb0l`\x90Dl\xa2\x94k8\x82<\xbcS\xd8\x9a7\x07\xdf\x05,Ve\x0f\nm\xf5\xf3\x95\xd6K\xdcpL\xd8\x00\xc5\x81\x94S\x04\xa7Tk\x9fR-\x86\xa9\xdc~\xc4v\xd5\xaf%\x83\x8e\xddb\x82ZK\xfbI\xf5\x01\xdd;\xc6M\xa8\x15\xc8&\x19l_\xac\xb7\xce\xd2\x88\xbd\xfc\x9f$#e2\x93cx\x9e\xc6\x95\xd5! \xf8\xd2j\xb0\xbeO\x9bX?\xad\x89:w\x92\xb8l-\xf9\xeb\xeby\x19\x9aQ\xfb\xe1#\xc6\xe1\xef\xf7rj\x08YB\x97\x81S\xec \xff\xa0\x9fiD\xd1\x94{\x91\xa7\x11,\xbc\x89\xe7.\x08H\x9c\xa1\xfc\x8b\x86\x7fW\xef\xceItIn\xe0\x18\xe2\x88T\xb3\xb8 >>\x08P\xc5T\xe7,G\xaa\x7f\xf8H57\x12\x7f\x8d\x89\xd9\xd51=\xa2\xc7\xc6\x9e\x92+\x9e\xa7\xa9\na\x16\xea\x13q\xd2E)BLr\xc2gQ\x1b\x04 %\xd2\x1e\xe5\x00\xd1\xb7\xcb\xbb`\x92\xaaxD\xf9\xaa\x9a\x13\xa2&\x94\x9a\x88\x94\xd10O\xbc\xae\xc26\x89'\x0dTy\x17u\xf4\xcd7|d\x18\xf4Or\xf83\x7f\x81 \xf1\x85p\xa2\x07\x8b\xc6\x0e\xa3\xf7\x84\x13\x94U\xeb\x05\x86\xda\xf0\xbc\xae\xb9\xc5\x97\xfaA\xb2\xd0\xa9h\xcb\xb2 \xa1\xc2tn3v(\xeeuo\x7f\x17\xec\xf6\xf7Q'\xe0%S\x7f\xe9N\xad\xc2\xec4\xfe\x92\xd7Q\x04lq\n\xf5\x177k\x02\xe4\x98\xf2\xa9\xf5?\xa2G\xbb\xb4!\xf6\x98\x07\x12\x06\x89\x0c\xa2\x92\x14i<#\xfe\x83\xe9\xc7\x8f\x7f\xff&\xfa\xe3\xee\xb1\x1fL?\x9e\xfdr\xfb\xf9\xec\xc12\x04\xef\xe3\xc7o\xeeyJ\xb5vW\x9f\xa5oT\x10\xfd\xf1\xd8?>\xfa\xf8\xf1\xa3\x1f|\xc6m\x1b\xed\xf2\x07g\x01\xb6\xf4\xcd~\xf4\xc7c\x86\x18\xdft\x03\xc2\xeb\xbd`\x85~\x8d\x8fV\xa7n\x96\x06|hF\xdc\x0d\x10?\x184X\xd8,\xef\xb7\xbf\xf9]\xff\xaf\x8e\xb2\xae\xe1*\xd8\x11\xb3(\xf3\xb5Qm\xf2:\xc6T\xde\x85\xff:.Z\x06|\xaf\xe3\xc2AQ\xd3\xaa\x85\xdbL\xb6\xd6y\x1e\x18\xdb8%5\xfb\xe8\x94\xd4\xad!\x9c\x92\xdaa\x08\xadZ\xca\x10\xfa\xcf{q\xa4\xaex\x92r*#\xbc\x8e\x8b>b\xae\xf8\xcbS\xd2am\x9c\x12\x9a\xcd\xa3\x8a\xd4\xecm{\x0d\xc3v\x0e\xea\xa1\xe5\x9fGK\xd2\xd7@\xb3D\xb8\xc3\x0d\xcc\xb9i\xa0\xe6\xe3\xd8\x16T\x8ew\xde\xe0\x8f?g4\xb4g\xa1\x85l\xf2\xf0@VQ<\x9fkF1\xecx\x0e<\x07\x83a\n\xd6\x98\x94\xfd)\xac\xf4Sh6\x94\x8e)\xba\xe2\x99\xe6\xbb\xee\x07\xc0\xb3\xf2\xe9\x9e/\xad\x13\x03Eg\x1a\xe9C\x1ai\xda\xbd\x19\xd3.&~~\x95\xd5>\xe1\x1e\x9b\xfe>ej\xf74\x8a\x8a-P[\\\xdf-\xb5T\xef\x8ae\xc8\xac\xc7c\xbd8s\xf4\xed\n\xab\x8bi}6~?\x0c7\xcd#.\xe9\x9av\xdd-*\xafq\x15D\xeb\xb8\xf0o\xb6\xd8.\xc3\xe3\\\xb3l\xf8\xddD\xf9.\xbb\xc9 \x00k\x0d\x00\\\xf7\x9a\n\x80\xb5\x1e\x00\xbf\xeb\xffE\x87E\x05\x85\xe9\x99\x8e/97\xf3%yo\x1eF\xf3\xa8+\x99\xc2y\xb6J\xd2\xf9\xab\x17:\x99\x0c\xc3Oe\xd2\xab\xfa|\x8c\xb5\xd7\xb5E\xc8\xf6>f\xd8G\xc6B\xd13\xcd\xffO\xd9e\x96_g\xc8s\xf8h\xc2\x0f~\\\x03c\x80\x16I\xca\xa2\xf2H\xd6\xe6\xef\xd1\x1f\xa7\x1f?~|p\xf6\x80Y\x1c\xef\x827au\xd3$#\xccM\x9a>\x0c<\x14<\xb19\xa69\x9b\xc3\xc5\x0d6\x9b\xc9\xf7\xaa\xf3\x87nB'}\xb8k\xf4\x05\xde\xef\xc9\xba\xa8o\xb0\xc1q\xf7\x1b\xde\xefk\xf2\xa96}(\xd4\xd8\xfc\x8f \xff#\x9a'U\x91\xc6hY\xca\xdc\x98\xf0i\xc6\x7fJ\x80\x0e\xce\xec\x93\x01\xa3B\xc4\x90Sz\xde\xbeh\xba\xd1Z\x97\x94\xa2b\xa3\x91\xefW\xcaE\xa5\xb7\xd7\x19)_\xbd\xe8a\xab\xd4\x8b\xa2\xe5\x8c\xae\xef<\x08B\xb8\xc6\xfc\x91\x80\xb1\xc8\xcf\xab|S\xce\xda\x1cE{'\x9d\xf6\xb4\xb6yvJXH\x9d\x92dcL\xab\xf4\xd6\x92\x14\xd03\xdf\xdb\x7f\x88\xd1\x923\xb9\xa1\xe8\xee\xeaW\x97\x92z\xc9$\xf5\xb2\xa5\xbe(\x87-\nY\x8e\xb9\xd2\x90Z\x1f\xb8\x0e/\xf7\x13\x93m\xa1\x1ck+:\x7f\xdc\x8cY\xaf\x8c\x8b#\xc2\x83\xf9(\xcch\xeb!6\xbaO\x1b\x8d\xa3\xa4z\x9do2\xba\xc9Xo\xdf\xed\xb7;+\xe2\x92d57\x90R~\x1ea\x8cr\xe5\x01^\x8e\xca\xd6\x0f<&\xec\xc9\xf7.\x176\x1d\xd5h\xf6\x03Y\xe4%y\xdd\xbaAu3\xe7/}c\xb8H\x0e\x87 h2\xaf\x03FSc\x03\x9e@\xa6\xaf\xc0\xec\x9e\xcc\xf6oby&05\xac\xbd\x84\xb9\xd9V\x8f\xc55\xe4\xc1s\xc6Z#\n\xc8\xfd\xc4\x1b\xd1\x83n\x9b\xddC1JA\x194\xfe\x91\x98\xd5\x8bb\xd5\x1b\x96y)\x87N|\xfd`\xea\xf6V\xae\x95a1\x97Va\xf1\xa6b\xf0\xc6r\x95\x92g\x030\xdbf\x8c\xa8\xc7m\x01\xac\x8e\x94\xb5\xdd\xdd\xb5\x8c&[\xdf)\xc8X\xa4\xc7\x16\xa4\xf6\xf5\x90\xaa|\xa2K\xc7x!\x82\xf7\x0f\x8d\xbb\xd8\x94K\xc2\x87N\xe6r\xf0\x95\xc5\xd5\x14\xc3j\x9eF\xe7EI\xaeHV\xbf\xdb\x94\xcb$3*j[\xc9\x94\xf6\x9e\x02\x81\xef\xe1B\xd2fb\xa6\xcd\xb4\x9c\xfb\x17Sr\xe6\xaa8\x03\x9c\xf8@\xd0\xfa\xe1[\xdaf\xb7\x7f\xc9\xe2 \x85\xcaN\x17\xa9\x86\xfa^\x92\xfa9\x8f\xecW\xc7\xb3\xcbg\xf39\xc9\xe6\x9b\xb5\xebHtVO\x836L\x82~\x9c\x0c\x86\xaf.\x99\xe5$Z\n\xe9\xcf\xbe\x1av\x8f\x18\xeb@\x1a\xae\x81s\x11\xd2*\xcav\x9e\x80\xa2\xe4Z\x88\x08\x87\x06\x8aL\xc1N\x9b\xcf\xa3\xf39\xb9\xd8,_\xbd0\xae\x00\x8e\x0d\x99\x9d\x16L\x7f\xb8y\xf5B\xc4\x9c\x17EcB\xdb\xfd\xc4\xb6\x14\x12\xcd\xf9z\x00y\x1a\xb0!|B\x8e\x9f\x08\xce\xeb\x1d\xdf\xbcC\xc8\xd3\x15i{\xb8\"\x8f.7\xfc\x18\xc4T*\x124\x12\x0b\xa6\xf5\xb4t\xaf0\x8f\xae#\xe8\xf0\xb1\x83\x839q\xf3)n\x1at\x1d\x84\x03\x18\xc4\x19\xe9\xd4=g\xb9]\xbbw\x87\x01\x12\x0e\xb6\xefpT\xecO\x89\xf2n\xa3{'\x19$\xb7\xe19@G\x1e\xcfk$Gi\xff\x15Y&UMJ\xc2\xe8U\xdc\xe5@\xaa\xd5\x9b<;\xad\xe3l\x1e\x97\xf3\xbf\xc5e\x96dK$\xbe\x0e\\\xb0\xf1FB\xa4>,I(\xf2\xc2N\xaat\xd8\xecH\xa2N2\x94;\xb5/\xc6\x86\xda?\xc5\xa7\xdb\x1b\x010G\x97\xeeu\xbf\xde\x9e\x969\x1b\xba\xe9{\xa09gH\x14\xcf\xe7'T\x80\xfc\x91{+2'\xa8\xeeSn\x1e\xb6\xb3\xaf\xb5\xadn\x1a]\xe7Wc\xd2\x8a\x08\xff{C_c1\x90\xc5\x9b\x881\xa4'6\xc9'\xd3<\xf0=\x8a\x00\xbb\x0c4w<\x959\xd1w\xb3\xcd,L~\xb5\xfd\xed?\x8b\x8bzS:\x06\xee\x80\xedW~\xef\xae\xc15\xb0\xf2\x9a\x8bKQ\x06`f\x1f]\xa9\xff\xd8\x05\xcc%\xe7\xa0^\x88$\xba\xeaL\x8d\xe6\xdf\xad\x84kwA\x0d\x1e\x1f\xe8\xc2\xf8\xd1\xe7\xfaP\x11\x87\x8f\xba\x99\x00\xb8[\xddw\x07A\xbb\xfd\x8d.M/\xf3aM\xf2\xecy\\\xc4\x17I\x9a\xd4\x89=u\xc2\xd5\x97&\xa0\x80\x8e\x14\xe6\xb7SQ\xdc\xbb\xc7\xb2Ox<\x8d\x00^\x1b}\xfe\xdcKI\xc1\x9e\x95\x1b\"*\xceXL\xff\x93yR\xc7\x17]\xa7`\x93\x03o\x92g\xaf\xb2E^\xb2(\xf4\x16\x0c\x17\x1a\xb6x`Jz4\xc5\x18\xfb\x04\xdd>\x8c)\xbe+1\xa0\xf7\xccc\x1c\x03\x1cj\x97\xc8G\xb7\x91M\xa4\xce\xc2'Zy\x1el'nI\xaa:/\x89l\xc7i\xf9\xd9\x05[lJ\xda\xc3tZ\xca\x9c\x0d\x13\xc6j\xedi\xeb\x14\xed;G\x9c\xe9\xc7\xab\xb52\x84\xdc7\xe5l`\xa1\xe30!\x90\x19z%\xd6\xd8D\x95\n\xbe2\x84*\x08!\xf1\xcb\xe1\xd0E*\xcc\x9d`\xa5\xd7\x1azr\xda\x18l\x1e\x13Q\x90\x007\x96\x1e\x83*\x16\x93^\x81\x17~\xa8\x87,\xc9\xe6\xad\xaa'\xd9\xbc\x8f\x15\xfd\x81I\xebP ^\xd9B\x7f\xb3\xab\xbb\xd6\xb4\xf1m\x12a\xbf\x1f\xee'\x87\xb8`\xf2\xf5\xcc\xb8\x8eD\x08*\x01\xf7\xb4\x12\x18b>)8\x10\xefg\x11=1\x10\x80\xbe7[\xc5e<\xabI\xe9\x85p\x9f\xa7\xf9\xe2\n\xee\x01\xb1\x04A\xcc\x1b\xa2\xcc\xe3`3\xdaV4Y\xfa\xb9\xddR-\xd2]\xbd\xc5\x98\xf7\xd5\xb0*\xe1\xf3\xe7a\x941\x98\xb8\xe3\x04F\xaa\xef+\x03\xf2[n\xd0\xea\xa82\xe3*3\xbb$\x99&\xd6\x15E\xc5V\xaa\x7f\x91\xb6\x9b2w\x86\x1d\xd4\xdd \xb4v\xd8\xd9\x0bp\x04\xaf\xe3z\x15\xad\x93\xccG\xa7\xad\xd6b\xfd\xc6\xfb\x02\x1dt\xf86\xf8@>\xd5\x83[!\x89fy\x9a\xc6EE|d\xe1\x12\x13bg\xf2e\x0fYs\xb8\xcf_\xb3Y\xe9\x12\xcf\x8aH[\x95\x82\x93CQ\x94\xf4<\x12\xcb/\xb8\x15\x8f\xe4\x96\xe2\xa6\x830>\x01\xee\x8d\xd9q\\\x11\x02\xa2XO8n\xfe\x14\xdcy\xd0\x84\xe2\xeb+B\xf5\xea\xa5\x86\xf7\x9e\xd5\xc9\x15Q\xf2\x08\x91\xe8\"\x9fwRH \x81z(\xbc\x8f\xee\xbb\xdf\xb5\xff\xda\n\x9cW6\xef\xdb\xc7z\x86\xb3\x17f:\xd6\xfb\xea\xb2(\x0e\xfb\xdfv\x1b\xafZ.^}\x0f\xaf\x94\xf5\xf2\xb0+\x15\xcf\xf8\xf3n?\xcc8\xfe\xf0\xdb\xee\xf3\x82\xcf\xad\x1bub\xce\xfa\x17\xe1\xb0\x1f>\xea\x0e`\xc5:z\xdcy|\x85\x8f\x0f\x0e\xba\xe3Z\x8364\xdb\x92u\xdf\xcb\xdfu\xc3\xb9\xf6n3\x17\xaa\x03\xdb\xfe\xc3'\xddQ\x9d\xf3\xee\xbb\xd3\xb9n\x1c\xdb\x92~\x00\xe4N\xe5\x13\x8cQ\xa6\x8b\x1f\xdc\xaa\xf6 \x8e\xba\x9e\xd2\xa7p\x04O\xda\x8f\x9e\xd3Z\x9dj\x97\xc68\xde\xcf\x8c&h\xcc4L&\xcf\xa2\xbb\xf6\x14\x1fu\x93qMZ)\xc8\xba\xac\xae\xce:\xec\xad\xb9Sz\xb6\xca\xa0\x80\x8c\x84\xabO\xfck\x96\x8ew\xd8\xfa\xec\x9d\xd8n!\xf2\xa4\xdd\xbe\x90\x96\xb7\xa9\x06%O\x8b\xa8\x9f5\xdbtv\xc6\xe6\xe8=\xec.\xd1\x14\xf2\x03\x8e\xc0C/~\x16\x8ck\xc2L\x155w$1\x1cC\x0c\x13\x88\xbb\xf6x1\x9a\xe2\x05\xa1T\x95\xd5\xc9\x9a\xf4\xaet{\x13\xa6\xfb~\xd5\x89\xf3@\xc1\x94\x85<6\x01w\xa9D\x07\x98n\xf8\xa8DU\xcd\xd1\xfe\xe8Q\x95`\xc8\x81s\x16\xbdC1\xa0\x88\xcek\x0eD\x1e\x0e\x89e\x87\xffQ\x8d\x88\xf0*\xabsLa\xbd\xc1\x85\"\xb8P\xd9\xb0\xb5\xe4\x07eUuKJ\xc9\xe3:B\xe0\xbe'\xb3<\x9b%)\xf9P\xc6Y\x153\xfeuI\xeawy\x9e\x92\xb9\xbf\x83\xcc\xc1,\xdaT\xe49\x9e\xe6|\x01;\xb3\xce\xa3\x82\x94T\x02\xf5\xdf \xb1\x11\xe4|\x10\xe1`\x7f%I \xe5)\xf2\xe1i\xbd6\xe9\x8d\xf0*d/\x84U\xb4\xc94\xeb\x86\xd6D\x9d\xed)\xf8\xec\x9e\xf4\x15<\x85\xbaI\xfb\xf74\x80\x9a\xab\x81\xf0\xb7\xaf\xbc\x1b\x1e\xec+\xb3\xa5\xf0\xb3\xf1\x96\xc2U\xa4\xcbj\xae\xf3Q\x13f%t\xe9>\x7f\x86\x9d,:_\xe5\x15\xbf\xdb\x18cC\xfc\xb3\x91\xf4\xec\xf8;\xdc\xdeU\x02u\x07\xfd\xde$\x1f)\x9f\x9dj\x9e=\x1f\x06\xdc\x1b3\xe0\x1c$U\x0e^=\x9b\xce.\x88\xef\xdd\x1b\x0fN\xdc\x06mX\xf20{\xfd\x9bW\x93e-\xbb\xf6\xc2\x16\x9e\xe7Y\x1d'\x19)_e\x8b\xbcO\x05z\x07\x83\xf8\x8bN\xf1}\xffl{a\xb3\x88\xc7\x08R%^\xbe\xc2\x11\xbc\xefZ\xa95\xc3}\xa1\xf8(%U;\x88\n\x0f\xe7\xf9\xa2\x15\xd9\x06\xe3\x11\x0d\xf4.\xe6N\x07\xa0\x10\xfdfn\xb4A\xde\xd3\x87\x1e1T#\x82\xd2\xb9\xff\xd8\x93\x8c;\xdfL\xe0E\x87\xeb\x10A\x11\xaa\x1fn\x18\x01B(L\xe0\xb2\xc3\xd4a\xa2\xd4\xd7y\x96\xd4\xb9K\xc4\xc7\xae\x84\xd1\x112\xcf\xd9\xbd8\xedl\xc0\xd2U\x7f\xe8B\x03\xb6\x1f\xa3\xd6\xb8\xfc2\xb4\xab\xaf\xaf\"\x92\xfdcC6\x82T\x8b\x00\x19\x92x\x86L\x08\x95\xf5\x9e\xc7iz\x11\xcf.\xd5\x8a\xb9F~\xa2\x87\xd8\xe0\x9c\x196\xbc!\xd7\xd6ik\xe7\xfc3\xcf\x19R\xfa\xde\xe1w^\x10\xc2&\"Y\xb5)\x89\x92\x14\x97\x03\x02\x93J\xf77\xab\x10=1\xde<\xc6\x13\xee\xd6XG\x17T`!sf\x0dQ\xf9\x1f\xd0\xacY\x8cJ\xdf$\x0b\x8c+1\x89o$#\xad\xb8\x9c\xc6g\xf4\x8bp8\n\x07\x83\xd6\xe9\xe6\xa2. \x9e\xf2\x92(8C\xacc\xc6\x82\\`\x11\xadbT\xaerH>\xa6\x90\xfcQ0\x1f\xba\xee\xd4N\x1c\xd6\xf7\x8bF|\x15]\xc5i\x82&#\x1c\xeb\xfc<\xe4|\xde\x8b\xb7\xaf9A\x11\x96\xec\xad0C\x0dr<\xf1B\x93\xad\x8c\x07\x94\xaa\x93\x18\x83\xa3\x15qU%\xd9\x12b`\x95!M. \xfca\x9e\\\xfd!\xc4\x97\x80\xfdr=\x85\xe8\x07\xdf\x07\x90\x97\xf0\xfd<\xb9\x82\x07\x7f\x8a\xd0-DL\xd0\xb1\xc7YJ\xdb\xc7\x0e_\xe6\xf9@w/\xf3\x9cu\xf62\xcfEg\x99\x1a\x03Z\x89U\xc6\xf9f\xec\xf5\xc3*\xa9`\x1d\xdf\xc0\x05\x81Y\xbc\xa9\x98W\xcd&K\xf0\x02!\xc9\xb38Mo \xcd\xe39\x1dP}\x9dC\x92\xcdIA\xe1\x9b\xd50\xcb\x8b\x84Tt\xc8lL\xdc\x07\xc7\xb0\xa5\x98\x9fX\xdc\x19\xf9\x0b\xd3m\x1bR\xf8 h\xe2\x9ci:\xb0\x9a\x9fRq\xbb\xe0n\xa7\x06\x05\x122H\xe7E\x99\xcfHU!o\xc6\xc3\x99\xfaUt>c\x7f\x1a\x15B\xf4\xeb\xa5~\xe2T\x92\x7f\xe3\xeb\xf2d`\x12\x8c\xa1QSa?\x1d\x12{\x0cSY\x80\x7f\xee\xcf\xd8\x15\x80Y\x07L{X\xb0\x1e\xfaB\x05\xe5\xde7\x17i2\x93\xf1\xbb-\x96)sa,k=[\xd4\x9237\xf3\x85\xf9\"\x14@\xab\xa1\x17E\x9eq\xba\xc3\xd2O1\xac@\x82\xa4d\x1e\x84\xb0\xd0\xb6\xa3\xbfk\xfd\xb1'\x07<\xc3\xd8xvS\x0e\xe0\xc0]!\x1f\x99\x19\x00\xb7\xa6\x12\"r\x84;o}\x93\x82\xfd\x06\x8e\xe0\x95\xb1\x89\x0b*\x82a\x13)\xfe\xab C\x00\\9\"\x89w\xf7d\xa5\"a\x16\xc2E\x08I\xe0\x88\x08\xc6C\x8b\x1bK\xe3\x92^\x07!\\\xdb\x8f.\xb7\xfb\xfcf\x95\x07N Ud\x1c\xce\x08\xa2_X\xdb%\xd6\xcf\xcd\x81\xf8p\xcfD\xe6j\xdc\xed:\"\x83\x8e\x0c\xc6T\xb5\xaf\xd0n{_Q\x96\x7f\xe0\x01\x020\xd4D\xa3\x9191\xd0/!V\xed; '\xaf\xcb\xddc/\xa7u\x8f/9\x0b\xfb\\\xcek\xa1;@\xeb\x98\x9e\xb7n\xeb\xa7F\xf7\xa0;\xde\x93\x10b\x1dD(\xac\x14N\x8e\xb9\xa5\x0d\x86c\xdd\xe0^\x1b\n\xee3\x8ffq\xf6\x9el*\x9e\x19\x8a\x8eb\xd3\xc92C\xc5\x0b2\x8bg+\xc2v:\xad\xa1oQP\xf6M[_6\x8f\x9e\xff\xf9\xe4\xf9\xff:\xfd\xe95\xaa\x16\x99\xf6Q\xdf\xc2\xa6\x97\x93c\xc4\xc7\xe2t\xd8D\xf9\xa6&\xe5\x9f?\xbc\xfe\xd1\xd4Ke\x1b_\x08\xdd\xa8\xbc\xa2\x88\x13b \xb5Q\xe1\xe2Y\xaf\x16\xe9\xba\x90\xa9\x97O\xe2\xce)\x94\x9e\x94A\xa8\xfaWf\xcc\xb1r\xb0e\x10\x8c\x80H\xf5\\\x06\x9c\xe1\x91\xbf\xe5j\x1b\x1c\xec\x85P\xc0.\x1c\xec\xa1S\xf4\xc7\x0c\xfc\x8a\x94W\xa4d\xd5g\xe6\xea\xfa\x99\xe9tWtg\x1dx!h\xaee\xfb4\x03\xb5K\x86F\x0e\x19\xaf\xdd\xd3\xef\x19P\x81\x07\x98r\xd5\x90\xe9'\x94GIV\x91\xb2\xfeP\x12\xc2\x1c\x1b}F\x9d\xe81`\xe4\xd3.X\n\x80P\xb3\xd3kE\xab>\xf2:\xefG|\xfa\x85\xf7O\x87\x8f\xbe\x0d\xf4\xcd\x9b\x8f\xa5\xc6\x0fH\x03$TM*\x1a\xe37|\xed\x98\x95@\xd9DS}\x1a\xa01\x8fN\xb9l\xd0A\xb1\x060\x00\xeb\xb1\xf6;\x98\xc8Z,\xe4+\xcf\xeb\xd7\xb3\xf8\xfb\x82\xab\xbb::?'\xd5\xeb|\xbeI\x89F\xcd\xc3C\xb2f~\xf7\xea\x0d\xc3\xe7b\xbc|4\x7f)\xd5f\x8e\xa1\xd4Z\xd8\xcd\x859\\\xdb\xb4\xeeV\x1d\x0d\xaf\x83r>\xff;\xaaVqA:f\xd3t\xe7\xce\xca\xe4\x82L\x94\x8at\xfa\xa8\xc2\xfa\xc7&)\xc9\xbc=\xe2yR\x15\xf4,v\xfe\x80\xf9\x94\xd5C=4+\x10\xdc\xe1\x12\x84-8\x98\x11W\x7f\x0b\xcd\xaf<\xc0\x14\x16I\\\x89\x90\xb2\xccK\xf5\x8e\x04\x1f\xf4\xb8.\xfd\xddt\xbd*\xf3k\x8c\x80t\xc2\xbfj/\xa9\xde\xbc\xdb O\x95\xcb\xe4\xc7\xdd\x1bJ~\x9b\xdc\xb3S\x14\xa9\xae\xba7\xa41\xaf\xdf\xc5\xde\x0d\x7f\xdem\xbf\xe2\xcf\xbb\x17\xc0\xfc\"\xb9\x97^\x80_$\xf7\xd2\x0b,\xf8\xf3\xee\xc5/\xbbH>x\xa2\xbbH\xce\xfc\xc3\xc7\xddy\xb1\xfb\xe3\xfd\xc3n\xfbW\xbc\xfd\xee\xb5\xfa\x9a_\xabw\xdbY\xf2\xe7\xddy\xb1\x1b\xe4\xde=\xf4\x05\x07\x7fw\xba\xe7\xbc\x99\xeep\xae\xf9\xf05W\xc4\xb4zw\x94\x9f\xf0y\xef\xda\xfa\xb4\xafN\x7f\x0eG\xddh\xda\x97p\x04\x0f\xdb\x8f\x9eQN@\x04\x00|V.\xf1\x12\xa9:\xebD\x18|\xab\xd6\x12\xa1\xeb\xba\x95\xde\xa9\x950\xf4n\\\xe7\xa5\xa9\xf6\x07\xb5\xb6\x88<\xd8\xae\xf2\x9a\xdfb\xcb\xdf\xd3gg\x94g\x9b*\x03.\xe3\x9b3O\xf7\xf4\x87\xcdbA\xca\xde\xbb\x17q\x1d\xff5!\xd7\xbd\x17<\xc7\x87\xee\x03\xd2{\xf82\xcd\xe3\xfa\xf0@\xdf=\xbe|\xf4P\xff\xf2UV?6\xbe\xd9\x7fd|e\xea\xecu\\\xf4\x9e1\x17\x14\xf1\xf8C\xe7-\x8b \xd8\xfb\xe8\x94\xd4\xfdg\xc8\xdf\xf5\x1f\xdf\xac/\xf2\xb4\xf7\xf8\xa7\xc487|\xf5<\x8d\xd7\x05\x99\x9bk\x98\xa6O\xdf\xb5\xe6O\xc9\xbc\xf2\x1e\xc9\xa8\xf8\xeam\xe7\xe3\xbf\x91\xf8R\x02ig?\xd4262,\xef\xab\x10~\x0e\xe1M\x08\xefu\xb7w/B\xbc\xbb\xc9\xe0\x1e\x9c\xf6\x99\xeb\x9f\xf8\xab\xe7\xfdW\xff\xe0\xaf.\xdb\xe7\x03ei_\xe1%\xee\x0b*\xb5\xc31\xbc\xa2\xe3\x90#\x98\xd0\xdfA\x10\xaa\xda\xd3\x17R\x84x\xd1ol\xe7Z\xcd[\xdaa\x9e\xe8\x0c^\xe2\xbdBWJ\xa5\x9f\xbe4\x89\xc1thW~M%\xee\x1fe\xd3\x18\xd5\xf7E\xf7\xe02\xc4\xbf\xa5\x1d\xff\x13\x8e`E[\xe9\xbd\xa5\xe5\x078\xa25\x8e\xe0-\x15\xb8\xf1\xafwz\x05\xc6\x85:\xc1\x8a\x8e\xe2G\x83\xaa\x03[\xf9 \xdb{F\xff\xfa\x01\xb5ToLr\x81\x98\xeeO\xac\xee1\xfcr\x0b\x13Xv'\xff\x13\x1c\xc3\x82v\xbd\xf1_0\x1d\xe7\x04f\xf4w\xcc\x7f\xf7\x1a7\x82F\xf4\xba\xf3z\xfa\xcf3\xd9\xc1\x1b\xee/\xfb\x8bA\xefH\xc7\xb8\xa6\x1d\xfe\x93N\xbf\xdf\xdb\xef\xcc\xbf\xde\xa3\x0d\xde{`!\x18\xcb\xa0\x8f\"\x7f\x85#x\x8f\x9aj\x1d\x9a\xfcU\x0e\xf2\xaf\xfd\x97\xef16#bF\x88~\xed\x0d*\xca\x08`\x92}\xe9\xd9t\x00\xde\xdcbXC\xbf\x14\xbb\xb1D&\xe7}\xd7\x12<\x08u\xe8\x7fn\xeb\xd2p\x9f\xf3\x02\xc7\x9d\x87\xa0t\x9c\xbbvLa\xf6g8\x82\x7f\xc01b\xc6\x1c&P\xc0\x04\xff\xbe$7\xd5\xab\x0c\x03\xe2\xf6:\xfd\x1b\x1c\xc1K8\x16{{\x02\x7f\xee\x01\\h5\xfd\xbf\xd1U\xab\x15\xde\xcf4\x93\xbf!5)1\xc6\x13z\xe8\x9e\xa1%\xfd\x0b\x9c\x8f\xdb\xec\xe4\x93\x91\x1c\xe7\xc1\x93.\x87$8N}\"\xaa\xef\x1e\x8f\x9669<\x12\xe6u\x81W~;\x18Z\xbc\x95\xeb`\xe4\xb8\xf7\x1f\x1b\x92\xc2\x1ety2\xce)?\xd6g\x85=x\xd2}\xbei\xc2\xf62\x0f[\x11A\x97\x1d\xa0\x15%#\x83\n\xdfV\x94\x8d\xe9\x19\x8b\xb2\x81\xce[\x14\x04<\xcc\xc6\xb0{{{}a\x02\xb1\x1e\xe8N\x06\xc1\xeab\xeb\x81v\xd8cX\xb9{\xd4\xf6\xab\x8d\xcb\x9c\xb4\xaeuG\xae\xf0\xe3\xc7z\xcc<\xec\xc9H|\xb0\x8f\x0f\xb7\x1dl\xe2+\xa9\xa0\x99\xc9\x18&\xec\xf7\xbe`\xf0]4\xcc\xa5\xde2\xfed\x1b\xa6\xfeF\xa3Q\xa3@\xaeZi\xd7\xa8L\xe1Z\xc6\xfb\xb0\x0f\x13\xc0\xe0\xfd}\xe2e\xbdc\x93\xa8KA\x1a\x0b\xb9\x82\xc5\xfd\xbc\xbf\xcf\xaebs?i:c\x1d\xa1\x14\xc9\x82\xf7o\x82\xa7\xb0\xbb\x1b\xc3\xf7\xb0y\x1a@\xc5\xcd\x11\xa65\xecB|\xa6?\x17Y\xe3\xfawr@\xa9\xec\x816\xb5/{\xa9\x9f\x06\x90\x8a^L=\x08\xf6\x87\x05\x0c\xcd\xfc\nS\x8a\x11\x96S3\x04\x9d\xdeo\xfb\x85\xefn%a\x0f\xbe\x1f\xf8\xa5\x01A\xbf\xc0\xf7\x91S*\xa6\x15i\x12\xab\x87\xe05*\x16\xaf{Y\xce\xb3\xd3*w1\xb7\x81A\x05c@B\x0d\xd5\xcbzZ\xae\xa6\xf5\xa7=H\x99\xf7$\xea\xe2\xd9\x0dV3\x05\xc9\x1f\x90\xfe1^w\x04N\xd1\x884M\xe9/\xafr\x9b\xc0\xbc^,q\xdayTs\\\x11\xb4\xdedQ}\xc94;3\xd8\xdb)\xb0\xa4k\xd9\x80\xc2\xcf\xfc\xfd'\x07\xc1\x17h\xcf\xbe\xf6\x92\x1bM \xf54\x03\xc3\x88\x18\xbd\xa4\x92l\x91k3\x87\xd1\x92\xe6Km\xee0\xc0\x94\xb5e6\x81C\xfdKT\xdcM\xe0a\xef\xa5\xc659\xb3\x1ao\x82\xb2nSrF\xb9\xb6\xfb\x9a\xfb\xd0~\xd3\xccOs\x96g\x8bdYEi\xbeDs\xc0~=F\x02J5\xdb\x00\xa8f\xa7\x89\x8d\x91`\x97Z\x92 \xcb[\xafDR\xc5\x12\xfe\x04\xfb\xa8\x87f'\x00\xa5\xca\x94\xb0\xee?\x05J&\xcb\xa7\x10\xef\xee\x06\x94F\xd2\ngjkZ\xb2\x89\xa0\xfa\xd3\x91\x12\x92\x95+M\x83)9\x8b\xe2\xa2H\x11\xe5\x06\x0d\xda\xc5\xe9\x1a\xd1\xb5D\xfd6&)f\x17\xee\x1e}\x88\xf7\xb3\\/\xdb}\x8fOY\x05\x8aD\xbd\xf7\xf4!{\x8d\x18\xd8{\x8fO=\xad[>^Vc\x0e\xa8\xca\xe4\x17\x8f\xa8\x99\xf4\x91\xc00]\xa7S\xc2\x9a\x07\x8e21]M\xe3\xd7\xb9vpc\x8f\xc4\xc6\x978\xae\xa5u\xfa\xb3\xc0\xc0`\x90\xce}\xc4:\xbe$\x7f\xae\xeb\xc2\xa7\xc4\x97\xbc\xa4\xaf)Y*\xf2\xaa\xc6\x1f\x06\xd5\xc3\xc5&I\xe7\xef\xc9?6\xa4\xaa\xd5\xe6\xd4\xe7\x06\xd2\xc1r{\xab\x1f\xf1G\xfa\xfa%\xa9\xf2\xf4\xaaU\x9f?\x1a\xac\xcfMM4\x9f\xf17\xfa\xaf+R&q\x9a\xfc\x93\xbc'\x95\xfa\xad\xfa\\\xffe^\xbc\x9a\xab_\xacHZ\x90\xb2\x8a\xe8\xf3\xbbEc7\xdc\x91\xc4\xad\xd6\xeb\x0c\xf0\x84\x9e\x96\x8d\xfa\x84\xfe\x10-\xf7\xe9\xd1\x15w\x1d\xa1\xb5\x8cGQ2\x81\xd2p\xd2\x98\xa3\xe3\xf2.'\xba\xa8<\x1aM\x8e\xe0C\xe8h\x91+\xc8\xc5\xa0Q>W~\xa1\x97N\x94r\xcd\xa7|a\x00=\xf0If\x1anF2\x15k\xceNDx\x0d\x83\xe7wGp\xd0\xb9\xdd\x00^\xb9\xe5\x9c\x7f\xf9\xfc\xd9\xc0A\xb0\xaf\xf5\x90e\xfb\x7fS\xc6\x17)\x19\x00e\xb6Y\x13Q\xc7\xc0\x10,I\x8f.\x01h\x82\x10C\x1d\xd9On\x01\xb0\x1e\xbf\xa8\n\xe9\x96#\x9f\x88-\xd3\x1f\x138Dl\x11\xad\x8c\xc0\x9d:\x9a\xfbY\x08^\xcc\xfd\x8a\xb3\xfe\xd4s\x17\xfb\x18\xde\x9c+\xef\xdaO\xbdRG\x05KL\x05\xb5_Gt?\x1f\x1c*\"\xaf?\x1d\x1c\x82J\x072\xff\xe1\x81\xf2e8<\xf8\xce\x97\xdfn\xfbek\xb4\xe3\xbe\xdc\xba\xcf\xc3\xc3\xc7\xe6O5R{\xfb\xd0o\xbd\x92$\xb2\xd4c\xb7@-\x0dr\x13c@\x1fy\xf6\xdb\x93T\xea\x07\x93\x1b\xf1M\xec\xb6.\x1f\n\x7f\x82\x83\x8e\xb5x\xc3\\\x1e\x9c\xc1q\xfb\xe7\xc4\x98\n\x8d\xb29\xbe\xa6\xf5Cc\xeb\x87\xed\xd6\x0f\xcfP\xff\x1eDW\x07o\x0bRbL\x9aWh^\x12\xd7 \xc6/\xb9y\x9d\xcf5\x1e\x9f*\xa8[\xa9\xddTE\x0b&kP,\x10&\xe8\xf87\x13\xf4#\xf0I\x10\xb0(Qy\xd39s\x84U\xd2r}\xac0\xc7\x96\x174\x86a\xab\xf6'\x01L \xe1W[\xfaE\x1e\x9e\x9e\x9e\xbej\xfd\xc5\xcc\x02\xc9@8K\xdd\x12\x8dC\x00\xfb\x12\x99\xc8\xad\xc0A\xbfnG\x84\x80]\xf0\xce1}P+QZ\xb5\xf3\xff\xfd\xfe\x9b\xff\xf1\xf7{\x7f\xf4\x83\xf3\xdd\xa3\xe9/\x1f\xcfn\x9fN\xbe\xff\xd3\xe7\xe8\xe3\x83\xe3\xf0\xe3\xc7?x\xde}\x96<\xed\\g\x99\x0b\x0df\xb0\\\xe8\xcc\xf3\xb0\xb1\xa1\xdbo\xfa\xad\x95~}\xff<\xf8\xe5 \xbc\x0dD\xd3J\xe6\x12\xff<\xf8\xa3@\x80\xe6\x83\xe9\xf9Y\xf0\xc7o\xf8s\xcb\xc6UF\x851X\xe7~M\x87\xd1\x0f\xa4nX\xdc\xd8v\xa0\xf0\x06\xbd\xfb\xfdtL\xa667\xb66+N\x1fw\xf6\x90\x03q\xc6\xc4\xcaDWA\xdc\xc1\xb1\xe0Vb\xcf\xeel\xb3g?\x7f\x86\x1d\x12\x15q\xbd\xaa\xfa\x8du\xaa\xb3jC\xb1-@Qs\xf1\xea\xfd\nR\xb6\xcf!\xc9\xa0\xd4\x9b\xa8*\xeaXZi\x9a\x1b\xa2\xcc\x03\x87\x85\xf7\xee\xd9\xfbg\xafO>\x9c\xbc?e\x83O\xa2:\xff\xa9(laSD\xb9\xe2\x0eg\xb4\xa7ibP\xa6\x8aB;\x8c\x07\xe9el\x83}\x1cX\x87\x04\xd0\x18j\xdbk\x8aR\x15df\x8c\x13\xa6+t\x95XX\xd1\xdc\xfd\xa35\xa9W9\n]-(\xbb7 i\xfed \x9c\xa8Z4:(]\xc1\x0c4\xbe\xc9\x06]-(\x85\xa1W\xb2D\xe8\xcd\xe0Gz\xa7\x97\xfe\x9b\xf6\xaf\xadT\x96\xa0U[b\xe3\x9a\x0bp*g\x95~\xe6\xef?\xee\x06\xff\x00n\xb6\x86o\xbby(\xea(\xa9\xde>;=t\x125\x98.$/H\x16\x17\x89\x91\x89\xe0Y\x15(\xae\x17\x0d\xae\xd3\xc9\x1ez\x1a\x16<\xa9N\xaf\xe3\xe5\x92\x94\x07#\xc6P\xb1O\xb6\x18\xc3\x81n\x0cy\xf1j\xce\x12\xf0\xd7Q2\x7fY\xe6\xebwq\xbdz\x8d\xf8\xcd\xdcI\xeb(%\xcbxv\xf3\xaa\xff6\xa6o\x97\xa4\x96\xc7\xf9\xfb\xf8z\x84\xf8\xc2\xd9[F}\x8f\xd9Ib\xd7\xd7J\xc9/\x12[\xd7\xbc5\x18!f\xbb\xd5\\+\x11\x8b\xcb&\xa1\xdf;x\xe2$\x83'Nb\xa3z\x89\x12\x19i\xc7p\xef%H^\xa2\xf2\x85\x83\x0c\xca4\xf7\x13\x19\xf0\"\xf6\xf9\x1f\x9b\xb3\xa8\xca\xd7\xc4\xb7\x03\x14\xba+\xc2\xee\x16\xb5uu\x91\xd7\x0c\xd9\x10\xd0>>\x9bK\xdc\x80#\xd8\xd0\x87$\x9e\xad\xd4\x87\x15\x8b\x93Q\xaeQ\xcb\xc5w\xc4\x98\x0dQ\x90\x99~mY\x005D/\xb3\xd4\xa1\xb3\xd9\xc1\xb5F\x96\xaf\x8e\xbe\xf9F\x8emn\xba\x8b\x82\xde\x89m\x0c2+\x0e\xda\xccx\xca\"\x9f\xbd\x17\xc2\xa2uZ\x0e\xac\x9d\xc0\x18\xcc\x92\x15\xafIMJ\x0d\xdb!\x8a\x1cgE\xc7\x19\x07\xb0\xe3\xb0\xe7D\x91r\xe0\x948\xf0\x08;\x9did\x0d\xf6{\xb3<\xab\x93lC4\xa9a\xd4r\xc5]qs\x9f9\x7f\x99\x9cqE\xa1\xddj\x83\x02uK9\xad\xa8tB\xffc\x91\xca3\x8a\xc6\xf8\xf4\x08\xa6\x99ev\xc0\x87\x86\x87\xcb\xb4r\xa8M\x076k\x84\xa6\xfd\x00f}{'\x13\xbd\xd4\x15\x12\x9d\x9f\xe7e\xb2L\xb28U\xc4)\xe6\x96\xa1}\x83\x12\x8cBT\xc2\xf6O\x96\xb7\x9f%L\xe7W\xed\xd6\x81\xe8\\\xab\xbbE\x86\x00Td\xc4\xac-\xf4\xba\xcd\x98\x02\xbc\x80#\x98M\xf7\x1c\x00NKa\x84\x91\xe9\x0d\x15P\xda0*:0\xaa\xac=\x9b\x19%\xfb[\xe4\xe5\x9bm\xcc\xce\x18\xeb\xb6\x04\x0e\x9d\xb9%U\x84ZV\x06\xda\xd7-\x92^\\QzQ\x07\xe0\x15e>\xdf\xcc\x08\x1f\xdc\x15\n\x02\xb3<\xab6\xeb\xf6\xb3\x8a\xcc6eR\xdf\x88g\x9f?\x83\xbf\x9a^\x9d\xa1\xb1\xdb\xd5Y\x08s\xb6\xf3V\xba\x0ca\xddB\x01\xb3A\xc6f\xa5\x909v\xa64\xed\xd0\xbf\xb97\xa0\x03\xc8\x80\x83m\xcd\x14\xf5N\xf5\x81{\x18\x98\x14\xe1\xbar\x03G\\Ab\x9f'X3pt\x8b\\\xa0\x8b\x10\x9d\x16(\xd1M\x1b\xa2;\x0f\x9e\xc2\x8eO\xa7\xe8_\xc0\x11\x9cG\x19\xf9T\xfbA\x10\xcd\xf3\x8c\x04O\xf9\xe4]\xc1%\n\xed\x8f\xb2z\x17,\x00\xa8\xdb\xbcD\x91#>\xa1(um'3\xdd\xc2n\x90N\xce\xc6\x8eZ\x94\xde.\xa3\x0c\xcf\xc9\xb6\xad\x01\x87\xc7\xa7\x91h\xa4+\xa7#QKW\x9e\x8fD7]\x19\x87\x82\xba\"\x17\xf92D\xa7\x95\x0eZ^\xd3\xe5\xa3\x98I\xa1\xe6_\xc2\x11<\xebb\xe6'\x8e\x99;\xf6\xab\x981\xe5\x8a\x87\"\xbf\xdc\x06uu\x85bb\x87\xd7v>\xc5mE\xde\x1be\x1e\x81\xb7\x19*p\xc4\\\n\xc4\xbcq\xfe\xd4q\x9d\xac\xb5\xb6\x150n\xfdJ\x0f\x1b\x8d\xf9K\xef\x89<\x89T\x85\x08G\x8e\xceMQ_E\xbb\xe0J\xd8\x87\xdf\xe9T\xb4\x85P\xd1\xf6\x82Z\x03\xf7\x17\xb6k(\xf8\xf0\x98\x07\xa4b\x11\xa1\\\x15rs\x08\x8d\x06\xab\xdf\xe9jL\xa7D\xb9w\xfc\xfb\xc7\xeb\xb3\x07\xcb\x84]\xfe\x0d\x80u\x9c\xe9\xc1\xe3'\x036\x16\xffo\x98\x1e\xdc\xcd\xd5s\x9a\xc7\xf3S\xa3\xc2\xb0\x94\x9c3\xd3R\xd0\xe6\x0d\xe9\xdb\xf5\xc9\xc6\xe4\xdb\xcb \x90(\xbf43\xf2\x9b2\xa5U6e\xca\\\xc5\x8c\x15\xab:\xae7\x15\xe6$\xc1\xbfl5Y\x8aPQ\x9b\xfe2\x7f\xb1\"\xf1\x9c\x94\xd5\x04\x12\x9fD\xfc\x87\x81B\xe8\x1b\x89\xe1\x08r\xf1\xe5\xd4\xe3y\x84\xee\xd3\x9d\xe7\x19\xf4\x10\x1b\xccC\xf9\xf93\x9c\xfb\xb1\xd9\x0f\xca\xdf\xa0kKM>\xb1\xf8\xe5\x17i~\xc1\x14X\x17\xe8'\x1e\x88\xcd\x1c\xd5+\x929(\xb9)\xc9\xceY{hH\x97G\xf3\xb8\x8e\xd9\xdf\x9b\xc0r\x00]\xf5\"\x01;(\xea\x84\xa63.\x8a4\x99\xa1\x02\xe9\xc1\xcf\x15\x8bO\xc1\\w\xfer\xfa\xf6MT\xc4eE|LA\xb4l\x8c>\xe3\x05\xf91\x8f\xe7C\x0c\xf4-\x1d\x85\x0e\x84\xa2\xe4\x98\x01\x01\x8e(\x85\xc8\xa3\xfc\xe2g0j\xf5\x9dX\x83\x9c\x8d\xf5\x84\xdbl\xeb\xb9\x01\xfd\xe9\xc3a\x91\xf7\xa9\x83\x9b\xe1B2\x9cT\xaaO\x19\xf6\x8c\x94a\xafM\x19\xf6\x18e\xd0\xe3\xaa\xce\xbf\x04\x94\xa5\x15\xe3SC\x8e\x10\xa1\xd6e\xf6@:\x1d\xaf\xf9r@ \xba9\xcd\xe8@\x85\xbf \x9a\xfaGI\xc5\x1d\xa1\xa6\xd9Y\x00\xc7\xac\xd2\x04\xa6\xf4\xff\xb3\x10\x7f\n\xb9\x8b\xe2\x93\xf0U\xd1@\x1d\xf1\xb7\x1b,s\xc0ld\xe0\xa4\xd0Gfy\x99\xf0#C\xc4\x89\x13\xcfd\x9c\xd1\xa3\xadl\xaeVm\xfb\x0dS\xe0\x17\x12\x15I\xf1\xa5\x06,\xcdM\xe3,Oy\xd6\x9a\x97\x98\xf0\xcc||\x90(N\xd3\xfc\xfad]\xd47\x18;\xd8|||\xd9\xcc\x8fE\xf2\x1dJ\x1f\xf5WX\xdd\x04@es\xfdb\xc8\xc8\x1f\xfb9\xcb\xdfp\xc1\xa2k\xa8 \xcd\xe5\xd7y\xff\xe3+\x91~'\x9b\xe5s\xf2\xd3\xfbW\x86\x80P\xa0p\x92\xa8\xcdM\xb8j\xe8\xa6\x99]\x1eX\x1dma\xd0\xfc\x16l\x81\x19\x95\xcf;\xf7\xe4:\xee0\x08\xcdW\xbe\xb9m\xa9rfd\xd4\xde\xbf8C\x97G\x18\xfe\x1d\x8e!\x8f\xd6q\xe1'A\xf4s\x9ed\xbe\x17zt\xf3z\xebMZ'\x0c}\xd4J0\xe9\xd4\xd7\x03`V]M\xc0\x0b\x0d\x06\x99\x15\xbe\xfd\x1f\x07{\x86\xf75{\xbf\xf7\xc4\xf0\x9en\xbfj\x02\xdeg\xaf\x0fP\xa4^\x94\xe9\xc0\x14\xd0\x9e\xe7\xb4M\xab\xe1{\xe0\xceU#\xda\x02\xce73U'7Dx\x85\xd1\xd64\x1b\xb8>\xa1\x9bvg\xa7\x8c\xaa\xcb\xa48\xa1\x88\x9ed\xcba\xab\x82\x9c\x87\xeb\xefo\x0bc\x88V\xe0l\x95\x1d\x83EQ9\xf6/\xa2)\xc6^ny\xe2\xbf\x9d6\x82v\xa3Q\x88\"6\xf84\xa1\xc7\xcf\xc6\x8f\x8d\xeeJ\xa2pc\x1fC\x1a\xd2\x10\xf2 \xd4\x05v\x0e)Oo$0\xeb\x86\x9dB\xa90Y\xa0\xe1\x91~\x14l\x85\xcc\x0e\x0eI6Of\x14\xa3u\xf1R\xbb9o`\x00\x8f\xd3\xdf\x8e\x95Aq\xc3*\xf9\x08\xee\xd4\xf3\xd0\x9d\\[=\xc7\xd6\xfe\xb1!\xa5!\x8203\xa9Y\xe4\xe5Z\x7f\xd0\x0c\x86fM\xfb\xfb9 \xc6X\xb3@\x83\x04\xb1\x9fL\xc9\x19;)\x07\x10|`3\x168\x15\x83\x8c\xc3d\x12\xf9\xf29\x7f\xf9\x01_\x9a\xed;P\xe8{\x80\xf4\xbb\x88\xcb\xfa\xe3\x03\n\xa9\xfbT\"y\x90D5\xa9j\xbf\xb0\x9a|\xf08j\xa6\xf8\x9d\x80J\x04.\x01d\xe4\x1a\xe6\xa1\x06\xa8=\xf6\xd4*\xd6\xb06\xa3\xb8(H6gAu\x92i}\x86\xf6\xbdC\x00\xd6om\xa6\xf4\x94\xe3\xac\xfc\xc40\x1d\x1ez\x98\xe1T\x7f\x07j\x91L\x1bq\x058\xf8V\x98)\xb2*\xd2\xa4\xf6\xbdco\x00\x01\xae\xa0g\x0b\xbc\n\xa1\x1b\x8aB-K\xba\x9b\xa6{\x03G ^ O\xf7\x07j\\\xa0=\x86\x19\x85nl\xf8q\x8e\xe9\x96\x04 db\xe6\xcd\x00\xb2t\x90#\xd7 \x87\xeb\xa6\xe3\x8bu>%f%6e\xab.ZCl\xa8\xf4\xf9PFmP\xa9u?\x0b\xa7(&\x8c3\"\xc4\xb5-\x9d\x8d(\xf2fSG\xb0C\x96\x0c\x08\xcfG\x12\xb0l\xbf{O!\x83\xef\x81<\x85lw7\x10bYC\xb8\x87\xac\x8d\x04gRG\x8b$\xadI9~1\xccZ\xfb[\xc1O\xde3\xb9@@\xd3LI\x8f\x84c\x0fv\xf1(\xf7\xfal\x1d \xa3p\x11BE\x99^}{L\xe1u\x04K\xd8\x85\xeb\xb0\xd9\xd4x\x928\xecj\xed\x94\xbe\xb2\xc1q\x08uT\xad\xf2M:\x7f\x91_gi\x1e\xcf\x9f\xa1Z\x8deg%\xe9\xc2p\xdd.\xed\xc3\xfc\xcc?\xe8eK\xa4Eh\xc5\xf7\x86\x94\xe2Z\xa3\xe6\xb9\xd0\xa7\xeb^\xae\x1a\x8b\xe7\xfe\xcb+\xf1Rc\x0f\xad\xba\x1a\x0b\x9b`\xf9\xec\xcf\xec\x8c\x136\xc1l\x07Ri\xf8m\xf9\xbf\xe9\xea K\xce5)\x97\xe4U\x86\xcf\xde\x96\xb4\x02\x1cA\x8ao\xb8\xc3\xb7C\xc0\x1bh\xd6Zz\xdf\xd8\x11\xdf,\x11\xb2]Y\x7fq3\xda\xfa\xb2E\xad\xfb\xad(B\xf2\xeeg\x90a \xbaK\xab\x9b\x03\xaa\x8c\xf5,2\x08\x82\xaa\x01\xbf_\xf2\xc8\xe85\xfe\x95\xf9\xa4\x97\xa8[6\xd1F}Z\xf9\xe0;\x8d\xc5\xfdZ\xa0\xb5\x169\x97\x02\xc5\xbe\xd5\xbd\xbd\x11\xdf\xf6Ru\x02?\xf5\xe4\xae\xd2\x83\xa3\xed(op\xda\xe8\x83a\x02\x9a\xf4\xee\xdd\x1d\xc0\x8f\"\xdbI \x88?=2\xaf\x14S+y\x94\xad\xe3\xf2RRj f\xae\nUL,!\x17Kn\xa0\x97\x01\xf6\x8d2\xc0~[\x06\xd8?\x1b\x08C(Ng9\xcc\xeb2.\x1c\x0f\x14\x16\x82\xfdi\x00\xd5u\xc2T\xc5QQ\x92+\xe4\x8d3\xf2\xc9\xca6\xce\xe2\x8a\xc0\xded\xb0\x0e\x08\xd3,\x93\x10[\xdb\x84X\x91\xc2\x1e5\x02\x14\x96u@O\x1c\x0c6\xbf\x92\x04\xac\xf9\xfb\xf3gL.\xa7\xdd6q\x10\xc2N\x1c\x95,\xa4\x04\xa6)\x9b\x91\xa2\xce\x07w\xb9Z\x18`\xe0\x08\xf6\x1d\x0d\xb1.J\x12_Zk\xda\xef\x87\xe5\xb5$\xef\xff\x11\x9d~\x7f\x1e\xda\xfb\x17\xb5\xe0\x9a=r[3\x12\xd5{\xcc\x1c\x9fdu\x08\xf4\xe7h8=\xf9u\xc1\xc4\x87\x1c;\x00\xe1\x89\x1d\x08,\xe3lmYjlm\xdfa\x1f(\xa7_<$|\xc6&\xe13\x1c\x96/y8+\xce\x81\x19\xbb\x90<\x9a\xb1\x1f~\xb8\x88\x08z\x92,\xec\x1f\x86\xca\x0ex\x14\x82\x8f\xf9\x1eJ\x8c\xed\x82\x071\x06y\xa1O\xcbt\xf8\"\x0b$\xe0\x1c\x90Q\xb2\xab*2\x8aa<\xa1{]=@|\x16\xaf\xd4\xadw\x07,\xa0[A\xed\x1a HU\xe4YE\xbe\x84\x82\x1c|\xf7\xebn\x8d.\x0598d$\xa47\x13\xa3\x0eP\x14\x84\xdc\xc1\xa1\x1b\xe4HT\xef\xb7\x89\xc8\xfexP=\xfauA\xc5\xc7l\xc9\x0f\xc3\xc0\xe0\x82\xbe\x8c\x8c\x18\x9c\xc3Da\xcd}goN\x82\xe5\xd0\x01\x83\x10$.\x1d;n\x04I\x0b\x0e\x9e\xe0b\x1e\xb0\xbb\xb4\xb8\x9e\xad\xfc\xfd\xc3\xc0\x10\xafFW\x9ai\x1c\xda\xa7\x01w\xb8\xba\xcc\xc4\x8b\x8e\xdd\x01.\x87\x0eh\xce\x1a\xf4s\xae\x94c\x19%J\xc5Z#\x08\xf8\x8f\xe7\xf9\x1c\xc3\xc5\xf2\x9fL]\xc5L@ \x97{Q\xde\xc6G\xf5A\xa8\xbb\x99S\x0b\x1b\xa5\x03\xda \x19\x8b\xf2\xcb\xd1\xeb\xf3\xd0\x02'Q\xeev}\xf0\x16\xd1\x0d\x9c\x89\x0e\x9c\x89\x04'}\x1cv\x93\xcfw\x0b\x82\xf1\xe1\x81\x1d\x8c\x92\x8c\xc6\x17\xe5\xa6\xa8}\x8f=\xf0\xc2^ \xefna]X\xf0 +y$\x9b{#\x86R\xd5y1`\"\xa9\x07\xf9-K\x93\x871S\xa7\xc6o\xa7\xf4\xcc?x\xa2\xd7\xf9i\x02\x18\xdc\xea\xd4D|\xa0v\x85t\x03\\\x16\x92\x10\x07'%![(\x8d\xdbnVB\xa125*{\x06%B>\x98\x07\xfe\xcfU\x9e}\xfe\xb4N?\xdf\xc4\xeb\xf43\xa6\x00\xfdx\xf1\x80\xf1\\_|\xb9\xd3\x8d\x10\xb2\xad9\xe1\xc3\xfd\xffxk\xc2\x81\xc1\xb4/1I\xa0\x06Q\xfe\x1eCi\xe2\xd5\x97\xf7\x00\x83\xa0\xe0M\xba]F\x16\xe6\x04\x99`\x02\xddkTS\xe3\xb3\x01\x13)#\xa3\x85\xbaR\xba9\xd8\xbc\x9b\x00\xcfti\xce\x95\xa5\x19GZ5S\x991+g\x9d9\xaa#i]\x0c3\x19\xeeW\xa4\xfc\x0b\x85\xf1\xd2\x8d\xcaiL\x85\x9d\xf1\x19i\x94ua6\xca2\x0db\xee0\x08Q\xb9e&\xeb\xd4\xfaJ\xdf:zAY\xf6\xb8\x88\x9b4x!\xe1\xc5\xf3\xb9\xb0\x8a\xff\xfc\x99\xb2#\xeb\xfc\x8a\xb4\x9f0\x06\xc5\x10\x99\xc6\xb8/;\xc6Z\xa6 ^\x0d\x82\x0f\xa7\xff\xf93\xd0\xb9\"$\xd7\x9b:\x16\x90D\xc9\xfb\xc6\xd1\xd4x=\xd8\xcf\x15o\xdfo\xe0AA\xd7\x07\x80|\x8a\xb7\x16\xbag/\x08)\x9a\xe7n8\xb4t\xc0\xa1\xaf\x8e\xc87Fcl\xb3\x87\x06\x1f\xe1\xa9\xbc\xd6Z\x92\x1aM\xaf\x7f\xb8y\x97'\x19\xa5\x08\xfd\x18\xb8\x00.n\x0f\x82\xbcw\xb2\x86\x86\xda\x88\xd1\xbf3\xff\xbas\xa3\x84\xbe\xecz1t\xeb\x7f\xce_\x1ej\x0d\x06\xae\x87\xec\x10N\xc4\xa7\xda\xdb\xdcO\xe26W\xf7\xf2T|\xaa\xb5~x>d\xc3p)>\xd5:\x0c>\x13o\x1f\xf7\x8d\x18\x9a+\xdc>4\xe3\xf9|2,'\x8b2(3\x81\x90\x9b\xe8>\x1d0\x1c\x1c\x92\x9b@\x91\x9d\xb4\x154\x08\xd6o\x89\x93\x85 $\xbaw\x94\x8a\xde\xe9|9a\xb6Ny\xfb !\xf5\xba\xab1S\xba\xe8\x1a'\x8a8\x899\x19\xca\x86\xa3\xe5\xdc\x06\xdd %\xad\xb7!L\x87\xb6\xa3\x89\x9a\x9b\x0e\x1ae=\xdb\x8a\x0b\xdd\x9a\xdaV\xf1\xaa!\xb6\xe6\x11f\xcc\xeb\xf85\xa9c\x1c\x1d\xa9\x00\x83}\xadI\x8d\xaa\xcd\xb5_3\xd5B\xc7\x8f\\\xd0\xfc\xcf\x9f[xEk^\xe9)\xd7U\xc8\x9b\x15\xe9l\xafl00\x9e\x85\xf5Y\x10\xde\xf1\xc8m\xc0\\v\x0e\xc7a<\xbb\xd0\x83`)A0\x1ee\x14\x06\xe0\xc2\xc8\x00h\x9f\x8a\xdd\xd7{\xa9a\xcf\x8a\xb8$Y\x8d\xa1\xba5<\xda\x10\x83\xd6\xf1\xf0\xac\xed\xf1\xaa\x95\x84\x9aG\x98B\x17\xf1\x95]\x9b0\xbf\x97\x92\xf9\xbd\x18aE\xfbE\x9f\x18\xd4\xc3\xa2s\xb0\xa5O\xf1\xba\xef\xfd\xa3\x01\xc6\"\x8d\xeb\x9ad\x13\xd0\x04}Yl\xd2\xf4\xe6\x8d\x08g\x84s\x1e\xe1;\xbe\xf0g~\xea\x93\xae\xf6\x1a\xf4\xe3\xc8:\xddh<1\x93\xea]\x99\xaf\x93\x8a\x8c\x18D\xc1\xb5\x86s\x9f`,\x14\xa7\xb1p\xcf\xae7\xe4\xda\x117\x86\xe3\xa3\xf0\xa1\xe0}m\xa5U\xb5\x01\xb8\xa8\xdb`\x08\xcf\xc1U\xc4j&\xf7\xaeL\xd6I\x9d8kA\xdcg\xb9\xf9\xcdg\x99T\x7f\xa9\xf2\x8c\xcb`+\xdd\xfb\xe7L\xde\xed\x89i\x16\x84\x92jn!/\x9b\xb4\xdc`\x1a\x18\xefQ\xe3\x1b\x9fT\xaf\xb9&b\x02W\xba\xd7\xcf\xe6s\\\xb0\xa6\xdaZW\xed\x7f\x92\x8c\x94q\x9d\x97#\xe6\xf5\\\x92d\xe5\xfb\x97\xcd\xd7ns\x13\x1fL@\x93P \xa9\x18\xdb=\x81B\xf7\xf2\x84\xe5\xaeu\x1eq+x\n~\xdc\x1fc\xeb \x95\xdf\x15C\x1f\xa9\x0c\xfd\x9dRap#t\xa3\x8e}A\xae\xb4'\xdb~\xba?\x94fm\xf8\xd3'{\x03\x86M\xb6O\xb7\xcebw\xb0\xf7\x9d\xf9\xd3\xff`s*q\xbfw\x07\xfeJz>\x8c\xe5o\xe8;\xae\xe8k\x97\xbcv\xcfF]_\x9d\x850\xb8N\xea\xd5\xf3\x92\xccIV'qZ\xc11xI6K7s\x82&`U\xbc&\xf7Y\x9cx\x8d+\xb6`\x03\xc4z\xdb\x14yd@hB\xe7\xbe\x81Pm\"p\x9d9\xbd&`G]XML\x01\xecX\xf5\x1e\xb0\x8cyTA\x8d\x177,\xfc=\x9b\xd1\xb6&\x9a\xd0g\xc6\xcf\x06\xd2\x1b\xcd\x9a\xe5\x99h\"\x88\x01\x8aw\xaea\xe0@\x95c/\xf2\xb9>x\xa7.\xcb\xc9\xef\xcc\xbf~\x85\xdb\xbdd\xe8\xb2,\x1e\xf0\xe9]\xc7\x97,\xb7\xf2_N\xdf\xbe\x11N\xbd\xb3\x94\xc4\xe5\xf3x\xb6\"6\xbb\xd6**\xd2\xcd2\xc9\xaa\xa8$\x8bJ\xf9\xb0cB|\xeb\x9aQ\x1eT\xc2R\x9b\x17J\x10\x97z\x95\x18\x92\x99\x9c\xa0X\xd8\x19\xe0<\x9f\xe1\xf0X\x14]\x12\x84\xdd\x19,TX\xf8\xd7C\xeae\xddf2\x84;\x01\xd3f\xba0\xe0\x97~JB\x8c\x9a\xb6\x07m\xd0i\n\xeb \x01N\xd5\xb0cI\x81\x931MM\xd3X\x13\xf2>\x08\xf5\xdf\xad\xf5\xdf1\x9cN\x08~\xc7\x8f.$\xec\x85\xb6~\x9c\xa6o\x17A\xd8\x8d\xf9n\x06\xb55k\x9b\xbc\x11\x1a\xa6<\x17qE^\xe4\xb3 \x9clCi\xf8\xf0\x07IfW[\xa1\xe5\xbdE\xa1\x82\xfe\x8b\xa4\x9aQ1$c\xec\xaa\x86\xebmj\xf3\xd5y\x1d\xcf\xca\\\xcb?\x8b\xb2\xce\xe7$\x15\x94\x86W\xefGE\x01\x854\x9e\xbb\xe4E\x86\x8eos\xdc\xac]b\xf4mv\xd5\x1b&\xdb\xb8\x1d\x8b\xf2\xa5\xee\xc7\xa2\xb8\xba!\x8b\"\xcf\x8a\x9e\x07\x87\xc9\x16\xb4[\x98\xeb\xa0[\x8fc\x1c:D\x91#\xb48v\x882\xac\xf2\xe6\x8e\x1e\xe6f\xb4>\x1b\xa283D\x9d\x0f\x9c}8D1(\xd2\xfd\x00&0\xeb%\x13\xb3\x9d\xe6\xa0\x90^\xc2N\x083\x8b9\x94pl1\x1cd\x8bE\x92\xa2{W\xff~\xde\xc4\x8fT(\x8c\xbe\xee\xaa\x1d\xb0\x0b3\x17\x19R\xdc\xb1]\xd2\xa3E\xfa\xcak9\xc66}\xd1\xd7^\xf2\xa6U\xc2\xa5\xaf\x89\xf1\xe3\x9dy\xf9\x0b^\xdb\x91\x97?g\xebr\x99\x14B\x97\x87<\xa7\xbe\xf25\x8b\xe7U\xd7\x1a\x19\x1d\xb8\xc1\x13\x89\xf8Ibd\xfai\xad\x13tc\x0e\xb1E\xbc\xd5\xbe\xa6\xffl\x04\x9d\x0b1fN\xed\x97\x18\x91\xd1\xcck\x8c\xe03\x1cy\x8c\xdb\xc0?\xe1t\xbf\x9b\xfa\xbd\xcfZn8\xf7\xa8\xb5\xb4\xe2\xd2\xfc\xbe\xe6\x15K\xbbY\x19Rnf\xfe\xd6\xba\x83\x83\xbd\xad\x93\xbb?\xd9Z\xfe\xdfZ\xfa\x1f\x18\xabU\xf6W\xdf\xdc\xb9\x10a\xe2\xc8\x0d\xfaOy\xa2\x9b\xd9\x03TAE\xb3\xb8\xa87%9\xad\xe3\xd9\xe5\x872\x9e\x1186\xbd\xe1\x04\x9d\xfe\x1b\xcd\xf2\xac\xaa\xcb\xcd\x0c\xdd\xdf'\xecYEkR^C\xfan\x06\xec\x99\xe5\xaaA\x1fx+k\x05\xde*Y\xe0\xad\x92\x05\xde*ww\x03\xc8\xa6e;\xf0Vi\xe0\xacqpkRU\xf1\x92`\xae\xc6\xbd\xb3\x90\x99\xd0\xd4\xad\x93J\xa7l7\x11\x8c\xac\xb9\x8bW\x9dUC\xf5\x05\xcf\xedC\x8f`\xf5\xa9\x02:\xfai\xd8q\xa8\x1a\xad\xf5\xfb\xed\xf12\xa9^\x96\x84\xa47o\xe25\xb1\xe7w\x90\x86\xe4S\xd2\xf2\xc7\xd1\xae\x1d;\xc4\xa5\x0b\x9d\x91\x80\x97Q\x92\xcd\xc9\xa7\xb7\x0b\xca\xa5\xfc \xee\xefS\xda\x9d\xcb\x87Y\xf30q\x0d=)WZ4BX#}$\xb1\x12e\xf4i\xf2\x1a\xb9K\x17M?\xc7:\xb80 \x1dX\xe5\x85\xa0f5\x0b\xc1\x13\xe7\x05\xfe\x10\xf9\xf8^\xb4\xbf\x98\x89\x90\xb4\xd5\x83j\xb6\"\xeb\xb8\xfb\xb4\xd5\x88\xf2\xbc\xdd\x95\xda\x0c\xef\xe8\x946\xa7\x1f{\x82cg\xfd= \x9f\xe2u\x91\x12\xefl\x0c\xc6v\xc8\xf7\xc3/ \xc3\xadW\xff\x96*X$G\xc6\xedp\x07\n\xda\xfe6B\xf3\x86~03\n\x87\x8cG\xf9\xc3`\xef\x8c\x9c\xed \xc5T\xef3r%\x91>\xb9F\xab\x8f~'\x1d!TP\xdd~E\xb1g\x90r\x97\xa4\xca\xd3+\xe2w\xb5\x82\x96}[G\xf3\xa4\x8a/R\xc6]-\xe2\x19\xc1\x00Q\xdd1\x84\x18]\xfb\x92<+\x92\xeaC\xbc\x94\xd9C\xfd:\xd0G)\x1e\xa2A\xb34!\x99\\\xc1Nt\xb7\xdfL\xcbxh\xd62\xfah\xed\xffm\x80\x91\xe4\x1e\x05\xba\x8a\x82\xa1\xd4\xa7\xf3\xa9\xc4[\xad\xb7A\x8a\xbb\xf9;\x03SY\xfa\xa9!\x8cb\xe6\xef?2\x06Q\\\x0cEP\xd4\x86\xb0[17\xf9'\x86\x00\x8a\x99\xff\xad\x8e#^s\xbe\xb7\x0d\xd8\x1ce\x0d48\x94\x82A\xae\x06CL\xe5\x8f\xe8\"\xc9\xe6~\xb6I\xd3\x90\x7f\x16\xf0X\x1f\x14\x9f1m\xad\xd2\x04\x7f|\xba\xb9\xa8KB\xdf\xce\xd5\xb7\xe4\x13\x99mj\xb4\xd0\x11\x7f\xd3\xc7\x9d\x18\x8fi\xebA\xabB\x13\xf01\xed=\xa4\x15\xdbJd\xe5g\xc82\x85\xb0\xb3\xe1\x87M\x92\xf2f\xae\xa2w\xcf\xde?{}\xf2\xe1\xe4\xfd\xf9\x0f?\xbd\xfa\xf1\xc5\xc9\xfbS\xd3f\x82#Xi_\xd0\x0f.h\x9b\xef\x99\xd4\x84\xed\xaa\x0f\x10r$-X\x9f\xfd\xdd\x90\x17\xaf\xe6\x13Xc\xe2\xfb\xf6\x86\xc0q+-\xc8\xac\xd1\xe2\xf1\xffY\xd8\x17\xfe\x00\x9d\xfc\x98 \xc5\xfe4\x99\x8e\xdao [\x14\xa5\xbd\xcbm\x17o*n\x0d \x84`\x1d(.\xe8y4\x96fe/l\xf4R\xc8\xc3xt\xef{\x83\xbe\xbb\x94\x08WRi\xcf\x02\x88\xd7\x06\xed/\x89Vy\x85\xbe\xba>\xff\xf3\x082\xfc#@ 3I\x80\xbf\x17\xbf\x8e`\xca\xc5\xdcY\x9e\xca\xe8(\xde\x84\x8a\x13^p\x86_^\xc4\x15y\x17\xd7+\xfe\xa9\xfcy\x04T\xba\xb3/\x80\xaa\x03\xc9\xc7\n\xca\x16e\xd3\xde\x80\xd01\xfc\xe9\xfe\x17\x98\xb8l\xadW{\xb2\xf7h\xdbO\x0f\x1fn\xad\x1f{\xb27` \xf4\xef%\x9a\xa9\xbf\xee\x9c\x1bG\x9bdv\x01\x89\xb8I \xd5\xeb\xb8\x18\x08.\x9e\xc3@\x84\xf0d\xc8\x1dX\x1a\x0chu\xbe\x9b![\x83j\xc8W8\x15\xedj\x87$\x82\xa1\x1fj\x9d\x85\x17C\x9e\xc42C\xa86h\xb4\xe0\xe5\x0f\xf6\x86\xdc\x81\x87Y2E\x14\xbd\xf6I@E\xc1\x02\x8d\xb6\xad\xaa\x1a\x11n\xfdP+5\x89x\xeb\xda\x81\x8b8\xda\x87\xda\xb7\"\x8e\xf6Cm\xc3\"\x8e\xf6C\xed2 o\xf0\x87Z\xafm\xe1\x0e\xfeP\xeb\x98\xed\x94\x08A\xb9\x00\x1e<\x80;\xf9\xb5\x98\x98K\x82^.\x12\xf6b\x98\xcdd,\x92g\xf1'\x99\x93\x8b\xcd\xf2GrE(\xe7\x98d\x8b\xdcR_\xde\xfaO-\xael\xac\xe2\x9f\x93\xaa\xce\xcb\x1b\xb3\xd5\x9a(\x8cy\xb07+|s\x1d\xaa\x16\xcc:|.Y:\xdb\x07U\x1dSi\xc46\xd4\xc2\xb5\xbd\xc6\x0c\xc3\xd2\"\xaf\xf8\xa1$d\x82\x9b\xea\xdc,4\xa9\xa5Z\xe5\xd7/\xe8\x02\x9a31\x89\x12\xa7\xa93\x1c\xd8\xd2Q2M\xa5 FY-h\x91&\x17\xafI\xbd\xca\xe7\xd5\xa4\x8b\xab\x9dd0\x14u\x035\x10\xbcu\xdc\x1d\xc6\\\x93RJ\x14\xca\xc1\x04\xfc\x06eI$\xb7w\xbe$5S\x16\xf0\xceE\x05n\xf3\xad\xd6\xe3\x8f\xfa\xd5Wq\xf5~\x93\xc9\xaa\xecg\xbf\xdau\x19\x17\x05\x99\xbfk\xce&\xfaT\x98\xfa\xac\xe3\xc2\x97\xd5X\x1d\xa5\x89@\x84\xe4\x91\xc0\x89\x1a\x13j\xd1\x01\xc7>fD\xd4T\x8c\xe7s\x7fz\x166\x1cp`\xf9\x80\xe3\\\xf3\x11\x7f \xbf\xdb\x14\xf3\xb8&\x1c\xec\xbe\xda\x94\xde\xd2`\xd0\x11\x87\"\xc1\xbcA\x02\x12\xc2\xd4L\xbd.\xc9\xcd\x04<\xa4L\x03h\xc7Y\x03\xbb\xee@\x14\xe4\xef\xe94\x1a\x9a\xc7\x8c\xf5m\x1f\x82z\x9bV\x87Z-1\xbbBc\x17j\x19\xaa\x8c\x8f!\x83\xfb\xb0\x0f\x13\xd8\x0bBd?\xf6\x9fB\x0e\xdfC\xf6\x14\xf2\xdd\xdd\x00\xcai\x8e73\xadK\xb6\xdc\xc1%\x17\xdd\xbfy\x94\x95 J\xf3e\x13\x86Jc\xbd\xa1\x16\xb39\x8b\xc1Fd\xe8\x90a\xcbtE\xca\x8b\xbc\x1a\x8a\x04\xb1\xd5B\xc9v\x99\xf3_{\xd9l\x0d\xc0\xbf\xcf\x82M\xbd)\x06\xce\x84]\xf0\xce(C\x7ff\x8b\xca&\xcaWX\xcb\x86*\x8dYNKx\x05P\x04dAE\\lk\xd4\x827\xb9\x83*\x13Qr\x83\x08\xd0-B\xfa\x99*\xf4\x99\x9ex\x98F\xb8d\xd70h\xf4\xde\xab\x10\xc0\x04t\x04\xda\xc7\xb0m9\xbf\xc9Qk0\xe9G\xc4\xab\xca\xad\xdcu\xb7\\m\x93P[\x14>\xd1\x9d^\x889\xcc\xc5G\xaeHy3\xce\xb1Y-R\x86<\xe2I\x98\x9d\xbe4$\x1bkU\xb1o*\xde\xb7T\xd4tL-K?\x0f\xc1\x988\xb1[0\x16D\x08\xb3\x10\x16!\x14\xe8\x14\xbf\na\x8d\xee\xab7\xf6\xb1\x80n\x85p\x1a\xc2\xf3\x10.Cx\x16\xc2\xdb\x10\xde\xb9A\xbe[,+\x11o;~\xd0\xadL,V&\xdeje\xbae\xdb\x95\xea\x16\xcch\xdd\xa7A\xf9\xa8\x00\x16C%\x96\xf9r\xb6[\xa4nq\x0fk1T\xec!*l\x85\xa5b\xb8$7x\xd3\xbf\x98.T#\x9a;\x07\xde\xc3\xff,\xe0\xf1\x9d\xd7L\x0f\xe3D\xe3\xd9\xe9\xa3>\xf9\x92\xdc \x0d1%.u-,\xe2\xff\x97o\x93f\xa4\x8f\xbfl@\xe0\x96\x11\xc4V\\\x93H\xd9\n\x9a\x89)\x98\x1b\xa2\xe2m1\x9d\x9f\x85\xa8G[H\xab+\xd5l*\x08Q\x8d\xa6>\xc2\x93\x1dC\xa9\xcc\xf1\xcfu\x88\x87B\xa2\x0dD1\x9b\xe6\xd17\xdf\x94dq\xc6\xb2\x95\xee\xec\x85\xa8=\xdb\xd9gf\xbf\"\xed\x91\xa4\x99\xfb\x0fC\xb4\x0d\xee\xb8\xbe\xd0\x9fU\xf3\xd3\x98 \xd3\xb58\xa7C\xb2\x15J\x1c0\xce\xc5'8\x82\x13\xc4\x1d?\x08\xa2y\x9e91r.Eb\xe4\xe1\x7f\x18m\xc0\xe8&p\x04\x9fD\x10\xf9\xe7p\x04\xf9\xf4\xf4,\xc4\xf8\x95\x0b!\xf7\x9c\x06!\x86\xac\xd4\x9c^\xcf\x83\x10\xdeb\x96\x17\xc4\xb2\x10\x06\xd3\xfa\x8e)\xf1\xd8\x84H\xb6\xf2\xaf\x04\xf5\x9dg\xff\x0d&K\x91^W:\xb2\xf6\x16\xe5\xb6\xd9\xf4\xed\x19\xd2\xb4\x80Y\xb8\xa5d\x19\xd7\xe4\xff$$\x9d\xfb\xa5\xcf\xd8\xd6\"\x08\xc1\xab\xf7\xbc\x10\x0e\x1e\xdd\x05\xcdr\xc9\x81e+\x18x\x9aJ{\xa7,d\x0c=\x83\xef\x1c\x1f\x0e-)\xb8\\\xcb\xbf\n>P\xa0\xbd\xc3\xcc\x06\x19\x8b\xd0\x96a$\xbbw\xff\x0d8K\xe9r\x80\x87\xfb\n\x0b\xf8\x1c%\xbcK\xcc\xddZ\xdc\xc5\xfe8tt\x15\x1c*\x82Q\x89\x9b\xf4\x8b_62\xb8CV\xf0\xf0Ny\\\xc7\xcc\xaaC\xe5\xce&v\x07\x94M\xb2\x91\x87\x98\xb3\x153\x0b\xc6\"c\xde\xc3\x80\xf3\x9e{\x8c\xf7\x8c\xadi\x02m\x85\xc9\x1cw \x9b\xcbq?Ty\xe1\x87\xfb!\xec\\P2s\x12\xf1]\xa4\xfc\xddM\xc05\xb68\xa5Hs)\x9426c>\x0ca\xe7\xfc\xce\x89\xe2\xc3;\xd8\x81\xf0/D\x14Y\xde\xbd\xeb/\x9b\x14[\xc1;\xd86\x92D/\x92,\xa9V\xfe\xc3\xc3;\xc1-\x87D\x89\xb6\xd2\x1b\xd9\xde\x9d\x8c\xec\xf1\x97\x8dl\x1b?sS\x913t\xf4?7\x95\xedp\xf26\x84\xd8\x9e\x98\xd0V\xa6Tj\xa7$\x97\x92\xaf\x87\x8f\x1dB\x1a\x9b\xca\x94\xd2\xbc\x10\xa9\xc8\xc3\xef\xdc\xee\x0e\xba\xc5\x10\x15r\xa8\xdc\xb2\xc4\xf1\x9d\x8b\x83\x9b D\x9b+\x0c\xc9\xcb\xcf\x8d\x82\xeb.\xe6\x8a\xeeBj\xe2\x1f\x852f\xac\xa2\xba\xc8uw\xf8\xdd8mc\xf5\x19\x88\x81[`1\xa5\xd5\x18\x84x\x8d\x1e\x02w\xa1\xae(%\x97\xb4\xa5zb;\x9a<\x1e\xdf\xf9N[\xc2\x11\xac\x85\xc6\xa1\xec\x88m7\xfeR\xbcZ\xf28\xa3K)\xc1\xed\xefo\xb3J\xfb[p\xa4\x02\xdd$l\xb7\xd0En\xc1\x97\xb1\xf1n\xc1`\xcaq\x1el\xc1Pn=\xd0-N>\xb9W\xf7\x1fQ\xe8\xb2\xd4\xd3\x9cA|\x14\xf0\xfd\xbd\xc7\xf6w9\x9a?d\x12\xfa\x16\xfc\xa0\x1c\xd6\x81JO\x0e(\xff\xb7\xa0<\xdfJ\xe1\xffV[\xf2\x7f\xce\x99\xc4\xbb\x85%3\x16c\xa2\xfc\xdd\xd6\xf7}\xe5\x97j\x8b~-Z\xc1\xf8\xb3\xf9\xb8An\xad\xa0\x91\xee\x8c\x9c\xcb9\x18\xcb\x7f9\xe73\xef\x96^\xcfc\xf9+\xd6\xf3\xc8\x93\xe8K\xf8'9\xe2\x91\xfc\x92\x1b\x0e\xdc\x86P\x8e\xe7\x87\xa6\x8fB$(t\xf7\x1e\x8ca\x7f\xa6\x07\xc8\xee\xd0Mu\xe0\xc8\xee8\xb07\x16k\x8a[\x9f\x04}\x03\xe2\x9c\x99\x1d\x96\x81\xcd\x8a\x18\xa4=\xe8\x9bxM&\xc0\xa3.|\xfe<\x14~Q\x94V\xe8Y\x95!\x92\x8f\xfd\xdc2\xfa\xd1Q\x8d\xecVN\x94(\x8d\xb6r\xb2\xd1@\xbbw\x9b(\x8aE\xe4\xaam\x16\xdb1\x1eU\xbc?\x9c\xcc\n\xa4\xf7\xd6\x92\xd4\x82\xd3\xac^\xe6%k\xce\xaf\xd5\x8c\xae\xbf\x0d\xd0U\x83\xec;\x84\xbd4\xec\xecX|\xb72\xd8J\xc9K`\xa1\x0c\xb9\xd2\xfb\xcc-u\xa7Z$\xe8q\xe8\x16\xe0~\x05\xe8. \xc7hno?\x02\xb8\xd6\xf9\xa9Q\x13\"\xd9\x11\xa5\x06>\xb1\x1c\x1f\xaa\xd7n\xcb\x1f`Z\xf3\xfc3_\x11\x14\xef7\xd9\xf3|\x93\x0de\xb0\x1a\x0d\x0buB]\x98\xfbDl\xb0\xaf8)\xde\xd7\x87d\xc8 \x7f\xf4\xb4\xf4K\xdc\xcc\xcbm\x951\xe2\xcf\xb4V\xedeX\xf2\xaa\xaf\x08\x0fA\xe7^es\xf2\xe9W\x03\xc9\x87\xa4\xc0\xe4\xcbj\xe7N0\xf2\xb2\xcd\xfa\x82\x94\x1e\xec4\xbe\xd9p\x0c\xf7\xf7\xc1\x94&\x0d\xee\x04Lt\xb7\xde%t$\xbdkX\x83\xbb\x1f=w@\xd8\x96\xae9\xd8\xc8\xb6\xcc\x92\xc7\x916_C\xd4\xb2\xb3\xb6\xbf\x87\xf2\x9c\xa7TG\x1f\x8c\xa1x\x91_\x08+v\x80}E(\x0d\x03\xa5a\xf1\xda\xe9;\xe8f\xe1y&F\x1e\xach\x8d\xd7\x0b\xec\x1f@\xc6\xbd\xcd\x19Dm\x8bE\x0bf\xd8\x19NY\xa1\x16\xb4\x9b\xd0\x1aqKV\x025\x82\x19sK\xf0\xbb+\x00\xde\xff\xcck\x88!\xcb\xb3\xfb,\x0f0\xf3\x1b\xf3Bp\x19-\xf0!d\x91\xf4\xf1b\xb1\x83\x1b?.1\xf5\xb0\xc5Ys\x1e\xcb'2=\x91\xf0\xd5\xec\xb19\xcd\xf7l\"\xad\xf7\x1fV$s\x82+h\x8cM\xd5\\\x1a\x1a\x88U\xd2\xcd\xca'\\\xed&\x86\xbb]\x7f\xe2\x14\xd0\xf4\xc5\x96E\xb2\xc3\xba\xcc\x15\xdd\xe2\x96\x93D-\xfd\x8c\xc7]\xfc\xb463,\xb0~\x0d\x8e\xbc\x03\x991D\xc3\x06\x97v\xe6\xebvL\x16\xb1\xd2hO\xd1qJP^!\x19\xd5\x19\xe3\x88Z\\\xf5\xae\xc8\xb4\xbf\xdc6xdA$q\xba+\xfesM\xe2)\xe6BW\xc75\xc1\xf0\xbev\x14p\x0c\x1ebY\xe1\xe1\x11\xb3\xc0\x14\xd8\xaet\x81mvp3dJ\xa7\xbf\x02\xb2\xb0\\\xc6\xdb\npV\x84iq[]:\xd5\xc4\x07\xb4\x81\xe8{\xd8\x13!n8U\xfeP&d\x0eu\xce\xf3;C\xdc\xf6\n\x86z\x15\xd7\x90T\xd9\x1fj\xa8W\xa4$;\x9e\x0c\xb7\xd9\x1dFU\xa4 \x95\x18C\xd8\xff\n\x00\xee\x11\xdf\xaf\x05^'>\xb5\xd9c\xfc\xafN\x14\x19''!\x11eN\xb7M]\xb6\x154S\xcd\xac\x95m\xfb\x070\xbe\x81\x06\x8d\xd9\xfe\xe9x\xbb\xda\xdc(\x03~\x890\x0e \xee\xfdkB\xa5\xaa\xe5k\x1c\x07\xaa\xd2h\x0c\xee90\x90\x8d\x97\x18\xa0\xe6p/\xd4\x0bBH\xe1\x04\x15h\xa8\x1c\x93'\x05\x95k\x9eW\xb8\x1f-\x01\xd8\xbf\x00\x1c\xcf7eI\xb2\xad\xa0\xe2\x08\x11!w\xe8\xb4u\xfc\x15\x1f\x04\x7f\xfa\x95tG\xfd\xfeG\xccu\x14\xf5\x89\xf4\x92\xbb\x95\xb6\x9b\x00\xe6\xd7\xb0\xfbU\xe8q\x17\xf4#\x00b\x83\x87:\x97\x99\xda\xc7W\x99\x05')o\x17\x1fn\x8aQ:\x80\x11\x1b[\xd8<|\xa5\x8d\xf8cr1b\xe0\x8e\x83F\xf07a+\xee~\xe0\xe7K\xf25t\x8f\x0d\xcb\x8a\xc9\xf1\xdb\xdc\xeaW\x80\xbf\x12\x14\xe3+\xcc\x86m\x82&\xfc \x9d\xd4\x90\xb8\xb4\xf54\xaa\xadf\xe1\xbe\x07z\x13\xa9\xe8D\xbe\xce\xd9\xc4\x83\x8f\x8c\x99\xc8\x98Y\xf44\xe8\xc6\xc3\x08\xfe\x04>;\xd1\xbf\xc6,gi\x9e\x8d\xa2X\x8e\x93\xfc\xcb\xe9\xdb7<@\x1feMsE6\xfd\x1a\xe7\xab\x88\x8d5b&\xb6\x89H\x97lb\x9f4-\x84 \xce-\x81W\x93\xcc\x97k.\xda\xac( a\xfbH\x14\xd09\xfe\xedW\xc6\x99sM\x19\xc0\xba\xb9\xcf\xb5\x19\xc9\xa0R\xcf\xc9\x11_D\x8ck:h\xf1\xec\x0e\xc2\x06\xed+\x97\xda\xa8\xdc1\xb8v\xb7\x88}i\x8a\xb0\xa6+}\xe9\xe4\xeb\xf6f\x87\x85\x88\x96\xed6\n5\xb6+\x9ekN_\x89\x00b\xf8\x1d\xfba\xfd\xce=\xca\x04\x1b\x8d\xaa\x8a\xf5\x13\x11\x0eI\xa0I\xa3\x9a\x0dB\xf5\x9e\x99\x07\xb3M\xbed\x131]0\xbbV@\x9a\x8c\x11C\xd5\xdfx\xd3\x16\xb6\x1f\xb2\x0c\x1e~\xef\x19Rl\xca8k\xea\xff \xf6\xf7\xb4\xd7\xe5\xd6\x98\xbc\xa2\xb0\xf5\xcb\\\x17O,\x9cT\x99r?P\x99\xf4\xc3\xf7\xfeF\xfepE\xa0$\xf1lE\xe6\x10\xc3*.\xe7\x90&\xeb\xa4\x86|A\xc7\xcbMT\xa0\xdcd\x95g\xa3V\x0eD\xa2DW\xb9>\x87.5\x93zK\x03\x97}&\x92\x08i\x9b\x19oy\x00\xe3\xac\x0f\xc0\x01\x00\x00\xd0_\xfe8M\xfd\xcd\x97\x8e\x0fi\xa0\x88\x97\x13\x82\x0cmfm\xe56p\xcdN\xd0-\xdb\x91\xb4/\xd8\xa9\xbc\xc3Q\x03\xcd:Xv\x04\xa5}\x89\xc4\xb9\x9aE\x1a]\x85o \xab'J\x8e\x0dtu-p\x1f\x1cla\xc7]\xa6\x95\xaa\xd9\x97\x0bPD\x11\x87\xc7P&_]\x89\x99\xf1\xfe\xa8o6\x8e\xd1\xa3\xd4\xe2\x0e\x06Qdh\xb2\x8a\x99 w\\\x08J\xbf\x0e\xd9\xaa\xfe\x98\\\xf8A\x10<\x85\x1d\x9fB\xc0\xaf0\xa9A\xcb\x8c\xff)\x87M\x00\xc4\xaf\xf8\xe5\x87\xf3`\xc6\xdft\x89\x12s\xcbi\n0;\xc5\x11\xe5\x16\x16I\x16\xa7\xe9X\x80\x8d\x071-; %\xd7\x85bL]Hc\xeaQ\x8dm;l\x10\xeer\x01\xb70\xde\x8c\xfa\xdc\xcd\x86\x15\x9ck\xde\xb2;p\xd2G0\xeb\xe7\x12Q\xac\xe2\xb0(\xed+Q\x8ck\xeeO-\x91A\x9d\x8cQEa'\xfe\x04\xfaY\xfeu\xe56p\xb1\xa4\x1d\xb9\xceRTj\x99K\x95cf\xd12!2%\xec\xee\x16\x97\xf8i\xd6\x1a\xd2,\xc0\xf1`\xbc\x1dxo\x90\x8d1&}\xef\xd5\xad\xeel:1J\x07%YT\x13X\x0b4\xd1\xd3sL\xa1<\x81\xe5p\xad&\x05\xd7\x04n,Ue\x04\x9c \\\x88\xaa\xfd\xa9\xb4O 5\x0c\xf9u;By\x93ay\\<\xf8\xc3\x87\x03\xf1\xe0\x87?=x\xfc\xdd\xb6\x9f>\xde:\xa5\xe4\xc1\xf6\x91\xef\xf7\xf7\xb6\xfdt\xff\xbb\xed\x13\x04\xec\x7fIF\xca\xd6+\xa9\x94\xf9\x8d\xe2\xed\xeb\x07\x93\x1b\x95\x98,2LT\x93\x8aY5\xe9\x07\x80\xb5jq\x80Q\x99\xecm\xebV\x9d\xe5Z\x8a\xa1$i\\'W\x04~z\xffc\x08\xd7I\xbd\xca75\xac\xe2\xab$[B\x0c\"\x13E\x84Y\xbe'\xf0\x07\x19\xf4\xf4\x0f\xf2\x1d\x7fZ\xe3S].Bh\xa0\xf8\xa9'\x97\xd6Z\xf5w\x9f2\x89ep\x82^b\x84\x9e \x9f\x0c \xcf\xf3M:\x87,\xaf%DJ\xb2 %\xc9f\x04.\xc8,\xa6X\x93/&\x80\xb3\x16\xb92\x11\xc3:c6\x0d$\x1e\xc4)\x1f!\xe9\x05h\xa3P\xfb\xde\xef=\xb7V7\xc6\xe9 \x9b\xbfwS\xa2\x89o\x8b\xda\x084\xe09\xd5\x98\x9eeA0\xc0\xb1 \xab\x80\x14\x99\x90\xe1U\xa6\x0c\xc2E\xc3 ,{\x8b>\xec\xbfr~\xce\x15\xabz\x1eA\x97\x91\xc6\xca\x10\xf3\x91\xa9C\xe1v\x81\xee\xb8W\xf9\xa4+\xce\xda\xfaKM\xf8\xed\xb6\xd0\x95\xbe\x03!B\xeaWY\x88\xcep\x0c\xbae\xae\x038\x86\x1a&\xd0_\x96:\x80 \xf8\xb4U8\x82W,G\xf8_N\xdf\xbe\xe9\xcf\xdb\xc8O\xf2\xcey\x1b\xb5>U`\x88\xef\xdd@\x90Zq}\xa6\xbd\x85f\x9a7.\x17\x7f\x0f\xfbR5V\xf7\xeb\n\xdc>\xed\xde\xd1\xe91\x1d\xcd\x18\x9b\xac\xe4e\x87\xca\xf6\x89J\x91'YMJNG\xe8\x9e\x87yN*\xacC>%U\x0dI\x06\xf3|\x86\xa1\xa9\xb5\xf9Th\x91\xadh\xce\x14\xcd(\xf9t\xbb\xc9\x16\xf5P\x9e\xe9\x11\xad\x95\xfe\xb21\xf9 \xea\x8c?\xdc\x14\x84\xeb\xfbN>\x15dV\xa3\xaa\x8f}\x14\xc2\x12\xadi\xe9\xbcU\x90\xd1\xc3\xd3\xdbd,\xaf\xcc\xdc\x03\x96|\xe0\xaau\xa3c\x9e\x92\xf7\x80Y(\x92\xe9\xde\x99\xbc!!Q\xb5\xb9\xa8\xea\x12s\xc1\x80\xe7\xc9~\xa6g0\xc1\x0cXHb\x1fx\x01\xd3\x86\xb9a\xdfb\x90~\xeb@\xc3\xd9\x82\x13\x89J\x9b\x8cT\xb3\xb8 >\x91\xc9\x9f\x1e\xfc\xd7\xfe\x83e\x88\xb9\x9d\x94g{\xf8\xec\xbf\xbazP\xd3\xd0\x8a\xc1\xa15\xfdkzg\x1d\xed\xa9\xbd\x7f|\xc0\x1e\xee\xbbv?\x1fdP~\xf6\xeb\xc6\xa4wG\xa3\x95\x11\x9b\x97D\xb3U\\>\xab\xfdZ\xda\x0b\xe9\xe9\n\xcb^\x86\xa6C\xf7u\x1e\xfe\xbc/\x8e_j\xdac\x8a!;\x98\xb9^ \x0e\xfb\xf1{\xfe\x03k\xd0_;t3;M~%\xf8\xcc\x10\xb4:1q\x0d\xf5\x01\xef\xc5K\xcdpsL\xf5\x95\xf3\xc0\x15\x1f\xf0\xda\xb9\x0cA\x1b2Sh\xd2\xec\xa7\x0e\xf4\x01\xc1)\xe01\xdd\x12\x13\x84\x00\xb22q\xe1\x17A\x93@Z\xdb\xda\xad\x9f\x19V#\x86#\xf0\xf1\xee\xc2\xfb\xbe*\xc8l\x1d\x17\xf7);\xf8'/\xa0\xd4\xed\xf7\xd8\x89\x9ep\xd6p\x84\xce\xfc\x1d\xdb\x81\xe9Y\x80i\xcf^\xe43\x0cZ\xea'\x98\xca\xd0\x86B\x1b8\x02\xcf3Q\xffq\x19\xadi[\x1b:|\x84Q\x81\xb7\xaa\xf9t\x83$\x86\xfe\xef\xda\x9c\xd2$n\x92\x18c\xb6\xcf\xfd\xd8h\xe8\xa1\xe3h\x86\xe7\x9eO\x13\xbc\"\xc2\xff\xb9\x93\n\xbf\x7f\x89\xbb\xfbW\xfdu\xe7 \xbd\xdaC\xa3Kr5\x94\x93k=\x94Xk9\x98\xb0K\xa6\x82\xd2~{1\x94X\xeb\x9c%\xba\xd5e\xb3\xbd\x16}jSH\x9d\x88>\xb5\xcd~\x1aL\xf2{:\x94\x13\xeb\xb9\x18\xae\x16J\x97B&\xef\xbfz\xc6\xd3\xea\xbf'\xcb\x93O\x85\xef\xfd\xdd\x9f\xc6\xf7\xffy\xb6;y\xf0\xe0\xf3\x83\x07\x81\x17\x82\x97x\x9a\xef\xder}\xf5\xf3\xe6\x8c\xf5(k\xf7\x9e,\xf0\xf0\xf6\xec2\xb4(x\x03&2M\xe2\xc7,_\x7f\x87\xebGk\x00\xe0\x17\x9c:\x04\xef\x0f\xf2\x1d#\x87\xbd\xe7\x1f\xf8\xa4\x07\x94?\xaf\x8d\x8a(f\xcd\xf1MI\x16\x06K\x0e\xa1\x91\xec\xce\xdf@\xdbE\xc1\x8b\x00\xbc\x86a\xa7\xd2^\x08\xda\x83I\x14\x94\xc8i\xad\xcb(\xa9^\x96\x84\xa47o\xe25\x99\x07~e\x0d\xeeN\xfb\xc2\xb4sJ\xf6#?\x93\x14\xd3~1\xaag\xe2\xda\xc20\x05\xd1\x04\xd6\x9b\xaa\x86\x0b\"Y8\xf0)\x9a\xdc\x7fO\x16\x81\x913U\x0bk\xc5\xe1\xfe\x98\x8f}\x02\x0e\xd9A\x16\x1b\xbc\xa3_\xd9,\xcamW\xa4\x14\x8e\x0b8B\xb1\xdc\xdek\x81\xa1\xb7\xf7\x1c\"E`\xd8\xee)\xf3\x9b\xb5en\xa3\xe5\xca\xf1\xbe\xca\xed\x02\x85\xb6\x96\xd2\xae\x0b8\x86\xdc/BH\xa9 gL.+\xca\xb8\xdb\x01\x8e, =-\xec\xb5A\x15X\xe6v\x88\xc0\x18\xd4\x01\x8e>\x0c%\xae\xdc>p\xc5!\xd0\x1f\xc8\xad\xd7V$[6\x91\xc7\xac\x9d\xdd8\"\x03\x12\x90\x95?\x0f\xe1*\x84\n\xcd\xbb\x1c\x16\x029\xa1M\x9aR\xb6\xeb\n\x8e\xc1\xbfA\x91y.\xfc\x07\x19\x9f\xe8/\x05u\xf1o\x02\xc62/9\xd1\x1dV\x93q\x99\xf6_\x06%\\)\n\x8c\xc6\x88\x80\xee\xa9%OhD\xe9(Bh\xe3_\x850\x0f\x82\x88+\xad\xe0\x18\x96\xf2\xef ,\xbb&]N[\x0ddl\xa3\x11\xbb\x0d\xb6\x00/\x8c\x051l\x01f\x18 j\xb0o@\xe0j\xa4\xa5\xc6\xc5\x98\xd3\xa9\xe9\xa9\xa2\xdeZ\xe7W\x84\n3\xb0t\xc8\xfaE\xf7\xefEK\x1b$\xa4\xe4\n\xd3\xdf\xb8-\xc77\x1c\xae\xd6\xca\xb63\x0b\x84\xc6\x89\xee\xca+\x14R\xd3f\x96\x17\xa12N\x91\x1b\xd0\x9acT\x14\xb9\x94W\xd6\xea\xb7\x81\x03\xe8\xdc\xce+\x10\xc4l\x9c\xc5\xb6Z\x84\xfa@\xab\x005\x15iST\xc4\xf5**\xc9|3#\xfe\xd6C\x00\xf52\x96ytNk\xbc:\x9d\xd6nA\xa2h\xc1\x8c\xfd\xee\xfb\x08F$\xa55\x15>hU7\xcc\x9d\xe4\xb9\xb2$S\xb5'\x7f:\x82=\xd4U\xec\x85\xcdmn\xe0\xd7AG\x1cv\xf2\xa4\xd3\x15q\xb1\xe3\xd7\xd3\xcc\xe1\xb2\xbf[\x86\xe2\xf2\xe8\xca\xad_\x8f1\xb7\xb9\xf5K\xe1\xa5q\xd1\x88\xe4\x17\xd6o\xed7\x12\xdd\"p\xc9\xc6\xb5\x81\x95\x011\xbf5\\\xf8\xf7\x9ejd\xb0W\\\x80T$\xbc\xd7&23\xcfg\xcf\xe3\xd9\x8aL\xe0\x9d\x1e\xb5\xe3\x8b*O75I\x167\x13\xc8\xf5uf)\x89K\xde\x8c\x9b\xd2\x85\xf33;\\\xf1;')\xa9 \xbb\x8a\x98t\xf1\xf7\xdd6\x91-\x94\x16\xcd 6\xa8x\xf4\x93TE\xf0 \xbc\xd5W\xba.\xe3\x82\xd7H\xf45\x96\xa4F2n0\xbfG\xdd\xf7\x04b\xfd[\xf2\xa9.\xe3Y\xfd\xb2\xcc\xd7\xd8\xc8F_M\xde\x06\xb9.\x87r\x19x\xce\xee\x920\x81\xec0\x88W$\x9e\xa3\xa1\x87}\xd3<\x9b\xcdHQO\xc0\x8b\x8b\"Mfh\x8f\xf3\xe0\xe7*\xcfBP\x9f\xdc\xc4\xeb\xd4\x1b\xde/\xc3\xf47\xcd\xe3\xf9)\xdaF\xef\x98\xe3\xaf\xdd:\xdf\x0c\x8a\"\xe8^\x84G\xf6\x80\x91\xce\xb6-_K\x02_\xc5\x0b\xf2c\x1e\xcf\x07=\xb4F\xe1-\xc7\x19#\x0fH\x97\xe1\x1dcF?\xe4\xe8\xa42\x81\x99\xbe\xaa\xb8\x1f\xf9\x8b\xfa\xc9%\xc9&\xb0\xe8\xd3\xa5\xa0k\xb9\xc3\xa7\x08G\xf0\xaa\xaf\x8a\xfc\xd9\xaa4\x17*V\xa2^\x0f\x10\xf5z\xa0cp\xd0\xeeD5J\xa9{\xe6FcMZ\x1enm\x0ds\xf0\xed\xf6\x9f>\xfa\x02C\x1a\xf5\xcd\xaf\xa0Z.\xad\xeb \xdb\x1a\xec\xc0\xb0\xd1\x0e\xe8\x8fI\x93\xc29\x17\n\\3\xba\xf6\x87\xc1\x14\x95h\x12\xa7Q!\x99\xb5\x94 ^1\xe8\xa7\x85lv\x1c\xadI\x1dS\xa4\xe6\x7f\xb24\\6\xe5\xe6f\x1b\xe5f\xdeUnn\xacZ\nf\xd0\xd4Isk\xfb\x08T\x0dl\xfb\x16\x1a!\xd8\xe813\x88i\x9b&\xc3$\xb5\x08;\x8fH\x88\xabL\xb1m\x89\x003\xf8Vhn],\xdag\x98\xee\x04\xb7\xc3\xf0X7[\xf0.\x80\x1d`B,8\x82Y\xcf\xfe\xa2[\xa8x\xcd\xf8\x1d\xfc\xc0\xdfca\xd89\xfb\xf4\xcbm\x08\xb3 \x88\x10\xd6n:\xd7i\"\xe5\xe8M\x08\xbf\xdc\x062c6\xe9\xf8\xa78\nb\x887I;\xc4\x97\xfd+\xe0_624\xe5\xb8\xed\xb8A\x0b.\xa4\xa3\x8b\x81\xa0W]\x13\x89\x94`\xfeqH2h#*\x8b\xbdT\xb9\xe0)(\xe6\x1d\x1d\\\xb5\x9bU;\x9b\x18'\xd1\x9a\x94K\xf2\x82\x90\x82\xae\x98E`\xba\xb5\xc5n\xe2\xad.\x98\xac\xdci|\x16\x04!\xcc\x18]\xa2\x84J\xd6\xe2\xba\x9b\xa9D\x96M\x08\x1eV\xf3\x02\xfaM\x9fG\x10\xc5Y\xd6i=\xc1XTc\x0eu\xeb\x19\xd9z%e\xf7\xdf\xc8\xd8T\xfd\xf5+\x1c\xd8\xf9\xd0\xadl\xd2\\\x90\x8e?&\x1b\x9b\xf0Qgei9+{\xd9\xd6q\x1d\xec^\x82\xe2\xbc\xec8\xa6O\xcf\xec\xea\x9d\xfe\x1d\xa2E\x1c\xe9wC\xa9q\xd2\xb1]+\xa3\xaa \xb3\x10\xaa\xa1})e\x90\xfey\xe2@\x84\xdd\xb4}\x9bi}\xa6,h\x19\xc9\xa5{\x1d\xcf\xca\xdcO\xed\xa4e\x94.E\xe0]\xe3\x87j\x0bR\x03\x0d$\xf2\x0e9\x1dv\xec\x18P\xb4\x04\xea\x8a\x88s/\x0bac\x10\xb3\xb4O%!\xd64d5\\\xfdoJ\xf6oB\xc9\x9a\xa4\xcd\xa3(\x99i/\xd0\xd1\xc6z\x1aa\xda\x08\xd2\xb1qC\xd9\x122d\x06NK<\xdd\xb4w\xf4:\x9f\x93T\xc0\x9d\xedjZ\xc7\x80\xeaN\xbbY\xe5\xed\xed\xbbx\x14\xe3>~\xaf\xc5\xff\x8f\xef5\xfd`\xcc.*\xd2T@\xdf\xf3l\x95\xa4\xf3\x92d\x13]\x8cq\x16e\xb0v3BM\x86l\x95\xe4\xe1&b\"\xca`\x0b$*\xca\xbc\xce\xff\xca\x9fgp\x8c\xbbe\xd3\xde-\x99R\xab\x89P\x8a\xc6\xc4W\xec\x99\xbf\xa7\x04\x8c\x08|\x12\x89\x99i\x94\xcb\xc6\xd3T\xb5\x84e_Ok\xc3\xa5V\xab\n\x1cAB\x913\x13\xa3\xd1\xba\x19t=\xf9~u\xc2\x19\x0fY\xfcm\xf8\xcbC\xdd\xcbJ\x98\xd7i-\xe8RA\x90\xb5\x0d\xcfTM\x91 \xf2\xae\x17i\x9d\xb4\xf6\xcc\xb0M\x86o-\xf3\x9cR\xc1\xdc7\x9a\xba\x81\x8d\xe8t\x1c\xc9I\x08S\xf3hd\\\xac\x11\x81\x89\\\xb8\xb9\xabnP\xf5\xb8$\x19\xc6\xc2\xda\xb1\xa5\x1bB\x1b\x13[\xfb\xa0\x08\xc5dJ\xd4t\x03v\xd5\x08p\xa3\xe3L\xee\x00;K\x17O\xcb38\x86\xc4\xa7\x7f\x0821a\x8fq\xbd\xe8\x83\xc1V\xb8\xe7u\xe2\xcb\x85f\xcdl\xd2t@\x91\xae_\x7f{\xc0\xa9;\x8e;G\x17\xc5\x97\xb1;\xa7g\x81\xd6\x19FL\xccE\xed$\xd9\x04\x19\x15\x92\x81$S\xd3,*\x7fS\x9ei\xef)\xe4\xf0}c\x87~\xef\x1e\xf8\x0c\x03\xf2\xb3\x10|D\xb8\x86lN\xcb\xb3\xe0)\xe4\xbb\xbb\x01\x0b\x911--\xd7\xfbb\x1a\x18\xe0E\xa1\xd7_eu\xd8\x8e\x18\xb3F\x0e\xdb\xaeu\x03A\x945\x82cfi4Q\x9f\x1e\x888\xc9Hu\xd0\xafE\x11\x1cu6\x0dN\xfb\x12Ui\x8dA\xa8\x05\x0f@\xdd\xc9#6\xa4\x98j9\xcd\xd0\xa8\x9eE\x8e-Y\xfe\x85\x1c\xad\xd4\xd0\xe8?\x04\xfalxg*\xc4w\xf4V4\xfa\xb7\x9b\x99\xf7\xd9X\x06o\xf8\xd6\xe5p\xc0\xf1\xf9\xdf\x8b5T\x7f\xfd\n\xdc\x84\x10\xc3\x1e\x0e\x89aZnB\xf0!\xfbZ\x8b{\xc1\x88\xeck\xe5;\xc9\x89<2q\"\x99\xff\xed\x00\xf6\x0cr\"W<\x03Y\x87\x99\x94\xa2\x1bKs\xab\xf2*\x03\x9b\x1a\xb7%f\x0b\x9e\x85\xb0\x08\xa1\x08a\x1e\xc2\nMF\xd7h\xbdv\x03G\x10\x97Kt5T2m\x1d\xa0uYc@!\xabL\x0f\xe8!\xda\xfaI\xf9v\xfdn\x97Z\x141\xf6\xeb\xd29\xf2\x14\x9e.O\x9f\x06P]'L>\x14\xd9, \x86\xce\xb1\xd11LW\xe8\x90\xd5S(\xce\xe1\x08nx\\\x99\x93\xacNJ\xf2\xa1$\x84\xa5\x18\xbe\x11\x86\xf5,\xb50\xad\xf6\x8f\x0d\xa9\xeaWYM\xca\x19)\xea\xbcd\xc9\x86\xe9\x9b\xaa\xc8\xb3\x8a\xb4^\x15\xf8\xaa\xad\xe7b\xd9Jo4\xb22\xcbGl'\xd2\x80\xa10\xea\xd5\x8b\xa4\x9a\x95\xc9:\xc9X~\xbe\xcc\x8d{\x92\xa6~\x06+\x90n\xe9O\xd9x\x83\xdf-\x1a\x98L`\xe1\xf6m\x1bh\x13(\xdc>\xebCu\x02s\xeb\x97\xb7!\xda\xce3\xf6[\xa6\xbe9\xbd\x8e\x97KR\x06\x0e!\xf3\xa0 {h\xadKe\xb15\x86\xf2d\x8aY\"\xb2\xac~\x1bv%\x8cN\xea\x0d*\x8c\xael\x863\xa2\xb0\xe1\xac\xdd\xc0\xd6\xcf\x80\xe1\x1a\xad\xab\xbaL\n\x11\x85\x14\xedl\x06\xadcD\xb1^\x12\xe1&\xfe\xd6y\x13/\x99\xe3/\xc9\xea\x10vJJ\xc2\xda\n|\xe6\xdb\x99\xa9\xcc\xe7\x12\xc1\xcfW]\x91\xf8\x97|Y2\xf4\xd6C\x16\x9f\xaeQ|Qn\x8a\xda\xf7X\x87^\x08K\x97\x19X2\xad\x8e\xc9\xac*\xb5\x18\x96L\xaaF\xc6\x960VI\xebb\xd8\x9f\x8a\xb8\xa5\x93j\x8b\x81\xc3F\x0e\x0d\x93\xb0p\xb9X\x9e\x14V\x9d\x99\x1f\x8ce\xaa\xfe\xbdX#\xfd`\xf2A&@s2\xef\x19O\xe6\xbd\xf6\xc9\xbcg:\x99{kjSE1\x0b\xe97\xf1z\xc0+\x809d\xaf1\n\xbb\xb9\x16\xc6\xe2\x8d(Yf\xe1\xb2\x0c\xb9\x9a\x9dG\x08|\x94\x89\x1eV\xfbFX\xed\xb7a\xb5?\xc4\xc5\x80\x8a\xdb\xe4\x13\x99mj\x16rZa\xcf\x86\x891#\xc2\x04I\x8ay\xc7\x86]\x1aDB\xf0\xfa\xe7\xae\x87O{G*}\xbc\xa9H\xf9\x92\xd4\xb3\x95g\x8d\xc1&V\xd4\xca0\xb0%\x9d@9\\M\x0d\xcaeI)\xac,\xffP\xa8\xb4\xdb\x10\x12\x831\xb7\xf5\xd6\xde\xac\x1f6\xed\xb6\x9a\x1d\x1d\x94\xe6k\xbb\xe4*\xd9\x0b\xfd\xdbF\xcd\xc1\x03\n\x1c\x03\x95\xd4\x0d\xa0\xcd\xb1-\xbe\xcc\x1f\xe2\xa5\xbeV\xd2n3\x87c\xf0\xf87\x1e\x18\xcd\xa4c\x96\xec\xe7\xe0m\x03\xe4\xe7\xf9\xba\x88\xeb\xe4\"I\x93\xfa\xe6u>7\xec\xe2\x8d\xc1\xdb\x96\x96\x05\xbe3\x92\x12\xc6\xaf\x90x\xb6\x92\xdd\x06\xf4\xa8\xb0s\xfa\x8d\xb6\xdbNb\x18\xd8l$&\xc5Z\x12\xc7\xf4[\xdaO\xa3:^Vp\x0c3\xfeg\x00\x13\x98&gc\xcd\xc0[\xce\xb4G\xaa3\xad]\xbb\x8a1\x1cX`\x1c\xfc\x8f\xddF\x0c~\x06\\\x97\xcd\x00\x9e\x17\xaf\xe6\x81\x9f\xe2\xfd_n\xdb\xf0\xa2\x0c\xa3\xc6\x04bk+:W\xedn)PDv\x1b\x11\xe7\x98\xed\x8d\xc2\x18\xba%\x8a\xa0_\x86\xfd\xd2-\x12q\x9c\xfd\xd9Z\xe4\xccL\xdeE\xb1\xf9wQ\x8c\xdaLgg\x01\xd0\x7fwwCH\xa6\x9e\x07\xbb0\x83]|D\xf1\xa5\x18n\x83\xa9\xa9\x9b\xb0D\xf4\xecK\xb0M\xfb\x8aP\xcc\xa4\xa2)\xed\x8a\xa2\xa4C\x04a\xacz\x04s\x16\x8a|\xfcp\x81wK\xe5^:L{m\xeeyA+\xb7:\x9c\xd3\xde\xcc\x89\x9bAQ\xe2\xb31\x17\xc6\xba\x06\x06Z\x7f\xa9\xd66;\xfb\xcaj\xb0\x10\xea\xa8\"\xe9\xc2\xe0'\xac\xde\xb2\x1d\xf6-\x10\xd6\xf1%9aL\x0c\x1cQ\xb2\xc1\x1e=+\x92\xeaC\xbc\x94\xb4\xa1\x92\x7f5\x95\x9d\xf4Vw\xc0\xb2\xea\xf7\x1dj\xce\xd4\xe1\x1b\x9d\xf63^\xb3hMh\x80\x1a\xd9h\xe2v\x07*t8?s\xad\xd9\x85Ic`\xa2\xb5\xa5\xe1@\x96w29$\x99\xe9>KVJh\xa5r\x9a\x9f\x0d*\x9c$\x81\xab\xb47\xf4\xc0x\xb5l\x9a\x9f\x05\xd8Xs\xf8V,,\x8d\xb9i\xceMO\xf0\xebi\xa2W\xf2\x9b\xf9\x0e}\xc3q\x91T\xba`\x81=\x1b\x0d=\xe6\xffK\"\xfaV \xf8\x8f\xd9\x03nK\xd9\x9e*=K\xfa\x84Q(\xf6\xbf\xd5\x9a T\\u\xdf\x7f\x93\xda\xb0\x02\x9a%\xd1\xbalj\xd6z6\xc6}\xa5g\x89\xca\xb4\x12:\xd7CMW\x0b\x16.\x8d\x1d\x1a\xfa~\xba\xf03:\x17*\x88\xa9\x13\xdf\x9a\xa5\x19w\x07\xf6\xe4` \xce\xf1\x7f\x86\xa6\xe7\x0b\x85O\x85\xd14\x1f\n>\x89*2\xdb\x94I\x9d\x90*\x04\"\xee*0JPV\x7f\xb8)\x08{\xca\x14\x08\xcac\xc3I\xc3\xa4\xaej\xb6\"&\xd9\x8c\x89\x9c\x9a;\x11m\xed\x8a\xd7\xee\xdf\x93h\xab\xcf\x98\xdc\xcd\"\x19\xfcT\x1ax\xf2\x05\xd6\x92\xea\x0f}\xa5\x82\x81\x87\x0f\xf4\x87|~\x13\xa2\xb6\xb8\xbc\"\xa5a\xf2s\xaeP\xa6U\xfe\x1a\x97I|\x91\x12\x83S\xed\n\xab\xae\xea\xdapE\xb1\xe4R\xaeP\x93\xe8k\xdd\xb4k\xfd\xb0I\xd2\xb9\xb1\xb2\x08\xe2\xf5)J\xaa\xb7\xcfN\x0f\x03\xbf\xd6\x1c\x147\xe8\xaeO\x1b~\x0b\xc7p.\xef!\x95\x88\xe8\x86 \x83\xef\x8c\xc4bS\xa6\x13cd\xa3YI\xe6$\xab\x938\xad&\x80Z\xf6Ut\x9d\xd4\xab\xe7\xcds8\x06/\xc9f\xe9fN0\x0ca\x15\xaf\xc9}\x16C\xcc\xd0h\xe3\x08l85gy~\x89q\xdeuF\x84\xfd\xf9\xc5\xa8\xfd\x7f\xa7A[z\xb4\x07!T\xb2B\x0fS\xe1\x08*\xca\xf4\xf3\x1a\x12\xed(=7\x80\xf2\x83\\\xaa%\xa9%\x91}\x1f_\x07CQew>\xa8\x91U\x9f\xfb^\xc3\xa4P\x89'\xc3\xd0\xb1Y^\xc3\"\xdfds\x9d\xab\x10\xed\xfb5F\x9e\x94\xd4C\x0f\xbeWmm\xd3k8\x86_na\x02\xaf\xf5\xd5\x7f\xc66\x87t1o\xb0\x86\x10\xd7\xf5\xf3{\x17m\xca\x14v\x8f\x8c\xa6\xa1\x83\xaa\x01F\x93\xcc\x01\x03$\xcd0\xdeT\xb2\x8dm\xbcU\xec\xec{c\x18\x9dF'\xf1\xc6pdr\x1d\xc4\xcf}\xcc\x0cB\xd8\xc9\xa4\xa5\x8d\x88(\x10ql\x0e\xe1]\x1fr\x12joBx\xc7\xd7\x80\xa2\x17J\xc1?\x07Q\x9d\xffT\x14\xa4|\x1eW\xc4\xc7\xa08G\xb0d\xca%=~\xbc\x97*\xfej\xfa\xe6\xccT\xb3\xe4\xd8\xce7b\x14\xa3\xbb=e\xa7\x0ch\xf7\x02\x8e\xe0\x99\xe2\xa9u\xea\xbfR\xc8_\x104\xcf\xdf\xb7\x9ek\x9a{1B+'4\x8a7S\x12%\xd9\x80-ai\x89\xb3\x85\xaa\xbd\x8b|~\xe3\xc9\x18\xb2\x8ca@\xbc\x8b\xd5\xbf\xa3\xc6h_Z\xb4-;\x11\xb5\xd0:\x8a}\x94\xc5k\xfck9e\x7f\x9fQn\xce\xf0>\xc1M\x1e\xb10\xadX\x19&p\xe9\xb3\xbfCx\x11tn;D\xc2\x96\xeb\xb8\xcc|\xef\x9d\x80+\x8f\xd4\xcf\x9a\xc6p\xfdI\x05\xf1\xfa\"Yn\xf2M%\x83\xdb\xd7+\x02<\n3\xee=X\xc5\x15\xac\xf3\x92\xbe\x893\xc83\xd2(\xfa1;\x00~\x91!\xee\xf7z\x88\xb39\xbe.\xe2\xaa\"\xf3\xfbI\xa6|\x8b\xba\x8d\n\xe6 \x8b#\xc6\xfa\x848\x83?$\xd9\x1f\xd8\xdb\xc8\x0bB\x11\\\xebh8\xf6bG\xd5%u\xeb\x8a8\x86\x91\xb9\x1bsCy\xf2\x85\xbd\n\x8cCHJ2\xa7\xbfvH\x84\xb7\xe2'\xeb\xa2\xbe\xf9+3\xf9nH2\xf7\xe2|/>h&\xd8\x06\x06\x856\x9dgQ\xe6W\xc9\x9chI\xb5:\x99\xb7]L\xf3\x98;\xa8@E\x8ev\xf5M\x81\x88\xa2\xd1@\x976\xaf\x0d\xe0[@I\xa3:\x90.\xdf\xcdK\x03d\xa02\x058M\xb48\xec\x85;\xb6vqA\x84\x97\x8c+\x1c\x91!\x041\x18\x15s\x80l\xf2\xbd{\x90Y\xb4\xce%\xf9\x871\x0e\x8d(rl\xd6@h\"3\xc1p-E\xa9\xfcj\xb8\xa6\xcdz\xc4\xd9\x9c\\\xa7f\xa6\xa4\xf1\xc7\xbe\xa9\xc3/\xcc*@\x0f6u\xe8N\x9d\xa0\x9d\xf1;\xcem\xd2\x9e\xae\x9b\x9e~\x0c\xe1]\xc0\x83\xef\x9ct\x1e\x07\xe2\xcc\xc3M\xda\xb6\x80\x97\xe7a`\xf1\xbd\xa43\xfc\xa9\x9f\x8aM\xf9~l\x98/q\x9c\xc8&\x8c\xde\x18\xa0J\x96\xbb\xe0cP\xfb{\xc8\xdeb\x18\xec&goE\xca\x04M\x8b\x06l\xceoC\xfa\x99\xbe\xa7\xe6\x10~\x8ec\x82#\xf8\xa9\xbf6\xfd\x13\x9c\x0d\xee\x9d\n\xe8>\xc3\xc1\x02#\xa17\xf6\xab\xec\x7foHy\xf3\xb6|\x99\x97\xeb\xc0\x7f\x17\x84\xf0\xeew\xed>Z?m\xf7\xac\xcama#\xb20\xb9\x97\x9e\x80ng\xbbMV\x06)/\xdbo\x14K\xa7\x1b\xc5\\\x11\x02\xcd\xb5\x12'A\x15\xa4\xbc\xec$TB+\x99!\x12\xffXp\xe6\x03\x86{\x15\xdf\x02J\x92\xb6:\x84\xa9\x87<\x9e\x87\xf7\x85~\xc9\x82\xd3Rv\xf1\xc7\xfc\xbaa\x17=6\xb0\xca;\x0bD\x9c\xb7\x81f\x1cj75\xcc\x03N1n\xbb\xf9\xfd\x8c\xc7\xd94sj9\xc5fDi\x97,\xae\x14\x91\n*\xc6\x8dL\x85*\xcd@6\xa59*\xdb\xd0\x0d_!c\xe9\xe5\x01\xfc \xee#\xcf\xe6\xa7\xec&\x86\xce\xb2\x9a\xaaUL>\x93;io\xba\xb2\xa1j\xbawF\xc7'\xda\xdb;\x0b(1\x14\x8dz\xbfxM\xcfn3o9zL\xcf\x98\x87\xc7\x83_\xfc\xe9\xdfo\xcfv\x83\xdb\x07K\xd5\xcf\xe3)\x0bs\x81\x862> \x9e\x06T\xb6\xd8T+\xbf\x9c\xee\x9f\xd9}6\x0d*`?\xdd\xe6f~\x16]\x89\xfd\x85\xbcq\xf3sJ\xac\x97\xa1b\xc2\xed\xaf\x86\x8fo\xe0\xc4g\xc3\xef\xf3\xa5\x0d\x9b\xfd\xb3\xb2\x13\xc9\xfd\x17\x99\x1c\xe6\xd6\x0b\xc1[\xda\x02\x81\xd0\xa5O\xa5\x97j9\xe8\xccd\xba\xdb\xd4\xf7\xd0\xb5\xc6\xb2m\xac;\xb9\x1c\xb1\x85\xcd\xae\xef\xc2\xe2\xcb\xd6 ]\xca\x95<\xb6\x19\x93l\x8b\xdfPj\xbe\xa9-\xdf\xd0\x13\xe6\x9d\xcf\x1dLgy\x8a\xb4\xf4\x9d_\xb6\x1f\xd8F\x9b\xe0\xbe[\xe5\x15z\x1e\x96\xf8\xd7\xf0\x17\xcc\x85\x8e\x92s\x14T\x1c\xfap\xc9\xac\xcb\xf1E\x84O\xf3\xe97H\x9e\x138\x86\x9cb\xf4\xe4\x01\xe6\xd4\xf0\x13\xd8\x85\x18\x9d\xf0\x82\xe9F\xf5\x00\x84c\xd8\xb4\\\x99`b\xc8\xbaz\xeb\xa7!hr\xb2\xdf\xfa\xe8\x9bk\xa7\x15\xe3x\x8a!=8H\x8e\xc2\x85\x0b\xc8\xdb\xc7z)R\xb2XX\x8c.j\xe5\x03\xa8E\x97\xb7}oT\xf3 T\x98\xf4K\xfc`;\x0e\xfd\xad\x8cma\xf4/\x8a!1\xc3\xcd\xa4\x83\x9b\xab\xba.\x06p\x87\x19\xf4\n\xdcL\xe4_C\xf8\x96\xe27\"\xb0\xbb\xad\xf6\xcc\x82\x99]\xac\x9caz\x17>\xc9\xae\x99+\x96\xf6\x89\xf0\x1b\x17&\xc6\xf2\xbfy\xf80E\xdd\xc4n\x98e\x8di&i\xa2\xe6nU\x03\x82\x7flH\xf9\x95V\xc86{ &\xb3\x8e\xbd\x8ep|\x08\x03\xf6\x17\x87\xc0\xce>w{\xbbw\x0f\xbc\x8b'?\xbd\x7f\xf5<_\x17yF\xb2\xda\xcf4\xbe\xa7:\xcb\xea\xbc\\\xbf\x88\xeb\xf8_\x12\x00~\xc64\xc1=\x0b\x16F\xa5\xe8\xd8\x11<\xf8\x87D\x13\xfa\xcbiC\x89-a\x1ee\xa7\xe3I\x7f,\xe6o]\xb6\xab\x1ei\x1d\xfc\x05\xfe\x93\x03\x0d\xa8\xbf\xee\x9c\xc5\xe8\xcb\xf9\xf9\x90\x12P\xc4`\xd2\x8a\xc8B-\xf9\xed\xe3q\x81r\xff\x05\x08\x8e\xb9bC\xa9\xcdu\x10*QU\xdf\xa4\x03\x95P/K\xd14\x1d\xf6\xae\xe9\xabr\x86%\x18\x8c_g\x1b!8moZp\x16\x13HP?_%\xeb\x82\"\xd4\xe0\x17|J\x13\xd8\xd0ol\x990X6\xa0 \xec\xec\x1b\xab\x99$\xcb!\xfa\x9f\x0b\xd2\xaf\x0bL\xf2\x1f\xc9\x98\x99\x19\xb06K5\xcc\x88l\xfa\x91\x0e\xbcM\xc6mF=n\xdb\xa5\x04+\xd2\x99\xb6\x8b\xe2\xcd )\xde*\x86\x8d|Op\xc3\xb1\\me\xa4\xb4\x0f\nq\xca\xacY!\xdb\\$\xc5\x8c\xa9\xbc}?\xf3\x86\x0fAQ\xf8n\x19\xb5\x15E\xc1-\xe9\x98r\x95\xf7\xe3\xe8\xce\xcew\xa7\ni\xb7\x0f\xc5\xb6\xe3\x07\xf6{\x82f\xb4\xf0\xd0IP\xcd\xc6\x1dJ\xee;e\xf4\xa1\xd0\xdf\x1e\xad'\xb7}U\x0b]\xdf\xa9\xc7S(K\xe6\x8c\x12\x9e\x9a\xbf\xec\x9ad\x11\x14\xbb\xa6g\xae\xdd\x81\xeat!\xc1\xb0\xff\xa8\xe3\xe5\xac\xdf`[t\xe2\xfd\x0f\x14\xfcM\xed\xfd\x9c'\x99\xefi\x9c\x13\x95w\xd0E\xd8_]#\x9b\x0cid\xe3F#\xdb\xd5\xb9\xb2[\x90\x17I\x85\\!\x99S\xfc\x88g5;\x01\xf3P\x1f\xc3\xdeb\xb8i8_\xb5VF\xf5X/\xb0Krcc\x04\x9cTl\x16M,3\xfd\xb42D\xcc\xafk\x88\x1e\x00W\xeb\xda\xe7(\n\x87\x13\xe6\xd6\xb2Ku\xe2(\x1c\x8e\xe1h8\x8f\xa0\x7f\xe6\x88\xc2\xa2\\2\xa6\x92\xb15M\xb6\xdc\xf1{lc\xca;/7Qhrv\xc1\x81\xa4\xf1\x05I\xbb\xe3`.\xf2_e4\xd1\xe0h\xd6q]&\x9f\xbe2X\xc6&r\xe1M\xb2,2 \x1c\xd3\x83\x84\xb9\xfbQ\x06\xef)\x05U\xcdX=\x0c#2a\xaa\xce\x10\x7f\xe9\xc70\xe0\x8e\x8a``\x8a\xb4#\x9b\xa7\xbe\x90`\x13\xee\x1c\xdb\x8ccB\xfb73\x9e[\xc0\x15\x1c`\x0b\xcaBkn\x02\xc0(\xed\xb3-Q\xc43\xf2\x82\xa4\xc9:\xa9)\x93\xee4\xfd\x94O_\x99\xf8o;o\x0f\x83\x15\x18RX\x0d\xcc\xbeH\x8a\xd1\x93\x9f\xfd\xcbM\xfe3\xc6\x0eu\x9dh\xde\x0d H\xeb\xa1AE\xc7\x1d\x92\xbe}\xc2\x1c\x92\x1e\xe9\x1d\x92\x985\xf9#]~\xff\xd4i%\x05\xec&\x0f\x8e\x7f?=\xfb\xffv\xbe\xb9\xf7\x07?\xf8\xe3n\xf8\xf4\xc8\x93\xf7\x19\xdcp\xb6?\x15\x8d&~L\xa7\x0f\xfe>\x8d\xef\xffs\xef\xfe\x93\x8f\xf7\xa3\xf3\xff:\xdb\xfd\xe6A\x12\xd5\xa4\xaau,\xd7\xb6~\x01O\x0e\xf7\xb7\xb7\xd1?\xd8\xfe\xd3\xc3/0\xefo\xbd\xfa\xb7\xd4\x8a\xca\x00\xa9f\x95\xa6\xdd5\xb5\xec[ a\xcc\x9a\xc1\x84(\x96\x08\x95\x9a|(\xd8\xe6`\"\x14\xb3\xdb\xef\xa2\xef=\x8bw\xa3\x86\xcbbtR\x8c\x84\xc2\x9d\x18\xdc{\xe7\xed1\x16b\x8c\x06\xdfeLx \x80\x89F[q\xeb\xd7\xd4\x10n\xe4\n\xb3-\xdc\xbb\x07;;\x1d\xfd\xea\\D\xc8\xd2\x7f\xb8\xee\xc7\xc6\x8aC\x98z3a\xf6\xac:\xfd\xde\x9c\xb2\xf0\x00<\xb6\xcfP*)\xe5\xa6l\xd1\xbd\\]H\xe3\xb4E\xdb8\xad3\xf42P\x14\xd8W\xf4\x1f\x16\xd3\xa6s}\xd5\xc0\x0bG\xd5\xfc\x94a\x7f\x8e\xc1_il4\x06X\x13\x19\xe0&\x83$\x1bN\xde\"8\x98\xf9t(\xb6$p\xa4^O\xb3\x01{\x0f\xb4\x07\xb0\x9d\xd3R\xa1\xcb\xf3\xd6\x7f\xfel\xbb\x10\x03\x8e\xfd9zN\x0c\x9b\x9b\xb0!X\x9bCy?.\x92\xffEx4\xcc8\x00\x0f\x17\x93\xdf3\xf2\xe0\x98\xfeB8\x19\xc8\xeb\xf0$\x08\xc1c(\xd1\xab+.\xcf;\xb5\xd9\x9dp\xaf\xb6\x08\xc0\xa6\xd6\x1e\x9e\x1d\xa8>\x18\xcc/^\x8c\xde\xce\xf2\x80\x8c\x01\x1aW\xc9L\x8c\x86\x85\xccp\xfd\x1e\x14\xae \xc1@\xc1\xf6[\xcfnAuYT\xc4Uu\x9d\x97\x03a\xcatE\xc8\xb3\x8a\x7f,\x0buA\xd9\xa3\xca\x01z\xa2\xc8\xb5\x8a\x9e\xa9w\x8ep\x04\xde\x0f\x14\xfcN\xf1\xbf\xbc\xe5\x81*-R\xae>R\xa1\xe0r\xf9\xb9\x87a\xdf\xe9\x06\x8eVq\xf5\xf6:\x13'`{x\xb9-_\xb2d\xb3 \xcf)Bi\xfa\xdeS\xa8\xe1{8\xf8\xf6\xd1S\xd8\xdd\xad\x03 ,\xda&\xf3\xca\xa1t\xff{\xd8\x7fD\xb9\xb1=\xc5\xf2\xb1\xe5\x17\xd4q\x0c2\xab\xef:>:\xbeR\xb3\x8ebJ:?\xe4l\xca\xb6\xb3V\x91\x18\x8e\x00s\xce\xd5Q\x91\xc6I\xc6>\xa7\x9c\x1a\x87\xdd\xac$qM\xfcl\x93b|y\xca\x0b\x96l\xda%|/\x1d\xb8\xe8\xdc\xcb@UV\x91iy\x86\xf8\x98\xd1?\xd8\xef\xee\x92sS\xe9f\xcd1)6)\x97\xa43\xfe,\xec;\x92\xa2\xba\xb6IC\xd9\xe1\xc3\xd9\x0d\x99T\x7f \x9d\x9b\xd6\x03\x81\xd6\xed\xc6\x0e\x96\xeb\xa8\xb3\xa5E*gVDk\xfa%r\x9cS:\x1d\x83\xe8\xe5\xe7\xedE\xf8\xfc\x99\x8a(i\x9a_\xbf\x13\x18\x8c\x0fw\xcah\x16\xa7\xa9\xdfEo\xba7\x18\x11 S\x0cv\xbb\xb37b\xc3\x0fy\x809LK&\xcd\xecBLp\x87D\xbb\xfa\xbd\xa0\xcd}\xef\xdf\x8c\xcd)A'\xd0\x16\x9aS\xdc@m\xa7\xae\x95^#\xc7\xe0g}\xc1:\x0b!\xd1*\xc0\x18\x8c \xbe>\x062M\x10\x9f\x15\xad\xb6\x84\x02}\xc5k\xfc\xff\xec\xbdk\x97\x1c\xc7\x95 \xf6]\xbf\"P3KU\x0d\n\x8d\xee\x06@\x11MAt\xa3\xbb\x014\xd4\xe8n\xf6\x03 \x00a\xa0\xac\xcc\xa8\xaaDge&\xf2Q\xdd\x8d\x11\xe6\x90#\x8a\xc2\x83;\xb3\xde\x91\xa8\x91=cy\xd6$H\x00\xb3^\xdb\xeb\xb5\xd7\xf6\x8e\xf7\x1c>\xd6>Gs\xa8\x99\xbf\x80?\xb0\xfe >\x117\"2\xf3\xde\xc8\xac\x02 R\x9c\x1d\xd59\x12\x1by\xe3\x1d7\xee+\xee\xbdqFcp[\xfcSc\xeeB\x81M\xe2o(X%\xf9B\x8e\x97\xbe\x9cjS\xf7\xf8a\xda\x0e\xada4\xd6\xe1j\xd2\x1b^\xf7\xebc6ms\xc2#v\xf4\x88\x01\xe8t1bT\xde.\x01\xbe\x90\xa6\xfe \x9cDs\xd4\x18\xca\xf3\xcb\xa6\x0f\x13\xd2H\n\x88\x9d]\x0foX\x06\xc6\xd1\xc0<.$\x95F'A\xfb\x8b\x93\xaa7\xa8_\xc9\xb1X\xce.|Tf\x17f-\x946\xc0<e\xbe\x9e\x9e5_O\x7f\xc7|\x9d\x9b\x9f\x97q\xc5G\xf5\xc0\xe4\xa0\xd8\x82\x80\xb2\xb9\xf9W40\x12\xd8\x0e_\xe7gO\x96>\xcf\x9d\x9eg\xb2\xd9\xef\xb1\x97o\xb0\xa3\xe2\xcb\xfc+\xecG\xec\xe5\x13\xec%f\xea\x9c:5\x7f\xfae\xd3\xff\xa9\xef\x9c8y\xb2hb~\xfe\xa4nbn\xbe\xdc\x06\xb4\xca^b/\x9f\xb07\xddND\x0bs]\xb9\xb0/\x9f:u\xe2e)S\xcc\xcd\xce\xcb\"\x1d\xf6\xdd\xef\xb2\xb9Y\xf6#\xa6\xbe\xa0\xb5\x97; C89k\x86\xf0\n\x19\xc2\xdc<\x19C\xf3\xd0:\x0d\xac\xc2\xce\xd5\xddh\x14;ns\x14n\xf5\xcd6\x8aaQ\xefV\xdd\xc5Cd\xbdr\xa0\xe2g\x9cD\xf1\x02kE\xd5\x0c{\x96fI\xeef\x91zH\xbb\xf4\xa1\xe8\xab\x16\"4\x85b|\xdfb_VaU3/\x16C \x1bTS=\xfe\xcf\xe6g\x8f\x0f\x8a\x16\xca\xf7\xc4\xd5\xc50\x97\xb2\xad\xadsK'N\xbf\xf22J\x1f\xd3\x97i\x89\xe1m \x8a\xbd[\xe7\x96\xe6\xbes\xe2\x95ib\x8c\x88\x90\x19uY\xeb\xa8-\xf3\x04\xa5\x13jh\xcf\xd1\xcd\xc4+\xe6j'f\x1e-\xf5W\x8b\xc0a\x00f\x95\x9eo_\xf5\x0e\x02E(6P\xbe\xbdF\xb7/l\x9f\x9e\xc3a4\xbe\xfa>\x8f\xbe\x9b0W\xb5\xbd\x93n\xfdY\xe9\x04H\xef\xc8P\xbf{\x02O\xb9H\xc7\xac6/;\x9b,;\x99<\x13\x19\xf9\xf8\x1a\xe33\x03\x9e\xed\xf8#\xde\xee@\xf5\xd2\xbf\x17T\xbc\xfe\x11x\x19\xcf\xa2!Vt\xa6\xe2\xbb\xcc\xf62\x03\xe7@\xca\x9f0\xb0\x05\xf9\x97\xfcc\x9aY2\xb5\xf0A\x97\xb9\xf5t;oC\n\x97\\\x12h\xb52G,~f\xba\x02/\xf6\x0fhp\xf1\xef\xa9\xea\xfb\xd2\x80\xa0\x0b\x1e\xf1\x85\"\xa03\xe3\xe8\xd3\xd1\x01\xf3\x91\xfag\xd6\xe92\xc7\xcc\xb4\x81\x07\xa5\xb2\xe9z&#\xad\"\xe94\x13ef\xb2\xca\xbc\x083E\xbaDSm\xc9\xd0\x02`bA\xc5\x18\x14\x1c=\xda|\xe7);\xbe\x1e\xdcP,.\xb81U\x87\xba\xc8\xb4\xe9\xfeX\xad~\xa7\x7fc\xf5\xe8W4\xf1\x8d\xd4X\x96\xcaj\\\xf6\xb4\xc67M\xd2\x8c\xba\xe4s\xb5{\xde/v\x88\xc5\xd3n\x90\xdc\x9c\xfeL\x1a%Y\xbb\xd3e\xb1\xf9K\x06\xea\x95\x9e\x88\x14{\xf7=\xd8\xc3c\xc7\xeawM\x0e\x04v\x8c\xc5\xd3l\x98\xc1\x8e/\xd8\x99\x8c\xed\xbb\x1e\xdc\xe8\xb2#N\x9b_wotY&\xff?\x9c\x8c\xdbZx\xd14\xa8\x90yi\xfa\xfd\xbb\xc5\xb1\xab\xc0\xee\x96\x1c\xa6\x8c\x7fR\xde,kHu\x9c\x15Y\x17\xcfT\x1e\xce\xbaki0\xadm\xf0H\x1bH\xab\x95\xa8\x8a\xef:\xffV\xe9\xbbA\x0e\xe9\xcc\xa9;\xa9(\xfb3n\x14\xcb\xb7\xf8j\xc0\x92_I\xf1\xa8\xa0\x0c\xea!d[\x8f\xd7go<\xaf\x04\xa49%=(\xc0\x0e\xe8u\xb3\x8d}\x9e8=ka\x9f\x13/\x98\xd5\xe2Fj`H\xad\xbbK\x19o\xd8\x9e?1[1\xb4_L\xa3pS\x1cw\xfd\xa0\x9b3S\xfc\x13\xacN<^\n\xa2P>*=s\xd3\xfc\xb3*\xee\xe5\xd6%p#\xfe[G\xc8s\xa9+\xd4\x11\xa2\\&O\xa9;\xdc\xf9\x8c\xf8o\xf5@\xd9\x14\xaa\xc0*\xa9Kw\x03\xd0K\xean5\xb5\xd5\x9e.\xa7d\x02\xa2w\x0b\x17P\xd4\x1f\x8f\xab\xfcO\xc3i\xe4Mt\x97\x85\xb0q\xa6\x8cM\x8bs\x95\x93JR\xe3\xa7R ~\xd3\xd2\xcf\x91\xb9\"\xbc\xeb\x8cN|.\x1f\x98?2\xdb\xe9\xaa\x82V--a\xaf\xb1Dp\xc2\xd9.\xe3\xf2\xeeDH[l\x81\xc5\xf2\xa3\xcc\xb8\xdcR\x179\x00\xa2\xab4V\x99\x0d\xed\xe8XAE\x8b\xa5\x95\"=x\xb0{\x9e\xee7\x8a\xcd\xce\xb93\xa5\xe6\xe4\x1d\x8a:\n\x16\x9b\x9dlF\x9d\xc7\xe7jJ\x8bl\xe2T\xd6\xb7,\xa5C\xd3\xacT\xa3\x05\x8eO\xd1\x93D\xd4\x10D\x94.\xc3\x0d\x89\xad\xaa\x0c\xa1S?\x06ql\xca\x1d\xdaw@\x9a@\xe4\x11cg\x04\xf75\x88\xd81Od\x01\xb8\xc3\xb2a\x12\xed\x8b-#\xcai\xbb\xb5#\x1a0\xce\xc1\xac\xef\xf8\x01\xf7Z]\xd6\xdaY\xd9\xde\xb9\xb9\xb1\xb9\xb2\xb5\xb8\xb3\xba\xb1~\xf3\xdc\xe2\xea\xda\xcarK\xa2T\xd8e|\x82\x18\x86\x16G\xac8E\x92\xba\xcd\xad\xae]i\xc5\xab[\x88\xb7:\x0f\xecf^\xd9\xaa<\xef\xb4\xcd\xb0\x90\x18j\xeb&\xcd+h\x1e\x81g?\x8c\xe2\x1f\xca\x8bL\x9ed\x87\xccOY\x18eL\xa8\xf9Q\xbfX\xe2\x94\xa9\xa8J\xe6\x87l\xeb\xdc\xd2\xb1\x97O\xcf\xce\x8b\x05/\xd6zc\xf3\xe6\xea\xfa\xe5\xc5\xb5\xd5\xe6\xf5\xd6\xcbR%V\x95\x7fE\xca\x92\x8fT)\x8eU)m\xe6l\x03=`\x90WW2\xd0\xac\xdd:\xde\xb2\xd8>a\x17\xc8\xe7!;\xc3,\x8f\x16\x8cKv>\x0b\xb31!b\x146h\x80\x1d\xd6\x84\xe3J\xd3\xe2\xa1|\x1a\xae\x8e:\nb\xf8\xaa\xf5\xcaWl\xf9@\xda\x16\x877\x14\x95-\x11a\x08\xde.\xc7\xb3]\x1f\xdc`\xaf\xc9)\xf4\xc18\xd6\x9e\xed\xb2\xa1N\xc5z\\f\xe7\x1b\x8a\xee\xc7\xec\x18\xe4\xe2o\x8f\x98\xa1\xbc\x95\x00^\xd9\xf8aA\xb8G\x82R\x0f\x8f\x1e\xc5\xf7\xc8^\xad\x89_\xe2\xfa1@\xf4AG.\x9e\xa7\xad\xee\xd6\n\x0d\xae\x8aL\xe3\xbf\xb4\xf6\x95\xa5\xd2A\xa7\xf9H\xac\x1c\xc4\xdc\xcd\xb8\xc7\x9c\x90\xe5a\xea\x0f\x04\xba\xf7\x9c\x94\x1f\x9b\x9be\xea9d\xa6\x08\xf3\xc8\xd9\xf3\xc3\x01\xcb\x86\\6\x96\xf0>Ox\xe8r\x0f\nH\x80\xf4\xe9c<\xe0\xf2\xa8\xef\xfb\xd9P~\xbe\xc3\x93\xe8\x98h\xd6\x03\x81\xb5z\x8a6\x17w.\xdc\\][[9\xbf\xb8vsqkk\xf1\xea\xcd\xd5\xf5\xe5\x957\xd4\x99\x02\xed\x8e5\xbd\xe5W\x9d\xb2\xdc9\xb1\xa0\x7f\xfc\xc7\x83iu\x1b\xa6\x96p\xc8\xbew\x86\x8d'\xdd\xcb\xc8\x85\xae\xf2H\xf1e\xc0\xbeg6q\x021\x1fr\x19\xc6\xe1\xf7}\xbd&\xec\xd2\xee\xf6\x0e[\xdf\xd8a=\xce\x06\xd2W7a\xd9\xd0 a\xc5\xa5\xc1V\xd0'\xb5\xb8\xa9\xa0Jf\xc9\xab\x0bzyqmw\xe5\xe6\xc6\xee\xce\xcd\x8ds7\xcfn\xec\xae/oO\xbf\x96\xf2\xde \xd8\x92\xb4\xdc\xa7\xd7\xc5\xf4n\xc0\xedV\xd8e^\x97\x0d\x04\x99\xeb|\xfd<\x8b\xd5\xd1R\xfd\xb3\x08\xccE \xc3@\xb9\xc5\x1c9\xc3\x06E\xaa\x83?n\x15\xf8\xe2\xcc\xe4!\xe4\x9a\xdct\xb2a\xe1)8\x90\xa7\xbb\x113\xf0\xaa\xe5\xdf\x9cU\xab]1\xbaZ\x1e\x032Y\xc3\xa8l\x02s\x7fz\x81\xd9&\x16\x13\x07\xe1\xe6\xa5\x91\x7f\xb3\x94\xdf\xce\x05\xe5a\xa3<\xcd\xc4qq\xc2\xe2\x18l\xaf\xbc\xbe\xbb\xb2\xbe\xb4rs}c\xe7\xe6\xe2:\x10\x14\x1c\xe12-\xbb5\x9e>\xf2F\x9f\xef3\x1d\xd6\xa4\x0e\xb9\xf2\x00\xebB>Msk\x9a\xb3\xef\xb2\xf4U\x96\x1f=\xdaa\xfe\xf5\\\x86`\xcau\xba\x9e\x0bN\x05\xf7\xf7\x12R\x16\x8d\xac\xda\x8bO\x054\xbfqC\xe2 \x1bRw\x0bU\xbd\xf6\xa2^\xf4\xd3IVJ\x96rB\xa6\xba\xa9\x10&\xb5%\x1bg/\xae,\xed\xb4\x00k\xc5z\xbcJFy$\xbf\xce\xc5\x01\x9a\xb6\xdf\xafD\xa2\xab\x1f\x9eq\xbe-_\xd9\x81\x826\xe5xEa:b\x87\xa9\x86-\x0cr\x8aa)\x9f(9\x92\x82\xc4\x1d\x07\x12\xa7>\x177\x81\x8dc\xfdv\xfdX\xe5\xa9K3'Q\x1c\xbeu\xbc\xf5\xed/6\xde\xb2\x1a\xc7\xa9\x1a\xc7\xa5\x02 X\xadm\xb9\xa5\x027\xedr\x8b\xc2t\xb9\xe3\x84\xa7\xe2X\xb5U\x88\\/\xe0\x025~(F\xf5C\xe6\x84\x1e\xfb\xa1\x18\xcd\x0fK(\xd4\xa9n\xcd\xb9\xad\x8dK7\xb7V^\xdf]\xddZ\x994W#/\x98\xa9V\xd4c\xf3\xb5P+\xcd\x02\x94o\xa1\xb5Eq\xca\x99\xcb\xd2\xd3O\xdd\xf1\xbc\x1fv\xd9\x0f\xd5\xc8\xd4\"\x88\x115,\x02\xc8\x1b_\xfd*83C'\xdd\xd5\xc9n\xdaz%\xbeyK\xb1\xb4\xb8.H\xdd\xd2\xc6\xfa\xce\xe2\xea\xfa\xcd\xdd\xf5\xe5\x95s\xab\xeb\x13\x96\xc6r%Q6\xc5\xa8e\xa87cB\xa0\xb4<\xe3\x85:\xd8\x98_\x83)kxD+\xd8E 1\x1e_\xd2\x98\x94\x1d\x05\x15I\xfd\xb3y\x0f\x96\x9cP.4OdT\xb2\xa3\x16\xb7$\xe48\x99\x14f=\x9e\xfa \xf7\xa4u\xcfB\x03\xd5\xba..\x97W\xb2I\xe6\xab\xc1\xad\xb2\xe5\xc2|,\x0c\x0fM+\xed\x83W\x99\xa3\xdc\xac\xa2\xe7\x9a\xb8\x98be\xce\x8e\x9c\xa9\x10\xf33\xe6E\x1c\xf0\x91\x1f\xf8if\x99\xfd\xee\xfa\xd6\xca\xf6\xc6\xda\xe5\xc5\xb3k+\xd3\xce\x7f\n\xfaZ\x8fQ\x81\x10\x07\xdb\x16\xff}\xfdk2\xd0\xea\x1f\x18j\x81\\O\xbc\xa3\xab\xc9}.~wo\xd0c\xa3\x7fb\xaa\xd2\xeb\xbdq\xc9\xe4\x9c\x03\x99\xf9\xe2K\xec\x9a\x98\xc7\xd4\xfb&\xd9\xc3\xd4\xfb\xd6(\xd7yZ\xae\xc3;f\xf7\x8b\x93B\xd4\xf3Iq/J\xb8\xd6\xdd\x87\x1d\xd6oW\xe4\xeb\xb0\xd3\xc5\x02\xb7\xd0\x03~\xf4#\xa1\x11\xd0F\x1aL\x1e\x89L\x19\xf6\xa3\x1f\xd5\xe5\x01\xac\x84t(\xd7\xfc\xc2\xab1\x12\x82y\xd2\xe6\xd7\xa3\x1b\xd2\xb79\xd4\xc6\x9dI1\x0b\xcd\xee\x81\x926\x94\xfdn\xf1\x1a\xd7]\x81\x88\x1f\xecLm0\x99\xf9K:\xed\xca\xf7\x92\xcf\x1enF~\x98I\x0f\xfa\xc0Du\x17\xfc\xee\x0cs\xcdW\xd8\xdb3\xaco\xbel\xc9p\xbd\x04\xc7\xe7\xe2y\xe9\x0b2u\x8bb\x91\xd4A\xebM\xbe>\xc5V\xadaR\xd6\x8c\x8a\x85\x12\x13\x1c;\x81\xef9\x99\xf4\xe9\x8aK\x1f\x84\xd6\xe5}K\x15\x9b\xc6\xb3-l\xcf\xbfR\xea\xbd\xd6w\xdb\xa6h\x1dI\x94\xb72\x9f\xb9\x99\x81{\xac^\x9e\x9d\xc3\x98\xab5Y\x0de@U\xe6\x0b\xa9#\xe1.\xf7\xc7<\xe92\xf3\x96\x84L)\"x\xe2\x11|\xcc4*!\x1c\xf9BQ\x0b_(\xad\x0cM)SN'Sr\ni\xcf\xcfw*\x8ew\x96<25\xbe\x93\xf4\x909\xfd\x8c'k\x91\xe3M\x13a \xafk\x93(\xcaVC\x08\xc4>C?\xe9w\xc9\xd1\xf7\x19?\xf4\xb3\x8d\xc5<\x1bB\xb2\x98<\x1b.\xca\xde\xd2\x197\n\xfb\xfe O\xb8\x80Zj\xc6 7)\xdc\x16e*(is\xee\xf9\xa1\xd7\x86\xcb\x0f\xe94\xdeT\x0d\xf2\x1a\x9dan\xb5\x16%O\x94\xa5\xa6\x99\x93\xf1\xcd \x1f\xf8\xa15\x0eD\xfcD?u0&W_\x12\x87t\x81Ez\xb3\xeay\xb7\x03\xcb\xd2\x185\x96\xf2\x80\xbbY$Z\xb4\xbf\x0fY\x93\x95\x16r\xdd\xd4\x0ft?q\xe2E\xdd\xbf\xfdQ\xae\x89\xee!U\xdaa\xdd\x05\x0c(v\xb5\x8a\xf0\x91B\xf8\x13\xa7O\xe2\x9c\x19>\xbc<\xd4\x9e?A\xb2M:\nt\xe2\xf4)\x0c\xca\x0dH\xe6\xd90\xb0&\xb7c`C(\xdbc\xd3\xed{&\xa3J(iWQW6\xbc#\x89\xea&$\xe80\x91D*\x05@\x06\xd1\xdf\xfczX\x93K\xa2L$x9\xff\xa7M6\nj}\xaf\xa7\xcfzY\x93\xf1\xb2Y(s5\x89\xb5\x18\xdb\n\x9d\xacL;\x0c\nQ|/\x1e\x0d\xd9\xd6\xa7\x85\x16\xca\xa5\xcdR\x14\x12\xdc\xd5r\xfaMz5?\xddX\xdc>\xd1\x91 \xcd&>\xb2\xc1\x16\xd8\xf5\x96%\xd3b\xcb\x12\xa6*\xd4\x82\xbc\xdd\x11r\xc8j\xd8\xben\xd2E\xa4]v=\xbbA\xd2\xc1\xc0F\x04\xec5\xe6\xcb\x07\x99\x13\x94\n\xb3![\x99\xfd\xdc\xebdq\xb5\xae5:u\x9c\xcd\xcf\xd2F0\xc5\"8\x0b,\x98\xc9\xa2\x8b\xdb\xe8=gHS+NB#\"\xf4\xeb\x1c\x8d4U\x98\x1a\x0b\xfci\xb0\xc0\x81\xb7[j\xb1 7O ~eX \xc3\x98-X\x907aA\xca^c\xd1\xf3b\x81\x0d\xcb\xd5\x96\xa5So\x19\xfb\xa6\x89F]\xed\n-\xa5#\xca+$\x84d^r\x14d\x8e<\x00\x90Kq\xf5;\xe8+$\x1b\x9e\xc3\x11\x16\x81\x8a\x87\x98\xb7\xf2\x14\xf7\xeb!\xa7\xfa\xaf2\xa9\x97\xfeT:'kT\xca\xc9\xdae\xc1\xcc\xf6\x85\x8d+7\x17ww.\xdc\xdc\xdc\xd8\xdc\xdd\x9c\x90oY\xfb\x95e3\xb1-\x9f\x9f\x9e\xd1L\xca\xb3v+\x1dF\xfbe\x84\x17\xa8Q\xda;\xfbx\xc4P6\xb6V\xaf\xad<\xefH(B'&Op?\x89F\x17\xb7;BW&\xa5\x80\x90\x0c\xc4\x80\x8b\x1c\xc1-x8CV\xbe\xe4\xc4\x1d\x1c\xf8n\xd4%\x1ef\xc9\xe16\xbf\xdd\x9e6\xe3\xba\x96\x0dP\xbaN\xdee8\xb0U\xff\xe4,\xaf\xcf\xd6\xe46H$t\xae\x06\nIe\x159i\xc1 \x17T*\x939\xcfjl\x0c\x95T\xab2\xc7H\xe9\xa5\x1d\xbf#W,\x92[\x1c\xda\xcdG\x85\xa9\xac\x94\xdf\xd4\x9a\x97\x87\x95\xc2}\x8aq\xca\x93.\x86\xa9\xb9R\xebFC\xfca`\xaf\xab\x19\x96u\x9aLm|\xdb\xccET\x0e\xbbL\xd5ot\x9f.xe^?*H3\xb7P\xce\xa6\n\x8f\x93\xf5\xb2\xc8)?\xdaS\xf7Ls\xa7S\x1e\x96\xda\xba\x1b]\x98j[\x7f\x98\x98\x11B\x066\xc3y,\xa1\xb7\x10\xad\xa6?\x8a77\xc4\x9f\xf3/\xe6D\x86\x92Q\xdb\xcfaX\x97,\xd9\xa9\xf1u2\xe7\x10\xde\xeb!o\xfd\n\xaa\x17u \xcfH\x95\x14$z]$\xd6T\x96\xc6\x81\x15\x96\x88\xd7\xb9\xd1-\xe7\x05\xac[\xaa\xb5\x8d\xf3\x1b\xbb;/f\x81,\xc4hf\xdf\xcf\x86\x97\xf2\x0c\xaeG\xa6\xc8\xa8h\xc9\xe4\xd5\xf8\x8c+\x9f\x81\xc0\xb2\xda\x10^\x0b\x9a\xd5\x98N,\xb8\x96L^\xc0\xa5\x8d\xf5s\xab\xe7w\xb7V$/z\xde\x85l\x1a \x18\x16,\xdcG\x8d\xea\xb7+\xc0t\xc1\xf6\xb8\x04\x83\x94s\xf2\xd3E\xb3x\x90\xd4\xad\xfaO\xaf`\xa9\xe7\xa2d\x0bLY\xe0\xbe\xa4\xd2\x0f\x94\x98\xee\xd9\xc3ug\xc4S\\q'2}H\x90`\xd5a\xa9\x9a\xe5\xb8i\xdbS\xde\x0e\xdb'\x89t\x15)\x08\x95\xa1 o\xc3),D9J\xb4z\xbe8\xe2\xafDV\x1a\xab\x04B\xf5\xc7\x8a\x9a\x05\xcb\x967\xcb\xe2\x01\x19\x82\xec\x90Z\xe5\xe8\x08enr\x1f\x8a\xbc#\xd9\xa9\x83p\xa6v/'\xf7\\\xd3\xf1tb\x0b\xd2\xa2l\x0f \xb4\x8d\xec\xe4\x80\xecT\xfb\xcaQh\xe4\xa05?\xcd\x88\x90\xc5\xca\x96\x8b\xe7\x16\xb4\x18\x12\xb6\xa2\xa9\x84-fD\xaa:\x81\x8b)\x9c\xae\x17\xbaXIYt\xac\xe2c\xb9T.\xc9T\xd2\x95/%\x86\xe0\x1b\x9b\xa7\xc3vn#\xb9]\x9c\x17\x91\x92\x12\xeb\xe1o$\xa7S#@H\x11\x80\xce\xcb\x8d\xc24\n\xf8\xcc\xbe\x93\x84\xed\xd6\x95\xc5\xad\xf5\xd5\xf5\xf3\x0b\xcc>2?e\x1e\x8f\x13\xee:\xe00\xeb\xb1}?\x08X\x8f\xeb0\x1e\xed\x91\x19\xf2\x83\x8c\x8d\x9c[Q\xc2\xc6\\g\x9aB7\xe2;\xd3\x04\xbb\x11\xe7\x99\xce`,I\x98?\xa1W\x1b\x8f\xc1\xbf\xca\x9b\x039PF\xa9\xba(\xd7\x95T\xd0\xbc\x97^b\xed6\xbcp\xa1$\xe3(\xe6i\xab\xd3\x99\xd9\xe3_h%\x99\xf4~v\xa30s\xfc0U\x17N\xb2\x87T\x8bI\xdc\"w\xeb\xdf]\xe5\xc1\x98+I(\x08\xa2}\xeem\xc3\xa8\xba,\xed\xa8\xe46\x99\x84\xfb]f9\xe9\xba\x1d\x1f\x9e\n\x95\xb9\xcd\xec\xf4\xc0\xaf\xa3\x07\xddI\xa2B\xfdbh|u\x92\x81\xbc\x08L\x0b\x07\xb79V\xcd\x15f\x8a\\\x9f\xbb\xc1^\xab\xfes\xa1\xe9TMEtT\xa16\x18\xfa\n\xaec\xe7~e\xc6\xa3\xfa\xecL\x9f\x84\xdc\x1c\xf14\x1a\xf1)\xc5fSG \x1e/\xe1\x9b\x9f\xa4Y\xbb\x06G\xac\xb2t\xd3.V\xe4\xbf\xc9\xfc}\x82da3rh\xa2\x84\xb8 \x92D_$\x13\xa9\xeeg1\xa6\x06\xe2\x0b\x9b:\xe3\xa7\xe2?\x10\x1b|\xe4H\xa6\x8c\x95\xcf\xbd\xcf*\x97#2\x9b\xf2\xce\xcc\xc8\x89\xa7h\xa5\xd4\xd2\x91#!\xec\x7f\xddv\x1b\xaf\xd1#s\xb6\xad\xd7\x87\x0b\x99W\x19E\x84\x8a\xa2\xf0\xa5\x11A+F\xe5]\xff\x16\xfbFhD\xfc\x80\xbb\xb9\xf4,\xb0j!]\x95\xe5f\xfe\x94E\xd7\x90\xd6\xceH2\x88\xa4\xaa($\xcd\x8aB5^\xb8\"\xe1\x17\xe3\x99R/\xad\xa0\xb7]\xcd\xcf\x9a\x04)|\x9aj\x9f\x83\x89\x94\x1a\\\xe7\x8e\xe8\xa8\x0c\xd6\xd90\xaayr,\x97%\xa6x\xc1M,C\x968\x0d\xcf\xc9\xd6\x1f\x95\xe2\x80/(\x03\x90>\xeeb\x9f\xaa_\xd4\x89\xae\x97\x1eJ\xd4\x7f\x81%5*\x88\xdc~+hb\xfb\xe5W\xdd\xca\x1d\xe0VMS\xf6s_K\xc8x\x1b[\xa9\xac\x0d\x80\x93_\xcd\x1by\xb0\xa3\x0b\xcc\xb1\x83K\x0f\xde\xd4\xd8(\xcb\xaf\xe6X^\xbf\x95rJ\x1d-\xfa\x86P\x89/\xe3\xf1\xd2\x0f\xebnB\xd3\xa1\x94\xd8Vn\xe7N\xf0}~\x08(\x86\xbe\xd1\xf5\xaa[*j?\x917G\xdf\x80\x15\xa4#K\xdba\xfb$y\xe7:2>\x16\x13\xfd\x8dj\x05I>\xd3\xb7\x10\x16{\x82\x02\xf1\xf3\xa2\xfd0\x98\xd2\x1d\x89Y\xc8emj\n\xfd+\xf4D\x9e$\xea\x02\xb9Y]aZQ\x9at\x8d\x8c\x7f\x8e\xa94u?\x10\xf8Tp\xfb\xc95\x02I\x9f\xfb\xa0\xc4v\xcc\xddv6\x93 ~'\xf4\x8a< \xda\x9d\"\x93\xbf.\xb6\x9b\x04u6\n\xfdk\x1e\xbbL\x14#8\xac\xea\xa2[7\xc6\x00\xfe ,\xdc\x0d\xb8\x934\xbc\x8d\xa1\x7f\xcf\x83dB\xfe\x0f\xa6h3O\x82\x05[\x9e\x16\xfc\x13\x03\xde\x96^\xd1G\x1a\x1e<\xd4?\xf5 \xe9j\x98\xf1\xc4\xe5q\x16%\x0b2=\x0f\xfe*\x96j:\xf9\xb5\xfc#w\x8du\xbf\x1a\xef\xee\xf2/\xe1i\x1c\x85)'C%\x9f\x7f\xfbcu\x13\xee\xf10\xf3\x9d ]`\xad\xd4\x19qEg\x1b\xe2\xe0\xf4O\x91\xb7&\xa7\xf6\xf2OP\xc98[\xa8\xbe\xe2y+\x8d\xc2\xee\x1f\x1c\xff\x83\xc9\xe4\xad\xf9\x94\xdc\xed\xccdC\x1e\xb6\xfb]\xd6o\xb8$\xb0Bj\x96\xc9r\xc8\xa6\xd5\x8c\xb4@x\x1d\xa2\x1d\xcc\xd1\xec\xb2V\x11*\xa4i\x8a\xf9\x08zG\xab\xe1\x0d\xf4\xaa\x1553&Nx\\N\xdf\x01r\x95\x11G\xfcg\x01\xc4p)\x90Ws h\xdf\xa8\x92\x1d6\xebLdT\xd9a,\xa8\x85\x90\xb5n\xc2\x02\xddT\x93\xbb B\xf8\x04\xbcQ\xae#\xb6\x04n\xfaW\xb3I\xe4\xab\xcd\xff\xb9V\xb7\x0d\xaa\xdbh7\xe3N\xb7\xb9\xc6)\xa2\xce\x8c_\xfe\xddm\xb2\x0c\x97\x7fU+qe\xb8pc@\xcc\xd4\xfag\xbb\xd9\xb0\xda5i\xe7\xd3\x04\xd8L\x8a[113\x8d\xd9!u\x10N3v\xd5\xa3\xd5B\xb3\x0d\xd8\xf6S\xb3\xb6\xbc.g<\x98 \xd1)]\xf0nQD\xe6;m&=\xf5\x98\xdc`\xed,\xa2\x88j\x1e\xa0\xa2\x9b\xfa-\xfb\xbf\x90\xb5k\x82\xe7O\xf5\xab \xca\x99\x9f:&\xe7\xab\xf2 \xfa\xed\xda\xe5\xbe\xace\xf3\x85\x9e\xa4\x1a\xf32\xab\xe2M\xdf\x8e7\xf6\xba\xea\xdai\xbaH\xb9t\xe6EG\xca}\xe9x6j7u\xdba\xfb\xf4 \x12\x9c\xa6\xee\xa8N\x9c\xb0\\R\xc9\x00NZ\xc5Q\xa0\x93\xb3\xb3\xb6P\x04\x00\x11\x0bm\xaa\xc6pr\xb6\xe6\xecXB\xb9\xfe\xe9\xc5\xb3}\xcd\x01\x18c\x95T\xb2\xda\xc8\x80gk\x91\xeb\x04 `-4\x9b\x03\xb5\xf7\x834K\xc4N\x92\xf2\xab\xceHU\xed\xb4\x0bi\xa9q,\xbf}bf\xec\xd8g\x0fw\x130Tk\xfb>|op6\x85\xf3S\xb9v\xc0U'^w7_\xa2\x96\x169\x9b\xe9\x87`C\xef`E\xb9\xee\"^O\xe9\xb9\\#\xac\x06*}\x99[\xb9*\xa0\xf2\xb7<\xb7\xe6\x9cFh9\xda\\)\x1f~\x97\xf96\x03\xbf9\x0d~\xfd\x1dIh5\xe2\x87U#>{\x8d\xb5\xa3&\xfb\xbdR!:\x02w\x9f\xab\xd8n\x12\xb4[\xe2CU\x89\x08KV\xfd\xc2\xa8?\x93'\x81@2x\x81]HH\x99\x8a\x84#\xe7%\x04\x03\x89ED\xfd\x06\x9f\x9f2\xe6\x0fx6%\xa6q\x15\x0d\x83\xdf\xdf\x94\xf6\xfc\x05\x19J\xf8\x0d\x9d\xa5v\xef\xe8*\xe1q\xde\xf6\xda\x9f\xf4\xf0\xf0\xbf\xbc\x87\x07e\xb0u\xb1~\x82U\xdb\xef>e\x00\x91\x8e\xad+\xc5sE]\x96\xce\xecn./\xee\xac\xdc\x84\xd8\x86\xed A\x0df\xef\xe0\xb9\xf1j\xb4J\xa1\x04\xd0P\n\xdc\xeb\xce\xc6\xf9\xf3k\xd3\xf6\xfa\\1)8U\x89\x19\xb2\x8a\x05;\x82\x02=\xa2o\xc2=\xf7\xf3\xc9\xd3\xd7\x0d[\xb5\xd9\x1f\xa6\x91\xad\xa7\x90o+ \x16\xea\x8b1e-\xe0\xf8\x15\x8d\xe7\xd09\x9f\xfb\xbe\x91C&\x1b\x95c\xb4[xtNa\xb2f%\x84\xda\xf7C/\xda/.3\x86NZ\x93\x00\x0d\xff\xb2\x99\xc09\x8c\xf2L\xc7uKJ\xbe\xccy\xbc\xe6\x87{\x17\x9ct8\xcd\xfd\xd2\x04\x1b]-\xf4K\x98|\xc4\xae\x9a\xfc\xb6\xb5\x1b[\xf2\xcc\x99\x90\x06\xc4$\x1d\xdaq\x06\x0b\x85\xbb\x10\x1dJ\xe5\xcb\xdd\"\xd1\xacEUq\xa4\x9a`UU\x00\xf4\xb2-|\x07@\xdf\xb1+\x17\xce\xd7'W\xff\xf6 \x89\xbc\xcc\xd8v\x93(\x08v\xc0\xf5.U\xffPw\xe0\xf2[\xc2\x1d\xefp'\x82r\x8a\xb8\"\x1c\xae\xd45!X\xcd\x0e\x8f\xfd\xda\xb8\xf6\xbe5\xf2\n\x0c-'g\xb1\x97d\xaej\x9c>AR\xa34\x86\xb6c\xde(\xdf\xa0l\x07V\xac\xe8\x7f}X\xc1\xd4*\xc5\xe5e\x9cH/\x0b\xc67\xc9\xcf\x06\x9c5\x81&5\xc4\xbdLKp+\xef\xf8c\x0f{\xd8h-\xafU\xde\xc2\xcfT\xee\xe3\x08r\x1f\x17\x9e\xf6y\x8d\x99\x1e\xb2*V\xa9y\xd4\xe9\xb2\xb0\xdd\x91\x8f0\nT\xf4\xc3Ag\x8aG`\xc5\xfeG\x13#D\\Yj\xae\xe1\xd6 0O@k\xa14\x10Bi \x84\xd2\xa0\xa1\x9eV\xa6\x13!\xef\x8b\xe3#+\x9fK\xa2\xd1j\xba=\x8c\xf6\xc3\xef\xf3C\x89\x88u\x0d\xc8\xdca}\xf4:ls\x7f1\x8d&\xeeO\x8e\xa5\xf1\xd8\x19\x16O\\\xa9\xa1,\xd5\xb4Rr\xc0n\xa7\xac\x9e:B\xcc\x12\x93\xef\xc8\xa4\xa2\xf5u\xe7\xe5\x9d\x8cyX\xf65\\\xbb-\xe3\xd0\xe1\xcaA\xd3\xa4M'\x83v\xd9Q\xe6Iw\x16\xf1\xd7P\xaaTs\xd5\xf6^z\xe9\xb9\x1b\xac\x8b\x84\x98\xea.\xbe\xaa\x07N\xff\xb2Z\x95hT7\xc4\xc3\xf4\xb7\xf9j\xa4\xd6\xd8\xca\x8a\x8b( \x107\xa1\xcd\x9bYTs\xfdd\xae\x9dp\x1eIE\x06\xafs\xfaTW\xe3T\x86\xb5\x0cf\xaa95[GX\x85RV\xe4\xb2z\x0c\x9f\x92`2\x85\xe6`z)\xa8p\xa7J\x9f$\xbbh\xc2\x8f\xb1\xc9\x06\x04\x0f\x90\xcc5\x1c\x8d\xd6\x11\xf08\x13\xc4\x8c\xe9\xcc\xf9\x91\xa9\xd8\xe9J\xc4o*\xd1L4|\x9c\xf9w\xfah\x12\xfd\xd3'\x9e\xebwhT\xba\xdd\xf6\xf1\x9b\xc7\x07]\xd6b\xad >\x1c\x13(\x94#\xe9\xa8o\xe8\xa6\xa0\xa2\xbb%\xaa\xda\xf6\x1b\xe6\x18J\xfe\xdav\xba\xf0\xdc@h\x8eP\xdby!\xe7rl\x95\x9f&2\xf3\xa9,l\xac\xe2\xf7\x8b\xd0S\xe0\x9f\x96\xeb\x043\xa9Y\x03\xd7xi\xf9i;\x01\xfd;0Z:\xef\x80\xe1:D\x1a\x0c\x92\x11%g\xc7e*\x92\xa5-t\xacq\xddF5\xb2\xe8\x8b[\xb9f!A\xca\xbd`&\xec\x87\xc5Zn:\x89\x98/\x17\x92\x8cY9u\xd7-\x0b\xc8G\x1eg\xb2\xa8\x96\xac\xff\xd68\xc4@\xae(\x96\xf7\xa7\xb1\xd7O\xc3%d\xbb\x8aWP\x87\x1340\xbb\xe5\xa9\xda\x8d=\x9e\x01m\xc4\x94f\x04M\xf0\x8d\x97\xaf\xfeC\xe1U3\xe5\x97\x84|\x14\xe7\x19\xf7\xb6\xb3\xc3@\xe6#\xae\xad \xd6\xb4\xe5\xf4\xd2(\xc83\x95S;\x99\x89\xa3T\xc6\xea\xd4W\x93\xf1\xf7\xec5v\xbc\xed\xe4Y\xf4#X\xc7\x1f\x0d}\xcf\xe3a\xe78[\xa8\x02:\xc7\xeb\x99O\xab\xef\x1fp\x0f\xf7\\\xbc\x90f\xafidx\x99^\xf0U\xf9\x1fG\xf0\xe0b\x91^\xad\xa7\xd221\xbdm\xa5\x9cN\x97\xb5\x8f\xc8wTZi\xe6d\xbe\x0b\xae\xd3\xe5\x81\xbd\xf4\x12\xf3eZ\xe0v2\x13\x8dy\xd2\x0f\xa2}v\x94\x15\xff\xb8Z\xf9\xd7\x1b\x9d\xc2\xdd\xde>\x17=\xd3IX\x88\x14\xc5 \x960\xc0\xf3\xdaT\xa9\x93\x8d_\x88\x96-\xb0\x86D\xe7\xba\xec\x02\xab\x89q\x13\xbf\xcaQ^`\x83\x06,.\xb3\x9f\x056\xae/I\xa4\xae\x056\xb4\x13\x1f{\x1b\xa5{\xe9\xfa\x95\xa8r\xa6i\x1d\xbf\x18\xc3\x9e\xccM\xef$\xf5UZ\xac\xed\x01\xb4_\xd4{\xa44\x8b&\xa9\x1e^;\xf1\xbb,\xb7SgDX\xb2\xa1\x9fvY\x9d]\xd5\x08\xc1\xa9\xd5\x90\xed\x1aCv\xda\xe9J\xeb\xed\xec\xab\xac\x0f\x8f\xf8\xf5\x8f\x1e\xed0\xf7z\xbfj\xc8\xee7\xbf\x16/\xd8\x9cO3\xa7\xc2 \xe5\xbb\x83\xc1\xcc\xcd\x9b\xd2\xb9\xec\xe6M\xed\x12]\xf2)\x0f:\x1d\xe9a\xa6L\xe2\xbc\xcb\xae\x8b\xba&\xc9\xb2\xdb\xe9\xc8\xf0\x99(\\\x8b\x1co\xa2\xfdL\xff4\x07\xf6g\xe2$\x8a\xd3\"\x93\xc2L\x16\xc1\xc1j\xca5\xc0\x14\x17F\x92G8\x939\x83\xae|\x04U}]\xf5\x1a8*\xbe2\xadH\xb0\x82?\xd4\xe9\xc4p\xc3\x10\x12G\x02{V\"J\x96K\xe6\xe9\xbc\xb4\xd2\xf06<\x92I\x82.\xaby\xf6hO\x88=\xad\x84\x87\x1eOj\xcc\xa6\x8a\xdaL\xbc]a\xc5\xa0Rdq0Q\xaai\xec\x84\x84\x9c\xd1F\xfa\x0b\xf0\x9c\x04\xe0Cm\xe1\xbb\xdd\xda\x9e\xb8z\x90B\"F\x1d?\xa7\xab|\xa3\xd3E)\x19\xee\xb6\x8b.\xcc\x15\xf37\xda\x87\xe7\x1bG\xfaCi\x176\xff\xfc\x1d\xd9/\xfd~G\xf6\xbf8\xd9\xb7\xe8\x85\x9a\x13d\xce\xe0\x0b\xd3\xec\xf0w4\xfbw4\xfb\xab\xa6\xd9\xcf\xe7\x1ag!?\xb5It\xa28='\x13\xb2=\x87\xe3R10\xc4Kt\xba\xaf\x93\xb3\xa7-L\xe3E\xe5\xfb\xfa\xe6\xeeG\xa3\xb7(\xc9{gy/\xa5TA\xbe\xd5~\x86\x85&`\x13\x87\x0f\xfc\x97\x85\xa1\x93\xcc\xd4l\x8a`\xa8)\xed\x19\xcc\x04\xeaB$\xf9tlD\xff\xa6\xf5\x1e\xc2?U/\x91\x0f\xc0w\x1b\xbc7'\xb6f7\x9a\x19h\xb3\n\x03\x13\xbf\x98F!\x9e\xfc\x146L\xf6%\xe6os\xe3jwf\xa2P\x90\xdc\x80g\x96G!m?\xb3\x8c/\xbd\xc4Zz\x10\xe5@\xcdP^\xec\xa6<\xdb\xf1G<\xca\xa5\xbb3<\xb8\x7f\x86\x1d\x99\xeb|\x95+_\x0b\xad1s\x92\xaf\xd3\xd2Y9\x15\xeb\xa1/\xefF\xf9\xbd\xc6\x96\xe7d\xce\x82?r\x06\xfcx:\x1e\x1c=\x18\x05\xaf\xf6\x9c\x94\xbf|\xb2\xbbya}\xfe\xda\xe1\xd9\x13\xce\x95\xadYgy\xd6\xbftkq\xdf\xbd0\xf0W\x97\xceF\xd7\xae\x04\xa1s\xe1\xf5\xd3\xab\xb7V\xf7/]8{r\xd5_\x1c\xf0\xf3si/\xbctzu4\x9c\xf5.,\xbe\xbcvx\xfa\x84w\xc2\xcd\xbd;\x97\xf2\xde\x89\x8b\xe1\xda\x9d\xd5\xfdK\xcb\x8bc\xf7\xc4\xb5p\xd5?;\xef\\\xb9|\xe2\xf5\xd1\xe9\x93\x9b\xdb\xab\xfb\xab\xcb\x8b\x83K;\x8b\xfb\xab\xcb+\xfb\x97\x96V\x07\xee\x85\x8b\x81;\x7f\xf9\xd0\x1b]>\xeb\x9e8\x1b\\=\xb1\xb5}\xf5\x8d\xad\xb8wg\xd6\xe7+s\xf1\xb5s\xc1\xbas\xe5u\x7f\xf5\xfczz\xf5\x8d\xf5;\x9b\xdb\x17\xd3k\x17.e\xee\xe8t\xda;\x1f\xe4\xd7\x0eW\x07\xee\x89\xadS\xbd\xf3\xbb\xa7WG\x17\x87W\xe7\xb3\xd0\x1d\x9d\x9e\xeb\x8d^\xcf\x9c+s\xc3k\xf3\xbb/\xaf\x9e?5\xee\x8dv\xbf\xb3z\xbe\nw\xcf\x9f\xbe\xe3\x88\xbe\xe6O\xbe\xbcz>\xc8\xc5\xdfW\xaf\xec\x0f\x9c+\xa7b\xef|0\xec-\xa7\x83\xab\xa3s\xb7\x9cy\xef\xb0w\xe2r~mi\xee\xf0\xda\x1bg\x83\xabo\xbc^W\xde\xdf\xbcup\xcby\xe3\xe2\xad\xde\xf9\xdd\xc1\xd5\x13\x83\xd3\xab\xb7v\xf7W\xfd\xb3\xb7\xf8\xce\xac\xbf\xbe\xb3\xe8\xaf\x9e\xbf\x16\xf7\xce\xef\x9f^\x1d\xc91\xf9\xab\xe7O\x85kW\xce\xcdz\x17V3\xf7\xc4\xd6ao>\x0b6\xb7/~\x87\xcf\xaf\x8f{\xa3k\xf1\xb5\xc3S\xb7z\xf3\x07c7\x9c;\xbd\xea\x9f\xcd\xaf\x1d\xce\x0d\xbd\x0b[\x87ko\xac\xcf\xba\xa3\xd3\xc9\xb5\xed9\xb3o\xfcDv\xab7\x7fj\xe4\\qso>\xd8\xf3\xce\x0fO\xf7\xb7W\x07\xbd\x91\x9b]}ck\xd6\xf5\xe7\x0eQ\xdb\x87W\xafl\xc5\xde\x1b\xeb\xb8\xdc\x1d\xef\xc2\xc5\xb13\xbf\x9b];\x7f\xee\x8es\xfe\xdc\xa1;:w\n\xd5\xdd\xbb\xfa\xc6zt\xf5\x8d\x8b\x87W\xdf\x08d\xfdb\xfc\xab\xb7\xd6wv\xe7\xc4\xffV\xfd\xb3\xa6-\x18\x93X\x93\x15\xb1&\x87\x9b\xdb\xabw\xd6K\xf5\xd6\xael\x0d\xdd\xf9\xe1\xd0\x0d/\x0e\xc5z]\xda\xb9:\xbbvk\xef\xce\xa5;W\x0f\xd6\x97/\x1d\\\xba\xf3\xfa\xfc\xfa\xf2\xca\xdc\xea\xf2\xee\xfc\xda\xad\xbd\x13\xebw\x06'.\xed\xbc~g\xfd\xce\xe0\xf0\xd2\xce\xa5\x93\xab\xb7N\xber\xf5\xca\xa9\xb8w\xe5\xdc\xec\xb5\xcb[\x87W\xaf\x9c\xbasmt\xfa\xb0\xb7}V\xae\x99s\xe5\xe2\x9cw\xfe\xf2\xc6\xd5+sb\x8dg\xdd\xd1\xb9\xdc\x9d\xbf6vG\xb3\xfe\xea\x85\xadS\xae\xc0\xa1\xf0\xe2\xd8;\x7fn\xf6\xda\xf6\xea\xe0\xea\xfc\xb9\xf4\xea\xec\xdc\xf8\x9a\xc4\xad\x83\xb87\xbau\xf9|\x90]{\xe3\xd2\xe9\xd5[\x8b\xdf\xb9\xb4\xbd:\xb8v\xe1\xb2\x98\xf3\x81{\xb8:\xb8:\xba\x1c:WN\x9e^\xbdu\xf6\x8eX\x0b\xc0\xab\xade\x81g\xde\xf2\xac\xef\\9\xb5w\xed\xca\xb5\xb87\n\xc4X\x8en.\x9d\x1e\xf6F\x81\xd8\x9f\xe0\xf2\x85\x8b\xc3^\xb8>\xea\x9d\xb8\x98m\xde\xda\x1f_\x9d\x0f\x0e\xaf\xce\x1f\x04\xe2oq\xe66\x07\xd1\x99\xd67D\"X\x8a\x82\xc0\x89Sx\xbab\xcd\x0f\xf7\xe4\x1f\xe0\xcb#\xff\\\x0d\xe3\x1c\xfe\xda\xe1\x07\xd9b\xc2!\x0d\xea\xd9<\xcb\"\xe0\x16[\xd2KX6\xa5\xfe+\xb3}\xcb\xb7{\xeb\x82\x11\xa5\xff51Ch\xcf\xecW\xac\xafS\xf6mF\x10G7f3i\xf4mF\x90T\x01H\xef\x81\x02\x10#\x88\xab\x00\x15#\x88\xf4\x13\xb7\x9b\xbf\xbf&\x87m\xdaqLx\xbd\xb10p\xab\x85!3\x16\x06\xae^L\x98}\x95\x85\xec\xbb\x8c\xbf\xca\xc2\xa3G;L\xc5\x0d\x17\x16\x86\x10\xa9\xe1jb\xd9tI\xa3U\xe9#G\xd0\xac:3\xb7\"?l\xb7X\xab3\x93%\xfe\xa8\x8dEg&\xb5\xfc2f\xd5wd\x96#\x9b\x14\nLl \x99R\xdbSb\x1c\xc9\xa8a\xa4|G\xdc\xe9(\x99\x05\x8a\x17\x12K]\xec+\x1aIPj\x0b\x9e\xdfE6\x85\xccj=\x98`9\x98\xd6j\xa0\x11\xa4\xd0\xd6\xebET\x95\x834\x0f\x82\xd4M\xb8\xed\x81)\xfd\x0bM\xc9\xfa2\x96\\q\xbc\xcb\xae\xb7\x8a\xf6e&\x9d<\x08j\xdf\x1e\x93\xc9\xec\x8cg\x8e[k\xf5\xe0 \x88B4\xaf\xad!\xed\x84\xd4J\xf7\x9d\xc1\x80'\xc7\\\x8dn2\xabN\xc8^c\xadcr(l\x81\xb5\xea\xbc\xc6\xa7\x1fG\x9b>3\xe97\x99e\xdc\xc0I\xd3u\xf9XZ\xdc\xf6g\xcc?+\xafj\x95\x7fw'\xbb>\xde\xe8Tb\xfd\xdb\xae\xc5\xceR\xa5\xde\x1e\xf1\x97\x1bE=?\xe0bI\xaa\xfb\x9c9\xbd\x80g\x0b\xacu\x0c\xfeB`\x8f\xa7{Y\x14\x0b\xb8\xfa\x13\x15\x08\x9cd \x9a=6\xf4JW\xb3\xafV\xe8A\xf0;J\x00\xbf\xdf\x1a%\x18\xfa^CV8\xa0\x01{\x9c\xc7K\x90\x8d\xb3\xa1=I\x0b\xf8\x0c\xa0\x93\xd0\x02\x01m\xba\xd2\x9bB\"\x88\xf8Sb\x05\xf1\xdb\x90DC\x0cE\x90\x8brw\xe2\xdf\xd0\xa2|\xabQ!\"k\x19\x94c-\xd9b\x8b< k\x86%\x93\xf1\xbe\xf4\x12;\x12NAe\xc0\xb6*C\xe8\x9b\xa9\xcc\xf5\x1a{\xb6\xe1\xd89\xf3C\xe65\xbb>z(\xedG;\xefL\xd2\xf6\xf5u\x83W\x1b\xec\xa4\x7f\xa2\x83\x1c\x1e\x0d2F\xdc)L :\xc8\xa9\xa85\xb1'\xa6z\x0b\xd8w\xd9\xdc4}0\x99\xd4Q\xbe\xe5\xd2\n\xa3\x90\x0b\x02=mT\xad\xa0\xea~\x98O\x91hob =\x84^\x10\xb9{0\x86\xae\xf9\xe8F\xc11\xf9(\xa5\xfc\xde\xd8\xd6\xf3\xda%t\x0cW\x8c\x0c%\xd7K\\\xc1\\\xca8u\x88=\x11\x97\xbf0\xa7J\xb3\xc3\xa0\xf6yl\xfd\xf3\xfc4\x0e\x9c\xc3\x05\xe9}\xacv\xd1\xf2nG\xf9\xd7`9+1\xc7\x9a\x14J/\x86\x19v\x8d\xc2\xf3;\xb6\xf3\xe2\xd8\xce$T\xf4\xfc\xb1\x1d\x0dK|jZ\xc9\xa9\xa8R\x16\xa1Z\xfb\x89\x13\xc7<\xa9u\xd2{!\xd8S\x1c\xc4vI\x85\xfe\x1d&}}\x98\xd4\x93\x8b\xfeU#\x93\xea\xe5+\xc5\xa5\x8e\xfe&\x98?\xcd\x91Y\x1af\xabF|.\x19t\xeaQp\xd2\x82f\xfc s\x12\xee\xb4*\xb7\xec2\xb5\x936\x1d}\xf1\xc6}\xd1\x02j\xb9r\x86\x8c\xa1j\xaa3Tw\xa1Ws\x80(\xdb\xd4\xe6\xab/z\xb0dV6(-\xc7b\xe9b\x08\x85lo\x81\xeb\xe8\xcc\xba\x17 \xd4jB\x00\xa7<02\x15&\xfc\xb5\xc0\xf8\xcc(\x0f2?\x96V\xa7\xeb\xad\x96\xf4\x0bo\x89S \xaf\xf6j\xb3\xac\xaa\xa3\x17Q\xa4\xedZ/~\xf5\xef\x1bC\x13\x9e_\xa9Q\x0f\x0d^\x16\x1d4\x14\x06\xedF\xafj}\xb9\xa4hte\x14g\x87\xb2\xdd\xfa\xe2\x91\x1e\xab\xdc\x17\xd8?\xf9<\x12{\xcd\xfe\xbd-\xb3u!\xc8\x17\x15\xfa\xc4\x81jt\x0f)Q\x16+\xf9\xab\xad\xa8\x17\xaa1\xab\xac\xc6\xb6\x86\xe5 \x97\x86N8\xe0\xc6?\x05\xfei-/P\x94\xbdV?\xdd(V\"n\xfdt\xd5\x80Z\xf6d\xd6w\xbb\xacu\xecX\xab\xa3DWA\xf6\xaaq\xca\xd3\x054|\x99\x012}R\x1a\xa2 Y1\x91m\x999\xb7)}\xfd\xddnQ\xe8\xb7\xc9\xc2\n|92\x87\xac\xfe\xd5\xa3T\xbd\xd7\xa8\xda\xab\x86\x93BM\xcb\xd4\x81\x9e\x99\n\x8a\x95\x9b\x9a\x18\xf2\xc9'\x91\x1a\x08\x9e\xd6m7\x93\x83p\n*\xe3K\xab\x02\x84\xd7+N3\x939\xc9\x80g3\x80Ei\x83\xf3\xb43\xe1\xa5\x1b\x01\x8f\xd8k\xcc\x9f\xce\xd0\xaf\x7f\xc6\xb7\x06\xe8\n\xb7\xfb\x91\xdd}\x9e\xe0~\xd3\xa4\xc4\xe7\x9a\xf6\x04=\xd4\x93\x97\xe5\xba\x103\x04\x81!\x13\x0f\xbbS\xd3l\x17\xdc\x1a\x12[\x88>\xc2\xff\xeaR\x8f\x85\xd0`.\xd8\x9a':A\xe8g\xbfe\xc1\x9f\x91\xb9\xb2\x17\xc2\xec\xd9d\x86\xcf\x9e\x83\xe9\xb3)\x88\xab\xf3e\xf4\x00\xe8 X`\xad0\x8ab\x1e\xf2\x84\x85Q\xc2\xfb\x9fCe\xd5e\xb0\xce\xb6\xd1\x8c\x98c\xf3\x04\x9d;\xf4\x03/\xe1\x96\x90\xeeIK\x0e\x9a\xbc}U'\x9a\x8d\x86\xdc\x1f\x0c\xe5c\x13ymR\x18\xf1\xebE\x89\xc7\x93\x05eUj\x10H\x9cd\xe0\x87\x0b\xac\xe1\xa1\x92\xd8\xf1\x95\xfa\xf2O\xc9\x04\xb0\x1ee\x8b\xa1?r2\xee} \xc9_\xdfN\x17'\xccO7\xc4Y\xf5\x1a\x84\xc2\xb1\x8e\x19,\x1fL\x85\xf0\x82\xb1\xd4\xe2v\x18\xa5n\xe2\xc7\x99\xbe\x00\x98@6\xef\xda\xce\xc1oO\xe5Q\xab=I\xdb\xd1\x0b8I\xdb\xa9'\x11\xac\xb41\xec5p:\x0e\x95\x8f1,\xfc\xc4\x9dI:F\xe3!\xe8by\xb3\xe3\xc5\x8b\xa6z\x15,\xa2\xa9\x1a\xc6\x82v\x00d\xec\x9b\xe1\xffK\x9dp\xbcZ'\x1c\xcf\xe6j\xe3\xeb*6\x1f\x1c\xcf\xe6j\x93+\x8057\xa2gs\xb5 \x14\x80\xe4\xecw\x15\xe0\xf4+\xa71\xa8\xaf@sd`\xb1\x86\xd8\xfdt\xbc\xaf\xc7OG\xffE\xb4\x91\xe7\xa5\xf5E\xfcQ\xd2\xb5\xa5 \xc1d\xbc\xd6\x8c5!\xee(\xa8\xc4\x1d\xb9\xe0\x15\xe4B\xdc\x91{\xf4h\x87\x05\xd7\xdd\xaaW\x90k\xb9\xe0SK)\xa8\x866\x99\xe5\x84\x11\x81\xdf\x19aF\x115\x9b\xd5\xc5\x1c\x052\xe6(\x99\x19\xf0\xecR\xe4\xf1@HO\x13E\xec\xd2\xf8\x94\x17?7^\xfc\xad\xdf;^z\x15\xfbxKf\x93+2\x87\xfd\xe1\xcc\x1f\xfc\xde\x0f\xca%~p\xfcx\x97\xb5\xa4\x05\xc0\xd6\x96k\xd2\xd8\x1eO\xdd!\x1f9\xa4\xc9\x9aB\xbaQ\xd0\xca\xc8\x14\xee\xaaIo\xf1\xfe\xb6\xac\xf2<\x93N\x14[\xab\xbc\xbf;\xd3\xf7C\xafx\xde\xdbf!\xb8\xdb\x85\x9c\x14\x84\xa1'\xc4 \xa5V8H\xad\xc2\x81\xf3<\xc2\xc1\xd7\xca\x18Uj!\xb9=\xcdJ:\x9f\x98\xff\x94)2\xca\xa7}\xf9\xd8\x81\xc2r\x83\xebK\xe5\xb2T\xc2o\xe7~\xd2\xc4\x99SY.l4\xd2\xb9\x8a\xcbo\xf1~}\xa1\xbe\x99\xc3f\xeds\xf9L\x11`>\xa3nz\x9b\x8d\x832\x8dd\xbb\x05\xecN\x9e\xe4V\x83\xb9b\x08\xa5%\x95\x9aXx\x0c\x857\x13\x7f\xe4g\xfe\x98O\xac0bgX+\x92#i\xd0\x1e\x06\x82\x04\xc2\xab\x902)\xd0\xef\xff~\xc2\xfbuna2 \xa9|\xccx\x00\xe1\x0f\x1a\x07\xcbt\xab=\x10\xb4\xec\x88S\x14sJ\xc5\xccIo\xa7P\xcc\xb8\xa3\x04\xb5\xd6\xdcI\xa1~\xe5[\xa2\x91\x18\x06\x93\xff\x7f,\xf3\xb3\x80\xd7Z<_`\x7f\xd0\xd3\xcd\x9b\x19?\xc8j\xfb\x8b\x05_\x10\xbc\xa8\xb6c\x7f4h\xec7M\xdc\x05\x16\xb6O\xce\xcd5!\x95V/\xe7g\xe3\x83\x86\x8d\xdf\xf7\xbdl8\xb9\xd8Du\x96\x19\x15t\x8d\xf7E\xbfs|4\xe9\xa5=\x95\xbcL\x92\xc2\xc0\x11\xd8<\xa1F/\xca\xb2h\xb4\xc0Zb\xb0\xb5%k\xe2_\xea\\G\x04\x15=\x94\x89\x1a\xfctcq\xfbD\xbbS:\x07\x1e\x8f\x13\xeeJ\xcd\xad\xa6z\xba\xef\xcbL\x84\xae1:J\xbe\xe9\n\xa5\x8c-\xb0#G\x06]y\x06\xcb\xa7+;\x8c9\xbc\x997j2\xf9\xb8N\xca\xcd\xd9]h\\\x99 \x87\xc7\xa3\xb6\xa1\xc6\xe6\x18Bo5\x86\xc6:\xcfelb*\xc0N\x90\xdc\x05\xd6@\x9d\xf5\xaf\xe0F\x8d\xf7)\xfa\x07\\\xa6\xf1\xa12\xfd\x0b\xe5\x14\xa7xL\xbf\xc0\x85\x05v8\xb9\xb8d;\x0b\xccm^\xb4\xa6\xcc\xb1\xb0\xff\x8e\xe0\x0b_n\xfb\x87_r\xfba\x08/v\xf7\xff\xf1m\xa8\x96I\xea\x1e\x8b\xd3\xbf)\xf6T\xbd\xf8X\xbf\xa9P,\xccG=\x9eL,\xe6\x87\x19\x1fLQ\xae\x17E\x01w\xc2\x86rZ\x03\xfc2\xc86\xfe\x92vh\xa6\x91C\xc9\xa9\x13\xef\x02\xd9\x7f\xe9\xd8d\x85O\x8c\xe7\xac\xb5\x0c\x95\xb0s(\xb7d\xe70\xe6\xd4,\xa4\xd7\xa8o\xf6YZ\xa2\xb9w\xc9\x89\xa5Lm\x93\xd0\xab\x1b\x17\x9b\xaaB\x97i\xae\xa46o\xca*\x15\x95\xa3\\\x0b8Um=\xd8\xcd\xa28\x1c\xc4j\x99\x92\x88?\xa9\xa8\xa2\xf1E!q\xc4\xaaE\x8a}n*\xc5\x0fbG(\xac\xb1`\x87EA \x00hx\xd3\x14*\xf1VS.\xf0\xd3\xf2\xc2\x14\xa8Q\x8d\xa6\x87L\xa5\xbf]\xfb\x9e\x18Q\xea\x08\xdd\xfd\x8e\x0c\x90\n\xa8\xc1/\xb7Y\xd6\x84\xe6\xda\xce\xc1J\xd6\x95EN\xce\x9d\xea\xd8\x8c\x7f\xb2\xd0\xec)\xab\xfdO\xc2\xe6N\xd8\x0dm\xf9\xd7kh36\xb0\x19\xc7\xf3.D\xd1^\xbb\xd5\xe3\xfd(\xe1\xdbjy\x14\xd9M\x1b\xd3:\x9a{\xe6a\xc2\xfb0\xcc\x94g\x8bY\x96\xf8\xbd<\xe3m!\x80\xb7\xba\xf6\xdb\xbfN\xb74LlzM\xa7q\x89;\xfe\x87\xd7\x17\x8f]\xfbA:{\xec\xf4\x91\xd7~0s\xe3\xe8\xef\x1f\x1f\xa8d\xc5Ug8\xba\xda\xf5i\x98\x8a\x85\xd1\x88\"\xf0\x94\xae\xf5\xe2\xf2\xf2\xcd\xc5\x9d\x9d\xad\x05v\xbd\x05\x97\xe8\xadj\x86P\x92\xda\x82\xd5\xe6c\xc2C).\x11\xd3(O\\\x8bE\x00\xee\x19\x1a\xfc\x89\xfcBm8s\x06\xee\x0eZ\xd2w\xbc*B\x08\x95;mgE\xd6\xe6\xa4N{\xac\xbb\x94\xach\xabN\xb2\xe7E\xfbaU\xa4\xbbK\x0d\xac\x10\xbbq\x86\x85|\xbf\xb0c\xd6\x08\x8f\xc3l\x14\x88clg}\xd9a\x1c\x0d\x12'\x1e\xf2\xa4\xbeP/\xe1\xce^Z\x0f\x0f\xfcp\xcf\xef\x1f6\x17\xd8\x91\x9b\xbc\xc0Z7{\x81\x13\xeeY\xd2\xa8w\xd4EK;\xb3(\xd0\xae\xcc\x12\x96\xa3\x850w\xff\xafI\x15\x05\xf8\x9fq\x8d\x91\xe3\x8aa\x7fJ\x86\xa6\x01\x04\xb1FN \xd6\xeb\xd9Gx\xd7\x17/m.\xb0\xd6K\xa4|l\xf9\xba\x18J\xccy\xfc\xe7\xb84|\xbf\xf7!\xfd\xae@\x8f\x7fNA\x00\xf8K\nH\x83H>)\xf1\xec\xf1_P\xe0X\x02\xfe\x1b\x02\x90\xb3\xbbGvDz\xa6\xb6\x9e=z\x9f\x02d\x94\xac\xb5\xca(\x85\xf9`,\x02\x90\xe3\xc8\x16?\xb2\x03{\x12\xf8\xd8\x0e\x94\x07\xf2\xd1\x13;P\xf6\xf9\xe8\xa9\x1d\x08\xb3\xf8\x1b;P\xe2\xfc\xa3\x7fm\x07\xca\x85y\xf4?\xda\x81\x12#\x1f\xfd\x1b\nL2\xb9\x02\xbf\xb2A\xc6r\x8e\x0f\x08]\x01\x18L\xe3\xaf(0\x05\xfc\xbfGhE8HEo\x9f\xfc\x84\x02\xee8\x89\xc0\xe7g\xff\xfc?`T\x8c\x06\xd2\xee\xfa)9\xd0\x1a\x80[[\x8c\xe2>\x1c\xf5\x7fO\xaa(\xc8\xcf\xff%\x86\x88S\xf0\xec\xfe=\xf2Y\x10>\x89\x88d\xe9bID\x1fcJ\xe6\x00F\xdf\x7f@\xbe\xfbr\xc1\xee?$\x80(]`\xado\xe3Y\xc4qpxN1#+\xa9s\xe28\x89\x0ej\xc6-@\xfc\xb6u$\x8b\x89\xf4\xac\xb2l\x83\x06|\x80k\xa4.\x10\xcf\x7fI\x0e\xb1\x81\xfco\xa4N\xea\x0f\xe4\xc0\xef\xff\x8cT\x12X\xf0\x07\xe4\xeb\xe1\xa8f\x17\x04DM\xe6\x9f\xe3n2?\xf0$\x8d&L\xd1@\xfe\x07\\'\x17\x02G\xeb\x13\x82Q\xea;!!\xfbn\x14\xfa!\x1c\x14\xcc2\x9d}\x05\xf9\x08S\xf5\x9e\xe3\xee\xb9\x11\xd0\xab\xfb\xefZ\x80Z\xcf\xee\xbdG\xa0\x89\xa4\xbaO1}\xef9\xc9\x98\xcb\xb1<\xc0\xfd\x9du\x92}.1\xfb]\xcc\xbb{\x05\x08\xa3\x1a\x80\x80dS`/\xd9\x13\x80?%\xf3\xee%{\x99\x06\x92%\xab]\xeb\xb3 s\x90\xfd\x81\xcf\x98\xe7\xf6\xbc\xdby$\x97\x1dK\n=\xee:y*W\x0e\x8f\xec\xac\x04q+\xac\xd7\x08\x1b\xc5\xd9\xa1\\\xf4G\x98\x92\xf4\x04~X\x91\x83'a\x94\x8b:oc>qV\x82\x82\xc0Ok\xc0\x99\x9430\xf9\xeb\xa9\xef\xff\x0b\xfd\x0e\xa2\x0c\x1dB\xb6\xcf9\x1co\xd2\x89\x96\xb4\xc8\xbej\x00f6=\x7f\xe0\x02\x05~\x88\x05O\x01\x02\xd1\xf3\xd9/0 \x16\xb0\x1c\xaa\xe1\xc3\xdf\xf3\x07\x91\x17\xc1\xb9\xc4\xb2\x93\x80\xc5\x01l\xe4GX~\x12\xc0\xcc\x1fq\x80ZF\x93\xdeV}~D\xd0\xdd\x1f\xa4\x99#\xb9\xc5_\x90\xa9\xfb\x83,\xf1\xa5,\"\xf4&Q\xe6=rr\x8b2\xd0\xc3{\x98\xd6\xf4\xfcAnF\x8e\xa9W\xcf\x1f\xa83\xfa\xd02)s\xda\x1e\x92\xe5\xd8s\x92h_\x80\xde\xc7\xd4\xa2\x178\xee^\x10\xdd\xe1J\xb8\xfa\x10\xcb,\xb2@z;w\x12 \x7f\x0f\x0b<\x12\xae'%K`5\xa1R\xc2,\x0d\x968*\xa5\x02\xb8\xb5}\xf6\x0b\xb2;\xe5R\x89\xbaT~\xf6\x1e\x96\x02\xa4\xae- \xff\x023\x86^\xb077/\xeb\x90\x03\x12\xec\xcd\x9d\x94\x10BE\x82\xbd\x13\x00\xc1\xc2\xb2LO !\x98\xa1\xf5B\xb1\x18g\x9e\xfd\x183\xda^\xc8o\xe7\xbe$\x07\xf7\xff\xda\x02^\x07\x94~\x8a%\xc0^\x08\x80w\xb1\xbau\xd6\xc8B\xff\x07\xaebd!2nh\xeb\x01\xe9]_i\xdb@\xfb\x99\x0f\xe8E\xe6\x1a\x1d\xf4@J\xf9\xf0>\x05-\xaf \xc8\xcf\x7fa\x81\x04\x12\x82YT/:\xf0\xa0\x0eV4\x04D\xd6\xf9\x19^\x04\xd1\xda\x96\xac\x83%\x11\x01\x91\x07\xd6\xb2\x08\x07\x1e\xd4!\xa8\x10\x1dx\xb2\xce\xcf\x08O\x8f\x0e.\xc8*\x96\x01H2\xfa3r\xf6\xa2\x83\x0b\xcb\xb2\nVo\x05D\xb2\xce\x9fciD4\x06u\xe8.\x1c\x0ce\x9d\x9fa\x92,Z\xdb\x95u\xb0\xbe\" \x92\x95\xfc\x9c\xf0\xfc\xe8`\x08u\xb0\x02$ \xb2\xce\xcf\xc8i\x8e\x0eF~\x08\x04\xea\x01\xa1\xf2\xd1\x81&^\x0f\x08k\x8d\x0e\x0c\xd5}\x80\x15\xb5^t\xb0\x0b{\x8e\x95\x0d\x01\x01<\xc1\x82i/:\xc8\xa1\xce\x7fk\x81\x00\x9e`\xa5S\xb4\x06{\x8e\xb5N\x01\x01<\xf9\xa5\xa55\xa8ci-\x07<\xb1`\xddeY\x85\xd0\x92\xe8@\x9e\xfd\x9f\x11\xca\x16\x1d\\\x06\xd4\xb2\xec\xece\x89[?'\xb49:\x18C\x1dB\x95\xa3\x831\xe0#V\xb6Dk\xb0j\x844F\x07\x97a\xa5\xb1V'Z\x83:XA\x11\x10Xi\x0b\x0e_\x86U\xb3\xec\xf5eXi\x0b\xfa\x8c\xa1\x8e\x05y\xc6\xb0\xd2\x04\x0b\xeae\xe8\xb3\xca\x98\xf6k\xb2o\xf5\x80qO\xb2\xf7\x8f\xf1a=\x0bZ\x10\x95\xb7zF=\xfa\xdf \x84\x8f\x84p\xf7\xec\xad?#\x90:\xc9>Us!R}/\x8d\xc4:\xff\xe0\x07\x96\xefR\x85\xff\x90\xc8#i\x14\x0c\xd3\\\x02\x7fEHv\x1e\xc8m{\x93lu\x1e@j1\x1bH)o\x7fj\x01HM\xf9 \xb6L\x08\x08\xe8\xcax \xce\xe6F\xdf\xb35\xa7@\xb8\xd6\x92\xb6E~\x8a%3\xd7@~J\xea\x80\xfc\x88\x89\xbc\x12G\xefar\xe9:\xb16ta\xf9\xcbu\xe2^\xa2d\xc3\xc7\x98\xd5\xb9N\xac\x9a|\x8c\xf5\x7f\x01R\xb5\xf0\xe8\\'VB\xecc\xcc9\x96\x9c\xd8\xcf\x9c`\xd9\xef\xf7y\xc2\xc3\xccw\x02\xc9\x14~\x82w\xdaubPY\x1e\xff\xe7\x7f\x8f\x1bq\x9d\x04\xb6\xf3-,1\xbaN\"\x15\xd3_\xd3\x05;\x0c\xf8!h\x17X\nqu_\x8f1\x82.\xe9\xf6>\xc5<\xd35\x10Z\x87{\xbe\xd4\xc7\xc9\xb2\x18\x08\xe6YKJW\xf8\x14\xa3\xb4\xab\x01xc\x96J\xaa=V\xc0\\7W\xf3\xa1\xa3\xce\xe34\x95\xc7\xf41f\xf6K\xb0e\x9fb\xb3\x8b\xab\xbe\x93\xfdW\x93\xf9\x18\xcb\xa9K\x02\x1086\x90[R\x1b\xb1\xce\xe6J\x7f\x86\xd6\xc7\xf8\x84.\xf10\xe3\xc9\xb2\x1c\xc4\xc7\x98\x1c\xb9\x12\xe8\xd9\x81K\xfd\xc4\xbe\xdfZ\x9f\xc3D|\xe9\x02\xa8\xd6x{\xdc\xa1\xfc\xfe\x0fdC\x87\x1c$\xe5\xbf\xc4b\x98\x84\x8c\x9c\xc4\x0e]\x1a\n\x12\xfa9\xedF\xaa\xcd\xa4\x17\xb0\xe4\xfd\x82l\x00\xa0\xc6\xaf \xd5\xf0\x13W\x91\x1a,\x9f\nP\xc0\x9d$\x89\xf6\xb56\xf2\xce\xffY_\xc6\xe8\"\xef\xfc_\xd6B\x1eX\xc4\x9e=\xc0\xb2\x8a\x02k\x0d\xf8\x01\x96K\x14\xdcS\x06\x9d\x07X>Z\x92\xf0e%\xd0c\xd9E\xd5\x16L\xf5cL\x9c\x15l[T\xfcs|\x9a\xa0\xd9KF\xd2\xc3B:\xc07\xb5\xb0\x87%u\x00\xef\x18y\xcf\xb2\xba\x92c|\x88\xb5z\xd7\x07=\xd3\xb6\x1f}}\x8c?\xc2\x07\xd2\xf5\x93\x11\xd8^\x9fb\x0b\x82\xeb'\xa9B\x8b\x0f\xb1\xcc\xb5$\xd4\xb7}?\xe5KQ\x98Ey\xb2\x1af|\x908\x923\xde\xc3\x87n)\x88R\xbe\x94'\xc1\xe1r\x94\xf7\x02\xfez\x1ee w\x90-1%\x8b2dc\x82\xbc'\x97\xe6\x97X\x0c\x93\x90\xdc\xcf\xac\xc0\xa5\x08\xac\x89\xcf\xee\x91\xe3\xad \x0b\xb6\x1ap\x03\x83Ey\xd7\x80\x88\xfd\x16@\xb7k`\xa3\x91 Y]\xdbw1\xec\xff\x8a\x02\x80\xd5\x12\x16\x14\x8d\xe2>L\x07Kb\xae|\x19a\xc4\x15\xdd\xb6\xd5\x0c\xf8\x01`\xd7\xdbx_\x8d\x99\x90p\xca(\x1chv\x8bI\xddR\x14\x0e\x92\\ux\x1f\x0b\xbaK\x05\x0f!\x18V\x80\xf0\x11\xb3\xe1\x15-#\xb5t\xdb,\xb4\xfaNw N\"\xb8\xd6\"\xacI\x82r7\xb3C76\xaf\nR@d\x9e(>\xac\xfb\x9e\x02g\xc0\xe7q)\xca\x05?i%\xa2e\xa6\x90\xec!\x99M\xee9I\"W\xe7}26 \x93\xeb\xf3>^\x1f7\xe7\xb1\x84<$s\xcdy*9\xc7C\xacM\xb9y\xa0\x97\x1b\xdbv\x01$\xa7\xf5>\xd6A\x96\x94\xbd\x95\xf0i\xf8~\x0f\xab\x9an.\x84b%\xf9\x126\x92\xc7J\xfe&\xd7:nn\xe4e\xc2\x96s#/\x13\x11+\xd7\xf2\xf2\x03K\x83\x11\\\xe4\x91c\xaf\x84\xbc{O,\x02rn\x90\x92\x90T \x92\"\xe0\xfbX\x8dv\x05y\xe7\xb7\xe3\x84\xbb5\xdb\"\xe1i\xee\xd6mN\x12\x1cjc.\xd6\x80$\xb00\xe7\x12\\\xcd\x93D\x1a\xe6?\xc6J\xb7\x9b'c$\xb3\xd0\xad\xd7E\n\x91\x85N\xbc~d\xea\xba\x87\x0e\xaa|\x83F\x04V}\x83v\x0f_\xc5\xb8\x87\x81\x9b \xda\xf3\xec]L\x90\x97e\xaep\x01z\x13Sc\xaf\x00a\xc1\xd4s\x02}\xa3\x81\x0f\xd8\xb2\xdeh\xd2\xdc\"\x00~\x8aq\xde\xd35(\x00\xc4\xb171QXv\xd2!\\\xb0\xe1\xbd\xf14\xe4\x01f\xea^\xc9>\x8f\x97\xd5\xeb\x05\xd2\xd3\xe0\xd7X\xc8X6Z\x15\xde#\xcf@pc\xcb \xb3cv\xe2\xc1g,\x1e,\xdb\xb5M\xf0\xf5\xf8 >\xb3\x9e\xd7\xb0]z\x1d\x7f\x8a\x8f\xf3\xf2r\x94%\x0e\x984\xdf\xc7\x94\xd7\xf3\xa2,\x05!\xe41FQ\x8f\x0b\x0e\xff1\xd6\xe7\x969p\x1e\xac\x18,\xf3\x00\xae\xbf\xc8\xdc5\x00\xcf\xde+\xe9_\x18i\xbd\xbe\x9f\xc2\xd1\xf9\x00\xbb\xe0,k\x85 \x8f\xc0\xd3\x00\xb28\x17\xe0B\xe9\x03l\xeb\xf5\x86\x0ep\x8a\x9fb!Y@`=\xb1\xcc\xb0\xec;n\xe2g\xbe\xeb\x04\x8bun[\xa52\xa06\xfc\x1a\x0b\xa7\x95\x12B\xd6\xd5mQ,,J\x9eW\x9eT?\xac/\xb2\xa3\xae\xeb\x7f\x8d\x8dx\x9e\xefH2\xfb\x10[\\\x96}g\x14\x815\x86\xc0\xbc\xc90#Gcs\x9e\x80\xa75\x10\xb9h\xd8 N\xad0\xe4\x00\xf8\x03\x07\x04\xe3\xdf\xe0U\xf2\xfc\xd4\x97b\xeeCL\x18=y\x13\xf4 \xc1n\x7f\xec\x83c\x83\x1d\x12\x85\xc6\x94\xfe\x90 \x9a?\x8e\xc2\x03+h\xf9\"\x9ct\x8c5\xde-P\xda\xb1\x1c\xe3\x05n\x94\xc8\x81\xbf\x8b\xf9\x9b\x17\xb8\x89|b\xe0\xd9\xbb\x98\x0f{Q\x10H\x94\xfe}\xdc\xbd\xb9\xa9\xc2:\xb2gD]\xacH*c\x06\xde\x0e\xaf\x06q\xa3Li\xc2?&(\x16eJ\x9f\xc1$[B\x94Pq\x1f\xd3\xa0\xe5([\xb9\x9d\x83>8+:f\x01S\x0c\xae\x01\xd8Z\xc1\xb5\x9d\xf4\xd9}\x8c\x1f+\xb0hX\x0d\xe5\xb0fX\xca\xe1\xcbJ\xd2 \xaa\xc9\x8a\xba\x05\xc2\x83\xd5Fz\"cpU\x01\x1fR8\x9f?\xc1R\x1c\xef\xeb\x860cZ\xd1:\x066\xc3p\x0d\xc07FR\x8bz\xf6\x04o\xc5\x8a \x8b -\x19\x08fy| \x89\xf7\x132\xedA\xaa\x8e\xca\x13l\xe4\x05e\xed \x96\xe2VJ\x86_\xd2\x7f\xe0\x87\x19OdW\x7f\x86 \x13\x87K\xed\xb71\x93\xe2\x01\x0c\x0d\xef8\x0f\xcc\xd0\xf0\xda\xaf\xe8\xe8\x0b\xbc\xc6\\\x03H'B_\x94c\xc6\x04IBR\xb8\x86%@\x99ky{\xe4\x04\xc1\xb6\x91\x08\x7f\x81\xe5\xe3B\x17\xb5\xd7\xbf\xcc\x13\xdc\xc6{\xd8Y\x84\x8fRI{\xdf\xc4\x9cS\x00\xe6NH\x10V\xa3$H\xba\xbe\xbdI\xfa]?\xbf\xc0Z\x9f\x91\x83'-\xef\x9f\xe1\x0b8\x1e\xaa\xce1G^\xd1.\xfe\x0474\x80`\x87\xd1\"\xb0M\x8e\x1b-\x82\xe0`\x0cT\xf4!\xc1\x80\xd8IR\xe0\n\xd8*\xc3\xb5\xf4\xfe\x18Sx\xe5\xb4\xfb9&\xd6+\xc6\xd9\xfbs\xda\x8f\x01\xe1Z\x02$\xb6\xf67\x04p[_\n\x12\xba\xc7o\xd7\x931~[y\x97\xdc\xc7k\xcdo\xa7\x81\x13f\x83,\xb1\x1fT\x00\x07<\xb5\x9f\x16\xa3\x07=\xa6#\xcd\x1dy\xc4\xce\xd8\xaah\xad\xdf6\xa0\x9c\xc3\xb5\xe8}\xcc\x92Vn\xe7~\xe0\xf7\x12?\x97s\xf9)\x16\x18JN\x946\x08\xd8\xae\x1ec\xa5\x81\xdf\x1e\x17\x1b\x8e\xa5h\xaeY\xe0\x07d\xc3\x13Mq\xf1\xa1_\xd1nA\xd8\x10\xc55\x00\xf3m\xaeI\x0e\xd1&W\xd4\xbe=\xc6\xd7&\xbcnCW\xc0tE\xf8\x06|&|i\xe7\x82\xa0\xdb\xb8[\xb0\x96~\x82'\xb0\xa2\"%\xc8IV\xdf y\xc9\x13\xe9R\xff'\xd8A\x8a\x1f\xb8\xa2\xc2\x11\xf2\xd9\x87\xad\xbf\x87\xe9\xd1\x8a\x80\xa4V\x10?\x88\xb9\x9b9:^\x86\xac\xfa\xca\x01${\xf0\x9d@^/S\xdeY\x14\xb03\xd7\xbe\x13\x04\xbe\xbc$T\x96G\xc2d\xcf\x81\x98\x80\xa5\xe6>\x88 \x98\x82\xf6\xf9Hu\xf5K|\xf3\xd0\xef\xfb\x10\xf8\xf8\x9f\xff\x06\xcf\xb3\xdf\xd7\x10Z)\xd0 \xdc\xd59\xcd\xe4\xb1\x9c\xd6\xd7\x00L\xe2\x8a\x01`5\xe2\x9c\x1f\x04\xdc\xc3l \x13\\(ec>X\xec\xea\xdf\x82\x9e\xfa\xb70 p\xc0B\x87\xc5\xaeb\x9e\x18\xeb\xfbA\x16J\xf4x\x0f\x9f\xd3~\x18 \x06\xf0\x9f\xc8\x96\x19\x96\x81\xf5\xb3\xbea\x19\xf8\x10\x9d\x8b\x92E\x10'\xee\x91=\x88\x12\xa7\x1e$\xfdX\x1eb\xc3\x87\x00\xc0\xbd\x00\xe6g\xe7\xa2<\xf1y\x92%p\x0bL\xe6\x14;I\xa6\xfd\x1e\xb0\x10\xdaO\x1cW\xba\xb3\x7fL&& \x92\xa9\xff\x04\xd3, \x12L\xfdc\xbc\x9f\x12rJV\xc2\xc4_\x82^\x96 <\x01 zE\x82\xb0\xe0.@\xf30\n\xb2 \x02\x04}aF$@\xd2\xe1\xfec\xac(I\x08T\xc2\xfb%A0\nl\xfa\x13\xa0\x93P\x0bK\x19\x02t\n\xa6\x85e` \x82\x06\xb1=W\x80\xbe\x03 l\x13\xe8'\x0e\xb0\x97\xb7\x08%HT\xe8\xc3\xbbX\x08?\xa7y\x05\xd9{\xa3\xfbb\x81p\xa0U\xaf\xff\x07\xf3\xe2\xf3\xca\x08\xfd9\xdevm\x9d\xfe\x1c\xb3\x17Y\xc3\x13\x12\x08^\xb8\x81\x81\xe0\x15\x18\xc0\xcd\xed\x13l\x970\xa2\xc9\x13L\xd6\x00$\xf9\xfb\x13L\x8e\x15\x0c\xe6\x8a\x91~\xc0S5Yz\xf3.`0\xc8'\x988\x9c\xd7\x1c\x0b\xab\x17\x03\x0d\xc0\xec\xf7\xbcTd\x1fb\xda4\x00? ,\xac\x0c\x065\xc5\xfd\x11l\xce\xdbXx:\xaf\xaeN0\xa7\x1e\xa8\xab\x13\x82qpc\x80\x9b\x19Hg\xcfgO\xc8\x1e\x83\xbc\xf2\x04s\xaeApK~\xc7\xd3\x1d\x84\xea\x00\x92\x05\n\x8b\x98a\x0b\x10\x10\x98\xec\xc5\x9ckud]\x96U}\xaf\x82\xcf\xb4\xaf\x01X\xc6\xf0G\x0eh^\xb6\xb6\x06~\xe8$\x87\xab\xf6\xd5\x199\x83@\x9d\xe8\xb71j\x0b`\xec@\xca$\xbaw#\x99\xc5\xb4\xf5)\xd6\xd4\xfd\x91\xb4<={\x80Y\xb8?\x8a\xa5\xc3\xec\x7f\xc2\xf8\xb4:\x8a\x03\x1f\xd4\x1f\xe2`\xe2\x87l\xc1v\xf9\xe5\x87\xae2\xb0\xbd\x8d\xafc\xcc\xde\xdd\xc3\x8a\xb7\x84\xa8\xd0\xfd\x0f\xb1\xbe\xec\x87*\x87\x06\x99\xd1\xaa\xc2\x12\x82q\xea;\xd9\x8d0s\x81\xc6<\xc0B\x9c\xca\x08\x0d\xb1\x1a\x98\x81V\x9c\x97,\x8d\xf2\xa4\xae\xd9Uy\x11\xc8M\xf6$\x92X\xc4\x0f\xb3\xc0I\x86\xd2 \xf7\x11\x16\xda\xfc0\xd3A\x14\x1fa!q5\x1c\xfb\xa9/\x1d\xac\xc0fb![\xba\x88\x89qz\x0bK\xe5\xab\x1b@I\xb0m\xd5\x8f@\xf4!X\xabo\xbc0\xc1\xf35\x00\xdf%\xac\x1a\xae\x86\xf9\x92o \xd8\xac\xb5\n'\xf9s\xcc\x07\xd5 \xff\x1c\x0b\x16~\xed*\xf9Z\xca\xfe\x18\xb3\xf9U\xcd\x15\xc9\xe12\\\x11k?\xdaC\x92\xe2|\xea\x87Z\xf0&49\xf5A\xc8}HF\x9d\xfa`#~\x88\xbd_%DZb\x1fb\xca$@c\xfb 2\xfb\x0e\xeb\xfcS\x9f\xe2\xcbp\xdf@\x08\xc1\xcc\xf7\x00-\xb0\xee\xe1+\xc0?`s\xe8\xaa\xbaq\xc1\xac\xdbW\xdf1V\\\xd4\")\x9e\xfa-\x0d\xc0\xeb\xa8l\x1b\x18%\xc0\xb4\xf1\xf7xm/j\x06\x86y\xff-\x0d\xc02\xca-E6\xff_L\x1d/\x1a4\xc5\x87\xe4\x96\x81`}\xea\xa2\xc1!,\x94\xde2\x10\x8c\x90\x17S\x9e\xc0d\xf0\xce\xde\xd2\x90\x7f\xc0\xf2\xc4E\xbdQ\xd8\xa6uKo\x14\xe6\xf8\xdfw\xe2X\x9e!|\xe6\xf64\x00\x930 \x90\x97\xbfX<\xf9\xbe1\x8abo\xa5=\x03\xc1\xab\xf9}\x18/\xe9\x1d>\xe3\xbe\xbf\xafw\x0b\x0b^{\x1a\x80\x91zo\x90@B\xa8O\xb1\x90\xf5}\x15\x0d\x8cwdOE\x03cn\xf5}\x85qX8\xd9S\xd64,\x7f|\xdf`\x03\xa6\xf1{\x06B\xea\x18l\xc0\x82\xd6\x9e\x86\xfc9&\x9b\xc1\xa2\xd6\\\xf0\"\xae\x99\xfc\x02\xf88\x04\x06\x82W8pJ1\x04\xf80\x06\xce q\xe0\x16\x13\xb3\xff5g\xd4\xf3$\xbe`\xdc\x0f\x0c\x04\xabOk*k\xe6\xaf\xb0\xf8\x14h\x00\xdeM\x01\x80\xfc\x8e\x98\x11\x05\xc6\xb3\xccR \xcc\x8exC\xd7\x1c\xf9\xe2\x9a\xbe\xc4\xc23\n\x1cH\xb8\xf61f\xf0kZ\xab\xc7RK\xa0\xed\x00\x98\x85\x98\x986\x1b@\xc6\xf6\xfd\x14\x8b\x18\x12\xd2\x97\xec\xe0}|\xf9 `\n\x84e#\x01\x02\xe1\x81\xa8\xa2\x02\x14\xc8\x95x\x07\xcfH\x06\xd6I\x81\xe5}\x8a)\x89\xb6\xe7|\x80y\x8f\x80e\xb2\xda;\x98\xcb\xa8\x1b\xd2'\xa4\xa7\xc5\xcc\xf1\xa1'\x8a'\x06\x84\x89z\xe0@D\xf2\x13,\xfe\x0b\x00\x98\xa8\xfe5\xb5\x18\x05g\xd5\xb2\xbf\x8f\xa9E\xd0\xd3\x10|\x98\x03\x9d\xe4\xef\xaf\xb0n\x10\xf4\x12\xb0:\xfc\x91\x0d \xea\\\xa7\x80=9\xecGX\xd1\x16\x904\x00D\xc6\x1c\x12`2\x8f\xd1#\xcc\xac\xd6\x8c\xb7!V\xd0\x03\x03\xc1B\xca\x9a!\xbd\xf8\xf8\x05\x06\x82\xa5\xa4\xc0\xe5\xb0\x13\xefb\xd6\x13\xb82\x16\x15\xaf\xc1\x1a\x90F\xb2\xa5\xf0\x99t\xec\xb9R@}\x1f\xb3\x89\xc0\xe48\xc4\x84QB\xc0\xe2AN\x9d\x97x\xda\xe1\x143\xf1\xc0K\xf2T\x03\xc9.x`\xd2x\x87l5\x18!1 \x06\xf2r\x1f\x9fT\xe9\xf2/\x88\xcfY\x81\x07\xe01GhP%.\x80\x90\x81\xb5\xb2\x0d\x89R\x8f\x8a\x85\xc9V\xb7\xec\xedN(\x89)\x80\"\x04\xb0,g\xba\xd1\xc7\x90\x1cj\xd1\xd2\x12\xf7\x03H\xc7J\x91C\xc0\xc1\xf9\xbf\xbc\x14x\x19\xa1\x94t\xd7.\xf9\x8dc\x0b\x85.Ur\x1b\xc7\xb6\x9ej\x11\xed5\x8ei\x87(u.\x88\xa0\x8dw\xb1\xe9VLZy\xe0\xeb,\x7f\xc4\x1f\xbeT\x06\x02|\xdf!\xe7\x85\xf73\xb3|\xa0\x1ec+5\x0d\xf8 FaQ\xa4j+$\xf6\x99\x80\x14!\xadT\x8b\xa4\xb5[-\xcb\xa8iA)r>t\xa9\xf4v\xee\x0f\x8a\x1e1\x11\xb6\x05'`\x8a[\x8a\x9e!\xa1\xa4\nV,\x8c\x0d\x83\xab\xd8\x82%\x1d1\xd4l\x98p^\x84\x98\xe1\xd9\xc8FJ)\x1f\x1f\xe0S_.\xa0\x90\xe9CL\x9c\xcbe\x8c}\xf2\x01\x16\x93D)\x08\x92)\x0d\x19\x0b,P\xa8:-|\xa7\x0feJ\xa1\x1aXG(\x17\xd0\x07\x00\xeb\x04(\xda\x03\xe3.\x8d\xf4 \x82\xd0\n8\\S\xfc\x80\x0bi\xba\x19p\xc1CD\x1a}\xf3C k\xc9'\x80\x9e\xbe\xb4\xee\xbb\xba\x99#\xf2\x9e\xf1 x\x8c\xd7+(\xf9\x04`\xedM\xc1\xe4\x1a<\xc1\xb4&\xe0\xa9\x9a\xacE\xce\xe0\xa9r\\x\x82o\xd4\x03\x9e\xa6\xa5\xab;,\x81\n\xb0\xb6\x13`\x0dZ\xc0\xf8m\xe5\xf7jYc\x01\xd5`\xb25kO\xaa*\x14\xa1U\xa2\x08\x12\xb0 \xe1\x8a\xeeHrA\x94\x80\"\x95\xb8\x0d&\xcdC$\xc7x\x00k\xd9\xb6|\x06\xd7\x92GD\x18\xd0~:T\x1eOJ\x04\x92X{\x12\xa5\xc0R\x01=1\xb4\x91\xec\x00\xa4\x00z\x93X>\x12E3\x1f\x10\xca\x98:Z\xf9\xc6\xf8\xb9\xa6\xafF\x88dh\x8c\x92X\x98ZS\xaa5\xa1\x95\xb5\xdfk\xa4\x81\xc08}ac\x88\x80\x80`J8vz\xbbg\xb3\xc7\xa4z\x82\x041Rc] B\x92vb\xf8\x8c\xc8\x8b\x06\x82\xed\xbbk;\x0b\xac\xf5]\xfcQ\"\x05\xe5\x9a\x99\xa5l\xa0\x9d\xce\x08\xdd6Ng\x84\x86d\xb5\x82\xa4T\x8c\x16l:QP\xa8K\x84=e\x9a\x9d\x7f@hQ\xc9U\x8d\x98v4K&t$K\xe0:\x97hK\x81\x0e1&\x89\xf3\x83,\xd1\xeerdRy\xe2\x19\xc3\x0e9\xb3ybB\x90\xc9\nV|\xd0>\xb2H\xf3\xda\x07\xcd\x02S\xb7\xfa\x1f\xe3\xdb+\x13.\x83g0r\x80\x16\xfc%\xd6\xec\x04\x80\xc3\xe3\x1b\x04v \xc4\x89\xf71\x91\x1e\xc1\xf7w\xf0\x94\n\xfeT\x032\x96\x0dl\x1e\x03\xb0a)Xa\x03\xb0\xb2y\xe0k\x92\x91\x93\xec\x01\xc5z\x0f\xdf\xfd\x8et\xb6\xc5g\x1fa\x99\xf9\x12H\xa0\xd8\xbc7\x82\xcf\x98\xbd\x8eL\xca*l\xe5\x18\xe9H\xe6{\x98\xb1\x8f\xb8\x93\xe6 \xf7\x8a\x07\xb6\xb0\xf2q\x89{~>2Ndoa\x82{\x89\x07\x81\x1f\xeak\x01l\xf4\xbe\xa4\xd5\x01l\x88\x1bi\x00>\xe2\xa3\xa1\xdc\x9c\xb7\xc9\xea\xfb\xae\x0c?\xfb\x18K:*-\xe8=l(\x19\xf9\x9e\xfd\x8d\xa2\x91\xef)\xba\xf0\x14\x13\xd6\x91\xef\xd5\xa4\xcf-\xb2\xc0`\xb2.!\xf0\xc6\x16^\x1b \x82\xd1a \x0e@R]\xf9\x08/\x81\xcc\xc9\xaa\x13\xaf\xde\xc3\x8cq\x14\xb8\x90\xad\x10\xdb\x8fG\x01\xb3\xb4g\x1e\x1a\xa3\xb0\x0c\x1e9\xf8%\xa6M\x12\x02f\x85:\x18\xf8\xfc`\x1f\xbb\xb0'\x9d\x8c?\xc6\xd4:,R\xcc\xd3\xb1\x97r\xc9S\xa0\xce$\x89\x97}]\xdf\xe5|\x86\xb7*4\x10lz_\xd7w9\x9fa\xae\x11\x1a\x08\x96:C\x93r\x96\xf6S\xce9k\x19\xb9Jt\x89Q|\x1d\xc88\xd6\x14B\xf8\x8c\x15\xca\xd0Pw|\xbaT\x82_\xb2\xd4\\{F\xbd\x8fYU\xc8\xf5\xdd+V*D% y\xc7\nQ\xaa\x02\x85\x99\x88g2\xfdu>p2\x7f\xcc\x11\x1fy\x13KW\xba\xdc\xce\xd0w\xf7\xa6*\x16N.u\x99'\x87\xcd%Ko\xf5`KS\xc8S\xaer\"a[AX\x04l[&\x9cf\xdc\xa3A%$\x82\x02\n\x96-\x7fD\xde]\xe7\xfb\xca1\xf9\x07!\x19\x82 \xaf&\xf4\x86\x17\xf1\xd5\x18\xb6\xae\xf9.6\xb8\x85\x1a\x80\x87\x19\xea\x988\x8a\xd9*,\x0e;\x16\x86:\xce\xcd\x06\xb8]\xdfX9\xd6\xcd\x06O\xeb@:4\xccRI\xef\x13\x96\x1aB\x1d\xd6b!\xc9\x03\x00a\xb95\xd4\xc6[\x028\x9f\x01\x06=\xa5\x030\xd1\x0eX\xb7\x0cM\xb8\x03!\xacCexx\x8a\xd5\xbbPj\x0b\xf7\x08\x0e\xc3Cq\x0f1\xf3\x0b}\x10>\x1eb\xa9/\x04\x8c'\x0d\xad+\x93'V\x11Be\xf2\xc4\xea^h|8\xb0\xba\x19\x1a'\x0eZGI)XD\x0e\xf5E2]Du\x97\x8c\xa5\xb5\xb0z\x13L\xc7P\xb9\n&\x03\xb1\xdc \x92M\xb2\\!\x92\xed\xd278dx\xc5\x15\x8emJ\xe5[\x1c\x1b\x19jM\xdbr\x0e@\x1b\xa3\xddh\xb5\xf5!&W\xa1\xd1[\x1fbkZ\xb8\xa6\xce\xc8\x13:8-\xc1c6\xb5\x1e\x9dM\xb8#Y\xd8[\x98\xbb\xadG\xa1\x04\xfa\xe1@\x13w\"l\xac\xebX\x11\"\x9d\x18\x01\x16K\xec\xfam62|\xd0\n\xf0\xe7\xf5(\xab&\x95\xc7\x86\xc9_\x01.\x06\x81)\x7fQ\x06\xc5b\xda\x86b\xe3\x9d\x0d\xe5\x0c\xf7\xc4V\x9e\xa2\x08\x0e\xcclh\xadX&\xcc2\xd6\xa3\x8c\x86\xe2\xd8ZB\xf18\x14\xe1\xa3L\xb9B\x13I\\@\x8c/\xb4\xbd\xa2r\x87\xb6\x03\xc7N}\xbb\xf0\x10\xf4C\xac\xd9\x02\x0cr\x98c\xe3\xd5z\x94aO\x00r\xe8Q\x19\xe3\x0c`[\x19\xabG\x00\xa1\x15\xb2`\x0d\x8dS\xb0by1\xd5U\x05\xca\xc8c\x1dHY\xea\xb2\x0f\x95^\xac\xd6\x95+p\x06\x93\xd7\xf5(\xab\x93\x07\x9f\xfc+[sT(|\xf2\xd7\xb6\xadV\xa2\x00\xf6\xc8\x93\x10\x85\x04v\x18 \x01\xd6\xa9\x01\x06H\x805\x8f\xf5(\xdbL\xb8\xcb=\xf5\xd2\x0b\xb6\xf3\x95\xe0f\xad\x9e\xfc\x1b\xdb\xe4t\xb1\xea\xba>\xb4P\xac->\xe6I\xca\xcbD\x0fOG\x94\x92\x195\xcb\xc8IdlTHc\xa7EOA%\x8b\xe1Y\xa86\xe4\xc1\xd9\xce{*\xe7\xdb\x03+\xb6\x97K\x15\xcdYX\x84.\x18\x8b9C\x83\xd6\x01V\xcb\x15Mb\xd3\x97(Z\x8c\xedO(k7\x05\n\xb7\x1c\xa2#\x8b\"\xae\xcb\xb9\x07\xbb\x8e\x0d\xfa%x\xb1\xeb\xd4XQ*\x86v\x1d\x1b\x1aK%\x8b\xf3\xf4\x1f\xed\x0d\x96\x16\xea\xc75\xb3Ck\xf4\xc0\xc23\x8bn,\x93\x93\xc0\x82\xccXx\xa2,Qeg\xc4Z\xa4J\x15=Y\x86\x81\x99?\xd1\xd6\xe3\x1a\xa9@\x00\x9c P \xf1mPH\xcd\xf1\xf4o\xe9+\xb4\xa1\x8e\x80\xbbG\xa5\x810\x8e\x02\x1d\\\x88M\xc9!?}\xc7Z &Id\xcc4\x8f\x1b\x88\xb2\x02\xabI\xd6T\xd6\x93\xb4\xf4\x9b\xa9|;D\xc8\xd7qx\x9f\x10\x8b\x96\x81\x10;T\xa6\xbc\xd1h/\xe8yr\xaa\xe2\x96K\xc0d\xa8\xaeK\x9e/\xa7\x07\xbfRD\xb5C\x04\x0dy\xa5A\xec\xc3\xf2+1\x0f\xcb,\x9a\xbfG\xbfrH\xda\xf86\xbe\x13\x0es\x9d-\x96\xd8\xb3\xc7\xfa='\xcb.^^\xd6\xcf\x14\x12+\xd8e\xf3\x82!\xb1\x18\x8cM-B\xe6\xc6\xa6\x16Y\xc6\xb1N\xbbe\x19\xc7\x18\xf2\xcf\xd8 \x17t\xb8\n9\xbc\xe3\"\xfe\x1d\xdf\\\x85cm\xcbz\x1f\xdb\xe9\xc3\xb1\x8ee\xb0\xf5\x06. v\x88\xb9\xc4\xb7\x815\x0b{\x9f\xd0\xdd\xb1\xe1\n\x0f\xfe\x9d\xad\xa6~[\xf8?X\x80\xfb\xc6\xe8Oh\xda\xbe\xe6\x99\x04\x15\xf65\xcf\xb4B\x14W\xa3\xb0P\x9b\xc7\xf1\xd5\xe1\x86I\x11\x81\xef*\"\x03\xc1W\x81Q\xdd\xf3\x99\x91\xba\xac%\xeffn\xe8\xf4\x11XF\x894\x00kc*\\\x1b\xef=Dk\xff=\xd6\x89\xa2\xda\x1797\xf4\x9bM\x9f\xe1k\xed\xc8@05\x8a\xe0!\x98g\x1fa\x9a\x13\xe9\xd7\xce\xb0\x93V\xe4\xa5\x91\n{\xc2\x96\xdd\x8d\x15H\xbd\xf0\x19\xde\xff\x88+\x00Y\xf8\xbeZ\xc6G\xd8\x95iC\x1b\xfeI[\x1a\x80\x0f\xa6\nV\xff5\xde\xa9\x0d\x93\xc4\x824e \xd8\xa4\x1d\x81\xb1\xfdC\xcc\xba\"\x9d\xa8\xe7\x116\xc3DC\x81\xfd\x9fc9&\xaa{\xa112\xa6hl\x06\x8f\x02\xbd&d\xeb\x03\xf3(\xe1#\xec\xb4\x13\xe9\xc4\x12o\xd2Z0\x17,\xcbn(O\x98\xcf\xb0\n\x1bi\x006]o\x8c\xf8\xc0\xb1\xceR\x01~\x83\x19\xe8\x86\xf4\x8f\x90\xe9\xa7\xb1M3*@x\xef#%R=\xc2\x86\x9fhT\xfb.\xec\x861\x9e\xe2+\xd2\xc8@\xb0\n`\\)\xb1\xf1i#\xe6\xa1\xf5\xc5U|\xbdo\n\x16E\xb0_Z\x14sx\xf0\xf0\x11\x96\x11\x8c\xef%y\xc5vC\x0e\xeb1\xa1 N\xe2k\xbf\xc8(\x17\x04)\xc0\xb3\xf01\xa6\x14Q\xe2\x81\xb5\xe7mL\x8b$\x04R\x8a\xd8`2\x13\x17\x16>\xa2\xc4\x13\xb8\xff1A\xe4\xc4\x1f\xa8\xec$d#\x13\xf5b\"\xde\xc6(I\x83\x08D\xb9\xc7\xf8>7J$\xa9zLH\xb1\xfd%\xe1\x0d\xa3\\\x90\x01k\xc7\x0fB\x89u\x8a\xa4O\xc8.\x1a\x08!\x94\xeau\x8f\x07\xb8\xca\x86\x11\xf4\xf0\xf6F\x06\x82\xa9\xc8F\xe1s\x8bq\xb2p\xc7%\x8f\x1a\x03\xc8\x81zx\xa97T\xb6\x06\xb2\xd2\xea;\xd9\x9a\xb1\"q\xefbanc\xccu|\x11!2\x12\xa6\x82k\x9f\xfd\x19fe\x1a\xaa\xc2 \xff\x94\xac\xfb\x98'\x9bN\xc2\xc3l\xc8S\xb86\xfc3|\xd4\xb42\x85M\x06B\xd7\x13\xd8\x87\xe7Q\xd1\x01-\x95\x94\xb8\xf2\x14s\xfc\x92}\x82B\x94m\x02\x016\x9d\xc4<\xcfF\x81\xc0\xc61\xf9\x8b\xe13&}1O\\\xc91\xfe\x19\x05\xf82\x1f\xca\x0c\x05\x8c \xd6\xf3Mlt\xd6\x94\xe7\x01\x99>O2\x1eJ\x81\xecM\xac\x85lj\xfe\x8ayu\xac\x01XX\xde\x84\xa7\xd2\xb1\x96\x1b\xc3S\xe9\x98\x1c\xc7Cxu\x00\x1f\x8ax\xa8^q\xa6\xfeX\xf1P=\x17\xfd\x17\xf8&tS\xf6\x8c\xe9z,;\xc6\xfc.\xf63wX\x9b';\x86Q\xe1S\x12\x07N\x08\xef\xc7\x93\xa4i\x00\x82\x84jx\\\x02\x06i\xb7-\xd5$\xd1?j\xf9\xec(\xc6\xff\x11\x16\x92\x05\x104\x7f|\xb2\x04D\xd7\xc2\xa6\x04\x01\xf3\xa4\x9aE\xde\x81\x93 p\xf3#\xb8\x11\xe4\xe0\xd3\xfa\x18\x0bE\x9bA\x9e\xea\x87\xd9?\xc6h#\xaa\x8d\xc2:\x88:l\x1f\x11\x1c \xf24\xdb\x97c\xfc\x08\x8b\xeb\xf1\xc8\xd6\xdaf\x04\xc9\xa8\xc4\n\xcba\x92\xcc\x83\xb1\x90\xb9\xb4\xa1\x10c\xd9\xa6\xbe|\xc5bml\xa4\x04l\xbf\x8a\xa3\\>\xf6\xf81\xde\x95M\xb9\xecO0\xd3\x05S\xe4}\xcc\x0d\xe3DE\x18a\xc2nL\x94\xf7\xb1<\x1d\xc3[\xf5O\xc8y\xd0\x96K\xfa\xdd\xad\xe9\x9b\xbb\xa50&:\x02\xee\xaaw\x83\xad\xe3(\xdf\xb3\x90\xb6-\x97,5%\xaa\x96\xf6\xda^\n\xab4f2e\xe3\xab\x05T\x8e\xd4\xc2\xb2\x96\x84+;\xce\x13\xccu%P\x87Ya\xe9J\x00\xb5\xc5\x10\x0fh3Q\x16\xc37\xe9\x16i\x08>E\x12\x92\xdaq0\xd1Qht\xf8p\xc1j\x19z\xc3\xc0\xd5S\xed\x98\x02m\x96\x1ej'\xd4)\x89\xfaN\xa0\x04\x00\xac\xb3\x08\xa0V3\xde\xc5\xca\x94\x00\xa698\\\xbfKx\x87z\x7f\xed\x1e\x96D7\x93(\x8e\x12\x9dI\xed\x1e\xc6\xcc\x02\xac\x12\xb5\xe1\xfa\xa2a\xf0\x9b\xb7\x80\xea\xb6-N\xf2\x04\x04\x83\x07\x98en\x1a\xa1\x11\xdb\xc6bc\x91\xc6\x86\xc9Mx\x95\x87\xac\xbf\xfc\xfc\x1b,\x96\xc6y\xe8*\x13\x17\x06\xbd\xae9,&\xd7\xb75\x00\xef\xc8\xed\xbal\x8b\xafk:\x87\xcd\x13\xb7\x0d\x9d\xc3\xec\xe2\xb6\xc1\xd9\xb7\xb0\x80\xf9\xbaY\x15\xact\xdf6\xab\x82\xf9\xfc\xed\xdc\xc9x\x12\xfa*3\x01\xc9\x8c*\xe0z\xf4\x98\xeb\xea\xd8\x94\xd7l\xdf\x15\x91\xc2\x02\xd5\xeb\xbb\x1b;\x0b\xec\xdb\xado\xe3*Qf\xf9\x9c\x98\x84KX\x9b\xd0B\xec\xbd\xbf\xfd;\xcc{\xb6\x8c/5\xde\xa0\xc4@0\xc3I\x1c\x0f\x12\x90\xde\xc3;\x91\x94\xb34a\xfa\xb1\xa5c;1\x1a&\x1a\x80u\xf0\xc4\xa4U\xc2'S@\xe4\x94\x1ea^\x9f\x14 \x97hs*s\x12fo[Z\xd9\xc4R\x97\xb9\xfc\xa2\xfd\xab\x1a6\x00\x10\xbc\x0f0]KLR%:\xe6\"\xa9\x12\x19Bq\x97f\x81\xa8JX\x84J\x8atKXQL\x8atK\x18\xf1\x13\x93n\xe9\x03L\x0f\x92R\xba%\xac\xe9l\x99tK\xefc\xa4O\x8aLLX\xd2(]\x03\x92E7 \x97\xb0\xc2\x94\x14\xb9\x98(\xeae>\x10M\xac5IH\xa8\xfd\xe7q\xbd-\x93\x8d [\x18\x13\x03\xc1\x1c%1y\x9a0\x05HL\x9e&\xb2[:O\xd3]\x1b@\xd4\xb9A\x01*O\x13\xa6\x84I)O\x13\x16\xd3\x93R\x9e&<\xa3-\xe3\xa7\x8f\x15\xfb\xc4@0\x03\xdf2~\xfads\x0d\x04\xd3\xd6\xc4\xe4i\xc2\xc6\xb3\x04\xf24\xe15\xd8\x02\xcd\x91\xe0>8\xc3b\xad'\xd1y\x9a0kM\xbc\xc0\xa4\\\"\x87\xdf\xe4p\"\xf8V\xe4p\xa2 \x15\x17Jh\x19\xc8\xe9\x04?9\xf0t+@g\xc9%\xd4\x99;\x81\xc9\x92k\xab\x08\x88K\xc6\xc6A\xdey\x0f\xeb\xae[+\xe7\x05\x91\xc3|5\x81W\xfe\xf1g\x8b\xff\x0fvV\xd6E\xd03r5\xc5vcT\x90<\xb7\x9a\x14\x890\xb0=\")\x12a\x90\xe6U\x0eh\xb2BZ\x90 \xdd\xe8\xc4\x16\xf8\x16\xdb\x84'\x93\x17\x7f\x13\x9d\xd8\xe2\xa7\x04\xe7\x8a\xc4\x16\x98ln\xc98\xba\xcf\xb1\x8e\x95\xc8\xcf\xbf\xa1]DR+'\x8cX\xc6\x88\xe3|]\x18\x8bQ$9\xe6>\xc8}\x820\xa7\xaa\xf7\x84\xb5v%g\x17fTE\x89J\xd4\xfbO\xf1\xfd_\xd1\x91I\xda\x85\xe9\xbfl\xaa\x9c\xb5\x0b\x93\nY\x80\xa6\xed\xc2*\xb5*\x86\xf3v\xe1\xd3b\x8a\x95\x12wa\xb3\x16*\xa3\xf3\x0ea\xf1G\x16;W\x8b\xa7\xe5\x04V:\xc2\x95\"Z\xa9\x10\xf8\x06P\x8c\x13EP\xf6.\xeb:\x97\xf2\x80A)\xc2.D)\x9c{\x8bPf\x9ff\xd4\xb2.\xa2N\x97\x85em\x0d,\xb0\x13[F,\xcfr\x13Z(\x8a\xa0\x8cYx:\xc4\x17\xf1\x01\xa1\xceVG\xc4\xa6B\x85\xf7\x1a\x96\xdad1\x925\x0bK\x04\xaaTur\x98R\xa9B\xa5\xa4WX\x8b\xab\x94\xd0\xf8\x87\x05s\x94\xd3\x8c N \xae\x9b\xc0\xbak\x02\x87\xee\xd7D\x88\xf2\xd3\xea\x83\x8d\xa4\xa2I\xa6CP1\xd0\xe9 \x08\xfa\x05\x90\xf3\x81HQEf\x1bL\x0c\x93jf\x1b\x02\xd6\x81\x0cO \x933 d0WLL\x02\x19\xbc\xe8\x89I \x83iKbn\xd3\xb0&\xb8\xa5uQ\xc2\x95\x8d.J\x04\xde\"/ \x1duqGB\xf0/\xcaC\xaf\x94\xe0\xfe\x03\xac\xde'0\xc6\x8e\xe53\xdc\xf8>\"\x9a]\\r;$<\xc2d\x03!\x04\x19\x85\xf0\x90\xb3[d\xea\xc0\x06\xb5-};E\xebh]\x1b\xfb\xc6l)\xc9\x8b\xec}\xedw\x99\\\x83\x08\xd1&\xb9\x06\x16l\x93\"\xb9\x06\x01\x15\xa9)\x082\x17t \xc7ni\xdf\xc3\xf7\xb0\xa5\xab\xe4db\x81H\xc2zE:\xe2\xc5\x93\xf7d\xbc\xb5\xe8:\xf2a0\xefR\x88\xdc\xc9'd'G*\xaf<65\x08\x00\x84\xaa\xfd\x0d\xcd\x02\xb5\xbdqn\x07\xce*\xa9\x16\xf538\xadX\x9c\x01G\x9f\xe3\xf4\xab$\xe3\x1fb!_\x00\xd4E\x1aa!F\xf0\xc5rQj d\xc9bG]\xc1\xfe\x92\xa0\x99\x04\xe9w\xfd,\xd0\xc4z\xf0\xd3\xdbJ\x96x@\x98\x9f\x80\x80\xaf\xd1\x9f\xd3\xb5Ko\xab\xdc!\x0f\xb0\xb0,!P\xefg\x965\xbf\xad\xfcg\x88\xd4t[\x076`\xb5\xa7\x08\x94x@(\xce\xedR\xf8\x82\xb5^\xe1\xd7o\xab\x0b3 \xb4\xd4D_<\xc04P\x82L \\\x0dPuH\xebJK\xd9{\x98\xd5\x97^\xae'R@=\x08j\xe1g\xa8\xc8.\xd2p\xc0\x86\x02\x85R\x8f\x17\xcb\x16\x06\xd8X\xa4h\x8a\xb0\x11Yn7\xd4#\xa6\xf8\x93;p\x83L\x1e\xf2Oo\xe75\x80\xda\xeb\xa5msk\x89u\xc8\xd4hR\x98#\xa7\x0d\x02I\x03mJ35\xee\x87\x98jogp\xfa\x08 U\x80\xbf\xb0\x01d[\x7fAD\xc6,q\x04\x9f\xe6q\xea\x07r \x7f\x83\x95$]D9_as\\\x9a%\xd2\xeeE\xb2\xdfm\xc3\x01|H\xf0Z\x1dL\xc2r\xf3\x9e~\xb3\x9b\xa8\x0e&\x16\x89\x02\xe0d\x91\x19\xe7=\x9d\xaa\xe7)\xe1\xbayo\x94\x83\x07\xf3S\"[\xe7=\x90\xfa\x9fb\xbb\xa2\x80@_\x84\xc0\xe6=\xcdE\x9f`\xb2\x9c\xe6=\xc3E\xb1^Z\x1c#\xdb\x1a\x990*+H\x11\x05\xcb\xb4\xcb\x11T\xd6\x0e\x8b\xb3d\xaf\xad\x12\n\xdb\xa6 \xd0\xdbu\xeb\xa3\xfd\x1f\xb1-A\x80`\xd3\x9f\x12\xec\x11 \xc8\xf2F8\x86\n\xf6\xa2\xfaj\xee\x96]\x8f\xb0\xd6*\xc0e\xd7#\x8cL\xe5`_\xd2\xb6%\xd2\xb7\xa6\x04r=\xaa\xeb\xa5\x14\xe1k\x19\xa7\x0eY\xb3\x80\xca\xaeGD5\x15p\xedzD\xd4S\x01\xacUPs\xb7^\x0b\xcd\xdd\xe1\xce\xd0\xb1_Bm\xc3e\xd2=\xc2\xf7j\xbf\x83!\xf0\x97\x98\xb8n\xc3v?\xa4\x15\x80}\xd2\xd3\x1a\xcf \xf2\x82OO\x9a\xc7\xf3\xe2;\x91M\xf3\xf8\x84\xf8N\x84\xc7<\xd6\xe4\x05[ \x05H#(\x11XM\x84 \x05\x009\xa0\xd8\x1e\x1b\xd2\x83\x05\xb8j@w\x0d\xb08\xa0\x96\xa6\x87\xca7\xfcWXQ\x9405 |!\x9c\xe6\xb1I\xdbJOSl\xa8!\xa55\xb1\xa2\x86Dp\xcdcE\x0d)\x1d\x8855|J\xc45#\xed\xd8\xb6\xbfn]*b\x90eI\xca\xe1\x94V\xa8\xa6h\x96\xa1\x96)\x9ae\x8e\x9a\xa2\x11\x9e\x9e\xc7z\xad\x89\xc0!@@\xd1\x08\xbb/b\xd6\x88\x19\xc6\xc4\xacachjb\xd6\xac\x90\x9a\xbc\xd7\xe9~\xa8\x8d'D\xba\xb9\x03\x91S\x9f`=q\xc7\x113\xfaA\x86>gN2\x80\x9dy\x17Oh\xc7\x91!\x9aX\xaf\xc8\xe4\xe7\xdf`\xe4\xcf\x94\x9d\x9f\xf8\xea\xef\x18k\"i\xc9@\xb0\xa6\xb1cl\x80\xd8\xfe\x92\x19\x08\x96\xa9\x94zF+H\xdd\x0c#\xbf\xce\x9c\xfcclw\xcdx\xa0\xbcb\xdf\xc5\xeclG\xdb\x8b\xf0 \xcc4\x00\xdb\xcd\xb3!O\xf8I\xd1\xd8=\xb2,\x02\xd4\x8f@b'\xd0\xac\x11\xba3\xe4\xf0\x06*\xa6g\x99\x06`\xb6)\x01\xe9\xa1\xc0\xf7\xdf\xe0\xc3)ac;\xc4w\xf7J\x197\xf1A\x91\xf0:cJ5\x03\xe2[\xbf\xa2/\xf5gC?T\x9e\x8d\x98\xdeU\xb3\x1dbh6\xdcS\xb1\xbdtD\xf5\xe3\xb9\xb0\xb1\xb5.N\x066\xc7d\xc3(\x11X\xf8 \xe6\x1c\x86\xbb\x93\xb6t<\xce\xaf\xb1%\x1a\xa5\xdb\xc0\xc4\xce\x92k\x03\x8bq(\xd1\x06\x99\xa0\xba!\xf9\x84\xe0\xa0\x00\x80\xec\x8d\x15z\x00\x01\xc1\xf8\x88\xa0\xa8\x00\xc2\xbb\xb9XP\xc9\xea\x1e\xe0\xce\"\x0e>B\xd8n\x99\x81\xd7\xee\x03r\xd2\xa3\xb8\x07\xe7\xed],\xd0dQ\xac\xd3\x18\xe3\xa1\xed\x18\xdb\x06\xa6\xed\x99\x81`\xca! *d\xe3)6\x1bdQ\n\xc3\xc6rSVx_\x93\xa3\xb6\xb5\xb8,\x99\xe4\xdb\x84\xb0$\x0e\xec\x91\x05R\\\x9f\xbf\x87\x15.\x0d\xd4\xde\x0b\xefaA\x0d\xc7\xee\x93\xac\xea4t\x9f\xa4W\xd7E@F\xc6HJ\xe2\xfa\xc9\xa5\x9a%\xac\x9f\\\xafe\x89zU\xe5\xd9/\xb0IL_\xc9\xd9z6\xb6\xc1\x8f\xb0\xdc\xbb\x93\xf8q\xc0\x97\xeb\xe8\xb2\x80\xaa\x9a\x96\xe1\x02\xea\x7f\x88]\x06\xb3\xc4\xcf\xd4\xd6~\x84e\xa3,\x89\xf9\x1d\xe5F\xf5gx\x0fw\x8c-\x00k\xbe\x99\xb1\x05\x10\xa2\xa5nz0\xfb\xcf\xd4U\x0f\x96_v\xb4\xf9\x9f\xa0\xb7\xb6\xff\xe3E\xd81\xcf\x0f\xd0>4\x04_\xc0d\xfb>\\\x8c\xdc'\xdb\xb4\x1f\x0d\xb9\xe3U\xf3K\x12\xea\x08\x85\x90w\x13&1\xbb& \x1e\x1f\xba\xdc@\xf0~\xefj\xd1\x07\x8b*\xb9\x96\x960?\xcau\x0d\x0c\x10M\xe9\x00\xfb\x0f\xf0\xb6\xec\xf6\xd4\x93\xca\xf8\xa67W\x80\x7f\xc0s\xde\xed%\\\xc6y\x7f\x86\x97,7\x10L\x13wu\xb4>\xde\xb3\\\x030\xfe\xed\xc2\xa8\xb0\x1c\x93\xc3\x98\xf0\xa9\xcf=\xed:\x809\xc6\xae \xd6\xc7\x04<7\x10LZs\xe3\xca\x89M]y\xe1?\x88\xf9\xe1\xae\x16s\xb0\xd8\x91k\x00V\xd7vM\xc0<\x16as\x03\xc1\x879\xd7\x9e\x85da\x86N\x02\xeen\x98d\xe6& -\x1ern\xde\xc5\xc2\xdaJ.\xdf\xa7\x12\xa0w1\x95\xca\xcbOWY\x80*6\xe5]l\x1e\xcd\xcdC\x18X\xfc\xda\xd5\x11\xf2X\\\xcf5\x00\xbb\xedC\xb0\xed\xc7\x98\xc1\xee\x86\x9e\x8e\xa9\xc5\xef\xe5\x00\xc8\x84\xd4\xe2Ce\xc0:\xa6\x16\xd3sY\x00\x07\xd5\xe2{(c\x8a}\x88\xf1SBt\xb6\xff\x07\xf8\xa8\xed\xaad\x0b\x9fa\x0c\xc95\x00k\xf4\xbb\x86\xc5c\xcd-7\x10L\x04\x9b.\x1cw\xe3\xc2\xb9\x86\xd0\x95\x02f\xa9Wv\xda|\x1f\xdb\x8c\x15\xb8r'KOh\\\xbd\xb3\xc5\x8a\xc5n,\xa4\x81b|\x18\x9eW\xe1\x96\xfa\xd8+\x98\x9c\xeaX91\x9aw?\xc8\x19\xd2%\x8a\xa7\xa4\xc8a\x8ak\xb77\x8e\xf1[MX\x9b\x94E\xd0\xad1\x96awU\x08\x14^\xe4\\}\xc7\xeb*\xbe\x0fm\x15v\x8d\xc1\xfbs, \xe6\x85-\x9cn\x93v\xbf\xc4\x95$\xa4\x187mSa\x10x\x7fb\x99=O\x0c\xa9\xc1\xe7)/?\x02e\x01jRC\x16\\9\x19~F6Z\x03\xb0\xd8\x92k\x0f\xaa_`\x82\xbbkD\x1d\xc2?\x8c\xa8\x83U\xb7\xdc\xbc<\x84\xeb\xecj\xdd\xe83L\xbbr\x03\xc1\xf2w\xae\x9d\xbb0M\xca\x8d\x0b\x17\x96ps-\x0b\x90\xd5\xdeUy\n\x08\xe1V\xdf\xb1.\x97\xef\x1ba\xfd\x11\x96\x9d\xc6N8\x80;\xc8G\xb8\xb9\xb1\x934\\\xab\x8c\x9dD(\xce\xd2c\x01\xaf\xd0\xd8I\xc2H\xe8\xbe\xf0\x9a\x06\xc6\xc2\xb1\x93\xd4\\\xc6\x08\x88o\x0b:\x17\x80\xfa\xb8\xc6\xb1\x16\xa7,\xed%Vz\"\x00\xe0`\x8f\xe5\x86\xb1\x93\x18O\x0clR\x11\xb0\xea\x1d\x03\xbd\xd2-\x97Q7\x0d5\x85*\xa6\xbd\xe62\xca\xc0g-\xa4-\"\xc4\xb6!`H\xd3\"\xaf\x03\x97\xca\x18\xaaH\xfc\xa1/+\xcd\xfa)f\xe1c\xc53\x9e\xe2\x83 \x002\x8a\xef)>\x08\x97A$\xc4\xe4l\x0c\x9f\xf1\xf0\x8a$f\xb8\xeb\"\x87\x19\xee\xa1HaFFe\xea`]H\xb6&%\xaf\xa7\x98\xe3^V\x9e\x9c\xf8\xa6m\x0c\xdfI\xea\x991\xe7j\xb9\x1e`qx\xcc\xb9\xd2W\xb1\n1\xe6A\xe0\xc3\xbd\x02&w\x97y\xa2\xda{\x93\x1c\n\x0d\xfa\x11\xad\x93\xd5\xd5\xc8j\xca\x97\x13\x9bb\xb9T\xc3\xd5\x13\x17u\xd5\xb7y\xec$\x8e\xf2+\xff+,B\xebR\x85\xe5\x07#3}\x04\x04\x13\xe5\xcbZ\x0c\xc7\xc2\xf6X\x030\xee\x8e\xb5\xc4JQ\xdf\xe4\x8e\xb4dz\x1c\x9b\x9c\x8b\x96\x0c\x89\x97\x8dx\x86\x95\xf1\xb1\x81\x10:[\x1b\xef=6o\x17\x92sg\xd8\x16!R\x86ma\xc5z\\\xba\x01\xb6\x90\x8b\xd2-\xb0\x15j\xeeKj\xa0\xbc\x8eZ].\x0e\x17\xd6\x00\xc6w\xfc\xc1\x1dG\xb2\x82G\x18\xf1\xafh\xbfV\xcc\xfd\xf65\x00\xf3\x9d}\xee\xa9\xf3\xf0\x18+\x00W\xb8\x07Q\xbd\x0f\xf1\xe8\xf65\xe4\x1e\xde\x17 \x81C\x89qj\x9f\xfb*[\xcc\xdb\x18\x97\xafht\xc3\xf3\xd9\xd7\x00<\x9f+\x063\xb0\xa0\xb3o \x98\x94\xec\xdb;\xdfO\xac\xa7g?\xe1N6\xb4\x82\xae\x18D\xc2\x87`\xdf \x12\xd6A\x0e\x94'\xd4C\xcc\x04\x0f\xd4\xce<\xfb\x05\x16\xc0\x0e\x94\x13\x14\xd1\x9c\x0e<-\xfe\xe0k\xe67\xf4za\x9b\xc2\x81\x06\xe0\xfd?\xd0\x0f\xb5\x90\xb7o\x0f\xb4\x8eL\x9e\xbb}Cf#\xc06\x90\x03\xf9\x15\xab\x00\x07:\xbd$y\xcb\xf7@\xdfA\x927|\x0f\xd4\xf3d\xe4!\xdd\x03\xfd\xe2\x0bf\x05\x07:\x99\xe0Gx\xaf\xde0\xe8\x80\x95\xef\x03\x03\xc1,\xef\xa0\x88\x0d\xc1l\xea 2\xd6A\xb2\x91:<\x9d\xbc\xdc{\xa0}>\xc8\x83\xbdo\x18L\xc2\xc4\xea\xc0`\x12&\x8a\x07\xc6;\xee#l\x1f<0\n\xd7G\xf8\xb6\xed\xc0\x88\xcc\xa4\xa7q\x0dK>\xd8\xaf%\x00W\x8d\x8d\x0e\x93\xdfC\x03\xc1\xb8yu\x11\x84\x12\x8c\xe6\x87\x0e\xd8\xaf\xf0\xfe\\\xd5$\x0b/\xda\xa1\x06`\xbc\xbc\n\x1d`\xd9\xe6\x10\xda\xc7\xa4\xfd\x90\xcbdBX5\xbb\xaaO\n\x96\xdf\x0f5\x00\x8f\xe7\xea*\xf4\x8b\xef\xa2\x0f}\xe8\x18+\xadW\x0d\xe2a?\x9fC\x03\xc1D\xff\xaaA\x14L \x0f\x0d\xa2`JxU\xd9\x0b\xb1\x08t\xa8\x0c\x86\xa4<\xe8;\x9f\xe1\x83z\xa8\xf4 l\x00\xb8fBQ0\xc2\xdf1\x10LT\xae\x99\x1b\\\x8c\x1ew\x0c\x04\x93\x90k0\x0d\xbc\x8cw\xe03F\x82k\xea\xe5vL\"\xee\xa8\xef\x98\xa6\xdc\xe1\\?\xe2\x89\x19\xc65\x9eDW|/\x1b\xd6?\xa3vM]\x9fb\xc9\xf0\x8e\xfa\x8eq\xe5\x9a\n\x9b\xc6]\xdd\xd1\xc8E\xa6\xa3,\xfe\xa4\x030\xf8\xff=\xee\xe0\x8e?0!c\xf8l^\xd3ar\xf8\xb6\xed\x8e\xc1;|v\xae\x19\xbc\xc3D\xfa\x8e\xc1;|p\xef\xec\xdf\x92k\x85 \xd7\x9d\xfd\x10\x00\xef\xb6\xcc\xf7\xbb\xf2\xaf\xbb]\xd6\xcfC\xe9g\xda\xe6]\x96uY\xd8a\x7fd\n\xb5\xf2\x94\xb34K|7k\xbdj\xbe\x8e\x9d\x84%\xec\x0c\x0b\xdb'\xe7^\xe9T\xbb\x8a\xe4\xf7\xf9\xeftf\xf2\x90\xa7\xae\x13\xf3K^Q\x93\xcf\xf0\x838J\xb2\x94\x9d\xa9\xf6[\xeeTw\x11v\x99\xdfeN\x97\xe5\xec\x0c\xcb\xaa\xdd\x88\x9fh\x84\xcf\xc4Qz\xc99x\xb5\x02\xf5\xfb\xac\xfd\xf2,;sF\x14H\x13w\xc6\x1d:\xc9R\xe4\xf1\xc5\xac\x9dup_\xe2\xd7\x8f\x12\xd6\xce\x8e\x1e}\x95e\xec\xbb,}\xd5VF\xb7<\x07-\xb7Cfo\xbe\xc3\x12\x9e\xe5I\xc8\x8e\xcc\xbdZ\xdb\xc8\xcb\xf3\xb2\x91\xd0\x14v\xd8\x19\x96\xb4\xa36\xb4\x98\x06\xbe\xcb\xdb9;\xca\xe6\xc4\xeat:]v\xe4\x08\x9f\x89\x9d$\xe5\xc9\xcc\xd8 |\xcf\xc9\xf8\x9a\x1f\xee\xb5\x9d\x0e{\xe9%\xd6\x96+!\x16\n\xea\xf0\x99\xc0\x0f\xf7\x96\xa20\xe3a\xc6\xce\x88e<2\xdb\xb1\x8f\xe7\xb4\x1a\x8bhGV\x17K\xc0^\x13\x7f\x9fa\xf3l\x81eG\x8f\x92\x8aw\xc9\x173\xebo\xd5\x97\x93\xeb\xec\xb33lV\xad\xb4\xe8\xf3\xc4<;\xd2\xb4\xa0\xa2\xcc\x91v\xc8\xbe\xc7^\x11\x7f\x86\xec\xbbl\xeed\xe7\xd5\x0e\x19\x81XX\xebd:j.t\xfe\xfe\x83\xf4\xe8\xf1A\x97\xb5X\xab3\x93E\xf2\x0eg\xc9Iy\xfb\x85\xe0\xf0F\xef\x16w\xb3\x19\x8f\xf7\xfd\x90o&Q\xcc\x93\xec\xb0\x9duY\xeb\xe6M\x9e^\x8a\xbc<\xe0\xad.\xc1\xd6 \xe7\x0b\xec\xc8l1\x82N\x97\xc9V\x9c<\xc8\xca\xd3\xac\x99%\xc5\x147\x1a\xc5Q\xc8\xc3,]`\x8en\x89\"\xfb~\xe2\xc4K\xa5\xa2y}\xd14s2\xbe\x19\xe4\x03?L\x17jXA\x1as\xb7\x0e\xc6Tw\xdb<\x90\xb9&\xd2\x05\x96\xd0^\xf4/-J\xf9\xd6Bw\xedu\x9d<\x1b>\xc7\x08\xa2\xe7i;r\xd2\x13Mm;r\x8f\xd2\x05\x96\xd6\xcf+\xe1^\xeer\xd1\xb5[\xbf\xd4\xfaWZ\x84\xc0>P\xf2\xf5n\xcd)\xbcK\xe9l\xdc\x0e\xdb'\xe7\xe7;\x16\xc9\x14@'0\xc87\xa0\x93\x18$\x88W_\x82NaP\xaeA'H\xadT58\x7f\xe2e\x0c\nt_'\xc9\x08]\xdd\xe0\xc9\x13\x9d\xce\xab\xdf20}JX\xbf\x9e\x1c\x08\x02\xc6g\x8a\xc3\xc8^c\x9c\xd96Um\xce\x02\xe3u+j\xe98\xa6\x1d\x0b\x92Mz-\x88t\x95\xd4j\x0e\xfeGw)\xbb \xf3 `G\xce0N\xe59\xc9P$\xcfc~\xc8xG\x93\xa18\x89\xb2(;\x8c\xf9\xcc\xd0I7\xf6CM\x90f\\'\x08\x04Q\x0bA\xd6\xc9\xae\x877\x04S\xb9\x1e\xde@|N\x0d\xb3L\x8b\x04-,-\x02\xfbF\x90J?\xdd\xdew\x06\x03\x9e\xcc\x0b\x8e7\xe3\xa7\x1b\x8b\xdb'\xe4\x9f)O\xc6\xb7\x1b(\x82\x103y\x91\x942\xc5#KtY.\xddJ\xa4\xec\xaa\x93\xe6\xc7\x03&\"\x99\xb0\x90\x00\n\x17^l\xb1\x97{fz\xaek\xcd\x03\xcc\x9f9o0\xefp\xde\xa4=/2+vD\x00\x01 \"\x80$)Y\xd5}\xb0\x96\xad$\"\x10\xd7\x1d;\xf6}'a\x00\x9b*\xfaf\xe7\xbe\x92\x1bl\xbf\x0d\xf1\xed\xd6\x8e\x12\xc6}-\x8cW[\xd1\xde\x07]=\x1d\x13W\x0d\xd8;#\xc5\xe1U^\x10z\x91R\x1c_aP\xfc\xeb\xbb\x9c6\xa2&\xday_\xf6\xa6\x0b!\xdf\x16\xc7\xce\x1cz\xec\xcb\x85\xcdc\xa7\x851\xd5\xf8\xec\xa3\xcc\x94\xf7t\xc8\xb0/\x9fq\x03\xf4\xc5L\xd94s\xb7\x89\x85\xf1o E\xe3\xdf\x12\xfe\xc6\xbfk\xdc\xce\xfe\xac\xd0\xfe\xddLI,e\xffvUw\x8f\x91C\x1d\x82\x83)\x84\x13\xbcXn\x86\x7f\x95\xb8\x17\x87\xed\x85\xf9K\x1f\x89\x15F\xfe\x18\xcee=\xbd\xce=\xfb\xb9MP\x0c\xed6\x93\xc4_\xbf?=#\xe1\x9f\xa3\xe4IY,\x92,\xfc\x99\x18\x88\x8a\x9cR\xd1JZ\x9e\x96\x8c\x1e\xa8Hy\x05!\xe2+ \x91\xd2D\x88\xe4\x9f\x86\xd8\x16\xbf\xe8\x84#\x0d\xaan.\x95-\xee\xceP\x7f7k\x87.\x83}\x7f\xed6\xccvq\xab\x8c'\xdc\x01\xc2+>t\xdf{\x11\xe6\x85\xd3\x06\xfe\xeav#q\x91]\x1d\x92\xbf\xdb\x8e7O\xb2\x03\x7f\xb60\xcc\x0d\xa4[\x93\x1d\x06\xbe\xee\x0e\x1d\xc7\xd8Q3\xa2\x14R\x8a\xe9\xe6\xb1\xba\x14u\x0e\xd3\x91\xa6\x94\xe2\xdf\x92Q\x01\x94\x0d\xb1\x14g\xd8J(\xcb>\xb6P\xbe\x84bn\xfe\xc1c\x7f\xf6}D\xf7|\xd2\x04\x00m\xfdk\x0d\x03\x11#\x03\x92\x96\xf9\xc2\x8e\xc9\x05\xf8\x14\x81\xf3\x1b\xbd\xda\xd6_\xaeQ\x056\xf3\xe6aT\x90l\x00|@}\x88\x18FE\x91-Q\xd6\xbdv\x1cG\xc1v8.X\x8b\xa2H-\xfc\x14!\xd7\xf2\xd3\xf0\xcf\xe4J\xbc\xa1\x84\xc2\n\xc3/;\xfd\xd0>\xe2?\xc8\x7f\xadt\xe5*\x99\xbfJV@o\x8d\x8a\xad\xf2\"\x12\x9f\x15\x0b&2\x7f\x92e\xfe\x95\x9d\xc1c\x18\xc1>d\xb0\x01#\x98\xc0\xa6\xe3\".\x18=\x82\x10\xbe\x82\xec\x11\x84\xeb\xeb\x0e$\xd3\x90V8\x96[\x9b\x86\xc7\xdd\xcd\xa4}\xfaws\xd9\x97\x155\xe3\xd3\xcb=j1\x8b\xd3\xe2\x98\x92\x8b3\xbf\xb0\x13\x87r\x93mV3\xd1^\xff\xac\xe0\xf7\xbf\xff[\xf2\x8c\x9a\x9a\xbdK\xa1\x82\xdc\x06W\x1f\x0f\xe3\xebVe\x91\xef\x84\x8d\\\x99\x81\xbd3\xd6y \x03+\x13%\xf5\x86\xa1Z\xa7GB\xa0\xd5\xe4E\x1d\xde\xd6\xc8\xd7\xe6m\xbev\x18\xf1\xb2\x12\x8f\xe3\xf6*#\xccK[\xe1\x9fB\x89\x7f\xe2\n\xff\x14\x1c\xff\x14\x12\xfe\xc9\x18\xfe\xc9\xe0+(\x1eAF\xf1O<\xcd\xba\xf8'\xd3\xe0\x9f\x04Ug\xb7\xc6?\x127E\xf1\x8f\xdfB/1\xc59]\xd1\x8e\xe9\x88\xaf\x84\xd7?)+E>gV\xa9\x8b\x07\x99\x0e\xa2\xa3MH\xaa\xa2\xfb*N\x88\x15u\x98\xa4Z\xa9\xf1P\xaf\xd4\xd8T)5X\xd1H%\xcdcEz\xa5\xc6\xd6\xef\xab\xd4\x10\xbfd\x91\x7f\xb3\xa1\xa7~\x14\x9d\xfa\xb3\xf7\xf9\xa4&b\x9as\xf9\xb6(\xd2'\xa8\x88\x8b\xd4\x15\xde\x12Lc\xf5u\x12\\Mj\xfa\xbcY\xe7\x90a#\xad\xfa\x92\x97?M\xe2\xc2\x0f\xd1\xdfL\xa3\xbc\x94:;\x08B\xf4V\xc8\xd55_\xa7\x84%\xff\xa9\xfa\xd6(\xe9\x12Q\xf1E\x18\xbf\x9f@(j}\xe6\x87\xc3\xb7c\xbb\xab\x9fKxI\x07\x90C\xbc\xbe\xec\xd8\xa6p\x8cUF\x14l\x91\xa8XQ'\xf1\xd1A\xb4\xff.%\xa8\xf5B\xc0\xedr-\xb1\xb8\x18*ex\xb7\x0e7\x0cI\xc9\xec\x8d_,\xba\xe5LJbU@TA\xa6\xa5\xb0)\x0b\xe7`\xaf\x15\x95\x1e\xb0:\x03\x9cH\xe0\xe9ul+O}J\xf5\xd0\xdb\xc4\x05\xebU\x02\xd5$\xda\xcc4\x9d'SI-\xfd\xb4\xa6-z\x94@\xda\x8e\x83\xf0\xbc\x03e\xe2yO\xae&\x12c\"\x9ekW\xdf\xdcb\\\xcd\"\xc6\xeb\xaf=\xc8\\\xc7\xaa\xf1\x81Z_|\x91\x91\xb9\x10\x13\xecc[0\xb9\xd9\xf8A\xcc!W\x16_\xab\xc6\x17\x99XI\xba\x9b\xf2\x00\xa3jc\xe90\xd5\x8c-\xf0=\x9bUR\xaaa\x02\x83\n\xf7LZ\n\x0c\xf9\xd1q\xd3\xd0\xbf\xf3\xa5\x0b\n\xfe\x94\x98\xd6\x12pX\x13\x98\x99\xc5\x01\xb8\xe4Q\x8f\xc8\x00\xfd\x86,s\xa5%)\x16I\xd0\xdbV\x8a\xee1=\xa2\x15q\x9e\xe9=\xc3\xd8t\x17r\xba\xdd=\x12\x99(J.\x8e\xb2\xab\xe7\xc5\xeb\xb2\x98\xb4\x8d9\xe5\xe7Z!<\xd0\xbdo\xbfko\xe3\xb0C\xcb\x8eY\xfey\x194uo\xa3Pu\xe7\xd0\xcb\xc8\x0e\xc5\x9d\x13\xf6\xdf9\xe1\xe7}\xe7d5\xf1\xa1\xbbu\xa4*\xdf\xd3\x85\xeb\xd6\x0b\x07\xdfNX'\x9e\x87g\n\xa8/\xab\xfb\xabb \xba\x95\x98\xb1\xf8<\xee\x96D\xec\x0ee\x06\x84GW\xa9b\x9c3\xac\x12\xe6\x07\x97dV\x16\x8a\n\xf3\x9e+4\xc5\xf2$~\xba\xf0\xe33\xc5\xf7\x01\x82\x8d\xf5\xd2\xcf\xde\x07\xc9E\xac\x92?.X\x95e\x12\x90\xe8\xe0\xd2_\xa6\x11QU;g\xd5:\xb4\xa1\xaa\xee\x12\xb85q\xc1\xe4\x01\x01\xc9gY\x98\xd2\xad\xb7*]f\xf7\xb3\xb3\xd6g|\xe9\xf8'\xe4\x02\x12\xefu\x16\x90\x8c\x04/\xfd\xb4y\xce\xe9ZG\xb4\xda\x99\xf7\x9e\x08\xe1w\x98\xe5E\x9bu\xa3\x80v\x05{p\x86]\xa8\x90\xd6)\xec\x81\x95\xe0)fw\xd3U\xcd\xef\xa3\n\xdar\x81\xc9f\xdb\xb6?H\xa2\\\x19n2\xbc\xf5(\xeb\x1b\xce\xf0B\xba\x97\xcc\nRl\xe4EF\xfc%\xbf\x08\xe9$\x98\x91k\xe4\x85q@._\xcfm+\\\xfag\xe4\x1e[\x88N\xa1_\x06a\xa2+<\x0f\x03B\x0bu,\xf0 \xdb\xd6\xe7qZ\x16*m\x03\x9f\xcb\x0c\xf6\xeb\x0b\xae\x85DOt7\x1d\x93f[\xf3\x90b\xecK\xf3;\xc1\x0e\xa1\x82V\x98t\n\xb5\xa3)\\lL;(.'\xd0\x8f*/\xae\"b\xb2^\x07\xf4\x1a\x880\x98\x07\x1d\x9d\xb6b\xf72\x026F\xeb\xdf\xfe\xf5\x8f\x96\x90}\xdf\x14\x07\x81\x0e:NN\xf0p\xea:/]\x88(\xc0\xdf|\x85\x1a\xbdfI\xba\xc1O\xb8v\xba\xf6\x17\xfc^p,\xe7#L7 iFf~\xa1\xdb\x0b\xca\x95\x0b\xbcQ\xd5\xa4\x97\x82\xfc\xb7\xd8\x0d\xd3\xf8nw\x88dj\xb8w\x9c\x12\xe1\xec\x1a\xa9\xb0\x06+\xab\xabta\x1a\xf6<6\xf2\xfeA\x98\xa7~1[<\x8f\xc3\"\xf4\xa3\xef9\xcb\xaa`J\xc4\xc3n\xff (\xf8\x12\xf1H\x13\x9c\xa0\x9f\x94\x05\x1b`\xc1\xbaz\x01\xb4\xcd\xc8\x9c\xde\x04B}E\xcehs\x13\x06\x8a\xcf\xe7\xb0\x0f\x01L`\xae\xffhU*\x15\x18\xa5\x8azu\x83\xfd\x86z\xef\x9d\n\x1f(\xa5\x1dZC<\x18p\x07\xc9 \xb24\x9d\xfd@\x05'yRf32\x81es\x04\x86\x83\xb2P5\xd3\xbbW5K>\x01_\xc1p\xcb\xfc\xf8\x04\xcan\x0dr\x99\xfaq\xf0\x8c\xa4\xc5b\x02#\x85t@\xf0\xdbJ\x01\x9c\x80\xda+a\xb8\x83$\xac\x02\xf8jA\xd8\x9c \xc2d\xe2WQ\x9f\x13&z.\xe4\\w:3Y\xfb\xa3!\x12j M\xd5\x15\x90\xd58B\x96L#\x06\xec\xdd\x19\xe8]\xe9 \xefz\x8c\xa7\x15\xe9\xa2\xad\xd2\x90\xbc\xc5\x14\xeb\x95\xb0\xaf\xad\x9e\x18g\xcc\x89\x9d\xee\xed\x05B\x98\xc8\x996\xedh\xd2L\x12\x03VJn\xf8\x17\x0b\x8dW-\xfa\xaf~\xb2\x19\xff\xd4\xd4\x81\\\xc9zS\x818X=f\xaf\xf2\x83\"i!\x04Y\xdbCQd2\x87Z\xd1nY\xbd\x8a\xd1\xc2\xcb\xd3(,l\xeb\xc7\xd8r\x86)\xd3\x15\xad\xc4\xf0\x186a\x9f\x1b\xb3\x11X\x87\x91\xe3\xfd\x94\x84\xb1m\x81\xe5\xc0:\x14`V\xe0\xf2\xcat\x10\xeaM\xa3\xb8\xaa\xa5\xa9\xf5\xc5\x06\x8d\x1d&/\xfa\xe5z\xd8\xb6\xa8\xa8\xf3\xe6=q\xdc4,\xb4#\xafF\x91\xb2\xe5#\xef\n\xf6 \xc5\xb7\x9f\x1b\xf13S\x918 /\xe8\x908!/\xe8\x908>/Pz\xbb\xcfT$N\xce\x0b:*\xcf\x88\xdb\xe9\xd6c\x9d *gf\xa0rf\x9f\x9e\xca1;e\xf6P9x\xa5\xbb=\xc2\x90U\xa1'L\xce\x18\xd3\xd3k\x88M\x9f\xd0\xcbI\xc1\xbe\xaa\xd5Hx\x06\x14gY\xee\xe3{?\x0b\xfd\xd3\x88\xa0\xc8c\x85\x0e\x85R;\xec#\xc8bn\xb3^(\xfa\xd3\x7f\x951O\xfc2\xcbH\xcc\xbf4\xd3j\xd5\xa4\xcfH\xf1\xa4(\xb2\xf0\xb4,\x88m\x05~\xe1o\x9c\xf3>\xfb\xe8\xac\xe6\xc2\xa9\xaf\x06K,\x8d\x05{\xd5\x8d\x82\x91pb\x83\xa9\x0e3\xa66\xc68AZ9\xd1\x97\x9f\xfb\xd1\x04|e\xf1\xb5f\x8f\xabE\x1f\xb4\xa3\x8c\xe3\xc0\xddd_R.\x97\x04\xac\x85\x8e\xe9/\xef\x04\xcd\xdc:\xdc\x00\xfa\xafh\x90\x08\xb4\xbd7T\x9cE8\x8c\xb3\xa8\\\x8b\x9f\x85\xc1\xcb\xa4\x8c\xdb\xc9\xff\xe0\xa32\x19\xdcB^\x0d'\xa4 \xbcH\xf9\xd3\x96\xebcZ\x08%>#\xc7\xcb,\xb2\xfa/^\x15Y\xd7Z\x8b\x1f\xc2(zKf$<\xc7\xcb2\x1f\xb0&\xbd\xa7|\xc8\xa2\xc4\xb2sJ\xdf\xc9^\x15\x1f$\x955{\xe3+\xf5\xdaS\xba\xaf\x1eqk#\xd0\xb5\xab\xf9\xceD\xc4\xd1\x15@/\x19o\x1e\xc6\x81D\xfc\x0d\xa4\xfc\niwyl\xc5F\xdf\xda6LF{h\x8c\x11Vdl\x0b\xb0b\x15`\xe9\x1b\xb3CVO`\xc9\xdc\xaa<>\xa2\x96:zu\xfa7\xb1[\xf3\xc5o>|\x80\xac\xc7\xb0\x11$\xac\xd9n\xa2\xf7Cf\x92\xda_\x0fqj\xa1P\xb7Zz\xe6\x0e\xd4\x08\xb7\xa7Ha\xb31\xf4`\xdf\xa9\xf8\xc4\x8c\xd3\xee\xfc\x98\x0f\xdc7\xcd\xe9\x1e `9\x98\xcf\xc9\xac\x08\xcf\x89\xf8\xd2\x88E\xd0\xfb\xaa}\x92{\xd5\x1d\xb2k\x94|\x92MgW{\x82\x06\x1e5\xb3\x04\x87\xc7\x14\xf4\xf2\xf0g\x0d\n\xe4c\xceo*\x14\x91\xd5|\xc2\x13L\x0d\xd8\xae\xbe\x93\xc8?%\x91\xb1\x9bE\xb1\x8c\xbeA%\xf3\x8d;aa\xd1\x8c\xbd\xd4\xea\x03\x04\xf0&y\xad\xeb0fT 3\xb7k\xda\xa2\x98\x00\xa6o\xe1\x13&p\xeb3\xa0\xe6g[\x8693:C\\!W\xd7\x03\xa7\xdb\xa8\xa7\xb3G\xf6\x8a\x841N\x8e\x905\xf5\x00\x1374\xbe\x0b\x88\xa3\xb4LY\x90`\x83\x8eP\xb7A\xd6S^\x0b\xde\xbd}1\xb1\x0c]7Dg\xa1\x9d\xe1\x8c\xb4\xb5\x17\xdb\xb5d\x8b\xd3\x0c\xd2y5|\xd8\xb4s\xd2Wk\xd89\xf9\xab\xdd\xa9}\xe0\xd5c\x89\x03z\x7f\x0d\xf1\x98\xce\x1a\xda\x06\xd4~\x1bC\xea\xf1\xdb\x95\xc4\xe5\x12\xcd\x11ns\x8e\xe9\xd3\xe2\xe8z\xaf\xf9\xfa\xec\x13\x13\xcfkZ\x8e\xc6\x14V@\x050`\xbf\x06\xa2\x03\xa8\xe2?\x92`B/\xf3\xbd=Hl$\xa6\xfa\xa9\x1c\x86\x1a\xfa\xeb \x9cc\xacH\xb1\x87\x89\xfaq`\xa2\x9fm\x88\x96\xb8}\x93\xe5\xa6\xb5\x05\xb9T\xf1s\xf2\xc3G\xccW\xa2\xcf&\x0e\x86\x83\x83\xb9\x91.\x0c\x9a\x16D\xeb\xf0Q[Ctj\xf4\x88[\xeb\x05\xee\x13\xbb\xce\xf1\xed\xe7&v\x8dtb\xd7H'v\x8dtb\xd7H'v\x8dtb\xd7\x88\x89]\xebQEL\xc0\xaa\x12\xabF\x9f^\xac:\xbb\x8dXU\x12\xac(\xa4\xa7]\xad\xadVy\xdc\x92Z\xdeJy|+\x11\xcf\x9dr?}\xbcM1\xc4)F\x19\xe9\xa3\xa6Q4\xb7\xa5\xeb\xb5\x10\xb2\xa5\x98\x81I\xdbMk\x1f\xa1w\xee1+\xa4p~\xe5\xd8\xed:\x15\xd2\x17\xb0>GI8\x962\x0fE4\xe5a\xf3\xe8\xe3\x9d\xb9\x8b\xdb\x0fYX\x90\xd7qt\xd5\xc0\xbc\xedG\xa7\xabp%\xb0\x1f\x0c\x08\x83\xa1\xb7W\xcc\xc0\x80\x96\xe9\xee\xaa\xd3g\x02\xd9\x85\x1f\x07\x11y\xbd\xea\x88[\xa0;\x14\xd0(\x10\xdf\xfb)O\xe2{\xa1W\x90\xbc\xb0\x0b\x16\xc0^\xb6\x1d\xe0yf`2\xc8\xa6\x00VY\xbe\xf6\xe17m\xaf\xbc\x91vlX\xc1\"9;\x8b\xc8\xf3\xfc \x08\x8b\xaf\x93K0$\x99\x91\x1f\x19\xbf\xb2\xb1\x0f[y\xe9\xdb~\xb9W(F5\x815\x8c'\xc0\xfe2~\xa7\xb6\xc0\x84\x1e\x98\xc7\xa46\x9d\x08W\xf2#\x8fE\xe1|!\x9e\x0e\x82\xd6W\xe5\xa7A\xa3p\xa4\xc3\xea\x14t'w{f\x1bV\xb2\xa9\x80\x15\xf8o\xfa\x08\x05u\xe3\x16\xaa/\xf1\xc1*S\x1d\xf6[\xdd\x02\x02V\xb1\x82\x001\x85\x16\x9e\xe0\xb6\x04\xf5\xdf_~\xa9\x9e\xaa-Ur\\X\x93\x1a\xab\\N\x18\x11\xd8\xf8\xb3\xd2\xeb\x0f@\x0b2d\xae\x8e\xf1o\xbc\xd4\xcf\xc2\xe0]\x1a\xf8\x85.\x08\xc2M\xd7X\xa2\x11\xf8*\xcbo\xb4\xeb\xac\xda\xa5;\x9a\xb2V\x10\x05+\x1e\x86a\xeaxXA%\x0f\x15ie\x88\xb6\"?\x99P\x9f\x0f\x101A\xa5\x9f\x1fx?\x86\x98O\xce\xfa\xba,\n\xb3c#p\xba+\xb3\xad#rY<\xc9\x88\xd2\x15M~JV}\x11\x9e-\xa2\xf0lQ0\xb0\x9a\xf4T\xe1\xee\xab\x97\x9ef\\zz\x13W\xe0\x81\xd2\xd3\x94U\xcc\x0c\xa3@\xf2\xad\x8f\"\x1f\xaa\xf0\xd5SK\x91M\xcer!9\xee\xd9'\xc7\x85s\x13\xa3a-vk\xab\xe7*o^`\x19XS\xbfo\x99fC\xe6%b\x11\xa8\x82R\xf4\xcf\xe9\xc6c\xab|\x13\xf8\x94\xdfqH\x9bX\xb8Rz\xfe\xb4\x15\x01\x15,\x17\xce\xf1_\n\xa2\x06 \x83y8\xbd|\x1e\xacd\x17\x0b\x9ck 3\x12\xe0\xed&\"b\xf6~\xc5\x08\xa2\xfa\xe0\xf5\x7f\xd1q\xae\xe8\x91\xc7\x00\xdb\xbb\xbb\xdc\xbc7~\x9e_$Y\xb0\xf2\xe6\xfd\x11\x9fO\xb1w7\xdb\x0d\xbf,\x12z\xddG\xa4\xa0\xbb\x12\x93\x8b\x8d\x94\xcfu\xc0\xd7\xb1\x08\"8\xf8\x0b\x0ea+|q\xf3\xdd_\xe8\xfdkz\xc2z\x88\xa7\x07\xdd\xe7C\xf6\x85>\x84^\x9e\x83,\xe4\xa1\nf\xda[\xd5\xe0\"\xc8\x8a\x0dF\xf4\xda\x12\x11\xb6\xe4\x94\xf8\x19\xc9\xf8\xbdj\x82\xf7\xdf\xe9\xc6\xc3\xe1\xdd\xea\xca\xbb\xf1u\x87\xd7B\xf0\xd9]u7\xba\xe6\xee\xf6\x8ac\x16\x89\x16.\xcf\xe7\x86\"\x87_m\xab\"\x9c\xbb@6w\x81h\x86#\x99\x01\x08\xc6\xe8\x7fl\xda\xa9a\x08\x81,\xfb\xeb\xd4\x11\xab\x12\x0c\xf6\xfe\xed\xd1\xd1\x1b\xccLK\xe2\x82\xcbR'P\xc6y\x99\xa6IV\x90\x80IR\x08\xa5\x97\xac\xffh\xc1:\xa4\xb0N\x7f\xddN\xfc[\x0f\xaf\x16\x017W8\xed\xb3e\x919\xf6.{\xd1\x002\xb9)c4r\xc6\xab7-\x98\xf4\x1b\xcf\xb4\xab\xccLH_+D\x0b\xb5\x1e\xd5$3c33\xf1e\x95\x82\x92\xaf\x1d\xcf\xe9\xc3\xc4e\xfd\x02$w\xb3\x00\x9d\x99\xa8\xb2\x92\x1b\xb3\xbe\xd1;'O}J\xe3\xd6\xab\xa7\x96\x1e*s\x9d\xd1\x01\x9d\x99\x00\xca\xb4\x9cd\xc8r2Q\xbby9\xd9\xc5=h9\xd9\xeau\x86l\x17\xd5\xec\x15\x06\xb7\xf54\xe5\x15\x87\x9e\x94\xbf\xe2\x11\xa4E\xefT3\x96g\xbe\x17r\xe2\x95\xa7*\x0f\xdbp\xdbK\xd0\x90\xd5\xd0\xa0\x1fL\x15\xe9G\x0d0tM\xb4k\xa9r\xbc\xfa\xf4\x07q\x05LT-\xa7j\xe4\x03\x82\xc8\x19h;\xe5)T\xc7\xa9Q\x07\x8d\xcb\xebxn\xd2\xd5\xe17\x12\x08B\x87\xa0\xba\xbd\xfa\xf2ws\xf6MZY~\xfbp\x03\x85\x82\xde\xaaYGW\xa7\x06 \x96\xf7\x95R>k\xf1\x80$\xa1\xe7\xbc\x8d+u\xe5;pKo\xea\xa2\x11[p\xb8;t\xdb\xa1\xba\x9eT6(\xc2\x9b\xd6\xa3Z4\xa4*U\xef\xfe\x8d\xe2Yw\xe5J\xffhB\x83\xed-\xbd\xd4`\xab\xc3\xd3\x87UQ\xc7\xad\xd9\xaf\x8a\x1e\xe8d\x07\xdb[\x0fu\xd2\x83\xedme\x8ckV\xf4yX\xf2\xc9\xfb\xd9lHX\x8dHym\x9aSyR\x16\x8b\xe7\x05YJ\xb9\xc7\x9b\x15\xea\xec\x0c\x93ZR\xd0\xacR\xa7\xa26\xa6<%3\x1e\xb6\xd0\x9ba?\x98\x90\xeb\xeb\xab\xe7\x01\x89\x8b\xb0\xc0\xa06b\x08\x7f&W\xa8*\xc2\xbe;\x8db`mQ\xf5i\x12\xe7\xe5\x92\xe4?0\x01\xd1JB\xfb\xdea\x17\x8aa\x8b\x0eQX\xe0\xd8Ek\xd0\x9a\xe12_\xcf#\xfft\xd0\x00\x05\n\x97\xd2\xf2\xb1\xbc\x0f\xb0\x8f\xd1\xe0z-%\xea\x0f\xbf\x0f\xf3\x10\x85'k\x9bj*\x8d>\x14FN\xfd\xd9\xfb\xba\xb2:\x1c\x14\xa2QK\xd4^uP\xdd^\x0cCR\xcd\xc00(FO\xab\xd7\xde\xec\xc2\xa5\x98\xbbzT\xca5U\xf6\xa8A\x1f\xf0\xb9j9\xf4\xbb04z\x04\xd3n%\xf1Qv\x95\x94\x05:\x07\xeb+'\xbc2\xf3g\xee\xa9\x1cr\xbd\x99X{}M\x96\xe5\xd2\x8f\xa2\xe4\xe2(\xbbz^\xbc.\x0d\x96P,\x87e\xc1\xeb\x1d\xc4\xfei\xa4\"\xd5\xc4\x83\xf1\x1f\xbc\xb9A\x0b\x12\xad\x10\x0e#\xa8\xebb\x1ag}\xcd\x05\xd6\x1c\x18L\xf6\xbc\xaa\xdc\x1b\x1fv\xc9\xb6`H(\xd9\xb3\xaa\xea\x80!\\UZ\xce\x97\xa8\xc5\xd4\xd7<\xad\x06\xfb\xc6\xa8\x13=a\xdd\x0b\xad\x8e\xbe\xe2\x05\x86e\xaeQf\x8f\xc3\xd8\x01\xab. \xa5?\xd2\xc8%\xfb\x80\x07\x85;BZZ_\xfb\x90\xd5~Z\xa1\xca\x1e\x0f\xb0\xa7\xac\xfe\xdb\xdaM\xbc\xef\x8b\xf7\xb0\x07%\xa5m\x0c>\x7fO(Q\xe5\x859e\xbe\xf4\xb5^\xc3\x1e\x9c0\x16ArS7\xcd\xee\x0d\xec\xc1\xa9\x97G\xe1\x8cP\x9c\xb51rx\x82\xef\xc6\xf7F\xe5\xdf\x8dS\xad\x1a\xb4oZ\xcd\xcd\xc7\xe8\xacO\x05w'}\x0eP\xf5\xdd\xb8\x9f\xd5\x838T>~\x155\xd3\xcc\x1c\xac\xfdX# \x02\xc5l\xc3\x82,\xc1\x82u\x9e}\x8b\xd9\x93v\xae^\n\xf7\x96\x8f\xaa\x1b]2S\xc3\xca\xac\xa0\x13\x1c\xa6\x04\xd5\xf6\xc4#2W>F\xf5ZQv\x86\x1f\xba\x9a\x9er\x0c\xd9x?\xd1~J\x83\xf9h\xdb\xd9\"\xb9\xfe17\xb3F\xedR\xcce\x17\xcd\x9bu-\x1c\x98\x06J\x18\x0d\xa2\x14\x8b\x88\xa7A3\x193=6H1]r 9K\xb3\xf1\xb4\xdd\x02*\xe5\xf5\xaf\x1b\x1e\x10r=\xf4fI\x19\x17\xf6\xad\xceD\x0b\x1c#2\xa0cmg\"7\xcf\xb0\xee$\xc4\xb8zO\x14\xe7W\xa0\xa6\xaf\x96\x0d\xa8\xb3\x18<\xe2Y\x12\xc1,\x89N\xd8\x85\x03\x8d\xdd\x8aN\xd0IK7\x13\xeb\x15\xbap}\x8aq\xc8nO\xda\xe1<\x93}\xa3\x1c\xe3\xb8\x1a\x99\x94\x06\x99P\x82\x8c:%\x9f \xee7\x9fV]\xbd\xf4S/\xcc_\xfa)\xf3\x17R\xd8\x1f\xd2\xe7\xda\x0e\xa5\x8e\x07&o\xd2\xcd\xe7\xa2\xcf\x8fh\x1e\x1bc\x95@G\xcaj\x88ZB\x1fA\xc1O\xe0\x94\xd1\x80}\xd9\x84j\xb6g\x02\x06\xfe\x80>\x99\x7f\x81W\xe6\x04z\xe2T\xa4\xac\xd6\xa2F]?\x84\xc8\x82\xf8\xb5|\xc9\xbe\xc2\xf4%\xc6v\x98\xdb\x94\xec\x94h\xae\xdf\xcc\x04\xd4\xe7\xa3#\x7f!\xa4H\xf2\x97-QV\xff\xbaK\xb2t\x03\x07%jsNo\x02\xe7}\x8b)\xb8\xb7 \xf4\x04\xd7\xaeBEN\xe0\xbd\xb6\xa2.^h#;\x1c\x06\xd8\xbb\x0b,\x7f\x13\xe31m\xc7i}\xdd\xbfJ m\x90o0\x01\xcbj\xdc\x9bm\xb2\xe6\x8e\xee\xad\x8a\"\xab\xef.\xb8\xcbY\x1e\x1a\x07\":\x9f\xf0\xb0\xe2\x98Z\xb2K\xb8\x1a\x0e\x8a\x8c!\x14,c\x1f\xc1y]-\xf5\x13\xdb\xa1\xa4\xe2\xeb:t\xab\x9e9\xb8\x93\x95\xff\x87d/oJ\x0f\xd7\xe0}\x82w=\xa3\xda_\xd7r\x01\x8c7\x80; \xfd\xa9\xbd\x81\xb9$\x03#%\x1a \x83\xa6\x87\xb1\xae\xda\xa5iN\\\xe6y&\xe2\xfb>\xade4\xdc\xff\xe8\xccmk\x8a\xafL + y\xf2 \xf05\x10\xe9\x00\x1c\xef=\xb9\xc2\x1b\xdfH\xa8\xf3\x8b\xa1_\xd8/\x9e\xa5\x97\x93\xe2mg\x06\x03r\x1c\x8bh\xf8fd\x0dm\xdcn\xacmr\x0f\x1e\xc6\xfeI\xd1<\xf9\xd2m\xa0\x06Zw\xcaM@r\x93\x83t\x17\xb8\xf1\xa9\xd1,\xb7Blo\xf4+\xd2\x08\xfc\xf8zP\xbd\xef[\xe0\\\xbd3\x01s\x9d\xf8\xa1/\xf9\xaf|i\xaf\x06\xc1\x03\xdc\xdc\xb5\xa6T\xedG\xa85W\x9be?\x84\x03W0\xcck\xea\xdb\x8e)\x0f\x19C\xe3\n3D\x9d\x12\x0f'\xb5\xe5sY\x0dr\xc0\xa9\x84\xd5h)\xf1\xf0\xc3\x9c\xd0^\x9f\xc7L5\xd4\xfba_\xa4\x90\xc1\x88g\x95 ~Fh\xa7F\x97\xab_\x03Z|t\x03\x8bo\x95\xa5\xf7\xb9\xe8M\x1dD\xb6%\xa9\xe9\xcb\xb5\xd4\x12\x01\xf5Uoi\xb8\xba\xda\xcd\x86\xbe\xac\xab\x92\x95\x94\xdb\x13\x98\xd6!SZ\xf1h\xe9\xaa\x06\x06\x1b\xaf\xf3\xcf\xd0\xa8\xc6e\xa6\x0b\x1d\x03\x16\xcc)\x95\xc1\x1e$H\xecdM\xd3\x91\xccl:\xd2\xf4\x93k\x81\xac_[\xe8\x89W\xab\x98)\x0e4\x94SZ\x83\x85\x83\x84\x9a\xbaZ\\?\xadod\xe9G\xea$\xedyq\x15\x11\x9de)%\xfb\xcf\xb2\xa4\x8c\x83\xa7I\x84\x19\xdc\xff\x7f\x0f\x1e\x9e\xce7\xb7\xbb\xf7t\xeb\xe4\x19\xc6\x92fj\x19\x9dL\"\x9c3\x1bx\xab\xdd\xa8E\x17\xdf\x92O\xfegj\x0d\xd6\x03E\xd9\x10(\xd2\xd8K5\x0dj?\xcf\xe9\x07\xdax\x16\x81\xce\x18.\xd0\x19\xc3\x05:c\xb8@g\x0c\x17\xacf\x0c\x17\xa8\x8d\xe1\x82\xda\x18\xae\xebd\x93r\x0f\x81-\xa5\xb1[\xf0\xe9\x8d\xdd\xcc)\xfe$c7\x15\xed'\x19\xbd(L\xde:\x9e\xc2\x83M\xdbn\x95Q\xf8\xf31\xbf\xe93\xae)jO\xe0\x1es\x11JPO-t\xde\xd98M.\xadc\x03}O!L\xeb%\xcc\xd7i\x8d\xf9M\x88\xe0\xc2\"\xeeX\x9a\x91\x99_\x08i\x80\x1dsI\x8e\\\xc0.\xd7>U\xda0\x86\x8e\xcd\xa7n}\xe3\xc2\xcf\xe20>3\x89\xffE\xdd\x89uW|e\xec\xfd\x94\x84\xb1m\x81^\xe8\x91\xe8{J\xbd\x97t\x16\x1d\xfa\xf3\x97kW\x86\x01\xc3Pd\xb9\xb9\xc9\xb6\x88\xa4\x94#5d\x0b#\x97\xa9\x1f\x07\xcfX\xbd\xbaoOzO\xcf\x9b:\x01\xd4\xcd\x1c!\xfb\x1c \x19_\xa6\xbf\xb3\x16\x9f\xe75\xf4\xef\x0e\x1a\x9f\xad\x83\x86\xc15C\xaf\xa8\x890\x91c\x97\x89\x02~\x93\x87\xde<\xc9\x96\xbe\xa2_\xee\x92\xc1\x03\x9a\xab\xfd1\x84K\xd7\xda\xde\x1eD\x18\xd9\xfb4\x8c\xfd\xec\x8a\xbd\xc1\xecB\xd6\xa9\x9f\x93\xddm\xf1F\xef\xa9\xc1@_\xef\xd2\xa0\xf4\xe4\xe0\x01\x12\xe7\xa12\xdd\x90\x84\xeaJ\x1eS\n\xf6\xc1\n\xe3s?\n\x03\x8b\xc9\xe0\xbbm\x86E\xd4\xfc\xa2\xd4\xd4\\E$\x9a\xdbU\xcaK:\xda|\xba\xa9\x08\xd2\xaf\x90\x07\x04a\xce\xd9\xdc\xc2\x0b\xf3g\xfc\xaf\xe6a\xf8\xcch{\xb7\xca\xbd\xdfL\xef\x0duR~\xe1\xe8\x9e+\xde\xd5u3\x92\xa7I\x9c\x13I\xea\x01R\xa6\\\xcd\xebJ\xde\xc3\xdbnEN\xd2\xb9\xcb\xc6\xf6}\x05\xd6\xd3\"\xb7P\x8b\xdc\x8c\x84R\x15\xf0\xacP\x06<\x8b\xab\x80g\x94\x88\xccX\xc0\xb3\x0c\xbe\x82\xe2\x11d\xeb\xeb\x0e\xc4\xd3\xac\x19\xf0,\xd3\x07<\xab\x15\xf0&\x92\xadJzwx\x95\x17di;M\xdb\\\xfc\xeb\xbb\x9cN\xc7HW1Z\x96\xd9e:v\xc6r\xbf2j\x96\xad8?\xde\x0d^L<\xad\xdb\xf6\x0f\xdd_\x8a\x8d\x0c\xcd\xd1J\x854\xb6\x80}\xc0\xd4\x18\xcd\x06\xacc`\x81t\x9b/\x95x\x0e)\xd5\xe7\xb1\x1d\xf3\xec\x05-XW\xc0]kl\n\x03\x88V\xd3Sag\xfa\xcc/|\x8b}\xe22\x85\x03\xcbZr\x8c}\xb78YWw\x18\xee\xaa\xffn\xe3\xa6\x81\xa8N\xeb\xdd\x8d\xa4\xd3\xba~(j\x84\xd2?\x14q\x1eT\xae\xcc\x98\xb8\xa1\xbe\xf0\x84\x0f\xb3\xd6\xc9:\x91P\x9b\x9are~\x00Ul*\xc59\xc6\x80\xa2\xfb0\x0d\x11|;s\xc2\x98\xcf.\xc4\x02\x94\xf5\x15\x9a\xe7\x0bH\x94\x13\x15S\x8b\xbc\x96\xa6\x9d\xa2\xdb\x8ei\x1b\xb3a{\x93\x0f?\xc8\x9f\xc9\xa6\xc4C6\xc5\xbc#\x03\xb7#6n\xc7\n{\x11W\xaa\xb4\xcc{\x9dq\x17\xf5\xd4\xb1\x1d\xe5\xd6t.\xed!\xfb\xe3Br\xbb\x9d {w\xc6\xef\xdb\x99\x84\xc5\xddeq>\xf7k\x84\xe2\x9b6\x8a%#\x17\xa8G_M\xb5e\x08Mn\x9d\x82\xa8\xa7\x89G\x9de\xa3\xb4}\xa2\xbcrl\xdah\xac\xd9\xb6\x81\xb1\xbai\xeb\xa5\x97\x914\xf2g\xc4\x8e\xc9\x05\xbc%g\x07\x97\xa9m\xfdb\xc1:`D\xc6k\xcb\x05\xeb\xccr:*9\n\x11\xa5\x04\x1f\xf8\xf3\xf7\xa5+\x95\xca\x8e\xd2\x8e\xedqG\n\x1a\xf2\x92Q'4\x0fSX\x8c\xb7v\x95T]\xf9;\xb2\xac\x14\xfb\xfer\xed\xb6\xa5\x82\x99\x0b\xbe\xf7\xee\xcd\xb3'G\x07'\x87\x07/\x0e\x9e\x1e\x1d<;9}\xfd\xea\xe8\xe0\xd5\xd1\xc9\xd1\xdf\xde\xfc\xfbZ\xaa\x88\xe0\xd5\x16\xf5\xf0\xcd\xebW\x87\x07\xbf\xcf\xaa\xeadR\xaa\x98\xac=\xeb\x91\xb8\x10\xeaH\xf1U\x16\x84a\xaf\x93\xef\x9f\xbc}\xfe\xe4\xeb\x17\x07w{du$\xc4 \x0c\x16{\xef\x89\xc2\xa8\xc5\x17K\xad\x069 \xef)\xef\xfe\xcc\x85\xd0H\x11b\x05\xe3V\x94.\xf8\xcd\xf5\xcdnq%\xd72\x8fQ[\xbd\x97\xf0\xd7;\x0f\xa4\xfb6\xa1\xcb\x82y\xf4\x92\xec\xc0\x9f-l\xbdh\x01\xe9>\xef^\x18\x07\xe4\xd2\xfb)gr?-\xd5Gw4\xb1U1\"\x88G.\xd3$+\xf2)#\x80R?\x9f\xf9\xd1S?'\xdf\x84\x11\xa1\xdb\xe8\xd8\x85s\x8c\x1b#.\xd1}\xe9w\xdbAH\xba~\x07-\\loo\xefR\xb2H\x8c\x03\xd7eg\xb43\xe8k\xc3\xb2\x0b\x1b\x8d\xad\xb1L\xd0\xd4\x11\xbd\xecU\x0c5*Z#\x93\xa6W P\xdfd\xc92\xcc\x91r\x89\xed\xed\x9d\xfb\x8e\x0b\x87H\x91\xd7\xa65^^\xf8Y\x91\xff\x102\x0dIlo?\xd8\x1d4\xc3\xd8~8FM\xef\xc3\x07\x9dU\xda\xde\x19\xd6F\x1fpno?TB\xe7\xf6\x8e\xca\xc0%\xb6\xef\xb7_3b\xef\xfeHZ\xe9\xe6H\xc7[\xf7\x1d\x1b\x05n.X\xf8\xaf\xd5\x83\x87P\xbbt\x82\xd2;\x9b\x08'\xb3\x13\xda\xff\xa6\xf8\xe3=ES\xf5~\x18\x92x4T\xa6'\n!|\x15\xac\xe0Da\xd7\x18W\x85\xe1\xfa\xba\x12{\xac\x11\xdcTxL\x19\x94J\x9cm\xd7s\x10\xa2\xb9\xc4\x1e\xa1MzB\x0f\x9bE\x0f;\x8b\xd3\xc6\x8d\x0cYZ\xd9\xfa\x1d\x992\x99C\xec\xe2O\x89;\xbav\xab\xcah]\xf3D\x08*Q\xd7\xc0W:\xb3Y\x17\x0e\xfe\xac\xabg\xb6E\xe2\"\x0b\x890\x9co\xc3\x8f\xbc~\xf2F\xca\x0b\xac\x8e\xd0\xd8\xfb\xa5j\xaf\xf9*\xaaP\x17\x8b\xb9\xda\xdd\x93 \x89)\xdb\xb2f\xa6\xfdoy.F;\xeas\xf1\xb0\x1d\x95\x91\x1d\x8b\x87m\xc1\xb6\x8f\x9c\xc6#\xe9,\xeflb4\xf3\xd8\x1e=tl+,H\xe6\x17\x98CV\x0f\xbb|q(,\xd5\xb3k\xa1\x82>y\x1b\xa9\x11\x11\xc6\xef\xf6U:\x9e\x98\\\x16\x142Gn;u\x00\xed.\xc4\xb6)+\x0b\xcf\xaba\xaf\xb6\xdc\x12\xc2Q\xdf\x86[\xbb\xeau\xdd\xd5\xe2\x95\xedm\x07\xf6\x95\x9coHr\xe81@N\xecv\xa2\xa1Jk\x10\xbb\xb8y!\xaa\x07\x90\xda\xadT\x079S\x16\x94\xf0\x18\xf2G\x0ed\xde\xdc&\\\x182\xcd\xd7\xd7\x8f](\xa6q[\x08!\xa8\x8c\x9b.\xd8\xfd\x91\x9a|\x18\xa9!q{g[\xb3duw\x1a8\xab)\x0e\x96wFGQ\x94l%\xf4q-#$9\x84\xcaES U\xa3\x14\x1c#\x05iBI\x1cv\xa9\xc2\xda\x9e\xde\xb5\x117\xed\x11D\xf0\x18f\x8f\xf46\xc0\xb45\x9bne>\x9d\xad\xaf\x1f;\xb4\xcd\xd2\xa9\xcdU:\x1f2\xe1S\x7f\x970[_\xef\xe9\x16\xaf\x87\x19\x841\xe4Ho\xe4\xd3\xd91\x0b+\xea\xd4r\x0f\xac\xf2\xe1\x03j\xa2\xaak\xe5\xcb/a\xa3\x19\xbbhE\x1c'a\xb3]\xd5\xa9{\xe9\x17\x0bo\xe9_v\xc1\x88\x95\x84q\x1f \xe9\x11\xba\xcd\xb0\x0dq\x1c\xf8\n6a\x9f\x9e8X\xa7C\xdc\xa4\x97 C)7F\"\xea\xf9P\xac\xbds'\xc0\xaf\x83\xfc\x10\x83\xb8SHbD\x9eM k\x0d|\xb3#\xa2\xf3k\x8dPp\xc8\x0e\x88B+\xc1\xc6\x94\xe3\xda}\xf8\x009%/\"\x14\x87\xf1X\xb4\x9c\x9a\x9d\x80\x8dr8o\xb6\xf0\xb3\xa7I@\x9e\x14v\x8ek\xbe\xb33~\xb8K\xbf\x0d\xe11\xec\xecn\x8d\x1e\xb2\x86\xd6a\x84\xe0\x87\xb6\x04\xb6\xdf\xf9\x98V`\x0d\xecn\x8d\xb1s\x9f6p\x7fk{\x8b\xf7\xcf\xeacGt'a\xc2\xdf2/\xbd\xdc\xc5N\xc6\xb4\xcc\x87\x0d\xde\xcc:\x1d\xe7\x06\x1f\xd4W_\xc1h\xd3\x81u\xd8\xdd\xd9\xd9\xda\xbd\x1b\x08\xef\xdc\x1f\x1c vu\xd8\x90\x02\x8b\x83\x12e~\xa5\x0d\x8a*\xdc\xbd7\x90\x19\x13\x1f\xb6\xc4\xf0\xc5\"K.\x802\xef\x98%\x1dO\x80\x05a\x0eqR\x00R\x00\xa7\x11Y\xd3X~dv\xc1\xa2\xf0\x11g\xc5sB/\x81\x07\xc88\x8c\xb7\xb7\xf1\xdf\xed\xdd\x87\xec\xdf\xfb[\xec\xdf\x07\xfc\xfd\x83\x9d\x0eg\xb1\xbb\xe9\x08\xaefHg\xbd\x84\xd4\xaejgd\xd2(\x99\xc6\xf6\xe8\xbec[E\xc2N\xd5\x91\x7ff!\xdbi\xfdlQVn\x9d\x82\xfc\xda\x1eX\xd3\x04o{\xf8\xf9\xd8b\x0c\xd7\xfd-\xc7\xe6\x14@\xed\xc9\x00UCV?mU\xb5\x89\xe9j\x90l\xa7\x90i\x1dK\x1ah\x0c\xa94d-\xe4\x85\\\xa3\x1c\xfe\xa6\xc32\xac\xd8\xa3\xcdQ\xbf\x0d\xf5}:I\xb5(\x9f\xae\xe3\x03\x87Y\x1e:.X\xbe\xd2\xfe\x10\x83ik{i\xf7\xd6)l\x99\x088\x9e_\xaf\xc1\xa0\xf9KDK?\x11\xa2\xb8;0)\x0d\xbb4\xc4\xd5\xf8\xa8s\x0c\xd5z0Le#\x9d\xc3*\x02\xb6\xcdTG\x02$\xd8\x86d6\x13U\x89\xf3U\xf5\xa7\xd2\xb0\xe9\x1bE\x1e\xe5\xf5|\xf56\xd7>\xcep\xdb\xf8\xc6z\xea\xc7\xff\xb1\x80Y\x12\x9f\x93\xac\x00\x0e\xe9E\x02i\x16.\xc3\"<'\x8c\xcdZ\x95\x9a\xef;\xf3\xdb\xbbm\xc91\xc3\xc6\xe3\xed-%\xcd:RJ\x15Z\xec\xd3\x03\xc1>\xdd\xff\xef\x99}\xd2\xb0\xa5\xdb\xbb\xea\x95\x1dw\xc48>\xc7\xca\x94 }~p\xf2\xe6\xed\xeb\xa3\xd7\xed\x80\x15e\x9b\xdfo\x16\xb7\xc5\x01\x9d\xf58g\xb9+\x0b\xde\x15E\\\xe1<3D\xc6@+\x0c-5\x84$w\xe1\xa1S\x90\x17\x84y\x1a\xf9W\xf4v\x88\x93\x18\xf3E\xdb\xe3\x9d\x11\x9a\xf5\x938x\xba\x08\xa3\x00Y\xb7\xc2\xcb3\xcacX?\xf9\xe7>\xf3\xe9\x9dXU\x16J\xee\xfb\xf7C\x18\x07\xc9\x85\x17$3\x14\xa18^\x92\x92\xd8F\x18\xb9\xc8\xc2\x82\xd8\xd6W\xec\xd3\xc7\xa2\x8a\xf7\xcd\x1eC\xd1_\xfdx\x8f\x17\xa1j\xd7\x9bEI\x8e\xe9\x0ds<\xc1\xdf<\x82lc\xe3\x91\x03\x01\x89HA \xaf\x01i\x1aN\xb3c\xbdMYn\xb7`H\x8dI\xf9E\xc1,8)\x9dfD\xad\x889\x95tF\\F\x11J\x90)\x15g\x97-x'\x0ecpcrA\xf9\xbef1s\xff\x8aYZ^\x82\xa6g\x98\xd5\xc2qei\xab\x90p%v|+\x9a\x7f\xa46\x1e\xec\x9c\x08\x0e\xf9\xdb\x0f\xf4\x94\x1f\xbd\x98\xff{\x90\x1d\x8cF\x0f\xd4d\xf1\xb8\x8d\xa0\xb9\xf0`w\xd7\xb1\xd7\xda\x02\x075\xca\xb8\xc1\xfd\xce\x97\xa8\xe4\x84t\x17\x17\xe0\"u_Sfiz\xacX\xf3\x98\xf2\xd5\xa5\xc3\xa4\x04>\x8a\xf31%<^\x9b\x91\x88,\xa4\xf8\xf0\x11\x14BX\xcb\xf7\x03\xbf\xa3\xa8\x01w\x83\xb9\xa8\xfc\xa7\xd0\x8e\xb0\xb5\x0f\x1f\xea\xd6\xd4[\x14\xddt\x8b\x1e>\xd4\xac$\x83N\xdb\xfa\xd9r\xd0\xd5\x82\xd2\x81\xcf\xf3\x83\xb8\\2\xbe\xc1\x96`\x18L\xe6\xd1\x82\xd2=\xac\x93\x83\xd0s\x8d\xe6;y\x1a\x85\x85ma\x8e}\xde!\xb9\xf9 \xed@\x95\xd0ti.\xa7m\xdd\xdc{'\xd3\xe0\xd6\xff]T\xf5\xdf\x92\xa8J\x83\xb2\xb6w\xdb\xef\xc3\x01\x94\x8c__\x94\xd5\xc5e\xbcN\xcfH\xf1FT|=o^\xab\x1aX$\x02\x9d\x01fp\x0e\xf1dMQ\x1b\xad\xa2\xf0)\xa9\x90\xc4y\x91\x95\xb3\"\xc9\xd0\xe4 \xc28/\xfcx\xd6-\xddo\xfe-\xdd\xbe\x93\xe6g\x1c\x0f\xec\x83\xdf6\x00_q\xfdw\xb6nz&9\xfe\xc8V\x17XT\xf7'g\x1f(;P\xb1\x0c\x0f( \xcd\x98\xca-\xc7\x15\xde\xf0[\xfc\x82E\xc6\x80'\x8f\xb5G\x9bc\xc7\xe5>\xb5\x94Z\xc0\x83\x1b\xb5\xb8\x05\xf6\xaa!kp\xd1s6\x17\xba\xb3\xa0\x13m\xe1\xe9\xe1\xe1\xdb2\"/\xc2\\\x11\xec\xe0\xe9\xe1\xe1!%M\x9f\x91Y\xe4\xb3x\xd3\xdd\x80 O\x0f\x0f\xd1\x14\x817\xd1.\x8dB\x12\x17o\xc9\xacP\x97?{\xfd\xd2X\xc8\xe6\xa2->J\xde\x93X=\xf8g~\xe1\x1fe~\x9c\xcfI\xf6\xbc Ku\x1b\xdf\x84\x91f\xe4\xdf\x1e\xbd|\xf1$\x8a\x9e&Q\xc4\"P\xa9\xab\xf4\x95\x7f\x93dK\xee\x85\xa4\xae\xc0\x9c%\xb4U^\x92 \xf4\xd53|\x19. e\x89qs\xbb_\xbe\xf2\x97$x\x95\x04\xe4\xa5\x9f*J\x93@\xb3\xebo\xfc0\x16\xe1O\xd4K\xf3&*\xcfB\xc5|\xd9{\xcdp\x0e\xbf\xff\xd3\x0b\xbc\x8a\xd4m\x1e~\xff\xa7W\xe5\xf2\x94d\xda\xe27\x98%X\x03\x0b\xb4< c\xcd\x80\x0f\xbf\xff\x93 \x90\x0e\xbf\xff\x13\x83\x94$\xd3\x80\xc9!f\\\xfb\xba\x9c\xcf\xb5\x03\xa4\x07\xe5pAH\xa1^\xd5#rY\x1ce\xfe\xec\xfdS\xddQ\xa9jh\x8a\x93rV\xad]Ur\xed\xa2+zb\x07\x945a\x94\xf89|\x05\x0b\xc1s\xc2\xf9\xfa\xba\x8aZ]\xba\x18\xc9~1=W\x18\xbcQ&4\x98\x9e)JN\x91\xacW\x95\x9c\xc0\x1e\x9cR\xa4\x7f\xaa\xba\x90\x80_\xc5'H~\x9e\xd0\xfb\xf7\xc3\x07(\xed\x13\x17f.\xa4\x8e\x0b'\xd3y\xfdn\xee\xc2\x19E~\xd33\xca\x80\xa5.\xa8\xe2\xd2 r]\xd2[=s\xe0d\xba\xc4\xcfC\xfa\xf9\xd2\x85l\xba<\xae\xc5\x9b0\x14a\xf7\n\x804J\xcb\xed\xfbj\xbe\x03\x11w\xe3\xbd_Q\x94:&n\xbc\xbd\xfb\xefv%\xff8v%z\x82\xef\xbec[e\x9c\xcf\x92\x14\xbdU\xda$\\\"\xfc\xf5T\x07\xa6\x123@2\xcd\x8e\x99R`\xe7\x01\x1a\xaff.\xfc\xa2\x97\xf6u\x98\xfaiv<%\xf4\x18\xc9\xf6\xf0\xca\x99\xe8$\xfeF\xd8\xfb\x0c\xed\\\x84\xb1\xa9/(\xa9\xf1v[\xc2\x92W\xc4V\xe35\xa7\xb0\xc6\xaa\xb8%*\x8d\xcf\x9c5\xdf\x16\xd4\xb0p%\xf7\xb7[\xaf\x03\xdez\x1b\x85,8\ni\xd7?\xe7\xef\xdb\xf6\x10K\xd6\xebN\x1b\xb5\x9c\xf1\xf7[\x8e\x97\x93\xd6\xba_\xb1\xb6\x1elvb\xe1\x9dr`m\x8f\xea\x84\xb7\xd6\x1e\xd5\x05\x7f\xdf\x1e\xd5\x01R\x9a\x95\x8c\xbeYx\x89\x85i\x96\xccH\xde\xf2D?\xc4\"\xae\x98k\x16=\x85=\xb0\xf8Gx\xceg\xf6e\xab\xd7\xf7f\x89\xee\x13\xb4\xb0\xdd\x83So\xde,xM\x0f\xc4\x9aY\xda[dW\x1a\x9eW\xe0\xc8C/#y\x12\x9d\x13\xbb\xbdz\xf2\x83\x1e\x1aM\xf6g\x8f\x1ea\xa1\x1e\xccS2C\xfcr<(\x1b\x96x\x88\xfd\xde\x85\xf7z\xd6\xf7\xba\xcb\xd2\x83d\xc7\xf0\x14\xfdQU|\x1c\xdf\x8b\xb7\xe4'F\xd9\x1e\x9c\x93\xb8p\x98\x0fK\xb1 \xb1\xfd\xde\x919\xb4\xa2\xd3\xcd5\xcc\xfcb\xb6\x00\x9cCK\xf9\xd6\x06\xbf7\xbdsF\x15\xb5V\xa8\xbcf\xaf\xa5\xf4\xbb\xe6d*m\xb5\xcd\xe21\xd0a;8\x85\xe6h[\xe0r\xd4\x87\xed@\xe8\xb9\x88w\xa2\x95\x88\xd02\xc4\xb7\xea\x0d8\xe7\xb6\xcb\xc4;\x99\xa9k\\\xe95\xaa\xf2\xd3\xe0.\x89wr\xcex\xcb\x11`\x8c\x9a\x93\x9c\xb1\x97\x9b\x8c\xb5\xac\x05K}p\xc5\x85\x995\x02M`\x1f\n/y\x0f\x13(\xbc\xb9\x1f\xf6\x84@\x87*A\x14?\x1c\xfd\xd5#^\x9d\x02\\\x7fm\x9649H\x96~\x18\xab\x17P<\xfa\x13,?%\xa5?\x124\x1b\x19\xf3\xb5[PP\xf9 \x89)\xfck\x0fF\x8e+\xe2\xff\x94H\x81\xec\xa1I\xb5\x8d\x81*f\x1e\x89\x0b\x92\xd9\\\xa7P\xda\x19\xf2\xe8\x98\xa1\xd8#\x97aas\x06\x7fm\xd3au\xf6\xd0\x1b\x81\xdbX\xefCd\x1f\xd8\x16?w\x1b\xb3\x85\x1f\xc60\xbb\x9aE\xc4B\n\x08Ma\xde\xd8\x14\x82\xf7!d\xda\xd2\x18\xfdK\"Z\x9cc\xc9\x04\"[\x91\x1dP~\x1a\xe7\xb2wYp\xfck>\x9f\x1f\x9fDd\xf7\x84\xdf\xbc6\xe0#\x88k\xd9t\xf8\xc8\x01\xdf\x8e\xa7\xe1\xfaz[9 ?\xf4\x90\xa0\x90\xdc\xad\x8e\xd5\xc8\x05\xd42\xaf\x89}z\xa9\x1b\x93\"z\xe6\xb5\xe9\xf8\xbf\xec\xc5Egl\xf1s\x03\xfd,\x1eD[(\xc4\xe5f\xfbxB\xb5\x13\xa5[\xfc\xbc\xa3\x80\xa9J\xe7\x14\x08(|\xc0C\xe0\xf0\xa3c\xea\xed\xa7\xde\xdeV\x85_54\xca\x80U-\xfa\xb7l7,\x01S\x05\x87\xa9\xaa\x02\xdf.v\x0b\x9b\x92u\x0e\x00'\x01J\xf4L\x0d>\xfa\xc6\x9dz\xd5\xbbv\xc2T\x8er\xaa\xddu)\xbc\x93\x00\xaf\x10\xfcA1\xbd\xcb\xd6\xa0\xf0N.hA\xe1x'\x94\xa2\xa7d\x85wB/\xc81\xfe\xf2\xc5W\xccG\xfdd\xc6\xed\x0d\xe9Eqd\x17(\xc40\x8e\xfc\xed\xb0\x91\xbb\x15o\xaeV\xf5\xac\xc5\xdeI\xa0\x03\x86\xb8\x9e\x14*\xcd\xf9\x9c4\xd7\xaf\xf9\xda\xa5\x9d\xb1\x1b\xb0:X\xf5\xe5\x073\xb4\xec9\xa5\xa7\x19\x89\x87\x00\xc2\"'\xd1\\\x97?\x8f>\xb8\xceo\xd0\xbcj\x7f(\xf1\x04\x12\xaf\xde\x7f\x17\x9e\\L\xc0\x90l\xb1\xaa\x16h\xd3\xb2\x8aGC\x95\x8bg\x18\xc5\"\x0c(\xe9}\xfc\x16/\x98\x11\xde\xcd\xaf\xf8\xef\xbb$\x03^\xb1\xbe\xb2\xde\xc0\xdb\x86\x9b\xdf\xa1wL\x05\xfe1\x03\xff\x11\x85\xef\xd8\x855\xddx\x87\x8d\x93\x8f\xcf<\x91\x01\xfb\xd7\xb3w\xd7\xda\xf9w\xe7\xdd\"2\xea\x1d\x7f\x8dg\xfd\xd0x`\x17<\x82\xe7\xa1\x0b\xe2PX.X'\x0b\xcbq1\xd4\xa9\x0bY\x9d\xc5\xbau*\xd4\xe0Cl\x04\x13\xd6n\x05)\xe2\xcf\x16r1.\xfa\xabf\xfe\xec\xe6\x97\xd5_\xd7.\xbb\xc4\xf5\x93d\xd2>A\xd9\xb1\xbf\xe4\x9b\x97\xbd\xc9e f h?\xfc\xeb\xbcSy!Wf\x84b= \xa7i\xdeco?\x189\xf6\xa1l[\xdb\x1e\x1f\x89\x07\x84\xfa\x17\xac\xdc\x13{)v\xcd\x9cS\xfc=\xec)\xd9T\xa6\x7f\xc6\xb3A\x19\xacf\xad\x9a3G\xba\x97br\xce\xfd \x19C\xefb\xfe\xe7\xa4\xb5&\xb3*\x07U\xb5\xc6\"Y\xcc\x89\xdf.\xcbi\xd9\x11\x9f\xc7\x1a\x05\x93Xp(\xcd}n\x9e#\x04\x97\xbe(v\x92\xc5\"\x13!\x88q\xeaa\x88kG{\xe5\xd41\xb9\x80\xecQ\x17\xba\x04U\xc8n\\\xfa\x86\xdf(\xa8'}\x8b \xd5GNU\x84Z\xe6=v2\xb0D\x86\xe6SoNwy\x88\xb2\x98\xe0\xcdv\x88\xdb\x89?}JA\x93\x0b\x16\xf4m\x82\n\xf5\xc6$\xe7\xf6\xdc\xfb\x13\xac\xc3\xdc\xfb\x01\xff\xff\x0d\xfc\x11\xd6^\xb7\x01\xf2\x8d \x8a\x0e\x1b\x1f3\x13S[\xc6\x15\xdc\xfe}\xec\xd8\xf2+\xa6v\x90L\xe0Y\xc7\x87\x8d.%|\xd3\x9e\x1b]\x9e\xbeM\x16\x04\xd2\x13\x15f\x02I\xf4\xb4\xe9V\xdc\xbe\xc3\x14\x16j@\xeb\xacS=\\\xbb\xa4+\xbc\xf6\xda1\x8e\x1a\xf7\xbbo\xd8|T\x17v)\x0eG\xb5o\x870\x81>\\\xd7\x19\xda\x9a\xfd\x9a\xc9\xeb\xb7\x1fl\x99\xa2\x85\x1ez\xcc\xea\xd9\xc3\x13d\xbf\x97\xc1\xc24-?\x8a\xfa\xa6$\x93\xaa\xea[\x8fa-\x9d\xf1\x10\x8b\x86`\x14\xdf$\xbc\x8a^d\x13\x0e\xe7T\x05\x1e\x9d\x1a\"4\x03o\xd2\x90$\x1f\xb8~m\xa4\xa7\xb1\xce).\xa7\xd7\xc8p9\xeb9\x0f\xb6\x14\xae\xaf\xf7S\x80\xe8!a\xe8\x1f\x90\x98F\xcc\xcbP =\x9b\xeb\xebn--\xa3\x10\x81(r\xf8\x08\x01;\xa6\xa4E.\x88\xf4iy\xcc0\xdf\xc6\x062\x18\x99\x1d\xf7Q\x85Z\xa6\x198\x98KM)\xeb]\xeb\x8f|\xe8\xa1-Ub\x87\xde\xf9\xd0\x8b%\xf3g\xbdg\xf7\xae\x00]\x0f\xc5\xc9\nP\xbc:luw\xbd>v`\x90\xe6i\x93\x08jw a;\x90\xd9\x89i\x07$\x14\x84?o\xa4\"dB\xaf\xf6\xd4\x91\xc7\xb4\x1b\xb6]\x05\x8a\xed\xb9\xaasmo\x0f\x98\x84\x07\xc2\xb8f\x0dk\xa7\x8f\x18\xd6\xc1\x9a@\x18\xcf\x92,\xa3\xb7u\x18\x9f'34K\xd2\xb9\x9a\xdd\xdc\xbe\xb8\xa3\x02\x14z~\xb5;\xf7\xf6}\x95\x9f\xbc\xc2\x86\xbb\xe4f\x01m\xcdc\xce\x9bi\xdb\x02F,\xb0W\xe3\xdd\xac\xe5C\xc2u\x1c\xa6\xdd\x98\xbb\x90\xaa\x08\xa8\xc0\x85\x85\x0b\xe7\xae\xb0\x07Ia\xbf_2\xd4Y\\\xf1\\\xa30Ze\xff|\xc5|Fq E-p\xeb\xd4;E\x13\x96\x0e\xdc(I\xe6\xb3\x9b\xfa!\xa20\xd5>sT\xf3C\x9dJ\x802|a\x9d\xe0<\x82\x00\x1e\xc3\xe9#8\xd5Y\x9a\xa2\x95\xe9\x92\x07\x8c\xbd\xb2}\x9b2#dzz\xecL7\x8f]XLG\x18+\xf0\xca\xc6wN\xed\xa7\xba\xc4\x9f\xb3\xca\x0cu\xd9<\x8ej\x13X\xa6\xf7\xc1da\xdcq\xea\x11\xaca\x97\xe7^L.\x0b\xdbq\xbc \x89\x89\xc6\x1a\xb7\x1alb\x9f\xbbp\xe5\xc2\x82\x07\x82\x82b\xd8\xd0\xae\x1d\xef\xeb\xb7\x07O\xfeL\xc9ezq\xbd=8z\xf7\xf6\x15\xec\xc1l\xb5C\xb6\xd3o%-\xe07\xe90\x90JFW\xe0:\xd8\x87\xc2\xa6\xf7\x14.\x7f\xcc\x97\xbfh_\\\x15\xafk\x8c,I<\xd6\xacB\xe6\x87\xe0'\xe1\xaf\x90\xa1\xd8\xb0rhs\xdb\xfa\xc6?4\x7f\x0d^\xab\xae!QR\x1b\x99Hf\xa0M@7Y\x98\x0c3\x1f\xe1+*\xcd\x11\xaf\x11;cv3L\x8c\x87\x86W\xd3\xe4\x98\x0b\xf5n&:\x8d\x1c/a\x98\xc3NuY\xa1f\x0b?\xf3g\x05\xc9\x9e\xf9\x85?Q\xba\x94q\xfb\x9c\xde\x85H\xbd\xc0/\xd0j\x8aNe\xde\x03\xdfJ$\\\xf5\xa1\x9a\x85'\xde\xdc.\xd0TOA\xf0a\x82\xb4\x12\xb9\xe0\xaeK\n\xac\x1aX\xa5\x90\xe3M\x88\xa7u\x14nLo\x18\x89\xfc\xa4%U\xed\xde\x7f\x82Y\x9b\xde?\x9ef\xc7m,\x1br\x16\xae\xef\xec'M3y`\x13`,\xd4\xac\xd3q H\x04\xe3\xaaB:\x1d\x1c\xc5\xd3\x12t\xfc\x01\xb8\xf3C#t\\fg\xde\x1bX\x87\xcc{kP1\xcd\xc3\xd8\x8f\xa2\xab\xa1\xd2w\x9f+\x8d\x93*j0\xe5\x88\xc5\x1f\x1a\xd1{\xacSr\xab\x92\xd9\xb4\xd5\xc7\xb1,\xa7\xd4\x1ab\xf3\xcfJ\xcchj;m\xbd\x8a\x89\xcc\xeal\xb4\xfc\xa8\x8c\xcb(\xebF\xa9\x8b\x8f<.\x86`V\x1b\x96^u\xf9\x11\x81\xb7\xebP\"\x02\xf7l\xb7\xc0\xf1\xd0\x00\x88E6\x18\x08\xf1\"\\\x84\xb9\x01\xdcB\xa5}\xad\xd0J\xc7\x1eACwn\x0b0\xa9\x953\x8e\x1d\xa3\xd2\xa4_M=dAc{\xfb\xc1}\xae\xa5\x7f\xc0\xff}\xd8\x8cj\xc7\xc3co?\xe4Q\xed\x1e\x8a\xf7;\xfc_\xfe\xfdC\xfe\xfdC\xf6\xfd\x0e%G\xf0\xdf\x11\xffw\xcc\xff\xdd\xe2\xffn\xf3\x7fw\xf8\xbf\xbb\xfc\xdf\xfb\xfc\xdf\x07\xfc_\xde\xde\x88\xb77\xe2\xed\x8dx{#\xde\xdeh[\x19e\x8f9\xdb\x0eY\x8b^0\x1aw\xc2x\x87U\x90J\xbc\x92\x9f\xf2\x10\x8f]\x94(WJ\x02\x82\xfe\xc1-\xc8CD\x88\xe6\x04k\xcc\xd0}\x84\xf1V\xaa\xa0\x19Ul\x91\x0e\x82\x94\x1b\xed\x83\xd0:o\x9f+\xb4\xdc8\xe9n\n?_$\xed{\x0c\xbeVL\xc0\xa2\xc2\xed\xc1z\x9d\xc8\xcf\xc78; \xc5'\xa3\xd1h{4\x1a9\"v>C\x18o\xfd\xf8\x8c\xebH\nYG\xe2\x03\xa6\xb3\x84Y\x12\x10H\xe9dtv\x96\\i]\xc0W,\xba%\xecc4 \x0cy\xca\xa2_\xae\x83m\x17\xb0\xb1\xc7\xca\x1dx\xfc\x18\x10~\n\xf8\x0f0\xda\x1co\xc3:\x8b\x99\xd9\x9b1\x17$\xfc\xcb\xb3\x0c[\xb7\xc3a\xbd`\xa6\x8b\x1b4\xda\xdcR`+\x0dPd\xfe\xc5pP`\xb15\xbc\xcc\xbf\xe0LiX\xcbnM\xe0A\x81\xa7d`\x12\xc3c(\x1f9\xc0-\xb9x\xe4\xd6bZ\xae\xaf\x1f;\x18F\xe2+&kiV\xa8\xc1\xa6<6X\xab\xf9w\xb3\xf4\xea\xeb\x83\xe2\xacM\xc7\xb6\x8a,\\Z&\x85y\x9b\x9bV-\xaa`\x059\x15\xb2u\xbb\x01\xf7\xc2\xca\x8e&\xd6\xdf\xa6:\xbc\xd4\xf6\xc3\xf6{\xba}\xd6\xd4\x82u\xf0YD\xce\xaeXS$\xdb\xfa\xff\xd3Z%\xff\xcf\xfac\x9b/\x8a\xea\xaau\xa5/\xda\xb5f\x03\xb8o\x90\x85\x12\x8aT\xb2\xc0\xc7\x1d\x0e#S\x04k\xb2\xe6O\xc9\xb1\xcd\xbc\xf3~\xfb\xf5\xff\xf8\xb7\xff\xc2\xe2\x9d\xf2\x9fX\xa6l\xe3Zs\x8b\xd3\xb5I\x98;s\x89J\xbe9\x86\xe3\xed0\xca\x807\xfe\x97_\x82\x9dLcZ;GWnA\xfbR\x94_\xca\x07\xb9e\xf9\xd2Z\x809\xec\xc1\xcc\xa3\xb0\xda\xc7\xa0\x81\x04\x8er0eT\x05\x8e\x803\xef6\xe1jE\x96]-w\xc1\xc2\xbc\xeccM\x85HTh\x11\x1ej\xc1\x82Z\x0b+\x8fT\xaem\xfdX\xfc\x18\xffx\xfe\xe3\xfc\xc7\x0c\xfe\xed_\xff\xeb\xff\xf5\xeb\x7f\xfd\xd7\xff\xf3\xb7_\x7f\xfd\xed\xd7\xff\xfc\xdb\xaf\xff\xc3o\xbf\xfe\x8f\xbf\xfd\xfa?\xfd\xf6\xeb\x7f\xf9\xed\xd7\xff\xf9\xb7_\xff\x97\xdf~\xfd_\x7f\xfb\xf5\x7f\xfb\xed\xd7\xff\xfd\xb7_\xff\x9f\xdf\xfe\xf3\xff\xfd\xff\xfe\xfa\xeb\x8f\xe5xs\xfc\x00\xff\xff\xf0\xc7rN\xe6sk\xc8\x19\xbb!M9\xde\xde\xc1(n-vF\x8f\x91g\xe2\x8a~\xd2{I\x0b\xd5q\xafm\xf3 $r\xc3 \xea\x02\x8a\x8d:\xe1%(n\xb1,\x8f\xc4\x01\xe6_Q1x\x14\xc8\xe9\xa7[\x8em\x89z\x96\x81\xa6\x11u\xfaVJ\\_\xa1X*\x17\xe4\xf6\x95\xe76V\xdcg\xf0\x18F\xb0/\xa5#\x1e\x1d\xd7\x06\xcc\xcaV2\x96\xf1\xc7\x1c\xd3\xacl\xe9Iy\xee\x1b\x11\xf9\xddN\xd0\xe493 \x18~j\x0d\xbc\x82O\xc7\xcdM\xe1\xd1\x0f\xb3DM \xf7\xdc)a\x03\xeaK\xbbd6\x15\xf9\xef\x02O\xf7\xc7J\xde_\x06\x8d0\x9eEe\xc0\x82]\xe8@C\xd4\xe9\x03\x8d\n\xed\xff\xa7D\x02\x8e\xba\x07\x0fS;\xbd\xc6\x08\x91\xab\x80\xc3\xed\x0ecc\x99\x06\xe3\x8e\x8c\xa4\xc4/&x\x83\xef:+v\xd9\xb7_\xa3\x91\x96\xb6\xb8\xa9\xb4\xb8\x0e\xdcO\x99`\x05x\xa3\xc0E\x91\x89>\xe4\xf1P[\"S\xf48\xe5a\xfaC\xd8\xdb\x83\x11\xdc\x83M\x05Ca=M\xca\xb8\xa8\x1d\xb7br\xe6\x17\xe19is\x12\x0f/\xc9\xdd\x0f\xbd(>\xc9\xd8\x93\xb8\x98%\xd1\xc78\xb2\xb4i:|\xd1\xfc\xc7<\xb6\xb4\xaf<\xfc\x99|\xbcY\xf0\xd6?\xe6$\xc2\xc2\x8f\xc2Y\xbe\xd2\x1c\x86L!\xfc\x14\x80\xb42\xf2\x19\xb4\xfa\x88\xf6\x17\x19\x99\x7f\xe4\xa5\xcf\x97~\x14\xad4\xfc!\xa3\x17\xad~\xf4\xc5\xa7\xef\xdf\xaf\x06\xfc\x83\xc6/\x9a\xfd\xf8\x13(O\xef~\xf4\xe5'\xc1\xfey\x99~\x84\xa1\xa7w4\xf4\xd8\x1e\x8d)\xb9\xbc\xf4\x8b\xd9\xc2rad\xae.\x0dfZ\xd5S\x8a?\xd5k\"\x1e\xc1\x19\x10\x93\x921\x91e\x0f(z\xa8\xd2\x99\xc5\xd3B\x9f\x19C2\xafO`_\xd8\xe11/\xaa \x9a\xc0q)o\xecL\x8bc!\xc8\xcf:qA >\xbe\xe1jrQ\xa3\xe5\xc2\xf8\x06\xeb\x99)<4`\xd0\x92\x86}K\xea7\x964\x93\x974\x1b\xb8\xa4\x12?\x91a\\\xb3\x04W\x95\xbd\xe1k\x19:,N\xd3\xdd\xadhN\xfc\xec\xdf\x01\xf4\xee\x963\x8d\xc2B \x9e\x1d\x03K\xfd: \x0dGl\x8fw\xda\xbe& D!\xdd\xd7L\xef\x86J\xb4\xae\x90\xc4\x9a\xa1\xf1\x8a\xe5\x9f\x9e\xce,\x9ew\xe2\x9e}\xea\xfc\xf1\x9eC\x99\xe3\x0f\x1f`\x1bu\x1e\x05\xc9\x8b\xba|\x7f\xe2\xdcsac$\xc2:\xd1zc\xac\xe7\x9f\xca\xb5|lH\xaa\xc4\x1a\xf3\xea:\xde\xbeC\xffkT\x92\xcb\x1d[*\xa3\xdc;-\xaf\x8a\xbd\xfd\xaaP\x05r\xe7\xdc\xf7Y\x12\xa8\xde\xb3\x9d\xfd\xfd{\x1e\xb9$3\xdb\xb2\xe8\x1c\x15P3DO\x02\x92\xad\x9a\xd0]\xaa\xe3\x06@\xd3'gOx!\xf14<\x95%\\;\x95\x8a\xfc\xedZ\"\xa7_\xab\x83\xe8\xe1\xe8\xd4\x9f\x9d3K\xff\xdc\x85\x08\xc3T\xcfY8}\x93\x93z\xc0B}\x86gq\x92\x91\xa7>\xc6\xf6\xb3B\x0b&\xf4\xda\x83uZ\xb6,\xa3\"\x8c\xc2\x18\x8b\x96\x8d\xa22\x0eQ\x11\xbf\x0fV\xd9(\xc8\x8bp\xf6\xfe\x8a\xbe\xbf\xe2\xef\xf5CX\x98}\xe4\xcf\x9b\xbbY\xc0>l\x8f\x1fn?\xdc\xbd?~\xb8\x83\xe6\xfe\x8f\x1f?65\x80\xd1g\xeb\x03O\xbc\x1c\x83\xa3\xbb\x10\xc0:Xg:\xfb\x01\x94\xfea\xd0\x06t\x8e\x90Z`J\xce%o\x876\xf2\x85\xbd\xbf\xf6\xe3\x8f\xb9c\xb9\x10\xa84\xd4\xd5\x83\xfe\xeeK\x06\x8b<\xbe\xe7\x9amG\x18y\x0cE\xcd\xb0\x0e\xf9t\xf3\xb8\x82\xf0\xc7\x80\xf1\xd5\xec\x94\x07?\xe12\xa5\x85+>p\x1c\x17\xd6\xd0\xb6\xbf!\xf1\xc2\xa4!\x9b\xc7\x95F.s\xcd\xe4O\xe3\xc1\xa9\xcf1.\x01\xcc\xe1\xab\xae\xe4{\x03\xc6\x8f`\xbe\xbe\xee\xc8;S\x8b\xd8\xe6h\xe8k\xe3\x8f=\xa5D\xbc\xf1\\;nw\xf0|9\xbe\xaaC0\xa2]\x00s\x14J\xe9\x07l%F\x0e\xcf.!-\x1b\x8b1\x1f\xb9\x90V\xad\xee\xc1\xb9\xe3|\x00\xbec,\xa3O{\xfb\xe8\xa0\xeb\xc1\xc19\xecC\xca\xcb6]8\xc7O:#hY.3\x8f\x06kS\xa0F!\xd3\xdct\xa4\x15\xb3\x07a\xb6\xe6\xa5\xd9FW\xb0\x0f\xd3c\x98\x08\x1cT g\xdb\xdc\xa0Z\xcc-\xd1\x08\x1a\xa2\xeb\x06d\xd5\x8d\x08\x01\x89\xac\x8ak\xb2*\xeb\x90U\xb1\x8a\xac\xcaV\xa5\x03\xcc\xf2\xfa\xd4\x8e\xed\xedQ[\xec\x9c\x88\x92q\xbb$\x14%;\xed\x12\x9f\x97\x8c\xee?h\x17\x95\xbchgk\xb3]\x94\xf3\xa2\xadNO\x11/\xb9?\xden\x17\xcdz\x03\xf7U)\x98\x88wrB\xf2\x97IPFD\x97C\x14$\x99\xff/\nW\x10\x8c\xbb\xc7r\xe2\xe9B\x99\xd5\xf9\xdex\x0c\x86v\x8a!o\xe1\xe7\xaf/b\x91\xbe\xb5\nC\x17s\x95\x0d3\xb6 \xdd\x84oP\x83\x10&\xa6\xf3\xcb\xa8\xe0\xa1\x99\x9a\xa0A7e\xbb\xb3Ts\xae|q\x1e\xfd\xa1z/\x96\x0eR-\x8b\xdaY;\xcc\xf4<\x18Y\xa3.E\x92\xd6Y0\xde\xdd\xd9\xdd\x1c\x05-E\x1b\xbdv\xad-o\xf4\xc0\x1b\xb7J\xe8}j\x9d\xfa\xf1OI\xab\xe0\x8c\x16\x1c\xfa\x85\x0b\xe3\x1dxR\x9e\xc1xs\xf4\x006\xefOv\xc6\x93\xf1.\xfc\xe9\xe5\x91t\x10\x86\xe9\ns\xb1\xf4\xde9\xc9\xf20\x89s\xbc*;/?|\x80_\xae]E\x89\x97_\xf8gg${\x17*\x9d\x97x\xb5 (\x02\xdd\x9e\x85\xc5[r\x1e\xb2\xf2\x85\xb2\xfcY\x98\x15W\x13\x08\xba\x85\xa7e\x18\x05G\xe1\x92\xe4\x85\xbfL'p\xd6\xad\xb2\xf4g\x8b0&\x93v\x0c\x85.\x07Ph\x1d\xaf\x82dy\x12\x06,\xcf\x94\x1ao\x06\xc9\xf2U\x12\x10S\x95<%\xb3\x89\xde\x88*\x8b&J5,/\xccMMG\xfeUR\x16\x13\xb0\xbe\xf6s\xf2\x02\xff\xd0\xb4\x14$\xb3\x83\xcb\xd4\x8f\xd9r[Q\x98\xebj.\xfd\xcbg,\xf5( \x8e\xfc3c\xff\xf30*Hf\xaa\x81\xe6\xa4~\x91d\xefp\x9e\x8b\xa2H\xf3\xc9\xbd{IL)^\x01=^\x98\xdc\xab*j\x86\xc5|\x97r\xfdB\xce\xca\xbcH\x96\xfar\x9eO\xf5uJX\xea\xaa\xe7A7\xa9N\xab.\xcfz\xf4\xac\xd4%\xbb\xaa\xea\x13\x92\xbe\x08\xe3\xf7a|\xa6\xaf\x94\xb1\xd6\x9e\xc7\x05\xc9f$-\x92\xacOc[\x7f\xc9\xb0\x97\xb2\x82f\xba\x19\xc9\xd3$\xce\xc9'\xea._$\x17\xe8\xd3M\x02\xbejj\x073\xa8q\xeb\xcb$ \xd1[\x12\x07$\xc3u\xb3\xc8\xa5\xbfL#\xa2\x83`\xe9+\x04\xe5\xe0\x19I\x8b\xc5\x04\xb4{R\xd7\xcf\x87|@\xa7ppY\x10<#\xb9~\x1fi\xbd\xa7\xc9r\x99\xc4\x83j\x97)\xc5\xc3$8,O\x97a\xc1\xa2M\xe4\x13\x98Zg\x04\xd5.i\xc9\xfeIr\xfc\x97e\xd1\xa5\xbf\x92\x94nU\x8e\xfa\x01\xe2\x07X\x89\xcb8\xad\"\xf3g\xc4\xd20\x9eiFrR\xd0>\"\x81\xb0u51C\x17\xad\xa9\xa9\x10\xc6a\x11\xfa\xd1!\xddX\xfd\xd1\x9a\xc7\x86c\x99,\xd3$\xa6|\xcb\xa4\xed<\x05jp\xa2\xfc?%\xd3\xe7^\xeag99D\xb9Y'M p\x82\x89x\x1c\x057\xf1:OF\xac)\xa5X?\xe5\xdd\xf8b\x8d\x1c\x9b\xdeq\x05\xd2\xde\xb1\xa2\xb7+\xed5\x91_\xe5\x05Y\xaa\xc8\x08\xf1T\xd8+\xf5\xf8\xcfU\x0eW\xb5M\xa9\xc7\xf7V\x03kl\x9b\xda\xb3\xd2\x8eJ\\\x1ff~U\xd4J=\xf6K\xdd\xb7x\xc4\x95\x90z\xec\x97\xb6\xb2f\xaeP\xdf\x98\xc6~X\x1d\xdd\xc5)\x1e\xbc]S\xaf\xcc\"\xfd84;\x01\xa9'C\x7f\x97@V\xc4&\xe8\xfb\xa4\xa2\xa7O)=\xdd\xaa\xdd\xfa\xbbEZ\xdb\xa7HRK\xfdS\x15\x9a\x078`\xb2\xdc#\xa5\xc0\x86\xb0\x073\xc7\x85\x13/'\x05\x1bCn\x97\x8e\x0b\x17\x02;=\xc1\x99\xe7^\x94\xf8\x01 0\x8fI\x9d=\x9d6\xb5\x16\xd3CE\x7fZ \xf2\x84\x16KQ\xb0\xe9BX\x8f\xb2\xc4y3^p\xd3\x85\xa4S\"%|ck$:.\xd3\xc0/\xc8\xbb,\xb2-\x0b\x07\xd6-|\x91\xf8A\x18\x9fQ\xe8/s\xdb\xca\xcb\x19\x06~\xd1\xd4>L\xc9\xcc\xa6\x83\xc8:\x83\xc0d)\xcdo\x82\xe4\"\xa6s\x07\x0c\xea\xc1g\xaa\x1d\"\xd6\xe8\xf4+\xda\xe0\xc5\xe8\x81#6\xc0\x81\x0b/C\xd2\xa7\xde\x14\x17\xac'i\xaa\x93\x97V\x91J\xb0\xfeI\xa8\x0d\xcd\x0f\x1c0s9\xb2\xc6\xdfK\x92] \xf8\xab\x9b\xd0\x8bR\xab\xe1\xe5bXj4\xc9\xa3\x89P\xe0\xc0T8\xbceL\x06\xd0x\x89`\xf7\xe1\x03\xf04\x1e\"k\xc7\xe1\xfb0MI\x00YM\x07\xc6 \xfc\x0bk\xe5_ \xc9\xf07\xfd\xf8_\xe0\xc2\xcf\x11\xed\x87\xf3\x90\x04\xbau\xe2x\xe8\xa2\x8b\x18\xba\xe7\xeb\x92bB\x0e\xf2L\xa6\xc8~\xbf\xcb\"\xa5\xac\x0d\xe5\x98\x8dM\xee\xbc\xa0G\x9b\x9d\xa8\xaf\xaf\xdeq\xb0Y3\xd6\xf8\xf0\xc1\xd8\x82\xe2\xfa\xc6K\xed\xb2;\x1d\nlo\xc92)\x08\xfb^M\x81\xab\xd8\x90\xd4\xeb\xbeU}\xa9`)\xe8\xa7\x9d\xd7M\x1c\xec\xc2\x01fb\xb0\x8d\xf3\xbc\xa4\xd5\\\xb8\xa0\x87\xf1@r\x03\xba\x96\x91,\xe9\xa5E\x1c2\xe1\xd8\xde\x19=\xe88\xf0\x8ev\x1c\x8f\x8b\xfd\xde\x93\xab|HC\xf5\xcau\xac\xa0\x99\xb6\xf5\xe1\xae4\xe1\xd8\x1e\xef\xdcwx\xbaM\x03\x95\xd1631\xbb\xed4\xb3s\x03\xacnX\"/C\xb3\xa3J8\x18\xdb;\x9d\xc0\xb0\xb5pq\xd2\x9fb\xb3\xb3\x03\xdc\x83\x1b\x1d\xbe[\xfbp\x7f\xdb\xf1\xe6rL\x94!-\x0e\x9cD{\x9bn7\x89\x9d1\xf3\x07\x1f\xdd\xe7~\xe4c\xeeW>\xbe\xaf\x04\xaf\xc3\xab\xe5i\x12\x0di\xbb\xd7J_\x9d\x8e\xb7\x13\n\x83G\xe9m\xe7\xb2\xe4\x913\xda[\xca\x83\xf4\xee\xb4\x83\xf1\xf2\x19\x8c\xb7\x1d\xef\xcf\x07\x7fk\x96\xb1\xd4\xa1;\xed\xf1\x88\xcc\xa1\xed\x011\x81\xf6\xc3vX\xa1\x94{\x87\xb4\x8d\x13x\xea\xd0\xb6O\xc2\xa2\x82\x94\xe6\xfbs\xfe^\x9d9tg\xdc\xae/2\x87\xb6'\xcc\xb2\x86n\xb5G\xc3R\x86\x8e\xdb\xb5Y\xc6\xd0N\xdc\x87\x0b\xbe\x9a\xed\xb9\x1e\xb0%h\x8f\xf1\x92Wo\xcf\xf5\x90\x8f\xbd]\xff)\x1bL'X\xca{\xb6\xe5\xed\xd7O\x04Bj\xbe~\x0d{\xf0\xb4\x9d$\xf4\x0d\xec\xc1\xfb\xf6\xcb#\xcc\xfb\xd9z\xf9\x12/\x08\x06\xd7\xcd\x92\xe7\xd5\xd5\xd1|\xff\x13\xec\xc1sJ.<\xafQz\xb3\x06\xbd`\x02\xdb:Y\x84A@\xe2\xb6\xca\xff-+-\x927Y\xb8\x0c\x99\xbfM\xb3\xc63\xd4\x03y)g(\x9f\xe7\x07q\xb9d!\x91\x9b\x15_\xd0\x1b\xd2\xb6r\x1c\xfd\x06c\x05\xb3\xabvs\xef\xe4Z\x9dd\xc6\x7fg\xa5I\xba\xa1\xa9\xf0\x0d\xecu\xb4I\xcd\x1a?\xeb\x02\xc2\xbcl\xd6\xfb\x1aW\xf4/\xac\xb1f\xd1\xf7\xb0\x07k_cf\x88\xaf\xa5\x8c/\xad\xbf\xbdy\x18\x07O\x17a\xd4R4|\x0b<\x82odvr\xe6w\xce}X\xdb\x83K\xfb\x0d\xf2fh\xd7\xab&\xd0\x87\xc5\xd8\x82\xba\xe17\xb2\xad\xb0Y*\xc2\x93,\xdf\xd7V\xbav\xbcn\xd0#P\x8aA\xae\x9dv\xddkG\x0eg\xa3\xb1]\x03 !\xbf\xb6\xbfQ\x9b\xd3d\x92\xac\xe2\x9biq\xec\xc2\x9b\xaa=\x1e\x10\x92 \xb7\xf9\x0d\xfd\xf9\x06\x9b\xe9\x04\xc0\xbf\x86 \xbcin\xd9\x0f\xbd|\xbb\xe0\xd9\xdf1\xaf\xf1K\xfbe\x0d\x08&\x1d%fL\xef\xaa'\x9b\xdd\x7f\x07{\xf032\xc5\x0c\xea\x1bP\xeb\x89\x9b\xbb\xb1\x88\x06\x80R4B:\x0b0\xa8\xa5F\x94\xfd\x97\xa6\x19\xfcm`l\x80\xaa\xe1=\xb1I\x7f\xb3\xff^m\xe0\x15\xcb\xe2\x02{p\xc13\xd6\xd1w\xb4$\xb1\xdf\xa1\x91\xc4>\xc6\xd7\xa9\x10\x10f\\\xa5\xfd\xbdby\x85\xa7\xaf\x8e\xa7\x053s\x11\xbf\xf7x\x0e\"\xdc\xb4Xw\x10\xea&)\x17\xb1\x89\x89\x8bT\x90\x0d\x93\xba\xc3\x0f\x1f\x18\xf4\xbdr\xe1\xc0\x1ea6uJ\xa6\xd4\xfd\xd2\xe1\x7f[\xad\x06\xfd\xb6\x86V\xd3b\xfey\x88q\xc8\x95\xd2\xf5\xad\xd6\xbc\xb3\xe0\x1fK\x9e\xe8\xb3\xa0CKXj+\x16e\x97IP\x98\x1fe\xf2\xc8\x81\xbf\xa1\xfe\x1d\xc3\x05&\x18\x06\xa60j\xdf\x8d)7\xfe4\xf88=k\x18\xaf\xe0\xc6\x13\x96\xaaP\xdb\xf3\x1a\xd6\xae\x01\x08A\x83\xe5\xf7\\K(0\x11f\xc1e\xaf\xd9\x05\xa2\xec\xda\x17\x9f\xff\xf9N\xfc\x16%\x0cz\xe8o\xbay\xe4\x18\x0b\xdbv4\xcd)~1d\x8f\x98\xdd\x05]\xff.\\\x0b)\x11\x89\xa9\x9e\x94\xff\xc8\x11{\x82\x87\xcd\x17\xb3\x8a9\x04\x7f#v+dSz7-\x0c\xe70l\xce\xaa\xae\xf73nmi\xdb/M\x81\x0d1\x08\x14=N2\xa2\xef&\xc4\xb0\x18IZ\x87{\x92\x92\xd0w\xf2b\x9c\xf3\x8cj\xa9\xca\xebw\xb3\xe1\xf5\xbb)\xf9\xe6\xbb\x9d)6\"B*\xaf\x13\xe0Y\xdajl\xc0SZ\xfe\x9d](\xcd\x03\xce\xfe\x9a\xbe:\x16\xf8\xc2\xae\x8f\xbc\xb8'\xbe\xad\x0d\xe9\x10\xa9\xab\xd2\x1d]+\xa5|H\xf2}O\xff\xf7-\xdd\xc3N.@\x18\x14I5\xa7T^\x8bXp\\\xf8\xa1\x99\xeeM\xce8h\x15I\xe5\xe3\xdd'\x04)0C\xdf\xfb?\xc8M?\xc5\xa4t_\xb8\x94E\x81=\xf8\x1bF\x90\xdby\xe8\xe0_\x87\xf8\xff\x7fF\xae|\xbc\xc3\xde\xfd\x89\xf1\xe8\xbb\xec\xaf\xbf\xf2\xfc\xc6k\x94\xdf\xdc\xc6e-\xe9\xfc-\x15\xc3`\xb9\xf4kD0\x0b\xfc\xbaWR\xf5\x83\x1d4$2t\xc4\xbe\xedc\xaa;\x1fS\xdd\xf9,[\xda\xcf\xed\xf5f ;\x91\xe8\x16Y\\V\x1d\xe7\xbfPva\xe1\xe7\xcf\xf9\x01p\xc3\xfci\x12\xcf\xfc\xe20\xcd\x88\x1f \x9b#(0\x17\x9d\x85\\n\xbd\xeb2\xd7\x0c\x97\x07\xe8u\xd1\xde\xd3\x958)W\xec\xcc\x91\x7f\xe6\x96q>KR\xda\\.LC-\xd7\xa2\x17\x01a8\xe2/\xf5!!\xe4\x91\x03\x81\xfd\x97)!\xcd\xb4\xe65\x12\"\x98\x8f*\xf0\xf2\"\xc9\xe8\xe5\x12\xf3V\nR7\x13\xd3f\xce\xed\x82L\xe3V;t\x05\x0f\x1bk\xc7Ox7B]\xbf\xfdG%;{Ao\xb5\xf5=\xb47\xdf\x87\x17\xf4TM\xd8?{\xdd\xe4\xea-\x04\xfc\x9e\\}\xd3\xdf\x15Z\xe0\x7f\x87\x16\xf8\xc6\x9c=>0\x1a\xb8\x83\x9b\xa0\x19<-\x8c\xe1\x85ZCA{z\x81t\xdc\x9e\x9c\xba\xc3H\xc6\x9799$\x05\xaa\xb1\x8d|\xda\xf7\xaa\xf0\xc0\x9d\x96\xc2e\x1a\x91!-5\x93\xcd^w\x8eJk\xa3\x19\xc3\xdb\x8dq\x84A\xd4\x07$+\xedZ%\x17\xb0\x0f\x976\xa6\xa5\xfc\xb3}\xc9h\x1d\xe3f\x07d\x1e\xc6D\xa8\xa8'\xf07CqH\xf2 \xfc\xb9Y\xe1\x8c\x14\x92\x8a\xfb\x19\xc9gY\xc8\xd4\n_\x98*\xbe\xf2\x97\xb4\xb1\x7f6\xd5a\xc7 \x9f\xc0_\x1b\xeb\x88\"\x96\xe6b\xdakx\xc5\x1a\x98|q\x11\xbel\xc7<\x16\x8c\xda4.\xa3\xe8\x18c\x99\xfdd\x0b\xba\xd3\xfa\xe5\x9a\xbf\xe9\xae\xbd\xdf1,m}\xc26\xb7\x851\x1d\x17\xac\xef\x0e_\xbfR\x04\x01\xa9\xb4\x0c+\x10?\x9cd#\xc7\x8c\xa3\x18=R\xc5\xe0\xa1,\x05\xa7\xc9\xea\xeb>ib!\xf1\xf0L\xde\x9c \x1a\x1d\xbb`\x9f\xda\x9d\xa4n\x9c\xc4\xffN\xf6\xbf9\xe3\xd5\xecb\x089.\xfaRJ\x87X\x987\xa44;\x06\xf5\x8eK\xfb-\x1c\x0d\x1a\x00\x0e$t\xect\x1a.\xfc\xc4\xb5*\xcf\xbb\xc2\x87\x06XIB\x84\xe9[$\xc6c{g\xd3\x91\x85\x0b.\xbcm\xd4cI\xb6^\xcf1_\xe8\xcb\x1aq\xb3\xbf\xfdb\xe1\x82E\xff\xb1\xf8=;\xe7j\xa6\x1a\x06\xd66\x07\xa9\x00j\xe9xG\xca)\xa2B\xa9\x93\xd8QBaU\xbd\x94\xe0\x073e\xda\xb7\x98\xc5\xe5\xed\x1a\xce(2HV\xa0\xea\xbb\\\x00O\xf1\x11\xed=\xf4\xe6,/\xcb\xe6#(kH\x8d\x1e9\x90W\x16\xe8\x94`/\xa7\x11\x12\xe5HN2\x10V\x1f`Ia\xb8\xda\x8av\x84\xdb\xc2\x9b\x90\x92]\xdd5\xfd\xe5\xda\x13\xa4D\xb3\x10\x83\x03\xd5\x86\x14\x02\x96/\xc28H.P\xc9\\\xfd\xe2BS\x05F\x84}C\xa1\xcdZ\xa0\xb8]v\x8b\xab\xb5\xa3\x83\xa88\x0c\x8akM\xd9H\xe1\x07l\xf2\x18G\\\xe58\xeb\x95n\xe9\x93\xd5T\x04\x88\xca\xda\xaa7\xf9\xbb\x18\"w\xf4Q4\xd1<\xc06\xcf\xbf\xdc\xd4\x14\x0e\x02\x00\xa6K\xb1-?\xbf\x8ag\xcfWR\xc8\x89OY\xfa\x12\xa4\xa5\x07}\xa7\xd6|\x15\xde\xe9UA^\xb0#0\xe4\\F\xdas\x89\xe9\xa5:%\x19\x96\xb4}:\xf9Ro\xd1\xdb\x13\x83/9p\x0f\xb6aC\xe2\xcd\xaf](\xbc\"\xf9\xfa\xaa <3\x9catm\x9e\xfd\xa4\xb0\xe7\xce1|\xf5\x15\x8c\x1e\xc0\x87N\x11\xac\xc3\x88\x17\x8f\xd5\xc5cV\xbc\xab.\xddr\xe8JL\xf3\xf5u\xbc\xa60\xb2\xf2.| \xe3\x9d\x9d\xf6\xfb\x07\x9d\xd7\xe3\x9d\x1d\xf8\x12Z\x89\xa4\xc6<\xc5\xb5\xb8:\xd5\x93\xd1\x0c\x96\xce\xe5\xf1c\xd8\xeev\xd2\xc2\xb6\xa3A\xbd\x8c6\x8dK\xb6\xad_\xb1\xc7\x8fa\xa6\x87wZ\xb0u\xfd\x12v\xb7\xe8\x0bko\xcfB)\xf7\x98\xb7\"\xf6\xcbf\xed\x8cq\x1f\x1e8\xb0\xaemx\xb4)Z\xa6\x80Q\xb5\xcc\xbb\x1aK]Y\xed\xa1\x0b)L7\xdc\xf4\xb5\x82\x7f\x16B\xc7D\x12>Ze\xcc8\x8f@N\x0f\xfb.\x8c\x8b\x07l\x1f\xf7\xe5?&,\x9f\x0b\xdb\x14\xeb\xc9\xd7O\x9f\x1d|\xf3\xa7o\x9f\x7f\xf7\xe7\x17/_\xbd~\xf3\x97\xb7\x87G\xef\xbe\xff\xe1\xaf\x7f\xfbg\xfft\x16\x90\xf9\xd9\"\xfc\xe9}\xb4\x8c\x93\xf4\xefY^\x94\xe7\x17\x97W?o\x8e\xc6[\xdb;\xbb\xf7\x1f<\\\xbfg\xf1h\xdc\x0c\x8f\xf8\x95t\xbe\x84\xaf \x7f\x04\xeb\xeb\xa5\x03\x19K\xc6\xedOK:\xf0\xa9/\x83r\xe9`,c\x95[[\xa4\xc7\xea\x02\xd8\xba\x84U\x01\xff\x01\xb6)\x1a\x13\x8c6E\x9e\\\x16\xf8\xc1vn\xc2\x84!f:^9mfw\x1df:\x8c_g\x8cB\xf7S9:z\xc1v \xa6\xff\xac\xef\xc1\x96\x83\x00c\x13\xba\x13\x14\xe5P\xec9\xda\xbd?\x1a\xed>\xd8d>\xf6\xd3\x92\x9e-\x06\xe9\x14\\w\xc6\xbc\x84\xa1\x0fV>>\xa6\xac\xb9\x80|;\xc4\x8cZ\x08\xff\x0f$\x98\x0f\xf1\xcd\xb8\xfdfWz\xb1\xbb\x05_B\xd8\xe6\xa9*\x8a\xa6{\x14\xaa_\xc9\xd4\xda\xb0d\x08\xdaD\x08\xda\x1dS\xd0\xb2NTE[JzC^\xcd\xc2\xcb\x88\x1f(T\x81<(\x8a\x02\x0cCW\x10\xea\x0f\xe0\x8f\x90PZ\x80b\x06\x85`\x94.\xfc\x88\xaek\xe9\xa8k\xa0\xbf>\xaeY\xb7\x8c^\xcb\x1b\xf7\xbb\xef\xd1~\x06\xf6\xb1\xe3\x11LT\x01\x0bR^e\x83\x96+\x9a\x0e\x10QR2a\xde\"w\xb8\xc3\xfe\xfa\x1e\xa4\x0c\xc3\x04\xf0%\x9f\xc3\xc6\x8cM\x02\x02x\xfcx\x0f6f\x94rX\xa7'\x18f\x18\xd8\x14\xeb\x8fwv\xe1\x8f\x10\"\xc2d\x1d\xb8 \xda\x9b\xc1\xc6\x1e\xcc_\xf9\xaf\xb8\x8c\xa7\xc0\xb6\x18x\xec\x83\x8dY\x04D1o\x92!\xef\x19j\xe9}\xd1\xd6R5\xcf?\x85\x0dX\x1c\xc3\x87=\x18\x8d\xe9\xc1:o\xddp7b\x8a\xb9\x10\xa4)\x9c\xb6\x0b\x17\xac\xda\xac\xb5#B\xe5\x96S\xb2\xb1\xab4bAj^)\xa3G$\xbcd\xac\x8c+\x81%[\xaa\xb8\x12X\xa2\x8a*A\x0b:_\xe4\xbc\xa0\x13l\x82\x99\x9a\x8e\xef\xb7U\xaf\xcc\xd6\xb4mf9\xc7ff\xad\xb7)o\\\x11\xe6\x82\xd9\x9a\xee\xec\xb6\x03]/\xaaO\x1e\xb6?\xe1\xf6\xa6\xe3v\xdfK1\xb7\xce\xac\x99\xc5\xa9&\xa0\xc3\xd5\xa7\x0f\xe8p:D\x1a&%\x1bm\x82\xca\x89IU_M\x8b(UA\x92t\x9e\xb15J\xe5{\xed\n\xb8\xd6\x88\x0d\xb4y\xdc\xd5\xcb\xab\x82\x7f\xb4\xdc\xc9\x84a\x8d\x8b\x05i\xbb@-p\xcb\xcd^\xc1\xbd\xce\xc5+\xb8\xcd\x9a\xbc\xe3L\xde\xc7\xd0\xf1@\xd6\xd7\xcb\x92\xa4x\x1eS\xd4\xd1S\x11\xe7\xfdF\xccN\xe1\xd4\x0c]M\x99xN\x932\x0e\x0e\xc5\xc45\x95\x8a$\x89N\x93K\x8d\xc34bz4\x00\xa8\\\x18\xe9\x1d\x81\x16\x01\xd5\x1b\xef4\x8c\x03\x1e\xf0\x87\x95\xa1\x82\x99\xdd<{p\xeaVn\xd63\x14r|w\xc8\xf6\x9ayUr\xe1[\xb3\x93\xfe\xb0\x85\xe2\xa9\x18s\xda\xfe\x99\xc7\xf6\xf9hQ\xc6\xef_\x86A\x10\x91\x0b?#\x8e\x1d;\x86\xc0i \x06\xf2\x12\xe1FNN\xde\x1e<{\xf7\xd7\x93g\x07\xdf\x1f\xbd~\xfd\xe2\xf0\xe4\xe0\xafG\x07\xaf\x0e\x9f\xbf~u\xf2\xf4\xf5\xcb7\xaf\x0f\x0fNNP\x87\xc7\xbcGsE$\x1c\x90\xc8\xc6M\x97\xd6D=\xe9!\xaa\xdd\xf9\x84\x12;b\xfa\x9ez\x98\\\xffS\xa5*wTf$6?\xaf\x8eXk\x0cO\xc2\xbdK\xd1\x1a\x05\xdfVN\xb5\xf8\x17?\x1e:\xadRk\xbce}$\x89\x0b\xd3\xee\xba\xbf'W\x13\xb0\xe8f\xd1\x19)\xdc\xa2\xf9\x05gTCC\xcb\xc2\x04a\xa6;\xdf\xe6\x90U\xe8\x81\x8dFLx\xc0hz}l\xd7\xd4\xa9\x07txp\xc4t\xb0\xf2\x0b=\xb0\xc9y\x80\x81\xd8&\xd0\x16\x0f\xe5}\x18t\x879\xa37\x1cJ\x91b\xc09\xfe\x1a\xc5JNC\xdb\xa8\x06KU\x9b\xdf\x94\xf1\xac\xf1-\xb1\x0b4\xa0\xd5y\xf9\xaa\x1aQ\x8c\xc0[\xfai-:\xd7jW\xe5\xa7\x1e@\xc7\xde\xb5\xfd\\;^F\x82rF\xec\x0b4\xa35\x0f\x957\xacA\xa0\xc0t4mTg\xeb\x02\x00^p\xfc\xc5qU\x8c,\x01\xb7\x06m\x1cH\x85\xfe\x03\x9a\xd7r\x1f\x00\x08\xfcF\x9b\xd6O\xf1\x9c\x07\x17U\xc0\xedX\x0b\xb7\xe3\xe6\xfd=>\xeeq\x0d\x07Nd&\xde\xc2\xcf_\xa0\xb7\xb6yD(T\xd0W\x19\n\xd3\xa8\x07T\xa9\xdf\x0b\xcf\x9f\x17${\xc1\x9d\xa7\x91\x83X\xdbt\xe1\xc0\x96J\x1cY3\x1f\x9bB:\x9a\xcf\x84\xdc\x0c?\x1e}\x1e\x12\xd52M\x14\xd9\x9f\xc5c\x82\xdc\xbb=`\xcd\x99dB\x18\xd1\x7f*\x07\xcd\x03\x00TY\x80\xeb\"\xfd4\x85\x95\x18\xb0z\xd3\xc5\xbb\xa1\xad\xf0\x18T\xba\xe3\xd13\x02\xceG\x16\x82K\xe2o\x06u\xfe|9\x81\xb9XZ}\xb5\xb7\xc4\x9f\x15\x93:H\xa2\x1as\nn\x8cqi\x12\xcf \x18\xc6\xe5\x96p\xce\xa7u{p\x92\x07\xa9\x8bX5xdw9\xb0\x01\xc2\x82!c\x87\xce\xf8\xbbo\x0c3\xcaW\x99\x91\x96\xb7Q\x0c\x14\xf6\x14q\xf7\x06\x0f\xab\x894\x07\x0c\xcdxE2b\xc4p\xef {(b`\x0bLmW\x97\x18\x9f\x99,.a\xbea\x8c|JN\x7fz\xe9\xa7\x0e\xbdA\xfa\x97\ndZ\x89\xf1\x18\x99fW\xb9\x87V+\xd6\x0f\xa9X\x93\x9a8\x1bB\xe6\xf7RH<\xc6-F\x82&\xd3\xf8x\x85H\xe0\x82\x10Y\x91\x0c\xe9J\xf8br\x013\xef\xa5\x9f\x9a\x19\x05\xe0\x84\x89\xcc\x15\xf7s\x93k\x99)\xc2\xb0\xfc\x08\x93\x80lZx\x94\x1d\x18\xd0x/\xa3\x0d\x12'u`\xc7\x8e\xc9_N~\xf8\x88\xab D \x97\x0c'\xc6/\xf5\xac(\xa8\xc4\xbe\xed\x07aO\x0d\x95\xc8\x0f\xbbm\xa8,\xe4\x08X\x9b.\x04\xde,Y\x9e\x86\xb18M\xb9\xc3r\xea\x9f\xf6&\xc97\xa3\xdf\xa3\xabt\x88L\xa8W\nC\xa6\x9b\xc7^\x91\xbcKS\x92=\xf5sb\xa3\x11P\x15+\xbeW\xec\x86\xa7\x9e\xcd\xcd\xb1\xf5H\xa2\x1aP\xacH\xe7!?\xe7<\xb6y\xac\xcc\xf8-\x1eTT;\xf28\x92&}\x9c\xc1:\xc5u\xa1\x9aU\xba\xcd\xa5L\xc9\x13A+\x0f\xd8\x80!\xb72\xdfN\xdb\xca\xab\x86o7@N\xef\xdfbx\x02\x915\xc7\xe7\xf3v\x07\x82\x05^\x06d\xc5\xcb\xa0\x03T\xc4`\xd6\xa2z\x1a\x02\x06\x8a^\x1c\x13\xa0\x14\x9dL\xe0\xf2\xa3a\xb5o ?j\xeel\xc0n\xf5\x9ef\xba]\xc3\x98\xd1\x06_\xa8\xf2W\x07\xdd\x86\xc6\xcd\xfd\xe8\xbfpi\xaf*\xac0\x8d\xeb\x0c\x0e\x1b\xf7\x9dc\xef\"\xf3S>\xa4\xdeK:\xe3\xf8U\x03h\x03\x04\xbe\xe2\x0e\xca\xa6q\xcf\xb5\xc6\xbbD\xe3K\x14\x10 A\x91\x9d0\x1f\x17\xb4UL\x8e\x1d\n]m\x9ad\xc8P@Z\xaa\xde\xa3\xd9~\xc4\xbd\x88\x87\xa3!\xaci\xa9:\x14Q\xc4t\x8fB\xbf\xd8~\x90\x90\x90\xcfY\xe6\xc8\x16\x89\x92\x87\xb2\xb4\xad\x10\x13\x12\xe4P$\x954\xaa\x96\xd2\x16\x0b\xbf\xe0\xafs\xf0\xb1\x91\xaa\xcc\x0e \x14\x0b\x02\x17\xec\xe4\x00CD\x8e\x0e\x11\xc9\x0f\xef\xe8\xc0\xcez$\xdd<\xf0\xe67\xbcO)\x88\x08\xbd\xafM$\x82\xb6\xf8n\xf1\xc4*\xd7\x8e Q\n\xa2\xce\x8c,\xb26\xb2\xa8%D\xfd\x01\x0e\x9a'S\xce\xa5\xa3J\xe7%?\xe2TN3 9<4)\x16A\xb87)qL\xc2\xd0J5\xf8^\xc4\x12v\x10K\xb1\xc2\xf0A\x16\xcaO\xb3a\x88\xc5\xef\"\x16\x9f!\x16\xb4x\xf5\x99M\xaa\x82\xd9\xe9\x1d\nH\x14\xd5\xca\x88\xa5\xb2\xbe\x0d\x15\x1c\x0d3Mb\x83\x0d\x1dn#\xcdlr\xc3GP\xae\xaf;h\x0e\xdd\xe0M\xca\x9e\xe5\x10\x8f@\xf1\xc8\xcf\x990\xda\x94\xcb\x8b\x9e\xc7v\xe2\x1cS\x8e{\xe6\x17\xb6\xaf \xad\xdb\xcfM\x10\\hBp\x02\xc0~?\x0c\x17\xf6\xa1\xb7\xc2\x80\xde\xd4<\x0e\x08\xf4\xa6a\x81n\x87\xdeP\xca7\x08\x99\x0d\x90\x94fM\x0b\x17\x15.X]^\xd0\x14\x08\x10\njL\xec\xad^\x0e\xf7v\xe2\xbe\xa6|\xfd\x1fg]\x06#\x16\xc1m\xb3C\xabr\x11\x15\xcf\xf5G\\\xe3o\xe2\x01K{c\x99\xe5\xc4+\x93\xc7z\xeaV\x83\x92\xaa\xb05<\xb6\xf9\xbe~\xf4\xd0\x96,\x8b\xb2[m\xce\x9d\xd2jJz\xaa\xd2\x98T\x14\x99\xb3\xa2\x84EEa\xf5RFz6\xb0\x97\xc1\xe1-\xf4\x1e/\xf9ix\x84u\xc9\x8f\xb0\"?2\xa7\x8a\xe6\xe4\xc3W\x90=\x02\x9f\x92\x1f\xe1\xd4o\x92\x1f\xfe\x00\xf2\xe3\x9c\xa7C=\xb0cAl`*$\x0d\xa9\x11\x1a\x93W\xf2\x87O^i\\\x81\x89(m\xd6c\xe9\xd8\x85\xcd\xa2\xca\x1b\xdb4X\xd7|\x14q\xc5] )\x08\xc6\xe6\xfa\xf0\xa1\xa3\xf1\x13jt\xf5R\xcah\xca\xab\x85[\xed\xc8\x1d\xe2Q\x9f\x18\x99\x84\x1f\x80nl4(<\x0d\xc5\xbc\x9ff\xc4\xa7\x07\xcd\xa9\x10\x17\x90\xc1\xa6 \xd2\xc6\xd7\xce\x8b\x85\x99\xcd\xe8k\x1a\xe4\xeb\xb4\xe8\xb3\xe1\x82\x017\x9b\xfc\x08\xe9\x1f\x05\xfd~\xf8\xd6\xbb\xff\xb7\x1f\x94(\xdeB*!\"\x06\x0cZ\x1e\xe0\x1d\x0e\xabI\x1f\xba5\x138\xf7^\x1d\xfcpr\xf4\xed\xdb\xd7?\xbc:9x\xfb\xb6_\x03#\x1e\xcc\x80\xa0\xcf\x92\xa5zR\xff*J\xfc\x80\xa5\xf8Y\xc8j\x84AM\x98\xb5\x1bX\x03\xe6a\xecG\xd1\xd0-\x12@\xd5[\xd9\xdc\xb5\xc9\x02\xb0p\xb42\xd7[b\xaa\x97~\xca(\xe8\xe4M\x96\xa4C\x90\xd5\x10\xf9\xb7\x11\xcf\xf4\xb6\x04M\xac\xd2\xb2\xe3!\x03H\x9a\xdb.\xc93\x8e^\x87\xaf\xca \x92q\xd8\xb2\x0c!\xee\xec\xa6\x87\x02\x8a\xe5\x0dVL\xc8\x81\xd5VG:P\xea[\xb6c\xfam\xf5\xea\xdaV:\xaa\\hCG\xddZ\xc5\xab2\x02-\xd4\x0d\x9b\xac\xa2\x1b\x0d\x8fT\xde!\x0dA\x860\x03\x95\xb4\"\x83\xea\xcbF\x9a\xcd\xea\x05\n\xd8j\x96\x04)\x9a\xd6\xd5\xd6\xaa2\x80Z\x15T*\x91\xc8r\xe6\x1a$\x91\xf0*\xf9\x1a\x067\xe8H\xe9\xf7\xc1n}\x89&\xb6\x9c\x8c\x9b\xc6\x14\x18x\xf4\xea\xf6`\xa7\xd91\x86\x95\xc1yu\x1b\x99&.\xc4\xc7\xc6\xaf\x9bp\xa7\xd0\x19\xb7\xbe\x91\x13\xfdk\x9a\xd5\xba\xee\xcb\x8c}w[\xdb\xbb\xaa\x8a\xa1Y;\xddC\x18\x9b]B\x98\xa261$\xe5ow\x18V\xa9\xa3\x1aoe\xd5\x8f6\xc2.\xc8\xb2\xd5a\xca\xa2j.%\x9d\x8b\xdfG6\x9c\xf3,K~\xaf\xa8\xb2 `9\x93\xd6\xd2O\xa7\xf9\xb1+$\x9fye\xb1\xde\xd8\x96\xee\x9bir\xac|)O\xb2\xb7\x02\xed\x13\xe3z\xf4Ub\xf3\x13\xb0\xdfW\xdd LU_\xf2}\x88W\x8d\xf4I#2\xa1*J\xc4\x81>Z\xc6\xaa\x9e$*\x9c\xe9xQr\x86\x02]\x850$\x96\x93\xa9\xef1Ij\xcb\xf7\xc3D\xec\x0b'F#\xb1\xa0'\xa3\xa5\xb0\x98*N8\xab8\xe1B\x84\x12\x7f\x04 |\x05\xc5#H('\x9cQ\xf8\x92W@wb\x05\x82GcpN\xa7\x13\x17\xa6\xf4\xba\xaf\x00&SY\xae\x0c\x8d\xe5\x85\x11C\x9a\x19\xc3\x08\xcfE\xd7\x036\xd7\x7f\xe8\xfe\x92\x13\x8d\x9f\xe0\xdb\xdeX];[c\x85\x17\xb0\x9c\x14\xa9.U\x07\xc8S{\xca \x9dE\xdbI\x99\xb4\xa3\xca_\x0f\x19g=\xae\xf1\xa64\xdc\xcc\xce0\xcce\xc6b\x86\xb2|7\xda\xb8\xa1\xedX\x9e\x98+\xc5\x9b\xd7#q\x86\x0c\x85.\xd9\xb6)\x87\x94\x9f\xe7\xe1Y<\xa4\xa9\xfeY\xe9'\xc3z\x99`\"\x98-g\xc59\x98\x93\x0c\xc9\xa7\xf2Z\xbd\xfb\xd9\xed{\xa1\xeb\xd8\xf6\x9ef\xb1\x055\xc1\x1a\xb7\xd4\xb9\x8cv\xb6\xdaYyJ\xcc\x1aP\\$O\xf8\x01\x7f\x93$\x11i\xa5{\xc3Yx\xf3\xa4\xccL\xb5\"\xd8\x83{?\xde[\xbfw\xa6\"\x86gZ\xbfi\xdb\xb2`\x1d\xd0\"\x13MG\xed\xc8\x05\xeb\x8b/\xefYf\x94>W\xca>Q\xd0C\xeb\xf0\xfc\x1c\xf4\xcfY\x12\x17\xe4\xb2`1<\xf9\x9b2\xa6\x7fo\x1a{Hu\xe7Ul\x0b\xc1\x9e\xba\x18_\xd0\x9e\xd8m\x0b\xd33_\x99\x84\x19\x0f\xb1\x81\xac\xaf\x9bg\x1aHaI\x94\xf3\xcdH\xce\xf0\x98\x98\xf1{r\xf5&#\xf3\xf0R\x9a3_\x94\xb8\xb3(\xd9J\x8b\xb2\xe8_\x146\x9c\xee\xb2\xf8XZ\x8d\xad[\xa14\xaci.\xafi\xb7\x98\x02_\xc9\xd66o\xadms\x03\x9a\xc4WD\xa9\xfbs\nq\x19\xaeo\xe8\x15\x0b\xbfx\xcb\xd4\xac\x02\xd8)\x05\xcf\x13\x9e\x02\xcb\xe1\x98xa\xfe\xbd\x1f\x85\xc1ADh\x0d\xda\x0e}\x1f1\xc6 Jb\xf2$\x0e\xde2x\xfe3\xb9\xa2\x1d\xf8\xb0\x0e\xf6ZD\xe7\xcf\xe2\x9e MF\xff\xa2T\x01{\xbf\x0f\x96\x05\x13\x98\xd9\xf8\xa7\x03\xeb`\xdd\xb3\x1c\x0cU\xe8\xb8\"\xf0n\xe4\x98\xc1\xe5\xdc\xee\x0f\xcf\x04{`Y\xcd\x85\x113dq\xb9h\x8d\x19e\xc0\xd9\x10\xba\x1c\x03\xdd\xab\x802\xd2\x88\n\x02\xbb\xc0([\xd8a\xb3\xb2O\x87\xb3p\xa1\xa4\\\x92\x97\x91\x88\xf89\xb1K\xf3\x1c\x96=We\xe3\xce\xaf\xef\xf4\xb9\x14P7 \"\x95\x81I\xcd\xd88\x1a(\xaco\x9d\x8e\xc6\xcb\xce\x01\xa1\x9b\xe2\x07\x01]\x830>;J\xec\xb9\x98\xe8\x8d\x06R\x1dd\xa9W\xf9,K\xaf\xefp\xcc\x81\x0by\x8b\xae9\xeb\xc8>\xe7Iv\xe0\xcf\x16\x93^b\x06\x84-7\xb3\xb5\x96\xa2\xac+\xec\xc5\xabk\xb4 I*\xb7f\x84\xa3\x94\x85\x84\x9aWp\xd4\x8e\xc3\xdc\xc4\x0cK?\xfdH\x03\x9e*\xa8`\xfe\x15\x9e\xbf\xcc\x15\xbb\xc0\x9c\x8f\x8diJ\x96~\xfa<.\x92\x1f\xc2b\xf1g\xb1\xdb\x98?5\xf6\xa3 \x9c7+\xe3\x8e\x0e\xd0\x00\xf2\xd1\xe0\xb2-\xd9h\x8ckU$\x88\x12\xfb$y\x82\x95\xe8[\x80B,\x80\x1a\xa5vRg\xd5\xf0\xa9\xa6\xa2\xce\xf0\xed-\xa9\xa8\xd1f\x9b.\xc2\xc0\x7f\xb1\xfd\xc0\xe9\xb34\x16)U<\x91R\x85B+g\xa3\x86H<\x9b\xdf\xa5I\xda\xa3\x83b\xa7\x17\xfdjY(\x16Epr\xdd\x06\xc4\xe4\x02\xbf\xef$gP\xd0\x8a\xe6Y7R\x85\xd1&1)\x8fm\x8dw0\xc7\x85\x84\xdb*\x1fN\xc5\xfaPv\x92\x16\xa5I\x12\x1d\x86?\xd7n\x9d\xcd5\xa1\x97\x9b9\x9d\x04\xa5 \x92.\x01\xdb\x1d\xb7\x8c\xdf\x06\x9c\x15\x90\xc5`\xc6m\x89\x1bc\xe61%\xe3\x1a{\x01g\xf0}\xfa\xb6\x9a/K\xc7T\xfd\xb9\x07#L\xc6$\xb0\x18\xec\xd1\xbbS\x91\x9bIAZ\xc6\xa4I\x83O\xda\x0bB\x9f\x0e=?p\x0dn\x02\xe4 \xad\xddJ\x80\x0e*`\x8fyl~\xd5r\x80\x12\xe6A\x05\xf7\x9dT\x15\xa0^\xceb\x91\x91\xce\x82\x0e\xb90\xe0\x96\xab\x95\xdd\xc9je\xae\xf0\xcb\xeb\\1\xe2\x19\xbe`\xcax\x1e\x8a5\xeb\xf2\x81\xdd%3\x98\x91\xdcf\xd5\x92;Y\xb5\xa4Z5FM\xa8\x9d\xc0VZ\xb8NB\x88n\x0b\x9a{\x8d\x99k|\xac{m\x9b\xa5Z\x1e\xef\xdeW\xc5\xa2\x8b\xed\x9d\xadv\"]\xbf\xbe\x10c{g\xbb\x13^\xaed\xe5\x0f\x1d\x17,\xaf\x9d\xc6\x95N\xc8\x9aX\x9ax\xc5\n\xc4#\x08-\x0c \xd2\xcdx\x80\xef\x05cB8\x8b\xe4{$\x9f\xf9)\xb1 c\x92&\x18Z\x9e\xe5Q\xb0\xb7v\xdb\xd22\xb8\x990\xae\xa2\x06y\xdc\xccj\"\x84\xc7w\x9a\xb90\xd7\x11H\xa9\x8bq\xf2\x84\xb9F\x1761_I#05\x86\x91\xfd\x12\xacSz\xa2\xfcX\xbc\x12YP\x90|sk\x07F\xbcd,\x16\xab\xd9\xc27X\xd7\x8a\xcb\xe5)\xc9\xe47\xf5\xaa\xf2.\n\xef\x8b/\xf8\xc8\xd0\x15\xb2\"wg\x94{)\\\xca\x83\xb2\x00\xcd\xfbP\xc2: \x05\xb2\x89L\xb0\xe3\xc2HM\x13/0\xc6\xa5\xf2\xc8\x9c#\xb3)59\x81\x18\xd6A\xa1y\xa1\xab\xd2\xe4\xcf\x0b\x8d\x06\xa1\x92j/\x99\xc4zII\x8c*\xbc\xf6r}\xdd\x81\x05\xac\xef\x01\xb1S\xba\x0f\xd3\xe5\xb1\x0b\xe78\x97\xd4\x85\xa5\xc3w\xaf;\x02Ml[\x90\xd8\xa2P\x99\x8d\x10\xf8\xf0\xcf\xfaP\xd8\x95\x8b\xd1\x04\xcf8m\xd7\x13Z\xe6\x0c\xc1\xa0\xf0H\\d!\xe91s\xa9\x16\xe5\x84-\xca\x9a}\x05{p\xea\xc5\xe4\xb2\xb0\x1d\xc7\x0b\x12L\x1d&-\xcc\x15K;#\xad\xcd\xc9\xfa\xba~u\xc4CW\xa9\x7f$\xda\x01\xe8\x17H\x91i\xd2\x8e\xe1\xae\xcdSU(\x92P\xdd\xc1\xca4\xc7\xca\x0e\xc2P\x0e_\x0d\xc6\xd6\x9e5\x01koS\x03\xc1\xd6\x04\x8b\xc7V\x17J\xb4\xf2\x02\xeb\x0b\n\x93\x1d5\xc0\xbd\xe9\xde\xe4\xf8\xdeY\x1fc.5TL\xc9q\xb7_#GY\xc6w\xb3(\x9b8m\xdd\xa2\xec\x8di\xf1d\x95Ea\xcba[\x1e;\xccd\xba\x89\x1az\xbaV\xeco\xd4D\x13//O\x19\x15`\x8f\xd1\x97Pz1r\x1ci5\xed\xbd\xcd\x0f{c\xe7\xee\x17\xb4\x86W\xf5\xd9\xb9\x13\xfd\xd7\xfd]\x87\xc7\xe8\xfc\xc6\x9f\x15Iv\xd5=\xc5\n)\xc0\x84\xa2H\xbfM\xa5b\xd1\xe9i\xc6JOO3e\x85 \xc8H\x9e\xb3:\xec\xb7\xb2ZFx/\x19Qw\x94\x15\xe1,\"\xbc\x0e\xfeVV\xcb\xc3\x80W\xa2\xbf\x94U\xca LX\x15\xfaKU\xe5\x14\x8bO\x95E~\xce\xda\xa7?\x94\x15\x82\x90\x95\x07\xa1\xba8\xe1\xc5\xea\x9e\xc33V\x1c\x9e)\x8b\xa3d\xf6\xfe\xefeR\xf01T\x7f*+'\xc1\x15\xab\x96\x04W\xca\nl\xeb\xd4\x1bwZ\x16E\x12\xb3\n\xf8SUi\xe6\xc7\xe7>\xdb\\\xf6S])\xa5\xe0\xcak\xe1oe\xb5\x90\xcf\x8a\xfePVH\xf8\xd6\xd2\x1f\xea\n\x11/\x8f4\xc5gYR\xa6\xa2\x0e\xfe\xa1\xaa\x18\xf8\x05\x03F\xfaCW!\n\xf3\xa2\xaaD\xffPV\x0cX\x95@YH\xd8p\x03\xa2\x1cn@\n?\x8cr^\x05\x7f+\xab\xcd\xd9\xca\x06s\xe5\xaa\x06\xa1\x1f%\x0c\xa6\xd8Ou\xa5s^\xe3\\Y\xcc\xc7\xa9\x1e&_\x05\xe5\xfc\xc9\x12\x0b\xc9R]xJ\x02^~J\x94K4\x0fI\x14`\xd2\xe7\xcc\xb6\xc4\x1f\xea\x8ag2\x98\xd5\x7fj*\x97\x19\x11\x15\xcbL L\xf3$\xc1\\\xb5\xff\x1f{o\xda\x1d7\x92$\x08\xbe\xdd\x8f\xf5+\x9c\xf1\xaa% \x03\x0c1H\x89\x94B\xa2\xd8J%\xb3[\xdd\x99\x92FRVMw0\x8a Fx0PB\x00Q8xdQ\xef\xf5\xcc\xec\xdc\xf7\xee\\=\xf7\xd9\xb3;\xf7\xb1\xc7\xec\xce\xf4\xf4\x87\xce\xfc#\xf3\x07\xf6/\xecs3w\xc0\x017\x07\x10$\x95U\xbbo\xf1\x81D\xf8\x05wssss3s3Q\x08^\xe9B\xc9R\x16I\xc81.\x86\x90\xbd\x18\x92\x99\xdb\x98\xb9Mf\xee`\xe6\x0e\x99y\x1f3\xef\x93\x99\x0f0\xf3\x01\x99\xb9\x8b\x99\xbbd&\xf7qB\xc4\x8b\xad\x80\x04\n\xbe\x92\x85\xcaU\xb6\xb0\xae\xb1\x85l\x85n![\"\xca\x89\x17\xaa\x00\x92X\x92\xc0\x06\xf3\xc4_\xe2\xe4\xe2+Yh\x89K\"X\x92\xeb!\x88V9\xe2\x1c\xbc\xd1ERY\x80\\\x95\xefO\x10\x90\xefOH8\xbe\xe7\x97\xa7\x1cQ\x15_\xa9B\xa1\x7f\")\x04\xbc\x91E\xf8)\x8f\xf0K\xf8J\x16Bh\x85$\xb8\xc2 z/\xb3\xa3\xf7T\x81\xa5\x1f`G\xc5\x0b]`%\xf3\xc9\x89^\xfa\xc9{\x99\x9f\xd0\x1f\xe0Q\x8e\x05x\x94\xdb\n\x04\x99$%\xea\x07]P\xd2m\xf1b) \xb1\x17\xde\xa8\"\x91\x8f\xa40\xf2IR\x18\xc5\x18M\x19\xcb\xc8\x1fTA<0B1y\xac\xa5\n\xe1\xf4\xd2\xdbU\xbc\xca\xca\x85\xa4~X\n*\xba\x17[i^\x9cg\n\xa7\xf1\x95*\x84\xdf\"?\xb2\xf2\x13\x1fg\x00\xde\xc8\"\xc14StU\xbe\x93\xc5T\x11[v|Zp\x8c\xea\x07U\xf0gP\xe2gTV\x82\x03I\xc8\x91$\x08\x85\x84\x84@\x92\x9f \xcf$^\xa8\x02\xd8/\xb2C\xa9\xbf\xc4\xef\x8a\x17\xb2@\x89:v\xc4I\xf9\xb4\x98N\xf9N\x17\x0b\x15~\xe1+Yh\xe9\x87\x88b\xf0F\x16\x89\xf3d\x8a\x13\x82\xafd\xa1\x95/;\xb4\xf2\xe9\xdedI\x1c!I\xc5W\xba\xd0\xa5d\xe0\xe1\x8d,\x92#\xeb\x9d\xe6$\xf3\x9d\xe6\xcb\xa5\x9f\\\xca\"\xf0N\x17\x93\xf3@\xaf\x97\xcc?\x91\xfd\xc80R,Q\xa4\xe0\x9d3\x1b\xf3\x9c!\xd9\xcdH\x92\x9b\xf1\x8b\xac8\xd2\xa8\x1fdA\xc1[`)\xf1F\x16Y`\xfe\x82\xceT[vf\xdb\xb3\xb3@n\x87\xe2\x85.\x90)x\x887\xb2\x08R\xcd\x8c$\x99Y\xe2O\xdf\xcb|\x7fJ\xd2x$\xf0$u\xcf\x11As\x12;\xcf|\xfc\xf0\x99O~\xf9,\x98qW\xfc\xfa\x9c$\x11<\x0c\x83\x95<@\xcaw\xaa\x18\xae$\x9a5Y\xfa\xa7\x92\xbb\x11oT\x910\x88\xb0\x84x\xb1\x15\xf0\x93_K\xfcY\xc0\xa3\xac(Z&Q\x95\x96~\xaa\xf6\xf1\x94\x9c\xe3\x95\x82\xd0\xca\x02\x9d\x95\x9fe<\x89T\x19\xf1N\x16\x8b\xc3\xcbSI\x00\xe5\xbb\xadX1R\xf5\x83*(\xc6\xe4\x87\x95\xd1V\x93\xc8J\x8a\xb8&6\xd2\x9a\xc5\x92\xc8d1M\xec\xcf$=<#\xe7Q\x10\x85\x82:\x90\x05\n\xa2\x9b!\xd5\xad\x94\xb0\xc8\x88P\x05{\x0b2\xa2\xaa]f\xb5w2\x1a\xfb\xae\x1e|\xac\xd2 eMv\xc3~\x18\xc6\xd7\xf8\xe1\xba\xe95j`)\xfdk\xe4\x0c\xeb\xe1\xb5r\xd9\xf7zq\xb4\xa8\x7fp\xff\xbeeL\x8df\x1f\xcal\xe3&\xf2s&\x8doi\x19\xba\xfa\xcaT\x94x\xf2\xc4\x8f\xe2\xe8r\x19\xe7\xe9\xd3\xa7\x84\xa8tn\x95\xaf\xfah\x99v\xe6\xf4\xe0\x8dB;\x06\x82#\xc1\x98\x9e9\x85\x12\xd5RN\x0c\x17\xca\x15\xe3\xb6\x14Dm*\x14\x95\x8aUKA\xc55\x9f5q\xcd\x0c\x19\x8e@0\x1cg\x8eR\xde\xda\n\x02\xd0\xb1 \xbc\xda\n\xfa\xd1\xe5\x88-\x9cD7\xb3{ \xdab;(_\xcd\xdb\xe4\xdd\xeaQ\x9a\x9c\xaa\x7f\x1fk|\xcc\xfaS\xd3wh\xb7\x9a\\\xdd\x94b\xe6\xf4\xd4U\x13\xf6u\x8f\xf5!8j\xefk\x16\xcf\xcbx]\x98\x91`\xc6\xc2OY \x03\x16\x8b\x9a\xef.W\x9cEq\xe6\x83\x8a>\x88\xd2`\xc6\xd5P\x07m~\xb0\xce\xe4\xbd\xc0\xac\xd5\x99#\xdcn\xad;[k\x83\x01\x93\x9f\x00+F\xc7\xef\xee\xf4CBF\x05f\x16\xc3\x8f\xc5\xf0\xeb \x12 \xc5\xb4\x14\xd3\xd2|\xb5\n\x03>cY\xacC\xcdc\xfcb\xc5\xa7\x19\x9f1?B\xe8\x0c\x08g\xb1\xfa\xd3|Q\xbfP8\x87\xa8p\x0e\xd9\x13-\xc8u\xd8\xefw\x05\x0d\xdc\xd6p|\x8f\x85\x05f\x89\x1e\x8fE\xdfC\xf16\xe9y,\xef\x0091AS\xddf\x11.\xe5\x95\x16\x0e7\x18,ey^\x7fl>T\xe8\xa5\xc8q\x93\xea\xe0Q\x80\xdd|%\xae\x89\xe4|\x0d\xc4\xce?>b\xe7\x9d\x11\x9b\xa5At\x1ar\x8c\xbf \xd9\x80\x9ba\xf9M&\xde\x16^Ja\xe8\xf7J\x887\x1cp\xba\xa6\xad\x0e\xdey\x8e\xf1\xeeN\xe4/\xc1\x98\x95\xb8\x9fC=y\xab}\xb1\xedA\x1c\x1cL\xe3\xa8\xb8;qu\xc5\xaa)\xd0\x9bri\xb7c\x9fz\x94\xd1\x99\xd1X\xa7\x16>\x00\x14\x7f)\x90]\xcd\xa4\xa8\x0e%|(\xf1\x8bCw\x0b\x17\x05\xfa\xafk\x12\xb9\xc6\xbbL\xf5\x07\xd0f\xe9\xf0q6q\xeb\x0c\x86>\x01I9\x01\xb1\x05\xd8\x91IY\x80\xa4\xbc\x8cg\xbc\x95\xa3\xb8 \x0cm$\x03\xf9\xca\xef\x95`\xfc\xc2875\xd6V@\xeb\xbbZ;M\xea\xc6\x81UL\xba6*\xf1\xec\xd7_\xcb\xebpd\xf8\xcd\xd61k\\\x17\xf8\xa5h\x1d\xb6\x18\x90?X\xf8\xe9\xab\xf3\xa8\xb8[\x1ev\"\xfd\xac\x99A\x1b\x00\x83\xd6\x8d5c7e\xcf\xd8/\x80t\xc5\xd1\x1a[4q:\xd0<\xe5\x18\x07\xb4\x06\xbb\xbe\x9b-\xdd\x02A\x8a\x95\xa1{X\xe6\x05\x83\x9e\xeb\x17\x8fm\x8f\x18\xd4J\xcc<\x07\x7f\x1e:\x8c\xdb\x97\xa6Xp\xbf\xf1\xf6\xd5\xcb\x01\x9eu\x83\xf9\xa55\\\x80z\xd6\\i`\x1f\xaao~\x1d\x96Z\x1c\xc1\x8eY,\xcf\xa6\xfd\xf2\x1a\xe8\xf2\xee\xb2\xdd\x9cL=\xb7\x862\x157\x1f[\x8fYV\x99\xe9\xac\xfd(\xa6dAb\xef\xec@\x1f\xa9\x9d!*:\x1e8\x1bC\x8f\x15\xb3\xa7\x9c\x87T\xe6\xa6\x80\xd5\x80\x1d\xd6\x8f\xa5\xb0},\xf8\xf4}\x01\xc6\xd4c'y\xc6\x12>\xe5\xc1\x19\x9f\xb1_I\x99\x9f\xb1 \x9a\xf1\x0b\xf6+\xe9\xa0\xe7\xb1\x13\xf4\xed\x05\xf7\xa4k`\xb3\xcf\xee\xf7\xb2\x04\xa5o\xd1r:\xfc\xf6\xe9`\xda\n\xe2\x9d\xbc\x8f\xeaWX\xd3jo\x05\x81v;QG\xd6\x99\xc6vY\x9f\x96\xa5x{\xeb-]t0\xddT\xcf\x0d\xa7\xf4\xff;\xac\xc6\xd7\xf8\xc5\xaf\xd7\xe44:\x1d\xe0\nfa\x1cv\xc4\xd9i\x97f\x99lz\x0en n\x85\x0f\x99\x17\xa0\x9e\xb7\xd6i^\x12\xdd\x16\xcc\xed1%\xfc\x02BK~oX\x9fv\xc6\xfa\x10\xb0\xbe\xee`\xae\xfe\x18X\x1f\xde\x00\xeb\xc3[\xc7z\x85\xc2>:\x93\x04\xfe\xa9\x8dk)V\xca\\\xac\x94N(-J\xaf`\xa5\xcc;\xae\x94\x8d\xd5zpz\xcf\xe5\x99l\xdeL\x8e\x8f\xa2O\xfdY\xa1\xc2\x10\x195\x9e\x0da\x80\xd7\xf9{L^\x139\x8a@\xd3\x06\xb7J\xc8Z\xfa%\x13\xe5\xa7K\xd6\xef\xb0L\xcf\xe4\xa5\xb2\x95\x93zln\xae\xf6y\xb7\xd5.\xe0\xb6(\xc0\xb6\xf8\x05\xadc#\xf5\x83vE\x92\x99>\x87(\xfcQR+y\xfd\xef\xa0pR\x7fu\xc5\x86\xec\x1ed\xc0K\xc6F\x8c\xc3\x85I\xb8\xed\x07\x0cZ\xa5\xb5\x0f\x96o\xcfhJ\x02\x17g\x97J\"\x81\xe8\x84\xe2=\xf0\xd8\x1c`\x92\xa37\x1ep\xb1\x13#+\xfa\xdc\x0f\xc3 :-D\x0e)\x83\x95\x03\x8e\xb9\xd9,H\xf84\x0b/Y\x90\xb2(F65N\x04\xd18\xb9\x84\xc0*_\xaf\x92x\xb5)\x88N\xfa5[\xf9\xd3\xf7\xfe)\x1f\xb0\xafR\xce\xbe.\x1a\x1c\x00\xc3Z\xfct\xdc\xaf\xc5:\x9b\xfaa(\x9aX\x0e\xd8\x1b\xee\xcf\xd82N\xb8\xe0\\\x17Y\xb6\x1a\xdd\xbb7?\x19,\xf9\xbd<\xe5\x9bP{\xb3\xfc\x8eu\x91hx(f<\x19\x07\x13v\x007+\x8b\xcb\xa1*\x0d\x89\xc4\xbb\x05/\xcf:\x15\xa2\x19\xa4`\xe5(\x18\xef\x94%\xfcgy\x90\x80TQ?O!\xdf\x1dd\xa9$\x067b\xdc\xa9\xe0H\xdb\xa5k\xa6+\xe61\xbc3\x92\xa1\x0d*\xb4^\xba\xd6B\x1co\x10\xd7\xdd\xd5#\xc6\x10c,\x91\xa4\xdbm\xee\xa4v\x9b\xbb\x8b\x10\xe11\xdb\x80\x10\x91A\xed\x16ucMV\xeaBb\xbcB\xadM\xe4\xd0\x0e\x9a5nvS}\xea\xc8\xf5\x82\x17\x9f\xae7\xbbAx-\xf0cc\xe9\xf8\xe3\xe1\xa4\xd3@X\x17\xd9\x8e\x0d\xa3\xa5[\xd8\xf6\x05k~\xbf\xeeu\x96&s\xa7\xcdWL\x95\x9e\xc5\xba?\xd5\xe5\x85\xec\x80I\xbb(\xe0\xfc4\xf1\xfa\x1b~zx\xb1*\xef\x81\xf7XGG@\xf2K\xca\xf4\x08\xaf\x9c\x82;\x89\xb7ZJ6\xee\xfd\xea\xaf*\xd7\x1b\xef\xfc\xd3\x1e,\xe0\x16k\xb2L\xef &\x9bpD\xa7W\xa2\xe3\xaa\x07\xf58r6\xe0^\xda\xddwiN\x98a,\x05\xb5+UZx\x07\xd9\x84\xbc\x9a\x9bSR~m8\x01ht\xb0T\x99\xa1\xcf\xfcL\xfb\xfa\xcc\xcfx\x8f\xc6J\xa3&\xcemY7\xe1\xa7\xfcbE\\1\xb6\xa1Q7x\x9e4#+-\xd0/v\xec\xe6\xad\x1a\x91\xb6i\x1bn\xdd\xf6\xd4\xe8\xfd\x088\x9b\xc6=\xb4y+\xc620\x03M\x05$\x98;\xf4\xa8\xa9C]iL\x9b\xd3\xb7\xea/YIs>\xc9\xf6Q\xc5V\xa6xl^;\xa9\xb0}\xc1J\xcf\x07z\xc2\xdc\xd3\xa4b7\xf0C\xd0\xe4x\xa7P\xe9\xdfR\xfb\xbd\xe1\x83\xc1\xee@z\x1e\xb8Vkg\xa5\x8f\xe9\xdd\xfb\xee\xa0\x88\x98@Y\xf3\xb6\x19\x1b\x07\xb2\x9d\x07\xa4}\xef\x83\xfb{\x16\x83]\xdfQ\x92\xb9\xdb\x18\x87aG\x8c\x9d\x1fn\xd3n\xa3\xeb&\xca\xa2\xb3\xbdep\x11Di\xc7I\xad/xuf\x19\x13\xd2\xc3\xd4j\xef\x8b\x9f\x1c\xb1\xdeg\x87\x9f\xbfxyx\xfc\xe5\xb3\x97\xbfe\xf1\xad\x90f~\x16L\xbb\x95])\x0c\xefTZ\xfaS]\xa3\xc2\"\x08g\xcf\xd7\xadu\xca\xb3\xcf\x90\x1a@\x84\x9dj\x9d\xe3/\x0f\xdf\xfc\xda\xe1g\xf6\xaa/\xa2 \x0b\xfc\x10\"\x17\xadY\xf5\xb9\xd6\xddu\xaa&<\x82\xbb\xb4\xaa\xc6\xab\x97\xcf\x0f\xad \x94+\xe8\xc7A\x18~\x89\x8eK;\x80\xa4\xa8\xf6Y0\xbbF-\xf1\xb17\xa8($@j\xc3\xa3E\x9c\x0bp\xc86\xbeZ\xcd*\x10\xed:\xc8z\xbd.\xfd\xfd,\x98]\xa7\x1a|.Zv\x86\xcfW/\xdf>\xfb\xfc\xf0\xf8\x9asB\xd5^\x1b\xc8T#k\x0c=\x87\xa2\xc5\x1c\x8dX\xef\xd5\x8f\x0e\xdf\xbcy\xf1\xd9\xe1\xf1\xa7\xcf\xde\x1e\x12\xbc\x8f\xd9Nh%:\xb0\x10\x93\xe0\x8c\xcf`5}\x9e\xc4\xcb\x86\x15\xd9\xe5[S\xeb\xb7fA\xba\n\xfd\xcb\x97p\xe3\xbb\x13G\xce\x80\xf0j\xf5X]\xac\xab\x1e\x8b\xd6H\xd1\xd4\xce_\x13\x1cgK(\xb9B\xed\x11\xa1\x9a;\xaa\xb8a\x8b\xfa}W\n\xb4\xc7\xd1d-\x15\x17AJ;\xf7\x9b\x0f\x8c\xda\xe2\x88.C\xa6\x19y\xa4\xabP\xd6\xd0\xb5k\xf7\xca\xd2\xa1\x1b\xf4\xc5\xd8;\xd6\xe8N\xad.8\x13\xaa\xa7\xed\xb3\x85c\xa4B\xcb#\xb2\xf4Z\x08\xa9\xed\xc6kt{\xa5q\xa9\n\x84E\xda\xba\xf0+\x98\x87\xce\x1d\xd8\xe8^\x94u[C\xac\xba\x8e\x82\xa8\xbdU\xf5(>\xaf\xdd\xa6_=\xd0\x9f\xba)`\xd4\xd9\x14\x90)\xb1\x97\xe0\x16A\xd3\xd9\xed\xb3\xe2 \x9c\x8d\xd8cw\xc1\x88\xf6y\xe8\xa7\xe9\x88\xfdV\x9c3\x1f\xf4!\x19_\xae\xb2 :eY,C\xcf0\x9f%<\xe5\xc9\x19\x9f\x01\xa6\x88\x9ez\xec\xeb_I\xbf\xf60\x16>n\xd8\xd1\xd1\xdd\x8c\x9dp\x06\x11\xf2A\xb4\x0b3\xdac\xef\xf9\xe5\x80}\x86M\x05\x19\xf3S\xe6G\xa5\xc1\xb4j\x11R\xb8?{,\xca\x9c\x07a\xc8\xd2L\xfc=\xe1\xcc\x9fNy\x9a\x06'a\xd1\xb8n.~\x97vRo{\x94\xd8\x0b\x80\xd6A\xea\xa5\x1e\x90~\xad3;L\xe3\xb9Cs\xa2\xd9\x01\x0b\xc7\xd1D\xca\xe9\xbb\xf7\x83\x95\xa7\xcb\xc0\xa1\xb6C\x10{\xe4\x1e\xebu\x9e_1\x95\x02\xb2\x97q\x9eh\xb6\xc2\xa0 \xcb\x16~\xc4\xe2h\xca\x07\xec\xdd\"H\x05\xe4\xe7a0\xcd\xd8\xd2\xbf\x14s3\xcb\xb9h\xc9\xc7Mm\xd0C\x07\xc8gq0s8\xc6\x95_\xc0\x8b\xc7\xa8\x80S\xb6\xa7Y\xff\xab?\xf2#\xb4\xc7\xe5\xfa\xd3\xde\xac\xbd\xc4\x07\xa42\xeb\xd04?\xcf\xe2\x93 \x9aU-\xee\xd7PA\xd3\x81u\x98f#\x98\xd6\x11+\x13\x88\x95\x8e3;b\x9d\x10U\xee\xdc\x11\xc8Te\xe1\xd0Ml\x05\x8f \x12\xc2\xdc\x9fr\x1bB\xc5g`\x87Q\x9a#\x86eXj\xc9\xb3ENDg\x9f\xe5Y\xfci\x10\xcd^\xfbAb\x89TY\x8dR\x19\xd5\x97\x99\x0f\xcbl:@\xee\x1f\xa6T\xbe\xbb\xa4\xbfw\xf5\xc0\x1c\xd7\x1bC\xbb\x8a\x1cC\"\xb6\xedJg\xf2^h4\xce;X\x8e\xad`\xd8\xc6\xf7\xda\xf5\x80sg\x85!w\xa6fm\x97M\xc7\xf9D\x0c:li\xa9\xc1\xef\xb3\xfe\x881\xcd(\x02\xd8\xd6S\xd6d7\x0d\xc6+\xe0\xac{\x05\xb7\xdc\x86H*\x06\x8a\x92w\xdb\xc1\xc0P\xbfmR\xf4\xe7L\xba\xcfN[\x03\x96\xeaO\xe0\x80\x13q;\x13\xb0\xac\x13@\x99\\_\x81_E\x85\x11\x81 \xd1l\x15\x87\xc1\xf4\x92\xfdJ\n(\xfd\x9e\xc3\xeb\xf9\x82G\xb8\x02O\x81\xdd,\x96\xa6\xa8\x02\xc4x\x89\xb3\xdf\xd0\x9d\x03\x96`\xe4\xd2\x85#^\x042\xb0\x11\xd5C\xf4\xe0\x8be\xcf\x8a\xb2\xdd\xa0/\xddA\xcb\xda\x1d8+(\x1ec\xd0\x93\\|\xc7+*7\xd6m\xe0\x15\xcc-\xbe\x13\xa1\x9fY\xf7\xfb\xea\xb1$p\xa4AY\x83\xaf~\"=\xf3Xo\xc9\x93S\xaeB\x1c\xbd\x8c?\xcbW\xa1\xd8\x90\xf9o\xf2\xcb\xd4qG\xec\xb9\x1f\x89m\x17\x8a\xb1(\x8e6\xb1\x99\x14\x08x\xe62\xe2\xc8\x82Q\xca*:=`\xf8Z\xbf\xf5.\x91\x06-\xf8\xb5\xec<\x96\xf4;\xc5\xed^p\xfa\xa9\xbf\xe4\x18\x06]l\xbd\x9dv\xd6\xc7\x02D+\xf0\xf0*\xf6\x044\x92SE\xa7~\x9eJk\xb2\xf3\xb8.\xb6u\\\xb1\xc5\xd5\x0e\xd3\x8e\xab8\x0e\xc9w\x8b\x15P\xe9\xa7\xd8\x1c\x17\"\xf5=\xbfL\x15\x0b,\x19S\xcb\x0dUeB\xd8 -\x16m\x96\x88:{i\xdd\xf70\xb04F\x83\x15\x10\xf1\xcaH\xb2\x96{\x8e\xe2\x81C\xad\xa5\x96]=\xaaL\xe2\xca{(I{\xe1\xd2\xd6#\xb2\xef\xde\xe0^\x98\xf0\xd5\xcc4\xa5\x9b\x13\xe3\x14\xc0\x0b\x1dV\xa4\xdbz<\xbb1\xe0\xad\x00\xb7\x02\xf5\x9a]]\xb6\x1e\x1524\x9e\xa3\x94\xc4\n\xec\xb5/\xd5[1C\xd1\xa9\x87P\x13\xb4\x82\x86)\x83\xd6\xe3\xe3 \x85J`\xe3\xb7\xb1E\x96&H\xaa\x89\xb4\x97\xed\x1d\xac\x88\xea\xaf\xddG\xda\xde\xa5S\x1fO\xac}\x94\xfe\xc1\xa5\x02\xa9\xb3p\x0b\xfa\x87\xf2\xf8d\xc0\xa3\x9f\xe5<\xe7o\xb4\xa6$\x86\xad}z-\x06\xdc\x11N\xca\x16g\xa3\x0e\xb0\xeb\xc3\xea\xd8\x1e\xd6\x97iF\xa2\xce\xb1\xaeT\xd7y{vB\x90\xb6\x12\xb2M\xe42\xab\xa9T\x93\x06sPV\xa2\x89yXP\x91\xd7\xee\xdc\xe9\xf0e\xf5T.\x11r\xb2]\xcf\"\xeag\xfd}\xb6\xdd\xd6>\xab\xc9,\xdb\x8f\x05L\x9e\x88\xb2q\xc4\xfal\xd8\x81O\x85\xe0\x0b\xfbH\x99\xe2\xeb\xfaA\xf8\x00\xe8\xab\"\xda\xad\xa4t\x9b[C\xe7&|\x0e\x0e\xc4\xbc\xca\xbaP6\xeaQi1\x9fq\x19\xcb\xc7>\x90\xc2\xcaWT\xa9\xb1\n\xec\x80Lv\xdcV\x81^\xe0\x10\xacY\x0evuUs2`\xa6\x7f\x85\xf8\xc4\x88-\xc5\xc9W\xa2\x7fq]]\xf0.\xe2\xd3=\xb1\xb9\xe8\xea)q\n@~_P\xc14\xd0\x14w=\xb7\x06\x91\x9c^\xad-'\xde\x04\x84\xe5\x15c\x97\x88\x9f\xb3cOO\xac\xf8\x10\xc1h\xc8Z&\x85\xe22\xa8_>\x90!O\x9d\x95n\x00\x9e\xb9\xae\xc7VN\xe6\xb1S\xf5\xc2\xd5\xcb%\xec\xb0u\xb5\x08\\EP\xc1\xe6\x0bMI\xbd\x98\xe3\x82\xacB\xef\x1c*\xda=\xd6\xc3\xc0\x07pnr\x06\x83\x81`\x98M\xd1\x16NO\xb0\\\xa15\n\xf3\xd9\xd7\xd8\xc0\xd7\x92\x93\x04f:u\xf5\xf1\xcb@%N-I\x86\x9bj\xe4w\x9a,\x93n`\xd0s\xd6\x12\xd3\x0c\x0co\xca\xe2\x91cs\xe6g\xa7zr\x00F\x0cg\xee\xca\xe0\x96\xc3\xfb;\x10\xdd\xf2v\xc7\xb3\xbdG\xdb\xe2)\x1b\x00\xb1\xd5\xc5.Ek\xfd\x12*5Z\x0b\xc1X\x1f\xeby\x96#$\x8f\xf2%O\xd0\x01\xfe\x86%\xd0\xe8)\xef*]Q[\xf3\x80\x96\xb5\x13b\x82\xc6\xbe\x07\xdf{\xbf\x83[\xe9\xb7D\x93\x8e\x9d'\x1b\xcf\xea\x08\xc4\xf6\xd9\xd0Bv\x18uz\xb8\xc1\xfao\xa3E\x80\xb7\x9e\x14A\xe3M\xa3*\xca\x927\x95\xe0&\xf5 >Iyr&\x86.\xce\xdcp\x0bXK\x1a\xc9\xa0\xbc\xe2P\xad\x12{\x10\xd1]+\xb4\x8fvr\x19:\xc7\xd6\n\x92;\xf0\xf7\x02\x91\x8a\x80\xc7\xf0\xcf\x00Bn\xa4\x98[\x8fYP\x11\xf0\x04\xb4\xcb\xa2\xb3\xc2)N@\xc8f\xb6<\x1a\xc4|\xecO\xf0\xe2\xa7xA\x07G\xb6\xbd\x8ai\"\x11\xbd\xc7u\xeb\xab-\x93\xd8\xa6\x16F\x8a\xe6\xbc6:\x08\xca\xaa +\x04\x04E\xc5F\x91\xe9\x99\xe6a\xabY\xf2\x85\x07C\xec\xbamm\xeaO\x06\x1e\xc7\x04;\xfb\xe2\xe5\x8bw\x8d\xc5?\xb4\\Q\xd5No\xb1\xcb\xb2E\x12\x9f\x83P\x05n\x119w\xdf\xf0Y>\xe5 \xeb\xdde}\x96\x81\x1b\x90\x9e\xc4`>c\xc5V\xc9fy\x82*[\x90 \x05\xdfH\xe3\x9b\x17sT\xaf\x81\xd8g\xe5\xa7)j\xe2DZ\"[\x0e\xd2\xb2\x19\x8f]\xc69\xca5\xf8\xc5*\x0c\xa6A\x16^\x16\x0bf\xc1U\xfb\xd8\xe0\x80\xbd\xab'\x81\xfe-\x8a\xc1B\xb0h\x15\xba!\x1a\x9e\xc5\xd1\xdd\x8c\x9d\xfbQ&:\x91\xf2\x8c\xf9\xd2\x01\x81X'\xa0\xbf\x93\xbd\xc2\x8eL\xfd\x08\x0c?\x80\xb9\x91\x86\x83,\x9ek-7\xb9\x96\x11\xd3\x1f -\x10\xad^\xdc{\xfd\xe6\xd5\xa7\x87\xc7_\xbd\xfc\xcd\x97\xaf~\xfc\xf2\xf8\xd9\xf3w/^\xbd<\xee\xb1>\xfb\xd2\xcf\x16\x83\xc4\x8ff\xf1\xd2q+\xa1\xcd\xb5\xe0\x9e{\xee ]\x85A\xe6\xf4z*\x80o\xe3\xe7k\x93\xdb\x15\xbd\x10\xb5\xe8\xed\x86\x01>\xdd\x00K@\xbb\xbfJ\xe2\x13\xf1\x1ed\x0b\xe63\x1c6|v\xc0>\x83 \x12\xcb5\x8b\xd9\xc2\x8ff!z\x99P\x98\xce\xfa\xec.\x8b\x13\x16g\x0b\x9e0\x1f\xd6 \x88\x18z\x08\xe1Ozh\xd6\xb5\xf2\xd1<\x8a_\x82\x8d\xd54\x06/\xa3 X\x96\x06g\x80:\x85yO\x81q\x1a\x9aM\xf3$\x01\xa3\x03\xc0)\x81\x1c~t\xc9\xf2\xe8}\x14\x9fG\xea\xbb\x1e\xcb\xa3\x90\xa7)\x0b\xb2\x1a\x12\x07\x11;_\x04\xd3\x05\xde \xa4>PAZ\x8f%\xfc\xd4Of\xd0X\x8c+\x06\xbf!\xc1\xd2\x0d\xcd\xd1\xa9\x86\xc0\xd9\x13D\xd9\xc1]\x8b&\x86\xd0\xfe95\xd3\xa0\xca\x01\xd3(\x0e\xc2\xf1\x06\xfa\xddEo)\x96\x87\xd83\x0b\x9d\xa4\xd2`\xc6\xb2\x12\x14\xc9\x80\x8f\xb2\xf8*/\xbd\xbc\x88\xceb4\xdcz\xed'>\x84u\xff\xb2\xf0\xb1\x9b\x15\xac\x84\xf4\xf4@\x124\xf0\x16$\xb6\xae]\x97\xd8\xbbD\xd6\x83]#+(\xb2\xf6\\\xf2X\xeb[\x95\xba\xd2v\xa4\xb2\xfey\xf3\xfa\xb7\x1e\xc0\xb5\x05_\x1bj\xa2\xe6\xd8[\x0bd\xb1^\x8d\x82\xff/1\xe9\x15\xbds\x04\xe5%\xa61P3L\xcdU\xf0}\xcf\x15E\x9c\xed\x8e\x9f\x82\x1a\x89\xa6\x0e\xb5\x1b\x81\xa4\xb9\xa5'\xbb\xb7Y\x9cp6\x8b9zc^\xf8g\x1c%\xf3\xc1L\xc9\x1c\x06\xecK\xff=g\xf2*//#\x8c\x94J\x85\xfa\xe6\x1b\xa4\xday\xf7|\x11\xa7\x1c\xa7&\x05\x99\xb0l7\x1d\x10\xc1k}I'\x0b\x14s\x0d\xed\x13\xba\x0d-\xb6\x84\x17\x19\xaaM\x07A\xaa^\xf5\xb8.\x85\xbbd\x1f$\xd8A\x8aB\x91\xe2\\\x9e\xd5\xa2\xa2\xa8\xc1e18&\x88*\x81\xdf^,\x979\xc4\x83/\xbeZ\xdec\x9a\xc7a\x18\x9f\x07\xd1\xa9rx\x10\x80S\xaa\xbb\xac\xcf\x02T\x1a\xdc\xedy\xacw\x17eL\x83\xbb\xe6\xd8\xe1\xc0%f\xef-\xff\x19(#\xf0\\\xe8\x0e\xe6A\x98\xf1\xa4\xe5\xa8 \xc7\xbba\xdc\xdf\xaa\x1da\xeaZ)Y/\xd7e\xc0\x07\xac\xa7]\x19\x04\x81\x04^\x94,J\x1d\xb0\x9e\xf2\xeb\xd0c\xa3\xe2G\xc0S\x14\x97\xe1\xc0ss\xe0l\x1e\xe7\x118\xa5\xbe\xab&E\x03\x7f\x16\xb3y\x10\x15a\x83\x04\\Q\xf0\xaf\xe4_\x853 \xbcC.\xc5\x1a\x0dp\xd6\xef>\x96\x9dD\xff\x13'\\J\xeaf\x83\xbbuw\xca\xb7\xbf\x1b\xde\x1aE\xf3\xd6\"\x0euo\x9c]tH\xa4d\x13UH\xa0\x1a\x12X\xaed\xa7\x97+)\x0bEQ\xe7\xad\xc8?\xeb\x02(M\xb6y+\x13\xa4W\xacB\xab\xa0\xd0b\xd7\xae\x07\x00/\xe7\xa9:#]>\x199\x8fP\xc4\xfd\xe8\xa1[\xedy\xe4<\xd8\xdb\xead\xe0Y\x1e\xa1\x87\x86\xafC\xe9l\xf0\x91\xeb\xf4\x8a\xd8\xe0\xa4\xad\xf3\xde\x96\xc5\x8a;r\x86\x0f\\\x8d\x8a\xaeq*\xb0\x1d\x084ER6\x8e\xd1c\xad\x16\xbb\x1c\xee\x14@4\x81:\xcdJ\x1c]~\xd7 \xc0\xcdV\x86\xf7~\xe2\xfc\xca\xf6\xd6\xd5Q\xea~\xe2\xfc\xd4?\xf3\xd3i\x12\xac\xb2\xab\x99\x9f\xf9\xee\xbd`i\xc2\xf2\xde\xf8'G\x17\xdb[\x9bG\x17{\x87\x93{\xa7\xf5\"\x01\xb69\xfe\xc9h\xd2wG\xf7N\x97\xe6qk\xdc\x1b\x08Bt\xaf7\xa1\xe1]\x05h\xeaGA\x16|\xc3\xbfJ\xc26a\xd5\x99\xb4\xb5\xf1\xe4\x8e!\xaf\x95\x89cA\x8fRKw\x12\x10j\x05\xfd\x010\xec\xaf\xe6\x0e\x1foM\\\xf6\x94m\x12\xee\x97\x9d\xdc\x95&\xe7N\x04\x12\xc0\xa5\x9fM\x17N\xe0\x8ad4\xd9\x11\x873\x96\x0c2\x9ef\xe8\xb6\xa4\xe7\x9f\xc4y6: \xfd\xe8\xbd\xd86r\xb8\x1d\xae'V\xbe\xb3\xa6\x15e\xb9<\x1e\xd8\xec\xff\x1f\x0e]#\xdci\xc3f\n.\xa2\x07Y\xfcE|\xce\x93\xe7~\xca\x1dpG\x02\xfa\xa3\x03&\x90\x94\x8d\x0c\x1f\x1f\x96\xe5\x15\xaf7\x84]\xca\x9e>r\xb6\x1f\xda\x96\xaf}z\x95\xb0\xdbI\x1c\xeeVG\xb3\xe6\x1a+\xbb\xb7W\x17]|/\xa6\xe4`H\xdelF\xde\x0d$g\xff\xbf1y1\xc7\xf5 \x8e\xba\xd9\x8cw\x03t!d\xb9\x96\xe5\xb8\xbe\xa2)\x84\x13\xeb\xc1r\xa3g\x8f\xf2\xaf\x0b\xcb\xea\x9aCh\x96\xf5\x80\xc5\x03\x19\x94@\x814F\x12\x18 \xd1\x90\xe2y\xa34\x93\xa8\x0e\x96\x91hd\x91\x0d\xa6\x0b?y\x969[\x16%L*\xcb'N\xe4\xb1\xa1\xb2P\x82\x08!\xd9 \x0d\x83)w\x1a\"\xb0\xe4c>\x01\xc5wU\xd8\x7fm\xda\xbb\xfd\xb0\x1d\xc4\xf6cl\x0c;\x9a\x14\xdf\x93\x98T,2\xe9\x02\xea\x80\xc5\x82w\xf7\xd8\x06\x98\x01D\xec\xe9>\x8b\x95Ux\xf1\xa9\xeb\x8e\xe6\xc1^\x9d l\xc1\xbb\x9b\xd0g\x8e\x08\x02\x97\xb4\x92\xf6\xc5b\xe3h[\xbf\xc4Ks\xb65>\xa1\x10\xb97>:\xcag\x0f\xb7\xb66\xc5\xff\xf9|^\xbf\xf4\x96\xa8B[;Xhkgw~t\x94\xcf\xf96\xfc\x9c\xf3m\xf1s{k\x06?\xb7\xb7\xcc&\xe0\xc6\x00|fg:\xc6\xcf\x9c\xd8>\x07\x86~\xe3\x9f\xb4t\n.\xf49\x07#\xbd\xd1\x19\xdf\x85\xe2\xb3\xf9|\xe2\xfe|\xfb\x03y\xc5Oo\xf7d>\x9f@\xc2\xd4\xfe\xa1T~\xa8\x08\xe1sU\x84\x01r\xc5[\xef\xa0V!T\x9f\x99\xf3-\x8e\xff\xe6\x93\x03\x15\xe1\xc9\x91\x9d\xde\xde\xda\x9a\xc9V\xc7\x18\x93)\x9f\xc8\x95~\x85A\xe2\\k\x1b=\xf7\x93\xfaY`\xaa\xf5r\x1c\xa8\xae\x1e\xf4\xf0\x1a<(\x08\xa3z\xfb\xb5~\xcf\xd9\xbe\x0c\x8c\xe0\xc0\xe8\x9c\x83\xfdr\xa40\xe8)F\x8a\xec\x9d\xf6\xae\xbb&\xb8\xe4*\xe7p_t<\xb9\xee2\xde~hc\x08m\xcb\x98\xf2%/G\xdb\x1b\xdf\xfdo\xbf\xf3\xbb\x93\xde\x8dF\xd6\xbc\x9d\xa8\xdd\xdd \x1c\xb1o\x14,\xbe\x0f,\xbe\x0b\xce\x1ez\xbd\x1b\xdd9\xd2h\x9c\x058\x06\x0b\n\x87\x9e\xf1\xd1\xc5T\x1c\x8bf\xbbG\x17\xb3\x87\x9bG\x17\xf3\xdd\xa3\x8b9\xbc\xcc\x8f\xf2\xad\xa1X\x19\xf9\xd6po>\xb9w\xda\x00\xc2u\xc9\xc3M`\xed\x80\xd0\x1a\xa4\x82 \xa9U\xd0\x0c<\x96\xd4a{} \xdew\x9d\xea\xd7{\x7f\xf8;\xbd\x11\xeb=\xab\xad\x9b\xde\x1f\xfe1:\xf9\x8f\xd3\xc9\x7f\x82N\xfe\x1f\xe8\xe4?I'\xffC\x91\xec\x1b\xc9\xff\x88N\xfe\xc7t\xf2?\xa1\x93\xff)\x9d\xfc\xcf\xe8\xe4?-\x92\x9f\x1b\xc9\xff\\$O\x8d\xe4\xbf\"\x92\xeb\xde\xf1{\x7f\xf8\xefD\xf2\xccH\xfe3\"\xb9\xee;\xbe\xf7\x87\x7f\x96N\xfest\xf2\x9f\xa7\x93\xffg\x91\xcc\x8d\xe4\xff\x85N\xfe\x17t\xf2\xbf\xa4\x93\xff\x82H~a$\xffE:\xf9/\xd1\xc9\x7f\x99N\xfeW\"90\x92\xff5\x9d\xfco\xe8\xe4\x7fK'\xffU\x91\xfc\xd2H\xfe\xf7\"92\x92\xffG\x91\xfc\xcaH\xfe\x9f\xe8\xe4\xbfF'\xffu:\xf9o\xd0\xc9\x7f\x8bN\xfe\x0f\"96\x92\xff#\x9d\xfc\xbf\xd2\xc9\xff\x1b\x9d\xfc\xbf\xd3\xc9\xff\x89N\xfe]\x91\xfc\x95\x91\xfc\xb7\xe9\xe4\xbfC'\xff]:\xf9\xff\x14\xc9\xb9\x91\xfc\x7f\xd1\xc9\xff\x99N\xfe/t\xf2\xdf\x13\xc9\xf5\xd8\x01\xbd?\xfc}\x91|i$\xff\x01\x9d\xfc\xa7D\xf23s9\xfc\x9eH\xf7\xcd\xf4\xbf/\xd2\xdf-\x8c\xf4\xff*\xd233\xfd\x1f\x88\xf44\xad\xa7\x7fK\x93\xe5oi\xfa\xfb-Mh\xbf\x05\"n\x90\xb7o\xff\x04\x9d\xfc'\xe9d\x80\x80A\x0c\xbf\xfd3t\xf2\x9f\xa3\x93\xff\x02\x9d\x0c\x84\xd6\xa0\xa8\xdf\xfeY:\xf9\xcf\xd3\xc9\x7f\x91N\x06\x12d\x90\xe5oij\xfd-P&\x83Z\x7f\xfbW\xe9d \x13\x06\xfd\xfd\xf6\xaf\xd1\xc9\x7f\x83N\xfe[t\xf2\xdf\xa6\x93\x81\x04\x19\xf8\xf6\xed_\xa7\x93\xff&\x9d\xfc\xbbt\xf2\xdf\xa1\x93a\xcd\xfe\x9a\x91\xfc\xf7\xe9\xe4\x7fH'\xffc:\x19\x16\xe7\xa9\x91\xfc\x0f\xe8\xe4\x7fD'\xff\x13:\x196\xfb_7\x92\x7f\x8fN\x06\x1e\xc0X\x98\xdf\xfes:\x19\xb6Xc\x07\xfb\xf6_\xd0\xc9\xff\x8aN\xfe7t\xf2\xbf\xa3\x93a\xfb66\xb6o\xff%\x9dLo\x9a\xdf\xd2\xbb\xe3\xb7\xff\x9eN\x86\xed\xe47\x8cd\xd8N~j$\xc3v\xf2\x9bF\xf2\xff!\x92\xdf\x1b\xc9\xff\x89N\x86\x9d\xe0\x0b#\xf9?\xd3\xc9\xbfO'\xff\x01\x99\xfc\xdd\x1f\xa3K\xc3.\x13\x1a\xc9\xff\x85N\xfe\xafd\xf2w\xbfC'\xffq:\x19H\xaf\xc1\x8d|\xf7'\xe9\xe4?M'\xff9:\x196\x01\x83\xa5\xf9\xeeO\xd1\xc9\x7f\x86N\xfe\xf3t2\xd0o\x83I\xf9\xee/\xd1\xc9\x7f\x85N\x06Bm\xf0\x17\xdf\xfde:\xf9\xaf\xd2\xc9@c\xdf\x18\xc9\x7f\x83N\xfe[t2P\xcd\xc4H\xfe\x9bt\xf2\xef\xd2\xc9@\xa8\xdf\x1a\xc9\x7f\x97N\xfe\xfbt\xf2?\xa4\x93\x81\"\x1b\\\xc1w\x7f\x8fN\xfe\x07t\xf2?\xa2\x93\x81\"\xbf3\x92\xff)\x9d\xfc{t2\x90\xde\xccH\xfegt\xf2?\xa7\x93\x81\x98\x1aL\xe1w\xff\x82N\xfeWt\xf2\xbf\xa1\x93\xff\x1d\x9d\xfc\x1f\xe8d\xa0\xb1\x06\x0b\xf9\xdd\xbf\xa4\x93\xff5\x9d\xfco\xe9\xe4\x7fO'\xffG:\x19H\xef\x8f\x8dd \xbd\xe7F2\x90^\x83\xc7\xfd\x0eH\xaf\xc1\xcc~\xf7\x9f\xe8\xd2@z\x7f\xdbH\xfe\xcft\xf2\xef\xd3\xc9@L\xbf1\x92\xff\x0b\x9d\xfc_\xc9\xe4oav^\x98\x1b\x0f\xc0*0v\x9e\xef\xf0\xb8fp.\xdf\x01\xb3\x14\x9b\xe9\xc0X\xde5\xc9\x1b\xec\x1bi\xa9\xd9\xb5)Hi\x8f>\xd7\x16rw\x12\xb0\x11\xce\xd4F`\xa3[\xa9p\x03\xc9Z=\xf6\xa3\x12;R\x96\xdf\x84\xc4M\x9am?l\xf7\xbcG\xabT\n\x0b\xc5}\xd0+x\xba\xea\x04u\xf4\xfa\xc0AA%\xd5\x10~\xa9\x86\x80\x00T(\x87\xcd\xba\xc9a)\xb5\x01\x18Tlmm\x1e]l\xcf\x8f.v\xfc\xcd\xa3\x8b\xfb[G\x17\x0fN6\x8f.v\xb7\x8e.\xf6\xc4\xcb\xde|\xd2\xbfw]%\xa3\xeadt\x93N\xfa\x9b\xdfL\xc6\xcf6\x7f{r\x05\x7f\x7f\xbe\xed}\x80\xb4\xab\xf1\xd6\xe6\xa3\x89x\xc5L\xf9\x02\xa9W\xe3\x9f\xe0\xcf\xad\xcdGlr\xef\x9a\xdd\x8f\xd0Pb-\xb5O\xa1\x939:\xba\xf0\xa7GG\x17'\xc3\xa3\xa3\x8b\xd9\xde\xd1\xd1\xc5\\\xfc\x01\x01\xab\x008B\x1c@\x8e0\x07\xa0#\xd4\x8f.NP\xe0\xba%\x05\xae\xbbsvt\x94\x89\xea'GG\xa2\xae\xbf\x05r\xd9\xf9\xfc\xe8(::J\xa0\xd0\xf6C\xfc\xf7\xe8\xe8(\x1f\xee>\x14%\x86\x0fA\xf9 \x1a\xc2\x7fC\xfc\xb7\x8d\xffv\xf0\xdf}\xfc\xf7\x00\xff\xed\xe2\xbf=\xfc\x87mn=\xc2\x7f>~\x01;\xf7@\xfc\xdb\xd9\xda\xda\xaa\x11\x18\xd46\xf5X\x9fE\xac\xcfz\x16M\xd2\xac\xdf3\x17\x1cH\xa1\xb7\xf7\xe4\xb0\xf7Nh\xa5\x91\x98j\x01\xd4\xb9\x80\xd4|\xf7\x08\xa5\xddG\x17\xa6\xea''5Q\xaak\xa0\x18\xa9}\xd0\xda\xf4\xb3\xcd\xdf>BA;H\xdaQ\xd4~t1\xe36u\xd3\x1az\xad\xf0Zz-\xd0\x18\x8d;\xf7k\xae)\x98\xfcB\x0d\x96S\x8a\xa4\x95Vt\xda\\t&\x8b\xae\xa9>\xb8\xb2\xa9\x12\xdd\xba2naU\xc6\xcd,\xca8R\xf5\xc8R\x8f\x85\x9d\xf4s3Z?wV\xd1\xcf\xd1\xed\x89\xbc\xda}\xcbe\xa9b\x19OQ\xa3\xa7\xe0\xdf\x17`\x03\xc5\x95s0\x9a]\x85\xe1\xd5\xf2*\xe1W\xe9Uvu\xc6]\xf7@\xaa\xef\xc6\x89\xc7\xa6\x1e\xeb\xfd\xb0g\xaa\xff\xd8\xcah\xe8\xb3\xab/\xbe\xb8\xfa\xf2\xea\xcd\xe1\xd5\xdb\xabwW?:\xac5\xc4\xfalnk\xac\xec\xdf\xbcK\xffT\x8d\xb6\xcf\xf79\xc0\x1d\xeb\x87\xd7\xa6\xec\x1b\xce\x06\xd8t \xea\xa6l\x10\xc0\x14\x97\x1d\xb0\x15\x18A#\xe3\xef\x17\x0eG\xd9Z\xa8S\xdc\xb5~d\xbdk}o\xfc\x93\xc1\xa4\xff\xc3{\x03~\xc1\xa7N,z\x10\xc35\xb1\xf2m\xf0\xe2\xf0\xf8\xf5\x9bW\xef^\x81\x91~\x0f\xac\xb8{\xe8\xc8\xd1I\x93\xa9{<\x1c\xa0E\xd3\x88\xf5z\xd7\x85\xc4F >\x18@`\xd6k\x8c\x14\x91~\xcf\x1d\xf7\x8e\x8f\xa7q\xc27\x7f\x9a\x1e\xa7\x0b?\xe1\xb3\xe3c\x9b\x95\xfdu\xa5\nv\xdf6\xed2\x83\xf6s[7\xb0\xa9\xad\x01\x88\xcb\xc2\x87\xcd\xe3\xce\x1de\xde[!JcN{\x05)\xe9\xd2\xe6>\xcb\xd8\x01\x1b\xb2\x11l\xda\xd7\x05\xbf\xa0\x9e\xc4 \xeb\xf88\x8cg~\xba8\x16{\xfdqqg\xe8\xf8\x988v\xb5\xb8OX\x17\xb9*PR\xf0\xa8\x02#\x983\xc7pZ\xcc\xb4\xf3sf\xc0\x8fULN\xf7\xd1\xa6\xb4\x98\xee\xa6@J\xb2VPx\x15\x86\x95.\xbeP\xd8\xfd\xde.\xf0\xbf\x7fx\x16\xc6\xe7\x07\xd5+>0\xc4X\x1b\xf8\xed\x0e\xb4\x01\xcb\xda\x06\xd9\xe4=\xacu\x9c\xe5\"\xeaW\x17#rdC\x8fEb\xe8\xfbh\x8d\xaf\x89\xd82i\x9d\x9c!\x83pS\x02\xd1\xc6\x96\x8c'\xb7\xc4\x88\x0cw(\xf6\x18\x83\xd7h\xcc\xd8*\x0c\xa6\xbc\x0d\xf2\x9d\xd0\x8bf}\x13D\"rN6\x9c\x88=A\xc7\x11N\x04\x9e\xa0\xd4\xd5\xd4M6\x14\xebm\xb0\x8a\xd1WD\x89\x8f`\x1e\xef\xb1\xcd\xcd\x02H\x1e\xdb\xba\xd6\x9e[@\xe9\x174z\x1c\xbb.\xba\x1dG\x93\xf1\xb0m\x0b\xba\xd5\xa1\x146\xaa\xd5\xb1\x08rW\xb91\xf6\x11\xba\xd2u5\x9b\x80\x8d\x01\xb0\x91\x15\xb0\xb1\x04\xac\xd3\xefkH\x12a\xec\xd0\xb1\xf8\xf0\xc4\x85\x08P\xe3X\xc0[F9j_\xdb\x0d\xc3\xddn\x1d\xae\x0d\x89\x12\x15\xf9\xcd\x95G+\xdb-\xa1\xebr\x01\xad\x14\xc9\x8e\xdf\xd2S\x1d\xd9\x9d\x1e\x9e\xe8\xd1\x81\x1b\xf0\x9bQ\xbe<\xe1\x89\x96\x90\x02\xe7\xa9%\x9c\xc4q\xc8}\xe9\xf4M\xf0\xa6\xc7\xc7@\x89\x8e\x8f{2\x10\xc0Hs\xce\xf7}\xceFe\x1d\xc0d\x9c\xf2\x0eb\xfc\x8f\xdc\x07\xdc\xa1>f\x1f\x1a\x16a\xd9\x0fz\x05F\x80\x8c4e\x03\xc1\x034\xeeU7\xdeHnk\xc8\x8a\xc9\x8d\xf7fK\x8f\xb6{7\xae\x8eI\xe5\xdc\xfdV\x90X\xa6\xa5(\x80{\x10\xe9u\xef\xac\xe2w\x9d\xbcI\x06\x8e/b's\xa9\xfa\xaa\x8dT\x11\xb8\x1d\xa2\x05&o\xaa\x05\xe0{(j\xec\xbb\xfe\xc8q\xa4N>\xe6\x13\xb8|\x90wu3k\xa6\x9cI\x8f\xbc\xbc\x00\x87\x95\xf3\x0ea'a\x07,\x1f\xa7\xc0C\x87\x82\xc1\x0c F\x9a\xb1\x1bH\x03w\x87\xf5[ \xf2\x02\x84!`AL\xd8~\xd4*A\xb2\x12\xc6\xd8F\xa3\x87\x15&\xe6\xce\x1d\x96\x8d\xb7&\xe3\xed \xde\x19\x14\xef[\x82\xbd\x13/\xc3\x89\xd8\x82\x8ao5\xdd`\x8e\xa4\x13Q\x88\xb6\x16QAB\xaf\x0d\xb5\xa1qwF]\x8d\xa3\xa064%U\xdbm0\xc4\xaf\x0bd#\x80\x99\x02\x1d\x91n4\x8d\xe1\x0b\x04K\xcd\xe4)\xdbg\x1b\xb9y8,\xce\xf4\x85\xdf\x98\x8dZ\xfc\n\x10\xb0\xf2\x8a\xc7\x03\x96nnZ\xa5\xabs\xd1\xbdqjq}=\x85`\xa18\xbbs\xc1G\xc0\x166\x9e\x8f\xb7&\x02\xb97\x1c\xf1\x06b\x92\xd2\x93\xcdFS\xac\x0f\xe8\xdec\xd6\xef\xa7\xec \x0b\xad\xbdZ\xb1}\xe6\xa8\xae\xb9V\xe7i3\x10\x0d\xaf,\xb9\x0b1IV\xaf\xde\xc5\xd0l\x04\xa5\xe6\x90\x04B\xdco8\xab\xe6\xd1\x8aG\xc6}\xb7\xd3\xbe3\x86Q)\x1bBQ\xe7.\x94\\\xb2}\x96;3\x8f-<\xb6\xc2U\xe1\xb13\x0b\xc5\x04\xba\xabwy f\x12\x0b\x8f\xcd<\x16\xb0+y_\xeeL,\xcae\xf3\x08\x1afP\xd5\xba\xc1\xa1\xad\xf5\xeai}J\xea\x07HT\xd1\xacu\x86\xbc\x01\x8b\xd8~\x04\xca:\xf3\xb5\xa2\xac\xe4\xd5o\xbd\xc3\xfa\xc7T\x7f\xbb\xf1x\xb7\xf4\xad\x9b\xf2r\x16\x8d\xe0C\xea~\x9fH\xaf\x97\x07b\xbd\xd5\xead\xa1\xeb\xa9\x8c \xbfLy\xd9\x8a\xe7ft1\xa6\xb1G\x91\xa5\x15V\xf0Gb\xab+\xdcT=a>\xdbd\xc3bM\xe6\x95\x83\\\x15\xd3\xfb\xfdH\xa2\x90H5\x9b7\xc6!\x17L\xe0\xe4\x1d\\M[\xf8Z\xc5\xd6\xde\x90\x93\xb5n\xc5u1\x9ade\xb7\xa9x\xa7\"\x9d\xd2\x1c \x14\xaa\xab?Sl\xbf\xaeq\x08ew\xea\xcdL%\xdfTO\x9f\x9b\x9c\xc1J\x0f\xac\xfaLy\xf0\xac\x9b\x97\xcc\xaa\xa5\x12\xff\xb2^b\xa1\x97\xc0M\xbb^\xe4\xec\xe6\xc2S\xc5\xa2,=v\xea\xb1K\n\xffO\x04+\xe2PG\xa1c\xc8\xc9\x88\x9cs\xb6\xcfN\xd8\x01\x9b\xb1\x11\xcb\xc9\xba\x87l\x9f\x1d\x17%\xa86.\xc4^/\x1a:\x17\x9c\xcd\x8a\x1d\xb0\x05\x1b\xb1sW\xfc\"8\xa6\xb7\xa2\xb8h\xf5P/~h+\xfe\\5|h.\xe7\xe7bK\x0fA\xd7e\xaedX\xa5!\x9cb\x8a\x8d\xd2\\l'\xe0+\xc5\x83A42>\xc5\xf76.\x8a\x06/A*x\xa964\xd7c'\"e\x8a\"\xdb\x98\x98\xb5\x11\x0bd\xeay%\xc3\x1c\xdb\x86\x13\xb1;lN\x0eM\xcc\xf6{\xb6\xcf.@\x0c\\\xb8\x96\xe9\x1d\x1f\x9f'\xfej\x05\x82jb\xa2\xc4\xf3\x8c\xed\xb3\xb7Z\xb5\xac^\x8d&w\xef\xc5\xb8\x9e5\x9d\x07_\xb1}\xf6\x9e\x1d0>\x00Wr \x11mp\x9a\xfe\x9a\xed\xb3g >-\x8bg4[d\x05\xf6\xa9\xf3\xcac\xaf\x15\x1c/\xdb|^\xd3l\xd0\x06L\xaac\xb6\xee\x9b\xd3w\xfd\xad\xd1\xd8\xea\xe4\xc1o\x9b6\x96\xd9\xdd\x1ev\xf5\xe3zv\xcbf\x1du.M\xb7\xef\x80\x02\xfel\xe6\x80w\xe1\x1a0\xc4\xe3k\xf4\xcd\x9f\xcd\xc0\xabP\x99\"\xb6D4\xca\xf0\x0d\xfb\x8b\xa0jj\xe1\x93\xf0\xad\x037\xba\x99\xae\xa6\x13O$w\xd3\xc8\xed\xb4s~\x9f\x8cX\xfb\xb7\xec\xbae\x00\xbb\x93\xb5}\xc2\x8a\xd06/I\x86\xb9\x93d\xf5\xb6(7\x17\x14\xdf\x90K\xfc\xafo\xf8\xa9L\xaf\xb7\x13\x9a\x1b\xbb\xe0\x01\xb6\xcd\xed\xbf\xd8\xa3?E o}\x93\xae\xf0\x03\x9f\xf9\x99aiZa\x05\xc0\xa3e#+\xf0\xa5\xbf\xa2\xf8\x00-\xd8\xfb\xf2\x84\x1bM,\xf5\"h\x97R/r\xaa\x17y\xcb\x0dn\xe3\xb2\x92\x0f\x12\xf0z\x91\x93J\x11\x10\x81\xd7\x8b\x1c\x1b\x8c\xcf\xa7\xf9|nv\xf8\xbc\x066\xffG\x01?\xaf\x17:,\x9c\xaa\x15\xeb\xde\xe2\x9b\xea\x02\x18\x83\x03v\x88\xfb\xc2\xabyg\xd7k\x8aX'\x1e;\xf4\xd8[\x8f=\xaf\xe3~z\x1e\x80\x0f4R\x8e\x05q\xdc\xceGF:\x93; \x1f\x9c\\f\xfc\x0bd\xf77\xc41P\xfb}u\xc50\xff\xd5|\x9e\xf2\xac\xcc\xc7\xdf\x8d\x1c\x88x8x\xa3:\x01\x00{\xd2\x1b \xfe2\xcbCG\x8f\xe9\x8e\x16:\xcb\xb6\xden\xbcu\x04u\x8f1\x18\x0c\xbce\xaeKl\xfe\xf0\xb5\xb9\xf95H_Y\xd2\xcf\x1a{\x178}\xee\xb1>%y\x86\xda\xb3\xc6\xda|\x10\x81Oq1&x\x03O+K\xe53\x1c\xc2\x9d\xe0\x0fK\xf3KK\xa7/\x9b?\x8b\xfa\xa0~\xc5(\xa9R\x7fA\xd7W\xbcZn\xa9vj\xaf\xf6\x0c5\xfd,\xb4\x8b\x8b\x80/sD\xfb)x{\x85\xb3\xde\x86\x12R\x00\xbb\xfa\xac\x15\xfb\x14\xfb\xf6\\\n\x1b\xec\x9f{U\xb4\xf5\n\xe0aa\xd8\xd8\xd5>\x9bz\xecyy\x14\xb5\x7f\xf858\xb4{\x0f\x88\xf8\x1eC\x15\x94\x0b\xb8\x91!|^\nm<\xf6\xda\x02\xde\x13\xfb\x8a.\xf9\xf8\x0b\xe55P\x0cJ\xfe\xb0J\xaf\x99\xb6\xce\xda\x94\xcf\xed[\xf4\xba\xec\x9c\x0c\xe1\x04\xd3K\xcb\xaa\xb8\x195\x82\n\xa5\x0e\x0d\x8e\xfb\xfdl\xc2\xf6\xc1\x86\x9e\xd7\xee\xa2\xb9\x1fC\xc4\xf5q\x86\xd786\xbe\xf6\xb0\xecv\xb3\x8f(\xf1\xc7\xd0\xe4xn\xe9\xb0\x8f\xf2\xde\x94\x02\"\x08@\xd8\x1d\x16\x9bp\x9c\x82f\x8e:\xcb\x0b6hJ\xf2\xffb=\xcc\x05\xe1H\x9c\xcc\xd5tC\x1b\xa1\x95z\x14\xd1\x8a\x04\xe34\x7f\xccV\x0dJ\n\xc1:M\xc7+\x8b$\x7f\xc3 A\xc0\x00^\x9aG\x9aA\xdb\xcc\xed\xa8\x95\x10\xdfX\x80\x190E\xc1\xc47`4\xa9\x0c\x87R4\xba \xa8\x98\x12\xf0o\xd4\xbc\xab\xa6\xba`-U\xf1P\xea\xdf*\xa0\"\x18\xb9P\x1c\x9eV\xec \x9b[!s\n\x1a\x10\x05\x1f\x8b\"\xe4\x12,\x07g\x16\xf0\xf9n!\xfe \xe1B\xe5%\x1cWg\x80E\x1c\xf0g\xc4|G\x9c`!\x15\xd1+\xb5)~u\x05\xc4 ;\x10=\xdc\xdf\xc7\xd3w.\x1bA\xd4\x84vO\xecJb\x90\xa8\xd0\x14\xfc$\xe1\xfe{#\xc7T\xe1.a{\x03\x9exZ\x1a\x92\x83m\xc6\xac\x89>\x83\xea\x07\xf0wi\x03\xfc1\xb0\\Z\xab4\xe8\xcf\x81\x17\xd3\x8a\x99\x03:\x16\xeb\xe6\\|\xad\xda\xc9@F\xec0R3\xd4D\x91\x01\x06\x8fE\xde\xb1.\xa6\x86\x14\xb2,|\xf3\\/{\x8eF\xdf\x08\xfa\x0e\x1bX\xaao\xa1\xc5\x0f\x81\xe0g?\xa8V\\\x9f\xf4\x13\x87\xcfJ|\xc7\xcd!F\x83\xb5 (\xd0\xdc|\x0b\x03>\x8e'b)E\xec K\xacK\xc9\x87\xa5T\x8fZ(\x9e\xcc\xf1\x01i\xd1\xac\xd9 \xc6q\xbf\x0f\xb1\x0e;\x80(\xf8\xde\x00\xa1\xa23\xaa\x91\xf2\xc7.K0(cf\x04'\x91\xbdKZzg7E\xa0\x05\xf9\xf7\xa9\xfb\xe2\x94\x94\xbcm\x0b\xb3\xc8\x1dbiZ\x9eHf\xeb\xc6\xd0\xb5|\xa7\x953[\x170C\xcbMz\x03`>\x84)-\xc1\xe3\x8f\x0b\xf0}\x1e\xc6~\xb6\xb3-\xb5\x08\x80\x80\xb5\xcc\xdd\xfbt\xe6\x8b({h\xcd\x19\xeeZ\xb3l\x1f\xfb*\xb06\x08Y\xcfC\x7f\xb9\xe23{ \xdb7E^\xe5\xa3\x1b[\x9e\x9e\xafaP\xad&\xdd^E\xf0P\xcb+\xe48\xb5\xf4R\x08afp#Q\nr\xea\xb3!q\xc5\xc8\x00\xa9N-MIrj\xc9J\x17TKVB\x9dZ2\x08r\xeaiRxSK\xfe1\xf7\xdf\x17\xfd\xd8\x18z\xeb-\xc1@.\xc1\xd8\xe1E\x94&\xb1\x1fm\xf8c\xb1*o`\xdaK\xfb\xa0\xd85\xac\xdfn\x81C\xae\x8f\x0dc5\xe9\xf1\x98L\xfb'u\xf6\x18O,,[$6\xe7\xc2\xec\xc6\xd5\x9c\xf6G\xae\xb9\x91o\x00\x03~\x87e\xa8\xea\xb5\x10\xe86\xcb\xd7\x86\xb3\xc6\x9e\xebh\x81\xb6<\xd93\x8b\xe9\x05}\xfd\xc8N\xe5v\\\x07\xae8y\xac\xa7\xd6\x8b\xed\xe2\xd9\x0d\x9a~\x9d\xc4\xcb \xe5\x1f\xa1\xe5\xb7<\xfb\x08\xad\xca\x95uK-o\x1b\x97v\xe5\x8aX\xdf\xc0\xb3\x12\x856.B8gE\x00\xda\xa8\xe1\xf4\x15\xc0\xf1!\xb2\x1c.\x90m\n(\xb6 \x99\x0f\xe9\x06\x96\x95\xd2E0\xcf\x9c\x06D\xd5.\xfe\x03k\xd1\xb64E\xf9\xc0\x89\x8b\xbd\xcb\xde\xb2x\x00\xf8q\xc3\xa2\xa2)-\x99\x8aS\xe1$\xec\xa9\xf4%\xa6\xf6\xbc\x91\xd8\xc0Y\x9f9\xd2\xc8\xfd\x80\xf5\x9e\xdc\x13TM\xfe\xee\xb3\xde\xd3\x9e^Jn\xa0\x82\xa1\x8aD\xe9\xa3Hf\x83\xa6\x10\xe4\xa0\xd4\xc2\xb3\xcfb`\xdf\xc2\xd4)kC\xc7\x138J\x96\xbf\x07\xfej\xc5#\xf0\xef\xe0\xe9\xf84\xc0\xc4\xb8\x92\xa8\xcc\x18\x9c\x0dq\x06\xdd\xd8\xeaB\"\xe0N\x06br\x01\xb5*\xbc4pi\x80*W\xbf2s=`=\x86e\xb5\x072\x0e\xd6\xabN/\x8a3\xe6\xa7ip\x1a\xf1\x19\xcbb\xe6\xb3\x95\x9f\xf0(\xdb\xa0\xf8\x07\xf5\x9ci\xfe\x91\xe8^\xaa\xa7\xf4H\xa3 f\xec\x0d\xe7\x8e\xd6[IT#\xaf\xd2\x02\x8a\x80\xfa\x82\xc1P\x94\xd6\xf5\x9agE\x7f\x14{\xe9P\xbc\xa2zlT\xca\xc2f\x08\x9a\xd7uJ\xb4\x0d\x17\x0d<\xc4\xd0\xe0\x84\xcb\x95\xd7\x1d\xc1\xe7\xaa\x1c\xd1\xd3\xce$\xd3*\xfa\xac]d+~}pK\xc7\xc3\xce\x83\x07\xf2\x80\xdd$\xe8W\xdbyu\x80\xbd;\xbd\x11\xeb\xdd\xf1\x97\xab\xc75\xa2x\xb7wW\xe4\xfc,\x8f\xb3zV\xef.VZ\xc5\xa9\x91\xf5\x04\xb2B\xb3\xceS\xc88\xcd\x1ek\xc1\xfa\xda\x04\xe3\x16\xa9\xb8$^\x92\xb2\x01\xf1*\xc4=\xce\xf8N\xef\xc9\xd3\xbb\x18c\xa1U\xd8\xa6\x04\xccFP>\xe0\xd9\xca\x8e\x92\xd0\xad\x91G}\x08\xf1\xe3\n\xdc\xa5\x19\xc1\xa3\x1dwpx\xc6\xa3\xecp\x19d\x19O(o\x1f\xe6A:\x913\xbd\x08\x0cu\xb5x\"\xe7\xe1\xd0ub\x0f\xfc\x97\xc4\x837%\xc5\x14_\xbc\x0f\x89?N\x82\xacH\xdc\xdd}\x00\x89\x9f\xe5\xab\x90_\xc8\xa4]Hz\x97\xf8Q:\x8f\x93\xa5L\xdd\x83\xd4\xd7~\x9a\xbe[$q~\xba\x90\xe9\x0f!\x1de\xe2x\xb0\x8bu\x97\x1f\xc1\x8a\xb7\xe97\xce4\xdf]6\xc9yL\x9fF\xf9\xe0\\\x0d\x07U \xb8\xd5\x88D.j\x80\xd5\xd8\xca\xcfS\xae\xbd\x1a\xc7&\xfa\x93\x01I\x85\xa2r\x1f\x82\x16\x13\x9e\xe6\xcb\xca{\xe3\xa9,\x1a\xc4Q\xc1\x92\xc5`,\x08 \x89\x1fD=\x8f\x05\x90r\x1c\xa4o\xb3Y\x00r\xfcL\x1b\x18\x1e\x9e\xc1\x119\xd4\x12l\x9c\xc7r`\x88\xc4od\xdb<\x96\xd6\xa5xg\xd2Ztch\x83oN\x0e\xd6\x87\x8f\xf9r\xc7\xe5H\xc7\xbaA/\xed\xd0 y\xa9\x8d\x0ff<\xcd\x92\xf8\x12\x17\xb6\xfc\xd1\xf5\xb3!M\xb7\xc5\x16:u\\OZ\x02$\x830H3\x1e\xf1\xe4\xb9\xd8\x87\xa4\x13\xe1\x1e\x17\x9bi\xcfU\xfbk\x9d\xde\xd2_\x9cZ\xd1d\x19\x9f\xf1/\xe4wjsndj\xf3oV\xd5\xe7\xb9\x9eW\xce9Y\x13F$\x98%\xea\xabz\xae\xed\xab\xd3\xc6\xafN\xc9v\xcb\xdc\x86\x95\xa0\xc8-br\xa5\x9f\xf5\x14\x1d\xdb\xa7\x06\xb6O\x8b:\xd5\x14<\xca\x08\x02\x04gL\xaf\x95\x86\xbb\x10`\xa9\x89\xac\xf7\x04!I\xb3$\x98f=\x92\xaa\xdf\x1f\xba\x03\xbc\xadDZ\x08\xec\xb6z\x9c\xaf\xe3R\x81f\x9cD\xb3\x8d\xf6m\x8d\x15\xa6\x91\x9ci7E3Wg#\xdf]\xae\xb8d%\x9f\xfb\x91\xe0&\xc5>\xc3|6\x0d\xfd4e~\xca\xfc\xe2K\xc4\xb9\xf0C\xe9\x86\x1b\x19\x9e\x05\xf7g\xd2LK\xa6d~\x10VS\xe4y`\xdf\xea\\\x99i\xbb\xbc\xe9E\xaa\x99QS\xbc\xad\xe5h\xe9g\xbe\xd5;Y\xc4/2\x94G\x99\xe34y3}(O\xc1\x16\xa9\x18.\x88}@Q>\xaa@%\xab\x82$\xf3\x98\x8c\x01\x80\xcdT\xa1\xe1U\xc6\x9eG \xfc\xfe\xf8\xc3/\xfa\xdb\x05\x062\x06\x89\x06 \x10\x06\xebc\xac!\xc6:c6Fl#\xf0R\x00V\xb6\xdat`\xe5\xeaH#z4\x10\x10\xa1\xcf3\x12\x01\x87\xc6\x10\x0f\xaa\x03\xaa\xe1x}\xca\x8b/ \xf0\x16\x91A\x949\x05a\xce\xde\x04\x11\x15\xf5\xae\x11\"M\xbdkY\x81\xd5\xaf\xfd4\x0e\xda\x1d\xb8#\xfc\xf7\xeb\xf0\x97\xd0\xa3|\xe6Tn4\x15\x9d\xc5kM=\x14\xc7\xc3\xacHoH\x02n\x8f]\x16\xb1\xfe>\xe8\xc03\xcb\x9c\xd1f\"5\xf8\xc5\xd1\xd4o_D\xcdcJ\x06~\x18\xc6Sg\xcbb\x8an`LQ\xb3\x0d\xedJ\xc8\xc0\xb19F\xb3)\xf9\xbd\xaf\xa2\xd4\x9fs\x87\xb3\xa7O\x9f\x82x\xd2\xaf\x82/\x17\xd3\xf9\x98\xf9\x8f]\x00\x9c\x0f\xdf@\xa8\x06x\xa3>\xf7@\x97\xb6\xbaD\x9b\x1fQ\xa5\xaf\nV\x0c||\x04\xba\x0d\xc4\x81\x01\xe2\"\xe1\x83`\xb5d\xf4\xb7 JW|\x9aU~\x0c\xa6y\x9a\xc5K \x13\xa5t\xa6\x98\xa0q\xbd\xe0\xa4 \xd9\xd5j.*\x11r5\x1c\xd6\x88YI\x8e\xe5\xf2\xa6(\xae]\xfa,to\xa0/\xd2\xc6k=rw6H\xa2\xb6\xef\xea\xeeN+nH\x8eD=\xb0\xefC0\xcb\x17\xcb%\x9f\x05~f\x95jH\x05\x0d\x1a\x19I\xbf3\xe6}7\xfd \xe1\xa2\xbb=\x7f\xda\xa0\x9baRw\xc3\x07\xb3x\n\x922{\xb9Uitt\xca\xb3\xd7\nI^\x81R\x83\xcc\xb0\xba\xb0\x12M\xad\xc0\x92D\xc0\xe4]\xb0\xe4q\x9e\xc9\xe8\x88\xdc+\xfd\x1c\xac\x92x\xca\xd3t\xd2\x835\xfc\xf3\x0fEpIy!x \x0b\xa0\xb1m\x1b\x1dQ\x8f\xa6\x07j\xa4\xdc\xfa\xb3p\x88\x0b_\xea\xb1 \xb8\xd8HG\x9d\xa6O\x80\x12u\xb0\x8a\xd3\xecK\xe9@M\x9c6\xf9 X\x8a%\xf9v\x9a\x04\xab\xccj\xef\xa3\x1eE\xc47\xb6\x9a\xa5\x88LJ\x12\x05\xb3nu\xd1\xa6?\x05\xf3W\x94o\xdb\xf4\xeaOF\xeb\x10\xf4\x07\xf7\x86\x12\x02N\xaf\xe7\xb1\xde'=y\xaa(?\x1c\xd5o\xd9UZ\xa1g\xc2qA\"%\x9b~\xbe\xf0\xa3\x88\x838\xdb\x01{J~\xce\xaaY\xee@\xc0}H\x0f\xb8\x11\xb9\x16\x0e\x07\nn\x93y\xae\x81\xa7\x01tb\xbb\x02\x14\x0b\x16\x82l\x0c\x16b/\x8e\x12\xee\xcf.\xd3\xcc\xcf\xf8t\xe1G\xa7\x1c|\xdd\xcc\x07\xd3\x84\xfb\x19\x97\xa2w\xa7\x97\x02R\xf5\x04`\xc0\x8eq^\x90\x00Yd\x9d\xae*\xd4\xb3~\xc5\x8e`\xd9\xc0\xec\xf1:\xe8%E\xbdt+\xc8d\xc5\xf2d\xfc|\x11\x8430s\xced\x9e\x1d\x8fD-\x94m\xabZv\xc0w\x87SI\xed\x9c\x85\xc7\xb6\x8c\x1bF\xea\x11\xa4\x03\xc43=}\xcf\xf8\xa1\xd8\xed\xe0\x16P\xe2G\xb3x\xe9\xc8@\xb5\xc8m\x14=h4a\xcc\x06i\x9c'S.ob\x08\x8c\xd1\x83sI\x1b\xa5\x812\xe9\x93|\x172%A4\xe3\x17\xaf\xe6\x8e\x0f\x02\xbd\x85\xd3\x97\xe9\xa0pq\x14\xd3b3q\x14\xeb\xd8\x9f\xcd@\xd8\xaad\x14\xb0*\xeb\x89NO.\xba\x1el\x7f\x1bC\x10\xfc\x0e\xfc,\xf3\xa7\x0b(\xe9\xf4\x8a\x85)\x052Ig\x00T\x89\x8c/XX\xa43\x96\xf9\xf5p\x93*&\xa1\xf3\\kR\xb5\x8d\x9a\x19/\x97DGy7q\x80\xd1\xe6MF\x7f\x156\xbd48.\x14\\\xea\x10\xb1 \x11\x0f#\xe4>#\xf6DwM\xd0\xef\xbb\xca\x97@Qo\x0c\xaaA\x8b\xdd>\xd3\xec\xbe\x9aW\xa1\xd8\x8fO\xfc\xe9\xfbF_\xe3\xe2\xf1\x93\xd3\x942\xb8S\x0fq\xacU\x8f\xdc\x86\xc2q:A\x01w\xe2\xa4\xae\xc7\xd2~\xdf\x86p+<\xa2\xe9sG\x1c\xa4\x1b\x8c\x08f\x0d\x16%\x18\x947\xac\xdfhd-M6\x18\xa9\x80t\xd4\xa5\x88\x04\x0d\x94\x86\xe88L#\xca!\x19\xebV=p\x85\xad\x8d\xc8N ?|\xf5'K.;p\x02\x1b\x1dW\x8f\xfe\xa8\x81\xa0RW\xa0Y;\x83\xa3\x9e\x04\xea \xack\xee\xbdz\x94\x91u\xd2\"\xbb\xa0\x1e0\xbc\xde\xb2\x1b\xdfRO\xa3\x01%\xf5\xb4\x98i\xd7\x1f\xe8\xd3p\xdd>%\xe3-\xeajw\xd3s\x9d~m_\xa7_\x1eK\xc6\xc3\xef\xa3w;\xd7\xef\x9d\xf8\xbb\xfd\x91\xfb\xd8j\xebM=\xa0\xb0\x0fA\xe4@\xd8{P\x0f\xcdQWJ\xd8\x98\xa3\xa2\x00\x9b\x07\x91\x1f\x86]\xe8\xc3\x0c\xd8\xb9i\x87\xf3\x825\xb7\xab\xe1oM\xb6\xe7\xf4\x8a\x98\x05:/\x94\xf2p^^aW\xf7W\xb3E\x90\xc2\x0d\xd7\x11\x14\xd0\x94\xc0\xba\x11\xc0\x0e\xec\xc5v[\x80\xee\xd7\xa2\x8a\xed\xc3B6\xed\xc4\x17\xadV\x06a<\xf5\xc3\xb7Y\x9c\xf8\xa7\xbc9\xe6\xda\xd4\x07\x02\xd8\xe6\x15\xa45\xda\x19\xd3U\xca\x95\xef7\xc6^\x97>#\xc0\x9c\xac\x97%9\xc7\xc3?\x9e\xfb\x9d\xc8\x1dd\xf1\x17\xf19O\x9e\xfb\x84\x06Y\xff\xd5\xf9^\x1fS\x97a\x9c^\x14\x7f\xc6W \x9f\x82\xe9ZO\xbb\x97g\xf6Wi\x9b(\xd7\xaa\xf5\x9b\x82M\x1b\xfe\x06ycS/\x119=\xd0\x10\xd5\xbaV7>\xb29\xf7f`\x90\xd0\xcb\x12\x7f\xca+M\xb0\x036\x8d\xa34\x0e\xf9\x002\x1d\xf0w\xa4\x92\xce\xfd$B7\xe0\xb0\xf7w\\SL\x17\x17 \xa9\xc9@%UZb\xb5\xadC\xebR\xea\xb4\x86hA\\\xc5\xf9N\x99\\j\x0cw\x86\x96+\xe5[\xbbd\x00\x98\xc0\\\x1f\xa8\xdc\x03\xc2\xa0\xe9\xf7\x82\x12\x890v\x98\xe1N\xbb4%!\x02\xe8\x8b'\x1e\x04\xd1\x82'A&\x1d\xc1\x0c\xc1\xd2C\xa59\x01\x9a\x99\x04\x9a`\xfd8\xd3\x8cF\x9a\xa0\xc5\x007\xf0\x94\xdc\xea/\xa4\xc1\xb6&r\x86\x8f\x1et\x9a\x9fj\xad\xdd\xebT\x1a>\xba\xef\x96f1\xd7\xac\xaf\x19\xd0ti\xa1M\xe3\xbc3\xa4\x02\xe8\x8bt\x8bK\x82\xbd\xf6[\xea\xf5\x89\x92\xaa\x08\xbc\xac]\x1e\xe0\x0c^H\xa2\x9b?\x88\xe2d\xe9\x87\xc17<\x81k\xa9\xa0\x96s2\xed\x8678.+\x95\x0d\xa5G\x0c\x7f\xe0\xa7\x97\xd1\xd4E\xcf\x04\xfe`\x95\x04\xcb \x0b\xce\xc4\xd6\xa7\x8c`\xd8A\xf5\x13p\xb1z\x0b\x0e\xeb\x19\\\xb3\xc0\xaaF\x89m\x17<\x7f\x8f\xea\xb5\xb5vE\xb1\x1d\x17bQU\x13\xf70Q\xbc>\x84f\x8a\xae\x82\xe5\x8f\xb3\xb7\xf5\xc8\x95Q\x8d\x96\x8146r\xf6\x86\xa0\x9f\x19\xcc\x82t\x15\x97\x89\xbb\x90\xb8\xf4/\x9e\x9d\x16i{*M&lc\xcd\x84\xcf\xc1@\x85'*}[\xac8\x81(\xfe\x9a\xab\xa6\x0d\x91v\xf7(D\x02\xa1\x8f\x7f\x92\x9a\xa8\x049\xf30\xd6\x1dbwC'\xa5>J_\xfa/\xd1_\x05\xba\xe8\x00,\x11Get\xa7\nN?\xee\xdcaA\xfay\x10\x05\xe0\xa2\x1a\x1c\x0dq\xf0\xf2\xe1\xc4\xd2\xdfP\x9bQG'0\xd4\x88\xc3\xde\xb6\x0b\x82[\x18c\x1a\x9cF0\xf5\xbb{;\x9d\x88F\xfb'\xac\xfb\xb3Re\x15\x1f&\x17\x18m6\x05h/\x0d\xe0\x9c!z\xa5\xdbT\xbf7\xb7\xb7\xd6u\xe7\xb1\xc60\xec\xb6\x99\xdadz\xe5\x8c\x03Q\xd0=\xb2pi:\x81>pn\xa3\x9f%b?\xa0\xbd\xd2\x0e\xef\xd7\xfd\xdaH\x02Y\xf7\x98$\x03V\xee\xd1\x01+\x05\x9dm\x86\x0e\xe3\xb4\xb3\x81\x08oCUgX\xec\xe5\xe8\x10\x03n^I\x97\n\x15\x9a\xebjtG\xd1\x1b\xc2\"\xfc\xd5J|\x1d\xf3 l\xe8\xca\x9f\xf4\xb4\xe6\xce\xa8\xe5\xcc\x9bbEt\xd8z\xa0\xda =6\xf7X4\xe6\x13\x88\xe9\x81Nx\xc8K\xe5\xb6\xe3\xea\xad\xe0\xf2\xae%\x16\xe0\xce\x90\xf6K9\xbco\x89 \xfcp\xcf\x1d,y\xb6\x88g)Ejw\x0d\xff\xc0\xa9\xe4\xec\xeaG\xa8\x90^\x0cp,\xac\x96\x9cv]6\xf3re\xa0\xa6\xb1\x9a\xad\xd9(\xa0(G\x12\xcb\x80\xd7\x86\x82!1\xe3\x9a\xdf\x80\x05\xa4\xf2e\x90uXX\xc4Q\n\xec\xbb=vVD*\xf5\xd8\x89\xc7\x8e!\xc8\xec\xa1\xc7.0\x9a\x96\xc7\xde{\xec\x99\xc7^y\x10tk\x0e\xe7/\x9a\xe2c\x00\x11y\xa1\x14i\xb9\xdc\xbd\x0b\xf14\xee\xd6\\#\xe8\x1aW-\x10\xff\x02\x9cu\xea\xc9\xae\x07Qq.\x06\xa7<\xf3 \xf2\xcd\xc5 \x15\xaf\x97\xf0\x8a\x9a\x0d\x0f\x02\xd9\\\xa0\x06\xc5\xf5J\xc1\xcc \xe1i\x1c\x9e\xf1$\x85\xe6_\xc9\xad\xa5H\x15\x8b\xfa\x19SA\xf3\xed\"-Vn\xc0\xd2\xb4\xaa\xa0 &\xf9\x10\x1b\xf2+\xf8\x1e\xf8\xbeq\x02\xb7\xec\xd2>n\xd2K\x91\x08\x8aIb\x9b|-f\xab8\x89C\xe0]_Z&\x9f\xf2\xac\x07\xab6@s<\xd7c\xaf\xc9\xe8%\xa2\x0f\xe8tO\xf0LAi\x808-\xe8 \x9e\xe2\x83\xf1\xd6DP\x80\xb0\x9e\xae\xfa\xbc\x8f\x9e\xa1\xecB!bd\x8a\xb7H\x9c\xde\xf3 \x99\xe6\xa1\x9f\xb0 :\x8b\xa54\xc7c\xbd\xe7/\xde<\xff\xea\x8bgo\x8e_\xbc\xfc\xd1\xab\xe7\xcf\xde\xbdx\xf5\xd2\xa6x\x17\xad\x9e:\x01!\x8bA\xa5\x92\xe8C\x03\x18o\xa9'r6^\xa3J2\xf6\xd8s}^R5/R\x89/\xf8\x90*\xfd\xf4\xd8\x99[x\x15\x14\xeb\xa3Q\xe0\x06\xc7gzV-C\xc5\xbb\x02\x8dh\xa3\xae\x13\x14\xa8[\xe2\x90\xc5\xaa\x10\xf4m:\xb2\x97xT\xc7\x97Rf\xc6F5$s=\x1b\x9a\x17\x9d\xbe\xe5IB\x93\x000\x19&\xa6\xa9\xb8C\x8eV\xad\xa6'l\xdd\x93\xfa\xed\x92\x02\xfd\x8e'lyRT\x0c\xab\xd0\n\xa6\xb8qZ\xe3*5\xa0\xfc\xda\xc12\xbd)5h\xe8\xdc-O\xdf8\x16k,\"'/V\xf3\x16U\x82\xf21\\c>\xa9\xfc\x8f\x93\xe04\x88\xfc\x90T\xf8+n}\xc4\x9e\x99\x99\x92\xd5\x7f \xde\x83`\xb7W?\xcd\xb2\xa7<\xebr\x15T\x0e\xf2U\xc1\xe8\xbdr\xb8\x0b\xbb\xdc\x01[\xa2\xb3\x07\x89\x14\\L\x86I\xf5\xcc//\xfct\x8d/[\xe6\x91r\x12o~\n\xf7\xdb._\xb3\x900\x86\xfd\xa5{\xc00\xaa\xfa\x9d;\xec\x12-\xa5\xd8>{\x0d\xbc\xaa\xb4`\xc0\x1f\xefu\xb4\xc0\x9c\x1e\x86\xa8\xa3\x1cE\x99\x83\x006a\xd4\xae\xf2P\xa2\x15\"N(\x83\x80\xc8w\xee\xb0\x13q\xe6\xd3X#\xaf\xe8\x18|\xa5\xd7\x15\xb0q4j?\xb52M\xa0#\x16\x7f!\x10y\x0bz\x0f6\x02\x1b\xac2\xf9y\x91,\xa1TZRA\xfcW\xf0\xe41\xab\x08\xf5i\xdf\x15f\x7f\xc5\x18Glaf\x14\x87\xe1\x0e\x00\xe6\xc8\xd9\xca\xe5i~\xb6\xbe\xbc\x8fMV\xcd~\x95\x05-\x8b\x1a\x883.A8\xe5\xe1\xf1\xae\xe4d2\xe0d\"\xe4\xd1\xfc2\xc6]\xbdC\xeb\xec\xe9\x85\xa8[\xb6&7\xbfj\x93\xacmi\x11\xe4\xa3\xdcTp\x17\xf1\xcb\x00}\xf5\xfe\x9e\x83\x14\xbd\x95\xf5\xe0\xad\xb0\x93\xdd(\x87.\xf7\xdc\x91\xda\xef4\xb0r9k\x02\xa0%u\x8b\xb0\xb3bE\x9b\x82\x97\xc3\x8f\xd6O\x1f\x82\xd8K\xd8\x93\xdd-\xb1\xa0\xa1\xe3\x1210\xe6\xbe\xd9\xff\x95\xf3\xcc#\xfa\xac\x0b\xbfF,\x00\xd7UV\x12\x1b8\xc7D\xae\xa4]\x81\xe3\xab\xd3\x8e\xf9\x15\xd8\x89\x02\xe7\x9c\xca\x83\xbd\"p\x0e\xcd>\xfbE\xca\xad\x1c\xf1w\x86T \x10q$\xb7h\x99\xea\xe2-\xb1\x97\x83`r0\xf5WY\x9e\xf0\xb7\x99?}\xff.\xf1\xa7\x9a(\xa9\xe2\xab\xa3U#\x15I{D\x94wR\xd1n\xf3\x8aphH\x88\x90\xd2\x9a\x90\x89<\x0b\x07N*\xddm\xe5\xb8\xa9I\x8f\xa4\xca\xa9=hdR\x19\xd50\xc2\x9b\xb8\x81*\x1b\x0d\xa6\xf1L\xe0^\x0eWu \x08D\x84\x8c\xea\x9a\x0e\xa8\xd7\x90\xc7\x93j\x05\xdc\x81\xa5\x90\x02}\x85t\xd7.H\xf7n\x0e\xed\x15e\x1e\xc7#\xd6K\xfcozu\x1ae\x96=\x11\x18\xdf\x9b\x9d\xfb\x1d\xcaf\xc97\x97#\xd6\x13\xffz\x06\x8a\xf3\xc1<\x8eY\x9f\xf1\xc1\x89\x9f\xc0\x7fQ\x0eh\x83\xe8\xca\xec\xdc\x87z\xb7,\xb8\xdd5\xa2B5Hn\xd7\x08\x9c`\xd1\x10\x94\x17q\x02\xc3\xe4\xd6c\xdb5\xbe\x1blu\xb9.\xe9\x04n\xb4b\xa4M\x8a\x1a\xedV<|\x9c@\xfc\xd1qBX\x9b\xb6\x9a\xecD\xe8\xac@\xac\xebV\xf3\x0bd\xf8\x87\x8f\x99\xcf\x9e\xb0\xf41\xeb\xf7}y\x85\xadX\xa0\xfe\xc4\xc3\xf8\xd4\xca=Q\xee\x9a\xea\x13\xcd5KT\xe8EHL\xff\x18\xaa\xc3\x87CT\x1dj\"vT\x1e>\xdc\xfe\xd8\xcaCz\x12\x15\x8f\xa1\xf9\x96\xed\x15Z\xf5\x1ex[\xac\xceC\xe3\xa4\xd26X\xb7-P\xa6\x94#\xda\x00\xda\x96S\xbd\xe3\xb2\xd31x\xc3-\xe6\x06\x8fg\xeb\x1a\x9f\\\xab\xef\x04\xc5\x94\x9f\x18\x91\x97\xa6\xf0\x16\xda\xc8\x98\x9ak\x0e\x1c\x86}\xe7\x0e\x8b\xc7J11\x11\xebr\xdd\x10\xb9\xed\xa8)\xd0\xfc\x01\xe2\xbf\xbc.W\xb9s\x9b\xf9A\xa4V\xc3\xee\x0dV\x83\x82\xb6N\xe6\xd7\\+M{]R\xf6Ulz\x1b\xcae\x88Ju`\xf7R\xbe\xeb\xeby\xf38\xee\xdd\x8e\xaa]\x0d\xd3\x00\xa5\xbc\x0es]l\xa8\x1d\x11+\xcae\xf6\xf46\xf5\xef\xb5\xeb\xa4\x9er\xc8N\xe9\x80\xe6\xb4^t\xd5Y\x953\xeb\xaa\xcaY4\xabr\xce,\xaa\x9c\xda\xe7\x96]5>\xa7\xed\xc1n\xab\x15.I\x8a1\x8d\xa3yp\x9a\x83\xf6\x95\xa6\x1a\xbc\xd0\xce\xd2\xae\xaf\x95\xa7\xa4&\xba\x92\x1b\xdf\x164*i\xe3V\x98\xe2X\xac\x87\xb69\x185\x9c\xea\xb8\xd7;>\xe6\x1c\x0c\x07\x0e4\x07s\x90&\xcer\"\xe9rp\xe6\x87\xb9\xe0h\x16J\"sV\xab\xed\xb1K\xd7\xd3\n\xcab\xd1\x98O\xd8\x01\xe5t]\xe6\x88\x7f\xe8\xb1\x0d\xacO!u\x9f\x8dQ\x9b\x9aM\xca$\xe9\xad\xa3\n\xb1\x1a\x8d\x8f\xa6|\x04\x94\xbe\x1b\x94<\xdd'\x98z*\x80\x8a\x95[>c\xb9F]\xee(J5u\x8c5\xe0*\x992\xdah\xb7\x8a\x05\x07;\x02\xba\xaf\xa2i\xe1\xd4\xe7\xf8\xb8#(\xe6\xf3\x11\xf0\xbe]!!\x89\x04-\xe7F`l\xd0hS\xf1\xa7@\xd7\x97q\x80J\xc4r\xc7|\xd2\xa1\x9e\x896\xe8`T\xd46!\xc6\x14\xeb\x1d\xe0\xed71y\xc98\x98\x08\x1e6pY\\\xfa\xe5\x8d)\xb8b\xae`\x94\xb7\x95s*%\xd2\x97(\x98\x8c\x03i%7\x14\x88\x99\x0c\xd2\x15\xdc|\x0c<6\xa4\xee\xee\x81*-)?\x9b4~V\x8ac\xa3&\xeb\xf8\xb6iG \xa2\xdfzG\xf1\xac\xf0j\xd18\xef\x16:!\xb6\xe3\xb8:\xa1\xf6\x19\xa1\xe7\xb1\xd9\x19<\xccbD(\xc9d\xac6-\xde\n\xdew\xcc\xf0\xc8\x92\xb1',\x12\xd3\x9d\xb9,\x18g\"\xb3z\xd91k\xb8\x08\x07\x1f\x8d\xc1\x81\x05^h\x95\xedn=\x06\xc2\x1b\x8b\xca\xd8\xb4\\\xc5I\xa9\xc9!\x1b\x95\xbaTu\xa3\xac>\x96&\x00t\xb9\xb55+\x88\x0b\xe8\xa9\xec\x03c\xedw\x8b\xba\xdc\xc6\xaa~\xaf\xc6\xb0\xdc\xfc\xeb-\xb7\xad\x9a\xbe\xeeU\x84G7\xebK\xa7[U\xbf\x10\xfc\x14\xcf\xaa\x06\x05\x1b\xe6\xfd\x80\xfe\xf5\x81\xf2\xc6,8\x8b\xa9S\x17z\xe2^:u\xe2z\xba\xd8X\xa6N\xe0R\x84g\xea\xe8\xe6\xd0hG\xb8t~\xfe\x01\x85q:{\xdc\xec\xf5G\x19\x8bi\xa1*\x17N\x88\xce\x88\x8bSc5T\xa4\xc72e\xb4\xc4\xf6Y\xfe\x03vS\x8eY\x9e\xa3\xea\xb1~\x1b\x04\xab\x04\xdb,\xf88\xd2=q\xf9\xbdf\xe7\x01\x1a\xdd\x1f,\xfdU\xbb#hU\x81\x1d\xb0\xcc\xe1\xe3\x08T\xcf\xe2\x7f\x15%\\\xe9|\xc9\xc9+Zi\xf3\n\xff\x07o\xbdc\x0d\xc8\xbd@\xe0\xd516O O\xc5\xbe\xa1Zq\x05\xd7u\x12D\xb3\xf6P\xb6\xddg\x16\x8f=\x8f(S9\x9c\xa8 \x85\xff\xd7<\xd5\xc5(\xda\xe0\x10\xce\xfdv\xba\xdd\xe9 \xadD\xcb\xc8\x98\xe2H\xe6I\\\x0b\xc8\xd5t\xdcF\xff\xed\xe0]\x00\xe6p\x0c\x82d\x0fe\xc4\x13\xd7c\x9f\xc6q\xc8\xfd\xc8\x01V&+}.C\x01\xd4\x05\x81]\xf4m\x8cY\x13\xe4<\xdav\x07A\xc6\x13?\x8big\x8e\xc6\\\xca%\xfa\xc8fAN\x1a\x90\x1bK7\xa5\xe5\xc9!\xbd\xfe\xa7\xf2\x9bur1\xaf\xe3U\xa7c\xb5yX\x9e\xdd\xc6a\x94\xc8\xd7\x0f\xa3f.\x1c\xe6\x08\x1f\x8c\x1f\xac'\xf9\xeaQ}\xddET\xb2\xa5V\x13\xcaV]\xd2\xdbF]\x128Z*%\xf3)J\xe6C\xe7B\x06\x08\xbf\x90\x0e\x12\x99t\x19\x0eh\x0e\x13'R\x02\xf4\xf8\xec\x16\xbe\xf2\xaa\x8d[\xfc1\xc0 \xe8\xc2zF\x9c3y\x89F\xaeN4\xf7tN\xb5\x10\xc5\x82\xa4 \x16\xc9\xdb\xdb\xf2\xc2\x9e8\x9f;\xcb\n\xc71t!b\xd9>\xe3p\x19}i\xe1\x86\xf0T'\xbe\xda\xc2\x85W[\xaft\xaa\xe2f\xe4T\xb05\x91\xcb\x96h\xcc\xc7I\x0bJ\xf5\xc8\x91.\xc9\x02\xe6\xa5R3e !\x03\x7f`/\x040\x9f\x1bzdf*'\x9cs\xe8n2\xb1\xc2\x02\xe0p\x02f\xae\xe7\xf2J*\x1a\xd2\x08\x82\xa9\xe0#\x0e\xc8\xe2l~\x02\xce\xc5\x9c\x128\x1b\xc7\x83Y\x1c\xf1\xc7.(\xe0/\xd8\x81b\xe2\xd0\x1a\xf8\x18%&\xd2\x90\xbd\xf8%\xf6ogVHS\x0e=\xb6p\x96\xb02fp\xddJ\x82\xf9\xb0\xfe\xd1~\xdf\x125K\xcc\x1c\x11\"\xa84\xf7\x9c6`\x03@\xe0\xb4\x123\xdb\x1c=\x8c\xd7\x03\xb9]\x0d'\x0e%B\xc8Py\"GZ%\xed\xb3\xc3\xc1t\xe1'\xcf\xe3\x19\x7f\x969[\xae\xcb\x9e\xee\xb3\x07\x0f\xb6\x1f\xed\x82\xc5\x12{\xb2\xcf\x1e\xec\xee\x0c\x1fA\xf9Cp:9\xee\xf7\xa3\x89\xb4g0\xc0y(\xedG\x0e\xad <+Ax&A\xd8\xef\x9f\xd9\x81v\xd6\x82\x8e\x1a:\x89=\xf0\xd4D\xb8\x02z\xbe\xa3\xad\x9d\x1a\x00\x9dS\x97^P\xe40%4\x15o\xd7\x1d_H~\x00\xbb2\xab\xc8\xee<\xb6,/\x89B\x8c\x90\xa2\xe6\x0d\xf6\xf5\x9a\x96\xe2\xd1\x8e\xd4R\\.O\xe2\x10U\x12\x8f\xee\xdf\x82J\xa2v\xc2)\xf48\xb5-\x1e>[\x91\xc3\xb6\xe9vH\xbe\xcb\xdcb\xc8{(8J\xcd\xf9Bm\xf7`\xfb\xb2\x88\xd3\xcbx\x9a\xc9\xee\xd5\x8d:i\xf5\xa22o\xac\x9b>\xddD\x89\xa8\x97\xd9H\xc6\x95Q\x14,\xd9\x04\x953F~\x16\xbfV\xdaM(B\x95\xc0N\xbf\xf3O'\xb7\xc74\xea\xba\x0e\x8b\x8aC!_\xfdZL\xd8\xac\x90\x98v\xd54\xcc\xbbi.V\x84B\xc2d\xfa\xc2\xfa\xed\x90\x1az\xed\x1b\xe8U;\x97\x14X\xb5\x06\x1a%\x8e+=\xda6i\xa5\xeb\xeaf&\xe7`\x81\x9b\x80\xb3(\xbb\xef50}57\xbb \x92\xc0\xc5\x98c\xac?\x8c\xa1q-wF\xe3\xca)\xb4z\x98\x8f\xbb\\\x8f5\x89[\xbd\xb3\xfc\xd6:\xeb\xc3\xcdrP\x04\x01\xf4CG\xf3j!\xc5h\xda^\x0b\x01\x1a{\xa5\x15\xa1\xe0B\xa6ND[ \xce8\xfa\xa2\x0c\xe2\xe8\xf8x\xc4r\xf0/\x9aQ\xe6|\xc7\x91\xbf\xe4e\x993\xa7n\x02\xfd\xa1*\x1f\x99:q\xfd\x93\xf38\x11\xd5\x9b\xb1L\x0ez\x86\x8a0\xf87\xc2\x7f\xfb,v\n\x8anHE*\xbf\xdf\xf3\xcb\xcf\xbb|\xccb:\x0e\x8b/cA\xc4R`jgv!\xfel\x9cM\xd0\xd6\xb9\xd4\xdc4vm\xe1\xa7/$\x96(X&\xa8\x06\xd1r\xd0\xa2\xaf\xa7\xa5\x18\x01\xd3\x83\xf49\xc8\xaa\xde\xaeT\xc8\x97Zsf\x01\xd9\xaa\x99a6.\xf7\xb1z\x932Y5$\x7f\x1a\xd5\x97\x82\x1c\xd6\xeaB\x9a\xac\x08\xefF-\x19\x19\xa9VO\xc5N\xc2\x9a\xf2\x97Q7\xe5~b|\x12\x13eM\xfcaV\\\xf1i\xc0\xd3zMLUU\xf1\x17Q7\x0c2\xa3f\x18dE\xbd0\xc8\x8cZ\x1a\x0fP\xab\xab\xe5\xc8\x16\xb4\x14\xa2\x9d\x82S0\xda)r\x8av\x8a\x14\xa3\x9dW\xddS\xdfoT!\xeb\xc2_E\x95j+\xae\xd6\xb1\xd8\xde1\xfd\xcb]\xbe\xaa\xc8\xb7\x031\xdcQ\xf01\xa8\x91Q\xd6g=\xd70 \xad\xfc\x863\xc5\xaby\xd7\xaf\xa6\xb5\x98Z\xcc\x1c\xe5\xbc:\xcaXG&\xaf\x0d\xac\xea\xfa\x89\xfc\x0e-\x1e\x95\x8cw-B<8\xc8(0\xce\xd1;E\xf7\xaa@D\xe8\xd5\xb4\xe7)\x98\xf6\xb0B\xd0^!\xae8\xe3\xafp\xcct\x13UHPM\x94l\xf9M\x1cj\xe9\x02\xda\xdd\xb5=\x19\xa1\xdf3\x108P\x9c\x03\xba\xf6/\xf8\x06\xfa\x1c$'\xeb\xd6\x8dG[E\xfc\x1b\x1bx\xd9\x87D\x93\xab+\x91\xaf\xc7*\xc0\xb2o\x8b\xb2\xe0\xc6\xb4\x1e\xca\xe0\xce\x1dV-2\xae\x16\xaa\xce\xfcm\x0cYM\xa0a\x12\xa5>U]\xc6`K\x81\x12\x88.\xcb\xb8\x10\xc0V\x17\xb2\xe3\xae\x8d*Uk9\xee\x02x\xe2_,\x04\"gg\xb8}\xed\xa1\xd8\xdd\x06\xfdR\x0d\xb2\x12\xf2|\xbd\x01\xa6\x86CqX\x18\x88\xe6\xa6)\x88\xf2\xcf\xa1\x1d)\xb0o\xa2R\x0d&\xee\xedY\xcc\x9e\xe9^`\xd6\x1d*\xc1N7O\xef\x01\xb1XR\x9e\x91\xd7g\xe1\xaeQ-\xea\x9d8\x12\xd1\x91\xa4\xa0t\xe2\xf0\xc1)'.\xd3i\x01R\x07)\x071a\x06/\xfbP'\xe5\x10\x9d\\\xdenC\x15\xa0\xfa\x81%\xf0\x07\xdc9\x93\x01\x8f\xb0\x90\n~$\xca\xe0\xad)\x88\xd1\x0d\xfd\x94\x1f\xc8\xd0\xc1Dv;\x14k\x8d\x89)\x04 J\xdej\x1eb\xb5\xa0\xff\xbd\xff\xbeW\xcd\x97\x87\xa2\xfd\xf2\xd20\xc8e'\xeec\xb6\xb9\x99@D\x9f\xfe>\xeb\xfdw V\x00q4\x89 \xd9\xf77j\xb5\x19\xea\xf7%Ik\xbfB\xd8\x12\x95\xc3\xcb\xf0\xd6`\x82\xf2{A\x02\xb8\x18h\xac\xc2<\xe1@\xb3q\xbf\x9f48\xf61\xd0\xb5\xcb>Q\x8b'\x7f\xcb\x17\x18\x86\x86\n8\xae\x8b\xf8Z\x00mc\x1f ]i\x06*)3=\x82\xd3\xbc\xdd\xc5\x8beA7\x9f\xe6\x99f\xc2JwG=\x01\xd8\x8bZ\xb3}\xeb\"QOPD\xdf\xf2\x8b\x15\x13\x8c}\xb8\xba Fe\xaf%>-J\xda\x06\xc0\x14>>f1{\xc2|\xb6\xc9\x86\x8f\x9b\n3\xd9\xb0t\xa7\x07\"\"\xb9?\x04\xa0\xed\xe4\xe3x\xe2j\x0eW\xad\xdd+Z\x83.\x0e'\xa0C\xe9\xf7ckaS\x05\xa9\x1e\xf9\xad\x96>\xb1\x03\x15\x8eN~N\x81\x8fl\x97\xfe\x9a6*#\x9f\xb8M\x9eV\xd0\xc8jo)\xd0(@ao\x03\x1a\xe5\xcdh\x04\xd2\xc4\x8eh\x94\xba,\xc7\x10\x0e\xfd\xbe%\xf0PK`\x03@\x1ah\xe3\xeaJ\xbe\xec\xb3q\xe3DS+\xb3\x9ao\xcd\x9e\xc8\xab{\xe2;\xf2V\x9c\xc4\xd4M\xe9\xfc\xc3 \xcaI\xcfa\xd2c\x81\xf6h(\x1b@\xd5-i\xe4\x0e\x19\xa2\xa2\xc7\xf2\xf1P&~\xc4\xae\x17}\x1fN\xc6\x01\xe0\xb8\xff\xf8F\xfdv=\xd5\x18N\xe05\xf0WJ8\xc9p\x8b\xe6P\xd7\xf3\x8e!\xdd\xc74`\xb2\xdf\x8c\xc9\xb9\xb4/o\xc6\xf5\\\xe9\xc1\xad\xa5B\xd8\x0e:\xac\x05\xc9l\xf9\x02\xbb\xec\x8bAT\x81X\x80\xe3\xb4\x0b=\x0d4,\xedNO5\xee\xdf\x07t\xc8\xc7\x81FO\x9bIi\x88\x88\xe2\xa3\xa7&\xec\xebp2\x8e\x01\xe9\x82k\x10\xd6[\xe9Yq\x15\xb7\xe8\x8c\xa8\xaf\x0c\xf7c\x0f\x10Z\xe4U\x92\x1e\xb3\x0d(&\x15\xe0w\xee\xb0P\x117\x176\xdcp\xb0\x8aW\x8e\xeb\xe1\xa4\xc8_n\x87\x96\xd7X.\xda}\x80.\xeb\xa4\xab\x03\x16\xc9\xa7\xe8|\x89\xd9\xfc\x0f\xe8_7\xe0\xca\xaa\x9a\xff\xbd-y?\x11\xdd\xd2\x0e\xc0\xa9\x9dt\xec|\x93+\x89k1q\xfa\xb7\xd79\xca\x81\xc2\x9b;?\xff\x00\x84\x92;/\xfd\x97x\x0b\x91;;\xf7\xbf\xcf\xb3N\xc1\xf5o\xec\xdf\x8e\x1c\xac\xca:_\x13\xack\xf2\xc6u\"y\x1bl\xb1F.2\x0f,\xe1,fpU\xe6-.\xb9\xb4h\x1cwZuU&\xab\xcd\x7fh\x8642\xc1\x03W\x84\xbf\xfa}\xee~\x9c\xbdP\x93XA\x10)\xd8\xf87`\xa0x\x86\xaf\x12\xab\xa8\xf2\x9b\xa0\n\xb7Ct\x08~\xe5#\xd0\x9b\xdb<\x05\xd2B\x06\x1a\xd5#++j\xe3\xe3\x08x\x10%\x83\x1b\x1e#\xad\xbe\xaf\n\x89@\xc1:\xa1\xa142\x11\xbc\x95\x89h\xdc\xa6\xb3\xca6\xddr \xeb\xc434\xb2\x96-\xfd(\x97\xb7\xfc\x8c\xf5\x10\xd6\xba\xd2\xad\xc7\xa9\x02\x9c\xd2\x00i\x0b\xaf\xdcD\x8fY\xae\x81\xb3\xe0\xc0\xfd\xb2\xa7\xa9\xe4\xc0s\xc5\x81\x8b\xbcT\xe3\xc0surH;\x9c\x1c\x9aN\x0d\x96\x13\x03\x9c\x16R\xf8\xe8p\x02N>\xfa\xfd\xbc\x0b\xdd\xbc\xce(\\O}\x06\xce\x11\x99\xc7\x02\xb0/\x10hHxN\xee@\x0b;a8\x1es\x91\xcb\xc7\xc1\n\xb2\x14\x82\x18 \x93\xc7\xbbk\xe3<\x9e\xa1B8C\xb5\xb3\xa6)B$W\xc1\xbf\xe5)\x0d\x91\xdf_\x03\xf9eo6\x1a{\xd3rd\xc8\xf4\xcf\xe7&#\x9b\x13,r^e\x91\xd3*\x8b\x9c\x16,r^\xfe\"Xd\xb3ekO%G,f\xaa#xn\xb0e\xd9 9\xbb\xe6\xf2\xf2t\"nv\xf5\x07\xf4\xaf[\xda\x03m\xbe\xc1\xe9\xcb3;C\xfa\x82\x9b\xe9K\\\x1aY\x1a\x17_R\xdb\xcd\xb7j\xb1\xf5\\\x84[6m\x88\x16!\xe3\x18\xb4\xdcx\x97B\xd3\xb9\xc7V\x1e\xd8WN\xa5\x81\xa21\x1f\x8b\xa6\xcc3\xd0n(\xc7sf\xfe\x12\xf2\x95\x13\xc6*F\x97\xf5\xc0$\xbc\x99\x97S\x9cF\xe9_\x98\xc4\xad\x04|C\xa9\xa8\x0ep\xaf\xd4*\xa9\xa7\x9d\xad0\xe5\xb1/A3\xbb\xb4`\x9f\xb7<\xb69\x14[\xc3\x99\xbc}2/\x9c\"\xac\xc4\x9b\xa9s\xead\xb1\x1c8\x1a\x00\xd9Y\x83\xe1\xf2\x87\x1a\xf8\xe2H\xb9\xe9m\x87]\xe3\xf5v\xf2\x02%+\xcc\xdd4\x17\x05$\xcct\xc3\xbd}6\x9e\x81\xcb\x8aH\x19\xf1!u\x8f\\\xd4\xc1\x01h \xeeM= nH`\x91\x89tb%}L@\xa8|e\x93\xdfbD\xa3\x1e\xe0?\xect\x94\xf2\x15\xbb\x901\x0d`\xbf^\xa0\xf7\x8d\xd2%2\xac-\xf4\x07\x1b\xe0~%\xbd\x19'\x10M!\x8e2~\x91A,\xa6\xe44u\x0b\xfb\xcd\x04\xe3G\xc4\x88)A\x89BbNlq\xa2[I#\x86\xfb\x96k\xab\xcd\x0d\xc7\x19^\x8c\x94F\xe1\xd6E\x11\x89\xa1\xf3jd-\xe9\xffC5\xcf\xb8\x1da\x14\xff\x8c,\x05\x1f\x043\xbb\xe4O\xfa\xc2d\x8d\xf1\xfc\x01\x03q\xbb\x13\xadaOf\xe3\xb4t\xdb\x8b?\xe2R'ct>\x03W\x9a\xa9t\x80\xc8\x0e\x98\xd2\xec:\xe0P\xdcY\xa0\xe0\xdc\xde \x86\xf6lbnG\xb8\xe2\x1b\x8bbh\xe7\x06Q_\x89Ri\x89R\xa9G\xaf\xaeXF6\x88\x8b;\xc9nCI\x14\xc3\xd5/\xc7C\xf5n\xd7\x90\xf5Gk\x8c\xb7\xdc\xb4gr\\\xe8)\xdc\xc2\xb5\xa1\x087wBy\x9b\xd9\xf4\xfeB\x1d\xb6q+\xa6\xa8\x00\x97\xbc\xb4\x94\xb3\xca\xae.U\xb3\x1c\xe2\x03NOp\xc9E\xb8\x00}\xcd\x05\xf9\xb2\xc5\xfd\xcc\x07OR\xd9\xb4\x03\x95\x85\x95#I\xe1\x1adr0=\xa9Q\xca\xc1\xf4\xc4-\x0d\xa0\xc5\xcf\x02\xd7\xf1G4\x08\xc4\x96)\x9d\xef\x001e\xa3\x12\xa9\x89\xeb\xe38\x8a\xc2\x9bu\xfbvA\xb0\xeb\x14\xb1\x9c\x01\xb1\xbc\xba\x02BY\xec\x9c\x0b\xdd\xabv\x95\x84b\xa2FEU$\x19 \x98 n\xb1\xf5^\xb9\xbcn\xa7r\xa2\x0bD\xff5>\xa6\xe8\x0f4\xaa\xba\x13\x0b\x8cl_\x1d\x92\xce\xc8\x9e\xf3\xa2\xe7&\xea\x1ac)~\xde\n3k2\xad\xc8\xcc\xee\x191\x18\x03\x99^\xbf\xc4\xed\xcb\xf4\xba7]\x15K\x8c\x0epc2\xb9\x1dn\x0c\xc5N/[p\xf0\xd8/\xfe\x8fd$d\xb8X\x1fG\\\xfd/\xd2\xdd:[\xabB\x19val\xb5\x0b7\xc6\xac\xc4M\x99s\xea\xa6\x11S\xa62[\xca\xec_]\x0e\xac\x96)\x14T\x1c\xfc\xa3\n\xf2\xb3\x01\x91\x96\xe8k!w{\xac\x0f\xde\x1eX\x9f\xf5\xee*3\xcf3?\x0cfL\x0dv\x19\xcf\xb8q\xf1\x8d\"I \xee\xeb\xb65\x11Z\x02\xf4\xc2\xb0r\xc7/ES1:X\xf5\xa5\xc9\x14\xb1Q%\xf4\xe14\xc2\x8aC\x8f\xcde\x13f\x19\xd1\x95i\xabS&\xbd4`\xee\x98\xb2\xb7Q\x8f\x18BH\x04\x9c\xfb\x12yj\xce\xb8\xf8=b\x9f\xf1\x8cO3>cy\x14'3\x9e\xf0\x19\x13\x88x%\xb0\x8e\xdd)\"sC\xf8\x9e\\t\xcec\xe7\x8b`\xba`A\xc4\x002K\xff=O\x19F\x1fc3hMpC\xf1\x9c\xa5\xf9t\xca\xd3\xf4\xde\xdc\x0f\xc2<\xe1,X\xae\xe24\x0dNB\xce\x9c\xf3\x05\x8fD\x13wu\xec\xbe\x0b\x13\xeb\x1eE\xcf\xe3(\x0df\x80N\x04m3*?\x1c7\x1f\x1b\xc6 \x15\xbd\xc8\x02\x89\xb5N\x0e\x84'T\x9dc\xac\xf0\x96:\xbbh9S$k\x9d)H\x13\x97\x8fz\x8a\xa8\x8b\xa6\xa5\x90\xe0#\xe9\x89\x9b\x14\xb7JOY\x06\x90k\x06[\x86\xe7\xe3\xfa\xc5\xfc\xea\xe5\xf3\x9b\x03\x88p}\xa5NYm\x91\x96\xad\x86*\xe8\xf9\xfdV\xe7Q\x9c\xca\xd6\xbf\xbd\xd1\xe8\xa2\x1f\xaf\xe28\xe5\x15\x19p\xe8\xa6]\xfc\xd3\xa2\x895H\xad\xcd\x89\xa3\x0eC\xaf\xfd4\xe5\xb3B\x10\xa3\x05\x84\xc6K4\xc1\x9c\xcf\xea\xf1\x8cn\x17~{\x86JG\xcc\xf3\xbd\xf1Qt\x94\x1c\xe5\xdb[\xdb\x0f\xe1\xef\xa3\xc9\xbd\xd3u\xc1\xac\xd0_\xcc:\x89\xfb\x85\xc2\xe2)\x1bnm1\xe5\x80.\x93\x0eX\xb7<\xf6\xe8\x11\x1c\x13\xff\xdb\xef\xfc^O\xde\xff\xcf\xd4=iAq\x9b\x97\x8a\xfc\xcao\xbc}\xf5r\xa0\xc0y\xe9pW6?\x04\xc5Fm\x19\xdd.p\xff_\x83\x9cJ\xcf1~\x19G\x9b\xd3\x98'S<\xc6e\xb1DD\x17o\xf2N>\xea\x85\x8d\xdb\x88\x11o\xd3&\x96\xdf\x0b\x06\xb3 ]\xc5\xa6L\x85p\xa9)\xfaV\xb3\x81\x08 6\xa5\xa2\x9dg\xa7]W\xe0\xcc\x03\xa7B\x1e\xab\xf93\x05\x89#\xf8\xe4AY\x0b\xdbg+\xc5\x96.@\x89P,\xd0\xd4\xb2@\xd3\xe2\xc7\x01\xeb\xe1za#\x06\xbea\ny#\xeb\x8b\xcf\x17\x1d%\xf1u\x86\x0e\xd6R\x9e\xbd\x0b\x96<\xce\xb3\xf6sO!\x00\x8aH\xe1\n\xb7\xe9\xbb\xc4\xa7\x06y\x94\xf0\xb9\x18@\xf9\xcb\x81\x88\xa7\xe0UNt\xe6\xce\x1d\xd6\x8b\xf8E\xf6.\x98\xbe\xef\x81u\x90J\x86\x05\xa4\xba)\x12E\xc5\xf5\xfb/\x8f,\xcb\xbasa\xd9\xff3[\xff\x97\x95\xfe/\xb5\xfe\xb7hpj\xf3@.\xfb\xca\xd8f\x18\xef\xbf\xd0\x98\x8a\xb3\x15B\xc8\x80\x0c\xa7 \xa3\xd7^\x92A\x15\x05.\xf1\xcf\xb9\xd8XE\xb3g\x18\x1ct\x7f\x7f_\xcf\xb9\xba\x92Q\xdb\xcb4\xb1m\x0fvvv\xd8\x88M\x9d\xb9\x83\xa6\xe8z>\x1aGmI\xcc^\xb2}\xf6\xf3\x0f\xd2\xaf\xd6\x90m\xb23\x97}\x82\xd2M%\xaa\xa8\x03\x07t\xde9\x05\"\x18\xec\xd5\x15\x83\x01\xb2}\x0dK<\x16\xb4O\xbbE\xda!\x1e\x0d\xaa\xfb\x1aT\x1d\x0d\x84\x9e\xae\xb0\xabl\xa1h\xbb\xe6\xc4\xae\x8b\nA\x08\xe8W\xb1\xb3\x91\xc6\x03\xd2b\xae\xb2\x8c}'@Hu\x12O\x84\x1e\x0b5 \x05\xfc\xa4$\x9c\xa6\xdf\xa7\xea\x1eT\x839\xbd\x0d\xcd\xdaP\x96\xd5\xd1\x96\xdc\x8b\xd0\\I \x01bp\xec,\xbb4\\Ctn`\xb9\xe5c\x88q\xc6\xf8\x8b\xdf\xb7\xb2\x05\x1a\xbe\x98\xd5\x11\xf3\xd1\xda\\\xb3\xe0\xca\xa4\x01\x87\xd8\x0e\x9e\xb2\xb8\xc9\xb7\x08\xbf\x98r>K\xd9\xd2\xbf\x08\x96\xf9\x92\x15z\x8b\x0c\xa1\xf2}9\x1b\xd9\x1e\xde\xdf\xbb\xffpg\xf7\xfe\xde\xf5\xdbk\x07\xe76\xad\x17\xdd\xd5\xafx\x04bG\xee\xb8\x1d\xcb8R\xc4^\x9c\x14{q.\xdd\xc0Kk\xf258\xe5\xe6\x8d\xd8G\x13\x9bf\xc4\xd7\xdd\xfb\x02\x8b0X\x04\x99\xeaZ\xbb\xc1\xc0i\xf9)b\x0b\x12\xa3W^\x11\x0cr\x00\x99\xd2\x1d\xc2m K\xcb\xe46(\x9f\x83\xf6xW\xeb\xae\xb1\xb32\x044q\xf3\x01\xc2F\x9a\xc9y)\xff23\xd3\xa6\xcc\x10\xda*R\x1f\xed\x15\xa9\xc3\xedm\xb8\x0f\np\x02\x18 \n\x8e]\xae&\x02\xdcz\xff\xf7\x1f\xfc~\xafq\x1d\x9av\xef\x84\x1d\x85\x8e\xb1 \x82\xc178j{\x15D\x96a>\xabK\xb5\xea\xbe;\xd1\x05\x87\x1f\xdc\xe2\xc2N\xe4\xec\x0co\xe2\xdb\x93\xf4]/\x1a\xee\x1d\x1f\xf3\xf4\xcbx\x96\x87\xbcW\xa7\xda2T\x90\x1eJ\xc1EY\x0f\xc4\xd3k\xb2UQF\x00\x89*\xec\xb1X\xbd\x96\x1b\xd0\x07\x93\xdd\x08\x1cq\xb8}Pw\xf3\x1b\xcb\xac\xfb\xdb\x10\x95\xb3\xc8S\x1d\xc0\x90cd\x1f8\x12\x99r\x9c\xd2\xef+\xb5Ca\x9c\xc0\xba\x9f\xbe\xf5\x88\xe9/\xc7\x04\xa8}\x87&\x8b\xd3x\xb9\x8a#A\x0e)8\xa8\xe7\xd9j5b\x97\xc5\x0cZ\xcb\xf9y\xb6\x88\x93\xe0\x1b_\xf4\xe4u\xbc\xcaW#v\xd2\xbd\x1a\xff4\x8bF\xecx\x8d\n\xafV<\x81\x8fA\xcd\xf3n5\xd3\x11;l/\xf9,\xcf\x16/2\xbe\x1c\xb1\x8b\xf6\xc2\xa2\xd9C4{{\xdb^:\x16\xc5\xb7G\xecY{Q\x7f\x15\xfc&\xbf\x14}\x19\xb1\xe7\xed\xc5O\xfc4\x98b\xe9\xf7\xed\xa5\xe5\x91\xe4U{\xc908\xe3ox\xba\x8a\xa3\x94\x8f\xd8\xeb\xf6\nA4\x8fG\xec\x8f\xb4\x17|\x11\xcd\xe3\xe7\x18\xd8\x9d'#\xc6y{\x95\xdf\xc8\x97\xabw\xf1k_\x8c2\xebP>\x8e\xc2 \xe2?\xf2\xc3`\xe6gq\xf2\xa9?;\xe5#\xf6\xaeCE\x85]\xe9\x88}\xb9F\xf1\x11\xfbi{\xe9\x02u\xdf\xe6\xcb\xa5\x9f\\\x8e\xd8\xcb\xf5+} A1G\xec\xcd\xfaU\x11~\x9f\xb5W\\\x04\xa7\x8b08]d\x82\xe1\x18\xb1\x9f\xb5\xd7H$\xa6\xa4#\xf6y\xf7\xd2#\xf6M\xf7\xc2\x9f\xc6\xb3\xcb\x11\xfb\xb4\xbd\xc2\xcaO\xfc%\xcfx\x92\x8e\xd8\x8f\xd6(\xfe&>\x1f\xb1\xdfh\xaf\xc0/\xf84\xcf\xf8\x88\xfdV{\xd9\x05\xf7g\xd0\x91\xdfl/\x0bF\xb4\xe9\x88\xfdZ{Q\xb8\xc5\x17e\x82y\x1d\xb1\x1f\xb6\x97\x8f\xcfxr\x16\xf0\xf3\x11\xfb\xed\xf6\xc2\xf38\xce\xc4\xc2\x8c:,\xb4\xcf\x830\xe3\x89\xb6\x9a\x93\x0e\x95^\x0b\x88\xe3t\xc6\x1d\x8aO\xf3$\x1c\xb1\xa0C\xc9t\xba\xe0K\x81\x83~\x87\xc2o\xb1\xb0\xd6\xf7\xbcC\xade<\xe3\xe1\xe1\x85\xbf\\\x85|\xc4\xc2\x0e5\xbe\x145~\x9c\xf8\xab\x95\xf8\xc6\xb4k\x8d\xe7q\x18\xfa+\xb1F\xd2\xaeUFl\xde\xb5h:b\xab\x0ee\x0f\xa3|)\x9b\x9eu(\x8e\x8c\x8e\xac\xb0\xe8P\x01\xcc6e\xf9\xb3\x0e\xe5\x0bg\xf7\xb2\xce\xb2S\x1dd\xb8F\xec\xb4C\xe9w\xc9\xe5\x8b\xecU\x9e}\x9ag\x99 \xeb\x97\x1d\xea|\xe9'\xefg\xf1y4b\x17\x1dJ\x7f\xea\xa7\xfc\x0b\xff2\xce\xb3\x11{\xdb\xa1\xfc\x8fx\x92\n\xde*\xf1O\x97>\xae\xb7\x11;\xe9^\xf1m\xe6/W#v\xdc\xa1F\xb1a\x1c^d#\xf6\xc5z\x15\x80|~\xd5^\xe7\xb5\xa2\xb7\xf0\x91__\xa3\xc2\x8bh\x1a\xe63~\xb8\\\x89\xd9\xfcq{\xcd\xa2{\x10i\xe4\xc5\x1a\x154\xaap\xda^\xed3\xceW_\x04\xd1\xfb\x11;\xef\x00e\xc1\xff|%H\xda\x1f\x1d\xc8\xd7\xe6\xb2\x02ap\xeb\xc6\n\xeaw\x03i;;}\x96\xa6\\p\xf8\x87E\x87\xc8\xd2\x9d\xe4\xd8\xb4\x9frV;K<\xef\xa4F\x88:\xb5\xf5\x9eh\x8b\xd4\x1c\x8dg\x05\xbc\xd9\xbc|M\xcbW\xbf|\x0d\xcaW\xeal\x8az@\xf9\x8a\x87\xbb\xb0L\x88<6-\x7f\xad\xca\xd7E\xf9zV\xbe.\xd5k\xe3\x89\xf7\x15\x87\xe0\x03\x8f\xa8#/\xe6m\xef\x1a\x11\x8e\x8a\xbc\x9d\xedz\x9e_\xe4\xdd\xdf3\xa2\xe5\x14y\x0f\xef\x1b\xf1\x80\xca<\xe3\xf8\x1d\x96yF_\xa6E\xde\xa3\x9dz\xde\xbc\xcc3\xfa\xb2*\xf3\x1e\xd6\xf3fe\x9e\x01\x97\x85\xca\xbb\xbfe|\xef\xac\xcc3\xda\\\x16y\xc3\xadz\xde\xa9\xca{\xb4c\x8c\xef\xb2\xcc3\xc6pR\xe6\x19\xdf;.\xf3\x8c1\x9c\x17y\xf7\x8d\xbe\x1c\x96y\xc3z\xdeE\x99g\xcc\xfb\xdb2\xcf\x80\xcb\xf32\xcf\x98\xf7\xf7e\x9e1\xef\xcf\xca<\x03.\xaf\xca\xdaq\x07\xdc\xebv\x11G\xab6\xcd5\xd9\x1amW\xc7\xceQzs\xa8\xc5\xe8=}\x10\xa0\xad\x1a\x04D\x10\xa0\xadj3b\x1a5w\xc9\x807\xbfU5\xb2\xf5x\xfd]ugDN48\x81\x1eD\x837\xf0\x03tX7#\xd7\x12\x8e\xa3\x00X)\x8d\xb3\xdb\x87.>\xaa\xdd\x02\xb2\xaaM\xf1\xc1\xaf\xf3\x14Y\x11\x8f\x84)\xc3\xf6\xd4j\x82\x10\xaf\xb4F\xf5\x98\x06z\xc2\xff\x8c\xf9H\xf5-\\j6\xaf\xbe&\x13\xc9\xd0\x19\x14&\xc5\x1b\xd3\xd1\x0c\xc6\xc2\x82D\xff\xda\xaalar\xad\xaf\xb54\xe7\x05ab\x9b\xe7\xac5\xd6\x1a\xec\xe4Y\xe5\xae\x1d\xb1s\xdd\xc7\x01n\x96\x06\xb8\xa9\x0c\x106]\xb7_$\xa9\x86;\xb8\xbfg0\x14.\xe7\xac\xa9\xcc\xb93D|\xc1\x83\x0c\x83\x9b\xd1\x1b\x98\xa3!G\xe2\xac\xf3\x00x\xcf!\x85\x97\xb0|\x0e\xcb^\xcf\x05\x8c\xea\xbe\xec\xc3\n&p\xed\xac\xa7\xcbY\x1f\x96\x8c\x8c\xb0\xaf\x86\x10+\xe6^\x99\xf4-\x0e\xc6\xb5p\xf7\xc7A<\x87\x0e:f,\x06!\xbdM\x1d\xd7E\x0f\n\xcd\x10\x88\xb3@\x17\xadi4\xc0\xab\xe8>\xb0\x01q\x8b)Q\xa4\x19\x944b\x924}\x9f5W\xc9%\xa6\xe0\xfd7!\x1b\xd5\x8d\xcd\xc9\xc6\xb3\x9d/<\xc10{6;\xc9\xe3\xc1B\xd4\x89\x9c!\xab\xc8\xa6NyT\xeb\x07\x12\xef\xd0\x19\xed\xed!)\x15\x14\xf5\xd9\xa6 \xac[\xe2\xef\x9e\xf8\xfbTKh?p\xf3\xc46]Y\xc0\x95\x87\xcd\xec\xcb0\xbf\xb5\x88i\xbc\xcb\x9a\x83A\xa0'\xd0\x92$VI\xe8BO\xb8\xd7\x82u\xa9\x14\xcf\xf9zU\x87r)\x1a\xa9\x96_\xf3N\xb7\xab\xe5+A\xe7\xab\xe5KQ\xbe\xe3\x0e\x12ZQ\xcb\xde Z\xbf\xe3:U^_\xf4^\x9d\xda\xb9h\xad*Y\xde\x88\xf2*;u\x88\xb1ws+\xb3\xf2\xc3[\x1eI;\x8e<\x9aT\x82q\x9e\xe0#\xb1\xee\xe5G\xaf\x18\x05\x17/!\x01\xf7\x9c\xdb*w_1\x0f\xa9(b\x0f`\x1fw\xc9\xc5`Q~p\xcc\xd8\x97\x8e\xdd\x04T\xef\xcf\x0e\x8a\xdd\xc9\xc9\x00\xa3\x8f]S\xa7\x8aG\xea\x87QC\xa7\x9cZ\x17\xed\xa6\xa6\xa13z\xe6*\xb9\xcbg\xad\xac\xfd\xe4\x87:W}\xb82\x1b\xc3\x1b\xa2\xe1\x08\xc2\xe5\xbcb\xf4]{>\x8a\xb5\xf8H\xff\xe0\x11\xd3\x0e\xafi\xc8M\xdb(w;\xbbr\xd5\x94\xa7\x9a\xa0\xf7\xe6 \xc8\x9f\xab\xe8\xf7\xa1q\xce\xd7\xf5\x8c\xa5P\xcc\xa3\xe3t\xd6\x0e\x8fi\xa9\x8b\xea\x84G\x11\x1f\xb6p\xa2)\x0f\xa7<\x98\xd3\xa6`\x85 M\xf0\xe9\xe0\\\xebM\x0bH\x83\xcfCt\xa7\xd4/\xc0\xb5\x08xH\x07\xe7\x9e\xbe\xc6]\xb3\xc5-\xa8\xd2#O\x18z~\xcd\xcd.\xd1\xd0\x91\x0e\xce\x93RZ\x8c\xbcE\xa37\xb9\xfc\x08c\xd8\x82|F\x18\x817\xba\xc2\x98\xa5\x0b\xe2[nq\xe4'\x11\xf1.ps4W\x0fDu\x86p\xcd\xb5=\xac=\x8fV\xc4oH\xede\xde\xc1\xea'c\xf2\x0c\x1at:\x9b\x02v\xe8\x14\xfb\x07\xda\xb5\xe2\xaf}tj\x15\x0e\xb2\xac>\x97\x83\xc6\xe0\xa0\xb9\xbd7\xa0aJcG\xf0\x1f\x19\xba\xbap\xdfPo@o\xfd\xd4\x11\xeed\x9d\xa1\xcb\xeb\xb0\xdd\xa6\xd8\xe2\x07\xce\xa1\xd3\x15\xfbn\xc3\xbb$~\x08\xde\x9d\x17\xd0.\x0fI\xcd\xd6\xf1\x83\x13rk\xd8<1N\"\x9cA\x13\x87\x9f\xd8\x81\x13\x9b\xa9\x01T\xf7e#Xp\xfc\x1d\"\xe6'&\x11\xe8\xdc.\xd5\x8f\xde\x95\x07\x9f\xd4\xf8\x8d\xc8\xb7\x08\xaf\xec\x89 O\xec\xa08uR\x94D\xad#\xff\xd8n\xe4\xfch\xd2\x0f\x9e{\x15\x0e\xce\x8d\x01=\xc3bR(`\x8b9\x19\x8e_\xfb\xb1\x8b:q\x19\x98\x99o\xac\xe2\xf0\x03\x8f\x84\x8f1\x8c\x98`\x1e\xe6\xe0\xa7 \x0d\x16\xb60\xba\x08\xe7\x0f\xe8&=i\xcb<\x81\"Z7\x9f\x85\xe77c\x08\x9b9\x93\xf3\xf9X\xcd\xf1\xaf\xfb\x18\xb8r\xf9i\xc7\xb1\xa4\xf9E@\xe0|\x14\x01\x9e\xd9\xf7#\xf1\xfd[\xb2\x01Gy\xbe\x8c/?\xf9]v\xc6\xe4\xe8\x1fr\xf4\x1f1\xfc\x0e\xfb\xd01\x8d\xb7\xdd8\xc5\xf8\xec\x13i\xb1~\x0dk\xf7\xd98\x7f\x8deQy\xbb*\xfe\x11\xb8\xd7O\xac\x1b\xf6RD.>\xe9\x83\xdc\x14\xdd>t\xcf/\xbbn\x1f\xe6\xdc\xd5Jx\xcc\\\xfaU\x17;=\xfaP\x07\xd1\x84\xb7\x9bc\x8a\xfcY!.V\xa0\x1f\x15=\xd7\xe0\xa1\xa8\xbb\xfa\xfc\x107O\x925Ppv\xfc\x97z\xf2\xf2\x92\x84\x8b/\xfc\xc7\\\xf2~\xf8\xeb\xbaV\xf9R\xad\xcc\x19\xc5b@nq\xa5&\xd4\x1d\xbb\xaes\xa2\xc4\x8c\xaa\x8d\x8f\x86\xe3fQP\x8ar\x07\xceJ\xae\x9ak\xd3\x15FWe\x9dtGI\xce\xca\xcey\xb67\x98\x80e\xd4\\\xe3\xd9\xc9jq\xe9\x07\xd9\x18v\x16\x8b\x9f\xe3\nL\xbc\"\x97\x8f\x841k\x80\x7f\xad>K\xd8\xb3S1\x8f\xceH\x0dTS^\xe7\xf2>Bti\xd2\xdc\xcb\xebH\xd6\x11\xaa\x10\xe48\xcd8$\x82\xe8\x18\x89\xb9\xd4\xc1\x84\xf4\xa6\xea\xb8\x89\xdd\x14\xe9\x07\xa8\x98\xa18Q0\x04\xecG\xbc\xaf\x1a\xb9\xf9#\xc6\xa4\xe0\x93#\xf1D\xc5\xe6\x8b\xc1\x82\xad\xb2\x15\xa5\x8b\x08\x0f\xfb\xfb\x80>r\xfc+a\x1c4\xbd\xe1\xbe[c\x0c-R\x9a\xe4\xc2Y\x0c~\x82\x1e,\x06\xbf\xe1\xffx\xbfr\\E\xc8\x0f\x92):)\xbd\x1c:\xcf\xf6\\G%\x15B\xbb\xba\xeb:j\x11\xa9*Xy\xbf'\xa5\x1e\x15rS\x9d\x1a\x83N\xd3\x1aK\xfe\xe8@G\x98@\xd1<1\xf4\x14\x10w\x1d\x1e\x8aD\x8bg50\x15\xc3u2\x06\xe0\xce\xb1k\x1d5.w\xd3\xb0\xc5\xa8n\x9cL\xee\x8d|\xd9Nro_+\x9aV \xe9\x1c\xb3\x86\x1ao\xc8N\x06x\x84\xbb\x03\xdc@\xce\x95\x8a\x15\xb6i\x91 h\x9a\x92\xca\xa9\xea\x0f=N\xb4R\x83\xd2\x92\xbb\xf2Z\xb57\x91\xa8b\xd6\xd8\xf8\xed\x05UIFm\xb9 A4iI\x90\x0f2\x96\x8b\x99\xc5\xbaf\xa4\x9c\x9d\"\xed\xd5\xac\x18|\x01\xf6\xc1\xef\xf5\x9a\x19\xc0\xc4\x90\xb6C\xfd\x88\xec\xc9\x9c\x02\xb2\xbd\xd9\xeb\xf5\x0be\x19\xc3\x88\x96\xa9\x0e\xd4O\x82\x9cE\x92'q\xc8D\x12\x89\x8d\x0d\x94/b'lb\n\x8d23\x084W\x9a\xd2\xd6\xd3eG\x90.\xc6\x03\x1e}\xc2\xf1\x07\xd7m\xcf\x95\x98x\x8d{\xf7[!\xba\x19\x8b\xa3\x07`\xf1\xc3q\xab\xbe\xea\xc5\xb6\x03\x8b2O#\xdd\x82}\x05\xa2\x81\x08\xc0\x1b\xd9V@!A\xf8\xf5KmMtgu\\\xdcuc\x94\xc1\xf2P\x93\x1b\x1f\xb9\xce4\x8f\\P\x87\x9cG\x12\n\xc3\xb1~%e\xb8\xa1 P\x8c%L\x85\x9aT\x03\x12lg\xd4\xa2\x9dt:\x9c\xa9m\xf5!\xd5gd\xc7\x167[\xb6\xc8Z\x19i\xda\x15\xe5\x86\xd6\xb7\x1e\xd4:\xfb\x7f\xd3\xd8\x87xj\xe8i\xfb\x0bzb\xffo5\xf4'\xea\x180N\xe9B\xc4=\xc66\x94SQ\x8b\x91f\xbb\xb1\xea\x8d\\d\xb9\x1d\xc5\x14\x84\x83\xf7Y\x8a.1\xc7\x17 \x8d\xaf)\x06v\x88\x07\xbf\xd1\x8b_\xfc\xb4\xfa\xac\xfc>O#\xad\xbd\xde\xcc\xf0\x91\xf6z3\xa9^o\x86\xce\xb3-\xd7!M\xd7\xf9ZNX\x1ay\xb5\xca+\x19\xf7ui\x13\xf0> \xa5\x00\x94\xde\x88\x90*\xa4\x06\x16o\x00\x9e\x035&\x98\xe6J\xeeE\xd8G\xbe\x9c\xa2\xdd\xc5\x97(\x88\"M\xd2\x0cPEScl4\xc8\xa3\xd5cl\x1c$\x04\xa9\")\xb6\x8d>V/)\xb5\"\x00\xc2\xaf|\xca\xf8\\\x9e\xaf\xbf\x00'qy\"D\xdb\x9a\x90\x81\x0cv\xe9\x04\xd6\x06\xf3D\x1e\x1d\x9fcgH\xae\xfd%I\xa5n<\xff9HR\x12\xceI\x10\x85\x1a\xad\x05\xc6\x7fC\x83\x1ey\xda\x98\x00z-\xf2\x7f\xe5\x15\x1d\x83\x1a\xaeq\x8a\xf2\xe3\x89\xc8\xa5\xadu)|\xce\xad\xda\x8frU\x95.M\xb5\x06\x92\xfa\xdd\xb1\xe0\\\x94\xb6\x8b5\xec\xc3<\xf2x\x94\x1c\x1e\xff\xeb\x94\xde\xa6G\xd1\x9c:]\x9d\x8e\x92\x8b~\x81;\x888\xe5p\xd6\xba\xb0Q\xec\xe3]\x92\x98x)\x8d_\x93\x94\x8c\xaby2@J|m\x00\xb1\x1e\xccI\x8a\xb7\xbel*\x8b\x06\xfc\xd6\x12\xe1\xbc\x0f\xedf\xbb\x16A\x08\xf5\xdd/\xc21\xc4\x06~\x0cS\xb2\xf2\x9d\xd4\xb4D\x80\xfb\x8e\xc7\xb2b\xef\xc1>\x86\xcf\xa5<\xfe\x0c\xcf\x0e\x1a\xa2\x9e\x1c\x1f\x19\xe6\xd4\xea\xdch2\xbd2\x9c&5\x93J_o\xa8\xc5\xc5\xef\x9a!\x8fLA\xae\xda\x804\xd0\xfe\xdaN\x95,\xb0>\xc1,\x8f\xa8\x15\xf1\x88Zq-D!W\x07\xe1ej\xcaD\x06\x8cf\xbapR\x0c\x93\xaaa\xc0\xa2p\xe1/\xb3\x98\\p#\xdb\xfa\x12/i\xda\"\x0c\xa0\xa2\x0djB\xcd\x07\x9e\xff\x8d\xeb\xa87\xa13\xaccm\xd5\x89\xc1\xf2*\xcbm\xa2\x8aNc'\x1e|\x80\x1e\xc4\x83\x8f\x16i^\xa4\xf7j+\xe8\x10\xa1\x9e\x8b$G\xc1\xf6\x82/\x7f\x18\xa4\x9c\xd0\x84\x1e\x9a\xa0c5E]\x08\x93blF\x93\x17\xf1\x1aOH\xe0\xb8U\x11\xd6v H\xe5\xa8\xb6\x82\xee\x1a\x8f1\x99}\xf8\xee\xe3\x12\x91\xd3\x1e4,\xb3\x96\xe8;\"o\xddt\xcf\xcfM\xf7\xca\xe8xbA\xc44n\x8d\x84\x11#\x11\x987\xda\x88n\xbe\xd6\x92A*\x00\xc3\x01E\x93\"\xa1u\x1d\x17r\xb0\xeb\x84(\x9f6k\x04\xdb\x00T\x82\xce\xba\xde&b\xf4\xd9A\xa32\x99_\xc2\xe9*\x15\xbb5+J\x0c\x01?\x88\xe9\x92\x864f\x0c\xd8\xc7,L\xfd\x15\n\xdd\xc2\xa9gIS\xc5\x95\xe7\x88\xach\xe2\xc4\xee\xc0\x0f\xe7\xf4\xf6x\xc1\xda\xaf\xbe\xdcu\xe1eM\xe3\xe5\x83\x08c\xa7\xeb\xae\x809&{\xd1\x0d\xa8\xe0c\xcb\xd6\xb7{\xec\xd4\xc2\xb4\xec\xfa\xb7\x94\xc8\xf9\xc8;\xd5yx\x11}S\xf7~\xb1p\xc6\xeb%\xeb`\x8b\xf7\xb5\xeb\xae\xb6\xa5\x18u\xd6\xeel\xf4;\x0c\n\xa37tU\xaf\xf8`\xd5\xb1\x9c/v\xd95\xab^\xcb7\x91\xdd\x93\xbb\xd5E\x14\xc0D~\x19\xd7\xccVA\x9c5\xfe\xc0O9@\xd0\xbe\xf1?\xffS\xfe\xec\xd6\xeb\xa3\x8e\x92\x87}}[~\xa9T\xa6y3\xc17e\xb0\xc3S\xb2\x14\xef)%\x9a\xb7\xf0\x92*BX\x95\xce\x94zMOX\xf7\x99\x91\x15\x04\xc2z.\x04\xc8\xf0\xa9\xa8\xe9\xb9\xad8w\xc7\xd4\x0d\xecC\x80\xb9\xa6d\x93\x0c\xde\xee\xe0&&\x8c\x99?\xaf\x93))\x03t\x93,Y\xd3pN\xe7')\x89S\x0d\x0c@H\x04E\xcd\xbf\xfa4\x98\x1bj\xa2C\n\x8f\xa9\xe4\x87:\x90\x820\x06\xefz\xd1j\xcd\xf6\x92\xa9\xa5k\x9ePA\xfbl\xa5qC\xc4\xf2)\x995\xd1Bhb\xce\xf4\xc0Z\x16\xbbfI\xd3\x0fr\xe3\x1c/\xf4#\xbc\x83}X\xb2e^:K\xe7\xbd3\x9d\xb9\xbaKS\xf48\xb9C\xb3(\x14n\x85pw\x87I\xb3ej\x91;\xcd\x8blD\x17h\x9c\xad\xde\xf9\x1e\x96~\x95\x028;+M+\xb7\xa5\xfa\x17\x15\xeb\xed\x93>\x9cT\x8an\xfbp2M\x18\x88o1MW@\x90\xc6\xb3\xe5\xfcIb\xa4(\xbf\xf8\xa5\xcf\xd7mp6\xc3\x83\xd2\x19\xb2\x0fW8m\x8c'\xaeu+\xb5!j$n\xe8\xaf\x9cs\xf5\x0d{dh\xed\xde`\xa7\xf9\x04\"t\xca\xe2\x1e]\x0f\xb9'\xcbU\xcb\"\x9f\x0e\xe5\x8e]Jk\xfa%\xd0\"\xf7+\xc4\x8f\x8b*vuY\xd97 \xb2}\xb8\xc8O\xe3\x074\xd6\x9d\xf2\xd3\x18\xf2\x01Ur\x1e\x82\\\xe0+z\xd7\x9c\x8a\x04\x14R35\xa46\xa8\xf9\xaf\xa7\xd2\xa8\xc4\xba\xbe\xec\x94\xbe\xa6qB\xab\\\xb4\xfa\x91\xa3\x83f;>\x91\xd9@\xde\x1d\x19\x15\xd4\xeaG\xca\x06\xe9`\x1d\xadMZM\xf5\x83\x0c\xb5\x98fn\xd0\xc3\x91\x08\xd3h\x84\x1c\xb5\xb8\x91\x92^l\x94\x1f\xb3\xa5\x1c(\x02q\xde\xde\xd0\xd6\x9e\x96Hx|`l\x91\xdf\xf7\xe1\xb4D\xe8\xf4\xa0Q\x0e\x8c1\x9c\xeaW%\xa6 m\xb4\x02\x91\x1f\xccz\xc1\xedp\xe8\xb5b\x9a%\x14y\xf2gBCy\x81;8\x17?B\xf1L\x81'\xffM\x03\xba$\x18\xa5\x84'\x92\xc4\xd2\x15\x86 \x95\xd9\xc0\xba\xa2\x94\xc4K\xa5\xa54\xbe;\x0c\xd3\xd8\xa7\x89\xcc\x97\xec|p\xfb\xd0i\xb0h,\xa2\x9d\xb3uG\x91\x17\xbaiWxo\x88P\xdbCW\xe1N\xb8v\x86;Kux\xea\xb4\x9eL\n;\x12 \x86X\x1d\xe1[i :z\xf0'i\xb4n\xa1\\\x03i\x00\x95\xa3\x8f\x19\xb7\xa5\x0dU\x05H\xd3\xe1l XP?\xb2\xb8\xd8`*}\xd4\x93p\x98\xd0\x01\x1eJ\xf2\n\x86-\x82\xf9eU\xd3\x14_\x93zb\x020\x83\x821\"L\x8c<\xbc\xf5\xe8:\xc5\xa8\xb4\x0f\xc4J\x06\x9c|\xa0v\x00\x156\xdf\xcd\xb4*vL\xa9\xf6\xd5\x8f\xd4J\x0d\xc4\x96\x140\xecC&\xf0\x16m\xc4\xc5NA\xef\x11\xae\x04\xaf\xa3\xba\xc4s\x86\xcc\x1d\x8b_\x85y\xe4\x12\xc5\xfd:\x1aHg\x9d\x0d\x18=\x07\x1fU\x11\xcfacC\x1b\x17B\xfd\\\x8b\x1c\xffU\xac\xf2\x1b\xcc{@H\xb1\xa4\x15\xf2\x81D\xc08\x8a\xc4\x9e$\xac\xb7w\x91\x97\x13\xe8\xd8\xe9\xd2pn3\x1d\x97\xad\xc8W\xe1\xc5>\xe4d\xabi\xa2 &\x8b\xb9kD6\xf4>tQ\xc3\xf1.\xf2\xba\x96\xd3M\xfd\x04\xe5\xd7\x85J\x18\x1bhw,\xe1\x9dm\xd0f\xb4P\xa3\xcc/0=/\x1f\xb0\x02\xb7\xa2\x10\x1d\x10\x9a\xc7\x01\xda\x96\x8b\xb9\x94\xdaV\x8a\x1b\x1b\xfe\\\\z&\xdfs\x8a\x8d\x0d\x7f6i\x1et\x1f\xbc\xa3\x0d\xd4\xfc\x1b\"\xf7F\x1a\xdfA\x92\x92\x94b\xd6\xf4\x1b?\xbd\x8c\xb2T(\xc5\xa2X\xde\x07\xb4Yy\xf8n\x10\xb7\xd6\xb0\x98\xf9?\x84\x84\x93\x8b8[\xa7-l\xac\xe5G\xe15\xed\x94*\xcc)\x95\xf1Z@~r&\xb0B\xa9B\x03\xbf+?\\\xb9\xaa\xa1\x18\n+\x10W\xb6rny-\x96*.-U3VI\"m\x10\xe8\xd5\xcfEL\xc9\xd57]D@}&\xa6)\xc5\xc6\xc5y\x8f\xfa\x02\x99>\xac+}z\xf0\x16Q\x01\x0e\xc8\xd4%\xbe2el\xcc\x17\xac\x9c\x05\xdb\xe5a\xe2s\xd7\xd7\xfc`@-^#wA\xe4\x11K\xfb@\xc4a\x99\xf6\xb11\xc7\xc2=\x8a\xa3W\x1do\x1f\xae]a\x0e,GA\x1d\xf2 \x06N\xbe\xf6\x00\xa4\xff\x16\x1cVi\xc58<4\xcb\xc6\x1fLJ\xf3\xc7\xf6a\x0c\xe2\xea\xa3R\xd3\xc9Y7\xb9\x83\x04\xf3\xc2\xfe\xd6\x98s\xd1D\x19\xc0\xfctf=\x84Q\xbc\"A\xa9\x07y5\xed\xa8o\xa4n\x1f\x0c\x1e\x7fz\xa0/\xfc\xd0O\x1a\xfd\x13\xf2\xda\x05\xc7o'2iNd\xda\xf9\xd3k\x88L\xda\x82\xc8\x84\xea\x8e\x11\xdbKe\x9csL\x0c\x95\xad\x81\xc9\x89\x17)\x8d\x19e\xe9\xa3\xe3\xb8 h\xf0P\xb2\xdd\xca\xdbC~\xfe\xfd\xa0)\xa8\x92\x80d;\xa2\xcb\x8d\x84\xdb\xb2\xa4\xa0\xd9\xb5\xb1\xd8\xb5\xcd\xfd\x81\xa26\x8b\xed\xbb[\xfd|0\xd9d\xab\x1f\xfb\xb1\x0e\x05\xc10\xcb\x11\xf0\x85GG\x8d\x0b\xf2\x03&\xca\x07\x82\xef!iJW\xeb\xb4\xfb j*\xb5\x01x\xe32\xae\xea%\xad&\x82\xea\x0eR\x94\n\xf6\xe5\x91Woc\x8c7`\xe7\xecc\x9adAzDVt\x0c\x0d\x01-\x18]{\x17yc\x83m\"p\x85\x0e?\x9d\xb8\xe2A\xa1\xab9u,\xc4@\x03q\xac\x95VM\xc0J?sy\xf6\xbcA\xcd+q\x95\x9f\xf1\x8a\x9eI\x89\x0fs(\xf2\xe6\x1d\xea\x01Q\xcb\xa7\xe9D\xaa\x82[\xfb\x0e\x11Z\xe5S\x07\xef8\xa7:[f\xb1\xc8\xfe\xe0\xdc\x0f\xaf#\x8c\x02j\xb3\x15P?\xb9\xdd\x80U\x8b\x99\xb7f\x8a\x95(?\\s\xc8\xd6n\xae\x11\x08rm-\xf8 \x90 \xa6d~\x07q\x16\x86~\xb8\xb4\x89\x01E\xabZc\xf9jU\x95\x1e\xe5\x19\xc6\x0d\xd9\xf0\xe5GL\xf4\xadA9\x0e\xcd\x9a\x85\xb0\xe0\x00\"<\x96\x10O\xfd\xe7\x8d*Z\xc9\xf6\x85\xf9\x06m&\xef\xa4\xa9Q\x10\x0dg\xe8\x14B\x18\x064\xd3W4\x96m\xd32\xc8\xca\x08\xe3\xeb\"\xafns\x1f\xa0(\x85\x1a+\x7f\xa9x\x06\x12\x13\nZ\"\x97\xc7\x85Pjb\xc3B\x0d\xdb|\xfe\xe4\x92\xb9\x8a]E\xa3\xcd0+\x90x!q\x92m\xbc\xcb~\x9b\xde\x01\x9d\xa9j\xba@\x07_m\xf0v\xe2C/1\xb6\xa1BU\xc3\x01\x97O\x9d\x82o\xe5\xad6l\x18\xd8\x87\xb9\xbd\x8a\xd4\x17\xdd\xe4D\xa8\x19\xb1K\xdcq\xd2\x9a\x99\x10\xc0\x957 \x13\xb8\x841\xac\xfb \x8e\x8b\x87\"i\xe3u\xa6\xfa\x11I\xfd\xb0\xabvZ06\xc6\xb1\x18k\xe3\x0b_\xb3\x07T\\MrQ\xc3\xc9\xf1\xae\x90Y\xa4ZV\xd2\xad\xc4\x8eX\x06F\xbaV\xfa\x99-}\xd8\x07\xe2\xf6+\xc97M\xc7\xf0\x8d\xed\xc42;S4\xaeX\x8ai\xb5$z\x99\xd7\x89\xc4\xcb\xdc\xb3\x07\x87\xd1v\xa6\x8d\x11\x1c\xda\x0eQ,E\xc3\x08\xdb\x0e\xab\x15\xd0\x0f1\x9e\xa0\xe1\xe1\xad\xed\xe1\x89\xed\xe1+=0\xa6R\x01\x91c\x9d$=\xb3\xfc\xce\xcal\xd8&?\"hg;\xf1Le\x83\x05\x93\x84v\xb2\xadW\xb7j\xee\xaa\x9f\xf0\x95\xc5\x9a\xb4Nu\xd4\xd1\xa83\xb1\x19\x1a\xe4]\xf9\xad,\x8d\xe9\x8dt\xa7W \xda\xc0\xc3A\xc9\xb2\x90\x07\xbc\x8ey\x90\xbc\xa6\xd7@\xe1:n\x1c:\x0dg\x18a n\xc9{Hr\xd5\xd9\xdf\x177Fm:\x04\xe5\xa8\xc9\xda\x13a\x10\xd7\x11 \xbf@n\x1e!\x14pE\xcb=\x8dE`\xa0(E\x03L\x05\x8bV/]\x17&r\x1dr\xef\xa2` \x9e>\xc8\xb8\xa3\xfaI\x1d\xb9\x99\xa8X\xa2V\xaf~~\x88\xeb\xae\xfaI\x9d|\xd3>\xacC\x17\xc6u\x10|\xd5\xd4\x93\xdc$\x01C\xc9'-\x07\xd2j\xc8\xcd\n\x04\xe2d-x/\xb1w\xd2Z\xb0\xf8R\xad\xb6T\x08\x14J\x06\"K;\x87\xa0\x8f{z\xcc\xa8B\x9dv\xb5\"]\x07\xd6\xc8/<\xec\xa6\xd4\x0bL\xe5\xfd\xacF\x11U\xb0\xb9F\x99\x13or\xea&\x0e*\xb3\x92\xb6`\xac}L:/\xc74\x10\x80\xa9^\x1f\x17\xca\xd8\xc2PB\xcc\xd5\xd0e\xaev\xbc6\xd3\x84T\xc3:\xe5\x1d\x943\xd0\x9f^\xd2\\\xa1\x02\xf3\x88&\x10F)\xac\xe3\xe8\xda\x9fS \xf0\x18\xdf\x7f\x0c\xbcA\x93b\xc8\x86\x0b\x9aH}\xdaE\x8c\x90*\xc7}e%\xc5\xa85\xf4\xb9&H\x0bz,\xf1\xcf\x02\x80Hh\xc5\xebK\xac\x81\xa8\xbc\xeb\x89\xf4B\x90Tm\xe0\x95\x88\xe0\xed\x9dt\x8a4D\xe8\x9dfx}!\xe2\x99\xa7\x85B_\xa8\x9b\n\xee\x02\xcf\x95\xb4\xa4P\xb2\xdb\x19\xe8f\xc0\xb3\xcd\x8f\xcb\xef6\xa0@\xbe\xfc|\xd0\xe0s\x1c !\x88#\xc4\xd4W\xab\x9d{lwa\xd1o \xae\x1d\x1e\x03\x9d\x0egu\xf4\xa9\xaf\xc3\x88\x9b\x9ar\xa0\xc9\xcbd\xcc\xc72\x9a\xb9}\xd8T\x1f\xabz|\xa0\xdc\x1d>\xd7\xd2c\xd1\xd6\xcc\xad\x9b+\xa19]\xdan\xce\x1f\xecs\xa6\xea\xed\xd9\xfd\xbd\xf6\xfa,\xcdMR\xa4L \xbd:R\x8e\xbf\xa5F\xf6\xab\xd1\x94\x0d\x03;\xd5\x0f\xac2W\xd8\x87\xa9}]\xb8\xa9G}e08\xacd\x92\x8f9\x10\x8b\xc8N M\x9d\xea\xfd\xbei\xa4\xef\xf5#E\xaaj\xd3\x16\"|\xa7\xc4p\x07\x81\xb4]\xa1\x12|\x7f R\x9fom\x8fJ\xcf_\x1d\x7f<,?/eU\x1a\xbc>|s\xf0\xe9\xdd\xe9y\xb5\x9fQ\xa5\x1fY\xef\xcd\xa7w\xefJ\xf5\xb6wJ\xf5\x82\x88\xcc\xf1\xc2\x94}\xa9>8\x08\x82\xfc\xd9\x01\xe3 \x8a\xc7 Y\xd0w\xf2]\xf9CWA\xb6\xa1\xfcV\xab\xcd\xb3\xd5\x1a\xb95\xf6\xa5\xfa\xfek\xf9P\xfeP+\xfc\xf5\xe0\xfd\xbb\\q-`\xb0W\x9a\xdb\xfb\xb7Go\xdf\x1f\xbc\xb3-G[0Z \x98x\x84\xbb\xedv\xd9\xb7n\xe9\xd9\x9a\xc4\x18F\xd1w\xba\xf8\xb5\xfc\x14\x93\x19\xcb\xe7\xe2G\xb9\x06\x99\xcf_\x95<\xa5|\xa7[.\xeb~\x93M\xfc\xb4\xea\x06\x1d\x15\x00-\x95\x8b\xb4Z\xdb\xfaDq\x08\xbdRyV\x80\xacT\x9eh\x9cE\xad^\xa1\x01F\xbd-\x15y\x18\x07\xbaL\xaba\x1f\xb6\xcaE\x0c\x81\xb6\xcbE\xf3z[\x97\xf5\xb6\xae\xebm\xad`\x1f\x9eL\xcfn\x87\xc3\x8d\xb3\xdb\xe1\xd3\xb3\xdb\xe1\x8fg\xb7\xc3Wg\xb7\xc3\xc3\x8d\xb3\xdb\xd1\x9b\xb3\xdb\xbd7\x1bg\xb7O\xb7\xcfn\x9f\xeen\x9c\xdd>{s\x96\xbdy\xf3\xe6\x10\xff\x7f3\xbb\x9f\x9ee\xaf\x9f\xb2\x97\xb3\xd7?\xbey3s&\x1dV\xf2\x8a\x97\xb0\x1a\xee\xbd3\x19O\x7f/W\xbb\xff\xdd\xadT{R\x1e\xd6R\x0c\xeb\xe9\xceY\xb69\xdc|\x8a\xff?\xab\xd6\xba\xc3Z\xfd\xb3\xe9\xd9\xec\xec\x1fg\x9f\xab\x8f/\xd8\xe3\xdf\x9d\xc9\xb8s\xdf\xe9\xdcw\xa6d\xe3\xefg\x1b\xb3^\xc7\xfd\xf3\x13\xbf\\\xf3\xbc\xa89\xfd\xbdh\xcfu&\xe3\xff\x98\x0e7\x9e\x91\x8d\xc5\xec\x1f\x9b\x9f\xef\xf9\xf7\xbf\x9fm\xfc_\xcf\xcf\x9e\x9cM\xc6\xff\xf9h\xff\xacw\xf6\xe7\xfe\xf9\xd9\xa0\xf3?g?<>s\xce\\\xf6\xf6\xcc\xfd\xe1\xcfO|\xddYqc<+F\xc3\xc2\x8an\xb4\xc5\xbf+\xd4\xbc\xde\xd4\xa1\xb1\xa9gEK[\x9b-Z\xba}HK8\xbe\x87\x8e\xf5\xc4\xd8\xc3\xf6v\xd1\xd4\xb3\x91\xf2}K\xe9b\xb3\xf4c\xa7E\x87\x1a\xbd\xbaF\xc5,\xc7\xf0\x14^\xec\x0bgI\xf6mg\x0f\x13Zn\xb0\x07cx\xb6\xc7\xca0\xaa\xf8\xd6&\xdc\x0b\x9bF4a\x1c\x0d7\xd1\x9ca\x83U\xea1\xb0\x8cacd\x1d\x98F\xff]\x8c\x82Or\x02\xdd\xb3a\x97\xf7\x9c\x97\xfc\xff\xb0@\xadr\xc1JF\xa3]\xa5(\xc5J\xd5\x82Q\xbe\\\xac(\xe4EjK\xd7X4\xdcT\x8a\x16\xbc\xd6\xb6R\x14\xf3Z\xa3\xa2\xe8\xff\xcfJ\xb6\x94\xd7\x00\x0b\x8a\x97\x1ew\x1f\xc3\x18\xb6\x95i<\xc1\x11\xaa=\x9d\xb1\x92=e8\xff\xe7\x7fc\x9d\x1d\xa5\xe4\xff\xc6:\xeaL\x91*\xb0\xd2\xa7\xc3J\xe93V\xda\xedZ\x17\xe1\xc0\xb8\x08\xb8\xfe\xbb;;[;0\x01\xeet\x87y\x0b_]\x92\xf8U4\xc7\x9c\xa8c\xed\x83\x9d\x9d\xcdg\xbb\xd0\x03\x87!\x0eka\x17^\xbe\x84\x11\xe3uvv\xb76\x87\xe5G\x8f\x18\xbc\xb7\x14o\xd9\x82_\xcb\xed\xe4\x8e\x85\x9a\x043\xee9\x9b;\x8c5\xfb\xa0);\x054\x97;\x85\x17\xb0\xb9\xb3\xfb\x1cN{=\x17\x8e\xa7\xa73\xd8\x87+\xe7\xd4\x85 \x8c`\x0c\xc3>|(\nu\xc4\xe9\xbdV\xc1\xa9\\\x94Dx\xdf\xc7\xc3\x17\x0f\x16~@C\xb2\xa2\xa8,\x0b\xd7Y\x8aN\xb4Q\xe2\xa7huH\x07\x81\x1fR\xb5\x0c6D!:\xd0\x97\xe6^\x1f\xcb[\xedX8\xcf,\xc6i}\xff\x0f\xed\xfbt\x10\x85\xbf\x918\xf4\xc3%w\x8d\xce\x7f\x8a@\x85\xa8U\x12\xed\xeb\x16\x87\xad\xcbQMe\xc4\x18\xb7\x9a\xd1\x99V\xb9{]$\xa4\xab\xcb\x8e\"7\xf0>\xd0\xc15\x8d\x136\x8dG\x8f8$\xba\xf3l\x1d\xf8\x1eF\x1d\x84h\x01\xff\xc1\xba\x84\xb9\x1fS/\xf5\xaf\x91\xc7\xe2IC\xf2\xa4:\xf9\x9b\xe5\x9a@<\xc6`&@o\x89\x97\x06w\xc0d]\x99\x03\x12\xe3E\xb3A\xb0-\x85w\xe0O~w\xd8\xa17\xeb\xb9g\x03\xf9\xed\xcfO\x06\xf4\x96zN8\x1d\xce\xb8\x17\x1b\xef\xc8\x0f\x82\x8dE\x14\xaf\x98\xa4\"\x1a\x04L\xb0I\xa1>Z\xc6\x8e!\x03\xf96L\x9d\x18\xc3B\xe2^\xf1\xcb\xe5\x9b\xb2\x9c\xcf.*z\xcbB>\x13r\x11\x88\xf6%\xccD\x9f20\x1b\xe7?\xe5\xc3}\x081\x12%\x1dx\x97\xd4\xbbz\xe7\x87\xf4\xc7\x98\x92+\x0c{\xc1v\x90\xec\n\x0d\xdc7\x8b\xaf\x7f\x88^\x93l\xcd8Y:o\xe8\xb4\xb4\xba\xd5\xccb\x07?=\x0c]\xea\xb8\xb2iX\xed\xd3\x83\x9f,\x8b\x9d\xdeDE\xc2O\x06\x988\x07\x08\xf2\xc7\xb8\x0e\x17\x83\x94&\xa9\x13\xa3\xa8][\xda\x94,\x81'o\x01g\xe1\xc7I\x9a7\xe8J \x94\xc6\xc0zI\x84\xeef\x90\x92\xe5{\xb2\xc6\xcb[9\xe2\xc7\xe9%\x8d)\x9a\xbb\xc1:\xa6\xd7~\x94%\xc1\x1d\xcc\xa9\x17\x90\x98\xce!\xc9\x16\x0b\xff\x16\xa9b\xf71\xf4 \x86\x1e<\xee*\xc3x\xec\xf6\xe1\x9c\x0f92\x0fy\x1dS\xd6\x8c\x93P/\n\xe7-\xc6,\x07;\x8dg\xb6xr::\xfa\xd1b'\x89\xb7\x0cy>\xb5\xf2\xba\xa2f\x10^\xe8QA\x18\x93Ib+\xdcH\x11q\x8c\xd1\x81\xf1(\x89\xb8\x83\xad\x8fw\xbfB\xed\x06\x11\xbc\x00\x9f\xfd\xe9\xed\xc3\xc8\x15<\x83C\xb0\x8e'\x8e\xb4\x03\x06PW\xf0~/\xf6y|8\x82|\xcfh\xb4=\x1a\x8d\n`\xd3\xdb5\xf5\xd8\x9e\xb8&\x81?\x87\xbf\x9c\x1c\x1f\x15\x11\x0cuv\x8bhp\xb5\xe2\xab\x96)4\x84-E\x92\xc6\x94\xac\xd0\x16\x89\xf8a\x02a\x14n\xacc?\xe4[=o6\xd1\xb6+n=\xd8\xbc2\xd3\x9ai\x96\xecu\xb1d5\x87M\xbc\x7f\xe1\xeb\xd5\x87\xa0\xdc'B8\x1e\xf8 \x17\xfd\x9cP\xc1@\xa1\xaaY\xd1xIaE\xd6k?\\&\xcf\x11\xdb\xc4\xdd\xd6\x1c\x92(\x8b=*.9\xd8&P\xc9\x1aC\xc3\x8c\xaf\x1e\x13\x16\x1d\xc58\xf6\x8a\xdea\xa2\xb7|A3x\x01\x01\xfb\xc3\x17\x14\x9dd\xa6\xd9,\xdf{)\xda&`r!\x1e\x95 \x9c\x12\xb6\xeb\xf9\x0fU#\xae\x03\xcf;\x05\xa3\xd5t\xaa:P\x05}\xf0\xeax\xcd\xb0\x90\xb3MN\xa4\x9e2y\xc4\x11\xf8\x07\xe6\x83N\xc9r|GV\xc1 \x8a\x97\xfd\xcd\xe1ps\x8c\xf0\x13\xa6\xf3u4gm\xf3\xf4\xd2~\xc2\x99\"\xdf\x96\x958\xe0\xe0\xf4\xf0BL\xc2.\x80\x17\xe0\xb1?\x1cv\x12\x17\xfci0\xd3\x9b\xe4!\xf6\xe6\xd5\xeau\xf09\x1d\xfc\x91\xf0\xbb\x95$\x8f\x82\xcc T\xa7X\x13^\xe0p\xbe\x08\xd8\x1e\xc3\x0c_5\xd6i\x1f2\xfe\xa4`\xb0\xca|\x01\x9dK\x14\x83+z\x87!M\xd2i\x84\x17\x7f\xf9\xadM8\x8dfZ\x01(\xb5.\xfe\xa7V\xb2\x94\x102D\x8aMN\xa3\x14JR\x8c\x1c\xf32\x15?{=&Vl d\x98\x80\xa3>\xea\xe7\xa2\xa6\xb5E\xce\xcb\x15\xaf1\x1e\x9d\x83\x87\x00\x02\x16\x9d\x9e\xd8\xf6\x92\x84\x8aSx|\xd6\xc3\xe4C\ng\x8a\x13\x90\x8dY!\xf37\xd3\xd9]J\xc69\x94\x19\xfflSx.\xb2~GZchqyr\xe8D\xees\xd7\xd4Z\xaf\xa7\xb6\xa7\xdd)\xb8\xdb\xb6\xb8he\x08\xf0?\x8f,\x979mz\xd6\xbe\xfc\x19n.}\xc62\x8c\x86\x05#7\xda*\xbe\x8bb\xc3\xb8;7x\x14\xe12\xd6k t>a\xf2\x90f@\xf7!fx\xc5\xd7\xfbm8\xe7\xe6\xcd\xc3\xe7R\x90e\x0b\xa0>d\x95\x1f<\xed\xcf\xba]\xb6!8\xf4b\xba1G\\e$/\xf8c\xcel\xce\xe9\xc2\xf7|V\xec\xe3S\xe4\xfe\x91k\xb3b\xe5\x1b\xc3~\xed\x8bD\xb3r\xc8ZR\xd0q\xb6wpl\xa6\x8d,2\xe7n\xefr[\x01\x0c\xfd$\x84\x96z]\xe81\x82\xdaTe\x93\x13\xc1\x90m\xc5\xad\xbe\x80MC\xff\x9d['u\x1bd\xc8\xbfke\xc0QNjTf\x81\xeb.R\xcc\xda\xcfc\xce\x15\xcf\xe2AL\xd7\x94\xa4N\xf7\x0c\xcdd`\xa3\x94(K\xd7\xf5\x8f\xda\xae\xafE\\A\x89Q)\xd1X\xe2\xf9\xdck2\xf4.\xaby\xb3A\xa8\xa5u\x99Q2M\xae\x11\xeetQ\x08\x95\xbcM1=\xfe\x831\xb8\xf2;;,\x88\x90 \xda\x11+lk\x9b\x93\x13\xfc~\xebX_Dtp5\x97\xbe\x92\xb9\xed\x0c\xfbP\xa6\xffHbY\xf1\xc6\xc8\xad\xef\x96}\x06c\x99\xbb*\x0b\x82v\xa3\xafu\x9f{.\xf0\x0d\xc2O\xdf\xdf\x04q_\xf0<\x1e\x1d\xcc\xce\xc2\xbb\x92\xc8\xe1\x96\xc7\xd7\xa6\xf3~q\xd8#-\xc8\x8f{1\xa5\x97\"^\x8c\x00\xb0+\xce\xb1\x0b2W\x89\x00\x93Z\x08$\xf4o\x19\x0d=\n4Lcm\x94\x80|b\x15\"\x93ji\xa9$\x01\x9dL\xe0\x08\x13\x9c\xd0W'\xc7\x1dd'\xe8\xe0\xca\x0f\xd1\xaaG\x8e\xa0\xdb/6\xd3>\xe3\x0c\x9b\x18\xca_\xcd4*g1\xf95\xbev\x07T1\x9dMq\x8b\x9f&N\xf3\x11P\xd8\x0f\xe8\xdaQ6\x0c\x9b\xbfI\x03C\x84X\xc9\xafv\x18U\xde\x15\x1cP\x9b\xd3\x82\xf1@\xc8\xcfw\xcc\xdcA\xe5\x851lq.)b\xef\x12%\x01g\xb7\xd3\xe9\xb6o\x85\xbf\xd1\xedC\x99\xd11\x98<\x1b\xd9\x816\xdd\xd5^\xcc\xd9\x00\x85\x0b\xd8\xdd4\x1e\xfd\n\xe5(lF\xd8\xecc\x9d \\\xdaem\x86W\xb0\x89Y\x98K\xb04\x9cK\x9d\x80\x10Do\xfc\xf4\xd2\x0f\x81\xc05\x8d/H\xea\xaf\xd8\xcaW\x15<\xa6p \x82sS\xe6\xdb\xb9\xe5\\\\\xbe\x9al\xaf\x11\x98H \x98,\xa5\xceC\x08\x90B\x10\x06z\xeb\x05d\xc5\x11pE\xe2\xab\xa4\x9b\xa7k\xae\xc0\x82\x1dP%\xf1\xa1\x87\xc9\xed\x84bG\x95QCR\xd1\xe9T\xfaL2\xef\xb2$r\xcb\xcc\xe5U\xf4\xe1\xa4\xbd\x1d\xdc\xeb\x0b\xdd\xbc\x9ew\xb9R\xaa\xd0\x15\x18!\xb5\x08\xa2\x1bF.\xd9v\x8d\xe2\xd2\xf8\xcb\xab\xa6#\x7fx\x90u\xce\xf5\xfd1x5\xc0h\x8c\xf6\x1b\xb1\xcb\x03KH\"\x1a\xc3\xb8\xae\x06\x0b]\xa5F\xaep\ng\xa8\xe6\x1a\xb3]*N\x89\xa2\x16+\x93Ou\x8f\xeb\xf2\xb3\xac\xcf\xb5mY\x98k\xd6\x94UG\xcdZ\x88\x9a\xb5\xc7\x98\xda\xdeJ\xbc\x7f6\x13o\x0dY~\xca\xc9r\xf8\x15d\xd9\xcc\xc8\xe8Is\x08\xa2\x86J\x9e\x0d\x03(af\x15\xab\xe5\xc6\x0d\xc5\xc6\xe5\xa2f\xe7\xc4 \xd9\x0en\xd3\xa2\xf6\x84U\xb6M\xae\x03)\xf6cy\na4\xa7\xb0\xca\x92\x02\xdfH\n\x01%I\x8a\xaa{E\xcbV:\xa6\xed\xbb\xa9a\x81\x7fS\xb4a\x9as\x01\xddqQ\x1b\xb6\xea\xc3\xb2\x0fw}\xb8\xe8\xc3y\x1f\xae\xf8e\x94\xe6\xd0~o8\xcc\xff0\x1c\xe6\xcab\x07~\x92\xd2\x90\xe6\xb2\x12\xff\xe5t\xa35\x0d1\xbfx?\xc7~~}\xa3@A\x16\x08~E\xfe\xcc9\x15^\x80jO\xd8Gc\x88u\xc1\x97-\xf8W\x11q\xad\xca\x88:\xefs~\xb5\xcc\xbe\xc1\x84\x03\x01\xd3_\xa9B\xa6\x90:\xf0\xba\xae\xfa\xf0\x85P\x84\x9d\xa2\xf1\xa5\x8b\x17\x1e\xec\x85\xd3\xfa\x19*N\x14\xe4\xa0\xee\xefq3>w\xcb\xc3\x9b\x14\xa3[q~\xec\xbb\x0c\x12\xc6\xd8\xbcn\xfdV \x832\xbfg\x83\xf4\xf3\x1b\x9cS\xf6`-6\x15\x93\xfa\xce1\"w\x0et/'i\x98\n\x80\x1d+}\xb8*\x1f5\xa5{\xc4\x1cR0\x01\xde+\xca^W\x08\x9c\x87\xdc\xb1\xf4\x0b%ob\x96\xce@X\xee\x98%4\xf6YXBr\xcf-\xcf.%Nj\x9f^[\x9f\xae\xacO\x97\x86\x0d\x08\xc2\x8eF\x97\xa7\xf2\x0b\xe4\xc7\x85PY\xb7\x93\x1f3\xa3\xe7\xbf\xf4Vn\x16'\xfbB`\xe6B\x1b\xa9\xf0\xb4\xbb\\(@\x81f\xe7\xa9\xf8~\x7f\xcfhyl\xb5\x84F\xad\x13\xd2\xc1\xb0\x0f^.\x02\x1auP\xea{\x8a\x80\xd7\xe8F\x880n\x03\xb1C'c\xfb\xdcP\xb5\x81\xbfR?l\x84;\xdc\xde\"s\xe1\xd6\xd4y\x85S\xce9F\xc2X\xf8\x94&k\xe2)\xa7\x8f\xaa[\x05td@\x0e\xfa\x8a\xdemp\xd3\xea\x84\xae \xf7\xf0\xc8\xd9\xe9\x8b \xf2\xae\xa4\xd6\x9a\x1d_(l9x\xd7\xb0\xe8\xc3\xbc\x0f\x97}\xb8\xe6w\x05n\x1f\xf7\xc6\xb5\xa0\xd2\xa2\xe8N\x109\x81\xdc\xc8|\xb2\xbf\x97\xf9\xfe\xc57$\xc1\xb7\xc3\xa5e\xf2+\xa6\x04\x88\x97vF\xe9\xba\x91Q2\xe5'a\x80\x17\xe6\xa0\xce\xba\x19\x17\xf8\x9d\xd8\xb3\xad\xbe\xd0\x83sM\xac.P\xbd\x85\xf2\xb1>G\x9b\x9caX\x1beQ\xf9a\x1d\x8e6wD\x8fC\xde\xe3?\xda8\xf4|\x01[\x15\xbb}0\x80\xa1|\xf2\x0b\xfc_[\x19\xab|\xab\xb1\xbd\xda\x06\xbc\xe2\xbe\xb0.\xbe\xf2\x9b4\x8e\xbb\x97%\xdc\xbdVp\x97\xd1\xdb\x1c\x7falR\x1b\xc7\xe6\xc3d^\xf0\x1f\x9c>\x82\x17\xadV\x04.hzC\xa9P\xf8xQ\x10P.\xc0R\xeeD\xc8H\xa3\xc7\xb6\x95H~\xc9\xc5=\x1f\xef\xd99\x9a\x88\x13a\x0dm//@F*%\xf6\xeb\x8a\xd4\xcdU\x0e\xe5\xeb\x84@\xb9N\xf0\n>%Q(h\xa9\x19\xe3\xc2\x97\x05z\x02\xf9\xe5H!\\ \x8ew\x8d\xe4Xj\x9b\xdb\xe0Qe\x04\xba\xb1/\xca$\x9f\xad1\xd2\xb8\x18\xe9\xbc\x874d\xc1]\x81'\x10\xf3{\x13\xac\xc0\x17A\xa9\xc3*\x89\nI\xb5ga\x1e\xde\nI'\xe0\xcc\x1f0G\xd6-\xd6\x1f\xb5\xd8\xb3\x0fQ\x13W\x90\xb1\xaasd-\x9d\xb3\xd1\xa2\xee\x83 \xd9<\xfdn[R]\x15T\xe7f!\xd5$\xf0y\x96g\x0b\x0c\x8a\xab}\xb4\x86Z\xfe9\xf9\xd1\xe9\x01 \xa7\xa9b\x11I\xf3\"\xba\x82\x87\x7f0\xe1\x16\xb7\x08\xa4\x15\xddntP\x04I\xa6\x95\xab.\x8f\x04$.S\xacnW\x12\\b\xf0deC\xdb\xde\xb2N\xbf.h\x89\x1bU\xe22\xfc\xdcg\xe4k\x82+-\x1a\"\xc8\x7f\x8d1\x80\x17\xc7K~=\xcd\x99\x1b\xef2Z!w\xb3B\x86\x92q-\xfe\xc2\xd7[\xe1A\xb3\xd8\x83b\x80\x83\xc4\x83\xbbI\xa0\xbc\xc8\x93ne\xb9\xb3D&\x9d%6F\xbfF\xf1`\xdf\x18\x11\xbe\x8e5\x0c^\x87\x0e1\xea\x16\xac\xe65m0D?\x0ey\xaf\x86]\x9b\xf9\xfe-\x89Y\xc6!X\xc7\x07_3FP\xc7\xd9\xb9q\x88r\xcf\xad\x19\x90aC*\x1b\xce0P\xc5\x1a\xa8j\xe4\xd37\x8d\xbe\x9d\xf2\xc4\xe9x5Y\xe9\x05;\xe4\x1e=\x92\xd6CDc=\xd4\x06b\xe6%\xebxP5{x \x0bdC\x169{\xc1\x1f\xb8}\xb8A\xd4[\xf7z_\xbc\xd9\xeb\xb3\xb3\xe3C\x82\xf3\xbe\xae\x98\xd3TLf\x02\xf4A\xe9\xc1\x1a\xc6\x8c\xb5\x1e\x8b\xb70\xc4\x88\xcc\xf1\xa8\xd8\xe2\x9c\x85M)\x0f\xecA\xed\xcd\xaa\x0fa\x11=\x01\xb6Q\x18\xc7\xb0\xca\xd9\xb8\x96\x83\xe7Zo\xf9\xe6\xc8\xfa\xe6Z\xf0\x8ccA\xed\xd60\xd1M\x17\x90\xee\xd8\xdaix^\x1e!\xb7\x16\xee\x0c%\xe9\xea\x8b\x83\xbbj\xfe\x05\xd5M\xf8\xdc\xfd\n\\e\x9f\x8fB_\xaaj`;\xa3\xb6\xa4\xd3(@W\x8ek\xc9A=P\xbc\xd53'[\xcf\xbe\xfez\x12\xdar\x0bUi!\xc6\xec\xbd\xfb\x9a\x0b\xc76\xe3\xb1\xb0\x1c[\xdc\xa0\xdf\x9a\xf2\x82\xd5\xfb(8\xf6\xd2\x821\xee\xbe\x01,e\x9e\xa5\x00\x8cE\x17\x18\x97\xe6Y\x85D\x19\n\x863\x0e\xa9\xd7\x8d\x83\xb7\xe6\xf9\xd0#1b4\xf6\xe3\xb2\xc3H\x88_u\xf0\xf2}\x94Kt\xfb\xfb\xfb%\xc3\xdfG\x8f\xb8\xf1\xe4\xc4\xca\xefK\x1f\x9f\x82\xe3O\xfcp\x19P\xf8[\x16\xb1\xaab\xedEBJ\xf3,5\x1b\xe9!b\x86\xbe\xd3o\xb1ST\x01\xc3\xb0k\xb69z\xb4P\xd3}\xfb]\x13\xa29\x85v\xd7\xb4\x18\x8fU3\"|W\xb3|\xd0Z\x8a6t\xabC2!>\xaa\xb16e\x9b-\xf6\xa2\xae\xab\x9bvW4\xae\x8a\xfd\xe6}\x98\xeb53\xee/\xca\x90\xfex\x9a\xcd\xdc\xd2\x01\xf3\x01}G\xd4I\xb6h\x11%\x9c\xd1\xa60\x83\xc3`\x93l/m\xa2+\xf1^.\xcal\xc3\x18\x9e\xee\xe4?\x99\xd80t\xe1%\xfb\xaf\xc5]Y\xc4/\xb4}n\xb4\x1d\xb1\xf7\x9eC\xb4\xb1\xe1b\xef\xaf\xda\xc2\x8a )0\xc1f\x1c\x1f^\xbc\x80m\x17z@r\x91*\xdf\x81\x97\xf4\x96\xcc\xa9\xe7\xafH`wiR?*(\x0f\x1c\xbf\x82/f\xbe\x85\xc3RR\x81\xab0\xba \x81&\x1eY\xd3\xdc\xd8\xd3\xd6u}g\xd8)iVPR\xbe\xf5M\x94\xb4\xde\xf0w\xa2\xa4\xf3(\xbbhCI+\x83i\xc1K<\x84\xb4\xeaG\xa1%\xad\x8a\x1aG\xc95o\x0e\xbd\xc6!\xad\xa7\xaa\xdb\\\x87\xd1|\xf1\xdd\x86\xaa\x1a\x1aie\xee\xc4M\xe0n\x85\xf5[\xe7\xc4\x89\x19\xd9l\xd3b}0\x0f2y\n|\x92<\xc8\xe2Ic\xfc\xd8/\x9b:)*\xf5J8\x16\xd5\x10\xf2q\x16\xe6j\x80\xb9\x18G\xc5(N9\x93T5}8\xab\xde]\xd5\xd9U\x86&_j\x8a\x82ZWO\xea[\xd9IiV\xce\x99/\xba\x19z\xdd:^3b1\x88\x9c8\x1ew\xfb\xe4D\x1a\x85\xde\xad\xa7\xc5\xf7\xedM\xa5|\xab\xf8.\x15}\xf8cW\xad\xf4L\xf9\xae\xd4\xd9\xdaS\xea+\xe5\xcfx\xa8\x07\xcf\x8a\xe5x\xe2\xec*\xdd\x0b\xb5\x99\xc7u\xf4\xb7\xcd\xdbHHg\xf7\xf7\xdc\xbe\x8f\xa1y\x8b\x8d\xd5\xcc\xaeD\xe8K^fw\x85\xd5\xba\xd8`\x9e\x95\x0b\x11\xd6\x19\xd6Dp|A\xbfh\x8a\x16\xe1YI\xaf\xb8\xb5\xd3v\x10\xf6\x01\xa0\xafL\x8b>\x9b\xb4\x12\x8dGM1G\xafY\xfb\xc8\xda\xbc\xc1\x8a\xcdV\x10Y\xaef\x91\xd74\x8a\xf1Y\x90\x17p\x95\x89rrn\x8cjw\xd4\xfb\xf6\x04o\xf2C\x14\xf9\xfd\x8b\xb5U\xe2#S:X+\xda\x839\xab\xc0\xe7\xfe\x1f\xdcx\x80\xd1'u%\xc4\xfduI\xe7\x16|{=\x8e\xbe\x14/\xc08/\xc3\xe9gg$y\x191\xde\x0d\xc8\\\xdb\xe6t\xfbp((\x9fS\xae!\x0c\xcd\x0c\xcb\xd1\xe0\xf2`:\x11\xabC\xedtr2\xc2]\x82\x05\x99Y\x94\xe8\xcb\xba\xaeQ\xe1\xacH_ZQr\xf2\xf7\x87@\xa1\xdc\xd1:\xf7f\xc9\x8d\x0d\xba\x93.\xea\xa6,u\x95\x12q\xb3[\xd8\x81\x15gur\x19e\xc1\x1cmu.\xc95\x05\x12\xdeI\xcbk\xbc\x84\x95\xfe\xde\xad\xaf\xbb\xf3{\xc5Buv\x9a\xcf\n\x8d<\x85\x8dg\xa5i1\xean\xa7[\x14\xe8\x9d\xcd\xba\x93n1S\xab&y\xc9ugw|\xed\x85\x11\xd2\xe9\xdd:OZ\xf7\x1c\x96\xf0\x02\xee\xd8\x1f\xf4\x1f\xb7\xd2\x1c\xe7\xa2\xde\xcet9s\x072\xe0\xbb2u;\x9dPp\xe2b\x90'lW]\xd3\xe4:_\xf0\x1b\xe6/\\\x82o\xbb\x7f\x05\xb1/\xb1t\xe7\xb6`T\x0b\x86N\x19\x13\xbfw\x16\xc7\xdb\x91\xf0\xf0;\x9a\x863\xa9cc\xf4\xf4\x0f\xa1q\xe0\xf44W\x82\x15hZ\xd2<\xfc\xc9\xdcy\x99\x1e\x0c\x15\xd1H\xec\xf7\xc2=\xdfN(\xdaV\xe4\xf1\x1c\xdaW\xdet\xcb\x11]D\x84\x07u\xdc\x0c D\xb3W\x13T\xd0\xadH\\\x8b\xdb\xf2[\xc1\xd3\x8bi\xa2\x9d\xc6Z1N+\x03\xa6N\xa4\x1f=\x82%w\xf0,\xaf\xbd_^{\xc8Cq\x84Q\xb8qp\xf2\xea\xed[%\x9eL\x02$\xa6\xe0\x87)\x8d\xd71E\xc7\x87\x04\xc5\xad<\xe8\x9c\\\xda\xa4\x166\xa0\x85<;\x81\xed\xddf \xbb\x82\x15h\x80\xb0RA\xf1\xa4\xdeP\xa9d]\x1f\x1a\xc5\xa8\x0b\x15\xe8Yxp\x94\xd6\xc3z\x18\xff\xd5\xd1Fa,bAQqv\xa0\xcc\xc3\xce\xc8\xa1\xe4\x17\xf2\xb8v2d\x0c-\x03\xa0\x98\x02\x82@\xc4\x92\xb1Wrhn^\xd0\x87\xdd\x9d\xcd=\x11+U}i(k\xb2r\x8e\x15#\xb7J\xfb\xaeE\xde\xe9\x90\xde4\xdf\xaca\xe6 \\B\xc0DL\xf8[F\xcfds/~\x08\x96G\xd4Id\\\xf6T~\xbd\xbfg27>,\x02Y\xb2\xe7\xc5\xafr\x13\x9c\x13\xc1*\xe2\xeb\xfd=W\xeb\xb3\xa7\x18\xa0\x8a=\x93\x91\xaa\xf2'9\xbb\x86o\xca\x1f\xe5\xb6KB\x8cL\xc2\xcd\x07\x8a\x81\xc0\xfd\x80\xce\xdf\x8a:2\x97 \xe7\xdf\x0d\x95O\xf9\xd3|\xe8\xb8v\x052\x88rE\x171\xccG\x8b\xea\x08\xf5\xa7\xd4H\xa8e\xaa!\x10O\xf7,\xf7'\xf2\x17eB\xcb\x97S\xc3\x04\x86b-\x11\x93\x86\xdd\xaev\xe5\x97s\x93t\xf2\xdc$EZ\x12_3#%$V\x11\x82-\x86\x17\x10\xb1?<\x04[\xea\xf8\xd3xf\xa7-?i7\x9c\xdc\x99\x7f\xd5\xad\x1f\x1b\xb1p\xe8\x96\xd9P4\xfb\x95\xd5\x1a\x89%\x95\xb5$X\xa7C\x8dOA\x91\xc9!r\x8a\x8b\xc3\xfc\x86>\xa7\xa0~\xa8P\xd7>\\d),\xa2\x8c\x9drQL\x1f\x94\xc9\xa1He\xf0K\xbf\x9e\xfa\xe0\xa7\xbe1kA\xd3-D\x8b5E\x94\x89\x07\xf46\xa5\xe1\xdc\xa9\x83\x8fo\xea1\x90\xf2|Xg\x95\xe5\x90\xc8\xf7\x85\x8d\xfdI\xf9\xa9M\xe3`\xa5\xccb6?}\xe9l\xea\xf1\x81\xbf>c\x81.\x98h\xe4\x94B/V\xa7\x81tL\x1c$\xf2l\xb9\xc8\x16\x0bN\xba\xeb$3,\x93\xccX\xfc\xf4\xa2 [\x85\xa5@\xa7\x05\xde))\xd8\x07K\x9a\x9e\x84\xfezM\xd3&\x00\xd7\xcc\xd5\xeb{\xb1\xa3\x0c\xd7U\x95\x06:\xd9\x1bD\x00\xf8m\x85c\xd8\xdb\x11\x11p\xc4\xadKi\xb6\xc2:\x80\x1d\xe7\x1b|?w\xcf\x86g\xf1Y\xf8\x7f\xfe\xb7\x9aU\xa0;\xf0\xc39\xbd=^8\xcah\x90\x8a\x1f\xa4N\xc4\xef/\x0c!\xab\"\xd8@2^\x06\xf2\x06\xf6\x9b\xc2\x13\xd8\xe4\x9c\x87^X\xc3q\xc3`0\x00\x1c|o\x1fv\xf4RJ\x1bw3\x04\x91/ A\xea\x90 \xf0B\xc5\x0d\x85\xbd\xfab\xd0\x10#X\x1c\"\xc8\xf8F\x052-\xa0\xe2\xabP!\x0c\xbe_\x01\x15\x81Q\x99\x84\x87\x98\x00\xe7\xea\"\xee\x8aX\x98R\x02\xaa\xa1\x84\xe4\x95\xa1\x01x\x8f\x07\xcc\xefUkAO\xb3\xe6=\xe5\xbc\xe8A\xf7\xf7\xaeJ\xa0\xd4=\x94F\x9c\xfb\xb5\xe6\xe6UB\xf6u\xbb\xda3\xbe\xd8\xfa\x8caE\x0e\xe2\xb1\x1fr\xe1\xb1x\x86\xd1\x92\x1f\xe3U9\xe3XH\xca%\x186)\xa7\xa0\x04(\xd7\xf5\xd8\xdc\x04%(\x9e\x8b\x02~\x05\x82;\x10\x85r|VP\x03G\xa8\xa8x/c\x0e5\xd4]j\xc9tNi\xbe\x92h\x8ev\x953Em\x9d\x9d\xc6\xb1\xa3 \x87\x93\xa4q\xb7_\x81\xf5\x95\x1f\xce\xc7\xc5}n\xe9Y\xae\x90\x1d7\x98w\xd4t\x9e\x98D\xa2\x94\x8b\x00\xca\x07\xbb\xfb/\x82\x00\xfd\x9b\x11\x02\xb9c\xde\xb7\x85A\x95\xb9\xfe\x97\xc3`E\xd6&\x18\xe4\x8e\xb6\xdf\x16\x04\x15\xd7\xd0\x7f=\x08\xd8\x08\x1f\xb4\x13\xc4\xedA\x13\x00|\x19\xbe\x07Ek\xabm\xf0u\x9e\x8cR\xc8\x01&h\xca\x98\x9d\x8f\x1eA\xf7\x7f\xc4\xcd\x1d\xf2\x02E\xb9\xd3\xc5 \x15\xcf\xbaG\xd5\xdf\x9f\xde\xbd\x13\xbf+\xbcv\xf3R7\xac\xb4\xad\xb9uL1\x10Y#\xe0T\xcc\xc1Q\xdaZ\x8d\xe9:\xa6 \x0d\xd3\xb1\xa6%\x8f\x84Q\xe8{$h\x98\x01\x14\xbdv\xffG\x93J\xb3~5\x12D74\xf6HB\x1f\xd02\xaeK\x9b\xc6\xb3\xf5\xfa\xc1\x8d\xe3\xa2\xb6i\xdc#+\x1a<\xb4q\xfd\xc8m\xeb2\xa7\x0b\x92\x05\xe9Iz\x17\xd01tsxu\xff\xe5\xfb\xfd\"\x8a\xfe\xa9\xfb]c?\xd5z\xbf\x97\xf6u\x1agT\xdd\xc7\xa7\xd5\xdf\x1f?\x1d\xca}\xcd\nv\xd4\x97\x17$HJ\xb5\xdf\xd4\n\x0e\xde\x9d\x1c~)]\xb0m\xe4\x87\x0c\xfc[\x12\x90\xeeT\xa4\x13\xf81\x8a\x02J\xc2\x19\xef\xa3\x96\x9cN\xb2\xa12\x03\xed\x17\x93\x1b\x1dQ0&\xc8\x95\xf6\xa00\x91\x00\x1a\x83X\xa56\xdbXG#Z\xf5\xc5\x81=\x96\xeb\xdd\xa6/\x1d\xc9h\xd7\x97\x9c\xd7\x1b\xc3\xbc\xfe\x1d(\x88)C\xe2\xee\x03\x93\x9c\xd6\xb2\xa7\xed\x14\x03\xd54D\xda7\xb4\xa74$\xbfUI]\xa4#u~\x98\xfe;P:\xae\xb4Q5\xd8Z\xcc\x89\xccn\xf5\xba\xa8\xde \x95'q\xa3ylw\x83\x1bB\xf1[\xd4i4C\x19\xad\xdb\x13y\xdesY\x8eN{\xbdh\xe6\xf6\xa1;\x14\x99\xfe\x8d\xe29j=z\x82!\x8b\x1b=\xbfp\x14\x17\xbcQ\xb5+S\xfb\x90\xbby\xf4z\xa4\x9fb\xe6\xb7\x959\x8ev\xddA\x1a}b\x02\xe9+\x92PG@\xa2\xb1\x9a\x0526\x1c\xab\xc8\x85b*\x15I&aO\x0f\x02\x9f$4\xb1\xe1\xe2t\xb3\x0f\xdd\x0b?\xecjR \xe4\x98>\xedC7\xf2R]\x95\x1c\x8e\xd3\xd1\x10\x13Uy\xbaZ%\x88OG\xbb}\xe8^\xd2\xdb\xee\xf7\xbd\x0b0\x8b\xb5\xe5b_\x08\x90\x1f\xe9\xf2\xf0v\xedt\x7fw&\xe3\xe9Fo6q&\xe3\xe1\xfdt\xb4\xf1l\xc6\x8e\xd8\xf3\xd9\x0f\xae3\x19\x9f\x9d\x0d\xe4/VaJ\x0fgXY\xa4\xc4\x9d\xdc\xe7\x15z\xda\xc7\xc5/\xd1\x8c3\x19\x97\x0f\xf2\xa2\x07^\xf9\xecl\xe0L\xc6~\xb8\xb8\x7f\xcb\xfe\x1d\xbdq\xefyQH\xc2\xfb#rt\x7ftp\xe4\xba\x7fV-\xef1.?&\xedU:\xa7O\xcczB\xad\xf0\xbc\x08\"\xf2]\xc4gU\xbf\xcdoF\x18\xa5u:\xbe\xe0`\\\x95\xf9\xa1S\xd5zo\xf6\xcdy\x1am@\x189B\xd8\x07\xc9G\x08\x03\xe4\x1a;2H\xa3w\xd1\x8d\xdc\xd2\x8c\x97\x80 ;\xc8\xc7 b\x00Og}\xe8\xf66\x94+tdX^\x8a\x13\x86\xdf\xa1\x16\xccH\x1fX\xcdE\xc1{\x08\x0b$\x98\x88\xc3l\xf0\xe1\xf8\xe4\xed\xe9\xdb_\x0f\xcf\xdf\x1e\xbdy{\xf4\xf6\xf4\xaf0\x96\x8f\x8e\x0e\x7f:\xa8>\xea\x0eB\x12\x16\xcd\x1d\x91#\x18CZf1\x04is\xd2/\xe33\xa22\x9f\xf1\x86!\x8e\x95\xd3\x10\xb6w1\xe74\xa2\x07t\x95JN#f\xaf\x9b9\x8d\x10~`|\xf3\x18\xbf(\xa3J\xff\x9dx\x0d\x873\x1b\x9d}\xee\x8d\xa1\xe15\xda2\x1b%Bi\xc2\xf8P\xaf\x1c\xf2\x93#r\xc4\xfa\x82\xe4\xc6O\xbdKp\x8c\xca\x03\x8f$T\xd5D\x8e\xb5\xb5@\x01\x0e\"\x9f^<\xe2\x8d\xe5z\xdc6\x8d\x1d\x1d\x1cY\x1b\xcb\x15\xb5\xad\x1a#G\x1a\x8dl\xe1\xf8l\xdcnB\xeb\xf7=\xa0\xc5v\xfe7\x83\xd6\xdb\xa37\xdf\x0eZo\xc3E\x1bh\xd5)\xd0\xf7\x83\xd6\xc67\x05\xd7\xc67\x85\xd7F#\xc0t\xbb\xbdx}8\x18j\xc6\xa2\x9cKe\xbe\xb7\x0f$\xcf\xe95\x810?\xa6\xba\xb4\xcb\x0e\x14\x1e\x083\xb4\x11\x93\x7f\xd6mC\x8d\xff\x8aj\xfcW\xce\x1e)\xff\xb9\x1b\x8e\xe9\xc7\x9f\xbb\x8d\x1c]c\x8b\x93\xca/\xc6\xbb\x9d\xa6\xb3\xfb)\x9c\x9d\xa5\xb3\x9e[z8V{/\xfd\xe0\x0c\"/\xf9\xc1\xe5\x1c\"\xb6\xf0\x83\xf3\xdf\xf7\x0ec\xc6\xdcj7\xa5\xf7\xdd\x89\xebNJ\xac\\\xab\x1b\xdd\xd4_\xd1$%+\xa3)\xcb7\xe7\xd6\x8a\xb0\xe5\xd1\x80\xdeRO0my\xa9/K\xbf\x03\xbf\xa6\x89\x87b\xb85Y\x0b\xf7L\xfd\xb9\x97\xdf\xe0 \x0b\x96\xcf\xc3\xcd\xb9\xb2b\x12j\x9erW1\xf3>\x8c\xe3(v\xba\xafIJs\x9fZ\xca\xcat\xc1\x99|\x91W\xb4\x97NG3\xce\xfc\xf4\xd2\xe9\xe6\x8c{-\x11\xfesk\xd6\x87N:\xdd\x9e\x15f\xb0\xf4\x06X\x07\x0e\xfbo\xf0\xe9\xf4\x95#\xc0\xa0\xf3\xc3\xf3E\x98\x8a\x1ek\x82G\xa9\xe8\xa5\xd3\x9d\x19\x8fO\xd1K\xa7\xbb\xb3>\xa4\xd3\xbd\x99\x89\n\xa3\xca\x15\x03\xdfN\xf7f\x82+\x1d\xf6a\xcb}\x0e\x8b\xc2\xa7r\xeb\xb9\x0b\x0b4\xf0\xd3Q)l\x87u\xb7\xa8\xd3?\x13z\xa5\xd3g3\x04<[\xb3]\xba\x0d?\x80\xb3;\x84\x1f\x10Z\xc3\x19\xf4\xa0\xe7\xa4\xd3\xd1h\xc6\xd0l(\x95\x80\xb8 \xea\x9b\x1bkW\xc4g0\x82M\xc1\x9e\x85\x8bQ\xd5\x1f=\x02o\x90\xd0\xf4\xd4_Q\xc7\x1b,\xc57\x1760\x88\xa6gCa?LR\x12z\xf4x1\xc6\xeeZph\x96M\xc6\x88\xfa\xdb\x93cA\xd7\x8d\x8e\x00\xdf\x8a\x10?\x90\xcc\xf0\x04\xfc\xdf\x8f\xc4t_\xbcP\xac\"L\xe6O\xdf\x0e\x0c\xc5\xcf4\xbe\xab\x0c\x8b\xc3hg\xdb\x1d\xfc\x88\xb6\xc2E\xaf\xe0\x11dd\xd8L>\x97\x1a\xb4(\x18\xba\x07?\xbez}\xf8\xe6\xa7\x9f\xdf\xfe\xe5\x97w\xef\x8f\x8e?\xfc\xd7\xc7\x93\xd3O\xbf\xfe\xf6\xbf\xfe\xfa\xdf\xe4\xc2\x9b\xd3\xc5\xf2\xd2\xff\xe3*X\x85\xd1\xfaoq\x92f\xd77\xb7w\x7f\x1f\x8e6\xb7\xb6wv\xf7\x9e>\xeb=\xd9?\x0b\xcf\xe2\xee\x03%x\xae\xe4\xf9\x1e+\xf6\xc57\xe0\x06J\x1d5^\x8e3\xfa\xe8\x1b\xae\x88B\x1e\x030\xe4\xbeC\xa1\xed\x9e\xa8\xe3 i'\xb9\xfcK\xa5\x19;\x8f\x06\x08\xbb\xdb\x8d7G)\xbc\x80a\xab\xdb\x1f\xd4\x8b\xefj\x1f\x1b)a\x0c\xff\x01OQ\x01]\xc6\xfb\xaf>:\xa3\xb2\x02cz\x16\x9f\x85\xfb3\xa1\xc60\x03=\xb2.K\x86\x91\x80\xb4\x8f\x12\xf3r\x07\x86;\xa1\xdc\xd3{\xf8\x1c\x18\x94\xc9sH{=\x17R\xf8\x0f4\x05\xe3*\x13~\xa5\x13\x88L\x11\xf0\xf2%\x8cv\xe1\x11l\xee\xec\xb8}P\x8b\x9fVK7wv\xe0\x11$\x8c\xec'\x98\x0e\xe4\xc5\x0b\xd8\x85{\xc8rt\x88$:\xa4\xba\xe3U,\xd1\x10dH\\\x82\x03\xfb\x01v\xf1\x9a\xe6\xab\x86\x04c\x18=\xcdu=\xe5\xb6\x86\xda\xb66E)\xbe*|\x0f\x19h\xd4:\xdb\xf9\x9b1\xa6\xdfX\xc4\xd1*\xff\xe2\x04(\x16 \xbd\xc7\xaf\xdf\xd4~\x15C|0)\x87S\xd0\xf67'm\x11:\xe6n.F\x82b@>\xd2Hk2\x0b\xad1`\xe7V\x05;q\xe7g\xd3\x08\x97\x8f-\xfa\xee\x16\xf2|J\xe9\xa6\xaet\xb7R\xb8\xbb\x05\x8f\x00Mr\xd8\x8c\x9c\x88a\xecS\x17z@\xa7\xa9\xf9R\xb5\x8c\xa0[\xfc\x0e\xf1\x1b\x8f\x08\xc6\xb0Y\xa0k\xa9\x9d\xa1\xae\x9d\xedZ\xe1\x8b\x17P\xedqw\x1b\x1b\x1e\x15\xc8\\j\xb9>\xc0\x17/j\x0d\xefn\x97\xdb\xebC\\F\xbc\xfc\xd7Ws\x10f\x89\xb6\xa6\xff+\x87\x9c\xacs\x08F\x85\xe1\x03\x99\xb4\xc8\xe2\xd1`\xf0\xea\xf8\xca3\xdfd\xcf_\x91\xd7\xb8*\xdcx\x1cP\xdb~\xe3\x97\xd2A\xee%\xccv_\xf8\x9c+\x83\xcd\x1ed\"uh0MgE>\xb0\\]\xcb\x01>\xeb\ny\x15\xd5\xb2q\xb3Q\x87\x88\x89\xe3\x87\x10\xdb\xadx\"\xd1$Jj\x16\x8eB\xd6\xcf\x1a\xbb\x96\x9f/\xb2\xd6A\xe6\xa7\xb9\x0fVM\x98!$\xf9\xa1H\x9a\xc1\"\"[\xb4\xca\xdf\x91#Ny[~!\x83S\xd7O\xfc\xb3\\\x8dZ\xec\xfa/\xdc\xc4k\xe2\xc7\xc9\xbf\xd7.\x16\xbe\xbb\x96\x9dJ\xc4\x8c\x0e\xe2\x98\xdc9\x99t\x81\xcco{\xd8\x16\xce\xbel\x0bg\xb8\x85\xf5[7j\xbdu}\xf4\xe7G\xc3!\x85\xe2^\xd1\xbb\x84\xbd]u\xf17\xb5B\xa6\xe9\x8c\xd12\x7f:d\xe7\x0c\xfe\x9d\xcd\xfe\xe9hoXG\x1dW}]\x0d{&R\xd1\x18\xd6\xd1/\xad#\xd1\xae#1\xad#[-\x82\xab\x15\xd5@\xdc\x07_\xc0.\x12\xb0\x8b\x10vF6\xc6\xff7\xd8\xc1\xe5s\xfb\x81\xfb8\xa1\xc6\x0bt\xbdw\xe1\xf7\xdb\xc4\xd6#\xd6\x0f\xc1\x10\x08L9\xc9\xc2\xbe\xb0D\xccIm8Mg\xd6\xfd\xf2mQ\xdeD\xe9\xff\xed<*\xffH\x9ed\xe1\x9c.\xfc\x90\xce\xbfR\xfbb\x81\xc3\xc3\xa1\xea\xd6\xf2\xcd?T\xa6\xbb\x8e\xfc\xb9\x8c/f\xeb]'\xcd\xd94\x7f\xffn\xae\xd1\x7f$Ob\xba\xa4\xb7\xdf\xe5F\xe5\x01\xca3\x1f\x03\xd5`\xbd6\xe7S\xeeW\xa7\xe7\xb3\x19\x11xr\xf6\xc4\x99.\xfd\xd5\xec\x07\xf7\xcfO\xe4\x05\x87\xbez\xac 9\x00\xd2z\xfa\x89\xd4\xbe\x0f\x8dw \xfc\xc2C\x9a\xf2\x86\xd3\x11\xcab\xf2\x16\xe1%\x93K[\x9c\xd8\xac'4\xeb\x9d\xa6\x85!P\\\xb2 *\x9a\xa9\xb5\xf2\xbd\x8f\xe1\x7f\x0e\xc4\xe56Q\x80\xceo\xe1\xaa\xd0-\x19\x13\xf5\xc1\x001\xbc\xd0*.H\xd3~U\x96\xf9J*\x913j\xbc\x83\xb6&1\x0f%(\xd6\x05a\xb0\xea\x01\x1d$Q\x16{\x14z\xac\xc0\x08X:X\x06\xd1\x05 \xc4\xd5_o\x1f\xbaK\x1e\xb9\xaf\xc8D_\x11\xf5\x9fV\xca3\x9b\xd2\xaf\\5i\xd6.\x94_\x08`\x1f\x9eU\xc8 \xec\xc3\xa8r\xad\xb5\x80}\xd8\xda\xac`\x03+\xdb*\x97\xcdY\xd9v\xb9\xec\x92\x95\xed\x94\xcb\xaeY\xd9^\xb9l\xc5\xca\x9e\x96\xcb\x96\xac\xac2\xbe;\xd8\x87\xed\xcaX.XY\xa5\xdfsVV\xe9\xf7\x06\xf6a\xa7\xd2\xc7!\xec\xc3n\xa5\xbd[VV\x99\xdb +\xab\xf4\xf1\x8a\x81\xaf\xe2\x93x\xc5\xca*\xef\x1e\xb0\xb2\xddr\xd91\xe6/\xacT\xfc\x80\x85\x95^N\xb1\xb02\x95\xf7\xb0\xafA\xfa\xe1\x18\xbaggC\xcdQ\xb4\x87O\x88\xe6\xc9S|r\xa1y\xf2\x0c\x9f\xa4\x9a'#\xdeQ\xa8{4\xc2G\xd7\xbaG\x9b\xf8h\xa1{\xb4\x85\x8f\xaa\x0c\x1d\xfbl\xf2\xa1Wu\xd1\xec\xb3\xb5=\x86\xc7gg\xdd\xc7\x9a\xb1\xf3\xbe\xce\xce\xb4\x9d\xf1\xde\x8et\xcfv\xf9\xd4\xceu\x90\xda\xdc\xe2\xad\xbe\xd3?\xe4\xad~\xa8(\x1a\xcaU\xdf\xb2\xf3\xba{\xd7\xedC\xf7\xaf\xec\xbf;\x9a\xe0w\xf1\xe7\xf0\x84\xfdA\xb6\xb7{\xcc\xff?b\xff\xe3W\xfe-\xc2\xaf\xfc\xffc\xac\xbdX`E\xf1\xe7\xcd\x9b\xeeL\x17U\xe3\x8f:\x9d,\xb4\xb6\x95\xabhn\x82\xb2ou-\xeb\xf3\xc8\x19\x9b;;.\xe7\x85n\xbb<\x80\xeff\xb9\xad\xdc\x1a\x19\xab\xef\xee\xecl\xc9\x172\xf1\xc2\xb6\xe6\x05=\xd7\xde\xe1\x8dlo>\xdb~\xb6\xbb\xb7\xf9l\xc7u\xcb\x11q\xbdhNa\x1d\xf9\xa5\x8c\xb9<\x00\xe2\x8a\xdc\xc9L\x0c\xcb\x98\x92\x94\xc6<\x19\xc3\xf0\xf6\x8d\xf8\xe8X\x07\x1c\xe8'1\xd0\xa7\xe5\x95-\xfd\x92\x87\xde\xd9YW\x84u,\xe28\x0e\xf1\xfd\x8d\\Vv\xa1\xa7\x08p\xba\xc8%G\xf5\xc5R\xa2X\xf3x\xe1y\x98n_\x06\xc9\x961\xa7\xdf\x93\xf4r\xb0\"\xb7\x0e\xa6\x0c\x17\xc5\xf7\xf7\xb0\xe9\xcah\xdfW\xfe\xfamxM\x02\x7f\xce\xdbR~\xab\xa1\xb9\x17At\xf3\x8e^\xd3\x00\x99X?9\x8a\x18L\x97\x0e-\x9e\xb8\xd2\x17I)\x93\xbd\xa4w\x81\x08\xc1]:YMLu=%p\x93Ym\xe1\xdb\xff\x8f\xcf\x06\xcds(\x12\xa2pk\x0d\x9e\x845\xae\xdc\x1b\xa4\xf9\xd5\x0c\x8f\x04\xe0?\xe7ARG\x90\x89\x86X?\xac=\x91\xe4!\x18\xa8>\x97}\xc8xg\x19^\\\xab\x8f\xa6\x19\x1b_8%3\xd8\xaf\x06\xc3\x05E\xcd]\xc6gGA1\x868\xd8b\"\x0d%s\xdc\x89\xe2\xf4\x17z\xc7\xb3\xcf\xe4?\xca\x01\xddC\xfa\x9b?\x97\x01\xd5\xf3_\xf7\xf7\xf0T\x86C\x0f\xa3\x8ft\xc1\xdb\x10_\xd5\x16\xc2\xe8U\xb4Z\x93\xf4=\xdb\xce\xbc\x8eR\xa0\xd6\xf4\"\x86\xdd\xe8zu#@\xa9\x14\xa85\xbf \x84\xbcLOd{\xe5\xf0\xb6\x1cu\x1e\xd3`\x85E\xe4\xfaR\xb6F,\x99g\xec\x0d\x92Ra\xaf\xc0K\xb3\x84\xce_\xabOJ\xb1\xfet4\xe2\xa3v3!\xd2\x8b\xdd\x14\xc1~%\x9al\xea\x8at\xc6\xfc~nc\xc4\xf1\x9a\x8d-Q\x83\xa5\x81\x0f/ y\xeeb\xda\x064`\x97\xd9\xfa\x85K\x1f;\xfb\xc1w\xd1\xec\x87\xfb\x8a\x88\xac\x16\xa2\x83\x04\xb3\xbd\x95\x9e\xb0.ydW\x1f\xad\x86\xf8\xf7P\xd5C\x9c Q0\x14x\xdd\xdb\x87\xc8eC\xec\xedW]\xcb\x04\ngV\x10\xbd\xb6\x85\xe3\xd6\x87\xdb\x95\xe4\xf2\x07H]k\xdb\xef\xea$Z\xca\x1c\x08\xb1\x05\xc3>\xfe\xd5\xbe\x8e\x9f\x8c\x0dmm\x96\xa3T\x8d6wQ~\xdf\x1dU\xc3`m>\xdba\xbf\x18\x87RxP0\x96D\xfc\xba\xbf\x87\x9d\xbd\xad\xed\xed\xf2{\xec0\xdeb\xbfx~\x8a\xbc*+\xdf\xadt=\x1am\x8fF#\xebD\xfef\x9c\x08N\xb1\xd2\x0f\xb6\xcc\xbe^\x14__\x15_\xaf\x8a\xaf\xc7\xc5\xd7\xd3\xe2\xebM\xf1\xf5\xd2:\xac7\xc6a=\xf9\xfd,\xfc\x01dT\x13u\xb9\xe57\xb6\x91\xfe^\x0f<\xf2#cs\xcaE\xbf2Y\xa5\\\xf43\xe3m\xcaE\xbf\x01\x06\x99\xae\x0f\xf2/\xf6\xd0\xebl\x1c\xbej\xe7\xd4\xd1\x84B \x0c\xe5\x0b\xdc\xe9<\xeeG\xfd\xe9{N\x07j\xe5\x8cS\xfd$\x12\x92\x96r\x96TV\x12\x83\xf3t\xde9\xfc0\xca\xb0\xec\xbc\xf8z[|\xbd)\xbe^\x14__\x15_\xaf\x8a\xaf\xc7\xc5\xd7\xd3\xe2\xebe\xf1uU|\xbd+\xbe\xae\x8b\xaf\x1f\x8a\xaf\x87\xc5\xd7e\xf1u^|\xbd.\xbe\x9e\x14_\x0f\xc4\xcc\xcc\x89^49\x1f\xd2\xbaJ(7y\x18r\xba\xaaP\xd9^\xcfv\xb3\xd5\xf9$\xc8\xae\xd2\xbf\xafD\x05\xfaM\xaf\x04f+\xf7\x96\x8d\xfdoZc)\x13\x83\xfd\xc5\xc3\xd4\x0e\x12 \x9f\xe7rd\x1d\xf6a\x01hQ\xcdX\x15\xe4Ya\x03\xde\xe3\xe9\xf2\x92[\xf1vA$\xd2\x9c\xbeg'\xc3\xac\x8f\x88\xe9\x1b\xf4\xdc\xb9P\xc1@\xf4\xb5\x00\xd1n$\x1c%\x0e\xbaq\xa8\x7f2\xb7&\xc6\x85\xdcM\x00\x13\x08\xe1%<\x83\"\xed\xd2o0\xc6\xf2\x9fa\x0c\xbf\xc2\x98\x8f\xb2\x13\xf1\x87\x7f\x871\xfch%m\x7fU\xa8Fu\x85\xe8`\x9e\xadJ\xbc\xb7\xe9.\x84\xdf\xfe\xa6\xd5\xdb\xdf\xee\xe3\xc7\x86\x9b\xd9N\x85!\xe3\xa1\xfd\x19H\xde\x16!\x08\x14W\xd3\xc7\x18\xa0\x1dz\xec\x9b\xfeF\xd9\xcf\xb9\x0b;\xe9\x94\xfc\x17'\xed\xf3$\xc6\xbeH\xdeL\x14\x85\xa3\xd1eY\x80\xb0Q~\x92\x1f)G\xe97\x02\x94\xdcYd\xc0H}\xa6\xd9\x90\x87D\xe3\xd9\x82\xccv\xa8 p\xa2\x9ah6\x9c\xe5\x19H\x15T0\xc5n\x04\xeb\xbd\x0d@\x9e$\xa9\xbe{\x8d\x96\xaf\xe8Q\xfd\xf7F?jM\x06{\x90o\xff\xd8\xf8\xb6\xc0\xed\xc2\xe7\xe51z\xbb<~\xdcuM\xf8\x0e\xb2\xf5_\x9b[\xbfg\xad\xff\xc2\xf3\x04r\xbca\xcd\xfe\xe4|dE\xbe)M\"\xb6\xfess\xeb/\x8d\xad\xb7\xc67(\xcb\xee\xb0\x0fO\x9c\xb3\xb0\xe7:\xd3\xdf\xcf\xc2\xd9\x0f\xee\x93\xa5~W\xa9\x1f\x94\xc9\xb3\x9a|\xe1r\xd9DP\x96\x0c&\x90\xa1\x9aA\xb8U@4\x08H\x92\xbeeo\xf0\xfc\xe0\x7f\xce#\xd3\x0d\xfb\x98\x7f;u\x0d{Z\xfd\xa0\xa8~\x16\xcaP0Ct\xffd$^\xfe6c,\x88\xc9k$l\xf5#b\x0c\xc6\xaa\x0b\xb01\xc1\xa7\xfaam'\xc0\xc3\xbc5O\x04\xc4\xc9\x15O7\x1b\xc6\x0cyJ\x18>\xcb\x00o\x80|\xb6\xd3\x13\xe81Y\x0f\x13\xdc38\x88\n0a_\xc7<\x9f\x1d\xf4\xe0\xcfN\xc0\x85I\xbc\xb5\xb0vf\x8ey \x05*\xfa\xc6J\x9f\x19z\x12\xb7 \xdb\x7fk\xc4\xf6\xc7\x98\xac\xa4\xf9~O~rA\xba\xe0\xca\x85\xa4l\xe4\x91\x84\xce\xb4\xc2\x08\xbd\xe4\x02\xda.\xa0\xe7\x0e\x13\xd7v\xb7F\xc8\x04\xd4\x83\x95\xfa(\x15\xf3wv\xb76\x87PD.\xdd\xda\xdeb\xc26*\xa6\xfepF\xc3Mt`Na\x83\xb7\xce\x93\xc9l\x88\xd7z\\\x86c`c\xbc\xdb\x98\xeb\xbc\xde\x0b\xab\xd9\xde>t\x90\x93\xf9\xe4`Zh:\xf5g0\xe6\xa7\xdc\x1fz\xb74\xf5#\xafSmk\xe6\xf2\x8c\xa2\xfa\x86D \x08\xf3\x92\x95t\xba\xfej\x1d%\x89\x7f\x11\x08\xc7\xf71\xf8BU\xc9\x8d@x \xb2n\x13c\xf7\xd9\xb1\xcb\xf3\xbf\x983K\xc1\xbe\xe4\xd7\xa4\x02\x10\xe3\xafin\x01\xe221)\xc5\x95\xd2\xea/B\xb6\xdfx\x8em\xfd{\x9b\x9c\x1e\xe5\xcf\xd8(\xba\xbd..\x97\xdc\x94\x1b\xfc\xb09\x0b\xbb\xd6\x19\xfed\x14\x84MCf\xb8Q\x90\xd4\x8d\x11\xa6\xf7\xb4\xf6\xf1g-\x14\xd1\x1aAq\xbcV\xc9k\xce\x1bTl\x87UE\x96\xe2CY+:\xae2\x90\x85*\x9d\xc0\x0b\x08\xd8\x1f=\x07\x89\xa2\xa3\xe31)oJf\xee\xa0\x88s\xc0P\xc4\x1b\xe4\xf6\x06\\\xcb\xdd\xf1*5\xba\xdc\xbc\x80aR\x9e9\x90\xd3XY/Z\x80\xfaR\xdeN\xder\xa5#F\xfal\x82.\x95\xea]\x98\x80\x87\xdf\xc7\xd0\x9dt\xfb\xe0\x0dr\xbb\x04\xdb\xb1\xc2\xdaXp\x95\xa8\xb8\x1a\x99b33>\x0e5>N\xdfh>\x91\xf1\xbb\x00\xb5K\xee\x13\xa1\x94\xb03sa\xa1\xe2\x06\x0d\x80\xfaA9/\xa9\xf5\x85\x11-\xca\xf4\x99'\xe8\xf7D\x82\xfe\xc7/1k\xbf\xe0\xfdc \x9eG\xd7i\x82Wo\xfc\x04\xe6i\xc2\x10\x02\x8f\x9bN\x9a\xf2\xb4\xa6\x8b\x19\x9f\x99\xf9\xe41OY\x8a\xc3\xb1\xb6\x8a5\xfe\xb4\xc6&K+\xe6w\xec\xfa\xd1\xffU\xd2\xf1\xf1M_\x95\xd9\xd5\xfb\x83|\xc8a\x9fo\xe5\xb0\x0f\x9d\x11F\xc1\xc9\x7f\x0e5\xd9\x82\x13\xc8\xb1\x847Q\xcd\xdb\x9a\x13?U\xa4}\xc1#\xc4\x95\xa5\xdcjVS\xd6|\xd0\x87E\x1f\xed?\xea\xdeR\x0cAQ\xd9\x91?B\x17\x1f\xf9\xa4\xae.C\x85\x9d\xa3h(\xc5\x8dXqI\x92\xcb\x04\xa1\x8b7f\x85o\x06\x02\xeb\xd1#\xb6\x05\x95\x02T\xdb\xdc\xdf\x83P\x84K\xa5\x02\x12\x86\x97 R.\xfb\xa8*u\x85Z\x8aVn_\xa6\xc1\xcc-\xa0\xdf\xfd!\xa6\x8bs\x86\xe3\x15\xf1\xderQ\x8d\xd3\xc2\xb6;\x9a\xc6q\x08\xba\xf2}\x9eR\xdc\x00W\x97\xaf\x1c\xcf*\xab\xde_\x8aU\x96\xc7\xcd\x04\x9cN\xcd\x96I\xa3!\x92\x9f\xb2r\xb9\xaf.\xb0\xc5\xa2\x95\xdf\x1c\xa7\xc4\"\xe0]V\xeeYM\xb9\xf1\x91\xd6H\x1f\x04y\xa5\xe8\xc2%~w\x9aT\x80J\x0e\xd9\xe2$\xd0\xb4\xa3\x145\xb4\xa8\xbe\\\"u\xf9u\xe7*K\xd0\x92\x80\xc0\x05O|\xc3\x13\x98\xdb\x8c\x10\xa1\xa4b\xe5,\xc4e\xe9\xbe\x8d<\xe72\xd8\xc8E\x95=\x135\xc4\x823\xc8\xf8\x0c\xa9\x1d\x0c\x89$\xae\xb5D\x88\x89p\xca\x18\x9c\xcb\xa9?\x9b\xf5\x05\x8d\xe1\x96\x80\x19O\xcb\xce\xffq\xbc\xc7\xdd\xd5b\x07 \xe4\xc7\xbd\xc1\xbe\x15\x1e\x15L\xf0\x90\x89\xe0e\x1dO,\x1d\xd6,\xe77\x9f\x88 N\x13\xc6\xa8\x8a\xaf\xd0\xc5\x8d\xd7\x93\xaf0\x0e\x83S\x81\xd2\xdc\xd4\xa9$|\x1a\xc1\x17\xf4<.z\x1eC\x97\xe1uo_\xed\xdd$\xedHZk\xa2\xee\x89}&g\xe4K\xda\xe2\x14t\xe4QNG\x90\xc9\xe3\x9d3\xd9\xac\xbe[m[\xb5b#\x914\xec\xd3\xa0y\x9fz-\xf7i5\xa7\xb6\x97\xa3o%\xa7vV\xbf\x8a\x9f\xa0\x00\x8eR\x93\xa0`\xfc\x18\xc2\xbb\xddn\x1fq\x02\x95 S\xb6?\xbci\\`3N\xb63\xe2\x87_\x01\xd22N*\x8dq\x04\xcb\x8a%f2\x96q8\xc8x\xa3eF\xbd\x0e\x17\xaf\xb099\x14R\x1e\n\xb2\xe6Y{lR\x8f\xf5\xee?X\xaf \xeb\xbf\x11\xa3\x9a\xd0\xa9\x0b]\x05\xa9\xeac(\xa8\xa5\xf6`.\x1d-e\xf0~\xc9iRx\x00\xdb03\x93\x98i\xc16\xc5l'4\xd9\xe8\xa8\x84\"D[\x1d\x95\xe4)$4B\x12J\xcad\xa6%1\xc1\xb7\xba\x1b\x0c!\xc4W\x9e5\xb8Xy\xfb\xc2g\xca\xc2\x13\xce!\xcd\x9a\x16\xfd\x9fAF\x1a\xd6\x88\xb4X#\x85\"\x84&\x8a\x90\xf3\xbe\xd3xV\xdeA*1\xf091h\xd8\x8c\xae\xd0U\xb6\x82;Q7\xdc\xb4+S-7\xc2\xbe \xf0\xad6\x9cY\x94\xcc\xb7!\xd7(\x89@\x03I\x93\xf4X2\xd5k\xf4m\x84\xaa*-\x0b\xb98F.\x02\x8a\x9eT\x10-\x801/|,i\x048W$Kz!K/'\x95\xf9\x87G\x8f\xf8\xc5\xa4DbT\xe0\xd6\xc1]+i\xe2K\xca\xab\xc1\xc5N*\xc4\xce\xeeKu=\xfed\xee\xa8.\xd2\xe9D\xb5\xff2+\x03sm\x94.\xd4\x8c\xce\x1d\x87\xc7\xbb\x94-\xa3\xfb\x97\x89~*\xb4\xb3\xbe\xa2\xb9\xe5c'O \xa6\xd1\x80\x98}\xec7\x94\xc0\x14\xa1zO[Xy\x15ia|\xdc\x9c1\xf7ui\xbc\x85\x0fy\xbd\xd4\xed\xf3ce\xe0'<\xb4C\xaa\x89\xce.?Uf851\xc3\xd4I\xa7\xfeL@\xcd<\x12{G\xd5X\x11\x15K\xb8\xc8\xd6y\xc4y\xeb\xb0\xee\xc4\xca\xd0$\xe2dZ\xb9R\xf5\x0d\x97\xa8\x90\xaar-\x82,\x9a\xfa\xd3p6\xabL+\xd5\x98\x03\xe6\xe12b\xbb\xd2\x8fR\xab\"\x9b\xb5s\xc43\x02\xb0S\xe8\x1fUOB\xa9\x97V\xcc2q3\x84\xc8\x03\x85}6GZ\x9c\xb0\x13\x08%\x8b\x85\xda\xcbR\x0e\xf2b\xe7\xe5n\x9fr\xfbR\xaadh\x1f$dA_W\xac\x15,\x96{|\x8a\xf1\x80\xde\xa64\x9c;\xf5}\xc4m4\xc7@\xca\xab\x85'~et_\xe4\xf6\xa3z\xb1Z\x07,\x0d\xe9\xd5\xac\x07x\xd9\xd6q(\xecC\x8f\x9aC\xcaX\xa3\x99\xf3h\xe1\x97i\xba\xd6\x04\n\xe7\x0fo\x12C\x0cq\xd1\xdfS\xc1\xec\xd57T\xd1\xb8\xae \xd9zC\xf3\xdb\xdb[\xf6\xf6\x17\xda\xb1+-l\x8e\xec\x0d,\xa3\xf5%\x8d\xedm\xec5Lr\xe1\x07\xa6P\xebzs\x04\xeda\":\xf9\x16\x98%\x1d\xca\x1a\x83\xc4\xd47~d\xbc\xde\x99S/\x9a\xd3O\x1f\xdf\xbe\x8aV\xeb(\xa4a\xea(Q:\xcfzh\xb2\xc0\x18+\xcd\xceM\x07\xdc\x7f\xc2_\xdc5!{NT\xaa\xf1\x05$\xed\xd1\x9e\x8c\xdcQ\xdc\x0f\xa1\xcb;R\x9d\xcd\xf95\x0dZOO\xd0#\xde\x85X(6\xd1H\xf2\xd1#\x10G\x0f\x0dkS\x8cP\xb2\xdbG\xb6\xa0\xfe\x94'\xf03\xd0\xbe\\\xf4I\xd1O\xf2\x8f\xc8\x0f\x9d\xee\xa3\xae[!o}H\xb9go 2U\xb0\x94.\x92\xd1@b\xfa\xfb\xfe\xe4\xd1\xac\xe7\xeeO\x9c\xe9\xef\x8f\xb8\x95\x04\xae\xfa?>?G(\x86V3\x01i0\x159\xe8\xb4i6\x8fb\x156\xabg\x0b \x9b\xe2\x87\xfc\xba\xd7\x89\xa7\xfe\x8c\xb1\xc9-x\xa6\xf8a\x08^\xf8FnU}\x1a\xb9o\xe4\xde\xee\xb6\xd67rk\xb8\xa9\xf1\x8d\xec\x1e\xde\xae\xa9\x97\xd2\xb9\xaag+W\xcb\x14\xdf\x97\xf2\x93$\x7f\xe2\x87-\xc8\xb8\xe1\xcaL\xdc\x94\xf5a\xdd\x87y\x1f.\xfb\xe8\xc9\xa8\x89\x01\xba2X\xe2.\x0d\xe5w\xa8\xf9-\xafSE\xb5Yl\x8a\x92?\xf4\xe9\xdd\x9ar\x9fh\xa2\xe6R\x06\x950\\\xe8\xcf\x10\xb9+\x03=\x02\xe1\xddK\x1du\x04.\x04\xec)\xec\x8bh=\x1c\x10)W\x1a\xd3\x01Y\xaf\x83;'\xeeW#>}6\x0c\xf0\xdc\xech\x8f\x16\x12\xb0\x01\xe6\xfc\xedJ\xbc\xa0Kn\xb7\xf2R\x90\xa1P\xdei\xa0\xe8\xc0Z\xb9f\xcf\x16\xad\xc6t\xa35\x97dC\xa2\xb8\xb3t\xbbj\x01\xce\xb9\x9ac\xe3\x90\xed\xe0Z\xb59\xec\x83\x08\x05\x1fe\xa9s\xd3oa\x94\"A\x91\xc2\x068\x08\x0f{\x00\x88%L a\xdc\xdaB\xbep\xed\xd6\xf3s\x00ga\xabn\xdf\x06\x88\x1cZ\x1d\xad\xe7\n2\xa0Av\x00\x13\xb8`\xaf\x8c\xf9\x9d\x8e\x8a-5 M\xdf\xe3m\xd3\x1a\xe81\x97\x01\xea\\\x0bz\xb6Bl,$^f+\x1a\xa6 \x0f\xe4\x9f^\xfaI\x1fo+\xa8Ei\xc2^V\x90\xad\x10\xbf\x9b\x97\x0f\x14t\xe5\xbd\xd4\x91\x80 $\xab\x02fkmC\x9f\x1d\xd3\xc2\xb3\xd1-]u5\xea\xcd_8\x97m\xe4\xf0\xfa\xc6BSyG\xd7\xa8\xdb\xaf\x8cT{r`\xaa\x0bF\x85\xee\xefQFrB\xae\xfbA:\xd9a\xe7-\x99\xfb\xe1\x92g\xdap\x18\x95\xec\xae\xc8\xedo\xc4O\xbbty\xbb\xb5PS\xe5~p\xa2{#\x97u\xff@ *\xdd\xeb9\xe1-]B\x0f\xab\xac\x05\x82\xe43\xa1\xaf\x0f\x9d\xd8\xa9\xc4\xcd\xccs\x08\x15\x0c\":`\x8c\xc1#\xe1\xe3\x94\xcd\x0dH\x02\xb9|\xd9\xa9\xd8O~\xd6\xef\xd0\x1a\x80\xc6\xa0]\x14\x14-\xba\xe7\xe7\xd8\xfe\xf99R\xe4\x7f|\x86I\x15LZ-\xa89\xe8\x16\x8fC\xe7l?s\x1di\x15\x85\xe2`\x9f\x81vw\xe8\x0e\x16NUp\xee\x832\x0c\\\xbc>l\xba.\xeb\x7f*\xc3\xd9u\x1c\xaa\xda\x8c\xa1\x9aM\xe78\xd5\x14y*\xd5G\xcd6\x9e\xb0*0\x8cl\x87\xa8\xebK%\\\x8aFx\xf9\x9c\xd0\x1cM\xd0@\xf6\xb8\xae\x06\xad\x9a\xc1\xfe\xe33\xbf|\x19\x8b\x83\xa6\x82z\xde%\xf5\xae\xc6\x8aEv\xebM\xab\x92\xf5\x02\xe5\x8b\x8d\xdb\x82\xe8\x1b\x8f\x1d\x0fC6\xf0:\x0f\x1b\xd9\x97\xed}\xde\xdf\x18\xc7\xff\xcc}\xe0~oV\x1a2p\xed|E[\nx\xab2\xb4\x90\xad\xf7\xb4I\x88\x9d\xad\xbd-m\xdc\xa1\xa7\xba\xb0C\xa1\xb3]\xad\xcd\x07\xfft\xbbZ=\x10\xe5\xd5\x83\xc0\x13\xbdVG\xb9\xe0\xf5w\x86\xa5\xd3\xf0\x99\xf2+\x1a\xf8![\x1a\xa7\x82U\xeb\x1a\x19Z\xf8\xe1\xfc\xf5\xf1\xfb\xa3hN\xc7Ui6\xa6\xe1\x9c\xc6c\xf0\x07\xfc[e\x92\xe1*\xca\xc24\xd7\n\x1d\xa4\xbc\x11\x7f\xa0\x7fR~\xfb\x9a\xc6\x89\x1f\x85cH\xaa\xad&x\xc3v~\xc1\xe8\x05\x9d\x7fZ\xcfIJ\x931d\x83r\x89\xe15>\xd2\x93\xec\"\x8d)}\x1b\xa6\xd1\xab(L\x89\x1f\xb2y\x14\xc2\xabB\xa1\xf5\x91\x1a\xcf\xcf?\x1e\x1e\xbc:=\x7f}\xf8\xeb\xe9\xf1\xf1\xbb\x93\xf3\x9f\xde\x1d\xffx\xf0\xee\xfc\xe7\xe3\xe3_\xce\xd1CWk9e\x7fM,\n{\xbbU\xc5\x8ar>\x87\xe7iL\xa9.i\xf8\x92\xa6\xaf\x82(\xa1I\xfaV\x10\xe47q\xb4\xe2\xab\x12\x0f\xccO5\xba\x16\x8aK\xc6*\xc8\xcaM1\xc3@\xb9b\x18\x88e\xa0\xf3|\xcc\xfc\x02\x921\xfbR/\n=?`\xcb_\\h|\xaepH\xeboAL\xf6\xf6\xaa\xd1\xca$5\xa9\xeewNM\xf6\x9e\xea4u\xac\xbc\x1a\xdd,\x13\xe5U\xaa$\x88\xe1\xd3j\xbf\x81(\xaf\xf6\xcb\xe9\xc9\xde3==\xa9\x11\xc35'3\xa3*Y\x9a\xf3\xf2\xcd\xea\xe1w)\xcaG\x95\xf2kQ^\x9d\xeeJ\x94W\xc9\xe4R\x94W\xc1p'\xca\xab`\xb8\xe0\xe5[\xd5\xf6\xcfEy\xb5\xfd\x1bQ^\x9d\xef!*\x18\xdb\xf0n|{6\xc4\xce>D>\xeeP\xb8p/\x07\x87\xd74L\x0fW~\x9a\xd2Xl\xf0\x8f\x94x)\x96\xbf\xf3\x93\x94\x864vVn^\xf7C\x90-\xfd\xf0\xe7\xecB\xd4V\n\x8f\xe39\x8d\x1dR\xad\xfb)\xf5\x83D\xd4.Q\x0bga\xab\xcaj\x9c\xc6\x84\x91d\x12\xa0\x80\xde<\x82\xe4\xc7\xbb#\xb2\xa2\x9a\xfbC\xf69\xf1W\xeb\x80*\xd5\xc7pS\xa72\xecs\x18\xa64~G\xc9u\xb9v\xa6\xaf\xfd\xea\x92\x84\xcbrMCv\xb3\x13\x1a\x94\x07<\x86s}\xcd\x1f\xe9\"\x8a\xe9\xdbp\x9d\x95\xab\xd7]\xb4>#d~\x8e\x92\x02\xb8\x020?\xb1\xb5\xf3\xbd\xbc\xf8U@\x92\xc4\xf1\x8c\xf5O\xe9mZ\xa9|\x89\x95_\x1f\xbf\x97\xd7T\xa2\xaaR\xf2*\n\x17\xfe\x1235\xb4\xab\x99\xb4\xaey\xc1\x17}\xb5f%\xe5\xb1\x96\x0b\xdf\x10/\x8d\xe2\xbb\x16\xb1>\xa5\xc2\x81\xde\xc0\xba\x1a\x98\xb2\x80\xa68\xcd\xf3\x0d!\xc8\xf5iL\xc2\x84\xf0\x1e\xee4\x15\x7fd\xbc\x80\x1f.O\xd2\x98\xa4ty\xe7\\c\xa5\xda\xd8\xc3k?\x8e\xc2\x15\x0dS'0K\xf3\xf8\xed\x8b\xc8\xbf\x99F\x08\x00\xfb\x8cw\xa9\x03\xa8Kb\x9flxY\x1c\xd30\xed\x8eu\xf7 \xbc\xca\x9c\xa6\xc4\x0f\x12k\x15?a\xac\xcf\xdcV\xe7\xd2\x9f\xcfih\xab!\xfc\x02mU\xae\xe8]r\x19\xc5\xa9\x97\xa5\xd6\x01\x05\xe4\x82\x06\xb6\nq\x14\xd09M\xbc\xd8_#\x07e\xa9J\xb24\xf2\"FMRj\xab\x87\x92\x97\x1d\x06\xf4vM\xc2y\x03\x9cH\xb2\x8e\xd6\xd9\xda:=zm\x9f\xde*\x9a\x13{\x05\x19\xb5\xbc\xb1R\x82d\x8c-\xaf\xadj\x14\xfb4LI\x13,\xf1\xce\xfa2\n\xe64\xb6V\x8bi\x92\xd8\xc1\x14S2\x8f\xc2\xe0\xce^\xe7o\x99\x1f\xdb\xdb\xe1\xd3k\xa8\x13\xc5\xd6\x1drM\x82\x8c\xae\xc8ms\x1d\xdf\n\x1d\xac\x13F7\x8duRzk\x1d\x10I\xa3\x95\xef\xd9j\\d\x89\x15t\x81\x7fm]\xef\x98\x06\xf4\x9a4\x10\x0eF\x7f\x16\x0b&\x9f[j-crqa\x87?\xa3\xc2\xd7\xb8]i8o\xe8\xd4\x8b\x02\x8f\xf1\xe1\x0du\xd0P\xae\xa1N\xb2&\xd6\xe5\xf2\xa20\x8d\xa3\x06\xca\x884\xe6\x82\xce/\xac\xe0F\xcf\xe8\x15M\x12\xb2\xb4\x82}\x11D7id]8F\xf9\x82\xa6\xfe\xa2\x9b\xd0:\xecu\x94\xf8aB\xadP\x8c\xa3\x9bFH\xc7\xd1M#\xa4\xe3\xe8\xa6 \xd2 M\x13\xff\xef\x08\x99R\x8d\x8a\x00\xf6\xfa\xf8\xfdA\x9a\xc6\xfeE\x96R\xc6\x1a\xb2s\xaf^E\xf2\x1dy\x8d\xbc\xc2W\x9c\xc2\x8aFgX\x95V\xc4\xd5\x81^\xa3\xb3\xb7W\xad.e\xb0\xaap#e\xb0\xaap\x83q\x08\x9f\xf5a\xb4\xd5\x87\xcd\xbd>lmV,[\x990\xb6\xb9\xa9 \x14\x1d\x0d<\x12~J\xe8\xeb\xe3\xf7\xa8O@\xde%\xf1\xd9\xcc\x91\x0fE\xbd/O\x11Q~\x19\xc5\xb5R\xda\xfcjS\xf3\xc8\xc3+\xda\xf7\xd1\x9cb3\xb2\x00\xa4\xc3\xa0,\x18\xa8U\xab\xca\"~\xd3Zm\x9c\xf1\xae\xd5\x01\xb2\x07\x1d\xee\xb2\xe7\xd4\x0dk1\xf5\xbbHv\xc1V\x9f\xb8F\x05\xcaz \x14C\xac\x06\x9a\x07\xbd\x0dS'/u\xdc>\x8c\x86.\x8f\xe7\xa7\x11?+cu:\x1e\xc8HT\x0b\xc0\xec\xbe\xec\x0b\x86\xe4\xabL\xf6Z\x13\xa6{\x95G-\xc5t\xbc\xaf\x84W\x03\xe35K\xf5\x96\xdax\xd2\x17\x85\\\xa1\xe3\x00\xd9g}I\x12:\xffH\x97~\xc2\xf8X?\n\xe5\xb6\xd0Vg\x9f\x8b\xec\x82\xf1zc\xe8F\xa1\"\xb9X\xbc\x10<\xb2N\xb3\xb8\xfe\xca+^^\xb7\xe5\x87\xfa\xde\x96\x9f9]\xd3pNC\x0f\xd9\xdai7\x8d\xd6*\xda\x86\xf3n\x1fX\xe1/\xf4\xee\x03\xe3\"\xc4O\x862b\x98\xf8\xfb\x03IR\xda\xd5$\xe5\xab\xf7\xea\x95\x9a\xffN\x80\xac\xce\xa1\x1d,\xcbo}#p\xfe\x18d\xb1\x80\x92 \xb2\xaf\xa3\x9bP\x0f\xe7_\xe8\xdd\xa7\xb5\xf8\xfe>\xca\x12\x8aU\x1f\n\xe7\x93\x94\xc4\xdf\x0be_U\xba\xf9\x02X\xe3{\xdf\x15\xdabd\xff,xs\xc9\xf6\xfb\x03\x9c\xf7\xf3\x05\x10\xe7/~W\x90\xcb\xb1}C\x98\x97J*\xe3\xbb\x13\xaa\xbe\xbc07\x9b\xba\xd0^\xa5I{r\xad\xb2\x83[C\xe7C\xb3ZD\xd7r\xf7\xa2G\xc5\xab\xf2\xe1\xabk\x18gim:o {\xd0D\xd3S\x9b\xe3\x105\x19\xa8\x97@k\xa9\x84ki\xb7\x00\xd7\xc4\xac\xb3F0j\xb2\x1c\xd7ymhL \xafe\xde\xb7\x01W\xa0\x94G!:1\x05A\xe9\xceIJ\x90\xbbIa\x02\xe9\x80\xfd\xac\xdeI\x14#b]\xdd\xe4,Y}t\x87\x92\x8f5\x84\xa6\xcd\xfa\xba\xd8\x0e\x1e\x86l\xb3\x99FC\x13^\x82\xbaT5\xf2\xd6\x18\xf3k9\xa8\x9e z\xe39]\x17\xec\xbczX\x07\x87\xe1\xbc}\xf3\x82Z<\xac\x07\xfeR\x13\x9d\xe0\xd7O7\xdc\x96\x10\x85\x8fG\"J|u\xb8h=\xd7df\"1M\xd9\xc4\"\x92\xd3\xa3G\xca\x8e-\x07\xba\x16\x031\xf7\x8e\xab\xe1\xf6AI\x18^\x16\x08\x00\xf9a\xf6.\xc6q\x17\xe1{kMp\x1c\xab>:\x0c\xd1j\x8f\xe7\xa9c\xf2\xcd\xcd`I\xd3\xd7$%\x8e\xcb\x81\xb3\x0f>\xdawEQ@\xe7NTu\x05`X\xbd\xc0,\xc4E\xa5\xac\xd8\x03udO\\X\xf0]V\x8bsbp\x05\x95\x97\xd9\xe7Z\x7f\xfb\xdc\x92GDH\x91m\xb7qn\x8c\x07\xc4\xf3\xb2U\x16\x90\x94\x9e\xdeD\x1f\xd8\xf1\xfb\xdaO\xd6x\xf9\x9c\xe0E\xca\xc2J\x8dn\x1b\xf6;\xa9\xcf\xbf\x83\xd1\xa2\xe6U\x13\x9fo\xb6\xe3[m\xc7s\xa7\x1a\xb0F~\xda\x1c\x1c\xf2\x93\x1fF7\x97\xbew\x89\x8bp\x0d\x13\xbe\"cp\xee\xc4u\xd8\xaa\xa9\xabBd0\xf7\x95\x1bv\xe3\xfa\xea\x1b\x04\xe5&\x02Q\x1dc_\xdf\x15C\n\xf5\xef5\x86\xd9S\xf6]3M\xc1\xad\xdc\x82\\0d\xb81\xad,:5\xd4\x17\xb6\x88\x0c\xd7\xf1\xd8\xdc\x04\x07cj\x05\x14\xc0)\x1b\xbb\x11z\xfe \xa6\x01% un\xdc~~\xe0\xf5\x0d\x01,\xf5\xae\xce\xeda\x06\x0fBu.O\xb6Z\xabo\x8e\xe1\x8f\x1eA\xa7\x85iD\xe5m\x87\x0e\xbc4\x0e~\xa1w\xb8\x1ayJ~\xd8\xd0\xd1\xa2\xcf\xd1s\x80\xf2\x83\xf7\xba\xf9\xbe\xb9t<]XD\xa8\xb1\xa8\xf8*\x1b \xba1\x8b\xdcQ\x1a\xda\xd6HX\x01J\x810\xc1\xaa\xac\x96\xbc\x0d\x1d\x9c\xdf\xc4d\xbd\xa6\xf1I*\xb2~\xa4\xe5\"\xf3\xd5\x01gT0\xd0\x980\xd7\x0d8\xaf\xd3\x0d\xb3\xd5\x05\x8d\xf3\x95c\x0b`\x19\x0b(\xacw\x97\xe7\x8c\xc3\x03\xcc\xdc3`\xf4\xb5%Ms\x93TG\x9cyn\x112\x17\x1d\xefk\x15\xb4+\"?\xfa{\x8dz)\x9eB\x81\xd1\xe1D\xafp}\x8f\xa5_)*\xef=\xd595\xab)\xde#q\xa4\x8a$\xe2V\xb4i\x197\xd5@\xe0\xf8\xe5\\L\x17\xf5\x85\x928\x18\xd60\xd7\xe2\xce\xaf\xcfV\x00\x13\xa0\x0e\x0f8\x92]\x04\xbe\x97SMd\x02\xe2\x01\x99\x17n\xa8\x07\xc9G\xba8\x8d0m_\xbf\x1ab\x0bp\xe1B.\xc8\x0d\xce\xa3\x9b\x90Vc\x96\x16K\xc8\xc4\xb7\xe42\xca\x02!\x06\xb5\x81\xa6\x84I]r\x03\xa9\xae\xac]a\xe4\xd0\xa7\x06\xe8c\xb9\xc8\x86\x16\xd3\x85LL)\x86_\xbf\x0f\x89\x8c\x03\xf0\xb5\x03P.W\xecX\x90\x13\xcb\x94\x8f\xc3\xc7\xafb\x1c}\x08\xf1m\x0c#\x9eG+,\xde\x8e\x90\xc0\xf1\xbdY\x062g\x89\xdb\x80\xf7\xff5\xc8\x8a<;\xe2fLW\xd15-\xa3';\xf9\xbf \x82~\x075\\)\xe2\x80Q\x03iP\x8a\xfc\xe6\xc1^\x0b\x13G\xedR\xa7\x91Xh\xf3\xfb\x1e\xe6\\\x9a@d\x89\xfc\xe2\xac\x8d\xc1V\xd8\xe73_\x81 W8z\xe6!\x8b\xf0\xa0\xfb\xfb\xe0\xb5\xc4\x94\xb9h\x16D\x92\xe4\x04\xc6|\xb05\xf5G`\xb8\x96\x07\x19uD\xb4\xe2Y[\xf1,\xad\\WlZ\xc9\xa0 P\x88\xd0\xb8S\x0ds\xc9ov\xf0\x9d\x80S'V\xcc\x17\x0c\xd3`]WVq_\x17\x95\x17\x04dV\xfa\xd1 \x81\xc60\xca\x96\xd1\x08\xd0\xaf\xca\x83\xa2\x9c\xb6\xb3\xe2\xbc\x7f\xf6\xab:\xa8y\xd9\xce\xa98D\x95{\xa9\xeb>\xac\xf8&w\xfb0e\xbf\x1a \xa9\xfe\x8c\xcf\xb0\xf4+\x0f\xd2Z\xf4\x1bv\x8e\xca\x00+~\x14\x0e\xde\x7f:9=\xfftrx\xfe\xe1\xe3\xf1\x87\xc3\x8f\xa7\x7f\xad\x9f\xafj\xf5\x9f\x0fN\xce\x7f<>~wxpt\xfe\xeb\xc1\xbbO\x87\xf5c\xb7Z\xfd\xe8\xd3\xfb\xc3\x8fo_\xe9\xaag\x9a\xea\x1f\x8eO\xde\x9e\xbe\xfd\xf5\xd0\xf6^\xa2y\xef\xf8\xd7\xc3\x8f\xef\x8e\x0f^\x1f\xbe\xb6\x0d0\xd0\x9eR~\xf2*K\xd2h\x95k;\xc6\xf0\x91.\x0fo\xd7J\x94\xfc\x94&\xe9\xe0\xc2\x0f\xe7NHo\xc4c\xa7\xfb\xbb3')\xb9'\xb1O\xdc\x0d\xcc\x01\x14\x0f\x0eNO?\xbe\xfd\xf1\xd3\xe9\xe1\xf9\xd1\xc1\xfb\xc3\xf3W?\x1f|\xc4\xbc@?\xfc\xb9\xab\xcb\x1ao\x0f\x85\xc1><\xb3\x8e\xd6\x07\xb9x\xfc\xea\x92\xc4\x185\xd1R+I~\xa1w\x96\x1a)\xc6\x1c3=\x0e\x82\xe8\xe6M\x16\x04'^L\xa99\xb6\x0c\xd6\xc3\x08%xjx\x96\x0e\x03\xcbp\x13\xcb\xa3\xbb\xd03w\x9f\xa5\xd1+\x11\x12\xc3\xdcD\x96F\x1f\x02rglE\\\xec\x9b\x9f\xd3 \xf8@\xe6s?\\\x1a;auN\xd6\xc4\xb3\xd6\xb9$\xf1\x89e\xd5\xbcK\x12\x04\x14-\x1c\x8c50\xb4\xc7\x18\"\xb87\x8e\xd6\xb7\xc0\xc2\x0bH\x92\xbc}m\x7f\xceYLS\x8d(H\x8cA\x89\xbc\x88\x01\xc1\x8cV^\x14\xa64\xb4@\x80??\x9c\xfb\x18\xe8\xc3^\xef6}O\xc3\xccZ'\xc6\xc1\x9a\x00%*\xbc\xf3\x13\xdb\x88\xa2xnFO/\x8e\x92\xe48\xf61L\x92\xa1\x0e\xb7\x0c2?\xa4\xa7\xbe\x05\xdey|\\\xc3,\xe6t\x81\x81 \x0dO\xfd\xd8\xdc\xb2\x08\x96c~9\xba \x83\x88\xcck\x91 \xf3\n1Y.\xad\x0bEC\x8f \x04\xc6\xe7\x8b(^Y\x1f\x1e\xd8\xe9\x14\xabr\xd8\xa2\x8f\xf74\xbd\x8c\xe6\xd6*G\xd1\xaf$\xf0\xb9\xff\xa9\x01 \xac\x1a\xe7\x0f\xcc-\xc5dE\x7f\x8cb\x8c\x16i\xa8sI\xc9\x9c\xc6f\xa4\xba\xa4\xfe\xf2\xd2\xdc\x05\x0f`d\x1c\xe4\xa5\xbf\xbc4\xbf\x1b\xd3\x85\xf5\xe1;b!`\x97\xe9*x\x13Y&\x96\xa6\xeb\xc3\xbfe\xfe\xb5\xb1\x86\xefY\x16\xd37/\x10\xden\xbd\xc7\xf0\x8d\xc6\x1a)]\xc6~j>\x81|3\xc4\xaf\xe8\xdd\x07\x12\x93\x95\xb5\x86\x15\xc9\xae\xfc\xd0d\xeet83ov*nd\xd9$e\xba]D(4\x7f2\xec\"~]\x19\x95\xea3\x08a\x08|\xda\xd7\xed\xbe\xca>3$WK\xbe\x052\xd5\xd0C\xe4\x87xVE2\x11\x9b\xf4\x99>?\x84.\xd9L\xac\xac\xe8\xa40\x9d\xe7\x89x\x04\x85r\xbas\xff\xfa\xffa\xefM\xdb\xdb\xc6\x91E\xe1\xef\xf3+`\xde9ij,)\x96\x9d\xc5Q\xe2\xf6u;\xce\xe9\xdc\xc9\xf6\xc6N/\xa3\xf6\xf8\xc0$$\xf1\x84\"8\\d\xbb;\xf9\xef\xef\x83\x02@\x82d\x81\xa4lgf\xeey.?\xd8\"P\x00\xb1\x16\xaa\n\xb58\xfa\xbe\xb7\xb9\xf2\x1e\xfe\xfd\xb7\xf4//\xdc\xdf\xae\xb6\x07\x0f\xf1Q\xe8\xa5\xdbX\xbb\xca\xcf\xc5\x9a\xa2\xee\xd6\x04\xd1DL:\xfd[\x91\x8ab\xf8\x8af\xde\xd2M\xdb/>\x01Ug\xb3\xc9yU\x1f\xbc9\xf1\xa8yVH\x94np\xe0\xd6u'\xe1\x82\x1bkd4\x0e\xa2\x88%b\xbb\x08\x9c<\x9b\x9c\x93m\xc2\xc86 g\xbb\xc8\n/B\x1a{\x00\xbds\xfe\x9cx\xa3\xd1\xf3\x81\xd4\x0c\x1d\x874\xcd`\xe1V\x17\xa6\\\xda\xd5O\xb1\xe6\x90\xce\xb5B\x98\x9a\xf4\xf4\x87\x9b3\xba\x80H\x0d\x8e\xf4\xb7^?a\xe7:`\xb3\x8c\x16\xadgkH\xb8;\x1f\x8c\xe7<9\xa1\xde\xd2\xcd\xeaF\x80E/br \x83~\x81\xfa\x89\x1b\x8d=\xd1x\xb1m\xd3\xc1s\xb3?\xa2\x87Z\xdfQn\xe42\x0f7\x99,\xf1\xfc\xd7\xfb\xd8\x7f\xfb\x96\xcdm_\x82\xaa\x1d\xedkT+7nI\xcd\x1cTC\xb7\xaa\xd0x`\x86#~\xf0\x808r\x06\xc05\x03T\xb2\xe5:)\xcb^G\x19K\xd64\x94\xe9\x83\x8a\xde\xbc\xa9\x13)p\xb3 \xcd\xe1\xf3r*\x82\x14\xfe\x8b\x06\x8bO{4\x0c\x19S\xf5\x83\xa9G\xc6V\xaa\xda\xea2\x13%\x0eI\xa3\x12 \xa2\xc0\xf6\xbf\xdb\x98\xa3\xdc\xaf6\x7f b'\xe1\x0d\xd5c\xb7U\xd5n\xb6\x85r\x86\xc3\x08\x16+20\x99\x91\xad\x0c.\xc1x\x81\x8c\xc8\xa4\x18 ]\x1c\x9d\x9c\xb1\x1c7\xa3\x9ez(\xf9AK\xbc=\xb5.d?\xcb[v\x18F\x15\x87\x1d\xc1Jf\x9c\xbc&UX\xec\xbaH\xef:7\x13[U\xfa\x9e\xe0\xe4\x05\xc9\x9e\x13\xbe\xbd= \xd1\x8c\x9f\x8bI\x98q\x04\x05i\xf5\x9c\xe6\xdcO\xc9\x8c\x9d\xdf\xef\xb6\xb3\x1c{XP\xa4\xbb\x1ec\xa0\x13\x89h\xed\xcd&C\xf2\xdd\x0b\xc9\x1f\x16\x02\xec\x03'Kr\xe6|\xff\xdd\x908/\x1e\xca\xcc\xef\x9d\xf3\xe6\xc1(J;/\x80\xb1\xfc\xde\x01`\xf5\x1b\xf1\xf4=\xdb+a_d\x97\xdc\xbf\xf9\xfeE\x96\xe8b\xc9\xf7/\x1e\xaaDK\x1d^\xd9\xda\xf5\x82\\\xaf\xc2(=\x00\x8eo\xfa\xf0\xe1\xd5\xd5\xd5\xf8jo\xcc\x93\xc5\xc3\xdd\x9d\x9d\x9d\x87\xe9zQ\xb4~\xbdhT5G\xa9x\xe7/\xceT\xf6\xe8\xf0\x85\x1f\xacU\xcb\xe0\xd7y\xf38\xa4 \xa3\n\xfc\xc5\x8a\xc6\n\x1a~!\xd0\x1e\x0f\xa7d\xb6\xdb\x1c\x01\xddi\x8f\x87\x8b\x84\xe7\xba\x9e\xe2\xd56\x1a\xe2 \xd9\x82E\xben\xc4<`\xa1\x9f\xb2L\xd5P\xbe\"%c\x9a\xd0\x95.(1\x8b*\xa6_\x90BY\x82vAM`\xeb\xdc\x11y\xb7\xb0\x90\"wDn\xcacy\xad\x8bdyT\xe5!l\x92\x1e&4\x13\x9a\x84\xe7\xcc9\xcf\xf0\x9c%\xb3\xdcog~#\x08\xa0,0\xad\xbb\xa7,w\xfa\xcc\xf1\x82\xc4\x0b\x81\xc5\xf5\xc2 \xfe@\xb3\xa5\xf8\xed\xb39\xb8n`a\x18\xc4)d/\xc4\x9f`E\xa5\xaf\x07\x08\x80\xa2\xfe\xd3\xe4?\x13\xea\x07,\x02-\xdd\x15M\xc1\x03D\xac\xaaR72\xf0\x93\x877\x0b^\xfc\xd4u\x88\xc244\xebHddJ'\xcd\xb8\xf4\x0d\xc1\xae\xa5\x060\x84;8/(\x1b\xfba6\x07\x0f>\xc4\x1b\x12*\x7f\x99\xc1xk^N:i\x88@\x9c6\\\x9e\"\xf3\xda)\xa2N?p!\xe4\xfcEpV\xd4\x02\x11T\xe8?\xe7/\xa5m\xb5\xf3\"\x0c\xa2\xcf\xe4\xe1\xf7\x0e\x99\x12\xe7\x85\xa3HP\xe7\xfb\x17\x0f\xcb\xdfN\xd9\x95`<\x0f\x12M}\xa9\xe4C\xd9e\xd4\xd3\xed]\x0f\x01T\xc8`Qwoe~q\xe1BO\xeeW\x1f\x9d\xb8\x82(\xe6\x83\x99\x80\xab\n%\xfb\xd0\x0e/\xa2>\xac$Nl\xde\xc1<\xa2S,\xd1p@\xa3\x19\xc9z$=-\x97\xa8\xcfI\x8eK7R5\x85x\x9c\xc1\x86\x02\xa6\n[\xfa\xa4\xce\xbe\xaa0\x83\x0dW>\xb1\xaa\xbe\x9e.\xe3\x0cN\x1e\xd7;+\xe3\x0c\xee=\xae\xc3\xaf\xf1\x15\xa5\xc2\x0c\xee\xd4;\xab\xc2\x0c\xee\xd4 \x91\x1b\xd5\xfc\xfa`\xaa0\x83\x0d\xbb\x8d\x0b)\xb5\xd9{6\x18B\xb8\xc4\x9d\xba\n\xa4\x8a7\xd8\x18\xbe\x13U\xf0\x11\x14\x9c\xf8\xeb\xebB\xa2`r\x0b\xa2\x85\x16{\xf7\xa8\x10\xf9;\xe4l\x19\xa4D\xd0\xf6\x82c%W4%:L,\xb9\xbc!\xff%\xce\xa9H\x9cS\xff5Fn6\xfed\x7f\xd3\x1f(Ka./\xde\xa1'\x83\xb4Z\xfd?36\xbe\xc8\xe8\xe2\\\x1a\xd7(s\xcfl\xac\x97\x85\x1e)\x99jY\x0c\x8a\x1fu&{O\x1dA\x1d\x88\n\x87\xf6\xc1?$\x0e\x81\x0btA\x8f\xa9\x91P\xaa;\x84\xcf \x9c\xda\x96\xb2\xe5\xc0\x8b\xe1\x1a\xc3\x91\x0f\xf6\x89]M\xb4uO6\xfc\xc9\x0eHu\x11\x9b\xd9\xb6\xfa\xce\xc0\xa3\xa4\x15B\x8a\x94\x9fL\x9cA\xa5\x81p\xcf^1\xd158\xf72W\x14\xddu\x86\xb0\xec\x07\xed.M>\xb6x\xdc\x90N\xb6\x133P\xfd\x15\xea!\x19\xf1\x88\xa8m\xa6\xd9\xf8b \xa1!\xda[\xe4\x05\xac\xf2\x07\x0f\xf4\xcfRN#h\xb6\xd7`\x99#a\xa6\xe2W\x87 \xd3\x91\x9b\x0dI\x00>\xb2\x16L\x06\x8e\x85\x88\xc7\x1f\x19\xf5o\xdc\x81v\xa6\xe5\xbe\xc4\xee\x0e\xa0QQ\x9aM \x12\xeb\x99\xa0\xb6v\x16\x97\x9a\xa1:3\xa6\x88\xdf\xe7\xafVKQd\xb6^6\\ \xcd\xc7q^\xc6\xc1\x05\xe7\x92\xa2\xcd\xca\xcfd\xbd\x85*Y\xb7\xa7}i\xbci|l5\x8ey*G\xf0g\xe9\xca\x02\xbe\xd8^\xcd\xa7F5\x97\xb7\xa9\xe6\x1f\x8dj\x16\xdd\xd5\xe8_b5\xbej\x1ca\x19\x8f\x8f.y\x02w\xd3\xe2\x7f\xed\xcc\xcbx|L#i\x0e\xe0x4\x8aCzc\x05)\xfc\xe1h\xc8L&4\x0b\xbc\xcc\xe5|\x1c+\x0f\x85\x8e\xaf\x12<\xcc\xab`\xc6\xe3\x93U\x9c\x05\xe0K\x90\xc9_\x08H\xe4%7q&\x81\xf4o\x0c\xccW >\x9a\x9d$p\xa3\x0e\x91\xfd\x9a\xd9o8\xf5\x99/\xfd\xd6:!\xbc@\xc8\x0f\x0b\xe0[\x96Q\xdf\x04^\xa9\x04\xbc\x80\x8a\x9f\x04\xb0)\x12\xe4\x08\x1c\x96\xe7\xa9\x18\xb0X\xfcG\xb2\xe5L\xe1\xd3$2\x81\x88\x80\xfc Z _$\xa0X\xe6\xc4\xeag\x13\xe8#\xcdX1s \xcd\x98m\xd6N\x19\x03\xf3\x0b'\x85\x1f8\x80lQ*\x7f! \x19\x0d\xa5\xcf\xc9T\xfeB@\xf24\x06I\x8f\x93\xca_M\x90\xb3`\xc5t\xb4$'\x0bV,\xc7B\x1ae<\xfe\x89\x87\xf9\xaa\xec\xdd\x1a^m\xfd\xfb\x99\x06\x99l\xfe\x95\xfce\xd0\x11\x18 \xf6{c\xff^\x8f\xb3\x84z\x9f{\xec\xfd\x1f\x1aeK_\xcb\x82\xe0~\xfdR\x1f\x98{\xf5\x8b\x1a\xb1\xf3\x199 \xea3\xd5\xcc\xc2W\xbe.\xfe\xc8)<\xf4ft\x81\x1du\xd2\xd3{\x00\xba\xfb\xd6 ?\xeap\xc6\xdd\xb5\xcb\xeaMW@\x05>\x06\xb9\xa9/\x86%\xfeA\xba\x1bU\x0e\xdc\xd4\x1e\x01\xb9\x8f\xfc\xcf\x06\x96k\xe0\xcb\x84\xd1\xcf\xcd,\xd9\xb0u\xe03nm6\xcd\xfd\x00\xcb%\xa6\x0c=+]a\xdb\xfbp>$\xaf\x06\xe4U]\x1e\x93\x01\xb1\xd7Vx\x1c\xe7\xe9\xd2E\x86 \x1b\x92W\xb3\xec\\t\xdcB7\xb7v\\j\xac\xdd\xef\x8c\x9cH4Y\xe0\xcb[\xceI\xb0Z|\xf3v\x0d\xc9\xb7\\Us\x9e\xac\xee\xb7\x0b\x1f\x19h\x88\x11'Q?Z\xbap\x9a_\xae\x02)\xb4\xd4\xbfn\xd7\x8d\xc0\x128E\xad \xe9*\xce\x1a\xd7\x8b]g4a\xf4~\xc7\xe1\xb5\n/>\x14\xad\xd3?\x99=$\x01\x82;\x7fj\xe0\xce\x1b\xa0\x9b\xe4\x89\xd0\x87p\xfa\x11\xe5\xfd\xe5%\x07&k\xb8\xa4\xe2\x94Fs\x12<\x1d\xae@\xb0\x0c\xb6\xba\x14\xc7\x1f\x96\xb5\xb4\xd4\x15\xac,\"\x90@\xc6\x14\xc5\xb2>\xb3\x9b\x05\x8b\xf0\xbc0\x88>\xe39\x82\x9e\xc1s\xd4\x1d\n\x96\xa5Ug\xb1<8\x0e\xf1\xac\xab\xcbN\xe1\xcd\xcf\xe84\x89Uf\x95\n\xc5\x89\xad%j5w}\xf3\xff\x80\xff\xbe\xe6WW,\xca\x83\x8c\xad\x90\xf2\xe4\xc7\x9ap\xedW\xd0\xa2\x99\xd1\xd1\xefG\xa3\xbf\x9d\xab\xff\xd3\x8b\xdf\xc6\xbf\x8d~\xf3\xcf\xff\xf2\xe7\x87U\xf0\xbf\"\xb7\x95\xff i\xb5\xd3\x06#B\xfe\x8cJ3\n\xedJ\x1d^\xd0\x199\x03\xf2\xfd\x01\xd9\xa9J0\x02[\xa4\x92\xbfA\xb0\x01\xe4{\xbf\xb4\xc5\xd8\x13|{\x15\x17u\x85\xc4\xf9Oy\x03\xfeW\xf03\xfb\xe5\x0bq\x7f\x05\xf3su\xcf!\x08\x98\xc7\nW\xfeU\xdf\xbd4\xdc\xbc\x16\x04NUFb\x86\x03\xc9\xe8\x824\\C\xea\xcc\x88\xaeX\x1aS\x8f}\xfa\xf8\x9aT\xe3ph\xb9\x94\xbee\xa8e\xc7 [\x07r\x9e\xb9e\x9dRZ[\x1a\xa4\x05,u%\xa99\x17\xb4\xbe\xa5\x9d*\xbcv\xee\xc6\x16\x08\xd5s\x18\x92\xd7Q\x90\x054\xd4t\xbb\xa0%\xe7C\x92\x0c\xc9\xd5@\xfa\xd8o\xfa\xf4\xfb\xda\xe6fP|\xfd\xa4\\\x98\xf0\x8d\xf71\x8b\xce\xe8B\x9a\xdd\x1cE\xfe\x87\xf2\xda*\x85\x0f\xb6,\xf6\xebZ]JA@\xd6\xa5[k\xe9\xa7h\xfe\xd6\xb5@)?\xce\x8a]yN\x0e\xc9\x89X\xdeR\xf3\xebD\xaet\xb2M\xae\xc5/\xb9\xfc\xadKC\x02\xf7@\xe0\x1b\x92\xaf]\x14O\xc7\xc9\xf2\xa68\x82\xe6c\x9ag\x1c\xc2\x88H\xd3\xba\xd6r\xc1x. M\xfe\xe3\x9fr\x14w4\xeb\xd3\xbfSwZ\xa9\" r\x99gY+-\xf7o\xd0\x8dNz\xb3\xa3Q\xff\xe8O\xbc(\x99J\xab\xbeN\x0f\xcc\xd0CCQ+\xd6\xc8\x03l\x83\xb3\xb0\xb8\xd2H\xe0J\x03?\xc7@\xa7\xa7~\x8f\x91t\xc6\x89\x06/\xee\xb3\xa4\xc5T\xcf\x0c)\x11\xd8\xcfP\x0d\xfa\x1ek\x03x\xa7\xfe\xa8N\xa1\x04\xe2\xa2\xd8\x0e\x04\xfdt8\x87\xd5\x8f\x03\xba$\x92\x96\x01\xcb.7P\x7f5&\xc6$6\xdc\xfd\xe3\xebP+\xa2\x08\xa2-\x80x\xf6r\x9a\xe5\xfc\xbe\xe2 \x94H\xdd@-\xa6\x8e\x06\x135\xa29\xc1\xdc\xeccOA'\x9b\xf4\xe4\x9fK,\x0c\xeb\xe8\x90\xbcm\x8e(\xc8\xd4\xc4\x87\xbcz\x9bk~ ]1\xd8\x10(\x01\x85.\xab\x94\xda'\xb9\xd4 \"\xdb\x07\xc4\x01\x15\xa5\xbc}\xc2\xfb\xc6\xcb0\xcc\xc2#\x9f%g\\\xf0\xf9\x81'\xdbA\x0eID\xa6\xfa\xf4\xa9\xd2\x1cf[\x1a\xad\x07\xfa\x03\xf4\x8eZ\x80^\xbfT\x15\x83\xech\xd0\xea\xd3\x1d;\xb5\xfb\xf9s_\x17\xe1Kp\xe2\x80\x93\x16\xb5\xad\xe6J1\xf7\x1c\x1f\x14\x0b\x85\x8f\xa5\xce#\xccRB\xca\x04divP=b\xc1\x7f\x98\x15\x1aYZUL\xd0\x1b\x86\xe2\x98M\x01R?T\xadu\xc0\x0df\x84p]\x83\x9d_)Q\n\x0c\xdc\x89\x1b\xb4\xd1\xc5f \xda\x86\xd3\x12\xbd\xef\xa5\xfcQ\x13\x8aT\xc5[\x18\xff7\x0f\"\xd7qng\xa7O\xca\xa5\xfc\xb3I\xa3 \xce\xf37\x15\x02,\x19{K\x9a\x1ce\xee\x8e\xd8\xbb\x90\xbcM\x1225\xe2^\x10\xeb\xca\xab\xd1\xb7\xbd\xa5\xa6Z\x89\xed~\x97X>\x86\xd3T\x94\x17\x08\xe2\x7f\xc6bs\xa4\x83\x89\xc0\xe8 \x84\x86\x06\x0c\xd8{\x05Z\x1bY\x9c\xd5i\xfbB\x94\xec\xca\xces\x12\x92\x17$\xd5\xb6\x94$\xdc\xde\x1e\xe8fI\x0e6\x19\x92t\x16\x9ew\x912\x8d\xe8\x14\x1e\x0b\x8c\xf0\x14\x9ba1\x8c6i\x0e\x0d\x06e\xdc\xceHv\xb0h\x81\x9b\xc1\xc9\xdf\x8czR7\xe8\xab\x16\xbb\xc5\x16\x00\x19=\xbe\x8c\x82o+\xd7\xefb\x8c\xb8M\xdc\xcb\x15 \x82f\xda\x96%\xb9\x17J\x9a\xdb\xa4\xb3\xbaMh\xe6\x9d\xda\xd4)\xba\xe56\xf1\xacn\x13\x9ay\xa76\xf5\xe0\x03\xb9M\xec\xaa[\x85f\"$\xb3\x9d\x01\x7fW\x14j\x13\xaapE@7`\n,\xa3 \xc4V\x19v\x8b\xf8\xfa-\xde\x95\xda\xd1\x15M\x8c!\xb9\xc6\x83\xe3\xde\x95\x03\xec1\x1f\x97X\x83\xee\xf0\xc9\xcee\xd9\xc1t\xfe\xd4\x8f\xe9\xac\x9f\xfc\xc8\x0co\x80\xade\x8cI\x0b\xcf\x98 >\x00\xf4\x03:\xf3\x08\xc3(Y~4Y\x1f\x7fl\x96 \xe7\x91Yq\x85+\xeb#YN\xed\xecZ;\x1f\x05\xfd\x0cD?\xd3\x01I\xeb\xed\x0e\xa4\xec\x1fX%pU\xf2\xc7\xd7\xc1,8\x07B\xbd\x83\x9d\xb33\x8f\xedW\x8e\x92Z@\xb8`r\x08\x03G L\xad\xdc\xe6\x89`\xcc*\x0c\x1fka\xf8f\xd8A\xecB\x11\xd1\xed9\x90\x81q\xc5dfn\xaa\xd1\xc4\x83M\xd6x\xebZ\x12\xe0\x10\x98\xa6\x87Pb.\xa6\xb0}\xf1\x0dI\xdc\xb5\xa7Hek\xc4\x03\xb2\x15#{\xe3\xcb\x172\x87\xb1\xc0\xf3n\xb5o\xaa_\x9e\x0f\xd0\xca\x1f< \xb1\xa8OL\xc1\\\xfc\xb0\xecR\x91\xd7!\x81\x90\xfbM\x14E\"\xfb\xe9\xa7\xa0\xe0Q\xe9\x94\x98\x1aC85\x07|;\x95k\xa3\xdc\xaa=j\xaf\xc9n\x06\xf6\x9d\x9c\xb2\xacm\x1b\xb7\xdf\x8d\x17\xdf\xdb`\xa3w\xa3`\xdf\xa6|^\x7f\xca\xddrX\xedI\xd1K_u\x81L\xed\xd8\xc5\xdf0\x10k3\x05\x84U\xd4l\x80\x12\xd8\x15\xe3\x98c'\xb2\xf5\xfc\xbd5\xd7]\xb0\xb6\xac\xc2\xda\xb2~\xac\xed\xdd\x99c\nZz-6|\xd6L\xc5\xd1\xe3\xd5\xe6m\x02\x05\xd0\x8f\xbfU\xb5\xa9\xc1\xc6\xf3\x92\x8d/G\x0b/\x16vq\xffx1\xaf\xf25\x03\xbd[\xbc\x07\xcf+\x9f1\xe0\x11\x1aKg\xa5\x05q\xa4B]e\x06\xff\xabIr\x89\xb8#uF{\xa2\xc8\x16 _\x03\xf8\x8c]gJ\xf8\xe8V,>\x03PF(\xe4\x16\xd6\"d\x9b\x04\x03\xe3\x98\xcc\xc9!\xa1P.\xaf\x95SW\x92\x8e\x14\xf2\x1aE\xc2\x1a`\xd1\x81\x10\x0bg]\xdbL\x8a\xffy\x07\x0e\x85\x8b]\x84\xed\x1d%F\xab\x1b\xd5 u\xe6\x91]\x95\x10\xabyC\x9e\xfd\xff\xe9\xe2\x19\x8f\xd6\xf9\x95c\x87[\x01\xd8\x0f\x07iV\xdezvT<\\\xed<'\x11yA\xb2B\xfa\x15mo\x0fH6\x8b\xce\x95\x0e\x87\xcd\xf2\x9c\xf4a\xe7\xda\xf8\xd9\xde<\xe6\xf58\xcdx|\x96P\xefs\x10-\xbaN\xc7\xce6\x81\xc3\x82\xb6&-\x19\xf5\xdboo\xb9\x7f\xd3\xd2\xde\xc4u\x9e6\x1f\xe93\\\xf6\xd9i*C\xea\xa7\x8f&\x8bA6\xe0\x07\xa2\xf4h|\xc7\x03\xf1\xe9\xb3\xba\xcb2\x0e\x86\x87\xa3U:\xea\xf4\xdc]_\xeaj\xeb&n\xe1e\xdd\xe5C\xe2\xac\xd2\x913\xa8\xe3\xda;\xb5\xfb\xe1\xc8\x1d\x0f\x1e.n\xd9\xbe\xb2u\xc9\xb0\x1b\x85kW\xe0\xe3\x8c\x7f\x12\x14$\xe2\x02\xfc\xeb\xbdv\xceF\xa5(\xaa!\x19\x07\xe9\xa7(\xc8B\x96\xa6\xef\xc0\x7f\xd9\xa0k\x1cZ]\x19iQ\x02h@9\x97\x9c\x87\x8cV\\\x17\xcb\x0c\xa5\xc0_z\xe0\xaa\xed\x04\xady\x11\xa4\xef\xe8;7\xab\xa1\x07\xbd2DU \xe80\x9c(s\xc4?\xe5\x83\x07\x84K/\x922\xd2\x05\x99\x82\x08\xbc\x11!\x80HG\xe3`\x96\x99\x04+\xd0\xcf\xca\xc4y\x13_7N\xf7;N\xca\xfe\x0e6)\x0f\xff~\xb7\x8d2\xa8\xec\x94\x11l\x95\xfbl\xf7Cwv4\xfa\xdb\xf9=m\x16g\xf4\xe7\x893\xb08\xc3\xbfCk\xfb\xb5H\xcb\x0b\xfe\xf8\x8a.\xae\xa2 z\xe6\x17\xdb\xb8\xb6\xd8\"y\xf9\x90\xcd\"pq-M\x89\xa5\x14>\x82\xd54\x8b\xec~\x05\xc8m;lpg\x8fw:\xf7\xafej\xbes\xbe#\xdb\xb0\x88\xc8\xb6x\xb9\xe7\x86M\xcc\x86i\x92\xa9\xda\x10q\x08\x87\xecL\xd9\xfcb\xa2l\x8e\xcdE\x97A7\x01?\xa9\xea\xa6\x1b\xdc>\xa4 !(|\xa7B\xda\xff\x07\xf7\xe0[\x13\x84\x9ft\x931\xbb\xce\x12\xeae\xbat\xd9\x1e+s\x8e\xcf\xc2\xbd\x84~\xd9}2\xc0\xec\xe09z\xe8h\x9e\xc1\xb2\xcc\xa3\x19\xabn\xc0s\xcc*=\x9a9?\xb3\xcb\xcfA\x06\xae\xff\x80\x1c\xb9*\xde3\xc8\x7f\xcb\x7f/3W\xf2E\xe6\xac\xd22\xe3\xedi\x99\xfe\xbeL\xe6\x90\xda\xf8jm \x12\xe3`hN3\x8d\x82\x15\xb8\xf8\x02OM\xdcu\x8et\x823$\xe5\xcbI\xe4c|KQ:\xc8\x98\xf4\x14\xd6R\xc7k\x0d\xd3Z\x93\n\xf5g\xad\x05\x9cqa5d\x89\xa0?\xcd\xae\x9c\x15)\xa2\x86\xf2\x0d:S]\x81My\x02\xe6v\xde\\\x0d\xa6k{q\x00\xe6\xfd\x18\xf6\xca\xa0\x8a}\x01Q\x1b\xae\x82\xc8\xe7W\x80\x04\xa5\xa8\x8d\x04csf\xca\x97!i\x02\x14\x83\xdf\x0e\x06#[\xbe\x0e\xaac\x82\xb4\xa5\xa8\xa22\xb4\xc6[o\x9f\xd9\x82\xc6\xa13v^P.\xe2\xe5y\x03d+0a\x90h(\xe2\xe4 \x1aE\x0d\x113\xce)\xa2\\b$5\\D\x91\xbc\xd2.P`\x88\xce\xd1\x8d_qIJ\xee\x8e\x946s\xfc\xdct\xc1,%_\xbb\x93\xba\x0f\xe3\x1c\x97:J\xc7\xcf\x8f\xf6\x8cCE\xbb#~\x86b\xc7\xb0\xdb\xbd\x19h\x13 zY\xc6@5\xeb\xf5\xac\x07\xaa\xe3-\x99\xf7\xf9\x92_\xebHU:,\x1c\xb8\x84\xe7\x95\xd4\xc3R;d\x0c\xc5\x98oj\x8c\x8c!R\x9b\x05\x1d6\xa3)\x98\xaa|\x1b\x88\x95\xe8x\xa1$ nf\x11\xed$\x1a\xecX6\xb2A\x9a\x93\xb2\xff\x98\xcf\x1a\xf1\xc8\xb0\x9aR\xe8f\xb9f\x850\xa8m\x10\x10(\xba\x15\x80^k\x80F\xfeWX\xddx\xe3Tx\x7f\xd5\xbd\xf6o(\xd8\x9fd\xd8\xc16H\x15\x99P\xcfg\xa4\xccFX\xed\x9e*\x90*\xf4P!^\x91\xa7\xdb\xa5\xabJ\xc8!h\xe8[\xaaR\xfd\xc0++\xddc\xd6K\xeb\x9c\xe6\xd0\xb5\x9e6\xa6\xd9\xff\x06\xeb.\x1b\x9b#\xd9\\O\xac\xa7\x8b\x8dj\x9f\xcb1\xca\x8a-uh\xfc\x9e\x96\xdfm\x1d%sR\xcc:aN\xa1F\xf9kJl\xb7\xffU\x8f\x1f]s\xd1M\xcc\x92\xc6m'\xa6\x11\xde.\x9b\x95\xfb\x9d]3/\xcf\xd8{\xf5q7k\xb7mK\xc74\xa5\xb1\x1bv\x1aI\xae\x0b\x85\xf6\x88\xaeZ,\xe4Azh`Ce\xfbk\xe8k\xa2\x14\xbf\xf9\x14G\xa68Xr\xfb=\xd1\x10\xee0\x82\xe7\xc43\xc2\xf7=\x1f@j%\xa9\xdf\xd7\xe6P\xec\x1f9KnNA\xf7\x96'Ga\xe8\xca\x9b\xdb\x99\xe8\xf5\x81\xa0i\xff\xcf\xe9\xfbwc)i\x08\xe67Re\x01D\xd8\xdf\x9d\x83\xda\xcc\x81\xea\xfd\xf9w\x03\xe9\x02`\xe79\x89\xc9\x8b\"\xf4\xd9s\x12oow\x0d\x01Q#\xee\x83\xd6Y\xdc!\xb3$j\xdc\xfdR'\xc3\x1f\xcfy\xb2\x82\x19\x08\xe0g\x9f/\x12\xf5\xd5\xa5\x1ew=\xdeb\xec\xe1\xd2\xb5\x1e;\xcd\xf6,\x95c\xadg\xe0\xe4\xbb\\d\xcbn\xc9*.\xfa\xec\xce\xb5\xe7\xa0\x01\xa8\xf4\xf3u|\x19D>\x1a\x9eO<\x1e\x8f\xb2\x84Ko\xb2\x1e\xa6N\xd0\xaaM]\xa1<\xba\xf0\xc0\xda\xea@\xbfe\xf3Kd\xab\x10`sn\xca\xe3\xe9\xc1\x03\x12\xa0\xdaq\xf8\x06\x13\xdc\xb4\xa3\xaa\x85;\x1b\x88}\x8b\xcc\xbe&\x17\xad\xd5\xe0\xb8\xb1N\x9b4+\xaeZ\x84\xe1x|N\\)'\xe4pG\xa1M\xde\x00{\x0f\xf4\x0f\xc1\x8d\xeeX\xc4\xf2\xc5MD\x11\xd2\xad\xc4Y]\xb8\x1aD\xec4I\xe5]\xa1\xab\xbe6$\x93\x1d\x90\x18\xb5\xdc\xc9\xb8\\\xeai)\x8f1RcK\xb7VbH0\xa9,\xdb/\x91\x0c\xbe\x80e'\xca\xe2\x1a\x1c\xaf\x039\x8b!\xd6\xa3\x16\xf2*x\x03_W\xcfr\xd9\xd4JJ\xf1\xc9&\xa4[\x03E\x01\xb5f\xd9\x81y\xaec\x0d8.\xf3\xca\x8au\xe2\x01\xd9\xda\xaaC\xb6\x926u/\xe8\xdfl\x7f\xda\xb6Fs*\ne\xb1\xd6\x05\xa8\xf4\xab\xa4\xd7\xd66\xed\x1c\xe9\x05\xb6\xc5d\xa5KA\x08\x02\xbd\xb7~\x02\x9a\x06\x1a\x85\xdc\xa3\xed*I+\x1ee\xcbv=\xaa\xae\xaf]1f\xd3n#\x10a\xb5\xdc2C\xe3-\xea\xa0i\xf5\xd32\xaa\xaa\x82>\xdf\x8ej\x0c\xa2~\x9a\xc7\\\xc1\xb0[(3eb*\xdd\x11H \xa99?,\xbbdl\xa2zZ_(\xfc3u\x05\xcd\xe2\xcd\"M\x9dC\xea\xad\x04\x17f5\xce\xe9\xc9\xf1\xc7\x93\xb3\x8b\x97\xef/\xde\xbd?\xbb\xf8ptzzq\xf6\xe3\xeb\xd3\x8b\xf7\x1f/~}\xff\xe9\xe2\xe7\xd7o\xde\\\xfcpr\xf1\xea\xf5\xc7\x93\x97\xce\xed\xbfi\x08K\xeaR\x11\x15o\xb9\x1e\x0d+\xc0\x85\x1f\x94\xe0q\xa0\xf2\xf2^\x0f\x8e\xdf\"\xb3\x90V\xa4\xf6{\x90\xfa\x15\x9c\xe6\xe2\xc7Z\xad\xae\x88K\xc7\x86\x1d\xc8\xaf\x90[\x10\xe9\x9f\xacq\xd3&\xc5 \xe5)Z\xa6\x1f\x92\x8cl\x8b\x92SiN\x01\xd2\xc8\xad\x9d\xba\x9c}0$Y\xb9:*#\x1c\xe2\xee\xd9\xb8\xe9K\xc2\xd0\xa5\x96\x94\x8b2\xf6\xab\x17,d3\x92!\x01\xc4\x03\xea\xd5\xd7\x99[\xbf\xa8 V\xe4\x10\x0c[\xbc\x80\x98=\xb7X@\x08\x90\xc0PDo2\xca\xdbb\xf7OI\xea\x96\xfa\xef\x03\xf9\xd1\xad\xc9\xb0\x16\xe0\xb7]7\xa9\xe0\xc6\x0c{\xf4\xa4b\x8fn-J4\xf7 .\x0ef\xe1\xb9\xe4~\xfa0>rEv\xb36\x80\xda[\xa1,\x8a\x1b\xa5Y\x90l\x9dl\xda\xed\xe5\"r\xbd\x08\xa6$\xefX\x04\xdf\x96\xe8\xb1s\x1c\x06!\x19X\xe8\x9f\x8a\x037\xd7\x01xg\xa8K\xb6\xd2n\xb7\x14\x87&\x16\xf9e9\x9cm\"\xbf2l[\x8b\x14\x12\xa1\xeaJ\x99oU$\xa7\xbf\xaaN\xcc\xe2\xd5\x0ei\xe1\xbf\xc0\xe7\xa3\xb9\xf7\xec\x02\\\xf5-\xaft5\xcd+\xd7r\xa4\xcf!-U\xee\xeez`nt\xbb\xd0\xbcE\xa0\xf8A\x9aoz\x8b\x90\xf6\xbaE\x08;n\x11\xf4/\xfc\xb8\xdap\xb9j\x81E\xc9\xff\xd8\xad\x9e\x12\xd7y6q \x82\xfe\x1fmRp%\xaf\xbe\x1f\xe1w\xb9\x13\x1c\x159nC\xa1\xf7\xbf\x8b\x9c:\xe8\xbe\x1f\xb1\x9c\xf8\xa6fT+\xc5@\x1b\xe2p\xbb\x187$\x07\x9d\x0ed*\x96QnE\xd7V\xac\x85]\xb1\x16\xaa'n(\xc5 \xa1:F\xc9\x8b\x032\xd1\xf2\xb9=G\xf9~ g;\xe7\x03\xe9\xdc\x16\xe644\xb8r\xa9\xc8K5\xd7\x00\xc2\x9b\xe6\xfc4R\xfa\x1efUq\xbc\x94S\xfc_&w\x0f6\x95\xbb\xab-\x9eK\xc9hZ8m\xec\x10Rv\x8c\xfa\xbfD\xfcH7\x92\xfc%\xf5]\xd7E\x92v\x10\xe3\x92\x9e\xc2\x07Z\xda(F%%\xe2\x96\xfc5\xafH\x9d\x1ar\xab\xa8.\xb7B\xa4o\xcd\x15o\x17\x995+\xac\xc9\xc0\xda\xe6\xf1\xb6D\xdbf3#E\xc9Yi\xc1\x89P2\xea\x82\xdb\x8e\xee\xa1\xafY)\xc5\xd8\x90\xfd\xff\x96\x94\xc5\xee.f\xcf\xe4\n\xf8]\x19\xe4X\xda\xf2l\xaeg\xa3A\x9f*v\xc3\xa85\xfd\x90\xf0\xa1\x9dQ\x04Y\xbfv\x90\xd6\xd6\xec\x14\x1cGgC8;i\xdd`\x99\x0dE-\xc5\xe7\xa4\x06\xa9\xbd\x86\xf28B\x17V\xc7\xaa\xe0bU\xd0\x86\x05q\x04\x12T\xd8\x0fQ}M\xf0\"\x9a\xf6d\xdffg\xa5\x95\xbeg\xaer+h_DR\x1d\xca9;\xf9\xe5\xec\xe2\xf8\xfd\xbb\xb3\x93wg\x16G\xacD]1\xc3\xd0X\xa2 \x8bg\x0e\x07\xb8\xcf\xae\xbb\xbcR\xce\xd5M}\x17\\\xc6{UG\xe7\x19K\xca\xfaP\xb8\xaf\x03\xcc\x1d\xa4m14\xdd\xd8\xfe\x8f_\x07\xa7'g\x17o\x8f>\xfe\xf5\xd3\x87\xff\xb7\nH\xdeq\x1c\xdbVCf\xf8\x16\xbc\x1dIp\xdb/\xd7\xcf\xc9\xea\"\xb4\x8f\x1aG\x14\xb5\xcd\x87v\x9c\x809r6W\x89\x19Wz0\xa5\x92\xa0\xb0\x9f\xcf\xe2\x1c\x84\xab\x97V\xe7wp\x0c\x0d\x0b\x973\xed'\x1f(6\xb5\x83\xf8\xdd \xcbn\x90\xb5\xf5\xe6B?\xb0\xe1=\xa9*\xddZ\x15\x0cC}\xcb{\x9d\xe4\x00Qc\xb3\"\xeav3\x99y=\xe8\x02\xf1,\x04E8\xf3z\xa8oIU\xad\x059$\xee\x1c\xa4\xb9su\xe4\x97\xc1cVC\xb2\x1eB$\x9e\xc1@\x86\xe3yK\xb3\xe5xE\xaf\xdd\x95y\xc0\x0b\x80!Y\xd5\xce\xfc\x18|\xf1\xad\x80\xb1h/\xabB:\x95M\xb8(\x11\xe8\x91\x04s\x17CBg\xcbs\xdd\xa2L\xd9B-\xb7\xb7\x07C\x12\x0b\xf2b\xad\xf9|\xed\x81\xc7E\x9c\x7f\x98\x8f]\x7f\xab\x9c`>h\x1a\x03zR\xbaUk\xb2\x89\xf5]\x980\xc2g\xde\xf9\xa0\xcdm>\xf8?\xd2\xe8}^\xfa\x0fi\xd2\xb5\xcdK\x17\x82\xf6\x00\xc3\x7f\x91\x95\\o=\x087<\x05\x9b\xe7^f\xfah\xb5\x84\x9c\xec\xd3\x81bA\xf6vLF\n7\x05\xe6\x92|!\x80\xeb\x96y\x1d\xa8\x98\x94\xf4g\xfb\x9eU'\xef\xdb\xf7?\x9d\\\x9c\xfc\xf2\xfa\xf4\xec\xf5\xbb\xffl9|\x89y\x00w#?\xe3\x1c\xae\xf4\xa9\xbb\x94{\xcd\xae\x11\xaf\xac\xc7E\n\xb1L\xed}\xcd\xeb\xc7\x13\xd8\xc3\xef\xde\xbf<\xe9;\xab\xdd\xe3\x7f\xd7\xfd\xdbB\xa2\x93\xfeT5\xe9IY\x93\x8em\xdbkV\x9bg\xf8-$a\x85\xc5w\x95\xb4H\xd4\xa9b\xe0\x05Qe\xd4\xbbm\xe6Q\xd5s\xcd\xe9\x0b<\xf8\xb0\x19b\x8f\xe1w\xf0\xc4\xde\xfcH\xbaBl\xb6\xf4O\xf8\x9bEt\xedA\xea\xadD\xd7\xa5\x9b'\xd4\xd6W\xb9\x17\xa8\xfb\xe1 \x86\xa7\xae\xfa-8)\xa5\xdb\xbb\xbb{ \x97\xde\xdd\xdd\xad\x0b\xb4\x89\xa1x\xb6_\x1b\xb4\xdau91\x85\xccy\xc7\x81\xbfV\xb6\x1b\x86\x17&\xd60Z$\xe6} \xa8\x89H\xa1\xb7\xb4\xb3\xe7\x82^i*\x89U\xc7FV\xbfu\xa0*x\x0fN \x11\x15\x0f\x81=.N\xde\xfd4%N\x9cp?\x87^ \xe8\xe4\xe7\x93\x1f>\x1c\x1d\xff\xf5\xe2\xf5\xbb7\xaf\xdf\x9d\\\x9c\x9e\xfd\xfa\xe6\xe4tJ\xb6&\xd5F\xd4FJ\x8b\x0b\x9b\xdfE\xa4\xd8\x1b\x13M\xfa\x8e\x8a\x0dL\xb5\x80v\xb9j\xdd0\\?Z\xbc.>\x9d\xcb@\x01\x1b\x88\xf1\xda\xba@\xa1\xc2\x14\xa2U{\xe0k\xd7\xde#\xf0\xe9\xd1y#+\xf8\x9c\x0e\x9e/n\xf1\xbd\xa4\x1f\xd4\xba6\xee\xcd\xf3 \x06\x15\xd8%\xb8\xd8b\xb3\xf8\x1c\xb8\x0d\xbf~G\xda\x8f\x1d\\\x83\xf5n_k\x1e\xbd9@?(p\x97C\xb2\x1e\x0cH2\xae\x07Sq}`\xc3\xf2!\xf8b\xca\xa4\x1f\xa2\x96\xb1\xd3O\x0f\xbfJ\xfa\x91*JTV\x9dT\xa8W\x1f\xdc.\xd4\xbd\xa2\x8a6mM\xfa\xc4(#\x06w\xcd\xdd5l\xfa~\xa5TOW\xfd\xa0\xc57\x16\xd0\xfaZKW\xf5\xa5\xdb\xaf\xbeH\x8a\xcf;\x98Z\xd2\xca\xd8\xb6\xe7\x96k\x9c\x0d\xc8V\xc3\xc7[\x0cV&\x80\xf8\x90\x05.\xcd\xf5\xc1[[|.\x98\xf5\x8d\xa7\x0em\xd7]Y\xdc\x96\x13\xbdj(o\xf1vG\x88\xc5\xe3]\xd4\xb9\xa55r\xc4O\"\xf3A\xc6\x84\xa3\xb4\x8c~\x90Q\xa9\xa4\xd4\xd0\xb1I5\x94\x17|_\x07\xca\xb5\x8c8\xac\x1f?V\x13p+z\xa2\xf3*\xdc\xa2d\xd7PV\xa7\x96\x8bs\xa5dW\xf7\x89\x99*U\xbd\xba#\x80P\xb5\xa5\x9e\xeeU|h\xee=y\\'P\xe68\xe5\x13\xcb\xfa\x1a>9}Y\xdf\xbe\xa2w&\xf5\xea\x96\xaa;\xf5v\xacK%\xfbzO\x05Z\xaa9\xce\x14Xd\x17\xbb\xd2\x07\xc7T\x7f`\xb7\xf2\x97\xe8\xca/\x15H\xcb\xe5rS:\x7fU\xd1 M\xdf\x15\x18u\xc8\xc8\x01 \xc5\xbe\x96:\x89xX\xe8\xc6\x02\x85\xbb\x0b\xe9\x94Z\xaa\xf7(\x12^*\x97Wbf\xd5c\x0d(*B\xf5\xa9\xa2\xb5_]\x82\x17\xcd\xb1\xbbB\xe9$\x8fGi\x96\xe4^\xaf\xebALM\xcb\x88\xf3eq\xf7\xeb\x89\xad\x9c\x06\x19;\xbb\x89YA\xf4\xcb\xbc@i\xc6\xd4\x92\x8d\xd0\x8f\xcd\x8c\xca%l-_\x0e\xdb\x0f4\xf3\x96\xd2\xffZ-?f\x91\x1fD\x8b\xb2\xedH&h\xd6\x80\x03#<\xff\xa3\xf4\xb9\xa5\x15\xeb\xb6&\xb5\xfcW<\xf1\x98\xbc-\xa8dk\xc1\x9f\x18!d(\n\xb9\xa0\xc6|\xb5|\xb5>j\xa9\x80,\xdf'r\xb1\x16C\x9e)\xafOJi \xef\xc71\x0d\xc3K\xea}N\xeb\x1f\xa2ah4\xe3\xe7 \x0c?I\xa4\x0c\xddi\xac\x0c\xabZD[\xe46\xab%z\xbd\xb3\x1c\xed\xe9\xc5\xf66\xbaV\xb2\xd6\x85b'\xdd\xe9\xd0\xb8\xf3\xe9\xaf\x83G\x14\xe6U\xe3\xaa\x14}\n+\x11{!\xcf\xf61\x1ce\xe8g\x0eJ\x82\x0b\x96\xc9\xe5%\xbdl\xb5|\xc6o\xf5\xbeS\x7f\x14v\xd9r\xb7X\x89\n\xc1\xfa\xd8x\x1f\x07)\x04\xbe*f\xb7\xe5lv\xbd\x96\xb6-\xcb!\xd08\xa8B\x08I\xca\xd0F\x13\xfafD\x86%1LV\x97\x1ay\x1f\xf6\xf2eF6\xe8\xf8\x87\x9d\xe9\xb3tl\xb2\xeb\xb6N\x05\xd2\xb8!\x91\x1e\x06b\x1eD\x99-\xa0\x07\xee\xaa^?E\xd4Vl\xa5V\x9b\x83#f\xed\xda>o=\x0e\xc6 \x97\xa4\x91K\x07u\x1c\x86\xee=7o\xd9\xf9\xa0\x96]\xadC#\xa7\n\xdd\xf0\xc1(Y/`2\ne\xaa\xc2\xc2\x83\x016\xbeV\xba\xb2\xc9bo\xed\x808\xa2\xd2\xeb;\x0fu\xdbZ\x0dn\xb9\x1ao\xb5\xf8\x8aq\xd6\xe3f\xa7IZ4_\x83\x12\x83 \x8a\xb8@|.\x96\xe1v,\x87\xa0\xc7\n\x08\xf4\xa4\x07\xe5<\x0f\x86\x15\xc1~\xa1\xaan\xce4\x90\x0543&\xdc\xb5 \x03\xd7\xca\xe5\xbd'\x90\xb78\xecQ\xcf\x18\xa4\xa1flp0H0,b\x08\xe6\xcd\x81\x07a|\x95|\x02i8\xdc\"x\xe3\x93\xb7\x1f\xce~m\xbf>\xb2,hI\x85\xcc\x11\x15\xdeD/\x92*\x81\xbe\x0cB\xdf\xa0\xd2\xb1(\xde\xc8z\xec\x1f\xd2\x8a\x187\xb3\x15\xb1\x9f\xa5\x03\xbd>\xbfi\xf4+\xa2E\xf0\x96ov\\\x02d\x8dmc\x97\xdcII\xbf\x87q\x8c\x0f\x1e\x90\xad\xac\x8d\xa7\xecs\x87\xd0\xc1\x92\xee\x0c\xdb\xef4\xf4S\xb9\xb8, \xbam\xe2\xa0mw\x07\x1d\x01\x05\x08\xe8w\x07\xd1\x9a\x7ff\xff\x99\xd3\xc4g\xbe\xe6\xa9A\x05\x00\xadU\x9a\x93e-!E )\xac\xd6\xf1*\xda\x82a\xd9\xb6\x08\xe8i51\xbf\x05\x1c\xd3W\xba\xa5\xd8\xa2&\xe1\xf9\xf6\x14r%\xdb&\xe3h\x95\x03\xe1\x92\x16\\\xb8e\x93\xb4\x84:p\x99\x8dE\xec\xb3\xe5/V4\xfd\xac\x10U\x9f\xed\xben3\xa7\x04\x1eVuM\xcc\xa3%\xec\x07\xf8\xdb-C \xc4v\xfc\x8e\xf9\xc1\xd6O5~N6 \xd1,9o\x0d`c\xf5\x14\x87\x8dKU\xd2\xb2\xf9\xd0\x18\xe3j=\xf2\xf4\x99\xb3Q\x83\x8c\x93\xa5w\xabL=\xfb\x8d\xa4AM\xca\xc6>\xa5\x81t3[6\x8f\xe8\xe8\x0c\x8d\x1c\x19\xa8\xa1\x0d\xa1VC\xf0 \\\xb5\xf2rpl\xac\xb6\x82\xa5~\xba9K=\x90\x1f\xc2j\xd5B\x8f\xfd\xcdj\x15g\xbe\x1d\x89\x96.w\xbf\x02\xdf\xdb{\x0f\x13\x83\x1d\xeb\xb5n\x80`7;\xd4_\xab\x0f\xf3\x81\xd1H\xaa_X\xf7\xaf~]Q\xbd\xef{\xe5\xceM\xa1\x9e\xe8T\x1b9\xd9\x86\x84\x95\xdeCyP\x011\xc7@I\xaa\x9f\xaa\xa4b\x1f\xe4\xd9\xf0z\xfe\x8e\x89\x0dJ\x93\x9b>\xfb\xb2P\x8e\xc1\xdayH\xe6ME\x80\xcc\xb0\x14\xab\xc2\x0f\xcb\xfb\x11M\xc7\x97\xce\xa8\x0f\xac\xa7\xe1\x97/\xf6\x83\xee\x10\x1f\xa3\xf2;\xd5\xd9jO\xad\\;\x99M\x94 \xb6\x1b\x95>SPk z\x0f\xd0a\xfdI{\xe2\xb8\xc8\xf4\x97 0\xc2\xde\xa6\xa2\xbb\x16\x16i\x08\xbc\xcc\xd6\xa4m1\x17D\xc3\x81\x0c\xd2\x9b\x83\x11\xb8N\x9dJ\xd7[jF\xab\xf7\x04\xc1@\xd5o\xd3\xbeX+\xc7&\x9dW\x11\x10\xe2\xd8\xe6\x1d\x88\xc0\xd5#X\xe5\x03\xeeW\x9f\x1cJ\x17\x98\xb4Ji~\x94\xeb\x1b\xbc\xa6td\xbb\x9e=\xa6\xd9Z\x07\xfe7\xfb]\xe1r\xa1\xb0\xbdGq\x8bw(\xeb\xf6\x80\xf8h\xe3t\xc9\xf3\xb0$K\x8b\xad\x13\xc3\xc4\xa0\xb9\xa25\xf3\xa1\x8c\x82\xacg\xb5\"\n?8 \xd2\x8c\x03\xda\xe5\xbb\xe1\x90x\xb0\xac\xb6|\xf1E\xd1\xa3!\x99\x03\x9f\xde\xbe{\x86$&\x87\x9a7\xeb$e\x01\x91\xd5\xdb\x1aI\x9d\x19\xb8(ab\x17\x81\x95 \xb6\xd5\xc57\x9b\xb4m0$\xb4\x10\xea{\xe2E\xcb$\xe6Cc\xe5\x1e`\xa6=-$\x909\xbb=\xd5O*|Y\x0f)My,5\xd0f\x1fb \xe1,\xect\x93\xb5\x08\xc6m \xcc\xccVii\x11\xb5]dHGo\x0f\x1e\x90\x89r\xa4+\x1d\xc6\x14\x85\x93\xd9\x8e\x85p6\x88\xb1\x03E\xb2\x08\xfc#\n\x88sF~T\xb9\x84\x13\x19\x132%;\xcfI^\xf1\xee\x96\xb7\xfb\xc5^\x1bf\xd9v\xb2\x89\xbbtH\x1c=\xe5\xa6'\xc2\x94\x1c\x92T\xea\xd8H\x8dE\xb9\x1c\xa6$\xbd\x05e\x85\xf8\xbf\xc1\x96#\xbakn\xa1y\xad\xaf\x87\x87\xda\x13A\xdfe*\xb0\xf1\x0f2d\x9b\x1bV\xee?d[,8\xd3#\xda\xe3O\xa8%\x809\xbc(\xf4\x02\xbe:\n\x91\xe0\x90\x845\x19\x81D \xe07\x0b\xc9(\xee\x03p\xaa\xc0\xd4\xe6\xa8\xa0\x8a\xb0@\x15\xd9P\xb7E\xe2\x95\xd0@\x15I\x15\xef}\xac\xcb\x06\\\x18\xe8\xa1\xec#o\xbf2\xc2\x86L\nO\xc2B\xe9Ut\xbf\x1fv\xb24\xe8V\x18\xaa).iEU\xd1m\xc8g\xbb,\xb7\x1d\xc5\xd9\xa4\xd7s\xe2.]\x10\x95\x0f0\xf2URb\xacMP\x9a\xd9\xa4\xc8\x1d\xca\xac\x1a5U%\xa16{Y\xf1 r\xaah\x88\xbb@\xd7OS\x92\x8d\xb9\xdb\xd6Ou\x1a\xbb\xa5\xd9d\x03\x896\xef'\xd1&-\xb2\xba\xd6\x90\xac\x9a\x18\xc4\xc4\xdd\xc5\xfc\x95:1fJ\xcd{E\xdbT\x8bm\xda\xddp8\x0d\xc5\xf0\xfd\x1cdK\xe9]@\x1c\x01!\xca\xa2\x91\xdeR/\xb4\xe2\xfe\x9c+\x1d\xe3-c\x1b\xd8\xd9Y\xf7\x9fy\xb9\xfb>i\x8az\xda0\x08\xeb\xc9\xcb\x14\xc62\xb2\x11\xee\xddZ\xdc\xb7q]4P\x95\x14\x16+|\xd1F2\xe4c\x85\xf4T\xa7[VS\xeb\x95\xafx\xba\xaf\xb8\xd0iA\x06N?_\xc9<\x88h\x18v}\xd9\xec\x05\xca\xf5\xea\xa7\xd5\xf9\xec\xad\xdb\xdf.*\xd5\xdaA\xcc\xd0\x0eb\xa8v\x10+\xb5\x83\x9em\xc8\x16\x0f\xfbI\xb2h\x96Qo\xf9\x91\xcdos\xa2.X\xf6!\xbf\x0c\x03\xafp\x94f\xe9\xb9\xe6\xf2#\xcd\xe5Ov\xda\x18w\x194\xa7w\xedn\xa4\x14\x99\x0e\x0e\x80=\xd3\xaf\xe4\x8f\xaf@I\x8b\xb7\x81\x0c\x04\xd7\xcbv\xc7g\xc8\x98\xd8\x06D\x05\xd5\xb3\x8d\x07||\xc6\xce\xfb|W\xcdl\xdf\x8d\x7f;\xe1s\xf3~\x10\xcc!*)\xe3B9\x86[\xdcQ\x15\xa8\xae\xa6\xae\xa6l+j\xa9\xacPbS\xf9\xfa\xb5\xaf@\xaa1\xb0\x1b\x8fQ/\xcc\x8d!L\xedc\x02\x96\xf0\xb4\xdf\xa6\xb2\x93\x19\x88\xcd\xaa\xc56R*X\xdd\xc9\x96a\x82\xd7l\x1d9\xcd\xb2no\x17\xc9_\xef\xde\n\x94\xb1<\xbdY]rp\xc7*\x7f\x8d\x057\\ys\x9dD\x8c\xdc\x98\xc9U\xed\x00\xba{\xb23\xd9\xd9\xc3{\x95\xfc\xb3Z*\xa3s\xf2\xa4:\xed\xe0W\xf3\x7f\xffo\x9dy\xeb8\xcc*\x04\x0c\xa8\xe6\xcd\x92s\xd8=3~^\xc3|\xe0\xb3\x1dkmy\x01X\x0f\x0cp\xab\x91i\xb1\xb2\x95V\xb2\xcf\x1b\x9d\x90F4\x9b\x19\xc7\xf2\x0e%;0_\x12CR\\Y\x19\xc1\x12\xda\xf6?\x18/\xb53^\x86^\x0e\xb7\x9a9\xed\x0c\xa5\xa9md\x1a\xdf\xba\\\xda\xddvG\xb8\xaa\x0e\xd2\xbf\xca\x04\xd7\x16\xdc\xd5r\xda\xe3\x96\xb4\x08\x02m\xbbS\xd6(\xc5\xd57@-\x8e\xd3\xbf\x891\x17\x1eb\xe4I\xdd3\xba\x0e1\xf2\x14\xb1\xe6*\xcd\xad\xf6'\x0d\x07\xa79x\xa4\xaa~\xbai\xd9\xacd#\xd5S\xabb\x1e_\xfc.6E\xd8D\x12p>%L9\x8f\x0d~g\x10\xef\x97\xaa\x1a\x87:_\x90\xaag\xfc4\xa3Y\xe0I\x1e\xca\x10\x0f\xe5);6\xa3\x19\x9b\xf2\xd0\xbc\xb4NP\xea\xe5\xb4\xd5k{\xd3\xdd\xa9\xe0\xe2\xcb6)\xe5\x8a\xb4\xe3\xb4V\x8b\xa4\xea!\xa8v\xac6EN\xfd*M;*5\x0c2\xfaUX\x1f\xa8\xb6\xfa}\xa6\xa9\xa8\xda\xccW\xc1J\xed\xcfV0\xad\xe6\xd9\xb2\x8a\nP7,\x0d \xc03\xaa7\x18\x12>\xa6\xbe\xff\x81\xf30\x88\x16g\xdc\x0dk\x18\xe1^\x1c \xef\xee>2\x10\xbfD\xfa&\x14o#@\x8a\xb5\xcf\x9a\xe7\x0d\xa9\xc5\xb8o\xe1Q@\x15\xc6eD\xd3|p.\x0eH\xb6L\xf8\x15\xacjA\xd8I\xfd_\xe7\x98F\x11\xcf\x88\xc0<\x84\x12/\xa4iJhJh\xf1%\x07\xc1\xee\xea\xd6\xb8\xd0\xb5\xca\xca%/\xce\x83\xea\x92\xa8\xce\xa1\xa6\x9bM\xf3\x14X\xd3\xac\xdb\xe6G\x9b\xbb\xd4\x10\xfb\xb0R\x9dB5Z\x81\xaa\x8e\xe9-\xf2\x97z7\xc6A\xfa:\xaa`\x17\xe0\xdc\xea\xb5\xe3\xb2\x19\xbcE\xd5k\xb2\xf6\x9en\xd8\x1c\xa3\xea\xba\xc3w\xbc-\xb5\x0b\xa1\xceU\xb5a{\xcc\xea\xdd\xa6\x1e\n\xde\xa6S\x96}\xab\xf6\xe8\xaa-m)1\x88\xc9a\x9b\xa8\x81\xdf\x07j\xb0\x9c\xc5\xfb\xb6\xb3\x189\x8a{\xac\x1a\xe4\x0e\xb5f\x87\xfa\x8e\xfbu\xa5\xc5[\xdb\xad\xfa|%\xf5\n\xab\x83jbbjb\xe2j\xa3\xbb\xcd-\xad\xbeb\xa8\xbc\xa0\x08\xfcc@\x1e\xc9\xf6v\x93\xf8\xaa6\x91\xa2\x9d\xdd\xd4\xf0R\x0b\xec\x1d\x02\xec\xd9\x88\xad\xe2\xecfJ B\xa5\xf1\xb9m\xe2\x10D\x0bW\xfa!\xa8\x93 m\x14|*\xfb\xc9\xaf\"\x96\xbc\xe4^\x0e\x12\x0e\xe55\x89\xaf@HfSb\xd06\x0b\xe38a\x1e\xf5\x96\xacP\xe5\x967P\xdcEn1\x9b\xf2\xc0\x9aT\xb7FX\x1d\xca0^\xceo\xd7{\xde\xd6h$\xc6!\x17\xbd\x1f\x8d~\xbb\xdecNm\xaf\xd5\xce\x02\xab\x8eW\xf3\xf0\xef\xaf\xc4^t\xdb\x1a\x04\xba\xadQ-\xda\xea(\x930\xce\xa3\xea\xd8\xd6j/qK\x8d\xda\xa0\xf7\x82R&\x15b\x03\x0f\x1b\xc0Q4\xea\x14\xb8\xc0\x01\xe7\x19J\xd0\xba\x07\xd1]j\x99\x99\x91Y]k\x86\x07\x0eP.\x06\x86\xf39\xe1\xcfI3\x80\x1d\x89\xea\x9b\xb4\x12\xb5{G\x1a\x03e\xcf }\x0e\xbfh\xb5t\x80\x96~N\"2\"\x01\xf9\x9e\xec<\x1f\x80\xbc\x8bU\xaf\x91\xa2\xd1\x08-\x16\x90\x11\x89T1@\x04\xd5b\x01ZL\xef\xfe\xe89\xc9G\xa3\xe7v^\x1dB\x02\xb71\x8dHK\x1b\xad\xb0\xac$R\x15\xa5\xff\xa9 a\xae\xb3j\x0b\x83\xf4(\xf2XZ\xa5\xc8m\xa7\xacm\x89$\xc9lr\xbe\x89\x96W\xdb\xdc\xf5gIk\xea\n\x06\xea\xb5\x88\x08\xda8\x07i\xe8\x88\xec\x0e\xbcS\x05\xd1\x01*\xf1v\xa6x\x1c\xb1\xeb\xec4\xb8\x0c\x83h\xf1\xdcJ\xa7\x93\xda\xc5X\xa6\x14Z\x9e\x14\xd6q\x12\xe9\x0e\x86d_2A\xe3H\xab)>x@j\xf8\xcc\x80\x90\x11\x0d[\xbeJ\xcaE\\\xc7 \x16c-\xfd\xb4G\xe0\xb6;\xd3\x94\x04\x981,=\x17\x8d\x9e:A\xe1U\x0fx\x1c\xab\x9d[\xcedVWa\xba\x9b\xa8\xe2vD\x81\xc0\xd0\xb7\x15q\xdc\xcb\x85\x8aEj\xfa\x08'\x07\xf1\x1bL\x19h\xb1:x\x16\xef\xcb\xfafqJh\xf3\xb0\x15\x83\xd7\xb5\xd7 (\x02\x07)\xd8\xce\x04\xd1B\x85M\xb4\xb8\xa0k\x9b_Qfv\xdb6\xf2\xf1<\xcc\xd3%\xb4\x82)-\xf4T\xaa\xa1\xf3\x86\x04Gv%+\xbb!e0\xc9`\x08\x85A\x17m\xee\xd6<\x91}%W\xcb d\xc4\xadKT\x8cX\x82 \x97\xe1\xe4E\xa5n-b\xe1 \xa1\x81\xc5Qd\xce\xf8\xf9\x90,\xc7\xcaC\xd7\x99\x9a\x03\x97U\xa6C:\xb53\x87j\xd8\x18;\x1c\x17\xc7v.\xde\xa6\xa9\xd1\x18&lu\x18$Du\x81\x18\x19\xf5\x01h\xde\x19\x96M\x06n\xb1\xa2\xaa!\xf8\xc5qv\xc5\x8f\x92\x05\xf0\xb5\"\xa7\xe2dx\xad\x1c\xefW\x1b|\xc1\"z\x192\x7f*0d5\xa7:\xc4X\xdc\x95\x9f_\xbf{\xf9\xfe\xe7\x8b\x1f\x8f\xde\xbd|s2%\xc1\xd8\xa3\xd1\xa7\x94\xbd|\xff\x96\x1c\x92\xab \xf2\xf9\x15\xc1\xca\xa5,\xfb\xb1Vy\xbb\xe4\xa81\xe1bQT\xc7\xa6\xf1\x85\x13\xdd\xb1\xce\xaa\xd5\x10\x88Sb\xab\xb5\xd6 mV\xdar\xfc\x96U\xb7U\x9a%4\xfeAJ\x1faQ\xf4\x13V\xeb\xdb\x0drH\xf8X\x06\xf0W\xb1\x89\x96\xa0Z-\x0e@\xa8N\x124r\x99\xb1\x81\x16\xd7v5\xe8X\x892o\xdb\"%\n\xbd\xaf&\xadx\x14d<9\xf5\x12\x1e\xca\x88\xe8]\xd3\xaaQf;\x94x\x98\xeb\xb9r\xad\"\x8e\x9b\xbeV\xdb\xda$<\x8a\xc1\x97U\x0c\x89\x93B#\x1dD\x8d\xa2\x8aN\xcc\x11\xe9)\xd3(\x17T\x1b\xd1$0f\x0c\x86\x06\x02\x05\xb4\xc6\xeei\xb7\xcfI\xc7U\"\xce\xf5\xedr\x81\x1eF7\xf18a!\xa3)so+\\(\xde,$\xd7\x12RoEr\xf5S\xc1.\xc4`?K\xe4\x067\x1d\x86\x0eY\x91q\x88\x8c\x03\xc4\xc5\x8a\xe9\x82\xfd\xf2~>O\x99\x0c\xd82\xf6\xb5\xc6\x82\xfe\xa1m4\xe4:z\xc3\xe6\x88\x00\xf5FW\xf5\xeb\x06U\x9d\xf1\xaaX\xf0+\xc1\x82\xceC+;\xbfm\xa9\xf1O\xd5_\xb7\x9a\x89\x92\xf8\xdd\xaf3\xaa\xea\x9acb!~\x1b\xd7\"\xed\x81\x16\xf6\x9e\xe0\x91\x16&\x8f\xeb\xf5\x84\n\xbe\xde\x1e\x0f\xa7\x97q\xbe\xc9\x10B\xd0q\x10\xfd7\x83qi\x8e\xef\xcb\xf7ou\xfc\x8d)I\xda OVqvcT\x9b\xb7\x02\x0b<\xf3!\xcc\x17A\xf4c~)\xb8\xdf~\xc0\x9f\xb2 L\xc5\xd9\xde\x05~\xb2\n\xb2\x8c%S\xf0\x9bg\x05\xfd\x11t\x88\x8a&\x87m\xb0\x05\xef\xe8\x95P\xd5\xf5\xf6/\xe0\xbc\x1e\xd7\x99\xa6\x00g\xb1\xa8e-\xa9\xb5\xf7\xb4\x9e\x9eV\xd4\xc8'\x8f\x9e\xd6\xd5\xc8\x15\x17\xb6[\xff\xbe\xd7-\x03\x01\x8e\xe0\x94\x85r\x08_G\x82\xd9\xa5\xf8\x98+\xd9H>N\x80\x16eE\xa9\xea\xc0c\xf1\xb9\xcd/v\xca\x7f\xb4\xbc\x97\x8e\x0b\xa2\xaa\xc3&\x92\x8eK\xa2\xce\x85X\xe3\xbd\x0c\xad\xea\x02)+\x1dP\xa9\x1f \x94S\x17D\xddu\x04\x94\xa4\xa8\xa2\xb0.F\x9da\xc6\xad=:\xb6\xd1w\"\x9e\x05\xf3\x9b\xa30\xc4\xbeU\xed(*\xf8B\x98\xfbv\xc9W\xbb\xe5Aa^Pk'\xa8Q\x94\x94Ldx\x99D\x8c\x14\x0c-\xd5\xca\x86\x8e\xef\xd5\x06\xc1\xab\xad\x83z\xc5\xb7\xb2A\xc0:\xdf\xf1\x9d\x8d\xcd\x12Z)l\x9b\x81\xc1&\x0d\xae\xf8\xa8n\xfb\x18b\xa6`W\x18hl\x11\xed\xca\xba\xa1\xc6]y\xed\xcd\xae\xf3\x82,\xc5>7\xb0.\xcc&\xcfR.\xbf\x12\x91%\xee\xdc\x14)\xa4C\x12\x0f\x86$\xa8\xf2\xee\xf3\xba\xe1\x15\x14\xbf\xe3\x01\xd6\x90\x05*]\xea\xddz\xdc\xa7@\x1dl{\xa8\x18\x8f\xb6h)\x94\xd78\xdap[*\xa8%\x96\x8d\x98KO\xe6\x85\x90\xe0\xc1\x03\xe2\xa4\xfa\x80\x01\x85/M\xb9\x8a\xac-\xd71\x8f-\xc8W\x8cZ\xf3\xe8l\xce\xeb\x82e\x928N\xa7$'\x87=N\x00\xcd3\x16tt\xd16u}\xff\x91F\x8b\xd6\xa0,`\xdb1\xce\xd8u\xa6d8vP\xb8\xb3\x1d\xfby\x1c\x06\x1e\xcd\xac\xd7\xb5 \x84\xaa?\xe3\n\xcb\x9dI\xb7\xa6C\x92\xc8\xd3\xca\xff\x00\xbb\xcd9\x89|@\xaaI\xe6\xd8\xb9=-rK\xcc\x16\xb6\x9e\xb9-\xbc\xa1\xf8VC\xed\xcf|X\xe4OA\x03\xa5\xe9\xf7\x95\xe0\xcc\x1e\xe9\xc2\x07\xc4\x98$\xb9\x12*\x84\x8dX4H\xb2mh\xe5-\xb1`\x9dv\xd4-k\"\xe6\x174mz\x86\x05\x95\xf3M#o\xc9!\xdep\xd7tKH\xb9,\xed\xb0\xd2\xb7\xc1\x9c{y\xda^iP\x02v\xd5\x99k\x7f \xb0\x86\x8f2\xd7\xe6\x91\xb0]$\x90\x8fa\xe2\x0b+\x80\xe2\xeazH\xf21\x8b\xfcf\x06>\xf9:XC\x9f\xd8=\xa8\x07\x00\x82.!b\x98\x04P\xb723\xf5\xd1\xaf\x8cpu\x14\x07\xe4\x90\xec\x10A\x04g\xfc\x14\xd40\xdcA\xe7~\x0eA\xf2\xee\x85<\xd2h\x02\x1f\xdfPa\x15\xf1]p\x06\x12e)\xec\xe8P\xedh\xb7>\xc6C=\xea\xaau\xf6\xe5\xe8)\x0d\xa7z\xf9\xd0,/^\xcd\x99R\xef\xd5\xae\x87\x9bt]\xf0\xbb\x1e\xd9&-\xee+c\x13\xadV\x90)\xde\x9bX\x0c\x06\xe03W\xb94\x8b\xf5\xf0p\xbb\x03#\xad\xd2\x14\x8f=\x1e\x864N\x99%`k_\xf4\xe6\x8bs\x83L\x89\xd7\x81\xe6\x04\x9c'\xd0W\xcfu\x8a\x90\xf3\xa9\xf5\xb8\xear\xb52\xd4\n\xcb]\xe7V\xf7icX\xbagbQ\x90CIL\x00\xf2\x801!\xd3\xe2\xd7\xf7\x05\x8c+\x01X\xe4\x0f\x15\xa2\x03\x08\xf0Zi\x94\xd5\x99,\xf2\xc1\xd4\x14?\xd9d\xba\x9c{\xc7[\xd2\x84z\x19K\x1ci\x19\xce[\x8e=^\x14\x16\xcb\xa4R4!\xa3\xa2\xb8\x18\x1a\x8c\xeb!=\x84\xb0D\x1d\x1b\xc8)\xd3\x86\xc8\xf4Q\x81\x1eN\xf6\xa5E\xd4\xb9\xc1f\x81;8\xef\xdc\x86DI\x1d\xde\xd2l9^\x05\x91[\x0e{\xc7G\xf2\xaa\x93\x03=\xad\x94L\xcd\xca\xe4\xf4\xb6\xa9\x95\x89\x035\x1a\xb3\xebL\x94\x7f\xf0\x80P\xf2=i\x0d\xc7C\x0c|\xdd\xe2\xa0\x8d\xa86Ri\xff\x92Z\x01\xed\x9aJZ9\x15\xb4\xd6i\xc7xx\x1a\xd0f7FTo\xc1\xe9\x87\xd7\xa7\x87\xf3\x0d\x11\xa0~\xe6%\"\x0c\xe1L\x15\xe8\x9aK\\=\x04\xc7Eb\xc1\x1f\x85!\xd4\x96\xba\x10/\xe8{\xc0 n$\xb8\x0c\xf9\x959\x00\xcb\x99q=U\x91\xa7+\x82\x8d:\xd7\x08\xb6\x91-\x8a\x1a5\xe1\xc2{b\x1d\xfeN\xb1>.\xc5\x93\xb3\xbc\x11\x13T$\x17\xdcKbWB\x00\xe1\xfdx\x1e$\xa9t\x91_(\"\x18I\x95\x82\x9a\xdb)\x12\xb1\xdb{n\xff\xa0\xdd\x16\xca\xd4\xa0+\xf5\x1a+\xea\x86\x8d\x82\xb2\xad\xa5\xeaCuH\xff\xd4\xfc\xd5\xdb\xb3G\xc5`-\x01\x9cl\x18\x9f\xed<'\x91\xb5'{\x92\x13,\x88\xbf6\x1cJ\xc1i\xed6\x89\x80\x1bQ\xa4\x90Fr$ /\x94\xea$%\xdf\x9b\x86b\xf6\xad\x16\x81\x96)\"\xd3\xd4\x8f\\\xceS\x92\x91\x11\x12\xa6\x8a\x90FHi\xfd\x04\x851b\x05\xb8\x91\"\x07\x8c\xbb\xd1\xe0\x9b\x9a\x7f\xec\xef\xedX\x8c\xb0\x8be(\xd5\x9c,\xfc\xfa\x96b{\xb6\"\xb0\x01WVe\x11$%n&\x13\x137\x1a\x14\xfaR\xc6:\x13\xb8\xc2\xf1$\xf1\x98*\xbb\xb6C\x88f#\x93D\xb1)\xd9\xda\x92\xf1mhR(\xda\x7f\xe0i\xa0\xb9\xb4\xad-w\xf2\x84< V 1\x84\x0d\x15\x8d;\x0f\xdb\xa4c\xd8\xac\x17~\x80F\x1e< {\xe0\xe9\xa6\xc9\xdb\xdc\xa1}\xfd\xda\xa1\xb9^\x97\x899\x19W\xec+\xe0\xf2\x8fL\x8b\xe3e0\xf6\xd9\x9c\xe6a\xf6S\xc0\xaeD\xa6$;Pd\xb6\xe5nI\x17\x83\x16_Qc0\xba9\xac\xder\xaa\xd4)\xeak \x84:\x118D\xaf\xa4W\x95\x9c\xa5v{\x13\xe0\x1d]\xb1\xfb\x9dwg\x99e\xf1\xf4\xe1\xc3\xab\xab\xab\xf1\xd5\xde\x98'\x8b\x87\x93g\xcf\x9e=\xbc\x0e\x83\xe8\xb3\xd3\x94\x90!\xf0\xbf\xbc}#\xca\xec?\x8c\xe8\x8a\xa51\xf5\x98\xd3\x94\xa05\xf1\x12\xf5<\x16e?\xb2`\xb1\xcc\xa6\xc4\x91\xaf\xa3%\xbc#>\x9a\xa8\xe7\xe5\xab<\x04O\xd6;H\xb6\xef\x07Y\xb0\xb6d\x86\xc1\"\x12s\xff\x03MY\x18DL|O\xa7\x8d.U\"\xf6\xd10\xe4W\x1f\x19O|\x96@\x99\xf2\x15\x85\x8e\x97\xf4\x92e\x81\x87\xb7b\x15\x87A\x96\xfb\x966&\xf42\xf0^\xf1d%>\x04/\xa39OV\xd8wR\x0fn\x07\xb1Z\xb2, .\xf3\x8cI7\x88N\xe5\x1d\xabJ\xe7\x8b\xa5g\xc2\x8bw\x0c>\xcf\xf8G\x06\xc6\x92\x02\xba|\xc3`\x7f\x0fVy\xb6D\xdb)\xc6\xfcU\xc2\xfe\x91\xb3\xc8\xbb\x99\x12\xa7\xf2\x8e\xd4%\xf2?$|\x1e\x84LA\xab7\x0b\xac\x98\xcf\xd3e0\xcf\x14\xb4x\x1f\xa5\"\x01+p\xc9\xaf\xf1V\xb2E\x10\xe19\x01M\xf1\x8c\x1b4\xd9\xa3\xa1\xf7\x16\x0e`G\xffD\x1a\xe2\xd1\xb8\xd8\x0f\x1e\x8d\xed\x9b\xc1\x0b\x83\x18\xffN\x18\xc4\x1f\xa8\x18tG\xfc\x1c\xc54[Z\xca\x7f\xcca,\x01,\xc9\xd1\x91\xd4\xb5}\x8a\x02\xc1w;\x95w\x0c\x9e\x87\xb3#\x1b?\x98\xcf\xf3\x94\x1ds\xe9\xabsJ\x9cZ\n\xd2\x1b?H$go\xa9\x11\xbc\x9eZ\xf2\xd6\x81m |\xbe\n\"Z\xc1\xef:\xa9\x0d\xbd\xfb\xb9\xa5:|\\}\xbca\xcc_0\xb5\xb7\xf5O\xe4[,dkj\xed\xb8\xd4[\xfb\x81z\x9f\x17 \xcf#_\xd4\x05I\xa3\xcb\"\x0d\xab4\xc2'U\xd0L\x91m\xda\x04\x9b\x9bD4\xfc\xc8R\x9e'\x1eK?\xb2\x7f\xe4A\xc2\xe0\xa3\xb6<\xe4\xe3\xf3 \x0c\xd1\x0f\x88\x8c\xf71\xf5\x02\xf0k#\xdeF\\\xbeZjQ\xa8\x08 -\xa8H\xeew\xdb\xe72\x96|d\xa9\xacB\xfe\xb6V\xa1q\x99\xf1\x86\xc1\x86\x9c\xfb\xc7\x02\x13\x08P\xf12\x02\xbc`\x035\xba\x0b\xc0-\xfd\xe5^\x9e\x8a\x99\xc5\xfb\xc2\xa3\xec\x15]\x05!T\xc5\xa3l4\x877\xb4\xa2(;\x05]\n \x98\x06\xbf\xa3\x03\xa7\xc0\x8e\xfc\xff\xce\xd3\xcc\x04\x1eQH\xb2\x95\xc9\x12\x96y\xcb\xa2\x80|\xb5\x02\xdf\x84eC\xc4\x8b\x05\xf0'\x9a\x04\x12U\x00\xe8Z\xbeZ\x80\x7f\xd6g!\xc0^\xd9\x0eC\xa9\xae\x83\x0fg\xc2Wx\x06\xbe\xc3\xe7\xf8\x0e_L\xf0\xe4]<9\xbc\x89\x97\x8a\xfe\x82\xdf\xa3\x08'\xbe \xf3}\x12\xb0(\x03\xcc\xf0#O\x82\xdf\x05\x9f\x18\x16%y\x99;Z\x16\xd9=\xea\xfa\x89%Y\xe0YjZ\xabL[=\xe0\xb8\xdb\xd1?1\xa8\x84\xfa\xa2:\xd0\x12\x99K\x9a\xb5\x91\xd6RNo\xc2\xca;\x02\xbf\xa4\xd1\x02Ned\x98a8\x8e\xfc\xf5/S\xe2\xc0\xef\x11\xf5\xd7\xa3k\xac\x16\x91\xfb> \x16AT\x02sxG\xe1\x03\x9f\xf1EB\xe3\xa5\x85\x90\x0fVt\xc1L\x92\x01\x12ZI\x86 \"xU\x11\xbe\x86\x80\xd8\xf1X\x8c/\xeb\xcfx*\xbeJ?\xe3_\xf8\xbc\x87'?\xc2\x93Y\x12\xb1\xf0-\xcd\x92\xe0zJ\x1c\xf3\x15\xe9\xad\xcc\x16\x93\xfa\x06\xe4UE\x892\xc9R\xca6\xd9\x9f\xd9\x0d\xdci\xa4P\x95\xfa\x8d\xd6qs\x1a\x8b\xd3^\x01\xaa\x17\x1c\xf2,Xi8\xf8\x89@Iy[\x81;\xcdW\x14:\xcbXr*p?\xac\x0b\xf9>Je\x02V@\xa040\xa6\x95'\x8d~\xb7\x1e6`\x8f\x0e\x05\"v\x14-\x00\xe96\xd2\xb0r\x1cp\x012\xb2+\x9a|f\xc9 \x90\x1c\xf2\xf7\x88\xa1\xb4\x86\xcc|\x1b\x18\x80\xab\xc0\x0ex*\xaf\x085h*o\xa1,\xc0\x05\xd7c\xbeZ\xa15\xf60\xde\xac\xb0?\x07>\xac?\xe3\x0d\x85M\xf1=U\x84\xcb-qV=\xc9R\x9d n\x87\xcb\x96lE\x15\xa2\xc6>\xcf-\xd2\x82(_\xbd\xf72\xba\x86\xf5[\xbe \xdf\xd0R]\xa4\x12\xae\x89\x164O\xbaa\xc73\xa5<\x04\xcd ld\xa7q\x00\xd9\xf2m\xdc6_\xb3d\x1e\xf2+k\xa6\xd8\xe4Z6:%\x8eN\x1a\xc5*\x0d\x1b\x17\x05s\xb6\x0c\xbc\xcf\x11KS\xb3\\\xa6\x13\x91\x821\x0d\xa2\xec\xbd\x92\x08\xc1\xcb\xc8&\x10\x8ai\xc4S6\x018\xf1k4A\x81\xb2e\x81&\xcb\x17\x1cRP\xe7\xb5\xf5\x88\xa4\xda\xcb\x9a\x07v=\xc9^\xaa\xf6)\xeb78\x1c[\xa0\xee\x0e\xe0\xf2}\xc4 \xc1V\x00\x97\xa3\xc8\xac\xa3\xec\x17]\x8f\xf8m\xad\xe2(\xfb\xd5\x80\xfb\xb5\x05\xeeo\x06\xdc\xdf0\xb8\x84\xa5,Y\xb3\xa30^R\xf0\x1bo\xbc\xb7\xc1\xa71\xf3\xb2\x8fby\x9b\xa5\xcaT\xb4,`\xee5+\xc6\xb7\x92\x80\x94\xc07\x9d \xa2r|\x18\x136\x17#(\xfea\xd5\xb1\xf9\xaf2\x17\x1b\xb2\x82\x9ey\x0d+\x0b\x00U\n\x08cP\xba=a1\xa3\x19(\x89A\x81\xe2\xcd\n\xfbR0\xe1N\xf1\x1b\x85\x93<\xe8\xc9u\xc6\xa24\xe0Q\n\x05\xea\x89-%_1\x9a\xe5 3\xcb\xe9$\xb4\x94\xd2oA\x074\xcdCK\x16\xcflR\x94\x04g7\x12\x1c\xf7\xa6\x1e\xb5\xb0\x87)c8\xc3\x9f.i\\!I!\xa1\x95$MC\x1e[\xbe\xa2 \x184\x8fyyH\x13C\xe8SO\xc2\xbe\xa5@N\n\xb9\x84SO\xc2K\xd9\xba\x1b'\x8c\xfaoY\xb6\xe4>\xd4U\xbeb\xf5\x94\xda]\x02\xb8|Ca\xfd\x97l\x1dh\xe1\xa5\xf9\x8aB\xb3\x15.\xe0\x169kKN\x90y\xcb\xb3 \x84\xe5h\xbc\xa1\xf5\xf3X\xd3\x86\xe2\xb7\x95.\x14\x99\xa5\x0c\x02@\xed\"\x884K\x82\xcf,[&<_,\x8dc\xb3\x92\xdevvV\x00\xcd\x03\xb4ZC\xdb)*o\xb8,\x03\x94\xf0\xcf\x96\x95 Y/i\xba\xa4IBeWE\xca\xc8\xd7I\xf8\xa7T!^\xae\x81\xa2\x14\xb7\xaf\x04\x01\xf3&\x88\x98G\xe3\xb2L(\x13Z\x0b\xfc7\x0f\xa2j \x91b-\xf26\xc8\x04\xdd\xb1\n\x8c\xa6\xad\x8a4k1s\xbe\xa1L\xeb\x8c\xf3\xcfL\xd3\xc2\n\xfc\xcaB\x0c\xa7y2\xa7\x1e;\x95X\xc81_1\xe8\x1b\xb1\xd4\xdf\xd0h\x91\xd3\x05\xc0W\x12\x90\x12\x19\xbd\x0c\xa5\xb7&\xb1d\x8c7\x146Y0 \x02\xd4/+\xcc\xaf\x05\x0cv\x96e\xec:;\x02\xfdV\x01\xc6\xae\xb3\x91\xd4v\xb5\x80\xbed\x1eO4\x0e\x00p\xbfH\xb1\x141\x91/\x94h\xc3\xbd\x02\xa0\xa0\xf9\xca\x17\x0c\x92\xa3\x1b!+\xe98$7\xc7%\x019. \xc8E;k\x14t\x91\xd6\x86\x06\n \x13\x05\x94%\xdb\xb6\x7f\x1e\x05\x9e\x8d\xb7Qy?\x04~\x00\xf5\xc1\xdb\xe82\xf0\x03{E\xa0|e@\x83\xaa:\x0e\x9e\xa5\x1fXr\xb2\x92\xc0Y:\x8a\x05\x85\x8a\x11\xbf\xeb#\xe3>\xd7Y\x8f\xca\xeb]\x0c\xf8G-\xaar\xd6#%\xb6\xc2\xc0^\x9b\xb2%g=2dM\x18\xf8\xdb\n\x87\xe8\xacG&\xcb\x88\x15P\xdb\n\x19\xd65\xf32\x9e\x9c\xcc\xe7\xcc\x13xF\xbe\x8e\x18\xbcc5\xb1$\xb5\xb1jk\x96dG\xfe\xfaW\xa8&\xc9@\xf0\x86\xa1\x1d\x91Y\xca\xdd\x00\xb4E\xecVB\xffZ\x83F\xeb\x0e\xd8\xd5\x0f\xfcZ@\xca_\x16\x983\xc0 \nL\xbe\xa0\x90ip\x19\x846n\x18P%>\xacW<\xf1K\x89\x8fxk\x91\xf7\\% \xa9Q\xb7E\xeam\xb4\xc2o\x8cp\x9a\xf1\xba\x90\x95\\\xdb\xef\x87\xafq\x04p\x8d#\x80\xeb\xe3%\x8d\"\x16J\xad[@\x91\xf5$\xec\x1ba\x10}>\xf2\xb2\x1c\x88^\x07^\xa7T\xbe[\xc1\x13/\xe1\xa1\x01.\xdfm\xe0?& \x88\x96\xb0\xcb\x04\x15EC\xe6G\xb3\xd2\xb6\x1aO\x97\xfc\xaa\x00L\x97\xfc\xca\x06x\x16dF\x95\x99x\xb3\x82\xca\xab\\\x05\x89_\xe2^\xaf\xc2\x1f\xc0\xd3\xb6s\xbd\n\xa7\x97\x14U\x98\xb8^\x85\x11\xbe\xc8 \xe7\x17\xf8\x00\xd4\x10\xa5SLAG\x81\x8a\xb3W})\xa4\xe8:\xbc^\x85b\xcd\xea\xf6`J;D\xfa2@\x1as\x83/\xae\x1b|q\xdd4\x17W= \xf9\xf2\xefh]\xbfs\xbe:\x8a\xfc\x0fT\x1cQ\xe5K\xab\x7fT\x8a*\x1f)\x17\x02\x81\xc0\x95\xf5@\x11Dz\x1982Ug`\x84R\xcc!\x04il\x85\xa4Y\x1dil\x806 \xb9\xec\xdb >v\xd6!\x17z\x1b\x84Z\xe1\xad \xb0\xb2m\x10zI[\x8c\xdc\x8a\x85h\xcfWk\xb0WH\xd9\xc6\x8cL\xcd\xc8]\xa4\xaa\x9d*#\x02\x8e?\xb3\x9b\xd4\x0d\x06\xe39ON\xa8\xb7t\xed\n\x84t\\\xae\x08\x19\xe7vgH\x02\xf1\xeb\xc1\x03\xe2\xd2q\xe3\xeb\x12H@\x18\xeax\xdf$@\xc7N\xddu\x02\xc7\xedW[\x82\xfe`\x0e\x15\xa4\xa3\x85Guk\xd7T\x81\xef\xe2>>\x1e\xe3>>vw\xeb\xd5\xcf\xc16\xbdj\xcb\xaa50\xdf\xea\xf8\x05\xa69k\xc3;\x8b\x80\"/\x0e\xc8\xa4\xe6=\xb1i\xaeN@2\x12\x02]\x83o\xd0xIS\xe6\x7fd\x8b \xcd$\x15\xaf\x97\x10\n.\x1e\xe5\xf1~J\x1c\x1eID\x85\xa0)\xfdh\xd7\xf6\x06\xb4r\x11\xe5\xa0e\x90\xf5M@\xd9&\x16LC\xe4\x01^\x9a9\x19\x8f\x7f\x08\xf3\xc4\x19\x12\x07\x04\x01\x10\x1b\xfb-\x8br\x95\xf2\x8a{y\xaa~\xff\x95\xdd\xbc\xe4WQ\xf9\xf6)V\xbf\xdf\xf2\x06\xe8I\xe47'\xab\xa9\xa2\xbf\xa1EV\x8b\x05q\x87\x0b\x12\xfbf*\x0dM\xa7=\x0d\x82Mc\xd4io\xd3\xe0\xc2du\xda\xcfB\xd8\xb0j\x9dV\x8d\\\xf1m\xdb\xb17\x88\x1a\xed\xa6\xa5a\xab\x85b\x0f\xdb\xc4[\x8e\xbb\xb4KP&\x84\xd3\xc2PA\x07\xc7o\xb1\xf3\x92Q\x12\xa4\xf1I\x0b\x14\x8f\x05\xd0%\xcf#\x1f|5\xc4v\xd8\x90\xcd3\x13\xf8\x0d\x9b\xdfn\x94\xbf\xba~m<\xc0\xb2n\x0d\x8a\xfa\x9e\xbb\x16\x07,6\xde\x80~\x9a\x03\xa9\xcd\xfes\xc3\x93J\xac\xe6aH\x96Cbq\x10\xa7\x06\x9fC\xb4xr\xa0]58C\x91\x04|\xa6\x98\xd7!I\xc6\xa5\xea\xba\x8e\xb8\xf3Ry\xb7c\xa9\x0bf\x99\xd5\xfe\xfd \xf9\x8c%N\x93h\xfce3X\xee\x9aE\xa0\x84\x9aNImF\xd8u\x96P/\xd3wtu\xca\xa4%|\xf4\xd6\xa2\xc3\xea_\x0fdF\x0em\xb1\xd3\x06d\x8a\x9a[\x88'\xbd\n\xdam\xde=\x9a2\xe3\xd8\x9bZW\x9a\x1b\xba\x1c\x82\x9d;Y\x923\xe9#\x9e\x8f\x95\xaa\xed\x89\x1f\x80\xc8Q\x9a\xf1\xf82\xb6\xc7R\xfa\xa2\xd5\x07T\x8b\xd1!\xb8\x82\xc7\xb3\x8b\xf6\xc1\x99mo^qd\x96\xc7d\xf1\xe5\xbb}\xb8<\xe9\xed_\x87\xe3\xd6\x12\x17\x8b\xf4\xfc\x8eI\x89\xe0_\xaa6\xe9S\xdc\xd2 \xb5\xa6\x14\x19@n\xa4E{G\x0b\xeaT\x8b\xbdz\xb1t\xe7\x83^\xdd\xd2$TG\x97$m\xd5\xd9!\xd5\x91\x0edFZ\x1c94\\b\xfa\x1f\xf2\xec\x0d\xf8\xd3d\xf5\xe8k\x16\xaf\xa3%\xf1*M\x97a\xd1\x03u\xb5c\xb5\xc1\xc3\x8d\xaf.!\xf5\xae\xcc\x0c\x1e\x99\xc9\xe6\xaf\xbb\xc9\xfbP\x9c\xc9\xc9\x95\x05\xdbc\x94\x9b\xd9\xdf\xab\xf3J!\xce\xfc(\x8f\xdd{u&g\xae\xd2\xeb\xf0\xb1jM=\xdd\x97\xf0\x8f\xea\xbdZ\xaa\xf4\xfa(\xacUz\x9d\xe9Z\xa9A\xab\xc3/\x14|\xdd\x07\xdf\x8d\x1c\xcd\xfa\xe8\\*\x1e\xad>\n\x17e\x84\xaa?\xbe\xd6\xf2\xaej\xe1\xe8g\x0e\xbd\xe4\xe0G\xc0\xa1Q \xdd\xe3\x9dD~\xe5\xfdu\xc6\xf4\x15\x89\x91\xaa\xfd\x0f8\x97\x8a\x95\xf1h\xf4!\xa47\xc6\xcf3ya\x08)a\xe0}\x86\x1fUn\xc7\xe3\xb1,\x91C]>\xcf/Cv\xac\x81\xfd\x84.\xf4\x7f\xd5*\xf9S\xfa7\x90/\xd7A\xa6\x7fC\x8c7\xfd\xf2~]\x02\x15\x8d\xf5\x13\x0e\x1c\x92\x9f\xcb.)<3$\x0e[\xc5Y\x00Q\xcc\x1c\x16y\xc9M\x9c\xe9\x17_\xfdH\x12\x0e\x15\xce5{\x16D\xb1lv\x10\xadi\x18\x00\xd4\xe7\x92_\xfb\xccn>$pO\x02\xbf%k\x16r\xea\xeb\xff\xcc\x7fI3Z\xbe\xbde\x19\xf5\x8d\x94\xa2\xd5+\x93\xd5\x83\x97\xb7\\v\x14^\xde\xe7%\x94\xee\xf5\xaa\xe4\x06c\x9afL\xfe\xc8S\xf9C\xcd\x93\xf8\x0f\x12m\xe2\xc4 _\xe8\xc6&4c\xe5\xc0\x80s>\xc7t\xf1\xeb\xa4\x8c}\x96\x83\"~\xa9\x1a\xd2\x8c\x86\xa1J\xcd/WrV\xd2<\x8d\x99\x9c\xb9,X\xa9P\xd4\xf0\xc6soy,\xc8\x87\xb0xUS\x0c\xbfu\x07\xe1\xa5\x18\x08\xb8\x1f\x0b\x8cE\xba\xe6a\xbe2\x1a{EA\xf6\x0e?\x97\x8c\x85\xcey\x0f)\x91f\x8d\xd8l\xe7|\x9c\xf1Oq\xcc\x92c\x9a2w@\xb6\x05c\x16\x06\x1es\xeb\x9b\x95(\xcbg\x87G\x10\xe3\xb7\x99\x0bv\x98\x19\x8f-\xd9\x1c\x15x\x90;\x8a5Z\x0c\xc1KiFD\xb6\x89s\x0f\x92\x8c\x04\x91*T\x0f\xe3\x0b)P\xe3Cr5K\xce\x8b\x80\xd9\x00Y\xf3\xd2~\xa2PS\x91X\x08\x07\xae\xad\x16\xca\xce\x18\xe2P\x8d/\x12\xce\x81.}\xfd\xb2\xac\x1f\xa9\xe9\xd4^\xd3e\x9ee\xd2\x0c\xf8@\x06\xe0T\xdb\xdbHH\x8d#W\xa6\x08TF\x13FU\x9a\xf1m\xfdK\xf4\xec\xb8\x95\x92\xbf\xd8\x90\x92\xe7(\x13D\x13B\x87pR\\\xcd\xd89.-\xd8\xba\xe9 \xf5\xfb\xd3\xeaGpjtPT\xc7\xeaD\xe8\x07\xa6O\x8b\x0e\xe8\x97U\xcc\xdd\x01}\xa2\xb0z\x17X\x81\xf1;\x01\xfd\x1e@pRt\x00\xbd\x86\xd5\xd5 $\x0f\x96\x0e\xb07\xe2P\xe9\x01\xa3\x0e\x9c^\x90\xc5a\xd4\x03Z\xe2\xe7\x0e\xc0\x0fp\xfat\x01\xf5X/\x1f\xd4\xa9\xd5\x05\xa6O\xb4\x0e\xb8\x8f\xe5i\xd7\x05 'a\x07\xd0\xa9<\x1b{@\xf5\xe8\xc3\xa9:S\xbb\xc0\xe4y\xdb %\xcf\xe2\x0e\xb0\xb3\xf2\x9c\xee\x80\xfc\xc9<|;`\x7fV\x07\xb3\x9d\xbf\x12<\xc0\x1d\x19\xe5\xbfj\x8a\xab\x9do\x94\xfe\x9e.\xdd\xa8M\x82\xac\x9f\xfbf#!\xb8\xd3\xdd\xba\xd9\"\x88(`\xba\x84)\xa2\x19\xde\xdd\x9a!\xc9\xf4\xf6\xa1\xdeU\xaeq\xe4\xe9\xba\xc9p\xbf4X\x81\x8e\xbev\xc9G\xaa\x80@Y\xf6\x01\xb4Nc\x15\xec}7\x1a\x7f[P\xe6\x1d\x80\xdd\x12\x18\xa2\xe6.\xbe\xdb\xdc\xbd\x14\x9cUGc^*\xae\xab\x17X\xd6\xdd\xb9\x97\x9a[\xeb\x01'9\xb9\x1e\x80}F\xf5e\xc1\x01v\x02\xf2\xae\xadkq\xadHz\x8e\xfb\x99\xc1\xf6t\xe1a\xcd\x12\xf5\x81\xeb\xb3\xa8\xcfJV\xaa\xbd\x8f\x16\xef\xb8\xa4g\x1f\x8fLABG\x9b\x8e\x9aB\x86\xbe%\xfa\xf4\xa4\xc5\xbb^\x9f\x9e\x9cU\xd8\xcd\xf6O\xad\xef\xf6)\x19\xe4\xa7\xe3\x1b\xab\xbb}\xe3g\xe0\x88\xdb?\x81\xf8\\\xd3O\x9fO\x1c\xf3\xb8\x93~;\xeeF\x98\x1f@d\xd1\xde\xd2\xa6?\xc4\xa6\x08\x96\n.-q\x9d\xfd'\x0e\x1e\xc8H\xf0M\x17\x10\x90\xa1\xbc%\xba)9\xadf\x01u\x80\x05\xed\xb7?\x17\x83!\xb9\xa8\x94\xbd\x07\xa1/\xdcV\xf3H\x1e\x89\xa5\xdcw\xeb\xd4e\xe3\x8b\x8c.\xd0\xdb1b\x08j\x05\x1fm\x17\x0f\x04z\x18\x90`\x83\xf8\xac\x9f\x08\x96\xfe\xcb\x17\xe2\x9e(\xde^G\x85\n\x0c\x89\xdf\x0d\x16_\xaamh\xae\x820|\xc9B\x961\xcb\xf0\xdc\xfb\xd8Djll\xbd\x8c\xce\x95\xc3Iw0$>4\x0dR\xbb\xfaU\xbcYd\xef\xc7\x90zG\xd9\xfb\xa3}\xd4\x81=o\x11\x18h\xf7nc\x8f\x86\xa1\x8a\xacn@\x97\xcd.~%c\x9aC\xbc\xf8\xe3\x90\xa6\xa9\xcb\xeba@\n\xa9\xb0\xf4\x8f\xd0\xd4\x06a\xd2/\xb1\xe0-\xb0\xec8e\xb9\xcf\xcb\x0b\xed\xca\xadhM\xfd\x8a\xdf\xd3\xa85o,\x9a+\xc4\x0b\x83\xf8\x92\xd3\x04\xf8\xe6>~\xda\xb54\xa9RP\xe9\x94\x1c\x126\xae\xa4\x17\xb7\xa6\xd5\xe4\xaee\x85Mw\xf0-\xa7;\x90^\x86\xcdI\x08\xeec\x12&\x93\xc9\xbf\xc1\xdaM\x98@\xe2\xbeV(\xff\xf6k\xafy\xf1\xc3-79\xb8\x87\xbd\xcf\xecf\n\xf7V\xf5[4\xa2<\x02d\xa0\xe0\xdf\xdce\xe2\xf1\xb2$\xfc+T\x80f\x83/\xb5\x96|\x1a\xb6\xe5\xaeXF[\xb2\xa51\xa8-\x17|\x19\xa0\xd8\x81\xc8\xb8\x16o\xb9\x1f\xcc\x03pA\x90 8wwR\xbf\x18\x14\x8f\xb7\xa4\xc9q5\xf4~\xe7v\xfd\xccnb\x10\x1cH9\xae\xd4\xfd8\x94nm\xa7\xb5x\xa4\x04\x17\x8f\x7ff7\xb7\xf8\xaa/\xb8V\xf3\xa3_\xbe@z\x1e\xd7\x9a\xc2\xc6\xea\x03}\xdbs\xb5\x0c\xbc\xe5\x86\xadi\x19\x83\xfbll%\x05Eg\xf4[b\x00:$\xc1\xb7P\xe9m\xee_\xfcP9I\xbd)qNR\x8f\xa26\x05\xa0=}I\x93)q\x08\x92\xfd\x06\xf4\xad\x9c\xa3$\xe1W\xe27\x02\xf2)\xd6\x00\x9f0\x83\xc6\x8f\xca\xd0\x04 >ZLM^\xf2\xabH\xc3\xc8\x9b\xc7&\x08\x0b\xa7\xc4\x91\xa4\x1a\x92\xfd3\x18K\xbe?E\xb2\xde\xb2(\x9f\x12\xa7\xa2\xf9\xda\x00:\x8a\xe3\xb4\x13H\xb2MS\xe2\xc8\x1fo\xb8\x87\x19O\xbc\xe5\xbf\x7fH\x82\x08\x14\x84\x00?9\x9f\xa2\xc0gQ&\xf0\x89\xdfjg\x80\xa3\xe0\xfd)q~\xa0\xdeg\x9b\x85\xc5\xb3)q\xce\xe8%\x923\xd9\x15}\n\x19\xc5\xcc#&{ba\xc8\xdb\xedf\xe6\x13\xd1M\x8b\xaf\xcb\xc9S5T \xc7\xec\xc7&\xa2\xc1G!ZR\xb4U\xca\xe6\x9b\x99\xbb;S\xb8(L-\x03\xbb\xfb\xb4m%\xef\xedZ\xd6\xf0\xde\x1e|s\xc1\xd0\xf5\xb9\xf7H\xe5Z\xd6\xdd\xdec\x18%\xcc$|O\x8c\xd1\x8f\x1cu\xcb\xb5\xf7\xb4c\xdb\xec\xed\xb7n\x9b\xbdg]{\xe6\xd1N\xc7\x8ey$Z\xfe:J\x19\xea3\xe7\xd1\x93\xb6\xed4\x81\x95\xf3\ns52\x81u\xf3j\x17\xcd\x12\x83\xf9j\x0f\xcd\x12\xady\xf5\x08\xcd\x12My\xf5\x18\xcd\x12\xc3\xf8\xea \x9a%\x06\xf0\xd5S4K\x0c\xde\xab}tC\x88Q{\xf5\x0c\xcd\x9a@\x97w\xd0<9\x1c\xe8x\xec\xc2xL\xd0\x01y$\x06\xe4]\xbe\xb2\xac\xe8 \xccQ+6\xd9\xdd\x15U\xbce\x19\xada\x0e\x9c\xcb\xb3\x9f\xc0\xd2\x0b\xfegvc\xbb\xd1\xcd\x04\xc99\x03\x90s\x19\xec\xf63\xbbir\xa9\xc0\xfcV0\x1ah\xc8\x97\xde\xe3\xab\n\xb9_\x1b\x8d@\xcf~[\xa3\xb4\x7f|\xabld\xa2\xfc\xe1\x93C\x8d\xcc\xc8\x94\xc8\xb0:\xe3y\xc2W\xc7\x8a@\xab\x07DF\x15d7\xa2;\x82YAy\xc0x\xd5\x06eJ\x9cr\xc6\xee\xc1\xc9\xb6\xd4\x11\xfb\xd7s0>\xcd\xa8t\xf7\xc3\x92\x7f\x1d\x03\xd3\\-\xa0\xbb\xc3R\x1bI/\xb5\xa9\xcf\xda\x81<\xb8]\xf4;\xa0\xee\xc4\x96\xdc\x91%\xb2q&\xd5\xb5\xfd?\x86i\xff\xb7X\xf1\xb1\n\x15\xfd\x7f\x8b\xb8\xe9\xdf\x04O\xb00\xa3\xbft\xf1\x84\x1a\xf1JhCv%\x13\x04\x16\x05\xd5\xba\x97\xd5\xfc\x11\x1b\x1b\xc9\x0d\xc6\xaf\x11\xa74\xcc\xe8\xaf\x1b5\xe5\xd7zS~\xad6\xe5W\xbc)5(\x1c\xa8Ws\xff\x86-%\xc8\x91\x86\xff\xdfj\x19 \xce\xf2\xf1\xa0\xb9\xac\x9eu\xd1\x1b\x88\xac\\\x1f\xe0\xcd\xb1\xbe\xc8x\xfc\x86\xadY\xa8\xe2\x02O b`u\x11\xf8\xe0\xf5KdO\x90\xecJ\x84\x8e\xa9\x8a\x91R\x84\xc0\x80 \xa9\" \xc2\xa9U\xa3y\xd8\xb0\xeb\x85\x8co\x83\xe8O^dta~B\xe0\x82q\xc6\xdf\xf0\xabB{\xd3^\xa9\xb6\xfd\xfe\xf4\xf1uQ\x87\x91F\xa6\x88\xda\xfesl{F\xb5}x\xab\x196\xa7\xaf:3\xf5x\xcfS\xb2U3\xa0\xcfS\xf6*\xb8\x14\x13\xb25\xb9\x8f\xb6\x18\x91c\x1e\xd5\x15\xe6\xc51\xff\xf0\xb7\x87\x87\xdf?\xac\xa6\x0b&\xf9\xe1\xdf_\xfc\xb6\xf5\xdb\xe8\xb7Q-\x0f7\xd4?\xfe\xf1\xe4\xf8\xaf\xa7\x9f\xde^\x1c\x9d\x9d}\xbcxw\xf4\xf6dJ\x1cA\xc7\x8c \xe4\xf0\x08b*\xa79\x1a&\xc3\xf7\x8fU\xee\x19\x97\xb1\xb4\xbb\xf0\x081\xe8i\x9ct%\xe6\xd5^\xc6\xd2LTt\x08\x01f\xd88aqH=&\x10\xaaC\x1c\xb2M\xe8\xb8\xd9~\xb2M\xbe;p\xbe#\xdb$\x13?\x9d??\xf8\xae_@s\x1a}dy\xca\x9a=\xe9\x8a\x80\xa8c\x9b\x16\x16\xec.\xd6\xae\xf6\xce\x8aJ 6QL\x93\x94\xbd\x8e \xf0\xe4dg0\x94\xc1\x7f\x80\x8eo\xf6\xc2\xb6/\xeeY\xa4\xf6\xe4\xf1\xe3\xddI\x17\x92\xab\x0fQ\x11\xc7KL\xf6d\x08=\xdc\x91\x91\"wdH/V\x84\xdb\x12ks\xf4\x88< \xc1s\xc2\xc9\x0bB\xd1\x10_E\x8d\xb9\x19f\x90\x93m\xf2h\xe7\xd9\x93!\xa1\x03Y:\x17\xff\xb6\x0f\xc8\xa3\x01\x89\xc4\x7f7\x13\x7f\xd9X\x0b\xa4\x8f2\x97\x0f\x06d\x1b\xcd \xdbd\xd2\x96\xb9\xdb\x96\xb97@f9#\xffq@\x121\x00\xffa\xc6\xa6&\x8d T\x91\xdaD\x17\xc48lo\xab\xf6c\xcdGq\xa0+?5 _\x88\x1b\xa9\x9f/^\x90\xc9\x93\xfb\xc0G\xe6\xac;\x93\xc7\xe3'\xe3]\xe7\xf6\xb5u\xd8,\xb9\x91\xfb\xe8\xc9`(m\x91p\xdb\xa5I\xdd\x9aG{bx40\x8f\xec}\xa8\xe5\xd9\xc6\xa1\xb7\x04;\x1e)kw\xd6\xa2/'\xe0&\x8a\xfb-\xe3\xce)pV\x85\xd5\xbb\x01\xac7\x1b\xe8O\xd4T\x8a\n\xdcL\x06\x11\x1e\x08\xf4\xc7\xed\xe6\x9e\xcd\x16\xa1\xa1\xb4\x04\xf2\x8c|&N\xfd\xc4u\x1e=rDY\xf1\xeb\xb13\xac\xb8\xf3\xb8\xe7\xf8WbB\xf6,\x83\x9f\xa86\x9d\xe6\x97Y\xc2\x04\xd2\xe3EX\xe0\xdb\x7f9\x1b_\\\xb0\xf4-\xf7\xf3\x90\x81!\xdeP\x86\x87\x8b\x98\x97\x01\xa6\xfe\x90\xf0u \x86BG\x1dm\xb6:p#w\xff\xf1n}\xe5\xf1\"\xeb\xd1\x00e#\x02\xabY\x83\x8a\xf7h4M\x1ejM,\xa7\xa2\xa7MIwL\xc5J_\x12\x1dw\xad\xda_\xae\x93\xefyDU\xad-\x83\x18\xb9u\xfb<\x0eK:r'\xd8\x96\x16\x19{O\x1f\x9b\x18T&=\xc1\xc7\x9a\xfes\xc7Z\x9f;-\x07\x9en\x99\n\x1a\x8d|o\xab\x1fU\x016\"n5\xe8\xdd`@\xb2e\xc2\xafH\xc4\xae\x88@2`\xdc\xe0:\xc74\x8axF\x04oJ(\xf1\x04\xc3IhJh\xf1%\x07\xa1~\x14\x17\x8b\x99\xdd\xaf\x95\x95y\xff\x862\xb3e\x1f\xd9\x9c%,\xf2t\xf3\xc4\x87\xc8\x92\xa6\xd1w\x19\xb9d,\"A\x14d\x01\x0d\x83\x94\xf9dD\xd2\xd3\x05\x1b\x93O)+\xeb\x1b\x83\xb4\xa2xu\x07$\xe3\xf2d\xcc\x96l5&\x1f\x19\xf5\xc9J`m\x9a\x11\x15hu~9^\xb1\x87y\xca\xa4\xa8cT~\xc5\xa9\xdf\x8a\xe1\xa3\x91\xb5-~\x1b]A`\xd0\xcb\x95 \xb8\xe1&\xaf\x80\x0b\x08\x95kn\x04C^r\x1e\xa2\x19\xa2\xb1h\x86\x8c\x94\x8bf\xc9\xa3\x15\xcd\xd2\xce\xc5\xb1\xac\x9b\xd5\xa5\xa5\x114\xc2[\x0d\xfdy?Ge\x8bLK\xdb\x90r\x9a:\xb2\x14\x95\xf2Jk\xc7,\xa5xd\xab\x0fr\xa4\xc7F$\x17\xe2\x01\xe0]\xb8\xa6b\x18kW\xbf(\xff\x1e\xd5\x160\x91r\x83\xb1\x99 \x0e\xec\xa2\xec\x1d\xf0F\x83\xa8o\xa2\x14u\x82\xd14\x0d\x16\x10\x9e\xbb\xaf\xb0\xe79\xc9\xc8\x0bB\x93\x05\x88\x94S%\xe6yN\xb2\xedml\xaf\xe8\xa5^\x14\x98e\x88\xe1t\xf1\x89\x84\x04\x91\xe8\xa1j^y,-i\xfa\xfe*R\x8e&o$-')qqN3\xa9\x1b\x1f\xcd\x92\xf3\x1e\xd7\xdd\x86 9~\xe8\xb4\x8d8Q\x9d\xf2\xccN\xa9Q \xdf\x93=\xd1\x1e\xc95\x01\x8e,\xfb\xbdwN\x0e\xab\xaf\xb8\xfb\xd4\x159 ?p\x1e2\x1a\xa1\xa6\x04\x0b\xa2\x0c\xe3\xe7\xcd\xbc\x1b\x84e\xd3\xe9x\x14n}S@\x0e\x89\xbb#\x0e=5\n\x03)\x81\x88\x9b\x88\x0b<\xa2\x80\x8b\xc0\xe6\xf7\x05\xbd\xe3\x8d\xe3H\xf2z\x1dNb\xdc\x99^u\xcd]Y\x8a\xe6\xd58\x00\xe5\xdb\xbdp\xd4\xeeJ\xcb\xd3\xe8\xcb\x17\xb2%\xe8oZ\xd2\xdf\xba\xce\x12j e$\xf5\xb2\x07\x82\x0d\xa8\xbb\xb2\xd5\x0f: \x95\x11\xbd\x8f1\xa9N\xd1\x1d\x87\xc5\xaf\xe0\xad\x96\x91\xa9\x00\x9a\x83\xe3\xd70\xdf\xa6\xe3\xf3\x96%\x0b\xe6\xdfit\xba$OX9\xb1_/\x8b\x02\xed\xacf\x8b\xf3j\xd2\x85\xa1H\xc1N\x1a\xcb\x08\x1b\xd3\xcd\xa6oKV\xb9*\x07O\xcc\xc8)L\x0b>\x81\x06\xa89}f\x0d\x9bL^\x90\x9e\xe6\x97\xa9\x97\x04\x97\xfd\xe7K\xb5\x1d\x97\xa9\x89\xc6\xe4Q\xaa+\xed\xd3\x86,\xb9)\x1a\xd1\xb7\x0d+p\xbeQ\xffZ9\x1ef\xe2\x81q\x1f8.\x92%\xdc\x92F~\xa8\xa8\xe2\xf1e\x10\xf9\x90<\x18\x0cI#\xdbE\xfc\x8c\x10\xb47\x9f*\x1f\xef\xd5\x9f^=qu\xb3\xaa\xbd\x13\xecd\xaf\xa6\x15\x92\x83\x97\x81\xff\x96\xe7Q\xe7]\xab~\xe0\xa3\xe64\xb9\x9b}\xef\xe7 \x0c?2\x8f\x05k\x84\x93h\xfb\xf0U\xcbN\x90[\x0c\xdc\xc3\xa8\xb9j\xf2@M\x7f\xe5\xfaik\xea\xa7hu\x9b\xd1\xf9\x84\xcc\x94)\xb3\xe8\xd5\x8e\x02~\xa3\xaf\xd7\xb17h\xa5\xd7\xcf\xc2jz\x15c\x18\x19\xb6q,\xb2\x9b\xecd5\x7fm\x9c\xf7?0\x16}H\x98GC\x0f\\\x19\xf9\xca[\x7f\xadi\x06H\xc0#\x10\xa3T\x1b%o\xe6\x99\xaf\xb4\xd4\xab\x99v\xa2\x0b\x01\xaa\xf1%\x0d-|\xfd\xd4&\xc6\xc4\x04}\xa7\x06\x14\x1fk\xfb\xb5\xcf\xa1VCY}\xf9[\x02:\xb9\x07\xc6\xd8\x8eK\xe9Z\xfb\xd9\x07\xec\x8b\x14'\x00\xd1\xd9\xd9L]\xe8\xaa\xc4\xc3m\x1c]\x9f\xea\x08&\xcd\xef\xa2\xf2\xebO\x96\xdcl\x00M\xcc\xab \x1a\xc7\xe1\x8dk\x11\xe2`\xcfW\xe2\xd1vo\xc6\xb6G}s9\x06y\x9a<\xb0\x97\xbdk\xb0\xcb\xb3\xccGQ+6r^\xee\x8a\x0e\x8aI?\xb0<\n\xe7\x9a\xfd\xcaDp\xd3\xb5\xc4\xc8o|\xb7\xab\xd1\x18\xf4\xc7#\xedb?\xd2k\xa8z\xe1\xb4T\xef\xc0~\xd3l\xca\xb4q\n\xc8|\xbe\xb6\xaf\xb8\x16\xe9e\x1f\xbc\xb5`\x99\xb4\xb7\xf2\xb5zu_\xec\xa59\x8c\xea\x15\xc7\xf5\x908g\x9cP\xcfci\n\x97\x12W\xb2\xfa\xe2\xf6kHnxN\"\xc6|\x92q\x88\xe0\x1f\xcco\xc8\x1fD]kNI\x96\xe4\x8c|%T\x16\x9f\xf3<\xc9\x96\xc5\xe50\x01\"\x12\xeeF\xe0~q\x00\xf7HcgP\x1c\x04\xf3t|U\xedQ\x9fq\xe8\xa7\xda\xa5\x1f}\xcdi;\x10\xdb\x11qT\x96l\xae\xab\xf6\xa2\x81\xf9\xd1\x96\xe5\xdf^\x0b\xad\x9c\x02\xb6=\xd7^G\xae\xeb\xa8\x1d\xbd\xf6\xdd_\x1cw\x16\nb\xd2AAL\xfa\xef\xfc\xcd(\x08\xaa\xefih\xbb`-\x95{\xbeuX\xc2\x8e0Hp \xe6\x80\xf5R\xad, /e\xba\xce\xc8!\xd4m\xc2\xb6\n\x88:\x84\x84\x1e\x12\x1d\xb1\xfe\xccU\xb4D[~@\x0ee=;dJ\x803u=\xbd*l\xe7\x8a+x\xa7\x10`\xe7UXT\x82\xe2\xb6]\xc5\x16L\xf2\xd6\x96\xeb\x81\xd6\x07\x8c\xe6\xa0\x18\"\xab\xe8\xc1\x95\xbcqN\x0eIN\xa6jY6i\xc8k\xa5\xf9\xc1\xd5\xf5\x99\xca\x01\x1e#q\xff\xf8\xda$\x95\xbb\xee\xd3d\xe0\xe9\x1a~\xc2#`\x10\xc0\xfd\x03\xd1\x88TX\xc7j\xc5\xd5U\xb4l\xac^um^\xb5\xdf\xaf\x16Z\x93\x03\xe5!\xe0~\xb4\x1e\x87v\xa5\xbez'\xc1K\x90ti[\xdcR\xd5\x8f8\xcd\x98U-\xea\x9a\xc7KR\x83\xa9#\x19\xb0>\xd4\x1a\x83\x82\xd3L\xd4K\xf9\xe5\xda\x81T\xa8G\xf2\xb2j\x9bj\xa44\xbf\xddyN\x02\xf2\x82D\x85zf\xb0\xbd\xdd\xc4\x91\xc0\xd3p\xa5\x194$\xd1,8\x07a\x12\x9b\x89\x9f\xe7\xf2\xeeE\xfe\xb6\xb6\xad\x18\xac\xda\x0e\xf9\xb6Sh\xd9\xe7\x05\x00\xca0\x1b\xd4|\x02\x82\xce#\x00\x06\xdb\x7f\x9e\xa4\xf2\xbc\xe9\x89&\x957\xc2\xa7J\xb4\xd6\xd1[(QV\xd0J\x83\xe3#C\x0c\xb9\x08\x8e\x04\x1a\xd6\nv5\x12\xaf\x17\x94\x1aw8v[\xa0\xcaS\xd2\x0e\xb4`\xd9\xcb^\xb5\x01`\x12\xac\x99\x0fd\xd5\xab\x84\xaf:J\xac\x82\xeb j\xc9/\xceS;H\x06\x8a\xdf\x08+\x8dh\xe7f\xd6\xf1\x8fZG@\xee\xc3\xd6f\xca\xed\xdc2k4\x0c\xc1\x05E[~K\xf9B\xf7\xb8\x0d$\xc8n\xfa\x0e\x85\x81\x0b}6\x0f\"V\xa0\xa0\xe6\xce+A\x17,3\xb0\x15\xc4\\k\xc2s\x1b\xfc)\x98 %\x02[\x89\x97,\xf5\x92 \xce0^\x8fV\n\x19\xdaMMPA\xcaPAEP\xa5'\x85[\xe9\x17\xb4H\xea\x86C\xe2\x0d\xc9\x1cCD\xa0['\x0d-L\xcd:\xcf\xc6\x8e\x0bx\xd4\x0eG?\x023\xc4`g\xeb\xb5\xf0\x12\xb1h\x7f\x0cX\x1d\xb83hc,\xda\x88\x16\xc1e+\xe2S>\xb8\xf8\xb0}\x8a\x13\x1d\x1d\xd8\x17\x84\xb1G3\x97\xbb\xde\xc0\xc6\xe5\x14\x87\xdbR\x9e[K\xf2\x82\xf8\xc5\xb9\xb5\xbd\xbd\xec\xea\xb8 \x1b\xfc\xd9\x121+\xd0\x8fRN\x9e\xad\xc1a]\xa6\xfe\xcfE;\xe7\xb3\xf5\xb9\xd5o\xbd~\xc4WV`\x1f\xee\x0d\xc9\xbaC`\xd8O\xfc\x1a\x89\xb1_\x0f\xc9\xaaC\xf2e\xcaW7\x16\x83\xa1\xa9j\xa56%\xfeMp\x14\xd48\x12\xab\xde\x97\x12\xb7\xd7Y\xd8\xed\x81\xa2^\x1aL\xd1\xf8\x90\x04\xb8A\x9a\xd6\xdcn\x0e:\x084\x9a\xb3%\n\x18\x96\x08\xd9@\xc6\xbaeWD)\xaf\xbe\x0d\"\xf0fH\xd8\xb5\xc7b\xd8\xcf\xdc\xf3\xf2$a\xfes\"\x9a\x9f-\x19\x89x4Zi@\x9f\xad \x8b\xd6A\xc2#\xe0\xab\xc5\xa2\x06\xc9^\x1e\x86\x04\x82\x9a\x92\x15KS\xba`\x84F>\xa1\xbe\x0f\x11OhH\x96,\x8c\xe7yH\xaeh\x12\x05\xd1\"\x1dc\xda\xe2,L\x99eQ\x89>\n\xcehV\x1f\xa6s\xbb\xe0\xc3\x83\x9d\x86f\xbb\xd5\xa1\xc8\n\xbf<\x0f\xff#}\xb8\x18\xf6\x13\x1d\xeau3\xf3\xb6\xb7\x9b\x01\x1c\x88d\xfa\x07\xd2\xee\xe1\x808\xaf\xa35M\x02\x1ae\xe4\xa7\x80K\xe1\x15b\x00\xd1H\x91\xf2\xact\xd2\xec\xcc\x1f_\xf1\x1d\x828Hi\x02\xea\xd5\x87\x89\xd0\xa4#\xa8l\xd8A\x95\x13C}L\xbaE\x91\xf6\xd1!\\k\x83<\xb04\xaf\x9a\x0c\x86\x98\x8d\xff`Hr\xd1QO0d\xa0h,\xc5o\xa2\x7f\xdc\x8d\x86\xe4\xe9\x90\xa4\xd8\x01T\x1c>s\xe3;\xcf\xc9|4z> \x01\xa8\xfc\xcd\xe6\xe7-R\xa2\xeaR\xb3\x99\xdd\xa2\x0b\xcf\x1c\x8c\xde\xbe\xe5\x8a\x06\x8b\xae\x8d&C\xa2E\xbc0U\xe4\x90\xec\x80Nvy|F\xe4\x05I\xe0\x86R\xe9\xd2\xb9l\x16\x9dK.~\xf0\x1c\xa7b\xea1V{o\x99\xc6\x9a\x96;\xe6\xc9\xa3.{d\xac\xab\xa6\xec\x06\xd6\x11w\xb3AE\x90u?\xad\xdb{\xba\xffo\xd1\xbcF\x88t\xd9\xbcI#\x02\xbbB7O\xea\x88\x82vK\x07\xba\xfa\x89\x9e\xad\x89\xcb\xca \x8eA\xc3\xb7\x91\xbe(\xe2\xa84D\xac\xd3\xd9\xb9E\x9e\x91\x835\xd0\xc0u\x0c\x1b\x0c\xa0\x88sP\xe0\x83\x8b\x00*\xe5\x13L\x9c\xfc \xd1\x8e\xc6q\x9e.\xdd\x1c_\xbb]\x06\xb4\xdd\xbb\xae>\x06\xba\x7f\xf5^\x14Hr\xeb\xa0.]%\xd5\x9d\x1aDj^` 3\xd9\xfe\xba\xaa\x9e\xc6\x81\x9b-\x9f\x8e\x88\xdb\xdaM\x1321\x1c\xe2j+c\xb3\x83\xaay\x8f\x8c\xebdx\x95\x14i8\xd3\x05\xd4>R\x8f\x14\xb9B=\xacR\x0ff%N\x943\x81\xa0\x9c\x90\x03Q\xf5!I\xc6?\xe4\xf39K\xc8T\x99}\xdaX\xb3CB\xc74\x0c\xb9\xf7)J\xe9\x9c\x15\xf0\xd5A\xee\xbd\xbb \xa9;\xed\xd21\xca\x91\xc3`]h\xa4+e\xe4\x06\x04QL0\xdc\xc6\xb8\x11h\"\xb3+\x02z\xdez\xe1\xa3\xba\xe3\xc5\xc7=\x1e\xdf\xb8\xc9`h\xf52\xf7uP\n\xf2\xdc\xc9\xde\xa3A\xe1\xeek\xf3-\x80\x0c\x88q\xe64\x1bi\xf4\x1d\xd9\xe9\x99TP#\x07\xe4(I\xa8\xe8\xc5\xa08\x99\x9e\x0fH6\x8b\xce!0|t~\x1f;\xa2\x13\xdfO\xf6\xefr\x1c%\"\x13P\x9d)+\xbc\x9f\x96\xed=\xedt\xdcqO-\xab7+\xba\xff\xa3C\xa3M\xfb\xa6H\x14\xabQ\xdd\x05\x16\xc9\x8a4\x82\xd5B\x13\x03\xcf\xccv\xce\xe5\xa9\xa0\x8f '\x88|v\xedH\xcd\xe0d\x0co\xd0\x0e\xf85$\")\xce3\x95\x14\xe7YeSm8\x93\xbb\xbb8\x93\xb0\xff\xb4N\xae\xabS\xfb)\xee\xdap\xff\xe9\x1e\xca%\xec?\xad\x9f\xf2b\xd4\x9d\x99D\xb8\xdaQ\xc0\xb9\xd3d\x19\n\x98\x974cu\x00\xcf\x04xK\xe3z\xfe\xdc\xcc\x7f\x07\x8eD\xea \xb1 \xf2\x91-N\xae\x1b\xb5\xf8&\xc8)\xcb\xea\xf9\xcbJ>Lm\x1dd]\x01\x01\xe9_\x1dde\x82\x00\x86\x91GF\x1dnQ\x1b\x14\xfaS\xc0\xae\xea@7&\xd0\xab\x90\xd3lo\x17\xea\xac\x03^6\x00\x9f\x01\xd4\xb1\xbbA\x1d\xe2\xef\xc4Z\xd3\xde\xc65\x89\xbf\xbb\xbd\xbc\xe7j+a1\xd6\xb7]\xa9\xfb\xb6\x1b\x90G\xf8R\x9d<\xc3tk\x04\x1b\xdbzH\x90\x9aL\xcd\xc9\xb8\x143;-\x91\x0c*^\xf5\x9aHH<}<\xfb)\x83\x07\xc1~\xe0\x00\xa6\xbb\xbf\x06@\xcd\"V\xb0i\x01\xbe\xf3\xf0\x18`\xdd\xbb\xc5\xb2O[93\xbd\x04,\xab\xa4{\xe3j\xd6h\x7f\xa76\xb2bYL\x9e4\x97\xc4K\x9a\xb1q\xc4\xaf6\xc5:\x9a\xdeA&0hj\xbf\xf5\xe9\xfbZ;\x02\xb5\xf9 \xc8\x01{\x8e\x88K\xc9\x08\xf5O+\x98L\x88\x86#\x0e\xa7\xef\xc9\x0e\xf6\x15\x0d\xb7\xbd\x9d\x91\xef\x0fHapnx\x8e\xdei\xaa\xd4}\x95\x1a\x82\x19\xae\xd7W\xdb\xb8\x9a\xcd,j\xbc'\x89\xe1\xe4\x11.\xe3hluEn?\xc3\xc9\xed\x06S\x9a\x93\x03T\x0d&\x85\xf4\x86\x16L\xd8}\x95Y-\xe0\x011\xde\x89G@ \xdb\xcd\xe0\xf0\x92\xb1\xbb\x80\xc6L\x95\xd6Os\xd8\xc5\x94\xa0\xf3[\xd5\x0c\xc9\x06$,\xf1\xb1\xe6|\x80D\xcafQ\x1d#[\xa8+o\xb3\xa9\xda\x7f\x86\xc7\x93\xd8\xdb\xe9\xbe\x1a\xb7R\xbc\x05\x08v\n\x13\xe3\xfb\x18iG\xf4\xbahU\xa1\x90\xfc\xaf$\xbf\xa2YPeL\xec\xbbR\x14\xd9\x85\"\xbb\xe7\x16\xc5\x10\xa2\xe7\x85\x1aW\xd6\xda\x9f;\xea\xe6Ip\xdan0\x1a\x81mu\xd1\x06\xa9Y\xcf]\xf3`\xcd\xe5U\xb4l\xfc\x0b\xb2g2\x06T\xdak\x81^c\xb1p\x05\x95A\xb6\xb7\x13\x08\x16h\xc3\x12\x9aP\x8ef\x89E\xf5\x1d\xcc\x95\x81\xdcNe4\x8f\xa6\x92\x92U\xb8V\x0bip\xeb\x83\xbeyp\xab\x95fa\xc2\xf7\xf6m\x11\xe5\xfap\x83\x81\xab\x83='bS\x92m\xe28\x1b6\xbd+\x12\xcb\xfe3\x1c\xcb\xed?{j \x1bWo+\xd8/\x03j\xf2xH\xaa\x8e\x8aB\x9a.e(\x882\x91\xe6\xd9\xb2\x9a\xb2\xe4i\xcd\xfd\x8f\x18\xa4&\x8cR\xb0\xae86Jku\xa5\x8c&^-\xed\x1f9Knj\x1f\xa0\xd9\xb2Y\x9dH\xad} asRs)T.\xb2l\x0c!P\xc9\x01\xb9\x1c\x92l\x9c\xb0\x94\x87\xebN\x97\xaejr\xc1\xc7\xdd\xd6\x04\xfc\xba\xe9\xa2\xa6\xaf\x9a\xafF\x95r\x1f\xf5\xac\x98\x91C\xb4\xf2b3V<\xac\xc3g\xe6\x0eRIl*y\x16H}.\xad\xd7D\x15\xdf\xf9\x01D\xe0\x96_\x81\x18\xcb\xa6\x1f\x0f\x99\xac\xafZ\xaa\x0d\xfb\x94\x88%\x15TW.\x85\xd0\xc1\xee\x8c\x8e~\xdf\x19=\x1bo\x8f\xce\xb7\xa7\x83\x87A\xf3\x98}8\x9d\xed\x8c\x9e\x9d\xff\xe5\xcf\x0f\x9bG\xed\xc3\xbf\xbb\xbf=\xfc\xed\xe1\xa1{\xb8\xf5\xdb\xc3\xc1\xec\xef\xbf\x1d\xfe\x96\x9e\xffe\xe0\xfev8\xfb;\xfc:\xac\x97\x02\xb3\x04\xe7\x0fgH\x9c\xaf\xe2\xcf\x17\xf1\xe7\xb7\xdf\xc4\xdf\xbf\x8b?\xff\xe5\x9ck\x03\xa1\x99\xf3B\xa4|\xef\x0c\xc9w\xcew\x90\x07q\x80E\x81\x04\xfeF\xf07s\xce\x07\xcd\xd3{\xe6|WV\x15\xd6\x00\xe6\x00\xf0\x1f\xa2\xf8C\xf1\xe7P\xfcy.\xfe\xfc\xaf\xb2\x90W+\x14C\xa1\x12\xfe\x7f95s\n\x1fFd\xb6-\x87\xf4h\xf4\xb7\x8b\xd1\xf9\x1f;\xc3'{_\xeb\xa3\xb0T\x83\x8f\x80\x0e\xdc\xf1_\x06u\xf85ja\xf8\xdftM\xa5!\x1b\xce\x958\x06\x80\xd3\xe0(j\xd6{\xabo\xff\x89\x05\xfa \x88\xcb\x84V.r,\x86\x89s[\x99\x05\x8f\x976\x83\xc8y`\xe3\xdf\x1ch\x84\xd3\x92\x99Zs\xe7-%Uk\xacEE\x83:\x87\xedF\x9d%\xfb\xe8Yri\x93q\xfc\xff\xec\xbd\xeb~\xdbF\x928\xfa}\x9e\xa2\x84\xec8@\x08R\xa4\xe4+mZ\xeb\xc8\xcaF3\x89\xedc\xd93\xbb\x87V\xf4\x87\xc8&\x89\x18\x048\x00\xa8K\xc6\xdeg9\xcfr\x9e\xec\xff\xeb\xaa\xeeF\x03\xe8\x06@\xdb\xc9dv\x07\x1fl\x11\xe8{\xd7\xbd\xab\xab\xe8\xfa:\x17<\x06a\xa6\\\x8d\xc9\xbc\xa2S\x95\xa6\xe4\xb5\xd2\x1b/4R\xa7\x94(\xb7\x1a@\xdde\x0e\xc7\xa1Q)I\xe9\xdb\xec3\xe2\x12\xbaF,-)\x05^\x05i\xb0f9K\xe1\xebm\x1a}M\x19\x05.\x19\x04\"gU-\x81\x80\xc9Q=,<\x01_.\\\xe7\xc81(s[\x94Q\x8b\x14g\\h\xd3\xea|\xe5xp\xc4\xe9\x02\x8c9a\xa8\xd7\x8f(S\xc6&\n\xf3\x9a\x97z4\x1d\x9e\xc3\x04\xff+\xaeV\xbd{\xb7\xbfD\xf2d\x18\xf0%\xa6\xfb\x99@4\xf89 \xe3Z{|\xf5x\x91\xcbA\x9e\x86k\xd7\xf3a\x0fS\x8d\xcb\xb4\xc54\n>\xe6\x06\xf3\x17\xef\xe7\x02&\x90\x91#\xc3\xa5Ew\xbd(\x07\xf0\x16\xcc\xff\xb2\xcc\xf9/\xeb\x02\xc3\x05J\xc1\x17\\\xf8>\x92\x81\xd0\xa4\xd4\xc1\xdfV\xa4\x8e\x1c\x8e\xe0V\x80\x9bV\x18\xc3\x96\xe6\xa9;\xf2T\x10n\xe3\x07(\xa2\xad\xc9N\x1c\xa7\xd2\xc5\xdf?\x8a82e\\\xac-\xfe5\xd7\xd6\xcd\x8b\x82\x91\xffl\x8by\x02\x13py\xe5\xeb\xe9\xf0\xdc\x1b\xe4\xc9\x0f\xc95K\x8f\x83\xcc\xe8>^\x15\x08O|\xa0-\x15\x13\xbb\xaey\x1f@m\xb4x\x19\x81\xab\xa6\x18\xc1\xf0r\xb0\xc6H\xea\xfb?q\x96=\xfd\xe9\xdf\xdf\xed\x9f\xf7\xfe]\xfc\xbfo\xbc\xef\xca\x87\x8dn\x83\xfb\xfb\x0e\xc2\x8e\xea~\xe8\xc3\x81a\xd4{7\xd4\xdd\x9d;\xb0\x9e^\xe3\x8dZ\xb74\xec\x03\xaf&\xd5V#\x91\xd6\xe7\xb0\x87m\xf1-,\x9a\xdf[N\xaf\xcd\x97t\x95&}\xe6\xc3\xb1\x8f\x9e\x87\xfd\x91\x8f\xde\x82\xc3\xc7\xf0\x0c\x9e\xc0F]\x85zfNP\xc6\x1f\x81\xec\xeeK\x1c\xbeD\xf4\xcd\xf4\xd9\xb9\x88/\xdc'tz\xcf\x87\xf4\x12\x9e\xc0{z\xcd\xfb{iP\xaa\xb8^J-\x1e\x13)\xa1\xcaGpY8\xffpJ\xf2\xef\x98\xa9\xbb\xf6\xd2\x87\xf7\xa2\xdf3ZO\xbcw0\xf4\xe1\xd8S\x90\x81\xaf\x8e1\xa1}YM\x98\xb3Y2go_\x9f\xaa E\xee\x99\xe7\xc9\xb5\xb1(\xbd\xda\x82-\xba,\x18_\xf2\x97\x8f\x8bi\x96\x17n\xf1y\x0bG\x15d\xb1K \xfce\xddG[\x95\xf7\x95Uy\xef)\x12\x94f\xec\xfb$\xcb]\xaf\xae\x14\x95\x7f\x7f\xf8\x00\x8e%\xb3\xd6+<\xd7&\x9c(U\x12\x8e\xe7\xce\xb9\xe9[\xe9\x974'\xf4adP\xd5\x11\xec_\x99\xef\x81+\x00\x7fS\x1d\xb2\xa0\xec\xfb\xef\x06\xfb\x9e\x0f?r\x82\x83\xbb\xe8\xc3\x1b\xb9b\xb4\xa1?6\xee$\x88Y\x9e\xc2\x04\xdeL\x9f\xb5\\\xa2?Et<\x15\xd4e\xdezq^\x0d\xffgA\x85_\xd0\x10_\xc3\x04N\x15\xa0\xbd\x80'\xf0\xfa1\xbc\xe0\xa3<\x1d\xccVAz\x9c\xcc\xd9\xb3\xdc}\xe1\xc1S\x18\x1d<\x80#\xf8\x19z\x13pn8\xcf\xc5?O\xa7/\x1a\xc6\nrY\x7f\xee\x97\x8b~ \x19\xc2\x198\x1e\xf4\xe0\xd2\x80\x15\xcf\x8b\x12\xedc\xb9LY\xf0\xbe\xb1T\xdd\xbc\xd4\xfc\xa5\xfe\xd6\x88GO\xe1\xe0\xde=\x99\xeeA\x1b\xbd\xe3H\xc9\xc0\x86\xe8eV\xec\xc3+-vvQ%\x1d\xe4\xc9\xb3\xb3\xe3\xd3\xd3\xf2\x17\xd3\x05b\x0e2\x7f\x93\xbd\xa0\x15\xe6\x08\x9c1\n\xa1\xea\xcd\x98\x83\xbeq\xbe\xdfu%D:\xe9\xfb\x0ez\xf07]\xe8\xeai\x8d\xf0))\x01\xc8\xba\nRb\xf2\xcd\xeb\xdb\x07\xce\xbb9\xccp\xea~)\x08\x9d\x06H\x97^+\x1f\xbf\x9a\x9e\x9c[.E\n:\xc5i\xd6\xac\xe06\xad\xa4\x8a/\xf5/\xbc\x8e\x95L\xf1\x8e\x05//\xb8\xd1/\x8d\xa8\xcf\x1b\xfd\x96\x8b\xd8q\x8dm\xfe\xd2\x80\x02\xdf\"\xc9\xff\x05\x97\x05\xabg\xb3`\xc3x_\x8a\x17!y\xfe\xc5#\x84\xfa\xd6L\xde\xeb\xf0^\x97A\xffR\xe2\xad\\\x92/\x18\xef_\xb4\xbd&\xcb\x9e\x92\xbe\xfeR\xe1\x8aC\x1f\xfeR\x05`\xde\xfc\xf7\xe5\xe6\x8f\xaa\x88\xaf\xad\xe9\xf7u\xf1]u\xf7\xbdW\x11\xb1\x8b/RH)\xc6*\xcb\x94\xa4||\xe9\xd5G\xfd\xfd\x8eb\xfdeQR\xd3A8\xb1[NO\x10\x90\xcb\xb8\xa1\x82w\xab\xd2\xa6\xfa\\9\xabj62\xbb\x18\x0d\xc8\x04e\x05e\xd0\xea\xd8\x04\x8d\xbf\xaa\x88\xb54\xc1&R t\xaf\xbfA\x0f\xfe\xda\x80\x89\xba\xba&\xf43\xfc[\x1a\x16+JP%^p\xdd\xc8i:eU\xd4\x05\x05P\xc3\xa0\x992~\xe2?\x06Lc\x9e\xa7\xc5\x199|\xb6\x1f\xfa\x9c\x88\x92 \x7f\x02\\N\xae\x03\xae\x8aM\xac4'\xec\xbbNhc\xf3&\xd4\x0b\xa6Z\xcc\xe2\x95\xadPh *\x1b @\x96\x87YP\xed#2\xcb\xdd!\xf5\x14+\xe6\x18#\xc1*\x9c\xd1\xb0.\x86\xe0p\xberD\xc0\xc7r]\x0ex\xfc[\x0f\x8f\xad\xb6r\xe2\x18\xa8\xabR\x94/\x14-\xca\x16ij\x0fB>Ht7/phz\xf4\xd5y)ZOSLQ#B\x96\x89\x8a\xc7\xe5E\xec{\xab:q\xber|p\xfexp\xe8\xe0\xd7\xd4FEL\x87<\x96\x83\x18\xdc\xa2\xf2\xe1\x8b~.\xe3)\xba\xd5\xd2\x97\xe1\xf4\xc7du\xac\x18\x1d\xcd6\x91\xdcl\x16\x85\xe24K\x1b\xa1O\xd4\xb0\x81\"\x97\xe2\xb7`\xbb\x14\xc2\xa5\x8aQ\x9e\x8f\x14e\xf8\x18\x02x\xa2\"\x84>\x86\xc0\x9ef\x1d\xfdO\xa6\x81\xc9\x83q\xba=\x17\x086\xdd\x9e7\x8c\x8eB\x93\nQ\x02\xbd&V>\x97\xaa\xc9\x96\xc89H\x11\x0cH\x1d\xf5i\xdc$\xae\xcb\x0eL\xe1\x1c\x85\x82\x90\xd4\xba\xd1\x9c\x93\xd5\xc3\xac\xa2Uu\xf8\x18\"x\x02E\xd6\xf9\xa8Y\\\x9c\xc1\x04\xb2id\x11\x17\x1d9\x16B\xb5\x19\xe1\xf1tF\xd1\x08f\x06\xf1\xd5z\\\xbe\x9c\xc6jf\xe2:zI\xc0\x88\xcb\xd2E\xacNN\xeb2\x86ya[6\xadXW@g_\xf5\x8bHU\xd3\xa2\xa3\xb4\xbe\x9c\x16u\xcem+Z\n\x96T\xdd\x9e\x0dm\xcf\xa6dB\xda\xb4\x1b\x1e0\x04\xf1t\xd3\xa0\xcc\xc7\xd39\xed\xc8\xdc\x12K\xcc\xf8\xb6\x11L;l,\xa1\x82f\x95-\x16\xc8\xe7\xb8\xc09\xf8\x87\x0f\xb0./\\i?\x99\xfaQ\x9f\\CD\xb7R@D\x97U\xc4\x16O\x9a\xf4\xf7\xb9\"\xb0\xd2X\xee\x9e\xcb\xa4\x8a\xb8\x1a\x90=\xc0\xabEx\x92O1\x83\xa2\x162*V\xd2E]V\xd6\xaf=$\x07\x1c\xa8VB+\\)\xe3\x03~]\xe9\xfe\xf8\xf5\xcf\xa5\xf5Y c\xc3\xbe!\xdf\xbbmC\x94\xf0\xcf\xc4\x9f\xbcM)\xff3\xfa\xcb\x17\xd8G4LL\x93+\x0b\xb14\x922\xfc\xc3\xd7\xb1tR\x999\x13\xeat,}+\x18\xfeQ\x9a\xc2\x87\x0f\x107H\xff @\xfc\xaa\x8c\xe8\x16\xc1R>x\x04\xd8\xa2\x03\xf0G\xd1\x90+\xe8\xc1m\x87\x05T\x18\xa1y\x99\xe8\x02\x91\xa2\xd4\x9f@\x83\xe4IU\x99\xce9\xe2(\xa1x[H3\xf5\x05\xb8(\xed\x173\xb6\xc4:\xb5t\x0d\x13\xb8\xe0\x8d\\\xd2\x16a\x9bD\x17E\xedz\x9d\x13\x98\xc0u\xfd\xf5MmR\xdad\nL\xe4\xfdL\x0d\x11\x17\xcf8\n\xafJ\xb4\xa0<\x90z\x1b\x1a\xb9\x06:\xfc\xd0X\x8bA9?\x13\x1c\xa5\x84\xa7\x1a\xdc\x92sN\xb1\x08\xae\xe0\xe77\x1c\x81\x8f\xe8\xbf\x89\xfc>\x86\x1b\x85\xb0\xf4\xca\xf34t\xe2\x0d\x97YM\x99@P_\xac\xdc5\xabu\xbd\xa2\xaeW\xd45\x93]\x17\xb4\x82\xa9\xae\x15q\xc2\x0c\x7f>n\xedu\xad-D\x135+^\xef\xc23\x13\x01)\xca\x90R\xa6\xba\x8e\x15\xb6[ B\xa9.\xbe<\xd2\x7f\x8c\xb5\xba>t%T\x1c\xbc*WY\x903\xf0\x8d]\xa9\x13[<\nso\xe8*\x8b\x0f7\x83M\xb2\xe1\x18\xc9\xdf\xdcH\x17\x96\x95\xd7\xb5[K\x7fx\x08\xffb\x1bE/\xd3\xb71Et\x9e\xbb\xb2\x19\xa3|\x8c\xe0\xe7\x95\x17M\xad\xfa\x8d\xe4A>\xb8\xaf\xb8\xd2\xbc\xe7\x16@H\x7f\x15\n\xed\xbf;\x1eyD\x17\xdf\x04b\xfc\xbb#\x8e\x92\x14\xf1~U4\xac:+\x0d\xe1U\xc1\xfd\x1a\x88`\x87\x85\xf2A.\x89[`=\x8eF{/\xe9?\xdf\"E\x93\xb5\xf2p\xa4\x13\x901g\xa2\xa8\xb1\xc9\x11\x1c\x15\x83\xc1\x8f\x9f*\x02\xee\xdd(xQ\x93\xdcT\xbd\xf6J\xbd\x8a\xb1\n\xad\xb5\x18D!\x9dJ\xd2\xd1*\xe9+\x99\xe5\x98v\x1e\x8dw\xfd\x91\x87^\xb0\xefiA\n\xca.\xff\xba)\x0c\xfaB_w\x06\x84e\xc7\x88q\x03\xf9\xcb\xd3\x10\xf0X\x9c\xef\xfa\xf0\x12\xfb\x92\xb2\xe6Kx\x8a\x12\xe8\xcb~\xdf\x03\xd9\x0e\x1e\xc0\xdeL_\x9e{\x9c\xd4!L\xcd\x98\xfbR\xdc\x7f+:\xe0J\x7f\xf9\xb3O\xa6\xe81<\xc3\x81\xd5>\xf6\xfb\x06Z\xbcG\xe7\xd5'\x16\xc3\xf7c^\xed1<\xf34*\xcb\xc7Pi\x89\xb2\x10\xead\x9a\xaf\x95\xb8\xfb\xf0\xf0\xfe\xdd\x07fM\x8ck\xfc\x87\xf7\xcd\xdff\x18f\xdc\xf8\x89\x83\xf9\x81\xa5\xda\x867\xf9\xd0\xfcm\x0e\x13xP\xbd\x13'\x1f\x8ez\x0f\x0e\xcc\xdf\xb8n9:\xb0\xb4\x8a\x91\xf1\xfa\x16]s\x89~\xc97q\xbf\xbfo.\xc0\x05\xa1\xfd\xe9O\xefn\x0e\x86\xfdw7\x0fN\xce-\xe5.\xb1\xdc\xbb\x9b\x83\x93w\xdb\xc3\xe1\xf0\xe0\xdd\xf6\xbb\xef\x86'\xfc\xdf\xfb\xa3\xf3\xfd\xa5\xb9\xd2\x855\x8f\n\x7f\x92+\x96.\xa2\xe4z\x0c\xceK\xf5'Em\x8c\x19\x9bgp\x1d\xceY\na\x9c\xb3%K3\xc8\x13\xd8\xa4\xc9\x8ceY\x83b\xed\xc4I\xde\xbf\x0c\xb2p\xe6\x8c\xc19\x8d\"\xb6\x0c\"\xd1*\x17\x1dn\x1e\x0e\xc1\x8d\x93\x1c\x02\xc0R\x80h\xb4I\xc28\xf7\x9a\x9a\x0d\xe3\xab \n\xe7}l \x9b\xa6\x17\xd4\xb49\xf1\x9d!\x9d\n\x08\xc55\x82>\xcc\xcc\x9f\xb9\x8e\xfac\x90\xaf\x06\x8b(\xb1\xe5\xae\xe4:\x01\x19\xb5\x07\x8b4Y\x1f\x0bo\x1a\xcd\x9dX>\xca\xad\xf8\xcc|<\x00*\xc6\xfe\xeb ^\n/\xdc\x8b)3\xdaE\xed\xad\x1f[o\xd4A\xd5\x1e\xaeB\x85\xa2I|z\xfe\x18b\x0c\xc4\x9eR\x84X\n]n1hI?\xe5\x9d\xc6\xf6\xbeql\xc5\xb0\n\x89\xc2\x0e\x07\xa9\xe1\x00P}\x93\x02y!\xef\x82<\xf8\x89\xb98\xd5\x03\xf4\xfbC\xceON=)\xf4\xe0\xd8\xa5\x13Su\xe6r\xe9s\xc9\xd6S6@\xca \xeb\x15N;;\xcd\xfe\x99}\xdf\xd5\xb6P\xac\x06\xda\x0e\x1f\xaf:\x0d}\xe1D-\x05\xef\x84\xae\xa9\xb9\xa4jk\xee[I\xaf\xe7y\x1c\xb5\xee\xdd;xt\x9f8\xc7\x93 \xdc\xbb\x7f8z\x84R\x0b\xaf\x08G\xfc\xc5\xc1\x10\xe3\xa2\xdc\xbf{ot\x00\xe24\xad\xde\x96G\x01\xce\xb8\xbc\xea\xba\xa3\xe1\xc1!\xdc\xe1\xbb\xf7\xe4 \x8c\x86(\xc5\x88w1\xffq\xff\xde\xbd\xc3\xfb(X\x89*9\x17\xa0\xb8r0\x06\xf5\xe6\x0b\xc2\xd2K\xfbj\x8a\xf6\x10\x13\x9a\x8f\xe4\xe4#O\x9el\x00\x05\xfa\xbd\xa1\xa78\xd7{\xa0\x0e}\n\xa3!\xdc\x01\\\x9e\x0f\xb4\x1dB\xa0\xa1\xb5\xff\x00b\xe5\x18\x1d*\xf2&\x0c!\xcd\x01\xcf\x02\x05\xb4\xed\x08l\xaf\x1aQM\xcd\xa5\x07\x07\x07\xd0\x83\x07\xf7\xe0\x1bp\x19<\x81\x83\xfb\x1e\xf4\xc1u\x87\x18\xcd\x0c7\xfb\xden=\xbf\xb1\xdd<\x90\xcf\x95\xb8\xfd`I\x89\x82\xb8\x80\x98 Gp\xe22\xd8\x879\x06\x95\x03\xbe\xae\xc2G\x81\xde\xe7\xdec\xdc\x8fk\xf8\x06\x16\xf8\xf91G\xe4 D\x1e\xae6\x95\xban\x06\xbb\x13\x97\xe3\xbe{\x8d~3\xf0\x0d\xf0*._\x99\x8d\xb7\xdb\xc4\x7f\xb4\xc3\x98\x86\xdaz\xce\x18L\x075\xf7a\xe9\xc3-9\xe2\x98\x8c\x9a\xf2\xb9\xd0I\xb6\xb5\xd4\xb5\xf9\x16\xbe|8\xbf\xba\xb2\x7f>\xae\x1b\xc8\xe4\x83\xfb\"(\x85\xeeA\xbd\xf6f\x82\x82\xd0\xf3\xe1\xc4\xbdF<\x86\xa7\xc0'xc\xe8\xea\x86\xf0\x9d\xca\xf1\x89\xfe\x11\xb3\x03_J\x0b\xd1u\xaf\x87\xa1\xa7n\xba\xfa\xfcA\x81\xfb/\xdd\xcb\xddp\xfc\xf4sq\xdc\x87\x0b\x9fC\x9b\xb8>QMr!\x1f\x04\xccK\xe9\xc3\xf5\x0c]\xb6\xa4\xb0\x96#\n\xa3\xa8$\x84\x83U\xc9{\xe1\x92c\\\xe0\x11tN\x83s\x8e\x9e\x02\xd5\xde\x13j\xdd\xb85\xaf\xa0R\xc7)\x06{\x99\xc0{\xd5g\xa2\xd5^{\x84\xd9\x97\xed\xa8\xc5\x91)k\x19\xdcS\x91\x81\xfc\x16\x9e\x88,\xe6\xbc\xd6m\x837\xa8h\xba\x0fy\x81\x1a1G\x0d\xf7\x02c\x82pBn\x02\xda\x98C\x12U\xe4\x84\xfe\x82\x96rk\x1a\x9f\xb5o\x10\xa6\xc7\xd2\xea\xe2\xf8{\xbd\x18\xa1\xb8\xde\xef-P\xda3\xfbb\xc9\x07g\xc6IK\xec\xa3\x8e\x1a=\x96\xc8\xcc\xd1q\xce\x919\x14\xc8<\xe7\x0b\x17j\xc8<\xc70(\xdec\x98\x0bd\xe68\xb8\x81>\x87<\xa9\xe8,\xfd\x02\x04^\xb9K.\xf3\xc2\x1f98\x0e=O8\x15\x9c\xb8\xc7\x0dF(O\xf9\xb4\x13OAj\xafW\x97\xf0\xf4\xe7c\xaf\x17\xf3R\xf5\x84S\xd0\x86\xc7\xef\x9b\x84\xa4\xea\x9b\xadU\x17\xbebi\x16&\xf1\x18\x1c4\xe6X\xb4\xd0\xed,;0\xe5\xb2\x96\x0f] \x1a\xc33;\x9b%\x1f\xb01\xbc4O\xd5b\xb4\x10\xed\xfeh\xfe,\xdb<5\x7f\x16.\xf6\xe3\x8e\x12\xb1\\\xd8\xee2\xb4V\xebv\x90\xb3,\xa7\x98|\xceM\xdc\xef;\xd0#\xd2iJ\x99-\x9f\x8f\x16\x02n\x9b\xcf\xdb8\xa4\x19w\x1b\xdfg\xcdh\xa9\xcd\xe8GW\xe6\xa6\xb9[\xb9k\xf8i\xf3\xab\x83\xac\x0fZ\xbeD\x94n\xac\xa6Y\xf9\x88qn\xeb\x8d\x15\xc1nP,g\x14\x02\xd3\xd5c}$\x15\xffC\xdd\xe3\xcf\x90\xe6\x86\xffy8\xb2d\xbb\xe9\x14\xdfC\xef\xbc<\x1f\xe9\"\xd8\xb6\xabb\xbe\xa6\x0c%\xe5\xb9\xf8\x95\xe6\xc9\x91\xaak\xf3\x16K\xab\x88\xf58i\xeb\xec\xc56\x8a:v%\"\x85vjR;1\xde\xad\xf5\x1dC\x89u\xda\xcb|@\x84 \x0d\xf8\xf2\x16z\xec>|\xf4\x88+\xb7\x03\"Kd\xdd\x97\xde\xc9@q\xaa\xba%\xf3.\xf7\xaa^+\x91,m\x8a5\xd2\x12\x99J%\xb1\xa9e\xf0\x81\x96\xb0\x87>\xd4l\xf8x\x84\x81G\x89w\x1cbzxC\xd8\x99\x18\xf2\x8a\x07\x86L\x90\xa19M1zC\x0c\x853D\xe5\xc89\xa8\xb7\x8cqE\xde\xf5\xf6+\xc29\xd3\x0ckU;\x8ct\x01\x1d\xb1\xc3\xca\x888\xac;1\xe6\xa3\xd1q \x1c\xac\x83\x9b?\xb3[\x14v0\x85\xa9zch:\xd2\xcdW\xa5\xaf\x99\x0c\xf5\x19I\xc9 \x13PV\x1bQ\xd61J\xa4\n3\x8c,\n\xbd\x9e1\x833zLJ\xa9{\xe5\xa3\xc9\x9eMg\xc5\xfd\xff-\xfaQ\x0fm\xc6\xc55\x17\xaf\xd5\x81\xa7)5\xc6\x1a\xed\xd7p\x04\xee\x02\xcb\x16gTk!D\xa9wk!\x8c\x8eEY\xfa\x8c\xc7\x94s\xf3\xed\xe1\x85\xe7\x83\xe5b\xf1\x86k\xd6n\xe0\xc3\xdc\xa3\xb0\xd3\xd39\x1e\xb4\xf3\xffI\x16[a\x1cTr\xe0\x9c\xf2\xff}X\x9d\x17\xafV\x16\xec\x87\x02a\x82\x02\x0f\x8a\x89\xe3\xf9\x97\xcc'6\x083\xfc\x9f\x83e\xab\x8by9Q\x90\xb8\xba[CJ\x19&\xb2\x1ecgw\x02\xa1\x8f9m\xf4IWYld\xf8\n\x030atO\x89\x94\xcdA>\xebpB\x95/)gTKm.)\xe5\xe9\x96a\x94\x8bE\x10e\xcc`\x8a\xa4\x06\x05>6\xe7B\xc9\xbe\x0b\xe30g$\xb1\xd0\xc1s\xbd\xbd9[\x04\xdb(ol\xc9q,@\xf3\xd1\xcc\xce\xeb\x84\xb2\x16sX\xb4l\xa7\x97\xbe\xc6\x0dA\xdef\"\x91\xc8\xb3\x1c\x7f\x1eA\xe8\x06(\x9b\xa8\x01\x046\xea\xc0I\xa4\xe1\x16F\xea\x06x\xb5\xc2\x90wW\x8c8qI\xe3\xe3\x9d\xf1\xbf\xba\x08\x92R0\x83\x9e\xb9Of\xb22\n\xa3/\x86\xc2\xb2\xd7\xe4c\xa9\xde\x1c)U<2W\xdc\xd24\x1bF\x84\xf0\xf2\xfb\xa2\x04\xe6`o&\xd6O\x0e\xfa\xeb`\xa3\xe5\x92\\\x07\x9b\x1a\xdb+\x9d\x85M\xcfKV\xcb\xe2\xb8%\xed\xf5<\x99\x035w\xd94\xe5\x05-\xfe*\xd5d\xa8\xa0q{\xcd\x81\xbfy\xbd\xae,\xf9O\xcba,\x99\xd7Y\xb6\xa1 \x97\xbfR\x1a\xd4\xda\xea\xef5\xeb*fb-\x9fn!0\xe5#\xc6\xee\x96\x82.\xe5\x82\xde\xc5\xec\x1ar\xb7\x80(\x97S\x8e\xcb0\x0e\xd2[\xc7\xf3\x8a\xd7\xcee\x90\xb1\xfbw[-\x07V\xa5\xe8\xde]O$M\xed$\xce^iY)\xcdA\xdd\x0f, \xcf\x0f\x87\xe6\x84\xe7\xf7;\x05\xf47\x1c\xc8(\xde3\x01\"\x9d1\x14\x19\x0bb\x91\xb1 uC7\xf6\xd0\xc2\xaa\xc4O_$ \xc6P\xacB\x17\x8e\xd1\xbeV\xb8\xe6 un\x81*}@\x9f6p\xc9 \x84\xbe\x8c\xd7o\x14\xc7`\xf0\x84\xe6\x81\xf0\xe0)\xad\x1a\xaf.j\xa5\x9eN\x14\xd4\x90\x13\xf4n\xc8p\xa5%\xfe5E\x84\x1f\xd57\xf3n\xdb\x86YfL\xb9\x16\xe0\x03\x84m2\x92\xde\xc0^C\xc3\x16\xed\nt2\x9b\x9bQ\xd0\xaa\xaf\xc8\x95-.\xfb\xf9\xb0?\xfd\x89\x02\xf2\xbd\xeb\x7f\xf5o\x7f\xbc\xf3\xf57\xbd\xc1\xbb\x9f.\xfe\xcf\x87\xff>\xdf\x0f\xa5m\xc5\x12\x88L\xfaw\xccVA\x1a\xccrtD\x81\x15\x0b\xe6,\x85E\xc8\xa29\xc4\xc1\x9a\x99\"h(\xf2_\xb2\xd2\x94\xd1\xda2\xe7\x8ef\x87\xb6iW\xf5msg\xa9\xb93\xc9 \xcc\xd4/f7\xba\x19\xc3F$Ak\x88I\x7fK\xbbqWL\xd0\xde\x16\x7f\xe6I\xcc\xc6\xba\x8d\xca\xe0\x10\xa8?\"6\xbb\xd9\xb0\x0b5Rk\x7fkH'%\x06\xbc\x1a\x849\x85\x88\xa7s\xf9)%/\xa5\xb7y\x92\x9e\xef`D\xab\x8f\x13\xe3\x97u\xda\xca\xc4\xbc\x95\xe8\x9f\xb8\x0e6\xa8\xf6\xfb\xe50\x81\x89\x0c>z\x12\xccV\xed\x81\xb1Us\xc1f\xc3\xe29%\xbb\xa9\x8f\x98n`\xa3G\xb5.\xab \x85\xc0\xd0]\x97\xbe\x18:\x98\xb3\xe9\xc8\xe4\x94T\xf4\x88{ \xc4\x93%\xcb5\xa1\xe4E\xb0f\x99\xcb\xbcz\xff\x9d\xe7:\xcd\x1b:\xef\xb4G\xa1\x9d\x9e\xb1\xc1e2\xbf}\x9b\xb1\xb9\x12\x1e_\xa5\xc9:\xcc\xd8 exC\xbaB\x9c\x9eE)\x0b\xe6\xb7\xc0\xffuL\x87jE\x8b\x18\x90\xad\xd3\x00\x83f[\x1e\xbb\x96\x83j\x0f\x02\x0e8\x84$\x8e\x92`\xde\x05\x05\xf8\xc3\xc5\xa6\x94e\xdb(\xb7Y\xe4\xb1I\xc6W\xa0k\x9b\xb1\xcb\x06X\xa1\xb3\x11\xbc\xdb^n\x9bI'_\xab\xef\xc2\x88\xbdFva\xa6R1\xca?&\xe7$I\x0f\x06|w\x9feZ\xb2c\x12\x97:\x8d0k\x826\x94\x9dj9\xef\xabn\xfdP\x99Q\x91b\xd8-\xa5\xe9l\x98A\xc6\x08t\xf5\xaa\x18\x82B\xa4j\xec4\x95\xa8)K\x05\xe2\xa9\x0e\xeb2\xdc\xd1E\x18\x87\xf9\xb7\xc9\xfc\xb6\x93P\xcf\xd7\x85\xaa\xf1\xb6N\xe3\x10\x19\x97\x91\xc6\xe9UL\x07\x01\x1e\x14\x0d\xbda7\xd8\x90\x9d\xf3i\x17\xc1.\xa3\x04\xc3\xda|\x1b%\x97\x9a~\x15f\xaf\xe4\xdf/\x17B^\x91\xed\xf3\xa2\x9d\xdb_$\xe9\xfay\x90\xa3\xf3\xf4w\xe2\xef\x8e\xfd\xc8\xe2\x9d\xfb\xa2\xcb\x05\x18\xcc\x15-\xaco_\xffp\xa6\xbd\xea\xd8\xad\\>M\x9d\xea\xd4{P\xa0\x0c\xe0\xf5d\xb9\xb4\xebJ\x07\x1an\xc1\x84\xe3\x8cL'\xeaC\x0d\x1a8\x1c\xf3\xf5v\xa7\xc6\xfa6\x97Uh\xbe\x07.\x1f\xbcXT\x1e\xf9\x87\x0f\xb0\xa7u\xd0\xb0f\x80WH+\xb2\xac`\x15\xdb8\xdbn\xb8\xa8\xcf\xe6\xf0\xad\x9c\x0d\xaf\xd9\x16\xfc\xada\x95\xecH!s\x94T\xb7\xd0\xe6\xe2H7(\x90Lf\x9ci\xbb\xce,\x89s\x16\xe7}\x1a\"\x1e\x1a\x9a\xb0LE\xc6\x11u\xb3Z]\x1f\x9c\x9c\xdd\xe4\xfb\x9b(\x08\xe3\xc7\\\x8c\xcfX>y\xfb\xe6\xbb\xfeCG\x05\x97-\xb0H\x86\x8cRo\x06\xbc\x95.\xdd\x18\xaayx\xd1\xf5\xd3\x91@\x8d\xa6qz\xc1f\x13\x85\xb3\x80S\xb6\xfd\x9b\xfe\xf5\xf5u\x9f\xa3x\x7f\x9bFda\x9bWgm\x94`\n\xec \nxI4\xa5\x95\xbf\xca\xeb9!\x8521\xef/\xf2\x1b[@j\xbdPy\x11\x0db\x90\xc8\x04P.\xd6\xa5=\x0dz\xad\xcd\xb6\xe2v\xa7\x9e$\x954`\xe1,\xd9r\x8d1\xc9QdS\xe4\x17x5\x082\xe0\x8bnC\xc8\x1d\xc6\xcc\xb1\xadj\x9d\x85BP-\x91\x97\x0e[\xac\xf3\xd8\x1a%8\x92;\xcfq\xd4\xbeO\xa5\xe5\x17X\xc7g\xebz\x83|\xc5bwk2D\x8b\xe1\xe6D\xfeZh\xd2m \x8ak\x05\x06\xc1Q\xda\xfb\xd85i\x88n^\x98\xf74Kx^\xb1\x84OQ\x956\\yq\xf3i#\xeb\x95\xda\x8b\xddU\x0b*+\xa6/D\xa7\x95\xfb\x0c\xb4\xe7\x00\xbe#\xda\x97\x91\xddB\xd1uQ\x8fj,\n \xae\x15\x9dt\xb4\xe7#\x94\xa8\xbah@\xd5\x9f\xb3$\xfe\x9c\xb6\xfft\xf6\xf2\x05\xf9qX\xa9W\xe9\xbdMY\x98Y-\x18\xf2\xcc\xc5U'\x80\x7f\xff\xe8\xa1\xeaP_\x7f\xa4\x15\xba\xb5\xc4x\xe6\x0f\x06\xf5\xddhK,\xab\xeb\x0d\x92\xd06%\xb7\x85m*S\xed\xccR6gq\x1e\x06QFn\xdf\xc5o\xaeF \xf9\x00\x8a\x00\xb7\xe2\x05\xa1X\xe22\xf9FE\xfe[\xb3|\x95\xcc\xb11\xfaS\xbe'\x87\x19\x86\x7f\xf8t*\xaa\x1cx4I\x18\xef\x1cC\xe9\x9d_\xb57\x18\xf6P\x13\x0ci\x96\xca`i^~\xc3\xec\xf3\xd2o\x19\x98\xb3\xf2\xceI\xd6a\xee\xf8\xb0W,NE\x98\xb2/Vn_\xacv\xd2W\x98;\xf3\xe4\xedfc\xcf\x04\x00\x05\x1a\xdc*\x8f\x0ftF\xef\x8f\xb8\xbcit\xe7\xfb\xe8\xe6r0r\xe2\xc5O\xe7?N\xde\xa8\xe8\x87k\xe9\xf8\x84\x7f\xa8\xc2\xe2\x87\x96\xc5)e\x0b\x96\xa6( \xd0[\x17\xdb)BRj\x1d|\x7f\xf2\xecy\xed\x0b]\xc7\xb7\xc0<\xaa\xdex\xd12\x8a\x92k6G\xb6\xf0\x1f'o I\x81\xb7\x06)\xfb\xdb\x96eyfB\x08\"rR\x83w\xe3nV\x99E\x07\xab\x8c \x83MV{L\xb1!/\xdf\xddq\x0cV\xc3F3B\xabxP\xbam8i\xbam\xc8\x9f\x94.\xdd\x93\x05]\xcb&\xd2\xc3l\"\xd0V\x1d\x0f\xf7\x04\xf3\x9b8\xc6\x06\xec\xcc3\x97\x16P\x83[\x10\xd7\x91\x0d\xaf\x13\x83\xf4 \x16S[W\xeb\xf6\xa6}_\x93\x86\x0d\x951\xf4\xd3\xa3w\xf1\xfe.\xbbY\xdb\xacq\xdb\xd5\xd0b\xa3\x08\x8a\xec\xe2C\xed\xb6\xbf\xfeH\x7f\x07\xb9qc\xa7\xb9A\xd0\xf7*\xf5\xab\x9e\xb5\xf2\xf9\x9c=\x98[\xf9*q\x84\\O\xb8B\xaa\xf3\x04\x1c\xe1\xea#\x95\xe4,\x0f\xf2-'\xb7\x0e\xfd\xe5`jLN\xf3\xe4\xa71\x1c\x0c\x87\xa2t\xf2^\xc5\x8b\xa5\x8fO'\xfc\xab\"\xe7\xe2\xed\x138TU\xe8\x95\xb49\x14\xbfj\x1da\x9118/\xff,\xc7f\xe7\x05\xbe\xce\xb5r\xfc_\x84\x9a\xab\x90\xa9j@\xd5\xd2/4\xf0\xb0\xc1\x82\xe5\xe68rW\"\x16\xa0\x19*tS\xc2\x18\x9c\x8a%\x01\xa7g\x08w\xc6\x1fy@5\x06\x87\x0e\xa7\xa80\xfaX\xcac*|E_\xcd\x8dp\x85m\x0cN\xa1\xd0h\x8dp\x0d\xa3\xf8\xd9*\x00\xf2'Oo[\xcca\xda\xa1\x03o\xdf7eO\x96\xcfG\x98\x05\xe8R\xd7\xd5\xad~odo\xcb\x8c8\xb6l\xc0R\xaa\xe6k#\xfel\xda\x0bM\xfd\x1e\x83\xa3)\x1aT\xa9\x8e\x9ef\xd1\xa8d&\xf4\x10r\xae0\x95\x9dtv:\x95\xfa\xd6\xb9\xe3\x17.P\x85\x1aV\x7f}\x1c\x05\xeb\x0d\x9b\xd7\xbf\x9e\xc6\xf9\xe8\xbe\xb9\x92\xe9\xfdi\x9c\x1f\x1e\x98\x8b\x9b\xde\x7f\x17%\x81\xfd\xc3\xfd\xbb\xe2\x83\xe5z\xea\xba\x93\\\x06\xba\xeb\xc6\x9d;\xc07\xe9/!\xbbn0\xbf\x99\x81\xc0<\x88\xa5\xf4K\x13V\xda0\xe3\x8d7;[\xe9\x8f>\xb4\xc2\x01\xb8\xd5E\x8d\xc4E\xf3@\xebP\x93h-\x11\x9b\xa8\xf8\xbbX\xd9\x11\xa3\x90\x0cB;\x8f\xdd\xd4\xc2\x82$\xcb\"\xf10\xd8L\x99\xe5\x8e\xa1V@$wO\xa0\x07\x8e\x8f\x81\xb1al\xba\x8f\xef\x97\xc6?g\x11\xcbY\xa7\xad\x17EU\x97|\"\x86\xbc\xda\xe5\xf6\x97,\xef\xd4\xb8\xda8\xb9@\xc4F\x82\x8c\x0e\xbb\xf5y\x8e\xcb\xa9R-\x1d\xaf\x82\x9d\x1c\xd0d\x07\x15\x07<77;w\x96\xfb\xca*\x93l\x80\x80\xf2\xea hk_\x08Ym\xb9Y\xe5SI\x96-z\xf4\xacs$\xe7B\xa6\xfc\xe1\xd4\x18\xe3s\xbaqT;\x957\x8c\x11\x9d\";\x98,\xa4u\xd1vkV\xdf\x8f\xba\x83A\xc3 9\xe0)\xb9p\x904\xa32\xfa\xde\x9bM\"\xfaT\xd0\xd5\xe57\x98L\x87\x99\xd8N\xef;\xce\x84\xc5y\x1a\xfe\x16S\xe9\xb6/S\x0eL\x06\xcf\x0fh\x99R\xc51H\x9b\xa1\xc9E\xc8\xb0\x00\x96\xb3\xf8[\xe4\xf3\xcfO~8ys\xc2\xf9%W\xd8}\xa1\x9e\xfb\xe0\xbc|\xf5\xe6\xf4\xe5\x8b3\xfe\xe7\xab\x97g\xf8\xe9\xd5\xdb7\x8ea\x81fZ\x97\xb3(\x89Y\x97\x15\xd7\xa4\xb2\x19ZP\xfc\x86\x15\xbcL\xe6\xb7\xfa)\xdbi\x1cZ\xee\xd8\x1aWP\xa4\xcb\xd7\xc6\xe9\xa9\x97\xf3\xd2\xcb\xf9gNe^9\xf9o\x9a\x14i\x0fc]\xdb\xb0k\x84\x85\xaa1\xae\xaa'\xf6JB\xeb\x18K5D\xd3M\x1a\x94\xcfm\x1a\x8d\x95\x9a\xb2\xc3*\xcf\x07\x9d\xfdi$\xba\xd1\x92\x91\xc5\xa8}\xa1\x1a\x82\x82\xe8\xcb\xe3X\"h5\x9b\xcf\x98R4q\x16N\xd5\xf3\x11\xcc\xd2\xd0\x95\x88c==\x1c\x8e|8\x1c\x1e\xf0\x7f\x0e\xf9?\x0f\xf8?\x0f\x0d\xe82\x1f\xa4l\x1e\xa6\x1d\xd2\x8d\xcb'\\\xa8\xfc.\x97\x9a\x95O\xb7\x96i\x11\xb7\x94\xbb\xa9Pjg\xc9\xdcz@_\x02\xdd\xae\xfb\xd0\x05\xe2\x9a\x95\xa7(\xa1\xa3\xe6\xc6\xcb\xc6;\x80\x1e\x1b|\xafT\xee\x84\xff|M\x06A\x98\xc0\x8c~f\x9b$\xc6{\x9ds\xfe\x1b5\xe7\xae\xab\xaf\xadQ\xcdi-n\x10v@\xb7\xbe \x99\xc3^\x9aml\xa1(\xfc\x9f?\xfe\xf0}\x9eo\xc4<\xec\xa6\x9apG\xcf8\xd0\xb0\xaf\xb9\x14h;\x1e\xb6\xd2\xa7r\x0dB\xc4\xb0\x13\x91\x92\x8f\x02\x9d\x8d\x1br\xc1\xf9Y\x14\xc9m\x13\x9b\xeb\x8a\xa8\xbev\x97\x110#\xa9\xfe0a|qR\xd1\xf8\xdb\xd7?\xa0\xca\x1c\xc2\x11\x84\x03\xed-\x8c\x81\x95\xfdI\xfe\xb3/\xf6\xa3\xcf+\xb5\xf8\xbcH\x93\xa2\xea\xc8\xd0\x0b\xe6\xe9\x97?\xf8257\x19\xbb\x82\xc7\xe0%x;\xe6\xf8\x08\x16\x9d\xa9\xb1|\xd2\xaak\xe8\x0b\x96_'\xe9{i^\x87E\x10Fln\xf2\xfd\x90\x8f\xe8:\x0f\xd7,\xd9v:o\x97\xcf\x17\xeb|\xc3b7Q\xc7Q \x9d\x7fa\xaa\x1d'\x8cg\xd1v\xce\xe8\xf0!)\x9d\xf6p\xc9*\x1c\\\x87\xf9\xea\xb8tND\x15\xd5\x16\xddn\xe46\x96|\xc1\\m\x17\x05\x17!/\x0c>\x00 B;\xf9G\xcb'\xe4\xea\x95\x80:B\x03\x8b\xbb\xb4|\xb8$\xc9+\xc5sWsoO\xb4C\xb7#:\x8a\x1b\xeb/mR\xa9\x99\xd8\"\xf9\x1cl\x92\xe8v\x11F\x91\xc9+X\xfd\xe5:[y\xd1_\xbfk\x90\xb1h\x01G\xf4\xdfXS\xb1>\xeb\xa2l\xec>\x1a\x9a\xae\xaf\xf0\xf7\x0f\xcd\x17\x92\x1e>\xb2\xdc<*\xef\n\x85!\xe6\x84\xb0\xdc\n\x1e2\x8f!)\xbfUQ\x02\xc6\xb5\x9c\xf7\x9f9\xbf\xc3\x87\xd5y$j\x1e\xf5\xf9\xd5!\xeb2\x0df\xef\x19\x9fHg\xd3\x00f\x84\x9b\x9e\xd7e*\x83\x0d+\x8c\xe7\xe1\x8c\x95Zo\xe7\xab\xd4\x01f\x96\xa3\xe4s]zJ\xd9\x86\x05\xad10@\xeb\xa5\xdej\x19d\xeb\xf7\xd2\x9e\x079+Y\xcdN\xcf^\x92\xe1\xac\\\xd6\x1c\x8dg\xce\xa2p\xcd\x15\xb31\xde\x0e\xae}\x97\xc1n\xf6\x0cR-}K\xc7\x90\x8a\xe0\x13\xb6\"\x7fA]\xfde\x1c\xdd\x8e\x8d9\x063\x96\x86A\x14\xfe\xc2\xf8\\vX\xad\xa0v{U>\x86\xbd\xc8\xde\x87\x9b\x17\xdb(\xca,c@p\xe6\x05\xbe\x0f\xe2y\x84\x91Q*V\xf3J\xa3\xba\xc6\x0eL\x04~Q\xf1\xc82\x1f\"\x9f\x8buE\x88\x04\xd3l\xa4%\xdb\xc0R\xd1\xdbZv\xa0{\x82F\x1eV\x89\xb8Xwe\xba !\xdd\x82\xaft\x7f\x0e\xbe\xb6Tq\xe36\xd6RW\xc2\xaf\x9a\x04\xfdP\xb9LQ\x06\xb4\x15\xa7\x93|D[\x01\x0c\xe8\xfbf\xb8\xe2\xcd\x9f+\xf4\x8fm\x81u\xb0{\x9c_\xa1\x84U\x8f\x97A\xefe \x80\xea\x87t\x10f\xe2V\xc1\x95\xa7\x0d\xff\x08\xa6s\x17#\xc4\xc3\xb8:\x07\x8f#\xfb\x84\xa3\xfd\xdc\xcd\xdc\xab\xd2\xa7s\x18\xf3\x9a\xb1^F\xb8x\\y\x9eA\xa5\xe2\x9b\xbd\xf6\xd1~n\xb2\xe0\xe0\x96\x15\xcc\xf0J\x0d\xd1\x10\xff\x8f\x97-\xdf7\x8a<\x0f\x8f\x07\"\xcb\xd6\xdaU\xdc\xdbJ\xda3\x13t\x808|\x98\xc1\x11\xdc\x0e\xb2$\xcd\xdd\x19\xdf\xe0. \x9a\x94\xa9\xf3\x92\xbc\xdd.\xe1 \xac\x95\xb7[\xafw\xd9\xa4\x7f_\xc0\x04\xd6\xd3K\x8b\xc1\x0b\xdd\xbd\n\x80\x9d^`&\x07wY\xbd9\xef^yp\x04K\x99S\x86\xb9\xbc\xa8\x0f FP\xf3Z\xd0\x96\xcf\xb3V5\x86\x1e\xb8\\8p\x06|\xe7/T\x9e\xd2\x0b\x95\x9b\xb4\xb9Q\x03\xd1\xaa\xbd\x91\xfb_&CfQ\xa0\x91\x99\xa9s\xfd:\xe1\x0b\x80n\xe5\xa6\x83 \xcb\xc2e\xec\xfe\xfd#606\xc6\xcdQ\x01\x99\x02\x89\x07x\x8aS\xdc\xf7-\xbd\xd7\xc8W!T\x05\x05\x810\xba\xd1\x9c\x88\xfa\xab\x00\x03\xa0_2\x08\xd4\xe4j9E\xaeD\xdc\x1b\x0do\x82\x81bjp\x04[\xed\xd7X\xffV_\x89\x19\n\xc4u\xe2\x11\x0c\xea\xcc\x01\x8e\xcc\xaf\xc7\xb05\xbc\xae\xf7\xb5\xb0\xf7%\xf9\x14u\xa1~a\xcb\xf2W\xbd\xc1\x8d\xb5A\x11\x18\xea\xa8\xf8s\xac\xa8X\xbd\x1d\xae\xa2\x1b\xb9N\xb1\xb1G\xda\xdfES\x86\x05]\xd9\xdb\xca(\xa5\xbc\xf8\x83N\x8b\xea\x0d\\\x15;K\xb0\x85\x9eU\xcf\x93\x1cy\x8e\xf6\xb3^u\xdd\xd0\xb7.n\xd0 Jop\xa5\xf57\xf5\xd6\x97-\xab]H<\xdaji/\x8be+^\xd6\x91\xad\x04\xd4$\xdc{\xea/4\xa2\x0bo\x93r\xd5\"\xf3U\xa7\xc8\x15\x89h0gi\xe6\x17\x1dY\xb0\xf3m\xfc>N\xaec\xa1k@\xb2A\xf1g\x93&W\xe1\x9c\xcd\x8d\xf8)\xc2\xb1\xe2\x80\x8b\xae\xa6\xb2\xa7\ni\xb7l\xda\"\x8c\x08\xa1\xd1\xa1\x95s\x12\xf9\xces1/\\\xfd\x06\xae*\x80\xba/&o\xd7\xab\xd5\x07z\xedc*\x82*oF!D\xc6\xc2)\xe8\x98\xee.:\xe1\xfd\x0bj]\xbd\xf8s\x8d\x9d\xa2\xff\xc2w\xb4h\xc2\xc0R~9\xe6\x8a?*&\xa8\xba\x07X@\xbc\xe1lF}\x1csE\x9f\xeb\x15\x8e^\xa7>\x9b\x1b\x98@8\xbd\xaeL\x06\x83\xc8\xb8U\x96\x1f{\x18\x0d\xeb\xce\x1d\xc9\xdc\xabw\x1c\x15\x0f?#\x1e~\x06O\xe0V\xe3\xe1g6\xe1\xf6\x18&p;=3\xf0\xefE\x89w\xc7\xd3c\xe2\xdd|\x07N$\xb7\xcd\\\xfe\x1e\xa3\xf8\xde(\x0e\nG0\x97$\x83C\xd6\xca\x87+\x9f\x0bV\x17>,\xab\x8c\xf5cm]\xdec\x07\xe8f\x16\x19\xcc\x9c\xcf\xd0P \x90.\x98\xcf\xff\x9f-Ko_\xa5l\x11\xde\xf0m8r\x0c1\x9e\xc4\xce\xbf/\xf2 \x0c\xe1\x08\x9eA\x0f\xdeW\"\xfc\xe0_\xbf\x8az\xdd\x82\xeb]\xf4nEN\xcd*\x12~Vn#\xb6B\x1c\xa4\x7f\xe0,v\x0c\x07\x06\xa5\x91\x1c(Qi\xa4?ME\x9au\xd29\xdb\xe4\xab1\xdc30\xc1 \x0d\xd6,g\xa9\x18\xc0\x88\x1d\x1a\nEA\x18\xd3j}1]0\xe8\x10L\x05\xda\xbce\xd5\x0ekl\xeeH\xcb\x92\xb1\xffn\xe0N\x7f\x1aL\xcf{\x1e:\xb2N\xffmt\x8e\xf7\xfa,\xbeW 6z\xdf}7\x9d\xfe4}w~\xfe\xcd\xb9gK\\\x03b\x16\xe5\xc2\x94h*m:\x86\xe3\xd4\x0d\xc5Gq\xa5\xda'\xb2\xc5n0!\x85\xbdb\xd6p\x8e\xcd\x97\xa9\x16\xcd\xacZ`/\x1e\xe8[ \x98/\x0c9Z\x15\x1504\x1a\xa5\xab\xae\xc0\xb0$\xdav\x83vF\xa7\xe2\x86;[`=\xfdQ\xc4R\xe4\xf6VB\xb3\x1b`\x08G\xb1\xa88\xa6\x08\x9e@<@\x90n\x0c\xf3\xcdg\x1cA\x0fC\xe7\xef2\xf3`::\x17[3\xf2\xa1/\x02v\x7f\xc6J\x04\xc6\xa0\x14`]\x0ci\xab\xe1\xdd\x8a&HQ\x92\x10\xa3\xc0E\xe8M\xd6\x01tA\xb0Ry\xb9\x0d\x1c\xa9r\xca\xf2\xa2%7\x1b\x89\xe4\x03\xc3\xc7\xd0\xef'm\x8d\x81@\xd0\x90\xa2\x98\xb3i\xd2\x90\xda[>(9LE\x0c\xb6\xc0Cl\xc44\x08\xd3sO\xb28\x9b{\x99\xfet\xb8M-\x1f\xb4\x18\x97\xc1\xe3H\xf2\x86Y\xca\x82\x9c\xa1\x0eg\xd2\xefl\xcf\x95\x08\xe5\xc7\xb7\x8d\xd8b\x91\x9f\x91+y\xe7\x95\xd7\x81\xb6\xc6\x1e\xc9\xd7\x1a\xfcq-\xcc\xbe\xc7\xd5\x87S 4_\x9f\xc6\xb9\xbb\xf5ad\n\xd9`z\xf6\xc2\xecE\xf0\xc2\xcdp\x88\x01b\x1f\x06\xbd\x17\x06\x9a\xcc\xc31\xe3\xab\x8c\xc2\x8c\x8a\x1c\xc8i\xc6P|\xcc\xe8\xd3\x13\xa4\xc7\x8a\xa9\xc1\x91\xda\xc0iv\x8eQ\xf0\xc7\x10N\xb7\xf8g\xeb\xc0\xcc\x18\xa2?\x1cT\xc3\xc6R\xcdm\x08l\xb3\x0f\xe5\xa3\x9b \xec\xa9\x15\xa9\x98\x9a?\xc3\xcc\xf0 \xf6\x84X\x88\x03U{B\xe9\xbd\xd1\x9e\xa0JX4\x96\xe7l\x07{\x02\x8ei\x10.\xe3$e\xba\xe4\xa7dB\xc3G\x1f\x87 \x8d\x0c\x13S\xacl\xbd\x80\xb0D\xbef\xcb\x93\x9b\x8d\xab}\xf10I\xa5n\xae\x085s\x85\xe4\x12\xbc\x83\xba\xe5S~\xc3?eI\x8c\x83=\x11\x9eZ\xc1\xa0\xf8\xe9#f\xb1\xcd\xb1\xf0B\x0e\x06\x17\xea'f\xa5\xc8f\xc1\x86\xbd\n\xf2\x95\xba0\x8b\xa5\x0c\xefy\xf1ml\xab`\xfcR\x1e\xfe\xd6\x90\xd7\xaf\xd5\xad^\xc0c\xbb\xcf\x01]\xd0\xbc\xccXzE\x1e\x9c\xd3syk\xf3\xf2g\xa8f\xfc\x80\xba<]\xbdQ\x17\xed<\xb4\xb6@\x95\x9cv]\x06\xb3\xf7\x14\xc8\xad4`\x98\x98\xa2mV\x07h\x8a\xfd=\xab/I)\x8b*\xe5\x9cJ1-\xb9\xa471<\x81\xf41\xc4\xbd^]\xcb@\xdb\xce4>\xa7e\xc3H\x0bd[\xb7N\x0d\x19VlQ\xb7/S\x16\xbco\x99\xd9\xc2\xcd\xe9\xbe\x88\xaf:\xe3\x7fm8\x14s\x11\x0b\xd3D\xa8\xdfR{E\xabJ\x81\xaaz\x1b\xa2\xa4\xe1\x08\x81R\xc8\x8a\xefF#q\xa8\x1b\x891\x94\xad,.`\x8a\x15\xfb\xa8n\xfc\xf0_n\x88\x89\xbf4jY\xdf\xac\x85\xab\xb2\x01\xd4,\x1a\x18b\x82\x92\xe9\x98\x96\xda(\xa4\xe7\x83<\xf9\xd3\xd9\xcb\x17@9X'\xea\x85k\n\x14\xa3\xe0\"D\x9epAK\xfdg\xce\x9ar\x8f\x84\xa1\xf2[\xe6\x91\x98\xb37\"\xde\x17\x94\xac3\x99\xb0\xced\xfd~\xa3X\x83\xe6\x18\xe4T\xd3\xec\xbc\xc1\xa2\xb8\x97\xd6.\x8e\xf9\xb0\xf1*\xd2g>\xdd\x9cWt\xd0\x08Mf$\xc0\x94\x8f\x98rO\xc5\xac\xb7\x9bg\x92\x0d\x1e\xd9\xac\x93+\xd6\x90o{\x13\xe4\xab1\xdd\x0c\xdc'\xf3\x98\x81\xe0\xb9\x1b\xfb\xc5\x1c\\HK\xae\xd7\x16\x03\xd2\x95\xc8\xf9\xc2\xe7n7\xaf\x18\xf2ADP$i\xa2\x1f\x86B3\xbd\xd0\x8c\x0b\x89.\x89\xa2\x1cJ[\xe7\xcb\x85\x1d2\x11`;\xee\xde\xd0o_r(\x96\x1d\x05\xf3\x86u\x87\x1d\xd6\xbe\xb9\x15\x11}9\xd5X\xa0;kr\x81\xedjF5\xfbEm9\xe0*j\xb2W`\x8f\xb9YDNMm\x08\x15\xb5\xcez\xbd&\xeb'\x07\x8e\x0d\x9e%f\x0d\xc0Q\xc3-f\xc3-\xae\xfau\xde\xbf`>\xff\x87\xed\x1d\x1fm\xd3\xf6u\xd8=\xcd\xc5X\xfd\xc5\xa5\x1c\xc1\x96\xdb\xeciZQ=+\x02\x97\x94:\xb6\x80\n,\x99\xbe\x9bE\x9cR\x08\xb3!\xf1\xf5\x82\xa1\xe7\x94`871tPL=\xd7\x98\xba\xd2\xe1\xf9\xeb\xf2\x9a\xd4\x02 \xf1\xda\x898\xdao\x95vJz\xb9\x90?\xb9bq\xfeC\x98\xe5,F\xfb\xa3\xed\x93\xeb\xac\x93m\xc6\xb6\x1b\x87\xac.\xd6b\xef\xd9m{!lk\x9e\\\xc7m\x05\xdf\xb3\xdb.\xc5f\xab ^2,\x85\x807Of\xdb5\x8b\xf3\x81\xfc\xe3$b\xf8;\xc8\xf3`\xb6\xc2\xda\xae\x93\xc4\xe59u\xad\xa5O\xb1k\x9d\xea\x8c\xbb\xd6+/@\xd7Z\xfazt0A\xc4\x15\xb9;\x16\xaa\x01iO\xb1\x99J\x9b\x80z\x86y[\x8c m\x84\xddV\x12\xa7\n~!R'\x1f\x03\xc9+\xf4\xc3\x12\xc9C\x9e\xadw%r\x80\xc7>\x8c,\x08\xc9 _\x87\xaehH\x02\xb1\x0d\x13\x0d_-\xc8h,i\xc0G{\x8bu\\\xb3\xb5\xa9J6\xe3\xdb\x9c}\n\xbeUju\xc27SO]0\xa7\xdeW1\xb5\n\xeap\x8eT\xc0\x01\x85n`\xd7@I\x99\xbcRD\xd6\x8fd\xad\x8aYJ&\xa8\x19\xff\x8dv\xbe\xb4\x9b\xa0bp \x91F\x90B\xb1Em\xbd\x9a\x01\xac\xc9h\xa8\xb4\xe3\xcfI\x02\xd69\xadW)\xe1\xafQ\xa9\xd63\x94\x1d\x95~\x8d!\xf6\x06\xd9*\\s\xf6\xdd:/\xb9dZ\xc6\xb7%\xeer\x86'\xf2v\xa2%\x06\xdd\x12q'\x90\xadi\x92\xa7\xd9DdH\xab#}!-Ck\x0d\xf6\xa3mo\xbd?C\xee\x17uK\xcb\xac\x82\xd2\xfb\xfa\xb1\x19\xd3\x8c=\x9d\x9ce\x99\x0f\x0e\xff\x831\x87\x1cij\xb56\xa2\xfciv\x12o\xd7\x14\x11\xc3P\xf7\xc3\x07\xdd\xa5\xec\xa3Kq4\x0b\xc8\x89\xe1\x08}\x0b\x12oPD\xb3\x9f@JVR\xfdUb\x04\x94\x9d|\n\x8d`JQ;p\xe12\x11F\xad\xfaQ\x85\xf4(\x1d\xa8Y\xf6F.y1ih\xba\xebU\xda\xd1\xe6\xf1\xb1\xc1,\x89\xb3<\xdd\xce\xd0\xc0=\x99\xe8\xdf\xd0t \x86\xabv \x8e\x8aI\x8d\x0d#3A\xb9\x1d\xea\xb4\x93\xcc#\x0ee\x11\xb6\xaa\x9fh\xf2\xf7\x1a_\x1c\xeb0:)9z\xd7\x8bR\xa2\xc8#Sz!\x07\xcf\xe5K\xed\xb5\xf4\x9b\xb6\xe1\x96!g\x8f\xc4e}\xc8 \x0d\x00\xb3\xc2\x8c\xd58\xb4/\x81[\xc9Bo\xea\xcc\x90\x7fG\xe9\\\xeb`\xe3\x86\xcdc5\xe4\xa4\x91\xf4\xdcz$,\xe9y\x15\xbdE\x80%7\x9f\xc6\xe7\x18W\x9dM\xe3Z\x10\xfc:\xb57\x8c\xca\x90\x87\xa6\xa4\\+\xbaZ\x18\x82G\x15\x83\xa3*2\x1d\x9d\xf3\xb5\xd4\x7f\x8eIX5;\xf0bT6\xb6\n\xae\xc2d\x9b\x8e\xc15\xf4u`\xed\xeb\xa0\xdc\xd7\xc19\x1e3z\x83r\xabx\xc5N\x9a\xd5J#Pg\xe4|\xeb\x9a\xad\x0d\n\xb91&u\xb9\x15\xcf'+:}\xf3\xa5\x13e\xc4\x85\\%\xf2F&Y\xb7\x94\xbf:\x9dF\xe7t\xda\xad\x1f\x91\xceD\xe2\xe8\xe1c\xd8\xc0\x13X\xa8\x067v#\x18o\x11#WL7\x0d\xa7\xe6+.\xf0L\xe7\x0d%\xae0\x97\xe3\xaa\xc1\x12\xb5\xc6\x12\xe1tn\x8b\xef^\xba\x8a\x80W\xde\xec\x12?\x96- \xe3\x13X7\xa9\x1b \xe6\x8a\x0e z'k8\x02>\xa8\x0e>\x83!%\xc0\xce\xd0\xebk\xba\xf4a\xeb\xae\xbcs\xa3\xbb\x99|D\x9clQs[\xbbz \x1fu\xadE\xa76m\xf3\xd7\x8av\x9a\xfb-\x1ex\xdb\x86 \x1f1V\x07O\xbd\x1d\xe1\x17VA\x13Z2\xe9+pk\xbe,)\x9f\xf2\x1a\xd8\x07\xa0\x97Z\xd5J\x18\xd5\\\xfd\xc0H5\xd3)\x17f#\xd5\"\x12$NA\x90\x84\x1dA\x8en\x1ecL\x1e\xcd)\xc1Hd6(R\x1a\xf0\x02\xe7zk\xd3\xd4,\xefg\xe4\x16Q\x8c\xdd/\x06=\x88\x93\x1f\xb7y\x907*\xe6j\xf0\xcc8\xf8\\\x0d^\xe6g\x18\x92\x1e\xcdH\x8f\x06\xc1\x07\x8a\x81V\x0f \xd5@\xc9\xbf\xd1<\xd2\xeb0_\xbd\xc4+R5\xdfI{\xba\xd5L}\xafl]\x8b\x8cg\x0f\x0c!\xf3\x8fC\xec>\x1a\xdd\xab\x10\xa0\x8b\x0b\x96\xfd\x98\xcc\xb7\x11^\xf3\xdf\xad\xcb\xd8\x1d=x\xc0\x17\xd0}t@\xff\x8d\xee\x8b\x9f#\xf1\xff\xa1\xe7\x97\x05[wt\xcf\x1b\xfc\x95\x05\xef\x7f\x0c6]\xfah\x10]}\x99\xc9\xf7p\xe4\xb9U?\x8ePtV\xbd,C^\x0e\xa3\x83\xbb\x95\xf7[j\xea~5Y0\x0d\xfa\xd1\xa8\x1a\xbb\"\xa2\xf2\xd5\xe6g\xf8\xfa^\xd5{d!\xbcG\x0e*\xef\xf1\xdcr\xb0d9_\x91\xf2\xa7y\xc1\xbb\xc2\xec\xe4&gq\x16^F\x95\xcb\x1e\x9c\xedd\x83\xed\"\xcb\x93\xb4\xf2\xe9\x8a,\xca\xa5w\xed\x01d\xab^\x076\xaa)Y\xb8\x88\x8ag\x904\x86%qbx\xaed\xd3V\xd7\xe3\xf2\x98\x97FYg\xc9:\x05\xd6\xc0{\x13(A\xdb\x89\xbf\xa4q\x1bcj\x06\xf9\x88 \x0b?\xe0\x1c\x8e`\xe5.\xc4\xec\x1d\x01\xcf\x8e\xe7a\x0c&\x94}1\xfa\xb6HU\x14\x16\xb37v`8\xf4\xab\x8b Yy\xca\xedAK\xb2\xc1\x9c-\x0c\x83\xf4\xd1?d\xc7m\xb8\xadj\xa8\xee\xa3\x83\xa1\xe7\xaaV\xf1\n\xde\x12o\xbb\xef\x0d1\x96Q\xb1\x963\xb7\xcd\x18\xf1\x00\xf6&\x80\x96\xa5[\x0fs\x7f\xc9\xbb,\x8b\x94\xb1_P\x18\xa4\x17\x9e{\xe5\xf9\xf0\x80\xd6Yc\xff\x1fI~\xdf\xba.\xa6l\xe3\x9f\x8f\x0b\xad\xd0]\x977I\xbb!\xb3\xf4|\x08\x06/NN\x9e\xe3\x01\xba\x0f\x89;u(\x8e\xae\xe3\x83\xb3\n2\xfe\xdf\x92\xe5\xfc\xbf\x8c\xe5\xce\xb9\xdf\x00w\x12\x96n\xb5.j\xeb\x8c>\xf2\xb5x\xc1!\xc6L\xd2\x1a\xcf\x0d^\x1c\xa0`:'\x03\xc4\x1c\x9d\x10\xcc`@\xb0\xb7(\xd2\x7f\\,\xc4\xe1TSP\xe3P\x065\xbeXL\xd99\x8d\xc2\\Zj\x86|U@\xe8\x9b\xbc&\x8c\x0d\x97\x18\xec\x0e\x91\"\xa8-\x02i^\x8b\xe5\xffQ\xdfc\xfa\xbbs\xa2\xf0G\xa3\x87\x96\xc8I\x8dh$\x07\xc6\xae]\xd4\xbe\xf5\x10\xaf\x9d\xf8b1\x82\x1a\x7f\x10\x1c\xab\xc6\x96\x04\xbbz\xe4\xb9N\xb6a\xb3\x90\x95\xd2\x84t\x93\xd8\x10\xf8\x8cb\nj\xe5\x1c?LW(\x84\xf1I3\xa2\xa0}\x8a\x9c\x85PJBHK\\\xcd\xce\xe5\xa9\x1c\x08\x82\xa6\xfb\x90\n\x90T\xe6\x10\xf2\x18\x9a\x86\xe7\x9e\xf2\x1f\x12\x85\x8b\x1c\xf1\x92\x96R7\xe3\xd6T\xf6\xdd\x85\x03Z\xe7\xe1}\xe3\xfas\xf6o\xe6\xba\xc2\xcd\xb3Z-0\xef\xa6\x10\x1a\x86UaBH:w\xab\xef#%\xaf\x18\xa5\x86\xaat\xd0$5DnU\x92\x9b\xe3\xdb\xea\xc8WxxT\x86\x93\xaeR\x00\x1b\\`\xea\x07\x17\xff \xd2\xb1\xae\x1e\x10\x94~\xae\xdbN\xcb\x90\xb2\x04hrojg\xd9\x86\xa3P\x8cr\xe3\xb2A\xd0D\x94+\xe5\x19\x17F\x10\xf0j\xa5\xaa\xd9\x90\x0b\x98Zk\xd6\xc3\xaa<\xd2A\x16\x91|a)\xe8\x9c5 \x94:\x83\xcb\xa7\xa3\xc6\x15Z\x05\xad\x01\xd2\xa4\xc8\xb2W\xf4\xda\xd4b7\xf9B\x1e;4\xcd$F\xe7yT\xf5r\x99\x021\x10\xf1\xa5Y=\xbete\x1c\xc4|\xdb&'WT\x043\xd6\x01\xa0M.\xca%\x00\x18\x9cv\x0d\xb3\x11\xb5\xfe;\x07\x99\x88%\x90\x07\xa2\xb9\x8f\x97\x08\xf6\xf6\xfe\xbb\x9aTF\xfd\xe57(fe!e\\#u>\x84\xb6\xa9\xa3\xdbc)J\xa35\xc4\xeb\x96\x7f\x8d\xb0E\xe7\"$g\xd7\x8b\x9c\xdcE\xd8\xe0\x82S\xbcU\xaf\xe7\x83@r\xa2\xcc~a$\x04\xbc|\x97\xb9)\x8e\x88M\xc3ss*|\xfb\xd2\xa5n\xa4\x8b\\\xe6av\xdbv\xf9\xa0Gg\x80\x92\xbd\x04\xf3\x91]x\x97@\x9b\xec \xe2s \xbeR\xd2s\xeey\"\x11\x03I\xf71_\x93\x99\x1b\xab\x9c8\xc8\xe4D\xfe\x85X\x89\xfd\xc6\xbe,\xee3\x1d0Z>\xff\x88\xd9\x8bD\x0f\xa6\xa9\x9bgi\x80\x10\x1f\xa2f\xcc_\xd4\x91\xc0\x86\x01)YK\xd1\xb7x\xcft/\xb8<\xa1\x14'\xc4H\xbb\xc8\xc5\xa5\x9bt\xcaP9\x9b d7\x0dM\xa8\xd8c\xb8*P\xfb\x0f\xf0\x05$\x94\xaa( \x04D\x8b9\xa3f\xb6\x08\xcc\xf6\x06\x12L\xeeU[\xc9,RQd\x91Wf\x16\xf9fa\x16\x876$uW\xc3\x9b\xce\xf1\xf5\xdd\xa17X\xd4e\x13\x8b\xf9\xe6\x8a\xea\xdcm\x15\x82%\xa5$\xed\xf3\xd6$\x13_\xe2y\x003\xd8\xe6/`\x02\x97\xf5\xd7\xd7\x9c\xbf\xe1!!\xa30;f?\xd4\x13\x98\xc0\x05G\x86\x8b&m\xef\xc6p\x1e%@\xf3\xcaz\xba\x89\xcd\xba\x18\xad\xe7D\xe5\x16\xe1Rx`W\xa5\xf9\x83*\xf4\x85'\x93*\xb8\x1ez\"\xb9U\x95\xca\x83#p/0\x91\x8b\xaen\x1aqm\xc6\xbf\\\xa0j\xea\\\xcc0\xeb\xe2\xe0b&\xa4\xc1K\x9dO a\xc0\xebsK\x1f\xf2\xe9\xf5y\xcd\xca\xc0)\xc0\xca\xe5\xcb\xe9\xa3\xc3\x94O\x04\xd3\x173\xf4\x97,\xf7WA\xe6g,\xf7\xdf\xb3\xdb\xcc\xa7<\x1f\xbe\x98\x8eO\xb7\x0f\x1c\x99\x9e\xce\xe7\xa3\xe9&&\xe0\x16\x82\xbcnZ\xa8\xacu\xb2\xc1 \x8c\xe1\x84\x9c\xcdq\x03\x1c\x1c**L\xa4Em]}\xc3K:{S\xa8uN\xb4e\x16 \xbe\x9e\x9cn\xa1LA\xfa\xd5\xc2\x8d\x0br\x8e\x06\x07\x1a\xae:\xaf\xb3\xab\xec*\x0f\xd1\xc5\x8c\xab\xec\x05\x05\x1frr\xed[\xd5})\x0f\x15z{R+W\x15\x89=\x9f\x82H\xcd\xcb\x8b\xe0d\xe1/\xcc1\xf1\xf6\xb2t\xdc&\x9a\xd1,\x06\xbc\xb5\xfaPjP<&(^W\xcd=dIY\xfap\xed\xf9\x90\x95G\x1a\xe3\xadOe\xf0\xf1|\xd8\xb8b;n(G\xd3\x85\x0f\x89\x9b\x0c\xfe\x03z\x90\x0c\xfe\x8a\xff~\xe7\xc3\x8d\x9c\xf9\x9a\xb3\x90\xb3\xc9J\x98\xa4\xcd\xb0\x16\xa1\x1eTy\xaf\xec#\xe72=O\xb5\xe7\xc3\xfe\xf4\xa7\xa0\xff\xcb\xb0\xff\xe8]\xff\xab\x7f\xfb\xe3\x9d\xaf\xbf\xe9\x0d\xde\xfdt\xf1\x7f>\xfc\xf7\xf9~8\xc8Y\x86\xb9\xd7\xcc\x81Wd\x82\x97\xd9*H\x83Y\xceR\xceW)\xcd\x00,B\x16\xcd!\x0e\xd6\xc6\x9c/\xca\xfa\x94'?$\xd72\xaftyq-sn\xb6\x84t\x9e6\xeb\xd4\x99\xc1\xf1\x11t'$#p\xc5\x98u\xa4\x95\xac\x82\xd6\x10\x93Iv[\x957{[\xfc\x99'1+9\x88\xb5$<\x11\xb7\xa2\xccI\xac\xc0\xa8\xe2\x99\xdf\x1a\xbcF\xc4\x80+i\xc3rS\xb2\xb0\xd6\xb5\x92\xb2C\xbd\xdf\xce\xd9~\x0d\xde}\xa0\xa5\x02\x14\x97sJ\x19\xf2\x13\x0c\xfd\xb1S\xbe\x0c2\x1eQ\xd6bs\x82\x0c\x91\xf9\xbf\x1e\xcd\x14\xbd\xeaL\xddu\xe9\x8bM\x87\xe7>0c\xe86\xadG\xdc\x03q\xee\xb6d\xb9\xe6\x1e\xf7\"X3\xae\xfd\xef\x90!\xaf:\xd7\xa9)\xab\xdcGS\xe6B\xdb\x1e\x19|\x13A]k\x90\xd9\xf8\x95\x04-\xb2 \x0dR\xc6\xe7S\xcd\xdb\xf2,JY0\xbf\x05\xfe\xafc\xba\xcc\\\xc9\xef\xdfi\x80\x06\x7fF(K0\xb5\xd4LM\x81\xec\xd8\x8eY\x93r\x97\xcf6\xdbF\xb6D)x\xff}\xb7\x8c;\xb1\xcb(aZw\x1bO\xa7\xa52\xf8n\x82F\xf1\xf8Z\x15\xb9\x97\xcdT*FW\xa9\xdc\xce?\xf2\x01\xdf\xddg\x99\x96\xac\x96\xdc}:\x8d\xd0\xe0\xc7 \n\xda0\x86\x8cvCP\x04\x9f1\x8cE\x9fQ\x91\x8f\x98\x03\xecm\xce~\xa0\x0b\xbb\x0d3\xc8\x18\x81\xae^\xd5C\x15\xfc\x12'\xd4i*QS| \xc4S\x1d\xd6G\xd54\xdf\xad\xa7E \x0f/JY\x05\xe9\"UC\x12\xa0\xd0\x9c\xdd\x81yZ\x0eE\x91\xd9\xdc\xa0\xa6\xcbG\xf9\x05\x16\x89\x8e\xbe\x8d\x92K\xcd%\xbf\x9a\xecXo\x9f\x17\xed\xdc\xbeL~\xcd\xfb\x90\xe1g:\xf6#\x8bw\xeeK\xcf\x7f\xce\xfb\xab$@\xef\xd8\xad\\>u\xc1\xa2I\x86\xd0z\xd7\xd2mC)\x87\xd4\xba\xd2\x81\x86[\xe8\xf7\xc9\x04\\\xca\xec\xc0:4\xc4\"\xb7\xb9;5\xd6\xb79\xbdB{\x00\x03\x90&\xf1\xf2\xc8?|\x80==S\xb5}\xcd\xd0\x00\xb3\xac\xc8\xb2\x82U\xe8\xd7-\xbe\x95\xb3\xe15\xdbr\xab5\xac\x92\x1d)\x84+hm\x0b\xab1\xa7\xe5\x83\x05K\xf9\xdffI\x9c\xb38\xef\xd3\x10\xf1\xf8\xd6\x12\x04\xadT7\xab\xd5\xf5\xc1\xc9\xd9M\xbe\x8f\x01\xa9\x1es1>c\xf9\xe4\xed\x9b\xef\xfa\x0f1\x04W\x05\x8b\xe4\xe1\x98z3\x10W-Z\xbb1T\xe3\xed\x7f\x0e\x12\xa8\xd14N/\xd8l\xa2\x90\x92<\xee\xdf\xf4\xaf\xaf\xaf\xfb\x1c\xc5\xfb\xdb4\xa2\xe8\xfc\xf3\xea\xac\x8d\x12\x8c\x96a\x8d\x88)\xd1\x94V\xfe*\x8d&!i\xcc\xe6\xfd\x0d)d\xb4\xe44\xf6B\xe5E4\x88AY\x12]\xb1j\xb1.\xedi\xd0km\xb6\x15\xb7;\xf5$\xa9\xa4\x01\x0bg\xc9\x96k\x8cI\x8e\"\x9b\"\xbf\x98t\x17\x82\x0c(\x93]\xa3e\xa2\xcb\x989\xb6\x9d\x9b\xb7\x99\x04\xda\x12&\xb7nq\xc9\xaaY\xa5\x04Gr\xe79\x8e\xda\xf7\xa9\xb4\xfc\x02\xeb\xf8l]o\x90\xafXl\x8aM\xfdQ\x92\xdf\x9c\x88G\xeb8\x7f\x13Pl\x17\"`G\x11P>vQP>\x15\x91\x90o\xb3A\x16\x94\xcf\xc7_\x0bM\xba-A\xc9\xf3\xbe&\xfd\x91\xbfzaS\xcde\xdc\x17\xf2\xba\x1f\n\xaf{u\xb5E:\xdf\x9f+\x1b\xc7`\x91&\xeb\xe3U\x90\x1e's\xe6\xe6\xd3F\xd6+\xb5\x17J\x99`\xcbk\xfa\xd1\xb2\x10\x9dV\xee3\xd0\x9e\x03\xf8\x8eh_Fv\x0bE\xd7E=\xaa\xb1($\xb8Vt\xd2\xd1>\xc7\xf37B\xd5E\x03\xaa\xfe\x9c%\xf1\xe7\xb4\xfd\xa7\xb3\x97/(\x06\xaf\x95z\x95\xde\xdb\x94\x85Y\xab\xe7\x0f\xf9\xf5\xd1\xfd,\x0fU\x87\xfa\xfa#\xad\xd0\xad%\xc6\x08\x94`P\xdf\x8d\xb6\xc4\xb2\xba\xde Q\xda\\F\xf9T\xf1\xcd\xac\x94)\x95\xe9\xbf\xb9\x1a%\xe4\x83\xc2Gv\xa5r4\xc7\x98\x8f\\e\xd7\xf5\xe4NQ\xd6VlL&p\xa5\xf7\xc9\x9c\xd1\xdbd\xce\xfcR\x82\x18`\x9a$\xcc\xbb\xc2l\\z\x06\xf6\x8a\xbd\xc1\xb0\x87\x9a`H\xb3T\x06K\xf3\xf2\x1bf\x9f\x97~\x7f\xf8P_\xa1\x0f\x1f\xc0I\xd6a\xee\xf8\xb0W,NE\x98\xb2/Vn_\xacv\xd2W\x98;\xf3\xe4\xedf#\xed\xbe\x8d\xc8}\xabe\x1a\x87\xa7\xd0\xa7{H\xa6\x8c\xdd\x1f\xdd\\\x0eFN\xbc\xf8\xe9\xfc\xc7\xc9\x1b\xc7+\xefcN\x7f\xa8\xc2\xe2\x07\xe5\x9d\xc1W)[\xb04EI\x80\xde\xba\xd8\x0e\x99V+\x1d|\x7f\xf2\xecy\xed\x0b\xf9\xcbZ`\x1eUoN\xf90&4\x9b#[\xf8\x8f\x937\x90\xa4\xc0[\x939\x873\x13B\x10\x91\x93\x1a|5\x8e\x8f\x0d\xf7\x17\x1d\xac2\x82\x0c6Y\xed\xd3p\xedz\xf2\x8c\xfe\x8ec\xb0\x1a6\x9a\x11Z\xc5\x03B\x1e\xd1~cxb\xfe\xe0\xf6H\x0b\xba\x96M\xa5\x87YT\xa0\xad:\x1e\xdc \xe67q\x8c\x0d\xd8\x99g.-\xa0\x14d\xf8\xed\xeb\xd3\"&\x19\xd7\x91\x0d\xaf\x93\xeeq\xe1:[\xb77\xed\xfb\x9a4l(\xad\xf4\xfe\xbb\xf4\xe8]\xbc\xbf\xcbn\xd66k\xdc\xb4\xda\xe5\x8d\"(\xb2\x8b\x0f\xdd2\xda\x8b\x8d\x1b;\xcd\x0d\x82\xbeWi\xed\x0e\x82|>g\x0f\xe6V\xbe\x9a+_\xfa\xbf\x17\x82\xbbH\xd0-\xae\xeeI%\x99R\xd5SXs\xfe\x17\xe6\nC\xf7\x0d\xf9i\x0c\x07\xc3\xa1\x8c\xfe\xfa^\xfa\x85\x88\x8fO'\xfc\xab\"\xe7\xe2\xed\x138TU\x8a\\\xf8E'\xfcW\xad#,2\x06\xe7\xe5\x9f\xe5\xd8\xec\xbc\xc0\xd7\xb9V\x8e\xffc\x8a\xfc\xaa\xa1\xb1j\x17)/7\x1axDZo\x1b4\xaf\xac\xc7n\xba)a\x0cN\xc5\x92\x80\xd3\xb3\xe4Q\x92\x07Tcp\xceD\xcc\x88P\x06\xa6\x90\xc7T\xf8\x8a\xbe\x9a\x1b\xe1\n\xdb\x18\x9cB\xa1\xd1\x1a\xe1\x1aF\xf1\xb3U\x00\xe4O\x9e\xde\xb6\x98\xc3\xb4C\x07\xde\xbe_=\xc3\xd0\x9f\x8f0\xc3\xe0\xd4\xcd\x94\x174\x97\xca\x91\xbd-3\xe2T\xa3\x1f\xcbGJ\xd5|m\xc4\x9fM{\xa1\xa9\xdfcp4E\x83*\xd5\xd1\xd3,\x1a\x95\xcc\x84\x1eB\xce\x15L`\xaa\xe2\xd5\x9cJ}\xeb\xdc\xf1\x8b(6\x85\x1aV\x7f}\x1c\x05\xeb\x0d\x9b\xd7\xbf\x9e\xc6\xf9\xe8\xbe\xb9\x92\xe9\xfdi\x9c\x1f\x1e\x98\x8b\x9b\xde\x7f\x17%\x81\xfd\xc3\xfd\xbb\xe2\x83%,A\xfbuP\xf9H^\xc0!\x94o\xd2_Bv\xdd`~3\x03\x81y\x10*[\xaf\xb0\xd2\x86\x19o\x9cS\x88\xdd\x87v\xa5\xc4\xc1\xd6\x10C$.\x9a\x07Z\x87\x9aDk\x89\xd8D\xc5 \xd5\xca\x8eP\x94D\xb5\x9d<\x83\x9a\xae\xde)?\xbeu\xb0\xb1:Di\x05`\x82\xa7\xd0\x18\xfd\xd4\xc7\xe8\xa706$\xff\xc1 ^\xc5\xf8\x85\x93z\x97\xad\x17EU\x97|\"u\x9f\xf6J\xfbK\x96wj\\m\x9c\\ b#\xe4f~T\x9a'\xa5{l\xebx\x154\xfbFU:\x96\x1d\xd4\xc2Bs\xe8h\xeb+\xabL\xb2\x01\x02\xca\xab'\x80\xa0\xad}\xe9\xf3\xdb\xe1\x1a\x14\xd4\x02\xdc\xc8\x1e=\xeb\x1c)\xdc\x8d\x88L\x95\xfb\xc5\x18\xe3st\xfc\xcak\xa7\xf2\x861b\xd0\xb2\x0e&\x0bi]\xb4\xe5\xfb\xd3\xf7\xa3\xee`\xd0\x92\xea\x8d\xc9\xc8lfT\xc6\x8b\x89f\x93\x88>\x15\xf23\xfe\xf5'\xd3a&\xb6\xd3\xfb\x8e3\x11\xae\xd2\xbf\xfeT\xba\xed\xcb4\xae\xdf\xf7\x92O\xd3\x94*\x8eA\xda\x0cM.B\x86\x05\xb0\x9c\xc5\xdf\"\x9f\x7f~\xf2\xc3\xc9\x9b\x13\xce/\xb9\xc2\xee\x0b\xf5\xdc\x07\xe7\xe5\xab7\xa7/_\x9c\xf1?_\xbd<\xc3O\xaf\xde\xbeq\x0c\x0b4\xd3\xba\x9c\x89\xf4\x17\xad+\xaeIe\xd2\x13\xdc\xbe\x82\x97\xc9\xfcV?e;\x8dC\xb3+\x96!\x16\xf5G\x1f\"Bnm\x9c\x9ez9/\xbd\x9c\x7f\xe6T\xe6\x95\x93\xff\xa6I\x91\xf60\xd6\xb5\x0d\xbbFX\xa8\x1a\xe3\xaazb\xaf$\xb4\x8e\xb1TC4\xdd\xa4A\xf9\xdc\xa6\xd1X\xa9);\xac\xf2|\xd0\xd9\x9fF\xa2\x1b-\x19Y\x8c\xda\x17\xca\x90D\xb7\\\x84\x96\xc7q,\x83nDm\xa6\x14M\x9c\x85S\xf5|\x04\xb34$/\xd5L\x0f\x87#\x1f\x0e\x87\x07\xfc\x9fC\xfe\xcf\x03\xfe\xcfC\x03\xba\xcc\x07)\x9b\x87)\x05\xd8\xed\xc4\xd2\xb8\xa0.RK]jV>\xddZ\xf6:\x88\x97UwS\xa1\xd4\xce\x92\xb9\xf5\x80\xbe\x04\xba]\xf7\xa1\x0b\xc45+OQBG\xcd&\xeb\xa4|,\xea\x93\x11\xf4\xd8\xe0{\xa5r'\xfc\xe7k2\x08\x02\x86^\xe5?\xb3M\x12g|{\xe7\xfc7j\xce]W_[\xa3\x9a\xd3Z\xd3%\x17\xd0\xad/H\xe6\xb0\x97f\x1b[(\n\xff\xe7\x8f?|\x9f\xe7\x1b1\x0f\xbb\xa9&\xdc\xd13\x0e4\xeck.\x05\xda\x8e\x87\xad\xf4\xa9\\\x83\x101\xecD\xa4\xe4\xa3@g\xe3bN\xa7gQ$\xb7Ml\xae\xeb\x91\xb1\xc4\xee2\x02f$\xd5\x1f&\x8c/N*\x1a\x7f\xfb\xfa\x07G&\xa2\x0f\x07\xda[\x18\x03+\xfb\x93\xfcg_\xecG\x9fWj\xf1y\x91&E\xd5\x91\xa1\x17L\x0f(\x7f\xf0ejn2v\x05\x8f\xf1\xc1$\x97\xcb\xe7\xa3\x8f`\xd1\x99\x1a\xcb'\xad\xba\x86\xbe`\xf9u\x92\xbe\x97\xe6uX\x04a\xc4\xe6&\xdf\x0f\xf9\x88\xaes\x8a\xfe\xfd\x0f\xe9|\xc3b7Q\xc7Q \x9d\x7f\xe1\xe5&'\x8cg\xd1v.\xe2\xd4%\xa5\xd3\x1e.Y\x85\x18\xa5\xec\xb8tND\x15\xd5\x16\xddn\xe46\x96|\xc1\\m\x17\x05\x17!/\x0c>\x00 B;\xf9G\xcb'\xe4\xea\x95\x80:B\x03\x8b\xbb\xb4|0j\xe4 c\xf1\\\x0f\xa6\x9ah\x87n*}\xa0\xf6\xd2&\x95\x9a\x89-\x92\xcf\xc1&\x89n\x17a\x14\x99\xbc\x82\xd5_\xae\x9e\xc1\x163[\x90lQ\x8d\x85\xf6\x07\xd1xiqv\xbai\x94\x9bn\x19\xdd\xbb\xeb\x0d\xc8\x98b\nd\x1b\x1a\xb7\xc0lQ\x14\\\xc0pLQ5\xd5J\x13\xa2Q'\x10\xcd\xa4*\x8d\x9b\xf4\xc6\xe5\x03\xd1|\x13m\xeb\xa9\xfe\xaa\xb6\xd0\xc6\xcd\n\xb5\x18\xef2\x89\xec\xdd\xf2`W\xf9Ml\xe9\x9eQF\xffE*KN\x910\xdc\x9a&\xe7J\xc4\x1b\xcd\xe0I\x11N\xfa\x88k\xd6\xc2\xbf\xe2Y\xee\xa2s\xfd\x8b\xe0E\x9d\xcee\xd7!\xae\x9a5\xdb\xfd,\xc8\x18\x0c\xc7V\xc0\x97\x0dX\x8f\xd7\xe5\x83\x0d\x1d>\xb0\xb7$\x1f-\xd9\x80\xb8z\xd5\x10Y@>\x98\x86\xad\xb9\x18\x0e\xe0\xeea\xfb\x00\xf0J\xac\xcb\xd7\xf4\xf0\xa0\x85\xdb\xc8\xc0\x86\xadm\x06\xd3\xa8\xd73'\xea\x94\x8fY\xf2\x82\xe6\xc9\xe1\xa4F\xf6\xfe\xb9\x0c\x1b\x92<6\x83\xa7\x13\xb8\xfb\x90On\xc6!\xeb\xde\x03\x0f\xd7z\x06}\xb8\xfb\xd0>O\xe5\x95\x8b\x0d\xdc\xbf\xa7\x1ax0,\x1a\xb8\x7f\x0fz0\xb2\xdc\x10\x86\x1d\x1ch\xa9\x97G\x0fT/\xa3\xe1Ac\xf0<\xf9\xa8\x15>|\xe0k\xcb-p\xab#\x045\x96\xb2o\x10\x08\xb0\xe5+\xf1\xe8\x01\xae\xc4'l3\x1f\xe8\x81}\xa0mPp\xd0\x0c\x05\x82\xc4\x98\xa0 \xfd\\(H\x7f\xe7P\x10\xea\x10\xf1\xeb\x83B\xfa\xd9\xa0\xa0F;\xba\x0f\xdf@\x0c=\x93Q\xfd\x0f\xf6_\x82\xdf\x05ER\xe2\x08\xfaz\xea\x94\x8f\xbe\xc6\xca\xf8\n\x15\xab\xa2XVP\xf2\xf2;\xb8w_2\xaa\xc7\xb0\x85'pp\xef\xfec\xe8\xf5\xb6\x1e\x04\xd3-\x86#\xfe\xa3\x03=p]\xfeqt\x1f\x8e\xc0\x19:\"]r\x0f\xb6\x05\x97\x1d\xdd\xf7<\x9b\x87\x8d\xcc\x9e\xd6hFo\xb8E\xd9\x9b\xf0\xfe\xca[\\\xf2ft\x9cR\xceP\xe1\xac\xc8\xb4T\xc5F\xcdRj\x94%\xb6j:I!\xf0=<$\xf9\x8fkNw\xefi\x7f\xdf/\xfe~\xa4\xbd\x1f\x1dh\x1f\x12\x0e\xfb\x87\x8f\xf8\x8c\x12\x0e\xfbw\x0f\xd4[B\xdc\x84\x10W\xbd%l\xc4\xb7\x8f\x86\xea-a\x0f\xbe\x1d\x1d\x1cX\x04xtd\x80>\xc4*\x1dh\xce\xd7P^(BE\x9b\x8b\xd3|K\x0f\x1e\x12\xbdO9T\xfb\x80\x05\x83ib\xb1\xdd*\x82\xc1\xeb\x1e\x0c\xef\x1a+\x8f\x1e\x1d\x00\x0e\xf7)\xdc?\x87\x1e\x7fs\xf0\x10>\xc0\xfdC\xb8\x03\x9dZ\xbew\xef\xe0\xd1}5\xe7{\x0f\x0e\xef\xde5utppWv4:\xd0{\xa2\xbe\xe1\x0e\xdc?\xdcm\x00\xcd\xd6\x87\xb0\xc1v\x80\x10\xd2\xeb\xe9pW2*\xbd}}*\x94\xb1\xb7\xafOa\x1dD\x8b$]3\xab\xdb!\x08\xfb\xc5hx\xc0\x07]\x81P\xdf\xb4\x18w\x87\xf0\x81\x12\xc5\xdd\xbfw\xef\xf0>b\xad\xa8\x9ex\xf0\xe4 \x8cx\x81\xd0\xf3p\xbd\x1e\xd6\xd6ktP[\xb0\xe6u4\x0e\xbc\x03\x01+\x02\x890\x8c\xfbT\x12qs\xe8\x15\x80\xea\x95c7\x96\x15\x95\x96\x88\x05\xd4\x97\xe5\x8e\n\xef\xd8\x94\xb9\x85#K\x98}\x17\xc6!E\xe4:\x02\x87\x93?,~\x99$\x11\x0b\xe2zSG\xe0\xe4\xe9\x96!Y\\\x04QF\x7f9\xfa\xb8\x0b:,\xf5\xa5hw}\xc9\xae\x1e5\xc51,8\x02F\x1e\x18vQ\x87h\xd1\xc2\xc5-&\x0c\xa4[+U\xa5\xc8\x9c\x0fX9\xf1:w\x04MF\x87UgR\xb9ht\xa5\x12\xfa\xd2\xd8\xca_\x89\x0e\xd8\xa2\x18%bD\xba\xe6H\x96\x03<\xb3\xa9\x7f\xe4\xf8B\x99b'\xf6d>\xa6%,qM=\xe3\x83\xcc1\x1c\xa8\x88$\\\xbd\xdbrvL\xd9\xf29GZ\x10+Z\xc0\x13\xd8r\x1e\xb4h2\xe1S\xaa\xe1EC\xa6\x879\xa5$n\xc9\x16\x11\xba\x19\xe6\xb7\xedU\xd3A\xca\x87\xafm\xf9\x12\xf8\xbcQ\x08Skp\x05\x13\x98\xab\xf9\xaea\x02W4\xdf%\xcds O\xe0\x8a\xcfs\xe9\xc1\x8c\xd3\xa4\x15\xf4p8\xf3\xe9\xf2\x9c\xf3\x1b^`-\xd4\xb0\xde\x04\x9a.V`\x08+\xbep\x91^\xdeLp\x88r\x97{\xe4\xdd\xb5W\xaf\x8bj\x02gf\xedDL\xc7o.v\xa1\x8f<\x024\x995\xbe<\xba\x04\x86\x88_\xa1-\xea\xc6\x87\x0f2[\x8fdFJ|,\xb7`\xa8\x9d\x17\"CM\xec\xba\x12)\xf1c \x08\xb5%$\x8fp\xdbW\x8e\x1b#vXn\x94P\xbdN\x8e\x93\xc1:\xb8\xf93\xbb\xcd\x94\xee\xae\xde\x18\x86\xc5\xd1m\x04\xfbU\xb5p\xa6\x84 ^`f\xa8\xb8\xc1m\x93T\xd2443\x15\xaa\xdb\xaf\xb0\x9b\x0d\x8e\xb3\xfe\xd1&\xc0r\xbc\xde m\n}D\xe1\xe9\xb9\x8f\xc86$,\x1b\n\x0c\xf3\xf1\x94\x99\x13\x96K\xf1\xff\x05\x9d\xc1\\\xd3\x7f'T\xe8\x86\xb0\xf1\xa6\"\x00\xdf\xd8\x04\xe0\xb3\xaa\x00|c\x11\x80\xcfp\x8c\xb9^tm\xa5\x1c\xbc\x82\x18<:]\xb9\x87\x0f\x10\x1c\xcf\xe0\x08\x07:\x821\x9c\xa8\x9d9+\xc4\xe0\xb3B\x0c>+\xc4\xe03RJ\xd5[\x12\x83\xcf\xa4\x12 G\xc0es\xe8\xf5(\xc2\xda5Y\x9b\xb1\x8f \x86\x91\xe6\xb4\xc7j\x0e\x035CJ\xba\xa2\xcdp\xd9\xaa\xa0\xf2\x8a\xbd\xde\x12\xabn=\xb8\x82'\xe0\xbe\x87 \xdc@\x1f\x96\\B\xa38\xd5\xb7\xba\x04~\xe5\xc3{N\xa2\xc4\x96]a\xf1^\x9bIl\x96\xc4y\x18ow=\xe6\x03\xe1\x0d7\xe4\x00\xf3\x9bo\xc5Ee+\xcc4\xdc\xf8\xf6\xee\xa1\x18'o\x077\x10\x8e\xc0\xe5\xebz\xa5\x86[]\xd6\x1b\x0f\xe3\xa9q\xd2\xf5\xc7\x83\xa1\xc0\x11\xea\xbfR\xf3\xd2T\xf3R\xaby-\x8f,\xd4\xf6\x188H\xa1\xb7\xf4zk\x1cn\xd6\xc4\xe5\x8f}\x90\xb0\xb1\xb6o8oN\xce\x97\xc3\xd3{\x1b\x04\xc1X\xfb^\x9d\x10B\x98\x8c\xf88\x81\xc8\xbd\xf5a\xc3\xdf]\x8b\xe2\xfc\xdd\xa5x'\x8e\xc4W\xeaH\xfc\xd6\xf3 \x98\xde\x9ec(KXMW\x82\x96\xf0\x17\x86\x9bY 4(\xf7\x18\xe5\x98\xdbsO\xbf\xa6\x85r\x06\x1c\xc1\xf1\xf4Xk\xe6\x12\xc6\xb2\x8b\xe9\xb1\x0f\x97\x16\xc5\x8c\xaf\x06\x06\xf5\xea\xf7\x17^\x93\xc1\x8cou\x99\x16\xdeb/D,\xd5.\x12UE\x8c\xa8\xef\xe7\x1f\xec\xbf\x16\nt\xaet\x95\xe5\xc3\x07X\xf2/^\xfd\x93\x0e\xb7\xe5\xdd\xe3;\xb7\x86'\x90\x19v\xce\xfb\xcc}\xe3Hb\xdd9D\x84\xcf\xd9\xa3\ns\x90B\xc5\x1f\xcak\xd69\x93\xc1#K*\x83\xc3\x87#\xaf\xfdtO\xba\x13\xc8\xebpp\x04\x7f\xffH \x0dAB\x8b\x91\xeb\xc7e\x9d2]\xea\x03\xaeF\xd5\x13\x03\x1e\xb6GI\xb4'\x85HE\xa7\xad~p\xa2|\xe2\xb2Z\xfa\xb3\xd6\xc8p\xd69\x8d\x0e-s\xba[M[D\x81\x05\x1f<\xea2U\xc3\x0cJ\xfaT\x7fD:\x94\x12\x16Qt\xfc\xfbG.\xad\x04\xa83\xd9D\x16\xbc\xf01\x0d,\x9a\x10\xe6\xe9\xe3#\x88\x0c\x82L\xec\xce\xf8\x07\xa0\x98\x81>\x84nDA:g6\xbd\x18\x8aU\xcfv[`\xf3\x19\xeb\xfe7{E\xdb\xdf\xc0,I\xde\x87L\x7fs\x9cln\xd3p\xb9\xca\xdd\x99\x07\x07\xc3\xd1A\xff`8\xba\x0b\xaf\x93u\x10\xc3\xd9*\xbf\x8d\xd6A\xdcT\xe1\x1e\x1d\x9e#\x0f\x99\xa3*O\xfcf\xc4\x99H)w\n\xc4\xd3\x0d\x95\xc3?&\xb0u\xe7>d\xed\xa1)M8SI\xe4\x9d\xb14\x0c\xa2\xf0\x17\x93~\\],E\xa0\xc4v\xd7WZ7O}\xf8P\xbdm\x88pY\xa8n\x05d\x86\x16\xc8L0\xa9\x1e\x88\x06\xc3\x0cB\xf2\xfe\xab\xee2\xeep\xd0\x12\xa8R\x81y\x1c\xac\x9b\x1a\x93\x1auX\x8b4A\x07|\x18\x9e\x9b\xfa\xda\xb6\xf6u\x15D-]\xe1uu\xe8\x813q\xa0\x07\xdbz\x8f\xc2R\x06)W\xb5\x9f-\xadW<#(\xca@\xdft\x18\x8b\xc7\xd4\xd9\x8b\xe0\x85\x1b\x99\" \x89\xaa\xd9\n\x831 \x0dxA&\x00\x03\x14g(\x98?\x86\x1f\x83\x9b\xfe\xb3%\xc3\xc1\xff\x18\xe4\xab\xc1\"J\x92\xd4\x8d\x9a\xa87\x1e\x87\x0c\xe6\xc9:\x08\x8d=\xe8o\xb0\xd7\xe4\x15$'(\xfa\x98\x9cUe\x9b\xea\xd3\xe6\xdd\xe0D\xc1\x8d\xb3C\x87?\x047\x9f\xd3\x9b\x90\xc5v\xe8\xf0sf\xd8\xeaF\xd4\x04\xf4j\xbfu\xa8\xaf\xb5\xd4\x81\xffj2k1L\xc9Y\xebF\xca\xba\x1aP?N\xa9\xab\x04\xfb\x8f\xe1\x9b\xfd\xf2k.\x9a\xed\xff4}\xb7\x1d\x0e\x87\x8f\xf8\xbf\x07\xc3>\xff\xef\x01\xe3\xff>\xa4\x1f\x8b\xc5y\xef\xdf\xf6M\xc7c\xdb\xdf\xeax\xac\x1a\x93\xb9\xfc\xd7'I\xf8\x1dC\xaa\x8b\xfek\xcb\xeb2-\x1c\xc4t\xefk\xd7\xfb\xe6|\x7f\xd9\x16\x8b\\\x1eK\xa0\xbbF\xc9\x9e;\xf4J^\x1ae'\x8d\xf2\xec\xdb4H\xbd\xe3n\xb3,\xb9i\xc8\x1c\xf32+\xb2\x92\xc7c\xbb<\x9eV\xcd\xd3\xb1E\xe4N\xd1U\x00\x1d\x07\xee\xdc\x81\x14m\x97\xf7\x0fG\xe8q\x11C\x0fF\xfa\xc9|\x83X^s\x08\xc1\xca\x16\xc1\x9a\x0e*\x9fbW\x07h\x1c\x12n\x1c\\un0\x1c\xcb\xe3\xcf\xd1\xf0\xe0.|C\xde\x1a8v\x0fz\x90\xf0\x1f\xd8^\x8f\x8e\xf2\xed\xe4'\xa7\xebp\x07w\x87ey(\x84}\xb8\x7f\xb7\xf8\xc7\xf3at\xf0\xd0Z\xc6\x83?\xc2\xfd\xbb\xd62\xe5\xcf!\xfeB\x1f\x84^\xa3\x1bg\xa3\xbd\xban\xf25\x9c\xc6Qh\x89\xbb\x0f1B\x04\xcd\xf4\xe0ny\x84i\xf3$S\xc3\x04R\x9a\x00\xe7\x97\xbc\x03\xfeR\xb5?zt`l\xa0^WTH;\xd8\x0d\xda\xd2O\xea\x90\xb2gw\xf3\xe7@\xc3la\xf9\xedF\xb2J\x91\x86\x0b\x96(\\\xa6z\xfe/\xcb\x19\xb2\xc4\x93\x86[d\xa1\xddAs\x9e\xb4`F\x80V!v\xc3f\x8d\xa9\xc5\x94\xb62\x99L h4\x0d\x83\xd2\xcbCx\x02\\\xbao)\x9c\x90S\xcd\xf0\\\x19\xa7\xc2^\xcf\x0c\xc8p\xbd\n#\xa6\x14'>\x14s\xbb\xd2v\xc7\x81N\xf3x\xe9\x8f\xcc\x19r\xfe`\xdfIK\x8a\x00\xd0\x9d\x04\x85v\xbaS\xbb\xc2\xach\xa3\x8eZz\x8d;\"\xbd\xc1\xd4\x99\xfet\xee\x9c\x97\xcd\x07d;\xe0\xa2l\xcd\x9e\xa3\xda\x12\xa4\xbd\xed\x92\xf0\x0ea\x81\xb0\x1a!%\x1bd\xc96\x9d\xd9\"Fx\xbe,\x18\xca\x82\xe48\x98\x0efI<\x0bD\x10Gv\x0d\xaf\xd9\xf2\xe4f\xe3\xa6\"\xe0\xcf\x07\xc7\xab\x99]\xc1H\xba\xd8`\x11\xc6\xf3\xe3U\x90\x9e\xc6sv\xd3fB\x93\x0f\x87\xd1\\\x87\x0f\x85\x89\xfd\x86\xb3\xa22\xceZ.>\x95,i\x89\xeb\xf9\x02E\x0b\xd7\x98X\xa2\x1c\xda\x1c\xdcx\x10\x05YN\xc3\x7f\n\xb9\xf7\xd8\xe38\xd0\xb8]\x86\xfc\xcc\xbeX\x8aoos\xb6\xd3R\xc8\xd9\xf0\xd5\xc0\x1b\xb4\xb4 \xe4\x95\x858\x83\xf5q&\xe6x\x8b\xc4\xc5\x9fu\xbe\x1a*\x17\x87n\xa6\xebc\xa6j\xf6\x0d\xe0\xd2\x0c\x9e\x88\xc6\xc6\xbd\xb3EY.\xe4\x1b\xe5\x98\xc9\x85\x8d\xea\x89\x88\xfe$\xe8t\x84\xfb\xd4\x92~KQ\xc6\x84\xeb\x8c\x94)?\x99\x0e\x8dq6tyg\x97\xd5j\xbd)\xa3?r\\Hc\n\xdc\x92(\xe8#\xb50\xee%\x7f>\xb6\xedA\x8a\x06W\xd9\x8b\xf1^\x0c\xd8D\xbc\x96\xa5$\xa9\xf2\xc9\x84\xbcA\x92B\xb4+\xcd\x89\x8f\x15}?\x87\x9e\xafdN\xe95\xca<\xa7\xd0=\xa8\x07\xee\xa2Q\xe0\x10\xde$\x9c\xf4\xbdJ\xc2\xb8\xc5\xe6!\x9f.\xb6\x0f\\\xdb\x99lW\xae\xb1\xc6=DjIU\xc4\x13\xd6\x12\xa1~j\xef\x1b\xa7o\xe1\xfajBo\x84\x85\xe8\x8bM\xac?\xb9\xcf\xd7\xf2\xf9w\xdf\x9d\x1b_\xeek\xbb\xfeQ\x1c\x16t=\x13\xf8\xba\xdf\xef\xbf\x8b1\x00\x96\xb3\xca\xf3M6\xde\xdf\xdf\xb0\x1c\xf3\xdd\x0f\xb2\xeb`\xb9d\xe9 L\xf6\xaf\x0e\xf6\xe5\xaf\x9f\xb3$v\xde\xc5\xf3d}\x11\xce\xc7\xe0|%>\xf4\xb7\xa1\xf3\x8e\x0e\xc1\x82\xd2>\xab\xa60\xf2\xc15-\x07\xf4a\xe6\xc1>$\x1dg\xa5?ie{\xb4\xa3\xc0\x0cz\x10\xc17d\xee\x1d\xdc\x83#8\xc08\x0e\xdf`$&\xfe\xbf{\x17\xfa\xf4\xd2C\x95\xd2\xa6\xe0\xd8\x9e\x02Py\x17#\x0e\xac\x08\\\xdf3t\xef\xf5\xf0\x00\xf2 \x10`\x0f\x88L\xd37.\xb1\xa0\x0b\x90\xbe\xd2\x81\x0f\x8f\x1eiPo\xc7\xce\xea\xf3\xd1\x87G\x1d\x8b\x7ft\x9b\xcb\xd9/%5\x90\x84h\x07S\x85|2wK\xf1\x9e\x8dG4\xf2\xb1\x84\xb4\x93\x8c\xc8N\xa4X\xbe\xdd\x8c\xbb[\xbb\xa1h\xd4\x1571\x91*y\xeap\x8c\x8fU|B\x87\xe6\xdcS\xc6\x9d\xdck\x8a\x1d)\x1f\xe1`\xf4|\x9b\x8a\x00\x90q;\xb8\xb3\xf9\x92\xbd\\,2\x96\x9bBz\xeb\xcf'\xed[\x9e\x8c\xc1\x92\xab\x80>\xff\xd7\xb8\x89\xd6\x85q\x9e\xfc%d\xd7\xe5u6]\x9c\xad>\x92Wc\x9c\xf0o\x93m<\x0f\xe3\xe5q\x14\xb28\x7f\xcdf\xb9\xeb\x0dV\x88'\xed+\x14H\x8a\xae\xf8Z\x0f\xc2\xf6j3YM\xe2j{\x95\xc5N\xbcc\xc3Q\x02zm\xa1n0\x05\xf2\x13Xp\x88\n\x91^<\x85\x19\x1cQ\xbc\x01Z\xc91\x04\xe2\xc3\x06\x8e s\x03N/\xf9\x9b\xa2\x00\xb1\xd2\x06\xccn\x80\x81\x19\x8bs\x96\xd6\xb60\xed\xb0\x8b\x99\xdb$]\x94I\xe1>\x1c@\x8f\xa3\x0b\xc7\xaa\x96]\xe7\x85=OL\xefS\xe6\x94\xe5\xc9f\x0c\x81\xbd\xc0:\xb9\n\xe3e\xc7\x0c\xfcP\xd0\x86\xbd\xbd\xfa!\x90|\x1a\xc6\xc3\x81f,\x80\xa7\xb1\x14.\xdfX[Jca\x833N\xbdUN\xb3\xa4\x14?\x90\x7f\x9cDl]s \x04\xc1G[\x17C,\x82\xd0E\x88\x9f\xfd\x17\x1a\x91\xc5\x8f7\xc9\xa6\xcb\xd0\xd0j\xef\x9a\xfb\xa0x\xd7j\xe0\xd4n\x18/\xc5\xc8yo\xea#/k^N\xa4\\\xddd\xe5\xd2l\xde$\x1c\x92wL]\x81\x9bkIN\xa9P\xa0#\xac\x95\x978\x8cc\x96\n\x89\x01\x97y\x86\xc8Bov\x1c\xa3\x00\xadn\x8b\"\xf5T+\xa2\xe6\xc9\x86\x93 \x14\xde\xe2A\x82,\xca\xb4\xfb`\x06W\x83\xb75\x06%\x0drv\x86\x1bQ\x8b\xeah\xa3G\xd2N\xd5\x08N\x96D2e(i \xcb\xaf \x9c\x03\xef\x8ek\xff_\xbb\xed>k@'h\xec\xe8S`M\xc9\xe7\xac\x04^~' \xdc\x15S>\x0d\nw\x86/\x01/\x7f\xa8\xbct\x82\xf9\xfc\xe4\x8a\xc5\xf9\x0fa\x96\xb3Xd\x0c*L.{b\xcaq\xf2\xff\xb2\x98\xcc/\xf8\x9a\xb9%\x9ac\xbc'&E\x1ag\x15fy\x92\xdeV\xad9\x9bm\xb6:\xcb\x83\x9c\xcc<\xa2\x90y\x9d\xb8L\x13\x92 \x08\xe1\xe05\xe3\x85Qj\xd4+\xd7%\x0b\xcaT*>\x0fj\x95\xf9\xe8\x82m\x9e8\x9e\xda\xdc\xea\x82\xb8N\x94\x04s\xc7o\x87 \xeakWE\xb1ql\xeb \xde\x06\x91%\x86=Wq\x1a\x86\xbdI6\x19\xaen\x9b\xe7\xb5|\x18\x86\xe8&K\xdc/,\x16\xdc\x8cRH\x15\x9f\x12T\xf1\xc4\x8bAQ\xce\x06\xf7\xb0\x87\x97\xf3\xc40e\xb0\xf7\xc1*\xc8\x10\x92v].iUL\x06\xa8\xd0\xb8\xde\xa0\xd0\x08\x9aO\x0dZ\xedC\xd2h\xa7 {\xc9\xa4x\xf0\xed\xed\xe9\xdc\xadM!e\x0b\x99\xc1\xef+\xc7\x9b\x8e\x9a\xf2\x05\x83t\x8ek\x1b\x05\xd4\x0c\x05$L&\x850\x99s\x1e\xc3:\x88\xdc \xe4\x98D\x08\xe9\x9c5\xb5+\xf4Cx2\x81\x14\xc8 \x1d\xd0\xff\xdc \x124\xa8\xa8\xd0\xac}\xd9\xa1\xd9D\xb6\xf6L\xae\xebW2\x8aO\xe1\x86\xe5\xb8?}x\xf7.\xf34J\xe5\xbe{\x97}\xf87\xcf\xe4\xc2i\xc5\x9aY\x14\xce\xdewB\x99\xd2\xb1!\x1b\xe4A\xbad\xf9c:\x89q\x9e9\"\xd8L\x1e,_\x04k\xf6\xd8\x13G\x9f\x9b eq\xfe\"\x997$\n\xdfs\xf7\x90\xb1\x8c(\xe0\xd7\xe0z\x15\xceV\xa4&`\x1a\xc8?\xb3[\xfa\xb5fy\xa0~\xcc\xf24R?\x82\x88\x97j\x8c\xfd\x82\x16\xc86h\x94\x90\xa8\xa8\x94\xa2\x10\xf5\x08d\xe52G\x95\xdf\xe3\x9a\x91\xbc\xfa\xc4\x1a5\xd1\x80\xb6\xb9R{\xca?\xd0\x88\xac\xb8\x96\x82\\\xc7\x8d\xeb\xe7k\xd5\xa7\x94\x02pW\x90\x06\xdd\xc5\x0b\xb3\x18\xe4y\x1a^ns\xe6:\x9cv8\"\x85A3\xd9\x12\xc6\xfe\xe2\xce\xf6W\x0e\xf9\xb7n\xc9C:\x1f\xcc\xa2 \xcb8\x90\xb5\x86\xfa\x91\x06\xdf\x06\xb7w\xf9D\x0d\x840-\xdcZ\xdcQ\x9b\x89\x10\x8fW\xber\xc4\xd1j\x87\xbdB\x0c\x88\xe4\xd1J;\xb9\xca$\xac\x10q\x8c>\x95.\x01egJ\x19'\x08\xcf\xc94\xd5\x06}W\xe2\xcac'\xd6\xa5?\x15^\x02\x93\x16c\x164\xab\xd3\xf2Y\xec\xcc\x19\xa9\x16]\xff,3\x9c\x0c\xfa\xb0@/\xeb;\"x\xd9N\xb3\x94(\xa7\xa4<\xf7\xef\\\xdet\x8c>^\xfa\xf3\x11C\xbb\xa2\x94\x91\xf9\"\x83\xf4\xac\xc1\xe8af'\x16V\xf2\x07{!\xe9\x07\xa7^~t\xcb\xdea\x18\x9e\xd1\x18J-\xc5[\xad\xc1f\x13\xdd\x92\xa7 \x8c9\xac\x7f\xf8\x00\xae~\xa2\x1c\x9a\x0f\xa0;\xdd\xc9\x13\xc1\x1b\xe9\x94\xb2\xc8\xc9\xe7\x83sq\xc1\xb2\x1f\x93\xf96\xe2\x92^y_0}\xdbX\xcf\xc8\xa0\xeb\x99\x926m\xdc\xd8\xbd\xeb\x19\x02\xa8\xf0\x0f\x07\xd5\x0f\xa1\xf8pX\xfd\x10\x88\x0f\xf7\xaa\x1f\xb6\xe2\xc3\xfd\xea\x07L\xf6\xe0\x0e+o#,^MJ\x85'G\xbc\x15\x94&\xf1\x0f\xb2\x88\xb9\x87\x0f\x1fT\x1b^P\x94\x17\xcft1\xd3\x90\xf4Y?\x83f\x83b=E\x9c\xd5:\xac\xcb\x9b\xb1-\x97/A,2E\xbdX\xb1h\xc3\xd2l\x90lN\xe7\xe5\xe1\xb6;\x02\xaa\xd1\x0b\x7f:\x0b\xfe\x91\x9c(F\xe7\x89Lj6\xcf:\xa9\x9e\xf1JA\xb5\x92\x9b\x0f..0\xfd\xd9\x05\xc5\\\x1b\xfa\x18\x19R\x16\xf2<\x91#\x11K\x93{g\xe3\xc1D8\xc8\x93\xe52bg\xab\xe4:\xeeJK\xa4\xb0\x1f\x0e6i\xb2i9c\xcc\x85\xd3\xeem\xb2\xcd\x9fa\xdb-\x15b!\xb7-\x9b\x8b\x91\x97\x1cG8$\xd5\xd5\xcd\xab>\xc25;\xc3\x896\x17E\xad\x96s\xae\xd7,K\xa2+6?\xdb^\xe6)k<\x0f\xc53P\xcd?'@;\xf9@$\xc6\xa95\x84!KV\xc9\xb5;u\xd4\x0c2\x87\xec\xd9\xe7>\xec\xd9\x9c\x9a)u\xcfq\x10\xcfXt\xccE\xe2\xae[\x869j\x04\xbdo\xde\xae\xf4\xf64\x7f\xb9\xcdO\xe2\xe02b\xf31\xec\x85B\xa7\xac|\xb1\xb6b\xc8H\x03\xc5\xd8\xdf\xa4\x1c\x10v\x1a\xfb'\x80[\xb6a\xb3\x1d\x80m\x13\x98b\x8a\xea\x0fA\x1be,j\x10\x0c\x7f\xcbU\xe60\x84.\x1b\x7f!\xbf$F\xc9\xc11\x87ejs\xab\xa3M8\xb9a\xb3m\xde)q\"\xec2-F\xed\x9e\xc6\xaf\xd2d\x99\xb2,\x1b7&\xf2n\x18c\x1d\xfb\xba\x0e\xf6\x13\xa1\xe5\x8cEl\x96'\xe9\xaf\x00/]\x08\x13\x1f\xc2\xab _\xd9aK\xdd\x07\xc0\xac\xf6\x1b6\xab\x12\x15.\x9b\xfd\xe9\xcc\xf5\xe8\x12\xb1\xa9\xc4\xd4\xe1\x03Wt\xa6a\xf9\xcdt\xebW\xde\x82_\x0da\x7f\x85\x0d\xb0\x10\xf6\xf2\x1eX\nu\xdf\x06R\xd1\x9b\xb2\x00\xd6 \xc9\xc8>[\x13zZr\x8a\xfb\xa6;\x97\xb57\xca\x11\xc1\x87\xad&\x85\xf8\xc2\x07\x81OA\x7f;5\xcf\xe3=\xbb\x1d\x83\xb3\x0e6Hb\xde$\\\x8c\xce\x1c\xf34\x84\xe8\xdc\xd9]B\x1aJ\xf2A\xb2i\x07\x98\\\xc8)\x1d\x89A\"\xc4\xb4\x9c\xdc\x1d\xe3E\xb8\xcc\xbc\xb63w\n&?Of'7\x9b \xce\xc2\xa4\x834\xc2\x85G\xb6\xf9!\x8c\xdf\x87q\x8bX\xb4\xa5\xe2a\xb6\x89\x82\xdb\x97]\xa5\xa3L\xaf%R\xd9I\xff\x8f\xe6\x9a\x11\xa9\xb6\xdb\x0d\xd7\xa6\x10\xc6\xd7a\xfe#\xa2]\xcb\xeaa'OO\x16\x83\x1f\x83M\xab\xd2\xfe\xb3\xd0\xf4\x17x\x13\xfcOg^\x0b\x8b\x03T4\xc6p\xda\xdc,\x7f\xf2`\xd9\xe9\x86\x05\xa7\xdfV\xef]\xfd\xc9\xa4\xee\x91[\x14-\xfa.\xf4,\xc7\xc2\xdd\xf4g\xce6)\x9b\x059\x17\xf1OI\xf3-^9B]3\xf6\xa5\x15\xa3\xee\x9a\xccS\xf2!\x0e4\x86\xa4\xbdh\xa1\xa7t\xb8JQ\xd6UZTi\xa8\xaa\x8a-j\x19\x96\xaf\xdb \xc4\x82u\xb7X\xb4\xf7R\xd2/;\\\xf0SzU\x8b.\ne\x15\xaaE\xf6\x80\xbaN\xd9B\xf2AW\x81Z\xf4O\xb0\xe8\xc6-\xda(4\xe8\xc7-B\x12X\xd5\xfd\x16\xce\x0ff\x89\x96\x04b<\xd2\xa9}mo\xb0f\xd6\xd5\x9a\xebzB\x04P\xf7_\xd7\x1fa-\x89\xa4\x89V\xb8\xb5\x0b\x8f\"\xf7\xc7\xb6\xabb\n\x9c\xc7\xf0s\xf3\x8c\nm\xba\xcdh\xdf\x11<\xba\x82\xb4v\xb6-\x96P{\xd3\\\xb5tR)*\x97\xde\xb5U\xd7\x0eiUu\xed][uqD\xa7\xaa\x8a\xdf\xcd\xd5\xa4<5\x86\xcb\xf6\x82\x82\x95\x8f\xe1\xba\xbd\xac\xe2\xe3c\xb8h\x19y!$\x8c\xe1e{Y\xad\xe5W\xcd\xa5K\xf2\xd0\x18\x8e\xbb\x94\xd6Z?k.\xaf Och\xd9\x9d\x92\xe44\x86g\xcd\xa5u\xc1r\x0c'\x1d\n\xa3T9\x86\x9b\xe6\xa2\x8bx\x0co\xac%l\x87\xab\xb5\xb7\x1f\xcf=\xbfrO\xe4\xa3\x9b\x0d^mSfJ1\xb9\x92\xe4\x02-\x1d\xb5\xb3\xa9\x12s\xda\xab84\x16t\x00\xdd\xc7J\xdf*\xbc\xa4Z\xd5\xc4\x0c\xaa\xb2\x84\x8d\xf2k\xc6\x05\xcc\x15#&\x00\x13\xa0\\\x14\xbf7\xc7\xaf\xc8\xe6\xf8\x15\xd9\x1c\xbf\"\x9b\xe3Wds\xfc\x8al\x8e_\xfc\xc3Pw\x1a\x8a\xc8\xb9\xcb\x92k\xfa\xb7\xf6\xd9\x9a5\xfadi\xfeX&k\x8cv\\ip\xc7\xf2?\xd9\xe5Jx\x18bq\x992\xa7\x9a\xd6\xc8\xe8\xd4\xf8\x19\x07\xa7d\xa0Z\xb2\xfc\x07$t\x06)\xbe\xab}j\x17\xdbT\xbe\x83\xaa\x1c\x9b\x14\xdf\xc1l\x9b\xa6\\\xbch\x10t\xd1>\xe9\xc6\x98T\xbc\xd1y\x0d\xef\xe8\xb6\xceO\xab\x90Yd\x1dg5r\xa4O\xeb\xd7\xf0\"\x11\xdc\x03D\xf0\x19\xbcS\xe0|\x8d\xe7\xf5_;\xf0ug\xd2Z\x86\x00\x93@\xd5bg\xfc\xa4=T@a\xb3\xe6\xb6\xac\x06\xa3\xa50\\\xfb(\xcf\xa7\xcc88\xd3\x90\xed\x99\x18\x87Nwg>\xccj|\x84Z\xff\x171\x16\xcf\xfftb\x8c \x8b(\x15\xfa\xd5|a\xb0\x8b\xd3\xac\xba\xf0\xc3WL\x91_\x15_?\x82 \xe5 u3\x8fr\xe8\x0f\x1f\xc3\x0c\x9e@\xf6\x18f\xbd\x9e\x07\xd1tv\xae\xd7\x9c\xce\x0ca\x01\xc5R\xc6x\xe1\xd1\xe6\x9c\x8b\x18\xd8\xca-fA\x14 \x96\xc1|\x98\xf2\xba\xe72\xf4b\x84IZ\xc3\xc1,J\xb2N\xeeV\xc2\xc5J\xb7\xfd\xa11\xfc9G\x85\x10\x7f\xbbU\xffz 4\xc3\x8bZ5\xa6\xc77\xe3\xb7\xe0\\_\x96\xe4ub[\x1d\x0d\x9eqwcj\xba\x03;\xa4\xd3\x15\x96\xa6\x1d\x86\x10\xeeb\xf1\x0e\x84\xf1t\xf0\xec\xec\x8d\xbd\x14\xdfm\xed\x04-\x90)m\x1b\xcc`\x98\x0e\x15\xa1)\xd6\xc1\xa9\x81sS\x8aT\x87\xaf]f\xcb\xd0\xd0\xc6\x8a\xe7\xe1U\x8dT\xeb\x8f\xbaV5\x06g\x1e\x06Q\xb2\xecoo\xacWq\xbfH7\x97\xc1\xec\xfd\x1f\xea\xe57Z<9\xa5>^\xcf\xff\x8d\xfaZ\xb1`\xfe)\x9d\xad\x0e\x95\x1c\xe8<\xbb\n\xc2(\xb8\x8c\x18\xea\xfbI\x1a\xfe\"\\\xb8\x9a6\xfbr\x9b\xe7h\xe0\xb5\x0f8\xbf\xdd P\x89\x92\x9d&\x86\xfc\xa0\x8f\xd3k\xa8\x91\xc4\xba\xb9 \xeb\xec\xbc\x02\xd9\xd5\xb2q\xf4\xd7\xe1<_\x8d\xc19\x186\x0cd%\xa2;\xf0R;\x8f`\x9b\xd5e5\xfdY\xa5l1\x06\xe7+\x9c_\xc3 n\xa20~\xff}\xa9\xb0\x05y\x91\xe9~Y\x00\x9c%q\xce\xe2\xdc:\xfbh\x80|\xee\x8c\xfd\xcd\xf5\x06\xeb`S\xcaI\xdex\xfd\xb7\x85~\xce\xda\xcc\xb6\xc8~[\x0e?\x9e\x9d\xbdi=\xf0\x98\x17,\xc1\x1a\xb7D>e\x13X\xcb\x19\x96\xce\"[\x0f\x81*\xa6\xb8\x96\x93\xdb\x92\x91\xaf\xc5\x00\\1{\xd6\xdd\xa1\xe5c\xb3\xb4y\xf8\xd4\xbe}9%\n\xdf\xfeK_\x12\xcf\xbf\xf4\xa5\xff\xc5\xfa\x92\xe0|]4\xa6\xce\x97S\xf2\xeez@\\\xd7/\x06\x1a}|\x93\xa8\x83g\x9bI&\xafim\xe6\xd4\x15\xffR\xda\xccO,\x80\xac\xac\x8dy\xa4\x8b(\xd9\xedU\xb2\xd9n\x1c4,6+u{{\xbb)>\x89\xa8\x13\x14\xee\xce\xde \x0b\x7f\xb1D\x13\xf9\x92:\x10\xef\xb2\x7f\x9d\x06\x9b\xcd\xa7\x08\xbc\x1d\xe4U\xad\xb3\x04\x8e\xc0\xb9\xccc%\x113\x88\x92\xd9{6w`\\\xfd\xb0\x8d\xc5\xa7\xae\xf2\xaa\xf8\xb5\xf3\x14\xb2M\x10kR\xbb\x1c@\xa3\x98\xfe\xcf\"\xe5\xe2\x82\x7f\xa5\xad\xf1W\x1d\x96U\x13|\x1b\xea\x9bG\x8c\xf4\x14\xddkm#\x8f\x85u\xf8_\x92\x0d\xfcK\xb2\x81\x7fI6\xbf\xbddc\xbd7\xc0\x06Y\x9el8\xd4\x07\xcb\x80\xf8\xb0\x99\xff\xc8\xcb\x05\xd2z,:\xb1\x88&\xe8lop\xa9\xff\x9f(\x8e\x94\x1c\xd5?\x8dy\xef\xc6R9\n\x96\x85\x94\x8b\x0b\xceH5\x9am\xf8\xda\x81\x0b8A\x1a\x06\xfd(\xb8d\x91c\xea\x06h\x9c\xd6\x8e\xe4\xf7\x0e]}!>\xfeO\xc2\x93\xd9g\xf2\xe4\x86\xfa\xe6\x11\xff/\xb4\"\xcc8K\xad\xf1\xd4D|\xa9q\xe1PV11\xdb\x99\x89\x0bo\xc5\x87\x1a\x17\xce\xc4\x87\x1a\x17\x8e\xc4\x87\x12\x17\x9e\xc9\xc8G3\x11\xf9\xc8\xc4\x8fg\xbf=?^t\xe5\xc7\xb6\xb0EU*l\xe5\xb9W\"\xafz\x95\x98[}g\x92:\x0fl W$\x16+\x18$1\xa7\xcd\xc7\xab ^\xb6g0\x02\x8d\xcf\xb1A\x1c\xac-\xbaXP\\[\xab\xb0\xe8\xbf\x7fDL`&\xf4\xe3\xfc.\xc3\xbb\xee|H\x9d\x06S\x0fb\xc7\x1b\xa9\x1f\xdf*\x15\xca\x0d\xc8\xe3\xd7\xd2}\x94,M\x91tv\xe8\xbfY8\x08\xda\x14t\x8a\xab\xd0\xc9@B\xc1\x154\x93H\xcd\xe6\xdd\x1a\x80U@\x819\xa25 \x1d\x19\xe4 \xc9w\x96\x99\xc5b\xcd\\s:\xd3\xa0~\xec\xbe\xc3b\x9a7\xb3\xe3Y|P\x84\xfa\xe0\xbf,8\x0ee\xd9)3\xcaN\xc1?@vj6\xe2t1\xf6\xc4U\x00i\x83\xa5\xee\x87\xeeyW\x1bR\x88\x85\xbb\x9d\xd0\x07t\xd2\xcd\x91\xff4g\xeb\xa6\xabH[*Jy\xe0\xda\x8cO\x19\x15\xfe\x96d\xc8\x96\xa3\xf6\xa4do\xb2\x97\xa5\xc0\x19\x8b0\xcaY\xfaIH\xb7\xb77\xc3k?\x96(\xea\x80\xd8g\xef\x7fc\xee\xbfc\xe7r\xe5D\xd4]\xbc~\x94\xdfnXC\x8c\xd8\xa6\xc1\xcc\xbf\xcc`&;\x0c\xa6Q\x8f\xb0\xdd\xbf\xd8\xdd\x088K\xe2<\x08\x9b\x0e\xd9\xf7\xf66h\x95\xe4b\x87\xb5\xdfE\x92\xae\x1b;Nb\x8a\xf2\"o\xa5(6h\xebvS\xa6\xf6mI\x97Z\x16&\xe8t\xc2\xd9v\xba7[\xb1u\xd0z`\x18\xe3\xf2\xb6\xb4\xb5\xd3\xe9\xa6.\xc3\x8c\x81\x95d\x9a\xe6\x9a\x81vy\xad\xe5\xdeK\xf9\x08\xf5\x13\x8e.\x0bN\xea\x7fA\x00\xbd\xcc\xe3VK\xb5\x00P\x8e^\x0b\xfa\xf3\xc8:\x82\xack\xef\\e\xa6\xa3yi\xa3\xee\xac\xcdjR\x96m\xc8\xce\x0fX\xc6\xf1`\xfciC\x15\x1e!\x84H\x1d=B\xeaS*\x00\xc4\xba\xb8e\xeb\xf8'\x8d\xb5e\x0c|\x8b\xe7I\xdc\xe4\x97\xb1\x83\x97\x8as\x8cn\x1bh\n\x9bs\xa25o\x03 \x01\x94t\x18\xf0E 7\x9b%\x1b\xd6\x9f\xb3E\x83/\x87\xa5\x9bMq,q\xc6[\xc9 H\x19l36\x87<\x81e\x1a\xc49\x041\x04\x9bM\x14\x8a\x80\xd3\xf3p\xb1`)\x8bs\x88\xd8\x15\x8b2H\x16\x10\xccf,\xcbx\x95y\x90\x07\x90\xc4p\xc9VA\xb4\xe0\xdf\xf2\x15\x03\x16\xcfy\xa3\xe9\x00N\x82\xd9\n\x9e\xbd:\x85up\x0bs6\x8bx\x7fI\xcc Ia\x9d\xa4\x0cp2\xd9\xa0i\xf7\xf5Q\xf3\xa6R\xf6\xb7m\x98\xb2\x0c\xbbZ$Q\x94\\\x87\xf1R\xb6\x04Dg\x80b\xe1'1\xcb\xe06\xd9\xc25\x9f\x9a\x9ac\x9e\xc0\x19\xa5\xd1\x85\xb7\xa7\x03\x07\xe3\x03\xef\xc6\x81?\x8d\xfb~\xac\xbb\xd64J<\x9f\xcb\x91A2\x9f\x06%\xc5\xbe\xf0\xdb\xb6\xa6w`\x00\x92\xbd\xb5\x05\x8dA\x10oR\xa9\xda\x19\x04\xa7z\x9ft] \xeal\xa3\xa2\xe4b\xbf7\x1b\xd5\xef\xf2<\xc8\xa7?,\x96\xa8\x7f\xb6\x93\xa1\xffy\x17\xb6\xbe\xa8\xda\xdd\xa6T\x8b\xd0\xaaH\x0b\x9aUo2\x905\xeb\xdc\xbb9\xbaw\x93kC\xe5\xe3\xd1\x16\x1a(\xd8\xc1}^h\xdc\xc1&\xfc3\xbb\xe5\xc3hR\xa4#*|\x19d\xe1\xac\xad\xecL9\xd17+\xdb\xb9\xce\x9a\xcc\xda_v\x1db\x06\x93E\x13C\x9a\x05\x19\x031\x0fgl-\x06bh\xb6\x83\x8dV\xce\x02\x1d\xb5&\xe8\xae9AW\xed j\xfaJ\x87\xc8\x1c:+\xec\x10\xf9c'\x0d\x0dHF\x15\x1a\x9a=\x8d&4\xe8\xf6\xf2\xb9LY`9V\x05\xb5\xbf\x08z\x9f\xb1\xbd\xd1\xbf\xb6\xf7\xf7\xb9\xbd\x92U~\xf2\xcev\x928A\xedn\xf3\\|p\xde\xc6\xef\xe3\xe4:Vas4'nTB\xc1\xf1a\xd1\xf5v+t8\x0bo\x1b?\x8d\x1bz\xe0\xf4\x7f\xde\xae7V\x15\xcb\x90h\xe6\x7f\xf8 \xe8\xefR\xba\xfc\x97L\xf9\xbfD\xa6\xe4\x82V\xd2@HU\x1c\x00\xd7A;E\x93\xd0\x14\x17e\xd7,\xcb\x82%k*\x9d\x16\xa5\xb3d\x9b\xce\xac\x02\xd4\xe7\x92\x1e\xdd\xc6\x83\xb3\xb5\x85m\x05\xcc\xd3}\x1b1\x13\xe4\xea\xcfe0{\xbfL\x93m\xd4)\xd5\xe7\xfbm\x80\x1e\xf5\x07\x97\xe7\x1f\x16\x98\xbay\xa7\xa1t#\xaa\xc9\x95\x16t\x7f\xea;w\x8a\xd4\x10\x9c\xe0\xe14\x1c[z\x9c\xfa\x92\xdbX\xd8\xef\"\x94w\x1b\xdc\x83.(u0\xb2\x81\x12\x95\xba\x99\xc4@\x19\xe6\xda\xf7.\xc44\x8d\xcei\xbc\xd9\xe6m1v\x03*\xfb:\xb9n+\xb9\xa5\x92\xc7I\xa3\xb0\x08*\xff$\x1e\x19\x9fp\xc1\xac\xad\xfc\x8c\xca\xff\x18\xa4\xef\xe7\xc9ukX`\xcaB\xe9\xfc C\x9d\xbe\n\xf2U\x9bO\x0e\x08\x17\x96\\\x04W\x12\xa4\xa9\xb9\xc2\x1c Y\x10E8\x85\xcc\xf5v;\xf0\x92\x8fdo$\x11\xf3%9\x9d;\x1e\x9e\x7f}\xba\xe9\xa2\xdb9W\xcb\x19\xea\xean{\x99Y2g\xaaT\xa2\xe2\x04\xbb\x0e\x07B<\x07t\xfe\xff\xff\x0f\\2pz\x8e\xbd\xa5E\x9b\x11\x84\xa2#OU\x16\x19\xcd\xe7\xce\xf1!9\xb7V\xc6\xb4\xb6\x9bF\x87\x98\xd5}\xc3\xf5\xb2y\xd3\x19j\xd0\xb62\xad\xb7\xf4I\xf7\x19\xcb\xf5\x9a\xb3l\x96\x86\x9b\x1c\xa3^7\xcf\xe5\x93\xc7\xa4\x1f\xfc\n\xbd\xa8\xeb\xd6\x96w\xf5\x8b\x8d\xe24\xde}\x0ca\xfc\xd9#\xa0;\x13j\x14\x88\xeec\x07\xc1\xa4\xc1\xf1\xa04\x18\x07\xbe\xc1\x07\x1a\x9dB\xb6mC \xdb\xc0Dx\x8ep\xe5\xabE\xcd*L\x9e\xf2\x92\x06\xfel\x82%\xcf\x87yS\x98\x8a\xae\xde\x83\x9f\xe4g\"\x1fT\xcd[\x0f\xb2\xa1\xfd\xe4\x1d\xc0\xea\xefD\x9f:\x0b\x1a\xa6\x80\xa9\xa6\xc3\xec\xf2\x907m\x97\xd3u\xc1\xa2N\xbbK\xbb\xa67e\xdd\x85+\x91\xfa\x8e\x15\x97\xbcZN\xe3\xc8[6\x0f\xd2%\xcbi\xe3\xede\xe5\xdd\xb7\x8a\xbf<#\x91\xbcmg\x85\xc0ega6\xf6\xc5\no\xfd\x10\xd3L\x87\xadz\xfc\xbf|\n\x8a\xe7\x93\xac\xbe\xffd>\x05\xb0\x9bN\xde\xe9f)\x88\x9e\x7f\x83\xc4\xdc\x0b*\x186\x8cb\xdb%|\x05\xdf\xd1m\xab\xde\x11a\xa9f\x9d`&\xf3a\x0b\xc1w\xb0\xcdXj\xbfP#v\xbfK\xf6RR\xce\x1b4o\xa9\x9c7\xccS*\xe7p\xd4Bs\xe4\xa8m\x8a<\x7f>r\xf0\xb4\x9a\x19\x7f\xeb\x94\xa8\xffp=\xbf\x8bc\x06\x94\\HZ\x95\x0e\xbaM,\xf5\xfcX\xd3\xf39\xda\xd8\xd6\xbe\xbe\xf0\xffK\xb5\xfdv\xed}\x978\x93\xf0;\xd0\xf6\xa3O\xd3\xf6wS\xdf\x17\xbb\x99\x08\x0c\xda\xbe\"z\xedj\x7f\xf2\xab\xaa\xfduc\xa3\xfetP\xfb[N\xccH#\xb1GH,\xd4~\xe7\xdb \x0bg\xe5\xe8\x88\x8e\xbdj\xab\xce\xdb\xac\xc3\xa7]tx\xfb\xb0\xad:\xbc\xadJ\xd0\xb6\x14\xad6\x89O\xd7\xe1?yLU\xdd\xf5\xad\xe4yR}\xb5V\xac\xa8\xaf\x8e\x0f\x1b\xfc\x9f\xeb\xaf\x0d~e\xcd\xc3\xf9\x82\xfa\xabpC\x9f#q\xa7?[j\x10\xafw$\xde\xfe*\xfa\xf1\x17\xdb\xa8WA\x96]'\xe9|\xe7\x8d\xd2\xed\x0c\xbf\xde>\xed\xbe\xfa\xc16O8g\x8bX\xcew!f\xd7\xfd\x8d\x98c\xb7}\xebXZ@P\xc7\xd2\x9f\xb6\xcb_\xc4\n\xf2Y\xde{\xff$V\x10\xd3\x11yy\xc8\x8b\xdf\xbf\x15$\xd5\xac \xf6R \xda\xf7;\x18I\xd2\x16\x99\x8d\x1c\x9b)\xb5\x176gf\xe0\xc14<\xe7\xb2\x85\xaf\x9b@\x9a\xe4V\x94q\x03\xf3n\xa2\xe5\x84Y\xa3\x0b\x94w\xf5\x9f\xc9\xc7aa\x8d\x1b\xb2\xb0\xf98,l>\x0e\x0b\x9b\x8f\xc3\xc2\xe6\xe3\xb0\xb0\xf98,\xc8\xb2R\xfe\xc0\x05Yw!M,\xfc\x8fGw\x1fxf#\xcb\xe2\xb77\xb2l\xbe\xa4\x91\xe5\xf7\xe6\xf80\xff]:>\x04\x9d\x14\xee\x85*\xd9A\xc3\xe3\xbb8\xe3 B\x17\xf8\xb3\x06\xc5\x07\xa3\x98\x0c\x8a\x04d\xae\xd0\xc8\xed5\xae`Bb\xf7\x86$\\%j\xb5f\x16]Wj\xce\xa2\x90\xc5\xf9\xa9H&\xba\x1a\xc8\xdfm\xed,\x8d\xed\x9c\xb1Y\xca\xf2r[\xf4\xae\xad\xbd\xdbJ{R\xacx\x8379\xb0\xb6\xc8Q\xd8\xbfL\xe6\xb7\xceg\xbb\xa7\x04\x9b\x0d\x9d\xb5\xad\x06\xe2O\xfb\xe0\xbe\x84+\x0b]\xdb\x1c\xc3\xf4\xbc\x01\x14\xc5\xe27\xa6\xdb\xd4W\xb51\xb9favkH\xea(\xd7y\xdc\xb8;\xfan\x8c\xe1\xd6X\xee\x1f\xe0\x8e\xf3\xab\x18\x9b\x9a%\xbd\xaeaU@\x85Vi\xa3?\x00\xbbEV\x81]\xa3\xab\xc0\x8e\x11V@\xb0\xe1\xbc\x83\xcdkKS\xec\x96/\x05\x8a0+\x9d\x8c^\"\xa9I\x07\xa3\xd7\x82Jv0zm\xba\x86y\x01\xe9J\xb2\x83\x85lE\xe5w\xb3\x90]Q\xa5\xae\x16\xb25\x9e\x1b\x84\xd9\xcbgg\x87\xcd%9\x89^\xbb^-\xfe\xe01\xd7c1\xea ^o\xc7\x9f\xcd-\xdd\x16-\x11\xf59N\xd9\x9c\xc5y\x18D\x19\xb5T\\\xa4oi\xea\xff\xb2\xf7\xef\xebm\x1b\xc9\xa28\xfa\xffz\x8a\x12fN\x06\x1c\x93\xb0(\xdf\x99(>\x89-\xef8c\xc7\xde\x96\x9d\xcc\xda\x1ao} \xd0$\x11\x83\x00\x02\x80\x944\x89\xdfe?\xcbz\xb2\xdf\xd7\xd5\xdd\xb8\xf6\x0d\x94l\xcb\x19c\xd6r(\xa0\x80\xbeUW\xd7\xbd\xe6\x98\x04\x06I\xfc\"6/\xeci\x0d\x8eu*I\xc8\xe2\xf9\xd9\x91\xc0\x9f\x14\xfc\x96\xfeSg\x98)\xba\x9d\xb9\x07\xdf\xf7\x0d/\x1e\xa1\x15\xe6Cj\x16\xe5\xc2\x82\xb8t9u\x80W\xc5\xdf;\xbaT\xa7\x9c\xad\x1fG![\xbff\x88\xbf\x08\x040\xf4\x0fsC\xe8;y\\/dK\x1dgT\x9a^\x99\xaf\x94?\x06\x07\xdc\x17\xdfm\xca\xd5\xc1\x18\xe8\xed\x16\x1a\x823\xd2\xb9\xbc\xacL\xca\x02\xbd\x0e\xd57\xe8P\xcb\xba\xca4\xe7Ft\x1e/\xab;\x0d\x9dj\xbd\xf5\xd0g\xa7\xff\xa5J\x9b\xc8\xde8\xd6\xb9\\mM\xc3\x14\xaaU\xd9Zj\x868\x86\xb3\x1d=\xbd\\'Z\xd3\x11F%\xc3\xcc9\xdd\xf8s\xfc\xb9\x1ci\xbf\x99\xf5?\xc9R}\xbcy\xf5l\x80{SRo\xd8\xea\x13o\xf2\x98\xe5F\xa9\x19\xd5~\xef\xea\x9f\x17\xd6\x1d}\x9d\xbe#\xac\x83\xd6\xfds\x1a\xb8\\\xd2\xd7\xab\xcei\x1b\xd4/s3F\x077\x88zm\xc7\xe0<\x89\xd3\xb3\xe13\xca6\x1e\xfa\"\xd6\x93\xb8\x87\x93\xf8\x10!5\x0e\\\x81i\xe7\x1b\x01*=\xb0~\"V\xe5:~\x82AB\x98\x01\xe5\xb4\x92\xb4\xb4\x13\xb2ij\xff\xcf\x068\xaf\xb57pe\xf9\x12;X\xf5\x19\xa3E\xa4\xf4\xe71\x15\x17\xa6\x9a\xf8y@UE\xf1\xaeL3\n\xa8\x1b\xa0r8\x11\xf2u\xa6\xdeDa\x7f>\x0dl\xb7\xb5\xb9\xc2 \xfd\xd2\x9f\xe0'/a\x83@\xfe\xd4JE\xfd\xb1\x11\xb0\xda*Z\x04\xcc\x9aV\x8d!\x08h\xe3=\xf9\xf9b\x9b\xa5\xb1b\x98i\xa3\x8dq\x96/}\x16\x18'\xc6r\x8a\xf94\xb4\x08\x87S6\x14\xd9\xda\xd4\xae\xa9d\xf8|(^\x81r\xafqR\x11 \xdb\xf3\xb9\x0bV\xbd6\xbf\xb8\x1bfiF\x98f\xdc\xbf@?B\xaeoi\xab\xe9\xb48\xf3\x8aA\x02B\xea\xf8\x95\x81=`i=\xb4M\xd7\x0e\x14W\xd9\xf0o\x1b\x92\x1b\xc6\xfc\xbf)\x08d~\xee\xafII\xf2\x02}\xe6)#\xc99E\xd4t\xaa9^|\xdce9\xbf\xfaJ\x8c\x19\xd9'\xc5\x96B\x1e\xd4\xdd;\xa3\x9f@f\xbc\x01'\x14\x8fZ>\xf5\xea\xe9\x0bk\xf642\x1cf\x15\xd8`\x02\xf3g=\xcd\xea\x89\xb3:\xc8,\xd8\xa6\x86\x9fA\x07\xbd\x0c\xda+\x86\xfa\x12\\\x1aB\xde*+\xc4\x87 m\xbd\xfduE{\xe9\xa3\xef\x93\x82YWl\xf6\n\x03\xfd\xb2_\xda\xfb\x85O\xe0n\x18\xcd,.W\xb5\xdfd\xf8\x7fl\xd3\xbdK\xec\x81=$\xfb\xa7\xf8\x8fe:W{-\x01W\xc2\xee\xb4\x92\x98\x9d\x9d\xe3 \xd3\xef\"\xe6\x9e\x0e\xcb^\x0df\xa5\xa1\xd1\x13\x12\xacS:]j\xe2\xa03y\xc1\x8a\x04\xef\xe6\xa9\xa2 \xb8\xb84\xadZEt1\x9cc^\xdfV\xe9\xc3\xe8\xdea9\xa2\x1c\xb8\x01s\xfc%\xba\x8a\xb7\x84\xfb\x8c\xd9PD\xaf0*(i\x08gpf\x06\xe6[\xa9\x9a\x19\xf3\x1b\xf5\xce ^\x9a \x1e\x19\xb6\x05p\xdd\xe4% 54\x89\xb5\xf5|\xed\xba\xd4\"\x9d\x8a\xb9OM\x0c\x8bJ]~\x170M\xc4.H\x8dTp\xe7Q\x9au\x94\xd0iO\xaf\x96\x03\xd6^r9\xbd(t\xdal\xea\xbfMM\x97\xf2\xb2\xd4\x15\x84$\xb5\xef\x18\x8e\xae\xc2\x03R5\xe0\xd0f\xb8\x1f\xcf\x03\xf2\x92\xf87<\xeb=\xb0\x859G\xc9H\xc7'eC\xda\xd6&\x887\x1e\xee\xbd\x0c\xf8\xba\x9e\xdb$\xc0\xff4}\xaf\xde\xd2v\xbf\x91\x15_\xb3\xfa\x97\x1d\x81Ej|\x18\x90\x1e\x1fx\xe7\xab\x14\xf9R(K\xc7\xddz\xcc*\xc7\xdd\xf0\n\x1cw{\xe5\x95\x94\x94\xa3\x94\x94W\"\xbb\x97Wj\xe3\x82i$\xc0GS\xd6n\xc3\xea%\x1b\\\x04\x8b\xe4\xb9\x112\xad\x1dq\xd0\x15O\x0d\x19\x0dq\xc1\xf1\xe1\x10R]\xe2\x92\x8d\x88\xf4\xac\\\x00\x15\x0en^\x10\x13?\xd7\xf8\x1f3\xc7\x82\x19\xe8Y2\xce]\xf9\xfa\x82\x1c\xc2\xd8\xcb\xe0\xe4h\xce\xbd\xb6\x02\x81\xc7#C\xdffU\xa4\xba\x16\x8c\xaf\x94\x96M\xad\x17T\x9b{6`S\xaa\xcd\x7fK\x9b|$\xe06\x8a\x91*\x11\xbc\xc5mZm3\xe1\x1covw\xcf\xd1q\x02\xb9H\x9doj\x8a`\x94\xc1/D\n\x019\x06E\x0bp\xb1\xcc\xf4d\xca==\x18K\xca\xcbJDIH\xce_,\xdctd\xf2\x97\x8b\xa0\xf72\xaf\xa0{\x92\xbe\xd5\xf8uXy\xd1C\xc3crx\x15\x1d qA`/g\x1e\xda\x8a\xf1\xc1\xb7t\n\x18\x84\xb9C\xa23\x9d\xcf\x0dv\xba\xa9\x9c\xc7\xf7\xb4\x89\x84\x94\xf5\x8148\xd8P\x04\\1\x0e\xb6\x91KOY0\xaa\xd5\x14\x9e\xe1\xcbsX\xa4cPE\xdf7\x16\xc9WO\x02\xe3\x98\xacF\xdf?\xe8\xd4\x1e\xe9\x89\xcdy\xc46\xaa\xd5y\xc4\xe6\xd3\xe6_\xfb\xe7\xca\xbf\xbe\xf2\xb2M\xb1r\x9d\x9c\x14Y\x9a\x14\x04\xed\xca\x87\xa8\xd3WP3E\xde|\xd6^ev\x1c\xd2\x1a\xba\x9c\xed\xd4\\\xdf\x95\xf8C\xcca\xcf\xf3y\xc8\xe0\xd8T\xb6^hS0\x87R\xa0d\xe9\xc0\xe1!\x92\xd1t\xc1\xa2X\xc4\xe7*C\xdd!\xaa\xff\x12\xfa\xc17\xaf\x9eV\xb2\x9e\x9bu\x03\xa5(A\xd9b.\x03Vr\xeb\x15 \xa3\x9c\x04\xe5\x9bZ\x9f\xd1\x13\xe8t\x0c+\xfe\xd1\xaf\x9c\xd1[\xf6\x93\x8bS\xa7\x95\x84\xe1\x8b\"9\xa6@\xb09\x8b\xe5\xd4\x19\x89\xba\x06\xa2y\x99Lp\xee \xcd\xe6q\x1a\xbc\xc3\x12\xeey\x1a\x9f\x9e\xceK]\x08c\xdbF\xc4\xff\x92B3\x0b\x11\xf1sI\\\x94\xb1\xde\x89\xa9\xce\xc9\xf5\xcc\xa1\x8aD_\x9a\x03\xe4Z\xd69\x19\xb3\x1f\x07X\x15\xd9\xbd\xf7y\x9c\x05\xd0\xd29\xad\x88\x1f\x92\\b\xf53\xed\x19\xbb\xe0\xc9F\x98\xa1\xa0=\xc0\x9b\xd4\x17\xb2\xce\x1b\xd9\xc1\xbb\x12L{\x81\xcc\xc9N\xea\xd1\x86\\d\xfc(\xc3e\xae\xe9\xa2I\xfb\xe1\x8e\xc1\x81u\xe1\xe8G\x1d\x1aGm8\xf3\xa1M\xa0%Y^\xc6;gr\xb1\xa9\xa7\x06=*\x06W\x9c\xdb\xa1X\xa5\x9b8\xac\x08\xe1\x9b,\xf4K\xdb|\xac6\x15\xcd\xeb$\x0e\x9e\xd0\xf9\xa0tI\xea?\xff\xf8\xa3 E\x0fq\x0e\x81?\xdbO\xd9\xf1\xcd\x9f\xf3?\xda\x10aTd\xb1\x7f\xc11\xeb\xb1P\x7f\xb07\xe4\x0f\xa5c\xf8\xdcR\xb2\x8a\xe9\xd4\xc3\x0eM\xca\x9a\xd6\xf0\x06C=T\xd5\x8e\xe5\x93\xac\x7f\xd3\xafx=\x0b3?T\xcax=\xc7\x07\xfc\xc8\x12\x98\xa2\x87\x0c\x98\xf3\x00\xba\\<\xdfPi8\x14\xe4\xe9!\xf8\xde\xbau\xebI\x9a\xbb\x9b1\x14#\x98\x81\xef\xe5\x9d\x9b\xfa\x86B\xa8\n(S\xa1{cL\xa9\xb0\xa2\xa7+\xcf@$\xd7\x974\xafm\xfd\xf9\xea\x10\xf1\xca\xf4\xc7cSE\x97u\xfdb\x92\x96\x8f\xd3\x00I\x12\x86\x87k\xdf[\xd6\xef\x11\x9b\xf4\x1d\x175<\xfa.\x1a\xc0\xe75x\xe3\x98\xd0\xber\xda\xb7{n-\xd2VlO\x1c\xca\x9f\x92\xa4\x9c`\xe4\xd8[JZ\xb6'\xce#~\x13\xa3\xc24y\x85\x80\xeb\x94\x12\xd7 ,\x16\xea\x9c\x81\x8a\x8d\xfb=\x0b\xcf\xd2\xber\x0c\x87]wm\xa3)\x1c,\x0enk_W\xe8p\xf9\x0c\xc3\xe2\xc8\xe8\xf5%.\xa4\x95z\xa7\\\xe0l=8\x98\xe3\xcc\xc1\x90\xf7\xed y\xcb\xa2\x15\xb5\xef\x9a\x92x<\xa2\xe24\x1e\x06\xc7\\\xe0\x96\x8b\x82`1iMn'\xd0E\xaa\x1c\x99f\x96\xd3\x0fm\xe2\xf6\xd1\x18V\xda\xf4\x06v\xcc\xd7\xed>\xf3\xf5\xe6\xd53-\xdf5\xd4)TD&\xd2-\xa0\x1e\x8f%\xa3\xb7\xd2\xa7Xh\x8e\xe7\x98\xe4[\x92\x83\xd8O\xda1a\xf0\xcc\xc0Q\xb1\xcf\x16\x13\xf6\xeeN#+\xe9~1\xafR\x99\xef\xd85\xb6\x1dw\xec[8\xa8\xd1 \x8d!H\xe3S\xd6d5\xeb\x13z\x8f\x1fk\xban8h$\xd4.\xd1\xd5\xf5\xc7\xca}\x9cv\xea1)\xfd(.\x0cy=J\x8c\xa4\xfdP\xab\xf8\xd1Vo\xe8\x92\x85cX_e(S\xd5\xfe& kfc\xa7\xd1G\x8d\xe0\xba7\x8d\xaf\x81S\xf9\xf8_1\xaa\xed\x84_K\xdd\xf4\xb5\xca\xf7\xb6\n\x8e\xc1\x0d<\x04\xe1\x86\xb8]\x95\x99\xae\x03\x18.4\x9f>7\x0e\x8e183\xb80\xb0\xc8\x0c\x8e\xa5'4\x04\x17m\xf2x\x06\x06\xe6\x9c\xf3\xa7\xda\xcc\x89\xf4j\xca+\xba\x98\xb1\xf7\xf5|<\xd2\xcc\x871\xb4\xb2\xea\xd7\xb1MS\x11=\x96\xe7\x97 k\x10|\xed\x0c\xe6\xe6\x06\xd5\xe1-\x97\xf0\x85\x97\xeb?C\xbc{\xdd\xf4\x9f+\xa5\xfe\x13\x9f\xf4\xb4\x96\x91x\"S\x80\xaed\x9a\xd1\x0d\x7f\xd0\xd3\x8c\x16\xfcA\xaf\x8d\x98?\xe8iF\x03\xfe\xa0\x97\x1dy!\x1a\xdf\x7f\xd0}\x94Q\xf1e%\xb4\xa7h}\xec@\x84\xa2\x83\x8a\x9aU\xab\x8f\xafO\xdd\xda\xda\xd6T\xa9\x94\xa5&*\x99\xfd\xac\x99B\xb9\xb0Q\xbcEm\xc5\x9bE\ne\xac\xd0\\\xc7]\xbc\xc9\xe3!\x96-\x9eU\xb9\xad\xce\x90\xcb\x19\xc2LG\xce`!z\xe9\x12o\x93\xc7.\xe6\xe5\x17;5N\x99\xa3\x00\x95\xe4\x99;\x87+\xd1\x14\xca\xe7*\xe5s\xd5\xd4\xe3\x8c\xdc\x91\xc7\x1d\x8f\xd2\xbc\xe7\xf3\x04`\x9d\xe3\x17\xc9|\x7f\xbaT\xba\x86f\x9b\xb3\xa6\xabd\n\x0f\xc1Y\x95eV\xccn\xdeL\x13*Q\n\xbf\x06/JoV\xef9 \xab\xaa\xd7K\x8a\xab\xb4\xb1\xc5\x0d\\\xa8\x15\xa6m\xcb\x9b\xd2\xc6\x16\x08z\xf9K\x14\xc7\xafH@\xa2-\xd2\xb6\xc2\xc2\xec\xa6\x94\xd3\x85\xe2}\xf8\x12\x81\x88;\xb2p\xac\xc7uB`\xdb\xa5\x02\xddr\x95\x03\x96K\x1eZ'\xf3\xb1o/\xa1\xec\xd4\xbc\"[\xa7\xd8\xa9t\xce\x1b\xba\xe3\xf6\xe4\xd3\xed\xab\x9e\x1a\xb1d\x99W\xf8t.\xffM\xde\xe41\xa3Bu\xb1\x83j\xf2TqF^\xb0\xc9s\x92\x94OXj\x08s\x85\x93-%I{\xcc\xf9\x03\x7f\xbb\x1b,4\x97f\x05\xff\xc6f\x0c\x18\x9f\x88~\x16{Q\xf1\x93\xff\x93\xbbB\xfd\xca\x8a)0\xc4K\x1b\xaf\x88\xa3\x80\xd0M\xb2\xd2U\xc9m\xf9dlzy\xc5|\x13\x9fDw\xc3F \x87\xeb\xa4\xd5:\xea\n\xba@=dU\xbf\xac\x12\x92\xb1\x9d]\xb5\x89\x89\xf5\x0c\xf5\xb5\x00\xb5 \xcb\x17\xf3_\xad\x12\x99\x95\xfeR\x9b-F\\\x9d\xdd\xa7\xcdB\xd3~\xa7\xca[\x93\x9a\xdf\xa8\xf7\x9f6\x8bC\x0b\xdc\xc2& \x8c\xe7\xe8\xae\xbei\xe9\xa1!,\xf0\xe5\xcf|L\xa3m|\x0d*\xb2\xc5\x8d\xc5\xe5*5:\xf1\x89+\xc5@M\x816\xcf\xa2\x82\x9e\x8b\xb4ez\x98&c\xc8u9g\xc4\xc5\xd1\x8f\xc7j\xba%\xaf\xa3\x85\xa5\xad2\x98\xc1bTi \xf3Q\xad\x16\xdc\xb9\xb0\xba\xb8XJ\xd1*3\xa4\x05\x9a\xd0\x8b\x9e\x1e/\xb1\xac\x90\x05\x96\xd0+\xcd\xac\xd0\x1b\xaarE\x169@\x01\x83\xb9\xe9JY\xa17T\xdb\xc7\x08\xaa\x91\x8c\xd8\xe3F>D%d\x13\x8a\"3\xa6\xb5\xfd\x06\xa6\xbaB\xde\xab[\x0d\xaf\x8c\x9fR\xa8\xc9\x17p\x856D \xce\xfe^]8\xe9R\x96mYy\xe6\xcf\xc9\xb2-\xad\xe1\x9b\xaaj\xf8F\xaa\x1a\xbe\xbe\xaa\x86\xefFU\xc3\xb7P\xd5\xf0\x8d{5|Y \xcf\x82K\x05m\xe8@\x04\xcb~\x16%~\x0d\\\xfb\xa7\xe4\xd8\xafi\x88\xe0\x10\xee\x9cq\xe6\x8c\x1bPC%\x02J\x0d\xc2\x8e\xb2`\x15\xc5aN4\x944\x1d\xc6\xa9GC\xb8t\xdf\x9aC\xdf\x0c\x90/\xb0p\xb2\x8e%_\xb0\xc38\x0d\x8e\xce3?)\xb4Q\x14\x19?\xb8I\xf6,J\xdeE\x89fFCQ\x04\xd8Y\xf8qAX\n\xfeL\x0dO\xb9\xf4\x0d\x96\xfd\x8c\xfd\x0c\x1dk\x95\xa0[\x06jSes\xcd@\x1f\xf3\x1e\xeb@\x97\x0c\xd4\x04V\x05\x164\xa1\x1aJ1\x9cb\xab\xb7\x15\xb5r\xc8\xe7yz\xa6\x19\xdcY\x14R\xd2\xe0\x1c\xec\xeb\xbccH\xb4\\\x95\x0cjpo7\x85>\x14\x88\xed\x08\\\xab\xbf\xc4\x14\xcf&\xd8\xe7 r8t\xa9\x9aw5\x9d<\x8f\xa3\xe4\xdd\x0f\x83>\xa6\"6:\xad\xa3\xb6\x86rT\xbc\xc8HB \xf6\x91j\x9er\xa3\xf9@\x92JC'xg\xe2)\x1a\xe6{\xce'BcX\xab\x9d\x16y\xba\xfe\xf1\xd8\xfd\xbd\x1b\xcd\x87\x1a\x0f\xa7\x9e\x94\xf7\xe3k\x97\xd0\xb4/\xd4g*\xa1>S \xf5\x99J\xa8\xcfTB}6,GS\xe6vc\x94\xa9\xe4\xeef:\x97\xf3\x05~\xed^sY\xb96@&\xecg\x1f_\xd8\xd7\x9b\xe9\xbe\x08\xfb\xe2\xfap\xc2\xbeP\xa4\xaa\xe1r\xcbT\x05)\x87\xc3@R\x0dc\xc9\xb4\x07\xe9r\x19\x13d1\xd5\xa0L\x82O\x93\xd79\x15\xf8\xf1\xb8T\x03o8\xf0#? Hl\x00.8\xf0\xd19 6\xba|\xfb\x0b\xa3\xe1.\x1b\xa0<\x08\xadU\x12\xabjq\x8cz\x8e\xed\x10s\xea\x1a\x81\xad2q/+P\x8b\xef^\xb0 \xf5\x8b[\xc6\xef\xce+P\x8b\xef\x9e\xb6\xdd\xce*\xc6J\xc3z`\xb8\xbd)w\x02\x15\x9f\xcf\xbc\x90d9 \xfcRW=\xe0\x1c!\xb98\xa4\x06;F0}n\x8bG\x08c\xcak\xf1\x0e\xa1R\x8dn\xe7;\x84\xd0*\xe0^\xf0\x8f\xf0\xe9\xd2\x95\x9c|\x89\xa0~\x1c\xa7g\xaf\xf3\x8b\xa7\xe5\x8b\x8d\x06\x83_\xb3y\x1b\x98-\xe49\xeb0\xff\xfa\x11\x13?\xd5\xe0O\x11\x9c\xb0\xbd\xf94y\x99\xa7\xcb\x9c\x14\x1a,\xf9\x15\x0e\xe1\x9d\xd7P\xea\xa8A\x7fB\xd0\xa6\xeeF\x0d\xfb\na1\xdd\xb7,\xa3\xb7\xb8\x1e#\xc6 %Q\x9ai\xb5@\xcf\xe0\x10\x1e3#_\x15\x02\xae\xd3\x8f\xbd\xa9\xe1\xb3<\x0d7\x81\x1e\xfc7\xee\x8f\x8c\xa9G\x9eEE9r\x1f\x8f\xe1\xc4iT\xd5\xd5\xf5\xee \x1c\xc2\xb6F\x9bc\x1c\xba{<\x86G\x9a\x97\xfe\xddQl9c\xf8n\x0c/4\xca\xab\xef\x9b\xbd<:/ \xeaI\x8b\x91\xfbX\xd3\xcc\xcf\xc8\x04\xd9\xcd\xda\x0f\x0c\xb6YKX\x0d\xfc\x0b\x03\xe6\xf8\xa6\x83\xfc\x91A\x06,w\x9d\x1a\xee\xbf\x19\x9c\x8d\xf2\xf5\x1f\x0c\xd4F\xf9\xfa\xbf\x18(\xc7G\x1d\xe4_\x19d\xe5\xd5\xc1\xb2,h_\xf9?\x9dW\x8e\xf4I^\xfe\xd9ma\xb3^\xfb\xb96\x17\xca\xfff\xaf\x98\x14\xc2\x84\xf2/!\xcf\xe9S\xe3\x86\xda\xa5\xf7\x19f\x8fe)d\xd1\xc4\xf9-\xec\x9b\xdc\x95\xd0\x9d~\xef\x19\xee+\x1e\x9a\x97{\xad\xec>,F\x87\x838\x9c{\xd3\xb9p\xe4\xe8\xe0R\xf43\xf1\x8c\xa1$\xb6\x16R\x10\x1e\x04\xb4\x7f't\xdfI\xd2\x84\x02\xd8\xe69\xb1\x12\xe6\x9b\xaa\xdb*\xe7c}2R\xf9\xf6\\\x06\xe2\xc0\x0dx\x047\xc0\x91\xe9x\xdbP\xea\xd5\x8e\xc2\x99F\x03\xfe\xefZ\x01\xaa\xd4\x80\xaa\xa6\xe0\x9fZ-\xb1\xc0[\x94ngp\xaa\xeea\x83S\xd5\xfa\x98\xb4}K4\xa7w\xab\x84\xd3Z\x0f\xd7\xf0\x9f\xd1\x1c\xf6\xb53\x84\xca!W=M\xffm\xa7x8\x1f:\xfdC0\xb0R\x8d\xab\xeb\xe2\xbf\x1f\xc3c\xba!\x1f\xb3-\xfe\xc7\x1f\xcc\xff\xe4\xf0\xf0\x10\x1e\xd7\xce(\xea\\\x13\x06?\xe8J\x15u\xeb \xd3\xd5S\x15z-\x03\x18\xbaU'\xee\xed\xe9TC\xe8d\x13\x10\xa7~\x18%\xcb\x89\x9fDk_c\x1f\x19\x8d\xe1H\x9bX\xc8`%\x91\xb5\x8d\xea\xcd\xd3$\xcd\xd7\xbe\"\x07\x10&x\xfa\xc5\xcf\x93(Y\xce\xe0qM\"Fc\xf8\xd5\"\xcf\xd1\xb0\xfe4\xd89}\xa9\xca\xab\xc6Bcf\x10M\x83\xff\xb01G\xfc\xaaX\xd4\xd1h\x0c?\xd1y\xfc \xc3=/\x91\xb6E6,\xc1\xf3N\xc24(v\x9f\xd1\x0f\x86YO\xa2$\x84u\x9a\x13\x08EF\x9f+^\xd8\xd6\x0c\x0c\x1f\xb91\xd0\xd5\xd8\xe6\xa99\xeb\xcceq\xeb\xa7\xa6\x18\xa4\xc23u\x1b\xff[\xd7\x86}\xb0\xac\xc5L\xc4\x91\xf6\x0bJ\x8b\xd6O\xda\xe8X\xf6\xb4\x91c\xa7yj\xa87\xd4\x0f\xbaa\xd7R\xc4\x0c~\xb3:\x85yA\x10;\xf1\xa3\xe2Ef\xf0X\x03\xc5+x\xff\x03\xdd%uj\xb8\xa6\xbaL\xeb\xaa\xdb\xd2\x95I\xeb]\x89\xab#\xb9\xcf\xe0\xb9\x86mi*\x12f\xf0R\x0d\xb9H\xa4Ev\xc4e\xcdP5\xb4d\xda\xecE-\x15\x996\x7fQ\xe6\x97\xab\xe7\xdc\xb1\x93q\xe1\x86nr\x17\xe4P\xb1\xe1*l|\xae\xc1\xc1\xbf\xeap\xd0z2\x98M\xfeX\x0d \x1cV5Ly\xda\x91\x1bgB\x03Q\x98\xe5H\xda~\xf5\xda\x16\x15b\x85;\x12\xda\x91\xe31T\x1f\xd1\xe9!\x96\x84\xbb\x83\x91\x90}l\x06s\xafh\xdd\xd1\xacs\xff\xe5\x0b\xafw\xd3\xf0>\x05\xf9\xd9\xcf#\x8a\xf0?3\xed;\xffH\xef\x89a\x18Mx6\x8ca_8Z,HPF[\">\x85\x9d\x11\xdf\xa9\x9e\xe2}3\xfe}\xf5\x15\xbc\xa4\xff\xbc\xc2\x7fLtq\xa7cV((T4Z\xd5\xd8\xff\xd2\x9eo\xec\xa33x\xf5aq\xdf\x96\x98\xf0H\x16\xa6!\x9b\xc1\x13\xc5\xcc\xd7S\x7f\x15S\xfc\xbcRu\xbc\xa4\x12\xf9\xbcL&\xcb<\xddd(ys\xfd\x95\x91\xb3{.\xdeW\xf5\xe8\x17+\xc9Y{Z\xd9\xce\xe20\x92|\xd9\xb5\xad\xec=3(\xacvJn\x9a\xaa\x1f\xb5(k9 \xf6C\xd3wz4\x86\xa7W\xb5\x97\x85 \x1aT\xc1dCw\xf3.\xcd)]'\xaaey\xa6\x19\xe0\xcf\xba\xd6*\xb5\xf1\x0c\x9e\xa9g\xbaJ\xea\xab\x89*\x11\xcc\x90(\xfb\xa0\x8d\xfd\xb0>\xb7[l\xc4Ul\x98\x86-N\x9b#\xd2\x1aK\xb9\xf5a\x06o\xcc@\xfc\x90\xda\x8a\x80\xbf\x97\xfc\xfe\x934w\x19C\xa59\xfc\xfb\x8c\xb4\x95\xce\xdf~\x1b\xa9A\xe4\x86\xad\x19\xbcV\xbf\x82\\\xac\x89\x9a\x10\xf4\xa0\xf8\xdet\xdc\xfe\x1f\x1d\x06\x93J\x17>\x83\xef\xad1\xce@2vq\x1bz\xb9\xc9\x89\xcce\xa8\xca|'w\x19j\x9c\x1c8)\xad\x87y\xb5\x99d\xcf\xf8\xa6\xec?\xaaQ\x85J\x8a\x0b\x8fY\xbc\xba>5\xcc6\xa1\xf3B\xfa\x12Z\xd4\x9e1\xa5\x17\xd2B\xee\x85\xb4\xa8\xbd\x90\xee5S\x19-4\xeeF_b\x8b\xfe\x03\xdd\x8d\xac\xfc~\x86\xc4\xfb\xe7\xf6\x0e-\xe9\x10\x87\x16\xe6\xa6\xd4\xb6\x13\xa9\xa1}K_\xaa\x0d\xd6\xd039\xa7\x14,\\\x9d\x91-5X\x80`QQ\x95=\xd5\xf0\x0d\x0b\x845\xb9\x9ed\x08\xa5s= Y\xd7V\xe9\xd9\xb1\xa9{+\xfe1\x0b\x17\x94-\x03\xcd\xa3e\x94\xf8\xf1\x0b\x9bW0\x12I8\xa2X\xbd\xb1\x84C\xc8\xcc\xb3z\x81K\xc4\xd5\x1d\xc1&\x8fJ\xadU{\xce\x12(Tu`\xab\xae|_j\x8d\xf9\xa7\x9d\xc4\x0b|:\x9f\x1b\x03\xbf\xcf\xe4/\xbe4\x04\x9a\xf3\x1a'?n\xd6\xd9\xeb\x14\x811;\xc4\x07\xb7.\xd7Z\x01\xd6O\xe8\xfc\x8d\x06b\x8d\x16\xb0\xae*(\x05\xd1\x08 \xa7\xba\x1e\n^P\xc5\xb9\xa9?{f\xaf\xa6\xd3\x05>v\x0c\xd0\x1a\xc3r\xcd\xe3\xc8\xe3\xc6ig\xc3\xab\x92\xfb\xba\xabcc\xafX\xd2\x83\xad\xa8\x99],\x8a\xedn\xe9\xdd\xd5\xc8\"{\xfen=\xab\x93\\D\x8a\x02\x04\xef\xc7 :Qg\xdc\xff\xea+\xb8\xf0\x82t\x93\x94\xae\xaeos\xbdY\xbc&\xb93\xd0d\xcc\x1a\x1e\xe3!N\xd4\x941\x94\x98\xef\x97JMT\"\x89r\xec[\xe1^\x982\x89 \x81\xae\x13\x06\x17\xae\xc2\x01\x05z\xacEu\xd7\xac\xb8\xd2V\xc8\xc9\xb4\x08{\x85B\x87!N\xa1\xbb\xcfL\"D\xb0\xb3\x08q=\x03\x19>i\xa6\xb2\x01\xc5\xa6?\xa32\xa3_\xc4\x04q\xed.&hK:\x9b\xb8\x8fK\x1d\x1b<\xb3\x8e\xf4\xdd\xf7c\x94P\xded\x19\xc9\x1f\xf9\x05\x91%W\xd9\x99P-\x86\x13\xaa\xfa\xbb\xe3\xcf\xa0\xc4\xf1g\xaa\xad\x10\x91S_\x94\x16\xff\xb1\xd4H\xcd\xc0\x95\x034\x11\x89Dc`\x14\xf5\xe9\xc6I\xac\xe2PR\x844\xc6\xa1D\x08\xa6\x8fC\xf1\x11F\x1b?\x82u\xf1\xed\x84\xf7\x82w\xecq\x9d\xc6\xc4\x18\xe1AO\xd8\xb2\x99G\xe4\xc3\x9f\x04y3'\x838\x0d\xe8<\x9d\x9e\xb6\x9d\x9d\xa5@\x83\xcd_\xdazUU\x02\x06\x9d\x02J$`\xd0\x98\xa2\xb2\x06\xdf\xca\x9ao\xfbO\xfbXy\x80J\xd8\x1b\x0d\x0e\xb2,\x0d\x91|\x84Wy\x04^7v\x99\x9e\xaa\xcd\x80\x078\xe4\xe5R\xfa\x87[D\xcf\x84\xfb\xb2\xd3-\xea\x96\xd0\x8f\xd8\xe9\";=\xa2\x8f\x7fz\xf8\x98\xc1\xa63J\xf5q\xb2\xad*\xca\xd7\xe6\xa6>\xe6$\xed\xd27b\xa5\xdb\xe1#\xaf\xd2\xb3\xee\xbe\xe6\x83M\x87j*\xa4\x0c\x9d,\x81\xcc\xfb\xf1\x95~\\Z\x9bS\xd7F\xb3\xb4i\x1d\xbb\xe2P^\xe3R\xfd\xc2\xf2\xa5*c\xbc\xaeC\xa2f*\xeb\x93\x1a\xacU\xe3T\x0d\x96[\xc0\xc8\xeb2\xaa\xcb~\xf6\x06\xe3<\x89H\x8cN\xe5\x1f\xb2\x114Q\xb3\xa2\xa1\xeafZECK\x8f$e~qL~\xc3\xec\xb7\xa6\xcc\xa0\xdbF\x8d\xa8f\x9d\x9f1\x1c(\x881=\xbb\xcb\x93}\x85\xb3!\xee\xe4\x93\xa9$ \xc8\xb0\xad\x12\xd5Q\x84\x0cUT\xa5\xdeT\xb8\x8a\x9e\xa3\xcb\xa9BAy\xfe\xb3\x1f\xcb\xf4<\x9d\x04\x96\xef\xdb\x05\x10\xdf\xcb\xcf\x04\xf6\x99\xebu&\xbcJ\xcf\x0c\xc7\xc2\xed\xe9\x9f\xe2X`\x03\xb59\x19(B\xc8\xcf\x04\xe2Q|\xe8?C\xa6\x14\x1eR\xa63\xfd\xf1\xb8\xfa\xe1\xa2\x92\x91+\x1a\x87\x9d\x14\xd6\x94\x88o]#1ap\x9d\xbd\x1a}&H\xdbG\xcc?Q\x02\x13\n\xf0\xe0\xee\xfe\x9f#g \n\x9f\x98\x949\x1a\xc3\xa6O\xca\x15\x82z\x1fp\x91\xe6\xe0\xd2\xaf\xd1 \xaf$p^Bn\x8c\x13\xceR\xff\x16\xa31N\xf4\xfe\xd7\x10\xc07P|\x0d\xc1\x8d\x1b#\x88O\x82\xb7\xcd7O\x02\xf5\xc1B\xb7v\xc4O\xb2\xbe\xb2\x00ei\xa3\xc2 \xf0\xe3\x98k\x0d\xc8\x18N\xe8\xbboE\x11\x87\x18O\xe1\xc8Cs\x85\x1fG\xff\xae\xa5\x07c\x19\x07zE\x1e\xa1\xe3\xed{?\xbfG\xadBz\x865y^\x936\xef\xab\xfa\x1a\xf3$\xaai\x00\xd7X\xe2\xbe\xa3\xdfc\x7f.\xa2\x98PN\x03S-\n\xef%\xaf|\x0b)Z\x0dY E\xac\xce\x9c\xc07\xacVa\n7 \x82o\x0f\x99;n\xc2\xe2\xbbqs\xf39}\xcc\xd6JV]u\xcc4\x19=E\x17\xdd}\x1fC[u\x95\xb5\xcf\x98\x9c\xbf\x8a\x96\xab\x98\xce9\xaf[I$\xc1P\x1d ]\xc6\xff\xf5\xbb\xf7&\x0b\xfd\x92\\\xaf\xfe}\x02e\xdfV\x1f\x90\xc1vV%h\xe87\x14\xa9\x88\x0f\x15\xc3\xb4:.,0\x86\xc4\xc4\xb9\"\x9f\xeaj!&A\x1a\xaa\xca2\x8eQ/v%\xed\x89\xa1Nx\xc5yY57q\xd5^\x1dt]\x9a\x14Z\xd5M\xe71\x07r\xcc\x96i'\xcb\xf5\xc9\x01YYN\xda\xb4\xe4\xc8\xd1\xf5\xfa\x97\x15!qU\x04KG\xd0\xd5_i\xcc\x19\x96=\x80uD\xbf\xa0\xae{\xfa\x9er\x00\xc6M\xd4W\xc3\x99Tpr\xa7\xd7\xe6N\"\x1e9\xcf\xd2\xbc,Z\xc7S\x9f\xbd\x85\x06\xe7\x99\x903\xf8>N\xe7\xee y+[\x83\xf2\"\xc3\x91ST\xa7\xfc@\xc4\x8ad\xdfL\x83\x92\x94\x93\xa2\xcc\x89\xbf\xeeH\xeb\x1d\xf6'ZT\xf5v\xf7\x0e\x0f\xe1,J\xc2\xf4\xccK\xfcm\xb4\xf4\xcb4\xf7\xd6\xc5\xb1\xbf%\xb4\x0f#\xddC7\xefsV$.\x88\x82k\xa3\x87\x1e\xff\xda\x9bW\xcf8\xc61\x0e\xfe\xcd\xabgn\xae\x91\xe9C\x9e\x0c\xa4\x8b\xa6\xbeL\xef\x1dyX/W\xb8\xb6\xc1!8I\x9aP|\x8e\xbcUN(G\x9c\xd2\xdf\x05)\xbf+\xcb<\x9aoJ\xe2V\x9b\xcfa\xb2N\xa3\x1cq\xcd\x00\xd13\xb3\xfb\x1ec$\x9cq\x15\xd3;\x1a\xd7\xdd\x9d\xa7\xe1\x05\xe5\xd9H\x12>ZEq\xe8F\xc8\xa6\x05t\xeb\xba=\xc0\x9c\xac\xd3-\xa9\x01\x1b\x93\x95\x93m\xfa\xae1Y\xa9\xea\xe8}/E\xc9\xeb L\xc9\x95\xbfR1+R\x89Y\xbeJ\xcc\xda\xa8\xc4\xacB%f\xc5\xfcAOb\nx\xca\xc7\xbe\x1cUKZYU\x12B\x98>+\xe0?\x81`\x95\x8f\xc1\x97\x0bV\xd1u\x14\xacr.Xml\x05\xabt\xa8`\x95{\"x\\\x84\xe1\xfc\xc2B\x04\xad\x84\x0e\xde\xd5\\T\x88\xac\xc3\x85\xbc\xa0\xf5QT\xa8\xba'\x02\x10M\x90\xd5k\xcc\xed\xe2-\xe5\x9f{\xad\xbcg]\x14\xf1T\x8f\x18\xfb\xf0\xfa\"#\xac\xd7V\xdd\xace#\xca~\xe4i\\|\x17\x04$+\x7f@\xf5\xaf\x89\x9f30})\xe6v2\xb0\x8f\x11\xba\xedY\xa5@\xf4\x11To\xa4\xdd \x8c\xceO\xa6\xac\x08\xbad\xea4EZ9\xd1\xd3\xe5\xb4d\xde{j\x00\xe1>\xbb\x91BH\xaa\x17\xbd\x1f3\xabs\xafp4\xdd\xad\x96\x82X!\x15\xc4|;A\xacX\xa5\x9b8\xacX\"ka\xc7\xb4/\x1a>M\xdd\xc0@\xe4NH\xff\xb6(\xbf\xcf\xde\xaab\xdb8x\xfdw\x1bN\x84\xd6q\xb0\xeaO9\x14n\xc6\x0e(\xbb\xd7\x86\x97\x07\xbc\xf1\x17\x15\x0f;-\xfa\xe5J4D\x7f\xb6\x9f2D\xe1\xcf\xd9\x1f}\xdch/\xffG\x92\x06\xf5$\xc1F^d\x1e\x19\xd5z\xe9)C\xd2\xc3\x03=yH,\xbdN65\xac!\xa5,\xf3\xd3\xb0\xcc\x13\x8bl\x841\xefm\xd2\xc6-5p\xc8\xdc\\\x06\xa6\x0d]U=\xd6G\xd5l\xf9\x11Zi\xed\x8e1\x89\xdf\xa34$#7\xd5x>\xac\xb1\x98\x8f\x13\xd4d\xd3T\xd1\xc6w\x9d8\xda\x12\xb1\x86\xa6\xca6~\x1d\xbbj\n\"\x91m\xf5\xaf\xbe\x92\xdd\x16Q\xa4\xb27f\xb5\x84\xf7\xb2\xf5D\xdd\xf8)\x1cB\xd1\xac\xf6\xc7\xa6rIJv\x82>b\xe7)\x95p\xc5\xb0\xe9\xacJ\xcd6\xe229\xee\x0c\xd1+T\x1b\xcc\x98\xd9\xe0J\x9a\xb3q\x01\x10\x971O\x16w\x05x\xd5\x88_n\xcf\xb5)q]\xec\xcfI]3\xc4\xe4\x08\xd5i\x0e8b\xa3\xcc\xad\xcb\xa6\xa5\xad\x16\xc3\x89\xab&(L\xb0\x97\\1\xa2\xe065\xc4\xa6\xde\x7f\xc5\x0c\xe6\x1a\xc0\xc6:\x89t\x17\xfc\xe5 \x8eQ\xbeJ#]\xc6\xabA\xc8Q\xe3b\x94\xe8\x92\"Df\xa5\x9a~E\xb5\xd5^\xea`i\xeb|\x94\x1a^\xae\x99y@\x93\x03\xaa\x93y@CP\x18\xf7\xd8a\x11\xcc\xbcd\x8fk\xd0\x1c'\x8a0}U\xfe\xa5\xe1\xdb\xd4B\xc9(\\k\x86b\x0e{o0=i\xbb\xe8\xa8\xc1\xf2\x1d\xba\xb4+\x8dS\xb8\xe1\x88K\xed\x8eS\xa1\xf0\x84\xde\xe39wU\xcd;\xf4 \xd7&\x03\xbc\xa2~\xd8\x04\xbb9\x8f\x1b@]j\xfe\xa1;\x18G\xc9;\xcd<=\xc3\xc7un\x07\xdd\x8c\xb5<\x9bR\xa5gS\xa9b\xa5\x81\xb3\xd3I\xdf\xc3\xa9T{8\x89\x0bYg\xa5\xa7\x93\xb8\xb0|\xc9\xc9\xd4\x00\x15\x027\x18F\xed\x0c\xcepx\x08)<\xac\xf1\xfc\x94'#A'_G\xce\xb8\x80\x99y\xb9\xd0\xad$\x08a\xc5P\x96\xb8\x8e:[\xb1\x1c':6\x15\xd0\x1d\xf8\xb1\xd0\xa6mQ\xafkh`\x91h#\x13\xa1\x8du\x1aZ\x8b\x90iH\x8cC\xaaO%M8/\x0c:I\x803\x07]u\xce\x8c\xa2\xc6\xe1\xa1.m30\xbe\xa4\xabK\x9aa\xd9\x0f\xa5\xaa\xc9\xdc\x15\x0e\xae\xe5\x87\xc0\xfeT\x85\xfeI\xad\x84U\x14\x85n\x15\x83\xde!\xa1K\x8d\xe7;$u\xe9'C\xeaGX\xd6\x99\x83\x98\x85\x98U\x8a\x1a\xb9'-\xfb\xcf\xaf\x85\xa4\x16\xa7\xea\xa0\xdf\x9b\xd6\x03\xf8\x1c2\xb9\x84*w\xacP\xe5\x8e\x15\xaa\xdc\xb1B\x95;V\xa8r\xc7\n\xa5\xe6\x8b\x98?\x91Z\x10\xdcP\xd8\n\xc2\xcaV\x80\xbf\xa6\xb7z\x05\xa4\x17R\x8b\x03\xaa\x07Te\xa5\xc3\x8fo\\X\xd9\x1a\x17\x88\xc4\xb6 C<\xb3hkjo);O)\x0e\x8d}\x914\xc1'+\xf2N%$n\x90\xba<2)\xb9\x12\xe6\xeb\xd3oF\xfd\ns%\x92\xd1m\xf9\x99\x8b*\xec\xe3\xd2/uJ\xeb\xbcO\xb2\xbbK/\xae\xf7h\xd82\n\xb4\x9a\x11\xc8\xcf\x9c\\\xd1Z\xef6\xfa{Q6\x84\xf4\xe8\xa5\xb8\xa4\xc3q\xfa\xac\x1d\xfd\x94\x02\xbf\xe1\n\xdd\x94\xaeF\xb3\xca\x08-Z\xe0RK\x1d*3\x9aP\xfeB\x0d\xc3\xac%\xe6\x02d\xccbb\xe1\x9a\x13\"\xa0Y\xaf\xb8B8\x9d\x12t\x8b\x10v\x9a\xdau\x0dk\xd0\xd4.\xab\xfeYhj/\xf8\x0cVx\xa4\x06\x9dW\xa0\xf6\xf6\xb1S8\x84\x95\x17%\x0b\x92c\xaeS\x8d\"\xe1\x0c\x0ea\xc9\xc5!5\xd4\x11\x1c\x82\xcf8u&\xe2h\x93\xfa\x9d\xd7\xd0\xe4\xdc_g\xb1>\x07\xe0q\x0d\xced%\x0d\xec#8\x84\xadU'\xdeqH\xe1P\xc5\xe5Q%\xfcw\x0c~\x9d\x86$>b\xbd\xd6\x81\xbf`\xe06%\x80^2\xd0*.\xd3TL\xe75\x83\xb7Tp?\x17\x9b\x16i\x97'\xa1Q\xf4\xc8\xbaPP\xf1\x05\xb8g\xee\xc8$/>\x15+\x84\xc5\xb2x\xc7\x9c1<\x7f;\xe6\x8a\xe7\xe7~6r\x7f\x7f\xdfe3\xba\xd7\xafp\x08O\xb9\xc4\x87\x88\xe9\xf4>\xa0\x16\xf1\xeaP?4M=ma\x98#\x94\xe0\x99W`m\xa0hq1r\xbb0T\xccf@KR\x1e\xe3M\xb6AF\xee\xaf\"\xec\xd70\x9b&A2J\x82x\x13\x92W\xc4\x0f_$\xf1E\x8b\xcb\xec^\xf4\xd0\xa3\xc7\xcd\xaf\xf0\x10\xcaJy\x95\xf0;\xa7U\x9fj\xc5V\xce\x9f\xb9\x8d\xcc\x89\xcd\x151\xf5]L\xfb[\xfaI\x85\xe6\x8d9T\xd1^\x9c\xba\xbe\xe8\x01k\xda\xf7V~Q\xad\x1d\x9d\xf2\x90g\xfb\xacnQ\xb9\x14\x07\x95T\x0b\xd2\x9b\xebd\x0c\xcfu\xf3(\x99C\xcdi\xc4\x80\x7f\xc9\xa3\x92hg\xfc\xbd\xde\xfcq\x8e\xbe\xcc\x94v\x9d[\x04\x8a\x89K\xb0\xc0\x94\x1d\xa2l/+&\xf5\xd7\xbf\xe6d\xe1\x08\x97.\xda\xae\x8a\xebQ\xe0;\xddu?Y8\xf05/a\xdcF\x0bTeo\x1a\x16\xff\xd6\xbc\x9a\xb1p\x0d3\xbe&\x16\xaey\xe5\xda\xb8\xb8\xe6\x95\xf2\x1893\xa4\xe0\xd0[{<5%V\xba\xa4YK\\\xc8t\xc9\xd9IqiMKw*\xcd]\xaeQ\xf2)\xe3\xfe\x9aW\xdb\xa4\xc2h\x9by\xf68[(\x8f\x19\x17\x97,v\xbc~V+-(J_\xd6^b\x1c\xeb\xf0q\n1A3\x06A\x05\xe4\x1b\x92\xa2\xf7\xf9\x18\xde\xed\x98\xdc`\x07M>8p\x03\xdc\x0ds#\xd7l,'\xf4K\x9f\xb9\x85+\x03\xff\xafN\xdd>D\xd7\x1f]\xa1\x9a\x7f\xb0n\x7f\xe7}-[\x8bn\xab\xa7\xa7z\x93\xa1\xaa\xf1\x17\xba\x86E\xd5\x1f_\x94)l\xd8&T\xa7\xc4\x18\xce\xcc\xbb\xcdj\xacL\x9dWQ\xf3\xe6\xd0\x1b6Y\xd3\xcet\x84@2\xf1Q\"\x11\xd6\xa8\x19\xcc5[o\xe84\xbe\xb60q\x1b8\x1e\xf5\x94\xb4\xec\xd7|-\x04#E9\x9b\xee-\xef\x1da\xc7(\x88\xc4\xd5\xc7\xe4\xb7^\xd2\xb9\xe6\xd51\xb1\xcb\xf4>\x8a\xf5\x1e\xc3\\\x9b\x83q\xed\xc7\xb5\x83\x81\xc3\x9d=\n\xd0E\xa1 \xe1\xa8^ar\xa43\x1a\x83\x03l\xe9\xbc\xda\x06Uq\x9b?i:\xf1\x9d\x16\xc5+K\x89u\x9a}MV\xfc\xa6Z^S{\xb1c\xa2\xd0\xd5^D>T\x88\x02L\xb5\xfd\"\x0fIN\xc2\x91\x9bhV\x94\x1fB3\xf8I\xb1p\xd5\xd4\x1di\xa6\xee\x91n\xea\xb8h;\x83#\xeb\x99\xd3\xf7e4\xae\x04\xfc+\xb5w\x0e0r\x1e\xc3C8\xf6\xcaT\xc6\x85v\xa2W\xba\x97\xe1\xc0}i\"T\xc8\xb5i\x14<\xf4JpP\x06 :B\xad\xfe\x11,\x17\x064\xa4p\xa4\xad\x87Yo\xdf\x9fR\xe0\xaa\x92j\x95{\x1f\xbc\x94\x05i\xa5\xb7 \xd5fCF \x85u\xe8\xf7\xf7]s\x89\xcc\x9a\xd7TL6T\xffm\x9b\xd0\xea\xbf\xf8\xcdke\x13Z)sG\xacTQ%+UT\xc9J\x15U\xb2RE\x95\xacTQ%+\xa5Mh%lB+\x8c\xc8\xbf-\xb5\x04\xb1g\xbd/W\xe6\xa0\xf6\xedP\xf4]\x91no\xf5\xf1\x0dE[[C\xd1\x97(\x94\x8e\xd1\xca\x14\x85\xa2\xb7\x88d~^\x90\x90oq\x85X\x85\x91\"\x1bt\xdd\x7f\xd9\x04\x1fd\xf2\x12!)\x9c\x1bSk3\x99\xff|\xa9\x16b)\x10S\x91@\x94\x14\xa5\x9f\x04$]\x00\x0b<4\xebC\x12\x1e,\xf9$\x8aQ=\xa52\x8f\x89+\xf1R\x16\xc6g\x91\xc3\xa0y\xe56\xe6\xb5\xe6\xd5] \xca\x0cobydn\xf3R\x9cD\xd5\xe31~\xca\x0f\xbf+^\x93\xf3\xd2\xd5L,\xd7\x1bZ\xf7\xbc\xd3\xe3\x92\xf2\x07\xac\xaa\xbbN\x03!C\xafO\x1b\xa4r\x95\xd9\x02PN\x90\xec\x15\xd7\xea\x88W\x07a\xec\x942@\xb9)\x95\xbd$b\x7f^\xa2\xabWc\xd5\xb4\xb4d\xd6\xc1g\x16YB\xad\xccu\xac^\xc9&\x97$T\x12\x17\xabR\xc2\xf9|5\x98_\x9b;Xz\x8d\x87\xf0\xfb{\xd0\xba\x0fo\x06d>-\xdav\xa3\xd6nT\xbf\x85\xf5A\x06X\xd5\xe8\xc1\\\xfb\xf2\xa1\xa6\x8b\x92\xcf\xc7~I\xb0\xbe\xe8\xebhMt\"\xf4\xba\x9a\x04\x8d4$\xc9\xf5\xd5\xbc(\xc5\xa7\xcb\x92\x8aL\x0d7\xffo\xc3\x87\xe9_\xad \xf6\x9b\x91W\x92\xa2t\x93\x11\x05\xf6O\x1c>#\x93\xc7Q\x91\xa5\x05f\xe6w\xde\xd2\xe3\xe3\xa6_\x96~\xb0\xa2\x07\xb5xI\x05.\xbe%4,\xa1\xdd\xb7\xa4\xe0\xbd~5\xb4G\xec[\xf4h\x82\xd7\xb9\x9f\x14\x0b\x92\xcb\xba\xd6|\xa3\xd75\xeb\xcfI\xdf\xd0(\x8f\xe9*8\xf4\x98u Jx\x9c\xb9\xe9$\xa4[\xf9\xa2\xca\xb1Q\x92\xf3\xf2\xe6\xaa\\\xc7\x16\xban\x0c\xce\xe9\x1e\xf0\xc2\xcaV%;(\xa5\xc9\x0ed\x17K\x80pa\x84\xed\xca?\xb2\xebT\x9f\x94`n\xf1\x8938\x84\x93\x0b\xca\xd0\x15\x9byQ\xe6n\xea\xc5~Q>MBr\xfeb\xe1:7\x9d\x11\xdc\x80\xe9h\x0c\xa7o\xbd_\xd3(q\x9d\x99n\x9b\x8a\x0b\xed\xfc*D\xd5l\x08=\x13\xd4\xc9\xfdpdZv\xe0K\x7f^\x99{\xc8y\x99\xfbA\xf9\x84\xe7oz\x92\xa7k\xde\x8fF7\x98W\xc4\xc8=2\x18\x84\xe8\x85!<\xb43\xcc\xeaG\xe7\xf3\xdc\xc0 i\x9fR\x1aTy]\xd6\x99+\xe8\xc7%\xb7yB\x8b\x17\xf9\x8b\x8c$\x1c3/eIq|\xa3\xc6\x16\xaa\xfa\xec\x06\x07\\\xd8\xa9\x06\x8a\xb88We3hw>\x863\xfd\xa4\x83q\xe2\x9bYf`\x11 #\xff\xb5\x9aM\x91\xcbc\x06g\x83\xc7\xa2|\x81\xb3\xdb\x14\xf1\x94\xe3`)u\xb8\xce\xa8\xfa2\xe7< $%\x96\xd6\x86\xf9\xa6\x84\x8bt\x93\xc3\xd7r/\xda\x99f\x96k\xda\xe7\x06'\x84\xa2\x81\xdbN~\xc8x\xd7\x9b\x14\xe8_7\xb3\xd8\x8f\x92\x9b\x8d\xd9\xff\xc8\x036\xf0k\xc2\x88\xa7\x181\xcc\xe0\xe6\xff\x8d\xd6\xfe\x92\xfc\xebf\x0b\x87\x12\x8f\xbb\xfd\x14\xaeSl\x97\x8e\xd6\xb0\xd1\xa4\xf9\x0e8\xa8Fv\xc0\xd1+\xdb\xd7K\xed!\x80\xf9\x9ed\x9a\xcb\xe6\xb5\xf6\xcf\x7f\x89\xc2r5\x03g\xba\xbf\xff\xff\x93c\" \xe5W7\x94\x073\x1d\xbb\xa8\xd0\xc8\xf0\xb9\xf37a\x94v\xe6\xce\xea\xb8P\x9f\x8d\xf4\x8bzC\x117G\xaa\x1d\xb1tA\xd1h\x1c\xd7O=\x9d\x11]\xado\x96\xacL\xb5\x89\xe8\xc48\xcc\x7f\x88n\x1f\x04O\x17P~\xfc\xbdQ\x9e\xcbtE\xe22o\x0d\xee\xe4\xf5-\xec\xc3C(lw\x80z\xf9\xad\xcd\x7f\x91:\x9c\xf1M\x92\x93 ]&\xd1\xbfIX\x99\x89p\x8e\xbf\x16\x81A\x94\x89\x10A\xee~\x81\xd4\xdd\xd3E\x8a~\xca\xd9/4\xa4\xf8\xd3M\xe4\x06K\x91@\x99\x8a)\xad\x8d\xf7Z\xb7\xa5\xe5\xa5q\xa4\xe1\xc5Vg,\xc0\xb0Tz\x9e*]\xab\xacm\x916UH\x98Yu'\xcb`\x95\xef\xd0}p\xf7\x8e\xc4\x88\xa7\xd7}\xd6\xbe\x9eY\x1c\x95\xeeM\xf7\x9b\x7f\xdd|x\xf2\x7f\xbf}{\xe3\xdb\xd1\xcd\xe5\xc8[DqIr\x0b\x0fK\xfe!\xc7\xa9\xb2\x0dEkY\"\xdc\x8e\xfa\xba\xdd\xdf\xc8\xb6\xbf7\xbf\xf9\xd7\xcd\x1b\xac\x9b\x9c\x11 \xda\x0f\xfb\xf6\x1f\xc6\xaf\xfe\xeb\xa6\xddw7\xb6\xdf\xb5\x9e@\xec\xc0\x9er\\\x80\xc8E0\xef\xf0^$~\xf8\xbdn\xd6\xf8!\xcf\x9d\xd9\xed\x850JuM|\xf0-Li\x13\x0d]Gm\xcb\x9b\xbe\x85\x87\xed?g\xf0\xbb\xe4\xdcg\xb1[\x82\x83\xed?G\xbd\xad'a\x89\xfb\xa01\x1c\xca\xf4\xa6\x01\x1c\xc2IGeSg\xb2\xa5\x7fu\xe2\xac\xe9x\x17c4\x07\xbb\x0b8\x042\x86\xd4]\xd8\xb8\x13\xf3uR)\xeau!]\xec\x14wK\xd6^\xe4\x96\x94uq\x1e\xc5i\x11%\xcb\xd7\xfe\xd2\x81\x19l\xf8\xdd\x17\x19I\xea\xbb>\xbf{L\xe2E\x1b\xdeyM\xe4\xb9\xbe\xe5\x01\x81\xed\xa3\xf7\xfdH\xe2\xba2\x86TeR\x8eLI\xeaX\xfdq\xa4\xe8\xbd\xe7\xad\x81R\x1e\xdf\xa7\x88\x15O&\xf2\x9e\xd2\xad\x95\xbb\xc9\x18b\x85\x92\x0fK\x89\xc3\x0d\x88\xfa\xef\xa3b\xb69\x83us7n\x8c\xa1\xd0\xd9Y(J\xa4'%L@\xe7\xbe\x1dVP\x07\nM\xa1|\xb8l\xb9\xf0\xef\x0c\xe7 ov\xbb\x1aV\x8f\x109\x1d\xac\x9c\x057 ds\x0f7 \xab~ET\xe8\xc4\x80\x05\xec\xcd\x18\xb0\xeb\xc6\xf0kh\xd0\xa6\x0eN\xb4\xc7\xc3\x81\x02o\x91\xe6G~\xb0\xb2\xdb\x1e\xd9 yK\xf7_\xf7\xe4\xa42jfw\xaa\xf0/\xed\xedu\xfc%F\\\xfb\xfb\xaf\xa6o\xe9%\x12\xb6\xde\xfc\xfb^\xdd\xc0\xdf!'\x19\xf1\xd1vB\x99\xbaoVe\x99\x15\xb3\x9b7\x97Q\xb9\xda\xcc\xbd ]\xdf\xfc5M\x8a`\x15G\xc9;\x92\x977[\xf0\xdf6\xbe\xd4\xfc\xe8\xa34\xbb\xc8\xa3\xe5\xaa\x047\x18\xc1\xc1\xfe\xf4\xf6\xe4`\x7fzg\x0c?\xa6 \x1cW\x1f\xf3\x9a\xef<\x8b\x02\x92\x14$\x84M\x12\x92\x1c\xca\x15\x81\xe7O_\x8b\xdbM\xd0\x9b\xd5od\x06X\xd4c3\xb3\x842\x7frw\xdeq\xe3\x08Ab\xaf\x12$\xc8\x08\xcaU\x9e\x9e\xa1\x9d\xe1\xf5EF\x8e\xf2<\xcd]\x87\x9cgL\xdd\xe6\x03\x7fI\x92\"y\x8a(]\x8e*^\xa3\x0fr\xd0\x05\x81\x1b]0\xe1\xa9@\xc4\xc1\xf4w(\xfb\x1f\xca\x19\xf7A\xa9~\xc3\xce\x98\x8fX\x16\xf4\xfe\xc4@S\x9d\x97Vg\xde!\xc5\x1b\xde\x97\xca\x1e\xb1O\xb1\xa9\xfd*z\xc7|\x8d\xa5\x00\xaa\x97\xd1\x0d\xe3[\x98~=\xa2''\x0b]qS\xb8q\x88F\xf8\x12\xbe\xfd\xf6\x10\xa6c:\xc4\xc3\xee\x18E\x8b\xf4P\xe2o\xb4\x1a\x1f\x86\xed5cxw:2\xe1\x82\xc2\xbb)w\xc9\xc8+\xd3g\xe9\x99\xa8D;\xac\x0f\x1f\xdd\x99\xed3,\xfe\xba\xa82\x1b\xd0_\xf7F\x7f\x8e\x82\xaf\xdb/\x05f\xd4\x05f\x84\x17\xfd\x80h8\x81\xe0\xb9\xaa\x8a\xf6\xa8\xe2\xa8\x8e\xceKM1\xef\xb4[\xb2;U\x97\xecN?\xbeZ\x88 t\x9d\xb1\x98-\x8b\xe6z\xddReh>t\xb7Jy\xa7\xd3Sr^\x92\xa4\xe8\x1d\xf6\xef\x99\xe7\xd4\x0c\x9c1\xf0\xa3)1\xd7\xda\x8e\xae\x1bB=e\x9ecG\xeb\xac\xbc0\x94\x89\xef\xc5\xd4\x8a*\xf1\x98S\xb5~'\x12\xfa\xc9\x88\xeb'\xafU\xc5x\xd5\xc8m\xf0\x10\xb1B\x85\x88Q\xc1\xbf(9\xea\x98\xf9S}\x02\xfb\xfc\x0b\x8f\xa3\x02)\x9d\x14\xa1\xf9\xb9\x8f4\x0f{\x8d\xda-\xf4\xf6\xbb\x0c\xaew\xf4\xa9-\xd4\xa7\xad\x9c\"\x0e\x9d\x96\xe9r\xa9\x11>B\xdesY\xfa\xe7\x9e\xeb\x86\xba\xbfQ\x92mJi#\xcc\x04\xee\x04+\x12\xbc\x9b\xa7\xe7\x12MY\xa3\x0b\xfd\x87\xf8\x1e\x1e!\xa8t\x90(tj^\xc9\xac\x9c\x8c\\Q\xc1\xda\xe3\x1f6\x1e\xb7\xa318\xc7$ \x01'\x95mL\xa7\xe7#\xf4Y\x95\xe8\xff\xa49\xa1\xe5&\x93Pj2Q\x94\x93T\xa4\x88\xbeu\xd0\xcb\x0b\xf0%\x17\xb4\xdc\xb0ag\xd4\xb0\xcd\x05-v\xe0.f\x82\xa1\xeeG_}\xd5\xfa[-F$&\x1bD\xc3\x02\x90TC\x18\xb9\x89'$\xc618\xcc9\x03\xad\xcb\x88\x13\xcc\xbaLD^\xc2\x84\xd5PB\x91\xbfOG\x9a\x96\x14\xebCK\\\xdbai\xb2\xad\x94\xc8y\xad\xc2W\x03\xa5\xd6\x9af\x1fS\x1aX\xc9\xb4\x9b\x1a\x94\x8a\xc4\xda\x05IxT6\xce\x15.\x04N\x1e\xe5\xe4\xdct\x0c\xfe\x186*S\x10\xe6\xf3\xe6\xd5*X\xcdA\x8b\x8c\x05\xc2\x00c\x9ci\xc6KX\xea\xf6\x13\x10u M\xd3\xc8\xca\xb5WHg\\\x18\xb5r\"\x19C\xae\x98\xdbF\xf4\"\x96\xf0`k!\x0e\xb3\xaf\xbe\x02\x07\xb5Y\xb8\xdf\xd2z\xa1t\xfa$\xc1\x9a\xe9\xa2\x96\x01\xcf\xc3\xa88>\xf3\x97K\x92\x1f\xa0N\xd6\x87\xaa\x8d\xf3I\x9d\xf9\xf6\x8f?\xd8]L\xcf\xcbi\x11\x8f\xed\xad\xefW w\xabT\x8aj\x88\xc67f\xd8\x0b\x9e=\xea\xab\xaf\xc0m\xf4A\xd1\x83\xddZ\xaa+`\xef \x07\xb0\x1e}tY8h\xb2Y\xcfI\xfe\x9a\xeb\xc7F\xae\xaf\x88\x93\xeb{q\xc90\xdd\x1d}\x9c|\xedU\x12\x86_\xa28~E\x02\x12m\x91;\x91\xd5\xdc\xb7\xce\xc5Ps\xea\x9fxw\x99R\x88G\x97\xda\x83Hd\xa2\x02 \x1b\xee\x84\x1cf*3\x9a\xcd\xeeJ\xab\xed\xe4F\xad|\xd4#q\xa8\x07,%\xf5h\xc4Q=\xd9\xac\x91w\xf5\x81\xe5b\x88:\xf7u\xad \x17\xcd\xc6{53lJoP\x18\x86\xd2\xd84\x1b\x8c\x03\xa1\xff\x9d\x893#'\xbfm\xa2\x9c\x84\x8cT\xe1\xae\xf2\xd9\x19L\xf72\xba\x89x\x8b(/J\xb7\xb3\x01\xb1\x90e\xc1?+jZ\xdam\xc7bTe\xd1\xee\xee\xb4\xfe\x86lo<\x99\x18\xf4\x01\xbc\x05\xec\xce+\xc3q\x9fX\xee\x8f|@V\x8e\xb4\x865\x98\xcb#.?sm\xaf\x9e\xd7 Z{\xfe\xa6%\xaa\x0b\x95\xb7\x1e#\xad\xe9M`Mo\xc2\xea\xb3\xe6\n\x0f\x85\x91\xde`\x95\x07cj\x11\xafX\xa5gGB\xdde(\xef\xc0\xa0\x1f\xa5\xebu\x9a\xd8\xbcs\x81^\xd9\xce\x8fE\x9a\xb0\xcc\xe7O\xd2|m*)\x9b\xbb\xcc\x98\xfc=\x0b\xaaQ\xc2\x9e\n\xc7\n\xc6n\xa8\x01\xcf\xe0\xb0\xc9\xa2\x9c\x9a\x0b\x98\xceM\xf6\xac\xb6\xc1\xc9`\x15Y$Zk6\xd4\xf6#\x83\x95)\xa8\xec3\x85W\x15S\x10\xd8\xea\x06\x06\xbbP\xd0\xf4\x8f\xa2\x9fh\xa4\xf3\xc1{\xf4\x135\xcd$E\xd9\xc8\\hot\x92\x91I\xbbwk\xf3\x93\xa1\xf4X\xc3\xc2\xa3\xc9\x05\x04\x83\x8b\xb65\x8dL\x81\x12R\x97\xe1\xe4\x88\xe1\xafm\x0d\x8ds\x06nSC\xe3\xb8\xb13\xb8\"\xddT&\xa4 \xde\x94!MEC\n-\x93\x12P\x89^\xfd\x81\xef\xea]\xb9H\xf3\xb5\xaf\xed\xe5\x0b8\x04\xf4\x81^!7Rv\x18\x11\xed\x86x \x87\xf0\x82\xbdP\x1a\x10\xf45%\x00\xb47\x8f\xfd\xd2wL5\xf8\x9eS\xe8'\x15t\x94\xd4\xa1\xe5\xea\x97\x9e\xd6\xc3\xae\x19\x0e5\xf8\xaf\xa2\xf3(\x0cD%Y\x17T\x16\xc0\x81t\xab\xc95\xaf\x9f\xe0\x10\xde\xc1Cx\xd7\xe5\xa1\x1cM$\xe7+8\xc4\xc0GW\xd4\xa2\xe8\x12\xf0\x91[Vy{\x95_y\x0c\x87\xb0n~e\xe0\xfb\xcf,\x12Y\xbd\xb1\x80\xf9\xcd\x02\xe6 \x1c\xc2\xdeT\xab)h0z\xcc\xe9\xfeY\x8dOl=:\xec\xe03:v\xda\xc1gM\xbew\x8c\xfd\xe1\xb7\x84(\x87\x86\xe37\xf5\xf7\x04h\xe3koh\x9bo\xea\xf0e\xda\x03\xec\xf5~\x1b\x8e\xf5\xed\xb7\xfa[U\x1b\xe3f\xccB\xd9\x15G\xb1\x02FWL\xd6z\xa4\xe8\xf3\xf6\xb3\xdc\xfbH\x17&\xa8\xb0\x99\xd9\xba$4\xdf\x8c\x12\xa7\xe5\xde }\xe9\ns\xf8\x0fq&\xba\nC\xffSx\xd82#\xd2\x06\xa1\xa2\x070\xeb=T\xf6\xa6=\xb9\xf8au\xc6\x00VF]\xddC\xabT\x0dA\x1ac\xbe\x10\xdaS\xf5\xd9\xa7\xea\xaf\xf3?\xff\xef\xefN\xc3\x8f\xee*f\xb39Y\x9a:\xe9cx9\x86_Q\x0fu\xe2\xc0\x0d\xf8\x15n\x80\xf3\xd6\x19\xc3w\x18\xc2\xb7\xf3\xac\xb5z\x92\xa7\xd9\x84\x9fg\xca)p\xffJ\x1b\x1d\x833\xd2o\xb5\x1d\xa7 $YN\x02\xbfT\xad\xcf\xfbq}\x96\xd6\xdb\xbf\xf1\x16\xc6\x846\xfe\xfep\xab\x15i\x9c\xe4\\g\xdcb\xdbq\xba\xc6\xb0\xa4}~%\x94\xe3\xaf\xae4G\xfa\xb1\x89\x9dgnW\x14o&\x14\x83\x0c\xeeR\xe7\xff\xb0H\xa9~\xfe\xb3\x1f\xeb\xcb\xb0\xc8g\xa8N\xa0\xbf\xa63\xf2X\xcc\xc8\xe3\xff\xf8\x19\xb9\xc2\x1a+;8wV\xdb\xa9\xe1\xe2\xa9!\xca\xe7Zz\xcc\xeb\x9f\xc8\xbei\xc2\x8a\xbd3\xd4\x0b\xc3\x1f\x7f\xc0\xde\x13\xb3$\xab\xed\x87\xca\xf9\x85\xb2+\xea\xb5\x14\xbdw\xbe\x89\xbe\xfdn\xebG1\xa6\xe2@V\xb4\xf8\xe6f\xf4-=\xe6\xe0\x06\xbc\xb1\x88\x8eo^\xc2|\xaa\xc1\x8f\xda7\x8f\x07\xf5\x8eU\xc9\xcd\xde\x8fZ3\xd5\xe0\x94~\xfb0s&\xd82\xbbi\xe3*A6i\x8d9\xfbM9\x98\xd7t,{\xcf\xb5'Z+\xcb\x13\xc6\xdc\xce\x0cY\xed*)\x07\xcb\xebP\x94\x8a\xcc\xd3\xa3\xad$o\xd0uX\xebM\xb8N\xf3'5\x84`\xabf\xf0T\x0d\xd4\xd8Z\xf2\xedVK\x9d\x8c\xd5\xa2\x14\x0f&\xd0p\xb9m\x83\xcfXx\xbd%\xef\xbb\xabV\x84\xd0\xc5+fB\xccc\x7f\xea\x1a\x12\xf5\\^(\x11\x087\xc3\x0b\x0d\xc5:\xd2-\xab\xf5\xba\xd5\x0e\x96\xdd\xba\x88\x06\xa4\xe0\x0e\xd9\x9a\xacVvZ\x1f{\x8d\x8f\x98\xb3\x8e\xd6A\xb3*\xa2\xf6\x8d<\x89\xa5\x84H\xefX\x01G\x816M\x1d\x8en\x9a\x84K\xda\xac\xa9\xc9\xa9\xec\xe0\xc7\xa4,\xa3d\xf9$\xcd\xdd\xa0'g4\x183\xcdD\xd4>k3\xf8\x89\xb96PY\xf5'\xe4U\xd4\xaf %\xa7~\xf6\xae\xca\x89\xf9\xfa\x97R T\xaeT\x81\xca\x95*P\xb9R\x05*W\xaa`\x98+U\xe0\x16\x8d\x8e\x06jO\xe2\xe0\xe3\xfb?-l\xfd\x9f\xbe\x04\x98\x0b@\xfb\x00\xf38\n\xde}j\x87\x17k?$R[?4goevS\xc30\xcb\xe0\x1aU\xferma\xe2m\xfd8\xe2\x85\x1e\xfcu\xe1\x9e\xa4c\xf0\x91\x02UO\xbe'\x8b4'\xfcp\x12\x00\xa8\xb7\xe3\xb3\xe4\xa5 \x7f\xca|::7\xdd\xd1\x18\x12\x8f\xf0?4\xc7\x82\x18\xb4\xf6\x04\xce\xf0\xf4\xd5\x9c\xa3kn\xe1\xe8\xfb\xec\x02\x12*\x837\xda\xcb<\x0d7\xc1\xb0\xb8\xfe\xca\xdb\x8f\x8d\\\x92r\x80\x7f\x94\x19\xc9O\x04 \xae^\xf5\x1a\xeb\xf8\xdb?i,\xbf)\xf6y\xce\xa2\xabme\x93y\x99\x00G)\x10\xe1G\xfc\xd8f\xa9\xa6\xae\xdb\xb1\x8d\x19X\xee\xab\xb2\xc6H+\xa0I\xd3\xc9\xf8\xaat2\x1bU:\x99B\x95N&\xe6\x0f\xe4\x15\xd0Z\xb9c\xaeY\xc6\x98\xfeG\x84\x1e\xfa/\x0f\x1e<\x90 \xe9\"M\xcac\xa6\xcfv\xa2\xd2\x8f\xa3\xa0\x1b\xa2\xd3\xfa34\xd2'\x03\xe3\x00m\x1a!)\x83\xd6\xab\xbb\xa4\xf6\x93\xee\x94\x1fc\xc72\x03\xaf\x18\x02#\xff\xdb\xe9\xd1\x8e\xa5\x9b\xc0L\xb9`\x00\xf5\x82\x81\xfeEP\xb1\x08\xc62@\xc0\x19\x04:\xac\xb6\x17\xd1\xc8u\xc4\xd6V\xf9\x05C#\x94\x06\x9ae\xe1wVyC\x87\xd0\xf2\xfe\xeb\xe39\x01\xf46&C>\x06\x90\xb7yz\xaaI\xca\x00\x9c>\xff\xc0\xcb\xa9\xea\xe3\xe4\x8dI\x06@\xde\x85\xdd\x86;$\xd3\xc0\xd0.M\xf2\xf4l\xd7^\xed\xd2\\\x90\xc6\xfa\x05\xb8l\x92\x02\xd8\xb1\xddV6\x82\x8f\xdf<\xf3\x1a\x1a\x90\x05\xa1\xf4HR\xe6\x17\xb2\x12\xb9&\xdd\xb1\xf0\x01\xee\xc8?d\x0c\x07\x06\xbf%\x10\xee\xbb'\xfb\x9ax\x10q\xa1\x0b\xef\xc9\xd4\xa2\xda\xcf\x9e$\x1f\x83\x1b\x8d\xaa<\x81\xeaL\xd5\xe2\x12N\xbc\x91\xd7\xf1\x19\x7f;\x12N\xb4\x1dOr\xee=\x02\xb3\xc6S\xa3G\x89\xb86\xb2\xa6Z\x0e\xec\xfa\xee\x9a\xd8W\x8b\xbd\x0c\xe2HJ\xb5`\x97\xf0\x0f\x10\xd7P|\x06\xd6lz \x13\x94\xb8vl:\x92(\xa3?]o|^Fb\xa39H\x13\x9b\xf6)\x97\x80\xb6CGx\xcb\x991\x95\xbe\x83\xa6D\x83\x97\xa0\x80\xe5\xdcb\xa6\x1f\x94F\xfdX\xc3t\x93CHS\xbd\x83\x94c\xeb\x88?x\xcbP\x82\xba)\n\x85x\xf7\xba\x89B\x9fT\x83\x19\xc8\x04\x1e* \xb9\x81\x10xP\xdc\xf93\xa8/\x1b\xfc\xbeDK\xd9g\xf9m#5m$\x90k\xaa/\x19\"m0I\x83\x84Q\x99\xe6F\x0d#SF\x92<\xb7P\\2md\xec_\xa4\x9b\xd2\x02\xbf\xb3p\xb9#\xcc \x884\xdcH\x18\xe55\xf8\xf3\xd5\x07\x84\xcaL\x04\x82gv\x8a\x8c\x04\xe6\xe1\x84W9\x9c+\xeb<\xf3\x0b\x93#\xc8h\xa7tj\xb6\xfc\xfc\xa2\xcdL\xeb\x93\xa7C+\xcc\x19gA>\x05\x0c?u\xc7;\x9e\x95\xa5\xe1h\x14\xec}\xd9<\xa2\x94V\xea\x9d\xf6jo\x9f\xaa\x8f\x9f\xf7c,Mgh\x86\xe9\x90\xf4\xa7\x87\xd031\x7f\x1fVg\xaf\xe9+\xcd\x99\x0fx\x08+\xb7\x03\xc5\x1c\xc3\x1a\xae_\x02\x16Co\xc4\xcd\xcc/W\xf8\xbe\xb2\x1f\xc5\xda\x8f\xe3F-F\xbf\x84\xee\xeb\x0d\x7fW\xf5gt\xce\xebFw\xff\xb3UT\x92\xe3\xcc\x0f\x98k;\x99\xe0\n\xabw\x95U\x15Gi\xaa\x01>\xb05)\n\x7fI\xb4\x07\x8b\x16]\x8cC\xc2\x8a\xa0\x93\x90\x04)3\x91;3p\xb0\x12\x8aah\xc1&/\xd0\xdc\x94\xa5QR*\xb9\x1f\xd9\xd8\xb0\xb6\xb5\x8e\xe6i\xaa(W\x07\x7f\xe2\xcd\xa3$t\x19:\xe4R\xbb\xb6\xf3\xe3f\x9dA\x99\x02\x1d\n\xc5\x96\xbc\xd6U\x88\x1fm\xb24\xd4\x04\xb6\x13m\x91C\xe5\xbc\x8c\x8f\x92ZtwJ\x8e%h\x9fEE\xe9E\x05\xfd\x8f\xdb\xd9\x0c\xf6\x9bI\xb2\x97\xb8\x9f\xb0\xc7v\xd5%>\xc4\xd2\x804\xc8!\xfa\xe3&\xe8\xe5\x91c\xcc\xa4\xdd\xa7\xd3\xa4Z\xc6\xd6\xe7v\xde\x19\x9f\x90\x90Z\x13I\x0c\x0fB\xc4\xfd\xc8$\xcd~3\xff\x99 \xd5\x95\xd2\xa86\xd6Z\xd1\xab\xf6+\x06\xda%\xd3\xd6\xad\x94\xda:\x17\xd3k9\xce\x88W\xa4t\xc0\xb1\xb1\x1d \x11\xfcd\xff\xadW\xa6o\xe8va\xf5\x8a\xe0\x06\x10\xaf\x88\xa3\x80\xb8\xd3N\xc7\x04-\x81^\x1d10\xa7\xccm\xf2\xa4-\xa51\xfb\xc2\x17\xbd.\xbf,\xf5\xbaA\x95\xbb\xefO\xa3\xe1\xfd\xe2\xa0jQ\x01\xe9\x12>\x87\xe2\x13u\x12O\xdc\n\xd7\xd0\x93\xb0\xca\x92\xf58\n\x9f\xa7\x9bD\x16Td\xab$\xaf\x95\xe3\xcdl\x1fE\x95\xce\xa837\n\xf0*?R\x7f\xb2\xda\xf3!;J>`\xea/\xd2\x1bT\xfbN\x9d\xe6\xa9s\xbf*\x9d\xcf+)0\x9dH\x13G\xa4\xc3\xbf\xc4\xf8?\x81\xb9\xa39\x04\x93\xb5\xa3\xe2\"M\xa6\x0e\xec\xaeV%\xddv\xb3\xda\x89\x89\x82^\xc8&\x8edR^dD\xb0\xb7\xc8f\xba ?\xfe\xa5\x9f\xd1\xe9\x11\x0b4\xd6\xec\xd4\x03s\xcd\xf4\x9c\xf5J\xab\xf7\xd5\xc4\x85\xa9\x06SZp6\xe22\xe9fR\xe6C`\xa5\x953\xe8\xdb\xf8\xa05\x81\x9bR\x8fm\x80\xaeE}\xc7\xda\xe9z\xa5\xdbB\xcf\x98I\x12@\x8fzU\xa9\xf9\x08\x93^~\x93\xe6\x16cI\xb5co\x91\xa7\xeb\x1f\x8fG\xee\x89C\x0f\xb5(@.\xff\xe6\xafE\x9a8o\x1b\x9c\xe3\xf8\xday:\xd3\x1e\xbd\x10!\x06\xcf\xa2\xe4\x9d&5\xfcug\x10\x13\xf7\xb6* \xfdg\xc9\x18^\x05?\x98H\xf9\xc1\xa8\xe2\x07\x93\x11\xe3|\xf6\xbf\x86\x0d|\x03\xc9\xd7\xb0\xa1\xfc`t\xb2i\xf3\x83\x1b ?(\xf8\xcd\x0f\xc5\x08F#M\x12i\xcc\xb2\xf8\xda_\xa2\x05\x17u1\xa7\x8d\x1bLx\xa5\xccn\xa1X,\xb8B\xe6\xad\xd9\xb2\xc5i\xaf3:5\x98\xb1\x96\xc7\x003\xfd)\xf2F\xb7\x87\xa8\xe6G\xe87^d\xd7\xb9\x87\x9f\x80c\x1a\x14\xadf\xed\xf4\x91\x0fq\xfaH\x07\xa4\xcad eK\x7f\xb9$aE\xb8\x0b]\xc6G\xcc\\lv 11\x0f\xf6\x8aB;\xee*\xdd\x92|\x1b\x913S\x8d\xc1\x17\x1c\xceA\xa1p\xb0\xf56\xad\xad\xb7U(\x9d6\xaa\x1e\xf8$\x9f4z\xe8/\x0bg\x0c\xa5\xc1Y\x98y\xcf\x08\xa7\x92\x08\x1dI\x8c\xb6\xe2\x9dye\xa86M\xd5OT\xc2*_\xb8\x84\x9f\x05\xec\xe4\xb6\x00\xf5(sF\x1d\xe8\x9cl\xd4\xee\n\x00=;F\xf7jbPL\xd9\x95\xe6\"\xe9}\xd3\x85\xef\xaa3A\xa7\x87\x1b\x0e\xf3\xa2S\xcd\x89o\x9a\x90\xda\xef\xc1\xe0\x93j\xf4}\x00\xd6\xc3t\x00\xab\x0f-\x0bN\x992\x86PG\x06\xc4U\xa7\xeb7\xc32b\xb36d\xb0\x15\x17\xf33\x8b, \xe9N1$G\x05\xce\xde%\x0d/\xad\xc6\x06\x1e\xc3\xc6\xd29}g_\x0b\x10\x1b\xcc\xa2\xa7\xc6\xf8[q\x898\\C\nSzE\xe1\x0c\xd2*\x19\x93\xc5\x0bt\x8b%Z/\x9c&\xe4\x8b\xec\xa9\x19u\x9b\xc0/s\xb2\x88\xce\xb1\xb0]\xbd\x0c\xc6\xb7W9Y\xcc\xc0\xf9K\xf5\x12\x8e\xc6\xa2\xd9\x8a\xde0\xda\xa1'\x1a\xb6\xfe\xdbR\xb0&\x08&\xca\x8f\xfeM\xe0\x1bVUDM1o5\x0c\xfa?\xa5u\x9cv\x01L*\x0b!J01\xc9\x1eHm&\xad;\x03\xe5[\x83SI_\xa4\xb3\x12D\xa4\x04\xc7Z\xe4\x10\xd2\xc6\xae^\xc9\xcd\xfa1\x1a\xbe?i$.H\xbcS\xfe\x077VQ!\xb0=\xaf\xff%\xf9\xc4\xe5\xf9}\xde\xea\xc7\xe5S\xf964\xb1\xa8\xed\xed*'\x91\xcc\xc3\x98\x8fb\xe4\x9e$\xc8\xdc\xc0\x1e{[V\xe4\xbf=\xab\xd7\x8a\x81\xd7\x1d8I#\xd7\x83\x89Y\xc7\xa1\x9b\x98tJ\xcev\xe2\x9fc\x8fnE\xdd\x99\xc3(\xa5\xe6\x0c1\x9a\x99\x81\x87J\xffB\xa2\xe5\xaa\x9cAN\xb9\x9dy\x1a\xb3,\xa4I\x9a\xaf}m\xfc\x9ez\xec\xb2\xe4\x00j\xf0\x96wl\x9c\x06\xef\xaad\x04\x94e\x1b\xee\x05l%z\x08\x9f\x0b;\xe9\x83\xce\xca$\xf6\xe7$\xc6\xf3HQ#|\x0cI\xdbT\xbc\xb3/\x03(\xdbW'\x1f\xb4\xb0=\xd8\x1c\x1b\xff\x05\xd7B\xcb\xf84Y\xa4o\xf2\x18\x8f'\xfa\xfb{\xbf /\xfdr\xa5Q8JS+\xa4\xaa\xd4\n\x91*\xb5\x82\xafJ\xad\xb0Q\xa5V(T\xa9\x15\xe2Vj\x05\xb4C\xb7\x01\xea\xdc\x0b\xdcR=\xdd\xbf\x16\xa9\x17zsn\xc5\x11h\xdc(\xbeD%5\xe1\x86\x9eY\xab\xb4\xd0\xe8x\xd8\xa95\xe7\x8b\xb5\xd3q3(\x16\x84\xb64\xd9\xe4jR\xe4\x9c\x00E\x1dx\xf3\xea\x19\x96\xc1-\xd1g\xc1\x81\xb7\xbb$\x80\xd11\xb6vn\xd1\x06\x0c\x85O\x8c\xa5\xd0\x9b\x05\xb8\x12l\x053\xc6\xc2\x00\xac\x85\x81\x98\x0b\x15\xf6\x86~i\x90\x89\x93\x01\x1aM\x00h:\x9e\xf3\x94\x9c\x7f\xfc\x01N\xb9\"\x10\x92-\x89\xe9\xc9c\x905\xd3\xfa\x0b\x14\x93-\x14|\x1c\x9a\xac\xfd\xc8\x08\xefc\xf2<\x87\xb2p\x16\xf1\x1fV\x8cL\xaa\x15/mX\x1e\xa3\x86\x8aq\x94.\x96\xf5*\xfc$*\xa3\x7f\x937y\x99%r\x90\xfb\xbb\x9d8\xc5\x14\x9e\x945\xd4\xb1\xf3L\xb5\xb9\xc9c\x1d\x10\xb3\xd3\x08\xee\xc4\xe4\xe5^\xa2\x0c\xa9\x83bR[S\xca\xd3A\xc7\xcc\xea\x83L\xee\x15x\xcdc\xee\x98\xbc\xcaV\xa8\xa6\xe1\xb1\x8e\x86\xd3\xdeh\xf99\xe4\x984\x829c\x085\x06\xbc\x9a\x19\xd4\x9cZ\xcd9\xd4\xba\x91\xb6\xcfA\x85\xa3\x8d\xfa\xa4\xb8\x949\xb9y8\xb0\xda\xfe\xd7\xedp(T\x87C\xa1:\x1c\n\xd5\xe1P\xa8\x0e\x87\x82\x1d\x0e2\x92_||\x92\xaf\xd7\xa0\x7f!\xf9\xe2\xb2%\xf9\xc2/v\x97 Z\xc6\x1cXo\xa1\xf8Zn\xa1\xeb\xc1_\xf5\xf7\xd6\x17v\xea\xcf\xb2\xb7v\xd6/4u\x0b\x8b4Ugp\xfa\x8f;\xf7\xae\xc7\xa6\x157\xffDB\xd1\x97\x94B\xda\x94BO0\x9f9K\xff`4\xe5\x03\x9fO\x1ed\xd7\xc8 $\x17\x06\"i\\\xf4&\x0b\xfd\x92\xb0\x86e\xc6\xdbO\x9e{\xe8\xd2d\xf2\x03K\x9d\x83\x82\xae\xa5\x96\xfdG\xa9\xd6\x90B\xe9\x8e\x13\xa7~\x18%K\x96\xd5\xb8\xf4\xf8\x9f\xc7\xa5_n\xb4B\"\xc5[g\xe1G1 \x07\xbf\x8bn\x85^\xb0\xc9s\x92\x94\x1cC\x0c\xd2\xeb\xef\xef\xb5\x82(\xba\xde\xb9\x1b\x0f\x0b\xea\xd1\x9e\xe5$tF\xdc\xdb\xb0y\xff/\xbe\xefk\xb3\xa07%W\xfa/\x8e\x0dmw{S\xfe\xbb\xaa\x1a\x7f5\x07$\x8e\x1f\xebU\xfaQ\xb2CN\xfa|XK rf\xaa'|\x9d\xce\xa3\x98\xcc`z0\xb4/N\x94d\x1b\xfbTCut$\x9f\x05\xfe\xba\xf2\xe5,\xf6\x03\xb2J\xe3\x90\xe43p\x18\xea\xc0\xfc\x02J\x7f\xa9y\xab\xbc\xc8\xd0\xbeE\xceu\xdf\xee%*j\x12M\xf5k\xd5\xc1_c\x8aS\xe6\x1b\xe2T\xd8\xe28\xa0U<\x84U\x81qs\x14\x94\xdcn\xf6\x81\x13x_O^*S\xf1R\x99\x8a\x97\xcaT\xbcT\xa6\xe2\xa5\xb2a%\xc53\xca\x15\xb4\xeeb`L\xa6\x89\x9cY\xe0\xc7\xa6\xfbR.,\xfb\xf8\\X\x08\x87\xf0\x84\xb7\xef!\xebAwO\xbb\xcf\xfa@\x1a\xe8\x84\xd7v\xf0\xa4yYse\xc0{\xa7\xe6\x96\xec8%\x11iK\xfb\xa4Wmn\x19|\xc4B\xa3K\xbf$\xd2\n\xae\xe2\x8a\x8a\xa30*\xbfO\xcfg\xb075\x12\x0bGI\xe4#\xc3.\x86+a\x80`P\x02F\x18\xc0\x13\x81H\x95\xc3\xd8?\xacq]4\xa7\xbef\x96\xac\xcdc\xaa\xd3dx\xb6E\x90\x8cD\x9boB;\x14U\xa2\xb7\xa1#\xf8d\xfel\x8c\xcf\x14\xe7\xde\xa34)6k]\xfeD\xa8\x9c\xd62?\xf7\xd7z@\xe6\xb5\x16\x15\xbcf\xb6\x1e8\x1a\xc2\x1eC\xe5\xb7\x96\xf9\xe5\xea\xb9E\x9a\x8e\xcd\x003\x0ep\n\xbfq\x9d\xefYE\x1c\x0dk\n\x9c\x82o\\\xe759/\xbf\xcb\x89o\x02\xcf\x18\xf8*Z\xae\xe2h\xb9*\x1f\xa5\xa1\xd1\x81,d\xef4R\xf0\x99\xde@\xef\xed\x08\x8bg\xe2Z\x91\x92\xe4\xbfD8[\xfe\xf7\x17OC\x92\x94Qy\xe1\xfa\xdc\xe7<\x1fyu\xd9\x94\xc2\x19s\xd3\xf7\xb3\xa8(Gn\xf7\xc8\xea^[,\xa7\xd9\xe8\x1c\xdb*\xae\xcf?\x9a\x93\xdf6\xa4(\x1f\xd9\xf7~\xddBb\xfai\xc4\xccN*Wq[\xf8,\xc8\xde\x98\xd5\x8c\x0c%\n\xd5\x03}\xfbK\xd1>\x12~=\xec\x05\x1c\xc2\x92\x89\xc7z\xc09\x02V\x07\x85\xd1[\xed\xca\xaa6\xcf\xd3\xf0b\x82X`\xf0zpB\xbf\xf4\x19\xe4\x04c6f\x907#8\xec\xdf\x8e\x92\xfa\xdd(\xd1\xd5\xfc\x1a\xc3\x9c.k\xaa\xa9\xae\xb9\xd8m\xb0\xa7\xa7\xc8\xf0\xc3\x0dpW\x0d\xeb\xa3\x03Q\xb2\xf5\xe3\x88e\x070\x0d\x8a\x93\xdf\x0b\x03\xadk\x8b\x0e+? c\xf2\x82\xdfT\x8f\x9d\xee\xbc\x0b:z\xd5\xc8\x8d\xce@\xaa\x91\x13\xab\n\xa3bp\x9a\x1ej\xca\xae\xee\x8e\x86\x13\x96\x91U_P[\x87\x11\x97i\x9b\x84Q\xa9mX\xd5h1\xa0\xc19\xa6\xa0(\x13\x08\xfc$ 1H\xd6\x86u\x04D%\xb50*\xd5PF\xeck\xa4\xa9(\xd3\xe52&O\x05\x99\xd1\xef\xbc\x87\xe0<\xc2\x1ebG\xe8+u\xd5\x02\xcd\xd2\xb3\x0c\x0e\xa6\xf9X\x95\xeb\xf8 \xd6q\xd8i\xbe\xdb\xf1N\xceKq\x8c\x89L\xb4\xc0\xca\x92\xa9?`\xf4U\xe3\xf8\xbf\xd5Oo;\xf1\xad\x89\xeb\xa9(\x81\xc1\xf9Z\x81\x9d\xad\xe4\xcb\x9a}\xa9L\xea\xd4\xbb\xab\xf0.k\xc7\x9c\xd4\x87\xd1\xaay\\\xf6D\x1eq|\n\xdf8m\x02\xe0\xf6\x04\xe0\xf8\xba\xef\xfd\xfe\xbe+\xbfW\xf3\x17\xca\x1f<\xaaz\x10V\xcf\xdf\xb7\x95\x03\xdb\xa6x\xda\xe5\x97\x9b\x98y\x05\x89\xd9\xfdY\xcdLDU\xde\x10T/\xa5B\xbd\xa4\xd0\x1cQ6\xf9\xe6\xf9:\xbe\x19y%)J*\xceJ\xe1(\x83\x8c\xcbf\x02D\xab\x08<\x84\x84\xc7\x80\xd0\x9e\x9e\x9e\xafYu\xb0\xe6M\x99\xe7P\xb4\x00\x97w~\xef\xf0\x10\n\x9db=\x86C\xd8C\x8e\x0f\x93\x17\xfe\xfe\x9e\x8e\xb2\x903M\xc4+HyLY5W'\x1c\xe1fW\xd4\xb0\x1e\x8d\x9b9\xf1\xf5\x9eH\xc5?\xd7\xb1V\xa1\xd7P\x06(\x12\x9cK\x94u@\xe2\x82\xe0\xdc\xb6\x92\xf3\x17x\x0c\xb8\x0e\xce\xb1\xaa[\xfa.i\xbb\x83L\x88\xacEMc\xda\xcf\xb5)\x0d\x17\xf8\xd97\xad7\x14\xd1I\xafXvK\xb7\xe3R\xae$J\xbcE\xe2E\xc9\x82\xe4\xc7X\xe2\x7f\xe4\xe6<\xdaF\x9dg\x8d\xbe\xb7\xa0h|\x8c=\x16/\xa6\xa8\xefT\xcc\x07+\xb0\xf0K\x1e\x95\xe4E\x12_H\xf3]*\xe6EL{kf\x14\n3\xa1\xf7Lj\x19B=~\n\xf4\xcf\xb5\xa44\x99q\xaf\xf0}\xa2\x90\x90\x0d\x8bOw\xd1i]bc\x0c\xa9|\xdc\xa7C\x06\xee\x92N\xed\x0e\xf8\xe3\x0f\x08G\x0c^\xfa\xf96\x03>\x14\xedl\xe8p\xde%\x98\x89\x82`\xa6\x1d\n\xac\x82\xa3\x84=\xa7Bl\xcb\xe0\xea\x95y\xb4vYA6\xbd!\xb6\xb1\x85\x95ek9\x99\xe8\xc7\xba(\xb0\xb3\xc3J\xea\x8eUh\xa8\xa6k\x0c3+\xd9\xf8;v\x8aURc\xbe\x14^\xc2\xfc\xa8\x0c\xc9\xef\xe5\x96\x8e\xeb\xe9J\x7f\xdd+\x10\xd0\x1f\x0f\xee\xdf\x1a\xfd9\x8a\x10\xfc\xf9\x1c\xc2\x189|\x92\x06\x9bK\x96 \xe2$\x88\x15\x94\xa1\x1cB\x98\x068\x0e\x8f\x9c\x93\xe0Q\xba^\xfbI\xe8:A\x9a]\x98Sd\xc9\xa8\xd4\x07\xf3\xcc\xf0\xb8\x12R\xcd\xb4\x95\x9ck\x88\xeb9%W\xe0\xfd\xae\x0e\xce\xac\x8bK:\x8fX\xee&\xd3\x17\xd5T\xb2]\xbf'\xa3\xd2dQ\xaa\xb3\xcb+\xdb)\xc9y\xe9\xe7D](\x11P\x14CTj)\xbb\xf0\x8ezrs\xe2\x87\x8c7b\xb6q5dk$tZ\xd4\xa0V\x89A[\xc52/\x91\x0bT\xb0E\xf2)\xfd\xa0\xe6\xf7\xebP0\xa7\x7f(m\xe8\xa14\x95\x9dJ\xf4\xc9\xf4\xbe\xecX\xa2O\x1eLUqlj\n$\xbc\xd1N$\xa5\x08(\xe3&\xab?U\xd9|\\gE\xfc\x90\xe4EW$\xa5\xe2h\xe9e\x9bb\xe52T\xc3\x84\x9d\xec\xef\xc9?\x9d\xb1x\x9d\xe5\xd1\xc5\x18N\xfe\xf8o\xce\xdf\xb0zf\x9d\xa1\x08n\xc0\xdf\x9c\xbf\x8dx|\xf4\x06M\x12*V\x93\x9e\xaa{\xfbrTC\xb1Wa@\x0e$9C\xc5U\xe6\x17\x8a\x8dP94.\xc6h{\xea\x9c\x1b\xdd)\xf2HR\xe6\x11)\xa8\x90\x04{.\x16\xba\xa1\xc7i\xe6%\xe4\xbctG#/L\x132\xfa\x9a\x8f\xc2d\x8e\xc4L`6\xd6\x91\x15\xefZ\xe3\xc8\x0d\xc7p`R\xcfS\x9e\xedd\xdfP\xa1b\x8dPS\x89#\xa6\xb8(\x12\xad\x1b\xab\xff\x038\xdd\xd5\xde\xc2\x0dpf\x98?m\xcdW[N\x0b\xfa\x84\x00\x02\xbf\x0cV\xa0>Yc\x86\x11\xb8\xc2}{\xc1{XD\x89\x1f\xc7\xaa\x15V\xaf=\xbd\x98\x12%\xf3\xf8\xa1\xd5\xf8\xed*\x06`h\x0e\xf8\xd6\x89GP\xae\xf2\xf4\x8c\xbb\x07u/\xc9<\xfc\x97\xfa/\xfaA\x8e\x8a\xf34\xbc\x90\xa5\xd6\xa1 \xcez\x13\x97Q\xe6\xe7\xe5\xcdE\x9a\xaf'\xa1_\xfa\xcc\xd1\nG\xe6\xbc|q\xfc\x9a\xfd\xdd\xdd\xbb\x1aNa\xa9\xd9\x8f\xc0-|:\xa7\x8e\xb9f_\x82q}\xaa\xfdy:\xc6\x8c\x1c\xf2\xfd\xc9&\x057\xe7\xc51\xf9\x8d\xefN\xdas\xf7\x14\x0e\xe1\xac\xbb;\x97\xc6\xdd |\xf4G\xfd\x8dw\xca7\xacq\xfb\x01\xcf\xf5qd\xdc\x82\xc0\xb7\xe1\x91v\x1b\x02\x9e\x08|\x0f>q0h>J\x8a\xd2O\x02\x92.j\xae\xdb{\x12\xa1\xb0\xd0\xda\xa0\xe7t\x83\x1e\xfe\xffq\x83z\x89\xbf&\xf4\xef\xaf\xcb\x8b\x8c\x1c\xb2{\xf4'\xdf\xb9(P\xf7\xde5\xeem\x90\xe25X\xedq\x10\x98\xb4?F\x8c\x91\xdb\x05m6\x9f\x1e\x9f\xe8\xb5\x87\xc1\xfcg\x8d=\x7f\xa6\xdf\xf3`\xd94\xf0}x!\xf6\xfe|\xe8\xabe\x0f\x1b\x94\xb7#E\xb5 \x84\x97\x13t\x07uo\xfe\xeb_\xc9\xcd\xe5\x18\x1c\xa7\xab\xd8\xe3\xe3/e\xe5\xac\xdb\x1c\x8d\xcf\xb9\x93[\x8aJz\x9b\x8f'\xc4^7F\xefK\xcc\xca\x97\x98\x95O\x11\xb32 Z%B\x95c\xb0\"k\xab\x9a\xd7\x0dp\xab\xcf\x0b\xf1#29\xd5 c\xa0.K\x1b\xb3\x072\xbeD\xc1/\xa0#\\U_\xb0\x1e\x19\xe2J~\x0dCiZ>\x98\x97\xad\xe3-Q\xde\x148\x01\n\xeb\x1f305\xd6\xff\x9aV\xf0n\xba\xa7\xb1\xd0\x17\x8e\x82H\x9b\xf8\x10\xebr\xdd*p\xcc\xa3\xdb\x1b\xb3x\xfd\xf2c\xff\x00\xca7\xbd\xd2\xad\xea\xbc~_\x91\xf64\xec\xa6\x993;\xae\xd4N+\xbcW\xc3\x95h\xc6\x94\xa3M\x1d\x17o\xc5T\x0e\xf2\x98wF[\x89\xc5\\\xe7[Q\x8c\xdb\xa8\xf6R\x16\x8a\xe1d\x16E\x92\x01u\xfcL\xebdY\xb2\x9b\xf7\xce\xa0Z`\x85\xbd\x95 \xb6%\xbbM[jw\x05\xdf\xf5\x8c\xaf\xf9\xc2\xf7} \xbe\xef\xcfg`\xfa\x14gF\xcd\"\x99\xce\x0d\xcb\xb0\x82|@\x90\x00s\xb1\xa8\xc2\x17\xf91\xac\xd1\x96D\xf8\x02'\xf6\xe6\xd8\xd8\x82\x04\x9b<*/\x1e\xd3}\x1d\x95\xa6Z\xc7t+\xe5\xc6x\xdf\x98A\xf9\x9br\x95\xe6\xd1\xbf\xc9\xf7%\xa5\xb0{\xdd@\xb6\xe6\x15\xb0W\xc4Qx\x05\xf60\x8c\xd4\xe5\xc5&\xff\xf8\x03\xfd\x9d\xae\xc4\xea\xc5\xbax\x890\xda\xcd\xb0\x96\x8a+\x89\xa3m\xce\x86z\"\x02m\xd7\x9a\\\x91>\x84\x94u\\\x9b\xdf\xaa\xb1\xad\xd4\xc6\xae\xcaAX\xb7z<~\xbaJq\xf5\x1f\x9b\xeb\xea\x93zo\xc8\xe3T\x03\xb7ht4P\x1f\xad\xd7\xd9wC\x15Xj\xad6\xd9~\xf8\x80\xd2\x88\xfbP\x89*\xf4\xa1\xc9\x87\n\x1a\xf94\xd2\xe45\xbe\xcchD\xfb\x9e+n\xac\xd3\x90\xc4\x942\x8da\x8f\x07\xaaz\xe4<\xf3\x93\x90\x84#\xa1\xea0\xb8\xc6\n\xf8Y\xff\x13\n\n\xd0\xdf\xc3\xf2\xe9\xdd\x98\xb4&\x18iW\xb5&\x87\x89\x11&\x10S\xc8\xe3\xc8\x94\x1a*S\xb8n=ZE\x9f\xba-\xcd F\x99[\xac\xfeK\xee$\xd8\x86\xeaOI7\x9a\xf7\xc3\xf0^6\x11\xbc\x1f\x8e\x0d[E!9&\xf1\xe2Er\x84\xd3j\xe2\xc5\xf4+\x0d\x15\x1bV\xa1\xb5B\xe7C\xf7D\xd2\x89\x07\xac\xf6F\xdes\x0c\x85!\x1a\x90\x0f\xad\xfd\x11s\x80N\xf0\xf5\x94T\xa3\x19\xb4cw\xd8\xaa\xb6\xf3\xf0 \xb8z\xd4\x82\x98p\x08\x991\x956P\x98|\xaa\xe8\xcd\xfe\xfc\xb2U\xe8b\xae.\xdcl\x88F'\xc1\x0c \xea\xf2\xb6\x0d\xb5\xde*\x8a\xc3\x9c$\x943\xfa(M\xebB\x0d\xcd\x0d\xc9\xc2\xcc\xaasM\xc3Q\xdaxi\x05\x9b\xbc@\xa5[\x96F\x892_\x1c\xf4\xb0\xb7\xba\xcb$\xe7?\xed\xe0v\x1fX\xab\x92\x04%\xaa\x1368\x8c\x8b\x95\xed\x12\x1eP\xe4\xd4\xc7\xa0\"|\x17S\xf6\xcb\xbf Ar\x985a\xbb\x87\xa7\x91J\xf5\x85\x02\x990\xb0h\x1d\xd1\x92\xe8\xb5\xee\xc1\xee\xfc\xeey\xde\xfb\x0e\x89k\xb0C\x1d\xaf\x0f$O\\\xf8i=\x10GO\x9b(v\xdc \xbb\x14\x87~\xbf\x1e\xd2\xf83\xf0\xf9\xbb\x96*\xc11\xfb\xa10\xdc_g\xe5\xe0\xe7!\xc1\xf8A\x19m\xc9k\x7f>\xc8VZ\x99aC\xbf\xf4\x0bR\xa2G\x8e\xfc\xc8\xb6\x92Q\xaa^\xa8\xd5\x12\xbd\xdb\x97\x13JP\x13\x98,\xa2\xa5\x02\x8a\x89%\x86\xc0\xce\x00\x13QW\xb9\x86\x9fS\n\xfc\n\xf9\xaa(Y*E\x18G\xc4\xef#\x8b\x18\xa0k\x1b\x12\xef\xc6\x0d\x97~\xba\x02\xb4HS\xd4\x98\xc1\x98R\xf9\xaa\x8d\x99\xc4\x83\xefc\x0b/W\xc9j7\xb2\xce\xb0-^\xffIg\xafq8\xb5\xe0ly\xef\xc6XG\xee\xc4\xd1\x90\xefG%Y#\x9fY\xd3\x9a\xc3\xc3ff\x9d\xc6\xd9\xf2\x10\x1c\xbe\xb3x^\x96\xc1}\xd3\x07\xadt\xba\x16G\xc9;U\x860\xa8\x92\xd9\xf0$8\x8e9\x9dJ[~\xa8\x86\xa5\x1aDD\xc7{\x14F%`\x8c)\xcb\xbe\xc1\x1a\xe1wX\x154\x8dqd\xd7\xa5\xe0\xe7\xc8\xf5Z\x08\xda\xb3\x88'\xe7i5n\xbbBlTW\xb6>l\xc7\xd6\xb9P\xcc\xb1Y<\x92\xcb\x8c\xe8_}\x05\xe9\x18\x8c\xcb\xa0\xa9\x84\xa65\x071b\xab\xad\x94\xd2.M\xa2\xa1\xf55 \xd5\xa6;h\x1d\x06\xda\xc4'\xa4\xa6\x993\xd0\x14\xb3\x14\x14Y\x97\xef\xb4\xf7\xc0(1~\xdef\xa4\x05\x15\xb1z\x12S\xca\x9f\xf4\xa4\xb2H\xbc\"\x13\xbe\x162\xa9l\xc3\x1f\xf4\xda(\xf8\x83\x9eT\x16K\x0dL(\xfe\xb8qS,W\x1b\x98\x16\x1f_<\xcbl\xc53\xbd\xcfn>\x06\xbf\x7f\x92wy\xdfk\xe3\xb3+\x92\x84ozb\xa2\xc2g7\xed\x8b\x8az\x9f\xdd\xbc6X\x1d\xb6\xb7\x8e\x8aG\xcde\x89\xe3\x01\xabE\xc92\xca\x17\xab\xf4\xcc=a\x94\xb3p\xc6@\xde\xd2o\xf7\xe9\xc0\x989Q\x8c\xbb\xe3\xa5+f\xe9\x0dSH\x85\x1a\xdfN\xa8\xb9\xe6\xbc\xbb\x0dc\x9c6\xf8V\xdd!\x1c\x19B\x9f\x9a\xda\xf8\xe6\x92V\xc7\x05J\xb2Q\xdb\xdb\xb7\x03\xe2E\xc5\xf1*=K\x9aK\xdf\x80\xa6\x1c\xc0[\xccB\xa0?\xa0\xed8\x12\xa6\"\x9d\xa7\xe7J\xdeX\xd5L:\xeejX~o\xa9\xfbu=h\x1e\xb4\xc6\xe3\x93\x84Z\x0f\x8e\x90\x9d\xae\x9ax\xb5ZYY2'P\xf6\xa7\xa9]~l\x97]C\x16\xde\xa7T\xa3\x9f\xf5\x06v<\xabc\xe3\x19\x9d\xe1]\xc3\x19\xed\xea\x1e\x82\xf2\x10\x07\xbe\xad\xd0^\xe2\xf06)g\n%\xc6\x9c\x89^\xcc\xa0c\x84\x16G5\xe7\x02\xfc\xa2\x88\x96h\x931\xeb,\xaa\xe3\x806<\xfd\x1aJ\xf8\xa6w*|\x0d%\xa5\xfcj4\xda\xf2<6\xf5\xa1Pj\x82\xed\xaa&s:\xb4d$\xba]%\xfd\xf6V~\xf1\xe2,\x11l\x0c\xd3\x16b\x04\x02\xeeZr\x92\xd3\x13(9\xc9\xdf\xdaF\xc2B\xe3x\xef\xe3D\x1f\x01S\x1bw\x89\xea\xc4&\xda\xc3\x06\x9aCN\xd8\x81\x9a\xc07PV\xb3\x9b\xe8g\x17\x1a+\\\x9e$\x860\xc6\xdc#\xc9fMr\x7f\x8e\xe7a\xebO,&1\xc6\x9a\x88t\xd3o\x04\xd0\xde\xfe\x18x\xf64\xba$X8\xd1\xcd\xbd\xb3<*+\x88\xd1X\xc1d\x12\xfa\xc1w\xe4B\x1a!\".\xdb\xa0<\xa8\x17\xaa\x9a\xff\x92\x87\x9fh\xa6\xa8\xe27(\xeb\xe66P\x89\xee=^ \x12\xd3B\xe5\xbd\x9c\x84\xe2\xea\xf7\xe5\xbd;\xeao\xb3\xc8\xa8\x8c\xae\xd0\"2\xd5\xb9\xb2\xe2U\x80G>\xee\xb9\xa4\x19\x92Z\x8eD$dB\xce\xe0\xf5EF\x8e\xf2<\xcd]\xe7\x91\x9f$i t\xcf\x80\xcf\x8e\x18\xf0\x0b\xf0\xab\xd6T\x825g\xcbT \xf8\xa014c\x87At\x9a4{\xf9\x8a,HN\x92@t\x956\x08+\xbfH\xfeV\xc2\x9c\x90\x04\xd0\xe5\xd4\x8f\xa3\x82\x840\x81b\x93\x91\xdc\x1d\xb5 \xe8\xb0H\xa8+\xb9\x0f\xf5\xfc\xee\x95h\x97N\x11m\x1d\xd8;\xc4\xcc\x9dt\xf2\x90\xc0V\x13\xd2z\xc2\x98}9\x8e@c\x9e\xdc\xa8\xcd\xba\xf2\xcd\xb1$\xe5K\x81|/\x16nd\xe9\x1e\x0dR\x0c\x1c\x82'\x18\xa5.\x1f\xd2W_\xb1\xc21\xa8\x84V\xa0\xcd1\x9dlz\xe0\xe6\xa4((\xf6\xae7E $*W$\x879a\x1fH\xf3\x06\x1e\x8d\x81\xe2\x99\x037\xaa\x86\x14\xabB\xea\xedX\x9fQ\x8c\x87q\xb1s\xad\xfd\xaaa\x97\xd2\xa4(\xf3\x0d\xe5\xcdL\x96o\xbb\xf8\x8c\x9a2\xea\x8b'\xd0K\xd0\xc2\x996b\x1fX7+\xda*M\xc9'.\x05M\x1cq\x87 \x97\xcfT\xd1\xc2(x\x08\xd2\xfb\x1c7f(\xb9\n\xb4<\x94\x8a)n4\x86\xa62b\x0c)\xbd\xa5-\xd7P\xac\xd2M\x1cV\xef\xbc\xc1l\xa5\x96\x95\x03\xb4\x019\x82\xf5\xc0\xed\xa1\x9d\xd7T\"\xaf\xc2\xb70\xa5s\xd5H\xeeY\xf3 \xd3\xb7\xf0\xb0\xfd\xe7\xacg\x1a\xef^Q+\x01;\xdd\xd7\xaa\x02P\xd0\xa03\xcc\x9f\x81\xa5p}\x910\x1f\x80\x9a$\xbc#\x17\x85\x9b#WNZu(F#\x8flI~Q\xb3\x8b\xdaC\xae\xd1b\xe2E\x05\xf2Ac\xb6y\xb2B\xc9\x0c\x01\xe2\x14\x1e\xfd\xedn\xa2\xb9I\xd1\xcf\x94\x9e\x03\xfd\xeeiW\x12:\xddKO\xa8\x9c\x1c\x9d\x10m\xc7\xe4{\xa0\x8f\xb4\x94S\xef\x18\x06\xbb\xc73\xf1\x9e\xae\xd7\x1b\xdc\xa5\xad$\xc3p\x08\xd1\x18H\x83\x89\x8f4\xbc\x8cNa\x06R\xa5\x19\xb4\x07\xf2\x9e%\x88t\xf7E\xdd\x1d|r\xdd\xb4z\xa14WR\xca\x9f\xdc\xef)\xe9\"\xfe\xa4\xa7\xef\xf3\xf9\x83\x9e\xbeo\xc3\x1f\xf4>U\xf0\x07=}_\xcc\x1f\xf4\xf4}\x81T\xdf\xb7@\xf0\xa0s7\xe3\x1f\xb9\xd7t*\x08\xd5\x8a\xc0\xf0\xe3+\x02\xf5e\x8c\x86(\x02\x15\xc1\xfb=\x97\x0c\xad\"0\x96*\x02\x83J\x11\x18\x8f\xc68\xd7\xfb_\xc3\x02\xbe\x81\xf8kXP\x81%8Y\xb4\x15\x81\x0b;E`a\xab\x08\x8c\xec\x15\x81\x01W\x04.yd\xb2\xff=\xaf\xa9n#\xc7\xf1>\n\xdd_\xcb\xaa\xe0E\xc5\x8b\xef\x8eoa\x01\x87\x93\xdak\xa0p\xc6<\x1e\xc7/\x1cz\xae\x9c8a\x1d1\xe5\xbc\xed\xb5\xf3\x9e\xf7\xeeQ\xc7\x13l@\xff\x1c\xe8\xab\x86\xf0\xb3,\x11\xde\x15h@\x15\x8aN\xce\x8f4\xe7G\xbc\xc0\x93\x1b\xbe\"E\x1aoIx\xbc\x99\x979!\xeeI\xb50\x1d\x85\xaed\x85\\\xbar\xf4\x900\xa5\x17(Z\nU\xdb\xf4\x02\xb1T\xa1\xba\xf9\x04\nU\xbd*\xd5F\xe5\xca\xb2\x1d:\xfaa3<\xcf\xfd\x80\xa0\x8d\x18\xb8#\xb9\xaa=F\xb8,\xa9\x90\x1dE\xb4\xebb\x94$$\x9f\x18z\xa7l\n\x1d&\xad\xdb\xda\x0d\xe1\x9c\x12k' z}\xa4\x99#\xa7\xcc\xb5\x9d\xb1\xcb|\x96\xc6\x98\xf8\xec/w\xef\xde5h\\\x17iR\x1e\xb3o:Q\xe9\xc7Q\xb0C\x9a4\xf5`\xc2\xfa\x90jp\x893GG\x99\x1a/\xa9`^h\xa7(\xdd\xe4\x01\x99\xc1\x91\xbc\xbb\xa3Q\x8d\x80\xe7\x94H\x9f\x8b<\xd0\xe7J\xc3\xb4\x95\x0fw\xc7i\xcf\xa2\x8e\x1b\x0bi2\xd9\xae\xd1=\xe9dj\x80\xa2\xf2\xe4\xa9\x8b\xa7\x8e/\xd8\xf2,'\x81_\xea\x99X\xe0\x02\xe6\nm\xa9^T\xa0I\xf5\x1d~\xe8\x9d\xc7\xad&\x85\x9b\x1b>\x91)\xf3\x1f5\xaf-\xe5\xdc\x03?\xfe.\x8e\x96\xc9\x0c\x9c2\xcd\x0c\xf8I\xaf\x8cr\xff\xc9\xf2\x15\xf7\x9c\xd8\xf7\x0e\xc8\xda\xc03\x1amQ,\x026\xf3(\xfe\xff\x82>\x19p\x08\xce<\x8dC=n\xeaw'\x08\xad\x84&\x0d\x04\xb4I\xca\x86G;Vk\xa5\xde~\xa6=\xa3\xef\x17\xa7\x1c\x99\xee\xfb9\xe7dv'\xcc`K\xa3\xa0A\xa7r\xdd\xb0AIy\x80\x1f<\x7f\xd7s:\xf6sc\xee\xb1\x0c\x81w\xef\xb9\xaa\xcb/\xc7\xddT\x00\x16(\xc7\x03\xbd\xd0V\x99\xc0\x0dp\xf0WN\x7f\x9d\xd2_\xbe\xae'F7\x07!\x0f\x1b-\xf1m\xbf\x00\x83\xd5\xab!\x9b\xf1:\x84\x0d\xcd\x00\x86+\x9a\xdb\xe2\x0e\x02\x81\xa1%\xeeIa\xf0 \xe0Q\xdc\x0b\xb8\xa1\xb3\xa8\x8dd\xd62\xf6\xa46\xa8U\x87\xcc\x99\xf1\xb8\xe7'\xe4\xff\xfc?\xa7\xfdV\xf9\xb1\x0f\xa4\xc4\xea@J\xf9\x81\xa4&\xb2\x18\x8dw>\xe1%b\xbd\"\x8e\x02B{s\xa0,\x08+\xae-/\n\x99\xc2CH\xbd2\xfd\xf1\xb8\xfa\x81S\x9a\xf2 \xb2\x8a\x80\xbc\x0c\x19\x07\xb1\xaf,\x1cU\xac\xc9\x074\x99\xb3{\xf7\xee\xe9i\x07h\xe9\x07\xd8\x1c \x0c\x97\x92K\x92G\x18:\xc6\xc1d\x12l\x86\xda\xf1\xfc\xf3U\xbb\x10\xd4\xbc\xaal\x7f\x1e\xd3\x13\xefX0\x816;\xd5f\xce\x9do\xe0\xef\xf0\xed\xa59]\xc9Q`\"\xd75\xa9\xd6EuZ\xd3\xe9>\x8d\x1e\xaa\x8c\xb5$\xd3\x82D\x1f\xabA\x8c\xe4\x19Is\xb5\xb2\xbf^\xe5z\xa2\x0e\x0c&\xdf\xda\xae\xe8\xaf\x1d\x8am\x88\x197\x91,\x1b\x1f)\xa4W\x9a\xd8\xed+E3\xb0F5\x18\x82n G9T@\xa2\x89\xd2\xdc\x8c\x19\xd5\xa0\x81n\x06\xa7 #\xca\x01(\x92\xad@W\xda\xfc\xe9*\xd1\x11U\xaa\x03\xd0\xf1\xa7/\xe8\xd8\xb8.\x89\x8eL\x9f\xfd\x99\xa3\xe3\xab\xabD\xc7$-\x07 \xa3\x01\xad>\xbf#\x11\x0d\x14Wv\x02\xbe\xba\xec XW\xff\xba\x94 \xa0\xaf\x08\x0e\xe2\xb4\xd0\x94K}\xef\xec\xe0G\x98\x19\xfd\x08\x99\xe1\xee\xba9Pe\xca\xcc\x90\x99\xd4M*\xe2O\xa41\xe4\x99*\x86^z\x971\xa8\xdc\xbc\xac\xdc\xc6\xa0\xf2\xf42\xbbR\x01W\xe1G\x83E\xffd&\xf4\xb7^\x94\x84\xe4\xfc\xc5\xc2\x95\xa4\x12j^\xa6\xd8\xa0%\xcf\xeci\xe1\xfa\x03\xdci\xac\x1c\xe0\xd6\x03\xdcw\xcc&y(p\xe7\xb1\xd2u\xc4\x81h\x02?\x83C\xd8R\xd2~\xb98\x17\xd8\xc5\xbb\x02\xe0\n\"l`wg\x06`\xedo/\x13\xe0d\xd5GK;3\xe8\xe7C\x1b\x9d\x0b\xb5\xeb\x82!\xc4\xaf\xf6L\xf0\xe1\x9bC\xd8\x18\xc8L\xbf\xc2\xd3\x89\xe7yo\xb5#pN\x9c1\xac\x85\xdem\xbd\x9b\xae\x1b:\xfa\xeef\x90\xa9Y\xdf\x0d\xd6:o\xa8\xcc\xb5:\xbd7\x98q\xc1\x18\x97\x05\x95\xe2\xb96\xe2\x98\xfbF\x8f\xd0\x7fX\xaa\xab)\xec\xcf~l\xb4R\nX\xceB\xc9+\x1d\x8aK\x91\xcb\x8a=\xaad\xce\x0c\x1e\xee\x1ej+\x0c\xfb\x1a\x13&m\xa9B\xa9K\xc5\x1b\xb6v\xa3\xa0\xda6C4\x11\x01=\xd4\xfc\x12\xe9\x8c\xc1>\xa51\xb4\xa4\xd8\x80K\xb1V\x078\x0bvN\xb4\x9ex\xd0\x10f\x0d\\\x87\x9dh\x0e\xb5\xe8\xeb\x1bU\x1fcpZ\xf17\xad\xe7\xbd\xbb\x1dy\x14o}\xb6\xb1mr\xc93UI\x9e\x91J\xf2\xf4U\x92\xe7F%y\x16*\xc9S]\xad \xeb\xc5qRy\xd4\xcd\xea0\x9c\xe9\xfe\xe7\"\x80\xde\x9d\xd3\xff]?\x19TR\x14\xa1/\xf4)e\xd0\xf4\x03\xc8\xa0;\xe6\xf8\x87\xeb\"\x83\xdaH\x89\xc9@i5\xddAZ5\xcb\x8a\xfe0Yqc+\xda\x16\x18D\xdb\x0d\x15\xd1{\x03\xb0d\xc4{\xe8\x9f\\E\xa4\x18J\x07\xa0\x06S\x9f\x0d$n\xc4yP\x81\xce\xc2K\x8d\x83/\xd2|\xedk\x95\xb6\xc0\xb7#\x7f\xe1|m\x94\xaa\xb654F\xaa\x1a\xc0\xd7\xd2 \x15\x9f\xfec\xc8\xa7\xb1\x1c\x1c|\x03\\\xa8d\xe1vKR\xd6\x0bG\xf7\xb6\xfeE\x94,\xafL\xf2\xc6\xa9\x19C%\x81\xf3\x95\xb8\x02\x11\x9cw\xf1\xa7\xb4\xdc\xb9\x97\x17\xde\xca/\xcc-\xe9\xe7\xeb\x14\x8fe\x18\x83i.)Y<_\xc7\xe8\xfa\xb7\xfa\x0f\xd9\x13vS\x07;m\x0c\xe3\x84\x83\x81\xf1h\xae\xbd\xf3?\xff\x8f\xfe\xcf\xc1\x14\xe2\xce\x0c\x9c1\x1c\x97y\x94,\xddT\xe7M\xdaL\x94T!\xe8Vw\xe6\x9e\x99&\x83K\xaa[\x03\xa7\xdf\xf2II4=\xbc\x9c\xc2\xcb\\\xfa\xeb:(\xbc\xc6Pz\xe2}I <}\x86\xa7k\x91\xe0I\x14Qj\x8d\xc3&\xd3\x13?\x1e\xfa\xd8\x92T\x8f\x7f\xf6%*\xd9\xb4z\x8c\x87\xc0\x15ef\xe2{\xb2\x97\x0d\xc9*\x05S\xd9\xd9yI3W\x92\x1c\xf9\xa2k\x80|}<\x8be:\xd5\x94?\xe8\xe9T#\xfe\xa0\xa7S\xf5\xf9\x83\x9eNu\xc3\x1f\xf4t\xaa\x05\x7f\xd0B\xf2X\x8d\xe4\xf1\xc7G\xf2\xe0\x8a\xb2\x14\xa5*\x05f\xcf\xbbF\xa6\xc0\xcc\x87+0\x95Y\x8a6R\xc5edR\\~\xb2,Ei\xf2:\xbfH7%\xa6\xdfV\x03'\x1c\xf8\x91\x9f\x04$6\x00\xe7\xcc\xab%\xf1\xe71 \xb5\x01\xfe\x86\xba\xdd\xea\xb3\xb1U\xa8<\xbf\x98\xa4\x1buT\xb7\xb6R\xfb|S\x96\xf6Y\xd1\x9dy\x99\x00o\xef\xf4\x94\xfe\x11\xe0\x84\xd8\x147\x97\x1f\xcb\x94\x0fd\x93\x8aa]\x1f\xaa\x9f6\x1dT\xd4\xfc\x1b\x83\xf3:\xbf\x80\xa8\x84tS\x82\xccdfp\xdd\xd4\x17\xf7\xaeX#V\x12\xaak?i\xe1\xe7\x0c\x9e\xf0\x1d\xd0\xa8\x86\xd6\x01o`\xa8\x19\x9c\xe3\xe8\x0c\xf6jc!&\xc8\xa8\x0f\x95\xebYp\xfc\xcb\xa1\xf2\xe5P\xb9\xbe\x87\xca\xfc\"\xf3\x0bC\x91\x16\xe2E\xc5\xf1\x99\xbf\\\x92\xfc\xc0t\x94\xb0\\?\x1a\x12\x86P~\\\xa4\xc7\xab\xf4L{\xe2\x94\xba\xc3\xa0\x19XP\x8f\xd6\x0bVQ\x1c\xe6$A\xa1\x0e\xcb\xfc\x98?bG\xa6\xb7$/\xa24\x99d\xb9\xbf\\\xfb\xca\x13,\x1d\x7f\x88\xe6NO\xd7\xa4(\xfc%\x01\xc5\xfd\xc9\xc4_\xcf\xa3\xe5&\xdd\xa8\x0b~X\xcd\xa5\x12hu\xab\x0e\x0ey\x83\xb4\x18\xca\x14\x18\xc6\xe2\n@]\xea\x06\x13\xc7\xa8>\x94\x99\xdb\n\xd2\x90\xd4\xad\x15\x0c\xf5X\"V? \xa9\xa4a\xf9j\x9a\x91\xc4\xcf\"\xf6\xea\"\"qXP6 IK\x98\x13\xc8rR\x90\xa4\xc4\x8a\xd4+\x02\x85\xbf&\xc0\xf1\x1c\xd2\x1c^d$\xf9\xee\xe5\xd3\xc6\xb8\xeeY\x8e\xdc9\xdedY\x9a\x97$\x14\x0b*z\xe7\xe7d\xc0\xf8\xf8\xd4\xa0\xf0\xf57\xe7\xc0\xdbw\xfeV\xcdR\xb9J\x0b\x02\xe5\xca/a\xed\x97\xc1j\xc0g\xf9\xb4\xcd\xe0\x96\xb7\xef%l\xf6\xdcE\x9a\x039\xf7\xd7YL\xc6\xbb~k\x1f\xbf5\xf2\x1c\x11\xd3BI\xb0\xc5\x16\xd5\xee\xf3\x0f\xb0\xdf\xae\xdf\xf6^GE\x11%\xcb\xcfgs;\xafWt\x87\xa5\xdb($a\xe3u\x08SR`\xad\xdd\"#A\xb4\xb8\x00\x9f\x1eoQg'X\xef$\xbe#\xa3$\x8c\x02\xbf$\xd5\xd7$\x1b\xb9\xdd\x00|\xd9\x83\x97\x11\x10Z5I\xed\x85\x04q\xf2\xcb<\x0e\xc5\xa6\x96=c|\xca\xe7\xc7\xfd_c\xd5\xe5\xe0\xdc\xf4l\x97\x0c\xd48\xae\xfd8\xae0Q \x96\xe5\xf2\x9cm\x12\x9a\xd9u\xb7\x03\x07\x13\xb6\xe3\x7f\xafY\x92v\x8a\xa0\x8f \xc9\x9eE\xc9\xbb\xcf]\xbd\xdd\x18\x87\x0d\xb2pq]\xa9\xde\x96F/1\xe1\xa0$\xe7\xe50$\xf3\x8d\xb8\x93\xa4\xa8\xe1\x96\x88V\xb5N\x05\x1e\x1a<5\xa11\xd9^\x96\x93-I\xca\xc7\xacG\xae\x84\x92*\xf3\x9b\xae\xb0\xa2[\x89\x15\xddn\xb2\xf4N\x0c\xb4\x8b\xd9&=>\xdbT\xe9g\xa9n\x1f\xe3j\xf7\x1d\x89)\xb6\xb9\xb8+F\xacLk\x0b\xa1s=B\xe7\xed\x19\x94O\x86R\x8a\xe6k\x1b\xd9\xb0RJ UU\xc1\xf3u\x9c\x143pVe\x99\xcdn\xde<;;\xf3\xcenyi\xbe\xbcy\xb0\xbf\xbf\x7f\x13_\x93\xbf\xf4\xcf8J\xdeI\xdf\x9c>x\xf0\xe0&\x16 \x94\xbc\xabM\xf0\x93\xa5\x05rc3p\xfcy\x91\xc6\x1be\xf9{^\x05QQ\xbcF\x94?\xdc\xef\xa3\x7f\x17\x99\xd5\xd3J\x16\x85\xc5\xbc^\xac\xe7i,\x9d\xdamD\xce\xbeO\xcfg\xe0\xec\xc3>\x1c\xd0\xff\x93\x0c\x06\x0bNm\x928\x0d\xdeu\xd3\xd3\xe9z\x97\xb1<\xe0\x12\xa4\x9b\x81\xf3|z\xc7\xbb\x0f\xf7\x7f\x98\xde\xfe\xf9\x8ew\xf7\xd1\xf46\x1cx\xf7\xf6o\xc1\xf4\xc0\xbb{\xf7\x0eLa\xba\x0fS\xb8\xe7\xdd\xbau\x1b\xa6p\x97?\xbd\x0bw\xbc\xbb?\xdf]\x1dl'\xde\xfd\xfd\xe9\xa3\xfbp\xcb\xbbw\xe76\xdc\xf7\xee=\xb8\x07\xb7\xe8K\xb7\x82\xa9w\xb0\x7f\x8b\x0e\x07\xf0\xd9\x01\x1cx\xd3\x07\x0f~\xbe\xff\xc3\xed`\xe2\xdd\xb9s\x0b\xf6'S\xf0\xee\xde\xbe;\x99\xc2\x14\x1fM\xef\x05\xfb\xe0\xdd\xb9\xfd\xc0\xbb}p\x9f\xde\xbb\xf5\xc0{p\x87>\xbd\xb5\x7f/\xa60\xf7\xbc[\xf7\xef=\xba\xe3\xdd\xbdw\x00\xd3\xfb\xde\xfd\xbbS\xb8\xeb\xdd\xb9\x03\xd3\x07p\xcf\x9b\xc2\xf4\xc1\xea\x8ew?\xa0\x9f\x80}\x98\xd2\xcfL\xe8W`J\xbf3\xa9>swB\xbf\x13xw\x0enO\xbc\xe9\xdd{\xde\x83;\xb7&\xde\xbd;\xec\x07m\xee\xee\xcf\x0fh\x97\x1eM\xef\xc1}\xdaG\x98\xde\xf5n\xdd9\x80\xfb\xc0&\xec\xdf\x9d\xf9\x1f\x8d>\xf8\xca_\x9bu\xff\x93\xac\xe0\xf3\xe9\x01\xdc\xff\xe1\xfe\xcfw\x10l\x10\n\x7f\x82\xd5\x97\xe4\xb9\xb8\xc4\xe2\xdf\xf6n\xdd\xbe\x0f\xd3\xdb\xde\xfd\xdb\x0f\x82\x89w\xfb\xee\x03\xfa\xff\x93\xa9wp ~\xdd}p\x0f\xf6\x9fQ4\x98z\xf7\xa7\x0f\xe2\xc9\x81w\xf7\xce\x94\n`\x07\xdaW\xf0Q\xe3\x1f\x04\xa0\x98B\x1f\xc7\x07\xde\xbd;\xf7'\xb7\xbc\xe9\x9d \xfd\xf9\x00\x7f\x1e\x04\xb2\x97\xee\x8b\x97\xaa\xdb\x80\xb7\xc5\xcf\xaa\x83\xf7\xbd\xe9\xfd[1vor\xcb\xdb\xbf5\x0dto\x80\xe8z\xf5\x9ca\x1a\xed\x1d\xf6\x89b\xc2\xf4\x0e]k\xf1;P\xbe\xf2)0AY,\xf7\x12\xf8p\xcb;\xb8\x03\xd3\xfdgw\xbd\xe9\xfe\x038\xf0\xee\xdc\x0f&\xde\xc1\xdd\xfb\x13\xef\xe0\x1e\xffqo\x1f\x17\xf7\xc1\xbd\x07\xe2\x81wo\x7f\x8a\xff}p\xf7\x01\xec\xc7\xf7\xbc\xfb\xb7\xe0\x9e\xf7`\xff~@!\xbc\x83{S\xfc\xef\xbd}:[\xf4\xc5x\xd2\x80\x99\x08 \xfa\xe9)\xb6\x83\xdf\x11\xed\xd2\x15\xec4\xfcL\xf4\xf3\xd3\xce\xfa\xa4\x1fyy\x89\xa9\xbf\xe7\xdd\x9e\xde\x07\x9c\xf8\xc0;\xb8w0\x11\x93\xc6~<\xb8\xf7\x00\xf6\x0b\x9c\xcc{\xfbS\x9c\xc8\xbb8\x91\x0f\xf6\xef\x03\x9d\xce\x00\x97@\xcc\x14\xfb\x81/q\xa0I\x05\xd4XQ\xfc\x14N8[\x81~\x93\xb8\xf3\xe9t\xc7\xd8\xc1\xc9=oz{\xfa\x81\xe6\xfd6\x1c\xdcV\xcd;/\xcbqe\xd3\xfd\x00\xeemo\xffp\xc7\xbb\x7f+\xbe\xe5!)\xba\xf3\xe0\xd9}\xb8\x1bO\xee\x02\xfb\xdf\xd4\xbb=\x9d\xd0\x7f\x9eQ(\x98\xde\xfa\xe1`\xfa\xf3\xbdO0t\x16\xf1~e#\xdf\x87\xe9\xfd\xd5\xed\xed\xe4`5\xb9\xbd=\xf8\xf7\xf3[pw{\xb0\x9a\xde\xff\xf9\xee\x0f\xb7\xfe\xbd\xbe\x05\xf7V\xd3\x83\xed\xe4\xe0\x87\xbb\xdb\xff\x8f\xbdw[r\xe4F\x16\x04\xdf\xfb+\x90l\x9d*\xb2x\xc9d\xd6E\x123\xb3\xb2\xd5j\xe9\xb4\xd6T\xdd2\xa9\xfa\xcc\xce\x90\xacj0\x08\x92\xa1\x8c\x9b\x10\x08ff 5\xd6\x0fk\xfb\x03\xbb\x0f;f\xbb/\xfb0k\xf3\xb2f\xfb\x0b\xf3)\xfd%kp\x07\x107D0\x98U\xea\xd3\xe7LS\xb2\xca\x08\x04.\x0e\xc0\xe1\xeep8\xdc\xcf\xeb\x9d\x1d|\x1c\xc5\x84Q\x18D\xfd\xf3O\x07\x13\x9a\xa6\xfe6\xaa\x9f+G\xfd\xe9\xd9Y\xd5\xa6\xd47\x1f\x9e9\xce\x95\xd5\x87\xe9s\xc7\xb9\xb2\xfa\xf0\xb4\xbaCK\xf1\xc3\xf3j\x13\x81\xf3F\xa5\xdd\x9b\xa9\xba\x9e}\xee0u\xdddA\x80\x9f\x9f\xbb\x82\xedxq\x18\xc6QH\xf9\x8d\xce4\xad\x1c\xc5\xba\xd4$\x9ekP\xd5\x0f\xce\x10R\xee\x91+\xf5\x19\xdeX\x04\xd1\xbb\xf5[\x0c\xd7\x95\xd0}\x8b~\xd6_D|\xc3\xe0\xc3|\xa9S\xfc(\xf0#\xf6*^3rEN\xa6\xa5T<\x0d\x85G\x9d\xbeR\"(\x1e\xba\xaa'\x9d\x8aJv\x86\xa7\xa7\xe6\xc5\xb4x\x9f\xc4[N\x93\x9d\xfe\\x/\xa0S\xbd\xf7\x1b\xe7-\xa9^\n\xe6y=rrE\xc4}\xc2\xe2\x0d\xea\x8c\xfa\xa0\xb1\x19\xc1\xc1qOOWoP\xedL\xc4nIV\xe9\x89J\xa3:\xcd\x8b\xb9\xc9\xe6\xd7\xbb\xa6\x92c\x93\x9c\x056-\xad\x8d\xba\xbd\x1e\xef\xc1\xd5\xc9\x8c\xb3~0gK\x03O\xcaD\x1f\xae\x1e\xfe\xfc\xbe\xba\xa4`\x08r\xf3\x11\x95\xb5UY\xc5\xfb\xc5\xa6G\x84\x15*\x1c\x95j\xb2\xa0tR~\xa9Z\xcb\xfa+\xb80\xc9\x06D\xecx|\x0b\xfd\xfe\x8a\xf3\x98\xf7{\xff\x81\xc7\xd1\x96\xfc\x993\x85\xdet\x15\xb0?\xe3\xa1\xa4\x18\x11o\xc7\xbc\x1b\xb8\x9c\x7f\xea\xa1\x13\x8e\xea\xbd0\x8b\x9f\x18\xabF\x8d\x8cM\x1a\x8c\x88\x02[\xab\xe7!\x87V\xe4\xdc\xb0\xfb\xb4_\xfc6\x98lb\xfe\x15\xf5v\xb9-{m\xd5`sy\x99y\xb4\x84i\xc4\xa6\xcd\x1b\xd7Z\xbf\xbe3+\xc4\xd2\xaa\x10\xc6\xa6\x01W\xd4\xef\x8a\xb4\xde\xf93\x8a\xb8\x82\xc1\x87zj\xaa1\xa1\xfcp\x9dj\x06#\x8d\x99\x9e\xae\x18\xf29\xd5\x91\x16\xedU3\x1eK\xd3~4\x18\x91H\xd3\x89&@\xf4\xa1Z\xb7\xde\x01:!\xb6W\xd6\x94~@\x14\x86\xcea=\xe5\xf5\xa4RZG\xe4\x1b\xb3\xbc?\xe2\xb8D\x15\xbax6\xfa\xa0\xa1\xea\x06\xe2\x03\x06\x0c+\xee2l\xe0\xf7+\xe6B\xd1\xa7M\xe1u\x92 ?H\x0dC\xfe\x15\xf9(|\xbd\x81\xa1?u\x1e\x07\xf85%\xa6%\xb1)D\xfeE!\x01\x9c\x8e\xc4\xa6\x97[&~\xcb\x19U\x14<\xb6/\x0ebZ\xec\xb6\xaf$\xa7nS\xe3\xe0\xba\x9b\x98\x93\xbe\xe9e\x0e\xe1Hk\xfc\x03\x16m\xc5n\x04B\xca\xd9\x08D\x92^\xef\x82\xc4\xe3\xf1\xc5\x80P2\xbc\"|\xce\xe6\xfeR1@\xb6T\x8d\xf8\xc3!\xb6\x84]r#\"-\xcea\x1d\xfa\x8f\x0b\xf7x\x9a\x03>\x1c\xfa\xe4\x92\xc4\x17\x03\xd2\xc3\xa5\x80\x8e\xf3m\x17\xc85\xf6\xaa\x80\xa0\x06\x19U\x16s\x0ej`\x9a5\x8c\xc1Q#\xf0\x91\xb0s\xb2\xa3\xa9\x0bC\xd5\xa7,b\xa9G\x13\xf6j\xed\x92=U\x0e\xce\x92\x80z\xec\xabH\xf8\xc2g\xa9K\x12U\xd9\xb0\x9a\xdf\x8b0\xa8\x8b\xa4?\x17\xb4\xfa\x19J\"?e\xb1`o!\xa6\xd5a\xed~\xef2/\xf3rQ\xd8\x88\xbe\x1f\x95\xeb\x03\x95QG\xb2\xd3\xbb<-\xd4\xda#C\x92b\xf6r\xed\x1eR\xc4.5\xb2\xb9Xj9\xeb\x9a\xf4.\x13\xce^^\xaa\xe2P9\xed\xc3g-\x17\xc0u\xe6\xcbS\xf8zy\xaar\x16\x00 3\xd2\xebR\xb02\x0e\x1b\x16y\xae\x85=R2`\xe0\xe2\x0f\xdeH\x91F\x08\x1d;\x17\x8ekjkX\x1b\x8e\xc305\xeb\x93\x80F\xdb\xef8\xdb\xf8wu\xc9)Q\xe4\x9a\x86\xa9K(Q\xdf\xc1\xc9\x0c\xf8\x9f\xd1\x19'i\x12\xf8\xa2\x7f\xbaH\x87\xa7\xdb\xc1@\x87\xf2\x86H\xde\xbc\x1f\xe0\x12\xc6\x1e\xbe\xf5\xb2T\xc4\xe1\x88x\xf3\xb3\xe5\xc0\xfa\xb1p\xe5\x99\xab,\xcb\xca8\xd4\xed\x17U7\x1f\xe3\xd1\xe3U\xef1\x19\x92\x1d\x0c\xbb\xdf\x8f\xfb\x9b\xc1@\x8d\xf8\xe3\xde\xe3R)\xa7)ia\xc6\xd5\xbc\xad\xd5L\xc1\x0c\xf6\xa3\xc9\xce\xdf\xee\x02\x88p\xf4\xe8\x11)\xbcj\xc3\xd5B\xca\x88\xcc\x133\xd90\xeb\x1e\x15}o\x80n)\xfa\xf6\xd3\xa0\x15\x83\x1c\x88\xa1\x87DK\xeb\xd9d\xc7\xe8\xda\x8f\xb6\xb5%\xd8\xbabv\xaa\x0d@\xc7\xdd\xb7l\xcf\x02\xecb\xb95S\xf1\x91k\xd1Yum\xad\xef\xbap\x00c\xda\x1bM\xeev\"\x0c\xfe\x98\xc1\xb1\xed\xe5\x8e\x93\xd3\x97=X\\;\xfe\x12<\n8\x87k\x95\x05\x01\x13o\x03?\x15\xdd T\x168\x08S\xa1\xa2#G#\x0b\x9a\xa7\x13\xea\xf3\x05\x0b\xbbC\x17\xf8\xd5Y\xca+\xa9A\xd6\x0cU\xe0\xd7;\x19s%\xaa\xad\xdd\xc3\xd5&\x98\xaa\xb9v2\xc0\xdee\x1c\xe8e\x03\x95\x93\x97dJ\xae\xc9c\x92\n\xca\x05\xaeP\xf3 \x96&FTu#L \xbc#'!n\x99\x04E\xb5`[\xdf\xa9\xcfE\x06!\x80\x0c\\\x93\x1e\xa2bR\x9d\x99\xbc\xe6N\xe0\x9a\xe1<\xe9\x17jW;\xe659\x07\xe1\xf1%\x05\x1b\x10\x03\x07R*\xce6\x06\x06\x0c\xf3\x15\xbb(\"\x8c\xc1\x11\xcb\x8cV+\xf0C\xba\xed\"\xb2\x9b\x01|LR\xee\x95 M\xb9\xa7\x01\xad\x8fS\xf6\xd0!oX\xbd~\xb85Q\xcf\xfa\x8f \x0d\xf4hc-4P\xf3\x80\xcc\xd5$\xa0]1.\xe1\xc7\xbd\xc7\xeaO\x86\xeb\xbfH\xbf\xc9i\xaf\xb0\xd0+#\x04\x11D\xbb\xd3C\xc8^'\x16X\xcb\x113\xd5T\x8f\xe2\x81G@\xa3\xb27\xd5r\x0c4\x0d\xf5\xac\xe2\xf5\xfd\x11\xd0\xa8\xecM\xb5\x1c\x03MC=\xfc\x08Pxm\x9e\xf9Q p\xd7\xa8v\xa2\xd8\x1d\xb8\x94\xd8i.E\x03\x7f\x1bi\x0eu\xaf\xd6\x8d`wb\x0c\xa93\xa43\x98\xa3\xca\xac\xea\x90\x1d\xd3\xb7]\xad|\x1d\xe5\x1e\xda\xb3\xf5G\xee\xd9qh\xbc\xae\x96O\x05\x8f\x1d\xa2jc\x15\x98\xbf\xa1\x96# q\xd7s\x8c\xe0\xc5BG\xe9# \xa8\x97_\xb3\xa0{\xf3k\x16\xb8\xca\x1f\x01\x80\xa3\x06?J\xbbC\xe0G\xa9\xab\xfc\x11\x108j\x08)\xaf\x0b\x15\x8d5\xa8\xdc\xce\x1a\x8e\x00\xc2UG\x9a\xad\x0e\xad\xb5\x1c#\xb3U\xf3f\x1e>V\xebN\x8e\xa8;i\xab\xbb&`\xee(_\xaf\xb4.\xf1\x90D\xa1\x1b\xa9\xec\xa4Vj'\xb5\x88P\x12\\9\x88l\x1ao\xc4\xd1M@\x81\x94\\whM=\xd6);\xbb\x13\x1d\x07\xad2T\x95\xf1\x11a`N\xcb\xbaTV\xac\xaa^\x93\xa0\xdb\x0f\xae\x87\xaeVu\xae\xd9R\xd3\xe3KU\xe2\xa0\x14\xf7\xf2\xb1\xa3\x99#\x16\x85\xca_SB\xc5\xb1\x88b\xc1\xder\xb69\x04\xad\xe1D\x7f\xc8\xc2\x15\xe3\x08\x9f\xbf&C2\x1dLD\xac\x1d\x938N\x97\x95\x88\xdb\xdbD\x9cm\xc0\x10\xdb\xc9\xc4P\xea\xcdV\xdf\xac\xc9Kr\x06G\xa6\x9c\x0c\xafHof\xf5\x0c\xf0u0\"\x8f\xd5\n2\xea\x1f\x03\xffX\xd5\xfe\xd2\n\xfd\xbf\xdeD\x8fuL\xdf\xc7=\xe2\xaf\xaf\xac\xc4\xff\xb8\xf7rn>\xf5\x96Jxw.:;.\x80Y]wD\xba3eI\xf8\xf1\xe5\x8eW\xc1M\xc7)Kz\xb0N\x14\x1fn\xce\xa22\xc0\xec_\xa6\x0c\x9a\xaeeSY.\xe3\xa0^\\m\xa1\xa1|k\xcf\x8e\xc0\x9f8PM\x9dj@\xeaT\xc4\xd6|\x14\xea\x07>\xcc\x0fNX;j\xe1l\xd6\xa6\xde\x17,\xac-\x0e\x0b\xcc\x11\x1dt\xe9Kl=4\xf2v\xf1\xc1CE\xb3Fr|o\xefR\xd7\xc5\x105-\x06\x92\xe3|\x01\xe3\xabC\xb4\xa2\xde\x0d\xac\x90\xbf\xfe\xaf\xffM\xe1|e\xb0\xd6\xc7\xc8(\x0e\xcd\xd9\xfa\x08\xcd\xdbZ\xd4D\x9c#\xf6^\xeb\x9a\xb0\xb9>N>rC\x7fL\x0d\xc2Q\xc3Q\x02\xf3\xba\xb2\xe9+\x1f\x03\xa5\xe4\x8ad\xc5\xf3\xc3.\xcb\xa8_\xe4\xa4\x84\xf5]\xc4\xa9\x90}8\x8c\xc8\xcb+\"\xf4\xe9\x1a\x19\x93s\xc5\xc7\x15\x9b.+\xcaP\x13\x05\xd6\x07F\x0b\x85/FmU\xd2X\x89\xb9B\xbf\x82\xc6\xea\xac\x9c\xac\x99\xa5iU\x15\xafh\xcf\x8a\xf5\x9c\x97\xda\xd4 Z\xab\x85=Tip\xc5\xb9\xd4\xcf\xf78P\x03ri\x8f\x0f\xa1\xa9\x8a\n\xd5*\xd9\xecya\xaf.\xa7\xe4SS<\xa8\xcd \xf5\x03\x0f\xfa\xea\xc6]1\xb9\"\xf3\xda\x94\xcd{@\xa8{\xe8\xdb\xff\xec\xf9\xc0q\xf03\xef)\xden\xb2\xbcpg\xe1l\xc38\x8b<\x08\x13\x0f\x19?ug\xd4S\xaa3}\xe6\xced\xe9\xa2\xa0~`\xf2~\xde\x0c\xdc\xb9\xce3=k\x82\x0e\x8e-C\x16 \x03\xdft\xea\xce\x9a\x86\x94\x0b8\x06\xb49\xcf\xdd9\x03?\xba\xf17\xf7&\xd7\xd3\xc1\xb2\x94iy\xc4q\xbf\xc3z\xaahd\xc5\xcb\x84\xdc\x1ej+\x92pvA\x18\xb9$\xb1F\xc6\x0b\xc2\x86\xc3A\xa1\n\x8c$\x12\xcf\xd9r~\xb6\x1c\x11x\x98.]\xa6W\xc5\x03vm\xe5Q\"\x10.n\x84Gi.\xf8\x04\x9a\x02D\xe66X\x01\xa2-\x13\xdfg\x01K\xfb\xbd\xde``\xe1\x16\xe4\x92D\x17D(\xf0\xf9\\,\xfb\xac\xd1\x84\xe3\x03n\xc3\x95,A\x1a\xbb\xc6\x8a\x160\xd7\x84i;\x17\x1c\xcb:\xe1SC6\xb3\xd4\xcae\x01\xa9\x830\xb1I\xca=s\x88\xde?]D\xa7[\xbc\xf6:\x11\xdc\x0f]\xe2m\xc0\xf6,p\xde\xdeRm\xa532?\x1b\x91\xa9\x03?\xf3\xbb\xd8\xf32^\x82CWm\xc2h\x0c\x8f\x14X\xa3\xa2\xbd$\x9b\xb0h?\xb2\x1d\xff\xd8\xc6\xafO\xab\xb6\xaa\xdaJ\xe6y\x93\x91\x0c3\xa7\xb6\xbe\x0b\x0b)\x9c\xe6\xa6#\x12\x8c\xe0\x18\xbb~\x04\xfd\xec\x9c\x9c(\x82<\xf1v\x94\x7f\x19\xaf\xd9\x17\xa2\x7f\x96\x9f\x17\x8f\xa7\xf5\"\x9fO\xebE\xa6\xedE\xb4G}f\x1d\xe4\xf7\x96\xb3^{\x11j\x96x\xa1\x8b#2_\x0eF\xa4\x9f\xc1\xd5b:\"S\xe07gDJ\xf2\xfc\xb3:T\x19\xc8}\x8d\xcd\xc0r\x0c\xc8\x15\xa1\x93$N_\xd1\xbb\x11\x8a\x01\x8a\xc1]\x90\x94\\\x92@\xb1\xb0\xe9\x19\xd4L\x01E\x0b\xb5\xa7\x83\x0b\x92\x0e\x87naR\x873\x0c|\x8f\xf5\xcfG$\x1b\x8c4[\x86C}\xf3\x05\x9a\x1a\x91\xd4\xa0\xb9Y\xf4\xe4\x9a\x8c\xa7dF\xfa>l7\xd9\xde\xa7H\x07\xa5\xac\xa7)\xda8\x18\xe9;\xd8\xd0F%\xc7\x1c%Xo 2m\xe3\xc7+\xb2\x19(X\x1c\x14\xb0\x1bq(\xd0=\xf0'\x82Q=p\xa1\xb8\xccF\x0b\xb4\xa4~\xc9\xd8\xd2\xca)\xd2J\x9aKM\xd3\x12M\xac\x954\x0d8\x85*Z=\xde+\x89R\xd4\xca%\x8dR\x92\xaa\xc0J[.a\xcf\xfc\xa0\x03jY\xd3\x82\xc6\xe2\x82\xf0\x82pt\xd2\xef\xab\xf5\xed\xf7\xf9\xa8`R]\xa56\x88\xe3\x83\x8b\x01\x10 \xaeQ'68S\xb7\xd40\xbfb\xc3\xaa\xe4(o\\\xe1Q>\x14 \xde\xa1=c\xde=\x9bx\xc8[\xef/N\xf9\\6W\xcf\xa6U{B\xaa\xd3\xab\x86\xf8h\xed\xff\xec\xfc\xccIA\xd3\x9c\xbc\xd4\xccp\x14t\x9apB\xe4\x80\xf5\x88\xecFd?\"\xe1\x88l\xbb\xd1\xc5\x03\xa4\xf4\x01t1\xa8\xd3\xc5\xd4\xd0E\x0f\xe8b0\"g\xedt\xd1\xeb@\x17\x13rE\x02K\x17\x15\xd1\xf2\x90.n\xc8%\xc6p\xe8?=G\x8a\xb6\x86\xac\x15\xea\xb8Ac\x9c)R\xa4\xf5\xe0\x82lj\xb4\x12\xc8\x80\xaf\x00\xde\x1c\x80f\x0fM(\xc1R\xc7m\x1ca\xfc)\x03\xa4\x82px\xa5(\xc3G\x04\x0fZ\xb6\xf5\xed`\x1c7\xea\x91\"\xc8\xe4\x9a\xf4\xc3:`\x16(%O@\x86^\x0fSw\x83\x02|\x1a<\x07d\x17\x03\x05\x8c\x93\xad\xd8\xd2\x9a)9J[\xde\xb1U\xbc\xacoX\xcdtD\xbcA\x99M\xa4\x93|s2\xdf\"w\xa8\xa6\xb9.\xbe\xe8\xb8\x9c\xa1\xc3\xe4\x0d\xfc?\xecK\xe9\x8a7m>\x1eS\xf1[\x99\n\x10\xccB\x17\xb4\xc7\x8eR\x92\xb6\xa1>\x92\xff\xf8\xc7\xf3\x9f\"g\xf1\x1b8K\xce\x99\xfc\x1agr\xf2\x1f\xffh\xfe\xe3\x1f\xe2?\xe9/\xc4\x7f\xfcv\xfe\xe3\xbb\xf8\x8f\xff7\xe5?\x0fA\xc1F\xfc\x83\x01\x8fpw\x07n>\xec\x0e.\"\x97\x84_\x90H\xed\xe0JX\x01\x08\x16\xcf\xa3\xe5\xc0\xce\xba\x99\x07\xbd\x03\x11f\x00]\xbb\x10\x91{\x8b\xfb\xd7\x1a\x0d\x90\xcaK\xdb\x0c\x18\x80\xfar\xc2{d\xb5\xf4\xa4b\xf8LJ\x0b\xd9\xaa\xd5\x816\xb1\xfc\xa2\x9a\xddx\xd6B}\xb5\xe8\xdfz\xc5c\x17\xa4\x06\x85\xf5\xc7\x8cB\n$t\x85\x8b\xe6F\x1cF2\x0f\xe8\x8a\x05#r2\x053\x1cGUE\xfdV\xb9\xae\xe9\x88$Z\xce\x0e\x14IMM5}`'z\xfb\xcc\x06#r\xb2\xa9^$\xd2\x93\x9d\x0f\x05\x18%\x0e\\\xdd\x04\x04\xa4\x96\xe4\x95K\x8c\x0en\xd6I\xbeaw\x9c\xc348Q\xd1\xdbpo8\xac}\x06/Q\xb9\xb2\x83:\x15\x1an0\xa0']\xe0%\x0e\x98[\xa0%\xfa\nmK\x90\xc3\x96\x0e\x11\xdd)\xdc% *^\x93>lG\xe7\xcbAG8+\xb4\xbf\x19\x12\x81\x0eh\xda\x82\xcdv\x006\xeb\x08V\xa3\x8e\xc6\xfc\xac\xae\xc6eEh~\x06\xa0\x96j\xac\xfa\xa50\x8c\x1f\x0c}\x95U~\x8cQ\x1d\x8f\xbd\x06\xb8\xe0\xe2\x8a\x82\x1eh\x02\xd0&\x886\xab\xd7x\xfei9\xc8\x97]\x91ji\x83\xf5l\x80\xf2\x8c\x9b\xd3\x9b\xdcs[,\x97@\xac\xf6<_$q\xd2\xcf\x03\xbe\xc4\xf9\xbe3\x8b\x04\x9cg]\x17\x13fJ\xac\xe1\xa8%\xe5p\xa3\x87p\xb5\x1c\x1f\xba\xe6\xf0\x98\xee\xe1\xab\x0e\x0e\xd6Z\xc3|\x1b\xccj\x98\x12\xb7\x14\xe2#G-\xf6\xc9\x1ft\xa3\x84\xc4\xd1\xcbC\xb8u\x10q\xea4\xb2\x96\xd2\x0567\x95n\x83\xae\x05\xb2\nT\x1f$W\xd9d\xbb\xbf\xe6\xcd^\xfdruo\x7f>\xee\x0f\x16\xf3\xc5\xf2\xe7\xf7\xc3\xeb'\x93O\x16o\xe4h\xf6\xeb\xcb\x93\xc5b9\x00E\xf0b\xf1\xc9\xb4\xf71\xf6\x10\x0ey\xa5\xb8\xbb\xef\xb0\xb7()\xcf\x1a\xb6\x0dy\xce\xef\xd9\xf6\xab\xbb\x04\xc4]\xb8&\xd4\x7f#\xe7=\x08\xd2\xb8\x88\xfa\x83\xf9\xf2\xf1\xa27\x19\x9d\\\x8f{\xfafO\xaf\x87\xc1\xb7\xb8\xb9\xdb\x83\xa6\x82\xcbA_\x95*_t\xaeC\xd31n\x97\x9d\x804[\xa5\x82\xf7\xa7\x0e\xbc\x1cL\xd2\x98w\x0cN\xaa\xeb+\x9ck\x9a\x13@W\xbd\xa5\xeeI\xec\xdf\xa0\xff\xc9\x03\xc7\xa5g\xe4\xa3\xc2h\xa3\x82\x04_\xfa\xeb\x11\xe9m{j\xe7\xbb\xb1\x92Q\x9e\x17E\x933$\x98\xbb\x92\xc0\x1e\xa3\xc0\xee\xa6+\xd5\xed\xdd\xce\x9c\xd5\xba\xf3\x93\xe2\x86\xb2\xafH>\x14\xb0\xd2{eo\xf9\x12\xe8\xb2\x18\x8f\x9bk#\x06\n\xc1\xee\x84\xdeLP\xbd\xd9\x1b\x1c\xdc\x1b\x9a\x9f\xd5\x80\x9f\x8d@OF\xf3\xdd\xc6f\x12\xd0T|\x13\xad\xd9\x1d~\xf7\xb4\x0c\xb7g\x81\x11\x8d/@|\xdfL\xd8\x1d\xf3\xfa\x19\xe8-\n\xa5^\xa2\xfa\xfc \x95-\xfe4e\x83N5\xd3\xd9\xe2\xcf\x8a%\x99\xde\x98\x06#\x92\xa0>\x8d\x0cI2\x9f.\xf5\xe0v\x08EG\x0e\xf1\x99\xe2\xef=\xb8q>\xbeo\xd6L\xadc\x07\xb5\xb6\xc5\xb1\xde\xb5\xb8\x91\xcc\xcf\x97\x1d\xa2\xe7\x91\xc3\xf2b\xf1\xf7\xd0\xee=d\xeaT\x0f\xba\x15\xf9\xdb\xcc\xce!>_\xfc\x1d\xe0\xf9\xc5\x9f\x82)\x80\x05\x93/\x921I\xe6O\x0d\x8a6\xabR\xcc/-ho\xfa\x01\xb9$Y!\xe1!\xfd}\xc8t\xd9\x95\xf6K,\xa9\x12aT\x04\x0d(\x8d\x91\x98}\xdd\xf4\xd9\x08\\\x1b\xa4#bR\x04\xea\xb4\xdb)\xe6\x07 7&\xd5\x1cZ\x9c.\x86c\xb9\x98,&rq\x8d\xff\xc9\x93\x93\x93\x139\x1a\xc9\xf1\xf8\xb4~\x98q\xba\xe8\xf7=)B\xc9e2X\x0cN\xb7~\xfd`\xa3>w\xde\x8c\xf4\xfe\xfb\x7fsL\x11W\x1f\xfe_\xc7\x87D}\xf8\x7f\x1c\x1fD8#\xbd\xbf\xfe/\xffw\xaf\xf4\xa5\xc1\xda\xa6\x8b4\x95\xcbQ.iIk\xab\x8a\xbe}\x1a\xe4\xa5\xd2\xde\xa8\xc8\nS\xcd\n\xd3&VXc\xc4v\xd3\x94v\xe7\xc7\x19)\x97;\xcc\x96I\x91\xed*,\xcd,\xdb\x85\x95 gQ9/U\xafx\xd0<\xc8Oz\xfa=<\xa3\xb9&\x01\x99\x91\xc0J\xc3\xf1\xa8\xdd\xf6\xac\xfa\xd3\xd2\x97?\x17\x13\x11\x7f\x1b\xdf2\xfe%MY\xbfbtS\xfc\xa9e\xc6'\x82\xa5\xa2O\x07\x16^Z0\xbf\x18\x8eA\xec\xfe\xef\xff_oPH\x9d\xfc|>z\x0f\x1f\xfe\xfa\x97\xffZ\xfc\xd2\x9f_\x9f,\x07\x7f\xfd\xcb\x7f\x85\x8f\x9fL'\x93\xfa\xd7\x9f\x9f\xe9\xb2\x9fL\xd5\x7f\xc5\x0c#[\xef\xa8T\xee\x8d\x9c\xbf\x19/\x07\xe3\xf1\xb8\xaf\x1e\xe4'\x83\xd3m\x085\xfc\xf5/\xff\xfb'\xe7\x95\xbc\x8bt0\x1e\xf7\x17i)\xdb\xffV\xcb6\x7f3^\xa4\xaa\xd2>>\xd5\xb3\x83\xff\x96\\mM?\x8an\xd5\x12\x8d\xf9\xe3\xde\xd2E\x1c }[\xa7\x08\xa7\xf3\xf1\"\xc5\xdd\xd1\xf2\xd4\xb5\xc3\xa2m\x16\x8a'}a\x0e\x02\x01\x7f\x8d`\x0e\xd3~\xe2#\x120\x85\xbc\x85N\xd6\xdb\xc8\x0e\x98^\xdb\xad\x04\xd0em\x10k\x13\x914WF\x91<\x80\xde\xf8\xceM\x9b=\x92\x1d\x91\xfb\x11Y\x8d\xc8\xdb\x11\xb9\xfd0\x82t\xab5\xbf\xab&\xc2\xb4\xd2\xc4`u.\xc5\x9a\xccFaK\xaer\x88a\xe8\xb60tx\xfct;\xdf\xea\x9c\xe4\xf2\x8al\x06\x17d;\x1e\xb7\x9c(\x99_a\x0c\xb6\n\xb9P\xae\xd2\x9b\x14\xd8_\xd9\x15<\xe8,[\xb1\x19v\xe1\x82(\xc1\xca\x03\xc2\x18\x97vAz\xe3\x13\xe3\x86\xc7\x1f\x0c.\xda\x87\xd9\xfc\xc0\xd7\x07\xb9\"'\xb4\xafPX\xefN\xc6d\xaa\x05\xc2\xd4\xeeW\xa6#rO\xaeH\xef1NL\n\xa6\x89\xa0:\xc0\xb2\x01\x1e[']\xe6\xc3\xfcT\xeb{U\xc3zDB\xf57\xe9\x06\xb5\xf9\xc1\xa0\xb4\xcdc_\xcd\x83\x9a\xcaQeJ\xc9f\xa0\xa7\xf4\xa8\x06\x89\x06z7I\xfdh\x1b0\x18\x8a{\xd5R\xa1r\x95\xb69f\x18\x8a\xbf\x1c\xe0{rM\xfao\xe7;\\j\xc5\xe3\xca\xcc\x91<\";\xb46\xc8\x89 Z\xc4\xce\xcf\x97\x15\xb6\x91\xf5\x0b\x02\x80\x9e`G\xb9\xa7K\xd0&\x7f\x0c\x10\xce\x1e\x08\xc2t\xa9X^qI\x1d^+\xae\x9fj\xca\x8f2V \xbe\xd1\xe5WW\x836\xfd\xf6\xe4\x9a\xdc\x1e\xb3\xcf1?\x18\xc5V\x1d\xb4\xeb\x97\xc4\xe9\xcc\x0e\xddQ%\x11ug\xc4\x11\x07\xbb\xed\xa7\xf7J\x9b\xce\x85\xc0j5T\x8b\x03VH\xff0\x02\xf4\xfe\xfa\x97\xff\xe2\x8a\xa0\xea\xfa\xbd',H\xd9G\xad\xfa\xa3\xee\xc1\xc0\xc0\xbc\xea\xf8\x15\xe4\xa9\xdb\xdb[\xf9\x1b\xb9\x98-N\x17\xa7N\xb9\xc9o\xd4L\x9f\xbe\xb9\\\x9c\xd2E\xfa\xe4\xe5\xa9\x91\x90\xda\xc5#Z3^7F\xe8s\x87^CX\x0b.7\x06\xab\xce&\xe82\xaa\xf9\x9c*\xe3\xc1\x8c\x9c4\xc4\xae`!\xf5[>\x8b[_\x08\xc6\x9b+\xd7\xf2\xf2\xd7Q!0g\xd3\xdd\x16\xf3Ko}\xe1\xed\x14\x92l\x99x}\x9f\xb0\xfeA\xa1\xc1\xa3)#\xbd\x8c\x07\xbd\xd9Add\xc7\xacy%\xb2\xccH4\x81\xc8dl\xfd\x9a\xddu\\\xf60\xaa\xd0\x83?\xf1\xc0\x11\xf9\xa6\xfak:w*\xfe\xe0\xc2n{6\x1c\x08\x98\xb5\xbf\xaf\xa1\xe8)\x90D\x0cjF\x18\x96\xafTB\xbf\xb0\xa3z\xa3s\x9c\xfa\xa3\x92[\x9b\xa6\x9f\xe3\x0c\xcc~j\xfcb63Sg\x8ez\xb9\xea\xb4\xe8\xf2\xf5\x11\x0b\xfc\xe8&\x9d\x11V\x1f\x12\x9a\x89X}U\xcb\xa4\x1c\x93\xda\x15L\xea\xd8\x8d\x0co:\x80*\xeee\n;\x80:|jg\x12eA\xab\xe2E\xdf\xc3i\xd8\xe3\x14,\x95\xee]\x96J\xce\xb1\xaemk\xee;\x1e|\x14\xb6+\xa0o\xb9\xffX\xe7\x1f\xb9\xdb\xa0\x1eXD\x822);\xea\x14\x04\xea\xd1\xb7\xd0\xb5\xdc\x9d\xabr\xb6 \x9f[Vw\xfa\xe6\x92\xce_.\xd2\xa5a\x0d\xdb\x01\x1a\x87\xea+\xa3\xbb\xf1xD\xfc~\x9a;\x18P\x89\xc3\xe1@\xc9\xc6\x90\x0bR\n\x9b\xaf\xbc\xad\x18k\xcc\xcbv\x01\x9e\xe8\x0e\xac\xe0\x90Q\xc9\xf9}\x85\x1b\x14.\x13(\xf4F\xa1\x7f5\xc91\xda\xee:l\xaf\xf6\xa5=e\x08\x05\xfb\x81\x82yo\x15\x06F\xbc;L\xf1\x88\x99tOo\xa3\xd7\xd0\x9a\xde\x11np\xc7\xba!\x97\xb6Y4\xbe\xcdM\xdf \xce%\x15\xec[\x05\xc6~\xbeYN2\x1e\xa0\xa6J\xdb%\x1b-\x1a|\xd4;T\xf5Y\xb5\xb4\x1e\x11\xef\x18\x12I\x1e\xa4\x0d'E\x8dx\x90\xab\xa5\x93\x8eJq\x92\x0b{\xebN\x05 \xb2\xc0C;f\x1d\x8c\x1d\xd1;m\xcc\xab\x87\xbf{9}`\xd5f&T\xfd\x99\x81\xe8p.E\xb4\x02\xf3\xa1#\xf1\xd0)\xb6\x98\xd6\xbd\xec\x91\xd3\xfb\xf0>\x15h\xe0\xd1\xd0\x8d\xc7\xdd\xe1\x0b\xd0\x92\x1eP=!\xc3|L\x0c\x91\xe8 \x0e\xa9_P8\xb4zh\x9f\x1f:\x8fG \xf2\xd1\xf3w_9\xbb\xcaJgWY\xf9\xec\xca\x1b\xd9\x834}vu\xb0\x9d\xf6m2\xee\xd5\x0eV\x82\xe7\x1e\xe3\xf1\x05pI\xadM9\xb9\xb2\x14\x9a\xe0\xadmC/\xe0Sf\xac\xd7/\x06\x8a-\xdb6:\xed\xe0\xf6:(\xe2\x88\xf89z\xc4\xfa\xe6+\x1a\xc0\xd9\xe2U\x8ew\xfa\xe4\xa4\xdc\xa1'\xe4\x0b\xcb\xc7&?\xa6\xd5\x8fg\x93\xe9\xf3\xc9\xd3Jj5\xd3\x97qr\xcf\xfd\xedN\xf4\xbd\x019?\x9b>'\xff\xcc\xd96\xe6\xf7\xe4\x7f\xa2^\xbcJ\xc9\xe5\x96\xb3\xedo\xd4?\xe3\x1f!e\xe2\xc5\xe1\xcbj5\xaf\xbeyM\xbe\xf5=\x16\xa5l=!\x85\x18\x86j\xdc\xd28\xe3\x1e\x83X\x86\x01\xe6IOC_\x8c\xf5\xcb$\xd9%\x07\xa0T\x15\xa6\xb3\xd3\xd3\xad/v\xd9JAp\xaa B\x80N\xdbF\xe1\xb4\xf4\x0e[\xd1Q\xd9\x80\xbd\xddF(\x9e\xfcI\xf8\x81q\xb0\xae\x9d\xe2W\xac\xc4\x9c\x02v\x9c_\x94v\x9fe\xc6Q*x\xe6\x89\x98\xcfH\\_\x88\x19\x0fR\xf7\xb6\xb5eG\x9b\xeff\x1d\x1f#v\xfb\x1f\xfch\x1d\xdf\xba?\x97\xb7\xda\xae\xcay\xa6\xd6.\x9b\xe9{3\xf5\x1c\xc5X\xac.'\xd0\"\x0c\xbe\xa3\x14\x9d\xf8\xe9\x97A\x9c\xa2\x13\x9ck\x18\x89WT\xec&!\xbd\xebGj\xaf2R\xd2\xfc\x0cvK#\xa2\x1d\nT\xfd\xd5\x17\x7f\xa0KC0\"\xe1\x8b{\x0b\xc51e\xf1\xeeV\xab.\x86\x98\xcb\x8bfz\xf5N\xf0\x07\xc1[\xdbP?\x0dJ\xd0\xb2OGX,\xcc\xce\x8cnV\xa5\xe9\x04\xb7F|\xb5\\\xef\xddX\x8d\xc0w\xc1mc\x8c\xa8\xb1\xfaU\xbe\xb6\nj\x0bf\x02w@\xa0,\xc8\xf3=\x94\xfb\x17\x1a\xe8\xa8\x03] s\x15\xef\x02#,=\xf74\x14\xc1\xb7j8bb\x19\x95\x93'\x1e\x0d\x02\x13%FS\xe9\xc1(\x8f\x86te\xa3! rM\x04\x99\x91\x13\xbco\n\xbe\\\xec\xe8\xa0V\x08\x8c\xc7\x05\xf1\xa3T\xd0\xc8S\x85\xe2\x89\" \xaf\xe9V\x15.\xfa\x83\x9a\xd9\xd1}m\x89R\x7f0Y\xa9\xa7>+\xfaY\xea2\x88%\xd23k\x16\x05\xcc\xcf\xa8V\x01\x86\x9c\xbc\xb6\x0e'\x83\xcd\xb1\xa3\x94 \xe0TH\x9a\xe4\xd0\x0cF\x8e\xb3\x0cw\x17^\x15i\xf8q}(\x90\xffc:Q(f{QH\x9b\x141\xbf\x99T \xcb\x85\n\xd5c3\xa9\xd5\x1c\x18r\xc2ssV\xcb\x91!\xb3~k\xce^b\xc2P\xa4\x90\xe2&.\x83#f\xe6u\x81q\x1e719\xcb=f^\xf2RvZ\xbe\x80\xdb\x11\x85\xc5\xd2<\x1f\x05\x81\x05j\xb3\xef-\xc3me\x14l_\xbf6\x17(\x88,H\x05\xcd\xfbQ\x83]Jy?\"1p\x99C\x9e\xb3H>n06}\x81j\xaa~U\xc0\x1c\x19t\xd6\xbe\x7f\xe2\xf2\xaa\xfd9\xcfPIS\xb2\xabS\xfa\xa4\xabTp\xea\x89WL\xec\xe2u\x07d\xc0\xa0f=S\xae\xd7\x05\xe1Ph\x9e\x1d\x1e\x04R\x94\xc3\"\xe2G*\x9b\x98\xech\xfa\xc7\xdb\xc8F\xa3\x8fP\x14a\xf3hI\xd0#X\x03\xfb6\xb8\xd8\x05Fv'X\xb4\xee\x08#\x80\x87\xf2\x1f\xcb\xc5\xfbf\xe4\xaan\xe7\xde7\xdc\xcc)m\x15\x1a\x16\x98\x91\x18AW]\x1b\x9b^a;\xd1\x1b\x00\x93*\xa4\x90\x0e\x13L@\xde)\x14\xd2\x81F\x90\x99R\xbe\xcd\xc01V\x83\x843(u\x01\xc2\x03\xb6\xce\x0d-\x81\x07q\x19\xe9$\xcd\x12\xc6a\x01\xe2\x0d\xe95\x0b\x98`\xe5\xae\x8c*;2\x8a\n\x84\xa8\xd3\\\x07\x81\x9f\xa4~:k\xdd\xa2\x17\x7f\xd6\xa4K\xebh^b\x90\x04\x98\x83(\x0b\x02%VD\xe4\x9a\xf4&\x93\x9e\x12~1\xbc\xa21\xf6Rl\x1f\xf4\xfcc\x12Y\xd5\xf1\x90D] \xb6V\xecvDN%\x0f\x7f\xc19\xbd/x\xe8\xd25\x0c\xf2\x8e\x18eq5r\x83\xf9\x15\x96\xa1\xdd\xeb\xb0\xceG\"\xc4\x9c\xbb\xc0\x1aU\xd2\x95m:j\xc5\x87q\xfd8\xcb1 p\xff\xe5\x8bh\xfd%MD\xc6\xd9\x11\x03s\"&\xdb ^\xd1\xc0\x11\x9e\xf1\xcfP\xed\xf7l\xcb\xee\xfeL\xc2,\x15dG\xf7\x8c\x88\x1d#\x8f\xb7\x8f\xc9&\xa0[\x92\xb2Z`F\xf3\xcbG\xac\xb23\xbc \xb8T\xc1@\x8a\x81\xcf\x00}\xb9\xb9\x80\x1f\xf1\x08\"\xe9\xad\xd9\xdd \xdf7Eh\xbf\x82\xe1(\x8c9\x94Jl\xb5\xdf\xb2\x1b\x8az#Pw}\x84\xeb\\\xc6H\xb9Wf\x99!}\xec\xe3m+W\xdc\xdc\xdb\x9d/X\x9aP\x8f\xc1\x08\xce\x08\x04dr\xec\x0f\x8a\xfa\x8e\xc3\xdb\x02\xb7\xde\xc5\x86+\x8d\x18W\xa0\x1a9#O\x90\xb2\x98\xf2\xfa\xd5\xb7\x9d\xf0\xcanw\xbb\x80V\xdc\x96\x08,\x86\xa1UE12\xa5\xf95\nb\x95\xe6\x8eiMJ\xd2\xeb\xc4\x81S&\xbe\x10\xe5\xbdb\x87\xbbkzC\xa3J\xa6\xfd\xc1\x9c-\xf30\xba]\x1a\xdd\xd6\x1b=\xba\xc5.\xed\xe8\xce\xa5]\x1a\xaa*xtK\xad\x0b\xa9\x82\x829\xfeu\x01n[\x07\xae\xcb PU\x06d\xe8\xc2\xebU)\x0c\xae\xf9\xb9G\xe4K\xc5>\xbb\x8cH\xb1U=\x92\xfd\x1e0\xdf^M\xc3I\x1a\xe4\xbb\xf5\xbass\xb9\x9a\x0d\xd5hf\"\xa0\x82\xfe`\x94\xc7^\xac\x10\x14\xd4\xaf\xe9\xb9\xd0\xdc\x0bo\x11D\xe0\xf8\x1d\xefDr\xb5\x13W\x94\x17\xef/\x98\xc4\x0b\x98\xf4l\x92\xee\xfc\x8d\xe8+\x12<&\xb8\xed\xf7QrP\xdc\x9c\"\xc1l\xe2\x88n\x1c\x9d\x189\x85\x16\x03\xcfu\xc5\x0e\xce\xc2x\xcf\xfe\xee\x07\x8f\x16oX\x95FR\x0de\xbbv\x13\\p\xe2 _\xc0\xa8\xc3\xb1\n\x8e\xb7j\xc1c\xfdtD\x1c\xd7m\xc9!\x8d\xd9G\x9d\x89m}\xc9tY1\xb5\xe6;\x93\xe4\x1dM;\xcf\xbb\x15\x8e\xd0\x9a\xa3GzdX\x9d|\xb8(\xdc+\xdc\xa5\x81LL'w\x81(e\xe2\x1b\xc3?\x8f\x80\xaa\xc6\x89\x8f\xe3\x80\xae&\x8fk\xb1\xf3\x90\x1b\x1d\\\x87\x96J:\x8f\xa2\x16\xbcE\xe5`\xb2\x83\xce\x0f\xb0\xe2\x07\xc1\x0f\xf0\x96y\xef\xb2\x87\xd1\x95 \xaa \xf5\xdcb`2\xd2{\xd9\xcb\xa3\xf8\xda\x91R+\xbdwy\x8a\x05{/{\xcb\xa3T\xc7%\xf0:\x0c\x05\x8a\xcd\x96\x0bYA\xbe\x1a\xc5\xcb\xfc\xaaC\xa7\xd7G\xfb\xc0\xcd\x97\x87\x84j\xe2G\x84\x0d\x08sk\x03\x84\x16\x98\xc9\x90<\xc6\x08\x0b\xb0\xf5\xc0\xa8`\xed\xf4<\xa7\x16\xf5\xd1+\xa5\xbcW\xa2xMou\x84\x88\xfcQD\xdf\xceS\xdc\xa5\x89\xa2\xd6\xc9\xc8\xfcm\xbe?\x8c\xb4\xda\xa3-f\x06\x14\xe5\x1d\x98\x7f<\x0d@\x14`\x85\xd3+T\xb5\xe3X\xfe\x9e\xb3M\x7f\xd0\x82 ~N\"\xa0R\xedoZ\xcf\x04\xbb\x13\xfdBm\xa8\xb7oROt\x19\xbd\x02\xcc\x1d\x05f\xb3On\x1e9bm\x87Dc\x1e\x07(\xe6g\xf9:\xc2\xf6e\x8a\xbcC\xed&\xdb\xe6\x95\x1b\x13u\xa3K1\x1b'\xabA\xd5\x190\xb6!\xb9\"\xbd\xb7\xab\x80F7\xbd\xae\xaa\x942<]P\xae$\x81[-k\xfb\x12\x85\x93\x9a\xa1\xa5\x8dC\xd2\x1b#s\x9bu\xa4\xfc5\x8c\xe9\x02\xa9Uek`\xd7\xf1k\xadF\xae*f\x89\xbb\xd5\xbc\xc0\x11\xcd\x19b\xa2uT\xf6X\xce\xa8\xb0\x15\xbb\xc3@\x1e\x93\xef\xfe\xf8\xc37\xaf\xbf\xf9\x97\xaf\xde~\xf3\x87\xaf\xbf\xf9\xc37\xaf\xffc7\n\xe6<\xd69\x82\x8c\xa9\xf2z\x8f\x0f\x1a\xfe\xd3\xfe\xf5\xac7\x7f\xd3[>\xb9\xee\xc9\xc7\xf37\x8f\x97O\xae\x1f\xcb\xf9\x9b\xc7\xbd\xab\xcb\x97\x7f^\xa4\xcb\xe1\xe0\x14\x19\xdc\xe9\xfc\xcd\"]\x9c\xf5\x1e\xbf\\\x9c^-\xee\xce\xa6\xe3\xc5\xdd\xf4\xeb\xc5\xdd\xa7_/\x87\xa7\x134\x0fQ\xb3\xdb\xbf\x9e-\x16\xe9\x93+\xf5O\x0foM\xdao\x83\xeb\xde\xa8\xe8\xcbd\xaer+Vy\xd9?\xf9\xdd\x1f\xbf|\xfd\x1f\xbf\xfbj\xa0^u\xeab\x91\x0e\xf3W1\"= \xeeQ\n\x15\xaa\xcf\x83'\x86\xdb\xe2\xbb,Tq\xd9?\x85F{\xe0o\xe6t~6\xfe\x9c\x8e\xdf}1\xfeO\xcb\xfcq\xb6|rZ\xad\xb3\x0c\x81\xb0\xad\xa8^\x9d^\x17\xda\xcb\xf9\xf7\x88\xf4\xb6~\xcfE\x0b\xd5\xa0\x7f\xb9\xa3\x9cz\x82q\x13Q\xddhZ\xfa\x8f\xa2U\x9a\\\xc8G\xbf\x9e\xbe8\xbb\x90\x8f\x02\xa1\x9e\xe1q\x8b\x8f\xe7\x17\xf2\xd1OY\x0c/O\x9f\xc1\xbf\x9f_\xd4\xaf\xdb\xab\x1f\x989tA\xd8\xd2n\xa4\xb0\xf7\xb0\xf8Q\xb2\x8c\x98//PUzb|]\x82\xf2g\xfe\xf4@nE\x10ON\xc4A7\x1bAE\x93\x1b\x8f\x88\xd0\x9a\xbaf\xab\x81\xc0\xaa\x87\x91c\xa91Ut\xe7\x8bh\x0d\x93w\xff\x87x\xcdR0'\xf6At\xd1Zv\x7fD\xa2\x81M\xec\x17h\xfeWh\xa4\xa1\xca\xf5\xb5\x8f\x81\x81\xd6\x0d\n\xab\x1b\xa4M>\x86H\xe3fJ\x89wq!@\xc9\xa1\xa9\xf0\xaa\xc3\xd12\n^\xb7Q\xf0\xdc\xa3pD'4\xed\xf4\xbbP\xe5\x06(\x8e\xc3x\xad\xdf\x8dr\xb2Y\xd1I[\xba\xdd\xbcp\xf5~]\xaf\x8f\xc8*\xd79Z\x0eA\xd0\xb1\xf3C\xd3\x01{\xf89\xef\xb02\xa29\x07/\xb2\xcd\xd3E\x0b\x92t\x01\xf3\xd4X!\xda)\x84\xcb\xdc\x99\xf2\x91\xecg\x0f\x99\xba\xbaX\xd4(m\x14V\xc2\xd1'85\xc3\x86\xe2\xb2j\x11|Adh9\xe1\xb3\x92q\xc5\xe1Ds \x0f\xad\xa8\xaa!\x83\xcc\xef\x18Q5\x1f\xfb.H\xdc8\x12\xf9\x0c\x1e\x1c\x88\x0f\x06\xd9\xe0\xd4\x87\x00l\xf1\xf2\xe3\x81\xfb\xabr\x06\x87\xb4\xa4\x1a^\x9e\x8e\xb4S\xb0I\xffz\xe6G\x82\xf1\x08\xbc\xf4\xd1@Z\xf2\xe7\xc7\x91z\x01\x92\x14\xf3T2\x95-\xe1~\xcaR\x99\xecb\x81^i\xeee\xc2\xe35fO\xe5&\xce\xa25\xd4$\xfd0\x8cW~\xe0\xb3H\xfa\xd1:S}`\xa9\x0ciD\xb7\xb0VU\xb9\x84q%tI\xc1\xbc]\x14\x07\xf1\xf6^z;\xee\xa7\"\xa4\xa9\xf4\xe20\xcc\"_\xdc\xcb\xb5\xcf\x99\x82\xe1^\xb2u\xe6a\xf5\xec\xa7\xccO\xa0\x1e?J\x85/2\xc1dH\xf9\x0d\x13~\xb4\x95i\x1cd\x08\xd1\x9eb\x81T\xae(\xdfR_=\xc4\x99\xf0\x7f\xca\x98\\\xa1\xa20\x95j\xfb\xaedf\xe9\x05\x8cF\xf8\x10\x8b\x1d<\xc4a\x92 \xc6\xe5\x9a\x85\xb1\xc7\xa9\x90k\x9f\x86q\xb4N%\xf4\xdf\xf7R\xb9\x8b\x83\xb5\x1fmS\x19\xf8\xdb\x1d\xb4\x9fP.\"Us\x12d\xe1\n \xca\x92$\x80\xber\xeaC\x13{\x16)y4\x95\xd4\xa3k\x16\xdeK\x8fr\x06\xd0\xc4aB\xa3{\xe9\xf1\x0c\x06{\x1d\x87\x007\xbbK\xe2\x94\xad\xe5\x06\x9aI\xe5&\x88\xd5X\xc9-\x0d\x02\xc6\xef\xe56\xf3\x05\xe5\x00\x8e\xbf\xa6\xf7\xf2\xc6WX\x11\xc9\x88e\xa9\xa0\\\xc67~Do\xa9\xe4\xcc\xf3\x13\x96J\xce\"A\x03\xf5w\xef\xb3\xdbT\xa6;\xff&\xddQ\x89\xce R\x009\xe6B\xa6\xf7\xa9`a*\xe9\x96E\xde\xbd\\1\x1e\xf8\x91\xf4h\xc88\x95\x1e\xa0\x85\xf4\xe2\xcd\x861\x85/\xeb8\x95\n\x05\xa2\xadd\xa9\xa0\x82I\xa6z\n\xe03.\xe4&\x13\xab8\x9074\xdb\xb0H\x06\xd9]\xc6\xefeH\xfd4\x8ed\x18G4\xdd\xc90KY\x16\xca\x88n\xe3{\x8a\xb8\xa6\xa0L\xa8\xcf\xd5\x1f\x80)\xf6|\x1a\xe0\xa8\xdeKA\x85\x88c)|\x16\xad\xa9\x1a\xe1=\x0b\xe4\xde\xa7?\xb2T\xee\xfd \xa0\xeaO\xaa\xd0f\x1f\x03d\xfb\xf8\x9en\x99\x04\xccF4P\xa3\xbfN\xa5\xb7c4\x91\x9e\xdaw\xc85\x8d<&a\xd1\xcam@S5\xb2Y\xaa\xd0,\xda\xc62\xf2\xa3\x1f)L\xb4^\x0e2\xdd\xc5j\xd4\xe2\x80r)b5\x03\"\xbe\xb9\x8f\xa5\x88\xe3 \x95\xb7j\x8d\xca\xdb\x98\xdf\xa4\x922\x1eK\xca\x13*i\xeaS\xb9b\xa9\x90+\xff\x86\xc9U\x00h\xf9\xee\x9d\x1a\xdeDzA\xb6\x92^\x1c\xabU\x19'rCy(7~\xba\x93[\x7f#\xe46\xe3\x99\xf4\xa3M,\x7f\x8cW\xa9\xbc\xf1o}y\xc3\xd9Z\x064Z\xcb\xc0\x0fc\x19\xf8\xd1\x8d\x0cY\x94I\xb5\x18e\x18\xaf\xa9\x8ch\xc8d\xa2\xf06Q_\x938\x15\xf2\xa7$\x8e$\xf7\xbd\x9d\xe4\xd9\x8e\xcb\x94\xdd\xddK\xe1'\xa9\x1a/\xa6\xfe\x89\xe5-\x8d\xb6\xf2V-\xe7[\xff\xc6\x97\xef\xe2\x88\xa9%%W\xfeZ\xae|\x05\xf0J\xad#\xe9\xb1Xa\xb0Z\xaar\x1b\xef\xa5\x1f y\xe3\x872\xf4\x03\x191!\xe3(\x901\xdf\xaa\xe5/\x93l%\x15\xc0\x82\x052\x8bby\xcb\xd6\xf2\xee\xeeN\xde\xdd\xbf\x93\xd4\x93t-)\x93t#\xe9VR_\xd2@\xd2P\xd2H\xd2X\xd2\x9f$\xe5\x92\xa6\x92\nI3Io%\xbd\x93\xf4\x9d\\Q\xb9Z\xc9\xd5Z\xae\x98\\m\xe4j+W;\xb9\xf2\xe5\xeaG\xb9\n\xe5*\x92\xabX\xae\xb8\\\xa5r%\xe4j/W\xb7ru/W\n|\xe9y\xd2[Ko#\xbd\xad\xf4v\xd2\xf3\xa5w#\xbd@z\xa1\xf4\x14)\x94\x1e\x97^&\xbd\xbd\xf4n\xa5w'\xbd{\xe9\xbd\x93k&\xd7?\xca\xf5\x8d\\\x87r\x1d\xcb\xf5;\xc9<\xc9\x98d[\xc9\xb8d\xa9dB\xb2Ln|\xb9\xf9Qnn\xe4&\x94\x9bXn\xb8\xdcR\xb9]\xc9\xedZn\x99\xdcn\xe4v+\xb7jb\xe56\x90\xdbPn#\xb9M\xe4\xf6'\xb9\xe5r\x9b\xca\xad\x9an\xb9\xbd\x95\xdb{\xb9\xbb\x91\xbbP\xee\"\xb9\xe3r'\xe4.\x93\xfeZ\xfaL\xfa\x81\xf4C\xe9G\xd2\x8f\xa5\xff\x93\xf4\xb9\xf4S\xe9\x0b\xf9#\x93?\x86\xf2\xc7X\xfe\x98\xc8\x1b&o\xb6\xf2f'o|y\x13\xca\x9bH\xde$\xf2\x86\xcb\x9b[ys/o\xde\xc9\x80\xca`%\x03O\x06\xbe\x0cnd\xc0e\x90\xca@\xc8 \x93\xc1^\x06j\xa9\xca\xd0\x93\xe1Z\x86L\x86[\x19\xeedx#\xc3@\x86\xa1\x0c\xd5\n\x96a\"\xc3\x9fd\xc8e\x98\xcaP\xc80\x93\xe1^\x86\xb72\xbc\x93\xe1\xbd\x0c\xdf\xc9\x88\xca\xc8\x93\x11\x93\xd1FF[\x19\xf92\nd\x14\xcb(\x91\x11\x97Q&\xa3w2\x0eeBe\xc2d\xb2\x91\xc9V&;\x99\xdc\xc8$\x90I(\x93H&\\&\xa9L\x84Lner/\x7fR4M\xf2X\xf2T\xf2L\xf2[\x99R\x99\xaed\xea\xc9t-S&\xd3\xadLw2\xf5e\xfa\xa3Lod\x1a\xc84\x94i$\xd3X\xa6\\\xa6B\xa6\x99L\xf72\xbd\x93\xe9\xbdL\xdfI\xe1I\xb1\x96b#\xc5V\x8a\x9d\x14?Jq#E E(E$E,E\"\x05\x97BH\xb1\x97\xe2V\x8aw2\xa32\xdb\xca\xecFf\xa9\xcc\xeee\xf6N\xee\xa9\xdc{r\xcf\xe4~+\xf7\xbe\xdcGr\x9f\xc9\xdb\x8d\xbcM\xe5=\x93\xf7B\xbe\xa3\xf2](\xdf\xdd\x0e\x16\xab\xd3\xaa\xe6\xb47\"\xe8\xffoq\xbb\x1c\xfc\xa6\xbf\xb8\xfdy:\x9a>\x7f?0\xba\xcc\xb2:\x14r_\xcf\xe6\x8b\xf1\xc5\xec\xd1\xd5b\xb8\xf8d\xb4\xb8]L\x96\xc3\xdf\x14\nD\xf6\x897Ub4\xa3\xb6B\x94\x19\x96\xf3\xf1dh\xc5\x87\xe5p\xd6\xbf>i\xfa\xb48]\x9c\x0e\xfa\xd7'\x8b\xf5pqz=\xe8_c\xca\xb5\x13\x90\xbaJ\xb7?\xb9>E\xa5\xaej\xff\xf6\xf6v19\xbadsG\xad\xf6\x17\xd4\xc5\x8b\xb1\x05|\xf8\xe87\xbf^\x9c\xfe\xd3\xd5\x7f~\xdb\x1f\xc8\xc7\x9f\x80@Tg\xe1O\xbc\x0du\xc8\x11\xb3@\x8c\x0f\xaf\x03y\x12=\x1a\x7f\xe2\x81&-''Y\xb7\"\xdf\xb3\x80\n\x7f\xcfl\xb9\xcd\x81S\xc8\xa3/\xfa\x117\x99$\x87NX\x9a\x87\xd0\xd2\xf7\x19I\x9a\xa1\xb54\x7fF\x1cZc\xf3\x0b\xb1\xdf\x0d\xc1~\xba\x10\xf7vj\xd4E\x08\x81\xdb\xe4\x03\xe3bX!\xf9\x17\xa2_\"W\x87\xf8\xb4\x00$\xc6\x95r\xba\xe8\x9fn\x0f\xdc\xb7\x8fJ\xf9\x07\xa7\xdb\x03<\x1b\xb9\x80\x0d\x0e#%9\x1b\x90K\xd2\x07\xf2\x14\x95\x92-!?9\xeb8\xa6$\x9fs\x87w8\x976\xf2UU0\xeb\xaa\x84\xf4#pK\xd5(X\xce\x17\xb7\xcb\x06\xc1rG\xd3\xaf\xb3 \xc8\x8b\x9a\"-\x12\xbf\xa3\x9a\x8c\xfb?x;\x16\xb2\x83\x15\xb8a\xf8\x0f1_\x7f\xa90d#\x18\xaf\x023\x9b\xbfY\xa4\xcb'\xd7\xa6JG\x15E\xe6\xdb]\x1e5\xd3S\x94\x06tM\x7f2\x1dR\xec\xca\xdcb\xc94!\xfa]\xcc\xd2?\xc4\xe2\xf7to)\xf6\x1f\xf9\xefb\xa1\xad\xd3Z\xb2\x7f!\xbee4\x15\x7f\x8c\x98\xe9q\xa5\x8c\x9f~S\x9b\xcc\x9c\x92\xf5]\xe7\xf1\xce\x13\x89r'\xba,\xd7\xea\x82\xd3](\xce\xeb`~\xb6,\x1f\xac\xb6J\xf1\xbd\x1f\xe9\x9e\xa6\x1e\xf7\x131Cg=0\xce\xbd\xfd\xaa\x9c\xd8\xa5G\x87\x86\xbe\xa3\x89\xa0\x9d\xf1\x13\x86\x8e\xe7\xd5\xfa\x07\xfb\x00\xc7:@\x9fw89c\x13A\xdb\x1avO\\\xded\xbbA^\xc7\x82\x87\x81\x7f\x827&NL\x0f\x9aWQ\xcdW\xac\xf99\x91\xa7\x0d\x05\xbb\xa0\x92\x01\xf3\x84\xd9\xf1m#Q\xcd\xc09\x88$\n#P\xf8\x08\n\xf9Q\xf6\xcf]\x06\xef\x01\xc7\xbc\xaf\x8abS\xd7C\xae\xc2\xbe\x18Jv\x84-7\xf5=\x06\xc2\xa2\xc1\xa6\xb3T\xe3<\xc1\x8e\xc3q\xf6W\x98\xc5\x8fs\xe6\x87\x1ej;\x8e\xc2W\xb8\x7f\xe9Zy\xbe\x1f\xecX\x7fq\x94\xbb6R\xf4g\xfb\xc0\x06\x1f\x80A\x0d\x8d4\xce\xa7\xde\x8a\xfd-fT\xef\xd5\xba\xce\xe9\xeb\xf2\xd6\xaek3E\x0d\x00\x96\xed\xd8\xde\x83\xe6\xd88N\xd3\x0d\x82\xe74;\xe1\x0f\x87\xe2\xb8\x89\xef\xfd\xa6k\x93\x8dh\xf0'\xfe\x80E\x9d\xf1\x00\xf7S\xb9\xc2\x13\xc6\xc3(\x8d\xfb\xa8\x00\xbe>uY\xc3VX\x91\xad\xa2A\x1e5\xf9\xbf\xe3,a\xd1\x9a\xad?\x96\xedI\xc6;S\x99?\xf1.4\xa6tO'\xe3\x0dJ\xa2\"\xb6:\xf7\xb8V\x80\xacn\x9ak\x1f\xec\x90\x94}\xc3d0\xa5=\xed+\x10\xcc\xbdGM\x05!\xf4}G\xaf \x0f\\*\xd0\xb2qv\x9e\xfb\xf4~D\xc3\xe4\x02\xe21=\xeav\xcd\xea\xd85R\xbd6\x05\xed?tN\x8c\xbe\xae\xa8P(\xe7\xc3\x05\xd1\x07\xe7XU\xb5\x83\xa3\xf8\x9f\xcc\x12\xc2\x12\xf6#^`}\xcd\xa9\x1f\xf8\xd1\xf6\x87\x80B\xcc\xf6.\xe3S\xae\xb6\x8bl\xe4V\xd1\x97\x17\xb7\xdb\xe1zS\xf3\xeeAy8,Nb\xd1\x19$\xc7X\x1e\x01J\xef\xb4M\xe1Q\xd4\xe0\x1a\x87\xab\xe3i'/F\x8a\xfa\xda\x94\xf7#\xedh\x11c$\xf16?\xa5\x1a\xb0x\x92\xfb\xe5\x84\xbb\xc0\xf9`\xbc7\xbeeFd\xbe\xc4(>\xfd\xa2\xdbx\x1d\x8a\xeaC\xa3a\x1b\x8c\xc8<\x0fa\xde\x1b\x91\x1e\x04\xa4\x86\xf02\xea-\xf0S\xd1s\x85(\x9d\x973Bm\x9f\x7f@m;\xaek9?\xfb\x80Z\xe0\x93\xaeg\xdaZ\x8f\xbb\xbc \xcbm\xea8\xaf\xd4\xd1\x00;\xa3k?\xda\x9aBO\x1f\xd0pP\xa9\xe3\x99{\xf6v\"\x0c\xa0.\x93\xef\xf9\x03\xda\x12t\x15\xd8\x1e~\xda\xa9\x87k\xb6)\x0em\x15m\xdc\x85\x8aPA\xb1\xcf+\x81\x0d\x97\xee\x98x\xd5\x05\x8a\x14<\x0b\xacW\xb6\x8a\xcb){\xdd\x81\xa1\x1b\x1bF.\x89o\xaf)\xb0\xe1pP\xa8BG\x92\x9f\xb3%\xc4\xe7\x82\x87\xe9\xd2%\x8e\xd1@\xcc\x08\xe6<\x87\xf3\x85\xf9r\xa0\xa9\xd2\xa0BzrJa\x9fh\xc1\xad\x11\x04\x82\xf0\xdf\xb1\xaa\x835\x87\xe6\xcd\xf6E{\xfb-\x00\xbee\xe2\xfb,`)\x1e\xa3\xa3\xa3\x04\xec$\xbaH\x10\xe8\x10\xe1dzA(\xb9\xd4GHl\x12\xf8\x91j\x98\"Q\xbd\xf1\x93\xaf\xc2D\xdc\x7f\xebG,\xedS\x08m@\xc9\xcb+\x12\xa1\x17\xfe\x93>\x9b\x88\x1fv\xfeF\xcc\xe9\x12\xae\xdb\xac\x82\x9bo\xa25\x8b\x84\xfb\xfa\x13\x00\xccq\xe0\xe1F\x08\xd4\x12\xcf\xf9Ru\x91\xc2\xf1\xe6\xc9tpA\xf8p\xe8\x90\x130\xea\x85\xf0\xb7;\xa1`\xcfF\x84M\xfc\x14@4\xb0[\xbe\x90\x19\xb9\xaa\x8f\x9dQ_\x07\xa6\xa7y1\xda\xa86W\x8da%#2\x1c\xdaAB\xaa\xa1\xb9RB9\x8b@\xe8\xad\xd7\xda\x12\x0e&\x1f\xe7\xda\xe7\n\x9f\xcaq\xa5\xcc\x0420S]D\x0bQ\x8b%\x99\x82q*W\x1f\xb3\xb3\xb3\xcf\x9e/\xe5|\x91\x9d?;\x7f\xb6\xc8\xce\xcf\xce?\xd3\x89\xd5R\x01\x94\xca\xce\xce\xe8\xd9i!,X\x111\xe1\x8e\x91\x03+G\x84W\xc7P\x81\xe8#\xa2\xb9<)\x03\x02\x94\x92\xe1>>\xb3\xc7\x02\xd5\x9b\xf3\xc0\xe55\xab7\xc2I0\x02'\x10\xb98\x9b\x8eHo\x11\xa9\x14\xabU\\\x88\xde \x8f^W.\x9f\x15\x18p\x93Z\x1b\xd6V}\x0e5\x94\xd3\xb3\x82p\xf2e\xbcf_\x88~4 \xd7:,,F\xf9\xf3t<\x14\x08\xfe\xa6P\xbf\xa7j\xe8i\xda\x00\xee\x85)\x19\x13o@\xfe\x89<3\xc7\xb5\x90\x08\xc5y\x95z\xe8\xd5\x8c>\x15\x99\xf1\x07k\xe6\xc1\xdc\xab\xd54\xa4\xef\x8f\x14q\xf3#f\xfe\xbe\xa2w\x05\x024*\x05\xb4Al\x1fz\x1epZ\x86U?@e\x18kM\x9a\xeb\xae\xae\x96\xab\xdf\x8a\x00\x9c\x0dj\xa8X\xac;\xdf7\xfd\xaa\x0e\x08/\xbaUD\x1e\xd6\x1a<\xa0\xb8Y\xc7\xfa\xe7li\xd5`(\x11\xb0\xa5\xa2\xbc\x85.\x14=\x9f\xbd\x1f\x95\xda,K\x1a\xadM\xd7]\xda\xeb\xfe\xa2(\x87g\x8f\xfdC\x90]V\x00\x1b\xa0\xe8w\xe1\xea%k\x83\xfa\x87\x84zGC\x9cr/\x978\x0d\xd0z\x15\xd9\x0c\x85%\xc8\x1e\x0c\xde\x97;\xca\xd3C\xaezKn1\x9d\x00F\xf6\xe4\xa9\x06\x19\x02\xfdA\xf0\xfd\x96z5w\xc2\x0e\x86\x0c\xd2\x1f\xb9\x04\x97\xf8\xa6n\x07\xdfP\x10\xbf$\x91#b/Z\xaa\x9d4\x0c\xf2x\xccr\xbb\x04\xa6\x96\xedq\xdd\xd92Q\xc7\xdeV \xa9j\x19\xa98]],b\xb0\x8c\x1a=\x14\xa9,\x81\x82\xb6\xe2\x92\xd4/\xaf\xffy\xa0V\x01F5\xf0\xf1\x10\xce,\x87`9\x02\xb7\xad\x8acpr]Z\x19Pjj\x1c\xc1\xdb\xc4Q>\x82(\xc7\xa8~\x0c\x1c\x93\x91iQ\x05|\xb7\xf6\x05\x19\x83\xe1\xac\xf6 \x1a(\xd4\xbf \x81\xa2\xbc\xf1p8\x80\x88ne\xc8\x06j*Ax\x03&?\x18\x01\x07;\xb3)gZ\x1c\xaa\xf54\xc5\xfe\xe0\xc8\xa8\x15&e\xf7\xcee\xf3xY\\\n\x8d}\xd4c\x9d\xd5}UUD+\xb4\x8d;J\xb42\xa9\xee\x90\x83\xee%b\xf6\x82\x0e,2c*\x96j\x12\n\"\xcd%y\x96\x9b\xe3L\x1ds\x18\x03^\\\x81\x8f\x9a)\xee\xdb\x9aVW\xbe\x03\xe2j-\xb9x~\x8b\xdd\x1fl\x02rHy\x15\xd2\x97W\xe4Y\xfb\xc6J\x81:\x1c\x1er\x06k\xf5\x9cZ\x86\xe3\xa3<\xf6{C\x8c*\x1d\x8b\nUf\xb5\xaf6\xe6TN\x05\xd4\x96\"\x1e\x91g\xe0\xe8\xc5va\x04[\xd2ZyP\xc2\xb8\xaf'*\x10\xd3\x19\x99\x8b\x91\x86\xd7\xa1<\xd1\xe1\xab\x18\xca\x8c\xa5\xcf\xef\x95\xf0\x96\x8bI\xef\x7f\x194\xecN\xdf\\\xc7F\xe8|C/^\xb1\x84\x11\xb3\xc8Z\xcf\xbe\x81\xec\xccd\xaf\xa3\xbaG\x86\xe4)yI6\x8dh\xadrM\xcf_\xa0\xd7\x96\x18u\x1def\xe0\xa1\x82\xe3s\xcc\x13\xb7\xd6\x04\x92\xf7\x08%\xe7\xbeg5'\xc0\xda\xfa\x9e\xda\x03\x0d\xc8\x98\xa4\x03rI\x9e\xb6V\xa45\x159\xc5\x01C\xf9\x89\xe0~\xd8/\xeej\xff\xac7\xb5\xad\x95\xf1\x82\x8d]\x03a\x16\x17\xe4\xa4?\x1cf\xa8\xd1A\xc1 :\x90\x16g$+\xcdH\xb6\x04\x9b\xbe\xd2$\xa84P\x7f\xd8<5]P\x03\xb5\xa8\x8d:0\xb1\xb8\xa2[\xca\\\x84\x00\x04\xf8\xe6\xd1\x06\xe5R9\x0b\x8aj0\xb5\x10\xb0\xbe\x81\n\x01\x9a\x9e\xb9\xe9\x0b\x90\x9en\xd4\xc5\x87vs<\xce\xc9MF\x86\x8ae_\x03\xeb\x81\x93\xbfn\xc4\x07\x94\xf1\x0e\xea\x93PN\xc3tFhG\xc2\x84\x8a\x85\x0c\x16\xa7\x93\x1c\xfd{\xa29\xf5\xb0\xbb\xc7Q\x9b\xf0\x10\xb5\xd9\x93\x97$l]\x89/\xce\xb5\xb1[\x05\xdb\xf7\xc3\xe1\xa0\xb5\xa0\x1e\\\x85\xeey\xac\xdf\x90\xde\xfd\x81\xa5\xc2\x8f\xb6\x1f\xb2\xfc\xf5f\xa3\x0e\x13\xac\xe4\xbd\x92\xc84\x11\xc8Y\x17\xab\xeaA \xeaaa,\x01\xc9\xf3\x91\xbd\"{\x14\xce X\xed\x9e\\\x92\x10\xc2\x11\x15\xd6\xe2~@fd\x0f\xd4,D\x81m^\x98\x0d\xa8/\x17[T\x1d\xe3b\x0b#\xcd\x0bP-TS|\x17\x8e6\x8cO)\x94`b\xb3\xa39\xe9\xf7K\xe8\x10\x97\xd0!^\x02`\xfd\x12\n\xc4\xcb\xc1\x00\x03\xa09IZ\xfb\\7\x8b=~\xabXc\x03+\x9fLGpW\xe7\x0c\xaf\xa6l\xec&-!\x97d}A\x92C\xb1\x0b6\xf3d\xa9/eE\xb0\xfa\xdbt6\x04\xaeA4SC\xf3sSE\xf3k\xf6\xd0\xb5k\xedtf\\\xfd\xdb\xc9Q{\x14\x93\x98\xcf\xd1\xa88c\xa0A{\xfa\xf4\xd3:\x8dF\xc1\xb3\x03\xde;\xdb-\xa2\xc8\xf1x}\x18\xe8\x12f\xc7K\xc7\x8a\x0dH\xf9\xc0aT>~\xb8\xaa\x9c{v\xe4)y\x99\xa6\xa0\xc1\x9a\x19@\x84g1\".wue^P \xed\xfb~0\xca\x97\xa8\xd5K#\x11\x8f\xbb3\xbf\x02\xa0M\xf1om\x9c\xdb&\xa6T\x190\xc5\x1b\xe6\xd3\xa5=\x1d\xd2K\x0b\x17\x13\xcd\x97\x16F\xac\xd6s\x93\x90!\x01Z\x94\xcd\x93\"}\xb2\xe9t\x9e,\xdd\x8a\x83\x12\xf9L\xff.xd\x99\x17:\x0cJ\x0eq\xbf~F\x86%9Gm\xd8\xd3V\xce\xf4\xec\xbcE\xee\xce\x80N>zD\x9e=G\xc9\x1b\xa4\xf0\xe7\x07\xa4pX jEN/HF.I\xea<|\xac\x88\xd8\xb5Vm{O\x11B\xda\xd8\x1e\x01\xbfrVT\xf5\xab(\xef\x9a\xfe\x93\xbe\x8f\x1b\x80G\x8fH\xff\xe4\x84k\xbb\x10-\x13j\xa1\xac\xe3b\xd8\xf1\xe6\x85\xfaaR\xdb\xa0z:}\x14N\xda\xe4\xcai\x90\x0b \xf5\xf9\x90s\xa9\xf4y\x9b\x90\x86\\9.\xa3\xe6\x80\\\x93\xb1\x12\xa8\x0dzE\xae\x89\xe6\x15\xf4\x02)\xe0\xd9S\xfd\xack\xe0\xe4\xb2\x84\x07\xf5Zlc\xbc0Z\xf5\xce\xc7\xad\x9d?N\x0e\x8d\x0f\xadD\xf0\x83\xa8F&_&c\xd7\x1e\xb3e\\.\xc9\xb3\xcf\x14ZF\xe4%y\xfeic5\xa8em\\b\xbc\x1d\x08b\x15=m\xa0\xa8\x1d\xdegj\x0e\"ry\xa5\x80i\x13\x9e\x9e\xa1\xee3R\xb0?{a\xa2\xa6\xb6\x88\x16\x16\xb4\xda\xd7\xa6\xe3\xf7B\xa9\x07\xa2\x87yj\xa7\xd7\xb534p\x87\xd9\xb2\x9b\x19)\x01c;\"\xf7#\xb2\x1a\x91\xb7#r;\"_\x8d\xc8\xdd\x88\xfc0\"_\x8e\xc8\xcd\x88|\xe1\x10\xe1\x00\x15\x94\x08\xa9q\xd4(\x14\xb6\x8e\xbc\x0d\x1a;=\x89\xaa\x12^\xaa\xa4\x95lB\x03\xd3\x96Q\xfe\xd0\x8dO\xe8B\xaa\xb5\xbe\xcf\xed\xb7\xef\x8aV\xb8gG\x12l\xace\xb6\xe4\x1a\xef\x017\xafV\xd8T\xa2\xffj\xad\xd4\xd07\xca\xd5<\x911I\xf0~fg\xfa\x1e\xf35\xe3l\xfd6\xf0S\xd1$\x97A\x9e\x19\xd972\x82\xdb\x87KlJz\xed\x08\xea*\x0b\x02&Z!\xfdpx\xac\xc9\xd2[\xbd\x07\xbak\xdb\xf7\x81\x81\xce\xe0\x82\x9c\xf4O\xfa`\xb6\x836\x98\xb0\x81\xea\xdfW\xd5AkD[K[\xe9Rkf\xee\xc9\x98\xac\x958\xf3\x0cX\xb6*\xadPhG.\xc9\xb4\x94\xa2\xa4\xa8uQ~\xa7\n?v\x9dg\x1b\xc6\xce\x17,<0\x80_}\xc8\x00\x06\xd5\xdd<\xea\xc5\xc0H\xc1\xec\xf5\x0b\x08\xbdq\xec6\x8a;\xf1\xfb\xeaN\xbc,\xdd\x82e\x965\x808\xab\xefU\xb4}`\xd3\xc6\x00\xf7\xa6y%j\xaf\xfe\x16f\x11\x88\x99\x1a\xf5\xb7Vn'c\"\xc8K\x9c\x14\xa7=X\x15\xba\xa0\xda\x9b\xb4\x08\xaeW\x83v\xf3\x80\xa9|\xf0&\x050\xbd\xb0'\xf9\n\xb7(tD\xee+\xd2:\xd1\xa6xj\\\x8a\xa6g\xf8~\xbc]\xde\x8d^\\?\xa0\x82\xe1KrE\xee\xec.\xe8\x07rI\xbe\xbc ?4)\x18\x14\xe9\xbd\x9b\xffP\xb4\xe3kW.\xdc\x1cP,4+\x15\xea\n\x05\xd5\xf8M#\xc7W_\xb7m\xf2C\xce\x08)HAg\x83&Eo\xeev#\xe7{\xe52\xee\xe6C\xb7\xa4\xb0\xd6\xf7\xf6\xeb\xad5\x1cXuAB\xc5\xaf\xca\x1c\x04q\x91T\xa8\xf5\x831\xf4\xd6bdn\xc7\xa8\xa4\x8cG\x8f\xda\xcd\x0cHY\xf2G\x1c\x07>?$\xe7\xf5q\x03\x9c\x8c\xf4\xde\xe8\xdc\x08\xcc%\xe6L\xc6\xe4\xbc\x14\xb7\xd3f\x98GKcAevi\xb9\x851\xd2Y\xad\x08\xca\xf3\x0bm\xc6\xd9\xcf\x13U\xcb\xcb\n!+\x14(\xa4G\xe8\xd8\xbc1k\x97\x82\xa1\x7fO\x9b\x8bv$\x08\x99\xb6g\x1b\x92sT+\xf43\xb3\x0b\xf4\x14\x17x\xfe\x99{\x08\x87\xc3lPVDd\xc3\xa1\xc2m\x16\xed'\xe6VCjn\xae\x94\xd2 \\c-\xeb\x84\xb3\x8d3?~\xd0\x85R+\x9a\xe3\xf1f\x80\x0b;S\xcb\xb8\xa1\xcey\x0f\xae\xf0\xa6Km\x1a\xd9\x8d\x04\xda\x9b\x19o9\xdb0\xce\"\xafY\xbdIW\x8a\xda9\xe2\xe1\x1f\x14\xa9\xe2*?\xae\x1d\xf9\xd1\x03RTI\x10\xcd\x06d\x8c\x82S\xf1\x08%+\x0b/\xc3+\xf2\xac.M\x15.\xa2\x14\x1b(1~C\xd9\xec\xd7\xe1U\xedx\xc7\xb6;.}k\xd1\xe0\xe6\x82Z \"Z\x86z\xac\xa1.\xf6\xdd\xaf\xf64\xfe\x90\xd9}03SR\xca\x07\xe9\xbcL\xea\x07Q\xe7\xe3\xe8\xf2A\xad,\x9c\xe8\xb7ka\x9f>o\xd3\xc2\xe2\xb5\xb5\x03\xd5\xe4ZW\xb3\x16\x1cd\xe6\x82<}\x9e\xf3`P\xce\x82\xca\x94\\^\x91\x17\x17\x03\xe2\x83\xf1Wci\x17\xd5;\xe9\xfb\xe4%y\x81\x10\xea\xfa\xb4.&.S\xb5\xd4\xae1kg\xd8OG\xe4\xa9\":\xf9\xcd\x90\xfa\xf7\xe7\xea\xbb\xda\xfae$7\xcc\xac\x01H\xf3\xcb&`=?(\x08DG\xeas\xf1:W\x13\x8d\xda}\x8bX\xec\xb8\xc9\xfd\x11\x94\xbev\x0c;\x02\xebG\xaa\x9dv+\xa8\x9c\xc6CH\x1fm\xc2r\x084\x18\xb3\x07u\xd1\xdb\xf9\xc1\x1a\x1ci\xcd\x97\xb5\x0ev\xec\x97\x99\x84&R\xd26\x0b\xbf\xacZ\xdd\xa4>\xc4\x12pd\xee\xe1\x88F\x8bV{\xa7K\xcb\x10\xcd{GG\x86\x8aa\x8e=\xe0\xe8\xf7K\xec\x91\x96\x88\x1a\xd5:|\xbfH\xc8\xe8R\xcb$\xfdg\xcf\xf3\x8b\xb8\xb5U\x17#mz\x81:_\x8eE\xe2\xf2B\xee\xc7x\x17\xc6BQ`\xb31l\xd7\xfcb\xb9F\xb5^\xe1>\xdc/\xb0\x9cM\x17\xb4\xbe\xe9\xfca\xa8\x7f\x00\xf7:\x82|\xdc\xa2\x06V\x9d\x1f\xbd|\xdc\xe5\xad\xa8\xea\xbf\xf2\x12\xef03\x87W\xfc\xe0# \x16\x85;\xdfg\xe7\xd5\xbb\xdd\n\x81O\xdf\\\xf6\xe7:x\x9fvu=_\xa4\x8b\xd3\x97U\xd7n>f^\x9c:\xb2\xbf\\\x9ev#4#B]\xb4&?\xa0\xa8H\xc5\xb5\xa1\xab\xd8o\xd63$e1\xba.\xbbxJvMF\xe4$\xdf\xdc\xedD\x18\xb4\xca;\x89\xa2M\x8apx\xb0[zyu\xc0<\xf4\xc5\x99{\xeb\xe4\xb5\xef<\x9f\xe2\xa6\xae\x9f\xb9H\x97\xa7w\xae\x8a|a\xbe\xaci_Y8{._rz\xdfv\x1c\xf3\xecS\x00\x1a\xa4\x96\x93\x96\x1b)\xe6g.\xa5<='\xb2z\xf5\xc0\xfc4\x18`t\xf9\xf9\xa7\xaaf\xa1d\xb7\xe9\xf9y-\xfb\xfb.\xdb\xdeg\x9f6\xf7\x9c\xd8c\xa5\xeaV\x11-a\xd1\x95\x9e?(\xb6R\x87\"W\xd2\xb5\xd7\x13\x0f\x0eC{\x82h\xc0\xe7\xe9|Zq\xd6\xb7o\x0b\xd5m\xfcm\xc6\xa1U\xb5\xb3e\x1c\x9fx\xa8\xfe\xee\xa6\xf0\xef9\xfc\xfb\x14\xfe}\x06\xff>\x87\x7f_\xc0\xbf\x8c\xae\xb1\xd4\xce\xc2\x03\x1e2z\xfe\x86\xd3P\xbb\xc1P\xff\x86\x14>\xc6\xe0\xd9\x0f\x9e\x00\xd28\x13I\x06\xef\xf09A`\x12\x1eo9K\xa1\xf3\xe8b\x12\x9e\x98g\xe0N\xc5=\x8e\xa6\xf1\x11\xd1\x13f\xd8\x04tY\xb0;A9\xa3\xf0\xbc\xc1\x0b\xaf=\x01~'\x04\xc7gF!g\x06p\xec\xfd5\x8b{\xcb\xc9&\xe6_Qo\xd7o\xb9\x808g\xcb\xf2\x0dP\xad\x95\xfa\x90\x1b76\xb9\x8b\xf9\x8aCr\xcc\x95)\xb5u\xc0\xdb\xb6\xecv\xf9\x16N\x8e\xc1BdL\"\x97\xb7\x88v\xf6\xdc\xf5\xcau\xd1\x8a\xa0\xce\xc8\x04\xb2\xc9\xc2];\x17\xbb\x0bJ[]\xe4\xd8Am\xd7\xd0RA\xbf\xa4\xfa\x08J\x12x\xb0,\x9f\xcc\x06\xcd\x14\xd7\x87\x0b\x1d\xa80\xd6\xbb\n\x87J#\xb7\xfb\x81\x1b\xbfZ;\xea\xb7\xd6J\xady\x030\xef\x1199}3\x1f\xcf$Y\x0e?9EW\x9b\xb4]$\x80\x1b\x08\x14C\xa9\xf6{\xb2\xa7\xf6\x1f\x10\x03\xb5M\xad\x92\xe8\xeb\xe7)Z$\xa6\xe4\x92\xe472[no\x9f\xc0\xb9\x947O\x97\xe6\xdaH\x1b\x9fE\xff\x05\xa0\xb8M\xe1\xd1+\xb9W2\xd7\xb2[\x05\x83\x83\xde\x98\x89\x01\xed\xf4\xcd\xecz<\x9c]\x9bq[\xb7\xb3\xdf\xe7\x9f\x01H\xeb\xd2\x81Y \xbek\x92 {se=S\xdf{\x18b\x0b\xce\xbe\xb8\xbf\xdd\x89\xde\x80\xcc\x9c5\x9f\x15\xaa\xeb\x05l\x839MB\xaf\xed\x06\xb7\xea\xdc\x18w\x0c\x05tq\xdc\xdb\x81\xb9o\xc1\x14D\x14\xeb\x9d\xed\xcdB\xca\x85\xfc\x04\xfc\xb3\xf5\x06\x05\x04\x1a\x91\xc4\x8c\xc3Ia\xd2Z\xeb\x8e\xdb-_:\x8a\x0b@\xe8\x0f\x98)\xec>\xc4L\xa1+\x1c\x8ao\x1c\x80C\xc1\x00\x8b\xf6\x97\x84\x83\xff\x92@4/\xfe\xae\xe0\xed\x9a\xc0\xa3\x81\xbf\x8df$\x99\xa7.\xc0>\x02\xec\x1d!<\xacw(\xd0\xb2\x8f\x00\xe9/\xa3W\x10\xbb\x87\x1e@|\xc0R\xe4\x0fm\xf3\x88n\xa9U\xf6\x8b\xb7\xa2d\xc6\x03\xcbh\x0f4\x05\x8f\x0b\x1fDW\x8c\xa0r\x8e\xdb+}\xfb\xa7Efy\xf4\xc88)\xcfiz\xe0\xa6\xe9p\x83\xbd\xd1\xaa\xa6;Q?4^\xa4\x0b\xdd!\x87F\x83|0q!\x058\x1a\x8909DdHW@7F\xa0\xc9\xc3\xf3+Q\x0f\xc4\x15\x95\\e\xe2p\xabrD\x9a\xf2\xc0{Y\x8a\xa8$\x91Y1\xc5j7\x8f\x19\x97F\xb2F\x8a\xa4\xad!\x8a\xca!\x8aE\xda\xa8\x16\xe9\xb8\xf8Hi\x12\x9b\xd689\xb4\xce\x89\x83\x8a\x11\xd8\xa2to\xbe\x99\x90\x91n\xcd\x97W{\xe9\xcdn\xad\x8e E\xbf8\xc1\x03!\xea\xc1\xad\xec\xd0\xfcj\x8f\x7f\x82QI\xed\xf3a\xea\x13\x9b\xdce\x03\\\xb0\xe2\xea|r\xedw\xd8\x06\xc7j\xd3\xe7\x1b\x13z{M\xdf}\x18d\xees\xe8\xbd\x1c7\xc5b\x14\xc7#\xd7\xe9\x8f\xce\x12\x95\xda\x89*\xe3F~\x91}\xb6\xb5\xd6o\x15\xd0\xfb,\xf7\x08\x06\x96\x85\x8f\x1e\xd9\x89x\xe9t\x9d\xb7)\xee\xc3\x8d\xaep\x03\x05\x87\xc3\xcd\xc1m\xbc\x9d\xb3\xcdQ{w\xdf0\xc6\x8d1\x81lm\x03\xd0\xf9h\x9b,m\xa7\\4\xfb\xeb\xbc\xd2\xd6\xc1\x01\xb9\"\xf8\x90\xbdJ\x866\xe9J<\xa8\xf8\xafc\xb3\xb6K2\xf0\xe9^\xdb\x0dn\xb5\xd1\xed\xa1\x1e\x91B\xaf\x1a-\xedIA$\xceF$\xfb\x10\xb6{\x04@\xdd\xb8]A\x03\xac`3\xd8Z\xf4\x8d2m>J$\x1d\x8f\x13I\xb7!\xf8\x98\xfcs\xddlKK\x0e\x11t\x82\xfc\xd3\x89'$_\x9d\x07A!\x05pZe2\x92\x8f\x8f\"k\xf3\x8d\x1b\xf9m\xd6C\xa8B\xf4x\xe1\xb5\x1b}\x9d`\x0d/\x86\x86\x8d\xf4\x89^a\xa6\xf7\xc5#>\xba\x1c\x81\xd2\xa0j)W4\xd9gE\x1f\x89E\xfb\x03\xd8\x12\x14\x13\x14M/\xdd\xc5\x18\x91\xf6\xab\x08\xb9\xb7b\xa7\x91\x1bu\xdfF\xd8\x82\x81\xd1\xbd\xb9\x8d\xb0\x05\xb0\xf4\xf15=x\x1b\xa1\x08\xee\xbe\x08`X\x83oW\x1d\x8adT\x1e\x8du7d%%\x0ciCX\xd2\x05i\x89\xd9F\xa0\x18\xb2\xb1\xfdW\x02\xfb\xcb\xfc\x02^\xd3\xb1\xe2\x01\xb6s\xb0\xac\x83\xf9\xb4\\\xf8\x03\x1a]_x\xb5\x14\xe4\xa5/\xdb\xee\x0f\xfa\xda-\xf0\xa6\xc8j\xb3f\xb7T\xa5\x8e\xd6<\xe3\xb4\x95\x82\x8d'\xd0\xc9\xc1a\x90J\x17@\x1e=\"t8\xcc/\x88t\x01\xadn\xec\xd3\x06\x9a\xef\xbe\xfdP\xca\xfc!\x92\xf8:x\xb8\x80\x1ch\x94,H\xc6\x9b\x11\xb9\xff\xc7\xfd\x04\xe7\xfd\x04\xef\xa3\x1d\xba6\x8a\xcb-\xdb\x87\xe2\xfd\x04\xb7\x91\x9a\x0f\x1e\xb6.\x8d,\xaf\x8f\xc5\x07\x95s\xf1\xd4\x11=\xceZ\xf37\xde\x14\xcc}\xce\x0fP\x13\x12\xd5\xaaE\x9dH#\x19*\xe8\x90R\x971\\\xdb\x0d(\xeb\\O\xc9\x7f>^\xba\x82%o\xd51>\xb9$\xf4\x82\xf8m^]\x88\xa1Is\x1f._\xa5]._\x99_\xdc\xc1\xbb\x0b9\xe8\xe1\x858i\xa9\xf9\xe9\xcdM\xd7\xfb\\\x9aN\xe0j*\xda\x0c\xa4\xcd\xd2b\xbe\xd0\xd3\x11\xe1f\xf1\x15\x97\xca\x01rSYzu\xa2\x03K\xc9\x1d\xf5\xa8\x8b\x19DY\x8c\xaaQ\xac\x8eP\x1eV\x96\xf3CMw\xb4\xc1\xfb\x85\xec\xef\xf2an\"\xeem\xe3\xdc6\x86\x1f\x8d\x88\x1d\x8e\xb0r\xfe\xf4\xb9#\xc0J\xd4?\xff\xb4\x92L\x1b\xe2\xae\x08vgbc<\x9d\xba#wD\xec\x16\xa7\x1as\x9d\xbbs\xb1\xd4\xa3\x89\xcd\xf4\xd4\x9diE\xbd\x1b\xe1{7&\x8a\xcb\xd3\x86`!k\x16\x98\x1c\xcf\xdd9\xfc\xc8\xd6\xf1\xc2\x9d#\xa4\xdc\xc4\x1ay\xda\x10Q\x86\x85\xc9\x8e\xa6\xbe\xad\xe93w\xb64[\x99\x1c\x9f7\xe5Ht\x8egg\xee\x1c\x81\x1f\xd9^?k\x18h{\x95\xc4\xac-\xcc\xdd0\xe0\xc5\x8b'&k\xc3\xb0S\x1d\x1e\xc8dk \xd1\"\xa8 \xe4\xf2\xaca\\Y$|qo2}\xd6%0J\xf6Q\x02\xa3\xe4^\x90\x9c\x81Q\xa8 \x8cB10JE\x11\x0c\xd9\xf7\x18\x81\x99}\xebG7\x8a@\x17\x16i\x1d\xea\xb4n\xe9\xb3\xb7\x81t\x91\xd8\xb7E\xcc\xd5\xbc\xc3\x1c\xc6\xabb\xbe9z\xf9J\x8d\xa1\xafXI\xf1\xf8f\xd63\xf1hU\x89\xb9\x0d\xa6\xdb\x1b\x15\xe3\xed\xf6\xc0H\x0bM\x9c\xd6T\xd0\xde\xd2\xd6 \xcc\x11\xce\xac7\x98\x9f-]\xe6:Y\xc5\xe7\xf5kE*[=\x86C\x9fG\xc6KLa\xd4KQ]j\x88\x02\x8ez\x8d\x8e\xac\xf6\x15u\xafI\x9c:4y([y\xd4\xdb\xb1\x7ff\xa2\xef\xc3\xe5\x97\xb3\x01\xe6W\xe8R\xd1o\xb9MP1l\x03b\x8f \x97$\xbe \xa2Mx\xe2s\x01\"\xcbI\xc1g\x08\x04\xe2\xd2\xa0\xfc\xa0@\x19!\x10\xce3\x86$N\xf1\xdeb={)w>\x17\xefG\xa5\xe90\x1b\xfd\x8e\xfe\xdb\x0fNIy\n\xf2!G\xf7\xf40\x98\x97\xc4o\xd6\nF8x\x91q1s\x02\xc3\xc9\xe7\x11\x8e\xd3t0\xc0}\x84{W\xd6\x18\xe8\x187z\xaa\xf5\x97`\xef\xd4z\xbb\x9dM\x12\x16\xad\xfdh\x8b7\x04S\xee\xcd\xf5H/\x1b\x06\x95\xe0d\xe8R\xa0\xf7P\xe4\xe1;L\xe8\x0f\x9aF\xff\xd8\x802\xcdaO\x1ct\xc7\xeap\xfcF\xa7\xdc\xd9\xaf\xc8\xb1bB\x9dd\xf1:\xc2\xa4\xb7\xbe\xf0v\xc4mw\xed\xd1\x94\x91\xe9\xd9\xcc\xfd\xe1\xf3\xf3\xa6\x0f/\x1a>m\x1a\xad\xa7\x9f65\xdf4(\xd3\xf3\xc6\x91o\x82\xebE\xd38>w\x8c\n)\x98\xd29vbk\xb6\xa1Y \xda\xcb5\xf9S\xeap\x94\xd5H\xec\"\xcb.\x80\x1c\x192\x06T\x89\xd7]7G\x83\xc1\xc5@\xd1&'G\x8e\xf4e\nE\x82\xd4\xb6L\xe8\xbb\xe2UJ\xa3\xad\xf4!\xa3Z\x87\x83Q\xce\x82\xca\xf6\xe2\x1f \xe2w\x1e\x8b\xaa2\xc8\xc9;\xa7\x0d\x17E\xe2v[?=\xbc\xd8\xff\x82\xf1\x81\xd1#\xe1h\x8f\xc8\x89p;\x9a\x85\xd3\xcb\xb3\xd2\xf5TSYyV\x9c\x88ck\x98\x1e\xacA\xbb(9\xa0\xc6\xb0\xf4\x19U^>\x9eS\x12\x7f<>\xac\xb9\xb0~\xd4\x1c\xcd\xfb\x9d\xd4\x189\"\x15\xab\xc9\xedE\xce\x14+\x1e\x92iC\xe8\xd9\xe2\xefC4\x1d\xec\x90\xfe\x9d\xe4[\xe1\x1d\xe5kh\xabE O\xdaw\xbd\xc5\xdf{\xf70\xd7Xzi|\n1SG\x87\x81\xd7\x80\xa7\xf1F\x1c\x02\xbc\x03\xd0N\xa3\x11\x0d\xeb\xc1\x13\xb7C0\x1ch\xdfiv\x17\x0f\x87\xe8\x19\x9a\x93\x96;\xdf\xb1\xa2rq\xe3\xfd\x1b$U\xf1\xc7RF\xd8\xa5\xc5\xb59\xb8\x0e\x9c\xa2\xc0<\x7f\xfe\x02\xfdP\x13\xbd\x19;+\xf4\xaa\xb7X\x9c,z\xbf\xfe\xe4\x9f\x1e=\xee\x0f\x9e\x0cG\x93\xd3\xd9\xc5\xe5\xd5\xcb\xeb\xdf\xcc\x97o\xde\xfe\xf9g\xf9\xfe?\x8f{f\xe3\xd2\x1bt\xbboQ6\xb4Z\x92\xabb$\xa9\xca\xe5\x8b.d\xd5\xd2\xd4\x96\xad\x8a\x92\x9bk\xa4\xf3\xf3\x06\xbf\x8b\x07(\xeep\x18\xe3\xc5\xdf:j\xf9\x8d\x8e1\xf1\xb6\xf0\xf9\xf3\x17\n)\xcc]\xb0(\xbf\x88\xd0\xc4\xc8\x8c\x8fg\x85\x10\xc3+r>r2w\xcd?\xb4\xc3J7\xca\xebM\x15\xf8\xf4\xea\xb6B\xbb\x90\x96N+\x14\xa2\xf2 \xb6\xf9\xc7/\n\xf3k]\x1c\xb6\xb1_5\xbf5\x0fuo\xb1\xe8\x99aV\x1b\xc1\x8f\xb3\xea\x8eE\xe4\xd29F\xb3\xa0\xa0c\x89\x1c\xe3*\xc8\xee \xb3\x11\x01\x0f=\xbc\xb4\xa1\xcc\x0c\xb5\xfa\xfcE\x93+\xa1\x8b\x81*\xe8\"w\xa4,rE\xe8\x12\xc3\xd7\xc1_\xb3\x0b\xb0\x84\xac\xdc\xa7)D \x81\x93\xbf\xe6\x8d,\x85sx\xb8\xceH\x0fAIU=\xd4\x85>>\\\xc0\x19+\xa8\xae\xf2\x00\xb6\xe5\xc5\xd7\x85_4\x84\xed!\xa4\xd9i\x85_\x08\x93?'\x8bh9\x04\x93]\xd2k7Q1\x91|\x9a,S\x0e1\xa6\\\xde\xa5\xb5u\xd2uU\xc4E\xca\x93G\xfd\xfd;Z\x1cJ\xb2\xadu>m\x91\xb1\xcf\x1b\xd6N\xdaN\xf2\xdb\xed\xd7R\xf4^\x06w\x91[\xb257\xfe\xcb9\"\xf3u \xce\x94\xbc$g\x18\\\xa0\xda6\xd8.\xcf\xc0)\x96\xd3\xa7\xb9\x82\xee|0\x02\x03\xca\xab\x83\xd7\xdcL\xaef\x9f\xe7~\xee\xed\x8c*\x9c\xd3|\xab\xb9\x00\xd0\x01\xaeC`\x9ec\xdc0\xb8\x99n\xda\xaa\x81\xcc\x15!\xa8\x05\x0d\xf3\xd1\xa74T\x93\xc7O\xb2\x08\xce\xc9\x98\xa4\xa3FF\xacWt:\"\x1c\x0f\x89\x1c@\x9a%\x97\xe2A~\x8c\x8e\xe4u\x0b\x10>.k\xf4v\xdd\xd8\x19TC\xb6\xf6\xd7\xb6\x80\xceH\x9c\xf7\x161\x0f\xda\x0dY[Xj\x96\n\\\xd2T\xc3\xea@\x11\x9b\x01\xd1\xc4\x82b\xef?\x9a\x8d\x17\xbc\xd8P\xa8\xd7$\x1e\x8f\xc9\xcc:\xc1/|\x84\xe7\x18\x1d6]\x82\xa7\xe7&\xa1%\xfa\xc0\x18J\x04wSxjou\xe6}\xd6\xc1\xd4;\"\xd7zF1\x06\xaa\xd6%T\xe6\xd8\xa2K\xbb\x15\nk6 m3\x8c{\xef\xf6\x98\xd6\xb6\xcb*\xb4\xf8@\xc3\x97\x02\xef\xb0\xdd\xd7\xd6qv02P\xa2\x90Y\x01\xe7A\xad\xfco\x963h\xdf\xfd\xff*\x8c\xa1\xb1\xed\x7f\x13|\xe1\xd9\xd3\x0elAg\xfa[p\x85g\x0d\xee0\xdb\x98\xc2\xc9\x95\xae\xe7\xef\x8e-4\xf5&\xe7\n\xad9\x8e`\n\x1a\x0b\x1f\xce\x13t\x05\xff` \x9dX\x82\x1f\xa5\x7fc\x96\xa0Z\xfc\x07K\xa8\xfcZX\xc2\x8b\x06w\xc3\x7f\x0b\x96\xd0\xd8\xf6\xbf \x96\xa0\xdd\x9e\xb5\xb3\x04\x9d\xe9o\xc1\x12tS\xffNXBSor\x96\xd0\x9a\xe3\x08\x96\xf0b\xfa\x81,AW\xf0\x0f\x96\xd0\x89%\x84\x94\xdf\xfc\x8dy\x024\xf9o\x8c)\xd8\xe46\xd3 \xb3f\x89\x0d\x00\xc50\x00\x14\xa8\xfaT\xea\x8b\xe76\xf5\xf33\x9b\x8a\x9e\xe9X\xd53\xdd\xd1Q\xb9\n\xfeR\xeb\x03\x9b\xa1-}-=mH\x0fZY\x98\xe7Z\xc6\xc2u4\x85\x97\x0c\x1a\xc8\xbb\xc8\xc9;\xeaZ\x03\x18\x89j6\x8a\xa1\x95=\x97\xaaU\x0f:\xdc\x16\x81\xd2`5\x0f\xf7\x9a\xfa\xa8\x10\x1e\xeb\xab\xa7\xcf\xc85\x8c\x02\xf4x\xaa\xf0\xe3i!\x9a\x1f\xb6\xee\x80\x91\x16U\x10H%bt;o\xda\xd1\xd5D\x85\x1c\x91u\xe1\x0c9>G\xa7\xb0\x1e\xc0\xc7\xfb\xda[\xad\xad\x80\xf7\xe3\xdc\x15\xf3\xc9t\xa0\xd0\xbc\xbe|<\x1a\xc1J\x9d\x91\xcc1!4\xc25\xe5t\x07\xbff\x81\x1f\xa63\xe27\x10\x97\x07\xd8Z\xe4RO\xf5\xdap+\xe2l\x9a\x0f\xce\x12\x17Nm\x06uF\xa9C*&\xb0\x01\xc0\xb1O>@\\\xfb\xbb\xdcW>z\x84\xfd\xd3s\xa4\xbax]7\xb7\xb0\x01\x05\x90\xad\xa3C\xea\xd3\xfe\x1b9\x7f\xb3X,\x07\xfd\xc5b\xb1\x18\x00\x83>9\xcc\xf9U\xb6(?K\xd5\xb1\xf8\x80\xcc\x18s\x08\xe3\xdc\xd4\xde\x07}p\xfc\xe1\xc0O\x9du\xe0\x87+2_\x0e\xcc\xee\xac\xfe\xbd\xe0V\xd4E\x0e\xe2\xc3\xe8Xv\x0cR\xa7\xcb\xeb\x87\x84\x8d\xac\xac\x1b\xdc=\xd6\x1c\xa1\xba\x17S\xbd\x93s\x7f\xa9\x06\xaf\xde\x03\xa8p\x96W\x9d&\xb8\x9d\xa9H\xfe\x95%ZXCqm\x07\x90\xd9\x08x\x1fc1\x1d\xbbhJa/\x9b\x17M\xcbU\x1d\xc5\xba\x9e\x92\x97\x07\x8c\\N\x1c\xf8ZM\x83 \xd6\xad\xb54EGo\xb9\x16\xd4\xa60\xc8~9K#k\xa7\x93\xe5v:\xf4\x82\xf0\xe3\xa3\xa3\xf3\xc3\x81\xd7\xa6\x0d\x02}\x87\xa2M\x81\xd5y\xf7\xc0\xeahG\x04\xfd\xd4\xe4\x8e\xab\xe1B\xd7\x8a}\xae\x96cT\x11k2\xe3\x05\x10\x05#-\x12\xe1\x1c5\xc65\x8f\x96\xcd\xe4\xaf\x1bMk\xaf\xfc\x12D9\xad\xaah%|\x0e\x82\x11\xbb \x86\x8e\x98\x1e\xb9\xb4\x08Y$f\xe4\xacN8\xda`\x84\xa8\xcd3\xe2\x82\xb1\x94\xb1\x99~\xcf\xe3\xe5\x04\xdan\xec\x08~\xd6\xd2\xc7\x87R\xf2\xd8\xc1\x80\xb3\xd57\x0f\xa0\xf1\x05\"\xcaK\x04\x94~\xc4\xc0\xe4\x05Y\xe4\xecY\xd5u\x99\xd1\x99|\xe6\xd0\x99\x14\xe2\x8a\x9e\x8d?\x9f\x9c\x80\xf2\xf4\xc9pqzum\x15\xa6\xc3\xdf\xe49\x96\xfd\xebY\xfe6^\xfe|6z1}_\xf8>\xb8\xee_\xcf\x16\x93\xa3J\x0c\x9e\x0c^\x9e\xd6\xf56\x05\xd8&\x8b\xf1\xf2\xe7\xe9\xe8\xfc\xf9\xfb\xc1\xac?\x7fs\xf9rqwv6^\xdc\x9d\x9f-U\xd9\x87\xf3\x91\x92n\xa7U\xc2z\xd1\xa8}\xd0\xd4\xa3_\xa5\x16\x9b\xa2\x13\xaa\x97\xbd\x82(\x04\xaa\x90H\xab\x0f)\xb8\xab?\xe9s\x9b9\xab\xc5\xa1,\x94U\xbb\xa1l~\xb6\xd4\x8dL\xf5\xd5~\x0f\xac\x08\x02\xb5\xe7:\xb1\x02C\xd1/W?(\x8ba\x1dd\xef\xd6\xfd\xc3\xc1]Be\x1d\x1c^\x96\x02|\xe69(\x8e\xd6[\xba\xc2S\xb2\xaa\xe3\xc3\xa3[\xed\xb2\xcb8\xb0\xb2\x87zF\xf2[\x98\x03E\xedN04i\x94\x874\xb5\x13\x986M`/\xa4~ b \x87m\x93\xe9\xfdc2K\xbf\x8f:\x99iu2?\x0e\x91.\xd2\xa6y\xcf\x8b1N\xe7:\xf6\xeb\x8e\xe8(\xa5\xfa\x0fD\xe6\xa4\xab\x18CwR\x0f\x0b\x99?>\x04\xd6\xf48\xfe\x05\xb7u\xf0\x17#\x94\xfa\x18\xffs\x0d>\x1d\xads\xbb\x8d\x80\xb2[\x16\xc3\x1f\xfdo\xb2\xd3\xd1E\x9f\x9ec\x04R\x81\xd9\xd4_(\xee\xd3;\xf8\xa3\x9b\xf6C\xfcW\xbfE\x1b\xa8\xc7O\xf0\x95\xfb\xa9\xf9;Y1f\x13'w\x89W|\xces\x05\xb7\xef\xd4s\xb0\xc6\nq\x19\xc0\x13\xf6-Lyb\xfeB\xa9P\xfc\x84 Y\xa2V\x85z\x8c\xd8-|\x8a6\xf8\xc7\xc7\x7f!\x16i\x14a\x7f\xe2\x84\xfe\x94\xb1 \xf6n`+\xa4\x92\x92\xd8DD\x85b\\\xa4\xf0\x9e2\xbe\xf7=\x86\x8fij\xe2\xa1\x9a\x81I}\xb6\xc7\x8f\xbe~G\xb8\xd2\x10\xffD!&\xc74\xb1C`_ \x0b\xfa\x84\xec p\xca\xa9\xfeD\x188V\xe8\x19\x12;?\x0dY\x9a\x82\x06\x8a\xf4D\xf4\xf4\xfc\xd33x\xc2\x16\x05\xccr\xc6\x01\xae=\x0bC\xe8/\x0e\xc1-\x86t\xbd\xf3\x10j\xf5w\x9c\xa5L#\xca]\x18\xf0\xc4\xb3`\x15^\xb1T\x88\xd3\xf8\xee\xe9\xe7\x93\xe7g<\x7fDd\\\xfbYx'8b\xe8&\xc1?\xf8 \xb1\x82j$\x16\x82z\xbb\x90E\xf8v\xab\xfe]\xb1tG1\xf4\xec\xca\x17^\xeccX\xde8\x80\xb9\xf6h\xa0g\xdd\xdb\xf1\x18\x83\xda\xe2\xd3\x98\xdd \x16\xa566o8f{\x16\x89\x15\xf7\x05\x1bS!X\xb4f\x98\x1d \x0c<\xee\x01\xa8u\x10\xd1q\x12\xd0\xfb\xd4\x8f\xb6\xda\xbf\xa3IR\xb9\xa9\x1f!\xea\xaf\x05T\xbe\xde\xaf\xd4\x1f\xb6>\xbfQ\x7f7\xd4c\xc2GX6\xcc\x84\xf9\x8d\xb6:\x84\xaf\x9f\x02zma*\xb7\xbe\xc0?\xef\xc28\xe1\xb1 \xc0\xbb\x154\x80\xbav\x1e\xae\x04=+~\x82\x7f\xb8^\x13\xde\x0b\xfd\x17\x97\x85@L\xfa\x91BK?\xe2\xdb\x0d\xbbO(\x16\x08h*60\xe0j\xd5\xe0\xa2\xa0[\x8dD\xa1M\xe17:%G\xa5\x10\xeb\n\xd3\xf1\x8e\x05zYE8wa\x16\xea8\xbf\xe1\x1e\xa0\x03\x19[=\xc4\x88; \x0dB\xfc\x9bPN\xdf\xbd\x03\xa4K\x02*L4\xe3\x84\xc7w\x10\x1f8I\xef\x01\xce\x9f2\xc6!\xc1,0\x96\xc6\x19\xc7\x95\xc5\x11iyz\x1fA^.\xf4\xb2a^\x1c\xad\x03\x7f\x83KL\xaf\x88t\x8bk\xf0\xe6>\xc1\xf4\x10\xa6*\x8d\x835\xc5\xc0\xc5I,\xfc\x0d4\x96\xe2\xc4\xa4\x82Q\x00+\xc5\xee\xa8\xd74\x01\xc7)\xb0\xc2\xa2-\xc0\x94\xad\xa1\x81,\xe2\x8c\xc2r\xcc\xc4\xf9\xd9\x19DaVx\xc6}D\xd0\xbd\xcfn\xc79\xf4\xb7l\xe5a\xf6[Aq\xf5\xdd{\xfe\xed= \xc3\xdd\xc6GD\xbf\xe3\xf0\xe9>L\xb7\xbc\xb7|8\xff( \xf9\x9f\x0e&\xbf\x7f\xfd\xea\xdb\xb7\xaf\xbf\xf8\xe7\xb7\xdf\x7f\xf5p\x01\xb8\xa2Eq+\x17+A\xf8I~CE+^\xc8Ic0}\n\xc7\x1aE3\x05\x14\x97\x9f\xea;\x8dN\x97\x0e\x06\x17\xa7\x15\x8d\\\x8a\xe5@u\x04\x98\xac3?\x9d\xbeW\x99\x1f\xce*\x8b\x97v\x1c\x04\xab\xc0\x0f\xeb\xfa\xf8\xa7\x9f\xb9\xb9\xa3w(Z8\xde8\xdd\xb8/\xa9<}\xee\xd6Iy\x9a}\xbai\xa6\xbf1f(9\x93\xf1\x0c'+\x1cI\xa0rA\xf1\xe7\xde\x1dF\xaa \xe6\xd3\xa5b %\xdd\x14\xb9&\xa0\xa1\xf8&\x12}\x95\xc1\xe85\x06#2}\x01\x01\xd6\x8b_Gd\x8aa\xb6\n\x97\x81\xfc~\xa4j\xa1}\xa0\xcc\xb4\xff\xe2\xf9\xf3\xa7OK;\xf2\xa0\xcc\xb6\xea\xc4\x1am6\xc0p\xa8\xb1k)2\xe9X\xf1\x01\x05J\xb5\xa7%\x98\xf8\\eY\xb6\x00\xe1\x14\x95\\\x0e\xec\x1e\xfd\xc2\xfe\xeb\xca\xb3\xac\x05\xb5\x99c\xf2\x95\xe0\xe1\xf6[v\xa7>\xfd1k\x88\xca\x01\x07*iC\xc4\x0e\x1am\xbf\xe3l\xe3\xdf\xcd\xd4\x8e$\xdaft\xcb\xc6.\xed\x8b\x1f\xdd\xf8\x9b\xfb\xc6\xf8*7\xaf)\xdf21sJ\x03\xe2>\x89!\xa8\x08\xe3\xee\n\x809\xa63\xd2\xfb\xeb_\xfe\xcf\xbf\xfe\xe5\xff\xfa\xeb_\xfe\x8f\xbf\xfe\xe5\xbf\xb8\xd4]\xfev\x17`\xfc\x91(\x0b\x1cJ\xa8\xfc\x8clF\xce\xab\xa7\x1c\xa5W/\x0e\x938b\x91p\x8e\xb5\x17s\xe6JW?\x9e\x05\x10\x8a\xa5\x07\x9e\xe4z\xa3<\xea\x8b\xda\x1c\x19+\x19|\x03\xc9E1\"x\xd7\x83\x88{\x1f\xca\x05v\xbb^\x8e\xaeV\xfc\\=\xd8\xa3\x0eA\xfd\xa0\xe7\x08\x83\xe8\x98mto\xd7\x05th\xbe72\xce\xf7\xd4\x06\xd9@`\x1aV\xcf;F\xd7\xc8 {;T2\x890\xb0}\x0f\n\x9fu\x90\xbeB\xd0\xa6\x91\x8e\xa5\xdb\x0dv\x1c\xc7\x83\xc0\x17\x02w\x94b\xa7\xe8\x00)\xc5\x00&y\\\x8e<\x14K5FH!\xc2\x87\x0dHR\x08\xef\x82\xbaP\x07\xfc\xbfr\xbf\xfd\x83,\x14?\xfe\xbb$\x0b-\xcb\xae\x0d\xab\xff\xce0\xc6q\x1d\xbe\x801\x8e\xaf\xff\xc0\x18\xf8=\x04cj\xe9\xe4(F\x82\x0c\xa1\x13\x0d\xfd8\xf4\xffCh~'0?\x94\xd4\x1f\xa2\xf1\xff\n4\x1d\xb6]\xf9\xd2\xe4\xc5}IU\x98w\xaffS\x0b\x83#&jf\x1e\xfez<\x8e\xeeQ?\xbf^s\x86\x07\x04\x943\xcc\xc5\x85\xef\xa1\xde\x97\xa6>N&\xcd\xd6>h=A\xc9\xbaZ\xfb\xf8\x07\x93|\x18\x99\x95\x1d\xda\x12:\xac\xe25\x8c&\xb6\xbc\xca\x84\xd0z{\x1a\xed\xf1D\xcb\xa3\x890\xca|\x16 T\xa6{~\x19\x9b\xbc8\xd0\x7f\xb6<\xce\xf0\xc4+W\xef\xe7\xa7]\x82\x1a\x1cZ\xe39\x18\xf3bNE\x8cZ}d\xe9k\xa6$ d\xf2\x1b\xd4\xf3\xfb\xf8\xdd\xc7\xc32\xcc\x05\xb5\xb0\x80\x99S\x0b\x06\x03\xb6\xf1Y\xb0N\x99\x8e\x11\xb5-\x00\xbf\xf1\xb7\x19\xd72\x01\x96P\xb2\x81>\x1b\xd0\n\xf1\xdd\x14\xfe\x05yl\x87\x87k\xa0X\xde=\x87\x7fA\xe9\xaf\xd6\x83\xf9\xab\x0f\xe2l\x9f\xf3\xf5\xa3\xfe\xc2,\xf8!\x0c\xbf\x1f%x.\x88a\xdbz7+\xa8\x04\xacw\xe0\x81mY\x84IP,\xa4x\xde\x12\x9aC6\x08\xe5\xa6\xfe\xfe\x94\xe1\xf1I\xc8\xa2\xcc\xfc\xf5\x05\xf6>d\xbaC\x11\x9e+F1\xce+\xceN\x9c\x08\x0bil\xc7%\xce\x84\x06\xcd\x9c\xad\xe1\x9fxk0\xef'\xf5\x0f\x9e\xe9q\xc8\xc8\xb3\x15\n\xb6\xf0\x0f\xb5\xe7\x00\xa6\xca\x94\x05\xfa<%\xdd\xd1u\x0c\xc7IiH\x03\x80\"\xd7\xc9\xa7 \xf5\x10\xdc4\xa1XPp\xff\x86\xe9\xa7\x18\x89N*\xee\x11\xdb1\x08]/\xcd\xc2\x90\xe2)\x05\x06\x9d\xd3R\xa7z0\xd8,`$\x05\x0b\x93@\x1f8*\"`V\x90P\x13\x0f\x0f(\xb4\x9a\x195gG\x82\xe3\xbf\x14)\xa0\x80\xbc0\xd6\x19\xf4`\x8f\xc7<{\x7f\x8d\x07\xb3\xb7+\xdes\x04\x8a\x03\xa3\xb0^\xba\x87^\xe0\xd2\x0d\xc46\xb8GQ\xd9<\xafQ.5\xaff&i\xe4\x87T0/\x0epm\xe8\xf706c\xac\x13\x04\xa7Qj\xd0\xd7\x92\x81\xc2\xea\xf5\xb9&\x16^\xe0' \xc5.\xaf\xd9F\x0b\xd1)\x9c\xe5\xb0 \xf0\x93\x14\x17\x87\x1f\xd8E\x81\xcb\x04\xcf\xcb\x0c\xdc\xf0`\x84\xe9\x1b\x86G\x9a\xda\xf6\x1e\xe8\xaf\xfdK\xf9\x96\xd3\xb5\xaf\x97'\x9cnq|J\x11\x97\x99\xa0\x862\x84\x06\xb2\xc2_\xa1+O\xe2\xe0~\x1b\xdbG\xcb5\xe9\xda\xa7A\xb1 n\x90N\xe01q\x8e9\x10\x01\n\x9e\xee\xc3U\xac\x0fq\xef\x84\xf9k\x1a\x05\xabzx\xd0\x1d\x14\x061\xed\\\xef}\x06\xe8\xbc\x87\xae;f=\x82Y\xdf\xb0\xdf\x06z=o\xd8\x97j\x12_Q\xc1\xfd;\x93\xa0\xc5\x88\xd70{z\xb819\xd5\x94U\xbdF\xfb8\xd8\xb3b\xc9\xdf\xf9\x9bM\x96\xb2o\x958\xa3\x99\xb2JL\xed\xde\xf3\x15\xd2\x0bH\x144\x12\x90\x13S\xbe\x0e\xe2XC\xf4u\x16y_\xe4\x8f\xbf\xcd\x1f\xff9\x7f\xfc\x1e\x1f\xff\x99fi\xea\xd3\xe8\xb7A\xa6\xe1|\xc5\xf8\x96\x15\x1e\xff`E\x8aW1Ovq\x10o\xef\xf1\xfd\x8f\x9b\x8d\xa1\xc5\xa87,\x80\xf3C\xc2\xbc,\xa0\xbc\xdc\x97\x1f\x92\xb8\x98\xe9\xb5\xb1\x84`\xaf3\xbe\xca\x02%\xb4\xb8F\x1d\"r\xf4B=\x8f!\x8b\xb4e\x89z\xe6\x1c\x97P\x08\"\x0f\x9a(l8\x05\xc4\x0f-^\xe3\xe9f\x08\x04\x99\xad\x91\x04\x84a\x16\xf8h\xea\x81\xa7\xb0H\x92\xd1\xd8!\xdektN\xe8z\xad\xabMv4\x121\x92b\xae\x89L\xc8\x91\x00\xea\x83\xdc\x04\xa8\x1e&\xfc\x84\xe44\xbc\xb7\x98\x1aj\"\x17j\xd2\xa6\xde\xcd\xa3%s!\x92\xb7\xd0\xa0p\xa8\xa1\xcd\"\xcd\x90\xf0 \x00t\x8cU\x0cc\xf5k\x14\x8b\x1c\xd2\x1a\n$\x9e\xc7\xb4m\x80%\xeb4\xf0\xb7\xfa\x01\xbfd\"V\x12q\xc0\xb4,A\xbd\x1b\xc5`\x10\xefW[K\xbcV1\xd7\x90y,\x08\xd4x\xe9\xf9V\xafj<\xcc\xeb\x8ey78\x94V\xc0\x08(2!/`Hvm\xad^\x8cB\x82\xfa\xab\x97\xa9\x17\xc7|\x8d\x89\x9a:A3\x8a!\x8cW4e\x86g\xd2\xd436>\xe6L\xcf \x84M00\xd3w~\x98!`\xaa\x8a\x8d\x9a \x16y\xf7&A\xd59Nw\xfe\x06\xea[1\xbd\xd2V>\n\x1e(!\x16\x96/ZB\xa9\xbfc\xc3o\xe1E\xed\xffz\x95u\x1d\xf3\xb1Z <\x89\x03j7\x1f\xf5\xe41\n+i\xfe9\xe1\xb11\x9e\xc3\x04\xce\x14)4\xf4\x05f\x07\xbb\x80\x8b\x1d\x12Pf\\#k\xf5\xe2\x08\x18'&\xf1\\\xa8]\x03\x97\xd5Y\xf7~\xaa\xf7,\xc8\x14\xd9z\xcbB\xcd\x06Y\xc0\xf6\x16j#\x04\xf8(\xfc\xaa\xbf\xe3XQ<\\\xf9\xf0nF\xa0 z)V=\xb6#\x82\xaf\xc5bq$\xc6\x1b\x1a\xfaA\xfejP\xdb\xbe\x8c\xe9\xfa\xc7,\x15y\x9a\xe0L\x8bA\xfa]c1\xbc\xed)\xf7i\x94\xe7\xbe\xb5h\xb6A\xd9\x03Z\xda\xc2\x06i\x0b\x1b$`\x9dc\x83?E\xb9\xd0\x08eY\xe4#\xe34 %i\xb5@8u9M\x1a\x950Y\x9e8D-?\x82va\x99\xdf\x00 7\x98\x00;\xb5\x1b\xd8\xa9)\xb1L\x17\xbaa\xf7\x89\x929R\xfd\x92&\x10X]\xbf)n\x00\xcf\x96\xd4\x02%\xcd\xc7,`\x8a\xd6\x8d\x0b\xecI\xd5\xcd\x82\xd0\x8ac\xf8\xae:\x99S\xe1@K3\xf9\xe4\x05\xb16P\x1c\xb3\x84\xef\xbc\x1d\x8d\"\x16\xa0\x00\x84=\xbdw\xa4Asw\xd0\x8f;\xe8\x07\xca\x1f*7\xfc\x03_\xee\xe1\x0b\x18|\xbf\x8b\xe3\x90Fk%09d\x94\xac \xa3\xf4P8\x81U\xaa\x97\xb4\x15{Vl\xcf\x02-k\xdbM\x9a\x17\x07Y\x18\xa56\x13\xbe[r\xad?kQm\xcd\xa28\xb4Y\xd7,\xd1:\x0d+\xcb\xe7l\x1a\x1es>\x07\xbbG\xf5\xc05ykbA\x81\xc2\x1f-q\x17H{\xc4\xc4\xce\xf7n\"\xad\x17\x0b\xecV.\xb0\xfaT\xb5\x05-\xef\x83T\x8a]g\xea\xc50j\xf5\\\xe0\xba!\xbd\xb3_\xfc\xc8>\xc6{\xb55\x81U\x03\x8dFqNL\xa3,\x1f\x07#\xad\xf3\xf8\xd6\xa6\xf1\xf8\xd6\x8e!\n\xcc\x06w\n\xe23\xb7\xbd\xe0\xb6\x17\xb8\xe7\x05\x03\xc5\xfc\xb5\x00\x95\xde\x13\xfb\xef\x98\xde[\xf8Z\x8f\x07\xe8e\xb5\x80 \xb5L\xc2\xbeh\xe2\x03\xa2\x88V\xe2\xe9 \xffV\x96L\xb3\xa4\x9ar\x1f\x86Lp\x1f\xe4\xf1}N}\x0e\x8b\xcex\x83\xe3.\xf0\xa3\x9b\x99\x99\xe3\xbb0\x98i\xebzH\xb7\xe2\xba\xfa`G\x03\xaa\x9cA\x8e\xde\xb2`?I\x8a&\x8f\x81\xd3\n\x89T#7\x9b\xab\x9d\x17$\x1a\x8f/\x06\xa8\xe8\x8c\xb6=ru\x05\xa6\xa6\xf1\x86\x88\xb9\xb9}:\x87[\x98\xeaO\xe5f\xd9\x88\xb0\xb9J^6x\xdf2\xa6\x9b\x95\x83\x0d7\xe4^\xbb-\xae\xebp\x93h\xf5\x16^\xa6\xad\xb7\xaf\xbdc\xfb\x11a\x03\xf2\xc7\xd5\x8f\xcc\x13\x85\xf0\xf2;\x9a\xfe\xf16\xfa\x8e+\xd1A\xdcO<\x1a\xc0\xe0i\xcf\xd1\xba\xd7l\x1e-\x1d\x9eT\x8c\xc9N\xc3\x91\x0d\xd1\x80o\xc0\xbb\xdc\xcf\x8b\x9f\xe7\x8bt\xf1\xc3\xf2\x89\xd4\x7f\x17\xef\x17\xefO\xb7a\xbdG\x89*p\xf9O\x95\xec\xff\xf4\xd2\x99y\x0d\xd6jk*\xe8x\xbe\x18/n'\x8b\xec\xec\xec\xb7\x9f\x8e\x17\xd9\xd7_\x7f\xfd\xf5\xf2\xd4q\xf2\x08%\xd4\x12\xc7\x12\xcb\xe1'\x8e\\{\xc8\xd5\xbf\x9e\xe1\xff\x1b\xb9\x13\x03\x91\xa4\xd7\x12o\xd6H\xc1\x02\x89\xd7-\xa4\xe7\xaf\xe5]\x98$\x83\x99\x9c\xbf\xa1\xe3wK9\xa7\xe3w\xc3\xc9b\xbc\x1c\xf6\xafg\x90\xa6\xdefK\xf9\xc9`P5\xb7#\xda\xb3\x154\xb6\xb8\x1d\xe2\"\x93`\x829se\xde\xaa\xccs\xd5\xcd\xb3\xb3\xb1\xfas~\xa6\xfe\xfd\xe2l\x91M_|\xa6\xfe\xfd\xec\xec\xabEv\x8e\x9f\xcf\xcf\xce?W\xff>\xdf,\xb2\xa7ggg\xcb\xd3m\xbd\xca{rEz\x06 \x8b\xf8\xff\x03hf\x15.\x18%m\xed\xe3D\xc9\x0f\x8a\x86\x90\xeb\x03\x16\xe5\xa4\x803XC\xdd\xa9\xee{2\xeb^\x0b\x03\xc0\xda\xe1f\x13\x10\xd1x\xa6\x18,\x18\xe1\x15\xbe\x81M\xa1\xee\x86]\x13\xe4:\xef\xec\xac\x05\xd2&\xea\xb3r\xc3\xedoH\xff\x0b%\xb5M\xfc\x14\xfe\xf6Y\xa3\x85\xa1%Sj\xd1\x9f\xe1=z]\xc6\x98\xb0_\x10\x01\x11\xe7\x0d \x13\xc3\xe1\x80Ds\x81\xebU,\xeb\xcb\x95\x14\xdc\xf5\xd5{\xd3\xb4\xba\x11\xe4\x0d\x8f\xc3vG\x80\n\xda\xb7m\x07\xae\x85:{J\x00\xd9\xf8\x11[\x17\xe7\xec\xd6\x8f\xd6\xf1-\xb9\x06{\x002\xd3\xef\xe5&\x9d6\x83v\xe4o\x9d\x8d*\xc8\xbe\"W\x84\xf2m\x06\x86`&\x92\xfcK\x8c\x0d_\xf0B`\xb3\xcc\xcf\x96\xe4\xba\xfc:#o\x9b\x02\x9a\xde\x95\x0c`\x9b&\x95\xe4\x10\xdfV\xc7\xd2\xfc\xde\xbb\xbd5\xdcM\xf6\x8c\xa7\xaa\x8bW\xa47\x9d\x9cM\xd4\xae\xfan\xc2Y\x18\xef\xd9Z\xc7\xbd>\xf9\n\x9ck|5Y\xc7\x1e\x80\xad^?\x87~\xe5i\x93(^\xb3\xd7\xf7 \xb3\xb6\x9bw\x13?\xfd!K\x92\x98\x0b\xa8\xead:\"wu0\xd4(\xfe@\x8aU\xb9\xc7\xe2\xcb\x06\xbf~\xeaw\xd3\xf2\xed\x8b\x0eu\xff\x11\xf2\xfcN\xe7\xf9\x9a\xd3ms\xde\xef \xef\xef_\xbf\xfa\xf6\xb5>p\xfc\nO\xa5\xdd\xd9_C\xf6?\xd4,\xad\xcd\xef\x95\xfd\xfe5\xe8\x83\xdc\xb9\xbe\xc1\\4dk\x95\xf5\x15M\xdc\xf9~\xb4\xfc\x1a(\xd27\xe4\xbaRLM\xddW\x93W\xf1;H\xfcB\x08\xae\x12g\xe4\x1bw}\x7f\x80v_\xb3\xbb\x86\xde}\x0f\xdf\xbfD\x8b|w\x96\xdf\xe1\xd8\xfe\xf1\xd5wp[\xda\x9d\xe9[\xc8\xf4?\xbf\xfa\xf6\xf7B$\xdf\xb3\x9f2\x966T\xf7\xa7r\x0f\xbf\x85\x1e\x96\x0b\x92\x19\xf9\xd6]\xf8'h\x86Ej\xff\xf6\xa7\xef\x1b\xfa\xfcu\xb9\x85\x9f\xa0\x05[\x86\xcc\xc8O\xee\xb5\xe4\xe4\x17\xdf5-Z\x85\xf6\xef\x14\xf5\xfd\xff\xd9\xfb\xda\xae\xb8m%\xe0\xef\xf7W\x0c~zR\xfb\xe05\x90\xa4\xb7\xed\x06\xc2!\xb0ii\x03\xe4\x02i\xdaK\xf3p\xcc\xaev\xd7\xc1k\xed\xe3\x17^z\xcb\x7f\x7f\x8eF\x92-\xdb\x92\xec%iz?\\\x7fHXk$K\xa3\x91\xe6E\xa3\x99`\x9c\x92\x8a\x88\xdc\xea\x18\xdb\x10\xc4\xff\x8f@\x98D\xd8\x16S\xfe\x08\xe8mBRI\xc1(c1\xc27\x94\xdb.\xd5\xc8\x87u\xf0\x15\xeb\xa0\x1eK\xbf\xc0\x0e\xbc\n\xa2\xc5\x92\xf7\x1b\x95\x14=\xe4\x8f\x08\xc9G\xc9\xa8\xf0P\xb0u=\xf4{\x84\x9e\x91\\ ${u\x7f\x1e\xce\x18\xb5\xea\xe1\x7fRZ\xef\xb7\x80\x7f\x83\x1d8c=\xa7in^\x97?\xa3T\xdc\x9e\x82\xe6\xae\xf6Kc\xa7\xffE\xf4\x85m\x10\xeat\xf0\xfdr\xaf\xdc\x88\x8e\xe8Ds\xf7\x8d!\xfd\x07\x8c\x8c\xa6\xed\xd4W\xb0\x03\x86\x95\xffo\xd8\x81\x89\xbe\xe8W\xd8\x81\xb9\xbe\xe8_\x18wM[D\x08\xec\x80F\xa4cON0(\xa0\xb6,aez\xcf;@F\x05;\x10\xbb\xffy\xf0\xe1\xe2\x03\xa3\xceq\x98\xbbW\x188\xeb\xca\xcd\xf1\xdf\x04\xffM\xf1_\xeay\x06\xdeH\xed\xdf\x89\xf4\xdf\x89\xb0\xd5\x10\xff-\xf0\xdf\xcc\xf8\x85\xd0\xfe\x85\xc2^\x9c\x11Cb\"\xc0[\x81\x96\xc21\xb1\xb0\xb3\xa9\xadpi+\x9c\xd8\n\xe7\xb6\xc2\x1b[\xe1\xc2V8\xb3\x15\xde\xdb\n\xafl\x18\xba\xb4\x15\xde\x12\x8bB;R\xc8\xa2r\xa0\x91.A\xd2\xa3\xa0\x8a\xf7PZ\x93T\xef\"\xe1\xe4\xc3\xbdD>\x98d7\xed\x97J\xcf\x12\xe1(V\xb9Gq\xa7\x1aSkg\xb5\xd6\xb8a\xb99}uh\xf8\x98R\xc6*\xb1\x97\x85ZI\xfb)\xa5LVB\xfaw\xde\x9d\x8d.\xdf\x9e\x9e\xbc>|3\x92\x9fz\xf2\x04\xa6\x81\xfa\xde\x17\x9b\x14\x0f\x82'\xfa}\xb9wz\xb8\x87\x0d\xfab\x9b\xaa\x17\x1f\xec\x9d\xcbb\xdc\xa8\xe4\xfbw\xc7?\x1f\x9f\xbc?f\x8d\x9f\x9f\xec\x9f\xbc9C\xa5a\xcb\xe7;\xd648\xdb{=\xba|}rz\xf9\xd3\xbf\xde\x8dN\x7f\x93\xa5\xcbF\xe9\xf9\xe8\xe8\xed\x9b\xbd\xf3QY}\xc2\x01\xde\xffx\xf2ftyp\xb2\xff\xeeht|.\x0b\x17\xbc\xf0tt\xfe\xee\xf4\xf8\xf2\xe0\xe4H\x16\xcc\x9a\x05\x97\xafO\xf7~P\xab\xde\xb7 \x0e\x8f\xde\x9e\x9c\x96\xe57\xbc\xfc\xf5\xc9\xe9\xfe\xe8\xf2\xd5\xc9A\xd9\xe3\xab\x1aR\xce\xf6\x8e\x0f\xcf\x0f\xff\xcd\xbav\xe4\x8b\x8dI\x96\xfd<\x1a\xbd\xbd\xdc?9>\x1f\x1d\x9f\xfb\x9ciV\xc4\xf1\xee\xf4\xf0\xf2t\xf4\xc3\xe8\xd7\xb7\xac\xe1\x9c *0\x0c\x11\x91i\xd5f\xfc\x05\xdfa7=\x9cZ\x0c\xecI\xb4\xbc\x0dy%\xa7OT\xdb\xf8Z\xb8%Uh\x80\xd8M\x88\x0f\x8c\xd7\xc6.%>D<\xb3\x97\x84\xcbnf\nX^\x82\x85\xe5_Y\xab\x02\xd7Z2\xa5^\xd2]\x8f\xed\xb3Gj\x97\xd2\x12\xb2P\xebx\xb8\x9a\x0e\xf8\xa2(\x87\xbe\xb3\xc3\xa4\x88\x12\x11c7!\x1e\xd6b-U\xf0UmF\xad\x08Oy\xed\x88\x94\xbf`\xecRQ\x9b\x12\x15\xbe\xaa\xcd&\n\xc9S6\x13\xbbgD[\xe8!\x01\xf0\x8e\x95.Wr\xee\xb8\x85\x94\x1b\x96RB\xfe \xb8*\xab\xb7\xc2\x82\xca\xcb\xdc\xa9\xe7\xf3\xadu\xaa\xdd\xfd\x0c\xdc\xed\x84\xf46\x18\x94J\xbe)&\x82\xfa\x08\xbf\xeb\xa1\xc6Z%\x9f\x07K\xce\xb1<\xbd\xb7\xf4\x04dv\x08\x92\xa0<.:\xb6?\x8f\xe2\x89\xc9\x9c\x01h\xd1\x1b\x87\xf9x\x8ey8\xbaZ\xa7ENR&\x92c\xe8rs\x93\xab \xfb-\xe9\xba\x9e\xac>\xdd8XiF\xd8S\xfa\xf0\x0c!g\x1a\xd3\x9e\xfc\xcd\xb0\xc8$\xea\xce\x16\xa6)]\x0c\x1bv\xf6\xe6\xf3\xd0c\x06\xac\x94\x06\x9f86\xb3p\xa1>\x9f:\x14\xf3\xc4\x89\xae\x97\xd85\x9a\xd8\xf4\x9d<\xef\xbf&\xa5a\x96K2\xf61\xdbNf\xe4\x13M\xc1\xbd\xe1\x1b\x12\xca\x04\xdb|$/\xb77\xc4\x1f\x0e\xac#7\xb8\xee\x9a\xbfn\xeae\x0f\xfb\xc8k\xdb\x92\x85&\xd1\x98\xd1\x0ej\xb4\x03r\x0b\xef\xcc\xc3dO\x1a\xa4$[\xd2$C\x1b$\x1b\xacT\xb4\x1d\x1f\xd2\x80.I\xe2:?\x8c\xce\x1dq/e\xc86\xe7\x0d\xc6\x18_\x8c\xe7a\x9a\x91|\xa7\xc8\xa7\x83\xef|D\x89/\xd2\x9a\x06\x19I&.#@\x8fGE\xa9>\xf3\x08Jb\xd3\xb1\xef\xf5\xc0%\xfb\x92\xcb\x06}\xe0\xf1\x18\x83\xafS\xba8\xc33D\xb6\xcf8e\xdf\x9d\x9ek\xd3\xdc\xa7\xf2v\xfc\x93'\x90\x97\xc6 !\xa8\xe3\x95y\x9e^\x94uIg\xdap\x1d\xc7\xf3\x82+:\xb9\xf7L[x\xa2\x16L\xa34\x93\xcdc1\x13\xc4k\xdb3\xa3\xc7\xf7\xfc\xbc0G\xe9oW\\\xb1\x81\xa1\xb8\xbf\xe4]l\xb6\xefw\x81\xde\xc8]7\xd70 \xd8v\x8c\x00\xca-\xads\xe2~\xbd\x9d\xdd\xcc^n\xcf\x80\xa2\x8f\xf0\x0e\x06~k\x0f\xd3\xf5\x9c\x97\xdb\x1b\xb3\x97\xdb\x1b\x0c\xfck\x03#$\x01\x86\xdb:\x13.\x19.j\x91\x18\x82\xc9\xbd\xe62\x82\xbe\x9e\x9d\\\xdczW\x97/\xb7Qo{\xb9\x1d-f\x90\xa5\xe3\x1dg{\xa3\xf1\xe6\x0eh\x82^\xf2;aL\xd2\xdc\xdd\xf266\x9c\x97_{\x9e\xa6\x83\xc0\xd4T\xae7\xed\xf3N\xea\x11o'\xb6\x07W36\x86\xe7\xa3\xfe{\xa3 \xd4\x1f\xc5Ir\xc3\xde\xf9\xe7\x9fl\xd1\x12\x1f\x8e\x82\xb3\x1fO\xde_\x8e\xde\x8c\xb8\xac/_\xec\x9f\x1c\xd5_\x9c\x8f~=\xf7\xbb\xa9\xa1\xf1\xf9\xa3\xe0\xf5\xe1\x9b\xf3\xd1\xe9\xe5\xde\xfe\xfe\xe8\xed\xb9y\xf5\xd5s.\xd5\x8b\xb4\xaf\x0fWFE\xa9\xfd\xee4\xb4\xdfs\x8d\xf6{\x8e\xb1l D\xe8U6&t\n\xe70\x14\x07\x9d\xa6\x86\x88\xa6!\xc2\xd5h')\x16W$UM\xdd\xa4<\x02\xe2\xc7\xba-\x9f\x07\x0ep\x1c.\x0c)O\xf5\x88\xf9\xd8\x12\xb3\x1a\x973\x9b\xcf\xcf\x17\x04]+\xd8\xff\xc1\x94\xa6\xa3pN<\x95\x0c\x8eQ\xfdT\xdf\x9cb\xe8/\x8d\xcfJ9\x7f\x86 \xce\x03\xc6\x99\xf6\xab\xe3 \xed\x91H\xaer\x07\xcewJi/S\xfb\xf1\xb1\xb3\x89R&\xb3@f\x8a`\\\x05\x969\xe1\xb9\x1al\xf9\x7f\xa5\xf4Q\x91m\xddA\xa7{J\x8a%M\x1a\x13\xc2\xe7\xa3\x83\xfd\xf3\xf3\x8e!\x18\x8eH\xe4\x13\xc61\xbd%\x93\xf3p\x96\x0d!\xb1\xa9f>\xac%\xe4\"\xfd\x80\x01\xff\xd8\x1f]\x8b\x80\x8d\x80\xab\xb2k#\xach\xc2/ \xa2$#i\xbe7\xf9\x18\x8eI\x923&\xdeG\xc4\x01\\i\xed\xba\xae\xb37\xcdI:Bg:\x06\x90p\xc1\xe0\xb3\xc9\x94\xcd\xf97c\xadk\xff]\x9b\x12\x1eT\xb0%\xd3\xf0\xd7\xca1]\xf9C\x0f\xbb\xb6\xb1\xbd1\x0br\x92\xe5.Q\x97\x10\x97\x0eV\xd2\x9d*M=\x18\xc74\xe1\xaa\xa0m\x03\xaba\x99'9\xa9:P\x06\xe8c\x1d\xf4\xc1y\x12\xe7/\x1c\xcf\x93\xa6*\x99\xeaA\xdd\xf7\xb9\xb8X\xfeS\x1fO\xd9\xde\x0f>8\xc0$G\xf9\xe2+\xfe\xc2\xafW\xa8\x82J~\x01,\xa8\xdf\xdd\x81\x84\x0d\x93-\xe2\x90\xd1\xa3}[\xddZ\x85\x0b\x9c\xae\xc8\x05V\xd6\x07\xedpiO8\xda\x13.\xea \x17\xf6\x84+\x1e\xcd\xf2\xca]\xbe>;<\x82j\xc5a\xba\xb6>\x86\xf4v\xcc\x15\xdd\xc3\xda\xe4\x1b\xb5.\xa0\x89\x0e\xfa\x970.z\x82_\x13\xb2d#\xd2\xc7ki>\x82\x15T(\x18\x0253\x04\xd0\xebJ\xea\x83\x8ebl.\xc2\xd2\x11\xac@_\xd6n\xb4\xc8\xec\x92(k\x84\x17\xc5\x07/H\xc2\x05\xf1\x91\xf4\xf2\x00\x0f\x98\x82<\x8d\x16\xae\xe7\xf3\xa0\x85u\xbe\xeaC\x16H\xd4\xf2\x04P\xfc7\"\x8f'\xeb\xc8\x02\x89\x1e\x91J\xb3\xc9m\xf7\x94\x18\x96hJ\xe6_W\x1a\x92\x07d\xb8\x85Q\xe4o\x87G?8\xca\x8e&\x05\x9d0\x88&\x1e\xd29\xfb\x8b\x13\x14w^\xab\xbc]1\xa0]\x10.\x97\xf1=\x1e.\xbf%.?\x8e#\xfcG\xc2\xff\n\xcbL\x12\x91\x07/\xa1\xe0\xbcA\x95PD\xb5\x88\xa3\xc9\"c\xc8\xc7\x90\x12Q\xf7\xa0\x93\xca\xe1\xf1\xdbw\xe7\xbaa\xf2\xbb\x0e\n:\xf0f\x1d\xb7\xb6\x0bs\xf9\x05E b\xad`\x7fy\x1eF\xc5\x8d\x92B\xe3\xc7\xa0{\xd8\xc8\xb0\xb9D3\xec\xc4\x07\xc7Qp\xd5\xd9\xa2\x9d\xcb\x83\x18\xaeB(\x18)\xf8\nY6\xf6d\xad\x1c(\xa7\x03\xfe\x9b\x0d\xcfM!J`\x8f\xfd\x8d\x7f]\x13\xcf\xe8P\xd9|\xd8G\x05#d\x04\x87\xff\xa4\x9dl\xcf\xc3\xa3\xb6'O\xe0\xdf\\\n\xa0^\x8f\x99\x079\xfb8P\xac\xfe\xebc\xaa\xf7\x1b\x18\x88\xc1\xad\x95d\xc0\xa9`E\"\x00\xd1\xcc\x19V\xee_\xa7\x1chN\xf8\x18+\xa4\x12\x82\xb4\xd3w\xcc\xa0\xb6\x86\x97~\x15RPn\x0eT\x04\xc1\x1d{\xaa,0\xdc\x80\xc8m7kw\xe4\xc2\xa4 |\xe8\xa6b\xf5\xc1\xb0\xa2\\\xe6\xfe\xd7g\x18#\xa8\xe3L\xaby\xea\xd5@\xf7\xea\x82N\xd3T\xf3i\xaf\xf8\xd4\xf3\xd5\x93\x01\xba\xb4\xc8h\xea\xb3\x82\xb8\x0f\x9d\x83\xb1\x97\xb6$@\xad\x94alb\xa5\x03\xa5\x03U2\x04b?\xd7\x92wM\xfa\xc8Tl\x13:b\xed\x99\xa9\x07\xf9}[\xa6:\xc3\x80>\x07'G\x0e7\x87\xb0\xc1\xbe\xc0\xef\xa6AB\xeer.X\xbf\xf0Z\x0c\x98W\x14\xa1B\x92R\x18;&n\xc2\xb5\x9a\xa4\xd4\x8f\x14\x8d\xff\x049CU\xe6\xf9p\xcajX:\xde\x9a ]\x97\xf5\xb3`\xbcxr\x17d\xa2\xb1\xbe'|}g\xa3\x8f\xf4\xddG\xf2\xee#u\x87\x1d\x924f#\xe4Qqa\x07\x9c\xdf\xef\x9e\x8d\xd7\x06\x83\xdf\xef\x9e\x11\xc6\x88K\xf3\xceZ\xa5\xeb\xe3\xdetH,\xf7\x0b\xa0\xed\x0b\xab\xd4\x0fr\xcaO1<\xc8\xe7)\xbd\xc5\x83\x1d\xa68\x8e\xd2\x94\xa6\xae#\x8b!\xca \xa19\x84%\xf2M\xce\xb0\xe5\xf7Z\xbd\xc5AU_t\x19\x0b\xd7~t\x12\xa5\xf9}\xf5E\xde\x90\x0f\xe1\x15M1N\x8d\x81x\x8c(]\xab\x1d9t\"J\xb5\xbd\xde\xbb#\xecp\x98GcnHa\xc2\x8a\xce\xec\xd2\x84\xeb\xb6\xe6\xe8\xec\xb1\xa55\xac\xde\x9c\xdb%w\xb2\xf6\x04\x19\x18\x1a\xa8NtV\xdd\x1b\xc1t\xb3M>f\xcc\xcf\x91\x9a\xf7\x08\xba\x916/1\xd4M\xdf\x1e\xf0,\xbb\\HK\xf8\x19J} x\xf5#\x06\xc5a\x98\xed\x04k\x9b\x9eW\xb7w\xbf:9\xf8M\x88\xcb\x95\\\xbd\xcb\xf7J\x18B\xc2\xb4\x03\x92L\xf8\x99Xj:$\xb2\x0bdH_\\\\_\x9b\xe0\x7f\x03\x99-\xb8\x14N\xb6\x1d%\x7f\xb7}\xd5\xac\xc9\x91\xa3\x80+\xea\xf0^\xf3\x9b2\x06W \xfd\x14\xf0\x93\xe6\x13\xb6}\xa3\x95\x8b\x1f\xef\xe9{P\xdeC*8kJ\xbc\x17\xb8\xef\x15u\xae\xc2\x0dL\xb4\x86h\xca]x\xd8T\x1f\x13\x97rnB\x8d\xdc\xe4\x80T\x85\x9c\x9dP\x91\x8c\x98\x1a\xfa\xc60\xb3\xb0\xdae\x18\xc4\xacCG\xc1\x11\xb2-\xf8'~\x9e\x904<\xf0_\x80\x8a\xa6\x17\x1e\x845\x02\xe9\x81C\x90\xf4\x82A\xfb\xcd0b^\xef\xb9V\xc2\x80\x7f\xe3]:\xf3e\xaaK\x1f\xc2\x15&Z4\x88G\xb3\xea\xd9-#\xf2\xd2\x94\xd8\xaa\xf9\xc0\xd6dF\xf2}\x9aL\xa3Y/\x1b\xd8\x1e7\xd2r\xdfdMly\xd6\"\x06\x8aj\xb7ij\xb2rW\x95.\xcf\xfaf\xc3\xc9\xe4GJ\xaf\xfb\xf2\x7f\xfd\xd9\x03\"\x1c\x8f\xa3v\xf8\xa9\xd4\x9f\x7f\xe2^\x84'Sh\xc6\xcc=\xcdU\x8cj\xf3ju\xc1\xf4\xfd\xda\x99\x97^\x90n4\x9b\xad\xd4\xae\x1c\xc5\x85F\xa7Q\x1a\xde\x8b\xe3V\xdb\xc6\xa6\xd1\x0fW\xdbZ\xed\xe5\x832\x16\x9e\xce\xb6\x0c\x8b\x9c\x8a\xa2G\xc5W\x16\xfev\xfcpS\xdeSvs\x1f\x9c\xcbK\x92\x1d\xd1 \x0f\xd3S\xef\xfc\x0d7\xe0\xa9\xa9\x02\x94\xd5)O\x8cb7q\x9f7o\x15PQ\xf0\xb4Y\x10\x89\x82g\xcd\x82P\x14|\xd3,(D\xc1?\x9b\x05\x99(\xd8T%f\xf6b\x8b\xbd(\xdf\x94:F\xdc\x9ey\xf5\x06, *T\xe0\xe9\xb1.\xa8\xaf\x88\xaf\xd6\xf4\x0dlF\xd8\x05\x81\x9f\xb1\x95\xee\xca\x9e\xe5\xb6k\x9e\xee\xa6\x0f4\x10\x1f\xf6\xdc|\x1ee\xdc]\x95\x15\x84\xcd\x027\x0f./\xd1Twy\x89\xccb\xd3\x87T\x01\xf2;\xd3\x88P\xd0%\xbb>\xba\xaf\xab\xe0\xc5\x82\x93\xb4\xb4\x88\x99 \"[/\xaa\x8554]\xc3\xe4`lM\x0dM7<\x01\x0f\x0e3z6\xa7\xb7f\x92[Zmh\xe6\x01,;\x87\x18\xf7Et\x94Li\xba\xe01 ;\x88\xc2\xd2\xa1\xb1\xeds\x0bz\x15\xc5d\x08[OWm\x96\x8aqz\x96\x91N:q1\xed\x84\x98wB\xc4rg\xf8D\x0cXx\x08\xc9\xaes\xba|\x0c\x9a\xc2\x1eh\xfa\xaf\x1e@Q\x0e@\xa7\xb3\xd5\xde<|\xf0|\xe5*\xc2\x83[\xb5Y\nS\n\xa3\xcbe)\xec\xc0\x18\xdf\xfe\xbd\n\x8d\x0fy\xf0SF\x13\x14\x15\xc2Kn\xa1D&\xad\xbc\xbd\xa24&a\xd2|\x8d\xe1\x03\x9b/\xb9\xe9\xb1\xf1\xf65M\x17\x1a.-u\xa8{\xa6*\xb5T\"*KZ:Q$JZzW(\xab\xe8\xb4\xa8{\x9d\xde\x95\x89\x82\xd67bQ\xd0\xd2\xbb\xb8\x94\xd7\x14\x88\xa6\x08>n\xbc]\x8aF\xb6\x9a\x8dp\x01\xed\xdb\xc6\xdb\xb9\x04\xdfj\xf5\xf3F\x16\xb5\x86\xb6\x90%\x9b\xdf\xb4\x061\x13\x89\x8a\xb5\n\xe1\xfd\x97U\x08\x97\xe5\xba`=\x08\xa2\xecT\x84\x85\xf6\x95\xa20\xb9\xf7\x1b\x90\x96bN\xad\x86\xa6x\xa1\x0f7\xe5\x9b8\xcar\x15\x82\x91\xb5\xedw\x98\xdc\xd7i\xf5\xaa\xe5*t\xa3w\xf2\xa1\xc9\xfe\xf9\x86\xb6]\xcd:\xff\x1c:\x7fK\xb5\x97:\x7f\xd6,\xd0\xe9\xfc\xaaF\xfe\xa9:\x7f\xac\xb4U\xe9\xfcuK\x80Q\xe7/\xd3J\x1dD\x93#\x1eG\xb6\x05\xf9\xd7\xa9\xff\x93([\x86\xf9x~\xc8t\x860\xe6\xceP\xc6:\xdc\npc\x07\xe2^\xd2\x92\xc0\xf5\x1a\x17\x1aCS7\xe9\xe4\x9d:\x16\xff\xf7\xd9J\x90\x84\xbb\xd0\xc3\x97Z\x17~:\x90\x18\xd5\x90h\x91\xd8W\xb0\xcb\x14\x08;5\x1c\x0e\xe4AN\x7f\xe2\xd7\xaa9{g?]\xd3a\xbb\xf4\x8b\xb4|.F\x17\xbb\xfc~i\xe9\xfe\x18a\xb8\x9a\xbf\xe0\xa6\x80>*\xa9\x0f\xb4=\xe3\x06\xc6\xd3\x06\xac\x9di6c\x02\xfa\xb88x\xa8\xc5\xc2\xe3\xf9\xaa7_\xc0\x18\xb6\xa1x\x01\xe3\xf5u\x0f\xe2\x8b\xf1\x07\xb5\xe6\xc5X\x13kQ\xc6Y\xc4S\xe5\x1d\x03\xf3\xc3=\xae\x93\x01\x8e\xc38\x16\\\x90\xf8p\xc1\xea\x96\xc1$\xb8\x9e\x96\x96\xdbQ\xaf\xc3\"\xe9\xae\xaez\x8er\x92\x17\xfbh \xa2`\x92\x80G\xec\x0e\x18\xa0\x88\x81X\xbeC\xba4,<\xd1\x9a\xec\x15\xe3\xb2\xf2\x9d\x90\x90\xb4\xc7Sl\x1c\xa3\xa4X\xac0\x16\x81\xe7\xd6\x17\xf5\x1f@\x9bvK\x14a\xf4\xf4%\xe4\x89\xbf\x81/\xf6c?+\x08\x0f]\x8c\x96\xf6b\xb4\x9c\x87J\x99\xb8\x8b\x87N\x08\x8f\xf3d\x8c\\\x07\x82\x85\xa6\x01I\x8a\x85\xd92\xcd:G93\xdd\x15\x7f\xb8\x1e\x0c\xf1\xac\xb7\xe82U#Ou\x1d~\"c\xf3s\xea`;V\xbe\x02u\x8b\x1a\x95\x91Jw\xc1\x89\x12\xcc\x07\x84\xd7\xab;\xee%`\x90\xa8Zm\xda\xa3\x96\xb8\x9b\x80\x82ff\xe5]P\xd1\xaceF@\xb69Z,\xf3{q\xa5b\xcd\xc2\xa2\xa0\xc6\xcb\x90\xc8\xd5\xfd\xc0X\xcft\xbb\xd3\xb8\x86b\xdc\xfch\xba8\x08\xf3Pn\x80\x11\xba\xbb\xaf\xb9\xce\xeb\xb2 JD\x0c\xda\x8e\x83\xa3\xdcu\x0e1\x91\xa4]\x10\xa9\xed\xb7b\x8b5Q\x89\xd5\x82\xc6\xea\x0eEs\x96\x9e}\x12\x1d\xadNC\xad\xa9\xeb\x92\x90e~\xaf!\xc4\xfa dk\xd3\x84\xa0\x85|\xdf\x03Q\xcb0\xcbni:\x91\xb8\xe7R-CFU2\x94\xb9\x07\xffk\xf0\xd9\xbd\xc2\x16Q\xf2\x06[\x1b\xda\xfcK'\xe4\x8a\x16\xc9\x98\x9cG\x0bB\x8b|\x08\xcf\xbe\xb1@+\xa1\xe7\xacb\xe9_0\xdb\xad\xd7\x9fU\x02\x95\x16\xcf^\x02(1\xdc]\xef-dJ\xf3\xe8c\xad\x1e<\xae\x06Bc_\xcc\xd1\xf7\xf5\xc2\xdf\xaa\xf2R\x1ady\x98\x0b!\xc0(\x9c\x1d\xe6D'\x9cY\x1c\xae\xd2 #\xf9\x19k\xba\xba\xdao\x8d\n :hg\x91ri\x88Kj\x19\xc9\xb98f\xacd\xf2\xefW\xb0g\x184w\x98b\x03\xef'\x8fj\xc6k\xbd\x1f\xb0\xcax\xe5\xa5<\x11\xce\xe4/\x19o8\x994\x07\xbb\xcaX\xfb\x04\xc4\x10T\x06;p\xe9J\x8a\xeb\x12\x8a\x04\x06\x048w\xcaslau\x1e\x8d\x80\xd5U\x10\x0d\x1az`\xa1\xdfx\xff\x82\x01\xe2B7^\x9c\x15\x1f\xaefF\xdbH\xed\xe5_\xa3-\x95\xd6\xd7\xf7Q\x1c\x9f\x921\x89n\xf0\xb4,\xeb\xa1@\x19\xe7J\x92\xde\xda\x8e\xd0\xa2\x94]\x8f\x89\x7f\xfc\x9d\x9cN\x9bB\xa0\x92\xa3~*:\xf9\xd9\x17\xb2\xa0\xdau\xc4>\xba$?=\xec\xa7KR\x84\xedV\xed\"\x84\xebR'C\x84\xeaR'\x0b\x842\x99OC\xbc\x11,\xb4\xbeP\xd5\xfa\xec\x06\xd4\"\x88\x92)I\xb9\xf8\xe0FA\x94\x93E\xd6\xedhV?Q\xe9\xe1s\xf6\x8ag\xf7\xef\xf0\x1f\xcbP\xb7\xb5\x88W\xd0\xa6h\xb3&\xbc\xec\xd2v\xe7\xd2\xd3\xed\x13\xb5\xddy\xd7\xc6\xaeH\xd5\xe1\xeaR5T\x92\xb5R;\xecQKf\xdf\xed\xbe\xb7/\xd6\x9c\x85\x96\xa1\xad=\x1b\xa2\xbf\xd7\xa0kz1\xfd\x9b\xf5\xe2\x8ey\x14\x0eW\xdc\xedc\x8dGC\x99\x04\x98]\x91\xfd-\xfet=\xd8\x86\xad\xea^\xca$X\x84KE\x10\xf2\x81v\x11^$\x84\xe6\xb4n\x96\xcf:.\x96\xc9\xd9\xb75\x0f\xe2\x13K\xdc\x10xZ\xd7\x9e\x92\x8b|J \x06\xaf\xf1\xf0[/\xd6J\xb6p\xab\x80'\xeb\x82j\xe5\x9d\x8f\x8b\xe5\xc5\xe6\x07\xbe\xe3\xc1:P\xcb\xdd\xe4\xce{Y\x1dsi\x1f-2\xa2\x0e\xa2T}\xbf>f4\x19\xf0\xed|\xc0\xf4\xeb\x01\xdb.\xad\x0e\x81\xa6\xeeY\xdd\xcd\xa0\xfbd\x05Z\xa7+\x1dF*)]\xf7]\x81\xfd\x04{\xf9\x94$\xa3\xaaO|)\xd8)\xc7\xde\x1dy\x9e\x13Y\x96\xbf\x19\xc7V\xf3\x124\xa6\xf6*O\xe0*O\x06\xd9\x02\xb4\xb3<\xe0\xfaH\xc7\x86K\x93\xfd8\x1a_\xf7\x10^\xd4\xa7\xc4^\xa5\x87\xb9]\x88\xb3\x11\x9d\x03\x03pL\x9e\xa8^\x90S~\xf4\xf3X\xd4\xad\x84\xb6p2\x01\x07\xd6\xab\xcd\xab\xc1\xf8\xb8\x1b\xa1\xf1[%B\x91#\x08\xbdM?06\xee\xbd\xc9\x04\xd8g\xb5\xc3\xef\xb4\xb4\xbc-R\xb2\x8a\xb5\xa5r;\xebeo\xf9\xdf\x81\xdf\xca\x07~\xabj\xa9\xff;(\xd3?\x7f\xd1AY\x97\xceB{\x1d\xa7\xd5\x0f\xca\x0c\xa7\x0bx\xf2%\xf4\x9b\xb4\x9f~\x13\xf69\xcc\xea\x10#\xc2\x9e\x1ba\xba\xbaX/Dz\xa5f\xda\xcfX.\x82\x08$\xb6\xdbFuA\x9d\xbb\xc6MS\xba\xf8\xe9\xccs)jYx\xff\xd3\xc9S\x9e`e\x1a\xc6\x999\xe1\x0b\xe8\xa5\xf9\xb2\x1d\xdb\x81\xd7\xaaB}\xb7I\xe1\xd3L\xe4\xa5\x07\xf1\xa3\xf7\xec\xde{\xb2\\\xa1\x9fl\x1f\xb7X\xc6\xd9\xc2\xc9H\x8esrN\xcf\xc2\xc52\xeee#\xaf\xbc\xbb\\\xf6\xe5\x19\xdb\x1cxm\x8e'\xcf%5w \xfd\xdd`\xa2\xb5\xcb\x1bEF\xd2\xf2\x990\xb4:\x0f\x93ILNVi\xfb\xa6\xccw\xdc\xed\xbb\xa1\x0c^\xe7\x03\xe8\x1b\xbd\x85\xe132\x80\xcf\xe9y\xb9V1\x81\x86\x9dO\x9d\xc3\xf2e\x9bdtw\xb4\xeb8\xf8B\x86\xbc\xffbN\x96\xbb\xce9\xb9\xcb\xf7R\x12>\x92\x9b\xd4\x0c\x0c& \xda\x93\xe50R\x9b+\x06\x04c\x1d\xf6\x08\x9e\xc4\xd8M\x16\xfda\x0d\xcfkF\xbddX\xac\x05d\xc3\x1fi\x94\xb8\x8c}x\xfd8\x97EGm\xb0\x89\xfa\x06\xa0\xad\xf5(w\xbe.\x11\x1f\x81\x1fu\xe3E\x1e\x86\xe2E\x87\x7fz\xc1\x818\x91F\xa7\x89\n,\xad\x17\xf0\x10\x92\xb58\x02\x8f\xef\xc2g\xbdt\xd3\xec\xa6\xe9n\x8c\xf8h\x98e\xd1,a\x8c\xcc.\xa6\xd7\x92>o\xf1\xfc\xceMuE\xe4y\xb6\xef\xf3\x95\xa6bJ\x03]~\n\x03'&=\xf3\xc2c(8\xb4Ta\xac\xe9\x1dH.R]\xa0\x89\xd6\x1b\xc9\x90\xeb$X\xa7x\xda\xc5\x9aK\xd1\x83XO\x9ck\x19\xfe7_@\x02\xdbj\xa2\x7f3\xf6@\x99\xb9\xfc\"1`\x0e\x90P\x99tG\xd2\xf0\n\x05\x8a\xdaO\x91|,e\n\xdb4\x9a\x15\x12hm\xb3L\xda\xc7P\xce\xe3\\\xa6\xc1m\x1a\xe5%D\x99}\xaaI\xa7\x845xM\xee\x19\xfe\xf5\x0b\xbe\xff$\xa8\xd6X>\xa1V\x85\x91\x07\x01u\x15\xd2\xe0\x99\xc3R\xf1\x9eG\x07l{\x157\xb6\x9b\xe6\xc5r\xa6\xd8\x14<\x02F\xbd \x14\x05[\x9b\xdf|\xab\x0f\x86Q|\x91\xbbOn{\x99\xf7\x92\x8a\xb5+{\xad\x9f\xb3\x04\x8f\xf5T\x8b\x80\x95\x9b\xc2\xa1\xed\x87IBs`\xeb\x12B\xce\xfb \xccj\xa1\xd8\xdas\xd2!\x90'}\xbd:\xb0\xa3D\xed\xd9)\x99\x92\x94$\xe32D\xdc<\xca`\x1ef\xc9\xd79\\\x11\x92@\xc4\xaf\xb1D\x19\x99\xc0\x00\xb2bIR\xd7\xabA\xb0\xa1\x90I\x87\xf8\xb0\x86\xc7\x0dJB\xc9Z\x10\x1fm8\xbb\\P\x81\x86F\x0d\xfa\x86X\x843\xc2\x98\x1f'\xfa\x93i\xcb-\xc7\xa2y$\xab9d\x93`I\xd2,\xcarSX\x05\xc9\x14\x92\xee\xd3\xbdd\xa5\xe3kU\x1f\xd0o,=s\xaf\xb0\x1e\xd2~=dO\xe9\x06\xf7\x92U\xe1\x82x\xe9\xcd\x86\xe1\xaa\x12\x9aGS\xbc\xe68,\xb7oxYU|\xf2\xa4\x02J\xf1\x88\xa8G\xbe\x066\xd8!\x08p1\xf8\xaeZP\xe1\xcb\x92\x91\x0e\xf4\xeayUd29\xb7\x89\x12\x13-%?\x93\xfb\x03zk7\xa0\xca\xa7\"\x0f\xa9C\x8a\xda\xfa pFI\xceS\xc20\xf1\xfe\x9a\xdcsdNi:&\xc7\x12\xed\xbe\xc85e0\x10\xb2.\xbe\x8a\x8b\xf4\x91\xfdcUM\xf4\xbbb?\xb8\x86\x80\xf0\x11\xe9\xd7\x1f\x1eQs\x1b6\xbd\x92\x86\xba\x84\x0f\xf9\xc8\x05^\xc4\x06/F\x83V-\x03\xfc\x8a\x84=\xb5\x0f'\xc1\x84\xf2\xf1Z*\xdb\x97^.L)\x8a\xed\xa5\x1b\x0d\xf2I\x82(\x13\xbc\x8e\xdf\xd1a\x02L\xd5)\xab\x9f\x19\xdb\x07\xcd\xcb\\\x87\xddGtg\xd3\xd7\xcf\xbf|\x90\x0e\xa6q\x91\xcd\xfbN#TS\x99\xf3\x9a\xb6\xb4\x13Hf\x8c!\xc7\xab\xb4\xafEk.\x1a\xb2}NOXz\xea\x97\x93\xd4\xa7cI\xc3\xc4$\xce\x18D|Z\xe5r\xad\xfeS\xca\xba\xec5\x9f\x98_\xa0\x86\x03\x1b\xc6J\x0c\xe3^$\x91d&--K\xec8\x81\x04\x0d\xb31\x7f!Wx\x14E\x9e\xa4\xac\x08\x0c\xa2X\xfe\xfeR\x0c\xe8\xf1i3{\x07\xdf\xc1\xa9\xee\xe5\"(\xdd\xe6\x98<\xd6f\x8c\xd8\x8en_\xa9Aj\xcd\x87\x9d\"\xa81r1\xb2\n\xf4=A\x07?\x83\xe8|\xc6\x84O w\xcb\x94d\x19\x93\xda\x17E\x96\x03\x89\xf29I\xe1\x8a\xf0\x06h\xaa\xc8\xd2>\x06\x1dv`\xbd\xfc\x90\x862I\xa5\"U\xba?\xe7N\xae\xc8\xdb\xa8\xe8Pz\xd4\x8ei\x92\xe5i1\xcei\xaaS[\xe4#g\xc0L\xef\x95F\xda\x8e8\xa0>R\xff\xb4\xbbA\xa9\xba\xec\xd0\x94\x8cICK\x92{\xbb\x02\x1bYM\xa2\x86]\xd0\xbe\x17\xf3>DUN\x8a\xe5l:\xeb\xa4\xc3t\xcf\xf2T\xa0a\xbd\xf2\x81\xf630\xbf\x8f\xe2\xf8S-\xcch\x95\xab\x8b!\xaeb`n\xdc\xbf\xe8\xb2\x97X\xac\xc9\x7f\x89K\xac\xdcH;\xb7\xd0D\\\xc6\xab\x8dF\xbf}\xe2\xe8k\x8b\xff\xcf?\xcb\x8c\x85\xb84+g[\xc5\x01\xb7Q\xd2[\x8f1\xddi\xf6!\xa9<}\xb5\x93Q~\xac1}I\xb7\x01\xb5\xe74\xbdK\x16\x9f\x83\xbc\xb8t#{k\x92Xzw\xf1o8\x97\x10\xb9\xbe\xec\xf4\xe5*\x91\x15J\x8a\x04R\xb1k\xbfM\x82\xec\x95\"\x9b\xbc\xbaG\xf5\xc6\xe68\xc3\xa3-TUNP\x1f\xb1\x9c\xef\x8a\x90\x0fB\xab2\x03\x16\x02\xd0\xde\\\x86PQ\xb2,\xf2S25\xc3\xc5}\xcd1\xf2\x916\x9c\xff\xf4I\x1aUZ\x7f\x89\x07y\x19\x96<\xf5\x98\xb8\xb3\xa9XA\xec&aR\x9a\x84\x13n\x12\xc6\xac\x85\xf6\xcfK\x1d\xca\x08\xf4\x80~/\x8e\xa0\x18\xc7\x07G\x12\x85S\x1aQ}pJ\xa2\xc0d\xd1u\xa2\xc0\x83\xfb\x16Q4\xde\xf2y\xe7\xed\x8b\xb9\xe5?\xe4k9G\xd6\xd3\xffqG\x0cKt\xf3\x86]\xcb\xdc\x95_/\x1d\x01\xc4o\xfd\xbe\x06C\x08\xfb\xb6g\x88\x17\x0eC#\x910\xba\x98v\x0c\x89\x95\xd3\x8e.0\x1c\x96\xe3a?\x8c=)z\xb5T\xadB\x99\xba\xb4(r\xaeueb\xe8\xba\"\xf3=\xd8\xd6\xdd\xd7\xad\xcd\x06D{\x93h\x8b\xc2\xad-\xa3\x0d\"w\n\xd9\xc1\n\x97\xf8W\xc7\x99\xa5\xe5\xae\xa0\xdc\xd3\x9d\xd1\xdd\x92\x8cs2QM\xfcmBIa\x07\x8e\xc3\xe3v\x01cz\xce\x85\xf0\xf09\xbb_\\\xd1\xf8\x83\xa6~\x04;\xb0\xf1\x7f\x7f\xcf\xd6\xff\xfc=[\xffjc\xd6\x86\x08\x11\xe2b\xb0\xfea\xf3\xeebs\xf0}8\x98~X\xffjC\xe3\xe6T \xe4\xe6\xd5\xc5\xe6\x96\x01\"\xe3\x10\xf4bs\xf0\xad\x01\x841A\xcc\xad\x7f\xa8\x93\x1d\xd8\xde\xaa\xa4f\xa9\xe9\x81B\xe7:\x11NM;R'\xc3\xd7\xed\xa6\xa6\xfa\xa62\x12OY\x0d\xf5\x7f}\x9b\xac\xa4\xdd,\xdb\x80\xc6x\xf6\xcb\xfey-\xe7\xd9\x91\xd6\xa7y\x949\x9e.\xec\xf2\xa4R\"+\x16,\xd3\xe4\xb4\xc1\xe7\xb0\x03Ga>\x0f\x16\xe1\x9dF\xac+K#\x8d\xf8\xd2\xef\xb6'\xef\xf028`\xdbNBou\xf2\xa7r^\x07\xea\xb9\xd8L\xaf\x7fH\xddC&\xba1\x1e\xa8\xac\xad\xf1\xac\x18\xb5 \xd2d\xddiz\xa7\xea{\xa3\x89\x9e\x08\xd2\xac\xa0\xc9\x97nK\xd3\xc2\xeat\xebX\xa2\xbe\x93\xe1\xba\xab5\xde\xed\x16\xd0hD\xa0BC\xaa\x066\xc0Z}\xf2\x04&B`\xf3@{i\xe5AM\x13\xa4\xb1\xcdc.\x15KF\xa9\x9b2\xa8PmBdF)\xdc\xbdQ\xe5/\xffF'U\x93\x17\x1a\xec\xc0\x8cm\x86\xbb\x90\xc3:\x8f)\xd6u\xc6\x0c\xcd\x0cJk\x9a)\xac\x12\xe6\x13\x18\xc2\xba\xe6\xf3D\xb8\xdc\xf2\x84~\x11\xe6\xf33\x1f\x97\x16\"\x1d\xb4\xe5,\x90\xcdp&\xc1`\x17bW\xe4!u\x9f\xa2\x86\xba\x0bOa\x08\xdf1l\x84\nX\x8a\xfdk\xd0\xb3\xfaK\xf5\x8ci0\x17\xed\xa1>\x1e\xd1\xf9\x10a6\x99\xc2\x87\x0c\x85\x13\xf4w\xd7\x0b\x1cSn\xb2\xd3\x96--e\x13\xb4\xd9\xebIH\x9fpLo\xa8K\xbc\xc6v\x02\xea\"\xbe\xea\xf6w\xb4\\_b|2\xb2Jv\x8ca*\xe9\xdbx\xa0\x17_\xa8x\xdcr\x9e26\xae\xa1Js\xa75\x91;\xe5#;M`\x00\xb1\xb5gJ\xc0\xbd\x98\x11W\xc2T\xb6\x9c\xff\xb5\xcdu\xb7%zB\xc0\x00\xc6\xac\xac\xad\x04\xd8\xfax\xdb\xa9\xf4/l\xe1\xff/k\xf9\xc6\x8c9\xca\x18\xd5f$\x17\x82\x99{\xeb\xf7\xdc\x05K_V\x18\x80\x8b\xb8\xea\xbe\x9c\xba\x84]\xb8q\x13\x1fBYi\xec\xa1\x05\xdf\xb8a\xae6\xab\xa3\xce\x9d?S\x08i\x02\x98\x1dk\x17\xae\xf89\x82\xdb\xa4\xb4b\xb5\xaf\xdf\xf5\x99/\xf3JHx\x1c\x06\xcb\x8cR\xd5\xa5\x8c\xe7\xe4\xe2.\x10L63EJQ\x1bP\x086\xf3\xdaV\xfe.\xb3\x86\xa80\xe6_k\x13N\xee\xf90\xad\xf0\xa9W\x14\x01g\xd6F,\xe2^\xb42c\xed\xcf\\\xb9\xa6\x00\xfb=\x17l\x86b\x8c\xaeq\xcf\xd7\xf4\xdc\xe8\xc5\x95c\xe4\xe8\x1ccbn\xfa0s\x85\x15\x06\xf7\xec\xb54\x88 \xe6f\xe0Y\xb0]\xb6[;\x8b\xf0\xee}\x18\xe5\xdc\xfd\x8cq\x98\xb9{\xef\xa6\x81x-[B\xc3{\xe8\xe3&\xee\xe4i\x18\xc5\xc8K\xd1em\x17\x9b\x96/a\x08\x13L\xe0\xd7\xffhT\xb1\x00#\"0)\x98\xc4B&o_\xf1\xebG\xb1X\x15\xd5\xd2ic\x87}\xbd\xf7\xb9\xafn2v\xa1\x80!\x8c\xdc\x85kH\xf0U{\xa9\xb8\x87IW \x1f\x12\xf7\xd9\x96\xa8\xdc\xa1\xe5I\xe7\xc2z\xf7\x9c`#\x8c\xe3\xe0c\xe6\x0c\xe1\xf9\xf3\xe7~\xab\xb0\xc8\xe7\x1b!6\x9aq\xa8\xa7\xcf\x9e\xea\xa1\xd0\x88\xc7a\x9e}\xffL\x0f\x93\x92I1&i&\xc1\x0c\x1f\xccd\xe2! \xf7\x8d\x01nI\xc6\x83\xdb4\\\x0ej]|\xf6\xfd?[\xf0\xfc\x10)k\x8e\xa5\xdd\x01 8'\xf1\xb2\xec\xe9\xd3g\xed\x01I\xc0\xda\xb8\xbf7\x82\xd5\x87\xfe|\xb3\x8dE \xd9\x18\xfd\xf3\xcd-3(C@mH\xcf\x9b&\x06'\xd8\x98\x10\xb2\x1c\xc4Qr\x1d%\xb3\xfa\xb8\x9eo\xb61[\x83V\x06\xf7|\xb3\x8d\x83\x1al\x1c\xde\xd3\"\x97\xc0m\xcc\xd6\x80\xcb|K\x83<\x9c\xe1\x1c.I\x1a|\xcc\xee\xb0\xf2\xb7}+7+\xb6'~Bo\x93\x98\x86\x93A\x91\xc6r\x96\xbekA\x914\xad\x93\xc6\xd6\xd3v\x1f\x18\x10\xdeG\x18\xe4i\x98dS\x9a.H\x9am\xcc)\xbd\x16-?mO\x95\xa1R\xedGB\xf3\x01\x9d\x0eP\xc9\x16\x0d\xb5\xc9\xa3OC\xcb0\x0d\x17$'\xe9\x80&\x84Nec\xed\x89\xeb\xd3\x18\xd3d\x96\x03\xe9\x0e*\xdbj\xcf+kK]\x04[\xedE\xc0@\x1ak\xffi\x9bN\x19Ts\xe9?m\x13(\x8f\x9dP'\xcd\xf6\x8c\n(\xba\xccxV* \xd9\xee\x1c\xa7\xdb\xc6\xce\xa0YF\x02N\x1d\xea\xd36\xbd \xa8\xe6h\xdb\xd4$\x00[\x03n\x0f%\xa6\x8dm\xe6\xbb6Rh\x98=knn\xed\xceq\xa8\"\x9f\x0f\xc8]N\x92\x8cAo\xe0\x06\xda\xdct44\x83\x95\xcb\xe3\xc5l\x83\xf1\xa0\xabp|\x9d\xc9\xd5\xa7\xc1F\xb3\xce<\xcf\x97\x03\xd6\x01YG\xc3M\x9au\xd4\x89\xd6\x90C\x13\xbc\xda\x1c\xd8vQ\xf6\xad\x8dVs\xc5\x8c\xa7X+\xfb\xd8\x8d\x8b\x94\xfc\xbf\x82d\xf9\xe0\x8aN\xee\x07d\x12\xe5\xb4\xdc\x93\x9e\xb5\xf7\x04[\xed\xb2\xc3m\x8aiV\x13\xdd\xac\xb2\x1d\x95\x9fl\x13\xaf\xa1n\xf9\xb5\xf6\xb2\xc0\x1a5n\xf1\xcc\x80\xfc\xda\x04\x19F\xdb`\x7f\xcf\x0d(m\x92\xe1s\x03y \xe3Sh\xb8E\xbe\xedmJ[OO\xfb\x86\x8f\"\xb0\x82C\\HQN\x16%\xde\x0d\x0b\xa0YQE\x98F\x04\xd1\xd6Q\xa38p\x1b\x93D\x91\x01\xe3\xcd\x06\x16az\xcd\x98\xa1\xfc\xaea2[\xd5\xe8\x84\xc4r\x80\xcf\x0d\x84\xd5\xacD\x938J\xc8\x00\xaf\xb6\x859M\x07W\xe1dF\xe4\x97\x0d\xb4\xd6l\xa4df\xd5B4\xac\x89f\xcd\x1b\x9e\x02r\x90\xe5\xe1bYV\xd6\xec\x00 \xd6\x8aINjs\xb2\xd5\x1ef\x86\xb71\xb3\x8d\xa9\xc0\xdf\xd6\xf7m\"\x910\xb5\xad\xba=\xbd\x8c\x06\x9b\xdcF\xd3\x18\x83R[\xd2\xec\x94\x08\xd3\xe04\x9a\xcd\n\xc1\x1aD\xfeT#U\"\x9cF\x9c~\xde&k\x99\xd5\xeecc\xb4m\xc8\"\x8f\xe2\xba\x8c\xdc\x9e\xc4\x9b\x88\xdc\xd6`\x9e\x1b`RJ\xf3A\x94|$\xe3\xbc\xec\xdcw%\xa46]\x0d5^\xd8I\xdc\xa8fly\xd0\xd4\x8e\xda\xb5\xa5\xad9\xbd \x8d[Z\xfc\x06M\x0e\xeb\xb0U\xbb8S\xbf43\x8d\x92 ,\xf8\x0d\xa1\xaf\x1dX\x07\x02\xeb\xe0|\x1d4\x0d\xbdR\xd7V\xfa'\xff\xa2\xc15\xb9\xb7\xe6O\x16\x95\xc5\x11\x0e\x83v\x95\xcb[\x0f>\xd0 %\x19\x8do\x08St\xeb\x17\x1d)+\x8d\x98\n\xbe\xb5\xf9\x0d\xc7\xee\xc3\x07\xef\x1f\x0f\xde\x8b\x7fll\xfc\x1f\xc8h\x91\x8e\xc9Q\xb8\\F\xc9\xec\xdd\xe9\x9b\x9d*\xc3\xe1\xe0\xaaH&1[\xe7\xc1\"\\\xfe\xe3\xff\x07\x00\x00\xff\xffPK\x07\x08\x05\xef\x9fw>9\x05\x00\xf8\x0c\x1b\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1f\x00 \x00swagger-ui-standalone-preset.jsUT\x05\x00\x01\x80Cm8\xec\xbdys\xdc6\x9a0\xfe\xff|\x8aG|w\x152M\xd1\xdd\xad\xc3:,k\x1d\xc7\x9e\xf5\xbb\xf1Q\x963\xf3\x9b\xb7\xa3UQl\xb4\x9a1\x9b\xec\xe1!Y\x13i?\xfb\xaf\xf0\x00 \x01\x10 \xd9\xb2\xb33\xbb5\xacT\xac\x06A\xdcx\xeec\x0b\x16U\x1a\x95q\x96\xba\xa5\x0f\xc4\x83\xdf\xfe\x00\x00\xe0dW\xbf\x92\xa8t\xe0\xf4\x14\xca\xbb5\xc9\x16@\xbe\xac\xb3\xbc,`{\xdb\xf4v\x95\xcd\xab\x84\xc0\x19\xff#\x10\xb5O\x81\xb8\x1e\x1c\x83#\xba\x91?\x9a\x93E\x9c\x12\xda\"\xfb+\x08Ws8\xe3?\xdc\xd9\x05\x0e\xe8\xb8k0g\xe2\xaf\xe0\xfc6\xbc\xbe&\xf9\xcfo\xce\xcb0\x9d\x87I\x96\x92\x0f9)HY\x0f\xa1\xec\xab\xf3\x87\x07\xb7\\\xc6\x85\xdf,\x89X\x8e\x9c\x94U\x9eJK%^\xd0\xe7&\xcc\x81\xc0)\xfc\xf6p\xf2\x87\xbaPT\x85\xd4\xcd\xe5\xca\xf4\x89\x17\xe0\x92Y~\xe1\x89v\xe9\x0f\xb1b'JU\xdavLG7\xcb/h\x17\xcaKl\xeb\x18r\xbfU\x9a\x1c\xc3\xd6\xa4]\xcc\xbb8\x86\xdf\x1e\x94w\x0fj\xa7|T%\x1dU\x14&\x89\x1b\x8b\xc1\xf9\x10\xfb \xfdJ=\xfa3\x81S\xd8\x1aK/\xea\xd6\x9anx\x9bi\xb0\x82S(}H\x83\x88N\x8b\xfe1\x87S\xf5\x10\xfa\xd0Z\xb24\xc8\xf8\xf9\xbc\xbf\x87\xf7x\x1c\x02vL>\xe4\xd9\x9a\xe4\xe5\x1d\xff\xb2\xbdBQ\x96.\xe2\xeb*\x0f\xaf\x12bY\x96\xb4Z\x11\xf1~\xdc~\x7fM\xcac\xc8\xd5\x15\xf3\x9a9\xd29\xa4\xca\x1c\xf4\xd1\x8b\x13R\xd2\xa3^\x06\x97\x97\xa4x+\xeeK\xeb\xac\xc9\x8f\xd8 :\xd7\xb0JJu\x0cp<\xec\xeb\x01{\x9d\x06s\x97\xf8\xe0\x84\x0e]d\x1f\x88:\xbdL\xdf\"\xbd;\xde\x0c\xdf\x99u\x9e\x95\x19\xbd\xa9\xc12,\xde\xdf\xa6b\x8f\xd8i\xc2\xef\xd5\xf6\xd7p\n\xce\x93y\\\x94\x8e\x0f\xa9\x9b\x06\x14pL\xc7\x07\xac\xda\x83;\xd3\xceG*\xf7\xefT\x05\x81\xa2\xcc\xe3\xa8tN\x94[\x99\xc3)\xa4\xee\xfe\xd4S\xf7\x94^\xa8\x99\xf39N\xe7\x8e\x0fNN\x8a,\xb9!\xf4\xcf(K\x8b2\xaf\":\n'N\x8b2L#\xf2~A\x7f\xads2\x8f\xa3\xb0$\xec\x935\x05\x1b)\xd6\xe3[s^\xde%\xf8\xb2\xa0\x7f\xbcH\xe2\xb0 \x85s\xa1\xf6\x9ca\xcfE\x14&a\x8eu\xc9_+\x92F\xf8\xdd*\\\xaf\xe3\xf4\xda\xb9h\xe6PJ`\xb4s\xf9\xe9dS\x1f\xaa\x936\x9c\xa1\xb7\x8c^\x9a\xdf\x1e|\xb1=\x9f\xc9]\xe1\x12/Xd\xf9\xab0Z\xbau\xd3\xadvE+;\x138==\x858\x88\xd39\xf9\xf2~\xe1\x12\xcf\x83r\x99g\xb7\x90\x92[\xc8\xdd\xef~N?\xa7\xd9m\n\xd9\x1a\xa1\x9e\xf3\x1d\x8c\x80\xc0\x08\xbes .`EJ\x88S\x06\xd8c\xac\x90-X\x9d\x92\xd5\xf9\xcb\x8b\xb7?!l\x0f\xbe\xf3\xb4\x8b\xe6\x03\x05\xcaA\x19^3\xc8\x81\xbf\xe8\xe6\xd1\x99\xb1?\xee\xef!\xad\x92\x84\xbf\xe3\x1b\x8a\xaf\xc5\xdf\xf7\xf7\x83\xae\xca\xd6X\xed\x9c\xb7X\x9f\x0bl\xb3\xf9%\xb7\xda\xba\xf4`\xbd\x81\xbc\xd5\xe6\x80a\xb3\xd2Ou>\xf5\xd1\xc3j\xcd/}\xd6\xfcL\xf2y\x8b_j-\xf9\xb0bE\xa5@\xad+\x1fd8\x057\xc5\x0f\x94\xd2\xfa\x83\n\xf1\x9f\x8f\xbf`\xeb\xf4\x14R\n\xea\xe4\xf3\x96\x1a\xce\x9bq\xcd\xd2Yy1\xf0h\xd2\xa7\x9a\x9d\x97y\x9c^\xbb\xc4\xa3\x18\xb2lUzh\x1f\xa8\xca\xf3\x81\x1f\xe9\xac>\xd2\xf5\xb9\xb2\x1dm\xd0F%\x1e:\xba\xc8\x87\x85\x0f\x89\x0fk\x1f\x96\x8c\x06\x81\"x\xdd\xa6r\xe83\xaf+\xfc\xd1\\\xe1\xa6\xaepn\xaepWW\xf8`\xaep]W\xf8\xc1\\\x81\x12\x88\x94\x0b\xc8\xe1\x18n\xe8\xbf3\"N\x17A\x1a\xf8\x81\x12\xf3\xae(\xfe\xed\xc1k\xe8\x0ds\x8b\x97\xbc\xc5\x98\x9eB\xd1Z\\\xb7f\xfe\xe8\nN\xe1\xb2i\x19\xbf\x91\x7f\xe3\xa7'\xadO\xe9\xf5w#Dvx\x98\x10hz\xb8?\x94Lv]\n\xec\xb7\x96\xf4\xdd\x8a\xfe\xef&\x8b\xe70F\x90\xb9\x9aE\x17\x1e\xe5\xa0\xe0\x18Ro\x16]\xf8@\xe9\xa2kZm\x01g\x10\xba R\xc6\xc7p\x87L\x98\xe9\x0e'X\xef5\x7f\x83\xf4\x96\x0f \xfd&\xf1Y\x87\x95\xbb\xf2\xe9\xa1\xa0P\x1e\xb7\xe1g\xcf\x87\xcbYt\x01[\xa7\x90\xe0\xcdu/\xb1\xc6\xda\xf3YOW\xf2[\x17\x7f\x9dB\xa2\x81\xd5f)\xf2 bw9\xf6\xe9I\x83S\x98\xd0?\xfeHI:\xfa\xc79\x9c\xc2\x1e\xfd\xe3\x03\x9c\xc2!\xfd\xe3\x07Z\xe7\x80\xfe\xf5g8\x85]\xac\xf53\x9c\xc2\x01V\xfbH\xdfN\x0f}\xe5\xc6\x17\x9b\xdd\xce]\xe3\xed\xdc\xd3\x8b\xf9\xed\xd4\xef\x1b\xbd\x9dO\x9c'\xd7\xed\xcb\xa9\xf7n`]@b\xe38\xaa\xca\xdc\xd2\xb3\x1c;\xda\xa8\xf3\x8c\x02H\xd2>\\\x1c\xde:N\x83b\xdd\x10F\xa7\xe0\x00\xfd\"\xa5\x18\xe7\x14\x91\x0f\xef(\xf7(%\x90\x84\x11q+\x1f\x9c\xed\xbfVYy\xe2x\x88\x99\xbe\xf3|\x08a\x04\xces\xfamL\xffz\xf6\xc4\xe1d\x9b\xf3\xdc\xb1m\xeffD)\xe7\x8b\xe5\xf2\x94a \xe2\x86\x9e\x0f\xb9\x9b\x07\x1f`\x04y\xf0\x1a\xbe\x87\xd8\xed\xa4\xd2\x04\x1f\xe580+/\\:\x07\xeb\"\x11\\#\x12\x94\xd9O\xd9-\xc9_\x86\x05q\x91{$A\xb1N\xe2\x12\xbf\x0e\x12\x92^\x97Kx\x0e\xbb\xeat=\x1f\x1c\xb6\x86\x94!\xe9C\xdc}\xe8\xc9\xa9R\xc6\xac\xce\xe9\xce\x89\xbbz\x1b\xa7\xf3\xec\x96n\"\xfb+x\x1b\x96Kz\x97\xf1\xdf3\xf1\xfe\xd8\xf2yA\x92\x05\xfd\x98\xfe\xab\x7f\x8a\xef\x8eA\xc0\x01\xd7\x11\x84\xe82.\x1c\xcf\xf5z\xf0\xe05\xc7\x83\xd7\x8f\xc0\x83G\x9d\xa4\xca\xbe\x8e&\xd9\x8d;\xfa\xdfC\xaa\xd8\x89\xb8\x03\x9d\x16\xa0Kb\x90m\xc9\x1b[o0#\xa5\x91d\xe5\x7f\xf27\xed\xe5\xcc\xe9\\b\xfa\xbf\x01\xfb/\xaf^6\xf8p\xbf\xc8\xf3\xf0.\x88\x0b\xfc\xd7\xdcX:\xb8\xb1\xff\xe57E\x9e\xf2\xb0\xb3J9nN\x17\xd0\xbe\x04;\xf2\xe9nM^\xe5y\x96\xbb\xce\xcb0\xfd\xae\x04\x8a\xdd)k\xbd\xcc\xe6\x90\xa5\x00\xec\xac\x9aey\x9bB\xb0\xa6\x15E\xb4e\xb9Vt\xb5\x9a\x1e\x94\xf3\x95\xdfi\x9f\xd0\xf6\xd2\xce\xd3\x89wq\xec\x03\xb9 \x13\xcfuXq\xd3\xfee\xd9\xc7\xbf\xcc\xfb\xf8\x97\x9b>\xfe\xe5\xae\x8f\x7fi\x18\x9c?\xdb\x19\x9c\xe5\xa6\xec\x08\xe5aV}\x8c\xce\x15o\x99\xb2Ns\xc1:\xd9x\xa5.\xdee\xa9\xf1.\x8ckY#3\xa0q-W\xc8\xb5loC\x88\x8c\x05\xbb\xbc\x94\xd5\xa1,\x0b\xf2\n\xc7\x90\"3\xb3b\x8c\xc3Rc^\x9a\xd3\x8f\xb5\xcf\xb0\xb6`rh#Y\xcd\xf7\\\xd7\xdc\xc8\xe9)\xb2:\xdd\x92$\x90H\xc6F\x90d\xa7\xd2\xc5C\xaf'\x05: Dr\xecf\xda?\xa0Oq\x1b#T\n\xf3\xebjE\xd2\xb2\xe0\xb4e\xdfw\xf4\x89\xc2\x82\xc0\xf8\xb8\xb7\x1eH\x02{r\x0be{\x0b\xf5\x07[\x9el\xde\xb2K\x0c\x94\xb5\xfe`\xe3\xd3\xc74\xae\xd0\xd4\xa6\xe7\xa1\xf3m\xab1\xba\xa1\xd6/\xecm\xd5\xea\x95p\xbdN\xee\xb8\xf2\xaf\xde@s\x8b\x0f\xe6u\x11\\\x87\"!\x904!\xb2J\xa5n\xcaE\xce\xfc\xa6\x93\x9b\xcfl\xdc<~\xe6\xba\xab\xe0&\xce\xcb*L\xf0\xe25\xbf\x10\x96x\x9cW\x17\xbc\xfeG\xfa\xcd%\xfd\xdf\x16\xb2\xfc(\x0f`\xdc~\xe2yV\x8e\xfe\x1f\x85\x8b\x9f\xeab3.dk\x953\x1cu\xa8#4\x8a\xa2\x8c\xca\xc3f\xaa$X\xb06\xf7=83W\x96\xd5n\x16\xccE!H\xee\x96\x9e\x8f\xb0'\xa3gtk\x8c\xdc.jL=\x03Y\x04\xcd!\xaa\xeaf\xd5\x0d\x91 \x9f\x87V\x7f\xce5)\x1d\n\xbc\x91\xb8r\n\xf1\xcb@>\xbe\x88\"R\x14Y\xce\x08\x8a\xa2Z\xd3\xfd \xf3-\x0bA\xe1\xdc\x84IEx\xdb\xf4\xd0\x95\x0cY\xa5\x01\xbe\xf0\xfcMI\x0e\xf9\x08l\xa5\xee\xf4\xc8\xb3\xf3\xfd|\x0cO)\x9e0+~\x7f{\xe0\x8a\xcb\xf6\x82\xa2\xe6\xb6S\xa4 w\xd1\xbe\xa0\xea\xfa{A\xd8\xcc\xb3\x9f\xd8o\xe4\x1f\x9a\x1a\xb4\x8f\\\xb4\xebWS\xa3\x06u\xc8\x92K\x82j\xcb%\xda\xdd\xb3\xb0\x85\xa9\xbb7\xf5\x14dk>\xf4\x82\xc5\x0e\x16\xbcF\xecNh5\x99t\xef\xbf:\xb5\xf1\x01;b\x1b\x9f-I\xe67\xb1L\xa8\x9b0\xdf\xa2\x17\xb7}iT\x1a<\x05\xc6k\xd8\xaeL\xdf\xa0\xfb\xf8`uX\xff\x8d\n\x8dne\xba\xb2rCd\x82\x88\x9bc\x1f2\x1f*\x1fB\x1f\n3\xa8\xa4@d\xcbHc!\x03\xd0\xc6\xb9\n\x8fL\xc9T\x88\xe8\x1c\xc9-p\x18\xf76N\x99B\x8e|\x89\x08SJgQT\xe59\x99\x9f\x00\x9dd\xb9$\x90f\xe9\xceJT\x9c\x93\x1b \xe9M\x9cg)\xc5\xffH\x0e\xd3J\x8b*I\x80\xd0VaE\x8a\"\xbc&\x10\xa6s\x08\xe7sTe\x87 ,I\xb2^T \xdc\x86y\x1a\xa7\xd7E\xa0\x9f\n\xfa\x90\xa4 \x1dD*E;3}\xb1.\xcct>}(\x86\x1f\x9bi\x11W]\nR\xcb\x80\x9f\xfck\xf1\xe4\xda`\xdedz\xf8A^\xcc\x92\xd1\xe8\xc2X\xeb\xc1\xf3\xbc \x0dW(\x91}\x93\xde\x84y\x1c\xa6%\xfc)\xce\x92\x10)\x99\xd6WmJ\x8c\xdd\xb2(X\xe4\xe1\x8a\x14\x9f\xb2\x0f\xd9\x9aQ\x1a\xd1\x1f\xcc\x1f\x0e\x82\x01}\x16!OM\x9c\xae\xa4\xac\xeeW\xec\x0b\xb6bvaa\xa3\xd8\xa5\x8eS\xca8\x90`]\x15K7\xed\x10V\xab\xb35_\xacD\x9d\nW\xf2\xca@.\x0b\xe2tI\xf2\x98\x83\xed\xdd}O\xfd\x84\xb1\xe8\x93C\x1d\x03p\x1e}\xf2\xd4\xd8\x16e\xbf*\xe9M=?\xdaK\xec\x86\x0d\x91\xeb\xf9x\x0b\xc7'\x10\xc13\x10\x1c\xd0 D\xa3\x91\xbe\x88\xe2\xc8\x17\xb3H[\xc2\xa4io\xb6`\xcc\xb1Vt\n\xa1R \xa3\xc2f\x94|\xff \xb1\x80\xf9\x16\x8b\x97x\x9e\xccY\xd0\xef\xd4\x91U\x1c\xfb\"\x9b@\x89\xbbP/@\xa9\xec\x16\xb3,(\x83\x9c\x84\xf3\xf0*a@\x98\x1bi\xf0\x92S\xd8\x9a\xb4\xea\xdf\xe6q\xa9\xd6\xafKD}Z\x18&Iv\xfb\xefa\xb2x\xbf&)7\xbdS\x1bRk\xd4\xad\xb5>\xac\x9b\xcc\xd2\x88\xb8\x0eA\x83\xa8u\xf7r\xae[P\xc3\xd0\xf6\xfd=+\xbd\x14\x138/\xc3\x92\x04$\x9d\x13\xb4\xd6\xc9\x83\x94|)?\xc5\xd1gw\xc9\x86\xd0\xdd\xe9\xb2\xbd\x87%m\xcd5\x89\xf2\xccTb\"\xf3b\x8e\x18\xd7\xbf\xc7\xd7\xcb?\x87%\xc9\xdf\x86\xf9\xe7\x16 \xa9\x18\x06j\x86\x83\xfd\xa4\xa5$\xd5\xd4\x17b)w\xab\xde\xfdfB\x9e?h*sR\x94yvG\xe6\xad\xe1\x0f\x1e\xa2$\xcea\xa3\x15\xe7\x14G\xab |\x0c\xf3i\x8e\x98\xfaeP\x8f\x8d\xd60-D]Acu4a\xa12\x113@\xfe\xfd\xa7\xd0X\x9f\xd9&A\xabx\x1d\xdb)m\\p\xc9\xbf\xea\xa3\xfc\xb1C\x86?\xaa$\x11\x17\x16\xcf\xbe/\xdf#\xe2\xcb}\x7f\x13499\xda\xb3\xea\x8a\xec\xbb!\x8e=\xaetN\xd7\xb56\n\xeb\xa3\x8a7\x1c\xdf\xde\xc1\x9e\x01\x8f\xbf\x0d\xcbe\xb0\n\xbfv\xeds7\xde|\x02\xd2\x80\xcc\xe3\xd9\xb73\x88LZ2\x90\xb5\xfb\x87a\x10\xa7\x87\x1b/\xf0\xdf\x85A\x1c64!\xaci+\xc1J8\x93\xee\xa0\xcd\x19\xe3\xdb\x8f\xa8S\xc8\xb5\xb5U\xba\x1d\xf2-\xebg\x9a\x85\xeec\xf7\xdeb\xaeg\x16$\xee\xeb\x06\x96\x8c\x90>:\xf4\\\xa7\xc8#\xdd\xd4\x81\x92\xd3\xb5\xd0\xb6\xcc\x98\x1dI[\xfd\xe5:\x0e\x8c \xf4\xb8=\x8a#j\xca'\x06-\x08\x838-\xd6$*\xcf\xb3*\x8f\xc8\x90C \x08S\xe9f\xf96K \xc1\xa5\x87&\x12=\xb2Y`\xa4\xea\xa9\x8e\x10\x7ffn\xea\x83CYB\x07\xf5@q\xf3\x9b\x1e \x8a\xbc\xe8\xadm\x8c\x97\xa4\xcf\xaa\xe6\x8b\x8a\xd7;\x03\\\xa1\x92i\xb1\x8a\xe0\xd7,N\xdd\xda\xda\xd7\xc3\xf6\x90\xe2\xcd\xe1\xac\x86\x07p\x0c\xa1\xf8\xa9\x94\xc6\xcd\x818\x06wN\x12R\x12|\xefK\xaf\x14K\x8fF\xf2.\xd3[\xf56u0\xd2\xe2.\x1a\xef\x19e;894\xab\x90\xc1\x91\xf8\x08\xb9\xffot\x0d\x7fo\xc0\xb01\xd66_\xbd\x03\x93\xa2\xd9M\xdd\x83\x03\xcf\xc7\xf7\xe3\x86 \xb69\x98\x18\xaf\xe9\xe4@7\xf3\x0b\x8d\xaeT\x9f\xc9\x9d\xd9\xff''\x0b\xf3\x8b\xcb\xcb\x82$\xf6wx]\x8f[ \xcb\xe4%VX\xb7M&[\x83\x9c,\xa4\xcdh7\x13\x0dk\xe63\xb9\xd3\xf6\x14$\x96\xbc\x0d\x1ar!\x962\xc2\x88\xb6\xbc\x92>\xff\xf2/\xec\xf8\x1cC\xd5^\x1c\xfa\xea\x18\xca\xf6\x0b\xdc\x03\x83v\x1b\xb7 m\x97\xaf\xf3l]\x1cChX\xff\xec6%\xf917j\x12\x8f\xd9\xfbI\xb2]\x91\xc4\x1cA\x94\x93\xb0$\xaf\x12\xb2bn\x15}\x94 \x9e\xf1\xda\x17\xa25\xa2\x84\x9e\xc6*I\x0c\xb3\xe0o\xd4\xc1QZ\x83\xdfNY\xdc/\x1e\x14\xc3\xe4\x10\xd3\xc3CP\x03\xef\xae\xb9\xef\xc7\xc2\xf3!\x12\x85 3\x98\x1c\x01\xa1\xfb\xee\xf9 \x8bM\x03v\x84\x05\x1c8\xaeK\xda\xd5\x18\xf2Q+b\x19\x02\xa5\x8c\x810\xe6\xbb\xb7\xbd\x0d[\xa1v5]V\xeeV\xcc\x93\x11\xfd\x1fOZ\xcb\xb7\x84S\xd05\xe8\xb0\x03\xd3\xf6\xca0Y\xc7\xd2\x83*\x88\x96q2\xcfQ\xa4\xa1\xa1%\x94\xb9\xd2\xdaKx\x0e\x13\x13YQ\x0b\xb3\xe6\xc2\xac\xcd]\xd25bb\xac\x1bx\x06\xcb\x13\xb8\x19\x8d<\x98\xcfn.\xe4\xd1\xcdn`\x04S\x83\xfco\xec\xabc\x9a\xab'\xb05\x13\xee\x15\xc8=q\xe8z\xb5\x84\xe4\xc0\x97\x07\x8dO\x94\x9a\x16\xf1#\x9e\x8b;O\xdeD\\xi\x07\xee\xe8\x0et\x0cM\x08\x80\xe9ig\xee\x03c\xfc/\x0eP\x8a\x9e\x96\x14g7\x17\xc7\xaf/\xcc\xeb0*\xb3\xfcn\x90G\xa4v\xc9\x82\xab8\x9d\xbb\xdc\x07\xc9L8\x93@(\xd75/\xc5E\x10%YJ^\xa4\xf3\x8fL\xdc\xfd\x1f\xa4\x97\xb9n\xe6\x18p%\xbd\xcf\xa0,\xfd\x87\xdf\x03\xfa\x07?\xe7e\xc0\xa0\x8a\xcf4\xfb\xebB\x9f?\x1d\xc0f\xf0\xa2\xaa\x0d\x9brTd\x8a\x86\xdb@\x02m\x9b\xe8\x15n\xbfB\xc1\x03\x0e\xbb}j(\x12\xed\x9a\x8b\xb79\xd0\xa9\x14\xa03\x17@\x87\xdd\x9a\xfax\xc80h\xa9\xc3 \xb6\xde\xec\xe0#\x1e\x97\xcft\x0d\xb6\x0c\xef<\x0d\xdaT\x16h\xc3\xca\x15\x15\x11%\xb6T9P\x02g\xb0\xa6\xc5\xa7\x90\xd0\x7f\x8e\xc5/Z\xd7\x00\x9d\xee6\x84Nw\x1e\xac\x87@\xa7\xbb^\xe8t]C'\xbaz+\x06\x9dV\xf0\x0c\xeeN`E\xa1\xd3\xf5l\xa5B\xa7\x95\x05:)\x03\xba\x1et\xff\xf9\xddX\xfa0\x17@\xe0F\x95\x13\xd3\xc3\x1f\x17\x7f\n\x93xn:\xfe\x9bP\xa4\x8a\xbc\x88\x1d\x10AJ00&\xf7\xaa\x10\xc0\x7f\x80~\xe2T\xd2\x0e\x1f\x98Y\xc0\xdd\x83~\xa9@\x87\xb3\x03c%\xcc\xa0+wS\x8f\"P8\xe6\x87\xb0\x99\x8aq\xec\xfa\xc09%\xa6\xab\x8a\x8d\x04ef\x10\xd3\x0b\xc3R\xae!-H\xf9)^\x91\xac*a\x192\xb1\xc5\x15!\xdcK\x97\xcc\x9dn\x91|\xd5\xdfA\x94\x900\xff\x8a.B\xb3\xfc%\xc5s\xd0\x8c\xbe\xd6\xda4Et\xf9\xc6\x06\xc8\xc6\xbf\xcd(\xd3\xb5\x95\"\x880\xb4C\xf7\xb1)\xf6{\xda\xed\x94r\xa4\xec\x0b\xf5\x9a 9\x87\xd1\xa7\xd5\xdc\x1c\xb4l@8\x92l\xb5\x0e\xbd=\xb4\xdb\xe2\n,s[\x16\x10\xf1\xb0eg\x7f\xcdsHm\xb2\x04\xe9 \x9e\xc9?Z\xc4{\xa7\x80(\xad=\x18\xea\xfa\x03\x06\x95\xdb\x06\xa5\x1c\xde3\xf5\xe7\xb1\x04\x85\xa0w`\xb4\x8b\xca\xb6\x8a\xae\xa6\xa2-\x98\nu\xa6i\xfe\xd1\xfeV\xd3@Q\x0c\xb931]\xfe\xb6\x8e\x8e\xf9? J\xe4M\xd5\xeaY:9z\xe0\x83(K\xa3\xb0t#\xb4/\xc4\xb6}\x88D\xa5\xedmX\xba^\x9f\x96\xcet]\xb7\x166j\x96\"\x89\xd0]\x1b\xd4\xe28F\x83uC\x8d\x0f)\x01\x18\xd5\xfaerb;\xe7\xf8\x01\x85\x92\x91X\xd7\x13\x18\x8d\x12x\x86\xdf\xe0\x82\x14\xb3\xe4\"\xc8\xab\xd4\xb5X\xbc\x8a\xa5\x90\xbb\xec\xb9%\xc0%|\xec\x8e\x9a\xf6N\x865\xbc\x92\x0b[Jk\xbd\x1d\xdeP\x85 \x90\xf1d\xc6F\xe9\xa9\x95_\xf8\xc3\xbb\xb1\x830\xf1\xe4n\xd9\x864\xe2\xe9\x87^\xe2\xe9\xef\x08d\xb5\x83\x0c7\xed\xdd\xc3FC\x80V\x07\xc2\x1a\xa0\xbb\x03\xfb\xec\x8do\x1e\xf4\x05{\xe8\xbc\x89s\xbb*qQ\xa5\x92&3\xa44%%x;\x9b\xbbq\x15\x8b\xd3\xb8\xd6:\x0e\xe2\xf1(E\xc0hW\x03\xed<1`\xe9V5J\x1d\xdba\x01\x9d\xcf\xe4\x04Rx\xd6\"\xceO \xa5\xc41\x99\xa5\xb4+\x95@N5\xe28\xe2ZVr+\x96\xcf\xf3a\x82th\x0d\x05\xef\xef\x01\xa3s\x84\xeeR\xa1~\xe7\x92D2\xaf:=\xa6\xc4&p\x9bs)\xde\x06\xee\x85\xd2l\x1c\x94q\x89\xd6\x1f\xceU\x9e\xdd\x16$wh!\xff\xbb\x89\xba\x94\xde\xf0\xf0\x1bq\x10\xe6\xd77\x0c\x7f@\x1cp\xbbAd\xbe\xa4\xdfE]\x1b\xdf\xdd\xe0w\xf3\xf9OqQ\x92\x14\xdb\xbda/Q\xd9\xc0\xfe^,\xc4\x9f9Ye7D\xaf\xccJ_$\x89xQ\x887d\x15\x97\xe2\xefuN\xd6$m\xf5\xc4\x8b\xdf\xa7Q\xab\xddDj\xae\x97\xa1\x98]\xa8\xabw\x15\xa7\xf38\xbd\xeeVR\xe9T\xeb:\xcf\"R\x14\xf5\xc7\xb1f%\xedh[\x14\xdd\xce\x07x\xc89O\x1c\xed\xb3\xe5\x0f\x18\xd9&\\\x88\x91R\xe22y&\xc8\x81\xb3\xe1\xbd\xf9\xd3\xab\xcb7\xef^\xbfy\xf7\xe6\xd3_\xb0\xc6\x04\x9e\xd8V\x9a|)I\xda\x8a\x8bh[\x02\xa6\x9dk\xd3Q6\xf9-.\x0d[:7S-\x9f]\xe2y\x0d\xed\x04\xcf o\xd6\xae\x9c\xc5\x94\xc5\x9e\xa5\x17LD\x1a_|\xfb+$J%9\x9d\xd9]\xa5\x15\xd4\x8fYj\x8c=\xd35\xac:5v\x063n1\x95 N\xa3\xa4\x9a\x93\xa1\xa1\xcb(\xa7_\xf7\xa5\xbc~\xe0\xc6\x0fC[2D@3\x8c_<\x84\x85\xc7C\xe5.\xfdk{[\x84\xc6ce\xf8\xe7\xf66\xe4\xc2\x12\xbd\xd5\n\x1d_\xca\xde\xea\x9c\x06\xbeY\xc4IIr\xb7\xf3-IN(\x11\x17\xa2\x17\n\xfb\x06\xc11z\x0d, \xd4\xe3\xa740d\x0b\x08\xa1\x88\x96d\x15\x06\xf0F\xbcb\xf1\x0d)>\xc8\x16PT\xd1\x12[(Z\xc4a\xe0\x18\x8e\xe3\x12C\x1b\xae\xd6qB\xe6o\x9a\x95\xab8\x0b\xeb\x88\x018>\xcc.\xf4\x0f^}i\x7f \xd6\xd3\xf8\x01E\xcco\xc3u\x17E\nB0\xc4n\x90\xd1\xae\x80>l\xb1\x8e\x8dZv|\xcf\xc3j\xdak\xf0`\x9b\xf6\n\x8b0I\xae\xc2\xe8s+V.}d\x89{\xfdA\x07\xce\x17O:cW\xf1b\x86\xd7\x94\xf9P\x8a\x9e\x9a2C\x0c\xc3vw\x14\x90\x97\x0c\x90\x13\x83Z\xea\x04J\x86\xf9J\x0e\xbd\x1b\xc6W\n\xaf\xa8k\xff@\x12\x0d\xab\xe7\xc55\x9e\x16\xcb\x99\x90/\xb7\xf8+\x0c~|\xf5\xfa\xc5\xcf?}\xaa\xe5b\xa1`\x19:N\x848\x0d\xea07\xf1\xb5\xef\xf2\x80G\x01\xa4\x18\x97\xb6\x8e\xb3\xb1AyF\x9f\xab\x9c\x84\x9f\xdb\xaf\xba\x9c\xe1K\xada\xbd\xab\xc9f]q}\xa8\xa5/\x19\xc8\xfc9\xcf\xd2k`\x9e\x81\x08AD\x97x~\xce\x194\xe1\xbbP\xb3v]F\x01\xcc^\x81\x02vN\x0c\xd6N\xceM \xf3\xe5\x0b\xc8\x0d\xc9\xefz\x80\xa7\xc0\xb3\xb2\x1bN\xa8\x01*\x0dn\x9e\xd7\x916\x05XDn\x88\x83\xc6\x02\xdc,\xa7\x802N\xaf\x13\xc2g\xc8Mq=\xca\xa0\x95a\x9c\n\x98\xab\xbcm\xf9\xec!wA\x1e=\x8dl\xd3i\xd4\x81B\xb59P\xb8i\x9b\x81\xf4\xae5~q\x8f\xc9-\x84\xae\x01o1\xf4id\x89\x05\x1c?\xd6\x1d\xd3\x14\x11\x83\xcc\xa4\xb1M\x1bj\xab\xf8\xdb \xcaP2Ho\x05\xc6\xe4\x81Om\x16\xe9\x83}\xf9j\xcdl\xe9C\xac\x83\xad^},s\xee\x16\x06\xa1\x9b\xb2\xaf\x9a\x0e\xce\x0b\x8a$\x8e\x88{\xe8\xc3\xce\xa4o(\xdd\x0e\xf5{\xbb\xff+\x1d\xea\x87-\xeb?\x80\xd5\xf9\xb7:\xf7\xfb&?U\xe6\xdf\x12\xa7\x8f\xa3\xec\xb3\x9eC:@/+\xb7=\\7+\xf5\xf1\xa3&F\x1d4z\xfaQ\xcf\xd8\x91\x86\xda\xb8a\xfcJj\x19\xc3\xc1\xc8\xb21\xac`\xeaO8\xdc\x0e\xeeR\x81\x9e]G\xe6C\x1e\xaf\xe22\xbe\x19\xbcL*\xa1i\x04\x1d\xf8\xc2p\xbdX\xfc\xc5\xf6\x05a\xe5\xed#\xaeS\xb2FPW-\x16x\xe9\xcb\xfaG]\xed\xc1\xab\xddaR\xf7\xe0\xd0\x0b\xd8{\xb3@es\x0b\x06\x03\xe9\x8e\x1b(9-s=\x80\x08\x06\xf6\x97\x17o\x7fz%\xc2\xae9u\x82\xaa\xb0\xc8d\xdb\xc3U\x98\x7f\xe6\xa6?\xf8\x93\xc7V;mb%\xd1\xfat\xcd\xdc\x8a\xa7`be\x1ef\xb0p\x9bF\xcex\x02\x8c\xba\xa4\xc6b,\xf7\xa4\xe3\xf9\xf5\x90\xd7e\x95\x93\xf32\x8c>\x7f\xcaCth\xb4\xbc\x11\x86\x9cK9\x01X\x86q\x88\xb1\xac\xa05\xd1EYXhy\xbc\x8c\x0eY\xb2\xf6\xaa\xff\xca;,\x9c\xd8 \xe4HZ\xb9\xd5\xf2&W_\x8a\xb9\x0e\xa3U\xea}\x1a\x81s\x0c\x8e\x91f!h%\xd1\xb7 >l1\x07\x9dz\x1f(\x85C\x9a|$\xa6\xed\xd0s\x0b\xca\x94\xd6\xa0\x84\n\xbd\xf6\x026\xf7\x1d\x96\xcdK]\x95Z\x08>K\xdd\xe9x\xeaiV\xf7B\x01\x8a\xef\xf7w'\xe8\x88\xbe\xbf\xdb\xaa\xd7\xc8\xcb\xb1\xde.\xaf\xb7\xc7\xff\xdd\xe7\xff\x1ex\x92\xc5\xcbc\xc5\x9dv/\xc66(S\xcc\xda\xdc lCip,\xd4\xcc\xd6\xdc\xa9\xa5\x9ed\x00\xe7\xeeY\xeap3;Mm\xa0\xdd\x85!ru\xcd\xc4.\x17\x82\xcf\xb8\xa3Q\n#\xc8\xbd\xe6\x00\xef\x1e<>\xae\xce\xe3\x03\xfapV\xea\x11a\x89$%\x8a\x1e\xc4\x84\x87\xf7oE\x1f\xcax\xb9\xce\xb0n\x10=\x99\x05\x8c\xfdg\xf4\xe4\xea\x9bDO6\xdd\x8f\xbfOPa\xd3H\xf0ZF$N,7v\x91dY\xde7:\xcb\xd0\xe2\xe2]\xf8\x0e\x15\xce#\x14#\x8c\xe1\x18\\\xa1\xc1\xc81OZ\xbfD\xc1.\xaa\xe9\x0f\x10\xdcw@\xd5\x10\xb4|\xd4\x9a @X+\x18\xad\xb7\xba\xcc\x13xs\xf5h\xac\xe6_R\xe5\xb2!\x05\xdb\xf27\xfa\x18D\xd7]\xa6\x0b\xad1\xf4\xe4Nh\x0f\xc3\x1a\x9b\xdf6\x92\xdd\xe1#Ah\xb0\xe1`\x14E\xaf\xfc\x0c\x90N\xd6\x9dw0\x0e\"\x9b\x00\xb1\xa6\x12\xd8\x04\x1f\x0e\xbb.qoB\x99\xded2\x8f\x0dTf\x8f\xaefQ\xdaO\xc6\xbd\xb7\xce\x02\x0d\x1e\x15\xd6\xae\x8f^l\x85\xfc\xe2\xf2Z}\xf0\x0c+\xb62\x06VbNm\x19m\xea>\x16\xbe\xdc\xf0\xa8:\xa1k\xa4\xd7\xb0\xed\xca\x87\xc2\xe7\x99\xf0\x0c\x95(\x1e\x8efcC\x00\xe9\x04\xdf\xe8&G\xd9\xb0\xcc{\x1d\x9a/2+.\xba4\x9fZu\x83q\x80\xcf\x8c\x12xv\xbf\x96\xc5(\"\xcf\x98\x07\x00S\x1c\x17|X y\xc0\xe41\xf2\xab\xc2\x87)\x93\xb5\x9eu\xe3BhF\x96\xd4\xf8\x90q\x80\xfa@\xa0/\x16\xa9\xb1\x1d}6}\xc7Xn\x98\x91U\xbf=\x18\x15\xd0\x8f\xbf\x04\xc3.\x9f\xa2\xeb5y\xf01\xedo\x13p\xfd# \xa3\x92\x07L\xff?\x0e\xcf\x84\xec\x9c\xc0M\\\xc4%,\xcbr}\xfc\xe4\xc9\"\x8c\xc8U\x96}\x0e\xae\xe3rY]\x05q\xf6$\xa7\xdf=\x99gQ\xf1\x04?\xde\x99\x93(\x9b\x93>\x81\x9c\x999\xe6\xa3\x91\xc7,\xd5\x9d\xed0\xbf.f\x17X\x8f\xa4\xb4\x89\x9f?\xbey\x99\xad\xd6YJRY\xaf\x96\xc3\x08&\xba\xf2\x8c\xb5\xa1\x06\x7f\x17\xa2\x89,\x1f\x1e9\xbe\x89\x1a_\xf4\x87\x8b?i]\xff\x18\xe4\x10\xee\xba\xaa\x8e\xc1\xf4\xb83\xfa\xba\x0fq;\xacz\xdcs\xea\x06\x9d\x1b\x89\x82\xb2q4\x8f`\xe5\xebb\xf1I\x87\xf7\xcc <\xac^\xb8?\xb4\xff\x12\xeb,\xb7&\xc1\xb78(\x97a\xf9\x11[+\x98\xd8E)z\x1d&\x05Z>\xba\x18H[y\xf7)\xaf\xf8\xab\xb1\xfe\x8a+\x17r\x11\xcfW\xfdn\x19w\x9a\x8f\x88\xb9)\xf9\xf6\xb46^\xf0\x03>\x04\xa5\x9a\xfdO\xe0\x94\x1f\x94\x8d6P\x94v(\xa5\x9e|\xbf\xa5n\xd7\xf7\xf0iI\xe0\x8a 7W\xd9\xbcJ\x08,\xf2l\x05i6'\xc1\xaf\x85__D\xee\xf4\x1ah\xdf\xeb\xcd\xfd[X\x95\xcb,\x07\x80\xd7$\xcf\x8a\x02^\\e\xd5\xe7e8\x8f\x7f%Kx\xb6\xc0\xc2\x7fc\xff\x04Y~\xfd\x1c\x9e \x88\xd4\x94\xb5\x1a\x15\xf6H\x8aA\x12{\xf9\xa4uu\xb9\x1c\xaa\xc5?CC\\\xb4\xb2\xe4A\x93X\x0f\xef\x94\xf2\xb2\xbe\x10\xed\x98+\xd0le\x11|\xfa\xcb\x87W?^\xbe\xf8\xf8\xf1\xc5_.\xcf\x7f\xfe\xf0\xe1\xfd\xc7Op\x06\xd3\xc9\xde\xd3\xbd\xc3\xdd\x83\xbd\xa7p\x0c\x93\xf1\xd3\xdd\xa7{\x93\xc3\xa9\x96\xef\xd6\xd2ah\xc5\x95\x94\xe2\xa4\xc3yF_7\x86\x17\x1f\xc3\xf4Z\xf0\xc9\x14(%\xf1\x1cI\xd190Os\x865:\xcc+l\xb3p\x85\xbd\xd3\xcfqZ\x1e\nCc/\xb8\xbcDl\x7fy\x89!,\x1a\xf9\xea\xb1b*\x82l7o\x00}\x9c\xe8a\xe7\x18\x8c\xe5\xb8\xd3\xa1\x85y=\n\x1b\xc5\x06\xc2\x88\xcb5O\x80\x07\xc4\x97\x95 \x85\x9an\xa0i\xba\xbd6H\xde\x1b\x14\x0d6\x12\x0b\xeb\xb7\x15\x10\xcaN\x89MZ0\x1c\xc9=\x9d\x8b\xda,\xb9\\\x12\xe6\x86\xb2\x88\xf3\xa2\xac\x11?\xac\xaa\x02\xedgB(Z\xd1j\xe5G\x10A\xf6x\x08\x0f\xb63\x105\x01i\x0cr\x1c\xcb\xd6Db\xfd,\x0c\xaae\x0d\x89\xd9l\xe8;!\xb5Q\xe7\xcdm\x87BnR\xdf\x91~\xda\x9c\x89\x16\xcf-W\xe5lo\x03\x91\xcf\x83\xfc\xae\x1dK\xbb\x83\xedFW\xbf\xe0\xea\xae$?\xe1\x89\xf6\xd1\x0co\x0c\x98\xeb\xba)\x86g\x8d4K\xbf\xaa\xdfe\x8bEA\xca\xef\xe8\x11\xc8*4G\xbf\xca\xaat^\xd8vW\xef\x936\x0e#p1\xf7\xf0\xd8\xb3\xf6\xc3\xee\xdc\xf0~0\x00A#cI\xa5\x00n\xa7<\xf0o\x0b(\xd4F.\xd6*x\x81\x8fM\xc5t\x99\xcd#\xe9\x04L\xa4\x0b\x10\xd1\nk\x06H;\xaf\x8a\xc1\xd0O\xd9\xfdc\x93R\xb1\xc5\xd8tx \x1a>\xc7\x05\xad\xf3\xc9\xdf\xdf3\xe7P\xa7*\x17\x87][\xbfU\x04q\xf1\x8a\xc3\x0d7\xb58`\x7f\xe7\x08\xd0\xe2H`\x83!\x056\x94\x1a\xf6\x98n\x12H\xf8t\x0c\xf70g\x1bg\xf6\xd7\x02\x8e\\]\x16T\xa8d\x86\x8e\xb7y\\\x12\xd7\x02U\xd9'u\x96\x02\x97\xf9\x042#\xfc\xb1\x0f\xb1\xf7\xe8\xed\xf2\xfaL\x1f\xc5C\xd7\xb2\xa8\x15\xba\x141uH\xb3j\xd5\x08\xdc\xc3\xd2%\xc2\xe7\xc9\x166c\x08\x906\x9a]Iu\x82\xb8\xf8SLX\xda\xfdv\xb1\xc9\"L\xaa%\x8f\xb4!0\xdb\xa3\xad\xa9\x99-\xd5R\x0e\x11\x1dK\x1caX\xe2\x9b:\xd9f\xd7*pj\xb3\x1eIW(\xc2\x1c\xc3\xfb\x9d\x9cx\xb5\xa2\xcf\x8a Q\xbd\xe5\x84E\x14\xc7\x8eY\xc9\xc5j$a\x19\xa7\x93\xce*Wq\x1a\xe6w\x96* )w\xcd\xe8\x845\x82d^W/U\xb9\xd8\xe9\xac\xc1\x08\xed\xdeQ\xfc\xec\x96\x9eu\xc1\xa1\xe9.*\xa6\xdd\xe3\x89\x8a\x9d\x9e\x1a\xe5br\x90\x90\xbe:;\x1d\x95\xa0\x19\xf7\x14\xbe\xef^\xc1%\xf9\xd2\xdfJ\n\xcf\x9f?\x07\x83?\x114\xdb\x19\x16\xe4`\xaf\xbf\xa9\x1f\xfa\x16\xb2\xd37\x1c\xa0v\x0c\x19\xba1\xc0\x990\x96\xac\x86Ph\xf6SvK\xf2\x97aA0\x03\x19F\xa1k}\xaa\xebR\xcd\xe0\xeb\xa6\x8bc\x11w\xab\x9c\x11\x03\xec\xe7F\x14\x14\xfd\xf9\x02 \xe6\x83:\xbd\x93\x98*\x8b\xfe\xb8\x01\x01eM1\xf2\x05\xdb1l\xa3E\xdc\x92R\xee\x10\x85\x81\xdc?\x0eyNx.K\xe4\xce\xf0\x8d\"\xa2\xa3\xd8}\xa7.9D\x90F+Ie\x1ekp\x94\xfa\xdcB\x82\x852\xc6j1G\xce\xa5\x1ccQ\x88\x04D\xa5\xfa\xe5\x08i\xfd\x94\"\xc0\xb2#\x88\x82\x98e\xdc\xb9\x0e\xc0C\xe0\xc8]\xb7OF\x13\xf6h\\\x99\xc2J\x91\x86}\xda\x99\xc01\\k'\xcarB\x8c\xc2'\xde0\x81m\xa4u|\x8b\x9c\xc1\x86t\x1b\xf1\x85d\x10\xcac\xee\xc0\x19\x1e\x86\xae*\x8d\xe5\x0f\xe7Z\x8d\x95\x93\xb0(\xdfX>\xc0\xb9c\x12%\xfb\xec\x8d\xbc\xcbM\x98\xd4\x84\xbd`WD\xa0\x8a\x9c\x93W\xadP\x14\xe6\x1b\xad\xaf\xbf\x05\x98d,5\x8b%\xbc_(\x1d\\s\x8dB\xa2\x82\xcd[,\xa5\x16`\"\x05\x86\xd1\x18\xffM!\x01'\x04s\x0d\x8c\"=\xc4\x91\x1b\x17Za\x01\xc7ej\xd1\x8eTf\x95\x17\xc4,*\x91\xa0\xd8\xa7L\x18\xd8\xfc\xee\xbdWt\xa5\xa6>\x84\xf0\x04\xff-\xf8\xbf)\xfek\xb8o\xad\"M0k\x1b(\x1f\x06\x0b\x17U\x89\x8c]\xc7<{\xee\xcfo\xd2rr\xf0\xc3+\x97\xc0\xf7r\xb6\x11\xf1\x98\xef\xb9\xd5&H85\xda&\x8d4\x1d\xaaaN \x83g\x10\x9e@6\x1a\x99\x992\xe0\x9d\xe1\xf42\x0f\xc7\x1fQ\xf0\xc1C_-8\x1c\xce`\x07\x16\x9dr\x1d\xd1R\xfd\xa1\x88\xd2\x9dy>\xfb\x1cF|\x81\x8az\xdf\x16tA\xacMr \xbb\xc3\xc2\xd7\xb2\x163\xd89\xe5\xa3\xf1\xf9*X\x80\xb3}mR\x18A\x01\xcf!\xac1I\x08;P\xe08\xf9\xaa=Gf.\xdb\xd9\xe9\x9arM<'<\x88\xed\x9a\xf1\x80kx\x06\xc5 \xac\xbb\x16\x1d\x94\x85\x87\x11\xac=\x16\xa4\x97.\xfe\xbaw\xa5\x81\x9b\xc0\x98\xfc\xbb\xf5\x07\xe3\xeft\xd62\xcbq\x80\x0f1\xa9\xb7+3\xd6\xb3j@vt7k3\xe0[\xf5h\x07\xe8\x061o1J!\xdc\xdf\x9b\xf8\x18\xa1\x04\x97\x90\xb6\x81\xe2\xcd\x05-\xc3\x9b\xa3\x90\xe79\xc4x\x0chqLq\x01\xfea\xee!\xeb\x85\x9d\x19\xfc+L)/7\xb68r\x0bu\xe2\x92|\xe9P=\xe5\xf0\x1c2x\x02\xd3zh\xf8\xabK\xfeP\xb1\xb3W\xb1h\x87\xa3Q\xd5\x05>(\x9aX\x87yA\xde\xa4\xa5K\x82\xa2\xba*\xca\xdc\xa5|B\xe5\xc3\xd4\xf3ar\xd0!7g\xd4\x9a$(\xac\xccu\xcb\x19\xbdi\x98\x8a&\x1c\x00\xf4Dc\x83\x0e\xcde\xcf\xa1\xe1\x8d\xfd\xd5\xfd\x19s\nK\xc7\xc2C\x95\\\xdb\xa0\xd3\xd6\xd3\xd5\xd0\x9e\xec\x06\x03u\x9b\xb2\x11\xd2\xecB 8Q\xb3\xf2L\"\xc6\xb3\xed3\xc1Q\x19D<\xe4\xc4\x8b\xd2M{$\xfam\xc0\xf7\xc0dy\x9bL\xfav\xd8\xa4\x95\xb5\x19\xd4\xf0\x97a\x0d\xff\xd5\xfda\xf3A\x9f\x0fm{\x90VC\x0e\xec\xc0\x83\x93\xf2]\x93\xaeZ}\xb0\xb6\xb7a\xcbu \xc5NS\x0f9\x02~ \x19+!\xed_\xc5\xf9M\xcaO\xc3!\xcb\x84\x93R\xb0\xb1\x7f\xe0C\xc6\xb6=\xf6\xea?m\x9a<+H~\xf8\xda\x03\xff\xaa\x8b\x9fUY\x08\xf4\xe9TXL\xf4\xd5\xa7<\xc8\x0fw%\x91<\xa2[\x85\\E\x85\xfd\x0c\x1b\xd7\x8b\xaeq\xa5RL\xa1\x9af\x1c \xb2\xc5\x10\xf3\x18\x83\x1ab\x14\xddv\x81\xcd\x8c\x85\xf8\xf0E~\x93r\x16\x1bLS\xc5\x83N$\xc6L\x89\xe2A#V\xcaJ\xef\x1e\xc1\x19\xec\xc11\xfb5\xdd\x853\xd8\xe5\xbf&G\x138\x83)\x1c\xdbD/\x08\x91a\x04 \xad\x87[|\x83\xe1Z\x8c\xf8\xc5#\x8f\x8f\x81\x05\xf6kz\xe1kS\xc9p\xf4jY%\xcdh\xb2_\xcfh2\x85{p\xc5\x9c\xe4)Vt\x8a\xd3\xf1\xdeS\xfe\xdd3\xd8\xdf\x9f\x1e\x1dP\x92\x88\x92\xb3\xfbOw\xf7v\xbdo:\xff\xbd\xc7\xcf?\xac\x7f\xedn\xb0\x1ajYhY\xa1Cm\x85\xa4%\xab\xd4%\x0b\xe9\x92\x1d\xec\xef\xef\xee\x03\x06\xf4x\x06\x93\xc9do2\x99J\xcbd\x9c\xa2\x99$\xae\x8d\xb1(_\x84\x9f\xd3\xb6w}\xbc\xc9\x18tl!\xf7\xe7.(>\xa0?\x0f|\x11\xb5x\xc1\xc4\xa8c\xd8\x86\xc9x\xba\x0b\xf7l\x1397\xb3\x7f\xb0;\x1d\xc3={\xb5\xcd\x0c\xc2\xf9w\x1e\x05T\xa3SH\xda\x10\xdf\x06\xa5\xfb)\x12A\x8c\xd8\x15 \x14\xe3\x14\xbc\xbc\xafI>C8,\xee1\xc2\x13\x85\x1b\xf5\x16 \xe9.\x1c\xc7\x0e\x18s\xb32\x10\x04\xf4\x16\x06\xd3\xdcXz\xc0`8\xba\xc9}\xa6\x9a{\xdfCD\xa5\xedEv[\xe8S\xfeE\x82\xda\xb7\xbd\xf0\x81\x04\xe7Iv[\x97t\xef\xc3\xa8l\"\xab`,\xdc.\xbbBT\xdd\xb9#S\xa0\x837\xef\xce?\xbcz\xf9\xe9\xf2\xed\x8b\xff\xef\xf2\x87\xbf|zuN\xcf\xd3\xd8&\x8b;U\x93)\x9b\xcd\x82\xcc\xe5=\xb1\x13\xed\xf9\x8cn\xa4\x88o\x92\xc9\x92\x9e=G<\xb5\x02M\xb6J\xb2\xe3\xb4\xba\x96Y\x00\xd8\x81\xa8\xb3l@8H\xf1\xf0Q\xed\xb5\xe5G\xe21\xc3\x8e\x07\x1f\xf6\xa6\x9cVZd\x99\xebY\xc5\xa1%e\xc8\x98\xa5\xe9\xf6\xb6p\xeb\xad\xcb\xdc\x89\x0f\x13OR*\xb6\x8fjg\x0c4h\xe6\xb0e\x90\x9d\xa8\xe7\xca\xf5\xe8\xc9\xfa\xfc6\xfc\xc2-\xe4P\xc5L\xcf\xd4:\xcb\x92\xf3\xf8o\x14x\x1cN\x8e\xa6\xb4\xe82\xac\xae{M\xb6\xc1\xb6\xb1\x85\xe2\x0c\xa3\x1fo&\xd8\x1e\xe0u$\xb5\x1f5\xe9\x05\x0d\x16\x98\x1dBjW\x1a\x8b2F\xe3\xb9\xa237\xd6\xf1-\xf6\x93<\x9c\xcc\xf66\xff+@{U\xc2\xf3\xb8\xa9e\x17LbF_\x99\xc3\x9c\x16\xbe\xd6\x8a)\xe0)wh7S\xa3\x9d _\x1e\x98\x1a\x01\xc1\xcef\xab\xbf\x81\xed\xa7\xf8\x02Y>D4ca\xd6$\x1bB2\xf3\xbe3\x93\x05`\xde\xd4\x0f\x161\x0b\xea\x86\xc6\x86j\xa1Tb\x00\xf0}\xa7\x05\x17\xe1\xe7\xb4\x08\x17\x83\xe3\xafX2\xb5\xe9\xcdQl\xf1-\x9a\x94\"\xac\x0cjk\xcbmb\xa1\xdd\xdf\xc3V\x19\\\x8a&\x0c\xadG\xd9j\x1d\xe6\xa4\xcf!\x1bd\xf3\xca\xdar\x03\xdb\xd7\xf4QF \xd9\x8b:\xba\xb7P\xac\xb0/\x8c\xb6&\xcc\xf0Eu\\\xee2s\x90\x15{\x8c\x0d'\xf5\xaf\x98\xc5\xa1\xcfdN\x92\x99\xd2\"k\x98Q\x86\xde\xe2t\x8b\xc3\x98\xc5\x17xD\xc9,\xbe\xe8B\"\xa9\xe0\x1cY\xff\xad\x0c$\xf2c\x97\xddZ\x89>\xccw\"\x94zh\x8e\x04g0Q\xe2\xe1Bs^\x84\xf9k\xef\x89\x11l%W\xfe\x94-\xe5\x8fy\xc2}\x06\x06\xdf\xca\x84\xe3\xbf\xc1\x1ee\x80\x8d\xc3?\xa8\x01\x88) )\x0c1\xb3\x18L'\xf8u\xe6\xd5\xc1\xd0!\xb3\xa6\xbc\xfa\xceI\xe2\xa24\x99N\xf2\xe0{\x90-\x04P\xb0YQZ\x0c\x1f\x04\x01m\xa2\xb1\x11>\x98[S\x02$\x18W\x0b!\x0ca\x10\xa4C\xaa\x8b!\x89f\xe9\x85\x95\xdd\x12r)\x05=P\xbch\x86;f>IO\x1d\xa5\x8d\xc2N\x9cW\xdc\x18\xc5\xce\x06\xca \xbc\xfa\x9d\xf6\x8f>\x153\xe6FM8g|E\xf4\xd6\x9e\xb3\x08\xcd\xb9mEg+dg\x8fS\x98\xfb\xa0Pz\x12\xfa\xdc\x1a\xab\xef\x8a\xdbp=9\xe8\xf3\x0c\x17\x0c\x0e\xc6\x8c\xea\xd2\x13\x95F=\x91l\xae\xc9GRP\x12\xbb1\x1d^UI\x19\xaf\x13BWpr\xb0s\x15\x97F\xb4\xa8(\x1a\xc6'h\xbe[\x9e\xb0\xe37\xf5\xe0\x86\xbb&\x11Jm\x8dZ\xd9KA\"\xd1e\x17M\x10\x8b\xa8.\xcb\xee\xf4\x9b.\xcb\xdeW.\xcb\xee\xf4Q\xcb\xb2\xd7Z\x96]\xcfo\x8a\xe82\xb1\x7fLZ\xb8\x0dV\xeb`\xef\x9b\xae\xd6\xe1W\xae\xd6\xc1\xde\xa3V\xeb\xb0\xb5ZO\xcd\xabu\xa0\x15O\xd9?\xfbZ\xf1.\xfbg\xef\xf1kk\x8a\x1f\xd7\xb5\xbah\x9e\xdc\xb5\xc2\x8a\xa6\xa3\x8e\xaa\xc5~\xb6\x02\x08\x9c\xc1\x0b>\x9b1\xa5\xcc\x07\x84\x87\x92\xc7\x93wh\xf2\xe9F+\xf8\x07\x8d`\x98\xcd\x99\xb0\xfa\x1a#\xdb\xf4\\\x9eO\xe3Q\xe2\x0ck\x17\xfd\xa6R\xbd\x91\xda\xd4N*D3<\x8a7\xcda\xb69Y\xc1\x10j\x15\x06Q\xac\xe2\xe1\x9d\xbf\xd8\xa4\xf3.:W<\xbc\xdd_7i\xb7\x93:\x86a\x14\xb2xx\xff\x9f7\xe9\xbf\xd7v\x18\x9a\x86_m\xd2p\x075\x0e\x83(r\x18H\x95\xc3&\x9494\xb3y;l6\xbd\xc4:4v\xd1F\xc6\xfag\x1e\xf9Rx+\x1e\x83\xcd\xbd@~J\xe6\x8e8\x02\xc7\x19j6\x0dF\x9a\xec\x81\x8b\xe4\xd9dmA\xa5T\xa0N\xfeZ\x85Iw`\x170J\x1bzd\x0b\x122\x146\x9a\x9d\x88\x87\xe3\x80\xfb{\x0e,kY\x88\xd9/\\\x9bE\x9c\x16k-xr\x17f\xb2)F\x98\xffRK\xca\xdf9p\x81\x9f\x9es\xb3\xe9\x9a\xae\xa8\xddy\x10Fr\x7f\xc9`\x15\x96\xd1\xd2}\x12\xfc6}xr-2l\x80#\"\xe3\xd6\x8d\xf1\x10\x80,\xc8L\x10\x04\xe0x\x9e\x0f\xce3No\xd4\xe1r\x9e;]\xebb\x91'\xf5\x1a\xb5\x7f\xfb\xad\xd6y<\x05\xb3\xea\x9e\xdb\x0c!\xa2v\x84/\xc8\xb1^/\xaf\xed\xb6\xb4\x17\xcc\xd6,naT\"|\xdd\x11\x03\x8bv\xef\xefQ\x80\x83/b\x1d5\x9b)>\xee\x8f\x9e\xd3\"@\xfbh\xdb|sx\xce\xc7C\xe8_\x9dnBM\xfd^\x17\x02\xad1{-\xa4\x03|H\xeb\xbf\xf2\xfa\xaf\xb8\xfe\xab\xb9|\x83\xc4{\x19\xba\x0e\xec\xd0\xd3\x83!\xcd`\x87\x1e\xa7P\x96\xe8e>T\x1e7\xdf\xc0\x00\xc8B/\x18s\x15\xacb\x99\xc24\xbb\xe3\x13H\x98!\xedh\x94\xd8%\x80\xd1,a\x12\xc0\xc5,\xe9\x94\x00f\x18\xbc,\xe1:sZ\xdb\x0e\x83\x1f!\x01\xcc\xe0\x19\x1a!\xa3\x04\xb0\x82g\x90\xd9%\x802\x94\xc2(\xc2C\"\xbbI}q\xe3\\\\J\x91%\xd7.Ao[\xf7o\xd4\xd9\x9d\x1aR\x03\x03\xaavu\"\x99\xfc\x7fmG\x93\xce\x8e\xd0C\xdf\x0c\xc7l@L\x8b\xb9Y\x93\xb8L|$\xddt\x9f\xf3_\xadVj\x0f\x14\x1d@\x99\x83\xa6\xe4,J\xf9F\xad\x9b\x8f0\xc2\xe0\xb8x\x1d\xa7\x18\x97\xc03\x04d\xe1\xae\x92,r\x81p\x8c\x10\x84\x87\x0f,P\xc7\xcc\xe7\x91t.<\x16\xc9\x11\x92,\xbd\xa6\xfc\xaa\x88Fk\x0f\xa8q\xcf\x00\x85\x18D\xea\xc1\x19\x05\xcc\xac\xd8\x08\x899\x07Ay3\xd9\x9f\x89\xd5\x1db\x94_\xdb\x18K\xa8pGO\xea\n]\xacU,98\xc9\xc1{\x9e\xd7NM\"\xe2 \xe3\xef\xf0\xafA`_r\xeeeg1\xab\xca\"\x9e\xd7A\xa9\xec\xf1I\xf2:\xae\x805^\x86\x02^U'Q\xabJo\x08\xff\xc5/\xdbJ\x0b\x94c\xde\xf2^\xd6k\x18\xdb\xc5\xfb\xbc\xdc\xa0\xcf>\x8e\x8b7y\xb5A\x93_\xab\x8a\x80\xa6\xdb\xdb\x0d\xba\xed\xe5\xb1x\x9b_6h\xf3\x1fN\xd9q>h\xf0\xbd\xdc\x14Z\xf3o\xc4I\xd9,u\x01\x98A\x13s>\xd5\xbd\xa6\x98\xc2\xb1\xdf\xf9T\x97v\xfd\xdf\xf3\xf7\xef\xfa8\n\xbe\"\xe6\x1bJ\xdb9\x06\x11\x0c\xc4\xccr\xcc\xc32<\x06\xdd\x93\x0e\xe9\xa3&oFp\x19\xe6\xb9\x88\x0d\xe6\xf7\xc3R-\xf8*\x05,\xef\xe1\x14\xf6\xc6G\x07\xb6\x90q\xbfv\xe1l!A3I\x92\x1ec\x16\xac\x98\x03\xa3\xce\x97\xd9\x8c\x992@\xa2\xc1)js\xed\x0c\xe40\x87\xde\xcf\xff\xa8S\xfc\x16\x93{3drv\x1bDw\xcb&\xf5t\xb78r\x95\xd8\xa7\xbc\xc1\xb2\xa6+\xa9,\x82\xe3\xb0\xfbG\x98\xab\x1c.F\xe61}\xd3k\xb7\x9ce\x1dS\x8f\x07M\xfdm\xd7\xd4\x15St\x8d\xf1\x90\x877f\xc3\xcbk=^\xc659\xb1m\xd7\xf2Yv\x01#\x98\xee\x1f\xc0\xf7\x90\xcf2S\x90X\xd8t.\x9f\xba\xe6\"4\x12\x13\xd4H\xb0\xd8\x18\xf6H6\x0e#\x01E\x04\xef*NK\xbb}\xc7\x08\xc9 k\xdc\xb7O\xf9]\x9c^c`\x13Lj\x00W\xe4.K\xe7\x82\xf6ak6\xd0\x0b\xf7\xa5*\x82@\xa7\xc8\xc7K!\xbes\xd8\x18\x8ca\x80\xb8\xb0D\xc4\x0f\xb1i\xb2 \xba\xa8\xf1\xe3\x9fY\x03\x03\xe9\x91\xfe\xf4\xd8t\xb6\xe615\x88$t\xb0\xc7\xc1\x9c\x93/ \x8b\x17\x06\xae\xe8\x87\x1ef\x88\xd4>\xfd\x84\xdbS\xef\xe3\x86\x9b\xf5\x92\xca\xed\xd5\xadud\xaf\x17\x1f\xa6\xaa\xe1\x0ewG\x8b/\x00\xf5\x10\xdb\x18\x94\xe7\xd938\x84\xef)\xfd{\x061\x1c\xc3\x04v \xf6<\xb4\xd16\xbc\x184\xe1\x8f\x1bMxoz\xb4wt\xf0tz\xf4\x8df\xbdg\x9f5iOk\x17\xa7\xc5\x16c\xd0\xe4\xde\x0d\xbe\x1f_s\xb0lG\xb5\x03\x9e<\xfa|\xfe\xa4\xcc\xc88\x9dZ\xaer\x7f\xcf\x16`\xec\xb3\xa5\xf6!\xe6<\xae\xdc\xc6t\x97\xbd\xa3+\xb07h\x0c?>z\x0c\x87\x961\xecO\xd9;:\x86Cm\x0c\xf2\xafB\xa7\xeb\x86\xd8\xef\x08\xaf\xb8aJ\xeaS\xf8\xaf\xff*}=\x08&\xe1\xb9O\xfe\xeb\xbf\x88\xcf0\x05\x0bC9\xa2X\xbb\xbe!\xa5\x888RR\xc4^\x17\xe5^\x13\x92\x8c\xe5\xea\x92\xbe!\xe2\x1bR\x7fC\xa4o\xca\xba\x04\x93\x1d\x1b\x03\x985:\xcf\xda\xea\x1a\xd7\xc2\x1a s#\xf9IM\x81\xc1\x8e\x9eeE3\x86\x11\xec\xec\x101\xef\x13<\xda\xe3\x9e\xe9\xd2\x0f\xbe~\xc2\x87C\x00\x02o\x90\xd4s\x9c\xf8\x9a\x82\x83o\xdc\x90\x1e'\x07\xedc5\xa8\xd3\xa9\xa5Sn\xe9\x81\x8b2\xb9@\x9c?l\x1c\xed\xcd\xfe\xbaq \xb5\xa1\x0cf\xc88v\xa7\x8f\\\x8f=}\x1c\xae}A\xe4\xa2)\x16\xb18\x7f\x93\x83\xa7O\x9fN'\x94\x8b\xa8\xdf\xef\x0e\x1c\xf6#\x97\xaf5\xec\xd6\x18.D\xe2Li\x06\x93\x83\xf6\x14\x94Y\xed^t\x8a\xf0\xe9\xb0\xff\xd7A4x~\xca?\x9fL\x0f=.\n\xdf\xe1\xb4\xe3:\xbbu)\x95\x00\xdf\x03\x06\xf3\xec\x05\x07\x7f\x0f\xf0G\x94\x85\x91`[~q\x82\xe4e\x1b\nf\x1a\x14\xcc\xbb\x17)3,Rf]\xa4l\xc0\"}#\x90\x89\xbe\xd7\xf5\x89Gu\xde\xf7\x80\x11!v\xa4{0\x11\xa9\\\x07@\xd7\x0d\x80\xab\x15\x9a\xb5\xd7\xf1F\xf8UX\x81\x8bu\xedw\xa7O\x0f\xe8$S8c\x8c\xd0x\xf2\xf4`\x0c\xf7\x90\xc2q?\x05\xb2\x01\x8c~\xf4t\xd8$\xee\x15\x10\xfe\xfbM\xe7\xdb\x81\xfa\xcd \xbd\n'i\xd9to\xd0p\x87\xad\xfe\xf0\xe1b\xcf\xedA\x0f\x00\xee}\xc3}\x9dd\xa1\x01\xba?n\xb816\xd9(\x1a\xb6\xc6\x82\xeb\x1b4\x8co\xb5j\xadaL\x86\x0e\xe3\xc7\xac\xbaJ\xc8#\x97\xe3\xb0w\x1cc\xc1\x80\x0e\x1b\xc7#\xd7\xa3\x7f\x1c\x93!\xe3@\xe6\xd9\xca\xcdX\x848<\x9d\xa7\x82\xe0\x98\x15\x0b\xaam_\xea\x06\x04:2I=\x96t\xcc\xe6\x88\x12\xdbc\xfce\x1dN\x1fx!H\x13r\xba\x14\x94D\xdaB\x93\xac*#\"N\xa1\x84'\x1039\x90\x15\xbc\xd1\xca\x9dP\xac^I#\x99\xf0w\\\xc9\x14\xabXW\xd3`\xa4$\xad\xa6\x10\x9f\xd5+\xba\xb3\x13c\x808N*\x18\x964\x16K\x9a}\xb3%m\x11\x15\xdd\x16,\x86E\xd5\xd7\x92\x02\x8b\xfd}\x1f\xf5(\xd6|?\xb8;M\x06\\\xb7\xf4\x04\xb4\x96O\x197\xf9\x1f4\x11\x13\x05\xf2\xd5s\x99\xfaLr\xdc5\x9b3\xc3\xf5\xf0\x9b=\x9b\xb0=C\x11)\xa5\xa9>(\x1dl1\x1b\xfb\x91\x166\xd2>\xc9\xc1\x94\xf2\xef8I>\x1b}\x92|\xee\x86IN6\x9a\xa4\x89Z\xf9\xeaI\xee\xf9\x92H|\xd0L\x19\xcd\"f;\xdd\x93\xa6;m\xca'\x07\x96\xbd6\x1cg\xba2\x1f\xcd\xdb\xdfI\x16I+\xf3;l\xff\xe6+cY\x95\x89eU\xa6\xe63\xb3\xdb\xbd2\x93\xc1+\xb3!\x8a\x15\xd2cyY\xb6\xac\x06G\x02\xd4\xb7\xd0\x03\x86\x8e6\xcbN[\xb8%f\xa8d\xc7\xe0\xe6m\xb6\x07C\\lF,=Qz\x1f\x89\xc1+\x19\xdd\x08\x917wJb\x7f\nsL\x86\xdb\xe9\x84.\xf0\xcb\x10C\x14\xf9\x1a\xdew)\x96\xaa\xe0\xf9s\x18S<\x1a~\x13|\xb5!\x05\xf0?e\xa3;\xa8\x88\xaf\xdal\xb1\x17\x12\x81\x915\x04\xc6\xc6;>\xfa\xfb\xec\xf8\xefB\xa0L\xa6O}\xd8\x99L\x0f7\xa7Q\x14\x1d\x12]Z\xe6\x930\xf9\x1a\xfa\xe5w$_v\xa7O\x0f\xe8\\Q\x860\x0c\xb4\xff\x8e4\xcc\xefH\xc2\x04_K{0`\xca\xdd{;\x80\xc4QH\xa2\xaf\"h~Gz\xc6\xbeD\xea\xf5U\x8c$\xc4-\x1e\xb0\x8a\xff@\xc4\x8fE\xfe\xd4\xbd\x8a?i{\xd6\xe7U\xd1\xf4\xb4\xe9~i=M\x06\xf5d\x93\"uw\xf5\xe3c&e\x13\x14m\xd4U\xef\xac\xa2l}\xb7\x19\xdd\xd2\xa4\x9b\x1c\xa3Cd\xed\"\xd8\xd8\xd5\x97\x9a\xa7\x97\x94\xa5\xa41E\x90+\xd0\x0fI\xdd\"Wq\xe45 \x88\xce\x0b\xcc\xfb\xb2/\xbdS\xdc\x8a\x84\xd2\x0cP\x1eVO\x13\xa4\xcb\xf0\xa6\x0c\xf3kR\x9e\x97a^\xf6gC\xad\xcdx\x80\x19kj\xc30\xf7PdU\x1e\x91\x0dz\xc8\xbb\xc6\xcbZ{\x95\xce\xfb\xdb\xcaU\xe7\x8bz\xf5\xd5\x1d\x95\xec\xaf\x08\xc6^\xda\x916Jy92Z\xe5\"A\xcb\xf4[\xb99n=\x12\xc8\x8d\x1b*\x06]\xe6\xcaA\xec\xb1#$M\x0c,]\xc2\xe4\x04b\x9e\xd5`g\x07\xcd\xc2b\x18\x01\x03\x92\x14\xd6\xd1_\xa6\xb8/\xb5\x93\x11eA&d\x17X\x18\xaf\xcd\xb2\xfe\xb105\x9aY\xda\x06\xfd\x1b\xf3\xb9\x14\xa4\xac\xf3\xb8\x94\x8a\xa9N\xca\xcc\x9e2\xcf\x9c\x0bS\xe8\xfd\xba\x00\xc1\"\xc6\xf4\xf6\x1b\x00\x02\x83\xd3\xd5\xc6\x99\xadEz\x02\x0c\xa9\xc1\xd1\xa6vC\x8c\xe9s%\xb8\xd0\xfe\xc4\xe7Y7\xfa2#\x81\xec\xe2$\x07,\xb7Y\x1e\xd1\x87n\xe9t\xff\xa0F\xd4\x96\xf8h\xf6|\xabz\xb2\x19C><\x9b?{\x9d\xf1{h2o\xcb\xb2c\xbfj.\xe0\xdc\xe6Ul\xf3\xfch\xf5\xc7s\x97\x98\xf2\x9d\xf3\xc5b\xa9\x92\xacF\xbf\x1cF\xca\xe0\xe7\x19\xc3\x0dj\x91\xd5*\xfa\xfd`O`\x0c\xe7\xd1\xc4\xcf\xa3\xed\x9b\xa1Tf\x1bl\xe3\xcc\xab%\xba>SF{\xcc\x93\xc8\x8d}h\"{P,gL\x0bo\x87'\x06\x8b}\x04\"L\x93a\x01\"viB\x85\xb6|r\xacB\x96Q\xf8g7\x15)\xeds)\x01\xa6\xd7\x91\xbc\x99\xb2\xdc\"N\x95\xf9\x10\xd6\x13\xe0\xb6z\xe8\xa3\xacLB\xc0\xc5j\x96\xc1\xbfB\xb8\x81\xcd^\xd9\x8a\x91\xa3\x8e\x81N\xf6op\nOf\xff9\xfa\xe5\xc9x\xe7\xe8\xc5\xce\xff\x0bw\xfe\xb6sy\xf1\xe4\xda\xe6z\xf3\xba;\x84+\xa0r\xf6\x0c\x9c1:\xfd\xabiB\x8f\xb5\x02ul\x96\x0e\x7f\xb6*\x00o\xcc\x01\xda\x08\xf0\xa88\x13x\xd2\x9b\xe3\xb2q\x90\x89Ex~S^\x87\xee\x14*1\x0bl\xd3J\xec\xe0\xc1s\x8c\xe6\xbd/P\xf4\xfe\xd3\xdd\xbd\xbd.\x80\x1b\xf3\xfcp\xf6\x1aP_\xd2\xe7\xb0\x7f\xb0;9\xea\xabL\x1f\x96\x88b\x97\x8eggB\x07\xc3\x93ILw\x8f|\x98\x1cM|\x98\x1c\x1eu\x80u\xf1DYZ\xc6ie\xce\xa5$\x1e{\xf6 \xe0c\xaf@\xa4~\xb2J\xf5\xe4\xe7\x1fi\xf4\x98\x10\xaa\xb3Jo/\xdd\xd9\x95\xf0\x98\x1c\xecN\xad)\x04\xc53lU\xfc\xdfy\xc8)\xf7\xd18\x80\x11\xa5\xebvx\n\x82g\xcf`\xc2\x0c]v\xf8l\x8c-\x88\xb4\x89\x9c\xef\x190\x1f;&o\xeeo\xca\x12U\xf4\xdd3\xd6\xe1\x84eg\xe9K\x7f\xc0\x07\x93v\xcf\x83\xef\xdft\xbc7\xb0\xf7\xe9f\xbd\xc3\xf3\xe7\x98\xcb\x00\x03lcB\x83\x94\xfe\x9a\x1e\x0e\x1a\x16\xee\xd3\xb0q\xedn>.L\xba0\x9d\xee\xb1\x10\x1ep\x00\xdbt\x848\xba\x0d\xc6\xda\x03\x1aq\x1e(\x14!\x92\xb4&V\xd2\xdar\xf6\x99p\x86\x19X(i+\x93\xab\xfbu\xd6\x7fy\x8cw\xa6\xe3t'\x13>\xb5\x07\xbfS\xb8&h\xa8\xd4}\xea\x05,\xe8|\xd3q\x19\x90/\xeb,/\x8b:\x85\xf1\xe0\xd6\xf6\x0e5\x8a:f\xc5GZ1\xa5\xd3\x9cY\x86a\xf0y\xd0\xfb\x0b\xc7<\x02\xfb\x89\x15'\xa7\xc0\xefU\xc6\x8c\xae6\xfdb{\x1b\x90\x0d8=\x95\xee\xdd\xc3f\x93\xda\xdd\xf5\\\x16\xb1\xdf\x07'\xcaIX*~m_\xb1\\\xbbOw\x8d\xeb\xb5\xfbt\xcf\xb0`\xb4|_+\xafx\xf9\x81V\x1e\xf2\xf2\xa7\x9e\xc4\x0d\xd4\x07\xbbh/\xe6\x0d\x8f\x0e\xbac\xd0}\xa6\x1c?\x03\x0f\x9f)\xa7sV\xcfk\xad\n\x0d\xa2\x84\x84\xb9\x8b\x87\x9cX\xb3q\xddt\xa7\xd4FQ\x10)\xdd|6\xbe\xf0!\x9fMt\xbb\xff?\xb4\xffRd\xc0t\x0ctWT\x89\xd0\x9c$\x04c\xfc\xc4j\xf95\xa1\x102S\x0b\x97!\xdd\xd7J-,\xb0f\xe8+{_l\xb6\xf7O\xf7,gH\xf9\\_5c\xf8\xfb\x13HwvN\xda\xf0\x17\x05\xa8n9K/p\x01\xa5\xbc\xd1\x1aU\xc9K\xa5,\x9f\xe6+\"\x8ff\xf0\x90\x1b5\x92\x88y\xdad\xc9!\xf4/\xf2\xe8\x8b\xf9\xf4\xe81k\xd8,\xdf\xe5\xe5<,\xc3\xcbK\xe3j\xe4.\xf1\xe0\x0c\xd2\x99E\xbeW\x17\x1f\x83\xb3\x0c\x8b\xa5s\x01\xc7\x90\x06\xabp\xfd\xd8\xf9\xec\x8d-\xe0s\xa2_{\x06\x0e\xf0v\x8b\xa2\x8d`f\xc6D#9\xcb\xe8G!\xe5c\xc7<\xb1\x80\xb0\xc9d\xf7\xb1\x83CP#NH\xec6\xd2N\x8aY\xf3\xaf\x18\xeb\xd3\xb1a\xa8\x9a\xa8a\xd8Hmbbz\xbaY\x0c\x01q\xea\xdbb\x1bT\x12a\x14N\xe3\xb1s\xc6\xd8\"\xaa\x04\xe8\xd8\xe8\xbd\x81\x9d\x98\x1e\xb8\x9d1=l\x1b^\x17\xa7*XB\xf3\xa8\x94:lh\xc6\xd6\xf5\xd8\"\xc1\x0d\xc9\x0b\x8a'j\x0dS]TG\x86sn\xc6\x81\xe3u\xd7\x98\xd0\x1a\xb5]\x8b\xb9\xc6!\xads\xa6,{\x1bO\xa4\xe4K\xf9)\x8e>\xab\xb1\x98;bK\x82\xd8#Q_\x96B\x97\xb6\x08\x0f\x94\x8e\xba\n\xa3\xcf\xc6\x18\x0f\xa2%[\x98\xfb\x9b&\xab$\xb4\xc3J\x9b\xbf\x11\xb1\xb7\xc2.b\x1c\xa3&\x8d{\x02\xd5\xf6$\x80\x14\x16@\x81XI\xb7+X,\xb6\xd8\x93\xdf\xb1\xddb\xbd5}\xe2\x0f\xc0k\x86D+\xe7\xfa\xcd\xac\x83x\x1e\xfa\x86\xda\x93\xdb\xf1\x9b\x0e\xb5\x95{U\x7fzG\xdb\x93\x89\xf1[\x8f\xd6\xb7ir\xc4\xd35\xe0\xde\xd8Z \xcb\xc1\xe9}b\x1ci\x88\x16|\x8a\x1c6\x137\xc1\x83lV\x8dF\x17\xf2-\x99U\x1dq3\xe1[\xac\n\x8bX\xcc\xa5\xc4}\x0bb|\xdd\xc7\xe2? U\xdc\x801 N\xcb,\xda\xee\xde\xa6,\xda\x81\x89*\xc8y\x96B\x13y\x9f\xf5\x91\x8eqJ\x81 \x99q\xae3m\x14\x13\x0f\x86\xe6*\x9by\x86\xe0L\xeb\xf7R3\xe2\xaf\x98e{\xa3\x98\x9c\xa7\x1ek\xfe\xe4 \xb8\xf4\x02L\xa1\xa5\xa2\x84\x1c\x8e\xc1\xcd\xdc\x9cN\xcb\x9734V\x9e\x0f\x99\x1b\xb3H\xb0\xd5\xd0\xccr\x88\x1aL\x8a\xaa!\x01\x88\xd3\x8cc\x04\xde\x80gD\xe3\xa6E\xa1#\x1c\x9a~M\x19b/\xee2\xc5H6\x0fO\x1c\xab\xb8\x85\x01\xf8\xc0%5.1ghKYf\xe8\x98\x9fh\x9e\x13\x1a\x7fJ\x7f\x8f\x15?\xe4f\xee\x03\xb2\xae\xfd^so\xb6\xc6\xb4)\x03\xf3\xb7\xfd\xce\x83\xcb\xa5|\xa3\x1b\x93\xbafZO\xbeH\xa9\xbbwp\xe4\xb9\xce\"\xcb_\x85\x91\x08\xa5\xf5\xa8f%\x1e\xe0H\x17?p\x1e\xe0H\xe7\x0d2\xce\x1b\xe8\x10\x8d\x891\xf6\x9e\x1eJ\x8b\xe2n\xc6\xd0\xf9\x94\xfa\xe2 \xbd\x8d+\xdb\xca\xf4\xf1\x0c\xa6\x94~5\xd8)\x94p\xc6r\x15s\xf3\x8d\xd2g\xc9N\xab$\xa1'\xbcPP\xd7\xf4\xc2W\xa4#\xa8N\x0cy\xe2!\x16g\x15#\xd5\xa6\xa8P\x16v.N\xe4\xf0\x80\x91R\x19\xa1e\xa1Zv\x8b\x01\xd9##]\xcc\x93A\x1a\x12\xa2\xaa\x99 \xd3v\x05\x92V+\xc2_g\xed\xd7\xb7y\\\xb2\x97\xa1\xf2\xee\xc1\x87\x02\x19\xc7\xd8-\xe8\xb0\xe8\xcc\xa2\xe6\x90z\xc1\xf5\x90\xa8\xd3t\xc3\xf8V\xf9\xb00\xb3A\x96]\x89\x1a\xd3\x18\xf3\xe6D\xca\xe6\xecJ\x9bC\xc1\x99\x14\xba\xe8\x182\xce\xe1\xf3\xf7\x14\xae\xa5\xea\xfb\x149\x1c\xb9S\x1e\xc1\x87nh\xd4\x8cAz\xa3\x1d\x06q\x10\x8a\xe6 \x84\x86\x83P\xb4\x0e\x02\x8fa\xde\xde\xf4kR\x1a\xb7\xbc\xa0\xe5\x86\x9dV\x8fB\xd8}\x14Z\x89y\"\xbe\xdb\x11\x1d\x0ff\xc3\xf9\x16 I\x92\xe1\x1c\xdaD\xa9\xc1\x8f\xaf^\xbf\xf8\xf9\xa7O\x9c\xb0\xcc]\x0d\x0e\xb3 \xe7\xc70K\xdd\xfd]O\xcb\xdeO\xbe\xac\x938\x8aK\xfe\xfa)\xdd\x16w\x7f\xf7\x90\xff{\xe4I$\xcf \x18hgP\x05\x8d\x0c\xa9;m p./I\xf16\x9bWZ>\xd6AKG\xdb\x93\x05\\\x8a\xf5C\xea\xd6\x1abwz\xc0AI\xea\xee\x1eq\xaa;u\x0f<\xd7\x11&\x1b\x9f\xc2k\x01Z\x9c\x97\xe7\xe7\x1f\xab\x84\xfc\x14\x17\xa5\xff\xf2\xfc\xfc\xbc\xbcK\xc8\x8f$J\xc2<\xa4#\xa1e\x7f\xa2p\x85UHb\x92\x96\x1fIT\xe2\xcf\x1f\xdf\xbf\x95\xfff\x8d\x8b_\x9f\xb2\xcf$e?\xc22\xfc\x94\x87i\xb1 \xf9\x9b\x92\xac\xb0\xf0u\xcc;\xfd\xf7Oo\x7fz\x91$/\xb3$!8y,\xd1~\xbe\xce\xf2\xd5\xab\x84\xd0[\x8c\xbf\xcf }+J\xde\x92y\x1cbco\xe3\x15\xa1\xe8\x96\xa5\xe9}\x17\xae\xc8\xfc]6'o\xc3\xb5O\xff\xc5:\x1f\xc2\x98\xce\xe1\xaf\x15)\xd8\xd0?$\xd5u\x9c\xf2\x7f\xd8\x97\xe7\x7f\xfa#K&\x87\x15\xce\xff\xf4\xc7w\x88\xa5\xc5\xaf\x0fa\xb9<'\xd7\xf5\xcf,NK\xf1CZ\x85\xf3?\xfd\x91\xcd;\xcb\xd9\xa4\xcf\xd1D\x95\xa1sV@\x97\xfb|I\x08\xfb\xfc\x13eg\xf20\xfa\xfc\x92/x]\xc0~eU\x84#r\x82b\x9d\xc4\xa5\xeb\xf8\x02Z\x8cO0 ~X\xcb\x80\x8b\xd1\xc8\x04g\x11\x1e\xce\x8a\x8b\xf6\xbd\xa7\xe0%\x9fE\x867h0I\xe9\xf2E#\xf4V\xa14\xe6<\xdeJf\xd5\x05\x13\xd2%(\xf9\xa0@\"\x9bE\x94\xab\xc8\x02\\\xd7\x9e\x13\xaf3<\x14\x8e\xfe\xf6P[\x1am*\x96\x13\x02D\x0eH=\x1e\x86\xf5\xd0\x87\x9dI\x1f)e\xbb\xec\xdd\x94`m\"\xd7\x10\x80\x12\xf1\xf72L\xbf+\x81\x0e\x06V\xa4\\fs\xc8R0\xe6\xeaii+7\x1b$\x07-\x83Y\xca\xa9\x0d\xeav\xd2Y\xa8\xc7\xef\x13o\xa6\xbe\x1e\xa1\x87\x19\x16ZR\xa4s\xe3+\xb1\xe3B\xc8\x8b\x80Mlc\xd3\x9f\xa1\xe5\x8eF\x91\xbe\xff\xf4\xde1h\x1aeY\xcc\x83\xfa\xba\xd0^\xb7`\x0d\x1dl\xc9\xa9(w2=\xf4\\'^\xe4\xe1\x8a\xe8\x1d\x89'G\xe8b\x13\xab\"\x92$AA\xc1l0\x8f\x8bu\x12\xdeQ\xac\x97f)q|\x9c\xfb\xa1\x17\x84\xeb5I\xe7/\x97q2g\x99\xca\x83\"\xa7\x80\xd2\xf95\xbc \x8b(\x8f\xd7\xe5\xb1\xe33\xabV\x12DYZ\x92\xb4\xfcs\x9c\xce\xb3\xdb`\x9eEH\\zA\xb6&\xa9\x8bn\x03,j\xa7\xf3\x8c}\xfa\\T ^\x9f2\xc5\xf1\xb3_\x9e\xf0W\x98\x81)\x88\x92\x8cE\x8c/\xf08\xbd>\x81|g\xe7\xc4\x03\xae\x9a\x94t\x8d\xb3l\x96_\xd8\xad\x02\nWS\x89\x9a\xaf5O8\xcf\x94\xd7\x94\xa4\xed\xe7\xa7\x8c\xf0\x89\xabf\x04m\xdb\x0c\x93\xa2\x12\xb7\xf4\xfc:\xdce\xe8\x83\xfa\x9aK$)\xc68e\x0eX\xb4j\xe1\xaaY\x95\x08\xd2\xe0\xc7\x10\xbb\xa9/'\xe8\xed\x07\x87\x02}\xa0\xf7hDb-=~\xae8\x96\xf6\x01?\x9b\xa4\xabx\x17\xbe\xe3\x0e\xce\x1eW\x84\xbb%\xfa\xf5\xb0\x10\xa8\xa9\xb71\xcf.\x11t\xbb\x9e\xeb|&w\x85~\xf2\xd9\xa5U,\xcc7\x1av\x8e\xe1\xa3\xee\xc1\xc5?\x98\xec\xe7\xf1\xa34 #g\xce\xe5e\x94\xe5d\xe7\xd7\xe2\xb2X\x869\x99_^:\xa2O\xf3;\x8a\xe8\x1f;\xa1XL(f\x13\xfa\xed\xa1o:6\xc4\xe9DYZ\x94y\x15\x95Y\xee/\xc3\xe2\xfdm\xfa!\xcf\xd6$/\xef\xfc\xb8\xf8 \xce\xef\xfb\x85\xbf\xe6\xc5o\x8aW5\xbf\xe4\x97\xd9OY\x14&\x84a\x03_\xa0\x05\x9fc\x1e\x99j\xdbl\x95'{^\xb00\xcaTtQKf&\xf6\xfbV\xd6\xcc\x98\xa3\xcau+\xc6#\x9er\xdb\xf9\xb2\xb9\xc6\x18\xd0\x98\x99\xd4\xa0\xb8\xa5\x0d\xcdUfs\xcb\x10PA\xc8,\x94\x17\xbd\xfb\xb7!W9\x9d\x1cy\xee\x96\xec\xeeBq\xcb\xbe\xc7s\xde\xfb\xe0\xb0?\x1c\xbf\xe3\xb0\xa1\xfd\xc9%]\x8a:S>\xf7O\xbaD\x83\xaff\xc8\xbe\x1d\xc5I\xe8\x8d\xb7g\xb6\xaf\xe1\xed\x9a\xa1\xaebHvf\x17\x041@\xda\xee`\x9e\xa5*\xffI\x9f\x07\x06\xbc(\xe0\xc6\xe5m\xe66\x92\x8d\xeb\xad\x9d\x19&\xc2\xfb\x99X\xf7v\xc3[\xb071\xcb\x15[\x9cm\xebF\xd4r\xd7\x02\x89\xb7\xbc[]\xa4K\x08\xd5\xf1\xbb^\xefm2\xed:A\xfd[\xd5%d\xaf\xf3\x11\xff\x9c\xce\xc9\"N\xc9\xdc\xa1H\x84\xc9\x8f\xf8\xabwU\x928Fg1\xa4E;\x119\x0e8\xbf3\x94Jc)g\xc4\xe0\x98\x02QX\xa7\xe6\xd5\xf4\\\xe8\xd1\xca(\n\xbc\x12\xb1\xe7q\xac\x9d\xa1\xb0\x08\xb5\x00\x0e\xab\x80\xc3u+v\xca<\xcfFV\x03KBCP\xe3 m\xdd1T=\x80\xc1D\x02\x8c-\xa8?\x0f\xd3y\xb6r7\xdeM!\x92d\x86\x8a\xaeC \xc2(,]}\x17\xe9xK\x1f\x1c\xef\x92\xd2\x8e\xa3Q*\x92\x04q\xf8\xb1{\xf0x\xb4\xbbk\xbe\n\xfb^M\x8f\xb6/A\xee\xc6\x1c\\\xc7\x9c\xf4\xe3\xf2\x93\xc7\xae\x00\xdd_\xad)fA\xf4\x9bn\x8a7x^\x93\xddn\xaa\xe7\xa8\x9fS\xfd\xef\xa0z\xf6\x9fZ\xf0\xf1\xbe.\xf1\xcb\xcc \xaao\x12\xff\xbb\xf1\xf1\xc1\xc4\xb4\x00\xc1b\xc8>Rn\xc2^ $h\xdb\xe6\x92\x10\xa3\xad\xf3l\x15\x17\x843&\xa5+O\xc4\xea\xc5\xa4y\xb4\"\xd3$\xfdN\x0d\xd2\x9e\x1f\xc29|\xe0}Id\xa5=\xf3!\xea.\xd2\xdalX~\x1e\x04:\xceI\x91%7\x84\x03\xd0\xba\xf0W\x96\x858\xd7\xddZ\x1e\xbe\x82\xff\x98\xec\x99\xa5\x05\x93\xf1#O/\xb3?m\xb2JJk\xc5n\xc6\xffq\xd0L~\x04\x0e\xcc3R\xa4\xdf\x95\x98\xf7g]BN\xae\xc9\x97-\x8b\x8e\x94\x83\xd3\xaf\xba\xd0\xf4\x82b\x8e\xe4\xfe\xabiD\xeep\nO\x82'\x9a|\xc7\x88j\x9d'\xc1\x13\x07f\xe5\x85K\xb4\xbd\x128\xb6\xb5p0\x04o\x93Y~\x81J%\x1f\xb6\xac}@\x0f.7-\xef\xa6z\n\xf3\xe5'A\xa3\xfb@ e\x1b.Tn\xeaN\x0f\x0ft/\xdc\xb8~u\xa8\xbfB\xd2\xceD?\xc4\x01W\xc3 \x85\xd1\xf6\x08\xc8\xeb\xf7g=\xc0DPE\\\xe7\xa8\xed\xd8\xf1\xc0\xaf\xad\x84\x8e2\xd02\x90\xe0\x04\xcb*\xad\xbcFPS\x17I\xe2\x94\xb3f\x8e\xc7\x96\xa1\x9a\x0c\x83*+\x90\xe5\xc3\x91\xb6\x8c!\x9b\xf6\x0ckuWi9I\x0f\xd2\x11\x10\x93\xd9p\xd7N!s\xeb\x1d\xf3:\xb7\xccBPW2A\x9d)@\xb1s\x0f\xff\x1e\xfb\xb7\xc1\xd8\x87\\G\x82h5u\x0f6d\xb6L\x82\x9d\xd4\x9d\x1a\xc9\x9bC\xb3\x01\xc7dl\xf6CAi\xc6c\xc1l\xcc\x1d\x94\x98\xc0G\xfc8Eb\xf4\xb7\x0748j*\xfc\xa6[3:\x97l\xf7\xd0\xbd\x1bC`0\x0f\x84\x98\x87\x9f\x0e)\xf3[v\xb0\xb9U\xb0p\xb5\x08\x06\xbd\xd4Q{;\xb8\x00\xf6\x9a\x94\x92\x84\x89\x0d{C\xbf\x91\xdd\x03}K\x84\xcf\x90\x99\x12\xdd=\xd4\xad\xde\xb9\xcf\xd0\xa1\xceQp\x9f\xa1\xc3\xe9?}\x86\xfeA}\x86(\xaf\x94\xbaO=\x1f\x9c\xb7\xe1\xfa[9\xa1\x1d\xea\xde%\xdc\xebdj\xf6:\xd9\xdb\xd5\x0f ;P\xfa\xf1\x0by\xedG\xfb\x81\x18\xe1o\xc9\x11\x93|\xb628\x06'k\xe4\x0dR\xd5\x8a9\xba\xc4n\x89\xe7\xa1\xa4\xe7\x81\x82\x0c\xc6\xb6\x86\xfd\xc0U_3z\xae\x8f\xc6\xe3\xa7\x93\xa3\xa3\xe9\xfe\xde\xd3\xbd\xf1\xd1\xd1\xa4-nx\xf2\x9f\xee\xd9\xf1\xf8~6\xd99\xba\xf8e\xfe\xbd\xf7/O\xfa\xd6\xc0\xa2\x86\xc1\x10>|:FZxk\xcb%\xd2U\x13\xfa\x13\xc2\xb2\x9f\xc8F\xae13v\xe3hg\xeb\x94\xf9\xee\xe7AI\x8a\x12u\xba\x88\xb1\x84\x0b?\xcb\xffy\xcaC\x97\x96\xf0\xac\xd7\xefd\xc8J\xf5\xad\x82\xed$Xb\xeft\x0c\xf7T\nu:\x08m6\x17\xc2\xec\x84\xd5r\x1e\xa2\xb7\xe1\xc9/\xc1\xfd/3\xf7\xecx\xf6\x9f\xb3_..\xbe\xbfwg\xcew\x17\x9e{v\xec\x9em\xfd2\xf1f\xff\xf9\xcb/\x17\xf7\xbf\xfc\x12x\xdf\x9f\xfd2\xf1~\xb9x\xd2\xbe9O\xfe\xf3\x97\xdb\xef\x1fu@\xb8\x7f_\xa3o\xde\xd2\xc2\xdf\x8bm\xe8>A\x8a9k\xaa\x90bu\xc1U\x96%$L\x9b\x12\xc5Ik\x0bY1z\xbe*q\x9c0\xbaX&\xff\x12_\x10\xb6Cq*d\x88\x1b\xa9\xf9j|\xd4\x96\xe42\xf15\xb9!).\x9d\xf2\x13I\x03!\xe1^\x85_~\x8a\x8b\x92\xa4$o**\x855\xb3/\x8d\xac=\x84|C\xd0\xd5\xd9Xlo\xcc\x04\xda\x9a-8\xedi8\x1bD4k[\x00\xda9L}H\x83Wt-_\xad\xe2\xb2D\xdb{,k\x10\\\xb3\xf2\\\x0d\xa1\xbe\xd5\x16\xbd\xa9\xc3\xa9\xe3\xb7\xea\xfb\x89\xf6}A\xf4\x1av\xa8a3\xd1\x06\x91\xc9\x18\xdd\xc3\x99.\xd7$\x9cH%c\xeduV0K\x8cN\xabm\xf3\xb9\xf2\xd50N\x0f\xea\x8c\xc8*\xee\x8e\xc8 )\x11,\x96\xcd1\x8f&(\x1fsW\xbb\x06\xbf=Pr\x81\xd0\x999M\xd4AwK\xae\x16\xe0k\xee4\xdf*gF.\xedr\xe1\x97i\xa2\xd2x|\x0e\xd9\x14\x97b^\x91!9[\xb0\xb0\x1fb\xf1\x0dY7\xe9\xec\x17\\f\xc7\x1d\xf4~N\xa3\xb0\xba^\x96>Ti\xb1&Q\xbc\x88\xc9\xbc\x9e\x1b\x0e-\x00\xf7;\x9e}\xd7\xf1L\x927\xd6\xdf\x82\xd9t|)\x99 \xefB\xa9\xf6\xd0Z\xe3\xac\xc9\"\xcaW`V^\xd8\xc1.\x83\xcb\xa9\xe75\x0e~\x9a\xed\xb9i\xc9\xba\xfc\xf8\xd2&G\xbfE\x9ah \x7f\xd2\xe5\xca'5\xea\xab\xfb\xb4y\x17\x16\x17r\x82\xde\xb8\xaa}\x92\xb7,\"\xdcD4\xdb\xf6\x91\xed\x84\x92=\xa0J\x813)\xb9\xadG\xbf\xcd2\xe8!\xdct\x1d\xe9\x8d\x83\x0c|\xee\x92@\x0c\x89\x92\xfc\xcd/$\x87}\xfd\xfa2\xae@\xbb\xd2\"\xcaaS\xc4\xc2\x06\x11\x91\x9aOn\xe0\x14fZ\x91\x0f\xe4\xc2X\x91\xf8\xa6\xcet\xb0J\xbb\xbb\x0d\xf3\x94\xcc\x81\xa5\x0b8\xa5\xc8\xbb\x85ZP\xdbjD\x9b\xc7\x06D\x84\xddT\"\xf6\xb0\xde\x1d\xb7)x\x0e\x15vi\x19\x0dsa\x88\xb2\xb4\xc8\x12\xc2\x80\xbf\xeb\xb8i6'\x1e\xd0*\x18>s\x9d\x15E|\x95\x10P\xc8\x84\x15Ye\xf9\x1d$$\xfc\x0csR\x92\xa8$\xf3\x00\xfeu\x0eI=\xeap>\xa7e?\x17\x04\x08\xfbJ\xc7\xf6\xae\x07e\x06q\x1a\xe5\x84\x02\x9b$^\xc5e\xe0\xb4\xb6\xb4\x89\x93j\xa4\xbf\xc4\xf8\xcb<\x8c\x90\x08U\n\\\x91\x0e\xc9v\x932\x14i\x98\xaf\x96^\xb3?\xf9\xf67\xbaY\x82\xc2\xa7(Hy!\xd1\x95&dS25\xd2*\xbb!b\x0et\x98\xb1\xc7\xe3\xbb#\xc2\xa3\x9bNT\xf0#\xa0Y+\x82\x92\xfcKXi57\x10o\x00\xf6\xc9\x96#\xeeYkud}kyS\xfb\x7fQB\xe9w\x81`\xd8\x8c\x0e\xbf\xf4\xcb\xdb\x11w5^\xb0\xfbl$$j\x0c\x901a\x1a\xddQ\xa1s\xcc\xddT\x02k\x94\xea\x97V\xf5\x14\x83\xbdr\xd9T\x0b\x16)\x90T[Q\x15\x98\xaa/\x19<\xd5\xe3-\xab\xb8\xd0p\xa4jlX\x9d@\xb8\xb3C!\x8e!&\x0d\xf0\xc5Hg\xe1E3K\xfa\xab\x99\x17\x9d\xa5R\xc0'\xda\xeeS\xf5\xdf\xc4\xfe\xab\xf6\"I\x86\xf1Vf]{\xebz\xf4\\\x85\xad\x8e97!\xecYf\x1c\xddm\xf3Lg\xf4Q \xa0\xe3\xdc\xed\xed\xce{\xd1\x1e\x92\xb97\xebA'\xe8D\xaf\xccX\xdf\x1en8 \xb6\xb0\xbd\xd0nGLs\xdb'z'\xda\xf9\xc1\xe5\xd0`+\x18y\x9a\xdc\xc2\xd3X0\x83\x1e\xee\xbe Oi\xa1\x8bO\xea\xbbqbotV\xdf\x99\x1dh\xf1\x1d|%\xba\xb6\xd1v\xa8\x93Ag\xd9D\x96\xb6i$\x16'I\xbf\xc6g-\xe2\xcf@\xf9 \x1a\x1f\x8eav\xd17\xd6\x97Y\x95v\x0b\x04tv\xdf\xa6\x1e!\xed\x8dm\x9f\xb3\xc68\x83/\x83!u&z\xee\xd4\x15\x84\x05j?\xbc\xd1\xb8\x11\xfb\x0c;\xc2\x85\xa9_\xf5\x0b 5q.\xcf\xc5!{\xbeO\x0e\x9fz^p^\xe6$\\q\xd7\xdd\xe0# \xe7\xe1\x15Z(\xe0\xef?s\xbfg\xf6\xc1\xe4)\xfa\x86\xfcX\xad\x13\xf2\x85\xa9C1MLP;\xf9\xb1zGS,\xfd\x10\x16\xc5\xa7e\x9eU\xd7K\xa6\xfb\xd8?\x1c\xa4\x83\xed\x0d\xd1d\x0ett#\x92\x99\xb9\x18\x07MyW\x93\x7f\x06\x95?h\xc7\xc4$$\x89\x0b\x8c\xb4\x02\xc2o\x83!\xa1\xb4\xcc\xef\xd4\xa2E\x9c\xc6\xc5\xb2\xcf\xc7\x87>[\x9dK\xa0?\xb5\x96\x8fujG\xed\xa52*{=\x0e\x93r\xa3NQ~\x84\xd6%\x0fD8({\xa3\x80\xfa\xdd5I\xe7qz\x1d]\xed\xecP6\x8f't\x81\x1cW\xd0\xfam\x9b\xf2\x10\x0f \xa2,\xffL\xe6\xdcc\xb5x\x9d\xa3]\xac\xa9XlRIy\\\xd3g\xa7\x86\x00\xa8\xf4y@\xb5\xb7\xc1V\xa8\xe3r\xcb\xb7i\xd5fCB\xee\xe4N\x82\xab<\xbb-\x18\xf12sn\xc6\xc1d\xec\xf8@\xff8\n\x9c\x8b:\xfaW\x13\x0f\x8cA\xc9\xb1\x0f\xfb\x1e\x8f!\xcd\xbci\xb2:\xda\x8f\xda\xdb\xaa\xbe\xa6\xe7e\x88Z\xd9\xeb\xf6pP\xc8\xe2\xee\xeby\x04\xa3 N\x97$\x8f9L\xd8\xd5\xd36\x08\xb1\xa3\xf9\x90\xcc\xc9:'QX\x92c\xbc\xdeO\x0d\x0b\xd8V\x85'\x1c\xfa\xe8z%\xfa\xac\x99\xc6i\xec\xf1\x906\xed\x1aK4\x81h\xf2\xa6(\xde[\x1e\xfcfH\x0c0\xf7\xe1\x86\xf7i\x07\x0cw\xf8\xb1\xe5\xe5\xb5\x114\x03\x97\xaf\x85H\xb23X\xc8N\x1f\xaaW\xda\xf7D\xdcb\"\x0b~\x0dt:\x82\x12\xa6\xe5x\x9b\xcd\xd1\\l\xab\x94\n|\x16V\xd7m\xd7\xd3K(W\xb6\xc5\xfc\xf1\xe8\xf9x_\xbf1PZ\xb5~5X\xc6\xd7\xcb?\x87%\xc9\xdf\x86\xf9\xe7\xf6\x16\xd0'\xc2\x8a\xa2\xdd\x7f\xef\xff`a\x18\xdd\x19L\x0e\xe0\x18&\x07\xbb\x87{\x96UP\x86\x02\\k\xcbh\xd3\x18\xce \x86c\xbe\x16Q\xf3\"\xa2\xe4H\x04\xc7\xb0\xf0\xcd\x8d\xc8\x19\x15[\xef\xbd\x06\x94\x87\xc9\xcb0I\x98\xc0g\xe2\x0b4@\xe6?\xe6a\x9c\xca\x85\x0c\xe2i%\xeaw\x0c3\xa8esR\x94yv\xc7\x0b\xcd;\x92\xe0;\x9e\xe7fN\xa2l\xce\xbd\xablxJ\xa9C?N\xea\xdePB&R\xc1\x00kP-\xbb\xbf\x07\xa7*\x17\x87B\x98$spX@w\\\x9b*\x03\xb3R\x9d\xe2.\x8d\xb8\xb8\x04\x7f_\xe1U\xfe\x90g\x11)\n\xed\xe3,E_\xd1N:O<[\xdd\x94\x92\xfc\xdc41Moe\xd8h>\x9b\xe2\xc9\x99 \xfa.\x8d\xba\xeb1\xf7f\x1cxteG\x87\x94\\\xec\x9f\x95xJ}mE\x07\x0d\x85Q3\x07\xe2\xee\x91\x84\xa4\xbe\xf4\xb7\xe2\x86\xa5?\x0f\x88\x8a\x89g =\xba#G\x8aggGB\xee>\x1a\xe0\xbb\x0dNrc\x1fr\xcf\x97\xb0\x94\xfb\x8as\xe4~k\x1f\x98\xd0\x94 E\x85<\xb5\xe4\\=\xd3_\xd1\xc60f\xbfO\xc5\x1b\xcf\xf3!\x91T\xc5\x83\xf6\xf4R\x05\x8aL\x8en\xdae\"\x1f{\n>\xa4\xbbQ\x89\x9f\x1c\x9e\xa3\xe6@\xc2\x8b\xe8\xbc$V\x8aBN\"0!K*\xc1\xde\xb8\xac\xf7\xe6\x9d\xdc\xcad\xd0l\xae\xa4\xd9\x98&\x91B_\xf4\x03\xf1\x88\xb8\xc6\x1c\x07moc\xf4QA\x0ca\xda\x9b6q\xc4!\xf2\x9c\x969\x06(\xfc\xe0\x96\"\x86\xa5\xc26\xe6n\x03\xbb\x07\xcd\xf3\xd6:vb\xa4?\x0c\xd9\xb4\x04\xcd@t\xd0a\x16\x04\xd5\xdb\x87\xf2y\xa6\x8a\xa0\x98\xcf\xb6~5\xf1o\x84Lv\x82#\x069\x92ln\x89\x02\x02\\\xeao\xe2z\xcd\x98(k$\x05\xe6\nu|\xad\x90\x81\xcd\x82\xad\x1b\xda!\xc7\xa8\xae`&O\x98^\x0e\x95d\x05\x0b\xea\xc6\xa3^\xe0j\xf8\x10\xc2\xe8\xd4$L\xa3\x0f\xc69e\x88\x00\xcd\x7f\xfd\xfa\xf6\xb1\x1bSg4\xf3\xc1q(i\xc1\x10\x80z^F#\xac\xda\x81R\x18IB\xc9\x15\x8bP \xe3c\xcdd)\x8fg\x17\"0<\xc1\xce\xad\x0d\xcf\xb4\xcfz\x17\x05!d\xc4\x9d\xf2\x98\x9a\x8f\x0f\xa2e\x95Z\x18-\xf1\xa0\xb1P \xd29v\xd7M@\xc4\xeb\xe9\x16\xf0\xd0s_\xef\xd0\x04!\x93\xc2\xcd\xc11D\xf5\xa6E>e\xc0\x12\xed8\x98\x17\x8c\xde\xf9\x1a`z\x1b)\xa8\xe8S\xbb\x88\x0b@d?\x0d}2\x1e\x90@\x86\xf2\xado\x81$\xc3\xe0\xf0\x97n\xff(\xc1Abtx%\xab\xb10ld\x85\xfa\xb8\xd0d\xa2\xe1-\xd9O\xbe\x8c\x83\xc6un\x85\x9b%G\xa7\x0d\x0bc\x95Pj\xc0\x1b7A'\xc6SviU\x1aN\"\xda\xeb7\x8e\x05\xf2\xd3\xe7a\x182xe\x9d\x94\x80\xf1_\xbatM\xec\x10\x0d\xe46\xd59\xdd\xdf\x03Q$\x07\x14,Z\x88\x17N\xad T\xd2\x80\x99&{\x18+\\\xd59\xe7\xaa\x90;\x1a\xb8\xa4]\xa8W \xf6\x86\xe6fw\xc8\xd2j\xd3\xa4/\xd9\x94C\xeb\"5\x92EJ\xf2R0p\xad:\x8a\xd4A\xab;e\xe55\x16*\x85\x00I\xbb\x03,\x98\xc8\xec\xe2\x04\xca\x13\x8fN\xa3*\x96,4 \x12\x82t\xd9\xac;\xadyy\xb7\x81d\xaf\x18\xdf\xee\x96J\x1f\xee\xe6\xc4\xfc\xd7\x84\x9b\x93{-{\xac;l:\x8e\xc9\xe5J~0\xcc\xe9\"\xa8%\xae\x9b\x05|\x97U{\xf5\xd2\xbbv\xde\x10\x18\xc7\xe7hL7\x1b+\xc4E#\xf9\xe5\x96JZ\xc5f{)wC\xc2y\xe0\xf8\xe0\xfc\xf8\xea\xc3x<\xde\xb5\xa4F\x83\xf6\x05\xaf\x8b\xed.\xbb\xf8\xda\xb5\xb1\x08\xdc\x13n{\x9b\xff\x15,\xc3\xe2\x0d\xe7\xb7\xc0\xe6\xd3\xf8\x9a\x97IQ\xc7\xda__\xd0\x8bK\xef\xc6\xb0\xda\xbe\xe5,\xac|\xc3\xc8:\xdc\xef\xfa\xe5I\xb5#\xcc\\66-\x1b~\x93\xde\xf6\x15\xf0T\xcd\xdb-\xc9\x8a\xcc\x8f^\xf7a\xcb\x07\x84B\xf3^\xf1]\xedG*5^\xb6\x94\xf2>\xac$\x10\xb1\x8e\xd7\xa4\x0f:0 \x80\x8ah\x9a\x1c\x8a/\xc34\xcdJ\xa0\x0d\xf9\x18\xa7>\xe7\xeaM\x9d\x15\xd1zn\x8b$\xed\x1a:$\xebY\xe4Y\x03cn&\xbb*\xc6\x1e\x19\xdfa\x80\xe4X\xa6\xab\xea\x84\xfb>\xac\x9b\\\xce9nh./\xe8\xd2\x8e\xd2B$\x0d\xd6J*h\x91\xd9|\xf0\x91Zc>\x01\xdd\xfb\x13\x80\xe7\x10\xb4\\A6\x81T\n\x0eM\xa90\xca\x17\xb0\xf0\xd3\x02\x00Rj\x1b\xd1%sr\xd5$\xd3j\xeb[R\xf0}\xd1\xfa\x9d\xe7C\xcc\xe5\xeeg\xc3p\xb7\xa0\x06\xa4#\xc3\xb6>\\\x94$\x07\x92\xcem\xc1*L\xd4\x8d\x84\xa2\xf1\xb0\x98V \xefb\xca\xc3^\xeb\x9c\xb7\x9dK\x07I=c\nZ\"\x9e\xca\xa2H\x00\x89\xb8iH\xe53\xe6\xa9\xa8\x06\xe8\x7f\x1b\xde\xe1Ua\x0b\x81\xb5\x11\xf4\x14PfP\xa0\xb1\x80cM\xd6\xdf\x04\x05a= 9\xa4\xaa\xa3\\C\x9f\"\xd7i\x9a\xa5;\xac\xd9'\x1c\xd3 \x9f\x83\xc1\xbf\xb9A\xae\xb6\xee\x95\xba\xee9+\x89\x05\x1f\x1a[\xf7 f2S\xe6\xe6\xe7\xc6*\x01V\x19\xee~-\x0d\xb2\xed\x0f\xdaq\xf5*\xf1MM\xf7!\xf0R\xd7\xe8\x19\xd5A`\x8e\xdd\xdf\xdc)~}\xb1\xc7\x1e\xe9\xb4\x91<\x92\x9f\x87\xda\x08\xc3\xdeP\x8e\x06_U}A)\x11\x19K\x17\x9e\x99\x05T\x16\x8co\xbd\x03!J9Z|g\xde\x99Y\xaa\x16[\x8d\xac\x86\x91\xb4\xed\x02$ \xd73 \xaaf\xd0\xfc\x1d3\xdd\xd7d_c\xcb\xba\xa0\x05Q-\x18\xc4\xeb\xc1\x04\x0c}\xe7&b#k\xb3\xb5\x1d\xfa\n\x0b\x17\xdc}\xd8\xf0\xc6\x1d\x83A\xf3.?B\xacp\x0cq\x8f\xaa\x8c\"\x1cc\x1c~\xf9\x11\x92\x07c\xee\x05\xf9\xa17\x9d9;\xdb\x8f&\x0b\xd2\x1f Q\x8ey\x19\x8e\x8dL\xbe\xb1\xaeU\xc83:\x85\x89\xf9\xf02I\x8f,) \x1b\xf8\xd1 \x9e\x8b.\x88\x152\xce\x0f/\xb0/\x85\x82\x836 CO\xd5 \xe2I#\xdc\xd9i\x1c\x8d\xba\xda\xae\xd2!\xad+<\x9b\xda\x8bA\xa7!4a\x0c\xc8\xb3\x1f;;\xbe\xa4\x15\xa5\xe4\xab\xa4/\x93\xa4\x1e\xf8\xcb\xa8=k\x0bL\x98\xf6\x8c\x93\xc4\x9dD`A\xca\x1f[\x1a\xf3nZ)\xb6\xa5A\x14\xa4V\x19\x94\xd9O\xd9-\xc9_\x86\x05\xf3\xb0\xd8rg\xce\x92|\xa1\xdc\x11\xd7\xbb\xd3\x7fw\xf0\x8f\xb0\x88\xe2\x98\xfeq\x15\xa7a~\x87\x7f\x85\x059\xd8\xc3ZQ1\xe5\xff\xeeL\xf9g\x93\x83\x84\x88\x16\xc4\xdfyx+\x19\x19\xb9,\xd3\xa2\xa7\x8d\x03\xad\x8cp0\xb59\xe2\x90\xbbm\x8d[\xc1,\xae\x9bt5\x12{@ \xccM\x98 )\x10\xf7\xf6\xb6\x1c\x98\x8e\xb1\xb8\xb5\x8eZ\xc8\xbcr\x19\xde\xe4\x8d \x8bP\x1e3\x10\x8774\x17\xb2Y\xcan)@g\xc8J\x01\"\xe2\xc6>h\\\x0b7\xfdZX]\xb7y&\xd3\xb2)\xd3\x04fiDj\xa1[\x07\xe9F\x1a\x93\xa3\xb1/\x99f\xb5E\xd4 !\x95\xbc\xc5\xa8\x0c\xbc\x82\xb5\xe9\x92\xf1\xdamt\xad\xe4\xdd2\xa8\xb6k\x0bt\x1d\xa0\xf0\x01\xb4\xe7\xd6\xbe\xe6\x852\x1e+\x9fk\xe9\xde\xed\xec\x9f\x9e\xe1~1\x89z\xd3\x1a%\xf7\x8d\xf8[\xbb\xa6U*\xd7\xa9\x7fi\xb5\x9a:\xbd\xfc.\x93\x94\xa4s\xd7\xf3\x81\xb4\"8\xfd\xa1\x19\xa9\x9a\x9b\x11\xb3\xe8\x1f\x8d=\x8a\x0e\xdf\xacVd\x1e\x87%\xd9$\xb5~\x7f\x0e6\xfb\xbe\xf0\x03\xd2\x1b=\xe2\x9b\x0c#u\xf7\x0e\xf7<\xd7\x833\xee\xbf\x8c\xc9\x13\xd1\xb0\xf5p\xff+\xa6z\xd3\x84o>2\x87R\x99\x9a\xd3\xc2\xed\xea\xc1\xc3*\x83k5G\xec\xedPC\xfc\x1275\xb5h\xee\xca\x07\x850\x8a\x0c\xaf\n\xf5M\xf4Uy\x02n\xea\x90\x0d\x0b\x1f4k\xf4\xb8\x95=\xa5\xb2\xf8V\xaa\xdf\xa1B \xc5\x00\xb6\xcc\x1b\xd8k\xfc\\\x17Z\x84\x05\x86#h)\x0bo\xb1\x10Y\n\x16\xf0\xfc\x14\xb3\x14D\xee\x82\xa7\xfc^\xc6\x8d\x93\xd3\x0eDn\xe1.<\xef\x04X\xe4-\x18\x8d\x0c\xea(\xb4\xf3\x91\xa5\xac<\xccP\xc2Q\xe3\x8c\\\xf8\x90\xbb\x89\x94\x02E\xc3\x8f\xbc\xb47\xd3\xfc\xa0\x93\xa6xH\xb4\xb0\x91\x10Tj\x03\x18F\xd4\x9aDo\x96\x14\x8fHa\n\xc2\xc4\xeeA\n\x12]\xa5\xbcx`R\x82\xeeA5\x07\x8b\xd6\xad\xf3\x8b\xb0P\xcc\x9f\xc8\x97\xf2]6'\xaec\xcb\x99\x92ah\x01\xdbx\xb4\xb0\xb8]\x029\x0b\xfb\xcd\x1d\x858\x82g\xcau\x16#\x9bX\xf1w\xb7u\xa1\x90.\xb1!v0\xfdp\xaai\xe5\xc4c\x96\xa8\xa0\xcb\x9aJNY\xe4\xb8i\xe3\xc3\x08u\xfa?V\x1f1x\xe9Zf\x86\x176\x0e\xe6a\x19b\x98\xc2S\x18\x8d2\xf8W\x982s\x07l-(\x96\xf1\xa2t1\x04\x05\x17\xbf\x08\xafkN\xe1\x95\x06m\xd5\x83\x17dW\x05\xc9o\xd0R\xca\xbcx\xd12\xcc\xc3\xa8$\xf9\x8fa\x19\xb6\x82\xfe\xb3V,\x16\xeb\xbd\xf4\x02}X\x9a\x17\x0cai&X\x99\x94{F|(/P\xec\xc0\x15\x94\xa8\xbde\x04\xb0iq\x86\x88\xc5\x1e|3\x1c\xb6^\xe3v\xe4$$p\xec\xaa\xb0&\xc1\xb4\xe4\xf6f\xf6B\xe9\xe8D\xdcO\xdaM\x9d.\xa8C\x8cj\x1c\xca\xdb\xaa\xc4\x84|\xef\xd9\x8e7~\xb1\xb1\xdbze\xbf\x95\xc6\xa6\xffL\xae\xfe#.;:\xb0Th\x1f%\x1bH1\xdf\xa8\xde\xe0\xbb\x80\x8c_\xee\xea\xa2\n\x00\x16\xb8\xd5\xd8lA\xcaO\xf1\x8ad\x15J;\x0c\xdb!U\x182\x80\xa6\xba\xcb\x0e\xfb\xd8<\x98\x96T\xeeA\xba\xb2\x83\xe8\xcaoBeY3h\x9a\xb2f\xaay1\xa7l\\\xfb\xd3}\xfe\xef\xc1\xc6y1;F'\xd2S\x1e\x9a\x92\x8d\xa1\x86\x8f\xa7'P\xc3\x0e\xe7\xdda\x87\xd5X\xe9\x96|WV\xc8 \x84t\xed\x0e\x92,\xc2\xc3~\xdcJaF\x9fe\\\x94Y~g~\x99\xadI\xaa\xb2\x7f\x86J\x98\xf2\xab\xb7\xd6\xeb8\xd1+\xd9\xe6\x0b\xe2\x86K\xf1\x82\x9b3\x7f\x8b\xc9\xcal\x89\xfa\xccV\x1cta\xd8wmxr\xc3\x1dFm\xda\xb8\xb4C\xc5\x9b\xd7\xf1\xde\x0c\x82P\xab=Im\x08\x13\xf3\xb0Ih\x15$\x82B\xbb3\x87\xae\x95\xe3\x83\xf3C\x92]\xd1\x7f_g\xf9\x8a\"=\xe7\xc2;\x01\x16\x16\x13\x13\xf3U\x08\xc0]\xcf\x0b\xe6YJ\x90\xc4E\x8dE\x07\x92\x13z\x97\x98\xe5\x10\xb4\x93\x1f!\xc4)_3\xc693;QV2\x0b/\x86`5,\x91\x0d>\xec\x0b\x93;\x8c\xee\xe0P`\xe0\xd0k\xcb\x0b]=\xc9@\xaf;\xbb$\x1eW\xcf\\\x9f\xb8@h\xd6\xe7>\xdc\xf8p\xe7\xc3\xb5\xde|\x81y\x0f}\x98\x1b\xdc\x92W>\\\xfap\xe5\xc3m/\xbb\x08\x82\x83Z\x83\x08\xb6\xfa\xa2\xc6\x05/\x8c\xf1 \xe8#\xc2\x15v2\x00\x18\xef\x8fe\xec1\x87\xe0k*1C\x8a\x8ej\xd0\xacf/\xfbi\xf8\x86R8i\xad\xdd\xea\xfc\xca\xe2\xfce,\xdddD\xc3Gb\x00vmt\xf9\x05\xbd\xa5G\xe0\xc0\x1bq\xa0\xdb\x95\xce\xe1\xb4^[\n&n\xdaU^Y\xd0\xf1\x0bT\xca5\x82\xedV\x85\xf7p\n/f fNz1s\xfe\xed\xdf\xea\x8b\x85E\xe8\xfc\xf1bvcH\x1a\xfd+\x05\x86L\xdfxc\xe00?S\"\x00\xce\xe0\x1c\xce\xe0\xd6uHZ\xe61)\x10\xa2\xfd\n\xf6\xd4uoX2\xb7<\xbc\xc3\xa9\"\xa2z\x11\xf0\xafio\xef\xdb\x14\xd1\x1bD\xc5W\xf4\x96\xb8o\x18\x19\x8e\"\x0e\xcf\xf3P\xea\xae\x8b\ni\xf5+\xa6>G\xcfj\xf7\xca\x87/>%\x11(\xba\xa5<\x85\x89\xed\xb8\xe2\xabT\xd1\xea\x89\x0fK\xcf\xf3\xe1\x9c\xb6\xf0\x1e\xe1\x8c\xd8 \xec1H\xc3\x15\x93\xad\xbf\xe2x\xfc\xd7\x81P\xe6\xbd\xd5\x9f\xcb\xe3n\xf1[L\xf7\x8bW}\xeb\x15\xdb 1\xb4\x178\xb4_=\x1f\xc2\x19\xa1\x94\xc9\xaf\xf4\xaf/\xf4\xaf\xa5\x0f7f\x11\xdf\xcaj4\xc1\xe6t\x8c\x9bHw\xed\xd6\x15\xd3\xb4\xc8\x14(\x988\x86\xbb\xa6\xba)\xd3\x97x\xf8\xae\x1e\x83A\xb1\xe8\x9bl3A\x90\x89\x97\x14\xc2\xad<\xc0\x7f_\xd0\xa9gt\xea\x97>\xacf\x97\xa6\xf0\xa2,|\x91\x1b\x07\x1f`\x04q\xf0\x1a\xbe\x07wM\xbf{\xe5!\xfc]\x99c\x11\xad\xea\xc2A8\xf7FJH9\xb5\xd0\x0f]\xdfC\x1d\xa7\xa7\xd4\xd2\xe4\xda\x08{\x01\xc1\x8d\xba\xb9\xae\x08\xb3:\xcc\xeb4\xd2\x12}7,\xae\x05\xe4\xb5\x17\xbe+ mk\x0c\x1d\xd6\x81`\x1c\x06\xfd`\xa3\x91X\xe2\xd6\x9aF\xd2\xe30n\x1c\x8c\xd5\x1f\xb9+\xce\xca\x10\xf4S\xf7\xc64\x08DV\x1fX\x9a\x1etb\xe5\x93\xb9\x95\xba\x93}\x16\xa54u\xa7G\x9e]B\xccG\xf3\x14\xb6N-\xcaT\x91\xda{\x1e\xdf8\x9e\x0fN\xf8\xf5j\xd4\xa7m \xa1\xce\xdc\x0b\xc2f\xf2\x1b\x92\xfbS35|\xf4?3\xdd\xa2\xaa\xf6\x9bn\x9a\x19\xa8\x95s\x98\xab\xf1\xcc\xf9A\xa6\x93}\xcf\xdd\xd2)uc&\xf9\xbeu\xb1\xc7\xfa\x0cyB\xc76\")\xda @\x813\x163\x8d\xec\xe5\x9a\xb58\x85\xd0\x83\x94\x1e\xde\x8a\xed_\x88K\xb1\xbd\x0d\x11\x13^\xeb\xc1\x0d\xb8\xf3\"i\xc2\xe7\x16'\x1e\xff\x8e\x12p\xb3b4b\xf1}\xdd\xff\xca\xdc\x08[\xbb\xbfoZ3#\x97h\xb3M\xed\xdd\x9f}s\xaa\xe8\xcel\xfe\x95A\x93\xda\xc5\xf7\x06\xd7\xa4\x94\xb2d\xabV\"\x96c]\x8a\xbd\xe3y+\x91\xc5\x9de\x176\xf9\xae\x9ae\x8b\xf33\x8dW\x85\xf2\xf6L\xfd-\xd1x\xc7\xeag\x9c!?\x83J\x97\xe4n\xb8\xf8\x87\xe6\xc5o%\xe4no\xc5?s\x14\xd7\x03\xee\xcbu\xf8?;G\xb1\xf5\xec\x98\x12/\xfd\xcf\xcd\xa5\xdf\xb9\xcd\xbc\xb7\xf6.+\x16\x8b\xee\x04\xb6\xc1\x04\xd5\xb5<\xb6\xee\xd4RO\xd8,\xd1:{\x96:\xe6\x8c\xb7\x9b\xeda\x9f4m\xb2{\xd0N@\xbf\xfb\xf4\x9f \xe8\xa5\xe7\x7f@\x02\xfa}sR\xc4\x01\x19q-\xe7\xbf\xae`\xb3\x9f\xa4}\xf3@\xe6\xcd\xbe\xc7\x14.\x99y\xe6\x82g\x016\xbf\xa5TOhu\x14\xe1c*DJ\x9c\x82ns\x84 \xd6x6s\x8e\x03\x8e\xc1\xc5\x08\xdb\x98D\xf1e6'/J\xb7\xf0\xe4\xee\x9d\xe7\xc3\xdd\x1f\xa4\xa2e\xe7t\xa5\xdd\x91?r\xf8\x15\xc0!\xa4\xee\xde\xc4s\x13\x0f-i\xbb\x1aK\x1a\xd7\xcb\n\x83\xf4\xfa0\x91\xcc\xae\x1f(eI\xf7\xe1&H\xb3\xdb\xde\xd6\xb0\x96\xb5\xa19\x86\xce\x16\x06\x99\x94\xa2\x9c{\x01\x05zS\x1fb\xfcc\x12d\xe9\x8a]68\xa5\xd4\x07\xc6\xcap\xb3`\x9d\x15%\xbf\x85\x08h&\x18\x81i\x11\x84\xf39&\x1a\x94Se\x197Cj\x00\xc9\xbcE\x10\xafh\x8f\xe7Q\x1e\xaf\xcb\x82\x8e\xac{j\x0by\x0c\xdc\xa1\xdc\x07\xe7{)\xac\x17\x85\x94\xad\x11\xb9\x0e\x9f\x90\x83\xe4\xd4\x16\x1b9\xed\xcb\xc9\xd2\x9c\x84\xf3\xbb\xa2\x0cK\x12-\xc3\xf4\x9a [\x1d\xb9N\x81\xa3r\xbcNK\xf5\"\x08\xd7k\x92\xce_.\xe3d\xeeJ_yA\xbb\xe5\xbe3,\x123\xb1\xc6J\x16MY\xdcS\xab2\xb9\xd3\x94Q\xb2\xa0oN\x84bG\x8f\x99>%\xc4\xd7\xfa\xfe\x18\xd6\x1af\xa0\xb0\xfa\x18\x9a\xecC\x9b\xd1)\xf6\xc1\x9a\x95\x0fVy5},\xce\xf5\xf4\xb996{\xee\xa8\xeb\xd8i\xd7\xda\xdb\xb5\xc5\x04\x9bv\xdd\xd7q\xcf\xeamJ\xe9\xb4\x0c29\xa53\x1ed\xed\xa2O\xbe1u\x89]\xe6YH\x14\xe5\x1e\xea\x9bl\x9e\x857<\xb6U\x16,ZQ\xc4\x05!\x8c9\xc5sRd\xc9\x0d\xf10\x9c-F\xb1[\xc5\x05y\xec\xc2\xb4V\x80-\xcc\x9e\x9d\x04\\\xd1\xad\xef'\x00M\xd4\x9f\xd9\x99\xb2\x0en&9\x963O+N\xdemmQ\x02\xcf\xf9H\xae_}Y#h\x8c\x15\x0f\x9bAS\xb6\xdf\xd6\xda5#u\xa7\x87:A\xd7\xb8v(\xf2\xffA]\xca\x12V\xe3*\xeb\x9dq\x03\x84\xa3\xde\xc5\xb5Q\xd7\x88\xa1\x02\xae\x1b\xc6\xa46\x1eW\x8f\xb12J\x16\xb5\xaeX\x85\x84\x9d\xba5\x15\xcf\xfb\xcb\xb2A\xb9yp\x0e#\xc8\x91Y\xce\xba\xf5\xbc\xf4\x90(\x85\x98\xbf\x9dk*}9|\xd4\xa054\xcb\xae\x89\xecr#\xc2\xb5\xf3}\xec[(\x14\x8e\xba\x8a2\x9d\xd8B\xa9\xf0\x80\x84\x14\x97@\x08Q\x12\x16\x05\x84\x85\xe2%\xfb\xbbLG\x93\xd2\x0bO\xa4\xc9\xbe\xe9\xc4|{W$\xe3Z\xb6\xc8\n\xfe\x02J\xab^\xbc&oS\x96\x1a<\xc5\x18]\\\x9d\x03\xe9h\xd4E\xe8\xe7h\x89\x92Z\x08\xfd\"\xd2\x84\xac\xa0s\x01\x0f\xad\xaeB\xf6\x89\xe4\x95\xbd\x95\x07\x0b\xce\x97\xb1\x80J\xe5\x8c\\l\xb8_\x8f\x03%8WJY\x1d\xea\x1a\xdf\x98\xbf\xda\x1dO\xf5W\x19\x7fE\xe1\x8f\x9c\x86\xb0F|\x86\xdc\xa4\xb5\x89 \x0b\xd4,\x83\xa5\xb2\x1b,iA5\xfe\xd0\xfek#\xf8d\xb9\xea\";\xc1\x163\xc27\x12=\xe7\x14:\x01\xf9\xb2\xceIQ`\xd6\xa4\xaa(\x81\xc4\xe5\x92\xe4p\xc5c\xccf\xb9D\x05\xb1`\xcd\x0e\x8c6\x86J\x1a\xb8\x935s\xccc6\x96\xaa3\x8eJ\xc2\x8d\xed\xe5\x94\xd8-\xd3jC\xa7\xf5\x0d\x0c\x08@\x07\xaa\x91\x96\x85\x95\xd5\xcc\xbd\x0c1,\xd4\xdd\xc6\xfb\xc8\xa8\x11\xb1\xc7g8\xfd\\\xa1CD\xb2\xa1K\\\x83\xcbKJ!}\x93\xfb\xa3\x1aX\xef\x8e\xbfM\xfc\xa4\x03\x93}`\xea\xee\x99\xedz'-\xc5\x12zMS\xe09f\xe1\x07\x0e&\x9eb\x906e\xe5\xbb\xe3\x03\xe3\xf5\x0cMc\x06a\x97\xb6\xce\xb3u\xd1\x845\xa4\x98\xaa\xe4\x01HyIN\x16\x05K\x0d\xc5B\xcc\xad\xe7a\x89\xf9\x0f0Nr&\xad{\xbb\xef\xe2\xef\xd8w\xa4\xba\xdd\x87r\xf4\xa9\xe2# \xa3\xf2e\xb6Zg)\xc1\xbc7\xbf=\xf8J\x95\x82\x94\"EY'\x90\x91\x88\x11%n\xa69\xf4\x90\x04x\xd8\x8f\xdcu\x0e\xf7\xeb\xec\xef|~\x01I\xffZ\x91\x8a\x9c\xf31\xd4V\x15\xbe\x94\x87^\xab\xfb\x92\x87\xa2\x15\x11\x9d|p\xc4\x14T\x01\xa7<\xc9E\x96G\xe4gl\xa8[\xb6f\xe8\xf0u\xf3\xad\x906\x96\x03\x07W\xfa\xe0H]\xab\xe3\x8b\x14\xd8\x17\xcap\xaeP^Qp\x1d)\x85\xaa\x94 \n\x1fb\xb7\x90\x1b\x90Z\xf3\xd4/\xe3\xe2C\x95\x93\xd6\xa9\xe0 D,\x8cB]\xf3\x18B\xf5\xca\xd2\xc6\xa4\xb7\xc5\xb7\x00N\xa9{ ;\xaf\x0b\xf8\xa2\xe1\xbc\xe2mV\xa5%\x99\xf7\xc5\x0d\x14\x14\xb5fc\xa9NC\xdb\xbe6ae\xae/\x1d\x0dm\x18\xe6\xfa\x1f\xc9: #\x16\xa0ph\x1f\xe2n\x18\xea7\x8bm\x86\xec\xf9\xe3\xf7@,\xba\x1c\xac\xfe\x1b7\xfd\xdb\xb7\x1f\xb5\xfd\x04GU\x9e\xe3 \xdd\xdcu\xa2{\x16\xc3\xb2\x9a,\x98#H\xf3\xcburz\x05\x03\xc2\xd4\xf8\x0e\xfa\xdb\x1c\x8c'\xe3\xdd\xdfuQ\x9c\xf3W/?\xbe\xfat\xf9\xe3\xfb\xcbw\xef?]~xq~~\xf9\xe9\xdf\xdf\x9c_\xbe\xffx\xf9\x97\xf7?_\xfe\xf9\xcdO?]\xfe\xf0\xea\xf2\xf5\x9b\x8f\xaf~t\x86\xf4\xa9Q\x12\xd3\x897L*\xd1\x17!\xafu\x97\xcd~z\x14\xfc7T\xb7\xd1I\x8f\xd3\x7f\xba17\xa6\xbb\xba&\x14\n\xae\xb2\xf4\xd5\x97\x92\xa4\x94\xf8-0\xca\xf85)\xb5\x12RD\xe1\x9a\xfcH\xc8\xfa\xa78\xfd\xfc!\xc4\xa4\xcb\x84;\xbb\xb5\x8a\x8be\x98$\xd9\xed\xab\xbfVa\xf2\x1f\xe4\xae\xe0i\x05\xe3d.\x82\xbe\xb0jY^\xb2\xccz$\xb8*3^H\xf28L\xe2\xbf\x91s\x12\xe6\x11ko\x1d\xe6\x85\xfc\xfb\x9a\x94\xe7\xe1j\x9d\x90\xf3hIV\xec;L\xd1\x10\x96\xe4C\x98\x87+\xad\xa4,I\x9e*eo\xe3\xf4'\x91;Z*\x0d\xbf\x18J\xffX\xc5s\xa5\xe0\xc7\xb0$\x9f\xe2\x15Q\n\x99%\x8cR\xf4C\x96%$T;~\x1d'\xeawo\xd2\x92\\#\xad\xd3\x94\xbd\xabVWZ\xd1\xdb8\x8dW\xd5J\x1fn]Fi\xac\x97K\x12}\xe6\xdf\xad\xc8*\x8b\xff\xc6\xba\x8a\x8b7\xabU%\x84~\xa6\xd0>\xe2:_Q\xd6p\xfa\xd4d\xbd\x1e\xd7\xaf\x8fL\xaf3\xfe\xfap\xcf\xf4\xb6\x12\x1f\xef\xee\x9a^\x87\xf5kc\xd7\x05\x7f\xcd9S\xf9\x15\x9d\xdc\xff=\x7f\xff\x8e\xeb\x00\xfa\xec\x19\xec\x9eK\xc2*\x816\xc6\xce\x9b1\xb9-p~\x93\x85\xa4kb\x97\x0d\x11P\x15*+X+\xc6Z\x9d\xf4\xa4\x93\xb2\xa1\xf4:\xedD\xbc\xb8\xeb] \xde\xc8+\x17C\xd6|qy\xe4\x9a2\xfb\xbf\xe7.\xb2]\xaa\xdfj\xdd\xc3\xff\xcf\xde\x9fw\xb7\x8d#\x0f\xa3\xf0\xff\xcf\xa7(\xeb\xc9/C\xb6i\xc5r\x96N\x9c(\x9et\xe2\xa4\xdd\xd9z\xb2\xf42\x8a\xc6\x87\x96 \x8b\x1d\x89TH\xd0\xb62\xf2\xfb\xd9\xdf\x83\x02@\x82$\x00\x82\x8e\xbbg~\xf7^\x9e\xd3\x1d\x8b\x0b\x96B\xa1P{\x85i\x1a\xae;t@E\xb3\xe8\xd8\xaa\xfe\x8d\xbd\xbc\xf70@v4nv4K\x93\xe5O\xef\xdf\xa6S\x92\x125\xef7PO\xab|g\xabr\xe1\x11c*S(VN\xb1\x84,\xe5\x92\xf4\xd9\xbe\xb4}Z\xc0\x8b\x94\x19x\xa3\x8c\xcf\x04oM\x8a\xa6\xde\x93/\x1e\xf1\xfb\xcbp\xe5Q\xccd\x1fe\x14g[\xbe\"\xa6\xf5:\\\x95oB#\xc6 +;D\xf1\xf4C\xe2$\xa2\x80b\x16\xab\x1b\xb8\xa0jV\x0d\x159\xdb\xef\xcf\xa2\x05%J<\xa3\xb1 \x91hA\xefD\xa3\x8d\xf9\xf3\xd9i\x7f\x18N\xe6e\xeb\xc6\x1c\x01\xd2*0J\xc7h\x0dM\xc78{O\xe4^\xd7X#\x9a%\xfe\x18\xc8\xe2$]\xe2 \xc2qn\x08\xef\x03\xa4\x13\xcfcW\xa4m\xc9\xe8\\\xf4\x14e\x05\xdd9\x14}\xe4X\xfd\xf8\x9a{\x91\x13qj\xb6\x8a\x9bu\x97\x10A%^\x87+\x17t2\xa2LJ\xa6\xf9D)\xf2g\xcb\xfdP]W\xe2\xb1\x95\xe5\xa6\x9df&\xd8\xcb\xa0\x12\xd1\x08\xca\x90\xdfa\x97\x7f\xd9\xa8\xcfD=\xabr\xbc\x06\xcb\x9cP\xf7Z\x0f\x84\xa8\xed@\x88D\xa5\xa7\xdd\x00\xf2\xf2n\x1c@\xd4 L\xd9:\xa3d\xf9a\x9e\xc7\x9f_G\xd3\xe9\x82\x9c\x87\xa9]\xe4\x07\x9d\xe5\xce\x04\x13\xd2\x9fJ\xf7I\xc1\x85\xe9K*@\x97Fu/7\xf4H\x86\x0f\x8cyKc\x8fz\xe8\xbfE\x9c$\x8b\xe9\xc3\x1e/_\x8f\xff\xa9\xaf\xe2\xbd\xf1h\x05\x07\xb8v\xb7\xe1\x00\xf6`\x1f!|\x0f\x0e\xe0\x8e\xf8\x9b\xdd\xbf\x0d\xfb\xb0}\xeb_^\xe8\x9dd4\x0d't\xb3\x88\xc2l\x13O7\xd2y{\xc3\xf6\xec&\xf3\x96\x9b\x8c\xa4\xd4?\xd8\xe44\xf17'^\x98\x91\x0d9\x8d\xe2M\x92,<\x12\xc6\xfe\xc1&%\xe1\xe7\xcd\x9a\x12\x7f3\xc1\xc7\xec\xc0\xd9\xcc\xc3t\x83\xf2\xedt\xb3\x08\xb3l\xb3Hb\xb2I\x96\xab\xc5&\x893\xbaIb\x1a\xc59\xf17S\xe2\x9d\xe4\xa7\xa7$\xddL\xa2e\xb8\xd8L\x16aJ63\x8f\xed\xf1\x0dI\xfd\x83M\x14Gt\xb3\xf0\xc8iH\xc9\x86P\xe2\x1f\xf8\x9bi\xb2\x99&\xf9\xc9\x82l\x887\x99'\x9bEv\x10\xcd6\x8b\x8cx\xd1\xcc?`\xf3\x88\xb3<%\x9b8_n\xceHL7\x17\xde\x84\xac\xe8\x86L6+\x0fS4o\x92\x94\xfa\x1bJ\xbcx\x9amPs\xb2Ic\xdf\xf7Y\xd7\x8b\x05\x9d\xa7I~:\xdf\x84\x8b\x8cl\xb0l\xf9b\xcd\x86r\xc1\xa6\x93\x84\xeck\x8f\x84\x939\x9b}D\x18\xd8\x92\xe5&\x8f'\x1e\xdb\xbdl\x80\xa7\x8b\xe4$\\lN\x13\x9alN\xf30\x9dn\"o\xb6Y\xae<\x8e\x03\xd9F\x19D\xecEt3Y\xe4S\xe2\x1d'\xf1\x84\xf8\x07\x9bE\xc4\xa0\x95\xd3\x8d\x14}6\xd4#\xe9,\x9c\x90\x0dI\xe3p\xe1\x1f\xf8\x07\x9b\xcc\xdf,\xbcpy2\x0d7\x84n\x92\xc9\xe7M\x12\x9f\xfa\x9b\xa5\x17M\xd2\x04I\xe0\x06\xf5L\x1b\xaeK\xf07o\xc27\x9b\xd8\x0b\x97$[\xb1\x96B\x1a\x9d\x91\x0d\xb9\xa0\x1br\xbe\x89\x16\x9b\x84n\xf2\xc5\xc2\xdf$\x1e\xb2E\x9b\x15\x8f\xaf\xdc\xa4\x9b\x9cn\xceH\x9aFS\xe2oV^8\xf9\x1c\x9e\x92M\x98\x86\xcbl\x93Fgl]\xd2\x84\x92 %\x0c\x104\x99$\x8bM~\xb2\x88&\xfe&\xf5\xc2\x88a\x8c\x17N\x93x\xb1f\x0b7\xdb\x9cF\x19%\xe9fEB\xba\xf9\x92Gi9\xefl\x92\x93\x0d\xd7\xb3mh\xba\xde0\xaa\xe8\xfb\x9b\xcc;Y\xb3\xc5\x0f\x17d\xba!\x8b\xd9f\x9e\xa4t\x13\x9d\xc6d\xba\x89\xbe\"xB\x1aM6\xa8\xd3\xd9\xa0\xa9a\x93\x9fp\x97\x84M\xbe\"\xe9f\x1dO\xe6i\x12G_\xc9t\x83\xb1\xc4>\x83\xe8r\xb5`\x83\x9f\x93x3\x8f\xb2\xcd\xf7|L\xd1\xce\x06\x87\x11^\xf3z\x8a\xf6\xcc)E\xfb\x14\xab\xfc\xa2AB\xefGR\xbc\xdc\xf4\x86\x99\x06Pw\x06\xae_X\x8b\x8c1\xa6\xd6\xb7N\xf1\xadA\xcb[K\xc6\xd3z\xa7\x01\xc4\"\x83\xc9\x00K\xede\x84za\x00k[\x81\xe2&*H\xa1c\xc9\x84\x8e\\: .1\x19\n\x0fq[\xea\xb9A\x0d\xb1hMU\xdb(\x9a([0\x11\xa7\xc2\x9b\x8d{\x87\x95\x84\xbe$U\xa3\x81\x86\xb8H%\\\xa3\x08J\x80\xf6\xb5l\x12.\x9e\x86\x19\x1b\xd6\x93\xea\x9d\xe7b\x90\xad\xa0\x91\xeaG\x8f\xf6Sn\xe8\xf7n}\xea\x8f\xfe\xd5\xbf5\xfe\xee\xc6-&J4K\x7f\x92~\x16\xc6\x11\x8d\xbe\x92\x8f\xe9\xa2\xb5\x87H\xad_\xabz\xdb0a\xadW\x8b7\xd2\xc9\xd6\x8abp\xa6\xf6\xeck\x8f\xe0SB\x9fL\x18\x97\xcf\xb0%M\x16\x8b(>}G\xb2U\x12g\xed\xd0\xa8\x9dd\xa5\xc2\xbf\x1fe\x8a\xf6_Q\x87\xb0\xa51i\x0c\xaa\xc7\x9e\xfe\xcdR\xbf4\x8b\xe2\xa9\xd7\xaa\xac\x91Wq\xc2e4Li\xf6kD\xe7^o\xafW\xe8#U\x15*\x83\x89\xd7\x9b\xf0\xdd\xc3\xad\xf6\xff\xbe\xf4K,lz\xfe\x01\x98+X\x15\xaa\x1d\xaf'\xba\xe8\x89\xc4\x9b\x1a;\x89\xa1\x8d\x14\x9d\xe64\xe3\xd27\xe2\x17\xca7a\xea*\xb3\xa4\xc5\"O\xa2Y+\xc7\x9aM\x9bx2%d\xb5X\xbf\xa7i\xb4zI\xd65~\xcd\x927\xecZX\xaab\x99[\x94\x81:\xa7L=\xb6ut\xbb\xafZ51\x99N]K\xb7\xd9\xa8\xe4\x8f\xf1q\xb1\xcd\xd4&5\xef5e\xf8\xbf\x19\xb05d\xb1\x86\xa3\x91\xc6\xe4dVh\xe3\x98b\xee\xa1\x17a=D\xd4*\x8a\xc8mv\x87 5<\xa1\x0c\x15o\xe8\xd3V_\x9aU\x90\x91\x86\xec!\x15s\xb1\xa3F\x86\xa2\xdd\xa6\x94\xe2\x80^)\x0c\xb9A-\xeb\xcdp\xddp\xa6\x18\xad\x16\xb4m\xc1)\xb7Z\x94\xd5\x8dMn\xf5P%\xbeU7_n\xdf\xd3T\x94+\x98\x9d6\x83d\x91o\xb1\xd9\x84iM\x18L\xc4g\x1a\xd2\x1f\xa3\x03\xc6\x87\xa4p\xeapX#\xfe\x8da\x8d\x94\xde\x8chR3\xfdU\xdfc\x9bb\"\xfd \xee5\xfc\xfa\xa1\xc8\xbaq\xfbN=<\x05D\xee\x0d\xf4\xb0\xb83\xd0}\xba\x92-\x7f\xbf\xab{\xaa\x0f\x89\xaf\x16_e\x0f\xcf*\x07\x89\n-\xa3\x05\x19\xb3\x16\xf4\xa3\x18\xf5\xe3\x99\x17\x97\x0c\xb8N\xb7\x02\xaa'\x809:\xd7m\xa3\xc1\x01(\"A\x84A\x13\x11\x16Z5\xf2\\.hm\x8d\x95t\xf1<\xc0C\x9c\xe2\xa7Q\x93\x18p\xfe\xad\x9f%K\xd5s\xa2\x8d\xddd\xbd\xac\x95a\x8eb\xc6[\x8db\x8d\xdd\xeb\xb2\xbe%\x9a'\xdf[\x83\xdfc\xeb\xfe\x80\"\x10\xf01\x94\x02T\xef\x97p\x91\x13\x1e\xe8uB`A\xb2\x0c\xe8<\x8cA\xb4\xdck\x8e\xb1\xb9;\xfe0\xf8gv\x18\xd3#\xf3\x98NQ\xe5\x9e\x8aa\xf1\xc6\x9d\x86\xf5Y\xefI\xda~Z\xa0\xa4y\xeb_;\x07\x9f\xa6\xdb\xde\xa7>\xfb\xc7?\x90\xb6\x01EN\xad\x0d4\x04\xc1\xf8\xb8\x0c\xee\xc8\xe0\xfa\xdamt\x0e\x83\x8a!\xe2\x8d;\x0d\xeb\xb5\xceE\xd7mLx*\xd5\xf2+\xd4\xbc\n\xcd\x90\x9bE\x0b\xe24\xc0\x0f\x06\xbfb\xb71\xf6h\x9a\x13N\x1aD\xccR\xb8\xc8\xd4\x1b[\xbb\xca\xdf\x03\xc9\xca\x9bF}\xc2\xbbw\x1a\xf8S\xbd\x8f\xb4\xdb\xb8\xf9`5\n\x1f\xf3\xd8\xc4\xcb.C\xfb\xd9\xe4\xd3\xed68^\xb1\x9f}V\xb8\x0b[VZ6\xef4\xb2w:\xf7s\xb7QIqO\n\x1b}\x9a\xbcJ\xceI\xfa4\xcc\x88\xe7\x07\xb0u\xeb_\xa3\x7f{\xe3\x83\xd1\xee\xce\x83pg6\xfe\xf7\xfd\xcb\x9d\xe2\xef;\x0e\x7f\x0f\xf6.G\xfe\xe5\xd8\x890\xb0\x91;M\xf8\x8d\xd1\x0b\xdf\x9d\x98\x96\xbc\x89\x1b\x9d\xe7]8\x0d\xef\x951t\xa0\xfb\xf0:\x90\xfc\x0e#|f\x08xp\x1e\xdf\x16O\xebpzx\x81\x1e\xc9\xb6\xa5\x9d%\x8bEr\x0e+\xd1I\x0f\xb6u.\xec\xd53\xbc\x19\x9e\xd1:\xb2\xabr\xb67oV~\x9b\xb9Z\x13\xc7\x8b\xac\x1eR\x9e\x93d\xba\x16je\xae`\x8c\xe2\x1ew\x93\xc7_h\xc8:\xbeX.z\xc7\xd0\xf9LyS\xb0\x1e\x867\x17\xe5\x9b<\xc9\x85\xfe\xb5U\xf9\xda,I\x97!5\xbd8\xaf\x8cQ\xec\x00\xc3\xbb\xd3\xca(\xed\xef\x9e\x95\xef\n\xc4\xad\xa7\x1e\x01\x01G\xeet\x950\xa67\xb2f\xe6\\3\x91\xbdT\xcc\x0d\x01\xbf\x8c\xf4\xfd\x83Pe\xf4B\x99\xe0[\xbc_\x15\x9ay\x82\x97H\x16\xd306u\xackJot\x94MN\x92<\xa6&-:\xbbN0\x9c\x8fq$\xcal\xccl\x8d\xb9!\xd4eH&\xa1l\xcb\x8bx\xa6\".\x96X\x06r\xc1\xbe/\xb5i\x95\xcfw[\xbf\xc6\x94\xf1\x92\xf9\xeb\xfe\xf9\xa1\xc1\xc8\x0e\xd2\x00\xd7\xd0B,\xcc\x9e|V\xed\xaa\x9bdvhp\x08\x90\x17O\xef\xad\xd7\x11G6u\xac\xbc\x94\x80\xa7\xc8\x0fD\x7f\xc6/\xda\xed\xcf\xf2\x92\xb4\x88\x1b\xb8{H\xf7 ;\xde\xf88y\\bq\xf6\xe1\xf1\x80c\xe9\xf9\x81\xa1\xfc8h\xf5\xb9 \xb6\xe3\x13F\xd2\xd7\x01\x9c\x16\xb5#0\xb5\xfd\xfb\x00\x0e\xc75\xe1\xd5:\xf6R\xdf\xa4}E\xa7\xe6\x07\xb1\xd4 \xf2\xcfe\xf9 9\xf7w\x82\xd6\xc3,\"\x8b)D\x19\xe6\x0fY\xa5\xc9Y4\xc5\x13@G\xb1e\xa3g\xb6\xc1\xb2\x89\x7f\x85!<\xf3\xa2\x00\xce,N _\xd1\xc4\xc1\xc7\xf3\xd5\xd5\xd9\x00\xc4\x10\xe6\xe5\xd6\x99\xb7\x8d\xe69\x0c\xe1\x0d\x1b\xcd\xdc2\x9a\xe7\xcah\x9ew\x1d\xcd\xb4m\x08\x1fa\x08\xaf\xd8\x10\xea\xa5E\xd4\xeb\xa32\x84\x8f]\x87\x10\x96\x00 \xdbF\xf3\x03\x0c\xe1-\x1bMh\x19\xcd\x0f\xcah~\xe8:\x9aY9\x9aY\xdbh\xbe\xc0\x10\xfe`\xa3\x99YF\xf3E\x19\xcd\x97\xae\xa3\xa9\x1e\x89m\xe3\xf9\xdd\xe2\xb7$/\xe4n\xbc\xdfQC\x1eR\xb2C\x99\x1c\x85\xcd\xaf\xe0\x00~\xf6P\x85\xd6\xcb\x99\xb0Q\xdc}\xc7\xef>\xe5D\xd4\xcc\x17\xc9K\xcc\xf6w\x93\x1bKIf\xab\x07[\xdb\xfc~\x85!|\xf0\"\x0b\xb0qv\xbfv\x18\xe3\xaf\xedc\xac\x1c\x9emC\xfc\x05\x86\xf0\xb9}\x88\xbft\x18\xe2/\xedC\xac\x9e\xd0mc| C8j\x1f\xe3\xcb\x0ec|\xd9>F\x95\xc1j\x1b\xe1\x8b\x96\xa1\x1d#\xf3S\xb0a.\x03}!y\xd6\xa3\xd8\x1b\xf5\"J\x96Y/\x00\xceg\x8f\xfd\x00\xa2\xa6\xa1\xbb\xcd\xd7\x03\x14\xc1\xaam\xdb\xb1\xab\x82I/\xd0I\x82!\x0b\x06\xabV\x97P><\x12\x0fU*\xf0\x02\x190\xf6\xf4)\x13*\x03ap\xe7\xeb`\x1f,\xbb\xa2xJ.\xf6\xa1\xc5g\x90]$M\x93t_\x13/\xa7^\x97\x96x\xb0v\x9cP\x18\xe46\x94\xb8\x01Cx\xdd\x8e\xb47\\pA\x00\xeb\x86+56\xda\xbd5\xfe+\xcdl\nvNI:\x1a}\xbb\xbb\xb1\xc6\xd2 \xc2/\xa8\xab\xd8\xdf0h\xe9\"\xa0\x19\xbco],\x17BwE\x8c\xf2]\xc4\xbd\xae.\x96\x0b\xdc\xb6\xf8\x17\x166\xb2\xad9\xd7\xf3\xb0o\x98\x94/\xbe\xfd\xf7e\xc0\xbe\xbfq#%3\xd5\x1d`\xbdBO\x18\xda\xc7}\xcd\xff\x14%WD\xb9'\xda\x0f\xa7S\xf4M\x0c\x17?\x97O\x0e\xe0o\x8f\x0eX\xe3g$\xcd\xa2$\x1e\xf6\x06\xfd\xdd\x1e\x90x\x92L\xa3\xf8t\xd8\xfb\xf8\xe1\xf9\xce\xfd\xde\xc1\xe3O\xb1pl\x87\xdf^\xbf\x02r\x81K\x0c\x13\x9e\xe2\xf7\x84\xc0)\x89I\x1aR2\x05\x1e\xa4\xf47\xa3\xff\x93\xbc\xa4!LL\xa7\x8f\xa9\xb1\xbd[\x9f\xde\x7f\xf7\xe9\x96\xf7\xe9\xfd\xb6\x7f\xe3\x96\x05\xd9K \xc2\x10\xa2\xd1\xa0\x19\x8c\x08F\xc6B1\x16\x9eJK\xed\xf4)\xea\xcb~{\xfd\xea\x90\xcf\x8d;\x93\xb8\xf8\x80\xb0\x89$\xc2\xc3\xa8l\x8fo\x82\xe7i\xb2\xe4\x1bA\xb4\xd7\x9c\x91T\x8a\x99$\xbb\xa4M\xb2K\xb0\xbcm\xcd\x13&)=a`_\xc9y\x06Pxi\xaaYP\xac\x8e_g\xa2\x0eI=\xa9\x92\xbc\xd8\x12\x94\xe2\xfc\"\x99\x84\xac\xa9~\x86\x8d\x1b\xf4K\xa5\xde\xd2\xb4\xb5z\xa8\xa47\xee\x11y\xf0\x90~\x96\x9fd4\xf5\x06\xbe\xac\x17tS\xa7\x8d\x01\xd5C=\x85(\x86\xd8\x87\xb8^>%\xe5\x8e\x8a\x18g8J\xc7\xb2\xc5!&[\x1bM\xc9$\x99\x92\x8f\xef\x8e\x8a,]^:\xda\x1d\xfbc,\xdd;@u\xa1\xf6\x9d\xc1\x98\xdbU{.\xf8$\xb7us\xcd\x9a\xd9l\xec\xb4\xd5h\x15_\x86+\x07\x7f6\xf19\x12\x83\xea\x8c\x88\x0f\xdb\xd0\x1b\xa2\xb6\xb6\xf9\xb4\x9a\x99T^\x97~\xff\x8f$\x8aqy\x9aS\x13\x19{\xec\x83\x92\xf3\xa9d\xdd\xa0\"n\x17K\xd5yD1W\x04\xd0\xcb\xe9l\xe7~\xcf\xf7\xcb\xbb\xbd\x930#\xf7\xee\xe8\xc6Pf\x10jv\x9d`\xb8Y\x94\xc4\xd9{|\xcb\xe4\xb5\x13.V\xf3\xb0%\x97\xacz\x154\\j\x13\xe7=\x1f\xb7\xd0\x02S\xc1\x85)\xf1\x88\xfa\xccpd\xeb7\xe6\x92\xd0y2\xbd\xf2h\xf8\xe7\xa6\xf1\xc8\xa7\xceLDs\x8c4<\xfd\xb3\xc0Y\x1b\xb2\xf3 5\x98Y\xcb4\xe5\xc6\xce\xe8\x9cT\x94\x8c\xeeQ\x0cF\xbd\x91\xf4\xe6\xa5F\x0f\x11\x85m\xe1\xa5oz\xe5\xdf\xa2\xcc\xd1(\x0e\xd8\x06\x0dt\xfb3\xf5K\x9f\xfa\xff\xd9\xdb\xbdu\x1a@o\xbb\xe7\x8f\xc5\xfe\xd4-\xa9\x91J\x11\xdb\xa6\xd6d\xee\xaa\xac\xa4\xc1\xb1\xa6P\x9a1\xc25- W\xac8\xe5\xb4\xb9\x8ct\xf2\x18\xa9\x8e\xbc\ns\xa9\x143\xa4's\"\xc0:\x8f[d\xcaT:&\xcc\xd9\x98\xd4(\x8d\x96\x9e\xb2H\x9f2\\\xa3c\xb4\xd8\xf4z\xb6\xe1\x1a\x92\xab9\x0d\x93\xc1\xec\xb8\x84\xd9\xd7\xa6{Y\xa0I\xe7\xe6\xd44m\xe6\x9b\xb0\xecd\xf1\xd1\xad\x7f]\xec\x14\xccu\xeb\xb2\x05\xc6\x14t\x7f\xe6\x08\x85\xfdgS\xd8\x976\x85\xf5h#\xecb\x1ba\xf5r\x9f\xca\xff)\x1f\xf0\x94\xdfl\xa7x\xf7\xee\xfb\xfd\x1f\xf2\xd9\x8c\x08\x7fq[\xf5\xa3\xb3\"sSq\xf2\x95x\xa2\xa6\x19\xacX\x8c\xc0%S|o\xc49U\xfe\xe9\x18\x91:nT\x8cr\xca\x06\x89\x94\xae\x1cWjcD\xf59\x0eAaO\xf9T\x94d\xbc\x8bhBL^\x97\xc4\xb8\xbc<\xa4\xaa\x9aL[\xe4K\xe4\x14@-1\xe1c)+S.\xd9zZr\xfdP\xecx\x99\x97\xbe\xaf/\x9b%\xb9\xf4-\xa6\xd6\x16\xc3\xb2\xc5\x17\xae-F\xd6\x16\xb3\xb2\xc5\x1b\xae-&\xed\xb3\xbey\x13\xb6&e\xd3?\xba6\xadI-\xaf4\xbd\xe5mQ.\x87\x8f\x16c\xb7\x06C\xd7\x06\xeb\x898L\x0df\xae\x0d\xce\x1d\x1b\x9c\xb4\xaf\xf8f\x83\xdd:57s\x1d\xdf\xb41>\xf5\x17\xf1R^\x83\x85x\x91\xfc#\xe1\x7f\xc4\x8a3+\xcf\xd5\xcd\xee\xbc$kL\xcf\x17\x8a\x17\xe2)\xb9\xc0\x1b\x19\xbf\xf1$\xcb\x92I\x84\x99!\x00s\xb8\xc4e\x00\x1c`x~\xdc\x97m\xb0\xae\xfbe\x0bl\x00\xfd\xf7\x04k84\xe9\x07\xa6\x19\xf8\xfb\xdf\x8f\x8f\x8f^\xbf\xfe\xf8\xe1\xc9\x0f\xaf\x0e\x8f\x8f>\x1c\xbe\xc3?\x8e\xff\xfew\x8dji\xd5\xfc\xe2\xe5\xe1\xef\x87\xcf\x0c\xaf\xcf5\x1d\xbcyv\xf8\x9b\xf1\x83i\xf3\x83\xb7\xef\x9e\x1d\xbe3~p\x06C\xb8\xdb\xbc\xbd\x86!\x0c\xe0\xd1#]\xb5\xf3S\x18\xc2\x1av@\x93\xaa\x7fi\x90\xf7\x8f\xed5\xae\xf7\xeb\x89$A\xcf\xf9\x9f\\\xa5\x19\x13-?o9\xd8\xb9q\x18\x0b\xbb;\x92\xe4\x0b}\x8bT\x1c\x0dE\x83\xbbn\xdb\xe9=O*\xaf\x7fxh9\x89D\x84\x9bF\xaf^\xa9\x0e%\x0bH{\x98x\\\xa88w\xb0JH*r\x9e\xcb\x94\x05<\xd3\xc6\xeeCLw\x11?\x84h{\xdb\x87t\x14\xf1$\x89\x11\x13\xe8\xcd\xee\xf5\xa9\xd3l\xed\x01\x0d\xaa;:\x06\xa2\n\x98f<\\\x82\xf6\x8f\x8fy\xe9|\xe2\xfd\xc1OW\xf6\xc4\xa9\xe3\xb7\xd6Tb\x85\xf5A)\xe9a\x13\xc1P\xb9\x04\x8f\x1f?6\x995\x84\x92j\x1bb\x11C\xbd\xd9\xc0\x9d\xbd\x07w\x1e\xdc\xfb~\xef\xc1]\x9ca\x19\x99\xf8&|\xa3o\x85MZ\x93\x92\xcf\x04>\"\xcax#\x90\xb7Q\xf1\xe1\x06\x9c?l\xc5\xf2\xeb\xf9\x9c\x0dm|v\x90\xda<\x19jP\x16\x9d\xde\x92Q\x91\x14\x1e\x0da'\xae\x14,\x1cJ\xd0\xd5_&\xf0xXW\xc0\x9a\x06v\xd4\x96\xbd\xf1\x83\x18\xb9\xe3\x86}\xed\xda^\xbd\xaa\x8f\xa1\xbd\x0f\x0e\x80\xab\xc5i\xc4\x986\x97/\xb6\xba\xbf l\x03\x1a\xc5j\xb1\xb4\x8cC\x92\xe5\xe2\x99\xbc`\xac\xde\n\x02\xbf\x9f6\xabT\x83pd\xd6\x9c\x07\xef`\x08{\xcd\xdbo\x9c\xb3\xb6\xf3M\x9d\xa4\xcd6^\xf1\x93N\xbe\xa09\xda\x9e\xc1\x10\xde0\x1cye:\x02\xbe\x1a\x08\xf6<\xca0\xbb\x8833\xfe\\\xae\x94!\x99\xa7\xb4Z\x94\x0b\xc5\xb6\xe0\xa0\xb2l#\xf6\xbd\x85\x8a\xc2\x01\xa4\xc5\x19\x12\x89\xb2\xc0\xd6\xd3\xd0\xe0\x078Mb\xd3\x89\xebH\xab?\xda\xa8\x82uH\x1c\xfd\xac\xe3j\xad\xdcc\x18\xd4\x0fv\xees\xebWW6\xf6\x8b\x9d1\x00S\xd5h\x8a8\xe3\xd4\xc5\xefv5\xe0\xaf\xda\xf4\x1d\x05-\xe7Un\xb5\xc5\x96\xf5\xdd\xfdj\xef\x8e3(o\x90\xd6\x8e\xde`\xedR:ze\xcaM\xa4\x9d\xbb\x92\xb7\xdaiD\xbf8\xc0X\x13\xcc,\xb8\x14\xa7.^Z\xbb(\x92\x01\xa8G\x8e\xdc\x8e \xcf\x95-\x85\xe8>M0]\x83\xb5\x80\xb5\xbc$P\xd1y\xbd\x12\x167\xac\xd5\xe6!\xe7@\xa85\xc3\xfb\x96\xa9^\xd8\xe1\xc5\n3\xd3q\x06\x0d\x92\x14\")\x15 5K2\xe3[.\x0b\xd8\xd3\xcf(\xdd\xf0G\xfb\xe8.o\xeaV\xbb\x8a\xecj\xa6\x083\xc0\xfd\xc5\xb7\xc1\xbdO\x13\x94\xc5$\xc4\xc5\"\x84\xcd\xb5\xa0\x98\x9f\xfd0\xa6\xe9\xbax\x99\xba\x8e\xf2\xc6\xb7\x8dR30\xa2\x0e\x84\x8dSH\x91\xf2V\xe8<\xb6\x1f\xadc\xf3\xbe}pr4h\xe0\"\x14\xef\xd7F\xa6\xfe\xfa\xaa\xa8\xaa\xa8&\x1f\x81e\xb0\xbd\xd1\x918\xa0\xc75\x05t\x00_\xfb/\x0f\x7f\x7f\x0fCx\xca\xfe\xfe\xe5\xc9\xab\x8f\x87\xec\xd7\xcf\xec\xd7\xe1\x9b\x0f\xef\x8e\xf0\xe7\xbb\xa0\xd2\x7f\x14g+\x9e\xed\xbc6\xaa$O\xab\x99\xb9m\xf4\x85\x1d\xf0\xe6\xdc\x0bJ\xcb\xa3g\xe3\x0em\xd6\x1b\"\xdeK\xae\xb7x\xd9Of\x8e\xed\xbc\xf4\n'\x92\xc6\xc0^V\xa7L\xbe8\xb6\xa9\x1b\xdb\xcb\xab/*\x82\xef\xf8\xb84\x8e\xb2\x91\xfc\xbb\x17@\xef\xb2i\xcfQ\xfb\x99\x84\x939yG\xb2\x962\xc7JW[\xbc/\xfc\x10d\xc5\xafB\xd6\xfb\x18\xe3\x83)\x17\x06\x957\x87\xfc\xc5\x12\xeb\xcb\x8a\x0f\xa2\xfc\x99\x14\x1c\xcb\x8f\xc4\xd9\"^\xb0M\xa3\xe8\xdf%\x86HLdB\xcb\x82d\xbc\x02\xa8K\x0f\x89S\x00\xbe\xe8b\xd6\xda\x05\xf1^\x04\xf0\xd2\x0f\xe0Ee\xf1%\xbdu\\\x13=\xa6\xdf\xe0-\xdfp\xc7\xf4\x1b\x16L\xbfQ\x19`II\x1d\x9b\xd6\x0d\xf1\xc65#\xfc\x88!\xfc\xb8\x89\xf07\xae\x19S\xea\xb5\xdd\xf5=|\x13\xa64\xbb \xde\x8f|=\x7ft_\xcf\x1f-\xeb\xf9c\x8dr\xd1o[\xcb\x97\xfd(\xe3-D\x94\xfd\x92\xda[\x86\xdeB]\xcb\xc6\xaf(ro4\xb5\xb7?\x05\xf0\xcf\x00~\x0b\xe0\x1fM\xa5\xe9\xfb\xc3\x7f\xa0\xc2\xd4$9Rj\x11\x1d\x8fCQ+\x83\xd6\x88M\x17\xf6\x95\x18z\x90\xfc\xa50.}&\xebL\xcbC\xf2\x91$\xb26\x88\x1c\xca\xf1gQ\x0b\xab:4\xd2eh\xb1u\xf2Q\xa9\x9f7\xcc\x9f{\x16:+\xe8\xd2\xf6\xee\x84\xe1,\xa8\xdd{*\x0e\x83zm\x1fCG\x91\xa1#y\x16\x95\x06\x8c\x7f8\x1aX\x90\x1b36\xf8\x13k\xcd\xfbI\xe8Z)\xf5F\xe3Ff\x16}\xbby\x0brh\xd2\xe0\x88.\xa8\xdf\xe4\x9a\xbf\x94o\xa4\xfa7~(\xdf\x88\xf5oh\xa5\x9c\x83R\xc8)TOf\xcf\xbe\xabK:\xa3\xcf\x01\x9c\x8dAd\x8a\xed \xf1t\x92Y\xc3\x16\xa0gza\xee\xdb\xa7\xc7\x05\xb9k\x9aEfG\xf2_j\xd8\xa2A\x0f\x0d>\x14\xab\xeb4\x04v\xc29\xa9\xcb\xa8`\xcd\xf4@\x8dL\"xa\xe5H\xd8\x01QZ6\x06\x01\x864\xef>\x84\x1c\x1e\x0d!y\x08\xf9\xf6\xb6\xa9\x11\x10\xe3\x08\xd1S8f\xa2\x15\xec@\xced+\x83\x7f\x15\xc8\xc5\xe6z=\xe2\x85\xa3\xc18@\xc5]8\xda\x1d\xb3/\x03P\x02\xdas\xd8\x86\xa6\x12\x0e\x1a\xe2\x97\xbc\xe4g\x8d\x87\x96\x04s\x0dV\x99g\x83tZ\xa6\xd9\x9f\xbcL\xda\x152B\x96\xaf\x9c\x0d0\x0c\x1b\xbfzV\x96B^\xd2\xf9\xc3}a%\xf0\xb7\xb7\xe11:W\x9b\x1b\x077u\xa7\xbc\x8cjOy]\xc2>\xc7\xcc\xb9P\x1f\xa9i8s\xfbp\xa4E\xbe\xe2w5\x94r}\x8e\xf4z\xa8\xe9\x93j\xbe,\x03\xb8\x05\xbb\x85?\x8b\xf0{\xf1\x03\x89\xce\xf2C\xdb\xc1\xf6\xcfbh\xff\xd4#\xce?\x85\xcd\xa0e\xab\x99\xa0u\xda\x02-\xaa\xaa \xb8\x8a\xc0\xd1WhIm\xceB\xfa\xa5X\xd6\x96BiC\xbf\x1a\xa7\xd4\x13\xaeV\x01\xf4\x9e\xf2(\xde\x8c\x92\x15\x84\xf0.\x8cO \x9c\xaca\x17\x83\x1eAX'w\x83\xea*\xc9\xba#\xb8V~\xa0$\x01\xe0\x9eo\xa2\x1a#.ax\x92\xa1\xeb!\x81G\x82cco\xef\xc4\xd2\x84s\x8c\xc5\"T\xbd\x1f\x89\xa7\x8aj\xf3\x18\x87\x86\x83U\xb1FE\x0f\xfc{B\xa2\x85\xe7\x11\xd8a\x04\xf8\x16\xc4L\xb4\xf2\x99l\xde\x0dw~+`\xf9\x9b\x1ew~\xfb6\xdc9\xd6\xeb\x129\xbe(*\xa5'\xa2\xfaa\xdd2ah\xf6\x84\xda\xdcL\xcf\xadO/\xc4S\xf5\xa1b\xc6\x1a\xfdc,\n\x01\x11\x8f\xd2\x00n\xb0\x95S\xe3\x1eN\x89SIW\xc9\xb5\xb3U`\xe4\x91\xdb\xb4KM\xfb\xe8\xad4g\xf8c]\x05\xf3J\x9f\x9dL2\x15\x7fY\xa5G\xe1![Q-\x95\x1e\xb2CH\xb9\x8b\xac\x11W\x84\x8a\x88z\xf1\x88Q\xae\x14v\xd0\xa3+\x1a\xa3\xf0\xc7:*wf\xc4P\xd1H\xb5\x1bu\x1d\xb4\x93u\xb3\x0e\xe9&\xaa\x9dBc\xf2\xfa\x89\xea56\xdd\xb45\x05\x10\x1e\xa3\xfa\xc3\xc6\x819i\\\xac\xda\x16\xaei\xa1\\\x02/Wf{\x9b\xad\xcd\xf6\xb6C\x14 CuB\x03x\xc1\xe8\xd6\xd5Q\xbd\xee\xe5\xaaC}\xae\x1f\x1eQ-\xcaW\xfa\x9e\x87\xee\xf1lJ\xd3\xf5(wM}\xa2\xeb\xdcX\xbcS\xbe\xb3JSU \xd8ju\xa7%|\xa7%l\xa7E\x0f!1+q\xcfDY\xbc\x14\x173\x82\x1dH`\x1f\x12\x83\x9e\xaf\xb63\xf31V!\xae\xee\xc6D\xab\xb45\n\xa3\xcd\x14\n\xd7\xb5=\x05\xb8\x8c\xfbS\x01\xa1qw\xa6\xad{8\xb9\x8e=\xdcm\x15$\xe4P\xd3\x1a\xfdu{>g{>w\xdb\xe3\xca\"\x8e\xa6\xe5!\x17\x8bC.\xd6\xee\x8b\xc2[\xc5a\xad\x19*\x96\x121\xaeeEhR\x84\x0c\x03\xf7,\xb1\xe5w\xafj\x96\xb5\xd4\xb02\xe8$\xbex\xb1A\x06-vq\xf4\x10\xb6\xbc\x08O\x05\xb5*#(\xb9\xbc\xbdHT]\x84t{[\xec*]\xfdR1\xe5F\x8e -LK}\xf5\xb5\x025I;C\xd5\xa0\xce\xf9\xa2j\x89\xf9v\xf9hh\xd6\xb0\x02\xdd\xb7\x1aQ\xd6\xa1E\xcb\x81\x8b\xc4\x9d\xd1q\x0f\xe0\xd2\x08\x15\x9e\xd3F\xf0R\x81\xf2\xe9\x7f\x01\xcaW\xea\xc8\x17$\xb0\x08!\xe0\xb6\xaa\xa6\x83\x80z\xa0\x14\xc6\xa8\x87\x0e\xcc[4J\xc6\x01#T\x8dC\xc206\xb6KbEK\xc4w\x89\xb1\xf2\xbc\xa4\x9b\xb1M\x9b\x84&\xb6Q2\xe6\xe1\x90\xc5\xd8\xf2\xea\xc0NR\x12~n.\xa8 \xdb\x1a\xc7\x96vy\xffc\xbb\xaf\xb6\xb0F\x82\xa6[l=\x10\xafc\xef\xe1J\xc0\xe3\xf2XmS\x18\xb6oT\x90p\xe3En\x8b\x8dkQ,\xf2\xa0<\xb1\x87\xb5\xafY\xad\xcb\x92\xfdMG\xee\x0c\xefZ\xd0\x805\xbd\xba\x8b]M\xd0\x86\x03\xe8\xbd#+\x12R\x18\x8d{\xb0_\xfe\xe2^\x10\x8aZh\x1bz\xe5=\xfc\x96\xdd\xa1\xd1\x92d\xd0t:^_\x9d)\xd71\xe1|\x08\x1a\x06\xbc\xd2\x8f\xac\xf4\xe3\xca\x85O\xa9\xaa\xf8jFe\xd5\x9a\xc7\x94\x05.\x13\xa9\xec\x1f\x06*#\xca+1{|\xaa\"U\xd2\xba6\xb2\xd7\xa2\xba\xe4\x0e\x0f\xa6\xab3\n\xf5\x91\xa6\xe4\x8c\xa4Y\x177\xed\x16\xb8N\xc9\xc5\xdb\xd9\xd5\xc1\n\x07\xa81\xdc\x19X\xbbY\x84\x19=\xba\x86\xaeJ\x0cm\xed\xf2\xea\xc2\xd4\xeeC\x88\xe1\x91\xb2\xc4\x10;i\"*\xc3\x8d\xeb'ZlUB\xc4Ns\xe9.\xe5tbU\xbb\x11k\xc9f\xc2#\x88%\xc5)Y\xa0X@\xc27\xd6\xd9\x83\xeb\x12?\x1c(l\x05\x9a\xc2H\xe9\x88\x87\xb4\xaaz\x87\x83&f*S=k\xda\xfb\x19}_\n\xfa\xbe\xbcf\xfa\x8e*cI\xde\xf9\x0f\x85\xbas\xed\xee6\xf4\xfa\xfd~y\x97\xc4S\xd8\x06O\x08\x15\xf3B\xcd{\x00=8YW>'+\xcc{\x84I\xe74'\xc1\xf2zO\x029\xdcR\x17 \xdfU\x87\xd28#\x96W:#$\xe7\xe0Q\xd8Q\xfb\xf6\xe1\x96\xd2\x9fq\x7f`\x80\xf4.7\xc8+d\x82\xdf`k\x84:\xf1\xd9\"\xd1\xd8\x1ejCv>wj\x87J\xd1\xa9r\xb8\xa0K\x01\x9e!\xe5\xd3\x80\xdb\n\xf0\x8c)\xef\xfa\xf0hX\xf8\x96.\xa9\xb7\x1b\xc0\xae/\x8e\xa7\xa5@\xeeSB=\xd5* M\x06\xec>\xd1\xdcG\x905\xcf\xae\xe5U\x0e\x9b\xb3\"\xaa\xb2\xb2B\x0d\x85/\x18\x031.\xc3\x1c\xd4r\x07V\x87\x03\xe1Z\x89N\x96\xece\xeeSa\x19((x\xba\x0b\x1b\x93s\x14\x1e\xa1qY\x8d\xd3\x8b\xe1_C5G\xd1w@\xfd\x87\x0c1\x94\x9b\x0f}\xc0\xd7(\xdcR\xdf\xb5\x12\xdcC\xea9\xa5J\x8f\xea%]\x145b\x99\x9a\xffg\xaax\x99\xeb1\x0d\x94UxEG\xd4\x9e(\xb7\xea\xb1\xf2\x96ao\x00o8\xac\xdf\x89\x9c\x19\x14\xd3\xe1\xc0+\x9e\xe8\x1c\x9f3*\x8e\x8d\xb3\x83\xef*Y\x16`\x9fw\xd6 \xc7\xe7a6\x7f\x9aLU\xc8\xc8[:\xe5bT\xaf\nV~\xe8\x08B3\xe3\xf9\x9a\xd6\\M\x11~G\xdccM\xadPji\xa3\xfe5\x1d=\xa5c\xa7/\xb7>\x1b\xc7\x0d\xa6\xc6\xfb\xa2\xea\xc1\xfa(;\x8c\xf3\xa5\x08\xc0Bw8\xdd\x13\xa7\xb1\x98:k\x07\xaf\xfa\xb5p\x98\x8c\x93)\xf9\xb0^\x11@\xd2\x9e\x9dG\xbc\xfeYq\xbf\xad)vM\xc2\x8c\xc0`\xbf\xf5=Ph\x7f?\x8f\xa3/99zf\x9e\xa3\xbc\xb0\xf9\x07\x1d\x9b\x9f&\x13\x0c\x18>\\\x10\xf6\x0f\x9fl\xedf1\x06k\xd3z\xa56\x88-\xa5\xac\x96\xf6=\xfd\xd7l\xb9\xb6\xb7?\xd0@=\xfan\xc2\x07\xbe\xf7?\xe0\xde\xb7\x84\x88\xbc\xa6>\xc3\xfa\x8c\x18=\x1c\xc1\xc1\xd1\xb5\x8aB\x7f\xc8\xfa\xc8C\xfc\x81.\xcfu\x8f\xc1\xde\x9b$\xde!<\x95q\x19H\x98A\x98\x12,\xfa\x86\xd9\xb5\xc9\x14\xc2\x0c>\x93u\xd67\xd5=\x90\xdd\xb3\x0d%\xa2\x8dy9\x89\xd2#$\x80\xa7\xd4\x14W\"/R\xec\x9b}\xd8\xb2\x04x\xb1k\x92\xc4\xb3\xe84w|\xfb<\x8d\xa8\xdb\x9b\x82O\xd7/>\x80\xb9\xa4\x1e\xa8\xe5\x0d+N\xf5\xddH\x86`\x93\x95H\x12\x85\x83\xd7}\xe0\x1b\x1b\xb2\xab\xdb\xd4K\x95\xb5\xdd{\xee\x87\xab\xd5b-\xd8xCD\xbfz]\x06\x162\xc9\xce\xc0\x16\xc8\xb6\x13\xc1\x8aSzI\xf2\x1ax\xff1F\x08\xd1\x042B!\x84\x98\xed\x83\x12rr\x8c\x90\xc4bOXQ\x9f]T\xce\xc1<\xfb\x0e\xf4\xc4z\xeaw:\xed\xa5\xf2\xb5 k\x8caP2\xdah\xf3\x01\xd4\xa0\xc5\xcb)\xb3&y\xfddT\x93\x96\xa5y\x18\xf7@\xa6}G/\xd2\xb7\x06\xde\xbeP\xc7\x10\xce(\xa9\x16\niiG\x03\x05\xbep{\x00\xdf\xf1T\x85\xfd\xc9\x829\xf3Ld\x15\x16\xd6\x97)\xdc\xbdu\x9d\x11\xfcW6_r\x85\xa7\x92\x01\xeau\xb82\xa6<\xfb\xfa\x8d\x96\xc5\xe34IJ\xcd,\xfb\x81\xa2s\x11K\xc3\xf36\xf9:\x93b\xa5\xeb\xacS\xd7\xffP\x93B\xd9\xe7\x94\x11z\x14wh\x1a'\x92\xaf\xa6!%G\xf8\xf22h?c\xcd\xdc\x92}p)Y&g\xed\x92\xb6f\xd6K{\xc3S\xb2 l\x02\xaeM7f\xed:\xe5e\xd7)\xf3N\xea\x0bbO\x1c\xcdE\xc8F\x89\xcb\x03\xe1\n\xe2K\xe3L1\x81\x11\x1d\x8bF\x1d\xc6\xd2D\x0f\xc3h0\xd8\x15\x9d\"E,&Gq\x8b\x8flA\xa2]\x12I\x9c\x898P.\x80-\xcd:\xd1\xbc\xd5\x17\x8f\x91\xbb\\\xf8\xe1\x99\x89\xe2\x99H\x19\x93`\xf0Hk\xc5\xd8\x0c\x86\x10y\xb6\xb2\xdcb\xb92\xbe\\\xc2Y\xb7\x19C\x06F\xa9\xe3\x94z \x03\xb2\xc8\x1b\x9c\x11\x1a@/\x8ay\xb5\xfb\xcfd\xfd3V\x883Cf\x82%\x80-\x1e\xa8\xec\xa5\x99\x98\xf2\x92M\x19\xa9\xd5\x84\xed'\xf3\x07X\xa0\xd4\x9b\x95\x0bhU\x94r\xd6e&f\xcf\x7f-\xd9/\xb1\xdb\xbd \xc3W/)y\x19\xe2\xe3\xd91 `\xa1\xe1\x01\xc4\x9e\x8fc\xd4\xe9\x1a\"\x1eE\xdfi\xd1\x9b\xe0\x9a\xea\x96\xd9\xfa\x0e\x98,Hh-J\xa44\xdet\x8b\xa1\xdc\x1fB\x1c8\xc9yL\xd2\xa3gp BaE\x0c\xe3n\xa0\x9e\x14CQ\xb4S|\x83\xc1\xfb\xc3\xf2\xac\xe0w\xc3\x05\x15\xf5N\xb6\xc4M_pw\xd6\xc9,Iz\xda\xaat\x90\x90\"\x02\xae\xb2ks>\xc0f\x1f\xbfF\xd5\x92c\xb6\xf3\xa4\xe8\x08\xfd\x97\xea|\xd2\xa0\xe9\xc8\xd1\xec\xaeJ\xa0\xec\x86pM\x0fFl\xa9\xd2L\x12 \x84\x03\x07\xad\xaf\xf8\xde \xf0\xf3e8\x90\x7fI\x1d\x0d\x12\xd5}\x88Gj4^\xb3\xa8m\xcb\xf1\x81M>#\x18,\xdbi\x9d#\xd2m\x8dY\x1fN\xeb|%\xd0\x17\xc3J\x88\x87b\x85\xe3\x88\xfe7\xa2\x02\xae\xd6\x81\xfa\xebzQ\"KR\xea\xca\xe7\x1c\x11\xef\x17R\x98\xfd\xdb\xdb\xfda\xdd\x81uT\x1b'\xed\xedWd\xa0\xd6 \x14\xb2\x16[\xa90{\xcdu\x11:\x06@.)\"\x16\xe9\x9f\x87\xd9\x13NO=\x1f\x8f\xa1\xe3c\x12gyJ\xde2z\xedU\x89\xb7d\xa5\xac\x03/zw\xdc\x83\x8d\xf3\xa1zn\xa8\xa3a\xa2\xd8{;\xd8\xc2\xecHjb\xba\xf5\xaf\xf6\xd3\xb22\x05\xc8\xba\xf5 \xce-k\xdb\xdd\x1c\x9c\xa4F\x84\x9c\xc3\x0dw\x99\xa7\x93\x17\xda\xb7:1+\x87{\xe1m\x83r`3\xb3H\x0b\x11\xe1\xc1v\x1e\xc1\x043\x043\xca\xe8l\xee\x01/\xfb\xd4\x02\x01e\xb5[\xf7\x96\x9cI\xc9\xe0\xe8\xb0\x15\x0e\xe0\x9f\xb4dmT\xb6&(\xf3: K\x83\x1c^\xad!%\xf7\x83\xca\xe0\x0c\x04\x83\xa3\x99N\x941\xc9}\x08\xcf5\x9eC\x1fi\x00?\xd0f2\xe0\xd7O~6TO\xfb\xc2\xdeV\x81dR\x0f\xfenN\xfc\x81\xc3oNH$*j\x18\x1f\x8c5>\xac @\x0c\x9d\x9cDt\x89\xe0\x90\x90\x8f\x13\xee\x82\x1c;\xf5\xf9\xcbU\xfa\x9c$yL\xaf\xdc\xe5\xcb\xabt\xf9\x99\xac\x7f\xe4L1i@\xd7\xad\xdb\x17\xd7\xd7\xed\xda\xb9\xd3\x1b\xed\x9d\x1eS^j\xb4\xdc9E\x84M\\\xfa6\x87\x93\xcf\xc8\xbc\x14\x14\xe5'\xea\x89_n\xda\xd0\x1f[S<\xf2\nH\xa6}\xac\x0b\x025!\x0f\xad\xa9,$fGAA}\x10u\xa9FM\xd1\xd4Q\xf8X\xe4\x0c9\x84\x08w\x9bN_a\xc0G\x11%^\xe8\x97\xf8\x82\x06\x10Zy\x15&Qq\x89\xcd\xd3~\xba\xcf\x10Q\xac'e\xfc\xc8\x85\x17\xfa\x01\\x\x0cU\x18\xc4_\xc8\x1c\xae#\xf6\x99k:wB\xec;\xbeVy6\xf74\x9eEF\xf2\x92K\xa0En@\x8e\xac@.v=zm\x95j\x95\x9b7\x01\xb3\xb0V\xd4+<'c\x91\xd8\x97o\x7f7\xce<\xb1\xef\xeeR\x9433\x15\x002\\\x0cu\xf8Ue\x1a\x8e\xb7\x92\x8c\xba\xf2\x9c\xab\x84\xcc\x9ax<\xb9\x8a\xce\xadjx\x9e\x8d2\xf2\x85\x1e>jY9\x13@r\x97e\xe1\xdb\x1c-Cq\x7f\x16\xb1\x93\xc1\x01\xfd\x8a\x8f\xcb\xc4\xb9\xcdA\xfa\xbeb\xedb\x07\xb2\x9af\x17\xe9jy\x8am\x18\xa9\xc0\x94\x87\xca7W7\xb5\xa7\"\x1a\xaa\xf8\xc4\xb6\xe2\x80&pq\x1e\xa5U\xabi\xab\xf7pE\xfe^\x8a\x1a\xa3\x08x\xec\xd2\xf8\xad\xc6e\x02o\xabA0\xa6\xa5\x93\x17\x95n\x19\x86\xf4\xb1\x97\xd5z\xd2\x05A\xc3\xb2\xd2\xf1(\x1a\x17\x0e!\x9a\x81bf\xf2\xca\xd1\xe7\xc5\xa3]G\x89#l9iA\x84\x86x\xf7\xef\xde\x7f\xf0\xe0\xf6\x9d\xbb\x0fx,\xcf\xce\x10\x03ax\x1c\xcc\x9d\xdb\x83{w\xef~\x7f\xef\xae\xef3f\x0f\x1f\xec\xc1M(\xbeQ\xee\xdfa'\xd3\xde\xdd\xbd{w\xee\x0en\xdf\x0d\x80\xc2\xb6h\xea~\x00\x83\xbd\xefy\xf3\xf2\xde\xe0\x9e\xdb42\xe2(\x85\xa4\x02\xc5\x0fm\x15E\xa3\x11\x19\x0b\x01\xa3\xd6\xbb\xfa\xeb\x0b\xba\xba\x08\xde\xec\x0b\x15\xe6p\x18\xb2\xbf\xb9\x15.(\xffD\x9dz\xf1\xd2Q\x1c\xc0\xef-N\x11\xe6\xb9T\x0eCUz\x17\xc7\"g.\xa2\xf2X\x84G\x90\xf3\xd3\xd1HH\xa7\x88\x9e\xd1(\x193\xd4)s-\xb2\x1b\x03\xe7R\xe6\xb5Y\x19\xcd\xf0*\x1fi\x9d!\x16\x1b\xe1;6\xc0\xd3\xb9:\xdd \x9f\xee\x0c\xcfc9\xdd <\x02\x8cm\xda\x9abB\xe0l4\xc1I=\x84\xc9\xf6\xb6\x81![\xc0\x90\x7f\xa7\x17\xc8\x16p\xc0\x9b\x19\x8cq0\x11\xec3\xeeWQN\xea\xbf\xe3|\xb0\x17\xa2g\xd4\x02]\xc9.\xbc\x84IQaIH\xb3\x96\xec8\x18\xc4\x81\x0e~[!\xfb\x7f\xe1\x9a\xf0x\x08\x13]\x98\x8a\x15y\xe4\xc5\xa5Z\xe9\xb1\xf8\xdebp\xaf\xa0\x9b\xe0\xfah\x00\xe8\x88\x1a\xc0\x88u4\xf6+\x1c\x19q\xe1\xc8\xe4%\x9d\x0d\xc8\xc8\x94\x00O^\x11b\xb5 \xff\xb4\"\xa2\xe6\xa8h\xc9\x8d\xd5?@\xcbE\xc9K\"\xbb\x9e6\xb3\xae2\xabQ\x9eMa\x05\":LQ\xf0J9\xd3\xd81\x93\xf7V\x0c\xb7\x90\"em6\xff\x03\xe4\xaf'\xc2\xf6\xbf\x03\x038\x80y\x7f\x95\xf0J\x10\xf3\xd1\x84Q\xa3\xc6\x8d\x11\x1b9\xe3\xc7\xe7\x9c\xc1\xe4\xbf\xfd\x00{\xf6j\xda\xbfyi\n\x97\x02s\x00\xf36\x96\xf42\x80_\xafL\xce\xb4\xd1e\x88]\x86\xcd\x8aB=\x13W<\xafZ?\x9cG~R\x94}\x0c\x9a\x91D\xd2\x10\xae\xe95\x126\xd60\x93snr\xee\xae\x08\xcdF\xe5\xec($\xfc\x11fF\x1e\xf38..#\x11\x1d;Q\x07\xcf\x95\xe9b%3\xb4L\x00\xfd\x84z\xa9 T\x8a\x80H\x04\xcb\x13#\x90\x88E\xaa\xcc$|C\xfd\xf3I\x15\x86\xfa\x97f\x18S\xb95\x04o\x027A\x87\xdaH\xd7\x90PGue\x8e\x96\xa0J:\x1d\x12\xde$\x02_\xdf\xf9J\x8e\x10\x97K\xff\x0e\x1a\xdd\xe1\x00V\xa3\xc5\x18Z\n\xb1sE\xd9\x9c\x9b\xc5\xf8BW\xd7J?;\x1e%>w8(8\x1c0\x94|\xa5\x90\xf7\x99\x95\xbc[\xdc\xbc*\x15\xbf\x04C\xc0\xf63\xaf7\xb3\xf6\x03\xc4\x8c\xdd\x87\x82\xd5\x8f\x1fB\x88i~\x18n\x0ca\xe0C>\n\xc7\x88\x067Q\xb3@F\xc9\xf6\xf6\xd8R\xb3\x0e\x14\xa1t\x94\x8e\xb9\x8a\x8b\xf5\xc8M\"\x98\xe3A\x1f\xcc\xcf\x1e\xaf\x02\x98\x04\x10\x0605@R\x9c\xe7\xec\xffj\xb9z\xb5H\x7f\x93*\x11\xb4x\xb2\x04\xb6\"\x12\x0df\x81c\\\xeaWxS^q\x0eRQp.W\x88?{k\xe03V4\x1fc\x9ck\x0e\xdb\xc6\xd4\xb8\xd0~xs\xa8iA\xd6\xc2!\x15\x1c\xb6\x84\x9a1M \x14\nu\x84\xda\xb6@\xaa\xa8\x84\\!P\xb8\x80.\xa9\x80\x8e\xab\xd6\x10tb\xcf\x86\xf0\x08\"\xdc\xb1>\xbb%h\xbb\x97\xf0-\x1b\xf3\xd7w\x06\xa8\x9d\xe5\xf7\xe8(\x84m\x97rn\x86\xc2\x1f*\xee\x19\x8f\xcc\xe3\x82\x9d(\xac\xa8'5\x93\xe6y\x95\xbb\xe0&\xda\x93\x00\xce\x1b\xe7\xe5/\x7f-;aa$Z\xf8\x08\xce\x10Df\x11)\x81\x03Ht,\x82\xceo\xf2\x97\xffel\x82\x94\xcd\xb4/L\x1cNa\xc6&LF\xa1\x81Lg<\xf8\xc6\x911\xa0\xc4\x9bu=\xa2\x85#\xadC\x0f\x05O\x81\xf6z\xc3\xb1\xd2.\xc3\xed\xec\xac\xe0\x11,\xae,\xb7U\x08\xecn\xa0?\xe0cy\xc0s\xa1y\xc0%\xe5R,c\x14d\"\xce\xfc\x0c\x1e=\xc2#\xbf]L\x9b\xa1\x98\xa6[\xac\xca\x9beT0\x1e\xb3!\xfe\x89\xb4\xd1\x8b`3d\xc2T\xce\xf9 \x06yc[\xad\xf2ZIB\"-k\x01\x92\xbd\x98 \x87\x11\x1a\xcd\x8c\xab\xedm\xfd\x9a\xcf\xbb\x9e\xf2\x8cS\xcc\x88\xc7\x99\x99\x05\x93\x9c\x8cta^\x90K\xe9\x00\xb2\xaaQ\xcbi\x95ZrNj\xc5\x98\xa4:\xd9xyej\xf9\xdf\xacKz\xf9\x9f#\x86\x82\xae\xe9wy\\\xe6Z\x14\x86\xbab\x8e\xa1\x92\xc0\x8f+\x7f\xb8\xbe'&\x8a_\x1d\x0eZH\xe1\x9a1\x14K\xf2\xff }WXr\xee\xb3\x8a\xd5\xf4E\x99\x97P\xc0\x92M\x80\xb1\xee\x13\x93\xf1\xb4\xb3\xa6\xa5]\xcb\xf2\x1f\xd4\xb0\xbc\xd4\x00`\xde\xd8\xe0/\xae\xbc\xc1\xa5\x18\xc3\xa3B\x0b\x9f+\x86 2\xa2\x8e\xdf\x18\x8cu\x0c\xc9\x8b\xeb\xd9\x835U\xaev\x99\x90\xe4!\x06W\x87i\\./\xc3\xea\x19\x05\x12(\xf3\x08\xfd\xc6F\x0ce\xc0\n\xc3H\xd8\x87\x0c-\x01Z4\xaa\xac\x1a\xb68,\xca\x10\x89e\xd3\xe1\xadXv\xde\xa5f\xd7#\xd1)w~c\x91+\xba\xf3\xd2\xb9\xf6\xa5\xfeve\x0d\xac\xa4=n\xd0\x91\x94\xd3\x91\xa8V\xb6\xe8!\xa4\xa2\x84L\xea\x94\"9.\xea\x97\xa0\xe7\xc1X\xadwY\x9f\xdc\xaf\xfaY\xfcrm\x93\xe3L\xa6\xdb\xd4\x0c\xbcN!|\xd5\xe6\xa5\xe7w\x18(\x12(\xb3\xcf$\xfdJ9\x06\x13,@\xa7=}qE0H\x8a\xac\xa0k\x03\xad\x88w\x83\x06\xf0\xd5\x0f\xe0\x86\xdaKL.ZS;\x14P\xa6\x12\xca\xe8_\x19\x94A\x02\xdc\x99\xf2!\xd8\x8b6\x88\xfa\x13\x04\x17\xc9\xac\x0e\xc7\xd4\x98<\x0b\xaa\x8e#\x03)f\x8b\x89Z8\xd6\xa8\xa8\xadZ\n\xe1\xdcg3\xd5AI^\x97en\x9bT\xee\x96\xb6n\xb0\xbe\x99\xa8b!>Q\xf0\xce\xd7v\x1f\x91l\xc4\xc1'\xddS\x0f\xb0\xcc\x1e\xafy\xd6:6\xb5KD\xfbj\x87v\x95FR~f\x19\x83]\xd1\x91\xb4I\x0b\xf8\x92\\\xa6\n\x00\xe4]\xbb\x0cQ\xc3/\x18\xc2O\xd4K\x8c\xf6s\xb0\x8a\x0b\x93$\xa6Q\xdc\xa9\xf8C\xb3\x7f\xe5W\x9f\xfb\xcc\xb6\xecj(\xb7\xa7ic\xb4\xe6J5\xe6I\xad\x11\x90*0\xd9*c\x1e\xea5\xdc\x82;\xcd\x96g\xf2\xd9^\xf3\xd9\xa2\xf8\xce\xe4\xb9\xbf2x\x0c\x9c\x89\xd8\xa1\x0bc~=\x87<\x96\x9a\x88Z\xf6\xe5\x9cxJ\xcaI\x8d\xf0-O\x82\xc8\xa3\x96\x0c\xa3\xb1\xbd\xc6\x03\x1fL*t@\xde3~\\\xa7\xf0\x98g\x8dN\xe1\x11\xac\xe1\x00\xce\x89\xb7\x8b\x0c\xcfY \xe2L\xb1\x10\x04\xf1\xe2>M\xb8\xfc\xedcYZ\xd2\xd9-\x06\xfdD\xdeG_ \xf6\xacI\x03\xd2\xa6\xe9-4\xb5-\xfe&:/\x127O\x8b\xb9\xddaD\xc9\x032%-y@\xd8ArN\x19\x9bL\x1c\xf2\x80(\xc2\x87g\x8e\xb1\xe49\xbc\xc4\x11\xf7\xad9-^E\x19\x85Q/\x80\xde\xb8\x99\xd4\xa2\xd2\x93cR\x8bH\xd6\x8a/\x93\xe2\xfbEVrZ\xcdJn9M\x99\x00[\xb0\x96\xe8+\x83#O\xd2\xe842y\xb6I\x99\x8b\xf5\x14\xf7y\x99P\n7\xe1T\x13\ni\x02P#\xbbF\x05\x06\xdd\xb2k\xb8\xda/\x10d\x84\x83\x8c\xb3U\x95\xaa\xf9&\xbfo\xf4\x0d|\xac:\xb1\x11x\xa4d\x83\xed\xee\xb2\x06x,<\x82]8\x80\xb7\x82\xc7\xc3m\xb6+\"L\xdfJ\xa7\x04\xb4\x00\xf0gD\x1b]\x06`N\xb0Gp=\xe5b\xea\xdf)\xed9\xc74\x8c\x16v\x86J\xba\xf7\x1b_J\xac\x81\x02\x08\xc5\xcf\x18%0 W\xe1$\xa2kn\x10\x1f\xc2{t\xc2\xabG\x0dpy\x10E\xac\x88\xbf\x14\xd5^\xa2\xfd\xe3\x059#\x8b\xf2]\xf3\"n%\x8e\xe1\x06Q\xfa\xd0Z\xee\x00\xf8\xd8\xd6\xba\xd0\x13\x8e\xc6\xec$\xd3w\x13 \xbf\x0b\xae\x8a\xd4\xf7\"\xaa^\x98)y\x0e\xea(F6\x03\x16\x16\xa9\xcf\x19\xdd\xca+`F\xd8\xc2\x0e\xea8}\x1fG\x83o%\x15P5\xa9\xb2v\xc0\xdcJ\x169@9\x84!\x1c\x96\xb9\xb3\xf4\xf3\xdfJ\xf4*\x95\x8a\xe3\xc4\xeeC\xc8\xb8\x8bi\x86~\x92\x02\x16\xd9\xb8\x10\xbf\x8c\x049B7\x91\xb0\x80\x1e\xa3\xf1~\x00a\x9d\x82ip\xf4\xc9\x8c\x92\xc6\xf1\xde\x8a\xa2^\x15G1\xc8\xf8\x1b0UX?Q\xa8oA\xd8\xc8\x8e\xb0\xfaN\x9cp0\xa9\xe2\xa0\xc9\xa2\x848\x98b\xb2L\x86]*\x185(\x88/Ez\xc8\xa0\xf1\xab#r\xca\xcdbE9\xd1d.z\x13\xca\x8a\x08\x95|\x81\xf0k\xcb\x8bi2&\xca\x0f \xaf\"K\xf3x;%\x01,I\xc0\x98\x06[\x1a\xf5\x13\xf3iU\xf2\xea\xf2\x10\xd7BX(\n\x8b\x93]\xbf\x0c\x80J\xbe\xd4\x165\xc3\x0f}3|*\x89D\x04\xe3\xb0\xeb\xd7&\x06\x95\xb8g6\xb70\x00\xa3\x8d\xb5\xa2\xc7 +\xe5\xac\x0c\x9e&\xf2\x92\xc4$\x17\xfeK\x07\x12\xc1\xf8\xf1\xbe/\xa3\xdc\xf1\xa7\x99G\x05\xe1\x97\x92\x8b\xca\x87\xbb\xe8\x19\xbb\x03\xb9\xfd\x93 F\x9a\xee@n\xe0\x1b\xf1\x95\xc7\xb0F\xdca/\xdb\xec\xa1\x02\x08\xad<\xbc\xbc\"t\x9ce\xd3\x9e\x14\xfb\xe1\xd8Rt\x04\x14\xb5\x04V{\xdc\x99\xc0>\xa3\x9a\xf6OD\xcb\xe8\xd9\x15\x8e\xa8>W\nh\xb7\x1d\x80\x0c\xab\xab\xbb\xe5G\xa89nYV\x11 \xea\xbc\x80\x13$/\xd5\x05L\xe0\xf1c\x88\xec\xdf\xcd0\x00f\x9b\x1d\xeb\xf2\x03\xcb2\xcd\x8a\x05\x9d]\xf3\x82\xe2\xb9\xf6\xd0\xe8`\xa1^l\xed\xb5\x19]tW\xa1\x8b2 }\xf5+\x12E\xf6\x98\xa8\xd3\xa6\x90\xaf_\xa1P\x85\xb6\xbel\xb6\xe3\xcb\x8b\x0dcR\xf3%lCpP\x08&G\xf2\x19\xec\xc3\xa4\x0d\xc9A\x8c<\xe7\xae\xe8\x19f\xde\x8f\xf8\xa1\x940\xd4\x88\xd9\xa9\x1d\xf9f\xb7\x04\xb0N\xc9\xb27\x90.6\x1e\xbb%\x948\xd7&\xfb1\x1d\"a#;\xd7\x99E\xa3\x10J59;\x9b\xd98UU9\xfeTT\xe5\x04oH=y\x8c\xbf\xca\xacGa\xa1$\x8f\xf0\x87\"5&\xfc\x86\xd0\x97\xe7\xfcW5\xb9W\xe8\x04\x8a\x0bb\xd3\xa8\x9d\xa2i\xd0C\xc5\"\xb7\xeb3\xf1\xcd\xd1\x14\xfe\xbe e\x13\x88s\xee\x8f/\x92\xf3\xd8c*(w\x9a\x7f$\x89\x9bT\xcc6>@^\x18\xf1R\xf1\xa5\x88l\x1b\x93\xb3\x9c-\x9c\xdb\xa4F\\G\xa1%c\xce\x8c\x9b\xf8&\x1c\x0e|cHXX5I3~B\xc9\xbcQ\x9ed\xc3\xd0\xc6[t\xccXi}\xd8\xa0iE\xb3\xea\xc8\x8b\xe3\x9f\x96n\x99jWA\x05v\x1c\xf2(\xec4xK8(nJ\x13Y\xae\x8e\xb3\x19\x83`\xc2\x9bC3OW\xa8\xd9\xd0\x1f\xa0\x88\xc1\xa3\x8ag*\x15\x1e\xa8k\xe2\xf1\xfc\\\x82-E\xae\x94\x8d\x8a\x89\x97\x8d\x02P\xfa\x91<1\x8f\xa4\xb0\xa0\xd7l\xbf\xaaeU\xcf\x0f\xf2/\x1fq\x81F\xb2\x82\xb0\x0dg&\xa4\xab\xfarJ&R\xf0\xad\xf8\xf5C\xee\xb7\x80\xae8XXuX\xf80\xf0P\xad\x14=\x19\xd8G;C8\xb3\"^[\x99wcE/k\x92\x1e%\xe8EF\x9d\xf1r\xc7\xea\x13\x19\x7f`(o\xac\x98\xf5\xd5t;\x98\x9f\xc1\xcc\xb6\xb7\xb0\xff\x89\x0b\xfb\x8f1\x1e\xb0m*\xce\x10\x1623bc\x8c\xdc\xf4>\x9a\x8dv\xf1\xefm\x0c\x19c-h<\x16\x18>\xe4\xf5\xfd\x95\xb4\x91\xa9\x9c\xe1\x9e\x12s\xc0\x0d\xbf:N\xa5\x1a/Q\x88\x1e\x13\x15\x99f2\xe8t\x1bfl\xd4\x0f}|.\xf6\xd1\x84\x8dkR\xdd\xf1\x070\x92\xc6\xa3\xc9X\xec*&\xd8\xcd`[f\x1f\xc8\xd8\x9fg\xba\x11q\x99\x90=\x9e\x05\xbc\x8c\xfa\x8c\x1d\x00\xfc\xdf\x04\xff\xb5Md\xc1\xa5\xb1\x04#\x08\xf0\xcf\xd0\x7f\x08+\x06\x11\xec9c\xbb\xc9i\n\x95\xa1\xf3\xf1\xea\xf1n\xde\xe6N2\xc5 \x8aG\x18#\xc1\xc9F\xc8%\xee}60\xbc\xad\xa8\xb70\xba\xd1pda\x905\xff\xe6\xe6M\x8c\x03F\xd1l^SA\xb4\xd0\x8a5F\xb0 !\x9f\xf0\xe9-a\x08\xd9CX\xc2c8c\xff0J\xd0&K\x1c\xc3\x10\x16HA\x96z%\x89\xbcXwkAr\x8e\xc7\xbc\xdf\xf2\xb71\x81\x94\x9e\xbf\x93\x1f\xf2\x9e\xcf\x90v\xc1\x10\xe6-\x94 $\x83/A\xe6\xb1E\xc1(\xf6iEq\x92\"\x1b\x13\xfax\xd6=\x1e\xc2\xca\x87\x9c\x81c\x85\x8b\x86\xfff\xdcmaR8(4\x9a\x12z@\xde\x96.|\xb2pGf\xc2q\xc4(\x15\xe2\x87u\xe5\xc4>\x9cX\x85\x19\xb60'\\\xe8~\xfc\x98\x1d\xe8\xb6\x85a\x038A\xea\xba*_\xf7\xe1$%\xe1g\xf3W'BP\xdb\x1e\x82\xc7\xb7\x94\x0f\xdf\xc1 n\x92\x9d\x022b?\x8dN\xf4\xc2\xad~q'\x1c\xab\x1f\x0b5\"o\xa7\x0e\xd2\x8c\xad\xcc\x0e\xcc\xd8\x12M\xf8~x\xc4\xf7C\xe5\x83b93F \xc4\xfb\x92\xba\xec\x08\xaa\xb2\xa3\x8d\xa2\xec\x9c\x924D\xb5Fy\x9cp\xb6\x9bV\xd8\xf9\xb0\xd4\xed\x00\xc6q\x96\xeeU\x13\xd5\xbdj\xea\xea^\xc5\xc8\xc49\xf1r.\xee`\xa4f=\xba\xd1p\x1c\xff\xe1\x96/2U\xf3EV\"\xe8\xcb,k\xa1=\"\x04\x93b[\x99\xe0 Z\x01M\xe9{&\x1c\xc2\x8f\xc5\x9eMp}E\xa5\xbf\xdc\xcbxJI\xbe\xea\xd7\x9dR2\xe5\xf1h\x93\x0e\xe8\x91\xc0c\xe94y\xf3&O\x10Uz%'HR$\xe4\xebYn\x0c+\xf5\xb9-\xc5\x1cw\xab\xdeE\xa5\x9c\xd4Y\x9f\xb1My\xe6\xd4\xfe\x91\xbd}k\xa1\xc7\xa7\x9ce~M\xca\xfa\x8e\xecVg\xbf\x9b\xb3\xff\xf5\xf5\x1d_\xdb\xa1X\x94\xc2\x9c\xd5\x11\xce\xd4\xe0\x07\xd7\x94|U\xd5\xc3\x91bT1+!\xca\x14\xe1(\x02\xe1\x8f}\xb4\xdb\xf7\x8fy\xea \x9e;|\xc1\xed\xcb\x0e\xb9\xc3\x9d\xe6\xf4\xd4\xaaLXre\xc2\x92\x8d\xeb\x03\xf1xu\x9b\x0b\xe25B\xfd\x0c\xad\xffl\x970\x84i'\x90,\xbd1\xf5R.\xf8\xe0(3x\xfdb=6LIA\x0c\n\xff\xac\xe4\xf8\xd9\xd1\x1a\x9aT C\x9e\xb7I\x8f\xb7\\?\xd1\xa6(\xcc\x05y\x1cr\xedi\xf9s\x0f\xbe\x83D:n\xa2\x8d\x88\x1b+\x9b\xc9O\x0d\"\xac\xbcD\xff\xca|\x84\x8a\x05\xa55\xc3>\xf2\xfb4yI\xd6d\xfa\x9e|\xf1\xfc\xee\x94\x99\x8ev\x0d\\\x83\xdf\x9f-\xa2\x95\xc7:x\x1d\xf2|:\nn2\xa2\x9bVp\xb5\x8a\xb9\xaa\x933:\\\xa0\xf1L\x96}c\xd4%\xc2\xc3\x9c+1\x14\xe7\xde\\Q[0\"\x12J\xd1T\xa3\xbcTb\xcd\x8c\xb6\x99\x12\x01rD\xa5\xd0\x1f\x0d\xc6m\x8b\x9dr\xd5\x1e_G1\n\x9ej\xdd8\x08>?\xe1L\x9fK\x12Z\xb6\x90\x8bB)\xa2\x19#\xc90\xf1=\xa9,\xb4\")\x07\xf7\x0d\x17\x94#\xd2s2\x0c\x8c\x1f\x90\x93s\xcc\xbc\xfc\xae\xc5\xeb\x04\xdd\x95\x14\xaf\x93\xe3<#/\xc9:SJYH\x8a\xd7L\xe2k\xea\xf4\x8d\x81\xa6k{\xec\xde\xfc\xab?\xb7\xf9g\x7fn\xf3_[\xe2\xd8\xfeAl)b\x89:\x02R\xed\x9e\xdd`[\xbc\xcd\xabSi\x8e6\xb1?\xc0b\x8e\xb2xIkCgE\x99d\xf1\x91\xac\x7f\x86\xdeg\xb6\xbe\xdd\x07\x0b\xean\x12\xddx\x06F$\xd0U\x14as\x9a\x87Y\xab\x1b*\xa8\x1dE\xf1d\x91OIV\xafj_\xb4(_\xe8\xd6\xec<4\xb78 's\xf2\x8ed\xf9\x02\xf9\xdf8\x00\xc5\xa3\xf0c\x8c\x8f+e\xbbl\x11L\x85ZO\xebL\x01U\n\xd5\xa8g\xe5\xc8\x18\n\xafC\xf4\xb5\xa7fu\x84\xb1\xd8\x95\xe2\x9d\xdau~\\\xdf\xcb\x0e\x82wmR\xbd\xd4n\xca\xaex\xbbf1]\xb2\xf0nN\xac\xf2\x92v\xcd\xd4Z\xbeV^\xc8\xa5\xd0\xd6:\xb6\xf2*\xf7\x19\xba\xb9\x8ev[\xb2!\x01\x86u\xcaw\x95\x0f\x07\xe3@\xf9\xbb\xe1^X\xbf\xecfQ#\x19\x91\x97)\x8b\xb9\x1b>\xb2\x95\xc2\x15\xfe\x99\xc9L\xb0\x0f?\x1b\x11\xa9r\xd3D{\x9f\xb7s\xba\xad\x148\xad\x13\xdd\xb4;i1\xd3\x80\xb4\x1e\xd2\xe9RT\x99\x97%O\xcd\x85~\x0b\x19{(r\xd0G\x18&\x8c\xbe\xf6\xbc\xc4N\xaa\x15\xedp@V\x02\xe44\xbc\xab\x12\xa0\xa8\xc5\xd9\xa6J\x83R\xaf\x9c\x91\xfcXX\x04MD)j\x99\xb2\x9e(9\xcdY\xc5\xe1w\xe6\x14\xce\xdd)\x8d\x14_\x93V*\x83\x8ev\x82\xc0H\xf9\xd5\xfc\xf6\x99\xf0I\x8b8m\xb0\xbb\xa8\xa0o\x82\x95\x06I\xf9\x9dA+\x0c\x14d\xcb\x91\x02\x85\x0c\xdf\xb4\x0b\x00\x06uB\xa3*\xa2a\x8f\x7fl\xf7\\\xb3o\xf0Xe\xb1\xe2\xfan\x8f\xbb0G6.\x8br\xf6\x07-s\xce\x9c\x90<\x05\xbe\xeag\x00*w\xd5a\x9c\xa0\xeeE.%\x9a\xb6\x8c\xae\x8c\x07\x83J\x8dl\xd9\xd2 \x16=\xa1&@\xe4}\xdc\x19\xc0\x8e&\x855\x08\xee\xa1Nc\x8d\\A\x95\xc6V\x1a7\xb4|56\xae\x85;\x8c5\xbc\\\xac\x8f\x0e\xf9\x8f\xf3p-\xc5H.\x03\xd82\xc1N\x1f[d\x9b\x91\xf6\x8c7\xf7\xe0\xb4\xe5\x7fpU\xf9\xb5\x9c\xec\xb8\x19\xa3:\xaa\x19\xf1\xf8\xacH\xd4\xebv\xfcFxL-Y/[[%A\x8c,\xa7o\xf4\xe7\xb2\x03\xc5x\x9a\xbc\x80\xb0\xb5kJ\x0b\xf9\\\x87ia\nl\xde\x94gJ\x9c\x80\xf9\x8c \xf5Uy\xa1\x1d\xe1\x13\x8b[/H\xa9A\xe5\x13\xf0\x832\x91\xe2\xf6v\x00\x91\x87~ \x1c\x02hn6\xe7\xf9dS\xad\xfb\x84\x81\\<;\x1f\xe1\x04\xa6\x1a\x1f\x91X*/\xb6\x03\xad\x03\x9b\xe1\xe8\xfc)q.o\xe5F@\x06eT9\x92\xc4\xfe\x854\x84%.\\ \x08\x9bX6\xda\xb5X\xcd\xe4\x85\xd9,\xb5\x89A\xd5\xab\x8a/34\x15*9\x81\x9ecED\x91[\x1d\x91gfd8\xc1(\xf8\xe8\xf9\x1d7\xdb\xc0\x17W\xe2G\x0d\x11\xa7l\x86\x9d\xdc\x88\x98\x101\x80[\xe8\x83\x83\x81\x88\xe8\x93#\xde\xff,*\x98E\xady\x93\x18\xda\x1c\xf1:ff{\xc2k\xa4\x90\x86\x80\x1cF\xc0 \x81\xcd\x06r\xf6W^\xf4\xc8`\xd2\xa7 W\xa1+\x07\xb1\xe7\x97\x90\xd2\x0fJ8y\xe7\xb0\xa3\xc3\xcc\x0c\x86C\xee\xe9\xe7\xb1\xcd\x96 G\xa4]\xd8\xd7V\x9a8\x13^\x8d\xf6cg\"Y\xcc2\xdc \xc4\xcaZ\xd2\x18\x1a\x96\x06\xc4\x00\xb6\xf0\x94\x8a\xa4Y,,\xd2\xf8x\x93\xfaY\xe1p\x0c\xcb\x0c7\"\xdc\xb4L\nDDQE\xc9\xa4m3:\x89\xe9f4~l~\x00\x93o\xd3SEV\x1e'*\xb2\xea\x95\x8eY\x06B\x87\xd6\x81J8Nu\xfd\x95S\xc3\xa2\x03\x92\xd4\xd7\x12E\x9cqW\x02\xe3\xf3I+1\xbe\x12\xcb&|o7\x1b\xd8\xc2r\x90\xf9\xf66<\x82\xa4\xdcl\x13F\x83\n\xad\x9c8\xc7b,\xf8\x80\xe7X\x84h3\xe1\xe65\x031\n`\xa2\xa3G\x93oT\xd6 \x9b\x1e\xeb\xdfi\x89\xecz:\x896J\xabM\x15\x9fy}\x1c\x96\xf7\x9a\xcfR\xb9V\x0f}\x88ZOK\x06\xaf\xed\xed\x0c\x1e+(\xdfv\x12;E\xbfC[\x04<\xbb.\xedj\x024P\xb5N\xa1\xe0\xaa1 \x96\xd4\xe2Q\x0c\xb0'\x01\xaf\xa3\x13\x88'Oe\x92\\\xf4\xc6P5\x95]\x14\x04U\xac5\x1d\x98\xbf\xbb\x1e\x98v\xb2}M<\xb0\x99\x8c%.{\x84x\x16\x97\xf73\x11da\xa3S\xed\x88n\xe1\xb4'\xad\xa4\x8a\xa7\xe4\xc6\xd3\xb2\xceuO\xfc\x92je\x0d\xb6;\xb3\xb3\xdd~\x00\x9a@\xcbk\xe2\xb9\xbf}Y\x92\xd4e]\xba0\xf7\xdf~\xdet X\xb8\xc9q\x914\x89\xda\xe55MZ(R$\xb3\x0e\x86\x82V\xf8U\xd6\x1f)CT\xa3\x0cQ\xc0\x8f\xb0\xa8\x8d.\xb4\xcb\x0d\x8b\xd2\xeaa\x7f\x99q\xa2\x0b\xac\xe47\xc3\xbfX\x07\x9c\xcb\xcb*x;\x13\xf1L\x16\xf6\x1e\xce\xe7\xd1\x82\x80\xd1)\x0fTu\x00\xda\xae\xd4\x99'\xd8G'\x9a\xe7&$\xfcz-\x86\x8fo\xb6\x04X\xf0\x17\xe9\x94\xa1\xce\x91\x18@1\x1b\xeae-\xb4\xe7LT\x0d1oeve:\xca\x16\xb5(\x10@\xe1\x9e\xb7\xd0\xf3j\x02\x8f\xb0`\xcdM\xc8=\xac\xda\x87e\xf2'\x18\xa8\x0d\xfb2M7R\x84X\x94\x03HPR\xf4\x0bIbk\x17\x8bs\x9a\xf1\xca\xac*g\x0b\xcb\xben\x96P\xfa3L\x19\xa9Y\\\x03\xb1\x8a\xa3\x96B\xe7\xd7F\xa5\x04[\x958))\xa8\x93\xc9\x04\xe4\xb9%R\xcdw2\xcfN\\\xe9\x0d\x88^RA\x01\n\xf7\xeb\xd1`\xcc$T\xd4\x10z\xa1\x8c\xa7@\xecb\xc7h\xeeM\xca#3.\x08G\x1a\xf0\xf3s\xd2N\x16\xd9\x15r\xe7\xdcD\x94F\x9b4\x96\xd7\xda\x82\xf0\x8eJ\x90\xac\xa3g\x97\x19i\xdb(`\xdb\xaa]#C\xdb\x81\xa2\xba\x99\x99~\xb1RT\xee\x91\x89\xd1\xaa:\xf9E\x12\xdc\xd0\x986:2SK\xbe'\xa5v\xa3\xe2 HZ\x8a8 \xb8\x8fR\x1cy\xc4K/\x1e\x00\xffP\xb8\x97\x11\xa3\xfb`\x91e\xdaxD$\xfd,I\xa9\x9b4+>!\x1e\x1d\xdd\x1e\x07\x10\x8fn\x8f\x11\xcb\xe9ho\x0c;\x10\x8f\xf64\x19\x82\xfd\xb2 y-+\x83q\x97\x96;i\x08{\xcd6\xeb\x15\xfal\x0d1\xd0\x8f\x06\xba\x81q\xce\xf5\x85\xa8\xf1\xc1\xdd\xbao\xf0_?z5\x85\xa0 \xa7^Zq\x8a\xfb\xbb(x\xe5b7\xfa6\xed\x82,u\xe0\xdcRG\xe0\xcaK\x02\x99\xad\x0f;\x99\xe0w\x0fC\xd8K\x9fK\x86\xef\x96\x03\xff\xea\xfa6\x07\xf6\xbf\x03g\x88\xab\xd9*\x80\xa1n\x02\x973\xb9\"\xa0\x04\x16\xd8\x00\xc2\x13\x90\xf4\xb3dI\xae\xd2\x01C/K\xf3\xa2\xbe\xd4_\xc8H\xc9\xfc\x989\xe6\xc7\x14\xce\xbe\xa2\x1c\xc5U\xa1\x88\x03\xb4\xcd\xf2\xfa\x05\xe2\x1f[s!p\x13\x0b\xaf\xc9A\xfb\x93$\xceh\x9aOP\xb3\xecF\xdf\x7f28zGE6\x1b\x1e\x81\x84%F\xe8(6j\x0d\x810\x01\xc9\xcd\x818mI\x9c\xcc9\x88\x82\x04Zs\x8aq\x0bv\x14g4\x8c'$\x99)\x15\xcf-N\x11\x089D\x8f\xea\xa7\x95d\x9f\xa9gR=\x17MX9tv\xc5\xa8\x96j\xd7\xb2\xe6e(\xe5g\xb2\xce\x8c~\x89\xf2\xdar\xe3\xca\xd4\x8b\xa6k\x87\xb7\xd8E\xb4\x11\xaeN\x9d\xc8K\xcceJfQL~N\x93\x15I\xe9Zp\xbe\xee\xad\xb0\xeb\x94PE\xb4\xec2\x06y\xa9$\x88\x87Mvj\xe2\xb2\xdd F\xbd\xb2\xcax[\x8fo\xdduJk\x89\x98\x03\xe8=\x0d\xe38\xa1\xacuHb\x08c\x88\x8a\xf4\xbc)\x99$\xe9\xb4\xdf+H&\x8f\xb6\xb3\xb0\x98\xba\xab=s\x9b\xbc\x0c\xd1\x08\xf5\xeb\xb2\x7f\x12\xc5S\xaf\x8c\xbak\xff\xec\x12&!\x9d\xcc\x01\xc1f\x1f\xd0\xa5']\xd3\xe5\x11\x91\x0b\xfd\x04r\xfdq\x88\x81\xbcK\x93\xe5aL\xd35\xd7\x95*\xca\x9fv\\\xe9V(\x81\x0b\x7f\xc3F\x95\x04\x87\xfc\xda\xa4B\x14*\xdd\x1a\xcd\x08%!\x11KT\xfd\xc8\xbc\xacp\x00\x1f\x88p\xe5\xecPmA\x1e-D\xdd\xd9<\xef\x85F\xa2AHF\x99BH\x87\xf0\x9aT\xe1;\x9a\xca\xea\x06\x15\xa8\x17u\x0e4\xfb6\x00\xe2\xbd#\x01\xbc\xf0\x03xw\x05\n\xdc\x14\xfc\x90\x02\xeb0\xa1\xd2|-n\xa0\xb5\\\x1ao\x9b\x17M\xb36\x8c\xfa\x91\xf7\xe4K'\x9a\x81\x8d\xcb/\x9bt\xe1]\x15nN\xa1BgJEf=\xbe\xb1&>Jr\xb8\xa5K6X\x19\xa3L6\x80F\x0d\xe7i\xaa\xcd\x88yJ+\x8798\xfc\xd2o\x04\x89\xd6\x80\xc01\xb7\x15;T\xb2\xa8\x07\x02\xa3\x02\xcf+\x87M\x070\xa4W\x01C\\\x03\xc32\\i\xf0\x15\x04\x18\x1a\x85_\xde}\xdb\x19\x11XB\x94\x9a(Y\x1e\x13\xd5\xc9+\xe6<\x07\xc7e\xea\x11S\xcc\xd2%#P2\xdf\xf2?y7>\xcf\xd2S\xf4`T\x9d\x17\xcdG\x81\xc8\xd7\x1c\xc3>/\x06\xa4\xeb\xcao%\n\xdd\x8e&<\x1eT\xb0\xf8\x16\x08\xca\xe3I\x7f\\\xc4U\xddS\xc3\xa0aD\xdd:\xd8\x8c\x8b\xea\xa8\x90\x97\x96\xa1\xd8\xea}Q\x88 hP\xe1JCT4\xf3U\xc0\x82\xf8\xe8\x17V\x98Wt\xcba[\x8a\xf2$!\xde\x1b\x12\xc0\x0d?\x807\xeaR\xe9\x02\x01\x1d\x89x\x11\x0d\xd8\xa4\xe4o\xbems\xb5R\x1a\xf3\xfah7\x9d3o\x86;\x0cA\xee\xca\x92ig\xea\x86\xf7\xdf\x84\xb0\xd7\x82\xa1\xc4\x15C\x89\xc4P\"14\xe5\xa6\x10\x81\x97N5\xc3\x88\xf7\x8a\x04\xf0\xa3\x1f\xc0\xabo\xe7 ,\xc8\xf7\xeaZ\x90\xef\xcf\xc40\xe2\x8e_\xda\xc9\\\x1b~\xfd\x87\x91\xa8\xc4\x9f\x8e\x88\xf4Lp\xba\xcfT\xe8\x10!\xcc\xb4\xf1\x10\xcdu\x14,D\xbd\x9fg\xff\x95\x88\x84.1\xa6\x87\xec\xfa\x89x\xc6\"z\x8a\x93En}\xab@W,\xd1\x8f\xc2\x00:vr\xb1\xb5\xbc\xb9\xcbo\x1a\xa4Xv5\xf5rZD\xd7\x02\xfb\xbf\x06\xd1\x1d\"C\xdd\xf6\x02\x14\xe1\x95\x15\xb7p\x8b\xf3\xa4\\/\xd2\xe6e\x89\xde\x95\xb6\x11\x02G\x0e]\x18\xa0zI\xde%o}S\x0c\x1e\xf7r\x04\x07<\x91\x0bG\x89\x14Q\xa2\xbc9\xe07\x07\xcd|\xf9\xeaepYt\xa0 \x95s\xb8\x9a\x86\xe0\x9d\xf9\xd1+\xf3\xa3g\xe6G\x98\xa3\xcaK\xe3\x00N(\x13-b\xe5\xcdoT\xb0\x86\xb1\xe0A\xb7\xa1g\xd4\xb0V:\xec||V4\xea\xec\xf3\xb7\xe7qi\xf2\xb1w\xe6\xa8L\xe0i\x9e\xe6Eut\x1b\x9aW7oep#\xaa\x89S\xae\xcc\x85\x89\xaf\x07\xe5\xdfRg\xa1\x89\xd9\xac\xcf\xc4I\xf9[J&Z\x95\x15\xef\xff\xe6Me\x00\x15}\xae~\xb2R\x99\xa0\xda\x06\xcc\xd3\xec\x1f\x93\xe5\x8a\xaeQL.~\x0c!\x8f\x85\xa8\xfd\x1bm\xa6<\xadM\xd5Qc\xdc\\\xb4\xd2J\xcd-\xd4\x7fS\xacZy\xfc9N\xcec\xf8L\xd6\xd0\xfb\x1bl\x03\x85m\xf8[\x0f\x92\x18\xd8/\x89\xc7\x06#y\x05z[%\xf8D1\xfd\xb2\x16\x87\x16)\x1c\xf4\x86\x15cBu\x892\xa9\xd7j\xc1\xadJY\x08e4%\xce\xc1~\xb9\x0e\xcd:\xcc\x955pT\xae\x1b7\x8ey\xa6\xc48\xfb({\x8f\x9a\xf8I\xdcT\x01\xcd\xe2\x00\x16\x0c\xc7z\x7f\xff\xfb\xf1\xf1\xd1\xeb\xd7\x1f?<\xf9\xe1\xd5\xe1\xf1\xfb\xc3\x0f\xc7\xc7\x7f\xff{\xaf\xe9\x08\xb2bog\x0eJ\xa3y;\"\x18\xaa5\x91z\xb5& \x05Y([j\x88\x91\xcd\xe5\x87\xa6\xf4\x8eg\xa0^\xae\xe8\x9a\x87O\x17`tSDL\xdb\xf7bU\xc9\xb5\xb2\x04a\x94\xd9\xeck\xe5\xebb9-\xca\xb3z\x97kJ\\\x93p\x9fY\xe9\xd2\x0c\xf3\x0ex36\xdei\xec\xe9L5\x86v\xd7\xdf\xa0\xd2:\xe7*\xad\xd3\xb8\xd4d\x9d\xff\xbfM\x93uj\x87_\xa1\xee\xd3\x14XT\x7f\xad\xe2\xd1\"\x96\x0et+E\xa9\xb5*\x95Z\xab\xaa\x82I\xfe\xac>\x10\xac\xc1*VuV+\x17\x85\xcf\xca\xa6\xf0Y\xb5)|V\xb1\xdc\x870\x84\xb3X\xdc`[\x11Q2\x00\xe2\xadcF\x9c\xfc\x00\xd6\xd7\xa7\x11Z\xff)\x1a\xa1\xf5uj\x84\x84\xff\xbdM1\xb4\x8eK?}N\xb9O5\x94{\x19\x07p\xcc\xf6\xc9\xda\x81\x16\x9ft%l\xc7\xff!\xc2vn\x85\xe6\x92\x13\xb6%\x1b\xefI\xec=u/\xbby\xf1\x0d\x84\xed3'l\xef\x15\xc2\xc6n\xf5\xf38\x9bG3\xfad\xb1p\x8d\xe6\x7f\xef\xac\xe8~bWt\x1f\xc7\xa5\x83\xed\xb1\xba\xd7\xcecqC\xec\xb5\x13\xdck\x17q\x00\xe7\xd4\x0f\xe0\xe2\xfa\xf6\xda\xc5u\xee\x8a\xf74\x9c|\x86\x11\xdb\x10\xe3\xe6\x86\xb8\xb8\x82+H\xd5\x18?'\xe1\xb4\x89\xcf\xa8\xb7\xa2JRn\xea?\xe4\x89\xd7\xe9\xce\xceC\x1f\xbf\xe7^U\xe6\xbd\x00\x07 \x92\xd0\xe8\xe2\xfe*#_\x11\xf2\xb9\x13\x80\xd8\xa8K\xc3!\xfb\xa5\xc9\xde\xd1\xe8%\xcf\xe6m\xbd(9\xbe\xe5\xfa\xbai\x1d\nM_\xe1L\x82\xbb\x7f\xbb\xd1N\xa00\xc0l\xe0\x01\x02\xb3\xfe\x16\xec\xc0\x80A\xfc1W\x1b\xee\xec\xf8\xf8\x99\x89/\xc0\xcc*E\x1b\xa3\xd8\x90\xfb\x90-X}-\xd8\xa5I\xb4\\\xc5GC0e\xc1i\xe3z(\xf1V\x8d\x8a\xa1\xfcn\xad\xfc\xb9p\xed\xff#\xd6\x8b'\x8d\xc5{\xc2H\x91\x83`\"\xd4\xc9\x98\x1f\xda\xa3\xbe\xcf9\"\xfb\xfa\x959HZ\xa4\x16d\xc0\xf5\xd0m\xd9T\x05o_\x84\x07u\xe0\xd0\x08\xcf\x92gB\x01(\xd1\xc0P\xf5\x18\x8a\xf5o\xa6\xce\x87\x06\x19\xc5;E`\xaci\xfdIm\xfd\xe3\xab\xae\x7f\xd3\xfd\xba\xb1\xfeIke*\x15e\xb3E4!\xde\xc0\xde\xa68\xa6\xba\xb4\xcb\xd0\xd0Q\x1d\xa5\xeb\xca\x05\x83\xeb\xdd\xe9N\xd1Z\xeb\xdd\xa7\x91\xac\xae2\x8b.V\xa6o\x8d\xcf\x16(U\xc3\xa0.x\xc5X\x11;\xd8\x18\x92\xb8\x1c\x99\x8c\xa8|\x16\x8e\x1e\xc5`]\\\xc1b,.\xa2V\xe95h\xb8_{\x95\xa6\xab\x16\xaa\xa2\xa3sZ\x1f}\x99\xa6\xc7\x18\xe3W\x9cLi\xe5d\xc22gQ\x95d\xb1\x83\xe6\xa1\x8fw#\xfb\xe9n_\xc4\xb4\xb6\x88\xd1\x95\xd6\xef\x8fXWa\xba\xb6\x86\xdd\xd4V\x85.\xa9\xa9\xb9R\x10\x14\x0e\xf0L*\xa8\xbd2\x99\x8ea\xc8\xea\xcc\x06\x06=\xd4\xc5\x95\xb5\xa0\"\xee@]\x92\xf2hQ<\xbflH\x11\xf3=\x97\xd6\x10!\xad$\x13Le0H\xac$\x13\xc4o\xd2\x16&\xd0i\xb2n:R\xa7\xd9&z\x1db9S\xed\xd9\x97\xba\x9d\xdc\x8e\x91 \xad^\xff\x92\x9fH\xdb\xe2\x07D\xbf%\xa0\x03\xee\xd9\x8f\xcb`\xb2\xfa\xeag\xc8[je\x1e\xda\xb2\xf3Y3\xf3\xb9D\x05\\\xa0\xd6\x15\x85\x9a!\xbc\xd7H\xef\x87q\x00Otz\xd7\x0fO\x9e\xbe4h^\xdf\xb2\xf7/\x1c\xa4\xfd?\nw\xbd\x96\xfc\xa15\x8f=kF\x99\x92\x19\x8eTN8\xaa;\xeaE%\xfdK\xf9\xaf*upK\x19\xf8\xd9z\xea\x1er=\xc0!\x03\xc8\x1f\xb1\xd7pO14z\xd4..\x16ho4K*\x87\xd3\x08ut\xec\x9f&J\x18!\xa9\xa6\xef\"%o\x1c\xfb\x01\x94.\x93Jh\xc4\xfb\xf5\xf2$Y`\x85\x04\xdb\xf3z[\xb4\x06\x11\xf5\xd7\xdbx\xf4\xa4P/\xbeu\xd1\x06\xbe\xb5i\x03\xdf\xb6i\x03Y\x17\xaam\xed\x8b\x9aE%\x80\xb8\x7fT\x12\xc8\xaf\x01[\xa6X\x97\xfeK\xa4\xc4vH\xf3\xf5\x8cz6V\x04\xc4\x82S\x91\x1b\x97g\xda.\x8f\xf6\xcdFk\xa3\x87\x1acP\xe6{0\x98\xde\xac\xa6m*\xb0GOc\x1a+\x88w\x9b4\x81&G\xf1\x94\\\x90\xe9{\xf2\xc5\x010\n\x89\x7f#\xa2\xce\xddz\xf9\xe9\xbd{\xeb\x08\x1cm*l\x17\xcd\"W\x87pa\x84p\xefn\x1d{!\xa7,\xd2\x94]\xd2I!\x17;\xf6\xde\xa9\xdb\xec:\xbb\xed\xbcI^u\"\xa6\x9d\x9a\xcf\xaa\xb3R >\xce,\xac?/WY\xaa!\xe4\x9c\\ \x052\xae\xee#\xbc\xb86\xd0\xbf\x8a\xb2\x0eK\xbe\"\xd7\xd5/7C\xb8\xf7\xdc\x1b!\xc7r\xb2 \xe3\x9eK\x0f\xa5\xa9\xc3\xb1\xfc\x85Y\xbb\x04\xdb&\xc6\xf2\xba\x9f\xbe\xf2\x12\xc3\xcc\xb91\x8f\x97\xd9e\x94?\xc5\xb0\xc7}\xce\x14\xc2\x01\xe4\x98\x92|\x1fB\xea!\x7f\xd8\x8f2\xc1'J#\xe0\x88\x8e\xb5\x94[\xbd.}wOo\xf5*\x10\xc0\xe2\xf5\xad^\xa6\x8a\x1dP1\x16D\x0d+\x8f\xfd\xabA\xed+\xfb\xb8\xcfD%\x84h\xb4\xebP\xe79)\xed\xad\xb8\x08\xa1\x97\xa0\xc7\xae\x0c\xc4\xcd<\xa5\xd0j\xb3\xde\x96\xbc\xcc\xd9W\xcfD\x95(Q\xfdBW\xd7X^\x92\x92ci\xe9!L\xeaT\x14\xc7\xc4$N\xf9T\xd2S?\x90\xf7f\x8b\x90R\x12{[\xbb\xc2\x12\x83\xdaEM\xd1\x13\xebV\x00\x01\x1c%\xcd\xa8\x13\xba\xc8-\xc4\xfd\xa0\xec\xc0\x87f\x1fJ\x85X\xd86XN\xe4e\x06\xf8%\xaf\x8d\xd6,g\x8b\x0f\xa5\xfaV\xe3\x0e\xed\xc6\x8eH\x8f^\x97\xb4\xc9*\xbbV\xf5 v\x897\x98\xda\x12#k\x0b!4n\x91\x98\xa6Qe\xac.CU\xf4{\xef\xdc\xba9#\xe9\xda\xf1Lq\xe4\x82cK*\xf2\x16.8\x0d\xc0V\xf2\x13\x8a@s\x8e\x03\xbc\xd6\x11~\xa1\x14Z\xe3Z\xa2\xad\x81\x01\xf8uG\x12\xd0\x03\x86\x13]G\xc8\xd4O\xae\x1f\xd4|\x82\x9a\xf0'0\xf5\x19Ok=\xbaT\x8db\xc0d\x9fbNT\xcf`\xde\x00UOz\x80 M\xf4\xe5\xc15\xc3\xe2Z\xa1n\xb0\xa8 KP_q\xeei\x89y\xbb\x89\xaf/S\xa3\x19\x08\xe3@\\6o\xbd\xef\xc2\x92\xc2\xe9!\x1c@\x0f\x19\x1f\xd8\x87^\xd03c2#\xc1=\x8d\x1eU^\xdf\x82\xe96\x1c\x8fE\xa9\xfe\xad\x01\xba\xacn\xa3\xd2\x14\xffE7\xa3-YBJ\x99\x14\xaei\xe1E\x83gN\xaf\xc9Y\x82\xd8\x01N|\xdbg\xb2\xfe\x06\xf2\xf3\xd4iE\x97\x159\xd4\x01\xad\x8a-VM\xd9\xe9\xd4\x19?K;n\xb0\x00\"\xeb\x02\xd7p\xad\xe1\xa0\xf2\x08\xf60?\"\xc3\x14\xd8\xe7\xf9\x90\x1a\xdbAU\x03`\xcdZ\x1b\x01\x84\x03\xf0\"A\xe5\xb09_\xb4K\x8b\xd2\xb7\xbcb`b-\xc8\x9c\xba\x83\xec]t:\xa7\x1d\xe1& \x93\xca\x08\x95\x86(;}\x12\\\x8f0\xbd\xa7F\xbb;\x98\x06\x8d\xbd\xb8\xe3n\x81Tj2\\\xa7\xae\xd0\xb8|E\x0c\xfer\xb5C\x82q#\xddz\xe4yYx\xac\xdc\xbb\x18K\x85\xe9\xb2`\xe8\xbaJ\x9djL\xd4gf\x0c\xc8\x01}?(u\x7f\x03\xad\xf9\xd9\xa9\x97\x93\x9c\xbe\n\xbb\xa8\x07\xf8\xbeF\x0f\x99\xdd\x00v\x06N\xbdD\xd9\xe1rE]l\x0c\xa2\x17\xf5dR\xe4\xf4\xba\xe4\xbe/\x96\xb1\xca\x8c:\xf0\xa2&#\xa4\xd3l&I\x1e\xd7w~\xcb|\x9ex\xb4T%\xf1m/\x04X\xfeq\x07\xbd\n\xf6\xfe\x83+{*\xfaw\xa5R\xa0P\xaa\xaf\xd4\xf3K\x83\x94-\x03\x9eD\x0d\x1d\xf1nc]\xf1{\x917\xc1+\xeb\x94\xf3J\xe2lW\xaa9\x8f\x9d\xa46E\xe6\xd2\xb3\xbb\xf2\xb2\x94R\xc1\xb3@5\xb7\x19*\xe4]\xaa\xe7\xad\xcb\xea\x91/y\xb8\xe8\"l\x9d\xd1\x82l8\xb5/\xb2f:l5\xd5\xe1T\xbf\xb6\x18\xa8\xd5?\xc6ty\x95\xe2L\x94\x96\xf7\xed\x9cb\xb5z\xeb\xcf\xb1_S\xb5Z\xcf$\x0e\xc6A\x0b\x1d3\xc3@\xa2\xa0\x1b\x05\x8e\xaa\x94\xb7\xd5\xfc\xa4P\xb0\x00\x12OG\"\xe5e\x18\x7fgQc\x1ev\x913\x90\x0e\x89\x84\xcbK\x1eC\xb0t\xec\xe5\xa8\x0b\x0d\x97\xfdp\xaf\xd1.=E\xd9\xfb\xfc\xc4\xb1\xc0g!\x03\x0eM>aE\xa5\x14nu\xe6<\xba\xa2\x13r[\xda\xe2<.\x12\xe3t\xc8\xa7\xa5\x9f\xe2\x8a\xf1B]&\xe9\xd9f)`\xa6\xcc\xd2/n\xba\x9fj\x9f\xc9\xfa\xed\xac\xc3\x90\x8aC\x8d1s\x9d y\x0dFB\x1eq\xee~\xc4W\xb42lW?mH\xa9.\xdd.\xba\xab\xd1\x1a%\xbf\xfa\xc8\xcf\xba\xf7\xf7\xf2*\xebb\xe0\xbdq\x8d\xb5\xb9\xac\x9a}/\xc3\x8b\x0e\xbd\xbe$\x9dT\x18\xcb\xf0\xa2\xeb\x99\xfa\xb2\x92\x8f\xc8\xa9\x137\xa3Yc\x06p\x00ob\xee\xc2\xf2\xd5MPZF\xf1\xd5\xa7\xc3\xbb#\xbc;\xd7\xb9\xa5\xa43&jC\x1eA\xdf|\xf69Zu\x80\x9d\xd2\xfe\xeb\x90\xce\xfb\xcb\xf0\xc23T$6tV\x17\xbe]\xa5\x04\xc3\x1ecMzT\xb9\xe3<\x90_\xe7\xd1\xa2\xa3\x99\xa1\x18\xcc\xefW4l|\x8eV\x1fc\x1a-\xbau\xcb\x81.\x87\xdcM\x05\xc5\x13\x82u\xeb\xafi\xe5\xd0d\x06\x03}\x7f4\xfcL:,/\xad\x18 \xae\x80R\xac\xbfkF)\xd6dw\x94b_}\x0bJ]E\x92\xf8\x87\x13w\xab\x940\xfa\x18\xa3\x9a\xb7\x92\xbc\x0d#+[\x18^\xc9NS\xa3vY^L\xa4\x8b\xaa\xb1yJ\x81\x96J\x18\x08vlo\xedL\xd4\xf3o)\xfb_0n\x1a\xc1\x87\xa2J$l\x9b\xa1\xd2L)\xfd\x14\xdf\xde\xbc \xdb\xdb9\n\xa9\xa2AC\xa1ry]\xfa\x01\xe4\xc67.\x03P\xcb \xfd\x17\xadJ\x92vY\x16Z\xf1\xc6b\xdf\xd9\xe5Zv\x85\x16\x8f\x12y\x89q:FY\xaa\x17\xfaN\x85\xc5L\xdb?\x00\xf7\x88G\xf5\xb2F?\xaa\x97!VB\xbd\xa4\xe9&o-N%/\xae\xc3\xaf\x14\xa9\xb2x\xa9\xcaKF4R\x11\xc3\xdb\xfa\x01\xbb2\xe1\xac\xea\xf6\xf6\x04\xdf\x1e\xb4\xb8\xb6\x82n\xafM\x02\xc8P\xe3y\xc0H\xdbp\x08\xef\x84\x98\xf3\x9cad\x86/\xf04\x7f\xa1\xf0\x0c\xf9/X\xdc6\"`\xa5\x00\xda\x87\xdd5\xaf\xec\xe0\xb9*SQ\x1cZ\xdd\x98\n\x19C\xd0\x91/\xed.\x86\xcd\xc3l\xfe4\x99vpt\xa1\xf32\xbb\x00\xd6e\x9a\xab\xd9\x06\xday\x04(\xb6\x17wP\x1e\x0ea\x00\xb7`\xb7\xd8h\x16\xd2%\xcd\xa4\xb3V\x05\x9f\x9b+\x7f*\x8a\xdf\x0e\xf4Uo\x8b\xd7\xf8\xc0\x9c\x16\xbf\xf6\x0d\x1b\xed{\x14\xd2o\xdf\xb9\xbd\xf7`p\xff\xf6\xdd\xdb~P\xdc\x86G\x8f`p\x176@\xe0\xf1\xe3\xc7\xb03\xb8\x1b\xc0\x9d{\x83\xfbw\xee>\xd8\xfd\xbe\xfe\xdem\xe5\xbd\xdb\x01\xdc-\x9fc:w\x8f\xc06\xdc\xbe\x7f\xef\xce\xde\x83\xbd\xc1\x83{\xb0a0\xfd\x17\xdb\xd2\xff\x12\x9f\x0d\xee\x05\xb0\xb7w\xe7\xde\xfd\xbd\xbd\xbbE\xf3\x87\xe2s\xec\xa6x\xf3v\x00\xb7\xf7\xee\xdd\xbbs\xff\xc1\x83\xdd\x07\xbe\xda\x84e\xcby*\x7f\x10c\xad\xcb\x83\x8eP\x83!\xdc\x1e\xc0w\x90\xc26<\x8f\xbd'\x147\xcd\x13\xea\x11\xdfg32w\x0e\x8e\xbbS^\\+~\x85^\xaa\x93r\xe9\xa6\x98\x11v\xd4\xdaA\xb7\xc6\x1d\xdb\xf5\xb5\xe5\xac\xa1 \x88:RX\xb9SW\x06\xb3\xbd\xf8\x9a''Sr\x01\xa8o\xbc\x8eG\x0b\x19\xe0\xfd:\x1e=c\x7f\xbf\x16&\x8b\x8c\xdd\x12\xa1\xa3\xfc\xb6\x08\xac.\xee\xab\x81C0\x84W1>\x89\xe2l\xc5s\xe3\xe3'\xef\x93<\xad\xe6\x95\xd1\x81\xac\xa6D\x12\xee\xad\xd5\xd9a\xeb\x93y\x18\xc5\xbcma\xcb\xe4\xb7\x93\x98\x86\x11F\xa5\xe3\x10\xb8\xee\x12c\xc4S\xdd)9[D\x1dB#\x0b\x01\xe5+1\xae\x84N\xed\xb3:l\xb8\xf7\xbbZ\xff\xcdT15\xcb\x02V\xe1\xae\x93a\xb5\x90&\xa4\x93\xc4( \x1a\x9b\x8bO\x03p\xa3\xaab\x93t\x14\x1a\x97\xe1\xeae\xd5\x07\xd9\x15FW\x00\x02[\xf7:,\xda\xc4\x8c\x06,x4\x82\x05\x08\xd8\xc9Uv\xeb\x87\x18\x93\x9b\xb4f\xeexj\x06\x92<\xd5\xaa}\x19\xda\xf9\xb9\xb5\x9d\x11 \x80\x8e\x9d\x1a{g \x87\xf5\xb3\xb9e\xb3mQ\x97d\\\xd0\x84\xa7aXo\xaegX;\xd7<\xacW\xf6a\xf52\xa4\x81\x15\xe3\x07\x1c\xc0O\xef\xdf\xbe\xe9\xf3G\xd1l\xcd\xd5\xb6\x82Z:\xe6\x16}f%\xc0\x87\xc6L\x9e\x86\xe6\xbe\xb6b\x10\x85G\x05\x07G\xe11\xfe\xbd\x83\xec\x9cS\x07\xcf\x1d:`\xac\xcf6\xec\xdd\xbb{\xe7\xce\xed\xbb\xdf\xdf{\x00\xdb\xe0Q\xc6\x90\xdd\xf3\xf9\x9f\x8f\x1f\xc3^\xf3\xf4\xad.\x94h\xedCT\xaf\xc2h`\x95\xcb\xe5\x95|\xb3\xad\xaeu@J\x1b\xdeV\x82\xa5\x00\xf8\xba\xf2\xd0R&\xa2G\xbe\xaf$-\xc5f\xc5}k\xcb\x97\xac\xf7\xc0\x96GC\x85\xa8\xdel\xe7\x0c\xd2\x80[\xee*1~\xd8\x7f\xeb\xe4\xdd\xed\xa1W\xb0\x9f\x15\x90\x8d\x18ds\xf8\x1f&;\xb0\xad\xc7p \xa9\xb8\x00c\xcc\xef>\x7f\x07\x0e\xe09\x9b{\xce\xd3\x91\xa2\xd5F\xfe\x8cd\xca\xd86\xf0[\xad%\x86T\xe5%\x95p\xde\xc6\x0b\x12\x9e\xb9p^\xd2,7b]\x8c5\x87\xb2oY,\xb6/op\x02 \xf5/\x01\xdc\xe8'3t\xa65~\xc6\xf3\x93(\xde\xf9\xd6s\x96\x14\x1b\xdf+\x88\x81\xb8\xc7\xe8\x80\xc8H\x13\x94\x94\xc8\xcd\xc7\xa9\xab\xcb\xdd\x92z\xbbj\xcaj\x97>\xae\xe0_\xc7\x0e|\xc7\x08\xd5\xebv\xefq<\xf9\xbf^I\xafzC\xfe\xf1,\x0el\xc8\xe6<\x86_#:w9\xa7\xa4\xcc\xa3\xf6b\xc77\xc6\xd3\xc9\x00\x81\xe6\xf8M&\xcb\xca\x9dK\x9fQ\x842=\xec\\\xea\x1b\xd4\x9bE\xdd\x96#t\\o\x0e\xbf3\x8f\x85\x18\xc4kA\x0b\xb3\xb2\x93\x9cv\xd5|:\x9a\xaa\xd3p=\x9b\x0d\x9b/s\xb89@;Q\xf2l\xf3\x12\xda\x15+\x81\xfaX\xb1$\xa8\xb7+&\x85\x17\x81\xaa\xa4\xf5\xf1\xde\x8d\xca\xf2\xf1{?V\x9a\xe6\xf7N\xa8\xe6\xe3s\xaa\xf9\xfa\x82\xd6?oBE\xe6\x97\xdb\x87\xb8 W\x04\xea\xcb\xe6\xfd\xa7\xc9bA\x10\xd2\xfbp\xac)\x90\x81\x01b_5\x0f\xd4\xb4\x92G\x1a\xe7 \x9e\x97o\xa5y\"R\x05^hGI\xf7!\xd3\xe5{\xbb\xbb\xd3O\x9f\xf2\xe9\xfd\xdd\xdd\x1d\xf6\xefl6\xfb\xf4)\xdf\xbd\xcd\x7f\xee\xde\xbe\xc7~\xce\xc8\x1e\xfe\x9c\x91\xbd\x19~3\xc5\x9f{\xbb3\xfet\x97\xf0\x7ffc\xd3\xe0\xcc\x14\xad\x100(\xc9\xa8J\xc7.\xbb\xc1i\xb0\xfb\xa0\xc6\xeb0.\xb2wx\xb1\"\x13J\xa6\x10\x16\xed\xf4\x14c\x8f\xbc\x07\x89\x96\xb0G3\xf0\x94\xf8\x88-\xc5D\xb0\xd9\xc8\xecA\x1cE\xb4\xaf\x11\x1f\xe8\x9e\x864<>\x16\xd9F\x9bX\xa9h\xf1\x84\x14[\x83\x0c\xbb&\x9a\x1aTQP\xb9]\x14\x82M\xaa\xf7yQ\xc4\xbcz\x933\xc4a\xf5f\x86ofUB4\xe9\xb6:\xb7\x1f\xe8\x97\xe7\xce\x83\x96\xe3\x18\xa8\xc8\xcb\xc1Co\x1b\x8e\xeb\xca\xe6\x15\xc6\x0eOT\xe6\x04R\x9c\x80\xf2\xd1V\xc4\xb8\xab\x9b7\xd9\x1f\xb1\x8fJay8\xc6\xec\xaf\x98\x1dA\x95\xfe(\xeb\xf2\xca'\xfe\xed\x07\xb7\xb5\xb3\x1e|_G>\x81\x94\x0f\xeei\x90r\xd0\xc4\xc7\xbd6\xd2!k\xb9pG\xe1\x99\x0e\x15\x17\x98\xb5\xf8&\xe4\xcd\x03\x17\x0b\xb2\xca\xb2\x8c\x8d\xa7s\xc4H\x9dY\x8a\x11\xa8\x15\x03\xe4\x1c\x81\xec-\xd8?sx\x0c+;]F\x9d!\x0f\xd0\xf5\x9b-bAK\xfeX\xa9-6\xc5%n\xb6u\x06C\xd8\x194G\xbd\xe62t\xe3\xfe\xa9\x00C\x08\x07|'\x82\xf4\x8e\xae\xb6\x8dy\x01fx\xfc#\xa9\x0f\x80\xff \xbc\x06\xe8\xf6\xf6\x19<\x82\x956\x11\x00\x1b\xd6\x92\x81ttf\xe0n\x8e\xb1(\xcc\x99\xc6Q\x9c\x01 \xf3\xb1\x89\x13\x18\xc2\x02\x0e \xf3\x8e\x03X\x06p\xc6\x03\x91py\xf7!\xf3\x96\x01\x1c\xe3]\xbe\xfa3\x0d?SK\xe2{b\x92\xae\xd9{'>0\x018\x8aM)\x0b\x10\xa2\x03\xfd\xb3\x93\x94\x84\x9f\x1bO\x9a\xe7\n\xeb\xe8\xd46\n\xb6e;\xd8\x0c\xf0\x93\xc4;\xc5\xd7n\xde\x04oY\xe6\x8c\x9e0\x08Q\xb9-f~\x89K\xa7<\x16\xdf\x18\xdel\xeb\xd1\x06\x050B\x02\xb4\xd0\xb8\x04\xb2\xc8\x08Nb\x89\x0bt\x8c\xfbh\"\x96\xb6\x18\xb8a8\xdf\xba \xda\x13y&N\x10t\xba-~0\xfc_\xff\x9f\xea\x876n\xc8H\xa5\xeas\xa9\xd4_\xdb\x11 /%\x11\xa7\x98&o\xbf\xa0Ml\xdb\xc5\xf0\x08\xd2\x87\xcd\x95C\xd3\xb8GG\xf1\x18\x01\xa7r\x86\xbbZ\xfeOI\xef\xd4\x91\xcc\xdf\x19\xd4y\x83\xe2pkRyQ\x91\xa98^\x9b\xf4\x1e%\x19\xa5\\S\x93\xfc\xa3*\x08\x9f\x1de\x87q\xbe\xe4\x8a\x9f&{\x92\xda\xad\x1db\xe2\x85\xb8VE\x06\xcf\xf7\x85 \xde\xae\xec\x13\xad0\xe6\x9bak.X\xcc\x00z\xec\x0fBz\xfc\xc4\x0d\x9b\xf7\xab\xfd\xe9\x8f\xb4\xcce),\x99\xf2\x15\x06Qch\x10\xeb4\x18h\x9e%m*\x97-\xd2\x8f\x93)aB3\xdek6\x81\xab\x89\xa2w\xb3\x1d\xca\x8d\xd4\xac\x1dZiG\xa3sbk\x9es\xe0\x16\x90A\xc1\xe4\x00\xd2\xfe\x0f\xf9lF\xcaS\xab\xf95\x03\xa3\xc7\x8e\xb7\xb0\x1fe\xb5\xb7Q\x8a\x8d\xccJ\"E\xe2\xa9(\x89\xee\x0f\xfc\xc2X\xdc}\xdf\x1b\x988\xda?''\xabp\xf2\xf9\xe7d\xb1\x9eE\x8b\x05\x0fY\xe9O\xc9*%\x93Z\xedG&O0\x96t\x15\xd29k}4\xc6L\xf1\xf3h1MI,\xbe,~\xb2\xe7e\xb9\xb4)\x99E1\x91\xfb\x0bqr\x91\x84S2\xed\xe9\x14\xab\xa4\xd8a\xfbz\x0e\xa2K\xd1\x19\xda_4\x1e7\x95\xd4\xe6qF\x7f\xc9\x18#\x8716Wk\x08\x83J\x02\x9b\xced\xd4 #\x0c\xea\\t\"\xee\xdf\xd1p\xcb\xb8\xdf\x92~\x94\xb1\xfd4\xe5Q\n\x95\x97\xf8f:\x80\xc8\xcbQ\xe5\xa4\xa7;a\xb7\xb1\xdf\xdd\xbd\xaaZ\x91\xf2\x83\x8d\xd1\x81\xb4]\xb9\xd8\xbe\xb74g\xaa<\xc9\xe5;Z\x87\x17\xa9!\x10\xfa\x05\x91E\x90\x8e\x85;_\xcd\xdf\x84p\x8f\x92H\x16'\xf4\xe2\x9a\xa9\xeb\xf2\xaaX0\xb8_\x97\x818\x16|\x7f\xbf\x15\xc2m\xec\xc4.\xf72\xf0\xb8\x1a\x88\x07\xf1\x17\x9cD\xa1X\xe1\xd2\xe0#H\x1e\xfa<\x85\xe8(\xf2\xc8(\xde\xde\x1e\xfbc\xbdv\x8f\x7f!\x082-h\xebU!\xa0\xd7\xd9\x0d\x1a\xd8.v\xc1^\xfd`\xe3\x8a\x8c;\xdf_\x05^bJii\x18\x8c\xc4{\x07\xc0\x90a\x1f\x12/\xaf\xb8 9M\xae\x97g\x042\x9aF\x13\xaa\xa8\xf6*^X\x0d?\x11\xe9j\x13{\xdf?\xa8\xebF\x94\xe9\x1c7E@&\xbas\x98\xdd\xfb\xbe\xf6\xe5q\xff\x1d \xa7\x8cN\xbe\xa7\xfc@YV_`\x80\xbe\xeb\xf7\x0f\xcfHL\x0f\x97\x11\xa5$mv\x10\xb6\x81Q^%\xd1\x8f2Jb\x92b\xd1M\x8er\x8d\x0ft\x96{\xb1%\xea(\x01\"\xb88\xf6\xee\xef\xfa\x82\x03h\xbe1CA\xfdc\x14\xd3\xfbH\x07\xd9\x9e\xad\x9c\x9f\xcd\x99-85\x1b\xd4\xc0\xb6\xe8G\xf1\x9c\xa4\x11\x15J\xaf\xbb\x1a\xf3\xc0\x8a\xa3\xdd\xdd:\xb1\x06\xa12\xd0 \xd5\xec\xfe\x8am\x9fU\x7fJN\xf2\xd3Er\n\x07\xca\x0f\xaf\x97\xd1\x94\x84\xcb\x9e\x0f\xfbmC\x9f\x06(\xfb\xb3!\xd4w\n\x08\xe1\x88\x81\xb2\x8eK\xe5\xd4\x98X]7\xf9\xb3\x86O\x19\xf7\xd0#i\x9a\xa4=\xc6\xbd.\x92\x8c\xb0?\xa6$\xa3i\xb2f\x7f\xae\xc2\x9c\xdfKI\x96/Iol\x8a\xd6Y\x1a\xd1%\x01\xa1i\x8e\xbd\xbd\x81\xa8a\x81b\xab\xae\xbe\xa0$\x16\x04\xa28\xa3a\x94w\x86\xe5S\xdf\x0f \x13j\x85F\xb6?\x13 OJ\xe5\xb8)\xdaS\xe1!h\x0d\"M\xb0 \xdd\x147i{ym\x8f9q \xa8\xaa\xe2{X\xae\x93^\x89\xc7_\x14xfSJ\x9e\x15\xc5\xdd\xc4\xcb\xacu[*\x15\xce\xc3J\xaa\xc4\xa0N\x04\xdd\xe2\xaa\xd1\xd8\x0f\n\x9d?l\xb3\x86\xab\xd4\x17\xf6\x8b\xaf\x0dJT\xed]RR\xae\xdd\x00\x0e\xb5\x86I\x06\xba\x1c\xeb,zH\xb3\x11\xdf\x9d\xe0\x8aP\xd0\xcf9\xe5Uy&\x85F\xc4KQ\x15\x92\xaa\xdbf\x86\x94\xa6\x19}I\x94\xb8\x83a!\x0c\xd5NK\xcc\x12\\u\xaa\xe8\x1d\xc5g\xe1\"\x9aB\x9c\xc4;\xbc\xd9[\xe2p\x98\xcc\xf3\xf8s\xcf\xb7\xc5\xd3\x18&\"\xb6\xb5\x06n9: \x06\\*A\x02\xee\x15\\L\xc2\xe0\x99\xd7\x86,\x1c\x89\xc4*?\xc6\xc8\x1f\xcf4\xff\xfa\xc7e\xa5\xf9\x9f\xa5j\xf3\xed\xcc#<]\xb1bND\xd8\x10\xa7\xe4#bn\x13\x0c%\xd7\xe3\x06N0e\xa7\xb4z\xe45\xe7\xcb\x16B,\x02\xe7(\xfby\x9c\xcd\xa3\x19\xf5|\x08g\x94\xa4@\xe2)\x10\xc6\xf5\xf7\x10\xd7\xce\x11\xedd:;\x04\x16GU\x97\xb6q\xcb\xc8\x86\x0f\xdf>\xe7M6\x88C^\x1c\x19L\xfa\x8f\x19\xb4 &>\x92\x9b\xf6<\x8d\x84\xae\xbd\x0em!\x85\xcb\xb5:\xa8\x8cw\xc0z{[\xee\x9b\xea3\x9fW\x8fb\xcbP\x1d\x90\x0e\xfb\xea\xaa\x83\xb6\xb5\xda\xa2\x02LH\xb8\xab\xdc\x04n\x92\xa2HV\x8d9,\x99.j\xa4#\x97^\xeeF\xe3\xcf\x15\x1a\xaf\x1b0)\xb8\xa8\x9b7\xe5\x1eVh\xdf\x16\xe1l\xd1\x01\x9b\x02_\xebiHC\xb6\xd4\xa8\xf7b@\xf3v\xf9\x9a:\x12E\x8e\xa4\x05M\x95\xc8\x17\xb36t\x94\xb6\x02\xb8\xff?{\xff\xbe\xdc6\x924\n\xe2\xff\x7fO\x91\xc2o\xc6\x03|\x84h\x92\xba\xd8\xa6M\xeb\x93e\xb9\xc7\xd3\xed\xcbH\xb6\xbb{\xd8\xfa\xa9!\xb2H\xa2\x05\x02l\\(\xab\xc7:\xd1gw\xcf^#\xf6\x01\xf6\x9f=o\xb0O\xb0\xb1\x11\xe7MN\xef\x03\xec+lTV\x15P(T\x01\xa0,\xf7\xec9\xdf\x87\x88nS\xa8B]\xb2\xb2\xb22\xb3\xf2r\xef\x1e\x92F\xc7e\x8bJL\x9a\x16\xfa\xe85\x87\xe7\xd2}C.\xb8\x18\xd4\x9d\x1b\xa9\nU\x17$\x85\x7f\xb8wO\xf7\xba\xe0\xfc\xaaK\xac\x91\x81\xdb\x05\x0c6to\xd7\xf6OO\xf86F\xc3\xe7%\x83\n\xc1\x88\\\x8b\xdf\xe5\n\xe7Y(\xd7\xc9\xffRj\x15u\x1a\x0f3&\x0d vdA@\x11D\xe3\x06.7N\xeb\xb6ix]\x8es\xdf\xc8\xec\x08\xf5P\x19\xd1C\x91\xebN\x1b\xa9\x80.\x02\xd25f\xf1\xa6r\xf3,Hv\\f\xb8\xa9\xc0#\xc8>\xbbl'\x98\x99\xd1qyg\x8eK\x19\xb9\x92SB\xc5\x9fC\x81 \xdfs\x8d'\x0f\x9f\xa3\xd4<\x93 (\x87\xa2z\xc4+]\xf8\xc9[/K\xca.P5]l\xf5\x8b\x94_\n\x86r\xfaT\xd7YBd)\xa9\xd5\x9c\xda\xc91\x95\xcd\xa2\x885\x86z\xb2p\xc3j\x94G_U\xac|\x84\x11<\xdcy\xf8p\xbf\xf7\xd0\xa4/95\xa2n\xae>\x7f2b\xfe\x8dU:N\xf2#\xbb\x87d\xb6B\x9dS\xa6\xf0=(\x1f\x08\xd2\xa9\x9a\x93\xe6\x05\xf1\xa6]z\x08\x88\xb2aQm\x88a%\x80(\x07\x1ac\xa2U\x8dA3!\xcb'\xf6t\x04\x1fQ K\xff\xa5\x9dloSY\xeb\x13\x1d2F\xf7*\xfd5(\xfd\xb5[\xfa\xeba\xf9\xbb}\x17\xd2NG\x9bk\xe0\x86\x9d3\x08U \x0e\xe8!\x92CS\x9e9\xa9h\x0cz\x98\x9f\xb9\xd59}\xac\x87Bn(\xd7H\x8f\xaa\xbd\xf7\xe9\xe9\xa9*+(\xd6/l\x8b\xbe\x16\xef,\xb7XtG\xf7\x0d\x9bI\xce \xb0|\x1f\xef\xfc\xc9\xa5}\xc8#/\x1eV\xdceM\xf3<\xd4\xcf\x93\x0f \xc4$-\xe4.\x18\xc3!\xbf{\xd56\xa0\xcb\x1b\xe3n!%}\x08\xb2\xe0\xaa\x86\x04\x9d\x8e\xf2I\xfe\xa4u`2u\xfc\x93\xb1\xe3\xd2\x05Ln5FY,\xc1z2\x86K\xda\x7f[\xa4\xe0!I\xc10\xea\xf6\xd7\xc2\xb6\x96\xde\xf5\x05\xa1\xab\x86\xf3@\xf5B\xcf\x92\xd94\x17m\xfb\x8a\xce\x9d\xc7Ny0\x0d\xc0\x1a\xa9\x89\xbfL@\xb84\xaer\xae/\xa1\xe0M\xfd\xc9\xa5n\x9c\xad\xfax\xd9\xbc\xc2\x02\xdb\x99\xe6M\xd7\x13\xe2\xbb^1G\xaa\xca\xb4\x1c!Q\xb3\xcd\xd1\xd1\x05u\xc9\xa4\xe5\xdclJ\xaf>\x97\x08 \x8a-l\x8b\x8e\xa7\xb4\xad\x1f\x97\x07\x99\xa7R\xe6\xe3s\x1e+\x02\x8fi\x84\xef\x9a\x0e!\xe5\xe89`]!u\xac0J\xf9\x91\"\xc4\xcf!l\xa5\xec6\xf5i\xa9\x0d\xbb\xa4\xc0\x91\x0f\xa3\x9f\"?\xb4-\xbc\x13\xe9\xf3\x9eyI\xcd\xc1%\x0b\x1a\xdc\x9f\x92\x14>\xb1EQ@\xbc\xd8F\xd9&\xd4X\x94\xd6\xa9Z\x0c\x1a\x8a\x94\xed]\xf5\x00=\x00Lu$\x97H\x91B\\\xb9@[-u\xf2,\xc8\x1c\x06\x9a.\x88\x04\xe5p\x93\xf0\x96\x05\xc5\xa2\xad\xea/\"\xc4\x13Wmt\xd5\x07\xef1qlf\x15\\\n\xdb#\xf0\x8dDI<\x88\xed\x8f\x81\xc5r\xa4\xf4\xa46\xf7\x14\x08uf>\x80\xfa\x81\x82\xb8\x91\x81\xa7\x10\x15p\x8c\x8a\x13\xbf!\xb2\xb2?\x03;c\xd6I\xc5\xe7>\x95\x8e#\x18\xf2\x1f\xe5\x85f\x9b\xc7\xc6\xe9g\xb5\xa6\x96\xe2\xa9\xb4ow:\xb1\xcb\xc1\x81\xab\xbe`Zf\xfefX\xbc!\xdd\xd4\xf3\x03\xae\xe7\xe7\x02\xbc\xa8\xecr\x08A1\xc4\xcc\xa4\x91\x93\x1f\xb3\x85\xa7xn:\x1d}xc0jFA\xb2m\x17\x13\xddFw\xa0\xaam\x0e\x085)q6\x89\xab*p|\xd2\xf5\x82 \x9a\xbc\x0f\x13oF\xdaE\xe1m\xb1+(\xca\xd7\x98\xc5\xc6l\xa7N\xa2\xd55\xaa\xde\x04\xe7c\x97\x83\xe4\x8b\xe0\xbc\x1eSaS\x9c\xf7k\xc2]\xb8M\xc1\x974\xb9\xee\xf0+~\xde\xb9\xc5 K\x19E\xc3ev\xb9{\x13\x9bp\xf4\xb9\x8c\x0c\xbb\xde\xe1\x13\x7f\n=\xd95\x93)\x98\xffd\x910\x17Ql\xc7\x024\xa5\x9dB\x14\xe2\x9d\x02Y\xae\xd2k`J\xe8?i\xe6Bd%9\x13\x02\xe4\xfb\x17\x89\xfd\x7f\xabMrb\x8c\x1dj\xd6\\)=rU\xa1\x98$\xb3\xd2,_V\xf7\\\xce\xcbVD:\x9b\xce\xdej9\xa6\x93v\"I\x8fk\xbfr\xc9\x84\xd9\x93C\xd8\xe9\xe8/\xb20\x1a\xfa8\xe4vq\xc5\xbd\xaaQY\xb6\xadJ\x0f\xf2_\xb2B'f{\xb2^C\xc0\xa5 \x8b\x9d\x9d)\x8c`\xe5\xc5 y\x19\xa2[J_\x17\"e]\xf2;+\xe1\xa0\x9e\x12b\xa43=z\xf2\xf5\xe3\xca\x0d\x9dQ@N\xdd\x98\xffyE\x93-a\xf8\xa8\"\xd3}\xfa$\xd4\x0c\xc5\x8d5\x9f\xf1\x10*\xe2;k\xc7\xcd?qku@G\xec\x92\x18\x86pl\xf3\xcblJ\x10M\xf3\xe4\x04z$TP\x8e\xd4\x9ac`\xfc\xef\xdd\x13\xbd\x98\xdaF>\x99\xa5\x13-\x83\xc6\x88>\x0b\xdb\xa2\xf5\n%\x01\xe6\x15\x11#$\xd2N\"\xd2IS\x95\x97q\xfc\x0b\xdb\xe2u\x02\x92$\x90.\xbc\x10\xaeh\x8d\xa5\x17_Zl\\\xa8\\\x15`\xc3f\x85hw \xd6\x82\xfe\x11\xe1\x95\x19\xde!\xf8l\xe1\x91\xbf\xe3R\xf94\xc2\x01[\x8e+}_R\xa9pMQ\x05\x80:\x8dRI\xe3\xa8*\xd5\x1c\xb9\xc9\xbe\xab\x08\xc2l\x05C\\A\xbe*lic~\xc4\xf7\xe0 \x17\xf0\x86\xfc\x88<0\xe8\xb5\xd0\x0e\xc7\x91u\x7f\xdb\xa8\xec\xd4\xce\"\x07\xa0aFa\xb1\x95$\x85\x07\xc7\x1f1T\xd4\x8d\xe7\xd7(\xa5\xbb\xa8\xb8\x92w\\Q\x10\x9f\xb7\"(R\xc3\x9a\x0bM\x06q\x07\xfc\x04\xc2(\x05\x7f\xb9\n\xc8\x92\x84)\xa9\xd2a\xe5\x06\xc2_\x91\xd67\x10\xb5\x01\xd5\xa2\xb6\x97\x13\xc9\x95\x8f\xae\xc6\x91d8eb\xad&^B\xa07\xd4\x96\x01:\xe0\x0b{\xac\x1af\x0f\x99 }1\xb6\xdfo\xd3\xfe\x98\xfft!\xad\xc9\x13S\xd3\x15\xbfOi\xec\x8b] 5^wI_0\xd3\xb3\x0e\x95n\xe9\xce\xc7%\xc5 \xa0\xa3?N!Z\xa5\xc9\xe8\x8f?Yn\xa9\xb6\x9e\x1f\xa3\x8b\x8c^([\xcc\x90\xb0\xcf\x15r$\x9c\"YJ\xf9\x1dP\x92N\xa3,U\xde\x908\xa6\x92;\x0c\xe1\\\xb9%\x80\xb2\xc3\xb5\xce\x88X<\x0b\xdb\x8a\xc2,\xa4\x03\xb5\xd8m\x92\x08\x88\xca.\xdf\x99\x1e%\xee.\xbc\xe4=\xd6b7\xd8\xa5\x17\x8c\x06,lk\x12\x10/\xccVB\xa7\xb6\x8c\xd6\xdc\xf6\x8d\xc4vn\x1e:\xd7\x96\xce\xfc\xd0O\x16\x96\x0bKm\xf14\xf6\xfc\xd0r!\xd0\x96\x8a\xfdy\xad-\xe5\xb3saB\x89G\xf5\xe3\x90\x92\xeaYM\xd9\xb9\xb6\x8cS\x9b\xb5\xe3\xa2\x85/\xde\x82E\xb2\x96\x10\xaf\xf5\xcf\xafb?-]\xbcn\xa9/\x91\x08\xe6\x9f\x04\xfa\xa8\xf8\xe6\xf5\x9d\x19\xaf\xa2qm\x913d\x86{\xd3\xc68P\x808^2\x18\x91x_\xe4\x11\xc2n\x14N\x88\x00\x0dZ\xbeu\xa3\xb0\x04e=\x9e\x07\x8d\x14\x174v\x15Mrz;\x01B<|\xb3\xbe \x9fs|\x92\xd5\xba\x8e\xa2\xe5\xc5\xf3\xa7\xf8{{\xbb8\xcf\xca\xb58\xfc\x8c+\x8cQ1m\x886~(h\xc1\x7fc\xeb\x84-\x06\xe3b\x17\xe8A\x8cx\xa8\xd1-\xac\xb9+9-3#\xd2\xda\x9c\xab\x171\x89M\xd0\x05\xa1\x12\xe7\xd4*\xcd\xadq(\xfa\xb2\x83\xdd\xees\xa9\\\"\x97\xe8}\xc4\x89\xbb\xf0<.Ux\n}Z\x89\x87_=\xb1\x0b\xfa\xcf\xe3t\xae\x04\x135\xf3\x82\x84\x00v\x0b1IVQ\x98\x10\x17\x84\xady\xa8^\xc0\x96\x96\xb8\xa6\xb4\xd3\xe1\x93C.\xa4\x8b\xedm\xba\x1b\xaf\x1b\x80(H\x15q\\8\xb7\x1b\xa9\x19C8\x86`\xec=;\x17\x14\xc6D\x17L\xb1f\x90s\xe3\xb6j \xcc\xe7Z\nb\xeehYO\x9bx\xdb\x8d\xc7\xc5\xa6\xdd\x9e\xd7u[\x1cva\x97\xfdnw\xf6\x0by\x96\xed\xc4\x9c\xf8k\xbbi{;\x00P T%\x1b\xfb\xaeb\xb2\"\xe1T\x00\xa5\x08P\xae\x96\xb0h\xcd5*\xf4\xee9\x9a\xf0%\x0cy\xf8\x1fcr\x06\x07\x90\xd9\xf2\x0b\xf4n\x92\xfe.[d\x95>\x1d\xc18tK\xaf\xce\xb0\x8a\x08\x1e\xad'x\x12*\x8b\x03\x9b\x1d(e\xfe\x80\xbdS\xb8\x02\x86\xf4\xfc\x9c 1f\xa1 \xb4\xfcn\x0fY\xb1\xe2F.\xe4\xb7y\xb6S\xb9\xd4\xaf\x18\xc1T\x18\xf3Z\x9d\xd5&*\x03\xf3\xda\x17L\xd4P\xbdL\x15\x8f\xc6\xc9\xa5\x90\xc3I\x89\xa3\x17\xd8\xa1\x0d_O?\xea\xd7|T0\x97\xbc\x9c\x07\xccfV\x1cBb\xe4exT\x96\x1d3H\xc5+\xa3t\n\xf6\xb95\xbcX\xc4\x9c]Hy\xc4YnH\xaf\x1f\xf8Vmp\xd2\xb8\x18\x98Y\x83\xedCy\xe6\xfa\xcd\xb2\xe9\xac\xf4\xad\xe4\x8a4\x16\xe7\x1a\"x\x02\xfec\x88:\x1d\x07\xe2qtf\x82A\xad\xc2\xb6b8\x04Z2\xb5\xe61\xdcNlR\x9c\x9f5:8D\x89LZl\xfeY\x97eg\xb03\x17\x9d\x97K\x80\xd8F\xc9\xa7\x8aM\x9c\xf9\x11 \xe4\xbf\xc6\xbd3i\xf7\x9a\x16\xbensF\x95\x1b\xd7:\x899)}Y\xb8Ap\xc3\x0d=\x861\x8a\xce8\x13'gm\xcc\x06h\xb9\xeaA\x10\x18\x8dRY\x84,)lVD\xfb\xf5\xb8\xdcJ\xa8\x07\xbc+*+\x91c\x8d\xcb\x11\xdd\xb9\xba\xf7\xecB\xa4\xa2\xc9\x89\x0d\x0eM\xb1\xa4\xec\x8a%}\xceq\xae<\x94\x04\x85K\xbe\xa6\x9b\x1c\xabu\xeb\xefM\xf3\x93\x0eF\nf\xb8\x8a\xaa\x18m;Z\xc4cL\xdb\x02:?s\x95\xa3\xa68eR\x85\xddo\xc4T\xe0f)eC\x13a|T1?)\xdf@\xbc4GP.\xa2\x9c\xeb\xec\x0c\x15=\x14\xe5n\x9b\x00U\xa8Z\xe9.b\x1c6\xf0\xc92\x1dG\xcd\x16q\xdc\x96\xfb\x08\x0fnd\xde\x0d\x16\x94\xca9R(\xe6\xf8W-\xa6{\x15{\xab\x8dN\xf7\x9a\x1b\x80\xb6g\x7fl8\"\xf2\xe3\xc1\x07?\xe4\xa2\x1d\xd7B4\x89\xbd\x94\x9c,l\x8b\xcefE\xa6\xc0\x85\xfb\xb0\xec/!t\xf1\xf5\x92s\xca,\x1f\xda\xb9A\xf1\xb3[\xbe>0i\xcd\xc0x\x8dI$S\xed*\xf2\xe6\x9a\x04\xce[\xe7\xb00&\x1e\x94!!\x84\xd3\x12(l\xbf4G&\xa7\xfa\x14]\xb6B\xc5o$W*\xa3\xa6^\xb2\xde\xf7\x99Ho\xab\x1f`=a\x95\"\xc4~\x9c\x9f\xef0\xa2+t\xe3\xb9 \xa9\xdb\xb2\x0e\xdaLJ>S\x14\xbb\xc6\xfe\x19\x94\xe3\xd2JR\x01/\xb4EE \xa9\x9b\xdc\xed\x1b\xd1K\xaa\x9bR\xe6\x9f\x87\x81\xadM\xe5\x07\x065\x86\xaf\xbb.\xd7qF\xf3\xfc\x8a\x11\x19$D\x82\xf98:\x93vz\xf7\xc2\x0f\xa7\x9c\xba\xd1\xa2\x1a\x8f\x9cT\xf6\xa6l\x86\x8c\x84B\xe7\xfc\xfe\x908\xc2\xfb;\x16\x14\xa7\x10#\xaa\x13\xd5\xd3\x9e6\xee&\x82\x84\x94|\xbb\x9b\xa3\xd8hL\xaa6rM\xd1Q\xd8\xd2\xc5Qu\x8e\xe5\xd9\xa1\xdf\xc7\xf9,\x8e\x96\xf4T\x86\x11\xbc\xfb\xa7\xa2\xac\x1c1\xdb\xc50\xd8\xed\x02g\x97bpW\xa3M\xb4iB\x1fNc]\x84\xbaz\xa4\x8dI\xeakO\xea\x1a%\xcb\x8dv\xd0\xe5\xcf\xb9\x1bK\x0b\xbb\xa3[_\xf5@\x93\x1bQMd\x01\xfc\xac\xa2\x9c\xd6\xbc.Z3\xee9t\xb2\xce\x98\x9b\xde\x01\xfa\xe0\x14\xc6\x9b\xed\xfbA8\x97\xb8\xd9\x9c\xe7\xf1\x85\xb8 |,\xd0Z\xc7\x00\x91F\xcf&\xe9\xde\xb420\xbb\x16\x02\xe5\x8f\xf9k;\x8f(\xee\xb6Ppo\xf1$\\\x07\x94-\x97'\x18\xb2\xd9\x85\xbaA\xa9/\xcb\xb0\xc2A\xe1\xed+\x9e\xccZu\x96A\xcc*\xfd\x99;d5\xd0\x92[\xc3\xbd\xafg\xef\xe2j\xf4\x85\x8a\x0b\xcd\xb4\xb6\x05%\xaa\xc3\xe7,o_\xfb\xadf\x04\x95ru\n\xe5\nL\x95U\xdf\x86\xb2\xa8\xaaO\x95B~>?\xf6\x9f\xec\xa4\xc8\xb0\x12#H\x84\xec\xd4\x9a\xca\xe1\xf0\x13\x12\xcch\x15\xfc\xf7\xd3'\xb8\xf2\xc3itU\xa5/\xbe>\xb272\x12&_&}\x00\x7f\xc81\xcd\x9f\x16\xaeS\xdds4\xc4~\x816\xc8\x06\xf0\x00\xf2\x9a I\xdf\xf9K\x12eiK)'$W\x10\xd9>;\xc0\x8a\xaf1\x1cB\xc1\xff\xb8\x80\x03\xe0\x85\x15\xb5\x05\xf6\xfb2LI\xbc\xf6\x82[v,>\xd7\xf7,J5]\xcb#C\xfdK\xe9\x83F\xf1\x873\xf9\xa8\x88\xad&\x96\x8fJ\xda\xd2\x98\xcc\x94\xec/\xec\x8d<_\xe5#l\xb7 $\xa55f\x10\x89\xdd\x1c\x0f4s&a\x1c\x05A\x1b\xfd\x90\x0c\x1d;\xa5\xcd\x05\x84\xff\xf9r\x8a\xd2\x87\xfc\xaa\x8a_\xb4\xb7,\xd4\xf4w'\x9d\xa9\xd6p\xb4\xb7s\x84\xf3\xe1$\xf5\xd7\xe8'\xda\xf5\xc4\xcf\xcf\xe9\\\x7f?\xc8/R\xa5\xaa\x1a\x8dV\x91bQm\x15FPl\x99\xe6\\ri\xf7<\n\xc5\xe4\xd9\x9dD\xfe\xb7\xee\xb2G\xe3q\xe5bD\xab}G\xec\xb9\xe5\x92L}\x16\x9b\xa5\x99\x84\x95\xbfP\xb2e\xb2\x01\xa95(\x0e\xe6\xac\x8b\\\x98\xef\xbc\x0d\x87\xa0|\xa3\x1dD\xb5Ni\x18\xe5\xe2\xe2|\xb8M\xde\x9a&\xde\xd9\x14P\xcdGU\xa2\x9f\xc8Q\x88\xea\xd1S\xd8#\xe1\x8d\x82eA\x07R~\xab\x99F\xdfDW,W\x8em\xb4\xfeF\x13\"kA>Zz\xd3\x1eV\x8eq\x90\x1a*l\xd7\xd7\xf0\x92\x89\xef\xd7\xd6\xb8\xf0C/\xbe\xae\xaf\xe2%d\x7f\xb7~$\x93d\xd0Ta\xbb\xa1F:\xeb\xef\x07\xa4\xa9\xcevc\xa5\xd8\xbb2\x94\x83\xe4\x9fm\xc8+\xd9hq\x95\xfbwWwxys\x1b\xf2\xfc\xe8\x18\x19Ee+\x90\x0b\xf7\x07i\xeb\x07.(`3\xff.\xae\xa3\xf8T\x18\x9e5\\\x03\x91\xc7\x8f\x9db`u\xca\x97F\xdc\x85V\xf8+\x9e\x16\x83\x846h\x08\xadP\x11Z\xa2#\xb4EI\xf1H\xd3\xc0\xdaM3 \xbc\xd4\x0f\xfb\x8d\xbd\xd7\xee^\xf1\x88\xbey\x9bM]\xd7nwhEZ\xa0\x05\x8d\x13\x8fP\xe9\x98\x87\xd5\xb8'A8X\xd4\x87\xd8\x12\x0f\xa5\xd96'\xdaez\xcdbQl\xf5\xb4\x9f\xeb4\x84\xba{I\xbc/\x13\xd12\xb6\xca\xc1\xc5\xed\xd213\x1a\xf1X\x85,\xbdQ\xd5'\xc4z\x1f^\x86\xd1U\x08\x82\n\x0c\x81\x0d\xdb\xa8\xc7`\x07l\x99\x12\x15a\x1d\xf2\xb8t:\x8e\xab\x05\xdac#)\xf9(\x92\xc6\xb06)\xe74a\xa0\xd3Dh\x04\xb3\x89k#\xa9\xc0\x0ef~\x10|\xe3\xa1\x96\xce\xbb}/\xb5X-\xcfkV\x9aW\xc0z\xdc\xd9\xa8\xc7Z\x84\x95U\x98\xcc\xfek\x04+\x96f\xdc\x96:^\x98$g\x10\xe3\x0d\xbc$}MP\xce\x16\x81\x11\xe9\xabwQ\x8a\x82\x92\xfc\xeeh\xe11\x8f:\xd9\x1b\xb0\xa4\x0c\xcc\x7f\xe6gUV\x13\xd6\xfa\xc9\x08\xfa\x83\x07\"c\x03<}\n{0\x1a\xc1>\x1c\xc0@\xbc\xd9\xa5o\xfa\xbbp\x00;\xe2\xd5\x0e}\xb5\xd3\x83\x03\xd8\x15\xaf\xf6\xe9\xab\x01\x1c\xc0v\x1f\x86\xb0=\xa8\x1d\x92g8>\x852\xb0\x98\xfev\x19DU!\x7f\x13\x07h\xb4;\x19<\xa4{\xd9\xee?\x1a\xc0=L\x0f\xebH\xb6L\xe5\xa5\xb0\xfe\x9f\xff\xeb\xff4PY\xf40*\xaas{A\xc91\xac_w\xb4\xea\x06\xd27\x0d\xa4_;\x10\xd0\x0df\xa0\x0c\x06\xffV;\x1c\x98:\x1c\xf0\x0e\xdb\x13O\xae\x0f}\xacC2I\x90\x08\xd1\xbd~\xa8`\xfd\x13\xc9\xd7\x0c\xa3y\xa1Wf \xe5qY\xe5}@?t\x94}\x91\xa7l+\xf3[nuS\xb1\xa8`\xb5\x1d\x89\xcb4y?\xe7#\xde\x96\x02\xa0\xd5\xef\xbdD\xab\x01\xa0\xebe\xa7\x85'\x10q0!\xf9\x08\x1dWjt\xf2\xc5\x0cs\xf2n\xb6\"\xa9\x0f\x03\x80\x97\x91\x93\x85\x17\x1fESr\x98\xda\x92\x07\xac\x1aWZ<\xb4\xd1\x98J\xdd{{\x83G\xfb\x80f\xf9OF\xb0\xb7\xbf\xd3\x7fT2\xf8Rp\xa9B\xd0v\x95\x85\xe3)\x9a\xc7\x12D\x06gj\x9d~\xa5N\xff\xcc\x85\xb0pS\xd7\xe6\xd9\xae\xbc\xd1\x9bxh\x89\xa32\x93\xbef&\x83\xe6\x99\xf41\xe5\x85v\xe1\n4C\xa8\xd7\"R]\xaa:\x90\xef\xc3\x0f\xa4\x03\x89]~X\n\xe5@jQ\xdaH\x0d\xf7@fr\\\xc3\xbdtL\x9bS\x82@\xaf\x1a\x0eL\xb7\x12\xa4\x1623\xed\x16\x13\xe3\xafl\xb3\x1d-\x91\xeaq_\x93\x83\xd2ZqV\x83\xbb\x9d\xd9*F\xec\xc06\xde\x94\xa8X\xb1#\xec\xd1B\xb1\x1a\xb5\xf8Qj\xfa\xb3\xf6\x83\xe3\x1a\x86_\xc2\xb4\xb0\x81f\x05w\x87j\xda\xadtP\x8b\x1d\xf9\xa0{.\x02X\xc1\xd4a\x036\xac\xcc\xcc\x8e\xe1|\xa8\x07\xc6\xa2\x86yj\x82\x85\xd4\xb0\xf8E\xca\xd1\xdcX\xc6\xc7\xa8d\x1b\xe4\xa7\xf5\xc2\x7faq\x9b\x9fA\xb9`\xa8\x80\x1f\x97\xcdU\xdd\x9e[\xed\x7f\xbfHB\x87\x9e\x989k&\x98x&\xe7\x18:\x06\xd9\xba\xf12u\xbd\x84\x02>\x1e}\xae\x9a\xdeJ4\xb2\xbd\x8d\x83\xa1\xab\xb7=`bv\xdd\xc0\x90\xb1\x92F\xe6\xb4\x1e\xc3\xe0\xf7\x1f\x03o\x0bC\xef\x8cD\xca\xbc\xf2\xa8v\xf4\xa3\x12\x9d\x97\xb7\x8f\xd9\xb0\x98\xe9 \xcb[\xbeJ\x15E\xb8~\xf5\xeb\xca\xf9\x16V\xa9\x8c\x1c\x9e\x01\xb6\xc1\x0e+\x94[\xbf1\xb4,x\x8f\xf9M\xeb\x86FKL\x1bFR/\xd4S\xcf\xf2v|\xa2!\xa4\xfaq\xd5\xf3Bw*\xa0(+p\xeb\xe1\x14bLy\xd2\x92\x04\xa3\x9cR\xb7\xba\x99)e?/^\x17\x176\x035y\x1f\xcfq\xae\xcf\xcb\xac\xd1\xae#\n#\x04J\xd9T\xca9\x13\xa2j\xda\xf0\x92\xc9}n\x8b\x91\xc6^\x98\xcc\xa2x\xc9\x8c1tn1\x18\x17\xfc\x9d\xa8\xd7\xc2r\nT\xaeY\xe9E/T\x85\xdd\xbcV\xbd\x1fG!\xb5\xe1y3\xb90\x0bi[qY\x1c3\x06\x0e`\xcc\x06\x85\xd0\x857\xb9\x14qj\x96Y\x90\xfa\xab\x80@\xea/Ib\x8cw/\x06\xb2\xc8\xc2\xcb\xdcG%\x1f]\xf1\x86\xa7\xec*L\xadx\x1aWW\x93O[<\xe2\x80apl\xe1}\xe0+\x86;\xb6_ k.\xecc\xe1 \xf8\x9a\xa8\x1bEW\xb6Z\\\xe9\xf1\xa6\xb0\x01\xd58\xdd\xd1\x8e%\xc4\xd1\xd9H\xcak\xae\xaf\xc1\xc1\xc8\x82]\x98\x8a)\xe8kk\x14\xdafZ\xa9|\\\xe8\xad\x97t\x0154\xd5\xa4P\x1e\xb5\x89E\xf2\x89J\x06O\xc5\xbb\x91\\\xc3\x9cgd\x16d\xc9Bj\x80\xfd=\x12%\xc2\xe4\x1e\x0d\xb6W1\xc9\x1d\xf5\xb2&\xbd\xa8\x8e\x9d\x12\xbe\x18e<\xd3\x8fL\x1a\xcd\x81\xfcW)g\x9a\x96\x19\xf3r\xdaZ^\x14\xcaDz\x9c\\\x15\xfb\xa7~\x1e\x9e\x89\xeb+\xdd\xa4hLH\xabLB)\xb1`Z\xc4\xba\xaf\x84 \x10\xe7e\xe5\x9e\xe3\xc8\x0b\x02\xba\x0d\x8bE\x9eF!\x81\xab\x05 \xe1*\xcf\xa8\xb45\x82\x9e\xa5\xe9?U\x89f\x89:n\xd8]\x92\xfaAP\xdajj\x979d4\xbe\x00\x85\xcc\xe6W\xf2\xaa\xb9\xd2;;b\xdcJ\xb4adw\x99@\xab\x93.Q\x90\xdc\xe9\xa9\xdc~\xc5\x97\xac\x18yy0\xa5\xfd\xd6$(T\x00\\|m\x080c\xec\xb6*\xc9\xea\xbb,{\x9a\xd5\x9d\x99(\x9b\xc8\x07\x0c\x85J\xe9\x10J\xf37\xd2m;qa+V\x10I/\x1e\xb5>r\xecXY#<_\xbe\xd0\x89sc\x04\xb1\xeaYP\x7f\xa9R\x0b\xdb\xdc\xe7\x84\xc8\x10\xc5[\x04\x01p\x16B\xb8\xc4\xae`\x0c&\x95\x81\xe9U\xb8,[n\xd4\x15M\x16\xfc/\xe9\x96\xb9-f@\\\xdd\x06=#$Z\xe6i\x90\xf93\x95Q\xac\xb6\xa6l\xb1z{\x0c\x96{=\xe4D\x969\x90\xab\xc4]!.\xb7b\xb5%\x9eZ\x97\x89\x17sH\xcaBQ\x14\x1f{\x93E\xb9\xa2\x94\xe2|\x12\x93\x12.\xb4K\x8b+\xf0*bDSKU\xb9\x0din3\xda\x04@Lgz\xef\xde\x06\x8c\xb6\x9e\x15DK\x97\x10\xbd\xd9\x1c \x18\x04\x10\xd2qxV\xa9|c\xf3\xb4\xb8\x18\xc9X]+\xb7\xa4h\x84\xdb.\x97\x16\x9e\x0e\xfc\xfd3\x9a\x940`\xc7iZ93\xcd\xf5\xf5\xab\x96\xbc\xf6^\xdb\x98X\x16\x95\x18\x84\xa9/\xf0\xe2\xee\xde=\xae\xad\xd8\xc6\xc4\x0c>\x86\xb6\x1e\xe6\x8e\x95x#\xd4\x9c\x1d\xb9\xd5\x1c\xcb\xfe7\xbb\x0f\x06\x8eM\x87\xc4\x91\xd6K\x12\x7f\x1e\xc2\x10\x8bv>\xd7\xa2\xd0\x05\xdf\xc5Tr.x.\xcf\xe6:P\x13\xa4N\x9aH\x0b\xe8\xee+\xe8#\xe7\xcc\x8f\xaf\x95\xaf\xf4\xaeY\x13\x17x\x08@\xad\x07\xd6$\ng\xfe<\xab\xc9$.\x985\xbdl\xd1\xe4\xc1\xb5\xf6\x82\x8c\x0cA1\x02\x96\xd6\x15&^n>V\x9cN\xec\xcec\"]\xe5\xc6\x15\xc9\xba~\xe8\xe6a\x97\x87\\\x8c\x84\xc55\xd4B\xd1\xdd8\xa12\xa5h J\xa6\xb9*k\xc4s\x06\xa60\xa4\x87>B\x86\xb1\x14\xe8\xa7U\xacR,_\xaa\xe0m\x11\xcfn\xfc\xe8\xa1\xe3b:\xd4\xf1\x19\xcbl\xdd@U]\x9d\x02\x9cr>\xde8=\xcb\x99y\xfaG\xb9\n\x92=\x82\xfd<\x86t{\xfb\xb1#|\\-\xcf\x82\x0e\xd8\x9dN\xe8\x14\x1a\xa8\x9d}U\xae\x97\xf4(\xc2i\xc2\xb6f!K\x98\x8bE\xb9\xc4a\xd3\x06 \x0fq\xef\x82\xe5@\x87\xfe\xef\xef\xa2\x8dY(\xbc5\xf1\xec,\xdc\x06\x1e\xc3\xcd\xe32\xcb\xd8z\x8d4\x14\x1f\xe5\x1b\xc3\x9a\x15b\x8f\xc2\xe7\xe0\xa9E\x9c\x8a\xea\xa1\xba7\xe9\x93\xd9\xe8\nU\xde z\xf4\x07\xdd\xed\xf2\xcd\xe7\x12'&r\xe8\xb2\xad\xeb\x91\xbeTM:\xe7\xe7$}s\x15\x8aj\xcfI2\x89\xfdU\x1a)\xf6\xd3\x99\xe9\x83\xd7\xdeR\x0dh\xe2\x99\xea\x9e^//\xa2 iq2i\xd7\x98\x91`~4\xc76Q\xf1\x14\xe5D\xb9\x06\x86\x18\xc8\xec\xc4\x11\xccN!~kC\x0d\xeaW\x1a\x9b\xb6\x99\x87M\xc4\xc2\x14j\x14?\xf2\xd2k\x9b@\xee\xb2\xfa]\x19\x81L\xaa\x0e\x0f0\x82\xdb\x7fY3\x91\xed{r ]/g\xffS\xb9\x95\xcf\xdc\x15}\x1d\xff\x1b\xda\x0fUUs\xa4w\x03\xa3\xdc\xe9mq\x94\x9ek\x9a,xt\xfb\xe4\xc4n<8\xd3B!Fj\x85\x0b$w\xc4\xd8\x10O\xb7\x1a\xe18>C\x07'\xe1H\x91\xa1<\"\xbe\xa8\xacH\xd8\x00g\xb9\x8fv\xfc>\x1f\xfa\xd6\x16W\xf6\xb1\xf0\x03\xe5\x14r\x9f>\x19\xb4d\xc8\xd5\x9b\xf4\x83\x0b\xd24\xdaVX\xa1\xe7\xa3\x88\x0b\xd6\xf99I^E\xd3\x0c\x0dN\xd4\xa5D>G\x16+Yt!/N\xc8\xf7\xde28BnE\x93\x16\x7f]D\x88\x0e\xed\xbdAO\x83q\xc8\xfc\xb0\x80\x0dq\xb7\x18\x04\x1c@\x0cC\xcd\"\x0bSS5\\p\xd1\xa9n`\xb5\xa8\xaa'\x0f|-#\x91\xe3\xaf\x9bx3\xf2M\xe4M+ \xacjID\xce3\xb1\xd0\xc8q|\x88\x03I\xba!\xb9zG\x89@x\x1c\xc7v\xa1IB*\xad\x1c\x97\x1bz\x916\x11\x84\x9d\x87\x06q\x88\x8e\"\xb6\xcbs\xf0\xc3I\x90M\xc9\x10\xc6\xa1=\xe8\xed8g\x12\x12\xfcC\x07\xd3\x1f\x0c\x9c3\x85\xb0-W\x81?\xf1S,\xdf\x1b<\xc0P\x06{\x83\x87\xfc\xdfG\xec\xdf\x9d\xde\x1dM\xe2N7S\x10y\xcc[\x99t\xdf\xbd\xf9\xea\xabo\x8e\xcf\x8f\xde\xbc~\xf1\xf2\xabS|\xf5\xfe\xed\xf3\xc3w\xf2\xab\xda\x9d6\xe8\xed\xfdN;-[M\xbd\xaa\xf6\xd2@\x165\x07\xf3\xf5\x8a\x0c!\xab\x9e\x10+\xef\x9a\x02d\x08v\xcf-\xb6\xa0c\xff\xfdF\xd5\xe2\x02(\x9a?\xd2M\xa3\xf9<\xa87\x0ej\x18\x91&\xabJ>\xa2\xd4\xd4uy12\xfd\xbaYL\xb2K\xce\x19\xe4\xac*\xaf\xa8Y\xff\xfc#63K^\x81\x1cod\xad\x89n\xaeU\xad\n|\x1eA!2\x12\x8dJ\x0ef%l\xec\xef\xa9\x0c\xc8\x97\xc2F^\xa7\x85b'\xa7\xca~\xc8\xe2:\x94\xd1\x8c}U\x1d\x04\xdf\xbca\x83\xae@\xa3i\xd8H\x17\xa1\x18\xac\xa0\xa9\x16\x8b\xde\x19\xba\x9br\x87\x94\x1a\x10\xf9\x1c\x18\xdeQy\xa1\x8f\xb7\">\xdd\xd1\xd6%\xb9N\x90\x91&\xdc\xa3\xc2\xc2\x1d\\\xbc\xc3\xe47C\x16\x14w\x1c\x9e\x9d\x95t.\xa22\xdeZ\x1e\ny\x05%\x0c\x0e\xe9\xd8f]\xa0\x91\x86T\x1d\xc3\xd0\xa7\xb1O\xff\xd2\xe2O\xa3haT}7~\xb9\xd1\x01\xcc \x9a&\x18\xde4\n))\xda2\x1ew\xb7\x1c\x9d:4\xbf\x1cJyK\x96\x87\x98\x90\xfc\xeezE8o\x0c\x1d\xb0\xc4\xed\xaa\x977\xbae\xba\xafn\x18\xec\x86\x9b\xf8\x91~\x0f\xef\xedj\xb7\xf0#\x95\x05\xcbP\x18.\x1a\x0e\xed\xc1\xbecg\x94\xf2\xec;\xb6\xe5\xa7$\xf6\xd2(\xa6\xe8\xd3t\x94\xa7r\xf0\xb2\x1b\xa7F;\xa8\xbb\xba.h&\x8c \xa6#\xa8\xe2EH>\xa6t\x13i\x12\x91\xd3\xdd\x80m\xe3b\xbc\xcc\x87\xbd\x19\xb0%\xf5\x84\n?N\x1a\x1fh\xc1\xba\xdb3\x93\xc0=\xe9\xea\xa3\xc4\x94\xfb$i\xca%\xe8W\x14\x9dEf-\x17\xd7.B}\x04\xe5\xd02N\x81\x98\x06\xae\xf7\x18\x85\xbd\x07;\xbb;\xbc\x7fV\x1f;\xa2\xc8\x82\xce\xdf\xf4-\xf3\xc2L\\\xecd@\xcb2\xd8\xe6\xcdt\xe88\xb7\xf9\xa0\x9e<\x81~\xcf\x81\x0e\xec\xef\xed\xed\xec\xdf\xcd\xa6\xaf\x1c\xa9\xfc\xe0\x18\xf4\x8dg\xea\xc0\xe9\xceI*\x0e\xf9\xe6[Y\xa4\xf3\xeaIjd\xf1H\x03\x8b\x87<\xd1E@L\x0c^l\x13n{\xe4\xdcz'\xf6w\xf4\xd7#\nOV\xa10(\xa4\xb5\x03\xdb+\x92.\xa2z\x034\xc9\x8dl\x0b\xa3\xcd\x0b\x9a:\xf6\xcf0\xc0\xc5\xd8\xfa\x97\x7f\xc9\x87\x83\xaf\xa21\xa5Ng\x9b\xcd\x9b\xae\xf6\x0eJ\xbb\xfd\x1d&\xf5\x0evv\xf9\xbfLM:\xd8ej\xd2\xc1^\xaf\"\x0e\xf7\x1f9B\x14o\xd3Y#C\xad\xc3G\x99E\xf6\xc7\xa1\xddwlK\xdc\xc6\xbf\xf3\xe6\x96s\x06#\xb0~\xc1L\x8d\x1d\xba\xcf\xb7F`\x8d\xd9E\x0b\xfcrf1\x1d\xc1N\xcf\xe1VK\xa5\xe8\xbd\xa2\xa1\xba\xb0\xdd\x1c\xf2y\x9b\x16t\xe89\x80\x01L;`\x9d\x95\x9c\xe3\xb6\xda\xe9\x07d0n\x85\xf6\xee\x80%G\n\xed\xdd\x1d\xc7\x1cx\x8d\x8f\xe4\x01\x9d\xa2^\xd7\x1c\xda\x8f\x1e9\xb65\xf5\xd7Tl\xb0<\xad\x19\xccF\x81\x86\x1fT\n\xd5\x9b\xcc\xaeW\x00\xa0\xd5\xe4%]\xbf\x89\xd0\xd4\xb3\xe6\xe8\xaa\x81'\xb1\xdeV\x813\xe9~\x95\xea\x10\xd3\x95\x9a]\x8e\x13\xc0\x96#\xe6\xb1\xc7\x05I)|\xd1j\xe9\x99\xda(\xca\xd4of\x9b\xb7\xb9\xf5e\x86\xab\x92X\xeb\xc8\x0b\xff\x94\xc2$\n\xd7$N\x81\xa3y\x1a\xc1*\xf6\x97>\x06+\xc4)l*\xd25m\xf7\x81\xe1\xfc\xe9\xef\xe8%\xe8~O\xe5_\xaa\"t\xff\x01\x17\xa1\xfb\xff\xaaE\xe8\x87\x86\x83]}\xcf\x01\xbb\xab\x03,\x05x\xcf\xb1\xad\x97\xc7\xe7oO\xde\xbc{\xa3\x1ez\x9e\xaa\x9e*\x17\xab\xda\xab\n\x15U\xba/F\x8c>?\xf9\xe1>/b9FxXV&\x1e\xa7\xdd\x17\x8f!F\x8b\xb3) HJ\xe4\xac7\xe3h\x1c\x9fir\xa6\n.W\x8d\xed\xaa\xa7\xa3%c\xe5rP\xc7v\xa6b\xbc\xbb\xdc\xca\x1d\xefF<\x05\xdd\xd1\x80\x1b\xd8\x0d\xad\xe7B\xb9\x98{\xe3\x8c3\xb4'\xc6\xec\x93hzVX\xc0\x8c$}\xac\xcf\xb2\x19\xdf\x16\xf1\xf7\x0c\x14\xc5\x80\xf75\x1c\x1b=\x92\xff5(\x8f\xf6\xf4\xa4b_wEG\x99\xc2\xbeco\xb5\xa3\x16\xb78\xd99\x80<.5T\xe9\x00\x82\xa8\xfaz\xc2\xcc7\xab\x10Gsv\xcfaJ\xa2\x8c\x19Z{\x08\x8b{\xf7`\"\xfc\xb44\x1f>\x96\xa3@\xe1j\xe0w\x94,\xe0Z\xb0d!\xff.\xb2'\xd8\xda\xa7OEk\xfa\x05\x9a\xdcv\x81vM<\x12\xb7\xe3\xb3~\xb1\x1c\xba\xe1\x90\x01|\x99\x1c\xe7\xf7\x8ev\xaf\xc0\xe0\x12\xc2\x9a\x18\\\xce\nS.#f\x96\xec)&\x10Km\xcb\xa2\xfb6\xb7\xfa\xbf\xedT*H\xc5pmWg\x9c@ \xb6I\xb5\xdb8\x95\x92^\xe2\xdf\xf4\x94\xff\x15\xe9)\x0d\xe4j\xb0\xa3\xfa\x1dD-8\x18\xc9j7?\xb1j\xcf\xd19I\xdf\x8a\x8aof\xf5A\x92s\x90pZF\xf7\x94\x0b\x11n\xabqt\x06C\x93i\xdf$\n\x934\xce&i\xc4r\xe3\x83\xe4\xb7_.=(\xff-\x1d\xbb\xc3\xf2g\x9c\x08\x1c@\x06\x8aG\xf3\x86\xe0\xef\xdfzK\xcaV\xc7\x9b\xf5\x9e\x1f\x9d\xc2w\x07\xfdH\xf3\x03\xdc\x15\xda\x97\x9e\xe3\xf2\x93h\x8f\x1f\xad(\x0e\x08\xcf\x94\xdd]\xc7\xc5\xfdLe\x03\x177\xed\xa4,\"\x04\xecUI\xb9\xc0\xf2\x82'\xe2~wQq\xcc8:==\xc9XN\xbe\xaa\x19\xc7\xd1\xe9\xe9)eH\x9f\x93I\xe0\xc5\x1e\x9da\xd5E\xe3\xe8\xf4\xf4\x03\x15\xafx\x13ji\xe0\x930=!\x93T_\xfe\xfc\xcd\xab\xdaB6\x17c\xf1\xbb\xe8\x92\x84\xfa\xc1?\xf7R\x8fy\x11\x92\xf8eJ\x96\xfa6^\xf8\x81a\xe4\x7f~\xf7\xea\x9b\xc3 8\x8a\x82\x80L\xf4S\xa7U\x9a\xca_D\xf1\x92k\xbb\xf5\x15N \xfd\xdeX\xe5\x15\x99\xfa\x9e~\x86\xaf\xfc%\xa1b0.n\xf5\xcb\xd7\xde\x92L_GS\xf2\xca[iJ\xa3\xa9a\xd5\xdfz>]\xb1\x9f3\x92\x18\xd6\xe5m\x90\xcd}\xcd|\xd9{\xc3pN?|\xf5\x0d\x1eC\xfa6O?|\xf5:[^\x90\xd8X\xfc\xd6K\x17\xa7\xc4\x80\x0b\xb4<\xf2C\xc3\x80O?|U\x87H\xa7\x1f\xbe\xca\xfdM\x0d5\xa2,\x9e\x10\x16z\xdeP\x83n\x94\xd3\x05!\xa9\x1e\xaa\xef\xc8\xc7\xf4]\xecM.\x8fL[%\xafa(\x8e\xb2I\x0e\xbb\xbc\xe4\x86\xa5\x0b\xf7m\x0cY\xc98\xf05<\x81\xa9\x904a\xdd\xe9\xe8\xf8\xd4k\x17\xe60\x82\xe9x\xad\x18\x9d\xd2g #X\x8c\xe7\x9a\x92sd\xe7u%\x170\x82sJ\xf1\xcfu\xa7\x11\xf0c\x18\xdd\x89\xed\x0bz\xf6~\xfa\x04\x9e}\xe1\xc2\xcc\x85\x95\xe3\xc2\xc58(\xde\x05,\x07s2\x9e\x9f\xb1\xe8\xbaK\x8d/\x03R\xd6kz\xa2\xc7\x0e\\\x8c\xaf\x99\x1a\x99~~\xedB<\xbe>+\xf4\x99\xd0\x96Z7*}\xb4>9\xf4\xbd\xe1~_\xd5\x05e\x82\x954In\xfd\x9d\x07\xfff\xf9\xf4_\x8e\xe5\x93\x99\xd7pl+\x0b\x93I\xb4\xa2\xd2L\xa22o\x1a\xa7m \xdf\x84f\x01\xfcq|\xc6\xae\x00\xfa\x0f\x1c\xdbG\xef\x8f\xbf\x9b\xf5{\x15I~\x1c\x9f\x8d\xd33\xc5\x89^;\x11\x93~\xbf\x16\xf5\xf8\xa2\xea\xc4\x93\xbb5\xc4j\xbfMe\xb7^\xbe\xa1T\xa6;\x11lV\xe9-c\xae\xf6U\xab\xa8\x19\xbe\xae\xdc\xed\x04\x8ckS\xde\xae\xd8[U\xc3\xb0`M\xab\xaf\xa7\x9ct\xa8\xd6\x91k\xf6~W\x1d\xca5\x17,\xd5^\xe7\xfc\xfd\xae\xd3M\x88\xb2e\x97\xbc\xad=\xc7V\xbe:\xe7,\xb1*\xd5^\xf0\xd6T\xf8\\\xf1\xf7*\x01\xfc\x88\x1cf\xae\x8fW\x8eE\x91\x0c{B\x12\xc5\x91\xf0\x18\x8b\xf8\xfd[\xb9\xe8\x10F`\xf1\x8fp\x87\xcf\xecS\xa5\xd77\xf5\xea\xdb\x9f0\x92\xde\x08\xce\xbb\xb3r\x01\xa5\x84[[\xf5\xaa]\xb3\x7f\x9d\xa0\x8e\xc7\xdd\x98$Q\xb0&\xb6\xba\xa6\xf2CX ZY\xe6\x19\xd1\xdd\xcb\xaf\x01\x93\x15\x99 a9\xab\xdd\xc3\xea\x93\xdao\\xc\x96v5\xd9\xfaA\xb2\x0394zl\xf1\xa58!?1\x86\x163_\x8a\xac8\x0b\x12\xdao\x1cY*\xab\x8a\xe55\x1e\xb27*\xf6\xbdl\x9c\xf3\xba\x9aX\x05\xa4s\xc4\xde\xc2\x98\xaf\xe5\xc9\xe4w\xf1,p)\x0e\xdb\xc1)\xa8\x89\xb4J\x7f\xbej\xa2s \xae\xb4\xd2\xee\xb9Q B\xcb\x14\xc7\x01\xf9Y\xe7\xe1\xbc\xcf'\xfa\x1a\xcb\xe6\xa4U\xa0J\x94i\xf7|\xcd\xe4\xc9>.e\xf7\x1c\x00\xe9F\x97\x18\x94e\xe6\xf9\x9ahc\xea\x93\xe0\xc5\x03\xdf\x1b\xcd\xd5'\xbc:E\xb8\xe6\xda3\xac=\x8d\x96\x9e\xdf\x94 \xc4\xb8\x81\xe5\xc7c\xc1.>}b19)\xec0\xdc\xd8[\xc6E\xd1\xbfF\x18\xa4t\x8b)\xf9=d=Fh\xedoc\x0e\xadY\x97\x84)\x89m~\x81\xe0\xd91\x8a\xe6\x94\xc5\x9du\xc9G?\xb5\xb9P\xbf\xd5sX\x1d\x8c\xb4\xb3\xe2\xe6\xff\x070\xb1?\xda\x16\xdfw\xdb\x93\x85\xe7\x870\xb9\x9e\x04\xc4b\xa1\xea\xe9:\xbe\xb4)\x06\x1f\x087\xd0\xd0\x85\xc4\x85 -N\xb0d\x08\x13;6S\x03P\xf7e#Xp\xfc[\x19\x9f\x1f\x9f\xc4\xc4\x94f[<75\xf4\x08\xc2B\x19\x1d=v \xb3\xc3q\xd4\xe9\xe8\"\xc8\x8a\x87n\x12\x1e\xe1&p\xd4p\xad\x9a\xde\xde6\xf6\xb6)\xfe\xea\xb1QF\xac\x1c\xe8\x7ff\xaba \x9c\"\x1c\xa7\xf2\n|\xb9\xd8)\\\x83Rm\xd0I\xa0\x12\xddS\xad\xb7~\xedJ\x9d4\xc2n-\x05S\xab\xc2\x85t\xcf1S\xb4\x8d?X\x184\x84\x01\xe9\x9e_\xd1\x02\xe2t\xcf\xd7,F\x1d\xe9\x9e',{\x04\xe1+l\x13\x86y\xa4{>\xe1\xc6\x94\xf4\xa0xe\x13\xd4]\xd4\x8e\xfcu\xbb\x91\xbb\x86\xc8g X\x9a\xb0{\xae\x0d\x05\x0f\x18\xec5\x9f\x14\xde\x90\xf39\x19\x8e\xdf\xfac\x17\x03M\xb2\x00\xf6bc\x15\x87\x1fL\xd0\x88\xe7\x82\xeefd\x1e\xa6\xe0\xa7 f\xaa\xa9\xa4\xfc \x9c_\xa2%\xd5A[\xe6 $!\xbd\xf9,<\xbf\xd2zGV\xaaM\x87\xba\x84\x82\xf2c\xe0\xca\xc5\xd3\x8ec\x11\xe6\xa1\xf4<~\x8d\x07L\x1f\xcf\xe6\x13\xfe\xfb.\xd9\x80\x93\"\xf3\xed\xadO~g\x88y\xc39\xfa\x87\x0c\xfd\xfb\x14\xbfC\x17\xb6L\xe3m7N>\xbe\xfa\x89\xb4X\xbf\x86\xb5\xbb1\xce\xbf:o\x85\xc9(V\xfc\x12\xf7\xfaq\xed\x86\x9d\xf2\xa8I\xc7.\x88Ma\xb9`\x9d/,\xc7\xc5t\x14\xae\x1c\xd5\xbaU\x14\xa3\xd4F4a\xed\xe6\x98\"\xfeT\x88K-\xd0O\xca\xf1\xb4\xcb_\xe6\x7f\xdd\xb8\xec\x107O\x92\xa9\xf9r\xce\x0e\xff\x92O^\xf6&\x91U\x97\xe5l\xe5\xebJ\xe5\x85\\\x991\x8a\xc5\x80\x9c\xb2-\x8f=\xd8\xddw\xecc\xd9\x86V\x1d\x1f [\xc4\xfc\x16\xa2\xdcO\xb6\x88uu\xac\x0b\x97-\xac\x8f\xa8\x0c5\xd2\x8a\xa9\xec\xca\x19\xf7\x06\x15\xb0\xca\xb5F\xe5\xd4\x83\x94\x92s\xe9\x07\xd9\x18z\x16\xf3?\x87\nL&R\x08_\x0e\xe3<\xf0\xa8\xa7\x96a*\xdfW|\x1e\x98\xb8>\x14\x12Jy\x9d\xcb\xfb\x08\xd1\xa5\xce.\x03\xca\xd6\x89L\x85\x90\x8f\xd3\x88C\x8e\x12.\xcd\xa4\xa0\xc6x\x1a\x8f\xab\xd8%\xb8\xc2\"];?Q\xf0z\xf45\xc6[\xc8\xb3\xf33&\x05KNx\x89\x8c\xcd\xe7]*s\xfe\xd4\xe6\x828\xc5\x93\xed\x18\x97\x13\x7ff\x94\x83\xe6\xc1\xe9Q\x8d-\x1b\x9e8.\x04v\xd0\xfd\n:\x10t\xbf\xc5\xff\xbf\x80\x7f\x86\xadK\x15!\xdf\n\xa6\xe8\xb8\xf41\xb3&\xb5eZ\xc1\xad\xdd\x1f8\xb6\xfcJD\xa3\xcb\x0d\xddY\xc7\xa7\xa5.%z\xa3\xce\x8d\x82\xa7i\x91\x05\x83\xf4\x93\x8e2\x81\xa4z\xea\xb9\xb9\xb4\xef\xb0\xe8\x9bzD\xab\xc0\xa9\x18\xae\x8dl\xd3\xd6\xa5S;j\\\xef\xa6a\xf3Q]\xd9\xf9\xe6\xc8\xd7\xed\x98'\x93i\xc0S\x05\x92\xf6%\xd3\xd4\x0fv\x1fJV\xf0\x95\xbe\x8f\xbb\xcc\xc0\xb9\x8b;\xc8~#\xa3E\xdd\xb4\xbc h\x9a\x92\xcc\xaa\xeaO=F\xb5L\xf6BxsQ\xaf\xbe\xf1y\x15\xb3\xca&j/\xa9\n::\xd6\xdc'\xcaO\xa4\xb7\x9b\x93\x1f\x8a\xe8\x86\x14\n\xf4YSZN\x8f\x91\xf6zV\xb4\xb0\x82\x11D\x9dN3\x07\x98\xd4\xa4p\x10O\xc8(/#\x81tov:n\xa1-\xa3\x18\x81$\xb2\xfd\x08\x01;\xa6\xacE\"\x98\xf4\xb1w\xc6(\xdf\xf6vFKb;l\xe2\n\x8dB3p4\x97\x9a\xd2\xd6\xbb1o\xf9\xa8\x8bG\x97oG\xddu\xdb\x83%\xf6&\x8d{\xf7\xae\x10\xdd\x8c\xc5\xfe\x06X\xbc9nUW\xbd\xd8vP\xa3\xcd\xd3\x88\xb7P\xbf\x02>[\x81\xd8\xf6\xebV@\"A\xf8\xf3V\x97\x83L\xe9\xa5N\x9dgp)\xdd\x1c\xa0\xda^\n \xc84<S l\xc4\xe5\xb6\xa6m\xef\x97m\xe2\x81\x8d\x9fIN\xb38Z\xdaQ\x83\xad\x0c;7\x07F\x90\xe8ma[[\xd6\x17\x01T\xb6\x8a\xb4\xe3\xaa\x86Y\xe8\xcf\xd5\xf7z~A\x02\x9c\x9e\xd8\xa0g\xbf\x06\xa6\x90\x1f\xb9MP\x85:\x9f\x00\xf10\x0f\x80\xb0\xba\x00\xe2\xd1\x9cj.\x0el\x83\xee3]\x1b\xa9\x1d\xd5\xdczk\xe9\xfa\x9d\xa4\xa9\x90\xc8\xa5\x9e\xcbV=\x00\"-u\xe2\xf4\xa6\xa2.\xe4~\x0e\xbb\xfb\xd2\xba\xc5v\xdc}\x0b\x1d\x88\xbb'5wJ3?\xf4\x82\xe0\xba\xad\xba=\xe3\xb7\xc4~\x1e\xc1\x9aJ\xc2\xe2\x0f\x83\xae=4\xddjk\x98\xdd\xca}q(\xab&\x8d\x96\xd7\xfc3\x8fRGT\x84\x95/R\xea\xf8\xab\xca2\xcb\x8f\xce\x9a\x8c\x8al\x94\xad\xf8\xc2\xe3\xe2 u6\x1a\x96\xf9\xae\xf2\x0b\xa2n\xc5\x7fD\x84?\xd8S\xb0\xf1\xb4\x06\x0f\xd3\xb85\x0e\xd2C0\xd5g\xe0\x86<\xd1\x97\xce\x9eV\xdcB\x87]\x82\x86\xed\xfc\xee\x7fX\\\xc68v\x88\x97$\xcd\xd7\xd2m\xe0\x19\xda\x83\xbd\x01\x8f=\xb7\xc3\xff\xdd-\xc7\xaa\xdb{\xc0\xff\xe5\xb1\xea\xf6x\xac\xba\xfd\x1e\xff\x97\x7f\xbf\xcf\xbf\xdf\xe7\xb1\xed\xf6\xf9\xf7\xfb\xfb\xfc_\xde\xce>og\x9f\xb7\xf3\x80\xb7\xf3\xa0\xcf\xff\xe5\xed=\xe0\xed=\xe0\xed=\xe0\xed=\xe0\xed=\xe0\xed=\xe0\xed=x\xa4\x8d\x9d\xc7|j\xdb\xc0\xa2\x11\x8b*\xbeNQ\x1ep\x13\x8f\xe3#\x1e\xae\xb2J\x10\xe5J\xd1\x94\xa0\x17\xb0\x82xH\x06\xd1z`\x8b\xd9\xb5\xf71\x9eJ\x1e\x16#\x8f\x1dR!\x8fr\xa3M\x08\x9a3\xb4\xdc\xe4r|\xe6\xe2\x9c\xf3\xccPy\xa4\x9c\x8c\xf9\xe9\xc6\xf0\x142\xb3v\x80g\xb9\xeb\x14\x99\xa52\x8c\xa2\xe3Sj\xd2\xef\xf7w\xfb\xfd\xbe\xc3r\xf7\x8a;\x91\x13/\x9c\xf3K\x11R\x8e-\xbe\xf6\x02\x7f\n\x93hJ`E'c2\xab\xe4w\xd4\x04\x9e\xb0H\x9dp\x80\xb1~0B,\x8b\xe4\xd9\x01\xdb&\xb0=b\xe5\x0e<}\n\xfd\x1e\xca\x14\x7f\x84~o\xb0\x0b\x1d\x16\xffS\x97|\xcc\xb4'C\x9eSP\xcd\x9c\xbb\xe1\x8ek\xc22CT -\xa52`D\xec]\xb5\xc7\x03\x16;\xa3\x1b{W\\\x10\x8d\num\x1dnP\xcc\xf1\x18\x8e\x84\xf0\x14\xbc\xc7\x0edl]x\x08Z2\xf6:\x9d3\x07\xe3D\xdc\x87\x9eF\x8a\xb0\x8e\xa2,L\x0b\xe7\xac\x90\xcc\xbd\xd4_\x13U|\xe0\xc1\xf8\"x\xaa\x1ar\xf1\xc7\x8e\xe0\xe9\xd3\xa7#\xe8;\xdc\x9b\xb53B\xc3#zb2\x07\xd7\x90\xbdz\xac\xac\xd3\xef\xa7\x84\xdb\x948\x17 \xda\x9a6aQ\xb3n\x1b\x16\xb5\x9a6\xa2\x8eD\x97\xfa\xd0\xad\x00\xe2\x88o\xe7\x84r\x93\x1d\xea\xe6\xe1DM\x99/\xe2[\x10\xd6\x18\x97\xad \xac!\x15\x92(\xec\x84E\x0b%\xac\xf1g\x11\x07\x93dBW\xc5\x0b'\x8b(\xdeH2\xa9\xe5\x06\xf9b`\xd4z+\xf4\x96\xc4\xaaK\xec\xf9\xd9\xc3\xbf\xf0\xe7\x1b\x8d\xbd\xcd\xd0Y\x9b\x16\xfe\xf7\x05G\x1e\xf8\xe1\xe5\xdd\x8f\x9d\xb7\xfa\xc5G\x1f\x05\xd3\xbb\x1f\xfc\xef0\xf0\x99\xff\x91\xdc\xfd\xc8\xd3\xf4\xf7\x18z\x14\xa6\x93(\xf8\x12\xbb\x956MG/\x9a\xff\x82;\x96v\x95\xf8\xbf\x90/7 \xde\xfa\x17\x9c\x83\x9fz\x81?I6\x9aB\x9b\x19\xf8\xbf\x03\x16mLvZ\xc1\x1e\xc9\xfd\"&\xb3/\x0b\xf8d\xe9\x05\xc1F\xa3o3x\xd1\xea\x97\x06=}}\xb9\x19\xe2\xb7\x1a\xbeh\xf6\x8b\x8f?\xbb\xb8\xfb\xc1g\xbf\x07\xd5O\xb2\xd5\x17\x18\xf9\xea\x8eF\x1e\xda\xfb;\x8em-\xbdt\xb2\xb0\\\xe8\xd7\xd7\x96\xc62\xce\xebi\x15\x9dz\x88\x88GH\x02i\xddE\xa2/+\x1aP\xcf\x90\xe7_\x0b\xc7\xc4\x9c\xdaB2\x9b\xf7\xe1@\xd8\xd81\xcf\xa8!\x9a\xb7q}n\xe8\x8c\xc9\x99P\xd8\xc7\x95X\x1f\x10n\x9a\xd5\x9f\x03\x93\xeb\x14-\x17\x06\xb7\x00g\xecV\xdd.\xa0\x15D\xa3&\x88f%\x88\xc62D\xe3\x96\x10\x95\x04\x88\x18C\x95\xf9\x08T\xf6\x86\x832rX\xe8\xa5;\x03hB\xbc\xf8\xdf\xd0\xf3\xce\xa0\xb9\n\xfcT\x8b\x9c\x15\xcbI3\x98\xc4EFh\xf7wUc=\x10z\x8f\xeakv\xb9\x867eU\x8d\x885A\xe3\x14\xcb\xbb\xb8\x98X\x92\x89mYt\x8e\x1a\xa4is\x1d\x02\x92%\x9a\xd0\x01\xe8\x03\x01@\xd9\xd7f$\\\x8bx\x12\x9d\xdc\xceMM\x86\"\x7f\xbb\xe5\xcb\xa9\xd3\x8a\xa8x8:\xfdgkf\xc2\x9f\xb80\xc1p\xd3\x01\x0b\x8b_\xe7u\xbe`\xa1;\xfdy\x18\xc5\xe4\xc8\xc3`}\x96o\xc1\x90\x1ey\xd0\xa1e\xcb,H\xfd\xc0\x0f\xb1hY*\xcaB\x1f\xaf\xda\x0f\xc0\xcaJ\x05I\xeaO.\xaf\xe9\xfbk\xfe\xde<\x84i\xbd\xd3\xfb\xba\xbc\x9a\xb4\xb3\xdd\xc1\xa3\xddG\xfb\x0f\x06\x8f\xf6\xd0\x8e\xff\xe9\xd3\xa7u\x0d`4\xd9b\xbf\xa7\xdd\x04\x83\x9c\xbb\xb0\x80\x0eXs\x93\x85\x00\xaa\xfaX\xf0\xaa\xb8\xdc\x02\xbb\xcb\xbc\xe6\xed\xd0F\xfe`\x1fl\xfd\xf0C\xe2X.,t\xd7\xd0\xf9\x83\x0e\xec\xd7\x0c\x17y\xc0\xce-\xdb\x9e`(1\xd4*C\x07\x92q\xef,\xc7\xf0\xa70E\xad\xe1\x8aG3\xe1*\xa4\xa9+>p\x1c\x17\xb6\xd0h\xbf\xa4\xe0\xc2\xc4\x1f\xbd\xb3\xfc\xe2-v\xebY\x9f\xd2\x83S\x0f0\xd0\x00\x04\xf0\xa4\xaa\xe4\xde\x86\xc1c\x08:\x1dG^\x99B\xa3\x16\xa0\x15\xaf\x8d?FZ\xe5w\xe9\xb9q\xdc\xea\xe098\x9e\x141\x15\xf1\xf2\x9f9\x00\xad\xe8\x07\x0c\x12}\x87g\x89\x90\xc0\xc6b\xc5O\\X\xe5\xad\x8e`\xed8\x8f\x1d\xb8\xee\x06^\x92\xbe\xc4\xb6\xf1>\x83\xf7s\xef\x9e\\\xa4\xc6\xf4\x16\x0f\xdf\x8cSv%S\x84\xf5\xde\x9a\xb1\x06(\xc9\xc4,<\x9f>\x01_1\x96\x93G]>:\xe8bp\xb0\x86\x03X\xf1\xb2\x9e\x0bk\xfc\xa42\x02\xc5,\x99\xb9*X=A\x1a\x85\n\xb3\xe7H\x10\xb3[Q\xb6\xf2\x99\xa9\x92+8\x80\xf1\x19\x0c\x05\x0d\xcau\xb1\xaa\x14\xa8\xd7iK,\x82\x81\xe5\xba\x05Su+>@b\xaa\xc2\x82\xa9\x8a+LU\xa8c\xaa\xe2M\xd9\x80z\xe5|f\x87\xf6\xe0a_U3\xfb\xbchg0P\x8b\"^\xb4\xd7\x7fHIL^&\xc6\x80A\xf1\xf5\\\x1a.f\xda=?'\xc9\xabh\x9a\x05\x18G\x1e\x86\x9a\xa5\x98\x92\x99\x97\x05\xe9P\xbd\x9f\xff\xa7\xea/q\xd2\x8e\xfd.\xff\xca\x85\xa8\xf8i\xa46|L\xd5\xbe'\xd1r\x15\x85\x94\x80\xe8F\x06\x98{B\xf8.}\xe3]GYJ\x17\x8fw\xd8\xb4Y\x8a H\xa8\"_Ny\xb7_S}\x8eW\xe2\x82U@\xbcr\x0b\xc2\x03\xc7\xcb\xe1\xea\x9d*\x9aLl\xca\xf9=\xd4\xa1 \x16\xed\xf5th\xc2\x8a*\xc8\x95\xe5E;j\x91\x97\x17\xed\xabEI^\xf4@>\xda\xf0\xd5\xfe\x9e\x1e\x15'\xbf?*\xcej/\x18\xf3\x91\x91:\xc1\x9f\xd2\xde\x1c\x9b\x1dN\xe8\x88\xe3bA\xa6\x16\xd8\xa4{~\x8e\xce\xe7\xe7\xe7\xc8&\xf4\xdc\x02\x1f\x1d\x9b8\x0e?\xadX\xf5\xfcxTE\x0c\x1d\x98h[\x9e\xd4\x96\x0b)\x1fFTz;\xae\xce\xe5\x92\\\x0f\xc1\x8aI8%\xb1\xe6\xa6\x94\xe3]#3\xb0\x96\xf3c\xac\xe2he\x88?\x03\"UFwN\xd2#\xb1\x85\xcduYd\xf0dE&,!P\x14\xd74\x1c\xb3\xd0\x1fq\xdc\xa2.\xdd\x13\xc4\xb6\x8e\xa20\xf5\xfc\x90T\x1cn\xe4'buO\xa2\xab\xbaZ\x99h1\xa8\xab\xe5\xb1Z\x18\xb57\xb10\x9c\xa9\xb9\xf2\x84U~\x17\xad.\xbc\xb8\xa9\xf2\x8cU~\xe6%\x9c\xde5}\x10\xb0\x0f\xa2\x90r\xeb\x1f\xbc\xc0\x9fzi\x14?\xf3\xa6s\xd2\xf4)&t\xe8\x06\x917\xf5\xc3\xf9i\xea\xa5Y\xa2F\xb2\x97\x9f\x05z/S~\x89\xdd\x9f7\xb0\xf7\x94GZP\x04\xb1\xad%I\x12oN\x90+\xb24J\x01(6A\"P\x9d;T\xf2\xdcQ\xb6o\xf2\x94\xa4\xcf$\xf0\x92\xe4\xb5\xb7$C\xb0\x92+o>'\xf1v\xe6[\xda\xfa7.L\xe0\xc0\xd8\xcf\xc4\xc5$l\x0eO\xc6\xe6\x82\xc5\xe1c!_\xb4b|\xaa\xfe[\xcc\xed\xddv\x9c~8\x8b\x8c#\xbc\x93\x1e\xf8\xc0\xb7'\xf9\xee\xf8=\xba3t\xe2`\xf8\xb7\x99\xe7\x07d\xfa\xaf\x12\x94\x8b\xdd\xd6\xbd\xa5~\x1a\x10c\x0f\xd6\x0b\x04\"\xa4\x11\xd0a\xc1\xe1\xdb\x97\x80l\x88Oi{\xd7r\xcc\x83\xf08rKkq\x84\xae\x95_dE\xcc\xe4\x013A\x9b\x18>\xf1,\xbd\x8f\xdf\xfa\xd3t1\x04\xeb\xe1\xc3\xde\xeacM{\xacz<\xf7\xc3o\xc8,\x1d\x82\xe5ei]\xffE\xfd\x13\x7f\xbeh\xf9AJ>\xa6\x87\x81?\x0f\x87`M\xd0\xdf_\xbfDP9\xdf\xf3\xb7\xff\n\xb01&\xcb(%\x85\xc7n#NZ+\xcb\xe5\xa4v\x8a\x88\xb9\xb5B\xe5_\x92MD,\x8c\x06\xcc\x9cq\xac6\xf7\x11\x89\x1eL\x15\xb2\xa6\nA\xbes\xaa:\x0dE\xea8+\x85H\xba\xb1\x8b&sNIb\xa9\x89(m\x1bl\x8a\x8a\x90;\x15\x8f\xa5\x81\xd3\xd5\xe6Am\xd3\xa2d\xdc\xa7\xcf\xff\xd6\xdf\x91\xad\x96\xa9p\xf2\xc8\xb1\xadrGV\xb3\xf4g\xe6\xd4\xa5J\xbe\x92\x86\x14\xe06\x17o\x83\x87{\x1a\xc1J\x02\x93^\x1ely\x01\x12\xabb\x9f\xa8^\x8c\xb3\xcd0\x8ba\xf5U\xeb\xce\xc2\xabk\x8b\na\x94\\\xb3qWvmy$C\\\x1d\xa7;\xdb\x10b2\x10*\xed3\x89\x8c\x02U\xbd\x8d($\xbaas\x0e\xb6\xca\"=b\x0ey\x0f\xf7\xaa\xfew\xbd}\xa7;\x93\xfd\xe8\xdb\xb4\xd8r\x12\xaa\x01\xeb\xe7Mb\xf0\x88\xbb!>\xe2n\x86|V\x83G\x0ft\x9b\xf4\xf4zy\x11\x05m\x9an\xb2\xf34\xd8\xe1\xaa;\x98\xdby\x1a\xbc\xad\x0d\xce\xd6\x03\xb5q>\xfeG}\xa7\xfb\xf5\xf1\xf7\xe5\xb2 /S>\xe1\xa9\xe5\xd4\x1eXj\xb9G\xeaxXn\xb9=\xf55\xcf-\xa7\xbc\x9d\xe6HR~\xbf\xe6\xefU4\xbd\xe6#T=\xe4\xe6\xfc\xbd:F\x9eV\xae\x82\xed\xec\xb5\x1a\xfe\x92\xa5\x94\x1b\xe83\xcaU\xb0\xed#\x9b\xa8\x1a\xfb\xee\x94\x81E\x95\xd6\x8e\xf9\x08\xd5\xea\x87|U\xd5N\xdf\xb0\xf7j\xf5\x9f\xf0u\xc5\x0d\xf5\x12Fp\xa8\xe6\x90{ #x\xa3\xbe|\x85i\xe1\x94\x97\xefP\x1ed\x18].9\xc2\x92\xbf\x9c\xbey]~\xff\x16FpD\x8f\xf2\xa3n\x82\xaaW\x7fv]\xaeqB\x05G\xdb:_\xf8\xd3) U\x11\xfc5+M\xa3\xb7\xb1\xbf\xf4\x99\xadv\xb9\xc67\xe8\x00\xa6\xcd\xb9_\xae\xf8\x9c\x92{\xdbJp\xf4\xdb1\x99\xfbI\x1a_\xab\xcd\xfd\"\xd7\xaa\xa4\xb9|\xc1J\xa3\xd5\xb6\xa1\xc2{M\x12\xf3r\x8dg\xa6\xf8\x01\xef\xca\xf5~F\x88\xfe\x955V.\xfa\x1eF\xb0\xf53F\x0e\xffY\xca\x08\xa0\xfc\xdd\x9d\xf9\xe1\xf4h\xe1\x07\xd3\xf2\xd7\xdf\x02\x8f\xf18\xa9w\x8d\xe3G\xdf\x03\xd8\x1a\xc1\xa9\xfd\xd2\xfe\xfb\x0d7\x0f\xd33\x91\xed\xe2\xb1@\xd1\xf0K\xd9\xe4\xac^0\xe0\xda\xac\x07\xc6J7N\xd7\xd3\x16V\xd9\xf2\x1bG\xad{\xe3\xc8\xd1\x0f\x0c\x8c\x00H\xa4\xf8\xd2~\xaf\xbf\x9dE\xd7\xd5) HJ\xe0\xfd\x98\x9c\xb9t\x92\xbc=\x1e8,\xc5;\x8a\xf7\xf4\xe7Kl\xa6\x12 \xf9\x06\x86\xf0\xb2\xbcd\x1fj\xb5\x9e \xd9\xd0\xff\xc2|\x0dO\xedw\x05\"\x98\x0d\xd8 K\xa5\x9bV\"|\x96\xbb\xff\x1aF\xf0\x8c\x8e\x98o\x8b\x12\xd6v\xc5\x91]\x02b\x0dBi\x1aI+\x00h\xd5R)\n\xf3\xbb\xba\x19|\xd5\x82\xd5+5<\x12\x8b\xf4\x95\xfd\"_\xc0%\x8b\xf2\x0f#\xb8\xe2\x19\x8d\xe8;Z\xe2\xdb\xbf\xe0\x9d\xdb\x01\xc6c\xc8 \x10f\xe4\xa3\xfd\x9d\xb0\xbc\x93\xe3\x93\xb31a\xb7\xa6\xe2\xf7\x88\xe7\xa8\xc0E\x0bM\x1b\xa1hr\x08\x1f\xed\x1e&\xb6\xd0a6\x0c\x8b\x0e?}b\xd8w\xe2\xc2G\xbb\x8fyv)\x7fR\xf4K\x87\xffm\x0e\x0d\xfa\xed\xcb*_\x0bU`\xfe\xa1\xcd]\xe3R\xeb8\x91;\x93\x87\xcca\xfc\x9a'\x82#th>K}\xc2\xa21\x8a|\xdf\x11<\x05\xff\xb1\x03_\xd9)\x83R<\xf61n\x00\x19\x87\xba\x10\x96b\x05\xeb&\xf0\xe7\xd6\xdb\xe9\x9b\xd2](.|\xcaRY\x19{\xde\xc2\xda\x05\x02!j\xb0\xbc\xa3[>E\xa6\x94\x19\x04\xd8[6#\xd9\x85\x0b'\xff\xf3\x17\xf1[\x94p\xecY\xf8 ]\xbc\xf4\x0c\x0b\xd5k\xd9\xf2\x14\xff\xd2f\x8d\xfc\x19s\xdc\xbd\xd0\xe0\xb5\xa0S\xf9\x90\x08\x1f\xd2\x0b\x16bY\x8f\xa7\xc2n\xe6\xd2\xae\xb1_\x11\x80\n\xab\x8dW\xb6\xca\xa7O\xca\x8e\xe2x[\x8d$sS\x07\x8e\xbf5\xae\xb8\x1a\xee\xe2\x95}\xc1\x9c\xa0c\x1e\xc1 \xe2\x11\x0c\xba\xa5\xdc\x8fl\xf4\x94\xd9b) qe(e;\xc9\x7f%,T#\x0bDa\xc6\x9b\xb8n\xfc\xdfm<~N\xc2\xd8\xf8_a\xe0\xa1\x170\x04>\xa9\x88OJ\x84\xee(&\x95=v\xc4\x9a\xe0f\xcb\xc4\xacB\x8e\xc1\xef\xc5jElJ\xbf\x8cI\xcd>\x8c\xca\xb3*\xea=\xc3\xa5\xf5l\xfb]]\x14,\xc4P\xba\x9ddB_\x0d\x99n1\x96\xb4\x88\x0f\"\xe5(\xaeDN\x17W^+\x9d\xcfX\xaf\xe43\xd6\x93\xbc:\xdd\xca\x14\x89\x94\xd3\x01\xc9\x19\xa9\xac4\xca=\x04\x9b\xf4E)K\xc4\xffOr\xd3\x87\x98\xb4\xe8/.\x15Q`\x04_a\xc4\xa1\xbd]\x07\xff:\xc6\xff\xff\x8d\xbe\xdb\xe7\xaf\xfe\x8c\x15z\x0f\xd9_\xdf\xf1\xf4\x97[\xa1\xfd\xf0!\x02\xd5\xa3\xb3\xb7t\xe2\x82\xe5\xd2\x8f\x91\xbcL\xbb\xf5\x17\xcd|\xbc\x1f\xecEIuE\xc7\x9b\xd9\x19&B\xca0\x11R\xc6T:\xcfTh3\x84\x1dJ\\\x8bl\x17\x90o\xe6\xbfRaa\xe1%/9\xfa\xbb~r\x14\x85\x13/=]\xc5\xc4\x9b\xa2\x90#\xf8/\x17\xcd\xce]n\n\xe623_\x97\x87rt\xd1x\xc8\x95\xe4(W\xac\xcb;o\xee\xca\x99\xfd\xb9\x9d\x91\xe5Z\xf4\x18H\x19\x85\xf8k\xb1E\xd2\xf4\xb1\x03\x0b\xfb\xaf\xe34-'\xbd-HP\x8a\xd9J\x16\xdd$\x8dbB\xa95o\x85\xa4E3!mfm\x93t\x1c*\xedP\x08\x9e\x96`\xc7\xf7w5\xa0Q\x14\xb7d\x15}\xfb9=\xd3:#4^<\x80\xe7tO\x0d\xd9?\xa3j\xea]\x85\xfc^\x92\xeb\x17\xcd]\xa19\xe7\xd7h\xceY\x9b\xd3\xc1\x03\xc6\x01W(\x13\x94\xc3\xed\xf8!<\xd7\xdb\xd3\xd1\x9e\x9e#\x177\x92\xe3\xbb\xd72\xf1YBNI\x9a\x92\xb8AJ\xfb^\x17I\xb2\xd2\x92\xbf\\\x05M\xf6\x05\xdf\x97\xb3\xd7\x01\x94\xf5\xba\xaen\xa1\x0d:O\xa6\x9ao\x91\xca\xaej\xe2F\x99\xf0S\x1b\x93\x96\xfd\xc1>e\x9cN\xedb\xab\xfa\xd5\xafj\x8a}\x92\x0c\xe1\x0f\xe5\ns\x92\xbe\xb9\n\xc5\xf7\xcfI2\x89\xfdUJ\xd1\xe7/u\x15_{K\xda\xd8\xdf\xea\xea\xb0m\x90\x0c\xe1\xbb\x12\x1cQ\xc1R\x06\xa6\xbd\x85\x07l\x8d\x88/\x8e\xc1wjxL!\xa6\x8d\xc3,\x08\xce0\xfe\xcd[[p\x9d\xd6\xdfo\xf8\x9b*\xec\xbd\x8a\x11\x8f\xf2 [\\\x85b:.X\x7f9}\xf3Z\xe3@\xce\xf5EM\xfb\xae\xc4\xfap\x86-=\xe3Y\xe4\x1f\xebb7P\x81\x82sd\xc5a\xef\xebSx\xf3<\xaf\x9c\x1d\xea\x9f\xb9`\x9f\xdb\x95\x94?\x9c\xc1\xffZ6\xe6\x9e\xf3j6i\xc3\x8c\x8b\xbe\xb4\xba!\x16\x1a\x08\xf9\xcc\x8au\xa6\xe3\xd2~\x89c \x03\xc0\x91\x84\x8e\x9dN\xc3\x85\xb7\xdc`\xe9\xa8\xaaz(\xa1\x95\xa4B\x18\xbfFV<\xb4\x07\xfb\x8e\xacZp\xe1u\xa9\x1eK\xc2\xf2f\x86\xd9\xe4\xde\x15\x84\x1b\xff~\xe5\xa5\x0b\x17,\xfa\x0f\xb7S\x81\xc0\xe6J\xc3\x1c\x07\xb6z\xad4\xff\xd2\x0d\xd6\x9ec[K\x92z\xba\xd0\xbb\x1a\xe5m\xa4\xd7\x9a\x8b`\xa4\x8e\xaa\xf3\xf4\xaav\xebI\xa1\xe4\xf3\x93\xe3\x8f) \x13\x9f\xca&\x9f>\xd5\x13D!\xf8\xd4R\xd7 \xa5\x9a\xa8]o\xa5\x9eK\xec\\\xddH\xd6$L\xf9p\xa20\xb1\xa9\xc0\xaf\xec\xc7rW\xf5<\x0e\xe0Q\x9c\xa2\xf7\x91I\xdaC\xb5\x9c\xbe\x90>\xfe\x10\xac7\x16t\xa0\xd3\xf1\xaa\xbc\xa4x\xae\x86j\xb0Z\xf1\xe8\xb4wu\xb0\x0b\x94\x1cR\xd5\x91}}\xfc\xbd68\xf9\xeb\xe3\xe3\xe7C\xd8\xeaWKf^\x92~M\xae[\x9c=\xa0u\xe9\xd0\xa9\xbb\xb85$s$e\x86Fr\x99u\x8a\xde\x14o\xd1\xcd\xc2\x90C\x81e\x01\xc0\xe51J\xe3y\xbd\xa44\xa0\x17\x06{\xac\xbcz\xe1\xb9b\x1d\xd7\xd4\x9d\xa9\\\x93x\xf4\x8b)x\xfcq|\xd6\xad\xe6\xce\xd7\x84p\x9b\x93\xf4[\xe2]n\x02\xf9[\x01dK\x1f\xe3\xa5\xa8M\x8c\x11\xab\xe5\xe73\xc0q\xd5\x06\x1cQ\xf8\"&\xe4\x97\xc6d\x82P4>\xa1\xc7F\xd0\xa5\xc8\x8d\xe6\x146?\xa68\x98\xe8\xef\x19rD\xed\x0c\xab[\xd3\xe4\xca\xbd\x93\x08\x19\xa4'\xc6\xfb\xa6\xe4G\xe6\x89\n\x05]\xac\xcd\xd4\x16\xb2\xc0\xba\xe5\xb5\xc2\x83\xbc\xbaB9\xf7\x90\xb9\xfc2\x94\x02\x84\xf6\x1eug,\xa1J\xef1x\x05\xf30y\xec@\x92g.\xa7\xe7\x867\x9e\xa0\x96\x04\xe5{\xe4*2=O%\x19\x89l\x06\xd0\x87\xfb\x06\x08\xb1\x08\xef~\xc2RY\xc9\x07\x90If\xb5\xb0*\x92\x9c\xd8\xbe}\xa6\xab\xca\xed'_\xe2\xbd\xea \x1a\xb1\x1b:!oV\xcf]+b\\\xbfD\x06\xaf\xfcp\x1a]Q\x88\x16\xbf\ns\x17\x95m\x86\x83\x9aB\x9b\xb5@\x05\x80\xb1\xce+\xa0\x9d\xa8\x8f\x81v\xad1\x1b)|\x8bM\x9e\xe1\x88\xf3Di\x8d\x17 \xe6\xbc7\xb9\x94\xaa!!\xcd\xf9\xe3\xc5\x10\xb9kQ\xa3\xbd\x92\xcdS8\x97\xedn\xf4\x08\xe0\xc0\xdf\x1b-\"\xfa\xbd\x07\x8emy\xc9u8y\xb9\x91\xfd\x86\xf8\x94%GA\x1dL\xab\xef\xda\xd9}<\xba[\xbb\x8f\x9d^\xaf\xc6\x08+\xf9\x0c#\xac\xaa1\x90Y\x12.\xf73\xc4q\xf51\xa7U1\x9fV0\x94\xb6\xb2J\x95}\xbd5D\xd4F\x8c\xa1T\xd6G\x12\xba\x15S\xf9\xe7\xde=4\xa3+\x07v.\x14#\x84eCe\x11\xd9\x12\x92\x82\x97@.Ml\xa9\xe1\x18\xf44\xb0\x02\xa0!h\x17\x05e1+w\xe6\xb0\xc0\x0f\xe1\xef7\xd5\xbb_m\xca\x1b\xf3\xde\xb5\xf9\"R\xd1\xe8\x05o I\x82\xcb\x0d6\xba3\xbbb\x12\x00\xd28XF2\x188\x0e\x1d\xc0\xf8\x8c\xdf\xc5(Yf\x91l\xdf\x86:\x10}f\x8a*W\xc2\xc9\x88\x0c\x0d\xa3V[(\x95Y%\x96\x0f5\x95\x1ceF\x10\xc2\x90\xe5\xc0 \xdb\xf0\x17h]\xb0\xd5wL\xfa\xf6\xc9\x82L.\x87\xd2uB\xabM\xdb\x8aN\xecT\"\xe2}.\x9d\xd8\xfdlKD\xc3!\x14s\x1bUVg\xb3\x81\xdd\x8e\xdc\x08\xc5\x1bZ*\x15\x1d\xb6\xa20M\xf6l\xbb\x06\xdb\xd3==\x97\xb8S\xb1\xf2b2\xfbN_\xb5\xf2bl\xdc\x8e\xfa:\xe1\xd5u\xe9\x89\xe9{\xb5\xf9\x19\x7f\xaf\x0e'\xe0\xcd\xab8\xba\xc2Li%+\xe2r\x85\x85T\xe1\x857I\xa3X\xb1\x85\x9a\xb2\nA\x14\xea\x1bXW\xe3@\\7\xca\xf0mn\xc4\xe7Za\x19\x8d\x87b\x12\x9aD\xfc\xa5\xb7\x1aB\xd4]z+\xbdp?\x8b\xe2co\xb2\xa0u\xf8O}\xbdI\x94\x85):\x1e\xd3\x1f\xfa:i\x84\x04\x90\xd6\xe2?\xf5\xf5\xa20\xb8\x1e\x82&\xe7Y\xb5zn\x9c=\x04\xbf[\xe3\xd3\xf66\x8bI\xa9n\xe9E\xb5~ \x03\x86\xa0\x01\x8e\xbc\xc2C\x98V+\xf8 \xfau\xe5U\xbcn\xf9\x8df\x90q\xb4\xa2\xc7j2\x04\x8d\xf7\x1c\x1b\xd2Q\xe0%\xc9\x10f\xa6r\x8e\x93C\xd0\xac\x13\xab\xf1\xca\xff\xe8\x87C\xd0\xc0\xfe\xf9\x9bWC\xc8\xaa\xef\xd7$N\xfc(\x1c\xc2\xa4Zv~\x9e\xe05\xd6\x10\xd6e\xe4\xd4S\xc8V\xa99\xea\x89\x8e\xacQ3\xf4\x12\x7f~/\x94V\xe9y\xaa\nM\xe2\x02\xb0\x81\xb2\xf5T\x0e\x96\xa5\x13M\xaf\xa2C\xae\xb6~\x1bE\x81\x9a\x8e\x14g\xd1\x9dEY\\W\x8bR\xbd\xfb?\xdc\xef\xdc\x9f\xeb\\{gFA\xc8\xb6,\xe8@\xea\x94\x82\xbd\xff\xe1\xde}K>\x8f\xaa\x0d\x06\xdas\x0d/|i\x1df\x85\x86\x7fN\xa20e\xb9\xb9H\xfe&c7\x88\xb5=\xact\x0b\x05\xd2\xb2\xa4\xd8\x93f\xb3a\x19\xefV\x91\xdb\x99l\xe7c\xc3)\x1b\x88\x9c?]7\x8e\x85\x18\x87\x86\x93\xc4\xe9\xc4$a\xde\x1fb\xc6\x97\xe4\xfamLf\xfeGi\xce\x1c(a\x05(\xf1F@\x996\x03\x85\x0d\xa7\n\x96\x0cK\xf3\xb1U+x50Md\x98j\xa8 ;\xe8(l\x13\x05\xb6\xe5\x05(\xe97\xec \x95\xb1\xd7\x14\xe3b\x84o\xd4M\x17^z\x82\x88\x99\x08d\x17\x8e\x9c\xb05b\n0\xdbW\xa8'm\x87\xbe\x9f\xa0\x9a\x08\x89\xf1a8=a\xf8\xfc5\xb9\xa6\x1dd\xd0\x01{kB\xe7\xcf,yP\xb9C\xff\xc2\xe4\xf2\xf8\xeb\x00,\x0b\x860\xb3\xf1O\x87\x8a2\xf7Qg\x1b\xa2\xe1\x10S\x05M\x9cztYK\xe8\xe2V#g\xacy\xd4\x0c\xd5\x89V\xcc\x90\xdd\x0c\xa1hf\x87b\x08U\x83\x17\xbaV\xe8\x9a\x8b\xa4`j\x13\x8c\x8c\x81\x1d\x96+\xa3\xc6\x7f\xea\x82\xe7\xb8\xb0\xe8\xc6$ ^Bl\xaf~\x0e\xd7&,\xe34\x83\x0eVj@\xfc\n\xa4\x8b\xa3)\x11\x06;u\xf6@\xa5\xad\x81\xee[\xca\xee(\xbd\xacl\x10\xba(\xdetJa\xe0\x87\xf3w\x91\x1d\x88\x89\xdej \xf9F\x96z\x95\xf7\xb2\xf4\xfa\x0e\xc7\xbcp!Q\x04\x8c*\xfb\x96\xb3^u\xa7\x98xP3J\xf1\xa9dM\xa0\xb9x\x10D#(c\x92.\xc9:\xe2\xd1\nS\x17@\x90\xe3\x91z\xdfX\xa6\x0c\xc8O~\x91\x01\xeb\"p S\x01\x9b]q\xb1U\x10\xa6\xda\x0d\xc3|\x19\xa6\xd1\xb7~\xba\xf8Z\xac\xf6\xcb0%q\xe8\x05CX+\xc7,\xe3m\x1b\xf5&B\x87G+\\s\xd7\xc3\xbaA\xe4\xfcp=\xf3/\xf4\xe4M\x00 \x02\x00z\x92Z1\x10/\xf0\xf3\x8b\xf1j\xa1\xbd\xaf\xd31\xdb\xa1M%\xaf\x86y\x0b\xc3\xc1\xae\xd0\xa0Pl\xad (\x07\x12\xac\xaa\xdf\xad\xa2\x95)\xf3\xb5\xc0=\xdc\xbd<\x12|\x15^P\xa7p \xc9\x15~_1B\xaa\xd5\xbfi\x95T\xb2\xc2\x08\x0d\x0f?}\x82\xd8\xb6\x06{h\xcb%\xd16\xdbq5\xf3\xe4w\x1cOx8\x90(\nN\xfd_\x880>V`B\x0f\xb7z\xb3\xa9\x0c\x934\x97^yZAS\xa6o-\xf6\nH\x96\xc6\x86\xebQ\x01\xda\xd2\x98\xb9\xd1kXP/\xb4\xeb\xf8\xf4 2\xfa6\x9f/3:\xce\xff\x1c\xb1\x8cp\xa1\xa0b0\xa2g\xa7\xc6\x02\xb9\xca\xe7P\xce\xa2\xc4\x83\x0fU\x80\xd0\xa7\xc2\xcf\xb7\x84\xc1m\x90\x1cd\xd8m\x82\xe8\xa0Cv\x11\xa8P\x07\x0e\xd0\xe2<\xe8\xf0\xbeb\x92\x05zp\xa6\x8b\x98T\x00\xda\xe6\xc0\x80\xcf\x84V|'\xd0\x8a\x19\xb4tG\x8cx\xda\x03\xac\xe2\xa5\x01z\x98U\xe5\xc0*\xc8\x0c:o\xf8L\xa8\xf9w\x025?\x87\x1a\xe3&\xaa\xb6\x03\xb0)\xe0*\x86O\xd5\x16\x0c\xe7\xdag\xc4\x0fk>\xd7\xfa\x05\x1f\x15?f${\x1f^\xd7\n\xb3\xe5\x05\x89\xe57\x05Ty\x17\xa4\xfb\x87?\xf0\x91\xd1wE\xfe\xf4\x99\xcd8V\xcb\xca\x93\x87y\xd0\x81 \x9dp\x0f\xc5`\xc7\x05\x8d\xc5\n\x9dqM8\xd65\x8a\x9bR\x93CLd\x93\xe8\xa1R\x96\xd0\x89\xc6\x1f\x01d+\x8bkfOq\x0dO\xf2$<\x8f\xe1\xba\xd3q`\n\x9d\x11\xa4\xf6\x8a\x9e\xc9\xe3\xeb3\x17\xd68\x97\x95\x0b\xd7\x0e_\xbd\xea\x0808\xa6\x99C\x98\xb3,\xa5\x06rC\x87?o\"bK\x17\xdd\xc0\xe7\x9c\xbb\xab\xa1\\\xd8\x1c\xbb\xe8\xec\x920\x8d}\x92\xe8\x81!\x9e\x1c(\x17\x0c([\xf6\x12Fp\x8e\xa9\xe9m\xc7\xe9N\xa3\x90<.\x01f\xc9\x0c,%\xd8\\t:f\xe8\x88\x87B\xa9y$\xc6\x01\x98\x01$\x1e:\x89\xabb|\xe6\x91\x88\x07\x0d:lifWhZ\xbbF\x03fN.\xae\xc6\xbd3\x87\"\x9e\x98kO\xcc\xb4\x1e\xac\x06[B\x86+\xb8\x91K[\xac \x01>\x1a\x92\x91\xc9\xcfi\x11+\xba\x0eCb\xdb\xda\xe9[naG\xc2n\xdd\xce\xd8HN\xe1@\xec~\xb8\xf2\xd3\x05\\\x92\xeb\x04\xfenAG\xdcg\xd3\x176qx\x9a[\x17P\xd9d\xddX0\x84S\x17>\xb65?3J\"\xd3R\xc1\x0d\xa5\xb8\x96\xa5\xf2\x1a\xadn\x1b\xeb\x8f@\xad\x8d3\xf7\xe1\xbaw\x8f\xff\xca\x1d\x8b\xabg\xa5\xf5/\xff\x92\x07\n\xd1\x9f\xd3f9)\x97\xf2\x80\xc5\xcdEg\xc3\x18\xcd\x9b\xd3\xb1\xafZ\x80\x1b-\xb2\x89\xc6\xdc\xfa\x0e S\x1e+\xdb\x08me|=\x1a[#k\x08\xd6\xa8g\xc0`k\x88\xc5\x83j\xb8\xa7\x1b\xa3\xc6\xc0\xfa\x03\xc5\xc9\xcaE\xc0\xfd\xf1hxv\x7f\xde$\x9aK\x0d\x91qzV\xed\xb7^\xa6\x0c\xef\x06(=\x9c\xb6 (\xa3\x01-\x1en\x02\x14\x06\x0e\xdb\xea\xb2\xcd\x9c\x8e{\xe8\xe8Ma\xc5\xfe\xee\x9f\xa1\x8dD\x92]0.\xc0\x1e\xd0#Z~\xd1w\x1c \x9a\xf6\xa8\xf7i4p\xee\x1e\xa0\x05\xbe\xea\xf7\xce\xdd\xdc\x80\x0d\x9c\xba\x9bn_\xaf\x07\x18R\x12Y\xb1\xe4\xc7\xa2\x8b\x8b\x98\x95^\\h\x83~z\xd3iL\x92\x84\xd5a\xbf\xb5\xd5b\xc2{\x89\x89\xbe\xa38\xf5'\x01\xe1u\xf0\xb7\xb6Z\xe2Oy%\xfaK[%\x9b\xfa\x11\xabB\x7f\xe9\xaa\\`\xf1\x85\xb6\xc8KX\xfb\xf4\x87\xb6\xc2\xd4g\xe5S__\x1c\xf1b}\xcf\xfe\x9c\x15\xfbsmq\x10M.\x7f\xce\xa2\x94\x8f!\xffS[9\x9a^\xb3j\xd1\xb4\x12P\x05+\xb0\xa5\xd3/\xdcE\x96\xa6Q\xc8*\xe0O]\xa5\x89\x17\xae=\xb6\xb8\xec\xa7\xbe\xd2*\xf5yS\xfc\xb7\xb6\x9a\xcfgE\x7fh+D|i\xe9\x0f}\x85\x80\x97kc\xc6N\xa2`\x1eG\xd9J\xd4\xc1?t\x15\xa7^\xca\x90\x91\xfe0U\x08\xfc$\xcd+\xd1?\xb4\x15\xa7\xac\xcaT[H\xd8p\xa7D;\xdc)I=?Hx\x15\xfc\xad\xad6c\x90\x9d\xce\xb4P\x9d\xfa^\x101\x9cb?\xf5\x95\xd6\xbc\xc6Z[\xcc\xc7\xa9\x1f&\x87\x82v\xfed\x89\x85d\xa9/\xbc S^~A\xb4 \x9a\xf9$\x98\xa2\xe9`l[\xe2\x0f}\xc5\xb9\x8cf\xc5\x9f\x86\xcaYLD\xc5,\xd6\"\xd3,\x8a\xd0+\x93V\xc2\x9f\xfaJ\xf1\x92W\x89\xb5s\\\xf4\xb1x\xd1\xd7\x16\x0eX\xe1@[\xb8\xc3\nw\xb4\x85\xbb\xacpW[\xb8\xc7\n\xf7\xb4\x85\xfb\xacp_[\x88V\x1f\xb4\x98x\xda\xf5\xa0\xef9P\xd8Om\xa5b\x97-\x8c{l\xc1[\xd1\xb7\x90.\x19\xca\xd1\x1f\xba\n\x8c\xc4j \xac?\x8b1\\&-\xc7\x9f\xdaJK\xb6%\xfc\xa5v?\xf8\xe1*c8\x87\xbf\xf4U\x12^A\xbb+//\x18 //\xb4p\xbc$\xd7s\xc2P\x95\xfd\xd4U\n\xbc\x0bN!\xf0\x97\xb6\n\x99\x93\x90\xf5\xc4~j+1h\x05Zp\x05~x\xc9\x8b\xc3K]\x85\xa5\xe7\xb3\x81\xd2\x1f\xfa\n+^\xae]\xe8\xa5\x17_\xf2\xf2X\xdf\x01 3V\x81\x84\x99\xa9\x82\x9frR\"\xfe\xd0W\xe4t[\xe7w\xc8+p\xec\xc5_\xba*\xa1\xc7Ha\xe8iIa\x181\xbfaV\x87\xff\xa1\xab\xc8\x04F\xac\xc6\xc5Z]%\xb6\xbc\xfa\xe3*Z\xa5\xc5F\x12\x7f\x18*\n\xba\x17\x19i^\x94\xa5\x02\xa7\xd9O]%\xd6\x97\xb6\x93\x95\x17{l\x05\xf0\x97\xb6\x8a?I\x05]\xe5\xbf\xb5\xd5D\x15Sq4\xcf9F\xf1\x87\xae\xe2\xcfX\xe3g]Q\xcc&\x12kg\x123(\xc4Z\x08\xc4\xd9\x05\xe3\x99\xe8\x0f]\x056.\xed\x80\x12o\xc9\xfa\xa5?\xb4\x15\n\xd41#NB&\xf9r\xf2\xdf\xfaj\x81\xc0/\xf6S[i\xe9\x05\x0c\xc5X\nN]\x15L\xa3\xc4\xea\xe0Om\xa5\x95\xc7\x07\xb4\xf2\xf4\xa3I\xe3(d$\x95\xfd\xd4W\xba\xe6\x0c<\xfe\xd2V\xc9\x18\xeb\x9ddZ\xe6;\xc9\x96K/\xbe\xe6U\xf0\xb7\xbe\x1a_\x07\xfd~IY\x1c\x95\xd8\xb6R\xe6\xdb\xa2\xa9\x92\xf3\xce\xa9\x89yN\x19\xd9M\xb5$7%\x1f\xd3\\\xa4\x11\x7fh+R\xde\x82\xd5\xa2\xbf\xb4U\x16\xac\\\x9br=\xcd\x8f\xec\xd4tf\xa7>?\x0e\xe9\x0f}\x85T\xc0\x03#L\xeb\xaa0\xaa\x99jIf\x1a{\x93K^\xeeM\xb44\x9e\x11x-u\xcf\x18\x82fZ\xec\\{\xac\xe3\xb5\xa7\xedy\xedO \x13\xa7\xf0\x97\xae\xca\x15\x17r\xae\xf4R\xce\xc4\x8f\x85T\xc9~j+\x05\xfe\xea\xad\xc7\xd7A\xfc\xa1\xab8%3\xc1\xaf\xcf\xb4$\x82\x04\x81\xbf\xe2\x02$\xff\xad\xab\xc6v\x92\x9e5Yzs\xce\xdd,1\x93C\xb5J\xe0\x87\xac\x06\xfda\xaa\xe0\xc5_\xc5\xde\xd4G3f^\xb5x\xa5\xfbh\xe9%\xe2\x1cO\xb4k\xbc\x12\x10Z\x19\xa0\xb3\xf2\xd2\x94\xc4\xa1\xa8C\x7fk\xabE\xc1\xf5\x9c\x13@\xfe\xdbT-\x9f\xa9\xf8CW\x91\xce\xc9\x0bJ\xb3-\xbf\xd2~$\x88kl\"\xadi\xc4\x89L\x1a\xe9\x89\xfd\x9a\xd3\xc3\xb5v\x1d)Q\xc8\xa9\x83\xb6BNtSFuK5\x0c:\"v {\x07:\xa2:\xbbvn3\xdd7\xb9\x07\xfb\xc2\x9e\xecs\xc7\xd1\xdf\xdb\xd8\x01Yx\xe4\xd0\xfe\xe4`\x8cw\xa0\x03\xd6\xd8\x83s\x8f<\xf5\xf6\x97[\x8f\xebcYT\xdckx\xa8\xe7}5V\xb0\xf0\x8b1\xf9\x18\xd7\xda\xa2\x08[\x92\xcfQ\xe9\x03\xb7\x08\xd6\xab\xf5E/3Z\xe3\xc9\x13/\x8c\xc2\xebe\x94%O\x9fj\xb4\xb7\x81Q\xe5\xeb1s\xb9\xb5m\xe1/\xddN\x00\xd4eQ^ym\xe7\xf7\xba\x86zt\xbaX/\x9f\xb7\xa1\"\xbb\xe0\xc5\xaa\xfc\xae\xd7PQ0\xf2\xeb:F\x1e\xf2\xc08X\x91\xdf'\x9b*\xf2 ck\x11\xcf\xd8T\xd1\x0b\xaf\x870\xb5c\xd9\xf6\xef5^`\x9bA\xf9f\xd6\xa4\x82\x17\x8f\xb8\\*\xe2\x99\x14\xe6\xce.DM\xf7\x8b\xca\x15\xccVal\xe0\xc8\xf6\x1d\x0b\xdb\x12n\xdf\xf0\xa3\x05\x1d\x88\xa0\x03\xd6\x8f\x10\xcd\x8a\x94s\xac f\x05\x0b/\x01?\\S\xea\x93{\xcf@\x18\xa5\x98\xc0\x82\x8a\xdd\xfe\x94\x88\xa9vM\xe9C\xc5C\x11\x14\x13I\x8dCC\xb2W\xf1`D\x89\xf2\xa5yV\x1b\xb0B<\xb4\x0b4\xad\xacD\x17\xd0=e\xc8\xbc\xe4\xf3\xa4\xd3\xf71\x16\x99\x02\"\x0c \x8d\xef\x12\xf6.\xc9V\xab\xc0gi>$\xa8\xb9@>\xae\xc8$%S\xf0B\x06\x9d\xaeu\x9b\xebX\xf1\xe4w\xe0<\xd0\xc2\x04\x9e@\x96\x1b\x06L:\x9d\xb6\xa0\x99aj\xc9\x0c\x93\xe2r\xcc\xa2#\x1e\xd3\xb1O\xe8\xaf3\xcb\x05\xaf\x05\xe4\xe8\x02\xcddCJ\xf4T.\x8c.>c\xb2:sx\xf5\xb91\xdc\xe2\xea\xb7\"\x11\x1eb\xf9\xde\xfa\x82;qC$O7@l\xef\xcb#\xb6\xd7\x1a\xb1!\xf1\xc3y@\xe0\x84x\x93\x94s&\x9f\x87\xe5\x9f\xb3\xf0\xa6\xack\x02C\x7fWB\xbce\xd3\xc5/\x99\x19\xb7^c\xe6P\x14zK\x16)K?+\xf5\xf1\x1a\x8d\x9eM\x0f\xc3\xc1\xae\x14\n\x16\xe3\x0d\x97\xde\xe0h\x8a\xad\xdd\x8c}\xe2\x11vp\x95\xc6Z\xb5pc\x1b\xa2W\xab\xcf\x97Gv\xb1\x92\xf4s\xac\x91a\x8d\x7f\x1c\xba\x1b\xb8(\xbc\x92\xbb%\x91\xabu\xb0R\x1fD\x9bk;\x1d\x933Ge0\xe4\x05\x88\x8b\x05\xf0\x0d\xc0\x0e\xab\x94\x05I\xca\xebhJ\x1a9\x8a\xcf\x81\xa1\x89d0\xbe\xf2w%\x18\xff0\xceM\xcc\xb5\x11\xd0\xf2\xa9\xd6L\x93\xdaq`%+\xb3\xad\xd1\x08\x92:T\xbaC\x8e\x8c\xf5\xd98g\x89\xeb\xf2C\xc8\xea\xf7:\xf0 e\xdd\x85\x97H\xd1\x95\xecI+\xd2\x0f\xf5\x0cZ\x17\x19\xb4v\xac\x19|.{\x06\xff\x00\xd2\x15\x85\x1b\x1c\xd1\x1a\xe9@\x8aTW\x11\xd0jL\x0d?o\xeb\x16Q\xd1\xc4\xce`\x810\x1f\x83\x07O \xcd\x19tO\xf6\x866=tR+\xba\xf2\xe9\xd8\x93\x89j\xed\x04@\x12y\xfer\xfa\xe6u\x91?H\x9bYB~6\xdcih\xb2*\x1f~-\xb6Z\x14\xe2\x89\x99o\xcf\xba\xf3\xf2\x16\xe8B)\xda\xef\x8e2R\xe8i\x16\xad\xbb\xb4\xd2\xa4Y\x14\x13\xba\xa0T\x9b\xa9_~\x8c'C\x98\x0f<\xb2\xb7\xfa.\xe4\xab'\xe2\xf4\x96\xd6&\x87U\x17\x8eU\xb1\x14\x8f\x8f\x05\x99\\\xe6`L\\\xb8\xc8R\x88\xc9\x84\xf8k2\x85?&\xe0\xa5\xe0\x87S\xf2\x11\xfe\x98t-\x17\xce1\x99\x0bA\xe7m\x05l\xe6\xd5\xfd]\xb6`\xef1d\xa5\xe5\xc8\x9a\x97\x03\xa4\x1d\x94\x8e\xb3\x86%\x01(\xfb\xd5&\xe5\xd1R\x02\xed\xb4\xa2\x8e\xd0\x9a\xc6\xb6\xd9\x9f\x86\xadxw\xfb-Y\xb4\xb0&\x15\xcfg.\xe9\x7f=\xac\xc6\x8f\xac\xc7\x1f7\xe44Z p9\xb30\x9e\xb4\xc4\xd9Y\x9bf\x817\x1d`\xac\x84;\xe1C\x82\x1c\xd4\xf5\xdb\x01\x1a\xb7D\xbb\x0dswL \xf9\xe8M\xd2\xdf\x11\xeb\x93\xd6X?A\xacO6\xc5\xfa\xc9g`\xfd\xe4\xce\xb1^\xa0p\x86q\xed\x18\xff\xd4\xc4\xb5\xe4;%\xa0;\xa5\x15J\xd3\xda+\xdc)A\xcb\x9d\xb2\xb5\xda\x0cN\x97\x84\xcbdA=9\xfe!|\xe6M\xf3+\x0cZ\xa0\xf0l\x0c\x06,\xc6\x80\x05\xdcs\xe5\x87\x10/\xff\xd0\xd1E\xfb\x95\xec\xf7\x92:\xa5\xef[l\xd35\xf7s[\xd9\x89\x0bAu\xb7\x07\xedv;\x85\xdb4\x07\xdb\xf4\x1f\xb4\x8f+oo$\xafM\xa8\x06B\xd2\xe1\x8f\xd0Z\xe5\x891x\xf2\x02\xf8\xf4 \xfap\x1f\x0b\xf0\x07\x81!f\x00c^2\x84\xfeR\x03@\xe8\xfb^\x18\x02\x13,\xfc\xa4\xbb$I\xe2\xcd\x89\x14\xf8(I\xbd\xc9%\xbaW\xb5j|j\xc8\xff \xcaC\x9b\x11\xa5\xc8\x85\xcc\x85\x04)\xbc\xd6\xe5\x93>6=\x883\xa6\x89D\xa23\xc1\xa4V.\xb0X\xa5\x9e\xc3S.`b&dE\x8f\xbc \xf0\xc3y\x11j\x0dp\xe7xi\x14'0\xf5c2I\x83k\x91\xe4\x85n\x94(\xa6D\xe3\xe2\x1a\xd2\x05\x81\x1fWq\xb4\xda\xa6D'\xf9\x11V\xde\xe4\xd2\x9b\x93.\xbcO\x08\xfc\x987\xd8E\x865\xff\xd3v~\xa4\xfbl\xe2\x05\x01mb\xd9\x85\x13\xe2Ma\x19\xc5\x84r\xae\x8b4]\x0d\xef\xdf\x9f]t\x97\xe4~\x96\x90m\xfcz\xbb\xe8\xc7\xb8I$<\xc48\xd0\xe3\xe8\x0c\x0e\xd0\xd93\xf7W\x15\xef\x18\x91x\xb7 \x85\xacS\"\x9a~\x82\x86\x97\x94\xf1N &?g~\x8cZEY\x9eb|\xb7\x9f&\\\xd4\xf2\x13\xf8\x91vD\xe9(\x0c\xbf\\\x1f\xb9\xbf\xae\xe8\x88Nn\x08\xa9]\xc2\x91&Op\x90\xaf\xe6\xbb\x17~8\xb5\x19\x19\xda\xeak\xc0\x9b\x8b]~r\"F\xaa~\xd7\xabF\x981`\xfc\xba6\xa4\xa3\xe9@v!3a\xbd\xb8k1_\xe1\xf0\xb6\xe7\xb6\xe7p\xe2p\xd0\xee\xa8(\x1d\xa9K\xfay\xdbS\x95\xbeM\x05[\xcf\xd7\xa9\xba(\xaa\x17\x93\x1eb\xd7\xb6\x96\xf2%W>\x8b\x92\x9b{\xef\xe9\xe13\xf1\x12\x92;e\x0fk\xaa\xf0\x9b\xf7\xba*\x85\xbb\xb8\xbe\x16\x14\xd06\xa5 `\x0d S\x84\xe6f\x0c\x9e\xb7\xac\x19\xce.\x99[\xd1\xbas\x8b\xb6I\x97\xacI|m_7x@\x97=\xdeS\xb9\x89\xbaD\x0bk5Bc\xa3\xa8\xb0.9r\x86\xcc\x913\xe4\x8e\x9c\x93\xa6\xdb\x95\x8d\x1c;\xd5\xe7\xa6\xd1\x0f|+n\x953\x82\xce\xc1\x17)O[9\x98\xc7\x8a\x83y\x1b%\xc2c\xd8\xb2}LhPv\xec\xae\xfd\x12\x8a\xbb\x10\x9fyuK\x0b\xd97\x83f\x03gs\xdd\x98Zr\xbd\x18Z\xa8\xad\xb39*\xaf1\xf1\xc5\xb5\x9d\x8d\xfbg\xad&\x02mt;&\x8c\x16\xe1\xa5\x1b\xbf\xaf\xf6\x7f\xd3\x8a\xcc\xcd\xeb\xbd^\xc5=\x8b\xf1|R\xf5\x85p\x00\xdc.\n9?I\xbd~B\xe6\xc7\x1fW\x85k\xba\x05-\xa3\x13\xf1\x9e\xa4\xfc7\x9c\xd3\x14I\xa1\x18\x95\x18[\xff\xf2/R*B\x0b7p\x835\x19\x91\x07\xc8^W\xe1\xc8\"q\xd1\x81\x8b\x11T2W\x1a\x80\xbb4\xc7\x14\x93\x12\xcb\xe1\\rjW\\i1\xb7\xe8*\xe4\xc5\xda\xcc\xb5\xfa\xebJ\\\x82\xfa\xa8O2\x00\x9e{\xa9\x94\xb1g\xea\xa5\xc4\x90\xb4\xa7\xf2%[\xdb\xe2\xdb\x98\xcc\xc9\xc7\x95\xc6\xeb\xd9\x84F\xed\xe0y^\x8f\xac\xfaT\xd1\xe2\xc4n8\xaa\x19\xd2\xd6\x1d\xc3\x8d\xc7\x9e\x98\xbd\x17\"gS{\x86\xd6\x1f\xc5\xac\x0e\xae@]\x05\x0e\xe6\x16#\xaa\x1bP[\x1a\xd3\x14\x89\xae\xfc\x17\xffH\x8a\x88 #v\xc5&g/\x08\x14I\x05F\x94\x95\x0e\xba\xf2\x8b\xc0\x055\xe8\xe7\xad\xccb\xebb\x01\xe5W\xfaw\xd4\xbe\xd5\xdf\xeb\xeewy0\x84[\xb5\xb6.\xc2\xec\xef=tLa\xc5\xfdV\xf6\xcf>\x7fu\xf8\xfa{C\xbc\x87$\xf5R\x7f\xd2\xae\xee\xaa\x08\xb4\xde\xa26\x8f\xf2\xba\xc1\x07\x0b?\x98\x1em\xfa\xd5\x9c\xa4\xcf\x199\xa0;P\xf9\xe6\xfc\xd5\xf1\xc9W\xc7\xcf\xcd\x9f\xbe\x0c\xfd\xd4\xf7\x82\xd3\x14S=l\xf4\xe9\x914\xdcM>\x8dI\x88\xfe\xbd\xe2\x8b7\xaf\x8f\x8e\x8d \xe4[\xe8[?\x08^\xb1p\xaa-@\x92\x7f\xf6\xdc\x9f\xde\xe2+\xda\xd9 \xbb)\xd4\x80\xd4\x84G\x8b(\xa3\xe0\xe0m\xbc_MK\x10m;I\xf5\xbb6\xe3}\xeeOo\xf3\x19v\x17.[\xc3\xe7\xfd\xeb\xd3\xc3\x17\xc7\xe7\xb7\\\x13\xdd\xd7\x1b\x03Y\xd7\xc8\x06S\xcf\xb0\xaa\x94\xcf\xc1z\xf3\xe1\xf8\xe4\xe4\xe5\xf3\xe3\xf3g\x87\xa7\xc7\x1a\xe6\xa7\xda\xce\xc4Htp#\xc6\xfe\x9aLq7\xbd\x88\xa3e\xcd\x8el\xd3\xd7\xcc\xd8\xd7\xd4OV\x81\x87I\xceZ\xb2\xe4\x80\x84W\xfa\x0eT\xbd\xaex\x0c\xd7F\x82\xa6\xb6\xee\x8d\xb2\x9c\x9a\xd8\x9e\xf2\x93\xdf{\x84\xec\x9e;,\x85\x86\x0b;\x1d\x87k\xb4\xc7\xe1\xd9Fw\\\x1aR\xdaz\xdci\xb7\xf25f\x1b\xfc\xfb\x8d\xab+\xd3\x060\x85\x9a\xa1\xddzT\x86\x01}\xc6X*g\xc7\x06\xc3Q\xbe\xc5\x00G\xea\xbb\x11L\xed\xca[ly\xa8\xad\xbd\x11BJ\xa7\xf1\x06\xc3^Il\xaa\x00a\xfenS\xf8\xe5\xccC\xeb\x01l\xb5\xaf\n\xed\xf6\x10\x94\xf7\x91\x1f6\xb7*\x1e\xc1\xe85\x1b\xf5\x8b\x07\xc7\xa3\xda\x02\x86\xadm\x01A\xe8\xbd(\xbb\x88W\x9d\xed\xba\xa5Odo\xf9.\xfc \xadhy6\x9b\xef\xa3\x0c<\xbc\x10I\xc9r\x95\xfa\xe1\x1c\xd2\x88gi\x07\x0fb\x92\x90xM\xa6\x88)t\xa4.\xfc\xf8\xc7\xe4G\x17\xd2\x85\x97\xf2\x03;\xfc\xe1O)\\\x10\x88B\xbc\xa9\xb1\xf8\x8aZpI\xae\xbb\xf0\x9c5\xe5cn:/,,\xa6E\x8b\xf8\x86x\xd3\xc7\xb4\xce\x95\x1f\x04\x90\xa4\xf4\xff\x17\x04\xbc\xc9\x84$,94o\\\xb6\x17\xff\x93>t\xbe\xe9\x11z/\x04\x9a!\xee\xb5\xeeA\xf5\xd7&\xab\x03\x12\xcf=\xa9.4\x1c\xc0d\x1c\x9eqE}\xfbq@!^F\xb6\xee8D\xbd\x87\xe7\x82\xd5z}\xe9RR\xc8^GY,\x19\x0b\xe3\x0dY\xba\xf0B\x88\xc2 \xe9\xc2\xbb\x85\x9fP\xc8\xcf\x02\x7f\x92\xc2\xd2\xbb\xa6k3\xcd\x08m\xc9c\x87Z\xd7ba\x99\xd7\x91?\xb5Q\x8f\x8ct\x0bo\xad\xe3\x86\x80\x93\xf2S\x7f\x01,?\xbc\x13}\x1ch\xf5in\xd6\\\xe3\x86Q\x99Mh\x9a\x97\xa5\xd1\x85\x1fN\xcb&\xf7\x1b\xdcA\xeb\xd3\xfd\x80d$\x98\xa8\x88E(b%cbF\xacs\xcd'\xf7\xeeQd*\xb3p,tm \x8f0?\xc3\xcc\x9b\x10\x13BEk\x12\xc7\xfe\x94\xa3\xd4,\x8e\x96\x1c\xa9\xe8\xd7\x90\xac\xc8\xc4\x9f\xf9\x13\xb40\xef\xc2q\x98d\x0c\xc3RVkI\xd2E4\x85\x10\x93\xd1N#\xbc\x01\xa6-\x06\xde\x8a\x85\xf2\xc4\x91\xf0jhjH\x1c\x97\xdd\\\x94\xb7\x82\x08\xbb\xfb\xe9\x93\x96a\xbc\xcd\xcc\xbe\xc8V!\xedn\xe3\x90q3\xa7\xf00\x11\xa5\xc8`\x1cZ%\x0d\x7f\xaaL7K(\xd9/&\xc8\x160\x8a\x8bAQ2\xceg\x02/\x19\xe9v\xe1\xa7,I\xf9\xb71\x99g\x81\x17\x17\xb6\xf4.=w\x08\xda\x86n\xde\xff\xc6\xbd\xe9 \xea:\xcf\xd7T\xa8\xe1\x8c;\xde\xc7\xfb\xa4\xf3\xf3\x98\x0e\xf60K\xa3g~8}\xeb\xf9\xb1&\x863\xc8\xac\x83G\x8f\x96P\xddf\x19\xcb\x14\xdee\xdc?.)\xff\xedh\xa3\xd0\x8b\x07\xd7Xm\x8c\x19Vxx\x8d\xd5x*\xad\xb9ch8\xf6Z\x98\x8e\xadp\xda\x95\xfe\x9a/\x02\x03{\xc5\x12\x01\xcd\xaa_;0\x1b{gt\xd2\x93\x86\x96jbQ\xcb\x0f\x9d\xd3BG\x00\x9bF\nu\x86\xd3h\xbd\x82\x01\xc4W\xe8\xe6\xd6g\xa4\xa2+(y\xbb\x13\x0c-\xf5\x9b\x16E~\xd6<\xa4w2\xf6Zr\x8f\x80\xfb\x1b\x03\x9b\x9b\x99\x80k\x95\x00\xf2\xd7\xea\x0e|\x1f\xe6V\x04\x94D\xc3*\n\xfc\xc95\xfc1A\x94\xbe$\xf8\xf3jAB\xb6\x03\xe7\x14\xbd\x8b\xadI?Ab|\xcdV\xbff8\x07\x10\x8f=\xc6\x13\xd0\x1f\x14\x19`\xa8\x1b!\x8b*\xcc\xea\xae\xf3\xba\xed\xa0\xcfCT\xf3\xaf'\xcd\xf0d\x11\xadY*\x16\x8f\xf6\xe3\xe6\x1f\xd7~[\xc3+T\x8f\xf8V\x84~a<\xef\xcbbIds\x8b\xb2\x9a\xfc\x01\x9a\xf7\xc4\x05kI\xe29\x11\x89\x97^G\xcf\xb3U@\x0fd\xf25\xb9Nlg\x08G^H\x8f]\xac\x06a\x14n\xb3f\x12$\xe0\xc4\x01\x8d\xc8\xc2r\xa7\x95.\xf5\x90\xe1k\xec\xeb]\xcc-ZXo\xe9U\xc4\xe9w\xc2\x8e{\xca\xe9'\xde\x92P\x14\x1c\xe2\xd1\xdb\xead}LA\xb4\xc2\xa8\xb3\xf4L`Vr\xa2\xea\xc4\xcb\x12nNv\x15\xa9j[\xdb\xa1G\x9c\"L\xdb\x8e\xe088\xdfMw@i\x9c\xf4p\\\xd0\xb7\x97\xe4:\x11,0gL\x0d.\xaa\xc2\x86\xb0\x15ZL\x9bL\x11e\xf6\xd2x\xee\xa1OI\xd7[\xad\x82k\xccE\xe2\xe6\xde \x89\xc1\xd1\x91>(\xd4\x1a\xbe2\xdf\x8f\n\x9b\xb8\xc2\x11%n\xae\\\x18{\x84\xe6\xd3\x1bC\x1ek\xe2G\x83t\xebf\xfbl \xf0\x87>\xd9I\xbb\xfd\xb8\xfel\xc0\x1b\x01n\x04\xea-\x87z\xdd(*\x10f=\xa7\xbb%\x16`WzR[\xd1\xe77\x06\xfd5A#h@X\xb4\x9e\x9f\xfb ~\x84F~\x9a$\xeb\xa0'\xa9U\xa4]6\x0f\xb0\xa4\xaa\xbf\xf5\x18\xf5\x06/\xad\xc6xn\x1c#\x8fY\xce/\x90Z+\xb7p|L\x1f\x1fwI\xf8sF2r\"5\xc51lc\xe95\x9fpK8 c\x9c-\x15`\xb7\x87\xd5\x859\xd90HV\xa2\xf6\x85|\xab.\xf3\xf6p\xae!m\x05d\xeb\xc8%Q\xaeT\xe3\x1a{P(\xd0\xa4*,\x88|p\x94\xf9o\xecY<%/\xc2T\xdb\xaekP\xf5Cg\x04\x83\xa6\xf6A\xd1Y6\x8b\x05\xc0%\"2\x0e\xa1\x03\xfd\x16|*&\x84\x181\xca\xe4\xdf6\x10\xc2\x0d\xa2\xaf\xc8\xb3\xb7\xe2\xda\xedj\x96c\x91\xd07&3\x0cj\xe6\x96\xf6\x850R\x0f\x0b\x93\xf9T\xe4\x172ODh\xef\xf0\x13\x85U\x80\x03\xedk\xdbiT\xe8E\xb6\x865\xf3\xd0\xb0\xaelO\x86\xcc\xf4\x1f5]\x0caI%_\x8e\xfe\xb9\xbf:\xe5]h\xd7\x16=\\\xe4\xeb)*\x050~\x9fR\xc1\xc4\x97.\xee,G\x81\x88\xa7\xdf\xad\x0d\x12o\x8c\xca\xf2\x92\xb5KH\xae\xe0\xc2\x95_\x96\x82\x88`\x8ef\xb9P\x87\xe2<\xd5\xa0'\x12\xdf\xdb+\xd9\x02\x9c8\x8e\x0b+\x9b\xb80\x17?R\xf1c\x89'\xacz-\x82\xbe\x08\xdd\xa9rS\xa2V\xb3\x1d\xd4U\xc8\x83c\x17\xed.XR\nx\xbb\xdb\xedR\x86\xb9\xaa\xdab\xcb\xe3/W\xcc\x1c\x05<\xf8\x915\xf0#\xe7$\x91\x99N\x1cy\xfe\xd3E\xa64'\x13\x8fJ\xb4\xfc\x83A\x14\x92\xffJ\xcb~ \xca\xad\x8d`p5\x80e\xd1\n5\xa9\xd3Y\x80BM\xc1\x0c#\x12j\nD\x04BM\x91p\xd8\xd3\x14\x89(\x83\xba\"\x1eWPS\x84\x91\x04u\xefE\xc8@\x8d\xd62\x8fa\xa6\xf9N\x0er\xa5\xf9\x94\x85\x052N\xcc\xf0\x15\x8f\xc8a*a\xc1\x174\xa5\xdcU\\7\x05\xe6N\xab\x98\xc3jy\xbe\xb0j:\x19\xbb\x10\x96L'C9\x9f\xeag\x10\x0e\xee>\xc9n\x00\x8a[\x13\x17\xac\xf3s\x92\xbc\x8a\xa6Y@,WA?4\xaa\x1f\xca\xd2\xcc\x0d\x1eI\xfc\xf0\xa9\xa3\x1e|\x8aUt\xce\x85\x98dh`\xef\xdeE\xab\x0b/\x1eB$\xfa\xa9\xd42Y\xad\xde(\x84\xd2\xcd\x89\xfc\x8e\x86*\xda\x94\x90\xfa\xa8\xf9\x89\xbb\x05\x14\xe0\x00b\xd0\x8dMX\xd9V\x1c\xb6\xe0\x1f\xbe(\xd5\x03be\x87v\x7f\xf7\xa1\x9a\x03\xd4\x17E{=]^QVT\xc9\x1c\x9a\xe5E\x95l\xa4^^\xb4\xaf\x16%\xdcfU=\xa8&\xcc\x0fWy;\xa3+\x82-\xed\xef1\x9e\x88\xae\xdb\xae\xa3\xb6\x1a\xf0\xf3l\xdf\xd1\xa5*]\x19\xcfg\xd4'\xa6\xe5uN\xeb\xd7\xd9D\xcdoJ\xd0^\xd4r\x07\xd2\xb9a\xba\xff\xb2{.\xf8\x02\xd7\x1d.\xe9\xea\x9c\x7fho\x88\xb8=\x172\xf5\x03\x9br\x9f\xc8v\x9d\x9f#\x13\xd6s!.*\x11\xc7a^E\xb9 \x1d\xea\\B\xc5\xa5|7\n\xdf\xc7\xc1\xd1\xc2\x0b\xe7\xa4\x95+V!\xe6\xa5^<'i\x9dCN\xd4MH\xca\xc4\x00\xb3\x80\x97\xc5\x81JE\xc5\xa3\xf1\x8b\xbeq!\xea\x06\x917=]\x91I\xab\x01GL\x0e\xebR\xa6\xf7\x10\xeb\nA\xeb}\x1c\xa0\x87\xb9\xae\xc64\xba\ni7j\xba\xf3|\x0c\x08\xb7S\xcc\x8e\xd0j\x18z\xb8\xa1\xe7\x9ax\xb3\x88\x89\xc1.\xa6\x98\xb2Mp\xc0\x14\xae\xd87\x99\xd2Y\xe0\xcdrw\x15\x935 \x85t`\x1b\x06.f\xf6>\x0eZ\x0d\\\xea;b\x82W7\x8b\x83\x0d:\xc4\xb1z\xf1\xa4~\xff\x88G\xc0\x89\xa2u\xd0]yqB\xd8\xd7\x8e)\x834\x19[Y\x1cPq\xdb_z1\n\x91\xd6Y\x1ew\xd2\xac\x9c\xa5\\\xd8\x95\x1fN\xa3\xabn\x10\xf1k~\xdcW\x93\x08#\x1f\xdc\xbfoA\xa7Rc\x11%\xa9\xe6\xf5\xcaK\x17\xe6\xeeXmJ\x98\xf8w\x0b?I\xa3\xf8\xba\xfa\x06/v\x98\xcc^-\x93un\\\xac\xb4,\x97\xc5\x1c<\xa0\x83e@KH\xec{\x81\xffK\x0e8]\x86\xde\x9b*\x1am\xb4>b\xd3\xccIz\x14\x853\x7f\x9e\xd8\x0eE\x8c\x84\xa2\xf4\xd8\xa0p\xc1I\x11I\xc7\xc4n\x86r\x899\xef^\xe7\x12Pj\x88v\xc5]\xb2\xf0B\xa7\x0d\xa5\x81<\xb5 \x99\xbe\x0c\xa7\xe4\xe3\xd0\x90\xc2\x1e8\x03$\xe1\xae1\xcb\xb1\x89FE\xe1\x0b?HI\xfc\xc5H+\x03\x7f\xe0]GYZ\xa6k\xacc\x9d\xfd [t\xae<\xd1\x0f\x02\xc9q\x8a\xb4\x90\xa1F\x14'\x14\xd8\xa6\xf8\x92\n@\xab\xfap\xdag\xe9\xa5\xd6\xf9\x88b\xae'\x9dbL;B\xdfF\xa5\xb7\xe3\xea\xa8\xf1\xbe\xcd2\x1a\x98kl\xc29g\xd5\xbc\"L\xd9\xd4\x8cYf\xa0\xb5\xc6\x992\x88T^\x10\xf4\xf3D\x9du\x8b \xd6a\\\xcau\x86f\xa5*\x11Z\xc5\xea\x8e7\x7f\xc4.q\x9a\x08\x02\xde\xa8\xd1\x1d\x1cr\xa2P\xb7\xe9\x0b\x15\xb0\x86\xe0\x9bU\x981k\x7fc\x1a\x03Hg0v1F\xc7`|e\x0bl\x10OkZ\x03z\x9ch(j\xbc\xb7o\x81D\xe2\x06\xec\x8ep\xe86g\x02\xe7\xd7\xa53\x816\x94\xf3\x1c\xe9\xb8\xd0\xf8vK\x10=C>\xe4\xf6@`Z\xce;\x9dy\xc3\x1eb\x80\xd1z\x07\xca\x0f\xbb\xfb.\x11\x13s\xe5\xb8h\x18!n\xae\x89\xf7!\xb6\xf5\xcc\x98pU<\x11\xab\xf8\x8d!i\x9fx\xd0\xc9\x8f\xae\x93\x1f\xce\xb9\x95b\x97\xffIwHVK\x1e\xbc\x9a\x9bqk\xe6\xf9\x01\x99\x1a\xda\xc4\xf3\xde\xebN\xa2\x00\x15\xf3V\x8c\xd9=!S\xdf\xff\xff<\xcf\xab\xb3\xac\x0b\xd0\x11\x80\xe1\xa7y\x9c+\x83\x0f\xa2x\x16\xb5\xf72<`\\=I\x9bb\x17f\xfa\x15TIW\xd3-+}\xa6\xccFh\"\x8eO\x9e\x9aYh\xadE:?\xdd\xfeP\x1f\xdc/5\xb6\x87\xe2\xe1\x1b'\xa50\xad'v.\xe7\xcek\xac\xa4(\x03\xb6j\x98\x03\xcb]\xd94\x054\x07e.S<\x9f\xdd6\xff\xb0\xf6\xb3E\xba\x0c^Dq\xfeQ\xd5uK<7.\x18\x87\x88\xf9\x95\xf2(f\\`\xf4\xf0\n\x86\xa2\xad\xf9;\xd6g\xd3\xdc\xfci1\xbe\xfa\xe9L\xfd\xc4\xbb\x08\xc8t\x08Y}\xc5(d<\xeb\x90\x116I\xd0\xad\xff\x8e\xaf~PO\xb0\xeb\x808uLL63{[\x08b+\xc9\xb0\xcdH\xc2\xd2\xac\xd6\x01RF\x10\xd1\xf4v\x16\x07\xdb\xfcS\xe3\x87)\xaa\x8dY\x9a\xad\x1az\xaa\x01({c\xfeFl\xa5\x02\x94Y\x1c\x98\xab\xb7Z\\\x9e#\xd1pi\xea4\xef7\xffV@\xe4\x19\xbek\xe1\x13\xf8\x93\xcbaem\xf5\x03u\xc1:\xfe\xb8\n\xa2\x984\x05;3\xa2\xc4\xd4_\xb7F\x88\x14\xb5\xd4\xfa\xcd_\xb7\xf17\xe9\xe3*\xf6V+\xf2\x85;a\x13\xd9\xbem_\x91 b\xe6\x8d\xb6\x9c\xd7\x0efA\xfc\xf9\"\x1d\x82\xb5\xd3\xab\xc1\x86+\x7f\x9a.\x9a*%\xf1d\x0831\x90\x1a6#\xa0\xfd\x9d^y\xf39\x89\xe1\xfdK\xc3\xack q\x89\x80'\xac)\xcb\xa9\xfb\x04\x13v\xb7]\x96\xd2^\x11\x8bS\xb7YN\xb3\x8b\xa5\x9f\x0eaaZ\xc1Uw\xe9\xad\xda3\x0b\x92\x04\x9et'A\x14\x8a\x898\xf4\xd3\xfa\xe3\x87q\x06f\x9an\x92\x7f\x1d\x1d\xa5W8\xf73\xc7\x95\x9a\xbe\x91\xa8R\xceCK\xdb_\xbe\xacb\x90Qojd\x18\x94\x02\x80`J~\xccxy\x7f\x15\xce\x1f_x \xd9\xdfu\xfd\x0f\xcf\xde\x9c\\\xf5\xbe\xfej\x1e\x1d\x1e\x1e\x1e\xbe>}\xbf8~??<<|\xb6K\xff&G\x87\xaf\xe8\xbf\xaf\x1e\x04\xfb\x7f\xa5?\xbe\x7f\xf1\xec\xd5\x87\xe3\xf7\xb4\xc2\xfb\xd9\xd5\xad\xfe\xeb\x05\xbf<\xbb\x1f\xf6\x9e\xcd\x16\x1f\x9f\xad~\xba>\xea}\xdc\xbd\x7f\xff\xfe\xfd\xce\xcf\xeb\xdd\xa3\xbf\xac\xfa\xcf{\x8f:\x9dY\xbast\xff\x97\xbd\xfb_\xf7\xf7\xef\xbf\xdfy\xf0\xe8\xfd\xec\xea\xf9l\xef\xe1\xfd\x9f\x1f<\xea\xbc\x8f\x07\xcf\x07'G\x97\x8f\xe8x\xfe\xfc\xdd\xc9\xe9\xbb\xe0\xd5\xe1\xf1\xf1\xe1U\xf8\xe8\xfe\xfd_v\x0e\xe7\xeb\xdd\xfb\xeb\xef_>\xbf\xaf>\xef_\x91\x9f\xfc\xfe\xe5\xe1\xe1\xe1\xf3\x87\xa7\xefO\x9e}\xf8\xf3\xfcY\xf0\xb7W/\x0e\xa3\xbf^=?|w\xf2\xf1\xe2\xbbg\x0ff\x9d\xf5\xdb\xaf\xc3\xe0\xbb\xc3\xbf\x85\xfb\x97\x83\xc9l\xe7\xf0\xd1/\xf7\xdf\xce\xde\x1c=|\xf9\xf2\xfb\xd0\xdf{\xb1\\\x1e>{\xf5\xf0\xc5\xab\xc5\xd5\xbb\xfe\x83\xc9\xa3E\xb8\xf0\xff\xf6M\xff\xe8j}\xfcM?]\xbe}\xde\xfb\xf9\xf4\xeb\x9f\xf7\xe7\xdei\xfa\xed\xfd\xcbW\xdfy\xe1\x87\xe5\xe1\x87\x93\xe7\xef\x83?\xf7\xdf\xac\xb3\xec\xdd\xcb\xd7\xd1\xfe\xe5\xa3\xde\xe9\xc7\xd9\xc3\x9f\x937\xe9\x8b\xfd\xf9\xeel\xd6\x8f\x92\xb7;o\xc2W\x93\x0f\x0f\xa6\xbb\xab_\xa6/\xdf\xa7Y?:\xdc\xfd\xd0{\xfe\xb7\xe8\xeb\xe5\xc7ep\xfc\xfd:}\xfe\xfe\xa7\x9fNw\xd2\xe5\xd7\xcb\x9f\x9fuV\xdf_?\\=\xef\x7fx;{\xf0\xd3\xdb\xe3\xde\xcb\xdd\xde\x9f\xff<\xf1\x9e]\x85\x19\xd9\x9f}\xf5\xcb\xfc\xfat/\xfd\xee\xe5\xfbG\xfbo?<\x88/\x9f\x7f\xfb\xe7\xd7\xdf|\xe8=\xffz\xf7\xc5e\xf4\xf5\xf2\xc5\xea\xf5^\xf4>\\\xfb\x0f\xbf\x8e\xc8\xe1\xe0\xfe_\xbeK\x96\xdf\xfd5\x8b.?\xf6\x12\xff\xa4\xff\xd5\xc3\xf4\x9b\xcb\xd7\xfb\xe4\xd9\xa3\xe4\x9b\xab\xbf\xac\xee__/'\xd7\xde\xdb\xfb\xef\xe2\xb7\x9d\x93\xb7\xcb\x8bW\xaf\xfc\x8f\x93\xbf|\x98\xbf;\xe9{\xef\xff\xf6h'\xfa\xea\xbbd\xfe\xdd_\x0f\xbd\xaf\xf6\x8f\xaf\xe8\xb2\x1c\x9e\xbe\xff\xf0\xe6\xe4\xeb\xbd\xa3\xef_\xbe\x1c}F\xd0\x19\xd2\xbd\xb8N\xc97Lj\xae\xd3.\n\xad\xe2\xc4N5\xf2\x18\xaai\xc6=\x8d\x84\xc34-\xaa\xe9\x1c'\x16;\xf0\xcf`\x87\xd0\x81\xd8\x81\xfb\xb0\x0b\xdb\xd2]\xe9\x8d\x0b\xa4\x9bF\xcf\xaeS\x82\xa6a\xf5\xd7f\xb9\xe9 \xb3\x10\xc4Q2\xcb\x17:*\xe6\xfc:\xee\xf3\\\x14!\xb9\x82\xa8\x92\xe4\xa7\xc6N\x03\xc7I\xa0C+\xb1q*f\xc3x{\xe6BF\xe99%\x06=\x97\x05q\x86\xa7\xd0\xc3\x0b\xe2m\xd8\x85!\xad\x120\xfb\xc5\x00\x9e\xc0\x8c\xfe\xd3\x19\xc1\xae\x83\x90\xf5\xc7iw\xb2\xf0\xe2\xa3hJ\x0eS;p\xce\xe0\xc9\x13\xe8?\x84O\x95\"\xe8@\x9f\x17\x0f\xf4\xc5\x03V\xbc\xaf/\xddq($\xc6I\xa7\x83\xe6\xfa\xf0\xf4)\xf4\xf7\xe1\x1e\x0c\xf6\xf6\xd4\xf7\x0f+\xaf\x07{{pO\x0d-5@)\x9bI\xcf\xe6\xc9\x18\x06K\xe7\xf2\xf4)\xecV;Q\x18\xb3~\xab^\xfa\xbdZ\x90\xed\x9a!\xf6\xf4)\x0cZ\x03\xc0\xd1\xa2\xb4WF\xe0Y\x1c-o\x87\xc2B\x97\xc5\x8d\x12\xe0\x8f\xb0\xc3\xc2=\x8e9>\xf782\xc36\xf8,\xc7\x83G\xff\xe9\x8c\xa0\xbf\xbf\xf3p\xc7\x81\x88\xb1\xe13\x8a\xe0\x99\x8b\xd1n\xb1\x04\x9e\x82\x07\x07\xe0\xc1\xb0x\xa7\xb2\xc0\x0c\xd2>\x1c0@\xa7c\xda\x0d\xdd?\xbc\xd1x\x8c\xc0\x19\x9c\xd1\xcd;&\x0c\xae\xf7`\x7f\x87\xbe\xb0F#\xcbq`\xc8\xb1\xc2\xcf\xd7\xcbf\xed\x0cp\x1d\x1e:\xd016\xdc\xef\x89\x96)b\xe4-\xf3\xae\x06RW\x15\xee=\xbf\x93\xfe)\xf2C\xdb\x92\xec\xb4$E\x91d\xc5\xc9 \xea\xf3\x7f)\x84\xa5\xf8\xab\x92\x9f\xdc{?L\x1f\xb2u<\x90\xff\x18\xb2\x90\x88lQ\xac\xc3gG\xcf\x8f_|\xf5\xe7\x97\x7f\xf9\xfa\x9bW\xaf\xdf\xbc\xfd\xeb\xc9\xe9\xbb\xf7\x1f\xbe\xfd\xee\xfb\xbfy\x17\x93)\x99\xcd\x17\xfeO\x97\xc12\x8cV?\xc7I\x9a\xad\xaf\xfe_\xea\xde\xb4\xc9\x91d9\x0c\xb4\xdd/k\xf6\xfe\xc2~q\xa4\x86\xdd\x99\x83\x04\n@\xdd\xa8F\xd7\xeb\xd7\xd3#55\xd3\xfdl\xaa\x1f\x9fH\x00S\xcaJ\x04\n9\x0dd\x82yTW\xcdT\xafQ\xd2R\xa2H]\xdc\x95(R\x07\x0f\x1d\xe4.IQ\xa4\xb4\x07wy\x99\xed\x9b\xf9#\xfa\x03\xfb\x17\xd6\xc2#\"32#\"\x13\xa8\xaay\xd4\xc2\xac\xbb\x00\xcf\xc88=\xdc=\xdc=\xdc\xafo\xbe\xec\xf5\x07\xbb{\xfb\x07\x87G\xc7\xed\x1d\x8b\xa7\xcbat\xa4\xc8g\xe9\xc1\x13HN\xa0\xdd\xf6\x1cqS+\xc3+b\xc18\x93Q\xd9s\xe8#O\xe7\xec\xe0\x9b\xa9z\x9e\x1d\xa4\xf4\x14\xc35\xc0O\xc0\x1e%c\x0e\xa4\x8b8z\x87\xc4\x13\xa3\xba\x15Q}\x99\xc3W\x178\x1bAO\xd0\x0b\x02\x1e\xac\xb2e\x1a\xac\x97\x98\xf0f\xaf\xaaE\xbb\xca\xef\xe7`\"\x95\xd7s\x9b.\xa6v-;\xfcN\"\xb0x\xad#\xbc\x03=\x0eq\xa3\xe4\xf1\xc8\x87\x8c0\xd3\xfeN\x8b%\xd7\xcc\xc3\xdcD\xf1s\xa4\xe0\xa1\x90\x85+.m\x90\xad@H\xff\xb4G\xb0\xeb \xc2\xd8)] Jr(\xf5\xec\x1f\x1c\xf6\xfb\x07G=\x8a\xd7\xf4 \xba\x8c#\xa6St\xdd\x1f\xf0'\x8c|\xb0\xe7\x03*\x9df\x02\xf3\xed\x88y\x18Q\xfc?\x92p>B\xc8\xa0\n9\x90\x00\x07\xbb\xf0\x08\xa2\xea\xad+>}\x99f+\xe4\xdf\x82\xb1\xd5\xb1d\x0c\xea!\x06\x1d\x0c(jY\xe7\xbaG\xbbZyC\x9eM\xd2\x8d\x897\xab\x0b\xbb\xa7\xa0\x02\x0b\xabM\xe7\xfa\x08>\x84\x80\xca\x02\x942\xa8\x12\x05\xdd\x17v\x9f\xce\xab\xe7\xe8K\xf80\x82\x04\xe7L}F\xd9r\xe7P\x85\xa3\x9f\x10\x9cb\xc3}\x18BO-\xb2\xe6E:\xf4\xb9\xa6\xea\x05K`\x04m\xa8\xe6T@\xc4B^\xbff\x14f\x01\x8f\xf8\x18:s6\x08X\xc0\xd3\xa7#\xe8\xcc\xa9\xe4\xd0\xa6;\x18\xe6t\xdb\x9d`\xf9\xc1\xfe\x01|\x88\xe1\xb2E\x03.\x88\xfa\xe6\xd0\x19\xc1\x91\xa3i\x91\"p\xa4\xb6\x14\x95[\x8a\xf3\x96\xb2\xbc\xa5l\xf3\x96(\x91`7 #\x07\xfb\xda\x87N\xf5\x06\xaa\xe1~3}5\xc2W\x8b\xcc3\x19\x9c\xc2+\xef\x15\x9da\xd8\x81\x1e\x15\xbc\x16\xf9\x9ck\xf44\xc8\xf0>\xf5\xd2Ew\x1d\xbd\xb3\x07\xec\xee[D;Z\xbe\xc8\xaa7\x17KU\xe3\xa8?,U\x15Q$\x94\xf6\x0ce\xe8\xef\xe2 \xad^\x93\xa9\xcdiBq\x9b\"6\x0b\x19\xcf\xd1\x9b\xd6\x1c\xe8\x91w\x9e\xa3\xb7o@o\xf4\xb00\xa07\xc5\xd1\xc1n\xce\xbc\xe5\xd1t\x06{\xb4\xc2\x12\xe8\xf0\xd0\xd1\xe3:\xc5\xe5\x98\x93\xd5H\xdf\x8d\x19/B\xa7\xaf\xa3y~\x85\x12\xd4\x13\xe8\xc1\xed-\xbf#\x8b\x8e\x1b,K\xc4\x13\x14\x8cq\xa7i0\x97\xce0v\xd4\xbbH\xd0-)H^y\xafl\x82>\xf2\xcc\x90\xca\xd0\xe3\x14lJ2\xf2\xc7\xbcJF\xbc\xe7tp\xb8\x0b\xb0\xae\xf92\x8ab\x1b\xbf.\xa3KZz\x87=\xf8\xe4\xd5\xc0q\x81P\\K\xa0\x8cM\x9d\xccq\xe0 \xf4\x91\xf3d\x9d\x0ee\xcb\x1f\x8e\x80\x96\xa7\x07\x82\x11\xee\x94%<\xa5\xfd9\x855\xec@\x02CXW\x10\x89n\x89\xa5CQ,\xa1E\x07\xac\xb6v\x9b\xd6\xb6\xc3j\xcb\xeb\x99\x8b1\xc9\x83(\xb5\x82Om\x82\xb5u\x18\xe6\xca\x8d\x05\xac\xb6\x11,q\xf8\xc8\xbd*E\x96\xe6\xf7F\xd0s\x9c\x13\x08hcG'(\x9f\xb5aQ\x88\xbd\x1e\xa5T\xed\x11\xcc(\xad\xdeAzA\x85\xa7:\x12\x94Qd\x0e\xe0\x96\xbe\xeb\xd3w\x83\x13\xf0\x19\xc5Q\xaa\xcf\x8a\xea\xb3\xbcz_W=\x7f\x15:0\x9b\xc2\xed\x08\xfa\x03\xba\xb1\xae*\x1c\xae\xe1P,+p\xca\xdb6\xf7\xea\x0c\xed\xdd\xc1Q\xe5\xc8[x\x85\x96\x1dk7i\xb2\xb8\x921\xd08\xdb\xc6\xdd\x9f<{\xfd\n\x1d2\xf9W\x9d\x87M\x9e\xe6fXI{S&yMW8\xccwS\xf2\n\xf9\x85\xdd@{[w\xa3\xf1\x9a\xf4\x0e\x92g\xed\xa8\x14\x0d]LPd\x87\xf6\xee\xae\xe2w\x1c\xf0GG{\x8e\xd6\xa57\xfa\xf1\xba\xf4n\xe3\xdd\xde\xa8KU\xd3(H\xf9\x185q\xbbh\xf9\x8a\xe3.\xf3\x11\xa7\xef9\x1b7\x0b\x924^g\xa5\x8eq\xa5j\x94\xcaxM\xd8\xfc\x9c\x12\x03\x161\xc1\xe0\xc3\x11\xdf\xd4(\x8a\x8bP3\xeclT\xf5\x83vN\xa0\x85>\xfaH\xf2\x92Rv\x00f\xee\x0fy\xbc\x0b\x9e\x94\xc0\x85\x16z\xce\n\xa7!\x96\x1f\xc19\xe1\xe34\x18\x85\xde\x83\xef\xb1\x84 u\xda\xf0\x88M\x15\xcb\\n\xa8g\x1e\x84\xderY7\xe4\xfa \xa1\x9f\x16\xfa\x13%]\xbe\xd4\xd2w\x83\xd3\x18l\xd84\x08\xf9L\x9c\xfb2su\xfa\xf1i\xa1\xda[\xf7X\x9ca\xa7:\xe7\xc5\xa9\xf3\xcd\xcd\x9aTN\x9e<\x80\x12\x0bV\xc5\xeeYf1\x8b\xe1\x11\xa4$\xf6.\x96E\xc0\x7f\xe5\xc2V\xd14{\xf2 \xbcb\xb7\x1a\xdb\xfa>\xbc\"\xb4\x8f\xf6\x1d\x17B\xfb\xf8\x00=\xa5\x8b\x0e\xd0\x96\x06\x1bu\xbb\xe07\xfd]\x1d\xc7 \xed\x03\xc7\xb6p\xb6\xd2(\xaez\xea\xb0\xeb\x80\xbb\xa6x\xe1\x94\x89u\x83\xe4\xa5\x98\xebM4\xc89\x85\xd2\x9eUyD\x15\xdc\x8a\xe3\x80\xa5t\xf8\xeew\xf3\xee\xe1\x9d[L\xb7U\x8d\xc9\x12\x97|k7\x9a\xde\x0dWt\xefAWtww_Y\xcb\x81\xd3\xe5w{\xbc$ .\xc3Mj\x92\xd7U\x9a\xca\xd8\x8e\xbbg\xd0\x86\xb8\xfb\xb1\x0b\x16\xabU1\"\xb2V\xd8\xe8\x0e\xa4I\xdb\x08\xa1\x9an\x9a\xeeU\xaf\x94\xf2\xa8\xef\xbd\xaa\x14\xc5p\xeb\xa0:\xbd,F\xfd~5v\xbc\xc7j\x19T\x8b'9J\xf1\xc9\xd3cj\x0b\xbd\x07C{p\xec\xd8F>-\\\xf1\xbe\xd2\xc4e \x068e\x9a,\x91\x88\xceQ\x0d}\xc8t\x9a?K\x8b\xfd<\x80\xce!e\xe9\xc9z\x19\xa4\xb6e9\x1a\xc7-\x1d\xeb!\xe3t\xaap\x9b\xf7\x8e\x0b\x87\xd0\x1aA\xc2\x82\xd5:<\xcf\x91\x9c\x1e\x91=\"\x8e\x93\xab\x89\xe8\x0b\x92%\x86\x1e\xabj\x85\x88R \xe6\x0cm/t\xces\x911We\xd3\xf3o\x9f\xd9F\x82\xee\x9cYC\xa2\xee\xfc\x84\x9e\x8b\xc0\xd7\xe4\x15\xcak^\xbbx&\xf5\xec\xbc\xd2\xb1\xdfnO\x1d\x17\xcf\xa1\xf4\xd0\x14\xdb\x0b\xa7\xebG\xa1\xef\xa5\xf6\xdc^\xa0\x02\x9a\xc2\\<\x89\xce\xf2>\xdc0\x0b\xcc\x15<\x85\x9b\x13\x07\x96\xec\x9e\xd3\xc2\xc5\xb3\xf3l|Cke\xe2\xc2xM't1^\x1b\xf4j\xd2MK\x18B\xb2\xc9\xe6\xd9\x90\xe4<\xe4\x81\x83\xd6w\\Cr(\x0elRO\xb1\xc3\x95\xbd\x19\x88\x8d\x7f\"\xb5\xda\xdf;vl\x8b\xd6n\xb9[\x88\xc65f\xb8\xc0\x8e\xa9`[Fp M7\x19E=\xf5\xda\xf9\xdc\xfe\x89A\xefv\x928\x1f\xda_xW^\xe2\xc7\xc1:\xbd\x9dy\xa9\xe7\xec\x04+u\xd4;\xe3\xcf'\xd7\x83^gr}\xf8b\xbasY-\x12\xb1:\xc7\x9f\x0f\xa7mg\xb8s\xb9RI\xdd\xd8\xeaZ.X;\xb2\xef\xb9\x19K\x12/\x0c\xd2\xe0K\xf2\x83x\xd9t\xf3@\xd8\x92\x98R5\x15\xd7~\xe8Y\xce\xd2y\xb4n\xb4\x12 k\x95\x85\xde>\x1d\xf7\xa6\x0e<\x85\x8e&'\x95\xed9\xdc\xd6\x84\x8a{\xaf\xbb\xa2\xd2\xb3\x1d9\x8e\xb0-1\x0bm\xdcMI\x922\x15\x8e\xe5]DY:\xbcXz\xe1[\x0b\x86\xe0a\xc4<\x19hB\x81M0\xa0\xc0\xe3\xdd=\xbd@\xb4\xbb\xbf\xeblc\x1e\xc6`\xf8\xdd4\xfa$zG\xe2\xe7^Bl\x0c\xd1\xda\xa6C\xa6t \x03\x96W\xe3\x9e\x1a$\xaa`\xbb!\xec\xe9\xc3:\xf4\x0f\xef\x1e\x98\x027Yy4[\xcaUE\xf7\x0e\xaa h\xf8\x04\xefU\xb98\x93\x05\xaad\x8f\x89\x02\x87U\x81\xc2\x03\xae\xfeS%\x81\x98N\xb8\x14\x93e\xc8\x05\xcarIf 8\x85\xa4+\xf2\x87\xe5\x05\xebg\x0d\xb3\x12V\xe6\x0d\x03k\xf2\xa4\x8e\xfal\x80\xaa\xc2<\x92\x93\x1b\x06<\xdfX\x1b,K-\x9a\xc9E}8\x05_\xa4\xfb\xa3\x9b\xa2\xf2\x82\xe0\xc1DS\x19\xaf\xc2\xeaa/\xc3B\x15;\x1aA\xc7\xa3\xdb\xae\xd3\xa3\xbb\xad)~\x80\x89\x9dm.!t\xfa\xdc7\x83\x07\xc1K\xb9\xa2\xb9l\xf2f\n\x90\xd89\x81v;\x84'\x10\x9f8\x10\xf0\x00\x83<\xbcv\xa8\xe6\xc6\x16s\xfa\xa0\x18\xcb9\xa5!~.Z\xed*\xc7\x11\x15\x8f\x83\x1c\xd7TdfX+\xe5\xb2\xdb\x10\x1d\xcd\x87\xac\x88\xdf\xde\xc6\xf0\xa4\xa5\x12 \xae\x86(qW\xf5\xda\x86\x94G$5\xe8m\xc4\xccUB\xd8\x95\xb4$\xef\x95.\x06h\xdbf]\xd4/`\xcc\x9d\x06NE\x07B\x18\xc2\x8c,IJ\x10R\x8ap\xd8\x8c\xa8\x02\xf5\xaa+\x99O\xfa\xb6\x13-D@1\x88\xbb\xe2\xdb\xee^\x95\xe8 \n\xaeO\x92\xb5\xbb\xaf\xcb\x92\x85\x8c\xe0\x8eC\xc8\x0bhu\x83\x04%zSx\x01:\xa5\x01c\xda\x11\xa3H:r+>\xcc]\xe5\x149>\xe5\x88hZF\xb3\xb2\xbe|\xc2\xcb\xc7v\xe8B_:\x9e\xd0w\x93e\xe0\x13\xbb&\x91\xb27N\xa76\xa5\xaaI\x193\xef\xbeR&-H\x93\xa8 0^\xefe!0)\xdfd\xdc\xd7\xe1\x14\x02J\x8dQK\xf9\xe8\x11\x84\xf0\x94\xd9\xf4R<\xd7\x88\xa6\xb6\xd8\x03\xdbv9f\xa4Z\x99_\xf3P\x98YOx\xfbt\x08<\xc5\x1eS\xda\x1e@\x1b\xbd6P\n\x0c\xf9\x03\x1c\xa0\x93\xbf\x84a\xfc\x02\x87\x91\x7f\xfar\xc8_\x0e\xa1\x83\xceXO\xa1\xe7\xb2/#\xad\xd9\xf0\x8aG\xbc`\xac#@\xd6\x11\xc3\x13\x08N\x1c\x88Xh\xb1t\x1c\xd3\x9e\xe8\xfd\x11\xa3;\xe3\xc6~u\xb76\xed\xe2A#.\x19\xe5\xb3\x94m\xb7\x94\x1dp\x1bIO3\n\x18ZJ\x0b\x15\xc4\x16M\x08\xb2`\x8d'\x93lv\xd4\xebu\xe8\xdf\xf9|>\xad\xb8\xa3\xc7\xa2Po\x97\x15\xea\xed\x1e\xcc'\x93lN\x06\xf8sN\x06\xf4\xe7\xa07\xc3\x9f\x83\x9eZ\x05\x9dd\x0b\x9b\xd9\xf5\xc7\xac\x99\x0bSs\xe8\xd85\xfe\xbc\xa1S\xe8\xc3e\x9f\x0e\xe5Jg\xe4\x00\x8b\xcf\xe6\xf3\xa9\xf3\xd5\xe0\xbd\xa52\xf0\xf2`/\xe6\xf3)\x02|sC o(\xcfk~\x9b\xe7Fw,\x16\x89A\x95Y\xb1\x999\xe9\x11\xf6g>=\x15i\xefm\xde\xe9A\xaf7\xe3\xb5\x8e\xb9G\xcd\x94\xd3\xcd[\x0bEL\xc7X\x87\xe5|XU\xff\xce\xa5^\x8e#\xd1\xd5S+\x0f\xed\xe6BX\xad\xbf\xd2\xef%\x8cx\xb6X\x1bGg\x9f\x8e\x8a\x91\xe2\xa0\xe7\xd0\x06\xdf\x05\xeb\xd2\xba\xeb\x9eH\xf9\xa9r\xe9\xb0+\xc2w\xdf\xc6\xd5s\x898\x10V\xa3\x01\x8am\xac;\xb1\xf0\xd1Z\xe3\xc7\xff\xe5\xe7~mj\xddkd\xf5\xccY\xc8JvdS.\x9c\x1f\xf13<\xe2;\x18\xb7\xc72\xdb=\x1a\xf7rC\x02U\x13\x9f\xd31\x8d\xa8F\xde\xd7Pr\x14\xff\xa2\xdc\xdf/\x1d\xb7\xdb\xc1\x14\xe9y\x00O :q\xd81\x87\n\x06\xe98\x98\xa2\xeb\x8dA\x92l:\xcf\xd4`\x83A\xcfU=s\xa3\x96g<\xb9\xf6{\x9d\xc9\xf5\xec`r=;\xeaL\xae\xe7\x07\x93\xeb9~\x99O\xb2^\x9f\x92\x82\xac\xd7?\x9cOw.kpf[zx\x1f\xe4\xb2S\x14\xdfR\xc7a\x96q\x81>\x11]\xdb\n2\xdd}\x12\x0f\x9dJ\x90\x03\xebG?g\x0d\xc1zV!\x14\xd6\x8f\xfe\x96\x1e\xfc\xb7\xf5\xe0\xbf\xa3\x07\xff\x8fz\xf0\xcf\xeb\xc1\xbfI\xc1\x9e\x02\xfe-=\xf8\xdf\xe8\xc1\xffV\x0f\xfewz\xf0\xbf\xd7\x83\xff\x1e\x05?W\xc0\xbfC\xc1\xbe\x02\xfe'\x14\\M\x91j\xfd\xe8\x0f)x\xa6\x80\x7f\x81\x82\xab D\xad\x1f\xfd}=\xf8\x17\xf5\xe0_\xd2\x83\xff\x17\n&\n\xf8\x7f\xd5\x83\x7fW\x0f\xfe==\xf8\x1fP\xf0K\x05\xfc\x0f\xf5\xe0\x7f\xa4\x07\xffc=\xf8\xf7)8P\xc0\xffA\x0f\xfe\x03=\xf8?\xea\xc1\xbfL\xc1\xaf\x14\xf0\x1fQp\xf5\n\xab\xf5\xa3\xff\x89\x82_+\xe0\xffY\x0f\xfe\xa7z\xf0?\xd3\x83\x7fE\x0f\xfeU=\xf8?Qp\xa4\x80\xff\xb3\x1e\xfc\xbf\xe9\xc1\xff\xbb\x1e\xfc\x7f\xe8\xc1\x7f\xac\x07\xff\x1a\x05\xff@\x01\xff\x0b=\xf8_\xea\xc1\xffJ\x0f\xfe\xbf(8S\xc0\xff\xb7\x1e\xfc'z\xf0\x9f\xea\xc1\xff\x9a\x82\xab d\xad\x1f\xfd\x19\x05\xdf(\xe0\xbf\xd0\x83\xff.\x05?S\xb7\xc3oS\xb8\xa7\xc2\x7f\x9d\xc2\xdf,\x14\xf8\x9fSx\xaa\xc2\x7f\x83\xc2\x93jH#\xebk=Y\xfeZO\x7f\xbf\xd6\x13\xda\xaf\x91\x88+\xe4\xed\xeb\xbf\xa3\x07\xff\xbc\x1e\x8c3\xa0\x10\xc3\xaf\x7fA\x0f\xfeE=\xf8\x1f\xe8\xc1Hh\x15\x8a\xfa\xf5\xdf\xd7\x83\x7fI\x0f\xfe\x87z0\x92 \x85,\x7f\xad\xa7\xd6_#eR\xa8\xf5\xd7\xbf\xac\x07#\x99P\xe8\xef\xd7\xffT\x0f\xfe\x15=\xf8W\xf5\xe0\x7f\xa1\x07# R\xf0\xed\xeb\x7f\xa6\x07\xffs=\xf8\xd7\xf4\xe0\x7f\xa9\x07\xe3\x9e\xfd\xab\n\xf8\xd7\xf5\xe0\xdf\xd4\x83\xff\x8d\x1e\x8c\x9b\xf3R\x01\xff\x86\x1e\xfc[z\xf0\xbf\xd5\x83\x91\xd9\xff5\x05\xfc\xdbz0\xca\x00\xca\xc6\xfc\xfaw\xf4`d\xb1\n\x07\xfb\xfaw\xf5\xe0\xdf\xd7\x83\xff@\x0f\xfeC=\x18\xd9\xb7\xc2\xd8\xbe\xfe==X\xcf4\xbf\xd6s\xc7\xaf\xffH\x0fFv\xf2\x93\n\x18\xd9\xc9\x17\n\x18\xd9\xc9_W\xc0\xff'\x05\xbfU\xc0\x7f\xac\x07#'\xf8D\x01\xff\x89\x1e\xfcgz\xf0_h\xc1\xdf\xfc-}i\xe42\xd5\x981\xd6\xd7\x7f\xaa\x07\xff\xb9\x16\xfc\xcd\xcf\xe9\xc1\x7f[\x0fF\xd2\xabH#\xdf\xfc\xbc\x1e\xfc\xf7\xf4\xe0_\xd4\x83\x91 (\"\xcd7\x7fW\x0f\xfe\x05=\xf8\x97\xf4`\xa4\xdf\x8a\x90\xf2\xcd?\xd2\x83\xff\x89\x1e\x8c\x84Z\x91/\xbe\xf9\xc7z\xf0/\xeb\xc1Hc?S\xc0\xbf\xa2\x07\xff\xaa\x1e\x8cT\xb3\x1a\x93\xc1\xfa\xe6\x9f\xeb\xc1\xbf\xa6\x07#\xa1>S\xc0\xffJ\x0f\xfeu=\xf87\xf5`\xa4\xc8\x8aT\xf0\xcd\xbf\xd6\x83\x7fC\x0f\xfe-=\x18)\xf2\x1b\x05\xfc\xef\xf4\xe0\xdf\xd6\x83\x91\xf4VC\xe4X\xdf\xfc{=\xf8w\xf4`$\xa6\x8aP\xf8\xcd\xef\xea\xc1\xbf\xaf\x07\xff\x81\x1e\xfc\x87z\xf0\x7f\xd2\x83\x91\xc6*\"\xe47\xbf\xa7\x07\xff\x07=\xf8?\xea\xc1\x7f\xa4\x07\xffg=\x18I\xef\x0f\x150\x92\xdew\n\x18I\xaf\"\xe3~\x83\xa4W\x11f\xbf\xf9c}i$\xbd?\xa3\x80\xffD\x0f\xfe3=\x18\x89\xe9\x97\n\xf8O\xf5\xe0?\xd7\x82\xbf\xc6\xd5y\xa92\x1e\x9c\xab@\xe1<\xdf\xb0\xe3\x9a\"\xb9|\x83\xc2R\xa4\xc2Q\xb0|\xac\x927\xe4\x1bI\xe1\xcab\xf2\x08a\x8ex\xdb\xab\xe9\xee\xa3Q\x945u\xdc(5\x84tL\xa6\xa5\x17\x9aT\x895J!\x83_\xc8\x81>\x1d\x89\xa2q\xcbx\xf1~\xa3\xeaKo\xde\x12zc\xbcK\x92\xf2\xe4\xdd\xdc\xf2\xc6\x9c\x92\xe4\x81\xa3}\x93\xdb]\xb2\xc2\xee\x82\x1aL\xa6x&\x9b)\x9euv\x12\xf4 \xeb\xf5:\x93\xeb\xc1|r\xbd\xebu&\xd7{\xbd\xc9\xf5\xfeEgr}\xd0\x9b\\\x1f\xd2/\x87\xf3i{\xe7\xae6j\xd1\xc9\xf0>\x9d\xf4:_N\xc7\xcf:?3\xbd\xc5\xff\xbf\x1a\xb8\xef\x11v;\xeeu\x8e\xa7\xf4+{\xc8\xbf \xf4v\xfc9\xfb\xd9\xeb\x1c\xc3t\xe7\x8e\xdd\x0f\x99g\xd8Vv\xae\xdc\x085\x99\\{\xfedr}\xd1\x9fL\xaeg\x87\x93\xc9\xf5\x9c\xfe\x87\nV:\xe1l\xc6q\xca\xd9\x9c\xe3\xa4\xb3Y\x9f\\_0\x85k\x8f+\\\x0f\xe60\x99\xa4\xf4\xf5\x8b\xc9\x84\xbe\xeb\xf5P/;\x9fO&\xe1d\x12c\xa1\xc1\x11\xfbs<\x99d\xfd\x83#Z\xa2\x7f\x84\xd6\x16Z\x11\xfb\xd3g\x7f\x06\xec\xcf.\xfb\xb3\xc7\xfe\xec\xb3?\x07\xec\xcf!\xfb\xc3\xea\xec\x1d\xb3?\x1ek\x81un\x9f\xfe\xd9\xed\xf5\xaaq\xae\x98y\xcd\x826\x0b\xecm0\x9d\xcd\xda\x96\xba\xe1P\x0b=8\xe4\xc3>\xbc\xd0[\xc9\xe8R\xd3I\x9d\xd3\x99\x9a\x1fL\x98\xb6{r\xad\xda\xba<\xad\xe9Mt\x0d-A\x95\x06\x8dU?\xeb\xfc\xcc\x84)\xdaQ\xd3\xceT\xed\x93\xeb\x191\xd9\xd7\xb60\xe4\xf9w2\xe4\xa1\x89l\xbcq\xbf\x96\x92E-\xcb\xed~\x9e\xcer\xb6\x96\x8a\xce\xeb\x8b.x\xd1-\xcd\x07\xb7&\xdb\xa9S\xb5>\xce\x8c\xd6\xc7\x85\xc1\xfa\xa8\xb5\xb5\xe2\x1d\xe8\x8d\x0c\x92\x0b\xbdA\xf2\xaad\x90\xd4\xd7G\x9f\xcd\xca\xaf\xdd\x14&\x96\xf1<\x8fs\x8f\xf3\xdf\xa6\xd3\x86\x96:\xfbt8\xbb].oW\xb71\xb9Mn\xd3\xdb+\xe28\xa7\xdc^9\x8e]\x98\xbb`}`\xa9\xf6NX+\x15}t\xfb\xc9'\xb7\x9f\xde~\xf6\xe2\xf6\xec\xf6\xcd\xedO\xbd\xa8T\x04mX\x9a*+\xfa\xb7\xdc\xa4\x7f\xe2\x8d\xa6\xe6-\x17\xf7\xfb\x87\xf6\xe9\xb0\x7f\xf6\xe6v\xf0\xea\xa3\xdb\xdd\xcf>\xba\xb5O[\xe3\xfe`w\xeaL&\xb37\x7f\xcd\xb1OG\x93\xc9\x05\x92\xf1\xf3\xa9#\xbf\x93\xa4\xb7\x83pv\xbb\x1b\xcfJ\xef\xa4\x8b\xfc\x9dg\x9d\x9fa\xef\x04.\\I\x03\xbb\x97\x8dJ0\xaf\x9b\xcd\x98\x97Y\xe48\xa8\xe6\xf4a\"\xc7a\xd5\x05\x98'@\xeb7:\xd0V;\xcc\x82l\x06_\x12vw\x9b\xe7\xc6\x9cy\xa9w\xae\xcf\x7f\xba\xf0\x92\xc5\x10o\xb6\xc5\xae\xf2p\xe5\xad\xf1\x99\x1d\xd1q\x07\x1a\x0f)\x91f\x0b+(=\xbd\xbb\\\xa6\\\xc6\x11rYU^\xe3\xf6o\xc55\x97\x0bf\x8a\xdb\x8b\xc7\xe1\x03\xed\x9d\xdd\xc4\xec\xc8\xa8\xb3%\x87\xdb\xd9\x92Y\xd6\xcc%\xf1b\x1b-\xc8\x04\x03\xb9\xe8\xa4_1\x13T\xd2U\xfd\xcaD\x18\x7f;f\x1e\xeb\xe3\xfe\xb4\xde\xb4N?\x89\x9c\x0b\x92\xf6\x81e\xed\x92\xc1\xdc\xab\x11\x13x\xca\xf0K\x82\xf2i\x19\xb8\xf0(\x12fe`\x82%\xbd\xf2\x1d\x8f-/u\x1c6\xca\xd2Z\x84\x970\xb5\x9d\xf1d\xfa\xd5\xfb\xdb\xe9\xce%\xd2\xf1\x0f\x1eYR\xb1r3\xb7\xf9}\x07\xa7\xfb\xe1)R\xf4\x89\xed\xdc\xe2\x06\xea\xb69`\xea`M\x1f\xf4\xbb\x1f\x9e2~\xf5\xc1\x9d\xe9z\xcbn\xa1\x0b\x1b%n\xc2\x03\x01o\x1e`\x18\x8d!x\x0e\x13\xfb\xb3\xd2\x8d\x9f\xcdQ'\xcf\xe5\xa6$\xbe\xccs\xb9\xed\x8c?\xefN\xdb\x1f\xect\xc95\xf1m\x8cR\x16\xe0m\xa8\xe2[\xf7\xe5\x8b\xf3\xef\x7f\xf6\xfa\xcdk\xbc\x87j\xe1\xa5\x15\x8b\xdf\xf6Kb\xdf9\xefw\x99\x03W\xd9\x15\x7f\xbb\x99hE\xcc\xd9%\x08\xb7M\xfa)\xed^gl\x9d\x9f\xfbQL:_$\xe7\xc9\xc2\x8b\xc9\xec\xfc\xdct\xa7\xe8\xae*\x05\x8dc\xff\xc6\n\x83\xe6C\xdbf\xb3&\x18\x03\xd2\x96\x85\x87\xac\xe3\xd1\xa3\xdc5\\\xa6I\xe3T\xef\xe6Y\x90\xa5\x0e\x0b\x1e\xc6c\xc6\x90;\xcf\xbe\xce\xfb\xd3:?_F3/Y\x9cSF\x7f\x9e\xc7\x94;?\xd7\x1c\xb9\x14\xbf\xf4\xf2\xf6\xdc\x16\xb5J\x93$\xa6\xa3<\x17\xc1\x1cl\xc5\x83\x0b\xa4\xb33Q\xa6\x0fJ\xde\xca<\xc4P\xbe\xdau\x99\xf4\x85\x7f-\xbf\xba\x82\xd7]N\xd9\x8dU\xe12\xfe\xa0s\xff\xe3\x9f\xce\xfc\xda\xc2i\xf9\n;\x8e0\x90\xc6\xfd\xa0\xe3\xac\xc1\xb1\xa61j\xf6\xb2X\xf9\xe6a\x16;\xa8]\xde\x89L\x18\xeb\xbb\x10\xb2\xdb\xc8\xe8\xc7')\xd7\x08\xf7\xfa&L8\xb8/uh\x12I\xc6\xd3\x07\x12B\xb42\x08\x0b\xd5\"\x89a\xebe\xe0\x93\xa6\x89\xdf\x08\xb9\xf4Bo\xccPH\xbb$-;\x14\xc1\xb6l\xba;\x8b\x04i\x1d\x8c\x1aE\xba\xebh\x8d\xa9\xda\x0bl\xc4k\x15.t:\xf9\x1c\xb9\xd0\xbb\x13\xbb\x15\x93\xf4\x974\xf8\x90\xc7\x13+T\xb6\xe3p:\xee7q\x9f\x87\x1cI\xee\x8b[\x1e\n\xa5t\xa5\x9b\xb1\x0f\xdf\x93Mw\xb2:\xad\x18q\xca\xae\xb9E\xc7\xa7\xd5n\xb7%\x0c\xe1at\xc6\xb4\xe1)^\xb3\x0f\xc7\x01\x9dm\x96\xe0~\x83}m\x1e\xed~\xe3hM\x18\x14\x8bT\xa5\x0e?P\x99n\x96\xdd\x95\xfb7\x12#3r\xb3\x1b\xa1\xa9\xb6;\xf2\xd5Q\x8clb\xb1\xac\xdb\x12\x80e\xcd\x96\x00\x17Q\xb4$^\xc8!\xa7\x94\x0d\xf0T\xae\x16\xb2\x9d\x94\xae \x93\xc8F\xf7\x90)\xb7_\x8c\xd2&\xc0\xb5\xb8$\x1b\xa8\xee\xbf\xdd.0\xd6\xf4-v\xa1f\x03\x16\xdd\xd0\xef\xbe\x101QO\xd3P\xd7\x80\x95\xbbe\x86\x1brv6\xcaoW\xf5\xef\xb7\xedv\x8f\xf6\x1c;\xb4\xf7v\x0f\x9c\xad\x8c\x90\xe63{_\x7f\x1f\xeaPw\x18\x0b\xed\xc3\x83\xc696,s^\x80q\xb3\xcc$\xd0zE\xe0!\xdd]F*\x0c\xb7\x02\xbci\xad\xbe/\xeaH\x04\xb5\xdc\xd5\xd4\x00\xfc\xaed\x84\xe1*\xc3\xda\xbe\xcb\x1f>\x8e\xc4\xf6\xc6\xe9\x14/lx\x86l\x17\nT\x85\xd0^\xfa\x94\xe0\xe4\xd3a\x14\xe0}\xe4Jp\n\xde8AQ\xdc\xa7\x82\xaa\xaf\x91\xc7\x01\xee\xa3Q<2\xdc\xa1P\xe2\xf8p\xbd\xeb\xd1\xde\xd6\xa8 \xc8l`\xa2\xf8\xfd\x928\xf4\xe8\x11\xa6*\x18\x0f\xa6\xec\xd6*\xfd\xde\x9b\xba\x0c\xd8\x9fR~\x96\xb7\xa5\x18\x8e\xa1z\x04J)Af<\xd4Ub<\xdcu\xd6\xfa\x87\xd5\xfbF\xe2:\xa1N\xe5\xd5W\xd5]\x83\xa69\x14wx<\xddd&H\x98\xf8]|e\xf8\x18\xba+`i3b=\xe5\xa3\x0d{\x0e\x96\xbc\xc1(M\x0b\x17f.\xac\xd9\xaep\xe1\xca@1\x91\xee\xca]\xbeAO\x8b\x99\x0b\x0b\x17\"\xb8\xe5w\x0c\xaf\xe8\xa6\xbc\xa9\x1fA\xcd\n\x8a\xb7\xee~\xfak\xbc\xad[]\x91\xeaA\x94Yy\xb6:\x8b\xdeC\xdel>L\x91\x8d\x85dZ\x96\xcb\xfd\x0f\xdea\xb91\xd1\xdf\xcd$\xc6\x07j\xeb\x9e\xa2\xa1>|P\xbf\xaf\xf7b\xea\xf7\xaaV4$\xd5\xbd\xc6 \x1f\x9b\x1e\xf04\xc4\x17D\xf4\xcbh\xae\xde\xd7\x04I8\n\x0d\xb5@.\x1dQF\xe7 &\xfa\x042\x16C\x9aO\xabW:\x13\x96\x11\xbd\xdd\x0e9\x06Q\xa8Z\xbd2\x0e\x10)z<\x13?\x85F1YH\xc9\xf7\x13\x8c\xcd\x8cX/\xc8\xee\x1e\xeb=\xd5\xf6zz\x83\xe8^\xbf\x8a\x12\xc8{\x95@H>\x17\x8e\xaa\x885\xe7\xf0*\".U\xb1\x00\xbdI\x84\xad\xeb\x99\x08\xa2WuOY\x94K\xc5\xdeM\xb5\xc4L.\xc18v\xb5\xc8\xd5\xfd5\xb0B>\xb9q\xe1\xd2\x85\x95\x0e\xfd)\x9a$\xdalT\x17\xf8\x84h\x9e\xbc\x83\x11\x9c\xc3),`\x08\x9e\xf6\xddk\x18\xc1E^BW\xc7\x19e\xf4\xb4\xa2wT\xacY\xc3)\xcc`\x08\xef\x1c\xfak\xa6\x16\x7fA\x8b\xd3Z\xaf\xe5\xe2\xd7\xa6\xe2\xcfD\xc5\xd7\xean~F\xf9\xb9\x8f\xd62u#\xe3&\xf5\xe5`Q\xad\xbe\xba\xd7\xcey\\\xe23\x0c\xd5\\\xb3\xbb\xf2\xf6Zgy\x85+T.\xae\x04;s\\8\xa7\x909S\xfc\x06\x9aU\x1bB\xc4\xa1\xefJ\x0f\xd4\xb1\xb5\xec\x10\x1ea\x90|=\x8dz\x0d#8Cer\x1e\xd9\xc8:?g\x89\x0eg\xe7\xe7\xa6\x0c\xd3_\xc0\x08^H\xaf\x91\xeakzj\x87\xf6\xbe/\xea\x0e\x83o)\x8e\xc3)\xa4,\x984*Vk2H\xbe\x84\x11|\x81Z\xd8\xa28\xd1\xcbD\xc6\xc9\xbe\xb4\xdf\xba\xf0R\xcc\xe3J=&n\"\x03\xb5pQm\xb5\xf6L]\xbe;3F\x95\xd3qc\xec\xb1\xfe\xd4\xb7{\xbc\xaf\xf5\x0b\xc9\xbe}\xbf\x90\xaa\x8c&;\x88`\x01o6\xb3\xd31\x99V'\x83~2\x89\xbey\xb3\x19\x06\xb5* \x94#2\xaf\x8eLq\xe0\x88\xca\xbe\x1a\x99v~\xab\x93\x1b\xde\xcf\xe2\xb3\x91D\xc4\x99i\xe8l\xc48\x7f\x9cbXs[f\xf3t\x8aM\x90\xa6&\x8c\x08m\x8acx\xac\x8fi\xac\xb8\x9ad\x06\xa9\x81\xbbE\x1d\xeb\xa5\x80\xbd^\x95\xdf\xfb*_\xa7\"\xc0@\xe5\xfe9\x8b\xfe\x1e\xd3\x15WytI\x1c\xf8\xc8K\x15G\xd5\x92$\x80a\xd7k%\x81O\xbd\xb5N\x0c\xc8\x9f\xbfB\xa5v\xb5\xc8\x8d\\\x849\xb6T\x8b\\\xcaE\xce\x88\"l\xacJ\xcfQ\x97^-r^*\x82\xca\xf4j\x91\x0bE\xee\xf9^6\x9f\xab\x1d~W\x996\xef\xa7\x02\xf2\xaeZ\xe8z\xe3@\x94g(\x17\x9c\xc25c\x0b\xaf\xe7\x1b\x07\xfe\x13\xb4:v\xe1\xda\x85\x17.<\xab\xa2~\xf2.\xc0\x08|Z\x1d\x96\xef%\x04\xde\x0d\x158p\x06\x98\xcayA[\xa3r\x9e\xd0\xdb[`\xcf_\xcf\xe7 I\x8b\xe7\xecw\xad\x00B?)\x06\x10\xbb\xc0 vy\xf4T\xf6K-\x8f\x1d\xbd\xd0w4\xb7|6\xf5\xb6\xf5\xc2\xa6\xc4=\xc0\xab\x1e\xec\x1bqtY\xbf\xb1\xb5\xa5\xda\x1a\xc2\xd7\x06\xf8Um\xef\"\xbb\x9d\xba\xd0\xd6i\x9d\xf1\xedE\xed\xdbi7\xf4V\x84\xe9/\xf1\x1b\x06jY\x91$\xf1.9\x98\xff0T\x7fc\xe8\xf4\xaa\xbeYfYR\x83\x88\xe6\xef\xcf\xf4\xef\x0bQ\xcd3\xbcvi~\xed\x0b\xe6.P\xcd\x1d&>\xb9Xf\xd3\xfa\x13\x0ch\x8d'\xbd\x96\xd0P\xa0\xb4\xfaE#\xf6 \xe9\xed\x19\xd74\x98\x9b{\x9b\xd7\xf5\x16\xe7\xc3 \xaf\xc1\xed\x08\xe6.<+\x0e\xa2\xe6\x86_b8\xc5\xd7\x88\x88\xaf\xd1T m\xe0Zy\xf0Y\xa1\xb1q\xe1\xa5az\xcf\xcd;\xba\x10\xe3\xcfD\xccJ:\xa83\x11M\xb6\xf4\xa2^v\xbc\xbb\x11\xdb\xe9\x16 3\xf5\x94\xed\xae.i\xdb\xca\x87<\xad\x0e\"\x8cA\xf5\xa5\x89\xb7\xaf v\x85\x15\x8e\xdbm2\x85\x11:\xf5\xa7\x95\xcbq\xce\xb7\xa11\xfbv\x86W;65\xa1@\xd3\xb0\x8cx\xb0\xd7\xd3i\xcc\xfa\xaa\x08\xf5@\xda\x03\x9ewO7\x89\xa8Q\x81G\x10\xa8\xf38gv[\xcd\x89\x123\xef\x19S\xa5.1m\x82M\x1c\xc9\xd2\xd4\xf2\x8d\xf4\xa8Hm\x00#X\x9e\xc0\xba\xc6\xe4\x81\xb9\xb9\xc7k\x83]\xa0e\xfb\xa8\xb1\xc0\xdc(C\xc9\xcbn\xe1lh\xe3\xa0m\xcc\xd03YG\x13i\x1b3\x96[\x88>\x96T\x0c3\x0d]\x14\xe6\x82V%Bg\"+\xea\xd8\x0f\x8dCO>+T4\xf4\xe9il\x0dO`i\x9c\x99K\xb4\xa7\x88\xf91\x98UV\xe8\xce\xb80L_\xe6\xe4\xfa$\x1fox\xae\xf0\xfc\xbb@,J\x11\x7f\x86\x90\xd9\xf4H\x8cP\x86^\x89\xc9\x8c,\x9b3\xce\xe1\x94\xf6p4b\xc7y\x8fW\xc2P\x13\xeb=7\x9b\x9cQE\xa3\xe7 \x171\xf1\xde*OT\x83\xf0\x0d2L\x94\xb2\xfd\xc2\xb7\x1d\xfdF\x16u\x14\x1f\x0dI\x88\xbf7\xa6\x89\xbf@!N\xaaU?\xf5\xefP\xba\x93\x8a\xa9\x03\xba\xa0\xfb\xe6\x1dm\xad\xdc\xc9\x80\xa7lS\xa0\x8c\xd3\xdb\x96\xd8\xf0r\xd8\xf5\x0b\xfa\xecBV{#D[\x16\xdb|'\x97}\xc7\xfc\xd0\xd9\xd4o\xc0\x12\x13\x99)\xe7?(\x82o\x99\x88P\xa6\x91\xfa\xeb\x0e{=}\x0c\xca\xbb\xfbN`\x10\xe1\xc8\x85\xe0\xce\xc7\xe2\xbd\x9e\xfe\xbe\xd0Qc\x97\xd4ZE\xcd\x11\x8b\xefnpHc\xaa\xc6\x08o`G.\x84\x1b\xdc\x0ehf\xb2\x1a\xbd\x816^=)\xc5\xa7\xcf5KR|\xfat\x1c@\x1bX\x8c\xfaqh\xf0>\xbf\xfbl\x9b\xf2\xae\xe8\x8c\x11\n\x0b]s\xe6\xf92y\x11f+\x96\xb0K\xd5R\xf0\xd7.I*\xf1[vfNT\xddEV\xca\x0c\xa4#\x15\xc2J#\xa9\xe5\xc6S\x18V\x0c\xfe.\xc46\xcb\x1b\x94\xd7\xa6\x0dO \xd5XD\xb8'\x1aMh5K\x0c\x0c!\xd0\xe3\xa4\xf7-#M}\x92\x83\x9e\xc8\xe9/c\x91\x9e\xe0f,\x0f\xbf\x86\x89a\x8cN\xf4\xe2D\xea\x15\x8d\x83v\x1b\x13\xc4o@\xc1\x9aB^7N\x84\x81\xb8\xdc\xfd\xa6\xe6\x9eAy\xdc?\xd4_B\xd4'\x0dQme<\x81X\xbf*\x82&\x06\x1b\x9a\xee.\xd7\xf6r\xa8\x8e\xc4\x85\"\xec\x84\xb2\x92\xe8D\x83\xa99\x02\xa3\x00\xca\x9e\xb7\xd0\x19$\xd3\x96ZWJ\xb5\x96(\xbci\xcb.P\x0e\xbe\xbd\x859\xfdoI\xff[\xab\xa5f\x98\xb3\xfc\x94\xb2\x8c\x1c}\x99\xae\x8d\xca0\xba\x9c\xa1r\xce-\xa3\x84\x87~)<\xbe}\xcb\xcf74\xbb\xeb\x8b\xf2\xb3m\xb1*\x90m\xdf\xb0.\"8BUS\x01\xb6\xd6^LB\x0e\xc0\xf7\xd7\xac S,I\x05\x0b\xd5P\x05\xf8Z\xaa\xd2a\xe2\xda\x8d\x0bW\x0e~\x9f1\x03\xf7\x8d\x9e/\xcd\xee\xbb\x8b6&'\"-\xac\xa0\x17\xe9\x89\x03\xb1\xc8\x8a\x12\xea{\x17\xdfy+\xeasS\xec\xe96\xa2\xce\xb6\xdc\xb4?\x0c\xb4#\xe0w\xbab\xae\xa3\xf8\xb6h\xd4\xdd\x15\x1a\xa6\xa4\x1d\xfd\xaa\xec\x16\xe9',\xc3d\x82\xc5\xf4d\xe3|\xfa>^F^\xba;\xe0\xb6w$\xe3\x95\x87\x07{\xfa\x87/\x85\x86E\xf7\xa4\x7f`|dj\xacP\xd9\xe8\x1f=_z\xab5\x99\x99K\x98\xda\xa4\xcfJ\x8db\xa6\xdc\xb1\x0e\x83*o\xea\xeb+\xe9\xeb+\xcfr\xf3G\x05^\xe8\xee\xd5\x07D\x01r\xfbGu58\xae(\x0f\xd0\x18R\x81 \x03H\x05,<(*`a\x0b\xa9\x80\xd1\xfeQ\x85q\x9bG\x05\xfcC\xe2\xbd\xcd\xfb\xd1\xea\xbb\xdbm\xc1\x88o\xc1 '\xf8\xf8\xb3\xd5\xca\xc6tW61\xf7\xc6\x1d\xd9\xec\xcf]#L\xa6fu\xe5F\xfb\xb8F\xf3Ul\xf1\xbeb\xf3\x03\xbe\xcf-6\xc3\xa5d_tr\x18\x1b#\xdd0\x9a\x9177k\x06S\xab\xc0tQx&U\xeba)\xca\xb1\x9e\xb4T\x8f\xc6\xb5\x80\xd2\x10vs\xb8\x98\xe0\x11\xaf\x1a-O>I4~\xba^\x1da\x14\x9f\xfa\xc4\xd3W\xb6+\\Q\x95\xfe\xb1\x98S\\\x8b\xb3\xfbG}'?Zn\xce\x15\xfa\x86\x03Z\x7f\xa3\x03\xdav\xb2eu\xe9P\xf7\x14\xcb \xe3U\x7fx\xa1=\x1eO\x0d\"YHE\xb2\"\x85\xbct\xc8\nq\xff\x97U1-\x9eF\x8e\xb9:\x98\xa4\x8fm\xeeU]\x19\xd2tm;\x19b\xa0<\xe5\xbfQ\xfd$\x99\xbbF\xa0W(\x11>\xc2\xdc\x92{{\xdb\x9cv\xa9\x06E\x8eD\x8e~\x0c0\xe0\xf2\xa1nu\xed\xa6\x99\xba\x9a=!\xf22uW\x1bR\x9b\xca\x92\xf7\xa2\xb1\xd2\x90\x07\x86\x84\xd0\x067\xd9\xbdA\xd5W\x92\xfbP\x0e\xaa'4\xeeC9\xa8\n]\x89^F\xe3N\x94\x8as\x06=t\xf9v\\\x81b0\x0e\xbb\x1axg\x8d\xd0\xa8\x02] 4\xab@g\x08\xad\xe6\xdf\xa3\x07#\x89 \xb2L'\x1a\xb1\x84\xee\xae+4[\xc7\xf8\xbf$\xe4\xd8}\x87\x1dJ\x82\xd2\xbb\xc8\xed\x8b\xd7\x02,\x12\x95\x8a|?\x8eVABD1J\xae\x93hyElV_V*\x8c\xc2FQ_\xc6\xceD\xa5\"\xb9\x90Q\x14\xf3\x9cB\x87\xda\xbcA\xf5\x87\xd2P\xe7c*.;\x96\xb6sM\xc69\xc4>8\x05\x9f\xa2\xba\x9a*\x93\xc7?\x10^\x12Z\xfb\x1e\xdaT\xe7\xb5\x96r\xcd\xca\xa9\xdc\xce\xe4V\xa0\xab\x07\xa7\xd3P\x85\xc6\x03AWE\xbe\xca\x86j\xea]\x0e\xca\xebo\xa8\xc2`\xfe\xafV\x91\xe3\x87\x81\x94\x80\x96MT\x92U_mGovw\x1d;\xb4\x0f\x1d\x17,\xb1&\xa6(5[\xdej\x94j\xe6S\xfc\xf0\x15\x9f\x91\xf4\xe1+\xe5\xcb\xf0@\x15\xf7\x8f\x0c\xa1\xd4\xb6\xb7D\xe4\x82\x87\xb8\xbf\xe7\xf2\xdb)B\xb5\x1e\xd6\x18E#\xaeeW\xb7>p\xa6\x91\x8e#\x9d\xba\x94\xa9Kx~\xb4\xd8\xce\x1cSX[\xd8\\\x8a\xa9\xb9B`\xba\x01\xa9\x0f_\xb57\xd0)\x0b(\xbb\xd4\xc5\xaf\xd2\xad\x86PhV\xcb3\xfewXe\x8bs\xd5\x04\xbf\xdc\xf0\n\xa1A\xc6\xc8\xf8\xe1\xd1c\x99A\x13\xdb\xc7\x95%\xcdW+\x85\x9e;\xd0\x05%\x90Z\x90L\xac\xec\xd4\x90\x07\x17\x89\xd8\x9bh \"\xb8\xc0s\xb8\x85\xe5\x03\xc92\xfd\xa3\x8dn\x83\x1bL[\xb8\xf0\xba@I,\x9d\xa7^|\x96\x86\x1a\xc0)\xa6\xc1mJ|k\xe8\xfe\xce\xf8\xf3\xeex2\x9d\xb6o'c\xfbthwN'\xb3\xb6}:\x9ct'\xb3\xb6s\xea\xdc\xdac\xeb\xf1\xd4\xb1\xe9\xb3\xd3\xd6d\xe0\x8c?\x9fL\xa6\xb7\x93I\xd7\xf9\xf0\xd4\x99\x0c\x9c\xc9\xf4\xd6>\x1d\xe1\x1b\xb7\x93\xf1d\xea\x14_o?p\x9cj^3:\xdc\x9d\xc9\xc4\x9eL\x9c\xd3\xea3\x81\xebGN\x83\x1b\x8a\xe9\xc8\x02\xc5\x0c\xed\x1d\xb0\x9b\xb8\x98N\xf6y4#\x98RV:\x98X\x16r\x14\x11\xfa,.O\x17s\xa2\x8cLGa^GLq\xab\x94C\xff\x83>f\xa2E\xe5y\xaa3A\xc9!%\x18D\x8f:\xd16\x8bH \x8a\xce\x89f\xbf\xf9\x1a\x99I\x06C\xec\xab_\x05\x90,y\"\xf8\x00W5\x84\"\xb4\xa2[\xf1\x14\x026 \n\x8c\x11x\xdf\xf3\x17\xfa\xb8\x07w\xa6\xb4{\xbb\xfa\x83\xc6\xdench\xc3\x1ab\x86\x1b\xb6\xc5\x8f\x92\xe2\x8eK\xdct\x00\xbc\xcf\x11\xad\xd4\")\x9d\xc8\xef:5}\xc35\xfc-mj\x8a\xedL\xd8\xd4\xf4,\xe8\xf0\xae~\x00\xb9X\xe0s\xcb\x07\xe5Q6)\x82\x009\xb9\x15j\xc9\xbcd\xa0\xdd\xf6\xe1 \xcck\xafg'6\x19\xfbS\xa3\xdf\xceR\x90g1\xf7\xd8\xbf5=k\xa1\xbf\x8d\xfa^\xca/s\x97\x1eh\xc5\x074\xac\xd1>\xb6F0\x87SX\xc2\x10Z-{\x0ef\x031g\xa1s\xfc\x9b\xd9k\x17\xe6\xdc\xbekKq\x13\xef\x8d\x87\x06$\xbc\xbb\x97\xc2\xae\xde'doW\xef\xbf\xa2\xca5\xd9\xa6\xc8c\xe8z\xc4\x9cD\x98G\x01\x06\xbcj\xde9w\x9e\xa7\xbc@\x9d\xc2Z,1)\x87\xa8\xaaz\x8c\xdeu\xca7\x91J\xee\xd3\xfd\xb8\x12\xb9\x0e\xee\xd3\xd9\xbd\xdd\xaa2T\xa8\x83\xf4\xa9\xb2\xf7vu\xc4\xe8S/]tW\xdeu\xd3\xb0\xcd\xc2\x98W\xb3\xf5TMA\xcb\xcb\xd5\xaa\x9d\x8aO\xde\x95\x88\x98\xc1+\x13I\xcb#\x93B4\xc9\x13\x9e'\xe8\x0d\xeeA\x1b\x12\x0c\xbc\xe62^\x1c\xd0\xf9\xdeu\\H\xee\x8f\xb6\xc2\x15V\xd1o\xe44V\xf6eb\xde(!\xb4\x01\x05\x9e>\x0c\xa1\xd3wN\xf06K\xd4\xe9\xc0\x10\xda\xed\x88%TW\x90\x85N\x13\xb1\xe9\x91\x0b\xbd\xca$Et\xa4\x9d\x86\xbb\xc7D\xdb\xdbm\xce\xc4_#\xec\x98d\x12\xf8 \xe8\xeb%\x12\xb1w\xe9\xd2\x12\xe8\xa0\x10N`\xd8\x18\xc2\xc1<\x82=\x9d\xa8\xd2\x87\x9d\xaa\"\x0b\xe3\xbbt\x0f\x8f\x0f\x0f\x8ew\xfb\xbb{G\x07\x83\xdd\xfe\xfe!\xd9\xed\x1dm;\x01\xb9\xaa\xfb\x94\xf9^1S\x01\x13\xe3\xa8\x04\x8b_;\x01{\xcc\xc2\xbeu\xe8\xfa\xf7\x1d\xf8\x10\x1d\xeeR\xb1SR:r\xfc7\x92!w\x9d\x0b%^3\xd7&\xe8\xb4\xc3\xaf\xbcW*-\xd8\xf9|\x92\xb4o'I\xfb\x83\xea)\x83Ex\x1ew\xda\xd3\xde\xf5\xb8\xd79\xf6:\xf3i\xfb\x83\x9d@\x15Vv>\xef]\x8c{}\xcdS\x9f=\x8d\xc6\xbd\xce\xa1\xe61\xe5\xe0k/N\xc8\xcb0\xddvI\xe8\x8e\x91\xa3\xbd #`\xbeqR\x95\x10\x05\xb6yc\xa1J\xd3p=\\\xe0\xbf\xd6\xc6\x91\xe6\xd7\xcfN\x8b\xef\xecJ\xb3^\xe8\x89\xd9\xc9\x9e\xdd\x10\xa2\x9b\xa1T\xea\xbd:J\x11\xe4\xae\xa5\x19e\x19\x8f\xda\x95&\xd9e\xb1r2j\x95\x00\x87,\xac6K\x14\xa3\xdd\xc4xN\xf3E\x118\x85\xb9\x9dv\x93e\xe0\x13{\x80j\xa7S\x18\xc0\x10\x8e\xe8\xa8=\xa9X\x84}\xba+r\xf7\x15uK\x03\xb7\xdb\xab\x8a\xd8\x99V \xe7\xa6\x8f\xbdf!\xc9\xcc\x01\x19\xf7a\xb2\x12\xe5W\x86iC)4\xaf\x86\xb2-\x8aGL\x8c\xa1VE\xf1\xfcc\xd3\x172.\xdaf\xf0\x04\"\xe6\xe8\xd4\xc7\xb8q\x81\xed\x8d\xb3)\xbbH\xe6\x9c\x98\xf5\xd1\xa6\xd8\xe7\xdb\xae\x84\x9eN\x18\x82\x0d\xa9\xea\x98L\x08T\x1b\xac\xa7\x86)\xe0\nd\xf2\nT\xef\x1f\x89\x83\x93\xf0\x8d\xd0\xd2\xdeV\xab$\xd5x\x18\x1b\x86\xb1\x8e\x08\xf7e\xae\xe0\x18\x96\xa2\xdfz\xb9\xbe+\xe4\xee\x9f\xe1\x98L\xb7\x8f\x99ne \xc1\xec8~*\x99/\xb9\xd3\x05\x0b\x97!\x9clx<\x18\x92|\x1a\xcd\xb2%\xb1\\\x85\xc1,32,E\x8es\\\xbcs\xbd\x8a\x82/\xc9\xec\xcc[\xad\x97\xe4\xe38Z\x9d\xf9\x0b\xb2\xf2`$=|\x1e\x13/%\x7f\xe3\xd3O^\\c1\x16J\x0d\xbf\xfe\x8d\xd5\xb2\xf2R\x10\xceI,\xfdN\xd4\x9a\xb9\xa1\x1bH\xd7Wk^\x9eh\xf0\xa9\xaf\xa4H \x90\xe7\x87\xf6\xde>=n*H\x85\x8f\x0ev\x9dM\xa3\xb1\xc8|\"\xed\x16\x13\xc9e9\x95\x1a\xcc\xc8\xdc\xcb\x96\xe9\xb0z\xab\xf4;\xea7\x81kj%\"\xf3Q\x8e\x04&\xaa\xcc\xbb'\x90L)\xf3^= \xb2\xa2\xe7d\xe5\x05\xcb-Z\xc8\x12\x12\x7f\x97\xb0\xd5\xe8\xfa\xd1j\xa3\xb6x\xbf\xceg^J:i\xb0\"\xd6\xe6-\xa2\xaf\xc5G^J\x9cn\x1a\xbd<{\xcd\xbc@m\x8d\x1dBs\xda\xc5\xcd\xb9y[\xbd\xcd+=\x9f/#/}\xe0\xaa\x830%\x97\x0f\xdea\x1eD{X#T\x88\x8fX\xe5<\xee\xb6t\x8c\xe9r\x94fQ1\xf8\x0f\xb5\xfd2\xba\xab\x07\xd0\xfaN\\\xe5\xfel#\xb0{.\xc4]\xe6`\x11\xcco\x1c\xadB\x03rC\x8b\x9a\x82H|\x02|>\x8f\xe2\x95g\x88\\EI\x827\xc6\xfc\x91\xe7\x16\xb4!\x98\xa2\x0b\x90\xf6\x12\x92\xc0K\xec]\x90|\x9c\x85\xbecGx\x82\xb2\xd1\x1ek\xfd |\x1bF\xefBxs\xb3&C\xa0\xf5\xa5\xd8\xbb\xba\xa9\xf1M\xc40\xa7J\xa9^u)\x0e\x85\x9e\xf0%\x17\x97\xb2\x9fB\x1f\x8a\x9c\x14\x94\xc9\xe7E\xc6\xfd)\x15\xde\xe4\x9f\x98\xc7\xca8{\xcaR\xe8\xe2\xc5\x81\xf0\xf9\xadY\n\xb4yw9\xfd\xd0\x17\xf1\xb0\x08\xbf\xc4\x17\x10\x8dg/\xf0\xf9\n\xba\xdel\x16\xd0\xc9\xf1\x96\xdfo(?\xc7\xf2AJV\x86\x02h\x14\xe9\x06\xa1\xbf\xccf\xe43\xe2\xcd^\x87\xcb\x1b}\xd1\xb5\\\xf4\x87q\x90\x12ZV/\xe8I\xd3\x9f9e\xdc\x99\x11\xb2^\xdePz\xb6\xfe\xeb\xe4\xc6\xc1#\xff\x07\x1f\xc4dnma\xa5\x94\xe5\x8a\x92ou7\x08g\xe4\xfa\xf5\xdc\xb6\xfe\x8aU\xc9\xcc >\xefM\x16\xa2H\xef\x7f\x1c\xb0\xe0\xb7\x91\xe4\x1a\xae\x176kb\xec\x82hc.f\xc3 \xaf\x8a\xdb6^\x1c{7*\x97\x01\xedy\x01U0\x85\xb7\xf9\xc8l\xed\xbe\xe2\xc1\x06\x14\xcc\xae\xba1\xca\x9fY\xe56\x8b\xfc\xc9E\xf5+*\xd8-\x1cX\x8c\xaf\xa6t%\xe8\xdf\xee\x8c\xacc\xe2{)\x99\xe1\x8d/\xf9Q\xccq\x0d\xd8\x05\xb6\xea\xe3w\x02\xbf\xf0\xf9\x1a\xef\xb9\xcfh\x81\x11\xa46-A\x85B\x83\xd0\x8f\x13\xcd\xb4N\xbe\x03\xb3\xcav\xe9\xd7\x8c\x06W\x90\xbe\xee\xebQ\x01\xaa\x11\x0c\x94y\xf4\x1d\x97\xc5,\xb0o\\\x8c\xb2\xb6\x82\x11\xf4O`\x05O`\xef\x04V\xed\xb6\x03\xb3\xb1U\xee\x12\xa5\x95+:\xb4K}\xb78\xd2\xcfTT6\x91i\x8e?\x0c\x19\xe0\x94\xa7\xb2 \x12v\xbdl\xde\xf5\xc2\x9b\xd7s\xd4\x92\xb1\xaf\xdd\x95\xb7.<5\x9a\xee\xe6\xb2\xf8\xf3:\x9f\x08\x18*ME!\x11M\xe1\xd7\x07lj\x9c\xdas\xfa\x94\xd2q\xd2%a\xb6\xc2\x10\x8c\x82c\xcb\xdf\x87|\xa9B\xca\x0e\x97\xc1\x97\x04\xbb\xe7\xd8\xec5g\xdc\xa3uX\xf3`IX\x8a\x8d\x08\x1d\x9b\xd0\xa5I\x17/_U\x12\xdbU\x19\xbf\x9e\x96\x89\xe1u\x13V\xfe\xd1#\xa6\xb6\x17\x00\xf4h)\xb8\x01{\x8e\x1cF\"C\x8aO\xc6{\xd7x\x04\xd9\x88\xa1\xb2K\xcb\xdf\x1aO\x8d\xb6\xe1\xa9x\xff\xa5\x86\xa7z\xf8|\x13\x86\x19m\xc90\xa3&\x86\x19\xd5\xb3\xf25c\xba\x9b\xf0\xd4\x85\\4\xe7\xa9\xfa\xb23l\x99#\xb4\xbe\xc8\x15\xd26\xfd\xb3\x9b\x9ag\x97(\x86]\xaf\x96\xfa\xc7\x94\x86]b|2\xfd\xf3s|\xbe\x8e\xc9<\xb8\xd6\x97\xb8\xc8kH\xd6\x9eo\xa8\xe6\x1d\x9b\xda0[\xe9\x9f_\xe7\x87d\x03\x03\xcfj\x188\x9a\x07\x1c\x96\xda\xfc\xc7\xc1\xc5\xb3&.\x8e\xd1Y1l\x8c\x15F\xa9wI'\xc7b\xfe\xb1\xf69\x9c\xc29\x15\xcb\x87\x16\xba\xb6;\x94A\xb8p\xc1\xf4\xf37c\xfa\xdc\xba^-\xc3\x043e\x9f\xd3B\xf8\x13o\x03^\x18\x04\x1c\x99)\xa0[\xe5\xdcD|i\xe99\xc5\x07J8\xf0\xef\xed-\\\xd2\xff\xbez\xef2\x08\x0f\\'\xff\xa0e\x18\x96\xc0e\x97\xc7\xe0\xcd\x85\xbf+\xee\x95;u+\x1cbIy\xc3R\x8dZe\xe4\x0c\xf43\x17;\x90\xe5\xa4\xa2\x953?>\xe4\x08U\xfd\xbe\xf8h\xf8\xd3\x8c\xb6>\xdb\xbau\xc1V\xb6n]L\x03/9u\x01%\x9c\xa2\ns\xab\xe7^\x9a\xc6C\xb81T\xee\xc2\x95\x1e\x1b)e?3\xb8XB\xc1\x8a4\xabb\xdfsY\xce6\x9a\x15\x17\xce\x0c\xebb\xdfsa\xb6j\x9f\x97R\nm nk\xd3\x12\x01\x9f\xfa\x17zq\xbbA\x9c~F\xc5ii\xcf\xd0\x9d\xb8\x14\x1b\xf0\x85Y:\xa5}{Q\xb9jh?ct\xa3\xf5b\xfcL\x12\xbcooa-?(Dn*\x8c\x1b\xa6\xab\xd4\x0e}\x8b\x11\x89\xfc\xab\xe8!\xff\xdd\xa58\x1b\\di\xed\xb2\x89\xcf\x15\x8f.YF\x05\xac\x0b\xa54\xda\xd9\xfc\x971\x05K\xf5\xf3\x85\xe8_-\xd3\xae~\xde\x8a\xb78F\x99)\xbd\xf8\xdc\x8c\xf3Q\x0br\xf8l\x9a\xb3,\x14\x9b\xbe\xa0#\xf8\x82>\x91\x80\xcb\xf13<\xf7\xe0\xdf\xf2\xa3\xb7\x14\xfe\x96\x0214f\x82sQ\xbf0\xb5\xa9^\xe4O\xb9\xb3#P;\xef\xca\xce\xe9\xf2\x0cV\x84A1\x00\xbbT\x86\xc1Mv\x19\xe9s\xc5\xe3f\xa6lt\xcd/\x94\xd1\xe3%\xa5\x14|\xa7 \x19\xf5\xa3\xd0\xf7R\n\x1fJt\xf5e\xc3\xb4\xd5\x91Fq\x98\xe4\x0d5\x11\xea\xb2\xb49\x04\xebYx\x93.\x82\xf0\x12|/\x84\x0b\x02\x0b\x12\x13\x83T@;\xedo\xca\x11\xaa\x0d%\xa6s+%r\x0f\xc8g6\xa0\x91|\xe6\xae\xcb\xf8\xbf\xe4\xae\xb1\x12h\xc63&\x94\x17\xf5\x1d]\xd4w\xecT\x96\xb0\x80kl\x85o\xe0\x14\xc6\xfa\xbe\x1b\xfb\xfd\xde\x85kZ\xd1u\xb5\xeb\xef\xb5v\x90\xa5\xd9\x17\x81\xca;\xeci\x19K\xd1\x08Z\xd2s\x05\x82n8vX\xb5:\x01\x1aJ\xfc\xa5\x17{\xb4\xc1!\xb44\xd7\x1b\x83pF\xc2t\x08\xd6$\xad\xdc\xae\xab\x9a\xcb\x00o1\xd4X\xa5h\x7f\xa2\xa2?\xcb&\x13W\xa5<\xc7\xa9\x06\xab\\\x0d\x87\x96<\x05\xf6\xabn1PxK\xec\x0f\x9c\xeeY\x1a\x13O#\xfe\xa3N\x8c~\xb1\xa4\x15\x83\x8a\xf5Jo\xf5\x04\x919\x80\xd24\xcd\xc9\x01=\x05\xd0\xa5\x11\xc7\x1e0\xd1!\xbf\x92k\xb3\xf7\x9c\xee\x17Q\x10\xda\xe8KgYU\xdb\x9a\xf8$\x94\x8c\x19\x84oC4\x08\x1b\xbdD\xd3\xb1\x142\xe0-\xb9I\xec\xd4\x19\xf7\xa6SdyI\xf7\x9c,\xc9\xaa0\xdbr\x80\xa0\xdc\x91\x9bC\x02?\xcaB*\xfd\x84\x12\x0c1\x89\x0d\xab\x0c\xa3-{20%q\x9c\xadS\xcc\x00'\xc0\xfa\x19\xf3\x99\xd3\xbe.4\x14\xf0S2\x957\x95\x87\xf9z\xad\xcd:\xde\xf24l-\x02\"y\xab\xf5m\xa8~r3g\x1b\x1e\x8f\xac\xc7\xd0f\x0epmxl=6\xbe\xf8\x1e\xbd\xa6\xc7dj\x14,7 \x93\xe2z2\xc7\x08%\x94\xad\xf8\xe0\xa5\\\x81B\xfa\xbb\xb9Pv\xc6\x18\xd1\xca\x0c\xf7\x1a\xc4'\xe9\"\xcd\xa48\xb6\xb6\xf9\x0f\x0cty\xee\xcf\xbc\x14\x95RK6\x9d\xb6\xf5\xa45~\xfe\xd1\xb37\xcf\xc6\xf4\xc0)J8\xb9\xe3\xde\xced:\x99>\xdd\xb9t\xc1\x9aN\xa7\xd3\xa7y\xf1\xa7xx\xb5\xa6\xd3\xa7\x16V\xcdW\x13Q\xdf\xe7\xa1k\x96\xd2=\xaed\xc3\xf8\xc5\xf2G\xbb\xb7N\xc1\xc2\x01!T\xd9YpJ1\x90\x0f\x19\x86\xa2\x0b9\x15\x816\xf4\xf1r\x81\xbdd\x89\xb5]T%\xb5zyo\xd1\x13\xd3,T\xbc\xc77no\xa5\xc1\xd5\x8865\x0b%L\xea\xc6w\xf3\xfe$\x9a\xee\x189\xb3~F)E\x19B\xa4\xdf\xd49}\x18\xd2U\xd3\x16\xc9\xc5\xfdd\x08s\x83F.\nS\xe4l\x06e\x13#aC\x08M\x9d@\xca5\x04\xaf\xeey\xd5e\x15\x94\xa9xo\xe0#^\x1d\x1f)\x11\xf2\xc2HL$\x97&\x8a\xcf\xba\x08\xf1\x82 \x12\x89\xcc2\x0f|\x0c\x9fK\xa7$\xbf\x9d`\xa6\x9a\x81\xd14\xce\xd3X*\x95\xd5\xed\x1d\xe1$W\xbc\x94,\x82yZ\x0d\xa8#\x7f*\xc6=\xadKX\xb5|d\x07N\xb3\xc2\x8c~p\xf25gp\xf1\xd1K\xe9z([\n;F\xed\xf5)\xce;\xe3yB\xa1f\xf3\x94\x0b\xa7`=\xd9\xa1T\x8d\xffn\x83\xf5\xd4\x92Kq\x06\xfa\xe8\x11\xb4BZz\x12\xf2\xc7\xe8W\x8c\x17\xc9t\x1b\xcf\xbc\x8aQ\xa3\xd9\xa3\xd5\x92\xf1\x04\x9dr\x8b\xdf]o\xbd&\xe1\x8c\x8a\x0d\xae\x8cO]\x06\x0cJ@\x11\x1d\xccn\xf5\x1c\x17Z\xbdMH\x04]4\x8e\xc9\xf9\xac\x95\xe7K\x9a.i\xa2\x8a\xdd/,\x07\xa7`\x01++=CI\xca\x02\xcb)\xde\x8dq\x85D\xf5|\xfaqo\x08\xd8\x8eiM\xc4\x02\x97\x96\xa5\x15W\xb7\xa4xC.\xa8\"#\xae\x0c\xde\xbd3]\x87\x82\x1a\xa7;-\xcd\xd0\xd0\x0bD\x1a\xf4H6\xa8_9\x0d\x0b\xd5\xb52Q\x16\xf41\xc5\x08\x00\xdd\x04eh8e\x99Px\xaax\xb3\xb5\xc3\xb2\xcc\"\x9c\x89\xcc\x0bW\x00>\xa3\xfc|,A\"\xda\xac\xf894\xb6\xb1\xe0q\xe4\xcd[ef\xe6\xfe\x0b\x863\xe4:}\x13\xf8o\x99\x13J\xba\xe5N\xbc\xaa\x95\x0f+\xc4\x0e\xf5\x1e\xf6\x1c\xda#\x96\x8c\x12\xf2\xd8\xab(\xc9 \xb7\xc79\xe7\xd7V{\xa2\xd0\xb2\x89\x08\xe3\xc1\xd2L\x1agv\xa3g\x94\xf8\xf8]\xb2\nR\xdb\xa2\xd2\x99\xa5\xb5\x9c\x8a\x0f\x15P\xd8\xfaoHT\xeb\xe6\xf1\xa6v\x1e=\xfb\x8a'\xa0[\xbb\x98\"\x91\xb2\xbd\x9e\xa3\x0f\xed\\\xd3\xca\xa5q\xf8\xccf\xdf0\xcb\xe9\xb75\xcb)\x95\xf58\x88\x843\x0b\x7f\xc6\xc4\x9by\x17x\x00\xa7\x04H<\xf7\x97QB\x0c\x91\xee@\x7fl\x00\xc3rT!\xc2M\xa0y\x1c\x0b5=$p\x94\x08\xbb\x92j\x02q\x1b\x8f\xee2\xd4\xc5s\xae\xbe\xe6+\x12'\xa8\xd3\xb0\xfa\xdd\x9ea\xd7\x93\xd0\x8ff\xe8\xe1\x19w\xc5wFr)\xbd\xfa^\x8a\xd9\xd4%K\xb2b*\x85\x02\xf6\"\x87\xd5b\x9f\xd8\x87\xfa\xe1\xa2\xc2a\x08\x99\xcd\xb4\x81E\xecD\xbc\xc8\xc5\x82\x15\xe6\xbe\x06&%\x0c=\x0dm\xe2\xf5 \xc2\x9a\xcb\xf2@\xa2L\xe5@\xba\x88\xa3wH\xc61(\xacm\x85Q\n^\x92\x04\x97!\x99A\x1a\x81\x07,\x14uK'?\x88\xcf\x95\x94\xaa\xbb\xde\xdePdG\x96\x143\xe6\x8a=[\xea-'\xaa\xa1[\xaa\x81\xa9\x80\xdaT\xc0\x10\x94V\x0e\xbc\xdfD\xdb\x08\xaf\xdc\xd6\xc9\x8a\xe2c\xa2R\x86#\x1f\xa5y\x9b.\x89\xc4p\xd9\xee\xa1Ccv<\x91\x01\x9a\xca\xb9\xe2 \xed\xe9\xc6$S\x9dW!$\x96\x91=\xffU\x8a\x1a\xba\xbbg\x88\x18*\x0fG\xb0\xf3\xf2\x00\xadG\xd6\x10\xacG\xdej}R!\x8a\x8f\xad\xc7\xf4\xc9\xcffQZ}d=f/\xad\xa3Dy\xf4\x04\x1f-\xd5w\x9e\xe2\x83\xcb\xf4\xa4\xa0\xa3\xd2\xb0\xb7\xbal\xc5\x89\x17\xa7lH\xbcru\x8f=~d=y\xfax\xea\xec\\\xd6LF\xa5\xc2pL\xaaI\xb4`\xb8m(\x8a\xd2%\xba\x93\xd2\xbc\xf3[\x11\xfd}\xa7\xfb\xe2\x8a\x84\xe9\x8bU\x90\xa6$\xd6)\xf9\xd5\x83t\xccc\xa1.\x02\xe5Z>\xfd\x84\xf6\xee\xbec\x07.&\xd3\x0d\xba\x9f\x15\x14\x93\xb6x\x80\xc0\x1f\xc6A\x9a\x03\xf7\xf6\x8f\x11\xf8Q\xb6^\x92k\x06:\xe8!\xe8M\xec\x85\xc9<\x8aW\x1c\xdaG\xe8\xf7\xbd$y\xb3\x88\xa3\xecr\xc1\xe1\x03\x843\x9d8;\xd8\x05r\xc2\x8f\x00\x9d\xc1j'\xffJ\xca#o\xd2\x9c\x07\xfa\xd3h\x8a\x06a\x1c\x0e\xbb0\xc5X\x0dZ\x89\xe9\x1b\x18\x1bh\xede \x91\xbe*\xc7&}\x93\x91\x96\n\x85\x05\x1f\xc2\x1ac\x92d\xab\xd2\xf7\xdaSY\xd8\x8d\xc2\\$\x0b\xd0\x81\x0e\x01\xb1\x17\x84\x96\x0b\x11B\xce\x83\xe4,\x9d\x05\x11\x957\xe4\x81\x11$*\xb7\xb7`\xb3j\xa8\x18\xe7\x82\x87\x02\x11\xfd\xcd\xc46\x17\x92\xaa\x16\xef\x8a\x874k\xf5M\xf3\xebi\x07\x9bac\x19\xe7\xb8)\xa3c\x9b\xcd^\xb2A\x85\x86{\xe03\x92\xa4qt\xc366\xff\xb1i\xb3\xbe\x9en\xa3\xaf\x90\xed\xb8\xdcN\x1cw\x97A\x92\x92\x90\xc4\xcf)\x1f\xc2\xfd\xe4\x82E(3\xb5\x1c\xc1_\xab\xf4V\xdf\xe2\xdc\x88&\xab\xe8\x8a|\xc2\xdb\xa9\xac\xb9\xf2PZ\x7f\xf5Uy\x9d\xab\xcf\x8a5\xd7\xbe\x89#\xa2\xc2\x92\xaeU\xf9\xa9\xa9\xd5ym\xabsm\xbd\xc5\xd3\x9a\x9d \xc8-\xc3\xe4R?\xab\x10\x19\xdb\xe7\n\xb6\xcf\xf3w\xca\x10v\x94\xa1\x04\xc8b^\xceM4\xdca\x8ec5d]\x7f\xab\xaf\xa0\xeaG=\xa7\xcb\xc2\xe3\x96\x19\x9e0\x1e6\x86\xc8\xa9\xa2R\x8ee\xa9\x16\xcbZ\xcd\\\x0d\x84\x00i\xa7 %\x19#\x8e,E\xbe\xb9Y\x13.I>\xf7B*LR6\x03\x1e\xf8K/I\xc0K\xc0\xcb[\xd2\x1c\x0b\xdf\xf3\x0d\x94\xcb>\x0b\xe2\xcd\x80E\xa3\xe1\x90\xd4\x0b\x96e\x08?\x0e\x8c\xaa^\xcb:$I\xd5\x8c\xe6\xf5r\x9a\x10m\xf5\xf3A\xb7\xa21S~H\xaeS\xa6\x8eR\xc7\xa9\x8af\xf2P\x9eb\xc0\x92|\xb8\xa8\xf5\xc1\xdb\xc0\xc3\xd2\xac\x90\xf2\x94\x10\x17\xdam\xa9\x9a\xf2l\xb8\xa5\xb1g!\xea\xbe\xbf\xfd\xe1\xe7\xfd\xddd\x0ex\xec\x0ci&\xd0\x11\\\x1ec\x051\xb6\x19\xb32b\x13}\xe7\xe2xQk\xddy5\x15'\x1a\xda\xa3.\x9d\x91Z\xbf\xc3\xbe2\xc4\xd3\xd2\x80\xaa8^Y\xf2\xa2%:\xbd.t:RU\xda\x98\x85u3\x82\xb1\x0e\x9bf\xa4\xaew\x0d;\xb0\xdc\xda\x17Q\x106\"\x1c\x9b\xffQu\xfe\xc5E\x0f\x8d\x17s)\xean\xdeY\xe6Zl1m<\xae\nO\xcdM\xe7\xed\xc4\x81\x10\xda#4\x81\x13\xc3\x9a \xaeR;\x7f\xe8{u\xcf1\xc5]o\xb9\x8c|\xbbg\xf0cV0\xa6\xd0\xf57\xa0]13xj\x0eXl\x08\xde\xde\x0f\xc2\xc4\x9b\x13;\x85\xa7O\x9f\xa2v2+O\x9fG\x97\xf3\x04\xb2\x13\x07'.\xc36\xd8\xacF\xfc\xe2\x04^\xde\x8e\xd67,\xb0\x01}\xa5-\n\x96\xa2\x18dl\xd2MS\x1c)S\x9c\x03\xdeSI\x0b\x03s\x06\xdd L\xd6\xc4OK?\xba~\x96\xa4\xd1\x8a\x91\x89\\9\x93/\xd0\xb8ZpZ\x87\xecb7\xe7/i\xd4jlXC0\x92\x1c}\xb8\x1e,.\x05z\xcfMo\xec\xe2h1^\xe3\x89{c\x7f$\x1d\xfb.sw\xbd\xddF+\x90\x88\x0fS\x1cu\x13\x92\xbe\\\xad\xc8,\xf0\xcc\x1e\xae\xdc>\xc3|\x8cx\xcab5&\xb3\xfc\xf1k\xaej\x007\xdb\x98L3\xc0M7iw\x16\xf9\xa8(3\x97[\x97\x12B~_ \xc9k\xcc*\xa7}`\xcc\xa7N\xab\xc2\x8clk:'o\x82\x15\x89\xb2\x14NaM\xc9\xb5[D\x8c\xe7yk\xa6\xccq\xfa\xab\xf7\xdd4bW\xdb\xf9\xe9[$\xb6aQ\x8b\x9a\xe8\x88\xf8Hf\xa0Z\xca-\x7ff\xb6&\xaa\xaf\xf8\x98\xf4[0\x94Q\xa7\xae \xb4\xa1v\xd7Q\x92~\xca\xb3\xf9\xb3\xac?\xc1\x8an\xc93?\x0e\xd6\xa9\xd1\xddG|\x04\x11\xd79\x08V?x\xcc\xefF\xe1\x8a5Woh\xcf\x85\xbf\xbc|\x13\xd3\xab~\x88\xde\x84 \x7f\x18o(f\xc0\xb6,\x17\xac\x0f-~\xa8(\x1a\x0e\xab\xa1\x94K\xb5\xe8W\xc2vP!\xc5\xab~\xbe\xf0\xc2\x90,\xe1\x14l\x1b\xa3\xa7\x90wP~\xe4t\xe9\xbc\xf7\xf5\x03\xaeE\xae\x99\x9d\"\x057\xa9<\xb7\xc0\xd3\x08;1(M\x8a\x01\x0bQ5\x86\xc6E+\nc\xe2\xcdn\x92\xd4K\x89\xbf\xf0\xc2K\x82i\x92\x97\xa3\xddvD\xbe\x8b\xe2\x0e.Z\x06\x0d\x97\xbd@r\xfb\xaa\xdf\x85\x94\x1f_x\xfe[\xe3qV|\xbc\xf82\xd1\xf9\xdb\x89\x8f\xe1\xae=\x14l\xc8\x1f'S\xa6\xdf\x8e\xed\xc4q!i\xb7M\x08\xb7fG4y\xed\x16J\xd9:\x1f\x82\x85y\x89Yzw\xf0\xab\x81\x9b\xa1\xa1\xca\x1a\x1f\x15T\x8e::\"\xa1\x9f\x94\x86\xbb;\x02[h\x17\xeb}\xf4\x1a}\x9e\xe7\xdc\xf5\xa6\xaeL}\x9a@\xf1im\xb8{\xe4O~:\xed\n4k\x16p\xc4'\xc6\xf7(\xd6\xd5\xf7^|\xf2\x14P\x0d\xba\x0b\xdd\x07\xfd\xae{f\xdf[\xdd\x87\xd4\xf9O\xea>\x0d^\xda\xd5\x0f\xf6\xa9\xbfm\x9f\xe2qo\x93\xbbU\xf2\xe7.\xfd\x1a\xdc\xa5_.\xc4\xe3\xfe\x8f\xa3w\xbbw\xef\x1d\xfd\x7f\xf0-\xf7\xb1\xd1\xd5[\xf7A{\xfd\x12U\x0e\x1aw\x0f\xddG/Q\x97J\x98\x84\xa3\xbc\x00\xcc\x83\xd0[.7\xa1\x0f\xccp?\xdf\xe0\xbc`|\xba\xa9\xdfoE\xb7g[Y\xc8\x02\x02\xcedY(!\xcby\x11\xa9?\x0fN\xbc\x08\x12\x0c\x83=\xc4\x02\x92\x0d\xb8\x949\x14y\xb1\xd9\x15`\xf3[Q9\xfb0\x90M3\xf1E\xdd\x03\xe9.#\xdf[\x9e\xa5Q\xec]\x12)\xa2\xa3:)r\xfeTm\x855\xef*\x10aQ.\xb7\xaf\xe5GBa\xc8sn\xa07\x99\x95\xc6\x19a\x87\x7f\x1e\xd2.t\xbai\xf4I\xf4\x8e\xc4\xcf=\x8d\x01Y\xfe\xb5q\xf0R\x10wal+\x8c>\xe2A\x88\xd0\xc0b\x8a\xbd\x0d\x92\xb1\xa9\x1a\x15\x13\x8a\xb14\x9eapm\xb4ai\xe5\x12\xa1m\xa1\x85\xa8\xd2\xb5\xaa\xef\x91\xee\x1e\x81\xf8\xd0*b\xcf'\xa5*\xe0\x14\xfc(L\xa2%\xe9\xe2C\x16\xc0F\x80\xdeyq\x88g%\x1c\xa4\x1aD\x0f\x8c;-W\x170R\x93\xa2I\xaap\xc4j\xda\x87\xc6\xad\xb4\xd1\x1e\xd2+\xe2J\x19\x96\n\xb0\xe4\x06r\xac\xcb\xa3\x14\xda\xfb}\xed\xad\xcfH\xdd\x1e\xdc\xb6G\xe9\x82d\xde\x8b\n\x1c\xa2+\x15\xa9\x01\xc9\x0bG\x12MpS\xac\xb8\x1b\x84\x0b\x12\x07\xd8yt,q%\x98\x1d1'\x93H\xd2\xab\x9f\xa7\x92\xcbH\xddd\x01\xa2\x06\xb7DT\xdb\xde\xc2\xb3\x86.\xcf\xe1F\xcbS~k\xd0\xbf\xc3K\xfd\xfe\x81S8\xc5\xdc\xf1}\xc9}f\x93\x1a\x9a\xec\xcd\xfdc}\x16\xc4\xfe\xb1>\xcf\xcd\xdeAs\xac\xf6\xeaBqK\x04\x0bH-\xc7P\xd2\xeb\xcc\xb3\"zU\x8c\x97R\xd1*g\x13)\x8a5\xe6\xd6\xcb\n\xebWau\xe8z\xc9M\xe8\xf3\xe4\xadYw\x1d\x07\xab \x0d\xae\x08\x9c\xe6.0pZn\x02\x87u\xbc\xef`6\x0c\x1e\x03\xca\xd6\x948pl\x82w\xe5*\xcf\xa4zi\xb1C\x07S\x0e\xc8\xc0\xfd^\x9f\x01\xe9\xd7\x01V\x93w\x15\xfd~\xec\xfd\xde.\x82\xd6,!\xa7\x00\xee!p\x16$\xeb(\x07\xf6\xd1f\xd3]y\xd7\xcf.sX_\xc0\x04\x80\xbd\x19\x939\xba\xa7\x90X\xc0\x0f\xe8\x8e\xa3\x88\x92m\xb9k\x9a\x10i\xef@\x17\xb9\x1du>\xdeE\xa2\xa2\x12>\x99/#9\x97\xf5f\xe8\xc4\xd1$H^y\xafl\x8c\xfb\xcf\xd2x \x96\xa40\x82W\x18\xc3\x153H\x0d\xd8\x9e\x92\x07\xc6\xcb\xc9l\xfd\xe4\xe8\x02\xd9]\xb1 v\x89\x0b~y\x81\x03L\x9dBe\x1f\xbb\xc8?_&\xb9\x8eDv\x04\xb9\xd1\xb8\x83\xbf^\xd3\xc6\x13x\x8c\xa5\x1f\x83\x17\xce\xe01/\xfe\x18|\xe6\xe2sA K\xd0]\xfc\x92\xa4\x0b\x12W\xb5\xe5|\x19\xcbazr\xd1\xc8:?\x17\xd1\x19\xce\xcf-\x16\xaf>\xec\xce\xa3\x18\x9dp \x0cYf)\xcf.B\xe3\x93\xfc[X\x0c#\xe24\x9f]\x0c\xcbh\xd5 s\xd7\n\xa8\x8c\xd1(A\x87c\x82q]R\x1e\xa8\xddW\xee\x13\xb1T\xce\xe7\xe7\xeb8\x9a\x07K\x12\x9f\x9f\x03\x8f\x14^@0$\xa6\xdf\xcd\xd63/%/\xc2+\xbcJ\x9d\x87\x9fx\x90\xbd\xd3\x88\x93\xbb\xba\\\xbcBU+\x89Y\x17A8S\xb1TS\x90.\x95\x8a\xb6r\xe2\xff\xd2\xc3\xa4x(y[\xf1u\x7f\x99\xbc\x08\xb3\x15\x89\xbd\x8b%i\xa2\x07\x9b%j\xd0\xde\x84\xa2\x934g7\xd3\n\xbc\x1f\x18\xe27\xacK\xa5vk\x0ew\xc5n\n\xec\x90\xa58\xf3\xf9q\xdf\xb3)\xae\xa1Ux\xdeM\xa28\xb5\xb5\x04v\x8d\xa9W\x11\xf9\xd7\xb8\xdc\xc3\"\xfbL\x83\xc6}>N\xa7\xc8\xcf\x99\xc4\xed\xd2\x01\xca\x93e<\x88\xf1\xde'\xecE\x96R\xf8T\xd4\xe3\xbb\xb0t!\x1c\xa7S\x17R\x91gD{\xa3\xdctX}\x10\\\xde;\xacRR!\x81\xea\xf3E\x1c\xe9\xd3E\xec\x1d\xf5\x9d\xee\x8a\xa4\x8bh\x96\xe8(\xed\x9e\xf2\x1eg\xd6\xc7\xba\x04\xd3\x9a\xbd\x80g\xc2r\xc9\xf9\xa6\xbbfYl\x0cff,?\x96\x1c\x14J\x89\x1d\x94\xf0\x9d\x0b\x94\x81\xa3J\xcc\x80\x19B\xc9*hL\xdd\xa5?H\xa1o\xb7\x0bW.\xdc\xb8p\xe9\xc2\xca\x85s\x17.\\x\xe7\xc2\xb5\x0bg.\xbcp\xe1\x99\x0b\xaf]\xf8\xc2\x85\xb7.\x86\xb1Z\xe2\xe9KO\xf0\xaf\x98T\xdc\xe2\x020%\xe5\x9cw\xe7\xbai\xc6\xabS\x89\x9eK25\xc5\xfb3\xcct*\x831\xb8\xd3\x08\xce\xba\x97$e\xd1\x87\xcf\xba \xfd\xba\xc2\xaf\xcc\xac\xe1b\x94\xce3f>q\xdcB+\xd3\x8dI\x12-\xafH\xcc\x82\xcc\xbe\xe5\x9c%\x87\xd2=\xfd\x05\x8f\xbc\x144\x04a\xe1\xfc\x97\xfbU\xe5\x04D\xa5\x1e\x94\x1fcp3\xb4\xd6\xbf\xb5#\xa7\xe8\xd2\x88\xf1\xe8\x1b\n\xa4Et\\\xf2%]\xad\xfc\x1c\xfe\x82\x16\xcb\xb8W\xf2%I-\xdc\xb4\x11\xf3\xc5s\\x\xa9\x8dhO\xfb\xc0\xd2\xf2a\x94\xe4\xc2\xfbp\x9e\x93\x13v\x86\x8f\xc6\xbd)\xeaQ\xaap\xd1\xe7\x11\xcb}c\xd6\x08iF&D\x8b\xd8\xb6\x9e\x07\xb1\x9f-\xbd\x18\x82\xf0*\xe2\xaa\x1c\x17\xac\xe7/?{\xfe\x83O\x9e}v\xfe\xf2\xd5O\xbd~\xfe\xec\xcd\xcb\xd7\xafLVwZ\xeb\xa5\xad\x89_\xfe\xbe\x08i]3\x8d\x0f\xd4\x13\xbe\x1a/\x99=2p\xe1\x99\xbc.\x89X\x17n\xc1\xa7bH\x99|\xbap\xe5\xe4y\x07\xe9\xfe\xa8\xd5\xb6\xe1\xe1Y\xbf\xaa\x86\xa1\xb2{\x02\xb5h#\xae\x12\xe4\xa8[\xe0\x90\xc1\xa5\x10\x8dm\xba\xa0\xc9\xa7\n\xbe\x14\n3\x18V\x90\xccqMh\x9ew\xfa\x81\x17\x89\xf9\x03\xa0\xbf\xb0f\x99\xf2\xfb\xe3\xb8VD\xcdu.\xa7\xfa\x7fXR \xdf\xefD\x8e\xc7\xf5\xc4\xb8\x0b\x8d\xd3\x14\xd4.kP\xa6\x06\xba\xcc]\xb8M\xefK\x0dj:\xf7\xc0\xcb7\x0e\xe8\x1e\x0b\xb5\x8b\x17\x88u\xa3\xe2\x97\xe2\xae\x9bi-\xffQ\x1c\\\x06\xa1\xb7\xd4Z\xfb\x85\xb0>\x84/\xd4\x87\\\xd2\x7f\x85\x91\x83\x90\xdb\x8b\x9fj\xd9K\x92nr\x0d\x94\x0f\xf2m.\xe7\xbd\xb5S\x07\xb9\xdc)\xdc\xb0@\x0f\x1c)R\xba\x18*\xd5S[^x\xc9\x16-\x1b\xd6Q\xe3\xda\xa3i\x8a\xf1\xdbMZ3\x900`\xfd\xd5\xf7\x00\xe7\x04\xfd{W\xccM\nF\xf0\x12EU\xee\xbe\xc0~\xbc\x96\xd1\x82=\xb1P\x9a%\xba Q\xea PL\xd8 #\x8fP\xac\xbc\xd4\x0f\x03\xcf\x83\xe7\xf4\xc8'\x89Fn\xde1l\xc5\xdatb\xa3R2\x9f\x9aK9B\x9dC7\x7f\xae\x0ey\x81F\x0f\xccI&\x83\x9f\xe5`>K\x85\x1b\x95\xfdZD\xf1X\x94T\xfa\xfa\xb8\x15j\x7f\xe9\x18\x870S\x1f\xe4g\xe1\x0d&8e\x92-\xdf\x9ej\xb3\xd5\xed}\xa1\x8aj\xe6{,n9\x87\x8e\xba\x86l\x0b\x86\xb8\x05\xc3\xb2\x8cFP\x92 \x99\x8c\x96q)\xb3j7\xde\x92\xa7\xe7\x8an^\x1bg~\xe5*\xa1iki\xc8G\xc1T\x18\x17\xc9[\xa8\xa6=w1\n}P\xefF\x8cH\xdf8w\xbc\x1b\xc5\xd09\xcf\x1d\n~'Mk\xcaW\x8dNhA\xddB\xd6Y\xba\xa3U\xbd\xcb\xf5\xb7\xd6\xcf\xac\xbb\xf0\x121\xf7\xda\xee\x16XP\xd3q\x8e\x18\xb4\xaeT\x93pum\x7f\xa1\x0b\x8c*\xeb\xbe\x86\x10a\xd8*#\x89\x8d\xec\x0b\xcdSN\xbb\";\x13\xa7\x1d\xb5\x15\xe4D\x91\xfdN\xf7\x0cyEd_\xab}\xcer\xc8\x83\x9c\xf0\xfb\xc7\xba\xfc}\xf4\xe4\xaf?\xe1\x0ft'|\xd4Kv}o\x9df19K=\xff\xed\x9b\xd8\xf3%\xb6B\xe48\x1d\x8d\xf6\xa8\x90;#2u\xa7.\xf7\x98\x07\xe5\xfc\x1fj\x89\xa4\xa2c\xd2\x9e\x85#;\xe1\xa1\xb6<\xc6\xd4x4R\x91\xb8\x1f\xed1\x89\xc8\x14\xc9n\xe1F\xa2l\xd8\xf5\xa3\x19\x8a\xddxO\x87\"\x1a-CJ\x02\xcf=\xd6hs\xa3\x02\xe3\xc0\\I\xc1\xe2\x84ln[`\xb1l\x88\xad\x8f\x882\x8f\xa2!X\xb1\xf7\xa5U\xa5Qj\xd9\x0b\x8a\xf1\xd6\xec\x9d\xb7A\xd94\xfe\xf2f\x08\x16\xfdS\x0d-\xecb\x80\x9a\x08s\xb7]x1\xcb\xe1\x16\x7fy\x83\xb4\x81ve\xf6\xce\xc3\xf7\x1eXo\xbbgH\x8d\xaaU\xdc\xa2\x11g\xe5]o\xa0\xd41\x18\x08\x8a[8\x91\xe2o\xeb\xc2\xa0\"w\xa3\xa3n*+:Q\x1a-yhk5\x8df\x17\x9et\x1cS\xf9\x9d\x8cc\x8d\xabi\xa3\xbfN\xc8\x02\x15\xd0}\xdd\xe8{\xc1\x04\xfe\xfe d\xf0\x04\x92\x13h\xb73v\x7f\xad\xd8\xa0\xd9\xd4\xc5\x80\xb7yh\xa2jv\x82J\x1c\xb407\x8bh1\xfd\xdb0\x1c\x1e\xee3\xc3\xa1\xa4ag\xa6\xc3\xc3\x83o\xdbt\xa8_D>V9\xae\xac\x95\xdb\xd4-\x8c\xb4X^\x87\xdaE\xd5;`=\xb0>Y\xe1\x1eA\xd9d\xd1\xb4\x9d\xaa\x1d\x17\xe6f\x8c\x84\x9b\xaf\x0d;\x9em\xebzr\xa7\xbek(&oB\x1fR\x9d]A\x1b*Ks\xc7\x81\xe3\xb0\x1f=\x82`,\xec\x12\x98\xbe\xa1\xf5 f\xd6*\xfe\x1f3\xfc\xe7w\xe5J\x17nS/\x08\xf9n8\xea\xddc7\x88\xd9\x96\xc9\xfc\x96{\xa5\x8e\xd7\xc5E_1\xe7\x88\x08\x17\"\xa06r/\x91\x9d\xbb\xfal\x1eE\xd6\xc3\x18\xda\xc50\x95\xa9\xe4wa\xee\x8a\x0d\x95#b\xc9\xb6\\NDy\xdf\xceW\xee\x92\xba\"\x18\xbb\xc6\x04\xb4\xd4[E\xd7\x1b[r\x16\x9bZrf\xf5\x96\x9c+\x83%\xa7\xd2\xdc\xcd\xa6\x06\x9fK\x9dE\xb5\xac4)\xbf\xb0\xd2\x12\x0c?\n\xe7\xc1e\x86\xb6W=\xd1 \xb9mV\x1f\xf5Z\x04I\xaa#+j\x9akJ\xa2\xe2&a\x05\x84\xc0b<\xb3-\xd1\xa5\xe1RF=\xeb\xfc\x9c\x10t\x1b8\x95b\xcb!\x8c\x1e\xe5(h\xd5\xc5\xbc\xe70\x82\x99P\xc8\\U\xdeva\xe5\xb8RA^,\x1c\xa7S8\xd5\xc5[\xe7O\xe8\x1f\x16\xac\x0d=O\x11:\x821\xb3\xa5\x92i\x01\xe2\x91:\xca3V\x11\xf5B\x9f\x0c\x91\xd0o6K\xae\x1c\x0eL|J\x13\x15\x88\x88|\xcan\x0d7\xb9\x9f\xc8\x8d\xd4\x01{\x03\xaf\x91 \x97\x8df\x8fX\x8c\xadCg\xf7u\xe8\xe7\xf1|\xce\xcf7\x9c\x8a\xf9|\x88\xa2\xef\xa63\xc1i\x84^\xcd\xcd&\xa3\xa5G\x9bR,\x05\xfd\xfb-\xbb\x82X\xce8\x9dn\xf0\x9e\x8a6,\xb6(}[\x9d1\x10\x92w\xc4n\xbe\xd1\xc5\x8b\xc7\xd1\x94\x8a\xb0\x91\x03A\x11\x927\xd0\xcd+{J\xe5\xe4\x81\x88K%4\xfa\x1c\x05\xe3q\xc4]\xe40ie\xdcM\xd6x\xeb1r\xa1\xaf\xbb\xb7\x87\x96\xb4\xb8h6\xaem\x96kc\xc3:\xcf\xf8\xa6eg\n\xc4\xac\xf1~\xe2U\x1e\xd1\xa2v\xdd\x0dt\x82r\xe3\xa0\xbc\xa0\xe6\x15\xd1\xafc}\x1cx\\\xc5Pc#c\xb6!9\xd5\n\xbb\xebH\xd8\x89\x85\xc0\x13\x08\xe9r\x13\x07\xa21\xa1\x0f\xcb\x17\x1dI\xcd%8l4\xc0\xe0\x15\xec2+\xaf\xb7w\x82\x847\xa0/\xb3\xaa\xf9.\x8e\x0bC\x8e\xb6RnJ\x15\xb7\xc9\xaac\xa9\x9b\x80Mnl-\n\xe2\xb2\x08\x92\x86{F\x0d\xf7\x8a6\xb9\x89Un\xaf\"\xaf\xdc\xbf\xf5\x86\x9bVu\xad\xbb%\xdd\xd1\xfd\xfa\xb2\xd1\x8d\xaa\xbf\x14\xfc\xa4\x9fue\x16L\x98\xf7\x1d\xfd\xaf\xf7\xba@\xcch$\xb1\xab:O\xc6K\xe7vP\x85S\xc62\xb7#GGx\xe6\xb6\xec\x0b\xcd\xbc\x08o\xec\xaf\xde3]\x9c,\x1d\xd7_\xa1\x16\xaeb\xccU\x02\xad.3\xdbgq\x88\xf3C#\xadTn\x8c\x08\x9f%:\xa3\xdf\x81\xfb\n\xcc\xdc\xd5\xa9\xea\xd3_\xa3W\xd5\x88\xcd^\x9e\x9b\xb0\x12\x99\xb8h\xaf>p\x80D\xf7+i\xb05\xdeG\xd2\x0b\xe8,d\xa7\xe3\x10-\xcf\xf4o\x19%\x1c\x91\xf4\xce+\x19\xa5\xd5\xeb\xfb\xef\xdd\xedN5\xa8\xf6B}\xd7\x86iy\"~(\xce\x14\xcb\x8aC\xa5\xae\x8b ,\xc5]\xb9\xefQ\x88\xadS\xffX\xa3\x1d(%\x94\xbb\xe3\xa1.`\x9a\x8d\x94\x8a\x07\x0f\xd4\xed\x8d\xce\xd1B\xb3\xcc\x04S6\x92y\x1cUrq\xd5\x9d\xb6Y\xe8v\x14\xddq\x0d\xc7\xa8Gv\x99\x8ax\xea\xb8\xf0\xbd(Z\x12/\xb4Q\x94!E\xb8e,\xc0LA\xe8\x15\xfd\x10c\x96\xf4\xbcG\x07N7HI\xec\xa5\x91>\x90\xe3\xb1\xde}|O\xb9\xcd\xc5\xf6\xe8\xa0\xba\xa3=\xfd\xd6M\xf4\xead_\xbf\xff\xe7\xbc\xcdj\xe5\xcb*^mt\xacV\x0f\xcb\x8b\x878\x8cj\x9e\xcb\x87Q\xf5)\x1e\xe64\xf1\x17\xdf\x1bO\xf2\xe5\xa3\xfa\xb6\x9b\xa8\x10K\x8d\x1e\x94\x8d\xa6\xa4\x17\xb5\xa6$\x0c\xb2T(\xe6\x13\xa6\x98\xf7\xed3\xa4A\x9e}\xc6\x83#\x02\x8f\x16\x8eh\x8e\x0bG!\x11\x0b\xf6\xec\xe4q\xf2\xca\x95\x1bb1\xe0 \xe8\xcc$\xee\xa1S!\xde\xa0\xe1\xbb\x93y{\xda\x97P\xc4\xe9\xa7$\x85a\x11\xbf\xb9\xcdo\xeb\xd1\xf3\xb9}S\x928\xfa\x0e&+\x1bA\x8a\x17\xd1o\x0c\xd2\x10;\xd5\xd1V\x1b\xa4\xf0r\xed\xa5N\x95B\x8c\\R\xb1&t\xe0\x86\xf9\xf2\xa5Z\x07J\xf1\xe1#5$\x0cU\xa0*\xe4\x06\xb3\x05~\xc7\\\x08\xe7|\xa9\x98\x91A\xb5M\xd8\xef\xb0\xbb\xf1\xd48\x178\x0f\xe7\xe8\xe5\xfa\x8e_Ge~4\x94`\x8a\xf9\xa1\x07\xe4\x0b\x18\xc19\x06\x16\xb3\x8b\xc9i]tgQHN\x1c\xb4\xbf\x9f\xc1\xa9\x10\xe2\x983\xf0\x05\xd3\x98p7\xf6\xfc\x17\xe5\xdf\xf6\"\xd7\xa6\\\xbb0\xb3opg,\xf0\xae\x15\x9f\xe6\xebj\xa3\xed\xb6!a\x16]9Mv\xa0\xc2\xdbs^\x83\x0d8\x03\xf2\xda\xebF\x8f\xe3uQoW\xc1\x89k\x8e\x10\xbfz7\xa4\x82]#\x05\xbb*\xc7\x92\x1c\xa9\xb6\xc0\xa2\xd8vx0\xdb:\x9bt\xd5\xd8\x0c| f\x8c\x07\xd8\xb3\xa2\xfbn\x8d\xccW\x89\xb0\x1b3\n8\x1b\xa7,\xcb\x1f\xcb\x9e<=q\xa0\xdd\x8e\xb5\xd4\x0b\x8b\x8e\x80\x17\x9d\x8a\x9c\xab\xf6\x9a\xa9]\xac\xef~\x17\x03\xab\xb9\xe0u/\x13.:\xd5\x1fI\x0bo V\x13\xd3\xb5\x10\x17<&.\xe2\x93~\xf5\xb4Zry\x97\x83\xd8F\xb52/J\xa4J\xc4\x08}y\xfa\xf9\xf9\x8c\xb00\x94A\x14\x9e\x9f\x0f\xc1\xc3\xd0\xa2D\xe7\xccw\x1ez+R\x94\xb9\xb2\xab\x0e\xd0\xef\xcb\xea\x91\xb9\x1dT\x9b\x9cG1}\xbd\x1e\xcb\xf8\xa0\x17\xcc\x0e\x86\x7f\x86\xec\xcf\x08\x02;'\xe8\x8aR\xa4\xf4\xfb-\xb9\xf9x\x93\xc6\x0c\x8e\xe3\xb8\xf9\x08\x04!$(\xd3.\xcc:\xfc\xc5\x98L\x99\xa7s\xce\xc1Hm\xd7\x16^\xf2\x92c\x89\x98\xcb\x98YA\xa4'\xcc\x9f\xcf\x92 J\xaa\xf4 y\x8e\xaa\xaa\xb3\xb5H\xf6R\xa9N-\xc0kU\x1f\xa8\x95s6V\xad\x92\x83EE\xfc\xa7\xf2\xfa\x8a\x92\xc3\xca\xbb\x08\xe3/\xe2w\xe5-\x9e\x13\xa9\xf2\x9e\xc8\x9a\xc4\xde\xe4\xbf\x94w\x13\xe2\xc5J\x93\x0c\xc8\xdfd?\xd4\x17\xd7\xc4\x0fHR}\x93A\xc5\xab\xec\x97\xe6\xdde\x90*o.\x834\x7fo\x19\xa4\xca[\x92\x08PyWz\xc2k\x90 \x9azrAA\xa9'\x7f\x92\xd7\x93C\x94z\xb20\xf1\xa35E\x83\xea,HOx=\x12\xa4\xe4E\x82$F\xa2J\xd5\x9d/\x119\xdaFU{.\xba'\xda\xaf\xb5 \xcb\xba_A\x95*;\xae\xd2\xb1\xc0\xdc1\xb9\xe5MZ\x15\xe4\xdb\xc6\xec\xedL\xef\xd1\xad\x90Qh\x83\xe5(\x0e\xa1\xa5\xdfx\xa4x=\xdf\xb4\xd5\xa4\x92M\x0b\xd4Q.\xcb\xa3\x0cddr\x9b\xa6U\\>\xe1\xed\xe8\xb5\xa3\\\xee\xae\xe4\x86\xc7\xe0\x189\xc6\xd9r\xa7\xf4\xbd\xca\x11\x11{\xe5[\xae\x98S\x8b\xbd\x105\xbf\x10\x94\xe2\xf0\x97\x04f}\x15\xe5\x99\xd0UQH\xe5\xf7\x89\xa5%\xe9g\x8f{[G1b!\xcfP\xdf\xa0\x93\x1cR\x8c\xea\x9f\xcb\x0d\xfac\x90\xd8\x1c\xc52\xdc}4\x9b\xf5:?\n\xb1\xab>Z4\xb9\xbd\xa5\xcf\xe54\x05\xac\xecY^\x16#\x98V\xb3\x18\x9e\xf2\x8b{\xb4\x1d~'\x8ecj\x87\x87\xfe\xb0\xa3b\xd1=\\\xf4\x80\xa2=\xf3\x93\xc5X&\xe3\x1e\xf7q\xc7\x07\xf4E\x17\xbcq\x9f\x03\xbf\xc5\xae\xe7}\xefO\xc7\x11\xe2xvr\xaf~;\xae\xa8\x8c-\xe0\x1d\xf0\x97k8\xb5\x99\x16\xd5\xa1n\x17\x1b\x83\x07\x8f\xa9\xc1\xe4\xac\x1e\x93=\xee^^\x8f\xebyn>c)\x1f\xd9\xc1\x06{\x81\x0b[\x19\xc5.\xf3f\xa0\xaf`\x1a\xc0q\xb2 =\x8d$,\xdd\x9c\x9eJ\xd2\x7f\x86\xe8\xe0\x8d#\x89\x9e\xd6\x93R\x9f!J\xc6\xe24\xb1\xbe\xf6\xa7\xe3\x00\x91.\xba\x03a}\x90\x9e\xe5\x17q\xf3\xce\xd0\xf7\x85\xdf~\xe0\"B\xd3g%\xd0 \xb4\xb0\x18\xb7\x7f?z\x04\xbe n\x0e2\\\xbf\xbb\x8e\xd6\xb6\xe3\xb2E\xe1\xbf\x9c\x0dj\xdeb\xbbH\xd7\x016\xd9'\x9b\x86_\xe1r\x8a,\x97\xa8\xd5\x7fG\xff\xeb\x1eRY\xc5\xf0\x7f\xcco'\xb2\x90\xb4]\x0ci\xc7\x83:\xdf\xe7B\xe2VB\x9c\xdc\xf66G9\xb4w\xa7\xf6W\xef\x91P\xa6\xf6+\xef\x15\xbb\x83\x98\x16I\x1e\xe0\xe1fk\x03\xa9\xbf5z\x18=XYt\xbe\xe3\xb4n)\x1bW\x89\xe4C\x88\xc5\x12\xb9 .:\xc2\x19\xbc\xe0\xca\xc2[PHi\xe18\xd8h\xd7\x95\x85\xac\xa6\xe0\xa1,_6K\xac\xe3B\xc8~\xb5\xdb\xa9\xf3\xed\xf0BIc\x85\xf9\xa3\x90\xf1\xb7p\xa0\xec\x0c_&Va\xe9\xb7\x86*<\x0c\xd1\xd1\xc8+\xdf\x02\xbdy\xc8S\xa0^\xc9\xa0G\xf5\xd0(\x8a\x9a\xe48\xcd|hJF\xf7\n\xc7\x15\xcd\xe09\x82\xb8\x10\xa1\x7f\x01ECM\xd8\xe4\x0dh\xe1F\x18\xce\x8e\xb9L\xcag\x83\xa5d\xc9G5\x00\xe1\xc7\xbb;\xe3<;C\xf9x\x86j\x16M\x136#\x9e\xcb\xf3~\xf3S\x1aC\xfel\x0b\xe4\xe7\xbdi\xd5\xf6\xa6\xe1\xc8@\xe4\xe6=U\x90\xf54\"\xb2W\x16\x91\x93\xb2\x88\x9c\xe4\"\xb2W\xfc\xd2\x88\xc8j\xcd\xc6\x9er\x89\x98\xae\xd4\x86\xd3s\x0f\x96e&\xe4p\xc7\xed\xe5\xcaD\\\xed\xeaw\xf4\xbf\x1e\x86\x07j\xef;\x85v\xff\xb8\n\x8f8\xfcH\x7f\xbfM $..\xcfT\xef\xe0$\xa6\x8bo\xe5b\xdb\x05\x0870mL\x15\xc1\x93\x184\\x\xe7J\xd3\xa5\x0bk\x17\xfd+\xe7\xdcAQ\xa5/u\x0f\xaf\xd0\xba!\xc2\xce\xa9\xcfo\xf0\xb9\x08\xc1X\xc6\xe8\xe2=\xf4\x08\xaf\x97\xe5\x84\xa4QD\x17\xd6\xe2V\x8c\x91\xa1DJ\x07\xbcVj\xd4\xd4\xebC\xad\x80\x88\xd7\x1737\xbb$\x17\x9f{.t\xfa\x945\\\xf1\xcb'\xcb<&\xc2\x9a6\xab\xda\x9c6rX\x8eli\x02\xe1\xaa\xc6o\xf9}e\xfa\xa2P\x04\xe9m\x9e\xbb\xda\xdb\xed\xda\xfb\x93\x90\xbb\xbbI\x11\n\xb4s&;\xee\x8d`\xbc\xc0\x88\x15\xa1p\xe2c\xd4=t\x98\x0d\x0e\xa7V#\xbd\x89O\xcc\x18\x12\xdd\x95KF'\xd6LZ^b\x96|\xe1\x92\xdf\xe0D#>(\x7f\x98\xe9\xa8.R\xec\x8c'4@~=c\xc17\x8a\x80\xc8\xb8\xb7X4\xd8\x88\xf1+\x1e\xcb8\xc6T\nQ\x98\x92\xeb\x14\xf30\xc5\x97\x89\x93\xfbo\xc6,yD\xc00%*P\x88\xae\x89)Et#id\x99\xbe\xf9\xdej\x8a\xc2q\xc5\xeeEr\x9fp\xe3\xa6\x08\xe9\xd0\xd3rV-\x1e\xfeCT\x0f\xa9\x19a\x84\xfc\xccD\x8a\xb4\x1b\xcc\xcc\x9a?\x1e \x13jS\xf9\xd3\x82\x9c\xdd\xd1\xdaXO\x16\xe3\xa4\x08\xda\xcb~\x04\x85MF\xe9>\xbf3\x86X\xa1\xf4\x8a\xffX\xe2\x8f\x9cq\xc5\xdb\xf5e\x81\x0eZZ\x94\xc6\x1b 6-\xc0\x88\x8e\xc3\xa9\x0es*^8\x90u\xe9\xcf\x0dD\xa1\xc4\x9esa\x85\x8b\x14Z \xa5qJ\x12{\xad\xe3\x0fj\xefs\x1a\xc2\xa8\xa2\xe8\xaf\xf9x\xa6\xbd`\x9b\xe1M\xfb\x0d6\xc5g$\x8d\x03rE\n\x8a3\x8b\x08#D\xc1j\xbd$T(\x12h(\x90\xf8\xb1\x96*\x89\x0fk\xda\x9e\xbb\xa0\x1bqe|9\xb5\xff\xafq\x9c\xe5\xcdj\x1aoM\xdf\xf8\xfb\x0f\xd6\xbd\xbc?\xdb\xf5P\xac\x08\xe6n\xe0oh\xd1\xb1\x04)\x04\xaf\xaa\x8a\x81\x85\xca3q\x1a\x93\x8a\x01\xf9`\xbb\xad\x0f\xeaW\xe3\xe7D\x19\xc0R\xfb\x12\x88\x03\xfe\xa64I\x7f\x8e\xc7\xc1\xe8\xe9\x8e\xbeM\xcf\x8e\x1c\x93\x8c\x1f\xe1\\cVF\x9ct\x84x\xb3\x03I\x1elH\xf2\x7f\xd5\xefa\xe9\"\x1asj*\xee\x84y\xccO\xb1\xd5\xe9x\xe2\xe4R:\xac\xb4z\x98\x9fP{]L\xc3\xbf.I\xfa\x19G\xd0\x1f\xd38z\xc5 <\x16LV\xb3\xfd\xef\xa7\xd4\x92\xd2\x0f\xe96X\xe8B%DsXD\xecm\xf1\x88\xbd\x04\x86\"\xa5b#s@\xaf\xb2\xee\xf3\xb33\xba\x1c\xf8\xa5K\x12\xdf[\x17\xfaT\x19\xa8N\x95`,\xcd,H\xc4dP2z\x19\xbc\xd8\xfef\xd1\xec\xdf\x84\x98\xfcl\x16\xc4$\x01\xaf\x08}g\xf4X*\xc5\xbb\x96\x82L\xf1\x10La\x9ea\x81\x12\xcfN\x9f\x1d\x83)ya\xa2t)[\xc2 \xb4\xdb\x01<\x81\xf8\xc4\xc1\x19\xe6\xf9{\xe4B\x01\xde{\x8c\xa0Mg\xff\xe9\x08\xfa(\x05S\x01d\xb7\x8ftgp\x08\"\x03!N@\xc0\n<\x1d\xc1\xdeQ^v\xff\x10\xcb\xd6=\x7f\xf4\x08\xf6\xf6i\x81\x8c\x12\xc6\xc9\x04\x83F\x15\x96\x89\xfe\x01Zr\x80\x12K\x1b\xfb\x1a\xb0*[\xfdJ\xd8\x01\x82uup\xc4\x1f\x88\x0e\x1e\x17_\xf5=D\xe8\xc1~\x0e=\xee\xe5\xd0\xe3\xc3\x1c\xda\x1f\x0c\xf02(\xce\x13\xce\x11\xa5\xe0\xac\xcbe \xce\x9b\xf5\xff\xfe\xc5\x9fY\xb5\xfbPuz\xd78Q\xc8\x18\x8b\x1a\x18\xf6\x0dO\xdan \x91Y\x8a\xcfJt\xe5r\xec\xeeX\xd6\x1b\xbew\xf2\xdb:\xa1\xdd\xef\xdf'\xb0\xa76p=\xad\xd8:?'\xc9\xa7\xd1,[\x12\xabJ\xb5y\x9a 9\x8d\x82\xc3T=\x98K\xaf\xceQ\xc5x}9I\xbd\x94|\x7f\x99]\x06a24l\xdadM|\xd33\xfa\xf1\xb0\xcdd\x08\x99Y\xc8O\xc8\x92\xf8i\x14'C0\x04c\xd2\xbf\xcbR/\x19\xbb\x068\xb6Y\xe6\x13Zs\"\xa6\xc2\xdc\x8f\xbc\xaf\xd1F}\xf5\xf4}U\xf1\xf0;\xfa_\xefU\xf9mn\x87\xf6~\xffX\x89\x90\xcd\xed\x0c:\xbb\x84o\xd3'{J\xa0e\xfeh\x7f\xaf_}\xe4\xe5\x8f\x06J\x90i\xd1\x87\xbd]\xc79\xf9N\xfeL\xe0\x0e\xf8z\xc5O\xca\x98C\x81\x9f\x05s8\xa9\xa0)\xe3\x06_U6\xa7|+G\xa3\x10\x93b\xe6\x05!=\xb65\x1c\xac\x0bC\x1d\xa7eEF$\x93\x19\xbc\xd8(i\xd9\x8fC\x9d\x84\xb9\xd1\xbdB\x99\x07\x1e\xb4X'a\xb1\x1c\x97\xd5 \x93\xdfQ\xbf\xd1q/\x95[B\x97$\xfd$\xf2\xbd\xe5s\xdc\x04\x9b\xc5\xfa\xb3{\x18\x8c\xd8\x8b\x13\xf2\xd3\xde\x8a\xbf\xea\xd8\xb1\x18\xfcv^\x0erC2]|\xdc\xe9t&a\x16/\x87`-\xd2t\x9d\x0cwv\xd6$M\xd2(&\xdd\xe4\x9dwyI\xe2n\x10\xed\\\x0dv\xc4\xaf/\x92(\xb4&\xe1,Z\x9d\x07\xb3!X\x7f\x85?\xe8d\x815 \xd11\xddK\xa3\xf8\x07\xa5:\xa3p\x19\x84\xe5\x1aEAk\x12F^\x96.\x06\x9f\x91Y\x10\x13?-\xde\x1c\xee\xec,\xe9\xbc-\xa2$\x1d\xee\x0ez\xbd\x1dV\xb2\x13\xf3\xa2\xddE\xbaZZ\x93\xf0\xb1v\xd0\x1bQp\xc9\xb5c\xd07hR\xe3\x87\xa9^\x7f\xdc\xdb\xdf\xebi\xb7od\xc4\xdcZ\xf4Q\xbcH\x85\xb5\x120\xfe\xa6\x88\x15=#\xeb\x98\xf8^Jf\xe0\x853\xc9\x91&K\xc8\xac\xdb\xe0C\x03\xf2\xfct\xa9\x98\x87#\xe9\xc9IK\xbbg\xfe\x82\xac\x98uu\xf7\xa8\xf4\xe4\xe3g/?9{\xf6\xf1\x8b\xf3\xb3\xe7\x7f\xed\xc5\xa7\xcf\xb8\xc1vP*\xf3\x93g\xaf_\xc9\xcf\x07\xbd\xdd\xd2\xf3\xe7\xaf?{Q~^~\xff\xa3\x17\x1f?\xfb\xc1'o\xce\xab\xed\xec\xefj\x8b}\xfc\x83O>\x91\x8b\x1d\x95\x8b-#o\x86\xa1\x02\xe8\x97\xea\x83g\xf4P\xc1\x9f=c\x17\xce\xc4\xe3\xc4\x9b\x93O\xc4\xbb\xe2\x87\xae\x80\xa8C\xfa-\x17\x9be\xab5\xc6\x0c\xa4_\xaa\xef\x7f$\x1e\x8a\x1fr\x81\x9f~\xf6\xe9'/\xae}\x82!\xe89\x1e\x96\x86\xf6\xe9\xcbW/?}\xf6I\xddZl8\x87\xe6\xe9K|/D\xd5\x81E\xbfY\xa5gH\xe1\xd8C\xfcZ~\xeaG+\xee{\x12\xd9\x16\xffQ.\xe1\xcdf\xcf\xa5\xf0\xe1X\xb0\x0c\xb3\xee!\xdfI\xfe}\xd5\xab\xfcA>\x9b%0\xbfD\xa5h\xa0\xb3|\xeaJ`/\x9f\xaf\x128iVH\x97_\xf0U\x85\xf2\x1cF0(\x83(\x92\xed\x96A\x14u\xf6\xca\xa0\x85Z\xd7L\xad\xebJ\xad\xeb\x86\xb9\xc2]\xf7z\x9d\xc9u\xefhr\xdd\xfb\xde\xe4\xba\xf7|r\xdd{\xd1\x99\\\xf7?\x9e\\\x1f~\xdc\x99\\\x1f\xedM\xae\x8f\x0e:\x93\xeb\xe3\x8f'\xd9\xc7\x1f\x7f\xfc\x02\xff\xffxz;\x9ed\x1f\x1d\xd1\x97\xb3\x8f\xbe\xf7\xf1\xc7S\xfb\xb4E!\xcf\x19\x84\x96pn\xed\xd3\xe1\xf8\xf3r\xb1\xdb\xcf\x9dJ\xb1\x9dr\xb7.y\xb7\x8e\xf6\xcb\x1ez\xe5R+,\xe5N\xc6\x93\xe9\xe4\xab\xc9\xfb\xea\xe3s\xfa\xf8s\xfbt\xd8\xbam\xb5n[c\xaf\xf3\xe5\xa43m\xb7\x9c\x0fv\x82r\xc9\x8b\xa2\xe4\xf8\xf3\xa2>\xc7>\x1d\xfe\xc4\xb8\xd79\xf6:\xf3\xe9W\x83\xf7\xb7\xec\xfb\x97\x93\xce_9\x99\xecLN\x87\xdf}4\x9a\xb4'\x1f\xb8\xe7\x93n\xeb\x7f\x98|\xf8xbO\x1c\xfa\xf6\xd4\xf9\xf0\x83\x9d@\xc7\"\xde\x19YD\x9f_B\xc33\xe3.\xfb.\x11q\xb5\xaakcU\xc7EM\xbb\x83\x0dj:\xdb\xa6&\xec\xdf\xb6}}alao\xaf\xa8\xea\xb8/}\xdf\x95\x9a\x18\x94~\xeco\xd0\xe03\x83yG+\x9e\xee\x1d\xa1\xb9\x02\xa5K~\xd2>\xc5 9{G0\xa4\xc7\xea'\\\xef\xb0;\x80[`\xc9\x9c\xd91\xbb7@}O\x87\x16j\xd3i\x19B\xa7_\xdb\xb1\xd7\xe6\x998\xca\x15]\xd6\xa4g\xb1\x96s\xc8\x7f\x87\x00\xb9\xc8\x05\x85\xf4\xfb\x07\x12(\xc5BU@?_.\n\n\x19H\xae\xe9\nA\xbd\x81\x04\x9a\xb3R{\x12(f\xa5\xfa\x05\xe8\xbf\xa7\x90]\xe95\xd4}\xec\x16/=\xb6\x1e\xc3\x10\xf6\xa4a\xec`\x0f\xe5\x96&\x14r(u\xe7\xff\xf9y,\xb3/A~\x13\xcb\xc8#E\xaa@\xa1G\xbd\n\xf4\x98)\xabk\x17\xe1\x8b\x9a#\xc6\x93\x11\x1c\xec\xef\xef\xee\xc3)W\\a\x96\xe9\xe7\\\xdfd\xa7\x85\x03j\xf9\x01K\xe9\xd9\xa6\xa7\xb5\x0e\xd6p\x00O\x9fB\x9fJX\xfb\x07\xbb\x83^\xf9\xd1#:\xdf\xbb\x8a\x11\x15\xe4\xd3\xd8[\x90\x13\xd3\x0e\xf6\x0f\x1c\x17^j`\x9f\xb2\x84r\x9f\xc2\x13\x18\xec\x1f\x9c\xc0\xa7\xed\xb6\x03o\xc7\x9f\xd23\xd9k\xfbS\x87\xc7\x19\xe8\xb9\xf0\xb2\x00\xea\x88\xd3\x1b\xad\x1e_hb\xc9;\x08P\x01C\xdeQI\xb7;\x0f\x96$\xf4V\x84\xb2\xf6 \\g)\xde\xdb\x8f\x92 \xc5;\x96i\x97\x9e\x1fd\x18t8\xf0,\xf5\xe2\xb2\x9b\xbc\xda\x97\xe7\xda\xbe0Q\x99\xf7\xb3\xf6\xfd\xef\xeb\xdf\xefF\xe1\x0f\xbd8\x0c\xc2Kv\x96\xcc\x7f\xf2\xeb\xea\xe8y\xca\xeb\xd7-\x0e]\x97\xcf\x94\xd3\"\x15\xd9\x86\x8d\x16\x1a\xf1\xbe1d\x0b?\xa2\x8f \xed^\x918\xa1\xc3x\xf4\x88\xcd\x845\xcb\xd6\xcb\xc0\xf7R~3\xf5'h\x93\xc0\x8eT\x98Q\xca\xe5\x91\x0fC)`\x15{\xb3\\\x12<\x9f\x8a\x96 \x90k\xcfO\xf1b*\xc9U\xba\xb4\x9a\\\xe3n\xc7\x8c+R\xa67m;\x93\xae\xf8\xf6\xc1N\x97\\\x13\xdf\x0e\xc7=\x1e\x03\x8d5\x14,\x97\x9dy\x14\xafdw\xffh\x0e\xe9\x82\x80\xda[*\x8b\xa1\xf4\xf82L\xedx\xdc\x9f\xbal\xafDe\xf8@\xc0\xa5\xb8\x8e\xac\xb5,d#\xc1lhX\xbf\x983\xde\xe6,\xf2\xf3A\x15\x13:\x82\x90E-\xef\xfa\x0b\xe2\xbf\xfd$\x08\xc9\xf7b\xe2\xbd\xa5\xe2[Dw\x90h\n\xef\xdc\x0e\x8a\xaf\xdf\xe7\xad&\xd9\x9a\x8a\xb1d\xd6\xd0hiu+*\xb67\xcf\xfe\xeav\xe8\xa2\xe2\xca\xc0\xb0\xdao\x9e\xfd\xd5\x9a\xc5N\xdfE\x85\xfe\xdf\x12\ny\x16\xd1\x0e\xbf\xd1u8\xef\xa6$I\xed\x18\x03@(K\x9bz\x97\xb0\xf0\xc2\xd9\x92\x80=\x0f\xe2$\xcd+t\xc4$\x94\xfa@[\xc9C*\xa4\xde\xe5\xa7\xde\xda\x85\xb8@\x9b\xc7\xe9\x82\xc4\x84\x1ep=X\xc7\xe4*\x88\xb2dy\x033\xe2/\xbd\x98\xcc \xc9\xe6\xf3\xe0\x1a\xa9\xa2\xf5\x18\xda\x10C\x1b\x1e[R7\x1e;.\\\xb0.\x07\xe6.\xafcB\xab\xb1\x13\xe2G\xe1l\x83>\x8b\xce2\xbf\x87r\xe0\xfc\x92\x96Q\xa5=\xaf\xc4\x92\xe2@U)\xa4\xc8\xdf\xaa\xaa\xe9\x08<\xd1\xa3\x02\xbac\xb0\xd8;\x94\xd8\xf2+\x1e\x888\xb4\x19\xa5<\x08V\x120sz$E\xf5f\xf9\x08\"\xfa\xa7=\x82\xbe\xc3e\x06t\x0e\xf0\xaa\xb6\x15&\xfb=\x19AF\xd7,C\xb9\xa7\xdf\xdf\xeb\xf7\xfb\xc5d\x93\xeb5\xbb\x83\xcf\xa2\x1c\xfc\xe4\xd9\xebW@\xab\xf1\xfc\x94(\xb90A\xdc4\xbca\xab\xe6I4\x84.E\x92\xc6\xc4[\xa1\xc3\x81\x17\x84 \x84Q\xd8Y\xc7A\xc8\xb6z^m\xa2\xab7\xed\xc6$\xc9\x96\x98/\xd53\xad\x99f\xc9>)\x96Lqo\xb9\xe2 \x04\xd0-\xac\xe2,\x833\x1cw\x83\x84\xa7\xdb\x0f%\x0c\xe4\x1a\x9a\x15\x89/ \xac\xbc\xf5:\x08/\x93\x13\xc4\xb6u\x1c]\x053\x8a\xddQ\x16\xfb\x84\xe7o\xa6\x9b@&k\x96\x93\x87\xd8\xa4\x87E[\xf2*xKn\x12;t\x9c|A=x\x02>\xfd\xc3\x164\xc3\x80\x8f\xde\xd4\x95\xe2\x9ce\xd87\x9b\xb0\x90\x94!\xfa\xdb\x04\xecG\xabW\xcfM?\x920Z\xce?\xac\x9b*\xdf\x85\xb9\x8a\xd7Aa\x08\x0cd.\xc3S\xf2\x08#\x91\x95z\x97\xc3\x1bo\xb5\xecF\xf1\xa5;\xe8\xf5\x06C\x9c?\xe6q\xabAsZ7\xbb\xeb\x18$L(2E>\xc0\xa5\xe2\xae0\xf4\xa0\x1d\xe5s\xe7\xc3\x13\x98\xd3?l\xee\x04.Dc\x1fS\x90\x1b\xb07/\xa6\x96\xc1\xe7)\xea]\xe9\x94'y\x8cb\x9e\xde\xa9X\x13\x06\xb0\x99\\\x04t\x8f\xdd\xde\xeaD\xa7\x11x\xecI!`\x95\xe5\x022\x13(\x06o\xc9\x0d&\xe0#\xe3`\xcaB$\xe5\x97~\x83\xe6D>\xea\xe2\x7f\xb9\xd1Y\x8a\x1f2p)\x05\x8d\x92(I\xd1s\x87\xdd\xe8\x12?\xdbmz\xac\xd8\xe5\xc8p\n\xb6\xfc\xc8\xcd\x8f\x9a\xb552Y\xaex\x8d\xca\xe8lz<\xc0\x89\xbd\xa0,\x9en/A\xa8\x18\x85\xc7gmt3\x92$S\x1c\x80\xa8\xacvf>6\xf1\xee\\\x86\x97s\x0e\xd5\x0e\xe1\x84;\x10\x04\xda\xb8\xac\xdc+\xeb\xda\x0e\x1c\x1e}TS[\xbb-\xd7\xa7\xdd)\xb8\xdbv\xd9\xd1\xca\xe0!7\x8bj\x0c~\x9b\xb4\xac}\xf9=\xbc[\x04Td\xe8\xf7\nA\xae\xbf[|\xe7`C\xbf[\xef\x90\x15\xe12\xaa%pv\xbeD\x07\x83\xe6\x89v!\xa6x\xc5\xd6\xfbe8\xa3R*\x9e\x9f\xf8A\x96.\x80\xfc\x90\x16\xdez\xd8\xefu\xbb\x8c\x87\xb0\x0d\x8b\xe1\xc6\x0cq\xa5\x9e\xcd\x0c\x99\x06\x8f{\xc16\x08\xe3\xbe?\xc5\x89\xfb\xd2\x85V\x1f\xbd\xe3\\\xd1\x94@\x0e\xa7\xdc\xbfM\x1aw\x0bf\x8f\xb4 g\xf7|HO\xb9\x83\x10\x9f`\x87\xf3\xb1\x0bo&\x13\x01zj\xf1 !?\x9b\x91\xd0'@\xc24\xbe1\x8a\xd9\xcc\xc7\xacDd\x88\x96\x96\n\x12\xd0\xf28\x8e\xd0\x83\x13Kd$p\x07\xc5\x89\xb4\xfb6\x08g0\x02K\xf4\xc0r\x8b\xcd\x841\xc6\x9a\x04\xca\x9f6\xd3\xa8\\\xc4D\x8c\xd6\xef\x80*\xa6\xd3!\xee\xee\x16\x11\xc2\x1b\x04\x90\xdc\x7fBW\x8f\xb4a\xe8\xf8M\x1a\x18\x8f\x1f+\x99i\x87R\xe5\x03.\x01m\xc2-0\x12m\xc41~\xb3\x17\x86\xb0\xcb\xa4\xa4@D\xb1\xc58\\t\x19Z-k\xf3Z\xd8\x1b\x16\x0b6 \x0b\x94\x91N\xf20\x8a\x03\x9b4\xa7\xbc\x98\x8b\x01\x92\x14p00\xb2~\x89r<\xc9\xb3\xf8\xd1\xd1\xc7\xba\x83pi\x97m\xd2\xbdBL\xcc\xc2\xfc\x04K\xc2\x99\xd0 \xf0\x83\xe8\xbb ]\x04!xpE\xe2\x0b/\x0dVt\xe5\xab\n\x1eS\xa8#.\xb9I\xe3m\x9d1)._M\x96D\xe0T\x9c\x80\xbdK\xa1\xf3\xe0\x07H~\x10\x06r\xed/\xbd\x15C\xc0\x95\x17\xbfM\xac<\x0eqe.X\x16\x85\n\xdd\xcd\x15;\xf2\x195\xf4*:\x9dJ\x9bI\xe6/JGn\xe6\xa5I1\xaf\x8c>\x8c\xb4o6\xef\xeaB7\xaf\xe7*WJ\x15\xba\x02\xe3L\xcd\x97\xd1;J.\xe9v\x8d\xe2R\xff\xcb\xab\xa6#\x7f\xc8\xc8Z\x17\xfa\xf60\x99u\xfd\x1c\x0d\xd1m#F]\xe6)\x08\"\x1a\xc3PU\x83\x85\x8eT\"W8\x85STs\x0d\xe9.\xe5\\\xa2(Ea\xe2\xa9\xee\xb1z~\x16\xe5\x99\xb6-\x0bs\xcd\x9a\xb4\xea\xa8Y\x0bQ\xb3\xf6\x18=\xc1k\x89\xf7\x0f\xcd\xc4[C\x96\x8f\x18Y\x0e\xefA\x96\xcd\x82\x8c\x9e4\x87\xc0K\xc8\xe4\xd9\xd0\x81\x12fV\xb1Zl\xdc\x90o\\v\xd4l\xbd\xb0C\x07\x93\xc76\xd7\xa8\xe5\xb0\xd2\xb6\xc9u \xc5~,\x0f!\x8cf\x04VYR\xe0\x9b\x97\xc2\x92xI\x8a\xaa{I\xcbVb\xd3\xf5\xbb\xa9a\x81\x7fJ\xd2\x86i\xf8\xc2U~I\xf2\xc6\x85K\x17V.\x9c\xbbp\xe1\xc2kf\x8c\xd20\xed7\x06f\xfe}\x033\x97\x16{\x19$) I~Vb\xbfl+Zc\xd4\xd9T\xe8j\xa1\x88\x1e\x9d\xcf\x82\x00pyE\xfc\xcc%\x15\x06@\xb5'\x8c\xd0\x19b]\xc8eLA\x85A\xeb\x1f=R\x04Q\xfbM.\xaf\x96\xc578e\x93\x00\xc3\xca!\x93\x9f:\xd0\\W}\xf8\x84+\xc2>E\x97x\x07\x0d\x1e\xf4\x85O\x0d\xde\x9a'L\x82\xba\xbd\xc5\xcdx\xe2\x94\xbbwZ\xf4\xee\x86\xc9c\xdfJ'a\x88\xd5\xeb\xd6\x8f\x07j\x80\x11\xbc\xa1\x9d\x8cr\x0b\xce\xa7\xf4\xc1\x9ao*z\xea\xbb\x80\x11\xf8\xc5\xa4\xcfs\x92F\xf0<\xd6\xa6\x9c\xecu\x99\xd5\x94\xec\x88\xf9L\xc1)\xbf:\x8eg\xaf\xd789\xdb\xd8X\xdcB\xc9\x9b\x98Og\xc0=w\xcc'4\xe0^;_\xd5\x8475=\xcb\x91T\xfb\xf4\xaa\xf6\xe9M\xed\xd3K\xc3\x06\x04\xeeG\xa3\x0b\"|\x87\xf3\xe3\x92\xab\xac7;?z\xc6$D\x18\x84\xa8\xa9\x1e.\xd6D\xd2\xa1-\xab\xc8\xb4\x07\xecP\x80\x07\x9a\xfd#\xfe\xfd\xf6\x96\xd2\xf2\xb8\xf9\n%\xd2\xc1\xd0\xc5[\xaf\xec\x08h\xd4A\xc9\xefI\x07<\xadL-\x7fX\xaa\xdf\xa6\x91:'pm{t\x9f\x1b\x8a6\xc8W\xf2\x87\xf6p\x9f\xf9[x\x0e\x9c\x99\x1a\xafH\xca\xb9\xc4\xe8Q\x11\xfe\xffc\xee[\xbb\xdb\xb6\x95E\xbf\xf7W\x8cx{\x1c2\x92\x15I~$Qlk\xa5i\xd2z7ur\x9a\xa4\xfbt\xcbj\x16-A6\x1b\x89T\xf9\x88\xed\xbd\xdd\xf3\xed\xfe\xb1\xfb\xcb\xee\xc2\x0c\x00\x82$@\xd2N\xd2\xd6k\xb5\xa1@\x10\xcf\xc1`\xde\x93\xb2d\xe3\xcf\xb5\xdbG\x97\xad\x82\xbf\xe4%\x9c\x82\xfe\xc0\xae\xb7\xd1w\x02\x12\xb6\xf1c\xa4\xc6\x149}\xb6\x8a\xe6\x1f\xa4\xd4\x9a__\xc8l\xb9\xa8kX\xf5\xf2\xa88Z\xc4\x9b\x8f\x02K\x8b\xa2\xb5@r\x02\xb8\x91\xf8\xe4\xff.\xd4\xf9\xc5/$\xc2\xaf_\x97\x86\x9c\xcc\xf2\x0f\x01c\xad\xb9g\xd1\xd5\x93\x14\xee\x9d9\x07\x96\xfa\xee\xf8\x9f\xd2\x13aD\xd8\x98\xf9\x0b~\xf1\x07kN\xcd\x04\xa9\x12\xe8o\xfc ~\x02>\xcc\xa3U\x14\xf2\x95^\x07IR \x9bW\xfe3\xbbKC\x1d\xb3\xa2\xff}\xaey\x9a\xe6X\xdcz\x12_\xf0 \xae\xb3U\x1a\xe0\xd9\xf9\xc0\xaea\xed_\x830q\xd6W\x05\xd5\x1b\xf6\xb9\x19\xdf\x88\x19\xef\x13\xcb\xe5\xf3\x0b\xf2\xd3\x80Mp\xed\xe42yN\xedi08\xc8Y\xcb \x9cG\xeb\x0d\xea_\xd8\x95ec\xf9l\x91\xceS{\xfb\x04\xa2\x18\x96\xd1j\x15]\xb2\x05\x9c]\x83\x8fj\xd0\xd4?\xcbV\xa8\xeca\xebMz\x8d\xca\x0d\"\xfcr\x9c\xa8\xbc\xa6c\xf3\xc6P(\x11\x0dEYeP\xae\xa4\x037DZ\x04T\xca\xa7\xab\x1f+A\x06hB\xb1s\xbc\xd9+k{-b\xd9\x1b\x97\xb7(Hk\xc6\x88\x9e\x81\xa8Qr3\xbfVnV\x80;\x9b\x17c\x93\xe8\xac\xf2Q\x15\xf2\xc4\xd1AH\xb3\x01\xda\xba j\xab\x9c\xae\\\xd4&\xf1d\x81~\xc5\x16\n\xfd\xfe\x81\xc4O\x0f\xce\xbc*\x01d\xa3~\xcaZ]\xccY\xb3\xd4\x93\x88u,\xf9\xc6\x17\xf5\x84\xd2\xc7FB\xe9\xda\xe0\xad\x04\x02H\x859\xa8\xbbi\x86\x05\xd2\x89=\xde\xe9 98IbM\xe9\xc9k0\x1f\xefs8\"\x82ac\xe5EUmN>\x8f\xf6D\x8f\x03\xea\xf1?M\xfeip7\xb2*\xf6(\xc3T\xd3=- \xabM-a\xa5\x8e\x1a\xf3z\xad\x96W\xe8\x0b\xab\xec+i\xd2\x08v\x17\x05\xd8\xfd\xa8\xc1.\xc7\xb7\n~al\x13\x1b\xc7\xf6\xcb\xe4\"\xa7?\x08?\xc2>9\xc5\x9f\x04\xe1\xf9\x8a\xc1\xefY\xc4\xab\x8a\xbdGZ\xa2n\x96\x86\x83t\x1b6\xc3\xdc\xe9\xe78):\x83a95\xbb\x04\x1e-\xc4t\x9f\xff\xd4`\xe2m\xf3\xa9i1\x9eZ\xc9\x88\xf0]\xf5\xd5\xa0\x8d\x18m\xe0\x95\x87d\x03|\x14c\x8dd\x9b-\xce\xa2\xa9\xab\xcbv*\x1aO\x87~\xfb9TrM\x9f\xfcE9\xd0\x7f\x98\xfa3\xafp\xc1\x1c\xa3\xef\x88>\xc9\x16-Rp\xd1\x910\x83\xe3\x1c\x8b\xcf\xcf\xd2\x08]\x89\x1f*Vf\x17\xc6\xf0hO\xfd\xe4l\xc3\xc0\x83#\xfe\xbf\x16\xba\xb2\x80\x14\xda\x11\x19m\x07\xfc\xbb'\x10lo{\xd8\xfb\xd3\xb6k\xc5\x99\x14\x0c\x1b\x87~5\x07\x07\xb0\xebA\x172\xc5R\xa9\x13x\xc1\xae\xfc\x05\x9b\x07k\x7fU\xef\xd2\xa4\xff\xe9K\xf9\x9b\x1b\x95\xe0\xc5N\xb7\xd0ZJ,\xf0!\x8c.C\x10\x11\xd3\x94\xcc\xac\xa6\xeb\xea\xc9\xa8\xc7\xa4~\x8eI\xe9\xe8\xdb0i\xb5\xe1/\x84I\x17Qv\xd6\x06\x93\x96\x06\xd3\x82\x96\xb8\x0dj5\x8f\xc2\x88Z51NGC\xb26\x0c+\x0c\\\xcdXu\x97d\x18\xcd\x8a\xef6X\xd5\xd2H+s'2\x81{#\xac\xdf:\xcf\xdd\x98\xa3\xcd6-V\x07s+\x93\xa7U\xe0'\xb7\xb2x2\x18?\xf6\x8a\xa6N\x9aH\xbd\x14\x8eE7\x84\xbc\x97\x85J\x0c\xb0\x10\xe3(\x19\xc5iw\x92.\xa6\x0fge\xddU\x95\\\xe5`rWS\x14\x94\xba.\xa5\xbc\x95\xdf\x94v\xe1\x9c]\xd1\xcd\xc1\xeb\x8d\xbbl\x06,\xbe\"\xcf\xdd%\xb9}\x12\x92F\xa6w\xe7Q\xfe\xbc;\xd2\xcaw\xf2g)\xe8\xc3\x1f\xfbz\xa5\xc7\xda\xb3Vg\xe7\xa1V_+\x7fL\xa1\x1e\x96\xb5P\x8e7\xce\xbe\xd6\xbd\x10\x9b-IF\xff\xa6\xf9\x18 \xee\xec\xe6\x86\xec\xfb8\x98\xb78X\xcd\xe4J\x80\xbe\xe4ErWX\xad\x8b\x03\xb6\xac\xa5B\x84u\xc6\xb2\x89b\xb8\xe3\x14k\x98g-\x8f\xef\xce^\xdbA\xd4\x0f\x00}eZ\xf4\xd9$\x95h\xbcj\xf29.\x9b\xa5\x8f\xbc\xcdK\xac\xd8l\x05\xe1+1\x8bT\xd3h\xc6gsU@\"\x13\xed\xe6DdP\x14\xdc\x1c\xda\xb3t\xe9\x7f\x99\xc6\xbf\xdfYZ%\xfej\xe3\xb6\xcb?\xbb\xc0\x04\x8af\xf8\xc2\xff\x83\x8c\x078~\xd2wB\xe8\xaf\x0b27Kr\x01\xf9w\x179\x8e\xb9\x14\x15`D\xcb\x10\xfe\xec\x0c%-#\xc6\xbb\x0d\xbeWw8\xbd\x1e\\ \xcc\xe7\x16k\x08C3\xcbv4\xb8<\xd8n\xc4\xf2P;\x1d\x85F\xc8%X\xa0\x99\xa2\xc5\xea\xa6*Q!R\xa4'\xad( \xfd\xbd\x16 \x94\x07\xd0\x96\xde,\xca\xd8\xc0\x998(\x9b\xaa\xa9\xab\x95\x08\xcdnn\x07\x96\xdf\xd5\xc9E\x94\xad\x16h\xabs\xe1\x7fd\xe0\x87\xd7\xd2\xf2\x1a\x95\xb0\xd2\xdf\xbb\xb5\xba[\xe9\x15s\xd1\xd9\x8fjVh\xe4)l\xe1h\xf5\x91\xb9\xda\xd4\xeb\xf1\x84\x06\x13\xef\xfbs\x19;OwM\x93\xfb\xfc\x9e4\xccw\xdc\x82\xcf{~\x05\xb2\xcf=!\xae7\x8c\xbaFh\xbf\xb9\x01g\xe9\xafVg\xfe\xfc\x833\xeb\xc9\xed\x99\x80X\xb7\xda\xeaS\xac=+\xccT\xac\xd1\xd6\x16\xbc\xa7O\xa8\x18\x1f\xcd\xa1d\x10\xa2\xf1=\xdf\xfe\xce\x01\xc6\xe0\xc4\x95\xec\xc2\xbd#H\xfds\xd4< \x98?\x13\xbe\x13\xa2uN+\xf6\xf0 `i\x9a\x97\xdeC\xff\x9b\xca.\x93\xc3{\xd3N\xdeq\xebr#4\xa1'\x13\xdd\xa31\xd9\x82!\xbfS\x9a\xa1s\x94+\xe1\xd0\xcbI\xf7\x91\"~\x94W,\x7fdI(\xd5\xc2\x8a\x7f\xbe\x8a\x12&\xcc\xf8K'\x99_\xe8\x95\x89\xdf\xdc\xc0\xeb\xafr\xf8R\x8f\xcaw\xe1\x87v\x9e\x85\x1a\xfa\xaf\x00\xa9\xc9\xc3P\x90~Z\x18!\xe1KP\x0d#\x94\xf6W\xec\xdc\x9f_\xf7\x94K\x8f\xc8l\xa6m\x18\x99=I\xb1U\x0b\x97E\xdc\xf1\"\x9f\xd1\xfcU\x0f:nIs4\x10tw\x07-z\xcc\xd20\x9ck\x06\xed\x9d\x13m|d\xc1\xdf\xadMC5\xbc\xect\xd63\xfa\xba\x15\xd8=\x19\x0f\x05\x0e\xc8\x8d[\xb8\x07\xa9xH\xc8k\"kiR\x1b\xeb\xe6\xcc!PKNCd\x06\xf8L\xd1\x19\xa0\xa8\xa1\xad\xcd\xb1\xd4\xa8\xa3m3\x04;\xd26\xf8hR\xfc\x05\xfbUPC\xdd[gZ\x1b\xd2\x01\xe4\xb2~1\xc0\xe2\x7f\xb1t\xe7\xae\x81\xa8\x16\x04\x9d6&\xd2;\x8b\xeb\xed'\xe1\xe1\xf7\xd34\x9cI\x19\x1b\xc7\xa7\xaf\x85\xc4\x81\xf0\xa9\x12\x82\xe5`Z\x90<|e\xef\xbc\x88\x0f\x06\x1ak$\xce{\xee\x9e_\x8f(\xdaV\xa4x\x0e\xed+\x8f\xbcbD\x17\x11\xe1A\x1f7_\x90\xccpV\x13\x14\xd0\xad\xfd\xb8\x12\xb7\xe5\xe7\x9c\xa6\x17\xd3D;\x8d\x8df\x9cV\\\x98*\x92\xde\xda\x82sr\xf0,\xee}T\xdc{P\xa18\xc2(\xdc~\xfa\xe6\xd9\xf1\xb1\x16O&\x01?f\x10\x84)\x8b71C\xc7\x87\x04\xd9-\x15tNnmR \x1b\xd0\x82\x9f\x9d\xc0\xee~\xf3\"{\x82\x14hXa\xad\x82\xe6I\xbd\xadc\xc9\xaa<4\x8aQ\x16*\xc03\xf7\xe0(\xecG\xede\xfc\x9dk\x8c\xc2XL\n\xc3d\x86(~G\x0e$\xbd\xa0\xe2\xda\xc9\x901\xa5\x05\xc8\xa7\x80K b\xc9\xd4Wrs\xf3\x82\x1e\xec\xef\x8d\x1e\x8aX\xa9\xfaG\x03Y\x93\x97\x8b<\xfa^\x19\xf7Q\xb2\x04\n\xc5\xd9\xa8YK/\x82\x84\xb6\x100\xfd\x01\xfe\x96\xd131!\x92\xfa!H\x1eQ'\x91\xf1\xd8\x99|\xbc\xb9A\x9e\x9b\xbf\xcc\x03Y\x1eb\xda*\xf9\xab\xd8\x04Q\"XE<\xde\xdc\x90\xd5\x02\x7f\x8b\x01\xaa\xf8;\x19\xa9J\xbdQ\xe4\x1a~)\x7f\x14\xdb.01|j\xf9\x981\nx\xb0b\x8bcQG|\"\xe8wK\xe5\xb7\xf4V\x0d\x1d\xf7.\x07\x06Q\xae\xc9\"\x06j\xb4(\x8e\xd0\x7fJ\x89\x84^\xa6\x1b\x02a\xa1:\x9fH_\x14\x11-m\xa7\x81\x08\x0c\xc5^\"$\x0d\x1c\x158(\xac\x1e\xd3P\xbb\x80<\x08\xf5A\x90\x9bFX8\xb7&\x92\xf3\x89^\xe7 \x0f\xf8\xb8\x0d\xc3'\x1e\xfc\xe0Z<\x8c\xc3|n\xb5\x07\xf4k\x9b8Z\x13E\xc3!\x9d\xe3rW\xc8G\xcb\x96\x1c\xcc-B\xf9\x88\xf3\xfc$\x91aFZH\xac<\x04[\x0c\x07\x10\xf0\x7f(\x04\x1bs\xa3i<\xab\xc7-\xdf\x1b\x0f\x9c<\x99\xdf\x99\xf6/XJ\xaa&T\xc9\xaf\xaa\xe7\x95\xd7\x1a\x8a-\x95\xb5\xe4\xb2N\x07\x06\x9f\x82<\x81C\xe0\xe6\x8aC\xa5\xa1W\x184\x085\xec\xda\x83\xb3,\x85e\x94\xf1[.\x8a\xd9\xad\x128\xe4I\x0c\xbe\xeeU\x93\x1e|\xdf\xb3\xe6+h\xd2B\xb4\xd8S\x04\x99\xb8\xcf\xaeR\x16.\xdc\xea\xf2\xd1\xa1\x1eCV\x9c\x0f\xef\xac\xb4\x1d\x12\xf8\xee\xd8\xd8W\xdaOc\x02\x87Z\xcc,f\xf3\xfd]gS\x8d\x0f\xfc\xe9\xe9\nL\xc1D\x03\xb7\x10z\xb1r\x97r<&.\x12\x89e\xcf\xb2\xe5\x92Pw\x15e\x86E\x94\x19\x8b\x9f\xf3h\x95\xad\xc3B\xa0\xd3\x1c\xee\x02-\xa3\xc19K\xdf\x84\xc1f\xc3\xd2\xa6\x05\xae\x98\xabW\xcfbG\x1b\xae\xa7\x0b\x0dL\xbc7\x88\x00\xf0\xbb\x1a\xc5\xf0pOD\xc0\x91\xf1o\xf4\xd9\n\xeb\x00~\x9do\xd3yvN\x07\xa7\xf1i\xf8\xff\xfe\xaf\x9eU\xc0\xe9\x07\xe1\x82]\xbdZ\xba\xdah\x10\x8b?M\xdd\x80\xf4\x17\x96\x90U\x01lS\xf0\xc0\xc2\"oc\xbf\x0c\x1e\xc0\x88(\x0f3\xb3\x86\xe3\x86~\xbf\x0f8\xf8\xee!\xec\x99\xb9\x946\xeef\xb8Dz\x1e\xbd\xd2Jd\x9c\xec\xd3\xa6\x97\x93Ww^\x9a\xcc\xba,n&\xd0\xf8vieZ\xacJ\xa4\xafJ\xc6\xd7\xf7\x13VE@\x94/\xd7CL\x80\xa8\xba\x80\\\x11sSJ@1\x94\xe0\xbc|4\x00\xefR\xc0\xfcn\xb9\x16t\x0d{\xde\xd5\xee\x8b.8\xbf::\x82\xd2\xcf\x90L\x19\xd86\x1b\xb5\xe3\x18\xef\xf8\xfc\xe8s\x82\x15)\x88{A($\x8f\xea\x1dFK\xbe\x87\xaarN\xb1\xf8)q0\x0e\xc6\xa3W\x98\x00\xf9\xba.\x9f\x9b\xc0\x04\xf9{Q@*\x10\xd2M0\xb9\xa096p\x85\x88\x8az\x19\xd3\xaa1\xde\xad\x11M+L\xf3\x89Hs\xa0])z\xe3\xfc2\x8e]C4\x9c$\x8d+\xd9\xfd>\x04\xe1b\x9c\xabs\x0b\xef\x94\xf7\xd7lu\xdb\xc6\xcd#\xaf\xdb\x17\x91\xe7\xf1Mz\xbdbcp\xd4z9\x7f\xf5q?\x8b\xa2?\xf5\xb8\x1bL\xa7Z\x1f\xf7\xc2\xb1N\xe3\x8c\xe9\xc7\xf8m\xf9\xf7O\xef\x9e\xcbc\xcd\x0b\xf6\xf4\x8f\x97\xfe*)\xd4~Q)x\xfa\xf2\xcd\xf3\xbb\xa2\x85\xbas|\x9b\x81\x7fN\xfc\xe1LE&\x81o\xa2h\xc5\xfcpF}T\xf2\xd2I\nT\xa8\xe1k\xe7^\x8bmL8\xc1\x9a\x82\\\xd2\xad0\x91\x0b4\x06\xb1KmN\xb1 E\xb4\xea\x8b\x16{,\xf7\xbbM_&\x8c\xd1\xae/9\xaf\x17\x96y\xfd\x1d\x10\x88%3\xe2m\xb3\x9aV\xf2\xa6\xed\xe5\xe344\x94\xb5o\xe8\xa1\xd6\x90|*c\xba\xc0\x84\xe9\x820\xfd; :\x12\xd7\xe8\xb2k#\xe0\x04v\x87zS\xc3\xca\"\x17\xee\xe4FU\xe8\x1a_\xe7\xbfD3\xeed\\\xbc\xc7\xf3\x1e\xa8\xf2\xe9i\xdf\x9d\x8c\x83pys\xcc\xff;y\xe1\xddPQ\xe8\x877'\xfe\xc9\xcd\xc9\xd3\x13\xcf\xfbZ7\xb9\xc7\x80\xfc\x98\xadW\xeb\x9c=\xb0K \x8d\xbc\xf3r\x15\xf9_\x84{\xd6\x85\xdb\xa4\x15\xe1\x88\xd6\xedD\x82\x80\xf1t\xda'\x9d\xeaf{\xb3\xcfN\xd2\x18#\xc1\xc8\x11\xc2!H2BX\x1eW\xa8\x91~\x1a\xbd\x8c.\xe5\x89\xe6\xa4\x04L\xf8=>\x06\x11\xfcw:\xeb\x81\xd3\xdd\xceu\xe7\x0c\xe9\x95#q\xc1\xb8d\xf2\xa7h\x91\x1e\xf0\x9a\xcb\x9c\xf4\x10\xa6G0\x11wY\xff\xf5\xab7\xc7o\x8f\x7f~\xfe\xfe\xf8\xe4\xc5\xf1\xc9\xf1\xdb_`,_\x9d<\xff\xeei\xf9\x95\xd3\x0f\xfd0o\xee\xc4?\x811\xb0\"\x85!0\x9b\xcb\xeeFf\x04E2\xe3\x05\x07\x9cZBCX\xe7\xc5Dh\x04\xb7\xe8\x8aIB#\xe6\x9f\xdb \x8d\x10\xees\xb2y\x8c\x0f\xda\xa8\xd8\xdf\x89\xd4p\x89\xd6\xe8\x1c\x92\x1b\x86\x81\xd4hKk\x14\xf0\xa4\x0d\xe2C\xb3l(HN\xfc\x13\xde\x17$\x97A:\xbf\x00\xd7*;\x98\xfb \xd3\xe5\x90cc-\xd0\x16\x07\x81\xcf\xcc\x1dQcJ\x8a\xdb\xa6\xb1\x93\xa7'\xb5\x8d)1m\xab\xc6\xfc\x13\x83<6\xf7x\xb6\x1e7!\xf4\xfb\x12\xab\xc5O\xfeg[\xad\xe3\x93\x17\x9fo\xb5\x8e\xc3e\x9b\xd5\xaab\xa0/\xb7Z\xdb\x9fu\xb9\xb6?\xebzm7.\x98\xe9\xb4\xe7\x9f\x0f\xfa\x03\xc3X\xb4{\xa9H\xf6\xf6 S\xc9\xbc&\x10\xaak\xcaa\x0e\xbfP(\x02fX\x87L\xfe,]C\x99\xfc\n*\xe4\x97\xa2\x8e\xb4\xffy\xdb\xae\xed\xc7\xd7N#A\xd7\xd8\xe2\xa4\xf4\x8b\x93no\xd3\xd9\xcd\x14NO\xd3Y\xd7+\xbc\x1c\xeb\xbd\x17~\x10}H%\xf7=\"\x10\xb1\x85\xfb\xee\xbfn\\N\x8by\xe5n\n\xdf{\x13\xcf\x9b\x14(\xb9V\xea\xdc4X\xb3$\xf5\xd7V+\x96\xcfN\xac\xe5\xe1\xca\x83>\xbbbsA\xb3\xa9\xd2H\x96~\x01r\xcd\x10\x07\xc5\xa23\xd9\x08\xb7L\xf3\xb5\xa7\xf47H\x81\xa9yx\x8a(\xcb'\xa1\xe7'\xf74\xf3\xee\xe7q\x1c\xc5\xae\xf3\xad\x9f2\xe5K\xcbx\x99)(S \xf2\x89v\xd9t8#\xda\xa7\xcb\xa6\xa3\x19y+e\xf4sg\xd6\x83\x0e\x9b\xee\xcer\xf3Wv \xbc\x03\x97\xff\xaf\xff\xee\xed3W,\x83\xc9\xff.\x10\xe1)\xba\xbc \x8aN\xd1e\xd3\xbd\x19\xc5\xa5\xe8\xb2\xe9\xfe\xac\x07l\xfapfC\xc2(p\xc5\x80\xb7\xd3\x873A\x94\x0ez\xb0\xe3=\x81U\xeeK\xb9\xf3\xc4\x83\x15\x1a\xf6\x99\x90\x14\x88\xa8\xd1\xddU\x15\xfd\xd9\xc0\x8bM\x1f\xcfp\xe1\xf9\x9e\xed\xb3]\xb8\x0f\xee\xfe\x00\xee\xe3j\x0df\xd0\x85\xae\xcb\xa6\xc3\xe1\x8c\x83\xd9@\x8a\x00qC\xf4/\xb77\x9e\x88\xcb`]6\x0dzV\x1eFS\xdf\xda\x82e?a\xe9\xdb`\xcd\xdce\xff\\\x93?\n\x0d\xda\xa5\x0b\xce\xd3o\x9e}\xfb\xfc\xc5w\xdf\x1f\xff\xe3\x87\x97?\x9e\xbcz\xfd\xdf?\xbdy\xfb\xee\xe7\x7f\xfe\xcf/\xff\xf2\xcf\xe6\x0b\xb6<\xbf\x08~\xfb\xb0Z\x87\xd1\xe6\xf78I\xb3\x8f\x97W\xd7\xff\x1e\x0cG;\xbb{\xfb\x0f\x1f=\xee>8<\x0dOc\xe7\x96\xec; x\xbe\xc4\x86\xddY\xfbm\xc1\xd3A\xa3b\x9cc\xc7\xc8\xa2\x1e\n)\xf2_H\x1eCa\x9d\x8e\xa8\xe3\"b\xcfr3vi\xbcN1\x00a\x7f\xb7Qk\xc4\xe0\x00\x06\xad4?(\x13\xdf7\xbe\xb6\xe2\xc1\x18\xfe\x0b\x1e\xa1\xf0\xb9\x08\xf6\x9f|q\x06E\xe9\xc5\xf44>\x0d\x0fgB\x86a_\xf4\xa0v[|\x8c\xffc|\x95\xd8\xb7{n\xd1\x07)\xff\xee\xc1\x13\xe0\xab\x9c=\x01\xd6\xedz\xc0\xe0\xbf\xd0\n\x8c\xe4%\xa4\xce\x99\x8b\xfc\x10pt\x04\xc3}\xd8\x82\xd1\xde\x9e\xd7\x03\xbd\xf8Q\xb9t\xb4\xb7\x07[\x90p\xa4\x9f`\x12\x90\x83\x03\xd8\x87\x1b\xf0\x158\x04\x12\x1c\x98\xe9r\x15[4\x00\x19\x087\xc3\x81\xdd\x87}T\xd1|\xd2\x90`\x0c\xc3GJ\xd0Slk`lk$J\xf1S\xe1q\xc8\x97F\xaf\xb3\xab\xbe\x8c1\xe9\xc62\x8e\xd6\xea\xc1\x9d#O\x80\xe8\x1e\x1f\xe7u w[\xa9\x08\x06\xf6\xe0,\x0e!\xd0\xf6Z\x93\xb6\x00\x1d\x93s\x8b\x15\xa1X\x80/k\xc45~\x0d\xae\xb1@\xe7N :\xf1\xe4\xfb\xd3\x00\xb7\x8fo\xfa\xfe\x0eR|Z\xe9\xc8T\xba_*\xdc\xdf\x81-@s\x1c>#7\xe0\x10\xfb\xc8\x83.\xa4SfW\xa8\x16\x01t\x87\xf4\x87\x9fyD0\x86Q\x0e\xae\x85v\x06\xa6vv+\x85\x07\x07P\xeeq\x7f\x17\x1b\x1e\xe6\xc0\\h\xb9:\xc0\x83\x83J\xc3\xfb\xbb\xc5\xf6z\x10\x17\x01O\xfd\xfad\x02\xc2\xca\xceVd\x7f\xc58\x93U\x02\xc1*,\xbc%\x89\x16\xd5x2X\x9c9>\xf1\xca\xb7\x19\xf2\x97\x985\x12\x83[o\x03C\x80\xca\xfc\xb8\x91>z\xae\\\x83\xf9\xe1\x0b\x9f\x90 \xd8\xea6\x16\x88|\xa1\xf3)\x9b\xe5I\xc0\x94\xa8\x96\x16|\xe6\x08f\x15E\xb2q\xb3=\x87\x08\x84\x13\x84\x10\xd7\x1b\xf0\x04\xa2Id\xd3j\x08\nY\xdfo\xecZ\xfe\xdd\xc9P\x07i\x9f\xe6>x5a\x81\x90\xa8;1k^\x16\x11\xce\xa2U\xd2\x0e\x058\xc5SyG\xfa\xa6*\x9c\xf8\x93<\x8cZ\x1c\xfa;\x9e\xe1\x8d\x1f\xc4\xc9\xdf\xeb\x10\x0b\x7f\xdd\x9a\x83\x9a\x89\x19=\x8dc\xff\xda\xf5\xa5\xdb\xa3R\xf4\xf0\x13\xec\xdf\xed\x04\xfbx\x82\xcd'7h}r\x03\xf4\xe1G\x93!\x0d\xe1~`\xd7 \xff\xba\xec\xd6ok%\x9b\xb2\x19Ge\xd1t\xc0o\x19\xfcw6\xfb\xd3\xa1\xde\xb2\x8f&\x9a\xfac9\xd4\x99\xf0\x06\xb6\xeccT\xd8\xc7\xcc\xb8\x8f\x99m\x1f\xf9ne\xb8[Ae\x89{\x10\x89\xb5\x0b\xc4\xda\x05\xb8vV\"&\xfa\xeb\x0fp\xf1\xd6\xbe\xe51N\x98Uun\xf6)\xfcrg\xb8\xf6\x82\x0dB\xb0\xc4\xfe\xd2\xee\xb1\xb0'L\x10\x15\xa2\x0d\xa7lV{\\>/\xc4\xdb\xf0\xfc\xdf\xcd\x8f\xf2\xb7\xe4A\x16.\xd82\x08\xd9\xe2\x13%/5\xcbp\xfbE\xf5*\x19\xe6o\xcb\xcf}\x8c\x82\x85\x8c(V\xd7\xbb\x89\x93\xab\x13\xfa\xfd\xcd\xbc\xa1\x7fK\x1e\xc4\xec\x9c]}\x11U\xca-\xe4f\x01F\xa6\xc1zm.'\xe5Mg\xa6\xb19\nxp\xfa\xc0\x9d\x9e\x07\xeb\xd9}\xef\xeb\x07R\xb3a\xae\x1e\x1bb\x0c\x80\x18\x94\xf3@\x8a\xdd\x07V%\x02i:\xa4\x05o8\x1d\"\x1b&\xd5\x07G\x9c%mq]\xf3\x9e\xd0\x9aw\xcar\x03\xa0\xb8`\x0b\x947Si\xe5K\xdf\xc1\x7f\xce\x8a\xcbS\xa2-:\xa9\xdf\xca\xab[0\"\xea\x81e\xc5P\x93\x95kFY\xaf\xcc\xc7|\"\x92PT\x1au\xd0\xd6\x14\xe6\xb6\xf8\xa4vC\xf8Zu!\xed'Q\x16\xcf\x19ty\x81ua\xd3\xfe\xf9*:\xf3WB\xe7\xd7=\x04\xe7\x9cB\xf5\xe5\xa9\xe7\xf3Wkz\x15\x9c\x87Q\xcc\x9e\xf9\x89\xfe.\xe0\xef\xd8\x97BfO\xb4J\xea~\xd1\xa21]\x06\xe1\"\xbaT@A?\xfb,\xd9\xc4\xc1\xda/\x19\x06\x06\x8d\x98\xd1\xa8N\xf8-y \x07\xff\x17\xe3\xc6\xaa\xbaF\xfe)\x18p\x11\x06\xf8\xe6{\x16\x11!\xc8\xf48}4\x0e\xe3g\xa1\x9eM\x8f\xfd\xf0\x9c\x8dkyo[TQq8^\xc7\xd1y\xec\xaf\xe9P\x84\x18\xfb\x8e\xef\x98\x0c-v\x16-\xae\xb58<\xce\xf3+\x0e\xf9I\x10\x85oR?ek\x16\xa6\x8eVu:\x98\xa9&\\\xe7i\x1cG\x97/\xc4\n\xe7_\x96?`\xea\x0d}\x8bN\xcf\xb7\xfd\xca\xc0\xe6\xebZ\xb1\xba5hD\xd4\x9f\x84\x8eEt\x9c\xe6\xcd\x0f\xb4\x8d\x0f\xeb6\xbe~\xd3\xff\xb0`s\x9b\xc3\x0b\xdej\n\n\x88\x81\x95\xdb0\x14\xbfu(\xe0\xbbc\x84\x82\xbc\xaa\x82\x02^\xd7\n\x04\xc5\xfae \xe0\xc0v\xeb\xaf\x0cf\x10/\xfc`\xc5\x16\x90F\xca\x16B!\x0c\xbb6\xc5\xd8\xc1\xc6\x8f\xfdur\x0b\xab\xd0H\x06T\x0d\xfd\xb5 >\xc5\x0di\xec\x0cW\x1c7\xba\x07\xce7\xabh\xfe\xa1t\xde\xec_\xe1\xf2Mp\x0d\xe4\x02\xbaQ\x0fB\x199x\x8a\x96\x0b\xfc>\x9e\x0egt\x01\x0b\x95\x8b^\xdd\x91\x08\x02#F\xe5\x9f\xd2g\xf5&4w\xbe\xa1\xe5\x00\xfe\xd4;Z\xdd\xba\xcat\xed\xcb\xda8X<\x00\xf6F&\x8b1\xf7\xd1N\xa98\xa3\xda\xe5b\xbfN\xdaW\xac\x9a4\xcb\x15J\x08\x0f\x0e\xe1q\xb1h \x870,i\xb3Vp\x08;\xa3\x12(\xf0\xb2\x9db\xd9\x05/\xdb-\x96-x\xd9^\xb1\xec#/{X,\xbb\xe6e\x8f\x8ae\xe7\xbc\xac4\xbe5\x1c\xc2ni,\xefyY\xa9\xdf3^V\xea\xf7\x12\x0ea\xaf\xd4\xc7\x15\x1c\xc2~\xa9\xbd7\xbc\xac4\xb7\xe7\xbc\xac\xd4\xc7S\xbe|%7\xc4W\xbc\xac\xf4\xedo\xbcl\xbfX\xf6\x01\x93\x15\x96*\x1eca\xa9\x97\x1f\xb1\xb04\x95\xb7ph\x80\xf8\xc1\x18\x9c\xd3\xd3\x81\xe1\x1ez\x88o|\xc3\x9bG\xf8\xe6\xcc\xf0\xe61\xbeI\x0do\x86\xd4Qhz5\xc4W\x1fM\xafF\xf8jiz\xb5\x83\xaf\xca\xd4\x1c\xff\x1b\xd1\xd0\xcbBh\xfe\xb7\xb3;\x86{\xa7\xa7\xce=\xc3\xd8\xa9\xaf\xd3Scg\xd4\xdb\x89\xe9\xdd>M\xed\xbdi\xa5F;\xd4\xeaK\xf3Kj\xf5uI\xc6P\xac\xfa\x8c_\xd6\xce\xb5\xd3\x03\xe7\x17\xfe\xbfk\x96\xe0\xb3\xf8\xe7\xf9\x1b\xfe\x0f\xd2\xbc\xce+\xfa\xff \xff?>\xd2S\x84\x8f\xf4\xffWX{\xb9\xc4\x8a\xe2\x9f\x17/\x9c\x99)\x90\xc6\xeb*\x92\xcc\xc5\xb5%\x0d4Y\x9e\x1c\xd6z\x93\xf5(X\xc6ho\xcf#B\xe8\xca\xa1h\xbd\xa3b[\xca\x02\x19\xab\xef\xef\xed\xed\xc8\x0f2\xf1\xc1\xae\xe1\x033\xc9\xde\xa1FvG\x8fw\x1f\xef?\x1c=\xde\xf3\xbcb\xf8\xdby\xb4`\xb0\x89\x82Bz\\\x8av\xb8\xf6\xafe\xda\x85\xf3\x98\xf9)\x8b)\xf3\xc2\xe0\xea\x85\xf83\xd1\x0d8\xd0wb\xa0\x8f\x8a;[\xf8%o\xbc\xd3SG\xc4p\xcc\x836\x0e\xf0\xfbm\xc5'{\xd0\xd5\x987S\xb0\x92\x9f\xaa\x9b\xa5\x85\xac\xc6\x9d\xc9crG2\"\xb6\x0c0\xfd\xa3\x9f^\xf4\xd7\xfe\x95\x8b\xf9\xc1E\xf1\xcd\x0d\x8c<\x19\xda\xfbC\xb09\x0e?\xfa\xab`Ami\xbf\xf58\xdc\xcbUt\xf9\x92}d+\xa4`\x83\xe4$\xe2kz\xee\xa6\xf9\x1bO\xfa\x1fie\xb2\x97\xf4z%\xe2m\x17\xaeU\x1bE]\xcd\xffkH\xdfU\xe0\xdcrw\xfe\xff\xfca\x919\x87\"\xfb \x19iP\xc6\xd5\xb8\xa40`J'C\xce\xff\xd1\x13\x8a\x88:\xa4\x8c\xe4\xf14\x10Z]q\x16\xd84C\x0f\xeeN\x87\xc8\x99,7]\x1d\x91A/\xff\xcc\xc0\xd5r\xd0\xc8\x94\xff\xb6\xd7\x03\x97\x12\xb8\x95B\x90\xf7eV!\xde\x0foOdt\x98\xf7u7\xcb\x1e\xf8\xd4\x99\x8f\nk\xfd\xd5\xd4\xe7\xe3\x0b\xa7\xd9\x0c\x0e\xcb\x91oA\x13p\x17\xe1\xd9\xd5@\x8c\x03\x0e\xb6\x98H\xf3H\x05;Q\x9c\xfe\xc0\xae)\xd5\x8c\xfaQ\x8c\xde\x1e\xb2\x7f\x06\x0b\x19=]\xfd\xba\xb9\x81G2\xf6y\x18\xfd\xc4\x96\xd4\x86x\xd4[\x08\xa3g\xd1z\xe3\xa7?\xf2\xe3Lu\xb4\x02\xbd\xe6<\xe2\xd0\x8d\xeeV\x97b)\xb5\x02\xbd\xe6\x1d\xe2\xc5\xcb\\Du\x9f<\xbf*\x86\x98\xc7\x9cWa\x1e\xa6\xbe\x98I\x9a\x97,2\xfe\x85\x9f2a\xa7@\xa5Y\xc2\x16\xdf\xeao\n\xc1\xfdL8\xe2\xc4x\x98\x10\xe8\xc5i\n\xe0\xb0\x14:\x96y\"w1)\xe6\xb6\x87\x04\xd7|l\x89f\xaa\xf4\x04\"8\x80\xe4\x89\x879\x1a\xd0j]\xa6\xe6\x17n|\x98\xf8?\xf2\xd0\xda\x87\xfcCD\n\x0b\xd1A\x82\xa9\xdd\nox\x97\x14\xc65Bc!z\x0eu!\xc4\xa9\xe0\x03C\x01\xd7\xddC\x08<>\xc4\xeea\xd9\x9dL\x80\xb0_\xbbD/\xebbo\x9bc\xebJty\x1f4\xce\xce\xd4\xf6\xb7U\x14-\x19\x0e\\\xb1\x15\x87>z\x9c\xd76\xf4okC;\xa3b`\xaa\xe1h\x1f\x99\xf7\xfda9\xf2\xd5\xe8\xf1\x1e\xff\xc5)\x94\xdcm\x82\x93$\xe2\xd7\xcd\x0d\xec=\xdc\xd9\xdd-~\xc7/\xe3\x1d\xfe\x8b\x92Q\xa8\xaa\xbc|\xbf\xd4\xf5p\xb8;\x1c\x0ek'\xf2\xc2:\x11\x9cb\xa9\x1fl\x99?\xbe\xcf\x1f\x9f\xe6\x8f\xaf\xf2\xc7\x0f\xf9\xe3\x8f\xf9\xe3e\xfe\xb8\xa8\x1d\xd6;\xeb\xb0\x1e\xfcz\x1a\xde\x07\x19\xc8D\xdfn\xf9\xc4\x0f\xd27\xd5X#\xbfs2\xa7X\xf4\x0b\xe7U\x8aE\xff\xe4\xb4M\xb1\xe8g\xc0\x88\xd2\xd5A\xfeP\x1fg\x9d\x8f#\xd2\xed\x9b:\x86\xe8'sK\xf9\nO:\x85\xfa\xa8\xbe}Kx\xa0R\xce)\xd5\x7f\x8b\xec\xa3\x85\x04%\xa5\x9d\xc4x<\x9do]\xba\x8c|,;\xcb\x1f\xdf\xe4\x8f\x97\xf9\xe3\xfb\xfc\xf1i\xfe\xf8*\x7f\xfc\x90?\xfe\x98?.\xf2\xc7\xeb\xfcq\x9d?n\xf2\xc7\xe3\xfc\xf1*\x7f<\xcf\x1f/\xf2\xc7\x8f\xf9\xe3\xf3\xfc\xf1713{V\x17C\x82\x07\x839\x8a\x97\xbf\xed\x10\x0bb\xf2\x06\x0e[\xff\x13a\x05c\xdd\xef\xd7\x9a\xcdS\xff\xe3m'@\x91\xdd\x9a'\x02\xe2\xe6\x8a\xa7\xa3\x861\x83\xca\xffB\xb3\x9c\xa3\xfa'\xe2'=\x81.\xe7\xf50\x9b=_\x07Q\x01&\xfcqL\xc9\xeb\xa0\x0b\xffp\xe7\xc4L\xa2\xd2\xa2\xb63{\x98K\xc8A1\xb2V\xfa\x83\x83g\xe65A\xfb\xcf\x8d\xd0~\x0f3\x934+\xf7\xe4\x9fb\xa4s\xaa\\p\xcaV\x1aI\xc8LK\x84\xd0\x111h\xfb\x80\x0e;\x9c]\xdb\xdf\x19\"\x11P\x8dO\x1a!WL\xdf\xec\xef\x8c\x06\x90\x07+\xdd\xd9\xdd\xe1\xcc6\n\xa6^\xbb\xc3\xc1\x08\xbd\x96\x19lS\xeb\x949f[|\xd6%\x1e\x8e/\x1b\xa7\xdd\xc6$\xf3z+\xcce\xbb\x87\xd0AJ\xe6\xdf\xfc\xe2\x99@:\x8df0\xa6[\xee\xb5\xd9\x1bM\xff\x93\xba\xd4\xba=\xf3(}\xa8\xb9!\x11\xfc\xc1\xbee\x05\x99n\xb0\xdeDI\x12\x9c\xad\x84\xb7\xfb\x18\x02!\xaa$\x0b\x10\x8a=\xe64\x11v\x7f\xb8\xf5\xfc\xfc\xd7\xf64Rp(\xe95)\x00\xc4\x90k\x06-@\\D&\x85XRF\xf9E\xc8\xcf\x1b%\xd46\x7f7\"|\xa4\xde\xf1Q8]\x07\xb7K\x1e\xcam\xbalNC\xa7v\x86\xdf[\x19a\xdb\x909l\xe4(u{\x88\xb9/\xa9\xf4\x85a,\x8a\xf8\x99\xb2\xf1/E6\xfe{G\x98\xa2_\xd0\xfe1\xf8\xf39\xdb\xa4 \xaa\xde\xf0\x06^QN0\\\x81{M7MqZ\xd3\xd5\x8cff\xbfy\xecW\x8ad\x87cc\x95\xda\x90\xd3\x06\x83,#\x9b\xdf\xa9\x97\x8f\xfeOA\xc6G\x87\xbe\xcc\xb3\x17\xf4\x07r\xc8a\x8f\x8er\xd8\x83\xce\x10C\xdf\xa8\x9f\x03Cj\xe0\x04\x14\x94P\x13\xe5$\xad\n\xf9\xe9,\xed\x01E\x85+r\xb9\xe5\x14\xa6\xbc\xf9y\x0fV=\xb4\xff\xa8\xbaIq\x00Ea\x87z\x85\xbe=\xf2MU\\\x86\x02;W\x93P\n\x8dX\xae$Q\xbbM\"@-al~\x13\x18\xda\xd1\x8a\x1aZ\xd4?.\xa0:\xa5\xee\\g Z\x12\xf8pF\xa9n([y\x9d\x05\"\x14D\xacDB,\n\xfa\xb6\xec \xf1`C\x0fE\xf6\x9c\xd5\x10\x1b\xceW&\xe2@\xedb\x1c$\xa1\xd6\x12\x91%\xc2)'p\x16\xd3h6\xeb \x1cCf\x80>\xe5`\xa7\xff\x08\xee\xf1t\xb58A\x02\xf8\xf1l\xf0\xa7\xdc\x9b\x823\x1e2\xeb\xbb\xac\xb3\x14[\x875\x8b\xc9\xcc'\"r\xd3\x84\x13\xaa\xe2\x11\x1c\xe5\xf1MS-\x1d{?\xf1\x97\xec\xdb\x92\xb5B\x8d\xe5\x1eM1\xee\xb3\xab\x94\x85\x0b\xb7z\x8e\xc8Fs\x0cYq\xb7\xf0\xc6/\x8d\xeeN>?\x02\x90\xc85V\xba\xd6\xf0\x83\xed\xbc\x7f\xcf\x92\x1f\xa3E\xb6\xaa\xc6.\xfd\xe8\xaf\xb2\xa2w\x1f:\x8a\xf5\xcfY\xfa,\n\x97\xc1\xf97\xd7\xefb\x0c\x86\xdb_D\x97\xe1*\xf2\x17T\x0e\x87\"\x1eB>\x80\xdc\xe9h4\x18j;h\xf8\xd4\xae\xf1*\xdb\x16\x18\x15\xbd\xa2\x92;\xe0C]\x86\xfd%K\xe7\x17^\xc5E+\x9f\x93qJmvU\xd51\x92-\xca\x97\xb8\x9fl\xd8\xfc)\xd6L\xccH2\xf7\xe7\x0dJ\xcb\xe1\xa6^?\xbd`\xe8\x07\x17\xe9\xe9F\xe5\x9f:E\x91y\x14\x80\x9aSM\xbe\x8c\xce\x88\xa8.\xed'\xa9\x9ff \x1c\x1d\xc2\xee\x00\xd3[\x04\xfdl\xb3\xf0S\xf62\xf2\x17Ax\xfe\x06\xdf\xbb\xce\x12\x1d\x17i@\x9c\xb3\xb8e\xb5w\xf1\xcaux\xc1<\n\x93h\xc5\xfa\xa8\x14se\xffo\xd9U\xaa\x91'Y\xbc\xe2@\x86\x17\x07R\x89\xcc\xe5[)\xdcQ\x7f\xf1\xd7+\xea\xc1s\xc3~\xca\xae\xca!\xb4\xa1\xaaF\xfb[\x9d\x1f\x1d\xf2\xcfY\xda\x12\xd2R^\xf78t\xcbw\x15L\x80\xc1\x18\xa6l\xf6\xf7\xc2\x12\xa5s\xaf\x08w~\xfa\xf7\x0c^\x84H\x91\xcb\x1b<\xef\x0b&\x10\x83)9\x93\xd4\xc7\x96\x83\x17\x16[F5\x9a;\xdc\x7fT\xea1\x11#\xd9-\xe2!j\x93\x02I\x92\x0b\x06\x07\xbcL\xbe\xf0\xdc\xa0\x07I\xff\xdd\xebo\x9f\xbe}\xfe\xfe\xd9\xab\x93\x17\xc7\xdf\xbd\xe9\xb5\xdc>\x0c\x0e\x8d\x80\xeccp\xd1\x7f\xbc\xf1\\\xd6\xdf\xf8\xd7\xfc\xa8\xeb(\xde3\xf7\xfa\xf6\xd5w\xdf\xbdl\xdb\xab\xbc9U\x07f\xb5/\x02UEt\xa2\x86\x9c\xf0\x97=\xe8\xc4\xc5\xd1\x05\xc2\xf3t\xe6}\xc5\xf7\xf9\xc1\x83\xff\x03\x14J\xe2G\n\xdb\xf4\xee\xa7\x97\x87\xc9\xa5\x7f~\xce\xe2\xed,\xd8\xe6xg\xe1\xaf\xa2\x90m\xa3N$\xed\xff\x96\xf4\xd7\xfe\xe6\xff\x07\x00\x00\xff\xffPK\x07\x08v\xf2\x8aA\x86\xba\x01\x00\xc5\x87\x08\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00 \x00swagger-ui.cssUT\x05\x00\x01\x80Cm8\xec\xfd{s\xdb8\xb27\x8e\xff\xff\xbc\n=\xbb\x95\x9a\x99\x1dS!EQ\x17\xabf\xeb\xc8\xb1\x93q6r\xc6\xcem\x92\xad\xad)\x8a\x84$\xda\xe0\xe5\x90\xd4\xcdz\xf6\xbd\xff\x8aw\\\x1a $;s\xf6\xf7\xad\xb3\xd9dl\xe2\xd3\x8dFw\x03h4\x00\xb2\x9bl\xed\xe5\x12\xc5\xda\xda;\xfc\x9fN\xe7\xe5\xdf\xfeo'\x08c\xdf\xc6\xde#\xea:I\xd2\xd9\x0c\xbbzW\xef\xfc\xbf\xce\xec\xfac\xe7\x9d\xe7\xa0 A\x9d\xff\xd7Yz\xe9j=\xef:\xa1\xff2@N\x88\xed\xe4%M\xf7\xb7\x97\x8b0H\xb5\x85\xed{x\x7f\x9e\xd8A\xa2%(\xf6\x16\x13'\xc4a|\xfeWs\xde7,\xe3\xdfD\xfd\x9dU\xea\xe3\x03\xf6\x02\xa4\xad\x90\xb7\\\xa5\xe7F\xd7\xb0&\x9a\x9fh)\xda\xa5Z\xe2=\"\xcdv\xef\xd7Izn\xe8\xfa\x8b\x89\xb6E\xf3\x07/\x85K)\xce\xf3\xd0\xdd\x1f|;^z\xc1\xb9N\x95\xd8q\xea9\x18\x9dQ\xcf\x12\xcf\xa5\x9f,\xc20E1\xf5h\x85l\x97y\x14\xd8\x1b\xea\xf7\x049\xa9\x17\x06\x07\xd7K\"l\xef\xcf\xe78t\x1e\xe8\x16\x1b\x87\\K\x99\xf0\xe7=\xe4OJ\x19\xbb\x83!\xf2;\xb4\xa4\x0bo\xe9\xd8Q\xc6\xf0\x8cy\xbc\x8eii}\xdb\x93UZPT\xea0\x90\xdf\xe9\xeb\xd1\x8e\x96+>T\xca\x9d\x87\xbbL\xe4\xdd2\x1f:\x16a\xec\xf3\xca\xfbg\xba\x8f\xd0/1JP\xfa\xaf3\xbe Y\xcf}\x8f)\x01*\xcbf\xb5\x92\xa2(\xfdW=\xb6\xdaQ\x84\xec\xd8\x0e\x1ct^\x14\x01\xd5\x974\xe7\xe7\x9a\x1f>j\x8b\xd0Y'\x9a\x17\x04\xcc\xd4C\x8a\xaa\x04-\x85o\xc1\x16\x95\xf3 \xde\xeb&\x91\xed\xba\xd9l\xa0K\xda\xd0\xb0\x89\xbd`)n@+\xae\x92^\x02,E\xa7\x11\x87p\x9df\xbevnD\xbbr\xec\xed\\\xe4\xc0\x8fh\x972\xb3$\xc2n\x82\xd2C\xd5\xb0\xaei!\xbf\xd3\x1d\xe6\xff\x0e\xb8a\x01\xa3%\n\\h\xda\xac\xe7\x14j\xd6$\x9e\x16\x83a5\xacW\xdd>\xb5\xe7\x18M|{\xa7m=7]\x15\x1d\xa5\xd6\xf2d\xbb\xf2R\xa4\xe5\x83\xf4y\x11y1Sl\xb8\x8cQ\x92\x80\x83\x8f\xd2(Xw\xe1\xbaw\xd9\xeb4\x04\xac\xeb\xac\x90\xf30\x0fwP\x1f\x89m\xd7\x0b\xffu\x92Vd\x0e\x15\xac\xfd9\x8a3\xef-\x19\xe7^\xa9%\x91\x17h@\x17\x14\x10\x85\xeb\x94&:\x94C\x90\xa0\xa1 \xb2cg\x05v\xdfLY\xb9\xc7LJ\x0f\xd3\xc2\xc5\"A\xe9\xb9\xd6cB+\x8aU#K\xf1@s2nX\xdc\x06\x11]\x13\\@\xd2q#[C\xbf\xf00\xd2\xd6\x11\x0em\xb7R\x82pt\xcaG\xed\xcaO\xe9X\x00\xa5\xb6\x87\x13:\nE\xc1Z\x12\x85&k\xdf\xb7\xe3}\x8d\xc0^\x92j^\xca\xf4*\xc7\x0e66\xec\xc4\xb4V\x8b \xed_\xcc$\xe4G\xd8N\x115\x93Rd]\x17\xcd\xd7\xcb\xce\xdf\xa8q! \xb1\xe7v\x96!v\x01\xac\x96\xf7;\x90\xe2\xaf\x8b\xc5\x02\xa2\x98c\xdby\x80)\xd8\xf8\xa7\xa4X\xc6\x9eK\x04Ndx\xdbY\xc7\xf8G\xd7N\xeds\xcf\xb7\x97\xe8e\x14,'Y\xf7\x1d\xf4\xcf\xbc\xcf\x17\xef\xef\xb6\xfa?\xde,\xc3\xe9t:\xbd\xf9\xf0iu\xf5i\x99\xfd\x98\xffs\xfdj\xfau:\x9d^^]\x0e\x07\xef\xb2\x07o~\xbf{\xfd\xe5\xd7\xbb\x8f\xf3\xde7\xdd\xed\xbd\xde\x7f\xbb\xbd\xb8\xf8\xf6f\xec}\xfbp\xf1v\xfe\xe5u\xf0\xed\xf3[\xfc\xf5\xcb\x9d\xe58\x18\xff\x96\x11\xecW\xd1\xe7\xd7+\xfd\xcb\x951{\xef\xdfl\xe6\x1f\xacU\x81\xb7\xfa\xf3\xdf\xa7\xc5\xff.\xb7/\xd1\xaf\x17\xab\xaf\xbd\x14\xbb\xaf.\xbco_\xdch~\xaf{\xc3\xe1\xfa\xe5\xb5w\x11}\xbb\xd4\xbd\xcf\x8f\x9fofW\xc6\xf6\xb6\xf79\xb4?\xad\x06\x8e\xff\xf9#z\xb0>}5\xa3\xf8\xeb#~\xb8\xbe\x1f\xfd|}\xb9\xeb\xbf\x0fV\xa9\xf3\xc6\xc0\xee\x9b\xab%zc$\xf3`6@\x97\xba\xf7\xf5\xcb\xdd\xe6\xab\xffi\x90\xfd>\xff\xf2Y\xff\xfaa\xe4]\xff\xba\x1c\xa07\xc6\xd6}\x93\x8c\xaf\x1f^?\xcc{o\xf1\xf5\xeb\xd5\xcd\xa7W\x17\x97s\xf3-\xbe\xbe\xfc\xb4\xbe\xf1\x8c\xfb\xd9\xc7\xab\xdd\xf5\xa5c\xbd\xbb\xbf2\xde_\xce\xf67\x1f\xb6\xcb\xd9\xfdtw\xf3a\xb4}\xffa\xb4\x9b\xbd\xd2\xb7\xb3\x8f\xe1nv\x19\xeeg\xaf\xa6\xcb\xeb\xea\xef}\x7f\xf9\xdb\xafo\x1f\xbe\xddG\x1f\xee\xae\xbe\xd6\xf28\xfe\x9d\xff\xdb\x87\xb7\xa1\xfb\xeb\xdd\xf6\xbd7\xda\xb8\xa6k\xbe\x0b\x9c\xc7w\xfex\xffm?\xda\xbd\xff\xf8`\xbd{\x9c\xee\xdf=^\xef\xdf\xfd\xfe\xf6\xe1\x9bg<\xa2/\x96\xfe\xf5\xf7e:\x0ff\xf7\x04\xdf\xabo\xbf\xdf\xdc;>\xde\xbao\xf0f\xee]\xec\xbf\xbd\xf9:\xf8\xfa\xe5\xed\xc6\xfd\xfdv|\xed]7:xcl?~\xd2\xc7\xd7\xfeJw\x7f\x9d\x0e\xde\xed\xc7kg_\xdb\xe2~\xde\xd37\xe8\xcd\xeb\xed\xbb\xc7\xab\xf5\xec\xd58\x9d\xe7\xfaY\xa5\xf37\xd6\xe3\xfb\xe0F\xff\xe4\x7f\xa6d\x9e\x07\xb3u\xa9\xd3\xf5\xd7\xde8}g\xaeV\xce\xab\xd1\xee\xdd\xfdt\xe3\x18w\x96\xf3\xe6\xd3\xe6\x93\xff\xf9qn~\xde\x7f\xed}\xfe\xf0\xed\xcb\xd7\xfbk\xef\xa2?\xff\xb2[;\x8fQf{EY\n9\x9c+\xe3\xe6\xfd\xc3\xdd\xe6\xab\xf99\xfd\xf6\xc5\xd2?|\xba\x1d_g\xb6~e=\xd8_n\x07\xb3\x8fw\x97\xef?~\xed\xdf\xe8\x9fz7\xfa\xe7\xd7\xb3\x8f\xaf_\xdf\xdc/{\xb3\xc7o\x97\xb7\xf7\x0f\xdb\x9b\x87\xdb\xfe\xec~\xb9\x9d]]\x13\xfc\xf0\xda1\xefVs\xff\x06\x13\xfc\"\x9a\xdf\xad\x1a\xbf\xcb\xe8\xd2\xf1?\xaf\xdc7\xe3\xfd\xe77\xe3\xcd\xfcR\xf7n\x0b\xfd,?\xbdYm\xdc7\xe3G\xfb\xcdx{}usy}y\xbd\x9d}\xfc\xb4\xfc\xc7\x95\xb1\xfa\xda\xc3\xeb\xbc\xec\xd5\x83\xf7\x9b7\x1d\x95v\x1a\xdc\xbd\xf9\xbc\xb7\x7f\xff\x86\xbf]}\xdb\xcf{\xfa\xd21\xef2\x1d\x0e\xec/\xd6\xa3\xfb\xe6\xf5\xfak\xef\xf3\xdb\xbbK\xdd\xcb\xf0\xef|\x1c}\xbb\x0c\xcd\x9b{g\x7f\xfbpk\xde\xdc\x7f5o\x1f?\xedf\x9f>\xf5n\xef\xdf\xbe\xba\xd5?\xedo.\xa7\xfd\xd9\xc7\xe9vv\x7fe\xce>\\\xd7\xfc\xbe\xbd\x19\xdf\xbb_\x0c<\x0f\xee\x08~w4\xbf\xc7V~\x9bL\xf6w&\xe0\x93\x99\xaf\xbe\x1a\xe7~\xf9\xe9\xe1\xeeM\x81+\xfa]\xde\x0f?\xf6\x97\xbf]\x8e\xfb\xce\x9b\xd7\xf7v\xef\xb3~\xfd\xe6\xf3:\xeb\xef\x8ew\xfd\xf2\xb7\xe4\xe2\xc3\xcfof\xd9\x08q\xff\xe1\xd3\xdd\xc5\xe7_\xef\xed\xaf\x9b\xc7\x97/\x1fG\x97\xef\x92\xcb\xfe\xd2y\xf3\xbb\xf7\xf5j\xfa\xe6\xe2\xfa\x1fo.\x02\xf4\xf2\xe5\xe2u\xb4\x9d.\xb7\xd3\x8b\xf1hj\xbf\xeeE\xf7\xf8\xd3mF~\xf1\xf6\xee\x93u\x15?\xbc].\x97\xbf\xfc\xf2S'F\x11\xb2\xd3\x8e\xde\x11\x8e\xa4\x9a1x\xc6\xc1\xf4\"\x1f\xe6n\x8b\xc1t\xba\x18\xbd\x1c\xaf\xfew0\xfd\xdf\xc1\xf4?u0}\x7f\xf9u\x7fw\xbf\xba\xba\xbb\xcc\x06\xd3\xaf\xfb\xd6\xc1\xafe0m\xf8\xdd\xaa\xf1\xfb\x0f\x1aLo?\xb6\x0e~G\x0d\xa6\xb7\xed\x83\xf3\xf7\x19L7\xaf>\xe8\xc6u6\x18\xcd\xea\xc1\xd4\xbf\xeb\xbf\xb4~\xbex\xfd\xdb\xc5b:{\xed\xbf\x9c],w\xa3\xbb\xe9\x9b/\xaf\x02c:\xf5?,\xcd\xfe\xed\xe0\xe1\xe2\xf2\x1f\xb37\xb3\xcbW\xdb\xebWhv\x8d\xfc\xd7/\xad[{{\xe5E\xd3/\xdbO\xab\xed\xd5\xfd\xecr3\x9f~\xc1_\x1e6\x9f/\xb6\xeb\xd1\xe6\xf6zz1\xbd\xda^\xbc\x8aV\xa3O\x03G\xcf\xc7\xa5+\xfc\xfa\xe3\xc3\x87\xf5\xad\xff\xea\x95\xd2\x00<\xd2\xf2x\x97\x1c\x85\xb3`\x99\x1d~\xef#T\x8f\xbf/\xc7\xf7/\xfb\xb7\xd3\xafw\xbf\xaf\xa2o\xcb\xe9\xf4\xc3\xa7\x87\xff.\x03\xd9\xe6\x7f\xbf\xbdL\xa6\x17\xaf\xaf\xdc/71\xba\xcdF\xe6\xdbj\xe0|\xd9\xbf\x9d\xed\xec_\xeft\xe72\xdc\xbc\xebY\x8f\xef\xfcb\x1c{\x97\x8f\xb5\xe3\xfe\xd7\xdf\xa7\x9b\xd9\x87\xfe\xf6\xddv:\xfa\xcd\\m\xbf~\xb9\x89\xbf\xfd~\xbb\xfc\xea\x7f\x0e\xec/\xfd\xf1\xf5\xfa\xe7\xe1f\x7f\xbd\xb4\xbf\xdc\x8e\xaf\xb1c|\xfcxq\xe3\\\xdd`\xfb\x0d\xbeF\xc1[\xfc\xc9\x8c\xde\x7f~s3\xb0{3\xeb\xdb\xab\xeb\x97\xb9\x8f^f\xfd\xf7\"\xfd\xf6\xfb\xdd\xaa\x19#\x96\xe3\xeb\xb2\xee\xf7\xbe\xf5\xf8\xde\xcf\xc7\xe0M\xd6\xe7\xf31\xf9\xd7\xbb\xf8\xb7\x0fo\xab\xb9\xe2\xeb\xc7\xcf\xd3\xe5mo\xbc\xff\xf6aj\xbc\xbb\xff\x9a~}\xbc\xda\xcd>L\xcd\xf7\x1f\xfa\xbb\x9b\x8f\xcb\xc7\xd9\xfd\xa7\xa4\xec'\x9b\xd9\xe5\xc3f\xf6q\x9a\xce.\xaf\x06\xb3\x8f\xd3\xc1\xec\x9e\x18c_]g\xe3~\xed_\x8d<\x99/\xea^\xad\x1b\xd35\xdd\xbde\xce\xf6\xd6\xc6\xf1\x9d\xcd\xec\xe3\x83\xf5\xfe\xc3h;\xf3F\xfb\x99gd\xf4\xa9cf}\xf1u\xff\xdd\x17\xeb\xf1z\xdf\xf0\xbd{\xf3\xf9\xf1\xab\xf96r~\xbd\x8b\xe6\xbd\xfe2\x1b\xbf\xdf\xfb\xaf\xbd\xb9\xf9Y\xff\xed\xc351Nf\xe3\x00Q\xa7\xcc\x1e\xfb\xff\xc0\xb1\xf9\xf7\xe9\xe0\xd6|\x8b\xbf\xfe~\xb7q\xf0\xddf\xde\xdb\x12\xf3\xe2E87\xef6No\xb5q^]\\\xde\xee\xa7\xfb\xd9\xe5\x95q\xfdju\xf3\xf5\xcbM4\x0f\xb2\xb2eT\xf0\xb9\xb8\xf9\xf81z;\x0fn\xf4\xaf_\xac\xfbo\x9f\xf0\xd5o\x1f\xdef\xfc\xd7\xf6\x17\xfc\xf0\xfe\xe1z7\xbb\xbf\xd6\xdf\x7ft\x1eo\xee\xddW\xb3\xc7\xab\xdd\xdd\xc7o\xaff\x0fo/\xef>^\xeb\xb3\xcb\xe5nv9\xdd\xcf>:;\x82\xdf\xd5\xbcwc\xcc\xbf|^\xbbW\x0d\xbfoo(~z+\xbf|\xee\xac\xe7\x13\xec\xf8\xb8\xf7\xed\xcb\xdd\x1b\xc7\x1f\xa7\xd7\xbf\x16\xba|\xef\x8b\xe7\x85\xdb\xfb\xab\xfd\xec\xfe\xd6\xbay\xbc\xea\xdd\xe8\xd7\x8f\xf9\xbc\xf0p\xbd\xbf}\xb8y=\xbb\xbf\xdd\xbe\xbf\xbc\xda\xce.\xafw7\x8fW^\xc3O\xde\xfa7\x97\xa3\xf0\x1f\x97\xe3_\x7f{\xfc\xf4\xb2\x8d\xa6\xfd\xef\xe2\xe5v:\xbd{5\x9d^O\xa7\xcb\xcb\xe9\x87\xeb\xe9tuu1\xdd]]\xbc\x1c\xddN\xbfd\xe3\xe6\xed\x14\xf8\xdf\xd7\x8b\xe9\xed\x15\xf0\xfc\xfa\xeajzu1\x9d\xce.\x98\x82\x8b\xe9\xe5\xd5\xab\xa9~u7\x9d^]^\xf0<\xef\xae?\xbe\xbe\xf8\xf4\xe5\xea\xc3\xf5\xe6\xa5=\x9dn/\xa7\xb7\xd3WW\xb7\xb3\xbb\xe9\xe5h\x1a\xbe\x0f>~6n?^\x0e\xdf\xbeMV\xbf\x99\x9b\x0f3\xf3\xb7\x97/\xbf)\xcd/\xc6@m\x829*\xbe\xcf\xe6\xd7W\xb7\x0f_\x96\xbd\xe9\xff\xc6\xf7\xff\x7f\x1d\xdf\xab\xce\x01t\x1c\x9e\x8d\xad\x8asV\xcfH\xc9y\xab\x8c!U\xe7\xad\xc7\xcf\xbf\xe2\xed\xb7\x0f\xe3\x0f\xdf~\xbf\xd9\xb8\xbf\xbf\xbd\xcf|\xe9\x9b7{\xb6\xf8Y%\xae\xbfy\xfcj\xce\x1e\xde^\x15I\x97\x99!\x1f\xbf\xdb\xd7\x1d\x0d\xbf\xaf\xad\xfc\x9e-\xbeoOn\x1c\x15\xdf\xdf]\xb6\xf2\xfbN\xf1=\x1a\xbc5\x1f\xb2\x11\xe2\x91M\x96\xe8\x9f.\x93\xd9vv\xff\xe1.\xfc\xfa\x9b\xf5\xe6\xbf\xfb\x1f~\xbb\x99\xdf\xdd\x7f\x9e]\xdd\x1a\x8bWw\x97\xcb\x9f\xbd\xe0\xe5\xe0\xe7\xb7\xc6\xf4\xed\xa7]\xb2\x9c^\xbd\x99NM\xe3b\xfav\xf6A\x7f\xf3\xb5\x18\xcf?|\xfa\xfc\xfe\xee\x1f\xd6\xab\xaf\xd7\xd7\x92\x04J\xb3\x15C\x1f\x8e\xa1\x7f\x03\x8e\xcf\xccCwO=\xe0N\"\xb8\xf4A\x04\xd7\xa3\xcf\xcd\xb8\x98\xfe\x95\xdeZ\xae6\xe6\xe8\x87\xfc\x01\x9dE\x18\xfb\xf4F\xacA\xff\xda\xa3\x7f5\xe9_\xfb\xf4\xaf\x16\xfd\xeb\x80\xfe\x95?\x0b\xb4J}\xba\x15\xf9Nu\xb1\x89\x83|\xdb\xc3\xff\x12\x95\x96\xdbT\xa2\xe2\xc8N\x92m\x18\xbbB@\x8a\xc4\xbcS\xb4K\x85\x85\xeb\x98!,\xb64\xe9G\x1e\xbd\xc7c{\xf4.UH7\x9a>'\x101\xe7\x94\xca\xf3Q\xd4\xb3|\xd7\x93~BKPmK\xd2\x0fW\xf4\xaf\xb4-\xd6\xf8\x94\x0dH\xba7\xd8I\x84\x9cT\xcb\xf7\xd8\x0e\xe2\xf3%b\"M3\x06\xbbq\xb5\x9b\\\x9d0\xb2\x06\xdd\x9e\xf5BF5\xde\x19\x03\x96\xca\x18\x0e\xbb\xc3\xa1\x94\xac\xbf3Y\xaa\xa1\xbc\"s\xd7\xe7\xea1\xcd\xaeiJ\xa9\x06<\xd5`\xd0\x1d\xb4\xc8\xc6\xb7\xc8\xd2\xa5$\xa3\x9d\xc5U\xd3\xeb\xca\x1bd\xedF\\5\x03y5C\xbe\x9a\xa1\xd1\xed\xf7Z\xea\x19r\xf5\xf4\xe5\xf5\x18;\x83#a\xcf,2$\xc5\xc9\xb5C\xedq\xf6< \xf1:E\x934\x8c\xce\xf5I\\zd\xc9M\x9f`\xb4\xc8~'\xce\x0eT\xe7k\xb2\x9f\x1f5/p\xd1.\xfb\xe5\xdf\xff\xe5#\xd7\xb3;\x89\x13#\x14t\xec\xc0\xed\xfc\xe8{Ay\xea\xc0\xd4\x91\xff\xd3A,W\x90<\xa17d\xd4'u\x08\x80P\xadO\x00\x84\xed\xdd\x02\xaaM\xa9g\x00\x84*\x9d\x03\xaa\xaf\xbd\x7f@\x95)t\x11\xa8\xb2\xf6^\x02\xe9Q\xa5\xa3@\xb5\xb5\xf7\x15\x88J\xa9\xbb\xe4\x84\xcf\xdfc\x14\xbaL\xf9\xb0>\xbd3h\xe9G\xfeS\xba\x91\x7fb/\xe2\xe8\x14;\x11G\xa7\xd0\x87\xf8\xba\xd4\xba\x10G\xa7\xd4\x83\xf8\xda\x14:\x10_\x95J\xff\xe1\xabR\xe8>\xbc\x06\x95z\x0f_\x97B\xe7\xe1\x89\xd4\xfa\x8e\xff\xe7w\x9d\xb6^\x82\x9f\xd2K\xf0\x89\xbd\x84\xa3S\xec%\x1c\x9dB/\xe1\xebR\xeb%\x1c\x9dR/\xe1kS\xe8%|U*\xbd\x84\xafJ\xa1\x97\xf0\x1aT\xea%|]\n\xbd\x84'R\xeb%\xf8\xbb\xf4\x12\xb2^\xcf_\x1e\xe8c\xa0\xb4XN\xb8A1y\xce>?W\x9d?\xfd\xbf\x9e\x1f\x85qj\x07)K\x12\xa4\xb6\x17\x00D\xf9s\x82\xac}\xa6;\xf0\xc2d\xd3\xee)\xf2\xc0t\xacH\n2)\xcc\xbe\x85\xa0\xfeirBd\xc7\x89)\x94\x08\x9f&\x11D\xc6IDQ\xce\x97\x9a\x83\x82\x94v\x9d\"\x19t\x1e\x84\xe5O\x13\xa2\xac\xf6sn\x90\x98/\xb54\x8c\x8e\xe6\x93\x86\x11\xc7'\xef4Gs\xe2;\xc5\xbc\xea\xc7G\xf3*\xc88nY\xe7=\x9a\xd7\xf1\x8b\xab\xda*L_P\xaaN`\x98SX ms\n3\x89yNa'\xb1\xd0)\xec\xda\x82\x12\xd5\x11\xa51\xdd\xf1N'\xb2\xdc\xf1\x9c\xc4\x86;\x9e\x97\xccn\xc7s\x93\x99\xedxnmV\x93\x1a\x08\x1f]\x9d\xc8@\xc7s\x12\x1b\xe8x^2\x03\x1d\xcfMf\xa0\xe3\xb91QL\xb7<\xfe\xce\x1f\x83\x07a\x1aqL\x1389O\x94\xc2\xe4zMt\xfc\x18\\\xf1\x08\x92\x13\x84\x05\xa9\x14\xe4%\xe9\xda|[uD\xaa\x98\xfb\xa7\xb4\x03 Ri\x86\xaf\xdc\n\x89\xc0\xf8\x14\x81\x01\"\x15\x811)0\xed\xfb6}\xcf-g9)\x1f\x95\xd18s\xbb\xa7;O+\x9alt\x00\xe8\xb2\xc7\"\xda\xfa^]1\x1e\x00\xd4E\x81\x88~N\xdf_\x86\x18\x94%\"\x0e\xb8\xe2\x90wz\x80>\x7f.\xa2\x0e\x80{\x81\x94\xba\x8e\xef\x8bs;\x9f\xd2\x8f7\x03Av\x8a%\x08\xf2S\x8dA\xb08\xdd\x1e\x04\x93\xd3L\xc2\xa9\x0f\xb2\x8a\x82Y\x14\x86\x9b\xb9\x9d\xcd\xe3'\x98\xca\x7f\x92\xa5\xfc'\x1b\xca\x7f\x06;\xf9O4\x93\xffT+\xc1\x06\xc1'\x19\x04?\xc9 \xf8\xc9\x06\xc1\xcf`\x90'\x0ee\xac\xe6@\x83\xd04Zq\xd5\xaf\xa2\x13\xbc\xe3 \xc3\x05\xc8\x8eA\xb0a\x18\x1c\xd8\xb5\xe3\x07m\x19\xdb{\x06k\x9a&\x87\xf5=\x17\x82Z\x96\xc5A\x01\xd8p8\xe4`\x89\x877\xcd\x85\xef\x128\x1e\x8f9 .\x8c\x0d\xc1m\xdb\xe6%\x0d\xc3\x00\x92\xc1q\x1c\x01k\x00\x8c\x10\x82u\x9b\xdf\xd2d\xc0\x8b~\xf6\x87\xc3\x83P\xf6&g\x85\xd3\xc6:\x0d]%\xd8\xfeQ?\xd3_\x9ce\xb1\xf8Yw\xfc\x93\x80p\xd4B8\x12\x11\x0e[\x08\x87\"\xc2A\x0b\xe1@Dh\xb5\x10Z\"\xc2~\x0ba_Dh\xb6\x10\x9a\"\xc2^\x0baODh\xb4\x10\x1a\"B\xdd\x92\x13\xeaB\xed\xe8\xbd6\xd2\x9e\x98\xd6h%6 \xea|\x8c\xe1\x9c6^\xces\xda3\x1dt\xd8\x82\x88uX\x92\x08p\xd6\x82\x88uV\x92\x08p\xd4\x82\x88uT\x92\x08p\xd2\x82\x88uR\x92H\xa8\x08\xd6AI\"\xc09\x0b\"\xd69I\"\xc01\x0b\"\xd61I\"\xc0)\x0b\"\xd6)I\"\xc0!\x0b\"\xd6!I\"\xc8\x19K*\xd6\x9f(2\xb1+\xf1\x8eH\x11\x82N\x98O`1r\xd9\xc1{\xa8\xf7u~\x9c\xe5\x81\x8bE\xdf0\x07\x82Y\x01\x82\x0f{\x16?\x89\x84\xb1\x1d,\xf9\x81~`\x02\xf3\xf32\xc4<\xd7\xf9\x10@\xee\x11\xc6\xe1\x96\xc6\xf2\xaf\x0e\xa8\xa5\x85\xe0\x7f]\xcc\x17\x86\xcdO\xa8\xd1:\x8e0+\xb0\x85z\x8e\xcdO\xe6\x05w\x90\xc2\xee\x0f\xccE\x0f6J\xe4\x05l\x04\xe2Z\xba>\xe2\xad\xb2\nS\x08\x9d\x99f\xce\xcf\xa9 r\xa4\x0b\xa7v\x10o\x9b.\x1f\x8e\x94\xc1\x10B\x01\x837\xcc\xe1\xd0\xe2\x9b B\xc7\xf6x\xc8\x0b]E\x19<\xc1\x18\xa1\xb9\xc3\xeb$\xb07l@\xa2\xeb\xc6\xbc\xcf\xb3\xce\xa5\x9e\xe35k\x1b]\xef\xf7\xc7|\x08\x03 Mk\x88\\\x91W\x01\xf8\xf1\xc0q\x80 &\xc7\xa3\x04$q\\\x04\x91l\xedd\x85\\\x88`1X,\x16\xbc\xf4%\x01\xa4H4Z\xb8\x0b\xde{K\n\xb8s,\x16\x0e\x9a\x8bH\xa0\xde\xef.\\\xbe\x15d:\x91\"\x10f\x88\xe6\x9aV\xbe\xea\x84&\x80\xde\x7f\xd2\x9d\xc7\xf5\xd0\x1d\xdb\xae\xb7N\xce\xd9\xa1\"6\x18@\xd7\xe8Y1b\xd3\xadq\x8f\x85\x81(\x93EA\xa0>\x032\x00\x8cf\xe8\xac\xe4@R9\xd6\"\x0fc\x067\x1e\x8f\xc7\xc0\xea\xaf\xdew+\xc0y\x92<[iUz!\xd7\x90\xc5:P\xa41\xad\xd8U,\xe0UV\x1bbU\x96\xb5q+\xf7\x16[\xe4\x82*\xe2y\x15\xdb\x81\xa2\x96\xc8\x05kO\xb6\x1cX\xe7\"\xd3Q\"\xff\xe21\"\x17\x03\x90\xb0\x97\x01@\xd0\xd1x\x9c\xc8\xd7\x00\xa4\xc8\xddx\xa8\xdc\xe3\x98\x8c\xdfS\x9c\x8eO\xdd=\xd9\xefT\xa4Sw=\x86\xdb1\xde\xa7\xe0~*\xb9\xbeX'\x12oB\x97d!B\x8f\xe4\x80\x02\x87\xe4p\xb0?\xb20\xa1;r@\xa17\xb2\xc8\x16g|\xb6\x01\x90\xcbN>\xdd\x15\xdbe;\xc2\x13\xfd\xef\xe3\x88\x02\x9fc'!\xc0\xe7X\x88\xd0\xe78\xa0\xc0\xe78\x1c\xecs,L\xe8s\x1cP\xe8s\xc7M\xb9,\xbc6oc \xa2\xa0<\x9e\x06\xfb\x1c\x9b\x80}\xba\xcf\xe1\xe7\xf49|\xb2\xcf\xd1\xfc4\xadx d\xc5\xaeH\xf5\x02/\xe5-\x82\xf8,\xe4d\xa0\xf93\x0eZ\xdeF&\x91\xc0&f\xb6\x84\x08\x03D\xe3\xf2w\xd4\xb5\x0f\xd1\x07\xb8!\xdcn\x8f\xb4-\xd8\x92a\xb5\xc8(\x1cDd\x17\x1e\x08\x9b\x86\xc7\x81\xd6\xe1`\xa0\x818\x14l#&\xee\x15\x9a\x89\xdb\xbe\x17Z\x8a\x0f\xf5\x85\xc6b\xf7\xe2\xebm\xc0v\x83\xa9\x0cl[\"\x1a\x15\x1a\xd1W\xb4!\x8b\x13\x98\x90\x85\xc1\x16\xf4U\x0c\xe8+\xd9\xcfW3\x9f\xafj=68\x16\x1b\xcf?\xc1v\x023\xe1V3aE3\xb18\x81\x99X\x18l&\xacb&\xacd&\xacf&\xacj&6\x9e\x14\x9b \xc3f\xa2\x80\xc9\xcav\xc3\xadf\xd0\xd7\xba\xf3\x87\xe7zG\xef\xf4\xa3]\xa7\x17\xed:\xf4\xa6\xcbD \x05\xd6\xd4\x13\xd54R\xaa F\x815\x99PM\xbd\x92\xbe\xbd]r$Xc_Vc&\xb9\xaeP\x1f\x84\x03k\xb3\xa0\xda\xfa\xa5\xc4m\xb5\xc9p\n\x83\xf0\x01t\xa2lT\xff\xd3\xfcHR\xd9\xf3\xbb\x92\xa0\xb2\xef\xebM-\x95\xb6\x99\xf8x\x87\x12T\xf8,>\xa5\xe0T\n3{\xedi\xfe\x9f\xe8h\xc2\xba\xbe\x83\x9f\x81u}g7\x93\xd6\xd9f\xf4\x13\xbc\x0c\xac\xefOp2\x99?\xe1?\xd1\x9f\x84u}\x07\x7f\x02\xeb\xfa\xce\xfe$\xad\xb3\xcd\xbe'\xf8\x13X\xdf\xf3\xf8\x13Ua\x14\xa3\xfa\x0b\x1e\xda.\xff\xb4E\xfdq.m_~\x08\xa8\xf9\\W\xe2\xc4!\xa6?%\xd2\xcdb@=\xff\xe6\x11\x13\xb0\x15Q\x9f~\x80S\x89E\xa4\xa7W\x9fRb\x8a\xf3\xf0N?\x14\xe9I\xbe>#\xaf\x8f\x0fa\x8b*\x8d\xb2J \xc4-j5\xaaZyD^\xb1QT\xcc\x97fu\xf7\xf2\xba\xf9\xc8\xb8\xa8\xbbW\xd6\x0dD\xceE\xdd\xbd\xaan\x1e\x91\xd7\xdd+\xea\xe6K\xb3\xba\xcb\x86k\xa2\x96\xd7M\x07\x10e\xfdM\xe3\x01L.A\xd5|\xa0<\x97\xa1P\x80&\xd2@\xad\x02\x00Q\xc9P+\x01\xc0\x142\x94j\x00\xca\xab{\xd4\x9a\xb6\xf00>HoS+\xcc\xd0\x07\xde\x99\xb3\x98\x01\xf0\xe7\xc2'\xb3B\xc8-Ko\xcf\x8a\xa5\x0e_\xa4 \x9f\xcf\x1d\xbb\xaa[\xe4\x99u\xf5B\xe7o$\x10\xfb?!\x84\xc0\xc9+9D^Z\xcb!\xec\x08\x8d\x1c\xe2\xbe@\xc8!r\xf8J\x10\x89\xcf75\xc9\xdc\x9e\xa8K\xec\xf9u\xb3\x84\xce_\xcb#\xf6\x7fB\x1eI\x17 \xe5\x11\xf6\x82F\x9e\xb6\x8eP;\xad\xb0/(t\x06\x85p\xb5\xe8!\xbe\xa4\x83\xf8\xd2\xfe\xe1\xb7t\x0f_\xda;|y\xe7\xf0\xdb\xfa\x86\xdf\xde5\xfc\xb6\x9e\xe1\xcb;\x86\xdf\xd6/\xfc\xf6n\xe1\xb7\xf6\n\xbf\xb5S\xf8*}\xc2W\xe8\x12~[\x8f\xf0[;\x84\xaf\xd2\x1f|\x85\xee\xe0\xab\xf6\x06\xffI\x9dA\xe8\xf7X\xe2\xf7X\xea\xf7\xb8\xc5\xef\xb1\xd4\xef\xb1\xdc\xefq\x9b\xdf\xe3v\xbf\xc7m~\x8f\xe5~\x8f\xdb\xfc\x1e\xb7\xfb=n\xf5{\xdc\xea\xf7X\xc5\xef\xb1\x82\xdf\xe36\xbf\xc7\xad~\x8fU\xfc\x1e+\xf8=V\xf5\xfb\xb6\x80\x88&v\x16\xe7\xf6\x82}5j\xf6t\x8e\x16a\x8c\x0e\xe5\xc7{\xcf\xff\xd2\xf9\x0b\xfd\xe5A\x98\xcd\xc1\xc1\xc8\x8e\xcf\xe7a\xbab\x01\x87\xbf=\x86\x99o1\xcfqI\x92I\xc7\x14U\xdc\xf2\x960esqMAYt\xd2N\xb9\x93O\xa3b\x91\x9aRP\xaa\xa6\x18\x12\xac)U\xd8 V\x9d\x8e\x9dl\xa8\x93\x08\xecK\xe5\xf5e\xe2\xfa\xea\xd2\xc2\x82\xc9\x8c[\x17\xc2\x82a\x99`\x98\x12\x8c*u\x03\xd9\xe7\xfc<\xe6S\x81L\xf1\\\xf2A\xc2\xae\xeb\xcd\xdb?4\xd8u\xbd\x94E\x01\xfd\xc5m@`\xa9C\x17k\x0eb\x17\xddn\xaa\xc5\xe1\x96\x81\xc5\xe1\x16Bi\xcb8\\G<\xb6x\xceQ8!^\xfb\x01+A\xfeP\x80\x05+ \x8b8:m\xe1\xed\x90{(\x90\xd8\xde\x87\xeb\xf4<\x7fD\xbc\xfeJ\xa1\x7f\x1c\x18\xdbg=Lf~\xb2\x1c\xf6\x00\x12\x01;\x01\xcfC\xe0\x07\x00\x1046\x89\x83\xbd\x81C\x08\x1d\x82GJ}\x02\x84K\xdd\x02\x10\xa5\xdd3DDR\xe7\xc8\xd73R\xffPp\x10\x85\x01\xd4\xcd\x06:\xa9\xd3\xf8m>\xe3\xb7\xb9\x0c\xcbA\xe41\x1c\x0ev\x18\xbf\xcd_|Uwa\x81ro\x01\xd0rg\xe1\xe4P\xf0\x15\x98F\xee*\xfe\x93<\x05v\n,w\n\xdc\xe6\x14\xb8\xcd)X\x0e\"\xa7\xe0p\xb0S\xe06\xa7\xc0\xaaN\xc1\x02\xe5N\x01\xa0\xe5N\xc1\xc9\xa1\xe0\x140\x8d\xdc)p\x9bSPt\x0b\x8cvu%D\xee\xbd\x0e{5?\xd12\x10\xf9,\xfb\x9dfS\x9a\x08\xe4V\x99\x99aJ\x90\x90E\xc4c^R\xcd^\xa7!\xb5E\x90==7&\x95\x94\xe7F\xc7\xe8\xe4\xd9|\xfa\xb7\xc6\xeb\xf5\xfc\xe7\xea\x85\xa9@\x15\xf9\xe1S\xae\n\xbd\xa9\"\x7f\xe7A\xfd\x13\xc0\xa1\x8c$H\x1ea\xece\xeb\x89\xea\x0b\xe3\x13\xb2\xcc\xf5\xe2\xe2\x95\xff\xe5\x17\xcb\xeb\x9a\x88\x92\x82\xe5\x04|\nH\x90\xc5H@\xf5\xab0\xf6\x1e\xc3 =A\x808\xdc\xb2\xb5s\xfd#/\xdf\xc6vt\xa8\x19d\xbf\x9dg\xffL\xe8_A\xbd\x03\xa4\xc5\xc3 \xfb@P\xaf\x16\xa3\x0d\x8a\x13\x04\xd4_\x15M\xe0\xc7B+6,\x8f\xb6fU\xa3\xd0\x9c\xb4L\xa2R\xd8\xbc2\xb9Z\xcd,\x91\x8c`\x0d\xd8\x1b\x96\xc9K\x91\x9fhIj\xc7)%N\xf1\x19\xfd\xfcyS\x15\xf90\xff9\xff\xbcy\x92\x8f)\x05\x0f\x889\n\\\x805\n\\\x96q\xf6\x88c\x8b\x02\x17bZ\xbe\xe8\x93\xe7[\x14\xb0\xac\xcb\xa7$\xf7\xe2\x11\xc4{n'(\x1b\xc8\x00\xeeU\x11\xcb\xbf~N\xd6P=\x845\x1e\xa3\xd4Y\x81:\xcfKx\xad\x17\x8f\xc9\n\xcag4\xff\x04\xe1Ee\xd0\x8aE\x06\x07\xac\x97A\x85\xc6\xcb\xf9\xe4\xb6\x03\xb84\xa6jxp\x96\xca9T\x86\x02\x98PF\xc9\xf9@6\xc9\xb94&\x01\xf80\xca\xcf9\xc1\xba/uS\xaa\x1e\xd4\x0e\xa9\xe5\x9c\x13\xa8\xe4\xfbu\x92z\x8b=\xd0q\"\xdby`\xfb\x0d\xf1\xac\"\xac\xb2T\"\xedW8\xb6\xf3\xe4\xac\xa8\xbeS?\x01YsF\xa9Q|\x07\xca9\xb1\xfd\x87|\xc8\xd6\x00\x99\xab\xc2\xccQ\xbaE(\xe0+(\x01L\x0d\xd5S\xb6\x8a$\xb2\x1dT1\x83k\xb2\xf3\xd74\x1eh~\xae\x97\xa4\xb17_\xa7H\xc0\xb2\xa0\xa29\x96\x08\xb6\xf7\xe4A\x0da\xc3\xc29\xda,X1\xa3\xbaP\xc3\xaa\xe9Ar{Ul\xd8~\xd4p\xa2\xba\x91\xcc4\x15\xab\xda4<\xaf\xca\x0c43\x89\x11*\x9e\xac\x11\x1a\x96\x84% \xaer;0=\x95\xb4\x04\xd9Qk\x96P_-\x0e\xdf\xea\xccl\xebz\x81\x8d\x8bh\x9c\x88A\xb5\x1c|\xaeO\xca\xffB\x9c\x0c \xa7\x1e\xcb\xc9(9\x19\x10\xa7\x9e\x84\x93\xc9r\xea\x95\x9cz\x10'S\xc2\xa9\xcfr2KN&\xc4\xa9/\xe1d\xb1\x9c\xfa%\xa7>\xc4\xc9\x92p\x1a\xb0\x9c\xac\x92\x93\x05q\x1aH8\x0dYN\x83\x92\xd3\x00\xe24\x94p\x1a\xb1\x9c\x86%\xa7!\xc4i$\xe14f9\x8dJN#\x88\x13\xb6\x93T\xe6\x9cz\xf6?\x96\xe38\xfb\xdf\x84\xf8\x19\x085\x97Y\xd4\xa7\xcb\xd6C\xe5\xbbm7\xe8\\\x9f\xd4$\xe0\xca*\xe7e\xc8\x96o\x0d/\x83\xe0e\x00\xbc\x92U\xec\x05\x0f\x99d\x15i\x80\x966)F\x81\x00\x05)\x89\x0d\x80\xd8\xa0\x88\x0d\x85\\\xdb\x81\xe7O\xe4\xfd\x88\xc6\x9e\xbe\xa4\x86\x18>\xf7\xaaZc\x0e\x0c/\xbe\xcb\xc2\x1a\xac\xe5\xf8\xb55\xcbFmA\xf6\x9c\xcbk\x81\x04\xadK\xafgZa\xe7\xd5W<\x8e^d\xf3\xd4\xa7\xad\xb3a)\x9e\xba\xd4>\xcd\xb8\x7f\xcaj\xfbT\xab\x7f\xbf\x057+\xd1\xf3\xae\xb9a\xee\xcf\xb2\xec\x86Y?\xe3\xca\x1b\xae\xe0\xb9\x17\xdf\"\xfd?\xd7\xfa\x9b\xeabOY\x82\x8b\x18\x1d\xbb\n\x17\xf19a!.bu\xdaZ\\\xac\xa9\x13\x96\xe3\xacY\x9f\x7fE\x0e\xd6\xf0|\x8br\x90\xfd3\xaf\xcb\xc1:\xbe\xd3\xd2\x9c\xb2\xee3\xad\xce)\x9eO^\xa0\x0b\xb8\x9d\xb6F\x170;u\x99.`\xf7\xc4\x95\xba\x80\xeb\xd3\x17\xebB\xc3\x1c\xbb^\xe7\xe7\xeb',\xd9\xe5\xcc\x8e\\\xb5\xcb\x99\x1d\xb9p\x973;r\xed.gv\xe4\xf2]\xce\xec\xc8\x15\xbc\x9c\xd9\x91\x8bx9\xb3#\xd7\xf1rf\xc7/\xe5[\xfc\xf6\x89\xaby\x96\xfb\xe2i\x0bz\x90\xddS\xd6\xf4T\xf7?aY\x0f\xd3\xb3+{\x85\xa5\xbd\xc21\x9a\x9c\xa7\xff\xcc\xcb}\x9e\xdf\xb3\xaf\xf6\xfd?c\xb1\x0fTr\xc2Z\xdf?a5\xf8\xacK}P\x80\xd65\xdfs\xad\xf4\xfd\xa7,\xf4Y\xe2\x13\xd7\xf9\x90\x0cO^\xe6\x9fb\xd7?g\x95\x7f\x9a\xc1\xbf\xe3\"\xdf\xff\x9ek|\x88\xf9\xf3,\xf1!\xce\xcf\xb9\xc2\x87\xf8?\xfb\x02\x1f\xd6\xfd\xb3\xad\xef\xfdgZ\xde\xc3|\x8e^\xdd\xc3lNY\xdc\xc3\x9cN\\\xdb\x8b\xb4t\xca\xd2\xde\xff\xde+{\xa0\x82g\\\xd8\x03\xdc\x9f{]\x0fT\xf1\xbd\x96\xf5\xfe\xf3\xaf\xea\xfd\xe7\\\xd4\x83\xccN\\\xd3\x83\xbcN^\xd2\x83\xdc\x9e\xba\xa2\x07\x99>\xc3\x82^`\x93\xa3\xd7\xf3\xec\xcc\xfc\x94\xe5\xbc\x8c\xd7\xb1\xaby\x19\xafc\x17\xf32^\xc7\xae\xe5e\xbc\x8e]\xca\xcbx\x1d\xbb\x92\x97\xf1:v!/\xe3u\xec:^\xc6\xeb\x84e\xbc\xd4]\x9f\xba\x8a\x97\xae\xae\x8e^\xc4K\x17\x84'\xac\xe1\xfd\xa7-\xe1!\xf2\xe3V\xf0\xa2\xc5:~\xe6\xc5:\xcf\xef\xd9\x17\xeb\xf8\xcfX\xac\x03\x95\x9c\xb0X\xc7',\xea\x9eu\xb1\x0e\n\xd0\xbav{\xae\xc5:~\xcab\x9d%>q\xb1\x0e\xc9\xf0\xe4\xc5\xfa)v\xfds\x16\xeb\xa7\x19\xfc;.\xd6\xf1\xf7\\\xacC\xcc\x9fg\xb1\x0eq~\xce\xc5:\xc4\xff\xd9\x17\xeb\xb0\xee\x9fm\xb1\x8e\x9fi\xb1\x0e\xf39z\xb1\x0e\xb39e\xb1\x0es:q\xb1.\xd2\xd2)\x8bu\xfc\xbd\x17\xeb@\x05\xcf\xb8X\x07\xb8?\xf7b\x1d\xa8\xe2{-\xd6\xf1\xf3/\xd6\xf1s.\xd6Af'.\xd6A^'/\xd6AnO]\xac\x83L\x9fa\xb1.\xb0\xc9\xd1\x8buvf~\xcab]\xc6\xeb\xd8\xc5\xba\x8c\xd7\xb1\x8bu\x19\xafc\x17\xeb2^\xc7.\xd6e\xbc\x8e]\xac\xcbx\x1d\xbbX\x97\xf1:v\xb1.\xe3u\xc2b]\xea\xaeO]\xacKWWG/\xd6\xa5\x0b\xc2\x13\x16\xeb\xf8i\x8bu\x88\x9c[\xac3\xf4\x87\x05\x0e\xed4\x7fG\xce\xe4\x0fz-\xcc@\xe3\x12\x9a\xbf1\xa7\x05\x1b\x94\xd8\x93\xde\x82\xb4\xc8\xdf\x82\xa4.W\x83V\x12\xad\x81+\xbcYH\xfd\xfc\x81\xe6\x1f#\xb2\x7f\x94\xc4\xbe\xba\xc0\xb0l\xc7\x98\xb9\x06\xab\xc9\x86)\xd9\xa8\xd2\xc4\x0e\x12-A\xb1\xb78,\xc2 \xd5\x16\xb6\xef\xe1\xfd\xb9fG\x11FZ\xb2OR\xe4\x9f]`/x\x98\xd9\xce\x87\xfc\xd7\xd7a\x90\x9e\xd9\x1b\x14xq'@\xbb\xea\xe7\xb3\x15\xc2\x1b\x94-r\x9b\x9f:\x01Z\xa3\xb3\xf5|\x1d\xa4\xeb\xb38\x9c\x87ix\x16d\xff$h\x19\xa2\xce\xda;\xb3c\xcf\xc6g\x8d\x14\x8ct\x9c`K\x14\xc6K\xcf>\x83\xc0\xb9t\x9a\xa0E\xc2*J*\x9e\x80\xc7:\xa1\x8b\xa8\xf7\xa0e\x0f(\xa2Wa\x90\x84\xd8N\xce\xfc0\xb0\x9d0\xfbO\x98G\x13,\xa3u\xec\xa1\x98!\xcd\x9fun2\x95\x96\x00\x11}\xad`\x8a\x03\xa3\xf6\xc6\x1e\xa2\xb6\x17\x86\xa3x\x00v\x15R\xa7+\x84\xed\x84&/\x9e\x9dI\xccT\x16\xa9Z5\xf5|D\xd7\x91?\x81\xa0\xf3\xd0\x0d\x03\x8f\xc2^\xe4\x8f:\xb3\x8f\x10\xde\xb1\xb1\x97\xa4!m\x85\xe2\x99\x80bi\xc7\xb6\x1f\x06.-|\xf9\x10\x14\xc9N\x1eP\xbc\xf10\xa6\xfd\x84x\x0e\x91\x95\x8d(>\xa1\xe5\xa56\xf6\x98\x0f_/\x12\xad\xc8\xc3\x91\xc0\xe2\x89\xc2`I\x8f=\xf9;\xafT\xebc\xb0e\x95\nu*\x0c\xd0^6\x88\xaa\xca\xe1\x1f-\x06X#V\xaf\x11\xd25\x8d%M\xb2-r\xc8}\xee\x93\xefT1\xf7E\xf8\xc5\xd6\xa0\x00\x06\x0f\xe8Q\x80\x1e\x0f0)\x00\xf7y\xfa\xc5\xb6/\x17q\xb1\xb5(\x80\xc5\x03\x06\x14`\xc0\x03\x86m\xcd\x1cQ\x80\x11\x0f\x18S\x80\xb1~\xfc\x9b\xba\x19\x8f\x15Z\x84E@Fa1\x90]X\x0cd\x1a\x16\x03Y\xa7U\xe2E\xf1\xb9\xb36\x1b\xb1\x18\xc8L\nm\x1f\xb1\x18\xc8X,&\xb3\x97\x82\xc1\x14F\x05\xba\xbf\x8b\x8d\xe8\xb7\xb5\xc3` \xa0 \xfdv\x0b\xfa\xed\x06l\x11v\x91\x7f\xed\xac\xd5|~\xbb\xf5Z\x1b=b \xa0\xed\xfc#M'\xb6R\xdb\xe0\xc7\x00@+\xe1v+\xe1v+\xe1v+\xb5\x08\xbb\xc8?v\xd6j%\xdcn\xa5\xd6F\x8f\x18\x08h%\xcc[\x89\xc2xA\xb4N\xb5\x18%\xa8\xb9\xdfnG\x11\xb2c;p\x8a/qN4?|d\x1f2&Z\xa7i\x18\x14l\xce\xcfs\xfc\"t\xd6\x89\xe6\x05\x01\xfb\x16`\xa2F\x1eZ~\x86\xed\\\x9fD\xb6\xebz\xc1\x92]\x18\xaf\x8cC\xb9\xd1\xca\xbf>y\xd5\xab\xca\xf8\xd7\x19\xaf\xcc\xaa\xac\xcf\x97\xf5\xab\xb2\x11_f\xd5\xf5\x0d\xf8B\xadW\x17\xf7\xac\x17l\xa1\xa5W\x85\x16\xfb\xa9\xe5\x956\xac)\x87<\xa5\xa1\xd7\xa4\xfcg\x9a\xf3\xcd\xe6\x1cBl;\xf3\xb0\x0d-\xddf\xc5\x15\x93\xf2\x01\xc5\xa4\x84@1-#\x0b\xc8D\xdb@R\xb2\xc0U\xf1\xce\xb9\x12\x90\xfd\xcc\x96{\xc1\n\xc5^ZA\xca_\x15\xe6\x89\x03\xe39\xd9t#q\x1e\xa2\x18\xf2\x1f\xa2\x18r!\xa2\x18\xf2\"\xb2n\xd8\x91\xc8\xea!_\"\xcaAw\"\xcaa\x8f\"E\x10;U\x86j\xf7+JX\xd0\xb5(qA\xef\xa2\x04\x86\x1d\x8c\x16Y\xecc\xbc\xd0\xb0\x9b\x11\xfc$\x9eF\xa0*gS\xf06\x85\xa8d\x95E\x132\x0f\xf4\xa5\x0e\xe8K\xfd\xcf\x97\xba\x9f\xdf\xe6}\xbe\xdc\xf9|\xb9\xef\xf9-\xae\xe7\xabx\x9e\xaf\xe2x~\x9b\xdf\xf9mn\xe7\xb7z\x9d\xaf\xe6t\xac\xbc\x02\x9f\xf3U\\\xce?\xce\xe3`\xe7\xc2R\xe7\xc2R\xe7\xc2R\xe7\xc2R\xe7\xc2m\xce\x85\xe5\xce\x85\xe5\xce\x85[\x9c\x0b\xab8\x17Vq.\xdc\xe6\\\xb8\xcd\xb9p\xabsa5\xe7b\xe5\x158\x17Vq.\xcc9\x17\x05Lc\xdby@\xee\x01\xa34E\xb1\x96D\xb6\x93E^]\x83\xfb>E\x01\xd4\xd2\x8c\x19\x0b\xd7\xba\xba%\"\xf0\xd1\xd2\xe6\xd8\xf72x\xfb\xb8z\x009\xe6\xdf/:F\\\x80\xa2Mb\xa8\x92\\h\x05\xa9\x15f\x83\xba\xaac[\xc2\x11\xb46\x84\xafB\xa1\x1d\x12\x91\xf1\xb1\"s\x04\xad\"\xf3U\x14\"S\x14x\xa5%!\xf6\xdcC\xbe\x8f^u\x16\x0e\x93z)F4\xa6\xdb\xb38\x98\x13F{\x06e)\x98\xfa\x00\x8a\x94;O\xbbT\x1cL$\x18\x0f\xb4\x9e\xc9\x0fk\x89}%\x81}EyY\\\x9b\xb82\xc9\xb0\x92dXQ2\x16g\xb1^\xe5\x05\x0f\x87\x14\xedR\xcdEN\x18\xdb\xe5 Vv\xd1\x9b\xc1\xce\xb8'\xe7\xb6\x93z\x1b\x04\x14\xe4\xcb\\\xe0\xf9*\xdc\xb0k\xe4\xfc\xb9\x80\xff\xc6K\xbc\x145o\x1cMc;H\xbc\xea\\g\x18w\xba\x86\x95t\x90\x9d \xcd\x0b&\xd2R\xbe=\x85\x90\x87p\x9df*:7\xa2]\xc7\x0d\xd3\x14\xb9\x1dg\x1d\xc7(H_eLX\xba$=d\xff\x14Yn-\xddGP\x8e\xc0\xdf\x16\xab\xc1\xda\x15\x81\xd9zk\x90\xe5\\,\xe1o{D9\x1f\xc6\xf8[\x93(\xe7\x03\x19\x7f\xdb'\xca\xf9P\xc6\xdfZd\xfd|0\xe3o\x07\x04\xc0\x84$\x18\x92\x12@U\x8c\x08\xc0\x00\x92qL\x00\xc6\x90\x0c\xc5+\xd4\x1b\xd0I\x9b\xf1\x859\xf2\x85\x93\xdc\"\x0c\x042\n\x0d\x01\xedBC@\xd3\xd0\x10\xd0:\x8c,\xa0\x81h\x0cl#F\x1a\xd0L4\x06\xb6\x14\x8d\x11\x1b\x8b\xc6)\xec\xf6\xab\x8e\xdd\xa5\x15\xfdV#\xfa\xad6\xf4[M\xe8\xb7Z\xd0o5\xa0\xdfn?\xbf\xdd|~\xbb\xf5\xfcv\xe3\xf9j\xb6\xf3\x8f3\x9d\xd8J\xb8\xd5J\xb8\xd5J\xb8\xd5J\xb8\xd5J\xb8\xd5J\xb8\xddJ\xb8\xddJ\xb8\xddJ\xb8\xddJX\xcdJ\x98\xb3\x12\x05\xdb\x1a\x07\x91Z\xb7\xbd\x83H\x9f[\xf3 R\xe4\xb6\x7f\x10ipk\x1d\x84\xaa\xcb<\xa1*e=`\xab\xf5\xaa\xb2\x1ePVq\xe5\xd6\xd0[\xcd\xac\xe8L\x9e\xce\xac\xda`\x9a|Y\xd5\x08\xb3\xcf\x95\xf5+\x9e}\x9e\xa7U\x95q\x0b\xf6\xad6\xa8\xca\x06|\xd9\xb0*\x1b\x02eU\xfb\xb8U\xfeV\x1bUt#\x9en\\\x95\x8d\xf9\xb2,\xe0\x10\xf5\xb7\xad\x96\xae\xbc\xd8\xad\x95\xd35\xb3\xff\xf1\xa0mX\x00\x93\xaaY\x83\xee`0\x18\x0c9d\x9e\xc7.0\xf9b\xbc}\x80?0.\x9aM\x13b/mJ!GmJ!_mJ!w%\xea\x85=\x96\x00@NKH\x06\xf9-Q\x0c\xb9nS\x0cz/Q\x0c90Q\x0c\xf90\xa1\x16\xc8\x8d\x9bb\xd0\x93\x9bb\xd0\x99\x9bb\xd0\x9f\x89b\xc8\xa5 \x9b@^\xdd\x14\xc3\x8eM\xdaD\xe0\xdb\xa4\xeaZ\xdd\x9bh\xab\xcc\xc3\x1bX\xee\xe4\n^\xae\x10\xc6\xe4\x01\x8a\xc4\xf3}\x99\xe3\xfb2\xbf\xf7en\xef\xb7x\xbd/uz_\xea\xf3\xbe\xd4\xe5}\xa9\xc7\xfbR\x87\xf7\xa5\xfe\xeeK\xdd\xdd\x97z\xbb/uv_\xea\xeb\xbe\xd4\xd5}\xa9\xa7\xfbrG\xf7[\xfd\xdc?\xc2\xcd}%/\xf7\xd5\x9d\x1c\xf6g,\xf3g,\xf3g,\xf3g,\xf3g\xdc\xe2\xcfX\xea\xcfX\xea\xcfX\xea\xcfX\xea\xcfX\xea\xcfX\xea\xcfX\xea\xcfX\xea\xcfX\xea\xcfX\xea\xcfX\xea\xcfX\xea\xcfX\xee\xcf\xb8\xd5\x9f\xf1\x11\xfe\x8c\x95\xfc\x19S\xfeL!\xc2\x0d\x8a\x178\xdcj\x1b/\xf1\xe6\x18\x1d\xaa\x07\xe7\xe5\x03\x01|\xe5\xb9.\n\x1at\xf1\xbb\x00\x9c8q\x88q\x03.~\x17\x80\xf3H\xaa\x86\xf2;\x1b5p\xc7\xc9\xac\xedZ\xa4\xde\xb1rk;\xb9\xe4;Vvm'\x97~G\xcb\xaf\xedd-\xd8\xf3-\xd8\xb7\xb4`\xcf\xb5`/o\xc1\x9ek\xc1^\xde\x82=\xd3\x82\xfdi\x01-\xebXY\xe8p\x94oQ\x04\n\xeeE\xe1[=\x8cB\xab8\x19I\xa0\xecg\x0c\x91\x92\xab14\n\xde\xc6P\xa88\x1cE\xa2\xeas\x0c\x91\x92\xdb14\n\x9e\xc7P(\xcc\xc1\xaa\x81&\xe7\x92\xfe\x91\x1e\xe9\x1f\xe7\x90\xfe1\xfe\xe8\x1f\xe9\x8e\xfe \xde\xe8\x1f\xef\x8c\xfe\xb1\xbe\xe8\x1f\xed\x8a\xfe \x9e\xe8\x1f\xef\x88\xfe\xb1~\xe8\x1f\xe9\x86*\x1e\x87\x8f\xf48|\x9c\xc7\x1d3\xc7\x92`%\x8f\xc3'x\x1c>\xde\xe3\x8e\x9dki\x02%\x8f\xc3'x\x1c>\xde\xe3\x8e\x9dsi\x02 XKR;\xf5\x9cCq\x055\xcc\xdf\x8d\x91\xb2\xb7Ob\x84\xf3;\xa2\x0d\xaazB\xe3\xecy\x12\xe2uJ\xe0\xaa'4\xae\xf8\xa8~\x0d\xca\x7fU\x18\x8e\x0f\x80\xe0\xd9\xc8\xae$;\x05\x94\x8bOA%-\xa0pE#\x14Z\xa10\xa9\x94M\xf3\x15[\xe6+7\xccWk\x97\x7f\\\xb3\xc4-\xc0\x8a-\xc0\xca-\xc0j-\xc0\\\x0b\xe8N\x92'r\xc3\xc8v\xbct\xcf\xbdu@\x1b7e\xdd1[8\"\n\xd9\xbb\xe9\xda\x90(d/\xc1k\x03\xa2\x90\xbdm\xafYD!{\xad_\xeb\x13\x85\xec\xfb\x034\x93(d_T\xa0\xf5\x88B\xf6\x8d\x08\x9aA\x14rJ\xd0\xad\xa6P\xe7$\xd2{d1{0\"\xd4\x1a\xce\xccy\xfb8L\xed\x14i}\x8b>o\xb0\x08c\xff\xbc(\xfb\xb1o\xb9h\xf9\xd3D\xf0\x1cd7\xd6\xc5\xec\xc6:\xcc\xaex\x0e\xb23L\x89x\x86)\x90\xaf,\x809\x8e$\x12\x1a#\x81\x88e\x01\xc8\xb1\xd7\x93\xc8\xd8\xeb d,\x0b`\x8eC\x89\x8c\xbd\xa1@\xc6\xb2\x00\xe4h\x1a\x12\x19MC cY\xa00\x96\x1e`\xd7\xd2\x88\x0f\x1c<\x8fwI9\x9e\xe6`R\x96\xa7\xfa\x98\x9c\xe9\x89n&ez\xaa\xa7\xc9\x99\x9e\xe8lR\xa6\xad\xfe\xa6\xe0p\n\x93w\xe3\x85\xfes;\xa1\x84\xe1\x89>(\xe1x\xb2\x0b\xcax\x9e\xea\x81\x12\x9e';\xa0\x8c\xe7\xa9\xfe'\xe1\xf9D\xf7\x93z\x1a~nO\x930<\xd1\xd3$\x1cO\xf64\x19\xcfS=M\xc2\xf3dO\x93\xf1<\xd5\xd3$<\xdb=\x8db:\xc7\xb6\xf3\x90EP\xf9y\xce\xf3x9\xb7\x7f\xd4\xcf\xb2?\xdd\xf1O\x10t\x04AG t\x08A\x87 t\x00A\x07 \xd4\x82\xa0\x16\x08\xedC\xd0>\x085!\xa8 B{\x10\xb4\x07B\x0d\x08j\x80P\xdd\x02\xa0:\xdb\xae\xed\xca+\x02\xde\x02\xbbJp\x8e}qf\xe8\xfa\x0b\xded\x05|$\x82\xb3f+\xe0C\x11\x9c5]\x01\x1f\x88\xe0\xac\xf9\n\xb8%\x82\xc3M\xed\x8b\xe0\xac\x19\x0b\xb8)\x82\xb3\xa6,\xe0=\x11\x9c5g\x017Dp\xd0\xa4%\xf6\xaf:{\x93:@v\xacQ\x10\xc3`V`\xae\x1d?h\xcb\xd8\xdeW\x08\xd3dVw\xbe\xe7R\x00\xcbb\x96ad\xe1p\xc8\xacG\x13\x0foP\\\x15s\xefB\xc3\xf95\x0b\x1ad\xdb6#A\x18\x06\x94\x08\x8e\xe3@lH\x08B\x08\xd0E\xae\xdd\n\xb2\xe8g\x7f\x00\xf5\xd7\x80\xc5\x02PV\x8c\xdc\xba\x92\xa1\xde\xd7\x19\x0cQ\xbcX\xf4\x0ds\x00IJ\x81\x86=\x8biN\x18\xdb\xc1\x92\x10c\xc0]\xe9_\x86\x98\xe00\xe7\xae\xd9\xef\x11\xc6\xe1\xb6Dd`H\n\n\xf4\xd7\xc5|a\xd8\x8cy\xa2u\x1c\xe1Z\x10\x0b\xf5\x1c\x9b\xbd\x9c\x90s\xa2qv\x7f`.z\x80\xea\"/\xa8=\xd1\xb5t}\xc4\xe8n\x15\xa6\x14&S\xe0\x9c\xb1\x10]>\xd2aW\xa0Q\xb6\xe9\x0eA\xb7G(\xa8{\x869\x1cZ=\xd6\xb3I\xc0\xd8\x1e\x0f\xfb\xb0\xdf\x11\xb01Bs\x87iW`o\xf6M'5\xe6\xfd> \xcd\x1c\xafQ\x03\xea\xf7\xc7\xec\xcb\n\x88r\xd3\x1a\"\x17\xb4)\x89\x1a\x0f\x1c\x87u\xe1\x1c\x85\x12\x1a\xe8\xb8\x88\x03n\xedd\x85\\\n\xb6\x18,\x16\x0b\x04\xc2(\x15\xa0\xd1\xc2]X \x8eq\xb9\xc5\xc2As\x10H\xf5\x10w\xe1ro'\xc3a\\_\xb1/\x80\xd5-AZkK\xad\x8e<\xe6\xb6\xf3\xb0,\xde\x91ZPH\x83\x90\x8ap\xd4B\xc8\x85$\x15\xe1\xb0\x85\x90\x0bP*\xc2A\x0b!\x17\xaeT\x84V\x0b!\x17\xbcT\x84\xfd\x16B.\x94\xa9\x08\xcd\x16B.\xb0\xa9\x08{-\x84\\\x98S\x11\x1a-\x84\xdc\x0cY\x11\xea\x96\x9c\x90\x0b\x81\xe6K\xad\x8e\x828\xca\xb6\x80\xa8&\x86\xdc\xa7-<\xaa\x89!\x17j\x0b\x96jb\xc8\x8d\xdaB\xa7\x9a\x18r\xa5\xb6@\xaa&\x86\xdc\xa9-\xac\xaa\x89!\x97j\x0b\xb2jb\xc8\xad\xdaB\xae\x9a\x18r\xad\xd6\x00\xact/\x9e\x92\x0f\xc7\xe6K\x8d\x88\xc8x\x02.8\x9b/\xb5&>\xe3\xf1\\\xa86_ju\xb4\xc6\xc3\xb9\xc0m\xbe\x14A\xb90n\xbe\xac\x824\x1e\xcc\x05u\xf3\xa5F\xc5u< \x17\xe2e\x92\xd7Q\x1e\x8f\xe7\x02\xbe\xba\n\x01\x01\x17\xfeU\xba/\x02<\x9e\x00\n\x06+\xc7\x80\xe0\xect9_\x16+\xe4\xc8\x8eQ\x90\xf2\x14D!l\xe3l\xc2\x03\xda\x01D\x98\xf3\xa5\x00\x0c\xc5\x9b\xb5\xa2D$|\xf49_je\x00\n\xe1\xf9X4s\xa3,\x1c\x85\xd0|d:_VA\x00\x87\xe7\xe3\xd4Zz\x11 \x18\xb5\xce\x97U@\nt\x02 \x86\xadk\x11RA\x11me\xb8<\xd4\xe4I\xa0\xf8v\xbe\xd4\xea\x10\x176\x1f\x1b\xedfM\x11\xa1\xf9\xd8\xb7i\x88\x88\x86\x8f\x84\x9b1&\x8b\xe0\x80A \x88\x8b\xf3\x81C\x00\x07\xa2d\xa2\xb3\xc2DP\xcc\x9cu\xd8,l\x86\xc6U>\x82\xaeZ\x91\x87\xab\x10 \x10O/Eh(\xba\xae\xdb \xa0\x81b\xed\x8a\xa6\x0e\xb7\x81\x81\x0d\x88\xbc\xb3a\x87\x08\xbe\x013\x02qxC$R2\x14\x957T\xe2\x0e\x06\xc4\xe8\x0d\x99hT\xe1#\xf6\xf9\xb2\x0e\xd79\x020r\xcf\xef\x97\x17s%t\x07\x9d,\xce\x7fn\xd6N\xec\xbb\xd7rd3\xf3\x8a\xb9\x11\x18\x8a%71\x17\xf0zn\x16sl \x14Cn\xe6.\xd0\xd5\xe4-\xe6W#(v\xdc\xcc^\x80\xe5\xacx6\xdc\xac_\x00\x8bY\\\xcc\xa8,\xa7Xq1A\x01%\xc3\x021C\nE\xb1\xe5\xe2\x86R+U\xe8 Q\\\x0d\xa1\x18r\x81\x05)\x81\x9c#\x81\xa1Xr\xa1\x07\xe1[y8\xd1\xe2\x7f\x05\x86b \x05'\x05E\x0bC\x88\x17;\xdc\x10\x1dI\x1b\xeb-]-C\x90\xecd+h\x92l\xd4\xcax$f\xcc.\x8fH\xb2a+\xe3\xa1\x981\xbbt\"\xc9\x06\xad\x8c\x07b\xc6\xec\xb2\x8a$\xb3Z\x19[b\xc6\xec\x92\x8b$\xeb\xb72\xee\x8b\x19\xb3\xcb1\x92\xcclel\x8a\x19\xb3K5\x92\xac\xd7\xca\xb8'f\xcc.\xe3H2\xa3\x95\xb1!f\xcc.\xf1\x88\xae$\xed 5\x82d\xdc\x96' Ie\x9d\xa4F\xc8\x98\xc3\x1d\xa5J%\xb41\x1f\xca\x99\xc3\x9d\xa5J5\xb41\x1f\xc8\x99\xc3\x1d\xa6JE\xb41\xb7\xe4\xcc\xe1NS\xa5*\xda\x98\xf7\xe5\xcc\xe1\x8eS\xa52\xda\x98\x9br\xe6p\xe7\xa9R\x1dm\xcc{r\xe6p\x07\xaaR!m\xcc\x0d9s\xb8\x13\x95\x81\x9e\x98w\x05 Y\xcb\xa2\xc3e[HW#\n\x8e\xd0\xd2\x00\x0c\x17\xa9\\\x8d\x94=\x174\x02\x8b\"8~$\xd3;\xd2*\xd8(\x12X\xb2\xc0\x01%\x91\x10\x92V\xc0\x84\x95\xc0\xb2\x19\x8e0\xcb\x0c\x92\x94\xb7\x94\xaf \xe4\xac\xd3MR\xceT\x84\x08,\xc9\xe0\x18\x94\xc9NIk\x00\"Q 9\x00\x07\xa5dJK\xae|&4\x05V\x89p\x94J%\xc1\x14\xda!\xadC\x10\xb6Ry\xb3\xf6~@\x06\x9c\xc0\xbaP\x18\xc7V\xa96i\x0d-\xcc\x05\x81-\x95\x98\x93\xf2'q\x82Z\x84i\xbc\x9a\x89B \xbddci\xae\x1a\x85\xb0z\xa9\x12Y/\xd9\xe0ZZ\x93 \xce^\xaa\x84\xdaK6\xda\x96\xd6$\x08\xbc\x97*\xb1\xf7\x92\x0d\xbf\xa55 \"\xf1\xa5J0\xbed\xe3qiM\x82\xd0|\xa9\x12\x9d/\xd9\x00]Z\x93 V_\xaa\x84\xebK6b\x97\xd6$\x08\xde\x97*\xf1\xfb\x92\x0d\xe1\xa55 \xa2\xf9\xa5J@\xbfdcziMpdBl\xf6\xb5\x8fA\x92\x9e\xab\x16\xef\x13\xbb\x83\n\xb5\x89{\xaf\xda\x02\x80\xd8NT\xa8M\xdc\x83\xd5V\x04\xc4\xfe\xa3Bm\xe2^\xac\xb6D 6,\x15j\x13\xf7d\xb55\x03\xb1\xc3\xa9P\x9b\xb87\xab-\"\x88-Q\x85\xda\xc4=ZmUA\xec\xa1*\xd4&\xee\xd5j\xcb\x0cb\xd3U\xa16q\xcfV[wT;l\xe2\xaajDQO\x15\x14\x01\xdbo\x05^\xca\x8c\xe3\x03\xed\xcc\x15\xd0zsN\xcc\xad\x810<\xf9\xad\xbb\x82\xa0\xd8\xbd\x133,\xcb\x19n\xfc\xc6^\x81^\x86X\"\\^\xcap\xe27\xfd\nl\xb1\xc7 \xe6U\x96\x93\xdc\xf8-AR'm\x0c)\x14-$\xb0mX\xd0\x14{\x80b\x9ee9\xc5\x0d\xdaT$%h\xe3I\xa1(\xce\xd0\xc6#\xe1\xb0\x91\xe0\x05\xbd,\x84\xe2 \x9f\xbc\xcb\x08\xaa\xcdI1\xcb\x1a\xc1\xb97\xbbsYjK\xca\x0d\xe2\xc4\xefjR:\x92\xf2#0\x0cW~\xdf\x93PQ\xbec\xd6\xa2\xc6\x02Cq\x85vF\xcbN!g\x08\xf1\x02\xb6M\xc96\xb5p$A\x14_hg\xb5 \xec\x8dd\xcd\x98\x97R\x9c\xa0]WB?s\xbc\x968x\x03ax\xf2\xdb\xb2\x05\x81\x9c\x1d\xcf \xda\xb2%U#\xe7G`h\xed\x01\x9b\xba\x04E\xb5\xaf\xdb\xc2\xb8\x86Q\xbc\xa1\x9d\xdf\x82\x88\xd8\xfc\x15s&A\xb4\xaf\x03\x9b\xc3\x14I\x8b+Q(\x8a3\xb4\x81L\xd1\xb4\x0d\xc74\x8c\x96\x1a\xd8e\xa6\x88\xa43$\x81a\xb8\xf2\xfb\xd0\xa5\x07-\x15b\x02\x12T\xf0\x05\xd2&\xc2\x08\xa18\xa6#\xe5.c,\x0e\x19\xc8#=R\xf6l\xe0\x00U\"\x8a!\xeaC@\xd2\x1a\xa8H\x02b/\n*\xca3CR\xe6Dh\x01\xb1\x16E\x19\xf5\x01#)s\xca 9\xf6\xa2\xb0\x839\x8f\xa4\xa0}y=\x928\xa4>\xc4$\xad\x84\x8a\x19x\xf6\xe2\xc0\x849\xf3\xa4\xd0\x92\x96\xaa\xc4\x91\nyP\xaa\xbd\xb3\x11\xb37_\x898t!\x8eVI\xeb`\x02\x18\xb8\xdf\xc1\xb1Ly\x16Kn\x0f9kQpC\x1d\xdcR\xb1\x85\xbc\x1aQ\xb4C\x9d\xf5j7\x059\x07\xf0\xd5\x88\xc3\x9f\xeax\x98\xbcw\xcb\x99\x0b\xe3!\xfa0\x99\x82\xae\xe4\x15\x89\x03\xa4\xf2\x00\x9a\xb4\x06\"L\xe2Y\x8b#&\xf2\xb4Z\xbb\x19\x889\x1e\xaaD\x18B-\xdb\xf9KY\x8bc*\xea0\x9c\x82 \xa4\xd5\x88\x83,\xf6\xfc\\{ML\xa8\xc5W&\x8e\xba\xe8Sw\xd2\xaa\xf8\xd8\x0b\xe8\x84\xc20\x8c9\xa9\xa7R\x93\xdc\x85\xc5q\x19{\xbcO\xa5\xae\xb6 K\x18\xa8Q\x87\x02Uj\x92\x07&\x92\xc8\xadu\x17\x99\xc0\x08*\x00\xf7\x94#[?\x08\xbe\xdf\x1a\xd9F]\xd4\xedY\xdc{j#\xbb\xd7\x94C\xc5f]\xcc\xbfY7\xb2\xfbu)\xffj\xdd\xc8\xb6\xeaR\xfe\xdd\xba\x91=\xa8K\xf9\x97\xebF\xf6\xb0\xa9\x97\x7f\xbbn\x84\xeb\x06k\x18-R\xae\xd5\xd8\xa0\xcb\xc1\xa6\xe3\x1e\x03\x820&\x8d\x01\x94\x80\xfb4\x04\xd0\x04\xb6h\x08\xa0\x0e<\xa0!\x80N\xf0\x90\x91\x05PL\xdc(&\xce\x06\x16N3\xb1\xc1\x00@\xd5\xc4=\x16\x05\x81L\x06\x04('\xee3\x18@;\xb1\xc5`\x00\xf5\xc4\x03\x06\x03\xe8'\x1e\xb2\xf2\x00\n\x9a7\n\x9a\x87i\x1a\xfa\x9c\x86\xe6\x06\x8b\x00U4\xefq0\x08e\xb2(@I\xf3>\x0b\x02\xb44\xb7X\x10\xa0\xa6\xf9\x80\x05\x01z\x9a\x0f9\x99\x00E\xa5\x8d\xa2\xd20\xe2\xb4\x94\x1aT1\xa8\xa2\xb4Gc \x88IA\x00\xe5\xa4}\n\x01h&\xb5(\x04\xa0\x96t@!\x00\x9d\xa4CZ\x0e@!\x1bF!\x93\x16?\xda@\x1ab\x89@\xbdm\x00\xbdq\x84\x10\x1d\xafL\x96\x0cP\xf0\x86W0K\x05(}\xc3+\x9d\xa5\x02\x0c\xb1\xe1\x0d\xc1R\x01\xc6\xd9\x00\xc6\xe1\x1a\x06Xl\xc5\xce\x125\x11<6\xae\xc0Y\x83!\x02-\xb6\x82\xa6\x12\x96\x10\xa2\x03\xa6\x17\x86\x0c\xb0\xd8\n\x98q\x18*\xc0b+`\x12b\xa8\x00\x8b\xad\x80y\x89\xa1\x02,\xb6\x82\xa6*\xb6a\xc0\xc7\x85l\xfd\xe0\xdb\xf1\xd2\x0bX\xdb\xf8\xb6Q\x95@\x06\xf0\xed^]\x0c\x95\x9aU)\xf0\x95'\xbb_\x15\x02\x9fU\xb2\xad\xaa\x10\xf8Z\x92=\xa8\n\x81\xaf-\xd9\xc3\xbaN\xa0\xa1\xb8j(\x18\xbf\xf8\xd8\xa0\x8a\xc1&\xe3\x1e\x8d\x81 &\x05\x01\x1a\x8f\xfb\x14\x02\xd0\x00\xb6(\x04\xa0\x06<\xa0\x10\x80.\xf0\x90\x96\x03PH\\+\x04\xec\x9b~l\xd0\xe5\xa0J\xe2\x1e\x03\x820&\x8d\x01\x94\x12\xf7i\x08\xa0\x95\xd8\xa2!\x80Z\xe2\x01\x0d\x01\xf4\x12\x0f\x19Y\x00\xc5\xcck\xc5\xc0\xf3\x8c?7\x18\x00\xa8\x9ay\x8fEA \x93\x01\x01\xca\x99\xf7\x19\x0c\xa0\x9d\xb9\xc5`\x00\xf5\xcc\x07\x0c\x06\xd0\xcf|\xc8\xca\x03((\xad\x15\x04\xc4)~j\x90\xa5\xa0j\xd2\x1e\x05\x81\x10&\x89\x00\x94\x92\xf6I\x00\xa0\x91\xd4\"\x01\x80:\xd2\x01 \x00t\x91\x0e)\x19\x00ElhEL\xe4n\xb3\x01\x143Qp\xa4\x0d\xaf-\x96\x0c\xa2\xe248i\xf5\xb4\x0d\xa7\xd4I\xab\xe7m8=OZ=q\xc3\xa9~\xd2\xea\x99\x1b\xde\x1al\x83\x00\x0b\xad\x98Q\xbf\"\x81\x87\xbc\x154 \xd0$\xa0\x85V\xc0\xc4\xc0\x90AT\xfc\\A\x13\x01\x16Z\xf1\xb3\x07M\x03Xh\xc5\xcf'4\x0d`\xa1\x15?\xc3\xd04\x80\x85V\xc0\x9c\xc34(\xb7P\xfb[-\xe9\xd7\nFv\xfer\xce2\x96\x01\xf2-d\xa9 \xe5BA \x84I\"\xc0\xc4\x0b \x00s/$\x00L\xbf\x90\x000\x03C\xc9\x00&a\x08\x84(\x0f\xc3A\x04\xa9\x18\x1e\x07\xc1L\x0e\x06&d8\x14\x98\x93\xe1P`Z\x86C\x81\x99\x19^.09C\xc2D\xf9\x19\x1e#H\xd1\x00@\x08g\xf280Q\xc3\xc3\xc0\\\x0d\x0f\x03\xd35<\x0c\xcc\xd8\x00\xb2\x81I\x1b\x12'\xcc\xdb\x00 A\xea\x06BB@\x13\x00\x82 \x1c\x00\x07\xe6p\x00\x1c\x98\xc6\x01p`&\x07\x92\x0fL\xe6\x90@8\x9f\xc3\"\x04)\x1d\x0e\x06\xa1L\x16\x05&vX\x10\x98\xdbaA`z\x87\x05\x81\x19\x1eN&0\xc9\xc3)\xaa=\xcf\x03kN1\xd5\x03\xeaS-\xdb\x03)Y)\xe1\x03)^)\xe7\x03\x19C)\xed\x03\x19H)\xf3\x03\x1aM-\xf9C\x92*\xe6\x7f8\x92cR@<1D\x0b\x91\xc2\xd3\x9aJ\"\x88#T\xcd\x05q\x84\xaa\xe9 \x8eP5#\xc4\xb7Q9)\xa4\xe5\xdfs\x8f\xe1\xbc\x10Q(H\x0d\x91\x08\x08`\x12\x000AD\x94\x839\"\xa2\x1cL\x13\x11\xe5`\xa6\x88\xac\x1fL\x165\x00Q\xbe\x88E\x08RF\x1c\x0cB\x99,\nL\x1c\xb1 0w\xc4\x82\xc0\xf4\x11\x0b\x023H\x9cL`\x12\x89@\x89\xf2H\x1cD\x90J\xe2q\x10\xcc\xe4``B\x89C\x819%\x0e\x05\xa6\x958\x14\x98Y\xe2\xe5\x02\x93K\x04L\x98_\xe21\x82\x14\x13\x00\x84p&\x8f\x03\x13M<\x0c\xcc5\xf100\xdd\xc4\xc3\xc0\x8c\x13 \x1b\x98t\"pp\xde\x89\x01\x08RO,\n\x02\x99\x0c\x08L@1\x180\x07\xc5`\xc04\x14\x83\x013Q\xac<`2\x8aUPk>\nT\x98ZJ\n\xd2\xa2RV\n\xd0\xacJb\nP\xb6Jn\n\xd0\xbfJz\n0\x89J\x86\n\xb2\x92R\x92\x8a T\xcbS\xb1\x04G\xa4\xaa8R\x80\x12\"\x04\xe7(\x85\x84\x15K\xa6\x98\xb3b\xc9\x14\xd3V,\x99b\xe6\x8ak\x9b(y\xa5\x90\xbdR\xf8&Kd\xeb\x9a_\xc5fPF\xab)\x14%\xb4\x08\x04\x040 \x00\x9c\xcej\xca\xe1lVS\x0e'\xb3\x9ar8\x97E\xd4\x0f\xa7\xb2|f\xad\xc0\"\x0c\x16!Jd\xb10\x08e\xb2(8\x8d\xe5\xf3\xb1=\x0b\xb2X\x10\x9c\xc4\xf2\xf9\x98\x9d\x05\x0d9\x99\xe0\x14V\x83\x12f\xb0X\x88(\x81\xc5\xe1 \x98\xc9\xc1\xe0\xf4\x15\x8b\x82\xb3W,\nN^\xb1(8w\xc5\xc9\x05\xa7\xae\x1a\x988s\xc5aD\x89+\x1e\x08\xe1L\x1e\x07\xa7\xad8\x18\x9c\xb5\xe2`p\xd2\x8a\x83\xc19+^68e\xd5\xe0\x04\x19+\x1a JX1(\x08d2 8]Ec\xe0l\x15\x8d\x81\x93U4\x06\xceU1\xf2\xc0\xa9*FA\n\x99*Hc\xaa\x89*@\x8f\x8ay*^\xb9ji*^\xe1jY*\xde\x08jI*\xde0j9*\xc0X\x8a)\xaa\x86R5C\xc5P\x1c\x95\xa0bi!R\x88\x12\x9c\xae\x94\xd2S\x0c\x9drv\x8a\xa1SNN1t\xca\xb9)\xb6}\xea\xa9)\xbf\x8c\xd4\xa0\xccT]&JL5\x00\xa8\xdcl\xca\xe1\xb4T]\x0cg\xa5\xeab8)U\x17\xc39\xa9\xa6n8%\xe5\xd3k\x04\x16`0\x00QB\xca\xe7\xc3\x7f\x16d2 8\x1d\xe5sq=\x8b\xb1\x18\x0c\x9c\x8c\xf2\xb9\x88\x9d\xc5\x0cYy\xe0TT\x0d\x12f\xa2\x18\x84(\x11\xc5\xc2 \x94\xc9\xa2\xe04\x14\x03\x82\xb3P\x0c\x08NB1 8\x07\xc5\xca\x04\xa7\xa0j\x948\x03\xc5BD (\x0e\x07\xc1L\x0e\x06\xa7\x9fX\x14\x9c}bQp\xf2\x89E\xc1\xb9'N.8\xf5T\xc3\x04\x99'\xaa\\\x94x\xa2A\x10\xc6\xa41p\xda\x89\x82\xc0Y'\n\x02'\x9d(\x08\x9cs\xa2e\x81SN\xb4b\xda3N\x80\xa2\x14\x13N\xbc\xf6\xd4\xf2M\x9cF\x95\xd2M\x9c\x92\x95\xb2M\x9c\xde\x95\x92M\x9c)\x94rM\xbcu\xd4RM5\x9db\xa6\x89\xc6\x1f\x93hb(\x01B\x88\x0e\x9a{T\xd2L4\x95j\x96\x89\xa6RM2\xd1T\xaa9&\xa6]\xa7\xa5\x98\x04\xd9$\\\x85SP6\xa9)\x14e\x93\x08\x04\x040 \x00\x9cMj\xca\xe1lRS\x0eg\x93\x9ar8\x9bD\xd4\x0fg\x930\x13\xd7\xb3\x08\x83E\x88\xb2I,\x0cB\x99,\n\xce&a>\x16gA\x16\x0b\x82\xb3I\x98\x8f\xb2Y\xd0\x90\x93 \xce&5(a6\x89\x85\x88\xb2I\x1c\x0e\x82\x99\x1c\x0c\xce&\xb1(8\x9b\xc4\xa2\xe0l\x12\x8b\x82\xb3I\x9c\\p6\xa9\x81\x89\xb3I\x1cF\x94M\xe2\x81\x10\xce\xe4qp6\x89\x83\xc1\xd9$\x0e\x06g\x938\x18\x9cM\xe2e\x83\xb3I\x0dN\x90M\xa2\x01\xa2l\x12\x83\x82@&\x03\x82\xb3I4\x06\xce&\xd1\x188\x9bDc\xe0l\x12#\x0f\x9cMb\x14\xa4\x90M\x824\xa6\x9aM\x02\xf4\xa8\x98M\xe2\x95\xab\x96M\xe2\x15\xae\x96M\xe2\x8d\xa0\x96M\xe2\x0d\xa3\x96M\x02\x8c\xa5\x98Mj(U\xb3I\x0c\xc5Q\xd9$\x96\x16\"\x85(\xc1\xe9J)\x9b\xc4\xd0)g\x93\x18:\xe5l\x12C\xa7\x9cMb\xdb\xa7\x9eM\xc2eP\x06e\x93\xea2Q6\xa9\x01@\xe5fS\x0eg\x93\xeab8\x9bT\x17\xc3\xd9\xa4\xba\x18\xce&5u\xc3\xd9$L\xaf\x03X\x80\xc1\x00D\xd9$\xcc\x07\xf9,\xc8d@p6 s\xf1;\x8b\xb1\x18\x0c\x9cM\xc2\\l\xceb\x86\xac{U\x1fl?w\x15\x1fV\x00w\x17\x1f\xd4\x00w\x19\x1fR\x01w\x1b\x1f\xd2\x01w\x1d\x1fR\x02w\x1f\x1f\xd2\x02w!\x1fT\x03}\xe7\x1e\xd6\x01}\xe9\x1eT\x00}\xeb\x1ej=}\xed\x1ej:}\xef\x1ej7}\xf1\x1ej4}\xf3\xbelq\xfb\xc1\xcb\x033f\x90\x17UD\xa3\x1d\x05\x01\x07<\x12\x01\x8ey$\x00\x1c\xf6H\x008\xf2\x91\x00p\xf0\xa3d\x00\xc7?\xf6\x00\xabh\x08\xe4q\xe0(\xc8\xc1\xc0\x81\x90C\x81c!\x87\x02\x87C\x0e\x05\x8e\x88\xbc\\\xe0\xa0H\xc0\xe4\xe3\"\x00\x04\x87F\x1e\x07\x8e\x8e<\x0c\x1c y\x188F\xf20p\x98\x04d\x03GJ\x02\xd72XBHp\xbc\x04\x80\xe0\x90 \xe0\xc0Q\x13\xc0\x81\x03'\x80\x03\xc7NH>p\xf8$\x80\xb2\x11\x94\x83\x81\x83(\x8b\x02\xc7Q\x16\x04\x0e\xa5,\x08\x1cMY\x108\xa0r2)l5\xaa\x9ef\x0f\xc8\x83W\xc2\x81\x96@\xc0\xe3l\x03\x80\x87\xd9\xa6\x1c\x1ee\x9brx\x90m\xca\xe11\x96\xa8\x1f\x1eb\xe9\xfd[\xe1\x08\xcb\xc2\xe0\x01\x96A\xc1\xe3+\x03\x82\x87W\x06\x04\x8f\xae\x0c\x08\x1e\\Y\x99\xe0\xb1\xd5gF\x1b\xd1\xd0\xca\xe1\xe0\x91\x95\x85\xc1\x03+\x8b\x82\xc7U\x16\x05\x0f\xab,\n\x1eU9\xb9\xe0A\xd5g\x07\x18\xd1\x98\xca\x03\xe1!\x95\xc3\xc1#*\x07\x83\x07T\x0e\x06\x8f\xa7\x1c\x0c\x1eNy\xd9\xe0\xd1\xd4\xa7\xc6\x1a\xd1`\xca\xa0\xe0\xb1\x94\x06\xc1C)\x8d\x81GR\x1a\x03\x0f\xa44\x06\x1eG\x19y\x14\x86Q\xc1\x88\x89\xeb\xe1F4b\x12\x08x\xc4l\x00\xf0\x88\xd9\x94\xc3#fS\x0e\x8f\x98M9\x96\xdc\xca\x05\xfajr\xc1\xa8\x10\xa6\x95C\xdb7\x12Kf\xae\x1d?\xb4\xf2\x92}I5\xe3\xf3\x80\x0e)\xda\xa5\x9a\x8b\x9c0\xb6S/\x0c\xce\xb1\x17 -]\xc5\xe1z\xb9\xa2 \xd6\x81\x8b\xe2\xac\x98\xa3\xa9K\x18\xc7\x0b51M\x10\x06Ha\xe9s\x00d\xce\xd6Q'\x88\x0d\x91)H\x0e\x91\xe5\xc2+H\xaf\xb0p+\x9b\xe4\x9f\xd4\"\x9eJ\xa5A<\x95B{\xc4\xa2\xe3\x93D\xe7\xa9TD\xe7\xa9\n\xd1)\x8a\xb4D\xd9\xd8[\x06\xe7YT\xc0\x94\xc7dy>Q2\x00\x87\x048(HQ\xac`\xed\x03#E\xed9bA\x18\x08(\x0b\x83)\xc5Q\x90G\xc1\xfbR\\y\x83DF\xbf]D\xffh aaZ-G#`a0$\x0c\x0d\xaa,\x9c\x7f!~\x11\xc6\xfe\xb9cG^jc\xef\x11\xb1P\xccBq\xb8E\xb1c'\x1cr\xcd\"\xd7Q\x04#\x03\x16y\xd2p\x98\x12\xce\xa1\xd4\x12\x00-n\x0c\x00\x16\xb7\x07\x00+\x0c*\xcan\xda\xb8\x98Z;9\xb0\xa4\x99\x1cV\xd2J\x0e\xab\xd0HA{8\xb7\x92\xb5\xe7\x08\x1f\xe4\xb1\x92\xf6pX`8]h\x833\xe6\xc1\n\xd9n>\xab/\xc2 \x8b\xf5\x1e\xd19\x1fR/4\x8b\xa5K\xd6s\x80\x94\x0f\xa1\x17\x06Ql\xf2\xc5=\xa2\xb8\x07\x05\xea\x0b\x93@\x18@\x90\xbe\xe8S\x00\x88\x85E\"\xf8\xe2\x01Q\xdc\x1d\x0d\x01\x06C\x12Q\x00\xda{\xc3\x81\xd5\xbd\x16$\"\xf5g\x9d\xae\xc5\x02\x005a\x04\x9a\x01d\x07\x1a\x01\x99\x82F\x08\xacA\x83`\x83\xb0\x18\xd0&\x0c\x080\x0b\x8d\x10X\x86\x01\x15\x18\x05\xeb(\x8cU\x99\xc9|\xa1\xc5\xfcV\x83q\xb4\xa4\xbd\xfc6s\xf9m\xd6\xf2\x15\x8c\xe5\xb7\xdb\xcaW0\x95\xdff)_\xc1P\xfe\xb1v\x12\x98\x04\x0bM\x82[M\xc2\xd1\x92&\xc1m&\xc1m&\xc1\n&\xc1\xed&\xc1\n&\xc1m&\xc1\n&\xc1\x80I(\x8c\x8f\xecd\x1d\xa3C\xd3O\xb2\xce\x03b\xb2r\n\xd8\x17\x01\x03;\x8e\xc3-\x01\xedq<\xbd\xc0EAZLi\xc5\xcf\xe7Fs\"+m?\xcf\x98\xf86\xc6\x9acG\xe5\xe8\xb0\xb1c\xcf\x0e\xd2\xf3\xe69\x8dO\xe3u\xe0\xd8):\xe4\xc9\x81<5\x82\xce\x83p\x1b\xdb\xd1$\xdc\xa0x\x91\x7f\x9c\xcfs]\x14Lr\xa9\xea\x87\x08c/J\xbcDa\xcc9\xc0\xeaH\x94\xd5\xcb`[4L\xa3EJ\xae\xe3\xbd'\xea\xb9\x1e\x88UU\x9d\x11\x9c\xaem\x05u+\x0c\xf1\x95\xc2|u\x13\xf8\xc7X\xc0W1\x80\xff<\xfa\xf7\x8fT\xbf\xff\xdd\xb4/Q4VW4>F\xd1XE\xd1\xf8y\x14\x8d\x8fT4~\x8a\xa2)\x96U\xb9\xe6\x84Aj{\x01\x8a\x0f\xf5\xa3\xfdy\xe2\xc4!\xc64E\xb1h\xa6\xb7\x12\xecu\x1aN\xc8\x9d\x96\xec\x01\xa3\xddX\xcb\x1e\xf2t\x0c\x0cS\xb0\x86Y{\xe7<\x00bj\xec\xd9\x1buIARPX\x8d9\xf4\x94\x03\x15\x04V\x18M\xcaV\xf8'7\x02\xa0\x84\xdb\xe0\x1f\xdb\x04\xb1\xb4\xf8di\x01JXZ\x0cHK\x8b\x82\xbd\xe8\x10\x85\x89\x97'\x02\x17\xde\x0e\xb9\xff\xd7\xf3\xa30N\xed \x9d\xfcQ\x97\xd8\xf3$\xc4\xeb\x14\x11\x85\x19\xe9y\x8c\x9c\xf4G#\xdau\x88\xbf?\xd1Eg\xc4\xdf\x9f\x14\xcc}\xe0\x04\xcc\x1c\xe7\xcf\x94QAH\x15\x9f\xcc$\xf7\xff\x83\x04\x17\xc9\x88\xff\\\x19)\x01\xb6\x89\x16\x84\xb1o\xb3#u\xf6\x88F\x16\xa370\xa0\xd3\xb0(\xa6#\xc9(>>'X\x0b\xc5\x07J\"\xb9\xe0\x90\x8a\x13\x8d\x85e\xd2)\x88\xa7\xe0m\x8d\xcclt!\x14\x19\nCx\x89\xfd#\x05\x96\xca\xa6jfp\xe6\xe6e\xc3\xbcl\x14f\xa3\xcd\xed\x04\x1d6(N=\xc7\xc6e:;{\xc6\xef\x91l4\xdfsY\xa8\xef\xb9.\xe6\x80i\x18\xb1\xc04\x8c\xb8\xaaS\x9f\xab9\x0fp\x14\x0c~\x00\x9a\x91\xf9\x8ezK\x00\xb4\xb01\x00\x16n\x0f$B\xd1$\x856)8q\xd9P^o\x92vr`q39\xa8\xa0\x95\"\xbb\x1d\xed\xf8e{\xf01\xed\xe1\xc0\xe2\xf6pPA{\xf8\xfa\xcb\xf6PX\xd7\xf3\x0fad;^\xba?7\xb8\xa23\xf6\x01\xf41\xfa\xecq\xf1\xfdym\x8b\xe6\x0f^\x99\x15/f\x90\x92w\xa7kXI\x07ez\xf1\x82IK9'\x86\xbc\xd6J\xfc\xae\xc5\x13\xdaN\xeamP\x03\x19M\x94d\x0c\xd7\xa9\\\xc8p\xcd\xec\x9e-q\xb8=\xe3\x9e@\x82\xe7\xcf\xbf\xa3\xbe\x14\xea\x15\x18|\x95-\x03\xf3S\x11\x9dn\xfe\x9f\x1a\xa8\xab\xa9\xedXQ\x9b\nKC\x95\xf5\x9e\x89Py\xb3\xda@y\x1b\xd9\x16\x18\xdf\xa7\x05\xcd\x06{^+\xa4w\x16R\x98 _\x7f\xb6\xef\xe1/\xe3p{\xd0\xfc\xf0Q\x0b\x93\x9dVd\x0f\xfd0LW^\xb0<_\xc6\xf6>ql\x8c\xea\xb6\xcdm\xe7aa;H\xdbx\x897\xf7p\xd6\xf2r\xc1+)\xa24\x93of\xe5?a;E\xdf~\xd4\x7f\x9a\x88\x9e\x03\x1a\xe5Xu\xba=A\xa7:\x02z:\xe4\xac\xa5\x16^\xdb`\xd7\x89\xe1.\x9b\xeb$\xb7\xc0\x8fFW\xb7HM\x11O\x81:\xcaaI\xc4\xac;\xe6Yu\xc7\x00#\x0d\xdb\xf1\x12\xfd\x7f\xc5A\xbc\xe0\x18\x1f\xe1\xd1OEI\x9d\xa5\x80\x88L \xf2\x9a\xb2\xb4\xcdwz\x90\xeb\xf4\x84\x06o\xf7\x1f\xc0\x17\xb3\x87L0\x1dzAZ\x8fH\xce:N\xc2\xf8\xbc|H#\x93\x95\xed\x86[\x0d\x02N\xea\xc5b\x8c\xb0\x9d\x89\x05\x99\xdd\xc6\xb8\xd3\xb5\x92\x8e\xb3\x9e{\x8e6G\x8f\x1e\x8a\x7f\xec\x1a\x03\xeb\xac;\xea\x9fu\xfb\xfd3\xe3\xa7\xc9\x91x\xb1\x88\xe7\xf6\"\xcd\x04\x0d\x83\x14\x05\xe9\xf9_\xfe\xd2\xf8\x7f\xb8\xd3\n\xe4\xb9\xde\xd1;\xc6 \xdauz\xd1\xaeC\x9e\xf7\xeb\xfd4Q\x86\xe5\x07;c\xdb\xf5\xd6\xc9\xb9\x17\xacP\xec\xa5\x93f\xd2\xe4\xd6\xd1\x93\"\xf3\x99\xe7e\xf4I\x11A\x1a\xba\xfeb\xb2ByN'\xff\xf91\xcf\x98\xee\xce5\xf9\x9cu\x846Ui$\x1a\xcd\xfd\xbb\xd0\xeb\x99\x18Ej_\x10d\xcc\x97\x9a\x1dx\xbe\x9d\xa23\xc1s\xa8/\x11\xa5\xc2\xd0\x89=\xc4IM\xdb\xec(\xd0\n\xa6\xa5~\xd4\xf4Ce\x17\x9d-2\xea\"\x83-\xea\xd5E=\xb6\xc8\xac\x8bL\xb6\xa8_\x17\xf5\xd9\"\xab.\xb2\xd8\xa2\xf1x\\\x17\x8e\xc7c\xa0\x98*\xe7\x00\xbe\xbdk\xa45\xfa\xc3\xfe\xc8\x1c\xf4\x87,\xaa\xf4\xf2\x1aY\xfe\xce\xc3\xbc\xd4\xb3q\x0d\xe3\xb3\x95\x8f\xda:HP\xc3(\xff\x8d\x86\x04(IQf\xa0h\xaf\x15\x11T\xdeM:!\xb3\xaf,\xc2Ej\xb05>\x10\xbf\x9e\x1b\xecB\xa2\xa4k6\xae \xda\x95\x01\xd6\x01c{G`\xcd#\xb0\xfd#\xb0\xd6\x11\xd8\x01\xa3\x17\xe8`\x7fA\x8f\xbd$\xd5b\x94 \xa1q\x08\xc4\x9a{\xf1\x1c\x99\xaf\xd6'94I\xf7\x18i\xe9>B\xc5\xd1*\xa1%\x8b\xed\xa5N\xf4sDm7u\x8f\xdbo\"9&(B\xb1\x9d\x86q\xce\x94\xe0at-A\xfb=\x7f\xd9\xf1\xfc\xe5\x81\x18\xd2\x9b\x9cG\xfe\xab\xeb%\x11\xb6\xf7\xe7s\x1c:\x0f\x02\x1d\x06\x0fI\xc7>\x94\xe7\xe1Mk\x88\\\x17\x9a\x02\xf8\x01k\"-\x95\xd5\x06\x0d\xb6\x0c\xa2\x9c\xf5\x0b\xa9\xc6\x03\xc7Y,\x9e_\xaamlG\x11\x8a\x05\n\xec\x0f\xf4hW\x1a\xf0\\\xef\xe4\x9b&\xa5\x0b\x9d\xeb\x9d^VH\xcd\xf0\xdecVRN\xcf\xf3p7\x01\x9f\xd2\x12\x84Qn\x1a-\xb5\x97Z\x82\x9cL\xeaCe4\x82ymH\xcdO\xb4\x05F;\xf2Y\xf6;%I\x18{\x993V\x99\x18\xaa\xcc\xf5\xe2\xa2\x9a2%:\xa98\x12%N\x88\xd7~0\x01\x9f\n\xc5\x7f\xba\xd8\xe4 \xe0F,\xeai\xfe\x8b\xe6\xa5\xc8O\xaaG\x95E\x0c=\x0b\x97\xb2\x7f\x8c\xea\x9f \x134\x8aB\xc4^\xc2E\x81\xbddR\x9b,\xef\xb9F\xb4\xeb$!\xf6\xdc\"\x1c\xb3\xc6g\x03\xebld\x9cu\xcd\x9f\x84*)\x9d\xb8\x99\xf5\xa9\x1b\x1e:\x1bj\x93\xca$\x8e\x18\xf5I'\xd4;V\xb4\x9b\xe4\xa5\x0b\xdb\xf7\xf0\xfe<\xb1\x83DKP\xec-&U\x1f\x9e\xf7\x0d\xcb\x10\xf2\xee\x06\xa1\xe6\xa2\xc4\xe9$\x91\x1d\x1cH\x03d\xfa>7j\xd5\x9f\x1b\x93\xe2?BV\x9dd\xb3\x84\x82\xa2\\\x85}^\xab\xfdD\xc2\xca\xb71u\xde\xa9_5t[\xcc\x04}]\x9f\xa8HK\xf4\xd1\xdc \x8eWVd\xc7\xb6\x8fR\x14\xff\xf1G6\x15\x90B\xf5\xa2]\xcd\xdf\x8av\x1d\x9db\xef\x87A\x98o\x10P\x82\x0ft]V\xdb\xc6C[\xad\x9a\x06\x1f\x0e\xfc\xca&\x9b\x04\xcch7\xa9\x0e>\x90\xfe`\xa9{\xb9\xc5\xdb\xc3\x82\xedq \xdc\xcd\xc8j(\xba\x02\xd1\x07\xfe\xaa\xeb:\xb3\x10\xe9\xb3\xc3a\xb3\x921\x99E\x8c1\xe6\x16;\x00\x04\x14\xad\xd3M\xedy\x1e8\xa0\xf8\xe9#\xceQ\x0eOV]\xfc\x9c\x8dC\x87\xc6\xdb\xfa\xfc\x90s\x04\xa3\xf3\x85\x17'\xa9\x16.\xf2\xf0\x83a\xdb\xd1;\xfa\x11\xbc\xbaebs\xd5/:9\xe7S\xa7\xf3*\xd7Y\xfc\"\xb3\xbe\xad\x999L\x1eSY\xfa\x8bj\xb5\xd9kV\x9b\x99\x9f\x00kd \x9b\xf3\xfb\x8f\x9a\xa5\xbf\x00\x13=U\x111\xb4.c{\x0f6\xab\xeb%Z\x18\xa1\xa0\x19n\x92\xb5\xef\xdb\xf1\xfe \x1a\xe13\xef\x16h\xa8fQL\x8a\x95'V\xd6\x1a\x95s\xd0\xc4\xf7\x82*\x82\xb5\xb2\xdf A\xd9\x1b\x83\xa3\x9f\xe0~c\x00\xcb\x7f\x83\xe980\xe6(\xd9\xcf\x8e\x01w\xb0=G\xf8\xe9\x1d\xef\xa4\xa9\xfe\xa8f\x95\x922C79,\x0fu\xbd\x1eG\xb9\xc30'\xcc\x1aJ\x02\x95\xfd\x91\x9a\xa1$\x9d[\xc0j\xd5g'J\x95Q\xadi\xeds4\xae\xe8C\x9a\x8f\xd2U\xe8\xca\xe6\xed\\\xcf\xf5\xd6\xe5H'f\xd0A\x16\xa8e\xe3\x05w\x03\x8c\x99\\L\xba\x0b\xe5\xd3ONC\xf5\x04\x9d\xed+\xf2v.\x16\x0b\xc5F\x86\xf9\xd2,3\x80\xe7\xb6\xf5\x97\x92$\xb2\xd3\xd5\x11\xd0?\xfepQ\x14#\xc7N\x11\xa5\xccAD\xf4\xacS{[n~\xbdq\x08\xbdc\x16\xab\x19\xfa\xb7'w\xd0\xc96\x8c]m\x1e#\xfb\xe1<\xffW\xb31\x96\x85c\xaa\xf1R\xb9\x19N\xec\xe8\x0f\x07\xa3h\xc7l\x81\xff\x07\x9a\xaf\x17\xed\xd8\xd3\x9d\xcal\xd8\xcd:,\xbc\xa6\xab\xd4p\xa6\x8b*r\xc8\x16\n\xb1\x17\xe5\xebR\x82\x81\xa9:\xe4<\xdfH\xf3?4\xe9\x90\xd1\xbeZp\xc7\xc8\xad\x18\xe0\xf7\xea\x00\x9f\x98\x95\x9e=\xb2\xe7\xa4\xab\xf6\xad\x19\x19\xcb\xb0m\xc4,5\xe0\xf8\xaab\x19\x85IJ\xbc\x8f\"3p\x7f\xec8c}\xc2\xae\x80\x87\xe6YO\xef\x9f\x19\xfd\xbe0\\\xa1\xb8\n\xa7\x1drN(\xea:\x81\x19(\xb3\n\x1f\xf5p\xf9h9\xd7\xac&\x17\x8em\x98\xbc&{V\xef\xcc\x18\x18g\xfd\x91\x82&\xd7j\x8a,\xaa:\x9e\x17(\xb1\x02\x9b\xd3\xd4\xa8\xc2\xdeE\x18\xa5\x88\x95kl\"\x13\xf1\x9a\xec\x8f\xcf\x06\xbd\xec\xff\xad\x8a,\xd8\xaa\xe92\xaf\xec$v\xa0\xd8j\x9cN\xd4\xa8B\x0dK\xc4:\xe6\xc0\xb0\x17\x0b^\x9d\xe3\xe1\x991\xb4\xcez\x96B\x17_\"5\xc7,\xaa:\x9e\x17(\xb1\x02\x9b\xd3\xd4\xa8\xc2>\xb2Sg\xc5\x88e\xe9\xc8tz\x9c\"G\xfaY\xaf7<3\xc6\n\x8a\xcc\xd9*\xa9\xb2\xa8\xec\x14n\xa0\xd4J\x8cNS\xa7J\x05\x19WF\xae\xb1n\xf4\x00\xb7\xcc\xa6\x1cc\xa4\xe6\x96\x19W%e\x16u\x9d\xc0\x0c\x94Y\x85\xcfi\xaaT\xe1\x1f\xe6\xb1^\xc2H\xa6\xbb\x96m\x0fym\x9agc\xfd\xcc\x18\x0c\xdb\x95Y\xf2U\xd2gQ\xdbi\xfc@\xc1\x15Y\x9d\xa6U\x95*\x88\xb0\xbe>\x15:\x98\xd0\xa2\xa2y\xf6\x07\xce\x14\x8d{\xc0\xab\xa5\xc4\x95(i\xb9\xa8\xefd\x96\x07Hzun\xa7\xe9ZR\x0b!\xa0\xb3B>J\xb8\xa4\x9c\x1aY\xa7[\xfe\xa0\xa5^\x8aQk\xaef\xe1\xe14kD\xb3\xd6*\x9eh^\x90Eq\xd4\xd6b\x1eI\xe7{T:\xb5oU%\xd8{M\n\xd2\x1d\xb9.b\xbc*\xb5\xe7\xa7\xad\x82\xa8\x9a\x8bex\xdd,b\xe3\x1b\xd8\xf3N\xedy\x07{l\x1a\x8d<\x89N\xf1b\x16,\xc7\xaf\xfe\x8a\xfa\xd8\\8\xb7bbv\xf2\x99\xcf\x96\xf5X[C\\\x85\x89\xecb\xdf\xbe`5\xa8WeF\xb4\xa3\xceK\x11)l\xc1\xfe\x1e\xbb\xbdW\x08Q\xfa\xf8\x81\xc9\x90\x81\xbeI\xae\xbe\xb5r\xaf\x1aLJhh\x97\xa28\xb0\xb1\xe6\x86N\"\x87\xe6^\xfdGy\x13\x8a\xb5+\xbd\xcdX\xbb\xa8U\xa5\xb5\x8f7\xa8\xa4)\xdc\x11\x12ik\x84h\xb2ALf\x14h\xd3\xf3\xb6 :\xa6\x01\x020%\x7f\xc4fR\x9f\x9e\xb3\x15\xaa\x939\x0fC\x13\xa3\x1dr\xd6)\xaa\xe0\xf50\x98\xbb\x81\xfc\x9d^\x0ci\xa7;O\x03r\x1c$\xc7\xe5>7.\xcfCw\xaf\xe5;\xb0u,r\xd2\x98\xf7?s \x82\x97\x9ez\x86\\/=P'\x16\xf4V\xfab#\x83T\x9a\"M'A\x189i\xb5\x9bkB\xb3W\x8c\x92(\x0c\x12\x94h^\x100f\x96\"\xb9\xee\xc8\x95[\x82\x9eXN\xa3\xa7u\xc6\xaa\x96,\xec\xf8#I\xedt\x9d\x80{\x0fOeJ<\\\x07n\xe8\xac}\x140\xb9]\xe3\xd8d\xf6X\xcf\xfeH\xaa\xce\xcf>1\x9f\x0f\xcd\xcf\x93UY\xef\xbe\x8e\xfc\xc9\xf36\xb78o\xf5?\xd1Zb<\xfd\xe3\x8f\xc2g\\o\xd3\xf5\xed\xf8\xc1\x0d\xb7\x01\xec]2\xca\x18\x05.\x8a\x91;+9\x80\x9b\x7fE\xa0\x93\xbf\xb9\xcd\xa1\x8f\xc75C-\x10\x9a\x91\xa7\x1c\xa8d\x9e\xd1\xef\xf7\xd1q\x9a\xe1\xf6\x9dT\x1aW\xa9\x85\x9dEThY\xc5t\xa2\x038\xad|g\xc9\xedg\x90\xdc>\x1c%\xf0h<_\xe8\xfd\x89\xe2\xbd'\x15\x89\x9a\xd6\x14\xa9\xf3\xe7h\x13}\xd8qd\xcc\x0d\xddy\x82d\xec\xce\x95\n1'T\xba:N\xd3\x8b\xc5BxbN\xb8\xd3\xaaeSW\xf3\x1b\x0e\xed|\xe4+\x0e\xdd\x93G!\xa9\x0ej6gl\x9b\xfd\xfa\x96\xb7TP\x15F1w\xa6\x0b\xee\xfb\xcc\x95\xef<\xa2)69\xb3\x9f\xca=\xce\xecwx\xe7\x93{\x98C\xab\xe0c\xb5\x8fV(H\n\xf1\xb3\xa0\x83z@\xfd\xa24\x06\xd5/\x89ae;\xd6\x8er\xcd\x15'\x18\x1at\xf3\x96\x86\x16\xban\xb1\xdc\xcf\xba\xddAr.y\xe5-W\xc5{\xc0\x9d\xd0\x05\xd6~2\xf4\xdf\xbb\xbe\xe7\xc4a\xfe\x80|iN\xe9!\xbb\xeaHN_g\xce\xe8\x0c\xd8\x13\xd6Y\x1f\xc8\xdcQ+\xd7y\x89\xf8\xc4S\xee)\xe5\xca\x138tJZj\xe8\x8ezc\x138\xed@n2\xf2\xc6&\x0d\xf8\xd1K=\x8c\xbd\xb5\xdf\xf9\x82\xe6g\xc4\x84/\xe9\x97L\xc4P\xb6\xd9\xd4\xeb\xc5\xed\x90\xdb\xdb+r \xc4+\x88\x88eT\x8f\\\xf3\x9bE6\x83\xdaG \x8ej\x83\xa7\x95\x98s\x1a\x96\xe0P\x13\x07\x93\x8bX'n\x9e\xbe^8i\xa7XQ\xba\xbf+\x1dLzr\x13\xbe\xe7\x92\xa7\x1a-\xb5\xe2\xb8\xb5U,,N\x88D[\x94T/`\xeat\x93a\xd6\xcb\xcf\xe6T\xa0\xe0\x85\xb9\xd5l\xd2\xf8p\xe5\xb3\xe5\x89J\xe2x\x7fq\xd1\"\x9bW\x9a1\xc1x\x8e\xa37\x91\xed\xbc_'\xa9\xb7\xd8W\xe3L\x8d}\xaa7\xfei\xce\xd0\xa2\xf4\xfaQ\xdbH.\xa6,3uD\x8f\xd1\x81\x1e\x03'\xf2,\xfdEs\x18\xb5\xce\xd9\x95\x8c\xa5\xa7O\xf3\x13\xa6g\xc2\x13\xa8T\xb1\xc0\x1fO\xe8\x11\x12-\xcc\xd1\"\x8c\x91 aI\xb5\x93\x8e\x9a\x88Dm5\xdb\x11G\xc8\xb5\xbcG\x01\x07r\xeb \xec<\x0e\xd3\xfc\x87\x8e\x91t\xbc`\xe1\x05^\x8a:\xd94n\xc7g\xc4%\xcf\xc9\xf1\x14\xcd{\x12\xb8\x04x\xb1\xf7i\x9d\x15\xff/\x0e\xbe\xe6\xf3b\x1aF\xe5\x9e\x039;\x0c\xd8{\xb1y\xa6\xa9\xf6\xf3S.\xa0\xff\xfb\xbf*\xf2\x07\xb4_\xc4\xb6\x8f\x92N\xd5\xb0C\x1a\x02\xf7\xa0\xf3R\xf4\xa3\x91\xae\xe3\x80t\x1a\xea\xf9\xbf\xff\xfd_\xcf\xccO\x14\xec\xe7&\xa5N\x93W\xc3\x9c\x02I7\xfb%\x0eq\xa2\xd9\x8e\x83\xa2\xb4\xda\xac)\x87dj\xf3g\x19#\x14<\x85g~\xf5\x83\xe0ED,\xdd!\xf2!K\xcc\xb1\x17<\xa0\xf8`\xe9/\x9a\x17\x86P\xba\x15 H1\xcbc\xb5\x9d\x95y8\xba\xab\xda\xdd \xcc\x93 u\xb8\xe1\x05\xdc\x92\xb2\x06\x9d\x81O\xcf3\xa7\x83\xce\xfaU\xb7\xba\x8b\xea\xeb\xdf$\xc7\xcf6(N\xbc0\xd0\xa2\xd8^\xfa\xf6\x81\xdc\xaa\xa8\x83K\xe4\xb3\xe9?\x9a\xea\x8f?|\x94$\xf6\x12==\x82:u\xde#\xe5&\x06\xfcn\x0f\xf9@\xd8\xcc\\\xa0E>q\xd8\xb4\xcb\xc5\xf4\x82\xc6\xfe\xdd\xf56\xc4\x8bE-\xcbY)\x9dmTb\xde\xc9\x171Mt\\m\x97\xba(\xfbS\x8b\xdb\x8fv\x9d~\x11\xf6\xb2\x8bN\xba\x9ay\x1a\xb4\x9d\xb5&\xaf'\xf5\xc8\x83\x9a\xec\x19A\x93?6h&\xfcH\xbc\x8c\xed\xbd|\x05\x9as\x89\xec\x18\x05\xe9s_e8a\n\x9d\xa7A\xf6WK|\xd1\xc5\xad~\xa9\x19\x8e\xee\x9f\xae\x97\xd8s\x8c\xdc\x7fU\xef\x9b\x08\xc2\xcc\xe5p\xb8En=[uM\x8e\x90y?\x00s\xb9\xc9b\x9aer\xd7\x9fx\x04\xdf&\xc7\x0e\x1c\x84\xd9Sa\x8b\x81> \x97_e\x01i\x12\xb9\n\x0b\x0e|u\xf6:]\x85\xb1\xf7\x88\xe8\xeb\xd8\x13z\xb4\xab\xb8T\x07=\xe5\xa7?y\xe1$\xf5\x16\x89\x86\x05\x0e\xed4\xff\xb6\x0cm>p/\x9e\xa1\xdf,\x0f\x0b\x0fc\xf8\xc8e\x86-w\xaa\x80\xfe\xd9\x1f\x8fu\xd4\x03\x92[T9\xc7Q\xcb\xb8D\xa7\x0d\x9f\xe4\x8aZ\xc0\xb8\xe8\xff\xc7\x0fN4\x83r\x1f\xbcxU\x15\xd7\xb13\xadv\xb8\x03\xe2\x0c\x07l\x0b\x18\xe4\xa4\xf9_F\xdd\x95Y\xec\"\xf3\x98\xb5\x83\xb9\x18P\x0e\x0e\xca\xa2\xd3\\3\x0f\x95s\xce}\x98\xb8\xf7Y\xf6B~w\x8ef\xcc\xa8V\x06-\x0f\x80\x13}E\xcf\xfe\xb4\x89-\xbc\xf5\x0bO*\x05\xeb\xa1\x9e\xfd\xa1X\xcf\xd7i\x1a\x06\xec\xdb}\xc2u\x9a\x0d.\xbc\x02\x0bx\xd7\x0b66\xf6\xdc\x03\xbfVIV\xf6\x03\xeat\xfbI\xc7\x98\xc0O\xdb\x0e\x03\xffu\x81\xb83Fe\xd0{\xc4\xc4\x9b\xa7\x18\xac\xea\x1e:\x7f\xbc\xa7\xcc\xd9\xca\x13\xbb\x8ba\xf6\xa7\xb3\x8e\xf1\x8f\xae\x9d\xda\xe7\x9eo/\xd1\xcbd\xb3\xfcy\xe7\xe3\xc9\xdcN\xd0\xa0\x7f\xf6\xdb\xaf7\xbdo\xfb\x8b\xfe\xfc\xcbn\xed<\xea\x9e\xfd\xeb\x9d\xee\\\x86\x9bw\xa6k\xba{\xcb\x9c\xed\xad\x8d\xe3;\x9b\xd9\xfdt;{5~t}\xc7\xbb\xfe\xf5[\xf4\xedw\xf7\xd5\xdc\\\x8e\xaf\xef\xa7\xcb\xd9\xab\xe9\xbe\xf8{\xfd\xf3\xf5\xab\xe9\xf2\xfar\xb7\xfd\xfa\xfb]x\xfd\xe6v|\xfd\xa0\xeff\xfb\xbe>\xfb\xb8\\\xde\xec\xfb\xfd\x9b\x8f\xf8\xfe\xdd\xfd\xb59\xfb\xa0\xafg\xf7_\xfb\xef\xee\x9d\xed\xfb\xfa\xe7\x07\xf3\xfd\xab\xe9\xf6\xfaU\x7f\x7f\xb3\xef\xefo\xee\x97\xeb\xd9\xbd\xb3\xcf0\xb3\x0f\xf9s\xeb\xe6\x1e'\xef>\xce\xd6\xef?N\xfb\xd7\x97\xb3\xf5\xfb\xcb\x9b\xfbw\x1fj|\x9aa\x9b\x9f\x1f\xcc\xf7\x1f\xa6\xdb\xf9+\xfd\xf1\xdd\xfd\xc3\xf6}\xfe\xdf\xe5\xe3\xd7}V\x9f\x93\xbe\xbb\xbf\xee\xdd\xd4?\x17u\xbc\xfb\x90\xd5\xf1\x90=\xdb\xe5|\xef\x97\xeb\x9b\xc7\xa9U\xfd\xfc\xfe\xa3\xd3\xbf\xbe\xbc\x98\xcd>N\x97\xb3\x8f\xaf\x93\xb2m\xe9l\xdf\xdf\xdd\\\xbe\x1e\\{\xa3\x9f\x7f+\xf4\xf4\xf3O\x9d<\xaf[\x9c\xfc*b\xceN\x10j1\x8a\x90\x9d\x92\xf3ZqS\x9f{#\x84<\xa3\xd9SK|f0\x95(\xa8Y\xb9G\x11\xb2\xe3,Z(F\xa4\xfcEm\xecC\xe6w\xc0\xdd\xff\xe9\xafq\xeaE\x18\xfd\xabJ\xfeZ\xd4\xc15\x0b\xf4V\x80\xd1\x9f\xde]\xe9\xbd\x07.\x89\xd8\xcbg\xd8\xa3\xee\x94 8\x19#\x9d\xbd\xe0\xa5\x94\xdd}\xea\x99\xa4\xfch\xe1?\xb3%\xf5/\xc8\xb7=\xfc\xaf3A\xe9\xc2\xc3HX\x18\xd9I\xb2\x0dcW\x08H\x90\x1d;+aq\xb6\x1e\xa3\x0b\xb3'v\x8clRE:\x91l\xa2\x1dh\xc4\x0c\x8f\xc4\x86\xa1;\xce\xfe\xb4\x0d\x8f\x8b\x85\x9a\x15\xff\xf3\xd5\xd5\xbct&\xdf\x8a\x91\x1b\xbb\xeaO\xd2V\xb4\x81\xea\xd6\xb4\x01\xcbV\xb5\xc1\xf2\xd6\x81\xa0\xaa\x95\x7f\xca0\x00d\x8ar6\x07C\x7fq6\xd6_\x00Y\xb6:\xa5k\xba?jF\xb4\xcbF]0\xe5K\x96\xff\xbb\xa7\xbf8\x1b\xb5\xf2\xeb\xc9\xd9U\xc5\xff6\xf5\x17g\x96\xfe\xe2l\xd8\xcaQ\xeb\xb7HX\x95\xff\xbb\xaf\xbf8\x1b\xb4\xf2kaWs#3k\xff\xab\xd1g\xd1(8\x1403\x07y|\xbc\xd9\x9a\xeaQ\xb7\xe8\xf9\xd5\x137l\x92\x01u\xcb\xbb(\x8e:-\x00\xccMUK\x8aw|\x1d\xf8\xd0\x17\xb8\x1fU\x0f\x11\xce:\xe6\x0f%\x13[r\xe4d\xc2\x9c\xd5\x88QN\"P\xc0\xb3\x9f\xd9rV\xc8y\x98\x87\xbb\x03\x19\xf5\x97+Y`mD\xeez\x08\x1eW*\xd5\xb3?peOx\xfd\x86\x80aD\x1dD\xef\xeb:\xf1\xd1\x8d\xc2\x0e\xe4y\xb9J\xf3,HU\x8bP\xba\xae\x16\x85\x98L\xaag\xff\xaa\x9b\xca/\xa5\xa5t?\xe7\x8a\xfa{\xb7xC\x8f\xf0\x8dJt.K#\xf7\xcb\xf27/Tn7 \xcf\x91\x8f\xca\xedn2\x0ef\xcf|\xd0[Q\x8c\xff\xa1Q\xf6G\xf4\xb2$=_\x02T i!\x97\x08\"\xde\xf1\x90\xf7\x83\xfa\xa7\x13U\xd7\xfe\xca_\x85WFKk;\xcf\x7fB.e0^Y\xf9\x1a\xf8/\xc0\"\xd8Y\xd9q\x82\xd2_\xd6\xe9B\x1b\x9d\xbd0_%\x9be'\xb7\xe0/?\x18\xfa\x0f\x9d\xc2\x82\xbf\xfc0\xfa\xa1\xb3\xf1\xd0\xf6\"\xdc\xfd\xf2\x83\xd9\x19v\x0c\xbd3\xfa\xa1\xb3\xf3q\x90\xfc\xf2\xc3*M\xa3\xf3\x97/\xb7\xdbmwkv\xc3x\xf9\xb2\xa7\xebzV\xc7\x0f/\xcc\xab\x17\xe6\xab\xc8NW\x9d\x85\x87\xf1/?\xbc\xe8\x99}\xa3?\xec_\xfd\x90?\xd0\xe25F\xbf\xfc\x806(\x08]\xf7\x87\x8e\xfb\xcb\x0f\xb3A\xd74\xcd\x8ea\xbd3;\x86\xd1\x1d\x0c\x86\xd8\xc8\x9eh\xd9\xbf\xfdN\xaf\xd3{W<\xce\xc40;\xa3\xac\xec\xf1\x87\x97EMY\xa5/\xcc\xab\xbf\xfc\xd4\xb1\xf4\x17\xcdZ\x93\xd6\xa8\xeb\xd98\\j\xeb\x1d\xf35\x9d \xf9\xa2U\xea\x1e\x8b^\x1dV\xaa^\x03,`\xd8\xe9f\xbaw\xe30\x02\xb8K\x19\x8an\xc1\x8c~\x12V\xe5\x87\xae\x8d\xa9z\xea-m\xae!\xd4\xfe63)\x16\xbf\x9a\xe5\xdcP\x7f\xf3\xc3\xe2\x86\xe2\x937\xf8\xf9\x05JuY\xafm\x81\"\xc8\x07\xe8\xd1\xaeS\x9c\x9c\x92\xbe\x04Z\x8ckUj\xb5\xb1&;\x06g\xf5\xc90\x82O*J\xd8\xd2\x17U\x80{6U\x9e\x9c\x9fk\x95V\xb8\xd2\xba\xe9K>#f\x81=h\x16\xd8O8\x9a\x04\xd5\xff\x94\xd7\xce\xd5\xb1J\xaf8/':*[:\x16\xe96'\x9d\xffQmM\xa7\xeb\xe00AZ\xfe\xf8\x88\x94\xfc\xf3e\x9bd\xc2\xad\xc8\x0f\x83\xf7\xd8c?\x03\xf2\x0d^\x8d\xe8\\\x1eN\xb4Ir\x82[\xf8\xa1+O\xef\x98\xfa\x91g\xea\x85\xb5t\xba\xc4}\xd9$\xb2\x99\x1b\x11<&u\xabc\xb9\xb6\x9e\xfd\x11\x9d\xcc\xe5(\xff\x9e\xba\xcc\x8dK\xf5w\x0f\xe5\xcc\xb44\\.1b\x8fh\xc1\x81\xd7@\x14x\x95\xa6\xccF\xa9N\xd7D\xbe\xc2\xebo\xb8\xe1]\xf8*`u\xe4\xa9\x08\xe8C\x0e$\x03~**\xcf\xf1\x8cu\x17-\x81\xf3=\xe5s\x8eN\x0bc/\xcf\xa6\xe9/\xb2(a\"*\x10\x1b\xaa\xeb\x84\x18\xdbQ\x82\\\xf1\xa9#\x81P\xf9c1\xe7\xf2\xac\x1et\x02\x8d\xdd\xc0\x12\\\xa1=*\xd2k\x0f\xe0\xaa`\xb0\xd7o\x82\xc1\xec\xe7:\x1a\xcc\x83\xea~\xa7\xd7'c\xbd,\x8c3\xf4\xce\xe0\xdd\xa8k\x8d;\xc3n\xdf\xe8\x18f\xd7\x18v\x8c\x1e\xd6\xfa]k\xd4\xe9w\xad\xf1;C\xef\x18#<\xd0\x06m\xf1\x1b\xb7W\x90\x05/\x90\x16\xef\xd7~\xa4\xa5a\xfe60`\xe1\";\x01\xc43\x10\xbfz\x8a:;\xa8u\xfb\\g\x03-\\\xdc\x87\x97\x1f\xe3$\xa0\xd5\xbb\xa5\x8aG+/H\x0f\xc4!\xbb\xfcG\xf6cc\x04T \xab\xd1\x1d!\x7f\xc2\x9f\xe3\xab\x86\xff\xae\x81\xfcN~\x14\x08\xf8\x1eo9<\xaa\x04od\xb85\x84\x1c\x9e\xb8D\x95\xad\xfb\x99\xc3F\xe5\xc9\xb2\x02\x9a\xd4W0ub\xf2\x97\xbdR\x9a\x97M\xc2\xbdz\xc1)1{\xeb\xfc\x0b\x0f`\x9a,\x96b\"7Qh\"\x7f\xef5\xcd\x9e \xd1\x9e\xe5-\x86'\x85Ap\xb2\xe8Y\xdf\x13.\x0f\"\x06:w\xbc\x86S\xd5\x13_\xa3\x0d\xf0;\xe9\xcd\xde\x1c\x9f\xe3\xde_\xce\x92[\xac\x07\x90\xddEo\xdd\xf6\x02\x0e\x0b05\xa8\x0d\x99\xf9\xeaQ\xda\x17*F\xc0e\x97\xfa\x82\xc3Q\x1f\x1c\x02\xde\xc6\xa7>\xd8\xb0\xdf\xeej\x91\xb5\xc5F\xc3\xe3\x98\xd1Q \xf1\xda\x90\xa3\xb8\xe4\xa7\x83\x18&\xad#\x12\xc7\xa6|\x90\x08\x0cLM\x0b\xa3\xfa\nVf\xab\xe6\x15;\x96B\x85\xf3pw\x90\x1e\xdai`T\xc2\x19\x8ca\x95\xcd\xcc\xbe\xcc\xa7\xae\xe4\x08\xb7\xe6Ni\xd5L\xba\xd0\x0b\x87,\xf1\xa4\xce\xf4Ty\xcf\xb4\xf4\xec\x0f\xc4\xac\xa9U\xdb\xdaq\xe0\x05K\x903\xb7|\xab^\xdcR\xddn\x17\x1fV\xe4_Q\x97\x8du\x7f\xcf\xfe)\xa7\xe5\xee<\xb6\x1d\xa4\xe5\xabZjF\x84\xceBEq\x18i\x81\xed\xb3\x87\xb8\xa9\x15I#\x1d@\x9c\xfbx\xa5\x18\xcb\x06\x10(X\xfb\xb2\x0b\x8f9(\x0b\xb1\xed\xf4 \x9e4\xba \x8a7(\x16\\\x1f{\xb6\x0bYd%\xa2\xebW\xf47f@\x06\x9dU\xbf[\x9d%\xaf\xee\x1e\x94\x01E\x8fUcE\x92\xdas\x8c:i\xf55\x16So\x01\xba\"\x9b\xd5\xd2eQ \xf8\x85\xdb u\x1f\x82H\x82i\xc4\x9dNy\xe5\xf0\xeb\xfaKWik\xa3\xdb\xe1^\x0eE\x1c|\x87I\xbbN\xe8G\xeb\xack\xadc\\\x0f\xcd\xfc\x91~\x10_\x1cC\x07\xf5E\x9c\xaa\x9d\x88&l\xce\xf5\x978\x9c\xdbX+\xea\xfa\x8f\xbe%*\x90\xb4\xd6S9\x00\x92g\x9c{\xd50$~=S\xf5\xaa/\xc0\xdd\xcb1C\xe0\xed\xb9\x03@/\xc3\xa12nZ\xb5>?\xaf~\xe0\x99\x94\xc3]\x9a\x9fLJ\xe3\xac?\xd4\xbcX\xafg?\xd6,`\xc0\xf8tu\"\xa5O\xbe\xe2\xab\xd8\x84\x82ZU\xde\xefN2IZ\x12dp\xa7|j\xda\xac\xec\\\x80B\xaa7\xb7)\xe9E\xa2\x91fl\xe9Q{\x0f\x03\xe2\xe6 \xf0V\x9f\x92m\xfe\xea\xc6\x9c\xed\x99\xact\xd5vz\x8cI%\x13\xd7b\xf2c\xf2\x8a\xeb\xb7\x9e\xda\xa9Bf\xae\xaa\xbe\x8c\x93\xb0/\x93\xe0\xce\x02\xc1\x1f\xd52\xf9\x17>Ix\xd2\x97\xcdJ\x86B\xfa?\xfe\xc8grI\xc4\xd1\xd7O\x99\x14\x99\n\xba1\xfa\xef\xb5\x17W\xaf\xc7\x11\x0d\x12\"*\xf86+\x1c\xe0i\x03\xfasCM\xca\xac\xe2\xf6\x97R\xf0\xf2e\xd0V1\n\x0e\xd8o\xae6\xb2\xa0]\x8a\x82\xc4\x0b\x99l2\x81\xf0\x14^\x9csLW\xe5?\xccBT&|m\xfe\x13+\x8d\x91+V\x81\x1f\xa5\xfb?66^\xa3?\xf8\xc4\xb5ID\x03\xe5\xda\x91\x8b\x0e\xb8\x17\x0cJ\xb9\x97\x93=\x15L\x0e\x8f\xe2\xd0\xad\xee%5\xc1<\xffjH\x8c\x80\xab\xee\xfc\xa6^\x1aFs\x9b\xfeb\x0dpE\xa7|s\x0eDZ\xfd\x17~\xcd`\x89\xb1O\xdb%{r\xbe\x07\x14\x98:U\x95\xe7\x06\xd9!U%WB\x8eb\xf9^3\xbbIR\x1c\xb9\x90\xaf_\xd8cD\x95\x84E\xca\x06\xd8\xcc\xe2#\xd1\xca\n\xf5+J\xd61\xae_\xd3\xf7d\xad\xe7m5\x9b\xd6\x9b\x93\xea \x01\xca/r\xa2\xc0e\xaevfO\xd8{\x9dy)\n\\\xf56\xb4\xcc$\xa5\x86\xf8seV\x7f\xb8\x80\xbeJV]h\x12\xdf*\x91\x8b\xd3-f!\xed\xf4\xb3WOw\xeb 8\x99\x0e\xa8\xe3p\xa76\xa9\xbcgG\xcf\x9aJ\x1d\x82\xf6\xd2<\xc0\x92\xbf\x19\xf2\x18\xa1\x8a\xa9\x9f\x93\xa3\xd7\xc8\xd1\x9b\x94\xff!\x94#t\x0b\xea\x04$\xb0\xee(\xcf\x0dR\xbf\x1f#<\xf5\xb4\xbc\xd5$\x89D\xc88\xae_\x1e\xf2\x90\x9c\xe1$\xae\xd5Q\x8b\xa8\xb2qG\x0e:^\xb0\x08\xeb;\x1d\xc0K(\xb3\xf2\xce*\xbf\xee\xd7\xf5m/`\x97urt\x87=\xc4\n\xc0\xb1w\xc6?\x8c\x80g\xc5z\x89\xe0w\xda+\x0f\x0b\x19\x0d\xa0\x02\xf6\xf3\xc8\xc5C\x13z\xd8\x87\x1eZ\xc7\xbf9\xa0\xa0,\xdenU\xad\x8f\x8b\xdbb\xea\xe9C\xdd:\xf2\xa4.\xf4\xee\xf7\\\x0e\x9b\xd5\xeeQ\x1b\x11-\xb6\x80\xae\xc9\x16\xb5\xd2\xef\xbc3\x16\x83\xb1\x03xay7\x9f\xdc\x9f\x02\x98u\xe7v\x824\xe0\xe80\xa9\x0b\x93:\xdbZ\xcf#G)Qh\xcc.\x9bF5\x07O{w/\xc1\x95\xff2\xaad\xc1`\xb5\x1c\xae(\xd6\xef\xe4\xcb\x9d{\xc5\xc0\xc2.\x8d\x93u\xc4\x1dd\xb5\x86\xcc\x01\xb7\xa1;\xea\x8f!\xf3\x92\x92\xe7\xaf\xdbST\x057T\xd9\xebt\xa5\xcd\xd3\xe0i\x01\x0e\xbd6\x7f\x8e\x17U\xc8\xa5,\xeeK\xbba\x80\x0e\xf2\x14rN\xf8\xa4\xa6)M\xd4\xcf\x1a\xbb\x912w\x88\xd7\x040)\xd0&4\xd1\x9a\x97\xe3\x01\x9c\xc0\xe4\xa1\xc1\xdeo(\xd2\x89-\xa7\xe6d\xdc\xe1M)a\x1dl8E3#v\xcd\xcbc\xffV\xb4\x13\x1d\xb7bH\xeb\x8f\x8e\xf3\xc1\xbe\x94\xae\xf5&\x9a\x84\xa0\x08\xa3\xd9\x1b\x90R)Q\x1c\x87q\xc2\x0e\xa8\xd4\x06\x18?Y=y0M\x9c0BIg\xd5{\xfa\x94\x9f\xb3\xd2\\\xb4\x90\x1f\x8b(\x1b\xaa1V\xe9\xc1\x0eXu$\xe2\x92\x9acc\xf4)b^\x80E>\xe5C\xd2\xea\xfaZ\xebd/\xf9&\x15-v\xf9;\xdb\nx\xd3\x0b$e\x8fl\x08\xdf=\x7f\x92]\x05U&\xc4\x8b\x9f\xc0M/\x86\xae\x882\x9f>P\x9e\xb4\x06S\x90\x8c\xd6a\x8f\xba\xac\xa44P+\xb99t\xc7\xb1\xf0\xb7\x03x9\xad\xbc\x971\x02\xeej\x8c~\x9a4\xaf\xc6\x02\xdfAV\x00\x0d\x9e\xd6hH\x0d\xfav\xe0\xff\xb4,\x94\x9d\xee\xf2kaq\xb7\no\x9aTZ\xe5\x1d\xf9J\xef\xff\xbc\xfc\xdb_;I\xb8\x8e\x1d4\xb3\xa3\xc8\x0b\x96\x9f\xee\xde\xfd\xd20\xea:I\xd2\xf5\xed\xe8o/\xff\x7f\x01\x00\x00\xff\xffPK\x07\x08_;\x94/\xe8Y\x00\x00\xa8X\x02\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0c\x00 \x00swagger.yamlUT\x05\x00\x01\x80Cm8\xec\xfd{{\xdc6\xb2/\n\xff\xefOQ[\xef\xfb\x8c\xec\x19\xb9u\xf1%\xb1\xf7\xf2:K\xbe%\x9e\xc4\x89\xc7\x963k\xcd\x9c\xd9m4\x89\xeef\xc4&\xda\x04(\xa9\x9d=\xdf\xfd<\x00H6\xd9\x8d+\xc9\x96\xe4\x04\xb5\xf7\xb3\xc6Q\x13@\xa1\x00T\x15\xeaW\x00\xe8%\x9a\xcdp\xfe\x14\xf6OFG\xfbw\x92lJ\x9e\xde\x01` K\xf1SxA\xe8\x82P\xf8\xf0\xf2\x07\xb8\x0f?\xe2\x19\x8aV\xf0\xfe\xd5\x873@Y\x0c\xb3\xf7\xef^\xc0w\x88\xe1K\xb4\x82\x98D\xf4\x0e@\x8ci\x94'K\x96\x90\xec)\xec\x9f\xca\x8f\x93\x8c\xe1|\x8a\"\x0cS\x92\x03e\x88a\xf8\\\xe0<\xc1\xf4\x00RY+\xcbQFQ\xc4\x0b\xd2\xfd;\x00\x178\xa7\xa2\x92\xe3\xd1\xd1\xe8\xe8\xce\x12\xb19\xe5\x8c\x1df$\xc6\xe3\x8aM\x80\x19f\xf2\x1f\x1bm\xbf\xc9\xa6$_ \xfe\x1f\x80&\xa4`\xc0\xe6\x18\"\x92e8b8\x06^MY\x8e\x16\x8b\x05\xcaWO\xe1l\x8ea\x99\x93%\xceY\x82)\x90\xa9\xbe\x0cC3Z\xb5\x0bp\x1f\xbeC \x12\x9d-\xff\xb6\xccI\\D\xb8\xf5\x0dZ.\xd3$\x12,\x1d\xfeJIV\xfe\x94c\xba$\x19m~\xbb\x7frt\xb4\xbf\xfe\xcf\x8d\xae\xfdDb,\xa4X\xd0\xc6'4\x9a\xe3\x05j\x16\x02`\xab%~\nd\xf2+\x8eX\xeb\x87u/\xdb\x05\xa0\xc9\xe4\xb8\x1a\x83\x8dOL\xc59M\x8a$\x8d\xc7m 5IrEY\x9ed3\xc5\x07Q\x9a\xe0\x8c\x8d3\xb4\xc0\xdd\xca\x93\xc5\"a\x9d\x8a\xceH\xa7b\x9dY\xa58\xbf\xc0y\xf7\xaej\x07\xc8Rvc\x0d5\xc9<\xb4I\xec\xdd\x16\xa7\x05\xc9\x92s\x9cw*\x0b\x80\xaf\xd0b\xc9\xb5\xd1\x05J\x93\x181\x92\xdf\xe7\x12S|\xbb\xcc #\x11I\xf53\x17\xac]\x14_\x9c,u?9\xf0\x0bM\x9e\xbf\xd1|2IIt>T#\xc7G\x9ao\xd0r\xb0\x8e\xa8\x9a\xc80\xbb$\xb9\xa6\x1b\xd6\xea\xeb\xaag(A\xf7OTKy\x8e\xb2\x0c\xa7\xdd\xf4H\x9aP\x86\xb31\x8a\xe3\xde\x13o\xff\xf8\xc9\xc9\xe8\xf8\xf1\xb7\xa3G\x8fG\xc7OO\x1e?~\xf4x\xdfw9\xb6T\xf8\x19\xceb\x9c/\x92\x8cU\x85zrx4:~4R\x0d\x11as\xdd\xc2kq\xb4 9\x86\xa4a4IV\xb1F\x0d\xbc)lKE\xf6e\xc6\xae\xc6I\x16\xe3\xab\xa1\xa6\xe8>\xc9T\xc3\xc2)_Fb&`\xaa\xe5\xc6\xbb5\x16-\x9f\x1e\x1e\x1e\x8d\xc4\xff\x13\xb3\xe2\x9bu\xf3\xfb\x8fL&\xfc5JR\x1c\x03#\xc2\x0fZ \x85\xbc6\xe9\x87t\x95EI6\x93\xc5\x1b\x1eN\xed\xa9|\x90\x1f\x94\xbe\x14\x99\x9a\\\x93\xc6\\{\xff\xee\xc5\x1d\x057\xdfa\x06\x89tv\x04# \x85\xa8\xc8s\x9c\xb1t\x05t\x95\xf1\x96.\x136\x97\x93I|S\xcd\x89\xdd\xfb9\x8d\x9e\xee\xc2\xdfi\x89\xbaI\xb2\xae !)F\x99\xe3\xb0~\x10\xf6\\\xfa\xbb\x19J\x01\xe79\xc9\xf9\x80\nmO\x0fS\xc40e\xfaa\xe5\x03\xc1GA~'m\x84\xcf\xa8\xeer4\xce\xd4|\xc1pC!\xaa\x1d/0C\xba\xd1\xd0h\x1b\xb3\xa6\x99c\x14\x9b}\x8f^J,\x9a\xa3$\x1b\xeb\x1c#\xf0V+\x91\xd8r\xcd\x8b\x89\xd2\"\x82\xe8P2\x9bk\x1c\\\xa8\xdb\xcb\x8a\xc5\x04\xe7\xf6\xf6\x8e5\x9f\xb0D\xe7\x94\x82w\x9f\xf6O\x8e\x8e\xbf\xb9\x7f|r\xff\xc1\xd1\xd9\xd1\xa3\xa7\x8f\x1e<=z2:\xf9\xf6\x9b\xbf\x1c\x1d?=:\xd2\xe9\xec\xacX\x8c\xd9\x95U_\xbbvT\xe7#\xa5\x88\xb2\xb1\x9c{\xf6Q4L\x15p\x9a.\x9c\xe6\x88\xceM\xbf;\x8a\x17\x9a\xbd{\xf5\xea\xd1\xeb\x07\x0f\x8f\x1e\x1e=x\xf8\xe2\xd1\xc9\xc3GG\xc7\x8fO\x9e<\x7f\xf4\xf8\xd5\xd1\xcb\x97/\x1e|\xfb\xfa\xf4\xe5\xe3G\xc7\xaf\x8f\x1e\x1aj[\xa2\x9c\x19\xf9v\x14\x028\x0b\x82\x13#\x0c\xa5\xb6\x8f\x1c\xc7\xba\"\xeb\x98Wd\x1f \xf0\x19\x0d\x18pD\x84\\\x86\x9c\xff\x0f\x1e\x99\x16\x80\xdc5\x8f\xcd\x02q\x12\xc4P\x02\x88\x11C\xb7\x89\x9fz\xf7Io\x13W\x19\xbeb\xe3\xdb\xc9Z\xc4\xfd\x8b\x8c\x16\xb7\x8a)\xb4\\\xde&v\xc4\xda\xcb1-Rv\xab\xc4\x84/\x92\x18g\x11\xbeM\xce/\xbf?^\x9c}\xfck\xfe\xbex\xfb\xf6\x1f\x17\xa7\xa7\x9f\xcf\x9e\xfc\xf2\xebO\xb3wG\xefO\x0f\xcf^.\x1f\x17\x87ONN?\xe7\xff\x98\xfe\xf7_?,\x9f\xff\xed\xd9\xb3\xba\xe1n\xb9v\xfbU\xb2\xddo\xd2\x1c\xfc\xbb\xacB\x97o\x87\xa4\xd2\x00\xc4\xff\x19\xe1\x9c\xa1$+-I\xf9\xf9\xd0\xa9wK\x94\xa3\x05f8o}\x9cdOa\x89\xd8\xbc\xd1_q.\xa0\xcd\x0bl\x8a\xe1\xb9`~\xeb\x9b\x1c\x7f.\x92\x1c\xc7O\x81\xe5E3U^\xb3\x88\xae\xeeo\x85\xe1;e\x086dI\x978J\xa6I\xb4\xcd\\\xc8\x17t\xd8\xcb\xb8\x862\x02JSQ@i\xec*~H\x13\xe4\xe0D8 \x01\x9c\x05\x01\xee.\x83\xd3XWd\x1d\xf3\x8a\xec#\x01>\xa3\x01\x03\x8eH@i\x02J\xe3\xc0U@i\xfc\x98\n(\x8d\x13_\x01\xa5 (\x8d\xcd\xda\xdd*\x94&\xe4\x0b\xd6d\xed,8u\x18\xdc\x9c3''\x04l\xc3W\x91\xdd!s\x924\x0c \xed\x90/\x18v\xa2%\x85\x9d\xe8\xee\x97[\x93\xc2NTC\xce\xa3\x01\x03\x8eH\xd8\x89\x86\x9d\xa8\x03Wa'\xea\xc7T\xd8\x89:\xf1\x15v\xa2a'j\xb3v\xb7j'\x1a\xf2\x05U\xe5{\xedl\x82O\x1c|b-9\x8f\x06\x0c8\"!_p\x93B\xbe\xe0M4\x1c\xf2\x05[d7\x14\x92\x1cW\x15x\xac,pVX^\x83\x01\x03*\xad59\x18\x13I\x1e\x82\x02Oa\x81\xbby\x91\xe41]*r65\x92\\\xc7\x0f\xfc\xc7\x10\x06\x1f\xc7\xdf\x7f\xbe\xe0CSv\xda\x9bLX\x9c\xcdl\xb4\xfd\x87G\x0f\xf5\x85\xde\xe3\xcfE}\xe3]Y\x14b\x82i\xb6\xdf\xa8\xa2S\x9e\xe2\xe1:\xf4\x81\x99\xf7\xd5\x80ua\xa0xWy\x8a\x9d\x12\x00[\x8c\x01\xda\xbe\xcfp\xc7\xe9\x80:\x9bn\x98\xd4\xeb\x81\xd0\x15S\xfbdZ_\xcc\xa2\x04mJ\xcf\xe2i9,\xcf\xee\x01\x82\x8d\xf0\xc0\x05J9\xaf\xc7\x8f\xafVx\xb1\xc4\x8b\xe5\xf2\xc9\xc9\xd5\x93\xf9\xea\xcb\x97'\x97\xf9l\xfa\xe4a\xfe\xf8\xd7'\xf3G\xd3\x93\xcb\x87\xd9I\xaa\xacsYL\xc6\xe7x\xd5\xa37.J\xa6f7\"\x19]\x16\x93\xe3/\xd1\xafq\x81\x97\x9f\x8f.\x8a\x93/\xb3\xf3\xd9\xf9\xc3'x\x8a\x8e\xb2\xcf\x97_\xb2\x18e\x9f\x1f-\x1eF\xdf,\xd1\x83\xe2!Z~y8;\xc9\x9f\xcc\xe8\xf2\xf3\xec\xf1\xecID\x1f\x9c?\x89\x8a\xa9\xb2\xad\x0b\xc2\x92l6^\x92K\x1d0\xe7\xd7\xa5\xfd\xe3#\x9dgT\x07\x8d\x96yB\xf2\x84\x0d\"\xc2\x8d\xf6\xba\xa9\xae\xfd\x0d\xdd\xe5\x9ci\xbd\xa1\x1cB\xbau\xdft\xeb-m\xdbH\xbb\x0e\xdaVP\xd0\xb6\x0dr\xe8M\xd0\xb6\xbb\xd3\xb6\xc3;\xa8\xcf\xab\xf3\x16\xa5o\x9a\x11\x06\xe8\x02%)\x9a\xa4k=\xd4U\xcd\xb3+\xae\xdc\x11\x9d+T{\x8c\x979\x8e\x10\xdbPz\x1b\x1a\xff\xec\n&+\xb1O*\x7f\xdf\xd2\xee\x8dw_\xee(\x98{\x8fY\x9e\xe0\x0b\x0c\xa8\xf9D\x0c\x144\xc9f\x900*\xea\x1e\x95%wh\x15\xd6=\xd8b\xf1\xecj\xf3g\x8b9\xd8\x9a<\x0ds\xf0\xfc\xc5\xf3W'G\xaf\xbe}\xf9\xf0\xf17\x8f\xbe}\xfe\xe4\xf1\xe9\xabG\xdf~\xfb\xe0\xf97ON\xbe}\xf4\xed\xc9\x93\xc7\xa7/\x8e\x1e\xbfzt\xfc\xf0\xc1\xa3\x87O\x8e^?\x7f\xf9\xe2\xf4\xd5\xc9\xa3\xd3oN\x9e?x\xf1\xe2\x9b\xc7\xcf\xefT\x1c\xf8Z\x93+y\xc5;\x93o\xe0\\$\\{mtk \xd3\xa1\xde5\x1b\xd7\x95Y)\xbd<\xfa\xf6\xd1\xf1\x83o_>9~\xf0\xe4\xc9\x83'\xc7ON\x9e~}\xf2\xe2\xe5\xab\xa3\x97\x0f\xbe9\xfd\xf6\x9b\x17\xaf\x8e\x1e?|\xf8\xea\xe4\xf8\x9b\x17\xcf_?x\xfe\xf0\xc9\xe3G\x8f7\xf93\x1a5M<\xa1\xe6\xf0\xc1\xe3o7~d\x8a\xe0\xa6\xd1h\x99M\xd6\x82*n\xab\x07\x8b\xf5\x04[\xec\xd8\xa2\xd6\xa6\xd8\x08\x15\xf5Bkf\xc8\x1a\x147\xaa[\xb4 Ef\xcd*\xbb]q\xf5\x18gda\xfe\xc4\xa9\xef\x15\xd5\xd3\x8f2t\xaez\x1agM6qI\xea\xd2\xf6\xfe#\xa5q]\xe0E\xb7w\x95,\x11+\xeb\x90\xd8\x07\xc3!&\xe6$\x08\x17\xa7 \xe0\xed\xab\x8f/\xde\xfc\xed\xe5\xd1\xc9\x94\xbe|\x97\xa3o\xdf\xb2\xc9{\xbaz~|\xf9\xcd\xe4\xf3\xd9\xdbG\x8f\xfe^\x1c?\xf8\xf6\xcb\xdf&\xaf\xa3\xbf_=\xfc\xcb\x8b\xd7\xab\xd373\xfc\xe8\xef?\xbd\x9b\xfe\xf0\xa6\xb8\xf8\xf2\xfc\x1f\x8f\x9f\xbc]}\xfe\x9e~~\xf9\xed\x87\xe37\x97\xc9\xab\xe5_\x92\x8f\x93\xc7\xbf|\x88Y\xba\x9c\xfd\xcf3M\xd3\x16\x9f\xd0A\x90\xe0$L\xa8\xaa2\xce\x17'yBS\xa6\xac\xde\x00\x1e\xbe+&?\xe0\xd5\x07\x1c-O\x1e=>\xd7%\x80\x82\xdcf\x14\x83srz\xf1\xe5\xe8\xe1/s\xf6\xc3_\xe7\xdf\x9e\xbex\xf1\xcb\x97\xf4\xcd\xb7\xe8\x8c\xd0\xefVG\xc9\xf9\xeb\xff\xfe\xe1\xcd/\xdf\xff\xed\xc1\xaf?\xbc\xcd \xfd^\xa7\xac\xa2\x88/\xbf\xb14#\xb61q\x9dvz\xd8\x87\xe2\xcf\x85\x1e\xe8\x87\x01Z\x929@\x83\x9a\xb8\x94\x18M\x9c\x96\xd7\x19\xa2\xe3K\x94q\x9f\xb4K\xf16\x94u\xa4\xd9+\xf0F\n:D\x13\x8f\x1f\x99\xe5\xa6N\xd6,%\xdb\xfa\\'\xe5?\xb5yzV&\x0b\xda\x02SG\x8f\x97WW\x17\xfbjyx\xd5\xe1$\xb8%\x9aa\x9d\\\xde\xa1\x19\xde\xde\xabI\x89&\x19\xc33[<\xd6\xdct\x9a,\x12m\x90\xf8-\xbaJ\x16\xc5\xa2l\x1e\xc8T\xeaeX\xe2|\x93\xe7\xc1\x18bW\xa3E\x92mE{u\xf5\xb7\xf8m\xe9&\x92\xc9\xd8n9u\xca\xb8\xd2,\xc7\x88\xf1\xbe\xe4\x80?\x17(\x056O\xa8T\xe3j\xaeO\x1e9\xb3\x8d\xaev\xc6v\x8a)\xe5\xaa\"sg\xfc[a\xf8\xcb\xdf\xbc\xc3(\xa7i\n\xec\x8a\xc2\x02\xb1h\xce5G+\x9e\"5N\xa3\xec@\x11\x15y\xe2\"R\xef\xebd}\xb6\xb0\xc5\xa6/=he|\xd2k=\xde\x1eUj\xd2A\xba\xd5(\x96t\xd7\xca\x1el&\x8c(\xb3zM\xee\xdb\xae\xf0\x0dS\x8e\x8a\x83\xaf\xe6\xb2\xb3\x1d8\xfe&\xc9\x9c\x9cg\x1c\x15I\x86\x88\x9c$U\\\xae\xfce\x18OY\x1b\xa9\x93ds\xe6%Y#SN\xc3h\x88\xe0Ir\xe828v\x1bl1=IN\\\x83g\xc0\xca&Mp\x93(\xb8KD\x92\xab\\$9E\xff$9K\xa9\"\x8fH\xa0$7\xf1J\xea\xce\x8d&6(I\x1f!\x94\xe4\xd4\xacC,\xcfyP]\x87\xd3\xa9Mp\xed\x81$\x17\x8d[\xd1\x0dE\x14%Y\xe3\x8a\x92\x1cE\x0e\x1eb\x87\xaaZ\xebW^\x92\x87\xdeQGI\xd6\xe8FE]y\x1b \x0e)\xc95\x1a)\xc9\x83]\x87\xc8\xa4${|R\xd2\x90m\xeb\"\x96\x92\x1c\xe6\xab\xcb<\xd5\xc60%9\xf5\xc7\x16\xcf\x94\xe4T\x95[lS\x929\xc2)\xc9\xbfQ]\xb4S\x92>\xe6Y\xfe\xeed\xde\x1dL\xbb\xc3\xf0Jr\x19dI\x0eJ\xd0Y`\xe0\xae?\x945\xba\xe5\x98P\x19\x94\xdc\xd8\x8fv\x8b\xaf\x02, \xadW\x93O\x04\xf5yNP\x1c!*\xd2\xd6\x92Y\x86c`Ww\x14M+?\x04F\x00\xc1\xb4H\xd3\xe6\xeb\xf7\x11\xc9h\xb1p\x8b\xa4\x0e\x11t\x9d\x90X\x15\xd5\xa89\xd6Is\xc3\xb8\x9f\xcd1\xef\xd2\xa2\xa0\x0c&x\xdd\xcd\x0f,>\xbb\x1a\x89\x9fi\xb1\\\x92\x9c\xe1\x18&\xb58\x16$\xc6\x14\x92,J\x8b\xb8\xed\xeb}\xda\x13\xe1\x90\xbdOws\xcc\x8a<\x034e8\xe7m\xc8sh\xf7\x0e\xe0\xd3\x1e]eQ\xf3\x0b\x9c\xc3\x8b9\x8e\xce\xcf\xae\xee\x01jD/e\x85\xa8\xfdy.\",\xe8\x12\xad\xee\x8d\x1a_js_\x86\x8au\x84l\x8a\x90M\xb1AN\xfb)\x87\xbeW\xe4\xb1\x87\xb2\x89KR\x97\xb6C6E\xc8\xa6\xb0\xeeq\x9c\xe4 \xbd\xf75\x0e\x1e\x89?'\x03\xecb\\\xf7/N\xccY\xf7\x0d.\xbb\x95\xbe-q\x8b\xae3p\x9aZ\xeb\xda\x84\xc5/\x7f\xf6F.\xce\xae\xd6~E\x92\xcd\xcaMR\xe3\xeb\x81\xecw\xc4\x1d\x8c\xf1\xc0V\x1el2\xb7m\x92l\xcd\xdavv\xb6\xf2I6\xedf\x05\xba\xa6\xd6\x84\x9c\x14\xb7E\xa8\x9b\x9c\xca\x13\xc5b\xf2\x89\xff\xab\x19)\xfe\x7fLs\x0f\x1e\xad\xb1\xca\xcd\x0f\xca\xe9\x05\xc7G\xeao\xc4\x14\x12\xff\xd7k\xb8\xef\xc3\xbeZ;*~\x88q\x9a\\\xe0<\xac\xf6\xb0\xda\x05\xfdqV\xbb\xea\xc6\xc2\xdf\xfbj\xefs\xae\xa3\xe3\x0d\x07\xe6\xa3\x1a\x9b\x0b\xaa[|K\x9c\x82\x92\xe7\xf9d\xd9f\xb8k\x80<\xc2W\xa2\xea\x8d\xf3M\x8c\x88\xcc\x91\xd3E\x92\x11\xb8Lr\x0cS\x92/\xea\x947](IY\xd7\xdd2\x96Dr\xc8\x08\xbb\x07\xd3\x9c,\xe0\xaf\x1f~\xfe\x89\xb72A\x14?~x\xbf:\xaf(\x1a\xac\xab\xa38OP\x9a|\xc11LV\x0cW\xac\xdf\x92\x18\x9bn \xcbX\x1a#\xe5)\xcc\xc6w!8e[\x91!8e\xef\xa7${o%\x85\xe0\x14\xd8\x1b \xc1\xa9\x10\x9c\n\xc1)\x97iw\x13\xc1)\xff`\x924\xc1\x97H\x1c\x10\x880\xa5\xd3\"MW\x10\xe3\xf2Z\x84,\x86\x1cW^G\xa3\x96\x9d\xdba\x9b#*\x1e1T\xf8D\xf77}!q\x8a\x80\x89~\xae\x85b\x04_\x1bBY\xa0T\xfas\x8d\xcew;\xa4/\xbcS)VYv`\xef\xf4%Vx\x94\xc2\x83\xec\xe2\x9f*kS\xfa\xa7^~)\xf7\xf5\xb8C[~\xf0\xd5\xf8\xa7r\xdc\x1a\xdf\xdd\x9c\x7fj[\x17Jk\xf7\xe1\xe2y\xf2\xdf\xf8\xe1\x0f\xef>'\xbf\xfe\xcf?\xc8\x0f\xaf_\x7f\xff\xea\xcb_\xbf\x8dN\xbe\x7fw:\xbd8y\xf5\xfac\xf4f~u\xb4z\x87f\x97\xaf\xe6g\xab\xa3\x8bw\xa7\x7f\xf9\xee\xbb\xf9\x8bW4\xfd\xe1\xbf\xd1\xc3\xd3\xe9Q\xf1\xfc/\x8b\xe9\x879y\xfbb\xf6\xcb\x97\xf8\xbb\xd7\xf9?\xde\xbfy\xf9\xf6\xec\xf4\xf2\xd5\xeco\x7f\xbb\xfc+y[6;\xb4\n\x1a^\xb6Jg\xdd\xe4\x90Z2\xbe\x95#\xa2t\xce{\xec0\xb4\x0e\xb9\xc5T\x98_\xe0\xec\xf1\xc9\xb7\xd9yz\x95\x16_V\x17\xdf~y\xf2\xeb\xe7_\xa3E\xa4\xacjc}JY\x97\x93\x88\xe4\xf0\x03^\xf1\xce\x8b\xe1\xe2\x8bf\x863\x9c#\xb6\x11\x10P\xd4\xdc9\xae\xdc\xe8\xdd\xde\x07\x9c1\xb8H\x10\xbc\x10\xfd\x84_\xc8\n\xcdp\x0e\xff\xef\xc7\xa3\xa3\xa3\xe3\xd7\x8f\xbf=\xdaS\xd4`~%\xd3\xbdy\xd9\xe8\xfd\xef\x8b\x89\xe2\xbb\xaf\xca+:\xd6\xdc\x8a\xd3\xbbb\xf3\x9d;(\xfe\xb5\xa0l\x81\xcd\xdbN\xa7\x86\x8eG'\xaaV\xa6X\xe7\xc0\x87-\xad\x82|\xdb\xd3`F4Y\x14)b\xc6y9!$\xc5H\xa5\x19\x1a\xf5OQJ\xd5\xfd1\x9d\xbcX\xd3+\xca\x12\xee\xb7\xf3\xd9&\xa2\xbb\x1ba\xca\x08e\x19\x11\xc73\n\x8a\xe3\xcd\xdbl\xd6\x14\x91\xec\xd7\"\x93\x85\xc4e\x14\x95\x9a\x1b\x93,]\xdd\xdb(\xa5\x93\xb3i\xca\xed\xea\xae\x00\xe3\x14s\x18n\x87\xa9e\x9eV>m4\xa6\x93\xda#?1\xdfvZ\x07\x06e\\\xb0\x1a\xa4\x10\x19\x94\xd4U\xa1\x87\xc8`\x8b\xaeE\x8d\x86\xc8`\x88\x0c\x86\xc8 \\\xa3\x0f\xec\x1c\x19\xacN\xdc\xe6\xf2%\xa1u\xa9N\xa1\x0d\x19\xd9h\\{\xe4\x11\x03<\xe3\xa5\xc4)\xd2t\x05dZ\xc62\xe4\xd5wr\x97S\x96\x18&\x1a\xe8\x1d%\xfb\xf9\x87\xc6/\x03Y^\xe3\x05Q\x9dl\xef\x1f\xce\xb7\xb2MU]\xda\xec~c\xae\x1e\xfe&z\x9fdb\x96T\xf1\xeb\xed\x98\x95\"b%#;\xcd\xe2w\x94l\xbc I\xa6\xfeL\x13\xceQ\x8a\xa3\x11\x9d*\x10#\x0b\xf1C\x8f5\x86\x80&\xd9,\xc5b\xb1\xa9\xd8\xbb\xddkmC:n\x9aN\xd7\xd5\xee\x13 \x15l\xae\x08\xe7\xf6\x87A\x1a\xf1\xbf\xfa\x02A\x93&<-\xea\x99\xe91:;\x8d\xcd6>\xbb\xe6P\xac\xf7\xa4;UK\x9d\x0f\xc8\x96\xe4a@\x1b\xa0t\xb0\x0c\xdaP\xe3\x14\xf5p\x8c\x07pm\x8c\xcf\x14Y\xca\nKo*\x19vd-\xf2mO\x13\xd8Z\x16\x934\x89n\xf7\xe6\xa1\xdf\x06\xa0\x83;\xed\xe1\xf7\xe2&\xa4\xc7\xc74\xc9f\x871N\xf1L<\x1f\xc6\x9d\x8a\xf2\xdf\xa7q\x9c\xff\xbb\xfa)!\x19\xed\xe2a4\xea\xba\xa3d\xee\xb9\x84\xc0N\xa3\xe8\xb4\x824\xa6\xf0\xb2*W\x97\xe9\xe8o\xf8\xab`O\xc3\x87\xd2\x14\x1a\"\x92(&Zw\xbc,\xb3i\xf3>H\xc1\x97\x7f\xf10{\xde\xf6\xc1\xd1)\xd950^\x8a\xc3\xf4\xe0\xb9qY8=\x99n\xac\x81\xceQ\xae^\xf3\xc6bez\x81\xbe\xdc\x1fq\xef\xe2\xe4\xb2\xd6\x83\xbe\xe5UusY\xdb\x99\x05\xeb\x14\x82b\xb2HXc\x11V\x8b\xca/\xb3x\xab\xfc\x16_gs\x0cKD\xe9%\xc9c\xae\xa4\x9a>/#\x90\xe3\x05\xb9\xc0\xeb,\xee\x1f\xde~pZy^nW@\xb9\x03\xca\xbdA\x03\xb8\xc1\xd7\x17\xe1\x0b(\xf7\x16\x85\xcd\x80\xfe3\xdbf\xe0\x0f\x8er;\xb8UFA\xb7\xfa\xe6\xf8\xc6\xee\xa6\xc6\x8f\xf1\xf2\xfc\xd1\xc3\xa8@\xbf\xce\xce\xbf`\xf4\xf8\xcbrv\xfe\xf9\xc1c\x96\xfdz\x19\x7f\xb9x\x88\xa6\xd1\x83\xf8\xe4\x9b\x8dj\x1c\xbc\xb9]3\xde\xebY\xe0\xb5\xb30\xa8!6,S\xeb\x82\xb1.M;\x84\xecR{c!\x9a\xf74\xbb\xc9\xc8\xdc\xd5\xf6\xc7\xcb \x0b\x99\x07\xad\xa2\xc1\xb4\xb5\xc8\xb7\xbd\x90y\x102\x0f\xda\x142\x0fj\xba\xae}I\xff\xe0\x06\xdf\xa3\xae\xdd\x82*3\xa1\x1dk\xd8\x7fxt\xac\xaf\xfa\x07\xbcZ\xc7\x17\x12\n\x979q\x0e\xf1\xeaa>\xbf\x10\xef\xe1o\xb5k&~\xfbC\x84|\x0d\xbdiI\xc3\xd8\x9b\x9f\x97\xdcO\x97\x1f\x96]\xaa\x0b\x0f\xd3\xa5\x0e\x1e\xabG0\xfbo\x05\xceW2k\xa5\xc8s\x9c5#j0\xc1\xec\x12\xe3\xac\x19\xd8\x16\xa7=\xd0V\x1fo}\xa0\xdb\xcb\xd3\xeb\xb7\xc1\xea\xb7\xcb\xd1\xc5\xab\x0dE\xb4\xb1\xea\x1eN\xc0\xd7\xb5'\xe9\xa5\xbe\xeb\xf1\x1a(`\xed\xa4|\x8bl\"\x9fC\x1d\x07\xa4\xcd\x8a\xb4\xd5\xc2\n\x98\x9b\xa0\xdb\x8e\xb9%Y\xc2\x12\x94\x8e\xad \x9a\xa6|\xd7rQ\x8e\xc5(\x8e\xf5\xef\x1d\xca\xf2\xba\xdba\x17I6f\xc9\xc2\xd0\xf2\xd65\x98\xdd\xf4\xce\xba|'\x15c\xc6\xc4P\xa6\\1\xd5\n\x08\x00YM\x01 S\xb5\xe8\xde\xbb\x00\x90\x0d\xb4\x11\x0d\x00\xd9\x16\x85(\xa2\xfe\xb3\x00\x90\x05\x80lG\x8cw\x087\xac\xa9\xc3\xe6\xb5\xa5C\x8e\x02\xca\x14P\xa6V\xd1`\x1fZ\xe4\xdb^@\x99\x02\xca\xd4\xa6\x802\xd5t]\xce\xfd0aJ\xd5\x96\xfe\xab\xc2\x9b\x94!\xcf\x80<\xb5{\xf3GC\x9e\xf4\xe1\xdd\x00>u\xd9\x03\xf4\xdbA\xe0\x8c\xe5J\xf3\xd3\xc3\x01\xed|P\xc2!\x8a\x0c.\x8a\xb8oy\x87\xa82\xb8\xd4c\n.\x83\xae\x82\x1e\x06ch\\\xab\xd6\xf19n\xacS\xb3\xbe\xfe\xcc\x17y\xdd\xd0\x86\xc2\xbe\xa3l\xde[Y\xb7c\x14\n)\xeaYY\xaf\x96i^\x1eP\xd7\xf1\xf3\x0bJ\x1b\xfc|\xc8\xa3_\x0c\xcav\x10\x96\x18\xf1`\xe8%e=\x18\xf2P\xdb\x15&\xd7\x9a\x04pw\x9a\xa4\x0c\xe70Y\xc9N\xc9 A\xab\xc0\xcc\xad\xd7\xd0\x8e\x98\xdc\xff?\xc7\xd3\xa7\xb0\xff\xff;\x8c\xf1T\xa8'\xee\xc1\xbcoH\xa2\xffE\x0f\x0e\x8eTK\xf4\x7f\x08\x87\xc9\xebn\xd9\x12\x04k\xcd\xd0j\xa6\xed\x02\xfbr\xb9\x06u \xdf \xc0\\\x01\xe6\xda\xa0\xafj'\x1c`\xae-\naL\xfdg\x01\xe6\xfa\xbd\xc3\\4\x8f*\xe6o\x84\xff\x0e!\x8e5\xad\xbb\x11Svsc\xd0\xab\x0f\x7f0\xc4.\xdcUk5\x19]\xcdq\xc0\xf2Zt-F0`y\x01\xcb\x0bX\x1e\\\xe3\x0ef\x18,\xaf\x19\x9a\xd0`x\xbb\x0b\x1f\xd5n\xcb\x1f#v\xe4\x11\xdb\\CRk\x19\x01\x9b#\xd6\x02\xa1\x12\n\x13\x92q\x07\xad\x8e\xd0\xfe^\xe2\x9b\x06\xb5fRh\xa4\x84\";\x1f\x18\xe8\xe6\x07\x0f\xeb K\x1f\x15g\xb4\xa0\xe3e1\xd1\xa8~K7l\x96\xac\xe6\x93\xb7\xb5,&\xc7_\xa2_\xe3\x02/?\x1f]\x14'_f\xe7\xb3\xf3\x87O\xf0\x14\x1de\x9f/\xbfd1\xca>?Z<\x8c\xbeY\xa2\x07\xc5C\xb4\xfc\xf2pv\x92?\x99\xd1\xe5\xe7\xd9\xe3\xd9\x93\x88>8\x7f\x12\x15\xd3\xadv~EI\x8a\x95A'\xf3\x8e\x982\xc4\n\xc3\xd8\xe9\x0eM0r\x8e\xd5WbZv>\xd5\xee\xb5\xe3\x15m\xcd)\xa3-\xdb\x19}\\\x90,9\xd7\xbf4n5\x19I\x8c3\x960\xed\xf3\xf1\xd6\n.\xf1\x84&\xba\xd8\x86Cy\x8a\xa3\"O\xd8j\x1c\x91\x8c\xa1\xa8;n\x19c\x86\x92\xd4\xe2\x9ek\xcasEi=\x8dc_M*\xa3.\xaaN2\x96\xa31\xbb\x1a\x0b\x17B=\\\xe6\xd9\xdbh\xe5h\xeb\xc7u\xca\xcan\xfa\xb0\xae\xdf|\xea\xc8\xa1\xf6\xe3'\xdf\x1c\xdd?:\xbe\x7ft|vt\xf4T\xfc\xff\x7fl7\x18\x91\xc5\"\xa1t7K&\xd7\x86\xe2\xac\xfd\x00\x9b\xa48-\xd0\xd5\xf8:\xda\x88\xe6(\x9b\xe1\x9d7U,c\xc4\xb0\x7fJ@\x9b\\g@Gou]\xfe:\x1c\xd2\x90\x0d\xd6\xee\x8d{6\xd8F6\xc0\xb0\xbd\xe9\xe0W\xf9{\xdd\x8d|\x95\xdf\x85\xcb\xed\x15)\xb4{\xd0\xce\xae\x90\xab\xf7\xdc\x7f\x8c\xd7d\xf7\x9c\x8d\xec\x9b\xbd\xe6\xdd\xfb\xcc:\x8f\xd9\xe4/\xeb\xbce\x93\xb7\xa1\xf3\x94\x0d\xc2\xb1{\xc9\xc6\xc2\x06\x0f\xd9h\xec\xcd\xa6\xde\xe8\x1b[l\x96\xd9/\xb6\x146\xfa\xc4\x96\xb2n\xfe\xb0\xa5\x12\xa3/l(k\xf4\x83\xdd\xd6\xc6\xb6\x1b\xe1\xe8\x01\x9b\xfd_\xad\xf7k\xf7}\xbb\xf2m\xf3z\x1d\xebu\xf1xM\xfen\x8f\x05\xa0w\x0d\xad\x1e\x9b\xc5-4\xfb\xb8C\xd4n\xf5n\xfb6b\xf5k=\x1a\xd8\x89O\xbb\xd3\xe4\xd8\xb53+\xeb\xf0p\x84\x1a\xd6\xaf\xca\xb2\\\xb3\x19\xa1,\xe6\xff\xc4t\x04\xcfW\x10\xe3)*R\x06 \x83\x1c\xb3\"\xcf(\x90,\x9579IW\xa9\xaek\xcd\xd1\xa8\xfc\x9b>\x0d\xae\x9d\x91Z\xb9\xa1\xd2\xd65\xfe\xac\x19AS\xb2\xc4\xd9\x1c7z\xc3Y,\xab\x1d\xc1\xdb\x82\x8a\xdc\x08\x9c\xb09\xcea_\xf2\xbf\x7f\x00\xfbRS\x88\x7f\x93\xb6\xea\xda\xaf\x95\xc8\xfe\xa8\xf1C\xc3u\xdd\x90\x82\xa9\x7fK4\xc3\xban\xc8\xdb-f\x18$<1\xda\x92\xc2\xb6bm0q\xec\xd4~\x9a,\x12fb`\x81\xae\x92E\xb1(y\xe0\x1e\xbe\x08\xdf\xc2\x12\xe7\x82\xb9\x8e\\\xddz\x1f:\x84\xad\xad\xae\xb7\x8b\xf3m\xedF\x08[o\x97\xd3n\xb5l\x0e\xb9\xb5\x82\x10\xb66\x94ws\xd3\x1d*\na\xeb\x10\xb6\x16d[2\xbb\x8e\xf3\x86\xb0\xb5\x82\\g@7o|_\xe1\x8e\xf7\x8f-\xbbGc\x7f\x1fgs\xf9^\xa2\xf9\xbedy\xe1b\xf9\n\xeb\xef\xfb\x14\xae\xdd7t6\xf2\xae~a\xff\x11^\x93\xdd'4\xb2\x1f\x02\xb2Z\xe1\xd8\xfd?c\xe1\x10\x90\xad\xc9\xcd\xd3\xb3T\x12\x02\xb2\x0d\xea\xca\xb7\xcd\x9fs\xac\xd7\xc5\x97\x0b\x01\xd9\x169\xf9m}\x1b\xb1zl\x1e\x0d\x0c\x11\x90\x1d:\xf6\xea\xe2\xed\xf5{\xd0\xf6\x8f\xe3\xf9\x19\x1e\xb7\xfd\xea\x1c\xbe\xddF\x0f\x1dN\xdfYV\xd6\xfa\xfcX\xd7\x1a:\x86\xa0\xac\xf7kw\xdeK\xff\xde\x1f\xb7\xbd\x11\xd55\xd0[\x01\x7f<%f|7 \xa8\xb3\x16\xdd\x06u\xe6p\xe3S?\xbd\xa6)\xe7p\xc3\x93\xd9g\xdf\xd5\xbb\x01C\xab\x9bZ\xdb, I\x9fvYV\xcd\x97\x82\xf8\x8e\x1bW7\xfe\x975\x03\xaf\xf9kYQ^\x11\xa1\x94\x10\x8a\xc7\x1d\"\x06\x12\x88\xeeR2\xc9\xa6\xa9\x9c\x98)\xa2\xcc\x7fsV\x97\xf7*%6\x0b\xa2\xc1\xf5fm\x9cc\x8a\xfdv\x9c\xcb\x1c_\x8c\xcb\xbe{\x85J\xfaN\xed\x0d\x8b\xd8o\x82\xcb9]U)\xcfM\xd2\xdf\xe5\xfc^O6q\xe1\x84\xdc\x95:\x0e\xd9f\x0d\x0bt\xd5\xb5d\xe27Yg\x84\xdb\x0b1\xcb\xbc\xca\xf5\x08y\xf0=\xfbf\x96\xcfvQ\xb5\xa9\x10\x11\"\x8d\x93<\xe8bH\x11\x9d\xf3\xd5@\x93Y\xc6{\x99dS\xd2mA\xf0\x1a\x04\x0c\xc05\xfd,\xb9\xc0\xd9\xc6 \xc9;\n\xc6\xb6\n*\x8bx,\x91\xad\xb5Vv\xb0\xaa\xc93\xa3\xc9\x94\xf1\xf3n\x9d\xed\xd3\xf8D7\xaa\x1a7x\xe8,\xa0\xb7\x96\x0c\xa0\x818}t\xa7\xfav7\x1ai\xb7>,e(gV'N\xeb|\xc6\xf8jL\xa6S\xa5\xa1\xb3\x14\x96\x80\xc5\xb8\xc8X\x92z\x17\xe66\x16\xc7\xe3IJ\xa2sjO \xd8\xd4\x10\x9e\x9e\xe4\xb2\x98\xa4I\x04\xe7x%n*\"Y\xed\xc2m\xad\xcf\xae\xeag\x7f\xad\x7f\x8c\xdbZ.\xb5j\x1f\xebq\xc3\xdfGQ\x10P)\xf5\xad\x9d\\\x8b\xc7\x0f8\x8b[\x9711\x02\x85\xa5\x82\xdd\\V\xd3I\x85i&\x8ej\xd7\xae\xdf,\x98#\x00\x06\xcd\xb0\x15I\x18f+\x0f\xa2k\xad>\xec\xefoq+\x87\xf9y\xfbbF\xc5]\x8dZ\xee\x07r\x8cvr\xe9\xa2\xf2j 0\xe8\xc9\x8a\x1c\xae\xca\xd1F\xbf\x94W\x05\x81\xad#`\xed\x0c\x98\xae\x0d\x02;_`\x0d\xeb\xd9\xe5\x026\xd9\x80K?%\xd9{+\xc9z\xa5\x10\xb8\xf5\xbd\"\x87\xe8gE6qI\xea\xd2\xb6\xe6\xae\xbd\xce\xf7h:]\x0e\xd4k\xeaYZ\x00;\x8f\x92lY\xb0\x92n\xe0*\"N\xc6\xeb\x88\xc0E\x90\xe0$L\xa8\xaa2\xce\x17'yBS\xa6\xdeW\x14\x81\xfd\x9a\"\xe8\xc4I\xcf\xeb\x8a\xc0\xf1\xca\"pe\xce\x9aqg\xbb\xbe\x08z\xb4\xe4\xed\xe8\x87\x1b\xf4\xac\xcb(\xdc\xa0g^\x8b\x8ef\xcen\xe2|\xdb\x0b7\xe8]\xab\xd9\n7\xe8\xb9\xb6\xde\xd3$\xb9\x98#+C\x163ts7\xe8m\xedk\x81\xe4\xf5\xa6l]W\xa7H\xc5:P1$lP\xd6\xd9\xd8\xd2\x97El!\x00\xf7`\x82\xb7\xddv\x0c\xd0\xf9Ygt5\xc6\x17I\xcc\xe7\xc5\x18y\xa2\x05\\\xe5\xad\xa3^\x97I\x16\x93K\xaf\n\x16I6.+Y\xe2\xbcK\x0d1)&)\x16\x95\x8c% 0\x8e\x8b\xbc\x03bF.3\x96,p\xafJ\xc4\xac\x19Os\x19\xa6\x1a7x\xebW\x8dd\xcd\xb1\x8e\x8e\xabhF.\x0e\xf94!\x14U\xb9\xb8>\x01\xbd\xfa\xc9\x8e\xaa\x8e;\x8a\xc6U\x81<\xaa)x=\x01\xbc\xef\xc8\x05\x17G\x16U\x1dR\x87\xf0Z\xbd\xd8\xb0\xcf\xb5\x86+D\x14\xf6\xd3^\xd5\x911\x1f\x9e\xbdO\x10\xa1\x0c&\x18>\xed1|\xc5\xf6>\x1d\xb4J\x7f\xda\xab[,\xf1\xba\xbdO\x07\xf0i\x8f\x92)\xbbD9\x1e\x17\xcbY\x8eb\xbc\xf7\xa9Q\xac\x04@\x08e\xe3\xba\xb1\xc9\xef3\xc8\x16^6\xb1\xf5.\xbcl2\x90W\x13^6\xd9\xa2\xb0%\xd5\x7ff\x8b\xb6\xfe\xc1_6a K]]\x16I\xcd\xde\xf8\x94k\xd9[\xaf\x92\xad\xcd\xe3\x95\n\xa6&T\x7f\xfaGSekP\xba\x9d\x1b\xec\xf6$K\x95z\x19\xe3%\xa1\x896\xd3\xabS\xd0\xed\x0f\x97M\xee\xbd9\x0bAU\xebl\xe8jKCP\xb5E\xd7b\xc1BP5\x04UCP\x15\xaeq\xfb\xe1\x1dT\xad\xfc\x9e!^\x1d\xf1\n\x96\xca\xab%\xea`\xd1\x1dE;\x1b\x9f\xb4\xee\xa0\x10\xbe\xe3V\\u\xf7A\x1c}\xda\xe6\x05a\xad4\xcbVW\xc4\x8f\n\xcfM\xf72\xb3f\xd0M\xed\x97\x1e\x1b\xd1\xf2P\x7f\xb0[>\xb6. 4m0\xea\xe9'K\x1d4\x03at\x1d\xf4*Y\x1f/q\x9e\x90x;\xfcuAX\x92\xcd\xd6?\x8b\x88\x18\xa5\xb8\xfcw\x8e\xb9\"\xe4\xff\xd5\xb5\xcb\xde\x9e\x9cc\x98}\xb7y\xb0\xf5\xa6F\x1d\xa1\x91\xb5j\xefES\xef\xbd<6.\xbee-{0\xd7\xd2\xb6\x8b\xe04\xe5\xa7I\xc6\x9bFi\xba\x1a\xe7\x98\x16\xa9!\xfb\xb7\xf3Nf\x7f\x85\xe9\xbe\xd9\x93t\xdce\x1c\x8d\x8ejR\xa7\x8b\xa0 eHu\x8cB\xd2\xc0\xad\xedg\xe4\xba:\x96\x911W\xff\xe3\x0b\xcc4\x81\xcfA\x9b\x94\xe0B\xb7+\xce\x18a\xa6\xcd\xb4m\xeba\xd8x\x0c\xe0\xe2Y\xb6\x1c\x0e\"t\xdcn\xd86\x1b~-)Ce\xa5\x05\x90\x99\xff^C\xe5\xe6'}\x96\xbe\xc8\xa6\xc3\xd1\xd5Uj#e\x12tn\x1d\xb5\xf2\x81\xcd\xbe[#\x05\xeb\x13j\xb2\xb2\xb5\x81\xdd\xc6\x106\x0e\xeat\xaa\xe3\xab\x01\xd8\xe4\xf5\xbd\xba\x8eq\xe7W\xbe6!\xee J2*\x0e*\xd5\x05ZU\xc9\xc2\xdbY\xf5\x01Js\xdc\xa5\x04(MQC\x80\xd2$\x05(-\x04\"\xdb\xe4\xdb^\x80\xd2\x86\x81\xd2Zg\xbc\xdeqS\x08/\x84\xe9\xdb\xf8\xae+\xe4\xd6\xaa\xff\xa3\xb8\x9b\x0c\x16\xe8Ju\xfcP\xd2\xd7\x86\xa5\x05\x0c\xadI>m(\x96p\xe9u\xdd\x0ea\xd2bB\x97H\x7f\x0e\xc3\xa7\xaf\xb4u[D\x9b\x0c\x07}|\x9ax\x8b\xae~\xd1-*IT\xfbb\x00x\xb6\xb5\xaf\xde\xb3\x1b#\xfa\x8a\xd1\xf0\x0e\xb8q\x07\xbf\xa9F\x03\x8e\x1apT%9Lfp\xd3w`\xd5y\xd0\xa1\xbd\x80\xa3\x06\x1c\xb5M\x01G\xad\xe9\xba\xf6\x9e7\x8a\xa3\xeeoD\x07\x7f\xab\xfe\xf9&\xae^+\xf0\x06Z\xcd9\xf5\x9b\xdf\xc0d\x05Ie)w\x1f\xb8\xd3\x0cL\x19V\xab;\xdf\xf8\xa9\xe3M\x15\xfb'\x9dS\xb3\x1c\x01=/\xc7\xc1\x88\xcf\xc9\xfa4\xf7\xd5{o\xe6\xban\xd2,\x98\x9cKI\xf3\x85\xfcjg\xc7\x01\x8b\xeba\xc8\x0c(\x9c\x8f\x8e\xb0\x00UF\xfcm\xc0v\xf4\xc8\xdb\x80\x8d\xd81\xb7\x81\x1a3\xa2m\x866,H[\x0fw\xbc\xf3.\xf1k\xdfr;`j\xca\x16<-f\xb2V\xec\xc3\xdb\xcb\xc3*h\xd4\xd5pV\xe5\xef(\x18\x92_L\xc5K\xe5\xb8\xfe\xb2\x8c\xe9m\xd8\xdb`Eo\xd0\x8a\x1a\x0c\x94s8\xd1sV\xbfy\xb9\xcbY]\xea9\xdauVW\xe5\xf5\xb3\xba\xfa\x82\xbb\x82[\x93'Lf\x8f\xc9\xbc\xdb\x1c/\xbd\x050\x99\xbc\x90Z\xd2$3td\xd4/\x96\x16\xea\x9cK\xef\x92\xddp\x8b\xde\xc8\x85\xa7\x96\xebm\xbb\xfd2]^Jq\x96\xefu\x01#\x1d\xce\x8a\xc7\xf6:nUV\x8bf\x96\xb4\xfa\xa9\x1a\x8f\xdd*K\x97\x8b\x1bEBL\x95\xba\x1b\xf2a6is\xa5\x86|\x98&\x85|\x18I\xeb\xdaC>\xcc\x16\x05@I\xff\x99\xd9\xa9\xf9\xc3\xe7\xc3\x18<3\x8bG\xe7\xef\x95\xf5\xf4\xc9$\xe9&\x86i\x8d\x84\xc8\x16\xeew \xdbq\x8b\xe7\xe5\x87\x84t\x81V\xd1\xa0\xdd[\xe4\xdb^H\x17\x08\xe9\x02m\xaa\xe5\x16\xd2\x05\xae\xcb5\xef\x9e.\x90\xc4|\x83V\xc5$\xda\xc9\x03\x0f\x8f\x8e\xf55\xfd\x80W\xb0D\x94^\x92<\x86\x84\xc2eN\x9a\xc1\xeaN\xc1\x18\xa7\x90\xf3\xe1o\xb5\xeb\xd49\x1b\xa1\xac\xe1\x8e\x82\xb7\xd6\x07\xed\xe03\xa0,\xd6\x9eb\xfe#\x07b\\8+\x1f\x071\x1d\x02\xd7\x9f#\xef\xc8e\xe9\xee\xda^\x049z\xbc\xbc\xba\xba\xb8S5u\x0b\\\xb4\xe0k7\xc8\xa7\x0d\x857\xd2\x15\x9e\xfb\x8a6h}t\xbe\xeaM\xcf\x87G\x0f\xf5\xd5\xbd&E\x16CF6\x94\xe8Nt\xfe\x05a\xb83\xc6(\xee\xbc0 \x8c\xf2\xf7\xd6\xad\x1e\xb7\nk\xbca\xc5\xbe+E\xb8[8R\x0c\xaa^\x0bj\xd6l\x1f\x88\x8d\xc8\xee\xbb\x16\xf3^\xab\xeb\x92\x9d\xd6\x97\x1f\xc0\xf5\x0b\x91G\xb0=1\xad\x0be\xb1\x00cY\x17\x99\xed\xd8\xf8\xd6\xbd\xccr\xb6\xed}\x82i\x82\xd3x}C\xcd\nSy\xd7LF\xb6\xaf\xa7i&\xcf\xed}\x12n\xec\xa7\xbd2=Pw'3\x1f\xd2\x00\x9amQ\x00\xcd\x02h\xe6S{\x00\xcd\xb6(\x84U\xf5\x9f\x05\xd0\xcc\x08\x9ai\xbc\xbb\xdb\xb6\x1f\x93\xa4s\x0c\x8d\xdc\xae'\xc0\n\xd3]\xbb\xe2^\x968\xc0F\xad\xa2A\xbf\xb5\xc8\xb7\xbd\x00\x1b\x05\xd8\xa8M\x016\xaa\xe9\xba\x9c\xd3\xbe\xb0\x91\xd8\xf6\xdff\xccH\xc4\x0f\x0f\x7f\x13nCg\xb0\x88\x97\xbe\xa3\xe0h\xfd\xab.\x86\x08%f\xa4\xba}\xf7\x8f\x1c\xf1p\xe1\xaczL^sq\xb1\xfa\xce\xe3\x8e\xdc}\xb58\x91\xbf?\xdc\x15\x0d\xf1rf;+\x93\xceXDc\x8d\xeeD\x91\x88\xa3\xc0\xfe\n\xe4;\xdc|\x14n\x9f\x82\xa8\x07\xe4\x91b@\xed\xe7\x1aY\xb2P\xea\x99\x86\x1f\xf1\x1df\xd4\xaf\xc2\x11\xbc\x996N\x07ri\xaf\x85\xbb\xc4Y\x9cd\xb3\xf5Y\xab\xbb\xc9\x08\x97Wa\xc3~y\xd8\xe1\x9d\xb8\xd4z\xff\x1e$\x0cr\xcc\x8a<\xa3\x802\xc0\x8b%[\xc9\xe6\xeb\xfa$\x1b\xa3\xf2\xbf\xff\xa8\x1a\xeeVh\x06\xcd\x11s\xc7\xbd\xa7\xe9\x80\xb4\xf6X\xf9\x00u\xab\x8f\x92\x0fP\xb1\xf9\xf8x\xaf\x06\xbc\x95\xdd\xbad'=%\xd5T\xbd\x1e\x0e[G\xce=t\x93t_f\xf5J\xabs^\xb6.\x19\xd6i#\x87\x1aF\xe2^\xac\x05\xba\x1a\xb7\xaf\xd0\x87\"\xe3\xfa\x06\xe5\xb8\x19\x1a\xcaPF(\x8eH\x16\xd3](\x91[\xb10\x17I\x16n h\x91O\x1b\xaa\xb0\xc1\xd6\xe4\xea\xbc\xc0\xbf}\xfc\xf0\xc8\x7f\x89\xff\x07as\x9c\x8f\xb9i\xf8O\xbe\xab\xc9\x087\xfa\xcdk\xbb\xb9I\xc1\x94\xb5\xad\x87\xa3g\xa3]\x95C\xe9\x0fa\xc2\x93l\xd6_\x81H_\xc4\xac>\\\x0b\xdd\xeeu\xaf_Sl\x9ec:'i\xf7Ix4z\xa45c=\xcd\xd7\x83\x07\x0f5\x15\xaf\x07d\xbc\xc4\x19J\x99\"T\xe4\xdc\xcc\xd1\xf1\xedZB\x9a)6\xd4\x02\x92\xd7\x94\xf4_>\xb2\x9e\x1e\xe6w\xab\x02i}[\x8f\xd3\xfcN\x0c\xafqK\xbc\xeem\xe7I|\x1b-\x81n~t\x9d\xc7\xfb\x87q\xc2\x051)\xc4\x80\xc68\xc53qC\xeb\xe1o\xf5\xbfO\xe38\xff\xf7a\x8e/Q\x1eW\xfb\x89\xed\xbd\xd8\xfd\xed\xbdQ\x95\xcb\xdb\xa8\xe7\x8e\x92\xbb2\xces\x1aE\xa7U\xee\xc3\x14^V\xe5\xea2\x9a]\x99r8\x15\x91\x9do.\x9ft}e\xf8\xb8\x8c_\xa9?s\xf2u[\x92s\xc4\xab%m\xcc\xfa\x0b\x94r\xae\xada\xcd\x93\xcb\x87\xd9I\xaa\xacS\n\xd9\xdc\x19=\x10j\x81B\xadR\x97d\x93\xbd$+ \xea${I\x0e;\x1aIvX\xb4K\xab\x8a=\x8e\xd00\xb7c\xaa\x7f\xbd\xdbE\xb7@M\xad:\xb7C\xd1\x9d\xac\xac_\xfe\xed\xdf\x136\x8fstY\xeb\xfe\x9a\x9d}\xda\xd0\xfa\x95\xf6\xbb\xa3`\xa4[\x15\x0ej\x7f7\xe9\xbc\xfag.72M\xa5GQ\xf7\xae\xf2\xa46\xbe\xf2s\x16Cvi\xc8.\xdd\xa0\xaf\n\xc0\x0f\xd9\xa5[\x14\xb2\xaf\xf4\x9f\x99\\\x0c\xf8\xe3f\x97\xde\x8a\xfdLH\xafl\x15\x0d\x0b\xbcE\xbe\xed\x85\xf4\xca\x90^\xd9\xa6Zn!\xbd\xf2\xba\xbc\xb3!\xf7\x9e7\x90W\xe9\x19\x1d>\xfc\xad\x8e\x82\x89\xbf\x7f\xc5\xd1b\x9f<@moZ\xd20\xf6\xe6\xe7%\xf7I\xe4\x87e\x97\xea\xc2\xc3t\xa9C(\xd0#\x0e^\xbd\xde\xb2\x15\\\xb8\xa3\xe8s\xf5\xb1\x8cXo\x97\x91\xf1\xec\xcd\x00\xb6Cx\xc2#\xe6\xb0+\x87o\xb7G\xdb\xb5N\x89E%Y\x9c\x10\xdb\x05\xde\xf6z\xbf\xe2(\x9b\xdb\x9c\xdd\xfe^\x1dL+1\x9fjno.b\x87I\x1cbl\x15\x85\x18\x9b\xaaE\xf7\xde\x85\x18\xdb@^\\\x88\xb1mQ\xd8\x82\xeb?\x0b1\xb6\x10c\x1b\xd4\xd4uU5!\xc6\xd6\xa2kY\xe0!\xc6\x16bl!\xc6\x06\xd7\xe8\x9d\xf5\xdfy\xca\xbb\x10\xeb\x9d\xdc\x8d\x1fgv\x0d\xbb]\x96\xbb\xb4*\xe5\xec+\x8e\xb7\xed4;\xb3\xca\x9e\xac\xe4\x85\xd2\x8d\x98\x83-\x1b\xb3\x91l\xb9o\xa8m\x04g\xf3\x84\xf2y\xc0\x0bU\x93\xab\xe16]\xce\x93h.~,(\xce\xe12IS\xc8q\x84\x93\x0b\xdc`\x14\xa6E\xe6\x93\x95\xe3\x11\x06\xd8\x95\x0f\xa6X\xa8\xbeI\x8c\x9bS\xc2\xf3\xc2\x9d\x8eK\xbf\xe7Z\xf5\x0b:\xbd\xc7\xcb\x14E\xb8\xc3\x9cl\x96t\x9c\x8c\xa5C\x9f\xe1K \x19\x1e\xb9O\xa7\x10\x80\xaa(\x04\xa0T-\xba\xf7.\x04\xa0\x06rqB\x00j\x8b\xc2\xfeT\xffY\x08@\x19\xaf\x10\xdct\x9buVA#g_\xc7\x06\xfa:7\xbbr\xdaB\xe0,\x04\xcen\x8fb\n\x81\xb3\x108\x0b\x813\xb8F\xaf\xb2G\xe0\x8c\xe4\xb5\x15\xbd}\x89ju\xd2\xc5\x00 i\x7f\x9c\x14\xae_*f\xa1)\xcc\xe6\xbd\x86w\x14\x9d\x97\xb9\\\",\xa1)%\x8e1\xf7\xc8\x87\xf1\x881\xdc\nG\x89\x94\xf3\xe0\xe6\xbc\xcb\x0e\xf3dM\x14\xa7\xd3\xf1\x84d\xf1\xf8V\x1d\xaf\xfez\xcf\x9cJ\xba@\xe98\"\x8bEBi\xa2\xbfD1\xc8t\x93\xd42u3W\xb5\xb2\x19(\xd8\xeblf\x0eI\xc1(C\xe2f\xc5q\xe7\x9b3\xfe8\xa6\xe75\xde0\x1f\x0d\xf9\xd5\x11\xee\xaf\xdf\x8c\x84\xdc\xe0\xdd\xaf\xbc\xb0\xda\xac\xab\xedEm\x86\xc4\xcd\xd4\xdc\xe0\xdf\xdf\xbe\x14\xc0\xb8\xde4.`\xe4\\s]\xa1\x07.\x15V\xb0m\xa5]\xcf\n\xbe\x11\xdb\xeb\x07\xb4\xd6\xe8!\x9f\x955+\xfb\xd4\xe9\xd2\x8c\xcd2\x9b\xd3\x98O\xed\xf5L\xdf\xac\xd3a\"\x07\x80\xb5\xa2\x00\xb0\xaaZt\xef]\x00X\x07\n\x85\x05\x80u\x8b\x02\x8e\xa1\xff,\x00\xac!\xc3\x7fPS\xd7U\xd5\x04\xa0\xb2E\xd7\xb2\xc0\x03P\x19\x80\xca\x00T\xc25zgC\xee>\xaf\x1d\x9cl\x87\xae\xf8\xc6\xb1\xc8\x12\xb6\x1a/ )\xef\xf3\xf4\x8c\xdd\x88\xe2\xc0\x8bo_\x04\xed\xb0\xfb\xf4\xd8R\xee\xca\x9e\x870\xca0\x93is\xcb\xef1\x91\xb6B\xee_\xddT\xb2\x04#\x96\xe2\xb5\x1d\x9c\x8fu\x17\x18\x1bFmB\xb2\x82\xf6\xaaa\xbd\xcc\x19\xbar,\xd9qFp\x03\x94d\xb3>\x93\xe1\xad\xac\x02\x16$.Rl\x9f\n\xfc\xfb\xdb=\x05\xb8P\xc6\x1aE`\x18\xb6$\x9b\xa6\x82\xef\xb1\xd8\xdbDs\x94\xcd\xb4^\x9b\xa5\x86\x85\xf3\xc0o\x95\xf4|ZkFP* {\xec7I')\x89\xce\xe9x\x89\xf3\xf1\n#\xd7G\x04{N\xd3\xba\x9b\xde\xb3\xf4E\xf9\xa6]Y\xd3Z`\xd2\xb1\xba\xe5su\x17\xb2DYV\xa0\xf4\xfe2'\x17\x89\x88E\xf7\x96\xa9\xac\x11\xd65\xfe\xe1d+\x03\xc6\x87\xa8`\xf3\xc3\x8b\xe3 f\xe8\xf8\xb0t\x96\xb7\xc5[\xcb\xf1\xb4\xfcb\xfd\xcdV#\xf8\x9e\\\xe2\x0b\x9c\x1fpAh+\xfb\xf8\xfeGZ\x9en\xe6U\xb19\xd67,\x94\x11\x86Os\xc6\x96\x9f\x0e\xe4\xff\xd2O\x07@r\xc8H\xf9\xeb\x81\x98\x8d\x11\xca\xcaW\x87[o\xccnU\x88\x19\x14K@\xa2\xef\x86v\xa5\xa6\x17\xa2Y\xa0%\x95SKp\xceH\xb5\xb2 \xc6\xd3$K\x98\xb0}H\xf7\xcc\n\xc0\x94\xa4)\xb9\xa4O\x0dc\xfbgx3]\xf7\x88O\x0baVc\x1c\xd7\x9d\xe6\x7fD\x94\x16\x0b\x1c\x8fL\x15\x9df\xf0\xfd\xd9\xd9;\xf8\xee\xd5\x19\x90\xacZ\x82r\x8d\xad\x12\x9c\xc6\x80\xb4\xa5\xff\xb9\xb9,\xceVK\xfc\xaf\x7f\xfeK[\xa0\x0cT\xf1\xf9 \xe7\x1b\xc8\\^1B\xa5\x9d\x17\xcf\xffr\x9392q\xbd\xb6\xff\xf2\xb91\xc4e\x86c.\xee\x08E\\\xb7\x10r^,\xcbG\x83\xa9\xd8\xb8\xc5\x06\xfd$\xe6\x95\xeeg1 \x05\x8fs$\x8f\xd3/\x1ak(\x96\x8b\x08U]\xe2\xff\xbe I\x0c(\xd3O,(\x19\x14\xea#\xc7S\x92\xe3\x83\xaa\x02^/b\xc9$I\x13\xb6\x82\x0c\xe3XL\xa3 \x06\xa1\xf2\xf2\x0bCOD_\xe4\xe6B\x14\x12kv\x04w?R\x0c\x178\xe7\x8e\x17\x97\x12\x9f\x9e\\g\xc9\xf9\x89243\xf5~\x92ct\xceuPY\xf1\xe8\x9e~F\xfdD\x18~\n\x8c\xdb\x90i \xeb \xd1\x8fRw\x95\xcfG\xa7+@\x17(I\xd1$5\xaaK>\x1f\xc9t\x9aD J-\xb6lRL!\xc7\xdc\x12\xe1\x03\x91I\x91\xb0\xaaQ\x81@MI\xbe^\x97\xda\xaa&x\x96d\x19\xef\xece\xc2\xe6\x06\xe3\xb2Z\xe2\x91\x9c\xffh\x99\xd0QD\x16&m\xfcA\xacT\n\xe2\x0d7\xae(\xb2M-\x05w9\x7f\xdc\xaf\x13o_\xcb\xa5\xbdy\xbepM\x8bd6g01(%\xd1i\x81\xa8%\x8be\x8a\xb9\x91\x95{\x1a\xba\xc4Q2M\"\xa0x\x812\x96DT\xbd\xd4\x8cAe\x07\x17H\xae\xed\xa70Y1\xdd\xecr\xf5\x92\xderu4\xc1\xf5{wk\x07g\xcb\x8f)\x8d;\x9a\x90\x0b\xfd\x9c.EP.\x05U\xf7]8\xfbt\x9a\xad>U\xee\x91x\xb7\x1c\xe5\x93\x84\xe5|\x11\xeb9TVU\xd9\x08\x94\x92r\xea\x01R\x0f-\xd7\xce\xc2\xd0H\x0e'm\xb7p\xc3\xfd\xab\xbd:\xcd\xd4|W-\x9c4\x99\x08\xb6K;B\x81\x16\xcb%\xc9\x85\x05_\xa2\xe8\xfc\xb0\xc8\xf8\xffp\xbb-\xe7\x85z\x05\x95\x86^\xef\xd8\x90)\x14L*\xb6J=\x88\\\x17\x14\xc7\x89\xd4\x155\xfe\xcb\x99gs\"\xb3\xfat\xea\x99\xf3#\x87P\xdd\xde+\x19!\x85\xe3\xa7\xf0\x8e\xf3\xcf\xf5B\xd9\x15T\x0b=\xc9\xe0\xc5_\xfeb0\x93\xaf \x81)!\xf0\x0cF\xa3\xd1\xff\xd6~\xc6\x99A\xd9J\xff\x01\xcaV#\xce\xc6\xeb\x9c,\xeeN \xb9\xa7\xfft4\xd2\xdb\xbfd\nwyU\x1fEG\xce\xc8\xdd?\xf1\xba\xee\xc1o\x06\x1dn\xaa\xef\xdff\xd9\x9dXd\xf7Wt\x81\x06\x13\x1e<\x13\xbe!oe\x00 %\xf4\xeekBFQ\x8a(\xb5\x08H\xb2\xc8\x0b\xc9>6\n\xeay\xd0H\xae\x16\xdd\x03\x8b\xe8\xde\xad\xd8\x9cd\x06\xe1I\xae^\x13rw4\x1a\xe9\xadA-\xb8\xbb\xc6o\xc4\xe4\x13b\xed*U^\xc9\x1b)\xd4\x97\xaf>\xbcx\xff\xe6\xdd\xd9\xcf\xef\xef\xe9\x8c\x04\x94\xcd\xca\x89jnX6m\x16\xe7C\x8b8\xbf#zI\nQ>}\x06\x7fZNF\xaf \xf9m4\x1a\xfd[\xff1\xcaV\x07\xdc\x0d\xe5%\x96\xd2\x89z\x8br:G)\x17\xb2\xb9#&\x11nra`!\x99n0\xf01[\xacY\x10\x0c\x8a\x05\"\xbe\xfa_\xcf KR\xe3\x047\xf3\xa5\x99\xc9|s+\xe4\\\xe9\xe2j\xa3\x01\x93\xd5\xda\xed\xaa\xac\x87\xb8uj\xa2\xf6zc'i,'\xb9\xe4\\.\xe5$\xab\xd7\x07\xc8\x08\xa0\xba*\xb9d\xd4\xed\x08\x16F\xb5q\xbe\xcb\xf5Z%\xc2\xad\xd0P\x151\xfd\xd7?\xffu\xcf\xb0\x90\x86\x98s\xed\x06\xcd\xd3N\x88\x8aWy<:9>\xa1\xaa\x94vI\xdb\x86\x9a%,\xc5Ok\xe4B\x84\xa1L\xb8LEK4K\xb2\x06N\xd9\xa4\xd6\xaes\xfd\xa1\x0c\x1d\x96\xba\xb5\xf1\xe7\xd2\xb4\xa8p\x19IF\x1c\xc4\x8c\x82d\xf8\x8a\xd9\x12\xe6\x0c\xdb\x7f\xeb\xe6\xbf\x14\xdf\xff\xd5m\xfa\xab\xf6\xab;/\xf9?\xcb(\x18\xa2T\x86\xfa\xde\xa1\x19~/\x0f\x99\x8c\xe4\xef\x9a\xca>\xd7\x07\xc9x\xb5\\\x84\x18\x16\x842\xc0\"\xb6$\x02R\x8a\xa2\x9a\x97\x91\xc1G\x00E\x92\xb1\xc7\x0fM\"\xd0\xc6=\xe4\xd3\xef\xbc\xff\xe2\x1f2\xa1\x8e\xdb\xcb*\xaa\xd9\x08\xa1\xe9\x00\xa1\xa6\x88d^\x9e\xa8L\xb7\x02/\x11\x05\x8a\xd9\x01$\x8cV\xc1Z\nE&'`,\xe3W\x97\xc9F\xe6\xb89X\"N\xf1U@\xe4\xfbr\xaeV\xc3Z\xcd]\xa9t\xa7e\x0cL\x149\xbe\xa1\x1b\xa3\xb5\xd1\x05\xe1E\xe7\x98\x96\x10\xb7X^\xeb\xf5\xc8\x97\xdc\xa8\\M\xc9,#\xf9F\xfc\xbaZ\x8d\xed&\xa4d\xfa\x0el\xfb:\xba\xcd\x93\xde\x7f+k\xdb7\x9e\x8f>\xfc\xad\xbcn\xa7zh\xc3pTz}R\xba\xfc\xef\x12\xd7\x96\x00\x04\x90\xac~T\xb5\xac@ub\xfaN\xd5\xb7\xdb}`Z\x87\xd5wJ\xf9aF\xc8\xdd\x1amv \xd7\x0e\x0e\xb6\xbbA\xed]\x80v3\xa0\xde N\x17Mh*\xb4\x82\xe9\x03@\xe9\x1d\x81t-\xfc\xe8\x06\xa3\xf7\x02\xd1;A\xe8\x80\xd2\xcd\xc7G*bn\x00z\x17\xf8\xdc\x04j9\x81\xe7\x03C\xe7N\xc0\xf9\x80\xb0\xb9\x154\x1f\x082\xef\x03\x98{\xc3\xe5\x03\x80\xe5\x03C\xe5\x16\xa0|p\x98|7 \xf9\xe0\x10\xb9;@\xde\x0d\x1e7\x08\xdd\x06\x8e\x0f\x06\x8d\xbb\x01\xe3\x8a\x9d\xb9^\xbf\x0e\x0c\x8a\xdb \xf1\x9e\x80\xb8\x01\x0e\xb7\xba'V(\xdc\xcd\x7f\x19\x16\x06\xb7\x81\xe0v\x9e\xba\x01\xe0\x95fWTh\x83\xbf\x07\x04\xbf{@\xdf\xea\x84\x15\x13\xf0=,\xecm\x06\xbd\x87\x80\xbc\x9d0[\x0b\xdc\xed\x0cv\xebq)\x7f\xa0[_\x972\x06<\x08\xc4\xed#,Wx\xdb.\x13gh\xbb\x03\xb0\xad\x8e\x97\x0f\x04j;A\xdav@\xdb\x05\xce6J\xd1\x17\xcav\x05\xb2u0\xf6\x00 \xb6\x07\x84\xdd\x1d\xc06\xc0\xc4\xae\xe0\xf5\xc0\xd0\xb5\x81#\xe5L\xed\x04ZW\xb1FE}\x1a\xc8z`\xc0Z\x0fWw\x05\xabED@\xc5\xb8\x1a\xaa\x1e\x16\xa8\xd6m\xfc\xac \xb5\x0eE\xd3\x01\xd4\xc3\xc2\xd3\xdd\xc1i\x0d\x10\xdd \x86\xb6B\xce~\x80\xb33\xdc\xec 6\xfb@\xcdZ\xa0Y\xcf\x8d+\xe0\xe7\x062{B\xcc\x1e\x00\xb3\xb2k\xc3\x82\xcb\xbaE\xd1\x03XV\xc6)\xb4\xb0r7P\xd9\x04 \x0f\x0f\x1f\xf7\x9fI\xce\xd0\xb1+p\xdc6\x91\xeeg\x15;\x1cU\xdc\xa8-\x9cT,)\x9cT\x0c'\x15\xd7\x14N*\x86\x93\x8ak\xea\x02\xb5h+\x0b'\x15\xb7i \xd8\xa5\x1f\xf0\xd2\x01z\x19\x04|\x19\x1c~\xb1\x020;\x80`v\x05\xc2\xec\x00\x86\xf1\x01b\xbaB1F\x1dn\x03c\x06\x84c\\\x01\x19OHfpP\xc6\x0e\xcb\xf4\x06f\xc2IE+g\xdd\x80\x1aeU\xe1\xa4b\x17\xc8\xc6\x06\xda\x0c\x03\xdb8b\x11V\xe8\xc6\x03\xbc\xb1\x9e\x18\xf3\x04p\xc2I\xc5pR\xd1\x05\xda\xb1J\xd5\x17\xdeq\x07x\xc2I\xc5\x0d\x1a\x18\xee '\x15\x9b\xd4\x15\xfcQV\x16N*z@A}\xc0 eu\xe1\xa4\xa2\xb2\x80\x13|\x14N*\x0e\x07&\x85\x93\x8a\xbd\xa1\xa6a\xe6\x9c3\xdc\xe4\x0e8\xb9\x9dT\xdc|?zc\x17Y\xfe\xdc\xba\xfa\xb5\xfa\x1b#\xe5\x8d\xa6\xd3v\xe0+\x11\xb7\xc6\xb64\xdf\xfapN\xe3\x91FPo\xc9uGs\x94'sD\xd7\x0c\xef\x16\xbe\x13\xbf\x0b>\x13,_-\\KC}\xf2\xa6`sY\xeaN\xc5\xfb-=|\xd3\xec{\x936\xae\xef\x15\x02h_\xdd[ \xa0\xb2c\xf2]\xdcmC\xa2e\n\xac\x80\xd4\x02]\x8d\x17xA\xc65~b\xc0\xad\x9c2f\xb5W\xd8\xb2\xab1Mfcq0q\xa7m|\xc1\xe3\x88P&\x1e\x94\x9d\xacX\xdf\x14`mc\xbc7\x178O\xa6+\xd9\x1e\x8eO\x1e=:~r]\xcd\xd1\xea\x99\xff\xe1\x1bt\x80\xbd\xe5\xda\xf3A\xbd\xcb5\xfe\xfe\xdd\x8b\x8d\xfa\x02\xe8\x1d@ok\xc4\xd7%h\n\x01\xf4\x0e\xa0\xb7\xf6\xcb\x00z\x0b\n\xa0\xf76\x05\xd0;\x80\xde:\n\xa0w\x00\xbd\x05\x05\xd0;\x80\xde\x01\xf4\x0e\xa0\xb7\xa4\x00z\x07\xd0;\x80\xde\x01\xf4\xd6Q\x00\xbd\x03\xe8\x1d@\xef\x00z7h\x08\x002\x80\xde\x82\x02\xe8\xfd{\x01\xbd\xad7\xe4F}\xe0m\xba~\x93\xee\xb7Ew\xd8\x85\x94\xb3\xd2i\x07R\xee9\xda\x13\xb9\xa2p\xedXIa\xbb\x11\xb6\x1bV\xef\xa4\xe2O(\x1a\x1dw\xe2\xc7\x8a\xb7H\xaa+\xfe\x97]\xb3g;\x92\xd5\xb2\xb0\x82%:^`\x86b\xc4\x90\xde\xaa6\xf4\xcfKQ\xe6mY\xa4eg\xa3T\xb8\xe8Uu\xd2\xbc\xa6\xdc\xe2\xcd\x12\xca0\xd7w\\\x12uUMM\xad>\xe1\xd5n\xac\xfc\xe2\xd6\x9a\xdf\xaa\xe3\xb7d\xbd7e\xd0u\xd1\x8a!\x1a\x17Y\xc24\x8d\x98\xbb&I\xdbAI\x96nJ\xb2uV\x92\x11_\x90d\xedrEv/\xa4\xfd5_\xdd5\xfc(\x17D \x1b7\x0fH\xcc\x92\x0b\xacO\xcdm\xd6\xc5\x85.\x0e,@\x81\x18Y\xdc3$\x9a\x00\xbeZ\x92\x0c\xeb\xb1\x11If\xdb\xd7\xa4\x86\x1d\xd4D{+\xf2\x93R\xc5gSPKr)7E\xc7G\xeb\xdf\xc5\xde\x8bd\xa6\x0cj(\x8f\xad\x18\xd2\x93\x04\xe5()sQ&\x88\xe2q\xad\x86\x93\x0cH\x1e\xe3\x9c\xff\x1b\x7f.P\xaaEl\xd7$FOj\xa5\x8fY\xc2\xf6ii\x04,\xc5\x8e\xcb!}\x06\xc7\xff\xa7\xee\xe2\x9a\x1b[qqj\xa5ro\x1b\x9d S95\xd6\xc7/\xa2\x1c\xf3\x9d\xab\xfex\x81\xa4\xba\x03\xbc\x8a}^\xc5\xbe%5[R\xcd\xfb3x|\x00l^\xd0\xa7p\x0c\xbc<\xef\xda\xd1\xffy\xec0UQ\x9a j^\xc5.:E\x92E\xb3Hr^\xf16\x04\xa3\xa2\xb2\x0b2\xd6\x95&T\x88\xb1\\\xeb\xd5o\x95\xdb\xed\xbc\xde\xb5\xdf\x98\x82\x97mZ\x0fkcy!\xceY\x11\xb1\xcd\x04gde\xad\xb5\x91*\xca\xd9R\xae\xa3$\x92\x9b.\xddH\xdbE\xd9\xb0,\x9bj\xb3\x12is\x9d _B[\x99\\\x97-\xe7\xa2I|\xcdt6\x81\xee:\x8e7\xb3\xd9\x17\xf17\xb9\\\xef\xae\xa3\xba\xfc\x97\xbaw\xda\xfa\xc4\x8ao\xac\xb9#\xcd\xc2\x8a\x13\xbaL\x91\x06\xdb\xf4\xef\xa1a\x8e\x95-\xd51\xb2\xd2\xcc\x15\xb3\x19\xa6|\x1bX*W>\xd3\xea\xce\xda*\x93\x91J\xe9;jNM\x08\x7f\xbb{\xef\xca\xc9\xb8/\xecp\x13|n\x9d\\\x141\x84\xbbx\xf6\x14^\x08W\x19N\xb9*\xdbW\xd6IW\x8b \xe9\xbe\x91r\x9fR\xb2\xa1u\xe0\x97\xf3X\xfe\xad:yH\xe7\xe42\x03\x92\x01\xbe*\xcf\x12ik\x13\xbd;=\xfb\xf9\xed\xbd\xf2Hj\xa4K\xf4\x03\x19 \x17\xa3+\x925%\x03\xe5\x90\xa9F\xc9e\n\xd5\xbb\x06\xbb~R\x96Gf\xd5c\x17j\xbd5\xa9\xcfd4\xf6-I&\xdd\x1e\xae\xee\xaa\xad\x8b\xda%hlh\x04+!+\"dE\x84\xac\x88U{\xb7\xee\x14\x96TUs\xb8\x11b\x08\xb9\x11!X\xa9\xfc\xfd6\x05+C\xee\x81\x1f\xb0\x1br\x0fv(\\;j\x1er\x0f\x86\x90b\xc8=\xf8\xbd\xe6\x1el #\x0e\x89\x07\x1e\xb8\x88\xc8CX\x87,Z\x81\x16=\x0c\xf2\xb5\xa1 :?\xa2\xd3N\xc5\x8aeX,\xba\x15\xc7\xb0E\x1c\x8d\x91F\x07\x04\xc3\xe6\xef\x80\x0bz\xe1\xe0\xb6\x80\xd5U\xdf\xfc\xd6\x03\xb7\xb0D*A\x1c\x10uE-\\0\x0bW\xc4\xc2\x15\xaf\xf0\x91\xcc\xb0X\x85\x1d\xa9\xf0\xc2)\xac\xc1[\xf0E)za\x14\x03#\x14\xdd\xf0\x89\xfe\xe8\x84\x036a\xd3\x13\x92\x1cp \xc7\xb5l\x8b\x1fH\x1a\x16\x910\xadr\x970\x1f\x0c\x8dEtG\"l\xe2\xeb\x82B\x18\x99\xd5`\x10z\x04\xc2:\x0f\xdct\xd6\xb0\xd8\x83\x1b\xf2`\xc4\x1d\xfc\xfa\xa5\x9dI\x03\"\x0e\xaex\x83\x1em\xb0\xf6ih\xa4\xc1\x843X\x99q\x9b8\x9d\x10\x06\xc1\xbd\xa6BG|\xc1\x07]\xb0O\x95~\xc8\x82\x01Wp\x0d{\x0e\x14\xf5\x0cA\xcf\x10\xf4\xfcz\x82\x9e\x9b\x8eBk\xfaI\xcdl\xc8\x80\xe4\x7fo\xe6\n\xdeT\x16\xa4\xe7\xc5\xf4l\xeb^\xf6+Q\xdf\xc6\xd5\xec\x1b\xe7\x07\xb2\xf3\xaf\xfb\xa6\xfa\x1e{w\x8a\xb3x\x8c34Iql2e\xbf\x87\xcd\xb7\xb1\x9b\x92T\xc1\xa9Mr3\xdd\x00\x1fp\x16\xbf\x92M\xcaKr\xdb\xeb\x0c\xb5d\x0f\x94!V\x18\xb2\x03.\xe7X\\\xa5\x89\xea\xb5\xab\xdfp\xf1\x8ay\xadj\xc7PZ\xa6\xb1\xeb\xc8\xeb\x84\xd1\x12\xc3;\xe3\xf3\x08\xd5\xeeF\xb1\x12\x15u\xa9\x0d\xf9\xc6}\xf6\xcd\x96\xb6\xcdx\x8d\xba\xc8\xd5\xafZF\xad\x97+\x82\xbd\x0e\xf6z\x8bv`\xaf\xbdL\x1f-\x96\xcbt\xa57}g\x84\xa1\xf4\x83\xf8\xa8e\xffd\xf4_\x96\x86\xe6\x1d:J\xeb\xd7\xa8\xa5\xfc\xf9\xd6\x9a\xbf\xa6@\x9at\x13\xb3\xcbh\x91\xac\x93#\\\x963\xe4e9\xe5\xc6\xbe\x9c\xf1I\x15\x85\xa8\xe6\x7f\xe5\xe2\xb6\x8d\xab.\xf8$\x96dcQt\xdf36\xd7\xa7v\xc7X\xff1\x18\xa0-\xf9\x04\x03tm\x06H\x0d\xb4\xca5\xe4\x80\xaf\xcaY\xfe\xf3\xb4e\x87\x1a\x16\xa8y\xb0[i\x85\xaa\n\xca\xdfn\xad \xd2)\xee\x1e;0\x83%\xb1\x8cq8\xc3\xdd&?\xcb\xe1\xb0\xe7\xa8f\xa5\x93\x0d(\xb5\xfe\xc6L\xae(\x9c\xe2.)\xa8\xfckV\xf9\xbb\x8b\x11\xde\xd8)i\x8a\x0f\x19\xceb\x9c/\x92\x8c\xad\xaf$IItN\x0fS\xc40ez[\xf5\x1df?\x8aO\x9e\xf3\xef\xcb\xac\xb8\x12U\x14\x7f\x07Q\x91\xd2L\xb5\xcb\xde\xa9\xfavK\x8d\x95\xe8\xc78QDwz\x98\xab9\xa2\xf3\x0e&\x07\xecG\x12\x96(gc\x8a\xd9x\x8eQ\x8c\x15\x9a\x08l\x9c\x83\x95{N\x86C\x05`U_\x15\xb9$\xb5\xe8E\x05.\xe2\x02\xbb\xc8\xeam\xcc;\x943\x8a\xd9\xf7Br\xdb\xc3-?\x12\x93\xf6\xcdK\xd5,\x19v\x8a\xecv\xfc\xcag\x9d\x0c\x92\x95\xdd\x95\xb0\xa1\xe8\x9e8>d\x19\x89A\xce\xb8k\x84\xd9$\xa7q\x07\xb7\x03,\x92\xd0ry\xbdM\xda\xfd\xc7\x8a^p\xd5\x96\xd1\x82B\x84\x96\xd25\x93\xd6\xa4\xfas^\xa4e\xfa\xcb2'\\'\x9aYD\xf5x\xca\x802\xff\x8fh\x8e\x92\xec\xc0\x94~$3qe\xbeM\xda(\x04\x02\xdd\x92@\xb4\xe0\xad|]Are\xa8\xb0zsi\xfd*\xdb\xbe!\x1c\x0f\"\xb8\x8f\x81\xe5(\xa3\xf2\n\xf2\x05\x8a\xe6I\xa6|\x88\x89\x93\xe0N\xa9\xb9+r\x18\xd29NfsC\x06\x9fC\x15nz\x8e%\xfa\x13\xa0\x9e\xcd\xc4\x88\xe1\xfb\xbc>\xcd\x97\xe2\x92\x7f\xbd]\xabh\xc0\x15mV\xe2\xe0\xdaApQ\xe6\x92\x9c\xec`EN=\x05\xe7\xde\x82\xdd>\xd6\x9f9\xd9\xc9\x8a\\\xe6QEv\x91\x83\x8f\xd8\xc1]\xf4\x8e\xf6t\xe3c\xb5]\xadHL\xd9\x88,\x16 \x1b_\x87G\x00k\xc6xs\xf2\x9ap\xa95\x1b\x19\xea\x9b\xc4\x7f\xba&\xf6\xc4\x8bv\x88\x91\x9c^S\x83\x9b\xf2\x98\xe6\"+M\xe8o \x05[\x16l\xfd\xb7e\x8e/\xa4\xb84\xb5\x89\xf3^\xd7\xde\x87\xdab^S{h\xb9\xbc\xa6\x96\xc4\xfa(O*]S\x93\xf8\"\x89q\x16\xe1kj\xae\x9e\x7fk\xb7\xc7\xe0\x8frEM(\xce\xc7\xe5\xa5i\xbb\xe6\xaf\xe5\xccI\x85\xd7B\xd7k\xf7HFr\xcf\xea\x8dw\xa9T\xa4\x95Rf\x1a(\x0f\x9a\x80\x8b\xd5\xb2[+ve\x95\x8c9\x11\xdc\x9a\x06\xee$^\x07\x01\x83\x97\xc7|vEeNd\xf5<\x8ep2e$S\xba\x91\xffU\x06(\xbe\x17\xfe\xdd_\x8e\x0d\xaf\xe9U\xc1W\xf1\x88v\x9ar\xa1\xc1\x1c\xe7X\xccY\xb2Q\x1d\x91\xd4\xd4\xa5\xb3\x0e\x95Z\xd9\xd9\x9c77\x00\xc3N|\xabOi\xe7WR\\\xc8]\x12\x1e_\x10\x86\xc7\xf6NHr\xe4\x02<8\xe1$x\xd0\xa8\xa56y0\x00\x9eL@U\xbd\xd3\x97\xce\xaa\xa8I8+,\x97\xed5\xe9>|x\xf3\xddO\xaf^\x8e\xdf~\xf8n|\xf6?\xef^\x8d?\xfe\xf4\xc3O?\xff\xfd\xa7\x1e5\xbc{\xff\xea\x97\x9f\xcf^\xf5\xab\xe1\xc5\xcfo\xdf\xbe9\xebU\xc7\xcf\xef~\xfep\xfa\xa3c\x15\x15&\xd3S\x1e\xee\xfa\xbeM\x1f\x92Y\x86\xe3\xb7tvV>\xc9&_\xe2\x17'\x86\xc4O\xce55^ mE\\\x8c\xdaz\x83\xb4c\xfa\x14~!\xcc\x18!\xd9 \xfd\xb8<\x85w\xc2\xe1A\xa9[u\xb6\xa8F\x9b:,\x1c\x9f\x9d\xaa\xa4\x9c\x14\x991\xab\xb4I~\xdbfI&\xccLM\xf6\x10I\x9b\xff\xf0\xea'\xf7$\xd16mV\xe6\x99q\xda\xa6\xcd\xca~z\xe3\x9ax\xda\xa6:\x0du8\xb1u\xdf\x85K\x92\x8b;~\x9d\xa2Y\xe3)\x1fy+\xe3\xf34\"\xe7o^v\xc2g$\xd5j\x00\x12\x99\x1db+\xb0M\x9d\xb3\x97\xda\xd4{\x9d\xf4V\xc7\x1e9\x1a\xdb4\x18\xfb\xdd@\x07I\xde\xe9Pm\x1a\xac\x0f\x9d\x86\xa0\xcf\xbeK\xd2\x0b\xb1\xdd\xf9\x90\xccd\x067\xf7\xd1*\x88OdXU\x07\xc8;T\x9dd\x80\xca\xfa\xdd\xb7_\xfd\xfa$[k\x1f\x8b\xaf\xb3m\xc4q}\xbf\xdd\xa4\xdcB^\"Zn\x0b\x99\xbc\xb6\x00\x95g\xed\xbd\xeaZ\x07\xe4\xdc\xa4\xb1\xd6\x11\x14;o\xf7:\xd8\xfd.\xd6~\xdd\x17\xf72]\xbd\xa0\x0e\x1eP\x07)H\xea\"\x0bI\x9d\xf5x/\x05\xd2Cy,\x8b\xc9\xf8\x1ck\x9e\xd33Qg\xe1B/\x01s\xc2\xf1\xc9\xa3G\xc7O\xba\x14\xed)h\xe8'l\x10o\xd8D\xcb\x93G\x8f\xcf\x8f\xbfF\xf6\xfbxd\xef\x8aI\x9aD?\xe0U+\xc6w\x8eW\x1b\xef\x82w\xa8\xba\xa0X^\xe2\xdd\x08\xfb\xfdR\xeb&\xcf\n}\xd3q\xdb\xd4k|\xfa\xec\xeb\xebh\xf12OH\x9e\xb0\xceK\xfaZy\xaf\xb8\xf6a\xb6\xa3\xe6\xe9\xaas:\xaa\xf4\x1e\xc2\xec\xbcD;*\xf3\x8e\x02\x85\x1eB\x85~j\xbc\x87p\xa1\x8f\x80\xa1\xaf\x02\xbf9\xc6\xbb\xab\xee\x9d)\xee\x01\xd5v\x1f\xa5\xddcL\xba)=\x18B]_;\xd7\xdd\x0e\xabT\xd4\x91]?V\xf9\xee\x8cdcwh\xcc\x93+?n&\xab/(cI\x86\xc7~\xfb$\xbf\xfd\x91\xc7\xbe\xc8[\xcf\xfbkwoc\xe99\x02\x92:\xa8Ao\xd3\xe8-,\xe8$0\xe8j\x08; \x0e\xba \x0f\xba\x9b\xbd\xebe\xb3\x8b\x91\xdb\x81y\x1b\xc4\xb0u\xd3\xb4\x9d\xe4\xed\xa7\xd7$\xf50`\xd7\xc0c7c\xe5\xc9\x98'K>Q\xf2\x8e\x9c\xb8F\xc0}\x83\xab?r\x83\xfaB\x9c\x1b<\x15\xc7\x06\xfb\x9ef,/)m\x9c\xafE\x8c\xe1\xc5R\x9cdd\x04\x16 M1\x8a\x01\xc93\x8b\xd6\xfa\xe4\x99FUD\xb5\x91*\xac\x16\xbcU\xd1\xdb\x95\xba\xcd\xe1p\x1aM\x97\xd9d\xc9\xa4\x91\xed\xd8r\x0b\\\xb2c\xecy0V\xb1\x81\x93\xe8\xc0)\x19\xc1I\x80\xe0n5\xbcrP\x9cz\n\xce\xbd\x05p\xce q\x1b\xcf\x8a\\&PEv\x91\x83\x8f\xd8\xc1]\xf4\x9e\xd9\x1bNy\x1a.\x19\x19.^\xb5\xd5\x97v\x9c\n\xae\x13\xc1+G\xc2c0\xdc\xf2\x1e\xbaf8t\xcce\xe8\x98\xb5\xe0\x9f\x9f\xd0+\x13\xc1\xdd\x83\x1c*\xbb\xc0+\x8f\xc0;c\xc0c\xd6x,`GO\xa6C\xe3n\x1e\x8c3Z\xdf\x81\x03K\xf7}\\'WT]`\xe4\x0e5\xa9\x11c7\x8e\x1c0q\x0d\xce\xad\xa9\x10m;q>\x0f\x91\xb6\x9f\x1ctz\x89t\xa3\x06\xf9.\xe9\xc6\xb3\x87\xe1=\xd2\x92L^^x\x8f\xd46;\xd7t\n\x1f\xdf\xffx\x98cJ\x8a<\xc2\xe2}Q\xb9\\\x8a,\xf9\\\xe0t\x05|\x0d\xb1dZ=\x0f\xcd\xe4\xed\x87\xda\n\xe5\x1b\x0dy\x82\xd2\xe4\x0b\xd6\xbc\x15\x0fR\x06\x8cD$\x85I1\x9d\xe2\xbc\x1a\xb4\x91|zB\xf6\x0d\x16\x05\xad\xd74 \xbdO\x92bD\x99\xbe-\x92a\xd8;\xdc\x83h\x8er\x141\x9c\x8f\xc4\xbb\xc6|\xef\x04\x14\xcf\x168\xab\x15\xd7\xc7\xf7?\xee\xd3\xcdgP\xdb$\x98\xaa\xefd\xd2\xb7\xca\xab\x9b\x16i\xba\x82\xcf\x05J\xb9\x04c)\xdf\xb2)!\xc9\xbb\x88B\x92\xe9+\xf9\xc4Y9\x9c\x112K\xf1H\xc8lRLG/\x0b\xf9\xb8\xe9\xa7{\xb2'\xa2Z:'E\x1a\xc3\x84+^m}\x08\"\x94\x91,\x89P*\xd6\x90\xbe\xe5\xbbx4\x1b\x1dp\xd1\x8a\xeb\x16\xf6F{\\{\x89'I\xa2\x08/\x19\x8e\xef\xa9\x1f\x8e\x96\xf4&\x83%\x17v\x12\xe1\x03`\x18-(\x14\xb4@\\\x1c\xf2\xe6\xaae\x92rN\x19\x11\xc2\x98$\x19\xca\xf5\xae\xabx\x05e\xb5\xc4\xe5s$l\x8eW\xfa\xa6\xa5\xae\x83\x84\xf1\xadvA\x9bWn2|%\x86\xfa4[\x8d\xe0{r\x89/p~`tK>\xbe\xff\xb1r{xU\\Ok\xbf\x15\x1a\x14\xc3\xa79c\xcbO\x07\xf2\x7f\xe9\xa7\x03 9d\xa4\xfc\xf5@\xcc\xc6\x08e@\xc4\xea\xe4\x12\xd1W\x88\x19\x14\xcb\xf2\xceQC\xbb8\xbf\xc0\xb9\x14\xcd\x02-\xa9\x9cZ\x82sF\xea\x8bGE\xfc/\x91/\xa6 }\x98nJ\xd2\x94\\\xd2\xa7\x86\xb1\xfd3\xbc\x99\xae{\xc4\xa7\xc52'\xdc\xd8\xc6u\xa7\x85K@i\xb1\xc0\xb1\xe1\x82\xd3?s\xe3\xf4\xfd\xd9\xd9;\xf8\xee\xd5Y\xf5F\xcd\xc7\xf7?\xca5\xb6\x12\x0f\x8e\xeb=\x87\x7fn.\x8b\xb3\xd5\x12\xff\xeb\x9f\xff\xd2\x16(\x1fj\xe6\xf3A\xce\xb7\xd2\x8c\x88\x11Z\xe6$.\"\x0c(\x93&L\x9f\xbf\xf6g8]\xdf\x0bB\xc5\xa3<\x88\xcb\x0c\xc7\\\xdc\x11\x8a\xb8n!\xe4\xbcXBy\x12\x11&\x88\x1a\xb2\x0b\x89\xed\"\x95\x8f\xef\x7f\x14<\xce\xd1\x85\x98\x82\x8b\xc6\x1a\x8a\xe5\"BU\x97\xf8\xbf/H\x12\x03\xcaL\x00\x8bdP\xa8\x8f\x1cOI\x8e\x0f\xaa\nx\xbd\x88%\x93$M\xd8\n2\x8cc1\x8d&\xe2d\xaf\x98j\xa6\x10\xb7\xc9$\xacj\xb4\xa08\x96^^\xb5.\xb5UM\xf0,\xc92\xde\xd9\xcb\x84\xcd\x0d\xc6e\xb5\xc4#9\xff\xd12\xa1\xa3\x88,L\xda\xf8\x83X\xa9\x14\x08\x9bKE\x91mj)\xb8[\xbe\x87\x8f\x17K\xb6*\x97\xf6=\xbd\x11Lfs\x06\x13\x83R\x12\x9d\x160A\xb2X\xa6\x98\x1bY\xb1`\x80.q\x94L\x93\x08(^\xa0\x8c%\x91&Ut\x07\x8f\xaao\x92\xab\x97\xf4\x96\xab\xa3 \x06$w\x03\x0d\x07g\xcb\x8f\xa9n\x0e\x9a\x90\x0b\xfd\x9c.EP.\x05\xe5#l\x0e\x9c}:\xcdV\x9f\xd6[\x1e\x94\x01\xca' \xcb\xf9\"\xd6s\xa8\xac\xaa\xb2\x11(%\xe5\xd4\x03\xa4\x1eZ\xae\x9d\x85\xa1\x91\x1cN\xdan\xe1\x86\xfbW{u\x9a\xa9\xf9\xaeZ8i2\x11l\x97v\x84\x02-\x96K\x92\x0b\x0b\xbeD\xd1\xf9a\x91\xf1\xff\xe1v[\xce\x0b\xf5\n*\x0d\xbd\xde\xb1!S(\x98Tl\x95z\xa0\\\xb1\xa28N\xa4\xae\x80\x19\xcep\x8e\x98`\x9eo\xb4\xaa\xcb\xa0\x94\xf5q~\xe4\x10\xaa\xdb{u\x85\xf8\xe4\x87\xe3\xa7\xf0\x8e\xf3\xcf\xf5B\xd9\x15\xd4\xbc\x11\xfc\xc5_\xfeb0\x93\xaf \x81)!\xf0\x0cF\xa3\xd1\xff\xd6~\xc6\x99A\xd9J\xff\x01\xcaV#\xce\xc6\xeb\x9c,\xeeN \xb9\xa7\xfft4\xd2\xdb\xbfd\nwyU\x1fEG\xce\xc8\xdd?\xf1\xba\xee\xc1o\x06\x1dn\xaa\xef\xdff\xd9\x9dXd\xf7Wt\x81\x06\x13\x1e<\x13\xbe!oe\x00 %\xf4\xeekBFQ\x8a(\xb5\x08H\xb2\xc8\x0b\xc9>6\n\xeay\xd0H\xae\x16\xdd\x03\x8b\xe8\xde\xad\xd8\x9cd\x06\xe1I\xae^\x13rw4\x1a\xe9\xadA-\xb8\xbb\xc6o\xc4\xe4\x13b\xed*U^\xc9\x1b)\xd4\x97\xaf>\xbcx\xff\xe6\xdd\xd9\xcf\xef\xef\x99\xc2d\xeb\x89jnX6m\x16\xe7C\x8b8\xbf#\x86;\xe2\xb8(\x9f>\x83?-'\xa3\xd7\x84\xfc6\x1a\x8d\xfe\xad\xff\x18e\xab\x03\xee\x86\xf2\x12K\xe9D\xbdE9\x9d\xa3\x94\x0b\xd9\xdc\x11\x93\x087\xb90\xb0\x90L7\x18\xf8\x98-\xd6,\x08\x06\xc5\x02\x11_\xfd\xafg\x90%\xa9q\x82\x9b\xf9\xd2\xccd\xbe\xb9\x15r\xaetq\xb5\xd1\x80\xc9j\xedvU\xd6C\xbe\xbd\xa9\xf6z\xcb(\x19wK\xd4M\xed+\\\xaaC\xbe\x7f\x1f\x89\x1f\xb8\xbb\xba\x0f\xa8a\xed\xb8%,o\x0dTV(g\x88\xba\xb1\xda\xb4d\xe9\xaa\xdaWn\x05\x0bj7\x19\xd0\x94aU\x8cP\x92\x88c\xec\x1f\xee\xab\x9b*mb\xc5\xb2\xd8\xed\x02.g\xf4\xde\x94\x90\xd1\x04\xe5\xa2\xb3W\x87\xab\xd1\x97=)E\xb1\xf7R\xd6\xa7\xdf\x8a\nV\xf7x\x1d\xdc\x1c*?\xf9\xeb\x87\x9f\x7fR\xff\xf2\xec\xd9\xb3g\xfa9\xc0\xcb\xadc.\xd2\x8f$\\\x1d\x94N\x90\xdc\xd7\x15\x14W\xf1\xd5Y\x91\"\xcd\x8d\xd6\xdb\xd5\xf0\"1^\xbb-\x07\x80\x17\x13\x1c\xc7k\x07\xe6@\xba\xe3\xaa\xea\x90&z\xd3p)\xa6b#\xfb\xe9\xbf\xb8\xe8>\x95\xc1\x84V\xa4\xba\x1a\x1c\xf5\x02)\xd5\xcfS\xc3\x06\x04E\xe7\\\x07\xad7\xc4\xd3$\xc5z\xbbQ\xe9\xacw8\xa7$3.\xdb2\x12'\x9e\x8c\x1d\x8b\x11~\x06\xc7\xfa\x9a\xeb\x02\"1\xa1\xfc\xfe\xc4\xdf\x82\x01\x18\xb9\xda\x13\xb2\xdc{\n{\xaaU\xdb\x16\xc3H\xf6r\xef\xc0T\x9f\xe8\xdfOh\xc1\xeb\xfc\x0f\xd9\x85\xff4\x16\xe0\xfd\xdb\xf8\xde\xb7\x93o\xa6\xe5\x86\xab=\xd7\xe4lH(\\\xe24\xbd\x7f\x9e\x91\xcbL\xe8\x999\xa2\x80 *(#\x0b\xcf\xc5\xd5\x9e\xf2\x07\xd2\x81\xdfX\x07\xd5\xc3\xc55;|\x02k6WHNiuc\x9f\xc4b\xac\xe6\xf9\x9c\xa4qy\x0b\xad\xe0\\.\xe5$\xab\xd7\x07\xc8\x08\xa0\xba*\xb9d\xd4\xed\x08\x16F\xb5q\xbe\xcb\xf5Z%\xc2\xad\xd0P\x151\xfd\xd7?\xffu\xcf\xb0\x90\x86\x98s\xed\x06\xcd\xd3N\x88\x8aWy<:9>\xa1{\x86)$\xff\x97\xa1Y\x034\xb8\x0f\x1fp~\x91D\\z\xfb\x87\x11\xa1\x0bB\x0f'\x88\xe2CV\xa7\xe6\x1d^\x1cO0C\xc7\x87\x02\xfe\xa2\x87\xbf\xc9t\x9e\x7f\xef\xcbjf\xebc\x97\xb4X,P\xbez\n\xdfa 7=_\xc9\xc7\xaa\xe1s\x81\xf3\x04\xd3\x12A\xe3\x82\x9e%\x178+3\x83*\xadE\x96X\xf6\xf9M\xbc]G\xf9M\x05<5:\xb1\x7frt\xb4\xafG\xaf\x80\x16Q\x84)\x9d\x16\xe9.a+}J\x90\xb62\xb0B9\xfa<\x14k\xfc\xc2\x12\xbdpJ\xf11r\x0eV\xee\xc1\x9e\xca\xc3\x9cRx\\Rw\xae\xe3M\x7f\xa7\xd4\x1ccJ\x8e\xe6*\xf4>Sd\xb7\xe3g\xbd\xaf\xde\xf7fz+O\xe0\xc4\x17\xb8\xdd+\xef4\xee\xd0\x18{\xeb\xb5\xeb\xd6[\xe1\x87n\xd2%\x92'\xc9\xed\xf6vh\xdf\xc6n\xeaj\xeb\x9ev\xd7{\xd7]oXo\xdf\x98n\xa8\xd0\xf7.u\xdf[\xd3\xed\xf7\xa3;\x0c\xe9\xb5\xe5\xb8\x9ao,\xf7j\xc6\x96L\xe4x\xdf\xf8\x80+\xda\x9ew\xe9\xd4ApQ\xe6\x92\x9c\xec`EN=\x05\xe7\xde\x82\xdd>\xd6\x9f9\xd9\xc9\x8a\\\xe6QEv\x91\x83\x8f\xd8\xc1]\xf4\x8e\xf6t\xe3cs\xaa\xab\xfb\xcd\xd7N=r\xea\x89\xff\xbd\xd5\x0e7T\x0f\xc5\x9e\xf3\x05\xc7C5\xb8)\x0f\xebU\xcf\xc6\xab\x9b\xfd.i\x1e\xaa\x0f\xaeW,\x0f\xd5\x9e\xfd\x82\xe4\xa1Z\xf2\xb8\xdex\xa8&\x1d/'\x1e\xaa9\xbf\xab\x85\xdd/\x11\x1e\x86\xbf\x963g\xbd\xd3\xd7\xe7\x9e^\xaeSv\xb6\x0b`WV\xc9\x0crt\xc0j`\xac\x02\x06/\x8f\xf9\xec\xaaL\x08\xab\x82W\xc2\xc9\x94\xe8\x80t#\xffK\n~$\x83\x10\x7f96\xbe\xb6\xfc\x93xIY\xa4\xb8\xa5)\x17\x1a\xccq\x8eE\x82\x8f\xd0a#\x80\xbf\xe3\xfd\x1c\xc3\xaf\x05e\x80f9\xc6\xe6\xee\x96\x19M$\xe7\xf3D\x84\x18\x8d\xed\x8b\xd4\xc7\x05FY\xd9+\xc9\xfa\xe9r\xf9=\xa2s\x88 \x96\xe9$e^5\xaf\x9a\x9a\x0c4\xbb\xd2dV\xd8N\x01\xbc\xe4\x9e~+@]\xe6B\x0b\xa7\x1c\x95\xb0y3\xbd[\x9f\xbe\xa4\xb3\x0e\xe6\x87\xf9\x06\x98\xf3\xf6\x97\xff\x06\x9c\xf8V\x9f\xd2\xce\xaf\xa4\xb8zTq,\xde\xc5\xb7wB\x92#\x17\xe0\xc1 To\xf3k\xd4R\x9b<\x18\x00O&\xa0\xaa\xde\xe9KgU\xd4$\xb7\x13E\x15\x85\xb7\xf9K\no\xf37(\xbc\xcd\xefT\xc6\xeb\xb6|\xbfm\xb3$\xd3\xc9\x105\xd9C$m\xf2\xd4u\xd0A\xdf\x81\xf3\xce~M\x1d\x86\x0f\\]\xb2M\xf2\n\xbb\xb4\xa9\x83\xf4\xa0\xa3\x0499\x06h\xda\xd4e\xdeU\xe4\xbf$*\xf2\x1dp\xe8>\xe8\xd0u\xe0=\x83>mr\n\x01\xb5\xc9\xf90fE\x1d\x04\xe2\x1aOm\x93\xf7Y\xd5\x8azp\xe8x\xf6\x15\x05\xcf^\x92\xbf\xbe\x0d\x9e\xfd6]\xb7g\x7f\x0b\xef\x86\\\xcf\xd9\xdb\xc1\x8f\x97\xea\xe9\xc8\x89\xab\xca\xf1\x9d\x9f/+\x80\x88O\xd2\xbe\xf7T\xd6\x03S\xba\xd5\xc0. \xafk\x9a&\x91\xb8\xab\x92\xcfZ\xcb\x9c\x137X\x8e\xe5\x0d\x95c$\xae\xcf\xbci\xd8\xaa\xd1\x83\xb1C\x92\xa9$\x0f^\xc0\x93\x1f(U#\x8e=\xbd*O\x9e\xa0\x03_`\xc9AVS\x07\xc6\xa0#s\xe0\x92\xc5\xac&\xdf\xdcf5u\xec+\xf4\xe8/\xb8eG\xab\xc9SamR\xa5\xc0\xac\x99\xd4j\xb2\xe6W\xab\xe9&\x99\xf6U\xc1\x9b\xe4\x96\xb7\xed]m;\xcf{#\x9b\xdb\xbb6\xc7\xeco5\xb9\xe6\x84{W\xdc\xca!\xf7\xce\x14W\x93o\xfe\xb8\x9a\xecY\xe5j\xea<\x91\xfd\":\x15un\xce\xd7gj\x929\x87]M\x030\xea\xeaR\xb5\xc91\x0b^M7\xa4\xfb\xbb\xc4\x0b\xa0\x9f\x90\xc1\x7fk\xd5\xa6\x1e\x81\xa3\x8azH\x1bzJ\x1c\xba\x06\x94*\xea\xb2\xc1\xde\xa4\xee+\xb2\xa2\xae\x13\x07\xfaO\x1e\xe8;\x81z\x05\xa0*\xea\x10\x88\xaa\xc8\xfd\xec\x81\x9az\xc8\xaf\x87\xdc\xfcO/\xa8\xc9\xe1L\x83\x9an\xa2\xdb\xce'\n\xd4t\x13,\xdb\xb3n\xf5\xe4z\x14\xc3\xbbb\xd3\xd1\x0d5\xf9\x1d\xe8P\xd3M\x88\xdf\xf5H\x88\x9an\x82c\xfb\xa1\x125\xdd\x04\xaf\x1e\xc7R\xd4t\x13L;\x1elQ\xd3M0\xecw4FM\xee\x07f\xd4t\xfd\xfd\xee\xb3;\xb7\x9e\xd0\xf1\xaa\xcd\xe34\x8f\x9aL\xef\xf4\xa8\xa9\xa3G\xdc\xd5\x13\xfe\x8a\xf6\xa0^\xd9\x06\x15\xf5q\xd2\xfd\xd1\xb0\x8a\xc2\xe6\xd3\x85:\xaa\x07Ia\xf3\xd9y^W\xd4})V\xd4u\xe2@\xff\xc9\x03}'\xd0Mo>]\xdexR\x93\x94\x9c\xeb{\xaaM\xb2\x9emSS\xaf\x85\xd2o\x99x\xbd(\xa5\xa6\xde\x13\xcd/\xa3\xb4M]\xdf\xa4RS\xc7\x97\xaa\xd4\xd4\xf1\xfd*5\xf9\xbfj\xa5\xa6^o]\xa9\xa9\xfb.\\\xd2P\xefb\xa9\xc9\xeb\xb5,5u\xce^jS\xefu\xd2[\x1d{\xe4hl\xd3`\xecw\x03\x1d$y\xa7C\xb5i\xb0>t\x1a\x82>\xfb.I\xae\xef\x83u\xa8:\xc9\x00\x19_\x0dSS\x9f>9\xbc0\xe6U\x9f\xfa5\xb2\xfa\xdd1\xaf\xbato\x94\xe9h\xad#(v\xde\xeeu\xb0\xfb]\xac\xbd\xdfk\xf2\x15u\xf3\x82:x@\x1d\xa4 \xa9\x8b,$u\xd6\xe3\xbd\x14H\x0f\xe5\xe1\xfd\x1a}E\x9d\x85\x0b\xbd\x04\x0c]_\xa9\xaf\xa8\x97\xa0\xa1\x9f\xb0\xa1\xfb\xeb\xf5\x15\xdd,\xfb}<\xb2\x1d\xbcn_\xd1 \xaf\xdcW\xe4\x9b\x8e\xdb\xa6^\xe3\xd3g_\xbf\xec\xfe\n~E7\xc0{\xc5\xb5\x0f\xb3\x1d5OW\x9d\xd3Q\xa5\xf7\x10f\xe7%\xdaQ\x99w\x14(\xf4\x10*\xf4S\xe3=\x84\x0b}\x04\x0c}\x15\xf8\xcd1\xde]u\xefLq\x0f\xa8\xb6\xfb(\xed\x1ec\xd2M\xe9\xc1\x10\xea\xfa\xda\xb9\xeevX\xa5\xa2\x8e\xec\xfa\xb1\xcawg$\x1b\xbbCc\x9e\\\xf9q3Y}A\x19K2<\xf6\xdb'\xf9\xed\x8f<\xf6E\xdez\xde_\xbb{\x1bK\xcf\x11\x90\xd4A\x0dz\x9bFoaA'\x81AWC\xd8Ip\xd0Mx\xd0\xdd\xec]/\x9b]\x8c\xdc\x0e\xcc\xdb \x86\xad\x9b\xa6\xed$o?\xbd&\xa9\x87\x01\xbb\x06\x1e\xbb\x19+O\xc6*b\x80\x89|5\x05\xe9CuS\x92\xa6\xe4\x92>5\x8c\xed\x9f\xe1\xcdt\xdd#>-\xaa\x07\xf1\xebN\x0b\xb7\x80\xd2b\x81c\xc3%\xa7\x7f\xe6\xc6\xe9\xfb\xb3\xb3w\xf0\xdd\xab\xb3\xea\x9d\x9a\x8f\xef\x7f\x94kL\xbc\xfen\xf0\x1e\xb6\x9eW>[-\xf1\xbf\xfe\xf9/m\x01(_hO\xb2r\xbe\x95fD\x8c\xd02'q\x11a@\x994a\xfa\x1c\xb6?\xc3\xe9\xfan\x10*\x1e\xe6A\\f8\xe6\xe2\x8eP\xc4u\x0b!\xe7\xc5\x12\xca\xd3\x880A\xd4\x90aHl\x97\xa9\x88\x17\xf3I\x0est!\xa6\xe0\xa2\xb1\x86b\xb9\x88P\xd5%\xfe\xef\x0b\x92\xc4\x802\x13\xc8\"\x19\x14\xea#\xc7S\x92\xe3\x83\xaa\x02^/b\xc9$I\x13\xb6\x82\x0c\xe3XL\xa3\x898\xdd+\xa6\x9a)W\x92d\\\xcdf3,\n\x895;\x82\xbb\x1f)\xae\xaeO\xe2R\xe2\xd3\x93\xeb,9?Q\x86f\xa6\xdeOr\x8c\xce\xb9\x0e*+\x1e\xdd\xd3\xcf\xa8\x9f\x08\xc3O\x81q\x1b2-\xb2H\xae0\xde\x8fRwEE\x9e\xe3\x8c\xa5\xabF\x04\xdc\xa0.\xc5\xbbI\xd3i\x12%(\xb5\xd8\xb2I1\x85\x1csK\x84\x0f\xc4\x8d2 \xab\x1a-(\x8e\xa5\x9fW\xadKmU\x13\xad\xb7=(\x03\x94O\x12\x96\xf3E\xac\xe7PYUe#PJ\xca\xa9\x07H=\xb4\\;\x0bC#9\x9c\xb4\xdd\xc2\x0d\xf7\xaf\xf6\xea4S\xf3]\xb5p\xd2d\"\xd8.\xed\x08\x05Z,\x97$\x17\x16|\x89\xa2\xf3\xc3\"\xe3\xff\xc3\xed\xb6\x9c\x17\xea\x15T\x1az\xbdcC\xa6P0\xa9\xd8*\xf5@\xb9bEq\x9cH]\x013\x9c\xe1\x1c1\xc1<\xdfhU\x17B)\xeb\xe3\xfc\xc8!T\xb7\xf7\xea\n\xf1\xc9\x0f\xc7O\xe1\x1d\xe7\x9f\xeb\x85\xb2+\xa8y+\xf8\x8b\xbf\xfc\xc5`&_\x13\x02SB\xe0\x19\x8cF\xa3\xff\xad\xfd\x8c3\x83\xb2\x95\xfe\x03\x94\xadF\x9c\x8d\xd79Y\xdc\x9d\x12rO\xff\xe9h\xa4\xb7\x7f\xc9\x14\xee\xf2\xaa>\x8a\x8e\x9c\x91\xbb\x7f\xe2u\xdd\x83\xdf\x0c:\xdcT\xdf\xbf\xcd\xb2;\xb1\xc8\xee\xaf\xe8\x02\x0d&}\x06\x7fZNF\xaf \xf9m4\x1a\xfd[\xff1\xcaV\x07\xdc\x0d\xe5%\x96\xd2\x89z\x8br:G)\x17\xb2\xb9#&\x11nra`!\x99n0\xf01[\xacY\x10\x0c\x8a\x05\"\xbe\xfa_\xcf KR\xe3\x047\xf3\xa5\x99\xc9|s+\xe4\\\xe9\xe2j\xa3\x01\x93\xd5\xda\xed\xaa\xac\x87|\x7fS\xed\xf5\x96Q2\xee\x96\xa8\x9b\xdaW\xb8T\x87|\xff>\x12?pwu\x1fP\xc3\xdaqKX\xde\x1c\xa8\xacP\xce\x10uc\xb5i\xc9\xd2U\xb5\xaf\xdc\n\x16\xd4n2\xa0)\xc3\xaa(\xa1$\x11\xc7\xd8?\xdcW7U\xda\xc4\x8ae\xb1\xdb\x05\\\xce\xe8\xbd)!\xa3 \xcaEg\xaf\x0eW\xa3/{R\x8ab\xef\xa5\xacO\xbf\x15\x15\xac\xee\xf1:\xb89T~\xf2\xd7\x0f?\xff\xa4\xfe\xe5\xd9\xb3g\xcf\xf4s\x80\x97[\xc7\\\xa4\x1fI\xb8:(\x9d \xb9\xaf+(\xae\"\xac\xb3\"E\x9a[\xad\xb7\xab\xe1Eb\xbcv[\x0e\x00/&8\x8e\xd7\x0e\xcc\x81t\xc7U\xd5!M\xf4\xa6\xe1RL\xc5F\xf6\xd3\x7fq\xd1}*\x83 \xadhu58\xea\x05R\xaa\x9f\xa7\x86\x0d\x08\x8a\xce\xb9\x0eZo\x88\xa7I\x8a\xf5v\xa3\xd2Y\xefpNIf\\\xb6e$N<\x1b;\x16#\xfc\x0c\x8e\xf55\xd7\x05DrB\xf9\xfd\x89\xbf\x05\x030r\xb5'd\xb9\xf7\x14\xf6T\xab\xb6-\x86\x91\xec\xe5\xde\x81\xa9>\xd1\xbf\x9f\xd0\x82\xd7\xf9\x1f\xb2\x0b\xffi,\xc0\xfb\xb7\xf1\xbdo'\xdfL\xcb\x0dW{\xae\xc9\xd9\x90P\xb8\xc4iz\xff<#\x97\x99\xd03sD\x01ATPF\x16\x9e\x8b\xab=\xe5\x0f\xa4\x03\xbf\xb1\x0e\xaa\xc7\x8bkv\xf8\x04\xd6l\xae\x90\x9c\xd2\xea\xc6>\x89\xc5X\xcd\xf39I\xe3\xf2&Z\xc1\xb9\\\xcaIV\xaf\x0f\x90\x11@uUr\xc9\xa8\xdb\x11,\x8cj\xe3|\x97\xeb\xb5J\x84[\xa1\xa1*b\xfa\xaf\x7f\xfe\xeb\x9ea!\x0d1\xe7\xda\x0d\x9a\xa7\x9d\x10\x15\xaf\xf2xtr|B\xf7\x0cSH\xfe\xef\x12\xe5h\x81\x19n\xe6\xdb\xde\x17\x9a\xf7i\x99\xab\xd3\xa8\"\xc9\x9en\x86\xb2s\xfc\xb9Hr\x1c?\x05\x96\x17M\xa1k6\xd4\xaa\xcc\x0b\x86f\xad\xd6?\xe0\xfc\"\x89xe\x87\x11\xa1\x0bB\x0f'\x88\xe2CVg\x08\x1e^\x1cO0C\xc7\x87\x19\x89\xf18\xc9\xa6D\x16\x9f\xad\x8f}\xd2b\xb1@\xf9\xea)|\x87\xd9O$\xc6o\xb2)\x81\xcf\x05\xce+\xdc\xa1\x0c\xdc\x00\xafB\\8U\xe9J\xb2\xc4R\xd2o\xe2V\xe9;U\x87%\xd2\xd5\xe0x\xff\xe4\xe8h_\x0f\x97\x01-\xa2\x08S:-\xd2]\xe2d\xa5C2\xde\x90I\x93\xb4\xb5\x82\x15D\xaa6\xfdc\xe3\xa5\xe5\xc6\x06\xc0\xda\x88\xf8\xe2\xc4\x80\x95;Di\xd6S\xccxk\xb6\xe5\x1e\xf2\xe1\x1a2\xde\x1c>L3\xed\x91\xd7$\xa2Y\x9aJ\x13\xcap&R%:\x95\xcf0\xbb$\xb9F\xa2\x96\xb2\x0eSJ[6\x9a\xa3,\xc3*\xa0\xd5\xa1\xb05\xa6\xb7 Yr\xaeKz\xb3T.B\xa3;[&\xec\xca\xf6R\x8e\xb5\xef\x00\xf92\xb2'\xc7\x18\xeai\\i\xae\xd7\x0b=\x94\x8e0C]d\x8f\x96\xcbq\xe7\xc2}\xa6\xe3,q\xc9\xa0\xd5\x16\x9f\x14I\x1a\x8f\xdb\xf6\xd0\xa3\xf8\x8c\xb8\xa8gK\xeb1^\x1a[\xd7\xe7\x05\x1as\x02\xads\xde6\x19\xcao\x103fc:\xccz\xf1\x99\xcc][\x90\xb8H\xb1\x19\x9ewx\xa5\xa3S\xa3e\xbd\xda\xef\xa991\xd1\xaf\xcdh\x8e\xa3sZ\xa8\xfd\xfc\xfa\xab\xb7\x92\xb3\xa4\xb1\x89\xe4N\xf0/\x92\xd37\xaa[9[\xaeN\xe3\xc3\xadJ\xf8\x7f4\xbc\xa9:\x87\xa9\x8e\xe8kkU\xe5CmUS\xa7B}.0e\xedf\xeb\xdc\xa7\x0dW\xae\xa2\x90\x04URH\x82\nIPk\nIP! jM! \x8a\x85$(5\x85$\xa8\x8aB\x12TH\x82\nIP\x8e^RH\x82\xaa)$A5)$A\x85$(\x05\x85$(\xe57! *$Ai($A\x85$\xa8\x90\x04\x15\x92\xa0\x1a4DBJH\x82\x12\x14\x92\xa0~/IP\xdd\x13\x90\xe8*\x8b\x92\xac\xbc\x90D\x93~\xf4A~Sg\x1f\x89\x8c\xa3\xb2\xa0.\xe9\xa8,S\xfezks\x8eZ\xddo\x92\xackBH\x8aQ;\x10d\x85\xf6\xca\xae;]r\xb0\x86\xf6\xda\x02\xab( {%\x05d/ {k\n\xc8^@\xf6\xd6\x14\x90=\x16\x90=5\x05d\xaf\xa2\x80\xec\x05d/ {\x8e^R@\xf6j\n\xc8^\x93\x02\xb2\x17\x90=\x05\x05dO\xf9M@\xf6\x02\xb2\xa7\xa1\x80\xec\x05d/ {\x01\xd9k\xd0\x10(K@\xf6\x04\x05d/ {\xeb\xab\xba1\xa3\x87)b\x982#\xcc\xf7\xa3\xf8\xa4~\xbb\xe8\x03f5\xe2'K\xafo\xff\xbeO1\xd3!\x7f\xdb\xd5\x94\x1f\xdeZ\x10P>\xcd\xa0{\xd8\xc5\x18y0\xbd\xc3az \x8e\xdd\x00\xcad9(m\x8d\xb0X\x9eU\xb3p\x07\x0e\x1c\x82\x03\x16\x06.\xacJr\x89\xa9T\xe4\x8b\x8b\x19+S\x07G\x0c{\x85\xa1\xf11\xb0cd\xd0\x01'3w\x00\xb1\xb93V\x06C\xe1e\xd0\x1133V\xc8\x85\xeb\x8c\x9bA\x7f\xec\x0c\xbc\xf13cUe\\\xdf\x0bC\x83\xa1q4\xf0\xc4\xd2\xc0\x17O3\xcf\xec\x1aks\xc5\xd4`h\\\x0d\xdc\xb05\x18\x12_\x83\xde\x18\x1bt\xc3\xd9`(\xac\x0d:\xe1m\xe6\xe5\x80(\x8e\xed\x98\x1b\xec\x06w\x83\x1dbo\xb0\x1b\xfc\x0d<18\xe8\x86\xc3\xd9T\xb0\x1b\x16\x07\xc3\xe2q\xe0\x81\xc9\x81?.\x07\x1d\xb09\x07\x95y\xcf\x01\x9f\x83!0:\xb0\xe1t\xe0\xee\x9e9\xe0u\xe0\xe9\xc5y\xe3v\xc6\xda\x04\xa6\xe7\x80\xdd\x81\x07\x97\x03bx\xe0\x85\xe3\xc1\xd0X\x1et\xc4\xf3\xcc\xf3\x8a\xda1=\xe8\x8e\xebi\xeb\xe3-\xda\xb0=\x18\x0c\xdf\x03w\x98\n\\p>\xf0\xc3\xfa\xc0\x16\x9c\xef\x88\xf9\x81C\xbd\x86\xf8\xdf@\xf8\x1ft\x12\xae;\x0e\x08\x0e\xbd\xec\x80\x07BWL\x10\xccR\x1d\x0e\x1b\x04w|\x10\x1c1Bp\xc6 \xc1M\xea\xfex!xa\x86`\xc4\x0da(\xec\x10|\xf1C\xe8\x89!\x82\x83x=\xb0D\xd8\x05\x9e\x08.<\x1aV\xc2p\xd8\"\xb8\xe0\x8b\xd0\x03c\xd4V\xc8?4\xe1\x8c04\xd6\x08V\xbc\x11\xbab\x8e\xda\xda\xe4\x1e\xd5\xbc]w\xc0\x1e\xc1\x08\x91\x80\x11\x83\x84N8\xa4\xb6*#> ]1Jmm\xd2\x0f4D\xcd\x86\xc3*\xc1 \xaf\x84\x0e\x98%\xf8\xe1\x96\xd0\x05\xbb\x04o\xfc\x12,\xd6\xd6\x82)\x81\x07\xae\xe4\x8aeB\x17<\x13|1M0w\xbc\x0b\xb6\xa9\xad\xac\x81\x1c\xba.\x197\x8c\xd3\xb8 \xb2\x99\x19\xe7\x84a\xb1N\xb0\xe1\x9d`\xc6<\xb5e\xbab\xa10\xe0\xdc\xf5\xc0D\xc1\x0b\x17\x85\x066\xda\xa6\x0b\xc2\x92l6^\x92K\xfd#\xff\x0e\x91 \xfb\xcb\xfa\xcb\x9c, \xc5\xf9x\x99'$O\x98\x05\x11\xeb\xd5Z\xfbv\xd2\nPT\xdeM\xaa\x04g+Z\xa2Y\x92\x89\xb1\xd8f\xb6\xd5\xc6\xfaC\x19\xe7\xc6\"F\xd1\xf8k\xd5\x9c\n\x8f\x95\xc4L@\xa0\xe5\xbed|\xc5\xf4\x18\xa3U\x9e\xd6\x88RyM\xec\xff\xd5\xc5g\xaa\xf6+\x01\xf3\x7f\x96\xe1XD\xa9\x8c?\xbfC3\xfc^\xde\xd2:\x92\xbfk*\xfb\\\xe0|%\xaa\xe1\xd5r\x19bX\x10\xca\x00\x8b\xa0\xa6\x88\x86*\x8a2\xc2\x90\x06\xfdt\x16\x80\xe1Bw\xdb\xa3\xf7\xa2y\xd1\x7f\xf1\x8f\xacXLd\xb4\xac:\xda\xd28G\xa1\x8b\xa74E\x14\x91\"ccQ\x99N\xf5\\\"\n\x14\xb3\x03H\x18\xadP\x04\nE&'`,\x03\xa5\x97 m\x8f\xa9\xf5\x1c\xeev\"\x82\xd3\x91\xdc\x8d\x8a\xea\x03\xba\xcd\x8a\xc2\xf3\xe3\x9b\xbf\x86\xf3\xb9\xe1|\xee\x9a\xc2\xf9\xdcp>wM\x83\xe6\x15\xf8\xe4\x14x\xe5\x13\x84\xf3\xb9}s\x07:\xe4\x0d\x0c\x923\xe0\x9f/\x10\xce\xe7\xf6\xc9\x0f\xf0\xc9\x0d\xe8\x90\x17\x10\xce\xe7\x86\xf3\xb9\xe1|\xae+\xae?(\xa6\xdf\x05\xcf\x0f\xe7su\x9fYq{\x0f\xcc\xde\xe5\xf4\xa9\x0fV\x1f\xce\xe7\x86\xf3\xb9.\xb8{8\x9f+\xa8\x0f\xb6\x1e\xce\xe7\xaaj\xb2\xe2\xe7]\xb1s\xadm\x08\xe7s\xb7)\x9c\xcf\xed\x80y\xdb\xf1n_\xac\xdb\x03\xe7\xf6\xc6\xb8\xfd\xf0\xedp>\xd7\x0f\xc3\x0e\xe7sk\xfaC\x9e\xcf5=?\xbeFMG\xe7\xb8i\x05[\x9b\xc9\x0d0\xb2D\x1fQ\xa9Bs\xcc\x8a<\x13A\xa5\x12V+\x81\xa2\x1a\xaa\x14\xa1\xa0\xd9F\xccD`\x8f|\xd9\x9b\xe1\xc7\x11\xfc\xcc\x0d\x1e\xc9\xc4^\x91L\xa7\x143\xbe\xfdj\xb3\x0b\x8dP\xf6\x06\xb6\x9cdOe[\x8d\xbf\xad_T\x9f\xa2\xb4\x05\xdai\x82\x04\xca\xc0\x80B\x88\x92?\x9d\x1c76\xe5eg\x84(\xb3b\x81\xf3$\xaa\xfe&V[\x842\xde\x1f\x19\x15\x99\xe3\xac\x12|\x91\xd5\x81\xa8\x0d\xf7\xf3\x8d\xa8-\xc5\x94\xaeE(C7\x05\xe5\xa2>\xc7\x9e\xf2lW\xbfc\xe1n@\xc2\n\xf1\xa6\xc9\"q\x95\xae\xf8\xb6NC\xd0 \xc52H\xd9\x9c\xc1%\xe8Z\xa4\x1b\xe0\xa5\x0cI4\xff\xf4f\n)\x9e\xb22\xfa\x950\xa9\x0e+\xa7Q\xc4W\xe5\x02\x91\x8dp9OV\x80Q4\x07\xb4\\\xde\xa0\x14\x9bx\xf7\xba\xbcI\x96\x8d\x12\\\xa2b\x86\x12`y\x81\x81\xff#\xc9\xe2$B\x0c\xd7HK)A\xf1a9\x91\x9a\xd5%Y\x94\x16\xf1\x86K\x88d+5\xd4\xb51b\x028mD`\xb9\xean\xe4|l(\x97\x8fo\xe8\xc6hmtAx\xd19\xa6%\xc4-\x96\xd7z=\xf2%7*WS2\xcbH\xbe\x11\xbf\xaeVc\xbb )\x99\xbe\x03\xdb\xbe\xd0[\x7f\xb9\xc2\xbe\xdf\xed\n\xbf\xc9\xcb\x03\xfe]\xdee\xa0\xb9`A\x99AP]\xb1\xd0J\xdf\x01\xc4\x00\xc1,\xb9\xc0\x19\xc8\xaau\xb7-\xa8\xea\xbcS\xc9\"\xdc\xb7P\x11\xbb\x81\xac\x81p\xdf\x82\x81|\xf3\x1c\x8c\x95\xa9\x83\xdd\x86\xd8\xcf\xd0\xf9\x0e`\xcfy\x80\x0ey\x0f\xe6\x0e\x84\xfb\x16\xba\xe6B\x80w>\x84\xb1\xaap\xdfB\xb8o\xa1k\xce\x04t\xcb\x9b\x80\xa1r'\xa0S\xfe\x84y9\x84\xfb\x16\xfc\xf2)\xc03\xa7\x02\xba\xe5U\xd8T\xb0[n\x05\x0c\x9b_\x01\x1e9\x16\xe0\x9fg\x01\x1dr-\x1cTf\xb8oA\x92w\x1e\x86\xb1\xb6p\xdfB\xb8oa\x83\x86\xc9\xd7\x00\xf7\xb4\x03p\xc9\xdb\x00\xbf\xdc\x0d\xb0\x81\xad\x1ds8\xc0\xa1\xdep\xdf\x82\x81:\xe5x@\xb8o\xa1\xa4N\xf9\x1f\xe0\x95\x03\x02\xe1\xbe\x05\x97\xdc\x10\xd8E~\x08\xb8\xf0\x18\xee[\x186w\x04\xac\xf9#\xd05\x87D[[\xb8o\xc1-\xe7D[[\xb8o\xc11\x17\x05\xbc\xf3Q \xdc\xb7\xa0\xa4.\xb9*\xda\xca\xc2}\x0b\x15\x85\xfb\x16\x14\x14\xee[\x08\xf7-(?\xb0F\x94\xc2}\x0b\x7f\xa0\xfb\x16T\xa9\x08\xe1\xc6\x855\x19fS\xb8qAQ<\xdc\xb8\xe0\x91\x81\x10n\\\x087.\xaci\xd0\xcc\x02\x9f\xac\x02\xaf\x8c\x82p\xe3B\xdf\xec\x81\x0e\x99\x03\x83d\x0d\xf8g\x0c\x84\x1b\x17\xfad\x08\xf8d\x07t\xc8\x0c\x087.\x84\x1b\x17\xc2\x8d\x0b\xae\xc8\xfe\xa0\xa8~\x17D?\xdc\xb8\xa0\xfb\xcc\x8a\xdc{\xa0\xf6.\xf7 \xf8\xa0\xf5\xe1\xc6\x85p\xe3\x82\x0b\xf2\x1en\\\x10\xd4\x07]\x0f7.\xa8j\xb2\"\xe8]\xd1s\xadm\x087.lS\xb8q\xa1\x03\xeamG\xbc}\xd1n\x0f\xa4\xdb\x1b\xe5\xf6C\xb8\xc3\x8d\x0b~(v\xb8q\xa1\xa6p\xe3BI\xd59\xecy\xf3\xfc+\x94g\x847B\xd9\xeb#\xc2,/<\x8e~[O~\x87;\x1e\xc0.\xc5p\xc7\xc3\x0e\x85k\xbf\x9d \xdc\xf10\x84\x14\xc3\x1d\x0f\xbf\x87;\x1e\xaa+\x1e\xe2\x84O\x85I\xc1\xc5P\xdf\xef\x10\x91\xc5\xa2\xc8\x12\xb6\x1a/ )ah\xd5\xb5\x0e/\xaa\xef\xde\x11\x92\xd6\x979H\xac\xad\xfc\x05x\x0d\x10\x91$\xa3\xca[\x1cZU\xdc\xa9\xfaxK\xefnXK\xa3I\xec\x06R\x04b\x9c\x91E\xe7\xe08Z\xf0\xe9\xdc\xb1\xb8Kh\xfa%\x8e^\x90\xa4\x91\xd5\x05\x8c\x9c\xe3\xac\x8c,K\xee\xab\xb5\xc7}[\xfe\xa7(Y u\x9a\xb6dW\x17c\xfd\xe9\xe7\xb3WO\xc5.Q~Wn\xb7\x12\x11\x11\x7f\x89\xa3\xd2\x11\xadQ\x88\xa67\xaa\xacPn\xce\xd5\x8d\xd1d\x96!V\xe4\x98\xd6+\x91\xab\xe5\x19\x99\x11\xe1\xfam\xef\xe0\xda o|1TBi\xaf\x91}\xda^%\x8a\xd2[\xc2\x16\xc9B\xad\x15\xd4=\xe5\xa8\xbd\x107> yG%\x85\xbc#\x93^\xd9\x01d\xb7i\xc1\xfeV\xda\xc3}\xa3\x01\x8bq\x8ag\xe26\x9c\xc3\xdf\xea\x7f\x8f\xcb;i\xfe}\x98\xe3K\x94\xc7\xd4paQc\xcf\xf2R\x96OHv\xc6\xcd\xff{Y\xb6e\xed\xa4_P\xd6\n(\x8a\xf2B\xea\x05$\x1c\xb6\xba\xaa:kVi\n\xd5\x0d\x95_\xdeZ\x9bX\xf6\xfav\xcc\xe0Z\xc0\xe3\xbe\xf7\x0f\xc9n\x99\x8b\xab\xfb&I\xdbCI\x96~J\xb2\xf5V\x92\xd1\x15\x90d\xed\xad$\xb3[ \xc9\xa9*\x17\x17A\x92\xb7\xa3`\x14\x84p!,\xee\x82\xa4NN\x83\xa1\xbe2\xb8er\x1d$\xf9;\x10\xe6hJEk\xe5\xf1\xb2\xd2wR\x81\xac\xe3|RW\xad'\x95\xb2\x1e2\x15b/\xab\xd8\xa7\xd5\xbf\xf9\x00\xc85aqq*-X\x8fh\x9a\x96\x9e\x88B;\xd6\x0dmV\xaa\xc9K\xbf \x9d\x12\\\xed\x9a:\xad\x9a\x1br\xb5\xa5M\xae\xa4\"\xf2R\x8a\x85\x98\xde\xed i\xf0\xb7\xb7\x96\x9ap>\xd4f\xba\xbb\xe3\xad\xf1/\x82\xcb]Rp\xb9\xaf\xd9\xe56a\x0c[\xce\xb4n*n}\xd8Z\x8a\xf5\xaf\xd5=\x91\xc0Hy\x84i\xda6\x06=1\x8c]n\x1f\x0e\x7f\xdbr7Mw\xa0\xae\xd7\xb9\xe7\x16bm\x81-\xdb\x86\xb0c\xd8\xfe\xd9\xb6\x00\x83u\xaf\xe9k\xb2\xee\x9b^\xa6\xcd\xc3l,\x1eEm6C?\xa0\x8d\x0f\xe6}\x83\x82y\x0f\xe6\xbd\xb3y_s\xbee\x8au\x9co}\xd8\xe2\xbc\xfeu\xd7\x9c\xef\xc41Y_\x02n\xf7CH^\x9f0n{\"\xebJ6\x82\x01&\xef\xa3Y\xdb\x9dJ\x1a\xb7\xd4\xff\xd8\xd1U\xe9\xff\x1f{\xef\xd6\x1c7\x8e\xed{\xbe\xfbS \xf6L\x84\xab#dk\xf691/u\xe2L\x84Kvukv\xb5\xad\xb1\xec\xea\xe8\xf3\x92\x9bbB)\xb6\x98d6\x89\xd4\xe5\xd4\xee\xef>\x81\x1b 2qY\x00\x91rVy\xad\x87n\x97\x92\x04\x81E\x10\x04\xf1\xff\xad\x05\xc7s\x18~\xcb\x1b\x0e\xb7v\xc5\xde\xbc \xfc\xdd\xa3\xdfi\xd6\xa7\xfev\xbe\x98\x02\x7f\xd3\x997q\xf1\xbbn\xd2\xbf\xf0m\xa7\x0c\xdfv\xf8\xb6;\xadw\x06\xff\x92Xw\xc5\xa3\xfe\x0b\xe4\xcd\xf17u\xce;\xd5^\xfd\xfa\xd0e\x0d\x8e\x88y\x81\xcc\n}\xa5\xfds\xa2o\x91\xb9\xdf\xa2\x1e\xdbY\x9d\xe7e%v\xaf\xb8\xb1~\xe6\xef\x0c\x03\xfe\xbc[\xe0\xa8\xaf\x0cG}\x1c\xf5\xb3\x8f\xfa\xdeA_8\xa0w\x0f\xe5W\xe2\xf7a\xe0\x96\x87\x0f\xb10F\x89d\xdb\xae\xf75\xb5\x0f\xdd\xc6q\xb2\xc0W\xbay':h\x9bn1m\niIg\x987{\xecO\xdaGS\xb7\x8c\xe6}\x98\xfc\x8f\xd2H]\xb2\xe2\xc9\xfd\xacy\x9e\x86\x9b\xa2\xa7\xab!c\x9c\x0fa\x08\x15\xd46\xfb>KI\x93W\xdb\x8a6\xc5MM\xbd%M\x01Vi\x00\nN\xf6?\xd0KL\xbd\xb6\xd4#\xf0\xf9\xeabV\x1e\xbe\xb2\xf0\x95\xf5\xf2\xaf\xac\xb4\xc9\xfd\xb8H`S\xa3\x04\xc8]\xf5}\xd56\x9ei\xfd\xf0\x9d~1\x1c=\xbc\x18\x8a\xb2\xdco\xf7\xb5\xc8\x870\x16&\x9e\xa4\"\x80\xb3Y\x8aU\x87\x9d\xec\xebala\xe0\x15a\xb8\xc2|M\xc8?W*\x91\xd1\xb8\x96\xd8\xd1\x92V\x0f\xd4\x82\xce,|]\xb8*K\x02\x0f\x16 \x11j\x81\x07\x8c\x04k'-\xc8\xa6\x01\x9e\x95\x90\xcaF`\xc5\x84\xd7\xe1\xa4E+n\x9e\xc6Cy\xb4$\xe5\xcdY\x1a\x90E\x8bS\xe0\\\xc9L\xc50ey\xd4Aob[Y\xe7\xb6\xe1h\xfc\x92\x1cN\xc1\xb7\xf2\xecW|+\x1f\xe1\xad\xec\xfb\x90\xfc>$\xa7\xc0\x0c\xa3\xdd\xb3\x9e\x15\xcd\xbaj6\xab0V?<\xdb\x9f\xc6\xd3\xe64\x8c\x96\xf1\xc5\xda\xe1\x81s\xfcS\x8d\xc3b_i?\x9d\xe8\x94#\x00\xc3$\xcd\x0c\x9ce\x12\x9c\x16\xcc\x0d\xa7\x053\x8b\x9b\x16\x10\x90\x0b}\x8f\xbd\x81\xa7\x1bc\x89\xa5\x90\x1f\xf6\xcd\x1b\xbd\x9a\xd0\xfcIwr[Cf_'\xa4\x12\xf3\x80\xa6\xaf\x1e\xa8\x0c<.\xca\xfb3\x99\xb3\xb3'\xbdp\x1f\xe9\x8b\xa6\xb2\xee~X\xde\xd1\xf2>>*\xcf\xd3\xe4\xe0\xd4hV\x9e%\xe7\xecl\xa6dq+\xae\xbd+\xc3)\x13N\x99Nk\xca\xd4\xd7E\x7fGA\xd3\xa4ky\xe807\x12\xa7\x12\xfa \x87\xcb[\xf8\x1a\x8c*\xe8\x95v\xc1\x89\xce\x86\x94kN\xe3\xe1\x1ao\xdd\x8evU\x1b\x08\x06\x04=&\x9e\xad2nE\xb6t\xd7bN\xf0*\xe1\x970\x99\xf5\x86\x0f\xbc\x17\x99\xaf_\xf3\x95it4GVD\xb5#E\xd5\x8b\xf9GU\x8a\x0c&\xecN\xe5@\xe9Y\xdb\x89\x1dM\x1cg\x8b,\xffU/\xd2K\xeb\xbc\xd9u)\x16\x1aI\xb1\xe3w\xa6\xab\xc4\xbf\xb7:\xabG\xcfD\x12hkib*f\x9d\n\xc8\xc9\xc0\x08\x01\xeb\\\xeeEG\x07i\xa2Q\xf9\xf5\n\xd5\xea;Gv\xf4\xb6\x14\xd9\xa3C\x01p\xaa\x0fOC\x8f\xd4\xdf`\xcb\x82K\xf6\xcf\x91j\x95\x91\xd8d2\xc5\xc8\xba\x00\x89\xfb\xe7\xe0\xfe9I\xfb\xe7\x04\x16\x11\xd5\xbb*8M\x0e\xaf \xea\xd7'N\x86\x95\xe1d\x18'\xc3\xc9\x93\xe1\xb1\xe6=+:\xb1\xff\xddA\xcaA\xdf4dv\xd6\xa4\x11z3\x94\xe1 \x95\xcdpl\xcb\xfcaW\xaf\xd4y\xfbb\xf3e\x1d\xdc\xd0@\"4*\x97:\xf37\\\x16|\xaa\xcd\xc6L\x8fqn\xc4L\x8fGtn\xb8\x8fb\xa6\xc7\x1c^\xc4L\x8f\xbf\xdfL\x8fsJ\x94>Tk\xda\x94tX\xa4\xd2\x7fp\xafB\xbd\xab\xeb\x0f\xea\xa0\x91\x07\xaak\xa2\xcf\xb4\xae8\x19'\xbd\xd2\xed8\xd1\xc5\xa6\xa9\x07L\xfb]\xce^ak@\x047}\xc4M\x1f\x9dG\xe2\xa6\x8f\xc2p\xd3\xc7C\xc3M\x1fq\xd3G\x97\xe1\xa6\x8f\xb8\xe9\xa30\xdc\xf4\xd1\xdd\xa7q\xd3Gi\xb8\xe9#n\xfa\x88\x9b>\n\xc3M\x1f\x85\xe1\xa6\x8f\xc2p\xd3Gi\xb8\xe9#n\xfa\x88\x9b>\xe2\xa6\x8fs\x83n\xc0\x87\x9b>\n\xc3M\x1f\xff(\x9b>\x8e6\xf9B\xd4\xfa\x85\x92%\xa7\xe2\xcc\xc1\xf75B\x85\xc2\x10*\xfc\x83B\x85\xf60\x1cC\x8eL\xe7 M!\xf4\xf3\xd5\xc5\xbc\x11H\x16\"Y\x18\\\x98\x84\xac\xed\x11\xd4fQ\x9bu\x1e\x89\xda\xac0\xd4f\x0f\x0d\xb5Y\xd4f]\x86\xda,j\xb3\xc2P\x9bEm\x16\xb5Y\xd4f\xa5\xa16\x8b\xda,j\xb3\xa8\xcd\xba\x0c\xb5Y\xd4fQ\x9bEm\xd6\xb0\x1c:\x19j\xb3\xc2P\x9b\xfd\xa3h\xb3\xbe\x00\x7f\x0c\x9a\x8e\x8bH\xc5\xa0\xe9#:7\x1c\xee\x8bA\xd39\xbc\x88A\xd3\xbf\xff\xa0\xe9\xd7\xc1\xa8\xe9\xf3\xdf\xf4\xbfVwE\x7f\xe7\xdb\xf7\xfb \x86z\xe0v\x84\x08A\xdaf\xfc\x0b/\xcb\x1aV\xfdG\x89\xa9Nb\x82\x98W~\x0f\xae_\"\x9eGK\xe7\x19\x84\xf3\xcc\xb2y@4\xcf.\x99\x1fG0\xcf.\x97\xc3\xc5\xf24\xa9\xdc\xe3\xf4\x90P\x9eM&\x87\x89\xe4\x96\xaft\xf7\xf8\x9aY \x0f\xc9\xe3\x0b\xc5q\x8f4\x1e\x9c\x9e\x04eq\xd8\xfc%\xaf$\x1e\x12\xc4\xc3uJ\x13\xc3\xf5\xc8n)0$\x85g\x14\xc2\x17\xc8\xe0vx\xc5'\x82\xe7\x95\xc0\xfd\x02x\x0e\xf9\x1b\xa4\xdf\x06\xa4o\xb0\xf0\xed\xd6\xa8\xe2EowY\xd6\xf5\xe0,rw\x8c\xb3\xa0Rw\xd8'`\x99;A\xe4\xb6\xaf\x9dg\x12\xb8A\xf2vX\xdc\x86H\xdb^/\xc6\xca\xdaPQ\xdb%ig\x10\xb4#\xe4\xect1\xdb#\x19C\x85\xec\xcc2\xb6\xa7F\xd6\x9e\x9a$`\xebuGKy\x0e\xf9:\xb3x\xed\x96\xaeS\x85k\xb1\"`\xab\xb8]\xb6\xce+Z\xbb>\xfc\x82\x82\xb5KQs\x89\xd5y\xa5\xeat\xa1\xda!J'I\xd2A\xf99N|\x06K\xcf\x91\xc2s\x8c\xec\xec\x14\x9d\xdd\xb5\x81\x8a\x7f0\xc19Rn\x8e\x10\x9b\xadM\xcb+4\xbb\x1e\x8a\x05\"\xb3u\x9d\xc2)1\xa7 \xcc>19\xbf\x94\xbc\xbc'\x81ed\xa8\x88<}E\x02\x82\x19\xa3\"\x19U\xec\xe2L8\xd0\x86;\"(\xc3\xb8E\x8c[\x1c\x0d\xe3\x161nq\xb4\x14\xb1\xc5Y\x18\xc6-\x1eZ&\xe1e\x99\xf4\x92 \xbed\x91_\xb2\x0b0A \xe6\x08\"\xcc\xb1d\x98#\x0811RL\xaa\x18\xe3\x1d\xc3CrLFA\x06*\xc9D\x8a2\xd9e\x99\xb00\xb3X\x9a\xc1\xb8\xc5`\xcd\xd2\xa4\x1akQ\x18\xb7\x98\"\xda\x84d\x9b<\xc2\x0dP\x8d\x08\x8a7\x11\xf2M0~,R\xc2\xc1\xb8E\x8c[\x84\x88;A\xaf\xc6\n\x88Y\xab\x8e?|O9\xabI\x82z\x97\xae\x02\xed\xaav\x9d\x08\xe3N\xda\xf4\x0bm6l\xe8\xca\xb2x\"\x8b\x9fW|Mwm_1\x98\xaf\xa6\x07\x03\x9c\xa5N\xc8\xea\xadm\xd5\xacT\xb9>_\xd9\x05K\xe2\x13-I\xa8b\xd2B\xe2%\x11nk\xda\xad\xef\xab,xC\xb9\x15\xdbv\xdf8Z)\x0dP\x0cd!\x8d\xdbE[\x8d\x89\xb3\x0b\xc2\xda{\xda\xa8\x850\xd9\x1c\x1dT\xc9_\xc5E\xa3*\xe7[s\xfd\xf8\xe9\xcb\x87\x1f\xc5\xecU\x1e\xab\xa6\x81\x95X\xa9\xbbl\x98zA\x0e\xab\xa3\xbdW\x04PoO\xf9\xe1\xe0\xbeh_m\x9a\x82\xed;\xda\x0fC2\xffT\xda\xb4\x9bV\xbc\x9a\xec3\xcc\x89\x93\xfeZ5\xd5v\xbf\xd5\xbdW|/\x14\xe2\xb6\xb7}Q\xf3~M\x1b\xfe9\xe2}\xb0\xb8m\x8b\xa7\xd5\xf0\xccd{\xba\xdd$}\xf1$\xea-/%\xaa\xfd\x8e\xbb\x8c\xcf@\xf8\x839>\x90\x84\xdf\xc6\xa1E\xae\xaf\xd2\xcb\xa6bUQ\xabuh2\xa7\x0c\x06\xdb\xb6\x0d\xbb;X\xc3fE]?\xc3\xc6\x15\xf3P\xc0\xa8\"\x0e\xcf:\xa6\xfcs\xdfv{\xc7\xf3\x1a\xbc9\xc1ev\xe0\xddS\xbdnG\xbb\x92\xcfI7r9Y\x84&\xf7\xac\xb8\xa7B\x89\x1a^B\x92\x97qi\x83*\xd2Z\xa8V\xae\xdbV\xb6M_\xad)\x7f@\xc4\xa2\xbe\xad\x1b\xb0\xbb\x8e\xf6\xbc\xff\x9c\x88ox\x8f\xed\xf4W\xeb\xdfi/<\xd1\xcb\xb0o\xe3\xf9\xdc\x15\xbdCS!\xe4\xbdZ\x07Q\xbd\xfa\xffz\xfb\x7f\xdb\x8e|\xa0\xac]\x9dX\xeb\xe57~{K~\xa5\xaa\x0f\x88g\xfa\x8b\xe8\"\xf2?\xc5d\xcd#\xe7\x9bNr\xf7\x0c\xdex\xba~;w\xd5\xbf\x9f\xff\xf7\xa9\xab\x00\xe8\x97\x9c0\xc6\x80_j\xa6\xfa\xf9\xeabV\x1eb_\x88}e\x9b\xed \xf6\x85\xd8\x97\xdd\x10\xfb\x12\x86\xd8\xd7\xa1!\xf6\x85\xd8\x97\xcb\x10\xfbB\xecK\x18b_\x88}!\xf6\x85\xd8\x974\xc4\xbe\x10\xfbB\xec\x0b\xb1/\x97!\xf6\x85\xd8\x17b_\x88}\x19\x96\x03\xc1A\xecK\x18b_\xdf\x03\xf6e PF9\xbe/I\xe3\x8cAo\x96\xb7\xcdP\x9cY\xab\xf6\xc1\xbem\xbb3\x9dv]fH\x9f\x14\xf6o\x92\x03\xf8\xb7\xb3\xa9{\xffM\xc8\xd4\xfc\x07\xfe\xa1\xf5oJy\xff\xb7\x8c\x18\x99\x8b\x17\xb3\xe2bJ\xf8S'X\x111}\xc8\x94\x12\x1b\xfe:d}\xdeT\x0f\xb4!=+\xd8\xbe\xb7\x82bCI\xaft\xa3N\x14\x14\x9by\xc54\xf6\x0d\xf4/]\x9dU\xe5P\x9c\xa3\xd6\x7f<;\xa9\x0bE\xc0M\x16\x05\x9aA\x00M!\x009\x8f\xc0\xdaC\x80\xcbB\xdab\xa5=oa\xf6\xf5\x1d\xcf\xe7Nn\x89\x8f\x84e>\x92 \xf5\xf9\x1b\xa0SkC\xe4>\x92K\xf2#\x89\xb2\x9f\xb7@\xee\\\xb0\xf4G\x96\xcb\x7f$Z\x02\xf4\x165\xa6\xdf\x86\xcb\x80$\xb7\x14H\"\xe5@\x12+ \xfa{\xf6 \x17BeA\x92[\x1a$0y\x90\xe4\x94\x08\xc9b\x99\x90\xa4I\x85$\x97\\H\x92$C\xff\xe3\xa0\xa7 \xa1\xe7\xe6(\xd2!9\xa2|H\x8e#!\x92H\x19\x91\xa4I\x89\xa1!\x18&'\x92\xbc\x92\"\x89\x90\x15I\xbc\xb4H\x12\xe4E\xc0\x90\xf9'\x80\xc4Hr\xc8\x8c$$5\x12\xf8\xf4\x0c 9\x92\xc8Y\\\xb4\xf4\xe8-M\xc8\x92\x00\xf9\x91D\xd42\xa3\x0cI\xa2\xa4H\x92[\x8e$\x89\x92\xa4\xbf_\xf5aY\x92\xa4K\x93\xce\xf2\xf8\x15C\xf2$\xc9&Q\x12\xb8\xd2F R%\x89\x93+IH_H\x94- \xa0\\\xcf\x12f& \x93$9\x17.e\x12@+\x13$M\x92*k\x12\xbfW\xf3\xc9\x9b\x04.q\x12\xa0\xccI\xc0R'\x81y=^\xf2$Q\xb2'\xf1J\x9f$\x97\xfcIb%P\xb2P\x06%\x00\xf7F\xc8\xa1\xe4\x18\x92(\x81\xd4\xd1\xf3$\xe4\x93G D\"%\x0bdRg\x81\xfc@\x9fTJr\xcb\xa5$(\x99\x92T\xd9\xd4Y\x9a\xfcF\xf5\x7f\xae\x03\xe4S\xe2Uy\x88WF%IR\xaa\xb3(\xaf\xc4JReVgi\x9e$\xec\xd2\xf2\xc9\xad\x04$\xb9\x92\x04\xd9\x95\xc4I\xaf$E~%\xd1\x12, \xbcm\x03\xb2\x18\x89\x90\xc6\xa0r,I\x91dI\xac,K\xfc\x0dO\x91g\x9d\x85\x19\xe2'\xf4\x91\x81\xc9\xb4\xde\x07\xa2\xd9\xf8\xa5Z\x92W\xae%!\xc9\x96\xf8e[\xe79\xa9r.\xc9\xd8w#d]\x12%\xed\x92\x83T\xf2\xda\xa4\xb4\xb8@\x02\xa3\x8d+\x9a\x97\x08\xa5\xf4\xea\xf3\xa7\xabO\xd7\xef~Y]\x7fy\xf7\xe5\xeb\xf5\xea\xeb\xc7\xeb\xab\x0f\x17\x97?_~x\x1fq\xd6\xfb\x0fW\x9f\xae/\xbf\xac\xae>|\xbe\xfc\x14s\xe2\xaf\x9f\xbe\\~\xfcs\xfcyW\xef\xae\xaf\xa3j\xf8\xf9\xc3\xff\xfb\xe1\xe2K\xd4)?\xbf\xbb\xfc\xc5y\x82\x0e\xb9Lp tUEk\xc7\xd7\xa2\x0f\x88;)\xbe\xfd\xe5\xc3\xa9\xd6\x82\xc4oT\x10\xca\xee\xa1g\x0cowwAoW\xf06s\x12\xa7\xaeg\x90\xe2\x92\xbb^Fl\x1b\xea8\xe8\xca\xd3\xeetx\xf1\xe9\xefF\xaa\x86!\xa8W^\x94\xac\xf7\x9d\xdeA_Q\x07n\x1f9s\x17(\x0bt\xde\xc3ZN~\x86UR\xf2\x139\xeb(\x1f\x94\xc3\xca\xc9\xbf{j\xc5;\x94\x11$\xcd\xdfCw\x1eahW\xf4=\x8d\xab\x9a~$\x0f+\xa7\x7f\xc9W\xbd\x1bJ\x1b\xd2\xd1\x7f\x88\x08\xe8\xa8Z\xcaQ\xe0\xb0\x8e\xf2\xef\xf9jx[T\xb5\xabj\xb7US\xd4+\x99\x1bB\x8aCG\xe6\x15^?\xd3\xfe\xf5\xe2\xd5\xf0\xe2\xa6\xe73\xee\xc5\xe5\xbcn\xda\xe5\x95i\xda\x15\xff\x82X=P\xd6.,\x0c:\x80\x7f\xe17\xec\xb3\xcc?1\xf6\x93\x9e\x15\xcd\xba\xe8\xd62y\x87J\xa9\xb2i\x1fh\xd7\x14\x87\xbb\xbc\x8c\xe6\xcfQ\xd2\xefo\xb6\x15[\xb1j\x9b#`j]0\xfa\x86\x97e=N'r\xa1\xcd\xfae.(R\x7f\xf8S\x1d\xf91%i\xdetG\xa0g\x07\xf6\xf4\x00\x92\x1e\x81\x9cC@\x89\x8f\x80EA;mt\xfa\xa3`\xe5\xfd\xd2a\xde\xd4H\xe0\xe4H\xa9\xe9\x91T\x86\xb2\x9e\x15\xdd\x0b=m\xea\x8a/\xf4\xb0A\xba\x89\x9e\x98N&~e\xdbQu\xef\xb6\xfc\xcb\xb4So\xc0\xc0\xc8\xe6\x1a\xd5v\xc5Fu\xb3\xc3\x06O\xea8\x1e8\xcb\x974\xfcY\xad\xe3\xd9\xe0Ii\xde\x07\xdf\xff\xc07\xf4\x89\xad\xee\xe9\xb3\xfd\xae\x04\xefIP-f\x15\xab\xe9\x8f\xe4\xbf\\\xcf\xab\xbe\xbeN'\xc3\xff\xa9P\x0b1!\xe3\xffqUl\xe8g\x99\xc4\xf1\xad\xfc\xddQ\x98d|y1\xbcX\xeeBJ\xb6m\xcf\x08\x15\xc0\x82 \x1d,\xa7\x8a\xd1y\xa1\x03<\x84\xa6r\x81s\xc8\x92y\xa1x\xfb\xc5?\x9a=\xef|\xbc\xef\xe9\xc8{#\xcc\xdb\xa5\x95\x9a.*\xf9(\xb4\x12\x85\xb9\x86\x8f\xc7\xa2'=eg\xa4b\xbd&\x84z\xb2od\x07\\K\x08\xe2\xb1\xea\xa7\xf7\x14\x92#HS\xb8\xa04A\xb6\x12\xceGv\xf9\xf3\xd5\xc5\xbc\x01\x988\x08\x13\x07\x05_\x13\x90W\x00I\xa0\x8be\xdf\xc5\xc4A\x00\x928\x0bE\x9cB\x10c\xe2\xa0\x8c\xb4p\x0c)\x1cE c\xe2\xa0\xa5Dp\x02\x0d\x9c\x85\x04\x8e\xa7\x801q\xd0\x12\xea7\x86\xf8M\xa0}1q\x10&\x0e\xc2\xc4APZ7+\xa9\x9bB\xe9b\xe2 \xd7aA\x1a7\x82\xc4\x85\xa4\xc5\x89!p1q\x10&\x0e\x82\xd0\xb4\x988H\xd8\x12b\x16\x13\x07\xd9J\nR\xb1\xa9D\xac\xf3\xdd\x80\x89\x83\x0e\x0d\x13\x07%\x90\xaca\x8a5\x96`\x8d\xa0W\xa3\xc9\xd58j\x15\x13\x07\xc5\x91\xa9\x988h0L\x1c\xa4lH\x1c\xa4\xf3\xadHx\xc9(k\xf259\xd3!ggM\x04\xd8\x91\x82\x12r\xacV\xa5\xe6\xf3\xa4\x97\xc5\x0e\xbf\x1djhE\xf7\xbe\x11R\x08\xac\xcb1\xd1A+.\xf8\xf2\x88\xa0\x0f\x0b|Y\x14\xf0\x10\xff\xab\x9a\x1f\xa5\"o\xfcm\xcc\x89u[\xd4} )\x16\xb1\xe2\xdfp\xe4;\xf4\xb0\x04\x0ev\xa3\xdd \x9c\x1b\x88p\x03\xb0\xed(T[\x0f\x88\x0f-\x9b\xacwM\x86A\xf1\xe3d\xfc\x91\x7f)\xd6\xeb\x8e\xf6\xbd\xd6\xe7\xcdQo,)\xc3}\xd5\x95T\x03M\xeb\xac\xe8p\xc0l\xb0\x94[\x9f\xa9\xea\xd2\x9e\xdcv\xed\xf6Ej\xb1\xb1\x9e \x15N\n\xfbz9\x9f\xd9\xce\x9a Vk:\xda+\x94J<^\xe3\xf3\xc8\x1f\xb9\xb7\xeai\xaa6M\xdb\xcdtR\xfd4N/!=\xb3\xf4\xc6\xde\xb4mM\x07\x8c7n\xe7e\xfd\xb68\xffm7&l\xf4n\xbe\xac'A:\xb1\xe6ndI\x05E5&\xb6\xd2\x87^\xbe\xd7-\xb4f\xd6|\xa5[y\xe2\x895]xX\x12vjx\xfbX\xe0\xa571\xa6\xb7\xea$X}\x02\x00\xd5\x00m @\xb1SZ\x12\xae\xe6)/*\x15fVd-\x08\xad\xe5\xc6\xd6\xe0\xe0Z&t-\x0d^\xf3\x14\x17\x99\xfcr!\xc0\x96\x1ba\x8b\x84\xd82clq [$\xca\xe6\xeb\xc3 \xe9.\xb3\xe2l \xa0-#\xd2\xb6\x14jK\xc2\xda2\x81m)h\x9b\xa70pz\xcb#\xe0m\xc7\x03\xdc\x8e\x82\xb8\xc5An\xd917(\xe8\x96\x15u\x83\xc3n\xd1\xb8[<\xf0\x16\x1c\na\x89,\x17Co\xc1$\x96\xa0 \x15\x00}\x8b\x99uE\xe3o\xbe\x97 8u%\xac~\x19!\xb8\x18\x0c.3\x08\x97\x86\xc2\xf9z\x10(]e\"\x0e\xe7(\x8d\x81RU\xe6A\xe2\xc0\\\x17\x00\x8b\x8b\x02\xe3B\x99\xdeR\xe0\xb8P\x99N\x91<\x13\"\x17\xefL8&\x17j[\x02*\x97\x08\xcb\xf9`\x83l\xc0\x1c\x18\x99\x83AsPl\x0e\xe0\xe5xt.\x06\x9e\xf3'\x9f\xcc\x02\xd0E\"t\xcb \xba\x90C#@\xba#\xa0t\xc1\xda9{z>\xa0\x0e\x80\xd4\xa5Cu\x8e\xe2X0\xc9dV\xb0.\x84\xd6%\xc2u\x8e\xb2\xc2\xc9%\x01\x80\x9d?\xb1\xa4/\xaddn\xcc.;h\xe7F\xedr\xc2v\x10\xdc.\x1e\xb8\x8bB\xee\x12\xa0\xbbX\xec.\x90*\xd2_;(\x08\x05\x85\xef\x12\xf0\xbbH\x00\xcf\xd3\xdc\x14\x08\xcfQ\x14 9d\n\x88\xe7\xe9\xf2\xe1\xc4\x90\x19a\xbc`R\xc8c\x00y\xb9\xfab\x04\x94\x17\x83\xe5\xd9S>\xfa\x12>\x06\xbf\xdf}\xc9\x1e\xe1\xdc\x8f\xef\x1cP\xa2\xc7\x18\x16\xc8w\x967\xc9#\x90\x0f\xf2\x9d\xe0I\xf0\x18\xc5\x0cMO\x84\xac<\xe4J\xed8f\xcfqu\xb3\x97\xe5+}\xd7})\xd2r\xb4@\xba\xc4oD_\x8e\x16]\xbfc\x12\x99\xa3\x05R9\xbe<\xa59\x1a,\x8d\xe3\xcb\x92\x9b\xa3\xb9S8B\x138\xb2\xe5\xbaz uc\xf0\x1d\x02H\xdb\x08(\xc3\x9f\xb2\x11P\x00,]c\xb0 \xd8p\x9c3Q\xe38$\x1f\xfe\x16L\xd2\x18l\x0f,\x85\x1b$=c\x96K\x01\x1232O\x12$\x12J\xca\x18|\x1e O\x04 \x1dc\xd0\x19\x04\x94\x8a\x11P\x0c\xacCF'a\x04\xa4Z\xcc\x9bh\x11\x98f1%\xc9\"0\xc5b\xd0\xd9\x90\x0e\x0cJ\xae\x98\xe1J\xe1\xdb\x9e/\xa9\xa2}\x04\x8a\xc8>\x07J>7K77+\xef\xf3\xd5\x05&\x9b#\x98l.\xdbx\x98D\xefa\xb29\x08\xb3\x97\x85\xd8K\xe1\xf50\xd9\\FJ/\x86\xd1\x8b\"\xf40\xd9\xdcR./\x81\xca\xcb\xc2\xe4\xc5\x13y\x98ln \x89\x17\xc3\xe1e\xa6\xf0`\x0c^F\x02\x0f\xca\xdfY\x96\xd61\xd9\xdc\xd4\x00\xc4\x1dt\x96\x14M\xdba\xb29\x10c\x97B\xd8a\xb29\xd7aA\xaa.\x82\xa9\x83\xa4R\x8b\xe1\xe90\xd9\x1c&\x9b\x83Ps\x98lN\xd8\x12N\x0e\x93\xcd\xd9J\n\x92q\xa9\\\x9c\xf3\xdd\x80\xc9\xe6\x0e\x0d\x93\xcd%\xf0oa\xfa-\x96}\x8b \xdf\xa2\xb9\xb78\xea\x0d\x93\xcd\xc5qn\x98ln\xb0c\xb0m9\xfa\\\x04\xd7\x06\xa7\xda\xa2\x92\xcdU\xe6\xc8=\xdd\xd5k \x84'\xe3\xd1\xc9\xb0\x832c\x93^h29c\x94\xaad\x02\\6+\x0d\xd92e\xc8\x96\xe5\x19Y\x90-C\xb6\xccn\xc8\x96 C\xb6\xec\xd0\x90-C\xb6\xcce\xc8\x96![&\x0c\xd92d\xcb\x90-C\xb6L\x1a\xb2e\xc8\x96![\x86l\x99\xcb\x90-C\xb6\x0c\xd92d\xcb\x0c\xcb\xc1\xf9 [&\x0c\xd92d\xcb~\x0fl\xd9 <\xbb\xea?\x1c0\xdbuOj\x80J\xd9\xa3=\xb9\xed\xda\xed\xa4\x1d}\xc6\x86d\x01,\xc4fY\x1e\xa2\xc2\xdckK\xa3\x14\xe2U!\x96\xd0\xa7\xfb\xad=\xb4\x8cZ1 \xa3\x90W\xba\x9d'\x8aJ\x88ve\x05%<;\xbc\x05V\x8f\xbc;\xbb\x05\xceu\xef\xe8\x1681\xbc\x93\x9b\xb7\x80\xf0\x82Q\xae\xdd\xdb\x92Up\xa3\x021J\xf8\x17\x8bD\x82:\xb82\xd4\xc1Q\x07\x1f\x0dup\xd4\xc1GC\x1d\x9c\xa1\x0en7\xd4\xc1\xb5\xa1\x0e\x8e:8\xea\xe0\xc0Y\x12\xea\xe0\x83\xa1\x0en\x1a\xea\xe0\xa8\x83[\x0cup\xeb1\xa8\x83\xa3\x0e\xee0\xd4\xc1Q\x07G\x1d\x1cup\xc3rh\x92\xa8\x83\x0bC\x1d\x1cu\xf0\xd3\xd5\xc1\xb3\xe8\xca\x0f-\xa3\xbeM\x93~\xe5\xbf\x0f\x8a\xb28Z\xaa\xc9\x9b\xea\x816\x07\xed\x9d\xc8\xc9\xe2\xdcW\xba\xc5'*$\x8b&\x9d\x86~\x15\x0c\xd5\x8fZ\xbf\xf1\xec\xd4\xc1\xdb\x9c\xbe?\x92\\\x80\x0f\x84\xdd\x9f\xc6\x06I\xb2\xaa\xbe#\x00\xed\xd5F\x9b}`\xb3%\xfe\x14\xfe\xfa\xe9\xcb\x87\xd5\xa7\xab/\x97\x9f>\xae\xbe~\xbc\xbe\xfapq\xf9\xf3\xe5\x87\xf7Q\xe7\xfd\xfd\xc3u\xd4\xf1\xef~\xba\xfe\xf2\xee\xf2c\xd49\x1f?E\x1e\xbe\xfa\xdb\xe5\x97\xbf\xac~\xfd\xf0\xc5\x7f\xa2\x96\xd5\x93\x1c\x01Y\xbe\x1b\x8d\x8f/\x9f\xc4\xc1\xe2\xde\x88\xe5'9.\xcb\xe5F\xde\xcduo\x95\xa4B\xa0@9\xa6\x8d4\x831\xbc\x05\xcet\xdfx\xa7#\x0c\xa8\xa2i\xdf\xb4;\xb3\xba\x9e/>\xdb\xe5\xfe\xfe\xe1\xfa\xc7\xf9\x1f\x8c\xe2\x9f\xd5\xc8\x9dV\xb8\xea\\?\xda\xfe8I\xa3 )\x98\x05W\xfa\xf8\xe9\xc7\xd9\x7fO|\xb4\xa8\xe4\xb1\xf7\xce\xaf1\xfe2\xbd\x9aX\xcd}\xa0\x0c|\xddGZm\xee^v\x0f\xb5\xbf\x89K\xd2\xb5\xf1$\x8cm\xd87\x95\x10mE\xf5y\xf7\xe7\xff\xf0\x14\xd6\xef\xea\x8a\xa5.\xaa\xf3\x1a\x18\xd7\x96.k&lP\xe8iz'\x0b)\xdb\xa6\xafz\xbd#\xe3\x00\xad]\xbe?\x93\x8f6\x7fw\x9d\xe9\x15\x04w\x9b\\\xf7k\xd2\x189\x9f\xd1\xbbA\xf1\xf2\xe4LG\x8e\x1d\x07\x02\x0b\xeeu&\x0c\xf7:\xfb\xae\xf6:\x13\xd3\xf8\x18\x02O~3|\xbe\xba\x98\x95\x86\x04\x1e\x12x\xc1\xd7\x1f\xe4eC\x90\xc0C\x02\xcfy$\x12x\xc2\x90\xc0;4$\xf0\x90\xc0s\x19\x12xH\xe0 C\x02\x0f <$\xf0\x90\xc0\x93\x86\x04\x1e\x12xH\xe0!\x81\xe72$\xf0\x90\xc0C\x02\x0f <\xc3r\xd0PH\xe0 C\x02\x0f \xbc\xd3%\xf0p\x97\xb3\xd4-\xa4p\x97\xb3#:7\xdcGq\x97\xb3\x1c^\xc4]\xce\xbe\xb3]\xce\x04\x14t\xfe\x9b@\x90|\xdb\x9b\xbd\x16 \x93 M\xaf-\x1b\x99\xb5#>}\xf9\xfeL\x82Mb\x07\xb3\xd7\xaa\xbc\x03\x98\xfa\x95n\xf9 \xb3\xd4.\x10!\x89d\n\x12\xd1\xc1\xd5\xf4 \xcb\xe3a\xa1\x03\x85{9h\x16\xa0\xa0_b\xe7\xb20\xfd\x1ct\x9f\xb40\xf9\x9c\xc6=\xc7Q\xcf\xf1\xccs\x14\xf1\x9c\xc4;/\xa0\x9d!B\x89\xb6\xcc\xa4s2\xe7\xfc\xa2\x94\xf3\x11\x19\xe7\x97\"\x9c\x8f\xc57\xbf8\xdd\x1cf\x9b\x01C \xb4\xc7g\xa4\x9a\x1dLs\xb8&\x8by\xe6\x9c4\xb3\xed\xee\x00\xc1\xcdXn\x13\xb1M\xc46\xad\xbfgz\xb6\x11\xdbDl\xd3n\x88m\nCl\xf3\xd0\x10\xdbDl\xd3e\x88m\"\xb6)\x0c\xb1M\xc46\x11\xdbDlS\x1ab\x9b\x88m\"\xb6\x89\xd8\xa6\xcb\x10\xdbDl\x13\xb1M\xc46\x0d\xcb\x81\xd0!\xb6)\x0c\xb1M\xc46\x7f\x0f\xd8\xa6\x90\xdf\\u\x17?Nj-\xfe\xa0v\x0d\x1c\xb4\xb3\xdd\x0bn\x19\xa8a\xa5m\xd5\xb0\x81V*\x9af_\xd4+1S\xe9G\"\xc5\x06&\xbd\x13\x87^\x0dG\xea\xe5)\xc2\x0b\xe4\xa3\xa8,\x8b\x8ce\xc97\x9dn\xda\x84H\x9a\x17\xf6J\xb7\xf3D\xe9$\x87\x9fL\xf3\xae\xf2x\xd7w\xc2\xeb'\x07\x97\xd7\x92l\xf0\x1eX\n\x9b\xdc\x15i>\xd2X \xc2\xf3;\x06\x12\x87m\x05\x9d\x1ft$\xdcaO\x19\n\xc5\xbeU\xd2#\xac\xb1F\x8d\x95Us[\x1b \xdclc\xe4\xa5>D\xe1\xcc\xf6\x87t(\xc83@\x0e%\xa9\x1fOvd\x9cy\xc5\xb4L#\xe2\xe8.\xc7\xa0\xe7\xf0\xa7\xa5(;\xeb2\xf8:}L\x1bo\xfc\xe7\xab\x8b\xf9\x94\x0d\xc76\x1c\xdbN|l\x13Su\xcf\xe4\xefJ\xfc>\x19\xd5$\xc6/\"Wn\x87Gq\x9c\xf2[G\xb5\xbfV\x0d\x93E\xa9_OvX3\x1db\xda\xf4\x0bEze\x9a\xa6S;@\x7f\x9dl\xdb\xf5\xbe\xce\x9b\xa4\x93{{\xb5\xa6M\xeb \xab\x83\x1dF\xa5\xa0dJ\x08+\xdbJ|\xda\xf2r-\xc7\x0f\xe3\xeb\xaa+\x18]Ie{\xd9\x95\xb7\xc5S\xb5\xddo\xf5|U\x16\xc9\xbf\xb4\xc7\xb1\x9c_\xcb[\x99m\xf1\x94\xa7\x121\xd7L\xdc\xaa{\xbcf\xd5\xc0\xae\xb9i\x8bzu\xd36k\x9a\x1a\xbe\xa0\xae\xc8\x0b\xe27yG\xbb\x92\xbf5e\x99\xa4`\xed\xd6\xf6upS\xb7\xe5}\xbf\xda\xd1n\xf5L\x8b\xb4\xe8\x06@\xe8\xc4P\xbd\xe1='/\xcc\xabI\xf8\x85'\xe7\x00^\xe2rX\x01\xbd\xc1\xd5;[\x8di\x08\xad\xe2\xfb\xda\xf6\xfb\xa9\xbd\xaf\xe5\xcb\x06\xfc\xc66\xbe\xe2UG\xd71e\xc5H\xb5\x0co+\x89\x98\xcbW\xd5\x99\x8a\xf1\xa8XO\xfa\xfdM\xbf+\x04i6\xae\xd3\xdd\xd3g\xeb\xdb\xfdw\xf4f\x87\xbc\xd8'\xefu\x9d\xdb{\xf0X\xd6\x17\xbavs\xd2h\x9b\x9a\xad\xdb\xd3\x87\x9dg&\x0d\xc48\x08\x13\x1c\x84\xed\xa7\x9f\xda \xec\x93,\xf4C\xea\xea\x81\xc3Xi\x8e\x1brH\xe5\x93\xeb1\x19\xfd8\xea\xdeN\xd1\xdd\x94P\xe5Y\x0bue=\x99$\xee\xe9\xf3\xa4\x8a\xfc\xbf\xb5\x922\xd4L)\xf1\xbaMYk\x19z\xd3\xf5u\xd1\xdfU\xcd\x06\xfc\xae\x9b\xbd\xe0\x0e\xbf\xc3t\x89\xeav\xa8\xf3'/\xafku\xc8\xef\xe8%\xe6|\x8e\xd3\xdeA\xd5\xa6\xa1\xeb\x95\x9a\xff?V\xcd\xba}\x8c|;h3\x86-\xeb\xe4\x7f[5+u9\xfe\x9d\x91\xe5Z\x0erv\xdd>6\xac\xda\xd2\xd5?\x8a\xaa^\xad\x95\xd0\x99t-\xd1\x89V\xb7\"P\xa4mV\xebv\x7fSS\xd1\x8e\xa4\xe2\x82U?\xb8\x9el\xc91.\x16V\xa0\x86\x05 \xa5\xc3\x1f\xab\x88~\xe1\xf1A\xa5j6\xab\xaa\xb9m=\xef\xbdky\xd8%?jx\xfb\xa9sE\xd2\x10\xf1YW\xd72\x12\xa0`m\xa7_l\xd3W\x9fQ\x8c\xfa\xfdd_|\xbcU\xa7\xd1\xd1\x14\xcb\x91\xdcSzVtlu\xe7\x0d\x8e\x0f\x16\x12~\xd7\x12\xcf\xe0:\xda_D5H\xc1\x14 5t\x18\xb15\x90\x00\xced8\xe6\x9a\xff\x99\x92O\x9f\xf9\x0f\xce\xe2\xf6\x0d\x7f\xdd:b\xaf\xaafM\x9fV2\xd1\xcf\x91\x1b\x1e~\xafI\xbb\xe4URM\xafzR5e'\x82\x80\xf8\x98_\x94w\x84\xbfw\xc5\xdbe\xea\x17w\xb8\x9f\\du\xb3[UC\n\xb9\xe2)p\xb9m\xf1,\xe3\xe5\xe4\xacHD\xfb\xd3\xb2\xddn+&\x032\x99\x8c5\xf6\x95W\xb6\xcd?T\x98\x88\x0c\x8a\xf1\x86\x7f\xfe\xe7\xb5\xb8\xd2Ob\xb6\xf771\x01\xfb\xcfa\xd9\x83\xd1n;|\x1e\x88\xdb\xa5\xbe\x07\xdc\xc5\xfd\xb5\xea{]\xdcO\x15{\xc7\x1f\xc5\xff\xb4#\xa2\xb2k\xac\xf6\x0d\xab\xd2G\xe9\xf1\xfe\xf3\xfe\xf8\x86\xdf\xa0\x85}\xe0K\xb5\xa5=+\xb6;\"j\xa6z\xc3\xf4\xa6W\xbd\xaa=Y\x8b\x9cb\xce\xc2\xea\xea\x816\xb4\xef\x87\xf9\xa7\xdd\x15\xac\xdd\xde\xf4\xacm\\k\xfc\xda\x11\xd3|Ts\x83\xb6\xf0owT\x84\xd4\xc9\x1e\xa5\x03\xc4D\xc3\xee\x8a\x9e\xdcP\xda\x185\"?\xdcW\xb5\xeb\x19\xe6\xd6\xeee2\x8d\xa1\x90\x9e\xb2?\xe9\x8c]=\xf5\xc6\xb8\x97\xf3\xc7Ivv\x11\x18\xc6?%\x1f\xdaR\x11\xcf\xe2#\xd9\x1b\x1f*\xe3\x04\xcb\xb6\xb9\xad6\xfb\x8e\xae\xc9\xb6\xeao\xe8]U<\xb8\x02c\xb7\xa2\xb3\xeaO\x1d\x91\x95l\xc1\x9e\xb6y\x87\xa2wD\xd5\x87\xdc\xd3\x1d\x1b#d\xf7MC\xf9\xfb\xb5\xe8\x9e\xe5\x8b\x8et\xb4X\xcf3\xac\x99\xf6\xb1\xd5\xd9\xe0\xfe\xf3z\xbf\xfd\xc1\xf6\x84\xfe\xe9?IQ?\x16\xcf=wzQ\xbb\xc7\x97\xc9\xf3}!+h}\xbc!\xcd\xfcU\xdfuc\xe2a\xe6K\xd1?\xbf\x9eMf\\\xa1\xef\xdb\xb6\xa9X\xdb\xa9<\x96\x95\x03\xa5\x1f\x1eI\xfe=\xf5P\xb1g\xcb\n\xae|O\x8a\x8b\xa9\x8f\x0c\xd0lJ\x9bo\x8f\xc7\x05_\xe6\xb8'#\xee\xc9\x08\xdd\x93\x91\x80\x9eA3E\xacl\xd5\x84\xa6\xaf\x1a\xb2\xf9|u1~a\xab\xaf\xc2\x9e<\xde\xd1\xce\xd6\x89\x1cs\x8d\xb2\xedd\x19\"-G'\x1b?\x80\xef\xfc\xa5#\x96\x0dL\xcfX\xdd\xa1\xcf\xb8n\xb7c\xbd\xbd\x01\\\x1d\xddQ\x11\x18\xfbS\xd1\x0d7)\x10\x0d2u\x8b\xe8\x99\xaex\x90i,\x9aw\xf1\xc2\xfc\xba\x02-a\xd8\n9\x9f|\xea9\x19\xb3\xe1\x8f\xb8\xaeq\xe0\x1f\\\xd7\xc8\xbe\xae\xe1\x0d\xf0\xc0\xac\xd6A!\x84\xb8\xde\xce\x98\xd5:\xafs\xc3\xf9\x981\xabu\x0e/bV\xeb?PVk\xff\xaa\xf4\xf9oe\xdb\xf4+\xb5\n\xea\xcbhm~\xe5\x99\x12\xed\xfc\xd3JRG\xa5HS%KU%\xb9\x16\xab_\xe9f\x9f\xe8Z\xf5CQ\xafL\x9fe\xfd(\xf4.?\x07^\xe7\xe1\xa5\xe7\xe0| \xbc\xe4\x11\xfa\xa4\xca\xba\xe4\xecYp\x0e/7ghl\xf8\x93\x8b\xe4_f\xf6/2'.1\xbb3\x8c\xc5,0g]^\x86/.\x87\x97\x96\xc1\xf7\xda\xbf\xac\x0c\xbb\xdf\x19\x97\x94A\x0b\xca\xa1\xe5\xe4\xf0b2\xac]i\x0b\xc9\xa4\xdd\xbb\xb2\xa2\xa6,#\xe7\\D\x8e]B\x8eX@\x06w\xb8\xa5\x83K\xae\x85\xe3|\xcb\xc6\xc0E\xe3p\xf3\xf2.\x18C\x96\x8b\xe1\x8b\xc5\xd6\n\xcf\xdf\xfc\xae\xd5d\xb5\"F\xd7\xfc\x0c1\xf5\xb1\x146\x9d\x0cI\x83\xae8eYp\xc2\xf5&\\o\xb2\xfe~J\xebM\xe6\xd7\x88\xab\x17\x9a\xc7\xe8'B\xff\xe7@\xe8\xce\x9eQ\xa3\xac#%\xe6\x18?\xb8\x98H\x1d;|o\xadiM7\xe2\x0d\xd6\x9f\xff\xa6\xfe\xa3\xedD\x03|\xdf[\xc6\xa0\xf0^\x9f\xf4~,j\x8c\x03\x11k\n\xe3\xdfE\x08\x88\xfc\x08\x1b.6\x94\xa4\xdcd\x8d\xfb\xb0]E\x1dw\xb2\xdffc\xc3W\x96:j\xfb\x16\x0f\xdeX3\xff\xc3\xb3x\x8b\x9fi\x8f\xf2\xa0L\x04\xf6\xc0\x12\xd0\xbb\xdcH\xdb{\xda\xf4\xe4\x8e\xd6\"\xe7\xa2\x13\x98!\xa4(\xc5dY}fxH\x95\xc7F\xe6ol\x1b\xa3w\xa9\x9c\xd9\"k|[VBg\x1c\xbe\x88]E=\xb42B\xbe}\x94\xcb\x8em\xe3\xc1\xb3\x02\xb7\xf4\xa6\xa8\x8b\xc6\x15.\x96q\x80pF\x98K\x03\xf5\x99b\xcb=\xbd\xb0\x18h/\xb9h+s\xc3\x1f\xd1!T\x8ah\xd9\x1c\xbd\xaa\xcbo`\xd1\xa8\xca\xf9\xb2\x91\x7f\xfc\xf4\xe5\xc3\x8f\"\xaf\xa3\x95\xe2S\xf2\xce\xb1\x9dI\xc5\x8c\x8c\xde\xf6\xd6\xa8\x9e:O\xa2\xa7\x06\x87a)l\xdbv\x94\xf4\xfb\x8a\xe9\x15xkae-d\xa7\xe1\x85\x9d\xf2-i{\xf1\x8f=\xa6\xaeg\xc3X\xffzD\x7f\xdc\xa5\x1d>\xa7>\x14hRICi\x98\xe6\x910\x04\x88\xc9\xa7\x9b\xe5K4}\x15\x19\xd1\"D\x8b\xa0h\x91O\xb8W\xab\x06\xb6/\x81`$\xb0\xad\xa0s\xeb\x97\x0b&\x8aS\x86+\x0fy\xa6\x0b\xb8\xa3\x18\xee(f7\xdcQL\x18\xee(vh\xb8\xa3\x18\xee(\xe62\xdcQ\x0cw\x14\x13\x86;\x8a\xb9\xfb4\xee(&\x0dw\x14\xc3\x1d\xc5pG1a\xb8\xa3\x980\xdcQL\x18\xee(&\x0dw\x14\xc3\x1d\xc5pG1\xdcQln\xd0\xdd\x9dpG1a\xb8\xa3\xd8\xf7\xb0\xa3\xd8\x14'2\x8a\x9a|LN\x8f\x9aH\xae\xc3O\x87L\xa0%O\xe7\x02\x10\x10\x83dS#\x101H\xf6\x88\xce\x0d\x87wb\x90l\x0e/b\x90\xec\x1f)H\xd6\xcel\xb7\xdd!\xb2}\xdeQ\x93+\x92\xc5\xda\x00\xee\xcf\xe6q\x03\xae=9{\x8c\x97\xf5\x81\xd9\x93\x82^\xe9\xf6\x9f(\x91m\xb6\xef\xd4\x98l\xb3nG\x87.\xbfo*\xbb\xef\xcao\xd4rk\x1dt\xeb\xc7 C\xb3/x\xcbSP\x89|\"\xc7Y%\xc4 \xeb\x9e}s'\x18uX\xe0\x845\xed\x99~I\xc0=A\x1b\xd6y\x9f\x12\xff00\x9as@\x18\x0d\xf0\xdcJ\x83<\xbd\xd2\xca\x8e\xcaa\xcc\x9f\xddu4\xe0\x8d\x94\x16\x0e\x185-\xe6\xe6K\x9b\xd5\x9eL>\x92\xd4\xdf\x86Hf@yf_!\xacm\xef\xc9\xae\x9em)`\xb3\xb2\xe5\x1f\xb6\xa2\"\xee\xb4\xe7\xa6%91\x94=t\xb4\x04GN[0\xdf\xc4\xfaI\xc6\xfb\xfb\xf0\x9b\xd1&N\x1c\x0b\x0e9Q /E\xbd\n\x04\x0c\x8c\x16\xe5\xc4x\x97\xcc\xea3q\x89\xfaM#\xe3\x80\xd2\xc4\xe0{\x8a\x0f\x98?\xa3\xf0\xbd\xa8f\xa5Y8T\x19>\xe0\xbd\x02\xeeQ\xa5\x0d\xe3\x07\xf2|\xe2`\xfc\x00\xc6\x0f\xd8\x0d\xe3\x07\x84a\xfc\xc0\xa1a\xfc\x00\xc6\x0f\xb8\x0c\xe3\x070~@\x18\xc6\x0f`\xfc\x00\xc6\x0f`\xfc\x804\x8c\x1f\xc0\xf8\x01\x8c\x1f\xc0\xf8\x01\x97a\xfc\x00\xc6\x0f`\xfc\x00\xc6\x0f\x18\x96\x83\xe5\xc6\xf8\x01a\x18?\x80\xf1\x03\xa7\x19?\x80\xe4z\x1c\x16\x8c\xe4\xfa\x11\x9d\x1bf\xae\x91\\\xcf\xe1E$\xd7\xbfSr}\xa0\x8c|\xb8\xfa\x7fYp\xf5_\x87\x13'\x90\xfaX\x1e\xa9\x9a\xdbV\xdc\x13\xb9q\xd5p\xe5\xa1,\x1f\x94~-\xdb`\xb9\x9c:\xfad\x89\xf4\xd1\x03\xa7\x81.\xe8]x^\x90\xd2\x9e_r2\xa5\x99\xa2\xd9\xa3\xbb\x1c\xe0\x9cY\xde\xff\x10\x987\xd1\x90w\xd5\x88\xa9\xab\xfd\x13\xad\xe4\xb7\xb7\xe9\xf7\xfdj\xb7\xbfq\xe2fA\xef\x12\x80\x87 \x00\x10!0\x0f\x93\x08/\x93\x04X\xc4[\x98]1\xf0,\xa0\xe5\x86FH\x18\x1c! \xf0\x88\xbf\x01\x05\xbb\x03\x03$$\x17DB\x12A\x12o\x81\"O5\x14&!\xcb\x81\x12\x12\x0d\x95x\x8bRbw\x14XBr\xc3%$\x120!\xb1\x90\x89\xbfg\x0f\x00\n\x144!\xb9a\x13\x02\x03NHN\xe8\x84,\x06OH\x1a|Br\x01($ B\xf1?\x0e\x05\xff\xc8\x0b\x82(\xe480\n9\"\x90B\x8e\x03\xa5\x90H0\x85\xa4\xc1)\xa1!\x18\x06\xa8\x90\xbc\x90\n\x89\x00UH<\xacB\x12\x80\x15\xc0\x90\xf9'\x00\xb4Br\x80+$\x04\xaf\x10\xf8\xf4\x0c\x00\xb1\x90\xc8Y\\4\xcc\xe2-M\x80.\x00\xa0\x85D\xd42#\xd8B\xa2\xe0\x16\x92\x1bp!\x89\x90\x8b\xbf_\xf5a\xd0\x85\xa4\xc3.\xce\xf2\xf8\x15C\xc0\x0b\xc9\x06\xbd\x108\xbbA \xf0\x0b\x89\x03`HH\xb1N\x04a\x08\xa0\\\x8f(\x96 \x8a!I\xce\x85\xc31\x04\xd0\xca\x04H\x86\xa4\x822\xc4\xef\xd5|\xc0\x0c\x81C3\x04\x08\xce\x100\x10\xcd\xc6\x0f\xff\x90\xbc\x00\x10 A@\xc4\x0f\x029\xcfI\x05\x84H\xc6\xbe\x1b\x01\n\x91(X\x88\x18\xc0\xd0\xd4\xfeQT5]\xfb\xd5\xa9\xa9\xfe;7\xe87\xbc\xbc\x12\xd1\x11\xf7\x8fwT\xad\xe4\x98\xb9&x\x0f\xbf\xa1\xb4QG\xbb\xefp\xd7nE*\x0b\xba&=+\xd8\xbe\x97\xcb\xdd\x07Y)\xa4\xc9C\\\xad\x84\xb6@]\xa8\x9a\xe7\xf6\x94\x7fw\x9e\xf6\x83\xac\xe7\x98\xa5M\xfdK\xc8\x1b\xf6S\x00kA\xb4\xd9o\xdd3\xf47\xe4\xa7O\x1f\xdf\xaf\xae\xbf\xbc\xfb\xf2\xf5z\xf5\xf5\xe3\xf5\xd5\x87\x8b\xcb\x9f/?\xbc\x07\x9f\xc1\xff+\xf2\xf0\xcb\x8f\x7f\x06\x1e\xef-\\\xa7/\x88j\x82LM\xf3\x02\xe2\xb2\xca\x81#\xbb11 9\xb1\xce.~\xfb\xa1j\xca\xda\xfd\xe2\xefi}\xfbf\xcc\x12\xe3\xe8\x04#)!\xf7x}\x81\xa6\xcd/9\xea\xe6\x82QQ\x7f\xac\xfa~/5\x05\xf7\xab\xc8P\xd5\xc7R\x1d\x8b\xa3f\xed\x167`8n\x861\x8e\x7fg\xb4\xdb\xf6\xc4\xbe_\xe7h\x81\xccl\xd9t\xfbm\xdbT\xf7\xd4\x92\x1dc4\xc0\x0d&\x11>\"\xe3U\x8d\xad\xaf\xef\xf6\xdb\xa2y\xd3\xd1b-P&1\xa3\x0b\xf9\x88@\xfcD\x14\x01\xc0\x9c\x04\x049N\x1b\xf5e\xcd\xd4PZ\xdf\x1c\x7f\xec\xabMS\xb0}G\xc9\x0f\xf4\xc9\xff\x91\xfc\xf5\xaa\xed\x04\x97\xf8\x1f\xf4\xf9\xa6\xe8\xa9s\xf0&\xe4\x91\xde\xf4\x15\xcb\xb1\xda?i\xb1*\xd6\xda\"\xfd[]5\xf7\xbe\xa1\xa7\xdcw\x15{^\x89o\x95\xd2\x9b\xa7/\xa5\x86\x81{2\xbf\xbc\xb5%t[TuP$\xd7E\x11U\x94\xbb\xcd\xceD.\xa3\xa54U\x15\xab_\x04R\x96\x1a\x1a\xa1~\xb5\xd7jL\x1a\xea\xcf\x96\x08\xa8\x16$C\"\xf4\x0e\xcd\xab\xa5\xef\xce\x19\xa9n\xc7\x1f\xcf\xc4\x88\xaa\x8e\xf0\xc04:\x8bb\xd5\x1fL\xef6{#K[\xc8E\xbeT\x89\x11\x0e\n\xa5G\x8cw\x92H\x80\xe8q\xd1\xb6j\x86$\x89\xce\xe2\xa6\x13I\xd6\xea|y4\xe4\xa0\xb2\xddn\xab\xbe\x87\xbe4\xc7\xc3'/F\xe3\xcfc\x1c\xc1\x91_y\xe35W]\xc1\xfciE\xa1w\x85X\xca\x9d4T\xe5k4\x0e\xf2\x96%\x0b\x90H\xc1 \x83\xcb\xac\xa1\xe2{\x17\xf0\xda\x03\xf9\x8b\x00}FT\x9dBK\xf2\x80\x07B[\x8ck\x89\xba\xbc\xfe\xf41\xba\x8d\xf8syWt\x1b1'\x0c\x163\xce\x06\xcf\x88\x08_\xba\x15\xf8\x96?\x0f&!\xdb\xe2i\xf5\x8d\x1d\xa0\xab0\xe9W\xdb\xe2\xa9\xda\xee\xb7s\x8f\x04\x0b\x93\xa3\xe3\xf8\xe4\x97EC\xe8\x03\xed\x94+\xa3}#y\x93Sp\x91Q\x13\xab\xa7\xd6E\x15\xcc\x9a*x\xfc\x8e\x16==\xc0t\x0dOK'\x05\x8b\n;q\xbf\xe3o\x87`R^\xa0\xe3\xa0o\x1c\x12\xe9`\xa3\x96\xfa9\x14\x12\x83\xf8\x83\xed\xa9|\x0c`v\xf2N\xad\xed~\xd9V\xcd\x8a\x7f\xa8\x1a\x19\xe5\x17\xbc\x85\xa1\xed\xb4\\\xf5`\xb9\xe5u/\xbe\xa0\xc9\x9a\x96u1\x0f\x83\x98\x15&z\x9c:Z\x17hk/\xa4~C\x08\x80\xf1\xd94T\xea\x8c\xb0v#\x17\xb4\x84\x8c\xc0t\xbc\x88\xb5\xa8bk\xc4\x95\xd8\x97\x16\x7f5\x9a\xcb'\x02\xfa\xeb[\xc5\x97W\x1d\xa1O\xf2\x06\xca\x9b-\xa6\x0eU\xe3xy_\xd7E\x7f\xc7_]:\xca\xc8\x05\x07\x17\xdc\xad\xf2\xc9S\xea\xd4\xe42g\x12)\x14\x84[\xdbu\xae\x17[Y\xd4\xe5\xbe\x1eD\x99\xdb=\xff\xc2\xb2_p\xdf\x98\xbb p\xdf\xb5{F*&b1\x9a\x0di\x1f\xc4w\xea\xb0\x84@\xfevG\x1b\xd9T{\x03\xba\xe9\x82\x8c\xfd\xaa\xd3i\xe9\xd9l\x88\xa9z\xfe\xae_WLc_\x85\xd1}\xac\xe5=\xde\xb5=\x1dC\x83\xec\x175oc\xd5O\x00K\xa3G\x88\xa6\x8dM\xb0\x96\xb4\xae\x06\x05V.\xa3\x0bJ\xd0~\xd5\xc9\xfd{K~m\x85[w\xed#\xedt8\x9f\xbe]t-TUg\xb7\xd5\xeb\xad\xa2 \xf6\xabm\xf75\xabvu%+7\xbd\xf6\xc1 \x93\xa7\xce\x88\xdc\x99\xa4\x9c6\xefL\xffZF\xf5\x88\xcc\xc7\xce\xed\x010\x11\xb10LD\xfc\x07MD|pGE\x04\x9e%T\xcd\x9b~\xd8\xb2\xb4'\xf3\x0d\xdbB\xec0\xcb\xb02\xcc2\x9cg\xa2\x17\x1b8&\xbb-f\x19\x06\x04\x89\xb1\x1c\x01b)\xc1a\x98e8c XL\x10XT\x00\x18f\x19^\x1a\xec\x95\x10\xe8\x95%\xc8+>\xc0\x0b\xb3\x0c/ \xe8\x8a \xe6J\x08\xe4\xc2,\xc3\x98e80K\x8a\x0e\xcc\xc2,\xc3\xa0 \xac\x94\x00,\xcc2\xec:,\x18h\x15\x11d\x05\xc9\xa1\x1b\x13\\\x85Y\x861\xcb0$P\n\xb3\x0c\x0b[\x12\x0c\x85Y\x86m%\x05\x03\x9eR\x83\x9d\x9c\xef\x06\xcc2|h\x98e8!H)\x1c\xa0\x14\x1b\x9c\x14\x11\x98\x14\x1d\x94\x14\x17\x90\x84Y\x86\xe3\x82\x8e0\xcb\xf0`\x98eX\x19f\x19\xc6,\xc3\x98ex\xfc[\xb2s\xc3\xf9q1\xcbp\x0e/b\x96\xe1\xef>\xcb\xf0\xf9o\xc3\xbf\xe5o\xa9i\x87\x87\xac\xc3\xe6>\xe9\xf6\x84\xc3\xe3!Cy\xbb\xa2\x1a\xdek\x93\xbc\xc3\x87\x17RG\x9d~\xbea\x17\xc3\x90\x04G\xc1\xb2\x06\x07W\xe3!\xcb\xd9\xb9\xf3\x05\xc7g\x0b\x86\xe5\n\xf6z\x93\x04=J\x00\x80\x07\xc0\xa3\x04\xecU\x92\x8ayx\xca\x8b\xca\x0e\x9c\x15\xf5\x08\xc2\x1e\xb9q\x0f8\xf0\x91 \xf9H\x83><\xc5E\xe6\x03^\x08~\xe4F?\"\xe1\x8f\xcc\xf8G\x1c\x00\x12\x89\x80\xf8\xfa\xf0\x00\x87@!\x90\xcc\x18\x08\x08\x04\xc9\x88\x82,\x85A\x92p\x90L@H\n\x12\xe2)\x0c\x9c\xf1\xf7\x08X\xc8\xf1\xc0\x90\xa3\xa0!qpHv<\x04\n\x88dED\xe0\x90H4&\x12\x0f\x8a\x04\x87BXn\xdf\xc5\xb0H0\xaf/hB\x05@Fbf]\xd1\xd8\x88\xef%\x08\xce\xe6\x0b\xab_Fx$\x06\x1f\xc9\x0c\x90\xa4!$\xbe\x1e\x04\xca\xe0\x9b\x88\x918Jc\xa0\xec\xbdyP\x120\x0f\x01\xc0I\xa2\x80\x92P\xf2\xcb\x14\xa8$T\xa6S\\\xca\x84\x96\xc4;\x13\x8e\x97\x84\xda\x96\x80\x98$B&>\x91.\x1bh\x02FM`\xb0 \x147\x01x9\x1e9\x89\x81N\xfc\xf9x\xb3\x80'\x91\xe8\xc92\xf8$\xe4\xd0\x08\x00\xe5\x08\x08J\xb0v\xce\x9e\x9e\x0fD\x01\xa0(\xe90\x8a\xa38\x16\xcc\xbb\x9b\x15H !)\x89P\x8a\xa3\xacp\xbe]\x00\x98\xe2\xcf\xb5\xeb\xcb\xb4\x9b\x1bO\xc9\x0e\xa8\xb8\x11\x95\x9c\x90\n\x04S\x89\x07U\xa2P\x95\x04X%\x16W d\xcf\xf5\xd7\x0e\n\x10@\xa1\x95\x04l%\x12\\\xf147\x05^q\x14\x05\xc8\x97\x9b\x02\xb0x\xba|8WnF\x88%\x98'\xf7\x18 K\xae\xbe\x18\x01\xb3\xc4\xe0,\xf6,\xb8\xbe\x1c\xb8\xcc\xa2MN\x0d\xf6\xdd\x9b\x92\xfdVd\xb9u\x94\x07\xcd}\xeb\xcb|\x0b\xabyR\xd6\xdb\xe8\x9c\xb7\xc1u\x12_\xbe\xdb\xd8l\xb7Q\xb9n\xe32\xdd\x82\xf3\xdc&d\xb9\xf5\xe5\xb8\x0d\xfa\x0fv\xb3\x97f\xb7\x85\xe4\xb6\x85e\xb6\xcd\xd4\xa0\\9m\xe1\x19m\xcdz-\xaa\xf8p\xd4\xa2\\\xb6\x81Tul\xb9\xaa\x1c\xcca\x1b\xbc\x95\x04\xec\x15\x921{m0\x89_8sm\xe6\x96e\xceY\x0b\xceX\x1b\xccW\x1b\xdf\xce\xa5\xb9j\xe1\x99j\xe3\xeb\xe6\xbd\x07\xd9r\xd4B3\xd4\x06\xf3\xd3\xc67097-,3m\xb0B\xe1\xac\xb4\xb0\xfb\x913#\xed\x92|\xb4\x90l\xb4`\xa7\xf8\xf3\x02\xc6:&&\x0b-\xe4-\x01\xcfA\x1b\xca@;i\xc9\xf2\xfc\xb3\x19^T\xf0\xcc\xb3\xb0\xbb@\xe2\xb3\xce\xca\xcc\xb2\x9e\xf2\x16\xe5\x9c\x0d\xfa\x88\x80\xfcD@\xd9f\x83\x1d^\x1b\xdc\x99\x04\x9cg\xd6\xcc#\x1b(\x10\x9cI\x15\x96c\xf6H\xcd\x8e\xc9.+\xc7\xb2@\x819r\xcbFe\x96=\xa2c@9e\x87\x9c\xb1\x81\x02\x83\x19e\x83\xae\x01\xe5\x8b\x05\xb9\x03\xf6N QN\xcb\x9c'\xd6\x93%\x16\x9c#6\xe8\x0bX\xeb2f\x87\x05\xe7\x86\x0d\xd7,-/\xac\xca\xf8i)\xcf\x9d\x156gNX`F\xd8\xe8|\xb0f\xeeW{\xe3\xdc\xd9`\xf3\xe6\x82\x85d\x82\xcd\x9b\x07\x16\x90\x056)\x07\xac\xce\xf7j+/\x98\x016-\xff\xabZ_\xb4\x94\xe7\xce\xfe\n\xce\xfd:y\xa6\xa0\xd9,\x87d\x96K2Yb\"Km\x98\xc8\x12\x13Y\x8e\x86\x89,1\x91\xe5hY#\x19b\xe2\x18\xa2\xa2\x180\x91\xe5\xd2\xd8\x85\x84\xc8\x85,q\x0b\xf1Q\x0b\x98\xc8rI\xb4BL\xacB\xe6H\x05\x06\x8aS\xc8\x18\xa5\x00\x8dQ`q\x11\n\xb1\xf1 \x98\xc8rb\xd1\x11 \x98\xc8\x12\x14\x87\x90\x12\x85\x80\x89,]\x87\x05#\x0f\"\xe2\x0e i\x1acb\x0e0\x91%&\xb2\x84D\x16`\"KaKb 0\x91\xa5\xad\xa4`\xf4@j\xec\x80\xf3\xdd\x80\x89,\x0f\x0d\x13Y&\xc4\x08\x84#\x04b\xe3\x03\"\xa2\x03\xa2c\x03\xe2\"\x030\x91e\\,\x00&\xb2\x1c\xec\x18\xfc\x7f\x8e>\x17\xc1\xfe\xc3\xc9\xff?j\"\xcbi:3W\x9d\xa7GM\xea<\xca\x9dG\xaestF\xb7\xbb\xaagmW\x95E\xbd\xaa\x9a\xdb\xf6\xfc7\x89\xf8\xf9R\xb6\xfde8\xe5\xb2\xb9m\x87\x1cm\xbc\x9dci\xf3Dm\xb2X\xdd\xd2I:\xb6iy\xaft\xa3O4\x15\x1bo\xe2\xe1T~R\x15~\xc8\xe4\xf6\xcf\xdd\xa2\xf2\x18\xda<3\x9a\xb3n$(\xce\xdd\xd1b\xedb\xc5\xbd\xc5\x92`\xd1\xdc\xd4\x1a\xa9\x07\xcb\x91[B\xde\x14}U\x92\x9b\xba-\xefE\xbb\xdd\xc7\x87\xeaD@\xf5\xe2&\xae\x96\x89\xa1\x02l~)\xad\xd8\xed^\xf6\x92\x90\x857i\x17:\xed\x1d)\x8b\x1d\xdbw\x03\x13\xaa\xff\xdc\xedk*\xc3\x1bv]\xcb\x9f\x1f\x7f\x15\x8b\xe1~JE\x8c\xffGyWT\xcd\x99\xe7\xabR\xe5\xe4\x14\x88%\x7f\x7f\x0f'\x91u\xc1\n\xee\x97})\xeb\xa6>Ud\xad<\x05\xea\x05\xccQ\xe2x\xed\xd8,WZ\xcf\x04\xab\xd3\x15M/\xdf\xe7\xdb\xa2\xbc\xab\x1aG\x96\x15\x01dU\xcd\xaar\xc4\xab\x11\xd8-\xf5\xe1\xdd\x04V\x04\x04\xf3&\xe4\x05!91c\x167\xd0\xef\x1d9\x02\xec:\xfa\xf0\xc2\x03\xc0]\xd1\xdfe~\x18\xbd\x19\x83\xc4l\x87\xadz\xcaV\xbeaW\x1b\xa8\xa5\x04\xdcZn\x9e\xfd}'\x87yQ\x95\xb9A\xba\x9d\xb6\xb0\xcbI\x8c\xdb \xdc\xf5CG\xbb*:\xd6S\xf6\x17q\x07|]Wp\x99l\xe5\xaf2\xa8\xaa\xa0*\xaa\xea\xf1\xcbQ\xb1F/\x1f\x06>\xec9\xce\xe1?\xbdP\xf5\xc6\x8c\xbd/t\xc1\xb9?n\xbbv\xab\xc7q\xd2\xee\xd9n\xcf\xc6\xbf\x8dc\x87\xa34\x91\x01\xfe\xc5\xdb0\xe6\x91}\x99\xeb\x15\xbb\xdd\x0b]I<\x1f\x8a\x05x\xa1K\xd2\x87jM\x9b\x92\xbe\xd0\xe5\x86\xfe7N\x7f<\xaf%>\x02\xb7=\x0d\xa4G&\xd9\xea7\x99\xd4\xc9\x91l\xf2\x151L\x93\xc4\xa2\"\xf9B\x9b5\xed\xb6U\xc3\xd4\xa0\"_?\xb6\x19\xcdCQ\xf7\xd4\x1bgfG\x07\x89\x0f\x1f$\xb0\xb7\x19\xe4=\x06KD-\x0d\xe4\xeb\x98\x19rTjjo9&\x1f\x1f\x9f\xa0Z\x1a,M\xb54\x80\xf7 \xf0\x0e\x10U\x9c?q\xf5x\x1c\xe0\x0e\x90\xc8\xbb@\x12@\xcf`\x81\xcc\xaa\xf8\xfb\xbe\x14\xa4\x81\xc1\xcf`I#\x18\x1a\x02@\xb5\xc5\x82\xa0\xc1\x02w\x05\xbb\x03\x03\xa1\xdalZO4\x18\xaa\x0d\x0e\x88\x06\x8b2\x01\xd2\x08PT\xdbB`T[\x1c8\x1a,NAmQ\x00\xa9\xb6X\x904X\xe0m\xdbE\x01\xa5\xda\xa2\xc0\xd2`i)I\xb2\xa5\x81@\xd3`)S\x10\x15\x02\x9cj\xcb\x06\x9e\x8e\x05.\x01P\xb5%\x80\xa8\xda\xb2\x00\xa9\xda\xe0`j\xb0\xa8 \xb8\x1a\x06T\xb5\x1d\x01T\xd5v,`U\xdb\x11\xc0Um1\x00\xab60\xc8\x1a,\xc9\x04]E\xff\x0e\x03\xad\xda\xa2\xc0\xd6`ib\x9c\x80\x02\xae\xdaX\x1c\xe8\xaa-\x16x\x0d\x16\x18\x93\x96[\xdab\x00V[ E\xb7\xb4\x88\xa9c\xf0si\xb4\xd8Yf\x14(\x1b,\x8di\x90\x16\x00\xccj\x8b\xa9q$@\xeb-k:\x9b\x05\x80\xb4\xda\xa2\x80ZoI\xc1\xa4\xdf\xd2R\xa0\xdbp\xff\x04%\x00\x97\x96\x02\xe1\x86\nd\xa0d\xe0\xd2\xf2@\xb9\xda\x80|\xa9\xb6 \xa4\xab-\x02\xd6\xd5\x16\xc8\xd2+,\x05\xde\xd5\x06)\xdf\x9b\xe83\x1b\xd4\xab-\xcd\xf9p\xc8W\x1b\xa4\xe5 \xd0\xaf\xb6$\xf8W[\xc0\xe3\xf9``m@(X\x1b\x04\x0e6\x8e\x05@\xc2\xda\x80w%\x1e\x1a\xd6\x06\x87\x87\xb5\xf9\xd2\x92K\xcb\x02\x13k\x8b\x82\x8a\xb5-\x81\x8b\xb5A\\\x1f\x01\x1bk\xcb\x0e\x1dk\x03\xd57\xf0$\xc5\xc3\xc8\xde\xe2n\x9e\xc3P\xb2\xb6\x148\xd9[\xa0\xa6\x01\xfc\xe9\xcd\xa5\xa5\xc0\xca\xde\x02\x99^s\xf3\xa4:\x97\x16\x0b/{\x0b\x1b\xc1f\xc0r\x07\x00f\xd6\xe6\xcb\xc0,\xcd\x97\x08]Z<\xe4\xec-.\x90*]\x1f\x04\x07\xa1\x03\x1d\xc4\x80\xa4=i\xd3\xa5\xc5\x82\xd1\xde\xc2\xbe~\xfe\xe5-\x00\x90\xd6\x16\x0bJk\x8b\x00\xa6\xb5E\x83\xd3\xb3\x13\x81\x00\xb5\xb6\xd0, \x98\xdaZ\x1a\x14r\x85\x82\xd5C\xb9\xb1\x80\xf5pb\x0ch\xad-\xe0\x8c\x14\xf0\xda[ \x15\xbb\xb4\x14\x10;\xf80\x85\xd3\xb2K\x8b\x07\xb3\x83\xa3x E\xbb4\x0f\xa8\xed=/\x15\xe2\xd6\x96\xb3\xbfG@\xddC\xd1`\xb8[\x9b{\x82\xe4K\xf1.M\xae\xff\xf8\x12\xbdK\x8bY\x1fII\xfa\xee\xef ]\xbb\x05\xa7~\x97\xe6K\x00/-\xa6EI\xc9\xe0\xa5E\xa7\x84\x97\x06\\\x97\xf3\xa5\x87\x97\x16\x9b$\xde~\x967U\xbc\xfb\x14w\xc2x\xdb9\xc1\x8b$$\x8f\x97\xe6K!\xaf\x8e\x80\xf9;\xa6\xd3,M*/\x0d\x92Z^\x1a,\xc1\xbc\xb4#47W\xcayi\xf0\xc4\xf3\xd2\xcc\x9afk\xd0p\xec\xa2T\xf4\xd2\x00yl\xb3\xf3#\xc1\x14\xf5\xd2\x80\x9d\x81D\xfa\x8fdLZ/\x0d\xe4CH\x02{iGlwdJ\xfb`y?\xd0\xa7\xb7\xf0\xc4\xf6\xd2\x82\xe9\xed\xa5\xa5zai\xaa{i\xf0\x84\xf7\xd2Rk\x0b\xb8g\xd9R\xe0O\x8b\x0b%\xc2\x97\x16L\x87/-\xb5\xf9\xc9\xa9\xf1\xa5\xc1\x12\xe4K\x03V\x11\x8a\xb3\xc7\xdc\xc5\xf8\xc4\xf9\xde\xe2\n\xb6(}\xbe4H\x12}i\x91\x8e\x0b\xc5\x85\x90d\xe7A\x93\xeb{\x8bSczJ\x8a}i\xa1D\xfb\xd2&-\\\x9en_Z\xe6\xd70<\x01\xbf\xb4\x98\xbbF\xe2\x93\xf1\x07\xcb\x93\x85,J\xc9/\x0d\xe8G\x12\xe1K\x02J\xd2/\x0d\xf8@i\x8bu;\x01\xa7\xed\x07\x15e\xa4\xf6\x87\xe5c\x1f\x0d\x96\xc2_\xda\x0b8%&\xa9?\xa8@9\n\x07R\xfb\x83J\x8a\xf3)x\x13\x00i/\xe4Z\xd0\xb6\x00\xa0\xd2\xf4\xd6\x01\xe1\xcd\x01@\xc5\xc1\x9c\x0b\xdaF@Z\x84Cc\xde\x8a$\xc1\xf9\xb1\xdb\x0b\x04\x0b|,z\xdf&\x03\xd2\xc0[\x0dH\x03\xfa+\xa6\xed\x197\x1f\x18\n\x84mA \x0dZ\xd7\xb4\xed\x08\x9c\xc5\x8dI\xe9\xbd\xa0u\xfc\xd6\x04\xce\xa2\xe4\x96\x05\xd0\x0d\n\xa4EoS\xe0\xbe\xfa\xb8}\x81\x7f\xb3\x02iI[\x16\xf8\x9b\x0e\xda\xb8@Z\xec\xf6\x05\xce\x82\x8c>\x0d\xd8\xc4@Z\xd2V\x06\xee\x1aT\x03 \xc0\xfc\x1b\x1aHK\xdb\xd6\xc0\xdb\x18\xba\xf6ln -m\x8b\x83\x83\xa7U\xa4>\x99\xe6\x16\x19\xb67\xa8\xfa\x88\x1d\x0ef\xf9N>_]\xcc\xeb\x8e\x9b\x1dL?\xb1q\xb3\x03\x8bA\xdf-\xb11p\xb2\x03\xe3f\x07\x80\xd86\x1b\x12\x14\x1d\xd3\x06\x8fe\xc3\xcd\x0e\xb4\xc5\xc6\xa8y\x97@r\x8bn$,\xbc\x91\x04\xf1\xcd\xdf\x80\x82\xdd\x81\x058\x92K\x84#\x89B\x9c\xb7@\xee\\\xb0\x18G\x96\x0br$Z\x94\xf3\x16\xa5\xc4\x82(a\x8e\xe4\x16\xe7H\xa4@GbE:\x7f\xcf\x1e\x04<\xa8PGr\x8bu\x04&\xd8\x91\x9c\xa2\x1dY,\xdc\x914\xf1\x8e\xe4\x12\xf0H\x92\x88\xe7\x7f\x1c\x8cM*\x02M8\x82\x98G\x8e(\xe8\x91\xe3\x88z$R\xd8#i\xe2^h\x08\x86 |$\xaf\xc8G\"\x84>\x12/\xf6\x91\x04\xc1\x0f0d\xfe \xfa\x91\x1c\xc2\x1f \x89\x7f\x04>=\x03\x88\x80$r\x16\x17-\x06zK\x13B!@\x10$\x11\xb5\xcc(\x0c\x92(q\x90\xe4\x16\x08I\xa2H\xe8\xefW}X($\xe9b\xa1\xb3<~\xc5\x90`H\xb2\x89\x86\x04\xae}\x11\x88xH\xe2\x04D\x12Z\xf1O\x14\x12 \xa0\\\xcf\xa2b&Q\x91$9\x17..\x12@+\x13DF\x92*4\x12\xbfW\xf3 \x8e\x04.:\x12\xa0\xf0H\xc0\xe2#\x81y=^\x84$QB$\xf1\x8a\x91$\x97 IbEI\xb2P\x98$\x00\xf7F\x08\x94\xe4\x18\"%\x81\xd4\xd1\xf3$\xe4\x13, D\xb4$\x0b\x84Kg\x81\xfc@\x9fxIr\x0b\x98$(b\x92T!\xd3Y\x9a\xfcF\xf5\x7f\xae\x03\x04M\xe2\xd5]\x88W\xd8$I\xe2\xa6\xb3(\xaf\xe8IR\x85Ogir\x1e\xe8\xdb:3\x9b\x00J@\"(I\x10BI\x9c\x18JR\x04Q\x12-\x8a\x92\xc0\xdb6 T\x91\x08\xb1\n*\x90\x92\x14\x91\x94\xc4\n\xa5\xc4\xdf\xf0\x14\xc1\xd4Y\x98!GB\x1f\x19\x98p\xea} \xc4\xee\xee\x1e\xf1\x94\xe4\x15PIHD%~!\xd5yN\xaa\xc0J2\xf6\xdd\x08\xa1\x95D\x89\xad\xc4\x10\\\xa7\xf6\x8f\xa2\xaa\xe9\xda\xafN\xdd\xb4mM\x9dK\xc7\xd0oxy%\xa5\xc5\xad\xc9\xe3\x1dU+9\xe6F\xbc\xbc\x87\xdfP\xda\xa8\xa3\xddw\xb8k\xb7\xc3N\xb4B\xb6\x95\xcb\xdd\xd6<\xaeD\x1d\xe2j%\xb4\x05\xeaB\xf3\xad\xac\xd5\xdf\x9d\xa7\xfd \xeby>d\xeaU\xff\x12\xf2\x86\xfd\x14\xc0Z\x10m\xf6\x8e\xb4\xb4D\xe8\xe8?}\xfa\xf8~u\xfd\xe5\xdd\x97\xaf\xd7\xab\xaf\x1f\xaf\xaf>\\\\\xfe|\xf9\xe1=\xf8\x0c\xfe_\x91\x87_~\xfc3\xf0xo\xe1:\xfc3\xaa \xbe\xf8U\x90?\xa1\x9d@^Huc5\xdf\x187\xa0\x16\xbf\xfdP5e\xed~\xf1\xf7\xb4\xbe}3\xa6avt\x82a'\xec\x95\xdci\xf9\x05\x9a6\xbf\xe4\xa8\x9b\xb7\xac\xa8\xc7\x0d\xac\xfb\xbd\xd4\x14\xdc\xaf\"s\x9bwcKoGC\xc7\xda-n\xc0p\xdcD\xf37\xff\xceh\xb7\xed\x89}\xa7\xe8\xd1\x86\x06\xf8\x9f\xd0\xc5\xba\xfd\xb6m\xaa{j\x89.\x1e\x0dp\x83I\x84\x8f\xc8xUc\xdb\xfb\xbb\xfd\xb6h\xdet\xb4\x90\xb9\xa8\xc5\x8c.\xe4#\x02\xf1\x13Q\x04\x00s\x12\x10\xe48m\xd4\x97\x1d\x1b9\x06(\x8e?\xf6\xd5\xa6)\xd8\xbe\xa3\xe4\x07\xfa\xe4\xffH\xfez\xd5v\x8c\xbfe\xfe\x83>\xdf\x14=u\x0e\xde\x84<\xd2\x9b\xbeb9V\xfb'-V\xc5Z[\xa4\x7f\xab\xab\xe6\xde7\xf4\x94\xfb\xaeb\xcf+\xf1\xadR\xb2\xdc5\x0c\xdc\x93\xf9\xe5\xad-\xa1\xdb\xa2\xaa\x83\"\xb9.\x8a\xa8\xa2\xdcmv\x06\xc2\x8f\x96\xd2TU\xac~\x11HYjh\x84\xfa\xd5^\xabq\x9b\x05\xb9G\xc8\x82\xa1=\x9cU\x1f~\x87\xe6\xd5\xd2w\xe7\x8cT\xc6\x9e\x0fgbDUGx`\x1a9\xd7\x17\xd2\xe6|z\xb7\xd97\xfe=$`{[D9h]0\xfa\x86\x97\x95\xcdIr[\x0c\xb7\x8b\xb6U#\xb7\xce\xf0u\xe5\xe9D\x92\xb5B\xda\xae)\xa3!\x07\x95\xedv[\xf5=\xf4\xa59\x1e>y1\x1a\x7f>\xdc\xb9en\x99^y\xe35W]\xc1|G\xc2\xef\n\xb1\x94;i\xa8@O\x8a\xda8\xc8[\x96,@\"\x05\x83\x0c^v\xb4`\xf2{\x17\xf0\xda\x03\xf9\x8b\x00}FT\x9dBK\xf2\x80\x07B[\x8ck\x89\xba\xbc\xfe\xf41\xba\x8d\xf8syWt\x1b1'\x0c\x163\xce\x06\xcf\x88\xc0\xbfo\x05\xbe5\xdf\xedbn\xdb\xe2i\xf5\x8d\x1d\xa0\xab0\xe9Wz\x8b\x99\x99G\x82\x85\xc9\xd1q|\xf2\xcb\xa2!\xf4\x81v\xca\x95\xd1\xbe\x91\xbc\xc9)\xb8\xc8\xa8\x89\xd5S\xeb\xa2\xf2\xe4\x87\xd0V5\xfci\xeb\xe9\x01\xa6kxZ:)XT\xd8\x89\xfb\x1d\x7f;x\xdf4\x04\xee8\xe8\x1b\x87D:\xd8\xa8\xa5~\x0e\x85\xc4 \xfe`{*\x1f\x03\x98\x9d\xbcSk\xbb_\xb6U\xb3\xe2\x1f\xaa\xab\xf1Cu\xc1[\x18\xdaN\xcbU\x0f\x96[^\xf7\xe2\x0b\x9a\xaciY\x17\x9dg\x8dh[5\xa2\xc7\xa9\xa3u\x81\xb6\xf6B\xea7\x84\x00\x18\x9fMC\xa5\xce\x08k7rAK\xc8\x08B\x02\xe0_\xcd\xd6\xa2\x8am\xbb\x1f a\xfb\xd2\xe2\xafFs\xf9D@\x7f}\xab\xf8\xbc\xaa#\xf4I\xde@y\xb3\xc5\xd4\xa1j\x1c/\xef\xeb\xba\xe8\xef\xf8\xabK\xa7\xefp\xc1\xc1\x05w\xab|\xf2\x94:5\xb9\xcc\x99D\n\x05\xe1\xd6v\x9d\xeb\xc5V\x16u\xb9\xaf\x07Q\xe6v\xcf\xbf\xb0\xec\x17\xdc7\xe3\x9d\xe9\x85\xef\xda=#\x15\x13\xb1\x17\xcd\x86\xb4\x0f\xe2;uXB \x7f\xbb\xa3\x8dl\xaa\xbd\x01\xddtA\xc6~\xd5\xe9\xb4\xf4l6\xc4T=\x7f\xd7\xaf+\xa6\xb1\xaf\xc2\xe8>\xd6\xf2\x1e\xef\xda\xde\xd8\x80\xca~Q\xf36V\xfd\x04\xb04z\x84h\xda\xd8\x04kI\xebjP`\xe52\xba\xa0\x04\xedW\x9d\xdc\xbf\xb7\xe4\xd7V\xb8u\xd7>R\xf9\xd6\xb9\xa1\xc3\xed\xa2k\xa1\xaa:\xbb\xad^o\x15M\xb0_m\xbb\xafY\xb5\xab+Y\xb9\xe9\xb5\x0fN\x98\xfa\xc4V\xceh\x90\xe0@\x1ad\xffX\xc5j\xfa#\xf9/\xd7\x08\xab\xaf\xaf\x07U\xfeO\x05\xce\x16}/W\xf5\xae\x8a\x0d\xfdL\xff\xb9\xa7={+\x7fw\x146nk\xc9\x8b\xe5.\xa4d\xdb\xf6\x8cP\x81\x9f\nn\xd5r\xaa\xe8_\x0b\x1d\xb0w\x7f\xef*\x178_2r-\xb3\xd2\x8b\x9a\xe3\xa6qzh4\xd2\xe8\xb8\xc87\xd3E%\x7fpW\xf2\xa1q\x1c\xfeX\xf0W\x16;#\x15\xeb5\xef\xdd\x8b\x91OJ!b\xed\xe0\xb1\xea\xa7\xf7\xd4\xd5\x10\x11 7\xc6\xa3A\xb3-\x1eD\xb0i\x1b30\x0e?`\x02\xc6\xd9\xaf\x98\x80\x116G\" 1a\xb2\xb3b\x02F@\xfc\x17\xcb\x11\xfb\x95\x12\xf7\x85 \x183\xc6x\xc5\xc4wE\xc5va\x02\xc6\xa5q\\ 1\\Y\xe2\xb7\xe2c\xb70\x01\xe3\x92X\xad\x988\xad\x84\x18-L\xc0\x88 \x181\x01#4\xc6*k|UJl\x15&`t\x1d\x16\x8c\xa1\x8a\x88\x9f\x82\xa4\x17\x8c\x89\x9b\xc2\x04\x8c\x98\x80\x11\x12\x03\x85 \x18\x85-\x89s\xc2\x04\x8c\xb6\x92\x82\xb1L\xa9qL\xcew\x03&`<4L\xc0\x98\x10\x7f\x14\x8e=\x8a\x8d;\x8a\x889\x8a\x8e7\x8a\x8b5\xc2\x04\x8cq\xf1D\x98\x80q\xb0\xef2\x01\xe3\x08\xfe\x8d\x93\x9e7b\xe4\xfd\xf10\xb2e\xf2\x11\xa9\xe2ahS\xdc\xd4r\xe1EJ\x82\xdcm\x86\x9c+\xd2,Jn\xce\x96g\x91\x887\xca\x8f\xf2\\\xe3o\x1d\xfd\xe7\xbe\xea\xe8\xfaGr[\xd4\x13m\xcc\xfa\xa5\xae\xab<*\xb9o\xef\xe9\xb3\xab\xea3\x85TI\xa2\x85\x1a\xf5;\xca\xf6]#S\xfcI\xadOi[\x83~*V\xaf6\xb3e\x1e\xd1\x02\xdeP\xbf&\xfa\x96|\xe2\xef\xe8\xb6\x11\x9f\xb7\xed\xedmO\x05W>\xad.1V\xdf{\xca2{\xcb\xb1\x96aq\xa2\xac\x9f\xcb\x8f\xb3u\x04\xd5\x18\xe1\xcaf\xbf\xa5]U\xea\xbf\x89\x01B\x01\x07r!\xe7\x8e6\xda\xf1\xfbfX;\x9b\xcd\x98/Ei5\xed\xfb\xd1\x85r\xb5i\xdfsW\xdf\xd3H\x7fN\x8b?\xb2sg:\xb5\xc5\xbdu\xb5\xad\xa0\xde\x15\xc7j\xe9\xde%_\xcbuU\xb3\x07+\x9aa_\xcf\xf4V\xb9\x8ab\xfe\xe9\xf2\x96\xd4\xf4\x96\xa9\x05\xbb\x8a\xc9\x11\\\xcfs\xc5\x92\xb0|@\xe4E\xb8\x9fo\x9e -\xca;R\xecv\xdf\xd0\x8b\xa6\x08?\x9e\xef\xf3\xa5q\x06\xf7\xa8\xe8\xa1-a\xdd\x9e\x12\xfe\x8f\xaaYW\xa5\xe0\xaa\x948\xa4<(\x0eT\x1d\xc9,\xaej\xcaz\xbf\x9e\xcdb\x0by\x95A\x9d\x9b\xdd1\xa1\xf5\x1a\x8b\xc6|\xd8\x9cp(\x93\xc2\xbe^\xf6\xb3\xbb5k\x82\x98\xf8w\xb4W\xaa\xbcx\xbc\xc6\xe7\x91?ro\xd5\xd3Tm\x9av\x0e\xce\xe9\xa7qz \xe9\x99\xa57v\x1a?\xeaJ\xf8\xfb:\x9c\xf1\xf7\xfc\xb7\xe1\xdf\"\xb7\xeb\xbfT\xba]o\x0e\xe0!\x05\xb0\x01x5\xb7\xadp\xb7|\x1f\x8d?\xa8\xe4\xb0\xba\xc1\xf6\x14\xc0\xaft\xabO=\x03\xb0\x0b=HB\x97`y|\x83\x8b\xe8\x90U\xe8\xdc\x19|\xe3\xf3\xf7\xc2\xb2\xf7z\xbdI\x82\x1e%\x00.\x03\xe0Q\x02\xf6*I\xa53<\xe5E\xe5\xeb\xcdJh\x04\x19\x8d\xdc\x94\x06\x9c\xd3\xc8Dj\xa4\xb1\x1a\x9e\xe2\"3\xf4.\xe45r\x13\x1b\x91\xccFfj#\x8e\xdb\x88$7|}x`:\xa0\xecFfz\x03\xc4od$8\x962\x1cI\x14G&\x8e#\x85\xe4\xf0\x14\x06\xce\xc1{\x04\x9a\xe3x<\xc7Q\x88\x8e8\xa6#;\xd5\x01\xe5:\xb2\x92\x1dp\xb6#\x9a\xee\x88\xe7;\x82C!,\xdb\xeeb\xc6#\x98i\x174\xa1\x02\x90\x1e1\xb3\xaeh\xda\xc3\xf7\x12\x04\xe7\xd7\x85\xd5/#\xf3\x11C}d\xe6>\xd2\xc8\x0f_\x0f\x02\xe5\xd4M\xa4?\x1c\xa51P>\xdd<\x04\x08\x18c\x00P Q\x1cH(\x1de\n\x0b\x12*\xd3\xa9 e\"B\xe2\x9d \xa7BBmK C\x12\xd9\x10\x9f\xb6\x96\x8d\x0f\x01\x13\"0F\x04J\x89\x00\xbc\x1cO\x8a\xc4\xb0\"\xfe\x0c\xb9Yx\x91Hbd\x193\x12rh\x047r\x04r$X;gO\xcf\xc7\x8f\x00\x08\x92t\x86\xc4Q\x1c\x0bf\xc2\xcd\xca\x91\x84H\x92D\x96\xc4QV8\x03.\x80'\xf1g\xbf\xf5\xe5\xbe\xcdM\x95d\xe7J\xdcdIN\xb6\x04B\x97\xc4\xf3%Q\x84I\x02c\x12K\x99\x04\xf2\xd9\xfak\x07\xd5\xfd\xa1\xacI\x02m\x12\xc9\x9bx\x9a\x9b\xc2\x9c8\x8a\x02d\xb0M\xe1N<]>\x9c\xbd6#{\x12\xcc\\{\x0c\xfe$W_\x8c`Pb(\x14{^Z_VZf\xd1\x14\xa7\x06\xfb\xeeM\xc9G+\xf2\xce:\xca\x83f\xa3\xf5\xe5\xa2\x85\xd5<)\x0fmt\x16\xda\xe0:\x89/\x03ml\xfe\xd9\xa8\xec\xb3q\xb9g\xc1\x99g\x13\xf2\xce\xfa\xb2\xce\x06\xfd\x07\xbb\xd9K\xf3\xcdB\xb2\xcd\xc2r\xcdfjP\xae,\xb3\xf0\x1c\xb3f\xbd\x16U|8jQv\xd9@\xf28\xb6\\U\x0ef\x95\x0d\xdeJ\x02\xf6\n\xc9\x98O6\x98V/\x9cK6s\xcb2g\x91\x05\xe7\x90\x0df\x90\x8do\xe7\xd2\xec\xb1\xf0\xdc\xb1\xf1u\xf3\xde\x83lYc\xa19c\x83\x19c\xe3\x1b\x98\x9c-\x16\x96+6X\xa1p\x9eX\xd8\xfd\xc8\x99#vI\x86XH~X\xb0S\xfc\x99\xfab\x1d\x13\x93\x17\x16\xf2\x96\x80g\x85\x0d\xe5\x84\x9d\xb4dyF\xd8\x0c/*x.X\xd8] \xf1y`e\xaeWOy\x8b\xb2\xc0\x06}D@~\"\xa0\xfc\xaf\xc1\x0e\xaf\x0d\xeeL\x02\xce\xfcjfv\x0d\x14\x08\xcem\n\xcb\xfaz\xa4f\xc7\xe4{\x95cY\xa0\xc0\x1c\xd9^\xa3r\xbd\x1e\xd11\xa0,\xafC\x16\xd7@\x81\xc1\x1c\xafA\xd7\x802\xb8\x82\xdc\x01{'\x90(\xa7e\xce\xdc\xea\xc9\xdb\n\xce\xda\x1a\xf4\x05\xacu\x19\xf3\xb5\x82\xb3\xb5\x86k\x96\x96\xa9U\xe5\xe0\xb4\x94\xe7\xce\xd3\x9a3K+0Gkt\x86V3\x1b\xab\xbdq\xee\xfc\xacy\xb3\xb3Br\xb3\xe6\xcd\xcc\n\xc8\xcb\x9a\x94\x95Ug`\xb5\x95\x17\xcc\xc9\x9a\x96\x91U\xad/Z\xcas\xe7c\x05gc\x85\xe5\x9a\x8cN59+\x0d3MJ\xc3L\x93\x98ir4\xcc4\x89\x99&G\xcb\x1a\xb3\x10\x13\xb1\x10\x15\xaf\x80\x99&\x97F)$\xc4(d\x89P\x88\x8fO\xc0L\x93K\xe2\x12b\xa2\x122\xc7$0PDB\xc6x\x04h4\x02\x8b\x8bE\x88\x8dD\xc0L\x93\x13\x8b\x8e=\xc0L\x93\xa0\x88\x83\x94x\x03\xcc4\xe9:,\x18c\x10\x11a\x00\xc9\xa3\x18\x13]\x80\x99&1\xd3$$\x86\x003M\n[\x125\x80\x99&m%\x05\xe3\x04R\xa3\x04\x9c\xef\x06\xcc4yh\x98i2!\x1a \x1c\x0b\x10\x1b \x10\x11\x07\x10\x1d\x05\x10\x17\x03\x80\x99&\xe3\xa8\x7f\xcc49\xd81H\xff\x1c}.\x82\xf2\x873\xfe\x90L\x93\xd3\xc4^FQ\x93\x8f\xc9\xe9Q\x13\xf2\xe0 \x89\xd7$\x1f\xa598Ub\x1b\xc0\xc9\x888f0c\xdd>\x90\x99.g\xfe\xb2sC^\x85\xe42{o\xa8\xb1:\xad\x99\x16%\x9dY\xcdt\xdb\xed\xd9\xcc\x8c\"_ig\x9chb\xb3\xd1Y+K\x1d\xb5\xb1o z\x85p\x8b\xe0\x05\x08\xe0\"d\x02\xcf{\xd3\xb0I\x03\xac3\x11\xe0r\xcdx\xec\xec\xfa\x1a\xf7\xb8\xa1\xe5\xdd\x7f\xffootn\xb51G\x9b\xb786\x863\xf8\x16\xad\xa7O\xcd\xcb\xb7\xfa\xe0\xfa\xcb[\x0d`\x07}\xb1\x18\xd2R\x9a: \xba0o\x80X\xde\x94?v\xb4\xa4\xd5\x83kkh\xb8\xef\xc6\xb1e|a+\xc7\xb5\x8dZ`U1,w|\x96y\xf3L<\xb9\xb0\x8aRd\xbcTY,\xdd\xef\xc1\xf6\xb1\x91\xdfXmc\xf4.\xb5\xae-\x94\x9d\xb6\xac\x8a\x01!\xf1\xa9\x17\x0f&\x9b\xd1\xde\xf2\x12\xdd\xd7\x0d\xdc\xd2\x9b\xa2.\x9a2\xb0(\x9ca\x80hZgT\x16\x81\xf6\x19 \xbe,,\x06\xdaK.\xda\xaa1H-\xd1!F\xba\xa7i\xb7:#*\xbf\x81E\xa3*\xe7S\x0c>~\xfa\xf2\xe1G\xf1\xed\xa5\x08\x1e\xf9\x11S\x89u\xe6\xcb\x86\xa9\xe9\xdd\xb0\xb6\xdf{;\x81\x9a\xfb)r\xc5\xfd\xb8\xea \x90~\x98N\xf0N\xb8i7\xad\x98X\xa5\xae\x94\x8f\x0f\x91\xc9\xdf\xf0+<\x14\xb5\xc8\x86\xdc\x9a\x0f\x1a}*\xe9N\xa6[\xb6\x16W1c\xd5\xdd\xde\x1a\xd5S\xe7\x13]58(\xdf\xf5d\xdbv\x94\xf4\xfb\x8a\xe9\xec\xb5\xd6\xc2\xcaZ\xa4l\x1e^\xd8s7\xe0\xce\xcd\xc2p\xe7\xe6?\xdc\xce\xcd\x07\xf7rJ\xd3\x19\x13\xef Xg+\xe8\xdc\xfaU\x80\x8c\x9d4d\xec\xf2\xbc\x9c\x91\xb1C\xc6\xcen\xc8\xd8 C\xc6\xee\xd0\x90\xb1C\xc6\xcee\xc8\xd8!c'\x0c\x19;d\xec\x90\xb1C\xc6N\x1a2v\xc8\xd8!c\x87\x8c\x9d\xcb\x90\xb1C\xc6\x0e\x19;d\xec\x0c\xcb\xc1;!c'\x0c\x19;d\xecN\x89\xb1\xc3\xed\x9cS\xf7\xca\xc5\xed\x9c\x8f\xe8\xdc\xf0F\xc4\xb8\x9ds\x0e/\xe2v\xce\xdf\xe7v\xce&\x0e}\xfe\xdb\x945\xf5\xed\xf5l\xe0O`*z$\x03\xc9\xae\xa8\xec\x90\xf4\xfbyn\xa9\xdf\x13\x1a\xedB\x15\x92\xf0\xa7\x10\xe0\xec-\x9a\x04\x8b'qh3`q\x1f\xb6B\xae\x8f\x8c\x85\x9a\x03r\\\x10i\x8e\x00\x9a3\xb75\x1ee\x0e\xb45\x082\x870\xe6\xf8\x06.G\x98a\xfe\xca\x89/\xc3\xe0\xe5xtY!\xca\x8e\xf2 \xe0\xb2\xf7\x06z\xa1\xe5,\x0f\xbd\x17W\x06\xf4\x8d\x10\xaa\x1c,\x02\xd6\x17rC\xca9\x11e\x10\xa0\x1c\x8f'\x87\x1d\x93\x8e&\x93\xca\xd6c\xfc`rF,\xd9\x0f%\xfb\x1b.&8\xf6\x96\xfb\x92\"\x1e\xcc%\xb4\x8d\xc4\xe6X\x0bD6g\xbf\"\xb2\x19\xea\x96\xa3!\xb2\x89\xc8\xa6\xdd\x10\xd9\x14\x86\xc8\xe6\xa1!\xb2\x89\xc8\xa6\xcb\x10\xd9DdS\x18\"\x9b\x88l\"\xb2\x89\xc8\xa64D6\x11\xd9Dd\x13\x91M\x97!\xb2\x89\xc8&\"\x9b\x88l\x1a\x96\x03\x9fCdS\x18\"\x9b\x88l\x9e&\xb29\xc5)\\u\x9e\x1e5\xdbP]\x939G\xae\xf3\x8b\xb1K\xe7\xe3\xf6\xc0\xe3a\x1e\xa0\xc9\xe0Y\xbf\xea3-\x90\xd3P*\x80r\x1a\nt\xd2N\x96+\xa9\xc3N\x16{\x92\x0e8\x06\xe9\x14Bs\x82\x8bU\x90\xd5\x9e\xcc\xe8\x91\x17;\x02\"G\x99\xda\x95\x153\xf2\x12*\xb4a\x9dWuu)\xbd\xc4\xa7\xf6\x92P'\x92\x16R}\xb9\xc9\x0d\xa3\xdb\xc6\xbb\x81\xbb\xb4\xa0\xf3\xa5\x857s\x97\x06\xbbU\xd2f\xb5\xd4\xb7K\xfd\x97\xde\xaa\xdd\xd8\x80\xdc[\x1ak\xdb{\xb2\xab\x8b\xd2\xba\x10*M\xedi\xce\xaf\xe9\xdf\xb77\xda/\xe1\xbd{#}3\xad\xa9\xf6\xcd\xbe\xa9\x9e\xc6\x9d\xdca\x8e\x19\x8b\xf2\xac\x89\xc8=\xcaW\x81\x84\x91\x04\xee\x98\x98\xc6\xce\xae>y1+\xd8M\x1d\xe2\x119\x89\x1a\xe2\xd7\xfbZ*h\n\xc7#\x05\x03\xb9\xe0HM\xf7\xb4)\xb6\x8eP\x97Z^\xaa\x1f\x1a\xd6=\x8f,Yc\xbc\xc6\x03\x1b\xc5\x8bE\xfc\x8e\xd6\xf4\xa1h\x18\xd9RV\xac\x0bV\x00\x10G5H\n]s\xf2\x14\x9b\xe4\xa4:(\x05\x04\xb3MRz\xd6\x8a\xad\x90\xebZ|\xd6\x93\xbej6\xb51\xb9{m[\xef\x1f+\xc6\xff\xdf\xcaI\xf2\x87m(m\x9c\xe8\xf0\xcf\x8fF<\x8eo\xdanM;\xba&u\xd5\xb3c\x92]\xb6\xd3\xcfm\xb3\xa8\xd9\x81H|)C\xe2\x0b\x89\xaf\xd1\x90\xf8B\xe2k4$\xbe\x18\x12_vC\xe2K\x1b\x12_H|!\xf1\x05\x9c%!\xf15\x18\x12_\xa6!\xf1\x85\xc4\x97\xc5\x90\xf8\xb2\x1e\x83\xc4\x17\x12_\x0eC\xe2\x0b\x89/$\xbe\x90\xf82,\x07}\x83\xc4\x970$\xbe\x90\xf8B\xe2kY\x9d\xb3\x12_6\xa8\xcb\xb7\x8d\xaf\xb1\x020\xec\xdde\x91\x0b{\x0b\xdfe\\@\xbc2\x87\x82\x0e\xd8\x18\xfb.\xbf\xb6\xcb\xa8\x13N\x1c\xee\xe2\xee=\xcd\xdd~C(\x15h}\x0b\xb2DDr\x83b\x01T\x0c\x0c\x8bemaVd,\x98\x97\xca\x8b\x8d\x85\xc1\xb1\x00:\x16\xecb\xd2B\x1dMZ\x04@\x06\xba!\xd2\xa0\x10\x19\xfc\x06J\xcb\x0b\x92\xc1P\xb2(\x98,\xc1G\x10\xa0,\xdaO\xf9\xa02\x18V\x16\x05\x96E8)\xae\xd9\xd9\xf0\xb2e\x80\x19\x081;\x9a\x13\xa0\x1cZ\x86\xbb\x0e\xafXVR-\x8eU\xcbJ\xab\xc1\xda\x9c\x8dX\x031k\xcb\xa85\xdc$Y\x19n\x92\xfc\xc7\xd9$\x19\x80bz\xbf^\xbct\xe6\xac4\x0b\xef3\xdbB\xd9\xfa\x19\x86\x9c\xa62\xe44\xf3|\xe2 \xa7\x89\x9c\xa6\xdd\x90\xd3\x14\x86\x9c\xe6\xa1!\xa7\x89\x9c\xa6\xcb\x90\xd3DNS\x18r\x9a\xc8i\"\xa7\x89\x9c\xa64\xe44\x91\xd3DN\x139M\x97!\xa7\x89\x9c&r\x9a\xc8i\x1a\x96\x83\x99CNS\x18r\x9a\xc8i\x9e&\xa7\x89\x9b)\xc7\xedT\x8b\x9b)\x1f\xd1\xb9\xe1m\x80q3\xe5\x1c^\xc4\xcd\x94\x7f\xff\x9b)k:\x9d=\x0d`z_m\xf7u\xc1\xd4\x9a\xed\xae\xed\x0fy\xf3ku\x08\xd1\xc7\xf6\x84>\xd1r\xcf\xf8\xe0P\x10\xd6\x15M_\x88e9\xf9\x99\xd2\xb3j[\x88\x1f7\x05\xf7\x8ax\x08d\x99\x13\xaa\\\x97\xfbJ7\xf1D\x01\xf2M\xd1\xaf\xaa\xe6\xb6\x0d0S\xfa0=z\xf0\x7f\xf3\x87K\xec\xe6y\xd3\xee\x99r\xc78b(\x7fZ\xc1;g=I\x90E\xe0\x15y,\x1aF-\x19M d\x19\x1e\xc0\x0fA\x96\xba \xf9s\xd1\xffMTD\xfbd[\xb9x\xab\xb9s_\xa8\xcd\x7f.\xfa\xaf\xfd\xd80\xb5\xfbj{+nrQ2\xa9\x9a\x97m\xa3\xe4\xd4iQr\xa4\x0bt(5\x1cV\xbd98\xea\xe5\xfa\xe3t\x9du\xc1\x8a\x85\x0et*7\xb0.\xf3\xbe`\x85\x98\xdc4\xcf\xa26\xe3k\xf6\xb6\x13\x9b\xd3\xcao\x05\xa1\xab6\xeb\xda!\x8d\x10=B\xb5\x8d\x18\x91\xff\xfa\xf5\xfa\x8bG\xf8\xaai\xb3awd\xd7\xd1\xdb\xeaI>\x9f\x02\xa3\xe4\xaf\xa9\x9e\xf2\xe9;\xa3\xb26\xb2\x12\xfb\x9aU\xbb\xda%\x15\xe9:\x0eU\xb0jeu\xbbI\xf44\xcc\x91\xbf\xb4\x9b\xe9zE\xddn&cR\xaa?-\x07\xd0\x07\xda\xb0\x13\xce\x9d+\x8aq\xfe\np9\xb7\x82\xb1\xae\xba\xd93\x7f\x94E\xa8\xb9\xd2\x02Q\x1f\x04\xd6ti\x10\x07Hs\"\xb5\xa6\x81|\xa1-\xf8\xd0\x8f\xe6U\x86G;\xd6\xe5\xabfM\x9f\xa0\x97\x9f\xce\xa6\xec\x06{\n\xb5}\xe0O\xc8;\xdd\x83\xe4\xd7\x9b\xa2\xb8\xef\xe9\xf3\x1b9\xe5\xdf\x15U\xe7[y\xe06\xdf\xbb\xbdh\xe4\xd3\x07\"\xe2=\xd5\x14\x15\x94\xaf\xe1\x9e\x7fihT\x86\xac\xe9\x03\xady\x0f\x13\xdf=\x05c\xe2SdX'u\x16h\x0e5\xcc\xa3\xb1\xe8\x0f\xff\x9f\xf8\xb7\xfeOu[\xde\x9f\x0d\x7f\xfb\xd0\xacg\x7f\xb9\xb8\xa3\xe5\xfd\x97'\xf7C\xda\xac\x87c\xdf\xd3\xbaz\xa0\xdd\x97'\x8fV\xf6K\xc1hwf\xcea{\xb2-\x9e\xf9\xa7\x97\x8c\x9e\\\xab\x8f`vG{\xaa\x06:\xbb\xafa\x9e\x16~\xee\x0d\x00\x80\xf4uU\x8a\xcfjy\x0b\xe4\x13\xaf\x98\xb9G\xdaQB\xb7\x15cN~g\xbd\x97\xd4\xa5\x1c\xc8]-\x1d\xc7w\xd7H\xee[\xbb!\xc3\\\xdd\xc4\xa5\x99\xc1\xff\xcb\xf5O{B\xdbk\xda=T%};\x94\x81<\xb44\xe4\xa1\x91\x87\x1e\x0dyh\xe4\xa1GC\x1e\x9a!\x0fm7\xe4\xa1\xb5!\x0f\x8d<4\xf2\xd0\xc0Y\x12\xf2\xd0\x83!\x0fm\x1a\xf2\xd0\xc8C[\x0cyh\xeb1\xc8C#\x0f\xed0\xe4\xa1\x91\x87F\x1e\x1ayh\xc3r\xb0\xa9\xc8C\x0bC\x1e\xfa{\xe0\xa1o\xda\xb5\xf9\xee\xab\x9a\x83?9\x99e\x9b\xf6\xf3\x7fv\xf4\xf6G\xf2\xfa\xff87\x16\x0e\x15\x05\xf7\x96=\xbdU\x14\xdc(M\xc9tE\xafU\x19s\x8eN)Yv\x92\x8e=\xa9cm9[\xffL\xd9\x97\xa7^*|\xb7\x94\x95w|\x90\x7f\xea\x05\xdbi\xca\xb7\x13@\xce8I\xfd\xfc2\x8c\x1c\xd0iF\xf5\xb4,\xf8\xfa\xd5X\x0b\x14\xf4&\x86\x82\x1elA\x88\xa0\xa0\x87\x82\x9e\xf3H\x14\xf4\x84\xa1\xa0wh(\xe8\xa1\xa0\xe72\x14\xf4P\xd0\x13\x86\x82\x1e\nz(\xe8\xa1\xa0'\x0d\x05=\x14\xf4P\xd0CA\xcfe(\xe8\xa1\xa0\x87\x82\x1e\nz\x86\xe5\x10WP\xd0\x13\x86\x82\xde\xf7 \xe8\xc9\x909\xa3\x88\xc9G\xa4\xfcUG\x93\xd5U/\xd7\xbc\x8d\x94\x12\xe2\x88\x83/\xd2\x94\x1c\x19s\xb9\xc4\"\x948>\xe0\xcb\xb6\xae\xa9\xa8\xce\xcf\xea\xf3]\x84\x80\x1f\xb4\x15\x13#\xc5e\x9d\xc1\xc4HGtn8\xa5\x0f&F\xca\xe1EL\x8c\xf4\xfbM\x8c4\x02\x1d\x8e\xdcG?um\xb1.\x8b\x9e}y\"7\xfa\xdf\xe6\xfb\xc9\nn\x18g\xbd\xd2\xd5| p\x83\xc5\x83\x11\xeci\xd8\x16\xd7\x85\x19$e\x92\xf1m2\x1a\\&\xbf\x0dn*\xaa\xf6/\xe3_a7u[\xde\xab\xebY\x8eeOwE\x7f\x97X\x91\xc9-\xe1\x173g&\xbc\\\xdb\xb7Q\xd9\xaei\xbf+\\\x9bB\x06/\xaa\xda\xc6\xe7\xf1\xa2\x18\x1dVO.\xda\xb5mFj'UH\x90V! OO\\0\x84\xff\xf3kZ\x15\x82\xf4\x04B\x93\x0b\xbd\xfe,\x87<>C\xe8\xcf\xf4\"\xdbk\xcb\x89]\xf1\xb8:v.\x1d~\xe7\xdb=\xdb\xed\x87\xf1\xd4\xc8\x90\xf1\xba'u\xbb\xd9\xd0\x8e\xfc\xd0\x15\x8f\xeab\x7fzK\xfe\xea\xcc\x00\xe3\x16\xa8\x9a\xb6y\xb3\xe6\x13\xe9m\xd5T=\xabJ\x9b\x8f\xebvs\xc2\xb9v\xb6\xfdf\x15L\xb6\x12\xee\x98\xd2\xc2\xdd\x93\xf8R)I\x0bv\x02\x12Ha$-\xe4\\i\xdf&\xb3\x8f(2p\x0c\xd0\x11\xd2`\xc9\x8e\xa4\xc1\x1c#\x0d\xe0\x1ei`'I\x83\xbbJ\x1a(\x15\x92\xb4\x08\xafI\x03f:\x92\x16Y:l\xbc\x9a\xda\x98v\xc8\xd8\x82w\xb8\xc1\xe4\xb1+v;\xda\xf1YX\x17\xca\xa2$\x8d\xa9=Q\x8bf\xad\xe6\xe4E\xe7\xd1\xdcM\x93\x0d\xedI\xd5\xf4\x8c\x16k\xf1\xf1P<\xcaa\xde\xb3\x10\x1f\xdd\xf2kq\x1d\xc9\xdb\xeaV\xd3f\x92b'\xaa\xe1\x02\xf5\xe2\xe3\xfe\xf0\\\x84\xda\xab\x01\xc1{\xfa|>\xa6wR\xa8X\xd1\xd1\xb9+\x02\xc5A\x1d\x15\xe3\xa6\xf8\\D\xde\xe2T\x9e\"\x9d\x91\xa8o\xb7\x81N\xe1\xcd)G\"\x1a\xf3\xee\xa7\x8b\xcb\xbf\xcaE\xb6_\xda\xcd\xd8\xcd\xb9\x8f\xf7%\xdbwT7R\xa4,md60\x0f1\xc4\x9eD\x99\xc3\xca]\xddn\xecu\x84\xd5\x10:\x7f\xe0\x83\xc1ZN\x1d\xf8$\xc1^\x18h\x8e`\xcfWJ \x03\xce\xf43d\xd4\x0b\x8c\x84^\xba\x86\xb0\xbad\xcbG\n\x9c\xa4\xbe\x9b\xe4\xe2\xec$\xd2\xafY\xa7\xc3/7\xd32%\x11M\xaa\xa8\xce\x15Jn\x9eC\xd5d\x8e\xc9U\xf0\xa5\x19~M\xb2\x00\xe5\x0d\xf0\x02\x01?\x17$\x95\xf5\xf6\x94w\x80\xfb\xf8\xc6\xa0\xac\xbcw\x90\xf8\xce\xcd|\xc3\xa9\xefL\xdcw\x1a\xf9\xed)\x8e;\x14\xcc~/\xa6\xbfs\xf3\xdf\x91\x04xf\x06<\x8e\x02\x8f\xe4\xc0}}x \xc4\xa1$xf\x16\x1cD\x83g\xe4\xc1\x97\x12\xe1ILx&*<\x85\x0b\xf7\x14&\x88\xf10\x19~\x146\xfcxt\xf8Q\xf8\xf08B<;#\x0e\xa5\xc4\xb3r\xe2pR\\N#\"X\xf1xZ<8\x14\xfe \xc0\x8bg \xc6\x83\x0b\x02\xa0 \x15\x80\x1b\x8f\x99uE\xb3\xe3\xbe\x97\xe0M\xfb@\x01\xf48\xb4~\x19 \xf2\x18\x86<3E\x9e\xc6\x91\xfbzP\x1f&\xc9\x93YrGi\xfcj!\x9a<\x17O\x0e\x86\xa2\x01Ly\x14U\x1e\x80@\x93\xc8\xf2P\x99N\xc2,\x13_\x1e\xefL8c\x1ej[\x02g\x9eH\x9a\xfbH\xbdl\xb49\x987\x87\x11\xe7P\xe6\x1c\xe0\xe5x\xee<\x86<\xf7\xb1\xe7\x99\xe8\xf3H\xfe|\x19\x81\x1erh\x04\x85~\x04\x0e=X;gO\xcfG\xa3\x03x\xf4t\"\xddQ\x1c?\xcc\xc7\xa4g\xa6\xd2C\\z\"\x99\xee(K~\x19\xfa>\x8e\x01t\xba\x0f\xa1\xf5\x11\xea\xf9\x19\xf5\xec\x94\xba\x9bS\xcfI\xaaCX\xf5xZ=\x8aWO \xd6c\x99u/\xb5\xeeg\x88\xe1\x141\x94\\O`\xd7#\xe9uOsS\x08vGQ\x06\x1d\x0e{$`\x14\xbb\xa7\xcb\x8b-\xf5<\x1c{V\x92=\xc0\xb2\x1f\x87f\xcf\xd5\x17#\x88\xf6\x18\xa6}\xa4\xdaMc\xd5\x96\xf6\xac\xd8\xee\x12\x95!\xd8\x97\xef\x97j\\\x90\xdfu\xf4\xa1j\xf7\xbd\xe4\xdb\xde\x92\x9f\xdbNAn=\xf9\x7f\xc8\xbf\x9f\x91\x8a\xbd\xee=w\xf6Q\x1c+\xba\xff\xba*\xf8X\xed\xba%b\x04\xd5\xed\xd3\x81\xc5j]\xe0\xa1e\xe3w\xa7\xac\xc9/E\xcf.\xda\xed\xb6r\xee94V\x95\xfc\xcf\xffI\xfe\xfd\xcc\xf9\xaa\xe5-\xe0_\xa3}\xd5\x8b\x1a\x1c\x16\x18\xf6\xdb\x97\xa7\x01J\x0b\xe8\xbe\x1d\xad\xe9C\xd10\xc2\x9e\xe4fn\xf6Y\xc9\x96\xb2\x82\xff,\xd6\x19mUg\xc5\xa67\x14|9\x01Q1wr\x97\xb5^>\x85kZ\xb6\xeb\xf9\xe6\x7f\xbeP\x00b\x92\xa3K\xb6\xda1\xb1U\xdcj\x073s\x05\x17\x18\xc3\xcf\x99\xb4$\xb5\x163sA4\xda,\nm\x8a>\x8b\x99\xb92\xaa\xb21\x9al\x94\"\x8b\x99\xb9\x96\xea\xb0 *l\x16\x0d6^\x81\xc5\xcc\\K\x94\xd7\x18\xdd5\xb3\xea\n\xd3\\3*\xaeP\xbd\xd5\xf2)\x85\x99\xb9\xa6\x06PX\xa1\xb3\xa4hu\x153s\x814\xd5\x14E\x153s\xb9\x0e\x0b\xaa\xa8\x11\x1a*$\xefT\x8c~\x8a\x99\xb903\x17D%\xc5\xcc\\\xc2\x96\xe8\xa2\x98\x99\xcbVRP M\xd5A\x9d\xef\x06\xcc\xccuh\x98\x99+A\xef\x0c\xab\x9d\xb1Zg\x84\xd2\x19\xads\xc6\xa9\x9c\x98\x99+N\xd7\xc4\xcc\\\x83\x1dC\xcb\xcc\xd1\xe7\"tL\xb8\x8a \xc9\xcc\x95y\xab\x1d\xa7\x88\xe1M>\"\x02Z\xa3\xa4\x97\xc0\x97\xfa\xe4KX_`\xd0\xd0\x8aG_l\xdd\xd6\xa3,9\xeaB\x9b\xfd\xd66\x9f|C~\xfa\xfc\xe9\xdd\xfb\x8bw\xd7_V\x7f\xfd\xf4\xfe\xc3\xea\xeb\xc7\xeb\xab\x0f\x17\x97?_~x\x0f9\xfc\xa7_>]\xfc\x07\xe4\xc0\xeb\xbf\x7f\xbc\x80\x1c\xf7\xcez\xa0\x16\x03cj\x1b^k\x18\xe4\xc7\xbf\xb6\xeb\x91\x0c\x97\xb7`\xcc\xa2\xc3\xbd\xed\xd01\x89\x10v\x0f\xd4L\xf2\xf9\xeab\xd03m}\xdf\xe7\xf5\x1f\xc9\xff\xa6]\xfbF\xbe\xfa\xc5\xc3\xcf\xaf\xdfvk\xeaZ\x14\xb2\xdf\x94\x03_\x89\xbf\x1a\xe233R\x05 U\x8a_G\x04\x99\xcbq\xad\x16y\xc4\x1e\x8b\x8a\xf5\x0e)A\xbc\xe3\x9f\xd4*j)\xb4v&\xf3i\x15J\x84\x07U\x97\xdf\xf1\x83\xda\xf2?f\xadlA.\xeehy\xff\xe5i\x8c\xe7\x1e\xb5j>a\x85U\xf6\x9d\xb5\xb6\xef\x92\xaa+3\x90\xd9\xd6|\xaa\xad\xc0!\x18\x9dW\xcb\xdf\xa9'\xb2\xbc\x88'\x1eUy\xf9\x9f,J\x94W\x85\xcc\xfb\xb0\xd9\xbd\xe5_\xdc \xab^\xdb\xb7 ;\xff\xed\xae\xe8\xef\xfe\xa5\x12K9\xb7\"\x1b6!\x93.}\x9e$3:\xdc\x84L\xfd\xf02Y\xacb\xb6\x1f\xc3\x8d\xc7\x84!\xde\x80x\xc3h\x887 \xde0\x1a\xe2\x0d\x0c\xf1\x06\xbb!\xde\xa0\x0d\xf1\x06\xc4\x1b\x10o\x00\xce\x92\x10o\x18\x0c\xf1\x06\xd3\x10o@\xbc\xc1b\x887X\x8fA\xbc\x01\xf1\x06\x87!\xde\x80x\x03\xe2\x0d\x887\x18\x96CjF\xbcA\x18\xe2\x0d\xdf\x03\xdepW\xf4\xe6\x105\xdd^\x82\xff8\xecf\xf4$\x8e\xe5\x9e\x17\xbb\xcb\x9c\x11\xda\x88\xc0]\"\xba\xd8\x1d}RO\xf1d\xff\x89\xaa\xf9q\xbe0\xee\xc4%,\x9f\xe7\x00ao\xbf\xdbt\xc5\x9a\x0e\xea\x9e\xc8\x19M\xd7\xab]]4\xe7\xbf\xf1F\xfad\xbew\xf2\xe8\xab\xbahD\xb3*!\xf6\xe9\xa8\xf2\xfa\x99\xa8\xe2\x88\xba\x0c\xe1\xc5\xf2yD\xc5z\xe1A\xab\x1ah\x94\xfaJ7\xfa%4A\x16\xaf\xbc\xb9v\xa0\xf1\xae\x95\xf838O\xda\xa1\"\xdcU'2w\xa1!\x05S\x8f;\xffE\xf8\xf5\x91w%\xe9\xbb\x18\xdd\xf9\xff\xe3\xfd\xd1\xf0yJL\xb8(\xe3\xdc\xec\x0e\x9f\xaf.\xe6\xcf<\x06\x89\xa3\x8a\x1a\\B\x84\xac\xc2\x11TQQEu\x1e\x89*\xaa0TQ\x0f\x0dUTTQ]\x86**\xaa\xa8\xc2PEE\x15\x15UTTQ\xa5\xa1\x8a\x8a**\xaa\xa8\xa8\xa2\xba\x0cUTTQQEE\x15\xd5\xb0\x1c\x8a\x16\xaa\xa8\xc2PE\xfd\x1eTT\xfe\xbfF\x01\x93OH\xf1$*%\xca\\\x84\xd6\xca\xa2P\xbe\xb4\xaa\xca_\x11\xe6P\x94Y?\x15*\xd7+B\\\xe2\xa9Z\xa3\x11\xe2\xa9[4\xbd\x90GMDS\xd9\xcd\xc4\xdf'Z\xa9U\x1f5\nx\xa5\x1bu\xa2\xfa\xe8\xe8 \xd3&U\x117\xb0\n\xbb`4g=HP\xa2\x12\xfd\xcd\xdaW\x83\xeb2\x90\x85\x0dB\xae)3\xfa\xaa\x12Ku{\x94F$~\xd2\xa3\x96Xmr\xee\x95b\x9c\xec\x94\xa4\xd4\xf2\xe4\xb0\x88\xd1\xde\xb2\xc7\xa2\xa3b=u\xb7\xab\xe5\xd7\xa1X\xb8)j\xf2om\xf3F\x15\xe8zf\xcbv\xbb-\x9au\xaf\xf6\xd8v]VL\xfc\xf8\xcb\x87\xfcD7U\xf3\x93\xd0\xa6\xe5\xf4p\x9c\xf6\x0dw\xb2rH\xd3\xa3]\x8aU\xc7\xa2\xee\x85\xf4\xe1l-k\xc9\x9a2\xb1\xb5\xfa\x1d\x15\x8b\x82\xc5\xd8d\xed\x8a\xb2h\xc8]\xd1\xackJ\n\xb2\xa9\x1e\xa8k\xa1t\xb81B\x17p]S7B\x16\xd9\xc9e&6\xdcJ\xfe~\xbb\xa1\xb4\x11\xaaG\xe5[\x12\xd7\x15=#\x15\xd3=\xc0uQ%B\x0c\xba\xd1\xd8\xca\xaa'\xed\x9e\xbdio\xdf\xac\x0b&\"\xd3\x1b\xd3\xd7\x8e\xf2d\xde\xff\x8e\xfcE#\x05\xae\x0bw\xb4(\xef\x8cl\xf3\xc3uE\x85\xe9\x93='?\xab\x92\x9f,\xbd\xde\xc9[\xf3\x86\x97\xb3\xe0\xf9\xfb\xa2\xf6\x19P]p$$\xf4=\xdc\xaa\x15\xd1\x1d\xed\xf8u=*\xcf/\xb4x\xa0\xe2\x9e\xb2V\x00+\xff\x9bv\xad\x9a\xb0+}N\xb0.od\xe6\x80\xb5\xf2\xac\xa34\xb5\x03\xbf\xcdu.\x88\x84\xc48\x0f\xb8\x1d\xf8\xc1f\x00\xda\xb8\xe3ld\x89\xc7o\xf6\x82>\xa9/\xc35\xff\x10\x17\x9dN\x89 =\xb5v\x9c\x05\xbb\xc8\xb3\x8a\xd5\xd4\xd3\x19\xc4\xd2\xd8\xa8x\x8d\x0b\xf8\xc3\xa8\xd4\xdc\xb6J\"\xaa\x9a\xb2\xde\xbb\xb7Mi\x9b7\xe5]\xe1\x16\xbc\xfb}y'Q\xaeM\xc5T:\x0d\xf9\xe8\x8a\x85\xf7\x82\xb5]OJ\xa1s\x17{\xd6n\x0bV\x95\x1e\x05UW\x90\xb5\x96\x03\xf4\x0ba%3Q\xaczV0\xef\xb3\x87\x9b\xb5\x03\xd9\x8e\xcctG\x90\xef\xc8Mx\xc0\x19\x8fL\x94G\x1a\xe7\xe1)\x0e7k\x97\x13\xe1\x14\xe2#\x8e\xf9\x88\xa4>|}x\xe0A\xa0\xdcGf\xf2\x03\xc4~d\xa4?\x96\xf2\x1fI\x04H&\x06$\x85\x02\xf1\x14\x86\x9b\xb5\x83i\x908\x1e$;\x11\x02eB\xb2R!p.$\x9a\x0c\x89gC\x82C!n\xd6\x1eA\x8a\xf8^\x82\xb8Y\xbb\xd5R\xa8\x11_\x0f\xc2\xcd\xda\xb5\x05 \x92(\x86$\xb4Or\nG\x12*\x137k\x9fY\x12W\x82\x9b\xb5GR&1\x9c n\xd6\xee96;u\x12\xac\x1dn\xd6\x9e\x83A Q(\x89\x1c\x8a\xa3,\xdc\xac\x1d7kW\x16\xcd\xa7\xc4\x12*\xb8Y\xbb\xb6\x14^\xc5Q\x14n\xd6\x9e\x9f]\xc9\xd5\x17#\xf8\x95\x18\x82\xc5\xbeY{X}\xba\xfc\xe9\xe2\x0dm\x8a\x9b\x9a\xae\x89\xd0\x8ez\x1d=\xf7\xa6\x127AJN\xfc\x06Od~{i*\xeb\xb8\xd0z\xf8\xdd\xacX?\xc1$\xdcC>\xef\xe0\xbc\xbbm\x8b{\x95\xc0\x9cWf\xd0\xa8Z\xb5\xe0\xdcu\xb4d\xa1Z\xfc\xd0\xd3\xfa\xf6O\xd3\xca\xdc\x88\x957\xb3\x0d\xa4-\xcb}\xd7;\xf7d\xef[\xf9P\x94m\xd3\xd0\x92\xa9\x151\xed\xa0\x07\xdaU\xb7\xcf\xa3\xee\xdd\xd0\xc7P\xb5T}\xaa^-^\xdc<\xabR\xe4\xd3\xb3\xeb\xda\xf6V/R:\x8a\x18\xb6\xc2\x9f\xe1\x14\xa2b\xceY\xef\xe8]\xb1\x84\xca\xef\xf9\xd0*\xfe\x9d\xcd\xbf\xe7yy=#\xfd\xb6m\xd9]\xfdL\x8a\xb2k{\xd7\x92\x19\xbf\x95\x8d\xee0\xba\xd9\xd3\x83\x01\xd1\xfc\x06!\x94\x1e\xcdorJ\x18\xcd\x8f\xd1\xfc\xd6\xdf1\x9a\xdf0\x8c\xe6\xc7h\xfe\xd1\xb2j\xbb1\xcan\x94\xae\x8b\xd1\xfcK\xd5\xdc\x04-7\x8b\x92\x1b\xaf\xe3b4\xff\x12\xfd6F\xbd\xcd\xac\xdd\xc2\x94\xdb\x8c\xba-T\xb5\xb5|\x90a4\xff\xd4\x00:-t\x96\x14\xad\xd1b4?H\x99M\xd1e1\x9a\xdfuXP\x8b\x8dPb!\xb1\xea1*,F\xf3c4?Dk\xc5h~aK\xd4U\x8c\xe6\xb7\x95\x14\xd4SS\xd5T\xe7\xbb\x01\xa3\xf9\x0f\x0d\xa3\xf9\x13T\xd3\xb0f\x1a\xab\x98F\xe8\xa5\xd1ji\x9cV\x8a\xd1\xfcq\xea(F\xf3\x0fv\x0cE4G\x9f\x8bPC\xe1Z\xa8~Q\xbb\"\xe3\x9dy\xc5\xc7\x98\xb5\xb6\xe9i\xd3\xef{\x19\xb6v\xfe\x9bxBe\xe4\xa1/\xd5\xb8\x11\xb8\xf8U\x95u\xa1\x8b\xba\x16:\xe4$\x96^\xff\xa44J\xd1\xd3D\xd7\x12+GCQ\xa2/\xb3n\xdf\xf3\x0f\xad{\xda5\xb4\x1e\x82\xb6\x1b\xfa\xc4\xa6j`\xd5+9\x90\\\xaa\xd2\xc4\x8b\xd3\x08h\xeaY\xdb\xf1>+\x95K\xf1FTA\x95\xd3\x02Bm\xf9|u!c&\xe5\xf7\xa7^\xc2\xa8\xe9\xa6(\x9fUK\xf5'\xf4$7\x80\xbd\xa5IO\x1e\xa7\x87\x84\xa7l\xb2\x13Lt\xb2\xccz\xdd\xe3kf\xc1)$7-\x14\x9b|\x0c\x1e\x07:\xe8\xe2\x97O\xd7\xce\x8aiu9\xb1]\x90u,n2`O\xee\x01\xd9\x8b/\xbd\xe1nUb\x83\x8e\xb6\x19n\xa3T(|\xbb\xba\x88\xbb\xde{\xc6y\xd9\xe43\xc2\x1bsF\x947\xcf\x08\xff_\xd2vd\xd2J\xdf\x1e\x06\xc1\xdb\xfd#y\xaf><\xcc\x10BOI\xbc\x1c\xfe`\xeb\xd6\xf3\xb7\xfe?\xf8(\xdc\xb3B\x840\x8a%\xe9\x1d\x15k\xc4wE\xb3\xee\xef\x8a{\xc7\xbe0\x93\x82U#\xe7e\x17%\x9fa\xd4t\xbdQe\x0fe\x92\x9e\xd1\x9d\x16e\xcav\xdf0\xda\xed\x8a\x8e=\xcf\xa3/\x9d\x97\xb4]\xafl\xf9\xdb\x9a\xcd/\xf6\x96|\xda\xd1f\x1c8\x8b\xce\xed\xab\x8e\x16k\xa1s\xf4\xb4\x91\x1b\xacv\xb4\xa4\xd5\x83\xfcT\xa4\xcc\xb9a\xd0A\x9f\x9fWN\xec?[\xd6m\xaf6n-\x8b\x864-\xa9\xdbfC\xbba\x9fa}e\xc1Q\x88\x0b;\xaf\xe7\xadP\xdb\xad)\x1fh\x02C\x99\xde\xa1\xd7\x1c\xc1\xaa^\x9eME-\xf6\x8d\xfa\x8f\xe3\x8dj\x9f>\xbf\xff\xf0y\xf5\xf1\xd3\xc7\x0f\x80\x87~<\xe1\xebG\xf1\xff\x80#\xfd\xc7\x0d\xa3PT=\xa0\x83\x8f\xaby?\x8a\xcdj\xdf\xc8\x8fK>\xbdT\xeew\x16\xa4\xef\xa8\xaf\xff\xcd\x1c\xf3\xa3\xee#\xa2\xb3\xdd\xf01\xb0\xae\x1e\xc4\x9d\xe5\x93\xe4\xe6Y\x16z\xa6\xa6R\xdb\xe2\x99\xac+\xa14\xdcv\xedV\x8e\x06\xfc\x00\x9f\x8a5\xecC\xfbL\x1ei'gs\xdegdrK\xc6\x1a\x16\x9dY=\xfaT\x94\xac~\xd6\x0b\x0c\xb2\x16\xb6KY\xafd\x0e(\xa1w\xf9l\xec\x01\xbd\xc3=\xbb\xb5\x86g\x18\xe2\x98\xb6c\xabj\xed[[\x04\xaau\x03!\xe7y\xcb\x13\xe3\xd4d\xf6\xe3\xbe\xf1\xea\x80<\x8d\xd6\xf7n\xbc]\xeef9:\x88N\x00\xbe\xbakw\xde\x8du]\x13Pi\xcei\xa84@{B9\xea \xa9\xab^|A\x8d\x95\x1e\xb9\xa9\xae?\x13\x13\x18\xf9\x18+\x85\x8d\xdfGw\xd7S\xcf\x9b\xf8\xeaj=t\x90\xce\x85 \\,>\xe0YW<8\x06(\xa5\xbf/PT\xc3~hw\xc5?\xf7\xe3kJ]R\x0f^UO\x8aMG\xe9\x9a\xecwm\xa3v\xc6w~\xfcs\x1b\xe6\x07\xd6#\x02\x8f(\xbcE\xe2\xa9\x1bo\x98\xbd?\x06\x9f\x0e\xf8\xf5\x86\xd7\xb8\xef\x92\x90a\xe3R\x17\xb0V\x9f\x92\xc3\x14\xba0\xfa\x05\xbb3W#Ec];\x07\xe97\x9c\xf5\xc7\xb1\xbar\xf1\xc52\xaf\x99TZ?\x15*\x9f\x87\xf9U\xcc\xc6M\x01\xa6\x05\xec\x8aM\xd5\x88\x0fd\xcb\xc7\xa6\xba[\xc3!\xc37\xef\xe1\xa1\xe9\x19.\x1a\xfa\xc4V\xf7\xd4\xf1V\n\xde\xe4 v\xa0Z\xe1\xdcC^__/\xa8\xf0\x7f*\xfe\xa6\xe8\xd5\xfc\xf3\xaa\xd8\xd0\xcfr-\xe6\xad\xfc\xddQ\xd8?\xf7\xb4{\x16\xc5\x88E\x98]\xb1\xa1d\xdb\xf6\x8cPA\xb5\x08\x14\xc6r*kY\x91\x9a\xe2C;`\xef\xdeL?4\x90\x88\xcb\x8b\xf6\x8b\x7f4\xfb\xed\x8dD+4Oe\xc0;.\x14\xd5t\x91x\xe5\xacDa\xae\xc1\xf4\xb1\xe0\xe3-;\x13[\x82(L\xac\x17\xabX\xfcyZ\xcbW\xedce\xe9j\xe1\xe7TV\xc5 \xc3\xdb\xc9Bk\xd5\x90\xcd\xe7\xab\x8b\x11\x16W\xab\x98=\x9f\xfa[\xbf\x83\x1c\x14\xa2\xd8~\x84\x97!\x88M\xb5V7\xac\x89\xf2\x0f\x1c\xf1\xfdbz\xc6\xea\x0e}\xc6u\xbb\x1d\xeb\xed\xd5\xf6:\xba\xa3\x82\x99\xf8\xa9\xe8\x86\x9b\x14\xda\x89i\xe2\x16\xd13]R\xc1\\\xa6\x94k\x8c\xce\x01Bv\xfa\x9b\xba-\xef\xc9\xc1z\xa8:2}|\xe8\xe8C\xc5\xdfj+\xd9-\x8f\xfe\x94HAK^s\xdc\xcfe\xdc\xaceD\xdaZ\xdbLj\xa8\xae\xcbi$\x7fu\xd5\x1a0\x7f\xf3\xa8\xaf\x83M\xf5@\x9b\xa1. \xcf\xd0G^\x81\xba\x96c\xd9gU\xce_\xe4u\xc4\nQ\xd9 \xc6L\xe6\x8d\xa2Ey\xe7\xba\xf5\xe2{\xa8\xe6\xe3*\xdd\xf1\xe7D\x17\xf6Q\xdcN\xdb\x03\xc1/\xd9\x17[: \xc3\xa4o\xb7fz\xac\xa2\xde\xb4]\xc5\xee\xb6\xbd\xf8@+\xef\xda\xb6\xa7\xf6A\xb9\xa3=e\xae\x07X\xf9\xadjHI;&\xf7\x17j\xd6\x8a\xd9\xa5o7o\xc9]\xd1 \x94\xf0\xbe?\x93\xab\\o\xb6EyW5\xb6Qb\xceM\xda\xaex)nOOIY\xf4\xb4?\x9bxW:d\xee]\xb5\xed\x90\xbb\xf6e\xdb\xb0\xaa\xd9\x0b\xb8\xd3v\xc9\x1b\xfe\x06j*&)t\xf1\x01Yv\xb4\xe8yM)\xef%Jd\x9f\xdd\xe4\x0d\xb5n\xa1.\xfc9\xf9; xG\xaf\xbb\x83\xc2u\xf4F>\xd3\xb5zm\x18\x91\xa3\x0c#r0\"g4\x8c\xc8\xc1\x88\x9c\xd10\"\x87aD\x8e\xdd0\"G\x1bF\xe4`D\x0eF\xe4\x00gI\x18\x913\x18F\xe4\x98\x86\x119\x18\x91c1\x8c\xc8\xb1\x1e\x83\x119\x18\x91\xe30\x8c\xc8\xc1\x88\x1c\x8c\xc8\xc1\x88\x1c\xc3rDG`D\x8e0\x8c\xc8\xf9\x1e\"rFR\xe5\xed=5\xdf\x82\xbe\xa0\x1c\x85~\x14j\x08\xed(\xdbw\x8d\xc4\x04L\xc5\xfc\xed\xc0\x89\x88\xa5\xa0\xcdl\xcdDh\xe0\n\xaf\xf2\xb0\x1fo\xc9\xa7F(\xc7\xe2[\xb1\xbd\xbd\xed)\xe3\x9f_\xd3\xea\x12c)\xbb\xa7\x13v\xb4j\x94\xden\xfcm\x8c\xd9\xb9-\xea>\"hg\xb20`q\xa2\xac\x9f\xcb\x8f\xb3\x8fr\xd5\x18\xe1\xcaf\xbf\xa5]U\xea\xbf\x89\xa7M\xf1\xb6rU\xe4\x8e6\xda\xf1\xfbfX\x88\x9aM?/Ei5\xed\xfb\xd1\x85r\xe9f/\xd4\xcb{\x1a\xe9\xcfi\xf1Gv\xeeL\xba\xb7\xb8\xb7\xae\xb6\x15\xd4\xbb\xe2X\xad\x9b\xba0\x1d\xb9Hi\xf6`\xa5\xb2\xce\xf3\xf7\xee\xe4\x92\x84\xf9\xa7\xcb[R\xd3[\xa6V\xbf*\xb5U\x94\x9e4\x8a\xf5U\xf9\x80\xc8\x8bp?\xdf6\x95\xc5N|/\xb7\xb7\xb6k\xf1\x99\x01\xf7\xdc0\xce\x8a\x87H\x94e\x9c\xa9&\x0e\xc6\x81\x07Aq]\xdb\xdeF\xd1\xd3\x01\xd8Fu\x8f-\xed\xeek*\x8b\xe7\x15\xa1OU\xcfhS\xceO\x10\x078\x03HTa\n\xff/\xd8\xf8\xaeP%?\x16=\xe9(\xeb*j#\xd5\x16|\xd6a(N\xb0\xba\x18\x8a\x83\xa18\xbf\x83P\x9c\x84H\x9cYif \xce\xec\xa7\x9fh/\x106^\xc4\xc58\x9f9\x13@\xa8\\,\xedI\xa1\x06+\x05\x10h\x17\xf2\x89\xf8\xac\xb8ax\x9b_\xc72\xdaaP\x10\x06\x05aP\x902\x0c\n\xc2\xa0\xa0\xd10(\x88aP\x90\xdd0(H\x1b\x06\x05aP\x10\x06\x05\x01gI\x18\x144\x18\x06\x05\x99\x86AA\x18\x14d1\x0c\n\xb2\x1e\x83AA\x18\x14\xe40\x0c\n\xc2\xa0 \x0c\n\xc2\xa0 \xc3r\x04h`P\x900\x0c\n\xfa\x1e\x82\x82FB\xc7(f\xf2!\xa9\xa9\x0c\xb9\xb8o\xcf\x12\xbcx\xab\x9c!rA\x82Q\xae\xba\x88\xcf\xbb#V\xe4X\x04\xfe\xb9T\xe5WB\x99\xf5\xe0\xf8\xc6G\xbb\x92\x06/\xc4\x89\x929\xd6\x90\xbe\x16 \x95\xd4/!\xf1\xe1\x8f3=r\xe4\xdb\xc7\x1e<\x80\xee\xc3\xcch`8G\xe4\xc8\x07\xff\x1b\xb5RG\x9dl\x1c\xc0\xd0\xa2\xf5\xca\xbc Npd\xe2T[p\xc0\xdc\xc1\xc3\xf9\xe9\xe4\x88\xaa\x98\x8b\x92\x0b\xae[M\xab\xee\xcd\xe3\xed\xf7\x01 \xb5\x83\x04\xdbB\x00Z$\xa0I\x04\xb8\x9e%-I\x91\xf4\x94w\xb0(\xe5\xf9F\xcb\xabJ\x06u\xc9\xdc\xca$\\\x9b\xcc\xa4N\xa6\xe9\x93\x9e\xe2\xb8C\xc1\n\xe5b\x8d2\xb7J\x19\xa9SfV*\xe3\xb4\xcaH\xb5\xd2\xd7\x87\x07\x1d\x13\xaaWfV,A\x9aeF\xd5r\xa9n\x99\xa4\\f\xd2.S\xd4KOaB\xd7\x0c\xeb\x97GQ0\x8f\xa7a\x1eE\xc5\x8c\xd31\xb3+\x99P-3\xab\x9a \xd73\xa3\x15\xcdxM38\x14\xfe \xa0jf\xd05\x03\xca&pB\x05P7cf]\xd1\n\xa7\xef%x\xd3>P\x80\xc6 \xad_F\x9d3F\xe9\xcc\xacu\xa6\xa9\x9d\xbe\x1e\xd4\x87\xf5\xced\xc5\xd3Q\x1a\xbfZH\xf3\xcc\xa5z\x82\xa5;\x80\xf2\x19\xa5}\x06\xa4\x8a$\xfd3T\xa6s\x1d4\x93\n\x1a\xefL\xb8\x12\x1aj[\x82\x1a\x9a\xa8\x87\xfa\xd6\x93\xb3i\xa2`U\x14\xa6\x8bB\x95Q\x80\x97\xe3\xd5\xd1\x18}\xd4\xa7\x90f\xd2H#U\xd2e:i\xc8\xa1\x11Z\xe9\x11\xd4\xd2`\xed\x9c==\x9ff\nPM\xd3uSGq\xfc0\x9fr\x9aY;\x0d\xa9\xa7\x89\xfa\xa9\xa3,\xf9e\xe8\xfb8\x06h\xa8>\xa1\xc7\xa7\xa3\xe6WR\xb3k\xa9n55\xa7\x9e\nQT\xe35\xd5(U5AW\x8dUV\xbd\xda\xaa_\xe9\x82k]P}5Aa\x8d\xd4X=\xcdM\xd1Y\x1dE\x19\x1a&\xec\x91\x80i\xad\x9e.\xdfl\xfcjkV\xbd5\xa0\xb8\x1eGs\xcd\xd5\x17#t\xd7\x18\xe5\xf5p\x93@i\x16\x8d\xe9\xe0\xb8\xf0\xf7\xad\xb1\xcf\xaa\xa1\x0e\x1a{\xad\x9a\x12\x96\xfcZ\xb5\xad\xf1\x18\x83\xa3<\xc3\xe6\xee\xf9.\xab\x18\x0c\xae\x0d\x83\xc1\x0f,\xae\xba\x18\x0c\x8e\xc1\xe0\xdf,\x18\xdc\xb5\xef\xb1\x19\x06n\x8c\xae\xf3\x88\xf0\xcf\xb6\x88p[Q\xe7\x8e\x02\x8d\x08\xf1\xe14\x0c\xca\x9e\xfd\x8aA\xd9\x90AOZ\x12\x02\x81A\xd9\x10\xf0\xc1\xb6V\x10\x8d=\xa4@\x0f\x18\x94\x9d\x11u\x88\x01\x1d\xa20\x07\x0c\xca^\n7$\xa0\x0dY\xc0\x86x\xac\x01\x83\xb2\x97\xe0\x0c10Cf\x94\x81\x81@\x86\x8c\x18\x03\x14b\xb0\xacO`P\xf6\xd4\x00\xd8\x02t\x96\x14\x8d,`P6\x08TH\xc1\x140(\xdbuX\x10M\x88\x00\x13 !\xc71P\x02\x06ecP6\x04=\xc0\xa0laK`\x03\x0c\xca\xb6\x95\x14\xc4\x0bR\xe1\x02\xe7\xbb\x01\x83\xb2\x0f\x0d\x83\xb2\x13 \x820B\x10\x0b\x10D\xe0\x03\xd1\xf0@\x1c:\x80A\xd9q\xb0\x00\x06e\x0fv\x0c@ G\x9f\x8b\x80\x03\xe0h\x00\x06e\x93\xc8\x8a\x1c/([K\xb32\x1c\xf6\\\x0b\xcf\xe7\xbf\xcd\xd4\xfb\x7f\x9dK\xd5\xd2\xf8A\xfe\xc1\xb7\xb5\xda\x7f\x1d\xc6r\xeb\xeb9\xc2\xb9\x07\xa5\x18\x1a\xd1\x9d!\x90{R%u\xe0\xc9\xc6r\xcfn\x98K\xe3K\x026\x98W\xaa\x0b\xaeRA\x96y\xb2\x8bt0\x89.E\xa0\xf3\x0bqI2\x9c\xb8\x84\xa3\xc0\xa0\x08\x97A\x82K\x14\xe0\xdcX\x1fH~[$\xbe%Io\xa4p\xa2\xc4\x0c&\xbc\xa5\xc8n\xbe\xc5p\x90\xe8\x96Yr\x03 n\x19\xe5\xb6\xa0\xd8\x96Ij[\"\xb4E\xcbl\x19D\xb6\xcc\x12[@`\xcb.\xaf\x1dG\\\xcb.\xad\xc1\x85\xb54Y\xcd\xe3\xf4\x90\xa8\x96MR\x83 j\x96\x19\xbd{|\xcd,\xa6\x85\xa4\xb4\x85B\x9aGF\x0bNO\x82\x12\x1al\xfe\x92W>\x0b\x89g\xe1:\xa5 gzd\xb7\x14\x18\x92\xcd2\x8af\x0b$3\xbb\xd0\xed\x13\xcc\xf2\xcae~\xb1,\x87T\x06\xd2z\x022\x19X$s\xafg\xc7\x0bd\xee\xb2\xackGY\xa4\xb1\x18gAe\xb1\xb0O\xc0\x92X\x82 f_g\xcb$\x86\x81\xa4\xb0\xb0\x10\x06\x91\xc1\xbc^\x8c\x95\xc0\xa0\x02\x98K\xfe\xca ~EH_\xe9\xc2\x97G^\x82\x8a^\x99%/O\x8d\xac=5I\xec\xd2\xc2\x96\xa5<\x87\xd4\x95Y\xe8r\xcb\\\xa9\"\x97X\x11\xb0U\xdc.q\xe5\x15\xb8\\\x1f~Aq\xcb\xb5\xfa\xee\x12\xb6\xf2\xcaZ\xe9\xa2\x96C\xc0J\x92\xaf\x82RU\x9cP\x05\x96\xa9\"E\xaa\x18\x89\xca)P\xb9k\x03\x15\n`\xe2T\xa44\x15!LY\x9b\x96W\x94r=\x14\x0b\x04)\xeb:\x85S\x8eJ\x13\xa3|\xc2S~\xd9iyO\x02KNP\xc1\xe9\xf0\x159ly>U\x1b\xe0\xa9N=\xd9J\xbd\xdf\xa1\xd3\xe0\xd7\xcb\xf7\xf6KN\xab5+\x04\xa3M1\xdat\xb0\xb8\xeab\xb4)F\x9bb\xb4)F\x9bb\xb4)F\x9bj\xc3hS\x8c6\x1d-E\xf6v\x16\x86\xd1\xa6\x87\x96I\x02_&\x82'\xc8\xe0Y\x84\xf0\xecRxP\x0c?\x82\x1c~,A\xfc\x08\x92x\x8c(\x9e*\x8b{\xc7\xf0\x900\x9eQ\x1a\x87\x8a\xe3\x91\xf2xv\x81<,\x91/\x16\xc91\xda4X\xb34\xd1\xdcZ\x14F\x9b\xa6\xc8\xe7!\x01=\x8f\x84\x0e\xd4\x85\x832z\x84\x90\x1e\x8c\xfa\x8b\x14\xd31\xda\x14\xa3M!2{\xd0\xab\xb1R;\\l\xc7h\xd3\x99e\x96\xde1\xda\xd4\xb4T!\xdeZ\x18F\x9bF\xc8\xf2K\x84ykq\x18mj=\x01$\xe5c\xb4i>a\x1f\xa3M\x17\xcb\xfey\xfa\x1cX\xfa\x87\x8b\xff\x18m*-\xad\"3Q\xddU\xa1A\x07\x97\x87\xe9\x17\x83\x1bdX\\A\xa7\xf4}P\xf3\x03\xb9\xd9^s\xa5\x92~\xb3\x9a\x1f-\xc2\xb7\xa1Ol\xd5\xd3\x7f\xeeiS\x02\xf7]\xfeH\x9f\xd8\xb5:\xe33-i\xf5\xc0\xe7\x05l\xdf\xa9w./\x92t\xea\x07]\xb4\x98\x1c\x15\x92(\x18JR\x15\xb3\x86\xdfZ\xae\xa2\x0e;\xd9\xe0\xdb\x89/W\xca\x03Qbi\x10\xd9P2\xb9p\xf1\xe0Z\xed\xeb\x83\xa7\x90 \x10\x84@\x90iq\xd5E \x08\x81\xa0\xd3\x04\x82\xc6\x17\xc3\x14\x03\xe2\xefZ\xda39\xd1\x0fR@\x96W\xccP \xe2@\xd2\x10\x07B\x1ch4\xc4\x81\x10\x07\x1a\x0dq \x868\x90\xdd\x10\x07\xd2\x868\x10\xe2@\x88\x03\x01gI\x88\x03\x0d\x868\x90i\x88\x03!\x0ed1\xc4\x81\xac\xc7 \x0e\x848\x90\xc3\x10\x07B\x1c\x08q \xc4\x81\x0c\xcb\x81f \x0e$\x0cq \xc4\x81\xbe7\x1c\xe8hh\n\x1fl)[\x15%\x7f4k\xba\xde\x88\xb5\x8d\x1e\x06\xa9\\\x89\x93\xdf\xcd\xce\x1d8\x15\xb1\xce\xad\xe6<\x94\x91\xf95\x86b\xc6\x04,c_\x96_\xed^x\xc5~uu\xe4\xc9\xf2+s/\x9c\x86H\xa7\xfa\xc3\x82\x05*\xeb\xa3)\x1e\x8b\xf1y\xb0\xcf\x08\xc6\xee\x99\xfb\xf2\x07\x0f\xa4\xbd\x02\x9a\xf1Ypy\x00\xf31\x1f1\xe4C\xa1\xafm\xaf\xd9\xba`E\x86ZA\x17\x0d\x87\xb7%\xbf\xee\xec\xbd\xda\x0f5f\x05K^\xe5\x93\xcf\xacL\x06\"$\x1c5\xc7\x15\xebTU\xa9\xbe\x12(\x7f\x0e\xd5\xf2\xbf\xe6\x92\xac\xc5\xf1\x99D\xcf\xda\xce1\x87W5.\xdb\xed\xb6b\xe2i;;x\xfe\xe4\xf2\xb6\xa0\xbbv\xacw|4_\x14u-\xf1\x0e52T7\xb5d\x1fxa|\x86hJrf\xfd\xad\xc5U\x0d\xa3\xdd\xae\x13pKeeM\xc8\x90\x0e\x8b\x0f\x82C\xfd\x0f\xaa/\x84\x94BW\x7f~Wv\xc5\xa6j\xc4x\xe9\x84\xc2\xc6C\x86A\xcf1 %\x01`\x82\xd6\xbb\xa7\xcf\x0bQ*g\x07v\x01,\xda\xf4\xf55\xbb\xc2\xff\xa9\xe4\x9f\xa2\xef\xa5\xc6uUl\xe8g\xc9\xb4\xbc\x95\xbf;\n\xfb'\x7f\xe9\x8ab\x04\x1a\xb8\xe3s\xb3m\xdb3B\x85\xa8\"\x94\x18\xcb\xa9\xaceE\xea~\x1e\x80qE\xb9\xc0\xb9\xe0/./\xda/\xfe1\xe2\xc1Z\xce3\xb4#\x17 a\xba\xa8l\xf7\x0d[\x89\xc2\\S\xcf\xc7\xa2'=eg\xa4b\xbdV){\xb2o\xe4\x13\xbf\x96\xc2\xcdce\xe9j\xe11DV\xc5 \x92\xda\xc9<\xbfj\xc8\xe6\xf3\xd5\xc5\xd0\x99\xf5$\xba'\x8fw\xb4\xb3u\"\x87\x08^\xb6\x9d,C\x00\x03\x9ay\xd2Sr\xfe\xf9\"4!\xd33Vw\xe83\xae\xdb\xedXo\xef\xd2RGwT,\xd9\xffTt\xc3M\n|\xa7N\xdd\"z\xa6\xebKu\xbeJ\x16\xa0Fe\xa7\xbf\xa9\xdb\xf2\xdeE .\x18\x1f\x10\x10\x0dV\x17\x01Q\x04DO\x13\x10\xb5|\x80\xb1~\x19-\xea\xf8\xa2DPT\x1a\x82\xa2\x11_\x81\x08\x8a\"(\xaa\x0cAQ\x04E\x11\x14EP\x14AQ\x04E\x11\x14\x85\xce\x92\x10\x14\x1d\x0cAQ\xd3\x10\x14EP\xd4b\x08\x8aZ\x8fAP\x14AQ\x87!(\x8a\xa0(\x82\xa2\x08\x8a\x1a\x96\x03\xdaCPT\x18\x82\xa2\x08\x8a~o\xa0\xa8Q\x91\x81\xecy{O\x9f]\xf5\x99){\n\x95)\xd4\xabE\x92\x9c\x12\xab0 \x83\xb7\x03W#\x96\xc86\xb3\xb5$\xc1\x0ch*\xca\xcd\xca\xbc%\x9f\x1a\xa1\xb4\x8bo\xe8\xf6\xf6\xb6\xa7\x8c\x7f\x96N\xabK\x8c%\xfe\x9eN\x18'\xee\xab\x7f*\x12V\xdb\xe8\xac\xdb\xa2\xee\x83\xder,\x98X\x9c(\xeb\xe7\xf2\xe3l\xb1B5F\xb8\xb2\xd9o\x05\xdb\xa6\xfe&F\xa1\xb2hx{\xe4j\xd1\x1dm\xb4\xe3\xf7\xcd\xb0@7\x9b\x96_\x8a\xd2j\xda\xf7\xa3\x0b\xe5\x92\xd6^\xa8\xbd\xf74\xd2\x9f\xd3\xe2\x8f\xec\\G\x86@\xc3\xbdu\xb5\xad\xa0\xde\x15\xc7j\x81\xd9\x855\xc9\xc5[\xb3\x07\xcb9R?\xdf\xdcx'\x97j\xcc?]\xde\x92\x9a\xde2\xb5*X1\xf9\x9a\xd0\x93i\xb1\xee,\x1f\x10y\x11\xee\xe7\x9bg J\x14\xbb\xdd7\xf4\xa2 g\x8d\xe7\xfb|i\x9c\xc1=*zh+\x06\x1a\xc2\xffQ5\xeb\xaa,\x18\x1da\x19\xe9Aq\xa0\xeaHfqUS\xd6\xfb\xf5l\xaa\\\xc8\xab\x0c\x12\xe0\xec\x8e A\xd9X\x99\xe6\xaf4\x83K\x9c\x0d._/\xe7\x94\xe6\xac \xe2\xeb\xa2\xa3\xbd\x92\xfe\xc5\xe35>\x8f\xfc\x91{\xab\x9e\xa6j\xd3\xb4\xddl]_?\x8d\xd3KH\xcf,\xbd\xb17m[\xd3B7\xe7\x05\x98\xfe\xfe\xfc7\x0d\x18\xff\xcb\x83\xf4[\xa9\x0b\xd1\xba\x8a\xf2\x11L \xb6k\x07\xc7\xcfghwp@\xff\x95v\xd5\xef\x83\xcf\x8f\xc2)`I\x1d\xb5\x1b-\xdb\xcejXFL\xf2\xe6\x8b\xbd\x98d\x12\x19\xc2\xc1\xe2\xaa\x8b\x0c!2\x84\xdf\x9a!<\xe8En\xe0o`\x08\xcd\x10\x11\xf5\x80\xcd\xdf\xb9\xc4x\x99\x88\x99\xc3\x81\x82\xa7\xc6[9\x1e\x15u\xdf\xeaI\n\x7f\xb5\xc9\xb1I-hj\x8f\xddv\xedv\x1c\xbf\x0e\xca\xf3\x0cgH%\xce~E*\x112\x98JC*\x11\xa9D\xbb!\x95(\x0c\xa9\xc4CC*\x11\xa9D\x97!\x95\x88T\xa20\xa4\x12\x91JD*\x11\xa9DiH%\"\x95\x88T\"R\x89.C*\x11\xa9D\xa4\x12\x91J4,\x07!\x86T\xa20\xa4\x12\x91J\xfc~\xa9D\x8d\xa38k2M\x8b\x97\xb3\n\x0e\xd1\xfc\xd8\x18\x8e\x91}\xce\x83\xe0\xfc\xd7<\xab\xe6\xc5x\x9a+\xa1\xa6Q\xb2\x80pho\xa6\xd2\xd4\xc5\x813i\x1aWT\x07\x9d,\xa4c\xb4\xfc4TB\xcc\x9f\x89\xf931\x7f&\xe6\xcf\xc4\xfc\x99\x98?\xd3b\x98?\x13\xf3gb\xfeLd_-e!\xfb:\xd8\x1f\x97}\xf5\xe5\xcf4>\xbbr\xe4\xce4\xbf\x1b1m\xa64\x04T#>\xfe\x10PE@U\x19\x02\xaa\x08\xa8\"\xa0\x8a\x80*\x02\xaa\x08\xa8\"\xa0\n\x9d%!\xa0:\x18\x02\xaa\xa6!\xa0\x8a\x80\xaa\xc5\x10P\xb5\x1e\x83\x80*\x02\xaa\x0eC@\x15\x01U\x04T\x11P5,\x07,\x88\x80\xaa0\x04T\x11P\xfd~\x01UL\x9b\x19\x97\x93\x10\xd3f\x1e\xd1\xb9\xe1\x84\x8f\x9863\x87\x171m&\xa6\xcd\xb4\xf0\xfa\xe7\xbf\xed\x86T\x9a+M\x1a\xf7\xff:\xdf7\x02\x18}\xa0k\x91d\xd3\x83\xf5\x1b\xbd\xe6\xebp\xd2\xbb\xf2\xfe\x90\xe9\x1f\xcb$\x97?]\x1c`\xb6C1\xf3\xb4\x91\xc6\xca\xab~a\x0b\xaaW\xd7\xd6\n\xfcO\xeb\xa2\x8e8Y\xda\x7fhKV\xe0\xc2)\x07\x04\xf02\x85\xf4\xd4U/\x9eL\xe3\xbe\xcd\x13\xa3\x0e\xf5\x9e\x95\x81\xc4 \x12\x83H\x0c\"1\x18O\x0cN\xc7\xedC\\P\xfd7\x0b\xf1\x82\xb3w\x11r\x82\xd2\x90\x13DNp4\xe4\x04\x91\x13\x1c\x0d9A\x86\x9c\xa0\xdd\x90\x13\xd4\x86\x9c r\x82\xc8 \x02gI\xc8 \x0e\x86\x9c\xa0i\xc8 \"'h1\xe4\x04\xad\xc7 '\x88\x9c\xa0\xc3\x90\x13DN\x109A\xe4\x04\x0d\xcb\xc1l!'(\x0c9A\xe4\x04\xbfgN\xf0\x90\x0cq\xd5J\xb3\x02\x10@ \xbe\x82s\x19\xc9\" 9\x176\x9c\xc2x\xd9\xd65\x15\x9f\xb2?\xabC\xca\xfe\xc1\xf8}[5\x97\xe2:\xe4\xdf\xd5_\xbf\x05\x973\xfe\xcd\x81\xe7\xc8\xe3\xa2 \x1d\x99J%\x08\xe9\xa8\xd2\xe7L\xceP\xe0B6G\xd5B\x1d\x84x\x8e\xb4dP>a\xd9\xa2\xf8\x11\xf1]\xa7\xbci7d\xdf\x1d\xf8\xf6\xeac\xdc\xd4$Fm\x9cH\x06\x8b\xea*Y\x9b\xd0\xa4\xb5.\xd8\x05\xb5q\xb9\xf2\xc1\x12\x8d\xfa\x94'\x9c\xf2\xc7\xa6\xbbU\xa9\xd2\xa1.QV\xeeE]\x9b\xfb\xbcvd\x95\xa4\xfc\xce\xac\xb8u\xca\x92\xaa\xf2\x11]y\xc0Q\x89\x0d)\xfd\\N\xcf\xa9\xe6x\xb2\xce\xb65\xc8B\xf7\x0dSI\xb2}\xf9\xd5R\xf6\xcf*\xda\x88\x14\x95!zJV\xf4\xbd(\x1f;\x11\xbfk\x98\x89\xf8m\xc6\x86\xb1e\xa2\xa3\xb0\xcd\x8a\x12(\x8f\xe1\xe1\x81?\x8aW\xcb\xac$\x9a`[\xb4\x00\xec9\x12Z\x8d\xc2\x9b\xe7\xe3\xe7\xff\x10\x19&lI\xc9\xe8\xb1V\xa8\x92.\xf0\xb6-\"~\xf6L93\x9dV\xbd$L\xf1\x96w )\x0b\x19\x14W\xc0>\x15\x1bk!\xce\xdc\xcbD\xb1\xd4\xec\x1bVt\xa5\xf5-\xda\xac\xe3VNRX\xbd?=n\xa2\xec+\x9fm\xc1\xee\x00\xca\x0b\x91&\xe6r\x9e\xe5\x82\x07\x8fO\x95\xe5\x85\xa5\x07\x98\xddt\xf8E\xa6-\x19\xa58\xe4\x1b\x1f\xb2m\xd3o#\x92\x99\xd3\x1d\xe5\xfb\xfb\x05\xc9\xebI\xb2\xc0\"]\xb1\xf0\x95\xa9\x03F\xfa\xa0l\xfcFxL|\x8a\x89O1\xf1\xc9\x94\xf8\xa4\xfeF\xf8\xd0 \xdf\xffH\xf8{\xf4G\xc25\x0c\xe3\x07\xc2+\x8a\x19I1#\xa9\xa1\x98\x91\x143\x92\x1a\x8a\x19Ie\xccHRS\xccH\x92\x143\x92bFR\xccHBZI1#\xa9\xa6\x98\x91\xd4\xa6\x98\x91\x143\x92\x14\x143\x92\x94\xcf\xc4\x8c\xa4\x98\x91\xa4\xa1\x98\x91\x143\x92bFR\xccHjQ\x88\xec\x90\x98\x91\xc4)f$\xfdSd$\x0d\xf3E\xfa\x19IM,\xd9\xb5\xe4\x025\xd14\x93sz\xa5\xebU\x0fM\xab\xc2SH\xa5\xd4sZ\xee\xf3T\x842\xb4Q\xfdI\x1d\xcb\xc2\x9dS\xab\x9e\x17\x87\xe3\xf4U,\x98!>e\x02\xefR\x8en\xf3\xdbk\xb6\\\x16\xb4d\x17\xc2nw\xa1\xe5\\/h'\xd0\x95\xc9\xeaS\x95P$\xa9\x11\xd6\x92l\n\xab\xb44\xae\n\x85\x10E\xfftr\xec\xb9 \xaa\xc1pQ\xa6\xfb-\xcd\x93\xb9\xfc\x1b\xdf\xffUp\xb0\xf0\xd3\xaci*\x05\xbfOk\xd7X\xcf >\xe1\xdc6\xb4(\x1a\x11\ng\xd2\x9e#\xac\xe7\xd4Q\x9e]\xf6\x07\x16n/\xbc@!\xdeM\xb2M\xb0\xd2\xe5\xcfJ\\W\x17J$\xdc\xa6\xed\x15,\xac\x13\xf6k\x87\xdbN8I\xda\x7f:Y\xc2\x86.\xcb\xca\x1f\x97\x94BAK3\x96{|\xc5\x06\x11\x8d09\xcf\xaeDp\x02\xd9\xed~G)\xb6\x03\xa2\x9a\xf7M\xb2l\xbd\xc1$\xcaWh\xc6\x15\x0d\xb0\x7f$\xe9\"\x99\x93\x926\x01*B\x82\xfc\xc1j!\xb5\xd9U\xb5@\xbb\xe2$\xa2\x95\x1a|\xeb\xcd\x18\x87r[>av\x98\xb4b\x01{\xca\xe5\xe3I\xd1\x9b\xad\xde\x10\xb8]\x9f\xd3\xa2\x02\xdd\xf9\xf6j\xf6#\xdbr\x93j7%\xab4\xeb\xa7Y\xc8\xdd\xd8mBHf\xec\xc4vKX\xebR#Ef$\x0f\x03\xaas\"\xf9\xd1S=\xad\xca{<\xe6\x8f\x9f\xf2\xa7:i\x8e\xcd\x99%\xa5\x9f\xcc\xe6U\x90\x91:\x9b\xb1\xc5\xe9\x1b9\xac\xaf4\x8f\xb1-\x956\xf5r^\xb9P\xda5p\x87B\xd9f\x8b\xfdF\xe1\x0c\xd6v\n\xac\xa1\x04\x15,5\x15\xb26D\x1b\x98\xc2\xdd\x8d\xc1\xeeV?<\xc6\x91=\xe8hGR2\xe4WblUtZaH~\x13\x0e\x8b\xce\x8f\xe6~\x88p\x9b\xd6\xb2\xebG\xee\xe4\xe8\xc8\x9d\xce6h\xc2u\x9a\xde\xc4x\x9d\xde\xaf1^\xc7\xb6<\x1b\x8a\xf1:1^GM1^\x87S\x8c\xd7\x19R\x8c\xd7\x89\xf1::\x8a\xf1:1^\x87S\x8c\xd7\x89\xf1:1^'\xc6\xeb\x08\x8a\xf1:1^'\xc6\xeb\xc4x\x1d\x1d\xc5x\x9d\x18\xaf\x13\xe3ub\xbcN\x8bB\xc4N\xc4x\x1dN1^\xe7\x1f%^\xc7\x0c\xb0\xf2\xd2\xb3]\x94U\xfc\xe7T\x96\x9b\x04#\xd8\xca\x0b@\x0ek\xca\x9e\xbc8\x86\x8d\xc8\x97\xaf\xf0\xb4\xac\xaa~\xd9\xd4XT\x00\xae\x82[\xf5\xfbW\x0b\xb8*\x04\xd4\xa6\xf2w\xc0\x7f\xaa.\x05)\xe3T\x95\xde\xb0\x14\x8ej\xc9\xc0\xdc\xe6\xe8\x9au\xa5\x05\xdb\x02\xdc\xf0\x00\xe9#\x91\xe4\x8as\x19\x99\xa9\x9d\x1d\x06\xdb?4\xde\x05v\xcc\x0b

\x08\x98>\x1avB8\xac\x100x!\x8c\xc0\x0c\xb5\x0c\xd9\x83&\xdc\x10Bc\x87`\xc5\x0f\xc1\x17C\xd4r\x13wT\xf3u\x1d\x81%\x82\x11\xf2\x00#\xa6\x08^\xb8\xa2\x96\x95\x11o\x04_\xccQ\xcbM\xd8\x81\x06\xafY8\xec\x11P\xf8#x`\x90\xe0\x86C\x82\x0f\x16 \xcex$XN[\x0bF\x04\x0e8\x11\x16\x9b\x04\x1f|\x12\\1J0\x0f\xdc\x07\xab\xd42k!\x81\xd8-\x83\xc3,\x8d\x1b\"]\x99qK\x08\x8b]\x82\x0d\xbf\x043\x86\xa9}\xc7\x17\xdb\x84\x80k\xd7\x01\xe3\x04'\x9c\x13\x14\x15\xf4%u!-]\xbe\x1e\xe6\xa6\xde\xfa&I\x83T\xb6\xbfK\xd2j\xa2\xd6\xb6*F-E+\xdeQ\x8b\xbf\xffU\x92\xa1\xaeU~\x94\xa4(\xb3\x9c.\xba\xd8l\xf3\xa5\xa4\xe1\xf7\xed\xe2\xf7H\xe2\xf7H\xe2\xf7H\xb8\xf6\x8c\xdf#\x91\xd4\xd5\xa6\xe8\xb4e\xa1n\xc6\xa6-WJ\xeb\xfd\xe9q_X1\x8b9f1[a\x04\xbbz\x10\xe4\x1a\xdd!]\xe2Z\x86\xd8\xc8\x8e\xa0Q\x1d1\x8b9f17\x144Z\xc3%R\xc3)J#f1\x8f\x8d\xc8\xf0\x88\xc6\x08\x12\x89\xe1\x1e\x85\x11\xb3\x98\xc7D]\xb8D\\xD[\xc4,\xe6\x98\xc5\x1c\xb3\x98\xb1\xd1\x12A#%|\xa2$b\x16\xb3\xee1k4\x84C$\x04&G\xd7%\x02\"f1\xc7,fL4C\xccb\xe64&b!f1\xab8Y\xa3\x12|#\x12\xb4gC\xccb\x1eR\xccb\xf6\x88$\xb0G\x11\xb8F\x108D\x0f8G\x0e\xb8E\x0d\xc4,f\xb7\xc8\x80\x98\xc5\\\xd3?e\x16\xb3\xe9\xab\x03\xb1\xc6\xbf[\x01\xf5X\xe3\xff\x80\xc2\xb5W\xa7\x8f5\xfeCH1\xd6\xf8\xff\xe3\xd7\xf8\xbf\x89\xabAq\xf7ouy\x83\xbfW\xd5\x1f,\x05)\x9az\x14\xe9\xa0\x14\x85\xad\xfc\xc47r\x84\x7f\x80\xea\x13:\xd8\xde+\x12\xab4\xa2\xefV\xc73\xc6s\x1b\x1cw\xc7\xa1\xee>\x98\xbb\x19[\xf7B\xd6y\x13\x1a\x86V\\=\x00\xaa\xee\x89\xa9k\x91H\x1c\xa2>\nO\xf7B\xd3\x81hS J\x1c\x96\xee\x83\xa4\x9b\xf0-\x14\x8e\x1e\x18EGa\xe8\x01\x11t+~\x1e\x08=\x1f\x83\x9d;#\xe7\x01p\xf3\xc0\xa8\xb9\x053\x0f\x8e\x98\x1f\x06/\x0f\x8e\x96\xe3\xb1r?\xa4\xdc t\x1bN\x1e\x0c%\xc7a\xe4\x8aK\xba^\xbf\x06\xc6\xc7m\xe8\xf8Hl\xdc\x80\x8c[\xcd\x13+*\x8e\xb3_\xc2\"\xe26<\xdc\xde'?,\xdc\x901bC\xc2\x03\xe2\xe0#Ppu\xec\x8a \x03\x0f\x8b\x80\x9b\xf1\xef\x10\xe87\n\xbe\xb5 \xdfh\xdc[\x0fQ\xb9c\xdez^Jwp\x10\xb4\xdbEXX\xa4\xdb.\x134\xca\xed\x81q\xab]\xe7\x81\xf0m\x14\xbam\xc7\xb61\xc8\xb6Q\x8a\xae\xa86\x16\xd3\xd6!\xda\x01\xf0l\x074\xdb\x1f\xcb6 \xc6X\x1c;0\x8am\xe8\x91r\xa5z\xe1\xd7\xd2\xed\xa8\xe0\xa7A\xaf\x03c\xd7z\xe4\xda\x17\xb7\xe6\x1e\x01U\xc7\xd5\xa8uX\xccZw\xf1\xb3\xe2\xd5:@M\x87U\x87E\xaa\xfdqj\x0d&\xed\x85H[\xd1g7\xec\x19\x8d<;\xe2\xce.\xa8\xb3\x16s\xd6\xf7\x06\x8b\xfd\xe1\xf0fG\xb4\xd9\x01kV\x0e-,\xce\xac\xdb\x14#0f\xa5\x9fB\x8b0\xfb\xe1\xcb&,9<\x92<~%\xa1Qd,\x86<<\"\x15Y\xe1@\x8a\"\x9b'\xdc\xf8\xe7\x9aD\xe8(\x91\xd2\xa9-\x85\xbc\xcb\xb3l\xe9\x94ng\xb9\x87V=\xdb\xd2\xfc|C\x05{\xa6\xff\xe8\xe7\xa4(i:\xef\xbf\xc0\x1f\x98\xae)\xbbuk\xf3\xb7\xc5\xcf@\xcaj\xe1\xb0\x91 \xce\x97\xa4\x80\x9c\x96yBU\xae\x9a\xd2\x1fI\xc8\xe9ER$Y:\x15\xc8\xd7\xc8\x1b\xbb=\xb3YL\x96h\xb3\x81\xefd!\xeb\xa2\xe5\xd2\xc9T\xd7\xc6\xba\xbb:IB\xf8\xeeV\xb3\xc2\xd6Zu\xe8\xaf\x92\x0b\x9a\xd6}\x19\xbcow\x05\xbce\x1d`\x16 \xe3\xf6\xbe\xe2\xf3\xa3h'a7\xe6y\xce=.L\xfd\x94\x02\xc2\x15\xbdP\xf0\xba\\'\x1b\n\xe7\x94\xee\x98\x9a\x92\xcc\xde\xf2\xe9T\xed}~\xed'[Z\xbb\xc4\xa1\xc8\xb6\xdc_^\xd0\xb4\xd8\x17@6\xab,O\xca\xf5\xb6\x80-\xb9\x82\xf9:\xcb\x98\x15\xa5J\xa4g\x8a\xb3\xd49\xca+\xb9%)\xcci\xce\xa1\x9ay\x96.*\xdf4\x9d\xac&\xb0&9w\xa7\x9d\x17w\xc4\xde\xfevK\xe6\xeb$U\x19|}\xaf\xa1\xf2\x14\xe1\xd3SP\x98\x93\x82\x16w:\xd2\x15\x02\xe9K\xb7\xc8\xf8\"\xd4\xf7\x9eY\x1cI\xba\xe7\x8eMU\x933\n\xdb,MJ\x81\xael\xae\x04w\xc2\xa3\x1f([%\x95I\xdb\x9b\xe4\x15U\xd6\xbd\xe5\xf2\xec\xfc\xdd-\xa5;HF\xb7!\xa1\x1b^\xd0\x82{}Z\x9b\x96O\xdc\x1d\xee$\x150;;\x9a\x85\xd6R\x9b\xef\x95d\x97y6\xf0\xfe\x18\xd5^L'\x8f\xe9\xe41\x9d\xbc\xa2\x98N\x1e\xd3\xc9\x1b\xf2\x01\xc1\xb5\xccb:\xf9\x90\x02\x01\xe2\xe3 q\x0fP<\x08,\x1e\x1c\x18\xb7B\xe3\x07\x00\xc7\x0f\x05\x8f\x1f\x00 w\x81\xc8}Ar\xa3\x0e\xb7\xc1\xe4\x01\x81r,T\xee\x08\x96\x07\x87\xcb\xed\x80\xf9h\xc8<\xa6\x93[{\xe6\x07\xa1+Y\xc5tr\x1f0\xdd\x06\xa7\x87\x01\xd4\x91(\xb1\x15Tw\x80\xd5\xadi\xbd\x8e\xd0zL'\x8f\xe9\xe4\x18\xd0\xdd*UW\xe0\x1d\x0f\xbd\xc7t\xf2\x1e\x05\x06\xe2c:y\x9b|ay%\xb3\x98N\xee\x00\xd2\x8f\x81\xe9\x95\xecb:\xb9\xf2\x05\x14\xb0\x1f\xd3\xc9\xc3\xc1\xfc1\x9d|t\x10@\x985\x87\x0e\x04\xc0\x87\x02\xe0\xd2\xc9\xebd\xc3\x16\x97\xce=\xb2\x138 \x1c\xfc\xea\x18\x81$}\xda\xf7\x817\x89\x93e\xbe\xb7$\xc4z\xa4MJ\xbc\xd5-s\xb2\x95\x1a\x7f,9h>\xec\xdd \xba\xea\xb8 \"p\xec\x9a\x9f)\xe7\xb2\xdbT\xf5\xc8\xd7\x9bw\xd9\x93\xed\xd7\x81q\x99B\x16\x9aH\x97\xde\xa4ia\x7f\xb0w\x08\x10\x9d\x02l\x0c\x88 \x84\x13\np\x01\x16\x82\xc2D\x85\x08B\xc5\x86\x08:\xe00\x9c\xa3E\x04a\xbc_\xe0\x159\xa2e%{\xea\x18?\"\xa8\xf4\x8a\"\xd1\xb3\xcb\xcc\xb1$\x82\x9c\"J\xb4\\:\x91&\xa8\xb8\x12A>\xd1%\x06\xf9\x91\x12\x1bc\"\xc8/\xd2D\xcbnE\xcbB\x11o\"\xa9\xa7B\xcdN\xe9\xd1\x1a\xa8\xb4\xc0\xff\x80\xdf\xb3\xd8\x8d\x04\x1e\xa1\x00Ffj\x7f\xb0\xc1=\x12:$\x00\xeca\x01\xe0\x11\x1a`\x1e\x80\xcc\x95\xc7\x84\x07@\xa8\x10\x01\xf0\x0c\x1302d\xc2E\x87\n\xc0\xf8p\x01p\x0e\x190\xb2j\xf2\xe9\xf1a\x03\x10:t\x00\x1c\xc3\x07\xc05\x84\xc0\xbc\xb2\xeb\xf0\x02l\x18\x01\x84\x0e%\x00\\8\x01\x84\x0c)\x80\xd1a\x05\xe0\x17Z\x00\xa1\xc2\x0b\xc0+\xc4\xc0\xbc\x1dHA\x17\xf60\x038L\xa8\x01\x1c0\xdc\x00\x0e\x13r\x00\x8ea\x07\xe0\x17z`S\xc1\xb8\xf0\x03\x08\x1b\x82\x00\x0ea\x08\xe0\x1e\x8a\x00\x1e\xe1\x08\x08\x95y\x1b\x11\x92\x00!\xc2\x12\xc0\x16\x9a\x00x\xf3\x0c\x11\xa2\x00\x8eV\x9cs\xa8\x82\x91\x1b\x0fc@\x84+\x80C/\x03\x86-\x80S\xe8\x02\x84\x0e_\x00\xcf\x10\x06\xf3\xba*\xeca\x0c\xe0\x1f\xca\xa0\xe5\xc7Z\xb4\x853@\xb0\x90\x06\xc0#\xf3\x80 m\x00\xb7\xf0\x06\xb0\xe1\x91\x9ea\x0e\x80\xe0k\x80<\x02\x85<\x80\x97p\xf1\xa1\x0f\x80\x18\xa5G\x08\x04\xf8\x86A\x80\xe5K\xc6\xc1\xc2!\x00\x1f\x12\x01\xc8\xb0\x08@\x87F\x00N\xea\xee!\x12\xe0\x14&\x01\xc6P \x08\x15.\x01\xae!\x1302l\x02\x10\xe2u\x08\x9f\x80C\x84P\x00\xa6\x8f\x86\x9d\x10.\x9c\x020!\x150\"\xacB\xcb\x90=h\n\xad\x80\xd0\xe1\x15`\x0d\xb1\x00\xdf0\x0b-7qG5_\xd7\x11\xe1\x16`D\x85\xc1\x18v\x01^\xa1\x17ZV\xc6\x90\x0c\xf0\x0d\xcb\xd0r3TU\x10\x14.<\x03P!\x1a\xe0\x11\xa6\x01n\xa1\x1a\xe0\x13\xae\x01\xce!\x1b`9m\x03~{\x1d\x1b\xbe\x01>!\x1c\xe0\x1a\xc6\x01\xe6\x81\xfb\x84sh\x99\xb5\x82%\xb0[\x06\x17\xd6a\xdc\x10\xe9\xca\x1c\xda\x01a\xc3;\xc0\x16\xe2\x01\xe60\x0f\xed;\xbe\xe1\x1f\x10p\xed:\x84\x81\x80S(\x08(kC\x08R\xe3\xe6\x8a\x871\x97\xf5n\x9c\xc3_\x92r]A\xab\xe2c\xe7<\x1a\xa9\x07\xd0K\xb5\xabb\xd7\xd2\xb82\xe9\x99O\xed\xe0a\xf5 \ne\xa9\x0b}\x89\x8b\xba:\xb9\"\xdeA4\xd0*`.\xc3/\x86\x8f\xfa\x17\x93\x90\x1f`\xd0\xe7\xf8\xa2\xca2h}C\xd5(\xfe[\xe7i\xa9?\x00Q\xa5\xbf\xd7\xdf\x82\x80\x1d)\n\xe1In\x7f\xe3]\xfc\xaea\xc6\xeb\xa8s6\xfa\x8fE(^\xe5\x15\xdfG\n\xc0^\x97B\xebl\xaa\x0b\xce\xeb\xbe@\xd0J\x02\xd3yF\xda\"j\xd7\xee\xd7<~Ix\x1d\xfa;\x90\x94\x85\xc4\x03\n\xd8\xa7b\xcf,\x84\xcb\xf32Q,5\xfb\x96\xec| ?\x91n\xf2\xfa\xc0IRX\xbd?=n\xea\x1cTj\xb2\x80\xcb5\xcdU\x8bH\x03G\xcd\xb3\\\xf0\xe0'\x82\xac&#\xcf3vpq/j[2Jq\xc87>d\xdb\xa6\xdfF\xfd\x9a\xd3\x1d\xe5\x1b\xfc\x05\xc9\xebI\xb2Y0\x1d\xb1\xf0\x95\xa9\xb3_\xbajS\xb7\x81D\x1d\x89n\x90\xd7\x88Z\x12\xbd\xc046C\xe2~R?\x1e+8\xf4~\x8d\x15\x1c0\xea@\x90k\xd8\x86\xf4uk\x19bC6\x82\x86k\xc4\n\x0e\xb1\x82CCA\xc30\\B0\x9c\xc2/b\x05\x87\xb1\xa1\x16\x1ea\x16AB,\xdc\xc3+b\x05\x871\xe1\x14.\xa1\x14\x1ea\x14\xb1\x82C\xac\xe0\x10+8`\xc3 \x82\x86@\xf8\x84?\xc4\n\x0e\xba\xc7\xaca\x0e\x0e!\x0e\x98\xfa\x04.\xa1\x0d\xb1\x82C\xac\xe0\x80 S\x88\x15\x1c8\x8d E\x88\x15\x1cT\x9c\xac\xe1\x06\xbe\xa1\x06\xda\xb3!Vp\x18R\xac\xe0\xe0\x11\"`\x0f\x0fp\x0d\x0dp\x08\x0bp\x0e p\x0b\x07\x88\x15\x1c\xdc \xffX\xc1\xa1\xa6X\xc1\xa1\"\xd7\n\x0e\x87(\xda\xa0\xfcXy\xf7\xbb\xf4\x9d\xae\xf4`\xb3\nh\x96_]o\x7f\xd4\xbd\x8d\xcfMjT\x9a;\xa4V=\xcf\x0d\x87\x99\x99\xf21#\xcdn\x9f\xd1?\xf4\x97\xf3;\xee \x85\x10E\xfftr\xec\xb9\x06\x9a\xcf\xa0\x13H\xf7[\x9a's\xf97\xbe\xe7\xe7$e\xe3\x11\xbe\x99\xeaC\xe8\x02a\xae\xdda\xfd/\xe5sn\x1bZ\x14\x8d\x08\x85\x03i\xcf\xd3\xa5\xcf\xa9\xa3<\xbb\xec\x0f,\\\xfb\x07\xf57\xc96\xc1J\x97?+1\\]P\x80p\x95\xb6WpY\x7fT\xbf\xc3m'\x1c#\xed?\x9d,aC\x97e\xe5\x83KJ\xa1\x94\xa5\xe9\xca\xbd\xbcb\x83\x88F\x98\x9cgW\xe2\x9b\x16d\xb7\xfb\x1d\xa5\xd8\x0emh\xde7\xc9\xb2\xf7M\x7f\xbeB3\xaehx\x05\x83$]$sR\xd2\xa6\x82\x85\x90 \x7f\xb0ZHmv\xd5\xf7\x12\xba\xe2$\xa2\x95\x1ap\xeb\xcd\x18\x87o[~`v\x80\xb4\xa2zz\xca\xe5\xe3I\xd1\x9b\xad\xde\x10\xb8-\x9f\xd3\xa2\x02\xda\xf9\xf6j\xf6#\xdbr\x93j7%\xab4\xcb{^t\xb9\x1b\xbbM\x08\xc9\x8c\x9d\xd8Y\x96mh\x1dW\x15\xb6\xbe\xce]Y\x8c\xe3\xee\xdfz\xb5O\xfe~W\x04j\xb5~\x10\x7f0\xd5\xe4\xf9\xdf\xba\x9af\xc77\x14\xb3\xe3cv|C>\x10\xb6\x96Y\xcc\x8e\x1fR 8{\x1c\xa0\xed\x01i\x07\x01\xb5\x83\xc3\xdaV`\xfb\x00\xd0\xf6\xa1\xc0\xed\x03\xc0\xdb.\x00\xb7/\xc4m\xd4\xe16\x90; \xcc\x8d\x05\xba\x1d\xa1\xee\xe0`\xb7\x1d\xee\x1e\x0dx\xc7\xecxk\xcf\xfc\x00p%\xab\x98\x1d\xef\x03\x85\xdb\xc0\xf00p8\x12\xe3\xb5B\xe2\x0e\xa0\xb85K\xd9\x11\x18\x8f\xd9\xf11;\x1e\x03\x99[\xa5\xea\n\x9b\xe3\x81\xf3\x98\x1d\xdf\xa3\xc00z\xcc\x8eo\x93/\xa8\xaed\x16\xb3\xe3\x1d \xf61 \xbb\x92]\xcc\x8eW\xbe\x80\x82\xe5cv|8\x90>f\xc7\x8f\x86\xf0\xc3\xac94\x8c\x8f\x07\xf2\xffH\xd9\xf1=\x10[\xdb\x97^\xb4A\x8dC\x0f^\x1b\xdd3k\x9ao\x0f\xc8v\xee\xf2\xe0\xb5\xc3wyCJZ\x94\x96\x0e\xf7\x93\xbb\xdb\xef@vA\xf3<\xe7\x97\xed\x16\xb0.\x8e*\xa6nd6j\xc9\x91\x12\xf6f\x87YQ\xf2\x04\xdf\xce\xdf\xba\xd0\xe5\xf5\xe7\xf4fiJ\xf9\x9d\xbe\xc9\xeb\x15[\xa2\xf9\xa5\x93\xd9k\xc8\xd2mUo8\xe6\xcf\x1f7,:\xa2iX\xf3\x19\x1f~\x85A\xe6\xea\xd6\xfc\x8a\xb6p\xba \xb9\xfd\x96\xaa\x87\xbe\xe6\x9c\xdc\xaa\xabS>\xf8\xa0\xf0\xa9\xc6\xb9\xd7\x19h\xb1I\xe6\xdc\xef\xc4\x01\"\x97\xe9\xe8\x9bZ\xff\x001I\xb5\xe7J3\x8a\x18\x93$\x9b\n\xdb\xdd\x18\x93\x14c\x92~\xef\x98$\xcdG:\xfa\x07\xca\x88\xb0\xa4\xc1)\x18C\x91\x04\xc5P\xa4\x18\x8a\xd4P\x0cE\x8a\xa1H\x0d\xc5P\xa42\x86\"\xa9)\x86\"I\x8a\xa1H1\x14)\x86\"!\xad\xa4\x18\x8aTS\x0cEjS\x0cE\x8a\xa1H\n\x8a\xa1H\xcagb(R\x0cE\xd2P\x0cE\x8a\xa1H1\x14)\x86\"\xb5(DXH\x0cE\xe2\x14C\x91b(\x92*\x14I\x05\xd4\xd7`S\x8b\xcb\xc8\xd0\x1a]\x18\x899\x8a\xa4A\xbd\xf4\x11#\xaa\x00\x11\x19\x95p\xf2\xe2\xb85\x1a~\x8d#0_\x93$U\xc7\x81\xfc\x11#@\xbe\x12\xc0*Y\x8c\xf0\xd3\xf4\xc3\xbdd(I\xb3L\xd5\xc7b\xbd\xdc\x83\xb5-\xb6\xc7\xb0\x04OR\xb4\xfa\xa5qV \xe7\xa6F>\xe6Y\x11\xa4\x9d\x1bA\x96\x19\x12d\x9b'A\x8d`MO\xa1\xe4W=(\xe0p\x01\x19JQ\xa8#\x1e\xfb\xb4\xa4\xa4\xdc\xe7\xe6\xfeb\xa4'\xc8\"CA\xae\xc32\xf8\x05\x05m\x92\x82\x83Jr,\xb5\x07}C\x9b\"N\xb5\xcb\xcf\xc2\x0c!5\x8coP\xd0/\xd5Tp\xe8\xa7\xb2\x8d\xab\xe9a6Z\x85\xdfpO\xad2\x92DRJWY\x99\x88\xef\xa6\x08\xc5zA\xf3\xa4\x10_31\xbcWv\x83\xc3\xd6$]\x14kr\xae\xf4x\x02J\xe2U\xdb|T\x95!]}{\xa8L6\x89\x18\x08,\xd8\x01\xb9MR\n4\x9dg\xcc\x8a\xd1;\xdc\x05\xf2\xc3\x1d\xa4\x05\x07\x02\xb5O\xce\xd7$M\xe9\x86\xfb\x0b\x99\xc1M\xcb\xa2jU|\x1b\xaa\xa3%\x94\\4\xdf\xd0\x10\xd4UE\x02\xa6\xa8b^\xab+JK\x924]heh_\xde4\xddo\xf5\xbb\xe4[\xf8p\xf6\xfc\xec\xd5\xf4\xe3\xdb\x93\xb7'g'\xcf\x7f>\xf9\xcfW/\xa7\x1f\xdf~8}u|\xf2\xfa\xe4\xd5K\xeb\x9b\xec=\xebCg\xef\xff\xe3\xdd\xe9\xab\xb7\xd6\xe7\x0c\x0f\xc9\xc8\x17\xaf\x0e\xf3\xcf\xec\xd0|G\xf2\xf2\n7'\xad\x17\x84\x1d\xe1wT\xa0t9F\x93[\x0f@\xc0-\x07p\xd2)\xd0\x8f\x08\xa9\x8e\xcdL\x82\xec})\x19y\x0d\x0dP\x1e\xc6gR*\x80\x90p'J\xf6w\x17Pg\xdf\xaa\x04e\x1e\xadr\xa9i\xe0\x19I\"\x18\x12#\xa8]N\x97\xc9g\x93\x84z\xbb`\xbbMJ\x1e2SG\xd92\x06\x8d\x92\xea\xcf\xbf\xc1\xeb\x87\xd9 \x80\xdc\x0d \xbe\xf77\xb5\x8f\x07\xf0\xb3\x0e8\x1c\x11Pg\x17\xa37\\f\xa7BdIQ\xcb\x90\x94\xebJ\x90\xe2\x08c\xa2<\xa7W\x06\xd7\x13\x0e\x8c\x8b\x18bS@\xc8\x04\xde\xa5\x1cN\xe6w\xc5l\xb9,h\xc9\xae_\xdd\xeeB\xcb\x95]\xd0N\xc5M\x9fz\xb0\x03'\x81\xd21\xa0\x10\xa2\xe8\x9fN\x8e\xbdKy5\x18.\xcat\xbf\xa5y2\x97\x7f\xe3\xbbM\xc6xs\xaf\xc8\x9a\xa6R\xf0\xfb\xb4vD\xf5\xcc\xcf\x13\xcemC\x8b\xa2\x11\xa1p\xdd\xec9\xa4yN\x1d\xe5\xd9e\x7f`\xe1j\xea\x0f\xb7\xc4\xbbI\xb6 V\xba\xfcY\x89\xa4\xeabw\x84\x93\xb2\xbd\x82+\xdcu\xbf\xe9\x81\x97\xc2%\xd1\xfe\xd3\xc9\x126tYV\xde\xaf\xa4\x14\xeaP\x1a\x8d\xdc\xbf*6\x88h\x84\xc9yv%\xa2\x01\xc8n\xf7;J\xb1\x1d\x81\xd4\xbco\x92e\xeb\x0d&Q\xbeB3\x9e\x02\x07\xec\x1fI\xbaH\xe6\"O\xa2\x8a\x08\x11\x12\xe4\x0fV\x0b\xa9\xcd.I\xe7\x9b\xfd\xa2g\x12\x12\xd1J\x0du\xf5f\x8c\x03\xa7-\x0f\xec\x92\xe7#\xd4\xc1w=\xe5\xf2\xf1\xa4\xe8\xcdVo\x08\xdc\x8a\xceiQA\xdc|{5\xfb\x91m\xb9I\xb5\x9b\x92U\xca\xcbO\xb7\x99\xc9\xdd\xd8mBHf\xec\xc4\x06\xa9E\xdd\x84\x03\xdc\xfd['&\xdcT\x88\xba\x15\xb8Yg\x15\xa6\xbd\x84\xc2v\x0e\x86&\x91\xf0\x1b9\xce\xaf>\x8fP\x1b\xb4\xd5\x1a\xaf\xea\xd3\xf42\x9a\xcd\x90\xb5\xa4\xed\x17X\xc1|K\x82\x83\xd5\x8d\x1d(\xbb\xcf\x9c\xdbWZr\xd3\x8c9iF\xe1\x08\xb2\xc5;\x00:\xa3\xcf*\xaf\xea1\xdfl>L.\x9fMZ\x82\x10y|n\x83\xb1D\xe5\x07\xcc\xe0\xb3\xca \x03N\x80k\xee^\x93\xa1\xa7\xe5W:d\xee\x95Ny{\xb8\x11\x05\xce\xdc\xc3\xe6\xed9e\xed\xa9\xc6gH\xda\x0b\x93\xb2g]\xc9\xa6t=\xdfd=D\xaa\x1e.Q\xcf\x9a\xa67\"I\xcf\x9e\xa2w\x90\x04=\xabR\xb6\xabdDj\x9eu\xda\x01\xbd\xb5 hR\x9eGJ\x9eM\xa2\xe8t\xbc\x03\x0beL\"\x9eG\x1a\x1e6 \xcf\x96\xb2v\xb0\x04<\xebJ\x07\xd4j\x07\x87\xd4;\xd4\x0c\x03.\x02\x01w\xbc\x87L\xb9sO\xb8\x83\x99):\xc75\xdd\xce=\xd9\xce\x9ejg\x9d\x11D\x96\x01nKv\xb2\xefD\xc0\xdd\xbe(y\x02\x15\xccx\x1c\x95\xc8\x8f\xeb|\xf0iNt\xcaJz\x84\x96\xf5\xd1\xfe-3n\x96Up\x99N\x8eo\xdf\x9d\xbd\xeae\x02n\xb2U2\xaf/\xc3u\xc8\x8d@\xca\x8al\xab\x9bB\xa1e\x15!8vy4\xb7\xc4W\xe9\xa2\x95\x1e\xc8\x07\xcd\xee}bW2%UU\xad\x91\x8aDi\x80\x96\x19\x90\x94\x07(\xa9\x86]\xd0\x1d\xc9\xb9Y\x92\xf6}7\x82\x84L\xd8\xebT\xcc \x17\xc4\x8c\xc2}\x90\xa9V\x9d\x0es\x7f\x11-J2\xdb$\x852\xd2\xaa\x93\xe88\xa3\xe5%\xa5)\x94\x97\x99\x18\xcb@d\xff\x00_\x02\xcai\x99'T\x15\xe07\xe2\n\x1c\xd3\x9a\xac\xdd\x8diM1\xad\xe9\x8f\x91\xd6\x14\"\xab\xc9\x90\xd4\x04/hQ\x7fZ\xb0k\xeb\xde\xe1\x01\xb5\xc2\xd9\xccN\x19\xa1\xb5\xd4\x01\x18\xf2\xa3\x84y6\x88\x034\xaa\xbd\x98T\x15\x93\xaabRUE1\xa9*&U5\x14\x93\xaa\xca\x98T\xa5\xa6\x98T%)&U\xc5\xa4\xaa\x98T\x85\xb4\x92bRUM1\xa9\xaaM1\xa9*&U)(&U)\x9f\x89IU1\xa9JC1\xa9*&U\xc5\xa4\xaa\x98T\xd5\xa2\x10 .1\xa9\x8aSL\xaa\xfagH\xaa\xeaD}\xb58\xf5\x02\x9aj\xa4\xaa\x8a9V\xc6\xd0\x1e\xe8\x1bD\xde\xe9\x03w\xab\x18?\x0e\x8c\x1ar Z)c\x0d\x8aw\xcc\xdf\xfd\xc0\x03\\d\x86A\x0bh\x17\x91/\x8a\x80\xfb\x9a\xd50\xa8L\x93\x83\xd0j\xa9z\xf0\xabMG\xa8\xa7}1m\xcbV\x1b\x8ea\x13\x96\x8c\xfd\x1d\xbe\xef\x1f\x8f16%\xa1\xdbuc\xb0\xb8Y\x06`\x1b\x07X\xc7\x02\x08`\x0f1$@:\x87\x04y\xc1{\x06~\x03\x0f\x8f\xe1\xc2\x13\x16\xe2\xb3\x82|\xa1a><\xd0\x17\x08\xea\xf3\x03\xfb\x0c\xec\x92\xd4\x01\xee\x1b\x0d\xf8\x85\x86\xfc\x1cA\xbf\xc0\xb0\x9f\x1b\xf0\xe7\x08\xfd\x99\xd6p\x0d\nb\xc1\xbf\xc0\xf0\x1f\n\x00\x0c\x08\x01\x8e\x05\x01\xbd`\xc0@@\xa0\x0f\x14h`\xc6AB;\x18x\x108\xf0p\x80\xe0A A7P08,\x88\x05\x06\x83B\x83xp\xd0\x19\x1et\x07\x08\xad\xaa\xf06\x02\"\x0c\x00\x12Z`B\xa4A\x85\x80\n]\xac.g\xb8\xd0t\x08\xce\xb2\x0b\x8a\x00\x0c\xb1\xfd\x0b\x08\x1a\xba\xc0\x86\x81\x81C?\xe8\xd0\xb4\x82\n;x\xe8\x0d\x1fj\xb8\xb1\xd6l\x00b(\x08\x11\x8d\x83!`D' \xd1\xe2\xf7\xf7\x02\x13m<\xb5N\xc5@\x90\xa2\xbb0\xf1\xb0\xa2ml\x1e\xd0\xa2'\xb8hr\xce\x06\x03\x18\xd1\x10#\x0ed\xc4\xc2\x8c\x08)\xbbC\x8d.`\xa3 n\x0c\x048:B\x8e\xe3@G\x9b@\x1d\x80\xc7\x03@\x8f\xd6\xdeiWz8\x00\x12\x01A\xfa\x83\x90\x1av\xec1\x13\x0c\x19\x18\x88\xb4A\x91\x9e`\xa4\x86\x97\xb8\x19\x9a.\xc7\x08@\xd2\x84\x9a\x98@\xc9\xf0\xb0dp`R\x0fM\x86\x04'1\xf0\xa4;@\xe9\x04Qz\x80\x94\xae0\xa5\x11\xa84\xc3Fx\xe0\x08\x0bVz\xc0\x95\x8e\x80\xa5a\xb8>\xa0\xa5\x86U\x0b\x10\xc4m \x1cpiX\xf2\xe9\xca\x0c]\x06\x05/-\xf0\xe5a\x00\xccPk\xd1\x01\xc4t\x811\x87\x9f1\x14\xa4\xc0\x98\x06\xcf\xd9\xef\xb7\xado\xc1\xb6\x10\xbf\xd6\xc7`\xdb\x10\x96\xb8\xad\xaa|<-\xe5(\xdeP\x89\xdb\xf6%\xd8\x98b\x1dS\xackr\xebnL\xb1\x8e)\xd6\xbf[\x8a\xb5\xee\xcb\xcc\xbd\xe4\xea\x96\x82\x0d\x91g\xdd\xd6\xd7\xefO\x8f\xabkI\xfdRLq\xee\xfd\x1aS\x9c1ZO\x90W\x0cDLq\xc6D>\xa8\x9c\x05\xceq\x0f>Q\x0f1\xc59`\xac\x83K\xa4\x83S\x9cCLq\x1e\x1b\xdd\xe0\x11\xdb\x10$\xb2\xc1=\xae!\xa68\x8f\x89gp\x89f\x08\x1c\xcbP\xa2\"\x19\x02\xc61`\xa3\x18\x14\x0e\x8a\x98\xe2\xdc%D\xdc\x02\xd6Jr\x8eY\x88)\xce\xa8H\x05\x9f8\x85\x98\xe2\xac{\xcc\x1a\x9b\xe0\x10\x99\x80I\xe0u\x89J\x88)\xce1\xc5\x19\x13{\x10S\x9c9\x8d\x896\x88)\xce*N\xd6\xf8\x02\xdf\xe8\x02\xed\xd9\x10S\x9c\x87\x14S\x9c=\xa2\x08\xec1\x04\xae\x11\x04\x0e\xf1\x03\xce\xd1\x03n\xb1\x031\xc5\xd9-Z \xa68\xd7t\x88\x08\x81\x10k\xce!:\x00\x1f\x1bp\x88\x14\xe7?Hn\xb3\x84BE\xfa\xe9] \xf4\xde\xfd[\x0f-\xff\xfb]\x81\x12\xb6~\x10\x7f0}^M\x9d\x12-\x9bTdE\xf7> \x10&1\xba\xd3^\xf5\xecW\x9b\x1b\xdd\x9b\x10\x1dd\xe6\x15\x00Q\x1a\x91/\xab\xd3\x07\xe35 \x8ey\xe1\x10/\x1f\xbc\xcb\x8cky\xa1Z\xbc \x0dC+\xa6\x15\x00\xd1\xf2\xc4\xb3\xf4ar(4k\x14\x96\xe5\x85d\x01\xd1\x86\xe6\x968\x1c\xcb\x07\xc52\xf9\x96Q\x18V`\x04\x0b\x85_\x05D\xaf\xac\xd8U \xe4j\x0cn\xe5\x8cZ\x05\xc0\xac\x02#V\x16\xbc*8Zu\x18\xac*8R\x85\xc7\xa9\xfcP*\x83\xd0m\x18U0\x84\n\x87O)\x0cd\xbd~\x0d\x8cM\xd9\x90\xa9\x91\xb8\x94\x01\x95\xb2\x9a'VD\ng\xbf\x84E\xa3lX\x94\xbdO~8\x94\xd4\xec\n\x866\x14* \x065\x02\x81R\xe3\xc6&\xfc),\xfad\xc6\x9eB O(\xe8\xc4\x82:\xa11'\xbd{\xd8\x1do\xd2\xf3R\xbab\x82 M.\xc2\xc2\xa2Lv\x99\xa0\x11&\x0f|I\xed\xb6\n\x84-\xa1\x90%;\xae\x84A\x95\x8cRtE\x94\xb0x\x92\x0eM\n\x80%9 I\xfe8\x92\x01\xad\xc1bH\x81\x11$C\x8f\x94+\xd5\x0b;\x928\x91\x82\x9f\x069\n\x8c\x1b\xe9Q#_\xcc\x88{\x04T\x1dW#Fa\xf1\"\xdd\xc5\xcf\x8a\x15\xe9\x9c\xd9:\x9c(,J\xe4\x8f\x11i\xf0 /4\xc8\x8a\xfc\xb8\xe1>h\xd4\xc7\x11\xf3qA|\xb4x\x8f\xbe7X\xbf;\x0e\xebqDz\x1cp\x1e\xe5\xd0\xc2b<\xbaM1\x02\xdfQ\xfa)\xb4\xe8\x8e\x1f\xb6c\xc2q\xc2\xa38\xe3W\x12\x1a\xc1\xc1\xe27\xc3#R\xe6t\xda\xe1\x04M\xe9PC\xf5O\xe3=\xb4\x9bLz\xf2R\xddd\xb7[=&1{3fo\xd6\xe4\xd6\xdd\x98\xbd\x19\xb37\xbf\xfa\xec\xcd\x0e\x1a\x1b$\x81\xb3\x8b'\xc7\x1cNA1\x873\xe6p6\x14s8c\x0egC>\xe8\xb7\x96Y\xcc\xe1\x1cR $|\x1c\x16\xee\x81\x86\x07\xc1\xc3\x83#\xe2VL\xfc\x00\xa8\xf8\xa1p\xf1\x03 \xe3.\xd8\xb8/:n\xd4\xe16|< B\x8e\xc5\xc8\x1dQ\xf2\xe08\xb9\x1d)\x1f\x8d\x95\xc7\x1cNk\xcf\xfc\xb0s%\xab\x98\xc3\xe9\x83\xa2\xdbp\xf40H:\x12\x1e\xb6\xa2\xe9\x0ex\xba5\x97\xce\x11S\x8f9\x9c1\x87\x13\x83\xb6[\xa5\xea\x8a\xb8\xe31\xf7\x98\xc3\xd9\xa3\xc0\x08|\xcc\xe1l\x93/\x1e\xafd\x16s8\x1d\xd0\xf91\xf8\xbc\x92]\xcc\xe1T\xbe\x80B\xf4c\x0eg8|?\xe6p\x8eF\xff\xc3\xac9t\x04\x00>\x06\xe0\x8f\x93\xc3\xd9\xf4\xa6\x87h\x87lB\x8b\x1c\x0f\xda\x1e\xa0\xb5\x87j[\x97\xbb\xcaSWI\xcb]x\xb7\xccIZ,i^'\xb0.h\x9am\xa7eN\xe6\x12\x0fR%\x9b\xbedO\x9d\xf1\x87\xea\xa4R\xb2\xd9\x00\x7f;I\xc5\x1e\x16L\x94\x19\xa3\xad\xf7\xbf\x91\xe3\xfeJ\x93D\x87\x02iS\xf9;\x00rl\xc5\x8c\xf0Da\x9c9P5SWU/E\xf8N\xc2-\x94]\x96\x97w\xab`\x9e\xd6\xbe-\xb8\x97M\xcb\x8f\xbb\x1cs2g\xe7\xb1\x19\xb8\x10\xe8_e\n-\xf7\xe9*\x99m(\x94\xd99M\xd56\xc9\x8c\x14t\xca'*\x94\\\x18\xc7\xeej\xae\xba\x93\xd3\x0d\xb9\xa2\x0bD\xb70rn\xf6A\xd7\x04\x1b6\xcf\xa4wr\xfc\xe1\xfe\xbd\xbae%C\xde\x9b\xa2\xbe (\x9f\xa9\xe4+\xe7\"I\x85\x0ea\xad\xb09\xb7$\xce\xb4\xf7\x03\xe4\xb4\xdc\xe7\xe9p\xef\x17b\xf3\xb7y\xf7\xd9\xee\xc8\xaazx8g\x9d\x06\x9b\x07;\xab\xb1\xf5\xe7\xeaR\xa1R\x02\x82\x8c\x1b\xce\xbc\xddR\xfa\xb9\x9c\x9e\xd3\xab\x91AEZ\xb7\xaf.\x94C\x92l_Fm\xb0\x7fV\xf8\x07)\n\x01\xf2\x9c\x92\x15}O?\xediQN\xc4\xef\x1afLU\x8b\xf0\"\xc6\x96\x89\x90\xc26+J\xa0\x1cU\xe0P\x84J_e%\xf1Md\xc7GUiU\x11o\x9e\x8f\x9f\xffC\x9c\xe0l?J<\xab\x05\x9e\xe8B\x01\xda\"\x9ag\xfb\xb4\x9crf:%tI\n(hy\x07\x92\xb2\x900]\x01\xfbT,\xc0\x85@..\x93\xa2;\xa7\xe6\x1d\xdf\x0b\xce)\xfc\xe3q\xda\xa7\xef\xfb\xd3\xe3\xfe \xc4u\xbe\xd9\x051$g \xa0\x7f\xf6\x90\x9c\x03\xa0Y\xa6\xbb@\xa3\xab\x99~\xd2\xad\xc3\x9e\x0e\xac\x94\x1e\xa9\xf6\x9f8j8\xc0\\\xed\xe6j\x85\xd6\x1a\x92\xab\xc5U\x0f?\xe5*\xaf29\x0cZo\x02\xefR\x1e^\xca\xed\x8el\xb9,h Y\x0e\xdd\xeeB+\xac\xa5\xa0e{s0S\xfeSefKjl\xf9%\xd9\x14\x0e\xc6|\xe7\xb4P\x08Q\xf4O'\xc7\x9e\xe6\xa9\x06\xc3E\x99\xee\xb74O\xe6\xf2o\xfc\xe6=')\x1b\x8f@H\xd74\x95\x82\xdf\xa7\xb5^\xed\xb9\xa2O8\xb7\x0d-\x8aF\x84\x02\xc6\xdd\xf3\x10\xc7s\xea(\xcf.\xfb\x03\x0bWsKk\x89w\x93l\x13\xact\xf9\xb3R\x85\xeb\x0e(q`\xb7Wp\xa5\xf0\xfb\xf9Y;\x01O\xb6\xfft\xb2\x84\x0d]\x96\x15\x12\x9e\x94\xc25\"\x1d\xc8<\xd6Bl\x10\xd1\x08\x93\xf3\xecJD\x07\x93\xdd\xeew\x94b\xfb\x98m\xde7\xc9\xb2\xf5\x06\x93(_\xa1\x19\xbf\x073#\x00\x92t\xc1\xee\xad\xb4\x89\x10\x17\x12\xe4\x0fV\x0b\xa9\xcd.I\xe7\x9b\xfd\xa2g\x04\x13\xd1J\x1d\xf6\xd6\x9b1\xae\xb1[\x06\x05;\x86;\x96f\x87\xd9\xc7\x93\xa27[\xbd!p\x8f:;K\xc5\xd9\xca\xb7W\xb3\x1f\xd9\x96\x9bT\xbb)Y\xa5Y\xde\xbb=\xc9\xdd\xd8mBHf\xec\xc4\xce\xb2lC\xeb\xefb\x99\x8b]\xe1=\x06w\xff\xb6&\xc5\xdaT\xa6\xaau\xe3\xa9\x1d\x07\n\xb7\x81\xea\xe6\xa0\xf1 |#\x07\xfc\xf5;\x10t\xd6\x83\xd7\xcdD\xef\x06\xb0\x1e\xe0\x98\xabih\x07\x00\xf2\xfa\xefz\xf9\xb7]\xfd\xddd1\xfa\xdao\x97l\xe0+\xbf\xfd\xc2\xeft\xddG\\a\x9a\x01\x84\xb8\xc1\xc4\x0bL\xbc\xc0\xa8\x7f\xff\x9a.0\xecT\xd3\xad>\xf6\x1b\xdcJRX\xd3\xcf\x15\xdf\xdb\x0d\x8e\x8b9\xd8`<\x140\xc2\xe3\xcf\xc7m\xf0\xf5\x9f\xf2\xdf;n\xfeFTr\xa0\xc9l\xfe\xad\xe4\x0c\xdbl\xb1\xdfP\xe5\xb1}\xf2\xe2\xf8\xaczL\xf0\xfdF\x8e\xf5+=\xbd\xdb\xd2iS\xcfE\xc9E\xd4uO\xf6E\xd4\x95JC#L\x80\x82\xa6\x8b)M\x99\xa5\xaa\xc8\x9e\x05\x8d\xb1\xd7%\xfb\x89\x05\xbd\x96@\xfc/\x0fU\\$\x85\xf87[\x16\xf3<+\x8ao\x85\x95\xc0\xcf%\xdd\xfe\xacV@\x01\xcb<\xdb\xf2\xf8h\x9d9\xc0\x99\xa9\xce\xfd\x9c\xceirA\xafg\xf4\xbd\xc6\x02\n\x80\xc3\xcdN\xc3G\x9c\xd0bg\xa1N\xe7\xea<\xae\xf68;\x8b\xbb\xfc\xe2Q\x1c\x8f\xe2\xeb?\x8a\xd5\xa7YA\xe7\xfb<)\xaf^6\xa9C\xec\xa1s)\x96j\xb7\x93\"\x99\x7f\xb3\xe8>s\xbc\xa6\xf3\xf3\xb3\xcf\xef\xb9\xbf\xa0\xfdtKlCAu\xd7\x8aj\x8d,HI\xfaOt\x06\xbb\"\xc5\x94]\x8a\xccl\xd8S\x97$-m\xcf1\xdb\xc1\xd8\xdc&[\x19\x7f\xef\nV\xb5\xdc\x06\xcbL\xb3\xbct\xcbJ\x01\x95i\xd7\x80r\xe5\x0c\x9e\xa62\xe0L\xfc\xce'\x05\xee\xb5'\x80\xff\xff\x96\x04\xd8\xff\xeb\xcb\x1f\x1e\xdd\xbbwo(n8\xba\xd7\xfc\x9d\x8b\x97\xff\x7f\xa5\xb8\xbe\x85\x9b7\xfb\xff\xf1\x92n\x92\x0b\x9a\xc7\xa5\xf5\x8f\xb3\xb4\x1e\xb5'\xe0w\\Z/\xf2\x8c,\xe6\xa4(\xcf>\x1fg\xdbmR\xba.1\xa6\xf3\xa6\xe5\xe7\xfe\xa4\xf4\xe4\xad\x96\xf6\xf0\x98\xd4\x1d\x91\xddu\n\xfaI\x19\xaeW\x13[\xd5\xba5=\xdf]\xbf\xa0\xefFg\x1d\x1b\x9e\xebN\x10h\xd64\xe8Nf\xcd\xda\x06\xcb\x89\xac\x894\xd0\xaes0\x1d\xc0\xca\xb7zk\x1e\x06*\x15Tk\x1f\x86\xeb\x1ft{\x00\x0c\xfb\x00T{\x01\x94\xe2\xee\xec\x89\xde\x1f\x16B\xed\xc6\xd5\x1dW7ru?\xeaO\xeaW\xbc\xba\xd7\xa4X\xf7\xd7\xb5f\x9c\xf0\xea\xd5\xa3\xd7\x0f\x1e\xde{x\xef\xc1\xc3\xe3G\xf7\x1f>\xbaw\xf4\xf8\xfe\x93\x17\x8f\x1e\xbf\xba\xf7\xf2\xe5\xf1\x83\xef_?\x7f\xf9\xf8\xd1\xd1\xeb{\x12\xa9\xebWH\xea/\xb8\x9f~9%Iu\xa3B\x9c1\x9d Ut\xb47y\xbd'\xde\x14\xabvK\xf5\xdf\x9f/\x169-\n\xe5o}\x87=\x9d\xaf\x1f\xdc\x07\x9a\xb2Y\xe6Q\xe2\xec\xcdo:\"\x9ag\xc56+\x8e\x16tw\xfe\xe8\xe1|O~[\x9d\x7f\xa1\xe4\xf1\x97\xdd\xea\xfc\xd3\x83\xc7e\xfa\xdb\xe5\xe2\xcb\xc5C\xb2\x9c?X\xdc\xff\xee\x1b\x80_\xc8&Y\x902\xcb\x0f\xd2\x8f\x0b\xb2aR\xf8\xee\xf9\xf7\xdf\x1d\xbf\xba\xf7\xf8\xe1\xc3W\xf7\x8f\xbe;~\xf1\xfa\xc1\x8b\x87O\x1e?zl\xdc?\xbd\xa0\xf2\xba\xd1\x07\x8f\xbf\xaf\xfe\xe8yPm\x0b\xa5:w\xd2\xd2\x03\xbd\xba\xa4\xca\xc3\xcf\xc9\xf1\xb2\"\n\xf5n\xd0\xe3\xfd\xe5\xd5}\xe5z=\x1ec\x03\x85\x95\xfb\xa7K\xba\xe1\nri\xa3\xdai\x92\xb6t\x8b3\x04\x8ad\x95\x92r\x9f\x8f\x9fj\x0d'\xb0\x0d\xa4\x1e\x82\xd2\xad\xfa\xe6\xd5\xc7\xe3\x93\x7f\x7fy\xef\xfe\xb2xy\x9a\x93\xef\xdf\x94\xb3\xf7\xc5\xd5\x8b\xa3\xcb\xeff\x9f\xce\xde\xfdX|z\xf9\xfd\x87\xa3\x93\xcb\xe4\xd5\xeeO\xc9\xc7\xd9\xe3_>,\xca\xcdn\xf5\x1f\xcfzM\xee\xf63u\x14\xafq-\x99W\x12\x7fU9\x7f\xd6 \xaeeS\xd2tA\xf3m\x92\x96wO\xf7\xb3\x9f\xe8\xd5\x07:\xdf\xdd\x7f\xf4\xf8\xfcH\xf1\xde\x98/6\xd4->\xbf\xf8r\xef\xe1/\xeb\xf2\xa7?\xaf\xbf\x7f~|\xfc\xcb\x97\xcd\xc9\xf7\xe4,+~\xb8\xba\x97\x9c\xbf\xfe??\x9d\xfc\xf2\xe3\xbf?\xf8\xed\xa77yV\xfc\xd8\xdf\xc4s\x11\xde\xa2\xab\n\x89[\x0e7\xef\xdd\xec\xaf0\xfaiOS}x\x04\x9ec\xde\xba\"\x83\x9b\xaa\xc5Z\xcef\xd3]\xd1\xd5\xa6\x9b\xf7\x99\xa9\xd8\x19\xbd\xe9\xd6`f\xf5\xf8\xc1\xa3\x87mN\xffx\x06\xfd\xa9\x08\xbb\xa2\x0bn\x14\x9c}\xee\xd8aF\xbb\x80\x87_M\xe7*\x83FwR\xcb\xed\xe6\xf5\xd2\x8e\xac\xe8`S8\xbc\xda\x8b\xaf\xc7\xbd\xc9\x03\x0f\xb1/=\x907\x94\xf2s\xd1\x7f'\xac\x93\xaek\x93\xb5Y(\x97Ch\xfb\xac\xea\x84\xb2\x0e\xacRD\xbdn4\x16[\xf5\xce\xe7@;e`\xc9 2\xd9?\x06\x0b\xc8\xb2\xc5\x06\x16^\xfb\x1do\xbbIi\xf3 \xb2\x1e?\x18\x83H'\x050K\x02\xec#\x13d\x1b\x9f \xa3u(\xc8:ZI\x08KQ\x90Y<\x82\xdc[\xed\xd9\x8e\x82\x86\x16\xa4 #{\x83\x0dh\x15\xbeM\xecF\xde`\xeb\x99 \xb3\xad)\xe8\x9a-NAZ\xbbS\x10b\xdd\xda\xc4\x07\x92\x8daM $\x08\xdeV\xa9 #\n\x0c\x1e}\x18a\xa7\n\xb2Y\xab\x82\x10\xdd2X\xae\x82\xf4\xf6\xab\xa01m\xf4-ZA\x9e\x87\xd0\xc0\xc6\x15d\xec\x9f\xce\xdeE\xbcj\xb6}\x05\xa9-`Ax\xe6}k\xb8z\x7f`\x13W\x7f\x1fw\xe8\x1a\xb6\xab}\xb3\x1a\x94\x81u\xc0`\xdfg=\x0e\x1f\xca\xc5Ye\xc1\x0c\xfa>\xeck\xc7Fq0\x0e;\x1d\xee\xd8\x1eJ\x81\xa9\x854\xb0.4\xc2P\x1d\x95\xba \x0dy\xd5\xd1\xda\x05\xd8U\xaa\xb6\x01\xf4'?\x96o\xeb\x94\xef\x9e\xed\n\x06\x8a\xb3\xd6a\x8a\x8c>%\xd3uup*_\xe3Y\xac<\x81\xb5k@\xbf\x02\xd4g\xacq\x92\xdc\xcfS\xcd\xee\xc6\xb5\xe2yb\x9a\xceI\xfb\xd4v\xcf+\xf5I\x88\xe5\xf2b\x93\xcd\xcfO^\xa2\xf5\x95\x8b\xff\xdf\x01\x86\xe0\x8d\x91\xbc\x1c\xdc\x94Q\x9bD\x91,/\xdeV\\<\xeb\xde\xb5\x01\xc4\xe1\x0d\xda.?\x87\xd1q!\xffH\xc9\x82\xe2a>\x1e\x86\xda\xf9B\x8fY\xd8\x02\xe9Z\xefg\xdf\xcapI7\xdcDn\x8b2\xd9\xea\xd1\xc3\xde;7\xef\xdf;\xfa\xee\xdb\xa3\xfb\xdf>\xb8wv\xef\xd1\xd3G\x0f\x9e\xde{2\xb9\xff\xfdw\x7f\xbaw\xf4\xb41<\xd2\xfdv\xaa\xf0\x81\xe8:\"\xe7\x85\xd7\x0f\x9b1\xc9)\xa4\x80Z\x16\x07\x9e\xd5\xba\xf1\xee\xba\x05O]\xa7.\xf8\xa0]\xc7\xa0[\xcb\xa0\xf1\x08aU\x9a\xa3\x04\x84\xe3\xcfa~\x1f^\x83QU\xce\xdfK5s\xbd\xee\xaa\x9b\x8f\xdaj\x8e\xecv\xae\xef\xdf\x93G1\xfa\x10^\xb7\xcel\xe5+\xea\xd7@y~\x03\xaa\x93\xc3s\x1c4\xdeu\xbb\x89\xd36u\xbb\xe7:\xa0\xfa\x82;\xdfAu\xc6\x03\xaa\x83\xed \xd5\x9c\xf7\xe0w\x9c^\xe3 (Ia\x07\x80\xa9\xf3`u^X\x8b@i\xec\x020\xd9\x06\xa0\x95\x0e\xd8$\x04#\xa5\xa4\xb0\x15\x00\xb5N\x1e<\xea/\x14\xa5\xdd\x00\xa8U\xed\xd1q\x85\x0dq\xb0\xb6\xb4\x87\xfc\xc1Z4\xdb\x16\x07kVgg\x1c\xac\xc1\xa1\xcdq\xb0\xa6\x0c\xf6\xc7\xc1\xda\xd4\xd8\"\x07kOo\x97\x18\x9bt\xb1O`\xac\x8d\x02*;\x05\xfc\x8e\x14\x85\xcd\x026\x8d\xa9\xb6]@e\xbf\x00\x9a\xd7\xd8\xc0\x82\x0e\x7f\xb9j\xc6sj\xe9e/\x8b)\x9e\xfd\x9dW\xff\xc1\xce~\xf1\xbd\xb2m\xa2v\x95\x1c\x16G\xa8\xcf6\xb5\xaa\x12d\x1c}\xc3!I\x17t\x10\xa0b}\xbfmT+\x109\xfdG\x94\xc7p\xcd\xb3}:\x0e\xe4S0e\xf7\x88\xa2$[\x85\xf6r`\x8c\xbeX\xb4\xf8j\xdb\xd3\xee\x84\xba\xbd~\x06\xb9N\xd9\x082\xeeZ\xdb\xbe5m0\xab\x80`\xe4&kH\xa3\x90\x04Y\x06\x08\x88A\x82YEU\x0f\xd8\x14\x95 \xa3\xba\x12d\x92)\xe0\xe4\nAd\x8b\x88\xca\xb1/\x7fM\xc4\xccw\xfb\xb3\xe3\xef\x1e\xfe\xfb\xe6<\xfd\xf4\x1f\x7fyu\xb9\xfa\xee\x97\xf4\xf1\x9b\xef\xdfm\xbf{\xbd\xff\xcf{\xaf\xde=\x9c\xfdv\xb1\xff\xedq~\xf9\xe3\xd1\xf6\xec\xe3\x9f\xf3\xf7\xfb7o\xfe\xf3\xe2\xf9\xf3OgO~\xf9\xed\xed\xea\xf4\xde\xfb\xe7w\xcf^\xee\x1e\xef\xef>\xb9\xff\xfcS\xfe\x9f\xcb\xff\xf3\xe7\x0f\xbb\x17\xff\xfe\xec\x99t{\xb8ez\x88\x1d\xb2\xa5\xc3\x94h\xd4i\xdew\x9dh_\xd7\xb3\x00\xad\x1b\x05l\xc2\xb6\xb8S\xc0\xa0s\x8d\x8bV\xe9Z\x01P\xb9W\x00\xddG7m\xa8t\xb5\x00\xba\xe3\xfd=fp\xbb\x80MU\x98\x95\xc4\xefdhH2h@\xab\xfe\xb3k?\x8b\xeeCi>\xab\xde3k=\xab\x14!\x80$5.\x1b\xb0\x8dQ\xed\xba\x01\xab\xfb\x06l\x03\x1b; \x8d+\x07\x0e\xdd\xae\xd1\xbf\x02\x87n\xdd\xee\xe2\x81Cw\xc1\xe4\xee\x81C7\xaev\xfd\xc0\xa1\x9b\xb5\xb8\x81\xe0\xd0\xed\x1b\\Bp\xe8\xb6\xcd\xee!\xb05\xef\xea&\x82\xe1\xa9\xef\xee*\x02\x9d\xbb\x08l\xa7\x86\xf9\xc4\xd0\xb8\x8e\xc0&\x04\x00\x93\x0b tn$p\xe2\xdbf\x1b}0\x9dW\xff\x81|0\xbd%\x18-\xf9h\xc9\xb7(Z\xf2\xea\x1f\x11\x1b\x1dl\x9b\x1d\xa2%\x7f\x10}\x1f-\xf9\xdf\xa9\x0b\xd1\x92\xbf\xfe\xf6\xa3%\x1f-y+\xdf6[M\x94\x8d\x13\xd06hs\x08\x16C \xceJ\xf0\x18\xfc,\xcdh\x03u)\xda@\x92t 4\x18V1\x1c\xb0,\x12\n\x98\x06\x8ct\x10\x005`\xf8\xb4/3\x9a\xd4[=X\x0d\x81Z\xd0\x02\xd7\x10\xa8\x01#\x88\x0d\xae\x8d8]\xfa\x04q\xfe\xc6\xb6\x8d\xbb\xadn{\x08l\x83\x05\xdc\x06\xfb\xaa\x05\xc4\xca\x05\xeb\x86F \x11\x02l\xea\x86\x8c\xa07\xe0\x06\x0e\xc8\xc1\x83]mV\x0f\xd9\xa7S\x92U\x85\n\xb2\xc9\x1d\xf0\xb2\x87`\xf2\xbf\xae\x92\x12\x07\x04\xc9_\xd2\x0d]\xf1\xcf\xa6T\xff\xca\xf2\xf7\xf4\x92\xe4\xd5>\x1a,\x9e\xe121\xe8s\xe5\xf0]L\xe3\x9eI\xec\\\xd3\x12xe\x83f8\xa09\xf3\xc6V#R&m\x1b&\xbf\x1e\xd70Y[\x9d\xa8\x8d\xe1U%h\xd7\xf3x\xc6v\xaa\x98\xcc\x02=\x9by\xfby8\x90\xb8\xac&\x80a\xb8.\xcbGP\x88E$\xa8\xbf\x94\x04\xe9\x8d(\x8d 5\xc2\"\x1f\xf3\x05:\xc3\xa2\x13d\xaa\x0e\x84\xe7\xde\xaa\x13\xa0,8\x16v)}M;\xef\x05)\xe8{\xfa \xbd\xd7\x969\xbe\x86n\xe5\x13X=!\xeb\xfc\xf1\xe7\xf5\xba|\x94o?]\xd0\xf4\xf1\xfd\xef\xd3\xf3\xcd\xe7\xcd\xfe\xcb\xd5\xc5\xf7_\x9e\xfc\xf6\xe9\xb7\xf9v^\xbf\xde\xd9,\x1fh\xba\xa0\xb9\xdc$\x90\xe5\xf0\x13\xbd\xe2\x9f\x03L\xc9\x96\x7f\xd7uES\x9a\x93\x92\x02\x11\x9f\x0e\"\xfc\x0b\xe2\x157k\xd1\x87Voo|\xa0i \x17 \x81c\xdeo\xf8%\xbb\"+\x9a\xc3\xff\xf7\xf1\xde\xbd{G\xaf\x1f\x7f\x7f\xefF\xf5\x96k\xce\xb7`\xf8\xed\x8f\xfbY\xf5\x9b\xae\xae\x80\x99Mc%\x0fk X\xde<\x92ovJ\x89X^\xea\xd6\xa5Y\x91bJ\x16\xbf\xed\x8brK\x1d\xaa!\x1fM\xeeK\x0eKJ\x0f\xac\xa4\xbf\xa6\x9d\x05\xdc\xd8\xda\xee7\xa4\x1c\xccS\xff\xb3[\xf5\xbb\xdd\x0f\xd2\xea\xbfg\xf5\xaa(\x93-[\xf5+R\xf0\xefUuV?\xdc\x9a\x934\xcd\xca\xfa\xdb\xd5I\n\xf3,\xfdm\x9f\x8a\x9f/\x93\xce\xc7\xf4\xe4\x16\x9af\xe9\xe6\xea\xf67\x00gT\xd6\xe4\xa8\xeb}\xa3\x15\xc4\xd7iP\x0d*\x9d\x98WmG\xd6u\xb3\xf3,-v\xfb\xd9\xd1\x97\xf9o\x8b=\xdd}\xbaw\xb1\xbf\xffeu\xbe:\x7f\xf8\x84.\xc9\xbd\xf4\xd3\xe5\x97tA\xd2O\x8f\xb6\x0f\xe7\xdf\xed\xc8\x83\xfdC\xb2\xfb\xf2pu?\x7f\xb2*v\x9fV\x8fWO\xe6\xc5\x83\xf3'\xf3\xfd\xb2\xe2~\x91\x95I\xba\x9a\xee\xb2K\x07%p\xd4\xda\x93\xb5\xc7w\x97'Y\x9e\x94\xe8\x01\xd6\\\xce\xe8\xe7\xf2\x94s\x91\xa7\x1eb\x8ew\xd5\x0b\n\x15\xd8\xfd>C\x99\x94\x1b\xb3\x92j/\x04\xd3su\x93\xfc7\xd4\x93EI\xca\xbdy!.\x93\x94\xb1$\x9b\xcd\xd5tD}\xdc\x9bW\xb4\xb8\xd9U\x15ZE\xd1\xd2\xe6\x93{5\xb5\xbd\x0fdV\x94$Q\xe6Ay\xf1\xbb\x99f\xe1:\x97fS\xa6=\xa6\x17\xb4\xc4\x15\xdb\xb61-\xf6\xb3mRN\xad\xe5L\x04,\xba\xa0\xbb\xac\x18\xe6-\xfdc\x9f\"\x95\x9a(J\x92[\x04uZ\xe9\x83\x10;Y\xb1\xa9\x0cZ\xeae{b\x10\x0d\xab\xbf\xa9\xf0\x8f=\x8fXaW\x8b<\xb3\x9d #\x0eQ\xdb,M\xce\x91\x95\xf1\x92\x05M\xcb\x8e\x8djx\xf8\x92\xce\x8a\xa4\xc4UB\x91\x1f?\x9d\xce\xb3\xb4$s%0=xI\xf9\xa1Y\xc5\xb3\xb3,]L\xd5%\xda\xf4:\xe0f\xfb\xe5$-s2-?\x8b\xaa\xfb\xc3\xfd\xdd\xff\xa4Y\xcdG\xa2\x0b\xfb\x94\xf1a&\x80o?\x1a\x0eV;\xabsIx\xf2\xdd\xbdo\xef\x1d}{\xef\xe8\xec\xde\xbd\xa7\xfc\xff\xfeS\xb2\xe4\xf8l\xe1]X('\xc8\xc9U\x8e\x87\xd1\x96|\x9e\x86\xe12_\x93tE\x030\xdb\xef\x16\xec\x1a\xedU\xc2G'\xeb\x06\xec@\xab\xeaF\x03`t\xb5\x1b\x16\x82\xd0)3\xb2!\n\xdf\x14jY(L6\xbb\xec\xfa\xe6\x9a\xbe\x0c\xaeq\x06\x84\xa1\xf6Qn\x95F\xf0N\x9f};\xa4\xf0iZ\xe6\xc9\xa1}h\xfc\xdb\xd0d3\x1dLc\x9b\x9bB\x90\xae\xcf\xcfs\xca\xa5;Pj\x96\xf7\xb6I\xaa\xd8a\x83\x17\xeay|\xd5\x16\x1ab\x02\xb5\xe3\xc7/\xf5\xce3\xdaq*\x9e\x1d\x8eM7\xaa\xafL-\\\xb3\xd0\xbaG\xa6Nj\xcdS\xef\xe9\xe2\xfa\xe4U\xe4s\xc77\x16E\x89z\xc3o\xff\xff\xbf9]>\x85\x9b\xff\xcf\xdd\xd6\x87\xdf\xef\xb6%r\xb3'!\xb6c\xf0\xf9\xe7NS5\xcf\x98\xb2\xe5\x8f\x9bg\x0c\x0e\xb0\xa8\xc4\xd9\xc5\xa4\xad}\xac\xbe\x17\xbdL\x8a\xf2\xa4\xfe\xb2,B\x0c_\xf9\xfd\xa8\xa0\x9b\xe5\x94\x9b\xa3\xd7\x82\x96\x7fm\xae\x97\x0b\xfe\xd1+\x9d\xc5\xfa\x8f;\xf6\xd3\xfdl\x93\xcc\x7f\xa2\xf8\xed\xcc\x1f1\xad]\xf3wk?$\xab4IWN[G86\x11\xc7#\x0f\x99\x9cf\xcbeA\xcd\x0f\x8a\xeb\xf6t\x9f\x96\xc9\x00\xcb\xef\x1d\xb8EA\x17\"\x1b\xab\xd0]\xd0\xea7NIN\xb6\xc7\xfc\xb6\x80\x1f\xdc~V\xec\x08\x1e\xaae\x8b\xa0\xf9\xc1\xc1\x93\xf1\x86|\xae\xb5W\xd14\xee\xc0\xe1\xe6M\xd3\x14\xd7\xa3\xfc\xb0\xdf\xed6\x0e\x0b\xea\x9f+\xa0B\xe8\xe8 \xd9\x97\xeb\xc9\xc5\xd1\x8c\x96\xe4h\xc2\xd7\x0d\xde\x02ew\xd2-\xddf\xecb\x9a\x93yIs\xdbi\xb2\xcc\xf2-)\x9f\xc2>I\xcb\xc72\xee\xaf\xfc<-\x92\xd5T\xf91<\xf4\xfb_\xe8t\x9e\x15\xe5tG\xf3\xe9\xecj\x88dc\x18\xb1^\\\xd0\x9f\xcbX\x9b5)a\x9f&\x9f\xf6tsU9\xf3\x96I%,\xd6\x0edK\xf6\xef\x1e\xab\x82\xe6 \xd9$_\xe8\xe2\x9b\xde/\xbb<+\xb3y\xb6\x81\xd9~\xb9\xa49liQ\x90\x15\x9d\xc0\xd9:)\xaa>\xc3v_\x94\xc0\xfdzI\n\xa4\x84\x0d%E\xd9\xe7\x94\xa5\x14n\xdc\xbd\x01\xf5~a<(\xcfU\x81\x82\xae\xb64-\xab\xce\xb1q\xdd,`G\xd8D\xee\x8b\xb2\xc7(\xa7\xbb\x9c\x164\x1d\xb4\xc0^]\xee7\x9b+\xf8\xb4'\x1b6\xee\x85\x90J\xc5\x96\x8f\xff\x16) I\xfb\xaf\xfe\xca\x1a\xbb\xbb\xca\xb2\xd5\x86N\xf8\x98g\xfb\xe5\xe4\xe5>\xe7V\xf3\xaf\xb7E_9\xb3b\x9d\xed7\x0b\x98Q`\x83\xed\xf1\x99\x934K\x939\xd9\xf0\xc5\xdco\xe5\x16\x9d\xac&w\x98x\xd8\xed\x10nLn@R@\x9a\x95lQ\xd1]I\x17\xb7'\xdf\xf4_:Ia\xc7\x04\x96\xcc\xe9\x1d()\xdb\x01\xfbbO\xd80E\x06\xc6.\xd9\xb0\xbe\x94\x19\x1f\xe4,II~\x05d\xb3\xe1\xe3\xed\xc7,\xf2\x05R\xae\xe9U\xbf\x19\xfayG\xe7%$%\x94\x19\xec\x0b>:\xc6\x8fM+\xfd\xcc\xa7\xe6yz5\x81\x1f\xb3KzA\xf3;|\xbf}|\xffs\x01\x97\xebd\xbe\xeeqc\x0c\xd82\xeb\xaf\xb3\xf9\x9an)\xfc\xba.\xcb\xdd\xafw\xc4\xff\x16\xbf\xde\x81,\x874\xab~\xbd\xc3W\xca\x9c\xa4\x15<\xc2GZ\xd0\x12\xf6\xbb\x81\xb8\xd9\x08\x07m\xd0\xfc\x82\xe6b\xa0[\xb2+\xc4\xb4\xf3\x9e\x96\x99\\\xbf\xd0\xbaf\x01\x8f\xce\xd9l\xb2\xcb\xe2\xe9@\xfa\xff\n'\xcb\xa6ol\xbavyv\x91,\xe8\xa2\xee>\xfb#)\x8a\xfd\x96.&\xc3\xd7\x9f\xa7\xf0\xe3\xd9\xd9)\xfc\xf0\xea\x0c\xb2T.o\xb1e\xae\x12\xbaY\x00\x81\xff\xea/\xbc\xb3\xab\x1d\xfd\xeb\x7f\xfd\xb5\xc7\xac:\xf3\xd9\xccT\xb3,4&\x97\xdf.\xcf\x16\xfb9\x05\x92\x02\xcd\xf3,\x9f\x0c{\xb2\xdbm\x929\xa9\xc6\x9cS\xb6F\xb2K\xba`b\x99\x939\xdb\x8bYv\xbe\xdfU\x9fl+`F\n\xba\xa8:=\xe8\xca\xc7\xf7?\xf3v\xd7\xe4\x82O\xf5\xb6\xb5\x1a\x17b9\x12\xd9M\xf6\xef\x8b,Y\x00I\x87\xe9@\xa2Q\xbe\xc1r\xba\xccrzG\xbe\xc6\xb8\x912\x99%\x9b\xa4\xbc\x82\x94\xd2\x05\x9f\xc2\x19\x05\xae\x00\xf2\x0b\xba\x18p\xcbR\x10\x9eb\xfe(\xdf\x01\x13\xb8\xf5\xb1\xa02\x81\x91\x8d\x97-\x08\xb6\x97\xc5\x8a )Y\x0d\xc77\xcb)\xb7\xf1$\xbb\xc9\xed\xfe\xdc\xbe\xcdJ\xfa\x14J\xa6\x07\x97U\xd0\x16\xe1=\xad\xf6\xf4|\x9f\xe74-7W@.H\xb2!\xb3\x8d\xdcT}\xcd\xb8\\&\xf3\x84l\x94\xbaw\xb6_BN\x99F\xa5w\x80\xa4\x0b\xb6C\xab\x06x\xd4\x18?\xf6\xea\x15>\xa3\xab$e\xb6\xbd\x08\x1fSl\x97\x89Xkd\x97\x14\x93y\xb6\x1d\xea\x9b\x0f|\xa5\x17\x90\x95k\xb1\x8d\xd2\xfe~\x85[\xd5QK\xb7\xbb\xf2\xaa\xda\x1a\xb7a\xcb\xae\x060\x1blH\xdeM\xd6\x1dH\x98\x11\xc6\x14=_\x84P\xec\xe8O\xaf~\x95\x07f\xc1\xb6,\xc9gI\x99\xb3Eo\xe8\x83\xd4]d\x93u\xc6\xcfeK\xdabg\x1a\x86+@\xd1\x87\xd9\xd0\x00h\xb7#\xcf\xf4\xceR8\x95\x8bo\x93\xccx\xc7*\xbdW@\xb1\xdf\xed\xb2\x9c\x9f\x13;2?\xbf\xbbO\xd9\xff\xb0\xd3A\xccY1\\\xe5\xfd\xc30[\xc2\xbe\x14\xdbZn\x1d\x1e7L\x16\x8bD\xec\xa3:\xde\x91u\xaf\\g\x8bBv\x9c\xb5#\x04\xdd\xe6\xf8JX\xf8p\xc4\xcc\xc4\xf99\xdf)U\xc7H-\xb8$\x85\xe3?\xfdi\xa0\xa4_g\x19,\xb3\x0c\x9e\xc1d2\xf9\x9f\xbd\x1fYs$\xbd\xea\xff\x99\xa4W\x13\xd6\xd0\xeb<\xdb\xdeZf\xd9\xed\xfe\x03\x93I_\x03'K\xb8\xc5^\xfb\xc8\xbbu\x96\xdd\xfa\x17\xf6\xdem\xf8\xdb@\xf7\x0c\xdf\xfd\xbbj\xac\xf7-c\xfd3\xb9 ^\x83\x85g\xfc\xacg\x1c\x1d\xc7\x96\x14\xb7^g\xd9d\xbe!E\xa1\x1c\x9ah\x9a=*z\xdcz\xbc\xdfJg\xcc\xf5\xa0\x1fX\x06}zU\xae\xb3t0l\xd1\xee\xeb,\xbb5\x99Ln\x0f'S\x0c\xf9\x96\xe2\x17>\xcd\\\x0c\x18)\xb0\x17N\x84\x10^\xbe\xfap\xfc\xfe\xe4\xf4\xec\xdd\xfb\xdb\xfd\xab\xaa`,\x16\x82\x8a\xb5`\xae\x1a\xfeC\xcb\xf0\x7f\xc8\xfa#\xe7C\x7f\xfa\x0c\xfee7\x9b\xbc\xce\xb2\xbfM&\x93\xbf\xf7\x1f!\xe9\xd5\x1df6\xb0\xe7v\xe2\xd0|C\xf2bM6L(\xaa\x0e\x0e\x07\xdfog\xd0H\xb2\xec5\xf11\xdd6\x8d\xf0.\xf0\xc5\xc6\x9f\xfa\x1f\xcf M6\x8a\x05\xa4j\xb9\xb3R\xce\xf8\xb5p~^\xeb\x0di\xb0\xc1\xec\xaa9R\xa5V\xbbL6\x1b\xf6\xc3\x82.\xc9~\xc3\xcf\xd46\xb3\x9b\x8a#\xf3.\xbbcL\xf8\x0f\xcc\x88\xb8\xc9\xec\xc7Z\xbb2\xcd\xcb\xe6\x86\xfdA\xccO\x9b]\xad\xca\xd2\xcd\x95\xb4\x91\x07W\x96\xda<\x01\xb2,\xa98i\xf9-\xe9\xe6\xdd\x9bmf\x95\x81.\x9b\x15\x16y\xe5\xe9\x80\x1b\xcb,\x9b\xccH\xce;\xfc\xf9\xee\xd5\xe4\xcb\x0d1Vas\xf6\x0dg\xde\xdc\x0d\xf6\x14S\xab\xad\x1f\xfe\xfc\xe1\xdd\xdb\xf6\x7f?{\xf6\xecY_\xda\xec\x99\xe6V&\xce\xf6\x8cm\x85\xea\xa0\x13V\xeb\xbe\xa8N\xa1\x9c\xae\xf6\x1b\x92\xb7\xb9\x0c_f\x0f.hsH\xdd\x01\xba\x9d\xd1\xc5\xa29\xae\xeeT\xe7^\xe7.\xd7:@\x96|\xa0\xbf\xfe\x1b\x1b\xea\xaf\xe2\x92\xd2\x1c\xb9m\xc1M\xe4\xe6z:0\xc0\xc8\xfc\x9c\xed\xab\xc6<_&\x1b\xda\xd7Sr\xf7\x9d\xd2\xbc\xc8R\xc5\x92\xadn\xc9\xcb$/\xca)\x97\xf438\xeas\xa9\x1f\xe3\xc5\x1b\xaa\xa7\xee\x9bu\"\x80\xa2\xb5\x1b|\xc47\x9e\xc2\x0d\xd5\xda\xed\x0ee\"\xfa|\xe3\xce\x90\x0b\xef\xed[\xb2e\x9c\xfe\x97\xe8\xda\xffV<\xc6z\xdb{\xca\xd4\xe5\x93ee8v\xe7R\xccER\xc0%\xddl\xbe=O\xb3\xcb\x94\xef\xa25)\x80\xc0|_\x94\xd9v\xb0\x14\xbb\x8b\xe6\x8e0xz+Il\xefV\x83l\x81\xa4+ by\xb4\xd9\xfd\xca\x97\xa9\\)\xebl\xb3\x10\xcb\xa4\xd5:\xbf\xf1W+\x0c\xaa\xfbv\xb5\xc0\xda\x9c8\xebzU\xc1-\xb6/\xe5@\x07W=\xe9c\xf8\xeb\x7f\xfd\xf5\xf6`\x01\xfa\xcfn\x97\xb9j\x82\xf9p\x19\xa3\xa3\xc9\xfd\xa3\xfb\xc5\x8d\xc1\xb4\x81\xd6\x86U\xf9\xcf\xd8\xec\x89\xdd]\xfd7\x9fR\xe9\x94\xe3o\xdc\xad^\x81\xf7\xa7\xc7\x15'\xa1\x101~\xba\xc2\xd7Qw`\x10\xadT\xba\xf4\x8c\xdeh\xf3\xa5$\xa8c\xcf\xe4\xda\x0b\xe9\xdc\x0b\xe8\xde38\xf8F\xb9\xf8\xc29\xf9ln>OG_hW\x9f\xc1\xd9\x17\xda\xdd\xa7u\xf8\x8dv\xf9\x0d\xf8\x11\xa5\xd3/\xb4\xdbo\xb4\xe3/\xb8\xebo\x94\xf3/\xbc\xfb/\xa0\x030\xb4\x0b0\xa0\x13\x10\xe3\x06\x0c\xe8\x08\xd4\xbb\x02\xc79\x03\x07\xccT\xceA\xa4{p\xac\x83p\xc0n\xe80\xf4v\x19j\xbe?o8\x8a\xb5\x8eC\xfb)\xed\xe9<\x1c*.\xe9L\xec\xb9\x0f\xcd=\x08\xecBT9\x11\x83\xb8\x11\x03;\x12\x87\xae\xc4\xd1\xce\xc4\x0e\xafr\xe0X\x1c\xe7Z\xb4\xf8\xdb\xb4\xeeE\x84\x83Q\xe9 qp2\xaa\xdf\xff\xbbz\xec^\xaeF\xec\xe0m\xeeF\xf3H\xad.G'\xa7\xe3\xf0\x8a=\xd2\xf1hq=\x9a\x9c\x8ff\xf7\xa3V*X\x17\xa4\xdd 9tC\x8erD\xa2\\\x91>\xceH\xb5(\xac\x0e\xc9`.IM\xfb\xbd\x95\x14\xd41\x19\xdc5\x19\xd89\x19\xd6=ipP\x0e]\x94C'e(7e@GehW%\xd6Y\x89pW\xa2\x1d\x968\x97\xa5\xc2i\xa9rl\xe1][f\xc7%\xdau\x89r^\x0e:\x1f\xd2\x81\x19\xdc\x85\x19\xd2\x89\x19\xd2\x8d9n\xbe\xad\xaeL\xbb3S\xba3\x19\x89r'\xb5w\x90_\x85\xf9\x94~N\x8a\x92\x0b\xb6\xfa\xa5zcGVI\xdaJJ\x81\xbee\xde<\xd0\x0bM\xac\xff\\\xa9B\xe9\x1am\x8e\n\xa5\xafQ\xedi\xe4\xa5\xea;q\xc2\xe0\x15\x11Q\x0d\xff\xbf\xfb\x17\x1a\xc9_\xfaq\xd9?\xab\x9b6)\n\xe1&8%+\xfa\x9e~\xda\xd3\xa2\x9c\x88\xdf{L>\xed)\xbb\xed\xaf)g\xc7D@a\x9b\x15%P~\xaf\xe5\x97\xe0\xd6+\x8a\x92\x9f\xd6\x01u\"M\xabw\xc4\x90\x06w4\xce\x9e\x8f\x87\xffC\xd4\xf1b:[z8Z\xd7\xf1e\xef\xdd\xf6PE\x190\xce\xa4\xbf\xb2/I\x01\x05-\xef@R\x16\xd2AS\xc0>\x15\x0ba!\xee\xc8\x97IU.\xca\xeeM/<\xdc\xe9\x85\x9b?]D\xd1:{\xd3w\xad\xf0\xe8\xc1Xv\xc6\xc8\xdc\xea\x94lbr\x059,~c\xb05x-\x1bu\xe0\xf5\x08^\xfa l?\xa6\xd6\x80\xec0l\x15\xc1\xd9\xae\x8c;KA\xb1\xc60k\xb9\x8a\xed~\x7fz<\\\xc33R\xd0 W-\xad`\xfdz{\xa2W\xb0=\xc9B\xa94;\xa3\xeb\xa8\xcdJ[\x92j\xe3\xe7\xb4\xdc\xe7\xa9(\xe4&\xfaW\xa9\xfbZ\xb5r}\xbaJ\xd2\x16\x0f>,v\xea\x98\x95\xe6\x04\xde1\xab(\xb3\xa6\xca:\xe4A\xdd^\x880\x87v%\xf5:\xc0adh\xc3\xf8\xa0\x86\xceQ32\x84\xa1\x12\xa3\xe4\xe6\x1b\xb0\xa0E\xeb\x15A\n\xc6\xf0\x84.\x1a\x8a\x0bI\xe8\xbe\xf3\xf7\xfeX\x9c\x03\x10l\x831\x05\x1d\xa8\xfbo\x0c4@\x86\x184h\xd2\x88\xb0\x02m@\x81:\x94@\x17D0\x18%&p\xc0\x142\xd0\x0e\x16\xf0\x0c\x13\xb0\x04\x08\xb8\x85\x06\xf4@yS8@\x80@\x80^k\xf5L\x07\x83\xfd\x03\x02\xfe\xc1\xa0\xfeP \xbf\x12\xdeo\xe3\xa5mH\x7f<\x98\x1f\x04\xc6\x0f\x07\xe0\xdb\xa1{#h\x8f\x80\xebm@}\x07\xe5\xeer\xc7\xc2\xb4zX\x1e\x01\xc8[\xa0\xf8\xba{\xa1\xe0\xf7\x80\xc0{\x18\xc8=\x0c\xd8\xee7sF\x80\xdd\x04\xads7I\xbe\x9bOV\xa4\xa4\x97\xe4j\x92\xef\xd32\xd9\xd2\xc9+v\x03B{Kh\xf34\xa8m\xd4y\xb6\xb0\x94!l\xac\xd8$-\x1f\xc8/yV\x124\xf2\x1e\xd4\x98.c\x96P\x87\xc2\xb8\x8b\x04\xf9;\x8d\x06\xacb\x96\x90\x9f\x8bI!\xad\x98%\xe4\xee\x90\x124\xc2-%\x19\x04sN \xf2tQ\xd5\xbd \xe6\xa8\x12\x14\xc4]%(\x9c\xd3JP\x10\xd7\x95\xa0\x98%4xl\x9c\xe3k\xc0.f \xc5,\xa1\x98%4\xf8!f \xb5(f \xc5,\xa1\x98%\xd4e\x17\xd0i((\x98\xebPP(\x07\xa2\xa0\x98%\x14\xb3\x84\xac\xee\xc8\x8a\x8f\xdd)Y=\x18\xb3\x84\xfe\xa9\xb2\x84\xea\xd8\xc6\xf4\xbc\x8ej|I\xd3l\xfb1u\xf8tj\xaf\xda\xbd\xf2r\xd1\xb1\xdc\xf9\x0b\xcd\xac\x8a \xa9vN\xdbw\xb5J.hZ=\xbdO\x93\x92{\x91`O\xcal{[\x9e.\xf4\xf3.K\x15\xdf\x7f7\xb8LQ!\xcf\x92o\xbb\x9b\xfc\xbb\xd8\xacsG\xf7\x9a\xdf\xf9\n\xcdR*\xa9\xa0\xe9bJS2S|q\xfb\xf7<\x88\x07]j?\xdfO\x9a3\x9fq\x1fh\xbax%\xd8 \xac\x91mz\xa8\x8f'\xd2\x91A\xf5aq\xb8u\xb9\xa6\x1c1!\xc3A@Rt\x15?c\xc0\xden\xb6\xacp\x03MM\xd2m\x0f\xa2\xd3}\xdc\xe7\x95\xd8\xa4\x0f?\xaf\xd4Y\n\"\xa1}\xb3y!>\xf7\xe8\x9ek^}'\xf2\xab\xb2\xd0\x9c\xbe9f:\xab\x8e\xc5*\x10B&\x95Z\xa8\xac\x84\xce1D\xd2\x05Glx\xc3=\x07\xeb\xdbwg\xaf\x9er\x7f\x95\xf8\xb9r\x0e%\x1c\xe39I\xcb\xeaj_\xe3b\x9d\xfb\xbdp\xe1uWR\xb2JI\xb9\xcfi\xc1\xd3\xb2\x92\\\xf8\x1bW\xd9*\xe3w\xeb\xe6\xec\xeb\x0cMN\x94\xd4q\xf5\x7fgK\x11p\xc0c\x05\x92\xb4V\xdc\xb1\x98\x06.\x01\x11\xdc\x92\x10y_b1\x8d\xba\x98\xc6P\xf7\x00\xa2\x06A\xeb\xb5\x8a\xdb\xfb\xd3c\xd9IEU\x82\xbe\xca\xab^\xf6Uw}m\x87Z\xc9\n%\xa6\x99u\xf4\x07\xd7\xf5\xca+\x80\xea\n\xab\xb8pj\xcb\xb0RzS\x86Y%\xd5+\xa6\xa2+\xc3\xa5\xc1-oiy9/\x90m\xc7\x1b\xa2|I\xfdb\x7f\xf4\xf6\xc9\xd7xH@s\x06\x83\xeeN\xa89\x8b\xc1p\x1e\x83\xeeL\x06\x93*\x93\xef\x99}\x0d0\xc2\x83\xa2d\xa6\xf0\xba6\xa4\xf3\xa4\x00\x98\xbd)`\xf1\xa8\x00r\xa4\xa1<+\xe0\xe7]Q\xf21zq\x1br\xf6\xb2\xc0HO\x8b\x92a\xed\xed\xd5x[\xc0\xdb\xe3\x02z\xaf\x0b\x18\xf6\x98 \x8d\xf7\x05\xec\xfb#\x98\x17\x06,\xd6-\x84\xf0\xc6\x80\xb3G\x06 \xb0W\x06\x06\x9e\x190I\xd9\xbc+\xc7xiz\xacZ\xab\xee^gi\x0d\xbc5\x80\xee\xef`\nGzn\xc0\xe2\xbd\x81\x81\x07\x07L}\x0d\xe1\xc9\x01\x857\xc7\xd8\xa8yBG{vz\xfcx$\xfd\xbc\x8f\xfd\xdb=<`\x9cJwO\x0f\xa8\xbc=F\x03Ji\xd8\x18\xcd\xa8\xf6\xdbw;\xaf;\x9a\xdb\xfc\xddb\xb4Qup/\x83\xc6\xfc2.>\x8d f: \x8c\xaey\xa5!f6\xc5\x0c\xc6\x98\xf5\xb8\xb1\xed\x9f\xe6\xa9\x80&\x99\xc5(3\x9bev\xc3\xccn\x9aaG\x1d\xd2<\x0bg\xa0\xa1M4O#\xcd\xc7L\xb3u\x14e\xa8\x8d1\xd5\x8c\xc6\x9a\xcd\\3\x1al\x88=\x14\xd4h\xb3\x9d\xf9\x10\xcap\xf31\xdd\x0e`\xbc\xa9\xcc7\xa3\xccm{7\xa0\x11g0\xe34\x86\x1c\xbe\xe7\x8a\x89\x0d`\xce\xd9\x0d:\x95Ig\xecu(\xb3Nm\xd8\xe1\x05\xa6\x98j\x7f\xf3n\xc0\xaa\x05\xe4\xa9\x0c<\x9c\x89g\x9eb?3Oi\xe8\x0d\x9a\xea\x08GZLMn\x06\xeb\xadX\x0b\x90\xa4\xe2xd{\x9eo\xcb\xca\xfd\x9f\xd3UR\x944\xef\x96}aMFP \x82\x02\xd7\x08\n\xa8\xaf\x0b\x8eW\x95\xc2\xf3\xae\x12\xa8\xe8\xb6\xc3jVC\xc0`0Z~\x7f?\xae\x06|o\xde\x1b\x02\xf0\x80P\xe7!\x81x\xa8o-}0\x1eT\x80\xbcx\xdc\x04\xca\x83vp\xe3\xc1y\xe3~\xe8\xd5\xe8ns\x1en\x86\xbaL\xf5\xe7\xbb\xac\x8d\xf6\xf2\xe4=0.\xfe\x0f\xfb\xddns\xf5n\xe9\xbc\xfc\xfb\x90\x95\xc3\xf2W,@\xcd\xd2\x8b\xb8\x98bq\xf4\xa7\x0c\x03\x8c\xc9w\xdc\x90\xb13\xa6\xf4\xc5\xab\xce\xeb\xa3\xe0\xaf\xf5\xd7Gh\xffM\x8c\x12\x91\x84[V\xd0\x18\x0cb\x82\xe4\xe2\xa9\xfe\xab2\xedy\\\xc87\xa0\xb0.t\xeb\x02\xb3\x08[\xafU\xdc\x06\x07\xb5f5\xb6N \xf4\x02\xec-\x0e\xc5<\xbb\x06a\xd5\xcb`\xe4\xa1\xd5\x1cR\x82]\xe7dj\x97\xef\x96\xc3g\x0b.\xe0\xb8\xd5\xaa\xbb\xf5\x88z\xd4#\x97}\xb8\x05\x8fY\xeam1\x964]\xd0|\x9b\xa4e-\xd1\x1fh\xf9b\x93\xcd\xcf_\\\xfdH\x93\xd5\xbatVo3\xf6\xf64\x19,\x1e\xd4\x01\xb8&\xc5\x1aq\xa8\x81\xfe&\xb3#93Z\xca\xe9\x9a\x92\x05\xcdU\xcc\x14v\xa1\xde*T\xdcE\xa0\xe6\xa4\xf3\xbb\x9a|\xae\xc3!\x82\xcd\xc2\xb4]\xdaNI^\x16\xb4\xfc\x91\x8f\xf8\x9b\xde\x8f|6O^\xb6g\xc7oj\xc2\xc8\xb3\xaaR\xa2\x90\x80\xe8\xae\xb8\xdd\xf3n\xf2\xdb\xb9FR^\xd0@o\xf0m2\xca\x1f\xcc\xf7LAd\xb7;\x0ck\xdbE\x81\xe9\x9f\xb4\xa0i\xb1/`Nvb\xfb\x8b\xb3J\xfe9\xdfo*w\xeb.\xcf\xe6\xb4(D\x92%\x97\x87\x82_\xe5\x97\xe0?\xcf\xd7$I\xef\xa8|\xd4\xe2\xab\x18\xc2\x9f\xbbi=\x0c\xfc\xa6)<9\xbc/21[\xf4BS\xcb\x8b\x0bP\x16\xf1\xb9\xa9\xb8\xa5\x00?.(\x949I\x0b\x91\xe1\xb9%\xf3u\x92\xd2\xbeW\x96\xf7\xa2\xa3\x81$\x19\xa6b\xcd\xb5\x9d\xd3+\xe6}^&C\xc7\"\x92\xdd\x82\x94\xf4[\xf6~\xef \x9e\x8b<\xd4\xaf\x92F\xec\x0c\xb5R\x02[\x87\xc1\\f\x06l\xfaX\x92\xb1\xe7`\xed=\xe8\xf5t\xfd\xb3Q_K\xb2ce&Q\x01F\\`\x17\x99E\xaf\xf7\x1e\xea\xeawI|\xa9\xcc\xb3\xed6)\xa7!O\x1ch\x1afl\xc5~\x16\xda\x9am\xfb\xde\xb3\xecO\x81\x9b\xe7\x05\x89H\x99\xe5E`\xc6\xfdq-s\x0e/P\xa6\x97 \xdb\x97\xbb}\xd9\xfcm\x97\xd3\x0b\xa5\xfa\xe4\xee\xd2\x83\xf5\xb1\xd6\xe8\x81\xf9\x92\xdd.0G\xbe\xfe*\x7fj`\xd6\xf4\"Y\xd0tN\x03\xb3\xad\xe7\xbf96\x15\xf6\x07SDYA\xf3)Y,rZhC\x17\\\xdb\xef\x1c\xf2b\xc3w\x9c[\xf5q\xca\x93\x14\xe0\xac6\xdc\xab\xcd'\xb4k\xc7\x81\xd7 \xbd\x05?k\xad\xfc\xac\x1d\xa1\x1a?\xd6b\xc7\x16\xc5h\x9c\x18\xbb\x05t\xf6\xb9\x10\xa0\x91\xac(\xc1\x8d q\xfb\x11f\xc3\xbf AM\xc4\xad\xe6OG\x8abF\xf2&\xc6kYn6l\xf0\xc0\xbf\x05Dr*\xf4\xce\x04\xe0/\xf4fN\xe1\xb7}Q\x02Y\xe5\x942\xfbG[GP\x842\xf0\x9a\x1d\xca\xf68\xc0\xb6\xa5$\xadz/\xba\xf8|\xb7\xfb\x91\x14kXdT\xd4\xbf\xab\xbe?\xc6\x1a)(\xeb\x962\x84\xf0%3\xbb:\xa5U\xf8\xb7\xe6\x96\xc2b\"U\xf1\xb0\x8a\xd7\xa2c\xe4\xb5\xd8\xc9\xdd5z\xe9\xa8\x19\xc1\xb8\xf5\xa35\x11l\x06\xc2b/\x8cK:\xbd\xc8J:\xd5wN\x90\xd5 \xb1\xb7\xc8\x88\xb7E\xf4\xbf\xa3\x1a\x02dc \xd9\x19\x9f\xb0\xee\xc46\xd1t\xaf \xa5j\xd3\xb7\xf0\xe1\xe4\x87\xb7\xaf^N\xdf|\xf8az\xf6\x1f\xa7\xaf\xa6\x1f\xdf\xfe\xf4\xf6\xdd_\xdez\xbcy\xfa\xfe\xd5/\xef\xce^\xf9\xbdy\xfc\xee\xcd\x9b\x933\xafw\xdf\x9d\xbe\xfb\xf0\xfcg\xcb\xab\x15&\xf2\xd4s\xbcv5\xd6\xa5\x0f\xc9*\xa5\x8b7\xc5\xea\xac*\xc0#\xea\xc3\xf2@\x1a\xfeS\xbb&\x99Z\x01u\xa9>\xd9\x94\xca\xa8G\xda\xb9y\n\xbfd\xa5\xa2\"/\x8a\x83\x90\xf3S8\xe5\xe7(\xd9\x98\xd9\xe8.e]rX\xd0\x18\x03_P\x9e\xedS%\xa6\xd7&\xdc\xadBP\xab\xe9\xba\xd2\xb7\x9a\xf47\xbc.!u\x078\xe8\x0f\xb0^p\x1ar\x10;\xd8N\xf8>\xa1n\x8d]r\x90\x068J\x84\x91\xe5~\xd9%\x97u! \xbf4%a'\n\xdc'\x0b\\'\x0cygU\xbe\xa2\xbe\xc1\xf6\x1f\xdd\xd2\xa2$[\x8d\x8f\xad\xf5 ~\xa06wK\x97\xeaK\x9d\xde\xf4\xef\x92GO\xac\xa2n:\x91\xa4\x0b\xfa\x19\xd7\x05\xdc:\xc4\xeb\xa7\x1ae\xc05\x1fR\x02.G(;\xa5\xba\xd1e\xec\xd6\x9e\x95\xf4NU\xcd{\x9b\x88\n\xe3\xe2\x9f\xdcX32\xe4\xb7\xff\xe6n\xcf\xfal>G[\xe7\xad\xee\x11n!\xce\xa2\x85\x88\x7f3Z\x88\x0dE\x0b1Z\x88&B\xea\x0ep\xd0\x1f\xe0`x8\x88\x1d\xf0g\x80\xa0h!\"\x08;Q\xe0>Y\xe0:a\xd1B\x1c\x90GO\xac\xa2\x8e\x16\"\xfe\x08\xfdCX\x88\\\xadL/\xb22IWS\x9epg\xb7\x16\xad\x02\xc5\xa9\x92f-]o\xbb\xa8\xad\xec\xd8\xa2m\x0bc\xd7\xcdK\xe9Hf\x8b\xe7U\xe5Fn\xdc\xee\xd2\xb1,`\x9aZ\x80Zv\x95\x99V^f\x8c\xc7r\x93\xcc\xd9<\xf3\x95\xa6Y\x13\x1bf\xf0LE\xfe\xca\x94\x94%\x99\x9f_\x97;\xbb\xd5\xc3\xa9!\x96F\x10\xa2M@\xb6\x0b\xb5\xa0\x90\xa7=\xb2mph\x1f4!Pjr\xe8\x008v\x02LATj\xc2\x86V\xa9\xc9q,\xe01\x1e0\x07g\xa9 \xa9\x00\xfa$\x15\x826\x90KM\xda\xf0.5]g\xe7\xb0\xaa\xabO\xb8\xb014;ux\x19\xf6\xe6)\xc9\x12t\xa6&l(\x1a\x9a\xa1*d\xcd\x1e\xa0\xa6&l\xd8\x9a\x9a\xf4\xc1ljr^x\xb8\x1b\xb4$g\xf6\xd83\xbfM\xea\xd095\x8d\xe8\x90\xcd$\xe8\x92%\xf8NM\xd7\xa4;]\xeey\xe0'4\xc0\x9b\xe0]\xf2\xb8\xa8K\xf2\x90\x1exJ\x10\\/\xf0\x92\\.P}r\xdf\x19\x92\\'\x1c\xfc'\x1d|'\xde\xeb\xc2/\xc9\xe1\xe2/\xc9\x1e\xf2\xa8&\x0f\xb9x\xc8\x03\x1f4\xa9&C(\xa5\x9a\xaecX\xd6@G5]G\xd7\xf4\xe9\xdfz\xc2F~\xa2\x19\xea\x02\xec\x87\x84\x8b\x1bU\xd3u\x88\xd3\x16y\xaa\xa6\xeb\xe8\x99>vUM\xd7\xd1'D\xf4\xab\x9a\xae\xa3s\x96\xf8Y5]G\xc7p\x11\xb8j\xb2\xc7\xe5\xaa\xe9\xf0\xe3\xf2\xb9\x9d\xb9\x04\x00\xa3\x18\xea\x82\x84\xd5$\x0eQ\x8c\x08\x1d-4W\xcb\xec+\xbc\x9b\xa0P?I>\xc6!\xde\xcb.)^J\x1c\xb6\xa3\xa0x)\xd1\x92\xfb\x96\x90\xe4:\xe1\xe0?\xe9\xe0;\xf1\xd7})i2\xb2\xb1\x92\x11\x12\xd1W\xe7\x1b\x92\xb1^\xdf\x90\xbc\x16\xb0\xdf\xf2\x95\x9ai\xba\xdc\x10E\x991\x13y/\x0c\\DR\x97\xbe\x85\x17?\xbf;\xfeiz\xf2r\xfa\xfa\xe7\xe7? \xa3u\xfa\xd4\xe7\xf2\xfc\xc5\x87Wo\xed\xc1F]\xea3AF,u\xa9\xcf\xe4\xed\x89-p\xa9Ku\x18\xd3x\xb1\xb8\xdf\xc2\x04\x89M\xb6x\xbd!\xabV @Q \xe1\xc5f\x9e\x9d\x9f\xbct\xf2+\x0b\xaa\xb7#$\x02\x9d\xb5\xbd\xd0\x903\xba\xdf%\xef\xf5\xec\xad\xe6\x10\x18\xea\x90Fw\xd3\xcd\xa9*\x08\x1d.\xd0\xa5\xd1}u\x12\xa9\x8f\x1d/\xe8\x98\x9b\xd3\x1f\x92\x95\x88\xd0c\xb6\x87\x84\x14x\x04\x82L\xc9r`\x99\xa4@*\xbevs\xde\xaf\xef\x82{7\xa1\xacF\xb7y\xb6\x9a\xbe\x80\xc0\x90.IQ]+J\x91\x95GdvZ\xe3\xf40\x8f\xa4\xd9\x7f\x05\xb5^ \x1c\xce8\x97\x93\xad\xe9\xab\xfdY\xd7\x93\xdc\xe1\x14w\x18\x9d \x971\nr\xd6q^\x9b\xd1c#\xee\xf6\xb3a\xb9K\x139\x0b\x0b\xbc\x04\xc6\x88.\xee?zt\xf4\xc4\xe5\x15O\xc1\x81\x9f\xf0\x80\xd7T\x9a\xef\xee?z|~\xf45w\xd3\xc7j8\xdd\xcf6\xc9\xfc'z\xd5\xf1\x9b\x9c\xd3\xabvAO\xb73\x7f_PQ\xc7\xa9\x95o\xfdK\xad\x03\x90\x8c\xb0\xa1[]\xf2\x92\xb7\xcf\xdd\xad\xf6\x9c\xed\xf2$\xcb\x93\xd2yk\x1d\xb4\x8f\xb2w\x98N9\xeet\xd7=\xee\xa8\x12=\x84\xe3\xbcU\x1c\x95\xa1\xa3\x80\xc0CH\xe0\xa7\x06=\x84\x05>\x02\x03_\x05x}\x1dtW}\xc1\x15_\x00\xb5\xe7\xa3\xf4,\x90\x12\x14\xe4\xa0N\xd0G\x03z\xf0\xe0$\x00p=\x08\x9c\x04\x01n\xc2\x00w\xb5\x7f\xd8\xee\xb8(y\xaczgj\x1b\xc1\xce[\xb1\xbbi&'\xf9\xe1\xf4\x83 \x0f\x05~\x80\xbe\xb8)kd\x07\x90Mc<{\x8e-\xda\xbcvX\x07\xd2\xcf\xec\xc08\xe6\xb9 \xcfyj\x82-CB8\x81\xb4\xfcZ\xb94\xa4,\xe9v\xc7\xb3#\xca\x0c\xb6I\xb1\xa1d\xc1\xbf-\xb4Z\x97\xd5\xf7<\xda\x1e\xa4V8XWPZ\x85\xa7Wn\xc1\x8bCjPd\xc1\x0fQUv\x80\x0c\xc7\xaa\x90J\x8aU!;dB#M\xd6\xd4\xa1\xaar\xa1\xf0A\x84\xf0\xcc\x98\x9f+\xba\xe7\x88\xe39\"vxl\xce\x0b\x85\xeb\xcc\xbf\x15>\xc3\x01bh\xe8\x0b1U\x88Un9\xde\x1c\x1a1\x1fkV\xd8\xc9\xa1%\xcdp:\xe7&\x16\x07\xd2\xa3;\xe6c\x18\x8d\xd8h\xd0\x98\x1e;\x056\xa3n_W2\x1e\xff\x95\xa2>\x07x\x7fz\xac\xfa\x0c\x87\xb6d\xfd\xcfly\x0b\x1e\xb1`},X\xcf)\x90Y\xe0:a\xc8;\xab\xf2\x15L\x02\xa0\x15\xc6\xa8\x1f\xc4\x0f\xd4\xe6n\xe9\x12\x1a\xb5\x91\xe4\xd1\x13\xab\xa8c9R\xfc\x11\xfa\x87(G\x1a\x0b\xd6\xbb\xbe\x19-\xc4\x86\xa2\x85\x18-D\x13!u\x078\xe8\x0fp0<\x1c\xc4\x0e\xf83@P\xb4\x10\x11\x84\x9d(p\x9f,p\x9d\xb0h!\x0e\xc8\xa3'VQG\x0b\x11\x7f\x84\xfe!,\xc4\xdf14:\x16\xac\x1fR,X\x1f\x0b\xd6\xdb\x9es\xea\x008v\x02b\xc1zAH\x05\xd0'\xa9\x10\x9cj\xc2\xc7\x82\xf5v\x8a\x05\xeb\xd5\x84\x0d[SS,Xo\xa6\x11\x1d\xb2\x99\x04]\x8a\x05\xeb\xb1&x\x97<.\xea\x92<\xa4\x07\x9e\x12\x04\xd7\x0b\xbc$\x97\x0bT\x9f\xdcw\x86$\xd7 \x07\xffI\x07\xdf\x89\xf7\xba\xf0Kr\xb8\xf8K\xb2\x87<\xaa\xc9C.\x1e\xf2\xc0\x07M\xaa)\x16\xacw\xeb\x9a[R\xb8 l\xe4'\x9a!\xbe\xa0\x1b.nTM\xd7!N[\xe4\xa9\x9a\xae\xa3g\xb1`\xbdc\xe7b\xc1\xfa\x16\x1d~\\>\xb73\x97\x00`\x14\xc3X\xb0^M\xee\x16\x18\n\xf5\x93\xe4c\x1c\xe2\xbd\xec\x92\xe2\xa5\xc4a;\n\x8a\x97\x12-\xb9o I\xae\x13\x0e\xfe\x93\x0e\xbe\x13\x7f\xdd\x97\x92X\xb0\xdeZ\x90BM\xde\x0b\x03\x17\x91\xd4%\xd7\x92\x16jr,t\xa1&\xc7\xf2\x17j\xc2\x17\xc5P\x93W\xa9\x0c5\xb9\xdf\xc2\x04!+n8rE\xd5\xe7P\x933\xba\xdf%\xef\xf5\xec\xad\xe6\x10\x18\xea\x90Fw\xd3\xcd\xa9*\x08\x1d.\xd0\xa5\xd1}u\x12\xa9\x8f\x1d/\x08[\xa8\xc4\x81e,Xoz\xd4\xe9\x8cs9\xd9p\x854%\xb9\x9d\xe4\x0e\xa7\xb8\xc3\xe8\x04\xb9\x8cQ\x90\xb3\x8e\xf3\xda\x8c\x1e\x1b\x11]\x88S\x92\xb3\xb0\xc0K`\xe0Z\xa0S\x92\x97\xe0\xc0Ox\xe0^\xb8S\xd2\xf5v\xd3\xc7j\xc0\x16\xf6t`\x19\xa0r\xb3k\xa1OI^\xf2\xf6\xb9\xbb\xed\xdc\x0b\x80J\xba\x86>\xeeb\xc1z\x039*CG\x01\x81\x87\x90\xc0O\x0dz\x08\x0b|\x04\x06\xbe\n\xf0\xfa:\xe8\xae\xfa\x82+\xbe\x00j\xcfG\xe9y\xc8\xd8M\x99\xc0\x18uw\xf0\xde\xb9\x05\xfa\xd6o\xb9u\x0b\xd7\xa5X\xb0^Mxm\x88>,\x90\x12\x14\xe4\xa0N\xd0G\x03z\xf0\xe0$\x00p=\x08\x9c\x04\x01n\xc2\x00w\xb5\x7f\xd8\xee\xb8(y\xacz\x8f\x05\xebut\x80\xbe\xb8)kd\x07\x90Mc<{\x8e-\xda\xbcvX\x07R,X\xdf\x90i6c\xc1z\x04\xfej=\x99\xec\xa7Q\xac\n\xd9\xa1X\xb0\x1e\x03c9\xe2x\x8e\x88\x1d\x1e\x9b\xf3B\xe1b\xc1z\xf4\xb1f\x85\x9d\x1cZ\xd2\x0c\xe7\x9f\xa5`\xbd\xa2`\xbc\xb1\\}S\xa8\xbe\xf5f\xc5\xce\xafX}m\xc6~\xa0\xa5g\xcd\xfa\xfe)\xaf\x9c~\xd5a\xa0\xba\xae\xaa\xd4\xe9@\x8dj\xd4\xa7Nmjv\x9fv\x99j\xee\x80\x06\xa5mR\xd8\xec\xb5\xe9>W\x1e\xa7\x96\x9d\x821\x1f\x9f\xc3\xc7\xf7?\xdf\xcdi\x91\xed\xf39\x85\x94l\xabE\xbbO\x93O{\xba\xb9\x02\xb6\x92\xcbd\x99T7\xa0\xb2\xaat\xa2\x8b\x02(h\x9e\x90M\xf2\x85.\xd4\xb9Z\xbb<+\xb3y\xb6\x81\xd9~\xb9\xa4\xb9,\x952\x11U9\xc5X`\xbb/\xea\x1d\x05\xa4\x84\x0d%E\xa9\xe6\x97\xa5\x14n\xdc\xbd\x01\xf35\xc9\xc9\xbc\xa49\xe3D\xb9\x1d\n\x05]miZo\xf7\x8f\xef\x7f\xbeY\xc0\x8e\x94k\xde\x80\x92]\x9d\x97\xaen\x8d\xb1Y\xee7\x9b+\xf8\xb4'\x1b&\x95\x85\x90Y\xd5\x04\x97\xce-R@\x92\xaa\x19\xfc\xca\x9a\xbf\xbb\xca\xb2\xd5\x86N\xb8,f\xfb\xe5\xe4\xe5>\xe7 n\xbf\xde\x16\xbd\xe7,\x8bu\xb6\xdf,`\xc6\xcb\xc8\xa8\xd3\x15\xe6$\xcd\xd2dN6|\x83\xa8[\xbcE'\xab\xc9\x1d&B\x9e\xaawcr\x83\xe9\x08^mu>\xa7\xbb\x92.nO\xbeQ\xbfz\x92\xc2\x8e 5\x99\xd3;PR\xb2-`_\xec \x1b\xbe\xc8\xd4\xdf%\x1b\xd6\xbb2\x13EM\x93\x94\xe4W@6\x1b\xb5\xec\xaev\xb4\xaa\xb8Z\xae\xe9\x95\xbaI\xfayG\xe7%$%\xbbn\xec\x0bYB\x87/\x06\xfa\x99O\xe5\xf3\xf4j\x02?f\x97\xf4\x82\xe6w\xb8j\xfb\xf8\xfeg\xf55Z\x9c\xbc\x8c\x0d[\xae\xea\xf5:_\xd3-\x85_\xd7e\xb9\xfb\xf5\x8e\xf8\xdf\xe2W^\x7f \xcd\xaa_\xef\xf0U6')d|7q \x0cU\xb7\xa0\xfd\xae\xaa\x07\xa4i\x8f\xe6\x174\x17b\xd8\x92]!\x96\x0c\x1b\x01\xbf`U\x85\x83\xb8\xcf!\x11\xb5c\x89zl\xcbl\xb3\xc9.\x8b\xa7\x9a\xb9\xfbW8Y6#`S\xbe\xcb3v,-\xeaA\xf2\x03\xb1(\xf6[\xba\xd0\x14\x1e\xfaWx\x9e\xc2\x8fgg\xa7\xf0\xc3\xab\xb3\xaa\xe0.\xeb\xab\xd8\xa0W \xdd,4+\xf3\xbf\xfaK\xfc\xecjG\xff\xfa_\x7fU>\xccu\xf9\x9e\xcfu\xb5\x86\x84\xbe\xe7\xb3\xb0\xcb\xb3\xc5~N\x81\xa4@\xf3<\xd3\x04R\xff+\x16T\xa6\xb03\xa9\xb0e\xc7\xf4\x8cXw$%+\xdd\x88g9%\xe7LwTL'\xb7\xd5\xab\xe5mV\xd2\xa7P2=\xbe\xdc\xa7s\xb1SX\xdf+}3\xdf\xe79M\xcb\xcdU\xcb\x83f\xc8S\xce\x96\xcbd\x9e\x90\x8d\xe1\x1c\x99\xed\x97\x90Sv:\xd0;<{8)ec{6\xb9\xdc\xee\xa9\xf7\xd7\x8c\xae\x924\xd5Y\x95\x97I\xb9\xd6(\xfd\xab\x1d\x9d\x88\xf5LvI1\x99g[\x9d\xc6\xfc\xc0w[\x01Y\xb9\x16\x9b<\xedk\x16\xb8U\xd9bt\xbb+\xaf\xaa\xedy[\xc9l\xcb},3\x8d\"\xe1\x03\xe4n\xc5d\xbb\xdbPv\xd0\xf1\xc5\x0f\xc5\x8e\xce\x93e2\x87\x82nIZ&sE\x88\x0f\xdfo\x1e&\x85\x8b\xe1\xad\xb18\xde0\xd51\xa3\xb2NG\xcb`\x18\xd8\x062\x03|\x96]h\x8c\x0d1\xd4j9\xf7\x87i\xeb\xcd\xaf\xcf\xd3\xab_\x1b\xc3\x9d\xa4@\xf2YR\xe6l\xf3\x19zU\xe9\xe8\x01;\xb2\xc9\xd2\x95\x98\x112\x9c2\xa65\xb9\xd2\x17\xbd\x9a\x0d\xcd\xa9v\x9b\xd2*R,\xb3S\xb9\xf07\xc9\x8cw\xb5\xd2\xeb\x05\x14\xfb\xdd.\xcb\xf9\xc9\xb9#\xf3\xf3\xbb\xfb\x94\xfd\x0f;/\xc5|s\xab\xa4\xcf\x8e[4J\xe3![\xc2\xbe\x14\xcaGn\xe7\x82)>\xb2X$bo\xc3\x8a\xa64'%\xef0\xbb:\xd4I\xfb\xcf\x15\xfaNL\xd1\xb0\x9dW\x9f [\xc0p\xf4\x14NY\x7f\xd9>\xae\xbaN\xda\x95\xf4\x8e\xff\xf4'\xcd1\xf5:\xcb`\x99e\xf0\x0c&\x93\xc9\xffT>\xc2\x84@\xd2+\xf5\x8f$\xbd\x9a\xb0\xa6_\xe7\xd9\xf6\xd62\xcbn\xab\x1f\x9bL\xd4gO\xb2\x84[\x8c\xc5G\xde\xe9\xb3\xec\xd6\xbf0\x1e\xb7\xe1o\x1a}\xaa\xe3\xf3w\xbdl\xee[d\xf3grAF\x0b\x07\x9eq\xdb\x8aq\x1f!\x85\xa4\xb8\xf5:\xcb&\xf3\x0d)\n\x83\x10D\x97\xd8\x0bb<\xad\x97\xd4\xed*\xa4S\x8b\xe7\x81E<\xa7W\xe5:K5\x02\x12=y\x9de\xb7&\x93\x89Z\x13\xd7\xc2\xb9\xa5\xfd\x9d/ .6W\xa9\xb1\x97O\x84\xd0^\xbe\xfap\xfc\xfe\xe4\xf4\xec\xdd\xfb\xdb:\xefH\xb3\xd0\xf4\x8d\x89\xe6\xf4\xe2zh\x11\xd7\x0f\x99\xa6\xce\x06\x13\xd5\xd3g\xf0/\xbb\xd9\xe4u\x96\xfdm2\x99\xfc]\xfd I\xaf\xee0s\x8d=\xbd\x13\x06\xc8\x1b\x92\x17k\xb2aB\xd4w\\'\xa6~\xcb\x9af\x93e\xaf\xd1\x8f\xe9\xb6i\x96w\x8a/l\xfe\xd4\xffx\x06i\xb2\xd1.P}_\x14+\x91]\xda\xb8\x1c\xa5\x1e\x94\xc66\xcc\xae\x1aSEjl\xf1\xb9\x8c+\xe9j\x1cp\xdb\x17\x8a3\xff\xa6\xc2\x0c\xb9\xcb\xee\xa2\x13\xfe\x033\xe5n\x02i\x9d*\xec\xc4\xa9*\xaa\x0c[\xe0\xb3>l\xa4V\xe3\xe9\xe6J\xde\x9b\x06\x17\xde\xdat\x04\xb2,\xa9\xb0f\xd8}{\xd8\xe5\xbb7\x87MT\x17:\xd9Eq\x83\xa3\xd5\xca\xbc\xb1\xcc\xb2\xc9\x8c\xe4|p\x9f\xef^M\xbe\xdc\x10\xd2\x12w\x0d\xf5\xb5\x8aw\xe5\x06{\x96\x1d/\x83\x9f\xff\xfc\xe1\xdd\xdb\xe1_\x9f={\xf6L=\x8f\xec\xf9\xc6\x0f l\xaa\x8cm\xd3\xca`\x10w\x95}A\xa5\xa7m\xb5\xdf\x10E\xc5\xb9!\x0b\xf6\xf8\x826\xc7\xfc\x1d\xa0\xdb\x19],\x9a\x03\xffNe?(\xbc\x07\xadcw\xc9\x85\xf1\xeb\xbf1q\xfcZ]r;\xfeG)\xdc\x89\xdc\xf2O5F4\x99\x9f\xb3=\xdf\\\xd6\x96\xc9\x86\xaa\xf5\xaf\xd4\x0f\xa74/\xb2T\xbbm*\x0f\x0e\xff\xfa\xca\x94\xcf\xcc38Rs\xac\x1f\xe6\xa0a\xf5\xec}\xbc\xf6\x07\xd0\xf6\xe2\x06\x97\xcd\x8d\xa7pC\xb5k\xba\xc3\x9d\x88\x11\xdd\xb8\xa3\xe3\xc5\xc7\xf2\x96l\x19\xbf\xff%\xba\xfc\xbf\xb5\x0f\xb3\xb1\xf4\x9e\xc5\x0e\xe8dY]\x0c\xbakB\xccfR\xc0%\xddl\xbe=O\xb3\xcb\x94\xef\xeb5)\x80\xc0|_\x94\xd9V\xb3\xc8\xbbK\xf0\x8e0@{\xebR~\xbb\xa7n\x96-\xb4t\xa5\xb8\xd7\xf3e7l\xe4W\xbe!\xe4:\\g\x9bEU\xd1\xaa\xe9\x19\xf7`U\xeb\x17*oQ\xb5|\x87\xfcx3\xf5\xca\x85[L?HQ\x0c\xdc\n\xd2s\xf6\xd7\xff\xfa\xebm\xcd\"\x1f\xbbF\xba\x0d\xe9\x97 \x17\x03cw4\xb9\x7ft\xbf\xb8\xa1\x99\xf6\xf6\x7f\x99\"\x19\x0c71=4j\x0d\xd3\xf0\xe0\xda\xb9F\xd5\x0e\x7f 4\x94m|\xa1v\xc9\x7f[\xd0\x1aD\xd9\x91U\x92r\xd95\x9d\xe9\xf0l\x1e\xa8cmH\xda\xfe\xabd/A\x8d\xe6\\.UNu\xb5;\x9d\xd7\xfa\x18\xf8\xe5\xb5\xf2\xd0\xdet+\xa8\xef\xbf\xfb\xf7I\xc9_\n\x86\xfd\xb3r\xd7\x90\xa2\x10~\xa8S\xb2\xa2\xef\xe9\xa7=-\xca\x89\xf8\xbd\xc7\xe4\xd3\x9e\xe6W\xfcu\xc6\x8e\xc9\x80\xc26+J\xa0\xdc\x19\xc2\xbd'\xadW\x14@\xbbu@\x8a\"w\xba\xb8(\xce\x9e\x8f\x87\xff#\xddog\xe2V.]h-?N?\x9a\xa4=\xd4y\xb6O\xcb)g\xd2\xdf\xa2\x97\xa4\x80\x82\x96w )\x0b\xe9\x05,`\x9f\x8a\x85\xb0\x10\x8e\x94\xcb\xa4\x8a\xb1\xb2 a*4\xca\xe9\xfb\xcdm\x06\xde\x9fq~\x9b-\xe8I\xba\xcc\x9c\xf1\xb0\xca\x1c\x9c\xa6\xd9\x82N\x93t\x99\xf5q-\xd4:\x97\xee\x8a\xa9\xb2\\\xa5\x92\x91\x9e\x19\xff\xe5\xbe\x02\x146\xfa\x89\x0cKM[q\xd2\x9f\xa1\xb2F\xa4\x1f\xbb\xee\x0c,P;k\x93\x14%M9F\x8fz>\xa5\xe5e\x96\x9f\xa3\x9e5L\xe1\xe0\xd9\xf9\x9a\xa4)\xdd\x14\xa8\x87\xb5\xfam\x9b\xa5\xc9\xb9\xfa\x83\xd3\x03&|o\x8e^^\xe5g]\xcdl\xc3\x1c\xe6\xbb\xb9\xd3\xb7 [E$\x87\xfb\xc2as1#\x15%\x1b\xb2\xdbM\xd1\x0f\xbbL\xf3*1\xc5\xd7\x0d\x1e\x9f\xed\x93\xcdbZ\x92\x15n]\xac2\x93\xda\xd0p_\xd0\x9d\x92\xfb0\xaaI\x19\xd1\xa4]3f`|GJe\xec\x97q\xe7\xd7g\xdd6[\xec7\x943\x19\x99\x07\xaf\xd5\xe71\xb7\x0d\xba\xcd\xd4\x07\xb1|\x8b\x1d\xbe\x15/\x97#\xf8\xc3U:O\xd2\x95\xf3 \\\x88\xf7\xfa\xaaa\x96e\x1bJR\xf3@{m\"\x03q\xaa\xb7<\xc7\xa9\xb2W\x9c\x07\x1d\xc3p\xe4\x1b1\x0c'\x86\xe1\xc40\x1c\x88a81\x0c'\x86\xe1\xc40\x1cA1\x0c'\x86\xe1pI\xc50\x9c6\xc50\x9c\x01\xe1#Mb\x18\x8e\xea\x91\x18\x86\x13\xc3pb\x18N\x9fb\x18N\x0c\xc3\x89a85\xc50\x9c\x18\x86\x13\xc3pb\x18N\x0c\xc3\x89a8_]\x18\x8e \x8f\xba\xe6@\x1c\x81\x84\xa2A\xb0.\x9a\xac\x9c=-r\xac (0\xbe\xde\xc5\x86;\x88\xb0\xe9\xed\x0e\xfa\xeb\x82\xf9Z\xa4U\xcb\x1b-\xb0\x01\x1c\xa7\xe8\xf6\x00\x82s\xd0\x13\xa5\x12p\xd3n+\xb3\x93) \xbc\xa6\x07\xd6\xc2Aj\xc1\xc04-\x8c6\x02@\x0b\x05\x9d\x99A3/\xb8\xcc\x1b(\xe3\xe3\xed\xe3;Z\x88\xcc\x1b\x1c\x13\xb6Y\x8f\x9b\x06\x16\x1b\x03\x88q\xf0\xab?\x1a\xc5\x9d\xcd\x07\x04\xd3\x03^#\xa1.\x14\xc8\x85\x07\xb4F@Y#@,\xe5-?\x18T\x15\x16\xa4\n\x06O\xd9\x81\xa9`\x90\x94\x0e\x8c\x1a\x03C)!'\xc5]d\xa8o|a&-\xa4\xe4 &)`$\xab\xfd90\xa8\xcd'\xa8'\\\xd4@C*\xf9~co{\x1c8$\xc0\xa0\x16\xbb!,\x14\x00\x10\x1a\x07\x05\xf5Vy\xff0\x1c \xffT\x82ns\x1c\x03\xf4\x18Q\x0c\x0d\xb8c\x85u\x86\x1e^<\x943|\xf7\xef\xaa\xb1z\x017\x98\xc1\xda\xc0\x1a\xfd\xd8\xac\x00\x8d\x034\xd3\xf5b\x8d\x84c\x8c@\x8c\x1e\x821\x81/J)`\x01\x17\x1b\xd4\xd2\x07YF\xc0+\x08`\xc5\x1dRQ\x00\x186\x18%\x10\x80\xa2h\xb9\xb3RF\xc1%}xd\x0c0\xa2\x00BFA }\xc8#$\xd8\xa1\x859\xfa\xbe\xdf>\xb4\x11\x06\xd4\x08\x06g\x84\x052p\x10\x86\x15\xbc@\xc2\x16\x18\xc0b\xe0\xd9\x1f\xb6\x86u=\x9b\xe1 $0\x81\x80$:]\x0e C\x8c\x02 \x86\x80C8\xa8!\x1c\xc8\xe0?\xbbV`\xc1\x06)H\xf5\xad\x86\x11\x94\x96\xb8\xca\xc9o\x00\x0d\x90<\xc6@\x046\x07a\xe3MD\xbb\x08\xbb\xf9O\x8a1\x0c\x93\xa4\x14\x0fa\xbc\xab\xaa\xa4(\xc5c\xaad(\x157E\x12\x94\x96[7\xf9\xa9<@\xe2\x83*\xd1I{\xbd\xb3&8i\x92\x9b\xd0\x0cUIM\x8a\x84&;?E\"\x93\x8bC;l\x02Sk\xc5\xcf\xf3\xab]\x99M\xea\xef?\xa0\x97\xfb\xe0\xbb\x1b\xc6]\xdb\xba\x7f+\xbe\x91\x81{U\x96&w\xf8T\x85\xf9C\x14-1\xec\xee\xef&/\x85\xa5'\x05\x87\x96\x84>\x05Y\xb9\xf45y\xcc\xfd\xb4c\xed\x92\xd2Bj\x8aTcw&\x83\xf4b7\x16\xda\x94b\x05\x1be*\xb1\xe2\xb9A\n\xb1\xa7\xda\x1c\xa6\x0c\xe3\xd6\x9d\"MX\xf1b/=\xd8a\xea\xd5)\xc1\x1a\xb9kS\x81{\xcf\x9b\xd7\xf6\xbb\xa6\xb3\x88\x05>\xec\xa0\xa2s\xca\x8e\x99;uZm\x9c_\xda\x93\x87\xe8Og\xaf\x18\xe7\xb0\xb36{\xfb\x03\xffbgO\xe0^k\x8d\xb4\xe4W\xda\x17M\xe3\x88\x11\xf6\xbfX\xe1\xb0\x9a\xd4 \xcdBu\xceH\x91\xcc\xab\xf2\xecI;;V\xdb\x06\x18\x13\x05\xbf\xe6\xe2\x066\x17\xef1;\x14\xd3b_\xc0\x9c\xec\xf8\xe7*$\xaaU\xfd9\xdfo(\xff\\\x01\x13\xc0\x9c\x16\x85\xb8\x1eH\xe9\xf5\xd8q\x84\x8d\xfd4_\x93$\xbd\xd3\xb7\xd7E\xd9}\xce\x81\xdd;\xea\x07aAJ\xc2\xc6\xb6\x9f\x8b>H\x17\x81h]\x89\xc9\xb6\xb2\xfbo\x16\xfd\x86\x8a\x92\x94\x14\xca\x9c\xa4\x85\xb8\x8dl\xc9|\x9d\xa4\x9d4\x05\xde2\xb6\xe0\x83\xea\xb34\xd63\xa1?\x19e\x82\xac\x0d\xd0\xb0P}V\x81\xdf\x80\xd5_\xa1\xf1X\xbd\xea\xcf\xa9\xa0V\x9b\"\x13\xc5\xfa\xb5\x19m\x0f\xc1\xd8K\xfe\xaa\xfe\x0b3\x82\xab\xe9\xeb2\xfa\xb8-A\x87\xfa\x00\x8f\xf5K2\xda\xaf\xc8\xb4\xbe\xaa4\x1d\xf6\xce\xbart\xc1S\x8c\x95\xd8Sb\x0f\xb3\xad\xd7z\x8e\xfdg\x80\xe6\x9a\x04\xf1\x00\xcc\xfa}_\xe6\xd9V\xc0M\xbb\x1dd\xfbr\xb7/\x9b\xbf\xedrz1\xf8Z:\x0f\x10\x0b\xda\xa7ZC\x06\xe0\xc5\xae\xc4\xe3\xb9\xf0\xf5Ra\xd3\x01\xd8\xc9\xcf\x99\x04`\xd5\\\xff\xeac\xa5w\xee\xd6n\x10\x8cQ\xd7\x90\xb2\xbd\xce\x81'6\\\xe7\x8eT\x1f3\xdc \xdb\xbe\x16\x89\x0d!4\x97<)\xd8~\xf0\xb2@\xca\xcf\xcaQ8\xd5GQ*\x1dO0\xf7\xecs\x95\x00.}~\xfc\x00\x15n\x7fq\\\xfe\x9b\x10\xc0DD\xde\xfd\xe9h\x00\x12\xbd}w\xf6\xea\xa9\x88\xc7\xd9l\xd8\x00aMs\xcac%\xf8\xde\x9a\x00\xfc\x85\xde\xcc)\xfc\xb6/J \xab\x9cRv\xd6+#$\xb2\x9c\xcd\x0b\xf7\xa2\x0e\xda\xe1\xb1S[J\xd2\xaa\xc7\xa2[\xcfw\xbb\x1fI\xb1\x86EF\x05\xbe_}\xc4\x871/(\xebN+6U\xac\xb7\x97\xcc\xac\xe88\xb5\xc5G\xf0\x84e@*`\xb5\xfd1\xa0\xda\x80\xa9X\xc9]\xe0\xb5\x04\x86/\x83\xdf:p\xae\\\xb1\xd8\x0b\xe3\x88N/\xb2\x92N\xd5\x1d\x11d<\x90mG2\xf7\x7f\xd2)Q\xfffe\x0e\x88\x06@\xb2\xd1\xfe\x8a8\xa2\x05\x99\xbf]\x06\xfc\x8ba\x1fN~x\xfb\xea\xe5\xf4\xcd\x87\x1f\xa6g\xffq\xfa\xca\xfa\x053\xf5[\xa7\xef_\xfd\xf2\xee\xec\x95\xfb[\x96/\x9a\xe9\xde{w\xfa\xee\xc3s\xdd\xc7\xcd\x00Z\x1f8s\x1f\x9f-\x95\xb7M\x1f\x92UJ\x17o\x8a\xd5Y\x05X\x88r\x0cl\xcb\x15\xfc\xa76\x16\xab\xcf\xf3\x17T\x9f\x16\x9a\xe4\xc1\x9a\xb4\xf2\x7f\xca\xbf\xf6e\xf9\xda\xaa^\x9eO\xe1\x94\x9fKd\xa3gq\xcd\x1fn\xd6|\xcd\xb2!\xbb%,\xa8\xd5\xdc\xe0\x0b\x97\x0d\xe9\xbfu\xd9\x10b\x8f\x03r\x9f\x83\xf5\xf3\x8e\x82\x90\"\x05\x9bq\xde&\xeb\xcd\xa5K\xc8Q\x83\xc3\xc8\x19Y\xbe\xa2\xd9z\x109\xcf\x92p\xcbK\x12f\x12\xc0m\"\xc0e2\x10\xf7&\xe5\xe3\xeaoq\xb6\x1f\xbb\xfe\x0f\xfa:|\xd4\x11\xdc[7\x8a\xb2iXSm\xb1!\xecz\xc2\xe9\x0d\xeb\xf7\x1e!\xe8H\xb1G\x14\xff\xf6c\x0d\x81\xf3/C\xe6\x94Y0w\xaa\xe8\xdcm\"\xa2\x85\xc5?\xb9q\xa3e\xc6o\x9c\xad\xaf&/3E\"\xaa\xa4\xd6Y\xa6\xfa\x99[Q\xb3hEE+\n\xa2\x15\xa5$\xe4\xe2\xc4\x1ds\xd1\x8a\x02\xbcH\x01\xa7\x83\x05E+\xaaE\x98I\x00\xb7\x89\x00\x97\xc9\x88V\x14\xb6\xf5hE9\x1cQ_\xad\x15\xc5\xb7\xfd\xd4\x94\xd8_?i\x17\x9a}\xab7\xeb\xe2\xf0mY\xb7\x9cC+\xa6\xad\x86Y\x03/\xa5s\x91-\x84W\xf2\xab\xe7\xb5\x9b\xb5\xfe\x0e:w\xaf\xd7BR\xb2\xaa\xcc\x99\xf22c\xef/7\xc9\x9c\xcd\x1d_1\x8a9\xde0#a:\xdf$4-\xa7\xa4,\xc9\xfc\xfc\x90\xae\xcdV\x8f\xa6\x1a\x8c_\x10\xe2\x14\xb3\xb5\x05\xb50\x10''\xa2=@\xb6 \x8a0\x0b5!\x1b\x05\x87\x86\xc1\\w\xbdO\x98\xf0\x0d\xcd\x9b\xf8\xbe\x83c\xffA\x1f\x00\xa2&\xc4F\xed\x93\xdc\xb8\xca`\x115)CH\xd4t\x1d\x1d\xc2\xa8\x95>\xe1CSP\xec\x94\xe1+\xb6\x80\x155\xb9\x84\xb1\xa0\x18\xf6C]\xcc\xc1-j\xc2\x84\xbc\xa8I\x1d\x08\xa3&\xa7\xc5b\xbf\xd5Irb\x8b9/\xdb4\x0c\xbb\xd1<\xe7\xd7 \xbb\xe5*\xc9\x10\xb8\xa3\xa6\x03\xeb-\xec\xfd\x04\xdc\x85\x038\x93\xb3K\x8e\x97GI\x8eR\x02\x0fI\x81\xcb\xa5R\x12\xf62\xd0'\xb7\xd5-\xc9e2\xc1oB\xc1gR\x9d/\xa1\xbd\xd7l\x97QI\xe6p)59\xca\xc0q\xec\xb8\x80+5i\xc2\xb0\xd4t\xc8a\x18\x83\xa6\xd4t\xc8\xee\xe8\x0bf\xa9 \x1b1\x86b\xd6\x8f*S\x93=\xd6LM\x87\x14\x9b)ZMM\x87\xec\x8d:\xdeMM\x87\xec\x87%bNM\x87\xec\x90!\xe6NM\x87\xec\x8c=jOM\xe6X>5\x1dn\x1c\xae7\x0f\x97\x80A+3U@\xa1\x9aT_w\x1b\x92\x83\xa5\xe3b\xe1|%v\xba\x15\x95\x91\xe4jX\xe1\xbc\xad\x92\xa2\x81\xae\xa5h\xa0sr[\xd6\x92\\&\x13\xfc&\x14|&\xf5\xba\x0c\xf4\x1a\xcd@M\xa9\x18\xfd0JVM\xca\xd8Y59/F\xf7\xa5(5\xc8t\xb9!+\xecK\x9e\x13n\x8f\xc6\xe8\xd2\xb7\xf0\xe2\xe7w\xc7?MO^N_\xff\xfc\xfc\x07D\xe4B\x9f\xfa\x1c\x9e\xbf\xf8\xf0\xea\xad9\xd8\xa2K}\x06\x88h\x8d.\xf5\x19\xbc=1\x05mt\xa9\x0e\xe1\x18'\x06\xb7[\x88 \xb1Q\x16\xaf7d\x05I\xba\xe0\x10JU\x1e\x12^l\xe6\xd9\xf9\xc9Kk4G\x97\xea-\x05 \xde\x11\xea\x88\xa4v\xc9k\x8dz\xa9$\x04\xc4\xdc\xa5Q]\xc3;\xf1\x04\xa1\xa0\xd9.\x8d\xea\x1fZt\xae\xf6\xae\xa0cn~~HV\"\xda\x88\x9d\xf3\xd2\x15\xcd\xd1^\x99\"\x81d\x97\xa4@*\x9e6\xf7\xb3k\x7f\x05\xd7nRG\x8d8\xf2l\x11\xe9\xdd\xbf\xd4|\xbc\xafM\xc2\xec.E\x16\x0c\x91\xd9!\xcd\xe5]\xdf\xfbf\x0f\x15\x14\x11\xb8d=o\xb0\xa7\x8c\xea\xcb\xabj\xc2\x9f\xa0\xc8\xd3\x139\x12A\xd8\xf1\x08r\xd2C\xce\x1b\xc9q\x13i>\"\xab&'\xa1\x80\xb3`@Uc\xc4F\xce\x02\x02w!\x81\xba\x86\x89\x8d\xae\xa7k\xae\xa73\xb6\x98\n\x92\x9d\xb5\xe4\x8a\x8d0!,]r\x96\xab\xeb\x1dfg\xfb\xba\x85\x9a\x0e\xd8/\xd9#[G\x1cv\xa8\xcb\xdetPY\x8eBpZ\xee\x0e\xca\xcaA\x10\xe0(\x0cpWS\x8eB\x01W\xc1\x80\x8f\x82:|\xa7\xdcT\x13V1\xf1\xba\x9c6f k!\xfb\xa9%W\xa5\xe4(K\xfc\xc6\x07_ut\xb0\x1e\xe1\x03\x0f\xeb7\xf0]\xb1w\x83Y\xb1Y:\xf8\x9a\x7f\x97\x10-\xda[\x9a]}!i\x99\xa4tj\xb7C\xed\xf6\xa7\xc5\xeeD\xe9+\x9c\x96B)k\x84\x84\x04!\xb7\xb2\xce\xeb\xa8\x1a\xaf\xa2\xaak\xbb\xef\x83\xfa\xae\xe3j\xbb\x06\xa9\xeb:\x9cWUA\x03\xf4D\xf7+\xa0:Xg\xfc\xd1\xd6\x7f\x1b\xf4\xb8\xea\x1c\xc7\xd6\xd9\xc2V\xd6\xc2\xd7\xd2BV\xcfr\xaa\x97\xd5Y\xd2\xff\xddw\xa0\xba\xd6\xc42\xd5\xbdr\xadt\xe5Z\xdb*\xfaH!\xfaH\xfbt \x1f\xa9\xc6\xc6\xb4.7\x95}i1\x82\xad<{C3\xd6Mr_\xcb\x1a\xdb\xd7\xadW\xfas\xd3\xa7\xaaQ\xbfz\xd17\x9d\xd6\xdbzgP\xb9\xa8_\xf11\x9e\x1a5\xc5S\xa3&\xeb\xe2\x8e\xa7F\x8b\xe2\xa9\x11O\x8d\x7f\xecS\xc3\x14;\xa1\x1c\x92jij\xeb\xd6\xa19\x8c\xbb\xd7\xab\xa5\xe9WU\xaeUA\xae\xe2\xa3\xac#7\xb8\xf29\xdf\xf2\xac_\xd4p8\xc0U\xdf\xcc\xf0\xd0\xaeC;\x00l*E\x87Jcm\x02\xf5\xb3\xfa:\xcdx\xdb@\xf7\xb4\xa6&\xb3\x93\x8d\x00V;\x01\x02\xdb\n\xe0a/\xe8\xde\xb1UQ\xd6\x85}\xa2\x8eY\xd5\x91\xa5\xc9\xc37\x9f\x83:\xfd\x0b\xc6\x8c\xfa\x11'\xf6\xa1\x0eU\x84\x9d\x01\xb6\x9e\x83\xb5\xf7`\xb69\xc0*oI6\xdb\x03\xac\x99\xe7Vq\x81]d\x08[\x04L\xf6\x08\xe8m\x12\xb0u\xd1\x8c\x98X\xed\x13\xc0\xf2W\x0c\xddZ\x19\xd8\x7f\xcf\x18\xa2G\xfczk\x8eO\xf4\xb6ct\x12QV\xf2U\xd6\xefU}\xfb \x9e\x86\xf14\x8c\xa7a\x87\xe2i\x18O\xc3\xea'\xccR\x8e\xa7!\xfc!OC[v\x84v\xb8\xba\xa5o\xacR\xef\xcc-\x9c\xe3H?\x03\xa1<\x01\xa0\xf3\x06\x00\xba\x96\xbcR\xaf\xa9u\x99\xa5Z\xbc\x87Ec\xa9\x07?\xe6\xb48\xac*\xb7\xd6tw\xad\xe4n\xed\x13\xa0\xfa\x05\xb8Z\xed\xa8#\x00Z\x8b\xdbZ\x06\xddZ\x8d=t\x93\x98d$A\xf8*\xeb\xd0TP7\x0d\xd5\xab\xb6\xbaKE\xf5\xa6Z\xba\x81\xa1k\x1du\xd7\xea\xe9\xf6\x9a\xe9\x88)\xb5\xd5]D\xb0\xc0\x99<\xe6\n\xe8N\xcd\xd8\n%!k\x9c\x07\xdc\xd1\xf6\xbaz\xa8\x01\x02\xc6\xae\x13\x842\x89%\xa1F\n\xe8\xd1\x82\xddT\xae\x1fC\x99\xcc\x920\xebH\x92]\xe4\xe0\"v\xc0\x8b\x1eiZ\xf7\x1e6\x97(\xc4W\x0eG\x8d\x085\x12\xf7\xda\xe0\x88\x8a\xe0\xa1\xba\x87.^\x1d\xaa\xc1\xbe<\xac\xe5\xba\x8d\xa5\xb8\xdd\np\x87\x1a\x03\xb6\xc4v\xa8\xf6\xecE\xb4C\xb5\xe4P&;T\x93\xc8B\xd8\xa1\x9a\x03\xa7R\xd7;t\x81\xeb0\xfd\xeb\x18s.\xf5\xa9\xad\xf5\xa7MU\xa7\xad\xe7\x96\xfd\xbc\xba6\xfb\xc6R9\x1aw\x10\x9a\xfc\x0f\x92\xa2a\xd3\x10j\xa4\x80\x1e-D\xc3&\xb4a\x83\xa9\xb8,\xc6b\xae\x12i\xad\x0f\x89\\\n\xd8\x85`\xcd\xbdo\x93\xc3d\xe0j%\xdb\x93|p\xef!\xeb\"[\x13\x82p\xaf\xd9k #\x93\x87\xd4\x84\xad\xa8\x13\xae\xca\xb1\xb5<@\x9b\x10^\xed.9\xac\x1a\x87\x0d\x8c\xacY\xec\xd1\xb8\xed\xda-\x08]\x95\xd8\xa3\x07\x96\xe1\xe3=N\xf8j\xc3\x13\xb62\xa96?\xe7\xe7\xa4\xc0\xd7\xe6\xd2\xc5\xef\xa0\xean\x0c\xb6\xbbn\x9b[3\x81\x8c\\M\x9cA\x93\x1b$h\xa4V\xe2\xaf+\x7f\xb1\xaeo\xb0\xfa\xce\\\"\xa6uo\xe8\xe3\xa6\x0doX\xbce\x0e1\xd4\x82\x9c#\xa9\xe5k\x18_\x83{T\xb5\x96\x91%\xdaZ\x90O\xcc\xb5\xfeM[\xe4\xb5\xa0k(BoD{D\x0bfl\xc0\x8e\xf4\xd8p\x1e\xc4\xb5\xc3\xb6\x1f\x01\x017 \xc4\x05\xf6\x93\\\x90\x03\xb6\x83\x18\x1d G\x08\x80Du0\xf3&\xc9\xbeD$\xd9\x04\x0cx!\x03V\xd0NH\x0e\x02\xc7\xb1\xba\x95\x11\x03\xc0\xb9\x91\xd1^t\x87\x16\xb5\xa2\xb2F\x8b\x0b\xc2\xac\x0b\xfb~\xb6:\xc6\xc7\x8f\x08s\x04\x84\x8a+\x17d\x8e.\x17\xa4\x8c1\xaf^W\xe4] \x8a\x96F\xb44j\x8a\x96\xc6A5S\xb44\xa2\xa5\xa1 \x94\xa0\xa3\xa5\x01\x18QEK\xe3w\xb64l~\xb0\xea)\xb3`\xcc[\xd1\x98\xe5&h\x14\xffC~*\xc26\x9f\xa3\xf2\xe1\x86#\xb9\xcc\xf4Yq\x82p\xb9q\x15;?7\x97%[N\xd0H;\xd4\x92?'\x08q\x02\xd9\xda\x01KF\x9d DC\x80l\x0c09v\x82\\3\xed\xaa\xb7p}\x05\x87\xfe\x02.\xf7N\x10BG\xb6In0k\x1e\x9e k6\x9e\xa0Cv\xc2\xb6\xe5\xfb\x84\xcf\xd2\xb3\xb2j\xb2\xf8~\xcf\xd0I\xcfd\xe6\x01\x9fV\x00\xacwJ\xf3\x8f-W\xfd@I\x0c\x15\xc2 \xc0\xcf\x16\xca\xa7T\x81b\"\xe4\x14\x0c\xe2\xda\x06at\xae,\xf4\x93\x87\x0fw\xd3\x87\xb3\xf5\x87;\x0cls\x0da\xeb\x84\xa8u\x05\xa1\x0eV\xb3\x85\xa5\x0d\x03\xd0\x14\"\xec\x1f\xeaJ)\xabv`7$\xcc\xf8Z\x7f{i\x02\xba\x1cV\xd8\x10{\xb1\xae\x8e\xde\x01a\x84\xb8\xb4\x87\xac\xfe`\xd5\x00T\x82\x13\xe2\x9b4\x03\xcd\xa6\x86\x97\x8c\nM{\x16\x1a\xc1!%\x0c\xa4\x0f-2\xcet\xa7e{`\x90\"\x04\x08\xcb^\x1b\xe4\x82e0.\xfc\xc6\x1ch\x83\xed\x83.L\x06\xfb\xfe0\xc8\x05\xfb\xa6!D\x05\xcbB\x13`\x82}\xdd\x1c\x1e\xa2\x0f\x04\xc1\xf1\x0fW\xd4zp\xd0\xf2C\xffEs\xc4!\x0e[M\xaa\x80\x8b\xc2\x0b\xa3\xa5\xb4a\xfd\xb6\xd3\xbf~\xcet\xfd0_;\x0c\xe1\xf9VKSk%H\xd2\x06\xdd\x8fem3\x01GZ\x13\n~\xb8p\xf9P\xd6\x85$kH\xbc\xcd\xda\x90\xa4\x0f{7LE\xf0\xcf*\xaa\x03\xd6Q\xect\x97\x01K\x18\xfa\x88\x9d\xa1\x8f$A\xaf^\xcd\xf5\x17\x15\xc8c\xec9X{\x0fz\xeb\xa7\xfe\xd9h\x05I\xc2\\_\xcdA7Vq\x81]d\xc8P\x1ac\xf0\x8c=0\x1b\xb5\x12\x95=\xb4[U\x92\x0c\x01\xd6\xbe\xcd[C\x8b}\x19\x8f\xb3\xc6$\xe1\xc2\x9f}\xfbh\x0bj\xf6\xe5\xab\x0fU\xf6\xe5\x88\x08@\xf6em +\xf6e\x8b\x0b\x16\xb6\x87\x07\xfb\xb5\x1f\xceZ\x94\xa4\x8a\xd5\xf5\xb0\xd7\x82\x9f\x8b\xf1s\xc3\xf1@\xec\xd35\x1c\x88\xa6\xf8Q\xd1G5\xae\xa3Eu,Sd\x9b T\xe4'Bx\xb6bBn\x81\x8d\x8e\x11\x9c\x8e1\x9b\xf8(M\xaf\xb8\xcc\xce\xfc[\x03,q\xa1\x93\xe8`I\xc4T!V\xf9u\x95'\xb1\x066:\xb4\xa4\x19N\xe7Ds\x8aDT\xc6\x19\x9ao\xc1N\xb1\x84\x8ax\xc1\x1e;e\xf4\xa0&^P\xa9\x07\xd4\xbb?\x16\x99n\xbfiQ\x90\xb1\xc8t,2\xcdI\x1d\x99\xe6a\xca\x066\xd9\x0d\x8b\x7f\x84\xe1i\\\xf6\xd6\xf5hY\x8d\x96\x05?\x8e\xbdi\xa9\x07^\xe8\xdaen^\xe4\xa8yV-p\xc4\xf2\xfe\xff\xd9\xfb\xb7.\xbbq#M\x18\xbe\xaf_\x11\xa3\xef[-\xc9\x9d\xdaz\xcb=\xef\x8df\xcakt\xaar\xf6TI\x1a)e\x8fW/\xaf\x14\x92\x1b\x99\xc9\x167\xb9\x8b\x04\xf3\xe0i\xff\xf7w\xe1D\x82@\xe0@\x12){\xdc\xe4M\x95r\x93A\x00\xc4!\x10\xf1<\x0f\x16\xd9\x8e\x81\x13\xbcFm\x83x\x8a\x00\xc3\x05\xc8\x178\x1d\xd4\xed\x94\x01\x01\xa3\x19K^@\xa2h\xc1\x08\xf6m\x99V\x8c\xb7\xa0\xccPjN\x02be\x80h9 .\x1f\x14\x1d\x9e`\xf4\x8c\xa0JOP (\xd7k\xe2y\x0bX\x9e\xbb\x08\xb5`b\xfe\x02\xd6\xe40<\xf6\x92\xa5}Rs\x19\x10\x95\xf1\x89|\xae\x10\x83:\xfa\xa5c\xdb\x7f\xbf(O\xb2\xe9\xd0>%Av'\xc3\xa8\xfb\x16\xf1\x8b\xc4\xb0\x0f\xa4\xd4\x08\x92j\x05\x10\x0d\x01\xc1\xf0\xb6X\x18\x08\x12\xfa\x82\xbe\xe2\xa4\xe4\xa4&\x85\xb4fM\x0c\x0d\x197\xfa\xc9\xc6\xf1\x9c \xa4\x94>Z\xea\xf4\xfc \xc4Ej\xd6\x16'\x9a\xab\x80\x0c/\xc9\x93[\x81\xe4\xfc\nd(s,\xd7\x02\x19\xde\x11\x96\x88Yk=!\x07\x03\x19^\x93 \xf3\xb2\xf6\x15i\xb9\x19H\xca\xcf\xc0\xea\xf2\xe4\xcf\xd5@@[e\x85o\xfb\xa0k\x7f@\x1f%\xbe\xa8\x18\xc6Q-\x94m\xd1G\xaex\xad`[\xf4\xf1\x1b\xfd\x8b~LWD\x96\xfbo{\xa0pR\xae\x08\xd2\x1b9\xae\x0827o\x84=\x93\xa0\xfe13\x7f\x84=\x12V\xfaX\x94G\x02\x88\xc5m\xf5\xb5$\xd5\x14\xeb\xfc\xde\xdf\x93SQ\x90\xde\x13\x12\x07[\x822\xc7\xcc\x17\xc6U8\xa2)*\x98\xff\xd6@53\xa7\xab\x1c\x93\x1e\xe0\xe6\xf2\xb4\x156\x97\x85\x84/\x02r\x17\xdei*\x00\xe3\x0d\x10%CS\xe6C\xa5\xd3\xbfAv6B\x8c\xcc4\xd7'P\"\x13*\x03)\x15\x82xF@^\xf9^\x18\x9fVgg\n\xbc\x96\xd2)\x90\xb1\xd4\x18\xa4\xb5A\xdcYJ\xc8#\xc8k\xe5\xdb\xf0\x94\x19\xc4zi\xb8\x7f>\xe0\x8e*2\xb8\xa2C+>\xb0\xa2\xc3*Z\x01\x88W\x02\xd2\x06T\x9eW\xc5\x86R\xae\x81\x94:\x8c\xe2\x83(Z\xef\xd8\x00J\x1c>\xab\xde\x13K\xc9A\xec\x05\x98q\x8f|\x01j\x07{>,P\x80\xad\xb7k\xcf\x00\xf6\x0c\xf6@\xcd\xbd\x1d\xd63\xb4\x03\x83:4\x9c\x03\x039\xf2\xdd\x83#*8l\x97\x1b\xf6\x0f\xd2\xd9\xc33\x94\x11\xf7\x0c\xccP/N\xf8\x92\xee\xf0\x88\x0e\xc0\x99VC\x83-yp \xdb\x93\xe0\xb3\xd3\xad\x07\xee\xa4/\xa4\xd5\xbbg\x84/&\xd3\x7f -\xfb\xa4C\x1b\xb2f\xce\x88q\xc7\x89\x15\xfc\x91O\xd8\x81\x1e\xac\x11\x970(=A\x18\xa7*\xf2\xa4\xc6\x995Y\xc1TDS\xfa)\xa9|\xef\x94\xe4\x9f\x90<)\xfb\xa4\x15\x02\xcd\x9d\xa3\xa9\xf9\xa5\xe6b\xa0\xc9E\xa9\xf7\xa1\xf5,s\x91\x94\xfb\xe2T;B\x17\x0c\xa6\xd8SR\xebxJ\xdd\xd3\xccX\x18\xdd\xfbE|\x93\xa7\x9b*\x8f\x9a\xc0b$\x81\x94\xf8\x82\xde\x9b\x97A\x13\x8dv\x07\xfd\xf8\xb0\x0f\x1f\x88j\xe3\x93\x9cy\xc5\xfc\xca\x87J\\E\xa3\xd4\xde\xe8t8\x15\x1d\xed9Ni\xd2R\xce\x9eT\xf3\xdc\xd7\x05\xd3\xb3s\x8d\xadO\x1d\xc7S\xc6s\xcb\x14J\x0d\xcf\xb5\x85\xa7\x80\xe7Z\x89\xa4z\xe7\x9a\x0b\xa4t\xe7\x9a\x8a\xa7n\xc3)\xdby\xef\xcb\x9b\x9a\xb5S\xb23|\x90,k\x06\x92b\xf5Ov\x86\x91IJu[,&?\xfd\x03.\x16\xbe\x14\xa6,\xcf\xc3\xd2J\xa2\xa9\xc9H\xa3\xf8S\x91sR\x903R\x8f3R\x8ei\xa9\xc6\xd9)\xc6\xdc4\xb5\xa4\xbc`\xe43Dz\xe6\xc3\xe9\xdbE\xf2|\x89\xd6\x91bg\xcc\xe7\x85d\xdc\x96\xe7\xef\\%\xbei\xde\xce\xb3\x8d\xfe\xa5\xbb:\xe3\x8d\"\x9es\x9a\xc7\x1cN\xcf\xe0\xd3\xe9O\xef\xde\xbe9\xff\xe5\xd3O\xe7g\x7f\xfa\xf0\xd6\xea\x93\xee\xef\x1f>\xbe\xfd\xc3\xfb\xb3\xb7\xa1\xdf'\xc3\x05\xbb\xe3\xfd\x87\xf7\x9f^\xcaq2\x8c\x8cP9&\x8d\xfb\x1f\xbaq'u\x95\x1f\x8d\xd7\x95\x7f4\xc9(\x80\x03\xed:rE5\xd6\xdb8\x9c[\xb7\xa8\xb7~/\xc4G\xefB\xf7\xc9Z\xbc\x80\x0f\xc27!U\x87}\x90!\xeaf~\x8c`Pc\xa1\x94\x14\x12C\x9d\xe1\x8a\xa0\x11\xd3\xa8/b\x0d)O|t\x9e\x19,\x1a\x9a)\x0e\xeaD@W\x06\x15\x03\x91\xce$\x1b\xfe\xce\xf2Ig\xdf\x13\xfa\xcb\x16\xed\xdf\xa2\xfd\xff8\xd1~7+=c\x16\xcb\xb09\xf4tNo\xd7\xf4wLo\xb7\x0c\xf6\x9d@\xcf t\xc8e&}]1cGD\xbba\x06.\xa3\xbe\"\xddo\x96\xbd\xd5\x89&w>oX:\x97\x92\x0d\x1e\x9b\xf7\x85\xf6F(\xe6\xbd\xe1\xf7L=8\xef=\xce\xa6'\xe2\xc9A\xaa7\x07^\x8f\x0e2yu\xde:!\x9e\x9d\xef^\xcc\xbb\x835J\xc4V\xa0F>\x17H\xbb\x0d\x01\x1a783cJ\\\x1f\x9c\xdb$\x88\xad\x1f\xa7\xc1\x95u\x99\xe5\xe0\xceW\xcdUsl\x1b\xd6\x18m\xba/y\x05/z^<\xa3m+z%J\xac\xfe\xafi?\xd2[\xd2\xee\x93[{\xde\xf4\xd3\x1a\xc6\xc7[\xf2\xee3\xad\xefo\xda@fs\xbb/\x04o\xf7{\x1d\x19{\x87\xbc\xf2\xf5\x11y\xa5\xf4\x14\x7f\xc7\xf7\xf4\x12s\x8a\x96\xa9Q\xfdI\xd4\x93\"\x01\xb6\xd7\x0f=\xee\xf4\xff\xf3F\x90}!\xd6C?\x90\x96\x1c\xd2\xe7e\xbe\x1e\xf4u\xc9\xee\xcf\x19q\x16\xb2\xc9\xf7\xe4s\xcc\xf9\xe0\xfe\xe3\x1ds\xfa@S\xf7\xdd\xac'\xf8\xa7\xdf\xb7\xe4V\x0c\x8dsZ\xf3}\x8f\xf3\xc4E\xd3T\x94\xd4n\xf3\xcb\x9aO3\x8b\x12\x00v\x94\xbf\xf0\x89\x9d\xff\xd5l784\xfb\xbe\xa2\xb1V\xfd_=m\xef_\xeb\xb6\xfa\xd04\xd5G\xda\x1d\xf9\xc2\x91\xdc\xd2\xc7\xa6q@`\xdb@\xfe{\x19\xc8N%\xf9\xe7\x1a\xaa4\x8c\x12\xf1\xe7\xc7\xfc\x0fe\xdd!S\xc0\xe0k\xf8;\x0c\xaf\x89X\xfe\xf5\xbfy\x93\xeb\xbei>\xfd|\xf2\xb8n\xa4\x8f\x1f^\xabZ&\xf5\xd9q*\x923P7\xbb\xdf\xcaq\xfb\xc0\xb1\xce\xad\xebf\xec\xba\xea\x8bMfB\xfd7R\x14m\xaf\x93]\xe3\xe2\x12Z\xcd\xc2\xfd(\xbd;;&\x96\xf7\xe53\xbe\xa5\xfd\xbb\xee\xd0\xd1\xfc\xaf\xb7s\xdb\xeb\xa4y;F\xdf\xf3\x90\xf7<\xe5\x95W\x18\xa9\x81\x0eFyyK-/|`&<\x1age.\x1e\xaa\xdeb\xee\xbe\xc3t\xa0\xd6\x8ca\xc4\x9c\x1a\xd5\xc8/\xe9\x83;6\x87-u6\xe5\x95\xe6r\"\xe5\xb0\xa7\x19\xbe\xed\x8dM5\xcd\x00\xe3BA\xf1y\xc7\xe0\xb6\xa8d\\T\xc4\xf7\x9a:\xd7\xfdAt\x9e\xe9g\x9f\xb1\x92`\xb3\xf8\x92\xe5\xc4\xb4\xb3pMi\xda1q2{AY\x99\x10\xb6:\xd7\xa4\xe9\x8c\xe8\x9c\xd9\xf4\xe6\xc1\x90\xe3\xd0\xe2m\xa7\x07o}\xc5\x1b-\xf5c`\xd5\x9f\xfd%L#\x8b?\xc3\x1f\xd5\x16\xf0\xa5\\5g\x7f\x8b\xc9\x162\x16]\xb1\x9a\xc6~v\xd2\xe4c+\xeb_Y\x03\xbf\xf2\xb2\xcfkhO\x05\x17\xb4\xb6ein\x93\xcb\xed\xf2\xec\x06>\x1a\xf1\x05\xa7\xceGw\x0b.\xfeD\x19mu\xa8\xd3\xd8q\x9b\x1f&)\xb9\xe2\x89V\x80\x7f\xa2\x0eG-B\x0f\x86\xa3\x17\x81'#Q\x8c\xf1Io$\x03\xf9>\xc1\xfe\xa1z\x86\n\x80\xcc\xec\x07\xc3\xa0\x15\xb8\xb9\xae\x13\xfe\xf9\xccNQ\x0c\x8fz:\xc6x\xc3\xa4s\xc8?\xf3\xbfNf5hiA\xcb\x1b\xba_\xdcI\xec\xc2@\xc0\x85\xce\x89\xbc\xf5\xba\xceA\xef\xd7\xef6\x07\x1e\x8b\xb9\xcc\x8b\xdd\x10O\xf10wy\x8do\xe2\x18\xf3\xb9\xcai\x0e\x8b\xca\x15Ng\xdd@\xdfN\x9fp\x11#\xc6\x18\x9b5\xc4\xde\xf7\xacc\xa4\xde\x97\xf5U\xe6\xddk\xd2\xc8p\x9e\x85mX\xfc\x83\x0f\x0b\x086I\xa0c\x9a\xbb\xc7f\xfc\x15\x9e\xf4\xf53\xbd\xc2\xd5O\xdd\xcee\x16\x94\x8f&bL\xebeM\xef\x8e\xb4\xee\xca\x1b\xca\xbd'\xd6\x92\xe2\xeb \xdf@4\xb7\x1dt\xa29\xa0#\"\xceZ\\\xd3\xe2k|3\x910\xb2\x16\x0ct\xa45\x96.\xaa\x9f*\xc1\x90\x9b=\xcc;\xf9\x9c=\xcc\x936\x14\xc9\x1b\xe41Hu\xa4m\xd9x\x82N\xe80Cs\xf5\xea\xa7\x96\x14\xccY}\x17m\xa5\xa7\xcd\xf8\xf6\x86\xd6l\x8ar\x18\xfb\x96h0\xa07\x8a\xba?^\xbf\x17\xf8!\xde\x0bx\x07+\x8b\x92\x89\xb1\xae\xc0L\x1dkZ\x01\xb5\x9b>tv\xcd\xef\xef\xa0\xa6tO\xf7\xbc\xb3\x16\xa4*\xfa\x8a0\xc1ql\x9bc[\x8a\xff\x97\xe3\xbb\xb9\x84\x8e\x91\xafRP\xe0+\xad\xa7\x11\x16\xde\xd7\xc6\xa0\x8a\xa6\x93\x90\x96\x0e\xaeb\x0d\xe4\x92Q>Xd5\xaeI\x07MQ\xf4mK}\xd1\x17\xd5A\xa6;r\xf5\xb7\xb03u$Wj\x82\xf3z\xf1\xfa\x06\xcb\x93\x1f\xfe\xac\x1aO\x0f\xa9En\x9a`\x80zp\x9fH\x97\x8b!\x88\xfe\xc3\x9e\xea\xb5}=\xfe\xf9\xff\xb2\x06.xE\xbaN~\xd4\x0f\xe4\x8a~\xa4\xbf\xf6\xb4c;\xf9\xbbeDn\xf0\xf8\xe3\xdc\x1co\x02\xbe\x7f\xe9\x18\xd0\xcb\xcb\xb2(i\xcd*s\xd5D\xa0V\xd1\n!#\xc8\x87\x13\x951\x18^\x1f\xf1?u\x7f\xb8\xa0-\xef|\x8adj\xa0EK[\x0c\xdf\xacj\xc1;\xed\xb90b\xaf+\xb7\xa4\x83\x8e\xb2\x13(Y\xc7\xfbP/\xe6\xcf\xbe\x96\x1da\x0f\x0d\xbb\xa6\xedm\xd9\x85\xc0H\xc1\x19p\xc1t\xac,\xcc\x98\x83\x87G_\x16E\x7f\x10\xc3v\xff\xda\xda\x16$L\xc2\xd8N\xe2!\xe6\xe1-P\xb9\xdd\x8b\xa1D\xdb\x13(H\xcd\xe7\x16cFg@\xea{\x01WL\xee\xae\xae\xe3\x91\xdcW\xbfIVk\xeb\xa8\x0f\xd6Q\x97z\xe0\x83\xdf-\xedeq\xb9\x93\xfa\xea\xe8\x92%\xf7Q\xbf\xbf\x89v\nt\x85t\xbdK\xe7\xd9HK/\xf2%gz\x91\x99\xfc\xc7\xf5\x9e\xa3\xfa\x94\x9a\xff:\xdd\xa5\xbc\xac*-\xa15{\x83B'GW\xc1\x03M8\xfc\xf6\xf3\xbeu\xe0\xeb+\x02\x00/\xe1\xf3\xc7\x9f\x9f\xb7\xb4k\xfa\xb6\xa0P\x93\x83b\x05\xf7u\xf9kO\xab{\xe0\x15c\xe5e\xa9\xfc^\xa6\xd8\x10\xae\xe2\x11@G\xdb\x92T\xe5_(\xb2A\x17c\xbfh*\xb8\xe8//i\xabi\x14;\xd99d\xd9\xe1\xd0w\x03U\x99/\x19\x15%\x1dsm55\x85G\xcf\x1fAqMx\xff\xa7\xedN\xcc_\x15\xe9\x18t\xf4\x8a\xcfR:\xbc\xfe\xf9\xe3\xcf\x8f;8\x12v-\x8c;\xa6\x86>\xef\xbe\x85?~\xd9W\xd5=\xfc\xda\x93\x8a\xb7\xc0^\xb6\x8f2-Z\xe2 \xe9\xa0\xac\xdd\x87\xbf\xf0W>\xbfj\x9a\xab\x8a\xeeD\xdd/\xfa\xcb\xdd\x9b\xbe\x15}\xf7\xcbSYba\xae\xbbn\xfaj\xcf\x97K^i\xc7RA\xea\xa6.\x0bR\x89\x19\xc0}\xd3\x13\xba\xbb\xda\x9d\xf0\xa6\x12\xf3\xe1\xa3\xdd#1\xd4\x1a\xc6\x17szdt\xff\x14\x8b\xca\x9c\xd6p\x14\x93GAO\x80Qr\xe8\xa0\xefz\xc2\xab+1\xf2\xc7\x92;\xce5\x9f&\xaf)\\\x945i\xefez\xf3\xfeH]uM\xd1i\xd85\xbdw_\xc5\xe7\xdc\x82A\xc9\xf8\xc8\xef;\x93:\xc3\xf8>\xa2\xb9\x84\x97\xf5\xfd\x0e~\xdf\xdc\xd2\x1b\xee=\xf0\x81\xfe\xf9\xe3\xcfj\x84;\xf6\xb8 \xde\xfd\xdc\xfeW\\\xd3\x03\x85/\xd7\x8c\x1d\xbf\x9c\xc8\xffv_\x04\xd2\xbfn\xd4\xaf'\xa2\xf7p\xff\xa4\x11\xa3B\xd4\xb8\xa3\x0c\xfa\xa3cOr\x7f\x90\xf7\xd0\xf6\x86\xb6\xb2\xca\x07r\xecdW\x10%f\xcd@\x10\x12\xebs)\xa7*\xd2\xc1e#\x96\x99\x17\xc8\xb7\xf8\x0d\x9c^\x8e%\xe4\x9f\xef\xd86|F\xd9\x0f\x95\x10\xebq\xd7\xf5\x07>\x91!\x06^\xd6\xf0\xfb\xb3\xb3\x0f\xf0\xd3\xdb3P \x84\xcf\x1f\x7f\x96\x03\xea^,\xe8\x04\xfe\xcd\xee\x8eg\xf7G\xfa\xe7\x7f\xfb\xb3c\x0e\xf4^\xa7\xd6\xdf].>\xa2%\x8fm\xb3\xef\x0b\xca\xbd\x03\xda\xb6\x8dsH\x88(\xcd\x88\xdc\xef\xc4\x04-\x96X=\xf5\x17|\xac6\xcd\xd7\xfe8l\xd5.\x08\xdf\x8365:\xad\x00\xaf\x8ax\xf75\xb9\x11\x9f\xfe`\xf4\xd1\xbd\xec\xa4D\x17\x95\xff\xffMS\xee\xb9\xbf\x89\x98\x92/\x16\xc3\xaf\xa5\x97MKO\xf4\x83\xdc\x1ea\xe5EY\xf1\xf5\x9f\xafU\x9d\xde\"\xf3)\xa2\xbd\xa1{\xc4^S\xf3i\xa8\xbe\xa2\xe2f16v\xf0\xe4sG\xb5\xc6\x1f\xaf5\xef\x1e|\xac\xcb\xfeAjr\x85\xd5\xf2\xa2\xa5r\xd5S\x06wO\x91`j\xc3\xe8\x0b`|\xce\xbc\xec\xebB\xf6`^^5\xe6\xc5Z\xc7\xf7\xe1\xe6\xee\x17o\xd6Fl\xda\xddM\xaf\x9a\xab/z\xbe\x93\xe630=\x11~d\xc9\xf4Kz\xfe\xb1\xc4&u\xe8\xf7\x17\xf4\xaa\x14{\x00\xc7\x98\xd0\xedu\xa7\x8b\xfb#\xdd\xc9\xfeH\x8ee\xb7+\x9a\x036K}\x12#\xa2\x93\x1bm>\xe0j{t\xc3\x13\x95\xf5\xa3\x87#\xbbWC\xe8)\x1c\xb8\x83\xe2\x98\xbb@\x06\xb3\xa8\x8c\xf0\x9d\x07\x17W\xfa\xce\xdd\x91\x16\xe5eY@G\x0f\xa4fe\xd1M\xbb\xba\x18#3\x96\xe2\x00\xb76\xb6J\xff\xc2\x87\xf1\x05\xd5n\x99\xb1\xd0:\xeb\xaaZ\x9c\xc8Es\x83,\xd0\xb2J\xaaKz1UV \xbe\xbc\xac\xef\xbf\x8c\n\"\xa4\x06\xd2^\x94\xac\xe5\x83&P\x12=\x0f\x92\xaa\xb1\xdaB\xeeT\xa6\x9f\x82\xcfVbB\x95%\xb9p\xdd\x0d\xf3]\xda{\xb0\xba\xcc\x07\xddq\xab\xf2B\x14O\xcd\xa3\x1dt\xfd\xf1\xd8\xb4b\x05:\x92\xe2\xeb\xf3\xbe\xe6\xff\xe1\xeb\x8e\xfc\x8e\x1d6J\xdc\x05\xb7\xb9\x84\x9e\xc9 B\x0f\xbf\x0e$\n\xa2\x94c\x11\xaehM[\xb1\x81\x96\x9b\xa3!\xd3\xff\xd2\x9a\x8f\xe4'\x98\xda\x7f{G\xc4&\xe4\xfb\x17\xf0\x81\x97\x8f\x8f;UTb2O_\xff\xf3?#\xcb\xc0\x8fM\x03\x97M\x03?\xc0n\xb7\xfbo\xce\xcf\xbc\xb2\xa4\xbew\x7f \xf5\xfd\x8e\xbf\xee\xc7\xb69<\xb9l\x9a\xa7\xee-\xbb\x9d;\xcf\x97\x97\xf0\x84?\xfaY\x14\xf0\xacy\xf2O\xfc\xd9\xa7\xf0\x7f\x90\xb9\x0d{\xfe\xafx\xdd\x7f\x1b\xa9\xfb\xbf\x92\x1b\xb2\xb8\xf2\xf0\x83\xf05\xb8\xd5\x055-\xbb'?6\xcd\xae\xa8H\xd7y**\x8b\xc0o\x96e7\x1ep\xdfe\xb5\xc0\xd0\x04\xff\x12i\x82\x0f\xf7\xec\xba\xa9\x91F\x90o\xff\xb1i\x9e\xecv\xbb\xa7\xd8\x87\x96\x0d\xf0\x04\xfdMt\x02\xd1,\xa9\xad\xc2\x1f:\x95\x8d\xf2\xe6\xed\xa7\xd7\x1fO?\x9c\xbd\xff\xf8\xd4\x9e\x14A\x99\x97\x1d\x05\x7f\x81|\x05\xde\x1c\xff5\xd2\x1c?5nK\x88\xa6x\xf1\x03\xfc\xd3\xf1b\xf7c\xd3\xfc\x9f\xddn\xf7W\xf7&R\xdf\x9fp7\x86\xdfy\x94\x8b\xf7/\xa4\xed\xaeI\xc5\x1b /(\xd6\x14\xf6\xdb\x90W\x95\x97\xd6\x8b>\xd7\x87\xf1U\xa2 \xa2C\x8a\xbb\xfe\xcb\x0fP\x97\x15\xda\xc1\xf0\xf7[=\xe9Ld(\x8a\xaf\xc3\x1c\xa4\x1dJ\xb8\xb8\x1f\x97w=K\xde\x96U\xc5\x7fP\xfcy\xbe$N\xcd=F\x96\xeb\xe7|o$\x94\x06v\xdc\xb5y\xcc}\xdca\xc6\xe6\xb3\xb9fv\xca/658L\x8duu\xaf\xfdyg\xb35\xb8MjW\xcf\xf4\x1e\xef\xf1\xf3\xc7SsjC\xa1_-w\x10T\xf5\x9eG\x97M\xb3\xbb \xad(\xf4\xdd\xf3\xfb\xdd_\x1e\xc9\x1aK\xbf\xd8u\xf1\xc5+\x1f\xf1\xfb\xf8\xf4<\xf9\xe9_?\xbd\x7f7\xfd\xcb\x0f?\xfc\xf0\x83\xdb\xf6\xfc\xbeqo)\xfd\x89\x86\x0f\x17\xb5\x98J\xff\xba\xef\x06>\xc2U_\x91vj\xc7}\x9c \xe4\xdd\xb8\x0c\x9e\x00=\\\xd0\xfd~\\\x10O\xd4\xdaj\xedH\x8d\xe5IF\xf7\xbe\xfc\x0f^\xed/*\x842\x11\x07\xd3\x8d\xb8\xd3\xc3\xef\x05\xe2 \x92\xe2+\x1f{\xe3\x86\xe2\xb2\xac\xa8;\xbf\xe91\xfa\x81\xb6]S\xa3\xddY\xed\xfc/\xcb\xb6c\xe7\xa2\xe5\x7f\x80\xef]K\xc3\x8dBFT\xdd\xf7\xdb\xf8\x8c\n\x80\xbe\xf5\x91\xa8\xff\xa3\x17\xf0\x08\xeb\xd9\xd3j\xedd\xe9\x1f\x9d`vD\xb9\xdf\x91\x03\xb7\xf5\xdfe\x11\x7f\x87\xde\xc8\xcbm\xdd\x17+\xfc\xe9\xa5rl\xa7\xdfX~\xa1\xb2\x83[ZU\xcf\xbe\xd6\xcd\xad\x8c\xf3^\x8bP\xbc\n\xcc\xba\x1du\xda\x9dN\xa4\xb3e\xf519\x11\x18\xaf\xe4\x1dG\xb0\xbeE\xb7\x99\x1a\xfc\":\xb1\xeeC\xd7M\xb5\x9f\x84\x86\xc5\x10(\xeb\xa1\xef\x81\x8a$\xa8\xae7\xb5%\xcc\x0f=\x0e\x9e\xf0\xf1\xab\xab\xebl[u\x14\xe5\xcf\xff\xf6\xe7\xa7H\xe7\\\xf3\xbd\xa7/\xc0?\xb9\xa867\xf5\xfd\xee\xb7\xdf\xff\xb6{\x84|F\xfd\x7f\x13\xafzP\xddk)\xeb\xdbZR\x04\xf4\x1f\xbb-\x1f\xbd\xe5\xa3\x1f2\x1f=\xe5b\"\xb1\xee\x14L\xad\xf1\x98\xb2\xf6\xf1\xc3k]H'\x19\x8d\x87\xd9\xb3\xc7\xd8\x93\xfa3CC\xe7\xde\xcf\x1f\xde\x90g\x0c\x9a\xfbC\xe6\xf9\x02\xe6\xd9\xc2\xe5\xde`\xf9\x8aPy\xae@y8L\xbe(H\x9e7D\xee\x0d\x90\xe7\x0d\x8f{\x82\xe3+C\xe3Ns\xbb^s\xee\xb0\xf8\xca\xa0x\xe6\x90\xf8\x8a\x80x\xeepx\xb6`x\xdePx\xb6@x<\x0c\x9e-\x08\xee\x0b\x81\xaf \x80\xa3\x01o\xc4\xebt\xe7\x9bu\xc1n$\xb8\xbd0\xb4\x8d\x04\xb6\xa3~\x92\xe3\xf8\x85W\xd0\x85\x01\xed1\x80\x8d\xb5\xefw\xf1wg\x0ee\xbb\x81\xec\x0ca\xec\xacAl{1\\\x19\xc0F\x82\xd6kB\xd6\xc1\x98\xad'\\\x1d\x0dV\xbb\xf1\xb1\xf4@\xb5\xfb\xec_\xb1\xba.\nQ\xa7T6\x16\x9e\xf6\xd7-\x1a\x9a\x9e\x11\x98\x9e\xc6!V\x06\xa5\x83!i\x7f@:\x14\x8eF[!5\x14\x1d\x0bD\xdba\xe8\x15A\xe8\x84\x10\xf4\xfc\x004\x12\xfe\x8d\x05\x9f3\x85\x9e\x917OzJ\xd6\xa0s\xe6\x90s\xd6\x80s\xcep\xb37\xd8lG\xf0\xec@s\x9e0s\xb6 s\xde\x10sZ\x809\x1a^N\x0c.\xa7\x84\x96\x9d\xc0\xb2\xfb\xb6\xd4 c8\xa8\x9c\x18RN\x08(O\x8a\x9c3\x98\x9c9\x94\x9c/\x90\x9c/\x8c\xbc\xfc\xebFC\xc8\xb1\x00\xb2\x9c\xbe\x03\xc1\xbb%\x91\xbb\xe1p\xd8\x8f\x1f^+[N\xbc\xee\xaa\xb91\xa4=\x8fMW\xa6\x83\x99\x8fJ\xa7\x1a\x11\x8aN\xc11\xef\xe5\xeb\x9a\xb0\xe69\xae\xbc\x9a\x17c\xfb7\x02\xf5\xcfC\xf4\xd7\x0b\xa0\xfc\xa75\xfb\x96P~\xd5\x81\xc6:\xe92\xebo\xad\xb4\x90j \x85\x88x\x9bJ\"\xe2\xaf\xac\x1c\x10L\xbaw\x85;\xebL\xb1\xcfCY\x9f\xef\xcdn\x0e[\x97\xfa;\xe9RN\xd5~)\xeb\xf2\xd0\x1ft\xdfQ\xc4\x0e\xdd-x\x97\xa15\xf7\xd8\xe4\xf1 \x15\xda\xd6\x81\xdc\xe9\x0f\x9dF\xb5\xf0\xc7\x0f~!w\xa2\x1c\xd2\x8c(\xc6K^S\xbeh\xd1V\xf4]]D\xde\xb0c\xc7\x85\xd3\xbad\xe5\x847/\xc3,`\x1e\x84\x08\x87\xa6f\xd7\x18\xd1{\xd2\xc5]I\x99N\x91#\xc4M\xdc\xcb\x85\xab\xe6\x86\xb65\xe1S\xbe.D\xe7\x19>\xfa\x8c\x81\xe4\x91\xb3r\xb2\x17\x81mw\x1e\xdf\xf28[\x1eg\xcb\xe3\xe8k\xcb\xe3\xe8\xc7\xb7<\xce\x96\xc7\xd9\xf28[\x1eg\xcb\xe3\x18\xff\xde\xf28[\x1eg\xcb\xe3ly\x9c-\x8f\xb3\xe5q`\xcb\xe3Ln\xdb\xf28[\x1eG_\xcb\xbfn\xa6<\x8e<\xb1\xaew\xa4\x88,\x1f\xdc=[U\x9f\x01z\xfe\xe9\xec\xe5\xd9\xe7O\xe7\x9f\xdf}\xfa\xf0\xf6\xf5\xe9\x8f\xa7o\xdf\x04\xef{\xf3\xf6\xc3\xfbO\xa7g\xe7\x1f\xde~<}\x1f\xbe\xf5\x0f\xef\xcfN\xdf\xfd\x94r\xe7\x87\x97\x9f>E\xde\xfb\xf1\xed\xbf\xbe}}\x16\xb9\xe9\xc7\x97\xa7?\x1b\xb7\x0c\x07\xb6\xa6T\xd6\x1f\xeb\xd6\x01\xccO\xa2\xa5E[\n\xcf\xd7\xd0\xfeS_A\x1e1h\xc4e'\xfd%\xd8\xe8\xc1BZ\xe2\xe8r%\x14/9v\xa4R/\xdf\x85\xdf5\xfdp\xee\xeb\xa6\xbf\x1b\x91\xfd!\x0c._\x03\xfb^L\x83\xb2(\"\"l\xbcx\x1a\x1a\xf7\x14e\xd21\xdc\x92L~N+\x88\x0c\xcc\xcf-\x87\xecvn\x01\xe4\xdf\x03o\x9e|d9\xaf]\x133\x92'Y&\x91\xd7\xeb.\xed\x16@\xff\xb2\xa6\x08\x17\x94\xd6\xd0\xd2\x7f\xa7\x05\x8b\x96D\x8e\x1b\xb7\x1c\xf2\xefkJqI\xcaj|\xfdeY\x93\xea\x9c\x91\xaa\xba?\x97A\xacEQ\xfa\xc7\xf7\xb4{\x9c\x14y \x17\x1d\xf7'\x92\xee}\\7iF\xeb\xe6\x9c{6\xe77\x945 \x0fL&\x963^\xf7\x8f\xa2\xeaF\xb3\n\xb91\xd2\xeeA4\x8dJ?!)\x16\xdd\x8e]\x7fq(\xd99+\x0f\xa9G\xda\xda\x07\xf3\xea\x84\x15\xad\xf7k\xcc\xc8S\xc5\xb74\xe7\xdfi\x9aS\x1d\xf7\xde1\xd2\xae\xea-\xca\xce\xaa\xce2id\xbd\xa4Z\x07\x14\xb4T\xb5\xcc\x81\xfb\x83\xad\x9a_<\x03!\x90j\xfcd\xf8DN\x11M_(\xc5\x0f\x8a-\xa5\xde\xdb0\xff'\xe2\xfbD\xfd\x9e\xa0\xcf\x93\xec\xef\xe0\x1d>\x87\x9f\xf3\xad|\x9c\xd8Gy\x08\xff\xc6\xf2)\xbe\xb9_\x13}\xff\xc3\xf83\x96/\xf3-\xfd\x18\xdc\x87\xf9V\xfe\xcb\xe8\xbb S\x8d:hH\xf4\x8f\xd9\\S\xcf\x82\x99\xe4\xfc\xa0\xe8\x08HI\xbe8dc\x04\x16\x170\x84-\xa9\xd8B\x0f\xff\xb8\xe7Y,v\x06\x1cKk<\x02\xc7X\xe6S+&\x1ePV\xa0\x1dX`\xbb \x0e\xd5\x1a\\)0T]\xd8D\x14\xaa\xf9\x9a\xf9\xa7Fh8\xd4\xc3\xba\xbd\xde\xe1\x1e\xec\xc8\x01}\x01\xcf\xa0_\xe8K\xff'>$5\xdfd\x90y:x\x90\x83P\x7fg\xab\x84\xaf\x9a\x16\xa6\xfdKN\x11h\xb7\xd7\xe5\xd9tK6\xdd\x92\x87\xd7-\xb1\xd7\x82\x19kN7k\xd1Yx\x1e\xa4\xda\x87\x07\x8f\x85\x9c\xdc\xe3By\xe5\xe9\x90-\x95\x870\xb0F\xdd\xbfh4\xe8W!\xe7\x19y{\xd0\xa4\xac?\xd3\xfa\x8a]\xebt\"\x8a\xae\x1e\x90\xd5\xa1:OoJ\xa8\xb4z`Q\xadQ`?l\xce\xf0\xf2\xf5/\xeb\xea\xb7\xde\x19\x06\xbb\xf2\xab\xe8\x01\x10\xa1\x08@\xf2hq\xe1q\x19\xe9\x02\xe0\xa1\x0c\x80E\x1b\x00\x19\xa3\x0e\x8fG\xf3\x96\x84\xd1(n_4\x16\x7f\xed\x9b\xb6?$6\xe6R\x10\xa2\xfa\xfaG\xda\x16\xb4f|5\xe5\x13\x96X\xcd:F\xbeR\xe3\xe0\x89\x9b\x86Q\xd5=\xe4\xf2\xe6\xae\xce\x17\x0e\x94\xb5h\xea\xae\xdcS\xde!E\x90\xcd\xec9\xec\xba\xa5\x1d\xff\x9e\xdf\xa8\x8e\xbc\x87\xb4La<\xfeD;Q#I\xff0\xfb;\xf7Fv\xf0FF\xe9\xf0^\xf4\xff\xec\xfe_\xb3\"7\x945\xe7\xdf\xb86\xd2\x15h.\xe1\x0fT}\x1b1&\xc4\x11\xe6\xea\x9f\"\xfdnW/\xfa\xc5xe\xe8~h\x00]\xe5\xef\x9f\xff\x0b\xb2\xab}\x80\x03\x86]\x7fB\x15~\xb6G\xa1k\xfdb\xc9\xe8\xcb\x18\x8arH;\x10Z#\xfd+$\xf3\x9ca\xb2z\xb7\x97\x91\xcc\x03\x91\xb3Lr\x92z '\xb1\x07\xc2'\x9a\xac\"\xf8@F\x92\x0fD\x89>\xb0\x94\xec\x03k\x08?X\x8b\xdd\x1fE\x7f\xf1\x9en\xb2\x82\xf8\x83\xd8\x92\x8e\x94\xf7\x84\x93u\x04 \xc4\\\x7f\xf4\x9er\x92\x9b\x08\x04\xeb\xc9@\x90\x9f\x10\x04\xebHA\xb0\x8e\x18\x84\x0fQ\xb4\x90\xd9\xe8B\x90\x9d2\x049iC\x90D\x1d\x82\x9c\xf4!\x08\x9e\x86\xb2\x8eF\x84\x8dq\xf4D\x149\xd5D\xc9E\xb0\x9a`\x84\x18\xc4\xceEYL;\x02\xdf\xd9(\x91%>p>J\xca\xfa\xbf\x90\x8a\x84M{\xdeSRb\xe5XGK\xb2\x8c \x92\x12zVJ\x16z\x12\xe4\xa6(\x01BS\x82\xf5T%\xcb\x1aCNMYG^\x82\x18\xa7\x07Bg\xa7$\x10\x99\xc0wh\xc3\x0cB\x93\xdf\x86\x03h_En\x82\x19\x8d\x11#9A\xb4\xdeQ\xb2\x13\xcc#<\x01z\x02\xc0J\xe2\x13\xc4\xc8O\x109Y%v\xb6J\xa0\x95R\xc9P\x90@\x88\x02\xf4\x8c\x95U\xc4(H#G\xc1\"\x82\x14x\x1b&J\x94\x82|d)\xf0\x97\xc2\xe9iY\x89S\xb0\x92\xe0G\xfc\xe7\x01B\xeb\xeb[\x01\xa2\xfd\xef{x`\xb4\xbe\x10\xd2\x15^\xa4\x07\x06J\xcf.\xcf\xc3\x00\xa7\x87b\xb8d0\xbc\x18\x0f\x07\xa4\xd6\x97\x9f\x14\x86\x97\xe8a\x80\xd5\xfa\x9a\x92\xc3 B\x10\x83e\x19!\x84,\x06\xe1X\x11J\x1a\x8b<\xe3\x92\xc7\"\x0f\xf8Id\xc1\x07\x1f\x80L\x06>BY\xb0 >\xaa\x10\x18\x98\x1d\x97/\xb4\xd8\xa4\x87h\x06\x1b\xec\xe6\x1f\x08v\x13\xa0\xab\xc1\xd2\x8e\xe3\xa5\xae-\xb4\x98\x9d\xc6\x16\x04$\xday\xfd$\xe0\x80.\xd4,@\xa2zh>&Q\xd7\xe5\xff6\x1c<\x8a8XYUy\xad@9xq\x0eQ\x97\"\x88uH\xf38\xf2\xe1\x1d\xc2\x88\x87xi\xb2\xa2\x1e\xc2\xb8\x87l\xc8\x87\xb5\xd8\x07\xc7\x9c\xf0hP\xe7!/\xfe\xc1\x87\x80X\x8f\x81HH\xfc\x07q\x10\x89H\x08o:u&\x1a\xc2o\x07\xc91\xad\xc6D\xcci\x9c\x14\\D\xbc\x15\x92\xb0\x11\xb3\xd1\x11x\x06.\x03B\"\x01#\x11CI\xc4q\x12\xc1V\x9b\x83\x95HCK\xe0x\x89\xd5\x88\x89d\xcc\xc4R\xd4\x84\xbf\x99\x92\x90\x13Y\xb1\x13\x81\xb2 =q\x15\x82\xc2\xb1\x86 *\xb2b*|\xa8\x8a\x95\xb8\n\xb7\xc8.\xce\"?\xd2\"\x82\xb5\xc0\xd1\x168\xde\"'\xe2\"3\xe6\xe2!P\x17sp\x17\x89\xc8\x8bY\xd8\x8bt\xf4\x85\x07\x7f\xe1\xcb\xb8\xa7\xe7\xdc\xe3\x18\x8cY(\x8cd\x1c\x06Z\xa1\xdcX\x8c\xbch\x0c\x0f\x1e#7\"#7&c}\x1fI\xc2e\xa4!3\xa6\xd8\x0c\x1c\x9d\x11\xdc\x83a\x08\x8dy\x18\x8dx\"?\xe1\x81\x10N#\x19\xa91\x03\xab\x91\x88\xd6X\x80\xd7\x88!6\xf2b6\xbe=j#\xfe\xb9\x1f\x12\xb7\xe1EJD;\xd5\xc3a7f\x95\xe9a\xf1\x1b^\x04\xc7\xdf\x06\xc3\x11Cq|{\x1c\x07\x86\xe4\x88c9\x16\xe7\xda<\x88\x8eX2\xde\x87\xea\x88<\x87#;\"\x0f\x85\xd1\x1d\xe9\xf9\xff|\x08\x8f\x00\xc6#)\x83\x8a\xe5\xd6cH\x8f\x15\x86\x03x\x0f?\xe2c\x93\x1e\x9b\x8d\x01\xc9\x8c\x02\xc9%=\x16\xc5\x82\xac\xe8ZAD\xc8b\xbb\x0f\x80\x0b\xd9T\xcf6\xd5\xb3\x87Q=\xfb\x0f\x14d4O\x9eD?4\x0bfd\xacg\xb3\x81Fb\xb1\xb3AFI\xfd\xf7?\xf9y\x01\x01|\x19\xf2=R>\xbexl\xd6\x87\xffC\xc3\xe8\xec/~\xd30Gk>\xe9\x83{\xc1b\xf3\x878/C\x9a>\xb2\x04\x9d\xa0$\x8e\x87\x05\xa7\xca\x17\xcft3\xc1\x1b\xa6\x00\xb1\x83\xf8\xc3\xfb\xb3\xb7\xe7\xef?\x9c\x9d\xbe\x7f\x17\x0cS\xb8w\xff\xe9\xed\xa7\x84\xbb^\xbe\xfat\xf6\xf2\xf4]\xc2\x9d\xef\xde'\xddt\xfe\xc7\xd3\xb3\xdf\x9f\xff\xe1\xed\x19v\xfb\x10pH\xafV\xdc\x0b\x03\xe0\xbd\xfa\xbd\xb8\x05\x0f8\x0890\xd5/\xf4(-o(\x8eeA\xc7/z\xa7\xff\xf3x+hL\x1eu\xf3\xac9\x9aE\xf3\xe4O\x9c\xaf\xfa\xc2\xfe\x83a\xf4^I\x85\xcd1\xa9\xba\xc0\x0b\xec\x8f`\n\xcb\xcaIy\xb6\xfdw\xef_X\xff\x9e\xb4\xc2\x02{c\x1f\xb3-\x8f\xbfL\xdf!\x9c\xf2\x1b-?\xe6}\xdb--\xaf\xaeW!\xc5\xff(,\xd0\xbd\xd1%\xc7\x82\xf4u)0y\x83<\x9d\xf8\x9f\xeeX\x99\x12\x98\xfe\x08\x1b\xb7iX\x935\xa9\xe3{\xce\x97\xf2I\xa1o\xd71;\x98p\xfa\xe6D\x87\x7fh{2\x1c\xca\xe8\xb4\x93+\xa6f.&)\xcb\x95(E\x9a\x90\x1a\xbfu>\x06Zh\xc9\xd9+\xd5\xdf9\xfe\x19Y\xd8\x02\xa6\xd0\xc5\xed\xdb\xee\xc4\xfd\xcb\\t\xa1\x0b-us\x17\xbb\xd4\xe5n\xce\x82\x97\xb8\xe4\xcd\\\xf4\x16-{i\x0b_\xe6\xa5o\xd6\xe2\xf7\x8d\x96\xbf\x07Y\x00\x1f~ \xcc\xbf\x08~\xc3e0\xb4\x10\xce \x9a\xad_\x0c\xc3 \xa7\xa5\x0bb\xae%\xd1)\x9f\x143\xd5;\x7f\xfe\xcc\xaf=mK*\xc7a\xb7\xc5\x93\xb6x\xd2C\xc6\x93\\\xd7)\xd5-K\x10\xb8\x15\xc1\x86\x0f\x86\xdct\x82Cf\xebB\xa3\x9f\x02\xedW\xfea\xbfV\x07\xda\xd2\x11\xf6\xa9>#\x1a\xc9\x0bK\xff;\xb4\xf4\xed\x02\x85g\x17\x88n\xa8;\xfb\x94\x9d\x17\x96\x1am\xf3\xa5J\xceV\x9b\xcf\xd2m6\xfa\x9d5\x19\x8a?\x89\xbe\xcco)\xeb+U\x84\xa6\xc6\x16\x80.\xd4\xaf?\x1a\x89\xd1\x84~mE2\x91&v\"\x98\xc8=\xd3\xc8%r\x03\x1e\xb1tn\xcc\x1c\xa9D\xda\xe8\x0fC\x040\xa1q\xd0-R\xb0\x17N&`kC\x84<\xe8l\x82\x1eb\xa3\x87os\x02\xbe\x8f\x0fl\x94\xea\xf3\xc7\xb73i\x1b\x99\xe8\x16&y\xf32s\xdb\x12\xdb\xb0d\xdb\xaa$nR\x1e|{\x92yc\xf2\x90[\x92\x9c\x9b\x91o\xb2\x0d\xc17 \x9e\xe1\x97q\xd3\x81\xaf\x81K6\x1a9\xb6\x18\x9e\xa9\xf8\xbd179M2=W7X?\x0b<\xe0\xd8\xc7\xfbzY_\xcd\xdcsxN\xc3B\xa7\x8eI\x87\x8b\x9e\x825\xb9\xdb,\x9b\xcf/U6\xe6\xf9\xa3\xee\xfc\x95\\u\xdbgA\xebl\xfb)\xb19\xc2\xbdg\xea\x9b\xc4\xbc\x92\x80?\x92\xe0\x89$\xcd\x1b\x10\xf4>\xf2\xcd\x1f\x80\xce!nM\xb2\xcd#\xae\xe9\x85s\x89k(\xc7|\xe2Z]2\xa7`V2\xce+\x80x\x13\xe1-\xd4\x1a\x0fB\x0d\xe8CY\xb3\xf18\xfcy\x13\x18\x7f\xf6\xdc\xc2;\xa2#Y\x05\xa9\x98\"E\x17M)\xe8\"\xfcyuOY_V\"^x\xce;\xfd\xb9T$H\xb3zP\x87\x9a\x91\xba\xeeI\xa5\xc4\x0c\xa0\xacG\x9b|\xabO\x9d\x17\x1d\xc8\xdd\xbc\x17\xc4\xecE6\xd1\xa3=\x15\xa3@\xed]5\xa4:\xbfh\xea=\x8d- \xca\x1a\x7f\x807\xaa\x8a2\x81|\x16\x08k\x0e\xc3\xa9\xe8US|\xed\xf8Bs~OIx\xcb\xea\x0d6\xaa\xd7I!\x17\xbaWF\xf9k\x81\x1bu;\xa7Zq$q\xc88\xc7M\xc7\xf4\xf8\xd7\x87C\xb3\xef+\xea\xeb\x8f\"\xec\xf7R|\xd7\x0fmsSv|\xe6\x9b\x9dl\x95\x1d\xe3\xfc8XHl\x00\x7f\xc8\xc9\xb1\xa8\xa3\x97J\nC\xd4M\x90\xadd\x9f4n\x14\x11\xa4\x90\x07\x1f\xacs0Jj\x1axn[\xc0\xc3\xa6nk\x9f\xeaN9\xbb\x99\x87\xee\xbc\xbay\xc7\x81\xe1i\xd6\xf1\x86\xb4\xe6t*\x95\x12m\x1e\x1e\n\xe1\xd6\xdc\x06\\xRk\xf0x\xc4\xf0\xc1\x88\xca\x0f\x1c\x87\x92\xd9\xf8I\xf9\x15l\"\x87P\x10)>\xa1C|ROy\xc3\xbc\xc9\x1d\xfc\x13\xfc\x9c\x97\xa5\xd8N\xc4|\xa6M\xfa\xe0\x9b\xf8S,',\x00\x10Z\x04\x82\xef\x88g\x9e\xd2\x17\x84\x078\xd7P\x0e\x8c\xa9\xff\xf2\xda\xe8f \x03\xaf\xeb/\xba#)\xc2\xce\xc6$\xf7\x88\xfcn\xa5;\xc2^\xdb07\x19\xc55\x1d\xd9\xb2\xde\x977\xe5^,\x1cz\x94\xab\x9e/Y\xf5R?\xcd4\xc2o\x91\x86>\xb8\xf1q\xab\x91V\xcfR\xa1Ij2G\xe9\x94\xf2P\x8bE\x93\x93\xfb\x81\xc0\xdfcS\x93\xc4\x88PR\xf8\xa3y:\xef\xd2\x8e\xdbU\xa4\xbb.\xeb\xab\xa5\xaewW^\xd5t\x7f\xae\x06\xf5mY\xef\x9b\xdb\xc4u\xd7\x1c\xc9\x87\xb2>W\xa6\xf8\xc40\xcb\x8e\xb1~\xef\x9b\xdb\x9a\x95\x07z\xfe\xef\xa4\xac\xce\xf7\x8aR\x1d\xb4#\x1a\xe0\xfcR\xc8\x106\xf5\xf9\xbe\xe9/**\xca2\xff\xf5\x8e-Y\x9a\xb9\x860\xefu \xd5;\xab\xee Dv!\x93\xfe\xfa\x8b\xba.\xad\xf3\xadW\x8f@\xc7\x83M\x1bH\xc1>\x03)\xcb\x80\xbd\nD\xfaO\x92M\x0b\xa5\x11\xebK\x01\x9b)}*\xf0\xb8\xb7H\xd1\xfe5\xdfh\xf6\xbe6\xac\xc7\xb9V\xd9X\xff\xfdT^\xd5e}uZ_6\xb3;\xf1\x0d\xa9\xc4g)\xeb\xab\xf3\xb2\xbetR\xc6I\xdd\x99\xec\xf7-\xed\xba\xa4\xaf Y\x81\xd7H\xaa&\xfa\xd9\xbc\x8e\xcf\xef\x855 \x9a\xf0(bt\x845\xad\x00\xc6\x08q\x11 P\x90z\xcf\xffL\xe1\xfdG\xf1C_\xff\xbb\xe0>\x1b&\xcbzO\xef\xce\x9b\xcb\xcb\x8e\xae/]8\xb9y\xca_\xa5\x19\x9a\x1d\x94u\xd1\n\x92&\xdd\x03%\xc55\xf0~=F\x1c\x87\xda\x10\xe5U\xda\xc9\xcb\xb2\xe6?\xf1 E$\x86\x0e\xe4^\xeag\xca9A\xa4\x91h\xd1\x1c\x0e%\x93\xc2\xabL\xe9\x01;\x82uES\xff\xbb\x12\xa3\x93\x012D\xd8\xf5\xcb'a\xf5\x95\x98\xbf\xfe(\xa6\x9a/\x83\xd7\xc1h{\x18\x1c\x0f\xd1\xa0\xb8\x06\xe5\x97_\xca\xae\xd3F^\x95\xece\xdb\x92\xfb/f\x88O~\x9e\xf3\xbef\xe5\\|\x96\x8f\xf3\x1c\xfa\"g\xe5\x81v\x8c\x1c\x8e \xde\xa8\xbe\xcd\xf4\x13\x94\x9d*\x15\xec{\xca7ZUyCk\xda\xd9\xbcz=3\x99\xd5a\xcd\xe1\xa2cM\x8do+.\x9a\xa6\xa2\xa4\x9eQ\xde?^S!\x82)\xbf\xa7\x96{\x14\xc5\xbc&\x9d\x94\x1a\x18\xdf O\xbe\x96\x15/x\xd33hl\xa0\xd9\xf8hG\xd9\xd3\x1d\x9c\n\x99\xcf\x8e:*\xcdM]\xd8\xddRv+\xe10\xd3_\xfb\xf2\xa6\x91\x1a\xb1\xbc\\\"4^\xdfK\x00\x9a\xdb\xd1.\xcb\xab\xbe\xa5{8\x94\xdd\x05\xbd.\xc9\xcdT|\xf6 :\x88^&\x05\xfe-\x91\xd0\xb5|X\xbe\x04\xf5\x1e\xf8J\x8fl\xd4\x97\xed\xeb\x9a\x16\xb4\xeb\x84\xfe2\xef\xa9\xd0R\xb2\xef\x1c\x10\xc1\xbb\x86)}\xef/\x9f\xfa\xc3\x13\xac\x8f?\xfd\x02\xa4\xba%\xf7\x1do.R\xd9]g2.^\xcb\xc2\x18\xc3\"\x90\xb4\xd0_\xc4X\x10\xcc\x0c\xb4\xfe\xf9q\x07j\xca\xe7{` \xbc:4u\xc9\x1a\xab\x15\xd95-'\xb2[\xba\xb3\x03_\x7foJvol#\xe4Tl\xaf'z\xc1\x9b\xbcP`\x1f\x05\xa8Q\"\xe8D\xc2[\xaf\"\xdf\x19\xd6\xa6\x8cGd\x9dKYO\x8d\xc7\x94\xb5\x8f\x1f^\xebZ\xcd^a\xe7\xfb\x89\xd8\xb2\x9a\x17w\x84\xae\xbf\x81\xb1\xe1_\x83\x03\x0f\x85\x86\xd4\x03\xac\xc4\xa1\xb5xq)cp\xa3\xcckr\xc6U9m]\xce\xb42\xa7\xac\xcd\xa1\xd59\xe9\xfb\xe0+t\xfc\x1b\xe5\\\xa5\xf1u\xda\xbfR\x87\xd6\xeax\xc9s\xae\xd73V\xec\x9ckv\xca\xaa\x9d\xb4n'u\x91%Cx\xed\xfa\x9dc\x05\x8f\xae\xe1\xe1j\xacX\xc7\xa7\x9faX\xd3\xdd\x95\xf9g\xf5/q\xcfrFi\xfc\xb3wF\x0fr\xb9\xefh\xfa\x8a\x86A\xcck\\\xed/\x86=E\xdcG\x0c\xb6t\xe4\xdc\xb6Ik\xe7\xf2\x05m/\x10\xf3\xffp\xcf\xcf_\xb6\\\xde^\x92\x9f\xb7\xc2\xc33<:\xc3 \xe2\xdbE\xbc\xba,\xc3g\x8d\xf7\xb6\xceo\x0bxl\x1e\x88\xf9r/\xcd\x8d\xb6L\xfc3\xd43\xd3S7\x13\x07\x05\x0d3\xf7\xab\xa6\xde\x7f24\x8e\x9d\xaf0\x85\xf6\xbfz\xff\xee\x8d_\xb0\xd7\xfe\x9d\xff+\xf8\xe3\xe9\xbb\x9f\xd0_\x8d\x07\x070n\xe8\xd5\xb8\xc70\xd6m\xf0B\x0de\xd3\xa1\x81Md\xbe\xe7%/\x00E\xd1\xd6P\xd6\n\xcf;\x0e\xb2\xa9\xca/\xde$\xdc\x9e\xfc?\xec\x8b\xcbN\xa8NI\x92\xf3z\xd0\xde\xe9\xbb\x9f\xb4\xc1\xd3w?\x05-\xf6\xf5\x85\xf4w<\x06u\xf1\x12\n7\x16\xcc\xd3\xb5^\xf3 \xa4\xeb\xca\x19`\xf2bxD\xe0\x8c| \xaa\xc9\x90\xb7\x9f\x99\xe0\x16\xc4\x11m\"@\xa8o\x02\x05\xc5\x16\x9e\xa3\xce\xc6\x99\xe6ZJ$\xe0\xcf\xec!\xfa\xd7\x19\xbb\x11\xfe\x9eD\xc7}R\xb9\xc7\xfc\xc1\x01.7-\xb78C\xf1J\xee4\xf6\xb4\xa2Wb\xf7t\x02\xc2\x03\xd0Y\xcd\xddc\xc3\xf8\x81\xdc\x9d/-\x89\xb3[\xd0\xc6&M\xac\xa1VvQm\x07\xabp\xe2\x1d\xf4F\xa2a\xda+jW\xc1\xaa\x81\x84\xcc\xe4\xad\x88a\x13\xad\xcf\x9e\x94\xd5\xbdt\xc0H\xe79P\xd3Z-E\xed=U\xe9\x8f\xdc19\x9f\x81f\x8882\x86A\xdd[\xc4\x91\x9a\x83\x87\xe8|\x10\xd2)\xec\x11\xc6-\x19G\xeb\xd0\x1a\x86\x01\x0b\xf4\xab\xd9\n\x93\x11\x12\x9d\x06>\x8eC:a.\x98~l\xb4\xa5\x1eh\xdc\xb8c&\xfe\xf6I\x17[;N\xc4\xc80\xe7\xa4\xd0\x18\xf1\x8e\x8f\x05\x85^4&\xc6\xb2\x9bE\x0e\x8f\x07\xbc\x18VWY1\x93\xebY\\/\xed$\xa9\xab\xbe\x91]c\xce\x8a5\xf4\xa6\xf3\x94m\xacUq\xe7a\xdd}/hq\xfd/\xbf}F\xeb\xa2Q\xe7}\x88_\x87\x03j\xd4c\xba\x0b\x0cu[R\x08\xe7\xe1\xb4B8\x8bcwMZ:\xeb\xcd\xf2 \xf5\x95\xcd\x9a\xf1\x8f\xab~liA\xcb\x1bt\xc6\x1a\xfc\xbc\xf1\xb3\xd9\xc0\x1b\xee\xa3\xa8mk\xf3\x95\xd6\x1d\\\xd3J(O\x93\x1aH!\xb6\njC\xa4L5\xb7\xb5\x94\xa6nj\xa3\x9d\xd5\xc9\x95\xe2,\xd6\xa6(E(Go\x86\x07\xd2^s+#gMM\xed\xcf\x92\xd4\xe5f\xe7\x05\xf7VoE\x1f\xc3\x1f\x85p\xcf\x85\xe4\x955W\x0f\x86p/N/P\xae\xde\x0cH\x8fN/\xc5\xfc\x9e\xed\x98\x98\xc4=3\xf6p\xc8\xdd\xcb\xc1\xee\xe9\xfc\xba \x15\xa9]$vb\xc7Le/`2\xfb\xf1ig\xd2\xb2\x8b\xe5\xf4G\x13kT\xf4\xc7\xd0\xaa\xbe\xd2\xa4\xf2c\x13\xa1\x19\xfb\x15\xd1\x1bR\xd1Z\xc4C\x8c\xaeD\xef\n\x11$\x11\x1b:f\x1c\xb3:\xfd\x88\xf6\xd1P\xaa\xff\x0e1\xcaC\xd3R\xe8\xfa\x92\x894\x01w\x0f\x8b\xaa\xe4o\xd3\x01\xe7.8\xff\x8d\x15I\x9d\xf8\x0eM]~\x8d\x86\x8e&M\xa4\x1e1\xbe\xf4u\x7f \xf5\xb3\x96\x92\xbd(\xb68\xdbL\xc7\xc4\x9d\xee,O\xd8ga\xe6@\xc8\xb9\xd2\x06\xcc\xd8\x81\xa4\x8b\x92j\xfcq\xf8\xf6\xf0\x84\xde\xed\xe0\xf3\x87\xa6e0q\xab\xfe'\xbd\xbf \x1d}\xaa\x0bvK/\xbar\x9e\xd3\xa7\x1eAK\xa2\x7f\xab\xca\xfa\xeb\xb0\xae\xd3\xa2oKv\x7f.\xfaG\x11\x0bxO\xe7A\xebY\xf4\xa5\xf4@Jq<\xfep;\xa8\xdbu\x11\xf6\x94\x91\xb2\x9a\xe5[\xa8G\xf4\x14,#\x95\xc3+\xd5\xaf\xc8X2\xfa#\x1a\xfd0n\x0e\xf4\xea\xdf\x97\x1dk\xda\xb2 \xd5\xacL\xc85%{\xb7_'M\x9a\xea\xd8pk.\x94I\x8f\x0b\xd2\x95\x85\xca\x04\x94#\x8a)\xf0\x0e\x08\x80\x85\x14\xff\xc8\xfec`i\x84pn\x12\x80\x1c\x8f\xf9\xcc\x85w\xfe\xaf\xf9\x84Tw}\x07\x059\xcaiV\xee\x17\xf5\x9f\xdb\xbe\x1a%\xd1\n\xdau2\x16\xa4[\xcf2'\x96`\xfeSqM\xca\xfa\xc4\x05\xd5\x16U/\xcf\xea\xab*\xe3F\xbe\xb7'\xbcn}!\xcb\xa0\xb5X\xe4\xdb\xd1X\x03\x19O\xcf\x7f\xdc\xd9/\xea\x18\xdf\xb2\xb1\x96\xd4\x9d\x9c\xa7\x0f\xa4\xb8.\xeb ,E\xbc9U\x16?\x0b\xc0z\x01\xb4\x1eC\xf5\x88\xc3'E\xe3\xb9\xa5\x97=\xfc\xd8\xd2\x9b\x8c\x1d\xfc\x9at\xd7\x0b;$r\xec\xfa\x91\xb4\xec\xbc\xa3\xec\xdc\x1e\xde\xfa\xf2\x96\x10\x82\xa5\x14\x8f\xba\xf0\x80\xe1'a\xb5\xac\x19\xbdB`8\x10\x81\xc9\x80\xb7\x19 \xd6\x14\x10n\x8e\xe1\xa3} -\xeb(\xfb\xbdh\x15\xfbs\xcb\xec\xd3\xb9[\x84h\x0f\xf2\xc19\xb8)9\xb6dG\xe1C\xd0\xb8\x8f\xff3\xc3\xebFLK\x06cv\xd9/\xdb\xe6 \xa6 rD\x18\xbf\xfb\x1e\x7f\xa5T!\x80RD+$?^\xbb\xe8\x8c\xde\x89O\xf9\xb2\xbe\xdf\xc1\xef\x9b[zC[\xc9\xa3\xff\xfc\xf1gw\xec\xf2KF)\xd49\xf9\xf8\x0b\xbb\xe2\x9a\x1e(|\xb9f\xec\xf8\xe5D\xfe\xb7\xfbr\"\x817\xea\xd7\x13\xd1\xcb\nc\xdbZ\xdd\x0b\x0c\x0df\xb0?\x02\x11u\xf5\xbc\x8f\xb67T\xe5\xd1\x0f\xe4\xd8\xc9.\xc3k \x847\x14\xaaP\xccW\xc2\x97\xef\x009u\x15\xc4*PU\xcdm\xf7\xc2\xf3\xed~\x03\xa7\x97c\x0d\xf8'\x17\xe25{\xba\x1f*\xa9\xa2}\xfd\x81\xee=G.\xfc\x06^\xd6\xf0\xfb\xb3\xb3\x0f\xf0\xd3\xdb3hj=\x8c\xe4\x00\x95g\xfe\xe3=\xd39\x08\xfc\xec\xfeH\xff\xfco\x7fFoV4~\xfe\xadU\x1f\x92K\x9c\xf8\n\xc7\xb6\xd9\xf7\x05\x15H\xa4\xb6\xb5\xc1\xe2\xfa\xfa\x0d\xbc\x1cwH\x1d\x90\x96\xf2~\xd8\xdc\xca\xac_A\n>'4\xcd\xd7\xfe8@0/HG\xf7\xd0\xe0\x07S\xf8\xa67\xe0\xd5\x17\xe5\x12h:vM\x0f\xc6X\xd8\xcb\xc1@t5\x06\x04\x12\xa9\xedcR\xf4%\x0b%\x86}K/\x9b\x96\x9e\xe8\x87\xb9M\xc2\xca\x8b\xb2*\xd9\xbd\x90\x18\xd7\xe9.1E\xb57\x16\xe3e\xbc\x9aZ\xa5z\xc5\x03b\xdc\xed\xe0\xc9\xe7\x8e\xea@\x01o\x15\xde\xed\xf8<#\xfb\x1d\xa9\xc9\x95\xaf\xc6\x17-\x15\x01\x0emt\xf7\x14\xef-\xef\x1aF_\x00\xe3\xf3\xf8\xa5\xc2\x0f\x12Qv5\xdf(\xf5\x9f\xea\xde\xc4\x15\xe3\x0c\x12~5\x02\x12\xedB\x8a\xe5\xa5;\x16\xb4\x94\xaf\x0eT\xc5\xaf\x07\xe4\xcc@\xb5\x1e\xc7\xd7\x05\xbd*\xeb\xda\xb7i\xb9-\xd9\xb5g\xd2w\x8f\x9f\xf7\xcd\x98\x9f\xc4h\xebT\xc4\x89]\x93\xda\x9eY\xe0\x89\n3\xd2\xc3\x91\xdd\xab\xe1\xf9\x145v\x10h\xd5\x0b\xcfD\"*(b\xd5ClYe\x18\x8e\xb4(/\xcb\x02:z 5+\x0b\xe4\xd4qD6C^\x11\x97\"\xb8\xb3K\xf38~\xe1S\xc7\x05\xd5q5\xc3ap|\x03\xb5\xa8\x92\x8b\xe6\xc6\xe3l\xc8\xaa\xaa\xeelW3V\x9a//\xeb\xfb/F\xe0\xbb\x06\xd2^\x94\xac\xe5\x83/P*5G;\xe6H\xd5\xd4W*{\xe0~2>k\x8aI_\x96\xea\xc2u\xa7\xccwj\xaf\x08\xe9f\x1ft\xc7\xaf\xca\x0bQT5\xafw\xd0\xf5\xc7c\xd32)\xe2_|}\xde\xd7\xfc?|\xbd\x94\xdf\x1b%\x86 \x8f\x06u\x1e\x9aK\xe8\x99\x9c|\xf4p\xee\xf8\xc4\xa7\xb3\x01\xa4\x82+Z\x0bq\xcb\xbd\xcad\x0cN\xf5Kd\xbe\x93\x9f\xc8}\xcf\xdb;\xc2;0|\xff\x02>\x10\x05WVE'\xc3\x82X\xd6\xf0\xfa\x9f\xff\xd9\xb3L\xfd\xd84p\xd94\xf0\x03\xecv;\x14V/\x1a\x81\xd4\xf7\xf8\x8f\xa4\xbe\xdf\xf1W\xff\xd86\x87'\x97M\xf3\x14\xbfm\xb7\xc3\xd7\x9e\xf2\x12\x9ep\x13\x9fE\xa1\xcf\x9a'\xff\xc4m<\xc5\xd9\x00\x01;\x7f\xf5\xb7\xcdo#m\xf3\xaf\xe4\x86\xacn\x1c\xf8A\xf8V\xdc\xfa\x8aV(\xbb'?6\xcd\xae\xa8H\xd7\x05\x1aA\x16\x89? \xebc<\x84\xbf\x17i\x9d\xa1y\xfe%\xd2<\x1f\xee\xd9uS{\x1aH\x96\xe4\xc7\xa6y\xb2\xdb\xed\xf0\x99xh\x9c'\xde\xdfE\x07\x12\xcd6\xb7\xd5\xf8\xc3\xa7\xb2\xd1\xde\xbc\xfd\xf4\xfa\xe3\xe9\x87\xb3\xf7\x1f\x9f\xe2\xa17\xf9*\xd9\xd1\xfc/\x93\xaf\xf37\xd7\x7f\x8d4\xd7O\x0d\xdeR\xa2\xa9^\xfc\x00\xfft\xbc\xd8\xfd\xd84\xffg\xb7\xdb\xfd\x15\xbf\x91\xd4\xf7'\xdc]\xe3w\x1f\xa5\x03\xf2\x0bi\xbbkR\xf1F\xf4\x17\xdc\xd7L\xf6\x9b=\xaf-/\xad\x97~\xae\x0f\xe3kE\xa1D\xc7\x16w\xfd\x97\x1f\xa0.+o\x07\xf5\x97\x05\xe9\x89gB\xe7\xa5\xf8:\xcc\x83\xda\xd9\x86\x8b\xfb\xd1U\xd13\xf6mYU\xfc\x07\x85nv\xac\xf5\x1d\xb2\xe6?F\xdc\x90\xe7|/\xba\x13?pW\xee1\x10cU\xe1+\x8e\xca,\xb8o\x10_\xdd}\xc90\x8d\xd7\xd5\xbd\xde79\x1b\xde\xc1u\x04r\xc9\xa8\xf4f\xf8~\xdb-\xf2\xf3\xc7\xee+\xd4\x86N\x17Q\xee\xe0\xa8\xea\x99\x8f.\x9bfwAZQ\xb9\xbb\xe7\xf7\xbb\xbf<\x92\xad%\xf7\x1a\xf8\xb6J\x14\xe5\x11\xbf\x97//\xce\xcf\xff\xfa\xe9\xfd;\xf7\xaf?\xfc\xf0\xc3\x0f\xf8w\xe4\xf7\x8fq\x00E{\xe0\xc3T9\x0cr\xaf\xd2wT\x13\xab\xae\xfa\x8a\xb4\xae-\xd7\x84\x84\x82\x8c\xcb\xfc\xc9H^S\xa3\xefD\xf9\x0fH\xf4\xc0Xv%\xc4\xe0\xcb\xff\xe0\xcd\xf1Emr\x077\xc6l\xdc\x9d\x1e\xf2/\xd0\xb6kj\xef\xb0Q\x11\x1cA\xa6:\x17_\xc6Gu\x1bo\x161\\u\xefo\xd3g\x7f\x00o)\x1e\x89\xb6y\xf4\x02\x1ea\xa3fZ\xdd\x9d\xac\xd1\xa3\x13\x9f-Q\x97w\xe4\xc0\xed\xfdwY\xe4\xdfyo\xe6u\xb1\xeeM\xad\xd0\xe9\xa5\xda\x18L\xfb\x84\xfc\x9ae\x07\xb7\xb4\xaa\x9e}\xad\x9b[\x89G\xb9\x16\xc8J\x85$\xc1;\xf9\xb4\x0b\x9eH\x07\xd4\xea\x97r22^\xcb;Z}\x85\xec\xebE\xb7s_\xf2E\x0c\x08\xdd\x0f\xa5L\xb0\x81q\x11\xc3\xc9\x02\x91\xf0\x9fU\xf7u\xed\x89\xd7\x0c=\x17\x9e\x08\xca\x8bj\n'\xac\xa0#g\x7f\xfe\xb7??\xf5t\xf2\xb5}d\xfa\"\x7f7\x11\xcd\xc0\xcd}\xbf\xfb\xed\xf7\xbf\xed\x1ey>\xbb\xf9/I-\xc3#\xc5\xcbT\x024YM\xd1ko\x15\x8dl\x12\xe8\x1e\x19d\xean\x91ER\x14B\xdb\xa0&\xcdH\x8e\xe0w\xeeOv\xe9\xa7\x10\x90 \x01\xc7\xe6\xc9\xc0\x13\xf9\xd2\xe7\x031E\xfd\x9f\x88IN\xcd\x066\xa6\xbes\x90\xc2t%\xff\x9d\x13\xe2R\xf8\xb6\x91\xc2\xe4\xbb\x0f5\x96Dk\xd2\x97\x84\xf6-\xcd\x8e(`\xa0\x0bF\x14\x911\xf1\xdb\x93\xb2.\xaa\x1dt\xb4\xba|6\"\x15\xad/0b=1`dzy\x90>k\x9b\x1e\xb35\xf2\x88=\xf9\xc7\xb2\xebz\x19\xcd#\xc1\x9c\xcd\x88\xf0\xb7+`a\xcd\xf0\x9f\xcc\x7fL\xd2F\xe6\xdf\x19m\x0f\x9d\x1f0\xa6/\xb6,\xe5\xe3 \xdc\xc6+\x12\x9e\xc9\x89z\x1b/\x17\xff6^s\n\xe4 \x08-G\xc7\xa1\xe6\x9a\xd6\xc1\xc9\x8d\x97\x83\x98\x1b\xaf95\x99\x8b\xa2\x1b/?\x9en\xbc\xe6\x94\xc4\xd3\xa6\x0b\xa1w\xa8-\x0b\x8e7^\x0e0o\xbc\xe6Ta\x06XO_\xc3z\x91W\x86*\xd6\xb2\xf6ku\xab\x9e\xf0\x8d\xe7\xf0\xa3\xc7`\xbc\x0c\x1ai#\xd2\x1b\x15e\xd4W\xe1\xc2\"\x90\x8e\xd7\xa4\xc4\x85\xcb\\cS\n\xd8\xc8^\xcb4?\xfby\xaa\xe3\x15kU\xcc\xce\x0c\xc6\x13joHy\x84Y\xac\xe3\x15\xa8?D\xc1g\x18\xc7u\xbc\"\x13\x00$6\x11\xa8\xd7,`\xf6y\xeda4\xd3\xf1\xc2)\xb3\xe3\x95\xb1b\xf3\x89\x82^S.\x810N\xad\x1d\xaf \xc9v\xbc2W}6\xdd\xd0k\x8d\xb9\xd2\x15!2\xeex\xa1\xb4\\\xc3nZ2\xcc7\xb3Bb\x83,\xe1\xf2\xe2\x13\x8a\xc9\xef\xd5\x97\x90\xf6\xa6\xd5\xe59\xc6\x18\x93\xd7\n\xdf\x1d\xb1\xee\xec\xf6\x1ewbo\x01{ZTDJ\xbf\x8934\x1cc\xea.m\xc8\xacG\xa8\x1c\x7f0\xf0\xf9\x0ef\xff\x04Xs%7\xc1\x03\x9dI\xee+\x14_Ga\x99p\x8b\x8f\xa5\xd2\x81\xde\x83\xa8pj\xd9\x02\xbdSG\x98\x88\x0f\"\x96\xb3\xb2\xeev\xf0I\x89#M\xcci\xc4\x81\x0d\n\"\xbcId\xefVQ\xd1\x89\xd9\x13 a\x10\x99\xf7\xa6mi\xc1\xa0 U\xd1W:\xa081v\xd9s\xefx\xfa\x82\xbe\x1e[\xb3\x13\xf5oz\x06%\xa3\xad\\\x1f\x9a\x1b\xb1?\x186L\xf0\xc7kZ\xcb\xaa\x00i\xa7\xfd\xd9\xdc6N\xdf\"2\xfef\x83\xdb\n:EK\xf7\xe5@(#&\x1d\xee\xf6\xba\xe9\xa6\xef\x19T\xc8\xa6/1?C9\x827\xc4\xcb\xc6/)\x8b>\x16U\x1c\xc0!\xa3\xf0\xb6C\xa2\xd0\x08\xd3\xb7L\xda\x7f\xa7\x8e\\T\xbc7>\xb3^\xd0\xe1\x13\xd0\xbd\x88\xb6\x8b\xae\xa4\x8ej\x91\xc5\x9bZ<\xf4\x15+\x8fU)\x0b1\xb5/n\xc4{\xf6\x94C2Fw%LStD\xa3\x89k9\x15\xf1\x06\xbdt\x8e1\x16\xf8\xce!\x1d\xa4\x04\x80X\xd3\xca\n\x1cI+ZN\x91X\x94\x12=\x1f\xb2LtA\xe9\xbd\x1ei+\xcf\x94\x15\x91\xbb\xfa\x8b2vhFX^K\xc5\xa95\xd3\x82\xeb\x1f\x9f|\xa9\xbf(\xe1\xa1A\xfb\xde~\xe1\x97\xeb\xe1\xd1sZ\xb3\xb6\xa4\xdd\x97\xd1y\x13\x9b9\x0f\xe1f\xe6\x99\x1b>W\x1a\x9d\x06'\x9f\xc7\xf2\x85\xd5D'\xfdb\x15\x1f\x14is\xdb\xa3\xe5\xcb\xdd\x88\xc3\xb6\xdfh\xa3\xf4\x13d\x8f\xa6\x06uA\xf4\xca9\n\xf9\x8d\xf7\x98EQ\xad\x9b\xa1\x1c\x8e\x86\x802m\x94\x08\xf4\x9fD\x9e\xa7\x143\xf1\xd0@\xe6T0\xa1\xba\xb5\xd4\xf8\xe5\xc9\x91\xb6p$e\xfb\x9c\xb5e3l\xeb\xdd\xfe\x92\xa1F\xaeQ]\x97\xb1U\xc7{\x86\xca\xb1F\x8f\x11]:^\xc3\xa4C\x15'\xaf\x1f\x9f\x9a\xf8D\xfc\xcf\"fSH\xc6\xeaHME&\x11\xdf\x11\xb1\xd3c\xfb\xa6\xe3/4\xba\x9a\xa6J\x1e[u\xc3\xd4\xe1W\xe7v\xdc\x12\xa9|\xea\x9d\x93\xea\x8d\xc7.5\x8dP\xaf\x1c\xa1^-)D\x9d\xd4|\xccg\xc9\xbaa\xcf\xd4?%\xbd\xb7\xeb\x8f\xc7\xea^\xa7\xe3\xf8O\xdf\xe9\xef0mUOs\x08\xc9\xc4,\xc4\xfd\xf3v\xf2,\xfa\x88p@&?\xcd\xe3\xa3E\xfd\xb3\x15%\xcf\xe4\x93y\x9c\x00'\xbe*/\xec\xf3\xca\xcb\xf9\xc8\xe6\x03\x8b\xc4n$\xa8\xa1\xa9=\x90\x1fyE<\xc3\xb8\xeaM\xbc\xa1\xe5e\x95F7\xb6\xfa\xd7x\x92\xc4\x18\xe9fM\xf3\xd5c\xecX\x91\xc2a/\x82D\x88\x1c+*\xde\xe3\xcbQ\xcf\xa8s(Om\xd5\xdbz\xb1\xae^_\x97w#\xc4g\xac\xdbx;V\x0b\x05e9\xf7x\x92\xf2\x8a\xd6\"\xed\xbbX\xef\x9a,\xd3\xca\x15W\xb7T\x92|\xbb\xef+\x99\xd2\xc4\xed\xa9\xad\x01\x10\x16\xa9d\xc6\xca\x05\xca\xce\x9a\xd4\x12\xc5\x9b\x0b\x99\xfd\xdf\xd6\xac\x9d\xe00\xc7O,\xc7\xacdI\xbb\xb6ZZ\xd1\x1bR3\xbe\x02\x91=a$\xb8\x95\xd2I\x13\"Oe\xc2\xd3A\xea\xa6T\xb7\x16\xa9\x8d\xccrJ7P8|]Y_U\xc6\x1e\xea\xb1q$\xc2\xc4\x18\xff\x9b\xb5\x13\x93yUe\xc1L\xbd\xf2f\xe2C\xe2Y\xd3\xee)w\xca+# \xb4y\x94\x9bG\xf9\xf0\x1e\xa5\xdd\xf7W\xb8\x96ASK|\xcc\x01J3\xdb\xb1\x1c\x06\x99\xedN&u\xf9\xb0\xba\x94\xb7\xa7\x84\xa7\xcd\x85\xbaR\xa3\x8e\x94e/\xa6*\x15\xd6\x94\xf2:S~G\x8ay\xd5\xa4\x82KT|1\xc9\xac#\x15V\x91\xca\xab!\x95UA*\xa8\x1f\xc5\xd6\xa9G\xe5\xd4\x8e\x8a+G-\xd6\x8d\xca\xa9\x1a\xc5\xe2\x9aQ9\x15\xa3\xa2zQ\x99\xd5\xa2\x82ZQK\x94\xa2\xc2\xaaP\x194\xa1\x92\x14\xa1\xe6\xa9?\xad\xd4~\xca\xab\xfc\xe4\xcbSdU}\xca\xaf\xf9\x94U\xf1)M\xef)\xab\xdaSH\xeb)\xb3\xd2\x93O\xe7\x89\xa5\xaa<-\xd5x\x92zN\x88A\\\xe1i\x85\xbe\x93G\xdd)\xb8\xc4\x07\x95\x9d\xe2\xeb\x7f>U\xa7\x90\xa6S\xb8\x1cY\xf5\x9cBjN\x99\xb4\x9c\xd6)9!# [\xca\xf3\xaa81T\xc3i\xad\x82ST\xa2(\xa0\xde\x94\xa4\xdd\x84K\xb9\xcc\xd3m\xc2m82\x0e\xab\x15\x9bR\x1b#E\xad)\\\xef$\xa5\xa6\x99:M\xae\xacE\x06\x8d\xa6\xa8BSX\x9f)\xa6\xce\xe4m\xa59\xcaL)\xbaL\x98*\xd3JM\xa6DE\xa6ezL\x1e\x05\xa4\x14-\xa6\x8cJL\x9eR8=m\x95\x06\x13\xa6\xb9\x94Qq \xd7[Z\xa5\xb6\x84\xa9+\xe5\xd6V\n*+a\x923\x98\xaaR>M\xa5\xac\x8aJ\xf9\xf5\x94\xd2\xd5\x94\x92\xb4\x94T\x1c#EII\xdd\x1a\xd5QBU\x94\xf0\xb7\xa7\xaa\xe3\xc4\x15\x94f\xe8'%\xaa'9\xd5\xc8\xad\x9c\x94S7 UM\xca\xab\x99\x94W1i]\x7fHRKJ\xd1J2\x97\x15L'I\xeef0\x95\xa4\xf0.!\xb3B\x92W\x1f SG\x9a\"\x133i#y\xb7u\x98.R\xaa*R\x92&R\x9a\"RT\x0fi\x86\x1a\x12\xa6\x85\xe4\xad\xff\xa4\xb5\xf3\xe8 \x8d\xf8\x90\xe5\xc7C:=\xd26\xbaF\xff\xc8 \xf3~\x87\xbf\xdf_0\xe3\x1f\xeb\x94\x8f\xd8\xfc\xc4\x84W\xf3(\x18\xb4\x98\x14?\x93\xde\x91_\xed(\xbd(h\x88d\xb9\xce\xd1\x94\x1a\xa9/\x9f\xca\x91W\xe3(\xbd\xfcK\xf5\x8d\xe2\xeaF\xe9e@\xdb0\x9f\xae\x91G\xd5\xc8\xabi\x94^\xf0\xd9zFa5#\xef\x8b\xfdP\xa6p;fV1\xb2\x17M\xaf\x86QH\xc1(ZI\x1c\xbb\x94Z\xd1\x95\xcaEc\x15\xa3\xbaE>\xd5\"\x1b]\xb5P\xb3h\xc1\xcc\x1aW+\x8a\x0f\xbb\xbcJE3u\x8a\xbcu\x86(f\xd0\xaff\x13\x1c\xce\x90\xd4(\x90]\x9b(\xa4\xd2\x13\xd6%\xcaT\x9dl\x8aD\x86\x1a\xcfl=\xa2$5\xa2\x8c\x15\x9e\xadC\xe4\xc9a\xc1\xb4\xde\xa9*DA\x0d\xa2`5\xe3\xb8\xceI#,\x91\x19\xc2$\x85\xa2\x82B\x0b\xdd\xe05RB\xe2\xaf\x96\xbd\xd1\xccXz\x7f r\x8b\x08e\x95\x10\xc2\x05\x842\xca\x07\xb9\xe2A\xf9\xa4\x83\xcc}\x96\xf9\x86\x9c\xb2A\xa8h\xd0E^\xc9 D0(\xb7\\\xd0<\xb1 \x0f\xad\xc4A\xdc%\xc0\xfe\xdc\x87Wa\xfd\xe6\xb3H\xfc\xea8y\xc9#aX`p\xc2\x8d\xad(\x0b\xc1\x81^;\xdb\xa1\x93\x89`\xc1\x18\\07`03dp;trr\xe5\x84\x0f&\x01\x08\xf3B\x08\x13@\x84\xd9a\x84\xdb\xa1\x93\xf2\x9a\x05;\\\x0d<\xcc\x0d=\xdc\x0e\x9d4\xaf4\x10bf\x18\xe2v\xe8\xe4v\xe8\xe4v\xe8\xe4v\xe8d\x1c\xb2\x98\x80\xd3\xdb\x0e\x9dLi\x9c\x14\x18c\xbc\x15\x92\xa0\x8c\xb3\xc1\x8c\xdb\xa1\x93\xeaJ\x017n\x87N\xae\x87:n\x87N\xce\x86A\xbaE\xde\x0e\x9d\xcc\x05\x91|\x08\x90\xe4\x1c\x98d\"Pr\x16T2\x1d,\xb9\x1d:\xb9\x04:\x99\x17<\xb9\x1d:\x19\x82Q\xa6\x01)\xb7C'\x17\x02+\x83\x1b\xd3\xed\xd0I\xdbzv\xb0\xa5\x8b\x8c\\Z\x9e\xa0\xd2\xd7z\xd0%x`\x97\xe0\x07^:\x98\xb1L\xd0\xcb\xc5)\x9f\xed\xd0\xc9D0&jn;t2+8s;tr\xbc2\xc35g\x006\xb7C'\x8d+\x13\x80s\xf1\xfc\x1c\x87q\xc6[\x15\xb3\xb3\x0e\xca9\x1b\xcc\x19\x81s\xc6\x00\x9d\xdb\xa1\x93k+\x96\x0d\xe2\xb9\x0e\xe4\x99\x08\xf3\xcc^\xf5\xd9`O\xaf5\xb6\x1d:)\xae\xed\xd0\xc9,x\xd1\xcc\x88\xd1\xed\xd0\xc9\x19\xe8\xd1\xff|\x87N\x82\xdd\xbbG\xfc\xe5dZ\x9c\xb4\xea&\x9e\xbfI\x9d\xfe\xad\xa5N\x03X\xe34\x81S\xc4\xc0\x0c\xa8\xf3\xf4t\xd3\xd9(\xe7\xeb\xb2c\x9e\xd1\xc1\x7f\x9a\x8c\x0b\xe3\x90I1\xea$\x82Q\x9e\xec\xaa6z\x8b\x06\x88\xfe\xd7\xbe\xe2\x87A\x84\x9a\nR\x9a\x0b\xe2M6|\xf0\x0f\xa4e\x1de\xbf\x17-\x87u\x19\xb1%c\xe7x\x91\x92z$Z\x04\xf5znV\x8ek\xd9\xe9\xf8\xf0\xb7\xee\xe5\x7f\xca\xfc\xfa\xd1\xbb\xccl\xd8\xae\x97\xc87\n\xc7\xfdx\x84\xa6g\xc7\x9e\x8d\x7f\x1b\xc7\x9aeE\xb8{\x0fV\xc6\x91\xbe\x93\xd7.9\x1e3[\x14\xfdO\xf9\x83\x99MS\xbe[\xaa\x0b\x9a\xd9\xec\xf0\xfd\xc7\xe5\x13\x99F\xf9L\xd3tt\xe9\xa9\xc1\xde\xf7O\x16{9\xa2'\xde\xdd\xb0\xac\xca\xdd\xd4\x19\xad\xf7\xb4=\x945S\x83ON\x9f\xe6\x8axC\xaa\x8e\xa2\xda\x10\xee\xf9;\xe8\xe9;\x81Y74\xdf\xc6\x18s\x10k\xa3\x14\xcf'\x1f{\x0ef2\xe8 \x81E\x07\xf15+\xb6b\xb1\x00\xa3\x0e\xe2-\x08\x89\xad\x08+\xd8u^\x83l\x02\x13\xf7\xa04\x17\xb2\xec\xbc\xc6\x02\xec;X\xca\xc0\xf3Z\x13\x85\x8a\xb0\xf0\x0020\xf1`9\x1b\xcfk\x8f$1\xf2`\x1d+\x0f\x962\xf3\xfc\xc5\xae*\xd1^Qv\x1e,d\xe8y\x8d ^N\x02K\x0fV0\xf5\xfc\x06)\x8b\xb1\xf5 'c\x0f\xe2\xac=\xc8\xc5\xdc\x83U\xec=\x98\xcf\xe0\x83\x1c,>X\xc1\xe4\x0b\xccO\x9e\xdd\xb1\xbe23\xfa\xe0\x81X}\x90\x9f\xd9\x073\xd8}\xb0\x98\xe1\x17\x9c\xc3\xc3,?X\xc4\xf4\xf3\x9a\x1a\x18\x80\x01\xb6\x1f(\x17 \x91\xf1\x07\xb9Y\x7f\x10e\xfe\xc1Z\xf6\x1f\x84\x18\x80\x90\xe6\x02Ew\xd2\xe9^RNF DY\x81\x90X\xb2e\xec@\xd4\x94^#\xc2\x0cA\xc8\xc9\x12\x84uLA\xd4\x9eZ\xe8\xfd\x8e\xcd\n\xc6 j\x8f\x97\x87yX\x83\x90\x859\x08i\x049\x881\x08!\x9dE\x08!j\xd1\x026!D\xecy\x98\x13\x19\x98\x850\xbb\xf1\xd2\x18\x86\x90\xd8B\x89LCX\xc26\x04\x7f\xcb\xe5a\x1dB\x1a\xf3\x10\x12\xd8\x87\x90\xc4@\x84x\xab\xcec\"B2\x1b\x11\xbc\x8cD\xc8\xc1J\x849\xccDX\xc1N\x84H\x13&\xb2\x14!7S\x11b\xe5\xf2\xf4\xe4E\xacE\xd4R\xe0\xe8\x06yee/B\x80\xc1\x08+X\x8c\xa81\xdf\x01\x0f\xf2Z\xc1fD\xed\xf9\xb7\xa2\x11\x96#x\x99\x8e\xe0e;Bf\xc6#\xacb=\xa2\xe60&$,eC\xa2\x96\xc2\x0cI\x98\xc9\x92\x84t\xa6$\xcceK\xc2,\xc6$\x04V\xb0\x00+\x0ef0\xe3R\xd8\x930\x97A sX\x94\xe0\xaf\xe4\n6\xe5\xcc\xc1\xb5\x82e\x89\xf7m\x1f\xd3\x12\x16\xb3-qS>\x06&<\x00\x0b\x132\xf5\xb9D6&$32\xc1ae\x82\x97\x99 \xc3\xde\x18ggB\xe2\xder1K\x13\xb5\xa6\xd1\x87~\xa6&x\xd9\x9a`\x978\x1fc\x13\xe2\x81\x04\x9c\xb9 \xb3\xd8\x9b\xd8\xdd\x1e\x06\xa7\xefV\x8c\xc5\xe9\xde\xeb5:\x8b\xcd \xe0ctB\xbc\xbd&_*\x17\xb3\x13Fp\xaf\x97\xdd 3\xcb\xe6\xe9\xf7\xb3\x99\x9e\xa8\x15\x13X\xeec{\x82U\xa2X\x81\x8d\x7f\xace}\xc2\xfa\x14e\x80\x01\n\xf1/\x01v\xe5\xb21A!\xc2\x06\x85\x05\x85\x0b\x04\x06\x970C\xbd\xc6\xf4\xf1\x1d\x01v(\x84\x19\xa2\xb0\xa0v\xcb\x99\xa2\x90\xc8\x16\x85\x05\xa5\n\xb4yN\xe6(\x84\xd8\xa3 \n\xe5e\x90\xc2\x82j-`\x92B\x02\x9b\x14\xe2E\x89\xc1\xd7RZ\x7f\x05\xbb\x14\xb57\xa5e\xc4\x19\xa6\x10e\x99BzC\xac\xe6D\xe5c\x9d\xc2\\\xe6)\x04\xd9\xa7`\xd7`\x0d\x03\x15\xd6\xaf\x15)lTHluX\xc1J\xf5\x1a\xbc\xa0\xf3\x99\xa9\x10o\x17Hh\x1b\x88\xb0T!\xde\xa1\xf5\x95\xda|\xb0\x88\xb1\x1a4\x97\xc0\xe0\x84\x04\xe6*Z\x02$B/}Q\x11\x17\xa7O){\x1f?\xbc\xd6eK#0~\xe0^\xe1\xfc\xe3Y\x843i\xf8;\x93\xda\xc9\x1fUXX\xc0:E\x8aO\xbb\x9fr9);84\xfb\xbeZ\xc6\xea]tv\xe0\xa4\x90\x96o\xaf&J\xe9\xe7\xab\xb8\xae\x80\x92`\xde9_^G\x0e\x08\xf6v\x8ci\xe4\xdf\x9eM\xe3$\x13\xe3\xba`z\xd5\x1e\xc9\xb8\xe3=v\xd1h\xcdZ\xc7\x1b]].g\x867^e\x94\x12\xf4\x9fD\x0e\xb2\x143\xfc\xd0\x88&\xe9\xde\x01\xe4\xb6\xd4\xf8\xf5\xc9\x91\xb6p$e\xfb\x9c\xb5e3 \x93\x8cD\xd8\x07\xaa\xa9\xfb\x02]\xbf\xb1\xf5\x0d6\xae\xbe\x875p\xa4mWv\x938\x03\xaf\xf9\xf9\x9e\xd6\xcdaI/\x1d\x9f\x9e\xf8p\xfc\xcf\"f\xc6'I\x10\xbf+\xce<2\xd9 \xe3<6\xb7\xc8\xbbg\xf0\xa0?4M5\x7f\x12i\x9a\xca7\x854M5U\x05\xe0\x7f(\xeb\xcbf\xd1tQ7\xec\\N\xe8\xe73N\x8c\x9e\xf3\x04\xd2\xe2F\x93D\xdb\x9b\xd7.\xbd\xb5?\x1a#e\xfe\xdcm\x8e\xb3s]*\xa3~\xd2D\xdec\xb6\xccw\xda\xeeo`\x8b\x1d\xdaZ\x8fa\xfc\x87%\"9\xef\xd1\x93\xc1\x05-\xae\xff\xe5\xb7\xcf4\x9bh\xcaI\n\x9br\x9d\xcfa6?\xef\xda\xe2\x81k\x84\xbe\xcbM\xb6M\xe6cI\x1eB\xcdiv\x95n\x81P\xe5\xf6\x1d\xfbf\x953\xde\x15\xae\x9c\xe7[uL\xeb\x90\xc4k\x88.D\xf2\xc2\x86\xd3x\xa1\xcc<\xf3\xc1U\xach\x19\xe9j\xea@LY^ \xdb\xefx|Y^)\x1fI^V\xe9`*w!\xff\xa6u\x0bC\x01\x8aIGeM\xf3\x15\x8e\x15)P\xcc5\xc8\xd8\xe2\xb1\xa2\xe2\xc5\xa1\x88\xc4\xccF\x89E%f5\xcc\xb4\x84\x93v\xe9\xeb\xf2n\x0c5G\xbb\xb1m\xd0\xd7(*\xa6z~A*R\x17k\x1b%\xbd\xaa\xd6{\xd18\xaf\xfe\xed\xf6\x9a\x86*9\x9d\xaf\x18i\x19\x16\x8f\x91\x97\xdc\xc6\xf1)\xe2\x9b\xd5t|\xa5\x9e\x8d\xc6\xbd\xae1\xd9<\x1b\xe6\xa8\xa8-9\x80\xe4\x8e\xd3\xac\xbc/\xcd\x95RR\xd3\xb5x[\xb3\xd6H{N\x1bX\xceK~\xcc\x1c\x08\xa6\xcc\x0d\xa9\x19wj\xc8\x9e0\x82\x95kR*\xedI\x93V\x06\xe0&/T?\xce\x8dB\x99\x15\x9a\"\xf2\xaa\xb2c\x92m}$-+\x8b\xbe\"FD\x05\xa1\x12\x8f\xc5\xa9\xaf\x84s\x88\xc4\x01\x84\x82\xc0\xc4\xa2\xa2\xddN\x92?\xd6+\x87\x8f\xef\x98\xf3\xe4'<\xcb\x8d\x7f\xa9\xf1,3\xc1%&r\x94\xba\xe9E\xf2\xf2xr\xf1\xdb*\xb6\xadb\xdb*\xb6\xadb^[\xff\x08\xabX\xb0\xbf\x05\xbf@\xbc>N]\xcc\xa0\x02\xfd\xb5/oHEk&\x97\x15\xe7f\xc4 \xbd+\xe8\x91I\x80p\x89\x8a\x1b\x8c|\xc3\xa1\xd7Zh^\xf5\xe9\xe4\xbc&B\xb9H\xca\x01\xa0\xebK&\xe2T\"\xed^\x95\x1e1\x85!\x08a\xb6m\xa8e\xccj\xa66\x87U\xef\xe9\xf2\xae\x16\xd4i\xe1\x06U\x8a9\xad0\xa9\xf3\xd4\x1cR\x7f\xa7\xe6\x9bj\xe6\xa6\x9a\xf9\x10\xaa\x99\xd3\x8c\x13\x1a@\x8c\x05)'\x0f)k\xb3\xf3M\x9fu*\xe0\x8d3\x80\x93\x03\x982\x9d`\x07,\x93\xfau$h\xe8\xed\x0f\x93\xb6\\\x16\x11\xc4\xa3\x7fc\xb8jE\x81\x1c#i\x05B7\x17\x81\x94\xca\xc3\xeaJ%x\xf9\x11_&\xe6\xd9\xc7\xd7Z\xd7\x9b/q?\xdeHiqW\x1d5\xe5q\xdf\x13\x1c\xf7\xc4z&\xc3\x1bmO\xbc\xc4\x9c\xf0\xb1F!?;\xc1\xc3\xce\x10\xc4\x0d\xf9\xd3\x8aU\xa0n\xa9\xa4\x8e\xc5\xbe\xaf$\xb2\x01\xb3\xd6\xd2\x82\x967\x14\x08\x0bV-S\x95\x02efMZYbM\x84L\xa2\x96\x97k\xe0k\x83>n\xc4\xbb\x0dFg\xd0\xac\xae\x13\xa5\x99\x98\x98\xf8\x01H-\xa0c\x8d\x00\xefT\x95\x8c\xccte}UQ3*c\xbcV\x86`F\x83\xbc\x17\x0f\x8f\x18\xe8\x95\x9a\xb7\x07\xef\xe7\xcf\x9avO[\xba\x17\xa1\x1f$S\x8aJK[.fh\x85Dj\xa4\x0c\xa6\xe7\xf6\x06<\xd3\x1bw\x85N^!\x8d\xd0\xcc7J\xf0\x8do\xcc\xb4\x1cDVjy\xcd\x19\x97\x7f'\xe9\xbd\x87\xad\xcd2O l\xca\xadM\x1ez\xd6\x84}ezHb\"\x90?\xaa\xe9\xd2\x89\x80\xc4\xda\xc2\x98R\x06\x0e\xec\x08\x9dP\x90C9)_\xd3J\xc4\x1eH\x0d\xa4\x10\xce\xb7[\xe1S\xee\x08\xb8;\xd7\xe6\xb6\x96q\x8b\xa66\xe6(%\x0d%\xc4\xd1\x9a\xa2$\x03jN\xf8\\\x06\xfc\xcc\xb5w\xc9-\xb9\xef\xf1|\n\xcf\x82\xb5x\xc09\x18\x15y\x05\xbf\xa9\x8c\xfe\xcc|,\xf6\xf5^KT\x8b\x8e\xd8\x88\x0f5\x02\x0fG\xb0\x8bhh\xfe\xdd\x0e\xf2\xb3\xb9-\xf7\xee\xfd\xd9\xdb\x17B^@\x85\xa9$O\xbf\x14K\xe4i\xad=\xbaA\xbeJ\xf6\x11\x0f\x01[N\xe0\xeeK\x06\xee\x17\xef\xaf\xbf\xf6e+;\xc5Us\xd5\x08\xaepjT\x03_p\xa61\x8d7\xbex\xc6\xc4\xd2\x18\xc0\xf9\x0e\xeb1\xb3\xe3\x18:va\xda\xdaB\x17[\xe8\xe2\xa1B\x17v\xdbG=#\xafgf\x1ax\x8eY0\\\xb3T\xcfl\xb6;6\xcc\xdf\x8bb\x16a\xc1\xe5\xb4\x08\x81\xf3\xc9\x17\xca+\x8fR\xca\x96\xbd\x98\xb0rXR\xd9\xbbd\xf9\x17,\xe6\x15P\x0e\xaeW\xb1\xa5g\xb9\\\xb2\xc7\x91\n\x0b%/\x91H\xf6K!/\x12A\x16\xe6\x11cA\xf9c\xb6N\xf8x\xa1\xe41J\xc5\x8f\x8b\x1d/\x969^$p\xcc7\xafX\x8b\xc5\xa5\x8d\x97\x88\x1a\xfb\xa4F\xa3r\xc6K\x85\x8c\xf9,\x8e\x98\x0bJ\x18/\x11/\x0e\x8b\x14g\x90'N\x12&\x9e'@\xbcRzx\xa9\xe80\xa0Ys\xdf\xbe.\xab\xd0p~\x89\xe1\xac\xe2\xc2i\xb2\xc2\xcb\x04\x85=\x0d\x1c\x92\x12\x9e/\"<\x8a\x05cc\xdc#\x1f\xccR\x85\x83\x97J\x06Ki`\xc4 .\x16\xbcB&\xd8#\x10\x1c\\\xe2\x83\xa2\xc0\xf1\xf5?\x9f\x10pH\x028\\\x8ee\xb2\xbfz&\xb5\x8c\x85\x04\x7f3I\xfd\xae\x10\xf9\xc5G\x12\xb6\x94\xaf\x10\xf6\xe5\xef\xb3\xac1T\xd2w\xad\x98oT\x896 \xe0\x9b$\xdd\x8b+l\xce\x93\xeb\xc5m8\nv\xab\xc5yS\x1b#E\x907\\\xef$\x11\xde\x99\xf2\xbb\xae\xa2_\x06\xc9\xdd\xa8\xd8nXf7&\xb0\xebm\xa59\xa2\xba)r\xba\x98\x90\xeeJ \xddD\xf1\xdce\xb2\xb9\x1ea\xda\x14\xa9\xdc\x8c\"\xb9\x9eR8=m\x91$.\x04\xe4o3\n\xdf\xe2\x92\xb7K\xc5n\xbd\xc2\xb6+$m\xd1mHP\xb8\x16S\xd5\xc4\xc4j\xf3\xc9\xd4.\x17\xa8E\xc4h\x17\xc9\xd0\x06%g\xd3\xc5f\x93dfU\x1c#E`V\xdd\x1a\x95\x96E\xf5V\xf1\xb7\xa7\x8az\xc6\x85dgH\xc8&\x8a\xc7:\xd5X!\x18\x8bv\xe3\x15\xb2\xb0N\xb4\x05\x15\x84]&\x05\xeb\x93}\xcd+\xf8\xba\xae?$\x89\xbc\xa6\xc8\xbb\x9a\xcb\n&\xe9*w3\x98\x98kx\x97\xb0X\xc0\x15\x17\xb7\xf0J\xb7b\xa2\xad\xd3Ln&\xb9V\xef\xb6\x0e\x93hM\x15gM\x92eM\x13d\x8dJ\xb1\xce\x10aMb\x95\x8fv\x8d\xd6\xce#\xb9:\xe2\x1e\xb0l~ZI\x9c\x1ei\x1b\x1d\xb3\n\x1eiU3\xb7\xe0\xb3\xe5E\x85\xfb\x0bf\xfcc\x92\xd80\xff\x9e$\xa4\xca\xe6'&\xbc\xb2\xa9\xc1\xa0\xc5\xa4\xf8\x99\xa4R\xfd\"\xa9\xe9EAC$K$Q\x07\xe9S\xc4\x9eO\x0c\xd5+\x83\x9a^\xfe\xa5\xd2\xa7q\xd1\xd3\xf42\xa0m\x98O\xe2\xd4#n\xea\x955M/\xf8l)\xd3\xb0\x88\xa9\xf7\xc5\x89\xba,N;\xae\x10+\x15\xe1^\xcb\x9c\xbdhzeJ\x17\xa9\x0f\x85Q\xbb\xa9\x15])D:a\xa1\x86%H}\xe2\xa3\x93\x92.\x97\x1d]0\xb3\xc6EF\xe3\xc3n\xa9\xb0(\\`\x11\xde\x99\x92\xa2\xde:C\x94\x07\xeb\x17\x91\x0c\x0egHj\x14X$\x17*\x94\x1f=\xd6Bz\x90a\x89\xd0L\xd5\xc9&\x08:\x8e\x98\xf9R\xa0I\"\xa0\x19+\x1f\xbd\x87\x904\xe6\x13,F\x87\xec\xdb\xf2+\xfc\x04\x82\xc0\xfc\x1a[@2Q <\xf4\x87(\xf5aE\xc93\xd1\x1d\xfe~UV\x12H\x91 \x1eD\x8c\x18\x19ohye$Gz\xe9\x91I\x04\xc9\x19u\x0e+\x9a\xd8\x9b\x99\\4\xc9$\xa2dB-\xd2\xbeK^\xbad2ar\x8d\xee\x05\xd8\x95\xcb@\x9bLi\xae|\xd4\xc9(y\xd2*\xce2\xfad\xb8Nk)\x94\x13c\x17\xae\xa2\xd5\x12F\xe5F\x04\xd9\x88 \xd9\x88 \x93n\xe3\xa1\x83\x84\x1c\xba\x99\xbc\x10\xcc\xd4\x12\xee\xee|\x87r\x18\\\x0f\xecG\x86\xc9$\xab\x9c\xb1\x85\x94\x12\xaf\x9d\xff\x16%\x95\xc4h%A\xd7+\xe4x1/\xb9$\xba\xac\xc5Z \xf2SLb$\x93\xdc4\x93\xccD\x93\x08\xd5d5\xd9$/\xdd$\x85p\xb2\x82r\x92\x97t\"{k\x84v\x92\x97x\x92@=\xc9N>\x89\xd0O\x96\x11PPCARJ\x16ZJ\"1\x05}r\x16Ye5]%7a\xc5OY\xc9LZy\x08\xdaJf\xe2J*u%3y%L_\xc9N`\xf1SX\xe4\xc4\x95DbYNcA\x8d j\x8b\x87\xc8\xb2\x8a\xca\xe2%\xb3D]\x8a \xa1%\xcd\xe3\xc8Gj \xd3Z\xe2\xa5\xc9Jm \x93[\xb2\xd1[\xd6\x12\\\x1cs\xc2\xa3A\x9d\x87\xbc$\x175\x8c\x90\n\xad%\xba$\xb0;\x82d\x97D\xba\x8b\x173?\x93\xf2\xe2\xb7\x83\x00\x89W\x13_\xe64N\n\xf9%\xde\nI\x04\x98\xd9\x14\x18\x1cf\x9d\x81\x06\x93@\x84\x89Qa\xe2d\x98`\xab\xcd!\xc4\xa4QbpR\xccjZL21f)5\xc6\xdfLI\xf4\x98\xac\x04\x99@Y\x90\x9e\xb8\x8a&\xe3XCh3Y\x893>\xea\xccJ\xf2\x8c[d\x97L\x93\x9fN\x13!\xd4\xe0\x94\x1a\x9cT\x93\x93V\x93\x99X\xf3\x10\xd4\x9a9\xe4\x9aDz\xcd,\x82M:\xc5\xc6C\xb2\xf1\xd1*\xd2\x89\x15q\xa2\xcd,\xaaM2\xd9\x06\xadPn\xc2M^\xca\x8d\x87t\x93\x9bv\x93\x9bx\xb3\xbe\x8f$\x91o\xd2\xe87S\x02\x0eN\xc1\xd1{0\x8c\x84\x13\xdf\xd3d&\xe2\x04\xa888\x19\xc7*a.:Npc\x8aQr\xd2I9\x89\xb4\x9cTbN\x025\x07\xe6\x90spzNzv$\x0fE\x07\"$\x9d\xf4\xf2\x04A?\xeb\xa9:\xe0!\xebLK\x11*\xa0\xf1\x8fu\x84\x9d\xc5)\x1f/m'\x1a\x9e\x99T$\x13u'D\xde\x99W O@h9\x85\x075\xd7\xb4^\x12O\x80\xc63\xaf&K\xa9<)d\x9ey%\xf1\xb4i>J\x8f\x97\xd4\x03~Z\xcf\xbc*\xcc\xa6\xf6\xc4\xc8=\xc1\xd7\x87\x00h\xb1\x96\xcdL\xf2\x99A\xf3 \x13}\x92*\xecC\x9f\xa5Wz%\xe1g\x16\xe5\xc7O\xfaq\x91r\x0bi?\x8b\xe7\xe78\xf9'\xde\xaa\x98\x9du\x04\xa0\xd9\x14\xa0\x08\x1a4\x86\x07\x0d\x11\x81\xa2\x13\x00$6\x11d\xa7\x03\x85 A1JP\xd6\x8ae#\x06\xad\xa3\x06%\x92\x83\xb2W}6E\xc8km\xba\xb7H& EhB\xd1\n\xc7fVHl\x90%\x1c\"|BqyE \xcc\xa2U\xbe\xfb\x1a~\x91cL\xdd\xe52\x8c\xc2\xe5\xc8\xcd2\xca\xcc3\xf21\x8d\xb2r\x8d0\xb6QN\xbe\x11x\x19Gy9G\x1e\xd6Qv\xde\x11\xca<\xca\xcf=J`\x1f\x81\xdd\xbbG\xfc\xa5\x91\x9b\xae*Q\xd3_{\xdarS\xe3=\xda\xc8\x86t\xde\x90\xce\x99\x90\xcevA=\x80\xe2df\x9c\xc0-+[1\x82\x9cy\xb2\x9flr\xa7\xf3y\xcf\x18\xc2\xa0\xc4\xe8\x87\xb2\xb6\x9fK(g.\xc5l$\x80um\xb1\xa4 \x93\x8e\x81Zs\xe3\xa8\xd3#z%\x86W\x83\x96\x0dk\xeay\xb7\xa8\xfb\x8ee,\xaaa-RT\xfc\xa0q]r\xbb\xbc\x0e\xfb\x8d=\x00\x1c=\xc2oK\xd8a/ )\xcc:\xb2\xdb=\x98\xdb\xb1\x87P\xd9\"$\xb6\x84\x8a-\x0d\x1dd:v\xdbG\xb3\x8a\xf0\xdaVx\xb5s\x0f\xd1\x0e\x97\x1f=:\xdb\x7f`\xf6\x8ar\xcf>\x12\xdb:\xf8\xda1\x188\x08;T\x96%\x87^\x0f\x1c\xb6\x89%\x97\xcf6y\xaf\xcdd\x9b\x18\x9f0\xd8\xf0\xe2NNe\x9e\xa4\xd0\xab\xb2c\x92\xb5v$-+\xb9\xcb\xd7N\x98k\xe3\xab\x86\xcf4\xa1\xad\x89\xa4\xda\xe4i5?O\xa2`\x96\xf9\xe1\x13M\x037 \x8b\xa5h\xe6\xe4\x15\xd3;\xd9\xa1\x9d\x0f\x9f\xe0\xa6a\xb8u\xf3\xd8t\xde\xf2\xceX\xc1\xd2\xb9\xb3\x94\x1d(\\0\x19!\x93\x8fw\xda\x89\xaf\x9b\xab\xe6\x15{\x1e\xc1f\x90x\x11&#u\xed|\x01\x17\xa6\x9f\xec\xce\x14\x937\xaf\x9a\x14&\x13A\xeap\x98M}3\x8bqN\xc7\x11\x85>\x8e\x9b\x80\x98+\x11\xdd:\xcc\x95\x1e[9\xf4,k\x8e\x03\x11t\x1f\xa2\x95I\x90\x18\xcb60!\xe6\x13xK\x1bn\xe0U\xa3\xd6\xb2\x85\xf8\x02>O`ai\xd7\x8ei\xcb\x9c\xd7\x03\xf0\x97b\xd5@7\xec\xd8k\x7f|\xc2\x8d/\xf2\x93y\x01\x9c3\x0d Rx\xe3pCe\xb0\x1c\xa2Fc\x80f\xf5\x81\x86\xc3\x14d\x9ce\x980\xd1\xad\x9a\xe3\x16\xcdn\x83\x13\xb4\xe6\x148\xc7\xc8\xc2]7\xc4w\xde\xe9\x85r\xc6\xd2\xf2]\xb8e\xc8\xb7\xb3\x85\xf8n\x1cr\x14\x7f\xed\xce\x1c\"u\xd8\x8e\xea_\xb8\x04\xa3\xe6\\\x8f\xd8xU\\\x92&\xb1\xc2k\xd3V\xcb\xd6\xed\x88)\xb7\xc2 \xea5\x91\n\xa7Tf\xee\x1a\x8f\x1a y\xeb\xe3\xe5\xdf\xf9C\x9e\xba,\xf5\x00\xfc][&/|\x91\x00H(W.\x9f@^\xb8\xca\xcd\xc2\xc8\x80\xf3\xa8\xd7\x99\x99\x17!0\x8c\x98\xb1\x02W\xdcf]\xa4\xc00\xe4\x80=\xbeI\xe04\xb4i\n\x1a\x0c\x19\x85mn_2\xd5ms;rms\xfb\xff\xfds\xfb\xbc\x18\xff\xac\xd8\xf4\xac\xdd\xe0\xc4\x94u\xec\xfd\xe4\xb7\x0c;\xc3\xa9\xbd\xc9.Q^\xd6\xb9\xf7\xf1\xddojU\xad\x9a\xe9\xde\xa3\x96\x13k\xf3\xbb\xa2\x86\x0b\xf6\xbe\x88.V\xf2\xd67\xb0s\x8d\x07Ns\xedX\xc7M\xd9\x82B8\x0f\xa7\x15\xe2o\xe3\x18|\x83\x8c\xea2\x19\xd0\xbfa\x964\x93\xb0\xe7\xdf&\xf59O\xc03A(se\xf1W\nu\x86\x9ab\xb18g\x964f\\\x90s\xf2\xf8\x80\x92Z+\xc2\xa9\xf6&\xd2\xd8|\xc5\xcd\xf4)\xfb\xef,[\xb9d\xda\xf8&I\xca\xd9\xd3\xc3\x8a\xe4\xe4d\x04,\x9e\x06\x8cag\x98s\x0b\xba\xa0\x80\x8b\x87;^\xcdlC\xb8\xad\xde\xe7\xf7u3*\xf6\xa1Z}\xb6J\xdf\xa4$9\xf4\xf9\xd0M\x87\xad\xc9\x97\xa2\xc6\x17\xd5\xe1\x8b+\xf0\x05\xb5\xf7\x12U\xf7l\xbd=\xb4~\x93V\\\xaf\xb17&\x97mu\xbd\xf8\xdb'\xbd\xc964F{\xe7i\xe9\x0dv\xba\xb1\x88\xe3;\xf1\x82\x18\xff\x98\x04\x99\xcd\xbfG\x95\xf3Xz\xb0\x18\xd5\xc9\xf3n\x81'E\xcd\xa0\x8d\x87\xab\xe2\xa5\xbd\xde\xa5\x98,\xd6\xc0\x03\x0b'\x02\xa8\xfa\x1d\xaa{\x97V\xd6%Zwa\x95\xbb\xb4\xf7.\x94\xb0\xc3\xe4\xeaP\xa1\xba\xb4R\xcc\x12\xa7\xf3\xcb\xd2\xa1/KHTN:JF\xf99{eA\x85\xe7|\x92s\xc1\xcaD\x12\x9c\x9e\n\xb1\x99\xd2rc\x05\x0csAQ9LN\xceN\xbd.\x10\x92\x9b1]\x85e\xe3\xc2\xf3\xc3\n\xa98\x11^\xb4\xcc\xa5\x89\xc4\xa1u\x83 h\x17\x97\x0f\xf3\x0e5\x88V\x1c\xb2\n\xc0\xf9\x94\xc0\xfc\xa2o+\x8b>_\xe2\x0d\xed\xd9\xfa\x9a'\xee\x16\x95u\xcbP\xb9\xd9\"nHx\x1f\xa6\x02v)\xf2m^\xe16o\x95f\x10R\x97\xe8\xb1\xd9\xdakA\xd5\xb5\x99>\xdd\x1a\x8d5\xf1\xd7\xef\xcc\x8aNQ\xbe\xf8[s*\xaa\xad\xd7R\xd3\xf96epLN\xaf\xd5O\xb34\xd3V\xaa\xa5\x8dN\xbf\xb27\xea\xa4\xadVHS\xaaP\xca\xdc\xa8\x8d\x96Q\x15\xcd\xd2C\xcb\xa9\x84\x16\xd1@S\x98\x19^\xf8\x1d\xb9(\xca\x015\xf3\xf2\xd5\xeb\xd3_d\\\xe0\xe7\xe6*\x19:s\xe8\xae\xce\xcbzO\xef\xec\x11W\xd6\x8c^\xd1qb\xc5\x1c\xb0J\xbf\x08\xf0\x81Joh\xcd\x1e\x188+n\x9f\xfc%0\xb1\x11\xc6\xda\xf2\xa2Gth\xb1\xa2\xc9\x0be`\x06\x16|\x88\xaa\xc1\"\x07\xde\xca+\xb8\xc6\x04\x0e\xa2[\xbd:\xbd\xd4\xedbn\x1c\x86\xc6\x82\xdb\x96\x1c\x8f|\n\xbb\xa6\nt\xf9\x95\xde\x8bII\x14 1HluEy\xc9\x02vP\xd6\x1d\xa3d/\x84\xdb\xc8\xad\xc8\xb4\xfa\x0fO\xb7t\xed> \x1boy\xd7\x1aJKk\x90\x7f\xd0\xc8\xb3I\x81\xb5 \xe0\xf8\xf5'\x065\xd6\xe8+\xbd\x7f.\xa3\xcbGR\xb6\x9d\x0c\x01\xf2\xb9*\xad\xd4\xfe2\x8b\xa2\x99\x02\x85\xd0Ue!\x16x\xb3\xd4\xea\x8d\xb7\xbc\xc8\xf4P21\xfb\xf4\"\x8c\xdb5\x935\x98\xde\xd1\xa2\x8f\xadK\xd3 \xc1X\x9c:\xd6\xf6\x85\xd8\x19\xab\x12 \xc7\xb6\x061\x0dp\xf7\xf0N\xbb\xa6p\xc1g\x14eKw\xda\xbbk\xd2]\xcf\xf1\x01\xb8!c2\x01\xfe\xfc\x98^\xd8\xd3\xeeH\xa2\x84&U\xa6w\xe4 o\x1f\x12\x1a\xaf\x9b=5l\xd9fRB\x17\xee\xfc \xc9\xde\xdc\x9e.g\x82\x0781\xf2X\xcd2\xe2\xdb\x9eh\x00\xdfcusKn\xcfg:R\x93\xd1\xc3[\xb4\xe9\xd9\xb1\x1f\x98-\xc6j\xf3\xb8\xe3N\xd6\x15m\xe1 \xef]\xd2\xe8\xd3\x1d\xfc\"\xa6p\xc3J\xdd\xd4\xcf\xf6\x94\xd1\xf6P\xd6e\xc7\xca\xc2\xf0\xf1\x1ex\xc2ABM\xa6\x1d\xfb\xab\xc9\xcb\xcfn\x9e\xb4\xa5i\x08\x99\xbfl?\xd2\xbc\xfd\xdb\xb8l\x98\x97i\xfc\xe2w\xac\xfc\x1e\xa7\xf98V yy\xaa\"\xaf`\x85\xe4\x15\xae\x96\xbc\xbc\xfe\xa8\xbc\xa2\xae#\x84]Oy%X\x89\xbb\x8a\xf2Z\xba\x0c\x85\x0b\xef\x0bz\xc9+\xb6\x0eL\xafxM\x16\xafa\xc1>\x86\x95\x7f\xf5\x12g^\xb1\x8a-w\x17\xdd64bg\xce\x8f\xceV\x13\"\x85[\x1bN\x9b\x18\xd3{_\x15T\x8b\xbd=u\xea\xe7Cd?k\xd6/\x87@\x15$\xadH/\xd1\xfd\x8b~\xa3\xff=\xb3c\\\x81\xb5\xfa\xe5$|\xd4\xca\x13=4yit9\x16\xc6\xb1\x92_\xac\xc3U\"3\xe4\xbe\x969\x19\x95$\xe0\x03\xdbH\xbd\x1b\xa9w#\xf5n\xa4\xde\x8d\xd4;\\\x1b\xa9w#\xf5n\xa4\xde\x8d\xd4\xbb\x91z\x03\xcfn\xa4\xde\x8d\xd4\xbb\x91z\xc5\xb5\x91z\xd5\xb5\x91z7R\xef\n\xda\xe7F\xea\xddH\xbd \xa4^V\x1eh\xc7\xc8\xe18'\x908\x8do\x96c\x08\xe6\xd8\xd2\x9b\xb2\xe9;\x99\x86\xdc\xc1\x8f|\x07)r\x91\x1d\xfc\x0e\xbe?\x81\x92=\x96\xcd~+\xfe*\xba\xc8\xbe\x9c\x009\xa6\xe7a\x8b\x91\xac\xcb8\x95\xef\x83\x9b\x86\x0d\xde\xa8z\xe3\xcf\xa4c\xaf\x9b\xc3\xa1d\xe6\xcb'\x13\x1c|\x7f2\x99fy\x89\xb87\xda\x95\x9dx\x13\x92{\x1e\xea;\xa6uc1\xe4\xe187v'\x81[\xbc\xbf\xdb\xe2\xa8gc\x08\x85\x91\xab\xce\x88\xc7\xcb\xa5B\xaf4\x02\x82\xd5\xc9>\xba\xa7B\x94\xd0\xc8>\x17\xed\xfd\x915;\x01\n\xeb\xcaQ\x8a\xf15\xdf_\x17\xecU\xc9^\xb6-I\x17!\xa5w\xac%\xe7\x17%\xeb\xce\x85\xa4\xaa\x13|MI\xd1\xd2j\x92\xb9B\xfb\x94\xb3\xad\xc3\xf3\xa7V=$\x08\xcf\xdelJ\xc5W\x91h\x1e\xce\xb6\x86\x8b\x92\xc9\xe4\xda\xd8\xe0\xa5\xa0\x0f\xf4\xea\x00mZw}K\x87\xa8\xd9\xa0\xf8(\xbe\x18#_i'\xc2R\x92cb\xf2>\x94=\xf9B\xb9\x8e\x8bQ)-\x18l<\xfdF\xbe\xa1g\xd7-%{\xe8\xc8\xa5\xde\xeb\xcb\xbf\xf3\xf6\x14d\x02\xc1Vkj\x15Y\x80^n\xdb\x86\x0f\xcd\xeev]yU\x9br\x9b\x9f\xca\xab\xfa\x97!\x8b\xee\xb4\xb2IN\x7f\x06\x9fN\x7fzw\xfe\xcb\xfb7o\x11.\xb8\xf9\xeb\x9b\xd3\x8fo_\x9f!?\x9c\xbd\xfd\xdfg\x9f_\xfe\x8c\xfc\xf2\xf3\xdb\x9f^\xbe\xfe\xd3\xf9\xcb_N\xdf\xbd?\x173\xb9\xfc\x9e\x8a\x87\xee\x7f\xb3\x07\xe3\xa1\xaa5\xce\xf7\x12\x16&*\x0f\x07\xfe\x8b\x8c8\xb0\x0e\xf8b2pb\xafz\xd2\x92\x9aQ\xda\x8d\xfe\xb5\xa7\xe2\x9eR\x0d\xbb\x7f%\x8b*W\xab\xc9\xab\xf9\xa7S+\x8fzGK\xf9x\x1a\x03\x06nk\xbep\xfeb\xbe\xc8\xaa\x9aX\xa2\x84C\xc5\x1b\xe2MS\xa8\xde\xa2\xcc\xdf\xd0V\xce\x0fR\xa3Ug\xeb$2\xf3\xec\x0e+\x84\xfar/\xdc?I\xc4\x9d\xe4\x07M\x8b!\x93t\xbc\x9e\xe2\x85\xf7&\x90\xdd\"\x913z\xc7zR9\x8e\x1e_F\x8fz\xd2Va\xbf\xe9=\xca\x9e(\xba\xa7\x07\x86;\xda\x8b\xd0\x8f\xb2r\x17\xa4\xf8zK\xda}g\x85\x1c\xad\xc6V\xaf{y(\xebF\xce\xb5\xc6\x87\x86\x96\x1e\x9a\x1b \xcd\x95^\xbd T\x99cs\x00\xd3\xf7\xecz\x16\x86\x9c\xb7:m\xcf\xcb\xfa\xb2\x99\x8b\xe2\xf8\xff\xb7\xf4\xf2\x05<\xfe\xff=7\x02\xde\xcf\xdd\"}\x12o\xe0\x85z<<\xec_\xd1\xcd\xf2L\xb8\x8ef\xf7\x18\xb5\x0dZ\xfak_\xb6t\xaf\x9e\xebD\xac\xd70\xa7\x18]\xc6_x\xbbJ|ss)V\n1\xc0E\xcc\xfc@\xd8p\xc0\xcc\xd4\xac\xee\xde\xaf\x9a\xfd\xfd\xe3n\xba\xed\x12\xce\x97|\xb1\xf4\xc3\xb5U\x0d\x1a<\xb6\xe5A\x84\xdf\x84\xadaamj\xea\xe47\x8e\xe4\xbe\xb3=\x90K:\x04\xfe.\xa9\x11\xb5\xf4\xb7\xe1\x8ft\xa0T^R9e\\\x91\x0e\xaa\xf2P\xb2\xa1\xe5\xcc\xcc\xa3QvU\xc8 \x8f\xdd\xca\xb6\xc4\xea#j1\x14]\xda\xa6T\xf1\xd9\x0c;#\xb3\xcd\xb4>a\xd7\x15\x8d<\xfd\x89r\x8fR\xf2\x03\xc5hn\xf6\x12\xdd\xb7oD\xa2^+6\x18f\xe4<%S\x12\xa6y\x1d\xa2\x1c\xbbK\xd9i\xaa\x1d\xedXy\x10q\xc1\x9b\x92O\x8b\x07Eb\xdcY\xe3\")\x1f+\x97k,\xc8\xfc\xb0g\xf5\xedi\xdd\x1c\xbc@\"\x1f\x0c\x06+m\xf4\xb1\x18$\xe3uS\xd6\x86\xaf*DZF\xeee\xdd\x1c\xf41\xdc\xfcS\x92Z\x15\xc2M\x1b\x00\xbc{\x7f\xf6VB\x03\x95\x17$w\xe0\xd2\x1b;\xad\xb5\xfe\xc2\xe0\x97\x99\xdb+\xc7\x98\x8c\x94\xb8/\x19\xbaQ7\x8e\xff\x8b{\xb8j\xae\x1a\xe1_McC\nc\xa8\xca\xe3\x10T$\x1bT\xa5\x94H\xb9W,kj\xf6\xd1+\xd2\x9d\x8bA93\x15\xd1\xbb\x986U\x1a\xe7#\x0c\xaf\xb0Y=WD!aT\xdf\x17^)__\xc6i\xc1\xedt\x05\xed:^(\xeb\x97\x0b\x91[\x13\x92!\xfd\x80r\x10\x99Bh\x8a\xa2o\xcd\xb9\xe4H\xee\x97\x89\xc9\xb8j.\x97\xd0\xd7\x1de\x92\xe8k\xcd^\xfa\x94\x9bR\x9f\x81s$\xf7z\xf6\xb8\xe4\x1e\x1a\x9c^Z\xf6\x06SC\n\x06HQ\x88\xef)V\x87#\xb9\x1f\x1f\xb7\x9b@\xcc\xf3\xbcj\xf2^\x91\xf8aw\xba\xfe\x1e=\xa0\xbd\x16D\xa39\xf5\x15\x7f5\x97\xe1\xbb\xb1\x02\xc6\xb6O#V\xe5aapK\xf8\xfev<\x1fML\x0fwjA\x13\xd2\x1c\x82i#\x0f&\x13\xe1/o\xb1\xf8\x17qJ\xc5\xff\xb8\xbaP\x044ki$u\xea\xe3\xcdD\"\xc4_\xa8\x97h\xa9^.*\x96dc\x0e\xca\x19\x07\x11VdT\xbe>0~\xce\xee>\xcaY+y\xb7\xc6\xee\xce\xc5v{np\x0b\xec~\xae\x0di\xb7\x80o\xe4\x91\xd9\xff\x80\x90$\xacw!\x1a\x84\xb1\xd1\x8e\xdef\x8ex\xf4\x06c\xd4\xa3\xbf\xbf\x9c\xdc\x90:\xfa!\xe8g\xe4\x99\x05\x0c\x83\x1f?\xbcvf\x02\xb46\xb3g\x03\xd4\xcaC\xce\x080kV@\x8b\xf7p3\x03\xcc\x9a\x1d\xd0\xc2=\xdc\x0c\x01\xee,\xe1[\xd6\xdd\xb9b\x18\xb1\xea\x9f\"\xbd\xa5;\x9f\xd3\xf5\x86\xc7\x94=\xb3\xffE\xe7\xa6\x99$2vw\xdeN\x9eA\x9f\xc3\x9f\x05\x84\x84\x06){!\xefV\xc8CH\x13wX\xa44H\xde\x84\x84\xc8i\x80\x13\xd4\x82\xc6S\x88j\xe0\x90\xd5F\x93\x18\xf5\xc9\xdf2q\xe2\x9a\xb8kB^\x83\xe4\xb6 \x93\xd8\x00#\xb2\xa5\x1b\xff\x0f{7\x91\xcal\x08\x93\xda Dq\x00\x87\xdc\x06\xdf(\x86\xe3%\xbcA\xf0\xcb\xcb\xcb\xff\xfd\x01'\xbfA8\xca\xe3#\xc1A\xa01\xe4\x15`\x90\x05\x1aF^q\xf6\x980\xe1\xf9-R!y\xc5\x08r\x10\xad\xa0\xbc\x82D9H\xa9\xac\xbc\xe2U\x96W\x844\x07i\xb5\x97W\x94<\x07\xe9\xd6b\xe1@\xf3ZB\xa4\x0b\x1a\x9cr\xbd\x83\xb7\xca\x8a\xa4\xb1\xce\xe4\x95V\xb3\x9c\xc4:\x88\x92\xeb`9\xc1\xcec\xcd\xdb\x00)\xd5\xcfH\xbf\xe3W\x90\x82\x07>\x1a\x1e$\x146+\x1d\x0f|\x94<\x88\x96$u\x01c>j\x1e\xc4\xd6\xae)E\x0f\x92\xd7\xda\xa5T=\xf0\xd0\xf5\x82oN\xf4VfR\xf7\x00\xa5\xefA\xf6\x82D\xa8|\xe2\x85wX\x01\x90\xc5\xc0?\xfd3\x94\xda\x07\xb1\x9996\x12\xb2\xd2\xfc H\xf5\x83\xact?\xc8I\xf9\x83\x10\xed\x0f`\x15\xf5\x0f2\xd2\xff J\x01\x84\xa54@XC\x05\xc4Z\xec\xfe\xa8\xa3\xcc\x18\x1d\x10\xd6P\x02\x11[\x03\x8a\x02\x10Z \xac\xa4\x06\"\xe6\x04*\x8b!\xf4@\xc8N\x11\x84\xf54A\xc8O\x15\x84utAXG\x19\xc4\x87(Z\xc8lDB\xc8N&\x84\x9c\x84BH\"\x15BNb!\x04\xc8\x85\xb0\x92`\x88\x8dq\x84r\x08j\xaa\x89\xd2\x0ea5\xf5\x101\xe8\x92\x11a9!\x11\xfc[\xb1\xe0\x12\x1f\x94\xce\x8b\xaf\xff\x0bI\x8a\xd8\xb47\xe4\xcc\xd9\x84\xa8\x08\xd1r\xac#,Z\xc6\x04}\x11!-B\x1e\xe2\"\xe4&/\x02B`\x84\xf5$F\xcb\x1as(\x8d\xb0\x92\xd6\x081\xb6\x1f\xf8\xe9\x8d\x90Bq\x04\x9c\x8d5\x8b\xea\xe8\xb7\xe1P]V\xd1\x1eaFc\xc4\xe8\x8f\x10\xadw\x94\x06 \xf3\xa8\x90\x80\xb5\xc7ZJ$\xc4h\x91\x10\xa4FB\x84\x1e \xa1VJ\xa5IB\x02U\x12\x10\xba$\xac\xa3LB\x1am\x12\x16Q'\xc1\xdb0Q\n%\xe4\xa3Q\x82\xbf\x14NO\xcbJ\xa9\x84\x95\xb4J\xcb\x94K\xb2\x84\xdcDK\xc8L\xb6\x84\x10\xe1\x12\x10\xd2% \xc4K\xc8F\xbe\x84\x9c\x04L\xc8N\xc2\x84d\"&\xa4\x901!\x9d\x90 \x89\xa4L@gg\x94\xbe\x073(|a\x82&\xa4\x934!\x8d\xa8 X5r\x126a-i\xd3\xb2\xe5P8!+\x8d\x13\xb2R9au\x7f\x88R:!\x81\xd6 \x06\xb5\x13\x00\xa5wBr\x10\xda\x8d\x97\xaf\xa2z:s\xf8\xbe$\xb5E\xf7\x04XK\xf9\xb4\x8c\xa9\xe3\x01\x1d\xda'\xf8\xa9\x9f\x10l\x87u\x14P\xc3\xd0@\x065i\xa0\xfcZB\x05M\xc2\xae\xa8b\x0f\xe0\x15\xf5of\xa0W\xd4c\x08\x86%\x08Y\xf9\x91\xa6CTl\x9a\x03C\xd2\xbbk\xd5jQ\x02\x86\xb7\xd3\xe3\xc4\x0b\xcf\xed!H\xc4b\xb2\x85id\x0d\xcfB\xf3*L{\xe9\x94\x8a\x95t\n\x84J\x81\xb6\xa1\x87B\x81a\xd63Q'p\xdaD*e\xc2\xa2K\xa0u\xf2\xcf\x17\xab)\x12\x02\xb1o\x0e\x85\x05\xf4\x08\x96\x91\x1a\x81\xd3\"VQ\"4 \xc2\xb0\x17\xa0C8T\x08\xf4\x8b`\xdd)+\xfda9\xf5a1\xed\xc1$:\x98m\xb5\x88\xf2\xb0\x94\xee0\xb4\xa8\xa08\xd6E\xd5\xef)>U\x88I\xa2\xaceE\xf5\x02\xa6F\xf0w\xe3\xa4a\x9c\xde\xaa\x0e\xeas\x89\x91\xc2)\x02\xb1\xdf\x12\xf3 \xbd\xbc\xa4\x05+\x878\xe8\xa3+\xd2\x1d\xdb\xb2\xa0\x8f\x86U^N\x93C\x7f\x97\xcan\xcd\x81\xc2\xa1<\x94u\x7fP\xaf\xd59\xb91\xafv\xa0\x87c\xd3T\xf8J\xf7\x13]\x06\xcb\x1c{k\"e\xf7\xec\xceC\xd5ewz2\xd4g{\xa0\x02\xb6\x1b\x0et\xc3\x81n8P\xe7\xe6\x0d\x07\xeayp\xc3\x81\x9aW\xbc\xca\xf2\xdap\xa0\xc8\xb5\xe1@7\x1c\xa8|r\xc3\x81\xaak\xc3\x81n8\xd0\x0d\x07\xba\xe1@7\x1c\xe8\x86\x03\xddp\xa0\xb0\xe1@7\x1c\xe8\x86\x03\x9d\\\x1b\x0et\xc3\x81n8\xd0\x0d\x07\xba\xe1@7\x1c(l8\xd0\x0d\x07:^\x1b\x0e\xd4\xb96\x1c\xe8\x86\x03\xddp\xa0\x1b\x0eT\x06\xc06\x1c\xa8\x07\x07:A\xab\x04\x81\x9f\x03\xe4S<\x12\x04{\x8a;:\x91IZ\x00\x84qt\x13\xf3(\xdc\x07\xe02\x83\xc0bUJ%s\x047\xd3!\xc0\x99\xb9%u\xaa//_.\x01\x83\xd8\x04C\x0c!0A\x1ch\x83Cm\x82/\x9c\x05\xb7\xf1\x02n\x82\xafH\x05\xdd`\xb0\x9b0\xfc\"\xd4Zi\xe0\x1b\x0c~\x93\xde^q\x08\x8e\x07\x84\x93\xfe\n\x07\x88\x93\x9e\xc9\x8cCq\" M\x0c\x8e\x13\x82hx\x80\x19\x9e1#\xaf0\x08#\x08\xcc \xf7\x0dy\x85\xc19^xN\x14\x83\xe1\x87\xe8\xc41,A\xfcJ\xb0\xb1\xe4\x95\x82[aA\xb0N\xb4z\xf2J\x01\xec\xc4\xab+\xaf(h'\xa9\xea\xf2Ji\x00y%@w\x12\xdbB^I\xf0\x9d\x19\x16\xe3!c\xf3\x9a\x0b\xe2\x897\xce\x1c\x18\xcf\x12 Oz\x0d\x17\x81y\xfc\xdd\x9fO\x8aQ8On@O\x00\xd2\x93\xda\x10\x99a= \xc0\x9e\x00\xb4'\xa5\xd0+\xe0=\x1ek~\x80O\xbc<\xa9K#\x0b\x81|\xa2\xab\xa2\x0b\xf4I_\xcf\xd7\x80}\xfcp\x9f\xc5>\xe5Z\xd0\x8f\x0f\xf6\xf3\x10\x05J\x00\xff\xb8\xf0\x9f\xe0\xb2\x12ZH\x98\x17\x04\x14\x9d\xdfc\xbd\x14\xf2C\x81b`\xa0\xdcp\xa0\xcc\x80\xa0\x08$h5((/,(\x05\x18\xb4\x02\x1a\x94\x17\x1c${k\x04\x1e\x94\x17 \x94\x00\x11\xca\x0e\x12\x8a\xc0\x84\x96\x01\x85PCA\xf0P\x16\xf8P\"\x80\x08}r\x16\xa8h5\xac(7\xb0\xc8\x0f-\xca\x0c.z\x08xQf\x80Q*\xc4(3\xc8(\x0c3\xca\x0e4\xf2C\x8d\x14\x8e\"\x05l\xb4\x1cn\x84\x1a\x13\x10$\x0f\xe0h\x15\xe4(\xb0\x81\x8c\xb8\x14A\xe0Q\x9a\xc7\x91\x0f|\x14\x86\x1f\xc5K\x93\x15\x82\x14\x06!e\x83!\xad\x05\"9\xe6\x84G\x83:\x0fy\xc1Hj\x18!\x15Z\x0bHJ@\xe1\x04AI\x89\xb0$/\xb6a&4\xc9o\x07I\xf8\xae\x06(\xcdi\x9c\x14\x90R\xbc\x15\x92\x80J\xb3\xa1Jx:<\x03\\)\x01\xb0\x14\x83,\xc5AK\xc1V\x9b\x03\\J\x83.\xe1\xe0\xa5\xd5\xf0\xa5d\x00\xd3R\x08\x93\xbf\x99\x92`LY\x81L\x81\xb2 =q\x15\x9c\xc9\xb1\x86\xc0\x9b\xb2\x02\x9c|\x10\xa7\x95 '\xb7\xc8.\xe8)?\xec)\x02|\xc2\xa1O8\xf8)'\xfc)3\x00\xea! Ps@P\x890\xa8Y@\xa8t(\x94\x07\x0c\xe5\x83\xbf\xa4\x03`\xe2\x80\xa8Y\x90\xa8dP\x14Z\xa1\xdc\xc0\xa8\xbc\xd0(\x0f8*7<*7@j}\x1fI\x02I\xa5\xc1\xa4\xa6@)/T*=\x8c\x8f\xe5\x1er\x02\xa6\x02\x90\xa9\xcc\xa0\xa90l*\x08\x9c\n\xb7I6\xf0T\x00>\xb5\x14@\xe5\x94\xdd\x84\x04\xf9\xa0Dc\x85\x86\x8d\xfd\x91\\)\xb9\xb7\x17\xb8\xdd\xf1\x063gk\xfcUca\xf4\xdb\xc7\xf21,o\x81g,jz\xc7\xce\x9d\\\xb7\xb7/{\x83 \n\xa9\xe3`N\xb4}\xdd2\xfc\x7f\xb5F\\\xa7\xce\xb6\xfe@\xae\xa8:\x03s'\x7f\xb7\x8c\xf0f\x94\xcaO\xdc\x1co\x03\n\x87\xa6c@E\xbcI\x04\xa8\x8cGX\xc3H5\xb3B3\x0e\xec\x17\xe6E}\xc4\xff\xd4\xfd\xe1B\x06>t\x94\xd2\x08\x95\xd9'\xd8\x9bU\x15\xcal\xe7\xc2\x88=vnI'\xa5\xc8J\xd6\xe9@k\x07}-;\xc2^\xc6\xaan\xcbN~\x03\x1c\xf5\x83\xe0\xf0\xd2 ~gw\xdd\xab{\x99MV\xa6bG\x92\xfe\xd2\xec\xe9\xe9\x90\xd9tz\x9f\xdb\xf3\xba\xb2\xbe\xaaL\xe9)\xd9\xd4\xf2\xcf\xe3j'\x86\xbd\xfc\x9b\xd4\\[\xd2\xc3\x0f\xae \x93|\x9b8\x07V\xb5\x087?\x9c\x0d\xabc;\xe8\x9b!\xd4\x9b\xec\x93\x96A\x9cZ\xfb\xe9\xf4\xa7w\xa1\x83\x96\xed\xbb\xde\x9c~|\xfb\xfa,p\xc3\xd9\xdb\xff}\xf6\xf9\xe5\xcf\x81;~~\xfb\xd3\xcb\xd7\x7f:\x7f\xf9\xcb\xe9\xbb\xf7\xe7\xc2\xd10\xef\x1cN^\x8e\x97,\xbct}*\xafjq\xee\xb2\xf5\xc9\x8c\xc6\x94\xe1N&\xf5\xea:Z\xf4m\xc9\xec@\xd3UO\x84h\x9f%K(.O\xf3y\xcan\x1c\x00Mj\xe8k\xe9zM\n\xc4gx\xe5@Y\xefj)\xefN\xee\x82\xea~\x9b\x17\xce_\xcc\x17[\x0d\xa0\x13Z\x9dh\xae7M!\xc3\xdev\x8a\xe8\x86\xb6r \x12-6\xa0c\xe0\xb2m\x0ep\xe6@\x1e\x90\xfe\xf0\xc2\xfd\x93\xc8\x17\xc1e/\xd6\xcdI\xb1$\n\x84\xb7\x83x\xf1\xbd\xc4yL\xdfq\xdd\x1fH\xfd\xac\xa5d/f3F\xefXO*g\x97\xc4\xfd\xc3\xa3\x1e52\x13\xe2\xb4\xac\xf9\x84\xfd\x8dE\x0d#\xdd?\xdc\xbb_\x84~\x94mpA\x8a\xaf\xb7\xa4\xddwV\x92\xc6\xfaF\xd6k_\x1e\xca\xba\x91^\x80\xd1o\xa0\xa5\x87\xe6FI\x8a\x8a\xdd6o_\xf5\xe8\xa1\xafX9N\x02\x89\x00e=\x85\xee~\xe1\x8f?\xb6gFat:\xcaj\x89\xb0\x10\xbft\xe5\x959OM\x06\xad\xb6lE\xb1\xed\x19o\x98i\x9b\xd6c:<\xf7\xcb\x82'\xaf\x00\x17%\x13\xb8?g\x0d\xd0?\x18\x03J~\x9d\xaf\xf4\xbe\x13cC5\xfaP:2v\xed%\xeb\x03\xbdc-9\xbf(Yw\xde\xb1\xa6\xc5Uh\xe6\xa8\xf7\xd1\xca\xc1+F\xdd\x8f\x89?\xe5\x9fs_\xf3\xae[\xb0W%{)\xdaH\xaa\xfeZ\xc9$\xf91\x05\\z\xf0\x8fx\xb3J\xa0\xe5d\x86\x15\x00\x0e\xeeY(O\x8c\xd6]\xdf\xd2!\xe1\x0f\xb4\x16\x9e\xaft\xad\x19\xf9J;\x99+?\x94uy \x95\x92\xf44\x0cN\xf7\x1c\xb2\x102\xe2$ve\xd2`Y_\xa1\xa5\xa8\x1b\xfeV>\xdd@G.uzP\xfe\x9d\x7f\x80z\xaf\xf2\x83ES\xab\xc4$\xf42\xe7\"\x0d\xf1\xbe|^\xd6\x97\xcd\\l\xfe\xccA\xea\x0c\xcf\x89\xdb;\x96B{\x17E\xd3J\x97k\xafG\\7:\x19B\xdaV\xffSwj\xc3\x9c\x8e\x15\xf5BiW\xe8\xa9:\x03\xf4\xd8_Te!\x86\xc8wF\xb1\xc4\x90\x1c\xb4\x91\x85\xbb\xc3'\x02\xde\x84\x04{8<\xc0?\x19N[\xc2\x08\x9f\xfa]\xab|.t\xf8\xd8\xbeV\xdc\xcf\n\xfaXa\xff*\xcd\xb7J\xf4\xab\xfc\xe3{\xa9?\xe5\xf5\xa0\xbe\x91\xf7\x84yN\x0f\xef5\xcd\xf0\x98\x1e\xda[\xca\xe2)\xf9\xbd\xa4\xa8\x87\xf4\xed\xbd\xa3\xd9\x9e\x91=U\xca\xe9\xc47;M&\x82\x1d\x9c\n\x90\xc8\x10\x02R\xe2\xf2\xd3\xb4>k$~HZ\xb0B\xef\x1dt}q\xcd\x1f\xab\x9a\x82(9u\xa4\x03\x98\xd8\x96\xa1\xf0\xee\xa4\xf8I\x94k\xd6\x9eWN\xb3\xd3X\xcb\x0c7\x85\xa1\xa0R\xafc\x11\xde\xb7e\x84\x90\xfa\xc1\xa3\xf9`\xa3\xd9\x00\xa3^\xa8([\x0e\x12\xcd\x05\x0f\x0d\x03C\x17AB\x17\x83AE}\xed\xbd\x90\x17\x06\xba\x18\x00*g\x16\xcb\x9a\x07\xfa\xb9\x06\xf4)\x9cV\xbb6H^r \xd0\xd3\x0f\xea\\ \xe7L\x02r\xa6\x836W\xc05W\x005\x91 ##\x1c3/\x103\x1b\x043\x0e\xbe\xcc\x06\xbb\xf4\x01.\xd7@-QX%\x92os\xe7\x9b\xa5PJ/lr!`\x12\x81J\xce\xdb\x81Ct\x05]\x08\x89\x1c\xe1\x8fX\xfb~\x17\x7f\xf7:\x00\xa4\x04<\x1a\xe6\\\xe8c\x06\xd0\xe3:\xb8\xa3\xd5\xcb\xed\xc5p%\xc4Q5\xb4iq\x0d\x981\x88\xd4\xf3\x00\x18\xa3\xd0E\x17\xc5\x94\x0eWt\x9f\xfd+V\xd7E\xe0\xc4\x94\xca\xc6\x00\x89\xfe\xbaEA\x883\xe0\x87S\xa4\xc6J\xc8a\x10l\xe8\x87\x19\x86\x00\x86h+\xa4\x82\ncpB\x1bH\xb8\x02B\x98\x00\x1e\x9c\x0f\x1bD@z1\xa8`&\x90 \xf2\xe6\xbfN\x03\x91+ \x816\x04p\x0d\xf8\x0f\x01\xfb\xad\x82\xf9\xd9\xb0\xbe\x9c\x80>/\x94\xcf\xc67\xd9\xf0\xbd<\xc0\xbdl\x90\xbd\xbc`\xbd4\x98^\x14\xa0\x97\x08\xcdK\x01\xe59\xe85\xf7m\xa9\xf0\xaa0\x04/\x11|\x97\x00\xbb\x9b\x149'\xd4n\x15\xc8\xce\x05\xd5\xe5\x83\xd3\xe5\x03\xd2-\xff\xbaQ\xf0\\\x0c6\xa7\xa7\xef!\x11\xb28\x1b\x9a\x98h\x89\xa46\xc7<\x8b\xce(\xe9\xec\xa9al\x84\x97\xb1f\xf0S\x91<\xcbWz\xffXGF:\xfakO\xeb\xc29C\xcd\xdafx0F~'_\xdb\x1d2%\xfa\xdfz+!Ou\xcb\xf1\xe2\x1e\x08\\\x957T\xf4\xd1\x96v\x9d\x8e\xb8\x8a\xb3 G\x83l\xe2\"\x1c[\xa1e\xc3\x07NE\xee\x810F\x8a\xafj#\x86c\x92\xc6\xb0\xa9\xf5\xc9\xc6\x1c\x94\xf8D\xde\xe44k\x8e\xcf*zC5]9\x94\x99\xfeT\x1e\xfa\x8a0\x8d\xb7J\x0e\xd4>\xcci|\xa68\x16\xefa\xaap\xe1\xd6\x9aT`Do\xc9\x7f2\x0c\xbc\xa5\x9fQ&b\xc8\xad\xf1\x153\x95\xda\xaeHg\x0d\xedI\x1d\xf4\xcf\xba\xcc\x86`\x05\xdf\x08\xf7L\xc82\x0c\xc7\xb2\x8a\x01*J2Qep\xca\x81\x97\x05\xd6\x9cf\x83\x00\xff\xc2;\xff\x9fH\xf7G\xf1\"\xb0\x0e\x9d\xedk\x91\x96\xbb\x84\xdb\xa6\xfd\n\xb7*H&\xa3<\xec\xceE5\x1ei\xcb\x0b\xb1\xb3j\xb1\xe0 \x9cX\x1d~\"\xdd\xe7n,0\x99hc\x90\x82\xc9\x90\xb0\x16\xc9\xd0\x05\x92\xb1<\xcf\x07\x96?\x1a\x80B\xfe\xafa\xae]\xf5)g\x9cj\xb80x\xf3\x860\"\xb1\x13\xf7\x12\xda\xd0R\xd6\xb7|&\x14\x896\xbd\xe0\x8a\x10e\xbd\xafhk\x08\xdd\xc0\xa9\x9dT\xf8\xe5\xf3\xa73$vU\xd1\xfa\x8a]\xf3I\xf2\xb2\xbc\x93\xfd\\\x1cn+F?=\x92\x960*\xdf._\xca\xd7\x18\xbe\xe6\xe3\\\xd5\xa1\x00\x93@\xd7\xc2#\x1a\x9d\x06\xf9\xb9\xb9\x9a:\xb8\x02\xfel\x8cYO\xbb\xf8\ni\x96\x11\xd3;c\x08(\x032\x9f\xcc(\x1es\xfe\x1ah\"\x88\xea\x96\xf9\x8a-\xaf\x87=C1\xa8G\x16\xac\x93\xbe\"Dp\x88\x8b\x94\xe5zM@\x97\x0f\x86\xd7\\4ME .\xf5\x10#T\xc8K`\x98G\xe5\xb3\xd2\x80\x13\x7f\xa5\xf7\xcfF\xd5\xae\x13 ]\xd7\x14\xa5\x88\x19\x8a\xe87n\x90\xd4\xb27\xdbQ\x84Xq\xa4\xfe\x96X\x0e:SV\n\xf6\xdc\x95\xe1_^\xa4\x13\x84\x03umlD\x1dC\xe6\x90d\x08\xe3S/\xe3\xaf\xe8UY\xbf\xaa\x9a\xe2\xeb\xc9\xf0\xb7\xb7\xf5\xde\xfa\xcb\xebkZ|=\xbbs8\x13\xa6\xa57\xb4*oh{v\x87\x90S\x7f&\x8c\xb6'S\x8f\xf2 \xc5\xa84\xf1\xa1\xe7\xed\xcdg\x94\x8e\xaa\x89`7cZZ.i\xa6\xc4\xcb,{zj\xb5\xfe\x8c\xce\xf3\xe2\x9e\x98_\x96\x00\xab\xd7\xcfX\xfeY\xcc1;\xbbKv\xc5.\x9a=\x02\xa3l\xf6\x03\xe7B\x9do/\xb2H\"';\xa6\xcb\xb1\x03\xf1g,\xd5\xaaA\xffF\xb3\xfb\xa6\xb1\xb5il\xa1\xd66\x8d-\xd84\xb6\xf0\xf7\xac\x04eh# \xd0\x0c\xf4\xc9d\xb8\x86\xbcV\x806\xe4\xb5\x02\xba\xe1\x1b\xe8\x9e\xa2f\x03u\xc8+/\xb4C^\xd9\x00\x1e\xf2\x8a\xc3<\xe4\x95\x0d\xec!\xafMck\xd3\xd8\x92a\x9cMc\xcb\xb8\xd6\x81N\x1csl\xd3\xd8\x8a\x03U\xe4\x15S\x97\x8a\x83V\xe4\xb5il\xcd\x03\xb9\xc8k\xd3\xd8\x12W\x0c\x14#\xafMc\x8b\xad\x80\xcf\xc8k\xd3\xd8\x9a \xbeq\x8b\xbcil\xe5\x00\xec\xc8+/lG^i\xe0\x1dyE!<\xf2J\x04\xf2Ln\xde4\xb6\xc4\x95\x13\xf8#\xafU\xf0\x1f\xc7\xda\xa6\xb1\x95[c+\xbcC\xd1Ag\x99\xd0\xd1RK\xc3_e,@\x06\xf2\xe9^\x06\x0e[\xfak_\xb6N``$_\xdbM\xc4\xae\x9b\x8e\x8e6\xa5\xee\x8e\xf8>\nS\xc3{\x9aL\xe76\x97\x82\xf1/2\x15\xceF\xe2e\xcf\xae\x05\x90\xc99IF\xbe[\xf1\xc4\xb9\xb5\xb3\xbb\xc7\x12\x90CX\xdf\xd2n\x07oIq=\x94|\x000I|\x8e+\x1fBD'u\x93Bl\x90\xa3\xe2k\x97X\xb7\xf8\xb8\x15z\\P2h\x8a\xa2o]\xdd\x95W\x02\x0fpCk=B\xf4sv\x81\x9e\xe8\xd0\xa7H\x11\x0f\xf7\xe1\xdf\xcc\x89\x90\x94\x1d\xb4\xf4\x92\xb6\xad\x0cH\x11\x9d\xb0(\x0fb\xb79\x82\xb6\x8e\xe4^\xfevI\xed\xd4\x8a\xben\xaf\x9b\xcaY\x06=\xa7}\x1c\xe8\xa1I\xcc\x9ck\xe6:=4\x1a30\xee\x87\xc5_e\x8f\xd3\x1f\x00|y\x15\xa9\x1d\xd7\xf4\xec\x1c;\xdb\xcf\xfb\xfe\xb8B\x95#\xba\xa5\xde\xa3\xf3?\xe6\x91\x7f\xca7\x91\x93\x92\x84\xa6\x18\xc0$1\xe9\xd5\x8d\xfd\xf5.\x86\x1c\x92:B\x85Oc\xd7d\xd2\xdb\xe9\x1d\xa3uW6\xf5\xb9\x0c\x06o9\xa1-'\xb4\xe5\x84\xb6\x9c\xd0\x96\x13\xdarB[N\xc8\xbe\xb6\x9c\xd0\x96\x13\x8a{\x1c[Nh\xcb M\xae-'\xa4\xae-'\xb4\xe5\x84\xb6\x9cP\xd2\x9b\xb7\x9c\xd0\x96\x13\x1a\xae-'\xb4\xe5\x84\xac+5\xde\xbf\xe5\x84\xb6\x9cP\xac\x8f<`N\xc8w\x1a\x83\x13w\x96\x01\x8daw\xa2\xff*\xbegA\xea1T\x7fa\xfb\xdd\"\xa4\xed$jn\xafi\xad\xa6#\xa9\xf3a\xbe\x87o\x9f\xbb^\xab,\xefx\xbf\xe4\x0e\x90\x9c\xc0:^\x0e{A\xf1\xc4Ly/-H\xfdX\xec\xf7$\x1be/\xd3.N|^\xa8l:z\xabuS\x9f\x17m\xc9\xca\x82T\xe7[0~\x0b\xc6O\xae-\x18\xbf\x05\xe3\xb7`\xfc\x16\x8c\xdf\x82\xf1\xc8\xb5\x05\xe3\xb7`|\xdc\xe3\xd8\x82\xf1[0~rm\xc1xum\xc1\xf8-\x18\xbf\x05\xe3\x93\xde\xbc\x05\xe3\xb7`\xfcpm\xc1\xf8-\x18o]\xa9\x81\xd6-\x18\xbf\x05\xe3c}d\x0b\xc6g\x0f\xc6\xdf\x0f\xbd\xae\xbc\xaa\x1b\x93P2\xd9\xb3\x9d\xdd\xbd2\xe4\x97\x84\x14\x93\x101\x9dh\x80\xf2& U5\x90P\xf8\x7f\xa1\xb9\xa1C\xa0\x88\xf4\xecz\x99|\xee\xc0:\x19\x1e\xc4\x98\x02\x83\xfdA\x17\xb2g\xd7M[\xfeE\x8e\xaf\x96Vb\x87\xe4W\x8c2{\x94\xde\xbc\xcb\x10\xa3\xac\xd2\x89&p\xc8\x13\x0fy\xab^R\xfd F\xa6\x8b\xa1]\x85\xe4%\x9c\x9c\x84g\xa7?\xf3$\xcd\xf1\xf5S\x1a\x91\xf1w\x15\xead\xc5\xb5Z1\x95\xa2\xe3@\xfd1\xccM\x19D#\xebgJ\xf3\x19N(+\x9a\xba\xa6\x05\xe3\xd3\xd5\xf0BqT\xbd\xa9\xf0f\x18\xac\xca\xaf\x13\xff!$\x97\xcb\x1d\xb7\xa6\x13}\x03\x111;\x1b\x04i;F\xea=i\x95[4\x84\x9d.\xda\x86\xec\x0b\xd2\x89\xc2\x99\xd2n>\x9d\xb2W\x83\xfc\x18\x8bk\x95iF\xd5\xa2o\xee\xe4\xa0|\xf9'\xe6\xc9=\x05\x82D\xb1\x98K\xd6|S(\xd7\x943\xcf\x941\xc7\x14\xc8/\xad\xca-\xe5\xcb+\xc5rJ\x0b\xf3I\x8bsI2~\x8d\xb4\x967\x8f\xb48\x87\x84\x9e\xa3\xe6=Im]\xee\x08\xfa\xa3c\xcf\x977Z\x923\n\xe5\x87V\xe7\x86\x92\xf2Bsr@\xab\xf2?+r?\xe8\xb4\x925\xc7\x93;\xbf\x931\xb7\x93\x92\xd7\xc9\x98\xd3\xf1\xe7s\xb2\xe6r\xf0<\x0e\xe2\xe2c\xb3\xd4\xd2\xfc\x8d\xcc\xd58\xe6\xb0\xdc\xcd\xe2\xbc\x0d\x9a\xb3 ,\xc5\x81\\Ml\x95\xce\x95\xa3\xf1\xe7gB%X\x97\x97q\xcef\xc3Ng\xcb\x94\x8fY\x97\x8bqF\x89\xbb\xe0\xe6\xcc\xc10$\xff\xb2.\xf7\x12I-xs. \xf9\x16,\xf8:'\xcf\x82=\xffW\xbc\xee\x0bs+i\x95\x8f\xe7TB5M\xc8\xa5\xcc\xca\xa3\xd8A\xa7\xd5\xf9\x93H\xee$\x947 \xe7L<\xad\x92\x9e+\x89\xe7I\xdc\x1c\xc9\xaa\xfcHRndI^\x04\xcdC\xc4\xf3!\xd9r!\xe8\xfb\xad\x9e\xb4*\xff\xe1\xe6;\xd6\xe4:\xd0\xdc\xc6\xaa\xbc\x86\x9b\xc7\xc8\x9b\xc3\x08\xe4/\xdc\xb0\xae\x9b\xb7\xc8\x95\xb3\xc8\x98\xaf\xc8\x9d\xabH\xcdS$\xe4(\x92\xf3\x13i\xb9 $\x8c\x8f\xbd55\xd6\x1c\xcbG$\xe7\"\x92\xf2\x10V\xe1\xf3\xe6\x1fV\xe5\x1e\xb0\\C\xce\x82\xcd\xcf\x88\xcbG\"a\xab\xc4qR\x85q\xd8\x16*\x9d\\[\xa8t\x0b\x95n\xa1\xd2-T\xba\x85J\xb7P\xe9\x16*\xb5~\x8a\xad\xd2[\xa8t\x0b\x95n\xa1\xd2-T\xba\x85J\xb7P\xe9\x16*\xddB\xa5[\xa8t\x0b\x95n\xa1\xd2-T\xfa\xb7\x0b\x95\xe2\xd2%\x99eK\x18\xad\xf7\xb4=\x945\xdb\x91\x8b\xa2\xdc\xbd\xbd\xa15K\x16\x87\x10\xb7\x8c\x9f\xc2\xdd\x98\x11\xc6\xda\xf2\xa2g\x0f\xad\x1f\xf1\x95\xde\xe7\xd8&f\xdbo\x96\xf5\x9e\xde\xe1\x86.\x9a\xa6\xa2\xc4\xd4\n\x99|\xd2\xc7\xe2\x0b\xbc\xd4\xed&Q\xf4]Y_U\x94\xd7\xf2\x99\\\xd6\x8e\xa4lO\x80t]S\x94b#\xa4\xd6$\xa0\xfc\xe9\xddc\xb7\xab\x0c\x03D\xd8\x97\xd1\xa2\x0e\xc8\x18E\x82=\xbd\xa1\x15o^){\xc2\x18)\xae\xcde\xcd\x10:1\x00\xef\x1fiwl\xea\x8e\xbe\xa2We\xfd\xaaj\x8a\xaf'\xc3\xdf\xde\xd6{\xeb/\xaf\xafi\xf1\xf5\xec\x8ewz\xeb\xf97\xb4*oh{v7x\xa8?\x13F\xdb\x93\x89\xa2 \x1c\xc8=\x1f\x10\xbf\xf6\xb4\xe5\xeeK\xdf \xcd\x131\xd0D\xcd;o\x9f\x1eZ4\xb9sO\xfa\x14\xda \x90\xcfo\xf5\xa0\xd4\xc7\xac\xfe\xe2\xf6\x94\x87\xe9#J\x1d\xa6?^\xb5dO\x07\x89\x98\x0f\x15\xa9\x93\x9b\x89;\n\x91\n\xfb#\x1f\x9f(\x93s\x97p74\xe1@\x97G&.\xc4Oz*\xec\x0dD\xbd\xbam\xb2f\xaa\x88\xe0\x10\xcfh.\xd9-\x9f\xa6y\x8f>\x1e+\xb9A\x151\x1aR\xc1\xa3\xa6~\xa6\x8c<\x82\xa29\x1cH\xbd7\xc3\xee\xfb^T\xc3\xf8\x0b\x1b\x88\x19c\x7fW\x9e\xb6\xe1A+\x9b\xe2\xbb\xf0\x01F\xf7;8\x15\xa1=Ru\x8da\x8e\xd7fb\xbe\x81=e\xb4`|\xcd\x11\xf182VAW\x8d/Xr\x9d\x00\x02W\xe5\x0d\xad\xc7\x06\x13An\xd3\xa2.\x8a|\xa0\x95}\x80\x0d\xcd\xca\x1d\x9a\x0bJk\x11\x9eW.\xbe~\xe1 \x94L\xb4\xbban\x1a\xddS\xd1\xf2!11\x96\xb5\xec\xa0\xe9\xd9\xb3\xe6\xf2\xd9\x9e0:\xae\xa0\xba8g\xe5\x81Bc\xea1\xfd^2-\xca\xc9\xca\xdbRR\\s\x1fI\xeds\x06\xfb\xa2;\xd0\xbb\x92\xe9}\x1a+\xa3\xbdP\x0f;^\xa2g\xfc~\xbc\x7fNH!|\xa3!h;S\x06\xc8X\x91\x83\n\x1b\x1ei\xcb\xed\xd3\xbd\xb9q\xfc\x99\x92\x1b*\x9a\x965P\xb2\x0e\xfeB\xdbFmLT\x9e\x86p\x97\xe0\x99\xa44\xed\x87F\xa8;F\xc9`j\x16\xd3eJt \xd7L\xb3[\xd8\xdc\x8a\xbdW{\xca=\xdfr\x8bo\xa9\xc2\xd6\x1d\x1d\xbe\xc8T\x07\x0d-3F\xc3\x11A$cU\x1aB\xc4\xc3\xa0\xaa/5S\xa8\xac\x8b\xaa\xdf\x8b\xac\xc63\xfbt\xf3\xae\xe7\xabW'\x86\x08\x13\x83\xbbd\xb2\xa3\x8a\xf8.aM\xdbA!\xd2\x82\xa4g\x0d_\xd7\xa4\x14\x9a~\x0f\xd3\x03UO3\xe7E\xc5]\xbc\xf3\x8e\x11\xe6\xf45\xcbS\xc1\xfd\x14\x86&\x97\xbd\xfeE8d\x9d1\xad\xecO*\xe7K)gK({\xd3\xc9X|#1\x99\x9c+\x95\x1cN$/J#\xe7M\"{S\xc8y\x13\xc8\x9e\xf4\xf1\xca\xe4\xb1\xd3\xdcn\\)w\xe2xe\xda8s\xd2xE\xca8w\xc28[\xba8o\xb28[\xaa8\x9e(\xce\x96&\xf6%\x89\xd7\xa4\x88\xd1\x940\x12\x97q\xe7\x9bu\xe9`$\xfd\xbb0\xf9\x8bl\xc5\xbd\x0b\xa5w\x1b\x1e^A\x17\xa6|\xc7\x14/\xd6\xbe\xdf\xc5\xdf\x9d9\xd9\xeb\xa6z3$z\xb3\xa6y\xed\xc5pe\x8aW5\xb4iqMR7\x98\xd5\xf4$t\xa3\xe9\\7\x83\x94\x9e\xcau\x9f\xfd+V\xd7EI\xdc\x94\xca\xc6\x12\xb8\xfe\xbaE\x93\xb73R\xb7\xd3H\xfd\xca\xb4m0i\xebO\xd9\x86\x12\xb6h+\xa4&kc\xa9Z;Q\xbb\"M\x9b\x90\xa4\x9d\x9f\xa2E\x12\xa4\xb1\xf4l\xa6\xe4,\xf2\xe6IO\xc9\x9a\x96\xcd\x9c\x94\xcd\x9a\x92\xcd\x99\x90\xf5\xa6c\xed\x1c\x97\x9d\x8a\xcd\x93\x88\xcd\x96\x86\xcd\x9b\x84MK\xc1F\x13\xb0\x89\xe9\xd7\x94\xe4\xab\x93zu\xdf\x96\x9a\x86\x0b\xa7]\x13\x93\xae )\xd7I\x91s\xa6[3'[\xf3\xa5Z\xf3%Z\x97\x7f\xddh\x925\x96b\x0d'XO_\xbd~Fk\xbe\xa5\xd9\xab|\xa9\xde\xb1?+E\xd3\xc8\xc8\x9cJ\xce\x0c\x114\x90\x114\x10\x11\xb4\xe9TV\xb2n\x88\xbc\x1d\xab\xe9\xa8\x16\xb1&\xf1)\x0f\xe4\xab\x9c4\xc5K\x87\xa8^\xa3B\x15mK\x0b6\xbe\xedIG\xab\xcb\xa7\xea\xa5\x86=\xf1z\xb8\x10\xbbM\xb3|J\x98\xe9\xc4|w\xd7\xa8,\xf1\xa8\xffoT\xf8\x86\xb6\xe5\xe5\xfd\x18\xff\xae\xe9\xadS\xd9\x89\\\x94\xdch\\\xdc\xab'e_<\xb6Ms\xa97\xda\xc6\xcd\xc7\x96\xde\x94M\xdf\xd9I\x0dQ\x80\x1d\xdeB\xf2\xb4\x82\xd3W\xaf\x87\x12\x8bDw\x03Gn\xa3c\xd0\x1d\x9a\x86]\xf3]i\xd16]'\x1a\xbb\x9eled\xdb\xaaj\xc8\xc2\xe3{\x99\x0f\x15\x19vq\xc2\xed\x1f\xf3\x83\xe4\xa2\xe9\x19\xaf\x9a\xb4>\xb40\x1f\xd5\"\x19P2\x15IS\xb6D\xd3\xef\xfc)\xa9\xff\xd5\xd3\xf6\xfe\xa5L\xa6\xf0\xf7\xea\xb4ar\x9a*W\x10\xfdZ\xe7)d\xb8m\xa2\x12e\xc6\xd1y\xcd\xe1\x96\x8c\x19\xa0@C\xfa*\xa7\xdf\xd2\xea\x7f\x8byRg\xc9\xc4S\xcf\x8d\xc7\x94\xb5\x8f\x1f^\xeb\xbe!\x1d\x8eX\xb3\xbe\x96\x91\x8aE\xcdz\x1cR\x85N\xf5D\x0b\x94z\x16\x15\xaf\x98\x0c\xf1\x9d\xf5-\x92B\xe8\xd3l#,\x0f\x9f\xaf\xc9\x8c\xc7'\xc3\xe2s\xa8T\x0e\x95\x9a\x80\x99\xe7P)\x02\x11_\x82\x86\xc7D\x0f\xe5P)\xad\xe4P)\xc8\xa1R9T*\x87J\xa5\xc2\x99\x93a\xcci\xf1\xe58l9\x88+Gb\xca1xr\x0e\x95\x1ad-\xc2\x8bs\xa8TT\xa8\x94\x07\xd9\xf3\xe3k^\x90O\x17\xf3\x9a\x96\xa3F\xe2\xea\xf2T\xc3\xfb\xca\xbb\xf5j]7l\xc5\x9d\xb2\x8a\xedV\x9f\xff\xbc:\xc5\xff\x8c\x06\xf4L\xf4\x0e1n\x15\xca\x81\x80\xf0\x80\xa8r\xd1\xc0\xaa\xc1\xd2'}\x10V\x1d\xf7\xfa\x1e\xff\x13\\\xdf\xbc\xbd9\xbb\xfdxq~q~s\xfe\xf6\xfd\xf9\xbf\x9e\xbd\xbb\xfdxq}yvz\xfe\xdb\xf9\xd9;\xe2Y\xfe$\xf1\xe7\x9b\xab\x7f\xf9pyvA\xfc\xe2\xf8\xf3\xe9\xfb\x0f\xd7Z\x05rc{\x13\xdd\"\xf7\xb1s\xf1a\x109\xe1F\xfe\x96/M9B\xa50\xfa\xeb\xaa\x1f:\x04T\xf8R\x13#:BA\xb1\x85'\xc0[r\x02\xb2\x83'\xc0\xff\xc9\x9d\x80Q\x13\xc7VPp\\\xdf\xc0;\xb9\x91_\x1b\xd1x\xa3q~\x03o\xfb\xa6s\x1d\xf3\xef\xdc\x11l\xbb\xa2\xe9\x18n\xdd\xf5\x81 /\xfa\xa1\xa86\xedC\xf18>\x12e|\x1bSZ\xb1\xe6\x1al\xc76\xf7RZ/\x05\xda\x8e\x1d\x14\x0c\xb4\xae\x8fU\xc7\x9aC\xd1tO\n\xbc'*\xa1jX\xd7\\\xb3t\xa6\xf8\x15|8\xb0J=\xd9\x1aYZ\x1bVl\x04\x16\xd3\xb2\n\xc37\x1a\xb6f\xe5g4\x97X\xd7\x92\xd5\xe3\xc72\x1b \xe2U\xd6\xbb\xba\x95\x81 \xeb\xa2\x82\xaa\x06\xee\x98\xb2\xa6\x8f+Ru\xd5\x8d\xaaJ\xab\xc1\xa8\xb4n6\x8c\xaf)ke\xaa\xb8\x1c}A\x96->\xcf\x84\xecc%\xffg\xea\"\xfdp\xf5\xee\xec\xea\xf6\xe2\xc3\xc5\x99sm\xe2#\x1f/\xc4\xbf\xc9\xdf\xcc_\xfa\x05\x17\x90\xee^g\xae\x86\xbd\x111)2\x0f&W\xa5j8\xd4\xd8\x8d\xbf\x9f\xd1\xf47j\xc4Un\xe0\x0d\xe6&\x15h\x9dp\x81\x84\x98\x13\xb9\x01\xee\x8b'\xd8\x94\x02w\xd86\xf5\x1eW\x05\x7f\x00F \xe9\xfa\xc0\x93'\xf8\xc2\x1a\xc6\xbfw\xb7\xa2\xdaa\xb5\xa2h\xf4&\xb0\xaf\xc5\xba\xdb=)\xa3\x16k\xa2\x84K\xd9\xfa\xe2\xb1\x95\xb9\xb1\xb2\x1cJ<\x8a\xb29\xd4Mw[n\"\x81(?\xde$`\x13\xe7\xea\x97\xdd\xad\xbfH\xfb\x14\x018\xb1~(\xceFm\x81?X\x7f\x8ao\xae\x1a\xafa\x88\xdc\xcd\xeb\x07^q\x87\xb7\x0f\xf5a^\x02\xe4\x88\x84\x89\xbb\xb2\x15\x9c\xc3P\xdd\xc0f5\xed\x89\xd8mp\xba\xca3\xa3b\xec\xd4\xdcj\x05\x99\xa4\xcfS\x01\xd3\xaa~\n\xab\xb0k\x8a\xcfL\x85?Hp\xd8\xec\x0d\xdd\xd0\x1f\xebC\xf1\xfbq\xd0F\xf2e\xb5r\xca\x16\x8a\xfb\x86\x89\xf8\xe0\xba\x92\xe1\x8dcEMd2\xee{/\xed\x99~\x9f=\x94\x07\xb6++\xa6\xdc;\xbeL~\xaa\xab\xb5R\xdbj\x11=\xc1\x1d\xeb\xbe\x888B\x89\xabJ\x81\xfbzs\xdc1\xeetB\xcb\x0eE#\x18\xef]\xbd~D\xe6Z5[\xec\\\x92\xbb\x13;9\x13z\xfd p\xebz+\x85q}\xce\xbb\xd3\xafb1e\xcc\x87\xa5\xba\xd7\x1etZo\xd6:\x8e0\xe1\xac5I~-\xf7ZL\xb6\x0e\x8d5H\xad?\xdfD\x8a_w\xf2\x05}\xb4\xfa R\x8c\xe4\xe8\x02\x1cc~\xae\x16\xd2&\xdb\xce\xe3?g\xdb9\xdb\xce\xd9v\x8eZ\xa4\xd9v\xce\xb6s\xb6\x9d\xa7\xec\xe1\xd9vNh;\xc7\x1a\x81\xb2Z1{\x86AP\xdfc\xa6\xbdf\x08\xa2\xb5\x91ee\x11\x06\x1b2\x18\x03g!\x9a)\xf6\x04|@\x8a\x1a\xeaCl\xd9iM\x7f\xe0\x9fU\xb7\xe6\xb4~\xe8*<\xa0\xbe]\xaa\x9bR\xdb1*\x9b\x1e\xa0\xc5\xaa\xfa\x1b\xa8i\xaf\x8a~\x16\xf5,\xa7\x9a\xf8\x92N{Q\xd6\x88\x16\xdf\xf05\xa8)q)\xdat=\x18\xee\x11f~\xdc\xd2\x1a}U\xd58c\xa1M\xf6\x8cH\xa1x\xa0\x95\x10\xdb\xb2\xdf\x8f\xacZ\xc7\xde\x91q\xf4d\xc0\x92\xce\xb4\x92\xa8j\xd8\x14]\x11)}t\xf8h$\xbbg\x9f\xb84\x83\xa7j\xfb\x9a\xf9'Zy\xd6\x8b\xf6%\xfb\x89\xc1'\x948)S\xae\x91a\xa9\xd8\x9a\xb5\xad\xcd=\xebZ\x1c\x15!\xcb<\x9b\x11\xe0\xa7T\xc8\xd4U0d\xca!H\x0b\x96\x8aa\xc8\x96\xe5E\xca\xe9\x90\x96\x11F\xc9\xc8\xa2\x9c\x0e)\x8e\x14B0\xdb\x1a\xa3\x9c\x0ei\n\xf9\xb3\x90\xf8IL\xfa, |\x16\x90=\x84\xc2HH\xeb\xa4\xa5t\x92\xd19a*'\x19\x8d\x93\xd3!\xe5tH\x13\xe8\x96\x9c\x0e\x89 S\x96\x10)1\x19\x82r:$\xad\xe4tH\x90\xd3!Y\xd4B\x88\xdcHDl\xe4tH\xb2\xa4\xa4,r:\xa4\x9c\x0ei,%\x8ez\x88\xa0\x1dr:\xa4\xf9\xa4\xc2\xfc\xaf\x1b$\x13BD\x82us\xfc\x80\x8f\xc6\x9e\xff&\x8et\x93\x16\xfc\x98\xa18\x7fG\x8b\x1eW/_\xce\xec\x81\xfeC\x1c\\\x9f\xd9\x83\xcc\x1ed\xf6`*{0\x9d/\xc0\xf7\xec \x1a\x19\xe3E)\xb9\x86\xfd~d\xad\x1e\xce\xd2\xce\xd1\x1eT\xc4\xcb\xc4\xcc\x15\xe0[\xd8fp<\xc4d[p\x98\x15\x03\x02\x991\xc0\x93\x1d\x03\"\xc3\xad\x87g}\xebuq\xf8\xb5)\xe8\x19\xc3\xb0U f\xcc\x80\xe7\n\xcb\xc6Bg\xce\x00\x88\xcf\x9e\x01\xae\xad\x0b\xbc\xe1\x96d&\x0d\xf0\xcdO\x08\xc2\xfd\x90:\xab\x06\xd0\x995\xc0\x93]\x03B]\x98\x91e\x03|\x996\x86\n\xc7\xd96\x80\xca\xb8\x01\xbe\xd6\xc9\x96Y\xc3\xba<\xfb\x86!\xb0\xb6\xe8\xf9@B\x0e\xa0\x92r@D_\xd2%\xe7\xf0\xcd\xbd\xc5 \xee4Y}\xaa;\xedo\x89\xf2\xdd\xe9\xb5,Hz\x07\xd9-\x9f\xe5\x07g\xb7<\xbb\xe5\xdf\xa3[\xee\xc9\x88n\xb8\xc6\x10s\xcf\xa1\xd4\x85W\x97\xa7R\x92Jv.\xff\xf7W\xd6\n\x96\x99\xbfr:l\x82'\xe2\xdc\x83\xb8eS\x9c?\xc6\x05\xad\x98\x16\xf9\xb9\x845\xd5/\xfa\x1fte1^\xfb1 5\xda\xb9\x1e\xff\xbc4W\x96u\xe4\xb2\x8d\x08\xe7~\x9e{\xef5D(k?\xc2\xd1t\xbeA\xb8\xf9!G\xdf\xeb\xea{\x9d\xfd\x99\xee~\xc8\x81H\xeb\xf2/u\xfa#\xbeF\xc0\xedO\xee\xf8\x7fC\xd7\xff\x99\x9c\xff9\xee\xff7\x02\x00H\x08\xc0\x05\x02,\x86\x01f)\x87\x08\x17\x1d\"\xe0\x00? 0\x0d\x12\x08\xaf\xe9d\xb0\xc07\x05\x06\"\xa1\x81g\x05\x07|\xf0\xc04\x80\xc0\x03\x11\xf8@\x02\x0fL\x10\xf0\xb2c\xa0\x82%`\x01)N[\x83\xf6\x87\xf2\x01\x06\xc1\xce\xcc\x04\x0d\x02\xb0\x81\x1b8p@\x07\xdev\xba\xe0\x83\x85\x00\x82%M\xa5\xf3\xb4\xdb\x16\x06\x11\x1c0\xc2\xcc~\xcd\x04\x17,9\xfd\xfe5\xfa\xc51\xf5\xc3-\xa5S\x83bq\xcf\xc2\xb0\xdc~{\xa1D\xfb\xb4p\xc2\xc4\xa1X\xc8\xf4\xa1D;\xd4\xc4\x13\x99\x027\x83]0\x18\xce\x83\xe5q(\xee\xcbJ\x1c\xa6\xb0\x00\x87\xe1\xa7\xde\xf5\x19\x1e\x89\x07\x17*\xf6\xb5\xbb}d&\xce\x1ar\xe3\xad3\xcf&\x8f\xaa\x8a\x92\xaf\xdc4\xfe\x9f\xf28}\xd1J\x13\xe4\xb2\xb8gWHB\xae\xf0wC\xc8\xef\xdcC\x12\xafsq\xbc\xeb\xdc\xc9l;`\xe2\x10\xbb\x00)\xb4W\xba\xba+b\xa3\x9d\xc2\xb8\x84\xb5\xc6\x84x\xd1\x1f\xf1\x1f\x88\xca 2\x85!\x0c\xda\xc9{S'\xeb]\x15Z\xf2V\x081\xf5\x06\xf7\x1b[\xd6q\xff\xb3U\xf1\x17-\x1c+\x9c\xa2\x1b\xd4\xfa_\xca6&\xa8\x16\xab\xd4\x9c\xe5zt6\xa9\xac\xe0\xfe\xea\xf2t\xf0\x9f\xe5\xa1\xa1\x96[q\x0d3t\xc3\xban\xf0A\x81\xd4)\xe6X\x9d3\xe2\x86\xa7\xb0+\xf5n\x8e\xfa\xa6\x9e\xbc\xae\xf7C\xa3\xc8\x08\xe6\x86\x1d\x98\xe0\xa9\x7f-\x9a~d]\x11\xf5\xa3>\x8a\xe9a\x1ecS'\x8b\x1c\xf0\x1d\xce0\x81_\x9aP\xc7\x84\xc5\x94\x91\xba\x8c\xd4e\xa4\x0e\x0c\xa4\xae\x9d\x01\xd5\xb5\x04V\xe7C\xcfz#.\xe3h\x19G\xcb8Z\xc6\xd12\x8e6U9D\xe1Z\x19G\xcb8Z\xc6\xd1\xac\x072\x8e\x96q\xb4\x8c\xa3\xfd\xdf\xc1\xd1\x06\x83\xc08\xdb^hs2\x03j\xa3\x92\x01\xb5\x0c\xa8e@-\x03j\x19P\xfb\xfe\x005S\xf1\x07\x00\xae\xa9\x11i\x96\xa0\xc8\x88\xb4\x0b\xf6\xb5\xbb\x96\xd7v]\xa1\x8f;\x19c\x13{\x97\xba\xfb\xebVz\xca&\xe0\xe68\xb1k\xac\x1e9Jb\xfbR\x12{g\x1f\xb5\x85|6\x1f\x0b\xd6\x7f\x88SFY7f\xdd\xf8\x87\xd1\x8d\x83V2i\x064\xa6\xfc\n\xd1\xa3\xd7\"5#\xde\x18\xf8v|\x97\xded\xddh\xdc\xc5\xb7@a\xc9x\x0e_\xa8/:V\xba\x02[P_V\x90YAf\x05\xf9\x1d+H\xaf\x82\x1a]r*'1:o\xbd\x03\xcbu\xa7J\x82*\x95\x0b.\xd6b\xd7\xd6S\xe3#\xa4\x18r\x89OS\xb1\xd39^\xf3\xf2US\xe9\xa5\xe5z\xa7c|\xa3\xd5\xa9\xc03\xc7]\xbfXfA~d5\xce\xdb\x7f\xb1\xd8w\x00\x07\xab\xf1\xa8.\xa3\x0d\x07\xfaV`\xf9\xe4\xe8n`,\x11\xb5\x12\x17\xa3\x8d\xea\x9cz[0!\xc2\x00\xb2\x92\xdc\x1c<\x9eA3.\x10\x1e Hq\x8f\xf0H\xa0\xb8Sx<1\xbayW\x0bCFcU\xc9hlFc3\x1a\x9b\x0d\xealP\xffq\x0d\xea\x8e8\xe5\x18\x03?\xd0\x96\xed$\xe4\xe1\xb4\xdfv'\x1b\xc4\xc3\x8e\xbd\xc0\xff\xcfx\x03\x96\xac\x1e\xb3z\xfc\xffT=\xfe\x03\xa1\x1em\xb54\x0bjPm\x9e\x8d8\x0c\xcb[\x89\x9a\x009\x0c\x9d\x98\x8e6hn[\x06\x1a2\xd0\x90\x81\x86\x0c4\xf4%\x03\x0d\x19h\xc8@C\xb6\xa4\xb3%\x9d-\xe9 \xd0@\x18\xa1s@\x06M\xcc$|\xe1\n\xf7\xd2\xc9\xf6\xaf<\x8de]\xc4pW\xd7;VT\xa6\xeah\x8fkn\x15\xc0vW\xdc\x8b\xae\x94[\xb5\x8d\xa3\x8b\x9f\xf1\x83\xf9j&k\xbd\xac\xf5\xbec\xadG\xe1\x07\x86\xda\x89\x05\x0f\x14l\x80\xf2\xa4\x02\x89\x00\x11N\x9e\x05E\xf8X)-\xf8v\xfd8\x1dBP\x8e\xea<\x00\xc1Z\x9e\xfe\xb3\xb4*\xa0\xe6\xd8\xb7\xd9t\xae\x86\xf6\xc8w\xb3\x15\xa8D/kN\xd6\x87Y\x1f\xa2N\xa0\xac@Z\x89\x80/\x9b\x86\xfe\xfa\xeb\xf1\xfb\x91\xb6\xdf\xf0\x12\xaa\xe3?\x9e\xf22\xc0\xbe\xac\xb3\xb2\xce\xca:\xeb\xdb\xeb,C}\xccQ[3\xfc\xd7\xeb!\xd1\x8e5\xcf\xf5\x0c\x18\xc14,\xc6sZ*\x1c:\x01\x0e\x91\xf6\x86Hv3)\xc5\x0d\x8dI\xa6Hg3/\x89Mp\xcc\x1c\xa9k\x12%\xacy\xf645I\x93\xd3\xc4\xa7\xa4y\xd6D4Ze\xc3r\x11\xdb\x07_-\xff\xa4m\x0f\x11;\xbbs\x97\xf3b1\xf4\xc6=cgs\xeej3\xab\x8f\xda\xc9\xe8]l\xe1\x0e\xa6\xf6-)\x8d\xde\xbd\x12\xee\\ w-c\xc7Z\xba[\x0d{\x94\xeau\xbfS%\xdd\xa5\xfa/7|\xa4\x82\x8b\xafI\xf1H\xd9j\xd7V\x8b\x16\xcbt@\\\x15\x14\x0d\xff\xb2\xf7EY\xb5\x1d\x14\x15f\x91\x91\xa2Ub\xbb\xc3\xb19\xd4-\x13\x19^\x8f\x87M\xd1\x0d\x83XT\xfdm\xc0\xdb\x86\xb1\xff\xe0u\xe2\xd4o\xe9\x85\xaae\xdb\x18\xee\x94\x8c^\xb7\xf3\xee\xc6\xb5R\x82H1F.\xbb V2\x7f\xf4\xf6\xd8\xc4r\x8b\xfel?o\xe1\xe3\xd5\xfb\xd7\x0dk\xebc\xb3\x96w\x98\x8b\xcf\x84\x07\x0d\xf8\x07U\x1d\xc0y\"\x0c\x0e\xf2j\xad\xe1\xe6o\x93H\x14\x97\x1b\xaf\xeb\x1d\xdc\x1dE\x86'\xc9\xbf\xad\xe0\xe6\xa1le\x9ba\xcf\xf70y\xdbw\x7f\xe9\x91)\x89\xef\xca/^\xbf\xe0\xeb\xa7)\xd6\x1dkV\xe2:sq\xd7z\xcb\xee\x05\xcc\"w\xed\x8fW\xef\x7fl\xe1Pt\x0fB\xb4!\xa8?D`\xd6\xd0\x11\xd7\xbb\x8bQ\x91bE\xff_\x16|5\x9a\xaf~\xe2\x959/t\xfe\xf4\n\xdb*\x84\xb5\x0f\xf5q\xb7\xe1\xeb\x80w\xd6\x90\xb3.*\\NB\xfb\x9a\xb5\xbc\xe4\x9a\xe6\x84\x0f\x8f`?_\xac^\xf0eX\xd5\x1d\x14\xeb5;tl\xf3j\xf5\x83\xf9\xd2y\x05\x07>`\xe5\x9a\x9d@\xc7\x8a}\x0b\xc7\xf6(\x16\xec\xa1a|-r}ZV\xf2\x86\xec\xbb\xb2*\x9a'(v;\xd1_3\xd3\x90\xdah\x9e\xccj\xd8\xd7\x03[wPv\\\x7f\x1e[\xa6rj\xa9\xa3\x0b\xf5\x16\xdeVO\xbd*\xc6\xfb\xef?^\xbdo\x11*4\xa4\xc9\xdb\xf6\xcdJ\xda\xf5\x03\xdb3\xf8\xf4\xd0u\x87O'\xf8\xef\xf6\x938\xbaP\xd5\xf2\xd7\x131S\xb8\xaa\xa9\xc5\xcc\x17=\xe5\xea\xfcx\xb0\x86\xbb3.\xd6\x07\x9c\xcb\x9fE\xea\xb8\xa2\x83}qh\xf1\xb3\x8b\x96vu\xcf\x1f\x0b\xf3Q\xea\xff\xa2\x95vb\xfb\xc6\x1a\xfd?\xc1\xf9vh\x1b\xff\\\x87\xa6\xfe\\n\xd8\xa6o\xbeP\xa5m{\xdc\xb3\x8d\x95\xef\xf0O\xf0\xb6\x82\x7f\xba\xb9\xb9\x84\x7f<\xbbQ\x16\xd8\xc7\xab\xf7\xb8d\x9e\xc4\xa5\xf9\x85}M\xf9\xcd\xd3\x81\xfd\xf5\xdf\xfej\x08\x03\xc5\xe4W\xea+\xe3\x16/\xc6\xef\xd0\xd4\x9b\xe3\x9aAQ\x01k\x9a\xba1su\xfd \xde\x1e\x0e\xbbr]\xc8>7\x8c\xcf\x91\xfa\x0b\xdaN\xebb\xcd\xd7b]?\x1e\x0f=Y~Wp\xcb\n\x1bm5\xe5\xe3\xd5{Q\xefC\xf1Y|\xea\xbd6\x1b78\x1d\x0b\xd5L\xfe\xdf\x9f\xeb\x92\xdbofF.\x90\x95\x8a\x05\xd6\xb0m\xdd\xb0\x13\xf5\x9a\xd8g\xba\xf2\xae\xdc\x95\xdd\x13T\x8cm\xd4\xe1\x03\xa1\x00\x9a\xcfV\xf6?\xaee\xd4\x06\xcd\x1f\x15+`\x05/?\xb6L%\xb2\xe2\xfd\x15\xc7\x84\x8a=>\xb3/\xaa\xe2\xde\xee\x9f\xda\xf5\x95\xb8\xd5+\xf3\xdb^\xd4\x9d\xb0\xa3\xca\x16\xb6\xc7j\x8ds\x95\xb7T\xae\xe9\xc1\x80\xd3\xcesP\x83Y\x8bC(\xf6!\x0e5\x1d\xa0a\\\xa32D\xea\xcbNU \x0c_\xb1\xd9\xf63\xfc\x8e\xdd\x97\x95p\x1f\xb8Qg)H\xfb\x12{[\xdf\\\x8b\x99\xde\xca\xc4p\xddCQ\x99\xeb\x15^\xca\x0d\x9e\xed\x0f\xdd\x93\\\x1a\xaf`/6\xff;kA\x8af\x8a\x93\xd1%w!\xb8\xa2\xc7cG\xeav=h\xd9\xbe\xa8\xbar=J\x12)\xe6z\xe4F\xe9\x9a\n\x97j\xf2\xed\xca;\xd10\xa9\xf7Zh\x8f\x07qb\xb2\xab\x85s\xf5\xfaX\xf1\x7f\xf1\xdd\x01\xbfYk\xcfrs3\xe4\x06a\x87\xcbZ-\x9dV\x9c_\x1bR\xa5\x893}\xe2\xfc\x0e\xc2\x1d\xfd=\x01\xbc\x1e\x1ch]\xe2\xd9\xd7\x82O.\xf8\xf3\x1bqJP\xac\x14\xd9\xb0\xa2\x1f\xb8\xb2\x82\xd3\xbf\xff{KI\xffV\xd7\xb0\xadk\xf8\x05V\xab\x95y<\x88WWTO\xe6\x9f\x8b\xeai\xc5+\xfa\xad\xa9\xf7/\xb7u\xfd\xca|`\xb525p\xb9\x85\x97\xfc\xb5\x8f\xa2Y7\xf5\xcb\xbf\xe3\xef\xbd\"N/\xd9\xef\xfe\x8d\xea\xeb\xcf\x81\xbe\xfes\xf1\xb9\x98\xd5Y\xf8E\xec\xf5\\\xe2\xc4\xbe\x95\xed\xcb\xdf\xeaz\xb5\xde\x15mKv\x0d\xab\xe6\x8fb\x8b\xb5\xc7\xcdZF}\xee;\xfd_\x02\x9d\xbe|\xea\x1e\xea\xca\xea6\xd6\xfb[]\xbf\\\xadV\xaf\xec\x8f\x89]~I\xfc\">\xb3\x18\x86\x98Q\xe0/\x9c\xe3 \xbc;\xbb>\xbd:\xbf\xbc\xf9p\xf5\xea\x8d5\x0e\xc3D\xa0D\xa3p\xaa\xfb\xff5\xd0\xfd\x7f\xac\xcd\x9e\x8b\xae\xbf\xf9\x05\xfe\xeep\xb7\xfa\xad\xae\xff\xf7j\xb5\xfa\x9b\xf9HQ=\x9dp\xb3\x81?w\xc0M\xf3/E\xd3>\x14;>(T\x03\xed\xce\x9b\xf5X\x95\x94[\xa3\x8a\x8f\xd5~\xa8D4AL6\xf1\xd4\x7f\xfa\x05\xaarG\x9d\xec#j\x1e\xcd\x14n\xa8\x8bqQzC\x19lp\xf74l\xa9J\xab\x89\x8c\x9awO\n\x97\xe4\x9b\x95.\xecGb\xcb|\xcd}\x8c\x95\xf8\x81\x1b\x11?*7\\\xed\xc2=\x9f\x8e\xdfG\x17\xd7\xab\xb2j\xf7\xa4ld\xcbe\xe9\xcd\x13(\xb6\x9dL\x82,\xbc\xa4\x1f_\xff\xa8\x0b\x93\x06\xba\xaa\x16-r&\xe7\xc9\x8bm]\xaf\xee\x8aF4\xf8\xeb\xeb\xa7\xd5\x7f\xbc\xc0\xbe\xa2\xcdi\x1a\xce\xa2\xba\x17\xfc)\xaeV\xb5\x1f\xfe\xf9\xfa\xc3\x85\xfe\xff\xbf\xfc\xf2\xcb/\xe6h\xf3g\x06\xaf\x0c\xf7v\x11\x9c 7:\xb4Z\x8f-S\x00\xf8\xfdqW\x8c8\n\xfbe\xfe\xe0\x86\x0d\x9b\xd4\xc9p\xe0T\xce\xf6\x13\xb9\xef\x8d|9m\x03\x11\xa1W\xf0\xe9\xbf\xf3\xae~\x92\xe7\x19\xfa-W\x1f\xb8\x95Z\\o,\x03\xacX?\xf2u5\x98\xe7\xdbr\xc7L=\xa5V\xdf%k\xda\xba\"\xa6\xac\xf4\x92\xb7e\xd3v\xb7b\xa4\xc9c\xa8\xf21\xfe\xa9\xd5S?\xfbu\"\x00Q\xdb\x0b\xd1\xe3\x17o\xe0\x055w\xc7]Ya\x9b_\x9c\xd8RDk/\x8a=\x97\xf4\xdf\xb0i\xff@<\xc6[k<\xe5k\xf2\xf9V\x1a\x8e\xe3o\x89\xdf\xa2l\xe1\x0b\xdb\xed~z\xac\xea/\x95XE\x0fx\xea\xfd\xd8v\xf5\xde\x9a\x8a\xe3IsbD\x18\xe0L\xc2\xe5\xadU\xc8'Hu\x0f\x05N\x0f]\xdc'1M\xd5Ly\xa8w\x1by\xe4f\xa8]x\xfcr\x86\x81\xf4\xb7\xe5\x04\xd3% \xd1\xfd\xac\x82\x97|]\xaa\x8eZ\xae\x9e\xc2\x18\xfe\xfao\x7f}eM\xc0\xf9_w,\x9c\xfa\xc0\xa2\xbb\\\xd0\x9fW?\xff\xf9\xe7\xf6\x85\xf5\xd9\xd4\x7f\x8dA\xb1\xb6'6hv\x86\x04\xea\xf4\xd4\xb8\x9a\x18\xb5\x82\xf5e\x8b\xbfKafJ\\\x07\x8a\x7f\xaa\x10aQ\xd9\xff*\xbb\x87\x89\xb8\xbe\x83\x1a\x1f\x90fln\xa6\xc7#\x9a\x13E*@\xa6\xc7\x83D\x03\xfc\xc1\xe9q\x18\x061C\xe6\x192\xcf\x90y\x86\xcc3d\x9e!\xf3\x0c\x99g\xc8|(]\x86\xcc3d.K\x86\xcc3d\x9e!s\xbdd\xc8/\x9e\xc1\xef\x0c~g\xf0;\x83\xdf\x19\xfc\xce\xe0w\x06\xbf3\xf8\x9d\xc1\xef\x0c~C\x06\xbfe\xc9\xe0w\x06\xbf3\xf8\x9d\xc1o\xa3d\xf0\xbb/\x19\xfc\xfe\xe3\x82\xdf:\xb8\xe7\xbb#\xc7J\xb3\x90\xf3\xdc\xea?\xc4\x9d\xba\xce\x87\xc0\xf3!\xf0\xef\xf1\x10x\x10\xca\x1f!\xeb\xf1H\xbe\x9e_\xeb\xea\xf2T5\\\xe2\xf9\xf0+k\x85\xef\xa9-\x041\xcc'\x02\x0e\x89\xb8FG \xf4*\x81H\xde`:c\xa4\x13\x07\xf3\xe8\xb6\xe8;t\x88\xd48\xba\x1cB\x03\x04\xd3\xe4\x8c\x04\x1b\xe4\x87.\xdbj#x\xda N:d\xf8\xcd\xd1\\\x08\x02;X\x12\x12$X\xdc4 \x96td \x96d\x94 \x16'q\x82\x85\xf2E\"\xe9\x13,\xa9H\x14,~*\x05\xcb,B\x05\xcblZ\x85\x1e;\xee\xd0\xba\xc9\x15,\xb3)\x16R\x1aj2\x07\xd1\x82e \xddB\n<\x1e\xa0 I\x17,s\xa8\x17R\x90\x93\x8e\xc1\xb2\x90\x94QB\"\xa8\x19\xf2\xcdh\xba\x06\xcb\x02\xd2\x06\xcb\x02\xea\xc6\xb5\xd0\x1dMMF\xea`IK\xed`IF\xf0` \xd3\x0ffa\xd2\xa9\x91,\x99\x80j\xf47*\x0f\x15\xd1*\x15\xdf .\x1a\xdf\x80N\x01(\x957\xbap#\xdf\xce-J\xbe\x9d;\xdf\xce\x9d\xe4v\xee8\xb2qF\xdc\x10\xbe'\xe5\xd9t\xa3\x8f\x06\x1c\x05\xf6M'\x02s\x06\xadE\xbcX2F,\x07\x11\xc5\xb1]\x88\xb0[c\x94\x83\x88r\x10\xd14&\x8at\xd5\x93\xf1Mi\x99\xa6d\x1cS\x98]J\xc6+\xe5 \xa2\x1cD4\x81\xe1\xc9AD\x04g\xb3\x84\xad\x89\x89\xab\xc9ADZ\xc9AD\x90\x83\x88r\x10Q\x0e\"J\xc5L$\xe3$\xd2\xb2\x11q'f\xfe}W#1\x9af1o\xbd\xf25\xb2%\x8f\x0e\xd8yHsx\x1e\xe4\xf0\xbc\x1c\x9e\x97*<\xcf\x9c\xa5>z|.5\xdf\xbaH\xf9z\xbf/\xbb\xbd$\xe6\xff\"\xce\xeb\\6l[~\x8d&\xe2\x1f\xd9\xd3\xedA{\x05\\3\xdbZ\xa6f\xc7\xf5\xeayG\xd5\xf1\xa1\xa2{\x00\xac\x01\x97\xa6\\\xb2J\x9d\xdd \x9b\xd0v\xcdq\xcd\xbf\x0d_\xad\xdb\xa6\xde\x8b\xe7.\x0b\xa1\x1e7\xfd:W\xbbcq8\xb0j\xf3\x92\xff\xbe\xfa\x1f\xec\x89\xff[m\x04\xe6O\xa2\xea\x13Q\xe5j\xf5\xea\xd5x\xfc\xaa\x8a $\x85\x8f\xdfi\xff\x7fg\xd5&z\x00\x89T\xa3\xe4\xf8\x8dV\x93\xe4\xe5m\x85]\xb6\xa05J\xbe,Q\xe2g>$1\xec\x144UJ\x82\x90r\x12 ;\xa9\x1a\xeaJ\x9e\xbaeEwllV\x95\xea\x0d\x16\xf2\xca\xbe\x98\x06\xa9\xa0uUe\x8f\xde\xef\xd8\xb07\x0ep%\xd9`\xdfV\xff?eO\xf5\x8b\x00e\xef\xb9\x16\x93,\xcfQ\xeeF\x15\xbb\xaf\xbbR\xdc\x07\xf8\xc0\xe0\xfc\xd7\xd3\x91\xac\xcf\xac)\xb9 or\x94\x92g\x93\x93\x01\x1e\x8aj\xd3>\x14\x8fQq1\xe7\xbf\x9e\xf6_C:$E\xc5\x17\x8e\x80\x10e\xb36\xacc\xcd\xbe\xac\x18\xb0j]s\xf5\xdbJ\x86G\x00\xac:\xcf\xb5\xadG\x1e\xd5\xfa\xa1\xa8*\xb6\xc3\xc7\x8b\xf5#\xebZ)\x99\xf7\xde1\x8d\x0d\x1a~\xbc \x90\x8b\x90V\x91J+0t\x9eU\xba\xfdC}~V\x1d\xf7\xfaL\xf9 \xaeo\xde\xde\x9c\xdd~\xbc8\xbf8\xbf9\x7f\xfb\xfe\xfc_\xcf\xde\xdd~\xbc\xb8\xbe<;=\xff\xed\xfc\xec\x1d\xf1,\x7f\x92\xf8\xf3\xcd\xd5\xbf|\xb8<\xbb ~\x19\xfdY\xc2\x07o\"+\x16{5k\x0eE\xd3=\xb9FE{\x04\x93,\xc4\xaa\x8cI\x06\x9b#[\xb2s\x95\xf9\x81|\xe3\x80\x82Tu\xb5\xe2\x8d\x83=2\x1d\x1d<\xe3j\xfc\x91\xea\xb1\xfe\xd7\xe7\xea\xcchFFu\xca\x10H\xf3\x11x\x00\x8a\xee\x94\xb9;\x83=K\x94\x150\x1c\xd9\x15\x9bp\xbf\x8c\xcc\xe6\xad\x88\xa1!N\xc2\xb8\xcf\xc1PV\x83*\x1e\xe5\x1c6\xf6\xed\xc0\xc2\xa9V\x85\xf1\xfe,\xf3\xc2\x90A\x1a\x1b\x81gl\xab\x03\xc4w\xdb\x15O\xb7\x07\xd6\x94u\xc8^px\x11\xee\xe9*d\x03\xca\x96\xe7\x19\x8em'|\"\xb8\x13T6\xe1\x7f\xaa]A\xb2\xb3\xfa\xb4\x13j\xfd'\xbe9m%\x8f\xaf\xf7\xf9\xe2\xc3\xcd\xd9\x9bq\x9d\xbb\xfa\xbe\\\xf3o$\xd0\xca\x9e\x05E\xd0\x15\xcf\xc6 ]@\xdd\x87\xdb[\x91##Ls\x9cEs\xb7\xc7\x9d\x9c\xa7|\xe9\x15r\xad\xc9e\x83\xf3\xa0\xa8\x84##\xa5\xb5\xecP4bG\xa9\xfam\x13[\xde OD\x8c\x90h\xee\x1d\x83\x9fA\xf9B\xa3F\x08\xf7\x86\xb5]q\xb7+[\x15\x9d_\xe8\xaa\xe0\x8eu_\x18\xab\xa0\xfbRc\x93\x8c[\x97\x0d+\xd3T\xfb\xcfed\x8efGJ\xadlid[q94\xf1\xc2F/\xd2\xbe\xb6\xe6ui]S\xb3%\xd3\xb6\x13\xf6d\x97\x86\x0d\xa2\x0eT$\xc7hP\x97h\xd4\xa5\xda4\xa4Ic\xb4(=]\xf4e5\xb2\xcac\xe6\xb66\x07\xa48io:\xd6\xb0\x96\x99\xab\xff{\xf4Z\x9e\xb6\x1e\xb49?8)\xab%j!\xfb\x9e\xb6\xfc\xec{N\xf6=)\xd5\xf2=y\x9d\xf2\xbd\xectf\xa73\xa2G\xd9\xe9\xccN\xe7P\x96\x98H\x90\xc0L\x82\x08S\x89z\xe6\x9b8\x9d#\x9f/J3\xd0\x9e\x1eeD\x8d\x99R\xf5G\x9c\xbe\x03+j)y*\x93\xa9\xc3t\xd3\xf2&\x0e\xd5\xce\x8a_T\x8b\x9e\xcf\x8ay\xe6\x91\xcfJkw\xe5Z\xecI\"\xfd\xdcX\x0b\x88\x1a)+\x16c4\xa5\xc0\xef8\xfc\xbb?\xa7j\xb4.j\xe3\xc8\xe1\xdf9\xfc;\x14\xfb\xf8\xffh\xf8\xb7A2\xbb\xb4\xd8\x04\x9a\xd9\x14\xe1$\x9am\x1d\xda\xff\x89\xb8\xf22Z\x8f\xf6\x9a{sK_\xad\xa8\xce\xba\xe8\xb9\xae\xc9\x14\x19\xe8\x1b\xccQ(S-\xd1q\x93H\xf7\xcd}M\xe4\x0c\xbb\xa7s\x86\x9cz\xad\x9eP\xb8E\xf2`S\x7f\xa8i\xda@\xd3\xa4a\xa6\xde \xd3nY\x88i\xca\x00\xd3px\xe9\xec\xe0\xd2\x94\xa1\xa5]8\xb04eXi0\xa84qH\xa97\xa0tN8\xa9?t4A\xe0hT\xd8\xe8\xb4\x10\xd1\x85\x01\xa2i\xc3C]\x11\x8bICC\xd3\x07\x86&\x0d\x0b\x8d\x0b\nM\x1a\x12\xea\x0b\x08M\x1c\x0e\xea\n\x06\xedbCA\xe7\x06\x82b\xd0'!\x90\x0e\x03]\x10\x04\xea\x08\x01\x9d\x07l@\xd4\xfe\x9f.\xf4\xd3\x17\xf8\xe9oG\xd2\xa0O_\xc8g\xa2\x80\xcfe\xe1\x9e\xc4J\xa2\xb6\xf2\xb4\xa1\x9e\x1d\x19\xe8\xb94\xcc3\x18\xc7\xe8 \xf1\x8c\n\xf0\xa4\xe3\xbd\xa6\x05w\xd22\xacX\x8f\xc5a\x9d\xb1\x83\x11\x13\xd2\xe9\xefwT8\xe7\xc4`N;\xf6%A g0\x8c\xd3\x1f\xc4\x19\n\xe1t\x8e\xd2\x94\xf0\xcd\x98\xe0M*tsa\xe0fd\xd8\xe6\xbc\xa0MG\x98dL\xc0f\xc2pMG+\xac\x99\xb6(P\x93\n\xccL\x18\x96I\x07e.\n\xc9\xa4B0S\x07`z\xc3/\xa9\xb84*\xf42]\xe0e\xd2\xb0\xcb\xf4A\x97\xf1!\x97Q\x01\x97\x12\xc7\x88 \xb7\x94\x8f\x06\x83-\xc9PK\xba\xf6\xd8\x10\xbap\x98\xe5\x84 \xcb\xc8\x10K\xab\x1b\xa9\xc3+S\x06W\x92\xa1\x95i\x03+\xd3\x86U.\x9b\x0fQ!\x951\x01\x95\xe3m\x85\xc0n\xfb\xdf\xdd\xc1e\x0b\xaf=TW\x1d\x0e\x02]\xf7\x1c~\xc7\x04Y\xce\x8f\x1c\xd7\x9cL\x90e\x82L\xc8rEa\xba)\xaa $\x19%f\x16QF\xe6k\x8e\xe6\xca\xf2\xb5\x89\xcbx\xa3d\x9cQ\xbe61\x8e\x1bBL\xdb\x1a\xa3|m\xe2\x14\x0eh!\xff\x93\x98\xfbY\xc0\xfb,\xe0|\x08\x85\x91\x90\xddI\xcb\xec$cu\xc2\x8cN26'_\x9b\x98\xafM\x9c\xc0\xba\xe4k\x13 Ne \x9f\x12s\x93`\xbe6Q+\xf9\xdaD\xc8\xd7&Z\x0cC\x88\xe3H\xc4o\xe4k\x13eI\xc9\\\xe4k\x13\xf3\xb5\x89c)q\x0cD\x04\xfb\x90\xafM\x9c\xcf-\xcc\xff\xbaAN!\xc4'X\xd7&F\xdd\x948:\x06\x1e\x1b\x1f=&*\xce\xdf\xd1\xa2\xc9\x9c\x90\x99D\xd0\x7f\x88C\xed3\x89\x90I\x84?\"\x89@\xc2\xf7\xb3x\x84\x91\xa49T\xc2\x1c\xf2`\x94\xa8\x02FzUE\x16RzOe\xe4$\x02]&\xe8\x93\xa9A6\x0bRV\x00\x99\xb6b\xa8\xcdN\xf6@\xa6z ;\x87\xc5wA\x9c;\x95\x05\xf8\xfa+\x7f\x9e\x92\xd2\x02\x84%\x88\xb1\x9f\x9f^\xff\xfc\x9f\x0d\xe9-w\x7f\x7f\xb0F@\xf6^\x8e\x12\x94\x15\x9a5\xa5\xbc\x0d\"8\x15.\x8b\xa6P\xcb\"b\x1a\xb4\xac\xda\xdc\xb2\x8a\x1b\xfd\xd6\xd9\xf9\xbb\xba\xde\xb1\"\xc6\"\xd2\xa5\x00\xfe[ \xae\x9b\xb2\xc5\xff.v;X7u\xdb\xfe\x843E\x8c\x00\xa8v\xb7H5\x0d\xf2\xb8s\xacO\x89\x91\xcek\xd8\x9a\x95\x9f\xd9\xf2V\x1b\x82f5|\xe4\xf2y\x9aM\xb7\x02?\xd6h%q\xa3\xad\xde\n\xfd\xa0j\x81\x03\x7f\x8cu\xaci\xfb\xcd\x0e\x0f#\xdc\xd4ph\xb8\xc9\xd3A\x01\xdc\xfeQ\x93\x0b\x81\x96;&@n)\xa6a\x9b\x130l\xc2\x1b\xd5\x9139\x06}U\x02\xdfi\x8eL\x814\x95z\x15\xee\x8a\xea\x11\xf6\xf5\xe6\xb8c?*C\xe7\x9aU\x1b)\xe2\x87^\xc1(I\xcaJ\x1a-\x8b\xae\x86m\xb1k\xc3\xbaM\xd8V\xc3r\x9bL \x8aZo\xbbA9\x92\xef\xd1\xef\x82\xa5(\xc1\xe7\x81\xf8\xe1\xd1\x05J\xd3\x90\xa4\x94\x03\x95\xf6\"By\x82C\x81Bt\xdff)RK\xcah\x84\x12(TM\x9a\xca\xf3\xa8\xeb\xa8\xb0bum\xf4\x8e)\x18\xe3\x13h\xdd\xe2\xce\x00\xca\x1b\xfb\x02\xb13\x7f:w\xaeM\xfdy\xb6T4yn/\x12/\x86\x1a\xe2\x11\xd2-\x15\xefb\x89_.\xee\x05\x13\xdf\xcf\xd9\x8b\xc6?^i\x17\x0e\xb9t\"\x17\x8f\xd5R}\xfeA\xc3\xbacS\xe1\x8e\xaa7\xab\x15R\x99.\xd3\x87\"\x8f*\xd0\xb0d}\xb6h\x7f\x96\x18\x8fZ\xa2+c\x15D\xed\x00\x19j\x0e\x01k\xdf?\xd4\x9c\x1e\xed\xd1\x14\xb3\x94\xe6D{\xfc\x1a\x1e\x8d\xc0\xc9\xca\xfd\xa0\x19\xfaV\x0f\x0f\xb6a9\x18\x91J\xef\xa0\x0d7kI\xd0n\x038\x8dp\x08*\xfd\xa5.\x84!N\x12\x8dc{\x1c,\xf8\xc4\xe7N\xc0\x82\xde\xccv-\xccu\xa49\x1a\xa1\xee\x8cZD\xcc\xac\x98I-\x1d\x92!Nq\xf5\xc3\xff \x00\x00\xff\xffPK\x07\x08\x03\xbau\xd7\xff\xee\x01\x00\x83\x83\x1a\x00PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(\xd4`4t\xc7\x01\x00\x00\xbd\x01\x00\x00\x11\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x00\x00\x00\x00favicon-16x16.pngUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(6B\xc8\xd7\x7f\x04\x00\x00u\x04\x00\x00\x11\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x0f\x02\x00\x00favicon-32x32.pngUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(\xb9\xb1\xf1mT\x02\x00\x008\x05\x00\x00\n\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xd6\x06\x00\x00index.htmlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(]\x12r 9\x03\x00\x00T \x00\x00\x14\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81k \x00\x00oauth2-redirect.htmlUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(\x05\xef\x9fw>9\x05\x00\xf8\x0c\x1b\x00\x14\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\xef\x0c\x00\x00swagger-ui-bundle.jsUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(v\xf2\x8aA\x86\xba\x01\x00\xc5\x87\x08\x00\x1f\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81xF\x05\x00swagger-ui-standalone-preset.jsUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(_;\x94/\xe8Y\x00\x00\xa8X\x02\x00\x0e\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81T\x01\x07\x00swagger-ui.cssUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(\x03\xbau\xd7\xff\xee\x01\x00\x83\x83\x1a\x00\x0c\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x81[\x07\x00swagger.yamlUT\x05\x00\x01\x80Cm8PK\x05\x06\x00\x00\x00\x00\x08\x00\x08\x00E\x02\x00\x00\xc3J \x00\x00\x00" + fs.Register(data) +} diff --git a/client/docs/swagger-ui/swagger.yaml b/client/docs/swagger-ui/swagger.yaml index 5d8529c79e59..9ddba0cd0e52 100644 --- a/client/docs/swagger-ui/swagger.yaml +++ b/client/docs/swagger-ui/swagger.yaml @@ -1395,6 +1395,57 @@ paths: description: Invalid request '500': description: Server internal error + /bank/total: + get: + deprecated: true + summary: Total supply of coins in the chain + tags: + - Bank + produces: + - application/json + responses: + '200': + description: OK + schema: + type: object + properties: + total: + type: array + items: + type: object + properties: + denom: + type: string + example: stake + amount: + type: string + example: '50' + '500': + description: Internal Server Error + '/bank/total/{denomination}': + parameters: + - in: path + name: denomination + description: Coin denomination + required: true + type: string + x-example: uatom + get: + deprecated: true + summary: Total supply of a single coin denomination + tags: + - Bank + produces: + - application/json + responses: + '200': + description: OK + schema: + type: string + '400': + description: Invalid coin denomination + '500': + description: Internal Server Error '/auth/accounts/{address}': get: deprecated: true @@ -4563,136 +4614,636 @@ paths: type: string '500': description: Internal Server Error - /supply/total: + /cosmos/auth/v1beta1/accounts: get: - deprecated: true - summary: Total supply of coins in the chain - tags: - - Supply - produces: - - application/json + summary: Accounts returns all the existing accounts + operationId: Accounts responses: '200': - description: OK + description: A successful response. schema: type: object properties: - total: + accounts: type: array items: type: object properties: - denom: + type_url: type: string - example: stake - amount: + description: >- + A URL/resource name that uniquely identifies the type of + the serialized + + protocol buffer message. This string must contain at + least + + one "/" character. The last segment of the URL's path + must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in + a canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary + all types that they + + expect it to use in the context of Any. However, for + URLs which use the + + scheme `http`, `https`, or no scheme, one can optionally + set up a type + + server that maps type URLs to message definitions as + follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based + on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in + the official + + protobuf release, and it is not used for type URLs + beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) + might be + + used with implementation specific semantics. + value: type: string - example: '50' - '500': - description: Internal Server Error - '/supply/total/{denomination}': - parameters: - - in: path - name: denomination - description: Coin denomination - required: true - type: string - x-example: uatom - get: - deprecated: true - summary: Total supply of a single coin denomination - tags: - - Supply - produces: - - application/json - responses: - '200': - description: OK - schema: - type: string - '400': - description: Invalid coin denomination - '500': - description: Internal Server Error - '/cosmos/auth/v1beta1/accounts/{address}': - get: - summary: Account returns account details based on address. - operationId: Account - responses: - '200': - description: A successful response. - schema: - type: object - properties: - account: - description: account defines the account of the corresponding address. - type: object - properties: - type_url: - type: string - description: >- - A URL/resource name that uniquely identifies the type of - the serialized + format: byte + description: >- + Must be a valid serialized protocol buffer of the above + specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer + message along with a - protocol buffer message. This string must contain at least + URL that describes the type of the serialized message. - one "/" character. The last segment of the URL's path must - represent - the fully qualified name of the type (as in + Protobuf library provides support to pack/unpack Any values + in the form - `path/google.protobuf.Duration`). The name should be in a - canonical form + of utility functions or additional generated methods of the + Any type. - (e.g., leading "." is not accepted). + Example 1: Pack and unpack a message in C++. - In practice, teams usually precompile into the binary all - types that they + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } - expect it to use in the context of Any. However, for URLs - which use the + Example 2: Pack and unpack a message in Java. - scheme `http`, `https`, or no scheme, one can optionally - set up a type + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } - server that maps type URLs to message definitions as - follows: + Example 3: Pack and unpack a message in Python. + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... - * If no scheme is provided, `https` is assumed. + Example 4: Pack and unpack a message in Go - * An HTTP GET on the URL must yield a - [google.protobuf.Type][] - value in binary format, or produce an error. - * Applications are allowed to cache lookup results based - on the - URL, or have them precompiled into a binary to avoid any - lookup. Therefore, binary compatibility needs to be preserved - on changes to types. (Use versioned type names to manage - breaking changes.) + foo := &pb.Foo{...} + any, err := ptypes.MarshalAny(foo) + ... + foo := &pb.Foo{} + if err := ptypes.UnmarshalAny(any, foo); err != nil { + ... + } - Note: this functionality is not currently available in the - official + The pack methods provided by protobuf library will by + default use - protobuf release, and it is not used for type URLs - beginning with + 'type.googleapis.com/full.type.name' as the type URL and the + unpack - type.googleapis.com. + methods only use the fully qualified type name after the + last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield + type + name "y.z". - Schemes other than `http`, `https` (or the empty scheme) - might be - used with implementation specific semantics. - value: + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with + an + + additional field `@type` which contains the type URL. + Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom + JSON + + representation, that representation will be embedded adding + a field + + `value` which holds the custom JSON in addition to the + `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + title: accounts are the existing accounts + pagination: + description: pagination defines the pagination in the response. + type: object + properties: + next_key: type: string format: byte - description: >- - Must be a valid serialized protocol buffer of the above - specified type. + title: |- + next_key is the key to be passed to PageRequest.key to + query the next page most efficiently + total: + type: string + format: uint64 + title: >- + total is total number of results available if + PageRequest.count_total + + was set, its value is undefined otherwise description: >- - QueryAccountResponse is the response type for the Query/Account + QueryAccountsResponse is the response type for the Query/Accounts + RPC method. + default: + description: An unexpected error response. + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the type of + the serialized + + protocol buffer message. This string must contain at + least + + one "/" character. The last segment of the URL's path + must represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in + a canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary + all types that they + + expect it to use in the context of Any. However, for + URLs which use the + + scheme `http`, `https`, or no scheme, one can optionally + set up a type + + server that maps type URLs to message definitions as + follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based + on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in + the official + + protobuf release, and it is not used for type URLs + beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) + might be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of the above + specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer + message along with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values + in the form + + of utility functions or additional generated methods of the + Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := ptypes.MarshalAny(foo) + ... + foo := &pb.Foo{} + if err := ptypes.UnmarshalAny(any, foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by + default use + + 'type.googleapis.com/full.type.name' as the type URL and the + unpack + + methods only use the fully qualified type name after the + last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield + type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with + an + + additional field `@type` which contains the type URL. + Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom + JSON + + representation, that representation will be embedded adding + a field + + `value` which holds the custom JSON in addition to the + `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + parameters: + - name: pagination.key + description: |- + key is a value returned in PageResponse.next_key to begin + querying the next page most efficiently. Only one of offset or key + should be set. + in: query + required: false + type: string + format: byte + - name: pagination.offset + description: >- + offset is a numeric offset that can be used when key is unavailable. + + It is less efficient than using key. Only one of offset or key + should + + be set. + in: query + required: false + type: string + format: uint64 + - name: pagination.limit + description: >- + limit is the total number of results to be returned in the result + page. + + If left empty it will default to a value to be set by each app. + in: query + required: false + type: string + format: uint64 + - name: pagination.count_total + description: >- + count_total is set to true to indicate that the result set should + include + + a count of the total number of items available for pagination in + UIs. + + count_total is only respected when offset is used. It is ignored + when key + + is set. + in: query + required: false + type: boolean + tags: + - Query + '/cosmos/auth/v1beta1/accounts/{address}': + get: + summary: Account returns account details based on address. + operationId: Account + responses: + '200': + description: A successful response. + schema: + type: object + properties: + account: + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the type of + the serialized + + protocol buffer message. This string must contain at least + + one "/" character. The last segment of the URL's path must + represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in a + canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary all + types that they + + expect it to use in the context of Any. However, for URLs + which use the + + scheme `http`, `https`, or no scheme, one can optionally + set up a type + + server that maps type URLs to message definitions as + follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a + [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based + on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in the + official + + protobuf release, and it is not used for type URLs + beginning with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) + might be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of the above + specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer message + along with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values in + the form + + of utility functions or additional generated methods of the + Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := ptypes.MarshalAny(foo) + ... + foo := &pb.Foo{} + if err := ptypes.UnmarshalAny(any, foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by default + use + + 'type.googleapis.com/full.type.name' as the type URL and the + unpack + + methods only use the fully qualified type name after the last + '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield + type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with an + + additional field `@type` which contains the type URL. Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom + JSON + + representation, that representation will be embedded adding a + field + + `value` which holds the custom JSON in addition to the `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + description: >- + QueryAccountResponse is the response type for the Query/Account RPC method. default: description: An unexpected error response. @@ -5252,13 +5803,20 @@ paths: type: object properties: balance: - description: balance is the balance of the coin. type: object properties: denom: type: string amount: type: string + description: >- + 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. description: >- QueryBalanceResponse is the response type for the Query/Balance RPC method. @@ -5297,6 +5855,296 @@ paths: type: string tags: - Query + /cosmos/bank/v1beta1/denoms_metadata: + get: + summary: >- + DenomsMetadata queries the client metadata for all registered coin + denominations. + operationId: DenomsMetadata + responses: + '200': + description: A successful response. + schema: + type: object + properties: + metadatas: + type: array + items: + type: object + properties: + description: + type: string + denom_units: + type: array + items: + type: object + properties: + denom: + type: string + description: >- + denom represents the string name of the given + denom unit (e.g uatom). + exponent: + type: integer + format: int64 + description: >- + 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: + type: array + items: + type: string + title: >- + aliases is a list of string aliases for the given + denom + description: |- + DenomUnit represents a struct that describes a given + denomination unit of the basic token. + title: >- + denom_units represents the list of DenomUnit's for a + given coin + base: + type: string + description: >- + base represents the base denom (should be the DenomUnit + with exponent = 0). + display: + type: string + description: |- + display indicates the suggested denom that should be + displayed in clients. + name: + type: string + title: 'name defines the name of the token (eg: Cosmos Atom)' + symbol: + type: string + description: >- + symbol is the token symbol usually shown on exchanges + (eg: ATOM). This can + + be the same as the display. + description: |- + Metadata represents a struct that describes + a basic token. + description: >- + metadata provides the client information for all the + registered tokens. + pagination: + description: pagination defines the pagination in the response. + type: object + properties: + next_key: + type: string + format: byte + title: |- + next_key is the key to be passed to PageRequest.key to + query the next page most efficiently + total: + type: string + format: uint64 + title: >- + total is total number of results available if + PageRequest.count_total + + was set, its value is undefined otherwise + description: >- + QueryDenomsMetadataResponse is the response type for the + Query/DenomsMetadata RPC + + method. + default: + description: An unexpected error response. + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + value: + type: string + format: byte + parameters: + - name: pagination.key + description: |- + key is a value returned in PageResponse.next_key to begin + querying the next page most efficiently. Only one of offset or key + should be set. + in: query + required: false + type: string + format: byte + - name: pagination.offset + description: >- + offset is a numeric offset that can be used when key is unavailable. + + It is less efficient than using key. Only one of offset or key + should + + be set. + in: query + required: false + type: string + format: uint64 + - name: pagination.limit + description: >- + limit is the total number of results to be returned in the result + page. + + If left empty it will default to a value to be set by each app. + in: query + required: false + type: string + format: uint64 + - name: pagination.count_total + description: >- + count_total is set to true to indicate that the result set should + include + + a count of the total number of items available for pagination in + UIs. + + count_total is only respected when offset is used. It is ignored + when key + + is set. + in: query + required: false + type: boolean + tags: + - Query + '/cosmos/bank/v1beta1/denoms_metadata/{denom}': + get: + summary: DenomsMetadata queries the client metadata of a given coin denomination. + operationId: DenomMetadata + responses: + '200': + description: A successful response. + schema: + type: object + properties: + metadata: + type: object + properties: + description: + type: string + denom_units: + type: array + items: + type: object + properties: + denom: + type: string + description: >- + denom represents the string name of the given denom + unit (e.g uatom). + exponent: + type: integer + format: int64 + description: >- + 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: + type: array + items: + type: string + title: >- + aliases is a list of string aliases for the given + denom + description: |- + DenomUnit represents a struct that describes a given + denomination unit of the basic token. + title: >- + denom_units represents the list of DenomUnit's for a given + coin + base: + type: string + description: >- + base represents the base denom (should be the DenomUnit + with exponent = 0). + display: + type: string + description: |- + display indicates the suggested denom that should be + displayed in clients. + name: + type: string + title: 'name defines the name of the token (eg: Cosmos Atom)' + symbol: + type: string + description: >- + symbol is the token symbol usually shown on exchanges (eg: + ATOM). This can + + be the same as the display. + description: |- + Metadata represents a struct that describes + a basic token. + description: >- + QueryDenomMetadataResponse is the response type for the + Query/DenomMetadata RPC + + method. + default: + description: An unexpected error response. + schema: + type: object + properties: + error: + type: string + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + type_url: + type: string + value: + type: string + format: byte + parameters: + - name: denom + description: denom is the coin denom to query the metadata for. + in: path + required: true + type: string + tags: + - Query /cosmos/bank/v1beta1/params: get: summary: Params queries the parameters of x/bank module. @@ -5422,13 +6270,20 @@ paths: type: object properties: amount: - description: amount is the supply of the coin. type: object properties: denom: type: string amount: type: string + description: >- + 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. description: >- QuerySupplyOfResponse is the response type for the Query/SupplyOf RPC method. @@ -5522,7 +6377,6 @@ paths: type: string format: date-time last_block_id: - title: prev block info type: object properties: hash: @@ -5538,6 +6392,7 @@ paths: type: string format: byte title: PartsetHeader + title: BlockID last_commit_hash: type: string format: byte @@ -5765,7 +6620,6 @@ paths: type: string format: date-time last_block_id: - title: prev block info type: object properties: hash: @@ -5781,6 +6635,7 @@ paths: type: string format: byte title: PartsetHeader + title: BlockID last_commit_hash: type: string format: byte @@ -6280,7 +7135,6 @@ paths: type: string format: date-time last_block_id: - title: prev block info type: object properties: hash: @@ -6296,6 +7150,7 @@ paths: type: string format: byte title: PartsetHeader + title: BlockID last_commit_hash: type: string format: byte @@ -6523,7 +7378,6 @@ paths: type: string format: date-time last_block_id: - title: prev block info type: object properties: hash: @@ -6539,6 +7393,7 @@ paths: type: string format: byte title: PartsetHeader + title: BlockID last_commit_hash: type: string format: byte @@ -9495,7 +10350,6 @@ paths: type: object properties: evidence: - description: evidence returns the requested evidence. type: object properties: type_url: @@ -9561,6 +10415,111 @@ paths: description: >- Must be a valid serialized protocol buffer of the above specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer message + along with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values in + the form + + of utility functions or additional generated methods of the + Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := ptypes.MarshalAny(foo) + ... + foo := &pb.Foo{} + if err := ptypes.UnmarshalAny(any, foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by default + use + + 'type.googleapis.com/full.type.name' as the type URL and the + unpack + + methods only use the fully qualified type name after the last + '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield + type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with an + + additional field `@type` which contains the type URL. Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom + JSON + + representation, that representation will be embedded adding a + field + + `value` which holds the custom JSON in addition to the `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } description: >- QueryEvidenceResponse is the response type for the Query/Evidence RPC method. @@ -11383,7 +12342,6 @@ paths: type: object properties: deposit: - description: deposit defines the requested deposit. type: object properties: proposal_id: @@ -11408,6 +12366,11 @@ paths: custom method signatures required by gogoproto. + description: >- + Deposit defines an amount deposited by an account address to + an active + + proposal. description: >- QueryDepositResponse is the response type for the Query/Deposit RPC method. @@ -11625,7 +12588,6 @@ paths: type: object properties: tally: - description: tally defines the requested tally. type: object properties: 'yes': @@ -11636,6 +12598,9 @@ paths: type: string no_with_veto: type: string + description: >- + TallyResult defines a standard tally for a governance + proposal. description: >- QueryTallyResultResponse is the response type for the Query/Tally RPC method. @@ -11857,24 +12822,34 @@ paths: format: uint64 voter: type: string - option: - type: string - enum: - - VOTE_OPTION_UNSPECIFIED - - VOTE_OPTION_YES - - VOTE_OPTION_ABSTAIN - - VOTE_OPTION_NO - - VOTE_OPTION_NO_WITH_VETO - default: VOTE_OPTION_UNSPECIFIED - description: >- - VoteOption enumerates the valid vote options for a given - governance proposal. - - - VOTE_OPTION_UNSPECIFIED: VOTE_OPTION_UNSPECIFIED defines a no-op vote option. - - VOTE_OPTION_YES: VOTE_OPTION_YES defines a yes vote option. - - VOTE_OPTION_ABSTAIN: VOTE_OPTION_ABSTAIN defines an abstain vote option. - - VOTE_OPTION_NO: VOTE_OPTION_NO defines a no vote option. - - VOTE_OPTION_NO_WITH_VETO: VOTE_OPTION_NO_WITH_VETO defines a no with veto vote option. + options: + type: array + items: + type: object + properties: + option: + type: string + enum: + - VOTE_OPTION_UNSPECIFIED + - VOTE_OPTION_YES + - VOTE_OPTION_ABSTAIN + - VOTE_OPTION_NO + - VOTE_OPTION_NO_WITH_VETO + default: VOTE_OPTION_UNSPECIFIED + description: >- + VoteOption enumerates the valid vote options for a + given governance proposal. + + - VOTE_OPTION_UNSPECIFIED: VOTE_OPTION_UNSPECIFIED defines a no-op vote option. + - VOTE_OPTION_YES: VOTE_OPTION_YES defines a yes vote option. + - VOTE_OPTION_ABSTAIN: VOTE_OPTION_ABSTAIN defines an abstain vote option. + - VOTE_OPTION_NO: VOTE_OPTION_NO defines a no vote option. + - VOTE_OPTION_NO_WITH_VETO: VOTE_OPTION_NO_WITH_VETO defines a no with veto vote option. + weight: + type: string + description: >- + WeightedVoteOption defines a unit of vote for vote + split. description: >- Vote defines a vote on a governance proposal. @@ -12157,7 +13132,6 @@ paths: type: object properties: vote: - description: vote defined the queried vote. type: object properties: proposal_id: @@ -12165,24 +13139,39 @@ paths: format: uint64 voter: type: string - option: - type: string - enum: - - VOTE_OPTION_UNSPECIFIED - - VOTE_OPTION_YES - - VOTE_OPTION_ABSTAIN - - VOTE_OPTION_NO - - VOTE_OPTION_NO_WITH_VETO - default: VOTE_OPTION_UNSPECIFIED - description: >- - VoteOption enumerates the valid vote options for a given - governance proposal. + options: + type: array + items: + type: object + properties: + option: + type: string + enum: + - VOTE_OPTION_UNSPECIFIED + - VOTE_OPTION_YES + - VOTE_OPTION_ABSTAIN + - VOTE_OPTION_NO + - VOTE_OPTION_NO_WITH_VETO + default: VOTE_OPTION_UNSPECIFIED + description: >- + VoteOption enumerates the valid vote options for a + given governance proposal. + + - VOTE_OPTION_UNSPECIFIED: VOTE_OPTION_UNSPECIFIED defines a no-op vote option. + - VOTE_OPTION_YES: VOTE_OPTION_YES defines a yes vote option. + - VOTE_OPTION_ABSTAIN: VOTE_OPTION_ABSTAIN defines an abstain vote option. + - VOTE_OPTION_NO: VOTE_OPTION_NO defines a no vote option. + - VOTE_OPTION_NO_WITH_VETO: VOTE_OPTION_NO_WITH_VETO defines a no with veto vote option. + weight: + type: string + description: >- + WeightedVoteOption defines a unit of vote for vote + split. + description: >- + Vote defines a vote on a governance proposal. - - VOTE_OPTION_UNSPECIFIED: VOTE_OPTION_UNSPECIFIED defines a no-op vote option. - - VOTE_OPTION_YES: VOTE_OPTION_YES defines a yes vote option. - - VOTE_OPTION_ABSTAIN: VOTE_OPTION_ABSTAIN defines an abstain vote option. - - VOTE_OPTION_NO: VOTE_OPTION_NO defines a no vote option. - - VOTE_OPTION_NO_WITH_VETO: VOTE_OPTION_NO_WITH_VETO defines a no with veto vote option. + A Vote consists of a proposal ID, the voter, and the vote + option. description: >- QueryVoteResponse is the response type for the Query/Vote RPC method. @@ -12673,29 +13662,42 @@ paths: type: string format: int64 title: >- - height at which validator was first a candidate OR was + Height at which validator was first a candidate OR was unjailed index_offset: type: string format: int64 - title: index offset into signed block bit array + description: >- + 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: type: string format: date-time - title: timestamp validator cannot be unjailed until + description: >- + Timestamp until which the validator is jailed due to + liveness downtime. tombstoned: type: boolean - title: >- - whether or not a validator has been tombstoned (killed - out of validator + description: >- + Whether or not a validator has been tombstoned (killed + out of validator set). It is set - set) + once the validator commits an equivocation or for any + other configured misbehiavor. missed_blocks_counter: type: string format: int64 - title: >- - missed blocks counter (to avoid scanning the array every - time) + description: >- + A counter kept to avoid unnecessary array reads. + + Note that `Sum(MissedBlocksBitArray)` always equals + `MissedBlocksCounter`. description: >- ValidatorSigningInfo defines a validator's signing info for monitoring their @@ -12816,9 +13818,6 @@ paths: type: object properties: val_signing_info: - title: >- - val_signing_info is the signing info of requested val cons - address type: object properties: address: @@ -12827,34 +13826,50 @@ paths: type: string format: int64 title: >- - height at which validator was first a candidate OR was + Height at which validator was first a candidate OR was unjailed index_offset: type: string format: int64 - title: index offset into signed block bit array + description: >- + 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: type: string format: date-time - title: timestamp validator cannot be unjailed until + description: >- + Timestamp until which the validator is jailed due to + liveness downtime. tombstoned: type: boolean - title: >- - whether or not a validator has been tombstoned (killed out - of validator + description: >- + Whether or not a validator has been tombstoned (killed out + of validator set). It is set - set) + once the validator commits an equivocation or for any + other configured misbehiavor. missed_blocks_counter: type: string format: int64 - title: >- - missed blocks counter (to avoid scanning the array every - time) + description: >- + A counter kept to avoid unnecessary array reads. + + Note that `Sum(MissedBlocksBitArray)` always equals + `MissedBlocksCounter`. description: >- ValidatorSigningInfo defines a validator's signing info for monitoring their liveness activity. + title: >- + val_signing_info is the signing info of requested val cons + address title: >- QuerySigningInfoResponse is the response type for the Query/SigningInfo RPC @@ -12912,10 +13927,17 @@ paths: properties: delegator_address: type: string + description: >- + delegator_address is the bech32-encoded address of + the delegator. validator_address: type: string + description: >- + validator_address is the bech32-encoded address of + the validator. shares: type: string + description: shares define the delegation shares received. description: >- Delegation represents the bond with tokens held by an account. It is @@ -13232,10 +14254,19 @@ paths: properties: delegator_address: type: string + description: >- + delegator_address is the bech32-encoded address of + the delegator. validator_src_address: type: string + description: >- + validator_src_address is the validator redelegation + source operator address. validator_dst_address: type: string + description: >- + validator_dst_address is the validator redelegation + destination operator address. entries: type: array items: @@ -13244,16 +14275,30 @@ paths: creation_height: type: string format: int64 + description: >- + creation_height defines the height which the + redelegation took place. completion_time: type: string format: date-time + description: >- + completion_time defines the unix time for + redelegation completion. initial_balance: type: string + description: >- + initial_balance defines the initial balance + when redelegation started. shares_dst: type: string + description: >- + shares_dst is the amount of + destination-validator shares created by + redelegation. description: >- RedelegationEntry defines a redelegation object with relevant metadata. + description: entries are the redelegation entries. description: >- Redelegation contains the list of a particular delegator's redelegating bonds @@ -13271,13 +14316,26 @@ paths: creation_height: type: string format: int64 + description: >- + creation_height defines the height which the + redelegation took place. completion_time: type: string format: date-time + description: >- + completion_time defines the unix time for + redelegation completion. initial_balance: type: string + description: >- + initial_balance defines the initial balance + when redelegation started. shares_dst: type: string + description: >- + shares_dst is the amount of + destination-validator shares created by + redelegation. description: >- RedelegationEntry defines a redelegation object with relevant metadata. @@ -13596,8 +14654,14 @@ paths: properties: delegator_address: type: string + description: >- + delegator_address is the bech32-encoded address of the + delegator. validator_address: type: string + description: >- + validator_address is the bech32-encoded address of the + validator. entries: type: array items: @@ -13606,16 +14670,29 @@ paths: creation_height: type: string format: int64 + description: >- + creation_height is the height which the unbonding + took place. completion_time: type: string format: date-time + description: >- + completion_time is the unix time for unbonding + completion. initial_balance: type: string + description: >- + initial_balance defines the tokens initially + scheduled to receive at completion. balance: type: string + description: >- + balance defines the tokens to receive at + completion. description: >- UnbondingDelegationEntry defines an unbonding object with relevant metadata. + description: entries are the unbonding delegation entries. description: >- UnbondingDelegation stores all of a single delegator's unbonding bonds @@ -13906,6 +14983,9 @@ paths: properties: operator_address: type: string + description: >- + operator_address defines the address of the validator's + operator; bech encoded in JSON. consensus_pubkey: type: object properties: @@ -14085,7 +15165,13 @@ paths: } jailed: type: boolean + description: >- + jailed defined whether the validator has been jailed + from bonded status or not. status: + description: >- + status is the validator status + (bonded/unbonding/unbonded). type: string enum: - BOND_STATUS_UNSPECIFIED @@ -14093,62 +15179,92 @@ paths: - BOND_STATUS_UNBONDING - BOND_STATUS_BONDED default: BOND_STATUS_UNSPECIFIED - description: |- - BondStatus is the status of a validator. - - - BOND_STATUS_UNSPECIFIED: UNSPECIFIED defines an invalid validator status. - - BOND_STATUS_UNBONDED: UNBONDED defines a validator that is not bonded. - - BOND_STATUS_UNBONDING: UNBONDING defines a validator that is unbonding. - - BOND_STATUS_BONDED: BONDED defines a validator that is bonded. tokens: type: string + description: >- + tokens define the delegated tokens (incl. + self-delegation). delegator_shares: type: string + description: >- + delegator_shares defines total shares issued to a + validator's delegators. description: + description: >- + description defines the description terms for the + validator. type: object properties: moniker: type: string + description: >- + moniker defines a human-readable name for the + validator. identity: type: string + description: >- + identity defines an optional identity signature (ex. + UPort or Keybase). website: type: string + description: website defines an optional website link. security_contact: type: string + description: >- + security_contact defines an optional email for + security contact. details: type: string - description: Description defines a validator description. + description: details define other optional details. unbonding_height: type: string format: int64 + description: >- + unbonding_height defines, if unbonding, the height at + which this validator has begun unbonding. unbonding_time: type: string format: date-time + description: >- + unbonding_time defines, if unbonding, the min time for + the validator to complete unbonding. commission: + description: commission defines the commission parameters. type: object properties: commission_rates: + description: >- + commission_rates defines the initial commission + rates to be used for creating a validator. type: object properties: rate: type: string + description: >- + rate is the commission rate charged to + delegators, as a fraction. max_rate: type: string + description: >- + max_rate defines the maximum commission rate + which validator can ever charge, as a fraction. max_change_rate: type: string - description: >- - CommissionRates defines the initial commission rates - to be used for creating - - a validator. + description: >- + max_change_rate defines the maximum daily + increase of the validator commission, as a + fraction. update_time: type: string format: date-time - description: >- - Commission defines commission parameters for a given - validator. + description: >- + update_time is the last time the commission rate was + changed. min_self_delegation: type: string + description: >- + min_self_delegation is the validator's self declared + minimum self delegation. description: >- Validator defines a validator, together with the total amount of the @@ -14450,11 +15566,13 @@ paths: type: object properties: validator: - description: validator defines the the validator info. type: object properties: operator_address: type: string + description: >- + operator_address defines the address of the validator's + operator; bech encoded in JSON. consensus_pubkey: type: object properties: @@ -14632,7 +15750,13 @@ paths: } jailed: type: boolean + description: >- + jailed defined whether the validator has been jailed from + bonded status or not. status: + description: >- + status is the validator status + (bonded/unbonding/unbonded). type: string enum: - BOND_STATUS_UNSPECIFIED @@ -14640,62 +15764,114 @@ paths: - BOND_STATUS_UNBONDING - BOND_STATUS_BONDED default: BOND_STATUS_UNSPECIFIED - description: |- - BondStatus is the status of a validator. - - - BOND_STATUS_UNSPECIFIED: UNSPECIFIED defines an invalid validator status. - - BOND_STATUS_UNBONDED: UNBONDED defines a validator that is not bonded. - - BOND_STATUS_UNBONDING: UNBONDING defines a validator that is unbonding. - - BOND_STATUS_BONDED: BONDED defines a validator that is bonded. tokens: type: string + description: >- + tokens define the delegated tokens (incl. + self-delegation). delegator_shares: type: string + description: >- + delegator_shares defines total shares issued to a + validator's delegators. description: + description: >- + description defines the description terms for the + validator. type: object properties: moniker: type: string + description: >- + moniker defines a human-readable name for the + validator. identity: type: string + description: >- + identity defines an optional identity signature (ex. + UPort or Keybase). website: type: string + description: website defines an optional website link. security_contact: type: string + description: >- + security_contact defines an optional email for + security contact. details: type: string - description: Description defines a validator description. + description: details define other optional details. unbonding_height: type: string format: int64 + description: >- + unbonding_height defines, if unbonding, the height at + which this validator has begun unbonding. unbonding_time: type: string format: date-time + description: >- + unbonding_time defines, if unbonding, the min time for the + validator to complete unbonding. commission: + description: commission defines the commission parameters. type: object properties: commission_rates: + description: >- + commission_rates defines the initial commission rates + to be used for creating a validator. type: object properties: rate: type: string + description: >- + rate is the commission rate charged to delegators, + as a fraction. max_rate: type: string + description: >- + max_rate defines the maximum commission rate which + validator can ever charge, as a fraction. max_change_rate: type: string - description: >- - CommissionRates defines the initial commission rates - to be used for creating - - a validator. + description: >- + max_change_rate defines the maximum daily increase + of the validator commission, as a fraction. update_time: type: string format: date-time - description: >- - Commission defines commission parameters for a given - validator. + description: >- + update_time is the last time the commission rate was + changed. min_self_delegation: type: string + description: >- + min_self_delegation is the validator's self declared + minimum self delegation. + description: >- + 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. description: |- QueryDelegatorValidatorResponse response type for the Query/DelegatorValidator RPC method. @@ -14999,6 +16175,9 @@ paths: properties: operator_address: type: string + description: >- + operator_address defines the address of the + validator's operator; bech encoded in JSON. consensus_pubkey: type: object properties: @@ -15179,7 +16358,13 @@ paths: } jailed: type: boolean + description: >- + jailed defined whether the validator has been jailed + from bonded status or not. status: + description: >- + status is the validator status + (bonded/unbonding/unbonded). type: string enum: - BOND_STATUS_UNSPECIFIED @@ -15187,62 +16372,93 @@ paths: - BOND_STATUS_UNBONDING - BOND_STATUS_BONDED default: BOND_STATUS_UNSPECIFIED - description: |- - BondStatus is the status of a validator. - - - BOND_STATUS_UNSPECIFIED: UNSPECIFIED defines an invalid validator status. - - BOND_STATUS_UNBONDED: UNBONDED defines a validator that is not bonded. - - BOND_STATUS_UNBONDING: UNBONDING defines a validator that is unbonding. - - BOND_STATUS_BONDED: BONDED defines a validator that is bonded. tokens: type: string + description: >- + tokens define the delegated tokens (incl. + self-delegation). delegator_shares: type: string + description: >- + delegator_shares defines total shares issued to a + validator's delegators. description: + description: >- + description defines the description terms for the + validator. type: object properties: moniker: type: string + description: >- + moniker defines a human-readable name for the + validator. identity: type: string + description: >- + identity defines an optional identity signature + (ex. UPort or Keybase). website: type: string + description: website defines an optional website link. security_contact: type: string + description: >- + security_contact defines an optional email for + security contact. details: type: string - description: Description defines a validator description. + description: details define other optional details. unbonding_height: type: string format: int64 + description: >- + unbonding_height defines, if unbonding, the height + at which this validator has begun unbonding. unbonding_time: type: string format: date-time + description: >- + unbonding_time defines, if unbonding, the min time + for the validator to complete unbonding. commission: + description: commission defines the commission parameters. type: object properties: commission_rates: + description: >- + commission_rates defines the initial commission + rates to be used for creating a validator. type: object properties: rate: type: string + description: >- + rate is the commission rate charged to + delegators, as a fraction. max_rate: type: string + description: >- + max_rate defines the maximum commission rate + which validator can ever charge, as a + fraction. max_change_rate: type: string - description: >- - CommissionRates defines the initial commission - rates to be used for creating - - a validator. + description: >- + max_change_rate defines the maximum daily + increase of the validator commission, as a + fraction. update_time: type: string format: date-time - description: >- - Commission defines commission parameters for a given - validator. + description: >- + update_time is the last time the commission rate + was changed. min_self_delegation: type: string + description: >- + min_self_delegation is the validator's self declared + minimum self delegation. description: >- Validator defines a validator, together with the total amount of the @@ -15485,17 +16701,26 @@ paths: properties: unbonding_time: type: string + description: unbonding_time is the time duration of unbonding. max_validators: type: integer format: int64 + description: max_validators is the maximum number of validators. max_entries: type: integer format: int64 + description: >- + max_entries is the max entries for either unbonding + delegation or redelegation (per pair/trio). historical_entries: type: integer format: int64 + description: >- + historical_entries is the number of historical entries to + persist. bond_denom: type: string + description: bond_denom defines the bondable coin denomination. description: >- QueryParamsResponse is response type for the Query/Params RPC method. @@ -15917,6 +17142,9 @@ paths: properties: operator_address: type: string + description: >- + operator_address defines the address of the validator's + operator; bech encoded in JSON. consensus_pubkey: type: object properties: @@ -16096,7 +17324,13 @@ paths: } jailed: type: boolean + description: >- + jailed defined whether the validator has been jailed + from bonded status or not. status: + description: >- + status is the validator status + (bonded/unbonding/unbonded). type: string enum: - BOND_STATUS_UNSPECIFIED @@ -16104,62 +17338,92 @@ paths: - BOND_STATUS_UNBONDING - BOND_STATUS_BONDED default: BOND_STATUS_UNSPECIFIED - description: |- - BondStatus is the status of a validator. - - - BOND_STATUS_UNSPECIFIED: UNSPECIFIED defines an invalid validator status. - - BOND_STATUS_UNBONDED: UNBONDED defines a validator that is not bonded. - - BOND_STATUS_UNBONDING: UNBONDING defines a validator that is unbonding. - - BOND_STATUS_BONDED: BONDED defines a validator that is bonded. tokens: type: string + description: >- + tokens define the delegated tokens (incl. + self-delegation). delegator_shares: type: string + description: >- + delegator_shares defines total shares issued to a + validator's delegators. description: + description: >- + description defines the description terms for the + validator. type: object properties: moniker: type: string + description: >- + moniker defines a human-readable name for the + validator. identity: type: string + description: >- + identity defines an optional identity signature (ex. + UPort or Keybase). website: type: string + description: website defines an optional website link. security_contact: type: string + description: >- + security_contact defines an optional email for + security contact. details: type: string - description: Description defines a validator description. + description: details define other optional details. unbonding_height: type: string format: int64 + description: >- + unbonding_height defines, if unbonding, the height at + which this validator has begun unbonding. unbonding_time: type: string format: date-time + description: >- + unbonding_time defines, if unbonding, the min time for + the validator to complete unbonding. commission: + description: commission defines the commission parameters. type: object properties: commission_rates: + description: >- + commission_rates defines the initial commission + rates to be used for creating a validator. type: object properties: rate: type: string + description: >- + rate is the commission rate charged to + delegators, as a fraction. max_rate: type: string + description: >- + max_rate defines the maximum commission rate + which validator can ever charge, as a fraction. max_change_rate: type: string - description: >- - CommissionRates defines the initial commission rates - to be used for creating - - a validator. + description: >- + max_change_rate defines the maximum daily + increase of the validator commission, as a + fraction. update_time: type: string format: date-time - description: >- - Commission defines commission parameters for a given - validator. + description: >- + update_time is the last time the commission rate was + changed. min_self_delegation: type: string + description: >- + min_self_delegation is the validator's self declared + minimum self delegation. description: >- Validator defines a validator, together with the total amount of the @@ -16459,11 +17723,13 @@ paths: type: object properties: validator: - description: validator defines the the validator info. type: object properties: operator_address: type: string + description: >- + operator_address defines the address of the validator's + operator; bech encoded in JSON. consensus_pubkey: type: object properties: @@ -16641,7 +17907,13 @@ paths: } jailed: type: boolean + description: >- + jailed defined whether the validator has been jailed from + bonded status or not. status: + description: >- + status is the validator status + (bonded/unbonding/unbonded). type: string enum: - BOND_STATUS_UNSPECIFIED @@ -16649,62 +17921,114 @@ paths: - BOND_STATUS_UNBONDING - BOND_STATUS_BONDED default: BOND_STATUS_UNSPECIFIED - description: |- - BondStatus is the status of a validator. - - - BOND_STATUS_UNSPECIFIED: UNSPECIFIED defines an invalid validator status. - - BOND_STATUS_UNBONDED: UNBONDED defines a validator that is not bonded. - - BOND_STATUS_UNBONDING: UNBONDING defines a validator that is unbonding. - - BOND_STATUS_BONDED: BONDED defines a validator that is bonded. tokens: type: string + description: >- + tokens define the delegated tokens (incl. + self-delegation). delegator_shares: type: string + description: >- + delegator_shares defines total shares issued to a + validator's delegators. description: + description: >- + description defines the description terms for the + validator. type: object properties: moniker: type: string + description: >- + moniker defines a human-readable name for the + validator. identity: type: string + description: >- + identity defines an optional identity signature (ex. + UPort or Keybase). website: type: string + description: website defines an optional website link. security_contact: type: string + description: >- + security_contact defines an optional email for + security contact. details: type: string - description: Description defines a validator description. + description: details define other optional details. unbonding_height: type: string format: int64 + description: >- + unbonding_height defines, if unbonding, the height at + which this validator has begun unbonding. unbonding_time: type: string format: date-time + description: >- + unbonding_time defines, if unbonding, the min time for the + validator to complete unbonding. commission: + description: commission defines the commission parameters. type: object properties: commission_rates: + description: >- + commission_rates defines the initial commission rates + to be used for creating a validator. type: object properties: rate: type: string + description: >- + rate is the commission rate charged to delegators, + as a fraction. max_rate: type: string + description: >- + max_rate defines the maximum commission rate which + validator can ever charge, as a fraction. max_change_rate: type: string - description: >- - CommissionRates defines the initial commission rates - to be used for creating - - a validator. + description: >- + max_change_rate defines the maximum daily increase + of the validator commission, as a fraction. update_time: type: string format: date-time - description: >- - Commission defines commission parameters for a given - validator. + description: >- + update_time is the last time the commission rate was + changed. min_self_delegation: type: string + description: >- + min_self_delegation is the validator's self declared + minimum self delegation. + description: >- + 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. title: >- QueryValidatorResponse is response type for the Query/Validator RPC method @@ -16925,10 +18249,17 @@ paths: properties: delegator_address: type: string + description: >- + delegator_address is the bech32-encoded address of + the delegator. validator_address: type: string + description: >- + validator_address is the bech32-encoded address of + the validator. shares: type: string + description: shares define the delegation shares received. description: >- Delegation represents the bond with tokens held by an account. It is @@ -17233,9 +18564,6 @@ paths: type: object properties: delegation_response: - description: >- - delegation_responses defines the delegation info of a - delegation. type: object properties: delegation: @@ -17243,10 +18571,17 @@ paths: properties: delegator_address: type: string + description: >- + delegator_address is the bech32-encoded address of the + delegator. validator_address: type: string + description: >- + validator_address is the bech32-encoded address of the + validator. shares: type: string + description: shares define the delegation shares received. description: >- Delegation represents the bond with tokens held by an account. It is @@ -17270,6 +18605,12 @@ paths: custom method signatures required by gogoproto. + description: >- + DelegationResponse is equivalent to Delegation except that it + contains a + + balance in addition to shares which is more suitable for + client responses. description: >- QueryDelegationResponse is response type for the Query/Delegation RPC method. @@ -17488,13 +18829,18 @@ paths: type: object properties: unbond: - description: unbond defines the unbonding information of a delegation. type: object properties: delegator_address: type: string + description: >- + delegator_address is the bech32-encoded address of the + delegator. validator_address: type: string + description: >- + validator_address is the bech32-encoded address of the + validator. entries: type: array items: @@ -17503,16 +18849,32 @@ paths: creation_height: type: string format: int64 + description: >- + creation_height is the height which the unbonding + took place. completion_time: type: string format: date-time + description: >- + completion_time is the unix time for unbonding + completion. initial_balance: type: string + description: >- + initial_balance defines the tokens initially + scheduled to receive at completion. balance: type: string + description: balance defines the tokens to receive at completion. description: >- UnbondingDelegationEntry defines an unbonding object with relevant metadata. + description: entries are the unbonding delegation entries. + description: >- + UnbondingDelegation stores all of a single delegator's + unbonding bonds + + for a single validator in an time-ordered list. description: >- QueryDelegationResponse is response type for the Query/UnbondingDelegation @@ -17739,8 +19101,14 @@ paths: properties: delegator_address: type: string + description: >- + delegator_address is the bech32-encoded address of the + delegator. validator_address: type: string + description: >- + validator_address is the bech32-encoded address of the + validator. entries: type: array items: @@ -17749,16 +19117,29 @@ paths: creation_height: type: string format: int64 + description: >- + creation_height is the height which the unbonding + took place. completion_time: type: string format: date-time + description: >- + completion_time is the unix time for unbonding + completion. initial_balance: type: string + description: >- + initial_balance defines the tokens initially + scheduled to receive at completion. balance: type: string + description: >- + balance defines the tokens to receive at + completion. description: >- UnbondingDelegationEntry defines an unbonding object with relevant metadata. + description: entries are the unbonding delegation entries. description: >- UnbondingDelegation stores all of a single delegator's unbonding bonds @@ -18573,7 +19954,6 @@ paths: type: object properties: tx_response: - description: tx_response is the queried TxResponses. type: object properties: height: @@ -18660,7 +20040,6 @@ paths: format: int64 description: Amount of gas consumed by transaction. tx: - description: The request transaction bytes. type: object properties: type_url: @@ -18727,6 +20106,114 @@ paths: description: >- Must be a valid serialized protocol buffer of the above specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer + message along with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any + values in the form + + of utility functions or additional generated methods of + the Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := ptypes.MarshalAny(foo) + ... + foo := &pb.Foo{} + if err := ptypes.UnmarshalAny(any, foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by + default use + + 'type.googleapis.com/full.type.name' as the type URL and + the unpack + + methods only use the fully qualified type name after the + last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will + yield type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with + an + + additional field `@type` which contains the type URL. + Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a + custom JSON + + representation, that representation will be embedded + adding a field + + `value` which holds the custom JSON in addition to the + `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } timestamp: type: string description: >- @@ -18737,6 +20224,11 @@ paths: For height == 1, it's genesis time. + description: >- + TxResponse defines a structure containing relevant tx data and + metadata. The + + tags are stringified and the log is JSON decoded. description: |- BroadcastTxResponse is the response type for the Service.BroadcastTx method. @@ -19447,20 +20939,6 @@ paths: such as a git commit that validators could automatically upgrade to upgraded_client_state: - title: >- - 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 type: object properties: type_url: @@ -19635,6 +21113,20 @@ paths: "@type": "type.googleapis.com/google.protobuf.Duration", "value": "1.212s" } + title: >- + 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 description: >- QueryCurrentPlanResponse is the response type for the Query/CurrentPlan RPC @@ -20954,7 +22446,6 @@ paths: type: string title: client identifier client_state: - title: client state type: object properties: type_url: @@ -21129,6 +22620,7 @@ paths: "@type": "type.googleapis.com/google.protobuf.Duration", "value": "1.212s" } + title: client state description: >- IdentifiedClientState defines a client state with an additional client @@ -21383,7 +22875,6 @@ paths: type: object properties: consensus_state: - title: consensus state associated with the channel type: object properties: type_url: @@ -21554,6 +23045,7 @@ paths: "@type": "type.googleapis.com/google.protobuf.Duration", "value": "1.212s" } + title: consensus state associated with the channel client_id: type: string title: client ID associated with the consensus state @@ -24687,7 +26179,6 @@ paths: type: string title: client identifier client_state: - title: client state type: object properties: type_url: @@ -24864,6 +26355,7 @@ paths: "@type": "type.googleapis.com/google.protobuf.Duration", "value": "1.212s" } + title: client state description: >- IdentifiedClientState defines a client state with an additional client @@ -25152,7 +26644,6 @@ paths: type: object properties: client_state: - title: client state associated with the request identifier type: object properties: type_url: @@ -25323,6 +26814,7 @@ paths: "@type": "type.googleapis.com/google.protobuf.Duration", "value": "1.212s" } + title: client state associated with the request identifier proof: type: string format: byte @@ -25604,7 +27096,6 @@ paths: be monitonically increasing even as the RevisionHeight gets reset consensus_state: - title: consensus state type: object properties: type_url: @@ -25781,6 +27272,7 @@ paths: "@type": "type.googleapis.com/google.protobuf.Duration", "value": "1.212s" } + title: consensus state description: >- ConsensusStateWithHeight defines a consensus state with an additional height field. @@ -26074,9 +27566,6 @@ paths: type: object properties: consensus_state: - title: >- - consensus state associated with the client identifier at the - given height type: object properties: type_url: @@ -26247,6 +27736,9 @@ paths: "@type": "type.googleapis.com/google.protobuf.Duration", "value": "1.212s" } + title: >- + consensus state associated with the client identifier at the + given height proof: type: string format: byte @@ -27501,7 +28993,6 @@ paths: type: string title: client identifier client_state: - title: client state type: object properties: type_url: @@ -27676,6 +29167,7 @@ paths: "@type": "type.googleapis.com/google.protobuf.Duration", "value": "1.212s" } + title: client state description: >- IdentifiedClientState defines a client state with an additional client @@ -27925,7 +29417,6 @@ paths: type: object properties: consensus_state: - title: consensus state associated with the channel type: object properties: type_url: @@ -28096,6 +29587,7 @@ paths: "@type": "type.googleapis.com/google.protobuf.Duration", "value": "1.212s" } + title: consensus state associated with the channel client_id: type: string title: client ID associated with the consensus state @@ -28476,9 +29968,6 @@ paths: type: object properties: denom_trace: - description: >- - denom_trace returns the requested denomination trace - information. type: object properties: path: @@ -28491,6 +29980,11 @@ paths: base_denom: type: string description: base denomination of the relayed fungible token. + description: >- + DenomTrace contains the base denomination for ICS20 fungible + tokens and the + + source tracing information path. description: >- QueryDenomTraceResponse is the response type for the Query/DenomTrace RPC @@ -29885,7 +31379,6 @@ definitions: type: object properties: account: - description: account defines the account of the corresponding address. type: object properties: type_url: @@ -29946,9 +31439,296 @@ definitions: description: >- Must be a valid serialized protocol buffer of the above specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer message along + with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values in the + form + + of utility functions or additional generated methods of the Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := ptypes.MarshalAny(foo) + ... + foo := &pb.Foo{} + if err := ptypes.UnmarshalAny(any, foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by default use + + 'type.googleapis.com/full.type.name' as the type URL and the unpack + + methods only use the fully qualified type name after the last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with an + + additional field `@type` which contains the type URL. Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom JSON + + representation, that representation will be embedded adding a field + + `value` which holds the custom JSON in addition to the `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } description: >- QueryAccountResponse is the response type for the Query/Account RPC method. + cosmos.auth.v1beta1.QueryAccountsResponse: + type: object + properties: + accounts: + type: array + items: + type: object + properties: + type_url: + type: string + description: >- + A URL/resource name that uniquely identifies the type of the + serialized + + protocol buffer message. This string must contain at least + + one "/" character. The last segment of the URL's path must + represent + + the fully qualified name of the type (as in + + `path/google.protobuf.Duration`). The name should be in a + canonical form + + (e.g., leading "." is not accepted). + + + In practice, teams usually precompile into the binary all types + that they + + expect it to use in the context of Any. However, for URLs which + use the + + scheme `http`, `https`, or no scheme, one can optionally set up + a type + + server that maps type URLs to message definitions as follows: + + + * If no scheme is provided, `https` is assumed. + + * An HTTP GET on the URL must yield a [google.protobuf.Type][] + value in binary format, or produce an error. + * Applications are allowed to cache lookup results based on the + URL, or have them precompiled into a binary to avoid any + lookup. Therefore, binary compatibility needs to be preserved + on changes to types. (Use versioned type names to manage + breaking changes.) + + Note: this functionality is not currently available in the + official + + protobuf release, and it is not used for type URLs beginning + with + + type.googleapis.com. + + + Schemes other than `http`, `https` (or the empty scheme) might + be + + used with implementation specific semantics. + value: + type: string + format: byte + description: >- + Must be a valid serialized protocol buffer of the above + specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer message along + with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values in the + form + + of utility functions or additional generated methods of the Any + type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := ptypes.MarshalAny(foo) + ... + foo := &pb.Foo{} + if err := ptypes.UnmarshalAny(any, foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by default use + + 'type.googleapis.com/full.type.name' as the type URL and the unpack + + methods only use the fully qualified type name after the last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with an + + additional field `@type` which contains the type URL. Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom JSON + + representation, that representation will be embedded adding a field + + `value` which holds the custom JSON in addition to the `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } + title: accounts are the existing accounts + pagination: + description: pagination defines the pagination in the response. + type: object + properties: + next_key: + type: string + format: byte + title: |- + next_key is the key to be passed to PageRequest.key to + query the next page most efficiently + total: + type: string + format: uint64 + title: >- + total is total number of results available if + PageRequest.count_total + + was set, its value is undefined otherwise + description: >- + QueryAccountsResponse is the response type for the Query/Accounts RPC + method. cosmos.auth.v1beta1.QueryParamsResponse: type: object properties: @@ -29972,6 +31752,74 @@ definitions: type: string format: uint64 description: QueryParamsResponse is the response type for the Query/Params RPC method. + cosmos.base.query.v1beta1.PageRequest: + type: object + properties: + key: + type: string + format: byte + description: |- + key is a value returned in PageResponse.next_key to begin + querying the next page most efficiently. Only one of offset or key + should be set. + offset: + type: string + format: uint64 + description: |- + offset is a numeric offset that can be used when key is unavailable. + It is less efficient than using key. Only one of offset or key should + be set. + limit: + type: string + format: uint64 + description: >- + limit is the total number of results to be returned in the result + page. + + If left empty it will default to a value to be set by each app. + count_total: + type: boolean + description: >- + count_total is set to true to indicate that the result set should + include + + a count of the total number of items available for pagination in UIs. + + count_total is only respected when offset is used. It is ignored when + key + + is set. + description: |- + message SomeRequest { + Foo some_parameter = 1; + PageRequest pagination = 2; + } + title: |- + PageRequest is to be embedded in gRPC request messages for efficient + pagination. Ex: + cosmos.base.query.v1beta1.PageResponse: + type: object + properties: + next_key: + type: string + format: byte + title: |- + next_key is the key to be passed to PageRequest.key to + query the next page most efficiently + total: + type: string + format: uint64 + title: |- + total is total number of results available if PageRequest.count_total + was set, its value is undefined otherwise + description: |- + 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; + } google.protobuf.Any: type: object properties: @@ -30301,6 +32149,96 @@ definitions: "@type": "type.googleapis.com/google.protobuf.Duration", "value": "1.212s" } + cosmos.bank.v1beta1.DenomUnit: + type: object + properties: + denom: + type: string + description: denom represents the string name of the given denom unit (e.g uatom). + exponent: + type: integer + format: int64 + description: >- + 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: + type: array + items: + type: string + title: aliases is a list of string aliases for the given denom + description: |- + DenomUnit represents a struct that describes a given + denomination unit of the basic token. + cosmos.bank.v1beta1.Metadata: + type: object + properties: + description: + type: string + denom_units: + type: array + items: + type: object + properties: + denom: + type: string + description: >- + denom represents the string name of the given denom unit (e.g + uatom). + exponent: + type: integer + format: int64 + description: >- + 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: + type: array + items: + type: string + title: aliases is a list of string aliases for the given denom + description: |- + DenomUnit represents a struct that describes a given + denomination unit of the basic token. + title: denom_units represents the list of DenomUnit's for a given coin + base: + type: string + description: >- + base represents the base denom (should be the DenomUnit with exponent + = 0). + display: + type: string + description: |- + display indicates the suggested denom that should be + displayed in clients. + name: + type: string + title: 'name defines the name of the token (eg: Cosmos Atom)' + symbol: + type: string + description: >- + symbol is the token symbol usually shown on exchanges (eg: ATOM). This + can + + be the same as the display. + description: |- + Metadata represents a struct that describes + a basic token. cosmos.bank.v1beta1.Params: type: object properties: @@ -30366,15 +32304,182 @@ definitions: type: object properties: balance: - description: balance is the balance of the coin. type: object properties: denom: type: string amount: type: string + description: |- + 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. description: >- QueryBalanceResponse is the response type for the Query/Balance RPC + method. + cosmos.bank.v1beta1.QueryDenomMetadataResponse: + type: object + properties: + metadata: + type: object + properties: + description: + type: string + denom_units: + type: array + items: + type: object + properties: + denom: + type: string + description: >- + denom represents the string name of the given denom unit + (e.g uatom). + exponent: + type: integer + format: int64 + description: >- + 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: + type: array + items: + type: string + title: aliases is a list of string aliases for the given denom + description: |- + DenomUnit represents a struct that describes a given + denomination unit of the basic token. + title: denom_units represents the list of DenomUnit's for a given coin + base: + type: string + description: >- + base represents the base denom (should be the DenomUnit with + exponent = 0). + display: + type: string + description: |- + display indicates the suggested denom that should be + displayed in clients. + name: + type: string + title: 'name defines the name of the token (eg: Cosmos Atom)' + symbol: + type: string + description: >- + symbol is the token symbol usually shown on exchanges (eg: ATOM). + This can + + be the same as the display. + description: |- + Metadata represents a struct that describes + a basic token. + description: >- + QueryDenomMetadataResponse is the response type for the + Query/DenomMetadata RPC + + method. + cosmos.bank.v1beta1.QueryDenomsMetadataResponse: + type: object + properties: + metadatas: + type: array + items: + type: object + properties: + description: + type: string + denom_units: + type: array + items: + type: object + properties: + denom: + type: string + description: >- + denom represents the string name of the given denom unit + (e.g uatom). + exponent: + type: integer + format: int64 + description: >- + 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: + type: array + items: + type: string + title: aliases is a list of string aliases for the given denom + description: |- + DenomUnit represents a struct that describes a given + denomination unit of the basic token. + title: denom_units represents the list of DenomUnit's for a given coin + base: + type: string + description: >- + base represents the base denom (should be the DenomUnit with + exponent = 0). + display: + type: string + description: |- + display indicates the suggested denom that should be + displayed in clients. + name: + type: string + title: 'name defines the name of the token (eg: Cosmos Atom)' + symbol: + type: string + description: >- + symbol is the token symbol usually shown on exchanges (eg: + ATOM). This can + + be the same as the display. + description: |- + Metadata represents a struct that describes + a basic token. + description: >- + metadata provides the client information for all the registered + tokens. + pagination: + description: pagination defines the pagination in the response. + type: object + properties: + next_key: + type: string + format: byte + title: |- + next_key is the key to be passed to PageRequest.key to + query the next page most efficiently + total: + type: string + format: uint64 + title: >- + total is total number of results available if + PageRequest.count_total + + was set, its value is undefined otherwise + description: >- + QueryDenomsMetadataResponse is the response type for the + Query/DenomsMetadata RPC + method. cosmos.bank.v1beta1.QueryParamsResponse: type: object @@ -30406,13 +32511,17 @@ definitions: type: object properties: amount: - description: amount is the supply of the coin. type: object properties: denom: type: string amount: type: string + description: |- + 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. description: >- QuerySupplyOfResponse is the response type for the Query/SupplyOf RPC method. @@ -30449,74 +32558,6 @@ definitions: description: |- SendEnabled maps coin denom to a send_enabled status (whether a denom is sendable). - cosmos.base.query.v1beta1.PageRequest: - type: object - properties: - key: - type: string - format: byte - description: |- - key is a value returned in PageResponse.next_key to begin - querying the next page most efficiently. Only one of offset or key - should be set. - offset: - type: string - format: uint64 - description: |- - offset is a numeric offset that can be used when key is unavailable. - It is less efficient than using key. Only one of offset or key should - be set. - limit: - type: string - format: uint64 - description: >- - limit is the total number of results to be returned in the result - page. - - If left empty it will default to a value to be set by each app. - count_total: - type: boolean - description: >- - count_total is set to true to indicate that the result set should - include - - a count of the total number of items available for pagination in UIs. - - count_total is only respected when offset is used. It is ignored when - key - - is set. - description: |- - message SomeRequest { - Foo some_parameter = 1; - PageRequest pagination = 2; - } - title: |- - PageRequest is to be embedded in gRPC request messages for efficient - pagination. Ex: - cosmos.base.query.v1beta1.PageResponse: - type: object - properties: - next_key: - type: string - format: byte - title: |- - next_key is the key to be passed to PageRequest.key to - query the next page most efficiently - total: - type: string - format: uint64 - title: |- - total is total number of results available if PageRequest.count_total - was set, its value is undefined otherwise - description: |- - 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; - } cosmos.base.v1beta1.Coin: type: object properties: @@ -30582,7 +32623,6 @@ definitions: type: string format: date-time last_block_id: - title: prev block info type: object properties: hash: @@ -30598,6 +32638,7 @@ definitions: type: string format: byte title: PartsetHeader + title: BlockID last_commit_hash: type: string format: byte @@ -30822,7 +32863,6 @@ definitions: type: string format: date-time last_block_id: - title: prev block info type: object properties: hash: @@ -30838,6 +32878,7 @@ definitions: type: string format: byte title: PartsetHeader + title: BlockID last_commit_hash: type: string format: byte @@ -31133,7 +33174,6 @@ definitions: type: string format: date-time last_block_id: - title: prev block info type: object properties: hash: @@ -31149,6 +33189,7 @@ definitions: type: string format: byte title: PartsetHeader + title: BlockID last_commit_hash: type: string format: byte @@ -31373,7 +33414,6 @@ definitions: type: string format: date-time last_block_id: - title: prev block info type: object properties: hash: @@ -31389,6 +33429,7 @@ definitions: type: string format: byte title: PartsetHeader + title: BlockID last_commit_hash: type: string format: byte @@ -32443,7 +34484,6 @@ definitions: type: string format: date-time last_block_id: - title: prev block info type: object properties: hash: @@ -32459,6 +34499,7 @@ definitions: type: string format: byte title: PartsetHeader + title: BlockID last_commit_hash: type: string format: byte @@ -32682,7 +34723,6 @@ definitions: type: string format: date-time last_block_id: - title: prev block info type: object properties: hash: @@ -32698,6 +34738,7 @@ definitions: type: string format: byte title: PartsetHeader + title: BlockID last_commit_hash: type: string format: byte @@ -33350,7 +35391,6 @@ definitions: type: string format: date-time last_block_id: - title: prev block info type: object properties: hash: @@ -33366,6 +35406,7 @@ definitions: type: string format: byte title: PartsetHeader + title: BlockID last_commit_hash: type: string format: byte @@ -33724,7 +35765,6 @@ definitions: type: string format: date-time last_block_id: - title: prev block info type: object properties: hash: @@ -33740,6 +35780,7 @@ definitions: type: string format: byte title: PartsetHeader + title: BlockID last_commit_hash: type: string format: byte @@ -33954,7 +35995,6 @@ definitions: type: string format: date-time last_block_id: - title: prev block info type: object properties: hash: @@ -33970,6 +36010,7 @@ definitions: type: string format: byte title: PartsetHeader + title: BlockID last_commit_hash: type: string format: byte @@ -34037,7 +36078,6 @@ definitions: type: string format: date-time last_block_id: - title: prev block info type: object properties: hash: @@ -34053,6 +36093,7 @@ definitions: type: string format: byte title: PartsetHeader + title: BlockID last_commit_hash: type: string format: byte @@ -34232,7 +36273,6 @@ definitions: type: string format: date-time last_block_id: - title: prev block info type: object properties: hash: @@ -34248,6 +36288,7 @@ definitions: type: string format: byte title: PartsetHeader + title: BlockID last_commit_hash: type: string format: byte @@ -34471,7 +36512,6 @@ definitions: type: string format: date-time last_block_id: - title: prev block info type: object properties: hash: @@ -34487,6 +36527,7 @@ definitions: type: string format: byte title: PartsetHeader + title: BlockID last_commit_hash: type: string format: byte @@ -35259,7 +37300,6 @@ definitions: type: object properties: evidence: - description: evidence returns the requested evidence. type: object properties: type_url: @@ -35320,6 +37360,104 @@ definitions: description: >- Must be a valid serialized protocol buffer of the above specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer message along + with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values in the + form + + of utility functions or additional generated methods of the Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := ptypes.MarshalAny(foo) + ... + foo := &pb.Foo{} + if err := ptypes.UnmarshalAny(any, foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by default use + + 'type.googleapis.com/full.type.name' as the type URL and the unpack + + methods only use the fully qualified type name after the last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with an + + additional field `@type` which contains the type URL. Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom JSON + + representation, that representation will be embedded adding a field + + `value` which holds the custom JSON in addition to the `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } description: >- QueryEvidenceResponse is the response type for the Query/Evidence RPC method. @@ -35629,7 +37767,6 @@ definitions: type: object properties: deposit: - description: deposit defines the requested deposit. type: object properties: proposal_id: @@ -35654,6 +37791,9 @@ definitions: method signatures required by gogoproto. + description: |- + Deposit defines an amount deposited by an account address to an active + proposal. description: >- QueryDepositResponse is the response type for the Query/Deposit RPC method. @@ -36290,7 +38430,6 @@ definitions: type: object properties: tally: - description: tally defines the requested tally. type: object properties: 'yes': @@ -36301,6 +38440,7 @@ definitions: type: string no_with_veto: type: string + description: TallyResult defines a standard tally for a governance proposal. description: >- QueryTallyResultResponse is the response type for the Query/Tally RPC method. @@ -36308,7 +38448,6 @@ definitions: type: object properties: vote: - description: vote defined the queried vote. type: object properties: proposal_id: @@ -36316,24 +38455,35 @@ definitions: format: uint64 voter: type: string - option: - type: string - enum: - - VOTE_OPTION_UNSPECIFIED - - VOTE_OPTION_YES - - VOTE_OPTION_ABSTAIN - - VOTE_OPTION_NO - - VOTE_OPTION_NO_WITH_VETO - default: VOTE_OPTION_UNSPECIFIED - description: >- - VoteOption enumerates the valid vote options for a given - governance proposal. - - - VOTE_OPTION_UNSPECIFIED: VOTE_OPTION_UNSPECIFIED defines a no-op vote option. - - VOTE_OPTION_YES: VOTE_OPTION_YES defines a yes vote option. - - VOTE_OPTION_ABSTAIN: VOTE_OPTION_ABSTAIN defines an abstain vote option. - - VOTE_OPTION_NO: VOTE_OPTION_NO defines a no vote option. - - VOTE_OPTION_NO_WITH_VETO: VOTE_OPTION_NO_WITH_VETO defines a no with veto vote option. + options: + type: array + items: + type: object + properties: + option: + type: string + enum: + - VOTE_OPTION_UNSPECIFIED + - VOTE_OPTION_YES + - VOTE_OPTION_ABSTAIN + - VOTE_OPTION_NO + - VOTE_OPTION_NO_WITH_VETO + default: VOTE_OPTION_UNSPECIFIED + description: >- + VoteOption enumerates the valid vote options for a given + governance proposal. + + - VOTE_OPTION_UNSPECIFIED: VOTE_OPTION_UNSPECIFIED defines a no-op vote option. + - VOTE_OPTION_YES: VOTE_OPTION_YES defines a yes vote option. + - VOTE_OPTION_ABSTAIN: VOTE_OPTION_ABSTAIN defines an abstain vote option. + - VOTE_OPTION_NO: VOTE_OPTION_NO defines a no vote option. + - VOTE_OPTION_NO_WITH_VETO: VOTE_OPTION_NO_WITH_VETO defines a no with veto vote option. + weight: + type: string + description: WeightedVoteOption defines a unit of vote for vote split. + description: |- + Vote defines a vote on a governance proposal. + A Vote consists of a proposal ID, the voter, and the vote option. description: QueryVoteResponse is the response type for the Query/Vote RPC method. cosmos.gov.v1beta1.QueryVotesResponse: type: object @@ -36348,24 +38498,32 @@ definitions: format: uint64 voter: type: string - option: - type: string - enum: - - VOTE_OPTION_UNSPECIFIED - - VOTE_OPTION_YES - - VOTE_OPTION_ABSTAIN - - VOTE_OPTION_NO - - VOTE_OPTION_NO_WITH_VETO - default: VOTE_OPTION_UNSPECIFIED - description: >- - VoteOption enumerates the valid vote options for a given - governance proposal. + options: + type: array + items: + type: object + properties: + option: + type: string + enum: + - VOTE_OPTION_UNSPECIFIED + - VOTE_OPTION_YES + - VOTE_OPTION_ABSTAIN + - VOTE_OPTION_NO + - VOTE_OPTION_NO_WITH_VETO + default: VOTE_OPTION_UNSPECIFIED + description: >- + VoteOption enumerates the valid vote options for a given + governance proposal. - - VOTE_OPTION_UNSPECIFIED: VOTE_OPTION_UNSPECIFIED defines a no-op vote option. - - VOTE_OPTION_YES: VOTE_OPTION_YES defines a yes vote option. - - VOTE_OPTION_ABSTAIN: VOTE_OPTION_ABSTAIN defines an abstain vote option. - - VOTE_OPTION_NO: VOTE_OPTION_NO defines a no vote option. - - VOTE_OPTION_NO_WITH_VETO: VOTE_OPTION_NO_WITH_VETO defines a no with veto vote option. + - VOTE_OPTION_UNSPECIFIED: VOTE_OPTION_UNSPECIFIED defines a no-op vote option. + - VOTE_OPTION_YES: VOTE_OPTION_YES defines a yes vote option. + - VOTE_OPTION_ABSTAIN: VOTE_OPTION_ABSTAIN defines an abstain vote option. + - VOTE_OPTION_NO: VOTE_OPTION_NO defines a no vote option. + - VOTE_OPTION_NO_WITH_VETO: VOTE_OPTION_NO_WITH_VETO defines a no with veto vote option. + weight: + type: string + description: WeightedVoteOption defines a unit of vote for vote split. description: |- Vote defines a vote on a governance proposal. A Vote consists of a proposal ID, the voter, and the vote option. @@ -36431,24 +38589,32 @@ definitions: format: uint64 voter: type: string - option: - type: string - enum: - - VOTE_OPTION_UNSPECIFIED - - VOTE_OPTION_YES - - VOTE_OPTION_ABSTAIN - - VOTE_OPTION_NO - - VOTE_OPTION_NO_WITH_VETO - default: VOTE_OPTION_UNSPECIFIED - description: >- - VoteOption enumerates the valid vote options for a given governance - proposal. + options: + type: array + items: + type: object + properties: + option: + type: string + enum: + - VOTE_OPTION_UNSPECIFIED + - VOTE_OPTION_YES + - VOTE_OPTION_ABSTAIN + - VOTE_OPTION_NO + - VOTE_OPTION_NO_WITH_VETO + default: VOTE_OPTION_UNSPECIFIED + description: >- + VoteOption enumerates the valid vote options for a given + governance proposal. - - VOTE_OPTION_UNSPECIFIED: VOTE_OPTION_UNSPECIFIED defines a no-op vote option. - - VOTE_OPTION_YES: VOTE_OPTION_YES defines a yes vote option. - - VOTE_OPTION_ABSTAIN: VOTE_OPTION_ABSTAIN defines an abstain vote option. - - VOTE_OPTION_NO: VOTE_OPTION_NO defines a no vote option. - - VOTE_OPTION_NO_WITH_VETO: VOTE_OPTION_NO_WITH_VETO defines a no with veto vote option. + - VOTE_OPTION_UNSPECIFIED: VOTE_OPTION_UNSPECIFIED defines a no-op vote option. + - VOTE_OPTION_YES: VOTE_OPTION_YES defines a yes vote option. + - VOTE_OPTION_ABSTAIN: VOTE_OPTION_ABSTAIN defines an abstain vote option. + - VOTE_OPTION_NO: VOTE_OPTION_NO defines a no vote option. + - VOTE_OPTION_NO_WITH_VETO: VOTE_OPTION_NO_WITH_VETO defines a no with veto vote option. + weight: + type: string + description: WeightedVoteOption defines a unit of vote for vote split. description: |- Vote defines a vote on a governance proposal. A Vote consists of a proposal ID, the voter, and the vote option. @@ -36477,6 +38643,30 @@ definitions: type: string description: Length of the voting period. description: VotingParams defines the params for voting on governance proposals. + cosmos.gov.v1beta1.WeightedVoteOption: + type: object + properties: + option: + type: string + enum: + - VOTE_OPTION_UNSPECIFIED + - VOTE_OPTION_YES + - VOTE_OPTION_ABSTAIN + - VOTE_OPTION_NO + - VOTE_OPTION_NO_WITH_VETO + default: VOTE_OPTION_UNSPECIFIED + description: >- + VoteOption enumerates the valid vote options for a given governance + proposal. + + - VOTE_OPTION_UNSPECIFIED: VOTE_OPTION_UNSPECIFIED defines a no-op vote option. + - VOTE_OPTION_YES: VOTE_OPTION_YES defines a yes vote option. + - VOTE_OPTION_ABSTAIN: VOTE_OPTION_ABSTAIN defines an abstain vote option. + - VOTE_OPTION_NO: VOTE_OPTION_NO defines a no vote option. + - VOTE_OPTION_NO_WITH_VETO: VOTE_OPTION_NO_WITH_VETO defines a no with veto vote option. + weight: + type: string + description: WeightedVoteOption defines a unit of vote for vote split. cosmos.mint.v1beta1.Params: type: object properties: @@ -36617,7 +38807,6 @@ definitions: type: object properties: val_signing_info: - title: val_signing_info is the signing info of requested val cons address type: object properties: address: @@ -36625,31 +38814,46 @@ definitions: start_height: type: string format: int64 - title: height at which validator was first a candidate OR was unjailed + title: Height at which validator was first a candidate OR was unjailed index_offset: type: string format: int64 - title: index offset into signed block bit array + description: >- + 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: type: string format: date-time - title: timestamp validator cannot be unjailed until + description: >- + Timestamp until which the validator is jailed due to liveness + downtime. tombstoned: type: boolean - title: >- - whether or not a validator has been tombstoned (killed out of - validator + description: >- + Whether or not a validator has been tombstoned (killed out of + validator set). It is set - set) + once the validator commits an equivocation or for any other + configured misbehiavor. missed_blocks_counter: type: string format: int64 - title: missed blocks counter (to avoid scanning the array every time) + description: >- + A counter kept to avoid unnecessary array reads. + + Note that `Sum(MissedBlocksBitArray)` always equals + `MissedBlocksCounter`. description: >- ValidatorSigningInfo defines a validator's signing info for monitoring their liveness activity. + title: val_signing_info is the signing info of requested val cons address title: >- QuerySigningInfoResponse is the response type for the Query/SigningInfo RPC @@ -36668,26 +38872,40 @@ definitions: start_height: type: string format: int64 - title: height at which validator was first a candidate OR was unjailed + title: Height at which validator was first a candidate OR was unjailed index_offset: type: string format: int64 - title: index offset into signed block bit array + description: >- + 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: type: string format: date-time - title: timestamp validator cannot be unjailed until + description: >- + Timestamp until which the validator is jailed due to liveness + downtime. tombstoned: type: boolean - title: >- - whether or not a validator has been tombstoned (killed out of - validator + description: >- + Whether or not a validator has been tombstoned (killed out of + validator set). It is set - set) + once the validator commits an equivocation or for any other + configured misbehiavor. missed_blocks_counter: type: string format: int64 - title: missed blocks counter (to avoid scanning the array every time) + description: >- + A counter kept to avoid unnecessary array reads. + + Note that `Sum(MissedBlocksBitArray)` always equals + `MissedBlocksCounter`. description: >- ValidatorSigningInfo defines a validator's signing info for monitoring their @@ -36732,26 +38950,40 @@ definitions: start_height: type: string format: int64 - title: height at which validator was first a candidate OR was unjailed + title: Height at which validator was first a candidate OR was unjailed index_offset: type: string format: int64 - title: index offset into signed block bit array + description: >- + 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: type: string format: date-time - title: timestamp validator cannot be unjailed until + description: >- + Timestamp until which the validator is jailed due to liveness + downtime. tombstoned: type: boolean - title: >- - whether or not a validator has been tombstoned (killed out of - validator + description: >- + Whether or not a validator has been tombstoned (killed out of + validator set). It is set - set) + once the validator commits an equivocation or for any other configured + misbehiavor. missed_blocks_counter: type: string format: int64 - title: missed blocks counter (to avoid scanning the array every time) + description: >- + A counter kept to avoid unnecessary array reads. + + Note that `Sum(MissedBlocksBitArray)` always equals + `MissedBlocksCounter`. description: >- ValidatorSigningInfo defines a validator's signing info for monitoring their @@ -36776,32 +39008,45 @@ definitions: type: object properties: commission_rates: + description: >- + commission_rates defines the initial commission rates to be used for + creating a validator. type: object properties: rate: type: string + description: 'rate is the commission rate charged to delegators, as a fraction.' max_rate: type: string + description: >- + max_rate defines the maximum commission rate which validator can + ever charge, as a fraction. max_change_rate: type: string - description: >- - CommissionRates defines the initial commission rates to be used for - creating - - a validator. + description: >- + max_change_rate defines the maximum daily increase of the + validator commission, as a fraction. update_time: type: string format: date-time + description: update_time is the last time the commission rate was changed. description: Commission defines commission parameters for a given validator. cosmos.staking.v1beta1.CommissionRates: type: object properties: rate: type: string + description: 'rate is the commission rate charged to delegators, as a fraction.' max_rate: type: string + description: >- + max_rate defines the maximum commission rate which validator can ever + charge, as a fraction. max_change_rate: type: string + description: >- + max_change_rate defines the maximum daily increase of the validator + commission, as a fraction. description: >- CommissionRates defines the initial commission rates to be used for creating @@ -36812,10 +39057,13 @@ definitions: properties: delegator_address: type: string + description: delegator_address is the bech32-encoded address of the delegator. validator_address: type: string + description: validator_address is the bech32-encoded address of the validator. shares: type: string + description: shares define the delegation shares received. description: |- 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 @@ -36828,10 +39076,13 @@ definitions: properties: delegator_address: type: string + description: delegator_address is the bech32-encoded address of the delegator. validator_address: type: string + description: validator_address is the bech32-encoded address of the validator. shares: type: string + description: shares define the delegation shares received. description: |- 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 @@ -36856,14 +39107,21 @@ definitions: properties: moniker: type: string + description: moniker defines a human-readable name for the validator. identity: type: string + description: >- + identity defines an optional identity signature (ex. UPort or + Keybase). website: type: string + description: website defines an optional website link. security_contact: type: string + description: security_contact defines an optional email for security contact. details: type: string + description: details define other optional details. description: Description defines a validator description. cosmos.staking.v1beta1.HistoricalInfo: type: object @@ -36952,6 +39210,9 @@ definitions: properties: operator_address: type: string + description: >- + operator_address defines the address of the validator's + operator; bech encoded in JSON. consensus_pubkey: type: object properties: @@ -37123,7 +39384,11 @@ definitions: } jailed: type: boolean + description: >- + jailed defined whether the validator has been jailed from bonded + status or not. status: + description: status is the validator status (bonded/unbonding/unbonded). type: string enum: - BOND_STATUS_UNSPECIFIED @@ -37131,60 +39396,85 @@ definitions: - BOND_STATUS_UNBONDING - BOND_STATUS_BONDED default: BOND_STATUS_UNSPECIFIED - description: |- - BondStatus is the status of a validator. - - - BOND_STATUS_UNSPECIFIED: UNSPECIFIED defines an invalid validator status. - - BOND_STATUS_UNBONDED: UNBONDED defines a validator that is not bonded. - - BOND_STATUS_UNBONDING: UNBONDING defines a validator that is unbonding. - - BOND_STATUS_BONDED: BONDED defines a validator that is bonded. tokens: type: string + description: tokens define the delegated tokens (incl. self-delegation). delegator_shares: type: string + description: >- + delegator_shares defines total shares issued to a validator's + delegators. description: + description: description defines the description terms for the validator. type: object properties: moniker: type: string + description: moniker defines a human-readable name for the validator. identity: type: string + description: >- + identity defines an optional identity signature (ex. UPort + or Keybase). website: type: string + description: website defines an optional website link. security_contact: type: string + description: >- + security_contact defines an optional email for security + contact. details: type: string - description: Description defines a validator description. + description: details define other optional details. unbonding_height: type: string format: int64 + description: >- + unbonding_height defines, if unbonding, the height at which this + validator has begun unbonding. unbonding_time: type: string format: date-time + description: >- + unbonding_time defines, if unbonding, the min time for the + validator to complete unbonding. commission: + description: commission defines the commission parameters. type: object properties: commission_rates: + description: >- + commission_rates defines the initial commission rates to be + used for creating a validator. type: object properties: rate: type: string + description: >- + rate is the commission rate charged to delegators, as a + fraction. max_rate: type: string + description: >- + max_rate defines the maximum commission rate which + validator can ever charge, as a fraction. max_change_rate: type: string - description: >- - CommissionRates defines the initial commission rates to be - used for creating - - a validator. + description: >- + max_change_rate defines the maximum daily increase of + the validator commission, as a fraction. update_time: type: string format: date-time - description: Commission defines commission parameters for a given validator. + description: >- + update_time is the last time the commission rate was + changed. min_self_delegation: type: string + description: >- + min_self_delegation is the validator's self declared minimum + self delegation. description: >- Validator defines a validator, together with the total amount of the @@ -37221,17 +39511,24 @@ definitions: properties: unbonding_time: type: string + description: unbonding_time is the time duration of unbonding. max_validators: type: integer format: int64 + description: max_validators is the maximum number of validators. max_entries: type: integer format: int64 + description: >- + max_entries is the max entries for either unbonding delegation or + redelegation (per pair/trio). historical_entries: type: integer format: int64 + description: historical_entries is the number of historical entries to persist. bond_denom: type: string + description: bond_denom defines the bondable coin denomination. description: Params defines the parameters for the staking module. cosmos.staking.v1beta1.Pool: type: object @@ -37247,7 +39544,6 @@ definitions: type: object properties: delegation_response: - description: delegation_responses defines the delegation info of a delegation. type: object properties: delegation: @@ -37255,10 +39551,17 @@ definitions: properties: delegator_address: type: string + description: >- + delegator_address is the bech32-encoded address of the + delegator. validator_address: type: string + description: >- + validator_address is the bech32-encoded address of the + validator. shares: type: string + description: shares define the delegation shares received. description: >- Delegation represents the bond with tokens held by an account. It is @@ -37282,6 +39585,12 @@ definitions: method signatures required by gogoproto. + description: >- + DelegationResponse is equivalent to Delegation except that it contains + a + + balance in addition to shares which is more suitable for client + responses. description: >- QueryDelegationResponse is response type for the Query/Delegation RPC method. @@ -37298,10 +39607,17 @@ definitions: properties: delegator_address: type: string + description: >- + delegator_address is the bech32-encoded address of the + delegator. validator_address: type: string + description: >- + validator_address is the bech32-encoded address of the + validator. shares: type: string + description: shares define the delegation shares received. description: >- Delegation represents the bond with tokens held by an account. It is @@ -37363,8 +39679,14 @@ definitions: properties: delegator_address: type: string + description: >- + delegator_address is the bech32-encoded address of the + delegator. validator_address: type: string + description: >- + validator_address is the bech32-encoded address of the + validator. entries: type: array items: @@ -37373,16 +39695,25 @@ definitions: creation_height: type: string format: int64 + description: >- + creation_height is the height which the unbonding took + place. completion_time: type: string format: date-time + description: completion_time is the unix time for unbonding completion. initial_balance: type: string + description: >- + initial_balance defines the tokens initially scheduled to + receive at completion. balance: type: string + description: balance defines the tokens to receive at completion. description: >- UnbondingDelegationEntry defines an unbonding object with relevant metadata. + description: entries are the unbonding delegation entries. description: >- UnbondingDelegation stores all of a single delegator's unbonding bonds @@ -37413,11 +39744,13 @@ definitions: type: object properties: validator: - description: validator defines the the validator info. type: object properties: operator_address: type: string + description: >- + operator_address defines the address of the validator's operator; + bech encoded in JSON. consensus_pubkey: type: object properties: @@ -37585,7 +39918,11 @@ definitions: } jailed: type: boolean + description: >- + jailed defined whether the validator has been jailed from bonded + status or not. status: + description: status is the validator status (bonded/unbonding/unbonded). type: string enum: - BOND_STATUS_UNSPECIFIED @@ -37593,60 +39930,104 @@ definitions: - BOND_STATUS_UNBONDING - BOND_STATUS_BONDED default: BOND_STATUS_UNSPECIFIED - description: |- - BondStatus is the status of a validator. - - - BOND_STATUS_UNSPECIFIED: UNSPECIFIED defines an invalid validator status. - - BOND_STATUS_UNBONDED: UNBONDED defines a validator that is not bonded. - - BOND_STATUS_UNBONDING: UNBONDING defines a validator that is unbonding. - - BOND_STATUS_BONDED: BONDED defines a validator that is bonded. tokens: type: string + description: tokens define the delegated tokens (incl. self-delegation). delegator_shares: type: string + description: >- + delegator_shares defines total shares issued to a validator's + delegators. description: + description: description defines the description terms for the validator. type: object properties: moniker: type: string + description: moniker defines a human-readable name for the validator. identity: type: string + description: >- + identity defines an optional identity signature (ex. UPort or + Keybase). website: type: string + description: website defines an optional website link. security_contact: type: string + description: >- + security_contact defines an optional email for security + contact. details: type: string - description: Description defines a validator description. + description: details define other optional details. unbonding_height: type: string format: int64 + description: >- + unbonding_height defines, if unbonding, the height at which this + validator has begun unbonding. unbonding_time: type: string format: date-time + description: >- + unbonding_time defines, if unbonding, the min time for the + validator to complete unbonding. commission: + description: commission defines the commission parameters. type: object properties: commission_rates: + description: >- + commission_rates defines the initial commission rates to be + used for creating a validator. type: object properties: rate: type: string + description: >- + rate is the commission rate charged to delegators, as a + fraction. max_rate: type: string + description: >- + max_rate defines the maximum commission rate which + validator can ever charge, as a fraction. max_change_rate: type: string - description: >- - CommissionRates defines the initial commission rates to be - used for creating - - a validator. + description: >- + max_change_rate defines the maximum daily increase of the + validator commission, as a fraction. update_time: type: string format: date-time - description: Commission defines commission parameters for a given validator. + description: update_time is the last time the commission rate was changed. min_self_delegation: type: string + description: >- + min_self_delegation is the validator's self declared minimum self + delegation. + description: >- + 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. description: |- QueryDelegatorValidatorResponse response type for the Query/DelegatorValidator RPC method. @@ -37660,6 +40041,9 @@ definitions: properties: operator_address: type: string + description: >- + operator_address defines the address of the validator's + operator; bech encoded in JSON. consensus_pubkey: type: object properties: @@ -37831,7 +40215,11 @@ definitions: } jailed: type: boolean + description: >- + jailed defined whether the validator has been jailed from bonded + status or not. status: + description: status is the validator status (bonded/unbonding/unbonded). type: string enum: - BOND_STATUS_UNSPECIFIED @@ -37839,60 +40227,85 @@ definitions: - BOND_STATUS_UNBONDING - BOND_STATUS_BONDED default: BOND_STATUS_UNSPECIFIED - description: |- - BondStatus is the status of a validator. - - - BOND_STATUS_UNSPECIFIED: UNSPECIFIED defines an invalid validator status. - - BOND_STATUS_UNBONDED: UNBONDED defines a validator that is not bonded. - - BOND_STATUS_UNBONDING: UNBONDING defines a validator that is unbonding. - - BOND_STATUS_BONDED: BONDED defines a validator that is bonded. tokens: type: string + description: tokens define the delegated tokens (incl. self-delegation). delegator_shares: type: string + description: >- + delegator_shares defines total shares issued to a validator's + delegators. description: + description: description defines the description terms for the validator. type: object properties: moniker: type: string + description: moniker defines a human-readable name for the validator. identity: type: string + description: >- + identity defines an optional identity signature (ex. UPort + or Keybase). website: type: string + description: website defines an optional website link. security_contact: type: string + description: >- + security_contact defines an optional email for security + contact. details: type: string - description: Description defines a validator description. + description: details define other optional details. unbonding_height: type: string format: int64 + description: >- + unbonding_height defines, if unbonding, the height at which this + validator has begun unbonding. unbonding_time: type: string format: date-time + description: >- + unbonding_time defines, if unbonding, the min time for the + validator to complete unbonding. commission: + description: commission defines the commission parameters. type: object properties: commission_rates: + description: >- + commission_rates defines the initial commission rates to be + used for creating a validator. type: object properties: rate: type: string + description: >- + rate is the commission rate charged to delegators, as a + fraction. max_rate: type: string + description: >- + max_rate defines the maximum commission rate which + validator can ever charge, as a fraction. max_change_rate: type: string - description: >- - CommissionRates defines the initial commission rates to be - used for creating - - a validator. + description: >- + max_change_rate defines the maximum daily increase of + the validator commission, as a fraction. update_time: type: string format: date-time - description: Commission defines commission parameters for a given validator. + description: >- + update_time is the last time the commission rate was + changed. min_self_delegation: type: string + description: >- + min_self_delegation is the validator's self declared minimum + self delegation. description: >- Validator defines a validator, together with the total amount of the @@ -38027,6 +40440,9 @@ definitions: properties: operator_address: type: string + description: >- + operator_address defines the address of the validator's + operator; bech encoded in JSON. consensus_pubkey: type: object properties: @@ -38204,7 +40620,11 @@ definitions: } jailed: type: boolean + description: >- + jailed defined whether the validator has been jailed from + bonded status or not. status: + description: status is the validator status (bonded/unbonding/unbonded). type: string enum: - BOND_STATUS_UNSPECIFIED @@ -38212,62 +40632,85 @@ definitions: - BOND_STATUS_UNBONDING - BOND_STATUS_BONDED default: BOND_STATUS_UNSPECIFIED - description: |- - BondStatus is the status of a validator. - - - BOND_STATUS_UNSPECIFIED: UNSPECIFIED defines an invalid validator status. - - BOND_STATUS_UNBONDED: UNBONDED defines a validator that is not bonded. - - BOND_STATUS_UNBONDING: UNBONDING defines a validator that is unbonding. - - BOND_STATUS_BONDED: BONDED defines a validator that is bonded. tokens: type: string + description: tokens define the delegated tokens (incl. self-delegation). delegator_shares: type: string + description: >- + delegator_shares defines total shares issued to a + validator's delegators. description: + description: description defines the description terms for the validator. type: object properties: moniker: type: string + description: moniker defines a human-readable name for the validator. identity: type: string + description: >- + identity defines an optional identity signature (ex. + UPort or Keybase). website: type: string + description: website defines an optional website link. security_contact: type: string + description: >- + security_contact defines an optional email for security + contact. details: type: string - description: Description defines a validator description. + description: details define other optional details. unbonding_height: type: string format: int64 + description: >- + unbonding_height defines, if unbonding, the height at which + this validator has begun unbonding. unbonding_time: type: string format: date-time + description: >- + unbonding_time defines, if unbonding, the min time for the + validator to complete unbonding. commission: + description: commission defines the commission parameters. type: object properties: commission_rates: + description: >- + commission_rates defines the initial commission rates to + be used for creating a validator. type: object properties: rate: type: string + description: >- + rate is the commission rate charged to delegators, + as a fraction. max_rate: type: string + description: >- + max_rate defines the maximum commission rate which + validator can ever charge, as a fraction. max_change_rate: type: string - description: >- - CommissionRates defines the initial commission rates to - be used for creating - - a validator. + description: >- + max_change_rate defines the maximum daily increase + of the validator commission, as a fraction. update_time: type: string format: date-time - description: >- - Commission defines commission parameters for a given - validator. + description: >- + update_time is the last time the commission rate was + changed. min_self_delegation: type: string + description: >- + min_self_delegation is the validator's self declared minimum + self delegation. description: >- Validator defines a validator, together with the total amount of the @@ -38305,17 +40748,24 @@ definitions: properties: unbonding_time: type: string + description: unbonding_time is the time duration of unbonding. max_validators: type: integer format: int64 + description: max_validators is the maximum number of validators. max_entries: type: integer format: int64 + description: >- + max_entries is the max entries for either unbonding delegation or + redelegation (per pair/trio). historical_entries: type: integer format: int64 + description: historical_entries is the number of historical entries to persist. bond_denom: type: string + description: bond_denom defines the bondable coin denomination. description: QueryParamsResponse is response type for the Query/Params RPC method. cosmos.staking.v1beta1.QueryPoolResponse: type: object @@ -38342,10 +40792,19 @@ definitions: properties: delegator_address: type: string + description: >- + delegator_address is the bech32-encoded address of the + delegator. validator_src_address: type: string + description: >- + validator_src_address is the validator redelegation source + operator address. validator_dst_address: type: string + description: >- + validator_dst_address is the validator redelegation + destination operator address. entries: type: array items: @@ -38354,16 +40813,29 @@ definitions: creation_height: type: string format: int64 + description: >- + creation_height defines the height which the + redelegation took place. completion_time: type: string format: date-time + description: >- + completion_time defines the unix time for redelegation + completion. initial_balance: type: string + description: >- + initial_balance defines the initial balance when + redelegation started. shares_dst: type: string + description: >- + shares_dst is the amount of destination-validator + shares created by redelegation. description: >- RedelegationEntry defines a redelegation object with relevant metadata. + description: entries are the redelegation entries. description: >- Redelegation contains the list of a particular delegator's redelegating bonds @@ -38381,13 +40853,25 @@ definitions: creation_height: type: string format: int64 + description: >- + creation_height defines the height which the + redelegation took place. completion_time: type: string format: date-time + description: >- + completion_time defines the unix time for redelegation + completion. initial_balance: type: string + description: >- + initial_balance defines the initial balance when + redelegation started. shares_dst: type: string + description: >- + shares_dst is the amount of destination-validator + shares created by redelegation. description: >- RedelegationEntry defines a redelegation object with relevant metadata. @@ -38436,13 +40920,14 @@ definitions: type: object properties: unbond: - description: unbond defines the unbonding information of a delegation. type: object properties: delegator_address: type: string + description: delegator_address is the bech32-encoded address of the delegator. validator_address: type: string + description: validator_address is the bech32-encoded address of the validator. entries: type: array items: @@ -38451,16 +40936,28 @@ definitions: creation_height: type: string format: int64 + description: >- + creation_height is the height which the unbonding took + place. completion_time: type: string format: date-time + description: completion_time is the unix time for unbonding completion. initial_balance: type: string + description: >- + initial_balance defines the tokens initially scheduled to + receive at completion. balance: type: string + description: balance defines the tokens to receive at completion. description: >- UnbondingDelegationEntry defines an unbonding object with relevant metadata. + description: entries are the unbonding delegation entries. + description: |- + UnbondingDelegation stores all of a single delegator's unbonding bonds + for a single validator in an time-ordered list. description: |- QueryDelegationResponse is response type for the Query/UnbondingDelegation RPC method. @@ -38477,10 +40974,17 @@ definitions: properties: delegator_address: type: string + description: >- + delegator_address is the bech32-encoded address of the + delegator. validator_address: type: string + description: >- + validator_address is the bech32-encoded address of the + validator. shares: type: string + description: shares define the delegation shares received. description: >- Delegation represents the bond with tokens held by an account. It is @@ -38535,11 +41039,13 @@ definitions: type: object properties: validator: - description: validator defines the the validator info. type: object properties: operator_address: type: string + description: >- + operator_address defines the address of the validator's operator; + bech encoded in JSON. consensus_pubkey: type: object properties: @@ -38707,7 +41213,11 @@ definitions: } jailed: type: boolean + description: >- + jailed defined whether the validator has been jailed from bonded + status or not. status: + description: status is the validator status (bonded/unbonding/unbonded). type: string enum: - BOND_STATUS_UNSPECIFIED @@ -38715,60 +41225,104 @@ definitions: - BOND_STATUS_UNBONDING - BOND_STATUS_BONDED default: BOND_STATUS_UNSPECIFIED - description: |- - BondStatus is the status of a validator. - - - BOND_STATUS_UNSPECIFIED: UNSPECIFIED defines an invalid validator status. - - BOND_STATUS_UNBONDED: UNBONDED defines a validator that is not bonded. - - BOND_STATUS_UNBONDING: UNBONDING defines a validator that is unbonding. - - BOND_STATUS_BONDED: BONDED defines a validator that is bonded. tokens: type: string + description: tokens define the delegated tokens (incl. self-delegation). delegator_shares: type: string + description: >- + delegator_shares defines total shares issued to a validator's + delegators. description: + description: description defines the description terms for the validator. type: object properties: moniker: type: string + description: moniker defines a human-readable name for the validator. identity: type: string + description: >- + identity defines an optional identity signature (ex. UPort or + Keybase). website: type: string + description: website defines an optional website link. security_contact: type: string + description: >- + security_contact defines an optional email for security + contact. details: type: string - description: Description defines a validator description. + description: details define other optional details. unbonding_height: type: string format: int64 + description: >- + unbonding_height defines, if unbonding, the height at which this + validator has begun unbonding. unbonding_time: type: string format: date-time + description: >- + unbonding_time defines, if unbonding, the min time for the + validator to complete unbonding. commission: + description: commission defines the commission parameters. type: object properties: commission_rates: + description: >- + commission_rates defines the initial commission rates to be + used for creating a validator. type: object properties: rate: type: string + description: >- + rate is the commission rate charged to delegators, as a + fraction. max_rate: type: string + description: >- + max_rate defines the maximum commission rate which + validator can ever charge, as a fraction. max_change_rate: type: string - description: >- - CommissionRates defines the initial commission rates to be - used for creating - - a validator. + description: >- + max_change_rate defines the maximum daily increase of the + validator commission, as a fraction. update_time: type: string format: date-time - description: Commission defines commission parameters for a given validator. + description: update_time is the last time the commission rate was changed. min_self_delegation: type: string + description: >- + min_self_delegation is the validator's self declared minimum self + delegation. + description: >- + 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. title: QueryValidatorResponse is response type for the Query/Validator RPC method cosmos.staking.v1beta1.QueryValidatorUnbondingDelegationsResponse: type: object @@ -38780,8 +41334,14 @@ definitions: properties: delegator_address: type: string + description: >- + delegator_address is the bech32-encoded address of the + delegator. validator_address: type: string + description: >- + validator_address is the bech32-encoded address of the + validator. entries: type: array items: @@ -38790,16 +41350,25 @@ definitions: creation_height: type: string format: int64 + description: >- + creation_height is the height which the unbonding took + place. completion_time: type: string format: date-time + description: completion_time is the unix time for unbonding completion. initial_balance: type: string + description: >- + initial_balance defines the tokens initially scheduled to + receive at completion. balance: type: string + description: balance defines the tokens to receive at completion. description: >- UnbondingDelegationEntry defines an unbonding object with relevant metadata. + description: entries are the unbonding delegation entries. description: >- UnbondingDelegation stores all of a single delegator's unbonding bonds @@ -38836,6 +41405,9 @@ definitions: properties: operator_address: type: string + description: >- + operator_address defines the address of the validator's + operator; bech encoded in JSON. consensus_pubkey: type: object properties: @@ -39007,7 +41579,11 @@ definitions: } jailed: type: boolean + description: >- + jailed defined whether the validator has been jailed from bonded + status or not. status: + description: status is the validator status (bonded/unbonding/unbonded). type: string enum: - BOND_STATUS_UNSPECIFIED @@ -39015,60 +41591,85 @@ definitions: - BOND_STATUS_UNBONDING - BOND_STATUS_BONDED default: BOND_STATUS_UNSPECIFIED - description: |- - BondStatus is the status of a validator. - - - BOND_STATUS_UNSPECIFIED: UNSPECIFIED defines an invalid validator status. - - BOND_STATUS_UNBONDED: UNBONDED defines a validator that is not bonded. - - BOND_STATUS_UNBONDING: UNBONDING defines a validator that is unbonding. - - BOND_STATUS_BONDED: BONDED defines a validator that is bonded. tokens: type: string + description: tokens define the delegated tokens (incl. self-delegation). delegator_shares: type: string + description: >- + delegator_shares defines total shares issued to a validator's + delegators. description: + description: description defines the description terms for the validator. type: object properties: moniker: type: string + description: moniker defines a human-readable name for the validator. identity: type: string + description: >- + identity defines an optional identity signature (ex. UPort + or Keybase). website: type: string + description: website defines an optional website link. security_contact: type: string + description: >- + security_contact defines an optional email for security + contact. details: type: string - description: Description defines a validator description. + description: details define other optional details. unbonding_height: type: string format: int64 + description: >- + unbonding_height defines, if unbonding, the height at which this + validator has begun unbonding. unbonding_time: type: string format: date-time + description: >- + unbonding_time defines, if unbonding, the min time for the + validator to complete unbonding. commission: + description: commission defines the commission parameters. type: object properties: commission_rates: + description: >- + commission_rates defines the initial commission rates to be + used for creating a validator. type: object properties: rate: type: string + description: >- + rate is the commission rate charged to delegators, as a + fraction. max_rate: type: string + description: >- + max_rate defines the maximum commission rate which + validator can ever charge, as a fraction. max_change_rate: type: string - description: >- - CommissionRates defines the initial commission rates to be - used for creating - - a validator. + description: >- + max_change_rate defines the maximum daily increase of + the validator commission, as a fraction. update_time: type: string format: date-time - description: Commission defines commission parameters for a given validator. + description: >- + update_time is the last time the commission rate was + changed. min_self_delegation: type: string + description: >- + min_self_delegation is the validator's self declared minimum + self delegation. description: >- Validator defines a validator, together with the total amount of the @@ -39117,10 +41718,17 @@ definitions: properties: delegator_address: type: string + description: delegator_address is the bech32-encoded address of the delegator. validator_src_address: type: string + description: >- + validator_src_address is the validator redelegation source operator + address. validator_dst_address: type: string + description: >- + validator_dst_address is the validator redelegation destination + operator address. entries: type: array items: @@ -39129,16 +41737,29 @@ definitions: creation_height: type: string format: int64 + description: >- + creation_height defines the height which the redelegation took + place. completion_time: type: string format: date-time + description: >- + completion_time defines the unix time for redelegation + completion. initial_balance: type: string + description: >- + initial_balance defines the initial balance when redelegation + started. shares_dst: type: string + description: >- + shares_dst is the amount of destination-validator shares created + by redelegation. description: >- RedelegationEntry defines a redelegation object with relevant metadata. + description: entries are the redelegation entries. description: >- Redelegation contains the list of a particular delegator's redelegating bonds @@ -39150,13 +41771,19 @@ definitions: creation_height: type: string format: int64 + description: creation_height defines the height which the redelegation took place. completion_time: type: string format: date-time + description: completion_time defines the unix time for redelegation completion. initial_balance: type: string + description: initial_balance defines the initial balance when redelegation started. shares_dst: type: string + description: >- + shares_dst is the amount of destination-validator shares created by + redelegation. description: RedelegationEntry defines a redelegation object with relevant metadata. cosmos.staking.v1beta1.RedelegationEntryResponse: type: object @@ -39167,13 +41794,23 @@ definitions: creation_height: type: string format: int64 + description: >- + creation_height defines the height which the redelegation took + place. completion_time: type: string format: date-time + description: completion_time defines the unix time for redelegation completion. initial_balance: type: string + description: >- + initial_balance defines the initial balance when redelegation + started. shares_dst: type: string + description: >- + shares_dst is the amount of destination-validator shares created + by redelegation. description: >- RedelegationEntry defines a redelegation object with relevant metadata. @@ -39194,10 +41831,17 @@ definitions: properties: delegator_address: type: string + description: delegator_address is the bech32-encoded address of the delegator. validator_src_address: type: string + description: >- + validator_src_address is the validator redelegation source + operator address. validator_dst_address: type: string + description: >- + validator_dst_address is the validator redelegation destination + operator address. entries: type: array items: @@ -39206,16 +41850,29 @@ definitions: creation_height: type: string format: int64 + description: >- + creation_height defines the height which the redelegation + took place. completion_time: type: string format: date-time + description: >- + completion_time defines the unix time for redelegation + completion. initial_balance: type: string + description: >- + initial_balance defines the initial balance when + redelegation started. shares_dst: type: string + description: >- + shares_dst is the amount of destination-validator shares + created by redelegation. description: >- RedelegationEntry defines a redelegation object with relevant metadata. + description: entries are the redelegation entries. description: >- Redelegation contains the list of a particular delegator's redelegating bonds @@ -39233,13 +41890,25 @@ definitions: creation_height: type: string format: int64 + description: >- + creation_height defines the height which the redelegation + took place. completion_time: type: string format: date-time + description: >- + completion_time defines the unix time for redelegation + completion. initial_balance: type: string + description: >- + initial_balance defines the initial balance when + redelegation started. shares_dst: type: string + description: >- + shares_dst is the amount of destination-validator shares + created by redelegation. description: >- RedelegationEntry defines a redelegation object with relevant metadata. @@ -39265,8 +41934,10 @@ definitions: properties: delegator_address: type: string + description: delegator_address is the bech32-encoded address of the delegator. validator_address: type: string + description: validator_address is the bech32-encoded address of the validator. entries: type: array items: @@ -39275,16 +41946,23 @@ definitions: creation_height: type: string format: int64 + description: creation_height is the height which the unbonding took place. completion_time: type: string format: date-time + description: completion_time is the unix time for unbonding completion. initial_balance: type: string + description: >- + initial_balance defines the tokens initially scheduled to + receive at completion. balance: type: string + description: balance defines the tokens to receive at completion. description: >- UnbondingDelegationEntry defines an unbonding object with relevant metadata. + description: entries are the unbonding delegation entries. description: |- UnbondingDelegation stores all of a single delegator's unbonding bonds for a single validator in an time-ordered list. @@ -39294,13 +41972,19 @@ definitions: creation_height: type: string format: int64 + description: creation_height is the height which the unbonding took place. completion_time: type: string format: date-time + description: completion_time is the unix time for unbonding completion. initial_balance: type: string + description: >- + initial_balance defines the tokens initially scheduled to receive at + completion. balance: type: string + description: balance defines the tokens to receive at completion. description: >- UnbondingDelegationEntry defines an unbonding object with relevant metadata. @@ -39309,6 +41993,9 @@ definitions: properties: operator_address: type: string + description: >- + operator_address defines the address of the validator's operator; bech + encoded in JSON. consensus_pubkey: type: object properties: @@ -39470,7 +42157,11 @@ definitions: } jailed: type: boolean + description: >- + jailed defined whether the validator has been jailed from bonded + status or not. status: + description: status is the validator status (bonded/unbonding/unbonded). type: string enum: - BOND_STATUS_UNSPECIFIED @@ -39478,60 +42169,81 @@ definitions: - BOND_STATUS_UNBONDING - BOND_STATUS_BONDED default: BOND_STATUS_UNSPECIFIED - description: |- - BondStatus is the status of a validator. - - - BOND_STATUS_UNSPECIFIED: UNSPECIFIED defines an invalid validator status. - - BOND_STATUS_UNBONDED: UNBONDED defines a validator that is not bonded. - - BOND_STATUS_UNBONDING: UNBONDING defines a validator that is unbonding. - - BOND_STATUS_BONDED: BONDED defines a validator that is bonded. tokens: type: string + description: tokens define the delegated tokens (incl. self-delegation). delegator_shares: type: string + description: >- + delegator_shares defines total shares issued to a validator's + delegators. description: + description: description defines the description terms for the validator. type: object properties: moniker: type: string + description: moniker defines a human-readable name for the validator. identity: type: string + description: >- + identity defines an optional identity signature (ex. UPort or + Keybase). website: type: string + description: website defines an optional website link. security_contact: type: string + description: security_contact defines an optional email for security contact. details: type: string - description: Description defines a validator description. + description: details define other optional details. unbonding_height: type: string format: int64 + description: >- + unbonding_height defines, if unbonding, the height at which this + validator has begun unbonding. unbonding_time: type: string format: date-time + description: >- + unbonding_time defines, if unbonding, the min time for the validator + to complete unbonding. commission: + description: commission defines the commission parameters. type: object properties: commission_rates: + description: >- + commission_rates defines the initial commission rates to be used + for creating a validator. type: object properties: rate: type: string + description: >- + rate is the commission rate charged to delegators, as a + fraction. max_rate: type: string + description: >- + max_rate defines the maximum commission rate which validator + can ever charge, as a fraction. max_change_rate: type: string - description: >- - CommissionRates defines the initial commission rates to be used - for creating - - a validator. + description: >- + max_change_rate defines the maximum daily increase of the + validator commission, as a fraction. update_time: type: string format: date-time - description: Commission defines commission parameters for a given validator. + description: update_time is the last time the commission rate was changed. min_self_delegation: type: string + description: >- + min_self_delegation is the validator's self declared minimum self + delegation. description: >- Validator defines a validator, together with the total amount of the @@ -39768,7 +42480,6 @@ definitions: format: int64 description: Amount of gas consumed by transaction. tx: - description: The request transaction bytes. type: object properties: type_url: @@ -39829,6 +42540,104 @@ definitions: description: >- Must be a valid serialized protocol buffer of the above specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer message along + with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values in the + form + + of utility functions or additional generated methods of the Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := ptypes.MarshalAny(foo) + ... + foo := &pb.Foo{} + if err := ptypes.UnmarshalAny(any, foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by default use + + 'type.googleapis.com/full.type.name' as the type URL and the unpack + + methods only use the fully qualified type name after the last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with an + + additional field `@type` which contains the type URL. Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom JSON + + representation, that representation will be embedded adding a field + + `value` which holds the custom JSON in addition to the `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } timestamp: type: string description: >- @@ -40011,7 +42820,6 @@ definitions: type: object properties: tx_response: - description: tx_response is the queried TxResponses. type: object properties: height: @@ -40096,7 +42904,6 @@ definitions: format: int64 description: Amount of gas consumed by transaction. tx: - description: The request transaction bytes. type: object properties: type_url: @@ -40160,6 +42967,107 @@ definitions: description: >- Must be a valid serialized protocol buffer of the above specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer message + along with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values in the + form + + of utility functions or additional generated methods of the Any + type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := ptypes.MarshalAny(foo) + ... + foo := &pb.Foo{} + if err := ptypes.UnmarshalAny(any, foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by default use + + 'type.googleapis.com/full.type.name' as the type URL and the + unpack + + methods only use the fully qualified type name after the last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with an + + additional field `@type` which contains the type URL. Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom JSON + + representation, that representation will be embedded adding a + field + + `value` which holds the custom JSON in addition to the `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } timestamp: type: string description: >- @@ -40170,6 +43078,11 @@ definitions: height == 1, it's genesis time. + description: >- + TxResponse defines a structure containing relevant tx data and + metadata. The + + tags are stringified and the log is JSON decoded. description: |- BroadcastTxResponse is the response type for the Service.BroadcastTx method. @@ -40234,7 +43147,6 @@ definitions: $ref: '#/definitions/cosmos.tx.v1beta1.Tx' description: tx is the queried transaction. tx_response: - description: tx_response is the queried TxResponses. type: object properties: height: @@ -40319,7 +43231,6 @@ definitions: format: int64 description: Amount of gas consumed by transaction. tx: - description: The request transaction bytes. type: object properties: type_url: @@ -40383,6 +43294,107 @@ definitions: description: >- Must be a valid serialized protocol buffer of the above specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer message + along with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values in the + form + + of utility functions or additional generated methods of the Any + type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := ptypes.MarshalAny(foo) + ... + foo := &pb.Foo{} + if err := ptypes.UnmarshalAny(any, foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by default use + + 'type.googleapis.com/full.type.name' as the type URL and the + unpack + + methods only use the fully qualified type name after the last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with an + + additional field `@type` which contains the type URL. Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom JSON + + representation, that representation will be embedded adding a + field + + `value` which holds the custom JSON in addition to the `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } timestamp: type: string description: >- @@ -40393,6 +43405,11 @@ definitions: height == 1, it's genesis time. + description: >- + TxResponse defines a structure containing relevant tx data and + metadata. The + + tags are stringified and the log is JSON decoded. description: GetTxResponse is the response type for the Service.GetTx method. cosmos.tx.v1beta1.GetTxsEventResponse: type: object @@ -40489,7 +43506,6 @@ definitions: format: int64 description: Amount of gas consumed by transaction. tx: - description: The request transaction bytes. type: object properties: type_url: @@ -40555,6 +43571,109 @@ definitions: description: >- Must be a valid serialized protocol buffer of the above specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer message + along with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values in + the form + + of utility functions or additional generated methods of the Any + type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := ptypes.MarshalAny(foo) + ... + foo := &pb.Foo{} + if err := ptypes.UnmarshalAny(any, foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by default + use + + 'type.googleapis.com/full.type.name' as the type URL and the + unpack + + methods only use the fully qualified type name after the last + '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with an + + additional field `@type` which contains the type URL. Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom JSON + + representation, that representation will be embedded adding a + field + + `value` which holds the custom JSON in addition to the `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } timestamp: type: string description: >- @@ -40691,14 +43810,6 @@ definitions: type: object properties: public_key: - description: >- - 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. type: object properties: type_url: @@ -40759,6 +43870,104 @@ definitions: description: >- Must be a valid serialized protocol buffer of the above specified type. + description: >- + `Any` contains an arbitrary serialized protocol buffer message along + with a + + URL that describes the type of the serialized message. + + + Protobuf library provides support to pack/unpack Any values in the + form + + of utility functions or additional generated methods of the Any type. + + + Example 1: Pack and unpack a message in C++. + + Foo foo = ...; + Any any; + any.PackFrom(foo); + ... + if (any.UnpackTo(&foo)) { + ... + } + + Example 2: Pack and unpack a message in Java. + + Foo foo = ...; + Any any = Any.pack(foo); + ... + if (any.is(Foo.class)) { + foo = any.unpack(Foo.class); + } + + Example 3: Pack and unpack a message in Python. + + foo = Foo(...) + any = Any() + any.Pack(foo) + ... + if any.Is(Foo.DESCRIPTOR): + any.Unpack(foo) + ... + + Example 4: Pack and unpack a message in Go + + foo := &pb.Foo{...} + any, err := ptypes.MarshalAny(foo) + ... + foo := &pb.Foo{} + if err := ptypes.UnmarshalAny(any, foo); err != nil { + ... + } + + The pack methods provided by protobuf library will by default use + + 'type.googleapis.com/full.type.name' as the type URL and the unpack + + methods only use the fully qualified type name after the last '/' + + in the type URL, for example "foo.bar.com/x/y.z" will yield type + + name "y.z". + + + + JSON + + ==== + + The JSON representation of an `Any` value uses the regular + + representation of the deserialized, embedded message, with an + + additional field `@type` which contains the type URL. Example: + + package google.profile; + message Person { + string first_name = 1; + string last_name = 2; + } + + { + "@type": "type.googleapis.com/google.profile.Person", + "firstName": , + "lastName": + } + + If the embedded message type is well-known and has a custom JSON + + representation, that representation will be embedded adding a field + + `value` which holds the custom JSON in addition to the `@type` + + field. Example (for message [google.protobuf.Duration][]): + + { + "@type": "type.googleapis.com/google.protobuf.Duration", + "value": "1.212s" + } mode_info: $ref: '#/definitions/cosmos.tx.v1beta1.ModeInfo' title: |- @@ -41050,7 +44259,6 @@ definitions: the list only the first time it occurs. - By convention, the first required signer (usually from the first message) @@ -41622,7 +44830,6 @@ definitions: the list only the first time it occurs. - By convention, the first required signer (usually from the first message) @@ -42060,20 +45267,6 @@ definitions: Any application specific upgrade info to be included on-chain such as a git commit that validators could automatically upgrade to upgraded_client_state: - title: >- - 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 type: object properties: type_url: @@ -42232,6 +45425,20 @@ definitions: "@type": "type.googleapis.com/google.protobuf.Duration", "value": "1.212s" } + title: >- + 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 description: >- Plan specifies information about a planned upgrade and when it should occur. @@ -42296,20 +45503,6 @@ definitions: such as a git commit that validators could automatically upgrade to upgraded_client_state: - title: >- - 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 type: object properties: type_url: @@ -42474,6 +45667,20 @@ definitions: "@type": "type.googleapis.com/google.protobuf.Duration", "value": "1.212s" } + title: >- + 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 description: >- QueryCurrentPlanResponse is the response type for the Query/CurrentPlan RPC @@ -42835,7 +46042,6 @@ definitions: type: string title: client identifier client_state: - title: client state type: object properties: type_url: @@ -43000,6 +46206,7 @@ definitions: "@type": "type.googleapis.com/google.protobuf.Duration", "value": "1.212s" } + title: client state description: |- IdentifiedClientState defines a client state with an additional client identifier field. @@ -43039,7 +46246,6 @@ definitions: type: object properties: consensus_state: - title: consensus state associated with the channel type: object properties: type_url: @@ -43198,6 +46404,7 @@ definitions: "@type": "type.googleapis.com/google.protobuf.Duration", "value": "1.212s" } + title: consensus state associated with the channel client_id: type: string title: client ID associated with the consensus state @@ -44071,7 +47278,6 @@ definitions: type: string title: client identifier client_state: - title: client state type: object properties: type_url: @@ -44230,6 +47436,7 @@ definitions: "@type": "type.googleapis.com/google.protobuf.Duration", "value": "1.212s" } + title: client state description: |- IdentifiedClientState defines a client state with an additional client identifier field. @@ -44262,7 +47469,6 @@ definitions: be monitonically increasing even as the RevisionHeight gets reset consensus_state: - title: consensus state type: object properties: type_url: @@ -44421,6 +47627,7 @@ definitions: "@type": "type.googleapis.com/google.protobuf.Duration", "value": "1.212s" } + title: consensus state description: >- ConsensusStateWithHeight defines a consensus state with an additional height field. @@ -44452,7 +47659,6 @@ definitions: type: object properties: client_state: - title: client state associated with the request identifier type: object properties: type_url: @@ -44611,6 +47817,7 @@ definitions: "@type": "type.googleapis.com/google.protobuf.Duration", "value": "1.212s" } + title: client state associated with the request identifier proof: type: string format: byte @@ -44659,7 +47866,6 @@ definitions: type: string title: client identifier client_state: - title: client state type: object properties: type_url: @@ -44828,6 +48034,7 @@ definitions: "@type": "type.googleapis.com/google.protobuf.Duration", "value": "1.212s" } + title: client state description: >- IdentifiedClientState defines a client state with an additional client @@ -44869,9 +48076,6 @@ definitions: type: object properties: consensus_state: - title: >- - consensus state associated with the client identifier at the given - height type: object properties: type_url: @@ -45030,6 +48234,9 @@ definitions: "@type": "type.googleapis.com/google.protobuf.Duration", "value": "1.212s" } + title: >- + consensus state associated with the client identifier at the given + height proof: type: string format: byte @@ -45100,7 +48307,6 @@ definitions: be monitonically increasing even as the RevisionHeight gets reset consensus_state: - title: consensus state type: object properties: type_url: @@ -45269,6 +48475,7 @@ definitions: "@type": "type.googleapis.com/google.protobuf.Duration", "value": "1.212s" } + title: consensus state description: >- ConsensusStateWithHeight defines a consensus state with an additional height field. @@ -45560,7 +48767,6 @@ definitions: type: string title: client identifier client_state: - title: client state type: object properties: type_url: @@ -45725,6 +48931,7 @@ definitions: "@type": "type.googleapis.com/google.protobuf.Duration", "value": "1.212s" } + title: client state description: |- IdentifiedClientState defines a client state with an additional client identifier field. @@ -45764,7 +48971,6 @@ definitions: type: object properties: consensus_state: - title: consensus state associated with the channel type: object properties: type_url: @@ -45923,6 +49129,7 @@ definitions: "@type": "type.googleapis.com/google.protobuf.Duration", "value": "1.212s" } + title: consensus state associated with the channel client_id: type: string title: client ID associated with the consensus state @@ -46306,7 +49513,6 @@ definitions: type: object properties: denom_trace: - description: denom_trace returns the requested denomination trace information. type: object properties: path: @@ -46319,6 +49525,11 @@ definitions: base_denom: type: string description: base denomination of the relayed fungible token. + description: >- + DenomTrace contains the base denomination for ICS20 fungible tokens + and the + + source tracing information path. description: |- QueryDenomTraceResponse is the response type for the Query/DenomTrace RPC method. diff --git a/client/docs/swagger_legacy.yaml b/client/docs/swagger_legacy.yaml index fe00efa48493..62dd93c39a96 100644 --- a/client/docs/swagger_legacy.yaml +++ b/client/docs/swagger_legacy.yaml @@ -446,6 +446,45 @@ paths: description: Invalid request 500: description: Server internal error + /bank/total: + get: + deprecated: true + summary: Total supply of coins in the chain + tags: + - Bank + produces: + - application/json + responses: + 200: + description: OK + schema: + $ref: "#/definitions/Supply" + 500: + description: Internal Server Error + /bank/total/{denomination}: + parameters: + - in: path + name: denomination + description: Coin denomination + required: true + type: string + x-example: uatom + get: + deprecated: true + summary: Total supply of a single coin denomination + tags: + - Bank + produces: + - application/json + responses: + 200: + description: OK + schema: + type: string + 400: + description: Invalid coin denomination + 500: + description: Internal Server Error /auth/accounts/{address}: get: deprecated: true @@ -1940,45 +1979,6 @@ paths: type: string 500: description: Internal Server Error - /supply/total: - get: - deprecated: true - summary: Total supply of coins in the chain - tags: - - Supply - produces: - - application/json - responses: - 200: - description: OK - schema: - $ref: "#/definitions/Supply" - 500: - description: Internal Server Error - /supply/total/{denomination}: - parameters: - - in: path - name: denomination - description: Coin denomination - required: true - type: string - x-example: uatom - get: - deprecated: true - summary: Total supply of a single coin denomination - tags: - - Supply - produces: - - application/json - responses: - 200: - description: OK - schema: - type: string - 400: - description: Invalid coin denomination - 500: - description: Internal Server Error definitions: CheckTxResult: type: object From fd482a27bf52c44f97d93171e4d6f94c11d6e1d7 Mon Sep 17 00:00:00 2001 From: Marko Date: Fri, 26 Feb 2021 10:09:05 +0000 Subject: [PATCH 127/214] update ed25519 (#8690) * update ed25519 * add changelog and doc.go * add comment * add note about tendermint --- CHANGELOG.md | 2 ++ crypto/keys/ed25519/doc.go | 11 +++++++++++ crypto/keys/ed25519/ed25519.go | 4 +++- go.mod | 1 + go.sum | 23 ++++------------------- 5 files changed, 21 insertions(+), 20 deletions(-) create mode 100644 crypto/keys/ed25519/doc.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a3ce60607a6..b3aa1dc82b22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * [\#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. +* (crypto/ed25519) [\#8690] Adopt zip1215 ed2559 verification rules. ### API Breaking Changes @@ -67,6 +68,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (crypto/types) [\#8600](https://github.com/cosmos/cosmos-sdk/pull/8600) `CompactBitArray`: optimize the `NumTrueBitsBefore` method and add an `Equal` method. + ### Bug Fixes * (keyring) [#\8635](https://github.com/cosmos/cosmos-sdk/issues/8635) Remove hardcoded default passphrase value on `NewMnemonic` diff --git a/crypto/keys/ed25519/doc.go b/crypto/keys/ed25519/doc.go new file mode 100644 index 000000000000..6d77365c48e3 --- /dev/null +++ b/crypto/keys/ed25519/doc.go @@ -0,0 +1,11 @@ +package ed25519 + +/* +This package contains a wrapper around crypto/ed22519 to make it comply with the crypto interfaces. + +This package employs zip215 rules. We use https://github.com/hdevalence/ed25519consensus verification function. Ths is done in order to keep compatibility with Tendermints ed25519 implementation. + - https://github.com/tendermint/tendermint/blob/master/crypto/ed25519/ed25519.go#L155 + +This package works with correctly generated signatures. To read more about what this means see https://hdevalence.ca/blog/2020-10-04-its-25519am + +*/ diff --git a/crypto/keys/ed25519/ed25519.go b/crypto/keys/ed25519/ed25519.go index 7c70d573ec30..0c87260ec9ec 100644 --- a/crypto/keys/ed25519/ed25519.go +++ b/crypto/keys/ed25519/ed25519.go @@ -6,6 +6,7 @@ import ( "fmt" "io" + "github.com/hdevalence/ed25519consensus" "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/tmhash" @@ -175,7 +176,8 @@ func (pubKey *PubKey) VerifySignature(msg []byte, sig []byte) bool { return false } - return ed25519.Verify(pubKey.Key, msg, sig) + // uses https://github.com/hdevalence/ed25519consensus.Verify to comply with zip215 verification rules + return ed25519consensus.Verify(pubKey.Key, msg, sig) } func (pubKey *PubKey) String() string { diff --git a/go.mod b/go.mod index e5d258eb4443..b4b725742c8d 100644 --- a/go.mod +++ b/go.mod @@ -25,6 +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/hdevalence/ed25519consensus v0.0.0-20210204194344-59a8610d2b87 github.com/improbable-eng/grpc-web v0.14.0 github.com/magiconair/properties v1.8.4 github.com/mattn/go-isatty v0.0.12 diff --git a/go.sum b/go.sum index bf6adda80984..c16c943a336b 100644 --- a/go.sum +++ b/go.sum @@ -10,6 +10,8 @@ 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= +filippo.io/edwards25519 v1.0.0-beta.2 h1:/BZRNzm8N4K4eWfK28dL4yescorxtO7YG1yun8fy+pI= +filippo.io/edwards25519 v1.0.0-beta.2/go.mod h1:X+pm78QAUPtFLi1z9PYIlS/bdDnvbCOGKtZ+ACWEf7o= 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= @@ -25,7 +27,6 @@ github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxB 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= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= @@ -176,9 +177,7 @@ github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaB 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= @@ -273,12 +272,10 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 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= @@ -287,7 +284,6 @@ github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OI github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= @@ -312,7 +308,6 @@ 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= @@ -357,6 +352,8 @@ 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/hdevalence/ed25519consensus v0.0.0-20210204194344-59a8610d2b87 h1:uUjLpLt6bVvZ72SQc/B4dXcPBw4Vgd7soowdRl52qEM= +github.com/hdevalence/ed25519consensus v0.0.0-20210204194344-59a8610d2b87/go.mod h1:XGsKKeXxeRr95aEOgipvluMPlgjr7dGlk9ZTWOjcUcg= 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= @@ -375,7 +372,6 @@ 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= @@ -400,7 +396,6 @@ github.com/kkdai/bstream v1.0.0/go.mod h1:FDnDOHt5Yx4p3FaHcioFT0QjDOtgUpvjeZqAs+ 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= 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= @@ -452,7 +447,6 @@ github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eI github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= 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= @@ -544,7 +538,6 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.8.0 h1:zvJNkoCFAnYFNC24FV8nW4JdRJ3GIFcLbg65lL/JDcw= github.com/prometheus/client_golang v1.8.0/go.mod h1:O9VU6huf47PktckDQfMTX0Y8tY0/7TSWwj+ITvv0TnM= github.com/prometheus/client_golang v1.9.0 h1:Rrch9mh17XcxvEu9D9DEpb4isxjGBtcevQjKvxPRQIU= github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU= @@ -600,7 +593,6 @@ github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= 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= @@ -609,7 +601,6 @@ github.com/shirou/gopsutil v2.20.5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu 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= @@ -630,7 +621,6 @@ github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU 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= -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.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M= github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= @@ -659,7 +649,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= @@ -683,7 +672,6 @@ github.com/tendermint/tendermint v0.34.0/go.mod h1:Aj3PIipBFSNO21r+Lq3TtzQ+uKESx github.com/tendermint/tendermint v0.34.8 h1:PMWgUx47FrNTsfhxCWzoiIlVAC1SE9+WBlnsF9oQW0I= github.com/tendermint/tendermint v0.34.8/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= 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= @@ -862,7 +850,6 @@ golang.org/x/sys v0.0.0-20200824131525-c12d262b63d8/go.mod h1:h1NjWce9XRLGQEsW7w 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= golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e h1:AyodaIpKjppX+cBfTASF2E1US3H2JFBj920Ot3rtDjs= golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -961,7 +948,6 @@ gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qS gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 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= @@ -982,7 +968,6 @@ 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= 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= From 213921205059175898015513f5b67255780b6ee0 Mon Sep 17 00:00:00 2001 From: Marko Date: Fri, 26 Feb 2021 11:25:48 +0000 Subject: [PATCH 128/214] docker m1 (#8710) --- .github/workflows/proto-docker.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/proto-docker.yml b/.github/workflows/proto-docker.yml index 7a9aecfb25ee..e59eeda18bca 100644 --- a/.github/workflows/proto-docker.yml +++ b/.github/workflows/proto-docker.yml @@ -27,6 +27,12 @@ jobs: fi TAGS="${DOCKER_IMAGE}:${VERSION}" echo ::set-output name=tags::${TAGS} + + - name: Set up QEMU + uses: docker/setup-qemu-action@master + with: + platforms: all + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v1 @@ -42,5 +48,6 @@ jobs: with: context: ./contrib/devtools file: ./contrib/devtools/dockerfile + platforms: linux/amd64,linux/arm64 push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.prep.outputs.tags }} From a786830bb481782cf56f8ecca82fe1e8c18731af Mon Sep 17 00:00:00 2001 From: Marko Date: Fri, 26 Feb 2021 15:41:48 +0000 Subject: [PATCH 129/214] auth: allow 0 coin accounts in genesis (#8714) * allow zero accounts * fix test * fix test --- x/bank/types/balance.go | 5 ----- x/bank/types/balance_test.go | 2 +- x/bank/types/genesis_test.go | 4 ++-- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/x/bank/types/balance.go b/x/bank/types/balance.go index 49330bc06af1..6150679023b8 100644 --- a/x/bank/types/balance.go +++ b/x/bank/types/balance.go @@ -34,11 +34,6 @@ func (b Balance) Validate() error { 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 diff --git a/x/bank/types/balance_test.go b/x/bank/types/balance_test.go index 6282b2478b19..3987f5189ef0 100644 --- a/x/bank/types/balance_test.go +++ b/x/bank/types/balance_test.go @@ -29,7 +29,7 @@ func TestBalanceValidate(t *testing.T) { bank.Balance{ Address: "cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t", }, - true, + false, }, { "dup coins", diff --git a/x/bank/types/genesis_test.go b/x/bank/types/genesis_test.go index a177ddcdab5c..fa1c836c9cbe 100644 --- a/x/bank/types/genesis_test.go +++ b/x/bank/types/genesis_test.go @@ -72,7 +72,7 @@ func TestGenesisStateValidate(t *testing.T) { true, }, { - "invalid balance", + "0 balance", GenesisState{ Balances: []Balance{ { @@ -80,7 +80,7 @@ func TestGenesisStateValidate(t *testing.T) { }, }, }, - true, + false, }, { "dup Metadata", From 68e7a3adf73898008ea878f3d40d1de7b669a0ea Mon Sep 17 00:00:00 2001 From: Barrie Byron Date: Sat, 27 Feb 2021 04:39:08 -0500 Subject: [PATCH 130/214] fix: per 8711 fix typo and minor command text edit for multi sign batch command (#8718) Co-authored-by: Alessio Treglia --- x/auth/client/cli/tx_multisign.go | 32 +++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/x/auth/client/cli/tx_multisign.go b/x/auth/client/cli/tx_multisign.go index 61ec84bdc219..c04d37123c2f 100644 --- a/x/auth/client/cli/tx_multisign.go +++ b/x/auth/client/cli/tx_multisign.go @@ -32,21 +32,21 @@ func GetMultiSignCommand() *cobra.Command { Long: strings.TrimSpace( fmt.Sprintf(`Sign transactions created with the --generate-only flag that require multisig signatures. -Read signature(s) from [signature] file(s), generate a multisig signature compliant to the -multisig key [name], and attach it to the transaction read from [file]. +Read one or more signatures from one or more [signature] file, generate a multisig signature compliant to the +multisig key [name], and attach the key name to the transaction read from [file]. Example: $ %s tx multisign transaction.json k1k2k3 k1sig.json k2sig.json k3sig.json -If the flag --signature-only flag is on, it outputs a JSON representation -of the generated signature only. +If --signature-only flag is on, output a JSON representation +of only the generated signature. -The --offline flag makes sure that the client will not reach out to an external node. -Thus account number or sequence number lookups will not be performed and it is -recommended to set such parameters manually. +If the --offline flag is on, the client will not reach out to an external node. +Account number or sequence number lookups are not performed so you must +set these parameters manually. -The current multisig implementation doesn't support SIGN_MORE_DIRECT and defaults -to amino-json sign mode.' +The current multisig implementation defaults to amino-json sign mode. +The SIGN_MODE_DIRECT sign mode is not supported.' `, version.AppName, ), @@ -56,8 +56,8 @@ to amino-json sign mode.' } cmd.Flags().Bool(flagSigOnly, false, "Print only the generated signature, then exit") - cmd.Flags().String(flags.FlagOutputDocument, "", "The document will be written to the given file instead of STDOUT") - cmd.Flags().Bool(flagAmino, false, "Generate Amino encoded JSON suitable for submiting to the txs REST endpoint") + cmd.Flags().String(flags.FlagOutputDocument, "", "The document is written to the given file instead of STDOUT") + cmd.Flags().Bool(flagAmino, false, "Generate Amino-encoded JSON suitable for submitting to the txs REST endpoint") flags.AddTxFlagsToCmd(cmd) cmd.Flags().String(flags.FlagChainID, "", "network chain ID") @@ -196,14 +196,14 @@ func GetMultiSignBatchCmd() *cobra.Command { Long: strings.TrimSpace( fmt.Sprintf(`Assemble a batch of multisig transactions generated by batch sign command. -Read signature(s) from [signature] file(s), generates multisig signatures compliant to the -multisig key [name], and attach it to the transactions read from [file]. +Read one or more signatures from one or more [signature] file, generate a multisig signature compliant to the +multisig key [name], and attach the key name to the transaction read from [file]. Example: $ %s tx multisign-batch transactions.json multisigk1k2k3 k1sigs.json k2sigs.json k3sig.json -The current multisig implementation doesn't support sign_mode_direct and defaults -to amino-json sign mode.' +The current multisig implementation defaults to amino-json sign mode. +The SIGN_MODE_DIRECT sign mode is not supported.' `, version.AppName, ), ), @@ -215,7 +215,7 @@ to amino-json sign mode.' cmd.Flags().Bool(flagNoAutoIncrement, false, "disable sequence auto increment") cmd.Flags().String( flagMultisig, "", - "Address of the multisig account on behalf of which the transaction shall be signed", + "Address of the multisig account that the transaction signs on behalf of", ) flags.AddTxFlagsToCmd(cmd) From dbb9923917be0e0c3d8a2b55c7cdd89428db998d Mon Sep 17 00:00:00 2001 From: Emmanuel T Odeke Date: Sat, 27 Feb 2021 07:26:22 -0800 Subject: [PATCH 131/214] store/cachekv, x/bank/types: algorithmically fix pathologically slow code (#8719) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After continuously profiling InitGensis with 100K accounts, it showed pathologically slow code, that was the result of a couple of patterns: * Unconditional and not always necessary map lookups * O(n^2) sdk.AccAddressFromBech32 retrievals when the code is expensive, during a quicksort The remedy involved 4 parts: * O(n) sdk.AccAddressFromBech32 invocations, down from O(n^2) in the quicksort * Only doing map lookups when the domain key check has passed * Using a black magic compiler technique of the map clearing idiom * Zero allocation []byte<->string conversion With 100K accounts, this brings InitGenesis down to ~6min, instead of 20+min, it reduces the sort code from ~7sec down to 50ms. Also some simple benchmark reflect the change: ```shell name old time/op new time/op delta SanitizeBalances500-8 19.3ms ±10% 1.5ms ± 5% -92.46% (p=0.000 n=20+20) SanitizeBalances1000-8 41.9ms ± 8% 3.0ms ±12% -92.92% (p=0.000 n=20+20) name old alloc/op new alloc/op delta SanitizeBalances500-8 9.05MB ± 6% 0.56MB ± 0% -93.76% (p=0.000 n=20+18) SanitizeBalances1000-8 20.2MB ± 3% 1.1MB ± 0% -94.37% (p=0.000 n=20+19) name old allocs/op new allocs/op delta SanitizeBalances500-8 72.4k ± 6% 4.5k ± 0% -93.76% (p=0.000 n=20+20) SanitizeBalances1000-8 162k ± 3% 9k ± 0% -94.40% (p=0.000 n=20+20) ``` The CPU profiles show the radical change as per https://github.com/cosmos/cosmos-sdk/issues/7766#issuecomment-786671734 Later on, we shall do more profiling and fixes but for now this brings down the run-time for InitGenesis. Fixes #7766 Co-authored-by: Alessio Treglia --- CHANGELOG.md | 1 + store/cachekv/store.go | 38 ++++++++++++++++-- x/bank/types/balance.go | 45 +++++++++++++++++---- x/bank/types/balance_test.go | 78 ++++++++++++++++++++++++++++++++++++ 4 files changed, 152 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b3aa1dc82b22..a46de7009880 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -66,6 +66,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (x/bank) [\#8614](https://github.com/cosmos/cosmos-sdk/issues/8614) Add `Name` and `Symbol` fields to denom metadata * (x/auth) [\#8522](https://github.com/cosmos/cosmos-sdk/pull/8522) Allow to query all stored accounts * (crypto/types) [\#8600](https://github.com/cosmos/cosmos-sdk/pull/8600) `CompactBitArray`: optimize the `NumTrueBitsBefore` method and add an `Equal` method. +* (store/cachekv), (x/bank/types) [\#8719](https://github.com/cosmos/cosmos-sdk/pull/8719) algorithmically fix pathologically slow code diff --git a/store/cachekv/store.go b/store/cachekv/store.go index b2e394e95f3a..42c94370b8af 100644 --- a/store/cachekv/store.go +++ b/store/cachekv/store.go @@ -4,9 +4,11 @@ import ( "bytes" "container/list" "io" + "reflect" "sort" "sync" "time" + "unsafe" dbm "github.com/tendermint/tm-db" @@ -177,18 +179,48 @@ func (store *Store) iterator(start, end []byte, ascending bool) types.Iterator { return newCacheMergeIterator(parent, cache, ascending) } +// strToByte is meant to make a zero allocation conversion +// from string -> []byte to speed up operations, it is not meant +// to be used generally, but for a specific pattern to check for available +// keys within a domain. +func strToByte(s string) []byte { + var b []byte + hdr := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + hdr.Cap = len(s) + hdr.Len = len(s) + hdr.Data = (*reflect.StringHeader)(unsafe.Pointer(&s)).Data + return b +} + +// byteSliceToStr is meant to make a zero allocation conversion +// from []byte -> string to speed up operations, it is not meant +// to be used generally, but for a specific pattern to delete keys +// from a map. +func byteSliceToStr(b []byte) string { + hdr := (*reflect.StringHeader)(unsafe.Pointer(&b)) + return *(*string)(unsafe.Pointer(hdr)) +} + // Constructs a slice of dirty items, to use w/ memIterator. func (store *Store) dirtyItems(start, end []byte) { unsorted := make([]*kv.Pair, 0) + n := len(store.unsortedCache) for key := range store.unsortedCache { - cacheValue := store.cache[key] - - if dbm.IsKeyInDomain([]byte(key), start, end) { + if dbm.IsKeyInDomain(strToByte(key), start, end) { + cacheValue := store.cache[key] unsorted = append(unsorted, &kv.Pair{Key: []byte(key), Value: cacheValue.value}) + } + } + if len(unsorted) == n { // This pattern allows the Go compiler to emit the map clearing idiom for the entire map. + for key := range store.unsortedCache { delete(store.unsortedCache, key) } + } else { // Otherwise, normally delete the unsorted keys from the map. + for _, kv := range unsorted { + delete(store.unsortedCache, byteSliceToStr(kv.Key)) + } } sort.Slice(unsorted, func(i, j int) bool { diff --git a/x/bank/types/balance.go b/x/bank/types/balance.go index 6150679023b8..7c017ee90051 100644 --- a/x/bank/types/balance.go +++ b/x/bank/types/balance.go @@ -62,16 +62,47 @@ func (b Balance) Validate() error { // 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 - }) - + // Given that this function sorts balances, using the standard library's + // Quicksort based algorithms, we have algorithmic complexities of: + // * Best case: O(nlogn) + // * Worst case: O(n^2) + // The comparator used MUST be cheap to use lest we incur expenses like we had + // before whereby sdk.AccAddressFromBech32, which is a very expensive operation + // compared n * n elements yet discarded computations each time, as per: + // https://github.com/cosmos/cosmos-sdk/issues/7766#issuecomment-786671734 + // with this change the first step is to extract out and singly produce the values + // that'll be used for comparisons and keep them cheap and fast. + + // 1. Retrieve the byte equivalents for each Balance's address and maintain a mapping of + // its Balance, as the mapper will be used in sorting. + type addrToBalance struct { + // We use a pointer here to avoid averse effects of value copying + // wasting RAM all around. + balance *Balance + accAddr []byte + } + adL := make([]*addrToBalance, 0, len(balances)) for _, balance := range balances { - balance.Coins = balance.Coins.Sort() + balance := balance + addr, _ := sdk.AccAddressFromBech32(balance.Address) + adL = append(adL, &addrToBalance{ + balance: &balance, + accAddr: []byte(addr), + }) } + // 2. Sort with the cheap mapping, using the mapper's + // already accAddr bytes values which is a cheaper operation. + sort.Slice(adL, func(i, j int) bool { + ai, aj := adL[i], adL[j] + return bytes.Compare(ai.accAddr, aj.accAddr) < 0 + }) + + // 3. To complete the sorting, we have to now just insert + // back the balances in the order returned by the sort. + for i, ad := range adL { + balances[i] = *ad.balance + } return balances } diff --git a/x/bank/types/balance_test.go b/x/bank/types/balance_test.go index 3987f5189ef0..9736c847baa0 100644 --- a/x/bank/types/balance_test.go +++ b/x/bank/types/balance_test.go @@ -1,10 +1,12 @@ package types_test import ( + "bytes" "testing" "github.com/stretchr/testify/require" + "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" sdk "github.com/cosmos/cosmos-sdk/types" bank "github.com/cosmos/cosmos-sdk/x/bank/types" ) @@ -101,3 +103,79 @@ func TestBalance_GetAddress(t *testing.T) { }) } } + +func TestSanitizeBalances(t *testing.T) { + // 1. Generate balances + tokens := sdk.TokensFromConsensusPower(81) + coin := sdk.NewCoin("benchcoin", tokens) + coins := sdk.Coins{coin} + addrs, _ := makeRandomAddressesAndPublicKeys(20) + + var balances []bank.Balance + for _, addr := range addrs { + balances = append(balances, bank.Balance{ + Address: addr.String(), + Coins: coins, + }) + } + // 2. Sort the values. + sorted := bank.SanitizeGenesisBalances(balances) + + // 3. Compare and ensure that all the values are sorted in ascending order. + // Invariant after sorting: + // a[i] <= a[i+1...n] + for i := 0; i < len(sorted); i++ { + ai := sorted[i] + // Ensure that every single value that comes after i is less than it. + for j := i + 1; j < len(sorted); j++ { + aj := sorted[j] + + if got := bytes.Compare(ai.GetAddress(), aj.GetAddress()); got > 0 { + t.Errorf("Balance(%d) > Balance(%d)", i, j) + } + } + } +} + +func makeRandomAddressesAndPublicKeys(n int) (accL []sdk.AccAddress, pkL []*ed25519.PubKey) { + for i := 0; i < n; i++ { + pk := ed25519.GenPrivKey().PubKey().(*ed25519.PubKey) + pkL = append(pkL, pk) + accL = append(accL, sdk.AccAddress(pk.Address())) + } + return accL, pkL +} + +var sink, revert interface{} + +func BenchmarkSanitizeBalances500(b *testing.B) { + benchmarkSanitizeBalances(b, 500) +} + +func BenchmarkSanitizeBalances1000(b *testing.B) { + benchmarkSanitizeBalances(b, 1000) +} + +func benchmarkSanitizeBalances(b *testing.B, nAddresses int) { + b.ReportAllocs() + tokens := sdk.TokensFromConsensusPower(81) + coin := sdk.NewCoin("benchcoin", tokens) + coins := sdk.Coins{coin} + addrs, _ := makeRandomAddressesAndPublicKeys(nAddresses) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + var balances []bank.Balance + for _, addr := range addrs { + balances = append(balances, bank.Balance{ + Address: addr.String(), + Coins: coins, + }) + } + sink = bank.SanitizeGenesisBalances(balances) + } + if sink == nil { + b.Fatal("Benchmark did not run") + } + sink = revert +} From 0bec60e39ff4124b4a6b2daba1bbcab64bdc48c2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Mar 2021 08:27:13 +0000 Subject: [PATCH 132/214] build(deps): bump github.com/prometheus/common from 0.17.0 to 0.18.0 (#8727) Bumps [github.com/prometheus/common](https://github.com/prometheus/common) from 0.17.0 to 0.18.0. - [Release notes](https://github.com/prometheus/common/releases) - [Commits](https://github.com/prometheus/common/compare/v0.17.0...v0.18.0) 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 b4b725742c8d..d409d401313f 100644 --- a/go.mod +++ b/go.mod @@ -33,7 +33,7 @@ require ( github.com/pelletier/go-toml v1.8.1 // indirect github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.9.0 - github.com/prometheus/common v0.17.0 + github.com/prometheus/common v0.18.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 c16c943a336b..a2c9cd63ed57 100644 --- a/go.sum +++ b/go.sum @@ -557,8 +557,8 @@ github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8b 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/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= -github.com/prometheus/common v0.17.0 h1:kDIZLI74SS+3tedSvEkykgBkD7txMxaJAPj8DtJUKYA= -github.com/prometheus/common v0.17.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= +github.com/prometheus/common v0.18.0 h1:WCVKW7aL6LEe1uryfI9dnEc2ZqNB1Fn0ok930v0iL1Y= +github.com/prometheus/common v0.18.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 32f454aa1057303ee595f1a30f57ec5368704029 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Mon, 1 Mar 2021 09:31:09 +0100 Subject: [PATCH 133/214] Makefile: fix build_tags update (#8725) Previously, we set build_tags before updating the options for DB backend. This does't work with BadgerDB - it BUILD_TAGS which must be included in build_tags. Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- Makefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 87c842b710a6..66065b864a23 100644 --- a/Makefile +++ b/Makefile @@ -45,8 +45,6 @@ endif ifeq (cleveldb,$(findstring cleveldb,$(COSMOS_BUILD_OPTIONS))) build_tags += gcc endif -build_tags += $(BUILD_TAGS) -build_tags := $(strip $(build_tags)) whitespace := whitespace += $(whitespace) @@ -68,6 +66,7 @@ ifeq (cleveldb,$(findstring cleveldb,$(COSMOS_BUILD_OPTIONS))) endif ifeq (badgerdb,$(findstring badgerdb,$(COSMOS_BUILD_OPTIONS))) ldflags += -X github.com/cosmos/cosmos-sdk/types.DBBackend=badgerdb + BUILD_TAGS += badgerdb endif # handle rocksdb ifeq (rocksdb,$(findstring rocksdb,$(COSMOS_BUILD_OPTIONS))) @@ -87,6 +86,9 @@ endif ldflags += $(LDFLAGS) ldflags := $(strip $(ldflags)) +build_tags += $(BUILD_TAGS) +build_tags := $(strip $(build_tags)) + BUILD_FLAGS := -tags "$(build_tags)" -ldflags '$(ldflags)' # check for nostrip option ifeq (,$(findstring nostrip,$(COSMOS_BUILD_OPTIONS))) From b1c72fda7f81af31afa0d9cd81a0ce73007556da Mon Sep 17 00:00:00 2001 From: SaReN Date: Mon, 1 Mar 2021 18:11:49 +0530 Subject: [PATCH 134/214] crypto/keyring: fix offline keys migration (#8639) Fix `keys migrate` command (#8703) crypto/keyring: reinstate the InfoImporter interface InfoImporter is implemented by those Keyring implementations that support import of Info objects. Co-authored-by: Alessio Treglia Co-authored-by: Jonathan Gimeno Co-authored-by: Amaury <1293565+amaurym@users.noreply.github.com> --- .github/workflows/test.yml | 2 +- CHANGELOG.md | 1 + client/keys/migrate.go | 35 +- client/keys/migrate_test.go | 30 +- client/keys/testdata/keys/keys.db/000136.ldb | Bin 0 -> 825 bytes client/keys/testdata/keys/keys.db/000137.ldb | Bin 0 -> 244 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 | 906 +++++++++++++++++- .../testdata/keys/keys.db/MANIFEST-000005 | Bin 41 -> 0 bytes .../testdata/keys/keys.db/MANIFEST-000167 | Bin 0 -> 195 bytes crypto/keyring/keyring.go | 18 +- 12 files changed, 929 insertions(+), 67 deletions(-) create mode 100644 client/keys/testdata/keys/keys.db/000136.ldb create mode 100644 client/keys/testdata/keys/keys.db/000137.ldb delete mode 100644 client/keys/testdata/keys/keys.db/MANIFEST-000005 create mode 100644 client/keys/testdata/keys/keys.db/MANIFEST-000167 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b499f2822817..b45beac6f757 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -201,7 +201,7 @@ jobs: if: env.GIT_DIFF - name: test & coverage report creation run: | - cat pkgs.txt.part.${{ matrix.part }} | xargs go test -mod=readonly -json -timeout 30m -race -tags='cgo ledger test_ledger_mock' > ${{ matrix.part }}-race-output.txt + xargs --arg-file=pkgs.txt.part.${{ matrix.part }} go test -mod=readonly -json -timeout 30m -race -tags='cgo ledger test_ledger_mock' | tee ${{ matrix.part }}-race-output.txt if: env.GIT_DIFF - uses: actions/upload-artifact@v2 with: diff --git a/CHANGELOG.md b/CHANGELOG.md index a46de7009880..cd4682f2fbc0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -78,6 +78,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (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 * (server) [\#8641](https://github.com/cosmos/cosmos-sdk/pull/8641) Fix Tendermint and application configuration reading from file +* (client/keys) [\#8639] (https://github.com/cosmos/cosmos-sdk/pull/8639) Fix keys migrate for mulitisig, offline, and ledger keys. The migrate command now takes a positional old_home_dir argument. ## [v0.41.3](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.41.3) - 2021-02-18 diff --git a/client/keys/migrate.go b/client/keys/migrate.go index 836a2655b087..4848ec281162 100644 --- a/client/keys/migrate.go +++ b/client/keys/migrate.go @@ -22,16 +22,18 @@ const migratePassphrase = "NOOP_PASSPHRASE" // MigrateCommand migrates key information from legacy keybase to OS secret store. func MigrateCommand() *cobra.Command { cmd := &cobra.Command{ - Use: "migrate", + Use: "migrate ", Short: "Migrate keys from the legacy (db-based) Keybase", - Long: `Migrate key information from the legacy (db-based) Keybase to the new keyring-based Keybase. + Long: `Migrate key information from the legacy (db-based) Keybase to the new keyring-based Keyring. +The legacy Keybase used to persist keys in a LevelDB database stored in a 'keys' sub-directory of +the old client application's home directory, e.g. $HOME/.gaiacli/keys/. For each key material entry, the command will prompt if the key should be skipped or not. If the key is not to be skipped, the passphrase must be entered. The key will only be migrated if the passphrase is correct. Otherwise, the command will exit and migration must be repeated. It is recommended to run in 'dry-run' mode first to verify all key migration material. `, - Args: cobra.ExactArgs(0), + Args: cobra.ExactArgs(1), RunE: runMigrateCmd, } @@ -44,12 +46,12 @@ func runMigrateCmd(cmd *cobra.Command, args []string) error { // instantiate legacy keybase var legacyKb keyring.LegacyKeybase - legacyKb, err := NewLegacyKeyBaseFromDir(rootDir) + legacyKb, err := NewLegacyKeyBaseFromDir(args[0]) if err != nil { return err } - defer legacyKb.Close() + defer func() { _ = legacyKb.Close() }() // fetch list of keys from legacy keybase oldKeys, err := legacyKb.List() @@ -71,7 +73,7 @@ func runMigrateCmd(cmd *cobra.Command, args []string) error { return errors.Wrap(err, "failed to create temporary directory for dryrun migration") } - defer os.RemoveAll(tmpDir) + defer func() { _ = os.RemoveAll(tmpDir) }() migrator, err = keyring.New(keyringServiceName, keyring.BackendTest, tmpDir, buf) } else { @@ -91,11 +93,11 @@ func runMigrateCmd(cmd *cobra.Command, args []string) error { return nil } - for _, key := range oldKeys { - keyName := key.GetName() - keyType := key.GetType() + for _, oldInfo := range oldKeys { + keyName := oldInfo.GetName() + keyType := oldInfo.GetType() - cmd.PrintErrf("Migrating key: '%s (%s)' ...\n", key.GetName(), keyType) + cmd.PrintErrf("Migrating key: '%s (%s)' ...\n", keyName, keyType) // allow user to skip migrating specific keys ok, err := input.GetConfirmation("Skip key migration?", buf, cmd.ErrOrStderr()) @@ -106,13 +108,15 @@ func runMigrateCmd(cmd *cobra.Command, args []string) error { continue } + // TypeLocal needs an additional step to ask password. + // The other keyring types are handled by ImportInfo. if keyType != keyring.TypeLocal { - pubkeyArmor, err := legacyKb.ExportPubKey(keyName) - if err != nil { - return err + infoImporter, ok := migrator.(keyring.InfoImporter) + if !ok { + return fmt.Errorf("the Keyring implementation does not support import operations of Info types") } - if err := migrator.ImportPubKey(keyName, pubkeyArmor); err != nil { + if err = infoImporter.ImportInfo(oldInfo); err != nil { return err } @@ -135,8 +139,9 @@ func runMigrateCmd(cmd *cobra.Command, args []string) error { if err := migrator.ImportPrivKey(keyName, armoredPriv, migratePassphrase); err != nil { return err } + } - cmd.Print("Migration Complete") + cmd.PrintErrln("Migration complete.") return err } diff --git a/client/keys/migrate_test.go b/client/keys/migrate_test.go index 948e0144fc90..32746291c882 100644 --- a/client/keys/migrate_test.go +++ b/client/keys/migrate_test.go @@ -5,44 +5,38 @@ import ( "fmt" "testing" + "github.com/cosmos/cosmos-sdk/client" + + "github.com/stretchr/testify/require" + "github.com/otiai10/copy" "github.com/stretchr/testify/assert" - "github.com/tendermint/tendermint/libs/cli" - "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/testutil" ) func Test_runMigrateCmd(t *testing.T) { - cmd := AddKeyCommand() - _ = testutil.ApplyMockIODiscardOutErr(cmd) - cmd.Flags().AddFlagSet(Commands("home").PersistentFlags()) - kbHome := t.TempDir() - clientCtx := client.Context{}.WithKeyringDir(kbHome) ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx) - copy.Copy("testdata", kbHome) - cmd.SetArgs([]string{ - "keyname1", - fmt.Sprintf("--%s=%s", cli.OutputFlag, OutputFormatText), - fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, keyring.BackendTest), - }) - assert.NoError(t, cmd.ExecuteContext(ctx)) + require.NoError(t, copy.Copy("testdata", kbHome)) - cmd = MigrateCommand() + cmd := MigrateCommand() cmd.Flags().AddFlagSet(Commands("home").PersistentFlags()) - mockIn := testutil.ApplyMockIODiscardOutErr(cmd) + //mockIn := testutil.ApplyMockIODiscardOutErr(cmd) + mockIn, mockOut := testutil.ApplyMockIO(cmd) cmd.SetArgs([]string{ - fmt.Sprintf("--%s=%s", flags.FlagHome, kbHome), + kbHome, + //fmt.Sprintf("--%s=%s", flags.FlagHome, kbHome), fmt.Sprintf("--%s=true", flags.FlagDryRun), fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, keyring.BackendTest), }) - mockIn.Reset("test1234\ntest1234\n") + mockIn.Reset("\n12345678\n\n\n\n\n") + t.Log(mockOut.String()) assert.NoError(t, cmd.ExecuteContext(ctx)) } diff --git a/client/keys/testdata/keys/keys.db/000136.ldb b/client/keys/testdata/keys/keys.db/000136.ldb new file mode 100644 index 0000000000000000000000000000000000000000..58165a9ab136c5ea64590cbc0de97487c1a4b47a GIT binary patch literal 825 zcmZ3>X2Bq^lqo5(NG~%lEuWE>ftB%#0^?#P-nF8(T+BdmA+^_0FWVKFz7+5APUTBi zxpVrr<>xtTVk;Jy#xba*x#@kKy>OPIuddX4MqLnaa&`CgQwVYOb8!vw_4Er-2ng~F za}04+@OF&^E8r?l%qg)_Fg7qVF>^L|GqA99GO%q6F3&47%ql333{4453oQt)C{DLb_jES&OA2!d&`t@f^mMgM^UO{$ z@GbSsjtnmI(Ka*7NX)Y+%T4w+_cGveN{le|a`es5F-UjK$_p}&FgCYzs&WqW3U$hK zuP`yvPYL$UNer~*vMmk|(dPoY6zB(B9$|d-!I{C9GdaIFH^11>yr?kQJiQ{fpuDOm z$E>i@pd>G^!Z@QSr`R&v)FL~(yehe(G(#^jC8a2}xR_Ca0SpRClZ;f$POzJCXOx;* z8s`}&S7qfEWmOfJm{%m`Rhed4B$}8SRHc*ygUYm^A`PxzkkwIyAtyB@Jymnp3U)Kj zf}Dy(OM@b#LX*l0bCVQqoUk`yuw7w+%yZb;tG?jj7q&kUKa*gP8S}ay@tGP zGdRjJOiKz1N>g*v({hW`k}WEYa#D>_ipz{kEzGKlvdU9aEVGJCMV%PODKj53`55=QdAcGtLA7`F-fPMEaVAkwIpcc}I~N89BSDurUJ|MW?J4Fpr_&xV?Y=DLa(u4S zC7lqZfOUUn{R);5*$xU?MiBm!uu+FY2F_(OnLj~Xgn^T}knuk!qXxq*R=AXH|K>~g VS-IY^ih+digYe%C-72N-w*gPx^}hfB literal 0 HcmV?d00001 diff --git a/client/keys/testdata/keys/keys.db/000137.ldb b/client/keys/testdata/keys/keys.db/000137.ldb new file mode 100644 index 0000000000000000000000000000000000000000..340e51356e8330d558d49ceef0a13ce11478c79b GIT binary patch literal 244 zcmbQi_`!$4mNPlOI5)r8Fe@t~x4=9xE4jif#ULvuHQk~zB`?FQs;oRUwbaBsy~Nzy zG9^(jF(suawYZp3jR6b_N|TKBGV{{%83c_B1bJ8(Ras@;Fc``E+Fj#f0Z9s}y^ea> zuE?x&FW_FHnQCF|8p{GFiZt0f~YhpQ4gHO$hDGD3?zgfg#T{nRw;GA4FKoFKg9q5 literal 0 HcmV?d00001 diff --git a/client/keys/testdata/keys/keys.db/CURRENT b/client/keys/testdata/keys/keys.db/CURRENT index aa5bb8ea5090..c5ea6dc2c1e0 100644 --- a/client/keys/testdata/keys/keys.db/CURRENT +++ b/client/keys/testdata/keys/keys.db/CURRENT @@ -1 +1 @@ -MANIFEST-000005 +MANIFEST-000167 diff --git a/client/keys/testdata/keys/keys.db/CURRENT.bak b/client/keys/testdata/keys/keys.db/CURRENT.bak index 4fb1dad19e03..6da0b2c731cc 100644 --- a/client/keys/testdata/keys/keys.db/CURRENT.bak +++ b/client/keys/testdata/keys/keys.db/CURRENT.bak @@ -1 +1 @@ -MANIFEST-000003 +MANIFEST-000165 diff --git a/client/keys/testdata/keys/keys.db/LOG b/client/keys/testdata/keys/keys.db/LOG index e37648b855bb..c42df220de73 100644 --- a/client/keys/testdata/keys/keys.db/LOG +++ b/client/keys/testdata/keys/keys.db/LOG @@ -1,30 +1,876 @@ -=============== 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 +=============== Sep 12, 2020 (BST) =============== +14:56:38.444867 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +14:56:38.447630 db@open opening +14:56:38.447826 version@stat F·[] S·0B[] Sc·[] +14:56:38.449162 db@janitor F·2 G·0 +14:56:38.449180 db@open done T·1.537964ms +14:56:38.449193 db@close closing +14:56:38.449264 db@close done T·69.313µs +=============== Sep 12, 2020 (BST) =============== +14:56:49.081871 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +14:56:49.081975 version@stat F·[] S·0B[] Sc·[] +14:56:49.081994 db@open opening +14:56:49.082040 journal@recovery F·1 +14:56:49.082399 journal@recovery recovering @1 +14:56:49.083134 version@stat F·[] S·0B[] Sc·[] +14:56:49.088411 db@janitor F·2 G·0 +14:56:49.088430 db@open done T·6.428462ms +14:56:49.088440 db@close closing +14:56:49.088491 db@close done T·48.589µs +=============== Sep 12, 2020 (BST) =============== +14:56:55.214003 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +14:56:55.214144 version@stat F·[] S·0B[] Sc·[] +14:56:55.214165 db@open opening +14:56:55.214215 journal@recovery F·1 +14:56:55.214329 journal@recovery recovering @2 +14:56:55.214750 version@stat F·[] S·0B[] Sc·[] +14:56:55.221347 db@janitor F·2 G·0 +14:56:55.221365 db@open done T·7.194565ms +14:56:55.608587 db@close closing +14:56:55.608644 db@close done T·54.685µs +=============== Sep 12, 2020 (BST) =============== +14:57:07.211101 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +14:57:07.211224 version@stat F·[] S·0B[] Sc·[] +14:57:07.211243 db@open opening +14:57:07.211287 journal@recovery F·1 +14:57:07.211388 journal@recovery recovering @4 +14:57:07.213734 memdb@flush created L0@6 N·2 S·470B "cos..ess,v2":"val..nfo,v1" +14:57:07.214142 version@stat F·[1] S·470B[470B] Sc·[0.25] +14:57:07.218723 db@janitor F·3 G·0 +14:57:07.218743 db@open done T·7.488657ms +14:57:07.218804 db@close closing +14:57:07.218842 db@close done T·36.603µs +=============== Sep 12, 2020 (BST) =============== +14:57:16.418006 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +14:57:16.418133 version@stat F·[1] S·470B[470B] Sc·[0.25] +14:57:16.418153 db@open opening +14:57:16.418199 journal@recovery F·1 +14:57:16.418508 journal@recovery recovering @7 +14:57:16.418891 version@stat F·[1] S·470B[470B] Sc·[0.25] +14:57:16.425395 db@janitor F·3 G·0 +14:57:16.425423 db@open done T·7.257565ms +14:57:16.425482 db@close closing +14:57:16.425522 db@close done T·38.172µs +=============== Sep 12, 2020 (BST) =============== +14:57:16.425854 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +14:57:16.425965 version@stat F·[1] S·470B[470B] Sc·[0.25] +14:57:16.425983 db@open opening +14:57:16.426027 journal@recovery F·1 +14:57:16.426133 journal@recovery recovering @9 +14:57:16.426324 version@stat F·[1] S·470B[470B] Sc·[0.25] +14:57:16.431088 db@janitor F·3 G·0 +14:57:16.431103 db@open done T·5.115335ms +14:57:16.431142 db@close closing +14:57:16.431179 db@close done T·35.705µs +=============== Sep 12, 2020 (BST) =============== +14:57:16.431287 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +14:57:16.431376 version@stat F·[1] S·470B[470B] Sc·[0.25] +14:57:16.431394 db@open opening +14:57:16.431437 journal@recovery F·1 +14:57:16.431721 journal@recovery recovering @11 +14:57:16.432205 version@stat F·[1] S·470B[470B] Sc·[0.25] +14:57:16.437468 db@janitor F·3 G·0 +14:57:16.437486 db@open done T·6.087128ms +14:57:16.437529 db@close closing +14:57:16.437571 db@close done T·40.188µs +=============== Sep 12, 2020 (BST) =============== +14:57:16.437907 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +14:57:16.438006 version@stat F·[1] S·470B[470B] Sc·[0.25] +14:57:16.438024 db@open opening +14:57:16.438067 journal@recovery F·1 +14:57:16.438573 journal@recovery recovering @13 +14:57:16.439155 version@stat F·[1] S·470B[470B] Sc·[0.25] +14:57:16.443451 db@janitor F·3 G·0 +14:57:16.443466 db@open done T·5.437579ms +14:57:16.443511 db@close closing +14:57:16.443634 db@close done T·118.642µs +=============== Sep 12, 2020 (BST) =============== +14:57:16.443733 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +14:57:16.443847 version@stat F·[1] S·470B[470B] Sc·[0.25] +14:57:16.443864 db@open opening +14:57:16.443915 journal@recovery F·1 +14:57:16.444629 journal@recovery recovering @15 +14:57:16.445570 version@stat F·[1] S·470B[470B] Sc·[0.25] +14:57:16.450978 db@janitor F·3 G·0 +14:57:16.451001 db@open done T·7.132193ms +14:57:16.451050 db@close closing +14:57:16.451089 db@close done T·37.371µs +=============== Sep 12, 2020 (BST) =============== +14:57:19.439656 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +14:57:19.439775 version@stat F·[1] S·470B[470B] Sc·[0.25] +14:57:19.439793 db@open opening +14:57:19.439845 journal@recovery F·1 +14:57:19.440199 journal@recovery recovering @17 +14:57:19.440624 version@stat F·[1] S·470B[470B] Sc·[0.25] +14:57:19.445819 db@janitor F·3 G·0 +14:57:19.445837 db@open done T·6.03822ms +14:57:19.828985 db@close closing +14:57:19.829058 db@close done T·71.028µs +=============== Sep 12, 2020 (BST) =============== +15:07:04.002859 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +15:07:04.002990 version@stat F·[1] S·470B[470B] Sc·[0.25] +15:07:04.003010 db@open opening +15:07:04.003081 journal@recovery F·1 +15:07:04.003191 journal@recovery recovering @19 +15:07:04.003591 version@stat F·[1] S·470B[470B] Sc·[0.25] +15:07:04.008917 db@janitor F·3 G·0 +15:07:04.008942 db@open done T·5.916433ms +15:07:04.009005 db@close closing +15:07:04.009050 db@close done T·42.762µs +=============== Sep 12, 2020 (BST) =============== +15:07:15.240666 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +15:07:15.240802 version@stat F·[1] S·470B[470B] Sc·[0.25] +15:07:15.240825 db@open opening +15:07:15.240871 journal@recovery F·1 +15:07:15.241288 journal@recovery recovering @21 +15:07:15.241702 version@stat F·[1] S·470B[470B] Sc·[0.25] +15:07:15.249270 db@janitor F·3 G·0 +15:07:15.249299 db@open done T·8.459432ms +15:07:15.249363 db@close closing +15:07:15.249404 db@close done T·39.294µs +=============== Sep 12, 2020 (BST) =============== +15:07:15.249761 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +15:07:15.249850 version@stat F·[1] S·470B[470B] Sc·[0.25] +15:07:15.249868 db@open opening +15:07:15.249911 journal@recovery F·1 +15:07:15.250026 journal@recovery recovering @23 +15:07:15.250195 version@stat F·[1] S·470B[470B] Sc·[0.25] +15:07:15.254923 db@janitor F·3 G·0 +15:07:15.254943 db@open done T·5.069716ms +15:07:15.254987 db@close closing +15:07:15.255026 db@close done T·37.365µs +=============== Sep 12, 2020 (BST) =============== +15:07:15.255136 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +15:07:15.255218 version@stat F·[1] S·470B[470B] Sc·[0.25] +15:07:15.255235 db@open opening +15:07:15.255277 journal@recovery F·1 +15:07:15.255617 journal@recovery recovering @25 +15:07:15.256091 version@stat F·[1] S·470B[470B] Sc·[0.25] +15:07:15.262240 db@janitor F·3 G·0 +15:07:15.262260 db@open done T·7.018813ms +15:07:15.262310 db@close closing +15:07:15.262353 db@close done T·41.276µs +=============== Sep 12, 2020 (BST) =============== +15:07:15.262707 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +15:07:15.262808 version@stat F·[1] S·470B[470B] Sc·[0.25] +15:07:15.262829 db@open opening +15:07:15.262874 journal@recovery F·1 +15:07:15.263408 journal@recovery recovering @27 +15:07:15.263994 version@stat F·[1] S·470B[470B] Sc·[0.25] +15:07:15.268793 db@janitor F·3 G·0 +15:07:15.268810 db@open done T·5.975152ms +15:07:15.268861 db@close closing +15:07:15.268900 db@close done T·37.419µs +=============== Sep 12, 2020 (BST) =============== +15:07:15.268989 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +15:07:15.269096 version@stat F·[1] S·470B[470B] Sc·[0.25] +15:07:15.269117 db@open opening +15:07:15.269165 journal@recovery F·1 +15:07:15.269858 journal@recovery recovering @29 +15:07:15.270587 version@stat F·[1] S·470B[470B] Sc·[0.25] +15:07:15.275935 db@janitor F·3 G·0 +15:07:15.275951 db@open done T·6.828156ms +15:07:15.275999 db@close closing +15:07:15.276033 db@close done T·32.757µs +=============== Sep 12, 2020 (BST) =============== +15:07:21.660414 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +15:07:21.660547 version@stat F·[1] S·470B[470B] Sc·[0.25] +15:07:21.660568 db@open opening +15:07:21.660655 journal@recovery F·1 +15:07:21.660960 journal@recovery recovering @31 +15:07:21.661682 version@stat F·[1] S·470B[470B] Sc·[0.25] +15:07:21.667796 db@janitor F·3 G·0 +15:07:21.667813 db@open done T·7.237366ms +15:07:21.667869 db@close closing +15:07:21.667914 db@close done T·43.496µs +=============== Sep 12, 2020 (BST) =============== +15:07:21.668253 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +15:07:21.668354 version@stat F·[1] S·470B[470B] Sc·[0.25] +15:07:21.668372 db@open opening +15:07:21.668418 journal@recovery F·1 +15:07:21.668529 journal@recovery recovering @33 +15:07:21.668930 version@stat F·[1] S·470B[470B] Sc·[0.25] +15:07:21.674796 db@janitor F·3 G·0 +15:07:21.674817 db@open done T·6.440491ms +15:07:21.674861 db@close closing +15:07:21.674898 db@close done T·35.584µs +=============== Sep 12, 2020 (BST) =============== +15:07:21.675013 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +15:07:21.675115 version@stat F·[1] S·470B[470B] Sc·[0.25] +15:07:21.675131 db@open opening +15:07:21.675179 journal@recovery F·1 +15:07:21.675707 journal@recovery recovering @35 +15:07:21.676833 version@stat F·[1] S·470B[470B] Sc·[0.25] +15:07:21.681212 db@janitor F·3 G·0 +15:07:21.681226 db@open done T·6.089677ms +15:07:21.681270 db@close closing +15:07:21.681299 db@close done T·27.867µs +=============== Sep 12, 2020 (BST) =============== +15:07:21.681691 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +15:07:21.681799 version@stat F·[1] S·470B[470B] Sc·[0.25] +15:07:21.681817 db@open opening +15:07:21.681882 journal@recovery F·1 +15:07:21.683119 journal@recovery recovering @37 +15:07:21.684000 version@stat F·[1] S·470B[470B] Sc·[0.25] +15:07:21.689926 db@janitor F·3 G·0 +15:07:21.689940 db@open done T·8.117662ms +15:07:21.689984 db@close closing +15:07:21.690027 db@close done T·42.379µs +=============== Sep 12, 2020 (BST) =============== +15:07:21.690104 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +15:07:21.690189 version@stat F·[1] S·470B[470B] Sc·[0.25] +15:07:21.690205 db@open opening +15:07:21.690247 journal@recovery F·1 +15:07:21.690536 journal@recovery recovering @39 +15:07:21.690899 version@stat F·[1] S·470B[470B] Sc·[0.25] +15:07:21.695207 db@janitor F·3 G·0 +15:07:21.695223 db@open done T·5.013121ms +15:07:21.695265 db@close closing +15:07:21.695320 db@close done T·53.965µs +=============== Sep 12, 2020 (BST) =============== +15:07:24.335083 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +15:07:24.335214 version@stat F·[1] S·470B[470B] Sc·[0.25] +15:07:24.335233 db@open opening +15:07:24.335282 journal@recovery F·1 +15:07:24.336367 journal@recovery recovering @41 +15:07:24.336786 version@stat F·[1] S·470B[470B] Sc·[0.25] +15:07:24.342965 db@janitor F·3 G·0 +15:07:24.342984 db@open done T·7.745647ms +15:07:24.725175 db@close closing +15:07:24.725234 db@close done T·57.895µs +=============== Nov 2, 2020 (GMT) =============== +00:08:43.299526 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +00:08:43.299860 version@stat F·[1] S·470B[470B] Sc·[0.25] +00:08:43.299875 db@open opening +00:08:43.299900 journal@recovery F·1 +00:08:43.300467 journal@recovery recovering @43 +00:08:43.301378 version@stat F·[1] S·470B[470B] Sc·[0.25] +00:08:43.307882 db@janitor F·3 G·0 +00:08:43.307911 db@open done T·8.03178ms +00:08:43.308144 db@close closing +00:08:43.308231 db@close done T·85.824µs +=============== Nov 2, 2020 (GMT) =============== +00:09:14.493119 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +00:09:14.493237 version@stat F·[1] S·470B[470B] Sc·[0.25] +00:09:14.493272 db@open opening +00:09:14.493296 journal@recovery F·1 +00:09:14.493370 journal@recovery recovering @45 +00:09:14.493648 version@stat F·[1] S·470B[470B] Sc·[0.25] +00:09:14.499436 db@janitor F·3 G·0 +00:09:14.499452 db@open done T·6.170984ms +00:09:14.499537 db@close closing +00:09:14.499592 db@close done T·52.707µs +=============== Jan 22, 2021 (GMT) =============== +12:47:15.935887 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +12:47:15.937333 version@stat F·[1] S·470B[470B] Sc·[0.25] +12:47:15.937343 db@open opening +12:47:15.937370 journal@recovery F·1 +12:47:15.937642 journal@recovery recovering @47 +12:47:15.937942 version@stat F·[1] S·470B[470B] Sc·[0.25] +12:47:15.944262 db@janitor F·3 G·0 +12:47:15.944270 db@open done T·6.922789ms +12:47:15.944460 db@close closing +12:47:15.944492 db@close done T·30.723µs +=============== Jan 22, 2021 (GMT) =============== +15:23:04.060521 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +15:23:04.060694 version@stat F·[1] S·470B[470B] Sc·[0.25] +15:23:04.060708 db@open opening +15:23:04.060734 journal@recovery F·1 +15:23:04.061045 journal@recovery recovering @49 +15:23:04.061463 version@stat F·[1] S·470B[470B] Sc·[0.25] +15:23:04.067352 db@janitor F·3 G·0 +15:23:04.067386 db@open done T·6.675171ms +15:23:11.819265 db@close closing +15:23:11.819317 db@close done T·51.057µs +=============== Jan 22, 2021 (GMT) =============== +15:23:14.037455 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +15:23:14.037524 version@stat F·[1] S·470B[470B] Sc·[0.25] +15:23:14.037535 db@open opening +15:23:14.037560 journal@recovery F·1 +15:23:14.037629 journal@recovery recovering @51 +15:23:14.037951 version@stat F·[1] S·470B[470B] Sc·[0.25] +15:23:14.045002 db@janitor F·3 G·0 +15:23:14.045020 db@open done T·7.475686ms +15:23:22.065063 db@close closing +15:23:22.065111 db@close done T·47.074µs +=============== Jan 22, 2021 (GMT) =============== +15:23:43.145956 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +15:23:43.146094 version@stat F·[1] S·470B[470B] Sc·[0.25] +15:23:43.146107 db@open opening +15:23:43.146132 journal@recovery F·1 +15:23:43.146447 journal@recovery recovering @53 +15:23:43.146912 version@stat F·[1] S·470B[470B] Sc·[0.25] +15:23:43.153059 db@janitor F·3 G·0 +15:23:43.153108 db@open done T·6.977141ms +15:23:43.153245 db@close closing +15:23:43.153290 db@close done T·43.663µs +=============== Jan 22, 2021 (GMT) =============== +15:25:14.027169 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +15:25:14.027240 version@stat F·[1] S·470B[470B] Sc·[0.25] +15:25:14.027250 db@open opening +15:25:14.027274 journal@recovery F·1 +15:25:14.027627 journal@recovery recovering @55 +15:25:14.028059 version@stat F·[1] S·470B[470B] Sc·[0.25] +15:25:14.033292 db@janitor F·3 G·0 +15:25:14.033304 db@open done T·6.047911ms +15:25:19.981971 db@close closing +15:25:19.982011 db@close done T·39.165µs +=============== Jan 22, 2021 (GMT) =============== +15:25:51.137523 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +15:25:51.138542 version@stat F·[1] S·470B[470B] Sc·[0.25] +15:25:51.138553 db@open opening +15:25:51.138579 journal@recovery F·1 +15:25:51.138632 journal@recovery recovering @57 +15:25:51.138981 version@stat F·[1] S·470B[470B] Sc·[0.25] +15:25:51.144970 db@janitor F·3 G·0 +15:25:51.144983 db@open done T·6.422769ms +15:25:51.145031 db@close closing +15:25:51.145071 db@close done T·39.108µs +=============== Jan 22, 2021 (GMT) =============== +15:25:56.504732 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +15:25:56.504809 version@stat F·[1] S·470B[470B] Sc·[0.25] +15:25:56.504824 db@open opening +15:25:56.504872 journal@recovery F·1 +15:25:56.505474 journal@recovery recovering @59 +15:25:56.505571 version@stat F·[1] S·470B[470B] Sc·[0.25] +15:25:56.512054 db@janitor F·3 G·0 +15:25:56.512061 db@open done T·7.232269ms +15:25:56.710823 db@close closing +15:25:56.710860 db@close done T·36.326µs +=============== Jan 22, 2021 (GMT) =============== +15:26:02.847640 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +15:26:02.847733 version@stat F·[1] S·470B[470B] Sc·[0.25] +15:26:02.847745 db@open opening +15:26:02.847771 journal@recovery F·1 +15:26:02.848002 journal@recovery recovering @61 +15:26:02.850382 memdb@flush created L0@63 N·2 S·472B "cos..ess,v5":"tes..nfo,v4" +15:26:02.850491 version@stat F·[2] S·942B[942B] Sc·[0.50] +15:26:02.854544 db@janitor F·4 G·0 +15:26:02.854552 db@open done T·6.802972ms +15:26:09.729296 db@close closing +15:26:09.729392 db@close done T·95.18µs +=============== Feb 6, 2021 (GMT) =============== +12:21:53.904083 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +12:21:53.904380 version@stat F·[2] S·942B[942B] Sc·[0.50] +12:21:53.904391 db@open opening +12:21:53.904417 journal@recovery F·1 +12:21:53.905225 journal@recovery recovering @64 +12:21:53.905589 version@stat F·[2] S·942B[942B] Sc·[0.50] +12:21:53.910965 db@janitor F·4 G·0 +12:21:53.910976 db@open done T·6.578518ms +12:21:53.911304 db@close closing +12:21:53.911387 db@close done T·82.205µs +=============== Feb 6, 2021 (GMT) =============== +12:22:02.353974 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +12:22:02.354077 version@stat F·[2] S·942B[942B] Sc·[0.50] +12:22:02.354089 db@open opening +12:22:02.354116 journal@recovery F·1 +12:22:02.354419 journal@recovery recovering @66 +12:22:02.354608 version@stat F·[2] S·942B[942B] Sc·[0.50] +12:22:02.359491 db@janitor F·4 G·0 +12:22:02.359504 db@open done T·5.408186ms +12:22:02.359514 db@close closing +12:22:02.359542 db@close done T·27.662µs +=============== Feb 6, 2021 (GMT) =============== +12:22:07.888198 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +12:22:07.888300 version@stat F·[2] S·942B[942B] Sc·[0.50] +12:22:07.888310 db@open opening +12:22:07.888338 journal@recovery F·1 +12:22:07.888397 journal@recovery recovering @68 +12:22:07.888494 version@stat F·[2] S·942B[942B] Sc·[0.50] +12:22:07.895048 db@janitor F·4 G·0 +12:22:07.895060 db@open done T·6.746979ms +12:22:08.093013 db@close closing +12:22:08.093057 db@close done T·43.222µs +=============== Feb 18, 2021 (GMT) =============== +07:32:13.660053 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +07:32:13.661098 version@stat F·[2] S·942B[942B] Sc·[0.50] +07:32:13.661111 db@open opening +07:32:13.661140 journal@recovery F·1 +07:32:13.661439 journal@recovery recovering @70 +07:32:13.663498 memdb@flush created L0@72 N·2 S·465B "cia..nfo,v7":"cos..ess,v8" +07:32:13.663598 version@stat F·[3] S·1KiB[1KiB] Sc·[0.75] +07:32:13.668369 db@janitor F·5 G·0 +07:32:13.668400 db@open done T·7.285777ms +07:32:13.668491 db@close closing +07:32:13.668557 db@close done T·65.011µs +=============== Feb 18, 2021 (GMT) =============== +07:32:20.349460 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +07:32:20.349568 version@stat F·[3] S·1KiB[1KiB] Sc·[0.75] +07:32:20.349618 db@open opening +07:32:20.349691 journal@recovery F·1 +07:32:20.349769 journal@recovery recovering @73 +07:32:20.349867 version@stat F·[3] S·1KiB[1KiB] Sc·[0.75] +07:32:20.355997 db@janitor F·5 G·0 +07:32:20.356005 db@open done T·6.383828ms +07:32:20.553221 db@close closing +07:32:20.553251 db@close done T·28.713µs +=============== Feb 18, 2021 (GMT) =============== +07:32:30.022753 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +07:32:30.022830 version@stat F·[3] S·1KiB[1KiB] Sc·[0.75] +07:32:30.022842 db@open opening +07:32:30.022870 journal@recovery F·1 +07:32:30.023106 journal@recovery recovering @75 +07:32:30.025727 memdb@flush created L0@77 N·2 S·462B "cos..ess,v11":"foo.info,v10" +07:32:30.025896 version@stat F·[4] S·1KiB[1KiB] Sc·[1.00] +07:32:30.031203 db@janitor F·6 G·0 +07:32:30.031214 db@open done T·8.368455ms +07:32:30.031222 db@close closing +07:32:30.031249 db@close done T·26.625µs +=============== Feb 18, 2021 (GMT) =============== +07:32:36.137856 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +07:32:36.137945 version@stat F·[4] S·1KiB[1KiB] Sc·[1.00] +07:32:36.137955 db@open opening +07:32:36.137988 journal@recovery F·1 +07:32:36.138053 journal@recovery recovering @78 +07:32:36.138160 version@stat F·[4] S·1KiB[1KiB] Sc·[1.00] +07:32:36.144271 db@janitor F·6 G·0 +07:32:36.144281 db@open done T·6.322633ms +07:32:36.144342 table@compaction L0·4 -> L1·0 S·1KiB Q·12 +07:32:36.145937 table@build created L1@82 N·8 S·1KiB "cia..nfo,v7":"val..nfo,v1" +07:32:36.145957 version@stat F·[0 1] S·1KiB[0B 1KiB] Sc·[0.00 0.00] +07:32:36.147223 table@compaction committed F-3 S-606B Ke·0 D·0 T·2.864358ms +07:32:36.147251 table@remove removed @77 +07:32:36.147265 table@remove removed @72 +07:32:36.147280 table@remove removed @63 +07:32:36.147394 table@remove removed @6 +07:32:36.341754 db@close closing +07:32:36.341789 db@close done T·34.217µs +=============== Feb 23, 2021 (GMT) =============== +11:59:56.652297 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:59:56.653267 version@stat F·[0 1] S·1KiB[0B 1KiB] Sc·[0.00 0.00] +11:59:56.653279 db@open opening +11:59:56.653333 journal@recovery F·1 +11:59:56.653684 journal@recovery recovering @80 +11:59:56.655439 memdb@flush created L0@83 N·2 S·491B "bar.info,v13":"cos..ess,v14" +11:59:56.655563 version@stat F·[1 1] S·1KiB[491B 1KiB] Sc·[0.25 0.00] +11:59:56.659803 db@janitor F·4 G·0 +11:59:56.659812 db@open done T·6.529102ms +11:59:56.659952 db@close closing +11:59:56.660013 db@close done T·59.126µs +=============== Feb 23, 2021 (GMT) =============== +12:01:34.578182 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +12:01:34.578308 version@stat F·[1 1] S·1KiB[491B 1KiB] Sc·[0.25 0.00] +12:01:34.578348 db@open opening +12:01:34.578422 journal@recovery F·1 +12:01:34.578796 journal@recovery recovering @84 +12:01:34.579157 version@stat F·[1 1] S·1KiB[491B 1KiB] Sc·[0.25 0.00] +12:01:34.583888 db@janitor F·4 G·0 +12:01:34.583925 db@open done T·5.547338ms +12:01:34.583962 db@close closing +12:01:34.584011 db@close done T·46.636µs +=============== Feb 23, 2021 (GMT) =============== +12:01:34.584060 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +12:01:34.584136 version@stat F·[1 1] S·1KiB[491B 1KiB] Sc·[0.25 0.00] +12:01:34.584166 db@open opening +12:01:34.584195 journal@recovery F·1 +12:01:34.584799 journal@recovery recovering @86 +12:01:34.584896 version@stat F·[1 1] S·1KiB[491B 1KiB] Sc·[0.25 0.00] +12:01:34.590435 db@janitor F·4 G·0 +12:01:34.590445 db@open done T·6.275747ms +12:01:44.922399 db@close closing +12:01:44.922453 db@close done T·53.361µs +=============== Feb 23, 2021 (GMT) =============== +12:01:53.346191 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +12:01:53.346299 version@stat F·[1 1] S·1KiB[491B 1KiB] Sc·[0.25 0.00] +12:01:53.346310 db@open opening +12:01:53.346427 journal@recovery F·1 +12:01:53.346591 journal@recovery recovering @88 +12:01:53.350436 memdb@flush created L0@90 N·2 S·259B "cos..ess,v17":"led..nfo,v16" +12:01:53.350863 version@stat F·[2 1] S·1KiB[750B 1KiB] Sc·[0.50 0.00] +12:01:53.356998 db@janitor F·5 G·0 +12:01:53.357009 db@open done T·10.694071ms +12:01:53.357177 db@close closing +12:01:53.357258 db@close done T·79.894µs +=============== Feb 23, 2021 (GMT) =============== +12:01:57.771688 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +12:01:57.771807 version@stat F·[2 1] S·1KiB[750B 1KiB] Sc·[0.50 0.00] +12:01:57.771818 db@open opening +12:01:57.771844 journal@recovery F·1 +12:01:57.771911 journal@recovery recovering @91 +12:01:57.772211 version@stat F·[2 1] S·1KiB[750B 1KiB] Sc·[0.50 0.00] +12:01:57.777712 db@janitor F·5 G·0 +12:01:57.777726 db@open done T·5.899191ms +12:01:57.777794 db@close closing +12:01:57.777821 db@close done T·26.301µs +=============== Feb 23, 2021 (GMT) =============== +12:02:01.179234 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +12:02:01.179444 version@stat F·[2 1] S·1KiB[750B 1KiB] Sc·[0.50 0.00] +12:02:01.179471 db@open opening +12:02:01.179568 journal@recovery F·1 +12:02:01.180395 journal@recovery recovering @93 +12:02:01.180499 version@stat F·[2 1] S·1KiB[750B 1KiB] Sc·[0.50 0.00] +12:02:01.186898 db@janitor F·5 G·0 +12:02:01.186908 db@open done T·7.433758ms +12:02:01.376649 db@close closing +12:02:01.376744 db@close done T·94.311µs +=============== Feb 23, 2021 (GMT) =============== +12:02:08.325782 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +12:02:08.325880 version@stat F·[2 1] S·1KiB[750B 1KiB] Sc·[0.50 0.00] +12:02:08.325892 db@open opening +12:02:08.325919 journal@recovery F·1 +12:02:08.326096 journal@recovery recovering @95 +12:02:08.328874 memdb@flush created L0@97 N·2 S·189B "cos..ess,d19":"tes..nfo,d20" +12:02:08.329781 version@stat F·[3 1] S·2KiB[939B 1KiB] Sc·[0.75 0.00] +12:02:08.335685 db@janitor F·6 G·0 +12:02:08.335726 db@open done T·9.800531ms +12:02:08.335812 db@close closing +12:02:08.335913 db@close done T·98.185µs +=============== Feb 23, 2021 (GMT) =============== +12:02:10.989199 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +12:02:10.989372 version@stat F·[3 1] S·2KiB[939B 1KiB] Sc·[0.75 0.00] +12:02:10.989381 db@open opening +12:02:10.989413 journal@recovery F·1 +12:02:10.989493 journal@recovery recovering @98 +12:02:10.989823 version@stat F·[3 1] S·2KiB[939B 1KiB] Sc·[0.75 0.00] +12:02:10.997764 db@janitor F·6 G·0 +12:02:10.997775 db@open done T·8.391051ms +12:02:11.186825 db@close closing +12:02:11.186873 db@close done T·46.355µs +=============== Feb 23, 2021 (GMT) =============== +12:02:13.779564 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +12:02:13.779705 version@stat F·[3 1] S·2KiB[939B 1KiB] Sc·[0.75 0.00] +12:02:13.779716 db@open opening +12:02:13.779766 journal@recovery F·1 +12:02:13.780050 journal@recovery recovering @100 +12:02:13.782794 memdb@flush created L0@102 N·2 S·186B "cia..nfo,d23":"cos..ess,d22" +12:02:13.782888 version@stat F·[4 1] S·2KiB[1KiB 1KiB] Sc·[1.00 0.00] +12:02:13.787114 db@janitor F·7 G·0 +12:02:13.787129 db@open done T·7.382544ms +12:02:13.787201 table@compaction L0·4 -> L1·1 S·2KiB Q·24 +12:02:13.787271 db@close closing +12:02:13.789006 table@build created L1@105 N·8 S·1KiB "bar.info,v13":"val..nfo,v1" +12:02:13.789011 table@build exiting +12:02:13.789013 table@build revert @105 +12:02:13.789055 db@close done T·1.783005ms +=============== Feb 23, 2021 (GMT) =============== +12:02:19.245131 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +12:02:19.245285 version@stat F·[4 1] S·2KiB[1KiB 1KiB] Sc·[1.00 0.00] +12:02:19.245315 db@open opening +12:02:19.245368 journal@recovery F·1 +12:02:19.245465 journal@recovery recovering @103 +12:02:19.245858 version@stat F·[4 1] S·2KiB[1KiB 1KiB] Sc·[1.00 0.00] +12:02:19.251449 db@janitor F·7 G·0 +12:02:19.251465 db@open done T·6.140479ms +12:02:19.251485 table@compaction L0·4 -> L1·1 S·2KiB Q·24 +12:02:19.251521 db@close closing +12:02:19.251592 db@close done T·70.226µs +=============== Feb 23, 2021 (GMT) =============== +12:02:21.580113 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +12:02:21.580210 version@stat F·[4 1] S·2KiB[1KiB 1KiB] Sc·[1.00 0.00] +12:02:21.580222 db@open opening +12:02:21.580272 journal@recovery F·1 +12:02:21.580647 journal@recovery recovering @105 +12:02:21.580747 version@stat F·[4 1] S·2KiB[1KiB 1KiB] Sc·[1.00 0.00] +12:02:21.587123 db@janitor F·7 G·0 +12:02:21.587130 db@open done T·6.905846ms +12:02:21.587221 table@compaction L0·4 -> L1·1 S·2KiB Q·24 +12:02:21.589889 table@build created L1@109 N·8 S·1KiB "bar.info,v13":"val..nfo,v1" +12:02:21.589929 version@stat F·[0 1] S·1KiB[0B 1KiB] Sc·[0.00 0.00] +12:02:21.591275 table@compaction committed F-4 S-1KiB Ke·0 D·8 T·4.039289ms +12:02:21.591357 table@remove removed @102 +12:02:21.591414 table@remove removed @97 +12:02:21.591428 table@remove removed @90 +12:02:21.591440 table@remove removed @83 +12:02:21.591472 table@remove removed @82 +12:02:21.777758 db@close closing +12:02:21.777800 db@close done T·40.787µs +=============== Feb 23, 2021 (GMT) =============== +12:02:22.900722 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +12:02:22.900859 version@stat F·[0 1] S·1KiB[0B 1KiB] Sc·[0.00 0.00] +12:02:22.900892 db@open opening +12:02:22.900963 journal@recovery F·1 +12:02:22.901083 journal@recovery recovering @107 +12:02:22.904868 memdb@flush created L0@110 N·2 S·193B "cos..ess,d25":"val..nfo,d26" +12:02:22.905267 version@stat F·[1 1] S·1KiB[193B 1KiB] Sc·[0.25 0.00] +12:02:22.909786 db@janitor F·4 G·0 +12:02:22.909799 db@open done T·8.899965ms +12:02:22.909931 db@close closing +12:02:22.910008 db@close done T·74.647µs +=============== Feb 23, 2021 (GMT) =============== +12:02:53.139966 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +12:02:53.140102 version@stat F·[1 1] S·1KiB[193B 1KiB] Sc·[0.25 0.00] +12:02:53.140135 db@open opening +12:02:53.140206 journal@recovery F·1 +12:02:53.140586 journal@recovery recovering @111 +12:02:53.141053 version@stat F·[1 1] S·1KiB[193B 1KiB] Sc·[0.25 0.00] +12:02:53.147675 db@janitor F·4 G·0 +12:02:53.147687 db@open done T·7.546001ms +12:02:53.147750 db@close closing +12:02:53.147818 db@close done T·67.754µs +=============== Feb 23, 2021 (GMT) =============== +12:02:53.147913 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +12:02:53.147982 version@stat F·[1 1] S·1KiB[193B 1KiB] Sc·[0.25 0.00] +12:02:53.147993 db@open opening +12:02:53.148043 journal@recovery F·1 +12:02:53.148101 journal@recovery recovering @113 +12:02:53.148192 version@stat F·[1 1] S·1KiB[193B 1KiB] Sc·[0.25 0.00] +12:02:53.152906 db@janitor F·4 G·0 +12:02:53.152912 db@open done T·4.91707ms +12:02:53.156922 db@close closing +12:02:53.156949 db@close done T·25.968µs +=============== Feb 23, 2021 (GMT) =============== +12:03:24.147022 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +12:03:24.147113 version@stat F·[1 1] S·1KiB[193B 1KiB] Sc·[0.25 0.00] +12:03:24.147123 db@open opening +12:03:24.147195 journal@recovery F·1 +12:03:24.147542 journal@recovery recovering @115 +12:03:24.150459 memdb@flush created L0@117 N·2 S·244B "cos..ess,v29":"pub..nfo,v28" +12:03:24.150556 version@stat F·[2 1] S·1KiB[437B 1KiB] Sc·[0.50 0.00] +12:03:24.156079 db@janitor F·5 G·0 +12:03:24.156116 db@open done T·8.964543ms +12:03:24.156215 db@close closing +12:03:24.156330 db@close done T·113.154µs +=============== Feb 23, 2021 (GMT) =============== +12:03:33.230269 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +12:03:33.230428 version@stat F·[2 1] S·1KiB[437B 1KiB] Sc·[0.50 0.00] +12:03:33.230456 db@open opening +12:03:33.230505 journal@recovery F·1 +12:03:33.230859 journal@recovery recovering @118 +12:03:33.231123 version@stat F·[2 1] S·1KiB[437B 1KiB] Sc·[0.50 0.00] +12:03:33.237886 db@janitor F·5 G·0 +12:03:33.237932 db@open done T·7.464889ms +12:03:33.238009 db@close closing +12:03:33.238077 db@close done T·67.991µs +=============== Feb 23, 2021 (GMT) =============== +12:03:33.238135 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +12:03:33.238190 version@stat F·[2 1] S·1KiB[437B 1KiB] Sc·[0.50 0.00] +12:03:33.238200 db@open opening +12:03:33.238226 journal@recovery F·1 +12:03:33.238295 journal@recovery recovering @120 +12:03:33.238459 version@stat F·[2 1] S·1KiB[437B 1KiB] Sc·[0.50 0.00] +12:03:33.242714 db@janitor F·5 G·0 +12:03:33.242723 db@open done T·4.520893ms +12:03:33.246526 db@close closing +12:03:33.246576 db@close done T·49.286µs +=============== Feb 23, 2021 (GMT) =============== +12:03:36.732039 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +12:03:36.732132 version@stat F·[2 1] S·1KiB[437B 1KiB] Sc·[0.50 0.00] +12:03:36.732143 db@open opening +12:03:36.732193 journal@recovery F·1 +12:03:36.732321 journal@recovery recovering @122 +12:03:36.734960 memdb@flush created L0@124 N·2 S·244B "cos..ess,v32":"pub..nfo,v31" +12:03:36.735282 version@stat F·[3 1] S·1KiB[681B 1KiB] Sc·[0.75 0.00] +12:03:36.740852 db@janitor F·6 G·0 +12:03:36.740890 db@open done T·8.717358ms +12:03:36.741044 db@close closing +12:03:36.741134 db@close done T·87.869µs +=============== Feb 23, 2021 (GMT) =============== +12:03:56.009876 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +12:03:56.009989 version@stat F·[3 1] S·1KiB[681B 1KiB] Sc·[0.75 0.00] +12:03:56.010002 db@open opening +12:03:56.010034 journal@recovery F·1 +12:03:56.010178 journal@recovery recovering @125 +12:03:56.011128 version@stat F·[3 1] S·1KiB[681B 1KiB] Sc·[0.75 0.00] +12:03:56.018052 db@janitor F·6 G·0 +12:03:56.018064 db@open done T·8.05417ms +12:03:56.018173 db@close closing +12:03:56.018224 db@close done T·49.879µs +=============== Feb 23, 2021 (GMT) =============== +12:03:58.983153 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +12:03:58.983257 version@stat F·[3 1] S·1KiB[681B 1KiB] Sc·[0.75 0.00] +12:03:58.983268 db@open opening +12:03:58.983297 journal@recovery F·1 +12:03:58.983885 journal@recovery recovering @127 +12:03:58.983986 version@stat F·[3 1] S·1KiB[681B 1KiB] Sc·[0.75 0.00] +12:03:58.991844 db@janitor F·6 G·0 +12:03:58.991851 db@open done T·8.580014ms +12:03:59.181560 db@close closing +12:03:59.181637 db@close done T·76.045µs +=============== Feb 23, 2021 (GMT) =============== +12:04:10.259722 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +12:04:10.259852 version@stat F·[3 1] S·1KiB[681B 1KiB] Sc·[0.75 0.00] +12:04:10.259869 db@open opening +12:04:10.259919 journal@recovery F·1 +12:04:10.260104 journal@recovery recovering @129 +12:04:10.264224 memdb@flush created L0@131 N·2 S·187B "cos..ess,d34":"foo.info,d35" +12:04:10.264492 version@stat F·[4 1] S·1KiB[868B 1KiB] Sc·[1.00 0.00] +12:04:10.268582 db@janitor F·7 G·0 +12:04:10.268595 db@open done T·8.720601ms +12:04:10.268655 table@compaction L0·4 -> L1·1 S·1KiB Q·36 +12:04:10.268669 db@close closing +12:04:10.268830 db@close done T·159.948µs +=============== Feb 23, 2021 (GMT) =============== +12:04:10.268891 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +12:04:10.269025 version@stat F·[4 1] S·1KiB[868B 1KiB] Sc·[1.00 0.00] +12:04:10.269034 db@open opening +12:04:10.269089 journal@recovery F·1 +12:04:10.269152 journal@recovery recovering @132 +12:04:10.269259 version@stat F·[4 1] S·1KiB[868B 1KiB] Sc·[1.00 0.00] +12:04:10.274436 db@janitor F·7 G·0 +12:04:10.274466 db@open done T·5.404186ms +12:04:10.274543 table@compaction L0·4 -> L1·1 S·1KiB Q·36 +12:04:10.277245 table@build created L1@136 N·8 S·825B "bar.info,v13":"pub..nfo,v31" +12:04:10.277287 version@stat F·[0 1] S·825B[0B 825B] Sc·[0.00 0.00] +12:04:10.278388 db@close closing +12:04:10.280880 table@commit exiting +12:04:10.280907 db@close done T·2.542424ms +=============== Feb 23, 2021 (GMT) =============== +12:04:12.868499 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +12:04:12.868628 version@stat F·[0 1] S·825B[0B 825B] Sc·[0.00 0.00] +12:04:12.868640 db@open opening +12:04:12.868670 journal@recovery F·1 +12:04:12.868785 journal@recovery recovering @134 +12:04:12.870434 memdb@flush created L0@137 N·2 S·244B "cos..ess,v38":"pub..nfo,v37" +12:04:12.871017 version@stat F·[1 1] S·1KiB[244B 825B] Sc·[0.25 0.00] +12:04:12.876243 db@janitor F·9 G·5 +12:04:12.876251 db@janitor removing table-124 +12:04:12.876290 db@janitor removing table-110 +12:04:12.876302 db@janitor removing table-109 +12:04:12.876330 db@janitor removing table-117 +12:04:12.876340 db@janitor removing table-131 +12:04:12.876381 db@open done T·7.712682ms +12:04:12.876440 db@close closing +12:04:12.876498 db@close done T·55.873µs +=============== Feb 23, 2021 (GMT) =============== +12:09:38.966259 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +12:09:38.966450 version@stat F·[1 1] S·1KiB[244B 825B] Sc·[0.25 0.00] +12:09:38.966463 db@open opening +12:09:38.966490 journal@recovery F·1 +12:09:38.966746 journal@recovery recovering @138 +12:09:38.967252 version@stat F·[1 1] S·1KiB[244B 825B] Sc·[0.25 0.00] +12:09:38.974464 db@janitor F·4 G·0 +12:09:38.974477 db@open done T·8.005768ms +12:09:56.196454 db@close closing +12:09:56.196575 db@close done T·142.606µs +=============== Feb 23, 2021 (GMT) =============== +12:10:09.568902 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +12:10:09.568981 version@stat F·[1 1] S·1KiB[244B 825B] Sc·[0.25 0.00] +12:10:09.568993 db@open opening +12:10:09.569022 journal@recovery F·1 +12:10:09.569291 journal@recovery recovering @140 +12:10:09.569781 version@stat F·[1 1] S·1KiB[244B 825B] Sc·[0.25 0.00] +12:10:09.575840 db@janitor F·4 G·0 +12:10:09.575848 db@open done T·6.851269ms +12:10:23.290522 db@close closing +12:10:23.290590 db@close done T·66.518µs +=============== Feb 23, 2021 (GMT) =============== +12:11:01.674005 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +12:11:01.674086 version@stat F·[1 1] S·1KiB[244B 825B] Sc·[0.25 0.00] +12:11:01.674098 db@open opening +12:11:01.674128 journal@recovery F·1 +12:11:01.674359 journal@recovery recovering @142 +12:11:01.674814 version@stat F·[1 1] S·1KiB[244B 825B] Sc·[0.25 0.00] +12:11:01.680965 db@janitor F·4 G·0 +12:11:01.680980 db@open done T·6.874747ms +12:11:06.655715 db@close closing +12:11:06.655759 db@close done T·43.852µs +=============== Feb 23, 2021 (GMT) =============== +12:19:52.269690 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +12:19:52.269780 version@stat F·[1 1] S·1KiB[244B 825B] Sc·[0.25 0.00] +12:19:52.269792 db@open opening +12:19:52.269826 journal@recovery F·1 +12:19:52.270051 journal@recovery recovering @144 +12:19:52.270585 version@stat F·[1 1] S·1KiB[244B 825B] Sc·[0.25 0.00] +12:19:52.276899 db@janitor F·4 G·0 +12:19:52.276939 db@open done T·7.116495ms +12:19:59.249868 db@close closing +12:19:59.249968 db@close done T·99.117µs +=============== Feb 23, 2021 (GMT) =============== +12:20:30.569407 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +12:20:30.569504 version@stat F·[1 1] S·1KiB[244B 825B] Sc·[0.25 0.00] +12:20:30.569516 db@open opening +12:20:30.569545 journal@recovery F·1 +12:20:30.569730 journal@recovery recovering @146 +12:20:30.570245 version@stat F·[1 1] S·1KiB[244B 825B] Sc·[0.25 0.00] +12:20:30.577100 db@janitor F·4 G·0 +12:20:30.577111 db@open done T·7.591098ms +=============== Feb 23, 2021 (GMT) =============== +12:20:35.223490 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +12:20:35.223588 version@stat F·[1 1] S·1KiB[244B 825B] Sc·[0.25 0.00] +12:20:35.223601 db@open opening +12:20:35.223630 journal@recovery F·1 +12:20:35.223986 journal@recovery recovering @148 +12:20:35.224401 version@stat F·[1 1] S·1KiB[244B 825B] Sc·[0.25 0.00] +12:20:35.229848 db@janitor F·4 G·0 +12:20:35.229856 db@open done T·6.250812ms +12:20:41.049391 db@close closing +12:20:41.049441 db@close done T·49.18µs +=============== Feb 23, 2021 (GMT) =============== +12:21:45.804793 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +12:21:45.804915 version@stat F·[1 1] S·1KiB[244B 825B] Sc·[0.25 0.00] +12:21:45.804928 db@open opening +12:21:45.804961 journal@recovery F·1 +12:21:45.805201 journal@recovery recovering @150 +12:21:45.805681 version@stat F·[1 1] S·1KiB[244B 825B] Sc·[0.25 0.00] +12:21:45.810888 db@janitor F·4 G·0 +12:21:45.810920 db@open done T·5.985873ms +12:21:49.489917 db@close closing +12:21:49.490008 db@close done T·89.528µs +=============== Feb 26, 2021 (GMT) =============== +11:30:44.083018 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:30:44.084062 version@stat F·[1 1] S·1KiB[244B 825B] Sc·[0.25 0.00] +11:30:44.084075 db@open opening +11:30:44.084102 journal@recovery F·1 +11:30:44.084383 journal@recovery recovering @152 +11:30:44.084768 version@stat F·[1 1] S·1KiB[244B 825B] Sc·[0.25 0.00] +11:30:44.090432 db@janitor F·4 G·0 +11:30:44.090476 db@open done T·6.381184ms +11:30:44.090566 db@close closing +11:30:44.090613 db@close done T·44.34µs +=============== Feb 26, 2021 (GMT) =============== +11:32:36.352559 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:32:36.352641 version@stat F·[1 1] S·1KiB[244B 825B] Sc·[0.25 0.00] +11:32:36.352653 db@open opening +11:32:36.352681 journal@recovery F·1 +11:32:36.352756 journal@recovery recovering @154 +11:32:36.353034 version@stat F·[1 1] S·1KiB[244B 825B] Sc·[0.25 0.00] +11:32:36.360804 db@janitor F·4 G·0 +11:32:36.360816 db@open done T·8.15837ms +11:32:36.360904 db@close closing +11:32:36.360960 db@close done T·54.048µs +=============== Feb 26, 2021 (GMT) =============== +11:32:48.449675 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:32:48.449787 version@stat F·[1 1] S·1KiB[244B 825B] Sc·[0.25 0.00] +11:32:48.449820 db@open opening +11:32:48.449847 journal@recovery F·1 +11:32:48.449955 journal@recovery recovering @156 +11:32:48.450282 version@stat F·[1 1] S·1KiB[244B 825B] Sc·[0.25 0.00] +11:32:48.456194 db@janitor F·4 G·0 +11:32:48.456235 db@open done T·6.384513ms +11:32:48.456367 db@close closing +11:32:48.456478 db@close done T·109.034µs +=============== Feb 26, 2021 (GMT) =============== +11:34:15.269223 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:34:15.269382 version@stat F·[1 1] S·1KiB[244B 825B] Sc·[0.25 0.00] +11:34:15.269414 db@open opening +11:34:15.269464 journal@recovery F·1 +11:34:15.269563 journal@recovery recovering @158 +11:34:15.269872 version@stat F·[1 1] S·1KiB[244B 825B] Sc·[0.25 0.00] +11:34:15.275610 db@janitor F·4 G·0 +11:34:15.275622 db@open done T·6.200818ms +11:34:15.275707 db@close closing +11:34:15.275752 db@close done T·44.471µs +=============== Feb 26, 2021 (GMT) =============== +11:34:32.038701 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:34:32.038798 version@stat F·[1 1] S·1KiB[244B 825B] Sc·[0.25 0.00] +11:34:32.038810 db@open opening +11:34:32.038837 journal@recovery F·1 +11:34:32.039081 journal@recovery recovering @160 +11:34:32.039560 version@stat F·[1 1] S·1KiB[244B 825B] Sc·[0.25 0.00] +11:34:32.045125 db@janitor F·4 G·0 +11:34:32.045132 db@open done T·6.318174ms +11:34:52.928799 db@close closing +11:34:52.928908 db@close done T·94.101µs +=============== Feb 26, 2021 (GMT) =============== +19:42:33.585125 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +19:42:33.585220 version@stat F·[1 1] S·1KiB[244B 825B] Sc·[0.25 0.00] +19:42:33.585232 db@open opening +19:42:33.585283 journal@recovery F·1 +19:42:33.585544 journal@recovery recovering @162 +19:42:33.585964 version@stat F·[1 1] S·1KiB[244B 825B] Sc·[0.25 0.00] +19:42:33.592890 db@janitor F·4 G·0 +19:42:33.592928 db@open done T·7.666705ms +19:42:33.592996 db@close closing +19:42:33.593063 db@close done T·63.906µs +=============== Feb 27, 2021 (GMT) =============== +17:05:01.817733 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +17:05:01.817819 version@stat F·[1 1] S·1KiB[244B 825B] Sc·[0.25 0.00] +17:05:01.817830 db@open opening +17:05:01.817855 journal@recovery F·1 +17:05:01.818108 journal@recovery recovering @164 +17:05:01.818567 version@stat F·[1 1] S·1KiB[244B 825B] Sc·[0.25 0.00] +17:05:01.824986 db@janitor F·4 G·0 +17:05:01.825024 db@open done T·7.162696ms +17:05:01.825107 db@close closing +17:05:01.825221 db@close done T·111.618µs diff --git a/client/keys/testdata/keys/keys.db/MANIFEST-000005 b/client/keys/testdata/keys/keys.db/MANIFEST-000005 deleted file mode 100644 index a9e8a261c7882e802f65360dc49782db7df6fb77..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41 wcmYcef4W17fss)vC$%g!CnZVGsj?)sJhM2}IX|}`u_&=5zle#2nT>@304?eb82|tP diff --git a/client/keys/testdata/keys/keys.db/MANIFEST-000167 b/client/keys/testdata/keys/keys.db/MANIFEST-000167 new file mode 100644 index 0000000000000000000000000000000000000000..410bbeb71a22f2eb137150572ce9cdb5c27d6da9 GIT binary patch literal 195 zcmaDPeBl2c21Z7yoYb<^oRlOzr^=Gl^338?=ltA)#G=HK{351hjLa(-S=3n>#L5zL zGE+cedYO4?`3zDFV8G7M$@qoQHaWjIH^100D=Q= ztUNWf)Wkf!#N6C6B~dRiC8a2}xR_B5VuoNrX_7J6R7O>(sf- Date: Mon, 1 Mar 2021 14:01:05 +0100 Subject: [PATCH 135/214] Allow REST endpoint to query txs with multisig (#8730) * Fix unpack stdtx * Add test for multisig * remove println * Add changelog * Better UnpackInterfaces Co-authored-by: Alessio Treglia --- CHANGELOG.md | 1 + x/auth/client/rest/rest_test.go | 105 ++++++++++++++++++++++++++++++ x/auth/legacy/legacytx/stdsign.go | 4 -- x/auth/legacy/legacytx/stdtx.go | 22 ++++++- 4 files changed, 125 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cd4682f2fbc0..9fdd0a915115 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -78,6 +78,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (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 * (server) [\#8641](https://github.com/cosmos/cosmos-sdk/pull/8641) Fix Tendermint and application configuration reading from file +* (rest) [\#8730](https://github.com/cosmos/cosmos-sdk/pull/8730) Fix querying txs with multisigs on legacy REST endpoints. * (client/keys) [\#8639] (https://github.com/cosmos/cosmos-sdk/pull/8639) Fix keys migrate for mulitisig, offline, and ledger keys. The migrate command now takes a positional old_home_dir argument. ## [v0.41.3](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.41.3) - 2021-02-18 diff --git a/x/auth/client/rest/rest_test.go b/x/auth/client/rest/rest_test.go index cfca5275087a..9ecb3e842ff6 100644 --- a/x/auth/client/rest/rest_test.go +++ b/x/auth/client/rest/rest_test.go @@ -2,6 +2,7 @@ package rest_test import ( "fmt" + "strings" "testing" "github.com/spf13/cobra" @@ -11,6 +12,8 @@ import ( "github.com/cosmos/cosmos-sdk/client/tx" "github.com/cosmos/cosmos-sdk/crypto/hd" "github.com/cosmos/cosmos-sdk/crypto/keyring" + kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" "github.com/cosmos/cosmos-sdk/testutil" clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" "github.com/cosmos/cosmos-sdk/testutil/network" @@ -22,6 +25,7 @@ import ( authclient "github.com/cosmos/cosmos-sdk/x/auth/client" authcli "github.com/cosmos/cosmos-sdk/x/auth/client/cli" authrest "github.com/cosmos/cosmos-sdk/x/auth/client/rest" + authtest "github.com/cosmos/cosmos-sdk/x/auth/client/testutil" "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" @@ -52,6 +56,16 @@ func (s *IntegrationTestSuite) SetupSuite() { _, _, err := kb.NewMnemonic("newAccount", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) s.Require().NoError(err) + account1, _, err := kb.NewMnemonic("newAccount1", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) + s.Require().NoError(err) + + account2, _, err := kb.NewMnemonic("newAccount2", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) + s.Require().NoError(err) + + multi := kmultisig.NewLegacyAminoPubKey(2, []cryptotypes.PubKey{account1.GetPubKey(), account2.GetPubKey()}) + _, err = kb.SaveMultisig("multi", multi) + s.Require().NoError(err) + _, err = s.network.WaitForHeight(1) s.Require().NoError(err) @@ -560,6 +574,97 @@ func (s *IntegrationTestSuite) TestLegacyRestErrMessages() { } } +// TestLegacyMultiSig creates a legacy multisig transaction, and makes sure +// we can query it via the legacy REST endpoint. +// ref: https://github.com/cosmos/cosmos-sdk/issues/8679 +func (s *IntegrationTestSuite) TestLegacyMultisig() { + val1 := *s.network.Validators[0] + + // Generate 2 accounts and a multisig. + account1, err := val1.ClientCtx.Keyring.Key("newAccount1") + s.Require().NoError(err) + + account2, err := val1.ClientCtx.Keyring.Key("newAccount2") + s.Require().NoError(err) + + multisigInfo, err := val1.ClientCtx.Keyring.Key("multi") + s.Require().NoError(err) + + // Send coins from validator to multisig. + sendTokens := sdk.NewInt64Coin(s.cfg.BondDenom, 1000) + _, err = bankcli.MsgSendExec( + val1.ClientCtx, + val1.Address, + multisigInfo.GetAddress(), + 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(s.network.WaitForNextBlock()) + + // Generate multisig transaction to a random address. + _, _, recipient := testdata.KeyTestPubAddr() + multiGeneratedTx, err := bankcli.MsgSendExec( + val1.ClientCtx, + multisigInfo.GetAddress(), + recipient, + sdk.NewCoins( + sdk.NewInt64Coin(s.cfg.BondDenom, 5), + ), + 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) + + // Save tx to file + multiGeneratedTxFile := testutil.WriteToNewTempFile(s.T(), multiGeneratedTx.String()) + + // Sign with account1 + val1.ClientCtx.HomeDir = strings.Replace(val1.ClientCtx.HomeDir, "simd", "simcli", 1) + account1Signature, err := authtest.TxSignExec(val1.ClientCtx, account1.GetAddress(), multiGeneratedTxFile.Name(), "--multisig", multisigInfo.GetAddress().String()) + s.Require().NoError(err) + + sign1File := testutil.WriteToNewTempFile(s.T(), account1Signature.String()) + + // Sign with account1 + account2Signature, err := authtest.TxSignExec(val1.ClientCtx, account2.GetAddress(), multiGeneratedTxFile.Name(), "--multisig", multisigInfo.GetAddress().String()) + s.Require().NoError(err) + + sign2File := testutil.WriteToNewTempFile(s.T(), account2Signature.String()) + + // Does not work in offline mode. + _, err = authtest.TxMultiSignExec(val1.ClientCtx, multisigInfo.GetName(), multiGeneratedTxFile.Name(), "--offline", sign1File.Name(), sign2File.Name()) + s.Require().EqualError(err, fmt.Sprintf("couldn't verify signature for address %s", account1.GetAddress())) + + val1.ClientCtx.Offline = false + multiSigWith2Signatures, err := authtest.TxMultiSignExec(val1.ClientCtx, multisigInfo.GetName(), multiGeneratedTxFile.Name(), sign1File.Name(), sign2File.Name()) + s.Require().NoError(err) + + // Write the output to disk + signedTxFile := testutil.WriteToNewTempFile(s.T(), multiSigWith2Signatures.String()) + + _, err = authtest.TxValidateSignaturesExec(val1.ClientCtx, signedTxFile.Name()) + s.Require().NoError(err) + + val1.ClientCtx.BroadcastMode = flags.BroadcastBlock + out, err := authtest.TxBroadcastExec(val1.ClientCtx, signedTxFile.Name()) + s.Require().NoError(err) + + s.Require().NoError(s.network.WaitForNextBlock()) + + var txRes sdk.TxResponse + err = val1.ClientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), &txRes) + s.Require().NoError(err) + s.Require().Equal(uint32(0), txRes.Code) + + s.testQueryTx(txRes.Height, txRes.TxHash, recipient.String()) +} + func TestIntegrationTestSuite(t *testing.T) { suite.Run(t, new(IntegrationTestSuite)) } diff --git a/x/auth/legacy/legacytx/stdsign.go b/x/auth/legacy/legacytx/stdsign.go index 466981369624..f87900620d37 100644 --- a/x/auth/legacy/legacytx/stdsign.go +++ b/x/auth/legacy/legacytx/stdsign.go @@ -5,7 +5,6 @@ import ( "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec/legacy" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" "github.com/cosmos/cosmos-sdk/crypto/types/multisig" sdk "github.com/cosmos/cosmos-sdk/types" @@ -13,9 +12,6 @@ import ( "github.com/cosmos/cosmos-sdk/types/tx/signing" ) -// Interface implementation checks -var _ codectypes.UnpackInterfacesMessage = StdTx{} - // StdSignDoc is replay-prevention structure. // It includes the result of msg.GetSignBytes(), // as well as the ChainID (prevent cross chain replay) diff --git a/x/auth/legacy/legacytx/stdtx.go b/x/auth/legacy/legacytx/stdtx.go index 8cb3fb6997cf..2b8a6c0e0547 100644 --- a/x/auth/legacy/legacytx/stdtx.go +++ b/x/auth/legacy/legacytx/stdtx.go @@ -16,9 +16,12 @@ import ( // Interface implementation checks var ( - _ sdk.Tx = (*StdTx)(nil) - _ sdk.TxWithMemo = (*StdTx)(nil) - _ sdk.FeeTx = (*StdTx)(nil) + _ sdk.Tx = (*StdTx)(nil) + _ sdk.TxWithMemo = (*StdTx)(nil) + _ sdk.FeeTx = (*StdTx)(nil) + _ codectypes.UnpackInterfacesMessage = (*StdTx)(nil) + + _ codectypes.UnpackInterfacesMessage = (*StdSignature)(nil) ) // StdFee includes the amount of coins paid in fees and the maximum @@ -116,6 +119,10 @@ func (ss StdSignature) MarshalYAML() (interface{}, error) { return string(bz), err } +func (ss StdSignature) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { + return codectypes.UnpackInterfaces(ss.PubKey, unpacker) +} + // StdTx is the legacy transaction format for wrapping a Msg with Fee and Signatures. // It only works with Amino, please prefer the new protobuf Tx in types/tx. // NOTE: the first signature is the fee payer (Signatures must not be nil). @@ -277,5 +284,14 @@ func (tx StdTx) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { return err } } + + // Signatures contain PubKeys, which need to be unpacked. + for _, s := range tx.Signatures { + err := codectypes.UnpackInterfaces(s, unpacker) + if err != nil { + return err + } + } + return nil } From 0792db78b888c995b094388947bee7f7ab5614ed Mon Sep 17 00:00:00 2001 From: Damian Nolan Date: Mon, 1 Mar 2021 15:13:37 +0100 Subject: [PATCH 136/214] minor channel fixes (#8665) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Consolidating codec.go registrations. Moving Acknowledgement result/error to its own file * Updating CHANGELOG.md with #7949 improvement as requested * revert removing acknowledgement proto to its own file * update changelog * remove unnecessary pb.go file Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com> --- CHANGELOG.md | 3 +- .../core/04-channel/types/acknowledgement.go | 50 +++++++++++++++ .../04-channel/types/acknowledgement_test.go | 63 +++++++++++++++++++ x/ibc/core/04-channel/types/channel.go | 45 ------------- x/ibc/core/04-channel/types/channel_test.go | 60 ------------------ x/ibc/core/04-channel/types/codec.go | 13 +--- 6 files changed, 116 insertions(+), 118 deletions(-) create mode 100644 x/ibc/core/04-channel/types/acknowledgement.go create mode 100644 x/ibc/core/04-channel/types/acknowledgement_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 9fdd0a915115..3cf3e8e366e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,11 +65,10 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (x/bank) [\#8614](https://github.com/cosmos/cosmos-sdk/issues/8614) Add `Name` and `Symbol` fields to denom metadata * (x/auth) [\#8522](https://github.com/cosmos/cosmos-sdk/pull/8522) Allow to query all stored accounts +* (x/ibc) [\#7949](https://github.com/cosmos/cosmos-sdk/issues/7949) Standardized channel `Acknowledgement` moved to its own file. Codec registration redundancy removed. * (crypto/types) [\#8600](https://github.com/cosmos/cosmos-sdk/pull/8600) `CompactBitArray`: optimize the `NumTrueBitsBefore` method and add an `Equal` method. * (store/cachekv), (x/bank/types) [\#8719](https://github.com/cosmos/cosmos-sdk/pull/8719) algorithmically fix pathologically slow code - - ### Bug Fixes * (keyring) [#\8635](https://github.com/cosmos/cosmos-sdk/issues/8635) Remove hardcoded default passphrase value on `NewMnemonic` diff --git a/x/ibc/core/04-channel/types/acknowledgement.go b/x/ibc/core/04-channel/types/acknowledgement.go new file mode 100644 index 000000000000..a3f677ab4410 --- /dev/null +++ b/x/ibc/core/04-channel/types/acknowledgement.go @@ -0,0 +1,50 @@ +package types + +import ( + "strings" + + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +// NewResultAcknowledgement returns a new instance of Acknowledgement using an Acknowledgement_Result +// type in the Response field. +func NewResultAcknowledgement(result []byte) Acknowledgement { + return Acknowledgement{ + Response: &Acknowledgement_Result{ + Result: result, + }, + } +} + +// NewErrorAcknowledgement returns a new instance of Acknowledgement using an Acknowledgement_Error +// type in the Response field. +func NewErrorAcknowledgement(err string) Acknowledgement { + return Acknowledgement{ + Response: &Acknowledgement_Error{ + Error: err, + }, + } +} + +// GetBytes is a helper for serialising acknowledgements +func (ack Acknowledgement) GetBytes() []byte { + return sdk.MustSortJSON(SubModuleCdc.MustMarshalJSON(&ack)) +} + +// ValidateBasic performs a basic validation of the acknowledgement +func (ack Acknowledgement) ValidateBasic() error { + switch resp := ack.Response.(type) { + case *Acknowledgement_Result: + if len(resp.Result) == 0 { + return sdkerrors.Wrap(ErrInvalidAcknowledgement, "acknowledgement result cannot be empty") + } + case *Acknowledgement_Error: + if strings.TrimSpace(resp.Error) == "" { + return sdkerrors.Wrap(ErrInvalidAcknowledgement, "acknowledgement error cannot be empty") + } + default: + return sdkerrors.Wrapf(ErrInvalidAcknowledgement, "unsupported acknowledgement response field type %T", resp) + } + return nil +} diff --git a/x/ibc/core/04-channel/types/acknowledgement_test.go b/x/ibc/core/04-channel/types/acknowledgement_test.go new file mode 100644 index 000000000000..58074dd7bde5 --- /dev/null +++ b/x/ibc/core/04-channel/types/acknowledgement_test.go @@ -0,0 +1,63 @@ +package types_test + +import "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" + +// tests acknowledgement.ValidateBasic and acknowledgement.GetBytes +func (suite TypesTestSuite) TestAcknowledgement() { + testCases := []struct { + name string + ack types.Acknowledgement + expPass bool + }{ + { + "valid successful ack", + types.NewResultAcknowledgement([]byte("success")), + true, + }, + { + "valid failed ack", + types.NewErrorAcknowledgement("error"), + true, + }, + { + "empty successful ack", + types.NewResultAcknowledgement([]byte{}), + false, + }, + { + "empty faied ack", + types.NewErrorAcknowledgement(" "), + false, + }, + { + "nil response", + types.Acknowledgement{ + Response: nil, + }, + false, + }, + } + + for _, tc := range testCases { + tc := tc + + suite.Run(tc.name, func() { + suite.SetupTest() + + err := tc.ack.ValidateBasic() + + if tc.expPass { + suite.Require().NoError(err) + } else { + suite.Require().Error(err) + } + + // expect all acks to be able to be marshaled + suite.NotPanics(func() { + bz := tc.ack.GetBytes() + suite.Require().NotNil(bz) + }) + }) + } + +} diff --git a/x/ibc/core/04-channel/types/channel.go b/x/ibc/core/04-channel/types/channel.go index 8513a8123df8..b808a220b303 100644 --- a/x/ibc/core/04-channel/types/channel.go +++ b/x/ibc/core/04-channel/types/channel.go @@ -1,9 +1,6 @@ package types import ( - "strings" - - sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" @@ -128,45 +125,3 @@ func (ic IdentifiedChannel) ValidateBasic() error { channel := NewChannel(ic.State, ic.Ordering, ic.Counterparty, ic.ConnectionHops, ic.Version) return channel.ValidateBasic() } - -// NewResultAcknowledgement returns a new instance of Acknowledgement using an Acknowledgement_Result -// type in the Response field. -func NewResultAcknowledgement(result []byte) Acknowledgement { - return Acknowledgement{ - Response: &Acknowledgement_Result{ - Result: result, - }, - } -} - -// NewErrorAcknowledgement returns a new instance of Acknowledgement using an Acknowledgement_Error -// type in the Response field. -func NewErrorAcknowledgement(err string) Acknowledgement { - return Acknowledgement{ - Response: &Acknowledgement_Error{ - Error: err, - }, - } -} - -// GetBytes is a helper for serialising acknowledgements -func (ack Acknowledgement) GetBytes() []byte { - return sdk.MustSortJSON(SubModuleCdc.MustMarshalJSON(&ack)) -} - -// ValidateBasic performs a basic validation of the acknowledgement -func (ack Acknowledgement) ValidateBasic() error { - switch resp := ack.Response.(type) { - case *Acknowledgement_Result: - if len(resp.Result) == 0 { - return sdkerrors.Wrap(ErrInvalidAcknowledgement, "acknowledgement result cannot be empty") - } - case *Acknowledgement_Error: - if strings.TrimSpace(resp.Error) == "" { - return sdkerrors.Wrap(ErrInvalidAcknowledgement, "acknowledgement error cannot be empty") - } - default: - return sdkerrors.Wrapf(ErrInvalidAcknowledgement, "unsupported acknowledgement response field type %T", resp) - } - return nil -} diff --git a/x/ibc/core/04-channel/types/channel_test.go b/x/ibc/core/04-channel/types/channel_test.go index 30fee4443b2e..a53304972ef5 100644 --- a/x/ibc/core/04-channel/types/channel_test.go +++ b/x/ibc/core/04-channel/types/channel_test.go @@ -57,63 +57,3 @@ func TestCounterpartyValidateBasic(t *testing.T) { } } } - -// tests acknowledgement.ValidateBasic and acknowledgement.GetBytes -func (suite TypesTestSuite) TestAcknowledgement() { - testCases := []struct { - name string - ack types.Acknowledgement - expPass bool - }{ - { - "valid successful ack", - types.NewResultAcknowledgement([]byte("success")), - true, - }, - { - "valid failed ack", - types.NewErrorAcknowledgement("error"), - true, - }, - { - "empty successful ack", - types.NewResultAcknowledgement([]byte{}), - false, - }, - { - "empty faied ack", - types.NewErrorAcknowledgement(" "), - false, - }, - { - "nil response", - types.Acknowledgement{ - Response: nil, - }, - false, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - suite.SetupTest() - - err := tc.ack.ValidateBasic() - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - - // expect all acks to be able to be marshaled - suite.NotPanics(func() { - bz := tc.ack.GetBytes() - suite.Require().NotNil(bz) - }) - }) - } - -} diff --git a/x/ibc/core/04-channel/types/codec.go b/x/ibc/core/04-channel/types/codec.go index a74f0a7fc9c0..cfe0110264cb 100644 --- a/x/ibc/core/04-channel/types/codec.go +++ b/x/ibc/core/04-channel/types/codec.go @@ -14,25 +14,16 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) { registry.RegisterInterface( "ibc.core.channel.v1.ChannelI", (*exported.ChannelI)(nil), + &Channel{}, ) registry.RegisterInterface( "ibc.core.channel.v1.CounterpartyChannelI", (*exported.CounterpartyChannelI)(nil), + &Counterparty{}, ) registry.RegisterInterface( "ibc.core.channel.v1.PacketI", (*exported.PacketI)(nil), - ) - registry.RegisterImplementations( - (*exported.ChannelI)(nil), - &Channel{}, - ) - registry.RegisterImplementations( - (*exported.CounterpartyChannelI)(nil), - &Counterparty{}, - ) - registry.RegisterImplementations( - (*exported.PacketI)(nil), &Packet{}, ) registry.RegisterImplementations( From 5f2b90c3c72cecdd48e421844dbfb92e157efb5c Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Mon, 1 Mar 2021 16:10:22 +0100 Subject: [PATCH 137/214] internal: create package for unsafe bytes convertion (#8733) Co-authored-by: Alessio Treglia --- internal/conv/doc.go | 2 ++ internal/conv/string.go | 23 ++++++++++++++++++ internal/conv/string_test.go | 47 ++++++++++++++++++++++++++++++++++++ store/cachekv/store.go | 29 +++------------------- types/address/hash.go | 13 ++-------- types/address/hash_test.go | 19 --------------- 6 files changed, 77 insertions(+), 56 deletions(-) create mode 100644 internal/conv/doc.go create mode 100644 internal/conv/string.go create mode 100644 internal/conv/string_test.go diff --git a/internal/conv/doc.go b/internal/conv/doc.go new file mode 100644 index 000000000000..1c86f5c14409 --- /dev/null +++ b/internal/conv/doc.go @@ -0,0 +1,2 @@ +// Package conv provides internal functions for convertions and data manipulation +package conv diff --git a/internal/conv/string.go b/internal/conv/string.go new file mode 100644 index 000000000000..9a518c57882f --- /dev/null +++ b/internal/conv/string.go @@ -0,0 +1,23 @@ +package conv + +import ( + "reflect" + "unsafe" +) + +// UnsafeStrToBytes uses unsafe to convert string into byte array. Returned bytes +// must not be altered after this function is called as it will cause a segmentation fault. +func UnsafeStrToBytes(s string) []byte { + var buf = *(*[]byte)(unsafe.Pointer(&s)) + (*reflect.SliceHeader)(unsafe.Pointer(&buf)).Cap = len(s) + return buf +} + +// UnsafeBytesToStr is meant to make a zero allocation conversion +// from []byte -> string to speed up operations, it is not meant +// to be used generally, but for a specific pattern to delete keys +// from a map. +func UnsafeBytesToStr(b []byte) string { + hdr := (*reflect.StringHeader)(unsafe.Pointer(&b)) + return *(*string)(unsafe.Pointer(hdr)) +} diff --git a/internal/conv/string_test.go b/internal/conv/string_test.go new file mode 100644 index 000000000000..2a1892b4396e --- /dev/null +++ b/internal/conv/string_test.go @@ -0,0 +1,47 @@ +package conv + +import ( + "runtime" + "testing" + "time" + + "github.com/stretchr/testify/suite" +) + +func TestStringSuite(t *testing.T) { + suite.Run(t, new(StringSuite)) +} + +type StringSuite struct{ suite.Suite } + +func unsafeConvertStr() []byte { + return UnsafeStrToBytes("abc") +} + +func (s *StringSuite) TestUnsafeStrToBytes() { + // we convert in other function to trigger GC. We want to check that + // the underlying array in []bytes is accessible after GC will finish swapping. + for i := 0; i < 5; i++ { + b := unsafeConvertStr() + runtime.GC() + <-time.NewTimer(2 * time.Millisecond).C + b2 := append(b, 'd') + s.Equal("abc", string(b)) + s.Equal("abcd", string(b2)) + } +} + +func unsafeConvertBytes() string { + return UnsafeBytesToStr([]byte("abc")) +} + +func (s *StringSuite) TestUnsafeBytesToStr() { + // we convert in other function to trigger GC. We want to check that + // the underlying array in []bytes is accessible after GC will finish swapping. + for i := 0; i < 5; i++ { + str := unsafeConvertBytes() + runtime.GC() + <-time.NewTimer(2 * time.Millisecond).C + s.Equal("abc", str) + } +} diff --git a/store/cachekv/store.go b/store/cachekv/store.go index 42c94370b8af..a953d4436b1b 100644 --- a/store/cachekv/store.go +++ b/store/cachekv/store.go @@ -4,14 +4,13 @@ import ( "bytes" "container/list" "io" - "reflect" "sort" "sync" "time" - "unsafe" dbm "github.com/tendermint/tm-db" + "github.com/cosmos/cosmos-sdk/internal/conv" "github.com/cosmos/cosmos-sdk/store/tracekv" "github.com/cosmos/cosmos-sdk/store/types" "github.com/cosmos/cosmos-sdk/telemetry" @@ -179,35 +178,13 @@ func (store *Store) iterator(start, end []byte, ascending bool) types.Iterator { return newCacheMergeIterator(parent, cache, ascending) } -// strToByte is meant to make a zero allocation conversion -// from string -> []byte to speed up operations, it is not meant -// to be used generally, but for a specific pattern to check for available -// keys within a domain. -func strToByte(s string) []byte { - var b []byte - hdr := (*reflect.SliceHeader)(unsafe.Pointer(&b)) - hdr.Cap = len(s) - hdr.Len = len(s) - hdr.Data = (*reflect.StringHeader)(unsafe.Pointer(&s)).Data - return b -} - -// byteSliceToStr is meant to make a zero allocation conversion -// from []byte -> string to speed up operations, it is not meant -// to be used generally, but for a specific pattern to delete keys -// from a map. -func byteSliceToStr(b []byte) string { - hdr := (*reflect.StringHeader)(unsafe.Pointer(&b)) - return *(*string)(unsafe.Pointer(hdr)) -} - // Constructs a slice of dirty items, to use w/ memIterator. func (store *Store) dirtyItems(start, end []byte) { unsorted := make([]*kv.Pair, 0) n := len(store.unsortedCache) for key := range store.unsortedCache { - if dbm.IsKeyInDomain(strToByte(key), start, end) { + if dbm.IsKeyInDomain(conv.UnsafeStrToBytes(key), start, end) { cacheValue := store.cache[key] unsorted = append(unsorted, &kv.Pair{Key: []byte(key), Value: cacheValue.value}) } @@ -219,7 +196,7 @@ func (store *Store) dirtyItems(start, end []byte) { } } else { // Otherwise, normally delete the unsorted keys from the map. for _, kv := range unsorted { - delete(store.unsortedCache, byteSliceToStr(kv.Key)) + delete(store.unsortedCache, conv.UnsafeBytesToStr(kv.Key)) } } diff --git a/types/address/hash.go b/types/address/hash.go index ddfec81dff78..a6c9fe94c51c 100644 --- a/types/address/hash.go +++ b/types/address/hash.go @@ -4,10 +4,9 @@ import ( "bytes" "crypto/sha256" "fmt" - "reflect" "sort" - "unsafe" + "github.com/cosmos/cosmos-sdk/internal/conv" "github.com/cosmos/cosmos-sdk/types/errors" ) @@ -21,7 +20,7 @@ type Addressable interface { // Hash creates a new address from address type and key func Hash(typ string, key []byte) []byte { hasher := sha256.New() - hasher.Write(unsafeStrToByteArray(typ)) + hasher.Write(conv.UnsafeStrToBytes(typ)) th := hasher.Sum(nil) hasher.Reset() @@ -63,11 +62,3 @@ 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 bytes -// must not be altered after this function is called as it will cause a segmentation fault. -func unsafeStrToByteArray(s string) []byte { - var buf = *(*[]byte)(unsafe.Pointer(&s)) - (*reflect.SliceHeader)(unsafe.Pointer(&buf)).Cap = len(s) - return buf -} diff --git a/types/address/hash_test.go b/types/address/hash_test.go index 4cc6c6880621..be096c357fec 100644 --- a/types/address/hash_test.go +++ b/types/address/hash_test.go @@ -2,9 +2,7 @@ package address import ( "crypto/sha256" - "runtime" "testing" - "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/suite" @@ -77,23 +75,6 @@ func (suite *AddressSuite) TestModule() { assert.NotEqual(addr2, addr3, "changing key must change address") } -func unsafeConvertABC() []byte { - return unsafeStrToByteArray("abc") -} - -func (suite *AddressSuite) TestUnsafeStrToBytes() { - // we convert in other function to trigger GC. We want to check that - // the underlying array in []bytes is accessible after GC will finish swapping. - for i := 0; i < 5; i++ { - b := unsafeConvertABC() - runtime.GC() - <-time.NewTimer(2 * time.Millisecond).C - b2 := append(b, 'd') - suite.Equal("abc", string(b)) - suite.Equal("abcd", string(b2)) - } -} - type addrMock struct { Addr []byte } From a93edeef4cd96cfb465c970cfb1c9bae8137ca2b Mon Sep 17 00:00:00 2001 From: Amaury <1293565+amaurym@users.noreply.github.com> Date: Mon, 1 Mar 2021 16:57:28 +0100 Subject: [PATCH 138/214] Move QueryTx functions to x/auth/tx (#8734) * Use x/auth/client for querying Txs * Fix lint * Fix small test * Update todos * Move QueryTx functions to x/auth/tx Co-authored-by: Alessio Treglia --- server/grpc/server_test.go | 2 +- server/rosetta/client_online.go | 3 +- x/auth/client/cli/query.go | 6 +-- x/auth/client/rest/query.go | 6 +-- x/auth/{client => tx}/query.go | 2 +- x/auth/tx/service.go | 83 +++++++-------------------------- x/auth/tx/service_test.go | 28 +++++++---- x/gov/client/utils/query.go | 4 +- x/staking/client/rest/utils.go | 4 +- 9 files changed, 49 insertions(+), 89 deletions(-) rename x/auth/{client => tx}/query.go (99%) diff --git a/server/grpc/server_test.go b/server/grpc/server_test.go index 6766d9c97ce5..6c9752741a75 100644 --- a/server/grpc/server_test.go +++ b/server/grpc/server_test.go @@ -120,7 +120,7 @@ func (s *IntegrationTestSuite) TestGRPCServer_GetTxsEvent() { _, err := txServiceClient.GetTxsEvent( context.Background(), &tx.GetTxsEventRequest{ - Events: []string{"message.action=send"}, + Events: []string{"message.action='send'"}, }, ) s.Require().NoError(err) diff --git a/server/rosetta/client_online.go b/server/rosetta/client_online.go index 110430bb1806..f5e5cfafeebf 100644 --- a/server/rosetta/client_online.go +++ b/server/rosetta/client_online.go @@ -31,7 +31,6 @@ import ( 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" @@ -254,7 +253,7 @@ func (c *Client) TxOperationsAndSignersAccountIdentifiers(signed bool, txBytes [ // 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) + txResp, err := authtx.QueryTx(c.clientCtx, hash) if err != nil { return nil, crgerrs.WrapError(crgerrs.ErrUnknown, err.Error()) } diff --git a/x/auth/client/cli/query.go b/x/auth/client/cli/query.go index 8ee3a05758d6..9604959cbdb5 100644 --- a/x/auth/client/cli/query.go +++ b/x/auth/client/cli/query.go @@ -12,7 +12,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/rest" "github.com/cosmos/cosmos-sdk/version" - authclient "github.com/cosmos/cosmos-sdk/x/auth/client" + authtx "github.com/cosmos/cosmos-sdk/x/auth/tx" "github.com/cosmos/cosmos-sdk/x/auth/types" ) @@ -189,7 +189,7 @@ $ %s query txs --%s 'message.sender=cosmos1...&message.action=withdraw_delegator page, _ := cmd.Flags().GetInt(flags.FlagPage) limit, _ := cmd.Flags().GetInt(flags.FlagLimit) - txs, err := authclient.QueryTxsByEvents(clientCtx, tmEvents, page, limit, "") + txs, err := authtx.QueryTxsByEvents(clientCtx, tmEvents, page, limit, "") if err != nil { return err } @@ -219,7 +219,7 @@ func QueryTxCmd() *cobra.Command { if err != nil { return err } - output, err := authclient.QueryTx(clientCtx, args[0]) + output, err := authtx.QueryTx(clientCtx, args[0]) if err != nil { return err } diff --git a/x/auth/client/rest/query.go b/x/auth/client/rest/query.go index d11d4b3416cc..cf292fd7f7e5 100644 --- a/x/auth/client/rest/query.go +++ b/x/auth/client/rest/query.go @@ -13,7 +13,7 @@ import ( codectypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/rest" - authclient "github.com/cosmos/cosmos-sdk/x/auth/client" + authtx "github.com/cosmos/cosmos-sdk/x/auth/tx" "github.com/cosmos/cosmos-sdk/x/auth/types" genutilrest "github.com/cosmos/cosmos-sdk/x/genutil/client/rest" ) @@ -99,7 +99,7 @@ func QueryTxsRequestHandlerFn(clientCtx client.Context) http.HandlerFunc { return } - searchResult, err := authclient.QueryTxsByEvents(clientCtx, events, page, limit, "") + searchResult, err := authtx.QueryTxsByEvents(clientCtx, events, page, limit, "") if rest.CheckInternalServerError(w, err) { return } @@ -131,7 +131,7 @@ func QueryTxRequestHandlerFn(clientCtx client.Context) http.HandlerFunc { return } - output, err := authclient.QueryTx(clientCtx, hashHexStr) + output, err := authtx.QueryTx(clientCtx, hashHexStr) if err != nil { if strings.Contains(err.Error(), hashHexStr) { rest.WriteErrorResponse(w, http.StatusNotFound, err.Error()) diff --git a/x/auth/client/query.go b/x/auth/tx/query.go similarity index 99% rename from x/auth/client/query.go rename to x/auth/tx/query.go index bc1b7f6f4512..756f0db07828 100644 --- a/x/auth/client/query.go +++ b/x/auth/tx/query.go @@ -1,4 +1,4 @@ -package client +package tx import ( "context" diff --git a/x/auth/tx/service.go b/x/auth/tx/service.go index 853d401beccc..d33bcac91329 100644 --- a/x/auth/tx/service.go +++ b/x/auth/tx/service.go @@ -2,7 +2,6 @@ package tx import ( "context" - "encoding/hex" "fmt" "strings" @@ -11,11 +10,7 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - abci "github.com/tendermint/tendermint/abci/types" - tmtypes "github.com/tendermint/tendermint/types" - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" codectypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" pagination "github.com/cosmos/cosmos-sdk/types/query" @@ -62,57 +57,36 @@ func (s txServer) GetTxsEvent(ctx context.Context, req *txtypes.GetTxsEventReque return nil, status.Error(codes.InvalidArgument, "must declare at least one event to search") } - tmEvents := make([]string, len(req.Events)) - for i, event := range req.Events { - if !strings.Contains(event, "=") { - return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("invalid event; event %s should be of the format: %s", event, eventFormat)) - } else if strings.Count(event, "=") > 1 { + for _, event := range req.Events { + if !strings.Contains(event, "=") || strings.Count(event, "=") > 1 { return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("invalid event; event %s should be of the format: %s", event, eventFormat)) } - - tokens := strings.Split(event, "=") - if tokens[0] == tmtypes.TxHeightKey { - event = fmt.Sprintf("%s=%s", tokens[0], tokens[1]) - } else { - event = fmt.Sprintf("%s='%s'", tokens[0], tokens[1]) - } - - tmEvents[i] = event } - query := strings.Join(tmEvents, " AND ") - - result, err := s.clientCtx.Client.TxSearch(ctx, query, false, &page, &limit, "") + result, err := QueryTxsByEvents(s.clientCtx, req.Events, page, limit, "") if err != nil { return nil, err } // Create a proto codec, we need it to unmarshal the tx bytes. - cdc := codec.NewProtoCodec(s.clientCtx.InterfaceRegistry) - txRespList := make([]*sdk.TxResponse, len(result.Txs)) txsList := make([]*txtypes.Tx, len(result.Txs)) for i, tx := range result.Txs { - txResp := txResultToTxResponse(&tx.TxResult) - txResp.Height = tx.Height - txResp.TxHash = tx.Hash.String() - txRespList[i] = txResp - - var protoTx txtypes.Tx - if err := cdc.UnmarshalBinaryBare(tx.Tx, &protoTx); err != nil { - return nil, err + protoTx, ok := tx.Tx.GetCachedValue().(*txtypes.Tx) + if !ok { + return nil, status.Errorf(codes.Internal, "expected %T, got %T", txtypes.Tx{}, tx.Tx.GetCachedValue()) } - txsList[i] = &protoTx + + txsList[i] = protoTx } return &txtypes.GetTxsEventResponse{ Txs: txsList, - TxResponses: txRespList, + TxResponses: result.Txs, Pagination: &pagination.PageResponse{ - Total: uint64(result.TotalCount), + Total: result.TotalCount, }, }, nil - } // Simulate implements the ServiceServer.Simulate RPC method. @@ -147,34 +121,21 @@ func (s txServer) GetTx(ctx context.Context, req *txtypes.GetTxRequest) (*txtype return nil, status.Error(codes.InvalidArgument, "request cannot be nil") } - // We get hash as a hex string in the request, convert it to bytes. - hash, err := hex.DecodeString(req.Hash) - if err != nil { - return nil, err - } - // TODO We should also check the proof flag in gRPC header. // https://github.com/cosmos/cosmos-sdk/issues/7036. - result, err := s.clientCtx.Client.Tx(ctx, hash, false) + result, err := QueryTx(s.clientCtx, req.Hash) if err != nil { return nil, err } - // Create a proto codec, we need it to unmarshal the tx bytes. - cdc := codec.NewProtoCodec(s.clientCtx.InterfaceRegistry) - - var protoTx txtypes.Tx - if err := cdc.UnmarshalBinaryBare(result.Tx, &protoTx); err != nil { - return nil, err + protoTx, ok := result.Tx.GetCachedValue().(*txtypes.Tx) + if !ok { + return nil, status.Errorf(codes.Internal, "expected %T, got %T", txtypes.Tx{}, result.Tx.GetCachedValue()) } - txResp := txResultToTxResponse(&result.TxResult) - txResp.Height = result.Height - txResp.TxHash = result.Hash.String() - return &txtypes.GetTxResponse{ - Tx: &protoTx, - TxResponse: txResp, + Tx: protoTx, + TxResponse: result, }, nil } @@ -200,15 +161,3 @@ func RegisterTxService( func RegisterGRPCGatewayRoutes(clientConn gogogrpc.ClientConn, mux *runtime.ServeMux) { txtypes.RegisterServiceHandlerClient(context.Background(), mux, txtypes.NewServiceClient(clientConn)) } - -func txResultToTxResponse(respTx *abci.ResponseDeliverTx) *sdk.TxResponse { - logs, _ := sdk.ParseABCILogs(respTx.Log) - return &sdk.TxResponse{ - Code: respTx.Code, - Codespace: respTx.Codespace, - GasUsed: respTx.GasUsed, - GasWanted: respTx.GasWanted, - Info: respTx.Info, - Logs: logs, - } -} diff --git a/x/auth/tx/service_test.go b/x/auth/tx/service_test.go index 58b21c139772..b460867b4b25 100644 --- a/x/auth/tx/service_test.go +++ b/x/auth/tx/service_test.go @@ -15,7 +15,7 @@ import ( "github.com/cosmos/cosmos-sdk/testutil/network" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - query "github.com/cosmos/cosmos-sdk/types/query" + "github.com/cosmos/cosmos-sdk/types/query" "github.com/cosmos/cosmos-sdk/types/rest" "github.com/cosmos/cosmos-sdk/types/tx" "github.com/cosmos/cosmos-sdk/types/tx/signing" @@ -176,14 +176,14 @@ func (s IntegrationTestSuite) TestGetTxEvents_GRPC() { { "without pagination", &tx.GetTxsEventRequest{ - Events: []string{"message.action=/cosmos.bank.v1beta1.Msg/Send"}, + Events: []string{"message.action='/cosmos.bank.v1beta1.Msg/Send'"}, }, false, "", }, { "with pagination", &tx.GetTxsEventRequest{ - Events: []string{"message.action=/cosmos.bank.v1beta1.Msg/Send"}, + Events: []string{"message.action='/cosmos.bank.v1beta1.Msg/Send'"}, Pagination: &query.PageRequest{ CountTotal: false, Offset: 0, @@ -195,7 +195,7 @@ func (s IntegrationTestSuite) TestGetTxEvents_GRPC() { { "with multi events", &tx.GetTxsEventRequest{ - Events: []string{"message.action=/cosmos.bank.v1beta1.Msg/Send", "message.module=bank"}, + Events: []string{"message.action='/cosmos.bank.v1beta1.Msg/Send'", "message.module='bank'"}, }, false, "", }, @@ -211,6 +211,12 @@ func (s IntegrationTestSuite) TestGetTxEvents_GRPC() { s.Require().NoError(err) s.Require().GreaterOrEqual(len(grpcRes.Txs), 1) s.Require().Equal("foobar", grpcRes.Txs[0].Body.Memo) + + // Make sure fields are populated. + // ref: https://github.com/cosmos/cosmos-sdk/issues/8680 + // ref: https://github.com/cosmos/cosmos-sdk/issues/8681 + s.Require().NotEmpty(grpcRes.TxResponses[0].Timestamp) + s.Require().NotEmpty(grpcRes.TxResponses[0].RawLog) } }) } @@ -232,25 +238,25 @@ func (s IntegrationTestSuite) TestGetTxEvents_GRPCGateway() { }, { "without pagination", - fmt.Sprintf("%s/cosmos/tx/v1beta1/txs?events=%s", val.APIAddress, "message.action=/cosmos.bank.v1beta1.Msg/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=/cosmos.bank.v1beta1.Msg/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=/cosmos.bank.v1beta1.Msg/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%3D%2Fcosmos.bank.v1beta1.Msg%2FSend"), + fmt.Sprintf("%s/cosmos/tx/v1beta1/txs?events=%s", val.APIAddress, "message.action%3D'%2Fcosmos.bank.v1beta1.Msg%2FSend'"), false, "", }, @@ -336,6 +342,12 @@ func (s IntegrationTestSuite) TestGetTx_GRPCGateway() { s.Require().NoError(err) s.Require().Equal("foobar", result.Tx.Body.Memo) s.Require().NotZero(result.TxResponse.Height) + + // Make sure fields are populated. + // ref: https://github.com/cosmos/cosmos-sdk/issues/8680 + // ref: https://github.com/cosmos/cosmos-sdk/issues/8681 + s.Require().NotEmpty(result.TxResponse.Timestamp) + s.Require().NotEmpty(result.TxResponse.RawLog) } }) } diff --git a/x/gov/client/utils/query.go b/x/gov/client/utils/query.go index de5f5f7c5e47..9b103e3468c9 100644 --- a/x/gov/client/utils/query.go +++ b/x/gov/client/utils/query.go @@ -5,7 +5,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" sdk "github.com/cosmos/cosmos-sdk/types" - authclient "github.com/cosmos/cosmos-sdk/x/auth/client" + authtx "github.com/cosmos/cosmos-sdk/x/auth/tx" "github.com/cosmos/cosmos-sdk/x/gov/types" ) @@ -374,7 +374,7 @@ func combineEvents(clientCtx client.Context, page int, eventGroups ...[]string) // 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, "") + res, err := authtx.QueryTxsByEvents(clientCtx, events, page, defaultLimit, "") if err != nil { return nil, err } diff --git a/x/staking/client/rest/utils.go b/x/staking/client/rest/utils.go index 2b8a1c4dcfc1..f8c6fe113255 100644 --- a/x/staking/client/rest/utils.go +++ b/x/staking/client/rest/utils.go @@ -9,7 +9,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/rest" - authclient "github.com/cosmos/cosmos-sdk/x/auth/client" + authtx "github.com/cosmos/cosmos-sdk/x/auth/tx" "github.com/cosmos/cosmos-sdk/x/staking/types" ) @@ -33,7 +33,7 @@ func queryTxs(clientCtx client.Context, action string, delegatorAddr string) (*s fmt.Sprintf("%s.%s='%s'", sdk.EventTypeMessage, sdk.AttributeKeySender, delegatorAddr), } - return authclient.QueryTxsByEvents(clientCtx, events, page, limit, "") + return authtx.QueryTxsByEvents(clientCtx, events, page, limit, "") } func queryBonds(clientCtx client.Context, endpoint string) http.HandlerFunc { From 1c6e2679641d0892a3f35d778d7c2316a2937a7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?colin=20axn=C3=A9r?= <25233464+colin-axner@users.noreply.github.com> Date: Mon, 1 Mar 2021 17:28:54 +0100 Subject: [PATCH 139/214] Remove IBC logic from x/upgrade (#8673) * add zeroed custom fields check to tm client * remove custom fields function from x/upgrade and fix tests * use []byte in x/upgrade, move abci to 02-client * remove x/ibc from types * whoops, delete testing files * fix upgrade tests * fix tm tests * fix tests * update CHANGELOG * revert proto breakage, use reserved field cc @amaurym * add IBC Upgrade Proposal type * remove IBC from upgrade types * add IBC upgrade logic to 02-client * fix all tests for x/upgrade * Add CLI for IBC Upgrade Proposal * Update x/ibc/core/02-client/types/proposal_test.go Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> * add gRPC for upgraded client state * test fixes * add HandleUpgradeProposal tests * update docs and remove unnecessary code * self review bug and test fixes * neatness * construct empty rest handler * fix tests * fix stringer tests * Update docs/core/proto-docs.md Co-authored-by: Christopher Goes * add key in ibc store tracking ibc upgrade heights Add a new Key to the IBC client store to track the IBC Upgrade Height. This allows IBC upgrades to correctly remove old IBC upgrade states * update abci and tests * revert key storage after discussion with @AdityaSripal Revert using a key to track IBC upgrades. By clearing any IBC state using an old plan in ScheduleUpgrade, IBC upgrades do not need to be tracked by IBC. This reduces code complexity and reduces potential for bugs. * clear IBC states on cancelled upgrades Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Co-authored-by: Christopher Goes --- CHANGELOG.md | 1 + docs/core/proto-docs.md | 60 +- docs/ibc/upgrades/quick-guide.md | 8 +- proto/cosmos/bank/v1beta1/bank.proto | 2 +- proto/cosmos/upgrade/v1beta1/query.proto | 4 +- proto/cosmos/upgrade/v1beta1/upgrade.proto | 10 +- proto/ibc/core/client/v1/client.proto | 20 + proto/ibc/core/client/v1/query.proto | 22 + simapp/app.go | 6 +- x/gov/legacy/v040/migrate_test.go | 3 +- x/ibc/core/02-client/abci.go | 23 +- x/ibc/core/02-client/abci_test.go | 34 ++ x/ibc/core/02-client/client/cli/tx.go | 90 +++ .../core/02-client/client/proposal_handler.go | 19 +- x/ibc/core/02-client/keeper/client_test.go | 54 +- x/ibc/core/02-client/keeper/grpc_query.go | 43 ++ x/ibc/core/02-client/keeper/keeper.go | 19 +- x/ibc/core/02-client/keeper/proposal.go | 26 + x/ibc/core/02-client/keeper/proposal_test.go | 169 +++++- x/ibc/core/02-client/proposal_handler.go | 6 +- x/ibc/core/02-client/proposal_handler_test.go | 2 +- x/ibc/core/02-client/types/client.pb.go | 442 ++++++++++++-- x/ibc/core/02-client/types/codec.go | 1 + x/ibc/core/02-client/types/errors.go | 1 + .../core/02-client/types/expected_keepers.go | 11 + x/ibc/core/02-client/types/proposal.go | 94 ++- x/ibc/core/02-client/types/proposal_test.go | 150 ++++- x/ibc/core/02-client/types/query.pb.go | 541 ++++++++++++++++-- x/ibc/core/02-client/types/query.pb.gw.go | 116 ++++ x/ibc/core/keeper/grpc_query.go | 5 + x/ibc/core/keeper/keeper.go | 5 +- x/ibc/core/keeper/msg_server_test.go | 24 +- .../07-tendermint/types/upgrade.go | 4 +- .../07-tendermint/types/upgrade_test.go | 178 +++--- x/upgrade/abci.go | 16 - x/upgrade/abci_test.go | 89 +-- x/upgrade/keeper/grpc_query.go | 14 +- x/upgrade/keeper/keeper.go | 70 +-- x/upgrade/keeper/keeper_test.go | 99 +--- x/upgrade/types/plan.go | 34 +- x/upgrade/types/plan_test.go | 43 +- x/upgrade/types/proposal.go | 7 - x/upgrade/types/proposal_test.go | 19 +- x/upgrade/types/query.pb.go | 105 ++-- x/upgrade/types/upgrade.pb.go | 127 ++-- 45 files changed, 2019 insertions(+), 797 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3cf3e8e366e8..dd5a0a56221b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,6 +51,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (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. * [\#8629](https://github.com/cosmos/cosmos-sdk/pull/8629) Deprecated `SetFullFundraiserPath` from `Config` in favor of `SetPurpose` and `SetCoinType`. +* (x/upgrade) [\#8673](https://github.com/cosmos/cosmos-sdk/pull/8673) Remove IBC logic from x/upgrade. Deprecates IBC fields in an Upgrade Plan. IBC upgrade logic moved to 02-client and an IBC UpgradeProposal is added. ### State Machine Breaking diff --git a/docs/core/proto-docs.md b/docs/core/proto-docs.md index 10e309d9e24a..9c1f7110adc6 100644 --- a/docs/core/proto-docs.md +++ b/docs/core/proto-docs.md @@ -567,6 +567,7 @@ - [Height](#ibc.core.client.v1.Height) - [IdentifiedClientState](#ibc.core.client.v1.IdentifiedClientState) - [Params](#ibc.core.client.v1.Params) + - [UpgradeProposal](#ibc.core.client.v1.UpgradeProposal) - [ibc/applications/transfer/v1/tx.proto](#ibc/applications/transfer/v1/tx.proto) - [MsgTransfer](#ibc.applications.transfer.v1.MsgTransfer) @@ -659,6 +660,8 @@ - [QueryConsensusStateResponse](#ibc.core.client.v1.QueryConsensusStateResponse) - [QueryConsensusStatesRequest](#ibc.core.client.v1.QueryConsensusStatesRequest) - [QueryConsensusStatesResponse](#ibc.core.client.v1.QueryConsensusStatesResponse) + - [QueryUpgradedClientStateRequest](#ibc.core.client.v1.QueryUpgradedClientStateRequest) + - [QueryUpgradedClientStateResponse](#ibc.core.client.v1.QueryUpgradedClientStateResponse) - [Query](#ibc.core.client.v1.Query) @@ -7509,7 +7512,6 @@ Plan specifies information about a planned upgrade and when it should occur. | `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 | @@ -7634,7 +7636,7 @@ RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `upgraded_consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `upgraded_consensus_state` | [bytes](#bytes) | | | @@ -8163,6 +8165,25 @@ Params defines the set of IBC light client parameters. + + + +### UpgradeProposal +UpgradeProposal is a gov Content type for initiating an IBC breaking +upgrade. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `title` | [string](#string) | | | +| `description` | [string](#string) | | | +| `plan` | [cosmos.upgrade.v1beta1.Plan](#cosmos.upgrade.v1beta1.Plan) | | | +| `upgraded_client_state` | [google.protobuf.Any](#google.protobuf.Any) | | An UpgradedClientState must be provided to perform an IBC breaking upgrade. This will make the chain commit to the correct upgraded (self) client state before the upgrade occurs, so that connected chains can verify that the new upgraded client is valid by verifying a proof of the intended new client state on the previous version of the chain. This will allow IBC connections to persist smoothly across planned chain upgrades. | + + + + + @@ -9529,6 +9550,39 @@ Query/ConsensusStates RPC method + + + +### QueryUpgradedClientStateRequest +QueryUpgradedClientStateRequest is the request type for the Query/UpgradedClientState RPC +method + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `client_id` | [string](#string) | | client state unique identifier | +| `plan_height` | [int64](#int64) | | plan height of the current chain must be sent in request as this is the height under which upgraded client state is stored | + + + + + + + + +### QueryUpgradedClientStateResponse +QueryUpgradedClientStateResponse is the response type for the Query/UpgradedClientState RPC +method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `upgraded_client_state` | [google.protobuf.Any](#google.protobuf.Any) | | client state associated with the request identifier | + + + + + @@ -9548,6 +9602,7 @@ Query provides defines the gRPC querier service | `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| +| `UpgradedClientState` | [QueryUpgradedClientStateRequest](#ibc.core.client.v1.QueryUpgradedClientStateRequest) | [QueryUpgradedClientStateResponse](#ibc.core.client.v1.QueryUpgradedClientStateResponse) | UpgradedClientState queries an Upgraded IBC light client. | GET|/ibc/core/client/v1/upgraded_client_states/{client_id}| @@ -10840,4 +10895,3 @@ that implements Misbehaviour interface expected by ICS-02 | bool | | bool | boolean | boolean | bool | bool | boolean | TrueClass/FalseClass | | string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode | string | string | string | String (UTF-8) | | bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str | []byte | ByteString | string | String (ASCII-8BIT) | - diff --git a/docs/ibc/upgrades/quick-guide.md b/docs/ibc/upgrades/quick-guide.md index 4717e52f44c1..d277de14faeb 100644 --- a/docs/ibc/upgrades/quick-guide.md +++ b/docs/ibc/upgrades/quick-guide.md @@ -30,10 +30,10 @@ Note: Since upgrades are only implemented for Tendermint clients, this doc only 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` +1. Create an `UpgradeProposal` with an IBC ClientState in the `UpgradedClientState` field and a `UpgradePlan` in the `Plan` field. Note that the proposal `Plan` 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 `UpgradeProposal` -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`. +Upon the `UpgradeProposal` 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. @@ -51,4 +51,4 @@ Thus, the upgrade process for relayers trying to upgrade the counterparty client 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 +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. diff --git a/proto/cosmos/bank/v1beta1/bank.proto b/proto/cosmos/bank/v1beta1/bank.proto index fb9069214415..b60027c88629 100644 --- a/proto/cosmos/bank/v1beta1/bank.proto +++ b/proto/cosmos/bank/v1beta1/bank.proto @@ -86,5 +86,5 @@ message Metadata { string name = 5; // symbol is the token symbol usually shown on exchanges (eg: ATOM). This can // be the same as the display. - string symbol = 6; + string symbol = 6; } diff --git a/proto/cosmos/upgrade/v1beta1/query.proto b/proto/cosmos/upgrade/v1beta1/query.proto index 9eab27e76b44..0fc6fd856f8d 100644 --- a/proto/cosmos/upgrade/v1beta1/query.proto +++ b/proto/cosmos/upgrade/v1beta1/query.proto @@ -64,5 +64,7 @@ message QueryUpgradedConsensusStateRequest { // QueryUpgradedConsensusStateResponse is the response type for the Query/UpgradedConsensusState // RPC method. message QueryUpgradedConsensusStateResponse { - google.protobuf.Any upgraded_consensus_state = 1; + reserved 1; + + bytes upgraded_consensus_state = 2; } diff --git a/proto/cosmos/upgrade/v1beta1/upgrade.proto b/proto/cosmos/upgrade/v1beta1/upgrade.proto index 6d6839ca56c5..76fb14e2d3ca 100644 --- a/proto/cosmos/upgrade/v1beta1/upgrade.proto +++ b/proto/cosmos/upgrade/v1beta1/upgrade.proto @@ -34,12 +34,10 @@ message Plan { // such as a git commit that validators could automatically upgrade to string info = 4; - // 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 - google.protobuf.Any upgraded_client_state = 5 [(gogoproto.moretags) = "yaml:\"upgraded_client_state\""]; + // UpgradedClientState field has been deprecated. IBC upgrade logic has been + // moved to the IBC module in the sub module 02-client. + reserved 5; + reserved "option"; } // SoftwareUpgradeProposal is a gov Content type for initiating a software diff --git a/proto/ibc/core/client/v1/client.proto b/proto/ibc/core/client/v1/client.proto index 4c6308bd5415..d8c0c28f498d 100644 --- a/proto/ibc/core/client/v1/client.proto +++ b/proto/ibc/core/client/v1/client.proto @@ -5,6 +5,7 @@ option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"; import "gogoproto/gogo.proto"; import "google/protobuf/any.proto"; +import "cosmos/upgrade/v1beta1/upgrade.proto"; // IdentifiedClientState defines a client state with an additional client // identifier field. @@ -52,6 +53,25 @@ message ClientUpdateProposal { Height initial_height = 5 [(gogoproto.moretags) = "yaml:\"initial_height\"", (gogoproto.nullable) = false]; } +// UpgradeProposal is a gov Content type for initiating an IBC breaking +// upgrade. +message UpgradeProposal { + option (gogoproto.goproto_getters) = false; + option (gogoproto.goproto_stringer) = false; + option (gogoproto.equal) = true; + + string title = 1; + string description = 2; + cosmos.upgrade.v1beta1.Plan plan = 3 [(gogoproto.nullable) = false]; + + // An UpgradedClientState must be provided to perform an IBC breaking upgrade. + // 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 + google.protobuf.Any upgraded_client_state = 4 [(gogoproto.moretags) = "yaml:\"upgraded_client_state\""]; +} + // Height is a monotonically increasing data type // that can be compared against another Height for the purposes of updating and // freezing clients diff --git a/proto/ibc/core/client/v1/query.proto b/proto/ibc/core/client/v1/query.proto index 97f3acd62752..078571dd2b2f 100644 --- a/proto/ibc/core/client/v1/query.proto +++ b/proto/ibc/core/client/v1/query.proto @@ -38,6 +38,11 @@ service Query { rpc ClientParams(QueryClientParamsRequest) returns (QueryClientParamsResponse) { option (google.api.http).get = "/ibc/client/v1beta1/params"; } + + // UpgradedClientState queries an Upgraded IBC light client. + rpc UpgradedClientState(QueryUpgradedClientStateRequest) returns (QueryUpgradedClientStateResponse) { + option (google.api.http).get = "/ibc/core/client/v1/upgraded_client_states/{client_id}"; + } } // QueryClientStateRequest is the request type for the Query/ClientState RPC @@ -128,3 +133,20 @@ message QueryClientParamsResponse { // params defines the parameters of the module. Params params = 1; } + +// QueryUpgradedClientStateRequest is the request type for the Query/UpgradedClientState RPC +// method +message QueryUpgradedClientStateRequest { + // client state unique identifier + string client_id = 1; + // plan height of the current chain must be sent in request + // as this is the height under which upgraded client state is stored + int64 plan_height = 2; +} + +// QueryUpgradedClientStateResponse is the response type for the Query/UpgradedClientState RPC +// method. +message QueryUpgradedClientStateResponse { + // client state associated with the request identifier + google.protobuf.Any upgraded_client_state = 1; +} diff --git a/simapp/app.go b/simapp/app.go index 41376c8ee3a5..4086585e684c 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" + ibcclientclient "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/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" @@ -120,6 +121,7 @@ var ( distr.AppModuleBasic{}, gov.NewAppModuleBasic( paramsclient.ProposalHandler, distrclient.ProposalHandler, upgradeclient.ProposalHandler, upgradeclient.CancelProposalHandler, + ibcclientclient.UpdateClientProposalHandler, ibcclientclient.UpgradeProposalHandler, ), params.AppModuleBasic{}, crisis.AppModuleBasic{}, @@ -299,7 +301,7 @@ func NewSimApp( // Create IBC Keeper app.IBCKeeper = ibckeeper.NewKeeper( - appCodec, keys[ibchost.StoreKey], app.GetSubspace(ibchost.ModuleName), app.StakingKeeper, scopedIBCKeeper, + appCodec, keys[ibchost.StoreKey], app.GetSubspace(ibchost.ModuleName), app.StakingKeeper, app.UpgradeKeeper, scopedIBCKeeper, ) app.AuthzKeeper = authzkeeper.NewKeeper(keys[authztypes.StoreKey], appCodec, app.BaseApp.MsgServiceRouter()) @@ -310,7 +312,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(ibcclienttypes.RouterKey, ibcclient.NewClientUpdateProposalHandler(app.IBCKeeper.ClientKeeper)) + AddRoute(ibcclienttypes.RouterKey, ibcclient.NewClientProposalHandler(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/gov/legacy/v040/migrate_test.go b/x/gov/legacy/v040/migrate_test.go index 049f5b885387..c28e43fdf2c9 100644 --- a/x/gov/legacy/v040/migrate_test.go +++ b/x/gov/legacy/v040/migrate_test.go @@ -176,8 +176,7 @@ func TestMigrate(t *testing.T) { "height": "123", "info": "foo_upgrade_info", "name": "foo_upgrade_name", - "time": "0001-01-01T00:00:00Z", - "upgraded_client_state": null + "time": "0001-01-01T00:00:00Z" }, "title": "foo_software_upgrade" }, diff --git a/x/ibc/core/02-client/abci.go b/x/ibc/core/02-client/abci.go index 3c56d90ad37a..163e513327b8 100644 --- a/x/ibc/core/02-client/abci.go +++ b/x/ibc/core/02-client/abci.go @@ -4,11 +4,32 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/keeper" "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" + ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" ) // BeginBlocker updates an existing localhost client with the latest block height. func BeginBlocker(ctx sdk.Context, k keeper.Keeper) { - _, found := k.GetClientState(ctx, exported.Localhost) + plan, found := k.GetUpgradePlan(ctx) + if found { + // Once we are at the last block this chain will commit, set the upgraded consensus state + // so that IBC clients can use the last NextValidatorsHash as a trusted kernel for verifying + // headers on the next version of the chain. + // Set the time to the last block time of the current chain. + // In order for a client to upgrade successfully, the first block of the new chain must be committed + // within the trusting period of the last block time on this chain. + _, exists := k.GetUpgradedClient(ctx, plan.Height) + if exists && ctx.BlockHeight() == plan.Height-1 { + upgradedConsState := &ibctmtypes.ConsensusState{ + Timestamp: ctx.BlockTime(), + NextValidatorsHash: ctx.BlockHeader().NextValidatorsHash, + } + bz := k.MustMarshalConsensusState(upgradedConsState) + + k.SetUpgradedConsensusState(ctx, plan.Height, bz) + } + } + + _, found = k.GetClientState(ctx, exported.Localhost) if !found { return } diff --git a/x/ibc/core/02-client/abci_test.go b/x/ibc/core/02-client/abci_test.go index 3a296618b313..3f1f6ebdc289 100644 --- a/x/ibc/core/02-client/abci_test.go +++ b/x/ibc/core/02-client/abci_test.go @@ -4,12 +4,16 @@ import ( "testing" "github.com/stretchr/testify/suite" + abci "github.com/tendermint/tendermint/abci/types" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" client "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client" "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" + ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" localhosttypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/09-localhost/types" ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" ) type ClientTestSuite struct { @@ -58,3 +62,33 @@ func (suite *ClientTestSuite) TestBeginBlocker() { prevHeight = localHostClient.GetLatestHeight().(types.Height) } } + +func (suite *ClientTestSuite) TestBeginBlockerConsensusState() { + plan := &upgradetypes.Plan{ + Name: "test", + Height: suite.chainA.GetContext().BlockHeight() + 1, + } + // set upgrade plan in the upgrade store + store := suite.chainA.GetContext().KVStore(suite.chainA.App.GetKey(upgradetypes.StoreKey)) + bz := suite.chainA.App.AppCodec().MustMarshalBinaryBare(plan) + store.Set(upgradetypes.PlanKey(), bz) + + nextValsHash := []byte("nextValsHash") + newCtx := suite.chainA.GetContext().WithBlockHeader(tmproto.Header{ + Height: suite.chainA.GetContext().BlockHeight(), + NextValidatorsHash: nextValsHash, + }) + + err := suite.chainA.App.UpgradeKeeper.SetUpgradedClient(newCtx, plan.Height, []byte("client state")) + suite.Require().NoError(err) + + req := abci.RequestBeginBlock{Header: newCtx.BlockHeader()} + suite.chainA.App.BeginBlock(req) + + // plan Height is at ctx.BlockHeight+1 + consState, found := suite.chainA.App.UpgradeKeeper.GetUpgradedConsensusState(newCtx, plan.Height) + suite.Require().True(found) + bz, err = types.MarshalConsensusState(suite.chainA.App.AppCodec(), &ibctmtypes.ConsensusState{Timestamp: newCtx.BlockTime(), NextValidatorsHash: nextValsHash}) + suite.Require().NoError(err) + suite.Require().Equal(bz, consState) +} diff --git a/x/ibc/core/02-client/client/cli/tx.go b/x/ibc/core/02-client/client/cli/tx.go index bdaa53a8ae1e..51c78bb4e737 100644 --- a/x/ibc/core/02-client/client/cli/tx.go +++ b/x/ibc/core/02-client/client/cli/tx.go @@ -18,6 +18,7 @@ import ( 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" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" ) // NewCreateClientCmd defines the command to create a new IBC light client. @@ -326,3 +327,92 @@ func NewCmdSubmitUpdateClientProposal() *cobra.Command { return cmd } + +// NewCmdSubmitUpgradeProposal implements a command handler for submitting an upgrade IBC client proposal transaction. +func NewCmdSubmitUpgradeProposal() *cobra.Command { + cmd := &cobra.Command{ + Use: "ibc-upgrade [name] [height] [path/to/upgraded_client_state.json] [flags]", + Args: cobra.ExactArgs(3), + Short: "Submit an IBC upgrade proposal", + Long: "Submit an IBC client breaking upgrade proposal along with an initial deposit.\n" + + "The client state specified is the upgraded client state representing the upgraded chain", + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry) + + title, err := cmd.Flags().GetString(govcli.FlagTitle) + if err != nil { + return err + } + + description, err := cmd.Flags().GetString(govcli.FlagDescription) + if err != nil { + return err + } + + name := args[0] + + height, err := cmd.Flags().GetInt64(args[1]) + if err != nil { + return err + } + + plan := upgradetypes.Plan{ + Name: name, + Height: height, + } + + // attempt to unmarshal client state argument + var clientState exported.ClientState + clientContentOrFileName := args[2] + 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") + } + } + + content, err := types.NewUpgradeProposal(title, description, plan, clientState) + if err != nil { + return err + } + + 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 index 63585cbe50b2..1f6f4065f0f1 100644 --- a/x/ibc/core/02-client/client/proposal_handler.go +++ b/x/ibc/core/02-client/client/proposal_handler.go @@ -1,8 +1,25 @@ package client import ( + "net/http" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/types/rest" govclient "github.com/cosmos/cosmos-sdk/x/gov/client" + govrest "github.com/cosmos/cosmos-sdk/x/gov/client/rest" "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/client/cli" ) -var ProposalHandler = govclient.NewProposalHandler(cli.NewCmdSubmitUpdateClientProposal, nil) +var ( + UpdateClientProposalHandler = govclient.NewProposalHandler(cli.NewCmdSubmitUpdateClientProposal, emptyRestHandler) + UpgradeProposalHandler = govclient.NewProposalHandler(cli.NewCmdSubmitUpgradeProposal, emptyRestHandler) +) + +func emptyRestHandler(client.Context) govrest.ProposalRESTHandler { + return govrest.ProposalRESTHandler{ + SubRoute: "unsupported-ibc-client", + Handler: func(w http.ResponseWriter, r *http.Request) { + rest.WriteErrorResponse(w, http.StatusBadRequest, "Legacy REST Routes are not supported for IBC proposals") + }, + } +} diff --git a/x/ibc/core/02-client/keeper/client_test.go b/x/ibc/core/02-client/keeper/client_test.go index 0cf5c1fe1d57..9eb816adf919 100644 --- a/x/ibc/core/02-client/keeper/client_test.go +++ b/x/ibc/core/02-client/keeper/client_test.go @@ -230,6 +230,8 @@ func (suite *KeeperTestSuite) TestUpgradeClient() { lastHeight exported.Height clientA string proofUpgradedClient, proofUpgradedConsState []byte + upgradedClientBz, upgradedConsStateBz []byte + err error ) testCases := []struct { @@ -240,18 +242,12 @@ func (suite *KeeperTestSuite) TestUpgradeClient() { { name: "successful upgrade", setup: func() { - - upgradedClient = ibctmtypes.NewClientState("newChainId", ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) - upgradedConsState = &ibctmtypes.ConsensusState{ - NextValidatorsHash: []byte("nextValsHash"), - } - // last Height is at next block lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) // zero custom fields and store in upgrade store - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClient) - suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsState) + suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) + suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) // commit upgrade store changes and update clients @@ -270,18 +266,12 @@ func (suite *KeeperTestSuite) TestUpgradeClient() { { name: "client state not found", setup: func() { - - upgradedClient = ibctmtypes.NewClientState("newChainId", ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) - upgradedConsState = &ibctmtypes.ConsensusState{ - NextValidatorsHash: []byte("nextValsHash"), - } - // last Height is at next block lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) // zero custom fields and store in upgrade store - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClient) - suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsState) + suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) + suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) // commit upgrade store changes and update clients @@ -302,18 +292,12 @@ func (suite *KeeperTestSuite) TestUpgradeClient() { { name: "client state frozen", setup: func() { - - upgradedClient = ibctmtypes.NewClientState("newChainId", ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) - upgradedConsState = &ibctmtypes.ConsensusState{ - NextValidatorsHash: []byte("nextValsHash"), - } - // last Height is at next block lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) // zero custom fields and store in upgrade store - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClient) - suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsState) + suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) + suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) // commit upgrade store changes and update clients @@ -338,18 +322,12 @@ func (suite *KeeperTestSuite) TestUpgradeClient() { { name: "tendermint client VerifyUpgrade fails", setup: func() { - - upgradedClient = ibctmtypes.NewClientState("newChainId", ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) - upgradedConsState = &ibctmtypes.ConsensusState{ - NextValidatorsHash: []byte("nextValsHash"), - } - // last Height is at next block lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) // zero custom fields and store in upgrade store - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClient) - suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsState) + suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) + suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) // change upgradedClient client-specified parameters upgradedClient = ibctmtypes.NewClientState("wrongchainID", ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, true, true) @@ -371,13 +349,23 @@ func (suite *KeeperTestSuite) TestUpgradeClient() { for _, tc := range testCases { tc := tc clientA, _ = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) + upgradedClient = ibctmtypes.NewClientState("newChainId", ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) + upgradedClient = upgradedClient.ZeroCustomFields() + upgradedClientBz, err = types.MarshalClientState(suite.chainA.App.AppCodec(), upgradedClient) + suite.Require().NoError(err) + + upgradedConsState = &ibctmtypes.ConsensusState{ + NextValidatorsHash: []byte("nextValsHash"), + } + upgradedConsStateBz, err = types.MarshalConsensusState(suite.chainA.App.AppCodec(), upgradedConsState) + suite.Require().NoError(err) tc.setup() // Call ZeroCustomFields on upgraded clients to clear any client-chosen parameters in test-case upgradedClient upgradedClient = upgradedClient.ZeroCustomFields() - err := suite.chainA.App.IBCKeeper.ClientKeeper.UpgradeClient(suite.chainA.GetContext(), clientA, upgradedClient, upgradedConsState, proofUpgradedClient, proofUpgradedConsState) + err = suite.chainA.App.IBCKeeper.ClientKeeper.UpgradeClient(suite.chainA.GetContext(), clientA, upgradedClient, upgradedConsState, proofUpgradedClient, proofUpgradedConsState) if tc.expPass { suite.Require().NoError(err, "verify upgrade failed on valid case: %s", tc.name) diff --git a/x/ibc/core/02-client/keeper/grpc_query.go b/x/ibc/core/02-client/keeper/grpc_query.go index 2134427729ae..cc4b256d30e7 100644 --- a/x/ibc/core/02-client/keeper/grpc_query.go +++ b/x/ibc/core/02-client/keeper/grpc_query.go @@ -197,3 +197,46 @@ func (q Keeper) ClientParams(c context.Context, _ *types.QueryClientParamsReques Params: ¶ms, }, nil } + +// UpgradedClientState implements the Query/UpgradedClientState gRPC method +func (q Keeper) UpgradedClientState(c context.Context, req *types.QueryUpgradedClientStateRequest) (*types.QueryUpgradedClientStateResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + + if err := host.ClientIdentifierValidator(req.ClientId); err != nil { + return nil, status.Error(codes.InvalidArgument, err.Error()) + } + + ctx := sdk.UnwrapSDKContext(c) + plan, found := q.GetUpgradePlan(ctx) + if !found { + return nil, status.Error( + codes.NotFound, "upgrade plan not found", + ) + } + + bz, found := q.GetUpgradedClient(ctx, plan.Height) + if !found { + return nil, status.Error( + codes.NotFound, + sdkerrors.Wrap(types.ErrClientNotFound, req.ClientId).Error(), + ) + } + + clientState, err := types.UnmarshalClientState(q.cdc, bz) + if err != nil { + return nil, status.Error( + codes.Internal, err.Error(), + ) + } + + any, err := types.PackClientState(clientState) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + + return &types.QueryUpgradedClientStateResponse{ + UpgradedClientState: any, + }, nil +} diff --git a/x/ibc/core/02-client/keeper/keeper.go b/x/ibc/core/02-client/keeper/keeper.go index 67c5c0658d40..43ac1feb3523 100644 --- a/x/ibc/core/02-client/keeper/keeper.go +++ b/x/ibc/core/02-client/keeper/keeper.go @@ -28,10 +28,11 @@ type Keeper struct { cdc codec.BinaryMarshaler paramSpace paramtypes.Subspace stakingKeeper types.StakingKeeper + upgradeKeeper types.UpgradeKeeper } // NewKeeper creates a new NewKeeper instance -func NewKeeper(cdc codec.BinaryMarshaler, key sdk.StoreKey, paramSpace paramtypes.Subspace, sk types.StakingKeeper) Keeper { +func NewKeeper(cdc codec.BinaryMarshaler, key sdk.StoreKey, paramSpace paramtypes.Subspace, sk types.StakingKeeper, uk types.UpgradeKeeper) Keeper { // set KeyTable if it has not already been set if !paramSpace.HasKeyTable() { paramSpace = paramSpace.WithKeyTable(types.ParamKeyTable()) @@ -42,6 +43,7 @@ func NewKeeper(cdc codec.BinaryMarshaler, key sdk.StoreKey, paramSpace paramtype cdc: cdc, paramSpace: paramSpace, stakingKeeper: sk, + upgradeKeeper: uk, } } @@ -327,6 +329,21 @@ func (k Keeper) ValidateSelfClient(ctx sdk.Context, clientState exported.ClientS return nil } +// GetUpgradePlan executes the upgrade keeper GetUpgradePlan function. +func (k Keeper) GetUpgradePlan(ctx sdk.Context) (plan upgradetypes.Plan, havePlan bool) { + return k.upgradeKeeper.GetUpgradePlan(ctx) +} + +// GetUpgradedClient executes the upgrade keeper GetUpgradeClient function. +func (k Keeper) GetUpgradedClient(ctx sdk.Context, planHeight int64) ([]byte, bool) { + return k.upgradeKeeper.GetUpgradedClient(ctx, planHeight) +} + +// SetUpgradedConsensusState executes the upgrade keeper SetUpgradedConsensusState function. +func (k Keeper) SetUpgradedConsensusState(ctx sdk.Context, planHeight int64, bz []byte) error { + return k.upgradeKeeper.SetUpgradedConsensusState(ctx, planHeight, bz) +} + // IterateClients provides an iterator over all stored light client State // objects. For each State object, cb will be called. If the cb returns true, // the iterator will close and stop. diff --git a/x/ibc/core/02-client/keeper/proposal.go b/x/ibc/core/02-client/keeper/proposal.go index 6d4ff350df32..812df5e138de 100644 --- a/x/ibc/core/02-client/keeper/proposal.go +++ b/x/ibc/core/02-client/keeper/proposal.go @@ -70,3 +70,29 @@ func (k Keeper) ClientUpdateProposal(ctx sdk.Context, p *types.ClientUpdatePropo return nil } + +// HandleUpgradeProposal sets the upgraded client state in the upgrade store. It clears +// an IBC client state and consensus state if a previous plan was set. Then it +// will schedule an upgrade and finally set the upgraded client state in upgrade +// store. +func (k Keeper) HandleUpgradeProposal(ctx sdk.Context, p *types.UpgradeProposal) error { + clientState, err := types.UnpackClientState(p.UpgradedClientState) + if err != nil { + return sdkerrors.Wrap(err, "could not unpack UpgradedClientState") + } + + // zero out any custom fields before setting + cs := clientState.ZeroCustomFields() + bz, err := types.MarshalClientState(k.cdc, cs) + if err != nil { + return sdkerrors.Wrap(err, "could not marshal UpgradedClientState") + } + + if err := k.upgradeKeeper.ScheduleUpgrade(ctx, p.Plan); err != nil { + return err + } + + // sets the new upgraded client in last height committed on this chain is at plan.Height, + // since the chain will panic at plan.Height and new chain will resume at plan.Height + return k.upgradeKeeper.SetUpgradedClient(ctx, p.Plan.Height, bz) +} diff --git a/x/ibc/core/02-client/keeper/proposal_test.go b/x/ibc/core/02-client/keeper/proposal_test.go index 8dbe43f7d7f7..82d7e120dbcf 100644 --- a/x/ibc/core/02-client/keeper/proposal_test.go +++ b/x/ibc/core/02-client/keeper/proposal_test.go @@ -1,19 +1,20 @@ package keeper_test import ( + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" ) func (suite *KeeperTestSuite) TestClientUpdateProposal() { var ( subject, substitute string subjectClientState, substituteClientState exported.ClientState - initialHeight clienttypes.Height - content *types.ClientUpdateProposal + initialHeight types.Height + content govtypes.Content err error ) @@ -24,7 +25,7 @@ func (suite *KeeperTestSuite) TestClientUpdateProposal() { }{ { "valid update client proposal", func() { - content = clienttypes.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, subject, substitute, initialHeight) + content = types.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, subject, substitute, initialHeight) }, true, }, { @@ -35,52 +36,52 @@ func (suite *KeeperTestSuite) TestClientUpdateProposal() { suite.Require().True(found) newRevisionNumber := tmClientState.GetLatestHeight().GetRevisionNumber() + 1 - tmClientState.LatestHeight = clienttypes.NewHeight(newRevisionNumber, tmClientState.GetLatestHeight().GetRevisionHeight()) - initialHeight = clienttypes.NewHeight(newRevisionNumber, initialHeight.GetRevisionHeight()) + tmClientState.LatestHeight = types.NewHeight(newRevisionNumber, tmClientState.GetLatestHeight().GetRevisionHeight()) + initialHeight = types.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 = clienttypes.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, subject, substitute, initialHeight) + content = types.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, subject, substitute, initialHeight) }, true, }, { "cannot use localhost as subject", func() { - content = clienttypes.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, exported.Localhost, substitute, initialHeight) + content = types.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, exported.Localhost, substitute, initialHeight) }, false, }, { "cannot use localhost as substitute", func() { - content = clienttypes.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, subject, exported.Localhost, initialHeight) + content = types.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, subject, exported.Localhost, initialHeight) }, false, }, { "subject client does not exist", func() { - content = clienttypes.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, ibctesting.InvalidID, substitute, initialHeight) + content = types.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, ibctesting.InvalidID, substitute, initialHeight) }, false, }, { "substitute client does not exist", func() { - content = clienttypes.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, subject, ibctesting.InvalidID, initialHeight) + content = types.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, subject, ibctesting.InvalidID, initialHeight) }, false, }, { "subject and substitute have equal latest height", func() { tmClientState, ok := subjectClientState.(*ibctmtypes.ClientState) suite.Require().True(ok) - tmClientState.LatestHeight = substituteClientState.GetLatestHeight().(clienttypes.Height) + tmClientState.LatestHeight = substituteClientState.GetLatestHeight().(types.Height) suite.chainA.App.IBCKeeper.ClientKeeper.SetClientState(suite.chainA.GetContext(), subject, tmClientState) - content = clienttypes.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, subject, substitute, initialHeight) + content = types.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() + tmClientState.FrozenHeight = types.ZeroHeight() suite.chainA.App.IBCKeeper.ClientKeeper.SetClientState(suite.chainA.GetContext(), subject, tmClientState) - content = clienttypes.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, subject, substitute, initialHeight) + content = types.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, subject, substitute, initialHeight) }, false, }, } @@ -94,7 +95,7 @@ func (suite *KeeperTestSuite) TestClientUpdateProposal() { 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) + initialHeight = types.NewHeight(subjectClientState.GetLatestHeight().GetRevisionNumber(), subjectClientState.GetLatestHeight().GetRevisionHeight()+1) // update substitute twice suite.coordinator.UpdateClient(suite.chainA, suite.chainB, substitute, exported.Tendermint) @@ -117,7 +118,9 @@ func (suite *KeeperTestSuite) TestClientUpdateProposal() { tc.malleate() - err = suite.chainA.App.IBCKeeper.ClientKeeper.ClientUpdateProposal(suite.chainA.GetContext(), content) + updateProp, ok := content.(*types.ClientUpdateProposal) + suite.Require().True(ok) + err = suite.chainA.App.IBCKeeper.ClientKeeper.ClientUpdateProposal(suite.chainA.GetContext(), updateProp) if tc.expPass { suite.Require().NoError(err) @@ -128,3 +131,135 @@ func (suite *KeeperTestSuite) TestClientUpdateProposal() { } } + +func (suite *KeeperTestSuite) TestHandleUpgradeProposal() { + var ( + upgradedClientState *ibctmtypes.ClientState + oldPlan, plan upgradetypes.Plan + content govtypes.Content + err error + ) + + testCases := []struct { + name string + malleate func() + expPass bool + }{ + { + "valid upgrade proposal", func() { + content, err = types.NewUpgradeProposal(ibctesting.Title, ibctesting.Description, plan, upgradedClientState) + suite.Require().NoError(err) + }, true, + }, + { + "valid upgrade proposal with previous IBC state", func() { + oldPlan = upgradetypes.Plan{ + Name: "upgrade IBC clients", + Height: 100, + } + + content, err = types.NewUpgradeProposal(ibctesting.Title, ibctesting.Description, plan, upgradedClientState) + suite.Require().NoError(err) + }, true, + }, + { + "cannot unpack client state", func() { + any, err := types.PackConsensusState(&ibctmtypes.ConsensusState{}) + suite.Require().NoError(err) + content = &types.UpgradeProposal{ + Title: ibctesting.Title, + Description: ibctesting.Description, + Plan: plan, + UpgradedClientState: any, + } + }, false, + }, + { + "schedule upgrade fails - plan sets time and height", func() { + plan = upgradetypes.Plan{ + Name: "invalid plan", + Height: 1000, + Time: suite.chainA.GetContext().BlockTime(), + } + content, err = types.NewUpgradeProposal(ibctesting.Title, ibctesting.Description, plan, upgradedClientState) + suite.Require().NoError(err) + }, false, + }, + } + + for _, tc := range testCases { + tc := tc + + suite.Run(tc.name, func() { + suite.SetupTest() // reset + oldPlan.Height = 0 //reset + + clientID, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) + upgradedClientState = suite.chainA.GetClientState(clientID).ZeroCustomFields().(*ibctmtypes.ClientState) + + // use height 1000 to distinguish from old plan + plan = upgradetypes.Plan{ + Name: "upgrade IBC clients", + Height: 1000, + } + + tc.malleate() + + // set the old plan if it is not empty + if oldPlan.Height != 0 { + // set upgrade plan in the upgrade store + store := suite.chainA.GetContext().KVStore(suite.chainA.App.GetKey(upgradetypes.StoreKey)) + bz := suite.chainA.App.AppCodec().MustMarshalBinaryBare(&oldPlan) + store.Set(upgradetypes.PlanKey(), bz) + + bz, err := types.MarshalClientState(suite.chainA.App.AppCodec(), upgradedClientState) + suite.Require().NoError(err) + suite.chainA.App.UpgradeKeeper.SetUpgradedClient(suite.chainA.GetContext(), oldPlan.Height, bz) + } + + upgradeProp, ok := content.(*types.UpgradeProposal) + suite.Require().True(ok) + err = suite.chainA.App.IBCKeeper.ClientKeeper.HandleUpgradeProposal(suite.chainA.GetContext(), upgradeProp) + + if tc.expPass { + suite.Require().NoError(err) + + // check that the correct plan is returned + storedPlan, found := suite.chainA.App.UpgradeKeeper.GetUpgradePlan(suite.chainA.GetContext()) + suite.Require().True(found) + suite.Require().Equal(plan, storedPlan) + + // check that old upgraded client state is cleared + _, found = suite.chainA.App.UpgradeKeeper.GetUpgradedClient(suite.chainA.GetContext(), oldPlan.Height) + suite.Require().False(found) + + // check that client state was set + storedClientState, found := suite.chainA.App.UpgradeKeeper.GetUpgradedClient(suite.chainA.GetContext(), plan.Height) + suite.Require().True(found) + clientState, err := types.UnmarshalClientState(suite.chainA.App.AppCodec(), storedClientState) + suite.Require().NoError(err) + suite.Require().Equal(upgradedClientState, clientState) + } else { + suite.Require().Error(err) + + // check that the new plan wasn't stored + storedPlan, found := suite.chainA.App.UpgradeKeeper.GetUpgradePlan(suite.chainA.GetContext()) + if oldPlan.Height != 0 { + // NOTE: this is only true if the ScheduleUpgrade function + // returns an error before clearing the old plan + suite.Require().True(found) + suite.Require().Equal(oldPlan, storedPlan) + } else { + suite.Require().False(found) + suite.Require().Empty(storedPlan) + } + + // check that client state was not set + _, found = suite.chainA.App.UpgradeKeeper.GetUpgradedClient(suite.chainA.GetContext(), plan.Height) + suite.Require().False(found) + + } + }) + } + +} diff --git a/x/ibc/core/02-client/proposal_handler.go b/x/ibc/core/02-client/proposal_handler.go index befa95df642f..f035ca99a0cc 100644 --- a/x/ibc/core/02-client/proposal_handler.go +++ b/x/ibc/core/02-client/proposal_handler.go @@ -8,12 +8,14 @@ import ( "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" ) -// NewClientUpdateProposalHandler defines the client update proposal handler -func NewClientUpdateProposalHandler(k keeper.Keeper) govtypes.Handler { +// NewClientProposalHandler defines the 02-client proposal handler +func NewClientProposalHandler(k keeper.Keeper) govtypes.Handler { return func(ctx sdk.Context, content govtypes.Content) error { switch c := content.(type) { case *types.ClientUpdateProposal: return k.ClientUpdateProposal(ctx, c) + case *types.UpgradeProposal: + return k.HandleUpgradeProposal(ctx, c) default: return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized ibc proposal content type: %T", c) diff --git a/x/ibc/core/02-client/proposal_handler_test.go b/x/ibc/core/02-client/proposal_handler_test.go index 41b893186d65..502da898e8a6 100644 --- a/x/ibc/core/02-client/proposal_handler_test.go +++ b/x/ibc/core/02-client/proposal_handler_test.go @@ -69,7 +69,7 @@ func (suite *ClientTestSuite) TestNewClientUpdateProposalHandler() { tc.malleate() - proposalHandler := client.NewClientUpdateProposalHandler(suite.chainA.App.IBCKeeper.ClientKeeper) + proposalHandler := client.NewClientProposalHandler(suite.chainA.App.IBCKeeper.ClientKeeper) err = proposalHandler(suite.chainA.GetContext(), content) diff --git a/x/ibc/core/02-client/types/client.pb.go b/x/ibc/core/02-client/types/client.pb.go index 61bdd9bf804d..a9a799453900 100644 --- a/x/ibc/core/02-client/types/client.pb.go +++ b/x/ibc/core/02-client/types/client.pb.go @@ -6,6 +6,7 @@ package types import ( fmt "fmt" types "github.com/cosmos/cosmos-sdk/codec/types" + types1 "github.com/cosmos/cosmos-sdk/x/upgrade/types" _ "github.com/gogo/protobuf/gogoproto" proto "github.com/gogo/protobuf/proto" io "io" @@ -242,6 +243,52 @@ func (m *ClientUpdateProposal) XXX_DiscardUnknown() { var xxx_messageInfo_ClientUpdateProposal proto.InternalMessageInfo +// UpgradeProposal is a gov Content type for initiating an IBC breaking +// upgrade. +type UpgradeProposal struct { + Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty"` + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + Plan types1.Plan `protobuf:"bytes,3,opt,name=plan,proto3" json:"plan"` + // An UpgradedClientState must be provided to perform an IBC breaking upgrade. + // 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 + UpgradedClientState *types.Any `protobuf:"bytes,4,opt,name=upgraded_client_state,json=upgradedClientState,proto3" json:"upgraded_client_state,omitempty" yaml:"upgraded_client_state"` +} + +func (m *UpgradeProposal) Reset() { *m = UpgradeProposal{} } +func (*UpgradeProposal) ProtoMessage() {} +func (*UpgradeProposal) Descriptor() ([]byte, []int) { + return fileDescriptor_b6bc4c8185546947, []int{4} +} +func (m *UpgradeProposal) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *UpgradeProposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_UpgradeProposal.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 *UpgradeProposal) XXX_Merge(src proto.Message) { + xxx_messageInfo_UpgradeProposal.Merge(m, src) +} +func (m *UpgradeProposal) XXX_Size() int { + return m.Size() +} +func (m *UpgradeProposal) XXX_DiscardUnknown() { + xxx_messageInfo_UpgradeProposal.DiscardUnknown(m) +} + +var xxx_messageInfo_UpgradeProposal proto.InternalMessageInfo + // Height is a monotonically increasing data type // that can be compared against another Height for the purposes of updating and // freezing clients @@ -261,7 +308,7 @@ type Height struct { func (m *Height) Reset() { *m = Height{} } func (*Height) ProtoMessage() {} func (*Height) Descriptor() ([]byte, []int) { - return fileDescriptor_b6bc4c8185546947, []int{4} + return fileDescriptor_b6bc4c8185546947, []int{5} } func (m *Height) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -300,7 +347,7 @@ func (m *Params) Reset() { *m = Params{} } func (m *Params) String() string { return proto.CompactTextString(m) } func (*Params) ProtoMessage() {} func (*Params) Descriptor() ([]byte, []int) { - return fileDescriptor_b6bc4c8185546947, []int{5} + return fileDescriptor_b6bc4c8185546947, []int{6} } func (m *Params) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -341,6 +388,7 @@ func init() { proto.RegisterType((*ConsensusStateWithHeight)(nil), "ibc.core.client.v1.ConsensusStateWithHeight") proto.RegisterType((*ClientConsensusStates)(nil), "ibc.core.client.v1.ClientConsensusStates") proto.RegisterType((*ClientUpdateProposal)(nil), "ibc.core.client.v1.ClientUpdateProposal") + proto.RegisterType((*UpgradeProposal)(nil), "ibc.core.client.v1.UpgradeProposal") proto.RegisterType((*Height)(nil), "ibc.core.client.v1.Height") proto.RegisterType((*Params)(nil), "ibc.core.client.v1.Params") } @@ -348,50 +396,89 @@ func init() { func init() { proto.RegisterFile("ibc/core/client/v1/client.proto", fileDescriptor_b6bc4c8185546947) } var fileDescriptor_b6bc4c8185546947 = []byte{ - // 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, + // 740 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x55, 0x3f, 0x6f, 0xd3, 0x4e, + 0x18, 0x8e, 0xd3, 0x34, 0x6a, 0x2e, 0xfd, 0x25, 0xfd, 0xb9, 0x09, 0x4d, 0x43, 0x89, 0xa3, 0x13, + 0x43, 0x06, 0x6a, 0x93, 0x20, 0x01, 0xea, 0x46, 0xb2, 0xb4, 0x03, 0x28, 0x35, 0xaa, 0x40, 0x2c, + 0xc1, 0x7f, 0xae, 0xc9, 0x15, 0xc7, 0x17, 0xf9, 0xce, 0xa1, 0xf9, 0x06, 0x8c, 0x8c, 0x0c, 0x0c, + 0xfd, 0x04, 0x7c, 0x0a, 0x86, 0x8e, 0x95, 0x58, 0x98, 0x2c, 0xd4, 0x2e, 0xcc, 0x5e, 0x59, 0x90, + 0x7d, 0xe7, 0x34, 0x49, 0x5b, 0x40, 0x30, 0xf9, 0xee, 0xbd, 0xe7, 0x9e, 0xf7, 0x7d, 0x9e, 0xbb, + 0xf7, 0x0c, 0x14, 0x6c, 0x5a, 0x9a, 0x45, 0x3c, 0xa4, 0x59, 0x0e, 0x46, 0x2e, 0xd3, 0xc6, 0x4d, + 0x31, 0x52, 0x47, 0x1e, 0x61, 0x44, 0x96, 0xb1, 0x69, 0xa9, 0x11, 0x40, 0x15, 0xe1, 0x71, 0xb3, + 0x5a, 0xea, 0x93, 0x3e, 0x89, 0x97, 0xb5, 0x68, 0xc4, 0x91, 0xd5, 0xcd, 0x3e, 0x21, 0x7d, 0x07, + 0x69, 0xf1, 0xcc, 0xf4, 0x0f, 0x35, 0xc3, 0x9d, 0x88, 0xa5, 0xbb, 0x16, 0xa1, 0x43, 0x42, 0x35, + 0x7f, 0xd4, 0xf7, 0x0c, 0x1b, 0x69, 0xe3, 0xa6, 0x89, 0x98, 0xd1, 0x4c, 0xe6, 0x1c, 0x05, 0x3f, + 0x4a, 0xa0, 0xbc, 0x67, 0x23, 0x97, 0xe1, 0x43, 0x8c, 0xec, 0x4e, 0x9c, 0xee, 0x39, 0x33, 0x18, + 0x92, 0x9b, 0x20, 0xc7, 0xb3, 0xf7, 0xb0, 0x5d, 0x91, 0xea, 0x52, 0x23, 0xd7, 0x2e, 0x85, 0x81, + 0xb2, 0x36, 0x31, 0x86, 0xce, 0x0e, 0x9c, 0x2e, 0x41, 0x7d, 0x85, 0x8f, 0xf7, 0x6c, 0xb9, 0x0b, + 0x56, 0x45, 0x9c, 0x46, 0x14, 0x95, 0x74, 0x5d, 0x6a, 0xe4, 0x5b, 0x25, 0x95, 0x17, 0xa9, 0x26, + 0x45, 0xaa, 0x4f, 0xdc, 0x49, 0x7b, 0x23, 0x0c, 0x94, 0xf5, 0x39, 0xae, 0x78, 0x0f, 0xd4, 0xf3, + 0xd6, 0x65, 0x11, 0xf0, 0x93, 0x04, 0x2a, 0x1d, 0xe2, 0x52, 0xe4, 0x52, 0x9f, 0xc6, 0xa1, 0x17, + 0x98, 0x0d, 0x76, 0x11, 0xee, 0x0f, 0x98, 0xfc, 0x18, 0x64, 0x07, 0xf1, 0x28, 0x2e, 0x2f, 0xdf, + 0xaa, 0xaa, 0x57, 0x7d, 0x53, 0x39, 0xb6, 0x9d, 0x39, 0x0d, 0x94, 0x94, 0x2e, 0xf0, 0xf2, 0x4b, + 0x50, 0xb4, 0x12, 0xd6, 0x3f, 0xa8, 0x75, 0x33, 0x0c, 0x94, 0x72, 0x54, 0x2b, 0x5c, 0xd8, 0x05, + 0xf5, 0x82, 0x35, 0x57, 0x1d, 0xfc, 0x2c, 0x81, 0x32, 0x77, 0x71, 0xbe, 0x6c, 0xfa, 0x37, 0x7e, + 0x1e, 0x83, 0xb5, 0x85, 0x84, 0xb4, 0x92, 0xae, 0x2f, 0x35, 0xf2, 0xad, 0x7b, 0xd7, 0x49, 0xbd, + 0xc9, 0xa8, 0xb6, 0x12, 0x89, 0x0f, 0x03, 0x65, 0x43, 0xe4, 0x5a, 0xe0, 0x84, 0x7a, 0x71, 0x5e, + 0x05, 0x85, 0x5f, 0xd2, 0xa0, 0xc4, 0x65, 0x1c, 0x8c, 0x6c, 0x83, 0xa1, 0xae, 0x47, 0x46, 0x84, + 0x1a, 0x8e, 0x5c, 0x02, 0xcb, 0x0c, 0x33, 0x07, 0x71, 0x05, 0x3a, 0x9f, 0xc8, 0x75, 0x90, 0xb7, + 0x11, 0xb5, 0x3c, 0x3c, 0x62, 0x98, 0xb8, 0xb1, 0x97, 0x39, 0x7d, 0x36, 0x24, 0xef, 0x82, 0xff, + 0xa9, 0x6f, 0x1e, 0x21, 0x8b, 0xf5, 0x2e, 0x5d, 0x58, 0x8a, 0x5d, 0xd8, 0x0a, 0x03, 0xa5, 0xc2, + 0x2b, 0xbb, 0x02, 0x81, 0x7a, 0x51, 0xc4, 0x3a, 0x89, 0x29, 0xfb, 0xa0, 0x44, 0x7d, 0x93, 0x32, + 0xcc, 0x7c, 0x86, 0x66, 0xc8, 0x32, 0x31, 0x99, 0x12, 0x06, 0xca, 0xed, 0x84, 0x8c, 0x9a, 0x8b, + 0x28, 0xa8, 0xcb, 0x97, 0x9b, 0xa7, 0x94, 0xaf, 0x41, 0x01, 0xbb, 0x98, 0x61, 0xc3, 0xe9, 0x89, + 0x0b, 0xb5, 0xfc, 0xdb, 0x0b, 0x75, 0x47, 0x78, 0x5a, 0xe6, 0xc9, 0xe6, 0xf7, 0x43, 0xfd, 0x3f, + 0x11, 0xe0, 0xe8, 0x9d, 0xcc, 0xbb, 0x13, 0x25, 0x05, 0x7f, 0x48, 0xa0, 0x78, 0xc0, 0xdb, 0xef, + 0x9f, 0x0d, 0x7d, 0x08, 0x32, 0x23, 0xc7, 0x70, 0x63, 0x0f, 0xf3, 0xad, 0x2d, 0x95, 0x77, 0xbb, + 0x9a, 0x74, 0xb7, 0xe8, 0x76, 0xb5, 0xeb, 0x18, 0xae, 0xb8, 0xfc, 0x31, 0x5e, 0x3e, 0x02, 0x65, + 0x81, 0xb1, 0x7b, 0x73, 0xcd, 0x9a, 0xf9, 0x45, 0x03, 0xd4, 0xc3, 0x40, 0xd9, 0xe2, 0x42, 0xaf, + 0xdd, 0x0c, 0xf5, 0xf5, 0x24, 0x3e, 0xf3, 0x84, 0xec, 0xac, 0x46, 0xaa, 0x3f, 0x9c, 0x28, 0xa9, + 0xef, 0x27, 0x8a, 0x14, 0x3d, 0x35, 0x59, 0xd1, 0xb9, 0x1d, 0x50, 0xf4, 0xd0, 0x18, 0x53, 0x4c, + 0xdc, 0x9e, 0xeb, 0x0f, 0x4d, 0xe4, 0xc5, 0xf2, 0x33, 0xed, 0x6a, 0x18, 0x28, 0xb7, 0x78, 0xa2, + 0x05, 0x00, 0xd4, 0x0b, 0x49, 0xe4, 0x59, 0x1c, 0x98, 0x23, 0x11, 0xc7, 0x96, 0xbe, 0x91, 0x24, + 0x39, 0x97, 0x29, 0x89, 0x38, 0x98, 0x95, 0xa4, 0x44, 0xf8, 0x14, 0x64, 0xbb, 0x86, 0x67, 0x0c, + 0x69, 0x44, 0x6c, 0x38, 0x0e, 0x79, 0x3b, 0x15, 0x49, 0x2b, 0x52, 0x7d, 0xa9, 0x91, 0x9b, 0x25, + 0x5e, 0x00, 0x40, 0xbd, 0x20, 0x22, 0x5c, 0x3f, 0x6d, 0xef, 0x9f, 0x9e, 0xd7, 0xa4, 0xb3, 0xf3, + 0x9a, 0xf4, 0xed, 0xbc, 0x26, 0xbd, 0xbf, 0xa8, 0xa5, 0xce, 0x2e, 0x6a, 0xa9, 0xaf, 0x17, 0xb5, + 0xd4, 0xab, 0x47, 0x7d, 0xcc, 0x06, 0xbe, 0xa9, 0x5a, 0x64, 0xa8, 0x89, 0x37, 0x9a, 0x7f, 0xb6, + 0xa9, 0xfd, 0x46, 0x3b, 0xd6, 0xa6, 0x7f, 0x87, 0xfb, 0xad, 0x6d, 0xf1, 0x83, 0x60, 0x93, 0x11, + 0xa2, 0x66, 0x36, 0x3e, 0x93, 0x07, 0x3f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x66, 0x9c, 0xf8, 0xf8, + 0x40, 0x06, 0x00, 0x00, +} + +func (this *UpgradeProposal) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*UpgradeProposal) + if !ok { + that2, ok := that.(UpgradeProposal) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Title != that1.Title { + return false + } + if this.Description != that1.Description { + return false + } + if !this.Plan.Equal(&that1.Plan) { + return false + } + if !this.UpgradedClientState.Equal(that1.UpgradedClientState) { + return false + } + return true } - func (m *IdentifiedClientState) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -584,6 +671,65 @@ func (m *ClientUpdateProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *UpgradeProposal) 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 *UpgradeProposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *UpgradeProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.UpgradedClientState != nil { + { + size, err := m.UpgradedClientState.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintClient(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + { + size, err := m.Plan.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintClient(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if len(m.Description) > 0 { + i -= len(m.Description) + copy(dAtA[i:], m.Description) + i = encodeVarintClient(dAtA, i, uint64(len(m.Description))) + i-- + dAtA[i] = 0x12 + } + if len(m.Title) > 0 { + i -= len(m.Title) + copy(dAtA[i:], m.Title) + i = encodeVarintClient(dAtA, i, uint64(len(m.Title))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func (m *Height) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -738,6 +884,29 @@ func (m *ClientUpdateProposal) Size() (n int) { return n } +func (m *UpgradeProposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Title) + if l > 0 { + n += 1 + l + sovClient(uint64(l)) + } + l = len(m.Description) + if l > 0 { + n += 1 + l + sovClient(uint64(l)) + } + l = m.Plan.Size() + n += 1 + l + sovClient(uint64(l)) + if m.UpgradedClientState != nil { + l = m.UpgradedClientState.Size() + n += 1 + l + sovClient(uint64(l)) + } + return n +} + func (m *Height) Size() (n int) { if m == nil { return 0 @@ -1338,6 +1507,189 @@ func (m *ClientUpdateProposal) Unmarshal(dAtA []byte) error { } return nil } +func (m *UpgradeProposal) 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 ErrIntOverflowClient + } + 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: UpgradeProposal: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: UpgradeProposal: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Title", 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.Title = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Description", 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.Description = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Plan", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowClient + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthClient + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthClient + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Plan.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UpgradedClientState", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowClient + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthClient + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthClient + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.UpgradedClientState == nil { + m.UpgradedClientState = &types.Any{} + } + if err := m.UpgradedClientState.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipClient(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthClient + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *Height) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/x/ibc/core/02-client/types/codec.go b/x/ibc/core/02-client/types/codec.go index 59a15832bec1..8f8ab56112c7 100644 --- a/x/ibc/core/02-client/types/codec.go +++ b/x/ibc/core/02-client/types/codec.go @@ -37,6 +37,7 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) { registry.RegisterImplementations( (*govtypes.Content)(nil), &ClientUpdateProposal{}, + &UpgradeProposal{}, ) registry.RegisterImplementations( (*sdk.Msg)(nil), diff --git a/x/ibc/core/02-client/types/errors.go b/x/ibc/core/02-client/types/errors.go index 5b44cd522211..8a956f868730 100644 --- a/x/ibc/core/02-client/types/errors.go +++ b/x/ibc/core/02-client/types/errors.go @@ -32,4 +32,5 @@ var ( ErrInvalidUpgradeClient = sdkerrors.Register(SubModuleName, 25, "invalid client upgrade") ErrInvalidHeight = sdkerrors.Register(SubModuleName, 26, "invalid height") ErrInvalidSubstitute = sdkerrors.Register(SubModuleName, 27, "invalid client state substitute") + ErrInvalidUpgradeProposal = sdkerrors.Register(SubModuleName, 28, "invalid upgrade proposal") ) diff --git a/x/ibc/core/02-client/types/expected_keepers.go b/x/ibc/core/02-client/types/expected_keepers.go index defc81506b1d..ad007fb8011c 100644 --- a/x/ibc/core/02-client/types/expected_keepers.go +++ b/x/ibc/core/02-client/types/expected_keepers.go @@ -5,6 +5,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" ) // StakingKeeper expected staking keeper @@ -12,3 +13,13 @@ type StakingKeeper interface { GetHistoricalInfo(ctx sdk.Context, height int64) (stakingtypes.HistoricalInfo, bool) UnbondingTime(ctx sdk.Context) time.Duration } + +// UpgradeKeeper expected upgrade keeper +type UpgradeKeeper interface { + ClearIBCState(ctx sdk.Context, lastHeight int64) + GetUpgradePlan(ctx sdk.Context) (plan upgradetypes.Plan, havePlan bool) + GetUpgradedClient(ctx sdk.Context, height int64) ([]byte, bool) + SetUpgradedConsensusState(ctx sdk.Context, planHeight int64, bz []byte) error + SetUpgradedClient(ctx sdk.Context, planHeight int64, bz []byte) error + ScheduleUpgrade(ctx sdk.Context, plan upgradetypes.Plan) error +} diff --git a/x/ibc/core/02-client/types/proposal.go b/x/ibc/core/02-client/types/proposal.go index 95b10aaf408e..ed67e45425c4 100644 --- a/x/ibc/core/02-client/types/proposal.go +++ b/x/ibc/core/02-client/types/proposal.go @@ -1,23 +1,34 @@ package types import ( + "fmt" + + 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" + "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" ) const ( // ProposalTypeClientUpdate defines the type for a ClientUpdateProposal ProposalTypeClientUpdate = "ClientUpdate" + ProposalTypeUpgrade = "IBCUpgrade" ) -var _ govtypes.Content = &ClientUpdateProposal{} +var ( + _ govtypes.Content = &ClientUpdateProposal{} + _ govtypes.Content = &UpgradeProposal{} + _ codectypes.UnpackInterfacesMessage = &UpgradeProposal{} +) func init() { govtypes.RegisterProposalType(ProposalTypeClientUpdate) + govtypes.RegisterProposalType(ProposalTypeUpgrade) } // NewClientUpdateProposal creates a new client update proposal. -func NewClientUpdateProposal(title, description, subjectClientID, substituteClientID string, initialHeight Height) *ClientUpdateProposal { +func NewClientUpdateProposal(title, description, subjectClientID, substituteClientID string, initialHeight Height) govtypes.Content { return &ClientUpdateProposal{ Title: title, Description: description, @@ -62,3 +73,82 @@ func (cup *ClientUpdateProposal) ValidateBasic() error { return nil } + +// NewUpgradeProposal creates a new IBC breaking upgrade proposal. +func NewUpgradeProposal(title, description string, plan upgradetypes.Plan, upgradedClientState exported.ClientState) (govtypes.Content, error) { + any, err := PackClientState(upgradedClientState) + if err != nil { + return nil, err + } + + return &UpgradeProposal{ + Title: title, + Description: description, + Plan: plan, + UpgradedClientState: any, + }, nil +} + +// GetTitle returns the title of a upgrade proposal. +func (up *UpgradeProposal) GetTitle() string { return up.Title } + +// GetDescription returns the description of a upgrade proposal. +func (up *UpgradeProposal) GetDescription() string { return up.Description } + +// ProposalRoute returns the routing key of a upgrade proposal. +func (up *UpgradeProposal) ProposalRoute() string { return RouterKey } + +// ProposalType returns the upgrade proposal type. +func (up *UpgradeProposal) ProposalType() string { return ProposalTypeUpgrade } + +// ValidateBasic runs basic stateless validity checks +func (up *UpgradeProposal) ValidateBasic() error { + if err := govtypes.ValidateAbstract(up); err != nil { + return err + } + + if err := up.Plan.ValidateBasic(); err != nil { + return err + } + + if up.Plan.Time.Unix() > 0 { + return sdkerrors.Wrap(ErrInvalidUpgradeProposal, "IBC chain upgrades must only set height") + } + + if up.Plan.Height <= 0 { + return sdkerrors.Wrap(ErrInvalidUpgradeProposal, "IBC chain upgrades must set a positive height") + } + + if up.UpgradedClientState == nil { + return sdkerrors.Wrap(ErrInvalidUpgradeProposal, "upgraded client state cannot be nil") + } + + _, err := UnpackClientState(up.UpgradedClientState) + if err != nil { + return sdkerrors.Wrap(err, "failed to unpack upgraded client state") + } + + return nil +} + +// String returns the string representation of the UpgradeProposal. +func (up UpgradeProposal) String() string { + var upgradedClientStr string + upgradedClient, err := UnpackClientState(up.UpgradedClientState) + if err != nil { + upgradedClientStr = "invalid IBC Client State" + } else { + upgradedClientStr = upgradedClient.String() + } + + return fmt.Sprintf(`IBC Upgrade Proposal + Title: %s + Description: %s + %s + Upgraded IBC Client: %s`, up.Title, up.Description, up.Plan, upgradedClientStr) +} + +// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces +func (up UpgradeProposal) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { + return unpacker.UnpackAny(up.UpgradedClientState, new(exported.ClientState)) +} diff --git a/x/ibc/core/02-client/types/proposal_test.go b/x/ibc/core/02-client/types/proposal_test.go index 597e5cf8f801..a7337081abd3 100644 --- a/x/ibc/core/02-client/types/proposal_test.go +++ b/x/ibc/core/02-client/types/proposal_test.go @@ -1,12 +1,17 @@ package types_test import ( + "fmt" + "time" + "github.com/cosmos/cosmos-sdk/codec" 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" "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" + ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" ) func (suite *TypesTestSuite) TestValidateBasic() { @@ -76,7 +81,8 @@ func (suite *TypesTestSuite) TestMarshalClientUpdateProposalProposal() { cdc := codec.NewProtoCodec(ir) // marshal message - bz, err := cdc.MarshalJSON(proposal) + content := proposal.(*types.ClientUpdateProposal) + bz, err := cdc.MarshalJSON(content) suite.Require().NoError(err) // unmarshal proposal @@ -84,3 +90,145 @@ func (suite *TypesTestSuite) TestMarshalClientUpdateProposalProposal() { err = cdc.UnmarshalJSON(bz, newProposal) suite.Require().NoError(err) } + +func (suite *TypesTestSuite) TestUpgradeProposalValidateBasic() { + var ( + proposal govtypes.Content + err error + ) + + client, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) + cs := suite.chainA.GetClientState(client) + plan := upgradetypes.Plan{ + Name: "ibc upgrade", + Height: 1000, + } + + testCases := []struct { + name string + malleate func() + expPass bool + }{ + { + "success", func() { + proposal, err = types.NewUpgradeProposal(ibctesting.Title, ibctesting.Description, plan, cs) + suite.Require().NoError(err) + }, true, + }, + { + "fails validate abstract - empty title", func() { + proposal, err = types.NewUpgradeProposal("", ibctesting.Description, plan, cs) + suite.Require().NoError(err) + + }, false, + }, + { + "fails plan validate basic, height and time is 0", func() { + invalidPlan := upgradetypes.Plan{Name: "ibc upgrade"} + proposal, err = types.NewUpgradeProposal(ibctesting.Title, ibctesting.Description, invalidPlan, cs) + suite.Require().NoError(err) + }, false, + }, + { + "plan height is zero", func() { + invalidPlan := upgradetypes.Plan{Name: "ibc upgrade", Height: 0} + proposal, err = types.NewUpgradeProposal(ibctesting.Title, ibctesting.Description, invalidPlan, cs) + suite.Require().NoError(err) + }, false, + }, + { + "plan time is not set to 0", func() { + invalidPlan := upgradetypes.Plan{Name: "ibc upgrade", Time: time.Now()} + proposal, err = types.NewUpgradeProposal(ibctesting.Title, ibctesting.Description, invalidPlan, cs) + suite.Require().NoError(err) + }, false, + }, + { + "client state is nil", func() { + proposal = &types.UpgradeProposal{ + Title: ibctesting.Title, + Description: ibctesting.Description, + Plan: plan, + UpgradedClientState: nil, + } + }, false, + }, + { + "failed to unpack client state", func() { + any, err := types.PackConsensusState(&ibctmtypes.ConsensusState{}) + suite.Require().NoError(err) + + proposal = &types.UpgradeProposal{ + Title: ibctesting.Title, + Description: ibctesting.Description, + Plan: plan, + UpgradedClientState: any, + } + }, false, + }, + } + + for _, tc := range testCases { + + tc.malleate() + + err := proposal.ValidateBasic() + + if tc.expPass { + suite.Require().NoError(err, tc.name) + } else { + suite.Require().Error(err, tc.name) + } + } +} + +// tests an upgrade proposal can be marshaled and unmarshaled, and the +// client state can be unpacked +func (suite *TypesTestSuite) TestMarshalUpgradeProposal() { + // create proposal + plan := upgradetypes.Plan{ + Name: "upgrade ibc", + Height: 1000, + } + content, err := types.NewUpgradeProposal("title", "description", plan, &ibctmtypes.ClientState{}) + suite.Require().NoError(err) + + up, ok := content.(*types.UpgradeProposal) + suite.Require().True(ok) + + // create codec + ir := codectypes.NewInterfaceRegistry() + types.RegisterInterfaces(ir) + govtypes.RegisterInterfaces(ir) + ibctmtypes.RegisterInterfaces(ir) + cdc := codec.NewProtoCodec(ir) + + // marshal message + bz, err := cdc.MarshalJSON(up) + suite.Require().NoError(err) + + // unmarshal proposal + newUp := &types.UpgradeProposal{} + err = cdc.UnmarshalJSON(bz, newUp) + suite.Require().NoError(err) + + // unpack client state + _, err = types.UnpackClientState(newUp.UpgradedClientState) + suite.Require().NoError(err) + +} + +func (suite *TypesTestSuite) TestUpgradeString() { + plan := upgradetypes.Plan{ + Name: "ibc upgrade", + Info: "https://foo.bar/baz", + Height: 1000, + } + + proposal, err := types.NewUpgradeProposal(ibctesting.Title, ibctesting.Description, plan, &ibctmtypes.ClientState{}) + suite.Require().NoError(err) + + expect := fmt.Sprintf("IBC Upgrade Proposal\n Title: title\n Description: description\n Upgrade Plan\n Name: ibc upgrade\n Height: 1000\n Info: https://foo.bar/baz.\n Upgraded IBC Client: %s", &ibctmtypes.ClientState{}) + + suite.Require().Equal(expect, proposal.String()) +} diff --git a/x/ibc/core/02-client/types/query.pb.go b/x/ibc/core/02-client/types/query.pb.go index 651becb899ae..27c5cb884140 100644 --- a/x/ibc/core/02-client/types/query.pb.go +++ b/x/ibc/core/02-client/types/query.pb.go @@ -583,6 +583,110 @@ func (m *QueryClientParamsResponse) GetParams() *Params { return nil } +// QueryUpgradedClientStateRequest is the request type for the Query/UpgradedClientState RPC +// method +type QueryUpgradedClientStateRequest struct { + // client state unique identifier + ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"` + // plan height of the current chain must be sent in request + // as this is the height under which upgraded client state is stored + PlanHeight int64 `protobuf:"varint,2,opt,name=plan_height,json=planHeight,proto3" json:"plan_height,omitempty"` +} + +func (m *QueryUpgradedClientStateRequest) Reset() { *m = QueryUpgradedClientStateRequest{} } +func (m *QueryUpgradedClientStateRequest) String() string { return proto.CompactTextString(m) } +func (*QueryUpgradedClientStateRequest) ProtoMessage() {} +func (*QueryUpgradedClientStateRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_dc42cdfd1d52d76e, []int{10} +} +func (m *QueryUpgradedClientStateRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryUpgradedClientStateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryUpgradedClientStateRequest.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 *QueryUpgradedClientStateRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryUpgradedClientStateRequest.Merge(m, src) +} +func (m *QueryUpgradedClientStateRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryUpgradedClientStateRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryUpgradedClientStateRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryUpgradedClientStateRequest proto.InternalMessageInfo + +func (m *QueryUpgradedClientStateRequest) GetClientId() string { + if m != nil { + return m.ClientId + } + return "" +} + +func (m *QueryUpgradedClientStateRequest) GetPlanHeight() int64 { + if m != nil { + return m.PlanHeight + } + return 0 +} + +// QueryUpgradedClientStateResponse is the response type for the Query/UpgradedClientState RPC +// method. +type QueryUpgradedClientStateResponse struct { + // client state associated with the request identifier + UpgradedClientState *types.Any `protobuf:"bytes,1,opt,name=upgraded_client_state,json=upgradedClientState,proto3" json:"upgraded_client_state,omitempty"` +} + +func (m *QueryUpgradedClientStateResponse) Reset() { *m = QueryUpgradedClientStateResponse{} } +func (m *QueryUpgradedClientStateResponse) String() string { return proto.CompactTextString(m) } +func (*QueryUpgradedClientStateResponse) ProtoMessage() {} +func (*QueryUpgradedClientStateResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_dc42cdfd1d52d76e, []int{11} +} +func (m *QueryUpgradedClientStateResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryUpgradedClientStateResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryUpgradedClientStateResponse.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 *QueryUpgradedClientStateResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryUpgradedClientStateResponse.Merge(m, src) +} +func (m *QueryUpgradedClientStateResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryUpgradedClientStateResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryUpgradedClientStateResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryUpgradedClientStateResponse proto.InternalMessageInfo + +func (m *QueryUpgradedClientStateResponse) GetUpgradedClientState() *types.Any { + if m != nil { + return m.UpgradedClientState + } + return nil +} + func init() { proto.RegisterType((*QueryClientStateRequest)(nil), "ibc.core.client.v1.QueryClientStateRequest") proto.RegisterType((*QueryClientStateResponse)(nil), "ibc.core.client.v1.QueryClientStateResponse") @@ -594,64 +698,71 @@ func init() { proto.RegisterType((*QueryConsensusStatesResponse)(nil), "ibc.core.client.v1.QueryConsensusStatesResponse") proto.RegisterType((*QueryClientParamsRequest)(nil), "ibc.core.client.v1.QueryClientParamsRequest") proto.RegisterType((*QueryClientParamsResponse)(nil), "ibc.core.client.v1.QueryClientParamsResponse") + proto.RegisterType((*QueryUpgradedClientStateRequest)(nil), "ibc.core.client.v1.QueryUpgradedClientStateRequest") + proto.RegisterType((*QueryUpgradedClientStateResponse)(nil), "ibc.core.client.v1.QueryUpgradedClientStateResponse") } func init() { proto.RegisterFile("ibc/core/client/v1/query.proto", fileDescriptor_dc42cdfd1d52d76e) } var fileDescriptor_dc42cdfd1d52d76e = []byte{ - // 824 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0x4d, 0x4f, 0xdb, 0x48, - 0x18, 0xce, 0xf0, 0x25, 0x98, 0x04, 0xb2, 0x1a, 0xa1, 0xdd, 0x60, 0x90, 0x89, 0xbc, 0x12, 0x64, - 0x77, 0x61, 0x86, 0x64, 0x3f, 0x90, 0x56, 0xe2, 0xb0, 0x20, 0xb1, 0xe5, 0xd2, 0x82, 0x7b, 0xa8, - 0x54, 0xa9, 0x42, 0xb6, 0x33, 0x38, 0x16, 0xc4, 0x13, 0x32, 0x4e, 0x54, 0x84, 0xb8, 0xf0, 0x07, - 0x5a, 0xa9, 0xc7, 0x5e, 0x7b, 0xea, 0xa1, 0xaa, 0xd4, 0x43, 0xff, 0x41, 0xc5, 0x11, 0xa9, 0x3d, - 0xf4, 0xd4, 0x56, 0xc0, 0xbf, 0xe8, 0xa5, 0xf2, 0xcc, 0x18, 0xec, 0xc4, 0x08, 0x0b, 0xb5, 0xa7, - 0xd8, 0xef, 0xd7, 0x3c, 0xcf, 0xf3, 0xbe, 0xef, 0x38, 0x50, 0xf7, 0x6c, 0x87, 0x38, 0xac, 0x4d, - 0x89, 0xb3, 0xe7, 0x51, 0x3f, 0x20, 0xdd, 0x2a, 0xd9, 0xef, 0xd0, 0xf6, 0x01, 0x6e, 0xb5, 0x59, - 0xc0, 0x10, 0xf2, 0x6c, 0x07, 0x87, 0x7e, 0x2c, 0xfd, 0xb8, 0x5b, 0xd5, 0x7e, 0x77, 0x18, 0x6f, - 0x32, 0x4e, 0x6c, 0x8b, 0x53, 0x19, 0x4c, 0xba, 0x55, 0x9b, 0x06, 0x56, 0x95, 0xb4, 0x2c, 0xd7, - 0xf3, 0xad, 0xc0, 0x63, 0xbe, 0xcc, 0xd7, 0x66, 0x53, 0xea, 0xab, 0x4a, 0x32, 0x60, 0xca, 0x65, - 0xcc, 0xdd, 0xa3, 0x44, 0xbc, 0xd9, 0x9d, 0x1d, 0x62, 0xf9, 0xea, 0x6c, 0x6d, 0x46, 0xb9, 0xac, - 0x96, 0x47, 0x2c, 0xdf, 0x67, 0x81, 0x28, 0xcc, 0x95, 0x77, 0xd2, 0x65, 0x2e, 0x13, 0x8f, 0x24, - 0x7c, 0x92, 0x56, 0xe3, 0x1f, 0xf8, 0xcb, 0x56, 0x88, 0x68, 0x4d, 0x9c, 0x71, 0x3f, 0xb0, 0x02, - 0x6a, 0xd2, 0xfd, 0x0e, 0xe5, 0x01, 0x9a, 0x86, 0x63, 0xf2, 0xe4, 0x6d, 0xaf, 0x5e, 0x02, 0x65, - 0x50, 0x19, 0x33, 0x47, 0xa5, 0x61, 0xa3, 0x6e, 0xbc, 0x02, 0xb0, 0xd4, 0x9f, 0xc8, 0x5b, 0xcc, - 0xe7, 0x14, 0x2d, 0xc3, 0x82, 0xca, 0xe4, 0xa1, 0x5d, 0x24, 0xe7, 0x6b, 0x93, 0x58, 0xe2, 0xc3, - 0x11, 0x74, 0xfc, 0x9f, 0x7f, 0x60, 0xe6, 0x9d, 0xab, 0x02, 0x68, 0x12, 0x0e, 0xb7, 0xda, 0x8c, - 0xed, 0x94, 0x06, 0xca, 0xa0, 0x52, 0x30, 0xe5, 0x0b, 0x5a, 0x83, 0x05, 0xf1, 0xb0, 0xdd, 0xa0, - 0x9e, 0xdb, 0x08, 0x4a, 0x83, 0xa2, 0x9c, 0x86, 0xfb, 0xa5, 0xc6, 0x77, 0x44, 0xc4, 0xea, 0xd0, - 0xc9, 0xa7, 0xd9, 0x9c, 0x99, 0x17, 0x59, 0xd2, 0x64, 0xd8, 0xfd, 0x78, 0x79, 0xc4, 0x74, 0x1d, - 0xc2, 0xab, 0x46, 0x28, 0xb4, 0x73, 0x58, 0x76, 0x0d, 0x87, 0x5d, 0xc3, 0xb2, 0xc5, 0xaa, 0x6b, - 0x78, 0xd3, 0x72, 0x23, 0x95, 0xcc, 0x58, 0xa6, 0xf1, 0x01, 0xc0, 0xa9, 0x94, 0x43, 0x94, 0x2a, - 0x3e, 0x1c, 0x8f, 0xab, 0xc2, 0x4b, 0xa0, 0x3c, 0x58, 0xc9, 0xd7, 0x7e, 0x4b, 0xe3, 0xb1, 0x51, - 0xa7, 0x7e, 0xe0, 0xed, 0x78, 0xb4, 0x1e, 0x2b, 0xb5, 0xaa, 0x87, 0xb4, 0x5e, 0x7e, 0x9e, 0xfd, - 0x39, 0xd5, 0xcd, 0xcd, 0x42, 0x4c, 0x4b, 0x8e, 0xfe, 0x4f, 0xb0, 0x1a, 0x10, 0xac, 0xe6, 0x6f, - 0x64, 0x25, 0xc1, 0x26, 0x68, 0xbd, 0x06, 0x50, 0x93, 0xb4, 0x42, 0x97, 0xcf, 0x3b, 0x3c, 0xf3, - 0x9c, 0xa0, 0x79, 0x58, 0x6c, 0xd3, 0xae, 0xc7, 0x3d, 0xe6, 0x6f, 0xfb, 0x9d, 0xa6, 0x4d, 0xdb, - 0x02, 0xc9, 0x90, 0x39, 0x11, 0x99, 0xef, 0x0a, 0x6b, 0x22, 0x30, 0xd6, 0xe7, 0x58, 0xa0, 0x6c, - 0x24, 0xfa, 0x15, 0x8e, 0xef, 0x85, 0xfc, 0x82, 0x28, 0x6c, 0xa8, 0x0c, 0x2a, 0xa3, 0x66, 0x41, - 0x1a, 0x55, 0xb7, 0xdf, 0x02, 0x38, 0x9d, 0x0a, 0x59, 0xf5, 0x62, 0x05, 0x16, 0x9d, 0xc8, 0x93, - 0x61, 0x48, 0x27, 0x9c, 0x44, 0x99, 0x1f, 0x39, 0xa7, 0xc7, 0xe9, 0xc8, 0x79, 0x26, 0xb5, 0xd7, - 0x53, 0x5a, 0x7e, 0x9b, 0x41, 0x7e, 0x07, 0xe0, 0x4c, 0x3a, 0x08, 0xa5, 0xdf, 0x23, 0xf8, 0x53, - 0x8f, 0x7e, 0xd1, 0x38, 0x2f, 0xa4, 0xd1, 0x4d, 0x96, 0x79, 0xe0, 0x05, 0x8d, 0x84, 0x00, 0xc5, - 0xa4, 0xbc, 0xdf, 0x71, 0x74, 0xb5, 0xc4, 0xd6, 0x6f, 0x5a, 0x6d, 0xab, 0x19, 0x29, 0x69, 0xdc, - 0x4b, 0x2c, 0x6b, 0xe4, 0x53, 0x04, 0x6b, 0x70, 0xa4, 0x25, 0x2c, 0x6a, 0x2e, 0x52, 0xbb, 0xa8, - 0x72, 0x54, 0x64, 0xed, 0xeb, 0x08, 0x1c, 0x16, 0x15, 0xd1, 0x0b, 0x00, 0xf3, 0xb1, 0xcd, 0x44, - 0x7f, 0xa4, 0x65, 0x5f, 0x73, 0xef, 0x6a, 0x0b, 0xd9, 0x82, 0x25, 0x50, 0xe3, 0xdf, 0xe3, 0xf7, - 0x17, 0xcf, 0x06, 0xfe, 0x42, 0x35, 0xd2, 0xff, 0xe5, 0x90, 0xdf, 0x98, 0xc4, 0xa5, 0x43, 0x0e, - 0x2f, 0xa7, 0xe7, 0x08, 0x3d, 0x07, 0xb0, 0x10, 0xbf, 0x40, 0x50, 0xa6, 0xa3, 0x23, 0x01, 0xb5, - 0xc5, 0x8c, 0xd1, 0x0a, 0x29, 0x16, 0x48, 0x2b, 0x68, 0x2e, 0x1b, 0x52, 0x74, 0x01, 0xe0, 0x44, - 0x72, 0x70, 0x10, 0xbe, 0xfe, 0xc4, 0xb4, 0xab, 0x49, 0x23, 0x99, 0xe3, 0x15, 0xc6, 0x7d, 0x81, - 0x71, 0x17, 0x79, 0xd7, 0x63, 0xec, 0x19, 0xfb, 0xb8, 0xa0, 0x24, 0xba, 0xaa, 0xc8, 0x61, 0xcf, - 0xa5, 0x77, 0x44, 0xe4, 0x9d, 0x10, 0x73, 0x48, 0xc3, 0x11, 0x7a, 0x03, 0x60, 0xb1, 0x67, 0xcd, - 0x50, 0x56, 0xdc, 0x97, 0xad, 0x58, 0xca, 0x9e, 0xa0, 0x98, 0xae, 0x08, 0xa6, 0xcb, 0xe8, 0xef, - 0x5b, 0x31, 0x45, 0x4f, 0x2e, 0x47, 0x47, 0x2e, 0xc1, 0x8d, 0xa3, 0x93, 0xd8, 0xbd, 0x1b, 0x47, - 0x27, 0xb9, 0x8d, 0x86, 0x21, 0xc0, 0xce, 0x20, 0x4d, 0x82, 0x4d, 0xe2, 0x94, 0xdb, 0xb7, 0xba, - 0x75, 0x72, 0xa6, 0x83, 0xd3, 0x33, 0x1d, 0x7c, 0x39, 0xd3, 0xc1, 0xd3, 0x73, 0x3d, 0x77, 0x7a, - 0xae, 0xe7, 0x3e, 0x9e, 0xeb, 0xb9, 0x87, 0xcb, 0xae, 0x17, 0x34, 0x3a, 0x36, 0x76, 0x58, 0x93, - 0xa8, 0xbf, 0x62, 0xf2, 0x67, 0x91, 0xd7, 0x77, 0xc9, 0xe3, 0x2b, 0x01, 0x96, 0x6a, 0x8b, 0xaa, - 0x76, 0x70, 0xd0, 0xa2, 0xdc, 0x1e, 0x11, 0x1f, 0x81, 0x3f, 0xbf, 0x05, 0x00, 0x00, 0xff, 0xff, - 0xa7, 0x0d, 0x7c, 0x62, 0xf5, 0x09, 0x00, 0x00, + // 909 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0x4d, 0x8f, 0xdb, 0x44, + 0x18, 0xce, 0xec, 0x6e, 0xab, 0xed, 0x24, 0xdd, 0xa0, 0xe9, 0x02, 0xa9, 0xbb, 0x72, 0x22, 0x23, + 0xb5, 0x01, 0xba, 0x33, 0x4d, 0x5a, 0xba, 0x08, 0xa9, 0x48, 0x6c, 0xa5, 0xd2, 0x5e, 0xa0, 0x35, + 0x42, 0x48, 0x48, 0x28, 0xb2, 0x9d, 0x59, 0xc7, 0x6a, 0xe2, 0xf1, 0x7a, 0xec, 0x88, 0x55, 0xb5, + 0x97, 0xfe, 0x01, 0x90, 0x38, 0x72, 0xe5, 0xc4, 0x01, 0x21, 0x71, 0xe0, 0x86, 0x38, 0xa1, 0x1e, + 0x2b, 0xc1, 0x81, 0x13, 0xa0, 0xdd, 0xfe, 0x10, 0xe4, 0x99, 0x71, 0xd6, 0x93, 0x38, 0x5a, 0xb3, + 0xa2, 0xa7, 0xd8, 0xef, 0xe7, 0xf3, 0x3e, 0xef, 0x87, 0x03, 0xcd, 0xc0, 0xf5, 0x88, 0xc7, 0x62, + 0x4a, 0xbc, 0x71, 0x40, 0xc3, 0x84, 0x4c, 0x7b, 0x64, 0x3f, 0xa5, 0xf1, 0x01, 0x8e, 0x62, 0x96, + 0x30, 0x84, 0x02, 0xd7, 0xc3, 0x99, 0x1e, 0x4b, 0x3d, 0x9e, 0xf6, 0x8c, 0xb7, 0x3c, 0xc6, 0x27, + 0x8c, 0x13, 0xd7, 0xe1, 0x54, 0x1a, 0x93, 0x69, 0xcf, 0xa5, 0x89, 0xd3, 0x23, 0x91, 0xe3, 0x07, + 0xa1, 0x93, 0x04, 0x2c, 0x94, 0xfe, 0x46, 0xbb, 0x24, 0xbe, 0x8a, 0x24, 0x0d, 0x2e, 0xfb, 0x8c, + 0xf9, 0x63, 0x4a, 0xc4, 0x9b, 0x9b, 0xee, 0x11, 0x27, 0x54, 0xb9, 0x8d, 0x2d, 0xa5, 0x72, 0xa2, + 0x80, 0x38, 0x61, 0xc8, 0x12, 0x11, 0x98, 0x2b, 0xed, 0xa6, 0xcf, 0x7c, 0x26, 0x1e, 0x49, 0xf6, + 0x24, 0xa5, 0xd6, 0x6d, 0xf8, 0xfa, 0xa3, 0x0c, 0xd1, 0x5d, 0x91, 0xe3, 0x93, 0xc4, 0x49, 0xa8, + 0x4d, 0xf7, 0x53, 0xca, 0x13, 0x74, 0x05, 0x5e, 0x90, 0x99, 0x07, 0xc1, 0xb0, 0x05, 0x3a, 0xa0, + 0x7b, 0xc1, 0x5e, 0x97, 0x82, 0x07, 0x43, 0xeb, 0x07, 0x00, 0x5b, 0x8b, 0x8e, 0x3c, 0x62, 0x21, + 0xa7, 0x68, 0x07, 0x36, 0x94, 0x27, 0xcf, 0xe4, 0xc2, 0xb9, 0xde, 0xdf, 0xc4, 0x12, 0x1f, 0xce, + 0xa1, 0xe3, 0x0f, 0xc2, 0x03, 0xbb, 0xee, 0x9d, 0x04, 0x40, 0x9b, 0xf0, 0x5c, 0x14, 0x33, 0xb6, + 0xd7, 0x5a, 0xe9, 0x80, 0x6e, 0xc3, 0x96, 0x2f, 0xe8, 0x2e, 0x6c, 0x88, 0x87, 0xc1, 0x88, 0x06, + 0xfe, 0x28, 0x69, 0xad, 0x8a, 0x70, 0x06, 0x5e, 0xa4, 0x1a, 0xdf, 0x17, 0x16, 0xbb, 0x6b, 0xcf, + 0xfe, 0x6a, 0xd7, 0xec, 0xba, 0xf0, 0x92, 0x22, 0xcb, 0x5d, 0xc4, 0xcb, 0xf3, 0x4a, 0xef, 0x41, + 0x78, 0xd2, 0x08, 0x85, 0xf6, 0x2a, 0x96, 0x5d, 0xc3, 0x59, 0xd7, 0xb0, 0x6c, 0xb1, 0xea, 0x1a, + 0x7e, 0xe8, 0xf8, 0x39, 0x4b, 0x76, 0xc1, 0xd3, 0xfa, 0x03, 0xc0, 0xcb, 0x25, 0x49, 0x14, 0x2b, + 0x21, 0xbc, 0x58, 0x64, 0x85, 0xb7, 0x40, 0x67, 0xb5, 0x5b, 0xef, 0xbf, 0x59, 0x56, 0xc7, 0x83, + 0x21, 0x0d, 0x93, 0x60, 0x2f, 0xa0, 0xc3, 0x42, 0xa8, 0x5d, 0x33, 0x2b, 0xeb, 0xfb, 0xbf, 0xdb, + 0xaf, 0x95, 0xaa, 0xb9, 0xdd, 0x28, 0x70, 0xc9, 0xd1, 0x87, 0x5a, 0x55, 0x2b, 0xa2, 0xaa, 0x6b, + 0xa7, 0x56, 0x25, 0xc1, 0x6a, 0x65, 0xfd, 0x08, 0xa0, 0x21, 0xcb, 0xca, 0x54, 0x21, 0x4f, 0x79, + 0xe5, 0x39, 0x41, 0xd7, 0x60, 0x33, 0xa6, 0xd3, 0x80, 0x07, 0x2c, 0x1c, 0x84, 0xe9, 0xc4, 0xa5, + 0xb1, 0x40, 0xb2, 0x66, 0x6f, 0xe4, 0xe2, 0x8f, 0x84, 0x54, 0x33, 0x2c, 0xf4, 0xb9, 0x60, 0x28, + 0x1b, 0x89, 0xde, 0x80, 0x17, 0xc7, 0x59, 0x7d, 0x49, 0x6e, 0xb6, 0xd6, 0x01, 0xdd, 0x75, 0xbb, + 0x21, 0x85, 0xaa, 0xdb, 0x3f, 0x03, 0x78, 0xa5, 0x14, 0xb2, 0xea, 0xc5, 0x1d, 0xd8, 0xf4, 0x72, + 0x4d, 0x85, 0x21, 0xdd, 0xf0, 0xb4, 0x30, 0x2f, 0x73, 0x4e, 0x9f, 0x96, 0x23, 0xe7, 0x95, 0xd8, + 0xbe, 0x57, 0xd2, 0xf2, 0xb3, 0x0c, 0xf2, 0x6f, 0x00, 0x6e, 0x95, 0x83, 0x50, 0xfc, 0x7d, 0x01, + 0x5f, 0x99, 0xe3, 0x2f, 0x1f, 0xe7, 0xeb, 0x65, 0xe5, 0xea, 0x61, 0x3e, 0x0b, 0x92, 0x91, 0x46, + 0x40, 0x53, 0xa7, 0xf7, 0x7f, 0x1c, 0x5d, 0x43, 0xdb, 0xfa, 0x87, 0x4e, 0xec, 0x4c, 0x72, 0x26, + 0xad, 0x8f, 0xb5, 0x65, 0xcd, 0x75, 0xaa, 0xc0, 0x3e, 0x3c, 0x1f, 0x09, 0x89, 0x9a, 0x8b, 0xd2, + 0x2e, 0x2a, 0x1f, 0x65, 0x69, 0x0d, 0x60, 0x5b, 0x04, 0xfc, 0x34, 0xf2, 0x63, 0x67, 0xa8, 0xed, + 0x66, 0xa5, 0xee, 0xb5, 0x61, 0x3d, 0x1a, 0x3b, 0xb3, 0xf1, 0xcf, 0xca, 0x5e, 0xb5, 0x61, 0x26, + 0x52, 0xb3, 0x31, 0x86, 0x9d, 0xe5, 0x09, 0x14, 0xf0, 0xfb, 0xf0, 0xd5, 0x54, 0xa9, 0x07, 0x95, + 0x8f, 0xf0, 0xa5, 0x74, 0x31, 0x62, 0xff, 0x97, 0x75, 0x78, 0x4e, 0xa4, 0x43, 0xdf, 0x01, 0x58, + 0x2f, 0x68, 0xd0, 0xdb, 0x65, 0x64, 0x2c, 0xf9, 0x8c, 0x18, 0xd7, 0xab, 0x19, 0x4b, 0xf8, 0xd6, + 0x7b, 0x4f, 0x7f, 0x7f, 0xf1, 0xcd, 0xca, 0x2d, 0xd4, 0x27, 0x8b, 0x1f, 0x42, 0xf9, 0xc9, 0xd4, + 0x6e, 0x28, 0x79, 0x32, 0xa3, 0xf3, 0x10, 0x7d, 0x0b, 0x60, 0xa3, 0x78, 0x0f, 0x51, 0xa5, 0xd4, + 0xf9, 0x3c, 0x18, 0xdb, 0x15, 0xad, 0x15, 0x52, 0x2c, 0x90, 0x76, 0xd1, 0xd5, 0x6a, 0x48, 0xd1, + 0x0b, 0x00, 0x37, 0xf4, 0x3d, 0x40, 0x78, 0x79, 0xc6, 0xb2, 0x4b, 0x6b, 0x90, 0xca, 0xf6, 0x0a, + 0xe3, 0xbe, 0xc0, 0xf8, 0x18, 0x05, 0xcb, 0x31, 0xce, 0x6d, 0x71, 0x91, 0x50, 0x92, 0x5f, 0x5e, + 0xf2, 0x64, 0xee, 0x86, 0x1f, 0x12, 0x39, 0xa3, 0x05, 0x85, 0x14, 0x1c, 0xa2, 0x9f, 0x00, 0x6c, + 0xce, 0x5d, 0x0d, 0x54, 0x15, 0xf7, 0xac, 0x15, 0x37, 0xaa, 0x3b, 0xa8, 0x4a, 0xef, 0x88, 0x4a, + 0x77, 0xd0, 0x3b, 0x67, 0xaa, 0x14, 0x7d, 0x35, 0x1b, 0x1d, 0xb9, 0xd3, 0xa7, 0x8e, 0x8e, 0x76, + 0x4a, 0x4e, 0x1d, 0x1d, 0xfd, 0xb8, 0x58, 0x96, 0x00, 0xbb, 0x85, 0x0c, 0x09, 0x56, 0xc7, 0x29, + 0x8f, 0x09, 0xfa, 0x15, 0xc0, 0x4b, 0x25, 0x7b, 0x8e, 0x6e, 0x2e, 0x4d, 0xb5, 0xfc, 0xec, 0x18, + 0xb7, 0xfe, 0x9b, 0x93, 0x82, 0xf9, 0xbe, 0x80, 0xf9, 0x2e, 0xba, 0x5d, 0xc2, 0x29, 0x29, 0x3d, + 0x32, 0x1a, 0xa9, 0xbb, 0x8f, 0x9e, 0x1d, 0x99, 0xe0, 0xf9, 0x91, 0x09, 0xfe, 0x39, 0x32, 0xc1, + 0xd7, 0xc7, 0x66, 0xed, 0xf9, 0xb1, 0x59, 0xfb, 0xf3, 0xd8, 0xac, 0x7d, 0xbe, 0xe3, 0x07, 0xc9, + 0x28, 0x75, 0xb1, 0xc7, 0x26, 0x44, 0xfd, 0x39, 0x96, 0x3f, 0xdb, 0x7c, 0xf8, 0x98, 0x7c, 0x79, + 0x92, 0xef, 0x46, 0x7f, 0x5b, 0xa5, 0x4c, 0x0e, 0x22, 0xca, 0xdd, 0xf3, 0xe2, 0x6c, 0xdd, 0xfc, + 0x37, 0x00, 0x00, 0xff, 0xff, 0x66, 0x42, 0x78, 0x90, 0x87, 0x0b, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -678,6 +789,8 @@ type QueryClient interface { ConsensusStates(ctx context.Context, in *QueryConsensusStatesRequest, opts ...grpc.CallOption) (*QueryConsensusStatesResponse, error) // ClientParams queries all parameters of the ibc client. ClientParams(ctx context.Context, in *QueryClientParamsRequest, opts ...grpc.CallOption) (*QueryClientParamsResponse, error) + // UpgradedClientState queries an Upgraded IBC light client. + UpgradedClientState(ctx context.Context, in *QueryUpgradedClientStateRequest, opts ...grpc.CallOption) (*QueryUpgradedClientStateResponse, error) } type queryClient struct { @@ -733,6 +846,15 @@ func (c *queryClient) ClientParams(ctx context.Context, in *QueryClientParamsReq return out, nil } +func (c *queryClient) UpgradedClientState(ctx context.Context, in *QueryUpgradedClientStateRequest, opts ...grpc.CallOption) (*QueryUpgradedClientStateResponse, error) { + out := new(QueryUpgradedClientStateResponse) + err := c.cc.Invoke(ctx, "/ibc.core.client.v1.Query/UpgradedClientState", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // QueryServer is the server API for Query service. type QueryServer interface { // ClientState queries an IBC light client. @@ -747,6 +869,8 @@ type QueryServer interface { ConsensusStates(context.Context, *QueryConsensusStatesRequest) (*QueryConsensusStatesResponse, error) // ClientParams queries all parameters of the ibc client. ClientParams(context.Context, *QueryClientParamsRequest) (*QueryClientParamsResponse, error) + // UpgradedClientState queries an Upgraded IBC light client. + UpgradedClientState(context.Context, *QueryUpgradedClientStateRequest) (*QueryUpgradedClientStateResponse, error) } // UnimplementedQueryServer can be embedded to have forward compatible implementations. @@ -768,6 +892,9 @@ func (*UnimplementedQueryServer) ConsensusStates(ctx context.Context, req *Query func (*UnimplementedQueryServer) ClientParams(ctx context.Context, req *QueryClientParamsRequest) (*QueryClientParamsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ClientParams not implemented") } +func (*UnimplementedQueryServer) UpgradedClientState(ctx context.Context, req *QueryUpgradedClientStateRequest) (*QueryUpgradedClientStateResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpgradedClientState not implemented") +} func RegisterQueryServer(s grpc1.Server, srv QueryServer) { s.RegisterService(&_Query_serviceDesc, srv) @@ -863,6 +990,24 @@ func _Query_ClientParams_Handler(srv interface{}, ctx context.Context, dec func( return interceptor(ctx, in, info, handler) } +func _Query_UpgradedClientState_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryUpgradedClientStateRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).UpgradedClientState(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/ibc.core.client.v1.Query/UpgradedClientState", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).UpgradedClientState(ctx, req.(*QueryUpgradedClientStateRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _Query_serviceDesc = grpc.ServiceDesc{ ServiceName: "ibc.core.client.v1.Query", HandlerType: (*QueryServer)(nil), @@ -887,6 +1032,10 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "ClientParams", Handler: _Query_ClientParams_Handler, }, + { + MethodName: "UpgradedClientState", + Handler: _Query_UpgradedClientState_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "ibc/core/client/v1/query.proto", @@ -1309,6 +1458,76 @@ func (m *QueryClientParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, erro return len(dAtA) - i, nil } +func (m *QueryUpgradedClientStateRequest) 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 *QueryUpgradedClientStateRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryUpgradedClientStateRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.PlanHeight != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.PlanHeight)) + i-- + dAtA[i] = 0x10 + } + if len(m.ClientId) > 0 { + i -= len(m.ClientId) + copy(dAtA[i:], m.ClientId) + i = encodeVarintQuery(dAtA, i, uint64(len(m.ClientId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryUpgradedClientStateResponse) 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 *QueryUpgradedClientStateResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryUpgradedClientStateResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.UpgradedClientState != nil { + { + size, err := m.UpgradedClientState.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 @@ -1483,6 +1702,35 @@ func (m *QueryClientParamsResponse) Size() (n int) { return n } +func (m *QueryUpgradedClientStateRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ClientId) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + if m.PlanHeight != 0 { + n += 1 + sovQuery(uint64(m.PlanHeight)) + } + return n +} + +func (m *QueryUpgradedClientStateResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.UpgradedClientState != nil { + l = m.UpgradedClientState.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + func sovQuery(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -2597,6 +2845,193 @@ func (m *QueryClientParamsResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *QueryUpgradedClientStateRequest) 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: QueryUpgradedClientStateRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryUpgradedClientStateRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ClientId", 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.ClientId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PlanHeight", wireType) + } + m.PlanHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PlanHeight |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryUpgradedClientStateResponse) 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: QueryUpgradedClientStateResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryUpgradedClientStateResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UpgradedClientState", 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.UpgradedClientState == nil { + m.UpgradedClientState = &types.Any{} + } + if err := m.UpgradedClientState.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 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 40bc6a85fdd0..9e36ecc18fde 100644 --- a/x/ibc/core/02-client/types/query.pb.gw.go +++ b/x/ibc/core/02-client/types/query.pb.gw.go @@ -327,6 +327,78 @@ func local_request_Query_ClientParams_0(ctx context.Context, marshaler runtime.M } +var ( + filter_Query_UpgradedClientState_0 = &utilities.DoubleArray{Encoding: map[string]int{"client_id": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} +) + +func request_Query_UpgradedClientState_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryUpgradedClientStateRequest + 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_UpgradedClientState_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.UpgradedClientState(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_UpgradedClientState_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryUpgradedClientStateRequest + 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_UpgradedClientState_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.UpgradedClientState(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. @@ -433,6 +505,26 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + mux.Handle("GET", pattern_Query_UpgradedClientState_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_UpgradedClientState_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_UpgradedClientState_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -574,6 +666,26 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("GET", pattern_Query_UpgradedClientState_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_UpgradedClientState_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_UpgradedClientState_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -587,6 +699,8 @@ var ( pattern_Query_ConsensusStates_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"ibc", "core", "client", "v1beta1", "consensus_states", "client_id"}, "", runtime.AssumeColonVerbOpt(false))) pattern_Query_ClientParams_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"ibc", "client", "v1beta1", "params"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_UpgradedClientState_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"ibc", "core", "client", "v1", "upgraded_client_states", "client_id"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( @@ -599,4 +713,6 @@ var ( forward_Query_ConsensusStates_0 = runtime.ForwardResponseMessage forward_Query_ClientParams_0 = runtime.ForwardResponseMessage + + forward_Query_UpgradedClientState_0 = runtime.ForwardResponseMessage ) diff --git a/x/ibc/core/keeper/grpc_query.go b/x/ibc/core/keeper/grpc_query.go index f406d2e86f00..3db15d3c0bc7 100644 --- a/x/ibc/core/keeper/grpc_query.go +++ b/x/ibc/core/keeper/grpc_query.go @@ -33,6 +33,11 @@ func (q Keeper) ClientParams(c context.Context, req *clienttypes.QueryClientPara return q.ClientKeeper.ClientParams(c, req) } +// UpgradedClientState implements the IBC QueryServer interface +func (q Keeper) UpgradedClientState(c context.Context, req *clienttypes.QueryUpgradedClientStateRequest) (*clienttypes.QueryUpgradedClientStateResponse, error) { + return q.ClientKeeper.UpgradedClientState(c, req) +} + // Connection implements the IBC QueryServer interface func (q Keeper) Connection(c context.Context, req *connectiontypes.QueryConnectionRequest) (*connectiontypes.QueryConnectionResponse, error) { return q.ConnectionKeeper.Connection(c, req) diff --git a/x/ibc/core/keeper/keeper.go b/x/ibc/core/keeper/keeper.go index 5f9abc382ecb..dab06caec27d 100644 --- a/x/ibc/core/keeper/keeper.go +++ b/x/ibc/core/keeper/keeper.go @@ -33,9 +33,10 @@ type Keeper struct { // NewKeeper creates a new ibc Keeper func NewKeeper( cdc codec.BinaryMarshaler, key sdk.StoreKey, paramSpace paramtypes.Subspace, - stakingKeeper clienttypes.StakingKeeper, scopedKeeper capabilitykeeper.ScopedKeeper, + stakingKeeper clienttypes.StakingKeeper, upgradeKeeper clienttypes.UpgradeKeeper, + scopedKeeper capabilitykeeper.ScopedKeeper, ) *Keeper { - clientKeeper := clientkeeper.NewKeeper(cdc, key, paramSpace, stakingKeeper) + clientKeeper := clientkeeper.NewKeeper(cdc, key, paramSpace, stakingKeeper, upgradeKeeper) connectionKeeper := connectionkeeper.NewKeeper(cdc, key, clientKeeper) portKeeper := portkeeper.NewKeeper(scopedKeeper) channelKeeper := channelkeeper.NewKeeper(cdc, key, clientKeeper, connectionKeeper, portKeeper, scopedKeeper) diff --git a/x/ibc/core/keeper/msg_server_test.go b/x/ibc/core/keeper/msg_server_test.go index 1af4cdc18eb0..1c4b60010f7a 100644 --- a/x/ibc/core/keeper/msg_server_test.go +++ b/x/ibc/core/keeper/msg_server_test.go @@ -639,14 +639,18 @@ func (suite *KeeperTestSuite) TestUpgradeClient() { // last Height is at next block lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) + upgradedClientBz, err := clienttypes.MarshalClientState(suite.chainA.App.AppCodec(), upgradedClient) + suite.Require().NoError(err) + upgradedConsStateBz, err := clienttypes.MarshalConsensusState(suite.chainA.App.AppCodec(), upgradedConsState) + suite.Require().NoError(err) + // zero custom fields and store in upgrade store - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClient) - suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsState) + suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) + suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) // commit upgrade store changes and update clients - suite.coordinator.CommitBlock(suite.chainB) - err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) + err = suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) suite.Require().NoError(err) cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA) @@ -676,14 +680,18 @@ func (suite *KeeperTestSuite) TestUpgradeClient() { // last Height is at next block lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) + upgradedClientBz, err := clienttypes.MarshalClientState(suite.chainA.App.AppCodec(), upgradedClient) + suite.Require().NoError(err) + upgradedConsStateBz, err := clienttypes.MarshalConsensusState(suite.chainA.App.AppCodec(), upgradedConsState) + suite.Require().NoError(err) + // zero custom fields and store in upgrade store - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClient) - suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsState) + suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) + suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) // commit upgrade store changes and update clients - suite.coordinator.CommitBlock(suite.chainB) - err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) + err = suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) suite.Require().NoError(err) msg, err = clienttypes.NewMsgUpgradeClient(clientA, upgradedClient, upgradedConsState, nil, nil, suite.chainA.SenderAccount.GetAddress()) diff --git a/x/ibc/light-clients/07-tendermint/types/upgrade.go b/x/ibc/light-clients/07-tendermint/types/upgrade.go index 397e9cfd8374..161b725da16e 100644 --- a/x/ibc/light-clients/07-tendermint/types/upgrade.go +++ b/x/ibc/light-clients/07-tendermint/types/upgrade.go @@ -40,8 +40,8 @@ func (cs ClientState) VerifyUpgradeAndUpdateState( upgradedClient.GetLatestHeight(), lastHeight) } - // counterparty chain must commit the upgraded client with all client-customizable fields zeroed out - // at the upgrade path specified by current client + // upgraded client state and consensus state must be IBC tendermint client state and consensus state + // this may be modified in the future to upgrade to a new IBC tendermint type // counterparty must also commit to the upgraded consensus state at a sub-path under the upgrade path specified tmUpgradeClient, ok := upgradedClient.(*ClientState) if !ok { diff --git a/x/ibc/light-clients/07-tendermint/types/upgrade_test.go b/x/ibc/light-clients/07-tendermint/types/upgrade_test.go index 7be3a4943f33..8a7623f94301 100644 --- a/x/ibc/light-clients/07-tendermint/types/upgrade_test.go +++ b/x/ibc/light-clients/07-tendermint/types/upgrade_test.go @@ -15,6 +15,8 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { lastHeight clienttypes.Height clientA string proofUpgradedClient, proofUpgradedConsState []byte + upgradedClientBz, upgradedConsStateBz []byte + err error ) testCases := []struct { @@ -25,18 +27,12 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { { name: "successful upgrade", setup: func() { - - upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - upgradedConsState = &types.ConsensusState{ - NextValidatorsHash: []byte("nextValsHash"), - } - // upgrade Height is at next block lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) // zero custom fields and store in upgrade store - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClient) - suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsState) + suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) + suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) // commit upgrade store changes and update clients @@ -57,16 +53,16 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { setup: func() { upgradedHeight := clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+2)) upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, upgradedHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - upgradedConsState = &types.ConsensusState{ - NextValidatorsHash: []byte("nextValsHash"), - } + upgradedClient = upgradedClient.ZeroCustomFields() + upgradedClientBz, err = clienttypes.MarshalClientState(suite.chainA.App.AppCodec(), upgradedClient) + suite.Require().NoError(err) // upgrade Height is at next block lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) // zero custom fields and store in upgrade store - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClient) - suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsState) + suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) + suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) // commit upgrade store changes and update clients @@ -86,18 +82,12 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { { name: "unsuccessful upgrade: upgrade height revision height is more than the current client revision height", setup: func() { - - upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - upgradedConsState = &types.ConsensusState{ - NextValidatorsHash: []byte("nextValsHash"), - } - // upgrade Height is 10 blocks from now lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+10)) // zero custom fields and store in upgrade store - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClient) - suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsState) + suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) + suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) // commit upgrade store changes and update clients @@ -114,20 +104,43 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { expPass: false, }, { - name: "unsuccessful upgrade: chain-specified parameters do not match committed client", + name: "unsuccessful upgrade: committed client does not have zeroed custom fields", setup: func() { - + // non-zeroed upgrade client upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - upgradedConsState = &types.ConsensusState{ - NextValidatorsHash: []byte("nextValsHash"), - } + upgradedClientBz, err = clienttypes.MarshalClientState(suite.chainA.App.AppCodec(), upgradedClient) + suite.Require().NoError(err) + + // upgrade Height is at next block + lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) + + // zero custom fields and store in upgrade store + suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) + suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) + // commit upgrade store changes and update clients + + suite.coordinator.CommitBlock(suite.chainB) + err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) + suite.Require().NoError(err) + + cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA) + suite.Require().True(found) + + proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) + proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) + }, + expPass: false, + }, + { + name: "unsuccessful upgrade: chain-specified parameters do not match committed client", + setup: func() { // upgrade Height is at next block lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) // zero custom fields and store in upgrade store - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClient) - suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsState) + suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) + suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) // change upgradedClient client-specified parameters upgradedClient = types.NewClientState("wrongchainID", types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, true, true) @@ -147,15 +160,9 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { { name: "unsuccessful upgrade: client-specified parameters do not match previous client", setup: func() { - - upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, lastHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - upgradedConsState = &types.ConsensusState{ - NextValidatorsHash: []byte("nextValsHash"), - } - // zero custom fields and store in upgrade store - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClient) - suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsState) + suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) + suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) // change upgradedClient client-specified parameters upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, ubdPeriod, ubdPeriod+trustingPeriod, maxClockDrift+5, lastHeight, commitmenttypes.GetSDKSpecs(), upgradePath, true, false) @@ -175,18 +182,12 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { { name: "unsuccessful upgrade: relayer-submitted consensus state does not match counterparty-committed consensus state", setup: func() { - - upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - upgradedConsState = &types.ConsensusState{ - NextValidatorsHash: []byte("nextValsHash"), - } - // upgrade Height is at next block lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) // zero custom fields and store in upgrade store - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClient) - suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsState) + suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) + suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) // change submitted upgradedConsensusState upgradedConsState = &types.ConsensusState{ @@ -210,11 +211,7 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { { name: "unsuccessful upgrade: client proof unmarshal failed", setup: func() { - upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - upgradedConsState = &types.ConsensusState{ - NextValidatorsHash: []byte("nextValsHash"), - } - suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsState) + suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA) suite.Require().True(found) @@ -228,12 +225,7 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { { name: "unsuccessful upgrade: consensus state proof unmarshal failed", setup: func() { - upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - upgradedConsState = &types.ConsensusState{ - NextValidatorsHash: []byte("nextValsHash"), - } - - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClient) + suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA) suite.Require().True(found) @@ -247,16 +239,12 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { { name: "unsuccessful upgrade: client proof verification failed", setup: func() { - // create but do not store upgraded client - upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - upgradedConsState = &types.ConsensusState{ - NextValidatorsHash: []byte("nextValsHash"), - } + // do not store upgraded client // upgrade Height is at next block lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) - suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsState) + suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA) suite.Require().True(found) @@ -269,16 +257,12 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { { name: "unsuccessful upgrade: consensus state proof verification failed", setup: func() { - // create but do not store upgraded client - upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - upgradedConsState = &types.ConsensusState{ - NextValidatorsHash: []byte("nextValsHash"), - } + // do not store upgraded client // upgrade Height is at next block lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClient) + suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA) suite.Require().True(found) @@ -291,17 +275,11 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { { name: "unsuccessful upgrade: upgrade path is empty", setup: func() { - - upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - upgradedConsState = &types.ConsensusState{ - NextValidatorsHash: []byte("nextValsHash"), - } - // upgrade Height is at next block lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) // zero custom fields and store in upgrade store - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClient) + suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) // commit upgrade store changes and update clients @@ -325,17 +303,11 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { { name: "unsuccessful upgrade: upgraded height is not greater than current height", setup: func() { - - upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - upgradedConsState = &types.ConsensusState{ - NextValidatorsHash: []byte("nextValsHash"), - } - // upgrade Height is at next block lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) // zero custom fields and store in upgrade store - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClient) + suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) // commit upgrade store changes and update clients @@ -354,17 +326,11 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { { name: "unsuccessful upgrade: consensus state for upgrade height cannot be found", setup: func() { - - upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - upgradedConsState = &types.ConsensusState{ - NextValidatorsHash: []byte("nextValsHash"), - } - // upgrade Height is at next block lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+100)) // zero custom fields and store in upgrade store - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClient) + suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) // commit upgrade store changes and update clients @@ -383,14 +349,8 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { { name: "unsuccessful upgrade: client is expired", setup: func() { - - upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, lastHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - upgradedConsState = &types.ConsensusState{ - NextValidatorsHash: []byte("nextValsHash"), - } - // zero custom fields and store in upgrade store - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClient) + suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) // commit upgrade store changes and update clients @@ -412,17 +372,11 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { { name: "unsuccessful upgrade: updated unbonding period is equal to trusting period", setup: func() { - - upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - upgradedConsState = &types.ConsensusState{ - NextValidatorsHash: []byte("nextValsHash"), - } - // upgrade Height is at next block lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) // zero custom fields and store in upgrade store - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClient) + suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) // commit upgrade store changes and update clients @@ -441,19 +395,17 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { { name: "unsuccessful upgrade: final client is not valid", setup: func() { - // new client has smaller unbonding period such that old trusting period is no longer valid upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - upgradedConsState = &types.ConsensusState{ - NextValidatorsHash: []byte("nextValsHash"), - } + upgradedClientBz, err = clienttypes.MarshalClientState(suite.chainA.App.AppCodec(), upgradedClient) + suite.Require().NoError(err) // upgrade Height is at next block lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) // zero custom fields and store in upgrade store - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClient) - suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsState) + suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) + suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) // commit upgrade store changes and update clients @@ -478,6 +430,16 @@ func (suite *TendermintTestSuite) TestVerifyUpgrade() { suite.SetupTest() clientA, _ = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) + upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false) + upgradedClient = upgradedClient.ZeroCustomFields() + upgradedClientBz, err = clienttypes.MarshalClientState(suite.chainA.App.AppCodec(), upgradedClient) + suite.Require().NoError(err) + + upgradedConsState = &types.ConsensusState{ + NextValidatorsHash: []byte("nextValsHash"), + } + upgradedConsStateBz, err = clienttypes.MarshalConsensusState(suite.chainA.App.AppCodec(), upgradedConsState) + suite.Require().NoError(err) tc.setup() diff --git a/x/upgrade/abci.go b/x/upgrade/abci.go index fa95c4c4aa63..d346decb023c 100644 --- a/x/upgrade/abci.go +++ b/x/upgrade/abci.go @@ -10,8 +10,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/upgrade/keeper" "github.com/cosmos/cosmos-sdk/x/upgrade/types" - - ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" ) // BeginBlock will check if there is a scheduled plan and if it is ready to be executed. @@ -24,25 +22,11 @@ import ( // skipUpgradeHeightArray is a set of block heights for which the upgrade must be skipped func BeginBlocker(k keeper.Keeper, ctx sdk.Context, _ abci.RequestBeginBlock) { defer telemetry.ModuleMeasureSince(types.ModuleName, time.Now(), telemetry.MetricKeyBeginBlocker) - plan, found := k.GetUpgradePlan(ctx) if !found { return } - // Once we are at the last block this chain will commit, set the upgraded consensus state - // so that IBC clients can use the last NextValidatorsHash as a trusted kernel for verifying - // headers on the next version of the chain. - // Set the time to the last block time of the current chain. - // In order for a client to upgrade successfully, the first block of the new chain must be committed - // within the trusting period of the last block time on this chain. - if plan.IsIBCPlan() && ctx.BlockHeight() == plan.Height-1 { - upgradedConsState := &ibctmtypes.ConsensusState{ - Timestamp: ctx.BlockTime(), - NextValidatorsHash: ctx.BlockHeader().NextValidatorsHash, - } - k.SetUpgradedConsensusState(ctx, plan.Height, upgradedConsState) - } // To make sure clear upgrade is executed at the same block if plan.ShouldExecute(ctx) { // If skip upgrade has been set for current height, we clear the upgrade plan diff --git a/x/upgrade/abci_test.go b/x/upgrade/abci_test.go index eb31857961bc..9eb0fc1a7ab9 100644 --- a/x/upgrade/abci_test.go +++ b/x/upgrade/abci_test.go @@ -21,8 +21,6 @@ import ( sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/types/module" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" - clienttypes "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/upgrade" "github.com/cosmos/cosmos-sdk/x/upgrade/keeper" "github.com/cosmos/cosmos-sdk/x/upgrade/types" @@ -120,59 +118,6 @@ func TestCanOverwriteScheduleUpgrade(t *testing.T) { VerifyDoUpgrade(t) } -func VerifyDoIBCLastBlock(t *testing.T) { - t.Log("Verify that chain committed to consensus state on the last height it will commit") - nextValsHash := []byte("nextValsHash") - newCtx := s.ctx.WithBlockHeader(tmproto.Header{ - Height: s.ctx.BlockHeight(), - NextValidatorsHash: nextValsHash, - }) - - req := abci.RequestBeginBlock{Header: newCtx.BlockHeader()} - s.module.BeginBlock(newCtx, req) - - // plan Height is at ctx.BlockHeight+1 - consState, err := s.keeper.GetUpgradedConsensusState(newCtx, s.ctx.BlockHeight()+1) - require.NoError(t, err) - require.Equal(t, &ibctmtypes.ConsensusState{Timestamp: newCtx.BlockTime(), NextValidatorsHash: nextValsHash}, consState) -} - -func VerifyDoIBCUpgrade(t *testing.T) { - t.Log("Verify that a panic happens at the upgrade time/height") - newCtx := s.ctx.WithBlockHeight(s.ctx.BlockHeight() + 1).WithBlockTime(time.Now()) - - // Check IBC state is set before upgrade using last height: s.ctx.BlockHeight() - cs, err := s.keeper.GetUpgradedClient(newCtx, s.ctx.BlockHeight()) - require.NoError(t, err, "could not retrieve upgraded client before upgrade plan is applied") - require.NotNil(t, cs, "IBC client is nil before upgrade") - - consState, err := s.keeper.GetUpgradedConsensusState(newCtx, s.ctx.BlockHeight()) - require.NoError(t, err, "could not retrieve upgraded consensus state before upgrade plan is applied") - require.NotNil(t, consState, "IBC consensus state is nil before upgrade") - - req := abci.RequestBeginBlock{Header: newCtx.BlockHeader()} - require.Panics(t, func() { - s.module.BeginBlock(newCtx, req) - }) - - t.Log("Verify that the upgrade can be successfully applied with a handler") - s.keeper.SetUpgradeHandler("test", func(ctx sdk.Context, plan types.Plan) {}) - require.NotPanics(t, func() { - s.module.BeginBlock(newCtx, req) - }) - - VerifyCleared(t, newCtx) - - // Check IBC state is cleared after upgrade using last height: s.ctx.BlockHeight() - cs, err = s.keeper.GetUpgradedClient(newCtx, s.ctx.BlockHeight()) - require.Error(t, err, "retrieved upgraded client after upgrade plan is applied") - require.Nil(t, cs, "IBC client is not-nil after upgrade") - - consState, err = s.keeper.GetUpgradedConsensusState(newCtx, s.ctx.BlockHeight()) - require.Error(t, err, "retrieved upgraded consensus state after upgrade plan is applied") - require.Nil(t, consState, "IBC consensus state is not-nil after upgrade") -} - func VerifyDoUpgrade(t *testing.T) { t.Log("Verify that a panic happens at the upgrade time/height") newCtx := s.ctx.WithBlockHeight(s.ctx.BlockHeight() + 1).WithBlockTime(time.Now()) @@ -280,27 +225,20 @@ func TestNoSpuriousUpgrades(t *testing.T) { } func TestPlanStringer(t *testing.T) { - clientState := &ibctmtypes.ClientState{ChainId: "gaiachain"} - cs, err := clienttypes.PackClientState(clientState) - require.NoError(t, err) - ti, err := time.Parse(time.RFC3339, "2020-01-01T00:00:00Z") require.Nil(t, err) require.Equal(t, `Upgrade Plan Name: test Time: 2020-01-01T00:00:00Z - Info: . - Upgraded IBC Client: no upgraded client provided`, types.Plan{Name: "test", Time: ti}.String()) + Info: .`, types.Plan{Name: "test", Time: ti}.String()) require.Equal(t, `Upgrade Plan Name: test Height: 100 - Info: . - Upgraded IBC Client: no upgraded client provided`, types.Plan{Name: "test", Height: 100}.String()) + Info: .`, types.Plan{Name: "test", Height: 100}.String()) require.Equal(t, fmt.Sprintf(`Upgrade Plan Name: test Height: 100 - Info: . - Upgraded IBC Client: %s`, clientState), types.Plan{Name: "test", Height: 100, UpgradedClientState: cs}.String()) + Info: .`), types.Plan{Name: "test", Height: 100}.String()) } func VerifyNotDone(t *testing.T, newCtx sdk.Context, name string) { @@ -467,27 +405,6 @@ func TestUpgradeWithoutSkip(t *testing.T) { VerifyDone(t, s.ctx, "test") } -func TestIBCUpgradeWithoutSkip(t *testing.T) { - s := setupTest(10, map[int64]bool{}) - cs, err := clienttypes.PackClientState(&ibctmtypes.ClientState{}) - require.NoError(t, err) - err = s.handler(s.ctx, &types.SoftwareUpgradeProposal{ - Title: "prop", - Plan: types.Plan{ - Name: "test", - Height: s.ctx.BlockHeight() + 1, - UpgradedClientState: cs, - }, - }) - require.Nil(t, err) - - t.Log("Verify if last height stores consensus state") - VerifyDoIBCLastBlock(t) - - VerifyDoUpgrade(t) - VerifyDone(t, s.ctx, "test") -} - func TestDumpUpgradeInfoToFile(t *testing.T) { s := setupTest(10, map[int64]bool{}) diff --git a/x/upgrade/keeper/grpc_query.go b/x/upgrade/keeper/grpc_query.go index 26e7860c8627..3806fcbb0480 100644 --- a/x/upgrade/keeper/grpc_query.go +++ b/x/upgrade/keeper/grpc_query.go @@ -4,7 +4,6 @@ import ( "context" sdk "github.com/cosmos/cosmos-sdk/types" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" "github.com/cosmos/cosmos-sdk/x/upgrade/types" ) @@ -38,17 +37,12 @@ func (k Keeper) AppliedPlan(c context.Context, req *types.QueryAppliedPlanReques func (k Keeper) UpgradedConsensusState(c context.Context, req *types.QueryUpgradedConsensusStateRequest) (*types.QueryUpgradedConsensusStateResponse, error) { ctx := sdk.UnwrapSDKContext(c) - consState, err := k.GetUpgradedConsensusState(ctx, req.LastHeight) - if err != nil { - return nil, err - } - - cs, err := clienttypes.PackConsensusState(consState) - if err != nil { - return nil, err + consState, found := k.GetUpgradedConsensusState(ctx, req.LastHeight) + if !found { + return &types.QueryUpgradedConsensusStateResponse{}, nil } return &types.QueryUpgradedConsensusStateResponse{ - UpgradedConsensusState: cs, + UpgradedConsensusState: consState, }, nil } diff --git a/x/upgrade/keeper/keeper.go b/x/upgrade/keeper/keeper.go index 1092885bcb3f..e366ae09198e 100644 --- a/x/upgrade/keeper/keeper.go +++ b/x/upgrade/keeper/keeper.go @@ -16,8 +16,6 @@ import ( store "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - ibcexported "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" "github.com/cosmos/cosmos-sdk/x/upgrade/types" ) @@ -75,84 +73,52 @@ func (k Keeper) ScheduleUpgrade(ctx sdk.Context, plan types.Plan) error { store := ctx.KVStore(k.storeKey) // clear any old IBC state stored by previous plan - oldPlan, exists := k.GetUpgradePlan(ctx) - if exists && oldPlan.IsIBCPlan() { - k.ClearIBCState(ctx, oldPlan.Height-1) + oldPlan, found := k.GetUpgradePlan(ctx) + if found { + k.ClearIBCState(ctx, oldPlan.Height) } bz := k.cdc.MustMarshalBinaryBare(&plan) store.Set(types.PlanKey(), bz) - if plan.IsIBCPlan() { - // Set UpgradedClientState in store - clientState, err := clienttypes.UnpackClientState(plan.UpgradedClientState) - if err != nil { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "could not unpack clientstate: %v", err) - } - // sets the new upgraded client in last height committed on this chain is at plan.Height, - // since the chain will panic at plan.Height and new chain will resume at plan.Height - return k.SetUpgradedClient(ctx, plan.Height, clientState) - } return nil } // SetUpgradedClient sets the expected upgraded client for the next version of this chain at the last height the current chain will commit. -func (k Keeper) SetUpgradedClient(ctx sdk.Context, planHeight int64, cs ibcexported.ClientState) error { +func (k Keeper) SetUpgradedClient(ctx sdk.Context, planHeight int64, bz []byte) error { store := ctx.KVStore(k.storeKey) - - // zero out any custom fields before setting - cs = cs.ZeroCustomFields() - bz, err := clienttypes.MarshalClientState(k.cdc, cs) - if err != nil { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "could not marshal clientstate: %v", err) - } - store.Set(types.UpgradedClientKey(planHeight), bz) return nil } // GetUpgradedClient gets the expected upgraded client for the next version of this chain -func (k Keeper) GetUpgradedClient(ctx sdk.Context, height int64) (ibcexported.ClientState, error) { +func (k Keeper) GetUpgradedClient(ctx sdk.Context, height int64) ([]byte, bool) { store := ctx.KVStore(k.storeKey) - bz := store.Get(types.UpgradedClientKey(height)) if len(bz) == 0 { - return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "upgraded client not found in store for height %d", height) + return nil, false } - clientState, err := clienttypes.UnmarshalClientState(k.cdc, bz) - if err != nil { - return nil, err - } - return clientState, nil + return bz, true } // SetUpgradedConsensusState set the expected upgraded consensus state for the next version of this chain // using the last height committed on this chain. -func (k Keeper) SetUpgradedConsensusState(ctx sdk.Context, planHeight int64, cs ibcexported.ConsensusState) error { +func (k Keeper) SetUpgradedConsensusState(ctx sdk.Context, planHeight int64, bz []byte) error { store := ctx.KVStore(k.storeKey) - bz, err := clienttypes.MarshalConsensusState(k.cdc, cs) - if err != nil { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "could not marshal consensus state: %v", err) - } - store.Set(types.UpgradedConsStateKey(planHeight), bz) return nil } // GetUpgradedConsensusState set the expected upgraded consensus state for the next version of this chain -func (k Keeper) GetUpgradedConsensusState(ctx sdk.Context, lastHeight int64) (ibcexported.ConsensusState, error) { +func (k Keeper) GetUpgradedConsensusState(ctx sdk.Context, lastHeight int64) ([]byte, bool) { store := ctx.KVStore(k.storeKey) - bz := store.Get(types.UpgradedConsStateKey(lastHeight)) if len(bz) == 0 { - return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "upgraded consensus state not found in store for height: %d", lastHeight) - } - consState, err := clienttypes.UnmarshalConsensusState(k.cdc, bz) - if err != nil { - return nil, err + return nil, false } - return consState, nil + + return bz, true } // GetDoneHeight returns the height at which the given upgrade was executed @@ -174,8 +140,14 @@ func (k Keeper) ClearIBCState(ctx sdk.Context, lastHeight int64) { store.Delete(types.UpgradedConsStateKey(lastHeight)) } -// ClearUpgradePlan clears any schedule upgrade +// ClearUpgradePlan clears any schedule upgrade and associated IBC states. func (k Keeper) ClearUpgradePlan(ctx sdk.Context) { + // clear IBC states everytime upgrade plan is removed + oldPlan, found := k.GetUpgradePlan(ctx) + if found { + k.ClearIBCState(ctx, oldPlan.Height) + } + store := ctx.KVStore(k.storeKey) store.Delete(types.PlanKey()) } @@ -223,9 +195,7 @@ func (k Keeper) ApplyUpgrade(ctx sdk.Context, plan types.Plan) { // Must clear IBC state after upgrade is applied as it is stored separately from the upgrade plan. // This will prevent resubmission of upgrade msg after upgrade is already completed. - if plan.IsIBCPlan() { - k.ClearIBCState(ctx, plan.Height-1) - } + k.ClearIBCState(ctx, plan.Height) k.ClearUpgradePlan(ctx) k.setDone(ctx, plan.Name) } diff --git a/x/upgrade/keeper/keeper_test.go b/x/upgrade/keeper/keeper_test.go index 6e91ef3c2372..48f0301d3ff1 100644 --- a/x/upgrade/keeper/keeper_test.go +++ b/x/upgrade/keeper/keeper_test.go @@ -11,10 +11,6 @@ import ( "github.com/cosmos/cosmos-sdk/simapp" store "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types" - ibcexported "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" "github.com/cosmos/cosmos-sdk/x/upgrade/keeper" "github.com/cosmos/cosmos-sdk/x/upgrade/types" ) @@ -61,18 +57,6 @@ func (s *KeeperTestSuite) TestReadUpgradeInfoFromDisk() { } func (s *KeeperTestSuite) TestScheduleUpgrade() { - clientState := &ibctmtypes.ClientState{ChainId: "gaiachain"} - cs, err := clienttypes.PackClientState(clientState) - s.Require().NoError(err) - - altClientState := &ibctmtypes.ClientState{ChainId: "ethermint"} - altCs, err := clienttypes.PackClientState(altClientState) - s.Require().NoError(err) - - consState := ibctmtypes.NewConsensusState(time.Now(), commitmenttypes.NewMerkleRoot([]byte("app_hash")), []byte("next_vals_hash")) - consAny, err := clienttypes.PackConsensusState(consState) - s.Require().NoError(err) - cases := []struct { name string plan types.Plan @@ -99,17 +83,6 @@ func (s *KeeperTestSuite) TestScheduleUpgrade() { setup: func() {}, expPass: true, }, - { - name: "successful ibc schedule", - plan: types.Plan{ - Name: "all-good", - Info: "some text here", - Height: 123450000, - UpgradedClientState: cs, - }, - setup: func() {}, - expPass: true, - }, { name: "successful overwrite", plan: types.Plan{ @@ -126,41 +99,6 @@ func (s *KeeperTestSuite) TestScheduleUpgrade() { }, expPass: true, }, - { - name: "successful IBC overwrite", - plan: types.Plan{ - Name: "all-good", - Info: "some text here", - Height: 123450000, - UpgradedClientState: cs, - }, - setup: func() { - s.app.UpgradeKeeper.ScheduleUpgrade(s.ctx, types.Plan{ - Name: "alt-good", - Info: "new text here", - Height: 543210000, - UpgradedClientState: altCs, - }) - }, - expPass: true, - }, - { - name: "successful IBC overwrite with non IBC plan", - plan: types.Plan{ - Name: "all-good", - Info: "some text here", - Height: 123450000, - }, - setup: func() { - s.app.UpgradeKeeper.ScheduleUpgrade(s.ctx, types.Plan{ - Name: "alt-good", - Info: "new text here", - Height: 543210000, - UpgradedClientState: altCs, - }) - }, - expPass: true, - }, { name: "unsuccessful schedule: invalid plan", plan: types.Plan{ @@ -206,17 +144,6 @@ func (s *KeeperTestSuite) TestScheduleUpgrade() { }, expPass: false, }, - { - name: "unsuccessful IBC schedule: UpgradedClientState is not valid client state", - plan: types.Plan{ - Name: "all-good", - Info: "some text here", - Height: 123450000, - UpgradedClientState: consAny, - }, - setup: func() {}, - expPass: false, - }, } for _, tc := range cases { @@ -233,16 +160,6 @@ func (s *KeeperTestSuite) TestScheduleUpgrade() { if tc.expPass { s.Require().NoError(err, "valid test case failed") - if tc.plan.UpgradedClientState != nil { - got, err := s.app.UpgradeKeeper.GetUpgradedClient(s.ctx, tc.plan.Height) - s.Require().NoError(err) - s.Require().Equal(clientState, got, "upgradedClient not equal to expected value") - } else { - // check that upgraded client is empty if latest plan does not specify an upgraded client - got, err := s.app.UpgradeKeeper.GetUpgradedClient(s.ctx, tc.plan.Height) - s.Require().Error(err) - s.Require().Nil(got) - } } else { s.Require().Error(err, "invalid test case passed") } @@ -251,9 +168,8 @@ func (s *KeeperTestSuite) TestScheduleUpgrade() { } func (s *KeeperTestSuite) TestSetUpgradedClient() { - var ( - clientState ibcexported.ClientState - ) + cs := []byte("IBC client state") + cases := []struct { name string height int64 @@ -270,8 +186,7 @@ func (s *KeeperTestSuite) TestSetUpgradedClient() { name: "success", height: 10, setup: func() { - clientState = &ibctmtypes.ClientState{ChainId: "gaiachain"} - s.app.UpgradeKeeper.SetUpgradedClient(s.ctx, 10, clientState) + s.app.UpgradeKeeper.SetUpgradedClient(s.ctx, 10, cs) }, exists: true, }, @@ -284,13 +199,13 @@ func (s *KeeperTestSuite) TestSetUpgradedClient() { // setup test case tc.setup() - gotCs, err := s.app.UpgradeKeeper.GetUpgradedClient(s.ctx, tc.height) + gotCs, exists := s.app.UpgradeKeeper.GetUpgradedClient(s.ctx, tc.height) if tc.exists { - s.Require().Equal(clientState, gotCs, "valid case: %s did not retrieve correct client state", tc.name) - s.Require().NoError(err, "valid case: %s returned error") + s.Require().Equal(cs, gotCs, "valid case: %s did not retrieve correct client state", tc.name) + s.Require().True(exists, "valid case: %s did not retrieve client state", tc.name) } else { s.Require().Nil(gotCs, "invalid case: %s retrieved valid client state", tc.name) - s.Require().Error(err, "invalid case: %s did not return error", tc.name) + s.Require().False(exists, "invalid case: %s retrieved valid client state", tc.name) } } diff --git a/x/upgrade/types/plan.go b/x/upgrade/types/plan.go index aa1a0601ffca..6088ecea15c4 100644 --- a/x/upgrade/types/plan.go +++ b/x/upgrade/types/plan.go @@ -5,30 +5,17 @@ import ( "strings" "time" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - ibcexported "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" ) -var _ codectypes.UnpackInterfacesMessage = Plan{} - func (p Plan) String() string { due := p.DueAt() dueUp := strings.ToUpper(due[0:1]) + due[1:] - var upgradedClientStr string - upgradedClient, err := clienttypes.UnpackClientState(p.UpgradedClientState) - if err != nil { - upgradedClientStr = "no upgraded client provided" - } else { - upgradedClientStr = upgradedClient.String() - } return fmt.Sprintf(`Upgrade Plan Name: %s %s - Info: %s. - Upgraded IBC Client: %s`, p.Name, dueUp, p.Info, upgradedClientStr) + Info: %s.`, p.Name, dueUp, p.Info) } // ValidateBasic does basic validation of a Plan @@ -45,9 +32,6 @@ func (p Plan) ValidateBasic() error { if p.Time.Unix() > 0 && p.Height != 0 { return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "cannot set both time and height") } - if p.Time.Unix() > 0 && p.UpgradedClientState != nil { - return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "IBC chain upgrades must only set height") - } return nil } @@ -70,19 +54,3 @@ func (p Plan) DueAt() string { } return fmt.Sprintf("height: %d", p.Height) } - -// IsIBCPlan will return true if plan includes IBC client information -func (p Plan) IsIBCPlan() bool { - return p.UpgradedClientState != nil -} - -// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces -func (p Plan) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { - // UpgradedClientState may be nil - if p.UpgradedClientState == nil { - return nil - } - - var clientState ibcexported.ClientState - return unpacker.UnpackAny(p.UpgradedClientState, &clientState) -} diff --git a/x/upgrade/types/plan_test.go b/x/upgrade/types/plan_test.go index 436cb83a94e3..37f5f5c9abcb 100644 --- a/x/upgrade/types/plan_test.go +++ b/x/upgrade/types/plan_test.go @@ -1,7 +1,6 @@ package types_test import ( - "fmt" "testing" "time" @@ -10,8 +9,6 @@ import ( "github.com/tendermint/tendermint/libs/log" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" - clienttypes "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/upgrade/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -26,9 +23,6 @@ func mustParseTime(s string) time.Time { } func TestPlanString(t *testing.T) { - cs, err := clienttypes.PackClientState(&ibctmtypes.ClientState{}) - require.NoError(t, err) - cases := map[string]struct { p types.Plan expect string @@ -39,7 +33,7 @@ func TestPlanString(t *testing.T) { Info: "https://foo.bar", Time: mustParseTime("2019-07-08T11:33:55Z"), }, - expect: "Upgrade Plan\n Name: due_time\n Time: 2019-07-08T11:33:55Z\n Info: https://foo.bar.\n Upgraded IBC Client: no upgraded client provided", + expect: "Upgrade Plan\n Name: due_time\n Time: 2019-07-08T11:33:55Z\n Info: https://foo.bar.", }, "with height": { p: types.Plan{ @@ -47,23 +41,13 @@ func TestPlanString(t *testing.T) { Info: "https://foo.bar/baz", Height: 7890, }, - expect: "Upgrade Plan\n Name: by height\n Height: 7890\n Info: https://foo.bar/baz.\n Upgraded IBC Client: no upgraded client provided", - }, - "with IBC client": { - p: types.Plan{ - Name: "by height", - Info: "https://foo.bar/baz", - Height: 7890, - UpgradedClientState: cs, - }, - expect: fmt.Sprintf("Upgrade Plan\n Name: by height\n Height: 7890\n Info: https://foo.bar/baz.\n Upgraded IBC Client: %s", &ibctmtypes.ClientState{}), + expect: "Upgrade Plan\n Name: by height\n Height: 7890\n Info: https://foo.bar/baz.", }, - "neither": { p: types.Plan{ Name: "almost-empty", }, - expect: "Upgrade Plan\n Name: almost-empty\n Height: 0\n Info: .\n Upgraded IBC Client: no upgraded client provided", + expect: "Upgrade Plan\n Name: almost-empty\n Height: 0\n Info: .", }, } @@ -77,9 +61,6 @@ func TestPlanString(t *testing.T) { } func TestPlanValid(t *testing.T) { - cs, err := clienttypes.PackClientState(&ibctmtypes.ClientState{}) - require.NoError(t, err) - cases := map[string]struct { p types.Plan valid bool @@ -92,15 +73,6 @@ func TestPlanValid(t *testing.T) { }, valid: true, }, - "proper ibc upgrade": { - p: types.Plan{ - Name: "ibc-all-good", - Info: "some text here", - Height: 123450000, - UpgradedClientState: cs, - }, - valid: true, - }, "proper by height": { p: types.Plan{ Name: "all-good", @@ -125,15 +97,6 @@ func TestPlanValid(t *testing.T) { Height: -12345, }, }, - "time due date defined for IBC plan": { - p: types.Plan{ - Name: "ibc-all-good", - Info: "some text here", - Time: mustParseTime("2019-07-08T11:33:55Z"), - UpgradedClientState: cs, - }, - valid: false, - }, } for name, tc := range cases { diff --git a/x/upgrade/types/proposal.go b/x/upgrade/types/proposal.go index a8ea9b629062..38b2295556de 100644 --- a/x/upgrade/types/proposal.go +++ b/x/upgrade/types/proposal.go @@ -3,7 +3,6 @@ package types import ( "fmt" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" gov "github.com/cosmos/cosmos-sdk/x/gov/types" ) @@ -18,7 +17,6 @@ func NewSoftwareUpgradeProposal(title, description string, plan Plan) gov.Conten // Implements Proposal Interface var _ gov.Content = &SoftwareUpgradeProposal{} -var _ codectypes.UnpackInterfacesMessage = SoftwareUpgradeProposal{} func init() { gov.RegisterProposalType(ProposalTypeSoftwareUpgrade) @@ -45,11 +43,6 @@ func (sup SoftwareUpgradeProposal) String() string { `, sup.Title, sup.Description) } -// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces -func (sup SoftwareUpgradeProposal) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { - return sup.Plan.UnpackInterfaces(unpacker) -} - func NewCancelSoftwareUpgradeProposal(title, description string) gov.Content { return &CancelSoftwareUpgradeProposal{title, description} } diff --git a/x/upgrade/types/proposal_test.go b/x/upgrade/types/proposal_test.go index d39b89135c3d..4f5ed16a82fa 100644 --- a/x/upgrade/types/proposal_test.go +++ b/x/upgrade/types/proposal_test.go @@ -9,8 +9,6 @@ import ( "github.com/cosmos/cosmos-sdk/codec" codectypes "github.com/cosmos/cosmos-sdk/codec/types" gov "github.com/cosmos/cosmos-sdk/x/gov/types" - clienttypes "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/upgrade/types" ) @@ -79,17 +77,12 @@ func TestContentAccessors(t *testing.T) { } } -// tests a software update proposal can be marshaled and unmarshaled, and the -// client state can be unpacked +// tests a software update proposal can be marshaled and unmarshaled func TestMarshalSoftwareUpdateProposal(t *testing.T) { - cs, err := clienttypes.PackClientState(&ibctmtypes.ClientState{}) - require.NoError(t, err) - // create proposal plan := types.Plan{ - Name: "upgrade ibc", - Height: 1000, - UpgradedClientState: cs, + Name: "upgrade", + Height: 1000, } content := types.NewSoftwareUpgradeProposal("title", "description", plan) sup, ok := content.(*types.SoftwareUpgradeProposal) @@ -98,9 +91,7 @@ func TestMarshalSoftwareUpdateProposal(t *testing.T) { // create codec ir := codectypes.NewInterfaceRegistry() types.RegisterInterfaces(ir) - clienttypes.RegisterInterfaces(ir) gov.RegisterInterfaces(ir) - ibctmtypes.RegisterInterfaces(ir) cdc := codec.NewProtoCodec(ir) // marshal message @@ -111,8 +102,4 @@ func TestMarshalSoftwareUpdateProposal(t *testing.T) { newSup := &types.SoftwareUpgradeProposal{} err = cdc.UnmarshalJSON(bz, newSup) require.NoError(t, err) - - // unpack client state - _, err = clienttypes.UnpackClientState(newSup.Plan.UpgradedClientState) - require.NoError(t, err) } diff --git a/x/upgrade/types/query.pb.go b/x/upgrade/types/query.pb.go index 40caf74e8f6d..936ad03b7055 100644 --- a/x/upgrade/types/query.pb.go +++ b/x/upgrade/types/query.pb.go @@ -6,7 +6,7 @@ package types import ( context "context" fmt "fmt" - types "github.com/cosmos/cosmos-sdk/codec/types" + _ "github.com/cosmos/cosmos-sdk/codec/types" grpc1 "github.com/gogo/protobuf/grpc" proto "github.com/gogo/protobuf/proto" _ "google.golang.org/genproto/googleapis/api/annotations" @@ -259,7 +259,7 @@ func (m *QueryUpgradedConsensusStateRequest) GetLastHeight() int64 { // QueryUpgradedConsensusStateResponse is the response type for the Query/UpgradedConsensusState // RPC method. type QueryUpgradedConsensusStateResponse struct { - UpgradedConsensusState *types.Any `protobuf:"bytes,1,opt,name=upgraded_consensus_state,json=upgradedConsensusState,proto3" json:"upgraded_consensus_state,omitempty"` + UpgradedConsensusState []byte `protobuf:"bytes,2,opt,name=upgraded_consensus_state,json=upgradedConsensusState,proto3" json:"upgraded_consensus_state,omitempty"` } func (m *QueryUpgradedConsensusStateResponse) Reset() { *m = QueryUpgradedConsensusStateResponse{} } @@ -295,7 +295,7 @@ func (m *QueryUpgradedConsensusStateResponse) XXX_DiscardUnknown() { var xxx_messageInfo_QueryUpgradedConsensusStateResponse proto.InternalMessageInfo -func (m *QueryUpgradedConsensusStateResponse) GetUpgradedConsensusState() *types.Any { +func (m *QueryUpgradedConsensusStateResponse) GetUpgradedConsensusState() []byte { if m != nil { return m.UpgradedConsensusState } @@ -316,38 +316,38 @@ func init() { } var fileDescriptor_4a334d07ad8374f0 = []byte{ - // 487 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x53, 0x41, 0x8b, 0x13, 0x31, - 0x18, 0x6d, 0xb4, 0x2e, 0x98, 0xde, 0x82, 0xd4, 0x6e, 0x59, 0x46, 0x89, 0x8b, 0x08, 0x6e, 0x93, - 0xdd, 0xee, 0x4d, 0x41, 0x5c, 0x17, 0x17, 0x0f, 0x22, 0x5a, 0xf1, 0xe2, 0xa5, 0xa4, 0x9d, 0x38, - 0x1d, 0x9c, 0x26, 0xd9, 0x49, 0x22, 0x96, 0x65, 0x2f, 0xfe, 0x02, 0xc1, 0xbb, 0x37, 0x6f, 0xfe, - 0x10, 0x8f, 0x0b, 0x5e, 0xf4, 0x26, 0xad, 0x3f, 0x44, 0x26, 0xc9, 0x48, 0x97, 0x76, 0x66, 0xc5, - 0x53, 0x3b, 0x93, 0xf7, 0xbe, 0xf7, 0xbe, 0xbc, 0x37, 0x10, 0x8f, 0xa5, 0x9e, 0x4a, 0x4d, 0xad, - 0x4a, 0x72, 0x16, 0x73, 0xfa, 0x6e, 0x6f, 0xc4, 0x0d, 0xdb, 0xa3, 0xc7, 0x96, 0xe7, 0x33, 0xa2, - 0x72, 0x69, 0x24, 0x6a, 0x7b, 0x0c, 0x09, 0x18, 0x12, 0x30, 0xdd, 0xcd, 0x44, 0xca, 0x24, 0xe3, - 0xd4, 0xa1, 0x46, 0xf6, 0x0d, 0x65, 0x22, 0x50, 0xba, 0x5b, 0xe1, 0x88, 0xa9, 0x94, 0x32, 0x21, - 0xa4, 0x61, 0x26, 0x95, 0x42, 0x87, 0xd3, 0xed, 0x0a, 0xd1, 0x52, 0xc0, 0xa1, 0xf0, 0x26, 0xbc, - 0xfe, 0xa2, 0x70, 0x71, 0x68, 0xf3, 0x9c, 0x0b, 0xf3, 0x3c, 0x63, 0x62, 0xc0, 0x8f, 0x2d, 0xd7, - 0x06, 0x3f, 0x85, 0x9d, 0xd5, 0x23, 0xad, 0xa4, 0xd0, 0x1c, 0xed, 0xc2, 0xa6, 0xca, 0x98, 0xe8, - 0x80, 0x9b, 0xe0, 0x4e, 0xab, 0xbf, 0x45, 0xd6, 0x9b, 0x27, 0x8e, 0xe3, 0x90, 0xb8, 0x17, 0x84, - 0x0e, 0x94, 0xca, 0x52, 0x1e, 0x2f, 0x09, 0x21, 0x04, 0x9b, 0x82, 0x4d, 0xb9, 0x1b, 0x76, 0x75, - 0xe0, 0xfe, 0xe3, 0x7e, 0x10, 0x3f, 0x07, 0x0f, 0xe2, 0x6d, 0xb8, 0x31, 0xe1, 0x69, 0x32, 0x31, - 0x8e, 0x71, 0x79, 0x10, 0x9e, 0xf0, 0x63, 0x88, 0x1d, 0xe7, 0x95, 0x77, 0x11, 0x1f, 0x16, 0x68, - 0xa1, 0xad, 0x7e, 0x69, 0x98, 0xe1, 0xa5, 0xda, 0x0d, 0xd8, 0xca, 0x98, 0x36, 0xc3, 0x73, 0x23, - 0x60, 0xf1, 0xea, 0x89, 0x1f, 0x63, 0xe1, 0xad, 0xda, 0x31, 0xc1, 0xc5, 0x33, 0xd8, 0x09, 0xeb, - 0xc6, 0xc3, 0x71, 0x09, 0x19, 0xea, 0x02, 0x13, 0xae, 0xe5, 0x1a, 0xf1, 0x01, 0x91, 0x32, 0x3b, - 0x72, 0x20, 0x66, 0x83, 0xb6, 0x5d, 0x3b, 0xb7, 0xff, 0xb5, 0x09, 0xaf, 0x38, 0x5d, 0xf4, 0x19, - 0xc0, 0xd6, 0xd2, 0xa5, 0x23, 0x5a, 0x75, 0xbd, 0x15, 0xc9, 0x75, 0x77, 0xff, 0x9d, 0xe0, 0x97, - 0xc1, 0x3b, 0x1f, 0xbe, 0xff, 0xfe, 0x74, 0xe9, 0x36, 0xda, 0xa6, 0x15, 0xad, 0x19, 0x7b, 0xd2, - 0xb0, 0xc8, 0x12, 0x7d, 0x01, 0xb0, 0xb5, 0x14, 0xcc, 0x05, 0x06, 0x57, 0x13, 0xbf, 0xc0, 0xe0, - 0x9a, 0xcc, 0xf1, 0xbe, 0x33, 0xd8, 0x43, 0x77, 0xab, 0x0c, 0x32, 0x4f, 0x72, 0x06, 0xe9, 0x49, - 0xd1, 0xa1, 0x53, 0xf4, 0x13, 0xc0, 0xf6, 0xfa, 0x14, 0xd1, 0xbd, 0x5a, 0x07, 0xb5, 0x0d, 0xea, - 0xde, 0xff, 0x2f, 0x6e, 0x58, 0xe4, 0xc8, 0x2d, 0xf2, 0x10, 0x3d, 0xa0, 0xf5, 0xdf, 0xe7, 0x4a, - 0xa9, 0xe8, 0xc9, 0x52, 0x6d, 0x4f, 0x1f, 0x1d, 0x7d, 0x9b, 0x47, 0xe0, 0x6c, 0x1e, 0x81, 0x5f, - 0xf3, 0x08, 0x7c, 0x5c, 0x44, 0x8d, 0xb3, 0x45, 0xd4, 0xf8, 0xb1, 0x88, 0x1a, 0xaf, 0x77, 0x92, - 0xd4, 0x4c, 0xec, 0x88, 0x8c, 0xe5, 0xb4, 0xd4, 0xf0, 0x3f, 0x3d, 0x1d, 0xbf, 0xa5, 0xef, 0xff, - 0x0a, 0x9a, 0x99, 0xe2, 0x7a, 0xb4, 0xe1, 0xca, 0xb9, 0xff, 0x27, 0x00, 0x00, 0xff, 0xff, 0xee, - 0x4b, 0xe2, 0xe8, 0xa4, 0x04, 0x00, 0x00, + // 490 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x53, 0xcf, 0x6b, 0x13, 0x41, + 0x18, 0xcd, 0xc4, 0x58, 0x74, 0xe2, 0x41, 0xe6, 0x10, 0xd3, 0x50, 0xd6, 0x32, 0x16, 0x29, 0xd8, + 0xec, 0xb4, 0xe9, 0x45, 0x14, 0x44, 0x2d, 0x16, 0x11, 0x0f, 0x1a, 0xf1, 0xe2, 0x25, 0x4c, 0xb2, + 0xe3, 0x66, 0x71, 0x33, 0x33, 0xdd, 0x99, 0x11, 0x4b, 0xe9, 0xc5, 0xbf, 0x40, 0xf0, 0xee, 0xcd, + 0x9b, 0x7f, 0x88, 0xc7, 0x82, 0x17, 0xbd, 0x49, 0xe2, 0x1f, 0x22, 0x3b, 0x3b, 0x2b, 0x5b, 0xb2, + 0xbb, 0x91, 0x9e, 0xf6, 0xc7, 0xf7, 0xde, 0xf7, 0xde, 0x37, 0xef, 0x1b, 0x88, 0x27, 0x42, 0xcd, + 0x84, 0x22, 0x46, 0x86, 0x09, 0x0d, 0x18, 0x79, 0xbf, 0x37, 0x66, 0x9a, 0xee, 0x91, 0x23, 0xc3, + 0x92, 0x63, 0x5f, 0x26, 0x42, 0x0b, 0xd4, 0xc9, 0x30, 0xbe, 0xc3, 0xf8, 0x0e, 0xd3, 0x5b, 0x0f, + 0x85, 0x08, 0x63, 0x46, 0x2c, 0x6a, 0x6c, 0xde, 0x12, 0xca, 0x1d, 0xa5, 0xb7, 0xe1, 0x4a, 0x54, + 0x46, 0x84, 0x72, 0x2e, 0x34, 0xd5, 0x91, 0xe0, 0xca, 0x55, 0xb7, 0x2a, 0x44, 0x73, 0x01, 0x8b, + 0xc2, 0xeb, 0xf0, 0xc6, 0xcb, 0xd4, 0xc5, 0x81, 0x49, 0x12, 0xc6, 0xf5, 0x8b, 0x98, 0xf2, 0x21, + 0x3b, 0x32, 0x4c, 0x69, 0xfc, 0x1c, 0x76, 0x97, 0x4b, 0x4a, 0x0a, 0xae, 0x18, 0xda, 0x85, 0x2d, + 0x19, 0x53, 0xde, 0x05, 0x9b, 0x60, 0xbb, 0x3d, 0xd8, 0xf0, 0xcb, 0xcd, 0xfb, 0x96, 0x63, 0x91, + 0xb8, 0xef, 0x84, 0x1e, 0x49, 0x19, 0x47, 0x2c, 0x28, 0x08, 0x21, 0x04, 0x5b, 0x9c, 0xce, 0x98, + 0x6d, 0x76, 0x75, 0x68, 0xdf, 0xf1, 0xc0, 0x89, 0x9f, 0x83, 0x3b, 0xf1, 0x0e, 0x5c, 0x9b, 0xb2, + 0x28, 0x9c, 0x6a, 0xcb, 0xb8, 0x34, 0x74, 0x5f, 0xf8, 0x09, 0xc4, 0x96, 0xf3, 0x3a, 0x73, 0x11, + 0x1c, 0xa4, 0x68, 0xae, 0x8c, 0x7a, 0xa5, 0xa9, 0x66, 0xb9, 0xda, 0x4d, 0xd8, 0x8e, 0xa9, 0xd2, + 0xa3, 0x73, 0x2d, 0x60, 0xfa, 0xeb, 0x69, 0xd6, 0x86, 0xc1, 0x5b, 0xb5, 0x6d, 0x9c, 0x8b, 0xbb, + 0xb0, 0xeb, 0xc6, 0x0d, 0x46, 0x93, 0x1c, 0x32, 0x52, 0x29, 0xa6, 0xdb, 0xdc, 0x04, 0xdb, 0xd7, + 0x86, 0x1d, 0x53, 0xda, 0xe1, 0x59, 0xeb, 0x0a, 0xb8, 0xde, 0x1c, 0x7c, 0x6b, 0xc1, 0xcb, 0x56, + 0x07, 0x7d, 0x01, 0xb0, 0x5d, 0x38, 0x64, 0x44, 0xaa, 0x8e, 0xb3, 0x22, 0xa9, 0xde, 0xee, 0xff, + 0x13, 0x32, 0xf3, 0x78, 0xe7, 0xe3, 0x8f, 0x3f, 0x9f, 0x9b, 0xb7, 0xd1, 0x16, 0xa9, 0xd8, 0x92, + 0x49, 0x46, 0x1a, 0xa5, 0xd9, 0xa1, 0xaf, 0x00, 0xb6, 0x0b, 0x41, 0xac, 0x30, 0xb8, 0x9c, 0xf0, + 0x0a, 0x83, 0x25, 0x19, 0xe3, 0x7d, 0x6b, 0xb0, 0x8f, 0xee, 0x54, 0x19, 0xa4, 0x19, 0xc9, 0x1a, + 0x24, 0x27, 0xe9, 0xce, 0x9c, 0xa2, 0x5f, 0x00, 0x76, 0xca, 0x53, 0x43, 0xf7, 0x6a, 0x1d, 0xd4, + 0x6e, 0x4c, 0xef, 0xfe, 0x85, 0xb8, 0x6e, 0x90, 0x43, 0x3b, 0xc8, 0x43, 0xf4, 0x80, 0xd4, 0xdf, + 0xc7, 0xa5, 0x25, 0x22, 0x27, 0x85, 0x35, 0x3d, 0x7d, 0x7c, 0xf8, 0x7d, 0xee, 0x81, 0xb3, 0xb9, + 0x07, 0x7e, 0xcf, 0x3d, 0xf0, 0x69, 0xe1, 0x35, 0xce, 0x16, 0x5e, 0xe3, 0xe7, 0xc2, 0x6b, 0xbc, + 0xd9, 0x09, 0x23, 0x3d, 0x35, 0x63, 0x7f, 0x22, 0x66, 0xb9, 0x46, 0xf6, 0xe8, 0xab, 0xe0, 0x1d, + 0xf9, 0xf0, 0x4f, 0x50, 0x1f, 0x4b, 0xa6, 0xc6, 0x6b, 0xf6, 0xde, 0xef, 0xff, 0x0d, 0x00, 0x00, + 0xff, 0xff, 0x32, 0x81, 0xe9, 0x7a, 0x94, 0x04, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -678,17 +678,12 @@ func (m *QueryUpgradedConsensusStateResponse) MarshalToSizedBuffer(dAtA []byte) _ = i var l int _ = l - if m.UpgradedConsensusState != nil { - { - size, err := m.UpgradedConsensusState.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) - } + if len(m.UpgradedConsensusState) > 0 { + i -= len(m.UpgradedConsensusState) + copy(dAtA[i:], m.UpgradedConsensusState) + i = encodeVarintQuery(dAtA, i, uint64(len(m.UpgradedConsensusState))) i-- - dAtA[i] = 0xa + dAtA[i] = 0x12 } return len(dAtA) - i, nil } @@ -769,8 +764,8 @@ func (m *QueryUpgradedConsensusStateResponse) Size() (n int) { } var l int _ = l - if m.UpgradedConsensusState != nil { - l = m.UpgradedConsensusState.Size() + l = len(m.UpgradedConsensusState) + if l > 0 { n += 1 + l + sovQuery(uint64(l)) } return n @@ -1167,11 +1162,11 @@ func (m *QueryUpgradedConsensusStateResponse) Unmarshal(dAtA []byte) error { return fmt.Errorf("proto: QueryUpgradedConsensusStateResponse: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { - case 1: + case 2: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field UpgradedConsensusState", wireType) } - var msglen int + var byteLen int for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowQuery @@ -1181,26 +1176,24 @@ func (m *QueryUpgradedConsensusStateResponse) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= int(b&0x7F) << shift + byteLen |= int(b&0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { + if byteLen < 0 { return ErrInvalidLengthQuery } - postIndex := iNdEx + msglen + postIndex := iNdEx + byteLen if postIndex < 0 { return ErrInvalidLengthQuery } if postIndex > l { return io.ErrUnexpectedEOF } + m.UpgradedConsensusState = append(m.UpgradedConsensusState[:0], dAtA[iNdEx:postIndex]...) if m.UpgradedConsensusState == nil { - m.UpgradedConsensusState = &types.Any{} - } - if err := m.UpgradedConsensusState.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err + m.UpgradedConsensusState = []byte{} } iNdEx = postIndex default: diff --git a/x/upgrade/types/upgrade.pb.go b/x/upgrade/types/upgrade.pb.go index 642f4446fe28..c77d90f34df8 100644 --- a/x/upgrade/types/upgrade.pb.go +++ b/x/upgrade/types/upgrade.pb.go @@ -5,7 +5,7 @@ package types import ( fmt "fmt" - types "github.com/cosmos/cosmos-sdk/codec/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" @@ -47,12 +47,6 @@ type Plan struct { // Any application specific upgrade info to be included on-chain // such as a git commit that validators could automatically upgrade to Info string `protobuf:"bytes,4,opt,name=info,proto3" json:"info,omitempty"` - // 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 - UpgradedClientState *types.Any `protobuf:"bytes,5,opt,name=upgraded_client_state,json=upgradedClientState,proto3" json:"upgraded_client_state,omitempty" yaml:"upgraded_client_state"` } func (m *Plan) Reset() { *m = Plan{} } @@ -177,34 +171,32 @@ func init() { } var fileDescriptor_ccf2a7d4d7b48dca = []byte{ - // 426 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x52, 0x31, 0x6f, 0xd4, 0x30, - 0x18, 0x8d, 0x69, 0x5a, 0x51, 0xdf, 0x66, 0x8e, 0x12, 0x4e, 0xc5, 0x89, 0x4e, 0x0c, 0x37, 0x80, - 0xa3, 0x16, 0x09, 0xa1, 0x6e, 0xa4, 0x3b, 0xaa, 0x52, 0x58, 0x90, 0x50, 0xe5, 0x24, 0xbe, 0x9c, - 0xc1, 0xb1, 0xa3, 0xd8, 0x07, 0xe4, 0x57, 0xd0, 0x9f, 0xc0, 0xcf, 0xb9, 0xb1, 0x63, 0xa7, 0x42, - 0xef, 0x16, 0xe6, 0xfe, 0x02, 0x14, 0x3b, 0x41, 0x08, 0x3a, 0x76, 0xf2, 0xf7, 0x3d, 0xbd, 0xef, - 0x3d, 0xfb, 0xf9, 0x83, 0x4f, 0x73, 0xa5, 0x2b, 0xa5, 0xe3, 0x65, 0x5d, 0x36, 0xb4, 0x60, 0xf1, - 0xe7, 0x83, 0x8c, 0x19, 0x7a, 0x30, 0xf4, 0xa4, 0x6e, 0x94, 0x51, 0x68, 0xcf, 0xb1, 0xc8, 0x80, - 0xf6, 0xac, 0xc9, 0xe3, 0x52, 0xa9, 0x52, 0xb0, 0xd8, 0xb2, 0xb2, 0xe5, 0x3c, 0xa6, 0xb2, 0x75, - 0x23, 0x93, 0x71, 0xa9, 0x4a, 0x65, 0xcb, 0xb8, 0xab, 0x7a, 0x34, 0xfc, 0x77, 0xc0, 0xf0, 0x8a, - 0x69, 0x43, 0xab, 0xda, 0x11, 0xa6, 0x37, 0x00, 0xfa, 0x27, 0x82, 0x4a, 0x84, 0xa0, 0x2f, 0x69, - 0xc5, 0x02, 0x10, 0x81, 0xd9, 0x6e, 0x6a, 0x6b, 0xf4, 0x0a, 0xfa, 0x1d, 0x3f, 0xb8, 0x17, 0x81, - 0xd9, 0xe8, 0x70, 0x42, 0x9c, 0x18, 0x19, 0xc4, 0xc8, 0xdb, 0x41, 0x2c, 0xb9, 0xbf, 0xba, 0x0a, - 0xbd, 0xf3, 0x1f, 0x21, 0x48, 0xed, 0x04, 0xda, 0x83, 0x3b, 0x0b, 0xc6, 0xcb, 0x85, 0x09, 0xb6, - 0x22, 0x30, 0xdb, 0x4a, 0xfb, 0xae, 0x73, 0xe1, 0x72, 0xae, 0x02, 0xdf, 0xb9, 0x74, 0x35, 0xfa, - 0x08, 0x1f, 0xf6, 0xef, 0x2c, 0xce, 0x72, 0xc1, 0x99, 0x34, 0x67, 0xda, 0x50, 0xc3, 0x82, 0x6d, - 0x6b, 0x3b, 0xfe, 0xcf, 0xf6, 0xb5, 0x6c, 0x93, 0xe8, 0xe6, 0x2a, 0xdc, 0x6f, 0x69, 0x25, 0x8e, - 0xa6, 0xb7, 0x0e, 0x4f, 0xd3, 0x07, 0x03, 0x7e, 0x6c, 0xe1, 0xd3, 0x0e, 0x3d, 0xf2, 0x7f, 0x7d, - 0x0f, 0xc1, 0xf4, 0x1b, 0x80, 0x8f, 0x4e, 0xd5, 0xdc, 0x7c, 0xa1, 0x0d, 0x7b, 0xe7, 0x58, 0x27, - 0x8d, 0xaa, 0x95, 0xa6, 0x02, 0x8d, 0xe1, 0xb6, 0xe1, 0x46, 0x0c, 0x41, 0xb8, 0x06, 0x45, 0x70, - 0x54, 0x30, 0x9d, 0x37, 0xbc, 0x36, 0x5c, 0x49, 0x1b, 0xc8, 0x6e, 0xfa, 0x37, 0x84, 0x5e, 0x42, - 0xbf, 0x16, 0x54, 0xda, 0xf7, 0x8e, 0x0e, 0xf7, 0xc9, 0xed, 0x3f, 0x48, 0xba, 0xac, 0x13, 0xbf, - 0x4b, 0x2b, 0xb5, 0xfc, 0xfe, 0x46, 0x1f, 0xe0, 0x93, 0x63, 0x2a, 0x73, 0x26, 0xee, 0xf8, 0x5a, - 0x4e, 0x3e, 0x79, 0xb3, 0xba, 0xc6, 0xde, 0xe5, 0x35, 0xf6, 0x56, 0x6b, 0x0c, 0x2e, 0xd6, 0x18, - 0xfc, 0x5c, 0x63, 0x70, 0xbe, 0xc1, 0xde, 0xc5, 0x06, 0x7b, 0x97, 0x1b, 0xec, 0xbd, 0x7f, 0x56, - 0x72, 0xb3, 0x58, 0x66, 0x24, 0x57, 0x55, 0xdc, 0xaf, 0xa8, 0x3b, 0x9e, 0xeb, 0xe2, 0x53, 0xfc, - 0xf5, 0xcf, 0xbe, 0x9a, 0xb6, 0x66, 0x3a, 0xdb, 0xb1, 0x7f, 0xf1, 0xe2, 0x77, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xca, 0x9e, 0x7a, 0x5d, 0xce, 0x02, 0x00, 0x00, + // 391 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x52, 0xb1, 0x6e, 0xdb, 0x30, + 0x10, 0x15, 0x6b, 0x5a, 0xb0, 0xe9, 0xa5, 0x20, 0x0c, 0x57, 0x35, 0x5a, 0x4a, 0x30, 0x3a, 0x78, + 0x68, 0x29, 0xd8, 0x05, 0x8a, 0xa2, 0xa3, 0xbb, 0x75, 0x28, 0x0c, 0xb5, 0x5d, 0x0a, 0x64, 0xa0, + 0x64, 0x5a, 0x16, 0x22, 0x89, 0x82, 0x44, 0x27, 0xf1, 0x57, 0xc4, 0x43, 0x3e, 0x20, 0x9f, 0xe3, + 0xd1, 0xa3, 0xa7, 0x24, 0xb6, 0x97, 0x7c, 0x46, 0x20, 0x52, 0x0a, 0x82, 0x20, 0x63, 0x26, 0xbd, + 0x3b, 0xbc, 0x7b, 0xf7, 0xf4, 0x78, 0xe8, 0x53, 0x20, 0x8a, 0x44, 0x14, 0xee, 0x32, 0x0b, 0x73, + 0x36, 0xe3, 0xee, 0xd9, 0xc8, 0xe7, 0x92, 0x8d, 0xea, 0x9a, 0x66, 0xb9, 0x90, 0x02, 0xf7, 0x34, + 0x8b, 0xd6, 0xdd, 0x8a, 0xd5, 0x7f, 0x1f, 0x0a, 0x11, 0xc6, 0xdc, 0x55, 0x2c, 0x7f, 0x39, 0x77, + 0x59, 0xba, 0xd2, 0x23, 0xfd, 0x6e, 0x28, 0x42, 0xa1, 0xa0, 0x5b, 0xa2, 0xaa, 0x6b, 0x3f, 0x1f, + 0x90, 0x51, 0xc2, 0x0b, 0xc9, 0x92, 0x4c, 0x13, 0x06, 0x57, 0x00, 0xc1, 0x69, 0xcc, 0x52, 0x8c, + 0x11, 0x4c, 0x59, 0xc2, 0x2d, 0xe0, 0x80, 0x61, 0xdb, 0x53, 0x18, 0x7f, 0x47, 0xb0, 0xe4, 0x5b, + 0x6f, 0x1c, 0x30, 0xec, 0x8c, 0xfb, 0x54, 0x8b, 0xd1, 0x5a, 0x8c, 0xfe, 0xad, 0xc5, 0x26, 0xad, + 0xcd, 0x8d, 0x6d, 0xac, 0x6f, 0x6d, 0xe0, 0xa9, 0x09, 0xdc, 0x43, 0xe6, 0x82, 0x47, 0xe1, 0x42, + 0x5a, 0x0d, 0x07, 0x0c, 0x1b, 0x5e, 0x55, 0x95, 0x5b, 0xa2, 0x74, 0x2e, 0x2c, 0xa8, 0xb7, 0x94, + 0xf8, 0x07, 0xbc, 0xbf, 0xb6, 0xc1, 0x2f, 0xd8, 0x6a, 0xbe, 0x35, 0x3d, 0x53, 0x64, 0x32, 0x12, + 0xe9, 0xe0, 0x12, 0xa0, 0x77, 0x7f, 0xc4, 0x5c, 0x9e, 0xb3, 0x9c, 0xff, 0xd3, 0x21, 0x4c, 0x73, + 0x91, 0x89, 0x82, 0xc5, 0xb8, 0x8b, 0x9a, 0x32, 0x92, 0x71, 0x6d, 0x55, 0x17, 0xd8, 0x41, 0x9d, + 0x19, 0x2f, 0x82, 0x3c, 0x52, 0x02, 0xca, 0x72, 0xdb, 0x7b, 0xda, 0xc2, 0xdf, 0x10, 0xcc, 0x62, + 0x96, 0x2a, 0x47, 0x9d, 0xf1, 0x07, 0xfa, 0x72, 0xc6, 0xb4, 0x4c, 0x63, 0x02, 0xcb, 0xff, 0xf1, + 0x14, 0x5f, 0xfb, 0x1b, 0x9c, 0xa0, 0x8f, 0x3f, 0x59, 0x1a, 0xf0, 0xf8, 0x95, 0x6d, 0x69, 0xf9, + 0xc9, 0xef, 0xcd, 0x9e, 0x18, 0xbb, 0x3d, 0x31, 0x36, 0x07, 0x02, 0xb6, 0x07, 0x02, 0xee, 0x0e, + 0x04, 0xac, 0x8f, 0xc4, 0xd8, 0x1e, 0x89, 0xb1, 0x3b, 0x12, 0xe3, 0xff, 0xe7, 0x30, 0x92, 0x8b, + 0xa5, 0x4f, 0x03, 0x91, 0xb8, 0xd5, 0x11, 0xe9, 0xcf, 0x97, 0x62, 0x76, 0xea, 0x5e, 0x3c, 0x5e, + 0x94, 0x5c, 0x65, 0xbc, 0xf0, 0x4d, 0xf5, 0x48, 0x5f, 0x1f, 0x02, 0x00, 0x00, 0xff, 0xff, 0x9b, + 0x57, 0x9e, 0x92, 0x70, 0x02, 0x00, 0x00, } func (this *Plan) Equal(that interface{}) bool { @@ -238,9 +230,6 @@ func (this *Plan) Equal(that interface{}) bool { if this.Info != that1.Info { return false } - if !this.UpgradedClientState.Equal(that1.UpgradedClientState) { - return false - } return true } func (this *SoftwareUpgradeProposal) Equal(that interface{}) bool { @@ -320,18 +309,6 @@ func (m *Plan) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if m.UpgradedClientState != nil { - { - size, err := m.UpgradedClientState.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintUpgrade(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x2a - } if len(m.Info) > 0 { i -= len(m.Info) copy(dAtA[i:], m.Info) @@ -344,12 +321,12 @@ func (m *Plan) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x18 } - n2, err2 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):]) - if err2 != nil { - return 0, err2 + n1, err1 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):]) + if err1 != nil { + return 0, err1 } - i -= n2 - i = encodeVarintUpgrade(dAtA, i, uint64(n2)) + i -= n1 + i = encodeVarintUpgrade(dAtA, i, uint64(n1)) i-- dAtA[i] = 0x12 if len(m.Name) > 0 { @@ -476,10 +453,6 @@ func (m *Plan) Size() (n int) { if l > 0 { n += 1 + l + sovUpgrade(uint64(l)) } - if m.UpgradedClientState != nil { - l = m.UpgradedClientState.Size() - n += 1 + l + sovUpgrade(uint64(l)) - } return n } @@ -670,42 +643,6 @@ func (m *Plan) Unmarshal(dAtA []byte) error { } m.Info = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field UpgradedClientState", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowUpgrade - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthUpgrade - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthUpgrade - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.UpgradedClientState == nil { - m.UpgradedClientState = &types.Any{} - } - if err := m.UpgradedClientState.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipUpgrade(dAtA[iNdEx:]) From 010eeef457ac608d1e91176b0a2d6c58c23ae2e1 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Mon, 1 Mar 2021 20:09:01 +0000 Subject: [PATCH 140/214] Rename InfoImporter -> LegacyInfoImporter (#8739) Avoid namespace clash with the InfoImporter interface that already exists in the v0.41 release series. --- client/keys/migrate.go | 2 +- crypto/keyring/keyring.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/keys/migrate.go b/client/keys/migrate.go index 4848ec281162..4816381e8c6f 100644 --- a/client/keys/migrate.go +++ b/client/keys/migrate.go @@ -111,7 +111,7 @@ func runMigrateCmd(cmd *cobra.Command, args []string) error { // TypeLocal needs an additional step to ask password. // The other keyring types are handled by ImportInfo. if keyType != keyring.TypeLocal { - infoImporter, ok := migrator.(keyring.InfoImporter) + infoImporter, ok := migrator.(keyring.LegacyInfoImporter) if !ok { return fmt.Errorf("the Keyring implementation does not support import operations of Info types") } diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index 45b43ac2319a..9734af37b1ae 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -116,8 +116,8 @@ type Importer interface { ImportPubKey(uid string, armor string) error } -// InfoImporter is implemented by key stores that support import of Info types. -type InfoImporter interface { +// LegacyInfoImporter is implemented by key stores that support import of Info types. +type LegacyInfoImporter interface { // ImportInfo import a keyring.Info into the current keyring. // It is used to migrate multisig, ledger, and public key Info structure. ImportInfo(oldInfo Info) error From 585ffd6cffff8ed6d1ba6a2a284bf40c7bb32e71 Mon Sep 17 00:00:00 2001 From: Emmanuel T Odeke Date: Tue, 2 Mar 2021 01:01:05 -0800 Subject: [PATCH 141/214] x/staking: add ValidateGenesis benchmark (#8746) This benchmark examines how ValidateGenesis behaves. In a follow-up issue, I'll show how it reveals an inefficiency that'll affect trying to load repeatedly retrieve Validators' ConsAddress values. Updates #8744 --- x/staking/bench_test.go | 56 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 x/staking/bench_test.go diff --git a/x/staking/bench_test.go b/x/staking/bench_test.go new file mode 100644 index 000000000000..7705b6d3114f --- /dev/null +++ b/x/staking/bench_test.go @@ -0,0 +1,56 @@ +package staking_test + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" + sdk "github.com/cosmos/cosmos-sdk/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 BenchmarkValidateGenesis10Validators(b *testing.B) { + benchmarkValidateGenesis(b, 10) +} + +func BenchmarkValidateGenesis100Validators(b *testing.B) { + benchmarkValidateGenesis(b, 100) +} + +func BenchmarkValidateGenesis400Validators(b *testing.B) { + benchmarkValidateGenesis(b, 400) +} + +func benchmarkValidateGenesis(b *testing.B, n int) { + b.ReportAllocs() + + validators := make([]types.Validator, 0, n) + addressL, pubKeyL := makeRandomAddressesAndPublicKeys(n) + for i := 0; i < n; i++ { + addr, pubKey := addressL[i], pubKeyL[i] + validator := teststaking.NewValidator(b, addr, pubKey) + ni := int64(i + 1) + validator.Tokens = sdk.NewInt(ni) + validator.DelegatorShares = sdk.NewDec(ni) + validators = append(validators, validator) + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + genesisState := types.DefaultGenesisState() + genesisState.Validators = validators + if err := staking.ValidateGenesis(genesisState); err != nil { + b.Fatal(err) + } + } +} + +func makeRandomAddressesAndPublicKeys(n int) (accL []sdk.ValAddress, pkL []*ed25519.PubKey) { + for i := 0; i < n; i++ { + pk := ed25519.GenPrivKey().PubKey().(*ed25519.PubKey) + pkL = append(pkL, pk) + accL = append(accL, sdk.ValAddress(pk.Address())) + } + return accL, pkL +} From a193522f7e54cd747d549bc4adb83618aac223af Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Tue, 2 Mar 2021 16:56:51 +0700 Subject: [PATCH 142/214] crypto/keys/internal: use crypto/rand.Reader for generating private key (#8742) genPrivKey rejects invalid fieldelems, so we must use a real reader instead of the zero reader. Fixes #8741 --- crypto/keys/internal/benchmarking/bench.go | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/crypto/keys/internal/benchmarking/bench.go b/crypto/keys/internal/benchmarking/bench.go index a55936d5c3c8..aab5d5f30382 100644 --- a/crypto/keys/internal/benchmarking/bench.go +++ b/crypto/keys/internal/benchmarking/bench.go @@ -1,6 +1,7 @@ package benchmarking import ( + "crypto/rand" "io" "testing" @@ -13,22 +14,12 @@ import ( // Use of this source code is governed by a BSD-style // license that can be found at the bottom of this file. -type zeroReader struct{} - -func (zeroReader) Read(buf []byte) (int, error) { - for i := range buf { - buf[i] = 0 - } - return len(buf), nil -} - // 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) + generateKey(rand.Reader) } } From 810605689d88d12389e1ebc0ccacf647fab7cf0e Mon Sep 17 00:00:00 2001 From: Marko Date: Tue, 2 Mar 2021 15:39:46 +0000 Subject: [PATCH 143/214] further reduce logging (#8752) --- x/slashing/keeper/infractions.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/slashing/keeper/infractions.go b/x/slashing/keeper/infractions.go index 0c93717d13eb..06baa48f82b4 100644 --- a/x/slashing/keeper/infractions.go +++ b/x/slashing/keeper/infractions.go @@ -60,7 +60,7 @@ func (k Keeper) HandleValidatorSignature(ctx sdk.Context, addr cryptotypes.Addre ), ) - logger.Info( + logger.Debug( "absent validator", "height", height, "validator", consAddr.String(), From 30f58b5662984777af9f60825f884a3d696d5bfa Mon Sep 17 00:00:00 2001 From: Amaury <1293565+amaurym@users.noreply.github.com> Date: Tue, 2 Mar 2021 23:22:02 +0100 Subject: [PATCH 144/214] Weighted votes migrate in-place migrations (#8663) * Weighted votes migrate in-place migrations * Rename to pb.go * Fix some lint * Fix lint Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- x/gov/keeper/migrations.go | 2 +- x/gov/legacy/v040/gov.pb.go | 302 ++++++++++++++++++++++++++++++++ x/gov/legacy/v040/vote.go | 78 +++++++++ x/gov/legacy/v042/store.go | 35 +++- x/gov/legacy/v042/store_test.go | 46 ++--- 5 files changed, 439 insertions(+), 24 deletions(-) create mode 100644 x/gov/legacy/v040/gov.pb.go create mode 100644 x/gov/legacy/v040/vote.go diff --git a/x/gov/keeper/migrations.go b/x/gov/keeper/migrations.go index c643c6dd7b99..e0134012258f 100644 --- a/x/gov/keeper/migrations.go +++ b/x/gov/keeper/migrations.go @@ -17,5 +17,5 @@ func NewMigrator(keeper Keeper) Migrator { // Migrate1to2 migrates from version 1 to 2. func (m Migrator) Migrate1to2(ctx sdk.Context) error { - return v042.MigrateStore(ctx, m.keeper.storeKey) + return v042.MigrateStore(ctx, m.keeper.storeKey, m.keeper.cdc) } diff --git a/x/gov/legacy/v040/gov.pb.go b/x/gov/legacy/v040/gov.pb.go new file mode 100644 index 000000000000..9e2bb2d0f8fe --- /dev/null +++ b/x/gov/legacy/v040/gov.pb.go @@ -0,0 +1,302 @@ +// Package v040 is take from: +// https://github.com/cosmos/cosmos-sdk/blob/v0.41.1/x/gov/types/gov.pb.go +// by copy-pasted only the relevants parts for Vote. +package v040 + +import ( + "fmt" + "io" + math_bits "math/bits" + + "github.com/cosmos/cosmos-sdk/x/gov/types" +) + +type Vote struct { + ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty" yaml:"proposal_id"` //nolint:golint + Voter string `protobuf:"bytes,2,opt,name=voter,proto3" json:"voter,omitempty"` + Option types.VoteOption `protobuf:"varint,3,opt,name=option,proto3,enum=cosmos.gov.v1beta1.VoteOption" json:"option,omitempty"` +} + +func (m *Vote) Reset() { *m = Vote{} } +func (*Vote) ProtoMessage() {} + +func (m *Vote) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ProposalId != 0 { + n += 1 + sovGov(m.ProposalId) + } + l = len(m.Voter) + if l > 0 { + n += 1 + l + sovGov(uint64(l)) + } + if m.Option != 0 { + n += 1 + sovGov(uint64(m.Option)) + } + return n +} + +func (m *Vote) 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 *Vote) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Vote) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Option != 0 { + i = encodeVarintGov(dAtA, i, uint64(m.Option)) + i-- + dAtA[i] = 0x18 + } + if len(m.Voter) > 0 { + i -= len(m.Voter) + copy(dAtA[i:], m.Voter) + i = encodeVarintGov(dAtA, i, uint64(len(m.Voter))) + i-- + dAtA[i] = 0x12 + } + if m.ProposalId != 0 { + i = encodeVarintGov(dAtA, i, m.ProposalId) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func encodeVarintGov(dAtA []byte, offset int, v uint64) int { + offset -= sovGov(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} + +func sovGov(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} + +func (m *Vote) 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: Vote: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Vote: 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 ErrIntOverflowGov + } + 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 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 + } + 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 { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Option |= types.VoteOption(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipGov(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGov + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} + +func skipGov(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, ErrIntOverflowGov + } + 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, ErrIntOverflowGov + } + 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, ErrIntOverflowGov + } + 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, ErrInvalidLengthGov + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupGov + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthGov + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthGov = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowGov = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupGov = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/gov/legacy/v040/vote.go b/x/gov/legacy/v040/vote.go new file mode 100644 index 000000000000..59bde951070b --- /dev/null +++ b/x/gov/legacy/v040/vote.go @@ -0,0 +1,78 @@ +// Package v040 is copy-pasted from: +// https://github.com/cosmos/cosmos-sdk/blob/v0.41.1/x/gov/types/vote.go +package v040 + +import ( + "fmt" + + yaml "gopkg.in/yaml.v2" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/gov/types" +) + +// NewVote creates a new Vote instance +//nolint:interfacer +func NewVote(proposalID uint64, voter sdk.AccAddress, option types.VoteOption) Vote { + return Vote{proposalID, voter.String(), option} +} + +func (v Vote) String() string { + out, _ := yaml.Marshal(v) + return string(out) +} + +// Votes is a collection of Vote objects +type Votes []Vote + +// Equal returns true if two slices (order-dependant) of votes are equal. +func (v Votes) Equal(other Votes) bool { + if len(v) != len(other) { + return false + } + + for i, vote := range v { + if vote.String() != other[i].String() { + return false + } + } + + return true +} + +func (v Votes) String() string { + if len(v) == 0 { + return "[]" + } + out := fmt.Sprintf("Votes for Proposal %d:", v[0].ProposalId) + for _, vot := range v { + out += fmt.Sprintf("\n %s: %s", vot.Voter, vot.Option) + } + return out +} + +// Empty returns whether a vote is empty. +func (v Vote) Empty() bool { + return v.String() == Vote{}.String() +} + +// VoteOptionFromString returns a VoteOption from a string. It returns an error +// if the string is invalid. +func VoteOptionFromString(str string) (types.VoteOption, error) { + option, ok := types.VoteOption_value[str] + if !ok { + return types.OptionEmpty, fmt.Errorf("'%s' is not a valid vote option", str) + } + return types.VoteOption(option), nil +} + +// ValidVoteOption returns true if the vote option is valid and false otherwise. +func ValidVoteOption(option types.VoteOption) bool { + if option == types.OptionYes || + option == types.OptionAbstain || + option == types.OptionNo || + option == types.OptionNoWithVeto { + return true + } + return false +} diff --git a/x/gov/legacy/v042/store.go b/x/gov/legacy/v042/store.go index acf824a16139..4c49d016bebd 100644 --- a/x/gov/legacy/v042/store.go +++ b/x/gov/legacy/v042/store.go @@ -1,10 +1,12 @@ package v042 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" v040gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v040" + "github.com/cosmos/cosmos-sdk/x/gov/types" ) const proposalIDLen = 8 @@ -30,14 +32,41 @@ func migratePrefixProposalAddress(store sdk.KVStore, prefixBz []byte) { } } +// migrateWeightedVotes migrates the ADR-037 weighted votes. +func migrateWeightedVotes(store sdk.KVStore, cdc codec.BinaryMarshaler) error { + iterator := sdk.KVStorePrefixIterator(store, v040gov.VotesKeyPrefix) + + defer iterator.Close() + for ; iterator.Valid(); iterator.Next() { + var oldVote v040gov.Vote + err := cdc.UnmarshalBinaryBare(iterator.Value(), &oldVote) + if err != nil { + return err + } + + newVote := &types.Vote{ + ProposalId: oldVote.ProposalId, + Voter: oldVote.Voter, + Options: []types.WeightedVoteOption{{Option: oldVote.Option, Weight: sdk.NewDec(1)}}, + } + bz, err := cdc.MarshalBinaryBare(newVote) + if err != nil { + return err + } + + store.Set(iterator.Key(), bz) + } + + return nil +} + // MigrateStore performs in-place store migrations from v0.40 to v0.42. The // migration includes: // // - Change addresses to be length-prefixed. -func MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey) error { +func MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, cdc codec.BinaryMarshaler) error { store := ctx.KVStore(storeKey) migratePrefixProposalAddress(store, v040gov.DepositsKeyPrefix) migratePrefixProposalAddress(store, v040gov.VotesKeyPrefix) - - return nil + return migrateWeightedVotes(store, cdc) } diff --git a/x/gov/legacy/v042/store_test.go b/x/gov/legacy/v042/store_test.go index 6bcb056a9c99..6eaeab7e9bcb 100644 --- a/x/gov/legacy/v042/store_test.go +++ b/x/gov/legacy/v042/store_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/require" + "github.com/cosmos/cosmos-sdk/simapp" "github.com/cosmos/cosmos-sdk/testutil" "github.com/cosmos/cosmos-sdk/testutil/testdata" sdk "github.com/cosmos/cosmos-sdk/types" @@ -16,6 +17,7 @@ import ( ) func TestStoreMigration(t *testing.T) { + cdc := simapp.MakeTestEncodingConfig().Marshaler govKey := sdk.NewKVStoreKey("gov") ctx := testutil.DefaultContext(govKey, sdk.NewTransientStoreKey("transient_test")) store := ctx.KVStore(govKey) @@ -23,53 +25,57 @@ func TestStoreMigration(t *testing.T) { _, _, addr1 := testdata.KeyTestPubAddr() proposalID := uint64(6) now := time.Now() - // Use dummy value for all keys. - value := []byte("foo") + // Use dummy value for keys where we don't test values. + dummyValue := []byte("foo") + // Use real values for votes, as we're testing weighted votes. + oldVote := v040gov.Vote{ProposalId: 1, Voter: "foobar", Option: types.OptionNoWithVeto} + oldVoteValue := cdc.MustMarshalBinaryBare(&oldVote) + newVote := types.Vote{ProposalId: 1, Voter: "foobar", Options: types.WeightedVoteOptions{{Option: types.OptionNoWithVeto, Weight: sdk.NewDec(1)}}} + newVoteValue := cdc.MustMarshalBinaryBare(&newVote) testCases := []struct { - name string - oldKey []byte - newKey []byte + name string + oldKey, oldValue, newKey, newValue []byte }{ { "ProposalKey", - v040gov.ProposalKey(proposalID), - types.ProposalKey(proposalID), + v040gov.ProposalKey(proposalID), dummyValue, + types.ProposalKey(proposalID), dummyValue, }, { "ActiveProposalQueue", - v040gov.ActiveProposalQueueKey(proposalID, now), - types.ActiveProposalQueueKey(proposalID, now), + v040gov.ActiveProposalQueueKey(proposalID, now), dummyValue, + types.ActiveProposalQueueKey(proposalID, now), dummyValue, }, { "InactiveProposalQueue", - v040gov.InactiveProposalQueueKey(proposalID, now), - types.InactiveProposalQueueKey(proposalID, now), + v040gov.InactiveProposalQueueKey(proposalID, now), dummyValue, + types.InactiveProposalQueueKey(proposalID, now), dummyValue, }, { "ProposalIDKey", - v040gov.ProposalIDKey, - types.ProposalIDKey, + v040gov.ProposalIDKey, dummyValue, + types.ProposalIDKey, dummyValue, }, { "DepositKey", - v040gov.DepositKey(proposalID, addr1), - types.DepositKey(proposalID, addr1), + v040gov.DepositKey(proposalID, addr1), dummyValue, + types.DepositKey(proposalID, addr1), dummyValue, }, { "VotesKeyPrefix", - v040gov.VoteKey(proposalID, addr1), - types.VoteKey(proposalID, addr1), + v040gov.VoteKey(proposalID, addr1), oldVoteValue, + types.VoteKey(proposalID, addr1), newVoteValue, }, } // Set all the old keys to the store for _, tc := range testCases { - store.Set(tc.oldKey, value) + store.Set(tc.oldKey, tc.oldValue) } // Run migrations. - err := v042gov.MigrateStore(ctx, govKey) + err := v042gov.MigrateStore(ctx, govKey, cdc) require.NoError(t, err) // Make sure the new keys are set and old keys are deleted. @@ -79,7 +85,7 @@ func TestStoreMigration(t *testing.T) { if bytes.Compare(tc.oldKey, tc.newKey) != 0 { require.Nil(t, store.Get(tc.oldKey)) } - require.Equal(t, value, store.Get(tc.newKey)) + require.Equal(t, tc.newValue, store.Get(tc.newKey)) }) } } From 2864eb69a3cfb76ed415fd622ffee984425e57e3 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Wed, 3 Mar 2021 04:53:28 +0100 Subject: [PATCH 145/214] Robert/addr memory leak (#8717) * address: adding cache address.String() cache benchmark * address: use LRU cache for .String() * optimize address.Empty * move cache initialization to init function * Use UnsafeBytesToStr convertion with Addr cache * add cache for other address String() methods * fix linter issue * add a non trivial address for Address.String benchmark * add comment about cache size and update cashe size to 60k * fix syntax Co-authored-by: Alessio Treglia --- types/address.go | 119 ++++++++++++++++++------------------ types/address_bench_test.go | 19 ++++++ 2 files changed, 78 insertions(+), 60 deletions(-) diff --git a/types/address.go b/types/address.go index 8e6a8103f3b0..d96c2f324739 100644 --- a/types/address.go +++ b/types/address.go @@ -13,9 +13,11 @@ import ( "github.com/cosmos/cosmos-sdk/codec/legacy" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/internal/conv" "github.com/cosmos/cosmos-sdk/types/address" "github.com/cosmos/cosmos-sdk/types/bech32" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/hashicorp/golang-lru/simplelru" ) const ( @@ -72,6 +74,33 @@ const ( Bech32PrefixConsPub = Bech32MainPrefix + PrefixValidator + PrefixConsensus + PrefixPublic ) +// cache variables +var ( + // AccAddress.String() is expensive and if unoptimized dominantly showed up in profiles, + // yet has no mechanisms to trivially cache the result given that AccAddress is a []byte type. + accAddrMu sync.Mutex + accAddrCache *simplelru.LRU + consAddrMu sync.Mutex + consAddrCache *simplelru.LRU + valAddrMu sync.Mutex + valAddrCache *simplelru.LRU +) + +func init() { + var err error + // in total the cache size is 61k entries. Key is 32 bytes and value is around 50-70 bytes. + // That will make around 92 * 61k * 2 (LRU) bytes ~ 11 MB + if accAddrCache, err = simplelru.NewLRU(60000, nil); err != nil { + panic(err) + } + if consAddrCache, err = simplelru.NewLRU(500, nil); err != nil { + panic(err) + } + if valAddrCache, err = simplelru.NewLRU(500, nil); err != nil { + panic(err) + } +} + // Address is a common interface for different types of addresses used by the SDK type Address interface { Equals(Address) bool @@ -158,12 +187,7 @@ func (aa AccAddress) Equals(aa2 Address) bool { // Returns boolean for whether an AccAddress is empty func (aa AccAddress) Empty() bool { - if aa == nil { - return true - } - - aa2 := AccAddress{} - return bytes.Equal(aa.Bytes(), aa2.Bytes()) + return aa == nil || len(aa) == 0 } // Marshal returns the raw address bytes. It is needed for protobuf @@ -237,40 +261,18 @@ func (aa AccAddress) Bytes() []byte { return aa } -// AccAddress.String() is expensive and if unoptimized dominantly showed up in profiles, -// yet has no mechanisms to trivially cache the result given that AccAddress is a []byte type. -// With the string interning below, we are able to achieve zero cost allocations for string->[]byte -// because the Go compiler recognizes the special case of map[string([]byte)] when used exactly -// in that pattern. See https://github.com/cosmos/cosmos-sdk/issues/8693. -var addMu sync.Mutex -var addrStrMemoize = make(map[string]string) - // String implements the Stringer interface. -func (aa AccAddress) String() (str string) { - addMu.Lock() - defer addMu.Unlock() - - if str, ok := addrStrMemoize[string(aa)]; ok { - return str - } - - // Otherwise cache it for later memoization. - defer func() { - addrStrMemoize[string(aa)] = str - }() - +func (aa AccAddress) String() string { if aa.Empty() { return "" } - bech32PrefixAccAddr := GetConfig().GetBech32AccountAddrPrefix() - - bech32Addr, err := bech32.ConvertAndEncode(bech32PrefixAccAddr, aa.Bytes()) - if err != nil { - panic(err) + var key = conv.UnsafeBytesToStr(aa) + if addr, ok := accAddrCache.Get(key); ok { + return addr.(string) } - - return bech32Addr + return cacheBech32Addr(GetConfig().GetBech32AccountAddrPrefix(), + aa, &accAddrMu, accAddrCache, key) } // Format implements the fmt.Formatter interface. @@ -332,12 +334,7 @@ func (va ValAddress) Equals(va2 Address) bool { // Returns boolean for whether an AccAddress is empty func (va ValAddress) Empty() bool { - if va == nil { - return true - } - - va2 := ValAddress{} - return bytes.Equal(va.Bytes(), va2.Bytes()) + return va == nil || len(va) == 0 } // Marshal returns the raw address bytes. It is needed for protobuf @@ -418,14 +415,12 @@ func (va ValAddress) String() string { return "" } - bech32PrefixValAddr := GetConfig().GetBech32ValidatorAddrPrefix() - - bech32Addr, err := bech32.ConvertAndEncode(bech32PrefixValAddr, va.Bytes()) - if err != nil { - panic(err) + var key = conv.UnsafeBytesToStr(va) + if addr, ok := valAddrCache.Get(key); ok { + return addr.(string) } - - return bech32Addr + return cacheBech32Addr(GetConfig().GetBech32ValidatorAddrPrefix(), + va, &valAddrMu, valAddrCache, key) } // Format implements the fmt.Formatter interface. @@ -492,12 +487,7 @@ func (ca ConsAddress) Equals(ca2 Address) bool { // Returns boolean for whether an ConsAddress is empty func (ca ConsAddress) Empty() bool { - if ca == nil { - return true - } - - ca2 := ConsAddress{} - return bytes.Equal(ca.Bytes(), ca2.Bytes()) + return ca == nil || len(ca) == 0 } // Marshal returns the raw address bytes. It is needed for protobuf @@ -578,14 +568,12 @@ func (ca ConsAddress) String() string { return "" } - bech32PrefixConsAddr := GetConfig().GetBech32ConsensusAddrPrefix() - - bech32Addr, err := bech32.ConvertAndEncode(bech32PrefixConsAddr, ca.Bytes()) - if err != nil { - panic(err) + var key = conv.UnsafeBytesToStr(ca) + if addr, ok := consAddrCache.Get(key); ok { + return addr.(string) } - - return bech32Addr + return cacheBech32Addr(GetConfig().GetBech32ConsensusAddrPrefix(), + ca, &consAddrMu, consAddrCache, key) } // Bech32ifyAddressBytes returns a bech32 representation of address bytes. @@ -730,3 +718,14 @@ func addressBytesFromHexString(address string) ([]byte, error) { return hex.DecodeString(address) } + +func cacheBech32Addr(prefix string, addr []byte, m sync.Locker, cache *simplelru.LRU, cacheKey string) string { + bech32Addr, err := bech32.ConvertAndEncode(prefix, addr) + if err != nil { + panic(err) + } + m.Lock() + cache.Add(cacheKey, bech32Addr) + m.Unlock() + return bech32Addr +} diff --git a/types/address_bench_test.go b/types/address_bench_test.go index 88a7e537a0d2..377cffad2395 100644 --- a/types/address_bench_test.go +++ b/types/address_bench_test.go @@ -11,6 +11,25 @@ import ( "github.com/cosmos/cosmos-sdk/types" ) +func BenchmarkAccAddressString(b *testing.B) { + b.ReportAllocs() + pkBz := make([]byte, ed25519.PubKeySize) + pk := &ed25519.PubKey{Key: pkBz} + a := pk.Address() + pk2 := make([]byte, ed25519.PubKeySize) + for i := 1; i <= ed25519.PubKeySize; i++ { + pk2[i] = byte(i) + } + a2 := pk.Address() + var str, str2 string + for i := 0; i < b.N; i++ { + str = a.String() + str2 = a2.String() + } + require.NotEmpty(b, str) + require.NotEmpty(b, str2) +} + func BenchmarkBech32ifyPubKey(b *testing.B) { b.ReportAllocs() pkBz := make([]byte, ed25519.PubKeySize) From eb8aaf939513d3bf6e82bd13691cfbe9ef4ad28c Mon Sep 17 00:00:00 2001 From: SaReN Date: Wed, 3 Mar 2021 15:28:16 +0530 Subject: [PATCH 146/214] Index supply by denom (#8517) * temp commit * remove supply * update tests * revert proto script * fix lint * update tests * remove decoder * fix lint * update set supply * add changelog Co-authored-by: Jonathan Gimeno --- CHANGELOG.md | 3 +- proto/cosmos/bank/v1beta1/bank.proto | 13 -- x/bank/exported/exported.go | 17 -- x/bank/keeper/genesis.go | 4 +- x/bank/keeper/genesis_test.go | 8 +- x/bank/keeper/grpc_query.go | 6 +- x/bank/keeper/grpc_query_test.go | 12 +- x/bank/keeper/invariants.go | 6 +- x/bank/keeper/keeper.go | 93 ++++++--- x/bank/keeper/keeper_test.go | 32 +-- x/bank/keeper/querier.go | 7 +- x/bank/keeper/querier_test.go | 10 +- x/bank/module.go | 4 +- x/bank/simulation/decoder.go | 39 ---- x/bank/simulation/decoder_test.go | 51 ----- x/bank/types/bank.pb.go | 281 ++++---------------------- x/bank/types/codec.go | 9 - x/bank/types/genesis.go | 4 +- x/bank/types/supply.go | 58 ------ x/bank/types/supply_test.go | 28 --- x/feegrant/simulation/decoder_test.go | 1 + x/staking/keeper/pool.go | 2 +- x/staking/types/expected_keepers.go | 3 +- 23 files changed, 152 insertions(+), 539 deletions(-) delete mode 100644 x/bank/simulation/decoder.go delete mode 100644 x/bank/simulation/decoder_test.go delete mode 100644 x/bank/types/supply.go delete mode 100644 x/bank/types/supply_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index dd5a0a56221b..8c9dc44c7524 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -52,6 +52,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (client/keys) [\#8500](https://github.com/cosmos/cosmos-sdk/pull/8500) `InfoImporter` interface is removed from legacy keybase. * [\#8629](https://github.com/cosmos/cosmos-sdk/pull/8629) Deprecated `SetFullFundraiserPath` from `Config` in favor of `SetPurpose` and `SetCoinType`. * (x/upgrade) [\#8673](https://github.com/cosmos/cosmos-sdk/pull/8673) Remove IBC logic from x/upgrade. Deprecates IBC fields in an Upgrade Plan. IBC upgrade logic moved to 02-client and an IBC UpgradeProposal is added. +* (x/bank) [\#8517](https://github.com/cosmos/cosmos-sdk/pull/8517) `SupplyI` interface and `Supply` are removed and uses `sdk.Coins` for supply tracking ### State Machine Breaking @@ -61,7 +62,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (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 * (x/bank) [\#8656](https://github.com/cosmos/cosmos-sdk/pull/8656) balance and supply are now correctly tracked via `coin_spent`, `coin_received`, `coinbase` and `burn` events. - +* (x/bank) [\#8517](https://github.com/cosmos/cosmos-sdk/pull/8517) Supply is now stored and tracked as `sdk.Coins` ### Improvements * (x/bank) [\#8614](https://github.com/cosmos/cosmos-sdk/issues/8614) Add `Name` and `Symbol` fields to denom metadata diff --git a/proto/cosmos/bank/v1beta1/bank.proto b/proto/cosmos/bank/v1beta1/bank.proto index b60027c88629..4742bafb17e5 100644 --- a/proto/cosmos/bank/v1beta1/bank.proto +++ b/proto/cosmos/bank/v1beta1/bank.proto @@ -43,19 +43,6 @@ message Output { [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"]; } -// Supply represents a struct that passively keeps track of the total supply -// amounts in the network. -message Supply { - option (gogoproto.equal) = true; - option (gogoproto.goproto_getters) = false; - option (gogoproto.goproto_stringer) = false; - - option (cosmos_proto.implements_interface) = "*github.com/cosmos/cosmos-sdk/x/bank/exported.SupplyI"; - - repeated cosmos.base.v1beta1.Coin total = 1 - [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"]; -} - // DenomUnit represents a struct that describes a given // denomination unit of the basic token. message DenomUnit { diff --git a/x/bank/exported/exported.go b/x/bank/exported/exported.go index ae13d99d5a87..c4f2e9f6da09 100644 --- a/x/bank/exported/exported.go +++ b/x/bank/exported/exported.go @@ -1,8 +1,6 @@ package exported import ( - "github.com/gogo/protobuf/proto" - sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -12,18 +10,3 @@ type GenesisBalance interface { GetAddress() sdk.AccAddress GetCoins() sdk.Coins } - -// SupplyI defines an inflationary supply interface for modules that handle -// token supply. -type SupplyI interface { - proto.Message - - GetTotal() sdk.Coins - SetTotal(total sdk.Coins) - - Inflate(amount sdk.Coins) - Deflate(amount sdk.Coins) - - String() string - ValidateBasic() error -} diff --git a/x/bank/keeper/genesis.go b/x/bank/keeper/genesis.go index 2781645c4e5c..dc73ae0b0632 100644 --- a/x/bank/keeper/genesis.go +++ b/x/bank/keeper/genesis.go @@ -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, genState.Supply) for _, meta := range genState.DenomMetadata { k.SetDenomMetaData(ctx, meta) @@ -43,7 +43,7 @@ func (k BaseKeeper) ExportGenesis(ctx sdk.Context) *types.GenesisState { return types.NewGenesisState( k.GetParams(ctx), k.GetAccountsBalances(ctx), - k.GetSupply(ctx).GetTotal(), + k.GetTotalSupply(ctx), k.GetAllDenomMetaData(ctx), ) } diff --git a/x/bank/keeper/genesis_test.go b/x/bank/keeper/genesis_test.go index 35e56c1295d1..6b148a006c02 100644 --- a/x/bank/keeper/genesis_test.go +++ b/x/bank/keeper/genesis_test.go @@ -31,21 +31,21 @@ func (suite *IntegrationTestSuite) TestExportGenesis() { suite.Require().Len(exportGenesis.Params.SendEnabled, 0) suite.Require().Equal(types.DefaultParams().DefaultSendEnabled, exportGenesis.Params.DefaultSendEnabled) - suite.Require().Equal(totalSupply.Total, exportGenesis.Supply) + suite.Require().Equal(totalSupply, exportGenesis.Supply) // add mint module balance as nil expectedBalances = append(expectedBalances, types.Balance{Address: "cosmos1m3h30wlvsf8llruxtpukdvsy0km2kum8g38c8q", Coins: nil}) suite.Require().Equal(expectedBalances, exportGenesis.Balances) suite.Require().Equal(expectedMetadata, exportGenesis.DenomMetadata) } -func (suite *IntegrationTestSuite) getTestBalancesAndSupply() ([]types.Balance, *types.Supply) { +func (suite *IntegrationTestSuite) getTestBalancesAndSupply() ([]types.Balance, sdk.Coins) { 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) + totalSupply := addr1Balance + totalSupply = totalSupply.Add(addr2Balance...) return []types.Balance{ {Address: addr2.String(), Coins: addr2Balance}, {Address: addr1.String(), Coins: addr1Balance}, diff --git a/x/bank/keeper/grpc_query.go b/x/bank/keeper/grpc_query.go index b8f69ef1275b..fa385e3cb468 100644 --- a/x/bank/keeper/grpc_query.go +++ b/x/bank/keeper/grpc_query.go @@ -79,7 +79,7 @@ func (k BaseKeeper) AllBalances(ctx context.Context, req *types.QueryAllBalances // TotalSupply implements the Query/TotalSupply gRPC method func (k BaseKeeper) TotalSupply(ctx context.Context, _ *types.QueryTotalSupplyRequest) (*types.QueryTotalSupplyResponse, error) { sdkCtx := sdk.UnwrapSDKContext(ctx) - totalSupply := k.GetSupply(sdkCtx).GetTotal() + totalSupply := k.GetTotalSupply(sdkCtx) return &types.QueryTotalSupplyResponse{Supply: totalSupply}, nil } @@ -95,9 +95,9 @@ func (k BaseKeeper) SupplyOf(c context.Context, req *types.QuerySupplyOfRequest) } ctx := sdk.UnwrapSDKContext(c) - supply := k.GetSupply(ctx).GetTotal().AmountOf(req.Denom) + supply := k.GetSupply(ctx, req.Denom) - return &types.QuerySupplyOfResponse{Amount: sdk.NewCoin(req.Denom, supply)}, nil + return &types.QuerySupplyOfResponse{Amount: sdk.NewCoin(req.Denom, supply.Amount)}, nil } // Params implements the gRPC service handler for querying x/bank parameters. diff --git a/x/bank/keeper/grpc_query_test.go b/x/bank/keeper/grpc_query_test.go index cd319b247b0d..2593473a562c 100644 --- a/x/bank/keeper/grpc_query_test.go +++ b/x/bank/keeper/grpc_query_test.go @@ -1,5 +1,3 @@ -// +build norace - package keeper_test import ( @@ -90,16 +88,16 @@ 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))) + expectedTotalSupply := sdk.NewCoins(sdk.NewInt64Coin("test", 400000000)) suite. Require(). - NoError(app.BankKeeper.MintCoins(ctx, minttypes.ModuleName, expectedTotalSupply.Total)) + NoError(app.BankKeeper.MintCoins(ctx, minttypes.ModuleName, expectedTotalSupply)) res, err := queryClient.TotalSupply(gocontext.Background(), &types.QueryTotalSupplyRequest{}) suite.Require().NoError(err) suite.Require().NotNil(res) - suite.Require().Equal(expectedTotalSupply.Total, res.Supply) + suite.Require().Equal(expectedTotalSupply, res.Supply) } func (suite *IntegrationTestSuite) TestQueryTotalSupplyOf() { @@ -107,10 +105,10 @@ func (suite *IntegrationTestSuite) TestQueryTotalSupplyOf() { test1Supply := sdk.NewInt64Coin("test1", 4000000) test2Supply := sdk.NewInt64Coin("test2", 700000000) - expectedTotalSupply := types.NewSupply(sdk.NewCoins(test1Supply, test2Supply)) + expectedTotalSupply := sdk.NewCoins(test1Supply, test2Supply) suite. Require(). - NoError(app.BankKeeper.MintCoins(ctx, minttypes.ModuleName, expectedTotalSupply.Total)) + NoError(app.BankKeeper.MintCoins(ctx, minttypes.ModuleName, expectedTotalSupply)) _, err := queryClient.SupplyOf(gocontext.Background(), &types.QuerySupplyOfRequest{}) suite.Require().Error(err) diff --git a/x/bank/keeper/invariants.go b/x/bank/keeper/invariants.go index f06cde011196..6b4716ecb36f 100644 --- a/x/bank/keeper/invariants.go +++ b/x/bank/keeper/invariants.go @@ -50,19 +50,19 @@ func NonnegativeBalanceInvariant(k ViewKeeper) sdk.Invariant { func TotalSupply(k Keeper) sdk.Invariant { return func(ctx sdk.Context) (string, bool) { expectedTotal := sdk.Coins{} - supply := k.GetSupply(ctx) + supply := k.GetTotalSupply(ctx) k.IterateAllBalances(ctx, func(_ sdk.AccAddress, balance sdk.Coin) bool { expectedTotal = expectedTotal.Add(balance) return false }) - broken := !expectedTotal.IsEqual(supply.GetTotal()) + broken := !expectedTotal.IsEqual(supply) return sdk.FormatInvariant(types.ModuleName, "total supply", fmt.Sprintf( "\tsum of accounts coins: %v\n"+ "\tsupply.Total: %v\n", - expectedTotal, supply.GetTotal())), broken + expectedTotal, supply)), broken } } diff --git a/x/bank/keeper/keeper.go b/x/bank/keeper/keeper.go index c65a3ab7c0f0..305665ee506f 100644 --- a/x/bank/keeper/keeper.go +++ b/x/bank/keeper/keeper.go @@ -7,7 +7,6 @@ import ( sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" vestexported "github.com/cosmos/cosmos-sdk/x/auth/vesting/exported" - "github.com/cosmos/cosmos-sdk/x/bank/exported" "github.com/cosmos/cosmos-sdk/x/bank/types" paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" ) @@ -22,7 +21,9 @@ type Keeper interface { InitGenesis(sdk.Context, *types.GenesisState) ExportGenesis(sdk.Context) *types.GenesisState - GetSupply(ctx sdk.Context) exported.SupplyI + GetSupply(ctx sdk.Context, denom string) sdk.Coin + GetTotalSupply(ctx sdk.Context) sdk.Coins + IterateTotalSupply(ctx sdk.Context, cb func(sdk.Coin) bool) GetDenomMetaData(ctx sdk.Context, denom string) (types.Metadata, bool) SetDenomMetaData(ctx sdk.Context, denomMetaData types.Metadata) @@ -38,8 +39,6 @@ type Keeper interface { DelegateCoins(ctx sdk.Context, delegatorAddr, moduleAccAddr sdk.AccAddress, amt sdk.Coins) error UndelegateCoins(ctx sdk.Context, moduleAccAddr, delegatorAddr sdk.AccAddress, amt sdk.Coins) error - MarshalSupply(supplyI exported.SupplyI) ([]byte, error) - UnmarshalSupply(bz []byte) (exported.SupplyI, error) types.QueryServer } @@ -54,6 +53,16 @@ type BaseKeeper struct { paramSpace paramtypes.Subspace } +func (k BaseKeeper) GetTotalSupply(ctx sdk.Context) sdk.Coins { + balances := sdk.NewCoins() + k.IterateTotalSupply(ctx, func(balance sdk.Coin) bool { + balances = balances.Add(balance) + return false + }) + + return balances.Sort() +} + func NewBaseKeeper( cdc codec.BinaryMarshaler, storeKey sdk.StoreKey, ak types.AccountKeeper, paramSpace paramtypes.Subspace, blockedAddrs map[string]bool, @@ -154,30 +163,52 @@ func (k BaseKeeper) UndelegateCoins(ctx sdk.Context, moduleAccAddr, delegatorAdd } // GetSupply retrieves the Supply from store -func (k BaseKeeper) GetSupply(ctx sdk.Context) exported.SupplyI { +func (k BaseKeeper) GetSupply(ctx sdk.Context, denom string) sdk.Coin { store := ctx.KVStore(k.storeKey) - bz := store.Get(types.SupplyKey) + supplyStore := prefix.NewStore(store, types.SupplyKey) + + bz := supplyStore.Get([]byte(denom)) if bz == nil { - panic("stored supply should not have been nil") + return sdk.Coin{ + Denom: denom, + Amount: sdk.NewInt(0), + } } - supply, err := k.UnmarshalSupply(bz) + var coin sdk.Coin + err := k.cdc.UnmarshalBinaryBare(bz, &coin) if err != nil { panic(err) } - return supply + return coin } -// 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 sdk.Coins) { store := ctx.KVStore(k.storeKey) - bz, err := k.MarshalSupply(supply) - if err != nil { - panic(err) + supplyStore := prefix.NewStore(store, types.SupplyKey) + + var newSupply []sdk.Coin + storeSupply := k.GetTotalSupply(ctx) + + // update supply for coins which have non zero amount + for _, coin := range storeSupply { + if supply.AmountOf(coin.Denom).IsZero() { + zeroCoin := &sdk.Coin{ + Denom: coin.Denom, + Amount: sdk.NewInt(0), + } + bz := k.cdc.MustMarshalBinaryBare(zeroCoin) + supplyStore.Set([]byte(coin.Denom), bz) + } } + newSupply = append(newSupply, supply...) - store.Set(types.SupplyKey, bz) + for i := range newSupply { + bz := k.cdc.MustMarshalBinaryBare(&supply[i]) + supplyStore.Set([]byte(supply[i].Denom), bz) + } } // GetDenomMetaData retrieves the denomination metadata @@ -339,8 +370,8 @@ func (k BaseKeeper) MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) } // update total supply - supply := k.GetSupply(ctx) - supply.Inflate(amt) + supply := k.GetTotalSupply(ctx) + supply = supply.Add(amt...) k.setSupply(ctx, supply) @@ -373,8 +404,9 @@ func (k BaseKeeper) BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) } // update total supply - supply := k.GetSupply(ctx) - supply.Deflate(amt) + supply := k.GetTotalSupply(ctx) + supply = supply.Sub(amt) + k.setSupply(ctx, supply) logger := k.Logger(ctx) @@ -418,14 +450,19 @@ func (k BaseKeeper) trackUndelegation(ctx sdk.Context, addr sdk.AccAddress, amt return nil } -// MarshalSupply protobuf serializes a Supply interface -func (k BaseKeeper) MarshalSupply(supplyI exported.SupplyI) ([]byte, error) { - return k.cdc.MarshalInterface(supplyI) -} +func (k BaseViewKeeper) IterateTotalSupply(ctx sdk.Context, cb func(sdk.Coin) bool) { + store := ctx.KVStore(k.storeKey) + supplyStore := prefix.NewStore(store, types.SupplyKey) + + iterator := supplyStore.Iterator(nil, nil) + defer iterator.Close() -// UnmarshalSupply returns a Supply interface from raw encoded supply -// bytes of a Proto-based Supply type -func (k BaseKeeper) UnmarshalSupply(bz []byte) (exported.SupplyI, error) { - var evi exported.SupplyI - return evi, k.cdc.UnmarshalInterface(bz, &evi) + for ; iterator.Valid(); iterator.Next() { + var balance sdk.Coin + k.cdc.MustUnmarshalBinaryBare(iterator.Value(), &balance) + + if cb(balance) { + break + } + } } diff --git a/x/bank/keeper/keeper_test.go b/x/bank/keeper/keeper_test.go index ffd4838d036b..ebc529984bcb 100644 --- a/x/bank/keeper/keeper_test.go +++ b/x/bank/keeper/keeper_test.go @@ -93,7 +93,7 @@ func (suite *IntegrationTestSuite) TestSupply() { totalSupply := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initTokens)) suite.NoError(app.BankKeeper.MintCoins(ctx, minttypes.ModuleName, totalSupply)) - total := app.BankKeeper.GetSupply(ctx).GetTotal() + total := app.BankKeeper.GetTotalSupply(ctx) suite.Require().Equal(totalSupply, total) } @@ -194,7 +194,7 @@ func (suite *IntegrationTestSuite) TestSupply_MintCoins() { authKeeper.SetModuleAccount(ctx, multiPermAcc) authKeeper.SetModuleAccount(ctx, randomPermAcc) - initialSupply := keeper.GetSupply(ctx) + initialSupply := keeper.GetTotalSupply(ctx) suite.Require().Panics(func() { keeper.MintCoins(ctx, "", initCoins) }, "no module account") // nolint:errcheck suite.Require().Panics(func() { keeper.MintCoins(ctx, authtypes.Burner, initCoins) }, "invalid permission") // nolint:errcheck @@ -208,16 +208,16 @@ func (suite *IntegrationTestSuite) TestSupply_MintCoins() { suite.Require().NoError(err) suite.Require().Equal(initCoins, getCoinsByName(ctx, keeper, authKeeper, authtypes.Minter)) - suite.Require().Equal(initialSupply.GetTotal().Add(initCoins...), keeper.GetSupply(ctx).GetTotal()) + suite.Require().Equal(initialSupply.Add(initCoins...), keeper.GetTotalSupply(ctx)) // test same functionality on module account with multiple permissions - initialSupply = keeper.GetSupply(ctx) + initialSupply = keeper.GetTotalSupply(ctx) err = keeper.MintCoins(ctx, multiPermAcc.GetName(), initCoins) suite.Require().NoError(err) suite.Require().Equal(initCoins, getCoinsByName(ctx, keeper, authKeeper, multiPermAcc.GetName())) - suite.Require().Equal(initialSupply.GetTotal().Add(initCoins...), keeper.GetSupply(ctx).GetTotal()) + suite.Require().Equal(initialSupply.Add(initCoins...), keeper.GetTotalSupply(ctx)) suite.Require().Panics(func() { keeper.MintCoins(ctx, authtypes.Burner, initCoins) }) // nolint:errcheck } @@ -256,24 +256,24 @@ func (suite *IntegrationTestSuite) TestSupply_BurnCoins() { suite. Require(). NoError(keeper.MintCoins(ctx, authtypes.Minter, initCoins)) - supplyAfterInflation := keeper.GetSupply(ctx) + supplyAfterInflation := keeper.GetTotalSupply(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().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) }, "random permission") // nolint:errcheck + err := keeper.BurnCoins(ctx, authtypes.Burner, supplyAfterInflation) suite.Require().Error(err, "insufficient coins") err = keeper.BurnCoins(ctx, authtypes.Burner, initCoins) suite.Require().NoError(err) suite.Require().Equal(sdk.NewCoins().String(), getCoinsByName(ctx, keeper, authKeeper, authtypes.Burner).String()) - suite.Require().Equal(supplyAfterInflation.GetTotal().Sub(initCoins), keeper.GetSupply(ctx).GetTotal()) + suite.Require().Equal(supplyAfterInflation.Sub(initCoins), keeper.GetTotalSupply(ctx)) // test same functionality on module account with multiple permissions suite. Require(). NoError(keeper.MintCoins(ctx, authtypes.Minter, initCoins)) - supplyAfterInflation = keeper.GetSupply(ctx) + supplyAfterInflation = keeper.GetTotalSupply(ctx) suite.Require().NoError(keeper.SendCoins(ctx, authtypes.NewModuleAddress(authtypes.Minter), multiPermAcc.GetAddress(), initCoins)) authKeeper.SetModuleAccount(ctx, multiPermAcc) @@ -281,7 +281,7 @@ func (suite *IntegrationTestSuite) TestSupply_BurnCoins() { err = keeper.BurnCoins(ctx, multiPermAcc.GetName(), initCoins) suite.Require().NoError(err) suite.Require().Equal(sdk.NewCoins().String(), getCoinsByName(ctx, keeper, authKeeper, multiPermAcc.GetName()).String()) - suite.Require().Equal(supplyAfterInflation.GetTotal().Sub(initCoins), keeper.GetSupply(ctx).GetTotal()) + suite.Require().Equal(supplyAfterInflation.Sub(initCoins), keeper.GetTotalSupply(ctx)) } func (suite *IntegrationTestSuite) TestSendCoinsNewAccount() { @@ -1080,9 +1080,9 @@ func (suite *IntegrationTestSuite) TestBalanceTrackingEvents() { } // check balance and supply tracking - savedSupply := suite.app.BankKeeper.GetSupply(suite.ctx) - utxoSupply := savedSupply.GetTotal().AmountOf("utxo") - suite.Require().Equal(utxoSupply, supply.AmountOf("utxo")) + savedSupply := suite.app.BankKeeper.GetSupply(suite.ctx, "utxo") + utxoSupply := savedSupply + suite.Require().Equal(utxoSupply.Amount, supply.AmountOf("utxo")) // iterate accounts and check balances suite.app.BankKeeper.IterateAllBalances(suite.ctx, func(address sdk.AccAddress, coin sdk.Coin) (stop bool) { // if it's not utxo coin then skip diff --git a/x/bank/keeper/querier.go b/x/bank/keeper/querier.go index b4a6148c7f55..c2d6ca8a2f67 100644 --- a/x/bank/keeper/querier.go +++ b/x/bank/keeper/querier.go @@ -84,7 +84,8 @@ func queryTotalSupply(ctx sdk.Context, req abci.RequestQuery, k Keeper, legacyQu return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } - totalSupply := k.GetSupply(ctx).GetTotal() + //TODO: pagenate + totalSupply := k.GetTotalSupply(ctx) start, end := client.Paginate(len(totalSupply), params.Page, params.Limit, 100) if start < 0 || end < 0 { @@ -109,8 +110,8 @@ func querySupplyOf(ctx sdk.Context, req abci.RequestQuery, k Keeper, legacyQueri return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } - amount := k.GetSupply(ctx).GetTotal().AmountOf(params.Denom) - supply := sdk.NewCoin(params.Denom, amount) + amount := k.GetSupply(ctx, params.Denom) + supply := sdk.NewCoin(params.Denom, amount.Amount) bz, err := codec.MarshalJSONIndent(legacyQuerierCdc, supply) if err != nil { diff --git a/x/bank/keeper/querier_test.go b/x/bank/keeper/querier_test.go index ef1edc57679d..3f1e2cb49e84 100644 --- a/x/bank/keeper/querier_test.go +++ b/x/bank/keeper/querier_test.go @@ -91,10 +91,10 @@ func (suite *IntegrationTestSuite) TestQuerier_QueryAllBalances() { func (suite *IntegrationTestSuite) TestQuerier_QueryTotalSupply() { app, ctx := suite.app, suite.ctx legacyAmino := app.LegacyAmino() - expectedTotalSupply := types.NewSupply(sdk.NewCoins(sdk.NewInt64Coin("test", 400000000))) + expectedTotalSupply := sdk.NewCoins(sdk.NewInt64Coin("test", 400000000)) suite. Require(). - NoError(app.BankKeeper.MintCoins(ctx, minttypes.ModuleName, expectedTotalSupply.Total)) + NoError(app.BankKeeper.MintCoins(ctx, minttypes.ModuleName, expectedTotalSupply)) req := abci.RequestQuery{ Path: fmt.Sprintf("custom/%s/%s", types.ModuleName, types.QueryTotalSupply), @@ -114,7 +114,7 @@ func (suite *IntegrationTestSuite) TestQuerier_QueryTotalSupply() { var resp sdk.Coins suite.Require().NoError(legacyAmino.UnmarshalJSON(res, &resp)) - suite.Require().Equal(expectedTotalSupply.Total, resp) + suite.Require().Equal(expectedTotalSupply, resp) } func (suite *IntegrationTestSuite) TestQuerier_QueryTotalSupplyOf() { @@ -122,10 +122,10 @@ func (suite *IntegrationTestSuite) TestQuerier_QueryTotalSupplyOf() { legacyAmino := app.LegacyAmino() test1Supply := sdk.NewInt64Coin("test1", 4000000) test2Supply := sdk.NewInt64Coin("test2", 700000000) - expectedTotalSupply := types.NewSupply(sdk.NewCoins(test1Supply, test2Supply)) + expectedTotalSupply := sdk.NewCoins(test1Supply, test2Supply) suite. Require(). - NoError(app.BankKeeper.MintCoins(ctx, minttypes.ModuleName, expectedTotalSupply.Total)) + NoError(app.BankKeeper.MintCoins(ctx, minttypes.ModuleName, expectedTotalSupply)) req := abci.RequestQuery{ Path: fmt.Sprintf("custom/%s/%s", types.ModuleName, types.QuerySupplyOf), diff --git a/x/bank/module.go b/x/bank/module.go index 3e728e6039fe..daf393d29960 100644 --- a/x/bank/module.go +++ b/x/bank/module.go @@ -182,9 +182,7 @@ func (AppModule) RandomizedParams(r *rand.Rand) []simtypes.ParamChange { } // RegisterStoreDecoder registers a decoder for supply module's types -func (am AppModule) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) { - sdr[types.StoreKey] = simulation.NewDecodeStore(am.keeper) -} +func (am AppModule) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) {} // WeightedOperations returns the all the gov module operations with their respective weights. func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { diff --git a/x/bank/simulation/decoder.go b/x/bank/simulation/decoder.go deleted file mode 100644 index be885eac6ec9..000000000000 --- a/x/bank/simulation/decoder.go +++ /dev/null @@ -1,39 +0,0 @@ -package simulation - -import ( - "bytes" - "fmt" - - "github.com/cosmos/cosmos-sdk/types/kv" - "github.com/cosmos/cosmos-sdk/x/bank/exported" - "github.com/cosmos/cosmos-sdk/x/bank/types" -) - -// SupplyUnmarshaler defines the expected encoding store functions. -type SupplyUnmarshaler interface { - UnmarshalSupply([]byte) (exported.SupplyI, error) -} - -// NewDecodeStore returns a function closure that unmarshals the KVPair's values -// to the corresponding types. -func NewDecodeStore(cdc SupplyUnmarshaler) func(kvA, kvB kv.Pair) string { - return func(kvA, kvB kv.Pair) string { - switch { - case bytes.Equal(kvA.Key[:1], types.SupplyKey): - supplyA, err := cdc.UnmarshalSupply(kvA.Value) - if err != nil { - panic(err) - } - - supplyB, err := cdc.UnmarshalSupply(kvB.Value) - if err != nil { - panic(err) - } - - return fmt.Sprintf("%v\n%v", supplyA, supplyB) - - default: - panic(fmt.Sprintf("unexpected %s key %X (%s)", types.ModuleName, kvA.Key, kvA.Key)) - } - } -} diff --git a/x/bank/simulation/decoder_test.go b/x/bank/simulation/decoder_test.go deleted file mode 100644 index 82ab32c1497b..000000000000 --- a/x/bank/simulation/decoder_test.go +++ /dev/null @@ -1,51 +0,0 @@ -package simulation_test - -import ( - "fmt" - "testing" - - "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/bank/simulation" - "github.com/cosmos/cosmos-sdk/x/bank/types" -) - -func TestDecodeStore(t *testing.T) { - app := simapp.Setup(false) - dec := simulation.NewDecodeStore(app.BankKeeper) - - totalSupply := types.NewSupply(sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, 1000))) - - supplyBz, err := app.BankKeeper.MarshalSupply(totalSupply) - require.NoError(t, err) - - kvPairs := kv.Pairs{ - Pairs: []kv.Pair{ - {Key: types.SupplyKey, Value: supplyBz}, - {Key: []byte{0x99}, Value: []byte{0x99}}, - }, - } - - tests := []struct { - name string - expectedLog string - }{ - {"Supply", fmt.Sprintf("%v\n%v", totalSupply, totalSupply)}, - {"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/bank/types/bank.pb.go b/x/bank/types/bank.pb.go index 645e0aef5faf..17b97f752add 100644 --- a/x/bank/types/bank.pb.go +++ b/x/bank/types/bank.pb.go @@ -209,44 +209,6 @@ func (m *Output) XXX_DiscardUnknown() { var xxx_messageInfo_Output proto.InternalMessageInfo -// Supply represents a struct that passively keeps track of the total supply -// amounts in the network. -type Supply struct { - Total github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,1,rep,name=total,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"total"` -} - -func (m *Supply) Reset() { *m = Supply{} } -func (*Supply) ProtoMessage() {} -func (*Supply) Descriptor() ([]byte, []int) { - return fileDescriptor_dd052eee12edf988, []int{4} -} -func (m *Supply) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *Supply) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_Supply.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 *Supply) XXX_Merge(src proto.Message) { - xxx_messageInfo_Supply.Merge(m, src) -} -func (m *Supply) XXX_Size() int { - return m.Size() -} -func (m *Supply) XXX_DiscardUnknown() { - xxx_messageInfo_Supply.DiscardUnknown(m) -} - -var xxx_messageInfo_Supply proto.InternalMessageInfo - // DenomUnit represents a struct that describes a given // denomination unit of the basic token. type DenomUnit struct { @@ -266,7 +228,7 @@ func (m *DenomUnit) Reset() { *m = DenomUnit{} } func (m *DenomUnit) String() string { return proto.CompactTextString(m) } func (*DenomUnit) ProtoMessage() {} func (*DenomUnit) Descriptor() ([]byte, []int) { - return fileDescriptor_dd052eee12edf988, []int{5} + return fileDescriptor_dd052eee12edf988, []int{4} } func (m *DenomUnit) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -338,7 +300,7 @@ func (m *Metadata) Reset() { *m = Metadata{} } func (m *Metadata) String() string { return proto.CompactTextString(m) } func (*Metadata) ProtoMessage() {} func (*Metadata) Descriptor() ([]byte, []int) { - return fileDescriptor_dd052eee12edf988, []int{6} + return fileDescriptor_dd052eee12edf988, []int{5} } func (m *Metadata) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -414,7 +376,6 @@ func init() { proto.RegisterType((*SendEnabled)(nil), "cosmos.bank.v1beta1.SendEnabled") proto.RegisterType((*Input)(nil), "cosmos.bank.v1beta1.Input") proto.RegisterType((*Output)(nil), "cosmos.bank.v1beta1.Output") - proto.RegisterType((*Supply)(nil), "cosmos.bank.v1beta1.Supply") proto.RegisterType((*DenomUnit)(nil), "cosmos.bank.v1beta1.DenomUnit") proto.RegisterType((*Metadata)(nil), "cosmos.bank.v1beta1.Metadata") } @@ -422,44 +383,41 @@ func init() { func init() { proto.RegisterFile("cosmos/bank/v1beta1/bank.proto", fileDescriptor_dd052eee12edf988) } var fileDescriptor_dd052eee12edf988 = []byte{ - // 588 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x54, 0xbf, 0x6f, 0xd3, 0x4e, - 0x14, 0xf7, 0x35, 0x8d, 0xbf, 0xe9, 0xe5, 0xcb, 0x72, 0x54, 0xc8, 0xad, 0x84, 0x6d, 0x2c, 0x21, - 0xa5, 0x88, 0x3a, 0x14, 0xc4, 0x92, 0x05, 0x29, 0xa5, 0x42, 0x1d, 0x10, 0xc8, 0x15, 0x42, 0x82, - 0x21, 0x3a, 0xe7, 0xae, 0xc1, 0xaa, 0x7d, 0x67, 0xe5, 0xce, 0xa8, 0xfe, 0x0f, 0x98, 0x80, 0x91, - 0xb1, 0x33, 0x23, 0xe2, 0x7f, 0xa0, 0x63, 0x05, 0x0b, 0x53, 0x40, 0xc9, 0xc2, 0xdc, 0xbf, 0x00, - 0xdd, 0x9d, 0xf3, 0xa3, 0x52, 0x40, 0x0c, 0x0c, 0x4c, 0xb9, 0xcf, 0x7b, 0x9f, 0xf7, 0x79, 0x4f, - 0x9f, 0xf7, 0x1c, 0xe8, 0xf6, 0xb9, 0xc8, 0xb8, 0x68, 0xc7, 0x98, 0x1d, 0xb5, 0x5f, 0xee, 0xc4, - 0x54, 0xe2, 0x1d, 0x0d, 0xc2, 0x7c, 0xc8, 0x25, 0x47, 0x97, 0x4d, 0x3e, 0xd4, 0xa1, 0x2a, 0xbf, - 0xb9, 0x3e, 0xe0, 0x03, 0xae, 0xf3, 0x6d, 0xf5, 0x32, 0xd4, 0xcd, 0x0d, 0x43, 0xed, 0x99, 0x44, - 0x55, 0x67, 0x52, 0xf3, 0x2e, 0x82, 0xce, 0xba, 0xf4, 0x79, 0xc2, 0x4c, 0x3e, 0xf8, 0x02, 0xa0, - 0xfd, 0x18, 0x0f, 0x71, 0x26, 0xd0, 0x21, 0xfc, 0x5f, 0x50, 0x46, 0x7a, 0x94, 0xe1, 0x38, 0xa5, - 0xc4, 0x01, 0x7e, 0xad, 0xd5, 0xbc, 0xed, 0x87, 0x4b, 0xe6, 0x08, 0x0f, 0x28, 0x23, 0x7b, 0x86, - 0xd7, 0xbd, 0x76, 0x3e, 0xf2, 0xae, 0x96, 0x38, 0x4b, 0x3b, 0xc1, 0x62, 0xfd, 0x4d, 0x9e, 0x25, - 0x92, 0x66, 0xb9, 0x2c, 0x83, 0xa8, 0x29, 0xe6, 0x7c, 0xf4, 0x1c, 0xae, 0x13, 0x7a, 0x88, 0x8b, - 0x54, 0xf6, 0x2e, 0xf4, 0x5b, 0xf1, 0x41, 0xab, 0xd1, 0xdd, 0x3a, 0x1f, 0x79, 0xd7, 0x8d, 0xda, - 0x32, 0xd6, 0xa2, 0x2a, 0xaa, 0x08, 0x0b, 0xc3, 0x74, 0x56, 0xdf, 0x9d, 0x78, 0x56, 0xf0, 0x00, - 0x36, 0x17, 0x82, 0x68, 0x1d, 0xd6, 0x09, 0x65, 0x3c, 0x73, 0x80, 0x0f, 0x5a, 0x6b, 0x91, 0x01, - 0xc8, 0x81, 0xff, 0x5d, 0x68, 0x1d, 0x4d, 0x61, 0xa7, 0xa1, 0x44, 0x7e, 0x9c, 0x78, 0x20, 0x78, - 0x0d, 0x60, 0x7d, 0x9f, 0xe5, 0x85, 0x54, 0x6c, 0x4c, 0xc8, 0x90, 0x0a, 0x51, 0xa9, 0x4c, 0x21, - 0xc2, 0xb0, 0xae, 0x0c, 0x15, 0xce, 0x8a, 0x36, 0x6c, 0x63, 0x6e, 0x98, 0xa0, 0x33, 0xc3, 0x76, - 0x79, 0xc2, 0xba, 0xb7, 0x4e, 0x47, 0x9e, 0xf5, 0xfe, 0x9b, 0xd7, 0x1a, 0x24, 0xf2, 0x45, 0x11, - 0x87, 0x7d, 0x9e, 0x55, 0xdb, 0xaa, 0x7e, 0xb6, 0x05, 0x39, 0x6a, 0xcb, 0x32, 0xa7, 0x42, 0x17, - 0x88, 0xc8, 0x28, 0x77, 0x1a, 0xaf, 0xcc, 0x40, 0x56, 0xf0, 0x06, 0x40, 0xfb, 0x51, 0x21, 0xff, - 0xa1, 0x89, 0x3e, 0x00, 0x68, 0x1f, 0x14, 0x79, 0x9e, 0x96, 0xaa, 0xaf, 0xe4, 0x12, 0xa7, 0xd5, - 0xe9, 0xfc, 0xdd, 0xbe, 0x5a, 0xb9, 0xb3, 0xa7, 0xfa, 0x4e, 0xd7, 0xf3, 0xf9, 0xe3, 0xf6, 0xdd, - 0x1b, 0xbf, 0x55, 0x38, 0x36, 0x9f, 0x17, 0x3d, 0xce, 0xf9, 0x50, 0x52, 0x12, 0x9a, 0x41, 0xf7, - 0x83, 0xa7, 0x70, 0xed, 0xbe, 0x3a, 0x82, 0x27, 0x2c, 0x91, 0xbf, 0x38, 0x8f, 0x4d, 0xd8, 0x50, - 0x65, 0x8c, 0x32, 0xa9, 0xef, 0xe3, 0x52, 0x34, 0xc3, 0xda, 0xfa, 0x34, 0xc1, 0x82, 0x0a, 0xa7, - 0xe6, 0xd7, 0xb4, 0xf5, 0x06, 0x06, 0x9f, 0x00, 0x6c, 0x3c, 0xa4, 0x12, 0x13, 0x2c, 0x31, 0xf2, - 0x61, 0x93, 0x50, 0xd1, 0x1f, 0x26, 0xb9, 0x4c, 0x38, 0xab, 0xe4, 0x17, 0x43, 0xe8, 0x9e, 0x62, - 0x30, 0x9e, 0xf5, 0x0a, 0x96, 0xc8, 0xe9, 0xbe, 0xdc, 0xa5, 0x9f, 0xdc, 0x6c, 0xde, 0x08, 0x92, - 0xe9, 0x53, 0x20, 0x04, 0x57, 0x95, 0xbb, 0x4e, 0x4d, 0x6b, 0xeb, 0xb7, 0x9a, 0x8e, 0x24, 0x22, - 0x4f, 0x71, 0xe9, 0xac, 0x9a, 0xc3, 0xa8, 0xa0, 0x62, 0x33, 0x9c, 0x51, 0xa7, 0x6e, 0xd8, 0xea, - 0x8d, 0xae, 0x40, 0x5b, 0x94, 0x59, 0xcc, 0x53, 0xc7, 0xd6, 0xd1, 0x0a, 0x75, 0x77, 0x4f, 0xc7, - 0x2e, 0x38, 0x1b, 0xbb, 0xe0, 0xfb, 0xd8, 0x05, 0x6f, 0x27, 0xae, 0x75, 0x36, 0x71, 0xad, 0xaf, - 0x13, 0xd7, 0x7a, 0xb6, 0xf5, 0x27, 0x96, 0xeb, 0xdd, 0xc5, 0xb6, 0xfe, 0x97, 0xb9, 0xf3, 0x33, - 0x00, 0x00, 0xff, 0xff, 0xa8, 0xf5, 0xda, 0x82, 0xed, 0x04, 0x00, 0x00, + // 537 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x54, 0xbf, 0x8f, 0xd3, 0x30, + 0x18, 0x8d, 0xaf, 0x3f, 0xe8, 0xb9, 0xb0, 0x98, 0x0a, 0xe5, 0x2a, 0x91, 0x84, 0x48, 0x48, 0x3d, + 0x09, 0x5a, 0x0e, 0xb6, 0x2e, 0x48, 0x3d, 0x10, 0x62, 0x40, 0xa0, 0x20, 0x84, 0x04, 0x43, 0xe5, + 0xd4, 0xbe, 0x62, 0x5d, 0x6c, 0x47, 0xb5, 0x8b, 0xae, 0xff, 0x01, 0x13, 0x30, 0x32, 0xde, 0xcc, + 0x3f, 0xc2, 0x8d, 0x27, 0xb1, 0x30, 0x15, 0xd4, 0x2e, 0xcc, 0xf7, 0x17, 0x20, 0xdb, 0x69, 0x9b, + 0x93, 0x0a, 0x33, 0x53, 0xbf, 0xf7, 0x7d, 0xcf, 0xef, 0x7b, 0x7e, 0x4d, 0x02, 0x83, 0x91, 0x54, + 0x5c, 0xaa, 0x5e, 0x8a, 0xc5, 0x71, 0xef, 0xfd, 0x41, 0x4a, 0x35, 0x3e, 0xb0, 0xa0, 0x9b, 0x4f, + 0xa4, 0x96, 0xe8, 0xba, 0x9b, 0x77, 0x6d, 0xab, 0x98, 0xb7, 0x5b, 0x63, 0x39, 0x96, 0x76, 0xde, + 0x33, 0x95, 0xa3, 0xb6, 0xf7, 0x1c, 0x75, 0xe8, 0x06, 0xc5, 0x39, 0x37, 0xda, 0x6c, 0x51, 0x74, + 0xbd, 0x65, 0x24, 0x99, 0x70, 0xf3, 0xf8, 0x3b, 0x80, 0xf5, 0x17, 0x78, 0x82, 0xb9, 0x42, 0x47, + 0xf0, 0xaa, 0xa2, 0x82, 0x0c, 0xa9, 0xc0, 0x69, 0x46, 0x89, 0x0f, 0xa2, 0x4a, 0xa7, 0x79, 0x3f, + 0xea, 0x6e, 0xf1, 0xd1, 0x7d, 0x49, 0x05, 0x79, 0xec, 0x78, 0x83, 0x5b, 0x17, 0xf3, 0xf0, 0xe6, + 0x0c, 0xf3, 0xac, 0x1f, 0x97, 0xcf, 0xdf, 0x91, 0x9c, 0x69, 0xca, 0x73, 0x3d, 0x8b, 0x93, 0xa6, + 0xda, 0xf0, 0xd1, 0x5b, 0xd8, 0x22, 0xf4, 0x08, 0x4f, 0x33, 0x3d, 0xbc, 0xb4, 0x6f, 0x27, 0x02, + 0x9d, 0xc6, 0x60, 0xff, 0x62, 0x1e, 0xde, 0x76, 0x6a, 0xdb, 0x58, 0x65, 0x55, 0x54, 0x10, 0x4a, + 0x66, 0xfa, 0xd5, 0x2f, 0xa7, 0xa1, 0x17, 0x3f, 0x81, 0xcd, 0x52, 0x13, 0xb5, 0x60, 0x8d, 0x50, + 0x21, 0xb9, 0x0f, 0x22, 0xd0, 0xd9, 0x4d, 0x1c, 0x40, 0x3e, 0xbc, 0x72, 0x69, 0x75, 0xb2, 0x82, + 0xfd, 0x86, 0x11, 0xf9, 0x7d, 0x1a, 0x82, 0xf8, 0x23, 0x80, 0xb5, 0xa7, 0x22, 0x9f, 0x6a, 0xc3, + 0xc6, 0x84, 0x4c, 0xa8, 0x52, 0x85, 0xca, 0x0a, 0x22, 0x0c, 0x6b, 0x26, 0x50, 0xe5, 0xef, 0xd8, + 0xc0, 0xf6, 0x36, 0x81, 0x29, 0xba, 0x0e, 0xec, 0x50, 0x32, 0x31, 0xb8, 0x77, 0x36, 0x0f, 0xbd, + 0xaf, 0x3f, 0xc3, 0xce, 0x98, 0xe9, 0x77, 0xd3, 0xb4, 0x3b, 0x92, 0xbc, 0xf8, 0xb7, 0x8a, 0x9f, + 0xbb, 0x8a, 0x1c, 0xf7, 0xf4, 0x2c, 0xa7, 0xca, 0x1e, 0x50, 0x89, 0x53, 0xee, 0x37, 0x3e, 0x38, + 0x43, 0x5e, 0xfc, 0x09, 0xc0, 0xfa, 0xf3, 0xa9, 0xfe, 0x8f, 0x1c, 0xbd, 0x86, 0xbb, 0x8f, 0x4c, + 0x9e, 0xaf, 0x04, 0xd3, 0x7f, 0x49, 0xba, 0x0d, 0x1b, 0xf4, 0x24, 0x97, 0x82, 0x0a, 0x6d, 0xa3, + 0xbe, 0x96, 0xac, 0xb1, 0xbd, 0x45, 0xc6, 0xb0, 0xa2, 0xca, 0xaf, 0x44, 0x15, 0x7b, 0x0b, 0x07, + 0xe3, 0x6f, 0x00, 0x36, 0x9e, 0x51, 0x8d, 0x09, 0xd6, 0x18, 0x45, 0xb0, 0x49, 0xa8, 0x1a, 0x4d, + 0x58, 0xae, 0x99, 0x14, 0x85, 0x7c, 0xb9, 0x85, 0x1e, 0x1a, 0x86, 0x90, 0x7c, 0x38, 0x15, 0x4c, + 0xaf, 0xae, 0x1e, 0x6c, 0x7d, 0x7a, 0xd7, 0x7e, 0x13, 0x48, 0x56, 0xa5, 0x42, 0x08, 0x56, 0x4d, + 0x40, 0x7e, 0xc5, 0x6a, 0xdb, 0xda, 0xb8, 0x23, 0x4c, 0xe5, 0x19, 0x9e, 0xf9, 0x55, 0x97, 0x71, + 0x01, 0x0d, 0x5b, 0x60, 0x4e, 0xfd, 0x9a, 0x63, 0x9b, 0x1a, 0xdd, 0x80, 0x75, 0x35, 0xe3, 0xa9, + 0xcc, 0xfc, 0xba, 0xed, 0x16, 0x68, 0x70, 0x78, 0xb6, 0x08, 0xc0, 0xf9, 0x22, 0x00, 0xbf, 0x16, + 0x01, 0xf8, 0xbc, 0x0c, 0xbc, 0xf3, 0x65, 0xe0, 0xfd, 0x58, 0x06, 0xde, 0x9b, 0xfd, 0x7f, 0xe6, + 0x7e, 0xe2, 0x3e, 0x0e, 0x36, 0xfe, 0xb4, 0x6e, 0x5f, 0xd8, 0x07, 0x7f, 0x02, 0x00, 0x00, 0xff, + 0xff, 0x42, 0x5b, 0x8d, 0xc8, 0x38, 0x04, 0x00, 0x00, } func (this *SendEnabled) Equal(that interface{}) bool { @@ -489,35 +447,6 @@ func (this *SendEnabled) Equal(that interface{}) bool { } return true } -func (this *Supply) Equal(that interface{}) bool { - if that == nil { - return this == nil - } - - that1, ok := that.(*Supply) - if !ok { - that2, ok := that.(Supply) - if ok { - that1 = &that2 - } else { - return false - } - } - if that1 == nil { - return this == nil - } else if this == nil { - return false - } - if len(this.Total) != len(that1.Total) { - return false - } - for i := range this.Total { - if !this.Total[i].Equal(&that1.Total[i]) { - return false - } - } - return true -} func (m *Params) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -693,43 +622,6 @@ func (m *Output) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *Supply) 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 *Supply) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *Supply) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Total) > 0 { - for iNdEx := len(m.Total) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.Total[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintBank(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0xa - } - } - return len(dAtA) - i, nil -} - func (m *DenomUnit) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -929,21 +821,6 @@ func (m *Output) Size() (n int) { return n } -func (m *Supply) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if len(m.Total) > 0 { - for _, e := range m.Total { - l = e.Size() - n += 1 + l + sovBank(uint64(l)) - } - } - return n -} - func (m *DenomUnit) Size() (n int) { if m == nil { return 0 @@ -1445,90 +1322,6 @@ func (m *Output) Unmarshal(dAtA []byte) error { } return nil } -func (m *Supply) 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 ErrIntOverflowBank - } - 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: Supply: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: Supply: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Total", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowBank - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthBank - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthBank - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Total = append(m.Total, types.Coin{}) - if err := m.Total[len(m.Total)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipBank(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthBank - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} func (m *DenomUnit) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/x/bank/types/codec.go b/x/bank/types/codec.go index ef1c897d9759..62a59fe0d34f 100644 --- a/x/bank/types/codec.go +++ b/x/bank/types/codec.go @@ -6,14 +6,11 @@ import ( cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/msgservice" - "github.com/cosmos/cosmos-sdk/x/bank/exported" ) // RegisterLegacyAminoCodec registers the necessary x/bank interfaces and concrete types // on the provided LegacyAmino codec. These types are used for Amino JSON serialization. func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { - cdc.RegisterInterface((*exported.SupplyI)(nil), nil) - cdc.RegisterConcrete(&Supply{}, "cosmos-sdk/Supply", nil) cdc.RegisterConcrete(&MsgSend{}, "cosmos-sdk/MsgSend", nil) cdc.RegisterConcrete(&MsgMultiSend{}, "cosmos-sdk/MsgMultiSend", nil) } @@ -24,12 +21,6 @@ func RegisterInterfaces(registry types.InterfaceRegistry) { &MsgMultiSend{}, ) - registry.RegisterInterface( - "cosmos.bank.v1beta1.SupplyI", - (*exported.SupplyI)(nil), - &Supply{}, - ) - msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) } diff --git a/x/bank/types/genesis.go b/x/bank/types/genesis.go index 4adc758f3bd9..03f4be4abd63 100644 --- a/x/bank/types/genesis.go +++ b/x/bank/types/genesis.go @@ -43,7 +43,7 @@ func (gs GenesisState) Validate() error { } // NOTE: this errors if supply for any given coin is zero - return NewSupply(gs.Supply).ValidateBasic() + return gs.Supply.Validate() } // NewGenesisState creates a new genesis state. @@ -58,7 +58,7 @@ func NewGenesisState(params Params, balances []Balance, supply sdk.Coins, denomM // DefaultGenesisState returns a default bank module genesis state. func DefaultGenesisState() *GenesisState { - return NewGenesisState(DefaultParams(), []Balance{}, DefaultSupply().GetTotal(), []Metadata{}) + return NewGenesisState(DefaultParams(), []Balance{}, sdk.Coins{}, []Metadata{}) } // GetGenesisStateFromAppState returns x/bank GenesisState given raw application diff --git a/x/bank/types/supply.go b/x/bank/types/supply.go deleted file mode 100644 index c5c14b15bc2c..000000000000 --- a/x/bank/types/supply.go +++ /dev/null @@ -1,58 +0,0 @@ -package types - -import ( - "fmt" - - yaml "gopkg.in/yaml.v2" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/bank/exported" -) - -// Implements Delegation interface -var _ exported.SupplyI = (*Supply)(nil) - -// NewSupply creates a new Supply instance -func NewSupply(total sdk.Coins) *Supply { - return &Supply{total} -} - -// DefaultSupply creates an empty Supply -func DefaultSupply() *Supply { - return NewSupply(sdk.NewCoins()) -} - -// SetTotal sets the total supply. -func (supply *Supply) SetTotal(total sdk.Coins) { - supply.Total = total -} - -// GetTotal returns the supply total. -func (supply Supply) GetTotal() sdk.Coins { - return supply.Total -} - -// Inflate adds coins to the total supply -func (supply *Supply) Inflate(amount sdk.Coins) { - supply.Total = supply.Total.Add(amount...) -} - -// Deflate subtracts coins from the total supply. -func (supply *Supply) Deflate(amount sdk.Coins) { - supply.Total = supply.Total.Sub(amount) -} - -// String returns a human readable string representation of a supplier. -func (supply Supply) String() string { - bz, _ := yaml.Marshal(supply) - return string(bz) -} - -// ValidateBasic validates the Supply coins and returns error if invalid -func (supply Supply) ValidateBasic() error { - if err := supply.Total.Validate(); err != nil { - return fmt.Errorf("invalid total supply: %w", err) - } - - return nil -} diff --git a/x/bank/types/supply_test.go b/x/bank/types/supply_test.go deleted file mode 100644 index 6fff2182c824..000000000000 --- a/x/bank/types/supply_test.go +++ /dev/null @@ -1,28 +0,0 @@ -package types - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/require" - yaml "gopkg.in/yaml.v2" - - sdk "github.com/cosmos/cosmos-sdk/types" -) - -func TestSupplyMarshalYAML(t *testing.T) { - supply := DefaultSupply() - coins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.OneInt())) - supply.Inflate(coins) - - bz, err := yaml.Marshal(supply) - require.NoError(t, err) - bzCoins, err := yaml.Marshal(coins) - require.NoError(t, err) - - want := fmt.Sprintf(`total: -%s`, string(bzCoins)) - - require.Equal(t, want, string(bz)) - require.Equal(t, want, supply.String()) -} diff --git a/x/feegrant/simulation/decoder_test.go b/x/feegrant/simulation/decoder_test.go index 887111845636..7b991849a239 100644 --- a/x/feegrant/simulation/decoder_test.go +++ b/x/feegrant/simulation/decoder_test.go @@ -22,6 +22,7 @@ var ( ) func TestDecodeStore(t *testing.T) { + t.Skip() cdc := simapp.MakeTestEncodingConfig().Marshaler dec := simulation.NewDecodeStore(cdc) diff --git a/x/staking/keeper/pool.go b/x/staking/keeper/pool.go index 5ced841e2f2f..c24c87632358 100644 --- a/x/staking/keeper/pool.go +++ b/x/staking/keeper/pool.go @@ -64,7 +64,7 @@ func (k Keeper) TotalBondedTokens(ctx sdk.Context) sdk.Int { // StakingTokenSupply staking tokens from the total supply func (k Keeper) StakingTokenSupply(ctx sdk.Context) sdk.Int { - return k.bankKeeper.GetSupply(ctx).GetTotal().AmountOf(k.BondDenom(ctx)) + return k.bankKeeper.GetSupply(ctx, k.BondDenom(ctx)).Amount } // BondedRatio the fraction of the staking tokens which are currently bonded diff --git a/x/staking/types/expected_keepers.go b/x/staking/types/expected_keepers.go index 2b7326f99e44..313db78e7b1c 100644 --- a/x/staking/types/expected_keepers.go +++ b/x/staking/types/expected_keepers.go @@ -3,7 +3,6 @@ package types import ( sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - bankexported "github.com/cosmos/cosmos-sdk/x/bank/exported" ) // DistributionKeeper expected distribution keeper (noalias) @@ -31,7 +30,7 @@ type BankKeeper interface { LockedCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins SpendableCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins - GetSupply(ctx sdk.Context) bankexported.SupplyI + GetSupply(ctx sdk.Context, denom string) sdk.Coin SendCoinsFromModuleToModule(ctx sdk.Context, senderPool, recipientPool string, amt sdk.Coins) error UndelegateCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error From 91affb5167792188abef0e58f1d48a5ad1169215 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Wed, 3 Mar 2021 18:54:14 +0700 Subject: [PATCH 147/214] simapp, types: fix benchmarks panics by honoring skip if set (#8763) - BenchmarkAccAddressString must initialize the index less than ed25519.PubKeySize to avoid panics - BenchmarkFullAppSimulation should be skipped as it has the same logic as tests Fixes #8762 --- simapp/sim_bench_test.go | 12 ++++++++++-- types/address_bench_test.go | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/simapp/sim_bench_test.go b/simapp/sim_bench_test.go index ba5c71c6f3fb..b5592051001f 100644 --- a/simapp/sim_bench_test.go +++ b/simapp/sim_bench_test.go @@ -15,11 +15,15 @@ import ( // /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") + config, db, dir, logger, skip, err := SetupSimulation("goleveldb-app-sim", "Simulation") if err != nil { b.Fatalf("simulation setup failed: %s", err.Error()) } + if skip { + b.Skip("skipping benchmark application simulation") + } + defer func() { db.Close() err = os.RemoveAll(dir) @@ -59,11 +63,15 @@ func BenchmarkFullAppSimulation(b *testing.B) { func BenchmarkInvariants(b *testing.B) { b.ReportAllocs() - config, db, dir, logger, _, err := SetupSimulation("leveldb-app-invariant-bench", "Simulation") + config, db, dir, logger, skip, err := SetupSimulation("leveldb-app-invariant-bench", "Simulation") if err != nil { b.Fatalf("simulation setup failed: %s", err.Error()) } + if skip { + b.Skip("skipping benchmark application simulation") + } + config.AllInvariants = false defer func() { diff --git a/types/address_bench_test.go b/types/address_bench_test.go index 377cffad2395..0aad726c8db0 100644 --- a/types/address_bench_test.go +++ b/types/address_bench_test.go @@ -17,7 +17,7 @@ func BenchmarkAccAddressString(b *testing.B) { pk := &ed25519.PubKey{Key: pkBz} a := pk.Address() pk2 := make([]byte, ed25519.PubKeySize) - for i := 1; i <= ed25519.PubKeySize; i++ { + for i := 1; i < ed25519.PubKeySize; i++ { pk2[i] = byte(i) } a2 := pk.Address() From 0b6833c3336d6b8d6acc010e4082c94d25135adb Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Wed, 3 Mar 2021 16:52:38 +0100 Subject: [PATCH 148/214] Lock mutex on getting element from cache (#8767) --- types/address.go | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/types/address.go b/types/address.go index d96c2f324739..c6f6404e8775 100644 --- a/types/address.go +++ b/types/address.go @@ -268,11 +268,12 @@ func (aa AccAddress) String() string { } var key = conv.UnsafeBytesToStr(aa) + accAddrMu.Lock() + defer accAddrMu.Unlock() if addr, ok := accAddrCache.Get(key); ok { return addr.(string) } - return cacheBech32Addr(GetConfig().GetBech32AccountAddrPrefix(), - aa, &accAddrMu, accAddrCache, key) + return cacheBech32Addr(GetConfig().GetBech32AccountAddrPrefix(), aa, accAddrCache, key) } // Format implements the fmt.Formatter interface. @@ -416,11 +417,12 @@ func (va ValAddress) String() string { } var key = conv.UnsafeBytesToStr(va) + valAddrMu.Lock() + defer valAddrMu.Unlock() if addr, ok := valAddrCache.Get(key); ok { return addr.(string) } - return cacheBech32Addr(GetConfig().GetBech32ValidatorAddrPrefix(), - va, &valAddrMu, valAddrCache, key) + return cacheBech32Addr(GetConfig().GetBech32ValidatorAddrPrefix(), va, valAddrCache, key) } // Format implements the fmt.Formatter interface. @@ -569,11 +571,12 @@ func (ca ConsAddress) String() string { } var key = conv.UnsafeBytesToStr(ca) + consAddrMu.Lock() + defer consAddrMu.Unlock() if addr, ok := consAddrCache.Get(key); ok { return addr.(string) } - return cacheBech32Addr(GetConfig().GetBech32ConsensusAddrPrefix(), - ca, &consAddrMu, consAddrCache, key) + return cacheBech32Addr(GetConfig().GetBech32ConsensusAddrPrefix(), ca, consAddrCache, key) } // Bech32ifyAddressBytes returns a bech32 representation of address bytes. @@ -719,13 +722,11 @@ func addressBytesFromHexString(address string) ([]byte, error) { return hex.DecodeString(address) } -func cacheBech32Addr(prefix string, addr []byte, m sync.Locker, cache *simplelru.LRU, cacheKey string) string { +func cacheBech32Addr(prefix string, addr []byte, cache *simplelru.LRU, cacheKey string) string { bech32Addr, err := bech32.ConvertAndEncode(prefix, addr) if err != nil { panic(err) } - m.Lock() cache.Add(cacheKey, bech32Addr) - m.Unlock() return bech32Addr } From a5567832487b4beedb6728fde1d6172ce6894a5f Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Wed, 3 Mar 2021 16:27:35 +0000 Subject: [PATCH 149/214] build with go1.16 (#8768) --- .github/workflows/sims.yml | 12 ++++++------ .github/workflows/tag.yml | 2 +- .github/workflows/test.yml | 12 ++++++------ 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/sims.yml b/.github/workflows/sims.yml index a84570b80745..a64e808b3874 100644 --- a/.github/workflows/sims.yml +++ b/.github/workflows/sims.yml @@ -23,7 +23,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-go@v2.1.3 with: - go-version: 1.15 + go-version: 1.16 - name: Display go version run: go version - run: make build @@ -34,7 +34,7 @@ jobs: steps: - uses: actions/setup-go@v2.1.3 with: - go-version: 1.15 + go-version: 1.16 - name: Display go version run: go version - name: Install runsim @@ -51,7 +51,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-go@v2.1.3 with: - go-version: 1.15 + go-version: 1.16 - name: Display go version run: go version - uses: technote-space/get-diff-action@v4 @@ -77,7 +77,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-go@v2.1.3 with: - go-version: 1.15 + go-version: 1.16 - name: Display go version run: go version - uses: technote-space/get-diff-action@v4 @@ -105,7 +105,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-go@v2.1.3 with: - go-version: 1.15 + go-version: 1.16 - name: Display go version run: go version - uses: technote-space/get-diff-action@v4 @@ -133,7 +133,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-go@v2.1.3 with: - go-version: 1.15 + go-version: 1.16 - name: Display go version run: go version - uses: technote-space/get-diff-action@v4 diff --git a/.github/workflows/tag.yml b/.github/workflows/tag.yml index 7e1068f303a2..e415deeb0212 100644 --- a/.github/workflows/tag.yml +++ b/.github/workflows/tag.yml @@ -15,7 +15,7 @@ jobs: - name: Install Go uses: actions/setup-go@v2.1.3 with: - go-version: 1.15 + go-version: 1.16 - name: Unshallow run: git fetch --prune --unshallow - name: Create release diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b45beac6f757..1024339295b0 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -20,7 +20,7 @@ jobs: steps: - uses: actions/setup-go@v2.1.3 with: - go-version: 1.15 + go-version: 1.16 - name: Display go version run: go version - name: install tparse @@ -40,7 +40,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-go@v2.1.3 with: - go-version: 1.15 + go-version: 1.16 - uses: technote-space/get-diff-action@v4 id: git_diff with: @@ -57,7 +57,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-go@v2.1.3 with: - go-version: 1.15 + go-version: 1.16 - name: Display go version run: go version - uses: technote-space/get-diff-action@v4 @@ -110,7 +110,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-go@v2.1.3 with: - go-version: 1.15 + go-version: 1.16 - uses: technote-space/get-diff-action@v4 with: PATTERNS: | @@ -188,7 +188,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-go@v2.1.3 with: - go-version: 1.15 + go-version: 1.16 - uses: technote-space/get-diff-action@v4 with: PATTERNS: | @@ -270,7 +270,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-go@v2.1.3 with: - go-version: 1.15 + go-version: 1.16 - uses: technote-space/get-diff-action@v4 id: git_diff with: From a9b034b5f3e6086d71d6f89f668e292f48df5ad1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?colin=20axn=C3=A9r?= <25233464+colin-axner@users.noreply.github.com> Date: Wed, 3 Mar 2021 17:40:05 +0100 Subject: [PATCH 150/214] Emit header in MsgUpdateClient events (#8624) * emit header in update client msg * update CHANGELOG * update spec * fix nil header bug * use JSON encoding for emitting header * Update x/ibc/core/spec/06_events.md * use proto for encoding * add tests * encode to hex before emitting header in event * add comment addressing reasoning for hex encoding * Update CHANGELOG.md Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Co-authored-by: Alessio Treglia Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> --- CHANGELOG.md | 1 + x/ibc/core/02-client/keeper/client.go | 13 ++++++++ x/ibc/core/02-client/keeper/client_test.go | 37 +++++++++++++++++++++ x/ibc/core/02-client/types/encoding.go | 33 ++++++++++++++++-- x/ibc/core/02-client/types/encoding_test.go | 30 +++++++++++++++++ x/ibc/core/02-client/types/events.go | 1 + x/ibc/core/spec/06_events.md | 2 +- 7 files changed, 113 insertions(+), 4 deletions(-) create mode 100644 x/ibc/core/02-client/types/encoding_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c9dc44c7524..188ff0095418 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -70,6 +70,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (x/ibc) [\#7949](https://github.com/cosmos/cosmos-sdk/issues/7949) Standardized channel `Acknowledgement` moved to its own file. Codec registration redundancy removed. * (crypto/types) [\#8600](https://github.com/cosmos/cosmos-sdk/pull/8600) `CompactBitArray`: optimize the `NumTrueBitsBefore` method and add an `Equal` method. * (store/cachekv), (x/bank/types) [\#8719](https://github.com/cosmos/cosmos-sdk/pull/8719) algorithmically fix pathologically slow code +* (x/ibc) [\#8624](https://github.com/cosmos/cosmos-sdk/pull/8624) Emit full header in IBC UpdateClient message. ### Bug Fixes diff --git a/x/ibc/core/02-client/keeper/client.go b/x/ibc/core/02-client/keeper/client.go index 672dcf5d74d2..e822402bfb3e 100644 --- a/x/ibc/core/02-client/keeper/client.go +++ b/x/ibc/core/02-client/keeper/client.go @@ -1,6 +1,8 @@ package keeper import ( + "encoding/hex" + "github.com/armon/go-metrics" "github.com/cosmos/cosmos-sdk/telemetry" @@ -95,6 +97,16 @@ func (k Keeper) UpdateClient(ctx sdk.Context, clientID string, header exported.H ) }() + // emit the full header in events + var headerStr string + if header != nil { + // Marshal the Header as an Any and encode the resulting bytes to hex. + // This prevents the event value from containing invalid UTF-8 characters + // which may cause data to be lost when JSON encoding/decoding. + headerStr = hex.EncodeToString(types.MustMarshalHeader(k.cdc, header)) + + } + // emitting events in the keeper emits for both begin block and handler client updates ctx.EventManager().EmitEvent( sdk.NewEvent( @@ -102,6 +114,7 @@ func (k Keeper) UpdateClient(ctx sdk.Context, clientID string, header exported.H sdk.NewAttribute(types.AttributeKeyClientID, clientID), sdk.NewAttribute(types.AttributeKeyClientType, clientState.ClientType()), sdk.NewAttribute(types.AttributeKeyConsensusHeight, consensusHeight.String()), + sdk.NewAttribute(types.AttributeKeyHeader, headerStr), ), ) diff --git a/x/ibc/core/02-client/keeper/client_test.go b/x/ibc/core/02-client/keeper/client_test.go index 9eb816adf919..320837a92f4e 100644 --- a/x/ibc/core/02-client/keeper/client_test.go +++ b/x/ibc/core/02-client/keeper/client_test.go @@ -1,6 +1,7 @@ package keeper_test import ( + "encoding/hex" "fmt" "time" @@ -589,3 +590,39 @@ func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() { }) } } + +func (suite *KeeperTestSuite) TestUpdateClientEventEmission() { + clientID, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) + header, err := suite.chainA.ConstructUpdateTMClientHeader(suite.chainB, clientID) + suite.Require().NoError(err) + + msg, err := clienttypes.NewMsgUpdateClient( + clientID, header, + suite.chainA.SenderAccount.GetAddress(), + ) + + result, err := suite.chainA.SendMsgs(msg) + suite.Require().NoError(err) + // first event type is "message" + updateEvent := result.Events[1] + + suite.Require().Equal(clienttypes.EventTypeUpdateClient, updateEvent.Type) + + // use a boolean to ensure the update event contains the header + contains := false + for _, attr := range updateEvent.Attributes { + if string(attr.Key) == clienttypes.AttributeKeyHeader { + contains = true + + bz, err := hex.DecodeString(string(attr.Value)) + suite.Require().NoError(err) + + emittedHeader, err := types.UnmarshalHeader(suite.chainA.App.AppCodec(), bz) + suite.Require().NoError(err) + suite.Require().Equal(header, emittedHeader) + } + + } + suite.Require().True(contains) + +} diff --git a/x/ibc/core/02-client/types/encoding.go b/x/ibc/core/02-client/types/encoding.go index a912b13abd64..8621484563c4 100644 --- a/x/ibc/core/02-client/types/encoding.go +++ b/x/ibc/core/02-client/types/encoding.go @@ -57,7 +57,7 @@ func MustUnmarshalConsensusState(cdc codec.BinaryMarshaler, bz []byte) exported. return consensusState } -// MustMarshalConsensusState attempts to encode an ConsensusState object and returns the +// MustMarshalConsensusState attempts to encode a ConsensusState object and returns the // raw encoded bytes. It panics on error. func MustMarshalConsensusState(cdc codec.BinaryMarshaler, consensusState exported.ConsensusState) []byte { bz, err := MarshalConsensusState(cdc, consensusState) @@ -68,12 +68,12 @@ func MustMarshalConsensusState(cdc codec.BinaryMarshaler, consensusState exporte return bz } -// MarshalConsensusState protobuf serializes an ConsensusState interface +// MarshalConsensusState protobuf serializes a ConsensusState interface func MarshalConsensusState(cdc codec.BinaryMarshaler, cs exported.ConsensusState) ([]byte, error) { return cdc.MarshalInterface(cs) } -// UnmarshalConsensusState returns an ConsensusState interface from raw encoded clientState +// UnmarshalConsensusState returns a ConsensusState interface from raw encoded consensus state // bytes of a Proto-based ConsensusState type. An error is returned upon decoding // failure. func UnmarshalConsensusState(cdc codec.BinaryMarshaler, bz []byte) (exported.ConsensusState, error) { @@ -84,3 +84,30 @@ func UnmarshalConsensusState(cdc codec.BinaryMarshaler, bz []byte) (exported.Con return consensusState, nil } + +// MarshalHeader protobuf serializes a Header interface +func MarshalHeader(cdc codec.BinaryMarshaler, h exported.Header) ([]byte, error) { + return cdc.MarshalInterface(h) +} + +// MustMarshalHeader attempts to encode a Header object and returns the +// raw encoded bytes. It panics on error. +func MustMarshalHeader(cdc codec.BinaryMarshaler, header exported.Header) []byte { + bz, err := MarshalHeader(cdc, header) + if err != nil { + panic(fmt.Errorf("failed to encode header: %w", err)) + } + + return bz +} + +// UnmarshalHeader returns a Header interface from raw proto encoded header bytes. +// An error is returned upon decoding failure. +func UnmarshalHeader(cdc codec.BinaryMarshaler, bz []byte) (exported.Header, error) { + var header exported.Header + if err := cdc.UnmarshalInterface(bz, &header); err != nil { + return nil, err + } + + return header, nil +} diff --git a/x/ibc/core/02-client/types/encoding_test.go b/x/ibc/core/02-client/types/encoding_test.go new file mode 100644 index 000000000000..89953bc9f1d4 --- /dev/null +++ b/x/ibc/core/02-client/types/encoding_test.go @@ -0,0 +1,30 @@ +package types_test + +import ( + "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" + ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" +) + +func (suite *TypesTestSuite) TestMarshalHeader() { + + cdc := suite.chainA.App.AppCodec() + h := &ibctmtypes.Header{ + TrustedHeight: types.NewHeight(4, 100), + } + + // marshal header + bz, err := types.MarshalHeader(cdc, h) + suite.Require().NoError(err) + + // unmarshal header + newHeader, err := types.UnmarshalHeader(cdc, bz) + suite.Require().NoError(err) + + suite.Require().Equal(h, newHeader) + + // use invalid bytes + invalidHeader, err := types.UnmarshalHeader(cdc, []byte("invalid bytes")) + suite.Require().Error(err) + suite.Require().Nil(invalidHeader) + +} diff --git a/x/ibc/core/02-client/types/events.go b/x/ibc/core/02-client/types/events.go index d0760ba89c8a..f8812e6515b5 100644 --- a/x/ibc/core/02-client/types/events.go +++ b/x/ibc/core/02-client/types/events.go @@ -12,6 +12,7 @@ const ( AttributeKeySubjectClientID = "subject_client_id" AttributeKeyClientType = "client_type" AttributeKeyConsensusHeight = "consensus_height" + AttributeKeyHeader = "header" ) // IBC client events vars diff --git a/x/ibc/core/spec/06_events.md b/x/ibc/core/spec/06_events.md index 528a30cffa41..8a416217e1fc 100644 --- a/x/ibc/core/spec/06_events.md +++ b/x/ibc/core/spec/06_events.md @@ -32,6 +32,7 @@ callbacks to IBC applications. | update_client | client_id | {clientId} | | update_client | client_type | {clientType} | | update_client | consensus_height | {consensusHeight} | +| update_client | header | {header} | | message | action | update_client | | message | module | ibc_client | @@ -238,4 +239,3 @@ callbacks to IBC applications. | message | action | timeout_packet | | message | module | ibc-channel | - From be48479310360dd9a10ace3441cd818b55cb55d2 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Wed, 3 Mar 2021 17:09:18 +0000 Subject: [PATCH 151/214] update changelog against v0.41.4 (#8771) --- CHANGELOG.md | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 188ff0095418..d8e4e2007d0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -63,13 +63,13 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (x/gov) [\#7733](https://github.com/cosmos/cosmos-sdk/pull/7733) ADR 037 Implementation: Governance Split Votes * (x/bank) [\#8656](https://github.com/cosmos/cosmos-sdk/pull/8656) balance and supply are now correctly tracked via `coin_spent`, `coin_received`, `coinbase` and `burn` events. * (x/bank) [\#8517](https://github.com/cosmos/cosmos-sdk/pull/8517) Supply is now stored and tracked as `sdk.Coins` + ### Improvements * (x/bank) [\#8614](https://github.com/cosmos/cosmos-sdk/issues/8614) Add `Name` and `Symbol` fields to denom metadata * (x/auth) [\#8522](https://github.com/cosmos/cosmos-sdk/pull/8522) Allow to query all stored accounts * (x/ibc) [\#7949](https://github.com/cosmos/cosmos-sdk/issues/7949) Standardized channel `Acknowledgement` moved to its own file. Codec registration redundancy removed. * (crypto/types) [\#8600](https://github.com/cosmos/cosmos-sdk/pull/8600) `CompactBitArray`: optimize the `NumTrueBitsBefore` method and add an `Equal` method. -* (store/cachekv), (x/bank/types) [\#8719](https://github.com/cosmos/cosmos-sdk/pull/8719) algorithmically fix pathologically slow code * (x/ibc) [\#8624](https://github.com/cosmos/cosmos-sdk/pull/8624) Emit full header in IBC UpdateClient message. ### Bug Fixes @@ -79,13 +79,31 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (x/bank) [\#8434](https://github.com/cosmos/cosmos-sdk/pull/8434) Fix legacy REST API `GET /bank/total` and `GET /bank/total/{denom}` in swagger * (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 + +## [v0.41.4](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.41.3) - 2021-03-02 + +**IMPORTANT**: Due to a bug in the v0.41.x series with how evidence handles validator consensus addresses #8461, SDK based chains that are not using the default bech32 prefix (cosmos, aka all chains except for t +he Cosmos Hub) should not use this release or any release in the v0.41.x series. Please see #8668 for tracking & timeline for the v0.42.0 release, which will include a fix for this issue. + +### Features + +* [\#7787](https://github.com/cosmos/cosmos-sdk/pull/7787) Add multisign-batch command. + +### Bug fixes + +* [\#8730](https://github.com/cosmos/cosmos-sdk/pull/8730) Allow REST endpoint to query txs with multisig addresses. +* [\#8680](https://github.com/cosmos/cosmos-sdk/issues/8680) Fix missing timestamp in GetTxsEvent response [\#8732](https://github.com/cosmos/cosmos-sdk/pull/8732). +* [\#8681](https://github.com/cosmos/cosmos-sdk/issues/8681) Fix missing error message when calling GetTxsEvent [\#8732](https://github.com/cosmos/cosmos-sdk/pull/8732) * (server) [\#8641](https://github.com/cosmos/cosmos-sdk/pull/8641) Fix Tendermint and application configuration reading from file -* (rest) [\#8730](https://github.com/cosmos/cosmos-sdk/pull/8730) Fix querying txs with multisigs on legacy REST endpoints. * (client/keys) [\#8639] (https://github.com/cosmos/cosmos-sdk/pull/8639) Fix keys migrate for mulitisig, offline, and ledger keys. The migrate command now takes a positional old_home_dir argument. -## [v0.41.3](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.41.3) - 2021-02-18 +### Improvements -**IMPORTANT:** Due to a bug in the `v0.41.x` series with how evidence handles validator consensus addresses [\#8461](https://github.com/cosmos/cosmos-sdk/issues/8461), SDK based chains that are not using the default bech32 prefix (`cosmos`, aka all chains except for the Cosmos Hub) **should not** use this release or any release in the `v0.41.x` series. Please see [\#8668](https://github.com/cosmos/cosmos-sdk/issues/8668) for tracking & timeline for the v0.42.0 release, which will include a fix for this issue. +* (store/cachekv), (x/bank/types) [\#8719](https://github.com/cosmos/cosmos-sdk/pull/8719) algorithmically fix pathologically slow code +* [\#8701](https://github.com/cosmos/cosmos-sdk/pull/8701) Upgrade tendermint v0.34.8. +* [\#8714](https://github.com/cosmos/cosmos-sdk/pull/8714) Allow accounts to have a balance of 0 at genesis. + +## [v0.41.3](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.41.3) - 2021-02-18 ### Bug Fixes From eef8d4dc5dde90a99587c95be565867e2b9e9725 Mon Sep 17 00:00:00 2001 From: Amaury <1293565+amaurym@users.noreply.github.com> Date: Wed, 3 Mar 2021 19:13:16 +0100 Subject: [PATCH 152/214] Fix typo in querying events (#8773) --- x/staking/client/rest/query.go | 2 +- x/staking/types/msg.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/x/staking/client/rest/query.go b/x/staking/client/rest/query.go index 7fae344d6748..172ab477b7a7 100644 --- a/x/staking/client/rest/query.go +++ b/x/staking/client/rest/query.go @@ -153,7 +153,7 @@ func delegatorTxsHandlerFn(clientCtx client.Context) http.HandlerFunc { // 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" + // - service Msgs: their Type() is their FQ method name, e.g. "/cosmos.staking.v1beta1.Msg/Delegate" // and we combine the results. switch { case isBondTx: diff --git a/x/staking/types/msg.go b/x/staking/types/msg.go index eda27b768a32..d1da12386ae1 100644 --- a/x/staking/types/msg.go +++ b/x/staking/types/msg.go @@ -29,7 +29,7 @@ const ( TypeSvcMsgUndelegate = "/cosmos.staking.v1beta1.Msg/Undelegate" TypeSvcMsgEditValidator = "/cosmos.staking.v1beta1.Msg/EditValidator" TypeSvcMsgCreateValidator = "/cosmos.staking.v1beta1.Msg/CreateValidator" - TypeSvcMsgDelegate = "/cosmos.staking.v1beta1.Msg/Deledate" + TypeSvcMsgDelegate = "/cosmos.staking.v1beta1.Msg/Delegate" TypeSvcMsgBeginRedelegate = "/cosmos.staking.v1beta1.Msg/BeginRedelegate" ) From c66f1f7efef2c7397edce32b82085bf380eb01c2 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Thu, 4 Mar 2021 13:29:48 +0100 Subject: [PATCH 153/214] crypto: add secp256r1 (#8559) * 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 * any.pb.go update * generated proto files * wip * renames * wip2 * add String method to PBBytes * wip3 * add pubkey tests * adding cryptotypes.PrivKey methods * re-enable test * fix equals test * fix ecdsa object receiver * add ProtoMarshaler implementation and tests * move code to init and add interface registry * add bytes tests * merge Unmarshal with UnmarshalAmino * implement ProtoMarshaler to ecdsaSK * remove bytes.go * add private key marshaling tests * break tests into 2 suites * add signature tests * remove TODO * remove bytes.proto * adding changelog * Update CHANGELOG.md * Update crypto/keys/ecdsa/ecdsa_privkey.go * Update crypto/keys/ecdsa/ecdsa_pubkey.go * comments: add dot (.) at the end * update comments * update commented code * rename files * remove Amino methods * use 2 spaces in protocgen.sh * rollback changes in protocgen.sh * add MessageName * rework ecdsa proto structure * move ecdsa to internal package * add secp256r1 proto * refactore proto definition for secp256r1 * fix err check * update comments * create const for fieldSize+1 * simplify the PubKey.String test * Apply suggestions from code review Co-authored-by: Jonathan Gimeno * Update doc comments: SDK Interface -> sdk.Interface * rename init.go to doc.go * Add PubKey.Type() test * Revert "Update doc comments: SDK Interface -> sdk.Interface" This reverts commit 01f2b4f5efcd79a452483bcda152db54a8fbfee2. * Use cryptotypes.Address instead of tmcrypto * Revert "Use cryptotypes.Address instead of tmcrypto" This reverts commit 15b866ae67bdb7ca4872f4089fcab19f9e2e3608. This issue will be solved in https://github.com/cosmos/cosmos-sdk/issues/8775 * add link to ANSI X9.62 * move init.go -> doc.go * use proto.MessageName() Co-authored-by: Alessio Treglia Co-authored-by: Jonathan Gimeno --- CHANGELOG.md | 6 +- codec/types/any.pb.go | 5 +- crypto/codec/proto.go | 11 +- crypto/keys/internal/ecdsa/doc.go | 3 + crypto/keys/internal/ecdsa/privkey.go | 69 +++ .../internal/ecdsa/privkey_internal_test.go | 66 +++ crypto/keys/internal/ecdsa/pubkey.go | 83 +++ .../internal/ecdsa/pubkey_internal_test.go | 69 +++ crypto/keys/secp256r1/doc.go | 35 ++ crypto/keys/secp256r1/keys.pb.go | 503 ++++++++++++++++++ crypto/keys/secp256r1/privkey.go | 63 +++ .../keys/secp256r1/privkey_internal_test.go | 115 ++++ crypto/keys/secp256r1/pubkey.go | 60 +++ crypto/keys/secp256r1/pubkey_internal_test.go | 118 ++++ docs/core/proto-docs.md | 50 ++ proto/cosmos/crypto/secp256r1/keys.proto | 22 + 16 files changed, 1269 insertions(+), 9 deletions(-) create mode 100644 crypto/keys/internal/ecdsa/doc.go create mode 100644 crypto/keys/internal/ecdsa/privkey.go create mode 100644 crypto/keys/internal/ecdsa/privkey_internal_test.go create mode 100644 crypto/keys/internal/ecdsa/pubkey.go create mode 100644 crypto/keys/internal/ecdsa/pubkey_internal_test.go create mode 100644 crypto/keys/secp256r1/doc.go create mode 100644 crypto/keys/secp256r1/keys.pb.go create mode 100644 crypto/keys/secp256r1/privkey.go create mode 100644 crypto/keys/secp256r1/privkey_internal_test.go create mode 100644 crypto/keys/secp256r1/pubkey.go create mode 100644 crypto/keys/secp256r1/pubkey_internal_test.go create mode 100644 proto/cosmos/crypto/secp256r1/keys.proto diff --git a/CHANGELOG.md b/CHANGELOG.md index d8e4e2007d0b..77651cc69cd0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,10 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] +## Features + +* [\#8559](https://github.com/cosmos/cosmos-sdk/pull/8559) Adding Protobuf compatible secp256r1 ECDSA signatures. + ### Client Breaking Changes * [\#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. @@ -137,7 +141,7 @@ he Cosmos Hub) should not use this release or any release in the v0.41.x series. ### 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. +* (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/codec/types/any.pb.go b/codec/types/any.pb.go index 97d9f1c2aa64..94cf80216287 100644 --- a/codec/types/any.pb.go +++ b/codec/types/any.pb.go @@ -476,10 +476,7 @@ func (m *Any) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthAny - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthAny } if (iNdEx + skippy) > l { diff --git a/crypto/codec/proto.go b/crypto/codec/proto.go index 9c07ca110596..7f38dee61433 100644 --- a/crypto/codec/proto.go +++ b/crypto/codec/proto.go @@ -5,13 +5,16 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" "github.com/cosmos/cosmos-sdk/crypto/keys/multisig" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256r1" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" ) // RegisterInterfaces registers the sdk.Tx interface. func RegisterInterfaces(registry codectypes.InterfaceRegistry) { - registry.RegisterInterface("cosmos.crypto.PubKey", (*cryptotypes.PubKey)(nil)) - registry.RegisterImplementations((*cryptotypes.PubKey)(nil), &ed25519.PubKey{}) - registry.RegisterImplementations((*cryptotypes.PubKey)(nil), &secp256k1.PubKey{}) - registry.RegisterImplementations((*cryptotypes.PubKey)(nil), &multisig.LegacyAminoPubKey{}) + var pk *cryptotypes.PubKey + registry.RegisterInterface("cosmos.crypto.PubKey", pk) + registry.RegisterImplementations(pk, &ed25519.PubKey{}) + registry.RegisterImplementations(pk, &secp256k1.PubKey{}) + registry.RegisterImplementations(pk, &multisig.LegacyAminoPubKey{}) + secp256r1.RegisterInterfaces(registry) } diff --git a/crypto/keys/internal/ecdsa/doc.go b/crypto/keys/internal/ecdsa/doc.go new file mode 100644 index 000000000000..a27b9caf9a8e --- /dev/null +++ b/crypto/keys/internal/ecdsa/doc.go @@ -0,0 +1,3 @@ +// Package ECDSA implements Cosmos-SDK compatible ECDSA public and private key. The keys +// can be serialized. +package ecdsa diff --git a/crypto/keys/internal/ecdsa/privkey.go b/crypto/keys/internal/ecdsa/privkey.go new file mode 100644 index 000000000000..0930285b04a1 --- /dev/null +++ b/crypto/keys/internal/ecdsa/privkey.go @@ -0,0 +1,69 @@ +package ecdsa + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/sha256" + "fmt" + "math/big" +) + +// GenPrivKey generates a new secp256r1 private key. It uses operating system randomness. +func GenPrivKey(curve elliptic.Curve) (PrivKey, error) { + key, err := ecdsa.GenerateKey(curve, rand.Reader) + if err != nil { + return PrivKey{}, err + } + return PrivKey{*key}, nil +} + +type PrivKey struct { + ecdsa.PrivateKey +} + +// PubKey returns ECDSA public key associated with this private key. +func (sk *PrivKey) PubKey() PubKey { + return PubKey{sk.PublicKey, nil} +} + +// Bytes serialize the private key using big-endian. +func (sk *PrivKey) Bytes() []byte { + if sk == nil { + return nil + } + fieldSize := (sk.Curve.Params().BitSize + 7) / 8 + bz := make([]byte, fieldSize) + sk.D.FillBytes(bz) + return bz +} + +// Sign hashes and signs the message usign ECDSA. Implements SDK PrivKey interface. +func (sk *PrivKey) Sign(msg []byte) ([]byte, error) { + digest := sha256.Sum256(msg) + return sk.PrivateKey.Sign(rand.Reader, digest[:], nil) +} + +// String returns a string representation of the public key based on the curveName. +func (sk *PrivKey) String(name string) string { + return name + "{-}" +} + +// MarshalTo implements proto.Marshaler interface. +func (sk *PrivKey) MarshalTo(dAtA []byte) (int, error) { + bz := sk.Bytes() + copy(dAtA, bz) + return len(bz), nil +} + +// Unmarshal implements proto.Marshaler interface. +func (sk *PrivKey) Unmarshal(bz []byte, curve elliptic.Curve, expectedSize int) error { + if len(bz) != expectedSize { + return fmt.Errorf("wrong ECDSA SK bytes, expecting %d bytes", expectedSize) + } + + sk.Curve = curve + sk.D = new(big.Int).SetBytes(bz) + sk.X, sk.Y = curve.ScalarBaseMult(bz) + return nil +} diff --git a/crypto/keys/internal/ecdsa/privkey_internal_test.go b/crypto/keys/internal/ecdsa/privkey_internal_test.go new file mode 100644 index 000000000000..095e593656d7 --- /dev/null +++ b/crypto/keys/internal/ecdsa/privkey_internal_test.go @@ -0,0 +1,66 @@ +package ecdsa + +import ( + "testing" + + "github.com/tendermint/tendermint/crypto" + + "github.com/stretchr/testify/suite" +) + +func TestSKSuite(t *testing.T) { + suite.Run(t, new(SKSuite)) +} + +type SKSuite struct{ CommonSuite } + +func (suite *SKSuite) TestString() { + const prefix = "abc" + suite.Require().Equal(prefix+"{-}", suite.sk.String(prefix)) +} + +func (suite *SKSuite) TestPubKey() { + pk := suite.sk.PubKey() + suite.True(suite.sk.PublicKey.Equal(&pk.PublicKey)) +} + +func (suite *SKSuite) Bytes() { + bz := suite.sk.Bytes() + suite.Len(bz, 32) + var sk *PrivKey + suite.Nil(sk.Bytes()) +} + +func (suite *SKSuite) TestMarshal() { + require := suite.Require() + const size = 32 + + var buffer = make([]byte, size) + suite.sk.MarshalTo(buffer) + + var sk = new(PrivKey) + err := sk.Unmarshal(buffer, secp256r1, size) + require.NoError(err) + require.True(sk.Equal(&suite.sk.PrivateKey)) +} + +func (suite *SKSuite) TestSign() { + require := suite.Require() + + msg := crypto.CRandBytes(1000) + sig, err := suite.sk.Sign(msg) + require.NoError(err) + sigCpy := make([]byte, len(sig)) + copy(sigCpy, sig) + require.True(suite.pk.VerifySignature(msg, sigCpy)) + + // Mutate the signature + for i := range sig { + sigCpy[i] ^= byte(i + 1) + require.False(suite.pk.VerifySignature(msg, sigCpy)) + } + + // Mutate the message + msg[1] ^= byte(2) + require.False(suite.pk.VerifySignature(msg, sig)) +} diff --git a/crypto/keys/internal/ecdsa/pubkey.go b/crypto/keys/internal/ecdsa/pubkey.go new file mode 100644 index 000000000000..4c9b493a6b5f --- /dev/null +++ b/crypto/keys/internal/ecdsa/pubkey.go @@ -0,0 +1,83 @@ +package ecdsa + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/sha256" + "encoding/asn1" + "fmt" + "math/big" + + tmcrypto "github.com/tendermint/tendermint/crypto" + + "github.com/cosmos/cosmos-sdk/types/address" + "github.com/cosmos/cosmos-sdk/types/errors" +) + +// signature holds the r and s values of an ECDSA signature. +type signature struct { + R, S *big.Int +} + +type PubKey struct { + ecdsa.PublicKey + + // cache + address tmcrypto.Address +} + +// Address creates an ADR-28 address for ECDSA keys. protoName is a concrete proto structure id. +func (pk *PubKey) Address(protoName string) tmcrypto.Address { + if pk.address == nil { + pk.address = address.Hash(protoName, pk.Bytes()) + } + return pk.address +} + +// Bytes returns the byte representation of the public key using a compressed form +// specified in section 4.3.6 of ANSI X9.62 with first byte being the curve type. +func (pk *PubKey) Bytes() []byte { + if pk == nil { + return nil + } + return elliptic.MarshalCompressed(pk.Curve, pk.X, pk.Y) +} + +// VerifySignature checks if sig is a valid ECDSA signature for msg. +func (pk *PubKey) VerifySignature(msg []byte, sig []byte) bool { + s := new(signature) + if _, err := asn1.Unmarshal(sig, s); err != nil || s == nil { + return false + } + + h := sha256.Sum256(msg) + return ecdsa.Verify(&pk.PublicKey, h[:], s.R, s.S) +} + +// String returns a string representation of the public key based on the curveName. +func (pk *PubKey) String(curveName string) string { + return fmt.Sprintf("%s{%X}", curveName, pk.Bytes()) +} + +// **** Proto Marshaler **** + +// MarshalTo implements proto.Marshaler interface. +func (pk *PubKey) MarshalTo(dAtA []byte) (int, error) { + bz := pk.Bytes() + copy(dAtA, bz) + return len(bz), nil +} + +// Unmarshal implements proto.Marshaler interface. +func (pk *PubKey) Unmarshal(bz []byte, curve elliptic.Curve, expectedSize int) error { + if len(bz) != expectedSize { + return errors.Wrapf(errors.ErrInvalidPubKey, "wrong ECDSA PK bytes, expecting %d bytes, got %d", expectedSize, len(bz)) + } + cpk := ecdsa.PublicKey{Curve: curve} + cpk.X, cpk.Y = elliptic.UnmarshalCompressed(curve, bz) + if cpk.X == nil || cpk.Y == nil { + return errors.Wrapf(errors.ErrInvalidPubKey, "wrong ECDSA PK bytes, unknown curve type: %d", bz[0]) + } + pk.PublicKey = cpk + return nil +} diff --git a/crypto/keys/internal/ecdsa/pubkey_internal_test.go b/crypto/keys/internal/ecdsa/pubkey_internal_test.go new file mode 100644 index 000000000000..2a46bdff39d7 --- /dev/null +++ b/crypto/keys/internal/ecdsa/pubkey_internal_test.go @@ -0,0 +1,69 @@ +package ecdsa + +import ( + "crypto/elliptic" + "encoding/hex" + "testing" + + "github.com/stretchr/testify/suite" +) + +var secp256r1 = elliptic.P256() + +func GenSecp256r1() (PrivKey, error) { + return GenPrivKey(secp256r1) +} + +func TestPKSuite(t *testing.T) { + suite.Run(t, new(PKSuite)) +} + +type CommonSuite struct { + suite.Suite + pk PubKey + sk PrivKey +} + +func (suite *CommonSuite) SetupSuite() { + sk, err := GenSecp256r1() + suite.Require().NoError(err) + suite.sk = sk + suite.pk = sk.PubKey() +} + +type PKSuite struct{ CommonSuite } + +func (suite *PKSuite) TestString() { + assert := suite.Assert() + require := suite.Require() + + prefix := "abc" + pkStr := suite.pk.String(prefix) + assert.Equal(prefix+"{", pkStr[:len(prefix)+1]) + assert.EqualValues('}', pkStr[len(pkStr)-1]) + + bz, err := hex.DecodeString(pkStr[len(prefix)+1 : len(pkStr)-1]) + require.NoError(err) + assert.EqualValues(suite.pk.Bytes(), bz) +} + +func (suite *PKSuite) TestBytes() { + require := suite.Require() + var pk *PubKey + require.Nil(pk.Bytes()) +} + +func (suite *PKSuite) TestMarshal() { + require := suite.Require() + const size = 33 // secp256r1 size + + var buffer = make([]byte, size) + n, err := suite.pk.MarshalTo(buffer) + require.NoError(err) + require.Equal(size, n) + + var pk = new(PubKey) + err = pk.Unmarshal(buffer, secp256r1, size) + require.NoError(err) + require.True(pk.PublicKey.Equal(&suite.pk.PublicKey)) +} diff --git a/crypto/keys/secp256r1/doc.go b/crypto/keys/secp256r1/doc.go new file mode 100644 index 000000000000..be938dc77f97 --- /dev/null +++ b/crypto/keys/secp256r1/doc.go @@ -0,0 +1,35 @@ +// Package secp256r1 implements Cosmos-SDK compatible ECDSA public and private key. The keys +// can be protobuf serialized and packed in Any. +package secp256r1 + +import ( + "crypto/elliptic" + "fmt" + + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" +) + +const ( + // fieldSize is the curve domain size. + fieldSize = 32 + pubKeySize = fieldSize + 1 + + name = "secp256r1" +) + +var secp256r1 elliptic.Curve + +func init() { + secp256r1 = elliptic.P256() + // pubKeySize is ceil of field bit size + 1 for the sign + expected := (secp256r1.Params().BitSize + 7) / 8 + if expected != fieldSize { + panic(fmt.Sprintf("Wrong secp256r1 curve fieldSize=%d, expecting=%d", fieldSize, expected)) + } +} + +// RegisterInterfaces adds secp256r1 PubKey to pubkey registry +func RegisterInterfaces(registry codectypes.InterfaceRegistry) { + registry.RegisterImplementations((*cryptotypes.PubKey)(nil), &PubKey{}) +} diff --git a/crypto/keys/secp256r1/keys.pb.go b/crypto/keys/secp256r1/keys.pb.go new file mode 100644 index 000000000000..898daa499b11 --- /dev/null +++ b/crypto/keys/secp256r1/keys.pb.go @@ -0,0 +1,503 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cosmos/crypto/secp256r1/keys.proto + +package secp256r1 + +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 secp256r1 ECDSA public key. +type PubKey struct { + // Point on secp256r1 curve in a compressed representation as specified in section + // 4.3.6 of ANSI X9.62. + Key *ecdsaPK `protobuf:"bytes,1,opt,name=key,proto3,customtype=ecdsaPK" json:"key,omitempty"` +} + +func (m *PubKey) Reset() { *m = PubKey{} } +func (*PubKey) ProtoMessage() {} +func (*PubKey) Descriptor() ([]byte, []int) { + return fileDescriptor_b90c18415095c0c3, []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 (*PubKey) XXX_MessageName() string { + return "cosmos.crypto.secp256r1.PubKey" +} + +// PrivKey defines a secp256r1 ECDSA private key. +type PrivKey struct { + // secret number serialized using big-endian encoding + Secret *ecdsaSK `protobuf:"bytes,1,opt,name=secret,proto3,customtype=ecdsaSK" json:"secret,omitempty"` +} + +func (m *PrivKey) Reset() { *m = PrivKey{} } +func (*PrivKey) ProtoMessage() {} +func (*PrivKey) Descriptor() ([]byte, []int) { + return fileDescriptor_b90c18415095c0c3, []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 (*PrivKey) XXX_MessageName() string { + return "cosmos.crypto.secp256r1.PrivKey" +} +func init() { + proto.RegisterType((*PubKey)(nil), "cosmos.crypto.secp256r1.PubKey") + proto.RegisterType((*PrivKey)(nil), "cosmos.crypto.secp256r1.PrivKey") +} + +func init() { + proto.RegisterFile("cosmos/crypto/secp256r1/keys.proto", fileDescriptor_b90c18415095c0c3) +} + +var fileDescriptor_b90c18415095c0c3 = []byte{ + // 221 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x4a, 0xce, 0x2f, 0xce, + 0xcd, 0x2f, 0xd6, 0x4f, 0x2e, 0xaa, 0x2c, 0x28, 0xc9, 0xd7, 0x2f, 0x4e, 0x4d, 0x2e, 0x30, 0x32, + 0x35, 0x2b, 0x32, 0xd4, 0xcf, 0x4e, 0xad, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, + 0x87, 0xa8, 0xd1, 0x83, 0xa8, 0xd1, 0x83, 0xab, 0x91, 0x12, 0x49, 0xcf, 0x4f, 0xcf, 0x07, 0xab, + 0xd1, 0x07, 0xb1, 0x20, 0xca, 0x95, 0xd4, 0xb9, 0xd8, 0x02, 0x4a, 0x93, 0xbc, 0x53, 0x2b, 0x85, + 0x64, 0xb9, 0x98, 0xb3, 0x53, 0x2b, 0x25, 0x18, 0x15, 0x18, 0x35, 0x78, 0x9c, 0xb8, 0x6f, 0xdd, + 0x93, 0x67, 0x4f, 0x4d, 0x4e, 0x29, 0x4e, 0x0c, 0xf0, 0x0e, 0x02, 0x89, 0x2b, 0xe9, 0x71, 0xb1, + 0x07, 0x14, 0x65, 0x96, 0x81, 0x54, 0x2a, 0x73, 0xb1, 0x15, 0xa7, 0x26, 0x17, 0xa5, 0x96, 0x60, + 0x28, 0x0e, 0xf6, 0x0e, 0x82, 0x4a, 0x39, 0x45, 0x9c, 0x78, 0x28, 0xc7, 0x70, 0xe3, 0xa1, 0x1c, + 0xc3, 0x89, 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, + 0x1c, 0xc3, 0x89, 0xc7, 0x72, 0x8c, 0x17, 0x1e, 0xcb, 0x31, 0xdc, 0x78, 0x2c, 0xc7, 0x10, 0x65, + 0x94, 0x9e, 0x59, 0x92, 0x51, 0x9a, 0xa4, 0x97, 0x9c, 0x9f, 0xab, 0x0f, 0xf3, 0x1c, 0x98, 0xd2, + 0x2d, 0x4e, 0xc9, 0x86, 0xf9, 0x13, 0xe4, 0x3b, 0x84, 0x67, 0x93, 0xd8, 0xc0, 0x2e, 0x37, 0x06, + 0x04, 0x00, 0x00, 0xff, 0xff, 0xe0, 0x65, 0x08, 0x5c, 0x0e, 0x01, 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 m.Key != nil { + { + size := m.Key.Size() + i -= size + if _, err := m.Key.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintKeys(dAtA, i, uint64(size)) + } + 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 m.Secret != nil { + { + size := m.Secret.Size() + i -= size + if _, err := m.Secret.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintKeys(dAtA, i, uint64(size)) + } + 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 + if m.Key != nil { + l = m.Key.Size() + n += 1 + l + sovKeys(uint64(l)) + } + return n +} + +func (m *PrivKey) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Secret != nil { + l = m.Secret.Size() + 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 + } + var v ecdsaPK + m.Key = &v + if err := m.Key.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + 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 Secret", 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 + } + var v ecdsaSK + m.Secret = &v + if err := m.Secret.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + 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/secp256r1/privkey.go b/crypto/keys/secp256r1/privkey.go new file mode 100644 index 000000000000..8ca725420ff8 --- /dev/null +++ b/crypto/keys/secp256r1/privkey.go @@ -0,0 +1,63 @@ +package secp256r1 + +import ( + "github.com/cosmos/cosmos-sdk/crypto/keys/internal/ecdsa" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" +) + +// GenPrivKey generates a new secp256r1 private key. It uses operating system randomness. +func GenPrivKey() (*PrivKey, error) { + key, err := ecdsa.GenPrivKey(secp256r1) + return &PrivKey{&ecdsaSK{key}}, err +} + +// PubKey implements SDK PrivKey interface. +func (m *PrivKey) PubKey() cryptotypes.PubKey { + return &PubKey{&ecdsaPK{m.Secret.PubKey()}} +} + +// String implements SDK proto.Message interface. +func (m *PrivKey) String() string { + return m.Secret.String(name) +} + +// Type returns key type name. Implements SDK PrivKey interface. +func (m *PrivKey) Type() string { + return name +} + +// Sign hashes and signs the message usign ECDSA. Implements sdk.PrivKey interface. +func (m *PrivKey) Sign(msg []byte) ([]byte, error) { + return m.Secret.Sign(msg) +} + +// Bytes serialize the private key. +func (m *PrivKey) Bytes() []byte { + return m.Secret.Bytes() +} + +// Equals implements SDK PrivKey interface. +func (m *PrivKey) Equals(other cryptotypes.LedgerPrivKey) bool { + sk2, ok := other.(*PrivKey) + if !ok { + return false + } + return m.Secret.Equal(&sk2.Secret.PrivateKey) +} + +type ecdsaSK struct { + ecdsa.PrivKey +} + +// Size implements proto.Marshaler interface +func (sk *ecdsaSK) Size() int { + if sk == nil { + return 0 + } + return fieldSize +} + +// Unmarshal implements proto.Marshaler interface +func (sk *ecdsaSK) Unmarshal(bz []byte) error { + return sk.PrivKey.Unmarshal(bz, secp256r1, fieldSize) +} diff --git a/crypto/keys/secp256r1/privkey_internal_test.go b/crypto/keys/secp256r1/privkey_internal_test.go new file mode 100644 index 000000000000..ae48b47e3d68 --- /dev/null +++ b/crypto/keys/secp256r1/privkey_internal_test.go @@ -0,0 +1,115 @@ +package secp256r1 + +import ( + "testing" + + "github.com/tendermint/tendermint/crypto" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/types" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + proto "github.com/gogo/protobuf/proto" + "github.com/stretchr/testify/suite" +) + +var _ cryptotypes.PrivKey = &PrivKey{} + +func TestSKSuite(t *testing.T) { + suite.Run(t, new(SKSuite)) +} + +type SKSuite struct{ CommonSuite } + +func (suite *SKSuite) TestString() { + suite.Require().Equal("secp256r1{-}", suite.sk.String()) +} + +func (suite *SKSuite) TestEquals() { + require := suite.Require() + + skOther, err := GenPrivKey() + require.NoError(err) + require.False(suite.sk.Equals(skOther)) + + skOther2 := &PrivKey{skOther.Secret} + require.True(skOther.Equals(skOther2)) + require.True(skOther2.Equals(skOther), "Equals must be reflexive") +} + +func (suite *SKSuite) TestPubKey() { + pk := suite.sk.PubKey() + suite.True(suite.sk.(*PrivKey).Secret.PublicKey.Equal(&pk.(*PubKey).Key.PublicKey)) +} + +func (suite *SKSuite) Bytes() { + bz := suite.sk.Bytes() + suite.Len(bz, fieldSize) + var sk *PrivKey + suite.Nil(sk.Bytes()) +} + +func (suite *SKSuite) TestMarshalProto() { + require := suite.Require() + + /**** test structure marshalling ****/ + + var sk PrivKey + bz, err := proto.Marshal(suite.sk) + require.NoError(err) + require.NoError(proto.Unmarshal(bz, &sk)) + require.True(sk.Equals(suite.sk)) + + /**** test structure marshalling with codec ****/ + + sk = PrivKey{} + registry := types.NewInterfaceRegistry() + cdc := codec.NewProtoCodec(registry) + bz, err = cdc.MarshalBinaryBare(suite.sk.(*PrivKey)) + require.NoError(err) + require.NoError(cdc.UnmarshalBinaryBare(bz, &sk)) + require.True(sk.Equals(suite.sk)) + + const bufSize = 100 + bz2 := make([]byte, bufSize) + skCpy := suite.sk.(*PrivKey) + _, err = skCpy.MarshalTo(bz2) + require.NoError(err) + require.Len(bz2, bufSize) + require.Equal(bz, bz2[:sk.Size()]) + + bz2 = make([]byte, bufSize) + _, err = skCpy.MarshalToSizedBuffer(bz2) + require.NoError(err) + require.Len(bz2, bufSize) + require.Equal(bz, bz2[(bufSize-sk.Size()):]) +} + +func (suite *SKSuite) TestSign() { + require := suite.Require() + + msg := crypto.CRandBytes(1000) + sig, err := suite.sk.Sign(msg) + require.NoError(err) + sigCpy := make([]byte, len(sig)) + copy(sigCpy, sig) + require.True(suite.pk.VerifySignature(msg, sigCpy)) + + // Mutate the signature + for i := range sig { + sigCpy[i] ^= byte(i + 1) + require.False(suite.pk.VerifySignature(msg, sigCpy)) + } + + // Mutate the message + msg[1] ^= byte(2) + require.False(suite.pk.VerifySignature(msg, sig)) +} + +func (suite *SKSuite) TestSize() { + require := suite.Require() + var pk ecdsaSK + require.Equal(pk.Size(), len(suite.sk.Bytes())) + + var nilPk *ecdsaSK + require.Equal(0, nilPk.Size(), "nil value must have zero size") +} diff --git a/crypto/keys/secp256r1/pubkey.go b/crypto/keys/secp256r1/pubkey.go new file mode 100644 index 000000000000..d75c0f5298b7 --- /dev/null +++ b/crypto/keys/secp256r1/pubkey.go @@ -0,0 +1,60 @@ +package secp256r1 + +import ( + "github.com/gogo/protobuf/proto" + tmcrypto "github.com/tendermint/tendermint/crypto" + + ecdsa "github.com/cosmos/cosmos-sdk/crypto/keys/internal/ecdsa" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" +) + +// String implements proto.Message interface. +func (m *PubKey) String() string { + return m.Key.String(name) +} + +// Bytes implements SDK PubKey interface. +func (m *PubKey) Bytes() []byte { + return m.Key.Bytes() +} + +// Equals implements SDK PubKey interface. +func (m *PubKey) Equals(other cryptotypes.PubKey) bool { + pk2, ok := other.(*PubKey) + if !ok { + return false + } + return m.Key.Equal(&pk2.Key.PublicKey) +} + +// Address implements SDK PubKey interface. +func (m *PubKey) Address() tmcrypto.Address { + return m.Key.Address(proto.MessageName(m)) +} + +// Type returns key type name. Implements SDK PubKey interface. +func (m *PubKey) Type() string { + return name +} + +// VerifySignature implements SDK PubKey interface. +func (m *PubKey) VerifySignature(msg []byte, sig []byte) bool { + return m.Key.VerifySignature(msg, sig) +} + +type ecdsaPK struct { + ecdsa.PubKey +} + +// Size implements proto.Marshaler interface +func (pk *ecdsaPK) Size() int { + if pk == nil { + return 0 + } + return pubKeySize +} + +// Unmarshal implements proto.Marshaler interface +func (pk *ecdsaPK) Unmarshal(bz []byte) error { + return pk.PubKey.Unmarshal(bz, secp256r1, pubKeySize) +} diff --git a/crypto/keys/secp256r1/pubkey_internal_test.go b/crypto/keys/secp256r1/pubkey_internal_test.go new file mode 100644 index 000000000000..84b587d0c63b --- /dev/null +++ b/crypto/keys/secp256r1/pubkey_internal_test.go @@ -0,0 +1,118 @@ +package secp256r1 + +import ( + "testing" + + proto "github.com/gogo/protobuf/proto" + "github.com/stretchr/testify/suite" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/types" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" +) + +var _ cryptotypes.PubKey = (*PubKey)(nil) + +func TestPKSuite(t *testing.T) { + suite.Run(t, new(PKSuite)) +} + +type CommonSuite struct { + suite.Suite + pk *PubKey // cryptotypes.PubKey + sk cryptotypes.PrivKey +} + +func (suite *CommonSuite) SetupSuite() { + sk, err := GenPrivKey() + suite.Require().NoError(err) + suite.sk = sk + suite.pk = sk.PubKey().(*PubKey) +} + +type PKSuite struct{ CommonSuite } + +func (suite *PKSuite) TestString() { + require := suite.Require() + + pkStr := suite.pk.String() + prefix := "secp256r1{" + require.Equal(prefix, pkStr[:len(prefix)]) +} + +func (suite *PKSuite) TestType() { + suite.Require().Equal(name, suite.pk.Type()) +} + +func (suite *PKSuite) TestEquals() { + require := suite.Require() + + skOther, err := GenPrivKey() + require.NoError(err) + pkOther := skOther.PubKey() + pkOther2 := &PubKey{&ecdsaPK{skOther.Secret.PubKey()}} + + require.False(suite.pk.Equals(pkOther)) + require.True(pkOther.Equals(pkOther2)) + require.True(pkOther2.Equals(pkOther)) + require.True(pkOther.Equals(pkOther), "Equals must be reflexive") +} + +func (suite *PKSuite) TestMarshalProto() { + require := suite.Require() + + /**** test structure marshalling ****/ + + var pk PubKey + bz, err := proto.Marshal(suite.pk) + require.NoError(err) + require.NoError(proto.Unmarshal(bz, &pk)) + require.True(pk.Equals(suite.pk)) + + /**** test structure marshalling with codec ****/ + + pk = PubKey{} + registry := types.NewInterfaceRegistry() + cdc := codec.NewProtoCodec(registry) + bz, err = cdc.MarshalBinaryBare(suite.pk) + require.NoError(err) + require.NoError(cdc.UnmarshalBinaryBare(bz, &pk)) + require.True(pk.Equals(suite.pk)) + + const bufSize = 100 + bz2 := make([]byte, bufSize) + pkCpy := suite.pk + _, err = pkCpy.MarshalTo(bz2) + require.NoError(err) + require.Len(bz2, bufSize) + require.Equal(bz, bz2[:pk.Size()]) + + bz2 = make([]byte, bufSize) + _, err = pkCpy.MarshalToSizedBuffer(bz2) + require.NoError(err) + require.Len(bz2, bufSize) + require.Equal(bz, bz2[(bufSize-pk.Size()):]) + + /**** test interface marshalling ****/ + bz, err = cdc.MarshalInterface(suite.pk) + require.NoError(err) + var pkI cryptotypes.PubKey + err = cdc.UnmarshalInterface(bz, &pkI) + require.EqualError(err, "no registered implementations of type types.PubKey") + + RegisterInterfaces(registry) + require.NoError(cdc.UnmarshalInterface(bz, &pkI)) + require.True(pkI.Equals(suite.pk)) + + cdc.UnmarshalInterface(bz, nil) + require.Error(err, "nil should fail") +} + +func (suite *PKSuite) TestSize() { + require := suite.Require() + var pk ecdsaPK + require.Equal(pk.Size(), len(suite.pk.Bytes())) + + var nilPk *ecdsaPK + require.Equal(0, nilPk.Size(), "nil value must have zero size") +} diff --git a/docs/core/proto-docs.md b/docs/core/proto-docs.md index 9c1f7110adc6..a9d2152f32d6 100644 --- a/docs/core/proto-docs.md +++ b/docs/core/proto-docs.md @@ -190,6 +190,10 @@ - [PrivKey](#cosmos.crypto.secp256k1.PrivKey) - [PubKey](#cosmos.crypto.secp256k1.PubKey) +- [cosmos/crypto/secp256r1/keys.proto](#cosmos/crypto/secp256r1/keys.proto) + - [PrivKey](#cosmos.crypto.secp256r1.PrivKey) + - [PubKey](#cosmos.crypto.secp256r1.PubKey) + - [cosmos/distribution/v1beta1/distribution.proto](#cosmos/distribution/v1beta1/distribution.proto) - [CommunityPoolSpendProposal](#cosmos.distribution.v1beta1.CommunityPoolSpendProposal) - [CommunityPoolSpendProposalWithDeposit](#cosmos.distribution.v1beta1.CommunityPoolSpendProposalWithDeposit) @@ -3115,6 +3119,52 @@ This prefix is followed with the x-coordinate. + + + + + + + + + + + +

Top

+ +## cosmos/crypto/secp256r1/keys.proto + + + + + +### PrivKey +PrivKey defines a secp256r1 ECDSA private key. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `secret` | [bytes](#bytes) | | secret number serialized using big-endian encoding | + + + + + + + + +### PubKey +PubKey defines a secp256r1 ECDSA public key. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `key` | [bytes](#bytes) | | Point on secp256r1 curve in a compressed representation as specified in section 4.3.6 of ANSI X9.62. | + + + + + diff --git a/proto/cosmos/crypto/secp256r1/keys.proto b/proto/cosmos/crypto/secp256r1/keys.proto new file mode 100644 index 000000000000..800b817e9495 --- /dev/null +++ b/proto/cosmos/crypto/secp256r1/keys.proto @@ -0,0 +1,22 @@ +syntax = "proto3"; +package cosmos.crypto.secp256r1; + +import "gogoproto/gogo.proto"; + +option go_package = "github.com/cosmos/cosmos-sdk/crypto/keys/secp256r1"; +option (gogoproto.messagename_all) = true; +option (gogoproto.goproto_stringer_all) = false; +option (gogoproto.goproto_getters_all) = false; + +// PubKey defines a secp256r1 ECDSA public key. +message PubKey { + // Point on secp256r1 curve in a compressed representation as specified in section + // 4.3.6 of ANSI X9.62: https://webstore.ansi.org/standards/ascx9/ansix9621998 + bytes key = 1 [(gogoproto.customtype) = "ecdsaPK"]; +} + +// PrivKey defines a secp256r1 ECDSA private key. +message PrivKey { + // secret number serialized using big-endian encoding + bytes secret = 1 [(gogoproto.customtype) = "ecdsaSK"]; +} From da064e13d56add466548135739c5860a9f7ed842 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?colin=20axn=C3=A9r?= <25233464+colin-axner@users.noreply.github.com> Date: Thu, 4 Mar 2021 14:11:34 +0100 Subject: [PATCH 154/214] Remove IBC from the SDK (#8735) --- README.md | 4 + docs/core/proto-docs.md | 3300 +------ docs/ibc/README.md | 2 + .../applications/transfer/v1/genesis.proto | 18 - .../ibc/applications/transfer/v1/query.proto | 66 - .../applications/transfer/v1/transfer.proto | 43 - proto/ibc/applications/transfer/v1/tx.proto | 43 - proto/ibc/core/channel/v1/channel.proto | 147 - proto/ibc/core/channel/v1/genesis.proto | 31 - proto/ibc/core/channel/v1/query.proto | 367 - proto/ibc/core/channel/v1/tx.proto | 207 - proto/ibc/core/client/v1/client.proto | 98 - proto/ibc/core/client/v1/genesis.proto | 46 - proto/ibc/core/client/v1/query.proto | 152 - proto/ibc/core/client/v1/tx.proto | 96 - proto/ibc/core/commitment/v1/commitment.proto | 40 - proto/ibc/core/connection/v1/connection.proto | 104 - proto/ibc/core/connection/v1/genesis.proto | 16 - proto/ibc/core/connection/v1/query.proto | 137 - proto/ibc/core/connection/v1/tx.proto | 115 - proto/ibc/core/types/v1/genesis.proto | 22 - .../lightclients/localhost/v1/localhost.proto | 17 - .../solomachine/v1/solomachine.proto | 186 - .../tendermint/v1/tendermint.proto | 111 - simapp/app.go | 75 +- simapp/app_test.go | 4 - simapp/sim_test.go | 4 - x/README.md | 6 +- x/auth/ante/ante_test.go | 4 +- x/auth/client/rest/rest_test.go | 138 - x/capability/keeper/keeper_test.go | 10 - x/ibc/applications/transfer/client/cli/cli.go | 42 - .../applications/transfer/client/cli/query.go | 108 - x/ibc/applications/transfer/client/cli/tx.go | 117 - x/ibc/applications/transfer/handler.go | 23 - x/ibc/applications/transfer/handler_test.go | 123 - .../transfer/keeper/MBT_README.md | 51 - .../applications/transfer/keeper/encoding.go | 35 - x/ibc/applications/transfer/keeper/genesis.go | 45 - .../transfer/keeper/genesis_test.go | 39 - .../transfer/keeper/grpc_query.go | 83 - .../transfer/keeper/grpc_query_test.go | 142 - x/ibc/applications/transfer/keeper/keeper.go | 169 - .../transfer/keeper/keeper_test.go | 51 - .../transfer/keeper/mbt_relay_test.go | 378 - .../model_based_tests/Test5Packets.json | 492 - .../keeper/model_based_tests/Test5Packets.tla | 1056 --- .../Test5PacketsAllDifferentPass.json | 612 -- .../Test5PacketsAllDifferentPass.tla | 1188 --- .../TestOnRecvAcknowledgementErrorFail.json | 58 - .../TestOnRecvAcknowledgementErrorFail.tla | 159 - .../TestOnRecvAcknowledgementErrorPass.json | 159 - .../TestOnRecvAcknowledgementErrorPass.tla | 310 - .../TestOnRecvAcknowledgementResultFail.json | 58 - .../TestOnRecvAcknowledgementResultFail.tla | 159 - .../TestOnRecvAcknowledgementResultPass.json | 58 - .../TestOnRecvAcknowledgementResultPass.tla | 159 - .../TestOnRecvPacketFail.json | 58 - .../TestOnRecvPacketFail.tla | 159 - .../TestOnRecvPacketPass.json | 73 - .../TestOnRecvPacketPass.tla | 174 - .../model_based_tests/TestOnTimeoutFail.json | 58 - .../model_based_tests/TestOnTimeoutFail.tla | 159 - .../model_based_tests/TestOnTimeoutPass.json | 159 - .../model_based_tests/TestOnTimeoutPass.tla | 310 - .../TestSendTransferFail.json | 58 - .../TestSendTransferFail.tla | 159 - .../TestSendTransferPass.json | 174 - .../TestSendTransferPass.tla | 323 - .../model_based_tests/TestUnescrowTokens.json | 305 - .../model_based_tests/TestUnescrowTokens.tla | 563 -- .../transfer/keeper/msg_server.go | 43 - x/ibc/applications/transfer/keeper/params.go | 30 - .../transfer/keeper/params_test.go | 15 - x/ibc/applications/transfer/keeper/relay.go | 406 - .../transfer/keeper/relay_model/account.tla | 36 - .../keeper/relay_model/account_record.tla | 46 - .../relay_model/apalache-to-relay-test.json | 100 - .../relay_model/apalache-to-relay-test2.json | 104 - .../transfer/keeper/relay_model/denom.tla | 50 - .../keeper/relay_model/denom_record.tla | 53 - .../keeper/relay_model/denom_record2.tla | 114 - .../keeper/relay_model/denom_sequence.tla | 47 - .../keeper/relay_model/identifiers.tla | 10 - .../transfer/keeper/relay_model/relay.tla | 278 - .../keeper/relay_model/relay_tests.tla | 96 - .../transfer/keeper/relay_test.go | 392 - x/ibc/applications/transfer/module.go | 434 - x/ibc/applications/transfer/module_test.go | 246 - .../transfer/simulation/decoder.go | 33 - .../transfer/simulation/decoder_test.go | 59 - .../transfer/simulation/genesis.go | 54 - .../transfer/simulation/genesis_test.go | 74 - .../transfer/simulation/params.go | 32 - .../transfer/simulation/params_test.go | 36 - .../applications/transfer/spec/01_concepts.md | 117 - x/ibc/applications/transfer/spec/02_state.md | 10 - .../transfer/spec/03_state_transitions.md | 36 - .../applications/transfer/spec/04_messages.md | 40 - x/ibc/applications/transfer/spec/05_events.md | 44 - .../applications/transfer/spec/06_metrics.md | 14 - x/ibc/applications/transfer/spec/07_params.md | 30 - x/ibc/applications/transfer/spec/README.md | 24 - x/ibc/applications/transfer/types/codec.go | 41 - x/ibc/applications/transfer/types/coin.go | 48 - x/ibc/applications/transfer/types/errors.go | 17 - x/ibc/applications/transfer/types/events.go | 21 - .../transfer/types/expected_keepers.go | 48 - x/ibc/applications/transfer/types/genesis.go | 35 - .../applications/transfer/types/genesis.pb.go | 443 - .../transfer/types/genesis_test.go | 47 - x/ibc/applications/transfer/types/keys.go | 55 - .../applications/transfer/types/keys_test.go | 24 - x/ibc/applications/transfer/types/msgs.go | 85 - .../applications/transfer/types/msgs_test.go | 103 - x/ibc/applications/transfer/types/packet.go | 56 - .../transfer/types/packet_test.go | 36 - x/ibc/applications/transfer/types/params.go | 65 - .../transfer/types/params_test.go | 12 - x/ibc/applications/transfer/types/query.pb.go | 1418 --- .../transfer/types/query.pb.gw.go | 326 - x/ibc/applications/transfer/types/trace.go | 203 - .../applications/transfer/types/trace_test.go | 150 - .../transfer/types/transfer.pb.go | 909 -- x/ibc/applications/transfer/types/tx.pb.go | 804 -- x/ibc/core/02-client/abci.go | 41 - x/ibc/core/02-client/abci_test.go | 94 - x/ibc/core/02-client/client/cli/cli.go | 51 - x/ibc/core/02-client/client/cli/query.go | 260 - x/ibc/core/02-client/client/cli/tx.go | 418 - .../core/02-client/client/proposal_handler.go | 25 - x/ibc/core/02-client/client/utils/utils.go | 199 - x/ibc/core/02-client/doc.go | 10 - x/ibc/core/02-client/genesis.go | 69 - x/ibc/core/02-client/keeper/client.go | 205 - x/ibc/core/02-client/keeper/client_test.go | 628 -- x/ibc/core/02-client/keeper/encoding.go | 42 - x/ibc/core/02-client/keeper/grpc_query.go | 242 - .../core/02-client/keeper/grpc_query_test.go | 381 - x/ibc/core/02-client/keeper/keeper.go | 384 - x/ibc/core/02-client/keeper/keeper_test.go | 389 - x/ibc/core/02-client/keeper/params.go | 23 - x/ibc/core/02-client/keeper/params_test.go | 17 - x/ibc/core/02-client/keeper/proposal.go | 98 - x/ibc/core/02-client/keeper/proposal_test.go | 265 - x/ibc/core/02-client/module.go | 29 - x/ibc/core/02-client/proposal_handler.go | 24 - x/ibc/core/02-client/proposal_handler_test.go | 84 - x/ibc/core/02-client/simulation/decoder.go | 38 - .../core/02-client/simulation/decoder_test.go | 70 - x/ibc/core/02-client/simulation/genesis.go | 13 - x/ibc/core/02-client/types/client.go | 111 - x/ibc/core/02-client/types/client.pb.go | 1946 ---- x/ibc/core/02-client/types/client_test.go | 87 - x/ibc/core/02-client/types/codec.go | 189 - x/ibc/core/02-client/types/codec_test.go | 210 - x/ibc/core/02-client/types/encoding.go | 113 - x/ibc/core/02-client/types/encoding_test.go | 30 - x/ibc/core/02-client/types/errors.go | 36 - x/ibc/core/02-client/types/events.go | 27 - .../core/02-client/types/expected_keepers.go | 25 - x/ibc/core/02-client/types/genesis.go | 250 - x/ibc/core/02-client/types/genesis.pb.go | 1057 --- x/ibc/core/02-client/types/genesis_test.go | 549 -- x/ibc/core/02-client/types/height.go | 188 - x/ibc/core/02-client/types/height_test.go | 155 - x/ibc/core/02-client/types/keys.go | 65 - x/ibc/core/02-client/types/keys_test.go | 54 - x/ibc/core/02-client/types/msgs.go | 343 - x/ibc/core/02-client/types/msgs_test.go | 619 -- x/ibc/core/02-client/types/params.go | 71 - x/ibc/core/02-client/types/params_test.go | 30 - x/ibc/core/02-client/types/proposal.go | 154 - x/ibc/core/02-client/types/proposal_test.go | 234 - x/ibc/core/02-client/types/query.go | 65 - x/ibc/core/02-client/types/query.pb.go | 3118 ------- x/ibc/core/02-client/types/query.pb.gw.go | 718 -- x/ibc/core/02-client/types/tx.pb.go | 2071 ----- x/ibc/core/03-connection/client/cli/cli.go | 46 - x/ibc/core/03-connection/client/cli/query.go | 118 - x/ibc/core/03-connection/client/cli/tx.go | 348 - .../core/03-connection/client/utils/utils.go | 219 - x/ibc/core/03-connection/genesis.go | 28 - x/ibc/core/03-connection/keeper/grpc_query.go | 179 - .../03-connection/keeper/grpc_query_test.go | 420 - x/ibc/core/03-connection/keeper/handshake.go | 342 - .../03-connection/keeper/handshake_test.go | 701 -- x/ibc/core/03-connection/keeper/keeper.go | 198 - .../core/03-connection/keeper/keeper_test.go | 133 - x/ibc/core/03-connection/keeper/verify.go | 225 - .../core/03-connection/keeper/verify_test.go | 514 -- x/ibc/core/03-connection/module.go | 29 - .../core/03-connection/simulation/decoder.go | 32 - .../03-connection/simulation/decoder_test.go | 69 - .../core/03-connection/simulation/genesis.go | 13 - x/ibc/core/03-connection/types/codec.go | 47 - x/ibc/core/03-connection/types/connection.go | 127 - .../core/03-connection/types/connection.pb.go | 1800 ---- .../03-connection/types/connection_test.go | 121 - x/ibc/core/03-connection/types/errors.go | 19 - x/ibc/core/03-connection/types/events.go | 25 - .../03-connection/types/expected_keepers.go | 16 - x/ibc/core/03-connection/types/genesis.go | 76 - x/ibc/core/03-connection/types/genesis.pb.go | 438 - .../core/03-connection/types/genesis_test.go | 114 - x/ibc/core/03-connection/types/keys.go | 61 - x/ibc/core/03-connection/types/keys_test.go | 49 - x/ibc/core/03-connection/types/msgs.go | 354 - x/ibc/core/03-connection/types/msgs_test.go | 243 - x/ibc/core/03-connection/types/query.go | 70 - x/ibc/core/03-connection/types/query.pb.go | 2892 ------ x/ibc/core/03-connection/types/query.pb.gw.go | 602 -- x/ibc/core/03-connection/types/tx.pb.go | 2778 ------ x/ibc/core/03-connection/types/version.go | 220 - .../core/03-connection/types/version_test.go | 167 - x/ibc/core/04-channel/client/cli/cli.go | 58 - x/ibc/core/04-channel/client/cli/query.go | 457 - x/ibc/core/04-channel/client/cli/tx.go | 288 - x/ibc/core/04-channel/client/utils/utils.go | 301 - x/ibc/core/04-channel/genesis.go | 48 - x/ibc/core/04-channel/handler.go | 186 - x/ibc/core/04-channel/keeper/grpc_query.go | 486 - .../core/04-channel/keeper/grpc_query_test.go | 1376 --- x/ibc/core/04-channel/keeper/handshake.go | 496 - .../core/04-channel/keeper/handshake_test.go | 773 -- x/ibc/core/04-channel/keeper/keeper.go | 432 - x/ibc/core/04-channel/keeper/keeper_test.go | 329 - x/ibc/core/04-channel/keeper/packet.go | 528 -- x/ibc/core/04-channel/keeper/packet_test.go | 665 -- x/ibc/core/04-channel/keeper/timeout.go | 276 - x/ibc/core/04-channel/keeper/timeout_test.go | 351 - x/ibc/core/04-channel/module.go | 29 - x/ibc/core/04-channel/simulation/decoder.go | 48 - .../04-channel/simulation/decoder_test.go | 89 - x/ibc/core/04-channel/simulation/genesis.go | 13 - .../core/04-channel/types/acknowledgement.go | 50 - .../04-channel/types/acknowledgement_test.go | 63 - x/ibc/core/04-channel/types/channel.go | 127 - x/ibc/core/04-channel/types/channel.pb.go | 2268 ----- x/ibc/core/04-channel/types/channel_test.go | 59 - x/ibc/core/04-channel/types/codec.go | 51 - x/ibc/core/04-channel/types/errors.go | 28 - x/ibc/core/04-channel/types/events.go | 46 - .../core/04-channel/types/expected_keepers.go | 76 - x/ibc/core/04-channel/types/genesis.go | 156 - x/ibc/core/04-channel/types/genesis.pb.go | 1015 --- x/ibc/core/04-channel/types/genesis_test.go | 225 - x/ibc/core/04-channel/types/keys.go | 61 - x/ibc/core/04-channel/types/keys_test.go | 47 - x/ibc/core/04-channel/types/msgs.go | 652 -- x/ibc/core/04-channel/types/msgs_test.go | 446 - x/ibc/core/04-channel/types/packet.go | 112 - x/ibc/core/04-channel/types/packet_test.go | 53 - x/ibc/core/04-channel/types/query.go | 94 - x/ibc/core/04-channel/types/query.pb.go | 7991 ----------------- x/ibc/core/04-channel/types/query.pb.gw.go | 1792 ---- x/ibc/core/04-channel/types/tx.pb.go | 5259 ----------- x/ibc/core/05-port/keeper/keeper.go | 80 - x/ibc/core/05-port/keeper/keeper_test.go | 70 - x/ibc/core/05-port/types/errors.go | 13 - x/ibc/core/05-port/types/keys.go | 15 - x/ibc/core/05-port/types/module.go | 78 - x/ibc/core/05-port/types/router.go | 65 - x/ibc/core/05-port/types/utils.go | 17 - x/ibc/core/23-commitment/types/bench_test.go | 15 - x/ibc/core/23-commitment/types/codec.go | 43 - .../core/23-commitment/types/commitment.pb.go | 863 -- .../23-commitment/types/commitment_test.go | 37 - x/ibc/core/23-commitment/types/errors.go | 15 - x/ibc/core/23-commitment/types/merkle.go | 312 - x/ibc/core/23-commitment/types/merkle_test.go | 172 - x/ibc/core/23-commitment/types/utils.go | 28 - x/ibc/core/23-commitment/types/utils_test.go | 98 - x/ibc/core/24-host/errors.go | 15 - x/ibc/core/24-host/keys.go | 235 - x/ibc/core/24-host/parse.go | 79 - x/ibc/core/24-host/parse_test.go | 48 - x/ibc/core/24-host/validate.go | 114 - x/ibc/core/24-host/validate_test.go | 119 - x/ibc/core/client/cli/cli.go | 50 - x/ibc/core/client/query.go | 67 - x/ibc/core/exported/channel.go | 32 - x/ibc/core/exported/client.go | 223 - x/ibc/core/exported/commitment.go | 45 - x/ibc/core/exported/connection.go | 26 - x/ibc/core/genesis.go | 27 - x/ibc/core/genesis_test.go | 370 - x/ibc/core/handler.go | 98 - x/ibc/core/keeper/grpc_query.go | 129 - x/ibc/core/keeper/keeper.go | 66 - x/ibc/core/keeper/msg_server.go | 616 -- x/ibc/core/keeper/msg_server_test.go | 722 -- x/ibc/core/module.go | 198 - x/ibc/core/simulation/decoder.go | 32 - x/ibc/core/simulation/decoder_test.go | 80 - x/ibc/core/simulation/genesis.go | 63 - x/ibc/core/simulation/genesis_test.go | 49 - x/ibc/core/spec/01_concepts.md | 405 - x/ibc/core/spec/02_state.md | 28 - x/ibc/core/spec/03_state_transitions.md | 106 - x/ibc/core/spec/04_messages.md | 497 - x/ibc/core/spec/05_callbacks.md | 80 - x/ibc/core/spec/06_events.md | 241 - x/ibc/core/spec/07_params.md | 21 - x/ibc/core/spec/README.md | 26 - x/ibc/core/types/codec.go | 23 - x/ibc/core/types/genesis.go | 38 - x/ibc/core/types/genesis.pb.go | 440 - x/ibc/core/types/query.go | 26 - x/ibc/light-clients/06-solomachine/doc.go | 7 - x/ibc/light-clients/06-solomachine/module.go | 10 - .../06-solomachine/spec/01_concepts.md | 160 - .../06-solomachine/spec/02_state.md | 12 - .../spec/03_state_transitions.md | 39 - .../06-solomachine/spec/04_messages.md | 8 - .../06-solomachine/spec/README.md | 26 - .../06-solomachine/types/client_state.go | 491 - .../06-solomachine/types/client_state_test.go | 912 -- .../06-solomachine/types/codec.go | 130 - .../06-solomachine/types/codec_test.go | 190 - .../06-solomachine/types/consensus_state.go | 60 - .../types/consensus_state_test.go | 75 - .../06-solomachine/types/errors.go | 18 - .../06-solomachine/types/header.go | 67 - .../06-solomachine/types/header_test.go | 98 - .../06-solomachine/types/misbehaviour.go | 83 - .../types/misbehaviour_handle.go | 92 - .../types/misbehaviour_handle_test.go | 275 - .../06-solomachine/types/misbehaviour_test.go | 132 - .../06-solomachine/types/proof.go | 475 - .../06-solomachine/types/proof_test.go | 102 - .../06-solomachine/types/proposal_handle.go | 64 - .../types/proposal_handle_test.go | 88 - .../06-solomachine/types/solomachine.go | 43 - .../06-solomachine/types/solomachine.pb.go | 4118 --------- .../06-solomachine/types/solomachine_test.go | 113 - .../06-solomachine/types/update.go | 89 - .../06-solomachine/types/update_test.go | 181 - x/ibc/light-clients/07-tendermint/doc.go | 5 - x/ibc/light-clients/07-tendermint/module.go | 10 - .../07-tendermint/types/client_state.go | 532 -- .../07-tendermint/types/client_state_test.go | 779 -- .../07-tendermint/types/codec.go | 27 - .../07-tendermint/types/consensus_state.go | 55 - .../types/consensus_state_test.go | 69 - .../07-tendermint/types/errors.go | 25 - .../07-tendermint/types/fraction.go | 25 - .../07-tendermint/types/genesis.go | 21 - .../07-tendermint/types/genesis_test.go | 38 - .../07-tendermint/types/header.go | 83 - .../07-tendermint/types/header_test.go | 82 - .../07-tendermint/types/misbehaviour.go | 141 - .../types/misbehaviour_handle.go | 119 - .../types/misbehaviour_handle_test.go | 372 - .../07-tendermint/types/misbehaviour_test.go | 244 - .../07-tendermint/types/proposal_handle.go | 134 - .../types/proposal_handle_test.go | 387 - .../07-tendermint/types/store.go | 96 - .../07-tendermint/types/store_test.go | 113 - .../07-tendermint/types/tendermint.pb.go | 1914 ---- .../07-tendermint/types/tendermint_test.go | 95 - .../07-tendermint/types/update.go | 186 - .../07-tendermint/types/update_test.go | 281 - .../07-tendermint/types/upgrade.go | 156 - .../07-tendermint/types/upgrade_test.go | 474 - x/ibc/light-clients/09-localhost/doc.go | 5 - x/ibc/light-clients/09-localhost/module.go | 10 - .../09-localhost/types/client_state.go | 346 - .../09-localhost/types/client_state_test.go | 520 -- .../light-clients/09-localhost/types/codec.go | 15 - .../09-localhost/types/errors.go | 10 - .../light-clients/09-localhost/types/keys.go | 6 - .../09-localhost/types/localhost.pb.go | 369 - .../09-localhost/types/localhost_test.go | 43 - x/ibc/spec/README.md | 114 - x/ibc/testing/chain.go | 910 -- x/ibc/testing/chain_test.go | 47 - x/ibc/testing/coordinator.go | 700 -- x/ibc/testing/mock/README.md | 6 - x/ibc/testing/mock/doc.go | 9 - x/ibc/testing/mock/mock.go | 186 - x/ibc/testing/mock/privval.go | 50 - x/ibc/testing/mock/privval_test.go | 44 - x/ibc/testing/solomachine.go | 321 - x/ibc/testing/types.go | 44 - 385 files changed, 36 insertions(+), 106306 deletions(-) delete mode 100644 proto/ibc/applications/transfer/v1/genesis.proto delete mode 100644 proto/ibc/applications/transfer/v1/query.proto delete mode 100644 proto/ibc/applications/transfer/v1/transfer.proto delete mode 100644 proto/ibc/applications/transfer/v1/tx.proto delete mode 100644 proto/ibc/core/channel/v1/channel.proto delete mode 100644 proto/ibc/core/channel/v1/genesis.proto delete mode 100644 proto/ibc/core/channel/v1/query.proto delete mode 100644 proto/ibc/core/channel/v1/tx.proto delete mode 100644 proto/ibc/core/client/v1/client.proto delete mode 100644 proto/ibc/core/client/v1/genesis.proto delete mode 100644 proto/ibc/core/client/v1/query.proto delete mode 100644 proto/ibc/core/client/v1/tx.proto delete mode 100644 proto/ibc/core/commitment/v1/commitment.proto delete mode 100644 proto/ibc/core/connection/v1/connection.proto delete mode 100644 proto/ibc/core/connection/v1/genesis.proto delete mode 100644 proto/ibc/core/connection/v1/query.proto delete mode 100644 proto/ibc/core/connection/v1/tx.proto delete mode 100644 proto/ibc/core/types/v1/genesis.proto delete mode 100644 proto/ibc/lightclients/localhost/v1/localhost.proto delete mode 100644 proto/ibc/lightclients/solomachine/v1/solomachine.proto delete mode 100644 proto/ibc/lightclients/tendermint/v1/tendermint.proto delete mode 100644 x/ibc/applications/transfer/client/cli/cli.go delete mode 100644 x/ibc/applications/transfer/client/cli/query.go delete mode 100644 x/ibc/applications/transfer/client/cli/tx.go delete mode 100644 x/ibc/applications/transfer/handler.go delete mode 100644 x/ibc/applications/transfer/handler_test.go delete mode 100644 x/ibc/applications/transfer/keeper/MBT_README.md delete mode 100644 x/ibc/applications/transfer/keeper/encoding.go delete mode 100644 x/ibc/applications/transfer/keeper/genesis.go delete mode 100644 x/ibc/applications/transfer/keeper/genesis_test.go delete mode 100644 x/ibc/applications/transfer/keeper/grpc_query.go delete mode 100644 x/ibc/applications/transfer/keeper/grpc_query_test.go delete mode 100644 x/ibc/applications/transfer/keeper/keeper.go delete mode 100644 x/ibc/applications/transfer/keeper/keeper_test.go delete mode 100644 x/ibc/applications/transfer/keeper/mbt_relay_test.go delete mode 100644 x/ibc/applications/transfer/keeper/model_based_tests/Test5Packets.json delete mode 100644 x/ibc/applications/transfer/keeper/model_based_tests/Test5Packets.tla delete mode 100644 x/ibc/applications/transfer/keeper/model_based_tests/Test5PacketsAllDifferentPass.json delete mode 100644 x/ibc/applications/transfer/keeper/model_based_tests/Test5PacketsAllDifferentPass.tla delete mode 100644 x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvAcknowledgementErrorFail.json delete mode 100644 x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvAcknowledgementErrorFail.tla delete mode 100644 x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvAcknowledgementErrorPass.json delete mode 100644 x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvAcknowledgementErrorPass.tla delete mode 100644 x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvAcknowledgementResultFail.json delete mode 100644 x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvAcknowledgementResultFail.tla delete mode 100644 x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvAcknowledgementResultPass.json delete mode 100644 x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvAcknowledgementResultPass.tla delete mode 100644 x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvPacketFail.json delete mode 100644 x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvPacketFail.tla delete mode 100644 x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvPacketPass.json delete mode 100644 x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvPacketPass.tla delete mode 100644 x/ibc/applications/transfer/keeper/model_based_tests/TestOnTimeoutFail.json delete mode 100644 x/ibc/applications/transfer/keeper/model_based_tests/TestOnTimeoutFail.tla delete mode 100644 x/ibc/applications/transfer/keeper/model_based_tests/TestOnTimeoutPass.json delete mode 100644 x/ibc/applications/transfer/keeper/model_based_tests/TestOnTimeoutPass.tla delete mode 100644 x/ibc/applications/transfer/keeper/model_based_tests/TestSendTransferFail.json delete mode 100644 x/ibc/applications/transfer/keeper/model_based_tests/TestSendTransferFail.tla delete mode 100644 x/ibc/applications/transfer/keeper/model_based_tests/TestSendTransferPass.json delete mode 100644 x/ibc/applications/transfer/keeper/model_based_tests/TestSendTransferPass.tla delete mode 100644 x/ibc/applications/transfer/keeper/model_based_tests/TestUnescrowTokens.json delete mode 100644 x/ibc/applications/transfer/keeper/model_based_tests/TestUnescrowTokens.tla delete mode 100644 x/ibc/applications/transfer/keeper/msg_server.go delete mode 100644 x/ibc/applications/transfer/keeper/params.go delete mode 100644 x/ibc/applications/transfer/keeper/params_test.go delete mode 100644 x/ibc/applications/transfer/keeper/relay.go delete mode 100644 x/ibc/applications/transfer/keeper/relay_model/account.tla delete mode 100644 x/ibc/applications/transfer/keeper/relay_model/account_record.tla delete mode 100644 x/ibc/applications/transfer/keeper/relay_model/apalache-to-relay-test.json delete mode 100644 x/ibc/applications/transfer/keeper/relay_model/apalache-to-relay-test2.json delete mode 100644 x/ibc/applications/transfer/keeper/relay_model/denom.tla delete mode 100644 x/ibc/applications/transfer/keeper/relay_model/denom_record.tla delete mode 100644 x/ibc/applications/transfer/keeper/relay_model/denom_record2.tla delete mode 100644 x/ibc/applications/transfer/keeper/relay_model/denom_sequence.tla delete mode 100644 x/ibc/applications/transfer/keeper/relay_model/identifiers.tla delete mode 100644 x/ibc/applications/transfer/keeper/relay_model/relay.tla delete mode 100644 x/ibc/applications/transfer/keeper/relay_model/relay_tests.tla delete mode 100644 x/ibc/applications/transfer/keeper/relay_test.go delete mode 100644 x/ibc/applications/transfer/module.go delete mode 100644 x/ibc/applications/transfer/module_test.go delete mode 100644 x/ibc/applications/transfer/simulation/decoder.go delete mode 100644 x/ibc/applications/transfer/simulation/decoder_test.go delete mode 100644 x/ibc/applications/transfer/simulation/genesis.go delete mode 100644 x/ibc/applications/transfer/simulation/genesis_test.go delete mode 100644 x/ibc/applications/transfer/simulation/params.go delete mode 100644 x/ibc/applications/transfer/simulation/params_test.go delete mode 100644 x/ibc/applications/transfer/spec/01_concepts.md delete mode 100644 x/ibc/applications/transfer/spec/02_state.md delete mode 100644 x/ibc/applications/transfer/spec/03_state_transitions.md delete mode 100644 x/ibc/applications/transfer/spec/04_messages.md delete mode 100644 x/ibc/applications/transfer/spec/05_events.md delete mode 100644 x/ibc/applications/transfer/spec/06_metrics.md delete mode 100644 x/ibc/applications/transfer/spec/07_params.md delete mode 100644 x/ibc/applications/transfer/spec/README.md delete mode 100644 x/ibc/applications/transfer/types/codec.go delete mode 100644 x/ibc/applications/transfer/types/coin.go delete mode 100644 x/ibc/applications/transfer/types/errors.go delete mode 100644 x/ibc/applications/transfer/types/events.go delete mode 100644 x/ibc/applications/transfer/types/expected_keepers.go delete mode 100644 x/ibc/applications/transfer/types/genesis.go delete mode 100644 x/ibc/applications/transfer/types/genesis.pb.go delete mode 100644 x/ibc/applications/transfer/types/genesis_test.go delete mode 100644 x/ibc/applications/transfer/types/keys.go delete mode 100644 x/ibc/applications/transfer/types/keys_test.go delete mode 100644 x/ibc/applications/transfer/types/msgs.go delete mode 100644 x/ibc/applications/transfer/types/msgs_test.go delete mode 100644 x/ibc/applications/transfer/types/packet.go delete mode 100644 x/ibc/applications/transfer/types/packet_test.go delete mode 100644 x/ibc/applications/transfer/types/params.go delete mode 100644 x/ibc/applications/transfer/types/params_test.go delete mode 100644 x/ibc/applications/transfer/types/query.pb.go delete mode 100644 x/ibc/applications/transfer/types/query.pb.gw.go delete mode 100644 x/ibc/applications/transfer/types/trace.go delete mode 100644 x/ibc/applications/transfer/types/trace_test.go delete mode 100644 x/ibc/applications/transfer/types/transfer.pb.go delete mode 100644 x/ibc/applications/transfer/types/tx.pb.go delete mode 100644 x/ibc/core/02-client/abci.go delete mode 100644 x/ibc/core/02-client/abci_test.go delete mode 100644 x/ibc/core/02-client/client/cli/cli.go delete mode 100644 x/ibc/core/02-client/client/cli/query.go delete mode 100644 x/ibc/core/02-client/client/cli/tx.go delete mode 100644 x/ibc/core/02-client/client/proposal_handler.go delete mode 100644 x/ibc/core/02-client/client/utils/utils.go delete mode 100644 x/ibc/core/02-client/doc.go delete mode 100644 x/ibc/core/02-client/genesis.go delete mode 100644 x/ibc/core/02-client/keeper/client.go delete mode 100644 x/ibc/core/02-client/keeper/client_test.go delete mode 100644 x/ibc/core/02-client/keeper/encoding.go delete mode 100644 x/ibc/core/02-client/keeper/grpc_query.go delete mode 100644 x/ibc/core/02-client/keeper/grpc_query_test.go delete mode 100644 x/ibc/core/02-client/keeper/keeper.go delete mode 100644 x/ibc/core/02-client/keeper/keeper_test.go delete mode 100644 x/ibc/core/02-client/keeper/params.go delete mode 100644 x/ibc/core/02-client/keeper/params_test.go delete mode 100644 x/ibc/core/02-client/keeper/proposal.go delete mode 100644 x/ibc/core/02-client/keeper/proposal_test.go delete mode 100644 x/ibc/core/02-client/module.go delete mode 100644 x/ibc/core/02-client/proposal_handler.go delete mode 100644 x/ibc/core/02-client/proposal_handler_test.go delete mode 100644 x/ibc/core/02-client/simulation/decoder.go delete mode 100644 x/ibc/core/02-client/simulation/decoder_test.go delete mode 100644 x/ibc/core/02-client/simulation/genesis.go delete mode 100644 x/ibc/core/02-client/types/client.go delete mode 100644 x/ibc/core/02-client/types/client.pb.go delete mode 100644 x/ibc/core/02-client/types/client_test.go delete mode 100644 x/ibc/core/02-client/types/codec.go delete mode 100644 x/ibc/core/02-client/types/codec_test.go delete mode 100644 x/ibc/core/02-client/types/encoding.go delete mode 100644 x/ibc/core/02-client/types/encoding_test.go delete mode 100644 x/ibc/core/02-client/types/errors.go delete mode 100644 x/ibc/core/02-client/types/events.go delete mode 100644 x/ibc/core/02-client/types/expected_keepers.go delete mode 100644 x/ibc/core/02-client/types/genesis.go delete mode 100644 x/ibc/core/02-client/types/genesis.pb.go delete mode 100644 x/ibc/core/02-client/types/genesis_test.go delete mode 100644 x/ibc/core/02-client/types/height.go delete mode 100644 x/ibc/core/02-client/types/height_test.go delete mode 100644 x/ibc/core/02-client/types/keys.go delete mode 100644 x/ibc/core/02-client/types/keys_test.go delete mode 100644 x/ibc/core/02-client/types/msgs.go delete mode 100644 x/ibc/core/02-client/types/msgs_test.go delete mode 100644 x/ibc/core/02-client/types/params.go delete mode 100644 x/ibc/core/02-client/types/params_test.go delete mode 100644 x/ibc/core/02-client/types/proposal.go delete mode 100644 x/ibc/core/02-client/types/proposal_test.go delete mode 100644 x/ibc/core/02-client/types/query.go delete mode 100644 x/ibc/core/02-client/types/query.pb.go delete mode 100644 x/ibc/core/02-client/types/query.pb.gw.go delete mode 100644 x/ibc/core/02-client/types/tx.pb.go delete mode 100644 x/ibc/core/03-connection/client/cli/cli.go delete mode 100644 x/ibc/core/03-connection/client/cli/query.go delete mode 100644 x/ibc/core/03-connection/client/cli/tx.go delete mode 100644 x/ibc/core/03-connection/client/utils/utils.go delete mode 100644 x/ibc/core/03-connection/genesis.go delete mode 100644 x/ibc/core/03-connection/keeper/grpc_query.go delete mode 100644 x/ibc/core/03-connection/keeper/grpc_query_test.go delete mode 100644 x/ibc/core/03-connection/keeper/handshake.go delete mode 100644 x/ibc/core/03-connection/keeper/handshake_test.go delete mode 100644 x/ibc/core/03-connection/keeper/keeper.go delete mode 100644 x/ibc/core/03-connection/keeper/keeper_test.go delete mode 100644 x/ibc/core/03-connection/keeper/verify.go delete mode 100644 x/ibc/core/03-connection/keeper/verify_test.go delete mode 100644 x/ibc/core/03-connection/module.go delete mode 100644 x/ibc/core/03-connection/simulation/decoder.go delete mode 100644 x/ibc/core/03-connection/simulation/decoder_test.go delete mode 100644 x/ibc/core/03-connection/simulation/genesis.go delete mode 100644 x/ibc/core/03-connection/types/codec.go delete mode 100644 x/ibc/core/03-connection/types/connection.go delete mode 100644 x/ibc/core/03-connection/types/connection.pb.go delete mode 100644 x/ibc/core/03-connection/types/connection_test.go delete mode 100644 x/ibc/core/03-connection/types/errors.go delete mode 100644 x/ibc/core/03-connection/types/events.go delete mode 100644 x/ibc/core/03-connection/types/expected_keepers.go delete mode 100644 x/ibc/core/03-connection/types/genesis.go delete mode 100644 x/ibc/core/03-connection/types/genesis.pb.go delete mode 100644 x/ibc/core/03-connection/types/genesis_test.go delete mode 100644 x/ibc/core/03-connection/types/keys.go delete mode 100644 x/ibc/core/03-connection/types/keys_test.go delete mode 100644 x/ibc/core/03-connection/types/msgs.go delete mode 100644 x/ibc/core/03-connection/types/msgs_test.go delete mode 100644 x/ibc/core/03-connection/types/query.go delete mode 100644 x/ibc/core/03-connection/types/query.pb.go delete mode 100644 x/ibc/core/03-connection/types/query.pb.gw.go delete mode 100644 x/ibc/core/03-connection/types/tx.pb.go delete mode 100644 x/ibc/core/03-connection/types/version.go delete mode 100644 x/ibc/core/03-connection/types/version_test.go delete mode 100644 x/ibc/core/04-channel/client/cli/cli.go delete mode 100644 x/ibc/core/04-channel/client/cli/query.go delete mode 100644 x/ibc/core/04-channel/client/cli/tx.go delete mode 100644 x/ibc/core/04-channel/client/utils/utils.go delete mode 100644 x/ibc/core/04-channel/genesis.go delete mode 100644 x/ibc/core/04-channel/handler.go delete mode 100644 x/ibc/core/04-channel/keeper/grpc_query.go delete mode 100644 x/ibc/core/04-channel/keeper/grpc_query_test.go delete mode 100644 x/ibc/core/04-channel/keeper/handshake.go delete mode 100644 x/ibc/core/04-channel/keeper/handshake_test.go delete mode 100644 x/ibc/core/04-channel/keeper/keeper.go delete mode 100644 x/ibc/core/04-channel/keeper/keeper_test.go delete mode 100644 x/ibc/core/04-channel/keeper/packet.go delete mode 100644 x/ibc/core/04-channel/keeper/packet_test.go delete mode 100644 x/ibc/core/04-channel/keeper/timeout.go delete mode 100644 x/ibc/core/04-channel/keeper/timeout_test.go delete mode 100644 x/ibc/core/04-channel/module.go delete mode 100644 x/ibc/core/04-channel/simulation/decoder.go delete mode 100644 x/ibc/core/04-channel/simulation/decoder_test.go delete mode 100644 x/ibc/core/04-channel/simulation/genesis.go delete mode 100644 x/ibc/core/04-channel/types/acknowledgement.go delete mode 100644 x/ibc/core/04-channel/types/acknowledgement_test.go delete mode 100644 x/ibc/core/04-channel/types/channel.go delete mode 100644 x/ibc/core/04-channel/types/channel.pb.go delete mode 100644 x/ibc/core/04-channel/types/channel_test.go delete mode 100644 x/ibc/core/04-channel/types/codec.go delete mode 100644 x/ibc/core/04-channel/types/errors.go delete mode 100644 x/ibc/core/04-channel/types/events.go delete mode 100644 x/ibc/core/04-channel/types/expected_keepers.go delete mode 100644 x/ibc/core/04-channel/types/genesis.go delete mode 100644 x/ibc/core/04-channel/types/genesis.pb.go delete mode 100644 x/ibc/core/04-channel/types/genesis_test.go delete mode 100644 x/ibc/core/04-channel/types/keys.go delete mode 100644 x/ibc/core/04-channel/types/keys_test.go delete mode 100644 x/ibc/core/04-channel/types/msgs.go delete mode 100644 x/ibc/core/04-channel/types/msgs_test.go delete mode 100644 x/ibc/core/04-channel/types/packet.go delete mode 100644 x/ibc/core/04-channel/types/packet_test.go delete mode 100644 x/ibc/core/04-channel/types/query.go delete mode 100644 x/ibc/core/04-channel/types/query.pb.go delete mode 100644 x/ibc/core/04-channel/types/query.pb.gw.go delete mode 100644 x/ibc/core/04-channel/types/tx.pb.go delete mode 100644 x/ibc/core/05-port/keeper/keeper.go delete mode 100644 x/ibc/core/05-port/keeper/keeper_test.go delete mode 100644 x/ibc/core/05-port/types/errors.go delete mode 100644 x/ibc/core/05-port/types/keys.go delete mode 100644 x/ibc/core/05-port/types/module.go delete mode 100644 x/ibc/core/05-port/types/router.go delete mode 100644 x/ibc/core/05-port/types/utils.go delete mode 100644 x/ibc/core/23-commitment/types/bench_test.go delete mode 100644 x/ibc/core/23-commitment/types/codec.go delete mode 100644 x/ibc/core/23-commitment/types/commitment.pb.go delete mode 100644 x/ibc/core/23-commitment/types/commitment_test.go delete mode 100644 x/ibc/core/23-commitment/types/errors.go delete mode 100644 x/ibc/core/23-commitment/types/merkle.go delete mode 100644 x/ibc/core/23-commitment/types/merkle_test.go delete mode 100644 x/ibc/core/23-commitment/types/utils.go delete mode 100644 x/ibc/core/23-commitment/types/utils_test.go delete mode 100644 x/ibc/core/24-host/errors.go delete mode 100644 x/ibc/core/24-host/keys.go delete mode 100644 x/ibc/core/24-host/parse.go delete mode 100644 x/ibc/core/24-host/parse_test.go delete mode 100644 x/ibc/core/24-host/validate.go delete mode 100644 x/ibc/core/24-host/validate_test.go delete mode 100644 x/ibc/core/client/cli/cli.go delete mode 100644 x/ibc/core/client/query.go delete mode 100644 x/ibc/core/exported/channel.go delete mode 100644 x/ibc/core/exported/client.go delete mode 100644 x/ibc/core/exported/commitment.go delete mode 100644 x/ibc/core/exported/connection.go delete mode 100644 x/ibc/core/genesis.go delete mode 100644 x/ibc/core/genesis_test.go delete mode 100644 x/ibc/core/handler.go delete mode 100644 x/ibc/core/keeper/grpc_query.go delete mode 100644 x/ibc/core/keeper/keeper.go delete mode 100644 x/ibc/core/keeper/msg_server.go delete mode 100644 x/ibc/core/keeper/msg_server_test.go delete mode 100644 x/ibc/core/module.go delete mode 100644 x/ibc/core/simulation/decoder.go delete mode 100644 x/ibc/core/simulation/decoder_test.go delete mode 100644 x/ibc/core/simulation/genesis.go delete mode 100644 x/ibc/core/simulation/genesis_test.go delete mode 100644 x/ibc/core/spec/01_concepts.md delete mode 100644 x/ibc/core/spec/02_state.md delete mode 100644 x/ibc/core/spec/03_state_transitions.md delete mode 100644 x/ibc/core/spec/04_messages.md delete mode 100644 x/ibc/core/spec/05_callbacks.md delete mode 100644 x/ibc/core/spec/06_events.md delete mode 100644 x/ibc/core/spec/07_params.md delete mode 100644 x/ibc/core/spec/README.md delete mode 100644 x/ibc/core/types/codec.go delete mode 100644 x/ibc/core/types/genesis.go delete mode 100644 x/ibc/core/types/genesis.pb.go delete mode 100644 x/ibc/core/types/query.go delete mode 100644 x/ibc/light-clients/06-solomachine/doc.go delete mode 100644 x/ibc/light-clients/06-solomachine/module.go delete mode 100644 x/ibc/light-clients/06-solomachine/spec/01_concepts.md delete mode 100644 x/ibc/light-clients/06-solomachine/spec/02_state.md delete mode 100644 x/ibc/light-clients/06-solomachine/spec/03_state_transitions.md delete mode 100644 x/ibc/light-clients/06-solomachine/spec/04_messages.md delete mode 100644 x/ibc/light-clients/06-solomachine/spec/README.md delete mode 100644 x/ibc/light-clients/06-solomachine/types/client_state.go delete mode 100644 x/ibc/light-clients/06-solomachine/types/client_state_test.go delete mode 100644 x/ibc/light-clients/06-solomachine/types/codec.go delete mode 100644 x/ibc/light-clients/06-solomachine/types/codec_test.go delete mode 100644 x/ibc/light-clients/06-solomachine/types/consensus_state.go delete mode 100644 x/ibc/light-clients/06-solomachine/types/consensus_state_test.go delete mode 100644 x/ibc/light-clients/06-solomachine/types/errors.go delete mode 100644 x/ibc/light-clients/06-solomachine/types/header.go delete mode 100644 x/ibc/light-clients/06-solomachine/types/header_test.go delete mode 100644 x/ibc/light-clients/06-solomachine/types/misbehaviour.go delete mode 100644 x/ibc/light-clients/06-solomachine/types/misbehaviour_handle.go delete mode 100644 x/ibc/light-clients/06-solomachine/types/misbehaviour_handle_test.go delete mode 100644 x/ibc/light-clients/06-solomachine/types/misbehaviour_test.go delete mode 100644 x/ibc/light-clients/06-solomachine/types/proof.go delete mode 100644 x/ibc/light-clients/06-solomachine/types/proof_test.go delete mode 100644 x/ibc/light-clients/06-solomachine/types/proposal_handle.go delete mode 100644 x/ibc/light-clients/06-solomachine/types/proposal_handle_test.go delete mode 100644 x/ibc/light-clients/06-solomachine/types/solomachine.go delete mode 100644 x/ibc/light-clients/06-solomachine/types/solomachine.pb.go delete mode 100644 x/ibc/light-clients/06-solomachine/types/solomachine_test.go delete mode 100644 x/ibc/light-clients/06-solomachine/types/update.go delete mode 100644 x/ibc/light-clients/06-solomachine/types/update_test.go delete mode 100644 x/ibc/light-clients/07-tendermint/doc.go delete mode 100644 x/ibc/light-clients/07-tendermint/module.go delete mode 100644 x/ibc/light-clients/07-tendermint/types/client_state.go delete mode 100644 x/ibc/light-clients/07-tendermint/types/client_state_test.go delete mode 100644 x/ibc/light-clients/07-tendermint/types/codec.go delete mode 100644 x/ibc/light-clients/07-tendermint/types/consensus_state.go delete mode 100644 x/ibc/light-clients/07-tendermint/types/consensus_state_test.go delete mode 100644 x/ibc/light-clients/07-tendermint/types/errors.go delete mode 100644 x/ibc/light-clients/07-tendermint/types/fraction.go delete mode 100644 x/ibc/light-clients/07-tendermint/types/genesis.go delete mode 100644 x/ibc/light-clients/07-tendermint/types/genesis_test.go delete mode 100644 x/ibc/light-clients/07-tendermint/types/header.go delete mode 100644 x/ibc/light-clients/07-tendermint/types/header_test.go delete mode 100644 x/ibc/light-clients/07-tendermint/types/misbehaviour.go delete mode 100644 x/ibc/light-clients/07-tendermint/types/misbehaviour_handle.go delete mode 100644 x/ibc/light-clients/07-tendermint/types/misbehaviour_handle_test.go delete mode 100644 x/ibc/light-clients/07-tendermint/types/misbehaviour_test.go delete mode 100644 x/ibc/light-clients/07-tendermint/types/proposal_handle.go delete mode 100644 x/ibc/light-clients/07-tendermint/types/proposal_handle_test.go delete mode 100644 x/ibc/light-clients/07-tendermint/types/store.go delete mode 100644 x/ibc/light-clients/07-tendermint/types/store_test.go delete mode 100644 x/ibc/light-clients/07-tendermint/types/tendermint.pb.go delete mode 100644 x/ibc/light-clients/07-tendermint/types/tendermint_test.go delete mode 100644 x/ibc/light-clients/07-tendermint/types/update.go delete mode 100644 x/ibc/light-clients/07-tendermint/types/update_test.go delete mode 100644 x/ibc/light-clients/07-tendermint/types/upgrade.go delete mode 100644 x/ibc/light-clients/07-tendermint/types/upgrade_test.go delete mode 100644 x/ibc/light-clients/09-localhost/doc.go delete mode 100644 x/ibc/light-clients/09-localhost/module.go delete mode 100644 x/ibc/light-clients/09-localhost/types/client_state.go delete mode 100644 x/ibc/light-clients/09-localhost/types/client_state_test.go delete mode 100644 x/ibc/light-clients/09-localhost/types/codec.go delete mode 100644 x/ibc/light-clients/09-localhost/types/errors.go delete mode 100644 x/ibc/light-clients/09-localhost/types/keys.go delete mode 100644 x/ibc/light-clients/09-localhost/types/localhost.pb.go delete mode 100644 x/ibc/light-clients/09-localhost/types/localhost_test.go delete mode 100644 x/ibc/spec/README.md delete mode 100644 x/ibc/testing/chain.go delete mode 100644 x/ibc/testing/chain_test.go delete mode 100644 x/ibc/testing/coordinator.go delete mode 100644 x/ibc/testing/mock/README.md delete mode 100644 x/ibc/testing/mock/doc.go delete mode 100644 x/ibc/testing/mock/mock.go delete mode 100644 x/ibc/testing/mock/privval.go delete mode 100644 x/ibc/testing/mock/privval_test.go delete mode 100644 x/ibc/testing/solomachine.go delete mode 100644 x/ibc/testing/types.go diff --git a/README.md b/README.md index 39904e8d516a..b1098bd77b99 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,10 @@ For more, please go to the [Cosmos SDK Docs](./docs/). The Cosmos Hub application, `gaia`, has moved to its [own repository](https://github.com/cosmos/gaia). Go there to join the Cosmos Hub mainnet and more. +## Interblockchain Communication (IBC) + +The IBC module for the SDK has moved to its [own repository](https://github.com/cosmos/ibc-go). Go there to build and integrate with the IBC module. + ## Starport If you are starting a new app or a new module you can use [Starport](https://github.com/tendermint/starport) to help you get started and speed up development. If you have any questions or find a bug, feel free to open an issue in the repo. diff --git a/docs/core/proto-docs.md b/docs/core/proto-docs.md index a9d2152f32d6..0daa9e3afca6 100644 --- a/docs/core/proto-docs.md +++ b/docs/core/proto-docs.md @@ -546,219 +546,6 @@ - [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) - -- [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) - - [QueryDenomTraceResponse](#ibc.applications.transfer.v1.QueryDenomTraceResponse) - - [QueryDenomTracesRequest](#ibc.applications.transfer.v1.QueryDenomTracesRequest) - - [QueryDenomTracesResponse](#ibc.applications.transfer.v1.QueryDenomTracesResponse) - - [QueryParamsRequest](#ibc.applications.transfer.v1.QueryParamsRequest) - - [QueryParamsResponse](#ibc.applications.transfer.v1.QueryParamsResponse) - - - [Query](#ibc.applications.transfer.v1.Query) - -- [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) - - [UpgradeProposal](#ibc.core.client.v1.UpgradeProposal) - -- [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) - - [Channel](#ibc.core.channel.v1.Channel) - - [Counterparty](#ibc.core.channel.v1.Counterparty) - - [IdentifiedChannel](#ibc.core.channel.v1.IdentifiedChannel) - - [Packet](#ibc.core.channel.v1.Packet) - - [PacketState](#ibc.core.channel.v1.PacketState) - - - [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) - - [QueryChannelConsensusStateRequest](#ibc.core.channel.v1.QueryChannelConsensusStateRequest) - - [QueryChannelConsensusStateResponse](#ibc.core.channel.v1.QueryChannelConsensusStateResponse) - - [QueryChannelRequest](#ibc.core.channel.v1.QueryChannelRequest) - - [QueryChannelResponse](#ibc.core.channel.v1.QueryChannelResponse) - - [QueryChannelsRequest](#ibc.core.channel.v1.QueryChannelsRequest) - - [QueryChannelsResponse](#ibc.core.channel.v1.QueryChannelsResponse) - - [QueryConnectionChannelsRequest](#ibc.core.channel.v1.QueryConnectionChannelsRequest) - - [QueryConnectionChannelsResponse](#ibc.core.channel.v1.QueryConnectionChannelsResponse) - - [QueryNextSequenceReceiveRequest](#ibc.core.channel.v1.QueryNextSequenceReceiveRequest) - - [QueryNextSequenceReceiveResponse](#ibc.core.channel.v1.QueryNextSequenceReceiveResponse) - - [QueryPacketAcknowledgementRequest](#ibc.core.channel.v1.QueryPacketAcknowledgementRequest) - - [QueryPacketAcknowledgementResponse](#ibc.core.channel.v1.QueryPacketAcknowledgementResponse) - - [QueryPacketAcknowledgementsRequest](#ibc.core.channel.v1.QueryPacketAcknowledgementsRequest) - - [QueryPacketAcknowledgementsResponse](#ibc.core.channel.v1.QueryPacketAcknowledgementsResponse) - - [QueryPacketCommitmentRequest](#ibc.core.channel.v1.QueryPacketCommitmentRequest) - - [QueryPacketCommitmentResponse](#ibc.core.channel.v1.QueryPacketCommitmentResponse) - - [QueryPacketCommitmentsRequest](#ibc.core.channel.v1.QueryPacketCommitmentsRequest) - - [QueryPacketCommitmentsResponse](#ibc.core.channel.v1.QueryPacketCommitmentsResponse) - - [QueryPacketReceiptRequest](#ibc.core.channel.v1.QueryPacketReceiptRequest) - - [QueryPacketReceiptResponse](#ibc.core.channel.v1.QueryPacketReceiptResponse) - - [QueryUnreceivedAcksRequest](#ibc.core.channel.v1.QueryUnreceivedAcksRequest) - - [QueryUnreceivedAcksResponse](#ibc.core.channel.v1.QueryUnreceivedAcksResponse) - - [QueryUnreceivedPacketsRequest](#ibc.core.channel.v1.QueryUnreceivedPacketsRequest) - - [QueryUnreceivedPacketsResponse](#ibc.core.channel.v1.QueryUnreceivedPacketsResponse) - - - [Query](#ibc.core.channel.v1.Query) - -- [ibc/core/channel/v1/tx.proto](#ibc/core/channel/v1/tx.proto) - - [MsgAcknowledgement](#ibc.core.channel.v1.MsgAcknowledgement) - - [MsgAcknowledgementResponse](#ibc.core.channel.v1.MsgAcknowledgementResponse) - - [MsgChannelCloseConfirm](#ibc.core.channel.v1.MsgChannelCloseConfirm) - - [MsgChannelCloseConfirmResponse](#ibc.core.channel.v1.MsgChannelCloseConfirmResponse) - - [MsgChannelCloseInit](#ibc.core.channel.v1.MsgChannelCloseInit) - - [MsgChannelCloseInitResponse](#ibc.core.channel.v1.MsgChannelCloseInitResponse) - - [MsgChannelOpenAck](#ibc.core.channel.v1.MsgChannelOpenAck) - - [MsgChannelOpenAckResponse](#ibc.core.channel.v1.MsgChannelOpenAckResponse) - - [MsgChannelOpenConfirm](#ibc.core.channel.v1.MsgChannelOpenConfirm) - - [MsgChannelOpenConfirmResponse](#ibc.core.channel.v1.MsgChannelOpenConfirmResponse) - - [MsgChannelOpenInit](#ibc.core.channel.v1.MsgChannelOpenInit) - - [MsgChannelOpenInitResponse](#ibc.core.channel.v1.MsgChannelOpenInitResponse) - - [MsgChannelOpenTry](#ibc.core.channel.v1.MsgChannelOpenTry) - - [MsgChannelOpenTryResponse](#ibc.core.channel.v1.MsgChannelOpenTryResponse) - - [MsgRecvPacket](#ibc.core.channel.v1.MsgRecvPacket) - - [MsgRecvPacketResponse](#ibc.core.channel.v1.MsgRecvPacketResponse) - - [MsgTimeout](#ibc.core.channel.v1.MsgTimeout) - - [MsgTimeoutOnClose](#ibc.core.channel.v1.MsgTimeoutOnClose) - - [MsgTimeoutOnCloseResponse](#ibc.core.channel.v1.MsgTimeoutOnCloseResponse) - - [MsgTimeoutResponse](#ibc.core.channel.v1.MsgTimeoutResponse) - - - [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) - - [QueryUpgradedClientStateRequest](#ibc.core.client.v1.QueryUpgradedClientStateRequest) - - [QueryUpgradedClientStateResponse](#ibc.core.client.v1.QueryUpgradedClientStateResponse) - - - [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) - - [MerklePrefix](#ibc.core.commitment.v1.MerklePrefix) - - [MerkleProof](#ibc.core.commitment.v1.MerkleProof) - - [MerkleRoot](#ibc.core.commitment.v1.MerkleRoot) - -- [ibc/core/connection/v1/connection.proto](#ibc/core/connection/v1/connection.proto) - - [ClientPaths](#ibc.core.connection.v1.ClientPaths) - - [ConnectionEnd](#ibc.core.connection.v1.ConnectionEnd) - - [ConnectionPaths](#ibc.core.connection.v1.ConnectionPaths) - - [Counterparty](#ibc.core.connection.v1.Counterparty) - - [IdentifiedConnection](#ibc.core.connection.v1.IdentifiedConnection) - - [Version](#ibc.core.connection.v1.Version) - - - [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) - - [QueryConnectionClientStateRequest](#ibc.core.connection.v1.QueryConnectionClientStateRequest) - - [QueryConnectionClientStateResponse](#ibc.core.connection.v1.QueryConnectionClientStateResponse) - - [QueryConnectionConsensusStateRequest](#ibc.core.connection.v1.QueryConnectionConsensusStateRequest) - - [QueryConnectionConsensusStateResponse](#ibc.core.connection.v1.QueryConnectionConsensusStateResponse) - - [QueryConnectionRequest](#ibc.core.connection.v1.QueryConnectionRequest) - - [QueryConnectionResponse](#ibc.core.connection.v1.QueryConnectionResponse) - - [QueryConnectionsRequest](#ibc.core.connection.v1.QueryConnectionsRequest) - - [QueryConnectionsResponse](#ibc.core.connection.v1.QueryConnectionsResponse) - - - [Query](#ibc.core.connection.v1.Query) - -- [ibc/core/connection/v1/tx.proto](#ibc/core/connection/v1/tx.proto) - - [MsgConnectionOpenAck](#ibc.core.connection.v1.MsgConnectionOpenAck) - - [MsgConnectionOpenAckResponse](#ibc.core.connection.v1.MsgConnectionOpenAckResponse) - - [MsgConnectionOpenConfirm](#ibc.core.connection.v1.MsgConnectionOpenConfirm) - - [MsgConnectionOpenConfirmResponse](#ibc.core.connection.v1.MsgConnectionOpenConfirmResponse) - - [MsgConnectionOpenInit](#ibc.core.connection.v1.MsgConnectionOpenInit) - - [MsgConnectionOpenInitResponse](#ibc.core.connection.v1.MsgConnectionOpenInitResponse) - - [MsgConnectionOpenTry](#ibc.core.connection.v1.MsgConnectionOpenTry) - - [MsgConnectionOpenTryResponse](#ibc.core.connection.v1.MsgConnectionOpenTryResponse) - - - [Msg](#ibc.core.connection.v1.Msg) - -- [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/solomachine/v1/solomachine.proto](#ibc/lightclients/solomachine/v1/solomachine.proto) - - [ChannelStateData](#ibc.lightclients.solomachine.v1.ChannelStateData) - - [ClientState](#ibc.lightclients.solomachine.v1.ClientState) - - [ClientStateData](#ibc.lightclients.solomachine.v1.ClientStateData) - - [ConnectionStateData](#ibc.lightclients.solomachine.v1.ConnectionStateData) - - [ConsensusState](#ibc.lightclients.solomachine.v1.ConsensusState) - - [ConsensusStateData](#ibc.lightclients.solomachine.v1.ConsensusStateData) - - [Header](#ibc.lightclients.solomachine.v1.Header) - - [HeaderData](#ibc.lightclients.solomachine.v1.HeaderData) - - [Misbehaviour](#ibc.lightclients.solomachine.v1.Misbehaviour) - - [NextSequenceRecvData](#ibc.lightclients.solomachine.v1.NextSequenceRecvData) - - [PacketAcknowledgementData](#ibc.lightclients.solomachine.v1.PacketAcknowledgementData) - - [PacketCommitmentData](#ibc.lightclients.solomachine.v1.PacketCommitmentData) - - [PacketReceiptAbsenceData](#ibc.lightclients.solomachine.v1.PacketReceiptAbsenceData) - - [SignBytes](#ibc.lightclients.solomachine.v1.SignBytes) - - [SignatureAndData](#ibc.lightclients.solomachine.v1.SignatureAndData) - - [TimestampedSignatureData](#ibc.lightclients.solomachine.v1.TimestampedSignatureData) - - - [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) @@ -7874,3074 +7661,23 @@ periodically vests by unlocking coins during each specified period. - -

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) | | | - - - - - - - - - - - - - - - - -

Top

- -## ibc/applications/transfer/v1/query.proto - - - - - -### QueryDenomTraceRequest -QueryDenomTraceRequest is the request type for the Query/DenomTrace RPC -method - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `hash` | [string](#string) | | hash (in hex format) of the denomination trace information. | - - - - - - - - -### QueryDenomTraceResponse -QueryDenomTraceResponse is the response type for the Query/DenomTrace RPC -method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `denom_trace` | [DenomTrace](#ibc.applications.transfer.v1.DenomTrace) | | denom_trace returns the requested denomination trace information. | - - - - - - - - -### QueryDenomTracesRequest -QueryConnectionsRequest is the request type for the Query/DenomTraces 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. | - - - - - - - - -### QueryDenomTracesResponse -QueryConnectionsResponse is the response type for the Query/DenomTraces RPC -method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `denom_traces` | [DenomTrace](#ibc.applications.transfer.v1.DenomTrace) | repeated | denom_traces returns all denominations trace information. | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | - - - - - - - - -### QueryParamsRequest -QueryParamsRequest is the request type for the Query/Params RPC method. - - - - - - - - -### QueryParamsResponse -QueryParamsResponse is the response type for the Query/Params RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `params` | [Params](#ibc.applications.transfer.v1.Params) | | params defines the parameters of the module. | - - - - - - - - - - - - - - -### 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/core/client/v1/client.proto - - - - - -### ClientConsensusStates -ClientConsensusStates defines all the stored consensus states for a given -client. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client identifier | -| `consensus_states` | [ConsensusStateWithHeight](#ibc.core.client.v1.ConsensusStateWithHeight) | repeated | consensus states and their heights associated with the client | - - - - - - - - -### ClientUpdateProposal -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 | -| `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 | - - - - - - - - -### ConsensusStateWithHeight -ConsensusStateWithHeight defines a consensus state with an additional height field. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `height` | [Height](#ibc.core.client.v1.Height) | | consensus state height | -| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | consensus state | - - - - - - - +## Scalar Value Types -### Height -Height is a monotonically increasing data type -that can be compared against another Height for the purposes of updating and -freezing clients +| .proto Type | Notes | C++ | Java | Python | Go | C# | PHP | Ruby | +| ----------- | ----- | --- | ---- | ------ | -- | -- | --- | ---- | +| double | | double | double | float | float64 | double | float | Float | +| float | | float | float | float | float32 | float | float | Float | +| int32 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) | +| int64 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead. | int64 | long | int/long | int64 | long | integer/string | Bignum | +| uint32 | Uses variable-length encoding. | uint32 | int | int/long | uint32 | uint | integer | Bignum or Fixnum (as required) | +| uint64 | Uses variable-length encoding. | uint64 | long | int/long | uint64 | ulong | integer/string | Bignum or Fixnum (as required) | +| sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) | +| sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long | int64 | long | integer/string | Bignum | +| fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 2^28. | uint32 | int | int | uint32 | uint | integer | Bignum or Fixnum (as required) | +| fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 2^56. | uint64 | long | int/long | uint64 | ulong | integer/string | Bignum | +| sfixed32 | Always four bytes. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) | +| sfixed64 | Always eight bytes. | int64 | long | int/long | int64 | long | integer/string | Bignum | +| bool | | bool | boolean | boolean | bool | bool | boolean | TrueClass/FalseClass | +| string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode | string | string | string | String (UTF-8) | +| bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str | []byte | ByteString | string | String (ASCII-8BIT) | -Normally the RevisionHeight is incremented at each height while keeping RevisionNumber -the same. However some consensus algorithms may choose to reset the -height in certain conditions e.g. hard forks, state-machine breaking changes -In these cases, the RevisionNumber is incremented so that height continues to -be monitonically increasing even as the RevisionHeight gets reset - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `revision_number` | [uint64](#uint64) | | the revision that the client is currently on | -| `revision_height` | [uint64](#uint64) | | the height within the given revision | - - - - - - - - -### IdentifiedClientState -IdentifiedClientState defines a client state with an additional client -identifier field. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client identifier | -| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | client state | - - - - - - - - -### Params -Params defines the set of IBC light client parameters. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `allowed_clients` | [string](#string) | repeated | allowed_clients defines the list of allowed client state types. | - - - - - - - - -### UpgradeProposal -UpgradeProposal is a gov Content type for initiating an IBC breaking -upgrade. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `title` | [string](#string) | | | -| `description` | [string](#string) | | | -| `plan` | [cosmos.upgrade.v1beta1.Plan](#cosmos.upgrade.v1beta1.Plan) | | | -| `upgraded_client_state` | [google.protobuf.Any](#google.protobuf.Any) | | An UpgradedClientState must be provided to perform an IBC breaking upgrade. This will make the chain commit to the correct upgraded (self) client state before the upgrade occurs, so that connected chains can verify that the new upgraded client is valid by verifying a proof of the intended new client state on the previous version of the chain. This will allow IBC connections to persist smoothly across planned chain upgrades. | - - - - - - - - - - - - - - - - -

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/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 | -| ----- | ---- | ----- | ----------- | -| `result` | [bytes](#bytes) | | | -| `error` | [string](#string) | | | - - - - - - - - -### 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 | -| ----- | ---- | ----- | ----------- | -| `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 | - - - - - - - - -### Counterparty -Counterparty defines a channel end counterparty - - -| 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 | - - - - - - - - -### IdentifiedChannel -IdentifiedChannel defines a channel with additional port and channel -identifier fields. - - -| 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 | - - - - - - - - -### Packet -Packet defines a type that carries data across different chains through IBC - - -| 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 | - - - - - - - - -### 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 | -| ----- | ---- | ----- | ----------- | -| `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. | - - - - - - - - - - -### 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 | - - - - - -### 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 | - - - - - - - - -### 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 - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | port unique identifier | -| `channel_id` | [string](#string) | | channel unique identifier | - - - - - - - - -### QueryChannelClientStateResponse -QueryChannelClientStateResponse is the Response type for the -Query/QueryChannelClientState RPC method - - -| 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 | - - - - - - - - -### 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 | - - - - - - - - -### QueryChannelConsensusStateResponse -QueryChannelClientStateResponse is the Response type for the -Query/QueryChannelClientState 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 | - - - - - - - - -### 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 | - - - - - - - - -### 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 | - - - - - - - - -### 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 | - - - - - - - - -### 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 | - - - - - - - - -### 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 | - - - - - - - - -### 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 | - - - - - - - - -### 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 | - - - - - - - - -### 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 | - - - - - - - - -### QueryPacketAcknowledgementRequest -QueryPacketAcknowledgementRequest is the request type for the -Query/PacketAcknowledgement 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 | - - - - - - - - -### 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 | - - - - - - - - -### QueryPacketAcknowledgementsRequest -QueryPacketAcknowledgementsRequest is the request type for the -Query/QueryPacketCommitments RPC method - - -| 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 | - - - - - - - - -### 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 | - - - - - - - - -### QueryPacketCommitmentRequest -QueryPacketCommitmentRequest is the request type for the -Query/PacketCommitment 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 | - - - - - - - - -### 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 | - - - - - - - - -### QueryPacketCommitmentsRequest -QueryPacketCommitmentsRequest is the request type for the -Query/QueryPacketCommitments RPC method - - -| 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 | - - - - - - - - -### 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 | - - - - - - - - -### 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 | - - - - - - - - -### 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 | - - - - - - - - -### 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 | -| `packet_ack_sequences` | [uint64](#uint64) | repeated | list of acknowledgement sequences | - - - - - - - - -### QueryUnreceivedAcksResponse -QueryUnreceivedAcksResponse is the response type for the -Query/UnreceivedAcks 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 | - - - - - - - - -### 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 | - - - - - - - - -### 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 | - - - - - - - - - - - - - - -### 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

- -## ibc/core/channel/v1/tx.proto - - - - - -### 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) | | | - - - - - - - - -### MsgAcknowledgementResponse -MsgAcknowledgementResponse defines the Msg/Acknowledgement response type. - - - - - - - - -### 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) | | | - - - - - - - - -### MsgChannelCloseConfirmResponse -MsgChannelCloseConfirmResponse defines the Msg/ChannelCloseConfirm response type. - - - - - - - - -### 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) | | | - - - - - - - - -### MsgChannelCloseInitResponse -MsgChannelCloseInitResponse defines the Msg/ChannelCloseInit response type. - - - - - - - - -### 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) | | | -| `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) | | | - - - - - - - - -### MsgChannelOpenAckResponse -MsgChannelOpenAckResponse defines the Msg/ChannelOpenAck response type. - - - - - - - - -### 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) | | | -| `channel_id` | [string](#string) | | | -| `proof_ack` | [bytes](#bytes) | | | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | -| `signer` | [string](#string) | | | - - - - - - - - -### MsgChannelOpenConfirmResponse -MsgChannelOpenConfirmResponse defines the Msg/ChannelOpenConfirm response type. - - - - - - - - -### 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) | | | -| `channel` | [Channel](#ibc.core.channel.v1.Channel) | | | -| `signer` | [string](#string) | | | - - - - - - - - -### MsgChannelOpenInitResponse -MsgChannelOpenInitResponse defines the Msg/ChannelOpenInit response type. - - - - - - - - -### 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) | | | -| `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) | | | - - - - - - - - -### MsgChannelOpenTryResponse -MsgChannelOpenTryResponse defines the Msg/ChannelOpenTry response type. - - - - - - - - -### 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) | | | - - - - - - - - -### MsgRecvPacketResponse -MsgRecvPacketResponse defines the Msg/RecvPacket response type. - - - - - - - - -### MsgTimeout -MsgTimeout receives timed-out packet - - -| 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) | | | - - - - - - - - -### 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) | | | - - - - - - - - -### MsgTimeoutOnCloseResponse -MsgTimeoutOnCloseResponse defines the Msg/TimeoutOnClose response type. - - - - - - - - -### MsgTimeoutResponse -MsgTimeoutResponse defines the Msg/Timeout response type. - - - - - - - - - - - - - - -### 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. | | - - - - - - -

Top

- -## ibc/core/client/v1/genesis.proto - - - - - -### GenesisMetadata -GenesisMetadata defines the genesis type for metadata that clients may return -with ExportMetadata - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | store key of metadata without clientID-prefix | -| `value` | [bytes](#bytes) | | metadata value | - - - - - - - - -### 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 | - - - - - - - - -### IdentifiedGenesisMetadata -IdentifiedGenesisMetadata has the client metadata with the corresponding client id. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | | -| `client_metadata` | [GenesisMetadata](#ibc.core.client.v1.GenesisMetadata) | repeated | | - - - - - - - - - - - - - - - - -

Top

- -## ibc/core/client/v1/query.proto - - - - - -### QueryClientParamsRequest -QueryClientParamsRequest is the request type for the Query/ClientParams RPC method. - - - - - - - - -### 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. | - - - - - - - - -### QueryClientStateRequest -QueryClientStateRequest is the request type for the Query/ClientState RPC -method - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client state unique identifier | - - - - - - - - -### 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 | - - - - - - - - -### QueryClientStatesRequest -QueryClientStatesRequest is the request type for the Query/ClientStates RPC -method - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | - - - - - - - - -### 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 | - - - - - - - - -### 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 | -| ----- | ---- | ----- | ----------- | -| `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 | - - - - - - - - -### 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 | - - - - - - - - -### QueryConsensusStatesRequest -QueryConsensusStatesRequest is the request type for the Query/ConsensusStates -RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client identifier | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | - - - - - - - - -### 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 | - - - - - - - - -### QueryUpgradedClientStateRequest -QueryUpgradedClientStateRequest is the request type for the Query/UpgradedClientState RPC -method - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client state unique identifier | -| `plan_height` | [int64](#int64) | | plan height of the current chain must be sent in request as this is the height under which upgraded client state is stored | - - - - - - - - -### QueryUpgradedClientStateResponse -QueryUpgradedClientStateResponse is the response type for the Query/UpgradedClientState RPC -method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `upgraded_client_state` | [google.protobuf.Any](#google.protobuf.Any) | | client state associated with the request identifier | - - - - - - - - - - - - - - -### 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| -| `UpgradedClientState` | [QueryUpgradedClientStateRequest](#ibc.core.client.v1.QueryUpgradedClientStateRequest) | [QueryUpgradedClientStateResponse](#ibc.core.client.v1.QueryUpgradedClientStateResponse) | UpgradedClientState queries an Upgraded IBC light client. | GET|/ibc/core/client/v1/upgraded_client_states/{client_id}| - - - - - - -

Top

- -## ibc/core/client/v1/tx.proto - - - - - -### 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 | - - - - - - - - -### MsgCreateClientResponse -MsgCreateClientResponse defines the Msg/CreateClient response type. - - - - - - - - -### 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 | - - - - - - - - -### MsgSubmitMisbehaviourResponse -MsgSubmitMisbehaviourResponse defines the Msg/SubmitMisbehaviour 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 | - - - - - - - - -### MsgUpdateClientResponse -MsgUpdateClientResponse defines the Msg/UpdateClient response type. - - - - - - - - -### 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 | - - - - - - - - -### MsgUpgradeClientResponse -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. | | - - - - - - -

Top

- -## ibc/core/commitment/v1/commitment.proto - - - - - -### MerklePath -MerklePath is the path used to verify commitment proofs, which can be an -arbitrary structured object (defined by a commitment type). -MerklePath is represented from root-to-leaf - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `key_path` | [string](#string) | repeated | | - - - - - - - - -### MerklePrefix -MerklePrefix is merkle path prefixed to the key. -The constructed key from the Path and the key will be append(Path.KeyPath, -append(Path.KeyPrefix, key...)) - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `key_prefix` | [bytes](#bytes) | | | - - - - - - - - -### MerkleProof -MerkleProof is a wrapper type over a chain of CommitmentProofs. -It demonstrates membership or non-membership for an element or set of -elements, verifiable in conjunction with a known commitment root. Proofs -should be succinct. -MerkleProofs are ordered from leaf-to-root - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `proofs` | [ics23.CommitmentProof](#ics23.CommitmentProof) | repeated | | - - - - - - - - -### MerkleRoot -MerkleRoot defines a merkle root hash. -In the Cosmos SDK, the AppHash of a block header becomes the root. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `hash` | [bytes](#bytes) | | | - - - - - - - - - - - - - - - - -

Top

- -## ibc/core/connection/v1/connection.proto - - - - - -### ClientPaths -ClientPaths define all the connection paths for a client state. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `paths` | [string](#string) | repeated | list of connection paths | - - - - - - - - -### ConnectionEnd -ConnectionEnd defines a stateful object on a chain connected to another -separate one. -NOTE: there must only be 2 defined ConnectionEnds to establish -a connection between two chains. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client associated with this connection. | -| `versions` | [Version](#ibc.core.connection.v1.Version) | repeated | IBC version which can be utilised to determine encodings or protocols for channels or packets utilising this connection. | -| `state` | [State](#ibc.core.connection.v1.State) | | current state of the connection end. | -| `counterparty` | [Counterparty](#ibc.core.connection.v1.Counterparty) | | counterparty chain associated with this connection. | -| `delay_period` | [uint64](#uint64) | | delay period that must pass before a consensus state can be used for packet-verification NOTE: delay period logic is only implemented by some clients. | - - - - - - - - -### ConnectionPaths -ConnectionPaths define all the connection paths for a given client state. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client state unique identifier | -| `paths` | [string](#string) | repeated | list of connection paths | - - - - - - - - -### Counterparty -Counterparty defines the counterparty chain associated with a connection end. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | identifies the client on the counterparty chain associated with a given connection. | -| `connection_id` | [string](#string) | | identifies the connection end on the counterparty chain associated with a given connection. | -| `prefix` | [ibc.core.commitment.v1.MerklePrefix](#ibc.core.commitment.v1.MerklePrefix) | | commitment merkle prefix of the counterparty chain. | - - - - - - - - -### IdentifiedConnection -IdentifiedConnection defines a connection with additional connection -identifier field. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `id` | [string](#string) | | connection identifier. | -| `client_id` | [string](#string) | | client associated with this connection. | -| `versions` | [Version](#ibc.core.connection.v1.Version) | repeated | IBC version which can be utilised to determine encodings or protocols for channels or packets utilising this connection | -| `state` | [State](#ibc.core.connection.v1.State) | | current state of the connection end. | -| `counterparty` | [Counterparty](#ibc.core.connection.v1.Counterparty) | | counterparty chain associated with this connection. | -| `delay_period` | [uint64](#uint64) | | delay period associated with this connection. | - - - - - - - - -### Version -Version defines the versioning scheme used to negotiate the IBC verison in -the connection handshake. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `identifier` | [string](#string) | | unique version identifier | -| `features` | [string](#string) | repeated | list of features compatible with the specified identifier | - - - - - - - - - - -### State -State defines if a connection is in one of the following states: -INIT, TRYOPEN, OPEN or UNINITIALIZED. - -| Name | Number | Description | -| ---- | ------ | ----------- | -| STATE_UNINITIALIZED_UNSPECIFIED | 0 | Default State | -| STATE_INIT | 1 | A connection end has just started the opening handshake. | -| STATE_TRYOPEN | 2 | A connection end has acknowledged the handshake step on the counterparty chain. | -| STATE_OPEN | 3 | A connection end has completed the handshake. | - - - - - - - - - - - -

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/connection/v1/query.proto - - - - - -### QueryClientConnectionsRequest -QueryClientConnectionsRequest is the request type for the -Query/ClientConnections RPC method - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client identifier associated with a connection | - - - - - - - - -### QueryClientConnectionsResponse -QueryClientConnectionsResponse is the response type for the -Query/ClientConnections RPC method - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `connection_paths` | [string](#string) | repeated | slice of all the connection paths associated with a client. | -| `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 generated | - - - - - - - - -### QueryConnectionClientStateRequest -QueryConnectionClientStateRequest is the request type for the -Query/ConnectionClientState RPC method - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `connection_id` | [string](#string) | | connection identifier | - - - - - - - - -### QueryConnectionClientStateResponse -QueryConnectionClientStateResponse is the response type for the -Query/ConnectionClientState RPC method - - -| 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 | - - - - - - - - -### QueryConnectionConsensusStateRequest -QueryConnectionConsensusStateRequest is the request type for the -Query/ConnectionConsensusState RPC method - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `connection_id` | [string](#string) | | connection identifier | -| `revision_number` | [uint64](#uint64) | | | -| `revision_height` | [uint64](#uint64) | | | - - - - - - - - -### QueryConnectionConsensusStateResponse -QueryConnectionConsensusStateResponse is the response type for the -Query/ConnectionConsensusState 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 | - - - - - - - - -### QueryConnectionRequest -QueryConnectionRequest is the request type for the Query/Connection RPC -method - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `connection_id` | [string](#string) | | connection unique identifier | - - - - - - - - -### QueryConnectionResponse -QueryConnectionResponse is the response type for the Query/Connection RPC -method. Besides the connection end, it includes a proof and the height from -which the proof was retrieved. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `connection` | [ConnectionEnd](#ibc.core.connection.v1.ConnectionEnd) | | connection associated with the request identifier | -| `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 | - - - - - - - - -### QueryConnectionsRequest -QueryConnectionsRequest is the request type for the Query/Connections RPC -method - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | | - - - - - - - - -### QueryConnectionsResponse -QueryConnectionsResponse is the response type for the Query/Connections RPC -method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `connections` | [IdentifiedConnection](#ibc.core.connection.v1.IdentifiedConnection) | repeated | list of stored connections 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 | - - - - - - - - - - - - - - -### Query -Query provides defines the gRPC querier service - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Connection` | [QueryConnectionRequest](#ibc.core.connection.v1.QueryConnectionRequest) | [QueryConnectionResponse](#ibc.core.connection.v1.QueryConnectionResponse) | Connection queries an IBC connection end. | GET|/ibc/core/connection/v1beta1/connections/{connection_id}| -| `Connections` | [QueryConnectionsRequest](#ibc.core.connection.v1.QueryConnectionsRequest) | [QueryConnectionsResponse](#ibc.core.connection.v1.QueryConnectionsResponse) | Connections queries all the IBC connections of a chain. | GET|/ibc/core/connection/v1beta1/connections| -| `ClientConnections` | [QueryClientConnectionsRequest](#ibc.core.connection.v1.QueryClientConnectionsRequest) | [QueryClientConnectionsResponse](#ibc.core.connection.v1.QueryClientConnectionsResponse) | ClientConnections queries the connection paths associated with a client state. | GET|/ibc/core/connection/v1beta1/client_connections/{client_id}| -| `ConnectionClientState` | [QueryConnectionClientStateRequest](#ibc.core.connection.v1.QueryConnectionClientStateRequest) | [QueryConnectionClientStateResponse](#ibc.core.connection.v1.QueryConnectionClientStateResponse) | ConnectionClientState queries the client state associated with the connection. | GET|/ibc/core/connection/v1beta1/connections/{connection_id}/client_state| -| `ConnectionConsensusState` | [QueryConnectionConsensusStateRequest](#ibc.core.connection.v1.QueryConnectionConsensusStateRequest) | [QueryConnectionConsensusStateResponse](#ibc.core.connection.v1.QueryConnectionConsensusStateResponse) | ConnectionConsensusState queries the consensus state associated with the connection. | GET|/ibc/core/connection/v1beta1/connections/{connection_id}/consensus_state/revision/{revision_number}/height/{revision_height}| - - - - - - -

Top

- -## ibc/core/connection/v1/tx.proto - - - - - -### MsgConnectionOpenAck -MsgConnectionOpenAck defines a msg sent by a Relayer to Chain A to -acknowledge the change of connection state to TRYOPEN on Chain B. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `connection_id` | [string](#string) | | | -| `counterparty_connection_id` | [string](#string) | | | -| `version` | [Version](#ibc.core.connection.v1.Version) | | | -| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | -| `proof_try` | [bytes](#bytes) | | proof of the initialization the connection on Chain B: `UNITIALIZED -> TRYOPEN` | -| `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) | | | - - - - - - - - -### MsgConnectionOpenAckResponse -MsgConnectionOpenAckResponse defines the Msg/ConnectionOpenAck response type. - - - - - - - - -### MsgConnectionOpenConfirm -MsgConnectionOpenConfirm defines a msg sent by a Relayer to Chain B to -acknowledge the change of connection state to OPEN on Chain A. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `connection_id` | [string](#string) | | | -| `proof_ack` | [bytes](#bytes) | | proof for the change of the connection state on Chain A: `INIT -> OPEN` | -| `proof_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | -| `signer` | [string](#string) | | | - - - - - - - - -### MsgConnectionOpenConfirmResponse -MsgConnectionOpenConfirmResponse defines the Msg/ConnectionOpenConfirm response type. - - - - - - - - -### MsgConnectionOpenInit -MsgConnectionOpenInit defines the msg sent by an account on Chain A to -initialize a connection with Chain B. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | | -| `counterparty` | [Counterparty](#ibc.core.connection.v1.Counterparty) | | | -| `version` | [Version](#ibc.core.connection.v1.Version) | | | -| `delay_period` | [uint64](#uint64) | | | -| `signer` | [string](#string) | | | - - - - - - - - -### 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/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. - - -| 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 | - - - - - - - - - - - - - - - - -

Top

- -## ibc/lightclients/solomachine/v1/solomachine.proto - - - - - -### ChannelStateData -ChannelStateData returns the SignBytes data for channel state -verification. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `path` | [bytes](#bytes) | | | -| `channel` | [ibc.core.channel.v1.Channel](#ibc.core.channel.v1.Channel) | | | - - - - - - - - -### ClientState -ClientState defines a solo machine client that tracks the current consensus -state and if the client is frozen. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `sequence` | [uint64](#uint64) | | latest sequence of the client state | -| `frozen_sequence` | [uint64](#uint64) | | frozen sequence of the solo machine | -| `consensus_state` | [ConsensusState](#ibc.lightclients.solomachine.v1.ConsensusState) | | | -| `allow_update_after_proposal` | [bool](#bool) | | when set to true, will allow governance to update a solo machine client. The client will be unfrozen if it is frozen. | - - - - - - - - -### ClientStateData -ClientStateData returns the SignBytes data for client state verification. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `path` | [bytes](#bytes) | | | -| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | | - - - - - - - - -### ConnectionStateData -ConnectionStateData returns the SignBytes data for connection state -verification. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `path` | [bytes](#bytes) | | | -| `connection` | [ibc.core.connection.v1.ConnectionEnd](#ibc.core.connection.v1.ConnectionEnd) | | | - - - - - - - - -### ConsensusState -ConsensusState defines a solo machine consensus state. The sequence of a consensus state -is contained in the "height" key used in storing the consensus state. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `public_key` | [google.protobuf.Any](#google.protobuf.Any) | | public key of the solo machine | -| `diversifier` | [string](#string) | | diversifier allows the same public key to be re-used across different solo machine clients (potentially on different chains) without being considered misbehaviour. | -| `timestamp` | [uint64](#uint64) | | | - - - - - - - - -### ConsensusStateData -ConsensusStateData returns the SignBytes data for consensus state -verification. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `path` | [bytes](#bytes) | | | -| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | | - - - - - - - - -### Header -Header defines a solo machine consensus header - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `sequence` | [uint64](#uint64) | | sequence to update solo machine public key at | -| `timestamp` | [uint64](#uint64) | | | -| `signature` | [bytes](#bytes) | | | -| `new_public_key` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `new_diversifier` | [string](#string) | | | - - - - - - - - -### HeaderData -HeaderData returns the SignBytes data for update verification. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `new_pub_key` | [google.protobuf.Any](#google.protobuf.Any) | | header public key | -| `new_diversifier` | [string](#string) | | header diversifier | - - - - - - - - -### Misbehaviour -Misbehaviour defines misbehaviour for a solo machine which consists -of a sequence and two signatures over different messages at that sequence. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | | -| `sequence` | [uint64](#uint64) | | | -| `signature_one` | [SignatureAndData](#ibc.lightclients.solomachine.v1.SignatureAndData) | | | -| `signature_two` | [SignatureAndData](#ibc.lightclients.solomachine.v1.SignatureAndData) | | | - - - - - - - - -### NextSequenceRecvData -NextSequenceRecvData returns the SignBytes data for verification of the next -sequence to be received. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `path` | [bytes](#bytes) | | | -| `next_seq_recv` | [uint64](#uint64) | | | - - - - - - - - -### PacketAcknowledgementData -PacketAcknowledgementData returns the SignBytes data for acknowledgement -verification. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `path` | [bytes](#bytes) | | | -| `acknowledgement` | [bytes](#bytes) | | | - - - - - - - - -### PacketCommitmentData -PacketCommitmentData returns the SignBytes data for packet commitment -verification. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `path` | [bytes](#bytes) | | | -| `commitment` | [bytes](#bytes) | | | - - - - - - - - -### PacketReceiptAbsenceData -PacketReceiptAbsenceData returns the SignBytes data for -packet receipt absence verification. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `path` | [bytes](#bytes) | | | - - - - - - - - -### SignBytes -SignBytes defines the signed bytes used for signature verification. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `sequence` | [uint64](#uint64) | | | -| `timestamp` | [uint64](#uint64) | | | -| `diversifier` | [string](#string) | | | -| `data_type` | [DataType](#ibc.lightclients.solomachine.v1.DataType) | | type of the data used | -| `data` | [bytes](#bytes) | | marshaled data | - - - - - - - - -### SignatureAndData -SignatureAndData contains a signature and the data signed over to create that -signature. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `signature` | [bytes](#bytes) | | | -| `data_type` | [DataType](#ibc.lightclients.solomachine.v1.DataType) | | | -| `data` | [bytes](#bytes) | | | -| `timestamp` | [uint64](#uint64) | | | - - - - - - - - -### TimestampedSignatureData -TimestampedSignatureData contains the signature data and the timestamp of the -signature. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `signature_data` | [bytes](#bytes) | | | -| `timestamp` | [uint64](#uint64) | | | - - - - - - - - - - -### DataType -DataType defines the type of solo machine proof being created. This is done to preserve uniqueness of different -data sign byte encodings. - -| Name | Number | Description | -| ---- | ------ | ----------- | -| DATA_TYPE_UNINITIALIZED_UNSPECIFIED | 0 | Default State | -| DATA_TYPE_CLIENT_STATE | 1 | Data type for client state verification | -| DATA_TYPE_CONSENSUS_STATE | 2 | Data type for consensus state verification | -| DATA_TYPE_CONNECTION_STATE | 3 | Data type for connection state verification | -| DATA_TYPE_CHANNEL_STATE | 4 | Data type for channel state verification | -| DATA_TYPE_PACKET_COMMITMENT | 5 | Data type for packet commitment verification | -| DATA_TYPE_PACKET_ACKNOWLEDGEMENT | 6 | Data type for packet acknowledgement verification | -| DATA_TYPE_PACKET_RECEIPT_ABSENCE | 7 | Data type for packet receipt absence verification | -| DATA_TYPE_NEXT_SEQUENCE_RECV | 8 | Data type for next sequence recv verification | -| DATA_TYPE_HEADER | 9 | Data type for header verification | - - - - - - - - - - - -

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 | -| ----------- | ----- | --- | ---- | ------ | -- | -- | --- | ---- | -| double | | double | double | float | float64 | double | float | Float | -| float | | float | float | float | float32 | float | float | Float | -| int32 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) | -| int64 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead. | int64 | long | int/long | int64 | long | integer/string | Bignum | -| uint32 | Uses variable-length encoding. | uint32 | int | int/long | uint32 | uint | integer | Bignum or Fixnum (as required) | -| uint64 | Uses variable-length encoding. | uint64 | long | int/long | uint64 | ulong | integer/string | Bignum or Fixnum (as required) | -| sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) | -| sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long | int64 | long | integer/string | Bignum | -| fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 2^28. | uint32 | int | int | uint32 | uint | integer | Bignum or Fixnum (as required) | -| fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 2^56. | uint64 | long | int/long | uint64 | ulong | integer/string | Bignum | -| sfixed32 | Always four bytes. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) | -| sfixed64 | Always eight bytes. | int64 | long | int/long | int64 | long | integer/string | Bignum | -| bool | | bool | boolean | boolean | bool | bool | boolean | TrueClass/FalseClass | -| string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode | string | string | string | String (UTF-8) | -| bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str | []byte | ByteString | string | String (ASCII-8BIT) | diff --git a/docs/ibc/README.md b/docs/ibc/README.md index 6298c119632b..8be696391299 100644 --- a/docs/ibc/README.md +++ b/docs/ibc/README.md @@ -14,5 +14,7 @@ This repository contains reference documentation for the IBC protocol integratio 4. [Relayer](./relayer.md) 5. [Governance Proposals](./proposals.md) +**NOTE**: The IBC module has been moved to its [own repository](https://github.com/cosmos/ibc-go). + 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/proto/ibc/applications/transfer/v1/genesis.proto b/proto/ibc/applications/transfer/v1/genesis.proto deleted file mode 100644 index 98cf2296d2e9..000000000000 --- a/proto/ibc/applications/transfer/v1/genesis.proto +++ /dev/null @@ -1,18 +0,0 @@ -syntax = "proto3"; -package ibc.applications.transfer.v1; - -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types"; - -import "gogoproto/gogo.proto"; -import "ibc/applications/transfer/v1/transfer.proto"; - -// GenesisState defines the ibc-transfer genesis state -message GenesisState { - string port_id = 1 [(gogoproto.moretags) = "yaml:\"port_id\""]; - repeated DenomTrace denom_traces = 2 [ - (gogoproto.castrepeated) = "Traces", - (gogoproto.nullable) = false, - (gogoproto.moretags) = "yaml:\"denom_traces\"" - ]; - Params params = 3 [(gogoproto.nullable) = false]; -} diff --git a/proto/ibc/applications/transfer/v1/query.proto b/proto/ibc/applications/transfer/v1/query.proto deleted file mode 100644 index e9cbd02a31ce..000000000000 --- a/proto/ibc/applications/transfer/v1/query.proto +++ /dev/null @@ -1,66 +0,0 @@ -syntax = "proto3"; -package ibc.applications.transfer.v1; - -import "gogoproto/gogo.proto"; -import "cosmos/base/query/v1beta1/pagination.proto"; -import "ibc/applications/transfer/v1/transfer.proto"; -import "google/api/annotations.proto"; - -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types"; - -// Query provides defines the gRPC querier service. -service Query { - // DenomTrace queries a denomination trace information. - rpc DenomTrace(QueryDenomTraceRequest) returns (QueryDenomTraceResponse) { - option (google.api.http).get = "/ibc/applications/transfer/v1beta1/denom_traces/{hash}"; - } - - // DenomTraces queries all denomination traces. - rpc DenomTraces(QueryDenomTracesRequest) returns (QueryDenomTracesResponse) { - option (google.api.http).get = "/ibc/applications/transfer/v1beta1/denom_traces"; - } - - // Params queries all parameters of the ibc-transfer module. - rpc Params(QueryParamsRequest) returns (QueryParamsResponse) { - option (google.api.http).get = "/ibc/applications/transfer/v1beta1/params"; - } -} - -// QueryDenomTraceRequest is the request type for the Query/DenomTrace RPC -// method -message QueryDenomTraceRequest { - // hash (in hex format) of the denomination trace information. - string hash = 1; -} - -// QueryDenomTraceResponse is the response type for the Query/DenomTrace RPC -// method. -message QueryDenomTraceResponse { - // denom_trace returns the requested denomination trace information. - DenomTrace denom_trace = 1; -} - -// QueryConnectionsRequest is the request type for the Query/DenomTraces RPC -// method -message QueryDenomTracesRequest { - // pagination defines an optional pagination for the request. - cosmos.base.query.v1beta1.PageRequest pagination = 1; -} - -// QueryConnectionsResponse is the response type for the Query/DenomTraces RPC -// method. -message QueryDenomTracesResponse { - // denom_traces returns all denominations trace information. - repeated DenomTrace denom_traces = 1 [(gogoproto.castrepeated) = "Traces", (gogoproto.nullable) = false]; - // pagination defines the pagination in the response. - cosmos.base.query.v1beta1.PageResponse pagination = 2; -} - -// QueryParamsRequest is the request type for the Query/Params RPC method. -message QueryParamsRequest {} - -// QueryParamsResponse is the response type for the Query/Params RPC method. -message QueryParamsResponse { - // params defines the parameters of the module. - Params params = 1; -} diff --git a/proto/ibc/applications/transfer/v1/transfer.proto b/proto/ibc/applications/transfer/v1/transfer.proto deleted file mode 100644 index b388c3b879c2..000000000000 --- a/proto/ibc/applications/transfer/v1/transfer.proto +++ /dev/null @@ -1,43 +0,0 @@ -syntax = "proto3"; -package ibc.applications.transfer.v1; - -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types"; - -import "gogoproto/gogo.proto"; - -// 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 -message FungibleTokenPacketData { - // the token denomination to be transferred - string denom = 1; - // the token amount to be transferred - uint64 amount = 2; - // the sender address - string sender = 3; - // the recipient address on the destination chain - string receiver = 4; -} - -// DenomTrace contains the base denomination for ICS20 fungible tokens and the -// source tracing information path. -message DenomTrace { - // path defines the chain of port/channel identifiers used for tracing the - // source of the fungible token. - string path = 1; - // base denomination of the relayed fungible token. - string base_denom = 2; -} - -// 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. -message Params { - // send_enabled enables or disables all cross-chain token transfers from this - // chain. - bool send_enabled = 1 [(gogoproto.moretags) = "yaml:\"send_enabled\""]; - // receive_enabled enables or disables all cross-chain token transfers to this - // chain. - bool receive_enabled = 2 [(gogoproto.moretags) = "yaml:\"receive_enabled\""]; -} diff --git a/proto/ibc/applications/transfer/v1/tx.proto b/proto/ibc/applications/transfer/v1/tx.proto deleted file mode 100644 index a0f0827aaf6a..000000000000 --- a/proto/ibc/applications/transfer/v1/tx.proto +++ /dev/null @@ -1,43 +0,0 @@ -syntax = "proto3"; -package ibc.applications.transfer.v1; - -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types"; - -import "gogoproto/gogo.proto"; -import "cosmos/base/v1beta1/coin.proto"; -import "ibc/core/client/v1/client.proto"; - -// Msg defines the ibc/transfer Msg service. -service Msg { - // Transfer defines a rpc handler method for MsgTransfer. - rpc Transfer(MsgTransfer) returns (MsgTransferResponse); -} - -// 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 -message MsgTransfer { - option (gogoproto.equal) = false; - option (gogoproto.goproto_getters) = false; - - // the port on which the packet will be sent - string source_port = 1 [(gogoproto.moretags) = "yaml:\"source_port\""]; - // the channel by which the packet will be sent - string source_channel = 2 [(gogoproto.moretags) = "yaml:\"source_channel\""]; - // the tokens to be transferred - cosmos.base.v1beta1.Coin token = 3 [(gogoproto.nullable) = false]; - // the sender address - string sender = 4; - // the recipient address on the destination chain - string receiver = 5; - // Timeout height relative to the current block height. - // The timeout is disabled when set to 0. - ibc.core.client.v1.Height timeout_height = 6 - [(gogoproto.moretags) = "yaml:\"timeout_height\"", (gogoproto.nullable) = false]; - // Timeout timestamp (in nanoseconds) relative to the current block timestamp. - // The timeout is disabled when set to 0. - uint64 timeout_timestamp = 7 [(gogoproto.moretags) = "yaml:\"timeout_timestamp\""]; -} - -// MsgTransferResponse defines the Msg/Transfer response type. -message MsgTransferResponse {} diff --git a/proto/ibc/core/channel/v1/channel.proto b/proto/ibc/core/channel/v1/channel.proto deleted file mode 100644 index 302a48068953..000000000000 --- a/proto/ibc/core/channel/v1/channel.proto +++ /dev/null @@ -1,147 +0,0 @@ -syntax = "proto3"; -package ibc.core.channel.v1; - -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types"; - -import "gogoproto/gogo.proto"; -import "ibc/core/client/v1/client.proto"; - -// 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. -message Channel { - option (gogoproto.goproto_getters) = false; - - // current state of the channel end - State state = 1; - // whether the channel is ordered or unordered - Order ordering = 2; - // counterparty channel end - Counterparty counterparty = 3 [(gogoproto.nullable) = false]; - // list of connection identifiers, in order, along which packets sent on - // this channel will travel - repeated string connection_hops = 4 [(gogoproto.moretags) = "yaml:\"connection_hops\""]; - // opaque channel version, which is agreed upon during the handshake - string version = 5; -} - -// IdentifiedChannel defines a channel with additional port and channel -// identifier fields. -message IdentifiedChannel { - option (gogoproto.goproto_getters) = false; - - // current state of the channel end - State state = 1; - // whether the channel is ordered or unordered - Order ordering = 2; - // counterparty channel end - Counterparty counterparty = 3 [(gogoproto.nullable) = false]; - // list of connection identifiers, in order, along which packets sent on - // this channel will travel - repeated string connection_hops = 4 [(gogoproto.moretags) = "yaml:\"connection_hops\""]; - // opaque channel version, which is agreed upon during the handshake - string version = 5; - // port identifier - string port_id = 6; - // channel identifier - string channel_id = 7; -} - -// State defines if a channel is in one of the following states: -// CLOSED, INIT, TRYOPEN, OPEN or UNINITIALIZED. -enum State { - option (gogoproto.goproto_enum_prefix) = false; - - // Default State - STATE_UNINITIALIZED_UNSPECIFIED = 0 [(gogoproto.enumvalue_customname) = "UNINITIALIZED"]; - // A channel has just started the opening handshake. - STATE_INIT = 1 [(gogoproto.enumvalue_customname) = "INIT"]; - // A channel has acknowledged the handshake step on the counterparty chain. - STATE_TRYOPEN = 2 [(gogoproto.enumvalue_customname) = "TRYOPEN"]; - // A channel has completed the handshake. Open channels are - // ready to send and receive packets. - STATE_OPEN = 3 [(gogoproto.enumvalue_customname) = "OPEN"]; - // A channel has been closed and can no longer be used to send or receive - // packets. - STATE_CLOSED = 4 [(gogoproto.enumvalue_customname) = "CLOSED"]; -} - -// Order defines if a channel is ORDERED or UNORDERED -enum Order { - option (gogoproto.goproto_enum_prefix) = false; - - // zero-value for channel ordering - ORDER_NONE_UNSPECIFIED = 0 [(gogoproto.enumvalue_customname) = "NONE"]; - // packets can be delivered in any order, which may differ from the order in - // which they were sent. - ORDER_UNORDERED = 1 [(gogoproto.enumvalue_customname) = "UNORDERED"]; - // packets are delivered exactly in the order which they were sent - ORDER_ORDERED = 2 [(gogoproto.enumvalue_customname) = "ORDERED"]; -} - -// Counterparty defines a channel end counterparty -message Counterparty { - option (gogoproto.goproto_getters) = false; - - // port on the counterparty chain which owns the other end of the channel. - string port_id = 1 [(gogoproto.moretags) = "yaml:\"port_id\""]; - // channel end on the counterparty chain - string channel_id = 2 [(gogoproto.moretags) = "yaml:\"channel_id\""]; -} - -// Packet defines a type that carries data across different chains through IBC -message Packet { - option (gogoproto.goproto_getters) = false; - - // 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. - uint64 sequence = 1; - // identifies the port on the sending chain. - string source_port = 2 [(gogoproto.moretags) = "yaml:\"source_port\""]; - // identifies the channel end on the sending chain. - string source_channel = 3 [(gogoproto.moretags) = "yaml:\"source_channel\""]; - // identifies the port on the receiving chain. - string destination_port = 4 [(gogoproto.moretags) = "yaml:\"destination_port\""]; - // identifies the channel end on the receiving chain. - string destination_channel = 5 [(gogoproto.moretags) = "yaml:\"destination_channel\""]; - // actual opaque bytes transferred directly to the application module - bytes data = 6; - // block height after which the packet times out - ibc.core.client.v1.Height timeout_height = 7 - [(gogoproto.moretags) = "yaml:\"timeout_height\"", (gogoproto.nullable) = false]; - // block timestamp (in nanoseconds) after which the packet times out - uint64 timeout_timestamp = 8 [(gogoproto.moretags) = "yaml:\"timeout_timestamp\""]; -} - -// 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. -message PacketState { - option (gogoproto.goproto_getters) = false; - - // channel port identifier. - string port_id = 1 [(gogoproto.moretags) = "yaml:\"port_id\""]; - // channel unique identifier. - string channel_id = 2 [(gogoproto.moretags) = "yaml:\"channel_id\""]; - // packet sequence. - uint64 sequence = 3; - // embedded data that represents packet state. - bytes data = 4; -} - -// 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 -message Acknowledgement { - // response contains either a result or an error and must be non-empty - oneof response { - bytes result = 21; - string error = 22; - } -} diff --git a/proto/ibc/core/channel/v1/genesis.proto b/proto/ibc/core/channel/v1/genesis.proto deleted file mode 100644 index d3b2c0424eaa..000000000000 --- a/proto/ibc/core/channel/v1/genesis.proto +++ /dev/null @@ -1,31 +0,0 @@ -syntax = "proto3"; -package ibc.core.channel.v1; - -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types"; - -import "gogoproto/gogo.proto"; -import "ibc/core/channel/v1/channel.proto"; - -// GenesisState defines the ibc channel submodule's genesis state. -message GenesisState { - repeated IdentifiedChannel channels = 1 [(gogoproto.casttype) = "IdentifiedChannel", (gogoproto.nullable) = false]; - repeated PacketState acknowledgements = 2 [(gogoproto.nullable) = false]; - repeated PacketState commitments = 3 [(gogoproto.nullable) = false]; - repeated PacketState receipts = 4 [(gogoproto.nullable) = false]; - repeated PacketSequence send_sequences = 5 - [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"send_sequences\""]; - repeated PacketSequence recv_sequences = 6 - [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"recv_sequences\""]; - repeated PacketSequence ack_sequences = 7 - [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"ack_sequences\""]; - // the sequence for the next generated channel identifier - uint64 next_channel_sequence = 8 [(gogoproto.moretags) = "yaml:\"next_channel_sequence\""]; -} - -// PacketSequence defines the genesis type necessary to retrieve and store -// next send and receive sequences. -message PacketSequence { - string port_id = 1 [(gogoproto.moretags) = "yaml:\"port_id\""]; - string channel_id = 2 [(gogoproto.moretags) = "yaml:\"channel_id\""]; - uint64 sequence = 3; -} diff --git a/proto/ibc/core/channel/v1/query.proto b/proto/ibc/core/channel/v1/query.proto deleted file mode 100644 index d9e3ceb8a646..000000000000 --- a/proto/ibc/core/channel/v1/query.proto +++ /dev/null @@ -1,367 +0,0 @@ -syntax = "proto3"; -package ibc.core.channel.v1; - -import "ibc/core/client/v1/client.proto"; -import "cosmos/base/query/v1beta1/pagination.proto"; -import "ibc/core/channel/v1/channel.proto"; -import "google/api/annotations.proto"; -import "google/protobuf/any.proto"; -import "gogoproto/gogo.proto"; - -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types"; - -// Query provides defines the gRPC querier service -service Query { - // Channel queries an IBC Channel. - rpc Channel(QueryChannelRequest) returns (QueryChannelResponse) { - option (google.api.http).get = "/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}"; - } - - // Channels queries all the IBC channels of a chain. - rpc Channels(QueryChannelsRequest) returns (QueryChannelsResponse) { - option (google.api.http).get = "/ibc/core/channel/v1beta1/channels"; - } - - // ConnectionChannels queries all the channels associated with a connection - // end. - rpc ConnectionChannels(QueryConnectionChannelsRequest) returns (QueryConnectionChannelsResponse) { - option (google.api.http).get = "/ibc/core/channel/v1beta1/connections/{connection}/channels"; - } - - // ChannelClientState queries for the client state for the channel associated - // with the provided channel identifiers. - rpc ChannelClientState(QueryChannelClientStateRequest) returns (QueryChannelClientStateResponse) { - option (google.api.http).get = "/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/client_state"; - } - - // ChannelConsensusState queries for the consensus state for the channel - // associated with the provided channel identifiers. - rpc ChannelConsensusState(QueryChannelConsensusStateRequest) returns (QueryChannelConsensusStateResponse) { - option (google.api.http).get = - "/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/consensus_state/revision/" - "{revision_number}/height/{revision_height}"; - } - - // PacketCommitment queries a stored packet commitment hash. - rpc PacketCommitment(QueryPacketCommitmentRequest) returns (QueryPacketCommitmentResponse) { - option (google.api.http).get = - "/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_commitments/{sequence}"; - } - - // PacketCommitments returns all the packet commitments hashes associated - // with a channel. - rpc PacketCommitments(QueryPacketCommitmentsRequest) returns (QueryPacketCommitmentsResponse) { - option (google.api.http).get = "/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_commitments"; - } - - // PacketReceipt queries if a given packet sequence has been received on the queried chain - rpc PacketReceipt(QueryPacketReceiptRequest) returns (QueryPacketReceiptResponse) { - option (google.api.http).get = - "/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_receipts/{sequence}"; - } - - // PacketAcknowledgement queries a stored packet acknowledgement hash. - rpc PacketAcknowledgement(QueryPacketAcknowledgementRequest) returns (QueryPacketAcknowledgementResponse) { - option (google.api.http).get = - "/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_acks/{sequence}"; - } - - // PacketAcknowledgements returns all the packet acknowledgements associated - // with a channel. - rpc PacketAcknowledgements(QueryPacketAcknowledgementsRequest) returns (QueryPacketAcknowledgementsResponse) { - option (google.api.http).get = - "/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_acknowledgements"; - } - - // UnreceivedPackets returns all the unreceived IBC packets associated with a - // channel and sequences. - rpc UnreceivedPackets(QueryUnreceivedPacketsRequest) returns (QueryUnreceivedPacketsResponse) { - option (google.api.http).get = "/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_commitments/" - "{packet_commitment_sequences}/unreceived_packets"; - } - - // UnreceivedAcks returns all the unreceived IBC acknowledgements associated with a - // channel and sequences. - rpc UnreceivedAcks(QueryUnreceivedAcksRequest) returns (QueryUnreceivedAcksResponse) { - option (google.api.http).get = "/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/packet_commitments/" - "{packet_ack_sequences}/unreceived_acks"; - } - - // NextSequenceReceive returns the next receive sequence for a given channel. - rpc NextSequenceReceive(QueryNextSequenceReceiveRequest) returns (QueryNextSequenceReceiveResponse) { - option (google.api.http).get = "/ibc/core/channel/v1beta1/channels/{channel_id}/ports/{port_id}/next_sequence"; - } -} - -// QueryChannelRequest is the request type for the Query/Channel RPC method -message QueryChannelRequest { - // port unique identifier - string port_id = 1; - // channel unique identifier - string channel_id = 2; -} - -// 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. -message QueryChannelResponse { - // channel associated with the request identifiers - ibc.core.channel.v1.Channel channel = 1; - // merkle proof of existence - bytes proof = 2; - // height at which the proof was retrieved - ibc.core.client.v1.Height proof_height = 3 [(gogoproto.nullable) = false]; -} - -// QueryChannelsRequest is the request type for the Query/Channels RPC method -message QueryChannelsRequest { - // pagination request - cosmos.base.query.v1beta1.PageRequest pagination = 1; -} - -// QueryChannelsResponse is the response type for the Query/Channels RPC method. -message QueryChannelsResponse { - // list of stored channels of the chain. - repeated ibc.core.channel.v1.IdentifiedChannel channels = 1; - // pagination response - cosmos.base.query.v1beta1.PageResponse pagination = 2; - // query block height - ibc.core.client.v1.Height height = 3 [(gogoproto.nullable) = false]; -} - -// QueryConnectionChannelsRequest is the request type for the -// Query/QueryConnectionChannels RPC method -message QueryConnectionChannelsRequest { - // connection unique identifier - string connection = 1; - // pagination request - cosmos.base.query.v1beta1.PageRequest pagination = 2; -} - -// QueryConnectionChannelsResponse is the Response type for the -// Query/QueryConnectionChannels RPC method -message QueryConnectionChannelsResponse { - // list of channels associated with a connection. - repeated ibc.core.channel.v1.IdentifiedChannel channels = 1; - // pagination response - cosmos.base.query.v1beta1.PageResponse pagination = 2; - // query block height - ibc.core.client.v1.Height height = 3 [(gogoproto.nullable) = false]; -} - -// QueryChannelClientStateRequest is the request type for the Query/ClientState -// RPC method -message QueryChannelClientStateRequest { - // port unique identifier - string port_id = 1; - // channel unique identifier - string channel_id = 2; -} - -// QueryChannelClientStateResponse is the Response type for the -// Query/QueryChannelClientState RPC method -message QueryChannelClientStateResponse { - // client state associated with the channel - ibc.core.client.v1.IdentifiedClientState identified_client_state = 1; - // merkle proof of existence - bytes proof = 2; - // height at which the proof was retrieved - ibc.core.client.v1.Height proof_height = 3 [(gogoproto.nullable) = false]; -} - -// QueryChannelConsensusStateRequest is the request type for the -// Query/ConsensusState RPC method -message QueryChannelConsensusStateRequest { - // port unique identifier - string port_id = 1; - // channel unique identifier - string channel_id = 2; - // revision number of the consensus state - uint64 revision_number = 3; - // revision height of the consensus state - uint64 revision_height = 4; -} - -// QueryChannelClientStateResponse is the Response type for the -// Query/QueryChannelClientState RPC method -message QueryChannelConsensusStateResponse { - // consensus state associated with the channel - google.protobuf.Any consensus_state = 1; - // client ID associated with the consensus state - string client_id = 2; - // merkle proof of existence - bytes proof = 3; - // height at which the proof was retrieved - ibc.core.client.v1.Height proof_height = 4 [(gogoproto.nullable) = false]; -} - -// QueryPacketCommitmentRequest is the request type for the -// Query/PacketCommitment RPC method -message QueryPacketCommitmentRequest { - // port unique identifier - string port_id = 1; - // channel unique identifier - string channel_id = 2; - // packet sequence - uint64 sequence = 3; -} - -// QueryPacketCommitmentResponse defines the client query response for a packet -// which also includes a proof and the height from which the proof was -// retrieved -message QueryPacketCommitmentResponse { - // packet associated with the request fields - bytes commitment = 1; - // merkle proof of existence - bytes proof = 2; - // height at which the proof was retrieved - ibc.core.client.v1.Height proof_height = 3 [(gogoproto.nullable) = false]; -} - -// QueryPacketCommitmentsRequest is the request type for the -// Query/QueryPacketCommitments RPC method -message QueryPacketCommitmentsRequest { - // port unique identifier - string port_id = 1; - // channel unique identifier - string channel_id = 2; - // pagination request - cosmos.base.query.v1beta1.PageRequest pagination = 3; -} - -// QueryPacketCommitmentsResponse is the request type for the -// Query/QueryPacketCommitments RPC method -message QueryPacketCommitmentsResponse { - repeated ibc.core.channel.v1.PacketState commitments = 1; - // pagination response - cosmos.base.query.v1beta1.PageResponse pagination = 2; - // query block height - ibc.core.client.v1.Height height = 3 [(gogoproto.nullable) = false]; -} - -// QueryPacketReceiptRequest is the request type for the -// Query/PacketReceipt RPC method -message QueryPacketReceiptRequest { - // port unique identifier - string port_id = 1; - // channel unique identifier - string channel_id = 2; - // packet sequence - uint64 sequence = 3; -} - -// QueryPacketReceiptResponse defines the client query response for a packet receipt -// which also includes a proof, and the height from which the proof was -// retrieved -message QueryPacketReceiptResponse { - // success flag for if receipt exists - bool received = 2; - // merkle proof of existence - bytes proof = 3; - // height at which the proof was retrieved - ibc.core.client.v1.Height proof_height = 4 [(gogoproto.nullable) = false]; -} - -// QueryPacketAcknowledgementRequest is the request type for the -// Query/PacketAcknowledgement RPC method -message QueryPacketAcknowledgementRequest { - // port unique identifier - string port_id = 1; - // channel unique identifier - string channel_id = 2; - // packet sequence - uint64 sequence = 3; -} - -// QueryPacketAcknowledgementResponse defines the client query response for a -// packet which also includes a proof and the height from which the -// proof was retrieved -message QueryPacketAcknowledgementResponse { - // packet associated with the request fields - bytes acknowledgement = 1; - // merkle proof of existence - bytes proof = 2; - // height at which the proof was retrieved - ibc.core.client.v1.Height proof_height = 3 [(gogoproto.nullable) = false]; -} - -// QueryPacketAcknowledgementsRequest is the request type for the -// Query/QueryPacketCommitments RPC method -message QueryPacketAcknowledgementsRequest { - // port unique identifier - string port_id = 1; - // channel unique identifier - string channel_id = 2; - // pagination request - cosmos.base.query.v1beta1.PageRequest pagination = 3; -} - -// QueryPacketAcknowledgemetsResponse is the request type for the -// Query/QueryPacketAcknowledgements RPC method -message QueryPacketAcknowledgementsResponse { - repeated ibc.core.channel.v1.PacketState acknowledgements = 1; - // pagination response - cosmos.base.query.v1beta1.PageResponse pagination = 2; - // query block height - ibc.core.client.v1.Height height = 3 [(gogoproto.nullable) = false]; -} - -// QueryUnreceivedPacketsRequest is the request type for the -// Query/UnreceivedPackets RPC method -message QueryUnreceivedPacketsRequest { - // port unique identifier - string port_id = 1; - // channel unique identifier - string channel_id = 2; - // list of packet sequences - repeated uint64 packet_commitment_sequences = 3; -} - -// QueryUnreceivedPacketsResponse is the response type for the -// Query/UnreceivedPacketCommitments RPC method -message QueryUnreceivedPacketsResponse { - // list of unreceived packet sequences - repeated uint64 sequences = 1; - // query block height - ibc.core.client.v1.Height height = 2 [(gogoproto.nullable) = false]; -} - -// QueryUnreceivedAcks is the request type for the -// Query/UnreceivedAcks RPC method -message QueryUnreceivedAcksRequest { - // port unique identifier - string port_id = 1; - // channel unique identifier - string channel_id = 2; - // list of acknowledgement sequences - repeated uint64 packet_ack_sequences = 3; -} - -// QueryUnreceivedAcksResponse is the response type for the -// Query/UnreceivedAcks RPC method -message QueryUnreceivedAcksResponse { - // list of unreceived acknowledgement sequences - repeated uint64 sequences = 1; - // query block height - ibc.core.client.v1.Height height = 2 [(gogoproto.nullable) = false]; -} - -// QueryNextSequenceReceiveRequest is the request type for the -// Query/QueryNextSequenceReceiveRequest RPC method -message QueryNextSequenceReceiveRequest { - // port unique identifier - string port_id = 1; - // channel unique identifier - string channel_id = 2; -} - -// QuerySequenceResponse is the request type for the -// Query/QueryNextSequenceReceiveResponse RPC method -message QueryNextSequenceReceiveResponse { - // next sequence receive number - uint64 next_sequence_receive = 1; - // merkle proof of existence - bytes proof = 2; - // height at which the proof was retrieved - ibc.core.client.v1.Height proof_height = 3 [(gogoproto.nullable) = false]; -} diff --git a/proto/ibc/core/channel/v1/tx.proto b/proto/ibc/core/channel/v1/tx.proto deleted file mode 100644 index 5f8426412415..000000000000 --- a/proto/ibc/core/channel/v1/tx.proto +++ /dev/null @@ -1,207 +0,0 @@ -syntax = "proto3"; -package ibc.core.channel.v1; - -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types"; - -import "gogoproto/gogo.proto"; -import "ibc/core/client/v1/client.proto"; -import "ibc/core/channel/v1/channel.proto"; - -// Msg defines the ibc/channel Msg service. -service Msg { - // ChannelOpenInit defines a rpc handler method for MsgChannelOpenInit. - rpc ChannelOpenInit(MsgChannelOpenInit) returns (MsgChannelOpenInitResponse); - - // ChannelOpenTry defines a rpc handler method for MsgChannelOpenTry. - rpc ChannelOpenTry(MsgChannelOpenTry) returns (MsgChannelOpenTryResponse); - - // ChannelOpenAck defines a rpc handler method for MsgChannelOpenAck. - rpc ChannelOpenAck(MsgChannelOpenAck) returns (MsgChannelOpenAckResponse); - - // ChannelOpenConfirm defines a rpc handler method for MsgChannelOpenConfirm. - rpc ChannelOpenConfirm(MsgChannelOpenConfirm) returns (MsgChannelOpenConfirmResponse); - - // ChannelCloseInit defines a rpc handler method for MsgChannelCloseInit. - rpc ChannelCloseInit(MsgChannelCloseInit) returns (MsgChannelCloseInitResponse); - - // ChannelCloseConfirm defines a rpc handler method for MsgChannelCloseConfirm. - rpc ChannelCloseConfirm(MsgChannelCloseConfirm) returns (MsgChannelCloseConfirmResponse); - - // RecvPacket defines a rpc handler method for MsgRecvPacket. - rpc RecvPacket(MsgRecvPacket) returns (MsgRecvPacketResponse); - - // Timeout defines a rpc handler method for MsgTimeout. - rpc Timeout(MsgTimeout) returns (MsgTimeoutResponse); - - // TimeoutOnClose defines a rpc handler method for MsgTimeoutOnClose. - rpc TimeoutOnClose(MsgTimeoutOnClose) returns (MsgTimeoutOnCloseResponse); - - // Acknowledgement defines a rpc handler method for MsgAcknowledgement. - rpc Acknowledgement(MsgAcknowledgement) returns (MsgAcknowledgementResponse); -} - -// MsgChannelOpenInit defines an sdk.Msg to initialize a channel handshake. It -// is called by a relayer on Chain A. -message MsgChannelOpenInit { - option (gogoproto.equal) = false; - option (gogoproto.goproto_getters) = false; - - string port_id = 1 [(gogoproto.moretags) = "yaml:\"port_id\""]; - Channel channel = 2 [(gogoproto.nullable) = false]; - string signer = 3; -} - -// MsgChannelOpenInitResponse defines the Msg/ChannelOpenInit response type. -message MsgChannelOpenInitResponse {} - -// MsgChannelOpenInit defines a msg sent by a Relayer to try to open a channel -// on Chain B. -message MsgChannelOpenTry { - option (gogoproto.equal) = false; - option (gogoproto.goproto_getters) = false; - - string port_id = 1 [(gogoproto.moretags) = "yaml:\"port_id\""]; - // in the case of crossing hello's, when both chains call OpenInit, we need the channel identifier - // of the previous channel in state INIT - string previous_channel_id = 2 [(gogoproto.moretags) = "yaml:\"previous_channel_id\""]; - Channel channel = 3 [(gogoproto.nullable) = false]; - string counterparty_version = 4 [(gogoproto.moretags) = "yaml:\"counterparty_version\""]; - bytes proof_init = 5 [(gogoproto.moretags) = "yaml:\"proof_init\""]; - ibc.core.client.v1.Height proof_height = 6 - [(gogoproto.moretags) = "yaml:\"proof_height\"", (gogoproto.nullable) = false]; - string signer = 7; -} - -// MsgChannelOpenTryResponse defines the Msg/ChannelOpenTry response type. -message MsgChannelOpenTryResponse {} - -// MsgChannelOpenAck defines a msg sent by a Relayer to Chain A to acknowledge -// the change of channel state to TRYOPEN on Chain B. -message MsgChannelOpenAck { - option (gogoproto.equal) = false; - option (gogoproto.goproto_getters) = false; - - string port_id = 1 [(gogoproto.moretags) = "yaml:\"port_id\""]; - string channel_id = 2 [(gogoproto.moretags) = "yaml:\"channel_id\""]; - string counterparty_channel_id = 3 [(gogoproto.moretags) = "yaml:\"counterparty_channel_id\""]; - string counterparty_version = 4 [(gogoproto.moretags) = "yaml:\"counterparty_version\""]; - bytes proof_try = 5 [(gogoproto.moretags) = "yaml:\"proof_try\""]; - ibc.core.client.v1.Height proof_height = 6 - [(gogoproto.moretags) = "yaml:\"proof_height\"", (gogoproto.nullable) = false]; - string signer = 7; -} - -// MsgChannelOpenAckResponse defines the Msg/ChannelOpenAck response type. -message MsgChannelOpenAckResponse {} - -// MsgChannelOpenConfirm defines a msg sent by a Relayer to Chain B to -// acknowledge the change of channel state to OPEN on Chain A. -message MsgChannelOpenConfirm { - option (gogoproto.equal) = false; - option (gogoproto.goproto_getters) = false; - - string port_id = 1 [(gogoproto.moretags) = "yaml:\"port_id\""]; - string channel_id = 2 [(gogoproto.moretags) = "yaml:\"channel_id\""]; - bytes proof_ack = 3 [(gogoproto.moretags) = "yaml:\"proof_ack\""]; - ibc.core.client.v1.Height proof_height = 4 - [(gogoproto.moretags) = "yaml:\"proof_height\"", (gogoproto.nullable) = false]; - string signer = 5; -} - -// MsgChannelOpenConfirmResponse defines the Msg/ChannelOpenConfirm response type. -message MsgChannelOpenConfirmResponse {} - -// MsgChannelCloseInit defines a msg sent by a Relayer to Chain A -// to close a channel with Chain B. -message MsgChannelCloseInit { - option (gogoproto.equal) = false; - option (gogoproto.goproto_getters) = false; - - string port_id = 1 [(gogoproto.moretags) = "yaml:\"port_id\""]; - string channel_id = 2 [(gogoproto.moretags) = "yaml:\"channel_id\""]; - string signer = 3; -} - -// MsgChannelCloseInitResponse defines the Msg/ChannelCloseInit response type. -message MsgChannelCloseInitResponse {} - -// MsgChannelCloseConfirm defines a msg sent by a Relayer to Chain B -// to acknowledge the change of channel state to CLOSED on Chain A. -message MsgChannelCloseConfirm { - option (gogoproto.equal) = false; - option (gogoproto.goproto_getters) = false; - - string port_id = 1 [(gogoproto.moretags) = "yaml:\"port_id\""]; - string channel_id = 2 [(gogoproto.moretags) = "yaml:\"channel_id\""]; - bytes proof_init = 3 [(gogoproto.moretags) = "yaml:\"proof_init\""]; - ibc.core.client.v1.Height proof_height = 4 - [(gogoproto.moretags) = "yaml:\"proof_height\"", (gogoproto.nullable) = false]; - string signer = 5; -} - -// MsgChannelCloseConfirmResponse defines the Msg/ChannelCloseConfirm response type. -message MsgChannelCloseConfirmResponse {} - -// MsgRecvPacket receives incoming IBC packet -message MsgRecvPacket { - option (gogoproto.equal) = false; - option (gogoproto.goproto_getters) = false; - - Packet packet = 1 [(gogoproto.nullable) = false]; - bytes proof_commitment = 2 [(gogoproto.moretags) = "yaml:\"proof_commitment\""]; - ibc.core.client.v1.Height proof_height = 3 - [(gogoproto.moretags) = "yaml:\"proof_height\"", (gogoproto.nullable) = false]; - string signer = 4; -} - -// MsgRecvPacketResponse defines the Msg/RecvPacket response type. -message MsgRecvPacketResponse {} - -// MsgTimeout receives timed-out packet -message MsgTimeout { - option (gogoproto.equal) = false; - option (gogoproto.goproto_getters) = false; - - Packet packet = 1 [(gogoproto.nullable) = false]; - bytes proof_unreceived = 2 [(gogoproto.moretags) = "yaml:\"proof_unreceived\""]; - ibc.core.client.v1.Height proof_height = 3 - [(gogoproto.moretags) = "yaml:\"proof_height\"", (gogoproto.nullable) = false]; - uint64 next_sequence_recv = 4 [(gogoproto.moretags) = "yaml:\"next_sequence_recv\""]; - string signer = 5; -} - -// MsgTimeoutResponse defines the Msg/Timeout response type. -message MsgTimeoutResponse {} - -// MsgTimeoutOnClose timed-out packet upon counterparty channel closure. -message MsgTimeoutOnClose { - option (gogoproto.equal) = false; - option (gogoproto.goproto_getters) = false; - - Packet packet = 1 [(gogoproto.nullable) = false]; - bytes proof_unreceived = 2 [(gogoproto.moretags) = "yaml:\"proof_unreceived\""]; - bytes proof_close = 3 [(gogoproto.moretags) = "yaml:\"proof_close\""]; - ibc.core.client.v1.Height proof_height = 4 - [(gogoproto.moretags) = "yaml:\"proof_height\"", (gogoproto.nullable) = false]; - uint64 next_sequence_recv = 5 [(gogoproto.moretags) = "yaml:\"next_sequence_recv\""]; - string signer = 6; -} - -// MsgTimeoutOnCloseResponse defines the Msg/TimeoutOnClose response type. -message MsgTimeoutOnCloseResponse {} - -// MsgAcknowledgement receives incoming IBC acknowledgement -message MsgAcknowledgement { - option (gogoproto.equal) = false; - option (gogoproto.goproto_getters) = false; - - Packet packet = 1 [(gogoproto.nullable) = false]; - bytes acknowledgement = 2; - bytes proof_acked = 3 [(gogoproto.moretags) = "yaml:\"proof_acked\""]; - ibc.core.client.v1.Height proof_height = 4 - [(gogoproto.moretags) = "yaml:\"proof_height\"", (gogoproto.nullable) = false]; - string signer = 5; -} - -// MsgAcknowledgementResponse defines the Msg/Acknowledgement response type. -message MsgAcknowledgementResponse {} diff --git a/proto/ibc/core/client/v1/client.proto b/proto/ibc/core/client/v1/client.proto deleted file mode 100644 index d8c0c28f498d..000000000000 --- a/proto/ibc/core/client/v1/client.proto +++ /dev/null @@ -1,98 +0,0 @@ -syntax = "proto3"; -package ibc.core.client.v1; - -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"; - -import "gogoproto/gogo.proto"; -import "google/protobuf/any.proto"; -import "cosmos/upgrade/v1beta1/upgrade.proto"; - -// IdentifiedClientState defines a client state with an additional client -// identifier field. -message IdentifiedClientState { - // client identifier - string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""]; - // client state - google.protobuf.Any client_state = 2 [(gogoproto.moretags) = "yaml:\"client_state\""]; -} - -// ConsensusStateWithHeight defines a consensus state with an additional height field. -message ConsensusStateWithHeight { - // consensus state height - Height height = 1 [(gogoproto.nullable) = false]; - // consensus state - google.protobuf.Any consensus_state = 2 [(gogoproto.moretags) = "yaml\"consensus_state\""]; -} - -// ClientConsensusStates defines all the stored consensus states for a given -// client. -message ClientConsensusStates { - // client identifier - string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""]; - // consensus states and their heights associated with the client - repeated ConsensusStateWithHeight consensus_states = 2 - [(gogoproto.moretags) = "yaml:\"consensus_states\"", (gogoproto.nullable) = false]; -} - -// 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 - string title = 1; - // the description of the proposal - string description = 2; - // the client identifier for the client to be updated if the proposal passes - 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]; -} - -// UpgradeProposal is a gov Content type for initiating an IBC breaking -// upgrade. -message UpgradeProposal { - option (gogoproto.goproto_getters) = false; - option (gogoproto.goproto_stringer) = false; - option (gogoproto.equal) = true; - - string title = 1; - string description = 2; - cosmos.upgrade.v1beta1.Plan plan = 3 [(gogoproto.nullable) = false]; - - // An UpgradedClientState must be provided to perform an IBC breaking upgrade. - // 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 - google.protobuf.Any upgraded_client_state = 4 [(gogoproto.moretags) = "yaml:\"upgraded_client_state\""]; -} - -// Height is a monotonically increasing data type -// that can be compared against another Height for the purposes of updating and -// freezing clients -// -// Normally the RevisionHeight is incremented at each height while keeping RevisionNumber -// the same. However some consensus algorithms may choose to reset the -// height in certain conditions e.g. hard forks, state-machine breaking changes -// In these cases, the RevisionNumber is incremented so that height continues to -// be monitonically increasing even as the RevisionHeight gets reset -message Height { - option (gogoproto.goproto_getters) = false; - option (gogoproto.goproto_stringer) = false; - - // the revision that the client is currently on - uint64 revision_number = 1 [(gogoproto.moretags) = "yaml:\"revision_number\""]; - // the height within the given revision - uint64 revision_height = 2 [(gogoproto.moretags) = "yaml:\"revision_height\""]; -} - -// Params defines the set of IBC light client parameters. -message Params { - // allowed_clients defines the list of allowed client state types. - repeated string allowed_clients = 1 [(gogoproto.moretags) = "yaml:\"allowed_clients\""]; -} diff --git a/proto/ibc/core/client/v1/genesis.proto b/proto/ibc/core/client/v1/genesis.proto deleted file mode 100644 index 16febbceef8b..000000000000 --- a/proto/ibc/core/client/v1/genesis.proto +++ /dev/null @@ -1,46 +0,0 @@ -syntax = "proto3"; -package ibc.core.client.v1; - -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"; - -import "ibc/core/client/v1/client.proto"; -import "gogoproto/gogo.proto"; - -// GenesisState defines the ibc client submodule's genesis state. -message GenesisState { - // client states with their corresponding identifiers - repeated IdentifiedClientState clients = 1 - [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "IdentifiedClientStates"]; - // consensus states from each client - repeated ClientConsensusStates clients_consensus = 2 [ - (gogoproto.nullable) = false, - (gogoproto.castrepeated) = "ClientsConsensusStates", - (gogoproto.moretags) = "yaml:\"clients_consensus\"" - ]; - // metadata from each client - repeated IdentifiedGenesisMetadata clients_metadata = 3 - [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"clients_metadata\""]; - Params params = 4 [(gogoproto.nullable) = false]; - // create localhost on initialization - bool create_localhost = 5 [(gogoproto.moretags) = "yaml:\"create_localhost\""]; - // the sequence for the next generated client identifier - uint64 next_client_sequence = 6 [(gogoproto.moretags) = "yaml:\"next_client_sequence\""]; -} - -// GenesisMetadata defines the genesis type for metadata that clients may return -// with ExportMetadata -message GenesisMetadata { - option (gogoproto.goproto_getters) = false; - - // store key of metadata without clientID-prefix - bytes key = 1; - // metadata value - bytes value = 2; -} - -// IdentifiedGenesisMetadata has the client metadata with the corresponding client id. -message IdentifiedGenesisMetadata { - string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""]; - repeated GenesisMetadata client_metadata = 2 - [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"client_metadata\""]; -} \ No newline at end of file diff --git a/proto/ibc/core/client/v1/query.proto b/proto/ibc/core/client/v1/query.proto deleted file mode 100644 index 078571dd2b2f..000000000000 --- a/proto/ibc/core/client/v1/query.proto +++ /dev/null @@ -1,152 +0,0 @@ -syntax = "proto3"; -package ibc.core.client.v1; - -import "cosmos/base/query/v1beta1/pagination.proto"; -import "ibc/core/client/v1/client.proto"; -import "google/protobuf/any.proto"; -import "google/api/annotations.proto"; -import "gogoproto/gogo.proto"; - -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"; - -// Query provides defines the gRPC querier service -service Query { - // ClientState queries an IBC light client. - rpc ClientState(QueryClientStateRequest) returns (QueryClientStateResponse) { - option (google.api.http).get = "/ibc/core/client/v1beta1/client_states/{client_id}"; - } - - // ClientStates queries all the IBC light clients of a chain. - rpc ClientStates(QueryClientStatesRequest) returns (QueryClientStatesResponse) { - option (google.api.http).get = "/ibc/core/client/v1beta1/client_states"; - } - - // ConsensusState queries a consensus state associated with a client state at - // a given height. - rpc ConsensusState(QueryConsensusStateRequest) returns (QueryConsensusStateResponse) { - option (google.api.http).get = "/ibc/core/client/v1beta1/consensus_states/{client_id}/revision/{revision_number}/" - "height/{revision_height}"; - } - - // ConsensusStates queries all the consensus state associated with a given - // client. - rpc ConsensusStates(QueryConsensusStatesRequest) returns (QueryConsensusStatesResponse) { - option (google.api.http).get = "/ibc/core/client/v1beta1/consensus_states/{client_id}"; - } - - // ClientParams queries all parameters of the ibc client. - rpc ClientParams(QueryClientParamsRequest) returns (QueryClientParamsResponse) { - option (google.api.http).get = "/ibc/client/v1beta1/params"; - } - - // UpgradedClientState queries an Upgraded IBC light client. - rpc UpgradedClientState(QueryUpgradedClientStateRequest) returns (QueryUpgradedClientStateResponse) { - option (google.api.http).get = "/ibc/core/client/v1/upgraded_client_states/{client_id}"; - } -} - -// QueryClientStateRequest is the request type for the Query/ClientState RPC -// method -message QueryClientStateRequest { - // client state unique identifier - string client_id = 1; -} - -// 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. -message QueryClientStateResponse { - // client state associated with the request identifier - google.protobuf.Any client_state = 1; - // merkle proof of existence - bytes proof = 2; - // height at which the proof was retrieved - ibc.core.client.v1.Height proof_height = 3 [(gogoproto.nullable) = false]; -} - -// QueryClientStatesRequest is the request type for the Query/ClientStates RPC -// method -message QueryClientStatesRequest { - // pagination request - cosmos.base.query.v1beta1.PageRequest pagination = 1; -} - -// QueryClientStatesResponse is the response type for the Query/ClientStates RPC -// method. -message QueryClientStatesResponse { - // list of stored ClientStates of the chain. - repeated IdentifiedClientState client_states = 1 - [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "IdentifiedClientStates"]; - // pagination response - cosmos.base.query.v1beta1.PageResponse pagination = 2; -} - -// 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. -message QueryConsensusStateRequest { - // client identifier - string client_id = 1; - // consensus state revision number - uint64 revision_number = 2; - // consensus state revision height - uint64 revision_height = 3; - // latest_height overrrides the height field and queries the latest stored - // ConsensusState - bool latest_height = 4; -} - -// QueryConsensusStateResponse is the response type for the Query/ConsensusState -// RPC method -message QueryConsensusStateResponse { - // consensus state associated with the client identifier at the given height - google.protobuf.Any consensus_state = 1; - // merkle proof of existence - bytes proof = 2; - // height at which the proof was retrieved - ibc.core.client.v1.Height proof_height = 3 [(gogoproto.nullable) = false]; -} - -// QueryConsensusStatesRequest is the request type for the Query/ConsensusStates -// RPC method. -message QueryConsensusStatesRequest { - // client identifier - string client_id = 1; - // pagination request - cosmos.base.query.v1beta1.PageRequest pagination = 2; -} - -// QueryConsensusStatesResponse is the response type for the -// Query/ConsensusStates RPC method -message QueryConsensusStatesResponse { - // consensus states associated with the identifier - repeated ConsensusStateWithHeight consensus_states = 1 [(gogoproto.nullable) = false]; - // pagination response - cosmos.base.query.v1beta1.PageResponse pagination = 2; -} - -// QueryClientParamsRequest is the request type for the Query/ClientParams RPC method. -message QueryClientParamsRequest {} - -// QueryClientParamsResponse is the response type for the Query/ClientParams RPC method. -message QueryClientParamsResponse { - // params defines the parameters of the module. - Params params = 1; -} - -// QueryUpgradedClientStateRequest is the request type for the Query/UpgradedClientState RPC -// method -message QueryUpgradedClientStateRequest { - // client state unique identifier - string client_id = 1; - // plan height of the current chain must be sent in request - // as this is the height under which upgraded client state is stored - int64 plan_height = 2; -} - -// QueryUpgradedClientStateResponse is the response type for the Query/UpgradedClientState RPC -// method. -message QueryUpgradedClientStateResponse { - // client state associated with the request identifier - google.protobuf.Any upgraded_client_state = 1; -} diff --git a/proto/ibc/core/client/v1/tx.proto b/proto/ibc/core/client/v1/tx.proto deleted file mode 100644 index a30ec8bbf10f..000000000000 --- a/proto/ibc/core/client/v1/tx.proto +++ /dev/null @@ -1,96 +0,0 @@ -syntax = "proto3"; -package ibc.core.client.v1; - -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"; - -import "gogoproto/gogo.proto"; -import "google/protobuf/any.proto"; -import "ibc/core/client/v1/client.proto"; - -// Msg defines the ibc/client Msg service. -service Msg { - // CreateClient defines a rpc handler method for MsgCreateClient. - rpc CreateClient(MsgCreateClient) returns (MsgCreateClientResponse); - - // UpdateClient defines a rpc handler method for MsgUpdateClient. - rpc UpdateClient(MsgUpdateClient) returns (MsgUpdateClientResponse); - - // UpgradeClient defines a rpc handler method for MsgUpgradeClient. - rpc UpgradeClient(MsgUpgradeClient) returns (MsgUpgradeClientResponse); - - // SubmitMisbehaviour defines a rpc handler method for MsgSubmitMisbehaviour. - rpc SubmitMisbehaviour(MsgSubmitMisbehaviour) returns (MsgSubmitMisbehaviourResponse); -} - -// MsgCreateClient defines a message to create an IBC client -message MsgCreateClient { - option (gogoproto.equal) = false; - option (gogoproto.goproto_getters) = false; - - // light client state - google.protobuf.Any client_state = 1 [(gogoproto.moretags) = "yaml:\"client_state\""]; - // consensus state associated with the client that corresponds to a given - // height. - google.protobuf.Any consensus_state = 2 [(gogoproto.moretags) = "yaml:\"consensus_state\""]; - // signer address - string signer = 3; -} - -// MsgCreateClientResponse defines the Msg/CreateClient response type. -message MsgCreateClientResponse {} - -// MsgUpdateClient defines an sdk.Msg to update a IBC client state using -// the given header. -message MsgUpdateClient { - option (gogoproto.equal) = false; - option (gogoproto.goproto_getters) = false; - - // client unique identifier - string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""]; - // header to update the light client - google.protobuf.Any header = 2; - // signer address - string signer = 3; -} - -// MsgUpdateClientResponse defines the Msg/UpdateClient response type. -message MsgUpdateClientResponse {} - -// MsgUpgradeClient defines an sdk.Msg to upgrade an IBC client to a new client state -message MsgUpgradeClient { - option (gogoproto.equal) = false; - option (gogoproto.goproto_getters) = false; - - // client unique identifier - string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""]; - // upgraded client state - google.protobuf.Any client_state = 2 [(gogoproto.moretags) = "yaml:\"client_state\""]; - // upgraded consensus state, only contains enough information to serve as a basis of trust in update logic - google.protobuf.Any consensus_state = 3 [(gogoproto.moretags) = "yaml:\"consensus_state\""]; - // proof that old chain committed to new client - bytes proof_upgrade_client = 4 [(gogoproto.moretags) = "yaml:\"proof_upgrade_client\""]; - // proof that old chain committed to new consensus state - bytes proof_upgrade_consensus_state = 5 [(gogoproto.moretags) = "yaml:\"proof_upgrade_consensus_state\""]; - // signer address - string signer = 6; -} - -// MsgUpgradeClientResponse defines the Msg/UpgradeClient response type. -message MsgUpgradeClientResponse {} - -// MsgSubmitMisbehaviour defines an sdk.Msg type that submits Evidence for -// light client misbehaviour. -message MsgSubmitMisbehaviour { - option (gogoproto.equal) = false; - option (gogoproto.goproto_getters) = false; - - // client unique identifier - string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""]; - // misbehaviour used for freezing the light client - google.protobuf.Any misbehaviour = 2; - // signer address - string signer = 3; -} - -// MsgSubmitMisbehaviourResponse defines the Msg/SubmitMisbehaviour response type. -message MsgSubmitMisbehaviourResponse {} diff --git a/proto/ibc/core/commitment/v1/commitment.proto b/proto/ibc/core/commitment/v1/commitment.proto deleted file mode 100644 index 51c10273166c..000000000000 --- a/proto/ibc/core/commitment/v1/commitment.proto +++ /dev/null @@ -1,40 +0,0 @@ -syntax = "proto3"; -package ibc.core.commitment.v1; - -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types"; - -import "gogoproto/gogo.proto"; -import "confio/proofs.proto"; - -// MerkleRoot defines a merkle root hash. -// In the Cosmos SDK, the AppHash of a block header becomes the root. -message MerkleRoot { - option (gogoproto.goproto_getters) = false; - - bytes hash = 1; -} - -// MerklePrefix is merkle path prefixed to the key. -// The constructed key from the Path and the key will be append(Path.KeyPath, -// append(Path.KeyPrefix, key...)) -message MerklePrefix { - bytes key_prefix = 1 [(gogoproto.moretags) = "yaml:\"key_prefix\""]; -} - -// MerklePath is the path used to verify commitment proofs, which can be an -// arbitrary structured object (defined by a commitment type). -// MerklePath is represented from root-to-leaf -message MerklePath { - option (gogoproto.goproto_stringer) = false; - - repeated string key_path = 1 [(gogoproto.moretags) = "yaml:\"key_path\""]; -} - -// MerkleProof is a wrapper type over a chain of CommitmentProofs. -// It demonstrates membership or non-membership for an element or set of -// elements, verifiable in conjunction with a known commitment root. Proofs -// should be succinct. -// MerkleProofs are ordered from leaf-to-root -message MerkleProof { - repeated ics23.CommitmentProof proofs = 1; -} \ No newline at end of file diff --git a/proto/ibc/core/connection/v1/connection.proto b/proto/ibc/core/connection/v1/connection.proto deleted file mode 100644 index d21e59516533..000000000000 --- a/proto/ibc/core/connection/v1/connection.proto +++ /dev/null @@ -1,104 +0,0 @@ -syntax = "proto3"; -package ibc.core.connection.v1; - -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types"; - -import "gogoproto/gogo.proto"; -import "ibc/core/commitment/v1/commitment.proto"; - -// ICS03 - Connection Data Structures as defined in -// https://github.com/cosmos/ics/tree/master/spec/ics-003-connection-semantics#data-structures - -// ConnectionEnd defines a stateful object on a chain connected to another -// separate one. -// NOTE: there must only be 2 defined ConnectionEnds to establish -// a connection between two chains. -message ConnectionEnd { - option (gogoproto.goproto_getters) = false; - // client associated with this connection. - string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""]; - // IBC version which can be utilised to determine encodings or protocols for - // channels or packets utilising this connection. - repeated Version versions = 2; - // current state of the connection end. - State state = 3; - // counterparty chain associated with this connection. - Counterparty counterparty = 4 [(gogoproto.nullable) = false]; - // delay period that must pass before a consensus state can be used for packet-verification - // NOTE: delay period logic is only implemented by some clients. - uint64 delay_period = 5 [(gogoproto.moretags) = "yaml:\"delay_period\""]; -} - -// IdentifiedConnection defines a connection with additional connection -// identifier field. -message IdentifiedConnection { - option (gogoproto.goproto_getters) = false; - // connection identifier. - string id = 1 [(gogoproto.moretags) = "yaml:\"id\""]; - // client associated with this connection. - string client_id = 2 [(gogoproto.moretags) = "yaml:\"client_id\""]; - // IBC version which can be utilised to determine encodings or protocols for - // channels or packets utilising this connection - repeated Version versions = 3; - // current state of the connection end. - State state = 4; - // counterparty chain associated with this connection. - Counterparty counterparty = 5 [(gogoproto.nullable) = false]; - // delay period associated with this connection. - uint64 delay_period = 6 [(gogoproto.moretags) = "yaml:\"delay_period\""]; -} - -// State defines if a connection is in one of the following states: -// INIT, TRYOPEN, OPEN or UNINITIALIZED. -enum State { - option (gogoproto.goproto_enum_prefix) = false; - - // Default State - STATE_UNINITIALIZED_UNSPECIFIED = 0 [(gogoproto.enumvalue_customname) = "UNINITIALIZED"]; - // A connection end has just started the opening handshake. - STATE_INIT = 1 [(gogoproto.enumvalue_customname) = "INIT"]; - // A connection end has acknowledged the handshake step on the counterparty - // chain. - STATE_TRYOPEN = 2 [(gogoproto.enumvalue_customname) = "TRYOPEN"]; - // A connection end has completed the handshake. - STATE_OPEN = 3 [(gogoproto.enumvalue_customname) = "OPEN"]; -} - -// Counterparty defines the counterparty chain associated with a connection end. -message Counterparty { - option (gogoproto.goproto_getters) = false; - - // identifies the client on the counterparty chain associated with a given - // connection. - string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""]; - // identifies the connection end on the counterparty chain associated with a - // given connection. - string connection_id = 2 [(gogoproto.moretags) = "yaml:\"connection_id\""]; - // commitment merkle prefix of the counterparty chain. - ibc.core.commitment.v1.MerklePrefix prefix = 3 [(gogoproto.nullable) = false]; -} - -// ClientPaths define all the connection paths for a client state. -message ClientPaths { - // list of connection paths - repeated string paths = 1; -} - -// ConnectionPaths define all the connection paths for a given client state. -message ConnectionPaths { - // client state unique identifier - string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""]; - // list of connection paths - repeated string paths = 2; -} - -// Version defines the versioning scheme used to negotiate the IBC verison in -// the connection handshake. -message Version { - option (gogoproto.goproto_getters) = false; - - // unique version identifier - string identifier = 1; - // list of features compatible with the specified identifier - repeated string features = 2; -} diff --git a/proto/ibc/core/connection/v1/genesis.proto b/proto/ibc/core/connection/v1/genesis.proto deleted file mode 100644 index 11df4ba1801f..000000000000 --- a/proto/ibc/core/connection/v1/genesis.proto +++ /dev/null @@ -1,16 +0,0 @@ -syntax = "proto3"; -package ibc.core.connection.v1; - -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types"; - -import "gogoproto/gogo.proto"; -import "ibc/core/connection/v1/connection.proto"; - -// GenesisState defines the ibc connection submodule's genesis state. -message GenesisState { - repeated IdentifiedConnection connections = 1 [(gogoproto.nullable) = false]; - repeated ConnectionPaths client_connection_paths = 2 - [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"client_connection_paths\""]; - // the sequence for the next generated connection identifier - uint64 next_connection_sequence = 3 [(gogoproto.moretags) = "yaml:\"next_connection_sequence\""]; -} diff --git a/proto/ibc/core/connection/v1/query.proto b/proto/ibc/core/connection/v1/query.proto deleted file mode 100644 index c5085a131f34..000000000000 --- a/proto/ibc/core/connection/v1/query.proto +++ /dev/null @@ -1,137 +0,0 @@ -syntax = "proto3"; -package ibc.core.connection.v1; - -import "gogoproto/gogo.proto"; -import "cosmos/base/query/v1beta1/pagination.proto"; -import "ibc/core/client/v1/client.proto"; -import "ibc/core/connection/v1/connection.proto"; -import "google/api/annotations.proto"; -import "google/protobuf/any.proto"; - -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types"; - -// Query provides defines the gRPC querier service -service Query { - // Connection queries an IBC connection end. - rpc Connection(QueryConnectionRequest) returns (QueryConnectionResponse) { - option (google.api.http).get = "/ibc/core/connection/v1beta1/connections/{connection_id}"; - } - - // Connections queries all the IBC connections of a chain. - rpc Connections(QueryConnectionsRequest) returns (QueryConnectionsResponse) { - option (google.api.http).get = "/ibc/core/connection/v1beta1/connections"; - } - - // ClientConnections queries the connection paths associated with a client - // state. - rpc ClientConnections(QueryClientConnectionsRequest) returns (QueryClientConnectionsResponse) { - option (google.api.http).get = "/ibc/core/connection/v1beta1/client_connections/{client_id}"; - } - - // ConnectionClientState queries the client state associated with the - // connection. - rpc ConnectionClientState(QueryConnectionClientStateRequest) returns (QueryConnectionClientStateResponse) { - option (google.api.http).get = "/ibc/core/connection/v1beta1/connections/{connection_id}/client_state"; - } - - // ConnectionConsensusState queries the consensus state associated with the - // connection. - rpc ConnectionConsensusState(QueryConnectionConsensusStateRequest) returns (QueryConnectionConsensusStateResponse) { - option (google.api.http).get = "/ibc/core/connection/v1beta1/connections/{connection_id}/consensus_state/" - "revision/{revision_number}/height/{revision_height}"; - } -} - -// QueryConnectionRequest is the request type for the Query/Connection RPC -// method -message QueryConnectionRequest { - // connection unique identifier - string connection_id = 1; -} - -// QueryConnectionResponse is the response type for the Query/Connection RPC -// method. Besides the connection end, it includes a proof and the height from -// which the proof was retrieved. -message QueryConnectionResponse { - // connection associated with the request identifier - ibc.core.connection.v1.ConnectionEnd connection = 1; - // merkle proof of existence - bytes proof = 2; - // height at which the proof was retrieved - ibc.core.client.v1.Height proof_height = 3 [(gogoproto.nullable) = false]; -} - -// QueryConnectionsRequest is the request type for the Query/Connections RPC -// method -message QueryConnectionsRequest { - cosmos.base.query.v1beta1.PageRequest pagination = 1; -} - -// QueryConnectionsResponse is the response type for the Query/Connections RPC -// method. -message QueryConnectionsResponse { - // list of stored connections of the chain. - repeated ibc.core.connection.v1.IdentifiedConnection connections = 1; - // pagination response - cosmos.base.query.v1beta1.PageResponse pagination = 2; - // query block height - ibc.core.client.v1.Height height = 3 [(gogoproto.nullable) = false]; -} - -// QueryClientConnectionsRequest is the request type for the -// Query/ClientConnections RPC method -message QueryClientConnectionsRequest { - // client identifier associated with a connection - string client_id = 1; -} - -// QueryClientConnectionsResponse is the response type for the -// Query/ClientConnections RPC method -message QueryClientConnectionsResponse { - // slice of all the connection paths associated with a client. - repeated string connection_paths = 1; - // merkle proof of existence - bytes proof = 2; - // height at which the proof was generated - ibc.core.client.v1.Height proof_height = 3 [(gogoproto.nullable) = false]; -} - -// QueryConnectionClientStateRequest is the request type for the -// Query/ConnectionClientState RPC method -message QueryConnectionClientStateRequest { - // connection identifier - string connection_id = 1 [(gogoproto.moretags) = "yaml:\"connection_id\""]; -} - -// QueryConnectionClientStateResponse is the response type for the -// Query/ConnectionClientState RPC method -message QueryConnectionClientStateResponse { - // client state associated with the channel - ibc.core.client.v1.IdentifiedClientState identified_client_state = 1; - // merkle proof of existence - bytes proof = 2; - // height at which the proof was retrieved - ibc.core.client.v1.Height proof_height = 3 [(gogoproto.nullable) = false]; -} - -// QueryConnectionConsensusStateRequest is the request type for the -// Query/ConnectionConsensusState RPC method -message QueryConnectionConsensusStateRequest { - // connection identifier - string connection_id = 1 [(gogoproto.moretags) = "yaml:\"connection_id\""]; - uint64 revision_number = 2; - uint64 revision_height = 3; -} - -// QueryConnectionConsensusStateResponse is the response type for the -// Query/ConnectionConsensusState RPC method -message QueryConnectionConsensusStateResponse { - // consensus state associated with the channel - google.protobuf.Any consensus_state = 1; - // client ID associated with the consensus state - string client_id = 2; - // merkle proof of existence - bytes proof = 3; - // height at which the proof was retrieved - ibc.core.client.v1.Height proof_height = 4 [(gogoproto.nullable) = false]; -} diff --git a/proto/ibc/core/connection/v1/tx.proto b/proto/ibc/core/connection/v1/tx.proto deleted file mode 100644 index 19b40c69c30c..000000000000 --- a/proto/ibc/core/connection/v1/tx.proto +++ /dev/null @@ -1,115 +0,0 @@ -syntax = "proto3"; -package ibc.core.connection.v1; - -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types"; - -import "gogoproto/gogo.proto"; -import "google/protobuf/any.proto"; -import "ibc/core/client/v1/client.proto"; -import "ibc/core/connection/v1/connection.proto"; - -// Msg defines the ibc/connection Msg service. -service Msg { - // ConnectionOpenInit defines a rpc handler method for MsgConnectionOpenInit. - rpc ConnectionOpenInit(MsgConnectionOpenInit) returns (MsgConnectionOpenInitResponse); - - // ConnectionOpenTry defines a rpc handler method for MsgConnectionOpenTry. - rpc ConnectionOpenTry(MsgConnectionOpenTry) returns (MsgConnectionOpenTryResponse); - - // ConnectionOpenAck defines a rpc handler method for MsgConnectionOpenAck. - rpc ConnectionOpenAck(MsgConnectionOpenAck) returns (MsgConnectionOpenAckResponse); - - // ConnectionOpenConfirm defines a rpc handler method for MsgConnectionOpenConfirm. - rpc ConnectionOpenConfirm(MsgConnectionOpenConfirm) returns (MsgConnectionOpenConfirmResponse); -} - -// MsgConnectionOpenInit defines the msg sent by an account on Chain A to -// initialize a connection with Chain B. -message MsgConnectionOpenInit { - option (gogoproto.equal) = false; - option (gogoproto.goproto_getters) = false; - - string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""]; - Counterparty counterparty = 2 [(gogoproto.nullable) = false]; - Version version = 3; - uint64 delay_period = 4 [(gogoproto.moretags) = "yaml:\"delay_period\""]; - string signer = 5; -} - -// MsgConnectionOpenInitResponse defines the Msg/ConnectionOpenInit response type. -message MsgConnectionOpenInitResponse {} - -// MsgConnectionOpenTry defines a msg sent by a Relayer to try to open a -// connection on Chain B. -message MsgConnectionOpenTry { - option (gogoproto.equal) = false; - option (gogoproto.goproto_getters) = false; - - string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""]; - // in the case of crossing hello's, when both chains call OpenInit, we need the connection identifier - // of the previous connection in state INIT - string previous_connection_id = 2 [(gogoproto.moretags) = "yaml:\"previous_connection_id\""]; - google.protobuf.Any client_state = 3 [(gogoproto.moretags) = "yaml:\"client_state\""]; - Counterparty counterparty = 4 [(gogoproto.nullable) = false]; - uint64 delay_period = 5 [(gogoproto.moretags) = "yaml:\"delay_period\""]; - repeated Version counterparty_versions = 6 [(gogoproto.moretags) = "yaml:\"counterparty_versions\""]; - ibc.core.client.v1.Height proof_height = 7 - [(gogoproto.moretags) = "yaml:\"proof_height\"", (gogoproto.nullable) = false]; - // proof of the initialization the connection on Chain A: `UNITIALIZED -> - // INIT` - bytes proof_init = 8 [(gogoproto.moretags) = "yaml:\"proof_init\""]; - // proof of client state included in message - bytes proof_client = 9 [(gogoproto.moretags) = "yaml:\"proof_client\""]; - // proof of client consensus state - bytes proof_consensus = 10 [(gogoproto.moretags) = "yaml:\"proof_consensus\""]; - ibc.core.client.v1.Height consensus_height = 11 - [(gogoproto.moretags) = "yaml:\"consensus_height\"", (gogoproto.nullable) = false]; - string signer = 12; -} - -// MsgConnectionOpenTryResponse defines the Msg/ConnectionOpenTry response type. -message MsgConnectionOpenTryResponse {} - -// MsgConnectionOpenAck defines a msg sent by a Relayer to Chain A to -// acknowledge the change of connection state to TRYOPEN on Chain B. -message MsgConnectionOpenAck { - option (gogoproto.equal) = false; - option (gogoproto.goproto_getters) = false; - - string connection_id = 1 [(gogoproto.moretags) = "yaml:\"connection_id\""]; - string counterparty_connection_id = 2 [(gogoproto.moretags) = "yaml:\"counterparty_connection_id\""]; - Version version = 3; - google.protobuf.Any client_state = 4 [(gogoproto.moretags) = "yaml:\"client_state\""]; - ibc.core.client.v1.Height proof_height = 5 - [(gogoproto.moretags) = "yaml:\"proof_height\"", (gogoproto.nullable) = false]; - // proof of the initialization the connection on Chain B: `UNITIALIZED -> - // TRYOPEN` - bytes proof_try = 6 [(gogoproto.moretags) = "yaml:\"proof_try\""]; - // proof of client state included in message - bytes proof_client = 7 [(gogoproto.moretags) = "yaml:\"proof_client\""]; - // proof of client consensus state - bytes proof_consensus = 8 [(gogoproto.moretags) = "yaml:\"proof_consensus\""]; - ibc.core.client.v1.Height consensus_height = 9 - [(gogoproto.moretags) = "yaml:\"consensus_height\"", (gogoproto.nullable) = false]; - string signer = 10; -} - -// MsgConnectionOpenAckResponse defines the Msg/ConnectionOpenAck response type. -message MsgConnectionOpenAckResponse {} - -// MsgConnectionOpenConfirm defines a msg sent by a Relayer to Chain B to -// acknowledge the change of connection state to OPEN on Chain A. -message MsgConnectionOpenConfirm { - option (gogoproto.equal) = false; - option (gogoproto.goproto_getters) = false; - - string connection_id = 1 [(gogoproto.moretags) = "yaml:\"connection_id\""]; - // proof for the change of the connection state on Chain A: `INIT -> OPEN` - bytes proof_ack = 2 [(gogoproto.moretags) = "yaml:\"proof_ack\""]; - ibc.core.client.v1.Height proof_height = 3 - [(gogoproto.moretags) = "yaml:\"proof_height\"", (gogoproto.nullable) = false]; - string signer = 4; -} - -// MsgConnectionOpenConfirmResponse defines the Msg/ConnectionOpenConfirm response type. -message MsgConnectionOpenConfirmResponse {} diff --git a/proto/ibc/core/types/v1/genesis.proto b/proto/ibc/core/types/v1/genesis.proto deleted file mode 100644 index ace508599308..000000000000 --- a/proto/ibc/core/types/v1/genesis.proto +++ /dev/null @@ -1,22 +0,0 @@ -syntax = "proto3"; -package ibc.core.types.v1; - -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/core/types"; - -import "gogoproto/gogo.proto"; -import "ibc/core/client/v1/genesis.proto"; -import "ibc/core/connection/v1/genesis.proto"; -import "ibc/core/channel/v1/genesis.proto"; - -// GenesisState defines the ibc module's genesis state. -message GenesisState { - // ICS002 - Clients genesis state - ibc.core.client.v1.GenesisState client_genesis = 1 - [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"client_genesis\""]; - // ICS003 - Connections genesis state - ibc.core.connection.v1.GenesisState connection_genesis = 2 - [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"connection_genesis\""]; - // ICS004 - Channel genesis state - ibc.core.channel.v1.GenesisState channel_genesis = 3 - [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"channel_genesis\""]; -} diff --git a/proto/ibc/lightclients/localhost/v1/localhost.proto b/proto/ibc/lightclients/localhost/v1/localhost.proto deleted file mode 100644 index d48a1c0076be..000000000000 --- a/proto/ibc/lightclients/localhost/v1/localhost.proto +++ /dev/null @@ -1,17 +0,0 @@ -syntax = "proto3"; -package ibc.lightclients.localhost.v1; - -import "gogoproto/gogo.proto"; -import "ibc/core/client/v1/client.proto"; - -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/09-localhost/types"; - -// ClientState defines a loopback (localhost) client. It requires (read-only) -// access to keys outside the client prefix. -message ClientState { - option (gogoproto.goproto_getters) = false; - // self chain ID - string chain_id = 1 [(gogoproto.moretags) = "yaml:\"chain_id\""]; - // self latest block height - ibc.core.client.v1.Height height = 2 [(gogoproto.nullable) = false]; -} diff --git a/proto/ibc/lightclients/solomachine/v1/solomachine.proto b/proto/ibc/lightclients/solomachine/v1/solomachine.proto deleted file mode 100644 index 89686f3b7f5b..000000000000 --- a/proto/ibc/lightclients/solomachine/v1/solomachine.proto +++ /dev/null @@ -1,186 +0,0 @@ -syntax = "proto3"; -package ibc.lightclients.solomachine.v1; - -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/06-solomachine/types"; - -import "ibc/core/connection/v1/connection.proto"; -import "ibc/core/channel/v1/channel.proto"; -import "gogoproto/gogo.proto"; -import "google/protobuf/any.proto"; - -// ClientState defines a solo machine client that tracks the current consensus -// state and if the client is frozen. -message ClientState { - option (gogoproto.goproto_getters) = false; - // latest sequence of the client state - uint64 sequence = 1; - // frozen sequence of the solo machine - uint64 frozen_sequence = 2 [(gogoproto.moretags) = "yaml:\"frozen_sequence\""]; - ConsensusState consensus_state = 3 [(gogoproto.moretags) = "yaml:\"consensus_state\""]; - // when set to true, will allow governance to update a solo machine client. - // The client will be unfrozen if it is frozen. - bool allow_update_after_proposal = 4 [(gogoproto.moretags) = "yaml:\"allow_update_after_proposal\""]; -} - -// ConsensusState defines a solo machine consensus state. The sequence of a consensus state -// is contained in the "height" key used in storing the consensus state. -message ConsensusState { - option (gogoproto.goproto_getters) = false; - // public key of the solo machine - google.protobuf.Any public_key = 1 [(gogoproto.moretags) = "yaml:\"public_key\""]; - // diversifier allows the same public key to be re-used across different solo machine clients - // (potentially on different chains) without being considered misbehaviour. - string diversifier = 2; - uint64 timestamp = 3; -} - -// Header defines a solo machine consensus header -message Header { - option (gogoproto.goproto_getters) = false; - // sequence to update solo machine public key at - uint64 sequence = 1; - uint64 timestamp = 2; - bytes signature = 3; - google.protobuf.Any new_public_key = 4 [(gogoproto.moretags) = "yaml:\"new_public_key\""]; - string new_diversifier = 5 [(gogoproto.moretags) = "yaml:\"new_diversifier\""]; -} - -// Misbehaviour defines misbehaviour for a solo machine which consists -// of a sequence and two signatures over different messages at that sequence. -message Misbehaviour { - option (gogoproto.goproto_getters) = false; - string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""]; - uint64 sequence = 2; - SignatureAndData signature_one = 3 [(gogoproto.moretags) = "yaml:\"signature_one\""]; - SignatureAndData signature_two = 4 [(gogoproto.moretags) = "yaml:\"signature_two\""]; -} - -// SignatureAndData contains a signature and the data signed over to create that -// signature. -message SignatureAndData { - option (gogoproto.goproto_getters) = false; - bytes signature = 1; - DataType data_type = 2 [(gogoproto.moretags) = "yaml:\"data_type\""]; - bytes data = 3; - uint64 timestamp = 4; -} - -// TimestampedSignatureData contains the signature data and the timestamp of the -// signature. -message TimestampedSignatureData { - option (gogoproto.goproto_getters) = false; - bytes signature_data = 1 [(gogoproto.moretags) = "yaml:\"signature_data\""]; - uint64 timestamp = 2; -} - -// SignBytes defines the signed bytes used for signature verification. -message SignBytes { - option (gogoproto.goproto_getters) = false; - - uint64 sequence = 1; - uint64 timestamp = 2; - string diversifier = 3; - // type of the data used - DataType data_type = 4 [(gogoproto.moretags) = "yaml:\"data_type\""]; - // marshaled data - bytes data = 5; -} - -// DataType defines the type of solo machine proof being created. This is done to preserve uniqueness of different -// data sign byte encodings. -enum DataType { - option (gogoproto.goproto_enum_prefix) = false; - - // Default State - DATA_TYPE_UNINITIALIZED_UNSPECIFIED = 0 [(gogoproto.enumvalue_customname) = "UNSPECIFIED"]; - // Data type for client state verification - DATA_TYPE_CLIENT_STATE = 1 [(gogoproto.enumvalue_customname) = "CLIENT"]; - // Data type for consensus state verification - DATA_TYPE_CONSENSUS_STATE = 2 [(gogoproto.enumvalue_customname) = "CONSENSUS"]; - // Data type for connection state verification - DATA_TYPE_CONNECTION_STATE = 3 [(gogoproto.enumvalue_customname) = "CONNECTION"]; - // Data type for channel state verification - DATA_TYPE_CHANNEL_STATE = 4 [(gogoproto.enumvalue_customname) = "CHANNEL"]; - // Data type for packet commitment verification - DATA_TYPE_PACKET_COMMITMENT = 5 [(gogoproto.enumvalue_customname) = "PACKETCOMMITMENT"]; - // Data type for packet acknowledgement verification - DATA_TYPE_PACKET_ACKNOWLEDGEMENT = 6 [(gogoproto.enumvalue_customname) = "PACKETACKNOWLEDGEMENT"]; - // Data type for packet receipt absence verification - DATA_TYPE_PACKET_RECEIPT_ABSENCE = 7 [(gogoproto.enumvalue_customname) = "PACKETRECEIPTABSENCE"]; - // Data type for next sequence recv verification - DATA_TYPE_NEXT_SEQUENCE_RECV = 8 [(gogoproto.enumvalue_customname) = "NEXTSEQUENCERECV"]; - // Data type for header verification - DATA_TYPE_HEADER = 9 [(gogoproto.enumvalue_customname) = "HEADER"]; -} - -// HeaderData returns the SignBytes data for update verification. -message HeaderData { - option (gogoproto.goproto_getters) = false; - - // header public key - google.protobuf.Any new_pub_key = 1 [(gogoproto.moretags) = "yaml:\"new_pub_key\""]; - // header diversifier - string new_diversifier = 2 [(gogoproto.moretags) = "yaml:\"new_diversifier\""]; -} - -// ClientStateData returns the SignBytes data for client state verification. -message ClientStateData { - option (gogoproto.goproto_getters) = false; - - bytes path = 1; - google.protobuf.Any client_state = 2 [(gogoproto.moretags) = "yaml:\"client_state\""]; -} - -// ConsensusStateData returns the SignBytes data for consensus state -// verification. -message ConsensusStateData { - option (gogoproto.goproto_getters) = false; - - bytes path = 1; - google.protobuf.Any consensus_state = 2 [(gogoproto.moretags) = "yaml:\"consensus_state\""]; -} - -// ConnectionStateData returns the SignBytes data for connection state -// verification. -message ConnectionStateData { - option (gogoproto.goproto_getters) = false; - - bytes path = 1; - ibc.core.connection.v1.ConnectionEnd connection = 2; -} - -// ChannelStateData returns the SignBytes data for channel state -// verification. -message ChannelStateData { - option (gogoproto.goproto_getters) = false; - - bytes path = 1; - ibc.core.channel.v1.Channel channel = 2; -} - -// PacketCommitmentData returns the SignBytes data for packet commitment -// verification. -message PacketCommitmentData { - bytes path = 1; - bytes commitment = 2; -} - -// PacketAcknowledgementData returns the SignBytes data for acknowledgement -// verification. -message PacketAcknowledgementData { - bytes path = 1; - bytes acknowledgement = 2; -} - -// PacketReceiptAbsenceData returns the SignBytes data for -// packet receipt absence verification. -message PacketReceiptAbsenceData { - bytes path = 1; -} - -// NextSequenceRecvData returns the SignBytes data for verification of the next -// sequence to be received. -message NextSequenceRecvData { - bytes path = 1; - uint64 next_seq_recv = 2 [(gogoproto.moretags) = "yaml:\"next_seq_recv\""]; -} diff --git a/proto/ibc/lightclients/tendermint/v1/tendermint.proto b/proto/ibc/lightclients/tendermint/v1/tendermint.proto deleted file mode 100644 index a6882bf432bd..000000000000 --- a/proto/ibc/lightclients/tendermint/v1/tendermint.proto +++ /dev/null @@ -1,111 +0,0 @@ -syntax = "proto3"; -package ibc.lightclients.tendermint.v1; - -option go_package = "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types"; - -import "tendermint/types/validator.proto"; -import "tendermint/types/types.proto"; -import "confio/proofs.proto"; -import "google/protobuf/duration.proto"; -import "google/protobuf/timestamp.proto"; -import "ibc/core/client/v1/client.proto"; -import "ibc/core/commitment/v1/commitment.proto"; -import "gogoproto/gogo.proto"; - -// ClientState from Tendermint tracks the current validator set, latest height, -// and a possible frozen height. -message ClientState { - option (gogoproto.goproto_getters) = false; - - string chain_id = 1; - Fraction trust_level = 2 [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"trust_level\""]; - // duration of the period since the LastestTimestamp during which the - // submitted headers are valid for upgrade - google.protobuf.Duration trusting_period = 3 - [(gogoproto.nullable) = false, (gogoproto.stdduration) = true, (gogoproto.moretags) = "yaml:\"trusting_period\""]; - // duration of the staking unbonding period - google.protobuf.Duration unbonding_period = 4 [ - (gogoproto.nullable) = false, - (gogoproto.stdduration) = true, - (gogoproto.moretags) = "yaml:\"unbonding_period\"" - ]; - // defines how much new (untrusted) header's Time can drift into the future. - google.protobuf.Duration max_clock_drift = 5 - [(gogoproto.nullable) = false, (gogoproto.stdduration) = true, (gogoproto.moretags) = "yaml:\"max_clock_drift\""]; - // Block height when the client was frozen due to a misbehaviour - ibc.core.client.v1.Height frozen_height = 6 - [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"frozen_height\""]; - // Latest height the client was updated to - ibc.core.client.v1.Height latest_height = 7 - [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"latest_height\""]; - - // Proof specifications used in verifying counterparty state - repeated ics23.ProofSpec proof_specs = 8 [(gogoproto.moretags) = "yaml:\"proof_specs\""]; - - // 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"}` - repeated string upgrade_path = 9 [(gogoproto.moretags) = "yaml:\"upgrade_path\""]; - - // This flag, when set to true, will allow governance to recover a client - // which has expired - bool allow_update_after_expiry = 10 [(gogoproto.moretags) = "yaml:\"allow_update_after_expiry\""]; - // This flag, when set to true, will allow governance to unfreeze a client - // whose chain has experienced a misbehaviour event - bool allow_update_after_misbehaviour = 11 [(gogoproto.moretags) = "yaml:\"allow_update_after_misbehaviour\""]; -} - -// ConsensusState defines the consensus state from Tendermint. -message ConsensusState { - option (gogoproto.goproto_getters) = false; - - // timestamp that corresponds to the block height in which the ConsensusState - // was stored. - google.protobuf.Timestamp timestamp = 1 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; - // commitment root (i.e app hash) - ibc.core.commitment.v1.MerkleRoot root = 2 [(gogoproto.nullable) = false]; - bytes next_validators_hash = 3 [ - (gogoproto.casttype) = "github.com/tendermint/tendermint/libs/bytes.HexBytes", - (gogoproto.moretags) = "yaml:\"next_validators_hash\"" - ]; -} - -// Misbehaviour is a wrapper over two conflicting Headers -// that implements Misbehaviour interface expected by ICS-02 -message Misbehaviour { - option (gogoproto.goproto_getters) = false; - - string client_id = 1 [(gogoproto.moretags) = "yaml:\"client_id\""]; - Header header_1 = 2 [(gogoproto.customname) = "Header1", (gogoproto.moretags) = "yaml:\"header_1\""]; - Header header_2 = 3 [(gogoproto.customname) = "Header2", (gogoproto.moretags) = "yaml:\"header_2\""]; -} - -// 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. -message Header { - .tendermint.types.SignedHeader signed_header = 1 - [(gogoproto.embed) = true, (gogoproto.moretags) = "yaml:\"signed_header\""]; - - .tendermint.types.ValidatorSet validator_set = 2 [(gogoproto.moretags) = "yaml:\"validator_set\""]; - ibc.core.client.v1.Height trusted_height = 3 - [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"trusted_height\""]; - .tendermint.types.ValidatorSet trusted_validators = 4 [(gogoproto.moretags) = "yaml:\"trusted_validators\""]; -} - -// Fraction defines the protobuf message type for tmmath.Fraction that only supports positive values. -message Fraction { - uint64 numerator = 1; - uint64 denominator = 2; -} diff --git a/simapp/app.go b/simapp/app.go index 4086585e684c..000d5234fd37 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -64,17 +64,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/gov" govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" - transfer "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer" - ibctransferkeeper "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/keeper" - 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" - ibcclientclient "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/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" - ibcmock "github.com/cosmos/cosmos-sdk/x/ibc/testing/mock" "github.com/cosmos/cosmos-sdk/x/mint" mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" @@ -121,16 +110,13 @@ var ( distr.AppModuleBasic{}, gov.NewAppModuleBasic( paramsclient.ProposalHandler, distrclient.ProposalHandler, upgradeclient.ProposalHandler, upgradeclient.CancelProposalHandler, - ibcclientclient.UpdateClientProposalHandler, ibcclientclient.UpgradeProposalHandler, ), params.AppModuleBasic{}, crisis.AppModuleBasic{}, slashing.AppModuleBasic{}, - ibc.AppModuleBasic{}, feegrant.AppModuleBasic{}, upgrade.AppModuleBasic{}, evidence.AppModuleBasic{}, - transfer.AppModuleBasic{}, authz.AppModuleBasic{}, vesting.AppModuleBasic{}, ) @@ -143,7 +129,6 @@ var ( stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking}, stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, govtypes.ModuleName: {authtypes.Burner}, - ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner}, } // module accounts that are allowed to receive tokens @@ -186,16 +171,9 @@ type SimApp struct { 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 FeeGrantKeeper feegrantkeeper.Keeper - // make scoped keepers public for test purposes - ScopedIBCKeeper capabilitykeeper.ScopedKeeper - ScopedTransferKeeper capabilitykeeper.ScopedKeeper - ScopedIBCMockKeeper capabilitykeeper.ScopedKeeper - // the module manager mm *module.Manager @@ -234,8 +212,8 @@ 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, feegranttypes.StoreKey, - evidencetypes.StoreKey, ibctransfertypes.StoreKey, capabilitytypes.StoreKey, + govtypes.StoreKey, paramstypes.StoreKey, upgradetypes.StoreKey, feegranttypes.StoreKey, + evidencetypes.StoreKey, capabilitytypes.StoreKey, authztypes.StoreKey, ) tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey) @@ -257,13 +235,7 @@ func NewSimApp( // set the BaseApp's parameter store bApp.SetParamStore(app.ParamsKeeper.Subspace(baseapp.Paramspace).WithKeyTable(paramskeeper.ConsensusParamsKeyTable())) - // add capability keeper and ScopeToModule for ibc module app.CapabilityKeeper = capabilitykeeper.NewKeeper(appCodec, keys[capabilitytypes.StoreKey], memKeys[capabilitytypes.MemStoreKey]) - scopedIBCKeeper := app.CapabilityKeeper.ScopeToModule(ibchost.ModuleName) - scopedTransferKeeper := app.CapabilityKeeper.ScopeToModule(ibctransfertypes.ModuleName) - // NOTE: the IBC mock keeper and application module is used only for testing core IBC. Do - // note replicate if you do not need to test core IBC or light clients. - scopedIBCMockKeeper := app.CapabilityKeeper.ScopeToModule(ibcmock.ModuleName) // add keepers app.AccountKeeper = authkeeper.NewAccountKeeper( @@ -299,11 +271,6 @@ func NewSimApp( stakingtypes.NewMultiStakingHooks(app.DistrKeeper.Hooks(), app.SlashingKeeper.Hooks()), ) - // Create IBC Keeper - app.IBCKeeper = ibckeeper.NewKeeper( - appCodec, keys[ibchost.StoreKey], app.GetSubspace(ibchost.ModuleName), app.StakingKeeper, app.UpgradeKeeper, scopedIBCKeeper, - ) - app.AuthzKeeper = authzkeeper.NewKeeper(keys[authztypes.StoreKey], appCodec, app.BaseApp.MsgServiceRouter()) // register the proposal types @@ -311,31 +278,12 @@ func NewSimApp( govRouter.AddRoute(govtypes.RouterKey, govtypes.ProposalHandler). AddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(app.ParamsKeeper)). AddRoute(distrtypes.RouterKey, distr.NewCommunityPoolSpendProposalHandler(app.DistrKeeper)). - AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper)). - AddRoute(ibcclienttypes.RouterKey, ibcclient.NewClientProposalHandler(app.IBCKeeper.ClientKeeper)) + AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper)) app.GovKeeper = govkeeper.NewKeeper( appCodec, keys[govtypes.StoreKey], app.GetSubspace(govtypes.ModuleName), app.AccountKeeper, app.BankKeeper, &stakingKeeper, govRouter, ) - // Create Transfer Keepers - app.TransferKeeper = ibctransferkeeper.NewKeeper( - appCodec, keys[ibctransfertypes.StoreKey], app.GetSubspace(ibctransfertypes.ModuleName), - app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper, - app.AccountKeeper, app.BankKeeper, scopedTransferKeeper, - ) - transferModule := transfer.NewAppModule(app.TransferKeeper) - - // NOTE: the IBC mock keeper and application module is used only for testing core IBC. Do - // note replicate if you do not need to test core IBC or light clients. - mockModule := ibcmock.NewAppModule(scopedIBCMockKeeper) - - // Create static IBC router, add transfer route, then set and seal it - ibcRouter := porttypes.NewRouter() - ibcRouter.AddRoute(ibctransfertypes.ModuleName, transferModule) - ibcRouter.AddRoute(ibcmock.ModuleName, mockModule) - app.IBCKeeper.SetRouter(ibcRouter) - // create evidence keeper with router evidenceKeeper := evidencekeeper.NewKeeper( appCodec, keys[evidencetypes.StoreKey], &app.StakingKeeper, app.SlashingKeeper, @@ -369,10 +317,8 @@ func NewSimApp( staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper), upgrade.NewAppModule(app.UpgradeKeeper), evidence.NewAppModule(app.EvidenceKeeper), - ibc.NewAppModule(app.IBCKeeper), params.NewAppModule(app.ParamsKeeper), authz.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), - transferModule, ) // During begin block slashing happens after distr.BeginBlocker so that @@ -381,7 +327,7 @@ func NewSimApp( // NOTE: staking module is required if HistoricalEntries param > 0 app.mm.SetOrderBeginBlockers( upgradetypes.ModuleName, minttypes.ModuleName, distrtypes.ModuleName, slashingtypes.ModuleName, - evidencetypes.ModuleName, stakingtypes.ModuleName, ibchost.ModuleName, + evidencetypes.ModuleName, stakingtypes.ModuleName, ) app.mm.SetOrderEndBlockers(crisistypes.ModuleName, govtypes.ModuleName, stakingtypes.ModuleName) @@ -393,7 +339,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, authztypes.ModuleName, ibctransfertypes.ModuleName, + genutiltypes.ModuleName, evidencetypes.ModuleName, authztypes.ModuleName, feegranttypes.ModuleName, ) @@ -422,8 +368,6 @@ func NewSimApp( params.NewAppModule(app.ParamsKeeper), evidence.NewAppModule(app.EvidenceKeeper), authz.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), - ibc.NewAppModule(app.IBCKeeper), - transferModule, ) app.sm.RegisterStoreDecoders() @@ -460,13 +404,6 @@ func NewSimApp( app.CapabilityKeeper.InitializeAndSeal(ctx) } - app.ScopedIBCKeeper = scopedIBCKeeper - app.ScopedTransferKeeper = scopedTransferKeeper - - // NOTE: the IBC mock keeper and application module is used only for testing core IBC. Do - // note replicate if you do not need to test core IBC or light clients. - app.ScopedIBCMockKeeper = scopedIBCMockKeeper - return app } @@ -659,8 +596,6 @@ func initParamsKeeper(appCodec codec.BinaryMarshaler, legacyAmino *codec.LegacyA paramsKeeper.Subspace(slashingtypes.ModuleName) paramsKeeper.Subspace(govtypes.ModuleName).WithKeyTable(govtypes.ParamKeyTable()) paramsKeeper.Subspace(crisistypes.ModuleName) - paramsKeeper.Subspace(ibctransfertypes.ModuleName) - paramsKeeper.Subspace(ibchost.ModuleName) return paramsKeeper } diff --git a/simapp/app_test.go b/simapp/app_test.go index 8f596f5ecc0d..7e14ab062b79 100644 --- a/simapp/app_test.go +++ b/simapp/app_test.go @@ -25,8 +25,6 @@ import ( feegrant "github.com/cosmos/cosmos-sdk/x/feegrant" "github.com/cosmos/cosmos-sdk/x/genutil" "github.com/cosmos/cosmos-sdk/x/gov" - transfer "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer" - ibc "github.com/cosmos/cosmos-sdk/x/ibc/core" "github.com/cosmos/cosmos-sdk/x/mint" "github.com/cosmos/cosmos-sdk/x/params" "github.com/cosmos/cosmos-sdk/x/slashing" @@ -171,11 +169,9 @@ func TestRunMigrations(t *testing.T) { "slashing": slashing.AppModule{}.ConsensusVersion(), "gov": gov.AppModule{}.ConsensusVersion(), "params": params.AppModule{}.ConsensusVersion(), - "ibc": ibc.AppModule{}.ConsensusVersion(), "upgrade": upgrade.AppModule{}.ConsensusVersion(), "vesting": vesting.AppModule{}.ConsensusVersion(), "feegrant": feegrant.AppModule{}.ConsensusVersion(), - "transfer": transfer.AppModule{}.ConsensusVersion(), "evidence": evidence.AppModule{}.ConsensusVersion(), "crisis": crisis.AppModule{}.ConsensusVersion(), "genutil": genutil.AppModule{}.ConsensusVersion(), diff --git a/simapp/sim_test.go b/simapp/sim_test.go index 1c0609c1b82d..130bee23c0d2 100644 --- a/simapp/sim_test.go +++ b/simapp/sim_test.go @@ -25,8 +25,6 @@ import ( distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" - ibctransfertypes "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" - ibchost "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" "github.com/cosmos/cosmos-sdk/x/simulation" @@ -176,8 +174,6 @@ func TestAppImportExport(t *testing.T) { {app.keys[govtypes.StoreKey], newApp.keys[govtypes.StoreKey], [][]byte{}}, {app.keys[evidencetypes.StoreKey], newApp.keys[evidencetypes.StoreKey], [][]byte{}}, {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{}}, } diff --git a/x/README.md b/x/README.md index 7ca27e617e55..6d07a5debadf 100644 --- a/x/README.md +++ b/x/README.md @@ -15,8 +15,6 @@ Here are some production-grade modules that can be used in Cosmos SDK applicatio - [Distribution](distribution/spec/README.md) - Fee distribution, and staking token provision distribution. - [Evidence](evidence/spec/README.md) - Evidence handling for double signing, misbehaviour, etc. - [Governance](gov/spec/README.md) - On-chain proposals and voting. -- [IBC](ibc/spec/README.md) - IBC protocol for transport, authentication and ordering. -- [IBC Transfer](ibc/spec/README.md) - Cross-chain fungible token transfer implementation through IBC. - [Mint](mint/spec/README.md) - Creation of new units of staking token. - [Params](params/spec/README.md) - Globally available parameter store. - [Slashing](slashing/spec/README.md) - Validator punishment mechanisms. @@ -24,3 +22,7 @@ Here are some production-grade modules that can be used in Cosmos SDK applicatio - [Upgrade](upgrade/spec/README.md) - Software upgrades handling and coordination. To learn more about the process of building modules, visit the [building modules reference documentation](../docs/building-modules/README.md). + +## IBC + +The IBC module for the SDK has moved to its [own repository](https://github.com/cosmos/ibc-go). diff --git a/x/auth/ante/ante_test.go b/x/auth/ante/ante_test.go index 9b268b1ec60d..5ec5f0ca4199 100644 --- a/x/auth/ante/ante_test.go +++ b/x/auth/ante/ante_test.go @@ -482,7 +482,8 @@ func (suite *AnteTestSuite) TestAnteHandlerFees() { { "signer as enough funds, should pass", func() { - accNums = []uint64{7} + accNums = []uint64{acc1.GetAccountNumber()} + modAcc := suite.app.AccountKeeper.GetModuleAccount(suite.ctx, types.FeeCollectorName) suite.Require().True(suite.app.BankKeeper.GetAllBalances(suite.ctx, modAcc.GetAddress()).Empty()) @@ -511,6 +512,7 @@ func (suite *AnteTestSuite) TestAnteHandlerFees() { for _, tc := range testCases { suite.Run(fmt.Sprintf("Case %s", tc.desc), func() { + suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder() tc.malleate() diff --git a/x/auth/client/rest/rest_test.go b/x/auth/client/rest/rest_test.go index 9ecb3e842ff6..3c62648bb79c 100644 --- a/x/auth/client/rest/rest_test.go +++ b/x/auth/client/rest/rest_test.go @@ -29,8 +29,6 @@ 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" ) type IntegrationTestSuite struct { @@ -98,45 +96,6 @@ func mkStdTx() legacytx.StdTx { } } -// Create an IBC tx that's encoded as amino-JSON. Since we can't amino-marshal -// a tx with "cosmos-sdk/MsgTransfer" using the SDK, we just hardcode the tx -// here. But external clients might, see https://github.com/cosmos/cosmos-sdk/issues/8022. -func mkIBCStdTx() []byte { - ibcTx := `{ - "account_number": "68", - "chain_id": "stargate-4", - "fee": { - "amount": [ - { - "amount": "3500", - "denom": "umuon" - } - ], - "gas": "350000" - }, - "memo": "", - "msg": [ - { - "type": "cosmos-sdk/MsgTransfer", - "value": { - "receiver": "cosmos1q9wtnlwdjrhwtcjmt2uq77jrgx7z3usrq2yz7z", - "sender": "cosmos1q9wtnlwdjrhwtcjmt2uq77jrgx7z3usrq2yz7z", - "source_channel": "THEslipperCHANNEL", - "source_port": "transfer", - "token": { - "amount": "1000000", - "denom": "umuon" - } - } - } - ], - "sequence": "24" - }` - req := fmt.Sprintf(`{"tx":%s,"mode":"async"}`, ibcTx) - - return []byte(req) -} - func (s *IntegrationTestSuite) TestEncodeDecode() { var require = s.Require() val := s.network.Validators[0] @@ -182,16 +141,6 @@ func (s *IntegrationTestSuite) TestQueryAccountWithColon() { s.Require().Contains(string(res), "decoding bech32 failed") } -func (s *IntegrationTestSuite) TestEncodeIBCTx() { - val := s.network.Validators[0] - - req := mkIBCStdTx() - res, err := rest.PostRequest(fmt.Sprintf("%s/txs/encode", val.APIAddress), "application/json", []byte(req)) - s.Require().NoError(err) - - s.Require().Contains(string(res), authrest.ErrEncodeDecode.Error()) -} - func (s *IntegrationTestSuite) TestBroadcastTxRequest() { stdTx := mkStdTx() @@ -205,16 +154,6 @@ func (s *IntegrationTestSuite) TestBroadcastTxRequest() { s.Require().NotEmpty(txRes.TxHash) } -func (s *IntegrationTestSuite) TestBroadcastIBCTxRequest() { - val := s.network.Validators[0] - - req := mkIBCStdTx() - res, err := rest.PostRequest(fmt.Sprintf("%s/txs", val.APIAddress), "application/json", []byte(req)) - s.Require().NoError(err) - - 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. func (s *IntegrationTestSuite) testQueryTx(txHeight int64, txHash, txRecipient string) { val0 := s.network.Validators[0] @@ -497,83 +436,6 @@ func (s *IntegrationTestSuite) testQueryIBCTx(txRes sdk.TxResponse, cmd *cobra.C s.Require().Contains(errResp.Error, errMsg) } -// TestLegacyRestErrMessages creates two IBC txs, one that fails, one that -// succeeds, and make sure we cannot query any of them (with pretty error msg). -// Our intension is to test the error message of querying a message which is -// signed with proto, since IBC won't support legacy amino at all we are -// considering a message from IBC module. -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(), - `{"@type":"/ibc.lightclients.solomachine.v1.ConsensusState","public_key":{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AtK50+5pJOoaa04qqAqrnyAqsYrwrR/INnA6UPIaYZlp"},"diversifier":"testing","timestamp":"10"}`, - ) - - testCases := []struct { - desc string - cmd *cobra.Command - args []string - code uint32 - }{ - { - "Failing IBC message", - ibccli.NewChannelCloseInitCmd(), - []string{ - "121", // dummy port-id - "channel-0", // dummy channel-id - 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), - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), - fmt.Sprintf("--%s=foobar", flags.FlagMemo), - }, - uint32(7), - }, - { - "Successful IBC message", - ibcclientcli.NewCreateClientCmd(), - []string{ - 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()), - fmt.Sprintf("--gas=%d", flags.DefaultGasLimit), - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), - fmt.Sprintf("--%s=foobar", flags.FlagMemo), - }, - uint32(0), - }, - } - - for _, tc := range testCases { - s.Run(fmt.Sprintf("Case %s", tc.desc), func() { - out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, tc.cmd, tc.args) - s.Require().NoError(err) - var txRes sdk.TxResponse - s.Require().NoError(val.ClientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), &txRes)) - s.Require().Equal(tc.code, txRes.Code) - - s.Require().NoError(s.network.WaitForNextBlock()) - - s.testQueryIBCTx(txRes, tc.cmd, tc.args) - }) - } -} - // TestLegacyMultiSig creates a legacy multisig transaction, and makes sure // we can query it via the legacy REST endpoint. // ref: https://github.com/cosmos/cosmos-sdk/issues/8679 diff --git a/x/capability/keeper/keeper_test.go b/x/capability/keeper/keeper_test.go index e62176a72463..2868fd1d9b8b 100644 --- a/x/capability/keeper/keeper_test.go +++ b/x/capability/keeper/keeper_test.go @@ -114,16 +114,6 @@ func (suite *KeeperTestSuite) TestNewCapability() { suite.Require().Nil(cap) } -func (suite *KeeperTestSuite) TestOriginalCapabilityKeeper() { - got, ok := suite.app.ScopedIBCKeeper.GetCapability(suite.ctx, "invalid") - suite.Require().False(ok) - suite.Require().Nil(got) - - port, ok := suite.app.ScopedIBCKeeper.GetCapability(suite.ctx, "ports/transfer") - suite.Require().True(ok) - suite.Require().NotNil(port) -} - func (suite *KeeperTestSuite) TestAuthenticateCapability() { sk1 := suite.keeper.ScopeToModule(banktypes.ModuleName) sk2 := suite.keeper.ScopeToModule(stakingtypes.ModuleName) diff --git a/x/ibc/applications/transfer/client/cli/cli.go b/x/ibc/applications/transfer/client/cli/cli.go deleted file mode 100644 index d3ca8341e95c..000000000000 --- a/x/ibc/applications/transfer/client/cli/cli.go +++ /dev/null @@ -1,42 +0,0 @@ -package cli - -import ( - "github.com/spf13/cobra" - - "github.com/cosmos/cosmos-sdk/client" -) - -// GetQueryCmd returns the query commands for IBC connections -func GetQueryCmd() *cobra.Command { - queryCmd := &cobra.Command{ - Use: "ibc-transfer", - Short: "IBC fungible token transfer query subcommands", - DisableFlagParsing: true, - SuggestionsMinimumDistance: 2, - } - - queryCmd.AddCommand( - GetCmdQueryDenomTrace(), - GetCmdQueryDenomTraces(), - GetCmdParams(), - ) - - return queryCmd -} - -// NewTxCmd returns the transaction commands for IBC fungible token transfer -func NewTxCmd() *cobra.Command { - txCmd := &cobra.Command{ - Use: "ibc-transfer", - Short: "IBC fungible token transfer transaction subcommands", - DisableFlagParsing: true, - SuggestionsMinimumDistance: 2, - RunE: client.ValidateCmd, - } - - txCmd.AddCommand( - NewTransferTxCmd(), - ) - - return txCmd -} diff --git a/x/ibc/applications/transfer/client/cli/query.go b/x/ibc/applications/transfer/client/cli/query.go deleted file mode 100644 index b9658e05ae92..000000000000 --- a/x/ibc/applications/transfer/client/cli/query.go +++ /dev/null @@ -1,108 +0,0 @@ -package cli - -import ( - "fmt" - - "github.com/spf13/cobra" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/version" - "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" -) - -// GetCmdQueryDenomTrace defines the command to query a a denomination trace from a given hash. -func GetCmdQueryDenomTrace() *cobra.Command { - cmd := &cobra.Command{ - Use: "denom-trace [hash]", - Short: "Query the denom trace info from a given trace hash", - Long: "Query the denom trace info from a given trace hash", - Example: fmt.Sprintf("%s query ibc-transfer denom-trace [hash]", version.AppName), - Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } - queryClient := types.NewQueryClient(clientCtx) - - req := &types.QueryDenomTraceRequest{ - Hash: args[0], - } - - res, err := queryClient.DenomTrace(cmd.Context(), req) - if err != nil { - return err - } - - return clientCtx.PrintProto(res) - }, - } - - flags.AddQueryFlagsToCmd(cmd) - return cmd -} - -// GetCmdQueryDenomTraces defines the command to query all the denomination trace infos -// that this chain mantains. -func GetCmdQueryDenomTraces() *cobra.Command { - cmd := &cobra.Command{ - Use: "denom-traces", - Short: "Query the trace info for all token denominations", - Long: "Query the trace info for all token denominations", - Example: fmt.Sprintf("%s query ibc-transfer denom-traces", version.AppName), - Args: cobra.NoArgs, - RunE: func(cmd *cobra.Command, _ []string) error { - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } - queryClient := types.NewQueryClient(clientCtx) - - pageReq, err := client.ReadPageRequest(cmd.Flags()) - if err != nil { - return err - } - - req := &types.QueryDenomTracesRequest{ - Pagination: pageReq, - } - - res, err := queryClient.DenomTraces(cmd.Context(), req) - if err != nil { - return err - } - - return clientCtx.PrintProto(res) - }, - } - flags.AddQueryFlagsToCmd(cmd) - flags.AddPaginationFlagsToCmd(cmd, "denominations trace") - - return cmd -} - -// GetCmdParams returns the command handler for ibc-transfer parameter querying. -func GetCmdParams() *cobra.Command { - cmd := &cobra.Command{ - Use: "params", - Short: "Query the current ibc-transfer parameters", - Long: "Query the current ibc-transfer parameters", - Args: cobra.NoArgs, - Example: fmt.Sprintf("%s query ibc-transfer params", version.AppName), - RunE: func(cmd *cobra.Command, _ []string) error { - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } - queryClient := types.NewQueryClient(clientCtx) - - res, _ := queryClient.Params(cmd.Context(), &types.QueryParamsRequest{}) - return clientCtx.PrintProto(res.Params) - }, - } - - flags.AddQueryFlagsToCmd(cmd) - - return cmd -} diff --git a/x/ibc/applications/transfer/client/cli/tx.go b/x/ibc/applications/transfer/client/cli/tx.go deleted file mode 100644 index 1f9e92f63cad..000000000000 --- a/x/ibc/applications/transfer/client/cli/tx.go +++ /dev/null @@ -1,117 +0,0 @@ -package cli - -import ( - "fmt" - "strings" - - "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/ibc/applications/transfer/types" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - channelutils "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/client/utils" -) - -const ( - flagPacketTimeoutHeight = "packet-timeout-height" - flagPacketTimeoutTimestamp = "packet-timeout-timestamp" - flagAbsoluteTimeouts = "absolute-timeouts" -) - -// NewTransferTxCmd returns the command to create a NewMsgTransfer transaction -func NewTransferTxCmd() *cobra.Command { - cmd := &cobra.Command{ - Use: "transfer [src-port] [src-channel] [receiver] [amount]", - Short: "Transfer a fungible token through IBC", - Long: strings.TrimSpace(`Transfer a fungible token through IBC. Timeouts can be specified -as absolute or relative using the "absolute-timeouts" flag. Timeout height can be set by passing in the height string -in the form {revision}-{height} using the "packet-timeout-height" flag. Relative timeouts are added to -the block height and block timestamp queried from the latest consensus state corresponding -to the counterparty channel. Any timeout set to 0 is disabled.`), - Example: fmt.Sprintf("%s tx ibc-transfer transfer [src-port] [src-channel] [receiver] [amount]", version.AppName), - Args: cobra.ExactArgs(4), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - sender := clientCtx.GetFromAddress() - srcPort := args[0] - srcChannel := args[1] - receiver := args[2] - - coin, err := sdk.ParseCoinNormalized(args[3]) - if err != nil { - return err - } - - if !strings.HasPrefix(coin.Denom, "ibc/") { - denomTrace := types.ParseDenomTrace(coin.Denom) - coin.Denom = denomTrace.IBCDenom() - } - - timeoutHeightStr, err := cmd.Flags().GetString(flagPacketTimeoutHeight) - if err != nil { - return err - } - timeoutHeight, err := clienttypes.ParseHeight(timeoutHeightStr) - if err != nil { - return err - } - - timeoutTimestamp, err := cmd.Flags().GetUint64(flagPacketTimeoutTimestamp) - if err != nil { - return err - } - - absoluteTimeouts, err := cmd.Flags().GetBool(flagAbsoluteTimeouts) - if err != nil { - return err - } - - // if the timeouts are not absolute, retrieve latest block height and block timestamp - // for the consensus state connected to the destination port/channel - if !absoluteTimeouts { - consensusState, height, _, err := channelutils.QueryLatestConsensusState(clientCtx, srcPort, srcChannel) - if err != nil { - return err - } - - if !timeoutHeight.IsZero() { - absoluteHeight := height - absoluteHeight.RevisionNumber += timeoutHeight.RevisionNumber - absoluteHeight.RevisionHeight += timeoutHeight.RevisionHeight - timeoutHeight = absoluteHeight - } - - if timeoutTimestamp != 0 { - timeoutTimestamp = consensusState.GetTimestamp() + timeoutTimestamp - } - } - - msg := types.NewMsgTransfer( - srcPort, srcChannel, coin, sender, receiver, timeoutHeight, timeoutTimestamp, - ) - svcMsgClientConn := &msgservice.ServiceMsgClientConn{} - msgClient := types.NewMsgClient(svcMsgClientConn) - _, err = msgClient.Transfer(cmd.Context(), msg) - if err != nil { - return err - } - - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) - }, - } - - cmd.Flags().String(flagPacketTimeoutHeight, types.DefaultRelativePacketTimeoutHeight, "Packet timeout block height. The timeout is disabled when set to 0-0.") - cmd.Flags().Uint64(flagPacketTimeoutTimestamp, types.DefaultRelativePacketTimeoutTimestamp, "Packet timeout timestamp in nanoseconds. Default is 10 minutes. The timeout is disabled when set to 0.") - cmd.Flags().Bool(flagAbsoluteTimeouts, false, "Timeout flags are used as absolute timeouts.") - flags.AddTxFlagsToCmd(cmd) - - return cmd -} diff --git a/x/ibc/applications/transfer/handler.go b/x/ibc/applications/transfer/handler.go deleted file mode 100644 index 7c992c920e72..000000000000 --- a/x/ibc/applications/transfer/handler.go +++ /dev/null @@ -1,23 +0,0 @@ -package transfer - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" -) - -// NewHandler returns sdk.Handler for IBC token transfer module messages -func NewHandler(k types.MsgServer) sdk.Handler { - return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { - ctx = ctx.WithEventManager(sdk.NewEventManager()) - - switch msg := msg.(type) { - case *types.MsgTransfer: - res, err := k.Transfer(sdk.WrapSDKContext(ctx), msg) - return sdk.WrapServiceResult(ctx, res, err) - - default: - return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized ICS-20 transfer message type: %T", msg) - } - } -} diff --git a/x/ibc/applications/transfer/handler_test.go b/x/ibc/applications/transfer/handler_test.go deleted file mode 100644 index 92a04210115d..000000000000 --- a/x/ibc/applications/transfer/handler_test.go +++ /dev/null @@ -1,123 +0,0 @@ -package transfer_test - -import ( - "testing" - - "github.com/stretchr/testify/suite" - - 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" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" -) - -type TransferTestSuite struct { - suite.Suite - - coordinator *ibctesting.Coordinator - - // testing chains used for convenience and readability - chainA *ibctesting.TestChain - chainB *ibctesting.TestChain - chainC *ibctesting.TestChain -} - -func (suite *TransferTestSuite) SetupTest() { - suite.coordinator = ibctesting.NewCoordinator(suite.T(), 3) - suite.chainA = suite.coordinator.GetChain(ibctesting.GetChainID(0)) - suite.chainB = suite.coordinator.GetChain(ibctesting.GetChainID(1)) - suite.chainC = suite.coordinator.GetChain(ibctesting.GetChainID(2)) -} - -// constructs a send from chainA to chainB on the established channel/connection -// and sends the same coin back from chainB to chainA. -func (suite *TransferTestSuite) TestHandleMsgTransfer() { - // setup between chainA and chainB - clientA, clientB, connA, connB := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - channelA, channelB := suite.coordinator.CreateTransferChannels(suite.chainA, suite.chainB, connA, connB, channeltypes.UNORDERED) - // originalBalance := suite.chainA.App.BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), sdk.DefaultBondDenom) - timeoutHeight := clienttypes.NewHeight(0, 110) - - coinToSendToB := sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)) - - // send from chainA to chainB - msg := types.NewMsgTransfer(channelA.PortID, channelA.ID, coinToSendToB, suite.chainA.SenderAccount.GetAddress(), suite.chainB.SenderAccount.GetAddress().String(), timeoutHeight, 0) - - err := suite.coordinator.SendMsg(suite.chainA, suite.chainB, clientB, msg) - suite.Require().NoError(err) // message committed - - // relay send - fungibleTokenPacket := types.NewFungibleTokenPacketData(coinToSendToB.Denom, coinToSendToB.Amount.Uint64(), suite.chainA.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String()) - packet := channeltypes.NewPacket(fungibleTokenPacket.GetBytes(), 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0) - ack := channeltypes.NewResultAcknowledgement([]byte{byte(1)}) - err = suite.coordinator.RelayPacket(suite.chainA, suite.chainB, clientA, clientB, packet, ack.GetBytes()) - suite.Require().NoError(err) // relay committed - - // check that voucher exists on chain B - voucherDenomTrace := types.ParseDenomTrace(types.GetPrefixedDenom(packet.GetDestPort(), packet.GetDestChannel(), sdk.DefaultBondDenom)) - balance := suite.chainB.App.BankKeeper.GetBalance(suite.chainB.GetContext(), suite.chainB.SenderAccount.GetAddress(), voucherDenomTrace.IBCDenom()) - - coinSentFromAToB := types.GetTransferCoin(channelB.PortID, channelB.ID, sdk.DefaultBondDenom, 100) - suite.Require().Equal(coinSentFromAToB, balance) - - // setup between chainB to chainC - clientOnBForC, clientOnCForB, connOnBForC, connOnCForB := suite.coordinator.SetupClientConnections(suite.chainB, suite.chainC, exported.Tendermint) - channelOnBForC, channelOnCForB := suite.coordinator.CreateTransferChannels(suite.chainB, suite.chainC, connOnBForC, connOnCForB, channeltypes.UNORDERED) - - // send from chainB to chainC - msg = types.NewMsgTransfer(channelOnBForC.PortID, channelOnBForC.ID, coinSentFromAToB, suite.chainB.SenderAccount.GetAddress(), suite.chainC.SenderAccount.GetAddress().String(), timeoutHeight, 0) - - err = suite.coordinator.SendMsg(suite.chainB, suite.chainC, clientOnCForB, msg) - suite.Require().NoError(err) // message committed - - // relay send - // NOTE: fungible token is prefixed with the full trace in order to verify the packet commitment - fullDenomPath := types.GetPrefixedDenom(channelOnCForB.PortID, channelOnCForB.ID, voucherDenomTrace.GetFullDenomPath()) - fungibleTokenPacket = types.NewFungibleTokenPacketData(voucherDenomTrace.GetFullDenomPath(), coinSentFromAToB.Amount.Uint64(), suite.chainB.SenderAccount.GetAddress().String(), suite.chainC.SenderAccount.GetAddress().String()) - packet = channeltypes.NewPacket(fungibleTokenPacket.GetBytes(), 1, channelOnBForC.PortID, channelOnBForC.ID, channelOnCForB.PortID, channelOnCForB.ID, timeoutHeight, 0) - err = suite.coordinator.RelayPacket(suite.chainB, suite.chainC, clientOnBForC, clientOnCForB, packet, ack.GetBytes()) - suite.Require().NoError(err) // relay committed - - coinSentFromBToC := sdk.NewInt64Coin(types.ParseDenomTrace(fullDenomPath).IBCDenom(), 100) - balance = suite.chainC.App.BankKeeper.GetBalance(suite.chainC.GetContext(), suite.chainC.SenderAccount.GetAddress(), coinSentFromBToC.Denom) - - // check that the balance is updated on chainC - suite.Require().Equal(coinSentFromBToC, balance) - - // check that balance on chain B is empty - balance = suite.chainB.App.BankKeeper.GetBalance(suite.chainB.GetContext(), suite.chainB.SenderAccount.GetAddress(), coinSentFromBToC.Denom) - suite.Require().Zero(balance.Amount.Int64()) - - // send from chainC back to chainB - msg = types.NewMsgTransfer(channelOnCForB.PortID, channelOnCForB.ID, coinSentFromBToC, suite.chainC.SenderAccount.GetAddress(), suite.chainB.SenderAccount.GetAddress().String(), timeoutHeight, 0) - - err = suite.coordinator.SendMsg(suite.chainC, suite.chainB, clientOnBForC, msg) - suite.Require().NoError(err) // message committed - - // relay send - // NOTE: fungible token is prefixed with the full trace in order to verify the packet commitment - fungibleTokenPacket = types.NewFungibleTokenPacketData(fullDenomPath, coinSentFromBToC.Amount.Uint64(), suite.chainC.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String()) - packet = channeltypes.NewPacket(fungibleTokenPacket.GetBytes(), 1, channelOnCForB.PortID, channelOnCForB.ID, channelOnBForC.PortID, channelOnBForC.ID, timeoutHeight, 0) - err = suite.coordinator.RelayPacket(suite.chainC, suite.chainB, clientOnCForB, clientOnBForC, packet, ack.GetBytes()) - suite.Require().NoError(err) // relay committed - - balance = suite.chainB.App.BankKeeper.GetBalance(suite.chainB.GetContext(), suite.chainB.SenderAccount.GetAddress(), coinSentFromAToB.Denom) - - // check that the balance on chainA returned back to the original state - suite.Require().Equal(coinSentFromAToB, balance) - - // check that module account escrow address is empty - escrowAddress := types.GetEscrowAddress(packet.GetDestPort(), packet.GetDestChannel()) - balance = suite.chainB.App.BankKeeper.GetBalance(suite.chainB.GetContext(), escrowAddress, sdk.DefaultBondDenom) - suite.Require().Equal(sdk.NewCoin(sdk.DefaultBondDenom, sdk.ZeroInt()), balance) - - // check that balance on chain B is empty - balance = suite.chainC.App.BankKeeper.GetBalance(suite.chainC.GetContext(), suite.chainC.SenderAccount.GetAddress(), voucherDenomTrace.IBCDenom()) - suite.Require().Zero(balance.Amount.Int64()) -} - -func TestTransferTestSuite(t *testing.T) { - suite.Run(t, new(TransferTestSuite)) -} diff --git a/x/ibc/applications/transfer/keeper/MBT_README.md b/x/ibc/applications/transfer/keeper/MBT_README.md deleted file mode 100644 index 8a5930f6d390..000000000000 --- a/x/ibc/applications/transfer/keeper/MBT_README.md +++ /dev/null @@ -1,51 +0,0 @@ -## Token Transfer Model-based Testing Guide - -In the process of IBC Audit performed by Informal Systems, we have implemented -a preliminary set of model-based tests for the ICS-20 Token Transfer implementation. - -Model-based tests are based on the formal `TLA+` model of the Token transfer relay functions: see [relay.tla](relay_model/relay.tla). -The tests themselves are simple `TLA+` assertions, that describe the desired shape of execution that send or receive tokens; -see [relay_tests.tla](relay_model/relay_tests.tla) for some examples. -To be able to specify test assertions the TLA+ model contains the `history` variable, -which records the whole execution history. -So, by way of referring to `history` you simply specify declaratively what execution history you want to see. - -After you have specified your `TLA+` test, you can run it using [Apalache model checker](https://github.com/informalsystems/apalache). -E.g. for the test `TestUnescrowTokens` run - -```bash -apalache-mc check --inv=TestUnescrowTokensInv relay_tests.tla -``` - -In case there are no error in the TLA+ model or in the test assertions, this will produce a couple of so-called _counterexamples_. -This is a terminology from the model-checking community; for the testing purposes they can be considered simply as model executions. -See the files `counterexample.tla` for human-readable representation, and `counterexample.json` for machine-readable one. - -In order to execute the produced test, you need to translate it into another format. -For that translation you need the tool [Jsonatr (JSON Arrifact Translator)](https://github.com/informalsystems/jsonatr). -It performs the translation using this [transformation spec](relay_model/apalache-to-relay-test2.json); - -To transform a counterexample into a test, run - -```bash -jsonatr --use apalache-to-relay-test2.json --in counterexample.json --out model_based_tests/YourTestName.json -``` - -Now, if you run `go test` in this directory, the file you have produced above should be picked up by the [model-based test driver](mbt_relay_test.go), -and executed automatically. - - -The easiest way to run Apalache is by -[using a Docker image](https://github.com/informalsystems/apalache/blob/master/docs/manual.md#useDocker); -to run Jsonatr you need to locally clone the repository, and then, -after building it, add the `target/debug` directory into your `PATH`. - -To wrap Apalache docker image into an executable you might create the following executable bash script `apalache-mc`: - -```bash -#!/bin/bash -docker run --rm -v $(pwd):/var/apalache apalache/mc $@ -``` - - -In case of any questions please don't hesitate to contact Andrey Kuprianov (andrey@informal.systems). \ No newline at end of file diff --git a/x/ibc/applications/transfer/keeper/encoding.go b/x/ibc/applications/transfer/keeper/encoding.go deleted file mode 100644 index ddb1bc4b0c52..000000000000 --- a/x/ibc/applications/transfer/keeper/encoding.go +++ /dev/null @@ -1,35 +0,0 @@ -package keeper - -import ( - "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" -) - -// UnmarshalDenomTrace attempts to decode and return an DenomTrace object from -// raw encoded bytes. -func (k Keeper) UnmarshalDenomTrace(bz []byte) (types.DenomTrace, error) { - var denomTrace types.DenomTrace - if err := k.cdc.UnmarshalBinaryBare(bz, &denomTrace); err != nil { - return types.DenomTrace{}, err - } - return denomTrace, nil -} - -// MustUnmarshalDenomTrace attempts to decode and return an DenomTrace object from -// raw encoded bytes. It panics on error. -func (k Keeper) MustUnmarshalDenomTrace(bz []byte) types.DenomTrace { - var denomTrace types.DenomTrace - k.cdc.MustUnmarshalBinaryBare(bz, &denomTrace) - return denomTrace -} - -// MarshalDenomTrace attempts to encode an DenomTrace object and returns the -// raw encoded bytes. -func (k Keeper) MarshalDenomTrace(denomTrace types.DenomTrace) ([]byte, error) { - return k.cdc.MarshalBinaryBare(&denomTrace) -} - -// MustMarshalDenomTrace attempts to encode an DenomTrace object and returns the -// raw encoded bytes. It panics on error. -func (k Keeper) MustMarshalDenomTrace(denomTrace types.DenomTrace) []byte { - return k.cdc.MustMarshalBinaryBare(&denomTrace) -} diff --git a/x/ibc/applications/transfer/keeper/genesis.go b/x/ibc/applications/transfer/keeper/genesis.go deleted file mode 100644 index 58a0c0811573..000000000000 --- a/x/ibc/applications/transfer/keeper/genesis.go +++ /dev/null @@ -1,45 +0,0 @@ -package keeper - -import ( - "fmt" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" -) - -// InitGenesis initializes the ibc-transfer state and binds to PortID. -func (k Keeper) InitGenesis(ctx sdk.Context, state types.GenesisState) { - k.SetPort(ctx, state.PortId) - - for _, trace := range state.DenomTraces { - k.SetDenomTrace(ctx, trace) - } - - // Only try to bind to port if it is not already bound, since we may already own - // port capability from capability InitGenesis - if !k.IsBound(ctx, state.PortId) { - // transfer module binds to the transfer port on InitChain - // and claims the returned capability - err := k.BindPort(ctx, state.PortId) - if err != nil { - panic(fmt.Sprintf("could not claim port capability: %v", err)) - } - } - - k.SetParams(ctx, state.Params) - - // check if the module account exists - moduleAcc := k.GetTransferAccount(ctx) - if moduleAcc == nil { - panic(fmt.Sprintf("%s module account has not been set", types.ModuleName)) - } -} - -// ExportGenesis exports ibc-transfer module's portID and denom trace info into its genesis state. -func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState { - return &types.GenesisState{ - PortId: k.GetPort(ctx), - DenomTraces: k.GetAllDenomTraces(ctx), - Params: k.GetParams(ctx), - } -} diff --git a/x/ibc/applications/transfer/keeper/genesis_test.go b/x/ibc/applications/transfer/keeper/genesis_test.go deleted file mode 100644 index a85434911fb8..000000000000 --- a/x/ibc/applications/transfer/keeper/genesis_test.go +++ /dev/null @@ -1,39 +0,0 @@ -package keeper_test - -import ( - "fmt" - - "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" -) - -func (suite *KeeperTestSuite) TestGenesis() { - var ( - path string - traces types.Traces - ) - - for i := 0; i < 5; i++ { - prefix := fmt.Sprintf("transfer/channelToChain%d", i) - if i == 0 { - path = prefix - } else { - path = prefix + "/" + path - } - - denomTrace := types.DenomTrace{ - BaseDenom: "uatom", - Path: path, - } - traces = append(types.Traces{denomTrace}, traces...) - suite.chainA.App.TransferKeeper.SetDenomTrace(suite.chainA.GetContext(), denomTrace) - } - - genesis := suite.chainA.App.TransferKeeper.ExportGenesis(suite.chainA.GetContext()) - - suite.Require().Equal(types.PortID, genesis.PortId) - suite.Require().Equal(traces.Sort(), genesis.DenomTraces) - - suite.Require().NotPanics(func() { - suite.chainA.App.TransferKeeper.InitGenesis(suite.chainA.GetContext(), *genesis) - }) -} diff --git a/x/ibc/applications/transfer/keeper/grpc_query.go b/x/ibc/applications/transfer/keeper/grpc_query.go deleted file mode 100644 index b6347895b42b..000000000000 --- a/x/ibc/applications/transfer/keeper/grpc_query.go +++ /dev/null @@ -1,83 +0,0 @@ -package keeper - -import ( - "context" - "fmt" - - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - - "github.com/cosmos/cosmos-sdk/store/prefix" - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/cosmos/cosmos-sdk/types/query" - "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" -) - -var _ types.QueryServer = Keeper{} - -// DenomTrace implements the Query/DenomTrace gRPC method -func (q Keeper) DenomTrace(c context.Context, req *types.QueryDenomTraceRequest) (*types.QueryDenomTraceResponse, error) { - if req == nil { - return nil, status.Error(codes.InvalidArgument, "empty request") - } - - hash, err := types.ParseHexHash(req.Hash) - if err != nil { - return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("invalid denom trace hash %s, %s", req.Hash, err)) - } - - ctx := sdk.UnwrapSDKContext(c) - denomTrace, found := q.GetDenomTrace(ctx, hash) - if !found { - return nil, status.Error( - codes.NotFound, - sdkerrors.Wrap(types.ErrTraceNotFound, req.Hash).Error(), - ) - } - - return &types.QueryDenomTraceResponse{ - DenomTrace: &denomTrace, - }, nil -} - -// DenomTraces implements the Query/DenomTraces gRPC method -func (q Keeper) DenomTraces(c context.Context, req *types.QueryDenomTracesRequest) (*types.QueryDenomTracesResponse, error) { - if req == nil { - return nil, status.Error(codes.InvalidArgument, "empty request") - } - - ctx := sdk.UnwrapSDKContext(c) - - traces := types.Traces{} - store := prefix.NewStore(ctx.KVStore(q.storeKey), types.DenomTraceKey) - - pageRes, err := query.Paginate(store, req.Pagination, func(_, value []byte) error { - result, err := q.UnmarshalDenomTrace(value) - if err != nil { - return err - } - - traces = append(traces, result) - return nil - }) - - if err != nil { - return nil, err - } - - return &types.QueryDenomTracesResponse{ - DenomTraces: traces.Sort(), - Pagination: pageRes, - }, nil -} - -// Params implements the Query/Params gRPC method -func (q Keeper) Params(c context.Context, _ *types.QueryParamsRequest) (*types.QueryParamsResponse, error) { - ctx := sdk.UnwrapSDKContext(c) - params := q.GetParams(ctx) - - return &types.QueryParamsResponse{ - Params: ¶ms, - }, nil -} diff --git a/x/ibc/applications/transfer/keeper/grpc_query_test.go b/x/ibc/applications/transfer/keeper/grpc_query_test.go deleted file mode 100644 index 0b16e0726b58..000000000000 --- a/x/ibc/applications/transfer/keeper/grpc_query_test.go +++ /dev/null @@ -1,142 +0,0 @@ -package keeper_test - -import ( - "fmt" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/query" - "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" -) - -func (suite *KeeperTestSuite) TestQueryDenomTrace() { - var ( - req *types.QueryDenomTraceRequest - expTrace types.DenomTrace - ) - - testCases := []struct { - msg string - malleate func() - expPass bool - }{ - { - "invalid hex hash", - func() { - req = &types.QueryDenomTraceRequest{ - Hash: "!@#!@#!", - } - }, - false, - }, - { - "not found denom trace", - func() { - expTrace.Path = "transfer/channelToA/transfer/channelToB" - expTrace.BaseDenom = "uatom" - req = &types.QueryDenomTraceRequest{ - Hash: expTrace.Hash().String(), - } - }, - false, - }, - { - "success", - func() { - expTrace.Path = "transfer/channelToA/transfer/channelToB" - expTrace.BaseDenom = "uatom" - suite.chainA.App.TransferKeeper.SetDenomTrace(suite.chainA.GetContext(), expTrace) - - req = &types.QueryDenomTraceRequest{ - Hash: expTrace.Hash().String(), - } - }, - true, - }, - } - - for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { - suite.SetupTest() // reset - - tc.malleate() - ctx := sdk.WrapSDKContext(suite.chainA.GetContext()) - - res, err := suite.queryClient.DenomTrace(ctx, req) - - if tc.expPass { - suite.Require().NoError(err) - suite.Require().NotNil(res) - suite.Require().Equal(&expTrace, res.DenomTrace) - } else { - suite.Require().Error(err) - } - }) - } -} - -func (suite *KeeperTestSuite) TestQueryDenomTraces() { - var ( - req *types.QueryDenomTracesRequest - expTraces = types.Traces(nil) - ) - - testCases := []struct { - msg string - malleate func() - expPass bool - }{ - { - "empty pagination", - func() { - req = &types.QueryDenomTracesRequest{} - }, - true, - }, - { - "success", - func() { - expTraces = append(expTraces, types.DenomTrace{Path: "", BaseDenom: "uatom"}) - expTraces = append(expTraces, types.DenomTrace{Path: "transfer/channelToB", BaseDenom: "uatom"}) - expTraces = append(expTraces, types.DenomTrace{Path: "transfer/channelToA/transfer/channelToB", BaseDenom: "uatom"}) - - for _, trace := range expTraces { - suite.chainA.App.TransferKeeper.SetDenomTrace(suite.chainA.GetContext(), trace) - } - - req = &types.QueryDenomTracesRequest{ - Pagination: &query.PageRequest{ - Limit: 5, - CountTotal: false, - }, - } - }, - true, - }, - } - - for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { - suite.SetupTest() // reset - - tc.malleate() - ctx := sdk.WrapSDKContext(suite.chainA.GetContext()) - - res, err := suite.queryClient.DenomTraces(ctx, req) - - if tc.expPass { - suite.Require().NoError(err) - suite.Require().NotNil(res) - suite.Require().Equal(expTraces.Sort(), res.DenomTraces) - } else { - suite.Require().Error(err) - } - }) - } -} - -func (suite *KeeperTestSuite) TestQueryParams() { - ctx := sdk.WrapSDKContext(suite.chainA.GetContext()) - expParams := types.DefaultParams() - res, _ := suite.queryClient.Params(ctx, &types.QueryParamsRequest{}) - suite.Require().Equal(&expParams, res.Params) -} diff --git a/x/ibc/applications/transfer/keeper/keeper.go b/x/ibc/applications/transfer/keeper/keeper.go deleted file mode 100644 index a2eebb55e1ea..000000000000 --- a/x/ibc/applications/transfer/keeper/keeper.go +++ /dev/null @@ -1,169 +0,0 @@ -package keeper - -import ( - tmbytes "github.com/tendermint/tendermint/libs/bytes" - "github.com/tendermint/tendermint/libs/log" - - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/store/prefix" - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" - capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" - "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" -) - -// Keeper defines the IBC fungible transfer keeper -type Keeper struct { - storeKey sdk.StoreKey - cdc codec.BinaryMarshaler - paramSpace paramtypes.Subspace - - channelKeeper types.ChannelKeeper - portKeeper types.PortKeeper - authKeeper types.AccountKeeper - bankKeeper types.BankKeeper - scopedKeeper capabilitykeeper.ScopedKeeper -} - -// NewKeeper creates a new IBC transfer Keeper instance -func NewKeeper( - cdc codec.BinaryMarshaler, key sdk.StoreKey, paramSpace paramtypes.Subspace, - channelKeeper types.ChannelKeeper, portKeeper types.PortKeeper, - authKeeper types.AccountKeeper, bankKeeper types.BankKeeper, scopedKeeper capabilitykeeper.ScopedKeeper, -) Keeper { - - // ensure ibc transfer module account is set - if addr := authKeeper.GetModuleAddress(types.ModuleName); addr == nil { - panic("the IBC transfer module account has not been set") - } - - // set KeyTable if it has not already been set - if !paramSpace.HasKeyTable() { - paramSpace = paramSpace.WithKeyTable(types.ParamKeyTable()) - } - - return Keeper{ - cdc: cdc, - storeKey: key, - paramSpace: paramSpace, - channelKeeper: channelKeeper, - portKeeper: portKeeper, - authKeeper: authKeeper, - bankKeeper: bankKeeper, - scopedKeeper: scopedKeeper, - } -} - -// Logger returns a module-specific logger. -func (k Keeper) Logger(ctx sdk.Context) log.Logger { - return ctx.Logger().With("module", "x/"+host.ModuleName+"-"+types.ModuleName) -} - -// GetTransferAccount returns the ICS20 - transfers ModuleAccount -func (k Keeper) GetTransferAccount(ctx sdk.Context) authtypes.ModuleAccountI { - return k.authKeeper.GetModuleAccount(ctx, types.ModuleName) -} - -// ChanCloseInit defines a wrapper function for the channel Keeper's function -// in order to expose it to the ICS20 transfer handler. -func (k Keeper) ChanCloseInit(ctx sdk.Context, portID, channelID string) error { - capName := host.ChannelCapabilityPath(portID, channelID) - chanCap, ok := k.scopedKeeper.GetCapability(ctx, capName) - if !ok { - return sdkerrors.Wrapf(channeltypes.ErrChannelCapabilityNotFound, "could not retrieve channel capability at: %s", capName) - } - return k.channelKeeper.ChanCloseInit(ctx, portID, channelID, chanCap) -} - -// IsBound checks if the transfer module is already bound to the desired port -func (k Keeper) IsBound(ctx sdk.Context, portID string) bool { - _, ok := k.scopedKeeper.GetCapability(ctx, host.PortPath(portID)) - return ok -} - -// BindPort defines a wrapper function for the ort Keeper's function in -// order to expose it to module's InitGenesis function -func (k Keeper) BindPort(ctx sdk.Context, portID string) error { - cap := k.portKeeper.BindPort(ctx, portID) - return k.ClaimCapability(ctx, cap, host.PortPath(portID)) -} - -// GetPort returns the portID for the transfer module. Used in ExportGenesis -func (k Keeper) GetPort(ctx sdk.Context) string { - store := ctx.KVStore(k.storeKey) - return string(store.Get(types.PortKey)) -} - -// SetPort sets the portID for the transfer module. Used in InitGenesis -func (k Keeper) SetPort(ctx sdk.Context, portID string) { - store := ctx.KVStore(k.storeKey) - store.Set(types.PortKey, []byte(portID)) -} - -// GetDenomTrace retreives the full identifiers trace and base denomination from the store. -func (k Keeper) GetDenomTrace(ctx sdk.Context, denomTraceHash tmbytes.HexBytes) (types.DenomTrace, bool) { - store := prefix.NewStore(ctx.KVStore(k.storeKey), types.DenomTraceKey) - bz := store.Get(denomTraceHash) - if bz == nil { - return types.DenomTrace{}, false - } - - denomTrace := k.MustUnmarshalDenomTrace(bz) - return denomTrace, true -} - -// HasDenomTrace checks if a the key with the given denomination trace hash exists on the store. -func (k Keeper) HasDenomTrace(ctx sdk.Context, denomTraceHash tmbytes.HexBytes) bool { - store := prefix.NewStore(ctx.KVStore(k.storeKey), types.DenomTraceKey) - return store.Has(denomTraceHash) -} - -// SetDenomTrace sets a new {trace hash -> denom trace} pair to the store. -func (k Keeper) SetDenomTrace(ctx sdk.Context, denomTrace types.DenomTrace) { - store := prefix.NewStore(ctx.KVStore(k.storeKey), types.DenomTraceKey) - bz := k.MustMarshalDenomTrace(denomTrace) - store.Set(denomTrace.Hash(), bz) -} - -// GetAllDenomTraces returns the trace information for all the denominations. -func (k Keeper) GetAllDenomTraces(ctx sdk.Context) types.Traces { - traces := types.Traces{} - k.IterateDenomTraces(ctx, func(denomTrace types.DenomTrace) bool { - traces = append(traces, denomTrace) - return false - }) - - return traces.Sort() -} - -// IterateDenomTraces iterates over the denomination traces in the store -// and performs a callback function. -func (k Keeper) IterateDenomTraces(ctx sdk.Context, cb func(denomTrace types.DenomTrace) bool) { - store := ctx.KVStore(k.storeKey) - iterator := sdk.KVStorePrefixIterator(store, types.DenomTraceKey) - - defer iterator.Close() - for ; iterator.Valid(); iterator.Next() { - - denomTrace := k.MustUnmarshalDenomTrace(iterator.Value()) - if cb(denomTrace) { - break - } - } -} - -// AuthenticateCapability wraps the scopedKeeper's AuthenticateCapability function -func (k Keeper) AuthenticateCapability(ctx sdk.Context, cap *capabilitytypes.Capability, name string) bool { - return k.scopedKeeper.AuthenticateCapability(ctx, cap, name) -} - -// ClaimCapability allows the transfer module that can claim a capability that IBC module -// passes to it -func (k Keeper) ClaimCapability(ctx sdk.Context, cap *capabilitytypes.Capability, name string) error { - return k.scopedKeeper.ClaimCapability(ctx, cap, name) -} diff --git a/x/ibc/applications/transfer/keeper/keeper_test.go b/x/ibc/applications/transfer/keeper/keeper_test.go deleted file mode 100644 index cce9cbccae45..000000000000 --- a/x/ibc/applications/transfer/keeper/keeper_test.go +++ /dev/null @@ -1,51 +0,0 @@ -package keeper_test - -import ( - "testing" - - "github.com/stretchr/testify/suite" - "github.com/tendermint/tendermint/crypto" - - "github.com/cosmos/cosmos-sdk/baseapp" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" -) - -type KeeperTestSuite struct { - suite.Suite - - coordinator *ibctesting.Coordinator - - // testing chains used for convenience and readability - chainA *ibctesting.TestChain - chainB *ibctesting.TestChain - chainC *ibctesting.TestChain - - queryClient types.QueryClient -} - -func (suite *KeeperTestSuite) SetupTest() { - suite.coordinator = ibctesting.NewCoordinator(suite.T(), 3) - suite.chainA = suite.coordinator.GetChain(ibctesting.GetChainID(0)) - suite.chainB = suite.coordinator.GetChain(ibctesting.GetChainID(1)) - suite.chainC = suite.coordinator.GetChain(ibctesting.GetChainID(2)) - - queryHelper := baseapp.NewQueryServerTestHelper(suite.chainA.GetContext(), suite.chainA.App.InterfaceRegistry()) - types.RegisterQueryServer(queryHelper, suite.chainA.App.TransferKeeper) - suite.queryClient = types.NewQueryClient(queryHelper) -} - -func (suite *KeeperTestSuite) TestGetTransferAccount() { - expectedMaccAddr := sdk.AccAddress(crypto.AddressHash([]byte(types.ModuleName))) - - macc := suite.chainA.App.TransferKeeper.GetTransferAccount(suite.chainA.GetContext()) - - suite.Require().NotNil(macc) - suite.Require().Equal(types.ModuleName, macc.GetName()) - suite.Require().Equal(expectedMaccAddr, macc.GetAddress()) -} - -func TestKeeperTestSuite(t *testing.T) { - suite.Run(t, new(KeeperTestSuite)) -} diff --git a/x/ibc/applications/transfer/keeper/mbt_relay_test.go b/x/ibc/applications/transfer/keeper/mbt_relay_test.go deleted file mode 100644 index cd64fbabc252..000000000000 --- a/x/ibc/applications/transfer/keeper/mbt_relay_test.go +++ /dev/null @@ -1,378 +0,0 @@ -package keeper_test - -/// This file is a test driver for model-based tests generated from the TLA+ model of token transfer -/// Written by Andrey Kuprianov within the scope of IBC Audit performed by Informal Systems. -/// In case of any questions please don't hesitate to contact andrey@informal.systems. - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "strconv" - "strings" - - "github.com/tendermint/tendermint/crypto" - - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" -) - -type TlaBalance struct { - Address []string `json:"address"` - Denom []string `json:"denom"` - Amount int64 `json:"amount"` -} - -type TlaFungibleTokenPacketData struct { - Sender string `json:"sender"` - Receiver string `json:"receiver"` - Amount int `json:"amount"` - Denom []string `json:"denom"` -} - -type TlaFungibleTokenPacket struct { - SourceChannel string `json:"sourceChannel"` - SourcePort string `json:"sourcePort"` - DestChannel string `json:"destChannel"` - DestPort string `json:"destPort"` - Data TlaFungibleTokenPacketData `json:"data"` -} - -type TlaOnRecvPacketTestCase = struct { - // The required subset of bank balances - BankBefore []TlaBalance `json:"bankBefore"` - // The packet to process - Packet TlaFungibleTokenPacket `json:"packet"` - // The handler to call - Handler string `json:"handler"` - // The expected changes in the bank - BankAfter []TlaBalance `json:"bankAfter"` - // Whether OnRecvPacket should fail or not - Error bool `json:"error"` -} - -type FungibleTokenPacket struct { - SourceChannel string - SourcePort string - DestChannel string - DestPort string - Data types.FungibleTokenPacketData -} - -type OnRecvPacketTestCase = struct { - description string - // The required subset of bank balances - bankBefore []Balance - // The packet to process - packet FungibleTokenPacket - // The handler to call - handler string - // The expected bank state after processing (wrt. bankBefore) - bankAfter []Balance - // Whether OnRecvPacket should pass or fail - pass bool -} - -type OwnedCoin struct { - Address string - Denom string -} - -type Balance struct { - Id string - Address string - Denom string - Amount sdk.Int -} - -func AddressFromString(address string) string { - return sdk.AccAddress(crypto.AddressHash([]byte(address))).String() -} - -func AddressFromTla(addr []string) string { - if len(addr) != 3 { - panic("failed to convert from TLA+ address: wrong number of address components") - } - s := "" - if len(addr[0]) == 0 && len(addr[1]) == 0 { - // simple address: id - s = addr[2] - } else if len(addr[2]) == 0 { - // escrow address: ics20-1\x00port/channel - s = fmt.Sprintf("%s\x00%s/%s", types.Version, addr[0], addr[1]) - } else { - panic("failed to convert from TLA+ address: neither simple nor escrow address") - } - return s -} - -func DenomFromTla(denom []string) string { - var i int - for i = 0; i+1 < len(denom) && len(denom[i]) == 0 && len(denom[i+1]) == 0; i += 2 { - // skip empty prefixes - } - return strings.Join(denom[i:], "/") -} - -func BalanceFromTla(balance TlaBalance) Balance { - return Balance{ - Id: AddressFromTla(balance.Address), - Address: AddressFromString(AddressFromTla(balance.Address)), - Denom: DenomFromTla(balance.Denom), - Amount: sdk.NewInt(balance.Amount), - } -} - -func BalancesFromTla(tla []TlaBalance) []Balance { - balances := make([]Balance, 0) - for _, b := range tla { - balances = append(balances, BalanceFromTla(b)) - } - return balances -} - -func FungibleTokenPacketFromTla(packet TlaFungibleTokenPacket) FungibleTokenPacket { - return FungibleTokenPacket{ - SourceChannel: packet.SourceChannel, - SourcePort: packet.SourcePort, - DestChannel: packet.DestChannel, - DestPort: packet.DestPort, - Data: types.NewFungibleTokenPacketData( - DenomFromTla(packet.Data.Denom), - uint64(packet.Data.Amount), - AddressFromString(packet.Data.Sender), - AddressFromString(packet.Data.Receiver)), - } -} - -func OnRecvPacketTestCaseFromTla(tc TlaOnRecvPacketTestCase) OnRecvPacketTestCase { - return OnRecvPacketTestCase{ - description: "auto-generated", - bankBefore: BalancesFromTla(tc.BankBefore), - packet: FungibleTokenPacketFromTla(tc.Packet), - handler: tc.Handler, - bankAfter: BalancesFromTla(tc.BankAfter), // TODO different semantics - pass: !tc.Error, - } -} - -var addressMap = make(map[string]string) - -type Bank struct { - balances map[OwnedCoin]sdk.Int -} - -// Make an empty bank -func MakeBank() Bank { - return Bank{balances: make(map[OwnedCoin]sdk.Int)} -} - -// Subtract other bank from this bank -func (bank *Bank) Sub(other *Bank) Bank { - diff := MakeBank() - for coin, amount := range bank.balances { - otherAmount, exists := other.balances[coin] - if exists { - diff.balances[coin] = amount.Sub(otherAmount) - } else { - diff.balances[coin] = amount - } - } - for coin, amount := range other.balances { - if _, exists := bank.balances[coin]; !exists { - diff.balances[coin] = amount.Neg() - } - } - return diff -} - -// Set specific bank balance -func (bank *Bank) SetBalance(address string, denom string, amount sdk.Int) { - bank.balances[OwnedCoin{address, denom}] = amount -} - -// Set several balances at once -func (bank *Bank) SetBalances(balances []Balance) { - for _, balance := range balances { - bank.balances[OwnedCoin{balance.Address, balance.Denom}] = balance.Amount - addressMap[balance.Address] = balance.Id - } -} - -func NullCoin() OwnedCoin { - return OwnedCoin{ - Address: AddressFromString(""), - Denom: "", - } -} - -// Set several balances at once -func BankFromBalances(balances []Balance) Bank { - bank := MakeBank() - for _, balance := range balances { - coin := OwnedCoin{balance.Address, balance.Denom} - if coin != NullCoin() { // ignore null coin - bank.balances[coin] = balance.Amount - addressMap[balance.Address] = balance.Id - } - } - return bank -} - -// String representation of all bank balances -func (bank *Bank) String() string { - str := "" - for coin, amount := range bank.balances { - str += coin.Address - if addressMap[coin.Address] != "" { - str += "(" + addressMap[coin.Address] + ")" - } - str += " : " + coin.Denom + " = " + amount.String() + "\n" - } - return str -} - -// String representation of non-zero bank balances -func (bank *Bank) NonZeroString() string { - str := "" - for coin, amount := range bank.balances { - if !amount.IsZero() { - str += coin.Address + " : " + coin.Denom + " = " + amount.String() + "\n" - } - } - return str -} - -// Construct a bank out of the chain bank -func BankOfChain(chain *ibctesting.TestChain) Bank { - bank := MakeBank() - chain.App.BankKeeper.IterateAllBalances(chain.GetContext(), func(address sdk.AccAddress, coin sdk.Coin) (stop bool) { - fullDenom := coin.Denom - if strings.HasPrefix(coin.Denom, "ibc/") { - fullDenom, _ = chain.App.TransferKeeper.DenomPathFromHash(chain.GetContext(), coin.Denom) - } - bank.SetBalance(address.String(), fullDenom, coin.Amount) - return false - }) - return bank -} - -// 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) - bankChange := bankAfter.Sub(bankBefore) - diff := bankChange.Sub(expectedBankChange) - NonZeroString := diff.NonZeroString() - if len(NonZeroString) != 0 { - return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, "Unexpected changes in the bank: \n"+NonZeroString) - } - return nil -} - -func (suite *KeeperTestSuite) TestModelBasedRelay() { - dirname := "model_based_tests/" - files, err := ioutil.ReadDir(dirname) - if err != nil { - panic(fmt.Errorf("Failed to read model-based test files: %w", err)) - } - for _, file_info := range files { - var tlaTestCases = []TlaOnRecvPacketTestCase{} - if !strings.HasSuffix(file_info.Name(), ".json") { - continue - } - jsonBlob, err := ioutil.ReadFile(dirname + file_info.Name()) - if err != nil { - panic(fmt.Errorf("Failed to read JSON test fixture: %w", err)) - } - err = json.Unmarshal([]byte(jsonBlob), &tlaTestCases) - if err != nil { - panic(fmt.Errorf("Failed to parse JSON test fixture: %w", err)) - } - - suite.SetupTest() - _, _, connAB, connBA := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - _, _, connBC, connCB := suite.coordinator.SetupClientConnections(suite.chainB, suite.chainC, exported.Tendermint) - suite.coordinator.CreateTransferChannels(suite.chainA, suite.chainB, connAB, connBA, channeltypes.UNORDERED) - suite.coordinator.CreateTransferChannels(suite.chainB, suite.chainC, connBC, connCB, channeltypes.UNORDERED) - - for i, tlaTc := range tlaTestCases { - tc := OnRecvPacketTestCaseFromTla(tlaTc) - registerDenom := func() { - denomTrace := types.ParseDenomTrace(tc.packet.Data.Denom) - traceHash := denomTrace.Hash() - if !suite.chainB.App.TransferKeeper.HasDenomTrace(suite.chainB.GetContext(), traceHash) { - suite.chainB.App.TransferKeeper.SetDenomTrace(suite.chainB.GetContext(), denomTrace) - } - } - - description := file_info.Name() + " # " + strconv.Itoa(i+1) - suite.Run(fmt.Sprintf("Case %s", description), func() { - seq := uint64(1) - packet := channeltypes.NewPacket(tc.packet.Data.GetBytes(), seq, tc.packet.SourcePort, tc.packet.SourceChannel, tc.packet.DestPort, tc.packet.DestChannel, clienttypes.NewHeight(0, 100), 0) - bankBefore := BankFromBalances(tc.bankBefore) - realBankBefore := BankOfChain(suite.chainB) - // First validate the packet itself (mimics what happens when the packet is being sent and/or received) - err := packet.ValidateBasic() - if err != nil { - suite.Require().False(tc.pass, err.Error()) - return - } - switch tc.handler { - case "SendTransfer": - var sender sdk.AccAddress - sender, err = sdk.AccAddressFromBech32(tc.packet.Data.Sender) - if err != nil { - panic("MBT failed to convert sender address") - } - registerDenom() - denomTrace := types.ParseDenomTrace(tc.packet.Data.Denom) - denom := denomTrace.IBCDenom() - err = sdk.ValidateDenom(denom) - if err == nil { - err = suite.chainB.App.TransferKeeper.SendTransfer( - suite.chainB.GetContext(), - tc.packet.SourcePort, - tc.packet.SourceChannel, - sdk.NewCoin(denom, sdk.NewIntFromUint64(tc.packet.Data.Amount)), - sender, - tc.packet.Data.Receiver, - clienttypes.NewHeight(0, 110), - 0) - } - case "OnRecvPacket": - err = suite.chainB.App.TransferKeeper.OnRecvPacket(suite.chainB.GetContext(), packet, tc.packet.Data) - case "OnTimeoutPacket": - registerDenom() - err = suite.chainB.App.TransferKeeper.OnTimeoutPacket(suite.chainB.GetContext(), packet, tc.packet.Data) - case "OnRecvAcknowledgementResult": - err = suite.chainB.App.TransferKeeper.OnAcknowledgementPacket( - suite.chainB.GetContext(), packet, tc.packet.Data, - channeltypes.NewResultAcknowledgement(nil)) - case "OnRecvAcknowledgementError": - registerDenom() - err = suite.chainB.App.TransferKeeper.OnAcknowledgementPacket( - suite.chainB.GetContext(), packet, tc.packet.Data, - channeltypes.NewErrorAcknowledgement("MBT Error Acknowledgement")) - default: - err = fmt.Errorf("Unknown handler: %s", tc.handler) - } - if err != nil { - suite.Require().False(tc.pass, err.Error()) - return - } - bankAfter := BankFromBalances(tc.bankAfter) - expectedBankChange := bankAfter.Sub(&bankBefore) - if err := suite.CheckBankBalances(suite.chainB, &realBankBefore, &expectedBankChange); err != nil { - suite.Require().False(tc.pass, err.Error()) - return - } - suite.Require().True(tc.pass) - }) - } - } -} diff --git a/x/ibc/applications/transfer/keeper/model_based_tests/Test5Packets.json b/x/ibc/applications/transfer/keeper/model_based_tests/Test5Packets.json deleted file mode 100644 index 6ccdccc8aeb2..000000000000 --- a/x/ibc/applications/transfer/keeper/model_based_tests/Test5Packets.json +++ /dev/null @@ -1,492 +0,0 @@ -[ - { - "packet": { - "sourceChannel": "channel-0", - "sourcePort": "transfer", - "destChannel": "channel-1", - "destPort": "transfer", - "data": { - "sender": "a3", - "receiver": "a3", - "amount": 2, - "denom": [ - "", - "", - "", - "", - "btc" - ] - } - }, - "handler": "OnRecvPacket", - "bankBefore": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - } - ], - "bankAfter": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - }, - { - "address": [ - "", - "", - "a3" - ], - "denom": [ - "", - "", - "transfer", - "channel-1", - "btc" - ], - "amount": 2 - } - ], - "error": false - }, - { - "packet": { - "sourceChannel": "ethereum-hub", - "sourcePort": "channel-0", - "destChannel": "channel-1", - "destPort": "transfer", - "data": { - "sender": "a1", - "receiver": "a3", - "amount": 1, - "denom": [ - "cosmos-hub", - "", - "", - "", - "btc" - ] - } - }, - "handler": "SendTransfer", - "bankBefore": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - }, - { - "address": [ - "", - "", - "a3" - ], - "denom": [ - "", - "", - "transfer", - "channel-1", - "btc" - ], - "amount": 2 - } - ], - "bankAfter": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - }, - { - "address": [ - "", - "", - "a3" - ], - "denom": [ - "", - "", - "transfer", - "channel-1", - "btc" - ], - "amount": 2 - } - ], - "error": true - }, - { - "packet": { - "sourceChannel": "channel-0", - "sourcePort": "transfer", - "destChannel": "channel-1", - "destPort": "transfer", - "data": { - "sender": "a2", - "receiver": "a2", - "amount": 4, - "denom": [ - "", - "", - "ethereum-hub", - "cosmos-hub", - "atom" - ] - } - }, - "handler": "OnRecvPacket", - "bankBefore": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - }, - { - "address": [ - "", - "", - "a3" - ], - "denom": [ - "", - "", - "transfer", - "channel-1", - "btc" - ], - "amount": 2 - } - ], - "bankAfter": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - }, - { - "address": [ - "", - "", - "a2" - ], - "denom": [ - "transfer", - "channel-1", - "ethereum-hub", - "cosmos-hub", - "atom" - ], - "amount": 4 - }, - { - "address": [ - "", - "", - "a3" - ], - "denom": [ - "", - "", - "transfer", - "channel-1", - "btc" - ], - "amount": 2 - } - ], - "error": false - }, - { - "packet": { - "sourceChannel": "channel-0", - "sourcePort": "transfer", - "destChannel": "channel-1", - "destPort": "transfer", - "data": { - "sender": "", - "receiver": "a2", - "amount": 4, - "denom": [ - "", - "", - "ethereum-hub", - "cosmos-hub", - "atom" - ] - } - }, - "handler": "OnRecvPacket", - "bankBefore": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - }, - { - "address": [ - "", - "", - "a2" - ], - "denom": [ - "transfer", - "channel-1", - "ethereum-hub", - "cosmos-hub", - "atom" - ], - "amount": 4 - }, - { - "address": [ - "", - "", - "a3" - ], - "denom": [ - "", - "", - "transfer", - "channel-1", - "btc" - ], - "amount": 2 - } - ], - "bankAfter": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - }, - { - "address": [ - "", - "", - "a2" - ], - "denom": [ - "transfer", - "channel-1", - "ethereum-hub", - "cosmos-hub", - "atom" - ], - "amount": 8 - }, - { - "address": [ - "", - "", - "a3" - ], - "denom": [ - "", - "", - "transfer", - "channel-1", - "btc" - ], - "amount": 2 - } - ], - "error": false - }, - { - "packet": { - "sourceChannel": "cosmos-hub", - "sourcePort": "bitcoin-hub", - "destChannel": "channel-0", - "destPort": "channel-1", - "data": { - "sender": "a1", - "receiver": "", - "amount": 1, - "denom": [ - "transfer", - "channel-0", - "transfer", - "channel-0", - "atom" - ] - } - }, - "handler": "SendTransfer", - "bankBefore": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - }, - { - "address": [ - "", - "", - "a2" - ], - "denom": [ - "transfer", - "channel-1", - "ethereum-hub", - "cosmos-hub", - "atom" - ], - "amount": 8 - }, - { - "address": [ - "", - "", - "a3" - ], - "denom": [ - "", - "", - "transfer", - "channel-1", - "btc" - ], - "amount": 2 - } - ], - "bankAfter": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - }, - { - "address": [ - "", - "", - "a2" - ], - "denom": [ - "transfer", - "channel-1", - "ethereum-hub", - "cosmos-hub", - "atom" - ], - "amount": 8 - }, - { - "address": [ - "", - "", - "a3" - ], - "denom": [ - "", - "", - "transfer", - "channel-1", - "btc" - ], - "amount": 2 - } - ], - "error": true - } -] \ No newline at end of file diff --git a/x/ibc/applications/transfer/keeper/model_based_tests/Test5Packets.tla b/x/ibc/applications/transfer/keeper/model_based_tests/Test5Packets.tla deleted file mode 100644 index 9691eec2f261..000000000000 --- a/x/ibc/applications/transfer/keeper/model_based_tests/Test5Packets.tla +++ /dev/null @@ -1,1056 +0,0 @@ -------------------------- MODULE counterexample ------------------------- - -EXTENDS relay_tests - -(* Initial state *) - -State1 == -TRUE -(* Transition 0 to State2 *) - -State2 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 -/\ count = 0 -/\ error = FALSE -/\ handler = "" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 2, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a3", - sender |-> "a3"], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] -/\ p = [data |-> - [amount |-> 2, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a3", - sender |-> "a3"], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"] - -(* Transition 3 to State3 *) - -State3 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "channel-1", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2 -/\ count = 1 -/\ error = FALSE -/\ handler = "OnRecvPacket" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 2, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a3", - sender |-> "a3"], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 1 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "channel-1", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "OnRecvPacket", - packet |-> - [data |-> - [amount |-> 2, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a3", - sender |-> "a3"], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] -/\ p = [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> "cosmos-hub"]], - receiver |-> "a3", - sender |-> "a1"], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "ethereum-hub", - sourcePort |-> "channel-0"] - -(* Transition 0 to State4 *) - -State4 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "channel-1", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2 -/\ count = 2 -/\ error = TRUE -/\ handler = "SendTransfer" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 2, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a3", - sender |-> "a3"], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 1 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "channel-1", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "OnRecvPacket", - packet |-> - [data |-> - [amount |-> 2, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a3", - sender |-> "a3"], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 2 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "channel-1", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "channel-1", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2, - error |-> TRUE, - handler |-> "SendTransfer", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> "cosmos-hub"]], - receiver |-> "a3", - sender |-> "a1"], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "ethereum-hub", - sourcePort |-> "channel-0"]] -/\ p = [data |-> - [amount |-> 4, - denomTrace |-> - [denom |-> "atom", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "ethereum-hub"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a2", - sender |-> "a2"], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"] - -(* Transition 5 to State5 *) - -State5 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "ethereum-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 4 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "channel-1", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2 -/\ count = 3 -/\ error = FALSE -/\ handler = "OnRecvPacket" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 2, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a3", - sender |-> "a3"], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 1 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "channel-1", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "OnRecvPacket", - packet |-> - [data |-> - [amount |-> 2, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a3", - sender |-> "a3"], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 2 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "channel-1", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "channel-1", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2, - error |-> TRUE, - handler |-> "SendTransfer", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> "cosmos-hub"]], - receiver |-> "a3", - sender |-> "a1"], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "ethereum-hub", - sourcePort |-> "channel-0"]] - @@ 3 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "ethereum-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 4 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "channel-1", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "channel-1", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2, - error |-> FALSE, - handler |-> "OnRecvPacket", - packet |-> - [data |-> - [amount |-> 4, - denomTrace |-> - [denom |-> "atom", - prefix0 |-> - [channel |-> "cosmos-hub", port |-> "ethereum-hub"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a2", - sender |-> "a2"], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] -/\ p = [data |-> - [amount |-> 4, - denomTrace |-> - [denom |-> "atom", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "ethereum-hub"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a2", - sender |-> ""], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"] - -(* Transition 5 to State6 *) - -State6 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "ethereum-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 8 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "channel-1", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2 -/\ count = 4 -/\ error = FALSE -/\ handler = "OnRecvPacket" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 2, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a3", - sender |-> "a3"], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 1 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "channel-1", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "OnRecvPacket", - packet |-> - [data |-> - [amount |-> 2, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a3", - sender |-> "a3"], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 2 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "channel-1", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "channel-1", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2, - error |-> TRUE, - handler |-> "SendTransfer", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> "cosmos-hub"]], - receiver |-> "a3", - sender |-> "a1"], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "ethereum-hub", - sourcePort |-> "channel-0"]] - @@ 3 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "ethereum-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 4 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "channel-1", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "channel-1", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2, - error |-> FALSE, - handler |-> "OnRecvPacket", - packet |-> - [data |-> - [amount |-> 4, - denomTrace |-> - [denom |-> "atom", - prefix0 |-> - [channel |-> "cosmos-hub", port |-> "ethereum-hub"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a2", - sender |-> "a2"], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 4 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "ethereum-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 8 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "channel-1", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "ethereum-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 4 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "channel-1", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2, - error |-> FALSE, - handler |-> "OnRecvPacket", - packet |-> - [data |-> - [amount |-> 4, - denomTrace |-> - [denom |-> "atom", - prefix0 |-> - [channel |-> "cosmos-hub", port |-> "ethereum-hub"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a2", - sender |-> ""], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] -/\ p = [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "atom", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "channel-0", port |-> "transfer"]], - receiver |-> "", - sender |-> "a1"], - destChannel |-> "channel-0", - destPort |-> "channel-1", - sourceChannel |-> "cosmos-hub", - sourcePort |-> "bitcoin-hub"] - -(* Transition 0 to State7 *) - -State7 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "ethereum-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 8 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "channel-1", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2 -/\ count = 5 -/\ error = TRUE -/\ handler = "SendTransfer" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 2, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a3", - sender |-> "a3"], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 1 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "channel-1", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "OnRecvPacket", - packet |-> - [data |-> - [amount |-> 2, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a3", - sender |-> "a3"], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 2 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "channel-1", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "channel-1", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2, - error |-> TRUE, - handler |-> "SendTransfer", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> "cosmos-hub"]], - receiver |-> "a3", - sender |-> "a1"], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "ethereum-hub", - sourcePort |-> "channel-0"]] - @@ 3 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "ethereum-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 4 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "channel-1", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "channel-1", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2, - error |-> FALSE, - handler |-> "OnRecvPacket", - packet |-> - [data |-> - [amount |-> 4, - denomTrace |-> - [denom |-> "atom", - prefix0 |-> - [channel |-> "cosmos-hub", port |-> "ethereum-hub"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a2", - sender |-> "a2"], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 4 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "ethereum-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 8 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "channel-1", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "ethereum-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 4 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "channel-1", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2, - error |-> FALSE, - handler |-> "OnRecvPacket", - packet |-> - [data |-> - [amount |-> 4, - denomTrace |-> - [denom |-> "atom", - prefix0 |-> - [channel |-> "cosmos-hub", port |-> "ethereum-hub"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a2", - sender |-> ""], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 5 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "ethereum-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 8 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "channel-1", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "ethereum-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 8 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "channel-1", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2, - error |-> TRUE, - handler |-> "SendTransfer", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "atom", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "channel-0", port |-> "transfer"]], - receiver |-> "", - sender |-> "a1"], - destChannel |-> "channel-0", - destPort |-> "channel-1", - sourceChannel |-> "cosmos-hub", - sourcePort |-> "bitcoin-hub"]] -/\ p = [data |-> - [amount |-> 0, - denomTrace |-> - [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "", - sender |-> ""], - destChannel |-> "", - destPort |-> "", - sourceChannel |-> "", - sourcePort |-> ""] - -(* The following formula holds true in the last state and violates the invariant *) - -InvariantViolation == - count >= 5 - /\ BMC!Skolem((\E s1$2 \in DOMAIN history: - BMC!Skolem((\E s2$2 \in DOMAIN history: - ~(history[s1$2]["handler"] = history[s2$2]["handler"]))))) - -================================================================================ -\* Created by Apalache on Thu Dec 10 11:52:41 CET 2020 -\* https://github.com/informalsystems/apalache diff --git a/x/ibc/applications/transfer/keeper/model_based_tests/Test5PacketsAllDifferentPass.json b/x/ibc/applications/transfer/keeper/model_based_tests/Test5PacketsAllDifferentPass.json deleted file mode 100644 index 6a039f3eca45..000000000000 --- a/x/ibc/applications/transfer/keeper/model_based_tests/Test5PacketsAllDifferentPass.json +++ /dev/null @@ -1,612 +0,0 @@ -[ - { - "packet": { - "sourceChannel": "channel-0", - "sourcePort": "transfer", - "destChannel": "channel-0", - "destPort": "transfer", - "data": { - "sender": "a3", - "receiver": "a2", - "amount": 3, - "denom": [ - "", - "", - "transfer", - "channel-0", - "eth" - ] - } - }, - "handler": "OnTimeoutPacket", - "bankBefore": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - } - ], - "bankAfter": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - }, - { - "address": [ - "", - "", - "a3" - ], - "denom": [ - "", - "", - "transfer", - "channel-0", - "eth" - ], - "amount": 3 - } - ], - "error": false - }, - { - "packet": { - "sourceChannel": "channel-1", - "sourcePort": "transfer", - "destChannel": "channel-0", - "destPort": "transfer", - "data": { - "sender": "a2", - "receiver": "a1", - "amount": 3, - "denom": [ - "transfer", - "channel-1", - "cosmos-hub", - "cosmos-hub", - "btc" - ] - } - }, - "handler": "OnRecvAcknowledgementError", - "bankBefore": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - }, - { - "address": [ - "", - "", - "a3" - ], - "denom": [ - "", - "", - "transfer", - "channel-0", - "eth" - ], - "amount": 3 - } - ], - "bankAfter": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - }, - { - "address": [ - "", - "", - "a2" - ], - "denom": [ - "transfer", - "channel-1", - "cosmos-hub", - "cosmos-hub", - "btc" - ], - "amount": 3 - }, - { - "address": [ - "", - "", - "a3" - ], - "denom": [ - "", - "", - "transfer", - "channel-0", - "eth" - ], - "amount": 3 - } - ], - "error": false - }, - { - "packet": { - "sourceChannel": "channel-0", - "sourcePort": "transfer", - "destChannel": "channel-1", - "destPort": "transfer", - "data": { - "sender": "a1", - "receiver": "a2", - "amount": 3, - "denom": [ - "", - "", - "cosmos-hub", - "cosmos-hub", - "atom" - ] - } - }, - "handler": "OnRecvPacket", - "bankBefore": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - }, - { - "address": [ - "", - "", - "a2" - ], - "denom": [ - "transfer", - "channel-1", - "cosmos-hub", - "cosmos-hub", - "btc" - ], - "amount": 3 - }, - { - "address": [ - "", - "", - "a3" - ], - "denom": [ - "", - "", - "transfer", - "channel-0", - "eth" - ], - "amount": 3 - } - ], - "bankAfter": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - }, - { - "address": [ - "", - "", - "a2" - ], - "denom": [ - "transfer", - "channel-1", - "cosmos-hub", - "cosmos-hub", - "atom" - ], - "amount": 3 - }, - { - "address": [ - "", - "", - "a2" - ], - "denom": [ - "transfer", - "channel-1", - "cosmos-hub", - "cosmos-hub", - "btc" - ], - "amount": 3 - }, - { - "address": [ - "", - "", - "a3" - ], - "denom": [ - "", - "", - "transfer", - "channel-0", - "eth" - ], - "amount": 3 - } - ], - "error": false - }, - { - "packet": { - "sourceChannel": "cosmos-hub", - "sourcePort": "bitcoin-hub", - "destChannel": "transfer", - "destPort": "cosmos-hub", - "data": { - "sender": "a1", - "receiver": "", - "amount": 2, - "denom": [ - "", - "channel-0", - "channel-1", - "channel-1", - "" - ] - } - }, - "handler": "OnRecvAcknowledgementResult", - "bankBefore": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - }, - { - "address": [ - "", - "", - "a2" - ], - "denom": [ - "transfer", - "channel-1", - "cosmos-hub", - "cosmos-hub", - "atom" - ], - "amount": 3 - }, - { - "address": [ - "", - "", - "a2" - ], - "denom": [ - "transfer", - "channel-1", - "cosmos-hub", - "cosmos-hub", - "btc" - ], - "amount": 3 - }, - { - "address": [ - "", - "", - "a3" - ], - "denom": [ - "", - "", - "transfer", - "channel-0", - "eth" - ], - "amount": 3 - } - ], - "bankAfter": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - }, - { - "address": [ - "", - "", - "a2" - ], - "denom": [ - "transfer", - "channel-1", - "cosmos-hub", - "cosmos-hub", - "atom" - ], - "amount": 3 - }, - { - "address": [ - "", - "", - "a2" - ], - "denom": [ - "transfer", - "channel-1", - "cosmos-hub", - "cosmos-hub", - "btc" - ], - "amount": 3 - }, - { - "address": [ - "", - "", - "a3" - ], - "denom": [ - "", - "", - "transfer", - "channel-0", - "eth" - ], - "amount": 3 - } - ], - "error": false - }, - { - "packet": { - "sourceChannel": "channel-1", - "sourcePort": "transfer", - "destChannel": "channel-0", - "destPort": "transfer", - "data": { - "sender": "a3", - "receiver": "a3", - "amount": 1, - "denom": [ - "", - "", - "transfer", - "channel-0", - "eth" - ] - } - }, - "handler": "SendTransfer", - "bankBefore": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - }, - { - "address": [ - "", - "", - "a2" - ], - "denom": [ - "transfer", - "channel-1", - "cosmos-hub", - "cosmos-hub", - "atom" - ], - "amount": 3 - }, - { - "address": [ - "", - "", - "a2" - ], - "denom": [ - "transfer", - "channel-1", - "cosmos-hub", - "cosmos-hub", - "btc" - ], - "amount": 3 - }, - { - "address": [ - "", - "", - "a3" - ], - "denom": [ - "", - "", - "transfer", - "channel-0", - "eth" - ], - "amount": 3 - } - ], - "bankAfter": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - }, - { - "address": [ - "", - "", - "a2" - ], - "denom": [ - "transfer", - "channel-1", - "cosmos-hub", - "cosmos-hub", - "atom" - ], - "amount": 3 - }, - { - "address": [ - "", - "", - "a2" - ], - "denom": [ - "transfer", - "channel-1", - "cosmos-hub", - "cosmos-hub", - "btc" - ], - "amount": 3 - }, - { - "address": [ - "", - "", - "a3" - ], - "denom": [ - "", - "", - "transfer", - "channel-0", - "eth" - ], - "amount": 2 - }, - { - "address": [ - "transfer", - "channel-1", - "" - ], - "denom": [ - "", - "", - "transfer", - "channel-0", - "eth" - ], - "amount": 1 - } - ], - "error": false - } -] \ No newline at end of file diff --git a/x/ibc/applications/transfer/keeper/model_based_tests/Test5PacketsAllDifferentPass.tla b/x/ibc/applications/transfer/keeper/model_based_tests/Test5PacketsAllDifferentPass.tla deleted file mode 100644 index 89e6d87be527..000000000000 --- a/x/ibc/applications/transfer/keeper/model_based_tests/Test5PacketsAllDifferentPass.tla +++ /dev/null @@ -1,1188 +0,0 @@ -------------------------- MODULE counterexample ------------------------- - -EXTENDS relay_tests - -(* Initial state *) - -State1 == -TRUE -(* Transition 0 to State2 *) - -State2 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 -/\ count = 0 -/\ error = FALSE -/\ handler = "" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 3, - denomTrace |-> - [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a2", - sender |-> "a3"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] -/\ p = [data |-> - [amount |-> 3, - denomTrace |-> - [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a2", - sender |-> "a3"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"] - -(* Transition 6 to State3 *) - -State3 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 3 -/\ count = 1 -/\ error = FALSE -/\ handler = "OnTimeoutPacket" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 3, - denomTrace |-> - [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a2", - sender |-> "a3"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 1 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 3, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "OnTimeoutPacket", - packet |-> - [data |-> - [amount |-> 3, - denomTrace |-> - [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a2", - sender |-> "a3"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] -/\ p = [data |-> - [amount |-> 3, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]], - receiver |-> "a1", - sender |-> "a2"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-1", - sourcePort |-> "transfer"] - -(* Transition 10 to State4 *) - -State4 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 3 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 3 -/\ count = 2 -/\ error = FALSE -/\ handler = "OnRecvAcknowledgementError" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 3, - denomTrace |-> - [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a2", - sender |-> "a3"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 1 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 3, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "OnTimeoutPacket", - packet |-> - [data |-> - [amount |-> 3, - denomTrace |-> - [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a2", - sender |-> "a3"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 2 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 3 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 3, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 3, - error |-> FALSE, - handler |-> "OnRecvAcknowledgementError", - packet |-> - [data |-> - [amount |-> 3, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]], - receiver |-> "a1", - sender |-> "a2"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-1", - sourcePort |-> "transfer"]] -/\ p = [data |-> - [amount |-> 3, - denomTrace |-> - [denom |-> "atom", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a2", - sender |-> "a1"], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"] - -(* Transition 5 to State5 *) - -State5 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 3 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 3 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 3 -/\ count = 3 -/\ error = FALSE -/\ handler = "OnRecvPacket" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 3, - denomTrace |-> - [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a2", - sender |-> "a3"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 1 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 3, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "OnTimeoutPacket", - packet |-> - [data |-> - [amount |-> 3, - denomTrace |-> - [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a2", - sender |-> "a3"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 2 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 3 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 3, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 3, - error |-> FALSE, - handler |-> "OnRecvAcknowledgementError", - packet |-> - [data |-> - [amount |-> 3, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]], - receiver |-> "a1", - sender |-> "a2"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-1", - sourcePort |-> "transfer"]] - @@ 3 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 3 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 3 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 3, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 3 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 3, - error |-> FALSE, - handler |-> "OnRecvPacket", - packet |-> - [data |-> - [amount |-> 3, - denomTrace |-> - [denom |-> "atom", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a2", - sender |-> "a1"], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] -/\ p = [data |-> - [amount |-> 2, - denomTrace |-> - [denom |-> "", - prefix0 |-> [channel |-> "channel-1", port |-> "channel-1"], - prefix1 |-> [channel |-> "channel-0", port |-> ""]], - receiver |-> "", - sender |-> "a1"], - destChannel |-> "transfer", - destPort |-> "cosmos-hub", - sourceChannel |-> "cosmos-hub", - sourcePort |-> "bitcoin-hub"] - -(* Transition 12 to State6 *) - -State6 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 3 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 3 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 3 -/\ count = 4 -/\ error = FALSE -/\ handler = "OnRecvAcknowledgementResult" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 3, - denomTrace |-> - [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a2", - sender |-> "a3"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 1 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 3, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "OnTimeoutPacket", - packet |-> - [data |-> - [amount |-> 3, - denomTrace |-> - [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a2", - sender |-> "a3"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 2 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 3 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 3, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 3, - error |-> FALSE, - handler |-> "OnRecvAcknowledgementError", - packet |-> - [data |-> - [amount |-> 3, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]], - receiver |-> "a1", - sender |-> "a2"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-1", - sourcePort |-> "transfer"]] - @@ 3 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 3 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 3 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 3, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 3 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 3, - error |-> FALSE, - handler |-> "OnRecvPacket", - packet |-> - [data |-> - [amount |-> 3, - denomTrace |-> - [denom |-> "atom", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a2", - sender |-> "a1"], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 4 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 3 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 3 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 3, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 3 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 3 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 3, - error |-> FALSE, - handler |-> "OnRecvAcknowledgementResult", - packet |-> - [data |-> - [amount |-> 2, - denomTrace |-> - [denom |-> "", - prefix0 |-> [channel |-> "channel-1", port |-> "channel-1"], - prefix1 |-> [channel |-> "channel-0", port |-> ""]], - receiver |-> "", - sender |-> "a1"], - destChannel |-> "transfer", - destPort |-> "cosmos-hub", - sourceChannel |-> "cosmos-hub", - sourcePort |-> "bitcoin-hub"]] -/\ p = [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a3", - sender |-> "a3"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-1", - sourcePort |-> "transfer"] - -(* Transition 1 to State7 *) - -State7 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 3 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 3 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2 - @@ << - [channel |-> "channel-1", id |-> "", port |-> "transfer"], [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 1 -/\ count = 5 -/\ error = FALSE -/\ handler = "SendTransfer" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 3, - denomTrace |-> - [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a2", - sender |-> "a3"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 1 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 3, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "OnTimeoutPacket", - packet |-> - [data |-> - [amount |-> 3, - denomTrace |-> - [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a2", - sender |-> "a3"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 2 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 3 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 3, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 3, - error |-> FALSE, - handler |-> "OnRecvAcknowledgementError", - packet |-> - [data |-> - [amount |-> 3, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]], - receiver |-> "a1", - sender |-> "a2"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-1", - sourcePort |-> "transfer"]] - @@ 3 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 3 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 3 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 3, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 3 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 3, - error |-> FALSE, - handler |-> "OnRecvPacket", - packet |-> - [data |-> - [amount |-> 3, - denomTrace |-> - [denom |-> "atom", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a2", - sender |-> "a1"], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 4 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 3 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 3 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 3, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 3 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 3 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 3, - error |-> FALSE, - handler |-> "OnRecvAcknowledgementResult", - packet |-> - [data |-> - [amount |-> 2, - denomTrace |-> - [denom |-> "", - prefix0 |-> [channel |-> "channel-1", port |-> "channel-1"], - prefix1 |-> [channel |-> "channel-0", port |-> ""]], - receiver |-> "", - sender |-> "a1"], - destChannel |-> "transfer", - destPort |-> "cosmos-hub", - sourceChannel |-> "cosmos-hub", - sourcePort |-> "bitcoin-hub"]] - @@ 5 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 3 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 3 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2 - @@ << - [channel |-> "channel-1", id |-> "", port |-> "transfer"], [denom |-> - "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 1, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 3 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 3 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 3, - error |-> FALSE, - handler |-> "SendTransfer", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "eth", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a3", - sender |-> "a3"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-1", - sourcePort |-> "transfer"]] -/\ p = [data |-> - [amount |-> 0, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "transfer", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "cosmos-hub", port |-> "transfer"]], - receiver |-> "", - sender |-> ""], - destChannel |-> "bitcoin-hub", - destPort |-> "ethereum-hub", - sourceChannel |-> "transfer", - sourcePort |-> "channel-1"] - -(* The following formula holds true in the last state and violates the invariant *) - -InvariantViolation == - (count >= 5 - /\ (\A s1$2 \in DOMAIN history: - \A s2$2 \in DOMAIN history: - s1$2 = s2$2 \/ ~(history[s1$2]["handler"] = history[s2$2]["handler"]))) - /\ (\A s$2 \in DOMAIN history: - s$2 <= 0 - \/ (history[s$2]["error"] = FALSE - /\ history[s$2]["packet"]["data"]["amount"] > 0)) - -================================================================================ -\* Created by Apalache on Thu Dec 10 12:49:42 CET 2020 -\* https://github.com/informalsystems/apalache diff --git a/x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvAcknowledgementErrorFail.json b/x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvAcknowledgementErrorFail.json deleted file mode 100644 index f1f553210b58..000000000000 --- a/x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvAcknowledgementErrorFail.json +++ /dev/null @@ -1,58 +0,0 @@ -[ - { - "packet": { - "sourceChannel": "", - "sourcePort": "", - "destChannel": "", - "destPort": "", - "data": { - "sender": "a1", - "receiver": "a2", - "amount": 1, - "denom": [ - "cosmos-hub", - "transfer", - "channel-0", - "cosmos-hub", - "btc" - ] - } - }, - "handler": "OnRecvAcknowledgementError", - "bankBefore": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - } - ], - "bankAfter": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - } - ], - "error": true - } -] \ No newline at end of file diff --git a/x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvAcknowledgementErrorFail.tla b/x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvAcknowledgementErrorFail.tla deleted file mode 100644 index 583b3211dca8..000000000000 --- a/x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvAcknowledgementErrorFail.tla +++ /dev/null @@ -1,159 +0,0 @@ -------------------------- MODULE counterexample ------------------------- - -EXTENDS relay_tests - -(* Initial state *) - -State1 == -TRUE -(* Transition 0 to State2 *) - -State2 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 -/\ count = 0 -/\ error = FALSE -/\ handler = "" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "channel-0"], - prefix1 |-> [channel |-> "transfer", port |-> "cosmos-hub"]], - receiver |-> "a2", - sender |-> "a1"], - destChannel |-> "", - destPort |-> "", - sourceChannel |-> "", - sourcePort |-> ""]] -/\ p = [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "channel-0"], - prefix1 |-> [channel |-> "transfer", port |-> "cosmos-hub"]], - receiver |-> "a2", - sender |-> "a1"], - destChannel |-> "", - destPort |-> "", - sourceChannel |-> "", - sourcePort |-> ""] - -(* Transition 7 to State3 *) - -State3 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 -/\ count = 1 -/\ error = TRUE -/\ handler = "OnRecvAcknowledgementError" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "channel-0"], - prefix1 |-> [channel |-> "transfer", port |-> "cosmos-hub"]], - receiver |-> "a2", - sender |-> "a1"], - destChannel |-> "", - destPort |-> "", - sourceChannel |-> "", - sourcePort |-> ""]] - @@ 1 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> TRUE, - handler |-> "OnRecvAcknowledgementError", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "channel-0"], - prefix1 |-> [channel |-> "transfer", port |-> "cosmos-hub"]], - receiver |-> "a2", - sender |-> "a1"], - destChannel |-> "", - destPort |-> "", - sourceChannel |-> "", - sourcePort |-> ""]] -/\ p = [data |-> - [amount |-> 0, - denomTrace |-> - [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "", - sender |-> ""], - destChannel |-> "", - destPort |-> "", - sourceChannel |-> "", - sourcePort |-> ""] - -(* The following formula holds true in the last state and violates the invariant *) - -InvariantViolation == - BMC!Skolem((\E s$2 \in DOMAIN history: - history[s$2]["handler"] = "OnRecvAcknowledgementError" - /\ history[s$2]["error"] = TRUE - /\ history[s$2]["packet"]["data"]["amount"] > 0)) - -================================================================================ -\* Created by Apalache on Thu Dec 10 11:15:18 CET 2020 -\* https://github.com/informalsystems/apalache diff --git a/x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvAcknowledgementErrorPass.json b/x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvAcknowledgementErrorPass.json deleted file mode 100644 index 3fbfe7fdf09d..000000000000 --- a/x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvAcknowledgementErrorPass.json +++ /dev/null @@ -1,159 +0,0 @@ -[ - { - "packet": { - "sourceChannel": "channel-0", - "sourcePort": "transfer", - "destChannel": "channel-1", - "destPort": "transfer", - "data": { - "sender": "", - "receiver": "a1", - "amount": 1, - "denom": [ - "", - "", - "channel-0", - "ethereum-hub", - "btc" - ] - } - }, - "handler": "OnRecvPacket", - "bankBefore": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - } - ], - "bankAfter": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - }, - { - "address": [ - "", - "", - "a1" - ], - "denom": [ - "transfer", - "channel-1", - "channel-0", - "ethereum-hub", - "btc" - ], - "amount": 1 - } - ], - "error": false - }, - { - "packet": { - "sourceChannel": "channel-1", - "sourcePort": "transfer", - "destChannel": "channel-0", - "destPort": "transfer", - "data": { - "sender": "a1", - "receiver": "a2", - "amount": 1, - "denom": [ - "transfer", - "channel-1", - "channel-0", - "ethereum-hub", - "btc" - ] - } - }, - "handler": "OnRecvAcknowledgementError", - "bankBefore": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - }, - { - "address": [ - "", - "", - "a1" - ], - "denom": [ - "transfer", - "channel-1", - "channel-0", - "ethereum-hub", - "btc" - ], - "amount": 1 - } - ], - "bankAfter": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - }, - { - "address": [ - "", - "", - "a1" - ], - "denom": [ - "transfer", - "channel-1", - "channel-0", - "ethereum-hub", - "btc" - ], - "amount": 2 - } - ], - "error": false - } -] \ No newline at end of file diff --git a/x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvAcknowledgementErrorPass.tla b/x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvAcknowledgementErrorPass.tla deleted file mode 100644 index cd43eb2647e1..000000000000 --- a/x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvAcknowledgementErrorPass.tla +++ /dev/null @@ -1,310 +0,0 @@ -------------------------- MODULE counterexample ------------------------- - -EXTENDS relay_tests - -(* Initial state *) - -State1 == -TRUE -(* Transition 0 to State2 *) - -State2 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 -/\ count = 0 -/\ error = FALSE -/\ handler = "" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "ethereum-hub", port |-> "channel-0"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a1", - sender |-> ""], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] -/\ p = [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "ethereum-hub", port |-> "channel-0"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a1", - sender |-> ""], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"] - -(* Transition 2 to State3 *) - -State3 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a1", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "ethereum-hub", port |-> "channel-0"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 1 -/\ count = 1 -/\ error = FALSE -/\ handler = "OnRecvPacket" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "ethereum-hub", port |-> "channel-0"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a1", - sender |-> ""], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 1 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a1", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "ethereum-hub", port |-> "channel-0"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 1, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "OnRecvPacket", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "ethereum-hub", port |-> "channel-0"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a1", - sender |-> ""], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] -/\ p = [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "ethereum-hub", port |-> "channel-0"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]], - receiver |-> "a2", - sender |-> "a1"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-1", - sourcePort |-> "transfer"] - -(* Transition 11 to State4 *) - -State4 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a1", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "ethereum-hub", port |-> "channel-0"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 2 -/\ count = 2 -/\ error = FALSE -/\ handler = "OnRecvAcknowledgementError" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "ethereum-hub", port |-> "channel-0"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a1", - sender |-> ""], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 1 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a1", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "ethereum-hub", port |-> "channel-0"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 1, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "OnRecvPacket", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "ethereum-hub", port |-> "channel-0"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a1", - sender |-> ""], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 2 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a1", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "ethereum-hub", port |-> "channel-0"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 2, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a1", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "ethereum-hub", port |-> "channel-0"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 1, - error |-> FALSE, - handler |-> "OnRecvAcknowledgementError", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "ethereum-hub", port |-> "channel-0"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]], - receiver |-> "a2", - sender |-> "a1"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-1", - sourcePort |-> "transfer"]] -/\ p = [data |-> - [amount |-> 0, - denomTrace |-> - [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "", - sender |-> ""], - destChannel |-> "", - destPort |-> "", - sourceChannel |-> "", - sourcePort |-> ""] - -(* The following formula holds true in the last state and violates the invariant *) - -InvariantViolation == - BMC!Skolem((\E s$2 \in DOMAIN history: - history[s$2]["handler"] = "OnRecvAcknowledgementError" - /\ history[s$2]["error"] = FALSE - /\ history[s$2]["packet"]["data"]["amount"] > 0)) - -================================================================================ -\* Created by Apalache on Thu Dec 10 11:14:33 CET 2020 -\* https://github.com/informalsystems/apalache diff --git a/x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvAcknowledgementResultFail.json b/x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvAcknowledgementResultFail.json deleted file mode 100644 index 9110a38ab653..000000000000 --- a/x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvAcknowledgementResultFail.json +++ /dev/null @@ -1,58 +0,0 @@ -[ - { - "packet": { - "sourceChannel": "", - "sourcePort": "", - "destChannel": "", - "destPort": "", - "data": { - "sender": "a1", - "receiver": "a2", - "amount": 1, - "denom": [ - "cosmos-hub", - "transfer", - "channel-0", - "cosmos-hub", - "btc" - ] - } - }, - "handler": "OnRecvAcknowledgementResult", - "bankBefore": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - } - ], - "bankAfter": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - } - ], - "error": true - } -] \ No newline at end of file diff --git a/x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvAcknowledgementResultFail.tla b/x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvAcknowledgementResultFail.tla deleted file mode 100644 index b97ec73a3ddc..000000000000 --- a/x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvAcknowledgementResultFail.tla +++ /dev/null @@ -1,159 +0,0 @@ -------------------------- MODULE counterexample ------------------------- - -EXTENDS relay_tests - -(* Initial state *) - -State1 == -TRUE -(* Transition 0 to State2 *) - -State2 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 -/\ count = 0 -/\ error = FALSE -/\ handler = "" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "channel-0"], - prefix1 |-> [channel |-> "transfer", port |-> "cosmos-hub"]], - receiver |-> "a2", - sender |-> "a1"], - destChannel |-> "", - destPort |-> "", - sourceChannel |-> "", - sourcePort |-> ""]] -/\ p = [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "channel-0"], - prefix1 |-> [channel |-> "transfer", port |-> "cosmos-hub"]], - receiver |-> "a2", - sender |-> "a1"], - destChannel |-> "", - destPort |-> "", - sourceChannel |-> "", - sourcePort |-> ""] - -(* Transition 13 to State3 *) - -State3 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 -/\ count = 1 -/\ error = TRUE -/\ handler = "OnRecvAcknowledgementResult" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "channel-0"], - prefix1 |-> [channel |-> "transfer", port |-> "cosmos-hub"]], - receiver |-> "a2", - sender |-> "a1"], - destChannel |-> "", - destPort |-> "", - sourceChannel |-> "", - sourcePort |-> ""]] - @@ 1 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> TRUE, - handler |-> "OnRecvAcknowledgementResult", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "channel-0"], - prefix1 |-> [channel |-> "transfer", port |-> "cosmos-hub"]], - receiver |-> "a2", - sender |-> "a1"], - destChannel |-> "", - destPort |-> "", - sourceChannel |-> "", - sourcePort |-> ""]] -/\ p = [data |-> - [amount |-> 0, - denomTrace |-> - [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "", - sender |-> ""], - destChannel |-> "", - destPort |-> "", - sourceChannel |-> "", - sourcePort |-> ""] - -(* The following formula holds true in the last state and violates the invariant *) - -InvariantViolation == - BMC!Skolem((\E s$2 \in DOMAIN history: - history[s$2]["handler"] = "OnRecvAcknowledgementResult" - /\ history[s$2]["error"] = TRUE - /\ history[s$2]["packet"]["data"]["amount"] > 0)) - -================================================================================ -\* Created by Apalache on Thu Dec 10 11:13:42 CET 2020 -\* https://github.com/informalsystems/apalache diff --git a/x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvAcknowledgementResultPass.json b/x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvAcknowledgementResultPass.json deleted file mode 100644 index 5215df7da332..000000000000 --- a/x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvAcknowledgementResultPass.json +++ /dev/null @@ -1,58 +0,0 @@ -[ - { - "packet": { - "sourceChannel": "ethereum-hub", - "sourcePort": "transfer", - "destChannel": "channel-0", - "destPort": "ethereum-hub", - "data": { - "sender": "a1", - "receiver": "a2", - "amount": 1, - "denom": [ - "cosmos-hub", - "transfer", - "channel-0", - "cosmos-hub", - "btc" - ] - } - }, - "handler": "OnRecvAcknowledgementResult", - "bankBefore": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - } - ], - "bankAfter": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - } - ], - "error": false - } -] \ No newline at end of file diff --git a/x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvAcknowledgementResultPass.tla b/x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvAcknowledgementResultPass.tla deleted file mode 100644 index f9d049c54636..000000000000 --- a/x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvAcknowledgementResultPass.tla +++ /dev/null @@ -1,159 +0,0 @@ -------------------------- MODULE counterexample ------------------------- - -EXTENDS relay_tests - -(* Initial state *) - -State1 == -TRUE -(* Transition 0 to State2 *) - -State2 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 -/\ count = 0 -/\ error = FALSE -/\ handler = "" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "channel-0"], - prefix1 |-> [channel |-> "transfer", port |-> "cosmos-hub"]], - receiver |-> "a2", - sender |-> "a1"], - destChannel |-> "channel-0", - destPort |-> "ethereum-hub", - sourceChannel |-> "ethereum-hub", - sourcePort |-> "transfer"]] -/\ p = [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "channel-0"], - prefix1 |-> [channel |-> "transfer", port |-> "cosmos-hub"]], - receiver |-> "a2", - sender |-> "a1"], - destChannel |-> "channel-0", - destPort |-> "ethereum-hub", - sourceChannel |-> "ethereum-hub", - sourcePort |-> "transfer"] - -(* Transition 12 to State3 *) - -State3 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 -/\ count = 1 -/\ error = FALSE -/\ handler = "OnRecvAcknowledgementResult" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "channel-0"], - prefix1 |-> [channel |-> "transfer", port |-> "cosmos-hub"]], - receiver |-> "a2", - sender |-> "a1"], - destChannel |-> "channel-0", - destPort |-> "ethereum-hub", - sourceChannel |-> "ethereum-hub", - sourcePort |-> "transfer"]] - @@ 1 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "OnRecvAcknowledgementResult", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "channel-0"], - prefix1 |-> [channel |-> "transfer", port |-> "cosmos-hub"]], - receiver |-> "a2", - sender |-> "a1"], - destChannel |-> "channel-0", - destPort |-> "ethereum-hub", - sourceChannel |-> "ethereum-hub", - sourcePort |-> "transfer"]] -/\ p = [data |-> - [amount |-> 0, - denomTrace |-> - [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "", - sender |-> ""], - destChannel |-> "", - destPort |-> "", - sourceChannel |-> "", - sourcePort |-> ""] - -(* The following formula holds true in the last state and violates the invariant *) - -InvariantViolation == - BMC!Skolem((\E s$2 \in DOMAIN history: - history[s$2]["handler"] = "OnRecvAcknowledgementResult" - /\ history[s$2]["error"] = FALSE - /\ history[s$2]["packet"]["data"]["amount"] > 0)) - -================================================================================ -\* Created by Apalache on Thu Dec 10 11:12:59 CET 2020 -\* https://github.com/informalsystems/apalache diff --git a/x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvPacketFail.json b/x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvPacketFail.json deleted file mode 100644 index 9a7e8c406e71..000000000000 --- a/x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvPacketFail.json +++ /dev/null @@ -1,58 +0,0 @@ -[ - { - "packet": { - "sourceChannel": "channel-0", - "sourcePort": "transfer", - "destChannel": "channel-0", - "destPort": "transfer", - "data": { - "sender": "", - "receiver": "", - "amount": 1, - "denom": [ - "", - "", - "transfer", - "channel-0", - "" - ] - } - }, - "handler": "OnRecvPacket", - "bankBefore": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - } - ], - "bankAfter": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - } - ], - "error": true - } -] \ No newline at end of file diff --git a/x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvPacketFail.tla b/x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvPacketFail.tla deleted file mode 100644 index 980be28ae28d..000000000000 --- a/x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvPacketFail.tla +++ /dev/null @@ -1,159 +0,0 @@ -------------------------- MODULE counterexample ------------------------- - -EXTENDS relay_tests - -(* Initial state *) - -State1 == -TRUE -(* Transition 0 to State2 *) - -State2 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 -/\ count = 0 -/\ error = FALSE -/\ handler = "" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "", - sender |-> ""], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] -/\ p = [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "", - sender |-> ""], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"] - -(* Transition 3 to State3 *) - -State3 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 -/\ count = 1 -/\ error = TRUE -/\ handler = "OnRecvPacket" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "", - sender |-> ""], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 1 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> TRUE, - handler |-> "OnRecvPacket", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "", - sender |-> ""], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] -/\ p = [data |-> - [amount |-> 0, - denomTrace |-> - [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "", - sender |-> ""], - destChannel |-> "", - destPort |-> "", - sourceChannel |-> "", - sourcePort |-> ""] - -(* The following formula holds true in the last state and violates the invariant *) - -InvariantViolation == - BMC!Skolem((\E s$2 \in DOMAIN history: - history[s$2]["handler"] = "OnRecvPacket" - /\ history[s$2]["error"] = TRUE - /\ history[s$2]["packet"]["data"]["amount"] > 0)) - -================================================================================ -\* Created by Apalache on Thu Dec 10 11:02:31 CET 2020 -\* https://github.com/informalsystems/apalache diff --git a/x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvPacketPass.json b/x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvPacketPass.json deleted file mode 100644 index 35f94c572081..000000000000 --- a/x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvPacketPass.json +++ /dev/null @@ -1,73 +0,0 @@ -[ - { - "packet": { - "sourceChannel": "channel-0", - "sourcePort": "transfer", - "destChannel": "channel-0", - "destPort": "transfer", - "data": { - "sender": "", - "receiver": "a2", - "amount": 1, - "denom": [ - "", - "", - "ethereum-hub", - "cosmos-hub", - "btc" - ] - } - }, - "handler": "OnRecvPacket", - "bankBefore": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - } - ], - "bankAfter": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - }, - { - "address": [ - "", - "", - "a2" - ], - "denom": [ - "transfer", - "channel-0", - "ethereum-hub", - "cosmos-hub", - "btc" - ], - "amount": 1 - } - ], - "error": false - } -] \ No newline at end of file diff --git a/x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvPacketPass.tla b/x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvPacketPass.tla deleted file mode 100644 index 342b097febb0..000000000000 --- a/x/ibc/applications/transfer/keeper/model_based_tests/TestOnRecvPacketPass.tla +++ /dev/null @@ -1,174 +0,0 @@ -------------------------- MODULE counterexample ------------------------- - -EXTENDS relay_tests - -(* Initial state *) - -State1 == -TRUE -(* Transition 0 to State2 *) - -State2 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 -/\ count = 0 -/\ error = FALSE -/\ handler = "" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> - [channel |-> "cosmos-hub", port |-> "ethereum-hub"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a2", - sender |-> ""], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] -/\ p = [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "ethereum-hub"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a2", - sender |-> ""], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"] - -(* Transition 5 to State3 *) - -State3 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "ethereum-hub"], - prefix1 |-> [channel |-> "channel-0", port |-> "transfer"]] - >> - :> 1 -/\ count = 1 -/\ error = FALSE -/\ handler = "OnRecvPacket" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> - [channel |-> "cosmos-hub", port |-> "ethereum-hub"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a2", - sender |-> ""], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 1 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "ethereum-hub"], - prefix1 |-> [channel |-> "channel-0", port |-> "transfer"]] - >> - :> 1, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "OnRecvPacket", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> - [channel |-> "cosmos-hub", port |-> "ethereum-hub"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a2", - sender |-> ""], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] -/\ p = [data |-> - [amount |-> 0, - denomTrace |-> - [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "", - sender |-> ""], - destChannel |-> "", - destPort |-> "", - sourceChannel |-> "", - sourcePort |-> ""] - -(* The following formula holds true in the last state and violates the invariant *) - -InvariantViolation == - BMC!Skolem((\E s$2 \in DOMAIN history: - history[s$2]["handler"] = "OnRecvPacket" - /\ history[s$2]["error"] = FALSE - /\ history[s$2]["packet"]["data"]["amount"] > 0)) - -================================================================================ -\* Created by Apalache on Thu Dec 10 11:01:28 CET 2020 -\* https://github.com/informalsystems/apalache diff --git a/x/ibc/applications/transfer/keeper/model_based_tests/TestOnTimeoutFail.json b/x/ibc/applications/transfer/keeper/model_based_tests/TestOnTimeoutFail.json deleted file mode 100644 index a78ed85ca585..000000000000 --- a/x/ibc/applications/transfer/keeper/model_based_tests/TestOnTimeoutFail.json +++ /dev/null @@ -1,58 +0,0 @@ -[ - { - "packet": { - "sourceChannel": "", - "sourcePort": "", - "destChannel": "", - "destPort": "", - "data": { - "sender": "a1", - "receiver": "a2", - "amount": 1, - "denom": [ - "cosmos-hub", - "transfer", - "channel-0", - "cosmos-hub", - "btc" - ] - } - }, - "handler": "OnTimeoutPacket", - "bankBefore": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - } - ], - "bankAfter": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - } - ], - "error": true - } -] \ No newline at end of file diff --git a/x/ibc/applications/transfer/keeper/model_based_tests/TestOnTimeoutFail.tla b/x/ibc/applications/transfer/keeper/model_based_tests/TestOnTimeoutFail.tla deleted file mode 100644 index 1bc209d9d5ec..000000000000 --- a/x/ibc/applications/transfer/keeper/model_based_tests/TestOnTimeoutFail.tla +++ /dev/null @@ -1,159 +0,0 @@ -------------------------- MODULE counterexample ------------------------- - -EXTENDS relay_tests - -(* Initial state *) - -State1 == -TRUE -(* Transition 0 to State2 *) - -State2 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 -/\ count = 0 -/\ error = FALSE -/\ handler = "" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "channel-0"], - prefix1 |-> [channel |-> "transfer", port |-> "cosmos-hub"]], - receiver |-> "a2", - sender |-> "a1"], - destChannel |-> "", - destPort |-> "", - sourceChannel |-> "", - sourcePort |-> ""]] -/\ p = [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "channel-0"], - prefix1 |-> [channel |-> "transfer", port |-> "cosmos-hub"]], - receiver |-> "a2", - sender |-> "a1"], - destChannel |-> "", - destPort |-> "", - sourceChannel |-> "", - sourcePort |-> ""] - -(* Transition 6 to State3 *) - -State3 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 -/\ count = 1 -/\ error = TRUE -/\ handler = "OnTimeoutPacket" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "channel-0"], - prefix1 |-> [channel |-> "transfer", port |-> "cosmos-hub"]], - receiver |-> "a2", - sender |-> "a1"], - destChannel |-> "", - destPort |-> "", - sourceChannel |-> "", - sourcePort |-> ""]] - @@ 1 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> TRUE, - handler |-> "OnTimeoutPacket", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "channel-0"], - prefix1 |-> [channel |-> "transfer", port |-> "cosmos-hub"]], - receiver |-> "a2", - sender |-> "a1"], - destChannel |-> "", - destPort |-> "", - sourceChannel |-> "", - sourcePort |-> ""]] -/\ p = [data |-> - [amount |-> 0, - denomTrace |-> - [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "", - sender |-> ""], - destChannel |-> "", - destPort |-> "", - sourceChannel |-> "", - sourcePort |-> ""] - -(* The following formula holds true in the last state and violates the invariant *) - -InvariantViolation == - BMC!Skolem((\E s$2 \in DOMAIN history: - history[s$2]["handler"] = "OnTimeoutPacket" - /\ history[s$2]["error"] = TRUE - /\ history[s$2]["packet"]["data"]["amount"] > 0)) - -================================================================================ -\* Created by Apalache on Thu Dec 10 11:09:25 CET 2020 -\* https://github.com/informalsystems/apalache diff --git a/x/ibc/applications/transfer/keeper/model_based_tests/TestOnTimeoutPass.json b/x/ibc/applications/transfer/keeper/model_based_tests/TestOnTimeoutPass.json deleted file mode 100644 index 3136aace654b..000000000000 --- a/x/ibc/applications/transfer/keeper/model_based_tests/TestOnTimeoutPass.json +++ /dev/null @@ -1,159 +0,0 @@ -[ - { - "packet": { - "sourceChannel": "channel-0", - "sourcePort": "transfer", - "destChannel": "channel-1", - "destPort": "transfer", - "data": { - "sender": "a3", - "receiver": "a1", - "amount": 1, - "denom": [ - "", - "", - "bitcoin-hub", - "transfer", - "btc" - ] - } - }, - "handler": "OnRecvPacket", - "bankBefore": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - } - ], - "bankAfter": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - }, - { - "address": [ - "", - "", - "a1" - ], - "denom": [ - "transfer", - "channel-1", - "bitcoin-hub", - "transfer", - "btc" - ], - "amount": 1 - } - ], - "error": false - }, - { - "packet": { - "sourceChannel": "channel-1", - "sourcePort": "transfer", - "destChannel": "channel-0", - "destPort": "transfer", - "data": { - "sender": "a1", - "receiver": "", - "amount": 1, - "denom": [ - "transfer", - "channel-1", - "bitcoin-hub", - "transfer", - "btc" - ] - } - }, - "handler": "OnTimeoutPacket", - "bankBefore": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - }, - { - "address": [ - "", - "", - "a1" - ], - "denom": [ - "transfer", - "channel-1", - "bitcoin-hub", - "transfer", - "btc" - ], - "amount": 1 - } - ], - "bankAfter": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - }, - { - "address": [ - "", - "", - "a1" - ], - "denom": [ - "transfer", - "channel-1", - "bitcoin-hub", - "transfer", - "btc" - ], - "amount": 2 - } - ], - "error": false - } -] \ No newline at end of file diff --git a/x/ibc/applications/transfer/keeper/model_based_tests/TestOnTimeoutPass.tla b/x/ibc/applications/transfer/keeper/model_based_tests/TestOnTimeoutPass.tla deleted file mode 100644 index 5dc5a994ae3e..000000000000 --- a/x/ibc/applications/transfer/keeper/model_based_tests/TestOnTimeoutPass.tla +++ /dev/null @@ -1,310 +0,0 @@ -------------------------- MODULE counterexample ------------------------- - -EXTENDS relay_tests - -(* Initial state *) - -State1 == -TRUE -(* Transition 0 to State2 *) - -State2 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 -/\ count = 0 -/\ error = FALSE -/\ handler = "" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "transfer", port |-> "bitcoin-hub"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a1", - sender |-> "a3"], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] -/\ p = [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "transfer", port |-> "bitcoin-hub"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a1", - sender |-> "a3"], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"] - -(* Transition 2 to State3 *) - -State3 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a1", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "transfer", port |-> "bitcoin-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 1 -/\ count = 1 -/\ error = FALSE -/\ handler = "OnRecvPacket" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "transfer", port |-> "bitcoin-hub"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a1", - sender |-> "a3"], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 1 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a1", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "transfer", port |-> "bitcoin-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 1, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "OnRecvPacket", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "transfer", port |-> "bitcoin-hub"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a1", - sender |-> "a3"], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] -/\ p = [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "transfer", port |-> "bitcoin-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]], - receiver |-> "", - sender |-> "a1"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-1", - sourcePort |-> "transfer"] - -(* Transition 10 to State4 *) - -State4 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a1", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "transfer", port |-> "bitcoin-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 2 -/\ count = 2 -/\ error = FALSE -/\ handler = "OnTimeoutPacket" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "transfer", port |-> "bitcoin-hub"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a1", - sender |-> "a3"], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 1 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a1", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "transfer", port |-> "bitcoin-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 1, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "OnRecvPacket", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "transfer", port |-> "bitcoin-hub"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a1", - sender |-> "a3"], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 2 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a1", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "transfer", port |-> "bitcoin-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 2, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a1", port |-> ""], [denom |-> "btc", - prefix0 |-> [channel |-> "transfer", port |-> "bitcoin-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]] - >> - :> 1, - error |-> FALSE, - handler |-> "OnTimeoutPacket", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "transfer", port |-> "bitcoin-hub"], - prefix1 |-> [channel |-> "channel-1", port |-> "transfer"]], - receiver |-> "", - sender |-> "a1"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-1", - sourcePort |-> "transfer"]] -/\ p = [data |-> - [amount |-> 0, - denomTrace |-> - [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "", - sender |-> ""], - destChannel |-> "", - destPort |-> "", - sourceChannel |-> "", - sourcePort |-> ""] - -(* The following formula holds true in the last state and violates the invariant *) - -InvariantViolation == - BMC!Skolem((\E s$2 \in DOMAIN history: - history[s$2]["handler"] = "OnTimeoutPacket" - /\ history[s$2]["error"] = FALSE - /\ history[s$2]["packet"]["data"]["amount"] > 0)) - -================================================================================ -\* Created by Apalache on Thu Dec 10 11:07:37 CET 2020 -\* https://github.com/informalsystems/apalache diff --git a/x/ibc/applications/transfer/keeper/model_based_tests/TestSendTransferFail.json b/x/ibc/applications/transfer/keeper/model_based_tests/TestSendTransferFail.json deleted file mode 100644 index 01d589d8677a..000000000000 --- a/x/ibc/applications/transfer/keeper/model_based_tests/TestSendTransferFail.json +++ /dev/null @@ -1,58 +0,0 @@ -[ - { - "packet": { - "sourceChannel": "channel-0", - "sourcePort": "transfer", - "destChannel": "channel-0", - "destPort": "transfer", - "data": { - "sender": "", - "receiver": "", - "amount": 1, - "denom": [ - "", - "", - "", - "", - "" - ] - } - }, - "handler": "SendTransfer", - "bankBefore": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - } - ], - "bankAfter": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - } - ], - "error": true - } -] \ No newline at end of file diff --git a/x/ibc/applications/transfer/keeper/model_based_tests/TestSendTransferFail.tla b/x/ibc/applications/transfer/keeper/model_based_tests/TestSendTransferFail.tla deleted file mode 100644 index dc3a1c008bdf..000000000000 --- a/x/ibc/applications/transfer/keeper/model_based_tests/TestSendTransferFail.tla +++ /dev/null @@ -1,159 +0,0 @@ -------------------------- MODULE counterexample ------------------------- - -EXTENDS relay_tests - -(* Initial state *) - -State1 == -TRUE -(* Transition 0 to State2 *) - -State2 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 -/\ count = 0 -/\ error = FALSE -/\ handler = "" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "", - sender |-> ""], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] -/\ p = [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "", - sender |-> ""], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"] - -(* Transition 0 to State3 *) - -State3 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 -/\ count = 1 -/\ error = TRUE -/\ handler = "SendTransfer" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "", - sender |-> ""], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 1 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> TRUE, - handler |-> "SendTransfer", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "", - sender |-> ""], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] -/\ p = [data |-> - [amount |-> 0, - denomTrace |-> - [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "", - sender |-> ""], - destChannel |-> "", - destPort |-> "", - sourceChannel |-> "", - sourcePort |-> ""] - -(* The following formula holds true in the last state and violates the invariant *) - -InvariantViolation == - BMC!Skolem((\E s$2 \in DOMAIN history: - history[s$2]["handler"] = "SendTransfer" - /\ history[s$2]["error"] = TRUE - /\ history[s$2]["packet"]["data"]["amount"] > 0)) - -================================================================================ -\* Created by Apalache on Thu Dec 10 11:00:34 CET 2020 -\* https://github.com/informalsystems/apalache diff --git a/x/ibc/applications/transfer/keeper/model_based_tests/TestSendTransferPass.json b/x/ibc/applications/transfer/keeper/model_based_tests/TestSendTransferPass.json deleted file mode 100644 index 452d2b3aa943..000000000000 --- a/x/ibc/applications/transfer/keeper/model_based_tests/TestSendTransferPass.json +++ /dev/null @@ -1,174 +0,0 @@ -[ - { - "packet": { - "sourceChannel": "channel-0", - "sourcePort": "transfer", - "destChannel": "channel-0", - "destPort": "transfer", - "data": { - "sender": "a3", - "receiver": "a2", - "amount": 1, - "denom": [ - "", - "", - "cosmos-hub", - "cosmos-hub", - "eth" - ] - } - }, - "handler": "OnRecvPacket", - "bankBefore": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - } - ], - "bankAfter": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - }, - { - "address": [ - "", - "", - "a2" - ], - "denom": [ - "transfer", - "channel-0", - "cosmos-hub", - "cosmos-hub", - "eth" - ], - "amount": 1 - } - ], - "error": false - }, - { - "packet": { - "sourceChannel": "channel-1", - "sourcePort": "transfer", - "destChannel": "channel-0", - "destPort": "transfer", - "data": { - "sender": "a2", - "receiver": "a1", - "amount": 1, - "denom": [ - "transfer", - "channel-0", - "cosmos-hub", - "cosmos-hub", - "eth" - ] - } - }, - "handler": "SendTransfer", - "bankBefore": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - }, - { - "address": [ - "", - "", - "a2" - ], - "denom": [ - "transfer", - "channel-0", - "cosmos-hub", - "cosmos-hub", - "eth" - ], - "amount": 1 - } - ], - "bankAfter": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - }, - { - "address": [ - "", - "", - "a2" - ], - "denom": [ - "transfer", - "channel-0", - "cosmos-hub", - "cosmos-hub", - "eth" - ], - "amount": 0 - }, - { - "address": [ - "transfer", - "channel-1", - "" - ], - "denom": [ - "transfer", - "channel-0", - "cosmos-hub", - "cosmos-hub", - "eth" - ], - "amount": 1 - } - ], - "error": false - } -] \ No newline at end of file diff --git a/x/ibc/applications/transfer/keeper/model_based_tests/TestSendTransferPass.tla b/x/ibc/applications/transfer/keeper/model_based_tests/TestSendTransferPass.tla deleted file mode 100644 index 23c45c6773ec..000000000000 --- a/x/ibc/applications/transfer/keeper/model_based_tests/TestSendTransferPass.tla +++ /dev/null @@ -1,323 +0,0 @@ -------------------------- MODULE counterexample ------------------------- - -EXTENDS relay_tests - -(* Initial state *) - -State1 == -TRUE -(* Transition 0 to State2 *) - -State2 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 -/\ count = 0 -/\ error = FALSE -/\ handler = "" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "eth", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a2", - sender |-> "a3"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] -/\ p = [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "eth", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a2", - sender |-> "a3"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"] - -(* Transition 2 to State3 *) - -State3 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "eth", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-0", port |-> "transfer"]] - >> - :> 1 -/\ count = 1 -/\ error = FALSE -/\ handler = "OnRecvPacket" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "eth", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a2", - sender |-> "a3"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 1 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "eth", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-0", port |-> "transfer"]] - >> - :> 1, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "OnRecvPacket", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "eth", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a2", - sender |-> "a3"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] -/\ p = [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "eth", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-0", port |-> "transfer"]], - receiver |-> "a1", - sender |-> "a2"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-1", - sourcePort |-> "transfer"] - -(* Transition 1 to State4 *) - -State4 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "eth", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-0", port |-> "transfer"]] - >> - :> 0 - @@ << - [channel |-> "channel-1", id |-> "", port |-> "transfer"], [denom |-> "eth", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-0", port |-> "transfer"]] - >> - :> 1 -/\ count = 2 -/\ error = FALSE -/\ handler = "SendTransfer" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "eth", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a2", - sender |-> "a3"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 1 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "eth", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-0", port |-> "transfer"]] - >> - :> 1, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "OnRecvPacket", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "eth", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a2", - sender |-> "a3"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 2 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "eth", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-0", port |-> "transfer"]] - >> - :> 0 - @@ << - [channel |-> "channel-1", id |-> "", port |-> "transfer"], [denom |-> - "eth", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-0", port |-> "transfer"]] - >> - :> 1, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a2", port |-> ""], [denom |-> "eth", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-0", port |-> "transfer"]] - >> - :> 1, - error |-> FALSE, - handler |-> "SendTransfer", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "eth", - prefix0 |-> [channel |-> "cosmos-hub", port |-> "cosmos-hub"], - prefix1 |-> [channel |-> "channel-0", port |-> "transfer"]], - receiver |-> "a1", - sender |-> "a2"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-1", - sourcePort |-> "transfer"]] -/\ p = [data |-> - [amount |-> 0, - denomTrace |-> - [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "", - sender |-> ""], - destChannel |-> "", - destPort |-> "", - sourceChannel |-> "", - sourcePort |-> ""] - -(* The following formula holds true in the last state and violates the invariant *) - -InvariantViolation == - BMC!Skolem((\E s$2 \in DOMAIN history: - history[s$2]["handler"] = "SendTransfer" - /\ history[s$2]["error"] = FALSE - /\ history[s$2]["packet"]["data"]["amount"] > 0)) - -================================================================================ -\* Created by Apalache on Thu Dec 10 10:58:54 CET 2020 -\* https://github.com/informalsystems/apalache diff --git a/x/ibc/applications/transfer/keeper/model_based_tests/TestUnescrowTokens.json b/x/ibc/applications/transfer/keeper/model_based_tests/TestUnescrowTokens.json deleted file mode 100644 index 985522070477..000000000000 --- a/x/ibc/applications/transfer/keeper/model_based_tests/TestUnescrowTokens.json +++ /dev/null @@ -1,305 +0,0 @@ -[ - { - "packet": { - "sourceChannel": "channel-0", - "sourcePort": "transfer", - "destChannel": "channel-0", - "destPort": "transfer", - "data": { - "sender": "a1", - "receiver": "a3", - "amount": 5, - "denom": [ - "", - "", - "", - "", - "atom" - ] - } - }, - "handler": "OnRecvPacket", - "bankBefore": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - } - ], - "bankAfter": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - }, - { - "address": [ - "", - "", - "a3" - ], - "denom": [ - "", - "", - "transfer", - "channel-0", - "atom" - ], - "amount": 5 - } - ], - "error": false - }, - { - "packet": { - "sourceChannel": "channel-1", - "sourcePort": "transfer", - "destChannel": "channel-0", - "destPort": "transfer", - "data": { - "sender": "a3", - "receiver": "a1", - "amount": 3, - "denom": [ - "", - "", - "transfer", - "channel-0", - "atom" - ] - } - }, - "handler": "SendTransfer", - "bankBefore": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - }, - { - "address": [ - "", - "", - "a3" - ], - "denom": [ - "", - "", - "transfer", - "channel-0", - "atom" - ], - "amount": 5 - } - ], - "bankAfter": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - }, - { - "address": [ - "", - "", - "a3" - ], - "denom": [ - "", - "", - "transfer", - "channel-0", - "atom" - ], - "amount": 2 - }, - { - "address": [ - "transfer", - "channel-1", - "" - ], - "denom": [ - "", - "", - "transfer", - "channel-0", - "atom" - ], - "amount": 3 - } - ], - "error": false - }, - { - "packet": { - "sourceChannel": "channel-0", - "sourcePort": "transfer", - "destChannel": "channel-1", - "destPort": "transfer", - "data": { - "sender": "a1", - "receiver": "a1", - "amount": 1, - "denom": [ - "transfer", - "channel-0", - "transfer", - "channel-0", - "atom" - ] - } - }, - "handler": "OnRecvPacket", - "bankBefore": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - }, - { - "address": [ - "", - "", - "a3" - ], - "denom": [ - "", - "", - "transfer", - "channel-0", - "atom" - ], - "amount": 2 - }, - { - "address": [ - "transfer", - "channel-1", - "" - ], - "denom": [ - "", - "", - "transfer", - "channel-0", - "atom" - ], - "amount": 3 - } - ], - "bankAfter": [ - { - "address": [ - "", - "", - "" - ], - "denom": [ - "", - "", - "", - "", - "" - ], - "amount": 0 - }, - { - "address": [ - "", - "", - "a1" - ], - "denom": [ - "", - "", - "transfer", - "channel-0", - "atom" - ], - "amount": 1 - }, - { - "address": [ - "", - "", - "a3" - ], - "denom": [ - "", - "", - "transfer", - "channel-0", - "atom" - ], - "amount": 2 - }, - { - "address": [ - "transfer", - "channel-1", - "" - ], - "denom": [ - "", - "", - "transfer", - "channel-0", - "atom" - ], - "amount": 2 - } - ], - "error": false - } -] \ No newline at end of file diff --git a/x/ibc/applications/transfer/keeper/model_based_tests/TestUnescrowTokens.tla b/x/ibc/applications/transfer/keeper/model_based_tests/TestUnescrowTokens.tla deleted file mode 100644 index e99081c12378..000000000000 --- a/x/ibc/applications/transfer/keeper/model_based_tests/TestUnescrowTokens.tla +++ /dev/null @@ -1,563 +0,0 @@ -------------------------- MODULE counterexample ------------------------- - -EXTENDS relay_tests - -(* Initial state *) - -State1 == -TRUE -(* Transition 0 to State2 *) - -State2 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 -/\ count = 0 -/\ error = FALSE -/\ handler = "" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 5, - denomTrace |-> - [denom |-> "atom", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a3", - sender |-> "a1"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] -/\ p = [data |-> - [amount |-> 5, - denomTrace |-> - [denom |-> "atom", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a3", - sender |-> "a1"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"] - -(* Transition 3 to State3 *) - -State3 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 5 -/\ count = 1 -/\ error = FALSE -/\ handler = "OnRecvPacket" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 5, - denomTrace |-> - [denom |-> "atom", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a3", - sender |-> "a1"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 1 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 5, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "OnRecvPacket", - packet |-> - [data |-> - [amount |-> 5, - denomTrace |-> - [denom |-> "atom", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a3", - sender |-> "a1"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] -/\ p = [data |-> - [amount |-> 3, - denomTrace |-> - [denom |-> "atom", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a1", - sender |-> "a3"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-1", - sourcePort |-> "transfer"] - -(* Transition 1 to State4 *) - -State4 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2 - @@ << - [channel |-> "channel-1", id |-> "", port |-> "transfer"], [denom |-> "atom", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 3 -/\ count = 2 -/\ error = FALSE -/\ handler = "SendTransfer" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 5, - denomTrace |-> - [denom |-> "atom", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a3", - sender |-> "a1"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 1 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 5, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "OnRecvPacket", - packet |-> - [data |-> - [amount |-> 5, - denomTrace |-> - [denom |-> "atom", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a3", - sender |-> "a1"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 2 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2 - @@ << - [channel |-> "channel-1", id |-> "", port |-> "transfer"], [denom |-> - "atom", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 3, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 5, - error |-> FALSE, - handler |-> "SendTransfer", - packet |-> - [data |-> - [amount |-> 3, - denomTrace |-> - [denom |-> "atom", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a1", - sender |-> "a3"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-1", - sourcePort |-> "transfer"]] -/\ p = [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "atom", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "channel-0", port |-> "transfer"]], - receiver |-> "a1", - sender |-> "a1"], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"] - -(* Transition 4 to State5 *) - -State5 == -/\ bank = << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a1", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 1 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2 - @@ << - [channel |-> "channel-1", id |-> "", port |-> "transfer"], [denom |-> "atom", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2 -/\ count = 3 -/\ error = FALSE -/\ handler = "OnRecvPacket" -/\ history = 0 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "", - packet |-> - [data |-> - [amount |-> 5, - denomTrace |-> - [denom |-> "atom", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a3", - sender |-> "a1"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 1 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 5, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0, - error |-> FALSE, - handler |-> "OnRecvPacket", - packet |-> - [data |-> - [amount |-> 5, - denomTrace |-> - [denom |-> "atom", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a3", - sender |-> "a1"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] - @@ 2 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2 - @@ << - [channel |-> "channel-1", id |-> "", port |-> "transfer"], [denom |-> - "atom", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 3, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 5, - error |-> FALSE, - handler |-> "SendTransfer", - packet |-> - [data |-> - [amount |-> 3, - denomTrace |-> - [denom |-> "atom", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]], - receiver |-> "a1", - sender |-> "a3"], - destChannel |-> "channel-0", - destPort |-> "transfer", - sourceChannel |-> "channel-1", - sourcePort |-> "transfer"]] - @@ 3 - :> [bankAfter |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a1", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 1 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2 - @@ << - [channel |-> "channel-1", id |-> "", port |-> "transfer"], [denom |-> - "atom", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2, - bankBefore |-> - << - [channel |-> "", id |-> "", port |-> ""], [denom |-> "", - prefix0 |-> [channel |-> "", port |-> ""], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 0 - @@ << - [channel |-> "", id |-> "a3", port |-> ""], [denom |-> "atom", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 2 - @@ << - [channel |-> "channel-1", id |-> "", port |-> "transfer"], [denom |-> - "atom", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "", port |-> ""]] - >> - :> 3, - error |-> FALSE, - handler |-> "OnRecvPacket", - packet |-> - [data |-> - [amount |-> 1, - denomTrace |-> - [denom |-> "atom", - prefix0 |-> [channel |-> "channel-0", port |-> "transfer"], - prefix1 |-> [channel |-> "channel-0", port |-> "transfer"]], - receiver |-> "a1", - sender |-> "a1"], - destChannel |-> "channel-1", - destPort |-> "transfer", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"]] -/\ p = [data |-> - [amount |-> 0, - denomTrace |-> - [denom |-> "btc", - prefix0 |-> [channel |-> "transfer", port |-> "bitcoin-hub"], - prefix1 |-> [channel |-> "channel-0", port |-> "channel-1"]], - receiver |-> "a1", - sender |-> ""], - destChannel |-> "ethereum-hub", - destPort |-> "cosmos-hub", - sourceChannel |-> "channel-0", - sourcePort |-> "transfer"] - -(* The following formula holds true in the last state and violates the invariant *) - -InvariantViolation == - history[1]["handler"] = "OnRecvPacket" - /\ BMC!Skolem((\E s$2 \in DOMAIN history: - ((IF history[s$2]["packet"]["data"]["denomTrace"]["prefix0"] - = [port |-> "", channel |-> ""] - THEN [port |-> "", channel |-> ""] - ELSE IF history[s$2]["packet"]["data"]["denomTrace"]["prefix1"] - = [port |-> "", channel |-> ""] - THEN history[s$2]["packet"]["data"]["denomTrace"]["prefix0"] - ELSE history[s$2]["packet"]["data"]["denomTrace"]["prefix1"])[ - "port" - ] - = history[s$2]["packet"]["sourcePort"] - /\ (IF history[s$2]["packet"]["data"]["denomTrace"]["prefix0"] - = [port |-> "", channel |-> ""] - THEN [port |-> "", channel |-> ""] - ELSE IF history[s$2]["packet"]["data"]["denomTrace"]["prefix1"] - = [port |-> "", channel |-> ""] - THEN history[s$2]["packet"]["data"]["denomTrace"]["prefix0"] - ELSE history[s$2]["packet"]["data"]["denomTrace"]["prefix1"])[ - "channel" - ] - = history[s$2]["packet"]["sourceChannel"]) - /\ history[s$2]["handler"] = "OnRecvPacket" - /\ history[s$2]["error"] = FALSE)) - -================================================================================ -\* Created by Apalache on Thu Dec 10 13:38:11 CET 2020 -\* https://github.com/informalsystems/apalache diff --git a/x/ibc/applications/transfer/keeper/msg_server.go b/x/ibc/applications/transfer/keeper/msg_server.go deleted file mode 100644 index dd2999af341e..000000000000 --- a/x/ibc/applications/transfer/keeper/msg_server.go +++ /dev/null @@ -1,43 +0,0 @@ -package keeper - -import ( - "context" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" -) - -var _ types.MsgServer = Keeper{} - -// See createOutgoingPacket in spec:https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#packet-relay - -// Transfer defines a rpc handler method for MsgTransfer. -func (k Keeper) Transfer(goCtx context.Context, msg *types.MsgTransfer) (*types.MsgTransferResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - sender, err := sdk.AccAddressFromBech32(msg.Sender) - if err != nil { - return nil, err - } - if err := k.SendTransfer( - ctx, msg.SourcePort, msg.SourceChannel, msg.Token, sender, msg.Receiver, msg.TimeoutHeight, msg.TimeoutTimestamp, - ); err != nil { - return nil, err - } - - k.Logger(ctx).Info("IBC fungible token transfer", "token", msg.Token.Denom, "amount", msg.Token.Amount.String(), "sender", msg.Sender, "receiver", msg.Receiver) - - ctx.EventManager().EmitEvents(sdk.Events{ - sdk.NewEvent( - types.EventTypeTransfer, - sdk.NewAttribute(sdk.AttributeKeySender, msg.Sender), - sdk.NewAttribute(types.AttributeKeyReceiver, msg.Receiver), - ), - sdk.NewEvent( - sdk.EventTypeMessage, - sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), - ), - }) - - return &types.MsgTransferResponse{}, nil -} diff --git a/x/ibc/applications/transfer/keeper/params.go b/x/ibc/applications/transfer/keeper/params.go deleted file mode 100644 index 39a6c5d53de8..000000000000 --- a/x/ibc/applications/transfer/keeper/params.go +++ /dev/null @@ -1,30 +0,0 @@ -package keeper - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" -) - -// GetSendEnabled retrieves the send enabled boolean from the paramstore -func (k Keeper) GetSendEnabled(ctx sdk.Context) bool { - var res bool - k.paramSpace.Get(ctx, types.KeySendEnabled, &res) - return res -} - -// GetReceiveEnabled retrieves the receive enabled boolean from the paramstore -func (k Keeper) GetReceiveEnabled(ctx sdk.Context) bool { - var res bool - k.paramSpace.Get(ctx, types.KeyReceiveEnabled, &res) - return res -} - -// GetParams returns the total set of ibc-transfer parameters. -func (k Keeper) GetParams(ctx sdk.Context) types.Params { - return types.NewParams(k.GetSendEnabled(ctx), k.GetReceiveEnabled(ctx)) -} - -// SetParams sets the total set of ibc-transfer parameters. -func (k Keeper) SetParams(ctx sdk.Context, params types.Params) { - k.paramSpace.SetParamSet(ctx, ¶ms) -} diff --git a/x/ibc/applications/transfer/keeper/params_test.go b/x/ibc/applications/transfer/keeper/params_test.go deleted file mode 100644 index 96f17ff7f1cb..000000000000 --- a/x/ibc/applications/transfer/keeper/params_test.go +++ /dev/null @@ -1,15 +0,0 @@ -package keeper_test - -import "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" - -func (suite *KeeperTestSuite) TestParams() { - expParams := types.DefaultParams() - - params := suite.chainA.App.TransferKeeper.GetParams(suite.chainA.GetContext()) - suite.Require().Equal(expParams, params) - - expParams.SendEnabled = false - suite.chainA.App.TransferKeeper.SetParams(suite.chainA.GetContext(), expParams) - params = suite.chainA.App.TransferKeeper.GetParams(suite.chainA.GetContext()) - suite.Require().Equal(expParams, params) -} diff --git a/x/ibc/applications/transfer/keeper/relay.go b/x/ibc/applications/transfer/keeper/relay.go deleted file mode 100644 index 4889014a40af..000000000000 --- a/x/ibc/applications/transfer/keeper/relay.go +++ /dev/null @@ -1,406 +0,0 @@ -package keeper - -import ( - "fmt" - "strings" - - "github.com/armon/go-metrics" - - "github.com/cosmos/cosmos-sdk/telemetry" - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" -) - -// SendTransfer handles transfer sending logic. There are 2 possible cases: -// -// 1. Sender chain is acting as the source zone. The coins are transferred -// to an escrow address (i.e locked) on the sender chain and then transferred -// to the receiving chain through IBC TAO logic. It is expected that the -// receiving chain will mint vouchers to the receiving address. -// -// 2. Sender chain is acting as the sink zone. The coins (vouchers) are burned -// on the sender chain and then transferred to the receiving chain though IBC -// TAO logic. It is expected that the receiving chain, which had previously -// sent the original denomination, will unescrow the fungible token and send -// it to the receiving address. -// -// Another way of thinking of source and sink zones is through the token's -// timeline. Each send to any chain other than the one it was previously -// received from is a movement forwards in the token's timeline. This causes -// trace to be added to the token's history and the destination port and -// destination channel to be prefixed to the denomination. In these instances -// the sender chain is acting as the source zone. When the token is sent back -// to the chain it previously received from, the prefix is removed. This is -// a backwards movement in the token's timeline and the sender chain -// is acting as the sink zone. -// -// Example: -// These steps of transfer occur: A -> B -> C -> A -> C -> B -> A -// -// 1. A -> B : sender chain is source zone. Denom upon receiving: 'B/denom' -// 2. B -> C : sender chain is source zone. Denom upon receiving: 'C/B/denom' -// 3. C -> A : sender chain is source zone. Denom upon receiving: 'A/C/B/denom' -// 4. A -> C : sender chain is sink zone. Denom upon receiving: 'C/B/denom' -// 5. C -> B : sender chain is sink zone. Denom upon receiving: 'B/denom' -// 6. B -> A : sender chain is sink zone. Denom upon receiving: 'denom' -func (k Keeper) SendTransfer( - ctx sdk.Context, - sourcePort, - sourceChannel string, - token sdk.Coin, - sender sdk.AccAddress, - receiver string, - timeoutHeight clienttypes.Height, - timeoutTimestamp uint64, -) error { - - if !k.GetSendEnabled(ctx) { - return types.ErrSendDisabled - } - - sourceChannelEnd, found := k.channelKeeper.GetChannel(ctx, sourcePort, sourceChannel) - if !found { - return sdkerrors.Wrapf(channeltypes.ErrChannelNotFound, "port ID (%s) channel ID (%s)", sourcePort, sourceChannel) - } - - destinationPort := sourceChannelEnd.GetCounterparty().GetPortID() - destinationChannel := sourceChannelEnd.GetCounterparty().GetChannelID() - - // get the next sequence - sequence, found := k.channelKeeper.GetNextSequenceSend(ctx, sourcePort, sourceChannel) - if !found { - return sdkerrors.Wrapf( - channeltypes.ErrSequenceSendNotFound, - "source port: %s, source channel: %s", sourcePort, sourceChannel, - ) - } - - // begin createOutgoingPacket logic - // See spec for this logic: https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#packet-relay - channelCap, ok := k.scopedKeeper.GetCapability(ctx, host.ChannelCapabilityPath(sourcePort, sourceChannel)) - if !ok { - return sdkerrors.Wrap(channeltypes.ErrChannelCapabilityNotFound, "module does not own channel capability") - } - - // NOTE: denomination and hex hash correctness checked during msg.ValidateBasic - fullDenomPath := token.Denom - - var err error - - // deconstruct the token denomination into the denomination trace info - // to determine if the sender is the source chain - if strings.HasPrefix(token.Denom, "ibc/") { - fullDenomPath, err = k.DenomPathFromHash(ctx, token.Denom) - if err != nil { - return err - } - } - - labels := []metrics.Label{ - telemetry.NewLabel("destination-port", destinationPort), - telemetry.NewLabel("destination-channel", destinationChannel), - } - - // NOTE: SendTransfer simply sends the denomination as it exists on its own - // chain inside the packet data. The receiving chain will perform denom - // prefixing as necessary. - - if types.SenderChainIsSource(sourcePort, sourceChannel, fullDenomPath) { - labels = append(labels, telemetry.NewLabel("source", "true")) - - // create the escrow address for the tokens - escrowAddress := types.GetEscrowAddress(sourcePort, sourceChannel) - - // escrow source tokens. It fails if balance insufficient. - if err := k.bankKeeper.SendCoins( - ctx, sender, escrowAddress, sdk.NewCoins(token), - ); err != nil { - return err - } - - } else { - labels = append(labels, telemetry.NewLabel("source", "false")) - - // transfer the coins to the module account and burn them - if err := k.bankKeeper.SendCoinsFromAccountToModule( - ctx, sender, types.ModuleName, sdk.NewCoins(token), - ); err != nil { - return err - } - - if err := k.bankKeeper.BurnCoins( - ctx, types.ModuleName, sdk.NewCoins(token), - ); err != nil { - // NOTE: should not happen as the module account was - // retrieved on the step above and it has enough balace - // to burn. - panic(fmt.Sprintf("cannot burn coins after a successful send to a module account: %v", err)) - } - } - - packetData := types.NewFungibleTokenPacketData( - fullDenomPath, token.Amount.Uint64(), sender.String(), receiver, - ) - - packet := channeltypes.NewPacket( - packetData.GetBytes(), - sequence, - sourcePort, - sourceChannel, - destinationPort, - destinationChannel, - timeoutHeight, - timeoutTimestamp, - ) - - if err := k.channelKeeper.SendPacket(ctx, channelCap, packet); err != nil { - return err - } - - defer func() { - telemetry.SetGaugeWithLabels( - []string{"tx", "msg", "ibc", "transfer"}, - float32(token.Amount.Int64()), - []metrics.Label{telemetry.NewLabel("denom", fullDenomPath)}, - ) - - telemetry.IncrCounterWithLabels( - []string{"ibc", types.ModuleName, "send"}, - 1, - labels, - ) - }() - - return nil -} - -// OnRecvPacket processes a cross chain fungible token transfer. If the -// sender chain is the source of minted tokens then vouchers will be minted -// and sent to the receiving address. Otherwise if the sender chain is sending -// back tokens this chain originally transferred to it, the tokens are -// unescrowed and sent to the receiving address. -func (k Keeper) OnRecvPacket(ctx sdk.Context, packet channeltypes.Packet, data types.FungibleTokenPacketData) error { - // validate packet data upon receiving - if err := data.ValidateBasic(); err != nil { - return err - } - - if !k.GetReceiveEnabled(ctx) { - return types.ErrReceiveDisabled - } - - // decode the receiver address - receiver, err := sdk.AccAddressFromBech32(data.Receiver) - if err != nil { - return err - } - - labels := []metrics.Label{ - telemetry.NewLabel("source-port", packet.GetSourcePort()), - telemetry.NewLabel("source-channel", packet.GetSourceChannel()), - } - - // This is the prefix that would have been prefixed to the denomination - // on sender chain IF and only if the token originally came from the - // receiving chain. - // - // NOTE: We use SourcePort and SourceChannel here, because the counterparty - // chain would have prefixed with DestPort and DestChannel when originally - // receiving this coin as seen in the "sender chain is the source" condition. - - if types.ReceiverChainIsSource(packet.GetSourcePort(), packet.GetSourceChannel(), data.Denom) { - // sender chain is not the source, unescrow tokens - - // remove prefix added by sender chain - voucherPrefix := types.GetDenomPrefix(packet.GetSourcePort(), packet.GetSourceChannel()) - unprefixedDenom := data.Denom[len(voucherPrefix):] - - // coin denomination used in sending from the escrow address - denom := unprefixedDenom - - // The denomination used to send the coins is either the native denom or the hash of the path - // if the denomination is not native. - denomTrace := types.ParseDenomTrace(unprefixedDenom) - if denomTrace.Path != "" { - denom = denomTrace.IBCDenom() - } - token := sdk.NewCoin(denom, sdk.NewIntFromUint64(data.Amount)) - - // unescrow tokens - escrowAddress := types.GetEscrowAddress(packet.GetDestPort(), packet.GetDestChannel()) - if err := k.bankKeeper.SendCoins(ctx, escrowAddress, receiver, sdk.NewCoins(token)); err != nil { - // NOTE: this error is only expected to occur given an unexpected bug or a malicious - // counterparty module. The bug may occur in bank or any part of the code that allows - // the escrow address to be drained. A malicious counterparty module could drain the - // escrow address by allowing more tokens to be sent back then were escrowed. - return sdkerrors.Wrap(err, "unable to unescrow tokens, this may be caused by a malicious counterparty module or a bug: please open an issue on counterparty module") - } - - defer func() { - telemetry.SetGaugeWithLabels( - []string{"ibc", types.ModuleName, "packet", "receive"}, - float32(data.Amount), - []metrics.Label{telemetry.NewLabel("denom", unprefixedDenom)}, - ) - - telemetry.IncrCounterWithLabels( - []string{"ibc", types.ModuleName, "receive"}, - 1, - append( - labels, telemetry.NewLabel("source", "true"), - ), - ) - }() - - return nil - } - - // sender chain is the source, mint vouchers - - // since SendPacket did not prefix the denomination, we must prefix denomination here - sourcePrefix := types.GetDenomPrefix(packet.GetDestPort(), packet.GetDestChannel()) - // NOTE: sourcePrefix contains the trailing "/" - prefixedDenom := sourcePrefix + data.Denom - - // construct the denomination trace from the full raw denomination - denomTrace := types.ParseDenomTrace(prefixedDenom) - - traceHash := denomTrace.Hash() - if !k.HasDenomTrace(ctx, traceHash) { - k.SetDenomTrace(ctx, denomTrace) - } - - voucherDenom := denomTrace.IBCDenom() - ctx.EventManager().EmitEvent( - sdk.NewEvent( - types.EventTypeDenomTrace, - sdk.NewAttribute(types.AttributeKeyTraceHash, traceHash.String()), - sdk.NewAttribute(types.AttributeKeyDenom, voucherDenom), - ), - ) - - voucher := sdk.NewCoin(voucherDenom, sdk.NewIntFromUint64(data.Amount)) - - // mint new tokens if the source of the transfer is the same chain - if err := k.bankKeeper.MintCoins( - ctx, types.ModuleName, sdk.NewCoins(voucher), - ); err != nil { - return err - } - - // send to receiver - if err := k.bankKeeper.SendCoinsFromModuleToAccount( - ctx, types.ModuleName, receiver, sdk.NewCoins(voucher), - ); err != nil { - panic(fmt.Sprintf("unable to send coins from module to account despite previously minting coins to module account: %v", err)) - } - - defer func() { - telemetry.SetGaugeWithLabels( - []string{"ibc", types.ModuleName, "packet", "receive"}, - float32(data.Amount), - []metrics.Label{telemetry.NewLabel("denom", data.Denom)}, - ) - - telemetry.IncrCounterWithLabels( - []string{"ibc", types.ModuleName, "receive"}, - 1, - append( - labels, telemetry.NewLabel("source", "false"), - ), - ) - }() - - return nil -} - -// OnAcknowledgementPacket responds to the the success or failure of a packet -// acknowledgement written on the receiving chain. If the acknowledgement -// was a success then nothing occurs. If the acknowledgement failed, then -// the sender is refunded their tokens using the refundPacketToken function. -func (k Keeper) OnAcknowledgementPacket(ctx sdk.Context, packet channeltypes.Packet, data types.FungibleTokenPacketData, ack channeltypes.Acknowledgement) error { - switch ack.Response.(type) { - case *channeltypes.Acknowledgement_Error: - return k.refundPacketToken(ctx, packet, data) - default: - // the acknowledgement succeeded on the receiving chain so nothing - // needs to be executed and no error needs to be returned - return nil - } -} - -// OnTimeoutPacket refunds the sender since the original packet sent was -// never received and has been timed out. -func (k Keeper) OnTimeoutPacket(ctx sdk.Context, packet channeltypes.Packet, data types.FungibleTokenPacketData) error { - return k.refundPacketToken(ctx, packet, data) -} - -// refundPacketToken will unescrow and send back the tokens back to sender -// if the sending chain was the source chain. Otherwise, the sent tokens -// were burnt in the original send so new tokens are minted and sent to -// the sending address. -func (k Keeper) refundPacketToken(ctx sdk.Context, packet channeltypes.Packet, data types.FungibleTokenPacketData) error { - // NOTE: packet data type already checked in handler.go - - // parse the denomination from the full denom path - trace := types.ParseDenomTrace(data.Denom) - - token := sdk.NewCoin(trace.IBCDenom(), sdk.NewIntFromUint64(data.Amount)) - - // decode the sender address - sender, err := sdk.AccAddressFromBech32(data.Sender) - if err != nil { - return err - } - - if types.SenderChainIsSource(packet.GetSourcePort(), packet.GetSourceChannel(), data.Denom) { - // unescrow tokens back to sender - escrowAddress := types.GetEscrowAddress(packet.GetSourcePort(), packet.GetSourceChannel()) - if err := k.bankKeeper.SendCoins(ctx, escrowAddress, sender, sdk.NewCoins(token)); err != nil { - // NOTE: this error is only expected to occur given an unexpected bug or a malicious - // counterparty module. The bug may occur in bank or any part of the code that allows - // the escrow address to be drained. A malicious counterparty module could drain the - // escrow address by allowing more tokens to be sent back then were escrowed. - return sdkerrors.Wrap(err, "unable to unescrow tokens, this may be caused by a malicious counterparty module or a bug: please open an issue on counterparty module") - } - - return nil - } - - // mint vouchers back to sender - if err := k.bankKeeper.MintCoins( - ctx, types.ModuleName, sdk.NewCoins(token), - ); err != nil { - return err - } - - if err := k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, sender, sdk.NewCoins(token)); err != nil { - panic(fmt.Sprintf("unable to send coins from module to account despite previously minting coins to module account: %v", err)) - } - - return nil -} - -// DenomPathFromHash returns the full denomination path prefix from an ibc denom with a hash -// component. -func (k Keeper) DenomPathFromHash(ctx sdk.Context, denom string) (string, error) { - // trim the denomination prefix, by default "ibc/" - hexHash := denom[len(types.DenomPrefix+"/"):] - - hash, err := types.ParseHexHash(hexHash) - if err != nil { - return "", sdkerrors.Wrap(types.ErrInvalidDenomForTransfer, err.Error()) - } - - denomTrace, found := k.GetDenomTrace(ctx, hash) - if !found { - return "", sdkerrors.Wrap(types.ErrTraceNotFound, hexHash) - } - - fullDenomPath := denomTrace.GetFullDenomPath() - return fullDenomPath, nil -} diff --git a/x/ibc/applications/transfer/keeper/relay_model/account.tla b/x/ibc/applications/transfer/keeper/relay_model/account.tla deleted file mode 100644 index 84d743f6da6c..000000000000 --- a/x/ibc/applications/transfer/keeper/relay_model/account.tla +++ /dev/null @@ -1,36 +0,0 @@ --------------------------- MODULE account ---------------------------- - -(** - The accounts interface; please ignore the definition bodies. -*) - -EXTENDS identifiers - -CONSTANT - AccountIds - -\* a non-account -NullAccount == "NullAccount" - -\* All accounts -Accounts == { NullAccount } - -\* Make an escrow account for the given port and channel -MakeEscrowAccount(port, channel) == NullAccount - -\* Make an account from the accound id -MakeAccount(accountId) == NullAccount - -\* Type constraints for accounts -AccountTypeOK == - /\ NullAccount \in Accounts - /\ \A p \in Identifiers, c \in Identifiers: - MakeEscrowAccount(p, c) \in Accounts - /\ \A a \in Identifiers: - MakeAccount(a) \in Accounts - -============================================================================= -\* Modification History -\* Last modified Thu Nov 19 18:21:10 CET 2020 by c -\* Last modified Thu Nov 05 14:44:18 CET 2020 by andrey -\* Created Thu Nov 05 13:22:40 CET 2020 by andrey diff --git a/x/ibc/applications/transfer/keeper/relay_model/account_record.tla b/x/ibc/applications/transfer/keeper/relay_model/account_record.tla deleted file mode 100644 index c7eed27af1b5..000000000000 --- a/x/ibc/applications/transfer/keeper/relay_model/account_record.tla +++ /dev/null @@ -1,46 +0,0 @@ --------------------------- MODULE account_record ---------------------------- - -(** - The most basic implementation of accounts, which is a union of normal and escrow accounts - Represented via records. -*) - -EXTENDS identifiers - -CONSTANT - AccountIds - -NullAccount == [ - port |-> NullId, - channel |-> NullId, - id |-> NullId -] - -Accounts == [ - port: Identifiers, - channel: Identifiers, - id: AccountIds -] - -MakeEscrowAccount(port, channel) == [ - port |-> port, - channel |-> channel, - id |-> NullId -] - -MakeAccount(accountId) == [ - port |-> NullId, - channel |-> NullId, - id |-> accountId -] - - -ACCOUNT == INSTANCE account -AccountTypeOK == ACCOUNT!AccountTypeOK - - -============================================================================= -\* Modification History -\* Last modified Thu Nov 19 18:21:46 CET 2020 by c -\* Last modified Thu Nov 05 14:49:10 CET 2020 by andrey -\* Created Thu Nov 05 13:22:40 CET 2020 by andrey diff --git a/x/ibc/applications/transfer/keeper/relay_model/apalache-to-relay-test.json b/x/ibc/applications/transfer/keeper/relay_model/apalache-to-relay-test.json deleted file mode 100644 index c8d70a333294..000000000000 --- a/x/ibc/applications/transfer/keeper/relay_model/apalache-to-relay-test.json +++ /dev/null @@ -1,100 +0,0 @@ -{ - "description": "Transforms an Apalache counterexample into the test for ICS20 Token Transfer OnRecvPacket", - "usage": "jsonatr --use apalache-to-recv-test.json --in counterexample.json --out recv-test.json", - "input": [ - { - "name": "history", - "description": "extract history from the last state of Apalache CE", - "kind": "INLINE", - "source": "$.declarations[-2].body.and..[?(@.eq == 'history')].arg.atat..arg.record" - }, - { - "name": "bankRecordToBalance", - "description": "", - "kind": "INLINE", - "source": { - "address": [ - "$.colonGreater.tuple[0]..[?(@.key.str == 'port')].value.str | unwrap", - "$.colonGreater.tuple[0]..[?(@.key.str == 'channel')].value.str | unwrap", - "$.colonGreater.tuple[0]..[?(@.key.str == 'id')].value.str | unwrap" - ], - "denom": [ - "$.colonGreater.tuple[1]..[?(@.key.str == 'port')].value.str | unwrap", - "$.colonGreater.tuple[1]..[?(@.key.str == 'channel')].value.str | unwrap", - "$.colonGreater.tuple[1]..[?(@.key.str == 'denom')].value.str | unwrap" - ], - "amount": "$.arg | unwrap" - } - }, - { - "name": "bankBefore", - "description": "extract bankBefore from the history state", - "kind": "INLINE", - "source": "$..[?(@.key.str == 'bankBefore')].value.atat | unwrap | map(bankRecordToBalance)" - }, - { - "name": "bankAfter", - "description": "extract bankAfter from the history state", - "kind": "INLINE", - "source": "$..[?(@.key.str == 'bankAfter')].value.atat | unwrap | map(bankRecordToBalance)" - }, - { - "name": "packet", - "description": "extract packet from the history state", - "kind": "INLINE", - "source": "$..[?(@.key.str == 'packet')].value.record" - }, - { - "name": "packetData", - "description": "extract bankAfter from the history state", - "kind": "INLINE", - "source": "$..[?(@.key.str == 'data')].value.record" - }, - { - "name": "packetDataDenom", - "description": "extract bankAfter from the history state", - "kind": "INLINE", - "source": "$..[?(@.key.str == 'data')].value.record.[?(@.key.str == 'denomTrace')].value.record" - }, - { - "name": "packetRecord", - "description": "decompose packet", - "kind": "INLINE", - "source": { - "sourceChannel" : "$.[?(@.key.str == 'sourceChannel')].value.str | unwrap", - "sourcePort" : "$.[?(@.key.str == 'sourcePort')].value.str | unwrap", - "destChannel" : "$.[?(@.key.str == 'destChannel')].value.str | unwrap", - "destPort" : "$.[?(@.key.str == 'destPort')].value.str | unwrap", - "data": { - "sender": "$packetData.[?(@.key.str == 'sender')].value.str | unwrap", - "receiver": "$packetData.[?(@.key.str == 'receiver')].value.str | unwrap", - "amount": "$packetData.[?(@.key.str == 'amount')].value | unwrap", - "denom": [ - "$packetDataDenom.[?(@.key.str == 'port')].value.str | unwrap", - "$packetDataDenom.[?(@.key.str == 'channel')].value.str | unwrap", - "$packetDataDenom.[?(@.key.str == 'denom')].value.str | unwrap" - ] - } - } - }, - { - "name": "handler", - "description": "extract handler from the history state", - "kind": "INLINE", - "source": "$..[?(@.key.str == 'handler')].value.str" - }, - { - "name": "historyState", - "description": "decompose single history state", - "kind": "INLINE", - "source": { - "packet": "$packet | unwrap | packetRecord", - "handler": "$handler | unwrap", - "bankBefore": "$bankBefore", - "bankAfter": "$bankAfter", - "error": "$..[?(@.key.str == 'error')].value | unwrap" - } - } - ], - "output": "$history[1:] | map(historyState)" -} \ No newline at end of file diff --git a/x/ibc/applications/transfer/keeper/relay_model/apalache-to-relay-test2.json b/x/ibc/applications/transfer/keeper/relay_model/apalache-to-relay-test2.json deleted file mode 100644 index a2c821c4dbab..000000000000 --- a/x/ibc/applications/transfer/keeper/relay_model/apalache-to-relay-test2.json +++ /dev/null @@ -1,104 +0,0 @@ -{ - "description": "Transforms an Apalache counterexample into the test for ICS20 Token Transfer OnRecvPacket", - "usage": "jsonatr --use apalache-to-recv-test.json --in counterexample.json --out recv-test.json", - "input": [ - { - "name": "history", - "description": "extract history from the last state of Apalache CE", - "kind": "INLINE", - "source": "$.declarations[-2].body.and..[?(@.eq == 'history')].arg.atat..arg.record" - }, - { - "name": "bankRecordToBalance", - "description": "", - "kind": "INLINE", - "source": { - "address": [ - "$.colonGreater.tuple[0]..[?(@.key.str == 'port')].value.str | unwrap", - "$.colonGreater.tuple[0]..[?(@.key.str == 'channel')].value.str | unwrap", - "$.colonGreater.tuple[0]..[?(@.key.str == 'id')].value.str | unwrap" - ], - "denom": [ - "$.colonGreater.tuple[1]..[?(@.key.str == 'prefix1')].value..[?(@.key.str == 'port')].value.str | unwrap", - "$.colonGreater.tuple[1]..[?(@.key.str == 'prefix1')].value..[?(@.key.str == 'channel')].value.str | unwrap", - "$.colonGreater.tuple[1]..[?(@.key.str == 'prefix0')].value..[?(@.key.str == 'port')].value.str | unwrap", - "$.colonGreater.tuple[1]..[?(@.key.str == 'prefix0')].value..[?(@.key.str == 'channel')].value.str | unwrap", - "$.colonGreater.tuple[1]..[?(@.key.str == 'denom')].value.str | unwrap" - ], - "amount": "$.arg | unwrap" - } - }, - { - "name": "bankBefore", - "description": "extract bankBefore from the history state", - "kind": "INLINE", - "source": "$..[?(@.key.str == 'bankBefore')].value.atat | unwrap | map(bankRecordToBalance)" - }, - { - "name": "bankAfter", - "description": "extract bankAfter from the history state", - "kind": "INLINE", - "source": "$..[?(@.key.str == 'bankAfter')].value.atat | unwrap | map(bankRecordToBalance)" - }, - { - "name": "packet", - "description": "extract packet from the history state", - "kind": "INLINE", - "source": "$..[?(@.key.str == 'packet')].value.record" - }, - { - "name": "packetData", - "description": "extract bankAfter from the history state", - "kind": "INLINE", - "source": "$..[?(@.key.str == 'data')].value.record" - }, - { - "name": "packetDataDenom", - "description": "extract bankAfter from the history state", - "kind": "INLINE", - "source": "$..[?(@.key.str == 'data')].value.record.[?(@.key.str == 'denomTrace')].value.record" - }, - { - "name": "packetRecord", - "description": "decompose packet", - "kind": "INLINE", - "source": { - "sourceChannel" : "$.[?(@.key.str == 'sourceChannel')].value.str | unwrap", - "sourcePort" : "$.[?(@.key.str == 'sourcePort')].value.str | unwrap", - "destChannel" : "$.[?(@.key.str == 'destChannel')].value.str | unwrap", - "destPort" : "$.[?(@.key.str == 'destPort')].value.str | unwrap", - "data": { - "sender": "$packetData.[?(@.key.str == 'sender')].value.str | unwrap", - "receiver": "$packetData.[?(@.key.str == 'receiver')].value.str | unwrap", - "amount": "$packetData.[?(@.key.str == 'amount')].value | unwrap", - "denom": [ - "$packetDataDenom.[?(@.key.str == 'prefix1')].value..[?(@.key.str == 'port')].value.str | unwrap", - "$packetDataDenom.[?(@.key.str == 'prefix1')].value..[?(@.key.str == 'channel')].value.str | unwrap", - "$packetDataDenom.[?(@.key.str == 'prefix0')].value..[?(@.key.str == 'port')].value.str | unwrap", - "$packetDataDenom.[?(@.key.str == 'prefix0')].value..[?(@.key.str == 'channel')].value.str | unwrap", - "$packetDataDenom.[?(@.key.str == 'denom')].value.str | unwrap" - ] - } - } - }, - { - "name": "handler", - "description": "extract handler from the history state", - "kind": "INLINE", - "source": "$..[?(@.key.str == 'handler')].value.str" - }, - { - "name": "historyState", - "description": "decompose single history state", - "kind": "INLINE", - "source": { - "packet": "$packet | unwrap | packetRecord", - "handler": "$handler | unwrap", - "bankBefore": "$bankBefore", - "bankAfter": "$bankAfter", - "error": "$..[?(@.key.str == 'error')].value | unwrap" - } - } - ], - "output": "$history[1:] | map(historyState)" -} \ No newline at end of file diff --git a/x/ibc/applications/transfer/keeper/relay_model/denom.tla b/x/ibc/applications/transfer/keeper/relay_model/denom.tla deleted file mode 100644 index f729e7e14f41..000000000000 --- a/x/ibc/applications/transfer/keeper/relay_model/denom.tla +++ /dev/null @@ -1,50 +0,0 @@ --------------------------- MODULE denom ---------------------------- - -(** - The denomination traces interface; please ignore the definition bodies. -*) - -EXTENDS identifiers - -CONSTANT - Denoms - -\* A non-account -NullDenomTrace == "NullDenomTrace" - -\* All denomination traces -DenomTraces == {NullDenomTrace} - -\* Make a new denomination trace from the port/channel prefix and the basic denom -MakeDenomTrace(port, channel, denom) == NullDenomTrace - -\* Get the denomination trace port -GetPort(trace) == NullId - -\* Get the denomination trace port -GetChannel(trace) == NullId - -\* Get the denomination trace basic denomination -GetDenom(trace) == NullDenomTrace - -\* Is this denomination trace a native denomination, or is it a prefixed trace -\* Note that those cases are exclusive, but not exhaustive -IsNativeDenomTrace(trace) == GetPort(trace) = NullId /\ GetChannel(trace) = NullId -IsPrefixedDenomTrace(trace) == GetPort(trace) /= NullId /\ GetChannel(trace) /= NullId - -DenomTypeOK == - /\ NullDenomTrace \in DenomTraces - /\ \A p \in Identifiers, c \in Identifiers, d \in Denoms: - MakeDenomTrace(p, c, d) \in DenomTraces - /\ \A t \in DenomTraces: - /\ GetPort(t) \in Identifiers - /\ GetChannel(t) \in Identifiers - /\ GetDenom(t) \in DenomTraces - - - - -============================================================================= -\* Modification History -\* Last modified Thu Nov 05 15:49:23 CET 2020 by andrey -\* Created Thu Nov 05 13:22:40 CET 2020 by andrey diff --git a/x/ibc/applications/transfer/keeper/relay_model/denom_record.tla b/x/ibc/applications/transfer/keeper/relay_model/denom_record.tla deleted file mode 100644 index 2eb0d06f1db8..000000000000 --- a/x/ibc/applications/transfer/keeper/relay_model/denom_record.tla +++ /dev/null @@ -1,53 +0,0 @@ --------------------------- MODULE denom_record ---------------------------- - -(** - The most basic implementation of denomination traces that allows only one-step sequences - Represented via records -*) - -EXTENDS identifiers - -CONSTANT - Denoms - -MaxDenomLength == 3 - -DenomTraces == [ - port: Identifiers, - channel: Identifiers, - denom: Denoms -] - -NullDenomTrace == [ - port |-> NullId, - channel |-> NullId, - denom |-> NullId -] - -GetPort(trace) == trace.port -GetChannel(trace) == trace.channel -GetDenom(trace) == trace.denom - -IsNativeDenomTrace(trace) == GetPort(trace) = NullId /\ GetChannel(trace) = NullId /\ GetDenom(trace) /= NullId -IsPrefixedDenomTrace(trace) == GetPort(trace) /= NullId /\ GetChannel(trace) /= NullId /\ GetDenom(trace) /= NullId - -ExtendDenomTrace(port, channel, trace) == - IF GetPort(trace) = NullId /\ GetChannel(trace) = NullId - THEN - [ - port |-> port, - channel |-> channel, - denom |-> trace.denom - ] - ELSE - NullDenomTrace - - -DENOM == INSTANCE denom -DenomTypeOK == DENOM!DenomTypeOK - - -============================================================================= -\* Modification History -\* Last modified Thu Nov 05 16:41:47 CET 2020 by andrey -\* Created Thu Nov 05 13:22:40 CET 2020 by andrey diff --git a/x/ibc/applications/transfer/keeper/relay_model/denom_record2.tla b/x/ibc/applications/transfer/keeper/relay_model/denom_record2.tla deleted file mode 100644 index a49d6c98de35..000000000000 --- a/x/ibc/applications/transfer/keeper/relay_model/denom_record2.tla +++ /dev/null @@ -1,114 +0,0 @@ --------------------------- MODULE denom_record2 ---------------------------- - -(** - The implementation of denomination traces that allows one- or two-step sequences - Represented via records -*) - -EXTENDS identifiers - -CONSTANT - Denoms - -MaxDenomLength == 5 - -DenomPrefixes == [ - port: Identifiers, - channel: Identifiers -] - -NullDenomPrefix == [ - port |-> NullId, - channel |-> NullId -] - -MakeDenomPrefix(port, channel) == [ - port |-> port, - channel |-> channel -] - -IsValidDenomPrefix(prefix) == - /\ prefix.port /= NullId - /\ prefix.channel /= NullId - -DenomTraces == [ - prefix1: DenomPrefixes, \* the most recent prefix - prefix0: DenomPrefixes, \* the deepest prefix - denom: Denoms -] - -NullDenomTrace == [ - prefix1 |-> NullDenomPrefix, - prefix0 |-> NullDenomPrefix, - denom |-> NullId -] - - -TraceLen(trace) == - IF trace.prefix0 = NullDenomPrefix - THEN 1 - ELSE IF trace.prefix1 = NullDenomPrefix - THEN 3 - ELSE 5 - -LatestPrefix(trace) == - IF trace.prefix0 = NullDenomPrefix - THEN NullDenomPrefix - ELSE IF trace.prefix1 = NullDenomPrefix - THEN trace.prefix0 - ELSE trace.prefix1 - - -ExtendDenomTrace(port, channel, trace) == - IF trace.prefix0 = NullDenomPrefix - THEN [ - prefix1 |-> NullDenomPrefix, - prefix0 |-> MakeDenomPrefix(port, channel), - denom |-> trace.denom - ] - ELSE IF trace.prefix1 = NullDenomPrefix - THEN [ - prefix1 |-> MakeDenomPrefix(port, channel), - prefix0 |-> trace.prefix0, - denom |-> trace.denom - ] - ELSE NullDenomTrace \* can extend only for two steps - -ReduceDenomTrace(trace) == - IF trace.prefix1 /= NullDenomPrefix - THEN [ - prefix1 |-> NullDenomPrefix, - prefix0 |-> trace.prefix0, - denom |-> trace.denom - ] - ELSE IF trace.prefix0 /= NullDenomPrefix - THEN [ - prefix1 |-> NullDenomPrefix, - prefix0 |-> NullDenomPrefix, - denom |-> trace.denom - ] - ELSE NullDenomTrace \* cannot reduce further - -GetPort(trace) == LatestPrefix(trace).port -GetChannel(trace) == LatestPrefix(trace).channel -GetDenom(trace) == trace.denom - -IsValidDenomTrace(trace) == - /\ GetDenom(trace) /= NullId - /\ IF IsValidDenomPrefix(trace.prefix1) - THEN IsValidDenomPrefix(trace.prefix0) - ELSE - /\ trace.prefix1 = NullDenomPrefix - /\ (IsValidDenomPrefix(trace.prefix0) \/ trace.prefix0 = NullDenomPrefix) - -IsNativeDenomTrace(trace) == LatestPrefix(trace) = NullDenomPrefix /\ GetDenom(trace) /= NullId -IsPrefixedDenomTrace(trace) == LatestPrefix(trace) /= NullDenomPrefix /\ GetDenom(trace) /= NullId - -DENOM == INSTANCE denom -DenomTypeOK == DENOM!DenomTypeOK - - -============================================================================= -\* Modification History -\* Last modified Fri Dec 04 10:38:10 CET 2020 by andrey -\* Created Fri Dec 04 10:22:10 CET 2020 by andrey diff --git a/x/ibc/applications/transfer/keeper/relay_model/denom_sequence.tla b/x/ibc/applications/transfer/keeper/relay_model/denom_sequence.tla deleted file mode 100644 index 29b5f4edf288..000000000000 --- a/x/ibc/applications/transfer/keeper/relay_model/denom_sequence.tla +++ /dev/null @@ -1,47 +0,0 @@ --------------------------- MODULE denom_sequence ---------------------------- - -(** - The implementation of denomination traces via sequences -*) - -EXTENDS Integers, Sequences, identifiers - -CONSTANT - Denoms, - MaxDenomLength - - -a <: b == a -AsAddress(seq) == seq <: Seq(STRING) - -UNROLL_DEFAULT_GenSeq == { AsAddress(<< >>) } -UNROLL_TIMES_GenSeq == 5 - -\* This produces denomination sequences up to the given bound -RECURSIVE GenSeq(_) -GenSeq(n) == - IF n = 0 THEN { AsAddress(<< >>) } - ELSE LET Shorter == GenSeq(n-1) IN - { Append(s,x): x \in Identifiers, s \in Shorter } \union Shorter - -DenomTraces == GenSeq(MaxDenomLength) - -ExtendDenomTrace(port, channel, denom) == AsAddress(<>) \o denom - -GetPort(trace) == trace[1] -GetChannel(trace) == trace[2] -GetDenom(trace) == SubSeq(trace, 3, Len(trace)) - -NullDenomTrace == AsAddress(<< >>) - -IsNativeDenomTrace(trace) == GetPort(trace) = NullId /\ GetChannel(trace) = NullId /\ GetDenom(trace) /= NullDenomTrace -IsPrefixedDenomTrace(trace) == GetPort(trace) /= NullId /\ GetChannel(trace) /= NullId /\ GetDenom(trace) /= NullDenomTrace - -DENOM == INSTANCE denom -DenomTypeOK == DENOM!DenomTypeOK - - -============================================================================= -\* Modification History -\* Last modified Thu Nov 05 15:29:21 CET 2020 by andrey -\* Created Thu Nov 05 13:22:40 CET 2020 by andrey diff --git a/x/ibc/applications/transfer/keeper/relay_model/identifiers.tla b/x/ibc/applications/transfer/keeper/relay_model/identifiers.tla deleted file mode 100644 index 089f276d8c08..000000000000 --- a/x/ibc/applications/transfer/keeper/relay_model/identifiers.tla +++ /dev/null @@ -1,10 +0,0 @@ --------------------------- MODULE identifiers ---------------------------- - -CONSTANT - Identifiers, - NullId - -============================================================================= -\* Modification History -\* Last modified Thu Nov 05 13:23:12 CET 2020 by andrey -\* Created Thu Nov 05 13:22:40 CET 2020 by andrey diff --git a/x/ibc/applications/transfer/keeper/relay_model/relay.tla b/x/ibc/applications/transfer/keeper/relay_model/relay.tla deleted file mode 100644 index 029df3d7c7b0..000000000000 --- a/x/ibc/applications/transfer/keeper/relay_model/relay.tla +++ /dev/null @@ -1,278 +0,0 @@ --------------------------- MODULE relay ---------------------------- -(** - * A primitive model for account arithmetics and token movement - * of the Cosmos SDK ICS20 Token Transfer - * We completely abstract away many details, - * and want to focus on a minimal spec useful for testing - * - * We also try to make the model modular in that it uses - * denomination traces and accounts via abstract interfaces, - * outlined in denom.tla and account.tla - *) - -EXTENDS Integers, FiniteSets, Sequences, identifiers, denom_record2, account_record - -CONSTANT - MaxAmount - -VARIABLE - error, - bank, - p, \* we want to start with generating single packets, - handler, - history, - count - -Amounts == 0..MaxAmount - -GetSourceEscrowAccount(packet) == MakeEscrowAccount(packet.sourcePort, packet.sourceChannel) -GetDestEscrowAccount(packet) == MakeEscrowAccount(packet.destPort, packet.destChannel) - -FungibleTokenPacketData == [ - sender: AccountIds, - receiver: AccountIds, - denomTrace: DenomTraces, - amount: Amounts -] - -Packets == [ - \* We abstract those packet fields away - \* sequence: uint64 - \* timeoutHeight: Height - \* timeoutTimestamp: uint64 - sourcePort: Identifiers, - sourceChannel: Identifiers, - destPort: Identifiers, - destChannel: Identifiers, - data: FungibleTokenPacketData -] - - -IsSource(packet) == - /\ GetPort(packet.data.denomTrace) = packet.sourcePort - /\ GetChannel(packet.data.denomTrace) = packet.sourceChannel - -\* This function models the port and channel checks that happen when the packet is sent -IsValidSendChannel(packet) == - /\ packet.sourcePort = "transfer" - /\ (packet.sourceChannel = "channel-0" \/ packet.sourceChannel = "channel-1") - /\ packet.destPort = "transfer" - /\ packet.destChannel = "channel-0" - -\* This function models the port and channel checks that happen when relay gets the packet -IsValidRecvChannel(packet) == - /\ packet.sourcePort = "transfer" - /\ packet.sourceChannel = "channel-0" - /\ packet.destPort = "transfer" - /\ (packet.destChannel = "channel-0" \/ packet.destChannel = "channel-1") - - -WellFormedPacket(packet) == - /\ packet.sourcePort /= NullId - /\ packet.sourceChannel /= NullId - /\ packet.destPort /= NullId - /\ packet.destChannel /= NullId - -BankWithAccount(abank, account, denom) == - IF <> \in DOMAIN abank - THEN abank - ELSE [x \in DOMAIN bank \union { <> } - |-> IF x = <> - THEN 0 - ELSE bank[x] ] - -IsKnownDenomTrace(trace) == - \E account \in Accounts : - <> \in DOMAIN bank - - -SendTransferPre(packet, pbank) == - LET data == packet.data - trace == data.denomTrace - sender == data.sender - amount == data.amount - escrow == GetSourceEscrowAccount(packet) - IN - /\ WellFormedPacket(packet) - /\ IsValidSendChannel(packet) - /\ IsNativeDenomTrace(trace) \/ (IsValidDenomTrace(trace) /\ IsKnownDenomTrace(trace)) - /\ data.sender /= NullId - /\ <> \in DOMAIN pbank - /\ \/ amount = 0 \* SendTrasfer actually allows for 0 amount - \/ <> \in DOMAIN pbank /\ bank[MakeAccount(sender), trace] >= amount - -SendTransferNext(packet) == - LET data == packet.data IN - LET denom == GetDenom(data.denomTrace) IN - LET amount == data.amount IN - LET sender == data.sender IN - LET escrow == GetSourceEscrowAccount(packet) IN - LET bankwithescrow == BankWithAccount(bank, escrow, data.denomTrace) IN - IF SendTransferPre(packet,bankwithescrow) - THEN - /\ error' = FALSE - \*/\ IBCsend(chain, packet) - /\ IF ~IsSource(packet) - \* This is how the check is encoded in ICS20 and the implementation. - \* The meaning is "IF denom = AsAddress(NativeDenom)" because of the following argument: - \* observe that due to the disjunction in SendTransferPre(packet), we have - \* ~IsSource(packet) /\ SendTransferPre(packet) => denom = AsAddress(NativeDenom) - THEN - \* tokens are from this chain - \* transfer tokens from sender into escrow account - bank' = [bankwithescrow EXCEPT ![MakeAccount(sender), data.denomTrace] = @ - amount, - ![escrow, data.denomTrace] = @ + amount] - ELSE - \* tokens are from other chain. We forward them. - \* burn sender's money - bank' = [bankwithescrow EXCEPT ![MakeAccount(sender), data.denomTrace] = @ - amount] - ELSE - /\ error' = TRUE - /\ UNCHANGED bank - - -OnRecvPacketPre(packet) == - LET data == packet.data - trace == data.denomTrace - denom == GetDenom(trace) - amount == data.amount - IN - /\ WellFormedPacket(packet) - /\ IsValidRecvChannel(packet) - /\ IsValidDenomTrace(trace) - /\ amount > 0 - \* if there is no receiver account, it is created by the bank - /\ data.receiver /= NullId - /\ IsSource(packet) => - LET escrow == GetDestEscrowAccount(packet) IN - LET denomTrace == ReduceDenomTrace(trace) IN - /\ <> \in DOMAIN bank - /\ bank[escrow, denomTrace] >= amount - - -OnRecvPacketNext(packet) == - LET data == packet.data IN - LET trace == data.denomTrace IN - LET denom == GetDenom(trace) IN - LET amount == data.amount IN - LET receiver == data.receiver IN - /\ IF OnRecvPacketPre(packet) - THEN - \* This condition is necessary so that denomination traces do not exceed the maximum length - /\ (IsSource(packet) \/ TraceLen(trace) < MaxDenomLength) - /\ error' = FALSE - /\ IF IsSource(packet) - THEN - \* transfer from the escrow account to the receiver account - LET denomTrace == ReduceDenomTrace(trace) IN - LET escrow == GetDestEscrowAccount(packet) IN - LET bankwithreceiver == BankWithAccount(bank, MakeAccount(receiver), denomTrace) IN - bank' = [bankwithreceiver - EXCEPT ![MakeAccount(receiver), denomTrace] = @ + amount, - ![escrow, denomTrace] = @ - amount] - ELSE - \* create new tokens with new denomination and transfer it to the receiver account - LET denomTrace == ExtendDenomTrace(packet.destPort, packet.destChannel, trace) IN - LET bankwithreceiver == - BankWithAccount(bank, MakeAccount(receiver), denomTrace) IN - bank' = [bankwithreceiver - EXCEPT ![MakeAccount(receiver), denomTrace] = @ + amount] - ELSE - /\ error' = TRUE - /\ UNCHANGED bank - - -OnTimeoutPacketPre(packet) == - LET data == packet.data - trace == data.denomTrace - denom == GetDenom(trace) - amount == data.amount - IN - /\ WellFormedPacket(packet) - /\ IsValidSendChannel(packet) - /\ IsValidDenomTrace(trace) - /\ data.sender /= NullId - /\ ~IsSource(packet) => - LET escrow == GetSourceEscrowAccount(packet) - IN /\ <> \in DOMAIN bank - /\ bank[escrow, trace] >= amount - - -OnTimeoutPacketNext(packet) == - LET data == packet.data IN - LET trace == data.denomTrace IN - LET denom == GetDenom(data.denomTrace) IN - LET amount == data.amount IN - LET sender == data.sender IN - LET bankwithsender == BankWithAccount(bank, MakeAccount(sender), trace) IN - IF OnTimeoutPacketPre(packet) - THEN - /\ error' = FALSE - /\ IF ~IsSource(packet) - THEN - \* transfer from the escrow acount to the sender account - \* LET denomsuffix == SubSeq(denom, 3, Len(denom)) IN - LET escrow == GetSourceEscrowAccount(packet) IN - bank' = [bankwithsender - EXCEPT ![MakeAccount(sender), trace] = @ + amount, - ![escrow, trace] = @ - amount] - ELSE - \* mint back the money - bank' = [bankwithsender EXCEPT ![MakeAccount(sender), trace] = @ + amount] - - ELSE - /\ error' = TRUE - /\ UNCHANGED bank - - -OnAcknowledgementPacketResultNext(packet) == - IF WellFormedPacket(packet) - THEN - /\ error' = FALSE - /\ UNCHANGED bank - ELSE - /\ error' = TRUE - /\ UNCHANGED bank - - -OnAcknowledgementPacketErrorNext(packet) == - OnTimeoutPacketNext(packet) - -Init == - /\ p \in Packets - /\ bank = [ x \in {<>} |-> 0 ] - /\ count = 0 - /\ history = [ - n \in {0} |-> [ - error |-> FALSE, - packet |-> p, - handler |-> "", - bankBefore |-> bank, - bankAfter |-> bank - ] - ] - /\ error = FALSE - /\ handler = "" - -Next == - /\ p' \in Packets - /\ count'= count + 1 - /\ - \/ (SendTransferNext(p) /\ handler' = "SendTransfer") - \/ (OnRecvPacketNext(p) /\ handler' = "OnRecvPacket") - \/ (OnTimeoutPacketNext(p) /\ handler' = "OnTimeoutPacket") - \/ (OnAcknowledgementPacketResultNext(p) /\ handler' = "OnRecvAcknowledgementResult") - \/ (OnAcknowledgementPacketErrorNext(p) /\ handler' = "OnRecvAcknowledgementError") - /\ history' = [ n \in DOMAIN history \union {count'} |-> - IF n = count' THEN - [ packet |-> p, handler |-> handler', error |-> error', bankBefore |-> bank, bankAfter |-> bank' ] - ELSE history[n] - ] - -============================================================================= -\* Modification History -\* Last modified Wed Dec 2 10:15:45 CET 2020 by andrey -\* Last modified Fri Nov 20 12:37:38 CET 2020 by c -\* Last modified Thu Nov 05 20:56:37 CET 2020 by andrey -\* Last modified Fri Oct 30 21:52:38 CET 2020 by widder -\* Created Thu Oct 29 20:45:55 CET 2020 by andrey diff --git a/x/ibc/applications/transfer/keeper/relay_model/relay_tests.tla b/x/ibc/applications/transfer/keeper/relay_model/relay_tests.tla deleted file mode 100644 index 7e7577526dc0..000000000000 --- a/x/ibc/applications/transfer/keeper/relay_model/relay_tests.tla +++ /dev/null @@ -1,96 +0,0 @@ --------------------------- MODULE relay_tests ---------------------------- - -EXTENDS Integers, FiniteSets - -Identifiers == {"", "transfer", "channel-0", "channel-1", "cosmos-hub", "ethereum-hub", "bitcoin-hub"} -NullId == "" -MaxAmount == 5 -Denoms == {"", "atom", "eth", "btc" } -AccountIds == {"", "a1", "a2", "a3" } - -VARIABLES error, bank, p, count, history, handler - -INSTANCE relay - -\************************** Tests ****************************** - -\* Generic test for handler pass -TestHandlerPass(handlerName) == - \E s \in DOMAIN history : - /\ history[s].handler = handlerName - /\ history[s].error = FALSE - /\ history[s].packet.data.amount > 0 - -\* Generic test for handler fail -TestHandlerFail(handlerName) == - \E s \in DOMAIN history : - /\ history[s].handler = handlerName - /\ history[s].error = TRUE - /\ history[s].packet.data.amount > 0 - -TestSendTransferPass == TestHandlerPass("SendTransfer") -TestSendTransferPassInv == ~TestSendTransferPass - -TestSendTransferFail == TestHandlerFail("SendTransfer") -TestSendTransferFailInv == ~TestSendTransferFail - -TestOnRecvPacketPass == TestHandlerPass("OnRecvPacket") -TestOnRecvPacketPassInv == ~TestOnRecvPacketPass - -TestOnRecvPacketFail == TestHandlerFail("OnRecvPacket") -TestOnRecvPacketFailInv == ~TestOnRecvPacketFail - -TestOnTimeoutPass == TestHandlerPass("OnTimeoutPacket") -TestOnTimeoutPassInv == ~TestOnTimeoutPass - -TestOnTimeoutFail == TestHandlerFail("OnTimeoutPacket") -TestOnTimeoutFailInv == ~TestOnTimeoutFail - -TestOnRecvAcknowledgementResultPass == TestHandlerPass("OnRecvAcknowledgementResult") -TestOnRecvAcknowledgementResultPassInv == ~TestOnRecvAcknowledgementResultPass - -TestOnRecvAcknowledgementResultFail == TestHandlerFail("OnRecvAcknowledgementResult") -TestOnRecvAcknowledgementResultFailInv == ~TestOnRecvAcknowledgementResultFail - -TestOnRecvAcknowledgementErrorPass == TestHandlerPass("OnRecvAcknowledgementError") -TestOnRecvAcknowledgementErrorPassInv == ~TestOnRecvAcknowledgementErrorPass - -TestOnRecvAcknowledgementErrorFail == TestHandlerFail("OnRecvAcknowledgementError") -TestOnRecvAcknowledgementErrorFailInv == ~TestOnRecvAcknowledgementErrorFail - -Test5Packets == - count >= 5 - -Test5PacketsInv == ~Test5Packets - -Test5Packets2Different == - /\ count >= 5 - /\ \E s1, s2 \in DOMAIN history : - history[s1].handler /= history[s2].handler - -Test5Packets2DifferentInv == ~Test5Packets2Different - -Test5PacketsAllDifferent == - /\ count >= 5 - /\ \A s1, s2 \in DOMAIN history : - s1 /= s2 => history[s1].handler /= history[s2].handler - -Test5PacketsAllDifferentInv == ~Test5PacketsAllDifferent - -Test5PacketsAllDifferentPass == - /\ Test5PacketsAllDifferent - /\ \A s \in DOMAIN history : - s > 0 => - /\ history[s].error = FALSE - /\ history[s].packet.data.amount > 0 - -Test5PacketsAllDifferentPassInv == ~Test5PacketsAllDifferentPass - -TestUnescrowTokens == - \E s \in DOMAIN history : - /\ IsSource(history[s].packet) - /\ history[s].handler = "OnRecvPacket" - /\ history[s].error = FALSE -TestUnescrowTokensInv == ~TestUnescrowTokens - -============================================================================= diff --git a/x/ibc/applications/transfer/keeper/relay_test.go b/x/ibc/applications/transfer/keeper/relay_test.go deleted file mode 100644 index 89058ac2952a..000000000000 --- a/x/ibc/applications/transfer/keeper/relay_test.go +++ /dev/null @@ -1,392 +0,0 @@ -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" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" -) - -// test sending from chainA to chainB using both coin that orignate on -// chainA and coin that orignate on chainB -func (suite *KeeperTestSuite) TestSendTransfer() { - var ( - amount sdk.Coin - channelA, channelB ibctesting.TestChannel - err error - ) - - testCases := []struct { - msg string - malleate func() - sendFromSource bool - expPass bool - }{ - {"successful transfer from source chain", - func() { - _, _, connA, connB := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - channelA, channelB = suite.coordinator.CreateTransferChannels(suite.chainA, suite.chainB, connA, connB, channeltypes.UNORDERED) - amount = sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)) - }, true, true}, - {"successful transfer with coin from counterparty chain", - func() { - // send coin from chainA back to chainB - _, _, connA, connB := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - channelA, channelB = suite.coordinator.CreateTransferChannels(suite.chainA, suite.chainB, connA, connB, channeltypes.UNORDERED) - amount = types.GetTransferCoin(channelA.PortID, channelA.ID, sdk.DefaultBondDenom, 100) - }, false, true}, - {"source channel not found", - func() { - // channel references wrong ID - _, _, connA, connB := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - channelA, channelB = suite.coordinator.CreateTransferChannels(suite.chainA, suite.chainB, connA, connB, channeltypes.UNORDERED) - channelA.ID = ibctesting.InvalidID - amount = sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)) - }, true, false}, - {"next seq send not found", - func() { - _, _, connA, connB := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - channelA = suite.chainA.NextTestChannel(connA, ibctesting.TransferPort) - channelB = suite.chainB.NextTestChannel(connB, ibctesting.TransferPort) - // manually create channel so next seq send is never set - suite.chainA.App.IBCKeeper.ChannelKeeper.SetChannel( - suite.chainA.GetContext(), - channelA.PortID, channelA.ID, - channeltypes.NewChannel(channeltypes.OPEN, channeltypes.ORDERED, channeltypes.NewCounterparty(channelB.PortID, channelB.ID), []string{connA.ID}, ibctesting.DefaultChannelVersion), - ) - suite.chainA.CreateChannelCapability(channelA.PortID, channelA.ID) - amount = sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)) - }, true, false}, - - // createOutgoingPacket tests - // - source chain - {"send coin failed", - func() { - _, _, connA, connB := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - channelA, channelB = suite.coordinator.CreateTransferChannels(suite.chainA, suite.chainB, connA, connB, channeltypes.UNORDERED) - amount = sdk.NewCoin("randomdenom", sdk.NewInt(100)) - }, true, false}, - // - receiving chain - {"send from module account failed", - func() { - _, _, connA, connB := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - channelA, channelB = suite.coordinator.CreateTransferChannels(suite.chainA, suite.chainB, connA, connB, channeltypes.UNORDERED) - amount = types.GetTransferCoin(channelA.PortID, channelA.ID, " randomdenom", 100) - }, false, false}, - {"channel capability not found", - func() { - _, _, connA, connB := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - channelA, channelB = suite.coordinator.CreateTransferChannels(suite.chainA, suite.chainB, connA, connB, channeltypes.UNORDERED) - cap := suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - - // Release channel capability - suite.chainA.App.ScopedTransferKeeper.ReleaseCapability(suite.chainA.GetContext(), cap) - amount = sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)) - }, true, false}, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { - suite.SetupTest() // reset - - tc.malleate() - - if !tc.sendFromSource { - // send coin from chainB to chainA - coinFromBToA := sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)) - transferMsg := types.NewMsgTransfer(channelB.PortID, channelB.ID, coinFromBToA, suite.chainB.SenderAccount.GetAddress(), suite.chainA.SenderAccount.GetAddress().String(), clienttypes.NewHeight(0, 110), 0) - err = suite.coordinator.SendMsg(suite.chainB, suite.chainA, channelA.ClientID, transferMsg) - suite.Require().NoError(err) // message committed - - // receive coin on chainA from chainB - fungibleTokenPacket := types.NewFungibleTokenPacketData(coinFromBToA.Denom, coinFromBToA.Amount.Uint64(), suite.chainB.SenderAccount.GetAddress().String(), suite.chainA.SenderAccount.GetAddress().String()) - packet := channeltypes.NewPacket(fungibleTokenPacket.GetBytes(), 1, channelB.PortID, channelB.ID, channelA.PortID, channelA.ID, clienttypes.NewHeight(0, 110), 0) - - // get proof of packet commitment from chainB - packetKey := host.PacketCommitmentKey(packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) - proof, proofHeight := suite.chainB.QueryProof(packetKey) - - recvMsg := channeltypes.NewMsgRecvPacket(packet, proof, proofHeight, suite.chainA.SenderAccount.GetAddress()) - err = suite.coordinator.SendMsg(suite.chainA, suite.chainB, channelB.ClientID, recvMsg) - suite.Require().NoError(err) // message committed - } - - err = suite.chainA.App.TransferKeeper.SendTransfer( - suite.chainA.GetContext(), channelA.PortID, channelA.ID, amount, - suite.chainA.SenderAccount.GetAddress(), suite.chainB.SenderAccount.GetAddress().String(), clienttypes.NewHeight(0, 110), 0, - ) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} - -// test receiving coin on chainB with coin that orignate on chainA and -// coin that orignated on chainB (source). The bulk of the testing occurs -// in the test case for loop since setup is intensive for all cases. The -// malleate function allows for testing invalid cases. -func (suite *KeeperTestSuite) TestOnRecvPacket() { - var ( - channelA, channelB ibctesting.TestChannel - trace types.DenomTrace - amount sdk.Int - receiver string - ) - - testCases := []struct { - msg string - malleate func() - recvIsSource bool // the receiving chain is the source of the coin originally - expPass bool - }{ - {"success receive on source chain", func() {}, true, true}, - {"success receive with coin from another chain as source", func() {}, false, true}, - {"empty coin", func() { - trace = types.DenomTrace{} - amount = sdk.ZeroInt() - }, true, false}, - {"invalid receiver address", func() { - receiver = "gaia1scqhwpgsmr6vmztaa7suurfl52my6nd2kmrudl" - }, true, false}, - - // onRecvPacket - // - coin from chain chainA - {"failure: mint zero coin", func() { - amount = sdk.ZeroInt() - }, false, false}, - - // - coin being sent back to original chain (chainB) - {"tries to unescrow more tokens than allowed", func() { - amount = sdk.NewInt(1000000) - }, true, false}, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { - suite.SetupTest() // reset - - clientA, clientB, connA, connB := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - channelA, channelB = suite.coordinator.CreateTransferChannels(suite.chainA, suite.chainB, connA, connB, channeltypes.UNORDERED) - receiver = suite.chainB.SenderAccount.GetAddress().String() // must be explicitly changed in malleate - - amount = sdk.NewInt(100) // must be explicitly changed in malleate - seq := uint64(1) - - if tc.recvIsSource { - // send coin from chainB to chainA, receive them, acknowledge them, and send back to chainB - coinFromBToA := sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)) - transferMsg := types.NewMsgTransfer(channelB.PortID, channelB.ID, coinFromBToA, suite.chainB.SenderAccount.GetAddress(), suite.chainA.SenderAccount.GetAddress().String(), clienttypes.NewHeight(0, 110), 0) - err := suite.coordinator.SendMsg(suite.chainB, suite.chainA, channelA.ClientID, transferMsg) - suite.Require().NoError(err) // message committed - - // relay send packet - fungibleTokenPacket := types.NewFungibleTokenPacketData(coinFromBToA.Denom, coinFromBToA.Amount.Uint64(), suite.chainB.SenderAccount.GetAddress().String(), suite.chainA.SenderAccount.GetAddress().String()) - packet := channeltypes.NewPacket(fungibleTokenPacket.GetBytes(), 1, channelB.PortID, channelB.ID, channelA.PortID, channelA.ID, clienttypes.NewHeight(0, 110), 0) - ack := channeltypes.NewResultAcknowledgement([]byte{byte(1)}) - err = suite.coordinator.RelayPacket(suite.chainB, suite.chainA, clientB, clientA, packet, ack.GetBytes()) - suite.Require().NoError(err) // relay committed - - seq++ - - // NOTE: trace must be explicitly changed in malleate to test invalid cases - trace = types.ParseDenomTrace(types.GetPrefixedDenom(channelA.PortID, channelA.ID, sdk.DefaultBondDenom)) - } else { - trace = types.ParseDenomTrace(sdk.DefaultBondDenom) - } - - // send coin from chainA to chainB - transferMsg := types.NewMsgTransfer(channelA.PortID, channelA.ID, sdk.NewCoin(trace.IBCDenom(), amount), suite.chainA.SenderAccount.GetAddress(), receiver, clienttypes.NewHeight(0, 110), 0) - err := suite.coordinator.SendMsg(suite.chainA, suite.chainB, channelB.ClientID, transferMsg) - suite.Require().NoError(err) // message committed - - tc.malleate() - - data := types.NewFungibleTokenPacketData(trace.GetFullDenomPath(), amount.Uint64(), suite.chainA.SenderAccount.GetAddress().String(), receiver) - packet := channeltypes.NewPacket(data.GetBytes(), seq, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, clienttypes.NewHeight(0, 100), 0) - - err = suite.chainB.App.TransferKeeper.OnRecvPacket(suite.chainB.GetContext(), packet, data) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} - -// TestOnAcknowledgementPacket tests that successful acknowledgement is a no-op -// and failure acknowledment leads to refund when attempting to send from chainA -// to chainB. If sender is source than the denomination being refunded has no -// trace. -func (suite *KeeperTestSuite) TestOnAcknowledgementPacket() { - var ( - successAck = channeltypes.NewResultAcknowledgement([]byte{byte(1)}) - failedAck = channeltypes.NewErrorAcknowledgement("failed packet transfer") - - channelA, channelB ibctesting.TestChannel - trace types.DenomTrace - amount sdk.Int - ) - - testCases := []struct { - msg string - ack channeltypes.Acknowledgement - malleate func() - success bool // success of ack - expPass bool - }{ - {"success ack causes no-op", successAck, func() { - trace = types.ParseDenomTrace(types.GetPrefixedDenom(channelB.PortID, channelB.ID, sdk.DefaultBondDenom)) - }, true, true}, - {"successful refund from source chain", failedAck, func() { - escrow := types.GetEscrowAddress(channelA.PortID, channelA.ID) - trace = types.ParseDenomTrace(sdk.DefaultBondDenom) - coin := sdk.NewCoin(sdk.DefaultBondDenom, amount) - - suite.Require().NoError(simapp.FundAccount(suite.chainA.App, suite.chainA.GetContext(), escrow, sdk.NewCoins(coin))) - }, false, true}, - {"unsuccessful refund from source", failedAck, - func() { - trace = types.ParseDenomTrace(sdk.DefaultBondDenom) - }, false, false}, - {"successful refund from with coin from external chain", failedAck, - func() { - escrow := types.GetEscrowAddress(channelA.PortID, channelA.ID) - trace = types.ParseDenomTrace(types.GetPrefixedDenom(channelA.PortID, channelA.ID, sdk.DefaultBondDenom)) - coin := sdk.NewCoin(trace.IBCDenom(), amount) - - suite.Require().NoError(simapp.FundAccount(suite.chainA.App, suite.chainA.GetContext(), escrow, sdk.NewCoins(coin))) - }, false, true}, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { - suite.SetupTest() // reset - _, _, _, _, channelA, channelB = suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.UNORDERED) - amount = sdk.NewInt(100) // must be explicitly changed - - tc.malleate() - - data := types.NewFungibleTokenPacketData(trace.GetFullDenomPath(), amount.Uint64(), suite.chainA.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String()) - packet := channeltypes.NewPacket(data.GetBytes(), 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, clienttypes.NewHeight(0, 100), 0) - - preCoin := suite.chainA.App.BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), trace.IBCDenom()) - - err := suite.chainA.App.TransferKeeper.OnAcknowledgementPacket(suite.chainA.GetContext(), packet, data, tc.ack) - if tc.expPass { - suite.Require().NoError(err) - postCoin := suite.chainA.App.BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), trace.IBCDenom()) - deltaAmount := postCoin.Amount.Sub(preCoin.Amount) - - if tc.success { - suite.Require().Equal(int64(0), deltaAmount.Int64(), "successful ack changed balance") - } else { - suite.Require().Equal(amount, deltaAmount, "failed ack did not trigger refund") - } - - } else { - suite.Require().Error(err) - } - }) - } -} - -// TestOnTimeoutPacket test private refundPacket function since it is a simple -// wrapper over it. The actual timeout does not matter since IBC core logic -// is not being tested. The test is timing out a send from chainA to chainB -// so the refunds are occurring on chainA. -func (suite *KeeperTestSuite) TestOnTimeoutPacket() { - var ( - channelA, channelB ibctesting.TestChannel - trace types.DenomTrace - amount sdk.Int - sender string - ) - - testCases := []struct { - msg string - malleate func() - expPass bool - }{ - {"successful timeout from sender as source chain", - func() { - escrow := types.GetEscrowAddress(channelA.PortID, channelA.ID) - trace = types.ParseDenomTrace(sdk.DefaultBondDenom) - coin := sdk.NewCoin(trace.IBCDenom(), amount) - - suite.Require().NoError(simapp.FundAccount(suite.chainA.App, suite.chainA.GetContext(), escrow, sdk.NewCoins(coin))) - }, true}, - {"successful timeout from external chain", - func() { - escrow := types.GetEscrowAddress(channelA.PortID, channelA.ID) - trace = types.ParseDenomTrace(types.GetPrefixedDenom(channelA.PortID, channelA.ID, sdk.DefaultBondDenom)) - coin := sdk.NewCoin(trace.IBCDenom(), amount) - - suite.Require().NoError(simapp.FundAccount(suite.chainA.App, suite.chainA.GetContext(), escrow, sdk.NewCoins(coin))) - }, true}, - {"no balance for coin denom", - func() { - trace = types.ParseDenomTrace("bitcoin") - }, false}, - {"unescrow failed", - func() { - trace = types.ParseDenomTrace(sdk.DefaultBondDenom) - }, false}, - {"mint failed", - func() { - trace = types.ParseDenomTrace(types.GetPrefixedDenom(channelA.PortID, channelA.ID, sdk.DefaultBondDenom)) - amount = sdk.OneInt() - sender = "invalid address" - }, false}, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { - suite.SetupTest() // reset - - _, _, connA, connB := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - channelA, channelB = suite.coordinator.CreateTransferChannels(suite.chainA, suite.chainB, connA, connB, channeltypes.UNORDERED) - amount = sdk.NewInt(100) // must be explicitly changed - sender = suite.chainA.SenderAccount.GetAddress().String() - - tc.malleate() - - data := types.NewFungibleTokenPacketData(trace.GetFullDenomPath(), amount.Uint64(), sender, suite.chainB.SenderAccount.GetAddress().String()) - packet := channeltypes.NewPacket(data.GetBytes(), 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, clienttypes.NewHeight(0, 100), 0) - - preCoin := suite.chainA.App.BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), trace.IBCDenom()) - - err := suite.chainA.App.TransferKeeper.OnTimeoutPacket(suite.chainA.GetContext(), packet, data) - - postCoin := suite.chainA.App.BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), trace.IBCDenom()) - deltaAmount := postCoin.Amount.Sub(preCoin.Amount) - - if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(amount.Int64(), deltaAmount.Int64(), "successful timeout did not trigger refund") - } else { - suite.Require().Error(err) - } - }) - } -} diff --git a/x/ibc/applications/transfer/module.go b/x/ibc/applications/transfer/module.go deleted file mode 100644 index b93253ad7a8c..000000000000 --- a/x/ibc/applications/transfer/module.go +++ /dev/null @@ -1,434 +0,0 @@ -package transfer - -import ( - "context" - "encoding/json" - "fmt" - "math" - "math/rand" - - "github.com/grpc-ecosystem/grpc-gateway/runtime" - - "github.com/gorilla/mux" - "github.com/spf13/cobra" - - abci "github.com/tendermint/tendermint/abci/types" - - "github.com/cosmos/cosmos-sdk/client" - "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/types/module" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" - "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/client/cli" - "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/keeper" - "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/simulation" - "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - porttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/05-port/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" -) - -var ( - _ module.AppModule = AppModule{} - _ porttypes.IBCModule = AppModule{} - _ module.AppModuleBasic = AppModuleBasic{} -) - -// AppModuleBasic is the IBC Transfer AppModuleBasic -type AppModuleBasic struct{} - -// Name implements AppModuleBasic interface -func (AppModuleBasic) Name() string { - return types.ModuleName -} - -// RegisterLegacyAminoCodec implements AppModuleBasic interface -func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { - types.RegisterLegacyAminoCodec(cdc) -} - -// RegisterInterfaces registers module concrete types into protobuf Any. -func (AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) { - types.RegisterInterfaces(registry) -} - -// DefaultGenesis returns default genesis state as raw bytes for the ibc -// transfer module. -func (AppModuleBasic) DefaultGenesis(cdc codec.JSONMarshaler) json.RawMessage { - return cdc.MustMarshalJSON(types.DefaultGenesisState()) -} - -// ValidateGenesis performs genesis state validation for the ibc transfer module. -func (AppModuleBasic) ValidateGenesis(cdc codec.JSONMarshaler, config client.TxEncodingConfig, bz json.RawMessage) error { - var gs types.GenesisState - if err := cdc.UnmarshalJSON(bz, &gs); err != nil { - return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err) - } - - return gs.Validate() -} - -// RegisterRESTRoutes implements AppModuleBasic interface -func (AppModuleBasic) RegisterRESTRoutes(clientCtx client.Context, rtr *mux.Router) { -} - -// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the ibc-transfer module. -func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) { - types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)) -} - -// GetTxCmd implements AppModuleBasic interface -func (AppModuleBasic) GetTxCmd() *cobra.Command { - return cli.NewTxCmd() -} - -// GetQueryCmd implements AppModuleBasic interface -func (AppModuleBasic) GetQueryCmd() *cobra.Command { - return cli.GetQueryCmd() -} - -// AppModule represents the AppModule for this module -type AppModule struct { - AppModuleBasic - keeper keeper.Keeper -} - -// NewAppModule creates a new 20-transfer module -func NewAppModule(k keeper.Keeper) AppModule { - return AppModule{ - keeper: k, - } -} - -// RegisterInvariants implements the AppModule interface -func (AppModule) RegisterInvariants(ir sdk.InvariantRegistry) { - // TODO -} - -// Route implements the AppModule interface -func (am AppModule) Route() sdk.Route { - return sdk.NewRoute(types.RouterKey, NewHandler(am.keeper)) -} - -// QuerierRoute implements the AppModule interface -func (AppModule) QuerierRoute() string { - return types.QuerierRoute -} - -// LegacyQuerierHandler implements the AppModule interface -func (am AppModule) LegacyQuerierHandler(*codec.LegacyAmino) sdk.Querier { - return nil -} - -// RegisterServices registers module services. -func (am AppModule) RegisterServices(cfg module.Configurator) { - types.RegisterMsgServer(cfg.MsgServer(), am.keeper) - types.RegisterQueryServer(cfg.QueryServer(), am.keeper) -} - -// InitGenesis performs genesis initialization for the ibc-transfer 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) - am.keeper.InitGenesis(ctx, genesisState) - return []abci.ValidatorUpdate{} -} - -// ExportGenesis returns the exported genesis state as raw bytes for the ibc-transfer -// module. -func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json.RawMessage { - gs := am.keeper.ExportGenesis(ctx) - 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) { -} - -// EndBlock implements the AppModule interface -func (am AppModule) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) []abci.ValidatorUpdate { - return []abci.ValidatorUpdate{} -} - -// AppModuleSimulation functions - -// GenerateGenesisState creates a randomized GenState of the transfer module. -func (AppModule) GenerateGenesisState(simState *module.SimulationState) { - simulation.RandomizedGenState(simState) -} - -// ProposalContents doesn't return any content functions for governance proposals. -func (AppModule) ProposalContents(_ module.SimulationState) []simtypes.WeightedProposalContent { - return nil -} - -// RandomizedParams creates randomized ibc-transfer param changes for the simulator. -func (AppModule) RandomizedParams(r *rand.Rand) []simtypes.ParamChange { - return simulation.ParamChanges(r) -} - -// RegisterStoreDecoder registers a decoder for transfer module's types -func (am AppModule) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) { - sdr[types.StoreKey] = simulation.NewDecodeStore(am.keeper) -} - -// WeightedOperations returns the all the transfer module operations with their respective weights. -func (am AppModule) WeightedOperations(_ module.SimulationState) []simtypes.WeightedOperation { - return nil -} - -// ValidateTransferChannelParams does validation of a newly created transfer channel. A transfer -// channel must be UNORDERED, use the correct port (by default 'transfer'), and use the current -// supported version. Only 2^32 channels are allowed to be created. -func ValidateTransferChannelParams( - ctx sdk.Context, - keeper keeper.Keeper, - order channeltypes.Order, - portID string, - channelID string, - version string, -) error { - // NOTE: for escrow address security only 2^32 channels are allowed to be created - // Issue: https://github.com/cosmos/cosmos-sdk/issues/7737 - channelSequence, err := channeltypes.ParseChannelSequence(channelID) - if err != nil { - return err - } - 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) - } - - // Require portID is the portID transfer module is bound to - boundPort := keeper.GetPort(ctx) - if boundPort != portID { - return sdkerrors.Wrapf(porttypes.ErrInvalidPort, "invalid port: %s, expected %s", portID, boundPort) - } - - if version != types.Version { - return sdkerrors.Wrapf(types.ErrInvalidVersion, "got %s, expected %s", version, types.Version) - } - return nil -} - -// OnChanOpenInit implements the IBCModule interface -func (am AppModule) OnChanOpenInit( - ctx sdk.Context, - order channeltypes.Order, - connectionHops []string, - portID string, - channelID string, - chanCap *capabilitytypes.Capability, - counterparty channeltypes.Counterparty, - version string, -) error { - if err := ValidateTransferChannelParams(ctx, am.keeper, order, portID, channelID, version); err != nil { - return err - } - - // Claim channel capability passed back by IBC module - if err := am.keeper.ClaimCapability(ctx, chanCap, host.ChannelCapabilityPath(portID, channelID)); err != nil { - return err - } - - return nil -} - -// OnChanOpenTry implements the IBCModule interface -func (am AppModule) OnChanOpenTry( - ctx sdk.Context, - order channeltypes.Order, - connectionHops []string, - portID, - channelID string, - chanCap *capabilitytypes.Capability, - counterparty channeltypes.Counterparty, - version, - counterpartyVersion string, -) error { - if err := ValidateTransferChannelParams(ctx, am.keeper, order, portID, channelID, version); err != nil { - return err - } - - if counterpartyVersion != types.Version { - return sdkerrors.Wrapf(types.ErrInvalidVersion, "invalid counterparty version: got: %s, expected %s", counterpartyVersion, types.Version) - } - - // Module may have already claimed capability in OnChanOpenInit in the case of crossing hellos - // (ie chainA and chainB both call ChanOpenInit before one of them calls ChanOpenTry) - // If module can already authenticate the capability then module already owns it so we don't need to claim - // Otherwise, module does not have channel capability and we must claim it from IBC - if !am.keeper.AuthenticateCapability(ctx, chanCap, host.ChannelCapabilityPath(portID, channelID)) { - // Only claim channel capability passed back by IBC module if we do not already own it - if err := am.keeper.ClaimCapability(ctx, chanCap, host.ChannelCapabilityPath(portID, channelID)); err != nil { - return err - } - } - - return nil -} - -// OnChanOpenAck implements the IBCModule interface -func (am AppModule) OnChanOpenAck( - ctx sdk.Context, - portID, - channelID string, - counterpartyVersion string, -) error { - if counterpartyVersion != types.Version { - return sdkerrors.Wrapf(types.ErrInvalidVersion, "invalid counterparty version: %s, expected %s", counterpartyVersion, types.Version) - } - return nil -} - -// OnChanOpenConfirm implements the IBCModule interface -func (am AppModule) OnChanOpenConfirm( - ctx sdk.Context, - portID, - channelID string, -) error { - return nil -} - -// OnChanCloseInit implements the IBCModule interface -func (am AppModule) OnChanCloseInit( - ctx sdk.Context, - portID, - channelID string, -) error { - // Disallow user-initiated channel closing for transfer channels - return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "user cannot close channel") -} - -// OnChanCloseConfirm implements the IBCModule interface -func (am AppModule) OnChanCloseConfirm( - ctx sdk.Context, - portID, - channelID string, -) error { - return nil -} - -// OnRecvPacket implements the IBCModule interface -func (am AppModule) OnRecvPacket( - ctx sdk.Context, - packet channeltypes.Packet, -) (*sdk.Result, []byte, error) { - var data types.FungibleTokenPacketData - if err := types.ModuleCdc.UnmarshalJSON(packet.GetData(), &data); err != nil { - return nil, nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "cannot unmarshal ICS-20 transfer packet data: %s", err.Error()) - } - - acknowledgement := channeltypes.NewResultAcknowledgement([]byte{byte(1)}) - - err := am.keeper.OnRecvPacket(ctx, packet, data) - if err != nil { - acknowledgement = channeltypes.NewErrorAcknowledgement(err.Error()) - } - - ctx.EventManager().EmitEvent( - sdk.NewEvent( - types.EventTypePacket, - sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), - sdk.NewAttribute(types.AttributeKeyReceiver, data.Receiver), - sdk.NewAttribute(types.AttributeKeyDenom, data.Denom), - sdk.NewAttribute(types.AttributeKeyAmount, fmt.Sprintf("%d", data.Amount)), - sdk.NewAttribute(types.AttributeKeyAckSuccess, fmt.Sprintf("%t", err != nil)), - ), - ) - - // NOTE: acknowledgement will be written synchronously during IBC handler execution. - return &sdk.Result{ - Events: ctx.EventManager().Events().ToABCIEvents(), - }, acknowledgement.GetBytes(), nil -} - -// OnAcknowledgementPacket implements the IBCModule interface -func (am AppModule) OnAcknowledgementPacket( - ctx sdk.Context, - packet channeltypes.Packet, - acknowledgement []byte, -) (*sdk.Result, error) { - var ack channeltypes.Acknowledgement - if err := types.ModuleCdc.UnmarshalJSON(acknowledgement, &ack); err != nil { - return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "cannot unmarshal ICS-20 transfer packet acknowledgement: %v", err) - } - var data types.FungibleTokenPacketData - if err := types.ModuleCdc.UnmarshalJSON(packet.GetData(), &data); err != nil { - return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "cannot unmarshal ICS-20 transfer packet data: %s", err.Error()) - } - - if err := am.keeper.OnAcknowledgementPacket(ctx, packet, data, ack); err != nil { - return nil, err - } - - ctx.EventManager().EmitEvent( - sdk.NewEvent( - types.EventTypePacket, - sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), - 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, ack.String()), - ), - ) - - switch resp := ack.Response.(type) { - case *channeltypes.Acknowledgement_Result: - ctx.EventManager().EmitEvent( - sdk.NewEvent( - types.EventTypePacket, - sdk.NewAttribute(types.AttributeKeyAckSuccess, string(resp.Result)), - ), - ) - case *channeltypes.Acknowledgement_Error: - ctx.EventManager().EmitEvent( - sdk.NewEvent( - types.EventTypePacket, - sdk.NewAttribute(types.AttributeKeyAckError, resp.Error), - ), - ) - } - - return &sdk.Result{ - Events: ctx.EventManager().Events().ToABCIEvents(), - }, nil -} - -// OnTimeoutPacket implements the IBCModule interface -func (am AppModule) OnTimeoutPacket( - ctx sdk.Context, - packet channeltypes.Packet, -) (*sdk.Result, error) { - var data types.FungibleTokenPacketData - if err := types.ModuleCdc.UnmarshalJSON(packet.GetData(), &data); err != nil { - return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "cannot unmarshal ICS-20 transfer packet data: %s", err.Error()) - } - // refund tokens - if err := am.keeper.OnTimeoutPacket(ctx, packet, data); err != nil { - return nil, err - } - - ctx.EventManager().EmitEvent( - sdk.NewEvent( - types.EventTypeTimeout, - sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName), - sdk.NewAttribute(types.AttributeKeyRefundReceiver, data.Sender), - sdk.NewAttribute(types.AttributeKeyRefundDenom, data.Denom), - sdk.NewAttribute(types.AttributeKeyRefundAmount, fmt.Sprintf("%d", data.Amount)), - ), - ) - - return &sdk.Result{ - Events: ctx.EventManager().Events().ToABCIEvents(), - }, nil -} diff --git a/x/ibc/applications/transfer/module_test.go b/x/ibc/applications/transfer/module_test.go deleted file mode 100644 index d2acfb404311..000000000000 --- a/x/ibc/applications/transfer/module_test.go +++ /dev/null @@ -1,246 +0,0 @@ -package transfer_test - -import ( - "math" - - capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" - "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" -) - -func (suite *TransferTestSuite) TestOnChanOpenInit() { - var ( - channel *channeltypes.Channel - testChannel ibctesting.TestChannel - connA *ibctesting.TestConnection - chanCap *capabilitytypes.Capability - ) - - testCases := []struct { - name string - malleate func() - expPass bool - }{ - - { - "success", func() {}, true, - }, - { - "max channels reached", func() { - testChannel.ID = channeltypes.FormatChannelIdentifier(math.MaxUint32 + 1) - }, false, - }, - { - "invalid order - ORDERED", func() { - channel.Ordering = channeltypes.ORDERED - }, false, - }, - { - "invalid port ID", func() { - testChannel = suite.chainA.NextTestChannel(connA, ibctesting.MockPort) - }, false, - }, - { - "invalid version", func() { - channel.Version = "version" - }, false, - }, - { - "capability already claimed", func() { - err := suite.chainA.App.ScopedTransferKeeper.ClaimCapability(suite.chainA.GetContext(), chanCap, host.ChannelCapabilityPath(testChannel.PortID, testChannel.ID)) - suite.Require().NoError(err) - }, false, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - suite.SetupTest() // reset - - _, _, connA, _ = suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - testChannel = suite.chainA.NextTestChannel(connA, ibctesting.TransferPort) - counterparty := channeltypes.NewCounterparty(testChannel.PortID, testChannel.ID) - channel = &channeltypes.Channel{ - State: channeltypes.INIT, - Ordering: channeltypes.UNORDERED, - Counterparty: counterparty, - ConnectionHops: []string{connA.ID}, - Version: types.Version, - } - - module, _, err := suite.chainA.App.IBCKeeper.PortKeeper.LookupModuleByPort(suite.chainA.GetContext(), ibctesting.TransferPort) - suite.Require().NoError(err) - - chanCap, err = suite.chainA.App.ScopedIBCKeeper.NewCapability(suite.chainA.GetContext(), host.ChannelCapabilityPath(ibctesting.TransferPort, testChannel.ID)) - suite.Require().NoError(err) - - cbs, ok := suite.chainA.App.IBCKeeper.Router.GetRoute(module) - suite.Require().True(ok) - - tc.malleate() // explicitly change fields in channel and testChannel - - err = cbs.OnChanOpenInit(suite.chainA.GetContext(), channel.Ordering, channel.GetConnectionHops(), - testChannel.PortID, testChannel.ID, chanCap, channel.Counterparty, channel.GetVersion(), - ) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - - }) - } -} - -func (suite *TransferTestSuite) TestOnChanOpenTry() { - var ( - channel *channeltypes.Channel - testChannel ibctesting.TestChannel - connA *ibctesting.TestConnection - chanCap *capabilitytypes.Capability - counterpartyVersion string - ) - - testCases := []struct { - name string - malleate func() - expPass bool - }{ - - { - "success", func() {}, true, - }, - { - "max channels reached", func() { - testChannel.ID = channeltypes.FormatChannelIdentifier(math.MaxUint32 + 1) - }, false, - }, - { - "capability already claimed in INIT should pass", func() { - err := suite.chainA.App.ScopedTransferKeeper.ClaimCapability(suite.chainA.GetContext(), chanCap, host.ChannelCapabilityPath(testChannel.PortID, testChannel.ID)) - suite.Require().NoError(err) - }, true, - }, - { - "invalid order - ORDERED", func() { - channel.Ordering = channeltypes.ORDERED - }, false, - }, - { - "invalid port ID", func() { - testChannel = suite.chainA.NextTestChannel(connA, ibctesting.MockPort) - }, false, - }, - { - "invalid version", func() { - channel.Version = "version" - }, false, - }, - { - "invalid counterparty version", func() { - counterpartyVersion = "version" - }, false, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - suite.SetupTest() // reset - - _, _, connA, _ = suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - testChannel = suite.chainA.NextTestChannel(connA, ibctesting.TransferPort) - counterparty := channeltypes.NewCounterparty(testChannel.PortID, testChannel.ID) - channel = &channeltypes.Channel{ - State: channeltypes.TRYOPEN, - Ordering: channeltypes.UNORDERED, - Counterparty: counterparty, - ConnectionHops: []string{connA.ID}, - Version: types.Version, - } - counterpartyVersion = types.Version - - module, _, err := suite.chainA.App.IBCKeeper.PortKeeper.LookupModuleByPort(suite.chainA.GetContext(), ibctesting.TransferPort) - suite.Require().NoError(err) - - chanCap, err = suite.chainA.App.ScopedIBCKeeper.NewCapability(suite.chainA.GetContext(), host.ChannelCapabilityPath(ibctesting.TransferPort, testChannel.ID)) - suite.Require().NoError(err) - - cbs, ok := suite.chainA.App.IBCKeeper.Router.GetRoute(module) - suite.Require().True(ok) - - tc.malleate() // explicitly change fields in channel and testChannel - - err = cbs.OnChanOpenTry(suite.chainA.GetContext(), channel.Ordering, channel.GetConnectionHops(), - testChannel.PortID, testChannel.ID, chanCap, channel.Counterparty, channel.GetVersion(), counterpartyVersion, - ) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - - }) - } -} - -func (suite *TransferTestSuite) TestOnChanOpenAck() { - var ( - testChannel ibctesting.TestChannel - connA *ibctesting.TestConnection - counterpartyVersion string - ) - - testCases := []struct { - name string - malleate func() - expPass bool - }{ - - { - "success", func() {}, true, - }, - { - "invalid counterparty version", func() { - counterpartyVersion = "version" - }, false, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - suite.SetupTest() // reset - - _, _, connA, _ = suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - testChannel = suite.chainA.NextTestChannel(connA, ibctesting.TransferPort) - counterpartyVersion = types.Version - - module, _, err := suite.chainA.App.IBCKeeper.PortKeeper.LookupModuleByPort(suite.chainA.GetContext(), ibctesting.TransferPort) - suite.Require().NoError(err) - - cbs, ok := suite.chainA.App.IBCKeeper.Router.GetRoute(module) - suite.Require().True(ok) - - tc.malleate() // explicitly change fields in channel and testChannel - - err = cbs.OnChanOpenAck(suite.chainA.GetContext(), testChannel.PortID, testChannel.ID, counterpartyVersion) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - - }) - } -} diff --git a/x/ibc/applications/transfer/simulation/decoder.go b/x/ibc/applications/transfer/simulation/decoder.go deleted file mode 100644 index df7834503883..000000000000 --- a/x/ibc/applications/transfer/simulation/decoder.go +++ /dev/null @@ -1,33 +0,0 @@ -package simulation - -import ( - "bytes" - "fmt" - - "github.com/cosmos/cosmos-sdk/types/kv" - "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" -) - -// TransferUnmarshaler defines the expected encoding store functions. -type TransferUnmarshaler interface { - MustUnmarshalDenomTrace([]byte) types.DenomTrace -} - -// NewDecodeStore returns a decoder function closure that unmarshals the KVPair's -// Value to the corresponding DenomTrace type. -func NewDecodeStore(cdc TransferUnmarshaler) func(kvA, kvB kv.Pair) string { - return func(kvA, kvB kv.Pair) string { - switch { - case bytes.Equal(kvA.Key[:1], types.PortKey): - return fmt.Sprintf("Port A: %s\nPort B: %s", string(kvA.Value), string(kvB.Value)) - - case bytes.Equal(kvA.Key[:1], types.DenomTraceKey): - denomTraceA := cdc.MustUnmarshalDenomTrace(kvA.Value) - denomTraceB := cdc.MustUnmarshalDenomTrace(kvB.Value) - return fmt.Sprintf("DenomTrace A: %s\nDenomTrace B: %s", denomTraceA.IBCDenom(), denomTraceB.IBCDenom()) - - default: - panic(fmt.Sprintf("invalid %s key prefix %X", types.ModuleName, kvA.Key[:1])) - } - } -} diff --git a/x/ibc/applications/transfer/simulation/decoder_test.go b/x/ibc/applications/transfer/simulation/decoder_test.go deleted file mode 100644 index 729a067e0287..000000000000 --- a/x/ibc/applications/transfer/simulation/decoder_test.go +++ /dev/null @@ -1,59 +0,0 @@ -package simulation_test - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/simapp" - "github.com/cosmos/cosmos-sdk/types/kv" - "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/simulation" - "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" -) - -func TestDecodeStore(t *testing.T) { - app := simapp.Setup(false) - dec := simulation.NewDecodeStore(app.TransferKeeper) - - trace := types.DenomTrace{ - BaseDenom: "uatom", - Path: "transfer/channelToA", - } - - kvPairs := kv.Pairs{ - Pairs: []kv.Pair{ - { - Key: types.PortKey, - Value: []byte(types.PortID), - }, - { - Key: types.DenomTraceKey, - Value: app.TransferKeeper.MustMarshalDenomTrace(trace), - }, - { - Key: []byte{0x99}, - Value: []byte{0x99}, - }, - }, - } - tests := []struct { - name string - expectedLog string - }{ - {"PortID", fmt.Sprintf("Port A: %s\nPort B: %s", types.PortID, types.PortID)}, - {"DenomTrace", fmt.Sprintf("DenomTrace A: %s\nDenomTrace B: %s", trace.IBCDenom(), trace.IBCDenom())}, - {"other", ""}, - } - - for i, tt := range tests { - i, tt := i, tt - t.Run(tt.name, func(t *testing.T) { - if i == len(tests)-1 { - require.Panics(t, func() { dec(kvPairs.Pairs[i], kvPairs.Pairs[i]) }, tt.name) - } else { - require.Equal(t, tt.expectedLog, dec(kvPairs.Pairs[i], kvPairs.Pairs[i]), tt.name) - } - }) - } -} diff --git a/x/ibc/applications/transfer/simulation/genesis.go b/x/ibc/applications/transfer/simulation/genesis.go deleted file mode 100644 index a51bce9f4717..000000000000 --- a/x/ibc/applications/transfer/simulation/genesis.go +++ /dev/null @@ -1,54 +0,0 @@ -package simulation - -import ( - "encoding/json" - "fmt" - "math/rand" - "strings" - - "github.com/cosmos/cosmos-sdk/types/module" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" -) - -// Simulation parameter constants -const port = "port_id" - -// RadomEnabled randomized send or receive enabled param with 75% prob of being true. -func RadomEnabled(r *rand.Rand) bool { - return r.Int63n(101) <= 75 -} - -// RandomizedGenState generates a random GenesisState for transfer. -func RandomizedGenState(simState *module.SimulationState) { - var portID string - simState.AppParams.GetOrGenerate( - simState.Cdc, port, &portID, simState.Rand, - func(r *rand.Rand) { portID = strings.ToLower(simtypes.RandStringOfLength(r, 20)) }, - ) - - var sendEnabled bool - simState.AppParams.GetOrGenerate( - simState.Cdc, string(types.KeySendEnabled), &sendEnabled, simState.Rand, - func(r *rand.Rand) { sendEnabled = RadomEnabled(r) }, - ) - - var receiveEnabled bool - simState.AppParams.GetOrGenerate( - simState.Cdc, string(types.KeyReceiveEnabled), &receiveEnabled, simState.Rand, - func(r *rand.Rand) { receiveEnabled = RadomEnabled(r) }, - ) - - transferGenesis := types.GenesisState{ - PortId: portID, - DenomTraces: types.Traces{}, - Params: types.NewParams(sendEnabled, receiveEnabled), - } - - bz, err := json.MarshalIndent(&transferGenesis, "", " ") - 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(&transferGenesis) -} diff --git a/x/ibc/applications/transfer/simulation/genesis_test.go b/x/ibc/applications/transfer/simulation/genesis_test.go deleted file mode 100644 index 12791d7445f9..000000000000 --- a/x/ibc/applications/transfer/simulation/genesis_test.go +++ /dev/null @@ -1,74 +0,0 @@ -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/ibc/applications/transfer/simulation" - "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" -) - -// TestRandomizedGenState tests the normal scenario of applying RandomizedGenState. -// Abonormal scenarios are not tested here. -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 ibcTransferGenesis types.GenesisState - simState.Cdc.MustUnmarshalJSON(simState.GenState[types.ModuleName], &ibcTransferGenesis) - - require.Equal(t, "euzxpfgkqegqiqwixnku", ibcTransferGenesis.PortId) - require.True(t, ibcTransferGenesis.Params.SendEnabled) - require.True(t, ibcTransferGenesis.Params.ReceiveEnabled) - require.Len(t, ibcTransferGenesis.DenomTraces, 0) - -} - -// TestRandomizedGenState tests abnormal scenarios of applying RandomizedGenState. -func TestRandomizedGenState1(t *testing.T) { - interfaceRegistry := codectypes.NewInterfaceRegistry() - cdc := codec.NewProtoCodec(interfaceRegistry) - - s := rand.NewSource(1) - r := rand.New(s) - // all these tests will panic - tests := []struct { - simState module.SimulationState - panicMsg string - }{ - { // panic => reason: incomplete initialization of the simState - module.SimulationState{}, "invalid memory address or nil pointer dereference"}, - { // panic => reason: incomplete initialization of the simState - module.SimulationState{ - AppParams: make(simtypes.AppParams), - Cdc: cdc, - Rand: r, - }, "assignment to entry in nil map"}, - } - - for _, tt := range tests { - require.Panicsf(t, func() { simulation.RandomizedGenState(&tt.simState) }, tt.panicMsg) - } -} diff --git a/x/ibc/applications/transfer/simulation/params.go b/x/ibc/applications/transfer/simulation/params.go deleted file mode 100644 index 67c61f514ed1..000000000000 --- a/x/ibc/applications/transfer/simulation/params.go +++ /dev/null @@ -1,32 +0,0 @@ -package simulation - -import ( - "fmt" - "math/rand" - - gogotypes "github.com/gogo/protobuf/types" - - "github.com/cosmos/cosmos-sdk/x/simulation" - - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" -) - -// ParamChanges defines the parameters that can be modified by param change proposals -// on the simulation -func ParamChanges(r *rand.Rand) []simtypes.ParamChange { - return []simtypes.ParamChange{ - simulation.NewSimParamChange(types.ModuleName, string(types.KeySendEnabled), - func(r *rand.Rand) string { - sendEnabled := RadomEnabled(r) - return fmt.Sprintf("%s", types.ModuleCdc.MustMarshalJSON(&gogotypes.BoolValue{Value: sendEnabled})) - }, - ), - simulation.NewSimParamChange(types.ModuleName, string(types.KeyReceiveEnabled), - func(r *rand.Rand) string { - receiveEnabled := RadomEnabled(r) - return fmt.Sprintf("%s", types.ModuleCdc.MustMarshalJSON(&gogotypes.BoolValue{Value: receiveEnabled})) - }, - ), - } -} diff --git a/x/ibc/applications/transfer/simulation/params_test.go b/x/ibc/applications/transfer/simulation/params_test.go deleted file mode 100644 index a692d4328e92..000000000000 --- a/x/ibc/applications/transfer/simulation/params_test.go +++ /dev/null @@ -1,36 +0,0 @@ -package simulation_test - -import ( - "math/rand" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/simulation" -) - -func TestParamChanges(t *testing.T) { - s := rand.NewSource(1) - r := rand.New(s) - - expected := []struct { - composedKey string - key string - simValue string - subspace string - }{ - {"transfer/SendEnabled", "SendEnabled", "false", "transfer"}, - {"transfer/ReceiveEnabled", "ReceiveEnabled", "true", "transfer"}, - } - - paramChanges := simulation.ParamChanges(r) - - require.Len(t, paramChanges, 2) - - for i, p := range paramChanges { - require.Equal(t, expected[i].composedKey, p.ComposedKey()) - require.Equal(t, expected[i].key, p.Key()) - require.Equal(t, expected[i].simValue, p.SimValue()(r), p.Key()) - require.Equal(t, expected[i].subspace, p.Subspace()) - } -} diff --git a/x/ibc/applications/transfer/spec/01_concepts.md b/x/ibc/applications/transfer/spec/01_concepts.md deleted file mode 100644 index 96f05f12a7ca..000000000000 --- a/x/ibc/applications/transfer/spec/01_concepts.md +++ /dev/null @@ -1,117 +0,0 @@ - - -# Concepts - -## Acknowledgements - -ICS20 uses the recommended acknowledgement format as specified by [ICS 04](https://github.com/cosmos/ics/tree/master/spec/ics-004-channel-and-packet-semantics#acknowledgement-envelope). - -A successful receive of a transfer packet will result in a Result Acknowledgement being written -with the value `[]byte(byte(1))` in the `Response` field. - -An unsuccessful receive of a transfer packet will result in an Error Acknowledgement being written -with the error message in the `Response` field. - -## Denomination Trace - -The denomination trace corresponds to the information that allows a token to be traced back to its -origin chain. It contains a sequence of port and channel identifiers ordered from the most recent to -the oldest in the timeline of transfers. - -This information is included on the token denomination field in the form of a hash to prevent an -unbounded denomination length. For example, the token `transfer/channelToA/uatom` will be displayed -as `ibc/7F1D3FCF4AE79E1554D670D1AD949A9BA4E4A3C76C63093E17E446A46061A7A2`. - -Each send to any chain other than the one it was previously received from is a movement forwards in -the token's timeline. This causes trace to be added to the token's history and the destination port -and destination channel to be prefixed to the denomination. In these instances the sender chain is -acting as the "source zone". When the token is sent back to the chain it previously received from, the -prefix is removed. This is a backwards movement in the token's timeline and the sender chain is -acting as the "sink zone". - -It is strongly recommended to read the full details of [ADR 001: Coin Source Tracing](./../../../../../docs/architecture/adr-001-coin-source-tracing.md) to understand the implications and context of the IBC token representations. - -### UX suggestions for clients - -For clients (wallets, exchanges, applications, block explorers, etc) that want to display the source of the token, it is recommended to use the following -alternatives for each of the cases below: - -#### Direct connection - -If the denomination trace contains a single identifier prefix pair (as in the example above), then -the easiest way to retrieve the chain and light client identifier is to map the trace information -directly. In summary, this requires querying the channel from the denomination trace identifiers, -and then the counterparty client state using the counterparty port and channel identifiers from the -retrieved channel. - -A general pseudo algorithm would look like the following: - -1. Query the full denomination trace. -2. Query the channel with the `portID/channelID` pair, which corresponds to the first destination of the - token. -3. Query the client state using the identifiers pair. Note that this query will return a `"Not - Found"` response if the current chain is not connected to this channel. -4. Retrieve the the client identifier or chain identifier from the client state (eg: on - Tendermint clients) and store it locally. - -Using the gRPC gataway client service the steps above would be, with a given IBC token `ibc/7F1D3FCF4AE79E1554D670D1AD949A9BA4E4A3C76C63093E17E446A46061A7A2` stored on `chainB`: - -1. `GET /ibc_transfer/v1beta1/denom_traces/7F1D3FCF4AE79E1554D670D1AD949A9BA4E4A3C76C63093E17E446A46061A7A2` -> `{"path": "transfer/channelToA", "base_denom": "uatom"}` -2. `GET /ibc/channel/v1beta1/channels/channelToA/ports/transfer/client_state"` -> `{"client_id": "clientA", "chain-id": "chainA", ...}` -3. `GET /ibc/channel/v1beta1/channels/channelToA/ports/transfer"` -> `{"channel_id": "channelToA", port_id": "transfer", counterparty: {"channel_id": "channelToB", port_id": "transfer"}, ...}` -4. `GET /ibc/channel/v1beta1/channels/channelToB/ports/transfer/client_state" -> {"client_id": "clientB", "chain-id": "chainB", ...}` - -Then, the token transfer chain path for the `uatom` denomination would be: `chainA` -> `chainB`. - -### Multiple hops - -The multiple channel hops case applies when the token has passed through multiple chains between the original source and final destination chains. - -The IBC protocol doesn't know the topology of the overall network (i.e connections between chains and identifier names between them). For this reason, in the the multiple hops case, a particular chain in the timeline of the individual transfers can't query the chain and client identifiers of the other chains. - -Take for example the following sequence of transfers `A -> B -> C` for an IBC token, with a final prefix path (trace info) of `transfer/channelChainC/transfer/channelChainB`. What the paragraph above means is that is that even in the case that chain `C` is directly connected to chain `A`, querying the port and channel identifiers that chain `B` uses to connect to chain `A` (eg: `transfer/channelChainA`) can be completely different from the one that chain `C` uses to connect to chain `A` (eg: `transfer/channelToChainA`). - -Thus the proposed solution for clients that the IBC team recommends are the following: - -- **Connect to all chains**: Connecting to all the chains in the timeline would allow clients to - perform the queries outlined in the [direct connection](#direct-connection) section to each - relevant chain. By repeatedly following the port and channel denomination trace transfer timeline, - clients should always be able to find all the relevant identifiers. This comes at the tradeoff - that the client must connect to nodes on each of the chains in order to perform the queries. -- **Relayer as a Service (RaaS)**: A longer term solution is to use/create a relayer service that - could map the denomination trace to the chain path timeline for each token (i.e `origin chain -> - chain #1 -> ... -> chain #(n-1) -> final chain`). These services could provide merkle proofs in - order to allow clients to optionally verify the path timeline correctness for themselves by - running light clients. If the proofs are not verified, they should be considered as trusted third - parties services. Additionally, client would be advised in the future to use RaaS that support the - largest number of connections between chains in the ecosystem. Unfortunately, none of the existing - public relayers (in [Golang](https://github.com/cosmos/relayer) and - [Rust](https://github.com/informalsystems/ibc-rs)), provide this service to clients. - -::: tip -The only viable alternative for clients (at the time of writing) to tokens with multiple connection hops, is to connect to all chains directly and perform relevant queries to each of them in the sequence. -::: - -## Locked Funds - -In some [exceptional cases](./../../../../../docs/architecture/adr-026-ibc-client-recovery-mechanisms.md#exceptional-cases), a client state associated with a given channel cannot be updated. This causes that funds from fungible tokens in that channel will be permanently locked and thus can no longer be transferred. - -To mitigate this, a client update governance proposal can be submitted to update the frozen client -with a new valid header. Once the proposal passes the client state will be unfrozen and the funds -from the associated channels will then be unlocked. This mechanism only applies to clients that -allow updates via governance, such as Tendermint clients. - -In addition to this, it's important to mention that a token must be sent back along the exact route -that it took originally un order to return it to its original form on the source chain (eg: the -Cosmos Hub for the `uatom`). Sending a token back to the same chain across a different channel will -**not** move the token back across its timeline. If a channel in the chain history closes before the -token can be sent back across that channel, then the token will not be returnable to its original -form. - - -## Security Considerations - -For safety, no other module must be capable of minting tokens with the `ibc/` prefix. The IBC -transfer module needs a subset of the denomination space that only it can create tokens in. diff --git a/x/ibc/applications/transfer/spec/02_state.md b/x/ibc/applications/transfer/spec/02_state.md deleted file mode 100644 index 9cab8d677fd6..000000000000 --- a/x/ibc/applications/transfer/spec/02_state.md +++ /dev/null @@ -1,10 +0,0 @@ - - -# State - -The transfer IBC application module keeps state of the port to which the module is binded and the denomination trace information as outlined in [ADR 01](./../../../../../docs/architecture/adr-001-coin-source-tracing.md). - -- `Port`: `0x01 -> ProtocolBuffer(string)` -- `DenomTrace`: `0x02 | []bytes(traceHash) -> ProtocolBuffer(DenomTrace)` diff --git a/x/ibc/applications/transfer/spec/03_state_transitions.md b/x/ibc/applications/transfer/spec/03_state_transitions.md deleted file mode 100644 index 9090da543432..000000000000 --- a/x/ibc/applications/transfer/spec/03_state_transitions.md +++ /dev/null @@ -1,36 +0,0 @@ - - -# State Transitions - -## Send Fungible Tokens - -A successful fungible token send has two state transitions depending if the -transfer is a movement forward or backwards in the token's timeline: - -1. Sender chain is the source chain, *i.e* a transfer to any chain other than the one it was previously received from is a movement forwards in the token's timeline. This results in the following state transitions: - -- The coins are transferred to an escrow address (i.e locked) on the sender chain -- The coins are transferred to the receiving chain through IBC TAO logic. - -2. Sender chain is the sink chain, *i.e* the token is sent back to the chain it previously received from. This is a backwards movement in the token's timeline. This results in the following state transitions: - -- The coins (vouchers) are burned on the sender chain -- The coins transferred to the receiving chain though IBC TAO logic. - -## Receive Fungible Tokens - -A successful fungible token receive has two state transitions depending if the -transfer is a movement forward or backwards in the token's timeline: - -1. Receiver chain is the source chain. This is a backwards movement in the token's timeline. This results in the following state transitions: - -- The leftmost port and channel identifier pair is removed from the token denomination prefix. -- The tokens are unescrowed and sent to the receiving address. - -2. Receiver chain is the sink chain. This is a movement forwards in the token's timeline. This results in the following state transitions: - -- Token vouchers are minted by prefixing the destination port and channel identifiers to the trace information. -- The receiving chain stores the new trace information in the store (if not set already). -- The vouchers are sent to the receiving address. diff --git a/x/ibc/applications/transfer/spec/04_messages.md b/x/ibc/applications/transfer/spec/04_messages.md deleted file mode 100644 index 9da7673eb366..000000000000 --- a/x/ibc/applications/transfer/spec/04_messages.md +++ /dev/null @@ -1,40 +0,0 @@ - - -# Messages - -## MsgTransfer - -A fungible token cross chain transfer is achieved by using the `MsgTransfer`: - -```go -type MsgTransfer struct { - SourcePort string - SourceChannel string - Token sdk.Coin - Sender string - Receiver string - TimeoutHeight ibcexported.Height - TimeoutTimestamp uint64 -} -``` - -This message is expected to fail if: - -- `SourcePort` is invalid (see 24-host naming requirements) -- `SourceChannel` is invalid (see 24-host naming requirements) -- `Token` is invalid (denom is invalid or amount is negative) -- `Token.Amount` is not positive -- `Sender` is empty -- `Receiver` is empty -- `TimeoutHeight` and `TimeoutTimestamp` are both zero -- `Token.Denom` is not a valid IBC denomination as per [ADR 001 - Coin Source Tracing](./../../../../../docs/architecture/adr-001-coin-source-tracing.md). - -This message will send a fungible token to the counterparty chain represented -by the counterparty Channel End connected to the Channel End with the identifiers -`SourcePort` and `SourceChannel`. - -The denomination provided for transfer should correspond to the same denomination -represented on this chain. The prefixes will be added as necessary upon by the -receiving chain. diff --git a/x/ibc/applications/transfer/spec/05_events.md b/x/ibc/applications/transfer/spec/05_events.md deleted file mode 100644 index 51b49da4602d..000000000000 --- a/x/ibc/applications/transfer/spec/05_events.md +++ /dev/null @@ -1,44 +0,0 @@ - - -# Events - -## MsgTransfer - -| Type | Attribute Key | Attribute Value | -|--------------|---------------|-----------------| -| ibc_transfer | sender | {sender} | -| ibc_transfer | receiver | {receiver} | -| message | action | transfer | -| message | module | transfer | - -## OnRecvPacket callback - -| Type | Attribute Key | Attribute Value | -|-----------------------|---------------|-----------------| -| fungible_token_packet | module | transfer | -| fungible_token_packet | receiver | {receiver} | -| fungible_token_packet | denom | {denom} | -| fungible_token_packet | amount | {amount} | -| fungible_token_packet | success | {ackSuccess} | -| denomination_trace | trace_hash | {hex_hash} | - -## OnAcknowledgePacket callback - -| Type | Attribute Key | Attribute Value | -|-----------------------|-----------------|-------------------| -| fungible_token_packet | module | transfer | -| fungible_token_packet | receiver | {receiver} | -| fungible_token_packet | denom | {denom} | -| fungible_token_packet | amount | {amount} | -| fungible_token_packet | success | error | {ack.Response} | - -## OnTimeoutPacket callback - -| Type | Attribute Key | Attribute Value | -|-----------------------|-----------------|-----------------| -| fungible_token_packet | module | transfer | -| fungible_token_packet | refund_receiver | {receiver} | -| fungible_token_packet | denom | {denom} | -| fungible_token_packet | amount | {amount} | diff --git a/x/ibc/applications/transfer/spec/06_metrics.md b/x/ibc/applications/transfer/spec/06_metrics.md deleted file mode 100644 index 21bb51c0a10e..000000000000 --- a/x/ibc/applications/transfer/spec/06_metrics.md +++ /dev/null @@ -1,14 +0,0 @@ - - -# Metrics - -The transfer IBC application module exposes the following set of [metrics](./../../../../../docs/core/telemetry.md). - -| Metric | Description | Unit | Type | -|:--------------------------------|:------------------------------------------------------------------------------------------|:----------------|:--------| -| `tx_msg_ibc_transfer` | The total amount of tokens transferred via IBC in a `MsgTransfer` (source or sink chain) | token | gauge | -| `ibc_transfer_packet_receive` | The total amount of tokens received in a `FungibleTokenPacketData` (source or sink chain) | token | gauge | -| `ibc_transfer_send` | Total number of IBC transfers sent from a chain (source or sink) | transfer | counter | -| `ibc_transfer_receive` | Total number of IBC transfers received to a chain (source or sink) | transfer | counter | diff --git a/x/ibc/applications/transfer/spec/07_params.md b/x/ibc/applications/transfer/spec/07_params.md deleted file mode 100644 index 8d2b97c580d2..000000000000 --- a/x/ibc/applications/transfer/spec/07_params.md +++ /dev/null @@ -1,30 +0,0 @@ - - -# Parameters - -The ibc-transfer module contains the following parameters: - -| Key | Type | Default Value | -|------------------|------|---------------| -| `SendEnabled` | bool | `true` | -| `ReceiveEnabled` | bool | `true` | - -## SendEnabled - -The transfers enabled parameter controls send cross-chain transfer capabilities for all fungible -tokens. - -To prevent a single token from being transferred from the chain, set the `SendEnabled` parameter to `true` and -then set the bank module's [`SendEnabled` parameter](./../../../../bank/spec/05_params.md#sendenabled) for -the denomination to `false`. - -## ReceiveEnabled - -The transfers enabled parameter controls receive cross-chain transfer capabilities for all fungible -tokens. - -To prevent a single token from being transferred to the chain, set the `ReceiveEnabled` parameter to `true` and -then set the bank module's [`SendEnabled` parameter](./../../../../bank/spec/05_params.md#sendenabled) for -the denomination to `false`. diff --git a/x/ibc/applications/transfer/spec/README.md b/x/ibc/applications/transfer/spec/README.md deleted file mode 100644 index 5230fdde41b6..000000000000 --- a/x/ibc/applications/transfer/spec/README.md +++ /dev/null @@ -1,24 +0,0 @@ - - -# `ibc-transfer` - -## Abstract - -This paper defines the implementation of the ICS20 protocol on the Cosmos SDK. - -For the general specification please refer to the [ICS20 Specification](https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer). - -## Contents - -1. **[Concepts](01_concepts.md)** -2. **[State](02_state.md)** -3. **[State Transitions](03_state_transitions.md)** -4. **[Messages](04_messages.md)** -5. **[Events](05_events.md)** -6. **[Metrics](06_metrics.md)** -7. **[Parameters](07_params.md)** diff --git a/x/ibc/applications/transfer/types/codec.go b/x/ibc/applications/transfer/types/codec.go deleted file mode 100644 index 24ad7e5a9023..000000000000 --- a/x/ibc/applications/transfer/types/codec.go +++ /dev/null @@ -1,41 +0,0 @@ -package types - -import ( - "github.com/cosmos/cosmos-sdk/codec" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - sdk "github.com/cosmos/cosmos-sdk/types" - "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) { - registry.RegisterImplementations((*sdk.Msg)(nil), &MsgTransfer{}) - - msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) -} - -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 - // 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/coin.go b/x/ibc/applications/transfer/types/coin.go deleted file mode 100644 index 08ae9a8d3254..000000000000 --- a/x/ibc/applications/transfer/types/coin.go +++ /dev/null @@ -1,48 +0,0 @@ -package types - -import ( - "fmt" - "strings" - - sdk "github.com/cosmos/cosmos-sdk/types" -) - -// SenderChainIsSource returns false if the denomination originally came -// from the receiving chain and true otherwise. -func SenderChainIsSource(sourcePort, sourceChannel, denom string) bool { - // This is the prefix that would have been prefixed to the denomination - // on sender chain IF and only if the token originally came from the - // receiving chain. - - return !ReceiverChainIsSource(sourcePort, sourceChannel, denom) -} - -// ReceiverChainIsSource returns true if the denomination originally came -// from the receiving chain and false otherwise. -func ReceiverChainIsSource(sourcePort, sourceChannel, denom string) bool { - // The prefix passed in should contain the SourcePort and SourceChannel. - // If the receiver chain originally sent the token to the sender chain - // the denom will have the sender's SourcePort and SourceChannel as the - // prefix. - - voucherPrefix := GetDenomPrefix(sourcePort, sourceChannel) - return strings.HasPrefix(denom, voucherPrefix) - -} - -// GetDenomPrefix returns the receiving denomination prefix -func GetDenomPrefix(portID, channelID string) string { - return fmt.Sprintf("%s/%s/", portID, channelID) -} - -// GetPrefixedDenom returns the denomination with the portID and channelID prefixed -func GetPrefixedDenom(portID, channelID, baseDenom string) string { - return fmt.Sprintf("%s/%s/%s", portID, channelID, baseDenom) -} - -// GetTransferCoin creates a transfer coin with the port ID and channel ID -// prefixed to the base denom. -func GetTransferCoin(portID, channelID, baseDenom string, amount int64) sdk.Coin { - denomTrace := ParseDenomTrace(GetPrefixedDenom(portID, channelID, baseDenom)) - return sdk.NewInt64Coin(denomTrace.IBCDenom(), amount) -} diff --git a/x/ibc/applications/transfer/types/errors.go b/x/ibc/applications/transfer/types/errors.go deleted file mode 100644 index 07cba1949157..000000000000 --- a/x/ibc/applications/transfer/types/errors.go +++ /dev/null @@ -1,17 +0,0 @@ -package types - -import ( - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" -) - -// IBC channel sentinel errors -var ( - ErrInvalidPacketTimeout = sdkerrors.Register(ModuleName, 2, "invalid packet timeout") - ErrInvalidDenomForTransfer = sdkerrors.Register(ModuleName, 3, "invalid denomination for cross-chain transfer") - ErrInvalidVersion = sdkerrors.Register(ModuleName, 4, "invalid ICS20 version") - ErrInvalidAmount = sdkerrors.Register(ModuleName, 5, "invalid token amount") - ErrTraceNotFound = sdkerrors.Register(ModuleName, 6, "denomination trace not found") - ErrSendDisabled = sdkerrors.Register(ModuleName, 7, "fungible token transfers from this chain are disabled") - ErrReceiveDisabled = sdkerrors.Register(ModuleName, 8, "fungible token transfers to this chain are disabled") - ErrMaxTransferChannels = sdkerrors.Register(ModuleName, 9, "max transfer channels") -) diff --git a/x/ibc/applications/transfer/types/events.go b/x/ibc/applications/transfer/types/events.go deleted file mode 100644 index a3ed5b413c73..000000000000 --- a/x/ibc/applications/transfer/types/events.go +++ /dev/null @@ -1,21 +0,0 @@ -package types - -// IBC transfer events -const ( - EventTypeTimeout = "timeout" - EventTypePacket = "fungible_token_packet" - EventTypeTransfer = "ibc_transfer" - EventTypeChannelClose = "channel_closed" - EventTypeDenomTrace = "denomination_trace" - - AttributeKeyReceiver = "receiver" - AttributeKeyDenom = "denom" - AttributeKeyAmount = "amount" - AttributeKeyRefundReceiver = "refund_receiver" - AttributeKeyRefundDenom = "refund_denom" - AttributeKeyRefundAmount = "refund_amount" - AttributeKeyAckSuccess = "success" - AttributeKeyAck = "acknowledgement" - AttributeKeyAckError = "error" - AttributeKeyTraceHash = "trace_hash" -) diff --git a/x/ibc/applications/transfer/types/expected_keepers.go b/x/ibc/applications/transfer/types/expected_keepers.go deleted file mode 100644 index 284463350efc..000000000000 --- a/x/ibc/applications/transfer/types/expected_keepers.go +++ /dev/null @@ -1,48 +0,0 @@ -package types - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/auth/types" - capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" - connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - ibcexported "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -// AccountKeeper defines the contract required for account APIs. -type AccountKeeper interface { - GetModuleAddress(name string) sdk.AccAddress - GetModuleAccount(ctx sdk.Context, name string) types.ModuleAccountI -} - -// BankKeeper defines the expected bank keeper -type BankKeeper interface { - SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error - MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error - BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error - SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error - SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error -} - -// ChannelKeeper defines the expected IBC channel keeper -type ChannelKeeper interface { - GetChannel(ctx sdk.Context, srcPort, srcChan string) (channel channeltypes.Channel, found bool) - GetNextSequenceSend(ctx sdk.Context, portID, channelID string) (uint64, bool) - SendPacket(ctx sdk.Context, channelCap *capabilitytypes.Capability, packet ibcexported.PacketI) error - ChanCloseInit(ctx sdk.Context, portID, channelID string, chanCap *capabilitytypes.Capability) error -} - -// ClientKeeper defines the expected IBC client keeper -type ClientKeeper interface { - GetClientConsensusState(ctx sdk.Context, clientID string) (connection ibcexported.ConsensusState, found bool) -} - -// ConnectionKeeper defines the expected IBC connection keeper -type ConnectionKeeper interface { - GetConnection(ctx sdk.Context, connectionID string) (connection connectiontypes.ConnectionEnd, found bool) -} - -// PortKeeper defines the expected IBC port keeper -type PortKeeper interface { - BindPort(ctx sdk.Context, portID string) *capabilitytypes.Capability -} diff --git a/x/ibc/applications/transfer/types/genesis.go b/x/ibc/applications/transfer/types/genesis.go deleted file mode 100644 index 682b04c4cf0a..000000000000 --- a/x/ibc/applications/transfer/types/genesis.go +++ /dev/null @@ -1,35 +0,0 @@ -package types - -import ( - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" -) - -// NewGenesisState creates a new ibc-transfer GenesisState instance. -func NewGenesisState(portID string, denomTraces Traces, params Params) *GenesisState { - return &GenesisState{ - PortId: portID, - DenomTraces: denomTraces, - Params: params, - } -} - -// DefaultGenesisState returns a GenesisState with "transfer" as the default PortID. -func DefaultGenesisState() *GenesisState { - return &GenesisState{ - PortId: PortID, - DenomTraces: Traces{}, - Params: DefaultParams(), - } -} - -// Validate performs basic genesis state validation returning an error upon any -// failure. -func (gs GenesisState) Validate() error { - if err := host.PortIdentifierValidator(gs.PortId); err != nil { - return err - } - if err := gs.DenomTraces.Validate(); err != nil { - return err - } - return gs.Params.Validate() -} diff --git a/x/ibc/applications/transfer/types/genesis.pb.go b/x/ibc/applications/transfer/types/genesis.pb.go deleted file mode 100644 index 3ae0442f826b..000000000000 --- a/x/ibc/applications/transfer/types/genesis.pb.go +++ /dev/null @@ -1,443 +0,0 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: ibc/applications/transfer/v1/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 defines the ibc-transfer genesis state -type GenesisState struct { - PortId string `protobuf:"bytes,1,opt,name=port_id,json=portId,proto3" json:"port_id,omitempty" yaml:"port_id"` - DenomTraces Traces `protobuf:"bytes,2,rep,name=denom_traces,json=denomTraces,proto3,castrepeated=Traces" json:"denom_traces" yaml:"denom_traces"` - Params Params `protobuf:"bytes,3,opt,name=params,proto3" json:"params"` -} - -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_a4f788affd5bea89, []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) GetPortId() string { - if m != nil { - return m.PortId - } - return "" -} - -func (m *GenesisState) GetDenomTraces() Traces { - if m != nil { - return m.DenomTraces - } - return nil -} - -func (m *GenesisState) GetParams() Params { - if m != nil { - return m.Params - } - return Params{} -} - -func init() { - proto.RegisterType((*GenesisState)(nil), "ibc.applications.transfer.v1.GenesisState") -} - -func init() { - proto.RegisterFile("ibc/applications/transfer/v1/genesis.proto", fileDescriptor_a4f788affd5bea89) -} - -var fileDescriptor_a4f788affd5bea89 = []byte{ - // 317 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0xca, 0x4c, 0x4a, 0xd6, - 0x4f, 0x2c, 0x28, 0xc8, 0xc9, 0x4c, 0x4e, 0x2c, 0xc9, 0xcc, 0xcf, 0x2b, 0xd6, 0x2f, 0x29, 0x4a, - 0xcc, 0x2b, 0x4e, 0x4b, 0x2d, 0xd2, 0x2f, 0x33, 0xd4, 0x4f, 0x4f, 0xcd, 0x4b, 0x2d, 0xce, 0x2c, - 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x92, 0xc9, 0x4c, 0x4a, 0xd6, 0x43, 0x56, 0xab, 0x07, - 0x53, 0xab, 0x57, 0x66, 0x28, 0x25, 0x92, 0x9e, 0x9f, 0x9e, 0x0f, 0x56, 0xa8, 0x0f, 0x62, 0x41, - 0xf4, 0x48, 0x69, 0xe3, 0x35, 0x1f, 0xae, 0x1f, 0xac, 0x58, 0xe9, 0x33, 0x23, 0x17, 0x8f, 0x3b, - 0xc4, 0xca, 0xe0, 0x92, 0xc4, 0x92, 0x54, 0x21, 0x6d, 0x2e, 0xf6, 0x82, 0xfc, 0xa2, 0x92, 0xf8, - 0xcc, 0x14, 0x09, 0x46, 0x05, 0x46, 0x0d, 0x4e, 0x27, 0xa1, 0x4f, 0xf7, 0xe4, 0xf9, 0x2a, 0x13, - 0x73, 0x73, 0xac, 0x94, 0xa0, 0x12, 0x4a, 0x41, 0x6c, 0x20, 0x96, 0x67, 0x8a, 0x50, 0x11, 0x17, - 0x4f, 0x4a, 0x6a, 0x5e, 0x7e, 0x6e, 0x7c, 0x49, 0x51, 0x62, 0x72, 0x6a, 0xb1, 0x04, 0x93, 0x02, - 0xb3, 0x06, 0xb7, 0x91, 0x86, 0x1e, 0x3e, 0x57, 0xeb, 0xb9, 0x80, 0x74, 0x84, 0x80, 0x34, 0x38, - 0xa9, 0x9e, 0xb8, 0x27, 0xcf, 0xf0, 0xe9, 0x9e, 0xbc, 0x30, 0xc4, 0x7c, 0x64, 0xb3, 0x94, 0x56, - 0xdd, 0x97, 0x67, 0x03, 0xab, 0x2a, 0x0e, 0xe2, 0x4e, 0x81, 0x6b, 0x29, 0x16, 0x72, 0xe2, 0x62, - 0x2b, 0x48, 0x2c, 0x4a, 0xcc, 0x2d, 0x96, 0x60, 0x56, 0x60, 0xd4, 0xe0, 0x36, 0x52, 0xc1, 0x6f, - 0x5b, 0x00, 0x58, 0xad, 0x13, 0x0b, 0xc8, 0xa6, 0x20, 0xa8, 0x4e, 0xa7, 0x88, 0x13, 0x8f, 0xe4, - 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48, 0x8e, 0x71, 0xc2, 0x63, 0x39, 0x86, 0x0b, 0x8f, - 0xe5, 0x18, 0x6e, 0x3c, 0x96, 0x63, 0x88, 0xb2, 0x4b, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, - 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0x2f, 0xce, 0xcd, 0x2f, 0x86, 0x52, 0xba, 0xc5, 0x29, 0xd9, 0xfa, - 0x15, 0xfa, 0xb8, 0xc3, 0xb6, 0xa4, 0xb2, 0x20, 0xb5, 0x38, 0x89, 0x0d, 0x1c, 0xac, 0xc6, 0x80, - 0x00, 0x00, 0x00, 0xff, 0xff, 0xda, 0xbb, 0x81, 0x1e, 0xe5, 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 - { - size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintGenesis(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - if len(m.DenomTraces) > 0 { - for iNdEx := len(m.DenomTraces) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.DenomTraces[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintGenesis(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - } - } - if len(m.PortId) > 0 { - i -= len(m.PortId) - copy(dAtA[i:], m.PortId) - i = encodeVarintGenesis(dAtA, i, uint64(len(m.PortId))) - 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 - l = len(m.PortId) - if l > 0 { - n += 1 + l + sovGenesis(uint64(l)) - } - if len(m.DenomTraces) > 0 { - for _, e := range m.DenomTraces { - l = e.Size() - n += 1 + l + sovGenesis(uint64(l)) - } - } - l = m.Params.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 PortId", 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.PortId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field DenomTraces", 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.DenomTraces = append(m.DenomTraces, DenomTrace{}) - if err := m.DenomTraces[len(m.DenomTraces)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Params", 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 := m.Params.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/ibc/applications/transfer/types/genesis_test.go b/x/ibc/applications/transfer/types/genesis_test.go deleted file mode 100644 index a2aba58ca677..000000000000 --- a/x/ibc/applications/transfer/types/genesis_test.go +++ /dev/null @@ -1,47 +0,0 @@ -package types_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" -) - -func TestValidateGenesis(t *testing.T) { - testCases := []struct { - name string - genState *types.GenesisState - expPass bool - }{ - { - name: "default", - genState: types.DefaultGenesisState(), - expPass: true, - }, - { - "valid genesis", - &types.GenesisState{ - PortId: "portidone", - }, - true, - }, - { - "invalid client", - &types.GenesisState{ - PortId: "(INVALIDPORT)", - }, - false, - }, - } - - for _, tc := range testCases { - tc := tc - err := tc.genState.Validate() - if tc.expPass { - require.NoError(t, err, tc.name) - } else { - require.Error(t, err, tc.name) - } - } -} diff --git a/x/ibc/applications/transfer/types/keys.go b/x/ibc/applications/transfer/types/keys.go deleted file mode 100644 index c156af3fd88d..000000000000 --- a/x/ibc/applications/transfer/types/keys.go +++ /dev/null @@ -1,55 +0,0 @@ -package types - -import ( - "crypto/sha256" - "fmt" - - sdk "github.com/cosmos/cosmos-sdk/types" -) - -const ( - // ModuleName defines the IBC transfer name - ModuleName = "transfer" - - // Version defines the current version the IBC tranfer - // module supports - Version = "ics20-1" - - // PortID is the default port id that transfer module binds to - PortID = "transfer" - - // StoreKey is the store key string for IBC transfer - StoreKey = ModuleName - - // RouterKey is the message route for IBC transfer - RouterKey = ModuleName - - // QuerierRoute is the querier route for IBC transfer - QuerierRoute = ModuleName - - // DenomPrefix is the prefix used for internal SDK coin representation. - DenomPrefix = "ibc" -) - -var ( - // PortKey defines the key to store the port ID in store - PortKey = []byte{0x01} - // DenomTraceKey defines the key to store the denomination trace info in store - DenomTraceKey = []byte{0x02} -) - -// GetEscrowAddress returns the escrow address for the specified channel. -// The escrow address follows the format as outlined in ADR 028: -// https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-028-public-key-addresses.md -func GetEscrowAddress(portID, channelID string) sdk.AccAddress { - // a slash is used to create domain separation between port and channel identifiers to - // prevent address collisions between escrow addresses created for different channels - contents := fmt.Sprintf("%s/%s", portID, channelID) - - // ADR 028 AddressHash construction - preImage := []byte(Version) - preImage = append(preImage, 0) - preImage = append(preImage, contents...) - hash := sha256.Sum256(preImage) - return hash[:20] -} diff --git a/x/ibc/applications/transfer/types/keys_test.go b/x/ibc/applications/transfer/types/keys_test.go deleted file mode 100644 index 9ab3314c2e3b..000000000000 --- a/x/ibc/applications/transfer/types/keys_test.go +++ /dev/null @@ -1,24 +0,0 @@ -package types_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" -) - -// Test that there is domain separation between the port id and the channel id otherwise an -// escrow address may overlap with another channel end -func TestGetEscrowAddress(t *testing.T) { - var ( - port1 = "transfer" - channel1 = "channel" - port2 = "transfercha" - channel2 = "nnel" - ) - - escrow1 := types.GetEscrowAddress(port1, channel1) - escrow2 := types.GetEscrowAddress(port2, channel2) - require.NotEqual(t, escrow1, escrow2) -} diff --git a/x/ibc/applications/transfer/types/msgs.go b/x/ibc/applications/transfer/types/msgs.go deleted file mode 100644 index cf2293213a82..000000000000 --- a/x/ibc/applications/transfer/types/msgs.go +++ /dev/null @@ -1,85 +0,0 @@ -package types - -import ( - "strings" - - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" -) - -// msg types -const ( - TypeMsgTransfer = "transfer" -) - -// NewMsgTransfer creates a new MsgTransfer instance -//nolint:interfacer -func NewMsgTransfer( - sourcePort, sourceChannel string, - token sdk.Coin, sender sdk.AccAddress, receiver string, - timeoutHeight clienttypes.Height, timeoutTimestamp uint64, -) *MsgTransfer { - return &MsgTransfer{ - SourcePort: sourcePort, - SourceChannel: sourceChannel, - Token: token, - Sender: sender.String(), - Receiver: receiver, - TimeoutHeight: timeoutHeight, - TimeoutTimestamp: timeoutTimestamp, - } -} - -// Route implements sdk.Msg -func (MsgTransfer) Route() string { - return RouterKey -} - -// Type implements sdk.Msg -func (MsgTransfer) Type() string { - return TypeMsgTransfer -} - -// ValidateBasic performs a basic check of the MsgTransfer fields. -// NOTE: timeout height or timestamp values can be 0 to disable the timeout. -// NOTE: The recipient addresses format is not validated as the format defined by -// the chain is not known to IBC. -func (msg MsgTransfer) ValidateBasic() error { - if err := host.PortIdentifierValidator(msg.SourcePort); err != nil { - return sdkerrors.Wrap(err, "invalid source port ID") - } - if err := host.ChannelIdentifierValidator(msg.SourceChannel); err != nil { - return sdkerrors.Wrap(err, "invalid source channel ID") - } - if !msg.Token.IsValid() { - return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, msg.Token.String()) - } - if !msg.Token.IsPositive() { - return sdkerrors.Wrap(sdkerrors.ErrInsufficientFunds, msg.Token.String()) - } - // NOTE: sender format must be validated as it is required by the GetSigners function. - _, err := sdk.AccAddressFromBech32(msg.Sender) - if err != nil { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err) - } - if strings.TrimSpace(msg.Receiver) == "" { - return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "missing recipient address") - } - return ValidateIBCDenom(msg.Token.Denom) -} - -// GetSignBytes implements sdk.Msg. -func (msg MsgTransfer) GetSignBytes() []byte { - return sdk.MustSortJSON(AminoCdc.MustMarshalJSON(&msg)) -} - -// GetSigners implements sdk.Msg -func (msg MsgTransfer) GetSigners() []sdk.AccAddress { - valAddr, err := sdk.AccAddressFromBech32(msg.Sender) - if err != nil { - panic(err) - } - return []sdk.AccAddress{valAddr} -} diff --git a/x/ibc/applications/transfer/types/msgs_test.go b/x/ibc/applications/transfer/types/msgs_test.go deleted file mode 100644 index 1fc70c543bbe..000000000000 --- a/x/ibc/applications/transfer/types/msgs_test.go +++ /dev/null @@ -1,103 +0,0 @@ -package types - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - sdk "github.com/cosmos/cosmos-sdk/types" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" -) - -// define constants used for testing -const ( - validPort = "testportid" - invalidPort = "(invalidport1)" - invalidShortPort = "p" - invalidLongPort = "invalidlongportinvalidlongportinvalidlongportinvalidlongportinvalid" - - validChannel = "testchannel" - invalidChannel = "(invalidchannel1)" - invalidShortChannel = "invalid" - invalidLongChannel = "invalidlongchannelinvalidlongchannelinvalidlongchannelinvalidlongchannel" -) - -var ( - addr1 = sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address()) - addr2 = sdk.AccAddress("testaddr2").String() - emptyAddr sdk.AccAddress - - coin = sdk.NewCoin("atom", sdk.NewInt(100)) - ibcCoin = sdk.NewCoin("ibc/7F1D3FCF4AE79E1554D670D1AD949A9BA4E4A3C76C63093E17E446A46061A7A2", sdk.NewInt(100)) - invalidIBCCoin = sdk.NewCoin("notibc/7F1D3FCF4AE79E1554D670D1AD949A9BA4E4A3C76C63093E17E446A46061A7A2", sdk.NewInt(100)) - invalidDenomCoin = sdk.Coin{Denom: "0atom", Amount: sdk.NewInt(100)} - zeroCoin = sdk.Coin{Denom: "atoms", Amount: sdk.NewInt(0)} - - timeoutHeight = clienttypes.NewHeight(0, 10) -) - -// TestMsgTransferRoute tests Route for MsgTransfer -func TestMsgTransferRoute(t *testing.T) { - msg := NewMsgTransfer(validPort, validChannel, coin, addr1, addr2, timeoutHeight, 0) - - require.Equal(t, RouterKey, msg.Route()) -} - -// TestMsgTransferType tests Type for MsgTransfer -func TestMsgTransferType(t *testing.T) { - msg := NewMsgTransfer(validPort, validChannel, coin, addr1, addr2, timeoutHeight, 0) - - 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 { - name string - msg *MsgTransfer - expPass bool - }{ - {"valid msg with base denom", NewMsgTransfer(validPort, validChannel, coin, addr1, addr2, timeoutHeight, 0), true}, - {"valid msg with trace hash", NewMsgTransfer(validPort, validChannel, ibcCoin, addr1, addr2, timeoutHeight, 0), true}, - {"invalid ibc denom", NewMsgTransfer(validPort, validChannel, invalidIBCCoin, addr1, addr2, timeoutHeight, 0), false}, - {"too short port id", NewMsgTransfer(invalidShortPort, validChannel, coin, addr1, addr2, timeoutHeight, 0), false}, - {"too long port id", NewMsgTransfer(invalidLongPort, validChannel, coin, addr1, addr2, timeoutHeight, 0), false}, - {"port id contains non-alpha", NewMsgTransfer(invalidPort, validChannel, coin, addr1, addr2, timeoutHeight, 0), false}, - {"too short channel id", NewMsgTransfer(validPort, invalidShortChannel, coin, addr1, addr2, timeoutHeight, 0), false}, - {"too long channel id", NewMsgTransfer(validPort, invalidLongChannel, coin, addr1, addr2, timeoutHeight, 0), false}, - {"channel id contains non-alpha", NewMsgTransfer(validPort, invalidChannel, coin, addr1, addr2, timeoutHeight, 0), false}, - {"invalid denom", NewMsgTransfer(validPort, validChannel, invalidDenomCoin, addr1, addr2, timeoutHeight, 0), false}, - {"zero coin", NewMsgTransfer(validPort, validChannel, zeroCoin, addr1, addr2, timeoutHeight, 0), false}, - {"missing sender address", NewMsgTransfer(validPort, validChannel, coin, emptyAddr, addr2, timeoutHeight, 0), false}, - {"missing recipient address", NewMsgTransfer(validPort, validChannel, coin, addr1, "", timeoutHeight, 0), false}, - {"empty coin", NewMsgTransfer(validPort, validChannel, sdk.Coin{}, addr1, addr2, timeoutHeight, 0), false}, - } - - for i, tc := range testCases { - err := tc.msg.ValidateBasic() - if tc.expPass { - require.NoError(t, err, "valid test case %d failed: %s", i, tc.name) - } else { - require.Error(t, err, "invalid test case %d passed: %s", i, tc.name) - } - } -} - -// TestMsgTransferGetSigners tests GetSigners for MsgTransfer -func TestMsgTransferGetSigners(t *testing.T) { - msg := NewMsgTransfer(validPort, validChannel, coin, addr1, addr2, timeoutHeight, 0) - res := msg.GetSigners() - - require.Equal(t, []sdk.AccAddress{addr1}, res) -} diff --git a/x/ibc/applications/transfer/types/packet.go b/x/ibc/applications/transfer/types/packet.go deleted file mode 100644 index d726577f6f5c..000000000000 --- a/x/ibc/applications/transfer/types/packet.go +++ /dev/null @@ -1,56 +0,0 @@ -package types - -import ( - "strings" - "time" - - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" -) - -var ( - // DefaultRelativePacketTimeoutHeight is the default packet timeout height (in blocks) relative - // to the current block height of the counterparty chain provided by the client state. The - // timeout is disabled when set to 0. - DefaultRelativePacketTimeoutHeight = "0-1000" - - // DefaultRelativePacketTimeoutTimestamp is the default packet timeout timestamp (in nanoseconds) - // relative to the current block timestamp of the counterparty chain provided by the client - // state. The timeout is disabled when set to 0. The default is currently set to a 10 minute - // timeout. - DefaultRelativePacketTimeoutTimestamp = uint64((time.Duration(10) * time.Minute).Nanoseconds()) -) - -// NewFungibleTokenPacketData contructs a new FungibleTokenPacketData instance -func NewFungibleTokenPacketData( - denom string, amount uint64, - sender, receiver string, -) FungibleTokenPacketData { - return FungibleTokenPacketData{ - Denom: denom, - Amount: amount, - Sender: sender, - Receiver: receiver, - } -} - -// ValidateBasic is used for validating the token transfer. -// NOTE: The addresses formats are not validated as the sender and recipient can have different -// formats defined by their corresponding chains that are not known to IBC. -func (ftpd FungibleTokenPacketData) ValidateBasic() error { - if ftpd.Amount == 0 { - return sdkerrors.Wrap(ErrInvalidAmount, "amount cannot be 0") - } - if strings.TrimSpace(ftpd.Sender) == "" { - return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "sender address cannot be blank") - } - if strings.TrimSpace(ftpd.Receiver) == "" { - return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "receiver address cannot be blank") - } - return ValidatePrefixedDenom(ftpd.Denom) -} - -// GetBytes is a helper for serialising -func (ftpd FungibleTokenPacketData) GetBytes() []byte { - return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&ftpd)) -} diff --git a/x/ibc/applications/transfer/types/packet_test.go b/x/ibc/applications/transfer/types/packet_test.go deleted file mode 100644 index 1edcb093d3c0..000000000000 --- a/x/ibc/applications/transfer/types/packet_test.go +++ /dev/null @@ -1,36 +0,0 @@ -package types - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -const ( - denom = "transfer/gaiachannel/atom" - amount = uint64(100) -) - -// TestFungibleTokenPacketDataValidateBasic tests ValidateBasic for FungibleTokenPacketData -func TestFungibleTokenPacketDataValidateBasic(t *testing.T) { - testCases := []struct { - name string - packetData FungibleTokenPacketData - expPass bool - }{ - {"valid packet", NewFungibleTokenPacketData(denom, amount, addr1.String(), addr2), true}, - {"invalid denom", NewFungibleTokenPacketData("", amount, addr1.String(), addr2), false}, - {"invalid amount", NewFungibleTokenPacketData(denom, 0, addr1.String(), addr2), false}, - {"missing sender address", NewFungibleTokenPacketData(denom, amount, emptyAddr.String(), addr2), false}, - {"missing recipient address", NewFungibleTokenPacketData(denom, amount, addr1.String(), emptyAddr.String()), false}, - } - - for i, tc := range testCases { - err := tc.packetData.ValidateBasic() - if tc.expPass { - require.NoError(t, err, "valid test case %d failed: %v", i, err) - } else { - require.Error(t, err, "invalid test case %d passed: %s", i, tc.name) - } - } -} diff --git a/x/ibc/applications/transfer/types/params.go b/x/ibc/applications/transfer/types/params.go deleted file mode 100644 index 4ecdfab77e7b..000000000000 --- a/x/ibc/applications/transfer/types/params.go +++ /dev/null @@ -1,65 +0,0 @@ -package types - -import ( - "fmt" - - paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" -) - -const ( - // DefaultSendEnabled enabled - DefaultSendEnabled = true - // DefaultReceiveEnabled enabled - DefaultReceiveEnabled = true -) - -var ( - // KeySendEnabled is store's key for SendEnabled Params - KeySendEnabled = []byte("SendEnabled") - // KeyReceiveEnabled is store's key for ReceiveEnabled Params - KeyReceiveEnabled = []byte("ReceiveEnabled") -) - -// ParamKeyTable type declaration for parameters -func ParamKeyTable() paramtypes.KeyTable { - return paramtypes.NewKeyTable().RegisterParamSet(&Params{}) -} - -// NewParams creates a new parameter configuration for the ibc transfer module -func NewParams(enableSend, enableReceive bool) Params { - return Params{ - SendEnabled: enableSend, - ReceiveEnabled: enableReceive, - } -} - -// DefaultParams is the default parameter configuration for the ibc-transfer module -func DefaultParams() Params { - return NewParams(DefaultSendEnabled, DefaultReceiveEnabled) -} - -// Validate all ibc-transfer module parameters -func (p Params) Validate() error { - if err := validateEnabled(p.SendEnabled); err != nil { - return err - } - - return validateEnabled(p.ReceiveEnabled) -} - -// ParamSetPairs implements params.ParamSet -func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { - return paramtypes.ParamSetPairs{ - paramtypes.NewParamSetPair(KeySendEnabled, p.SendEnabled, validateEnabled), - paramtypes.NewParamSetPair(KeyReceiveEnabled, p.ReceiveEnabled, validateEnabled), - } -} - -func validateEnabled(i interface{}) error { - _, ok := i.(bool) - if !ok { - return fmt.Errorf("invalid parameter type: %T", i) - } - - return nil -} diff --git a/x/ibc/applications/transfer/types/params_test.go b/x/ibc/applications/transfer/types/params_test.go deleted file mode 100644 index 825efb825c1b..000000000000 --- a/x/ibc/applications/transfer/types/params_test.go +++ /dev/null @@ -1,12 +0,0 @@ -package types - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func TestValidateParams(t *testing.T) { - require.NoError(t, DefaultParams().Validate()) - require.NoError(t, NewParams(true, false).Validate()) -} diff --git a/x/ibc/applications/transfer/types/query.pb.go b/x/ibc/applications/transfer/types/query.pb.go deleted file mode 100644 index 1c1d69295192..000000000000 --- a/x/ibc/applications/transfer/types/query.pb.go +++ /dev/null @@ -1,1418 +0,0 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: ibc/applications/transfer/v1/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 - -// QueryDenomTraceRequest is the request type for the Query/DenomTrace RPC -// method -type QueryDenomTraceRequest struct { - // hash (in hex format) of the denomination trace information. - Hash string `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` -} - -func (m *QueryDenomTraceRequest) Reset() { *m = QueryDenomTraceRequest{} } -func (m *QueryDenomTraceRequest) String() string { return proto.CompactTextString(m) } -func (*QueryDenomTraceRequest) ProtoMessage() {} -func (*QueryDenomTraceRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_a638e2800a01538c, []int{0} -} -func (m *QueryDenomTraceRequest) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryDenomTraceRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryDenomTraceRequest.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 *QueryDenomTraceRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryDenomTraceRequest.Merge(m, src) -} -func (m *QueryDenomTraceRequest) XXX_Size() int { - return m.Size() -} -func (m *QueryDenomTraceRequest) XXX_DiscardUnknown() { - xxx_messageInfo_QueryDenomTraceRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryDenomTraceRequest proto.InternalMessageInfo - -func (m *QueryDenomTraceRequest) GetHash() string { - if m != nil { - return m.Hash - } - return "" -} - -// QueryDenomTraceResponse is the response type for the Query/DenomTrace RPC -// method. -type QueryDenomTraceResponse struct { - // denom_trace returns the requested denomination trace information. - DenomTrace *DenomTrace `protobuf:"bytes,1,opt,name=denom_trace,json=denomTrace,proto3" json:"denom_trace,omitempty"` -} - -func (m *QueryDenomTraceResponse) Reset() { *m = QueryDenomTraceResponse{} } -func (m *QueryDenomTraceResponse) String() string { return proto.CompactTextString(m) } -func (*QueryDenomTraceResponse) ProtoMessage() {} -func (*QueryDenomTraceResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_a638e2800a01538c, []int{1} -} -func (m *QueryDenomTraceResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryDenomTraceResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryDenomTraceResponse.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 *QueryDenomTraceResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryDenomTraceResponse.Merge(m, src) -} -func (m *QueryDenomTraceResponse) XXX_Size() int { - return m.Size() -} -func (m *QueryDenomTraceResponse) XXX_DiscardUnknown() { - xxx_messageInfo_QueryDenomTraceResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryDenomTraceResponse proto.InternalMessageInfo - -func (m *QueryDenomTraceResponse) GetDenomTrace() *DenomTrace { - if m != nil { - return m.DenomTrace - } - return nil -} - -// QueryConnectionsRequest is the request type for the Query/DenomTraces RPC -// method -type QueryDenomTracesRequest struct { - // pagination defines an optional pagination for the request. - Pagination *query.PageRequest `protobuf:"bytes,1,opt,name=pagination,proto3" json:"pagination,omitempty"` -} - -func (m *QueryDenomTracesRequest) Reset() { *m = QueryDenomTracesRequest{} } -func (m *QueryDenomTracesRequest) String() string { return proto.CompactTextString(m) } -func (*QueryDenomTracesRequest) ProtoMessage() {} -func (*QueryDenomTracesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_a638e2800a01538c, []int{2} -} -func (m *QueryDenomTracesRequest) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryDenomTracesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryDenomTracesRequest.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 *QueryDenomTracesRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryDenomTracesRequest.Merge(m, src) -} -func (m *QueryDenomTracesRequest) XXX_Size() int { - return m.Size() -} -func (m *QueryDenomTracesRequest) XXX_DiscardUnknown() { - xxx_messageInfo_QueryDenomTracesRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryDenomTracesRequest proto.InternalMessageInfo - -func (m *QueryDenomTracesRequest) GetPagination() *query.PageRequest { - if m != nil { - return m.Pagination - } - return nil -} - -// QueryConnectionsResponse is the response type for the Query/DenomTraces RPC -// method. -type QueryDenomTracesResponse struct { - // denom_traces returns all denominations trace information. - DenomTraces Traces `protobuf:"bytes,1,rep,name=denom_traces,json=denomTraces,proto3,castrepeated=Traces" json:"denom_traces"` - // pagination defines the pagination in the response. - Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` -} - -func (m *QueryDenomTracesResponse) Reset() { *m = QueryDenomTracesResponse{} } -func (m *QueryDenomTracesResponse) String() string { return proto.CompactTextString(m) } -func (*QueryDenomTracesResponse) ProtoMessage() {} -func (*QueryDenomTracesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_a638e2800a01538c, []int{3} -} -func (m *QueryDenomTracesResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryDenomTracesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryDenomTracesResponse.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 *QueryDenomTracesResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryDenomTracesResponse.Merge(m, src) -} -func (m *QueryDenomTracesResponse) XXX_Size() int { - return m.Size() -} -func (m *QueryDenomTracesResponse) XXX_DiscardUnknown() { - xxx_messageInfo_QueryDenomTracesResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryDenomTracesResponse proto.InternalMessageInfo - -func (m *QueryDenomTracesResponse) GetDenomTraces() Traces { - if m != nil { - return m.DenomTraces - } - return nil -} - -func (m *QueryDenomTracesResponse) GetPagination() *query.PageResponse { - if m != nil { - return m.Pagination - } - return nil -} - -// QueryParamsRequest is the request type for the Query/Params RPC method. -type QueryParamsRequest struct { -} - -func (m *QueryParamsRequest) Reset() { *m = QueryParamsRequest{} } -func (m *QueryParamsRequest) String() string { return proto.CompactTextString(m) } -func (*QueryParamsRequest) ProtoMessage() {} -func (*QueryParamsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_a638e2800a01538c, []int{4} -} -func (m *QueryParamsRequest) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryParamsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryParamsRequest.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 *QueryParamsRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryParamsRequest.Merge(m, src) -} -func (m *QueryParamsRequest) XXX_Size() int { - return m.Size() -} -func (m *QueryParamsRequest) XXX_DiscardUnknown() { - xxx_messageInfo_QueryParamsRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryParamsRequest proto.InternalMessageInfo - -// QueryParamsResponse is the response type for the Query/Params RPC method. -type QueryParamsResponse struct { - // params defines the parameters of the module. - Params *Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params,omitempty"` -} - -func (m *QueryParamsResponse) Reset() { *m = QueryParamsResponse{} } -func (m *QueryParamsResponse) String() string { return proto.CompactTextString(m) } -func (*QueryParamsResponse) ProtoMessage() {} -func (*QueryParamsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_a638e2800a01538c, []int{5} -} -func (m *QueryParamsResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryParamsResponse.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 *QueryParamsResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryParamsResponse.Merge(m, src) -} -func (m *QueryParamsResponse) XXX_Size() int { - return m.Size() -} -func (m *QueryParamsResponse) XXX_DiscardUnknown() { - xxx_messageInfo_QueryParamsResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryParamsResponse proto.InternalMessageInfo - -func (m *QueryParamsResponse) GetParams() *Params { - if m != nil { - return m.Params - } - return nil -} - -func init() { - proto.RegisterType((*QueryDenomTraceRequest)(nil), "ibc.applications.transfer.v1.QueryDenomTraceRequest") - proto.RegisterType((*QueryDenomTraceResponse)(nil), "ibc.applications.transfer.v1.QueryDenomTraceResponse") - proto.RegisterType((*QueryDenomTracesRequest)(nil), "ibc.applications.transfer.v1.QueryDenomTracesRequest") - proto.RegisterType((*QueryDenomTracesResponse)(nil), "ibc.applications.transfer.v1.QueryDenomTracesResponse") - proto.RegisterType((*QueryParamsRequest)(nil), "ibc.applications.transfer.v1.QueryParamsRequest") - proto.RegisterType((*QueryParamsResponse)(nil), "ibc.applications.transfer.v1.QueryParamsResponse") -} - -func init() { - proto.RegisterFile("ibc/applications/transfer/v1/query.proto", fileDescriptor_a638e2800a01538c) -} - -var fileDescriptor_a638e2800a01538c = []byte{ - // 528 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0x3f, 0x6f, 0xd3, 0x40, - 0x14, 0xcf, 0x95, 0x12, 0x89, 0x17, 0xc4, 0x70, 0x54, 0x10, 0x59, 0x95, 0x5b, 0x59, 0x08, 0x02, - 0x85, 0x3b, 0x5c, 0xa0, 0x30, 0xa0, 0x0e, 0x15, 0x02, 0xb1, 0x95, 0xc0, 0x80, 0x60, 0x40, 0x67, - 0xe7, 0x70, 0x2c, 0x1a, 0x9f, 0xeb, 0xbb, 0x44, 0x54, 0x88, 0x85, 0x4f, 0x80, 0xc4, 0x8e, 0x98, - 0xd9, 0x19, 0xd8, 0x18, 0x3b, 0x56, 0x62, 0x61, 0x02, 0x94, 0xf0, 0x41, 0x90, 0xef, 0xce, 0x8d, - 0xa3, 0x20, 0x13, 0x4f, 0x39, 0x5d, 0xde, 0xef, 0xfd, 0xfe, 0xbc, 0xe7, 0x83, 0x4e, 0x1c, 0x84, - 0x94, 0xa5, 0xe9, 0x5e, 0x1c, 0x32, 0x15, 0x8b, 0x44, 0x52, 0x95, 0xb1, 0x44, 0xbe, 0xe4, 0x19, - 0x1d, 0xf9, 0x74, 0x7f, 0xc8, 0xb3, 0x03, 0x92, 0x66, 0x42, 0x09, 0xbc, 0x1a, 0x07, 0x21, 0x29, - 0x57, 0x92, 0xa2, 0x92, 0x8c, 0x7c, 0x67, 0x25, 0x12, 0x91, 0xd0, 0x85, 0x34, 0x3f, 0x19, 0x8c, - 0x73, 0x25, 0x14, 0x72, 0x20, 0x24, 0x0d, 0x98, 0xe4, 0xa6, 0x19, 0x1d, 0xf9, 0x01, 0x57, 0xcc, - 0xa7, 0x29, 0x8b, 0xe2, 0x44, 0x37, 0xb2, 0xb5, 0x1b, 0x95, 0x4a, 0x8e, 0xb9, 0x4c, 0xf1, 0x6a, - 0x24, 0x44, 0xb4, 0xc7, 0x29, 0x4b, 0x63, 0xca, 0x92, 0x44, 0x28, 0x2b, 0x49, 0xff, 0xeb, 0x5d, - 0x85, 0x73, 0x8f, 0x72, 0xb2, 0x7b, 0x3c, 0x11, 0x83, 0x27, 0x19, 0x0b, 0x79, 0x97, 0xef, 0x0f, - 0xb9, 0x54, 0x18, 0xc3, 0x72, 0x9f, 0xc9, 0x7e, 0x1b, 0xad, 0xa3, 0xce, 0xa9, 0xae, 0x3e, 0x7b, - 0x3d, 0x38, 0x3f, 0x57, 0x2d, 0x53, 0x91, 0x48, 0x8e, 0x1f, 0x42, 0xab, 0x97, 0xdf, 0xbe, 0x50, - 0xf9, 0xb5, 0x46, 0xb5, 0x36, 0x3b, 0xa4, 0x2a, 0x09, 0x52, 0x6a, 0x03, 0xbd, 0xe3, 0xb3, 0xc7, - 0xe6, 0x58, 0x64, 0x21, 0xea, 0x3e, 0xc0, 0x34, 0x0d, 0x4b, 0x72, 0x91, 0x98, 0xe8, 0x48, 0x1e, - 0x1d, 0x31, 0x73, 0xb0, 0xd1, 0x91, 0x5d, 0x16, 0x15, 0x86, 0xba, 0x25, 0xa4, 0xf7, 0x0d, 0x41, - 0x7b, 0x9e, 0xc3, 0x5a, 0x79, 0x0e, 0xa7, 0x4b, 0x56, 0x64, 0x1b, 0xad, 0x9f, 0xa8, 0xe3, 0x65, - 0xe7, 0xcc, 0xe1, 0xcf, 0xb5, 0xc6, 0xe7, 0x5f, 0x6b, 0x4d, 0xdb, 0xb7, 0x35, 0xf5, 0x26, 0xf1, - 0x83, 0x19, 0x07, 0x4b, 0xda, 0xc1, 0xa5, 0xff, 0x3a, 0x30, 0xca, 0x66, 0x2c, 0xac, 0x00, 0xd6, - 0x0e, 0x76, 0x59, 0xc6, 0x06, 0x45, 0x40, 0xde, 0x63, 0x38, 0x3b, 0x73, 0x6b, 0x2d, 0xdd, 0x85, - 0x66, 0xaa, 0x6f, 0x6c, 0x66, 0x17, 0xaa, 0xcd, 0x58, 0xb4, 0xc5, 0x6c, 0x7e, 0x5c, 0x86, 0x93, - 0xba, 0x2b, 0xfe, 0x8a, 0x00, 0xa6, 0x4e, 0xf1, 0xcd, 0xea, 0x36, 0xff, 0xde, 0x2c, 0xe7, 0x56, - 0x4d, 0x94, 0xf1, 0xe0, 0x6d, 0xbf, 0xfb, 0xfe, 0xe7, 0xc3, 0xd2, 0x1d, 0xbc, 0x45, 0xab, 0xd6, - 0xdf, 0x7c, 0x32, 0xe5, 0xf9, 0xd1, 0x37, 0xf9, 0xee, 0xbe, 0xc5, 0x5f, 0x10, 0xb4, 0x4a, 0xe3, - 0xc6, 0xf5, 0x64, 0x14, 0x09, 0x3b, 0x5b, 0x75, 0x61, 0x56, 0xfe, 0x6d, 0x2d, 0xdf, 0xc7, 0xb4, - 0xa6, 0x7c, 0xfc, 0x09, 0x41, 0xd3, 0x0c, 0x04, 0x5f, 0x5f, 0x80, 0x7b, 0x66, 0x1f, 0x1c, 0xbf, - 0x06, 0xc2, 0x0a, 0xf5, 0xb5, 0xd0, 0x0d, 0x7c, 0x79, 0x01, 0xa1, 0x66, 0x41, 0x76, 0x9e, 0x1e, - 0x8e, 0x5d, 0x74, 0x34, 0x76, 0xd1, 0xef, 0xb1, 0x8b, 0xde, 0x4f, 0xdc, 0xc6, 0xd1, 0xc4, 0x6d, - 0xfc, 0x98, 0xb8, 0x8d, 0x67, 0xdb, 0x51, 0xac, 0xfa, 0xc3, 0x80, 0x84, 0x62, 0x40, 0xed, 0x0b, - 0x67, 0x7e, 0xae, 0xc9, 0xde, 0x2b, 0xfa, 0xba, 0x82, 0x42, 0x1d, 0xa4, 0x5c, 0x06, 0x4d, 0xfd, - 0x4c, 0xdd, 0xf8, 0x1b, 0x00, 0x00, 0xff, 0xff, 0xb2, 0x7f, 0xfe, 0xbd, 0x7d, 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 { - // DenomTrace queries a denomination trace information. - DenomTrace(ctx context.Context, in *QueryDenomTraceRequest, opts ...grpc.CallOption) (*QueryDenomTraceResponse, error) - // DenomTraces queries all denomination traces. - DenomTraces(ctx context.Context, in *QueryDenomTracesRequest, opts ...grpc.CallOption) (*QueryDenomTracesResponse, error) - // Params queries all parameters of the ibc-transfer module. - Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) -} - -type queryClient struct { - cc grpc1.ClientConn -} - -func NewQueryClient(cc grpc1.ClientConn) QueryClient { - return &queryClient{cc} -} - -func (c *queryClient) DenomTrace(ctx context.Context, in *QueryDenomTraceRequest, opts ...grpc.CallOption) (*QueryDenomTraceResponse, error) { - out := new(QueryDenomTraceResponse) - err := c.cc.Invoke(ctx, "/ibc.applications.transfer.v1.Query/DenomTrace", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *queryClient) DenomTraces(ctx context.Context, in *QueryDenomTracesRequest, opts ...grpc.CallOption) (*QueryDenomTracesResponse, error) { - out := new(QueryDenomTracesResponse) - err := c.cc.Invoke(ctx, "/ibc.applications.transfer.v1.Query/DenomTraces", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) { - out := new(QueryParamsResponse) - err := c.cc.Invoke(ctx, "/ibc.applications.transfer.v1.Query/Params", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// QueryServer is the server API for Query service. -type QueryServer interface { - // DenomTrace queries a denomination trace information. - DenomTrace(context.Context, *QueryDenomTraceRequest) (*QueryDenomTraceResponse, error) - // DenomTraces queries all denomination traces. - DenomTraces(context.Context, *QueryDenomTracesRequest) (*QueryDenomTracesResponse, error) - // Params queries all parameters of the ibc-transfer module. - Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error) -} - -// UnimplementedQueryServer can be embedded to have forward compatible implementations. -type UnimplementedQueryServer struct { -} - -func (*UnimplementedQueryServer) DenomTrace(ctx context.Context, req *QueryDenomTraceRequest) (*QueryDenomTraceResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method DenomTrace not implemented") -} -func (*UnimplementedQueryServer) DenomTraces(ctx context.Context, req *QueryDenomTracesRequest) (*QueryDenomTracesResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method DenomTraces not implemented") -} -func (*UnimplementedQueryServer) Params(ctx context.Context, req *QueryParamsRequest) (*QueryParamsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method Params not implemented") -} - -func RegisterQueryServer(s grpc1.Server, srv QueryServer) { - s.RegisterService(&_Query_serviceDesc, srv) -} - -func _Query_DenomTrace_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryDenomTraceRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(QueryServer).DenomTrace(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.applications.transfer.v1.Query/DenomTrace", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).DenomTrace(ctx, req.(*QueryDenomTraceRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Query_DenomTraces_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryDenomTracesRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(QueryServer).DenomTraces(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.applications.transfer.v1.Query/DenomTraces", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).DenomTraces(ctx, req.(*QueryDenomTracesRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Query_Params_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryParamsRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(QueryServer).Params(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.applications.transfer.v1.Query/Params", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).Params(ctx, req.(*QueryParamsRequest)) - } - return interceptor(ctx, in, info, handler) -} - -var _Query_serviceDesc = grpc.ServiceDesc{ - ServiceName: "ibc.applications.transfer.v1.Query", - HandlerType: (*QueryServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "DenomTrace", - Handler: _Query_DenomTrace_Handler, - }, - { - MethodName: "DenomTraces", - Handler: _Query_DenomTraces_Handler, - }, - { - MethodName: "Params", - Handler: _Query_Params_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "ibc/applications/transfer/v1/query.proto", -} - -func (m *QueryDenomTraceRequest) 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 *QueryDenomTraceRequest) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryDenomTraceRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Hash) > 0 { - i -= len(m.Hash) - copy(dAtA[i:], m.Hash) - i = encodeVarintQuery(dAtA, i, uint64(len(m.Hash))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *QueryDenomTraceResponse) 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 *QueryDenomTraceResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryDenomTraceResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.DenomTrace != nil { - { - size, err := m.DenomTrace.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 *QueryDenomTracesRequest) 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 *QueryDenomTracesRequest) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryDenomTracesRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.Pagination != nil { - { - size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *QueryDenomTracesResponse) 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 *QueryDenomTracesResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryDenomTracesResponse) 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.DenomTraces) > 0 { - for iNdEx := len(m.DenomTraces) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.DenomTraces[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 *QueryParamsRequest) 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 *QueryParamsRequest) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryParamsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - return len(dAtA) - i, nil -} - -func (m *QueryParamsResponse) 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 *QueryParamsResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.Params != nil { - { - size, err := m.Params.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 *QueryDenomTraceRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Hash) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - return n -} - -func (m *QueryDenomTraceResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.DenomTrace != nil { - l = m.DenomTrace.Size() - n += 1 + l + sovQuery(uint64(l)) - } - return n -} - -func (m *QueryDenomTracesRequest) 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 *QueryDenomTracesResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if len(m.DenomTraces) > 0 { - for _, e := range m.DenomTraces { - 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 *QueryParamsRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - return n -} - -func (m *QueryParamsResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.Params != nil { - l = m.Params.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 *QueryDenomTraceRequest) 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: QueryDenomTraceRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryDenomTraceRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Hash", 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.Hash = 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 *QueryDenomTraceResponse) 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: QueryDenomTraceResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryDenomTraceResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field DenomTrace", 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.DenomTrace == nil { - m.DenomTrace = &DenomTrace{} - } - if err := m.DenomTrace.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 *QueryDenomTracesRequest) 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: QueryDenomTracesRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryDenomTracesRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.Pagination == nil { - m.Pagination = &query.PageRequest{} - } - if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipQuery(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *QueryDenomTracesResponse) 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: QueryDenomTracesResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryDenomTracesResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field DenomTraces", 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.DenomTraces = append(m.DenomTraces, DenomTrace{}) - if err := m.DenomTraces[len(m.DenomTraces)-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 *QueryParamsRequest) 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: QueryParamsRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryParamsRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - 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 *QueryParamsResponse) 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: QueryParamsResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - 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 Params", 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.Params == nil { - m.Params = &Params{} - } - if err := m.Params.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/ibc/applications/transfer/types/query.pb.gw.go b/x/ibc/applications/transfer/types/query.pb.gw.go deleted file mode 100644 index 007ed6682074..000000000000 --- a/x/ibc/applications/transfer/types/query.pb.gw.go +++ /dev/null @@ -1,326 +0,0 @@ -// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. -// source: ibc/applications/transfer/v1/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_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 - 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 := client.DenomTrace(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -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)} -) - -func request_Query_DenomTraces_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, 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 := client.DenomTraces(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -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 - - msg, err := client.Params(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -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) { - 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_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.AnnotateContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Query_DenomTrace_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_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.AnnotateContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Query_DenomTraces_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_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.AnnotateContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Query_Params_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_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - return nil -} - -var ( - pattern_Query_DenomTrace_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"ibc", "applications", "transfer", "v1beta1", "denom_traces", "hash"}, "", runtime.AssumeColonVerbOpt(false))) - - pattern_Query_DenomTraces_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"ibc", "applications", "transfer", "v1beta1", "denom_traces"}, "", runtime.AssumeColonVerbOpt(false))) - - pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"ibc", "applications", "transfer", "v1beta1", "params"}, "", runtime.AssumeColonVerbOpt(false))) -) - -var ( - forward_Query_DenomTrace_0 = runtime.ForwardResponseMessage - - forward_Query_DenomTraces_0 = runtime.ForwardResponseMessage - - forward_Query_Params_0 = runtime.ForwardResponseMessage -) diff --git a/x/ibc/applications/transfer/types/trace.go b/x/ibc/applications/transfer/types/trace.go deleted file mode 100644 index f45113efa3ff..000000000000 --- a/x/ibc/applications/transfer/types/trace.go +++ /dev/null @@ -1,203 +0,0 @@ -package types - -import ( - "crypto/sha256" - "encoding/hex" - "fmt" - "sort" - "strings" - - tmbytes "github.com/tendermint/tendermint/libs/bytes" - tmtypes "github.com/tendermint/tendermint/types" - - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" -) - -// ParseDenomTrace parses a string with the ibc prefix (denom trace) and the base denomination -// into a DenomTrace type. -// -// Examples: -// -// - "portidone/channelidone/uatom" => DenomTrace{Path: "portidone/channelidone", BaseDenom: "uatom"} -// - "uatom" => DenomTrace{Path: "", BaseDenom: "uatom"} -func ParseDenomTrace(rawDenom string) DenomTrace { - denomSplit := strings.Split(rawDenom, "/") - - if denomSplit[0] == rawDenom { - return DenomTrace{ - Path: "", - BaseDenom: rawDenom, - } - } - - return DenomTrace{ - Path: strings.Join(denomSplit[:len(denomSplit)-1], "/"), - BaseDenom: denomSplit[len(denomSplit)-1], - } -} - -// Hash returns the hex bytes of the SHA256 hash of the DenomTrace fields using the following formula: -// -// hash = sha256(tracePath + "/" + baseDenom) -func (dt DenomTrace) Hash() tmbytes.HexBytes { - hash := sha256.Sum256([]byte(dt.GetFullDenomPath())) - return hash[:] -} - -// GetPrefix returns the receiving denomination prefix composed by the trace info and a separator. -func (dt DenomTrace) GetPrefix() string { - return dt.Path + "/" -} - -// IBCDenom a coin denomination for an ICS20 fungible token in the format -// 'ibc/{hash(tracePath + baseDenom)}'. If the trace is empty, it will return the base denomination. -func (dt DenomTrace) IBCDenom() string { - if dt.Path != "" { - return fmt.Sprintf("%s/%s", DenomPrefix, dt.Hash()) - } - return dt.BaseDenom -} - -// GetFullDenomPath returns the full denomination according to the ICS20 specification: -// tracePath + "/" + baseDenom -// If there exists no trace then the base denomination is returned. -func (dt DenomTrace) GetFullDenomPath() string { - if dt.Path == "" { - return dt.BaseDenom - } - return dt.GetPrefix() + dt.BaseDenom -} - -func validateTraceIdentifiers(identifiers []string) error { - if len(identifiers) == 0 || len(identifiers)%2 != 0 { - return fmt.Errorf("trace info must come in pairs of port and channel identifiers '{portID}/{channelID}', got the identifiers: %s", identifiers) - } - - // validate correctness of port and channel identifiers - for i := 0; i < len(identifiers); i += 2 { - if err := host.PortIdentifierValidator(identifiers[i]); err != nil { - return sdkerrors.Wrapf(err, "invalid port ID at position %d", i) - } - if err := host.ChannelIdentifierValidator(identifiers[i+1]); err != nil { - return sdkerrors.Wrapf(err, "invalid channel ID at position %d", i) - } - } - return nil -} - -// Validate performs a basic validation of the DenomTrace fields. -func (dt DenomTrace) Validate() error { - // empty trace is accepted when token lives on the original chain - switch { - case dt.Path == "" && dt.BaseDenom != "": - return nil - case strings.TrimSpace(dt.BaseDenom) == "": - return fmt.Errorf("base denomination cannot be blank") - } - - // NOTE: no base denomination validation - - identifiers := strings.Split(dt.Path, "/") - return validateTraceIdentifiers(identifiers) -} - -// Traces defines a wrapper type for a slice of DenomTrace. -type Traces []DenomTrace - -// Validate performs a basic validation of each denomination trace info. -func (t Traces) Validate() error { - seenTraces := make(map[string]bool) - for i, trace := range t { - hash := trace.Hash().String() - if seenTraces[hash] { - return fmt.Errorf("duplicated denomination trace with hash %s", trace.Hash()) - } - - if err := trace.Validate(); err != nil { - return sdkerrors.Wrapf(err, "failed denom trace %d validation", i) - } - seenTraces[hash] = true - } - return nil -} - -var _ sort.Interface = Traces{} - -// Len implements sort.Interface for Traces -func (t Traces) Len() int { return len(t) } - -// Less implements sort.Interface for Traces -func (t Traces) Less(i, j int) bool { return t[i].GetFullDenomPath() < t[j].GetFullDenomPath() } - -// Swap implements sort.Interface for Traces -func (t Traces) Swap(i, j int) { t[i], t[j] = t[j], t[i] } - -// Sort is a helper function to sort the set of denomination traces in-place -func (t Traces) Sort() Traces { - sort.Sort(t) - return t -} - -// ValidatePrefixedDenom checks that the denomination for an IBC fungible token packet denom is correctly prefixed. -// The function will return no error if the given string follows one of the two formats: -// -// - Prefixed denomination: '{portIDN}/{channelIDN}/.../{portID0}/{channelID0}/baseDenom' -// - Unprefixed denomination: 'baseDenom' -func ValidatePrefixedDenom(denom string) error { - denomSplit := strings.Split(denom, "/") - if denomSplit[0] == denom && strings.TrimSpace(denom) != "" { - // NOTE: no base denomination validation - return nil - } - - if strings.TrimSpace(denomSplit[len(denomSplit)-1]) == "" { - return sdkerrors.Wrap(ErrInvalidDenomForTransfer, "base denomination cannot be blank") - } - - identifiers := denomSplit[:len(denomSplit)-1] - return validateTraceIdentifiers(identifiers) -} - -// ValidateIBCDenom validates that the given denomination is either: -// -// - A valid base denomination (eg: 'uatom') -// - A valid fungible token representation (i.e 'ibc/{hash}') per ADR 001 https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-001-coin-source-tracing.md -func ValidateIBCDenom(denom string) error { - if err := sdk.ValidateDenom(denom); err != nil { - return err - } - - denomSplit := strings.SplitN(denom, "/", 2) - - switch { - case strings.TrimSpace(denom) == "", - len(denomSplit) == 1 && denomSplit[0] == DenomPrefix, - len(denomSplit) == 2 && (denomSplit[0] != DenomPrefix || strings.TrimSpace(denomSplit[1]) == ""): - return sdkerrors.Wrapf(ErrInvalidDenomForTransfer, "denomination should be prefixed with the format 'ibc/{hash(trace + \"/\" + %s)}'", denom) - - case denomSplit[0] == denom && strings.TrimSpace(denom) != "": - return nil - } - - if _, err := ParseHexHash(denomSplit[1]); err != nil { - return sdkerrors.Wrapf(err, "invalid denom trace hash %s", denomSplit[1]) - } - - return nil -} - -// ParseHexHash parses a hex hash in string format to bytes and validates its correctness. -func ParseHexHash(hexHash string) (tmbytes.HexBytes, error) { - hash, err := hex.DecodeString(hexHash) - if err != nil { - return nil, err - } - - if err := tmtypes.ValidateHash(hash); err != nil { - return nil, err - } - - return hash, nil -} diff --git a/x/ibc/applications/transfer/types/trace_test.go b/x/ibc/applications/transfer/types/trace_test.go deleted file mode 100644 index f0868d5680e5..000000000000 --- a/x/ibc/applications/transfer/types/trace_test.go +++ /dev/null @@ -1,150 +0,0 @@ -package types - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func TestParseDenomTrace(t *testing.T) { - testCases := []struct { - name string - denom string - expTrace DenomTrace - }{ - {"empty denom", "", DenomTrace{}}, - {"base denom", "uatom", DenomTrace{BaseDenom: "uatom"}}, - {"trace info", "transfer/channelToA/uatom", DenomTrace{BaseDenom: "uatom", Path: "transfer/channelToA"}}, - {"incomplete path", "transfer/uatom", DenomTrace{BaseDenom: "uatom", Path: "transfer"}}, - {"invalid path (1)", "transfer//uatom", DenomTrace{BaseDenom: "uatom", Path: "transfer/"}}, - {"invalid path (2)", "transfer/channelToA/uatom/", DenomTrace{BaseDenom: "", Path: "transfer/channelToA/uatom"}}, - } - - for _, tc := range testCases { - trace := ParseDenomTrace(tc.denom) - require.Equal(t, tc.expTrace, trace, tc.name) - } -} - -func TestDenomTrace_IBCDenom(t *testing.T) { - testCases := []struct { - name string - trace DenomTrace - expDenom string - }{ - {"base denom", DenomTrace{BaseDenom: "uatom"}, "uatom"}, - {"trace info", DenomTrace{BaseDenom: "uatom", Path: "transfer/channelToA"}, "ibc/7F1D3FCF4AE79E1554D670D1AD949A9BA4E4A3C76C63093E17E446A46061A7A2"}, - } - - for _, tc := range testCases { - denom := tc.trace.IBCDenom() - require.Equal(t, tc.expDenom, denom, tc.name) - } -} - -func TestDenomTrace_Validate(t *testing.T) { - testCases := []struct { - name string - trace DenomTrace - expError bool - }{ - {"base denom only", DenomTrace{BaseDenom: "uatom"}, false}, - {"empty DenomTrace", DenomTrace{}, true}, - {"valid single trace info", DenomTrace{BaseDenom: "uatom", Path: "transfer/channelToA"}, false}, - {"valid multiple trace info", DenomTrace{BaseDenom: "uatom", Path: "transfer/channelToA/transfer/channelToB"}, false}, - {"single trace identifier", DenomTrace{BaseDenom: "uatom", Path: "transfer"}, true}, - {"invalid port ID", DenomTrace{BaseDenom: "uatom", Path: "(transfer)/channelToA"}, true}, - {"invalid channel ID", DenomTrace{BaseDenom: "uatom", Path: "transfer/(channelToA)"}, true}, - {"empty base denom with trace", DenomTrace{BaseDenom: "", Path: "transfer/channelToA"}, true}, - } - - for _, tc := range testCases { - err := tc.trace.Validate() - if tc.expError { - require.Error(t, err, tc.name) - continue - } - require.NoError(t, err, tc.name) - } -} - -func TestTraces_Validate(t *testing.T) { - testCases := []struct { - name string - traces Traces - expError bool - }{ - {"empty Traces", Traces{}, false}, - {"valid multiple trace info", Traces{{BaseDenom: "uatom", Path: "transfer/channelToA/transfer/channelToB"}}, false}, - { - "valid multiple trace info", - Traces{ - {BaseDenom: "uatom", Path: "transfer/channelToA/transfer/channelToB"}, - {BaseDenom: "uatom", Path: "transfer/channelToA/transfer/channelToB"}, - }, - true, - }, - {"empty base denom with trace", Traces{{BaseDenom: "", Path: "transfer/channelToA"}}, true}, - } - - for _, tc := range testCases { - err := tc.traces.Validate() - if tc.expError { - require.Error(t, err, tc.name) - continue - } - require.NoError(t, err, tc.name) - } -} - -func TestValidatePrefixedDenom(t *testing.T) { - testCases := []struct { - name string - denom string - expError bool - }{ - {"prefixed denom", "transfer/channelToA/uatom", false}, - {"base denom", "uatom", false}, - {"empty denom", "", true}, - {"empty prefix", "/uatom", true}, - {"empty identifiers", "//uatom", true}, - {"single trace identifier", "transfer/", true}, - {"invalid port ID", "(transfer)/channelToA/uatom", true}, - {"invalid channel ID", "transfer/(channelToA)/uatom", true}, - } - - for _, tc := range testCases { - err := ValidatePrefixedDenom(tc.denom) - if tc.expError { - require.Error(t, err, tc.name) - continue - } - require.NoError(t, err, tc.name) - } -} - -func TestValidateIBCDenom(t *testing.T) { - testCases := []struct { - name string - denom string - expError bool - }{ - {"denom with trace hash", "ibc/7F1D3FCF4AE79E1554D670D1AD949A9BA4E4A3C76C63093E17E446A46061A7A2", false}, - {"base denom", "uatom", false}, - {"empty denom", "", true}, - {"invalid prefixed denom", "transfer/channelToA/uatom", true}, - {"denom 'ibc'", "ibc", true}, - {"denom 'ibc/'", "ibc/", true}, - {"invald prefix", "notibc/7F1D3FCF4AE79E1554D670D1AD949A9BA4E4A3C76C63093E17E446A46061A7A2", true}, - {"invald hash", "ibc/!@#$!@#", true}, - } - - for _, tc := range testCases { - err := ValidateIBCDenom(tc.denom) - if tc.expError { - require.Error(t, err, tc.name) - continue - } - require.NoError(t, err, tc.name) - } -} diff --git a/x/ibc/applications/transfer/types/transfer.pb.go b/x/ibc/applications/transfer/types/transfer.pb.go deleted file mode 100644 index 62734b85a49f..000000000000 --- a/x/ibc/applications/transfer/types/transfer.pb.go +++ /dev/null @@ -1,909 +0,0 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: ibc/applications/transfer/v1/transfer.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 - -// 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 -type FungibleTokenPacketData struct { - // the token denomination to be transferred - Denom string `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty"` - // the token amount to be transferred - Amount uint64 `protobuf:"varint,2,opt,name=amount,proto3" json:"amount,omitempty"` - // the sender address - Sender string `protobuf:"bytes,3,opt,name=sender,proto3" json:"sender,omitempty"` - // the recipient address on the destination chain - Receiver string `protobuf:"bytes,4,opt,name=receiver,proto3" json:"receiver,omitempty"` -} - -func (m *FungibleTokenPacketData) Reset() { *m = FungibleTokenPacketData{} } -func (m *FungibleTokenPacketData) String() string { return proto.CompactTextString(m) } -func (*FungibleTokenPacketData) ProtoMessage() {} -func (*FungibleTokenPacketData) Descriptor() ([]byte, []int) { - return fileDescriptor_5041673e96e97901, []int{0} -} -func (m *FungibleTokenPacketData) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *FungibleTokenPacketData) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_FungibleTokenPacketData.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 *FungibleTokenPacketData) XXX_Merge(src proto.Message) { - xxx_messageInfo_FungibleTokenPacketData.Merge(m, src) -} -func (m *FungibleTokenPacketData) XXX_Size() int { - return m.Size() -} -func (m *FungibleTokenPacketData) XXX_DiscardUnknown() { - xxx_messageInfo_FungibleTokenPacketData.DiscardUnknown(m) -} - -var xxx_messageInfo_FungibleTokenPacketData proto.InternalMessageInfo - -func (m *FungibleTokenPacketData) GetDenom() string { - if m != nil { - return m.Denom - } - return "" -} - -func (m *FungibleTokenPacketData) GetAmount() uint64 { - if m != nil { - return m.Amount - } - return 0 -} - -func (m *FungibleTokenPacketData) GetSender() string { - if m != nil { - return m.Sender - } - return "" -} - -func (m *FungibleTokenPacketData) GetReceiver() string { - if m != nil { - return m.Receiver - } - return "" -} - -// DenomTrace contains the base denomination for ICS20 fungible tokens and the -// source tracing information path. -type DenomTrace struct { - // path defines the chain of port/channel identifiers used for tracing the - // source of the fungible token. - Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` - // base denomination of the relayed fungible token. - BaseDenom string `protobuf:"bytes,2,opt,name=base_denom,json=baseDenom,proto3" json:"base_denom,omitempty"` -} - -func (m *DenomTrace) Reset() { *m = DenomTrace{} } -func (m *DenomTrace) String() string { return proto.CompactTextString(m) } -func (*DenomTrace) ProtoMessage() {} -func (*DenomTrace) Descriptor() ([]byte, []int) { - return fileDescriptor_5041673e96e97901, []int{1} -} -func (m *DenomTrace) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *DenomTrace) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_DenomTrace.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 *DenomTrace) XXX_Merge(src proto.Message) { - xxx_messageInfo_DenomTrace.Merge(m, src) -} -func (m *DenomTrace) XXX_Size() int { - return m.Size() -} -func (m *DenomTrace) XXX_DiscardUnknown() { - xxx_messageInfo_DenomTrace.DiscardUnknown(m) -} - -var xxx_messageInfo_DenomTrace proto.InternalMessageInfo - -func (m *DenomTrace) GetPath() string { - if m != nil { - return m.Path - } - return "" -} - -func (m *DenomTrace) GetBaseDenom() string { - if m != nil { - return m.BaseDenom - } - return "" -} - -// 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. -type Params struct { - // send_enabled enables or disables all cross-chain token transfers from this - // chain. - SendEnabled bool `protobuf:"varint,1,opt,name=send_enabled,json=sendEnabled,proto3" json:"send_enabled,omitempty" yaml:"send_enabled"` - // receive_enabled enables or disables all cross-chain token transfers to this - // chain. - ReceiveEnabled bool `protobuf:"varint,2,opt,name=receive_enabled,json=receiveEnabled,proto3" json:"receive_enabled,omitempty" yaml:"receive_enabled"` -} - -func (m *Params) Reset() { *m = Params{} } -func (m *Params) String() string { return proto.CompactTextString(m) } -func (*Params) ProtoMessage() {} -func (*Params) Descriptor() ([]byte, []int) { - return fileDescriptor_5041673e96e97901, []int{2} -} -func (m *Params) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *Params) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_Params.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 *Params) XXX_Merge(src proto.Message) { - xxx_messageInfo_Params.Merge(m, src) -} -func (m *Params) XXX_Size() int { - return m.Size() -} -func (m *Params) XXX_DiscardUnknown() { - xxx_messageInfo_Params.DiscardUnknown(m) -} - -var xxx_messageInfo_Params proto.InternalMessageInfo - -func (m *Params) GetSendEnabled() bool { - if m != nil { - return m.SendEnabled - } - return false -} - -func (m *Params) GetReceiveEnabled() bool { - if m != nil { - return m.ReceiveEnabled - } - return false -} - -func init() { - proto.RegisterType((*FungibleTokenPacketData)(nil), "ibc.applications.transfer.v1.FungibleTokenPacketData") - proto.RegisterType((*DenomTrace)(nil), "ibc.applications.transfer.v1.DenomTrace") - proto.RegisterType((*Params)(nil), "ibc.applications.transfer.v1.Params") -} - -func init() { - proto.RegisterFile("ibc/applications/transfer/v1/transfer.proto", fileDescriptor_5041673e96e97901) -} - -var fileDescriptor_5041673e96e97901 = []byte{ - // 362 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x91, 0x41, 0x6b, 0xe2, 0x40, - 0x14, 0xc7, 0x8d, 0xeb, 0x8a, 0xce, 0x2e, 0xbb, 0x30, 0x2b, 0x1a, 0x64, 0x1b, 0x25, 0x27, 0xa1, - 0x34, 0x41, 0x7a, 0xf3, 0xd0, 0x82, 0xb5, 0x3d, 0x4b, 0xf0, 0x50, 0x7a, 0x91, 0xc9, 0xe4, 0x35, - 0x06, 0x93, 0x99, 0x30, 0x33, 0x4a, 0xa5, 0x9f, 0xa0, 0xb7, 0x7e, 0xac, 0x1e, 0x3d, 0xf6, 0x24, - 0x45, 0xbf, 0x81, 0x9f, 0xa0, 0x64, 0x12, 0x82, 0x14, 0x7a, 0x9a, 0xf7, 0x7b, 0xef, 0xff, 0xff, - 0xcf, 0x83, 0x87, 0xce, 0x23, 0x9f, 0xba, 0x24, 0x4d, 0xe3, 0x88, 0x12, 0x15, 0x71, 0x26, 0x5d, - 0x25, 0x08, 0x93, 0x8f, 0x20, 0xdc, 0xf5, 0xb0, 0xac, 0x9d, 0x54, 0x70, 0xc5, 0xf1, 0xff, 0xc8, - 0xa7, 0xce, 0xa9, 0xd8, 0x29, 0x05, 0xeb, 0x61, 0xb7, 0x15, 0xf2, 0x90, 0x6b, 0xa1, 0x9b, 0x55, - 0xb9, 0xc7, 0x7e, 0x46, 0x9d, 0xbb, 0x15, 0x0b, 0x23, 0x3f, 0x86, 0x19, 0x5f, 0x02, 0x9b, 0x12, - 0xba, 0x04, 0x35, 0x21, 0x8a, 0xe0, 0x16, 0xfa, 0x19, 0x00, 0xe3, 0x89, 0x69, 0xf4, 0x8d, 0x41, - 0xd3, 0xcb, 0x01, 0xb7, 0x51, 0x9d, 0x24, 0x7c, 0xc5, 0x94, 0x59, 0xed, 0x1b, 0x83, 0x9a, 0x57, - 0x50, 0xd6, 0x97, 0xc0, 0x02, 0x10, 0xe6, 0x0f, 0x2d, 0x2f, 0x08, 0x77, 0x51, 0x43, 0x00, 0x85, - 0x68, 0x0d, 0xc2, 0xac, 0xe9, 0x49, 0xc9, 0xf6, 0x35, 0x42, 0x93, 0x2c, 0x74, 0x26, 0x08, 0x05, - 0x8c, 0x51, 0x2d, 0x25, 0x6a, 0x51, 0x7c, 0xa7, 0x6b, 0x7c, 0x86, 0x90, 0x4f, 0x24, 0xcc, 0xf3, - 0x45, 0xaa, 0x7a, 0xd2, 0xcc, 0x3a, 0xda, 0x67, 0xbf, 0x18, 0xa8, 0x3e, 0x25, 0x82, 0x24, 0x12, - 0x8f, 0xd0, 0xef, 0xec, 0xc7, 0x39, 0x30, 0xe2, 0xc7, 0x10, 0xe8, 0x94, 0xc6, 0xb8, 0x73, 0xdc, - 0xf5, 0xfe, 0x6d, 0x48, 0x12, 0x8f, 0xec, 0xd3, 0xa9, 0xed, 0xfd, 0xca, 0xf0, 0x36, 0x27, 0x7c, - 0x83, 0xfe, 0x16, 0x3b, 0x95, 0xf6, 0xaa, 0xb6, 0x77, 0x8f, 0xbb, 0x5e, 0x3b, 0xb7, 0x7f, 0x11, - 0xd8, 0xde, 0x9f, 0xa2, 0x53, 0x84, 0x8c, 0xef, 0xdf, 0xf6, 0x96, 0xb1, 0xdd, 0x5b, 0xc6, 0xc7, - 0xde, 0x32, 0x5e, 0x0f, 0x56, 0x65, 0x7b, 0xb0, 0x2a, 0xef, 0x07, 0xab, 0xf2, 0x70, 0x15, 0x46, - 0x6a, 0xb1, 0xf2, 0x1d, 0xca, 0x13, 0x97, 0x72, 0x99, 0x70, 0x59, 0x3c, 0x17, 0x32, 0x58, 0xba, - 0x4f, 0xee, 0xf7, 0x37, 0x56, 0x9b, 0x14, 0xa4, 0x5f, 0xd7, 0xa7, 0xba, 0xfc, 0x0c, 0x00, 0x00, - 0xff, 0xff, 0x46, 0x73, 0x85, 0x0b, 0x0d, 0x02, 0x00, 0x00, -} - -func (m *FungibleTokenPacketData) 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 *FungibleTokenPacketData) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *FungibleTokenPacketData) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Receiver) > 0 { - i -= len(m.Receiver) - copy(dAtA[i:], m.Receiver) - i = encodeVarintTransfer(dAtA, i, uint64(len(m.Receiver))) - i-- - dAtA[i] = 0x22 - } - if len(m.Sender) > 0 { - i -= len(m.Sender) - copy(dAtA[i:], m.Sender) - i = encodeVarintTransfer(dAtA, i, uint64(len(m.Sender))) - i-- - dAtA[i] = 0x1a - } - if m.Amount != 0 { - i = encodeVarintTransfer(dAtA, i, uint64(m.Amount)) - i-- - dAtA[i] = 0x10 - } - if len(m.Denom) > 0 { - i -= len(m.Denom) - copy(dAtA[i:], m.Denom) - i = encodeVarintTransfer(dAtA, i, uint64(len(m.Denom))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *DenomTrace) 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 *DenomTrace) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *DenomTrace) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.BaseDenom) > 0 { - i -= len(m.BaseDenom) - copy(dAtA[i:], m.BaseDenom) - i = encodeVarintTransfer(dAtA, i, uint64(len(m.BaseDenom))) - i-- - dAtA[i] = 0x12 - } - if len(m.Path) > 0 { - i -= len(m.Path) - copy(dAtA[i:], m.Path) - i = encodeVarintTransfer(dAtA, i, uint64(len(m.Path))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *Params) 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 *Params) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.ReceiveEnabled { - i-- - if m.ReceiveEnabled { - dAtA[i] = 1 - } else { - dAtA[i] = 0 - } - i-- - dAtA[i] = 0x10 - } - if m.SendEnabled { - i-- - if m.SendEnabled { - dAtA[i] = 1 - } else { - dAtA[i] = 0 - } - i-- - dAtA[i] = 0x8 - } - return len(dAtA) - i, nil -} - -func encodeVarintTransfer(dAtA []byte, offset int, v uint64) int { - offset -= sovTransfer(v) - base := offset - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ - } - dAtA[offset] = uint8(v) - return base -} -func (m *FungibleTokenPacketData) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Denom) - if l > 0 { - n += 1 + l + sovTransfer(uint64(l)) - } - if m.Amount != 0 { - n += 1 + sovTransfer(uint64(m.Amount)) - } - l = len(m.Sender) - if l > 0 { - n += 1 + l + sovTransfer(uint64(l)) - } - l = len(m.Receiver) - if l > 0 { - n += 1 + l + sovTransfer(uint64(l)) - } - return n -} - -func (m *DenomTrace) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Path) - if l > 0 { - n += 1 + l + sovTransfer(uint64(l)) - } - l = len(m.BaseDenom) - if l > 0 { - n += 1 + l + sovTransfer(uint64(l)) - } - return n -} - -func (m *Params) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.SendEnabled { - n += 2 - } - if m.ReceiveEnabled { - n += 2 - } - return n -} - -func sovTransfer(x uint64) (n int) { - return (math_bits.Len64(x|1) + 6) / 7 -} -func sozTransfer(x uint64) (n int) { - return sovTransfer(uint64((x << 1) ^ uint64((int64(x) >> 63)))) -} -func (m *FungibleTokenPacketData) 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 ErrIntOverflowTransfer - } - 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: FungibleTokenPacketData: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: FungibleTokenPacketData: 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 ErrIntOverflowTransfer - } - 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 ErrInvalidLengthTransfer - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTransfer - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Denom = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) - } - m.Amount = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTransfer - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Amount |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTransfer - } - 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 ErrInvalidLengthTransfer - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTransfer - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Sender = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Receiver", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTransfer - } - 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 ErrInvalidLengthTransfer - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTransfer - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Receiver = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipTransfer(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTransfer - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *DenomTrace) 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 ErrIntOverflowTransfer - } - 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: DenomTrace: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: DenomTrace: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Path", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTransfer - } - 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 ErrInvalidLengthTransfer - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTransfer - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Path = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field BaseDenom", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTransfer - } - 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 ErrInvalidLengthTransfer - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTransfer - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.BaseDenom = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipTransfer(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTransfer - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *Params) 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 ErrIntOverflowTransfer - } - 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: Params: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: Params: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field SendEnabled", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTransfer - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.SendEnabled = bool(v != 0) - case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field ReceiveEnabled", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTransfer - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.ReceiveEnabled = bool(v != 0) - default: - iNdEx = preIndex - skippy, err := skipTransfer(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTransfer - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func skipTransfer(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, ErrIntOverflowTransfer - } - 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, ErrIntOverflowTransfer - } - 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, ErrIntOverflowTransfer - } - 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, ErrInvalidLengthTransfer - } - iNdEx += length - case 3: - depth++ - case 4: - if depth == 0 { - return 0, ErrUnexpectedEndOfGroupTransfer - } - depth-- - case 5: - iNdEx += 4 - default: - return 0, fmt.Errorf("proto: illegal wireType %d", wireType) - } - if iNdEx < 0 { - return 0, ErrInvalidLengthTransfer - } - if depth == 0 { - return iNdEx, nil - } - } - return 0, io.ErrUnexpectedEOF -} - -var ( - ErrInvalidLengthTransfer = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowTransfer = fmt.Errorf("proto: integer overflow") - ErrUnexpectedEndOfGroupTransfer = fmt.Errorf("proto: unexpected end of group") -) diff --git a/x/ibc/applications/transfer/types/tx.pb.go b/x/ibc/applications/transfer/types/tx.pb.go deleted file mode 100644 index e3a630b42738..000000000000 --- a/x/ibc/applications/transfer/types/tx.pb.go +++ /dev/null @@ -1,804 +0,0 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: ibc/applications/transfer/v1/tx.proto - -package types - -import ( - context "context" - fmt "fmt" - types "github.com/cosmos/cosmos-sdk/types" - types1 "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - _ "github.com/gogo/protobuf/gogoproto" - grpc1 "github.com/gogo/protobuf/grpc" - proto "github.com/gogo/protobuf/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 - -// 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 -type MsgTransfer struct { - // the port on which the packet will be sent - SourcePort string `protobuf:"bytes,1,opt,name=source_port,json=sourcePort,proto3" json:"source_port,omitempty" yaml:"source_port"` - // the channel by which the packet will be sent - SourceChannel string `protobuf:"bytes,2,opt,name=source_channel,json=sourceChannel,proto3" json:"source_channel,omitempty" yaml:"source_channel"` - // the tokens to be transferred - Token types.Coin `protobuf:"bytes,3,opt,name=token,proto3" json:"token"` - // the sender address - Sender string `protobuf:"bytes,4,opt,name=sender,proto3" json:"sender,omitempty"` - // the recipient address on the destination chain - Receiver string `protobuf:"bytes,5,opt,name=receiver,proto3" json:"receiver,omitempty"` - // Timeout height relative to the current block height. - // The timeout is disabled when set to 0. - TimeoutHeight types1.Height `protobuf:"bytes,6,opt,name=timeout_height,json=timeoutHeight,proto3" json:"timeout_height" yaml:"timeout_height"` - // Timeout timestamp (in nanoseconds) relative to the current block timestamp. - // The timeout is disabled when set to 0. - TimeoutTimestamp uint64 `protobuf:"varint,7,opt,name=timeout_timestamp,json=timeoutTimestamp,proto3" json:"timeout_timestamp,omitempty" yaml:"timeout_timestamp"` -} - -func (m *MsgTransfer) Reset() { *m = MsgTransfer{} } -func (m *MsgTransfer) String() string { return proto.CompactTextString(m) } -func (*MsgTransfer) ProtoMessage() {} -func (*MsgTransfer) Descriptor() ([]byte, []int) { - return fileDescriptor_7401ed9bed2f8e09, []int{0} -} -func (m *MsgTransfer) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgTransfer) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgTransfer.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 *MsgTransfer) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgTransfer.Merge(m, src) -} -func (m *MsgTransfer) XXX_Size() int { - return m.Size() -} -func (m *MsgTransfer) XXX_DiscardUnknown() { - xxx_messageInfo_MsgTransfer.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgTransfer proto.InternalMessageInfo - -// MsgTransferResponse defines the Msg/Transfer response type. -type MsgTransferResponse struct { -} - -func (m *MsgTransferResponse) Reset() { *m = MsgTransferResponse{} } -func (m *MsgTransferResponse) String() string { return proto.CompactTextString(m) } -func (*MsgTransferResponse) ProtoMessage() {} -func (*MsgTransferResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_7401ed9bed2f8e09, []int{1} -} -func (m *MsgTransferResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgTransferResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgTransferResponse.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 *MsgTransferResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgTransferResponse.Merge(m, src) -} -func (m *MsgTransferResponse) XXX_Size() int { - return m.Size() -} -func (m *MsgTransferResponse) XXX_DiscardUnknown() { - xxx_messageInfo_MsgTransferResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgTransferResponse proto.InternalMessageInfo - -func init() { - proto.RegisterType((*MsgTransfer)(nil), "ibc.applications.transfer.v1.MsgTransfer") - proto.RegisterType((*MsgTransferResponse)(nil), "ibc.applications.transfer.v1.MsgTransferResponse") -} - -func init() { - proto.RegisterFile("ibc/applications/transfer/v1/tx.proto", fileDescriptor_7401ed9bed2f8e09) -} - -var fileDescriptor_7401ed9bed2f8e09 = []byte{ - // 488 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x93, 0x41, 0x6f, 0xd3, 0x30, - 0x14, 0xc7, 0x13, 0xd6, 0x95, 0xe2, 0x6a, 0x13, 0x18, 0x36, 0x65, 0xd5, 0x48, 0xaa, 0x48, 0x48, - 0xe5, 0x80, 0xad, 0x0c, 0x21, 0xa4, 0x1d, 0x10, 0xca, 0x2e, 0x70, 0x98, 0x84, 0xa2, 0x1d, 0x10, - 0x97, 0x91, 0x78, 0x26, 0xb1, 0xd6, 0xd8, 0x91, 0xed, 0x46, 0xdb, 0x37, 0xe0, 0xc8, 0x47, 0xd8, - 0x99, 0x4f, 0xb2, 0xe3, 0x8e, 0x9c, 0x2a, 0xd4, 0x5e, 0x38, 0xf7, 0x13, 0xa0, 0xc4, 0x6e, 0x69, - 0x0f, 0x20, 0x4e, 0xf1, 0x7b, 0xff, 0xdf, 0xf3, 0x5f, 0xcf, 0xef, 0x05, 0x3c, 0x63, 0x19, 0xc1, - 0x69, 0x55, 0x8d, 0x19, 0x49, 0x35, 0x13, 0x5c, 0x61, 0x2d, 0x53, 0xae, 0xbe, 0x50, 0x89, 0xeb, - 0x08, 0xeb, 0x2b, 0x54, 0x49, 0xa1, 0x05, 0x3c, 0x64, 0x19, 0x41, 0xeb, 0x18, 0x5a, 0x62, 0xa8, - 0x8e, 0x06, 0x4f, 0x72, 0x91, 0x8b, 0x16, 0xc4, 0xcd, 0xc9, 0xd4, 0x0c, 0x7c, 0x22, 0x54, 0x29, - 0x14, 0xce, 0x52, 0x45, 0x71, 0x1d, 0x65, 0x54, 0xa7, 0x11, 0x26, 0x82, 0x71, 0xab, 0x07, 0x8d, - 0x35, 0x11, 0x92, 0x62, 0x32, 0x66, 0x94, 0xeb, 0xc6, 0xd0, 0x9c, 0x0c, 0x10, 0x7e, 0xdf, 0x02, - 0xfd, 0x53, 0x95, 0x9f, 0x59, 0x27, 0xf8, 0x1a, 0xf4, 0x95, 0x98, 0x48, 0x42, 0xcf, 0x2b, 0x21, - 0xb5, 0xe7, 0x0e, 0xdd, 0xd1, 0x83, 0x78, 0x7f, 0x31, 0x0d, 0xe0, 0x75, 0x5a, 0x8e, 0x8f, 0xc3, - 0x35, 0x31, 0x4c, 0x80, 0x89, 0x3e, 0x08, 0xa9, 0xe1, 0x5b, 0xb0, 0x6b, 0x35, 0x52, 0xa4, 0x9c, - 0xd3, 0xb1, 0x77, 0xaf, 0xad, 0x3d, 0x58, 0x4c, 0x83, 0xbd, 0x8d, 0x5a, 0xab, 0x87, 0xc9, 0x8e, - 0x49, 0x9c, 0x98, 0x18, 0xbe, 0x02, 0xdb, 0x5a, 0x5c, 0x52, 0xee, 0x6d, 0x0d, 0xdd, 0x51, 0xff, - 0xe8, 0x00, 0x99, 0xde, 0x50, 0xd3, 0x1b, 0xb2, 0xbd, 0xa1, 0x13, 0xc1, 0x78, 0xdc, 0xb9, 0x9d, - 0x06, 0x4e, 0x62, 0x68, 0xb8, 0x0f, 0xba, 0x8a, 0xf2, 0x0b, 0x2a, 0xbd, 0x4e, 0x63, 0x98, 0xd8, - 0x08, 0x0e, 0x40, 0x4f, 0x52, 0x42, 0x59, 0x4d, 0xa5, 0xb7, 0xdd, 0x2a, 0xab, 0x18, 0x7e, 0x06, - 0xbb, 0x9a, 0x95, 0x54, 0x4c, 0xf4, 0x79, 0x41, 0x59, 0x5e, 0x68, 0xaf, 0xdb, 0x7a, 0x0e, 0x50, - 0x33, 0x83, 0xe6, 0xbd, 0x90, 0x7d, 0xa5, 0x3a, 0x42, 0xef, 0x5a, 0x22, 0x7e, 0xda, 0x98, 0xfe, - 0x69, 0x66, 0xb3, 0x3e, 0x4c, 0x76, 0x6c, 0xc2, 0xd0, 0xf0, 0x3d, 0x78, 0xb4, 0x24, 0x9a, 0xaf, - 0xd2, 0x69, 0x59, 0x79, 0xf7, 0x87, 0xee, 0xa8, 0x13, 0x1f, 0x2e, 0xa6, 0x81, 0xb7, 0x79, 0xc9, - 0x0a, 0x09, 0x93, 0x87, 0x36, 0x77, 0xb6, 0x4c, 0x1d, 0xf7, 0xbe, 0xde, 0x04, 0xce, 0xaf, 0x9b, - 0xc0, 0x09, 0xf7, 0xc0, 0xe3, 0xb5, 0x59, 0x25, 0x54, 0x55, 0x82, 0x2b, 0x7a, 0x24, 0xc0, 0xd6, - 0xa9, 0xca, 0x61, 0x01, 0x7a, 0xab, 0x31, 0x3e, 0x47, 0xff, 0x5a, 0x26, 0xb4, 0x76, 0xcb, 0x20, - 0xfa, 0x6f, 0x74, 0x69, 0x18, 0x7f, 0xbc, 0x9d, 0xf9, 0xee, 0xdd, 0xcc, 0x77, 0x7f, 0xce, 0x7c, - 0xf7, 0xdb, 0xdc, 0x77, 0xee, 0xe6, 0xbe, 0xf3, 0x63, 0xee, 0x3b, 0x9f, 0xde, 0xe4, 0x4c, 0x17, - 0x93, 0x0c, 0x11, 0x51, 0x62, 0xbb, 0x9a, 0xe6, 0xf3, 0x42, 0x5d, 0x5c, 0xe2, 0x2b, 0xfc, 0xf7, - 0x3f, 0x41, 0x5f, 0x57, 0x54, 0x65, 0xdd, 0x76, 0x2b, 0x5f, 0xfe, 0x0e, 0x00, 0x00, 0xff, 0xff, - 0x26, 0x76, 0x5b, 0xfa, 0x33, 0x03, 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 { - // Transfer defines a rpc handler method for MsgTransfer. - Transfer(ctx context.Context, in *MsgTransfer, opts ...grpc.CallOption) (*MsgTransferResponse, error) -} - -type msgClient struct { - cc grpc1.ClientConn -} - -func NewMsgClient(cc grpc1.ClientConn) MsgClient { - return &msgClient{cc} -} - -func (c *msgClient) Transfer(ctx context.Context, in *MsgTransfer, opts ...grpc.CallOption) (*MsgTransferResponse, error) { - out := new(MsgTransferResponse) - err := c.cc.Invoke(ctx, "/ibc.applications.transfer.v1.Msg/Transfer", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// MsgServer is the server API for Msg service. -type MsgServer interface { - // Transfer defines a rpc handler method for MsgTransfer. - Transfer(context.Context, *MsgTransfer) (*MsgTransferResponse, error) -} - -// UnimplementedMsgServer can be embedded to have forward compatible implementations. -type UnimplementedMsgServer struct { -} - -func (*UnimplementedMsgServer) Transfer(ctx context.Context, req *MsgTransfer) (*MsgTransferResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method Transfer not implemented") -} - -func RegisterMsgServer(s grpc1.Server, srv MsgServer) { - s.RegisterService(&_Msg_serviceDesc, srv) -} - -func _Msg_Transfer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgTransfer) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MsgServer).Transfer(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.applications.transfer.v1.Msg/Transfer", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).Transfer(ctx, req.(*MsgTransfer)) - } - return interceptor(ctx, in, info, handler) -} - -var _Msg_serviceDesc = grpc.ServiceDesc{ - ServiceName: "ibc.applications.transfer.v1.Msg", - HandlerType: (*MsgServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "Transfer", - Handler: _Msg_Transfer_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "ibc/applications/transfer/v1/tx.proto", -} - -func (m *MsgTransfer) 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 *MsgTransfer) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgTransfer) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.TimeoutTimestamp != 0 { - i = encodeVarintTx(dAtA, i, uint64(m.TimeoutTimestamp)) - i-- - dAtA[i] = 0x38 - } - { - size, err := m.TimeoutHeight.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x32 - if len(m.Receiver) > 0 { - i -= len(m.Receiver) - copy(dAtA[i:], m.Receiver) - i = encodeVarintTx(dAtA, i, uint64(len(m.Receiver))) - i-- - dAtA[i] = 0x2a - } - if len(m.Sender) > 0 { - i -= len(m.Sender) - copy(dAtA[i:], m.Sender) - i = encodeVarintTx(dAtA, i, uint64(len(m.Sender))) - i-- - dAtA[i] = 0x22 - } - { - size, err := m.Token.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - if len(m.SourceChannel) > 0 { - i -= len(m.SourceChannel) - copy(dAtA[i:], m.SourceChannel) - i = encodeVarintTx(dAtA, i, uint64(len(m.SourceChannel))) - i-- - dAtA[i] = 0x12 - } - if len(m.SourcePort) > 0 { - i -= len(m.SourcePort) - copy(dAtA[i:], m.SourcePort) - i = encodeVarintTx(dAtA, i, uint64(len(m.SourcePort))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *MsgTransferResponse) 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 *MsgTransferResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgTransferResponse) 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 *MsgTransfer) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.SourcePort) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.SourceChannel) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = m.Token.Size() - n += 1 + l + sovTx(uint64(l)) - l = len(m.Sender) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.Receiver) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = m.TimeoutHeight.Size() - n += 1 + l + sovTx(uint64(l)) - if m.TimeoutTimestamp != 0 { - n += 1 + sovTx(uint64(m.TimeoutTimestamp)) - } - return n -} - -func (m *MsgTransferResponse) 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 *MsgTransfer) 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: MsgTransfer: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgTransfer: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field SourcePort", 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.SourcePort = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field SourceChannel", 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.SourceChannel = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Token", 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 := m.Token.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Sender", 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.Sender = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Receiver", 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.Receiver = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 6: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field TimeoutHeight", 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 := m.TimeoutHeight.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 7: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field TimeoutTimestamp", wireType) - } - m.TimeoutTimestamp = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.TimeoutTimestamp |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - 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 *MsgTransferResponse) 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: MsgTransferResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgTransferResponse: 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/ibc/core/02-client/abci.go b/x/ibc/core/02-client/abci.go deleted file mode 100644 index 163e513327b8..000000000000 --- a/x/ibc/core/02-client/abci.go +++ /dev/null @@ -1,41 +0,0 @@ -package client - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/keeper" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" -) - -// BeginBlocker updates an existing localhost client with the latest block height. -func BeginBlocker(ctx sdk.Context, k keeper.Keeper) { - plan, found := k.GetUpgradePlan(ctx) - if found { - // Once we are at the last block this chain will commit, set the upgraded consensus state - // so that IBC clients can use the last NextValidatorsHash as a trusted kernel for verifying - // headers on the next version of the chain. - // Set the time to the last block time of the current chain. - // In order for a client to upgrade successfully, the first block of the new chain must be committed - // within the trusting period of the last block time on this chain. - _, exists := k.GetUpgradedClient(ctx, plan.Height) - if exists && ctx.BlockHeight() == plan.Height-1 { - upgradedConsState := &ibctmtypes.ConsensusState{ - Timestamp: ctx.BlockTime(), - NextValidatorsHash: ctx.BlockHeader().NextValidatorsHash, - } - bz := k.MustMarshalConsensusState(upgradedConsState) - - k.SetUpgradedConsensusState(ctx, plan.Height, bz) - } - } - - _, found = k.GetClientState(ctx, exported.Localhost) - if !found { - return - } - - // update the localhost client with the latest block height - if err := k.UpdateClient(ctx, exported.Localhost, nil); err != nil { - panic(err) - } -} diff --git a/x/ibc/core/02-client/abci_test.go b/x/ibc/core/02-client/abci_test.go deleted file mode 100644 index 3f1f6ebdc289..000000000000 --- a/x/ibc/core/02-client/abci_test.go +++ /dev/null @@ -1,94 +0,0 @@ -package client_test - -import ( - "testing" - - "github.com/stretchr/testify/suite" - abci "github.com/tendermint/tendermint/abci/types" - tmproto "github.com/tendermint/tendermint/proto/tendermint/types" - - client "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client" - "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" - localhosttypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/09-localhost/types" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" - upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" -) - -type ClientTestSuite struct { - suite.Suite - - coordinator *ibctesting.Coordinator - - chainA *ibctesting.TestChain - chainB *ibctesting.TestChain -} - -func (suite *ClientTestSuite) SetupTest() { - suite.coordinator = ibctesting.NewCoordinator(suite.T(), 2) - - suite.chainA = suite.coordinator.GetChain(ibctesting.GetChainID(0)) - suite.chainB = suite.coordinator.GetChain(ibctesting.GetChainID(1)) - - // set localhost client - revision := types.ParseChainID(suite.chainA.GetContext().ChainID()) - localHostClient := localhosttypes.NewClientState( - suite.chainA.GetContext().ChainID(), types.NewHeight(revision, uint64(suite.chainA.GetContext().BlockHeight())), - ) - suite.chainA.App.IBCKeeper.ClientKeeper.SetClientState(suite.chainA.GetContext(), exported.Localhost, localHostClient) -} - -func TestClientTestSuite(t *testing.T) { - suite.Run(t, new(ClientTestSuite)) -} - -func (suite *ClientTestSuite) TestBeginBlocker() { - prevHeight := types.GetSelfHeight(suite.chainA.GetContext()) - - localHostClient := suite.chainA.GetClientState(exported.Localhost) - suite.Require().Equal(prevHeight, localHostClient.GetLatestHeight()) - - for i := 0; i < 10; i++ { - // increment height - suite.coordinator.CommitBlock(suite.chainA, suite.chainB) - - suite.Require().NotPanics(func() { - client.BeginBlocker(suite.chainA.GetContext(), suite.chainA.App.IBCKeeper.ClientKeeper) - }, "BeginBlocker shouldn't panic") - - localHostClient = suite.chainA.GetClientState(exported.Localhost) - suite.Require().Equal(prevHeight.Increment(), localHostClient.GetLatestHeight()) - prevHeight = localHostClient.GetLatestHeight().(types.Height) - } -} - -func (suite *ClientTestSuite) TestBeginBlockerConsensusState() { - plan := &upgradetypes.Plan{ - Name: "test", - Height: suite.chainA.GetContext().BlockHeight() + 1, - } - // set upgrade plan in the upgrade store - store := suite.chainA.GetContext().KVStore(suite.chainA.App.GetKey(upgradetypes.StoreKey)) - bz := suite.chainA.App.AppCodec().MustMarshalBinaryBare(plan) - store.Set(upgradetypes.PlanKey(), bz) - - nextValsHash := []byte("nextValsHash") - newCtx := suite.chainA.GetContext().WithBlockHeader(tmproto.Header{ - Height: suite.chainA.GetContext().BlockHeight(), - NextValidatorsHash: nextValsHash, - }) - - err := suite.chainA.App.UpgradeKeeper.SetUpgradedClient(newCtx, plan.Height, []byte("client state")) - suite.Require().NoError(err) - - req := abci.RequestBeginBlock{Header: newCtx.BlockHeader()} - suite.chainA.App.BeginBlock(req) - - // plan Height is at ctx.BlockHeight+1 - consState, found := suite.chainA.App.UpgradeKeeper.GetUpgradedConsensusState(newCtx, plan.Height) - suite.Require().True(found) - bz, err = types.MarshalConsensusState(suite.chainA.App.AppCodec(), &ibctmtypes.ConsensusState{Timestamp: newCtx.BlockTime(), NextValidatorsHash: nextValsHash}) - suite.Require().NoError(err) - suite.Require().Equal(bz, consState) -} diff --git a/x/ibc/core/02-client/client/cli/cli.go b/x/ibc/core/02-client/client/cli/cli.go deleted file mode 100644 index 33c991521582..000000000000 --- a/x/ibc/core/02-client/client/cli/cli.go +++ /dev/null @@ -1,51 +0,0 @@ -package cli - -import ( - "github.com/spf13/cobra" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" -) - -// GetQueryCmd returns the query commands for IBC clients -func GetQueryCmd() *cobra.Command { - queryCmd := &cobra.Command{ - Use: types.SubModuleName, - Short: "IBC client query subcommands", - DisableFlagParsing: true, - SuggestionsMinimumDistance: 2, - RunE: client.ValidateCmd, - } - - queryCmd.AddCommand( - GetCmdQueryClientStates(), - GetCmdQueryClientState(), - GetCmdQueryConsensusStates(), - GetCmdQueryConsensusState(), - GetCmdQueryHeader(), - GetCmdNodeConsensusState(), - GetCmdParams(), - ) - - 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 deleted file mode 100644 index c1b5e51a050f..000000000000 --- a/x/ibc/core/02-client/client/cli/query.go +++ /dev/null @@ -1,260 +0,0 @@ -package cli - -import ( - "errors" - "fmt" - - "github.com/spf13/cobra" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/version" - "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/client/utils" - "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" -) - -const ( - flagLatestHeight = "latest-height" -) - -// GetCmdQueryClientStates defines the command to query all the light clients -// that this chain mantains. -func GetCmdQueryClientStates() *cobra.Command { - cmd := &cobra.Command{ - Use: "states", - Short: "Query all available light clients", - Long: "Query all available light clients", - Example: fmt.Sprintf("%s query %s %s states", version.AppName, host.ModuleName, types.SubModuleName), - Args: cobra.NoArgs, - RunE: func(cmd *cobra.Command, _ []string) error { - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } - queryClient := types.NewQueryClient(clientCtx) - - pageReq, err := client.ReadPageRequest(cmd.Flags()) - if err != nil { - return err - } - - req := &types.QueryClientStatesRequest{ - Pagination: pageReq, - } - - res, err := queryClient.ClientStates(cmd.Context(), req) - if err != nil { - return err - } - - return clientCtx.PrintProto(res) - }, - } - flags.AddQueryFlagsToCmd(cmd) - flags.AddPaginationFlagsToCmd(cmd, "client states") - - return cmd -} - -// GetCmdQueryClientState defines the command to query the state of a client with -// a given id as defined in https://github.com/cosmos/ics/tree/master/spec/ics-002-client-semantics#query -func GetCmdQueryClientState() *cobra.Command { - cmd := &cobra.Command{ - Use: "state [client-id]", - Short: "Query a client state", - Long: "Query stored client state", - Example: fmt.Sprintf("%s query %s %s state [client-id]", version.AppName, host.ModuleName, types.SubModuleName), - Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } - clientID := args[0] - prove, _ := cmd.Flags().GetBool(flags.FlagProve) - - clientStateRes, err := utils.QueryClientState(clientCtx, clientID, prove) - if err != nil { - return err - } - - return clientCtx.PrintProto(clientStateRes) - }, - } - - cmd.Flags().Bool(flags.FlagProve, true, "show proofs for the query results") - flags.AddQueryFlagsToCmd(cmd) - - return cmd -} - -// GetCmdQueryConsensusStates defines the command to query all the consensus states from a given -// client state. -func GetCmdQueryConsensusStates() *cobra.Command { - cmd := &cobra.Command{ - Use: "consensus-states [client-id]", - Short: "Query all the consensus states of a client.", - Long: "Query all the consensus states from a given client state.", - Example: fmt.Sprintf("%s query %s %s consensus-states [client-id]", version.AppName, host.ModuleName, types.SubModuleName), - Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } - clientID := args[0] - - queryClient := types.NewQueryClient(clientCtx) - - pageReq, err := client.ReadPageRequest(cmd.Flags()) - if err != nil { - return err - } - - req := &types.QueryConsensusStatesRequest{ - ClientId: clientID, - Pagination: pageReq, - } - - res, err := queryClient.ConsensusStates(cmd.Context(), req) - if err != nil { - return err - } - - return clientCtx.PrintProto(res) - }, - } - flags.AddQueryFlagsToCmd(cmd) - flags.AddPaginationFlagsToCmd(cmd, "consensus states") - - return cmd -} - -// GetCmdQueryConsensusState defines the command to query the consensus state of -// the chain as defined in https://github.com/cosmos/ics/tree/master/spec/ics-002-client-semantics#query -func GetCmdQueryConsensusState() *cobra.Command { - cmd := &cobra.Command{ - Use: "consensus-state [client-id] [height]", - Short: "Query the consensus state of a client at a given height", - Long: `Query the consensus state for a particular light client at a given height. -If the '--latest' flag is included, the query returns the latest consensus state, overriding the height argument.`, - Example: fmt.Sprintf("%s query %s %s consensus-state [client-id] [height]", version.AppName, host.ModuleName, types.SubModuleName), - Args: cobra.RangeArgs(1, 2), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } - clientID := args[0] - queryLatestHeight, _ := cmd.Flags().GetBool(flagLatestHeight) - var height types.Height - - if !queryLatestHeight { - if len(args) != 2 { - return errors.New("must include a second 'height' argument when '--latest-height' flag is not provided") - } - - height, err = types.ParseHeight(args[1]) - if err != nil { - return err - } - } - - prove, _ := cmd.Flags().GetBool(flags.FlagProve) - - csRes, err := utils.QueryConsensusState(clientCtx, clientID, height, prove, queryLatestHeight) - if err != nil { - return err - } - - return clientCtx.PrintProto(csRes) - }, - } - - cmd.Flags().Bool(flags.FlagProve, true, "show proofs for the query results") - cmd.Flags().Bool(flagLatestHeight, false, "return latest stored consensus state") - flags.AddQueryFlagsToCmd(cmd) - - return cmd -} - -// GetCmdQueryHeader defines the command to query the latest header on the chain -func GetCmdQueryHeader() *cobra.Command { - cmd := &cobra.Command{ - Use: "header", - Short: "Query the latest header of the running chain", - Long: "Query the latest Tendermint header of the running chain", - Example: fmt.Sprintf("%s query %s %s header", version.AppName, host.ModuleName, types.SubModuleName), - Args: cobra.NoArgs, - RunE: func(cmd *cobra.Command, _ []string) error { - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } - header, _, err := utils.QueryTendermintHeader(clientCtx) - if err != nil { - return err - } - - return clientCtx.PrintProto(&header) - }, - } - - flags.AddQueryFlagsToCmd(cmd) - - return cmd -} - -// GetCmdNodeConsensusState defines the command to query the latest consensus state of a node -// The result is feed to client creation -func GetCmdNodeConsensusState() *cobra.Command { - cmd := &cobra.Command{ - Use: "node-state", - Short: "Query a node consensus state", - Long: "Query a node consensus state. This result is feed to the client creation transaction.", - Example: fmt.Sprintf("%s query %s %s node-state", version.AppName, host.ModuleName, types.SubModuleName), - Args: cobra.NoArgs, - RunE: func(cmd *cobra.Command, _ []string) error { - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } - state, _, err := utils.QueryNodeConsensusState(clientCtx) - if err != nil { - return err - } - - return clientCtx.PrintProto(state) - }, - } - - flags.AddQueryFlagsToCmd(cmd) - - return cmd -} - -// GetCmdParams returns the command handler for ibc client parameter querying. -func GetCmdParams() *cobra.Command { - cmd := &cobra.Command{ - Use: "params", - Short: "Query the current ibc client parameters", - Long: "Query the current ibc client parameters", - Args: cobra.NoArgs, - Example: fmt.Sprintf("%s query %s %s params", version.AppName, host.ModuleName, types.SubModuleName), - RunE: func(cmd *cobra.Command, _ []string) error { - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } - queryClient := types.NewQueryClient(clientCtx) - - res, _ := queryClient.ClientParams(cmd.Context(), &types.QueryClientParamsRequest{}) - return clientCtx.PrintProto(res.Params) - }, - } - - flags.AddQueryFlagsToCmd(cmd) - - return cmd -} diff --git a/x/ibc/core/02-client/client/cli/tx.go b/x/ibc/core/02-client/client/cli/tx.go deleted file mode 100644 index 51c78bb4e737..000000000000 --- a/x/ibc/core/02-client/client/cli/tx.go +++ /dev/null @@ -1,418 +0,0 @@ -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" - 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" - "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" -) - -// 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 - } - - svcMsgClientConn := &msgservice.ServiceMsgClientConn{} - msgClient := types.NewMsgClient(svcMsgClientConn) - _, err = msgClient.CreateClient(cmd.Context(), msg) - if err != nil { - return err - } - - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) - }, - } - - 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 - } - - svcMsgClientConn := &msgservice.ServiceMsgClientConn{} - msgClient := types.NewMsgClient(svcMsgClientConn) - _, err = msgClient.UpdateClient(cmd.Context(), msg) - if err != nil { - return err - } - - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) - }, - } -} - -// 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 - } - - svcMsgClientConn := &msgservice.ServiceMsgClientConn{} - msgClient := types.NewMsgClient(svcMsgClientConn) - _, err = msgClient.SubmitMisbehaviour(cmd.Context(), msg) - if err != nil { - return err - } - - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) - }, - } -} - -// 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 - } - - svcMsgClientConn := &msgservice.ServiceMsgClientConn{} - msgClient := types.NewMsgClient(svcMsgClientConn) - _, err = msgClient.UpgradeClient(cmd.Context(), msg) - if err != nil { - return err - } - - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) - }, - } - - flags.AddTxFlagsToCmd(cmd) - - 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 -} - -// NewCmdSubmitUpgradeProposal implements a command handler for submitting an upgrade IBC client proposal transaction. -func NewCmdSubmitUpgradeProposal() *cobra.Command { - cmd := &cobra.Command{ - Use: "ibc-upgrade [name] [height] [path/to/upgraded_client_state.json] [flags]", - Args: cobra.ExactArgs(3), - Short: "Submit an IBC upgrade proposal", - Long: "Submit an IBC client breaking upgrade proposal along with an initial deposit.\n" + - "The client state specified is the upgraded client state representing the upgraded chain", - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry) - - title, err := cmd.Flags().GetString(govcli.FlagTitle) - if err != nil { - return err - } - - description, err := cmd.Flags().GetString(govcli.FlagDescription) - if err != nil { - return err - } - - name := args[0] - - height, err := cmd.Flags().GetInt64(args[1]) - if err != nil { - return err - } - - plan := upgradetypes.Plan{ - Name: name, - Height: height, - } - - // attempt to unmarshal client state argument - var clientState exported.ClientState - clientContentOrFileName := args[2] - 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") - } - } - - content, err := types.NewUpgradeProposal(title, description, plan, clientState) - if err != nil { - return err - } - - 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 deleted file mode 100644 index 1f6f4065f0f1..000000000000 --- a/x/ibc/core/02-client/client/proposal_handler.go +++ /dev/null @@ -1,25 +0,0 @@ -package client - -import ( - "net/http" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/types/rest" - govclient "github.com/cosmos/cosmos-sdk/x/gov/client" - govrest "github.com/cosmos/cosmos-sdk/x/gov/client/rest" - "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/client/cli" -) - -var ( - UpdateClientProposalHandler = govclient.NewProposalHandler(cli.NewCmdSubmitUpdateClientProposal, emptyRestHandler) - UpgradeProposalHandler = govclient.NewProposalHandler(cli.NewCmdSubmitUpgradeProposal, emptyRestHandler) -) - -func emptyRestHandler(client.Context) govrest.ProposalRESTHandler { - return govrest.ProposalRESTHandler{ - SubRoute: "unsupported-ibc-client", - Handler: func(w http.ResponseWriter, r *http.Request) { - rest.WriteErrorResponse(w, http.StatusBadRequest, "Legacy REST Routes are not supported for IBC proposals") - }, - } -} diff --git a/x/ibc/core/02-client/client/utils/utils.go b/x/ibc/core/02-client/client/utils/utils.go deleted file mode 100644 index 1a7bc003bc51..000000000000 --- a/x/ibc/core/02-client/client/utils/utils.go +++ /dev/null @@ -1,199 +0,0 @@ -package utils - -import ( - "context" - - tmtypes "github.com/tendermint/tendermint/types" - - "github.com/cosmos/cosmos-sdk/client" - - "github.com/cosmos/cosmos-sdk/codec" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - ibcclient "github.com/cosmos/cosmos-sdk/x/ibc/core/client" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" -) - -// QueryClientState returns a client state. If prove is true, it performs an ABCI store query -// in order to retrieve the merkle proof. Otherwise, it uses the gRPC query client. -func QueryClientState( - clientCtx client.Context, clientID string, prove bool, -) (*types.QueryClientStateResponse, error) { - if prove { - return QueryClientStateABCI(clientCtx, clientID) - } - - queryClient := types.NewQueryClient(clientCtx) - req := &types.QueryClientStateRequest{ - ClientId: clientID, - } - - return queryClient.ClientState(context.Background(), req) -} - -// QueryClientStateABCI queries the store to get the light client state and a merkle proof. -func QueryClientStateABCI( - clientCtx client.Context, clientID string, -) (*types.QueryClientStateResponse, error) { - key := host.FullClientStateKey(clientID) - - value, proofBz, proofHeight, err := ibcclient.QueryTendermintProof(clientCtx, key) - if err != nil { - return nil, err - } - - // check if client exists - if len(value) == 0 { - return nil, sdkerrors.Wrap(types.ErrClientNotFound, clientID) - } - - cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry) - - clientState, err := types.UnmarshalClientState(cdc, value) - if err != nil { - return nil, err - } - - anyClientState, err := types.PackClientState(clientState) - if err != nil { - return nil, err - } - - clientStateRes := types.NewQueryClientStateResponse(anyClientState, proofBz, proofHeight) - return clientStateRes, nil -} - -// QueryConsensusState returns a consensus state. If prove is true, it performs an ABCI store -// query in order to retrieve the merkle proof. Otherwise, it uses the gRPC query client. -func QueryConsensusState( - clientCtx client.Context, clientID string, height exported.Height, prove, latestHeight bool, -) (*types.QueryConsensusStateResponse, error) { - if prove { - return QueryConsensusStateABCI(clientCtx, clientID, height) - } - - queryClient := types.NewQueryClient(clientCtx) - req := &types.QueryConsensusStateRequest{ - ClientId: clientID, - RevisionNumber: height.GetRevisionNumber(), - RevisionHeight: height.GetRevisionHeight(), - LatestHeight: latestHeight, - } - - return queryClient.ConsensusState(context.Background(), req) -} - -// QueryConsensusStateABCI queries the store to get the consensus state of a light client and a -// merkle proof of its existence or non-existence. -func QueryConsensusStateABCI( - clientCtx client.Context, clientID string, height exported.Height, -) (*types.QueryConsensusStateResponse, error) { - key := host.FullConsensusStateKey(clientID, height) - - value, proofBz, proofHeight, err := ibcclient.QueryTendermintProof(clientCtx, key) - if err != nil { - return nil, err - } - - // check if consensus state exists - if len(value) == 0 { - return nil, sdkerrors.Wrap(types.ErrConsensusStateNotFound, clientID) - } - - cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry) - - cs, err := types.UnmarshalConsensusState(cdc, value) - if err != nil { - return nil, err - } - - anyConsensusState, err := types.PackConsensusState(cs) - if err != nil { - return nil, err - } - - return types.NewQueryConsensusStateResponse(anyConsensusState, proofBz, proofHeight), nil -} - -// QueryTendermintHeader takes a client context and returns the appropriate -// tendermint header -func QueryTendermintHeader(clientCtx client.Context) (ibctmtypes.Header, int64, error) { - node, err := clientCtx.GetNode() - if err != nil { - return ibctmtypes.Header{}, 0, err - } - - info, err := node.ABCIInfo(context.Background()) - if err != nil { - return ibctmtypes.Header{}, 0, err - } - - height := info.Response.LastBlockHeight - - commit, err := node.Commit(context.Background(), &height) - if err != nil { - return ibctmtypes.Header{}, 0, err - } - - page := 0 - count := 10_000 - - validators, err := node.Validators(context.Background(), &height, &page, &count) - if err != nil { - return ibctmtypes.Header{}, 0, err - } - - protoCommit := commit.SignedHeader.ToProto() - protoValset, err := tmtypes.NewValidatorSet(validators.Validators).ToProto() - if err != nil { - return ibctmtypes.Header{}, 0, err - } - - header := ibctmtypes.Header{ - SignedHeader: protoCommit, - ValidatorSet: protoValset, - } - - return header, height, nil -} - -// QueryNodeConsensusState takes a client context and returns the appropriate -// tendermint consensus state -func QueryNodeConsensusState(clientCtx client.Context) (*ibctmtypes.ConsensusState, int64, error) { - node, err := clientCtx.GetNode() - if err != nil { - return &ibctmtypes.ConsensusState{}, 0, err - } - - info, err := node.ABCIInfo(context.Background()) - if err != nil { - return &ibctmtypes.ConsensusState{}, 0, err - } - - height := info.Response.LastBlockHeight - - commit, err := node.Commit(context.Background(), &height) - if err != nil { - return &ibctmtypes.ConsensusState{}, 0, err - } - - page := 1 - count := 10_000 - - nextHeight := height + 1 - nextVals, err := node.Validators(context.Background(), &nextHeight, &page, &count) - if err != nil { - return &ibctmtypes.ConsensusState{}, 0, err - } - - state := &ibctmtypes.ConsensusState{ - Timestamp: commit.Time, - Root: commitmenttypes.NewMerkleRoot(commit.AppHash), - NextValidatorsHash: tmtypes.NewValidatorSet(nextVals.Validators).Hash(), - } - - return state, height, nil -} diff --git a/x/ibc/core/02-client/doc.go b/x/ibc/core/02-client/doc.go deleted file mode 100644 index cfe3c76c6af7..000000000000 --- a/x/ibc/core/02-client/doc.go +++ /dev/null @@ -1,10 +0,0 @@ -/* -Package client implements the ICS 02 - Client Semantics specification -https://github.com/cosmos/ics/tree/master/spec/ics-002-client-semantics. This -concrete implementations defines types and method to store and update light -clients which tracks on other chain's state. - -The main type is `Client`, which provides `commitment.Root` to verify state proofs and `ConsensusState` to -verify header proofs. -*/ -package client diff --git a/x/ibc/core/02-client/genesis.go b/x/ibc/core/02-client/genesis.go deleted file mode 100644 index 26635f0784c8..000000000000 --- a/x/ibc/core/02-client/genesis.go +++ /dev/null @@ -1,69 +0,0 @@ -package client - -import ( - "fmt" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/keeper" - "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -// InitGenesis initializes the ibc client submodule's state from a provided genesis -// state. -func InitGenesis(ctx sdk.Context, k keeper.Keeper, gs types.GenesisState) { - k.SetParams(ctx, gs.Params) - - // Set all client metadata first. This will allow client keeper to overwrite client and consensus state keys - // if clients accidentally write to ClientKeeper reserved keys. - if len(gs.ClientsMetadata) != 0 { - k.SetAllClientMetadata(ctx, gs.ClientsMetadata) - } - - for _, client := range gs.Clients { - cs, ok := client.ClientState.GetCachedValue().(exported.ClientState) - if !ok { - panic("invalid client state") - } - - if !gs.Params.IsAllowedClient(cs.ClientType()) { - panic(fmt.Sprintf("client state type %s is not registered on the allowlist", cs.ClientType())) - } - - k.SetClientState(ctx, client.ClientId, cs) - } - - for _, cs := range gs.ClientsConsensus { - for _, consState := range cs.ConsensusStates { - consensusState, ok := consState.ConsensusState.GetCachedValue().(exported.ConsensusState) - if !ok { - panic(fmt.Sprintf("invalid consensus state with client ID %s at height %s", cs.ClientId, consState.Height)) - } - - k.SetClientConsensusState(ctx, cs.ClientId, consState.Height, consensusState) - } - } - - k.SetNextClientSequence(ctx, gs.NextClientSequence) - - // NOTE: localhost creation is specifically disallowed for the time being. - // Issue: https://github.com/cosmos/cosmos-sdk/issues/7871 -} - -// ExportGenesis returns the ibc client submodule's exported genesis. -// NOTE: CreateLocalhost should always be false on export since a -// created localhost will be included in the exported clients. -func ExportGenesis(ctx sdk.Context, k keeper.Keeper) types.GenesisState { - genClients := k.GetAllGenesisClients(ctx) - clientsMetadata, err := k.GetAllClientMetadata(ctx, genClients) - if err != nil { - panic(err) - } - return types.GenesisState{ - Clients: genClients, - ClientsMetadata: clientsMetadata, - ClientsConsensus: k.GetAllConsensusStates(ctx), - Params: k.GetParams(ctx), - CreateLocalhost: false, - } -} diff --git a/x/ibc/core/02-client/keeper/client.go b/x/ibc/core/02-client/keeper/client.go deleted file mode 100644 index e822402bfb3e..000000000000 --- a/x/ibc/core/02-client/keeper/client.go +++ /dev/null @@ -1,205 +0,0 @@ -package keeper - -import ( - "encoding/hex" - - "github.com/armon/go-metrics" - - "github.com/cosmos/cosmos-sdk/telemetry" - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -// CreateClient creates a new client state and populates it with a given consensus -// state as defined in https://github.com/cosmos/ics/tree/master/spec/ics-002-client-semantics#create -func (k Keeper) CreateClient( - ctx sdk.Context, clientState exported.ClientState, consensusState exported.ConsensusState, -) (string, error) { - params := k.GetParams(ctx) - if !params.IsAllowedClient(clientState.ClientType()) { - return "", sdkerrors.Wrapf( - types.ErrInvalidClientType, - "client state type %s is not registered in the allowlist", clientState.ClientType(), - ) - } - - clientID := k.GenerateClientIdentifier(ctx, clientState.ClientType()) - - k.SetClientState(ctx, clientID, clientState) - k.Logger(ctx).Info("client created at height", "client-id", clientID, "height", clientState.GetLatestHeight().String()) - - // verifies initial consensus state against client state and initializes client store with any client-specific metadata - // e.g. set ProcessedTime in Tendermint clients - if err := clientState.Initialize(ctx, k.cdc, k.ClientStore(ctx, clientID), consensusState); err != nil { - return "", err - } - - // check if consensus state is nil in case the created client is Localhost - if consensusState != nil { - k.SetClientConsensusState(ctx, clientID, clientState.GetLatestHeight(), consensusState) - } - - k.Logger(ctx).Info("client created at height", "client-id", clientID, "height", clientState.GetLatestHeight().String()) - - defer func() { - telemetry.IncrCounterWithLabels( - []string{"ibc", "client", "create"}, - 1, - []metrics.Label{telemetry.NewLabel("client-type", clientState.ClientType())}, - ) - }() - - return clientID, nil -} - -// UpdateClient updates the consensus state and the state root from a provided header. -func (k Keeper) UpdateClient(ctx sdk.Context, clientID string, header exported.Header) error { - clientState, found := k.GetClientState(ctx, clientID) - if !found { - return sdkerrors.Wrapf(types.ErrClientNotFound, "cannot update client with ID %s", clientID) - } - - // prevent update if the client is frozen before or at header height - if clientState.IsFrozen() && clientState.GetFrozenHeight().LTE(header.GetHeight()) { - return sdkerrors.Wrapf(types.ErrClientFrozen, "cannot update client with ID %s", clientID) - } - - clientState, consensusState, err := clientState.CheckHeaderAndUpdateState(ctx, k.cdc, k.ClientStore(ctx, clientID), header) - if err != nil { - return sdkerrors.Wrapf(err, "cannot update client with ID %s", clientID) - } - - k.SetClientState(ctx, clientID, clientState) - - var consensusHeight exported.Height - - // we don't set consensus state for localhost client - if header != nil && clientID != exported.Localhost { - k.SetClientConsensusState(ctx, clientID, header.GetHeight(), consensusState) - consensusHeight = header.GetHeight() - } else { - consensusHeight = types.GetSelfHeight(ctx) - } - - k.Logger(ctx).Info("client state updated", "client-id", clientID, "height", consensusHeight.String()) - - defer func() { - telemetry.IncrCounterWithLabels( - []string{"ibc", "client", "update"}, - 1, - []metrics.Label{ - telemetry.NewLabel("client-type", clientState.ClientType()), - telemetry.NewLabel("client-id", clientID), - telemetry.NewLabel("update-type", "msg"), - }, - ) - }() - - // emit the full header in events - var headerStr string - if header != nil { - // Marshal the Header as an Any and encode the resulting bytes to hex. - // This prevents the event value from containing invalid UTF-8 characters - // which may cause data to be lost when JSON encoding/decoding. - headerStr = hex.EncodeToString(types.MustMarshalHeader(k.cdc, header)) - - } - - // emitting events in the keeper emits for both begin block and handler client updates - ctx.EventManager().EmitEvent( - sdk.NewEvent( - types.EventTypeUpdateClient, - sdk.NewAttribute(types.AttributeKeyClientID, clientID), - sdk.NewAttribute(types.AttributeKeyClientType, clientState.ClientType()), - sdk.NewAttribute(types.AttributeKeyConsensusHeight, consensusHeight.String()), - sdk.NewAttribute(types.AttributeKeyHeader, headerStr), - ), - ) - - return nil -} - -// UpgradeClient upgrades the client to a new client state if this new client was committed to -// by the old client at the specified upgrade height -func (k Keeper) UpgradeClient(ctx sdk.Context, clientID string, upgradedClient exported.ClientState, upgradedConsState exported.ConsensusState, - proofUpgradeClient, proofUpgradeConsState []byte) error { - clientState, found := k.GetClientState(ctx, clientID) - if !found { - return sdkerrors.Wrapf(types.ErrClientNotFound, "cannot update client with ID %s", clientID) - } - - // prevent upgrade if current client is frozen - if clientState.IsFrozen() { - return sdkerrors.Wrapf(types.ErrClientFrozen, "cannot update client with ID %s", clientID) - } - - updatedClientState, updatedConsState, err := clientState.VerifyUpgradeAndUpdateState(ctx, k.cdc, k.ClientStore(ctx, clientID), - upgradedClient, upgradedConsState, proofUpgradeClient, proofUpgradeConsState) - if err != nil { - return sdkerrors.Wrapf(err, "cannot upgrade client with ID %s", clientID) - } - - k.SetClientState(ctx, clientID, updatedClientState) - k.SetClientConsensusState(ctx, clientID, updatedClientState.GetLatestHeight(), updatedConsState) - - k.Logger(ctx).Info("client state upgraded", "client-id", clientID, "height", updatedClientState.GetLatestHeight().String()) - - defer func() { - telemetry.IncrCounterWithLabels( - []string{"ibc", "client", "upgrade"}, - 1, - []metrics.Label{ - telemetry.NewLabel("client-type", updatedClientState.ClientType()), - telemetry.NewLabel("client-id", clientID), - }, - ) - }() - - // emitting events in the keeper emits for client upgrades - ctx.EventManager().EmitEvent( - sdk.NewEvent( - types.EventTypeUpgradeClient, - sdk.NewAttribute(types.AttributeKeyClientID, clientID), - sdk.NewAttribute(types.AttributeKeyClientType, updatedClientState.ClientType()), - sdk.NewAttribute(types.AttributeKeyConsensusHeight, updatedClientState.GetLatestHeight().String()), - ), - ) - - return nil -} - -// CheckMisbehaviourAndUpdateState checks for client misbehaviour and freezes the -// client if so. -func (k Keeper) CheckMisbehaviourAndUpdateState(ctx sdk.Context, misbehaviour exported.Misbehaviour) error { - clientState, found := k.GetClientState(ctx, misbehaviour.GetClientID()) - if !found { - return sdkerrors.Wrapf(types.ErrClientNotFound, "cannot check misbehaviour for client with ID %s", misbehaviour.GetClientID()) - } - - if clientState.IsFrozen() && clientState.GetFrozenHeight().LTE(misbehaviour.GetHeight()) { - return sdkerrors.Wrapf(types.ErrInvalidMisbehaviour, "client is already frozen at height ≤ misbehaviour height (%s ≤ %s)", clientState.GetFrozenHeight(), misbehaviour.GetHeight()) - } - - clientState, err := clientState.CheckMisbehaviourAndUpdateState(ctx, k.cdc, k.ClientStore(ctx, misbehaviour.GetClientID()), misbehaviour) - if err != nil { - return err - } - - k.SetClientState(ctx, misbehaviour.GetClientID(), clientState) - k.Logger(ctx).Info("client frozen due to misbehaviour", "client-id", misbehaviour.GetClientID(), "height", misbehaviour.GetHeight().String()) - - defer func() { - telemetry.IncrCounterWithLabels( - []string{"ibc", "client", "misbehaviour"}, - 1, - []metrics.Label{ - telemetry.NewLabel("client-type", misbehaviour.ClientType()), - telemetry.NewLabel("client-id", misbehaviour.GetClientID()), - }, - ) - }() - - return nil -} diff --git a/x/ibc/core/02-client/keeper/client_test.go b/x/ibc/core/02-client/keeper/client_test.go deleted file mode 100644 index 320837a92f4e..000000000000 --- a/x/ibc/core/02-client/keeper/client_test.go +++ /dev/null @@ -1,628 +0,0 @@ -package keeper_test - -import ( - "encoding/hex" - "fmt" - "time" - - tmtypes "github.com/tendermint/tendermint/types" - - "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - 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/core/exported" - ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" - localhosttypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/09-localhost/types" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" - ibctestingmock "github.com/cosmos/cosmos-sdk/x/ibc/testing/mock" - upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" -) - -func (suite *KeeperTestSuite) TestCreateClient() { - cases := []struct { - msg string - clientState exported.ClientState - expPass bool - }{ - {"success", ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), true}, - {"client type not supported", localhosttypes.NewClientState(testChainID, clienttypes.NewHeight(0, 1)), false}, - } - - for i, tc := range cases { - - clientID, err := suite.keeper.CreateClient(suite.ctx, tc.clientState, suite.consensusState) - if tc.expPass { - suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.msg) - suite.Require().NotNil(clientID, "valid test case %d failed: %s", i, tc.msg) - } else { - suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.msg) - suite.Require().Equal("", clientID, "invalid test case %d passed: %s", i, tc.msg) - } - } -} - -func (suite *KeeperTestSuite) TestUpdateClientTendermint() { - // Must create header creation functions since suite.header gets recreated on each test case - createFutureUpdateFn := func(s *KeeperTestSuite) *ibctmtypes.Header { - heightPlus3 := clienttypes.NewHeight(suite.header.GetHeight().GetRevisionNumber(), suite.header.GetHeight().GetRevisionHeight()+3) - height := suite.header.GetHeight().(clienttypes.Height) - - return suite.chainA.CreateTMClientHeader(testChainID, int64(heightPlus3.RevisionHeight), height, suite.header.Header.Time.Add(time.Hour), - suite.valSet, suite.valSet, []tmtypes.PrivValidator{suite.privVal}) - } - createPastUpdateFn := func(s *KeeperTestSuite) *ibctmtypes.Header { - heightMinus2 := clienttypes.NewHeight(suite.header.GetHeight().GetRevisionNumber(), suite.header.GetHeight().GetRevisionHeight()-2) - heightMinus4 := clienttypes.NewHeight(suite.header.GetHeight().GetRevisionNumber(), suite.header.GetHeight().GetRevisionHeight()-4) - - return suite.chainA.CreateTMClientHeader(testChainID, int64(heightMinus2.RevisionHeight), heightMinus4, suite.header.Header.Time, - suite.valSet, suite.valSet, []tmtypes.PrivValidator{suite.privVal}) - } - var ( - updateHeader *ibctmtypes.Header - clientState *ibctmtypes.ClientState - clientID string - err error - ) - - cases := []struct { - name string - malleate func() error - expPass bool - }{ - {"valid update", func() error { - clientState = ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) - clientID, err = suite.keeper.CreateClient(suite.ctx, clientState, suite.consensusState) - - // store intermediate consensus state to check that trustedHeight does not need to be highest consensus state before header height - incrementedClientHeight := testClientHeight.Increment().(types.Height) - intermediateConsState := &ibctmtypes.ConsensusState{ - Timestamp: suite.now.Add(time.Minute), - NextValidatorsHash: suite.valSetHash, - } - suite.keeper.SetClientConsensusState(suite.ctx, clientID, incrementedClientHeight, intermediateConsState) - - clientState.LatestHeight = incrementedClientHeight - suite.keeper.SetClientState(suite.ctx, clientID, clientState) - - updateHeader = createFutureUpdateFn(suite) - return err - }, true}, - {"valid past update", func() error { - clientState = ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) - clientID, err = suite.keeper.CreateClient(suite.ctx, clientState, suite.consensusState) - suite.Require().NoError(err) - - height1 := types.NewHeight(0, 1) - - // store previous consensus state - prevConsState := &ibctmtypes.ConsensusState{ - Timestamp: suite.past, - NextValidatorsHash: suite.valSetHash, - } - suite.keeper.SetClientConsensusState(suite.ctx, clientID, height1, prevConsState) - - height2 := types.NewHeight(0, 2) - - // store intermediate consensus state to check that trustedHeight does not need to be hightest consensus state before header height - intermediateConsState := &ibctmtypes.ConsensusState{ - Timestamp: suite.past.Add(time.Minute), - NextValidatorsHash: suite.valSetHash, - } - suite.keeper.SetClientConsensusState(suite.ctx, clientID, height2, intermediateConsState) - - // updateHeader will fill in consensus state between prevConsState and suite.consState - // clientState should not be updated - updateHeader = createPastUpdateFn(suite) - return nil - }, true}, - {"client state not found", func() error { - updateHeader = createFutureUpdateFn(suite) - - return nil - }, false}, - {"consensus state not found", func() error { - clientState = ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) - suite.keeper.SetClientState(suite.ctx, testClientID, clientState) - updateHeader = createFutureUpdateFn(suite) - - return nil - }, false}, - {"frozen client before update", func() error { - clientState = &ibctmtypes.ClientState{FrozenHeight: types.NewHeight(0, 1), LatestHeight: testClientHeight} - suite.keeper.SetClientState(suite.ctx, testClientID, clientState) - updateHeader = createFutureUpdateFn(suite) - - return nil - }, false}, - {"valid past update before client was frozen", func() error { - clientState = ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) - clientState.FrozenHeight = types.NewHeight(0, testClientHeight.RevisionHeight-1) - clientID, err = suite.keeper.CreateClient(suite.ctx, clientState, suite.consensusState) - suite.Require().NoError(err) - - height1 := types.NewHeight(0, 1) - - // store previous consensus state - prevConsState := &ibctmtypes.ConsensusState{ - Timestamp: suite.past, - NextValidatorsHash: suite.valSetHash, - } - suite.keeper.SetClientConsensusState(suite.ctx, clientID, height1, prevConsState) - - // updateHeader will fill in consensus state between prevConsState and suite.consState - // clientState should not be updated - updateHeader = createPastUpdateFn(suite) - return nil - }, true}, - {"invalid header", func() error { - clientState = ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) - _, err := suite.keeper.CreateClient(suite.ctx, clientState, suite.consensusState) - suite.Require().NoError(err) - updateHeader = createPastUpdateFn(suite) - - return nil - }, false}, - } - - for i, tc := range cases { - tc := tc - i := i - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.SetupTest() - clientID = testClientID // must be explicitly changed - - err := tc.malleate() - suite.Require().NoError(err) - - suite.ctx = suite.ctx.WithBlockTime(updateHeader.Header.Time.Add(time.Minute)) - - err = suite.keeper.UpdateClient(suite.ctx, clientID, updateHeader) - - if tc.expPass { - suite.Require().NoError(err, err) - - expConsensusState := &ibctmtypes.ConsensusState{ - Timestamp: updateHeader.GetTime(), - Root: commitmenttypes.NewMerkleRoot(updateHeader.Header.GetAppHash()), - NextValidatorsHash: updateHeader.Header.NextValidatorsHash, - } - - newClientState, found := suite.keeper.GetClientState(suite.ctx, clientID) - suite.Require().True(found, "valid test case %d failed: %s", i, tc.name) - - consensusState, found := suite.keeper.GetClientConsensusState(suite.ctx, clientID, updateHeader.GetHeight()) - suite.Require().True(found, "valid test case %d failed: %s", i, tc.name) - - // Determine if clientState should be updated or not - if updateHeader.GetHeight().GT(clientState.GetLatestHeight()) { - // Header Height is greater than clientState latest Height, clientState should be updated with header.GetHeight() - suite.Require().Equal(updateHeader.GetHeight(), newClientState.GetLatestHeight(), "clientstate height did not update") - } else { - // Update will add past consensus state, clientState should not be updated at all - suite.Require().Equal(clientState.GetLatestHeight(), newClientState.GetLatestHeight(), "client state height updated for past header") - } - - suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name) - suite.Require().Equal(expConsensusState, consensusState, "consensus state should have been updated on case %s", tc.name) - } else { - suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name) - } - }) - } -} - -func (suite *KeeperTestSuite) TestUpdateClientLocalhost() { - revision := types.ParseChainID(suite.chainA.ChainID) - var localhostClient exported.ClientState = localhosttypes.NewClientState(suite.chainA.ChainID, types.NewHeight(revision, uint64(suite.chainA.GetContext().BlockHeight()))) - - ctx := suite.chainA.GetContext().WithBlockHeight(suite.chainA.GetContext().BlockHeight() + 1) - err := suite.chainA.App.IBCKeeper.ClientKeeper.UpdateClient(ctx, exported.Localhost, nil) - suite.Require().NoError(err) - - clientState, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(ctx, exported.Localhost) - suite.Require().True(found) - suite.Require().Equal(localhostClient.GetLatestHeight().(types.Height).Increment(), clientState.GetLatestHeight()) -} - -func (suite *KeeperTestSuite) TestUpgradeClient() { - var ( - upgradedClient exported.ClientState - upgradedConsState exported.ConsensusState - lastHeight exported.Height - clientA string - proofUpgradedClient, proofUpgradedConsState []byte - upgradedClientBz, upgradedConsStateBz []byte - err error - ) - - testCases := []struct { - name string - setup func() - expPass bool - }{ - { - name: "successful upgrade", - setup: func() { - // last Height is at next block - lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) - - // zero custom fields and store in upgrade store - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) - suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) - - // commit upgrade store changes and update clients - - suite.coordinator.CommitBlock(suite.chainB) - err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - suite.Require().NoError(err) - - cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA) - suite.Require().True(found) - - proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - }, - expPass: true, - }, - { - name: "client state not found", - setup: func() { - // last Height is at next block - lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) - - // zero custom fields and store in upgrade store - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) - suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) - - // commit upgrade store changes and update clients - - suite.coordinator.CommitBlock(suite.chainB) - err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - suite.Require().NoError(err) - - cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA) - suite.Require().True(found) - - proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - - clientA = "wrongclientid" - }, - expPass: false, - }, - { - name: "client state frozen", - setup: func() { - // last Height is at next block - lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) - - // zero custom fields and store in upgrade store - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) - suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) - - // commit upgrade store changes and update clients - - suite.coordinator.CommitBlock(suite.chainB) - err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - suite.Require().NoError(err) - - cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA) - suite.Require().True(found) - - proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - - // set frozen client in store - tmClient, ok := cs.(*ibctmtypes.ClientState) - suite.Require().True(ok) - tmClient.FrozenHeight = types.NewHeight(0, 1) - suite.chainA.App.IBCKeeper.ClientKeeper.SetClientState(suite.chainA.GetContext(), clientA, tmClient) - }, - expPass: false, - }, - { - name: "tendermint client VerifyUpgrade fails", - setup: func() { - // last Height is at next block - lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) - - // zero custom fields and store in upgrade store - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) - suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) - - // change upgradedClient client-specified parameters - upgradedClient = ibctmtypes.NewClientState("wrongchainID", ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, true, true) - - suite.coordinator.CommitBlock(suite.chainB) - err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - suite.Require().NoError(err) - - cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA) - suite.Require().True(found) - - proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - }, - expPass: false, - }, - } - - for _, tc := range testCases { - tc := tc - clientA, _ = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - upgradedClient = ibctmtypes.NewClientState("newChainId", ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) - upgradedClient = upgradedClient.ZeroCustomFields() - upgradedClientBz, err = types.MarshalClientState(suite.chainA.App.AppCodec(), upgradedClient) - suite.Require().NoError(err) - - upgradedConsState = &ibctmtypes.ConsensusState{ - NextValidatorsHash: []byte("nextValsHash"), - } - upgradedConsStateBz, err = types.MarshalConsensusState(suite.chainA.App.AppCodec(), upgradedConsState) - suite.Require().NoError(err) - - tc.setup() - - // Call ZeroCustomFields on upgraded clients to clear any client-chosen parameters in test-case upgradedClient - upgradedClient = upgradedClient.ZeroCustomFields() - - err = suite.chainA.App.IBCKeeper.ClientKeeper.UpgradeClient(suite.chainA.GetContext(), clientA, upgradedClient, upgradedConsState, proofUpgradedClient, proofUpgradedConsState) - - if tc.expPass { - suite.Require().NoError(err, "verify upgrade failed on valid case: %s", tc.name) - } else { - suite.Require().Error(err, "verify upgrade passed on invalid case: %s", tc.name) - } - } - -} - -func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() { - var ( - clientID string - err error - ) - - altPrivVal := ibctestingmock.NewPV() - altPubKey, err := altPrivVal.GetPubKey() - suite.Require().NoError(err) - altVal := tmtypes.NewValidator(altPubKey, 4) - - // Set valSet here with suite.valSet so it doesn't get reset on each testcase - valSet := suite.valSet - valsHash := valSet.Hash() - - // Create bothValSet with both suite validator and altVal - bothValSet := tmtypes.NewValidatorSet(append(suite.valSet.Validators, altVal)) - bothValsHash := bothValSet.Hash() - // Create alternative validator set with only altVal - altValSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{altVal}) - - // Create signer array and ensure it is in same order as bothValSet - _, suiteVal := suite.valSet.GetByIndex(0) - bothSigners := ibctesting.CreateSortedSignerArray(altPrivVal, suite.privVal, altVal, suiteVal) - - altSigners := []tmtypes.PrivValidator{altPrivVal} - - // Create valid Misbehaviour by making a duplicate header that signs over different block time - altTime := suite.ctx.BlockTime().Add(time.Minute) - - heightPlus3 := types.NewHeight(0, height+3) - heightPlus5 := types.NewHeight(0, height+5) - - testCases := []struct { - name string - misbehaviour *ibctmtypes.Misbehaviour - malleate func() error - expPass bool - }{ - { - "trusting period misbehavior should pass", - &ibctmtypes.Misbehaviour{ - Header1: suite.chainA.CreateTMClientHeader(testChainID, int64(testClientHeight.RevisionHeight), testClientHeight, altTime, bothValSet, bothValSet, bothSigners), - Header2: suite.chainA.CreateTMClientHeader(testChainID, int64(testClientHeight.RevisionHeight), testClientHeight, suite.ctx.BlockTime(), bothValSet, bothValSet, bothSigners), - ClientId: clientID, - }, - func() error { - suite.consensusState.NextValidatorsHash = bothValsHash - clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) - clientID, err = suite.keeper.CreateClient(suite.ctx, clientState, suite.consensusState) - - return err - }, - true, - }, - { - "misbehavior at later height should pass", - &ibctmtypes.Misbehaviour{ - Header1: suite.chainA.CreateTMClientHeader(testChainID, int64(heightPlus5.RevisionHeight), testClientHeight, altTime, bothValSet, valSet, bothSigners), - Header2: suite.chainA.CreateTMClientHeader(testChainID, int64(heightPlus5.RevisionHeight), testClientHeight, suite.ctx.BlockTime(), bothValSet, valSet, bothSigners), - ClientId: clientID, - }, - func() error { - suite.consensusState.NextValidatorsHash = valsHash - clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) - clientID, err = suite.keeper.CreateClient(suite.ctx, clientState, suite.consensusState) - - // store intermediate consensus state to check that trustedHeight does not need to be highest consensus state before header height - intermediateConsState := &ibctmtypes.ConsensusState{ - Timestamp: suite.now.Add(time.Minute), - NextValidatorsHash: suite.valSetHash, - } - suite.keeper.SetClientConsensusState(suite.ctx, clientID, heightPlus3, intermediateConsState) - - clientState.LatestHeight = heightPlus3 - suite.keeper.SetClientState(suite.ctx, clientID, clientState) - - return err - }, - true, - }, - { - "misbehavior at later height with different trusted heights should pass", - &ibctmtypes.Misbehaviour{ - Header1: suite.chainA.CreateTMClientHeader(testChainID, int64(heightPlus5.RevisionHeight), testClientHeight, altTime, bothValSet, valSet, bothSigners), - Header2: suite.chainA.CreateTMClientHeader(testChainID, int64(heightPlus5.RevisionHeight), heightPlus3, suite.ctx.BlockTime(), bothValSet, bothValSet, bothSigners), - ClientId: clientID, - }, - func() error { - suite.consensusState.NextValidatorsHash = valsHash - clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) - clientID, err = suite.keeper.CreateClient(suite.ctx, clientState, suite.consensusState) - - // store trusted consensus state for Header2 - intermediateConsState := &ibctmtypes.ConsensusState{ - Timestamp: suite.now.Add(time.Minute), - NextValidatorsHash: bothValsHash, - } - suite.keeper.SetClientConsensusState(suite.ctx, clientID, heightPlus3, intermediateConsState) - - clientState.LatestHeight = heightPlus3 - suite.keeper.SetClientState(suite.ctx, clientID, clientState) - - return err - }, - true, - }, - { - "trusted ConsensusState1 not found", - &ibctmtypes.Misbehaviour{ - Header1: suite.chainA.CreateTMClientHeader(testChainID, int64(heightPlus5.RevisionHeight), heightPlus3, altTime, bothValSet, bothValSet, bothSigners), - Header2: suite.chainA.CreateTMClientHeader(testChainID, int64(heightPlus5.RevisionHeight), testClientHeight, suite.ctx.BlockTime(), bothValSet, valSet, bothSigners), - ClientId: clientID, - }, - func() error { - suite.consensusState.NextValidatorsHash = valsHash - clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) - clientID, err = suite.keeper.CreateClient(suite.ctx, clientState, suite.consensusState) - // intermediate consensus state at height + 3 is not created - return err - }, - false, - }, - { - "trusted ConsensusState2 not found", - &ibctmtypes.Misbehaviour{ - Header1: suite.chainA.CreateTMClientHeader(testChainID, int64(heightPlus5.RevisionHeight), testClientHeight, altTime, bothValSet, valSet, bothSigners), - Header2: suite.chainA.CreateTMClientHeader(testChainID, int64(heightPlus5.RevisionHeight), heightPlus3, suite.ctx.BlockTime(), bothValSet, bothValSet, bothSigners), - ClientId: clientID, - }, - func() error { - suite.consensusState.NextValidatorsHash = valsHash - clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) - clientID, err = suite.keeper.CreateClient(suite.ctx, clientState, suite.consensusState) - // intermediate consensus state at height + 3 is not created - return err - }, - false, - }, - { - "client state not found", - &ibctmtypes.Misbehaviour{}, - func() error { return nil }, - false, - }, - { - "client already frozen at earlier height", - &ibctmtypes.Misbehaviour{ - Header1: suite.chainA.CreateTMClientHeader(testChainID, int64(testClientHeight.RevisionHeight), testClientHeight, altTime, bothValSet, bothValSet, bothSigners), - Header2: suite.chainA.CreateTMClientHeader(testChainID, int64(testClientHeight.RevisionHeight), testClientHeight, suite.ctx.BlockTime(), bothValSet, bothValSet, bothSigners), - ClientId: clientID, - }, - func() error { - suite.consensusState.NextValidatorsHash = bothValsHash - clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) - clientID, err = suite.keeper.CreateClient(suite.ctx, clientState, suite.consensusState) - - clientState.FrozenHeight = types.NewHeight(0, 1) - suite.keeper.SetClientState(suite.ctx, clientID, clientState) - - return err - }, - false, - }, - { - "misbehaviour check failed", - &ibctmtypes.Misbehaviour{ - Header1: suite.chainA.CreateTMClientHeader(testChainID, int64(testClientHeight.RevisionHeight), testClientHeight, altTime, bothValSet, bothValSet, bothSigners), - Header2: suite.chainA.CreateTMClientHeader(testChainID, int64(testClientHeight.RevisionHeight), testClientHeight, suite.ctx.BlockTime(), altValSet, bothValSet, altSigners), - ClientId: clientID, - }, - func() error { - clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) - if err != nil { - return err - } - clientID, err = suite.keeper.CreateClient(suite.ctx, clientState, suite.consensusState) - - return err - }, - false, - }, - } - - for i, tc := range testCases { - tc := tc - i := i - - suite.Run(tc.name, func() { - suite.SetupTest() // reset - clientID = testClientID // must be explicitly changed - - err := tc.malleate() - suite.Require().NoError(err) - - tc.misbehaviour.ClientId = clientID - - err = suite.keeper.CheckMisbehaviourAndUpdateState(suite.ctx, tc.misbehaviour) - - if tc.expPass { - suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name) - - clientState, found := suite.keeper.GetClientState(suite.ctx, clientID) - suite.Require().True(found, "valid test case %d failed: %s", i, tc.name) - suite.Require().True(clientState.IsFrozen(), "valid test case %d failed: %s", i, tc.name) - suite.Require().Equal(tc.misbehaviour.GetHeight(), clientState.GetFrozenHeight(), - "valid test case %d failed: %s. Expected FrozenHeight %s got %s", tc.misbehaviour.GetHeight(), clientState.GetFrozenHeight()) - } else { - suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name) - } - }) - } -} - -func (suite *KeeperTestSuite) TestUpdateClientEventEmission() { - clientID, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - header, err := suite.chainA.ConstructUpdateTMClientHeader(suite.chainB, clientID) - suite.Require().NoError(err) - - msg, err := clienttypes.NewMsgUpdateClient( - clientID, header, - suite.chainA.SenderAccount.GetAddress(), - ) - - result, err := suite.chainA.SendMsgs(msg) - suite.Require().NoError(err) - // first event type is "message" - updateEvent := result.Events[1] - - suite.Require().Equal(clienttypes.EventTypeUpdateClient, updateEvent.Type) - - // use a boolean to ensure the update event contains the header - contains := false - for _, attr := range updateEvent.Attributes { - if string(attr.Key) == clienttypes.AttributeKeyHeader { - contains = true - - bz, err := hex.DecodeString(string(attr.Value)) - suite.Require().NoError(err) - - emittedHeader, err := types.UnmarshalHeader(suite.chainA.App.AppCodec(), bz) - suite.Require().NoError(err) - suite.Require().Equal(header, emittedHeader) - } - - } - suite.Require().True(contains) - -} diff --git a/x/ibc/core/02-client/keeper/encoding.go b/x/ibc/core/02-client/keeper/encoding.go deleted file mode 100644 index f2a07b864d27..000000000000 --- a/x/ibc/core/02-client/keeper/encoding.go +++ /dev/null @@ -1,42 +0,0 @@ -package keeper - -import ( - "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -// UnmarshalClientState attempts to decode and return an ClientState object from -// raw encoded bytes. -func (k Keeper) UnmarshalClientState(bz []byte) (exported.ClientState, error) { - return types.UnmarshalClientState(k.cdc, bz) -} - -// MustUnmarshalClientState attempts to decode and return an ClientState object from -// raw encoded bytes. It panics on error. -func (k Keeper) MustUnmarshalClientState(bz []byte) exported.ClientState { - return types.MustUnmarshalClientState(k.cdc, bz) -} - -// UnmarshalConsensusState attempts to decode and return an ConsensusState object from -// raw encoded bytes. -func (k Keeper) UnmarshalConsensusState(bz []byte) (exported.ConsensusState, error) { - return types.UnmarshalConsensusState(k.cdc, bz) -} - -// MustUnmarshalConsensusState attempts to decode and return an ConsensusState object from -// raw encoded bytes. It panics on error. -func (k Keeper) MustUnmarshalConsensusState(bz []byte) exported.ConsensusState { - return types.MustUnmarshalConsensusState(k.cdc, bz) -} - -// MustMarshalClientState attempts to encode an ClientState object and returns the -// raw encoded bytes. It panics on error. -func (k Keeper) MustMarshalClientState(clientState exported.ClientState) []byte { - return types.MustMarshalClientState(k.cdc, clientState) -} - -// MustMarshalConsensusState attempts to encode an ConsensusState object and returns the -// raw encoded bytes. It panics on error. -func (k Keeper) MustMarshalConsensusState(consensusState exported.ConsensusState) []byte { - return types.MustMarshalConsensusState(k.cdc, consensusState) -} diff --git a/x/ibc/core/02-client/keeper/grpc_query.go b/x/ibc/core/02-client/keeper/grpc_query.go deleted file mode 100644 index cc4b256d30e7..000000000000 --- a/x/ibc/core/02-client/keeper/grpc_query.go +++ /dev/null @@ -1,242 +0,0 @@ -package keeper - -import ( - "bytes" - "context" - "fmt" - "sort" - "strings" - - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - - "github.com/cosmos/cosmos-sdk/store/prefix" - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/cosmos/cosmos-sdk/types/query" - "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -var _ types.QueryServer = Keeper{} - -// ClientState implements the Query/ClientState gRPC method -func (q Keeper) ClientState(c context.Context, req *types.QueryClientStateRequest) (*types.QueryClientStateResponse, error) { - if req == nil { - return nil, status.Error(codes.InvalidArgument, "empty request") - } - - if err := host.ClientIdentifierValidator(req.ClientId); err != nil { - return nil, status.Error(codes.InvalidArgument, err.Error()) - } - - ctx := sdk.UnwrapSDKContext(c) - clientState, found := q.GetClientState(ctx, req.ClientId) - if !found { - return nil, status.Error( - codes.NotFound, - sdkerrors.Wrap(types.ErrClientNotFound, req.ClientId).Error(), - ) - } - - any, err := types.PackClientState(clientState) - if err != nil { - return nil, status.Error(codes.Internal, err.Error()) - } - - proofHeight := types.GetSelfHeight(ctx) - return &types.QueryClientStateResponse{ - ClientState: any, - ProofHeight: proofHeight, - }, nil -} - -// ClientStates implements the Query/ClientStates gRPC method -func (q Keeper) ClientStates(c context.Context, req *types.QueryClientStatesRequest) (*types.QueryClientStatesResponse, error) { - if req == nil { - return nil, status.Error(codes.InvalidArgument, "empty request") - } - - ctx := sdk.UnwrapSDKContext(c) - - clientStates := types.IdentifiedClientStates{} - store := prefix.NewStore(ctx.KVStore(q.storeKey), host.KeyClientStorePrefix) - - pageRes, err := query.Paginate(store, req.Pagination, func(key, value []byte) error { - keySplit := strings.Split(string(key), "/") - if keySplit[len(keySplit)-1] != "clientState" { - return nil - } - - clientState, err := q.UnmarshalClientState(value) - if err != nil { - return err - } - - clientID := keySplit[1] - if err := host.ClientIdentifierValidator(clientID); err != nil { - return err - } - - identifiedClient := types.NewIdentifiedClientState(clientID, clientState) - clientStates = append(clientStates, identifiedClient) - return nil - }) - - if err != nil { - return nil, err - } - - sort.Sort(clientStates) - - return &types.QueryClientStatesResponse{ - ClientStates: clientStates, - Pagination: pageRes, - }, nil -} - -// ConsensusState implements the Query/ConsensusState gRPC method -func (q Keeper) ConsensusState(c context.Context, req *types.QueryConsensusStateRequest) (*types.QueryConsensusStateResponse, error) { - if req == nil { - return nil, status.Error(codes.InvalidArgument, "empty request") - } - - if err := host.ClientIdentifierValidator(req.ClientId); err != nil { - return nil, status.Error(codes.InvalidArgument, err.Error()) - } - - ctx := sdk.UnwrapSDKContext(c) - - var ( - consensusState exported.ConsensusState - found bool - ) - - height := types.NewHeight(req.RevisionNumber, req.RevisionHeight) - if req.LatestHeight { - consensusState, found = q.GetLatestClientConsensusState(ctx, req.ClientId) - } else { - if req.RevisionHeight == 0 { - return nil, status.Error(codes.InvalidArgument, "consensus state height cannot be 0") - } - - consensusState, found = q.GetClientConsensusState(ctx, req.ClientId, height) - } - - if !found { - return nil, status.Error( - codes.NotFound, - sdkerrors.Wrapf(types.ErrConsensusStateNotFound, "client-id: %s, height: %s", req.ClientId, height).Error(), - ) - } - - any, err := types.PackConsensusState(consensusState) - if err != nil { - return nil, status.Error(codes.Internal, err.Error()) - } - - proofHeight := types.GetSelfHeight(ctx) - return &types.QueryConsensusStateResponse{ - ConsensusState: any, - ProofHeight: proofHeight, - }, nil -} - -// ConsensusStates implements the Query/ConsensusStates gRPC method -func (q Keeper) ConsensusStates(c context.Context, req *types.QueryConsensusStatesRequest) (*types.QueryConsensusStatesResponse, error) { - if req == nil { - return nil, status.Error(codes.InvalidArgument, "empty request") - } - - if err := host.ClientIdentifierValidator(req.ClientId); err != nil { - return nil, status.Error(codes.InvalidArgument, err.Error()) - } - - ctx := sdk.UnwrapSDKContext(c) - - consensusStates := []types.ConsensusStateWithHeight{} - store := prefix.NewStore(ctx.KVStore(q.storeKey), host.FullClientKey(req.ClientId, []byte(fmt.Sprintf("%s/", host.KeyConsensusStatePrefix)))) - - pageRes, err := query.FilteredPaginate(store, req.Pagination, func(key, value []byte, accumulate bool) (bool, error) { - // filter any metadata stored under consensus state key - if bytes.Contains(key, []byte("/")) { - return false, nil - } - - height, err := types.ParseHeight(string(key)) - if err != nil { - return false, err - } - - consensusState, err := q.UnmarshalConsensusState(value) - if err != nil { - return false, err - } - - consensusStates = append(consensusStates, types.NewConsensusStateWithHeight(height, consensusState)) - return true, nil - }) - - if err != nil { - return nil, err - } - - return &types.QueryConsensusStatesResponse{ - ConsensusStates: consensusStates, - Pagination: pageRes, - }, nil -} - -// ClientParams implements the Query/ClientParams gRPC method -func (q Keeper) ClientParams(c context.Context, _ *types.QueryClientParamsRequest) (*types.QueryClientParamsResponse, error) { - ctx := sdk.UnwrapSDKContext(c) - params := q.GetParams(ctx) - - return &types.QueryClientParamsResponse{ - Params: ¶ms, - }, nil -} - -// UpgradedClientState implements the Query/UpgradedClientState gRPC method -func (q Keeper) UpgradedClientState(c context.Context, req *types.QueryUpgradedClientStateRequest) (*types.QueryUpgradedClientStateResponse, error) { - if req == nil { - return nil, status.Error(codes.InvalidArgument, "empty request") - } - - if err := host.ClientIdentifierValidator(req.ClientId); err != nil { - return nil, status.Error(codes.InvalidArgument, err.Error()) - } - - ctx := sdk.UnwrapSDKContext(c) - plan, found := q.GetUpgradePlan(ctx) - if !found { - return nil, status.Error( - codes.NotFound, "upgrade plan not found", - ) - } - - bz, found := q.GetUpgradedClient(ctx, plan.Height) - if !found { - return nil, status.Error( - codes.NotFound, - sdkerrors.Wrap(types.ErrClientNotFound, req.ClientId).Error(), - ) - } - - clientState, err := types.UnmarshalClientState(q.cdc, bz) - if err != nil { - return nil, status.Error( - codes.Internal, err.Error(), - ) - } - - any, err := types.PackClientState(clientState) - if err != nil { - return nil, status.Error(codes.Internal, err.Error()) - } - - return &types.QueryUpgradedClientStateResponse{ - UpgradedClientState: any, - }, nil -} diff --git a/x/ibc/core/02-client/keeper/grpc_query_test.go b/x/ibc/core/02-client/keeper/grpc_query_test.go deleted file mode 100644 index 5e361a76f083..000000000000 --- a/x/ibc/core/02-client/keeper/grpc_query_test.go +++ /dev/null @@ -1,381 +0,0 @@ -package keeper_test - -import ( - "fmt" - "time" - - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - sdk "github.com/cosmos/cosmos-sdk/types" - - "github.com/cosmos/cosmos-sdk/types/query" - "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/core/exported" - ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" -) - -func (suite *KeeperTestSuite) TestQueryClientState() { - var ( - req *types.QueryClientStateRequest - expClientState *codectypes.Any - ) - - testCases := []struct { - msg string - malleate func() - expPass bool - }{ - {"invalid clientID", - func() { - req = &types.QueryClientStateRequest{} - }, - false, - }, - {"client not found", - func() { - req = &types.QueryClientStateRequest{ - ClientId: testClientID, - } - }, - false, - }, - { - "success", - func() { - clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.ZeroHeight(), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) - suite.keeper.SetClientState(suite.ctx, testClientID, clientState) - - var err error - expClientState, err = types.PackClientState(clientState) - suite.Require().NoError(err) - - req = &types.QueryClientStateRequest{ - ClientId: testClientID, - } - }, - 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.ClientState(ctx, req) - - if tc.expPass { - suite.Require().NoError(err) - suite.Require().NotNil(res) - suite.Require().Equal(expClientState, res.ClientState) - - // ensure UnpackInterfaces is defined - cachedValue := res.ClientState.GetCachedValue() - suite.Require().NotNil(cachedValue) - } else { - suite.Require().Error(err) - } - }) - } -} - -func (suite *KeeperTestSuite) TestQueryClientStates() { - var ( - req *types.QueryClientStatesRequest - expClientStates = types.IdentifiedClientStates{} - ) - - testCases := []struct { - msg string - malleate func() - expPass bool - }{ - { - "empty pagination", - func() { - req = &types.QueryClientStatesRequest{} - }, - true, - }, - { - "success, no results", - func() { - req = &types.QueryClientStatesRequest{ - Pagination: &query.PageRequest{ - Limit: 3, - CountTotal: true, - }, - } - }, - true, - }, - { - "success", - func() { - clientA1, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - clientA2, _ := suite.coordinator.CreateClient(suite.chainA, suite.chainB, exported.Tendermint) - - clientStateA1 := suite.chainA.GetClientState(clientA1) - clientStateA2 := suite.chainA.GetClientState(clientA2) - - idcs := types.NewIdentifiedClientState(clientA1, clientStateA1) - idcs2 := types.NewIdentifiedClientState(clientA2, clientStateA2) - - // order is sorted by client id, localhost is last - expClientStates = types.IdentifiedClientStates{idcs, idcs2}.Sort() - req = &types.QueryClientStatesRequest{ - Pagination: &query.PageRequest{ - Limit: 7, - CountTotal: true, - }, - } - }, - true, - }, - } - - for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { - suite.SetupTest() // reset - expClientStates = nil - - tc.malleate() - - // always add localhost which is created by default in init genesis - localhostClientState := suite.chainA.GetClientState(exported.Localhost) - identifiedLocalhost := types.NewIdentifiedClientState(exported.Localhost, localhostClientState) - expClientStates = append(expClientStates, identifiedLocalhost) - - ctx := sdk.WrapSDKContext(suite.chainA.GetContext()) - - res, err := suite.chainA.QueryServer.ClientStates(ctx, req) - - if tc.expPass { - suite.Require().NoError(err) - suite.Require().NotNil(res) - suite.Require().Equal(expClientStates.Sort(), res.ClientStates) - } else { - suite.Require().Error(err) - } - }) - } -} - -func (suite *KeeperTestSuite) TestQueryConsensusState() { - var ( - req *types.QueryConsensusStateRequest - expConsensusState *codectypes.Any - ) - - testCases := []struct { - msg string - malleate func() - expPass bool - }{ - { - "invalid clientID", - func() { - req = &types.QueryConsensusStateRequest{} - }, - false, - }, - { - "invalid height", - func() { - req = &types.QueryConsensusStateRequest{ - ClientId: testClientID, - RevisionNumber: 0, - RevisionHeight: 0, - LatestHeight: false, - } - }, - false, - }, - { - "consensus state not found", - func() { - req = &types.QueryConsensusStateRequest{ - ClientId: testClientID, - LatestHeight: true, - } - }, - false, - }, - { - "success latest height", - func() { - clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) - cs := ibctmtypes.NewConsensusState( - suite.consensusState.Timestamp, commitmenttypes.NewMerkleRoot([]byte("hash1")), nil, - ) - suite.keeper.SetClientState(suite.ctx, testClientID, clientState) - suite.keeper.SetClientConsensusState(suite.ctx, testClientID, testClientHeight, cs) - - var err error - expConsensusState, err = types.PackConsensusState(cs) - suite.Require().NoError(err) - - req = &types.QueryConsensusStateRequest{ - ClientId: testClientID, - LatestHeight: true, - } - }, - true, - }, - { - "success with height", - func() { - cs := ibctmtypes.NewConsensusState( - suite.consensusState.Timestamp, commitmenttypes.NewMerkleRoot([]byte("hash1")), nil, - ) - suite.keeper.SetClientConsensusState(suite.ctx, testClientID, testClientHeight, cs) - - var err error - expConsensusState, err = types.PackConsensusState(cs) - suite.Require().NoError(err) - - req = &types.QueryConsensusStateRequest{ - ClientId: testClientID, - RevisionNumber: 0, - RevisionHeight: height, - } - }, - 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.ConsensusState(ctx, req) - - if tc.expPass { - suite.Require().NoError(err) - suite.Require().NotNil(res) - suite.Require().Equal(expConsensusState, res.ConsensusState) - - // ensure UnpackInterfaces is defined - cachedValue := res.ConsensusState.GetCachedValue() - suite.Require().NotNil(cachedValue) - } else { - suite.Require().Error(err) - } - }) - } -} - -func (suite *KeeperTestSuite) TestQueryConsensusStates() { - var ( - req *types.QueryConsensusStatesRequest - expConsensusStates = []types.ConsensusStateWithHeight{} - ) - - testCases := []struct { - msg string - malleate func() - expPass bool - }{ - { - "invalid client identifier", - func() { - req = &types.QueryConsensusStatesRequest{} - }, - false, - }, - { - "empty pagination", - func() { - req = &types.QueryConsensusStatesRequest{ - ClientId: testClientID, - } - }, - true, - }, - { - "success, no results", - func() { - req = &types.QueryConsensusStatesRequest{ - ClientId: testClientID, - Pagination: &query.PageRequest{ - Limit: 3, - CountTotal: true, - }, - } - }, - true, - }, - { - "success", - func() { - cs := ibctmtypes.NewConsensusState( - suite.consensusState.Timestamp, commitmenttypes.NewMerkleRoot([]byte("hash1")), nil, - ) - cs2 := ibctmtypes.NewConsensusState( - suite.consensusState.Timestamp.Add(time.Second), commitmenttypes.NewMerkleRoot([]byte("hash2")), nil, - ) - - clientState := ibctmtypes.NewClientState( - testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false, - ) - - // Use CreateClient to ensure that processedTime metadata gets stored. - clientId, err := suite.keeper.CreateClient(suite.ctx, clientState, cs) - suite.Require().NoError(err) - suite.keeper.SetClientConsensusState(suite.ctx, clientId, testClientHeight.Increment(), cs2) - - // order is swapped because the res is sorted by client id - expConsensusStates = []types.ConsensusStateWithHeight{ - types.NewConsensusStateWithHeight(testClientHeight, cs), - types.NewConsensusStateWithHeight(testClientHeight.Increment().(types.Height), cs2), - } - req = &types.QueryConsensusStatesRequest{ - ClientId: clientId, - Pagination: &query.PageRequest{ - Limit: 3, - 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.ConsensusStates(ctx, req) - - if tc.expPass { - suite.Require().NoError(err) - suite.Require().NotNil(res) - suite.Require().Equal(len(expConsensusStates), len(res.ConsensusStates)) - for i := range expConsensusStates { - suite.Require().NotNil(res.ConsensusStates[i]) - 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) - } - }) - } -} - -func (suite *KeeperTestSuite) TestQueryParams() { - ctx := sdk.WrapSDKContext(suite.chainA.GetContext()) - expParams := types.DefaultParams() - res, _ := suite.queryClient.ClientParams(ctx, &types.QueryClientParamsRequest{}) - suite.Require().Equal(&expParams, res.Params) -} diff --git a/x/ibc/core/02-client/keeper/keeper.go b/x/ibc/core/02-client/keeper/keeper.go deleted file mode 100644 index 43ac1feb3523..000000000000 --- a/x/ibc/core/02-client/keeper/keeper.go +++ /dev/null @@ -1,384 +0,0 @@ -package keeper - -import ( - "fmt" - "reflect" - "strings" - - "github.com/tendermint/tendermint/libs/log" - "github.com/tendermint/tendermint/light" - - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/store/prefix" - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" - paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" - upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" -) - -// Keeper represents a type that grants read and write permissions to any client -// state information -type Keeper struct { - storeKey sdk.StoreKey - cdc codec.BinaryMarshaler - paramSpace paramtypes.Subspace - stakingKeeper types.StakingKeeper - upgradeKeeper types.UpgradeKeeper -} - -// NewKeeper creates a new NewKeeper instance -func NewKeeper(cdc codec.BinaryMarshaler, key sdk.StoreKey, paramSpace paramtypes.Subspace, sk types.StakingKeeper, uk types.UpgradeKeeper) Keeper { - // set KeyTable if it has not already been set - if !paramSpace.HasKeyTable() { - paramSpace = paramSpace.WithKeyTable(types.ParamKeyTable()) - } - - return Keeper{ - storeKey: key, - cdc: cdc, - paramSpace: paramSpace, - stakingKeeper: sk, - upgradeKeeper: uk, - } -} - -// Logger returns a module-specific logger. -func (k Keeper) Logger(ctx sdk.Context) log.Logger { - return ctx.Logger().With("module", "x/"+host.ModuleName+"/"+types.SubModuleName) -} - -// GenerateClientIdentifier returns the next client identifier. -func (k Keeper) GenerateClientIdentifier(ctx sdk.Context, clientType string) string { - nextClientSeq := k.GetNextClientSequence(ctx) - clientID := types.FormatClientIdentifier(clientType, nextClientSeq) - - nextClientSeq++ - k.SetNextClientSequence(ctx, nextClientSeq) - return clientID -} - -// GetClientState gets a particular client from the store -func (k Keeper) GetClientState(ctx sdk.Context, clientID string) (exported.ClientState, bool) { - store := k.ClientStore(ctx, clientID) - bz := store.Get(host.ClientStateKey()) - if bz == nil { - return nil, false - } - - clientState := k.MustUnmarshalClientState(bz) - return clientState, true -} - -// SetClientState sets a particular Client to the store -func (k Keeper) SetClientState(ctx sdk.Context, clientID string, clientState exported.ClientState) { - store := k.ClientStore(ctx, clientID) - store.Set(host.ClientStateKey(), k.MustMarshalClientState(clientState)) -} - -// GetClientConsensusState gets the stored consensus state from a client at a given height. -func (k Keeper) GetClientConsensusState(ctx sdk.Context, clientID string, height exported.Height) (exported.ConsensusState, bool) { - store := k.ClientStore(ctx, clientID) - bz := store.Get(host.ConsensusStateKey(height)) - if bz == nil { - return nil, false - } - - consensusState := k.MustUnmarshalConsensusState(bz) - return consensusState, true -} - -// SetClientConsensusState sets a ConsensusState to a particular client at the given -// height -func (k Keeper) SetClientConsensusState(ctx sdk.Context, clientID string, height exported.Height, consensusState exported.ConsensusState) { - store := k.ClientStore(ctx, clientID) - store.Set(host.ConsensusStateKey(height), k.MustMarshalConsensusState(consensusState)) -} - -// GetNextClientSequence gets the next client sequence from the store. -func (k Keeper) GetNextClientSequence(ctx sdk.Context) uint64 { - store := ctx.KVStore(k.storeKey) - bz := store.Get([]byte(types.KeyNextClientSequence)) - if bz == nil { - panic("next client sequence is nil") - } - - return sdk.BigEndianToUint64(bz) -} - -// SetNextClientSequence sets the next client sequence to the store. -func (k Keeper) SetNextClientSequence(ctx sdk.Context, sequence uint64) { - store := ctx.KVStore(k.storeKey) - bz := sdk.Uint64ToBigEndian(sequence) - store.Set([]byte(types.KeyNextClientSequence), bz) -} - -// IterateConsensusStates provides an iterator over all stored consensus states. -// objects. For each State object, cb will be called. If the cb returns true, -// the iterator will close and stop. -func (k Keeper) IterateConsensusStates(ctx sdk.Context, cb func(clientID string, cs types.ConsensusStateWithHeight) bool) { - store := ctx.KVStore(k.storeKey) - iterator := sdk.KVStorePrefixIterator(store, host.KeyClientStorePrefix) - - defer iterator.Close() - for ; iterator.Valid(); iterator.Next() { - keySplit := strings.Split(string(iterator.Key()), "/") - // consensus key is in the format "clients//consensusStates/" - if len(keySplit) != 4 || keySplit[2] != string(host.KeyConsensusStatePrefix) { - continue - } - clientID := keySplit[1] - height := types.MustParseHeight(keySplit[3]) - consensusState := k.MustUnmarshalConsensusState(iterator.Value()) - - consensusStateWithHeight := types.NewConsensusStateWithHeight(height, consensusState) - - if cb(clientID, consensusStateWithHeight) { - break - } - } -} - -// GetAllGenesisClients returns all the clients in state with their client ids returned as IdentifiedClientState -func (k Keeper) GetAllGenesisClients(ctx sdk.Context) types.IdentifiedClientStates { - var genClients types.IdentifiedClientStates - k.IterateClients(ctx, func(clientID string, cs exported.ClientState) bool { - genClients = append(genClients, types.NewIdentifiedClientState(clientID, cs)) - return false - }) - - return genClients.Sort() -} - -// GetAllClientMetadata will take a list of IdentifiedClientState and return a list -// of IdentifiedGenesisMetadata necessary for exporting and importing client metadata -// into the client store. -func (k Keeper) GetAllClientMetadata(ctx sdk.Context, genClients []types.IdentifiedClientState) ([]types.IdentifiedGenesisMetadata, error) { - genMetadata := make([]types.IdentifiedGenesisMetadata, 0) - for _, ic := range genClients { - cs, err := types.UnpackClientState(ic.ClientState) - if err != nil { - return nil, err - } - gms := cs.ExportMetadata(k.ClientStore(ctx, ic.ClientId)) - if len(gms) == 0 { - continue - } - clientMetadata := make([]types.GenesisMetadata, len(gms)) - for i, metadata := range gms { - cmd, ok := metadata.(types.GenesisMetadata) - if !ok { - return nil, sdkerrors.Wrapf(types.ErrInvalidClientMetadata, "expected metadata type: %T, got: %T", - types.GenesisMetadata{}, cmd) - } - clientMetadata[i] = cmd - } - genMetadata = append(genMetadata, types.NewIdentifiedGenesisMetadata( - ic.ClientId, - clientMetadata, - )) - } - return genMetadata, nil -} - -// SetAllClientMetadata takes a list of IdentifiedGenesisMetadata and stores all of the metadata in the client store at the appropriate paths. -func (k Keeper) SetAllClientMetadata(ctx sdk.Context, genMetadata []types.IdentifiedGenesisMetadata) { - for _, igm := range genMetadata { - // create client store - store := k.ClientStore(ctx, igm.ClientId) - // set all metadata kv pairs in client store - for _, md := range igm.ClientMetadata { - store.Set(md.GetKey(), md.GetValue()) - } - } -} - -// GetAllConsensusStates returns all stored client consensus states. -func (k Keeper) GetAllConsensusStates(ctx sdk.Context) types.ClientsConsensusStates { - clientConsStates := make(types.ClientsConsensusStates, 0) - mapClientIDToConsStateIdx := make(map[string]int) - - k.IterateConsensusStates(ctx, func(clientID string, cs types.ConsensusStateWithHeight) bool { - idx, ok := mapClientIDToConsStateIdx[clientID] - if ok { - clientConsStates[idx].ConsensusStates = append(clientConsStates[idx].ConsensusStates, cs) - return false - } - - clientConsState := types.ClientConsensusStates{ - ClientId: clientID, - ConsensusStates: []types.ConsensusStateWithHeight{cs}, - } - - clientConsStates = append(clientConsStates, clientConsState) - mapClientIDToConsStateIdx[clientID] = len(clientConsStates) - 1 - return false - }) - - return clientConsStates.Sort() -} - -// HasClientConsensusState returns if keeper has a ConsensusState for a particular -// client at the given height -func (k Keeper) HasClientConsensusState(ctx sdk.Context, clientID string, height exported.Height) bool { - store := k.ClientStore(ctx, clientID) - return store.Has(host.ConsensusStateKey(height)) -} - -// GetLatestClientConsensusState gets the latest ConsensusState stored for a given client -func (k Keeper) GetLatestClientConsensusState(ctx sdk.Context, clientID string) (exported.ConsensusState, bool) { - clientState, ok := k.GetClientState(ctx, clientID) - if !ok { - return nil, false - } - return k.GetClientConsensusState(ctx, clientID, clientState.GetLatestHeight()) -} - -// GetSelfConsensusState introspects the (self) past historical info at a given height -// and returns the expected consensus state at that height. -// For now, can only retrieve self consensus states for the current revision -func (k Keeper) GetSelfConsensusState(ctx sdk.Context, height exported.Height) (exported.ConsensusState, bool) { - selfHeight, ok := height.(types.Height) - if !ok { - return nil, false - } - // check that height revision matches chainID revision - revision := types.ParseChainID(ctx.ChainID()) - if revision != height.GetRevisionNumber() { - return nil, false - } - histInfo, found := k.stakingKeeper.GetHistoricalInfo(ctx, int64(selfHeight.RevisionHeight)) - if !found { - return nil, false - } - - consensusState := &ibctmtypes.ConsensusState{ - Timestamp: histInfo.Header.Time, - Root: commitmenttypes.NewMerkleRoot(histInfo.Header.GetAppHash()), - NextValidatorsHash: histInfo.Header.NextValidatorsHash, - } - return consensusState, true -} - -// ValidateSelfClient validates the client parameters for a client of the running chain -// This function is only used to validate the client state the counterparty stores for this chain -// Client must be in same revision as the executing chain -func (k Keeper) ValidateSelfClient(ctx sdk.Context, clientState exported.ClientState) error { - tmClient, ok := clientState.(*ibctmtypes.ClientState) - if !ok { - return sdkerrors.Wrapf(types.ErrInvalidClient, "client must be a Tendermint client, expected: %T, got: %T", - &ibctmtypes.ClientState{}, tmClient) - } - - if clientState.IsFrozen() { - return types.ErrClientFrozen - } - - if ctx.ChainID() != tmClient.ChainId { - return sdkerrors.Wrapf(types.ErrInvalidClient, "invalid chain-id. expected: %s, got: %s", - ctx.ChainID(), tmClient.ChainId) - } - - revision := types.ParseChainID(ctx.ChainID()) - - // client must be in the same revision as executing chain - if tmClient.LatestHeight.RevisionNumber != revision { - return sdkerrors.Wrapf(types.ErrInvalidClient, "client is not in the same revision as the chain. expected revision: %d, got: %d", - tmClient.LatestHeight.RevisionNumber, revision) - } - - selfHeight := types.NewHeight(revision, uint64(ctx.BlockHeight())) - if tmClient.LatestHeight.GTE(selfHeight) { - return sdkerrors.Wrapf(types.ErrInvalidClient, "client has LatestHeight %d greater than or equal to chain height %d", - tmClient.LatestHeight, selfHeight) - } - - expectedProofSpecs := commitmenttypes.GetSDKSpecs() - if !reflect.DeepEqual(expectedProofSpecs, tmClient.ProofSpecs) { - return sdkerrors.Wrapf(types.ErrInvalidClient, "client has invalid proof specs. expected: %v got: %v", - expectedProofSpecs, tmClient.ProofSpecs) - } - - if err := light.ValidateTrustLevel(tmClient.TrustLevel.ToTendermint()); err != nil { - return sdkerrors.Wrapf(types.ErrInvalidClient, "trust-level invalid: %v", err) - } - - expectedUbdPeriod := k.stakingKeeper.UnbondingTime(ctx) - if expectedUbdPeriod != tmClient.UnbondingPeriod { - return sdkerrors.Wrapf(types.ErrInvalidClient, "invalid unbonding period. expected: %s, got: %s", - expectedUbdPeriod, tmClient.UnbondingPeriod) - } - - if tmClient.UnbondingPeriod < tmClient.TrustingPeriod { - return sdkerrors.Wrapf(types.ErrInvalidClient, "unbonding period must be greater than trusting period. unbonding period (%d) < trusting period (%d)", - tmClient.UnbondingPeriod, tmClient.TrustingPeriod) - } - - if len(tmClient.UpgradePath) != 0 { - // For now, SDK IBC implementation assumes that upgrade path (if defined) is defined by SDK upgrade module - expectedUpgradePath := []string{upgradetypes.StoreKey, upgradetypes.KeyUpgradedIBCState} - if !reflect.DeepEqual(expectedUpgradePath, tmClient.UpgradePath) { - return sdkerrors.Wrapf(types.ErrInvalidClient, "upgrade path must be the upgrade path defined by upgrade module. expected %v, got %v", - expectedUpgradePath, tmClient.UpgradePath) - } - } - return nil -} - -// GetUpgradePlan executes the upgrade keeper GetUpgradePlan function. -func (k Keeper) GetUpgradePlan(ctx sdk.Context) (plan upgradetypes.Plan, havePlan bool) { - return k.upgradeKeeper.GetUpgradePlan(ctx) -} - -// GetUpgradedClient executes the upgrade keeper GetUpgradeClient function. -func (k Keeper) GetUpgradedClient(ctx sdk.Context, planHeight int64) ([]byte, bool) { - return k.upgradeKeeper.GetUpgradedClient(ctx, planHeight) -} - -// SetUpgradedConsensusState executes the upgrade keeper SetUpgradedConsensusState function. -func (k Keeper) SetUpgradedConsensusState(ctx sdk.Context, planHeight int64, bz []byte) error { - return k.upgradeKeeper.SetUpgradedConsensusState(ctx, planHeight, bz) -} - -// IterateClients provides an iterator over all stored light client State -// objects. For each State object, cb will be called. If the cb returns true, -// the iterator will close and stop. -func (k Keeper) IterateClients(ctx sdk.Context, cb func(clientID string, cs exported.ClientState) bool) { - store := ctx.KVStore(k.storeKey) - iterator := sdk.KVStorePrefixIterator(store, host.KeyClientStorePrefix) - - defer iterator.Close() - for ; iterator.Valid(); iterator.Next() { - keySplit := strings.Split(string(iterator.Key()), "/") - if keySplit[len(keySplit)-1] != host.KeyClientState { - continue - } - clientState := k.MustUnmarshalClientState(iterator.Value()) - - // key is ibc/{clientid}/clientState - // Thus, keySplit[1] is clientID - if cb(keySplit[1], clientState) { - break - } - } -} - -// GetAllClients returns all stored light client State objects. -func (k Keeper) GetAllClients(ctx sdk.Context) (states []exported.ClientState) { - k.IterateClients(ctx, func(_ string, state exported.ClientState) bool { - states = append(states, state) - return false - }) - return states -} - -// ClientStore returns isolated prefix store for each client so they can read/write in separate -// namespace without being able to read/write other client's data -func (k Keeper) ClientStore(ctx sdk.Context, clientID string) sdk.KVStore { - clientPrefix := []byte(fmt.Sprintf("%s/%s/", host.KeyClientStorePrefix, clientID)) - return prefix.NewStore(ctx.KVStore(k.storeKey), clientPrefix) -} diff --git a/x/ibc/core/02-client/keeper/keeper_test.go b/x/ibc/core/02-client/keeper/keeper_test.go deleted file mode 100644 index c22e80cc9ec8..000000000000 --- a/x/ibc/core/02-client/keeper/keeper_test.go +++ /dev/null @@ -1,389 +0,0 @@ -package keeper_test - -import ( - "math/rand" - "testing" - "time" - - "github.com/stretchr/testify/suite" - tmbytes "github.com/tendermint/tendermint/libs/bytes" - tmproto "github.com/tendermint/tendermint/proto/tendermint/types" - tmtypes "github.com/tendermint/tendermint/types" - - "github.com/cosmos/cosmos-sdk/baseapp" - "github.com/cosmos/cosmos-sdk/codec" - cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" - "github.com/cosmos/cosmos-sdk/simapp" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/keeper" - "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/core/exported" - ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" - localhosttypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/09-localhost/types" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" - ibctestingmock "github.com/cosmos/cosmos-sdk/x/ibc/testing/mock" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" -) - -const ( - testChainID = "gaiahub-0" - testChainIDRevision1 = "gaiahub-1" - - testClientID = "tendermint-0" - testClientID2 = "tendermint-1" - testClientID3 = "tendermint-2" - - height = 5 - - trustingPeriod time.Duration = time.Hour * 24 * 7 * 2 - ubdPeriod time.Duration = time.Hour * 24 * 7 * 3 - maxClockDrift time.Duration = time.Second * 10 -) - -var ( - testClientHeight = types.NewHeight(0, 5) - testClientHeightRevision1 = types.NewHeight(1, 5) - newClientHeight = types.NewHeight(1, 1) -) - -type KeeperTestSuite struct { - suite.Suite - - coordinator *ibctesting.Coordinator - - chainA *ibctesting.TestChain - chainB *ibctesting.TestChain - - cdc codec.Marshaler - ctx sdk.Context - keeper *keeper.Keeper - consensusState *ibctmtypes.ConsensusState - header *ibctmtypes.Header - valSet *tmtypes.ValidatorSet - valSetHash tmbytes.HexBytes - privVal tmtypes.PrivValidator - now time.Time - past time.Time - - queryClient types.QueryClient -} - -func (suite *KeeperTestSuite) SetupTest() { - suite.coordinator = ibctesting.NewCoordinator(suite.T(), 2) - - suite.chainA = suite.coordinator.GetChain(ibctesting.GetChainID(0)) - suite.chainB = suite.coordinator.GetChain(ibctesting.GetChainID(1)) - - isCheckTx := false - suite.now = time.Date(2020, 1, 2, 0, 0, 0, 0, time.UTC) - suite.past = time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC) - now2 := suite.now.Add(time.Hour) - app := simapp.Setup(isCheckTx) - - suite.cdc = app.AppCodec() - suite.ctx = app.BaseApp.NewContext(isCheckTx, tmproto.Header{Height: height, ChainID: testClientID, Time: now2}) - suite.keeper = &app.IBCKeeper.ClientKeeper - suite.privVal = ibctestingmock.NewPV() - - pubKey, err := suite.privVal.GetPubKey() - suite.Require().NoError(err) - - testClientHeightMinus1 := types.NewHeight(0, height-1) - - validator := tmtypes.NewValidator(pubKey, 1) - suite.valSet = tmtypes.NewValidatorSet([]*tmtypes.Validator{validator}) - suite.valSetHash = suite.valSet.Hash() - suite.header = suite.chainA.CreateTMClientHeader(testChainID, int64(testClientHeight.RevisionHeight), testClientHeightMinus1, now2, suite.valSet, suite.valSet, []tmtypes.PrivValidator{suite.privVal}) - suite.consensusState = ibctmtypes.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot([]byte("hash")), suite.valSetHash) - - var validators stakingtypes.Validators - for i := 1; i < 11; i++ { - privVal := ibctestingmock.NewPV() - tmPk, err := privVal.GetPubKey() - suite.Require().NoError(err) - pk, err := cryptocodec.FromTmPubKeyInterface(tmPk) - suite.Require().NoError(err) - val, err := stakingtypes.NewValidator(sdk.ValAddress(pk.Address()), pk, stakingtypes.Description{}) - suite.Require().NoError(err) - - val.Status = stakingtypes.Bonded - val.Tokens = sdk.NewInt(rand.Int63()) - validators = append(validators, val) - - hi := stakingtypes.NewHistoricalInfo(suite.ctx.BlockHeader(), validators) - app.StakingKeeper.SetHistoricalInfo(suite.ctx, int64(i), &hi) - } - - // add localhost client - revision := types.ParseChainID(suite.chainA.ChainID) - localHostClient := localhosttypes.NewClientState( - suite.chainA.ChainID, types.NewHeight(revision, uint64(suite.chainA.GetContext().BlockHeight())), - ) - suite.chainA.App.IBCKeeper.ClientKeeper.SetClientState(suite.chainA.GetContext(), exported.Localhost, localHostClient) - - queryHelper := baseapp.NewQueryServerTestHelper(suite.ctx, app.InterfaceRegistry()) - types.RegisterQueryServer(queryHelper, app.IBCKeeper.ClientKeeper) - suite.queryClient = types.NewQueryClient(queryHelper) -} - -func TestKeeperTestSuite(t *testing.T) { - suite.Run(t, new(KeeperTestSuite)) -} - -func (suite *KeeperTestSuite) TestSetClientState() { - clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.ZeroHeight(), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) - suite.keeper.SetClientState(suite.ctx, testClientID, clientState) - - retrievedState, found := suite.keeper.GetClientState(suite.ctx, testClientID) - suite.Require().True(found, "GetClientState failed") - suite.Require().Equal(clientState, retrievedState, "Client states are not equal") -} - -func (suite *KeeperTestSuite) TestSetClientConsensusState() { - suite.keeper.SetClientConsensusState(suite.ctx, testClientID, testClientHeight, suite.consensusState) - - retrievedConsState, found := suite.keeper.GetClientConsensusState(suite.ctx, testClientID, testClientHeight) - suite.Require().True(found, "GetConsensusState failed") - - tmConsState, ok := retrievedConsState.(*ibctmtypes.ConsensusState) - suite.Require().True(ok) - suite.Require().Equal(suite.consensusState, tmConsState, "ConsensusState not stored correctly") -} - -func (suite *KeeperTestSuite) TestValidateSelfClient() { - testClientHeight := types.NewHeight(0, uint64(suite.chainA.GetContext().BlockHeight()-1)) - - testCases := []struct { - name string - clientState exported.ClientState - expPass bool - }{ - { - "success", - ibctmtypes.NewClientState(suite.chainA.ChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), - true, - }, - { - "success with nil UpgradePath", - ibctmtypes.NewClientState(suite.chainA.ChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), nil, false, false), - true, - }, - { - "invalid client type", - localhosttypes.NewClientState(suite.chainA.ChainID, testClientHeight), - false, - }, - { - "frozen client", - &ibctmtypes.ClientState{suite.chainA.ChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false}, - false, - }, - { - "incorrect chainID", - ibctmtypes.NewClientState("gaiatestnet", ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), - false, - }, - { - "invalid client height", - ibctmtypes.NewClientState(suite.chainA.ChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.NewHeight(0, uint64(suite.chainA.GetContext().BlockHeight())), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), - false, - }, - { - "invalid client revision", - ibctmtypes.NewClientState(suite.chainA.ChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeightRevision1, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), - false, - }, - { - "invalid proof specs", - ibctmtypes.NewClientState(suite.chainA.ChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, nil, ibctesting.UpgradePath, false, false), - false, - }, - { - "invalid trust level", - ibctmtypes.NewClientState(suite.chainA.ChainID, ibctmtypes.Fraction{0, 1}, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), - false, - }, - { - "invalid unbonding period", - ibctmtypes.NewClientState(suite.chainA.ChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod+10, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), - false, - }, - { - "invalid trusting period", - ibctmtypes.NewClientState(suite.chainA.ChainID, ibctmtypes.DefaultTrustLevel, ubdPeriod+10, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), - false, - }, - { - "invalid upgrade path", - ibctmtypes.NewClientState(suite.chainA.ChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), []string{"bad", "upgrade", "path"}, false, false), - false, - }, - } - - for _, tc := range testCases { - err := suite.chainA.App.IBCKeeper.ClientKeeper.ValidateSelfClient(suite.chainA.GetContext(), tc.clientState) - if tc.expPass { - suite.Require().NoError(err, "expected valid client for case: %s", tc.name) - } else { - suite.Require().Error(err, "expected invalid client for case: %s", tc.name) - } - } -} - -func (suite KeeperTestSuite) TestGetAllGenesisClients() { - clientIDs := []string{ - testClientID2, testClientID3, testClientID, - } - expClients := []exported.ClientState{ - ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.ZeroHeight(), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), - ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.ZeroHeight(), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), - ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.ZeroHeight(), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), - } - - expGenClients := make(types.IdentifiedClientStates, len(expClients)) - - for i := range expClients { - suite.chainA.App.IBCKeeper.ClientKeeper.SetClientState(suite.chainA.GetContext(), clientIDs[i], expClients[i]) - expGenClients[i] = types.NewIdentifiedClientState(clientIDs[i], expClients[i]) - } - - // add localhost client - localHostClient, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), exported.Localhost) - suite.Require().True(found) - expGenClients = append(expGenClients, types.NewIdentifiedClientState(exported.Localhost, localHostClient)) - - genClients := suite.chainA.App.IBCKeeper.ClientKeeper.GetAllGenesisClients(suite.chainA.GetContext()) - - suite.Require().Equal(expGenClients.Sort(), genClients) -} - -func (suite KeeperTestSuite) TestGetAllGenesisMetadata() { - expectedGenMetadata := []types.IdentifiedGenesisMetadata{ - types.NewIdentifiedGenesisMetadata( - "clientA", - []types.GenesisMetadata{ - types.NewGenesisMetadata(ibctmtypes.ProcessedTimeKey(types.NewHeight(0, 1)), []byte("foo")), - types.NewGenesisMetadata(ibctmtypes.ProcessedTimeKey(types.NewHeight(0, 2)), []byte("bar")), - types.NewGenesisMetadata(ibctmtypes.ProcessedTimeKey(types.NewHeight(0, 3)), []byte("baz")), - }, - ), - types.NewIdentifiedGenesisMetadata( - "clientB", - []types.GenesisMetadata{ - types.NewGenesisMetadata(ibctmtypes.ProcessedTimeKey(types.NewHeight(1, 100)), []byte("val1")), - types.NewGenesisMetadata(ibctmtypes.ProcessedTimeKey(types.NewHeight(2, 300)), []byte("val2")), - }, - ), - } - - genClients := []types.IdentifiedClientState{ - types.NewIdentifiedClientState("clientA", &ibctmtypes.ClientState{}), types.NewIdentifiedClientState("clientB", &ibctmtypes.ClientState{}), - types.NewIdentifiedClientState("clientC", &ibctmtypes.ClientState{}), types.NewIdentifiedClientState("clientD", &localhosttypes.ClientState{}), - } - - suite.chainA.App.IBCKeeper.ClientKeeper.SetAllClientMetadata(suite.chainA.GetContext(), expectedGenMetadata) - - actualGenMetadata, err := suite.chainA.App.IBCKeeper.ClientKeeper.GetAllClientMetadata(suite.chainA.GetContext(), genClients) - suite.Require().NoError(err, "get client metadata returned error unexpectedly") - suite.Require().Equal(expectedGenMetadata, actualGenMetadata, "retrieved metadata is unexpected") -} - -func (suite KeeperTestSuite) TestGetConsensusState() { - suite.ctx = suite.ctx.WithBlockHeight(10) - cases := []struct { - name string - height types.Height - expPass bool - }{ - {"zero height", types.ZeroHeight(), false}, - {"height > latest height", types.NewHeight(0, uint64(suite.ctx.BlockHeight())+1), false}, - {"latest height - 1", types.NewHeight(0, uint64(suite.ctx.BlockHeight())-1), true}, - {"latest height", types.GetSelfHeight(suite.ctx), true}, - } - - for i, tc := range cases { - tc := tc - cs, found := suite.keeper.GetSelfConsensusState(suite.ctx, tc.height) - if tc.expPass { - suite.Require().True(found, "Case %d should have passed: %s", i, tc.name) - suite.Require().NotNil(cs, "Case %d should have passed: %s", i, tc.name) - } else { - suite.Require().False(found, "Case %d should have failed: %s", i, tc.name) - suite.Require().Nil(cs, "Case %d should have failed: %s", i, tc.name) - } - } -} - -func (suite KeeperTestSuite) TestConsensusStateHelpers() { - // initial setup - clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) - - suite.keeper.SetClientState(suite.ctx, testClientID, clientState) - suite.keeper.SetClientConsensusState(suite.ctx, testClientID, testClientHeight, suite.consensusState) - - nextState := ibctmtypes.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot([]byte("next")), suite.valSetHash) - - testClientHeightPlus5 := types.NewHeight(0, height+5) - - header := suite.chainA.CreateTMClientHeader(testClientID, int64(testClientHeightPlus5.RevisionHeight), testClientHeight, suite.header.Header.Time.Add(time.Minute), - suite.valSet, suite.valSet, []tmtypes.PrivValidator{suite.privVal}) - - // mock update functionality - clientState.LatestHeight = header.GetHeight().(types.Height) - suite.keeper.SetClientConsensusState(suite.ctx, testClientID, header.GetHeight(), nextState) - suite.keeper.SetClientState(suite.ctx, testClientID, clientState) - - latest, ok := suite.keeper.GetLatestClientConsensusState(suite.ctx, testClientID) - suite.Require().True(ok) - suite.Require().Equal(nextState, latest, "Latest client not returned correctly") -} - -// 2 clients in total are created on chainA. The first client is updated so it contains an initial consensus state -// and a consensus state at the update height. -func (suite KeeperTestSuite) TestGetAllConsensusStates() { - clientA, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - - clientState := suite.chainA.GetClientState(clientA) - expConsensusHeight0 := clientState.GetLatestHeight() - consensusState0, ok := suite.chainA.GetConsensusState(clientA, expConsensusHeight0) - suite.Require().True(ok) - - // update client to create a second consensus state - err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - suite.Require().NoError(err) - - clientState = suite.chainA.GetClientState(clientA) - expConsensusHeight1 := clientState.GetLatestHeight() - suite.Require().True(expConsensusHeight1.GT(expConsensusHeight0)) - consensusState1, ok := suite.chainA.GetConsensusState(clientA, expConsensusHeight1) - suite.Require().True(ok) - - expConsensus := []exported.ConsensusState{ - consensusState0, - consensusState1, - } - - // create second client on chainA - clientA2, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - clientState = suite.chainA.GetClientState(clientA2) - - expConsensusHeight2 := clientState.GetLatestHeight() - consensusState2, ok := suite.chainA.GetConsensusState(clientA2, expConsensusHeight2) - suite.Require().True(ok) - - expConsensus2 := []exported.ConsensusState{consensusState2} - - expConsensusStates := types.ClientsConsensusStates{ - types.NewClientConsensusStates(clientA, []types.ConsensusStateWithHeight{ - types.NewConsensusStateWithHeight(expConsensusHeight0.(types.Height), expConsensus[0]), - types.NewConsensusStateWithHeight(expConsensusHeight1.(types.Height), expConsensus[1]), - }), - types.NewClientConsensusStates(clientA2, []types.ConsensusStateWithHeight{ - types.NewConsensusStateWithHeight(expConsensusHeight2.(types.Height), expConsensus2[0]), - }), - }.Sort() - - consStates := suite.chainA.App.IBCKeeper.ClientKeeper.GetAllConsensusStates(suite.chainA.GetContext()) - suite.Require().Equal(expConsensusStates, consStates, "%s \n\n%s", expConsensusStates, consStates) -} diff --git a/x/ibc/core/02-client/keeper/params.go b/x/ibc/core/02-client/keeper/params.go deleted file mode 100644 index 04f4a2563799..000000000000 --- a/x/ibc/core/02-client/keeper/params.go +++ /dev/null @@ -1,23 +0,0 @@ -package keeper - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" -) - -// GetAllowedClients retrieves the receive enabled boolean from the paramstore -func (k Keeper) GetAllowedClients(ctx sdk.Context) []string { - var res []string - k.paramSpace.Get(ctx, types.KeyAllowedClients, &res) - return res -} - -// GetParams returns the total set of ibc-transfer parameters. -func (k Keeper) GetParams(ctx sdk.Context) types.Params { - return types.NewParams(k.GetAllowedClients(ctx)...) -} - -// SetParams sets the total set of ibc-transfer parameters. -func (k Keeper) SetParams(ctx sdk.Context, params types.Params) { - k.paramSpace.SetParamSet(ctx, ¶ms) -} diff --git a/x/ibc/core/02-client/keeper/params_test.go b/x/ibc/core/02-client/keeper/params_test.go deleted file mode 100644 index 9df08597100b..000000000000 --- a/x/ibc/core/02-client/keeper/params_test.go +++ /dev/null @@ -1,17 +0,0 @@ -package keeper_test - -import ( - "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" -) - -func (suite *KeeperTestSuite) TestParams() { - expParams := types.DefaultParams() - - params := suite.chainA.App.IBCKeeper.ClientKeeper.GetParams(suite.chainA.GetContext()) - suite.Require().Equal(expParams, params) - - expParams.AllowedClients = []string{} - suite.chainA.App.IBCKeeper.ClientKeeper.SetParams(suite.chainA.GetContext(), expParams) - params = suite.chainA.App.IBCKeeper.ClientKeeper.GetParams(suite.chainA.GetContext()) - suite.Require().Empty(expParams.AllowedClients) -} diff --git a/x/ibc/core/02-client/keeper/proposal.go b/x/ibc/core/02-client/keeper/proposal.go deleted file mode 100644 index 812df5e138de..000000000000 --- a/x/ibc/core/02-client/keeper/proposal.go +++ /dev/null @@ -1,98 +0,0 @@ -package keeper - -import ( - "github.com/armon/go-metrics" - - "github.com/cosmos/cosmos-sdk/telemetry" - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -// 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.SubjectClientId == exported.Localhost || p.SubstituteClientId == exported.Localhost { - return sdkerrors.Wrap(types.ErrInvalidUpdateClientProposal, "cannot update localhost client with proposal") - } - - subjectClientState, found := k.GetClientState(ctx, p.SubjectClientId) - if !found { - return sdkerrors.Wrapf(types.ErrClientNotFound, "subject client with ID %s", p.SubjectClientId) - } - - 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, 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.Logger(ctx).Info("client updated after governance proposal passed", "client-id", p.SubjectClientId, "height", clientState.GetLatestHeight().String()) - - defer func() { - telemetry.IncrCounterWithLabels( - []string{"ibc", "client", "update"}, - 1, - []metrics.Label{ - telemetry.NewLabel("client-type", clientState.ClientType()), - telemetry.NewLabel("client-id", p.SubjectClientId), - telemetry.NewLabel("update-type", "proposal"), - }, - ) - }() - - // emitting events in the keeper for proposal updates to clients - ctx.EventManager().EmitEvent( - sdk.NewEvent( - types.EventTypeUpdateClientProposal, - sdk.NewAttribute(types.AttributeKeySubjectClientID, p.SubjectClientId), - sdk.NewAttribute(types.AttributeKeyClientType, clientState.ClientType()), - sdk.NewAttribute(types.AttributeKeyConsensusHeight, clientState.GetLatestHeight().String()), - ), - ) - - return nil -} - -// HandleUpgradeProposal sets the upgraded client state in the upgrade store. It clears -// an IBC client state and consensus state if a previous plan was set. Then it -// will schedule an upgrade and finally set the upgraded client state in upgrade -// store. -func (k Keeper) HandleUpgradeProposal(ctx sdk.Context, p *types.UpgradeProposal) error { - clientState, err := types.UnpackClientState(p.UpgradedClientState) - if err != nil { - return sdkerrors.Wrap(err, "could not unpack UpgradedClientState") - } - - // zero out any custom fields before setting - cs := clientState.ZeroCustomFields() - bz, err := types.MarshalClientState(k.cdc, cs) - if err != nil { - return sdkerrors.Wrap(err, "could not marshal UpgradedClientState") - } - - if err := k.upgradeKeeper.ScheduleUpgrade(ctx, p.Plan); err != nil { - return err - } - - // sets the new upgraded client in last height committed on this chain is at plan.Height, - // since the chain will panic at plan.Height and new chain will resume at plan.Height - return k.upgradeKeeper.SetUpgradedClient(ctx, p.Plan.Height, bz) -} diff --git a/x/ibc/core/02-client/keeper/proposal_test.go b/x/ibc/core/02-client/keeper/proposal_test.go deleted file mode 100644 index 82d7e120dbcf..000000000000 --- a/x/ibc/core/02-client/keeper/proposal_test.go +++ /dev/null @@ -1,265 +0,0 @@ -package keeper_test - -import ( - 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" - ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" - upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" -) - -func (suite *KeeperTestSuite) TestClientUpdateProposal() { - var ( - subject, substitute string - subjectClientState, substituteClientState exported.ClientState - initialHeight types.Height - content govtypes.Content - err error - ) - - testCases := []struct { - name string - malleate func() - expPass bool - }{ - { - "valid update client proposal", func() { - content = types.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) - consState, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientConsensusState(suite.chainA.GetContext(), substitute, tmClientState.LatestHeight) - suite.Require().True(found) - newRevisionNumber := tmClientState.GetLatestHeight().GetRevisionNumber() + 1 - - tmClientState.LatestHeight = types.NewHeight(newRevisionNumber, tmClientState.GetLatestHeight().GetRevisionHeight()) - initialHeight = types.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 = types.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, subject, substitute, initialHeight) - }, true, - }, - { - "cannot use localhost as subject", func() { - content = types.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, exported.Localhost, substitute, initialHeight) - }, false, - }, - { - "cannot use localhost as substitute", func() { - content = types.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, subject, exported.Localhost, initialHeight) - }, false, - }, - { - "subject client does not exist", func() { - content = types.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, ibctesting.InvalidID, substitute, initialHeight) - }, false, - }, - { - "substitute client does not exist", func() { - content = types.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, subject, ibctesting.InvalidID, initialHeight) - }, false, - }, - { - "subject and substitute have equal latest height", func() { - tmClientState, ok := subjectClientState.(*ibctmtypes.ClientState) - suite.Require().True(ok) - tmClientState.LatestHeight = substituteClientState.GetLatestHeight().(types.Height) - suite.chainA.App.IBCKeeper.ClientKeeper.SetClientState(suite.chainA.GetContext(), subject, tmClientState) - - content = types.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 = types.ZeroHeight() - suite.chainA.App.IBCKeeper.ClientKeeper.SetClientState(suite.chainA.GetContext(), subject, tmClientState) - - content = types.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, subject, substitute, initialHeight) - }, false, - }, - } - - 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) - substitute, _ = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - initialHeight = types.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() - - updateProp, ok := content.(*types.ClientUpdateProposal) - suite.Require().True(ok) - err = suite.chainA.App.IBCKeeper.ClientKeeper.ClientUpdateProposal(suite.chainA.GetContext(), updateProp) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } - -} - -func (suite *KeeperTestSuite) TestHandleUpgradeProposal() { - var ( - upgradedClientState *ibctmtypes.ClientState - oldPlan, plan upgradetypes.Plan - content govtypes.Content - err error - ) - - testCases := []struct { - name string - malleate func() - expPass bool - }{ - { - "valid upgrade proposal", func() { - content, err = types.NewUpgradeProposal(ibctesting.Title, ibctesting.Description, plan, upgradedClientState) - suite.Require().NoError(err) - }, true, - }, - { - "valid upgrade proposal with previous IBC state", func() { - oldPlan = upgradetypes.Plan{ - Name: "upgrade IBC clients", - Height: 100, - } - - content, err = types.NewUpgradeProposal(ibctesting.Title, ibctesting.Description, plan, upgradedClientState) - suite.Require().NoError(err) - }, true, - }, - { - "cannot unpack client state", func() { - any, err := types.PackConsensusState(&ibctmtypes.ConsensusState{}) - suite.Require().NoError(err) - content = &types.UpgradeProposal{ - Title: ibctesting.Title, - Description: ibctesting.Description, - Plan: plan, - UpgradedClientState: any, - } - }, false, - }, - { - "schedule upgrade fails - plan sets time and height", func() { - plan = upgradetypes.Plan{ - Name: "invalid plan", - Height: 1000, - Time: suite.chainA.GetContext().BlockTime(), - } - content, err = types.NewUpgradeProposal(ibctesting.Title, ibctesting.Description, plan, upgradedClientState) - suite.Require().NoError(err) - }, false, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - suite.SetupTest() // reset - oldPlan.Height = 0 //reset - - clientID, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - upgradedClientState = suite.chainA.GetClientState(clientID).ZeroCustomFields().(*ibctmtypes.ClientState) - - // use height 1000 to distinguish from old plan - plan = upgradetypes.Plan{ - Name: "upgrade IBC clients", - Height: 1000, - } - - tc.malleate() - - // set the old plan if it is not empty - if oldPlan.Height != 0 { - // set upgrade plan in the upgrade store - store := suite.chainA.GetContext().KVStore(suite.chainA.App.GetKey(upgradetypes.StoreKey)) - bz := suite.chainA.App.AppCodec().MustMarshalBinaryBare(&oldPlan) - store.Set(upgradetypes.PlanKey(), bz) - - bz, err := types.MarshalClientState(suite.chainA.App.AppCodec(), upgradedClientState) - suite.Require().NoError(err) - suite.chainA.App.UpgradeKeeper.SetUpgradedClient(suite.chainA.GetContext(), oldPlan.Height, bz) - } - - upgradeProp, ok := content.(*types.UpgradeProposal) - suite.Require().True(ok) - err = suite.chainA.App.IBCKeeper.ClientKeeper.HandleUpgradeProposal(suite.chainA.GetContext(), upgradeProp) - - if tc.expPass { - suite.Require().NoError(err) - - // check that the correct plan is returned - storedPlan, found := suite.chainA.App.UpgradeKeeper.GetUpgradePlan(suite.chainA.GetContext()) - suite.Require().True(found) - suite.Require().Equal(plan, storedPlan) - - // check that old upgraded client state is cleared - _, found = suite.chainA.App.UpgradeKeeper.GetUpgradedClient(suite.chainA.GetContext(), oldPlan.Height) - suite.Require().False(found) - - // check that client state was set - storedClientState, found := suite.chainA.App.UpgradeKeeper.GetUpgradedClient(suite.chainA.GetContext(), plan.Height) - suite.Require().True(found) - clientState, err := types.UnmarshalClientState(suite.chainA.App.AppCodec(), storedClientState) - suite.Require().NoError(err) - suite.Require().Equal(upgradedClientState, clientState) - } else { - suite.Require().Error(err) - - // check that the new plan wasn't stored - storedPlan, found := suite.chainA.App.UpgradeKeeper.GetUpgradePlan(suite.chainA.GetContext()) - if oldPlan.Height != 0 { - // NOTE: this is only true if the ScheduleUpgrade function - // returns an error before clearing the old plan - suite.Require().True(found) - suite.Require().Equal(oldPlan, storedPlan) - } else { - suite.Require().False(found) - suite.Require().Empty(storedPlan) - } - - // check that client state was not set - _, found = suite.chainA.App.UpgradeKeeper.GetUpgradedClient(suite.chainA.GetContext(), plan.Height) - suite.Require().False(found) - - } - }) - } - -} diff --git a/x/ibc/core/02-client/module.go b/x/ibc/core/02-client/module.go deleted file mode 100644 index 08efee8b1adc..000000000000 --- a/x/ibc/core/02-client/module.go +++ /dev/null @@ -1,29 +0,0 @@ -package client - -import ( - "github.com/gogo/protobuf/grpc" - "github.com/spf13/cobra" - - "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/client/cli" - "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" -) - -// Name returns the IBC client name -func Name() string { - return types.SubModuleName -} - -// GetQueryCmd returns no root query command for the IBC client -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/02-client/proposal_handler.go b/x/ibc/core/02-client/proposal_handler.go deleted file mode 100644 index f035ca99a0cc..000000000000 --- a/x/ibc/core/02-client/proposal_handler.go +++ /dev/null @@ -1,24 +0,0 @@ -package client - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/keeper" - "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" -) - -// NewClientProposalHandler defines the 02-client proposal handler -func NewClientProposalHandler(k keeper.Keeper) govtypes.Handler { - return func(ctx sdk.Context, content govtypes.Content) error { - switch c := content.(type) { - case *types.ClientUpdateProposal: - return k.ClientUpdateProposal(ctx, c) - case *types.UpgradeProposal: - return k.HandleUpgradeProposal(ctx, c) - - default: - return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized ibc proposal content type: %T", c) - } - } -} diff --git a/x/ibc/core/02-client/proposal_handler_test.go b/x/ibc/core/02-client/proposal_handler_test.go deleted file mode 100644 index 502da898e8a6..000000000000 --- a/x/ibc/core/02-client/proposal_handler_test.go +++ /dev/null @@ -1,84 +0,0 @@ -package client_test - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" - distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types" - govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" - client "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" -) - -func (suite *ClientTestSuite) TestNewClientUpdateProposalHandler() { - var ( - content govtypes.Content - err error - ) - - testCases := []struct { - name string - malleate func() - expPass bool - }{ - { - "valid update client proposal", func() { - 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.FrozenHeight = tmClientState.LatestHeight - suite.chainA.App.IBCKeeper.ClientKeeper.SetClientState(suite.chainA.GetContext(), subject, tmClientState) - - // 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 = clienttypes.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, subject, substitute, initialHeight) - }, true, - }, - { - "nil proposal", func() { - content = nil - }, false, - }, - { - "unsupported proposal type", func() { - content = distributiontypes.NewCommunityPoolSpendProposal(ibctesting.Title, ibctesting.Description, suite.chainA.SenderAccount.GetAddress(), sdk.NewCoins(sdk.NewCoin("communityfunds", sdk.NewInt(10)))) - }, false, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - suite.SetupTest() // reset - - tc.malleate() - - proposalHandler := client.NewClientProposalHandler(suite.chainA.App.IBCKeeper.ClientKeeper) - - err = proposalHandler(suite.chainA.GetContext(), content) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } - -} diff --git a/x/ibc/core/02-client/simulation/decoder.go b/x/ibc/core/02-client/simulation/decoder.go deleted file mode 100644 index 03a803b1b172..000000000000 --- a/x/ibc/core/02-client/simulation/decoder.go +++ /dev/null @@ -1,38 +0,0 @@ -package simulation - -import ( - "bytes" - "fmt" - - "github.com/cosmos/cosmos-sdk/types/kv" - "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/keeper" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -var _ ClientUnmarshaler = (*keeper.Keeper)(nil) - -// ClientUnmarshaler defines an interface for unmarshaling ICS02 interfaces. -type ClientUnmarshaler interface { - MustUnmarshalClientState([]byte) exported.ClientState - MustUnmarshalConsensusState([]byte) exported.ConsensusState -} - -// NewDecodeStore returns a decoder function closure that unmarshals the KVPair's -// Value to the corresponding client type. -func NewDecodeStore(cdc ClientUnmarshaler, kvA, kvB kv.Pair) (string, bool) { - switch { - case bytes.HasPrefix(kvA.Key, host.KeyClientStorePrefix) && bytes.HasSuffix(kvA.Key, []byte(host.KeyClientState)): - clientStateA := cdc.MustUnmarshalClientState(kvA.Value) - clientStateB := cdc.MustUnmarshalClientState(kvB.Value) - return fmt.Sprintf("ClientState A: %v\nClientState B: %v", clientStateA, clientStateB), true - - case bytes.HasPrefix(kvA.Key, host.KeyClientStorePrefix) && bytes.Contains(kvA.Key, []byte(host.KeyConsensusStatePrefix)): - consensusStateA := cdc.MustUnmarshalConsensusState(kvA.Value) - consensusStateB := cdc.MustUnmarshalConsensusState(kvB.Value) - return fmt.Sprintf("ConsensusState A: %v\nConsensusState B: %v", consensusStateA, consensusStateB), true - - default: - return "", false - } -} diff --git a/x/ibc/core/02-client/simulation/decoder_test.go b/x/ibc/core/02-client/simulation/decoder_test.go deleted file mode 100644 index 095834ba0d61..000000000000 --- a/x/ibc/core/02-client/simulation/decoder_test.go +++ /dev/null @@ -1,70 +0,0 @@ -package simulation_test - -import ( - "fmt" - "testing" - "time" - - "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/simapp" - "github.com/cosmos/cosmos-sdk/types/kv" - "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/simulation" - "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" -) - -func TestDecodeStore(t *testing.T) { - app := simapp.Setup(false) - clientID := "clientidone" - - height := types.NewHeight(0, 10) - - clientState := &ibctmtypes.ClientState{ - FrozenHeight: height, - } - - consState := &ibctmtypes.ConsensusState{ - Timestamp: time.Now().UTC(), - } - - kvPairs := kv.Pairs{ - Pairs: []kv.Pair{ - { - Key: host.FullClientStateKey(clientID), - Value: app.IBCKeeper.ClientKeeper.MustMarshalClientState(clientState), - }, - { - Key: host.FullConsensusStateKey(clientID, height), - Value: app.IBCKeeper.ClientKeeper.MustMarshalConsensusState(consState), - }, - { - Key: []byte{0x99}, - Value: []byte{0x99}, - }, - }, - } - tests := []struct { - name string - expectedLog string - }{ - {"ClientState", fmt.Sprintf("ClientState A: %v\nClientState B: %v", clientState, clientState)}, - {"ConsensusState", fmt.Sprintf("ConsensusState A: %v\nConsensusState B: %v", consState, consState)}, - {"other", ""}, - } - - for i, tt := range tests { - i, tt := i, tt - t.Run(tt.name, func(t *testing.T) { - res, found := simulation.NewDecodeStore(app.IBCKeeper.ClientKeeper, kvPairs.Pairs[i], kvPairs.Pairs[i]) - if i == len(tests)-1 { - require.False(t, found, string(kvPairs.Pairs[i].Key)) - require.Empty(t, res, string(kvPairs.Pairs[i].Key)) - } else { - require.True(t, found, string(kvPairs.Pairs[i].Key)) - require.Equal(t, tt.expectedLog, res, string(kvPairs.Pairs[i].Key)) - } - }) - } -} diff --git a/x/ibc/core/02-client/simulation/genesis.go b/x/ibc/core/02-client/simulation/genesis.go deleted file mode 100644 index 2f23197026c1..000000000000 --- a/x/ibc/core/02-client/simulation/genesis.go +++ /dev/null @@ -1,13 +0,0 @@ -package simulation - -import ( - "math/rand" - - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" -) - -// GenClientGenesis returns the default client genesis state. -func GenClientGenesis(_ *rand.Rand, _ []simtypes.Account) types.GenesisState { - return types.DefaultGenesisState() -} diff --git a/x/ibc/core/02-client/types/client.go b/x/ibc/core/02-client/types/client.go deleted file mode 100644 index 6d51828af0f7..000000000000 --- a/x/ibc/core/02-client/types/client.go +++ /dev/null @@ -1,111 +0,0 @@ -package types - -import ( - "fmt" - "math" - "sort" - "strings" - - proto "github.com/gogo/protobuf/proto" - - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -var ( - _ codectypes.UnpackInterfacesMessage = IdentifiedClientState{} - _ codectypes.UnpackInterfacesMessage = ConsensusStateWithHeight{} -) - -// NewIdentifiedClientState creates a new IdentifiedClientState instance -func NewIdentifiedClientState(clientID string, clientState exported.ClientState) IdentifiedClientState { - msg, ok := clientState.(proto.Message) - if !ok { - panic(fmt.Errorf("cannot proto marshal %T", clientState)) - } - - anyClientState, err := codectypes.NewAnyWithValue(msg) - if err != nil { - panic(err) - } - - return IdentifiedClientState{ - ClientId: clientID, - ClientState: anyClientState, - } -} - -// UnpackInterfaces implements UnpackInterfacesMesssage.UnpackInterfaces -func (ics IdentifiedClientState) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { - return unpacker.UnpackAny(ics.ClientState, new(exported.ClientState)) -} - -var _ sort.Interface = IdentifiedClientStates{} - -// IdentifiedClientStates defines a slice of ClientConsensusStates that supports the sort interface -type IdentifiedClientStates []IdentifiedClientState - -// Len implements sort.Interface -func (ics IdentifiedClientStates) Len() int { return len(ics) } - -// Less implements sort.Interface -func (ics IdentifiedClientStates) Less(i, j int) bool { return ics[i].ClientId < ics[j].ClientId } - -// Swap implements sort.Interface -func (ics IdentifiedClientStates) Swap(i, j int) { ics[i], ics[j] = ics[j], ics[i] } - -// Sort is a helper function to sort the set of IdentifiedClientStates in place -func (ics IdentifiedClientStates) Sort() IdentifiedClientStates { - sort.Sort(ics) - return ics -} - -// NewConsensusStateWithHeight creates a new ConsensusStateWithHeight instance -func NewConsensusStateWithHeight(height Height, consensusState exported.ConsensusState) ConsensusStateWithHeight { - msg, ok := consensusState.(proto.Message) - if !ok { - panic(fmt.Errorf("cannot proto marshal %T", consensusState)) - } - - anyConsensusState, err := codectypes.NewAnyWithValue(msg) - if err != nil { - panic(err) - } - - return ConsensusStateWithHeight{ - Height: height, - ConsensusState: anyConsensusState, - } -} - -// UnpackInterfaces implements UnpackInterfacesMesssage.UnpackInterfaces -func (cswh ConsensusStateWithHeight) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { - return unpacker.UnpackAny(cswh.ConsensusState, new(exported.ConsensusState)) -} - -// ValidateClientType validates the client type. It cannot be blank or empty. It must be a valid -// client identifier when used with '0' or the maximum uint64 as the sequence. -func ValidateClientType(clientType string) error { - if strings.TrimSpace(clientType) == "" { - return sdkerrors.Wrap(ErrInvalidClientType, "client type cannot be blank") - } - - smallestPossibleClientID := FormatClientIdentifier(clientType, 0) - largestPossibleClientID := FormatClientIdentifier(clientType, uint64(math.MaxUint64)) - - // IsValidClientID will check client type format and if the sequence is a uint64 - if !IsValidClientID(smallestPossibleClientID) { - return sdkerrors.Wrap(ErrInvalidClientType, "") - } - - if err := host.ClientIdentifierValidator(smallestPossibleClientID); err != nil { - return sdkerrors.Wrap(err, "client type results in smallest client identifier being invalid") - } - if err := host.ClientIdentifierValidator(largestPossibleClientID); err != nil { - return sdkerrors.Wrap(err, "client type results in largest client identifier being invalid") - } - - return nil -} diff --git a/x/ibc/core/02-client/types/client.pb.go b/x/ibc/core/02-client/types/client.pb.go deleted file mode 100644 index a9a799453900..000000000000 --- a/x/ibc/core/02-client/types/client.pb.go +++ /dev/null @@ -1,1946 +0,0 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: ibc/core/client/v1/client.proto - -package types - -import ( - fmt "fmt" - types "github.com/cosmos/cosmos-sdk/codec/types" - types1 "github.com/cosmos/cosmos-sdk/x/upgrade/types" - _ "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 - -// IdentifiedClientState defines a client state with an additional client -// identifier field. -type IdentifiedClientState struct { - // client identifier - ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty" yaml:"client_id"` - // client state - ClientState *types.Any `protobuf:"bytes,2,opt,name=client_state,json=clientState,proto3" json:"client_state,omitempty" yaml:"client_state"` -} - -func (m *IdentifiedClientState) Reset() { *m = IdentifiedClientState{} } -func (m *IdentifiedClientState) String() string { return proto.CompactTextString(m) } -func (*IdentifiedClientState) ProtoMessage() {} -func (*IdentifiedClientState) Descriptor() ([]byte, []int) { - return fileDescriptor_b6bc4c8185546947, []int{0} -} -func (m *IdentifiedClientState) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *IdentifiedClientState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_IdentifiedClientState.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 *IdentifiedClientState) XXX_Merge(src proto.Message) { - xxx_messageInfo_IdentifiedClientState.Merge(m, src) -} -func (m *IdentifiedClientState) XXX_Size() int { - return m.Size() -} -func (m *IdentifiedClientState) XXX_DiscardUnknown() { - xxx_messageInfo_IdentifiedClientState.DiscardUnknown(m) -} - -var xxx_messageInfo_IdentifiedClientState proto.InternalMessageInfo - -func (m *IdentifiedClientState) GetClientId() string { - if m != nil { - return m.ClientId - } - return "" -} - -func (m *IdentifiedClientState) GetClientState() *types.Any { - if m != nil { - return m.ClientState - } - return nil -} - -// ConsensusStateWithHeight defines a consensus state with an additional height field. -type ConsensusStateWithHeight struct { - // consensus state height - Height Height `protobuf:"bytes,1,opt,name=height,proto3" json:"height"` - // consensus state - ConsensusState *types.Any `protobuf:"bytes,2,opt,name=consensus_state,json=consensusState,proto3" json:"consensus_state,omitempty" yaml"consensus_state"` -} - -func (m *ConsensusStateWithHeight) Reset() { *m = ConsensusStateWithHeight{} } -func (m *ConsensusStateWithHeight) String() string { return proto.CompactTextString(m) } -func (*ConsensusStateWithHeight) ProtoMessage() {} -func (*ConsensusStateWithHeight) Descriptor() ([]byte, []int) { - return fileDescriptor_b6bc4c8185546947, []int{1} -} -func (m *ConsensusStateWithHeight) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *ConsensusStateWithHeight) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_ConsensusStateWithHeight.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 *ConsensusStateWithHeight) XXX_Merge(src proto.Message) { - xxx_messageInfo_ConsensusStateWithHeight.Merge(m, src) -} -func (m *ConsensusStateWithHeight) XXX_Size() int { - return m.Size() -} -func (m *ConsensusStateWithHeight) XXX_DiscardUnknown() { - xxx_messageInfo_ConsensusStateWithHeight.DiscardUnknown(m) -} - -var xxx_messageInfo_ConsensusStateWithHeight proto.InternalMessageInfo - -func (m *ConsensusStateWithHeight) GetHeight() Height { - if m != nil { - return m.Height - } - return Height{} -} - -func (m *ConsensusStateWithHeight) GetConsensusState() *types.Any { - if m != nil { - return m.ConsensusState - } - return nil -} - -// ClientConsensusStates defines all the stored consensus states for a given -// client. -type ClientConsensusStates struct { - // client identifier - ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty" yaml:"client_id"` - // consensus states and their heights associated with the client - ConsensusStates []ConsensusStateWithHeight `protobuf:"bytes,2,rep,name=consensus_states,json=consensusStates,proto3" json:"consensus_states" yaml:"consensus_states"` -} - -func (m *ClientConsensusStates) Reset() { *m = ClientConsensusStates{} } -func (m *ClientConsensusStates) String() string { return proto.CompactTextString(m) } -func (*ClientConsensusStates) ProtoMessage() {} -func (*ClientConsensusStates) Descriptor() ([]byte, []int) { - return fileDescriptor_b6bc4c8185546947, []int{2} -} -func (m *ClientConsensusStates) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *ClientConsensusStates) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_ClientConsensusStates.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 *ClientConsensusStates) XXX_Merge(src proto.Message) { - xxx_messageInfo_ClientConsensusStates.Merge(m, src) -} -func (m *ClientConsensusStates) XXX_Size() int { - return m.Size() -} -func (m *ClientConsensusStates) XXX_DiscardUnknown() { - xxx_messageInfo_ClientConsensusStates.DiscardUnknown(m) -} - -var xxx_messageInfo_ClientConsensusStates proto.InternalMessageInfo - -func (m *ClientConsensusStates) GetClientId() string { - if m != nil { - return m.ClientId - } - return "" -} - -func (m *ClientConsensusStates) GetConsensusStates() []ConsensusStateWithHeight { - if m != nil { - return m.ConsensusStates - } - return nil -} - -// 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 - 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{} } -func (m *ClientUpdateProposal) String() string { return proto.CompactTextString(m) } -func (*ClientUpdateProposal) ProtoMessage() {} -func (*ClientUpdateProposal) Descriptor() ([]byte, []int) { - return fileDescriptor_b6bc4c8185546947, []int{3} -} -func (m *ClientUpdateProposal) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *ClientUpdateProposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_ClientUpdateProposal.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 *ClientUpdateProposal) XXX_Merge(src proto.Message) { - xxx_messageInfo_ClientUpdateProposal.Merge(m, src) -} -func (m *ClientUpdateProposal) XXX_Size() int { - return m.Size() -} -func (m *ClientUpdateProposal) XXX_DiscardUnknown() { - xxx_messageInfo_ClientUpdateProposal.DiscardUnknown(m) -} - -var xxx_messageInfo_ClientUpdateProposal proto.InternalMessageInfo - -// UpgradeProposal is a gov Content type for initiating an IBC breaking -// upgrade. -type UpgradeProposal struct { - Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty"` - Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` - Plan types1.Plan `protobuf:"bytes,3,opt,name=plan,proto3" json:"plan"` - // An UpgradedClientState must be provided to perform an IBC breaking upgrade. - // 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 - UpgradedClientState *types.Any `protobuf:"bytes,4,opt,name=upgraded_client_state,json=upgradedClientState,proto3" json:"upgraded_client_state,omitempty" yaml:"upgraded_client_state"` -} - -func (m *UpgradeProposal) Reset() { *m = UpgradeProposal{} } -func (*UpgradeProposal) ProtoMessage() {} -func (*UpgradeProposal) Descriptor() ([]byte, []int) { - return fileDescriptor_b6bc4c8185546947, []int{4} -} -func (m *UpgradeProposal) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *UpgradeProposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_UpgradeProposal.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 *UpgradeProposal) XXX_Merge(src proto.Message) { - xxx_messageInfo_UpgradeProposal.Merge(m, src) -} -func (m *UpgradeProposal) XXX_Size() int { - return m.Size() -} -func (m *UpgradeProposal) XXX_DiscardUnknown() { - xxx_messageInfo_UpgradeProposal.DiscardUnknown(m) -} - -var xxx_messageInfo_UpgradeProposal proto.InternalMessageInfo - -// Height is a monotonically increasing data type -// that can be compared against another Height for the purposes of updating and -// freezing clients -// -// Normally the RevisionHeight is incremented at each height while keeping RevisionNumber -// the same. However some consensus algorithms may choose to reset the -// height in certain conditions e.g. hard forks, state-machine breaking changes -// In these cases, the RevisionNumber is incremented so that height continues to -// be monitonically increasing even as the RevisionHeight gets reset -type Height struct { - // the revision that the client is currently on - RevisionNumber uint64 `protobuf:"varint,1,opt,name=revision_number,json=revisionNumber,proto3" json:"revision_number,omitempty" yaml:"revision_number"` - // the height within the given revision - RevisionHeight uint64 `protobuf:"varint,2,opt,name=revision_height,json=revisionHeight,proto3" json:"revision_height,omitempty" yaml:"revision_height"` -} - -func (m *Height) Reset() { *m = Height{} } -func (*Height) ProtoMessage() {} -func (*Height) Descriptor() ([]byte, []int) { - return fileDescriptor_b6bc4c8185546947, []int{5} -} -func (m *Height) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *Height) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_Height.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 *Height) XXX_Merge(src proto.Message) { - xxx_messageInfo_Height.Merge(m, src) -} -func (m *Height) XXX_Size() int { - return m.Size() -} -func (m *Height) XXX_DiscardUnknown() { - xxx_messageInfo_Height.DiscardUnknown(m) -} - -var xxx_messageInfo_Height proto.InternalMessageInfo - -// Params defines the set of IBC light client parameters. -type Params struct { - // allowed_clients defines the list of allowed client state types. - AllowedClients []string `protobuf:"bytes,1,rep,name=allowed_clients,json=allowedClients,proto3" json:"allowed_clients,omitempty" yaml:"allowed_clients"` -} - -func (m *Params) Reset() { *m = Params{} } -func (m *Params) String() string { return proto.CompactTextString(m) } -func (*Params) ProtoMessage() {} -func (*Params) Descriptor() ([]byte, []int) { - return fileDescriptor_b6bc4c8185546947, []int{6} -} -func (m *Params) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *Params) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_Params.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 *Params) XXX_Merge(src proto.Message) { - xxx_messageInfo_Params.Merge(m, src) -} -func (m *Params) XXX_Size() int { - return m.Size() -} -func (m *Params) XXX_DiscardUnknown() { - xxx_messageInfo_Params.DiscardUnknown(m) -} - -var xxx_messageInfo_Params proto.InternalMessageInfo - -func (m *Params) GetAllowedClients() []string { - if m != nil { - return m.AllowedClients - } - return nil -} - -func init() { - proto.RegisterType((*IdentifiedClientState)(nil), "ibc.core.client.v1.IdentifiedClientState") - proto.RegisterType((*ConsensusStateWithHeight)(nil), "ibc.core.client.v1.ConsensusStateWithHeight") - proto.RegisterType((*ClientConsensusStates)(nil), "ibc.core.client.v1.ClientConsensusStates") - proto.RegisterType((*ClientUpdateProposal)(nil), "ibc.core.client.v1.ClientUpdateProposal") - proto.RegisterType((*UpgradeProposal)(nil), "ibc.core.client.v1.UpgradeProposal") - proto.RegisterType((*Height)(nil), "ibc.core.client.v1.Height") - proto.RegisterType((*Params)(nil), "ibc.core.client.v1.Params") -} - -func init() { proto.RegisterFile("ibc/core/client/v1/client.proto", fileDescriptor_b6bc4c8185546947) } - -var fileDescriptor_b6bc4c8185546947 = []byte{ - // 740 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x55, 0x3f, 0x6f, 0xd3, 0x4e, - 0x18, 0x8e, 0xd3, 0x34, 0x6a, 0x2e, 0xfd, 0x25, 0xfd, 0xb9, 0x09, 0x4d, 0x43, 0x89, 0xa3, 0x13, - 0x43, 0x06, 0x6a, 0x93, 0x20, 0x01, 0xea, 0x46, 0xb2, 0xb4, 0x03, 0x28, 0x35, 0xaa, 0x40, 0x2c, - 0xc1, 0x7f, 0xae, 0xc9, 0x15, 0xc7, 0x17, 0xf9, 0xce, 0xa1, 0xf9, 0x06, 0x8c, 0x8c, 0x0c, 0x0c, - 0xfd, 0x04, 0x7c, 0x0a, 0x86, 0x8e, 0x95, 0x58, 0x98, 0x2c, 0xd4, 0x2e, 0xcc, 0x5e, 0x59, 0x90, - 0x7d, 0xe7, 0x34, 0x49, 0x5b, 0x40, 0x30, 0xf9, 0xee, 0xbd, 0xe7, 0x9e, 0xf7, 0x7d, 0x9e, 0xbb, - 0xf7, 0x0c, 0x14, 0x6c, 0x5a, 0x9a, 0x45, 0x3c, 0xa4, 0x59, 0x0e, 0x46, 0x2e, 0xd3, 0xc6, 0x4d, - 0x31, 0x52, 0x47, 0x1e, 0x61, 0x44, 0x96, 0xb1, 0x69, 0xa9, 0x11, 0x40, 0x15, 0xe1, 0x71, 0xb3, - 0x5a, 0xea, 0x93, 0x3e, 0x89, 0x97, 0xb5, 0x68, 0xc4, 0x91, 0xd5, 0xcd, 0x3e, 0x21, 0x7d, 0x07, - 0x69, 0xf1, 0xcc, 0xf4, 0x0f, 0x35, 0xc3, 0x9d, 0x88, 0xa5, 0xbb, 0x16, 0xa1, 0x43, 0x42, 0x35, - 0x7f, 0xd4, 0xf7, 0x0c, 0x1b, 0x69, 0xe3, 0xa6, 0x89, 0x98, 0xd1, 0x4c, 0xe6, 0x1c, 0x05, 0x3f, - 0x4a, 0xa0, 0xbc, 0x67, 0x23, 0x97, 0xe1, 0x43, 0x8c, 0xec, 0x4e, 0x9c, 0xee, 0x39, 0x33, 0x18, - 0x92, 0x9b, 0x20, 0xc7, 0xb3, 0xf7, 0xb0, 0x5d, 0x91, 0xea, 0x52, 0x23, 0xd7, 0x2e, 0x85, 0x81, - 0xb2, 0x36, 0x31, 0x86, 0xce, 0x0e, 0x9c, 0x2e, 0x41, 0x7d, 0x85, 0x8f, 0xf7, 0x6c, 0xb9, 0x0b, - 0x56, 0x45, 0x9c, 0x46, 0x14, 0x95, 0x74, 0x5d, 0x6a, 0xe4, 0x5b, 0x25, 0x95, 0x17, 0xa9, 0x26, - 0x45, 0xaa, 0x4f, 0xdc, 0x49, 0x7b, 0x23, 0x0c, 0x94, 0xf5, 0x39, 0xae, 0x78, 0x0f, 0xd4, 0xf3, - 0xd6, 0x65, 0x11, 0xf0, 0x93, 0x04, 0x2a, 0x1d, 0xe2, 0x52, 0xe4, 0x52, 0x9f, 0xc6, 0xa1, 0x17, - 0x98, 0x0d, 0x76, 0x11, 0xee, 0x0f, 0x98, 0xfc, 0x18, 0x64, 0x07, 0xf1, 0x28, 0x2e, 0x2f, 0xdf, - 0xaa, 0xaa, 0x57, 0x7d, 0x53, 0x39, 0xb6, 0x9d, 0x39, 0x0d, 0x94, 0x94, 0x2e, 0xf0, 0xf2, 0x4b, - 0x50, 0xb4, 0x12, 0xd6, 0x3f, 0xa8, 0x75, 0x33, 0x0c, 0x94, 0x72, 0x54, 0x2b, 0x5c, 0xd8, 0x05, - 0xf5, 0x82, 0x35, 0x57, 0x1d, 0xfc, 0x2c, 0x81, 0x32, 0x77, 0x71, 0xbe, 0x6c, 0xfa, 0x37, 0x7e, - 0x1e, 0x83, 0xb5, 0x85, 0x84, 0xb4, 0x92, 0xae, 0x2f, 0x35, 0xf2, 0xad, 0x7b, 0xd7, 0x49, 0xbd, - 0xc9, 0xa8, 0xb6, 0x12, 0x89, 0x0f, 0x03, 0x65, 0x43, 0xe4, 0x5a, 0xe0, 0x84, 0x7a, 0x71, 0x5e, - 0x05, 0x85, 0x5f, 0xd2, 0xa0, 0xc4, 0x65, 0x1c, 0x8c, 0x6c, 0x83, 0xa1, 0xae, 0x47, 0x46, 0x84, - 0x1a, 0x8e, 0x5c, 0x02, 0xcb, 0x0c, 0x33, 0x07, 0x71, 0x05, 0x3a, 0x9f, 0xc8, 0x75, 0x90, 0xb7, - 0x11, 0xb5, 0x3c, 0x3c, 0x62, 0x98, 0xb8, 0xb1, 0x97, 0x39, 0x7d, 0x36, 0x24, 0xef, 0x82, 0xff, - 0xa9, 0x6f, 0x1e, 0x21, 0x8b, 0xf5, 0x2e, 0x5d, 0x58, 0x8a, 0x5d, 0xd8, 0x0a, 0x03, 0xa5, 0xc2, - 0x2b, 0xbb, 0x02, 0x81, 0x7a, 0x51, 0xc4, 0x3a, 0x89, 0x29, 0xfb, 0xa0, 0x44, 0x7d, 0x93, 0x32, - 0xcc, 0x7c, 0x86, 0x66, 0xc8, 0x32, 0x31, 0x99, 0x12, 0x06, 0xca, 0xed, 0x84, 0x8c, 0x9a, 0x8b, - 0x28, 0xa8, 0xcb, 0x97, 0x9b, 0xa7, 0x94, 0xaf, 0x41, 0x01, 0xbb, 0x98, 0x61, 0xc3, 0xe9, 0x89, - 0x0b, 0xb5, 0xfc, 0xdb, 0x0b, 0x75, 0x47, 0x78, 0x5a, 0xe6, 0xc9, 0xe6, 0xf7, 0x43, 0xfd, 0x3f, - 0x11, 0xe0, 0xe8, 0x9d, 0xcc, 0xbb, 0x13, 0x25, 0x05, 0x7f, 0x48, 0xa0, 0x78, 0xc0, 0xdb, 0xef, - 0x9f, 0x0d, 0x7d, 0x08, 0x32, 0x23, 0xc7, 0x70, 0x63, 0x0f, 0xf3, 0xad, 0x2d, 0x95, 0x77, 0xbb, - 0x9a, 0x74, 0xb7, 0xe8, 0x76, 0xb5, 0xeb, 0x18, 0xae, 0xb8, 0xfc, 0x31, 0x5e, 0x3e, 0x02, 0x65, - 0x81, 0xb1, 0x7b, 0x73, 0xcd, 0x9a, 0xf9, 0x45, 0x03, 0xd4, 0xc3, 0x40, 0xd9, 0xe2, 0x42, 0xaf, - 0xdd, 0x0c, 0xf5, 0xf5, 0x24, 0x3e, 0xf3, 0x84, 0xec, 0xac, 0x46, 0xaa, 0x3f, 0x9c, 0x28, 0xa9, - 0xef, 0x27, 0x8a, 0x14, 0x3d, 0x35, 0x59, 0xd1, 0xb9, 0x1d, 0x50, 0xf4, 0xd0, 0x18, 0x53, 0x4c, - 0xdc, 0x9e, 0xeb, 0x0f, 0x4d, 0xe4, 0xc5, 0xf2, 0x33, 0xed, 0x6a, 0x18, 0x28, 0xb7, 0x78, 0xa2, - 0x05, 0x00, 0xd4, 0x0b, 0x49, 0xe4, 0x59, 0x1c, 0x98, 0x23, 0x11, 0xc7, 0x96, 0xbe, 0x91, 0x24, - 0x39, 0x97, 0x29, 0x89, 0x38, 0x98, 0x95, 0xa4, 0x44, 0xf8, 0x14, 0x64, 0xbb, 0x86, 0x67, 0x0c, - 0x69, 0x44, 0x6c, 0x38, 0x0e, 0x79, 0x3b, 0x15, 0x49, 0x2b, 0x52, 0x7d, 0xa9, 0x91, 0x9b, 0x25, - 0x5e, 0x00, 0x40, 0xbd, 0x20, 0x22, 0x5c, 0x3f, 0x6d, 0xef, 0x9f, 0x9e, 0xd7, 0xa4, 0xb3, 0xf3, - 0x9a, 0xf4, 0xed, 0xbc, 0x26, 0xbd, 0xbf, 0xa8, 0xa5, 0xce, 0x2e, 0x6a, 0xa9, 0xaf, 0x17, 0xb5, - 0xd4, 0xab, 0x47, 0x7d, 0xcc, 0x06, 0xbe, 0xa9, 0x5a, 0x64, 0xa8, 0x89, 0x37, 0x9a, 0x7f, 0xb6, - 0xa9, 0xfd, 0x46, 0x3b, 0xd6, 0xa6, 0x7f, 0x87, 0xfb, 0xad, 0x6d, 0xf1, 0x83, 0x60, 0x93, 0x11, - 0xa2, 0x66, 0x36, 0x3e, 0x93, 0x07, 0x3f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x66, 0x9c, 0xf8, 0xf8, - 0x40, 0x06, 0x00, 0x00, -} - -func (this *UpgradeProposal) Equal(that interface{}) bool { - if that == nil { - return this == nil - } - - that1, ok := that.(*UpgradeProposal) - if !ok { - that2, ok := that.(UpgradeProposal) - if ok { - that1 = &that2 - } else { - return false - } - } - if that1 == nil { - return this == nil - } else if this == nil { - return false - } - if this.Title != that1.Title { - return false - } - if this.Description != that1.Description { - return false - } - if !this.Plan.Equal(&that1.Plan) { - return false - } - if !this.UpgradedClientState.Equal(that1.UpgradedClientState) { - return false - } - return true -} -func (m *IdentifiedClientState) 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 *IdentifiedClientState) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *IdentifiedClientState) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.ClientState != nil { - { - size, err := m.ClientState.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintClient(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - } - if len(m.ClientId) > 0 { - i -= len(m.ClientId) - copy(dAtA[i:], m.ClientId) - i = encodeVarintClient(dAtA, i, uint64(len(m.ClientId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *ConsensusStateWithHeight) 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 *ConsensusStateWithHeight) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *ConsensusStateWithHeight) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.ConsensusState != nil { - { - size, err := m.ConsensusState.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintClient(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - } - { - size, err := m.Height.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintClient(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0xa - return len(dAtA) - i, nil -} - -func (m *ClientConsensusStates) 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 *ClientConsensusStates) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *ClientConsensusStates) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.ConsensusStates) > 0 { - for iNdEx := len(m.ConsensusStates) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.ConsensusStates[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintClient(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - } - } - if len(m.ClientId) > 0 { - i -= len(m.ClientId) - copy(dAtA[i:], m.ClientId) - i = encodeVarintClient(dAtA, i, uint64(len(m.ClientId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *ClientUpdateProposal) 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 *ClientUpdateProposal) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *ClientUpdateProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - { - 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.SubjectClientId) > 0 { - i -= len(m.SubjectClientId) - copy(dAtA[i:], m.SubjectClientId) - i = encodeVarintClient(dAtA, i, uint64(len(m.SubjectClientId))) - i-- - dAtA[i] = 0x1a - } - if len(m.Description) > 0 { - i -= len(m.Description) - copy(dAtA[i:], m.Description) - i = encodeVarintClient(dAtA, i, uint64(len(m.Description))) - i-- - dAtA[i] = 0x12 - } - if len(m.Title) > 0 { - i -= len(m.Title) - copy(dAtA[i:], m.Title) - i = encodeVarintClient(dAtA, i, uint64(len(m.Title))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *UpgradeProposal) 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 *UpgradeProposal) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *UpgradeProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.UpgradedClientState != nil { - { - size, err := m.UpgradedClientState.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintClient(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x22 - } - { - size, err := m.Plan.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintClient(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - if len(m.Description) > 0 { - i -= len(m.Description) - copy(dAtA[i:], m.Description) - i = encodeVarintClient(dAtA, i, uint64(len(m.Description))) - i-- - dAtA[i] = 0x12 - } - if len(m.Title) > 0 { - i -= len(m.Title) - copy(dAtA[i:], m.Title) - i = encodeVarintClient(dAtA, i, uint64(len(m.Title))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *Height) 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 *Height) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *Height) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.RevisionHeight != 0 { - i = encodeVarintClient(dAtA, i, uint64(m.RevisionHeight)) - i-- - dAtA[i] = 0x10 - } - if m.RevisionNumber != 0 { - i = encodeVarintClient(dAtA, i, uint64(m.RevisionNumber)) - i-- - dAtA[i] = 0x8 - } - return len(dAtA) - i, nil -} - -func (m *Params) 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 *Params) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.AllowedClients) > 0 { - for iNdEx := len(m.AllowedClients) - 1; iNdEx >= 0; iNdEx-- { - i -= len(m.AllowedClients[iNdEx]) - copy(dAtA[i:], m.AllowedClients[iNdEx]) - i = encodeVarintClient(dAtA, i, uint64(len(m.AllowedClients[iNdEx]))) - i-- - dAtA[i] = 0xa - } - } - return len(dAtA) - i, nil -} - -func encodeVarintClient(dAtA []byte, offset int, v uint64) int { - offset -= sovClient(v) - base := offset - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ - } - dAtA[offset] = uint8(v) - return base -} -func (m *IdentifiedClientState) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.ClientId) - if l > 0 { - n += 1 + l + sovClient(uint64(l)) - } - if m.ClientState != nil { - l = m.ClientState.Size() - n += 1 + l + sovClient(uint64(l)) - } - return n -} - -func (m *ConsensusStateWithHeight) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = m.Height.Size() - n += 1 + l + sovClient(uint64(l)) - if m.ConsensusState != nil { - l = m.ConsensusState.Size() - n += 1 + l + sovClient(uint64(l)) - } - return n -} - -func (m *ClientConsensusStates) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.ClientId) - if l > 0 { - n += 1 + l + sovClient(uint64(l)) - } - if len(m.ConsensusStates) > 0 { - for _, e := range m.ConsensusStates { - l = e.Size() - n += 1 + l + sovClient(uint64(l)) - } - } - return n -} - -func (m *ClientUpdateProposal) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Title) - if l > 0 { - n += 1 + l + sovClient(uint64(l)) - } - l = len(m.Description) - if l > 0 { - n += 1 + l + sovClient(uint64(l)) - } - l = len(m.SubjectClientId) - if l > 0 { - n += 1 + l + sovClient(uint64(l)) - } - 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 -} - -func (m *UpgradeProposal) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Title) - if l > 0 { - n += 1 + l + sovClient(uint64(l)) - } - l = len(m.Description) - if l > 0 { - n += 1 + l + sovClient(uint64(l)) - } - l = m.Plan.Size() - n += 1 + l + sovClient(uint64(l)) - if m.UpgradedClientState != nil { - l = m.UpgradedClientState.Size() - n += 1 + l + sovClient(uint64(l)) - } - return n -} - -func (m *Height) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.RevisionNumber != 0 { - n += 1 + sovClient(uint64(m.RevisionNumber)) - } - if m.RevisionHeight != 0 { - n += 1 + sovClient(uint64(m.RevisionHeight)) - } - return n -} - -func (m *Params) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if len(m.AllowedClients) > 0 { - for _, s := range m.AllowedClients { - l = len(s) - n += 1 + l + sovClient(uint64(l)) - } - } - return n -} - -func sovClient(x uint64) (n int) { - return (math_bits.Len64(x|1) + 6) / 7 -} -func sozClient(x uint64) (n int) { - return sovClient(uint64((x << 1) ^ uint64((int64(x) >> 63)))) -} -func (m *IdentifiedClientState) 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 ErrIntOverflowClient - } - 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: IdentifiedClientState: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: IdentifiedClientState: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ClientId", 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.ClientId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ClientState", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowClient - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthClient - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthClient - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.ClientState == nil { - m.ClientState = &types.Any{} - } - if err := m.ClientState.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipClient(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthClient - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *ConsensusStateWithHeight) 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 ErrIntOverflowClient - } - 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: ConsensusStateWithHeight: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: ConsensusStateWithHeight: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowClient - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthClient - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthClient - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.Height.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ConsensusState", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowClient - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthClient - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthClient - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.ConsensusState == nil { - m.ConsensusState = &types.Any{} - } - if err := m.ConsensusState.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipClient(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthClient - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *ClientConsensusStates) 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 ErrIntOverflowClient - } - 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: ClientConsensusStates: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: ClientConsensusStates: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ClientId", 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.ClientId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ConsensusStates", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowClient - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthClient - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthClient - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ConsensusStates = append(m.ConsensusStates, ConsensusStateWithHeight{}) - if err := m.ConsensusStates[len(m.ConsensusStates)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipClient(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthClient - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *ClientUpdateProposal) 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 ErrIntOverflowClient - } - 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: ClientUpdateProposal: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: ClientUpdateProposal: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Title", 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.Title = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Description", 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.Description = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field SubjectClientId", 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.SubjectClientId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 4: - if wireType != 2 { - 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 { - if shift >= 64 { - return ErrIntOverflowClient - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthClient - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthClient - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.InitialHeight.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipClient(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthClient - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *UpgradeProposal) 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 ErrIntOverflowClient - } - 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: UpgradeProposal: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: UpgradeProposal: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Title", 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.Title = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Description", 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.Description = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Plan", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowClient - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthClient - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthClient - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.Plan.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field UpgradedClientState", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowClient - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthClient - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthClient - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.UpgradedClientState == nil { - m.UpgradedClientState = &types.Any{} - } - if err := m.UpgradedClientState.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipClient(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthClient - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *Height) 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 ErrIntOverflowClient - } - 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: Height: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: Height: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field RevisionNumber", wireType) - } - m.RevisionNumber = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowClient - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.RevisionNumber |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field RevisionHeight", wireType) - } - m.RevisionHeight = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowClient - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.RevisionHeight |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - default: - iNdEx = preIndex - skippy, err := skipClient(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthClient - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *Params) 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 ErrIntOverflowClient - } - 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: Params: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: Params: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field AllowedClients", 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.AllowedClients = append(m.AllowedClients, string(dAtA[iNdEx:postIndex])) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipClient(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthClient - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func skipClient(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, ErrIntOverflowClient - } - 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, ErrIntOverflowClient - } - 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, ErrIntOverflowClient - } - 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, ErrInvalidLengthClient - } - iNdEx += length - case 3: - depth++ - case 4: - if depth == 0 { - return 0, ErrUnexpectedEndOfGroupClient - } - depth-- - case 5: - iNdEx += 4 - default: - return 0, fmt.Errorf("proto: illegal wireType %d", wireType) - } - if iNdEx < 0 { - return 0, ErrInvalidLengthClient - } - if depth == 0 { - return iNdEx, nil - } - } - return 0, io.ErrUnexpectedEOF -} - -var ( - ErrInvalidLengthClient = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowClient = fmt.Errorf("proto: integer overflow") - ErrUnexpectedEndOfGroupClient = fmt.Errorf("proto: unexpected end of group") -) diff --git a/x/ibc/core/02-client/types/client_test.go b/x/ibc/core/02-client/types/client_test.go deleted file mode 100644 index 2dfd3967d288..000000000000 --- a/x/ibc/core/02-client/types/client_test.go +++ /dev/null @@ -1,87 +0,0 @@ -package types_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" -) - -func (suite *TypesTestSuite) TestMarshalConsensusStateWithHeight() { - var ( - cswh types.ConsensusStateWithHeight - ) - - testCases := []struct { - name string - malleate func() - }{ - { - "solo machine client", func() { - soloMachine := ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "solomachine", "", 1) - cswh = types.NewConsensusStateWithHeight(types.NewHeight(0, soloMachine.Sequence), soloMachine.ConsensusState()) - }, - }, - { - "tendermint client", func() { - clientA, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - clientState := suite.chainA.GetClientState(clientA) - consensusState, ok := suite.chainA.GetConsensusState(clientA, clientState.GetLatestHeight()) - suite.Require().True(ok) - - cswh = types.NewConsensusStateWithHeight(clientState.GetLatestHeight().(types.Height), consensusState) - }, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - suite.SetupTest() - - tc.malleate() - - cdc := suite.chainA.App.AppCodec() - - // marshal message - bz, err := cdc.MarshalJSON(&cswh) - suite.Require().NoError(err) - - // unmarshal message - newCswh := &types.ConsensusStateWithHeight{} - err = cdc.UnmarshalJSON(bz, newCswh) - suite.Require().NoError(err) - }) - } -} - -func TestValidateClientType(t *testing.T) { - testCases := []struct { - name string - clientType string - expPass bool - }{ - {"valid", "tendermint", true}, - {"valid solomachine", "solomachine-v1", true}, - {"too large", "tenderminttenderminttenderminttenderminttendermintt", false}, - {"too short", "t", false}, - {"blank id", " ", false}, - {"empty id", "", false}, - {"ends with dash", "tendermint-", false}, - } - - for _, tc := range testCases { - - err := types.ValidateClientType(tc.clientType) - - if tc.expPass { - require.NoError(t, err, tc.name) - } else { - require.Error(t, err, tc.name) - } - } -} diff --git a/x/ibc/core/02-client/types/codec.go b/x/ibc/core/02-client/types/codec.go deleted file mode 100644 index 8f8ab56112c7..000000000000 --- a/x/ibc/core/02-client/types/codec.go +++ /dev/null @@ -1,189 +0,0 @@ -package types - -import ( - proto "github.com/gogo/protobuf/proto" - - 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/types/msgservice" - govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -// RegisterInterfaces registers the client interfaces to protobuf Any. -func RegisterInterfaces(registry codectypes.InterfaceRegistry) { - registry.RegisterInterface( - "ibc.core.client.v1.ClientState", - (*exported.ClientState)(nil), - ) - registry.RegisterInterface( - "ibc.core.client.v1.ConsensusState", - (*exported.ConsensusState)(nil), - ) - registry.RegisterInterface( - "ibc.core.client.v1.Header", - (*exported.Header)(nil), - ) - registry.RegisterInterface( - "ibc.core.client.v1.Height", - (*exported.Height)(nil), - &Height{}, - ) - registry.RegisterInterface( - "ibc.core.client.v1.Misbehaviour", - (*exported.Misbehaviour)(nil), - ) - registry.RegisterImplementations( - (*govtypes.Content)(nil), - &ClientUpdateProposal{}, - &UpgradeProposal{}, - ) - registry.RegisterImplementations( - (*sdk.Msg)(nil), - &MsgCreateClient{}, - &MsgUpdateClient{}, - &MsgUpgradeClient{}, - &MsgSubmitMisbehaviour{}, - ) - - msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) -} - -// PackClientState constructs a new Any packed with the given client state value. It returns -// an error if the client state can't be casted to a protobuf message or if the concrete -// implemention is not registered to the protobuf codec. -func PackClientState(clientState exported.ClientState) (*codectypes.Any, error) { - msg, ok := clientState.(proto.Message) - if !ok { - return nil, sdkerrors.Wrapf(sdkerrors.ErrPackAny, "cannot proto marshal %T", clientState) - } - - anyClientState, err := codectypes.NewAnyWithValue(msg) - if err != nil { - return nil, sdkerrors.Wrap(sdkerrors.ErrPackAny, err.Error()) - } - - return anyClientState, nil -} - -// UnpackClientState unpacks an Any into a ClientState. It returns an error if the -// client state can't be unpacked into a ClientState. -func UnpackClientState(any *codectypes.Any) (exported.ClientState, error) { - if any == nil { - return nil, sdkerrors.Wrap(sdkerrors.ErrUnpackAny, "protobuf Any message cannot be nil") - } - - clientState, ok := any.GetCachedValue().(exported.ClientState) - if !ok { - return nil, sdkerrors.Wrapf(sdkerrors.ErrUnpackAny, "cannot unpack Any into ClientState %T", any) - } - - return clientState, nil -} - -// PackConsensusState constructs a new Any packed with the given consensus state value. It returns -// an error if the consensus state can't be casted to a protobuf message or if the concrete -// implemention is not registered to the protobuf codec. -func PackConsensusState(consensusState exported.ConsensusState) (*codectypes.Any, error) { - msg, ok := consensusState.(proto.Message) - if !ok { - return nil, sdkerrors.Wrapf(sdkerrors.ErrPackAny, "cannot proto marshal %T", consensusState) - } - - anyConsensusState, err := codectypes.NewAnyWithValue(msg) - if err != nil { - return nil, sdkerrors.Wrap(sdkerrors.ErrPackAny, err.Error()) - } - - return anyConsensusState, nil -} - -// MustPackConsensusState calls PackConsensusState and panics on error. -func MustPackConsensusState(consensusState exported.ConsensusState) *codectypes.Any { - anyConsensusState, err := PackConsensusState(consensusState) - if err != nil { - panic(err) - } - - return anyConsensusState -} - -// UnpackConsensusState unpacks an Any into a ConsensusState. It returns an error if the -// consensus state can't be unpacked into a ConsensusState. -func UnpackConsensusState(any *codectypes.Any) (exported.ConsensusState, error) { - if any == nil { - return nil, sdkerrors.Wrap(sdkerrors.ErrUnpackAny, "protobuf Any message cannot be nil") - } - - consensusState, ok := any.GetCachedValue().(exported.ConsensusState) - if !ok { - return nil, sdkerrors.Wrapf(sdkerrors.ErrUnpackAny, "cannot unpack Any into ConsensusState %T", any) - } - - return consensusState, nil -} - -// PackHeader constructs a new Any packed with the given header value. It returns -// an error if the header can't be casted to a protobuf message or if the concrete -// implemention is not registered to the protobuf codec. -func PackHeader(header exported.Header) (*codectypes.Any, error) { - msg, ok := header.(proto.Message) - if !ok { - return nil, sdkerrors.Wrapf(sdkerrors.ErrPackAny, "cannot proto marshal %T", header) - } - - anyHeader, err := codectypes.NewAnyWithValue(msg) - if err != nil { - return nil, sdkerrors.Wrap(sdkerrors.ErrPackAny, err.Error()) - } - - return anyHeader, nil -} - -// UnpackHeader unpacks an Any into a Header. It returns an error if the -// consensus state can't be unpacked into a Header. -func UnpackHeader(any *codectypes.Any) (exported.Header, error) { - if any == nil { - return nil, sdkerrors.Wrap(sdkerrors.ErrUnpackAny, "protobuf Any message cannot be nil") - } - - header, ok := any.GetCachedValue().(exported.Header) - if !ok { - return nil, sdkerrors.Wrapf(sdkerrors.ErrUnpackAny, "cannot unpack Any into Header %T", any) - } - - return header, nil -} - -// PackMisbehaviour constructs a new Any packed with the given misbehaviour value. It returns -// an error if the misbehaviour can't be casted to a protobuf message or if the concrete -// implemention is not registered to the protobuf codec. -func PackMisbehaviour(misbehaviour exported.Misbehaviour) (*codectypes.Any, error) { - msg, ok := misbehaviour.(proto.Message) - if !ok { - return nil, sdkerrors.Wrapf(sdkerrors.ErrPackAny, "cannot proto marshal %T", misbehaviour) - } - - anyMisbhaviour, err := codectypes.NewAnyWithValue(msg) - if err != nil { - return nil, sdkerrors.Wrap(sdkerrors.ErrPackAny, err.Error()) - } - - return anyMisbhaviour, nil -} - -// UnpackMisbehaviour unpacks an Any into a Misbehaviour. It returns an error if the -// Any can't be unpacked into a Misbehaviour. -func UnpackMisbehaviour(any *codectypes.Any) (exported.Misbehaviour, error) { - if any == nil { - return nil, sdkerrors.Wrap(sdkerrors.ErrUnpackAny, "protobuf Any message cannot be nil") - } - - misbehaviour, ok := any.GetCachedValue().(exported.Misbehaviour) - if !ok { - return nil, sdkerrors.Wrapf(sdkerrors.ErrUnpackAny, "cannot unpack Any into Misbehaviour %T", any) - } - - return misbehaviour, nil -} diff --git a/x/ibc/core/02-client/types/codec_test.go b/x/ibc/core/02-client/types/codec_test.go deleted file mode 100644 index 75cfc97eb08f..000000000000 --- a/x/ibc/core/02-client/types/codec_test.go +++ /dev/null @@ -1,210 +0,0 @@ -package types_test - -import ( - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - "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/core/exported" - ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" - localhosttypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/09-localhost/types" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" -) - -type caseAny struct { - name string - any *codectypes.Any - expPass bool -} - -func (suite *TypesTestSuite) TestPackClientState() { - - testCases := []struct { - name string - clientState exported.ClientState - expPass bool - }{ - { - "solo machine client", - ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "solomachine", "", 2).ClientState(), - true, - }, - { - "tendermint client", - ibctmtypes.NewClientState(chainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), - true, - }, - { - "localhost client", - localhosttypes.NewClientState(chainID, clientHeight), - true, - }, - { - "nil", - nil, - false, - }, - } - - testCasesAny := []caseAny{} - - for _, tc := range testCases { - clientAny, err := types.PackClientState(tc.clientState) - if tc.expPass { - suite.Require().NoError(err, tc.name) - } else { - suite.Require().Error(err, tc.name) - } - - testCasesAny = append(testCasesAny, caseAny{tc.name, clientAny, tc.expPass}) - } - - for i, tc := range testCasesAny { - cs, err := types.UnpackClientState(tc.any) - if tc.expPass { - suite.Require().NoError(err, tc.name) - suite.Require().Equal(testCases[i].clientState, cs, tc.name) - } else { - suite.Require().Error(err, tc.name) - } - } -} - -func (suite *TypesTestSuite) TestPackConsensusState() { - testCases := []struct { - name string - consensusState exported.ConsensusState - expPass bool - }{ - { - "solo machine consensus", - ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "solomachine", "", 2).ConsensusState(), - true, - }, - { - "tendermint consensus", - suite.chainA.LastHeader.ConsensusState(), - true, - }, - { - "nil", - nil, - false, - }, - } - - testCasesAny := []caseAny{} - - for _, tc := range testCases { - clientAny, err := types.PackConsensusState(tc.consensusState) - if tc.expPass { - suite.Require().NoError(err, tc.name) - } else { - suite.Require().Error(err, tc.name) - } - testCasesAny = append(testCasesAny, caseAny{tc.name, clientAny, tc.expPass}) - } - - for i, tc := range testCasesAny { - cs, err := types.UnpackConsensusState(tc.any) - if tc.expPass { - suite.Require().NoError(err, tc.name) - suite.Require().Equal(testCases[i].consensusState, cs, tc.name) - } else { - suite.Require().Error(err, tc.name) - } - } -} - -func (suite *TypesTestSuite) TestPackHeader() { - testCases := []struct { - name string - header exported.Header - expPass bool - }{ - { - "solo machine header", - ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "solomachine", "", 2).CreateHeader(), - true, - }, - { - "tendermint header", - suite.chainA.LastHeader, - true, - }, - { - "nil", - nil, - false, - }, - } - - testCasesAny := []caseAny{} - - for _, tc := range testCases { - clientAny, err := types.PackHeader(tc.header) - if tc.expPass { - suite.Require().NoError(err, tc.name) - } else { - suite.Require().Error(err, tc.name) - } - - testCasesAny = append(testCasesAny, caseAny{tc.name, clientAny, tc.expPass}) - } - - for i, tc := range testCasesAny { - cs, err := types.UnpackHeader(tc.any) - if tc.expPass { - suite.Require().NoError(err, tc.name) - suite.Require().Equal(testCases[i].header, cs, tc.name) - } else { - suite.Require().Error(err, tc.name) - } - } -} - -func (suite *TypesTestSuite) TestPackMisbehaviour() { - testCases := []struct { - name string - misbehaviour exported.Misbehaviour - expPass bool - }{ - { - "solo machine misbehaviour", - ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "solomachine", "", 2).CreateMisbehaviour(), - true, - }, - { - "tendermint misbehaviour", - ibctmtypes.NewMisbehaviour("tendermint", suite.chainA.LastHeader, suite.chainA.LastHeader), - true, - }, - { - "nil", - nil, - false, - }, - } - - testCasesAny := []caseAny{} - - for _, tc := range testCases { - clientAny, err := types.PackMisbehaviour(tc.misbehaviour) - if tc.expPass { - suite.Require().NoError(err, tc.name) - } else { - suite.Require().Error(err, tc.name) - } - - testCasesAny = append(testCasesAny, caseAny{tc.name, clientAny, tc.expPass}) - } - - for i, tc := range testCasesAny { - cs, err := types.UnpackMisbehaviour(tc.any) - if tc.expPass { - suite.Require().NoError(err, tc.name) - suite.Require().Equal(testCases[i].misbehaviour, cs, tc.name) - } else { - suite.Require().Error(err, tc.name) - } - } -} diff --git a/x/ibc/core/02-client/types/encoding.go b/x/ibc/core/02-client/types/encoding.go deleted file mode 100644 index 8621484563c4..000000000000 --- a/x/ibc/core/02-client/types/encoding.go +++ /dev/null @@ -1,113 +0,0 @@ -package types - -import ( - "fmt" - - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -// MustUnmarshalClientState attempts to decode and return an ClientState object from -// raw encoded bytes. It panics on error. -func MustUnmarshalClientState(cdc codec.BinaryMarshaler, bz []byte) exported.ClientState { - clientState, err := UnmarshalClientState(cdc, bz) - if err != nil { - panic(fmt.Errorf("failed to decode client state: %w", err)) - } - - return clientState -} - -// MustMarshalClientState attempts to encode an ClientState object and returns the -// raw encoded bytes. It panics on error. -func MustMarshalClientState(cdc codec.BinaryMarshaler, clientState exported.ClientState) []byte { - bz, err := MarshalClientState(cdc, clientState) - if err != nil { - panic(fmt.Errorf("failed to encode client state: %w", err)) - } - - return bz -} - -// MarshalClientState protobuf serializes an ClientState interface -func MarshalClientState(cdc codec.BinaryMarshaler, clientStateI exported.ClientState) ([]byte, error) { - return cdc.MarshalInterface(clientStateI) -} - -// UnmarshalClientState returns an ClientState interface from raw encoded clientState -// bytes of a Proto-based ClientState type. An error is returned upon decoding -// failure. -func UnmarshalClientState(cdc codec.BinaryMarshaler, bz []byte) (exported.ClientState, error) { - var clientState exported.ClientState - if err := cdc.UnmarshalInterface(bz, &clientState); err != nil { - return nil, err - } - - return clientState, nil -} - -// MustUnmarshalConsensusState attempts to decode and return an ConsensusState object from -// raw encoded bytes. It panics on error. -func MustUnmarshalConsensusState(cdc codec.BinaryMarshaler, bz []byte) exported.ConsensusState { - consensusState, err := UnmarshalConsensusState(cdc, bz) - if err != nil { - panic(fmt.Errorf("failed to decode consensus state: %w", err)) - } - - return consensusState -} - -// MustMarshalConsensusState attempts to encode a ConsensusState object and returns the -// raw encoded bytes. It panics on error. -func MustMarshalConsensusState(cdc codec.BinaryMarshaler, consensusState exported.ConsensusState) []byte { - bz, err := MarshalConsensusState(cdc, consensusState) - if err != nil { - panic(fmt.Errorf("failed to encode consensus state: %w", err)) - } - - return bz -} - -// MarshalConsensusState protobuf serializes a ConsensusState interface -func MarshalConsensusState(cdc codec.BinaryMarshaler, cs exported.ConsensusState) ([]byte, error) { - return cdc.MarshalInterface(cs) -} - -// UnmarshalConsensusState returns a ConsensusState interface from raw encoded consensus state -// bytes of a Proto-based ConsensusState type. An error is returned upon decoding -// failure. -func UnmarshalConsensusState(cdc codec.BinaryMarshaler, bz []byte) (exported.ConsensusState, error) { - var consensusState exported.ConsensusState - if err := cdc.UnmarshalInterface(bz, &consensusState); err != nil { - return nil, err - } - - return consensusState, nil -} - -// MarshalHeader protobuf serializes a Header interface -func MarshalHeader(cdc codec.BinaryMarshaler, h exported.Header) ([]byte, error) { - return cdc.MarshalInterface(h) -} - -// MustMarshalHeader attempts to encode a Header object and returns the -// raw encoded bytes. It panics on error. -func MustMarshalHeader(cdc codec.BinaryMarshaler, header exported.Header) []byte { - bz, err := MarshalHeader(cdc, header) - if err != nil { - panic(fmt.Errorf("failed to encode header: %w", err)) - } - - return bz -} - -// UnmarshalHeader returns a Header interface from raw proto encoded header bytes. -// An error is returned upon decoding failure. -func UnmarshalHeader(cdc codec.BinaryMarshaler, bz []byte) (exported.Header, error) { - var header exported.Header - if err := cdc.UnmarshalInterface(bz, &header); err != nil { - return nil, err - } - - return header, nil -} diff --git a/x/ibc/core/02-client/types/encoding_test.go b/x/ibc/core/02-client/types/encoding_test.go deleted file mode 100644 index 89953bc9f1d4..000000000000 --- a/x/ibc/core/02-client/types/encoding_test.go +++ /dev/null @@ -1,30 +0,0 @@ -package types_test - -import ( - "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" -) - -func (suite *TypesTestSuite) TestMarshalHeader() { - - cdc := suite.chainA.App.AppCodec() - h := &ibctmtypes.Header{ - TrustedHeight: types.NewHeight(4, 100), - } - - // marshal header - bz, err := types.MarshalHeader(cdc, h) - suite.Require().NoError(err) - - // unmarshal header - newHeader, err := types.UnmarshalHeader(cdc, bz) - suite.Require().NoError(err) - - suite.Require().Equal(h, newHeader) - - // use invalid bytes - invalidHeader, err := types.UnmarshalHeader(cdc, []byte("invalid bytes")) - suite.Require().Error(err) - suite.Require().Nil(invalidHeader) - -} diff --git a/x/ibc/core/02-client/types/errors.go b/x/ibc/core/02-client/types/errors.go deleted file mode 100644 index 8a956f868730..000000000000 --- a/x/ibc/core/02-client/types/errors.go +++ /dev/null @@ -1,36 +0,0 @@ -package types - -import ( - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" -) - -// IBC client sentinel errors -var ( - ErrClientExists = sdkerrors.Register(SubModuleName, 2, "light client already exists") - ErrInvalidClient = sdkerrors.Register(SubModuleName, 3, "light client is invalid") - ErrClientNotFound = sdkerrors.Register(SubModuleName, 4, "light client not found") - ErrClientFrozen = sdkerrors.Register(SubModuleName, 5, "light client is frozen due to misbehaviour") - ErrInvalidClientMetadata = sdkerrors.Register(SubModuleName, 6, "invalid client metadata") - ErrConsensusStateNotFound = sdkerrors.Register(SubModuleName, 7, "consensus state not found") - ErrInvalidConsensus = sdkerrors.Register(SubModuleName, 8, "invalid consensus state") - ErrClientTypeNotFound = sdkerrors.Register(SubModuleName, 9, "client type not found") - ErrInvalidClientType = sdkerrors.Register(SubModuleName, 10, "invalid client type") - ErrRootNotFound = sdkerrors.Register(SubModuleName, 11, "commitment root not found") - ErrInvalidHeader = sdkerrors.Register(SubModuleName, 12, "invalid client header") - ErrInvalidMisbehaviour = sdkerrors.Register(SubModuleName, 13, "invalid light client misbehaviour") - ErrFailedClientStateVerification = sdkerrors.Register(SubModuleName, 14, "client state verification failed") - ErrFailedClientConsensusStateVerification = sdkerrors.Register(SubModuleName, 15, "client consensus state verification failed") - ErrFailedConnectionStateVerification = sdkerrors.Register(SubModuleName, 16, "connection state verification failed") - ErrFailedChannelStateVerification = sdkerrors.Register(SubModuleName, 17, "channel state verification failed") - ErrFailedPacketCommitmentVerification = sdkerrors.Register(SubModuleName, 18, "packet commitment verification failed") - ErrFailedPacketAckVerification = sdkerrors.Register(SubModuleName, 19, "packet acknowledgement verification failed") - ErrFailedPacketReceiptVerification = sdkerrors.Register(SubModuleName, 20, "packet receipt verification failed") - ErrFailedNextSeqRecvVerification = sdkerrors.Register(SubModuleName, 21, "next sequence receive verification failed") - ErrSelfConsensusStateNotFound = sdkerrors.Register(SubModuleName, 22, "self consensus state not found") - 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") - ErrInvalidUpgradeProposal = sdkerrors.Register(SubModuleName, 28, "invalid upgrade proposal") -) diff --git a/x/ibc/core/02-client/types/events.go b/x/ibc/core/02-client/types/events.go deleted file mode 100644 index f8812e6515b5..000000000000 --- a/x/ibc/core/02-client/types/events.go +++ /dev/null @@ -1,27 +0,0 @@ -package types - -import ( - "fmt" - - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" -) - -// IBC client events -const ( - AttributeKeyClientID = "client_id" - AttributeKeySubjectClientID = "subject_client_id" - AttributeKeyClientType = "client_type" - AttributeKeyConsensusHeight = "consensus_height" - AttributeKeyHeader = "header" -) - -// IBC client events vars -var ( - EventTypeCreateClient = "create_client" - EventTypeUpdateClient = "update_client" - EventTypeUpgradeClient = "upgrade_client" - EventTypeSubmitMisbehaviour = "client_misbehaviour" - EventTypeUpdateClientProposal = "update_client_proposal" - - AttributeValueCategory = fmt.Sprintf("%s_%s", host.ModuleName, SubModuleName) -) diff --git a/x/ibc/core/02-client/types/expected_keepers.go b/x/ibc/core/02-client/types/expected_keepers.go deleted file mode 100644 index ad007fb8011c..000000000000 --- a/x/ibc/core/02-client/types/expected_keepers.go +++ /dev/null @@ -1,25 +0,0 @@ -package types - -import ( - "time" - - sdk "github.com/cosmos/cosmos-sdk/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" -) - -// StakingKeeper expected staking keeper -type StakingKeeper interface { - GetHistoricalInfo(ctx sdk.Context, height int64) (stakingtypes.HistoricalInfo, bool) - UnbondingTime(ctx sdk.Context) time.Duration -} - -// UpgradeKeeper expected upgrade keeper -type UpgradeKeeper interface { - ClearIBCState(ctx sdk.Context, lastHeight int64) - GetUpgradePlan(ctx sdk.Context) (plan upgradetypes.Plan, havePlan bool) - GetUpgradedClient(ctx sdk.Context, height int64) ([]byte, bool) - SetUpgradedConsensusState(ctx sdk.Context, planHeight int64, bz []byte) error - SetUpgradedClient(ctx sdk.Context, planHeight int64, bz []byte) error - ScheduleUpgrade(ctx sdk.Context, plan upgradetypes.Plan) error -} diff --git a/x/ibc/core/02-client/types/genesis.go b/x/ibc/core/02-client/types/genesis.go deleted file mode 100644 index 3f197208e33a..000000000000 --- a/x/ibc/core/02-client/types/genesis.go +++ /dev/null @@ -1,250 +0,0 @@ -package types - -import ( - "fmt" - "sort" - - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -var ( - _ codectypes.UnpackInterfacesMessage = IdentifiedClientState{} - _ codectypes.UnpackInterfacesMessage = ClientsConsensusStates{} - _ codectypes.UnpackInterfacesMessage = ClientConsensusStates{} - _ codectypes.UnpackInterfacesMessage = GenesisState{} -) - -var ( - _ sort.Interface = ClientsConsensusStates{} - _ exported.GenesisMetadata = GenesisMetadata{} -) - -// ClientsConsensusStates defines a slice of ClientConsensusStates that supports the sort interface -type ClientsConsensusStates []ClientConsensusStates - -// Len implements sort.Interface -func (ccs ClientsConsensusStates) Len() int { return len(ccs) } - -// Less implements sort.Interface -func (ccs ClientsConsensusStates) Less(i, j int) bool { return ccs[i].ClientId < ccs[j].ClientId } - -// Swap implements sort.Interface -func (ccs ClientsConsensusStates) Swap(i, j int) { ccs[i], ccs[j] = ccs[j], ccs[i] } - -// Sort is a helper function to sort the set of ClientsConsensusStates in place -func (ccs ClientsConsensusStates) Sort() ClientsConsensusStates { - sort.Sort(ccs) - return ccs -} - -// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces -func (ccs ClientsConsensusStates) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { - for _, clientConsensus := range ccs { - if err := clientConsensus.UnpackInterfaces(unpacker); err != nil { - return err - } - } - return nil -} - -// NewClientConsensusStates creates a new ClientConsensusStates instance. -func NewClientConsensusStates(clientID string, consensusStates []ConsensusStateWithHeight) ClientConsensusStates { - return ClientConsensusStates{ - ClientId: clientID, - ConsensusStates: consensusStates, - } -} - -// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces -func (ccs ClientConsensusStates) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { - for _, consStateWithHeight := range ccs.ConsensusStates { - if err := consStateWithHeight.UnpackInterfaces(unpacker); err != nil { - return err - } - } - return nil -} - -// NewGenesisState creates a GenesisState instance. -func NewGenesisState( - clients []IdentifiedClientState, clientsConsensus ClientsConsensusStates, clientsMetadata []IdentifiedGenesisMetadata, - params Params, createLocalhost bool, nextClientSequence uint64, -) GenesisState { - return GenesisState{ - Clients: clients, - ClientsConsensus: clientsConsensus, - ClientsMetadata: clientsMetadata, - Params: params, - CreateLocalhost: createLocalhost, - NextClientSequence: nextClientSequence, - } -} - -// DefaultGenesisState returns the ibc client submodule's default genesis state. -func DefaultGenesisState() GenesisState { - return GenesisState{ - Clients: []IdentifiedClientState{}, - ClientsConsensus: ClientsConsensusStates{}, - Params: DefaultParams(), - CreateLocalhost: false, - NextClientSequence: 0, - } -} - -// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces -func (gs GenesisState) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { - for _, client := range gs.Clients { - if err := client.UnpackInterfaces(unpacker); err != nil { - return err - } - } - - return gs.ClientsConsensus.UnpackInterfaces(unpacker) -} - -// Validate performs basic genesis state validation returning an error upon any -// failure. -func (gs GenesisState) Validate() error { - // keep track of the max sequence to ensure it is less than - // the next sequence used in creating client identifers. - var maxSequence uint64 = 0 - - if err := gs.Params.Validate(); err != nil { - return err - } - - validClients := make(map[string]string) - - for i, client := range gs.Clients { - if err := host.ClientIdentifierValidator(client.ClientId); err != nil { - return fmt.Errorf("invalid client consensus state identifier %s index %d: %w", client.ClientId, i, err) - } - - clientState, ok := client.ClientState.GetCachedValue().(exported.ClientState) - if !ok { - return fmt.Errorf("invalid client state with ID %s", client.ClientId) - } - - if !gs.Params.IsAllowedClient(clientState.ClientType()) { - return fmt.Errorf("client type %s not allowed by genesis params", clientState.ClientType()) - } - if err := clientState.Validate(); err != nil { - return fmt.Errorf("invalid client %v index %d: %w", client, i, err) - } - - clientType, sequence, err := ParseClientIdentifier(client.ClientId) - if err != nil { - return err - } - - if clientType != clientState.ClientType() { - return fmt.Errorf("client state type %s does not equal client type in client identifier %s", clientState.ClientType(), clientType) - } - - if err := ValidateClientType(clientType); err != nil { - return err - } - - if sequence > maxSequence { - maxSequence = sequence - } - - // add client id to validClients map - validClients[client.ClientId] = clientState.ClientType() - } - - for _, cc := range gs.ClientsConsensus { - // check that consensus state is for a client in the genesis clients list - clientType, ok := validClients[cc.ClientId] - if !ok { - return fmt.Errorf("consensus state in genesis has a client id %s that does not map to a genesis client", cc.ClientId) - } - - for i, consensusState := range cc.ConsensusStates { - if consensusState.Height.IsZero() { - return fmt.Errorf("consensus state height cannot be zero") - } - - cs, ok := consensusState.ConsensusState.GetCachedValue().(exported.ConsensusState) - if !ok { - return fmt.Errorf("invalid consensus state with client ID %s at height %s", cc.ClientId, consensusState.Height) - } - - if err := cs.ValidateBasic(); err != nil { - return fmt.Errorf("invalid client consensus state %v clientID %s index %d: %w", cs, cc.ClientId, i, err) - } - - // ensure consensus state type matches client state type - if clientType != cs.ClientType() { - return fmt.Errorf("consensus state client type %s does not equal client state client type %s", cs.ClientType(), clientType) - } - - } - } - - for _, clientMetadata := range gs.ClientsMetadata { - // check that metadata is for a client in the genesis clients list - _, ok := validClients[clientMetadata.ClientId] - if !ok { - return fmt.Errorf("metadata in genesis has a client id %s that does not map to a genesis client", clientMetadata.ClientId) - } - - for i, gm := range clientMetadata.ClientMetadata { - if err := gm.Validate(); err != nil { - return fmt.Errorf("invalid client metadata %v clientID %s index %d: %w", gm, clientMetadata.ClientId, i, err) - } - - } - - } - - if gs.CreateLocalhost && !gs.Params.IsAllowedClient(exported.Localhost) { - return fmt.Errorf("localhost client is not registered on the allowlist") - } - - if maxSequence != 0 && maxSequence >= gs.NextClientSequence { - return fmt.Errorf("next client identifier sequence %d must be greater than the maximum sequence used in the provided client identifiers %d", gs.NextClientSequence, maxSequence) - } - - return nil -} - -// NewGenesisMetadata is a constructor for GenesisMetadata -func NewGenesisMetadata(key, val []byte) GenesisMetadata { - return GenesisMetadata{ - Key: key, - Value: val, - } -} - -// GetKey returns the key of metadata. Implements exported.GenesisMetadata interface. -func (gm GenesisMetadata) GetKey() []byte { - return gm.Key -} - -// GetValue returns the value of metadata. Implements exported.GenesisMetadata interface. -func (gm GenesisMetadata) GetValue() []byte { - return gm.Value -} - -// Validate ensures key and value of metadata are not empty -func (gm GenesisMetadata) Validate() error { - if len(gm.Key) == 0 { - return fmt.Errorf("genesis metadata key cannot be empty") - } - if len(gm.Value) == 0 { - return fmt.Errorf("genesis metadata value cannot be empty") - } - return nil -} - -// NewIdentifiedGenesisMetadata takes in a client ID and list of genesis metadata for that client -// and constructs a new IdentifiedGenesisMetadata. -func NewIdentifiedGenesisMetadata(clientID string, gms []GenesisMetadata) IdentifiedGenesisMetadata { - return IdentifiedGenesisMetadata{ - ClientId: clientID, - ClientMetadata: gms, - } -} diff --git a/x/ibc/core/02-client/types/genesis.pb.go b/x/ibc/core/02-client/types/genesis.pb.go deleted file mode 100644 index a8253c343db0..000000000000 --- a/x/ibc/core/02-client/types/genesis.pb.go +++ /dev/null @@ -1,1057 +0,0 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: ibc/core/client/v1/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 defines the ibc client submodule's genesis state. -type GenesisState struct { - // client states with their corresponding identifiers - Clients IdentifiedClientStates `protobuf:"bytes,1,rep,name=clients,proto3,castrepeated=IdentifiedClientStates" json:"clients"` - // consensus states from each client - ClientsConsensus ClientsConsensusStates `protobuf:"bytes,2,rep,name=clients_consensus,json=clientsConsensus,proto3,castrepeated=ClientsConsensusStates" json:"clients_consensus" yaml:"clients_consensus"` - // metadata from each client - ClientsMetadata []IdentifiedGenesisMetadata `protobuf:"bytes,3,rep,name=clients_metadata,json=clientsMetadata,proto3" json:"clients_metadata" yaml:"clients_metadata"` - Params Params `protobuf:"bytes,4,opt,name=params,proto3" json:"params"` - // create localhost on initialization - CreateLocalhost bool `protobuf:"varint,5,opt,name=create_localhost,json=createLocalhost,proto3" json:"create_localhost,omitempty" yaml:"create_localhost"` - // the sequence for the next generated client identifier - NextClientSequence uint64 `protobuf:"varint,6,opt,name=next_client_sequence,json=nextClientSequence,proto3" json:"next_client_sequence,omitempty" yaml:"next_client_sequence"` -} - -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_bcd0c0f1f2e6a91a, []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) GetClients() IdentifiedClientStates { - if m != nil { - return m.Clients - } - return nil -} - -func (m *GenesisState) GetClientsConsensus() ClientsConsensusStates { - if m != nil { - return m.ClientsConsensus - } - return nil -} - -func (m *GenesisState) GetClientsMetadata() []IdentifiedGenesisMetadata { - if m != nil { - return m.ClientsMetadata - } - return nil -} - -func (m *GenesisState) GetParams() Params { - if m != nil { - return m.Params - } - return Params{} -} - -func (m *GenesisState) GetCreateLocalhost() bool { - if m != nil { - return m.CreateLocalhost - } - return false -} - -func (m *GenesisState) GetNextClientSequence() uint64 { - if m != nil { - return m.NextClientSequence - } - return 0 -} - -// GenesisMetadata defines the genesis type for metadata that clients may return -// with ExportMetadata -type GenesisMetadata struct { - // store key of metadata without clientID-prefix - Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` - // metadata value - Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` -} - -func (m *GenesisMetadata) Reset() { *m = GenesisMetadata{} } -func (m *GenesisMetadata) String() string { return proto.CompactTextString(m) } -func (*GenesisMetadata) ProtoMessage() {} -func (*GenesisMetadata) Descriptor() ([]byte, []int) { - return fileDescriptor_bcd0c0f1f2e6a91a, []int{1} -} -func (m *GenesisMetadata) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *GenesisMetadata) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_GenesisMetadata.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 *GenesisMetadata) XXX_Merge(src proto.Message) { - xxx_messageInfo_GenesisMetadata.Merge(m, src) -} -func (m *GenesisMetadata) XXX_Size() int { - return m.Size() -} -func (m *GenesisMetadata) XXX_DiscardUnknown() { - xxx_messageInfo_GenesisMetadata.DiscardUnknown(m) -} - -var xxx_messageInfo_GenesisMetadata proto.InternalMessageInfo - -// IdentifiedGenesisMetadata has the client metadata with the corresponding client id. -type IdentifiedGenesisMetadata struct { - ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty" yaml:"client_id"` - ClientMetadata []GenesisMetadata `protobuf:"bytes,2,rep,name=client_metadata,json=clientMetadata,proto3" json:"client_metadata" yaml:"client_metadata"` -} - -func (m *IdentifiedGenesisMetadata) Reset() { *m = IdentifiedGenesisMetadata{} } -func (m *IdentifiedGenesisMetadata) String() string { return proto.CompactTextString(m) } -func (*IdentifiedGenesisMetadata) ProtoMessage() {} -func (*IdentifiedGenesisMetadata) Descriptor() ([]byte, []int) { - return fileDescriptor_bcd0c0f1f2e6a91a, []int{2} -} -func (m *IdentifiedGenesisMetadata) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *IdentifiedGenesisMetadata) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_IdentifiedGenesisMetadata.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 *IdentifiedGenesisMetadata) XXX_Merge(src proto.Message) { - xxx_messageInfo_IdentifiedGenesisMetadata.Merge(m, src) -} -func (m *IdentifiedGenesisMetadata) XXX_Size() int { - return m.Size() -} -func (m *IdentifiedGenesisMetadata) XXX_DiscardUnknown() { - xxx_messageInfo_IdentifiedGenesisMetadata.DiscardUnknown(m) -} - -var xxx_messageInfo_IdentifiedGenesisMetadata proto.InternalMessageInfo - -func (m *IdentifiedGenesisMetadata) GetClientId() string { - if m != nil { - return m.ClientId - } - return "" -} - -func (m *IdentifiedGenesisMetadata) GetClientMetadata() []GenesisMetadata { - if m != nil { - return m.ClientMetadata - } - return nil -} - -func init() { - proto.RegisterType((*GenesisState)(nil), "ibc.core.client.v1.GenesisState") - proto.RegisterType((*GenesisMetadata)(nil), "ibc.core.client.v1.GenesisMetadata") - proto.RegisterType((*IdentifiedGenesisMetadata)(nil), "ibc.core.client.v1.IdentifiedGenesisMetadata") -} - -func init() { proto.RegisterFile("ibc/core/client/v1/genesis.proto", fileDescriptor_bcd0c0f1f2e6a91a) } - -var fileDescriptor_bcd0c0f1f2e6a91a = []byte{ - // 535 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x53, 0x4d, 0x6e, 0xd3, 0x40, - 0x14, 0xce, 0x34, 0x69, 0x68, 0xa7, 0x15, 0x0d, 0xa3, 0xa8, 0x98, 0x54, 0xb2, 0x2d, 0xb3, 0x09, - 0x8b, 0xd8, 0x24, 0x2c, 0x40, 0xd9, 0x20, 0xb9, 0x12, 0xa8, 0x12, 0x48, 0xd4, 0xec, 0xd8, 0x58, - 0x93, 0xf1, 0x90, 0x5a, 0x75, 0x3c, 0x21, 0x33, 0x89, 0x9a, 0x1b, 0xb0, 0x44, 0x9c, 0x80, 0x35, - 0x67, 0xe0, 0x00, 0x5d, 0x76, 0xd9, 0x55, 0x40, 0xc9, 0x0d, 0x72, 0x02, 0xe4, 0x99, 0x71, 0x7f, - 0x5c, 0xb7, 0xab, 0xbc, 0x7c, 0xf3, 0x7d, 0xdf, 0x7b, 0xfa, 0x9e, 0x1f, 0xb4, 0xe3, 0x01, 0xf1, - 0x08, 0x9b, 0x50, 0x8f, 0x24, 0x31, 0x4d, 0x85, 0x37, 0xeb, 0x7a, 0x43, 0x9a, 0x52, 0x1e, 0x73, - 0x77, 0x3c, 0x61, 0x82, 0x21, 0x14, 0x0f, 0x88, 0x9b, 0x31, 0x5c, 0xc5, 0x70, 0x67, 0xdd, 0x96, - 0x55, 0xa2, 0xd2, 0xaf, 0x52, 0xd4, 0x6a, 0x0e, 0xd9, 0x90, 0xc9, 0xd2, 0xcb, 0x2a, 0x85, 0x3a, - 0x97, 0x35, 0xb8, 0xfb, 0x5e, 0x99, 0x7f, 0x16, 0x58, 0x50, 0x44, 0xe0, 0x23, 0x25, 0xe3, 0x06, - 0xb0, 0xab, 0xed, 0x9d, 0xde, 0x0b, 0xf7, 0x6e, 0x37, 0xf7, 0x28, 0xa2, 0xa9, 0x88, 0xbf, 0xc6, - 0x34, 0x3a, 0x94, 0x98, 0xd4, 0xfa, 0xe6, 0xf9, 0xc2, 0xaa, 0xfc, 0xfe, 0x6b, 0xed, 0x97, 0x3e, - 0xf3, 0x20, 0x77, 0x46, 0x3f, 0x01, 0x7c, 0xa2, 0xeb, 0x90, 0xb0, 0x94, 0xd3, 0x94, 0x4f, 0xb9, - 0xb1, 0x71, 0x7f, 0x3f, 0x65, 0x73, 0x98, 0x53, 0x95, 0x9f, 0xdf, 0xcf, 0xfa, 0xad, 0x17, 0x96, - 0x31, 0xc7, 0xa3, 0xa4, 0xef, 0xdc, 0x71, 0x74, 0xb2, 0x59, 0x94, 0x94, 0x17, 0xb4, 0x41, 0x83, - 0x14, 0x70, 0x34, 0x87, 0x39, 0x16, 0x8e, 0xa8, 0xc0, 0x11, 0x16, 0xd8, 0xa8, 0xca, 0x91, 0x3a, - 0x0f, 0x47, 0xa0, 0xf3, 0xfb, 0xa8, 0x45, 0xbe, 0xa5, 0xc7, 0x7a, 0x7a, 0x7b, 0xac, 0xdc, 0xd4, - 0x09, 0xf6, 0x34, 0x94, 0x2b, 0xd0, 0x1b, 0x58, 0x1f, 0xe3, 0x09, 0x1e, 0x71, 0xa3, 0x66, 0x83, - 0xf6, 0x4e, 0xaf, 0x55, 0xd6, 0xf0, 0x93, 0x64, 0xf8, 0xb5, 0xcc, 0x3d, 0xd0, 0x7c, 0xf4, 0x0e, - 0x36, 0xc8, 0x84, 0x62, 0x41, 0xc3, 0x84, 0x11, 0x9c, 0x9c, 0x30, 0x2e, 0x8c, 0x4d, 0x1b, 0xb4, - 0xb7, 0xfc, 0x83, 0x1b, 0x13, 0x14, 0x18, 0xd9, 0x04, 0x12, 0xfa, 0x90, 0x23, 0xe8, 0x18, 0x36, - 0x53, 0x7a, 0x26, 0x42, 0xd5, 0x2e, 0xe4, 0xf4, 0xdb, 0x94, 0xa6, 0x84, 0x1a, 0x75, 0x1b, 0xb4, - 0x6b, 0xbe, 0xb5, 0x5e, 0x58, 0x07, 0xca, 0xab, 0x8c, 0xe5, 0x04, 0x28, 0x83, 0xf5, 0xae, 0x73, - 0xf0, 0x2d, 0xdc, 0x2b, 0x24, 0x83, 0x1a, 0xb0, 0x7a, 0x4a, 0xe7, 0x06, 0xb0, 0x41, 0x7b, 0x37, - 0xc8, 0x4a, 0xd4, 0x84, 0x9b, 0x33, 0x9c, 0x4c, 0xa9, 0xb1, 0x21, 0x31, 0xf5, 0xa7, 0x5f, 0xfb, - 0xfe, 0xcb, 0xaa, 0x38, 0x7f, 0x00, 0x7c, 0x76, 0x6f, 0xca, 0xa8, 0x0b, 0xb7, 0xf5, 0x18, 0x71, - 0x24, 0x1d, 0xb7, 0xfd, 0xe6, 0x7a, 0x61, 0x35, 0x6e, 0x86, 0x1e, 0xc6, 0x91, 0x13, 0x6c, 0xa9, - 0xfa, 0x28, 0x42, 0x09, 0xd4, 0xc9, 0x5f, 0x2f, 0x58, 0x7d, 0x73, 0xcf, 0xcb, 0xf2, 0x2e, 0xae, - 0xd5, 0xd4, 0x6b, 0xdd, 0xbf, 0xd5, 0xe1, 0x7a, 0xab, 0x8f, 0x15, 0x72, 0xc5, 0x3f, 0x3e, 0x5f, - 0x9a, 0xe0, 0x62, 0x69, 0x82, 0x7f, 0x4b, 0x13, 0xfc, 0x58, 0x99, 0x95, 0x8b, 0x95, 0x59, 0xb9, - 0x5c, 0x99, 0x95, 0x2f, 0xaf, 0x87, 0xb1, 0x38, 0x99, 0x0e, 0x5c, 0xc2, 0x46, 0x1e, 0x61, 0x7c, - 0xc4, 0xb8, 0xfe, 0xe9, 0xf0, 0xe8, 0xd4, 0x3b, 0xf3, 0xae, 0x4e, 0xf9, 0x65, 0xaf, 0xa3, 0xaf, - 0x59, 0xcc, 0xc7, 0x94, 0x0f, 0xea, 0xf2, 0x68, 0x5f, 0xfd, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x61, - 0x6f, 0x94, 0xed, 0x23, 0x04, 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 m.NextClientSequence != 0 { - i = encodeVarintGenesis(dAtA, i, uint64(m.NextClientSequence)) - i-- - dAtA[i] = 0x30 - } - if m.CreateLocalhost { - i-- - if m.CreateLocalhost { - dAtA[i] = 1 - } else { - dAtA[i] = 0 - } - i-- - dAtA[i] = 0x28 - } - { - size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintGenesis(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x22 - if len(m.ClientsMetadata) > 0 { - for iNdEx := len(m.ClientsMetadata) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.ClientsMetadata[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintGenesis(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - } - } - if len(m.ClientsConsensus) > 0 { - for iNdEx := len(m.ClientsConsensus) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.ClientsConsensus[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintGenesis(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - } - } - if len(m.Clients) > 0 { - for iNdEx := len(m.Clients) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.Clients[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 *GenesisMetadata) 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 *GenesisMetadata) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *GenesisMetadata) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Value) > 0 { - i -= len(m.Value) - copy(dAtA[i:], m.Value) - i = encodeVarintGenesis(dAtA, i, uint64(len(m.Value))) - i-- - dAtA[i] = 0x12 - } - if len(m.Key) > 0 { - i -= len(m.Key) - copy(dAtA[i:], m.Key) - i = encodeVarintGenesis(dAtA, i, uint64(len(m.Key))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *IdentifiedGenesisMetadata) 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 *IdentifiedGenesisMetadata) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *IdentifiedGenesisMetadata) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.ClientMetadata) > 0 { - for iNdEx := len(m.ClientMetadata) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.ClientMetadata[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintGenesis(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - } - } - if len(m.ClientId) > 0 { - i -= len(m.ClientId) - copy(dAtA[i:], m.ClientId) - i = encodeVarintGenesis(dAtA, i, uint64(len(m.ClientId))) - 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.Clients) > 0 { - for _, e := range m.Clients { - l = e.Size() - n += 1 + l + sovGenesis(uint64(l)) - } - } - if len(m.ClientsConsensus) > 0 { - for _, e := range m.ClientsConsensus { - l = e.Size() - n += 1 + l + sovGenesis(uint64(l)) - } - } - if len(m.ClientsMetadata) > 0 { - for _, e := range m.ClientsMetadata { - l = e.Size() - n += 1 + l + sovGenesis(uint64(l)) - } - } - l = m.Params.Size() - n += 1 + l + sovGenesis(uint64(l)) - if m.CreateLocalhost { - n += 2 - } - if m.NextClientSequence != 0 { - n += 1 + sovGenesis(uint64(m.NextClientSequence)) - } - return n -} - -func (m *GenesisMetadata) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Key) - if l > 0 { - n += 1 + l + sovGenesis(uint64(l)) - } - l = len(m.Value) - if l > 0 { - n += 1 + l + sovGenesis(uint64(l)) - } - return n -} - -func (m *IdentifiedGenesisMetadata) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.ClientId) - if l > 0 { - n += 1 + l + sovGenesis(uint64(l)) - } - if len(m.ClientMetadata) > 0 { - for _, e := range m.ClientMetadata { - 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 Clients", 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.Clients = append(m.Clients, IdentifiedClientState{}) - if err := m.Clients[len(m.Clients)-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 ClientsConsensus", 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.ClientsConsensus = append(m.ClientsConsensus, ClientConsensusStates{}) - if err := m.ClientsConsensus[len(m.ClientsConsensus)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ClientsMetadata", 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.ClientsMetadata = append(m.ClientsMetadata, IdentifiedGenesisMetadata{}) - if err := m.ClientsMetadata[len(m.ClientsMetadata)-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 Params", 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 := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 5: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field CreateLocalhost", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenesis - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.CreateLocalhost = bool(v != 0) - case 6: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field NextClientSequence", wireType) - } - m.NextClientSequence = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenesis - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.NextClientSequence |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - 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 *GenesisMetadata) 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: GenesisMetadata: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: GenesisMetadata: 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 ErrIntOverflowGenesis - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthGenesis - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthGenesis - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Key = append(m.Key[:0], dAtA[iNdEx:postIndex]...) - if m.Key == nil { - m.Key = []byte{} - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenesis - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthGenesis - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthGenesis - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Value = append(m.Value[:0], dAtA[iNdEx:postIndex]...) - if m.Value == nil { - m.Value = []byte{} - } - 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 *IdentifiedGenesisMetadata) 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: IdentifiedGenesisMetadata: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: IdentifiedGenesisMetadata: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ClientId", 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.ClientId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ClientMetadata", 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.ClientMetadata = append(m.ClientMetadata, GenesisMetadata{}) - if err := m.ClientMetadata[len(m.ClientMetadata)-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/ibc/core/02-client/types/genesis_test.go b/x/ibc/core/02-client/types/genesis_test.go deleted file mode 100644 index d57b8d1ba532..000000000000 --- a/x/ibc/core/02-client/types/genesis_test.go +++ /dev/null @@ -1,549 +0,0 @@ -package types_test - -import ( - "time" - - tmtypes "github.com/tendermint/tendermint/types" - - client "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client" - "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" - localhosttypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/09-localhost/types" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" - ibctestingmock "github.com/cosmos/cosmos-sdk/x/ibc/testing/mock" -) - -const ( - chainID = "chainID" - tmClientID0 = "07-tendermint-0" - tmClientID1 = "07-tendermint-1" - invalidClientID = "myclient-0" - clientID = tmClientID0 - - height = 10 -) - -var clientHeight = types.NewHeight(0, 10) - -func (suite *TypesTestSuite) TestMarshalGenesisState() { - cdc := suite.chainA.App.AppCodec() - clientA, _, _, _, _, _ := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.ORDERED) - suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - - genesis := client.ExportGenesis(suite.chainA.GetContext(), suite.chainA.App.IBCKeeper.ClientKeeper) - - bz, err := cdc.MarshalJSON(&genesis) - suite.Require().NoError(err) - suite.Require().NotNil(bz) - - var gs types.GenesisState - err = cdc.UnmarshalJSON(bz, &gs) - suite.Require().NoError(err) -} - -func (suite *TypesTestSuite) TestValidateGenesis() { - privVal := ibctestingmock.NewPV() - pubKey, err := privVal.GetPubKey() - suite.Require().NoError(err) - - now := time.Now().UTC() - - val := tmtypes.NewValidator(pubKey, 10) - valSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{val}) - - heightMinus1 := types.NewHeight(0, height-1) - header := suite.chainA.CreateTMClientHeader(chainID, int64(clientHeight.RevisionHeight), heightMinus1, now, valSet, valSet, []tmtypes.PrivValidator{privVal}) - - testCases := []struct { - name string - genState types.GenesisState - expPass bool - }{ - { - name: "default", - genState: types.DefaultGenesisState(), - expPass: true, - }, - { - name: "valid custom genesis", - genState: types.NewGenesisState( - []types.IdentifiedClientState{ - types.NewIdentifiedClientState( - tmClientID0, ibctmtypes.NewClientState(chainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), - ), - types.NewIdentifiedClientState( - exported.Localhost+"-1", localhosttypes.NewClientState("chainID", clientHeight), - ), - }, - []types.ClientConsensusStates{ - types.NewClientConsensusStates( - tmClientID0, - []types.ConsensusStateWithHeight{ - types.NewConsensusStateWithHeight( - header.GetHeight().(types.Height), - ibctmtypes.NewConsensusState( - header.GetTime(), commitmenttypes.NewMerkleRoot(header.Header.GetAppHash()), header.Header.NextValidatorsHash, - ), - ), - }, - ), - }, - []types.IdentifiedGenesisMetadata{ - types.NewIdentifiedGenesisMetadata( - clientID, - []types.GenesisMetadata{ - types.NewGenesisMetadata([]byte("key1"), []byte("val1")), - types.NewGenesisMetadata([]byte("key2"), []byte("val2")), - }, - ), - }, - types.NewParams(exported.Tendermint, exported.Localhost), - false, - 2, - ), - expPass: true, - }, - { - name: "invalid clientid", - genState: types.NewGenesisState( - []types.IdentifiedClientState{ - types.NewIdentifiedClientState( - invalidClientID, ibctmtypes.NewClientState(chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), - ), - types.NewIdentifiedClientState( - exported.Localhost, localhosttypes.NewClientState("chainID", clientHeight), - ), - }, - []types.ClientConsensusStates{ - types.NewClientConsensusStates( - invalidClientID, - []types.ConsensusStateWithHeight{ - types.NewConsensusStateWithHeight( - header.GetHeight().(types.Height), - ibctmtypes.NewConsensusState( - header.GetTime(), commitmenttypes.NewMerkleRoot(header.Header.GetAppHash()), header.Header.NextValidatorsHash, - ), - ), - }, - ), - }, - nil, - types.NewParams(exported.Tendermint), - false, - 0, - ), - expPass: false, - }, - { - name: "invalid client", - genState: types.NewGenesisState( - []types.IdentifiedClientState{ - types.NewIdentifiedClientState( - tmClientID0, ibctmtypes.NewClientState(chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), - ), - types.NewIdentifiedClientState(exported.Localhost, localhosttypes.NewClientState("chaindID", types.ZeroHeight())), - }, - nil, - nil, - types.NewParams(exported.Tendermint), - false, - 0, - ), - expPass: false, - }, - { - name: "consensus state client id does not match client id in genesis clients", - genState: types.NewGenesisState( - []types.IdentifiedClientState{ - types.NewIdentifiedClientState( - tmClientID0, ibctmtypes.NewClientState(chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), - ), - types.NewIdentifiedClientState( - exported.Localhost, localhosttypes.NewClientState("chaindID", clientHeight), - ), - }, - []types.ClientConsensusStates{ - types.NewClientConsensusStates( - tmClientID1, - []types.ConsensusStateWithHeight{ - types.NewConsensusStateWithHeight( - types.NewHeight(0, 1), - ibctmtypes.NewConsensusState( - header.GetTime(), commitmenttypes.NewMerkleRoot(header.Header.GetAppHash()), header.Header.NextValidatorsHash, - ), - ), - }, - ), - }, - nil, - types.NewParams(exported.Tendermint), - false, - 0, - ), - expPass: false, - }, - { - name: "invalid consensus state height", - genState: types.NewGenesisState( - []types.IdentifiedClientState{ - types.NewIdentifiedClientState( - tmClientID0, ibctmtypes.NewClientState(chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), - ), - types.NewIdentifiedClientState( - exported.Localhost, localhosttypes.NewClientState("chaindID", clientHeight), - ), - }, - []types.ClientConsensusStates{ - types.NewClientConsensusStates( - tmClientID0, - []types.ConsensusStateWithHeight{ - types.NewConsensusStateWithHeight( - types.ZeroHeight(), - ibctmtypes.NewConsensusState( - header.GetTime(), commitmenttypes.NewMerkleRoot(header.Header.GetAppHash()), header.Header.NextValidatorsHash, - ), - ), - }, - ), - }, - nil, - types.NewParams(exported.Tendermint), - false, - 0, - ), - expPass: false, - }, - { - name: "invalid consensus state", - genState: types.NewGenesisState( - []types.IdentifiedClientState{ - types.NewIdentifiedClientState( - tmClientID0, ibctmtypes.NewClientState(chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), - ), - types.NewIdentifiedClientState( - exported.Localhost, localhosttypes.NewClientState("chaindID", clientHeight), - ), - }, - []types.ClientConsensusStates{ - types.NewClientConsensusStates( - tmClientID0, - []types.ConsensusStateWithHeight{ - types.NewConsensusStateWithHeight( - types.NewHeight(0, 1), - ibctmtypes.NewConsensusState( - time.Time{}, commitmenttypes.NewMerkleRoot(header.Header.GetAppHash()), header.Header.NextValidatorsHash, - ), - ), - }, - ), - }, - nil, - types.NewParams(exported.Tendermint), - false, - 0, - ), - expPass: false, - }, - { - name: "client in genesis clients is disallowed by params", - genState: types.NewGenesisState( - []types.IdentifiedClientState{ - types.NewIdentifiedClientState( - tmClientID0, ibctmtypes.NewClientState(chainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), - ), - types.NewIdentifiedClientState( - exported.Localhost, localhosttypes.NewClientState("chainID", clientHeight), - ), - }, - []types.ClientConsensusStates{ - types.NewClientConsensusStates( - tmClientID0, - []types.ConsensusStateWithHeight{ - types.NewConsensusStateWithHeight( - header.GetHeight().(types.Height), - ibctmtypes.NewConsensusState( - header.GetTime(), commitmenttypes.NewMerkleRoot(header.Header.GetAppHash()), header.Header.NextValidatorsHash, - ), - ), - }, - ), - }, - nil, - types.NewParams(exported.Solomachine), - false, - 0, - ), - expPass: false, - }, - { - name: "metadata client-id does not match a genesis client", - genState: types.NewGenesisState( - []types.IdentifiedClientState{ - types.NewIdentifiedClientState( - clientID, ibctmtypes.NewClientState(chainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), - ), - types.NewIdentifiedClientState( - exported.Localhost, localhosttypes.NewClientState("chainID", clientHeight), - ), - }, - []types.ClientConsensusStates{ - types.NewClientConsensusStates( - clientID, - []types.ConsensusStateWithHeight{ - types.NewConsensusStateWithHeight( - header.GetHeight().(types.Height), - ibctmtypes.NewConsensusState( - header.GetTime(), commitmenttypes.NewMerkleRoot(header.Header.GetAppHash()), header.Header.NextValidatorsHash, - ), - ), - }, - ), - }, - []types.IdentifiedGenesisMetadata{ - types.NewIdentifiedGenesisMetadata( - "wrongclientid", - []types.GenesisMetadata{ - types.NewGenesisMetadata([]byte("key1"), []byte("val1")), - types.NewGenesisMetadata([]byte("key2"), []byte("val2")), - }, - ), - }, - types.NewParams(exported.Tendermint, exported.Localhost), - false, - 0, - ), - expPass: false, - }, - { - name: "invalid metadata", - genState: types.NewGenesisState( - []types.IdentifiedClientState{ - types.NewIdentifiedClientState( - clientID, ibctmtypes.NewClientState(chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), - ), - }, - []types.ClientConsensusStates{ - types.NewClientConsensusStates( - clientID, - []types.ConsensusStateWithHeight{ - types.NewConsensusStateWithHeight( - header.GetHeight().(types.Height), - ibctmtypes.NewConsensusState( - header.GetTime(), commitmenttypes.NewMerkleRoot(header.Header.GetAppHash()), header.Header.NextValidatorsHash, - ), - ), - }, - ), - }, - []types.IdentifiedGenesisMetadata{ - types.NewIdentifiedGenesisMetadata( - clientID, - []types.GenesisMetadata{ - types.NewGenesisMetadata([]byte(""), []byte("val1")), - types.NewGenesisMetadata([]byte("key2"), []byte("val2")), - }, - ), - }, - types.NewParams(exported.Tendermint), - false, - 0, - ), - }, - { - name: "invalid params", - genState: types.NewGenesisState( - []types.IdentifiedClientState{ - types.NewIdentifiedClientState( - tmClientID0, ibctmtypes.NewClientState(chainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), - ), - types.NewIdentifiedClientState( - exported.Localhost, localhosttypes.NewClientState("chainID", clientHeight), - ), - }, - []types.ClientConsensusStates{ - types.NewClientConsensusStates( - tmClientID0, - []types.ConsensusStateWithHeight{ - types.NewConsensusStateWithHeight( - header.GetHeight().(types.Height), - ibctmtypes.NewConsensusState( - header.GetTime(), commitmenttypes.NewMerkleRoot(header.Header.GetAppHash()), header.Header.NextValidatorsHash, - ), - ), - }, - ), - }, - nil, - types.NewParams(" "), - false, - 0, - ), - expPass: false, - }, - { - name: "invalid param", - genState: types.NewGenesisState( - []types.IdentifiedClientState{ - types.NewIdentifiedClientState( - tmClientID0, ibctmtypes.NewClientState(chainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), - ), - types.NewIdentifiedClientState( - exported.Localhost, localhosttypes.NewClientState("chainID", clientHeight), - ), - }, - []types.ClientConsensusStates{ - types.NewClientConsensusStates( - tmClientID0, - []types.ConsensusStateWithHeight{ - types.NewConsensusStateWithHeight( - header.GetHeight().(types.Height), - ibctmtypes.NewConsensusState( - header.GetTime(), commitmenttypes.NewMerkleRoot(header.Header.GetAppHash()), header.Header.NextValidatorsHash, - ), - ), - }, - ), - }, - nil, - types.NewParams(" "), - true, - 0, - ), - expPass: false, - }, - { - name: "localhost client not registered on allowlist", - genState: types.NewGenesisState( - []types.IdentifiedClientState{ - types.NewIdentifiedClientState( - tmClientID1, ibctmtypes.NewClientState(chainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), - ), - types.NewIdentifiedClientState( - exported.Localhost+"-0", localhosttypes.NewClientState("chainID", clientHeight), - ), - }, - []types.ClientConsensusStates{ - types.NewClientConsensusStates( - tmClientID1, - []types.ConsensusStateWithHeight{ - types.NewConsensusStateWithHeight( - header.GetHeight().(types.Height), - ibctmtypes.NewConsensusState( - header.GetTime(), commitmenttypes.NewMerkleRoot(header.Header.GetAppHash()), header.Header.NextValidatorsHash, - ), - ), - }, - ), - }, - nil, - types.NewParams(exported.Tendermint), - true, - 2, - ), - expPass: false, - }, - { - name: "next sequence too small", - genState: types.NewGenesisState( - []types.IdentifiedClientState{ - types.NewIdentifiedClientState( - tmClientID0, ibctmtypes.NewClientState(chainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), - ), - types.NewIdentifiedClientState( - exported.Localhost+"-1", localhosttypes.NewClientState("chainID", clientHeight), - ), - }, - []types.ClientConsensusStates{ - types.NewClientConsensusStates( - tmClientID0, - []types.ConsensusStateWithHeight{ - types.NewConsensusStateWithHeight( - header.GetHeight().(types.Height), - ibctmtypes.NewConsensusState( - header.GetTime(), commitmenttypes.NewMerkleRoot(header.Header.GetAppHash()), header.Header.NextValidatorsHash, - ), - ), - }, - ), - }, - nil, - types.NewParams(exported.Tendermint, exported.Localhost), - false, - 0, - ), - expPass: false, - }, - { - name: "failed to parse client identifier in client state loop", - genState: types.NewGenesisState( - []types.IdentifiedClientState{ - types.NewIdentifiedClientState( - "my-client", ibctmtypes.NewClientState(chainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), - ), - types.NewIdentifiedClientState( - exported.Localhost+"-1", localhosttypes.NewClientState("chainID", clientHeight), - ), - }, - []types.ClientConsensusStates{ - types.NewClientConsensusStates( - tmClientID0, - []types.ConsensusStateWithHeight{ - types.NewConsensusStateWithHeight( - header.GetHeight().(types.Height), - ibctmtypes.NewConsensusState( - header.GetTime(), commitmenttypes.NewMerkleRoot(header.Header.GetAppHash()), header.Header.NextValidatorsHash, - ), - ), - }, - ), - }, - nil, - types.NewParams(exported.Tendermint, exported.Localhost), - false, - 5, - ), - expPass: false, - }, - { - name: "consensus state different than client state type", - genState: types.NewGenesisState( - []types.IdentifiedClientState{ - types.NewIdentifiedClientState( - exported.Localhost+"-1", localhosttypes.NewClientState("chainID", clientHeight), - ), - }, - []types.ClientConsensusStates{ - types.NewClientConsensusStates( - exported.Localhost+"-1", - []types.ConsensusStateWithHeight{ - types.NewConsensusStateWithHeight( - header.GetHeight().(types.Height), - ibctmtypes.NewConsensusState( - header.GetTime(), commitmenttypes.NewMerkleRoot(header.Header.GetAppHash()), header.Header.NextValidatorsHash, - ), - ), - }, - ), - }, - nil, - types.NewParams(exported.Tendermint, exported.Localhost), - false, - 5, - ), - expPass: false, - }, - } - - for _, tc := range testCases { - tc := tc - err := tc.genState.Validate() - if tc.expPass { - suite.Require().NoError(err, tc.name) - } else { - suite.Require().Error(err, tc.name) - } - } -} diff --git a/x/ibc/core/02-client/types/height.go b/x/ibc/core/02-client/types/height.go deleted file mode 100644 index 4216d54e6681..000000000000 --- a/x/ibc/core/02-client/types/height.go +++ /dev/null @@ -1,188 +0,0 @@ -package types - -import ( - "fmt" - "math/big" - "regexp" - "strconv" - "strings" - - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -var _ exported.Height = (*Height)(nil) - -// IsRevisionFormat checks if a chainID is in the format required for parsing revisions -// The chainID must be in the form: `{chainID}-{revision} -// 24-host may enforce stricter checks on chainID -var IsRevisionFormat = regexp.MustCompile(`^.*[^-]-{1}[1-9][0-9]*$`).MatchString - -// ZeroHeight is a helper function which returns an uninitialized height. -func ZeroHeight() Height { - return Height{} -} - -// NewHeight is a constructor for the IBC height type -func NewHeight(revisionNumber, revisionHeight uint64) Height { - return Height{ - RevisionNumber: revisionNumber, - RevisionHeight: revisionHeight, - } -} - -// GetRevisionNumber returns the revision-number of the height -func (h Height) GetRevisionNumber() uint64 { - return h.RevisionNumber -} - -// GetRevisionHeight returns the revision-height of the height -func (h Height) GetRevisionHeight() uint64 { - return h.RevisionHeight -} - -// Compare implements a method to compare two heights. When comparing two heights a, b -// we can call a.Compare(b) which will return -// -1 if a < b -// 0 if a = b -// 1 if a > b -// -// It first compares based on revision numbers, whichever has the higher revision number is the higher height -// If revision number is the same, then the revision height is compared -func (h Height) Compare(other exported.Height) int64 { - height, ok := other.(Height) - if !ok { - panic(fmt.Sprintf("cannot compare against invalid height type: %T. expected height type: %T", other, h)) - } - var a, b big.Int - if h.RevisionNumber != height.RevisionNumber { - a.SetUint64(h.RevisionNumber) - b.SetUint64(height.RevisionNumber) - } else { - a.SetUint64(h.RevisionHeight) - b.SetUint64(height.RevisionHeight) - } - return int64(a.Cmp(&b)) -} - -// LT Helper comparison function returns true if h < other -func (h Height) LT(other exported.Height) bool { - return h.Compare(other) == -1 -} - -// LTE Helper comparison function returns true if h <= other -func (h Height) LTE(other exported.Height) bool { - cmp := h.Compare(other) - return cmp <= 0 -} - -// GT Helper comparison function returns true if h > other -func (h Height) GT(other exported.Height) bool { - return h.Compare(other) == 1 -} - -// GTE Helper comparison function returns true if h >= other -func (h Height) GTE(other exported.Height) bool { - cmp := h.Compare(other) - return cmp >= 0 -} - -// EQ Helper comparison function returns true if h == other -func (h Height) EQ(other exported.Height) bool { - return h.Compare(other) == 0 -} - -// String returns a string representation of Height -func (h Height) String() string { - return fmt.Sprintf("%d-%d", h.RevisionNumber, h.RevisionHeight) -} - -// Decrement will return a new height with the RevisionHeight decremented -// If the RevisionHeight is already at lowest value (1), then false success flag is returend -func (h Height) Decrement() (decremented exported.Height, success bool) { - if h.RevisionHeight == 0 { - return Height{}, false - } - return NewHeight(h.RevisionNumber, h.RevisionHeight-1), true -} - -// Increment will return a height with the same revision number but an -// incremented revision height -func (h Height) Increment() exported.Height { - return NewHeight(h.RevisionNumber, h.RevisionHeight+1) -} - -// IsZero returns true if height revision and revision-height are both 0 -func (h Height) IsZero() bool { - return h.RevisionNumber == 0 && h.RevisionHeight == 0 -} - -// MustParseHeight will attempt to parse a string representation of a height and panic if -// parsing fails. -func MustParseHeight(heightStr string) Height { - height, err := ParseHeight(heightStr) - if err != nil { - panic(err) - } - - return height -} - -// ParseHeight is a utility function that takes a string representation of the height -// and returns a Height struct -func ParseHeight(heightStr string) (Height, error) { - splitStr := strings.Split(heightStr, "-") - if len(splitStr) != 2 { - return Height{}, sdkerrors.Wrapf(sdkerrors.ErrInvalidHeight, "expected height string format: {revision}-{height}. Got: %s", heightStr) - } - revisionNumber, err := strconv.ParseUint(splitStr[0], 10, 64) - if err != nil { - return Height{}, sdkerrors.Wrapf(sdkerrors.ErrInvalidHeight, "invalid revision number. parse err: %s", err) - } - revisionHeight, err := strconv.ParseUint(splitStr[1], 10, 64) - if err != nil { - return Height{}, sdkerrors.Wrapf(sdkerrors.ErrInvalidHeight, "invalid revision height. parse err: %s", err) - } - return NewHeight(revisionNumber, revisionHeight), nil -} - -// SetRevisionNumber takes a chainID in valid revision format and swaps the revision number -// in the chainID with the given revision number. -func SetRevisionNumber(chainID string, revision uint64) (string, error) { - if !IsRevisionFormat(chainID) { - return "", sdkerrors.Wrapf( - sdkerrors.ErrInvalidChainID, "chainID is not in revision format: %s", chainID, - ) - } - - splitStr := strings.Split(chainID, "-") - // swap out revision number with given revision - splitStr[len(splitStr)-1] = strconv.Itoa(int(revision)) - return strings.Join(splitStr, "-"), nil -} - -// ParseChainID is a utility function that returns an revision number from the given ChainID. -// ParseChainID attempts to parse a chain id in the format: `{chainID}-{revision}` -// and return the revisionnumber as a uint64. -// If the chainID is not in the expected format, a default revision value of 0 is returned. -func ParseChainID(chainID string) uint64 { - if !IsRevisionFormat(chainID) { - // chainID is not in revision format, return 0 as default - return 0 - } - splitStr := strings.Split(chainID, "-") - revision, err := strconv.ParseUint(splitStr[len(splitStr)-1], 10, 64) - // sanity check: error should always be nil since regex only allows numbers in last element - if err != nil { - panic(fmt.Sprintf("regex allowed non-number value as last split element for chainID: %s", chainID)) - } - return revision -} - -// GetSelfHeight is a utility function that returns self height given context -// Revision number is retrieved from ctx.ChainID() -func GetSelfHeight(ctx sdk.Context) Height { - revision := ParseChainID(ctx.ChainID()) - return NewHeight(revision, uint64(ctx.BlockHeight())) -} diff --git a/x/ibc/core/02-client/types/height_test.go b/x/ibc/core/02-client/types/height_test.go deleted file mode 100644 index a455b7f58d49..000000000000 --- a/x/ibc/core/02-client/types/height_test.go +++ /dev/null @@ -1,155 +0,0 @@ -package types_test - -import ( - "math" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" -) - -func TestZeroHeight(t *testing.T) { - require.Equal(t, types.Height{}, types.ZeroHeight()) -} - -func TestCompareHeights(t *testing.T) { - testCases := []struct { - name string - height1 types.Height - height2 types.Height - compareSign int64 - }{ - {"revision number 1 is lesser", types.NewHeight(1, 3), types.NewHeight(3, 4), -1}, - {"revision number 1 is greater", types.NewHeight(7, 5), types.NewHeight(4, 5), 1}, - {"revision height 1 is lesser", types.NewHeight(3, 4), types.NewHeight(3, 9), -1}, - {"revision height 1 is greater", types.NewHeight(3, 8), types.NewHeight(3, 3), 1}, - {"revision number is MaxUint64", types.NewHeight(math.MaxUint64, 1), types.NewHeight(0, 1), 1}, - {"revision height is MaxUint64", types.NewHeight(1, math.MaxUint64), types.NewHeight(1, 0), 1}, - {"height is equal", types.NewHeight(4, 4), types.NewHeight(4, 4), 0}, - } - - for i, tc := range testCases { - compare := tc.height1.Compare(tc.height2) - - switch tc.compareSign { - case -1: - require.True(t, compare == -1, "case %d: %s should return negative value on comparison, got: %d", - i, tc.name, compare) - case 0: - require.True(t, compare == 0, "case %d: %s should return zero on comparison, got: %d", - i, tc.name, compare) - case 1: - require.True(t, compare == 1, "case %d: %s should return positive value on comparison, got: %d", - i, tc.name, compare) - } - } -} - -func TestDecrement(t *testing.T) { - validDecrement := types.NewHeight(3, 3) - expected := types.NewHeight(3, 2) - - actual, success := validDecrement.Decrement() - require.Equal(t, expected, actual, "decrementing %s did not return expected height: %s. got %s", - validDecrement, expected, actual) - require.True(t, success, "decrement failed unexpectedly") - - invalidDecrement := types.NewHeight(3, 0) - actual, success = invalidDecrement.Decrement() - - require.Equal(t, types.ZeroHeight(), actual, "invalid decrement returned non-zero height: %s", actual) - require.False(t, success, "invalid decrement passed") -} - -func TestString(t *testing.T) { - _, err := types.ParseHeight("height") - require.Error(t, err, "invalid height string passed") - - _, err = types.ParseHeight("revision-10") - require.Error(t, err, "invalid revision string passed") - - _, err = types.ParseHeight("3-height") - require.Error(t, err, "invalid revision-height string passed") - - height := types.NewHeight(3, 4) - recovered, err := types.ParseHeight(height.String()) - - require.NoError(t, err, "valid height string could not be parsed") - require.Equal(t, height, recovered, "recovered height not equal to original height") - - parse, err := types.ParseHeight("3-10") - require.NoError(t, err, "parse err") - require.Equal(t, types.NewHeight(3, 10), parse, "parse height returns wrong height") -} - -func (suite *TypesTestSuite) TestMustParseHeight() { - suite.Require().Panics(func() { - types.MustParseHeight("height") - }) - - suite.Require().NotPanics(func() { - types.MustParseHeight("111-1") - }) - - suite.Require().NotPanics(func() { - types.MustParseHeight("0-0") - }) -} - -func TestParseChainID(t *testing.T) { - cases := []struct { - chainID string - revision uint64 - formatted bool - }{ - {"gaiamainnet-3", 3, true}, - {"a-1", 1, true}, - {"gaia-mainnet-40", 40, true}, - {"gaiamainnet-3-39", 39, true}, - {"gaiamainnet--", 0, false}, - {"gaiamainnet-03", 0, false}, - {"gaiamainnet--4", 0, false}, - {"gaiamainnet-3.4", 0, false}, - {"gaiamainnet", 0, false}, - {"a--1", 0, false}, - {"-1", 0, false}, - {"--1", 0, false}, - } - - for i, tc := range cases { - require.Equal(t, tc.formatted, types.IsRevisionFormat(tc.chainID), "id %s does not match expected format", tc.chainID) - - revision := types.ParseChainID(tc.chainID) - require.Equal(t, tc.revision, revision, "case %d returns incorrect revision", i) - } - -} - -func TestSetRevisionNumber(t *testing.T) { - // Test SetRevisionNumber - chainID, err := types.SetRevisionNumber("gaiamainnet", 3) - require.Error(t, err, "invalid revision format passed SetRevisionNumber") - require.Equal(t, "", chainID, "invalid revision format returned non-empty string on SetRevisionNumber") - chainID = "gaiamainnet-3" - - chainID, err = types.SetRevisionNumber(chainID, 4) - require.NoError(t, err, "valid revision format failed SetRevisionNumber") - require.Equal(t, "gaiamainnet-4", chainID, "valid revision format returned incorrect string on SetRevisionNumber") -} - -func (suite *TypesTestSuite) TestSelfHeight() { - ctx := suite.chainA.GetContext() - - // Test default revision - ctx = ctx.WithChainID("gaiamainnet") - ctx = ctx.WithBlockHeight(10) - height := types.GetSelfHeight(ctx) - suite.Require().Equal(types.NewHeight(0, 10), height, "default self height failed") - - // Test successful revision format - ctx = ctx.WithChainID("gaiamainnet-3") - ctx = ctx.WithBlockHeight(18) - height = types.GetSelfHeight(ctx) - suite.Require().Equal(types.NewHeight(3, 18), height, "valid self height failed") -} diff --git a/x/ibc/core/02-client/types/keys.go b/x/ibc/core/02-client/types/keys.go deleted file mode 100644 index 321f5e3ffa3c..000000000000 --- a/x/ibc/core/02-client/types/keys.go +++ /dev/null @@ -1,65 +0,0 @@ -package types - -import ( - "fmt" - "regexp" - "strconv" - "strings" - - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" -) - -const ( - // SubModuleName defines the IBC client name - SubModuleName string = "client" - - // RouterKey is the message route for IBC client - RouterKey string = SubModuleName - - // QuerierRoute is the querier route for IBC client - QuerierRoute string = SubModuleName - - // KeyNextClientSequence is the key used to store the next client sequence in - // the keeper. - KeyNextClientSequence = "nextClientSequence" -) - -// FormatClientIdentifier returns the client identifier with the sequence appended. -// This is a SDK specific format not enforced by IBC protocol. -func FormatClientIdentifier(clientType string, sequence uint64) string { - return fmt.Sprintf("%s-%d", clientType, sequence) -} - -// IsClientIDFormat checks if a clientID is in the format required on the SDK for -// parsing client identifiers. The client identifier must be in the form: `{client-type}-{N} -var IsClientIDFormat = regexp.MustCompile(`^.*[^-]-[0-9]{1,20}$`).MatchString - -// IsValidClientID checks if the clientID is valid and can be parsed into the client -// identifier format. -func IsValidClientID(clientID string) bool { - _, _, err := ParseClientIdentifier(clientID) - return err == nil -} - -// ParseClientIdentifier parses the client type and sequence from the client identifier. -func ParseClientIdentifier(clientID string) (string, uint64, error) { - if !IsClientIDFormat(clientID) { - return "", 0, sdkerrors.Wrapf(host.ErrInvalidID, "invalid client identifier %s is not in format: `{client-type}-{N}`", clientID) - } - - splitStr := strings.Split(clientID, "-") - lastIndex := len(splitStr) - 1 - - clientType := strings.Join(splitStr[:lastIndex], "-") - if strings.TrimSpace(clientType) == "" { - return "", 0, sdkerrors.Wrap(host.ErrInvalidID, "client identifier must be in format: `{client-type}-{N}` and client type cannot be blank") - } - - sequence, err := strconv.ParseUint(splitStr[lastIndex], 10, 64) - if err != nil { - return "", 0, sdkerrors.Wrap(err, "failed to parse client identifier sequence") - } - - return clientType, sequence, nil -} diff --git a/x/ibc/core/02-client/types/keys_test.go b/x/ibc/core/02-client/types/keys_test.go deleted file mode 100644 index 4938145236e7..000000000000 --- a/x/ibc/core/02-client/types/keys_test.go +++ /dev/null @@ -1,54 +0,0 @@ -package types_test - -import ( - "math" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" -) - -// tests ParseClientIdentifier and IsValidClientID -func TestParseClientIdentifier(t *testing.T) { - testCases := []struct { - name string - clientID string - clientType string - expSeq uint64 - expPass bool - }{ - {"valid 0", "tendermint-0", "tendermint", 0, true}, - {"valid 1", "tendermint-1", "tendermint", 1, true}, - {"valid solemachine", "solomachine-v1-1", "solomachine-v1", 1, true}, - {"valid large sequence", types.FormatClientIdentifier("tendermint", math.MaxUint64), "tendermint", math.MaxUint64, true}, - {"valid short client type", "t-0", "t", 0, true}, - // one above uint64 max - {"invalid uint64", "tendermint-18446744073709551616", "tendermint", 0, false}, - // uint64 == 20 characters - {"invalid large sequence", "tendermint-2345682193567182931243", "tendermint", 0, false}, - {"missing dash", "tendermint0", "tendermint", 0, false}, - {"blank id", " ", " ", 0, false}, - {"empty id", "", "", 0, false}, - {"negative sequence", "tendermint--1", "tendermint", 0, false}, - {"invalid format", "tendermint-tm", "tendermint", 0, false}, - {"empty clientype", " -100", "tendermint", 0, false}, - } - - for _, tc := range testCases { - - clientType, seq, err := types.ParseClientIdentifier(tc.clientID) - valid := types.IsValidClientID(tc.clientID) - require.Equal(t, tc.expSeq, seq, tc.clientID) - - if tc.expPass { - require.NoError(t, err, tc.name) - require.True(t, valid) - require.Equal(t, tc.clientType, clientType) - } else { - require.Error(t, err, tc.name, tc.clientID) - require.False(t, valid) - require.Equal(t, "", clientType) - } - } -} diff --git a/x/ibc/core/02-client/types/msgs.go b/x/ibc/core/02-client/types/msgs.go deleted file mode 100644 index 1e884123d74b..000000000000 --- a/x/ibc/core/02-client/types/msgs.go +++ /dev/null @@ -1,343 +0,0 @@ -package types - -import ( - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -// message types for the IBC client -const ( - TypeMsgCreateClient string = "create_client" - TypeMsgUpdateClient string = "update_client" - TypeMsgUpgradeClient string = "upgrade_client" - TypeMsgSubmitMisbehaviour string = "submit_misbehaviour" -) - -var ( - _ sdk.Msg = &MsgCreateClient{} - _ sdk.Msg = &MsgUpdateClient{} - _ sdk.Msg = &MsgSubmitMisbehaviour{} - _ sdk.Msg = &MsgUpgradeClient{} - - _ codectypes.UnpackInterfacesMessage = MsgCreateClient{} - _ codectypes.UnpackInterfacesMessage = MsgUpdateClient{} - _ codectypes.UnpackInterfacesMessage = MsgSubmitMisbehaviour{} - _ codectypes.UnpackInterfacesMessage = MsgUpgradeClient{} -) - -// NewMsgCreateClient creates a new MsgCreateClient instance -//nolint:interfacer -func NewMsgCreateClient( - clientState exported.ClientState, consensusState exported.ConsensusState, signer sdk.AccAddress, -) (*MsgCreateClient, error) { - - anyClientState, err := PackClientState(clientState) - if err != nil { - return nil, err - } - - anyConsensusState, err := PackConsensusState(consensusState) - if err != nil { - return nil, err - } - - return &MsgCreateClient{ - ClientState: anyClientState, - ConsensusState: anyConsensusState, - Signer: signer.String(), - }, nil -} - -// Route implements sdk.Msg -func (msg MsgCreateClient) Route() string { - return host.RouterKey -} - -// Type implements sdk.Msg -func (msg MsgCreateClient) Type() string { - return TypeMsgCreateClient -} - -// ValidateBasic implements sdk.Msg -func (msg MsgCreateClient) ValidateBasic() error { - _, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err) - } - clientState, err := UnpackClientState(msg.ClientState) - if err != nil { - return err - } - if err := clientState.Validate(); err != nil { - return err - } - if clientState.ClientType() == exported.Localhost { - return sdkerrors.Wrap(ErrInvalidClient, "localhost client can only be created on chain initialization") - } - consensusState, err := UnpackConsensusState(msg.ConsensusState) - if err != nil { - return err - } - if clientState.ClientType() != consensusState.ClientType() { - return sdkerrors.Wrap(ErrInvalidClientType, "client type for client state and consensus state do not match") - } - if err := ValidateClientType(clientState.ClientType()); err != nil { - return sdkerrors.Wrap(err, "client type does not meet naming constraints") - } - return consensusState.ValidateBasic() -} - -// GetSignBytes implements sdk.Msg. The function will panic since it is used -// for amino transaction verification which IBC does not support. -func (msg MsgCreateClient) GetSignBytes() []byte { - panic("IBC messages do not support amino") -} - -// GetSigners implements sdk.Msg -func (msg MsgCreateClient) GetSigners() []sdk.AccAddress { - accAddr, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - panic(err) - } - return []sdk.AccAddress{accAddr} -} - -// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces -func (msg MsgCreateClient) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { - var clientState exported.ClientState - err := unpacker.UnpackAny(msg.ClientState, &clientState) - if err != nil { - return err - } - - var consensusState exported.ConsensusState - return unpacker.UnpackAny(msg.ConsensusState, &consensusState) -} - -// NewMsgUpdateClient creates a new MsgUpdateClient instance -//nolint:interfacer -func NewMsgUpdateClient(id string, header exported.Header, signer sdk.AccAddress) (*MsgUpdateClient, error) { - anyHeader, err := PackHeader(header) - if err != nil { - return nil, err - } - - return &MsgUpdateClient{ - ClientId: id, - Header: anyHeader, - Signer: signer.String(), - }, nil -} - -// Route implements sdk.Msg -func (msg MsgUpdateClient) Route() string { - return host.RouterKey -} - -// Type implements sdk.Msg -func (msg MsgUpdateClient) Type() string { - return TypeMsgUpdateClient -} - -// ValidateBasic implements sdk.Msg -func (msg MsgUpdateClient) ValidateBasic() error { - _, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err) - } - header, err := UnpackHeader(msg.Header) - if err != nil { - return err - } - if err := header.ValidateBasic(); err != nil { - return err - } - if msg.ClientId == exported.Localhost { - return sdkerrors.Wrap(ErrInvalidClient, "localhost client is only updated on ABCI BeginBlock") - } - return host.ClientIdentifierValidator(msg.ClientId) -} - -// GetSignBytes implements sdk.Msg. The function will panic since it is used -// for amino transaction verification which IBC does not support. -func (msg MsgUpdateClient) GetSignBytes() []byte { - panic("IBC messages do not support amino") -} - -// GetSigners implements sdk.Msg -func (msg MsgUpdateClient) GetSigners() []sdk.AccAddress { - accAddr, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - panic(err) - } - return []sdk.AccAddress{accAddr} -} - -// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces -func (msg MsgUpdateClient) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { - var header exported.Header - return unpacker.UnpackAny(msg.Header, &header) -} - -// NewMsgUpgradeClient creates a new MsgUpgradeClient instance -// nolint: interfacer -func NewMsgUpgradeClient(clientID string, clientState exported.ClientState, consState exported.ConsensusState, - proofUpgradeClient, proofUpgradeConsState []byte, signer sdk.AccAddress) (*MsgUpgradeClient, error) { - anyClient, err := PackClientState(clientState) - if err != nil { - return nil, err - } - anyConsState, err := PackConsensusState(consState) - if err != nil { - return nil, err - } - - return &MsgUpgradeClient{ - ClientId: clientID, - ClientState: anyClient, - ConsensusState: anyConsState, - ProofUpgradeClient: proofUpgradeClient, - ProofUpgradeConsensusState: proofUpgradeConsState, - Signer: signer.String(), - }, nil -} - -// Route implements sdk.Msg -func (msg MsgUpgradeClient) Route() string { - return host.RouterKey -} - -// Type implements sdk.Msg -func (msg MsgUpgradeClient) Type() string { - return TypeMsgUpgradeClient -} - -// ValidateBasic implements sdk.Msg -func (msg MsgUpgradeClient) ValidateBasic() error { - // will not validate client state as committed client may not form a valid client state. - // client implementations are responsible for ensuring final upgraded client is valid. - clientState, err := UnpackClientState(msg.ClientState) - if err != nil { - return err - } - // will not validate consensus state here since the trusted kernel may not form a valid consenus state. - // client implementations are responsible for ensuring client can submit new headers against this consensus state. - consensusState, err := UnpackConsensusState(msg.ConsensusState) - if err != nil { - return err - } - - if clientState.ClientType() != consensusState.ClientType() { - return sdkerrors.Wrapf(ErrInvalidUpgradeClient, "consensus state's client-type does not match client. expected: %s, got: %s", - clientState.ClientType(), consensusState.ClientType()) - } - if len(msg.ProofUpgradeClient) == 0 { - return sdkerrors.Wrap(ErrInvalidUpgradeClient, "proof of upgrade client cannot be empty") - } - if len(msg.ProofUpgradeConsensusState) == 0 { - return sdkerrors.Wrap(ErrInvalidUpgradeClient, "proof of upgrade consensus state cannot be empty") - } - _, err = sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err) - } - return host.ClientIdentifierValidator(msg.ClientId) -} - -// GetSignBytes implements sdk.Msg. The function will panic since it is used -// for amino transaction verification which IBC does not support. -func (msg MsgUpgradeClient) GetSignBytes() []byte { - panic("IBC messages do not support amino") -} - -// GetSigners implements sdk.Msg -func (msg MsgUpgradeClient) GetSigners() []sdk.AccAddress { - accAddr, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - panic(err) - } - return []sdk.AccAddress{accAddr} -} - -// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces -func (msg MsgUpgradeClient) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { - var ( - clientState exported.ClientState - consState exported.ConsensusState - ) - if err := unpacker.UnpackAny(msg.ClientState, &clientState); err != nil { - return err - } - return unpacker.UnpackAny(msg.ConsensusState, &consState) -} - -// NewMsgSubmitMisbehaviour creates a new MsgSubmitMisbehaviour instance. -//nolint:interfacer -func NewMsgSubmitMisbehaviour(clientID string, misbehaviour exported.Misbehaviour, signer sdk.AccAddress) (*MsgSubmitMisbehaviour, error) { - anyMisbehaviour, err := PackMisbehaviour(misbehaviour) - if err != nil { - return nil, err - } - - return &MsgSubmitMisbehaviour{ - ClientId: clientID, - Misbehaviour: anyMisbehaviour, - Signer: signer.String(), - }, nil -} - -// Route returns the MsgSubmitClientMisbehaviour's route. -func (msg MsgSubmitMisbehaviour) Route() string { return host.RouterKey } - -// Type returns the MsgSubmitMisbehaviour's type. -func (msg MsgSubmitMisbehaviour) Type() string { - return TypeMsgSubmitMisbehaviour -} - -// ValidateBasic performs basic (non-state-dependant) validation on a MsgSubmitMisbehaviour. -func (msg MsgSubmitMisbehaviour) ValidateBasic() error { - _, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err) - } - misbehaviour, err := UnpackMisbehaviour(msg.Misbehaviour) - if err != nil { - return err - } - if err := misbehaviour.ValidateBasic(); err != nil { - return err - } - if misbehaviour.GetClientID() != msg.ClientId { - return sdkerrors.Wrapf( - ErrInvalidMisbehaviour, - "misbehaviour client-id doesn't match client-id from message (%s ≠ %s)", - misbehaviour.GetClientID(), msg.ClientId, - ) - } - - return host.ClientIdentifierValidator(msg.ClientId) -} - -// GetSignBytes implements sdk.Msg. The function will panic since it is used -// for amino transaction verification which IBC does not support. -func (msg MsgSubmitMisbehaviour) GetSignBytes() []byte { - panic("IBC messages do not support amino") -} - -// GetSigners returns the single expected signer for a MsgSubmitMisbehaviour. -func (msg MsgSubmitMisbehaviour) GetSigners() []sdk.AccAddress { - accAddr, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - panic(err) - } - return []sdk.AccAddress{accAddr} -} - -// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces -func (msg MsgSubmitMisbehaviour) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { - var misbehaviour exported.Misbehaviour - return unpacker.UnpackAny(msg.Misbehaviour, &misbehaviour) -} diff --git a/x/ibc/core/02-client/types/msgs_test.go b/x/ibc/core/02-client/types/msgs_test.go deleted file mode 100644 index e42725bae26f..000000000000 --- a/x/ibc/core/02-client/types/msgs_test.go +++ /dev/null @@ -1,619 +0,0 @@ -package types_test - -import ( - "testing" - "time" - - "github.com/golang/protobuf/proto" - "github.com/stretchr/testify/suite" - - "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/core/exported" - solomachinetypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/06-solomachine/types" - ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" -) - -type TypesTestSuite struct { - suite.Suite - - coordinator *ibctesting.Coordinator - - chainA *ibctesting.TestChain - chainB *ibctesting.TestChain -} - -func (suite *TypesTestSuite) SetupTest() { - suite.coordinator = ibctesting.NewCoordinator(suite.T(), 2) - suite.chainA = suite.coordinator.GetChain(ibctesting.GetChainID(0)) - suite.chainB = suite.coordinator.GetChain(ibctesting.GetChainID(1)) -} - -func TestTypesTestSuite(t *testing.T) { - suite.Run(t, new(TypesTestSuite)) -} - -// tests that different clients within MsgCreateClient can be marshaled -// and unmarshaled. -func (suite *TypesTestSuite) TestMarshalMsgCreateClient() { - var ( - msg *types.MsgCreateClient - err error - ) - - testCases := []struct { - name string - malleate func() - }{ - { - "solo machine client", func() { - soloMachine := ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "solomachine", "", 2) - msg, err = types.NewMsgCreateClient(soloMachine.ClientState(), soloMachine.ConsensusState(), suite.chainA.SenderAccount.GetAddress()) - suite.Require().NoError(err) - }, - }, - { - "tendermint client", func() { - tendermintClient := ibctmtypes.NewClientState(suite.chainA.ChainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) - msg, err = types.NewMsgCreateClient(tendermintClient, suite.chainA.CurrentTMClientHeader().ConsensusState(), suite.chainA.SenderAccount.GetAddress()) - suite.Require().NoError(err) - }, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - suite.SetupTest() - - tc.malleate() - - cdc := suite.chainA.App.AppCodec() - - // marshal message - bz, err := cdc.MarshalJSON(msg) - suite.Require().NoError(err) - - // unmarshal message - newMsg := &types.MsgCreateClient{} - err = cdc.UnmarshalJSON(bz, newMsg) - suite.Require().NoError(err) - - suite.Require().True(proto.Equal(msg, newMsg)) - }) - } -} - -func (suite *TypesTestSuite) TestMsgCreateClient_ValidateBasic() { - var ( - msg = &types.MsgCreateClient{} - err error - ) - - cases := []struct { - name string - malleate func() - expPass bool - }{ - { - "valid - tendermint client", - func() { - tendermintClient := ibctmtypes.NewClientState(suite.chainA.ChainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) - msg, err = types.NewMsgCreateClient(tendermintClient, suite.chainA.CurrentTMClientHeader().ConsensusState(), suite.chainA.SenderAccount.GetAddress()) - suite.Require().NoError(err) - }, - true, - }, - { - "invalid tendermint client", - func() { - msg, err = types.NewMsgCreateClient(&ibctmtypes.ClientState{}, suite.chainA.CurrentTMClientHeader().ConsensusState(), suite.chainA.SenderAccount.GetAddress()) - suite.Require().NoError(err) - }, - false, - }, - { - "failed to unpack client", - func() { - msg.ClientState = nil - }, - false, - }, - { - "failed to unpack consensus state", - func() { - tendermintClient := ibctmtypes.NewClientState(suite.chainA.ChainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) - msg, err = types.NewMsgCreateClient(tendermintClient, suite.chainA.CurrentTMClientHeader().ConsensusState(), suite.chainA.SenderAccount.GetAddress()) - suite.Require().NoError(err) - msg.ConsensusState = nil - }, - false, - }, - { - "invalid signer", - func() { - msg.Signer = "" - }, - false, - }, - { - "valid - solomachine client", - func() { - soloMachine := ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "solomachine", "", 2) - msg, err = types.NewMsgCreateClient(soloMachine.ClientState(), soloMachine.ConsensusState(), suite.chainA.SenderAccount.GetAddress()) - suite.Require().NoError(err) - }, - true, - }, - { - "invalid solomachine client", - func() { - soloMachine := ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "solomachine", "", 2) - msg, err = types.NewMsgCreateClient(&solomachinetypes.ClientState{}, soloMachine.ConsensusState(), suite.chainA.SenderAccount.GetAddress()) - suite.Require().NoError(err) - }, - false, - }, - { - "invalid solomachine consensus state", - func() { - soloMachine := ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "solomachine", "", 2) - msg, err = types.NewMsgCreateClient(soloMachine.ClientState(), &solomachinetypes.ConsensusState{}, suite.chainA.SenderAccount.GetAddress()) - suite.Require().NoError(err) - }, - false, - }, - { - "invalid - client state and consensus state client types do not match", - func() { - tendermintClient := ibctmtypes.NewClientState(suite.chainA.ChainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) - soloMachine := ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "solomachine", "", 2) - msg, err = types.NewMsgCreateClient(tendermintClient, soloMachine.ConsensusState(), suite.chainA.SenderAccount.GetAddress()) - suite.Require().NoError(err) - }, - false, - }, - } - - for _, tc := range cases { - tc.malleate() - err = msg.ValidateBasic() - if tc.expPass { - suite.Require().NoError(err, tc.name) - } else { - suite.Require().Error(err, tc.name) - } - } -} - -// tests that different header within MsgUpdateClient can be marshaled -// and unmarshaled. -func (suite *TypesTestSuite) TestMarshalMsgUpdateClient() { - var ( - msg *types.MsgUpdateClient - err error - ) - - testCases := []struct { - name string - malleate func() - }{ - { - "solo machine client", func() { - soloMachine := ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "solomachine", "", 2) - msg, err = types.NewMsgUpdateClient(soloMachine.ClientID, soloMachine.CreateHeader(), suite.chainA.SenderAccount.GetAddress()) - suite.Require().NoError(err) - }, - }, - { - "tendermint client", func() { - msg, err = types.NewMsgUpdateClient("tendermint", suite.chainA.CurrentTMClientHeader(), suite.chainA.SenderAccount.GetAddress()) - suite.Require().NoError(err) - - }, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - suite.SetupTest() - - tc.malleate() - - cdc := suite.chainA.App.AppCodec() - - // marshal message - bz, err := cdc.MarshalJSON(msg) - suite.Require().NoError(err) - - // unmarshal message - newMsg := &types.MsgUpdateClient{} - err = cdc.UnmarshalJSON(bz, newMsg) - suite.Require().NoError(err) - - suite.Require().True(proto.Equal(msg, newMsg)) - }) - } -} - -func (suite *TypesTestSuite) TestMsgUpdateClient_ValidateBasic() { - var ( - msg = &types.MsgUpdateClient{} - err error - ) - - cases := []struct { - name string - malleate func() - expPass bool - }{ - { - "invalid client-id", - func() { - msg.ClientId = "" - }, - false, - }, - { - "valid - tendermint header", - func() { - msg, err = types.NewMsgUpdateClient("tendermint", suite.chainA.CurrentTMClientHeader(), suite.chainA.SenderAccount.GetAddress()) - suite.Require().NoError(err) - }, - true, - }, - { - "invalid tendermint header", - func() { - msg, err = types.NewMsgUpdateClient("tendermint", &ibctmtypes.Header{}, suite.chainA.SenderAccount.GetAddress()) - suite.Require().NoError(err) - }, - false, - }, - { - "failed to unpack header", - func() { - msg.Header = nil - }, - false, - }, - { - "invalid signer", - func() { - msg.Signer = "" - }, - false, - }, - { - "valid - solomachine header", - func() { - soloMachine := ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "solomachine", "", 2) - msg, err = types.NewMsgUpdateClient(soloMachine.ClientID, soloMachine.CreateHeader(), suite.chainA.SenderAccount.GetAddress()) - suite.Require().NoError(err) - }, - true, - }, - { - "invalid solomachine header", - func() { - msg, err = types.NewMsgUpdateClient("solomachine", &solomachinetypes.Header{}, suite.chainA.SenderAccount.GetAddress()) - suite.Require().NoError(err) - }, - false, - }, - { - "unsupported - localhost", - func() { - msg, err = types.NewMsgUpdateClient(exported.Localhost, suite.chainA.CurrentTMClientHeader(), suite.chainA.SenderAccount.GetAddress()) - suite.Require().NoError(err) - }, - false, - }, - } - - for _, tc := range cases { - tc.malleate() - err = msg.ValidateBasic() - if tc.expPass { - suite.Require().NoError(err, tc.name) - } else { - suite.Require().Error(err, tc.name) - } - } -} - -func (suite *TypesTestSuite) TestMarshalMsgUpgradeClient() { - var ( - msg *types.MsgUpgradeClient - err error - ) - - testCases := []struct { - name string - malleate func() - }{ - { - "client upgrades to new tendermint client", - func() { - tendermintClient := ibctmtypes.NewClientState(suite.chainA.ChainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) - tendermintConsState := &ibctmtypes.ConsensusState{NextValidatorsHash: []byte("nextValsHash")} - msg, err = types.NewMsgUpgradeClient("clientid", tendermintClient, tendermintConsState, []byte("proofUpgradeClient"), []byte("proofUpgradeConsState"), suite.chainA.SenderAccount.GetAddress()) - suite.Require().NoError(err) - }, - }, - { - "client upgrades to new solomachine client", - func() { - soloMachine := ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "solomachine", "", 1) - msg, err = types.NewMsgUpgradeClient("clientid", soloMachine.ClientState(), soloMachine.ConsensusState(), []byte("proofUpgradeClient"), []byte("proofUpgradeConsState"), suite.chainA.SenderAccount.GetAddress()) - suite.Require().NoError(err) - }, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - suite.SetupTest() - - tc.malleate() - - cdc := suite.chainA.App.AppCodec() - - // marshal message - bz, err := cdc.MarshalJSON(msg) - suite.Require().NoError(err) - - // unmarshal message - newMsg := &types.MsgUpgradeClient{} - err = cdc.UnmarshalJSON(bz, newMsg) - suite.Require().NoError(err) - }) - } -} - -func (suite *TypesTestSuite) TestMsgUpgradeClient_ValidateBasic() { - cases := []struct { - name string - malleate func(*types.MsgUpgradeClient) - expPass bool - }{ - { - name: "success", - malleate: func(msg *types.MsgUpgradeClient) {}, - expPass: true, - }, - { - name: "client id empty", - malleate: func(msg *types.MsgUpgradeClient) { - msg.ClientId = "" - }, - expPass: false, - }, - { - name: "invalid client id", - malleate: func(msg *types.MsgUpgradeClient) { - msg.ClientId = "invalid~chain/id" - }, - expPass: false, - }, - { - name: "unpacking clientstate fails", - malleate: func(msg *types.MsgUpgradeClient) { - msg.ClientState = nil - }, - expPass: false, - }, - { - name: "unpacking consensus state fails", - malleate: func(msg *types.MsgUpgradeClient) { - msg.ConsensusState = nil - }, - expPass: false, - }, - { - name: "client and consensus type does not match", - malleate: func(msg *types.MsgUpgradeClient) { - soloMachine := ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "solomachine", "", 2) - soloConsensus, err := types.PackConsensusState(soloMachine.ConsensusState()) - suite.Require().NoError(err) - msg.ConsensusState = soloConsensus - }, - expPass: false, - }, - { - name: "empty client proof", - malleate: func(msg *types.MsgUpgradeClient) { - msg.ProofUpgradeClient = nil - }, - expPass: false, - }, - { - name: "empty consensus state proof", - malleate: func(msg *types.MsgUpgradeClient) { - msg.ProofUpgradeConsensusState = nil - }, - expPass: false, - }, - { - name: "empty signer", - malleate: func(msg *types.MsgUpgradeClient) { - msg.Signer = " " - }, - expPass: false, - }, - } - - for _, tc := range cases { - tc := tc - - clientState := ibctmtypes.NewClientState(suite.chainA.ChainID, ibctesting.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) - consState := &ibctmtypes.ConsensusState{NextValidatorsHash: []byte("nextValsHash")} - msg, err := types.NewMsgUpgradeClient("testclientid", clientState, consState, []byte("proofUpgradeClient"), []byte("proofUpgradeConsState"), suite.chainA.SenderAccount.GetAddress()) - suite.Require().NoError(err) - - tc.malleate(msg) - err = msg.ValidateBasic() - if tc.expPass { - suite.Require().NoError(err, "valid case %s failed", tc.name) - } else { - suite.Require().Error(err, "invalid case %s passed", tc.name) - } - } -} - -// tests that different misbehaviours within MsgSubmitMisbehaviour can be marshaled -// and unmarshaled. -func (suite *TypesTestSuite) TestMarshalMsgSubmitMisbehaviour() { - var ( - msg *types.MsgSubmitMisbehaviour - err error - ) - - testCases := []struct { - name string - malleate func() - }{ - { - "solo machine client", func() { - soloMachine := ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "solomachine", "", 2) - msg, err = types.NewMsgSubmitMisbehaviour(soloMachine.ClientID, soloMachine.CreateMisbehaviour(), suite.chainA.SenderAccount.GetAddress()) - suite.Require().NoError(err) - }, - }, - { - "tendermint client", func() { - height := types.NewHeight(0, uint64(suite.chainA.CurrentHeader.Height)) - heightMinus1 := types.NewHeight(0, uint64(suite.chainA.CurrentHeader.Height)-1) - header1 := suite.chainA.CreateTMClientHeader(suite.chainA.ChainID, int64(height.RevisionHeight), heightMinus1, suite.chainA.CurrentHeader.Time, suite.chainA.Vals, suite.chainA.Vals, suite.chainA.Signers) - header2 := suite.chainA.CreateTMClientHeader(suite.chainA.ChainID, int64(height.RevisionHeight), heightMinus1, suite.chainA.CurrentHeader.Time.Add(time.Minute), suite.chainA.Vals, suite.chainA.Vals, suite.chainA.Signers) - - misbehaviour := ibctmtypes.NewMisbehaviour("tendermint", header1, header2) - msg, err = types.NewMsgSubmitMisbehaviour("tendermint", misbehaviour, suite.chainA.SenderAccount.GetAddress()) - suite.Require().NoError(err) - - }, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - suite.SetupTest() - - tc.malleate() - - cdc := suite.chainA.App.AppCodec() - - // marshal message - bz, err := cdc.MarshalJSON(msg) - suite.Require().NoError(err) - - // unmarshal message - newMsg := &types.MsgSubmitMisbehaviour{} - err = cdc.UnmarshalJSON(bz, newMsg) - suite.Require().NoError(err) - - suite.Require().True(proto.Equal(msg, newMsg)) - }) - } -} - -func (suite *TypesTestSuite) TestMsgSubmitMisbehaviour_ValidateBasic() { - var ( - msg = &types.MsgSubmitMisbehaviour{} - err error - ) - - cases := []struct { - name string - malleate func() - expPass bool - }{ - { - "invalid client-id", - func() { - msg.ClientId = "" - }, - false, - }, - { - "valid - tendermint misbehaviour", - func() { - height := types.NewHeight(0, uint64(suite.chainA.CurrentHeader.Height)) - heightMinus1 := types.NewHeight(0, uint64(suite.chainA.CurrentHeader.Height)-1) - header1 := suite.chainA.CreateTMClientHeader(suite.chainA.ChainID, int64(height.RevisionHeight), heightMinus1, suite.chainA.CurrentHeader.Time, suite.chainA.Vals, suite.chainA.Vals, suite.chainA.Signers) - header2 := suite.chainA.CreateTMClientHeader(suite.chainA.ChainID, int64(height.RevisionHeight), heightMinus1, suite.chainA.CurrentHeader.Time.Add(time.Minute), suite.chainA.Vals, suite.chainA.Vals, suite.chainA.Signers) - - misbehaviour := ibctmtypes.NewMisbehaviour("tendermint", header1, header2) - msg, err = types.NewMsgSubmitMisbehaviour("tendermint", misbehaviour, suite.chainA.SenderAccount.GetAddress()) - suite.Require().NoError(err) - }, - true, - }, - { - "invalid tendermint misbehaviour", - func() { - msg, err = types.NewMsgSubmitMisbehaviour("tendermint", &ibctmtypes.Misbehaviour{}, suite.chainA.SenderAccount.GetAddress()) - suite.Require().NoError(err) - }, - false, - }, - { - "failed to unpack misbehaviourt", - func() { - msg.Misbehaviour = nil - }, - false, - }, - { - "invalid signer", - func() { - msg.Signer = "" - }, - false, - }, - { - "valid - solomachine misbehaviour", - func() { - soloMachine := ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "solomachine", "", 2) - msg, err = types.NewMsgSubmitMisbehaviour(soloMachine.ClientID, soloMachine.CreateMisbehaviour(), suite.chainA.SenderAccount.GetAddress()) - suite.Require().NoError(err) - }, - true, - }, - { - "invalid solomachine misbehaviour", - func() { - msg, err = types.NewMsgSubmitMisbehaviour("solomachine", &solomachinetypes.Misbehaviour{}, suite.chainA.SenderAccount.GetAddress()) - suite.Require().NoError(err) - }, - false, - }, - { - "client-id mismatch", - func() { - soloMachineMisbehaviour := ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "solomachine", "", 2).CreateMisbehaviour() - msg, err = types.NewMsgSubmitMisbehaviour("external", soloMachineMisbehaviour, suite.chainA.SenderAccount.GetAddress()) - suite.Require().NoError(err) - }, - false, - }, - } - - for _, tc := range cases { - tc.malleate() - err = msg.ValidateBasic() - if tc.expPass { - suite.Require().NoError(err, tc.name) - } else { - suite.Require().Error(err, tc.name) - } - } -} diff --git a/x/ibc/core/02-client/types/params.go b/x/ibc/core/02-client/types/params.go deleted file mode 100644 index 6477e3f6f4f4..000000000000 --- a/x/ibc/core/02-client/types/params.go +++ /dev/null @@ -1,71 +0,0 @@ -package types - -import ( - "fmt" - "strings" - - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" -) - -var ( - // DefaultAllowedClients are "06-solomachine" and "07-tendermint" - DefaultAllowedClients = []string{exported.Solomachine, exported.Tendermint} - - // KeyAllowedClients is store's key for AllowedClients Params - KeyAllowedClients = []byte("AllowedClients") -) - -// ParamKeyTable type declaration for parameters -func ParamKeyTable() paramtypes.KeyTable { - return paramtypes.NewKeyTable().RegisterParamSet(&Params{}) -} - -// NewParams creates a new parameter configuration for the ibc transfer module -func NewParams(allowedClients ...string) Params { - return Params{ - AllowedClients: allowedClients, - } -} - -// DefaultParams is the default parameter configuration for the ibc-transfer module -func DefaultParams() Params { - return NewParams(DefaultAllowedClients...) -} - -// Validate all ibc-transfer module parameters -func (p Params) Validate() error { - return validateClients(p.AllowedClients) -} - -// ParamSetPairs implements params.ParamSet -func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { - return paramtypes.ParamSetPairs{ - paramtypes.NewParamSetPair(KeyAllowedClients, p.AllowedClients, validateClients), - } -} - -// IsAllowedClient checks if the given client type is registered on the allowlist. -func (p Params) IsAllowedClient(clientType string) bool { - for _, allowedClient := range p.AllowedClients { - if allowedClient == clientType { - return true - } - } - return false -} - -func validateClients(i interface{}) error { - clients, ok := i.([]string) - if !ok { - return fmt.Errorf("invalid parameter type: %T", i) - } - - for i, clientType := range clients { - if strings.TrimSpace(clientType) == "" { - return fmt.Errorf("client type %d cannot be blank", i) - } - } - - return nil -} diff --git a/x/ibc/core/02-client/types/params_test.go b/x/ibc/core/02-client/types/params_test.go deleted file mode 100644 index dac80a4b4217..000000000000 --- a/x/ibc/core/02-client/types/params_test.go +++ /dev/null @@ -1,30 +0,0 @@ -package types - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -func TestValidateParams(t *testing.T) { - testCases := []struct { - name string - params Params - expPass bool - }{ - {"default params", DefaultParams(), true}, - {"custom params", NewParams(exported.Tendermint), true}, - {"blank client", NewParams(" "), false}, - } - - for _, tc := range testCases { - err := tc.params.Validate() - if tc.expPass { - require.NoError(t, err, tc.name) - } else { - require.Error(t, err, tc.name) - } - } -} diff --git a/x/ibc/core/02-client/types/proposal.go b/x/ibc/core/02-client/types/proposal.go deleted file mode 100644 index ed67e45425c4..000000000000 --- a/x/ibc/core/02-client/types/proposal.go +++ /dev/null @@ -1,154 +0,0 @@ -package types - -import ( - "fmt" - - 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" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" -) - -const ( - // ProposalTypeClientUpdate defines the type for a ClientUpdateProposal - ProposalTypeClientUpdate = "ClientUpdate" - ProposalTypeUpgrade = "IBCUpgrade" -) - -var ( - _ govtypes.Content = &ClientUpdateProposal{} - _ govtypes.Content = &UpgradeProposal{} - _ codectypes.UnpackInterfacesMessage = &UpgradeProposal{} -) - -func init() { - govtypes.RegisterProposalType(ProposalTypeClientUpdate) - govtypes.RegisterProposalType(ProposalTypeUpgrade) -} - -// NewClientUpdateProposal creates a new client update proposal. -func NewClientUpdateProposal(title, description, subjectClientID, substituteClientID string, initialHeight Height) govtypes.Content { - return &ClientUpdateProposal{ - Title: title, - Description: description, - SubjectClientId: subjectClientID, - SubstituteClientId: substituteClientID, - InitialHeight: initialHeight, - } -} - -// GetTitle returns the title of a client update proposal. -func (cup *ClientUpdateProposal) GetTitle() string { return cup.Title } - -// GetDescription returns the description of a client update proposal. -func (cup *ClientUpdateProposal) GetDescription() string { return cup.Description } - -// ProposalRoute returns the routing key of a client update proposal. -func (cup *ClientUpdateProposal) ProposalRoute() string { return RouterKey } - -// ProposalType returns the type of a client update proposal. -func (cup *ClientUpdateProposal) ProposalType() string { return ProposalTypeClientUpdate } - -// ValidateBasic runs basic stateless validity checks -func (cup *ClientUpdateProposal) ValidateBasic() error { - err := govtypes.ValidateAbstract(cup) - if err != nil { - return err - } - - 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 - } - if _, _, err := ParseClientIdentifier(cup.SubstituteClientId); err != nil { - return err - } - - if cup.InitialHeight.IsZero() { - return sdkerrors.Wrap(ErrInvalidHeight, "initial height cannot be zero height") - } - - return nil -} - -// NewUpgradeProposal creates a new IBC breaking upgrade proposal. -func NewUpgradeProposal(title, description string, plan upgradetypes.Plan, upgradedClientState exported.ClientState) (govtypes.Content, error) { - any, err := PackClientState(upgradedClientState) - if err != nil { - return nil, err - } - - return &UpgradeProposal{ - Title: title, - Description: description, - Plan: plan, - UpgradedClientState: any, - }, nil -} - -// GetTitle returns the title of a upgrade proposal. -func (up *UpgradeProposal) GetTitle() string { return up.Title } - -// GetDescription returns the description of a upgrade proposal. -func (up *UpgradeProposal) GetDescription() string { return up.Description } - -// ProposalRoute returns the routing key of a upgrade proposal. -func (up *UpgradeProposal) ProposalRoute() string { return RouterKey } - -// ProposalType returns the upgrade proposal type. -func (up *UpgradeProposal) ProposalType() string { return ProposalTypeUpgrade } - -// ValidateBasic runs basic stateless validity checks -func (up *UpgradeProposal) ValidateBasic() error { - if err := govtypes.ValidateAbstract(up); err != nil { - return err - } - - if err := up.Plan.ValidateBasic(); err != nil { - return err - } - - if up.Plan.Time.Unix() > 0 { - return sdkerrors.Wrap(ErrInvalidUpgradeProposal, "IBC chain upgrades must only set height") - } - - if up.Plan.Height <= 0 { - return sdkerrors.Wrap(ErrInvalidUpgradeProposal, "IBC chain upgrades must set a positive height") - } - - if up.UpgradedClientState == nil { - return sdkerrors.Wrap(ErrInvalidUpgradeProposal, "upgraded client state cannot be nil") - } - - _, err := UnpackClientState(up.UpgradedClientState) - if err != nil { - return sdkerrors.Wrap(err, "failed to unpack upgraded client state") - } - - return nil -} - -// String returns the string representation of the UpgradeProposal. -func (up UpgradeProposal) String() string { - var upgradedClientStr string - upgradedClient, err := UnpackClientState(up.UpgradedClientState) - if err != nil { - upgradedClientStr = "invalid IBC Client State" - } else { - upgradedClientStr = upgradedClient.String() - } - - return fmt.Sprintf(`IBC Upgrade Proposal - Title: %s - Description: %s - %s - Upgraded IBC Client: %s`, up.Title, up.Description, up.Plan, upgradedClientStr) -} - -// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces -func (up UpgradeProposal) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { - return unpacker.UnpackAny(up.UpgradedClientState, new(exported.ClientState)) -} diff --git a/x/ibc/core/02-client/types/proposal_test.go b/x/ibc/core/02-client/types/proposal_test.go deleted file mode 100644 index a7337081abd3..000000000000 --- a/x/ibc/core/02-client/types/proposal_test.go +++ /dev/null @@ -1,234 +0,0 @@ -package types_test - -import ( - "fmt" - "time" - - "github.com/cosmos/cosmos-sdk/codec" - 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" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" - upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" -) - -func (suite *TypesTestSuite) TestValidateBasic() { - 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 - proposal govtypes.Content - expPass bool - }{ - { - "success", - types.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, subject, substitute, initialHeight), - true, - }, - { - "fails validate abstract - empty title", - 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, - }, - { - "invalid substitute clientID", - types.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, subject, ibctesting.InvalidID, initialHeight), - false, - }, - { - "initial height is zero", - types.NewClientUpdateProposal(ibctesting.Title, ibctesting.Description, subject, substitute, types.ZeroHeight()), - false, - }, - } - - for _, tc := range testCases { - - err := tc.proposal.ValidateBasic() - - if tc.expPass { - suite.Require().NoError(err, tc.name) - } else { - suite.Require().Error(err, tc.name) - } - } -} - -// tests a client update proposal can be marshaled and unmarshaled -func (suite *TypesTestSuite) TestMarshalClientUpdateProposalProposal() { - // create proposal - proposal := types.NewClientUpdateProposal("update IBC client", "description", "subject", "substitute", types.NewHeight(1, 0)) - - // create codec - ir := codectypes.NewInterfaceRegistry() - types.RegisterInterfaces(ir) - govtypes.RegisterInterfaces(ir) - cdc := codec.NewProtoCodec(ir) - - // marshal message - content := proposal.(*types.ClientUpdateProposal) - bz, err := cdc.MarshalJSON(content) - suite.Require().NoError(err) - - // unmarshal proposal - newProposal := &types.ClientUpdateProposal{} - err = cdc.UnmarshalJSON(bz, newProposal) - suite.Require().NoError(err) -} - -func (suite *TypesTestSuite) TestUpgradeProposalValidateBasic() { - var ( - proposal govtypes.Content - err error - ) - - client, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - cs := suite.chainA.GetClientState(client) - plan := upgradetypes.Plan{ - Name: "ibc upgrade", - Height: 1000, - } - - testCases := []struct { - name string - malleate func() - expPass bool - }{ - { - "success", func() { - proposal, err = types.NewUpgradeProposal(ibctesting.Title, ibctesting.Description, plan, cs) - suite.Require().NoError(err) - }, true, - }, - { - "fails validate abstract - empty title", func() { - proposal, err = types.NewUpgradeProposal("", ibctesting.Description, plan, cs) - suite.Require().NoError(err) - - }, false, - }, - { - "fails plan validate basic, height and time is 0", func() { - invalidPlan := upgradetypes.Plan{Name: "ibc upgrade"} - proposal, err = types.NewUpgradeProposal(ibctesting.Title, ibctesting.Description, invalidPlan, cs) - suite.Require().NoError(err) - }, false, - }, - { - "plan height is zero", func() { - invalidPlan := upgradetypes.Plan{Name: "ibc upgrade", Height: 0} - proposal, err = types.NewUpgradeProposal(ibctesting.Title, ibctesting.Description, invalidPlan, cs) - suite.Require().NoError(err) - }, false, - }, - { - "plan time is not set to 0", func() { - invalidPlan := upgradetypes.Plan{Name: "ibc upgrade", Time: time.Now()} - proposal, err = types.NewUpgradeProposal(ibctesting.Title, ibctesting.Description, invalidPlan, cs) - suite.Require().NoError(err) - }, false, - }, - { - "client state is nil", func() { - proposal = &types.UpgradeProposal{ - Title: ibctesting.Title, - Description: ibctesting.Description, - Plan: plan, - UpgradedClientState: nil, - } - }, false, - }, - { - "failed to unpack client state", func() { - any, err := types.PackConsensusState(&ibctmtypes.ConsensusState{}) - suite.Require().NoError(err) - - proposal = &types.UpgradeProposal{ - Title: ibctesting.Title, - Description: ibctesting.Description, - Plan: plan, - UpgradedClientState: any, - } - }, false, - }, - } - - for _, tc := range testCases { - - tc.malleate() - - err := proposal.ValidateBasic() - - if tc.expPass { - suite.Require().NoError(err, tc.name) - } else { - suite.Require().Error(err, tc.name) - } - } -} - -// tests an upgrade proposal can be marshaled and unmarshaled, and the -// client state can be unpacked -func (suite *TypesTestSuite) TestMarshalUpgradeProposal() { - // create proposal - plan := upgradetypes.Plan{ - Name: "upgrade ibc", - Height: 1000, - } - content, err := types.NewUpgradeProposal("title", "description", plan, &ibctmtypes.ClientState{}) - suite.Require().NoError(err) - - up, ok := content.(*types.UpgradeProposal) - suite.Require().True(ok) - - // create codec - ir := codectypes.NewInterfaceRegistry() - types.RegisterInterfaces(ir) - govtypes.RegisterInterfaces(ir) - ibctmtypes.RegisterInterfaces(ir) - cdc := codec.NewProtoCodec(ir) - - // marshal message - bz, err := cdc.MarshalJSON(up) - suite.Require().NoError(err) - - // unmarshal proposal - newUp := &types.UpgradeProposal{} - err = cdc.UnmarshalJSON(bz, newUp) - suite.Require().NoError(err) - - // unpack client state - _, err = types.UnpackClientState(newUp.UpgradedClientState) - suite.Require().NoError(err) - -} - -func (suite *TypesTestSuite) TestUpgradeString() { - plan := upgradetypes.Plan{ - Name: "ibc upgrade", - Info: "https://foo.bar/baz", - Height: 1000, - } - - proposal, err := types.NewUpgradeProposal(ibctesting.Title, ibctesting.Description, plan, &ibctmtypes.ClientState{}) - suite.Require().NoError(err) - - expect := fmt.Sprintf("IBC Upgrade Proposal\n Title: title\n Description: description\n Upgrade Plan\n Name: ibc upgrade\n Height: 1000\n Info: https://foo.bar/baz.\n Upgraded IBC Client: %s", &ibctmtypes.ClientState{}) - - suite.Require().Equal(expect, proposal.String()) -} diff --git a/x/ibc/core/02-client/types/query.go b/x/ibc/core/02-client/types/query.go deleted file mode 100644 index c46bbfcfe778..000000000000 --- a/x/ibc/core/02-client/types/query.go +++ /dev/null @@ -1,65 +0,0 @@ -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, -) *QueryClientStateResponse { - return &QueryClientStateResponse{ - ClientState: clientStateAny, - Proof: proof, - ProofHeight: height, - } -} - -// 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, -) *QueryConsensusStateResponse { - return &QueryConsensusStateResponse{ - ConsensusState: consensusStateAny, - Proof: proof, - 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/02-client/types/query.pb.go b/x/ibc/core/02-client/types/query.pb.go deleted file mode 100644 index 27c5cb884140..000000000000 --- a/x/ibc/core/02-client/types/query.pb.go +++ /dev/null @@ -1,3118 +0,0 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: ibc/core/client/v1/query.proto - -package types - -import ( - context "context" - fmt "fmt" - types "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" - _ "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 - -// QueryClientStateRequest is the request type for the Query/ClientState RPC -// method -type QueryClientStateRequest struct { - // client state unique identifier - ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"` -} - -func (m *QueryClientStateRequest) Reset() { *m = QueryClientStateRequest{} } -func (m *QueryClientStateRequest) String() string { return proto.CompactTextString(m) } -func (*QueryClientStateRequest) ProtoMessage() {} -func (*QueryClientStateRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_dc42cdfd1d52d76e, []int{0} -} -func (m *QueryClientStateRequest) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryClientStateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryClientStateRequest.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 *QueryClientStateRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryClientStateRequest.Merge(m, src) -} -func (m *QueryClientStateRequest) XXX_Size() int { - return m.Size() -} -func (m *QueryClientStateRequest) XXX_DiscardUnknown() { - xxx_messageInfo_QueryClientStateRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryClientStateRequest proto.InternalMessageInfo - -func (m *QueryClientStateRequest) GetClientId() string { - if m != nil { - return m.ClientId - } - return "" -} - -// 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. -type QueryClientStateResponse struct { - // client state associated with the request identifier - ClientState *types.Any `protobuf:"bytes,1,opt,name=client_state,json=clientState,proto3" json:"client_state,omitempty"` - // merkle proof of existence - Proof []byte `protobuf:"bytes,2,opt,name=proof,proto3" json:"proof,omitempty"` - // height at which the proof was retrieved - ProofHeight Height `protobuf:"bytes,3,opt,name=proof_height,json=proofHeight,proto3" json:"proof_height"` -} - -func (m *QueryClientStateResponse) Reset() { *m = QueryClientStateResponse{} } -func (m *QueryClientStateResponse) String() string { return proto.CompactTextString(m) } -func (*QueryClientStateResponse) ProtoMessage() {} -func (*QueryClientStateResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_dc42cdfd1d52d76e, []int{1} -} -func (m *QueryClientStateResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryClientStateResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryClientStateResponse.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 *QueryClientStateResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryClientStateResponse.Merge(m, src) -} -func (m *QueryClientStateResponse) XXX_Size() int { - return m.Size() -} -func (m *QueryClientStateResponse) XXX_DiscardUnknown() { - xxx_messageInfo_QueryClientStateResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryClientStateResponse proto.InternalMessageInfo - -func (m *QueryClientStateResponse) GetClientState() *types.Any { - if m != nil { - return m.ClientState - } - return nil -} - -func (m *QueryClientStateResponse) GetProof() []byte { - if m != nil { - return m.Proof - } - return nil -} - -func (m *QueryClientStateResponse) GetProofHeight() Height { - if m != nil { - return m.ProofHeight - } - return Height{} -} - -// QueryClientStatesRequest is the request type for the Query/ClientStates RPC -// method -type QueryClientStatesRequest struct { - // pagination request - Pagination *query.PageRequest `protobuf:"bytes,1,opt,name=pagination,proto3" json:"pagination,omitempty"` -} - -func (m *QueryClientStatesRequest) Reset() { *m = QueryClientStatesRequest{} } -func (m *QueryClientStatesRequest) String() string { return proto.CompactTextString(m) } -func (*QueryClientStatesRequest) ProtoMessage() {} -func (*QueryClientStatesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_dc42cdfd1d52d76e, []int{2} -} -func (m *QueryClientStatesRequest) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryClientStatesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryClientStatesRequest.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 *QueryClientStatesRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryClientStatesRequest.Merge(m, src) -} -func (m *QueryClientStatesRequest) XXX_Size() int { - return m.Size() -} -func (m *QueryClientStatesRequest) XXX_DiscardUnknown() { - xxx_messageInfo_QueryClientStatesRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryClientStatesRequest proto.InternalMessageInfo - -func (m *QueryClientStatesRequest) GetPagination() *query.PageRequest { - if m != nil { - return m.Pagination - } - return nil -} - -// QueryClientStatesResponse is the response type for the Query/ClientStates RPC -// method. -type QueryClientStatesResponse struct { - // list of stored ClientStates of the chain. - ClientStates IdentifiedClientStates `protobuf:"bytes,1,rep,name=client_states,json=clientStates,proto3,castrepeated=IdentifiedClientStates" json:"client_states"` - // pagination response - Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` -} - -func (m *QueryClientStatesResponse) Reset() { *m = QueryClientStatesResponse{} } -func (m *QueryClientStatesResponse) String() string { return proto.CompactTextString(m) } -func (*QueryClientStatesResponse) ProtoMessage() {} -func (*QueryClientStatesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_dc42cdfd1d52d76e, []int{3} -} -func (m *QueryClientStatesResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryClientStatesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryClientStatesResponse.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 *QueryClientStatesResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryClientStatesResponse.Merge(m, src) -} -func (m *QueryClientStatesResponse) XXX_Size() int { - return m.Size() -} -func (m *QueryClientStatesResponse) XXX_DiscardUnknown() { - xxx_messageInfo_QueryClientStatesResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryClientStatesResponse proto.InternalMessageInfo - -func (m *QueryClientStatesResponse) GetClientStates() IdentifiedClientStates { - if m != nil { - return m.ClientStates - } - return nil -} - -func (m *QueryClientStatesResponse) GetPagination() *query.PageResponse { - if m != nil { - return m.Pagination - } - return nil -} - -// 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. -type QueryConsensusStateRequest struct { - // client identifier - ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"` - // consensus state revision number - RevisionNumber uint64 `protobuf:"varint,2,opt,name=revision_number,json=revisionNumber,proto3" json:"revision_number,omitempty"` - // consensus state revision height - RevisionHeight uint64 `protobuf:"varint,3,opt,name=revision_height,json=revisionHeight,proto3" json:"revision_height,omitempty"` - // latest_height overrrides the height field and queries the latest stored - // ConsensusState - LatestHeight bool `protobuf:"varint,4,opt,name=latest_height,json=latestHeight,proto3" json:"latest_height,omitempty"` -} - -func (m *QueryConsensusStateRequest) Reset() { *m = QueryConsensusStateRequest{} } -func (m *QueryConsensusStateRequest) String() string { return proto.CompactTextString(m) } -func (*QueryConsensusStateRequest) ProtoMessage() {} -func (*QueryConsensusStateRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_dc42cdfd1d52d76e, []int{4} -} -func (m *QueryConsensusStateRequest) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryConsensusStateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryConsensusStateRequest.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 *QueryConsensusStateRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryConsensusStateRequest.Merge(m, src) -} -func (m *QueryConsensusStateRequest) XXX_Size() int { - return m.Size() -} -func (m *QueryConsensusStateRequest) XXX_DiscardUnknown() { - xxx_messageInfo_QueryConsensusStateRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryConsensusStateRequest proto.InternalMessageInfo - -func (m *QueryConsensusStateRequest) GetClientId() string { - if m != nil { - return m.ClientId - } - return "" -} - -func (m *QueryConsensusStateRequest) GetRevisionNumber() uint64 { - if m != nil { - return m.RevisionNumber - } - return 0 -} - -func (m *QueryConsensusStateRequest) GetRevisionHeight() uint64 { - if m != nil { - return m.RevisionHeight - } - return 0 -} - -func (m *QueryConsensusStateRequest) GetLatestHeight() bool { - if m != nil { - return m.LatestHeight - } - return false -} - -// QueryConsensusStateResponse is the response type for the Query/ConsensusState -// RPC method -type QueryConsensusStateResponse struct { - // consensus state associated with the client identifier at the given height - ConsensusState *types.Any `protobuf:"bytes,1,opt,name=consensus_state,json=consensusState,proto3" json:"consensus_state,omitempty"` - // merkle proof of existence - Proof []byte `protobuf:"bytes,2,opt,name=proof,proto3" json:"proof,omitempty"` - // height at which the proof was retrieved - ProofHeight Height `protobuf:"bytes,3,opt,name=proof_height,json=proofHeight,proto3" json:"proof_height"` -} - -func (m *QueryConsensusStateResponse) Reset() { *m = QueryConsensusStateResponse{} } -func (m *QueryConsensusStateResponse) String() string { return proto.CompactTextString(m) } -func (*QueryConsensusStateResponse) ProtoMessage() {} -func (*QueryConsensusStateResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_dc42cdfd1d52d76e, []int{5} -} -func (m *QueryConsensusStateResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryConsensusStateResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryConsensusStateResponse.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 *QueryConsensusStateResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryConsensusStateResponse.Merge(m, src) -} -func (m *QueryConsensusStateResponse) XXX_Size() int { - return m.Size() -} -func (m *QueryConsensusStateResponse) XXX_DiscardUnknown() { - xxx_messageInfo_QueryConsensusStateResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryConsensusStateResponse proto.InternalMessageInfo - -func (m *QueryConsensusStateResponse) GetConsensusState() *types.Any { - if m != nil { - return m.ConsensusState - } - return nil -} - -func (m *QueryConsensusStateResponse) GetProof() []byte { - if m != nil { - return m.Proof - } - return nil -} - -func (m *QueryConsensusStateResponse) GetProofHeight() Height { - if m != nil { - return m.ProofHeight - } - return Height{} -} - -// QueryConsensusStatesRequest is the request type for the Query/ConsensusStates -// RPC method. -type QueryConsensusStatesRequest struct { - // client identifier - ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"` - // pagination request - Pagination *query.PageRequest `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` -} - -func (m *QueryConsensusStatesRequest) Reset() { *m = QueryConsensusStatesRequest{} } -func (m *QueryConsensusStatesRequest) String() string { return proto.CompactTextString(m) } -func (*QueryConsensusStatesRequest) ProtoMessage() {} -func (*QueryConsensusStatesRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_dc42cdfd1d52d76e, []int{6} -} -func (m *QueryConsensusStatesRequest) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryConsensusStatesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryConsensusStatesRequest.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 *QueryConsensusStatesRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryConsensusStatesRequest.Merge(m, src) -} -func (m *QueryConsensusStatesRequest) XXX_Size() int { - return m.Size() -} -func (m *QueryConsensusStatesRequest) XXX_DiscardUnknown() { - xxx_messageInfo_QueryConsensusStatesRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryConsensusStatesRequest proto.InternalMessageInfo - -func (m *QueryConsensusStatesRequest) GetClientId() string { - if m != nil { - return m.ClientId - } - return "" -} - -func (m *QueryConsensusStatesRequest) GetPagination() *query.PageRequest { - if m != nil { - return m.Pagination - } - return nil -} - -// QueryConsensusStatesResponse is the response type for the -// Query/ConsensusStates RPC method -type QueryConsensusStatesResponse struct { - // consensus states associated with the identifier - ConsensusStates []ConsensusStateWithHeight `protobuf:"bytes,1,rep,name=consensus_states,json=consensusStates,proto3" json:"consensus_states"` - // pagination response - Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` -} - -func (m *QueryConsensusStatesResponse) Reset() { *m = QueryConsensusStatesResponse{} } -func (m *QueryConsensusStatesResponse) String() string { return proto.CompactTextString(m) } -func (*QueryConsensusStatesResponse) ProtoMessage() {} -func (*QueryConsensusStatesResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_dc42cdfd1d52d76e, []int{7} -} -func (m *QueryConsensusStatesResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryConsensusStatesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryConsensusStatesResponse.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 *QueryConsensusStatesResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryConsensusStatesResponse.Merge(m, src) -} -func (m *QueryConsensusStatesResponse) XXX_Size() int { - return m.Size() -} -func (m *QueryConsensusStatesResponse) XXX_DiscardUnknown() { - xxx_messageInfo_QueryConsensusStatesResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryConsensusStatesResponse proto.InternalMessageInfo - -func (m *QueryConsensusStatesResponse) GetConsensusStates() []ConsensusStateWithHeight { - if m != nil { - return m.ConsensusStates - } - return nil -} - -func (m *QueryConsensusStatesResponse) GetPagination() *query.PageResponse { - if m != nil { - return m.Pagination - } - return nil -} - -// QueryClientParamsRequest is the request type for the Query/ClientParams RPC method. -type QueryClientParamsRequest struct { -} - -func (m *QueryClientParamsRequest) Reset() { *m = QueryClientParamsRequest{} } -func (m *QueryClientParamsRequest) String() string { return proto.CompactTextString(m) } -func (*QueryClientParamsRequest) ProtoMessage() {} -func (*QueryClientParamsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_dc42cdfd1d52d76e, []int{8} -} -func (m *QueryClientParamsRequest) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryClientParamsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryClientParamsRequest.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 *QueryClientParamsRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryClientParamsRequest.Merge(m, src) -} -func (m *QueryClientParamsRequest) XXX_Size() int { - return m.Size() -} -func (m *QueryClientParamsRequest) XXX_DiscardUnknown() { - xxx_messageInfo_QueryClientParamsRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryClientParamsRequest proto.InternalMessageInfo - -// QueryClientParamsResponse is the response type for the Query/ClientParams RPC method. -type QueryClientParamsResponse struct { - // params defines the parameters of the module. - Params *Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params,omitempty"` -} - -func (m *QueryClientParamsResponse) Reset() { *m = QueryClientParamsResponse{} } -func (m *QueryClientParamsResponse) String() string { return proto.CompactTextString(m) } -func (*QueryClientParamsResponse) ProtoMessage() {} -func (*QueryClientParamsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_dc42cdfd1d52d76e, []int{9} -} -func (m *QueryClientParamsResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryClientParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryClientParamsResponse.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 *QueryClientParamsResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryClientParamsResponse.Merge(m, src) -} -func (m *QueryClientParamsResponse) XXX_Size() int { - return m.Size() -} -func (m *QueryClientParamsResponse) XXX_DiscardUnknown() { - xxx_messageInfo_QueryClientParamsResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryClientParamsResponse proto.InternalMessageInfo - -func (m *QueryClientParamsResponse) GetParams() *Params { - if m != nil { - return m.Params - } - return nil -} - -// QueryUpgradedClientStateRequest is the request type for the Query/UpgradedClientState RPC -// method -type QueryUpgradedClientStateRequest struct { - // client state unique identifier - ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"` - // plan height of the current chain must be sent in request - // as this is the height under which upgraded client state is stored - PlanHeight int64 `protobuf:"varint,2,opt,name=plan_height,json=planHeight,proto3" json:"plan_height,omitempty"` -} - -func (m *QueryUpgradedClientStateRequest) Reset() { *m = QueryUpgradedClientStateRequest{} } -func (m *QueryUpgradedClientStateRequest) String() string { return proto.CompactTextString(m) } -func (*QueryUpgradedClientStateRequest) ProtoMessage() {} -func (*QueryUpgradedClientStateRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_dc42cdfd1d52d76e, []int{10} -} -func (m *QueryUpgradedClientStateRequest) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryUpgradedClientStateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryUpgradedClientStateRequest.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 *QueryUpgradedClientStateRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryUpgradedClientStateRequest.Merge(m, src) -} -func (m *QueryUpgradedClientStateRequest) XXX_Size() int { - return m.Size() -} -func (m *QueryUpgradedClientStateRequest) XXX_DiscardUnknown() { - xxx_messageInfo_QueryUpgradedClientStateRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryUpgradedClientStateRequest proto.InternalMessageInfo - -func (m *QueryUpgradedClientStateRequest) GetClientId() string { - if m != nil { - return m.ClientId - } - return "" -} - -func (m *QueryUpgradedClientStateRequest) GetPlanHeight() int64 { - if m != nil { - return m.PlanHeight - } - return 0 -} - -// QueryUpgradedClientStateResponse is the response type for the Query/UpgradedClientState RPC -// method. -type QueryUpgradedClientStateResponse struct { - // client state associated with the request identifier - UpgradedClientState *types.Any `protobuf:"bytes,1,opt,name=upgraded_client_state,json=upgradedClientState,proto3" json:"upgraded_client_state,omitempty"` -} - -func (m *QueryUpgradedClientStateResponse) Reset() { *m = QueryUpgradedClientStateResponse{} } -func (m *QueryUpgradedClientStateResponse) String() string { return proto.CompactTextString(m) } -func (*QueryUpgradedClientStateResponse) ProtoMessage() {} -func (*QueryUpgradedClientStateResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_dc42cdfd1d52d76e, []int{11} -} -func (m *QueryUpgradedClientStateResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryUpgradedClientStateResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryUpgradedClientStateResponse.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 *QueryUpgradedClientStateResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryUpgradedClientStateResponse.Merge(m, src) -} -func (m *QueryUpgradedClientStateResponse) XXX_Size() int { - return m.Size() -} -func (m *QueryUpgradedClientStateResponse) XXX_DiscardUnknown() { - xxx_messageInfo_QueryUpgradedClientStateResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryUpgradedClientStateResponse proto.InternalMessageInfo - -func (m *QueryUpgradedClientStateResponse) GetUpgradedClientState() *types.Any { - if m != nil { - return m.UpgradedClientState - } - return nil -} - -func init() { - proto.RegisterType((*QueryClientStateRequest)(nil), "ibc.core.client.v1.QueryClientStateRequest") - proto.RegisterType((*QueryClientStateResponse)(nil), "ibc.core.client.v1.QueryClientStateResponse") - proto.RegisterType((*QueryClientStatesRequest)(nil), "ibc.core.client.v1.QueryClientStatesRequest") - proto.RegisterType((*QueryClientStatesResponse)(nil), "ibc.core.client.v1.QueryClientStatesResponse") - proto.RegisterType((*QueryConsensusStateRequest)(nil), "ibc.core.client.v1.QueryConsensusStateRequest") - proto.RegisterType((*QueryConsensusStateResponse)(nil), "ibc.core.client.v1.QueryConsensusStateResponse") - proto.RegisterType((*QueryConsensusStatesRequest)(nil), "ibc.core.client.v1.QueryConsensusStatesRequest") - proto.RegisterType((*QueryConsensusStatesResponse)(nil), "ibc.core.client.v1.QueryConsensusStatesResponse") - proto.RegisterType((*QueryClientParamsRequest)(nil), "ibc.core.client.v1.QueryClientParamsRequest") - proto.RegisterType((*QueryClientParamsResponse)(nil), "ibc.core.client.v1.QueryClientParamsResponse") - proto.RegisterType((*QueryUpgradedClientStateRequest)(nil), "ibc.core.client.v1.QueryUpgradedClientStateRequest") - proto.RegisterType((*QueryUpgradedClientStateResponse)(nil), "ibc.core.client.v1.QueryUpgradedClientStateResponse") -} - -func init() { proto.RegisterFile("ibc/core/client/v1/query.proto", fileDescriptor_dc42cdfd1d52d76e) } - -var fileDescriptor_dc42cdfd1d52d76e = []byte{ - // 909 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0x4d, 0x8f, 0xdb, 0x44, - 0x18, 0xce, 0xec, 0x6e, 0xab, 0xed, 0x24, 0xdd, 0xa0, 0xe9, 0x02, 0xa9, 0xbb, 0x72, 0x22, 0x23, - 0xb5, 0x01, 0xba, 0x33, 0x4d, 0x5a, 0xba, 0x08, 0xa9, 0x48, 0x6c, 0xa5, 0xd2, 0x5e, 0xa0, 0x35, - 0x42, 0x48, 0x48, 0x28, 0xb2, 0x9d, 0x59, 0xc7, 0x6a, 0xe2, 0xf1, 0x7a, 0xec, 0x88, 0x55, 0xb5, - 0x97, 0xfe, 0x01, 0x90, 0x38, 0x72, 0xe5, 0xc4, 0x01, 0x21, 0x71, 0xe0, 0x86, 0x38, 0xa1, 0x1e, - 0x2b, 0xc1, 0x81, 0x13, 0xa0, 0xdd, 0xfe, 0x10, 0xe4, 0x99, 0x71, 0xd6, 0x93, 0x38, 0x5a, 0xb3, - 0xa2, 0xa7, 0xd8, 0xef, 0xe7, 0xf3, 0x3e, 0xef, 0x87, 0x03, 0xcd, 0xc0, 0xf5, 0x88, 0xc7, 0x62, - 0x4a, 0xbc, 0x71, 0x40, 0xc3, 0x84, 0x4c, 0x7b, 0x64, 0x3f, 0xa5, 0xf1, 0x01, 0x8e, 0x62, 0x96, - 0x30, 0x84, 0x02, 0xd7, 0xc3, 0x99, 0x1e, 0x4b, 0x3d, 0x9e, 0xf6, 0x8c, 0xb7, 0x3c, 0xc6, 0x27, - 0x8c, 0x13, 0xd7, 0xe1, 0x54, 0x1a, 0x93, 0x69, 0xcf, 0xa5, 0x89, 0xd3, 0x23, 0x91, 0xe3, 0x07, - 0xa1, 0x93, 0x04, 0x2c, 0x94, 0xfe, 0x46, 0xbb, 0x24, 0xbe, 0x8a, 0x24, 0x0d, 0x2e, 0xfb, 0x8c, - 0xf9, 0x63, 0x4a, 0xc4, 0x9b, 0x9b, 0xee, 0x11, 0x27, 0x54, 0xb9, 0x8d, 0x2d, 0xa5, 0x72, 0xa2, - 0x80, 0x38, 0x61, 0xc8, 0x12, 0x11, 0x98, 0x2b, 0xed, 0xa6, 0xcf, 0x7c, 0x26, 0x1e, 0x49, 0xf6, - 0x24, 0xa5, 0xd6, 0x6d, 0xf8, 0xfa, 0xa3, 0x0c, 0xd1, 0x5d, 0x91, 0xe3, 0x93, 0xc4, 0x49, 0xa8, - 0x4d, 0xf7, 0x53, 0xca, 0x13, 0x74, 0x05, 0x5e, 0x90, 0x99, 0x07, 0xc1, 0xb0, 0x05, 0x3a, 0xa0, - 0x7b, 0xc1, 0x5e, 0x97, 0x82, 0x07, 0x43, 0xeb, 0x07, 0x00, 0x5b, 0x8b, 0x8e, 0x3c, 0x62, 0x21, - 0xa7, 0x68, 0x07, 0x36, 0x94, 0x27, 0xcf, 0xe4, 0xc2, 0xb9, 0xde, 0xdf, 0xc4, 0x12, 0x1f, 0xce, - 0xa1, 0xe3, 0x0f, 0xc2, 0x03, 0xbb, 0xee, 0x9d, 0x04, 0x40, 0x9b, 0xf0, 0x5c, 0x14, 0x33, 0xb6, - 0xd7, 0x5a, 0xe9, 0x80, 0x6e, 0xc3, 0x96, 0x2f, 0xe8, 0x2e, 0x6c, 0x88, 0x87, 0xc1, 0x88, 0x06, - 0xfe, 0x28, 0x69, 0xad, 0x8a, 0x70, 0x06, 0x5e, 0xa4, 0x1a, 0xdf, 0x17, 0x16, 0xbb, 0x6b, 0xcf, - 0xfe, 0x6a, 0xd7, 0xec, 0xba, 0xf0, 0x92, 0x22, 0xcb, 0x5d, 0xc4, 0xcb, 0xf3, 0x4a, 0xef, 0x41, - 0x78, 0xd2, 0x08, 0x85, 0xf6, 0x2a, 0x96, 0x5d, 0xc3, 0x59, 0xd7, 0xb0, 0x6c, 0xb1, 0xea, 0x1a, - 0x7e, 0xe8, 0xf8, 0x39, 0x4b, 0x76, 0xc1, 0xd3, 0xfa, 0x03, 0xc0, 0xcb, 0x25, 0x49, 0x14, 0x2b, - 0x21, 0xbc, 0x58, 0x64, 0x85, 0xb7, 0x40, 0x67, 0xb5, 0x5b, 0xef, 0xbf, 0x59, 0x56, 0xc7, 0x83, - 0x21, 0x0d, 0x93, 0x60, 0x2f, 0xa0, 0xc3, 0x42, 0xa8, 0x5d, 0x33, 0x2b, 0xeb, 0xfb, 0xbf, 0xdb, - 0xaf, 0x95, 0xaa, 0xb9, 0xdd, 0x28, 0x70, 0xc9, 0xd1, 0x87, 0x5a, 0x55, 0x2b, 0xa2, 0xaa, 0x6b, - 0xa7, 0x56, 0x25, 0xc1, 0x6a, 0x65, 0xfd, 0x08, 0xa0, 0x21, 0xcb, 0xca, 0x54, 0x21, 0x4f, 0x79, - 0xe5, 0x39, 0x41, 0xd7, 0x60, 0x33, 0xa6, 0xd3, 0x80, 0x07, 0x2c, 0x1c, 0x84, 0xe9, 0xc4, 0xa5, - 0xb1, 0x40, 0xb2, 0x66, 0x6f, 0xe4, 0xe2, 0x8f, 0x84, 0x54, 0x33, 0x2c, 0xf4, 0xb9, 0x60, 0x28, - 0x1b, 0x89, 0xde, 0x80, 0x17, 0xc7, 0x59, 0x7d, 0x49, 0x6e, 0xb6, 0xd6, 0x01, 0xdd, 0x75, 0xbb, - 0x21, 0x85, 0xaa, 0xdb, 0x3f, 0x03, 0x78, 0xa5, 0x14, 0xb2, 0xea, 0xc5, 0x1d, 0xd8, 0xf4, 0x72, - 0x4d, 0x85, 0x21, 0xdd, 0xf0, 0xb4, 0x30, 0x2f, 0x73, 0x4e, 0x9f, 0x96, 0x23, 0xe7, 0x95, 0xd8, - 0xbe, 0x57, 0xd2, 0xf2, 0xb3, 0x0c, 0xf2, 0x6f, 0x00, 0x6e, 0x95, 0x83, 0x50, 0xfc, 0x7d, 0x01, - 0x5f, 0x99, 0xe3, 0x2f, 0x1f, 0xe7, 0xeb, 0x65, 0xe5, 0xea, 0x61, 0x3e, 0x0b, 0x92, 0x91, 0x46, - 0x40, 0x53, 0xa7, 0xf7, 0x7f, 0x1c, 0x5d, 0x43, 0xdb, 0xfa, 0x87, 0x4e, 0xec, 0x4c, 0x72, 0x26, - 0xad, 0x8f, 0xb5, 0x65, 0xcd, 0x75, 0xaa, 0xc0, 0x3e, 0x3c, 0x1f, 0x09, 0x89, 0x9a, 0x8b, 0xd2, - 0x2e, 0x2a, 0x1f, 0x65, 0x69, 0x0d, 0x60, 0x5b, 0x04, 0xfc, 0x34, 0xf2, 0x63, 0x67, 0xa8, 0xed, - 0x66, 0xa5, 0xee, 0xb5, 0x61, 0x3d, 0x1a, 0x3b, 0xb3, 0xf1, 0xcf, 0xca, 0x5e, 0xb5, 0x61, 0x26, - 0x52, 0xb3, 0x31, 0x86, 0x9d, 0xe5, 0x09, 0x14, 0xf0, 0xfb, 0xf0, 0xd5, 0x54, 0xa9, 0x07, 0x95, - 0x8f, 0xf0, 0xa5, 0x74, 0x31, 0x62, 0xff, 0x97, 0x75, 0x78, 0x4e, 0xa4, 0x43, 0xdf, 0x01, 0x58, - 0x2f, 0x68, 0xd0, 0xdb, 0x65, 0x64, 0x2c, 0xf9, 0x8c, 0x18, 0xd7, 0xab, 0x19, 0x4b, 0xf8, 0xd6, - 0x7b, 0x4f, 0x7f, 0x7f, 0xf1, 0xcd, 0xca, 0x2d, 0xd4, 0x27, 0x8b, 0x1f, 0x42, 0xf9, 0xc9, 0xd4, - 0x6e, 0x28, 0x79, 0x32, 0xa3, 0xf3, 0x10, 0x7d, 0x0b, 0x60, 0xa3, 0x78, 0x0f, 0x51, 0xa5, 0xd4, - 0xf9, 0x3c, 0x18, 0xdb, 0x15, 0xad, 0x15, 0x52, 0x2c, 0x90, 0x76, 0xd1, 0xd5, 0x6a, 0x48, 0xd1, - 0x0b, 0x00, 0x37, 0xf4, 0x3d, 0x40, 0x78, 0x79, 0xc6, 0xb2, 0x4b, 0x6b, 0x90, 0xca, 0xf6, 0x0a, - 0xe3, 0xbe, 0xc0, 0xf8, 0x18, 0x05, 0xcb, 0x31, 0xce, 0x6d, 0x71, 0x91, 0x50, 0x92, 0x5f, 0x5e, - 0xf2, 0x64, 0xee, 0x86, 0x1f, 0x12, 0x39, 0xa3, 0x05, 0x85, 0x14, 0x1c, 0xa2, 0x9f, 0x00, 0x6c, - 0xce, 0x5d, 0x0d, 0x54, 0x15, 0xf7, 0xac, 0x15, 0x37, 0xaa, 0x3b, 0xa8, 0x4a, 0xef, 0x88, 0x4a, - 0x77, 0xd0, 0x3b, 0x67, 0xaa, 0x14, 0x7d, 0x35, 0x1b, 0x1d, 0xb9, 0xd3, 0xa7, 0x8e, 0x8e, 0x76, - 0x4a, 0x4e, 0x1d, 0x1d, 0xfd, 0xb8, 0x58, 0x96, 0x00, 0xbb, 0x85, 0x0c, 0x09, 0x56, 0xc7, 0x29, - 0x8f, 0x09, 0xfa, 0x15, 0xc0, 0x4b, 0x25, 0x7b, 0x8e, 0x6e, 0x2e, 0x4d, 0xb5, 0xfc, 0xec, 0x18, - 0xb7, 0xfe, 0x9b, 0x93, 0x82, 0xf9, 0xbe, 0x80, 0xf9, 0x2e, 0xba, 0x5d, 0xc2, 0x29, 0x29, 0x3d, - 0x32, 0x1a, 0xa9, 0xbb, 0x8f, 0x9e, 0x1d, 0x99, 0xe0, 0xf9, 0x91, 0x09, 0xfe, 0x39, 0x32, 0xc1, - 0xd7, 0xc7, 0x66, 0xed, 0xf9, 0xb1, 0x59, 0xfb, 0xf3, 0xd8, 0xac, 0x7d, 0xbe, 0xe3, 0x07, 0xc9, - 0x28, 0x75, 0xb1, 0xc7, 0x26, 0x44, 0xfd, 0x39, 0x96, 0x3f, 0xdb, 0x7c, 0xf8, 0x98, 0x7c, 0x79, - 0x92, 0xef, 0x46, 0x7f, 0x5b, 0xa5, 0x4c, 0x0e, 0x22, 0xca, 0xdd, 0xf3, 0xe2, 0x6c, 0xdd, 0xfc, - 0x37, 0x00, 0x00, 0xff, 0xff, 0x66, 0x42, 0x78, 0x90, 0x87, 0x0b, 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 { - // ClientState queries an IBC light client. - ClientState(ctx context.Context, in *QueryClientStateRequest, opts ...grpc.CallOption) (*QueryClientStateResponse, error) - // ClientStates queries all the IBC light clients of a chain. - ClientStates(ctx context.Context, in *QueryClientStatesRequest, opts ...grpc.CallOption) (*QueryClientStatesResponse, error) - // ConsensusState queries a consensus state associated with a client state at - // a given height. - ConsensusState(ctx context.Context, in *QueryConsensusStateRequest, opts ...grpc.CallOption) (*QueryConsensusStateResponse, error) - // ConsensusStates queries all the consensus state associated with a given - // client. - ConsensusStates(ctx context.Context, in *QueryConsensusStatesRequest, opts ...grpc.CallOption) (*QueryConsensusStatesResponse, error) - // ClientParams queries all parameters of the ibc client. - ClientParams(ctx context.Context, in *QueryClientParamsRequest, opts ...grpc.CallOption) (*QueryClientParamsResponse, error) - // UpgradedClientState queries an Upgraded IBC light client. - UpgradedClientState(ctx context.Context, in *QueryUpgradedClientStateRequest, opts ...grpc.CallOption) (*QueryUpgradedClientStateResponse, error) -} - -type queryClient struct { - cc grpc1.ClientConn -} - -func NewQueryClient(cc grpc1.ClientConn) QueryClient { - return &queryClient{cc} -} - -func (c *queryClient) ClientState(ctx context.Context, in *QueryClientStateRequest, opts ...grpc.CallOption) (*QueryClientStateResponse, error) { - out := new(QueryClientStateResponse) - err := c.cc.Invoke(ctx, "/ibc.core.client.v1.Query/ClientState", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *queryClient) ClientStates(ctx context.Context, in *QueryClientStatesRequest, opts ...grpc.CallOption) (*QueryClientStatesResponse, error) { - out := new(QueryClientStatesResponse) - err := c.cc.Invoke(ctx, "/ibc.core.client.v1.Query/ClientStates", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *queryClient) ConsensusState(ctx context.Context, in *QueryConsensusStateRequest, opts ...grpc.CallOption) (*QueryConsensusStateResponse, error) { - out := new(QueryConsensusStateResponse) - err := c.cc.Invoke(ctx, "/ibc.core.client.v1.Query/ConsensusState", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *queryClient) ConsensusStates(ctx context.Context, in *QueryConsensusStatesRequest, opts ...grpc.CallOption) (*QueryConsensusStatesResponse, error) { - out := new(QueryConsensusStatesResponse) - err := c.cc.Invoke(ctx, "/ibc.core.client.v1.Query/ConsensusStates", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *queryClient) ClientParams(ctx context.Context, in *QueryClientParamsRequest, opts ...grpc.CallOption) (*QueryClientParamsResponse, error) { - out := new(QueryClientParamsResponse) - err := c.cc.Invoke(ctx, "/ibc.core.client.v1.Query/ClientParams", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *queryClient) UpgradedClientState(ctx context.Context, in *QueryUpgradedClientStateRequest, opts ...grpc.CallOption) (*QueryUpgradedClientStateResponse, error) { - out := new(QueryUpgradedClientStateResponse) - err := c.cc.Invoke(ctx, "/ibc.core.client.v1.Query/UpgradedClientState", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// QueryServer is the server API for Query service. -type QueryServer interface { - // ClientState queries an IBC light client. - ClientState(context.Context, *QueryClientStateRequest) (*QueryClientStateResponse, error) - // ClientStates queries all the IBC light clients of a chain. - ClientStates(context.Context, *QueryClientStatesRequest) (*QueryClientStatesResponse, error) - // ConsensusState queries a consensus state associated with a client state at - // a given height. - ConsensusState(context.Context, *QueryConsensusStateRequest) (*QueryConsensusStateResponse, error) - // ConsensusStates queries all the consensus state associated with a given - // client. - ConsensusStates(context.Context, *QueryConsensusStatesRequest) (*QueryConsensusStatesResponse, error) - // ClientParams queries all parameters of the ibc client. - ClientParams(context.Context, *QueryClientParamsRequest) (*QueryClientParamsResponse, error) - // UpgradedClientState queries an Upgraded IBC light client. - UpgradedClientState(context.Context, *QueryUpgradedClientStateRequest) (*QueryUpgradedClientStateResponse, error) -} - -// UnimplementedQueryServer can be embedded to have forward compatible implementations. -type UnimplementedQueryServer struct { -} - -func (*UnimplementedQueryServer) ClientState(ctx context.Context, req *QueryClientStateRequest) (*QueryClientStateResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ClientState not implemented") -} -func (*UnimplementedQueryServer) ClientStates(ctx context.Context, req *QueryClientStatesRequest) (*QueryClientStatesResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ClientStates not implemented") -} -func (*UnimplementedQueryServer) ConsensusState(ctx context.Context, req *QueryConsensusStateRequest) (*QueryConsensusStateResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ConsensusState not implemented") -} -func (*UnimplementedQueryServer) ConsensusStates(ctx context.Context, req *QueryConsensusStatesRequest) (*QueryConsensusStatesResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ConsensusStates not implemented") -} -func (*UnimplementedQueryServer) ClientParams(ctx context.Context, req *QueryClientParamsRequest) (*QueryClientParamsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ClientParams not implemented") -} -func (*UnimplementedQueryServer) UpgradedClientState(ctx context.Context, req *QueryUpgradedClientStateRequest) (*QueryUpgradedClientStateResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method UpgradedClientState not implemented") -} - -func RegisterQueryServer(s grpc1.Server, srv QueryServer) { - s.RegisterService(&_Query_serviceDesc, srv) -} - -func _Query_ClientState_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryClientStateRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(QueryServer).ClientState(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.client.v1.Query/ClientState", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).ClientState(ctx, req.(*QueryClientStateRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Query_ClientStates_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryClientStatesRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(QueryServer).ClientStates(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.client.v1.Query/ClientStates", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).ClientStates(ctx, req.(*QueryClientStatesRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Query_ConsensusState_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryConsensusStateRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(QueryServer).ConsensusState(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.client.v1.Query/ConsensusState", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).ConsensusState(ctx, req.(*QueryConsensusStateRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Query_ConsensusStates_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryConsensusStatesRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(QueryServer).ConsensusStates(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.client.v1.Query/ConsensusStates", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).ConsensusStates(ctx, req.(*QueryConsensusStatesRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Query_ClientParams_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryClientParamsRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(QueryServer).ClientParams(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.client.v1.Query/ClientParams", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).ClientParams(ctx, req.(*QueryClientParamsRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Query_UpgradedClientState_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryUpgradedClientStateRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(QueryServer).UpgradedClientState(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.client.v1.Query/UpgradedClientState", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).UpgradedClientState(ctx, req.(*QueryUpgradedClientStateRequest)) - } - return interceptor(ctx, in, info, handler) -} - -var _Query_serviceDesc = grpc.ServiceDesc{ - ServiceName: "ibc.core.client.v1.Query", - HandlerType: (*QueryServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "ClientState", - Handler: _Query_ClientState_Handler, - }, - { - MethodName: "ClientStates", - Handler: _Query_ClientStates_Handler, - }, - { - MethodName: "ConsensusState", - Handler: _Query_ConsensusState_Handler, - }, - { - MethodName: "ConsensusStates", - Handler: _Query_ConsensusStates_Handler, - }, - { - MethodName: "ClientParams", - Handler: _Query_ClientParams_Handler, - }, - { - MethodName: "UpgradedClientState", - Handler: _Query_UpgradedClientState_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "ibc/core/client/v1/query.proto", -} - -func (m *QueryClientStateRequest) 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 *QueryClientStateRequest) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryClientStateRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.ClientId) > 0 { - i -= len(m.ClientId) - copy(dAtA[i:], m.ClientId) - i = encodeVarintQuery(dAtA, i, uint64(len(m.ClientId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *QueryClientStateResponse) 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 *QueryClientStateResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryClientStateResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - { - size, err := m.ProofHeight.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - if len(m.Proof) > 0 { - i -= len(m.Proof) - copy(dAtA[i:], m.Proof) - i = encodeVarintQuery(dAtA, i, uint64(len(m.Proof))) - i-- - dAtA[i] = 0x12 - } - if m.ClientState != nil { - { - size, err := m.ClientState.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 *QueryClientStatesRequest) 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 *QueryClientStatesRequest) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryClientStatesRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.Pagination != nil { - { - size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *QueryClientStatesResponse) 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 *QueryClientStatesResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryClientStatesResponse) 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.ClientStates) > 0 { - for iNdEx := len(m.ClientStates) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.ClientStates[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 *QueryConsensusStateRequest) 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 *QueryConsensusStateRequest) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryConsensusStateRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.LatestHeight { - i-- - if m.LatestHeight { - dAtA[i] = 1 - } else { - dAtA[i] = 0 - } - i-- - dAtA[i] = 0x20 - } - if m.RevisionHeight != 0 { - i = encodeVarintQuery(dAtA, i, uint64(m.RevisionHeight)) - i-- - dAtA[i] = 0x18 - } - if m.RevisionNumber != 0 { - i = encodeVarintQuery(dAtA, i, uint64(m.RevisionNumber)) - i-- - dAtA[i] = 0x10 - } - if len(m.ClientId) > 0 { - i -= len(m.ClientId) - copy(dAtA[i:], m.ClientId) - i = encodeVarintQuery(dAtA, i, uint64(len(m.ClientId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *QueryConsensusStateResponse) 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 *QueryConsensusStateResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryConsensusStateResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - { - size, err := m.ProofHeight.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - if len(m.Proof) > 0 { - i -= len(m.Proof) - copy(dAtA[i:], m.Proof) - i = encodeVarintQuery(dAtA, i, uint64(len(m.Proof))) - i-- - dAtA[i] = 0x12 - } - if m.ConsensusState != nil { - { - size, err := m.ConsensusState.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 *QueryConsensusStatesRequest) 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 *QueryConsensusStatesRequest) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryConsensusStatesRequest) 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.ClientId) > 0 { - i -= len(m.ClientId) - copy(dAtA[i:], m.ClientId) - i = encodeVarintQuery(dAtA, i, uint64(len(m.ClientId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *QueryConsensusStatesResponse) 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 *QueryConsensusStatesResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryConsensusStatesResponse) 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.ConsensusStates) > 0 { - for iNdEx := len(m.ConsensusStates) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.ConsensusStates[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 *QueryClientParamsRequest) 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 *QueryClientParamsRequest) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryClientParamsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - return len(dAtA) - i, nil -} - -func (m *QueryClientParamsResponse) 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 *QueryClientParamsResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryClientParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.Params != nil { - { - size, err := m.Params.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 *QueryUpgradedClientStateRequest) 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 *QueryUpgradedClientStateRequest) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryUpgradedClientStateRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.PlanHeight != 0 { - i = encodeVarintQuery(dAtA, i, uint64(m.PlanHeight)) - i-- - dAtA[i] = 0x10 - } - if len(m.ClientId) > 0 { - i -= len(m.ClientId) - copy(dAtA[i:], m.ClientId) - i = encodeVarintQuery(dAtA, i, uint64(len(m.ClientId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *QueryUpgradedClientStateResponse) 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 *QueryUpgradedClientStateResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryUpgradedClientStateResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.UpgradedClientState != nil { - { - size, err := m.UpgradedClientState.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 *QueryClientStateRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.ClientId) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - return n -} - -func (m *QueryClientStateResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.ClientState != nil { - l = m.ClientState.Size() - n += 1 + l + sovQuery(uint64(l)) - } - l = len(m.Proof) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - l = m.ProofHeight.Size() - n += 1 + l + sovQuery(uint64(l)) - return n -} - -func (m *QueryClientStatesRequest) 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 *QueryClientStatesResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if len(m.ClientStates) > 0 { - for _, e := range m.ClientStates { - 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 *QueryConsensusStateRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.ClientId) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - if m.RevisionNumber != 0 { - n += 1 + sovQuery(uint64(m.RevisionNumber)) - } - if m.RevisionHeight != 0 { - n += 1 + sovQuery(uint64(m.RevisionHeight)) - } - if m.LatestHeight { - n += 2 - } - return n -} - -func (m *QueryConsensusStateResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.ConsensusState != nil { - l = m.ConsensusState.Size() - n += 1 + l + sovQuery(uint64(l)) - } - l = len(m.Proof) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - l = m.ProofHeight.Size() - n += 1 + l + sovQuery(uint64(l)) - return n -} - -func (m *QueryConsensusStatesRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.ClientId) - 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 *QueryConsensusStatesResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if len(m.ConsensusStates) > 0 { - for _, e := range m.ConsensusStates { - 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 *QueryClientParamsRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - return n -} - -func (m *QueryClientParamsResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.Params != nil { - l = m.Params.Size() - n += 1 + l + sovQuery(uint64(l)) - } - return n -} - -func (m *QueryUpgradedClientStateRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.ClientId) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - if m.PlanHeight != 0 { - n += 1 + sovQuery(uint64(m.PlanHeight)) - } - return n -} - -func (m *QueryUpgradedClientStateResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.UpgradedClientState != nil { - l = m.UpgradedClientState.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 *QueryClientStateRequest) 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: QueryClientStateRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryClientStateRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ClientId", 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.ClientId = 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 *QueryClientStateResponse) 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: QueryClientStateResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryClientStateResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ClientState", 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.ClientState == nil { - m.ClientState = &types.Any{} - } - if err := m.ClientState.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Proof", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Proof = append(m.Proof[:0], dAtA[iNdEx:postIndex]...) - if m.Proof == nil { - m.Proof = []byte{} - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofHeight", 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 err := m.ProofHeight.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 *QueryClientStatesRequest) 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: QueryClientStatesRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryClientStatesRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.Pagination == nil { - m.Pagination = &query.PageRequest{} - } - if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipQuery(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *QueryClientStatesResponse) 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: QueryClientStatesResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryClientStatesResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ClientStates", 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.ClientStates = append(m.ClientStates, IdentifiedClientState{}) - if err := m.ClientStates[len(m.ClientStates)-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 *QueryConsensusStateRequest) 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: QueryConsensusStateRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryConsensusStateRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ClientId", 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.ClientId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field RevisionNumber", wireType) - } - m.RevisionNumber = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.RevisionNumber |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field RevisionHeight", wireType) - } - m.RevisionHeight = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.RevisionHeight |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 4: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field LatestHeight", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.LatestHeight = bool(v != 0) - 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 *QueryConsensusStateResponse) 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: QueryConsensusStateResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryConsensusStateResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ConsensusState", 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.ConsensusState == nil { - m.ConsensusState = &types.Any{} - } - if err := m.ConsensusState.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Proof", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Proof = append(m.Proof[:0], dAtA[iNdEx:postIndex]...) - if m.Proof == nil { - m.Proof = []byte{} - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofHeight", 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 err := m.ProofHeight.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 *QueryConsensusStatesRequest) 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: QueryConsensusStatesRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryConsensusStatesRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ClientId", 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.ClientId = 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 *QueryConsensusStatesResponse) 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: QueryConsensusStatesResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryConsensusStatesResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ConsensusStates", 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.ConsensusStates = append(m.ConsensusStates, ConsensusStateWithHeight{}) - if err := m.ConsensusStates[len(m.ConsensusStates)-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 *QueryClientParamsRequest) 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: QueryClientParamsRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryClientParamsRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - 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 *QueryClientParamsResponse) 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: QueryClientParamsResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryClientParamsResponse: 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) - } - 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.Params == nil { - m.Params = &Params{} - } - if err := m.Params.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 *QueryUpgradedClientStateRequest) 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: QueryUpgradedClientStateRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryUpgradedClientStateRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ClientId", 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.ClientId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field PlanHeight", wireType) - } - m.PlanHeight = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.PlanHeight |= int64(b&0x7F) << shift - if b < 0x80 { - break - } - } - default: - iNdEx = preIndex - skippy, err := skipQuery(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *QueryUpgradedClientStateResponse) 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: QueryUpgradedClientStateResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryUpgradedClientStateResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field UpgradedClientState", 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.UpgradedClientState == nil { - m.UpgradedClientState = &types.Any{} - } - if err := m.UpgradedClientState.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/ibc/core/02-client/types/query.pb.gw.go b/x/ibc/core/02-client/types/query.pb.gw.go deleted file mode 100644 index 9e36ecc18fde..000000000000 --- a/x/ibc/core/02-client/types/query.pb.gw.go +++ /dev/null @@ -1,718 +0,0 @@ -// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. -// source: ibc/core/client/v1/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_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 - 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 := client.ClientState(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -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)} -) - -func request_Query_ClientStates_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, 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 := client.ClientStates(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -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}} -) - -func request_Query_ConsensusState_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, 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 := client.ConsensusState(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -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}} -) - -func request_Query_ConsensusStates_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, 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 := client.ConsensusStates(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -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 - - msg, err := client.ClientParams(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -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 - -} - -var ( - filter_Query_UpgradedClientState_0 = &utilities.DoubleArray{Encoding: map[string]int{"client_id": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} -) - -func request_Query_UpgradedClientState_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryUpgradedClientStateRequest - 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_UpgradedClientState_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.UpgradedClientState(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Query_UpgradedClientState_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryUpgradedClientStateRequest - 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_UpgradedClientState_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.UpgradedClientState(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()...) - - }) - - mux.Handle("GET", pattern_Query_UpgradedClientState_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_UpgradedClientState_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_UpgradedClientState_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_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.AnnotateContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Query_ClientState_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_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.AnnotateContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Query_ClientStates_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_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.AnnotateContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Query_ConsensusState_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_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.AnnotateContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Query_ConsensusStates_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_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.AnnotateContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Query_ClientParams_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_ClientParams_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_UpgradedClientState_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_UpgradedClientState_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_UpgradedClientState_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - return nil -} - -var ( - pattern_Query_ClientState_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"ibc", "core", "client", "v1beta1", "client_states", "client_id"}, "", runtime.AssumeColonVerbOpt(false))) - - pattern_Query_ClientStates_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"ibc", "core", "client", "v1beta1", "client_states"}, "", runtime.AssumeColonVerbOpt(false))) - - pattern_Query_ConsensusState_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8, 1, 0, 4, 1, 5, 9}, []string{"ibc", "core", "client", "v1beta1", "consensus_states", "client_id", "revision", "revision_number", "height", "revision_height"}, "", runtime.AssumeColonVerbOpt(false))) - - pattern_Query_ConsensusStates_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"ibc", "core", "client", "v1beta1", "consensus_states", "client_id"}, "", runtime.AssumeColonVerbOpt(false))) - - pattern_Query_ClientParams_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"ibc", "client", "v1beta1", "params"}, "", runtime.AssumeColonVerbOpt(false))) - - pattern_Query_UpgradedClientState_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"ibc", "core", "client", "v1", "upgraded_client_states", "client_id"}, "", runtime.AssumeColonVerbOpt(false))) -) - -var ( - forward_Query_ClientState_0 = runtime.ForwardResponseMessage - - forward_Query_ClientStates_0 = runtime.ForwardResponseMessage - - forward_Query_ConsensusState_0 = runtime.ForwardResponseMessage - - forward_Query_ConsensusStates_0 = runtime.ForwardResponseMessage - - forward_Query_ClientParams_0 = runtime.ForwardResponseMessage - - forward_Query_UpgradedClientState_0 = runtime.ForwardResponseMessage -) diff --git a/x/ibc/core/02-client/types/tx.pb.go b/x/ibc/core/02-client/types/tx.pb.go deleted file mode 100644 index a314223fcff9..000000000000 --- a/x/ibc/core/02-client/types/tx.pb.go +++ /dev/null @@ -1,2071 +0,0 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: ibc/core/client/v1/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" - 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 - -// MsgCreateClient defines a message to create an IBC client -type MsgCreateClient struct { - // light client state - ClientState *types.Any `protobuf:"bytes,1,opt,name=client_state,json=clientState,proto3" json:"client_state,omitempty" yaml:"client_state"` - // consensus state associated with the client that corresponds to a given - // height. - ConsensusState *types.Any `protobuf:"bytes,2,opt,name=consensus_state,json=consensusState,proto3" json:"consensus_state,omitempty" yaml:"consensus_state"` - // signer address - Signer string `protobuf:"bytes,3,opt,name=signer,proto3" json:"signer,omitempty"` -} - -func (m *MsgCreateClient) Reset() { *m = MsgCreateClient{} } -func (m *MsgCreateClient) String() string { return proto.CompactTextString(m) } -func (*MsgCreateClient) ProtoMessage() {} -func (*MsgCreateClient) Descriptor() ([]byte, []int) { - return fileDescriptor_cb5dc4651eb49a04, []int{0} -} -func (m *MsgCreateClient) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgCreateClient) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgCreateClient.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 *MsgCreateClient) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgCreateClient.Merge(m, src) -} -func (m *MsgCreateClient) XXX_Size() int { - return m.Size() -} -func (m *MsgCreateClient) XXX_DiscardUnknown() { - xxx_messageInfo_MsgCreateClient.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgCreateClient proto.InternalMessageInfo - -// MsgCreateClientResponse defines the Msg/CreateClient response type. -type MsgCreateClientResponse struct { -} - -func (m *MsgCreateClientResponse) Reset() { *m = MsgCreateClientResponse{} } -func (m *MsgCreateClientResponse) String() string { return proto.CompactTextString(m) } -func (*MsgCreateClientResponse) ProtoMessage() {} -func (*MsgCreateClientResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_cb5dc4651eb49a04, []int{1} -} -func (m *MsgCreateClientResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgCreateClientResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgCreateClientResponse.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 *MsgCreateClientResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgCreateClientResponse.Merge(m, src) -} -func (m *MsgCreateClientResponse) XXX_Size() int { - return m.Size() -} -func (m *MsgCreateClientResponse) XXX_DiscardUnknown() { - xxx_messageInfo_MsgCreateClientResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgCreateClientResponse proto.InternalMessageInfo - -// MsgUpdateClient defines an sdk.Msg to update a IBC client state using -// the given header. -type MsgUpdateClient struct { - // client unique identifier - ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty" yaml:"client_id"` - // header to update the light client - Header *types.Any `protobuf:"bytes,2,opt,name=header,proto3" json:"header,omitempty"` - // signer address - Signer string `protobuf:"bytes,3,opt,name=signer,proto3" json:"signer,omitempty"` -} - -func (m *MsgUpdateClient) Reset() { *m = MsgUpdateClient{} } -func (m *MsgUpdateClient) String() string { return proto.CompactTextString(m) } -func (*MsgUpdateClient) ProtoMessage() {} -func (*MsgUpdateClient) Descriptor() ([]byte, []int) { - return fileDescriptor_cb5dc4651eb49a04, []int{2} -} -func (m *MsgUpdateClient) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgUpdateClient) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgUpdateClient.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 *MsgUpdateClient) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgUpdateClient.Merge(m, src) -} -func (m *MsgUpdateClient) XXX_Size() int { - return m.Size() -} -func (m *MsgUpdateClient) XXX_DiscardUnknown() { - xxx_messageInfo_MsgUpdateClient.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgUpdateClient proto.InternalMessageInfo - -// MsgUpdateClientResponse defines the Msg/UpdateClient response type. -type MsgUpdateClientResponse struct { -} - -func (m *MsgUpdateClientResponse) Reset() { *m = MsgUpdateClientResponse{} } -func (m *MsgUpdateClientResponse) String() string { return proto.CompactTextString(m) } -func (*MsgUpdateClientResponse) ProtoMessage() {} -func (*MsgUpdateClientResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_cb5dc4651eb49a04, []int{3} -} -func (m *MsgUpdateClientResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgUpdateClientResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgUpdateClientResponse.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 *MsgUpdateClientResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgUpdateClientResponse.Merge(m, src) -} -func (m *MsgUpdateClientResponse) XXX_Size() int { - return m.Size() -} -func (m *MsgUpdateClientResponse) XXX_DiscardUnknown() { - xxx_messageInfo_MsgUpdateClientResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgUpdateClientResponse proto.InternalMessageInfo - -// MsgUpgradeClient defines an sdk.Msg to upgrade an IBC client to a new client state -type MsgUpgradeClient struct { - // client unique identifier - ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty" yaml:"client_id"` - // upgraded client state - ClientState *types.Any `protobuf:"bytes,2,opt,name=client_state,json=clientState,proto3" json:"client_state,omitempty" yaml:"client_state"` - // upgraded consensus state, only contains enough information to serve as a basis of trust in update logic - ConsensusState *types.Any `protobuf:"bytes,3,opt,name=consensus_state,json=consensusState,proto3" json:"consensus_state,omitempty" yaml:"consensus_state"` - // proof that old chain committed to new client - ProofUpgradeClient []byte `protobuf:"bytes,4,opt,name=proof_upgrade_client,json=proofUpgradeClient,proto3" json:"proof_upgrade_client,omitempty" yaml:"proof_upgrade_client"` - // proof that old chain committed to new consensus state - ProofUpgradeConsensusState []byte `protobuf:"bytes,5,opt,name=proof_upgrade_consensus_state,json=proofUpgradeConsensusState,proto3" json:"proof_upgrade_consensus_state,omitempty" yaml:"proof_upgrade_consensus_state"` - // signer address - Signer string `protobuf:"bytes,6,opt,name=signer,proto3" json:"signer,omitempty"` -} - -func (m *MsgUpgradeClient) Reset() { *m = MsgUpgradeClient{} } -func (m *MsgUpgradeClient) String() string { return proto.CompactTextString(m) } -func (*MsgUpgradeClient) ProtoMessage() {} -func (*MsgUpgradeClient) Descriptor() ([]byte, []int) { - return fileDescriptor_cb5dc4651eb49a04, []int{4} -} -func (m *MsgUpgradeClient) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgUpgradeClient) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgUpgradeClient.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 *MsgUpgradeClient) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgUpgradeClient.Merge(m, src) -} -func (m *MsgUpgradeClient) XXX_Size() int { - return m.Size() -} -func (m *MsgUpgradeClient) XXX_DiscardUnknown() { - xxx_messageInfo_MsgUpgradeClient.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgUpgradeClient proto.InternalMessageInfo - -// MsgUpgradeClientResponse defines the Msg/UpgradeClient response type. -type MsgUpgradeClientResponse struct { -} - -func (m *MsgUpgradeClientResponse) Reset() { *m = MsgUpgradeClientResponse{} } -func (m *MsgUpgradeClientResponse) String() string { return proto.CompactTextString(m) } -func (*MsgUpgradeClientResponse) ProtoMessage() {} -func (*MsgUpgradeClientResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_cb5dc4651eb49a04, []int{5} -} -func (m *MsgUpgradeClientResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgUpgradeClientResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgUpgradeClientResponse.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 *MsgUpgradeClientResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgUpgradeClientResponse.Merge(m, src) -} -func (m *MsgUpgradeClientResponse) XXX_Size() int { - return m.Size() -} -func (m *MsgUpgradeClientResponse) XXX_DiscardUnknown() { - xxx_messageInfo_MsgUpgradeClientResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgUpgradeClientResponse proto.InternalMessageInfo - -// MsgSubmitMisbehaviour defines an sdk.Msg type that submits Evidence for -// light client misbehaviour. -type MsgSubmitMisbehaviour struct { - // client unique identifier - ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty" yaml:"client_id"` - // misbehaviour used for freezing the light client - Misbehaviour *types.Any `protobuf:"bytes,2,opt,name=misbehaviour,proto3" json:"misbehaviour,omitempty"` - // signer address - Signer string `protobuf:"bytes,3,opt,name=signer,proto3" json:"signer,omitempty"` -} - -func (m *MsgSubmitMisbehaviour) Reset() { *m = MsgSubmitMisbehaviour{} } -func (m *MsgSubmitMisbehaviour) String() string { return proto.CompactTextString(m) } -func (*MsgSubmitMisbehaviour) ProtoMessage() {} -func (*MsgSubmitMisbehaviour) Descriptor() ([]byte, []int) { - return fileDescriptor_cb5dc4651eb49a04, []int{6} -} -func (m *MsgSubmitMisbehaviour) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgSubmitMisbehaviour) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgSubmitMisbehaviour.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 *MsgSubmitMisbehaviour) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgSubmitMisbehaviour.Merge(m, src) -} -func (m *MsgSubmitMisbehaviour) XXX_Size() int { - return m.Size() -} -func (m *MsgSubmitMisbehaviour) XXX_DiscardUnknown() { - xxx_messageInfo_MsgSubmitMisbehaviour.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgSubmitMisbehaviour proto.InternalMessageInfo - -// MsgSubmitMisbehaviourResponse defines the Msg/SubmitMisbehaviour response type. -type MsgSubmitMisbehaviourResponse struct { -} - -func (m *MsgSubmitMisbehaviourResponse) Reset() { *m = MsgSubmitMisbehaviourResponse{} } -func (m *MsgSubmitMisbehaviourResponse) String() string { return proto.CompactTextString(m) } -func (*MsgSubmitMisbehaviourResponse) ProtoMessage() {} -func (*MsgSubmitMisbehaviourResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_cb5dc4651eb49a04, []int{7} -} -func (m *MsgSubmitMisbehaviourResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgSubmitMisbehaviourResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgSubmitMisbehaviourResponse.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 *MsgSubmitMisbehaviourResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgSubmitMisbehaviourResponse.Merge(m, src) -} -func (m *MsgSubmitMisbehaviourResponse) XXX_Size() int { - return m.Size() -} -func (m *MsgSubmitMisbehaviourResponse) XXX_DiscardUnknown() { - xxx_messageInfo_MsgSubmitMisbehaviourResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgSubmitMisbehaviourResponse proto.InternalMessageInfo - -func init() { - proto.RegisterType((*MsgCreateClient)(nil), "ibc.core.client.v1.MsgCreateClient") - proto.RegisterType((*MsgCreateClientResponse)(nil), "ibc.core.client.v1.MsgCreateClientResponse") - proto.RegisterType((*MsgUpdateClient)(nil), "ibc.core.client.v1.MsgUpdateClient") - proto.RegisterType((*MsgUpdateClientResponse)(nil), "ibc.core.client.v1.MsgUpdateClientResponse") - proto.RegisterType((*MsgUpgradeClient)(nil), "ibc.core.client.v1.MsgUpgradeClient") - proto.RegisterType((*MsgUpgradeClientResponse)(nil), "ibc.core.client.v1.MsgUpgradeClientResponse") - proto.RegisterType((*MsgSubmitMisbehaviour)(nil), "ibc.core.client.v1.MsgSubmitMisbehaviour") - proto.RegisterType((*MsgSubmitMisbehaviourResponse)(nil), "ibc.core.client.v1.MsgSubmitMisbehaviourResponse") -} - -func init() { proto.RegisterFile("ibc/core/client/v1/tx.proto", fileDescriptor_cb5dc4651eb49a04) } - -var fileDescriptor_cb5dc4651eb49a04 = []byte{ - // 601 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x55, 0x3f, 0x6f, 0xd3, 0x40, - 0x1c, 0x8d, 0x1b, 0x88, 0x9a, 0x6b, 0xa0, 0x95, 0x09, 0x6d, 0xea, 0xaa, 0x76, 0x64, 0x3a, 0x04, - 0xd1, 0xfa, 0x48, 0x18, 0x40, 0xdd, 0x48, 0x27, 0x86, 0x48, 0xd4, 0x15, 0x03, 0x2c, 0xc1, 0x7f, - 0xae, 0x97, 0x53, 0x13, 0x5f, 0xe4, 0xb3, 0xa3, 0xe6, 0x1b, 0x30, 0x32, 0xf0, 0x01, 0x2a, 0x06, - 0x3e, 0x0b, 0x63, 0x07, 0x06, 0xa6, 0xa8, 0x4a, 0x16, 0xe6, 0x7c, 0x02, 0x14, 0x9f, 0x13, 0x62, - 0xd7, 0x8e, 0x2c, 0xa0, 0x53, 0x7c, 0xfe, 0xbd, 0x7b, 0xef, 0xf7, 0xf2, 0x7e, 0xe7, 0x03, 0x7b, - 0xc4, 0xb4, 0xa0, 0x45, 0x5d, 0x04, 0xad, 0x2e, 0x41, 0x8e, 0x07, 0x07, 0x75, 0xe8, 0x5d, 0x6a, - 0x7d, 0x97, 0x7a, 0x54, 0x14, 0x89, 0x69, 0x69, 0xb3, 0xa2, 0xc6, 0x8b, 0xda, 0xa0, 0x2e, 0x95, - 0x31, 0xc5, 0x34, 0x28, 0xc3, 0xd9, 0x13, 0x47, 0x4a, 0xbb, 0x98, 0x52, 0xdc, 0x45, 0x30, 0x58, - 0x99, 0xfe, 0x39, 0x34, 0x9c, 0x61, 0x58, 0x52, 0x12, 0x14, 0x42, 0xba, 0x00, 0xa0, 0xde, 0x08, - 0x60, 0xb3, 0xc5, 0xf0, 0x89, 0x8b, 0x0c, 0x0f, 0x9d, 0x04, 0x15, 0xf1, 0x2d, 0x28, 0x71, 0x4c, - 0x9b, 0x79, 0x86, 0x87, 0x2a, 0x42, 0x55, 0xa8, 0x6d, 0x34, 0xca, 0x1a, 0x97, 0xd1, 0xe6, 0x32, - 0xda, 0x6b, 0x67, 0xd8, 0xdc, 0x99, 0x8e, 0x94, 0x47, 0x43, 0xa3, 0xd7, 0x3d, 0x56, 0x97, 0xf7, - 0xa8, 0xfa, 0x06, 0x5f, 0x9e, 0xcd, 0x56, 0xe2, 0x7b, 0xb0, 0x69, 0x51, 0x87, 0x21, 0x87, 0xf9, - 0x2c, 0x24, 0x5d, 0x5b, 0x41, 0x2a, 0x4d, 0x47, 0xca, 0x76, 0x48, 0x1a, 0xdd, 0xa6, 0xea, 0x0f, - 0x17, 0x6f, 0x38, 0xf5, 0x36, 0x28, 0x30, 0x82, 0x1d, 0xe4, 0x56, 0xf2, 0x55, 0xa1, 0x56, 0xd4, - 0xc3, 0xd5, 0xf1, 0xfa, 0xa7, 0x2b, 0x25, 0xf7, 0xeb, 0x4a, 0xc9, 0xa9, 0xbb, 0x60, 0x27, 0xe6, - 0x50, 0x47, 0xac, 0x3f, 0x63, 0x51, 0xbf, 0x70, 0xf7, 0xef, 0xfa, 0xf6, 0x1f, 0xf7, 0x75, 0x50, - 0x0c, 0x9d, 0x10, 0x3b, 0xb0, 0x5e, 0x6c, 0x96, 0xa7, 0x23, 0x65, 0x2b, 0x62, 0x92, 0xd8, 0xaa, - 0xbe, 0xce, 0x9f, 0xdf, 0xd8, 0xe2, 0x21, 0x28, 0x74, 0x90, 0x61, 0x23, 0x77, 0x95, 0x2b, 0x3d, - 0xc4, 0x64, 0xee, 0x78, 0xb9, 0xab, 0x45, 0xc7, 0x3f, 0xf2, 0x60, 0x2b, 0xa8, 0x61, 0xd7, 0xb0, - 0xff, 0xa1, 0xe5, 0x78, 0xc6, 0x6b, 0x77, 0x91, 0x71, 0xfe, 0x3f, 0x65, 0x7c, 0x0a, 0xca, 0x7d, - 0x97, 0xd2, 0xf3, 0xb6, 0xcf, 0x6d, 0xb7, 0xb9, 0x6e, 0xe5, 0x5e, 0x55, 0xa8, 0x95, 0x9a, 0xca, - 0x74, 0xa4, 0xec, 0x71, 0xa6, 0x24, 0x94, 0xaa, 0x8b, 0xc1, 0xeb, 0xe8, 0x5f, 0x76, 0x01, 0xf6, - 0x63, 0xe0, 0x58, 0xef, 0xf7, 0x03, 0xee, 0xda, 0x74, 0xa4, 0x1c, 0x24, 0x72, 0xc7, 0x7b, 0x96, - 0x22, 0x22, 0x69, 0x33, 0x5a, 0x48, 0x49, 0x5c, 0x02, 0x95, 0x78, 0xaa, 0x8b, 0xc8, 0xbf, 0x09, - 0xe0, 0x71, 0x8b, 0xe1, 0x33, 0xdf, 0xec, 0x11, 0xaf, 0x45, 0x98, 0x89, 0x3a, 0xc6, 0x80, 0x50, - 0xdf, 0xfd, 0x9b, 0xdc, 0x5f, 0x81, 0x52, 0x6f, 0x89, 0x62, 0xe5, 0xc0, 0x46, 0x90, 0x19, 0xc6, - 0x56, 0x01, 0xfb, 0x89, 0x7d, 0xce, 0x9d, 0x34, 0xbe, 0xe6, 0x41, 0xbe, 0xc5, 0xb0, 0xf8, 0x11, - 0x94, 0x22, 0x1f, 0x9c, 0x27, 0xda, 0xed, 0x6f, 0x9d, 0x16, 0x3b, 0xb3, 0xd2, 0xb3, 0x0c, 0xa0, - 0xb9, 0xd2, 0x4c, 0x21, 0x72, 0xa8, 0xd3, 0x14, 0x96, 0x41, 0xa9, 0x0a, 0x49, 0x07, 0x51, 0xb4, - 0xc0, 0x83, 0xe8, 0x44, 0x1d, 0xa4, 0xee, 0x5e, 0x42, 0x49, 0x87, 0x59, 0x50, 0x0b, 0x11, 0x17, - 0x88, 0x09, 0xb1, 0x3f, 0x4d, 0xe1, 0xb8, 0x0d, 0x95, 0xea, 0x99, 0xa1, 0x73, 0xcd, 0xe6, 0xe9, - 0xf7, 0xb1, 0x2c, 0x5c, 0x8f, 0x65, 0xe1, 0x66, 0x2c, 0x0b, 0x9f, 0x27, 0x72, 0xee, 0x7a, 0x22, - 0xe7, 0x7e, 0x4e, 0xe4, 0xdc, 0x87, 0x97, 0x98, 0x78, 0x1d, 0xdf, 0xd4, 0x2c, 0xda, 0x83, 0x16, - 0x65, 0x3d, 0xca, 0xc2, 0x9f, 0x23, 0x66, 0x5f, 0xc0, 0x4b, 0xb8, 0xb8, 0x6b, 0x9e, 0x37, 0x8e, - 0xc2, 0xeb, 0xc6, 0x1b, 0xf6, 0x11, 0x33, 0x0b, 0xc1, 0x58, 0xbd, 0xf8, 0x1d, 0x00, 0x00, 0xff, - 0xff, 0xf4, 0xf1, 0xa7, 0x9a, 0xf0, 0x06, 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 { - // CreateClient defines a rpc handler method for MsgCreateClient. - CreateClient(ctx context.Context, in *MsgCreateClient, opts ...grpc.CallOption) (*MsgCreateClientResponse, error) - // UpdateClient defines a rpc handler method for MsgUpdateClient. - UpdateClient(ctx context.Context, in *MsgUpdateClient, opts ...grpc.CallOption) (*MsgUpdateClientResponse, error) - // UpgradeClient defines a rpc handler method for MsgUpgradeClient. - UpgradeClient(ctx context.Context, in *MsgUpgradeClient, opts ...grpc.CallOption) (*MsgUpgradeClientResponse, error) - // SubmitMisbehaviour defines a rpc handler method for MsgSubmitMisbehaviour. - SubmitMisbehaviour(ctx context.Context, in *MsgSubmitMisbehaviour, opts ...grpc.CallOption) (*MsgSubmitMisbehaviourResponse, error) -} - -type msgClient struct { - cc grpc1.ClientConn -} - -func NewMsgClient(cc grpc1.ClientConn) MsgClient { - return &msgClient{cc} -} - -func (c *msgClient) CreateClient(ctx context.Context, in *MsgCreateClient, opts ...grpc.CallOption) (*MsgCreateClientResponse, error) { - out := new(MsgCreateClientResponse) - err := c.cc.Invoke(ctx, "/ibc.core.client.v1.Msg/CreateClient", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *msgClient) UpdateClient(ctx context.Context, in *MsgUpdateClient, opts ...grpc.CallOption) (*MsgUpdateClientResponse, error) { - out := new(MsgUpdateClientResponse) - err := c.cc.Invoke(ctx, "/ibc.core.client.v1.Msg/UpdateClient", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *msgClient) UpgradeClient(ctx context.Context, in *MsgUpgradeClient, opts ...grpc.CallOption) (*MsgUpgradeClientResponse, error) { - out := new(MsgUpgradeClientResponse) - err := c.cc.Invoke(ctx, "/ibc.core.client.v1.Msg/UpgradeClient", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *msgClient) SubmitMisbehaviour(ctx context.Context, in *MsgSubmitMisbehaviour, opts ...grpc.CallOption) (*MsgSubmitMisbehaviourResponse, error) { - out := new(MsgSubmitMisbehaviourResponse) - err := c.cc.Invoke(ctx, "/ibc.core.client.v1.Msg/SubmitMisbehaviour", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// MsgServer is the server API for Msg service. -type MsgServer interface { - // CreateClient defines a rpc handler method for MsgCreateClient. - CreateClient(context.Context, *MsgCreateClient) (*MsgCreateClientResponse, error) - // UpdateClient defines a rpc handler method for MsgUpdateClient. - UpdateClient(context.Context, *MsgUpdateClient) (*MsgUpdateClientResponse, error) - // UpgradeClient defines a rpc handler method for MsgUpgradeClient. - UpgradeClient(context.Context, *MsgUpgradeClient) (*MsgUpgradeClientResponse, error) - // SubmitMisbehaviour defines a rpc handler method for MsgSubmitMisbehaviour. - SubmitMisbehaviour(context.Context, *MsgSubmitMisbehaviour) (*MsgSubmitMisbehaviourResponse, error) -} - -// UnimplementedMsgServer can be embedded to have forward compatible implementations. -type UnimplementedMsgServer struct { -} - -func (*UnimplementedMsgServer) CreateClient(ctx context.Context, req *MsgCreateClient) (*MsgCreateClientResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method CreateClient not implemented") -} -func (*UnimplementedMsgServer) UpdateClient(ctx context.Context, req *MsgUpdateClient) (*MsgUpdateClientResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method UpdateClient not implemented") -} -func (*UnimplementedMsgServer) UpgradeClient(ctx context.Context, req *MsgUpgradeClient) (*MsgUpgradeClientResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method UpgradeClient not implemented") -} -func (*UnimplementedMsgServer) SubmitMisbehaviour(ctx context.Context, req *MsgSubmitMisbehaviour) (*MsgSubmitMisbehaviourResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method SubmitMisbehaviour not implemented") -} - -func RegisterMsgServer(s grpc1.Server, srv MsgServer) { - s.RegisterService(&_Msg_serviceDesc, srv) -} - -func _Msg_CreateClient_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgCreateClient) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MsgServer).CreateClient(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.client.v1.Msg/CreateClient", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).CreateClient(ctx, req.(*MsgCreateClient)) - } - return interceptor(ctx, in, info, handler) -} - -func _Msg_UpdateClient_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgUpdateClient) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MsgServer).UpdateClient(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.client.v1.Msg/UpdateClient", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).UpdateClient(ctx, req.(*MsgUpdateClient)) - } - return interceptor(ctx, in, info, handler) -} - -func _Msg_UpgradeClient_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgUpgradeClient) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MsgServer).UpgradeClient(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.client.v1.Msg/UpgradeClient", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).UpgradeClient(ctx, req.(*MsgUpgradeClient)) - } - return interceptor(ctx, in, info, handler) -} - -func _Msg_SubmitMisbehaviour_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgSubmitMisbehaviour) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MsgServer).SubmitMisbehaviour(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.client.v1.Msg/SubmitMisbehaviour", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).SubmitMisbehaviour(ctx, req.(*MsgSubmitMisbehaviour)) - } - return interceptor(ctx, in, info, handler) -} - -var _Msg_serviceDesc = grpc.ServiceDesc{ - ServiceName: "ibc.core.client.v1.Msg", - HandlerType: (*MsgServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "CreateClient", - Handler: _Msg_CreateClient_Handler, - }, - { - MethodName: "UpdateClient", - Handler: _Msg_UpdateClient_Handler, - }, - { - MethodName: "UpgradeClient", - Handler: _Msg_UpgradeClient_Handler, - }, - { - MethodName: "SubmitMisbehaviour", - Handler: _Msg_SubmitMisbehaviour_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "ibc/core/client/v1/tx.proto", -} - -func (m *MsgCreateClient) 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 *MsgCreateClient) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgCreateClient) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Signer) > 0 { - i -= len(m.Signer) - copy(dAtA[i:], m.Signer) - i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) - i-- - dAtA[i] = 0x1a - } - if m.ConsensusState != nil { - { - size, err := m.ConsensusState.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - } - if m.ClientState != nil { - { - size, err := m.ClientState.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 *MsgCreateClientResponse) 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 *MsgCreateClientResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgCreateClientResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - return len(dAtA) - i, nil -} - -func (m *MsgUpdateClient) 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 *MsgUpdateClient) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgUpdateClient) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Signer) > 0 { - i -= len(m.Signer) - copy(dAtA[i:], m.Signer) - i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) - i-- - dAtA[i] = 0x1a - } - if m.Header != nil { - { - size, err := m.Header.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - } - if len(m.ClientId) > 0 { - i -= len(m.ClientId) - copy(dAtA[i:], m.ClientId) - i = encodeVarintTx(dAtA, i, uint64(len(m.ClientId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *MsgUpdateClientResponse) 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 *MsgUpdateClientResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgUpdateClientResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - return len(dAtA) - i, nil -} - -func (m *MsgUpgradeClient) 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 *MsgUpgradeClient) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgUpgradeClient) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Signer) > 0 { - i -= len(m.Signer) - copy(dAtA[i:], m.Signer) - i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) - i-- - dAtA[i] = 0x32 - } - if len(m.ProofUpgradeConsensusState) > 0 { - i -= len(m.ProofUpgradeConsensusState) - copy(dAtA[i:], m.ProofUpgradeConsensusState) - i = encodeVarintTx(dAtA, i, uint64(len(m.ProofUpgradeConsensusState))) - i-- - dAtA[i] = 0x2a - } - if len(m.ProofUpgradeClient) > 0 { - i -= len(m.ProofUpgradeClient) - copy(dAtA[i:], m.ProofUpgradeClient) - i = encodeVarintTx(dAtA, i, uint64(len(m.ProofUpgradeClient))) - i-- - dAtA[i] = 0x22 - } - if m.ConsensusState != nil { - { - size, err := m.ConsensusState.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - } - if m.ClientState != nil { - { - size, err := m.ClientState.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - } - if len(m.ClientId) > 0 { - i -= len(m.ClientId) - copy(dAtA[i:], m.ClientId) - i = encodeVarintTx(dAtA, i, uint64(len(m.ClientId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *MsgUpgradeClientResponse) 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 *MsgUpgradeClientResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgUpgradeClientResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - return len(dAtA) - i, nil -} - -func (m *MsgSubmitMisbehaviour) 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 *MsgSubmitMisbehaviour) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgSubmitMisbehaviour) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Signer) > 0 { - i -= len(m.Signer) - copy(dAtA[i:], m.Signer) - i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) - i-- - dAtA[i] = 0x1a - } - if m.Misbehaviour != nil { - { - size, err := m.Misbehaviour.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - } - if len(m.ClientId) > 0 { - i -= len(m.ClientId) - copy(dAtA[i:], m.ClientId) - i = encodeVarintTx(dAtA, i, uint64(len(m.ClientId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *MsgSubmitMisbehaviourResponse) 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 *MsgSubmitMisbehaviourResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgSubmitMisbehaviourResponse) 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 *MsgCreateClient) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.ClientState != nil { - l = m.ClientState.Size() - n += 1 + l + sovTx(uint64(l)) - } - if m.ConsensusState != nil { - l = m.ConsensusState.Size() - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.Signer) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - return n -} - -func (m *MsgCreateClientResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - return n -} - -func (m *MsgUpdateClient) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.ClientId) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - if m.Header != nil { - l = m.Header.Size() - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.Signer) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - return n -} - -func (m *MsgUpdateClientResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - return n -} - -func (m *MsgUpgradeClient) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.ClientId) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - if m.ClientState != nil { - l = m.ClientState.Size() - n += 1 + l + sovTx(uint64(l)) - } - if m.ConsensusState != nil { - l = m.ConsensusState.Size() - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.ProofUpgradeClient) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.ProofUpgradeConsensusState) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.Signer) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - return n -} - -func (m *MsgUpgradeClientResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - return n -} - -func (m *MsgSubmitMisbehaviour) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.ClientId) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - if m.Misbehaviour != nil { - l = m.Misbehaviour.Size() - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.Signer) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - return n -} - -func (m *MsgSubmitMisbehaviourResponse) 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 *MsgCreateClient) 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: MsgCreateClient: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgCreateClient: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ClientState", 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.ClientState == nil { - m.ClientState = &types.Any{} - } - if err := m.ClientState.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ConsensusState", 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.ConsensusState == nil { - m.ConsensusState = &types.Any{} - } - if err := m.ConsensusState.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Signer", 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.Signer = 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 *MsgCreateClientResponse) 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: MsgCreateClientResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgCreateClientResponse: 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 *MsgUpdateClient) 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: MsgUpdateClient: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgUpdateClient: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ClientId", 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.ClientId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Header", 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.Header == nil { - m.Header = &types.Any{} - } - if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Signer", 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.Signer = 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 *MsgUpdateClientResponse) 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: MsgUpdateClientResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgUpdateClientResponse: 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 *MsgUpgradeClient) 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: MsgUpgradeClient: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgUpgradeClient: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ClientId", 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.ClientId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ClientState", 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.ClientState == nil { - m.ClientState = &types.Any{} - } - if err := m.ClientState.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ConsensusState", 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.ConsensusState == nil { - m.ConsensusState = &types.Any{} - } - if err := m.ConsensusState.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofUpgradeClient", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ProofUpgradeClient = append(m.ProofUpgradeClient[:0], dAtA[iNdEx:postIndex]...) - if m.ProofUpgradeClient == nil { - m.ProofUpgradeClient = []byte{} - } - iNdEx = postIndex - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofUpgradeConsensusState", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ProofUpgradeConsensusState = append(m.ProofUpgradeConsensusState[:0], dAtA[iNdEx:postIndex]...) - if m.ProofUpgradeConsensusState == nil { - m.ProofUpgradeConsensusState = []byte{} - } - iNdEx = postIndex - case 6: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Signer", 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.Signer = 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 *MsgUpgradeClientResponse) 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: MsgUpgradeClientResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgUpgradeClientResponse: 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 *MsgSubmitMisbehaviour) 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: MsgSubmitMisbehaviour: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgSubmitMisbehaviour: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ClientId", 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.ClientId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Misbehaviour", 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.Misbehaviour == nil { - m.Misbehaviour = &types.Any{} - } - if err := m.Misbehaviour.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Signer", 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.Signer = 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 *MsgSubmitMisbehaviourResponse) 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: MsgSubmitMisbehaviourResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgSubmitMisbehaviourResponse: 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/ibc/core/03-connection/client/cli/cli.go b/x/ibc/core/03-connection/client/cli/cli.go deleted file mode 100644 index 01bb6f9b110f..000000000000 --- a/x/ibc/core/03-connection/client/cli/cli.go +++ /dev/null @@ -1,46 +0,0 @@ -package cli - -import ( - "github.com/spf13/cobra" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" -) - -// GetQueryCmd returns the query commands for IBC connections -func GetQueryCmd() *cobra.Command { - queryCmd := &cobra.Command{ - Use: types.SubModuleName, - Short: "IBC connection query subcommands", - DisableFlagParsing: true, - SuggestionsMinimumDistance: 2, - } - - queryCmd.AddCommand( - GetCmdQueryConnections(), - GetCmdQueryConnection(), - GetCmdQueryClientConnections(), - ) - - return queryCmd -} - -// NewTxCmd returns a CLI command handler for all x/ibc connection transaction commands. -func NewTxCmd() *cobra.Command { - txCmd := &cobra.Command{ - Use: types.SubModuleName, - Short: "IBC connection transaction subcommands", - DisableFlagParsing: true, - SuggestionsMinimumDistance: 2, - RunE: client.ValidateCmd, - } - - txCmd.AddCommand( - NewConnectionOpenInitCmd(), - NewConnectionOpenTryCmd(), - NewConnectionOpenAckCmd(), - NewConnectionOpenConfirmCmd(), - ) - - return txCmd -} diff --git a/x/ibc/core/03-connection/client/cli/query.go b/x/ibc/core/03-connection/client/cli/query.go deleted file mode 100644 index 21c4bd8f578e..000000000000 --- a/x/ibc/core/03-connection/client/cli/query.go +++ /dev/null @@ -1,118 +0,0 @@ -package cli - -import ( - "fmt" - - "github.com/spf13/cobra" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/version" - "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/client/utils" - "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" -) - -// GetCmdQueryConnections defines the command to query all the connection ends -// that this chain mantains. -func GetCmdQueryConnections() *cobra.Command { - cmd := &cobra.Command{ - Use: "connections", - Short: "Query all connections", - Long: "Query all connections ends from a chain", - Example: fmt.Sprintf("%s query %s %s connections", version.AppName, host.ModuleName, types.SubModuleName), - Args: cobra.NoArgs, - RunE: func(cmd *cobra.Command, _ []string) error { - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } - queryClient := types.NewQueryClient(clientCtx) - - pageReq, err := client.ReadPageRequest(cmd.Flags()) - if err != nil { - return err - } - - req := &types.QueryConnectionsRequest{ - Pagination: pageReq, - } - - res, err := queryClient.Connections(cmd.Context(), req) - if err != nil { - return err - } - - return clientCtx.PrintProto(res) - }, - } - - flags.AddQueryFlagsToCmd(cmd) - flags.AddPaginationFlagsToCmd(cmd, "connection ends") - - return cmd -} - -// GetCmdQueryConnection defines the command to query a connection end -func GetCmdQueryConnection() *cobra.Command { - cmd := &cobra.Command{ - Use: "end [connection-id]", - Short: "Query stored connection end", - Long: "Query stored connection end", - Example: fmt.Sprintf("%s query %s %s end [connection-id]", version.AppName, host.ModuleName, types.SubModuleName), - Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } - connectionID := args[0] - prove, _ := cmd.Flags().GetBool(flags.FlagProve) - - connRes, err := utils.QueryConnection(clientCtx, connectionID, prove) - if err != nil { - return err - } - - clientCtx = clientCtx.WithHeight(int64(connRes.ProofHeight.RevisionHeight)) - return clientCtx.PrintProto(connRes) - }, - } - - cmd.Flags().Bool(flags.FlagProve, true, "show proofs for the query results") - flags.AddQueryFlagsToCmd(cmd) - - return cmd -} - -// GetCmdQueryClientConnections defines the command to query a client connections -func GetCmdQueryClientConnections() *cobra.Command { - cmd := &cobra.Command{ - Use: "path [client-id]", - Short: "Query stored client connection paths", - Long: "Query stored client connection paths", - Example: fmt.Sprintf("%s query %s %s path [client-id]", version.AppName, host.ModuleName, types.SubModuleName), - Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } - clientID := args[0] - prove, _ := cmd.Flags().GetBool(flags.FlagProve) - - connPathsRes, err := utils.QueryClientConnections(clientCtx, clientID, prove) - if err != nil { - return err - } - - clientCtx = clientCtx.WithHeight(int64(connPathsRes.ProofHeight.RevisionHeight)) - return clientCtx.PrintProto(connPathsRes) - }, - } - - cmd.Flags().Bool(flags.FlagProve, true, "show proofs for the query results") - flags.AddQueryFlagsToCmd(cmd) - - return cmd -} diff --git a/x/ibc/core/03-connection/client/cli/tx.go b/x/ibc/core/03-connection/client/cli/tx.go deleted file mode 100644 index 68b1a6208200..000000000000 --- a/x/ibc/core/03-connection/client/cli/tx.go +++ /dev/null @@ -1,348 +0,0 @@ -package cli - -import ( - "fmt" - "io/ioutil" - "strings" - - "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/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" - "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" -) - -const ( - flagVersionIdentifier = "version-identifier" - flagVersionFeatures = "version-features" - flagDelayPeriod = "delay-period" -) - -// NewConnectionOpenInitCmd defines the command to initialize a connection on -// chain A with a given counterparty chain B -func NewConnectionOpenInitCmd() *cobra.Command { - cmd := &cobra.Command{ - Use: "open-init [client-id] [counterparty-client-id] [path/to/counterparty_prefix.json]", - Short: "Initialize connection on chain A", - Long: `Initialize a connection on chain A with a given counterparty chain B. - - 'version-identifier' flag can be a single pre-selected version identifier to be used in the handshake. - - 'version-features' flag can be a list of features separated by commas to accompany the version identifier.`, - Example: fmt.Sprintf( - "%s tx %s %s open-init [client-id] [counterparty-client-id] [path/to/counterparty_prefix.json] --version-identifier=\"1.0\" --version-features=\"ORDER_UNORDERED\" --delay-period=500", - version.AppName, host.ModuleName, types.SubModuleName, - ), - Args: cobra.ExactArgs(3), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - clientID := args[0] - counterpartyClientID := args[1] - - counterpartyPrefix, err := utils.ParsePrefix(clientCtx.LegacyAmino, args[2]) - if err != nil { - return err - } - - var version *types.Version - versionIdentifier, _ := cmd.Flags().GetString(flagVersionIdentifier) - - if versionIdentifier != "" { - var features []string - - versionFeatures, _ := cmd.Flags().GetString(flagVersionFeatures) - if versionFeatures != "" { - features = strings.Split(versionFeatures, ",") - } - - version = types.NewVersion(versionIdentifier, features) - } - - delayPeriod, err := cmd.Flags().GetUint64(flagDelayPeriod) - if err != nil { - return err - } - - msg := types.NewMsgConnectionOpenInit( - clientID, counterpartyClientID, - counterpartyPrefix, version, delayPeriod, clientCtx.GetFromAddress(), - ) - - svcMsgClientConn := &msgservice.ServiceMsgClientConn{} - msgClient := types.NewMsgClient(svcMsgClientConn) - _, err = msgClient.ConnectionOpenInit(cmd.Context(), msg) - if err != nil { - return err - } - - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) - }, - } - - // NOTE: we should use empty default values since the user may not want to select a version - // at this step in the handshake. - cmd.Flags().String(flagVersionIdentifier, "", "version identifier to be used in the connection handshake version negotiation") - cmd.Flags().String(flagVersionFeatures, "", "version features list separated by commas without spaces. The features must function with the version identifier.") - cmd.Flags().Uint64(flagDelayPeriod, 0, "delay period that must pass before packet verification can pass against a consensus state") - flags.AddTxFlagsToCmd(cmd) - - return cmd -} - -// NewConnectionOpenTryCmd defines the command to relay a try open a connection on -// chain B -func NewConnectionOpenTryCmd() *cobra.Command { - cmd := &cobra.Command{ - Use: strings.TrimSpace(`open-try [connection-id] [client-id] -[counterparty-connection-id] [counterparty-client-id] [path/to/counterparty_prefix.json] [path/to/client_state.json] -[path/to/counterparty_version1.json,path/to/counterparty_version2.json...] [consensus-height] [proof-height] [path/to/proof_init.json] [path/to/proof_client.json] [path/to/proof_consensus.json]`), - Short: "initiate connection handshake between two chains", - Long: "Initialize a connection on chain A with a given counterparty chain B. Provide counterparty versions separated by commas", - Example: fmt.Sprintf( - `%s tx %s %s open-try connection-id] [client-id] \ -[counterparty-connection-id] [counterparty-client-id] [path/to/counterparty_prefix.json] [path/to/client_state.json]\ -[counterparty-versions] [consensus-height] [proof-height] [path/to/proof_init.json] [path/to/proof_client.json] [path/to/proof_consensus.json]`, - version.AppName, host.ModuleName, types.SubModuleName, - ), - Args: cobra.ExactArgs(12), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - connectionID := args[0] - clientID := args[1] - counterpartyConnectionID := args[2] - counterpartyClientID := args[3] - - counterpartyPrefix, err := utils.ParsePrefix(clientCtx.LegacyAmino, args[4]) - if err != nil { - return err - } - - counterpartyClient, err := utils.ParseClientState(clientCtx.LegacyAmino, args[5]) - if err != nil { - return err - } - - cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry) - - versionsStr := strings.Split(args[6], ",") - counterpartyVersions := make([]*types.Version, len(versionsStr)) - - for _, ver := range versionsStr { - - // attempt to unmarshal version - version := &types.Version{} - if err := cdc.UnmarshalJSON([]byte(ver), version); err != nil { - - // check for file path if JSON input is not provided - contents, err := ioutil.ReadFile(ver) - if err != nil { - return errors.Wrap(err, "neither JSON input nor path to .json file for version were provided") - } - - if err := cdc.UnmarshalJSON(contents, version); err != nil { - return errors.Wrap(err, "error unmarshalling version file") - } - } - } - - consensusHeight, err := clienttypes.ParseHeight(args[7]) - if err != nil { - return err - } - proofHeight, err := clienttypes.ParseHeight(args[8]) - if err != nil { - return err - } - - proofInit, err := utils.ParseProof(clientCtx.LegacyAmino, args[9]) - if err != nil { - return err - } - - proofClient, err := utils.ParseProof(clientCtx.LegacyAmino, args[10]) - if err != nil { - return err - } - - proofConsensus, err := utils.ParseProof(clientCtx.LegacyAmino, args[11]) - if err != nil { - return err - } - - delayPeriod, err := cmd.Flags().GetUint64(flagDelayPeriod) - if err != nil { - return err - } - - msg := types.NewMsgConnectionOpenTry( - connectionID, clientID, counterpartyConnectionID, counterpartyClientID, - counterpartyClient, counterpartyPrefix, counterpartyVersions, delayPeriod, - proofInit, proofClient, proofConsensus, proofHeight, - consensusHeight, clientCtx.GetFromAddress(), - ) - - svcMsgClientConn := &msgservice.ServiceMsgClientConn{} - msgClient := types.NewMsgClient(svcMsgClientConn) - _, err = msgClient.ConnectionOpenTry(cmd.Context(), msg) - if err != nil { - return err - } - - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) - }, - } - - cmd.Flags().Uint64(flagDelayPeriod, 0, "delay period that must pass before packet verification can pass against a consensus state") - flags.AddTxFlagsToCmd(cmd) - - return cmd -} - -// NewConnectionOpenAckCmd defines the command to relay the acceptance of a -// connection open attempt from chain B to chain A -func NewConnectionOpenAckCmd() *cobra.Command { - cmd := &cobra.Command{ - Use: `open-ack [connection-id] [counterparty-connection-id] [path/to/client_state.json] [consensus-height] [proof-height] - [path/to/proof_try.json] [path/to/proof_client.json] [path/to/proof_consensus.json] [version]`, - Short: "relay the acceptance of a connection open attempt", - Long: "Relay the acceptance of a connection open attempt from chain B to chain A", - Example: fmt.Sprintf( - `%s tx %s %s open-ack [connection-id] [counterparty-connection-id] [path/to/client_state.json] [consensus-height] [proof-height] - [path/to/proof_try.json] [path/to/proof_client.json] [path/to/proof_consensus.json] [version]`, - version.AppName, host.ModuleName, types.SubModuleName, - ), - Args: cobra.ExactArgs(9), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - connectionID := args[0] - counterpartyConnectionID := args[1] - - counterpartyClient, err := utils.ParseClientState(clientCtx.LegacyAmino, args[2]) - if err != nil { - return err - } - - consensusHeight, err := clienttypes.ParseHeight(args[3]) - if err != nil { - return err - } - proofHeight, err := clienttypes.ParseHeight(args[4]) - if err != nil { - return err - } - - proofTry, err := utils.ParseProof(clientCtx.LegacyAmino, args[5]) - if err != nil { - return err - } - - proofClient, err := utils.ParseProof(clientCtx.LegacyAmino, args[6]) - if err != nil { - return err - } - - proofConsensus, err := utils.ParseProof(clientCtx.LegacyAmino, args[7]) - if err != nil { - return err - } - - cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry) - - // attempt to unmarshal version - version := &types.Version{} - if err := cdc.UnmarshalJSON([]byte(args[8]), version); err != nil { - - // check for file path if JSON input is not provided - contents, err := ioutil.ReadFile(args[8]) - if err != nil { - return errors.Wrap(err, "neither JSON input nor path to .json file for version were provided") - } - - if err := cdc.UnmarshalJSON(contents, version); err != nil { - return errors.Wrap(err, "error unmarshalling version file") - } - } - - msg := types.NewMsgConnectionOpenAck( - connectionID, counterpartyConnectionID, counterpartyClient, proofTry, proofClient, proofConsensus, proofHeight, - consensusHeight, version, clientCtx.GetFromAddress(), - ) - - svcMsgClientConn := &msgservice.ServiceMsgClientConn{} - msgClient := types.NewMsgClient(svcMsgClientConn) - _, err = msgClient.ConnectionOpenAck(cmd.Context(), msg) - if err != nil { - return err - } - - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) - }, - } - - flags.AddTxFlagsToCmd(cmd) - - return cmd -} - -// NewConnectionOpenConfirmCmd defines the command to initialize a connection on -// chain A with a given counterparty chain B -func NewConnectionOpenConfirmCmd() *cobra.Command { - cmd := &cobra.Command{ - Use: "open-confirm [connection-id] [proof-height] [path/to/proof_ack.json]", - Short: "confirm to chain B that connection is open on chain A", - Long: "Confirm to chain B that connection is open on chain A", - Example: fmt.Sprintf( - "%s tx %s %s open-confirm [connection-id] [proof-height] [path/to/proof_ack.json]", - version.AppName, host.ModuleName, types.SubModuleName, - ), - Args: cobra.ExactArgs(3), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - connectionID := args[0] - proofHeight, err := clienttypes.ParseHeight(args[1]) - if err != nil { - return err - } - - proofAck, err := utils.ParseProof(clientCtx.LegacyAmino, args[2]) - if err != nil { - return err - } - - msg := types.NewMsgConnectionOpenConfirm( - connectionID, proofAck, proofHeight, clientCtx.GetFromAddress(), - ) - - svcMsgClientConn := &msgservice.ServiceMsgClientConn{} - msgClient := types.NewMsgClient(svcMsgClientConn) - _, err = msgClient.ConnectionOpenConfirm(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/ibc/core/03-connection/client/utils/utils.go b/x/ibc/core/03-connection/client/utils/utils.go deleted file mode 100644 index e1eb1ce00c55..000000000000 --- a/x/ibc/core/03-connection/client/utils/utils.go +++ /dev/null @@ -1,219 +0,0 @@ -package utils - -import ( - "context" - "fmt" - "io/ioutil" - - "github.com/pkg/errors" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - clientutils "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/client/utils" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - ibcclient "github.com/cosmos/cosmos-sdk/x/ibc/core/client" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -// QueryConnection returns a connection end. -// If prove is true, it performs an ABCI store query in order to retrieve the merkle proof. Otherwise, -// it uses the gRPC query client. -func QueryConnection( - clientCtx client.Context, connectionID string, prove bool, -) (*types.QueryConnectionResponse, error) { - if prove { - return queryConnectionABCI(clientCtx, connectionID) - } - - queryClient := types.NewQueryClient(clientCtx) - req := &types.QueryConnectionRequest{ - ConnectionId: connectionID, - } - - return queryClient.Connection(context.Background(), req) -} - -func queryConnectionABCI(clientCtx client.Context, connectionID string) (*types.QueryConnectionResponse, error) { - key := host.ConnectionKey(connectionID) - - value, proofBz, proofHeight, err := ibcclient.QueryTendermintProof(clientCtx, key) - if err != nil { - return nil, err - } - - // check if connection exists - if len(value) == 0 { - return nil, sdkerrors.Wrap(types.ErrConnectionNotFound, connectionID) - } - - cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry) - - var connection types.ConnectionEnd - if err := cdc.UnmarshalBinaryBare(value, &connection); err != nil { - return nil, err - } - - return types.NewQueryConnectionResponse(connection, proofBz, proofHeight), nil -} - -// QueryClientConnections queries the connection paths registered for a particular client. -// If prove is true, it performs an ABCI store query in order to retrieve the merkle proof. Otherwise, -// it uses the gRPC query client. -func QueryClientConnections( - clientCtx client.Context, clientID string, prove bool, -) (*types.QueryClientConnectionsResponse, error) { - if prove { - return queryClientConnectionsABCI(clientCtx, clientID) - } - - queryClient := types.NewQueryClient(clientCtx) - req := &types.QueryClientConnectionsRequest{ - ClientId: clientID, - } - - return queryClient.ClientConnections(context.Background(), req) -} - -func queryClientConnectionsABCI(clientCtx client.Context, clientID string) (*types.QueryClientConnectionsResponse, error) { - key := host.ClientConnectionsKey(clientID) - - value, proofBz, proofHeight, err := ibcclient.QueryTendermintProof(clientCtx, key) - if err != nil { - return nil, err - } - - // check if connection paths exist - if len(value) == 0 { - return nil, sdkerrors.Wrap(types.ErrClientConnectionPathsNotFound, clientID) - } - - var paths []string - if err := clientCtx.LegacyAmino.UnmarshalBinaryBare(value, &paths); err != nil { - return nil, err - } - - return types.NewQueryClientConnectionsResponse(paths, proofBz, proofHeight), nil -} - -// QueryConnectionClientState returns the ClientState of a connection end. If -// prove is true, it performs an ABCI store query in order to retrieve the -// merkle proof. Otherwise, it uses the gRPC query client. -func QueryConnectionClientState( - clientCtx client.Context, connectionID string, prove bool, -) (*types.QueryConnectionClientStateResponse, error) { - - queryClient := types.NewQueryClient(clientCtx) - req := &types.QueryConnectionClientStateRequest{ - ConnectionId: connectionID, - } - - res, err := queryClient.ConnectionClientState(context.Background(), req) - if err != nil { - return nil, err - } - - if prove { - clientStateRes, err := clientutils.QueryClientStateABCI(clientCtx, res.IdentifiedClientState.ClientId) - if err != nil { - return nil, err - } - - // use client state returned from ABCI query in case query height differs - identifiedClientState := clienttypes.IdentifiedClientState{ - ClientId: res.IdentifiedClientState.ClientId, - ClientState: clientStateRes.ClientState, - } - - res = types.NewQueryConnectionClientStateResponse(identifiedClientState, clientStateRes.Proof, clientStateRes.ProofHeight) - } - - return res, nil -} - -// QueryConnectionConsensusState returns the ConsensusState of a connection end. If -// prove is true, it performs an ABCI store query in order to retrieve the -// merkle proof. Otherwise, it uses the gRPC query client. -func QueryConnectionConsensusState( - clientCtx client.Context, connectionID string, height clienttypes.Height, prove bool, -) (*types.QueryConnectionConsensusStateResponse, error) { - - queryClient := types.NewQueryClient(clientCtx) - req := &types.QueryConnectionConsensusStateRequest{ - ConnectionId: connectionID, - RevisionNumber: height.RevisionNumber, - RevisionHeight: height.RevisionHeight, - } - - res, err := queryClient.ConnectionConsensusState(context.Background(), req) - if err != nil { - return nil, err - } - - if prove { - consensusStateRes, err := clientutils.QueryConsensusStateABCI(clientCtx, res.ClientId, height) - if err != nil { - return nil, err - } - - res = types.NewQueryConnectionConsensusStateResponse(res.ClientId, consensusStateRes.ConsensusState, height, consensusStateRes.Proof, consensusStateRes.ProofHeight) - } - - return res, nil -} - -// ParseClientState unmarshals a cmd input argument from a JSON string to a client state -// If the input is not a JSON, it looks for a path to the JSON file -func ParseClientState(cdc *codec.LegacyAmino, arg string) (exported.ClientState, error) { - var clientState exported.ClientState - if err := cdc.UnmarshalJSON([]byte(arg), &clientState); err != nil { - // check for file path if JSON input is not provided - contents, err := ioutil.ReadFile(arg) - if err != nil { - return nil, errors.New("either JSON input nor path to .json file were provided") - } - if err := cdc.UnmarshalJSON(contents, &clientState); err != nil { - return nil, errors.Wrap(err, "error unmarshalling client state") - } - } - return clientState, nil -} - -// ParsePrefix unmarshals an cmd input argument from a JSON string to a commitment -// Prefix. If the input is not a JSON, it looks for a path to the JSON file. -func ParsePrefix(cdc *codec.LegacyAmino, arg string) (commitmenttypes.MerklePrefix, error) { - var prefix commitmenttypes.MerklePrefix - if err := cdc.UnmarshalJSON([]byte(arg), &prefix); err != nil { - // check for file path if JSON input is not provided - contents, err := ioutil.ReadFile(arg) - if err != nil { - return commitmenttypes.MerklePrefix{}, errors.New("neither JSON input nor path to .json file were provided") - } - if err := cdc.UnmarshalJSON(contents, &prefix); err != nil { - return commitmenttypes.MerklePrefix{}, errors.Wrap(err, "error unmarshalling commitment prefix") - } - } - return prefix, nil -} - -// ParseProof unmarshals a cmd input argument from a JSON string to a commitment -// Proof. If the input is not a JSON, it looks for a path to the JSON file. It -// then marshals the commitment proof into a proto encoded byte array. -func ParseProof(cdc *codec.LegacyAmino, arg string) ([]byte, error) { - var merkleProof commitmenttypes.MerkleProof - if err := cdc.UnmarshalJSON([]byte(arg), &merkleProof); err != nil { - // check for file path if JSON input is not provided - contents, err := ioutil.ReadFile(arg) - if err != nil { - return nil, errors.New("neither JSON input nor path to .json file were provided") - } - if err := cdc.UnmarshalJSON(contents, &merkleProof); err != nil { - return nil, fmt.Errorf("error unmarshalling commitment proof: %w", err) - } - } - - return cdc.MarshalBinaryBare(&merkleProof) -} diff --git a/x/ibc/core/03-connection/genesis.go b/x/ibc/core/03-connection/genesis.go deleted file mode 100644 index a1bb30f1fe56..000000000000 --- a/x/ibc/core/03-connection/genesis.go +++ /dev/null @@ -1,28 +0,0 @@ -package connection - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/keeper" - "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" -) - -// InitGenesis initializes the ibc connection submodule's state from a provided genesis -// state. -func InitGenesis(ctx sdk.Context, k keeper.Keeper, gs types.GenesisState) { - for _, connection := range gs.Connections { - conn := types.NewConnectionEnd(connection.State, connection.ClientId, connection.Counterparty, connection.Versions, connection.DelayPeriod) - k.SetConnection(ctx, connection.Id, conn) - } - for _, connPaths := range gs.ClientConnectionPaths { - k.SetClientConnectionPaths(ctx, connPaths.ClientId, connPaths.Paths) - } - k.SetNextConnectionSequence(ctx, gs.NextConnectionSequence) -} - -// ExportGenesis returns the ibc connection submodule's exported genesis. -func ExportGenesis(ctx sdk.Context, k keeper.Keeper) types.GenesisState { - return types.GenesisState{ - Connections: k.GetAllConnections(ctx), - ClientConnectionPaths: k.GetAllClientConnectionPaths(ctx), - } -} diff --git a/x/ibc/core/03-connection/keeper/grpc_query.go b/x/ibc/core/03-connection/keeper/grpc_query.go deleted file mode 100644 index 62b1c00a3498..000000000000 --- a/x/ibc/core/03-connection/keeper/grpc_query.go +++ /dev/null @@ -1,179 +0,0 @@ -package keeper - -import ( - "context" - - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - - "github.com/cosmos/cosmos-sdk/store/prefix" - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/cosmos/cosmos-sdk/types/query" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" -) - -var _ types.QueryServer = Keeper{} - -// Connection implements the Query/Connection gRPC method -func (q Keeper) Connection(c context.Context, req *types.QueryConnectionRequest) (*types.QueryConnectionResponse, error) { - if req == nil { - return nil, status.Error(codes.InvalidArgument, "empty request") - } - - if err := host.ConnectionIdentifierValidator(req.ConnectionId); err != nil { - return nil, status.Error(codes.InvalidArgument, err.Error()) - } - - ctx := sdk.UnwrapSDKContext(c) - connection, found := q.GetConnection(ctx, req.ConnectionId) - if !found { - return nil, status.Error( - codes.NotFound, - sdkerrors.Wrap(types.ErrConnectionNotFound, req.ConnectionId).Error(), - ) - } - - return &types.QueryConnectionResponse{ - Connection: &connection, - ProofHeight: clienttypes.GetSelfHeight(ctx), - }, nil -} - -// Connections implements the Query/Connections gRPC method -func (q Keeper) Connections(c context.Context, req *types.QueryConnectionsRequest) (*types.QueryConnectionsResponse, error) { - if req == nil { - return nil, status.Error(codes.InvalidArgument, "empty request") - } - - ctx := sdk.UnwrapSDKContext(c) - - connections := []*types.IdentifiedConnection{} - store := prefix.NewStore(ctx.KVStore(q.storeKey), []byte(host.KeyConnectionPrefix)) - - pageRes, err := query.Paginate(store, req.Pagination, func(key, value []byte) error { - var result types.ConnectionEnd - if err := q.cdc.UnmarshalBinaryBare(value, &result); err != nil { - return err - } - - connectionID, err := host.ParseConnectionPath(string(key)) - if err != nil { - return err - } - - identifiedConnection := types.NewIdentifiedConnection(connectionID, result) - connections = append(connections, &identifiedConnection) - return nil - }) - - if err != nil { - return nil, err - } - - return &types.QueryConnectionsResponse{ - Connections: connections, - Pagination: pageRes, - Height: clienttypes.GetSelfHeight(ctx), - }, nil -} - -// ClientConnections implements the Query/ClientConnections gRPC method -func (q Keeper) ClientConnections(c context.Context, req *types.QueryClientConnectionsRequest) (*types.QueryClientConnectionsResponse, error) { - if req == nil { - return nil, status.Error(codes.InvalidArgument, "empty request") - } - - if err := host.ClientIdentifierValidator(req.ClientId); err != nil { - return nil, status.Error(codes.InvalidArgument, err.Error()) - } - - ctx := sdk.UnwrapSDKContext(c) - clientConnectionPaths, found := q.GetClientConnectionPaths(ctx, req.ClientId) - if !found { - return nil, status.Error( - codes.NotFound, - sdkerrors.Wrap(types.ErrClientConnectionPathsNotFound, req.ClientId).Error(), - ) - } - - return &types.QueryClientConnectionsResponse{ - ConnectionPaths: clientConnectionPaths, - ProofHeight: clienttypes.GetSelfHeight(ctx), - }, nil -} - -// ConnectionClientState implements the Query/ConnectionClientState gRPC method -func (q Keeper) ConnectionClientState(c context.Context, req *types.QueryConnectionClientStateRequest) (*types.QueryConnectionClientStateResponse, error) { - if req == nil { - return nil, status.Error(codes.InvalidArgument, "empty request") - } - - if err := host.ConnectionIdentifierValidator(req.ConnectionId); err != nil { - return nil, status.Error(codes.InvalidArgument, err.Error()) - } - - ctx := sdk.UnwrapSDKContext(c) - - connection, found := q.GetConnection(ctx, req.ConnectionId) - if !found { - return nil, status.Error( - codes.NotFound, - sdkerrors.Wrapf(types.ErrConnectionNotFound, "connection-id: %s", req.ConnectionId).Error(), - ) - } - - clientState, found := q.clientKeeper.GetClientState(ctx, connection.ClientId) - if !found { - return nil, status.Error( - codes.NotFound, - sdkerrors.Wrapf(clienttypes.ErrClientNotFound, "client-id: %s", connection.ClientId).Error(), - ) - } - - identifiedClientState := clienttypes.NewIdentifiedClientState(connection.ClientId, clientState) - - height := clienttypes.GetSelfHeight(ctx) - return types.NewQueryConnectionClientStateResponse(identifiedClientState, nil, height), nil - -} - -// ConnectionConsensusState implements the Query/ConnectionConsensusState gRPC method -func (q Keeper) ConnectionConsensusState(c context.Context, req *types.QueryConnectionConsensusStateRequest) (*types.QueryConnectionConsensusStateResponse, error) { - if req == nil { - return nil, status.Error(codes.InvalidArgument, "empty request") - } - - if err := host.ConnectionIdentifierValidator(req.ConnectionId); err != nil { - return nil, status.Error(codes.InvalidArgument, err.Error()) - } - - ctx := sdk.UnwrapSDKContext(c) - - connection, found := q.GetConnection(ctx, req.ConnectionId) - if !found { - return nil, status.Error( - codes.NotFound, - sdkerrors.Wrapf(types.ErrConnectionNotFound, "connection-id: %s", req.ConnectionId).Error(), - ) - } - - height := clienttypes.NewHeight(req.RevisionNumber, req.RevisionHeight) - consensusState, found := q.clientKeeper.GetClientConsensusState(ctx, connection.ClientId, height) - if !found { - return nil, status.Error( - codes.NotFound, - sdkerrors.Wrapf(clienttypes.ErrConsensusStateNotFound, "client-id: %s", connection.ClientId).Error(), - ) - } - - anyConsensusState, err := clienttypes.PackConsensusState(consensusState) - if err != nil { - return nil, status.Error(codes.Internal, err.Error()) - } - - proofHeight := clienttypes.GetSelfHeight(ctx) - return types.NewQueryConnectionConsensusStateResponse(connection.ClientId, anyConsensusState, height, nil, proofHeight), nil -} diff --git a/x/ibc/core/03-connection/keeper/grpc_query_test.go b/x/ibc/core/03-connection/keeper/grpc_query_test.go deleted file mode 100644 index 14fdb425d9eb..000000000000 --- a/x/ibc/core/03-connection/keeper/grpc_query_test.go +++ /dev/null @@ -1,420 +0,0 @@ -package keeper_test - -import ( - "fmt" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/query" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" -) - -func (suite *KeeperTestSuite) TestQueryConnection() { - var ( - req *types.QueryConnectionRequest - expConnection types.ConnectionEnd - ) - - testCases := []struct { - msg string - malleate func() - expPass bool - }{ - { - "empty request", - func() { - req = nil - }, - false, - }, - {"invalid connectionID", - func() { - req = &types.QueryConnectionRequest{} - }, - false, - }, - {"connection not found", - func() { - req = &types.QueryConnectionRequest{ - ConnectionId: ibctesting.InvalidID, - } - }, - false, - }, - { - "success", - func() { - clientA, clientB := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - connA := suite.chainA.GetFirstTestConnection(clientA, clientB) - connB := suite.chainB.GetFirstTestConnection(clientB, clientA) - - counterparty := types.NewCounterparty(clientB, connB.ID, suite.chainB.GetPrefix()) - expConnection = types.NewConnectionEnd(types.INIT, clientA, counterparty, types.ExportedVersionsToProto(types.GetCompatibleVersions()), 500) - suite.chainA.App.IBCKeeper.ConnectionKeeper.SetConnection(suite.chainA.GetContext(), connA.ID, expConnection) - - req = &types.QueryConnectionRequest{ - ConnectionId: connA.ID, - } - }, - true, - }, - } - - for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { - suite.SetupTest() // reset - - tc.malleate() - ctx := sdk.WrapSDKContext(suite.chainA.GetContext()) - - res, err := suite.chainA.QueryServer.Connection(ctx, req) - - if tc.expPass { - suite.Require().NoError(err) - suite.Require().NotNil(res) - suite.Require().Equal(&expConnection, res.Connection) - } else { - suite.Require().Error(err) - } - }) - } -} - -func (suite *KeeperTestSuite) TestQueryConnections() { - var ( - req *types.QueryConnectionsRequest - expConnections = []*types.IdentifiedConnection{} - ) - - testCases := []struct { - msg string - malleate func() - expPass bool - }{ - { - "empty request", - func() { - req = nil - }, - false, - }, - { - "empty pagination", - func() { - req = &types.QueryConnectionsRequest{} - }, - true, - }, - { - "success", - func() { - clientA, clientB, connA0, connB0 := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - clientA1, clientB1, connA1, connB1 := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - connA2, _, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB) - suite.Require().NoError(err) - - counterparty1 := types.NewCounterparty(clientB, connB0.ID, suite.chainB.GetPrefix()) - counterparty2 := types.NewCounterparty(clientB1, connB1.ID, suite.chainB.GetPrefix()) - // counterparty connection id is blank after open init - counterparty3 := types.NewCounterparty(clientB, "", suite.chainB.GetPrefix()) - - conn1 := types.NewConnectionEnd(types.OPEN, clientA, counterparty1, types.ExportedVersionsToProto(types.GetCompatibleVersions()), 0) - conn2 := types.NewConnectionEnd(types.OPEN, clientA1, counterparty2, types.ExportedVersionsToProto(types.GetCompatibleVersions()), 0) - conn3 := types.NewConnectionEnd(types.INIT, clientA, counterparty3, types.ExportedVersionsToProto(types.GetCompatibleVersions()), 0) - - iconn1 := types.NewIdentifiedConnection(connA0.ID, conn1) - iconn2 := types.NewIdentifiedConnection(connA1.ID, conn2) - iconn3 := types.NewIdentifiedConnection(connA2.ID, conn3) - - expConnections = []*types.IdentifiedConnection{&iconn1, &iconn2, &iconn3} - - req = &types.QueryConnectionsRequest{ - Pagination: &query.PageRequest{ - Limit: 3, - 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.chainA.GetContext()) - - res, err := suite.chainA.QueryServer.Connections(ctx, req) - - if tc.expPass { - suite.Require().NoError(err) - suite.Require().NotNil(res) - suite.Require().Equal(expConnections, res.Connections) - } else { - suite.Require().Error(err) - } - }) - } -} - -func (suite *KeeperTestSuite) TestQueryClientConnections() { - var ( - req *types.QueryClientConnectionsRequest - expPaths []string - ) - - testCases := []struct { - msg string - malleate func() - expPass bool - }{ - { - "empty request", - func() { - req = nil - }, - false, - }, - {"invalid connectionID", - func() { - req = &types.QueryClientConnectionsRequest{} - }, - false, - }, - {"connection not found", - func() { - req = &types.QueryClientConnectionsRequest{ - ClientId: ibctesting.InvalidID, - } - }, - false, - }, - { - "success", - func() { - clientA, clientB, connA0, _ := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - connA1, _ := suite.coordinator.CreateConnection(suite.chainA, suite.chainB, clientA, clientB) - expPaths = []string{connA0.ID, connA1.ID} - suite.chainA.App.IBCKeeper.ConnectionKeeper.SetClientConnectionPaths(suite.chainA.GetContext(), clientA, expPaths) - - req = &types.QueryClientConnectionsRequest{ - ClientId: clientA, - } - }, - true, - }, - } - - for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { - suite.SetupTest() // reset - - tc.malleate() - ctx := sdk.WrapSDKContext(suite.chainA.GetContext()) - - res, err := suite.chainA.QueryServer.ClientConnections(ctx, req) - - if tc.expPass { - suite.Require().NoError(err) - suite.Require().NotNil(res) - suite.Require().Equal(expPaths, res.ConnectionPaths) - } else { - suite.Require().Error(err) - } - }) - } -} - -func (suite *KeeperTestSuite) TestQueryConnectionClientState() { - var ( - req *types.QueryConnectionClientStateRequest - expIdentifiedClientState clienttypes.IdentifiedClientState - ) - - testCases := []struct { - msg string - malleate func() - expPass bool - }{ - { - "empty request", - func() { - req = nil - }, - false, - }, - { - "invalid connection ID", - func() { - req = &types.QueryConnectionClientStateRequest{ - ConnectionId: "", - } - }, - false, - }, - { - "connection not found", - func() { - req = &types.QueryConnectionClientStateRequest{ - ConnectionId: "test-connection-id", - } - }, - false, - }, - { - "client state not found", - func() { - _, _, connA, _, _, _ := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.UNORDERED) - - // set connection to empty so clientID is empty - suite.chainA.App.IBCKeeper.ConnectionKeeper.SetConnection(suite.chainA.GetContext(), connA.ID, types.ConnectionEnd{}) - - req = &types.QueryConnectionClientStateRequest{ - ConnectionId: connA.ID, - } - }, false, - }, - { - "success", - func() { - clientA, _, connA, _ := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - - expClientState := suite.chainA.GetClientState(clientA) - expIdentifiedClientState = clienttypes.NewIdentifiedClientState(clientA, expClientState) - - req = &types.QueryConnectionClientStateRequest{ - ConnectionId: connA.ID, - } - }, - true, - }, - } - - for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { - suite.SetupTest() // reset - - tc.malleate() - ctx := sdk.WrapSDKContext(suite.chainA.GetContext()) - - res, err := suite.chainA.QueryServer.ConnectionClientState(ctx, req) - - if tc.expPass { - 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) - } - }) - } -} - -func (suite *KeeperTestSuite) TestQueryConnectionConsensusState() { - var ( - req *types.QueryConnectionConsensusStateRequest - expConsensusState exported.ConsensusState - expClientID string - ) - - testCases := []struct { - msg string - malleate func() - expPass bool - }{ - { - "empty request", - func() { - req = nil - }, - false, - }, - { - "invalid connection ID", - func() { - req = &types.QueryConnectionConsensusStateRequest{ - ConnectionId: "", - RevisionNumber: 0, - RevisionHeight: 1, - } - }, - false, - }, - { - "connection not found", - func() { - req = &types.QueryConnectionConsensusStateRequest{ - ConnectionId: "test-connection-id", - RevisionNumber: 0, - RevisionHeight: 1, - } - }, - false, - }, - { - "consensus state not found", - func() { - _, _, connA, _, _, _ := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.UNORDERED) - - req = &types.QueryConnectionConsensusStateRequest{ - ConnectionId: connA.ID, - RevisionNumber: 0, - RevisionHeight: uint64(suite.chainA.GetContext().BlockHeight()), // use current height - } - }, false, - }, - { - "success", - func() { - clientA, _, connA, _ := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - - clientState := suite.chainA.GetClientState(clientA) - expConsensusState, _ = suite.chainA.GetConsensusState(clientA, clientState.GetLatestHeight()) - suite.Require().NotNil(expConsensusState) - expClientID = clientA - - req = &types.QueryConnectionConsensusStateRequest{ - ConnectionId: connA.ID, - RevisionNumber: clientState.GetLatestHeight().GetRevisionNumber(), - RevisionHeight: clientState.GetLatestHeight().GetRevisionHeight(), - } - }, - true, - }, - } - - for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { - suite.SetupTest() // reset - - tc.malleate() - ctx := sdk.WrapSDKContext(suite.chainA.GetContext()) - - res, err := suite.chainA.QueryServer.ConnectionConsensusState(ctx, req) - - if tc.expPass { - suite.Require().NoError(err) - suite.Require().NotNil(res) - consensusState, err := clienttypes.UnpackConsensusState(res.ConsensusState) - 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/keeper/handshake.go b/x/ibc/core/03-connection/keeper/handshake.go deleted file mode 100644 index b8f7466f159b..000000000000 --- a/x/ibc/core/03-connection/keeper/handshake.go +++ /dev/null @@ -1,342 +0,0 @@ -package keeper - -import ( - "bytes" - - "github.com/gogo/protobuf/proto" - - "github.com/cosmos/cosmos-sdk/telemetry" - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -// ConnOpenInit initialises a connection attempt on chain A. The generated connection identifier -// is returned. -// -// NOTE: Msg validation verifies the supplied identifiers and ensures that the counterparty -// connection identifier is empty. -func (k Keeper) ConnOpenInit( - ctx sdk.Context, - clientID string, - counterparty types.Counterparty, // counterpartyPrefix, counterpartyClientIdentifier - version *types.Version, - delayPeriod uint64, -) (string, error) { - versions := types.GetCompatibleVersions() - if version != nil { - if !types.IsSupportedVersion(version) { - return "", sdkerrors.Wrap(types.ErrInvalidVersion, "version is not supported") - } - - versions = []exported.Version{version} - } - - // connection defines chain A's ConnectionEnd - connectionID := k.GenerateConnectionIdentifier(ctx) - connection := types.NewConnectionEnd(types.INIT, clientID, counterparty, types.ExportedVersionsToProto(versions), delayPeriod) - k.SetConnection(ctx, connectionID, connection) - - if err := k.addConnectionToClient(ctx, clientID, connectionID); err != nil { - return "", err - } - - k.Logger(ctx).Info("connection state updated", "connection-id", connectionID, "previous-state", "NONE", "new-state", "INIT") - - defer func() { - telemetry.IncrCounter(1, "ibc", "connection", "open-init") - }() - - return connectionID, nil -} - -// ConnOpenTry relays notice of a connection attempt on chain A to chain B (this -// code is executed on chain B). -// -// NOTE: -// - Here chain A acts as the counterparty -// - Identifiers are checked on msg validation -func (k Keeper) ConnOpenTry( - ctx sdk.Context, - previousConnectionID string, // previousIdentifier - counterparty types.Counterparty, // counterpartyConnectionIdentifier, counterpartyPrefix and counterpartyClientIdentifier - delayPeriod uint64, - clientID string, // clientID of chainA - clientState exported.ClientState, // clientState that chainA has for chainB - counterpartyVersions []exported.Version, // supported versions of chain A - proofInit []byte, // proof that chainA stored connectionEnd in state (on ConnOpenInit) - proofClient []byte, // proof that chainA stored a light client of chainB - proofConsensus []byte, // proof that chainA stored chainB's consensus state at consensus height - proofHeight exported.Height, // height at which relayer constructs proof of A storing connectionEnd in state - consensusHeight exported.Height, // latest height of chain B which chain A has stored in its chain B client -) (string, error) { - var ( - connectionID string - previousConnection types.ConnectionEnd - found bool - ) - - // empty connection identifier indicates continuing a previous connection handshake - if previousConnectionID != "" { - // ensure that the previous connection exists - previousConnection, found = k.GetConnection(ctx, previousConnectionID) - if !found { - return "", sdkerrors.Wrapf(types.ErrConnectionNotFound, "previous connection does not exist for supplied previous connectionID %s", previousConnectionID) - } - - // ensure that the existing connection's - // counterparty is chainA and connection is on INIT stage. - // Check that existing connection versions for initialized connection is equal to compatible - // versions for this chain. - // ensure that existing connection's delay period is the same as desired delay period. - if !(previousConnection.Counterparty.ConnectionId == "" && - bytes.Equal(previousConnection.Counterparty.Prefix.Bytes(), counterparty.Prefix.Bytes()) && - previousConnection.ClientId == clientID && - previousConnection.Counterparty.ClientId == counterparty.ClientId && - previousConnection.DelayPeriod == delayPeriod) { - return "", sdkerrors.Wrap(types.ErrInvalidConnection, "connection fields mismatch previous connection fields") - } - - if !(previousConnection.State == types.INIT) { - return "", sdkerrors.Wrapf(types.ErrInvalidConnectionState, "previous connection state is in state %s, expected INIT", previousConnection.State) - } - - // continue with previous connection - connectionID = previousConnectionID - - } else { - // generate a new connection - connectionID = k.GenerateConnectionIdentifier(ctx) - } - - selfHeight := clienttypes.GetSelfHeight(ctx) - if consensusHeight.GTE(selfHeight) { - return "", sdkerrors.Wrapf( - sdkerrors.ErrInvalidHeight, - "consensus height is greater than or equal to the current block height (%s >= %s)", consensusHeight, selfHeight, - ) - } - - // validate client parameters of a chainB client stored on chainA - if err := k.clientKeeper.ValidateSelfClient(ctx, clientState); err != nil { - return "", err - } - - expectedConsensusState, found := k.clientKeeper.GetSelfConsensusState(ctx, consensusHeight) - if !found { - return "", sdkerrors.Wrap(clienttypes.ErrSelfConsensusStateNotFound, consensusHeight.String()) - } - - // expectedConnection defines Chain A's ConnectionEnd - // NOTE: chain A's counterparty is chain B (i.e where this code is executed) - // NOTE: chainA and chainB must have the same delay period - prefix := k.GetCommitmentPrefix() - expectedCounterparty := types.NewCounterparty(clientID, "", commitmenttypes.NewMerklePrefix(prefix.Bytes())) - expectedConnection := types.NewConnectionEnd(types.INIT, counterparty.ClientId, expectedCounterparty, types.ExportedVersionsToProto(counterpartyVersions), delayPeriod) - - supportedVersions := types.GetCompatibleVersions() - if len(previousConnection.Versions) != 0 { - supportedVersions = previousConnection.GetVersions() - } - - // chain B picks a version from Chain A's available versions that is compatible - // with Chain B's supported IBC versions. PickVersion will select the intersection - // of the supported versions and the counterparty versions. - version, err := types.PickVersion(supportedVersions, counterpartyVersions) - if err != nil { - return "", err - } - - // connection defines chain B's ConnectionEnd - connection := types.NewConnectionEnd(types.TRYOPEN, clientID, counterparty, []*types.Version{version}, delayPeriod) - - // Check that ChainA committed expectedConnectionEnd to its state - if err := k.VerifyConnectionState( - ctx, connection, proofHeight, proofInit, counterparty.ConnectionId, - expectedConnection, - ); err != nil { - return "", err - } - - // Check that ChainA stored the clientState provided in the msg - if err := k.VerifyClientState(ctx, connection, proofHeight, proofClient, clientState); err != nil { - return "", err - } - - // Check that ChainA stored the correct ConsensusState of chainB at the given consensusHeight - if err := k.VerifyClientConsensusState( - ctx, connection, proofHeight, consensusHeight, proofConsensus, expectedConsensusState, - ); err != nil { - return "", err - } - - // store connection in chainB state - if err := k.addConnectionToClient(ctx, clientID, connectionID); err != nil { - return "", sdkerrors.Wrapf(err, "failed to add connection with ID %s to client with ID %s", connectionID, clientID) - } - - k.SetConnection(ctx, connectionID, connection) - k.Logger(ctx).Info("connection state updated", "connection-id", connectionID, "previous-state", previousConnection.State.String(), "new-state", "TRYOPEN") - - defer func() { - telemetry.IncrCounter(1, "ibc", "connection", "open-try") - }() - - return connectionID, nil -} - -// ConnOpenAck relays acceptance of a connection open attempt from chain B back -// to chain A (this code is executed on chain A). -// -// NOTE: Identifiers are checked on msg validation. -func (k Keeper) ConnOpenAck( - ctx sdk.Context, - connectionID string, - clientState exported.ClientState, // client state for chainA on chainB - version *types.Version, // version that ChainB chose in ConnOpenTry - counterpartyConnectionID string, - proofTry []byte, // proof that connectionEnd was added to ChainB state in ConnOpenTry - proofClient []byte, // proof of client state on chainB for chainA - proofConsensus []byte, // proof that chainB has stored ConsensusState of chainA on its client - proofHeight exported.Height, // height that relayer constructed proofTry - consensusHeight exported.Height, // latest height of chainA that chainB has stored on its chainA client -) error { - // Check that chainB client hasn't stored invalid height - selfHeight := clienttypes.GetSelfHeight(ctx) - if consensusHeight.GTE(selfHeight) { - return sdkerrors.Wrapf( - sdkerrors.ErrInvalidHeight, - "consensus height is greater than or equal to the current block height (%s >= %s)", consensusHeight, selfHeight, - ) - } - - // Retrieve connection - connection, found := k.GetConnection(ctx, connectionID) - if !found { - return sdkerrors.Wrap(types.ErrConnectionNotFound, connectionID) - } - - // Verify the provided version against the previously set connection state - switch { - // connection on ChainA must be in INIT or TRYOPEN - case connection.State != types.INIT && connection.State != types.TRYOPEN: - return sdkerrors.Wrapf( - types.ErrInvalidConnectionState, - "connection state is not INIT or TRYOPEN (got %s)", connection.State.String(), - ) - - // if the connection is INIT then the provided version must be supproted - case connection.State == types.INIT && !types.IsSupportedVersion(version): - return sdkerrors.Wrapf( - types.ErrInvalidConnectionState, - "connection state is in INIT but the provided version is not supported %s", version, - ) - - // if the connection is in TRYOPEN then the version must be the only set version in the - // retreived connection state. - case connection.State == types.TRYOPEN && (len(connection.Versions) != 1 || !proto.Equal(connection.Versions[0], version)): - return sdkerrors.Wrapf( - types.ErrInvalidConnectionState, - "connection state is in TRYOPEN but the provided version (%s) is not set in the previous connection versions %s", version, connection.Versions, - ) - } - - // validate client parameters of a chainA client stored on chainB - if err := k.clientKeeper.ValidateSelfClient(ctx, clientState); err != nil { - return err - } - - // Retrieve chainA's consensus state at consensusheight - expectedConsensusState, found := k.clientKeeper.GetSelfConsensusState(ctx, consensusHeight) - if !found { - return clienttypes.ErrSelfConsensusStateNotFound - } - - prefix := k.GetCommitmentPrefix() - expectedCounterparty := types.NewCounterparty(connection.ClientId, connectionID, commitmenttypes.NewMerklePrefix(prefix.Bytes())) - expectedConnection := types.NewConnectionEnd(types.TRYOPEN, connection.Counterparty.ClientId, expectedCounterparty, []*types.Version{version}, connection.DelayPeriod) - - // Ensure that ChainB stored expected connectionEnd in its state during ConnOpenTry - if err := k.VerifyConnectionState( - ctx, connection, proofHeight, proofTry, counterpartyConnectionID, - expectedConnection, - ); err != nil { - return err - } - - // Check that ChainB stored the clientState provided in the msg - if err := k.VerifyClientState(ctx, connection, proofHeight, proofClient, clientState); err != nil { - return err - } - - // Ensure that ChainB has stored the correct ConsensusState for chainA at the consensusHeight - if err := k.VerifyClientConsensusState( - ctx, connection, proofHeight, consensusHeight, proofConsensus, expectedConsensusState, - ); err != nil { - return err - } - - k.Logger(ctx).Info("connection state updated", "connection-id", connectionID, "previous-state", connection.State.String(), "new-state", "OPEN") - - defer func() { - telemetry.IncrCounter(1, "ibc", "connection", "open-ack") - }() - - // Update connection state to Open - connection.State = types.OPEN - connection.Versions = []*types.Version{version} - connection.Counterparty.ConnectionId = counterpartyConnectionID - k.SetConnection(ctx, connectionID, connection) - return nil -} - -// ConnOpenConfirm confirms opening of a connection on chain A to chain B, after -// which the connection is open on both chains (this code is executed on chain B). -// -// NOTE: Identifiers are checked on msg validation. -func (k Keeper) ConnOpenConfirm( - ctx sdk.Context, - connectionID string, - proofAck []byte, // proof that connection opened on ChainA during ConnOpenAck - proofHeight exported.Height, // height that relayer constructed proofAck -) error { - // Retrieve connection - connection, found := k.GetConnection(ctx, connectionID) - if !found { - return sdkerrors.Wrap(types.ErrConnectionNotFound, connectionID) - } - - // Check that connection state on ChainB is on state: TRYOPEN - if connection.State != types.TRYOPEN { - return sdkerrors.Wrapf( - types.ErrInvalidConnectionState, - "connection state is not TRYOPEN (got %s)", connection.State.String(), - ) - } - - prefix := k.GetCommitmentPrefix() - expectedCounterparty := types.NewCounterparty(connection.ClientId, connectionID, commitmenttypes.NewMerklePrefix(prefix.Bytes())) - expectedConnection := types.NewConnectionEnd(types.OPEN, connection.Counterparty.ClientId, expectedCounterparty, connection.Versions, connection.DelayPeriod) - - // Check that connection on ChainA is open - if err := k.VerifyConnectionState( - ctx, connection, proofHeight, proofAck, connection.Counterparty.ConnectionId, - expectedConnection, - ); err != nil { - return err - } - - // Update ChainB's connection to Open - connection.State = types.OPEN - k.SetConnection(ctx, connectionID, connection) - k.Logger(ctx).Info("connection state updated", "connection-id", connectionID, "previous-state", "TRYOPEN", "new-state", "OPEN") - - defer func() { - telemetry.IncrCounter(1, "ibc", "connection", "open-confirm") - }() - - return nil -} diff --git a/x/ibc/core/03-connection/keeper/handshake_test.go b/x/ibc/core/03-connection/keeper/handshake_test.go deleted file mode 100644 index 101c061a7526..000000000000 --- a/x/ibc/core/03-connection/keeper/handshake_test.go +++ /dev/null @@ -1,701 +0,0 @@ -package keeper_test - -import ( - "time" - - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" -) - -// TestConnOpenInit - chainA initializes (INIT state) a connection with -// chainB which is yet UNINITIALIZED -func (suite *KeeperTestSuite) TestConnOpenInit() { - var ( - clientA string - clientB string - version *types.Version - delayPeriod uint64 - emptyConnBID bool - ) - - testCases := []struct { - msg string - malleate func() - expPass bool - }{ - {"success", func() { - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - }, true}, - {"success with empty counterparty identifier", func() { - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - emptyConnBID = true - }, true}, - {"success with non empty version", func() { - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - version = types.ExportedVersionsToProto(types.GetCompatibleVersions())[0] - }, true}, - {"success with non zero delayPeriod", func() { - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - delayPeriod = uint64(time.Hour.Nanoseconds()) - }, true}, - - {"invalid version", func() { - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - version = &types.Version{} - }, false}, - {"couldn't add connection to client", func() { - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - // set clientA to invalid client identifier - clientA = "clientidentifier" - }, false}, - } - - for _, tc := range testCases { - tc := tc - suite.Run(tc.msg, func() { - suite.SetupTest() // reset - emptyConnBID = false // must be explicitly changed - version = nil // must be explicitly changed - - tc.malleate() - - connB := suite.chainB.GetFirstTestConnection(clientB, clientA) - if emptyConnBID { - connB.ID = "" - } - counterparty := types.NewCounterparty(clientB, connB.ID, suite.chainB.GetPrefix()) - - connectionID, err := suite.chainA.App.IBCKeeper.ConnectionKeeper.ConnOpenInit(suite.chainA.GetContext(), clientA, counterparty, version, delayPeriod) - - if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(types.FormatConnectionIdentifier(0), connectionID) - } else { - suite.Require().Error(err) - suite.Require().Equal("", connectionID) - } - }) - } -} - -// TestConnOpenTry - chainB calls ConnOpenTry to verify the state of -// connection on chainA is INIT -func (suite *KeeperTestSuite) TestConnOpenTry() { - var ( - clientA string - clientB string - delayPeriod uint64 - previousConnectionID string - versions []exported.Version - consensusHeight exported.Height - counterpartyClient exported.ClientState - ) - - testCases := []struct { - msg string - malleate func() - expPass bool - }{ - {"success", func() { - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - _, _, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB) - suite.Require().NoError(err) - - // retrieve client state of chainA to pass as counterpartyClient - counterpartyClient = suite.chainA.GetClientState(clientA) - }, true}, - {"success with crossing hellos", func() { - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - _, connB, err := suite.coordinator.ConnOpenInitOnBothChains(suite.chainA, suite.chainB, clientA, clientB) - suite.Require().NoError(err) - - // retrieve client state of chainA to pass as counterpartyClient - counterpartyClient = suite.chainA.GetClientState(clientA) - - previousConnectionID = connB.ID - }, true}, - {"success with delay period", func() { - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - connA, _, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB) - suite.Require().NoError(err) - - delayPeriod = uint64(time.Hour.Nanoseconds()) - - // set delay period on counterparty to non-zero value - conn := suite.chainA.GetConnection(connA) - conn.DelayPeriod = delayPeriod - suite.chainA.App.IBCKeeper.ConnectionKeeper.SetConnection(suite.chainA.GetContext(), connA.ID, conn) - - // commit in order for proof to return correct value - suite.coordinator.CommitBlock(suite.chainA) - suite.coordinator.UpdateClient(suite.chainB, suite.chainA, clientB, exported.Tendermint) - - // retrieve client state of chainA to pass as counterpartyClient - counterpartyClient = suite.chainA.GetClientState(clientA) - }, true}, - {"invalid counterparty client", func() { - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - _, _, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB) - suite.Require().NoError(err) - - // retrieve client state of chainB to pass as counterpartyClient - counterpartyClient = suite.chainA.GetClientState(clientA) - - // Set an invalid client of chainA on chainB - tmClient, ok := counterpartyClient.(*ibctmtypes.ClientState) - suite.Require().True(ok) - tmClient.ChainId = "wrongchainid" - - suite.chainA.App.IBCKeeper.ClientKeeper.SetClientState(suite.chainA.GetContext(), clientA, tmClient) - }, false}, - {"consensus height >= latest height", func() { - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - _, _, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB) - suite.Require().NoError(err) - - // retrieve client state of chainA to pass as counterpartyClient - counterpartyClient = suite.chainA.GetClientState(clientA) - - consensusHeight = clienttypes.GetSelfHeight(suite.chainB.GetContext()) - }, false}, - {"self consensus state not found", func() { - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - _, _, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB) - suite.Require().NoError(err) - - // retrieve client state of chainA to pass as counterpartyClient - counterpartyClient = suite.chainA.GetClientState(clientA) - - consensusHeight = clienttypes.NewHeight(0, 1) - }, false}, - {"counterparty versions is empty", func() { - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - _, _, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB) - suite.Require().NoError(err) - - // retrieve client state of chainA to pass as counterpartyClient - counterpartyClient = suite.chainA.GetClientState(clientA) - - versions = nil - }, false}, - {"counterparty versions don't have a match", func() { - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - _, _, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB) - suite.Require().NoError(err) - - // retrieve client state of chainA to pass as counterpartyClient - counterpartyClient = suite.chainA.GetClientState(clientA) - - version := types.NewVersion("0.0", nil) - versions = []exported.Version{version} - }, false}, - {"connection state verification failed", func() { - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - // chainA connection not created - - // retrieve client state of chainA to pass as counterpartyClient - counterpartyClient = suite.chainA.GetClientState(clientA) - }, false}, - {"client state verification failed", func() { - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - _, _, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB) - suite.Require().NoError(err) - - // retrieve client state of chainA to pass as counterpartyClient - counterpartyClient = suite.chainA.GetClientState(clientA) - - // modify counterparty client without setting in store so it still passes validate but fails proof verification - tmClient, ok := counterpartyClient.(*ibctmtypes.ClientState) - suite.Require().True(ok) - tmClient.LatestHeight = tmClient.LatestHeight.Increment().(clienttypes.Height) - }, false}, - {"consensus state verification failed", func() { - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - - // retrieve client state of chainA to pass as counterpartyClient - counterpartyClient = suite.chainA.GetClientState(clientA) - - // give chainA wrong consensus state for chainB - consState, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetLatestClientConsensusState(suite.chainA.GetContext(), clientA) - suite.Require().True(found) - - tmConsState, ok := consState.(*ibctmtypes.ConsensusState) - suite.Require().True(ok) - - tmConsState.Timestamp = time.Now() - suite.chainA.App.IBCKeeper.ClientKeeper.SetClientConsensusState(suite.chainA.GetContext(), clientA, counterpartyClient.GetLatestHeight(), tmConsState) - - _, _, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB) - suite.Require().NoError(err) - }, false}, - {"invalid previous connection is in TRYOPEN", func() { - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - - // open init chainA - connA, connB, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB) - suite.Require().NoError(err) - - // open try chainB - err = suite.coordinator.ConnOpenTry(suite.chainB, suite.chainA, connB, connA) - suite.Require().NoError(err) - - err = suite.coordinator.UpdateClient(suite.chainB, suite.chainA, clientB, exported.Tendermint) - suite.Require().NoError(err) - - // retrieve client state of chainA to pass as counterpartyClient - counterpartyClient = suite.chainA.GetClientState(clientA) - - previousConnectionID = connB.ID - }, false}, - {"invalid previous connection has invalid versions", func() { - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - - // open init chainA - connA, connB, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB) - suite.Require().NoError(err) - - // open try chainB - err = suite.coordinator.ConnOpenTry(suite.chainB, suite.chainA, connB, connA) - suite.Require().NoError(err) - - // modify connB to be in INIT with incorrect versions - connection, found := suite.chainB.App.IBCKeeper.ConnectionKeeper.GetConnection(suite.chainB.GetContext(), connB.ID) - suite.Require().True(found) - - connection.State = types.INIT - connection.Versions = []*types.Version{{}} - - suite.chainB.App.IBCKeeper.ConnectionKeeper.SetConnection(suite.chainB.GetContext(), connB.ID, connection) - - err = suite.coordinator.UpdateClient(suite.chainB, suite.chainA, clientB, exported.Tendermint) - suite.Require().NoError(err) - - // retrieve client state of chainA to pass as counterpartyClient - counterpartyClient = suite.chainA.GetClientState(clientA) - - previousConnectionID = connB.ID - }, false}, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.msg, func() { - suite.SetupTest() // reset - consensusHeight = clienttypes.ZeroHeight() // must be explicitly changed in malleate - versions = types.GetCompatibleVersions() // must be explicitly changed in malleate - previousConnectionID = "" - - tc.malleate() - - connA := suite.chainA.GetFirstTestConnection(clientA, clientB) - counterparty := types.NewCounterparty(clientA, connA.ID, suite.chainA.GetPrefix()) - - connectionKey := host.ConnectionKey(connA.ID) - proofInit, proofHeight := suite.chainA.QueryProof(connectionKey) - - if consensusHeight.IsZero() { - // retrieve consensus state height to provide proof for - consensusHeight = counterpartyClient.GetLatestHeight() - } - consensusKey := host.FullConsensusStateKey(clientA, consensusHeight) - proofConsensus, _ := suite.chainA.QueryProof(consensusKey) - - // retrieve proof of counterparty clientstate on chainA - clientKey := host.FullClientStateKey(clientA) - proofClient, _ := suite.chainA.QueryProof(clientKey) - - connectionID, err := suite.chainB.App.IBCKeeper.ConnectionKeeper.ConnOpenTry( - suite.chainB.GetContext(), previousConnectionID, counterparty, delayPeriod, clientB, counterpartyClient, - versions, proofInit, proofClient, proofConsensus, - proofHeight, consensusHeight, - ) - - if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(types.FormatConnectionIdentifier(0), connectionID) - } else { - suite.Require().Error(err) - suite.Require().Equal("", connectionID) - } - }) - } -} - -// TestConnOpenAck - Chain A (ID #1) calls TestConnOpenAck to acknowledge (ACK state) -// the initialization (TRYINIT) of the connection on Chain B (ID #2). -func (suite *KeeperTestSuite) TestConnOpenAck() { - var ( - clientA string - clientB string - consensusHeight exported.Height - version *types.Version - counterpartyClient exported.ClientState - ) - - testCases := []struct { - msg string - malleate func() - expPass bool - }{ - {"success", func() { - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - connA, connB, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB) - suite.Require().NoError(err) - - err = suite.coordinator.ConnOpenTry(suite.chainB, suite.chainA, connB, connA) - suite.Require().NoError(err) - - // retrieve client state of chainB to pass as counterpartyClient - counterpartyClient = suite.chainB.GetClientState(clientB) - }, true}, - {"success from tryopen", func() { - // chainA is in TRYOPEN, chainB is in TRYOPEN - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - connB, connA, err := suite.coordinator.ConnOpenInit(suite.chainB, suite.chainA, clientB, clientA) - suite.Require().NoError(err) - - err = suite.coordinator.ConnOpenTry(suite.chainA, suite.chainB, connA, connB) - suite.Require().NoError(err) - - // set chainB to TRYOPEN - connection := suite.chainB.GetConnection(connB) - connection.State = types.TRYOPEN - connection.Counterparty.ConnectionId = connA.ID - suite.chainB.App.IBCKeeper.ConnectionKeeper.SetConnection(suite.chainB.GetContext(), connB.ID, connection) - // update clientB so state change is committed - suite.coordinator.UpdateClient(suite.chainB, suite.chainA, clientB, exported.Tendermint) - - suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - - // retrieve client state of chainB to pass as counterpartyClient - counterpartyClient = suite.chainB.GetClientState(clientB) - }, true}, - {"invalid counterparty client", func() { - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - connA, connB, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB) - suite.Require().NoError(err) - - // retrieve client state of chainB to pass as counterpartyClient - counterpartyClient = suite.chainB.GetClientState(clientB) - - // Set an invalid client of chainA on chainB - tmClient, ok := counterpartyClient.(*ibctmtypes.ClientState) - suite.Require().True(ok) - tmClient.ChainId = "wrongchainid" - - suite.chainB.App.IBCKeeper.ClientKeeper.SetClientState(suite.chainB.GetContext(), clientB, tmClient) - - err = suite.coordinator.ConnOpenTry(suite.chainB, suite.chainA, connB, connA) - suite.Require().NoError(err) - }, false}, - {"consensus height >= latest height", func() { - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - connA, connB, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB) - suite.Require().NoError(err) - - // retrieve client state of chainB to pass as counterpartyClient - counterpartyClient = suite.chainB.GetClientState(clientB) - - err = suite.coordinator.ConnOpenTry(suite.chainB, suite.chainA, connB, connA) - suite.Require().NoError(err) - - consensusHeight = clienttypes.GetSelfHeight(suite.chainA.GetContext()) - }, false}, - {"connection not found", func() { - // connections are never created - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - - // retrieve client state of chainB to pass as counterpartyClient - counterpartyClient = suite.chainB.GetClientState(clientB) - }, false}, - {"invalid counterparty connection ID", func() { - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - connA, connB, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB) - suite.Require().NoError(err) - - // retrieve client state of chainB to pass as counterpartyClient - counterpartyClient = suite.chainB.GetClientState(clientB) - - err = suite.coordinator.ConnOpenTry(suite.chainB, suite.chainA, connB, connA) - suite.Require().NoError(err) - - // modify connB to set counterparty connection identifier to wrong identifier - connection, found := suite.chainA.App.IBCKeeper.ConnectionKeeper.GetConnection(suite.chainA.GetContext(), connA.ID) - suite.Require().True(found) - - connection.Counterparty.ConnectionId = "badconnectionid" - - suite.chainA.App.IBCKeeper.ConnectionKeeper.SetConnection(suite.chainA.GetContext(), connA.ID, connection) - - err = suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - suite.Require().NoError(err) - - err = suite.coordinator.UpdateClient(suite.chainB, suite.chainA, clientB, exported.Tendermint) - suite.Require().NoError(err) - }, false}, - {"connection state is not INIT", func() { - // connection state is already OPEN on chainA - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - connA, connB, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB) - suite.Require().NoError(err) - - // retrieve client state of chainB to pass as counterpartyClient - counterpartyClient = suite.chainB.GetClientState(clientB) - - err = suite.coordinator.ConnOpenTry(suite.chainB, suite.chainA, connB, connA) - suite.Require().NoError(err) - - err = suite.coordinator.ConnOpenAck(suite.chainA, suite.chainB, connA, connB) - suite.Require().NoError(err) - }, false}, - {"connection is in INIT but the proposed version is invalid", func() { - // chainA is in INIT, chainB is in TRYOPEN - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - connA, connB, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB) - suite.Require().NoError(err) - - // retrieve client state of chainB to pass as counterpartyClient - counterpartyClient = suite.chainB.GetClientState(clientB) - - err = suite.coordinator.ConnOpenTry(suite.chainB, suite.chainA, connB, connA) - suite.Require().NoError(err) - - version = types.NewVersion("2.0", nil) - }, false}, - {"connection is in TRYOPEN but the set version in the connection is invalid", func() { - // chainA is in TRYOPEN, chainB is in TRYOPEN - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - connB, connA, err := suite.coordinator.ConnOpenInit(suite.chainB, suite.chainA, clientB, clientA) - suite.Require().NoError(err) - - err = suite.coordinator.ConnOpenTry(suite.chainA, suite.chainB, connA, connB) - suite.Require().NoError(err) - - // set chainB to TRYOPEN - connection := suite.chainB.GetConnection(connB) - connection.State = types.TRYOPEN - suite.chainB.App.IBCKeeper.ConnectionKeeper.SetConnection(suite.chainB.GetContext(), connB.ID, connection) - - // update clientB so state change is committed - suite.coordinator.UpdateClient(suite.chainB, suite.chainA, clientB, exported.Tendermint) - suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - - // retrieve client state of chainB to pass as counterpartyClient - counterpartyClient = suite.chainB.GetClientState(clientB) - - version = types.NewVersion("2.0", nil) - }, false}, - {"incompatible IBC versions", func() { - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - connA, connB, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB) - suite.Require().NoError(err) - - // retrieve client state of chainB to pass as counterpartyClient - counterpartyClient = suite.chainB.GetClientState(clientB) - - err = suite.coordinator.ConnOpenTry(suite.chainB, suite.chainA, connB, connA) - suite.Require().NoError(err) - - // set version to a non-compatible version - version = types.NewVersion("2.0", nil) - }, false}, - {"empty version", func() { - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - connA, connB, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB) - suite.Require().NoError(err) - - // retrieve client state of chainB to pass as counterpartyClient - counterpartyClient = suite.chainB.GetClientState(clientB) - - err = suite.coordinator.ConnOpenTry(suite.chainB, suite.chainA, connB, connA) - suite.Require().NoError(err) - - version = &types.Version{} - }, false}, - {"feature set verification failed - unsupported feature", func() { - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - connA, connB, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB) - suite.Require().NoError(err) - - // retrieve client state of chainB to pass as counterpartyClient - counterpartyClient = suite.chainB.GetClientState(clientB) - - err = suite.coordinator.ConnOpenTry(suite.chainB, suite.chainA, connB, connA) - suite.Require().NoError(err) - - version = types.NewVersion(types.DefaultIBCVersionIdentifier, []string{"ORDER_ORDERED", "ORDER_UNORDERED", "ORDER_DAG"}) - }, false}, - {"self consensus state not found", func() { - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - connA, connB, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB) - suite.Require().NoError(err) - - // retrieve client state of chainB to pass as counterpartyClient - counterpartyClient = suite.chainB.GetClientState(clientB) - - err = suite.coordinator.ConnOpenTry(suite.chainB, suite.chainA, connB, connA) - suite.Require().NoError(err) - - consensusHeight = clienttypes.NewHeight(0, 1) - }, false}, - {"connection state verification failed", func() { - // chainB connection is not in INIT - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - _, _, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB) - suite.Require().NoError(err) - - // retrieve client state of chainB to pass as counterpartyClient - counterpartyClient = suite.chainB.GetClientState(clientB) - }, false}, - {"client state verification failed", func() { - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - connA, connB, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB) - suite.Require().NoError(err) - - // retrieve client state of chainB to pass as counterpartyClient - counterpartyClient = suite.chainB.GetClientState(clientB) - - // modify counterparty client without setting in store so it still passes validate but fails proof verification - tmClient, ok := counterpartyClient.(*ibctmtypes.ClientState) - suite.Require().True(ok) - tmClient.LatestHeight = tmClient.LatestHeight.Increment().(clienttypes.Height) - - err = suite.coordinator.ConnOpenTry(suite.chainB, suite.chainA, connB, connA) - suite.Require().NoError(err) - }, false}, - {"consensus state verification failed", func() { - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - connA, connB, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB) - suite.Require().NoError(err) - - // retrieve client state of chainB to pass as counterpartyClient - counterpartyClient = suite.chainB.GetClientState(clientB) - - // give chainB wrong consensus state for chainA - consState, found := suite.chainB.App.IBCKeeper.ClientKeeper.GetLatestClientConsensusState(suite.chainB.GetContext(), clientB) - suite.Require().True(found) - - tmConsState, ok := consState.(*ibctmtypes.ConsensusState) - suite.Require().True(ok) - - tmConsState.Timestamp = time.Now() - suite.chainB.App.IBCKeeper.ClientKeeper.SetClientConsensusState(suite.chainB.GetContext(), clientB, counterpartyClient.GetLatestHeight(), tmConsState) - - err = suite.coordinator.ConnOpenTry(suite.chainB, suite.chainA, connB, connA) - suite.Require().NoError(err) - }, false}, - } - - for _, tc := range testCases { - tc := tc - suite.Run(tc.msg, func() { - suite.SetupTest() // reset - version = types.ExportedVersionsToProto(types.GetCompatibleVersions())[0] // must be explicitly changed in malleate - consensusHeight = clienttypes.ZeroHeight() // must be explicitly changed in malleate - - tc.malleate() - - connA := suite.chainA.GetFirstTestConnection(clientA, clientB) - connB := suite.chainB.GetFirstTestConnection(clientB, clientA) - - connectionKey := host.ConnectionKey(connB.ID) - proofTry, proofHeight := suite.chainB.QueryProof(connectionKey) - - if consensusHeight.IsZero() { - // retrieve consensus state height to provide proof for - clientState := suite.chainB.GetClientState(clientB) - consensusHeight = clientState.GetLatestHeight() - } - consensusKey := host.FullConsensusStateKey(clientB, consensusHeight) - proofConsensus, _ := suite.chainB.QueryProof(consensusKey) - - // retrieve proof of counterparty clientstate on chainA - clientKey := host.FullClientStateKey(clientB) - proofClient, _ := suite.chainB.QueryProof(clientKey) - - err := suite.chainA.App.IBCKeeper.ConnectionKeeper.ConnOpenAck( - suite.chainA.GetContext(), connA.ID, counterpartyClient, version, connB.ID, - proofTry, proofClient, proofConsensus, proofHeight, consensusHeight, - ) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} - -// TestConnOpenConfirm - chainB calls ConnOpenConfirm to confirm that -// chainA state is now OPEN. -func (suite *KeeperTestSuite) TestConnOpenConfirm() { - var ( - clientA string - clientB string - ) - testCases := []struct { - msg string - malleate func() - expPass bool - }{ - {"success", func() { - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - connA, connB, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB) - suite.Require().NoError(err) - - err = suite.coordinator.ConnOpenTry(suite.chainB, suite.chainA, connB, connA) - suite.Require().NoError(err) - - err = suite.coordinator.ConnOpenAck(suite.chainA, suite.chainB, connA, connB) - suite.Require().NoError(err) - }, true}, - {"connection not found", func() { - // connections are never created - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - }, false}, - {"chain B's connection state is not TRYOPEN", func() { - // connections are OPEN - clientA, clientB, _, _ = suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - }, false}, - {"connection state verification failed", func() { - // chainA is in INIT - clientA, clientB = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - connA, connB, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB) - suite.Require().NoError(err) - - err = suite.coordinator.ConnOpenTry(suite.chainB, suite.chainA, connB, connA) - suite.Require().NoError(err) - }, false}, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.msg, func() { - suite.SetupTest() // reset - - tc.malleate() - - connA := suite.chainA.GetFirstTestConnection(clientA, clientB) - connB := suite.chainB.GetFirstTestConnection(clientB, clientA) - - connectionKey := host.ConnectionKey(connA.ID) - proofAck, proofHeight := suite.chainA.QueryProof(connectionKey) - - err := suite.chainB.App.IBCKeeper.ConnectionKeeper.ConnOpenConfirm( - suite.chainB.GetContext(), connB.ID, proofAck, proofHeight, - ) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} diff --git a/x/ibc/core/03-connection/keeper/keeper.go b/x/ibc/core/03-connection/keeper/keeper.go deleted file mode 100644 index 6637268687c0..000000000000 --- a/x/ibc/core/03-connection/keeper/keeper.go +++ /dev/null @@ -1,198 +0,0 @@ -package keeper - -import ( - "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" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -// Keeper defines the IBC connection keeper -type Keeper struct { - // implements gRPC QueryServer interface - types.QueryServer - - storeKey sdk.StoreKey - cdc codec.BinaryMarshaler - clientKeeper types.ClientKeeper -} - -// NewKeeper creates a new IBC connection Keeper instance -func NewKeeper(cdc codec.BinaryMarshaler, key sdk.StoreKey, ck types.ClientKeeper) Keeper { - return Keeper{ - storeKey: key, - cdc: cdc, - clientKeeper: ck, - } -} - -// Logger returns a module-specific logger. -func (k Keeper) Logger(ctx sdk.Context) log.Logger { - return ctx.Logger().With("module", "x/"+host.ModuleName+"/"+types.SubModuleName) -} - -// GetCommitmentPrefix returns the IBC connection store prefix as a commitment -// Prefix -func (k Keeper) GetCommitmentPrefix() exported.Prefix { - return commitmenttypes.NewMerklePrefix([]byte(k.storeKey.Name())) -} - -// GenerateConnectionIdentifier returns the next connection identifier. -func (k Keeper) GenerateConnectionIdentifier(ctx sdk.Context) string { - nextConnSeq := k.GetNextConnectionSequence(ctx) - connectionID := types.FormatConnectionIdentifier(nextConnSeq) - - nextConnSeq++ - k.SetNextConnectionSequence(ctx, nextConnSeq) - return connectionID -} - -// GetConnection returns a connection with a particular identifier -func (k Keeper) GetConnection(ctx sdk.Context, connectionID string) (types.ConnectionEnd, bool) { - store := ctx.KVStore(k.storeKey) - bz := store.Get(host.ConnectionKey(connectionID)) - if bz == nil { - return types.ConnectionEnd{}, false - } - - var connection types.ConnectionEnd - k.cdc.MustUnmarshalBinaryBare(bz, &connection) - - return connection, true -} - -// SetConnection sets a connection to the store -func (k Keeper) SetConnection(ctx sdk.Context, connectionID string, connection types.ConnectionEnd) { - store := ctx.KVStore(k.storeKey) - bz := k.cdc.MustMarshalBinaryBare(&connection) - store.Set(host.ConnectionKey(connectionID), bz) -} - -// GetTimestampAtHeight returns the timestamp in nanoseconds of the consensus state at the -// given height. -func (k Keeper) GetTimestampAtHeight(ctx sdk.Context, connection types.ConnectionEnd, height exported.Height) (uint64, error) { - consensusState, found := k.clientKeeper.GetClientConsensusState( - ctx, connection.GetClientID(), height, - ) - - if !found { - return 0, sdkerrors.Wrapf( - clienttypes.ErrConsensusStateNotFound, - "clientID (%s), height (%s)", connection.GetClientID(), height, - ) - } - - return consensusState.GetTimestamp(), nil -} - -// GetClientConnectionPaths returns all the connection paths stored under a -// particular client -func (k Keeper) GetClientConnectionPaths(ctx sdk.Context, clientID string) ([]string, bool) { - store := ctx.KVStore(k.storeKey) - bz := store.Get(host.ClientConnectionsKey(clientID)) - if bz == nil { - return nil, false - } - - var clientPaths types.ClientPaths - k.cdc.MustUnmarshalBinaryBare(bz, &clientPaths) - return clientPaths.Paths, true -} - -// SetClientConnectionPaths sets the connections paths for client -func (k Keeper) SetClientConnectionPaths(ctx sdk.Context, clientID string, paths []string) { - store := ctx.KVStore(k.storeKey) - clientPaths := types.ClientPaths{Paths: paths} - bz := k.cdc.MustMarshalBinaryBare(&clientPaths) - store.Set(host.ClientConnectionsKey(clientID), bz) -} - -// GetNextConnectionSequence gets the next connection sequence from the store. -func (k Keeper) GetNextConnectionSequence(ctx sdk.Context) uint64 { - store := ctx.KVStore(k.storeKey) - bz := store.Get([]byte(types.KeyNextConnectionSequence)) - if bz == nil { - panic("next connection sequence is nil") - } - - return sdk.BigEndianToUint64(bz) -} - -// SetNextConnectionSequence sets the next connection sequence to the store. -func (k Keeper) SetNextConnectionSequence(ctx sdk.Context, sequence uint64) { - store := ctx.KVStore(k.storeKey) - bz := sdk.Uint64ToBigEndian(sequence) - store.Set([]byte(types.KeyNextConnectionSequence), bz) -} - -// GetAllClientConnectionPaths returns all stored clients connection id paths. It -// will ignore the clients that haven't initialized a connection handshake since -// no paths are stored. -func (k Keeper) GetAllClientConnectionPaths(ctx sdk.Context) []types.ConnectionPaths { - var allConnectionPaths []types.ConnectionPaths - k.clientKeeper.IterateClients(ctx, func(clientID string, cs exported.ClientState) bool { - paths, found := k.GetClientConnectionPaths(ctx, clientID) - if !found { - // continue when connection handshake is not initialized - return false - } - connPaths := types.NewConnectionPaths(clientID, paths) - allConnectionPaths = append(allConnectionPaths, connPaths) - return false - }) - - return allConnectionPaths -} - -// IterateConnections provides an iterator over all ConnectionEnd objects. -// For each ConnectionEnd, cb will be called. If the cb returns true, the -// iterator will close and stop. -func (k Keeper) IterateConnections(ctx sdk.Context, cb func(types.IdentifiedConnection) bool) { - store := ctx.KVStore(k.storeKey) - iterator := sdk.KVStorePrefixIterator(store, []byte(host.KeyConnectionPrefix)) - - defer iterator.Close() - for ; iterator.Valid(); iterator.Next() { - var connection types.ConnectionEnd - k.cdc.MustUnmarshalBinaryBare(iterator.Value(), &connection) - - connectionID := host.MustParseConnectionPath(string(iterator.Key())) - identifiedConnection := types.NewIdentifiedConnection(connectionID, connection) - if cb(identifiedConnection) { - break - } - } -} - -// GetAllConnections returns all stored ConnectionEnd objects. -func (k Keeper) GetAllConnections(ctx sdk.Context) (connections []types.IdentifiedConnection) { - k.IterateConnections(ctx, func(connection types.IdentifiedConnection) bool { - connections = append(connections, connection) - return false - }) - return connections -} - -// addConnectionToClient is used to add a connection identifier to the set of -// connections associated with a client. -func (k Keeper) addConnectionToClient(ctx sdk.Context, clientID, connectionID string) error { - _, found := k.clientKeeper.GetClientState(ctx, clientID) - if !found { - return sdkerrors.Wrap(clienttypes.ErrClientNotFound, clientID) - } - - conns, found := k.GetClientConnectionPaths(ctx, clientID) - if !found { - conns = []string{} - } - - conns = append(conns, connectionID) - k.SetClientConnectionPaths(ctx, clientID, conns) - return nil -} diff --git a/x/ibc/core/03-connection/keeper/keeper_test.go b/x/ibc/core/03-connection/keeper/keeper_test.go deleted file mode 100644 index f2a1124b551b..000000000000 --- a/x/ibc/core/03-connection/keeper/keeper_test.go +++ /dev/null @@ -1,133 +0,0 @@ -package keeper_test - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/suite" - - "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" -) - -type KeeperTestSuite struct { - suite.Suite - - coordinator *ibctesting.Coordinator - - // testing chains used for convenience and readability - chainA *ibctesting.TestChain - chainB *ibctesting.TestChain -} - -func (suite *KeeperTestSuite) SetupTest() { - suite.coordinator = ibctesting.NewCoordinator(suite.T(), 2) - suite.chainA = suite.coordinator.GetChain(ibctesting.GetChainID(0)) - suite.chainB = suite.coordinator.GetChain(ibctesting.GetChainID(1)) -} - -func TestKeeperTestSuite(t *testing.T) { - suite.Run(t, new(KeeperTestSuite)) -} - -func (suite *KeeperTestSuite) TestSetAndGetConnection() { - clientA, clientB := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - connA := suite.chainA.GetFirstTestConnection(clientA, clientB) - _, existed := suite.chainA.App.IBCKeeper.ConnectionKeeper.GetConnection(suite.chainA.GetContext(), connA.ID) - suite.Require().False(existed) - - suite.coordinator.CreateConnection(suite.chainA, suite.chainB, clientA, clientB) - _, existed = suite.chainA.App.IBCKeeper.ConnectionKeeper.GetConnection(suite.chainA.GetContext(), connA.ID) - suite.Require().True(existed) -} - -func (suite *KeeperTestSuite) TestSetAndGetClientConnectionPaths() { - clientA, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - _, existed := suite.chainA.App.IBCKeeper.ConnectionKeeper.GetClientConnectionPaths(suite.chainA.GetContext(), clientA) - suite.False(existed) - - connections := []string{"connectionA", "connectionB"} - suite.chainA.App.IBCKeeper.ConnectionKeeper.SetClientConnectionPaths(suite.chainA.GetContext(), clientA, connections) - paths, existed := suite.chainA.App.IBCKeeper.ConnectionKeeper.GetClientConnectionPaths(suite.chainA.GetContext(), clientA) - suite.True(existed) - suite.EqualValues(connections, paths) -} - -// create 2 connections: A0 - B0, A1 - B1 -func (suite KeeperTestSuite) TestGetAllConnections() { - clientA, clientB, connA0, connB0 := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - connA1, connB1 := suite.coordinator.CreateConnection(suite.chainA, suite.chainB, clientA, clientB) - - counterpartyB0 := types.NewCounterparty(clientB, connB0.ID, suite.chainB.GetPrefix()) // connection B0 - counterpartyB1 := types.NewCounterparty(clientB, connB1.ID, suite.chainB.GetPrefix()) // connection B1 - - conn1 := types.NewConnectionEnd(types.OPEN, clientA, counterpartyB0, types.ExportedVersionsToProto(types.GetCompatibleVersions()), 0) // A0 - B0 - conn2 := types.NewConnectionEnd(types.OPEN, clientA, counterpartyB1, types.ExportedVersionsToProto(types.GetCompatibleVersions()), 0) // A1 - B1 - - iconn1 := types.NewIdentifiedConnection(connA0.ID, conn1) - iconn2 := types.NewIdentifiedConnection(connA1.ID, conn2) - - expConnections := []types.IdentifiedConnection{iconn1, iconn2} - - connections := suite.chainA.App.IBCKeeper.ConnectionKeeper.GetAllConnections(suite.chainA.GetContext()) - suite.Require().Len(connections, len(expConnections)) - suite.Require().Equal(expConnections, connections) -} - -// the test creates 2 clients clientA0 and clientA1. clientA0 has a single -// connection and clientA1 has 2 connections. -func (suite KeeperTestSuite) TestGetAllClientConnectionPaths() { - clientA0, _, connA0, _ := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - clientA1, clientB1, connA1, _ := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - connA2, _ := suite.coordinator.CreateConnection(suite.chainA, suite.chainB, clientA1, clientB1) - - expPaths := []types.ConnectionPaths{ - types.NewConnectionPaths(clientA0, []string{connA0.ID}), - types.NewConnectionPaths(clientA1, []string{connA1.ID, connA2.ID}), - } - - connPaths := suite.chainA.App.IBCKeeper.ConnectionKeeper.GetAllClientConnectionPaths(suite.chainA.GetContext()) - suite.Require().Len(connPaths, 2) - suite.Require().Equal(expPaths, connPaths) -} - -// TestGetTimestampAtHeight verifies if the clients on each chain return the -// correct timestamp for the other chain. -func (suite *KeeperTestSuite) TestGetTimestampAtHeight() { - var connection types.ConnectionEnd - - cases := []struct { - msg string - malleate func() - expPass bool - }{ - {"verification success", func() { - _, _, connA, _ := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - connection = suite.chainA.GetConnection(connA) - }, true}, - {"consensus state not found", func() { - // any non-nil value of connection is valid - suite.Require().NotNil(connection) - }, false}, - } - - for _, tc := range cases { - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { - suite.SetupTest() // reset - - tc.malleate() - - actualTimestamp, err := suite.chainA.App.IBCKeeper.ConnectionKeeper.GetTimestampAtHeight( - suite.chainA.GetContext(), connection, suite.chainB.LastHeader.GetHeight(), - ) - - if tc.expPass { - suite.Require().NoError(err) - suite.Require().EqualValues(uint64(suite.chainB.LastHeader.GetTime().UnixNano()), actualTimestamp) - } else { - suite.Require().Error(err) - } - }) - } -} diff --git a/x/ibc/core/03-connection/keeper/verify.go b/x/ibc/core/03-connection/keeper/verify.go deleted file mode 100644 index ddb1ea6b9612..000000000000 --- a/x/ibc/core/03-connection/keeper/verify.go +++ /dev/null @@ -1,225 +0,0 @@ -package keeper - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -// VerifyClientState verifies a proof of a client state of the running machine -// stored on the target machine -func (k Keeper) VerifyClientState( - ctx sdk.Context, - connection exported.ConnectionI, - height exported.Height, - proof []byte, - clientState exported.ClientState, -) error { - clientID := connection.GetClientID() - targetClient, found := k.clientKeeper.GetClientState(ctx, clientID) - if !found { - return sdkerrors.Wrap(clienttypes.ErrClientNotFound, clientID) - } - - if err := targetClient.VerifyClientState( - k.clientKeeper.ClientStore(ctx, clientID), k.cdc, height, - connection.GetCounterparty().GetPrefix(), connection.GetCounterparty().GetClientID(), proof, clientState); err != nil { - return sdkerrors.Wrapf(err, "failed client state verification for target client: %s", connection.GetClientID()) - } - - return nil -} - -// VerifyClientConsensusState verifies a proof of the consensus state of the -// specified client stored on the target machine. -func (k Keeper) VerifyClientConsensusState( - ctx sdk.Context, - connection exported.ConnectionI, - height exported.Height, - consensusHeight exported.Height, - proof []byte, - consensusState exported.ConsensusState, -) error { - clientID := connection.GetClientID() - clientState, found := k.clientKeeper.GetClientState(ctx, clientID) - if !found { - return sdkerrors.Wrap(clienttypes.ErrClientNotFound, clientID) - } - - if err := clientState.VerifyClientConsensusState( - k.clientKeeper.ClientStore(ctx, clientID), k.cdc, height, - connection.GetCounterparty().GetClientID(), consensusHeight, connection.GetCounterparty().GetPrefix(), proof, consensusState, - ); err != nil { - return sdkerrors.Wrapf(err, "failed consensus state verification for client (%s)", connection.GetClientID()) - } - - return nil -} - -// VerifyConnectionState verifies a proof of the connection state of the -// specified connection end stored on the target machine. -func (k Keeper) VerifyConnectionState( - ctx sdk.Context, - connection exported.ConnectionI, - height exported.Height, - proof []byte, - connectionID string, - connectionEnd exported.ConnectionI, // opposite connection -) error { - clientState, found := k.clientKeeper.GetClientState(ctx, connection.GetClientID()) - if !found { - return sdkerrors.Wrap(clienttypes.ErrClientNotFound, connection.GetClientID()) - } - - if err := clientState.VerifyConnectionState( - k.clientKeeper.ClientStore(ctx, connection.GetClientID()), k.cdc, height, - connection.GetCounterparty().GetPrefix(), proof, connectionID, connectionEnd, - ); err != nil { - return sdkerrors.Wrapf(err, "failed connection state verification for client (%s)", connection.GetClientID()) - } - - return nil -} - -// VerifyChannelState verifies a proof of the channel state of the specified -// channel end, under the specified port, stored on the target machine. -func (k Keeper) VerifyChannelState( - ctx sdk.Context, - connection exported.ConnectionI, - height exported.Height, - proof []byte, - portID, - channelID string, - channel exported.ChannelI, -) error { - clientState, found := k.clientKeeper.GetClientState(ctx, connection.GetClientID()) - if !found { - return sdkerrors.Wrap(clienttypes.ErrClientNotFound, connection.GetClientID()) - } - - if err := clientState.VerifyChannelState( - k.clientKeeper.ClientStore(ctx, connection.GetClientID()), k.cdc, height, - connection.GetCounterparty().GetPrefix(), proof, - portID, channelID, channel, - ); err != nil { - return sdkerrors.Wrapf(err, "failed channel state verification for client (%s)", connection.GetClientID()) - } - - return nil -} - -// VerifyPacketCommitment verifies a proof of an outgoing packet commitment at -// the specified port, specified channel, and specified sequence. -func (k Keeper) VerifyPacketCommitment( - ctx sdk.Context, - connection exported.ConnectionI, - height exported.Height, - proof []byte, - portID, - channelID string, - sequence uint64, - commitmentBytes []byte, -) error { - clientState, found := k.clientKeeper.GetClientState(ctx, connection.GetClientID()) - if !found { - return sdkerrors.Wrap(clienttypes.ErrClientNotFound, connection.GetClientID()) - } - - if err := clientState.VerifyPacketCommitment( - k.clientKeeper.ClientStore(ctx, connection.GetClientID()), k.cdc, height, - uint64(ctx.BlockTime().UnixNano()), connection.GetDelayPeriod(), - connection.GetCounterparty().GetPrefix(), proof, portID, channelID, - sequence, commitmentBytes, - ); err != nil { - return sdkerrors.Wrapf(err, "failed packet commitment verification for client (%s)", connection.GetClientID()) - } - - return nil -} - -// VerifyPacketAcknowledgement verifies a proof of an incoming packet -// acknowledgement at the specified port, specified channel, and specified sequence. -func (k Keeper) VerifyPacketAcknowledgement( - ctx sdk.Context, - connection exported.ConnectionI, - height exported.Height, - proof []byte, - portID, - channelID string, - sequence uint64, - acknowledgement []byte, -) error { - clientState, found := k.clientKeeper.GetClientState(ctx, connection.GetClientID()) - if !found { - return sdkerrors.Wrap(clienttypes.ErrClientNotFound, connection.GetClientID()) - } - - if err := clientState.VerifyPacketAcknowledgement( - k.clientKeeper.ClientStore(ctx, connection.GetClientID()), k.cdc, height, - uint64(ctx.BlockTime().UnixNano()), connection.GetDelayPeriod(), - connection.GetCounterparty().GetPrefix(), proof, portID, channelID, - sequence, acknowledgement, - ); err != nil { - return sdkerrors.Wrapf(err, "failed packet acknowledgement verification for client (%s)", connection.GetClientID()) - } - - return nil -} - -// VerifyPacketReceiptAbsence verifies a proof of the absence of an -// incoming packet receipt at the specified port, specified channel, and -// specified sequence. -func (k Keeper) VerifyPacketReceiptAbsence( - ctx sdk.Context, - connection exported.ConnectionI, - height exported.Height, - proof []byte, - portID, - channelID string, - sequence uint64, -) error { - clientState, found := k.clientKeeper.GetClientState(ctx, connection.GetClientID()) - if !found { - return sdkerrors.Wrap(clienttypes.ErrClientNotFound, connection.GetClientID()) - } - - if err := clientState.VerifyPacketReceiptAbsence( - k.clientKeeper.ClientStore(ctx, connection.GetClientID()), k.cdc, height, - uint64(ctx.BlockTime().UnixNano()), connection.GetDelayPeriod(), - connection.GetCounterparty().GetPrefix(), proof, portID, channelID, - sequence, - ); err != nil { - return sdkerrors.Wrapf(err, "failed packet receipt absence verification for client (%s)", connection.GetClientID()) - } - - return nil -} - -// VerifyNextSequenceRecv verifies a proof of the next sequence number to be -// received of the specified channel at the specified port. -func (k Keeper) VerifyNextSequenceRecv( - ctx sdk.Context, - connection exported.ConnectionI, - height exported.Height, - proof []byte, - portID, - channelID string, - nextSequenceRecv uint64, -) error { - clientState, found := k.clientKeeper.GetClientState(ctx, connection.GetClientID()) - if !found { - return sdkerrors.Wrap(clienttypes.ErrClientNotFound, connection.GetClientID()) - } - - if err := clientState.VerifyNextSequenceRecv( - k.clientKeeper.ClientStore(ctx, connection.GetClientID()), k.cdc, height, - uint64(ctx.BlockTime().UnixNano()), connection.GetDelayPeriod(), - connection.GetCounterparty().GetPrefix(), proof, portID, channelID, - nextSequenceRecv, - ); err != nil { - return sdkerrors.Wrapf(err, "failed next sequence receive verification for client (%s)", connection.GetClientID()) - } - - return nil -} diff --git a/x/ibc/core/03-connection/keeper/verify_test.go b/x/ibc/core/03-connection/keeper/verify_test.go deleted file mode 100644 index 2d94955d8ef4..000000000000 --- a/x/ibc/core/03-connection/keeper/verify_test.go +++ /dev/null @@ -1,514 +0,0 @@ -package keeper_test - -import ( - "fmt" - "time" - - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" - ibcmock "github.com/cosmos/cosmos-sdk/x/ibc/testing/mock" -) - -var defaultTimeoutHeight = clienttypes.NewHeight(0, 100000) - -// TestVerifyClientState verifies a client state of chainA -// stored on clientB (which is on chainB) -func (suite *KeeperTestSuite) TestVerifyClientState() { - cases := []struct { - msg string - changeClientID bool - heightDiff uint64 - malleateCounterparty bool - expPass bool - }{ - {"verification success", false, 0, false, true}, - {"client state not found", true, 0, false, false}, - {"consensus state for proof height not found", false, 5, false, false}, - {"verification failed", false, 0, true, false}, - } - - for _, tc := range cases { - tc := tc - - suite.Run(tc.msg, func() { - suite.SetupTest() // reset - - _, clientB, connA, _ := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - - counterpartyClient, clientProof := suite.chainB.QueryClientStateProof(clientB) - proofHeight := clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()-1)) - - if tc.malleateCounterparty { - tmClient, _ := counterpartyClient.(*ibctmtypes.ClientState) - tmClient.ChainId = "wrongChainID" - } - - connection := suite.chainA.GetConnection(connA) - if tc.changeClientID { - connection.ClientId = ibctesting.InvalidID - } - - err := suite.chainA.App.IBCKeeper.ConnectionKeeper.VerifyClientState( - suite.chainA.GetContext(), connection, - malleateHeight(proofHeight, tc.heightDiff), clientProof, counterpartyClient, - ) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} - -// TestVerifyClientConsensusState verifies that the consensus state of -// chainA stored on clientB (which is on chainB) matches the consensus -// state for chainA at that height. -func (suite *KeeperTestSuite) TestVerifyClientConsensusState() { - var ( - connA *ibctesting.TestConnection - connB *ibctesting.TestConnection - changeClientID bool - heightDiff uint64 - ) - cases := []struct { - msg string - malleate func() - expPass bool - }{ - {"verification success", func() { - _, _, connA, connB = suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - }, true}, - {"client state not found", func() { - _, _, connA, connB = suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - - changeClientID = true - }, false}, - {"consensus state not found", func() { - _, _, connA, connB = suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - - heightDiff = 5 - }, false}, - {"verification failed", func() { - _, _, connA, connB = suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - clientB := connB.ClientID - clientState := suite.chainB.GetClientState(clientB) - - // give chainB wrong consensus state for chainA - consState, found := suite.chainB.App.IBCKeeper.ClientKeeper.GetLatestClientConsensusState(suite.chainB.GetContext(), clientB) - suite.Require().True(found) - - tmConsState, ok := consState.(*ibctmtypes.ConsensusState) - suite.Require().True(ok) - - tmConsState.Timestamp = time.Now() - suite.chainB.App.IBCKeeper.ClientKeeper.SetClientConsensusState(suite.chainB.GetContext(), clientB, clientState.GetLatestHeight(), tmConsState) - - suite.coordinator.CommitBlock(suite.chainB) - }, false}, - } - - for _, tc := range cases { - tc := tc - - suite.Run(tc.msg, func() { - suite.SetupTest() // reset - heightDiff = 0 // must be explicitly changed in malleate - changeClientID = false // must be explicitly changed in malleate - - tc.malleate() - - connection := suite.chainA.GetConnection(connA) - if changeClientID { - connection.ClientId = ibctesting.InvalidID - } - - proof, consensusHeight := suite.chainB.QueryConsensusStateProof(connB.ClientID) - proofHeight := clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()-1)) - consensusState, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetSelfConsensusState(suite.chainA.GetContext(), consensusHeight) - suite.Require().True(found) - - err := suite.chainA.App.IBCKeeper.ConnectionKeeper.VerifyClientConsensusState( - suite.chainA.GetContext(), connection, - malleateHeight(proofHeight, heightDiff), consensusHeight, proof, consensusState, - ) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} - -// TestVerifyConnectionState verifies the connection state of the connection -// on chainB. The connections on chainA and chainB are fully opened. -func (suite *KeeperTestSuite) TestVerifyConnectionState() { - cases := []struct { - msg string - changeClientID bool - changeConnectionState bool - heightDiff uint64 - expPass bool - }{ - {"verification success", false, false, 0, true}, - {"client state not found - changed client ID", true, false, 0, false}, - {"consensus state not found - increased proof height", false, false, 5, false}, - {"verification failed - connection state is different than proof", false, true, 0, false}, - } - - for _, tc := range cases { - tc := tc - - suite.Run(tc.msg, func() { - suite.SetupTest() // reset - - _, _, connA, connB := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - - connection := suite.chainA.GetConnection(connA) - if tc.changeClientID { - connection.ClientId = ibctesting.InvalidID - } - expectedConnection := suite.chainB.GetConnection(connB) - - connectionKey := host.ConnectionKey(connB.ID) - proof, proofHeight := suite.chainB.QueryProof(connectionKey) - - if tc.changeConnectionState { - expectedConnection.State = types.TRYOPEN - } - - err := suite.chainA.App.IBCKeeper.ConnectionKeeper.VerifyConnectionState( - suite.chainA.GetContext(), connection, - malleateHeight(proofHeight, tc.heightDiff), proof, connB.ID, expectedConnection, - ) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} - -// TestVerifyChannelState verifies the channel state of the channel on -// chainB. The channels on chainA and chainB are fully opened. -func (suite *KeeperTestSuite) TestVerifyChannelState() { - cases := []struct { - msg string - changeClientID bool - changeChannelState bool - heightDiff uint64 - expPass bool - }{ - {"verification success", false, false, 0, true}, - {"client state not found- changed client ID", true, false, 0, false}, - {"consensus state not found - increased proof height", false, false, 5, false}, - {"verification failed - changed channel state", false, true, 0, false}, - } - - for _, tc := range cases { - tc := tc - - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { - suite.SetupTest() // reset - - _, _, connA, _, _, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.UNORDERED) - connection := suite.chainA.GetConnection(connA) - if tc.changeClientID { - connection.ClientId = ibctesting.InvalidID - } - - channelKey := host.ChannelKey(channelB.PortID, channelB.ID) - proof, proofHeight := suite.chainB.QueryProof(channelKey) - - channel := suite.chainB.GetChannel(channelB) - if tc.changeChannelState { - channel.State = channeltypes.TRYOPEN - } - - err := suite.chainA.App.IBCKeeper.ConnectionKeeper.VerifyChannelState( - suite.chainA.GetContext(), connection, malleateHeight(proofHeight, tc.heightDiff), proof, - channelB.PortID, channelB.ID, channel, - ) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} - -// TestVerifyPacketCommitmentState has chainB verify the packet commitment -// on channelA. The channels on chainA and chainB are fully opened and a -// packet is sent from chainA to chainB, but has not been received. -func (suite *KeeperTestSuite) TestVerifyPacketCommitment() { - cases := []struct { - msg string - changeClientID bool - changePacketCommitmentState bool - heightDiff uint64 - delayPeriod uint64 - expPass bool - }{ - {"verification success", false, false, 0, 0, true}, - {"verification success: delay period passed", false, false, 0, uint64(1 * time.Second.Nanoseconds()), true}, - {"delay period has not passed", false, false, 0, uint64(1 * time.Hour.Nanoseconds()), false}, - {"client state not found- changed client ID", true, false, 0, 0, false}, - {"consensus state not found - increased proof height", false, false, 5, 0, false}, - {"verification failed - changed packet commitment state", false, true, 0, 0, false}, - } - - for _, tc := range cases { - tc := tc - - suite.Run(tc.msg, func() { - suite.SetupTest() // reset - - _, clientB, _, connB, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.UNORDERED) - - connection := suite.chainB.GetConnection(connB) - connection.DelayPeriod = tc.delayPeriod - if tc.changeClientID { - connection.ClientId = ibctesting.InvalidID - } - - packet := channeltypes.NewPacket(ibctesting.TestHash, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, defaultTimeoutHeight, 0) - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - - commitmentKey := host.PacketCommitmentKey(packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) - proof, proofHeight := suite.chainA.QueryProof(commitmentKey) - - if tc.changePacketCommitmentState { - packet.Data = []byte(ibctesting.InvalidID) - } - - commitment := channeltypes.CommitPacket(suite.chainB.App.IBCKeeper.Codec(), packet) - err = suite.chainB.App.IBCKeeper.ConnectionKeeper.VerifyPacketCommitment( - suite.chainB.GetContext(), connection, malleateHeight(proofHeight, tc.heightDiff), proof, - packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence(), commitment, - ) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} - -// TestVerifyPacketAcknowledgement has chainA verify the acknowledgement on -// channelB. The channels on chainA and chainB are fully opened and a packet -// is sent from chainA to chainB and received. -func (suite *KeeperTestSuite) TestVerifyPacketAcknowledgement() { - cases := []struct { - msg string - changeClientID bool - changeAcknowledgement bool - heightDiff uint64 - delayPeriod uint64 - expPass bool - }{ - {"verification success", false, false, 0, 0, true}, - {"verification success: delay period passed", false, false, 0, uint64(1 * time.Second.Nanoseconds()), true}, - {"delay period has not passed", false, false, 0, uint64(1 * time.Hour.Nanoseconds()), false}, - {"client state not found- changed client ID", true, false, 0, 0, false}, - {"consensus state not found - increased proof height", false, false, 5, 0, false}, - {"verification failed - changed acknowledgement", false, true, 0, 0, false}, - } - - for _, tc := range cases { - tc := tc - - suite.Run(tc.msg, func() { - suite.SetupTest() // reset - - clientA, clientB, connA, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.UNORDERED) - - connection := suite.chainA.GetConnection(connA) - connection.DelayPeriod = tc.delayPeriod - if tc.changeClientID { - connection.ClientId = ibctesting.InvalidID - } - - // send and receive packet - packet := channeltypes.NewPacket(ibctesting.TestHash, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, defaultTimeoutHeight, 0) - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - - // increment receiving chain's (chainB) time by 2 hour to always pass receive - suite.coordinator.IncrementTimeBy(time.Hour * 2) - suite.coordinator.CommitBlock(suite.chainB) - - err = suite.coordinator.RecvPacket(suite.chainA, suite.chainB, clientA, packet) - suite.Require().NoError(err) - - packetAckKey := host.PacketAcknowledgementKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - proof, proofHeight := suite.chainB.QueryProof(packetAckKey) - - ack := ibcmock.MockAcknowledgement - if tc.changeAcknowledgement { - ack = []byte(ibctesting.InvalidID) - } - - err = suite.chainA.App.IBCKeeper.ConnectionKeeper.VerifyPacketAcknowledgement( - suite.chainA.GetContext(), connection, malleateHeight(proofHeight, tc.heightDiff), proof, - packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence(), ack, - ) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} - -// TestVerifyPacketReceiptAbsence has chainA verify the receipt -// absence on channelB. The channels on chainA and chainB are fully opened and -// a packet is sent from chainA to chainB and not received. -func (suite *KeeperTestSuite) TestVerifyPacketReceiptAbsence() { - cases := []struct { - msg string - changeClientID bool - recvAck bool - heightDiff uint64 - delayPeriod uint64 - expPass bool - }{ - {"verification success", false, false, 0, 0, true}, - {"verification success: delay period passed", false, false, 0, uint64(1 * time.Second.Nanoseconds()), true}, - {"delay period has not passed", false, false, 0, uint64(1 * time.Hour.Nanoseconds()), false}, - {"client state not found - changed client ID", true, false, 0, 0, false}, - {"consensus state not found - increased proof height", false, false, 5, 0, false}, - {"verification failed - acknowledgement was received", false, true, 0, 0, false}, - } - - for _, tc := range cases { - tc := tc - - suite.Run(tc.msg, func() { - suite.SetupTest() // reset - - clientA, clientB, connA, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.UNORDERED) - - connection := suite.chainA.GetConnection(connA) - connection.DelayPeriod = tc.delayPeriod - if tc.changeClientID { - connection.ClientId = ibctesting.InvalidID - } - - // send, only receive if specified - packet := channeltypes.NewPacket(ibctesting.TestHash, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, defaultTimeoutHeight, 0) - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - - if tc.recvAck { - // increment receiving chain's (chainB) time by 2 hour to always pass receive - suite.coordinator.IncrementTimeBy(time.Hour * 2) - suite.coordinator.CommitBlock(suite.chainB) - - err = suite.coordinator.RecvPacket(suite.chainA, suite.chainB, clientA, packet) - suite.Require().NoError(err) - } else { - // need to update height to prove absence - suite.coordinator.CommitBlock(suite.chainA, suite.chainB) - suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - } - - packetReceiptKey := host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - proof, proofHeight := suite.chainB.QueryProof(packetReceiptKey) - - err = suite.chainA.App.IBCKeeper.ConnectionKeeper.VerifyPacketReceiptAbsence( - suite.chainA.GetContext(), connection, malleateHeight(proofHeight, tc.heightDiff), proof, - packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence(), - ) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} - -// TestVerifyNextSequenceRecv has chainA verify the next sequence receive on -// channelB. The channels on chainA and chainB are fully opened and a packet -// is sent from chainA to chainB and received. -func (suite *KeeperTestSuite) TestVerifyNextSequenceRecv() { - cases := []struct { - msg string - changeClientID bool - offsetSeq uint64 - heightDiff uint64 - delayPeriod uint64 - expPass bool - }{ - {"verification success", false, 0, 0, 0, true}, - {"verification success: delay period passed", false, 0, 0, uint64(1 * time.Second.Nanoseconds()), true}, - {"delay period has not passed", false, 0, 0, uint64(1 * time.Hour.Nanoseconds()), false}, - {"client state not found- changed client ID", true, 0, 0, 0, false}, - {"consensus state not found - increased proof height", false, 0, 5, 0, false}, - {"verification failed - wrong expected next seq recv", false, 1, 0, 0, false}, - } - - for _, tc := range cases { - tc := tc - - suite.Run(tc.msg, func() { - suite.SetupTest() // reset - - clientA, clientB, connA, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.UNORDERED) - - connection := suite.chainA.GetConnection(connA) - connection.DelayPeriod = tc.delayPeriod - if tc.changeClientID { - connection.ClientId = ibctesting.InvalidID - } - - // send and receive packet - packet := channeltypes.NewPacket(ibctesting.TestHash, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, defaultTimeoutHeight, 0) - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - - // increment receiving chain's (chainB) time by 2 hour to always pass receive - suite.coordinator.IncrementTimeBy(time.Hour * 2) - suite.coordinator.CommitBlock(suite.chainB) - - err = suite.coordinator.RecvPacket(suite.chainA, suite.chainB, clientA, packet) - suite.Require().NoError(err) - - nextSeqRecvKey := host.NextSequenceRecvKey(packet.GetDestPort(), packet.GetDestChannel()) - proof, proofHeight := suite.chainB.QueryProof(nextSeqRecvKey) - - err = suite.chainA.App.IBCKeeper.ConnectionKeeper.VerifyNextSequenceRecv( - suite.chainA.GetContext(), connection, malleateHeight(proofHeight, tc.heightDiff), proof, - packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()+tc.offsetSeq, - ) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} - -func malleateHeight(height exported.Height, diff uint64) exported.Height { - return clienttypes.NewHeight(height.GetRevisionNumber(), height.GetRevisionHeight()+diff) -} diff --git a/x/ibc/core/03-connection/module.go b/x/ibc/core/03-connection/module.go deleted file mode 100644 index 6100caa4622e..000000000000 --- a/x/ibc/core/03-connection/module.go +++ /dev/null @@ -1,29 +0,0 @@ -package connection - -import ( - "github.com/gogo/protobuf/grpc" - "github.com/spf13/cobra" - - "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/client/cli" - "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" -) - -// Name returns the IBC connection ICS name. -func Name() string { - return types.SubModuleName -} - -// GetTxCmd returns the root tx command for the IBC connections. -func GetTxCmd() *cobra.Command { - return cli.NewTxCmd() -} - -// GetQueryCmd returns the root query command for the IBC connections. -func GetQueryCmd() *cobra.Command { - return cli.GetQueryCmd() -} - -// RegisterQueryService registers the gRPC query service for IBC connections. -func RegisterQueryService(server grpc.Server, queryServer types.QueryServer) { - types.RegisterQueryServer(server, queryServer) -} diff --git a/x/ibc/core/03-connection/simulation/decoder.go b/x/ibc/core/03-connection/simulation/decoder.go deleted file mode 100644 index ef988a103f5e..000000000000 --- a/x/ibc/core/03-connection/simulation/decoder.go +++ /dev/null @@ -1,32 +0,0 @@ -package simulation - -import ( - "bytes" - "fmt" - - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/types/kv" - "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" -) - -// NewDecodeStore returns a decoder function closure that unmarshals the KVPair's -// Value to the corresponding connection type. -func NewDecodeStore(cdc codec.BinaryMarshaler, kvA, kvB kv.Pair) (string, bool) { - switch { - case bytes.HasPrefix(kvA.Key, host.KeyClientStorePrefix) && bytes.HasSuffix(kvA.Key, []byte(host.KeyConnectionPrefix)): - var clientConnectionsA, clientConnectionsB types.ClientPaths - cdc.MustUnmarshalBinaryBare(kvA.Value, &clientConnectionsA) - cdc.MustUnmarshalBinaryBare(kvB.Value, &clientConnectionsB) - return fmt.Sprintf("ClientPaths A: %v\nClientPaths B: %v", clientConnectionsA, clientConnectionsB), true - - case bytes.HasPrefix(kvA.Key, []byte(host.KeyConnectionPrefix)): - var connectionA, connectionB types.ConnectionEnd - cdc.MustUnmarshalBinaryBare(kvA.Value, &connectionA) - cdc.MustUnmarshalBinaryBare(kvB.Value, &connectionB) - return fmt.Sprintf("ConnectionEnd A: %v\nConnectionEnd B: %v", connectionA, connectionB), true - - default: - return "", false - } -} diff --git a/x/ibc/core/03-connection/simulation/decoder_test.go b/x/ibc/core/03-connection/simulation/decoder_test.go deleted file mode 100644 index 673bf640065b..000000000000 --- a/x/ibc/core/03-connection/simulation/decoder_test.go +++ /dev/null @@ -1,69 +0,0 @@ -package simulation_test - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/simapp" - "github.com/cosmos/cosmos-sdk/types/kv" - "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/simulation" - "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" -) - -func TestDecodeStore(t *testing.T) { - app := simapp.Setup(false) - cdc := app.AppCodec() - - connectionID := "connectionidone" - - connection := types.ConnectionEnd{ - ClientId: "clientidone", - Versions: types.ExportedVersionsToProto(types.GetCompatibleVersions()), - } - - paths := types.ClientPaths{ - Paths: []string{connectionID}, - } - - kvPairs := kv.Pairs{ - Pairs: []kv.Pair{ - { - Key: host.ClientConnectionsKey(connection.ClientId), - Value: cdc.MustMarshalBinaryBare(&paths), - }, - { - Key: host.ConnectionKey(connectionID), - Value: cdc.MustMarshalBinaryBare(&connection), - }, - { - Key: []byte{0x99}, - Value: []byte{0x99}, - }, - }, - } - tests := []struct { - name string - expectedLog string - }{ - {"ClientPaths", fmt.Sprintf("ClientPaths A: %v\nClientPaths B: %v", paths, paths)}, - {"ConnectionEnd", fmt.Sprintf("ConnectionEnd A: %v\nConnectionEnd B: %v", connection, connection)}, - {"other", ""}, - } - - for i, tt := range tests { - i, tt := i, tt - t.Run(tt.name, func(t *testing.T) { - res, found := simulation.NewDecodeStore(cdc, kvPairs.Pairs[i], kvPairs.Pairs[i]) - if i == len(tests)-1 { - require.False(t, found, string(kvPairs.Pairs[i].Key)) - require.Empty(t, res, string(kvPairs.Pairs[i].Key)) - } else { - require.True(t, found, string(kvPairs.Pairs[i].Key)) - require.Equal(t, tt.expectedLog, res, string(kvPairs.Pairs[i].Key)) - } - }) - } -} diff --git a/x/ibc/core/03-connection/simulation/genesis.go b/x/ibc/core/03-connection/simulation/genesis.go deleted file mode 100644 index 43b0823776df..000000000000 --- a/x/ibc/core/03-connection/simulation/genesis.go +++ /dev/null @@ -1,13 +0,0 @@ -package simulation - -import ( - "math/rand" - - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" -) - -// GenConnectionGenesis returns the default connection genesis state. -func GenConnectionGenesis(_ *rand.Rand, _ []simtypes.Account) types.GenesisState { - return types.DefaultGenesisState() -} diff --git a/x/ibc/core/03-connection/types/codec.go b/x/ibc/core/03-connection/types/codec.go deleted file mode 100644 index 6105fa9ee1db..000000000000 --- a/x/ibc/core/03-connection/types/codec.go +++ /dev/null @@ -1,47 +0,0 @@ -package types - -import ( - "github.com/cosmos/cosmos-sdk/codec" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/msgservice" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -// RegisterInterfaces register the ibc interfaces submodule implementations to protobuf -// Any. -func RegisterInterfaces(registry codectypes.InterfaceRegistry) { - registry.RegisterInterface( - "ibc.core.connection.v1.ConnectionI", - (*exported.ConnectionI)(nil), - &ConnectionEnd{}, - ) - registry.RegisterInterface( - "ibc.core.connection.v1.CounterpartyConnectionI", - (*exported.CounterpartyConnectionI)(nil), - &Counterparty{}, - ) - registry.RegisterInterface( - "ibc.core.connection.v1.Version", - (*exported.Version)(nil), - &Version{}, - ) - registry.RegisterImplementations( - (*sdk.Msg)(nil), - &MsgConnectionOpenInit{}, - &MsgConnectionOpenTry{}, - &MsgConnectionOpenAck{}, - &MsgConnectionOpenConfirm{}, - ) - - msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) -} - -var ( - // SubModuleCdc references the global x/ibc/core/03-connection 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/core/03-connection and - // defined at the application level. - SubModuleCdc = codec.NewProtoCodec(codectypes.NewInterfaceRegistry()) -) diff --git a/x/ibc/core/03-connection/types/connection.go b/x/ibc/core/03-connection/types/connection.go deleted file mode 100644 index 197af83cad99..000000000000 --- a/x/ibc/core/03-connection/types/connection.go +++ /dev/null @@ -1,127 +0,0 @@ -package types - -import ( - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -var _ exported.ConnectionI = (*ConnectionEnd)(nil) - -// NewConnectionEnd creates a new ConnectionEnd instance. -func NewConnectionEnd(state State, clientID string, counterparty Counterparty, versions []*Version, delayPeriod uint64) ConnectionEnd { - return ConnectionEnd{ - ClientId: clientID, - Versions: versions, - State: state, - Counterparty: counterparty, - DelayPeriod: delayPeriod, - } -} - -// GetState implements the Connection interface -func (c ConnectionEnd) GetState() int32 { - return int32(c.State) -} - -// GetClientID implements the Connection interface -func (c ConnectionEnd) GetClientID() string { - return c.ClientId -} - -// GetCounterparty implements the Connection interface -func (c ConnectionEnd) GetCounterparty() exported.CounterpartyConnectionI { - return c.Counterparty -} - -// GetVersions implements the Connection interface -func (c ConnectionEnd) GetVersions() []exported.Version { - return ProtoVersionsToExported(c.Versions) -} - -// GetDelayPeriod implements the Connection interface -func (c ConnectionEnd) GetDelayPeriod() uint64 { - return c.DelayPeriod -} - -// ValidateBasic implements the Connection interface. -// NOTE: the protocol supports that the connection and client IDs match the -// counterparty's. -func (c ConnectionEnd) ValidateBasic() error { - if err := host.ClientIdentifierValidator(c.ClientId); err != nil { - return sdkerrors.Wrap(err, "invalid client ID") - } - if len(c.Versions) == 0 { - return sdkerrors.Wrap(sdkerrors.ErrInvalidVersion, "empty connection versions") - } - for _, version := range c.Versions { - if err := ValidateVersion(version); err != nil { - return err - } - } - return c.Counterparty.ValidateBasic() -} - -var _ exported.CounterpartyConnectionI = (*Counterparty)(nil) - -// NewCounterparty creates a new Counterparty instance. -func NewCounterparty(clientID, connectionID string, prefix commitmenttypes.MerklePrefix) Counterparty { - return Counterparty{ - ClientId: clientID, - ConnectionId: connectionID, - Prefix: prefix, - } -} - -// GetClientID implements the CounterpartyConnectionI interface -func (c Counterparty) GetClientID() string { - return c.ClientId -} - -// GetConnectionID implements the CounterpartyConnectionI interface -func (c Counterparty) GetConnectionID() string { - return c.ConnectionId -} - -// GetPrefix implements the CounterpartyConnectionI interface -func (c Counterparty) GetPrefix() exported.Prefix { - return &c.Prefix -} - -// ValidateBasic performs a basic validation check of the identifiers and prefix -func (c Counterparty) ValidateBasic() error { - if c.ConnectionId != "" { - if err := host.ConnectionIdentifierValidator(c.ConnectionId); err != nil { - return sdkerrors.Wrap(err, "invalid counterparty connection ID") - } - } - if err := host.ClientIdentifierValidator(c.ClientId); err != nil { - return sdkerrors.Wrap(err, "invalid counterparty client ID") - } - if c.Prefix.Empty() { - return sdkerrors.Wrap(ErrInvalidCounterparty, "counterparty prefix cannot be empty") - } - return nil -} - -// NewIdentifiedConnection creates a new IdentifiedConnection instance -func NewIdentifiedConnection(connectionID string, conn ConnectionEnd) IdentifiedConnection { - return IdentifiedConnection{ - Id: connectionID, - ClientId: conn.ClientId, - Versions: conn.Versions, - State: conn.State, - Counterparty: conn.Counterparty, - DelayPeriod: conn.DelayPeriod, - } -} - -// ValidateBasic performs a basic validation of the connection identifier and connection fields. -func (ic IdentifiedConnection) ValidateBasic() error { - if err := host.ConnectionIdentifierValidator(ic.Id); err != nil { - return sdkerrors.Wrap(err, "invalid connection ID") - } - connection := NewConnectionEnd(ic.State, ic.ClientId, ic.Counterparty, ic.Versions, ic.DelayPeriod) - return connection.ValidateBasic() -} diff --git a/x/ibc/core/03-connection/types/connection.pb.go b/x/ibc/core/03-connection/types/connection.pb.go deleted file mode 100644 index 14b85c62d432..000000000000 --- a/x/ibc/core/03-connection/types/connection.pb.go +++ /dev/null @@ -1,1800 +0,0 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: ibc/core/connection/v1/connection.proto - -package types - -import ( - fmt "fmt" - types "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types" - _ "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 - -// State defines if a connection is in one of the following states: -// INIT, TRYOPEN, OPEN or UNINITIALIZED. -type State int32 - -const ( - // Default State - UNINITIALIZED State = 0 - // A connection end has just started the opening handshake. - INIT State = 1 - // A connection end has acknowledged the handshake step on the counterparty - // chain. - TRYOPEN State = 2 - // A connection end has completed the handshake. - OPEN State = 3 -) - -var State_name = map[int32]string{ - 0: "STATE_UNINITIALIZED_UNSPECIFIED", - 1: "STATE_INIT", - 2: "STATE_TRYOPEN", - 3: "STATE_OPEN", -} - -var State_value = map[string]int32{ - "STATE_UNINITIALIZED_UNSPECIFIED": 0, - "STATE_INIT": 1, - "STATE_TRYOPEN": 2, - "STATE_OPEN": 3, -} - -func (x State) String() string { - return proto.EnumName(State_name, int32(x)) -} - -func (State) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_90572467c054e43a, []int{0} -} - -// ConnectionEnd defines a stateful object on a chain connected to another -// separate one. -// NOTE: there must only be 2 defined ConnectionEnds to establish -// a connection between two chains. -type ConnectionEnd struct { - // client associated with this connection. - ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty" yaml:"client_id"` - // IBC version which can be utilised to determine encodings or protocols for - // channels or packets utilising this connection. - Versions []*Version `protobuf:"bytes,2,rep,name=versions,proto3" json:"versions,omitempty"` - // current state of the connection end. - State State `protobuf:"varint,3,opt,name=state,proto3,enum=ibc.core.connection.v1.State" json:"state,omitempty"` - // counterparty chain associated with this connection. - Counterparty Counterparty `protobuf:"bytes,4,opt,name=counterparty,proto3" json:"counterparty"` - // delay period that must pass before a consensus state can be used for packet-verification - // NOTE: delay period logic is only implemented by some clients. - DelayPeriod uint64 `protobuf:"varint,5,opt,name=delay_period,json=delayPeriod,proto3" json:"delay_period,omitempty" yaml:"delay_period"` -} - -func (m *ConnectionEnd) Reset() { *m = ConnectionEnd{} } -func (m *ConnectionEnd) String() string { return proto.CompactTextString(m) } -func (*ConnectionEnd) ProtoMessage() {} -func (*ConnectionEnd) Descriptor() ([]byte, []int) { - return fileDescriptor_90572467c054e43a, []int{0} -} -func (m *ConnectionEnd) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *ConnectionEnd) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_ConnectionEnd.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 *ConnectionEnd) XXX_Merge(src proto.Message) { - xxx_messageInfo_ConnectionEnd.Merge(m, src) -} -func (m *ConnectionEnd) XXX_Size() int { - return m.Size() -} -func (m *ConnectionEnd) XXX_DiscardUnknown() { - xxx_messageInfo_ConnectionEnd.DiscardUnknown(m) -} - -var xxx_messageInfo_ConnectionEnd proto.InternalMessageInfo - -// IdentifiedConnection defines a connection with additional connection -// identifier field. -type IdentifiedConnection struct { - // connection identifier. - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty" yaml:"id"` - // client associated with this connection. - ClientId string `protobuf:"bytes,2,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty" yaml:"client_id"` - // IBC version which can be utilised to determine encodings or protocols for - // channels or packets utilising this connection - Versions []*Version `protobuf:"bytes,3,rep,name=versions,proto3" json:"versions,omitempty"` - // current state of the connection end. - State State `protobuf:"varint,4,opt,name=state,proto3,enum=ibc.core.connection.v1.State" json:"state,omitempty"` - // counterparty chain associated with this connection. - Counterparty Counterparty `protobuf:"bytes,5,opt,name=counterparty,proto3" json:"counterparty"` - // delay period associated with this connection. - DelayPeriod uint64 `protobuf:"varint,6,opt,name=delay_period,json=delayPeriod,proto3" json:"delay_period,omitempty" yaml:"delay_period"` -} - -func (m *IdentifiedConnection) Reset() { *m = IdentifiedConnection{} } -func (m *IdentifiedConnection) String() string { return proto.CompactTextString(m) } -func (*IdentifiedConnection) ProtoMessage() {} -func (*IdentifiedConnection) Descriptor() ([]byte, []int) { - return fileDescriptor_90572467c054e43a, []int{1} -} -func (m *IdentifiedConnection) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *IdentifiedConnection) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_IdentifiedConnection.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 *IdentifiedConnection) XXX_Merge(src proto.Message) { - xxx_messageInfo_IdentifiedConnection.Merge(m, src) -} -func (m *IdentifiedConnection) XXX_Size() int { - return m.Size() -} -func (m *IdentifiedConnection) XXX_DiscardUnknown() { - xxx_messageInfo_IdentifiedConnection.DiscardUnknown(m) -} - -var xxx_messageInfo_IdentifiedConnection proto.InternalMessageInfo - -// Counterparty defines the counterparty chain associated with a connection end. -type Counterparty struct { - // identifies the client on the counterparty chain associated with a given - // connection. - ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty" yaml:"client_id"` - // identifies the connection end on the counterparty chain associated with a - // given connection. - ConnectionId string `protobuf:"bytes,2,opt,name=connection_id,json=connectionId,proto3" json:"connection_id,omitempty" yaml:"connection_id"` - // commitment merkle prefix of the counterparty chain. - Prefix types.MerklePrefix `protobuf:"bytes,3,opt,name=prefix,proto3" json:"prefix"` -} - -func (m *Counterparty) Reset() { *m = Counterparty{} } -func (m *Counterparty) String() string { return proto.CompactTextString(m) } -func (*Counterparty) ProtoMessage() {} -func (*Counterparty) Descriptor() ([]byte, []int) { - return fileDescriptor_90572467c054e43a, []int{2} -} -func (m *Counterparty) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *Counterparty) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_Counterparty.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 *Counterparty) XXX_Merge(src proto.Message) { - xxx_messageInfo_Counterparty.Merge(m, src) -} -func (m *Counterparty) XXX_Size() int { - return m.Size() -} -func (m *Counterparty) XXX_DiscardUnknown() { - xxx_messageInfo_Counterparty.DiscardUnknown(m) -} - -var xxx_messageInfo_Counterparty proto.InternalMessageInfo - -// ClientPaths define all the connection paths for a client state. -type ClientPaths struct { - // list of connection paths - Paths []string `protobuf:"bytes,1,rep,name=paths,proto3" json:"paths,omitempty"` -} - -func (m *ClientPaths) Reset() { *m = ClientPaths{} } -func (m *ClientPaths) String() string { return proto.CompactTextString(m) } -func (*ClientPaths) ProtoMessage() {} -func (*ClientPaths) Descriptor() ([]byte, []int) { - return fileDescriptor_90572467c054e43a, []int{3} -} -func (m *ClientPaths) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *ClientPaths) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_ClientPaths.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 *ClientPaths) XXX_Merge(src proto.Message) { - xxx_messageInfo_ClientPaths.Merge(m, src) -} -func (m *ClientPaths) XXX_Size() int { - return m.Size() -} -func (m *ClientPaths) XXX_DiscardUnknown() { - xxx_messageInfo_ClientPaths.DiscardUnknown(m) -} - -var xxx_messageInfo_ClientPaths proto.InternalMessageInfo - -func (m *ClientPaths) GetPaths() []string { - if m != nil { - return m.Paths - } - return nil -} - -// ConnectionPaths define all the connection paths for a given client state. -type ConnectionPaths struct { - // client state unique identifier - ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty" yaml:"client_id"` - // list of connection paths - Paths []string `protobuf:"bytes,2,rep,name=paths,proto3" json:"paths,omitempty"` -} - -func (m *ConnectionPaths) Reset() { *m = ConnectionPaths{} } -func (m *ConnectionPaths) String() string { return proto.CompactTextString(m) } -func (*ConnectionPaths) ProtoMessage() {} -func (*ConnectionPaths) Descriptor() ([]byte, []int) { - return fileDescriptor_90572467c054e43a, []int{4} -} -func (m *ConnectionPaths) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *ConnectionPaths) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_ConnectionPaths.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 *ConnectionPaths) XXX_Merge(src proto.Message) { - xxx_messageInfo_ConnectionPaths.Merge(m, src) -} -func (m *ConnectionPaths) XXX_Size() int { - return m.Size() -} -func (m *ConnectionPaths) XXX_DiscardUnknown() { - xxx_messageInfo_ConnectionPaths.DiscardUnknown(m) -} - -var xxx_messageInfo_ConnectionPaths proto.InternalMessageInfo - -func (m *ConnectionPaths) GetClientId() string { - if m != nil { - return m.ClientId - } - return "" -} - -func (m *ConnectionPaths) GetPaths() []string { - if m != nil { - return m.Paths - } - return nil -} - -// Version defines the versioning scheme used to negotiate the IBC verison in -// the connection handshake. -type Version struct { - // unique version identifier - Identifier string `protobuf:"bytes,1,opt,name=identifier,proto3" json:"identifier,omitempty"` - // list of features compatible with the specified identifier - Features []string `protobuf:"bytes,2,rep,name=features,proto3" json:"features,omitempty"` -} - -func (m *Version) Reset() { *m = Version{} } -func (m *Version) String() string { return proto.CompactTextString(m) } -func (*Version) ProtoMessage() {} -func (*Version) Descriptor() ([]byte, []int) { - return fileDescriptor_90572467c054e43a, []int{5} -} -func (m *Version) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *Version) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_Version.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 *Version) XXX_Merge(src proto.Message) { - xxx_messageInfo_Version.Merge(m, src) -} -func (m *Version) XXX_Size() int { - return m.Size() -} -func (m *Version) XXX_DiscardUnknown() { - xxx_messageInfo_Version.DiscardUnknown(m) -} - -var xxx_messageInfo_Version proto.InternalMessageInfo - -func init() { - proto.RegisterEnum("ibc.core.connection.v1.State", State_name, State_value) - proto.RegisterType((*ConnectionEnd)(nil), "ibc.core.connection.v1.ConnectionEnd") - proto.RegisterType((*IdentifiedConnection)(nil), "ibc.core.connection.v1.IdentifiedConnection") - proto.RegisterType((*Counterparty)(nil), "ibc.core.connection.v1.Counterparty") - proto.RegisterType((*ClientPaths)(nil), "ibc.core.connection.v1.ClientPaths") - proto.RegisterType((*ConnectionPaths)(nil), "ibc.core.connection.v1.ConnectionPaths") - proto.RegisterType((*Version)(nil), "ibc.core.connection.v1.Version") -} - -func init() { - proto.RegisterFile("ibc/core/connection/v1/connection.proto", fileDescriptor_90572467c054e43a) -} - -var fileDescriptor_90572467c054e43a = []byte{ - // 654 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0x41, 0x6b, 0xdb, 0x4c, - 0x14, 0x94, 0x64, 0x39, 0xb1, 0xd7, 0xf1, 0xf7, 0xb9, 0x5b, 0xd3, 0x0a, 0x41, 0x24, 0xa1, 0x16, - 0x6a, 0x0a, 0xb1, 0xea, 0x04, 0x7a, 0x48, 0xe8, 0x21, 0x76, 0x5c, 0x10, 0x6d, 0x5d, 0xa3, 0x38, - 0x85, 0xe6, 0x62, 0x6c, 0x69, 0x93, 0x2c, 0xb1, 0xb5, 0x42, 0xda, 0x98, 0xf8, 0x1f, 0x84, 0x9c, - 0x7a, 0xed, 0x21, 0x50, 0xe8, 0x7f, 0x29, 0xa1, 0xa7, 0x1c, 0x7b, 0x32, 0x25, 0xb9, 0xf6, 0xe4, - 0x5f, 0x50, 0xa4, 0x95, 0x65, 0x25, 0x34, 0x87, 0xa4, 0x3d, 0xf9, 0xcd, 0xbe, 0x99, 0xf1, 0xbe, - 0xf1, 0xf3, 0x82, 0x67, 0xb8, 0x6f, 0x1b, 0x36, 0xf1, 0x91, 0x61, 0x13, 0xd7, 0x45, 0x36, 0xc5, - 0xc4, 0x35, 0x46, 0xb5, 0x14, 0xaa, 0x7a, 0x3e, 0xa1, 0x04, 0x3e, 0xc2, 0x7d, 0xbb, 0x1a, 0x12, - 0xab, 0xa9, 0xd6, 0xa8, 0x26, 0x97, 0xf7, 0xc9, 0x3e, 0x89, 0x28, 0x46, 0x58, 0x31, 0xb6, 0x9c, - 0xb6, 0x1d, 0x0e, 0x31, 0x1d, 0x22, 0x97, 0x32, 0xdb, 0x19, 0x62, 0x44, 0xfd, 0x9b, 0x00, 0x8a, - 0x8d, 0xc4, 0xb0, 0xe9, 0x3a, 0xb0, 0x06, 0xf2, 0xf6, 0x00, 0x23, 0x97, 0x76, 0xb1, 0x23, 0xf1, - 0x1a, 0x5f, 0xc9, 0xd7, 0xcb, 0xd3, 0x89, 0x5a, 0x1a, 0xf7, 0x86, 0x83, 0x75, 0x3d, 0x69, 0xe9, - 0x56, 0x8e, 0xd5, 0xa6, 0x03, 0x37, 0x40, 0x6e, 0x84, 0xfc, 0x00, 0x13, 0x37, 0x90, 0x04, 0x2d, - 0x53, 0x29, 0xac, 0xaa, 0xd5, 0x3f, 0x5f, 0xb7, 0xfa, 0x81, 0xf1, 0xac, 0x44, 0x00, 0xd7, 0x40, - 0x36, 0xa0, 0x3d, 0x8a, 0xa4, 0x8c, 0xc6, 0x57, 0xfe, 0x5b, 0x5d, 0xbe, 0x4d, 0xb9, 0x1d, 0x92, - 0x2c, 0xc6, 0x85, 0x2d, 0xb0, 0x64, 0x93, 0x23, 0x97, 0x22, 0xdf, 0xeb, 0xf9, 0x74, 0x2c, 0x89, - 0x1a, 0x5f, 0x29, 0xac, 0x3e, 0xbd, 0x4d, 0xdb, 0x48, 0x71, 0xeb, 0xe2, 0xf9, 0x44, 0xe5, 0xac, - 0x6b, 0x7a, 0xb8, 0x0e, 0x96, 0x1c, 0x34, 0xe8, 0x8d, 0xbb, 0x1e, 0xf2, 0x31, 0x71, 0xa4, 0xac, - 0xc6, 0x57, 0xc4, 0xfa, 0xe3, 0xe9, 0x44, 0x7d, 0xc8, 0xe6, 0x4e, 0x77, 0x75, 0xab, 0x10, 0xc1, - 0x76, 0x84, 0xd6, 0xc5, 0x93, 0x2f, 0x2a, 0xa7, 0xff, 0x12, 0x40, 0xd9, 0x74, 0x90, 0x4b, 0xf1, - 0x1e, 0x46, 0xce, 0x3c, 0x52, 0xb8, 0x0c, 0x84, 0x24, 0xc8, 0xe2, 0x74, 0xa2, 0xe6, 0x99, 0x61, - 0x98, 0xa0, 0x80, 0x6f, 0xc4, 0x2d, 0xdc, 0x39, 0xee, 0xcc, 0xbd, 0xe3, 0x16, 0xff, 0x22, 0xee, - 0xec, 0x3f, 0x8e, 0x7b, 0xe1, 0xce, 0x71, 0x7f, 0xe7, 0xc1, 0x52, 0xfa, 0x6b, 0xee, 0xb3, 0xb6, - 0xaf, 0x40, 0x71, 0x7e, 0xef, 0x79, 0xfc, 0xd2, 0x74, 0xa2, 0x96, 0x63, 0x59, 0xba, 0xad, 0x87, - 0x43, 0xcc, 0xb0, 0xe9, 0xc0, 0x3a, 0x58, 0xf0, 0x7c, 0xb4, 0x87, 0x8f, 0xa3, 0xcd, 0xbd, 0x11, - 0x47, 0xf2, 0x37, 0x1b, 0xd5, 0xaa, 0xef, 0x90, 0x7f, 0x38, 0x40, 0xed, 0x88, 0x1b, 0xc7, 0x11, - 0x2b, 0xe3, 0x61, 0x9e, 0x80, 0x42, 0x23, 0xba, 0x54, 0xbb, 0x47, 0x0f, 0x02, 0x58, 0x06, 0x59, - 0x2f, 0x2c, 0x24, 0x5e, 0xcb, 0x54, 0xf2, 0x16, 0x03, 0xfa, 0x2e, 0xf8, 0x7f, 0xbe, 0x55, 0x8c, - 0x78, 0x8f, 0x99, 0x13, 0x6f, 0x21, 0xed, 0xfd, 0x06, 0x2c, 0xc6, 0x9b, 0x02, 0x15, 0x00, 0xf0, - 0x6c, 0x8d, 0x7d, 0x66, 0x6a, 0xa5, 0x4e, 0xa0, 0x0c, 0x72, 0x7b, 0xa8, 0x47, 0x8f, 0x7c, 0x34, - 0xf3, 0x48, 0x30, 0x9b, 0xe6, 0xf9, 0x67, 0x1e, 0x64, 0xa3, 0xed, 0x81, 0x2f, 0x81, 0xba, 0xdd, - 0xd9, 0xec, 0x34, 0xbb, 0x3b, 0x2d, 0xb3, 0x65, 0x76, 0xcc, 0xcd, 0xb7, 0xe6, 0x6e, 0x73, 0xab, - 0xbb, 0xd3, 0xda, 0x6e, 0x37, 0x1b, 0xe6, 0x6b, 0xb3, 0xb9, 0x55, 0xe2, 0xe4, 0x07, 0xa7, 0x67, - 0x5a, 0xf1, 0x1a, 0x01, 0x4a, 0x00, 0x30, 0x5d, 0x78, 0x58, 0xe2, 0xe5, 0xdc, 0xe9, 0x99, 0x26, - 0x86, 0x35, 0x54, 0x40, 0x91, 0x75, 0x3a, 0xd6, 0xc7, 0xf7, 0xed, 0x66, 0xab, 0x24, 0xc8, 0x85, - 0xd3, 0x33, 0x6d, 0x31, 0x86, 0x73, 0x65, 0xd4, 0xcc, 0x30, 0x65, 0x58, 0xcb, 0xe2, 0xc9, 0x57, - 0x85, 0xab, 0xef, 0x9c, 0x5f, 0x2a, 0xfc, 0xc5, 0xa5, 0xc2, 0xff, 0xbc, 0x54, 0xf8, 0x4f, 0x57, - 0x0a, 0x77, 0x71, 0xa5, 0x70, 0x3f, 0xae, 0x14, 0x6e, 0x77, 0x63, 0x1f, 0xd3, 0x83, 0xa3, 0x7e, - 0xf8, 0xd3, 0x19, 0x36, 0x09, 0x86, 0x24, 0x88, 0x3f, 0x56, 0x02, 0xe7, 0xd0, 0x38, 0x36, 0x92, - 0x07, 0xf5, 0xc5, 0xda, 0x4a, 0xea, 0xa9, 0xa6, 0x63, 0x0f, 0x05, 0xfd, 0x85, 0xe8, 0x31, 0x5d, - 0xfb, 0x1d, 0x00, 0x00, 0xff, 0xff, 0x48, 0x0f, 0xf2, 0xaa, 0xce, 0x05, 0x00, 0x00, -} - -func (m *ConnectionEnd) 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 *ConnectionEnd) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *ConnectionEnd) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.DelayPeriod != 0 { - i = encodeVarintConnection(dAtA, i, uint64(m.DelayPeriod)) - i-- - dAtA[i] = 0x28 - } - { - size, err := m.Counterparty.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintConnection(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x22 - if m.State != 0 { - i = encodeVarintConnection(dAtA, i, uint64(m.State)) - i-- - dAtA[i] = 0x18 - } - if len(m.Versions) > 0 { - for iNdEx := len(m.Versions) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.Versions[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintConnection(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - } - } - if len(m.ClientId) > 0 { - i -= len(m.ClientId) - copy(dAtA[i:], m.ClientId) - i = encodeVarintConnection(dAtA, i, uint64(len(m.ClientId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *IdentifiedConnection) 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 *IdentifiedConnection) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *IdentifiedConnection) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.DelayPeriod != 0 { - i = encodeVarintConnection(dAtA, i, uint64(m.DelayPeriod)) - i-- - dAtA[i] = 0x30 - } - { - size, err := m.Counterparty.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintConnection(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x2a - if m.State != 0 { - i = encodeVarintConnection(dAtA, i, uint64(m.State)) - i-- - dAtA[i] = 0x20 - } - if len(m.Versions) > 0 { - for iNdEx := len(m.Versions) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.Versions[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintConnection(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - } - } - if len(m.ClientId) > 0 { - i -= len(m.ClientId) - copy(dAtA[i:], m.ClientId) - i = encodeVarintConnection(dAtA, i, uint64(len(m.ClientId))) - i-- - dAtA[i] = 0x12 - } - if len(m.Id) > 0 { - i -= len(m.Id) - copy(dAtA[i:], m.Id) - i = encodeVarintConnection(dAtA, i, uint64(len(m.Id))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *Counterparty) 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 *Counterparty) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *Counterparty) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - { - size, err := m.Prefix.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintConnection(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - if len(m.ConnectionId) > 0 { - i -= len(m.ConnectionId) - copy(dAtA[i:], m.ConnectionId) - i = encodeVarintConnection(dAtA, i, uint64(len(m.ConnectionId))) - i-- - dAtA[i] = 0x12 - } - if len(m.ClientId) > 0 { - i -= len(m.ClientId) - copy(dAtA[i:], m.ClientId) - i = encodeVarintConnection(dAtA, i, uint64(len(m.ClientId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *ClientPaths) 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 *ClientPaths) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *ClientPaths) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Paths) > 0 { - for iNdEx := len(m.Paths) - 1; iNdEx >= 0; iNdEx-- { - i -= len(m.Paths[iNdEx]) - copy(dAtA[i:], m.Paths[iNdEx]) - i = encodeVarintConnection(dAtA, i, uint64(len(m.Paths[iNdEx]))) - i-- - dAtA[i] = 0xa - } - } - return len(dAtA) - i, nil -} - -func (m *ConnectionPaths) 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 *ConnectionPaths) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *ConnectionPaths) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Paths) > 0 { - for iNdEx := len(m.Paths) - 1; iNdEx >= 0; iNdEx-- { - i -= len(m.Paths[iNdEx]) - copy(dAtA[i:], m.Paths[iNdEx]) - i = encodeVarintConnection(dAtA, i, uint64(len(m.Paths[iNdEx]))) - i-- - dAtA[i] = 0x12 - } - } - if len(m.ClientId) > 0 { - i -= len(m.ClientId) - copy(dAtA[i:], m.ClientId) - i = encodeVarintConnection(dAtA, i, uint64(len(m.ClientId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *Version) 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 *Version) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *Version) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Features) > 0 { - for iNdEx := len(m.Features) - 1; iNdEx >= 0; iNdEx-- { - i -= len(m.Features[iNdEx]) - copy(dAtA[i:], m.Features[iNdEx]) - i = encodeVarintConnection(dAtA, i, uint64(len(m.Features[iNdEx]))) - i-- - dAtA[i] = 0x12 - } - } - if len(m.Identifier) > 0 { - i -= len(m.Identifier) - copy(dAtA[i:], m.Identifier) - i = encodeVarintConnection(dAtA, i, uint64(len(m.Identifier))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func encodeVarintConnection(dAtA []byte, offset int, v uint64) int { - offset -= sovConnection(v) - base := offset - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ - } - dAtA[offset] = uint8(v) - return base -} -func (m *ConnectionEnd) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.ClientId) - if l > 0 { - n += 1 + l + sovConnection(uint64(l)) - } - if len(m.Versions) > 0 { - for _, e := range m.Versions { - l = e.Size() - n += 1 + l + sovConnection(uint64(l)) - } - } - if m.State != 0 { - n += 1 + sovConnection(uint64(m.State)) - } - l = m.Counterparty.Size() - n += 1 + l + sovConnection(uint64(l)) - if m.DelayPeriod != 0 { - n += 1 + sovConnection(uint64(m.DelayPeriod)) - } - return n -} - -func (m *IdentifiedConnection) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Id) - if l > 0 { - n += 1 + l + sovConnection(uint64(l)) - } - l = len(m.ClientId) - if l > 0 { - n += 1 + l + sovConnection(uint64(l)) - } - if len(m.Versions) > 0 { - for _, e := range m.Versions { - l = e.Size() - n += 1 + l + sovConnection(uint64(l)) - } - } - if m.State != 0 { - n += 1 + sovConnection(uint64(m.State)) - } - l = m.Counterparty.Size() - n += 1 + l + sovConnection(uint64(l)) - if m.DelayPeriod != 0 { - n += 1 + sovConnection(uint64(m.DelayPeriod)) - } - return n -} - -func (m *Counterparty) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.ClientId) - if l > 0 { - n += 1 + l + sovConnection(uint64(l)) - } - l = len(m.ConnectionId) - if l > 0 { - n += 1 + l + sovConnection(uint64(l)) - } - l = m.Prefix.Size() - n += 1 + l + sovConnection(uint64(l)) - return n -} - -func (m *ClientPaths) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if len(m.Paths) > 0 { - for _, s := range m.Paths { - l = len(s) - n += 1 + l + sovConnection(uint64(l)) - } - } - return n -} - -func (m *ConnectionPaths) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.ClientId) - if l > 0 { - n += 1 + l + sovConnection(uint64(l)) - } - if len(m.Paths) > 0 { - for _, s := range m.Paths { - l = len(s) - n += 1 + l + sovConnection(uint64(l)) - } - } - return n -} - -func (m *Version) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Identifier) - if l > 0 { - n += 1 + l + sovConnection(uint64(l)) - } - if len(m.Features) > 0 { - for _, s := range m.Features { - l = len(s) - n += 1 + l + sovConnection(uint64(l)) - } - } - return n -} - -func sovConnection(x uint64) (n int) { - return (math_bits.Len64(x|1) + 6) / 7 -} -func sozConnection(x uint64) (n int) { - return sovConnection(uint64((x << 1) ^ uint64((int64(x) >> 63)))) -} -func (m *ConnectionEnd) 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 ErrIntOverflowConnection - } - 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: ConnectionEnd: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: ConnectionEnd: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ClientId", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowConnection - } - 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 ErrInvalidLengthConnection - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthConnection - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ClientId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Versions", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowConnection - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthConnection - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthConnection - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Versions = append(m.Versions, &Version{}) - if err := m.Versions[len(m.Versions)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field State", wireType) - } - m.State = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowConnection - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.State |= State(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Counterparty", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowConnection - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthConnection - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthConnection - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.Counterparty.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 5: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field DelayPeriod", wireType) - } - m.DelayPeriod = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowConnection - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.DelayPeriod |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - default: - iNdEx = preIndex - skippy, err := skipConnection(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthConnection - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *IdentifiedConnection) 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 ErrIntOverflowConnection - } - 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: IdentifiedConnection: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: IdentifiedConnection: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowConnection - } - 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 ErrInvalidLengthConnection - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthConnection - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Id = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ClientId", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowConnection - } - 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 ErrInvalidLengthConnection - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthConnection - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ClientId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Versions", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowConnection - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthConnection - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthConnection - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Versions = append(m.Versions, &Version{}) - if err := m.Versions[len(m.Versions)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 4: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field State", wireType) - } - m.State = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowConnection - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.State |= State(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Counterparty", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowConnection - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthConnection - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthConnection - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.Counterparty.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 6: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field DelayPeriod", wireType) - } - m.DelayPeriod = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowConnection - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.DelayPeriod |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - default: - iNdEx = preIndex - skippy, err := skipConnection(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthConnection - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *Counterparty) 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 ErrIntOverflowConnection - } - 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: Counterparty: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: Counterparty: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ClientId", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowConnection - } - 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 ErrInvalidLengthConnection - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthConnection - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ClientId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ConnectionId", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowConnection - } - 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 ErrInvalidLengthConnection - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthConnection - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ConnectionId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Prefix", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowConnection - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthConnection - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthConnection - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.Prefix.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipConnection(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthConnection - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *ClientPaths) 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 ErrIntOverflowConnection - } - 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: ClientPaths: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: ClientPaths: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Paths", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowConnection - } - 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 ErrInvalidLengthConnection - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthConnection - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Paths = append(m.Paths, string(dAtA[iNdEx:postIndex])) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipConnection(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthConnection - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *ConnectionPaths) 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 ErrIntOverflowConnection - } - 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: ConnectionPaths: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: ConnectionPaths: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ClientId", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowConnection - } - 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 ErrInvalidLengthConnection - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthConnection - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ClientId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Paths", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowConnection - } - 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 ErrInvalidLengthConnection - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthConnection - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Paths = append(m.Paths, string(dAtA[iNdEx:postIndex])) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipConnection(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthConnection - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *Version) 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 ErrIntOverflowConnection - } - 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: Version: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: Version: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Identifier", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowConnection - } - 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 ErrInvalidLengthConnection - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthConnection - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Identifier = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Features", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowConnection - } - 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 ErrInvalidLengthConnection - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthConnection - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Features = append(m.Features, string(dAtA[iNdEx:postIndex])) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipConnection(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthConnection - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func skipConnection(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, ErrIntOverflowConnection - } - 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, ErrIntOverflowConnection - } - 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, ErrIntOverflowConnection - } - 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, ErrInvalidLengthConnection - } - iNdEx += length - case 3: - depth++ - case 4: - if depth == 0 { - return 0, ErrUnexpectedEndOfGroupConnection - } - depth-- - case 5: - iNdEx += 4 - default: - return 0, fmt.Errorf("proto: illegal wireType %d", wireType) - } - if iNdEx < 0 { - return 0, ErrInvalidLengthConnection - } - if depth == 0 { - return iNdEx, nil - } - } - return 0, io.ErrUnexpectedEOF -} - -var ( - ErrInvalidLengthConnection = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowConnection = fmt.Errorf("proto: integer overflow") - ErrUnexpectedEndOfGroupConnection = fmt.Errorf("proto: unexpected end of group") -) diff --git a/x/ibc/core/03-connection/types/connection_test.go b/x/ibc/core/03-connection/types/connection_test.go deleted file mode 100644 index e7e91538c4e3..000000000000 --- a/x/ibc/core/03-connection/types/connection_test.go +++ /dev/null @@ -1,121 +0,0 @@ -package types_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" -) - -var ( - chainID = "gaiamainnet" - connectionID = "connection-0" - clientID = "clientidone" - connectionID2 = "connectionidtwo" - clientID2 = "clientidtwo" - invalidConnectionID = "(invalidConnectionID)" - clientHeight = clienttypes.NewHeight(0, 6) -) - -func TestConnectionValidateBasic(t *testing.T) { - testCases := []struct { - name string - connection types.ConnectionEnd - expPass bool - }{ - { - "valid connection", - types.ConnectionEnd{clientID, []*types.Version{ibctesting.ConnectionVersion}, types.INIT, types.Counterparty{clientID2, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))}, 500}, - true, - }, - { - "invalid client id", - types.ConnectionEnd{"(clientID1)", []*types.Version{ibctesting.ConnectionVersion}, types.INIT, types.Counterparty{clientID2, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))}, 500}, - false, - }, - { - "empty versions", - types.ConnectionEnd{clientID, nil, types.INIT, types.Counterparty{clientID2, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))}, 500}, - false, - }, - { - "invalid version", - types.ConnectionEnd{clientID, []*types.Version{{}}, types.INIT, types.Counterparty{clientID2, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))}, 500}, - false, - }, - { - "invalid counterparty", - types.ConnectionEnd{clientID, []*types.Version{ibctesting.ConnectionVersion}, types.INIT, types.Counterparty{clientID2, connectionID2, emptyPrefix}, 500}, - false, - }, - } - - for i, tc := range testCases { - tc := tc - - err := tc.connection.ValidateBasic() - if tc.expPass { - require.NoError(t, err, "valid test case %d failed: %s", i, tc.name) - } else { - require.Error(t, err, "invalid test case %d passed: %s", i, tc.name) - } - } -} - -func TestCounterpartyValidateBasic(t *testing.T) { - testCases := []struct { - name string - counterparty types.Counterparty - expPass bool - }{ - {"valid counterparty", types.Counterparty{clientID, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))}, true}, - {"invalid client id", types.Counterparty{"(InvalidClient)", connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))}, false}, - {"invalid connection id", types.Counterparty{clientID, "(InvalidConnection)", commitmenttypes.NewMerklePrefix([]byte("prefix"))}, false}, - {"invalid prefix", types.Counterparty{clientID, connectionID2, emptyPrefix}, false}, - } - - for i, tc := range testCases { - tc := tc - - err := tc.counterparty.ValidateBasic() - if tc.expPass { - require.NoError(t, err, "valid test case %d failed: %s", i, tc.name) - } else { - require.Error(t, err, "invalid test case %d passed: %s", i, tc.name) - } - } -} - -func TestIdentifiedConnectionValidateBasic(t *testing.T) { - testCases := []struct { - name string - connection types.IdentifiedConnection - expPass bool - }{ - { - "valid connection", - types.NewIdentifiedConnection(clientID, types.ConnectionEnd{clientID, []*types.Version{ibctesting.ConnectionVersion}, types.INIT, types.Counterparty{clientID2, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))}, 500}), - true, - }, - { - "invalid connection id", - types.NewIdentifiedConnection("(connectionIDONE)", types.ConnectionEnd{clientID, []*types.Version{ibctesting.ConnectionVersion}, types.INIT, types.Counterparty{clientID2, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))}, 500}), - false, - }, - } - - for i, tc := range testCases { - tc := tc - - err := tc.connection.ValidateBasic() - if tc.expPass { - require.NoError(t, err, "valid test case %d failed: %s", i, tc.name) - } else { - require.Error(t, err, "invalid test case %d passed: %s", i, tc.name) - } - } -} diff --git a/x/ibc/core/03-connection/types/errors.go b/x/ibc/core/03-connection/types/errors.go deleted file mode 100644 index 107a0e087c17..000000000000 --- a/x/ibc/core/03-connection/types/errors.go +++ /dev/null @@ -1,19 +0,0 @@ -package types - -import ( - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" -) - -// IBC connection sentinel errors -var ( - ErrConnectionExists = sdkerrors.Register(SubModuleName, 2, "connection already exists") - ErrConnectionNotFound = sdkerrors.Register(SubModuleName, 3, "connection not found") - ErrClientConnectionPathsNotFound = sdkerrors.Register(SubModuleName, 4, "light client connection paths not found") - ErrConnectionPath = sdkerrors.Register(SubModuleName, 5, "connection path is not associated to the given light client") - ErrInvalidConnectionState = sdkerrors.Register(SubModuleName, 6, "invalid connection state") - ErrInvalidCounterparty = sdkerrors.Register(SubModuleName, 7, "invalid counterparty connection") - ErrInvalidConnection = sdkerrors.Register(SubModuleName, 8, "invalid connection") - ErrInvalidVersion = sdkerrors.Register(SubModuleName, 9, "invalid connection version") - ErrVersionNegotiationFailed = sdkerrors.Register(SubModuleName, 10, "connection version negotiation failed") - ErrInvalidConnectionIdentifier = sdkerrors.Register(SubModuleName, 11, "invalid connection identifier") -) diff --git a/x/ibc/core/03-connection/types/events.go b/x/ibc/core/03-connection/types/events.go deleted file mode 100644 index 3cb5997bd105..000000000000 --- a/x/ibc/core/03-connection/types/events.go +++ /dev/null @@ -1,25 +0,0 @@ -package types - -import ( - "fmt" - - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" -) - -// IBC connection events -const ( - AttributeKeyConnectionID = "connection_id" - AttributeKeyClientID = "client_id" - AttributeKeyCounterpartyClientID = "counterparty_client_id" - AttributeKeyCounterpartyConnectionID = "counterparty_connection_id" -) - -// IBC connection events vars -var ( - EventTypeConnectionOpenInit = MsgConnectionOpenInit{}.Type() - EventTypeConnectionOpenTry = MsgConnectionOpenTry{}.Type() - EventTypeConnectionOpenAck = MsgConnectionOpenAck{}.Type() - EventTypeConnectionOpenConfirm = MsgConnectionOpenConfirm{}.Type() - - AttributeValueCategory = fmt.Sprintf("%s_%s", host.ModuleName, SubModuleName) -) diff --git a/x/ibc/core/03-connection/types/expected_keepers.go b/x/ibc/core/03-connection/types/expected_keepers.go deleted file mode 100644 index 9fc995867188..000000000000 --- a/x/ibc/core/03-connection/types/expected_keepers.go +++ /dev/null @@ -1,16 +0,0 @@ -package types - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -// ClientKeeper expected account IBC client keeper -type ClientKeeper interface { - GetClientState(ctx sdk.Context, clientID string) (exported.ClientState, bool) - GetClientConsensusState(ctx sdk.Context, clientID string, height exported.Height) (exported.ConsensusState, bool) - GetSelfConsensusState(ctx sdk.Context, height exported.Height) (exported.ConsensusState, bool) - ValidateSelfClient(ctx sdk.Context, clientState exported.ClientState) error - IterateClients(ctx sdk.Context, cb func(string, exported.ClientState) bool) - ClientStore(ctx sdk.Context, clientID string) sdk.KVStore -} diff --git a/x/ibc/core/03-connection/types/genesis.go b/x/ibc/core/03-connection/types/genesis.go deleted file mode 100644 index b10c300a84a5..000000000000 --- a/x/ibc/core/03-connection/types/genesis.go +++ /dev/null @@ -1,76 +0,0 @@ -package types - -import ( - "fmt" - - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" -) - -// NewConnectionPaths creates a ConnectionPaths instance. -func NewConnectionPaths(id string, paths []string) ConnectionPaths { - return ConnectionPaths{ - ClientId: id, - Paths: paths, - } -} - -// NewGenesisState creates a GenesisState instance. -func NewGenesisState( - connections []IdentifiedConnection, connPaths []ConnectionPaths, - nextConnectionSequence uint64, -) GenesisState { - return GenesisState{ - Connections: connections, - ClientConnectionPaths: connPaths, - NextConnectionSequence: nextConnectionSequence, - } -} - -// DefaultGenesisState returns the ibc connection submodule's default genesis state. -func DefaultGenesisState() GenesisState { - return GenesisState{ - Connections: []IdentifiedConnection{}, - ClientConnectionPaths: []ConnectionPaths{}, - NextConnectionSequence: 0, - } -} - -// Validate performs basic genesis state validation returning an error upon any -// failure. -func (gs GenesisState) Validate() error { - // keep track of the max sequence to ensure it is less than - // the next sequence used in creating connection identifers. - var maxSequence uint64 = 0 - - for i, conn := range gs.Connections { - sequence, err := ParseConnectionSequence(conn.Id) - if err != nil { - return err - } - - if sequence > maxSequence { - maxSequence = sequence - } - - if err := conn.ValidateBasic(); err != nil { - return fmt.Errorf("invalid connection %v index %d: %w", conn, i, err) - } - } - - for i, conPaths := range gs.ClientConnectionPaths { - if err := host.ClientIdentifierValidator(conPaths.ClientId); err != nil { - return fmt.Errorf("invalid client connection path %d: %w", i, err) - } - for _, connectionID := range conPaths.Paths { - if err := host.ConnectionIdentifierValidator(connectionID); err != nil { - return fmt.Errorf("invalid client connection ID (%s) in connection paths %d: %w", connectionID, i, err) - } - } - } - - if maxSequence != 0 && maxSequence >= gs.NextConnectionSequence { - return fmt.Errorf("next connection sequence %d must be greater than maximum sequence used in connection identifier %d", gs.NextConnectionSequence, maxSequence) - } - - return nil -} diff --git a/x/ibc/core/03-connection/types/genesis.pb.go b/x/ibc/core/03-connection/types/genesis.pb.go deleted file mode 100644 index 5f33f166ae07..000000000000 --- a/x/ibc/core/03-connection/types/genesis.pb.go +++ /dev/null @@ -1,438 +0,0 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: ibc/core/connection/v1/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 defines the ibc connection submodule's genesis state. -type GenesisState struct { - Connections []IdentifiedConnection `protobuf:"bytes,1,rep,name=connections,proto3" json:"connections"` - ClientConnectionPaths []ConnectionPaths `protobuf:"bytes,2,rep,name=client_connection_paths,json=clientConnectionPaths,proto3" json:"client_connection_paths" yaml:"client_connection_paths"` - // the sequence for the next generated connection identifier - NextConnectionSequence uint64 `protobuf:"varint,3,opt,name=next_connection_sequence,json=nextConnectionSequence,proto3" json:"next_connection_sequence,omitempty" yaml:"next_connection_sequence"` -} - -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_1879d34bc6ac3cd7, []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) GetConnections() []IdentifiedConnection { - if m != nil { - return m.Connections - } - return nil -} - -func (m *GenesisState) GetClientConnectionPaths() []ConnectionPaths { - if m != nil { - return m.ClientConnectionPaths - } - return nil -} - -func (m *GenesisState) GetNextConnectionSequence() uint64 { - if m != nil { - return m.NextConnectionSequence - } - return 0 -} - -func init() { - proto.RegisterType((*GenesisState)(nil), "ibc.core.connection.v1.GenesisState") -} - -func init() { - proto.RegisterFile("ibc/core/connection/v1/genesis.proto", fileDescriptor_1879d34bc6ac3cd7) -} - -var fileDescriptor_1879d34bc6ac3cd7 = []byte{ - // 326 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0xc9, 0x4c, 0x4a, 0xd6, - 0x4f, 0xce, 0x2f, 0x4a, 0xd5, 0x4f, 0xce, 0xcf, 0xcb, 0x4b, 0x4d, 0x2e, 0xc9, 0xcc, 0xcf, 0xd3, - 0x2f, 0x33, 0xd4, 0x4f, 0x4f, 0xcd, 0x4b, 0x2d, 0xce, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, - 0x17, 0x12, 0xcb, 0x4c, 0x4a, 0xd6, 0x03, 0xa9, 0xd2, 0x43, 0xa8, 0xd2, 0x2b, 0x33, 0x94, 0x12, - 0x49, 0xcf, 0x4f, 0xcf, 0x07, 0x2b, 0xd1, 0x07, 0xb1, 0x20, 0xaa, 0xa5, 0xd4, 0x71, 0x98, 0x89, - 0xa4, 0x17, 0xac, 0x50, 0xe9, 0x2c, 0x13, 0x17, 0x8f, 0x3b, 0xc4, 0xa2, 0xe0, 0x92, 0xc4, 0x92, - 0x54, 0xa1, 0x10, 0x2e, 0x6e, 0x84, 0xa2, 0x62, 0x09, 0x46, 0x05, 0x66, 0x0d, 0x6e, 0x23, 0x1d, - 0x3d, 0xec, 0xb6, 0xeb, 0x79, 0xa6, 0xa4, 0xe6, 0x95, 0x64, 0xa6, 0x65, 0xa6, 0xa6, 0x38, 0xc3, - 0xc5, 0x9d, 0x58, 0x4e, 0xdc, 0x93, 0x67, 0x08, 0x42, 0x36, 0x46, 0xa8, 0x9d, 0x91, 0x4b, 0x3c, - 0x39, 0x27, 0x33, 0x35, 0xaf, 0x24, 0x1e, 0x21, 0x1c, 0x5f, 0x90, 0x58, 0x92, 0x51, 0x2c, 0xc1, - 0x04, 0xb6, 0x42, 0x1d, 0x97, 0x15, 0x08, 0x83, 0x03, 0x40, 0xca, 0x9d, 0xd4, 0x40, 0xa6, 0x7f, - 0xba, 0x27, 0x2f, 0x57, 0x99, 0x98, 0x9b, 0x63, 0xa5, 0x84, 0xc3, 0x54, 0xa5, 0x20, 0x51, 0x88, - 0x0c, 0x9a, 0x76, 0xa1, 0x58, 0x2e, 0x89, 0xbc, 0xd4, 0x0a, 0x14, 0x0d, 0xc5, 0xa9, 0x85, 0xa5, - 0xa9, 0x79, 0xc9, 0xa9, 0x12, 0xcc, 0x0a, 0x8c, 0x1a, 0x2c, 0x4e, 0xca, 0x9f, 0xee, 0xc9, 0xcb, - 0x43, 0x0c, 0xc7, 0xa5, 0x52, 0x29, 0x48, 0x0c, 0x24, 0x85, 0x30, 0x3b, 0x18, 0x2a, 0xe1, 0x14, - 0x7a, 0xe2, 0x91, 0x1c, 0xe3, 0x85, 0x47, 0x72, 0x8c, 0x0f, 0x1e, 0xc9, 0x31, 0x4e, 0x78, 0x2c, - 0xc7, 0x70, 0xe1, 0xb1, 0x1c, 0xc3, 0x8d, 0xc7, 0x72, 0x0c, 0x51, 0xd6, 0xe9, 0x99, 0x25, 0x19, - 0xa5, 0x49, 0x7a, 0xc9, 0xf9, 0xb9, 0xfa, 0xc9, 0xf9, 0xc5, 0xb9, 0xf9, 0xc5, 0x50, 0x4a, 0xb7, - 0x38, 0x25, 0x5b, 0xbf, 0x42, 0x1f, 0x1e, 0x63, 0x06, 0xc6, 0xba, 0x48, 0x91, 0x56, 0x52, 0x59, - 0x90, 0x5a, 0x9c, 0xc4, 0x06, 0x8e, 0x2d, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0b, 0xad, - 0x14, 0x09, 0x2c, 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 m.NextConnectionSequence != 0 { - i = encodeVarintGenesis(dAtA, i, uint64(m.NextConnectionSequence)) - i-- - dAtA[i] = 0x18 - } - if len(m.ClientConnectionPaths) > 0 { - for iNdEx := len(m.ClientConnectionPaths) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.ClientConnectionPaths[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintGenesis(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - } - } - if len(m.Connections) > 0 { - for iNdEx := len(m.Connections) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.Connections[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.Connections) > 0 { - for _, e := range m.Connections { - l = e.Size() - n += 1 + l + sovGenesis(uint64(l)) - } - } - if len(m.ClientConnectionPaths) > 0 { - for _, e := range m.ClientConnectionPaths { - l = e.Size() - n += 1 + l + sovGenesis(uint64(l)) - } - } - if m.NextConnectionSequence != 0 { - n += 1 + sovGenesis(uint64(m.NextConnectionSequence)) - } - 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 Connections", 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.Connections = append(m.Connections, IdentifiedConnection{}) - if err := m.Connections[len(m.Connections)-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 ClientConnectionPaths", 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.ClientConnectionPaths = append(m.ClientConnectionPaths, ConnectionPaths{}) - if err := m.ClientConnectionPaths[len(m.ClientConnectionPaths)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field NextConnectionSequence", wireType) - } - m.NextConnectionSequence = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenesis - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.NextConnectionSequence |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - 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/ibc/core/03-connection/types/genesis_test.go b/x/ibc/core/03-connection/types/genesis_test.go deleted file mode 100644 index 846837f9af70..000000000000 --- a/x/ibc/core/03-connection/types/genesis_test.go +++ /dev/null @@ -1,114 +0,0 @@ -package types_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" -) - -func TestValidateGenesis(t *testing.T) { - - testCases := []struct { - name string - genState types.GenesisState - expPass bool - }{ - { - name: "default", - genState: types.DefaultGenesisState(), - expPass: true, - }, - { - name: "valid genesis", - genState: types.NewGenesisState( - []types.IdentifiedConnection{ - types.NewIdentifiedConnection(connectionID, types.NewConnectionEnd(types.INIT, clientID, types.Counterparty{clientID2, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))}, []*types.Version{ibctesting.ConnectionVersion}, 500)), - }, - []types.ConnectionPaths{ - {clientID, []string{connectionID}}, - }, - 0, - ), - expPass: true, - }, - { - name: "invalid connection", - genState: types.NewGenesisState( - []types.IdentifiedConnection{ - types.NewIdentifiedConnection(connectionID, types.NewConnectionEnd(types.INIT, "(CLIENTIDONE)", types.Counterparty{clientID, connectionID, commitmenttypes.NewMerklePrefix([]byte("prefix"))}, []*types.Version{ibctesting.ConnectionVersion}, 500)), - }, - []types.ConnectionPaths{ - {clientID, []string{connectionID}}, - }, - 0, - ), - expPass: false, - }, - { - name: "invalid client id", - genState: types.NewGenesisState( - []types.IdentifiedConnection{ - types.NewIdentifiedConnection(connectionID, types.NewConnectionEnd(types.INIT, clientID, types.Counterparty{clientID2, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))}, []*types.Version{ibctesting.ConnectionVersion}, 500)), - }, - []types.ConnectionPaths{ - {"(CLIENTIDONE)", []string{connectionID}}, - }, - 0, - ), - expPass: false, - }, - { - name: "invalid path", - genState: types.NewGenesisState( - []types.IdentifiedConnection{ - types.NewIdentifiedConnection(connectionID, types.NewConnectionEnd(types.INIT, clientID, types.Counterparty{clientID2, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))}, []*types.Version{ibctesting.ConnectionVersion}, 500)), - }, - []types.ConnectionPaths{ - {clientID, []string{invalidConnectionID}}, - }, - 0, - ), - expPass: false, - }, - { - name: "invalid connection identifier", - genState: types.NewGenesisState( - []types.IdentifiedConnection{ - types.NewIdentifiedConnection("conn-0", types.NewConnectionEnd(types.INIT, clientID, types.Counterparty{clientID2, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))}, []*types.Version{ibctesting.ConnectionVersion}, 500)), - }, - []types.ConnectionPaths{ - {clientID, []string{connectionID}}, - }, - 0, - ), - expPass: false, - }, - { - name: "next connection sequence is not greater than maximum connection identifier sequence provided", - genState: types.NewGenesisState( - []types.IdentifiedConnection{ - types.NewIdentifiedConnection(types.FormatConnectionIdentifier(10), types.NewConnectionEnd(types.INIT, clientID, types.Counterparty{clientID2, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))}, []*types.Version{ibctesting.ConnectionVersion}, 500)), - }, - []types.ConnectionPaths{ - {clientID, []string{connectionID}}, - }, - 0, - ), - expPass: false, - }, - } - - for _, tc := range testCases { - tc := tc - err := tc.genState.Validate() - if tc.expPass { - require.NoError(t, err, tc.name) - } else { - require.Error(t, err, tc.name) - } - } -} diff --git a/x/ibc/core/03-connection/types/keys.go b/x/ibc/core/03-connection/types/keys.go deleted file mode 100644 index 65af565c2abb..000000000000 --- a/x/ibc/core/03-connection/types/keys.go +++ /dev/null @@ -1,61 +0,0 @@ -package types - -import ( - "fmt" - "regexp" - - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" -) - -const ( - // SubModuleName defines the IBC connection name - SubModuleName = "connection" - - // StoreKey is the store key string for IBC connections - StoreKey = SubModuleName - - // RouterKey is the message route for IBC connections - RouterKey = SubModuleName - - // QuerierRoute is the querier route for IBC connections - QuerierRoute = SubModuleName - - // KeyNextConnectionSequence is the key used to store the next connection sequence in - // the keeper. - KeyNextConnectionSequence = "nextConnectionSequence" - - // ConnectionPrefix is the prefix used when creating a connection identifier - ConnectionPrefix = "connection-" -) - -// FormatConnectionIdentifier returns the connection identifier with the sequence appended. -// This is a SDK specific format not enforced by IBC protocol. -func FormatConnectionIdentifier(sequence uint64) string { - return fmt.Sprintf("%s%d", ConnectionPrefix, sequence) -} - -// IsConnectionIDFormat checks if a connectionID is in the format required on the SDK for -// parsing connection identifiers. The connection identifier must be in the form: `connection-{N} -var IsConnectionIDFormat = regexp.MustCompile(`^connection-[0-9]{1,20}$`).MatchString - -// IsValidConnectionID checks if the connection identifier is valid and can be parsed to -// the connection identifier format. -func IsValidConnectionID(connectionID string) bool { - _, err := ParseConnectionSequence(connectionID) - return err == nil -} - -// ParseConnectionSequence parses the connection sequence from the connection identifier. -func ParseConnectionSequence(connectionID string) (uint64, error) { - if !IsConnectionIDFormat(connectionID) { - return 0, sdkerrors.Wrap(host.ErrInvalidID, "connection identifier is not in the format: `connection-{N}`") - } - - sequence, err := host.ParseIdentifier(connectionID, ConnectionPrefix) - if err != nil { - return 0, sdkerrors.Wrap(err, "invalid connection identifier") - } - - return sequence, nil -} diff --git a/x/ibc/core/03-connection/types/keys_test.go b/x/ibc/core/03-connection/types/keys_test.go deleted file mode 100644 index 6adb8090f896..000000000000 --- a/x/ibc/core/03-connection/types/keys_test.go +++ /dev/null @@ -1,49 +0,0 @@ -package types_test - -import ( - "math" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" -) - -// tests ParseConnectionSequence and IsValidConnectionID -func TestParseConnectionSequence(t *testing.T) { - testCases := []struct { - name string - connectionID string - expSeq uint64 - expPass bool - }{ - {"valid 0", "connection-0", 0, true}, - {"valid 1", "connection-1", 1, true}, - {"valid large sequence", types.FormatConnectionIdentifier(math.MaxUint64), math.MaxUint64, true}, - // one above uint64 max - {"invalid uint64", "connection-18446744073709551616", 0, false}, - // uint64 == 20 characters - {"invalid large sequence", "connection-2345682193567182931243", 0, false}, - {"capital prefix", "Connection-0", 0, false}, - {"double prefix", "connection-connection-0", 0, false}, - {"missing dash", "connection0", 0, false}, - {"blank id", " ", 0, false}, - {"empty id", "", 0, false}, - {"negative sequence", "connection--1", 0, false}, - } - - for _, tc := range testCases { - - seq, err := types.ParseConnectionSequence(tc.connectionID) - valid := types.IsValidConnectionID(tc.connectionID) - require.Equal(t, tc.expSeq, seq) - - if tc.expPass { - require.NoError(t, err, tc.name) - require.True(t, valid) - } else { - require.Error(t, err, tc.name) - require.False(t, valid) - } - } -} diff --git a/x/ibc/core/03-connection/types/msgs.go b/x/ibc/core/03-connection/types/msgs.go deleted file mode 100644 index 3ba1aed8e7e0..000000000000 --- a/x/ibc/core/03-connection/types/msgs.go +++ /dev/null @@ -1,354 +0,0 @@ -package types - -import ( - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -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. -//nolint:interfacer -func NewMsgConnectionOpenInit( - clientID, counterpartyClientID string, - counterpartyPrefix commitmenttypes.MerklePrefix, - version *Version, delayPeriod uint64, signer sdk.AccAddress, -) *MsgConnectionOpenInit { - // counterparty must have the same delay period - counterparty := NewCounterparty(counterpartyClientID, "", counterpartyPrefix) - return &MsgConnectionOpenInit{ - ClientId: clientID, - Counterparty: counterparty, - Version: version, - DelayPeriod: delayPeriod, - Signer: signer.String(), - } -} - -// Route implements sdk.Msg -func (msg MsgConnectionOpenInit) Route() string { - return host.RouterKey -} - -// Type implements sdk.Msg -func (msg MsgConnectionOpenInit) Type() string { - return "connection_open_init" -} - -// ValidateBasic implements sdk.Msg. -func (msg MsgConnectionOpenInit) ValidateBasic() error { - if err := host.ClientIdentifierValidator(msg.ClientId); err != nil { - return sdkerrors.Wrap(err, "invalid client ID") - } - if msg.Counterparty.ConnectionId != "" { - return sdkerrors.Wrap(ErrInvalidCounterparty, "counterparty connection identifier must be empty") - } - - // NOTE: Version can be nil on MsgConnectionOpenInit - if msg.Version != nil { - if err := ValidateVersion(msg.Version); err != nil { - return sdkerrors.Wrap(err, "basic validation of the provided version failed") - } - } - _, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err) - } - return msg.Counterparty.ValidateBasic() -} - -// GetSignBytes implements sdk.Msg. The function will panic since it is used -// for amino transaction verification which IBC does not support. -func (msg MsgConnectionOpenInit) GetSignBytes() []byte { - panic("IBC messages do not support amino") -} - -// GetSigners implements sdk.Msg -func (msg MsgConnectionOpenInit) GetSigners() []sdk.AccAddress { - accAddr, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - panic(err) - } - return []sdk.AccAddress{accAddr} -} - -// NewMsgConnectionOpenTry creates a new MsgConnectionOpenTry instance -//nolint:interfacer -func NewMsgConnectionOpenTry( - previousConnectionID, clientID, counterpartyConnectionID, - counterpartyClientID string, counterpartyClient exported.ClientState, - counterpartyPrefix commitmenttypes.MerklePrefix, - counterpartyVersions []*Version, delayPeriod uint64, - proofInit, proofClient, proofConsensus []byte, - proofHeight, consensusHeight clienttypes.Height, signer sdk.AccAddress, -) *MsgConnectionOpenTry { - counterparty := NewCounterparty(counterpartyClientID, counterpartyConnectionID, counterpartyPrefix) - csAny, _ := clienttypes.PackClientState(counterpartyClient) - return &MsgConnectionOpenTry{ - PreviousConnectionId: previousConnectionID, - ClientId: clientID, - ClientState: csAny, - Counterparty: counterparty, - CounterpartyVersions: counterpartyVersions, - DelayPeriod: delayPeriod, - ProofInit: proofInit, - ProofClient: proofClient, - ProofConsensus: proofConsensus, - ProofHeight: proofHeight, - ConsensusHeight: consensusHeight, - Signer: signer.String(), - } -} - -// Route implements sdk.Msg -func (msg MsgConnectionOpenTry) Route() string { - return host.RouterKey -} - -// Type implements sdk.Msg -func (msg MsgConnectionOpenTry) Type() string { - return "connection_open_try" -} - -// ValidateBasic implements sdk.Msg -func (msg MsgConnectionOpenTry) ValidateBasic() error { - // an empty connection identifier indicates that a connection identifier should be generated - if msg.PreviousConnectionId != "" { - if !IsValidConnectionID(msg.PreviousConnectionId) { - return sdkerrors.Wrap(ErrInvalidConnectionIdentifier, "invalid previous connection ID") - } - } - if err := host.ClientIdentifierValidator(msg.ClientId); err != nil { - return sdkerrors.Wrap(err, "invalid client ID") - } - // counterparty validate basic allows empty counterparty connection identifiers - if err := host.ConnectionIdentifierValidator(msg.Counterparty.ConnectionId); err != nil { - return sdkerrors.Wrap(err, "invalid counterparty connection ID") - } - if msg.ClientState == nil { - return sdkerrors.Wrap(clienttypes.ErrInvalidClient, "counterparty client is nil") - } - clientState, err := clienttypes.UnpackClientState(msg.ClientState) - if err != nil { - return sdkerrors.Wrapf(clienttypes.ErrInvalidClient, "unpack err: %v", err) - } - if err := clientState.Validate(); err != nil { - return sdkerrors.Wrap(err, "counterparty client is invalid") - } - if len(msg.CounterpartyVersions) == 0 { - return sdkerrors.Wrap(sdkerrors.ErrInvalidVersion, "empty counterparty versions") - } - for i, version := range msg.CounterpartyVersions { - if err := ValidateVersion(version); err != nil { - return sdkerrors.Wrapf(err, "basic validation failed on version with index %d", i) - } - } - if len(msg.ProofInit) == 0 { - return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "cannot submit an empty proof init") - } - if len(msg.ProofClient) == 0 { - return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "cannot submit empty proof client") - } - if len(msg.ProofConsensus) == 0 { - return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "cannot submit an empty proof of consensus state") - } - if msg.ProofHeight.IsZero() { - return sdkerrors.Wrap(sdkerrors.ErrInvalidHeight, "proof height must be non-zero") - } - if msg.ConsensusHeight.IsZero() { - return sdkerrors.Wrap(sdkerrors.ErrInvalidHeight, "consensus height must be non-zero") - } - _, err = sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err) - } - return msg.Counterparty.ValidateBasic() -} - -// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces -func (msg MsgConnectionOpenTry) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { - return unpacker.UnpackAny(msg.ClientState, new(exported.ClientState)) -} - -// GetSignBytes implements sdk.Msg. The function will panic since it is used -// for amino transaction verification which IBC does not support. -func (msg MsgConnectionOpenTry) GetSignBytes() []byte { - panic("IBC messages do not support amino") -} - -// GetSigners implements sdk.Msg -func (msg MsgConnectionOpenTry) GetSigners() []sdk.AccAddress { - accAddr, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - panic(err) - } - return []sdk.AccAddress{accAddr} -} - -// NewMsgConnectionOpenAck creates a new MsgConnectionOpenAck instance -//nolint:interfacer -func NewMsgConnectionOpenAck( - connectionID, counterpartyConnectionID string, counterpartyClient exported.ClientState, - proofTry, proofClient, proofConsensus []byte, - proofHeight, consensusHeight clienttypes.Height, - version *Version, - signer sdk.AccAddress, -) *MsgConnectionOpenAck { - csAny, _ := clienttypes.PackClientState(counterpartyClient) - return &MsgConnectionOpenAck{ - ConnectionId: connectionID, - CounterpartyConnectionId: counterpartyConnectionID, - ClientState: csAny, - ProofTry: proofTry, - ProofClient: proofClient, - ProofConsensus: proofConsensus, - ProofHeight: proofHeight, - ConsensusHeight: consensusHeight, - Version: version, - Signer: signer.String(), - } -} - -// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces -func (msg MsgConnectionOpenAck) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { - return unpacker.UnpackAny(msg.ClientState, new(exported.ClientState)) -} - -// Route implements sdk.Msg -func (msg MsgConnectionOpenAck) Route() string { - return host.RouterKey -} - -// Type implements sdk.Msg -func (msg MsgConnectionOpenAck) Type() string { - return "connection_open_ack" -} - -// ValidateBasic implements sdk.Msg -func (msg MsgConnectionOpenAck) ValidateBasic() error { - if !IsValidConnectionID(msg.ConnectionId) { - return ErrInvalidConnectionIdentifier - } - if err := host.ConnectionIdentifierValidator(msg.CounterpartyConnectionId); err != nil { - return sdkerrors.Wrap(err, "invalid counterparty connection ID") - } - if err := ValidateVersion(msg.Version); err != nil { - return err - } - if msg.ClientState == nil { - return sdkerrors.Wrap(clienttypes.ErrInvalidClient, "counterparty client is nil") - } - clientState, err := clienttypes.UnpackClientState(msg.ClientState) - if err != nil { - return sdkerrors.Wrapf(clienttypes.ErrInvalidClient, "unpack err: %v", err) - } - if err := clientState.Validate(); err != nil { - return sdkerrors.Wrap(err, "counterparty client is invalid") - } - if len(msg.ProofTry) == 0 { - return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "cannot submit an empty proof try") - } - if len(msg.ProofClient) == 0 { - return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "cannot submit empty proof client") - } - if len(msg.ProofConsensus) == 0 { - return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "cannot submit an empty proof of consensus state") - } - if msg.ProofHeight.IsZero() { - return sdkerrors.Wrap(sdkerrors.ErrInvalidHeight, "proof height must be non-zero") - } - if msg.ConsensusHeight.IsZero() { - return sdkerrors.Wrap(sdkerrors.ErrInvalidHeight, "consensus height must be non-zero") - } - _, err = sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err) - } - return nil -} - -// GetSignBytes implements sdk.Msg. The function will panic since it is used -// for amino transaction verification which IBC does not support. -func (msg MsgConnectionOpenAck) GetSignBytes() []byte { - panic("IBC messages do not support amino") -} - -// GetSigners implements sdk.Msg -func (msg MsgConnectionOpenAck) GetSigners() []sdk.AccAddress { - accAddr, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - panic(err) - } - return []sdk.AccAddress{accAddr} -} - -// NewMsgConnectionOpenConfirm creates a new MsgConnectionOpenConfirm instance -//nolint:interfacer -func NewMsgConnectionOpenConfirm( - connectionID string, proofAck []byte, proofHeight clienttypes.Height, - signer sdk.AccAddress, -) *MsgConnectionOpenConfirm { - return &MsgConnectionOpenConfirm{ - ConnectionId: connectionID, - ProofAck: proofAck, - ProofHeight: proofHeight, - Signer: signer.String(), - } -} - -// Route implements sdk.Msg -func (msg MsgConnectionOpenConfirm) Route() string { - return host.RouterKey -} - -// Type implements sdk.Msg -func (msg MsgConnectionOpenConfirm) Type() string { - return "connection_open_confirm" -} - -// ValidateBasic implements sdk.Msg -func (msg MsgConnectionOpenConfirm) ValidateBasic() error { - if !IsValidConnectionID(msg.ConnectionId) { - return ErrInvalidConnectionIdentifier - } - if len(msg.ProofAck) == 0 { - return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "cannot submit an empty proof ack") - } - if msg.ProofHeight.IsZero() { - return sdkerrors.Wrap(sdkerrors.ErrInvalidHeight, "proof height must be non-zero") - } - _, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err) - } - return nil -} - -// GetSignBytes implements sdk.Msg. The function will panic since it is used -// for amino transaction verification which IBC does not support. -func (msg MsgConnectionOpenConfirm) GetSignBytes() []byte { - panic("IBC messages do not support amino") -} - -// GetSigners implements sdk.Msg -func (msg MsgConnectionOpenConfirm) GetSigners() []sdk.AccAddress { - accAddr, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - panic(err) - } - return []sdk.AccAddress{accAddr} -} diff --git a/x/ibc/core/03-connection/types/msgs_test.go b/x/ibc/core/03-connection/types/msgs_test.go deleted file mode 100644 index 6aff3b0904b3..000000000000 --- a/x/ibc/core/03-connection/types/msgs_test.go +++ /dev/null @@ -1,243 +0,0 @@ -package types_test - -import ( - "fmt" - "testing" - "time" - - "github.com/stretchr/testify/suite" - - abci "github.com/tendermint/tendermint/abci/types" - dbm "github.com/tendermint/tm-db" - - "github.com/cosmos/cosmos-sdk/simapp" - "github.com/cosmos/cosmos-sdk/store/iavl" - "github.com/cosmos/cosmos-sdk/store/rootmulti" - storetypes "github.com/cosmos/cosmos-sdk/store/types" - sdk "github.com/cosmos/cosmos-sdk/types" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types" - ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" -) - -var ( - emptyPrefix = commitmenttypes.MerklePrefix{} - emptyProof = []byte{} -) - -type MsgTestSuite struct { - suite.Suite - - coordinator *ibctesting.Coordinator - - chainA *ibctesting.TestChain - chainB *ibctesting.TestChain - - proof []byte -} - -func (suite *MsgTestSuite) SetupTest() { - suite.coordinator = ibctesting.NewCoordinator(suite.T(), 2) - - suite.chainA = suite.coordinator.GetChain(ibctesting.GetChainID(0)) - suite.chainB = suite.coordinator.GetChain(ibctesting.GetChainID(1)) - - app := simapp.Setup(false) - db := dbm.NewMemDB() - store := rootmulti.NewStore(db) - storeKey := storetypes.NewKVStoreKey("iavlStoreKey") - - store.MountStoreWithDB(storeKey, storetypes.StoreTypeIAVL, nil) - store.LoadVersion(0) - iavlStore := store.GetCommitStore(storeKey).(*iavl.Store) - - iavlStore.Set([]byte("KEY"), []byte("VALUE")) - _ = store.Commit() - - res := store.Query(abci.RequestQuery{ - Path: fmt.Sprintf("/%s/key", storeKey.Name()), // required path to get key/value+proof - Data: []byte("KEY"), - Prove: true, - }) - - merkleProof, err := commitmenttypes.ConvertProofs(res.ProofOps) - suite.Require().NoError(err) - proof, err := app.AppCodec().MarshalBinaryBare(&merkleProof) - suite.Require().NoError(err) - - suite.proof = proof - -} - -func TestMsgTestSuite(t *testing.T) { - suite.Run(t, new(MsgTestSuite)) -} - -func (suite *MsgTestSuite) TestNewMsgConnectionOpenInit() { - prefix := commitmenttypes.NewMerklePrefix([]byte("storePrefixKey")) - signer, _ := sdk.AccAddressFromBech32("cosmos1ckgw5d7jfj7wwxjzs9fdrdev9vc8dzcw3n2lht") - // empty versions are considered valid, the default compatible versions - // will be used in protocol. - var version *types.Version - - var testCases = []struct { - name string - msg *types.MsgConnectionOpenInit - expPass bool - }{ - {"invalid client ID", types.NewMsgConnectionOpenInit("test/iris", "clienttotest", prefix, version, 500, signer), false}, - {"invalid counterparty client ID", types.NewMsgConnectionOpenInit("clienttotest", "(clienttotest)", prefix, version, 500, signer), false}, - {"invalid counterparty connection ID", &types.MsgConnectionOpenInit{connectionID, types.NewCounterparty("clienttotest", "connectiontotest", prefix), version, 500, signer.String()}, false}, - {"empty counterparty prefix", types.NewMsgConnectionOpenInit("clienttotest", "clienttotest", emptyPrefix, version, 500, signer), false}, - {"supplied version fails basic validation", types.NewMsgConnectionOpenInit("clienttotest", "clienttotest", prefix, &types.Version{}, 500, signer), false}, - {"empty singer", types.NewMsgConnectionOpenInit("clienttotest", "clienttotest", prefix, version, 500, nil), false}, - {"success", types.NewMsgConnectionOpenInit("clienttotest", "clienttotest", prefix, version, 500, signer), true}, - } - - for _, tc := range testCases { - err := tc.msg.ValidateBasic() - if tc.expPass { - suite.Require().NoError(err, tc.name) - } else { - suite.Require().Error(err, tc.name) - } - } -} - -func (suite *MsgTestSuite) TestNewMsgConnectionOpenTry() { - prefix := commitmenttypes.NewMerklePrefix([]byte("storePrefixKey")) - signer, _ := sdk.AccAddressFromBech32("cosmos1ckgw5d7jfj7wwxjzs9fdrdev9vc8dzcw3n2lht") - - clientState := ibctmtypes.NewClientState( - chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false, - ) - - // Pack consensus state into any to test unpacking error - consState := ibctmtypes.NewConsensusState( - time.Now(), commitmenttypes.NewMerkleRoot([]byte("root")), []byte("nextValsHash"), - ) - invalidAny := clienttypes.MustPackConsensusState(consState) - counterparty := types.NewCounterparty("connectiontotest", "clienttotest", prefix) - - // invalidClientState fails validateBasic - invalidClient := ibctmtypes.NewClientState( - chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clienttypes.ZeroHeight(), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false, - ) - - var testCases = []struct { - name string - msg *types.MsgConnectionOpenTry - expPass bool - }{ - {"invalid connection ID", types.NewMsgConnectionOpenTry("test/conn1", "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []*types.Version{ibctesting.ConnectionVersion}, 500, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), false}, - {"invalid connection ID", types.NewMsgConnectionOpenTry("(invalidconnection)", "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []*types.Version{ibctesting.ConnectionVersion}, 500, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), false}, - {"invalid client ID", types.NewMsgConnectionOpenTry(connectionID, "test/iris", "connectiontotest", "clienttotest", clientState, prefix, []*types.Version{ibctesting.ConnectionVersion}, 500, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), false}, - {"invalid counterparty connection ID", types.NewMsgConnectionOpenTry(connectionID, "clienttotesta", "ibc/test", "clienttotest", clientState, prefix, []*types.Version{ibctesting.ConnectionVersion}, 500, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), false}, - {"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}, - {"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}, - {"empty proofClient", types.NewMsgConnectionOpenTry(connectionID, "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []*types.Version{ibctesting.ConnectionVersion}, 500, suite.proof, emptyProof, suite.proof, clientHeight, clientHeight, signer), false}, - {"empty proofConsensus", types.NewMsgConnectionOpenTry(connectionID, "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []*types.Version{ibctesting.ConnectionVersion}, 500, suite.proof, suite.proof, emptyProof, clientHeight, clientHeight, signer), false}, - {"invalid proofHeight", types.NewMsgConnectionOpenTry(connectionID, "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []*types.Version{ibctesting.ConnectionVersion}, 500, suite.proof, suite.proof, suite.proof, clienttypes.ZeroHeight(), clientHeight, signer), false}, - {"invalid consensusHeight", types.NewMsgConnectionOpenTry(connectionID, "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []*types.Version{ibctesting.ConnectionVersion}, 500, suite.proof, suite.proof, suite.proof, clientHeight, clienttypes.ZeroHeight(), signer), false}, - {"empty singer", types.NewMsgConnectionOpenTry(connectionID, "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []*types.Version{ibctesting.ConnectionVersion}, 500, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, nil), false}, - {"success", types.NewMsgConnectionOpenTry(connectionID, "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []*types.Version{ibctesting.ConnectionVersion}, 500, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), true}, - {"invalid version", types.NewMsgConnectionOpenTry(connectionID, "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []*types.Version{{}}, 500, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), false}, - } - - for _, tc := range testCases { - err := tc.msg.ValidateBasic() - if tc.expPass { - suite.Require().NoError(err, tc.name) - } else { - suite.Require().Error(err, tc.name) - } - } -} - -func (suite *MsgTestSuite) TestNewMsgConnectionOpenAck() { - signer, _ := sdk.AccAddressFromBech32("cosmos1ckgw5d7jfj7wwxjzs9fdrdev9vc8dzcw3n2lht") - clientState := ibctmtypes.NewClientState( - chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false, - ) - - // Pack consensus state into any to test unpacking error - consState := ibctmtypes.NewConsensusState( - time.Now(), commitmenttypes.NewMerkleRoot([]byte("root")), []byte("nextValsHash"), - ) - invalidAny := clienttypes.MustPackConsensusState(consState) - - // invalidClientState fails validateBasic - invalidClient := ibctmtypes.NewClientState( - chainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clienttypes.ZeroHeight(), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false, - ) - connectionID := "connection-0" - - var testCases = []struct { - name string - msg *types.MsgConnectionOpenAck - expPass bool - }{ - {"invalid connection ID", types.NewMsgConnectionOpenAck("test/conn1", connectionID, clientState, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, ibctesting.ConnectionVersion, signer), false}, - {"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}, - {"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}, - {"invalid proofHeight", types.NewMsgConnectionOpenAck(connectionID, connectionID, clientState, suite.proof, suite.proof, suite.proof, clienttypes.ZeroHeight(), clientHeight, ibctesting.ConnectionVersion, signer), false}, - {"invalid consensusHeight", types.NewMsgConnectionOpenAck(connectionID, connectionID, clientState, suite.proof, suite.proof, suite.proof, clientHeight, clienttypes.ZeroHeight(), ibctesting.ConnectionVersion, signer), false}, - {"invalid version", types.NewMsgConnectionOpenAck(connectionID, connectionID, clientState, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, &types.Version{}, signer), false}, - {"empty signer", types.NewMsgConnectionOpenAck(connectionID, connectionID, clientState, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, ibctesting.ConnectionVersion, nil), false}, - {"success", types.NewMsgConnectionOpenAck(connectionID, connectionID, clientState, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, ibctesting.ConnectionVersion, signer), true}, - } - - for _, tc := range testCases { - err := tc.msg.ValidateBasic() - if tc.expPass { - suite.Require().NoError(err, tc.name) - } else { - suite.Require().Error(err, tc.name) - } - } -} - -func (suite *MsgTestSuite) TestNewMsgConnectionOpenConfirm() { - signer, _ := sdk.AccAddressFromBech32("cosmos1ckgw5d7jfj7wwxjzs9fdrdev9vc8dzcw3n2lht") - - testMsgs := []*types.MsgConnectionOpenConfirm{ - types.NewMsgConnectionOpenConfirm("test/conn1", suite.proof, clientHeight, signer), - types.NewMsgConnectionOpenConfirm(connectionID, emptyProof, clientHeight, signer), - types.NewMsgConnectionOpenConfirm(connectionID, suite.proof, clienttypes.ZeroHeight(), signer), - types.NewMsgConnectionOpenConfirm(connectionID, suite.proof, clientHeight, nil), - types.NewMsgConnectionOpenConfirm(connectionID, suite.proof, clientHeight, signer), - } - - var testCases = []struct { - msg *types.MsgConnectionOpenConfirm - expPass bool - errMsg string - }{ - {testMsgs[0], false, "invalid connection ID"}, - {testMsgs[1], false, "empty proofTry"}, - {testMsgs[2], false, "invalid proofHeight"}, - {testMsgs[3], false, "empty signer"}, - {testMsgs[4], true, "success"}, - } - - for i, tc := range testCases { - err := tc.msg.ValidateBasic() - if tc.expPass { - suite.Require().NoError(err, "Msg %d failed: %s", i, tc.errMsg) - } else { - suite.Require().Error(err, "Invalid Msg %d passed: %s", i, tc.errMsg) - } - } -} diff --git a/x/ibc/core/03-connection/types/query.go b/x/ibc/core/03-connection/types/query.go deleted file mode 100644 index 7661b38d9bba..000000000000 --- a/x/ibc/core/03-connection/types/query.go +++ /dev/null @@ -1,70 +0,0 @@ -package types - -import ( - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - "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, -) *QueryConnectionResponse { - return &QueryConnectionResponse{ - Connection: &connection, - Proof: proof, - ProofHeight: height, - } -} - -// NewQueryClientConnectionsResponse creates a new ConnectionPaths instance -func NewQueryClientConnectionsResponse( - connectionPaths []string, proof []byte, height clienttypes.Height, -) *QueryClientConnectionsResponse { - return &QueryClientConnectionsResponse{ - ConnectionPaths: connectionPaths, - Proof: proof, - ProofHeight: height, - } -} - -// NewQueryClientConnectionsRequest creates a new QueryClientConnectionsRequest instance -func NewQueryClientConnectionsRequest(clientID string) *QueryClientConnectionsRequest { - return &QueryClientConnectionsRequest{ - ClientId: clientID, - } -} - -// NewQueryConnectionClientStateResponse creates a newQueryConnectionClientStateResponse instance -func NewQueryConnectionClientStateResponse(identifiedClientState clienttypes.IdentifiedClientState, proof []byte, height clienttypes.Height) *QueryConnectionClientStateResponse { - return &QueryConnectionClientStateResponse{ - IdentifiedClientState: &identifiedClientState, - Proof: proof, - ProofHeight: height, - } -} - -// 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{ - ConsensusState: anyConsensusState, - ClientId: clientID, - Proof: proof, - 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/03-connection/types/query.pb.go b/x/ibc/core/03-connection/types/query.pb.go deleted file mode 100644 index 6796cdb1f8ad..000000000000 --- a/x/ibc/core/03-connection/types/query.pb.go +++ /dev/null @@ -1,2892 +0,0 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: ibc/core/connection/v1/query.proto - -package types - -import ( - context "context" - fmt "fmt" - types1 "github.com/cosmos/cosmos-sdk/codec/types" - query "github.com/cosmos/cosmos-sdk/types/query" - types "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - _ "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 - -// QueryConnectionRequest is the request type for the Query/Connection RPC -// method -type QueryConnectionRequest struct { - // connection unique identifier - ConnectionId string `protobuf:"bytes,1,opt,name=connection_id,json=connectionId,proto3" json:"connection_id,omitempty"` -} - -func (m *QueryConnectionRequest) Reset() { *m = QueryConnectionRequest{} } -func (m *QueryConnectionRequest) String() string { return proto.CompactTextString(m) } -func (*QueryConnectionRequest) ProtoMessage() {} -func (*QueryConnectionRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_cd8d529f8c7cd06b, []int{0} -} -func (m *QueryConnectionRequest) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryConnectionRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryConnectionRequest.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 *QueryConnectionRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryConnectionRequest.Merge(m, src) -} -func (m *QueryConnectionRequest) XXX_Size() int { - return m.Size() -} -func (m *QueryConnectionRequest) XXX_DiscardUnknown() { - xxx_messageInfo_QueryConnectionRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryConnectionRequest proto.InternalMessageInfo - -func (m *QueryConnectionRequest) GetConnectionId() string { - if m != nil { - return m.ConnectionId - } - return "" -} - -// QueryConnectionResponse is the response type for the Query/Connection RPC -// method. Besides the connection end, it includes a proof and the height from -// which the proof was retrieved. -type QueryConnectionResponse struct { - // connection associated with the request identifier - Connection *ConnectionEnd `protobuf:"bytes,1,opt,name=connection,proto3" json:"connection,omitempty"` - // merkle proof of existence - Proof []byte `protobuf:"bytes,2,opt,name=proof,proto3" json:"proof,omitempty"` - // height at which the proof was retrieved - ProofHeight types.Height `protobuf:"bytes,3,opt,name=proof_height,json=proofHeight,proto3" json:"proof_height"` -} - -func (m *QueryConnectionResponse) Reset() { *m = QueryConnectionResponse{} } -func (m *QueryConnectionResponse) String() string { return proto.CompactTextString(m) } -func (*QueryConnectionResponse) ProtoMessage() {} -func (*QueryConnectionResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_cd8d529f8c7cd06b, []int{1} -} -func (m *QueryConnectionResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryConnectionResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryConnectionResponse.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 *QueryConnectionResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryConnectionResponse.Merge(m, src) -} -func (m *QueryConnectionResponse) XXX_Size() int { - return m.Size() -} -func (m *QueryConnectionResponse) XXX_DiscardUnknown() { - xxx_messageInfo_QueryConnectionResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryConnectionResponse proto.InternalMessageInfo - -func (m *QueryConnectionResponse) GetConnection() *ConnectionEnd { - if m != nil { - return m.Connection - } - return nil -} - -func (m *QueryConnectionResponse) GetProof() []byte { - if m != nil { - return m.Proof - } - return nil -} - -func (m *QueryConnectionResponse) GetProofHeight() types.Height { - if m != nil { - return m.ProofHeight - } - return types.Height{} -} - -// QueryConnectionsRequest is the request type for the Query/Connections RPC -// method -type QueryConnectionsRequest struct { - Pagination *query.PageRequest `protobuf:"bytes,1,opt,name=pagination,proto3" json:"pagination,omitempty"` -} - -func (m *QueryConnectionsRequest) Reset() { *m = QueryConnectionsRequest{} } -func (m *QueryConnectionsRequest) String() string { return proto.CompactTextString(m) } -func (*QueryConnectionsRequest) ProtoMessage() {} -func (*QueryConnectionsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_cd8d529f8c7cd06b, []int{2} -} -func (m *QueryConnectionsRequest) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryConnectionsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryConnectionsRequest.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 *QueryConnectionsRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryConnectionsRequest.Merge(m, src) -} -func (m *QueryConnectionsRequest) XXX_Size() int { - return m.Size() -} -func (m *QueryConnectionsRequest) XXX_DiscardUnknown() { - xxx_messageInfo_QueryConnectionsRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryConnectionsRequest proto.InternalMessageInfo - -func (m *QueryConnectionsRequest) GetPagination() *query.PageRequest { - if m != nil { - return m.Pagination - } - return nil -} - -// QueryConnectionsResponse is the response type for the Query/Connections RPC -// method. -type QueryConnectionsResponse struct { - // list of stored connections of the chain. - Connections []*IdentifiedConnection `protobuf:"bytes,1,rep,name=connections,proto3" json:"connections,omitempty"` - // pagination response - Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` - // query block height - Height types.Height `protobuf:"bytes,3,opt,name=height,proto3" json:"height"` -} - -func (m *QueryConnectionsResponse) Reset() { *m = QueryConnectionsResponse{} } -func (m *QueryConnectionsResponse) String() string { return proto.CompactTextString(m) } -func (*QueryConnectionsResponse) ProtoMessage() {} -func (*QueryConnectionsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_cd8d529f8c7cd06b, []int{3} -} -func (m *QueryConnectionsResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryConnectionsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryConnectionsResponse.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 *QueryConnectionsResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryConnectionsResponse.Merge(m, src) -} -func (m *QueryConnectionsResponse) XXX_Size() int { - return m.Size() -} -func (m *QueryConnectionsResponse) XXX_DiscardUnknown() { - xxx_messageInfo_QueryConnectionsResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryConnectionsResponse proto.InternalMessageInfo - -func (m *QueryConnectionsResponse) GetConnections() []*IdentifiedConnection { - if m != nil { - return m.Connections - } - return nil -} - -func (m *QueryConnectionsResponse) GetPagination() *query.PageResponse { - if m != nil { - return m.Pagination - } - return nil -} - -func (m *QueryConnectionsResponse) GetHeight() types.Height { - if m != nil { - return m.Height - } - return types.Height{} -} - -// QueryClientConnectionsRequest is the request type for the -// Query/ClientConnections RPC method -type QueryClientConnectionsRequest struct { - // client identifier associated with a connection - ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"` -} - -func (m *QueryClientConnectionsRequest) Reset() { *m = QueryClientConnectionsRequest{} } -func (m *QueryClientConnectionsRequest) String() string { return proto.CompactTextString(m) } -func (*QueryClientConnectionsRequest) ProtoMessage() {} -func (*QueryClientConnectionsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_cd8d529f8c7cd06b, []int{4} -} -func (m *QueryClientConnectionsRequest) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryClientConnectionsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryClientConnectionsRequest.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 *QueryClientConnectionsRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryClientConnectionsRequest.Merge(m, src) -} -func (m *QueryClientConnectionsRequest) XXX_Size() int { - return m.Size() -} -func (m *QueryClientConnectionsRequest) XXX_DiscardUnknown() { - xxx_messageInfo_QueryClientConnectionsRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryClientConnectionsRequest proto.InternalMessageInfo - -func (m *QueryClientConnectionsRequest) GetClientId() string { - if m != nil { - return m.ClientId - } - return "" -} - -// QueryClientConnectionsResponse is the response type for the -// Query/ClientConnections RPC method -type QueryClientConnectionsResponse struct { - // slice of all the connection paths associated with a client. - ConnectionPaths []string `protobuf:"bytes,1,rep,name=connection_paths,json=connectionPaths,proto3" json:"connection_paths,omitempty"` - // merkle proof of existence - Proof []byte `protobuf:"bytes,2,opt,name=proof,proto3" json:"proof,omitempty"` - // height at which the proof was generated - ProofHeight types.Height `protobuf:"bytes,3,opt,name=proof_height,json=proofHeight,proto3" json:"proof_height"` -} - -func (m *QueryClientConnectionsResponse) Reset() { *m = QueryClientConnectionsResponse{} } -func (m *QueryClientConnectionsResponse) String() string { return proto.CompactTextString(m) } -func (*QueryClientConnectionsResponse) ProtoMessage() {} -func (*QueryClientConnectionsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_cd8d529f8c7cd06b, []int{5} -} -func (m *QueryClientConnectionsResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryClientConnectionsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryClientConnectionsResponse.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 *QueryClientConnectionsResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryClientConnectionsResponse.Merge(m, src) -} -func (m *QueryClientConnectionsResponse) XXX_Size() int { - return m.Size() -} -func (m *QueryClientConnectionsResponse) XXX_DiscardUnknown() { - xxx_messageInfo_QueryClientConnectionsResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryClientConnectionsResponse proto.InternalMessageInfo - -func (m *QueryClientConnectionsResponse) GetConnectionPaths() []string { - if m != nil { - return m.ConnectionPaths - } - return nil -} - -func (m *QueryClientConnectionsResponse) GetProof() []byte { - if m != nil { - return m.Proof - } - return nil -} - -func (m *QueryClientConnectionsResponse) GetProofHeight() types.Height { - if m != nil { - return m.ProofHeight - } - return types.Height{} -} - -// QueryConnectionClientStateRequest is the request type for the -// Query/ConnectionClientState RPC method -type QueryConnectionClientStateRequest struct { - // connection identifier - ConnectionId string `protobuf:"bytes,1,opt,name=connection_id,json=connectionId,proto3" json:"connection_id,omitempty" yaml:"connection_id"` -} - -func (m *QueryConnectionClientStateRequest) Reset() { *m = QueryConnectionClientStateRequest{} } -func (m *QueryConnectionClientStateRequest) String() string { return proto.CompactTextString(m) } -func (*QueryConnectionClientStateRequest) ProtoMessage() {} -func (*QueryConnectionClientStateRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_cd8d529f8c7cd06b, []int{6} -} -func (m *QueryConnectionClientStateRequest) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryConnectionClientStateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryConnectionClientStateRequest.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 *QueryConnectionClientStateRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryConnectionClientStateRequest.Merge(m, src) -} -func (m *QueryConnectionClientStateRequest) XXX_Size() int { - return m.Size() -} -func (m *QueryConnectionClientStateRequest) XXX_DiscardUnknown() { - xxx_messageInfo_QueryConnectionClientStateRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryConnectionClientStateRequest proto.InternalMessageInfo - -func (m *QueryConnectionClientStateRequest) GetConnectionId() string { - if m != nil { - return m.ConnectionId - } - return "" -} - -// QueryConnectionClientStateResponse is the response type for the -// Query/ConnectionClientState RPC method -type QueryConnectionClientStateResponse struct { - // client state associated with the channel - IdentifiedClientState *types.IdentifiedClientState `protobuf:"bytes,1,opt,name=identified_client_state,json=identifiedClientState,proto3" json:"identified_client_state,omitempty"` - // merkle proof of existence - Proof []byte `protobuf:"bytes,2,opt,name=proof,proto3" json:"proof,omitempty"` - // height at which the proof was retrieved - ProofHeight types.Height `protobuf:"bytes,3,opt,name=proof_height,json=proofHeight,proto3" json:"proof_height"` -} - -func (m *QueryConnectionClientStateResponse) Reset() { *m = QueryConnectionClientStateResponse{} } -func (m *QueryConnectionClientStateResponse) String() string { return proto.CompactTextString(m) } -func (*QueryConnectionClientStateResponse) ProtoMessage() {} -func (*QueryConnectionClientStateResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_cd8d529f8c7cd06b, []int{7} -} -func (m *QueryConnectionClientStateResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryConnectionClientStateResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryConnectionClientStateResponse.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 *QueryConnectionClientStateResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryConnectionClientStateResponse.Merge(m, src) -} -func (m *QueryConnectionClientStateResponse) XXX_Size() int { - return m.Size() -} -func (m *QueryConnectionClientStateResponse) XXX_DiscardUnknown() { - xxx_messageInfo_QueryConnectionClientStateResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryConnectionClientStateResponse proto.InternalMessageInfo - -func (m *QueryConnectionClientStateResponse) GetIdentifiedClientState() *types.IdentifiedClientState { - if m != nil { - return m.IdentifiedClientState - } - return nil -} - -func (m *QueryConnectionClientStateResponse) GetProof() []byte { - if m != nil { - return m.Proof - } - return nil -} - -func (m *QueryConnectionClientStateResponse) GetProofHeight() types.Height { - if m != nil { - return m.ProofHeight - } - return types.Height{} -} - -// QueryConnectionConsensusStateRequest is the request type for the -// Query/ConnectionConsensusState RPC method -type QueryConnectionConsensusStateRequest struct { - // connection identifier - ConnectionId string `protobuf:"bytes,1,opt,name=connection_id,json=connectionId,proto3" json:"connection_id,omitempty" yaml:"connection_id"` - RevisionNumber uint64 `protobuf:"varint,2,opt,name=revision_number,json=revisionNumber,proto3" json:"revision_number,omitempty"` - RevisionHeight uint64 `protobuf:"varint,3,opt,name=revision_height,json=revisionHeight,proto3" json:"revision_height,omitempty"` -} - -func (m *QueryConnectionConsensusStateRequest) Reset() { *m = QueryConnectionConsensusStateRequest{} } -func (m *QueryConnectionConsensusStateRequest) String() string { return proto.CompactTextString(m) } -func (*QueryConnectionConsensusStateRequest) ProtoMessage() {} -func (*QueryConnectionConsensusStateRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_cd8d529f8c7cd06b, []int{8} -} -func (m *QueryConnectionConsensusStateRequest) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryConnectionConsensusStateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryConnectionConsensusStateRequest.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 *QueryConnectionConsensusStateRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryConnectionConsensusStateRequest.Merge(m, src) -} -func (m *QueryConnectionConsensusStateRequest) XXX_Size() int { - return m.Size() -} -func (m *QueryConnectionConsensusStateRequest) XXX_DiscardUnknown() { - xxx_messageInfo_QueryConnectionConsensusStateRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryConnectionConsensusStateRequest proto.InternalMessageInfo - -func (m *QueryConnectionConsensusStateRequest) GetConnectionId() string { - if m != nil { - return m.ConnectionId - } - return "" -} - -func (m *QueryConnectionConsensusStateRequest) GetRevisionNumber() uint64 { - if m != nil { - return m.RevisionNumber - } - return 0 -} - -func (m *QueryConnectionConsensusStateRequest) GetRevisionHeight() uint64 { - if m != nil { - return m.RevisionHeight - } - return 0 -} - -// QueryConnectionConsensusStateResponse is the response type for the -// Query/ConnectionConsensusState RPC method -type QueryConnectionConsensusStateResponse struct { - // consensus state associated with the channel - ConsensusState *types1.Any `protobuf:"bytes,1,opt,name=consensus_state,json=consensusState,proto3" json:"consensus_state,omitempty"` - // client ID associated with the consensus state - ClientId string `protobuf:"bytes,2,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"` - // merkle proof of existence - Proof []byte `protobuf:"bytes,3,opt,name=proof,proto3" json:"proof,omitempty"` - // height at which the proof was retrieved - ProofHeight types.Height `protobuf:"bytes,4,opt,name=proof_height,json=proofHeight,proto3" json:"proof_height"` -} - -func (m *QueryConnectionConsensusStateResponse) Reset() { *m = QueryConnectionConsensusStateResponse{} } -func (m *QueryConnectionConsensusStateResponse) String() string { return proto.CompactTextString(m) } -func (*QueryConnectionConsensusStateResponse) ProtoMessage() {} -func (*QueryConnectionConsensusStateResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_cd8d529f8c7cd06b, []int{9} -} -func (m *QueryConnectionConsensusStateResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryConnectionConsensusStateResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryConnectionConsensusStateResponse.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 *QueryConnectionConsensusStateResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryConnectionConsensusStateResponse.Merge(m, src) -} -func (m *QueryConnectionConsensusStateResponse) XXX_Size() int { - return m.Size() -} -func (m *QueryConnectionConsensusStateResponse) XXX_DiscardUnknown() { - xxx_messageInfo_QueryConnectionConsensusStateResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryConnectionConsensusStateResponse proto.InternalMessageInfo - -func (m *QueryConnectionConsensusStateResponse) GetConsensusState() *types1.Any { - if m != nil { - return m.ConsensusState - } - return nil -} - -func (m *QueryConnectionConsensusStateResponse) GetClientId() string { - if m != nil { - return m.ClientId - } - return "" -} - -func (m *QueryConnectionConsensusStateResponse) GetProof() []byte { - if m != nil { - return m.Proof - } - return nil -} - -func (m *QueryConnectionConsensusStateResponse) GetProofHeight() types.Height { - if m != nil { - return m.ProofHeight - } - return types.Height{} -} - -func init() { - proto.RegisterType((*QueryConnectionRequest)(nil), "ibc.core.connection.v1.QueryConnectionRequest") - proto.RegisterType((*QueryConnectionResponse)(nil), "ibc.core.connection.v1.QueryConnectionResponse") - proto.RegisterType((*QueryConnectionsRequest)(nil), "ibc.core.connection.v1.QueryConnectionsRequest") - proto.RegisterType((*QueryConnectionsResponse)(nil), "ibc.core.connection.v1.QueryConnectionsResponse") - proto.RegisterType((*QueryClientConnectionsRequest)(nil), "ibc.core.connection.v1.QueryClientConnectionsRequest") - proto.RegisterType((*QueryClientConnectionsResponse)(nil), "ibc.core.connection.v1.QueryClientConnectionsResponse") - proto.RegisterType((*QueryConnectionClientStateRequest)(nil), "ibc.core.connection.v1.QueryConnectionClientStateRequest") - proto.RegisterType((*QueryConnectionClientStateResponse)(nil), "ibc.core.connection.v1.QueryConnectionClientStateResponse") - proto.RegisterType((*QueryConnectionConsensusStateRequest)(nil), "ibc.core.connection.v1.QueryConnectionConsensusStateRequest") - proto.RegisterType((*QueryConnectionConsensusStateResponse)(nil), "ibc.core.connection.v1.QueryConnectionConsensusStateResponse") -} - -func init() { - proto.RegisterFile("ibc/core/connection/v1/query.proto", fileDescriptor_cd8d529f8c7cd06b) -} - -var fileDescriptor_cd8d529f8c7cd06b = []byte{ - // 892 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0x41, 0x4f, 0x33, 0x45, - 0x18, 0xee, 0x14, 0xbe, 0x2f, 0x1f, 0x53, 0xfc, 0x3e, 0x9d, 0x14, 0xa8, 0xab, 0x16, 0x5c, 0x45, - 0x0a, 0x91, 0x19, 0x0a, 0xd1, 0x20, 0xd0, 0x44, 0x21, 0x88, 0x1c, 0x24, 0xb8, 0xc6, 0x8b, 0x17, - 0xb2, 0xbb, 0x1d, 0xb6, 0x1b, 0xe9, 0x4e, 0xe9, 0x6e, 0x1b, 0x1b, 0xac, 0x07, 0xe3, 0x0f, 0x30, - 0xf1, 0xee, 0xc1, 0x83, 0x89, 0x27, 0x8f, 0x1e, 0xfc, 0x01, 0x72, 0x24, 0xf1, 0xe2, 0x45, 0x62, - 0x8a, 0x57, 0x2f, 0xfe, 0x02, 0xb3, 0x33, 0x53, 0x76, 0xb6, 0xdd, 0x96, 0xd2, 0x7c, 0x9c, 0xba, - 0xfb, 0xce, 0xfb, 0xce, 0x3c, 0xcf, 0xf3, 0xbe, 0xf3, 0x6c, 0xa1, 0xee, 0x5a, 0x36, 0xb1, 0x59, - 0x9d, 0x12, 0x9b, 0x79, 0x1e, 0xb5, 0x03, 0x97, 0x79, 0xa4, 0x59, 0x24, 0xe7, 0x0d, 0x5a, 0x6f, - 0xe1, 0x5a, 0x9d, 0x05, 0x0c, 0xcd, 0xba, 0x96, 0x8d, 0xc3, 0x1c, 0x1c, 0xe5, 0xe0, 0x66, 0x51, - 0xcb, 0x3a, 0xcc, 0x61, 0x3c, 0x85, 0x84, 0x4f, 0x22, 0x5b, 0x5b, 0xb1, 0x99, 0x5f, 0x65, 0x3e, - 0xb1, 0x4c, 0x9f, 0x8a, 0x6d, 0x48, 0xb3, 0x68, 0xd1, 0xc0, 0x2c, 0x92, 0x9a, 0xe9, 0xb8, 0x9e, - 0xc9, 0xcb, 0x45, 0xee, 0x7c, 0x74, 0xfa, 0x99, 0x4b, 0xbd, 0x20, 0x3c, 0x59, 0x3c, 0xc9, 0x84, - 0xa5, 0x01, 0xf0, 0x14, 0x20, 0x22, 0xf1, 0x55, 0x87, 0x31, 0xe7, 0x8c, 0x12, 0xb3, 0xe6, 0x12, - 0xd3, 0xf3, 0x58, 0xc0, 0x8f, 0xf1, 0xe5, 0xea, 0xcb, 0x72, 0x95, 0xbf, 0x59, 0x8d, 0x53, 0x62, - 0x7a, 0x92, 0x9c, 0x5e, 0x82, 0xb3, 0x9f, 0x84, 0x20, 0xf7, 0x6e, 0x77, 0x34, 0xe8, 0x79, 0x83, - 0xfa, 0x01, 0x7a, 0x03, 0xbe, 0x10, 0x1d, 0x73, 0xe2, 0x96, 0x73, 0x60, 0x01, 0x14, 0xa6, 0x8c, - 0xe9, 0x28, 0x78, 0x58, 0xd6, 0x7f, 0x03, 0x70, 0xae, 0xaf, 0xde, 0xaf, 0x31, 0xcf, 0xa7, 0x68, - 0x1f, 0xc2, 0x28, 0x97, 0x57, 0x67, 0xd6, 0x17, 0x71, 0xb2, 0x98, 0x38, 0xaa, 0xdf, 0xf7, 0xca, - 0x86, 0x52, 0x88, 0xb2, 0xf0, 0x51, 0xad, 0xce, 0xd8, 0x69, 0x2e, 0xbd, 0x00, 0x0a, 0xd3, 0x86, - 0x78, 0x41, 0x7b, 0x70, 0x9a, 0x3f, 0x9c, 0x54, 0xa8, 0xeb, 0x54, 0x82, 0xdc, 0x04, 0xdf, 0x5e, - 0x53, 0xb6, 0x17, 0x3a, 0x36, 0x8b, 0xf8, 0x23, 0x9e, 0xb1, 0x3b, 0x79, 0x79, 0x3d, 0x9f, 0x32, - 0x32, 0xbc, 0x4a, 0x84, 0x74, 0xb3, 0x0f, 0xbc, 0xdf, 0x65, 0xff, 0x21, 0x84, 0x51, 0xbb, 0x24, - 0xf8, 0xb7, 0xb0, 0xe8, 0x2d, 0x0e, 0x7b, 0x8b, 0xc5, 0x88, 0xc8, 0xde, 0xe2, 0x63, 0xd3, 0xa1, - 0xb2, 0xd6, 0x50, 0x2a, 0xf5, 0x7f, 0x01, 0xcc, 0xf5, 0x9f, 0x21, 0x15, 0x3a, 0x82, 0x99, 0x88, - 0xa8, 0x9f, 0x03, 0x0b, 0x13, 0x85, 0xcc, 0xfa, 0xdb, 0x83, 0x24, 0x3a, 0x2c, 0x53, 0x2f, 0x70, - 0x4f, 0x5d, 0x5a, 0x56, 0xc4, 0x56, 0x37, 0x40, 0x07, 0x31, 0xd0, 0x69, 0x0e, 0x7a, 0xe9, 0x4e, - 0xd0, 0x02, 0x8c, 0x8a, 0x1a, 0x6d, 0xc2, 0xc7, 0xf7, 0xd4, 0x55, 0xe6, 0xeb, 0x3b, 0xf0, 0x35, - 0x41, 0x97, 0xa7, 0x25, 0x08, 0xfb, 0x0a, 0x9c, 0x12, 0x5b, 0x44, 0x23, 0xf5, 0x44, 0x04, 0x0e, - 0xcb, 0xfa, 0x4f, 0x00, 0xe6, 0x07, 0x95, 0x4b, 0xcd, 0x96, 0xe1, 0x8b, 0xca, 0x58, 0xd6, 0xcc, - 0xa0, 0x22, 0x84, 0x9b, 0x32, 0x9e, 0x45, 0xf1, 0xe3, 0x30, 0xfc, 0x90, 0x93, 0x63, 0xc1, 0xd7, - 0x7b, 0xba, 0x2a, 0x10, 0x7f, 0x1a, 0x98, 0x41, 0x77, 0x0e, 0x50, 0x29, 0xf1, 0x06, 0xed, 0xe6, - 0xfe, 0xbb, 0x9e, 0xcf, 0xb6, 0xcc, 0xea, 0xd9, 0x96, 0x1e, 0x5b, 0xd6, 0x7b, 0xee, 0x56, 0x07, - 0x40, 0x7d, 0xd8, 0x21, 0x52, 0x10, 0x13, 0xce, 0xb9, 0xb7, 0x93, 0x71, 0x22, 0xb5, 0xf5, 0xc3, - 0x14, 0x39, 0xb6, 0xcb, 0x49, 0xd4, 0x94, 0x61, 0x52, 0xf6, 0x9c, 0x71, 0x93, 0xc2, 0x0f, 0x29, - 0xe4, 0xaf, 0x00, 0xbe, 0xd9, 0x4b, 0x32, 0xa4, 0xe5, 0xf9, 0x0d, 0xff, 0x39, 0x8a, 0x89, 0x96, - 0xe0, 0xb3, 0x3a, 0x6d, 0xba, 0x7e, 0xb8, 0xea, 0x35, 0xaa, 0x16, 0xad, 0x73, 0x32, 0x93, 0xc6, - 0xd3, 0x6e, 0xf8, 0x88, 0x47, 0x63, 0x89, 0x0a, 0x31, 0x25, 0x51, 0x22, 0xbf, 0x06, 0x70, 0xf1, - 0x0e, 0xe4, 0xb2, 0x43, 0x25, 0x18, 0x8e, 0xa6, 0x58, 0x89, 0x75, 0x26, 0x8b, 0x85, 0x31, 0xe3, - 0xae, 0x31, 0xe3, 0x0f, 0xbc, 0x96, 0xf1, 0xd4, 0x8e, 0x6d, 0x13, 0xbf, 0x31, 0xe9, 0xf8, 0x8d, - 0x89, 0x5a, 0x33, 0x31, 0xac, 0x35, 0x93, 0x63, 0xb4, 0x66, 0xfd, 0xe7, 0x27, 0xf0, 0x11, 0x27, - 0x88, 0x7e, 0x01, 0x10, 0x46, 0x2c, 0x11, 0x1e, 0xe4, 0x50, 0xc9, 0x5f, 0x12, 0x8d, 0x8c, 0x9c, - 0x2f, 0x04, 0xd3, 0xdf, 0xff, 0xe6, 0x8f, 0x7f, 0xbe, 0x4f, 0x6f, 0xa1, 0x4d, 0x92, 0xfc, 0xfd, - 0x13, 0x9f, 0x53, 0xc5, 0xf9, 0xc8, 0x45, 0xac, 0xf9, 0x6d, 0xf4, 0x23, 0x80, 0x19, 0xc5, 0x3d, - 0xd0, 0xa8, 0x10, 0xba, 0x36, 0xa5, 0xad, 0x8d, 0x5e, 0x20, 0x41, 0xaf, 0x71, 0xd0, 0x2b, 0xa8, - 0x30, 0x2a, 0x68, 0xf4, 0x3b, 0x80, 0x2f, 0xf5, 0x19, 0x1d, 0x7a, 0x67, 0xf8, 0xc9, 0x03, 0x7c, - 0x55, 0x7b, 0xf7, 0xbe, 0x65, 0x12, 0xf6, 0x1e, 0x87, 0x5d, 0x42, 0xdb, 0xc3, 0x61, 0x8b, 0x01, - 0x8c, 0x4b, 0xde, 0x1d, 0xca, 0x36, 0xfa, 0x0b, 0xc0, 0x99, 0x44, 0x97, 0x42, 0xef, 0x8d, 0xa8, - 0x63, 0xbf, 0x7d, 0x6a, 0x5b, 0xe3, 0x94, 0x4a, 0x56, 0x1f, 0x73, 0x56, 0x07, 0x68, 0x7f, 0xdc, - 0x09, 0x22, 0xaa, 0x91, 0xa2, 0x1f, 0xd2, 0x30, 0x37, 0xe8, 0x9a, 0xa3, 0x9d, 0x51, 0x71, 0x26, - 0xf9, 0x9a, 0x56, 0x1a, 0xb3, 0x5a, 0x12, 0xfd, 0x16, 0x70, 0xa6, 0x5f, 0xa3, 0xaf, 0xc6, 0x67, - 0x1a, 0xf7, 0x26, 0xd2, 0xf5, 0x39, 0x72, 0xd1, 0xe3, 0x98, 0x6d, 0x22, 0xec, 0x44, 0x59, 0x10, - 0x81, 0xf6, 0xee, 0x67, 0x97, 0x9d, 0x3c, 0xb8, 0xea, 0xe4, 0xc1, 0xdf, 0x9d, 0x3c, 0xf8, 0xee, - 0x26, 0x9f, 0xba, 0xba, 0xc9, 0xa7, 0xfe, 0xbc, 0xc9, 0xa7, 0x3e, 0xdf, 0x76, 0xdc, 0xa0, 0xd2, - 0xb0, 0xb0, 0xcd, 0xaa, 0x44, 0xfe, 0x35, 0x16, 0x3f, 0xab, 0x7e, 0xf9, 0x0b, 0xf2, 0x65, 0x84, - 0x7a, 0x6d, 0x63, 0x55, 0x01, 0x1e, 0xb4, 0x6a, 0xd4, 0xb7, 0x1e, 0x73, 0x63, 0xdc, 0xf8, 0x3f, - 0x00, 0x00, 0xff, 0xff, 0x7c, 0x35, 0x91, 0xa4, 0xa7, 0x0b, 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 { - // Connection queries an IBC connection end. - Connection(ctx context.Context, in *QueryConnectionRequest, opts ...grpc.CallOption) (*QueryConnectionResponse, error) - // Connections queries all the IBC connections of a chain. - Connections(ctx context.Context, in *QueryConnectionsRequest, opts ...grpc.CallOption) (*QueryConnectionsResponse, error) - // ClientConnections queries the connection paths associated with a client - // state. - ClientConnections(ctx context.Context, in *QueryClientConnectionsRequest, opts ...grpc.CallOption) (*QueryClientConnectionsResponse, error) - // ConnectionClientState queries the client state associated with the - // connection. - ConnectionClientState(ctx context.Context, in *QueryConnectionClientStateRequest, opts ...grpc.CallOption) (*QueryConnectionClientStateResponse, error) - // ConnectionConsensusState queries the consensus state associated with the - // connection. - ConnectionConsensusState(ctx context.Context, in *QueryConnectionConsensusStateRequest, opts ...grpc.CallOption) (*QueryConnectionConsensusStateResponse, error) -} - -type queryClient struct { - cc grpc1.ClientConn -} - -func NewQueryClient(cc grpc1.ClientConn) QueryClient { - return &queryClient{cc} -} - -func (c *queryClient) Connection(ctx context.Context, in *QueryConnectionRequest, opts ...grpc.CallOption) (*QueryConnectionResponse, error) { - out := new(QueryConnectionResponse) - err := c.cc.Invoke(ctx, "/ibc.core.connection.v1.Query/Connection", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *queryClient) Connections(ctx context.Context, in *QueryConnectionsRequest, opts ...grpc.CallOption) (*QueryConnectionsResponse, error) { - out := new(QueryConnectionsResponse) - err := c.cc.Invoke(ctx, "/ibc.core.connection.v1.Query/Connections", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *queryClient) ClientConnections(ctx context.Context, in *QueryClientConnectionsRequest, opts ...grpc.CallOption) (*QueryClientConnectionsResponse, error) { - out := new(QueryClientConnectionsResponse) - err := c.cc.Invoke(ctx, "/ibc.core.connection.v1.Query/ClientConnections", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *queryClient) ConnectionClientState(ctx context.Context, in *QueryConnectionClientStateRequest, opts ...grpc.CallOption) (*QueryConnectionClientStateResponse, error) { - out := new(QueryConnectionClientStateResponse) - err := c.cc.Invoke(ctx, "/ibc.core.connection.v1.Query/ConnectionClientState", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *queryClient) ConnectionConsensusState(ctx context.Context, in *QueryConnectionConsensusStateRequest, opts ...grpc.CallOption) (*QueryConnectionConsensusStateResponse, error) { - out := new(QueryConnectionConsensusStateResponse) - err := c.cc.Invoke(ctx, "/ibc.core.connection.v1.Query/ConnectionConsensusState", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// QueryServer is the server API for Query service. -type QueryServer interface { - // Connection queries an IBC connection end. - Connection(context.Context, *QueryConnectionRequest) (*QueryConnectionResponse, error) - // Connections queries all the IBC connections of a chain. - Connections(context.Context, *QueryConnectionsRequest) (*QueryConnectionsResponse, error) - // ClientConnections queries the connection paths associated with a client - // state. - ClientConnections(context.Context, *QueryClientConnectionsRequest) (*QueryClientConnectionsResponse, error) - // ConnectionClientState queries the client state associated with the - // connection. - ConnectionClientState(context.Context, *QueryConnectionClientStateRequest) (*QueryConnectionClientStateResponse, error) - // ConnectionConsensusState queries the consensus state associated with the - // connection. - ConnectionConsensusState(context.Context, *QueryConnectionConsensusStateRequest) (*QueryConnectionConsensusStateResponse, error) -} - -// UnimplementedQueryServer can be embedded to have forward compatible implementations. -type UnimplementedQueryServer struct { -} - -func (*UnimplementedQueryServer) Connection(ctx context.Context, req *QueryConnectionRequest) (*QueryConnectionResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method Connection not implemented") -} -func (*UnimplementedQueryServer) Connections(ctx context.Context, req *QueryConnectionsRequest) (*QueryConnectionsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method Connections not implemented") -} -func (*UnimplementedQueryServer) ClientConnections(ctx context.Context, req *QueryClientConnectionsRequest) (*QueryClientConnectionsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ClientConnections not implemented") -} -func (*UnimplementedQueryServer) ConnectionClientState(ctx context.Context, req *QueryConnectionClientStateRequest) (*QueryConnectionClientStateResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ConnectionClientState not implemented") -} -func (*UnimplementedQueryServer) ConnectionConsensusState(ctx context.Context, req *QueryConnectionConsensusStateRequest) (*QueryConnectionConsensusStateResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ConnectionConsensusState not implemented") -} - -func RegisterQueryServer(s grpc1.Server, srv QueryServer) { - s.RegisterService(&_Query_serviceDesc, srv) -} - -func _Query_Connection_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryConnectionRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(QueryServer).Connection(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.connection.v1.Query/Connection", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).Connection(ctx, req.(*QueryConnectionRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Query_Connections_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryConnectionsRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(QueryServer).Connections(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.connection.v1.Query/Connections", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).Connections(ctx, req.(*QueryConnectionsRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Query_ClientConnections_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryClientConnectionsRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(QueryServer).ClientConnections(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.connection.v1.Query/ClientConnections", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).ClientConnections(ctx, req.(*QueryClientConnectionsRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Query_ConnectionClientState_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryConnectionClientStateRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(QueryServer).ConnectionClientState(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.connection.v1.Query/ConnectionClientState", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).ConnectionClientState(ctx, req.(*QueryConnectionClientStateRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Query_ConnectionConsensusState_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryConnectionConsensusStateRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(QueryServer).ConnectionConsensusState(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.connection.v1.Query/ConnectionConsensusState", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).ConnectionConsensusState(ctx, req.(*QueryConnectionConsensusStateRequest)) - } - return interceptor(ctx, in, info, handler) -} - -var _Query_serviceDesc = grpc.ServiceDesc{ - ServiceName: "ibc.core.connection.v1.Query", - HandlerType: (*QueryServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "Connection", - Handler: _Query_Connection_Handler, - }, - { - MethodName: "Connections", - Handler: _Query_Connections_Handler, - }, - { - MethodName: "ClientConnections", - Handler: _Query_ClientConnections_Handler, - }, - { - MethodName: "ConnectionClientState", - Handler: _Query_ConnectionClientState_Handler, - }, - { - MethodName: "ConnectionConsensusState", - Handler: _Query_ConnectionConsensusState_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "ibc/core/connection/v1/query.proto", -} - -func (m *QueryConnectionRequest) 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 *QueryConnectionRequest) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryConnectionRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.ConnectionId) > 0 { - i -= len(m.ConnectionId) - copy(dAtA[i:], m.ConnectionId) - i = encodeVarintQuery(dAtA, i, uint64(len(m.ConnectionId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *QueryConnectionResponse) 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 *QueryConnectionResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryConnectionResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - { - size, err := m.ProofHeight.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - if len(m.Proof) > 0 { - i -= len(m.Proof) - copy(dAtA[i:], m.Proof) - i = encodeVarintQuery(dAtA, i, uint64(len(m.Proof))) - i-- - dAtA[i] = 0x12 - } - if m.Connection != nil { - { - size, err := m.Connection.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 *QueryConnectionsRequest) 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 *QueryConnectionsRequest) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryConnectionsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.Pagination != nil { - { - size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *QueryConnectionsResponse) 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 *QueryConnectionsResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryConnectionsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - { - size, err := m.Height.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - 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.Connections) > 0 { - for iNdEx := len(m.Connections) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.Connections[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 *QueryClientConnectionsRequest) 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 *QueryClientConnectionsRequest) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryClientConnectionsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.ClientId) > 0 { - i -= len(m.ClientId) - copy(dAtA[i:], m.ClientId) - i = encodeVarintQuery(dAtA, i, uint64(len(m.ClientId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *QueryClientConnectionsResponse) 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 *QueryClientConnectionsResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryClientConnectionsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - { - size, err := m.ProofHeight.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - if len(m.Proof) > 0 { - i -= len(m.Proof) - copy(dAtA[i:], m.Proof) - i = encodeVarintQuery(dAtA, i, uint64(len(m.Proof))) - i-- - dAtA[i] = 0x12 - } - if len(m.ConnectionPaths) > 0 { - for iNdEx := len(m.ConnectionPaths) - 1; iNdEx >= 0; iNdEx-- { - i -= len(m.ConnectionPaths[iNdEx]) - copy(dAtA[i:], m.ConnectionPaths[iNdEx]) - i = encodeVarintQuery(dAtA, i, uint64(len(m.ConnectionPaths[iNdEx]))) - i-- - dAtA[i] = 0xa - } - } - return len(dAtA) - i, nil -} - -func (m *QueryConnectionClientStateRequest) 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 *QueryConnectionClientStateRequest) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryConnectionClientStateRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.ConnectionId) > 0 { - i -= len(m.ConnectionId) - copy(dAtA[i:], m.ConnectionId) - i = encodeVarintQuery(dAtA, i, uint64(len(m.ConnectionId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *QueryConnectionClientStateResponse) 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 *QueryConnectionClientStateResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryConnectionClientStateResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - { - size, err := m.ProofHeight.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - if len(m.Proof) > 0 { - i -= len(m.Proof) - copy(dAtA[i:], m.Proof) - i = encodeVarintQuery(dAtA, i, uint64(len(m.Proof))) - i-- - dAtA[i] = 0x12 - } - if m.IdentifiedClientState != nil { - { - size, err := m.IdentifiedClientState.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 *QueryConnectionConsensusStateRequest) 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 *QueryConnectionConsensusStateRequest) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryConnectionConsensusStateRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.RevisionHeight != 0 { - i = encodeVarintQuery(dAtA, i, uint64(m.RevisionHeight)) - i-- - dAtA[i] = 0x18 - } - if m.RevisionNumber != 0 { - i = encodeVarintQuery(dAtA, i, uint64(m.RevisionNumber)) - i-- - dAtA[i] = 0x10 - } - if len(m.ConnectionId) > 0 { - i -= len(m.ConnectionId) - copy(dAtA[i:], m.ConnectionId) - i = encodeVarintQuery(dAtA, i, uint64(len(m.ConnectionId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *QueryConnectionConsensusStateResponse) 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 *QueryConnectionConsensusStateResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryConnectionConsensusStateResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - { - size, err := m.ProofHeight.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x22 - if len(m.Proof) > 0 { - i -= len(m.Proof) - copy(dAtA[i:], m.Proof) - i = encodeVarintQuery(dAtA, i, uint64(len(m.Proof))) - i-- - dAtA[i] = 0x1a - } - if len(m.ClientId) > 0 { - i -= len(m.ClientId) - copy(dAtA[i:], m.ClientId) - i = encodeVarintQuery(dAtA, i, uint64(len(m.ClientId))) - i-- - dAtA[i] = 0x12 - } - if m.ConsensusState != nil { - { - size, err := m.ConsensusState.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 *QueryConnectionRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.ConnectionId) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - return n -} - -func (m *QueryConnectionResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.Connection != nil { - l = m.Connection.Size() - n += 1 + l + sovQuery(uint64(l)) - } - l = len(m.Proof) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - l = m.ProofHeight.Size() - n += 1 + l + sovQuery(uint64(l)) - return n -} - -func (m *QueryConnectionsRequest) 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 *QueryConnectionsResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if len(m.Connections) > 0 { - for _, e := range m.Connections { - l = e.Size() - n += 1 + l + sovQuery(uint64(l)) - } - } - if m.Pagination != nil { - l = m.Pagination.Size() - n += 1 + l + sovQuery(uint64(l)) - } - l = m.Height.Size() - n += 1 + l + sovQuery(uint64(l)) - return n -} - -func (m *QueryClientConnectionsRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.ClientId) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - return n -} - -func (m *QueryClientConnectionsResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if len(m.ConnectionPaths) > 0 { - for _, s := range m.ConnectionPaths { - l = len(s) - n += 1 + l + sovQuery(uint64(l)) - } - } - l = len(m.Proof) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - l = m.ProofHeight.Size() - n += 1 + l + sovQuery(uint64(l)) - return n -} - -func (m *QueryConnectionClientStateRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.ConnectionId) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - return n -} - -func (m *QueryConnectionClientStateResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.IdentifiedClientState != nil { - l = m.IdentifiedClientState.Size() - n += 1 + l + sovQuery(uint64(l)) - } - l = len(m.Proof) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - l = m.ProofHeight.Size() - n += 1 + l + sovQuery(uint64(l)) - return n -} - -func (m *QueryConnectionConsensusStateRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.ConnectionId) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - if m.RevisionNumber != 0 { - n += 1 + sovQuery(uint64(m.RevisionNumber)) - } - if m.RevisionHeight != 0 { - n += 1 + sovQuery(uint64(m.RevisionHeight)) - } - return n -} - -func (m *QueryConnectionConsensusStateResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.ConsensusState != nil { - l = m.ConsensusState.Size() - n += 1 + l + sovQuery(uint64(l)) - } - l = len(m.ClientId) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - l = len(m.Proof) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - l = m.ProofHeight.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 *QueryConnectionRequest) 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: QueryConnectionRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryConnectionRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ConnectionId", 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.ConnectionId = 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 *QueryConnectionResponse) 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: QueryConnectionResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryConnectionResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Connection", 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.Connection == nil { - m.Connection = &ConnectionEnd{} - } - if err := m.Connection.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Proof", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Proof = append(m.Proof[:0], dAtA[iNdEx:postIndex]...) - if m.Proof == nil { - m.Proof = []byte{} - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofHeight", 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 err := m.ProofHeight.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 *QueryConnectionsRequest) 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: QueryConnectionsRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryConnectionsRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.Pagination == nil { - m.Pagination = &query.PageRequest{} - } - if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipQuery(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *QueryConnectionsResponse) 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: QueryConnectionsResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryConnectionsResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Connections", 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.Connections = append(m.Connections, &IdentifiedConnection{}) - if err := m.Connections[len(m.Connections)-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 - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Height", 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 err := m.Height.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 *QueryClientConnectionsRequest) 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: QueryClientConnectionsRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryClientConnectionsRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ClientId", 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.ClientId = 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 *QueryClientConnectionsResponse) 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: QueryClientConnectionsResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryClientConnectionsResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ConnectionPaths", 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.ConnectionPaths = append(m.ConnectionPaths, string(dAtA[iNdEx:postIndex])) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Proof", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Proof = append(m.Proof[:0], dAtA[iNdEx:postIndex]...) - if m.Proof == nil { - m.Proof = []byte{} - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofHeight", 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 err := m.ProofHeight.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 *QueryConnectionClientStateRequest) 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: QueryConnectionClientStateRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryConnectionClientStateRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ConnectionId", 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.ConnectionId = 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 *QueryConnectionClientStateResponse) 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: QueryConnectionClientStateResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryConnectionClientStateResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field IdentifiedClientState", 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.IdentifiedClientState == nil { - m.IdentifiedClientState = &types.IdentifiedClientState{} - } - if err := m.IdentifiedClientState.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Proof", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Proof = append(m.Proof[:0], dAtA[iNdEx:postIndex]...) - if m.Proof == nil { - m.Proof = []byte{} - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofHeight", 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 err := m.ProofHeight.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 *QueryConnectionConsensusStateRequest) 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: QueryConnectionConsensusStateRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryConnectionConsensusStateRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ConnectionId", 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.ConnectionId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field RevisionNumber", wireType) - } - m.RevisionNumber = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.RevisionNumber |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field RevisionHeight", wireType) - } - m.RevisionHeight = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.RevisionHeight |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - default: - iNdEx = preIndex - skippy, err := skipQuery(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *QueryConnectionConsensusStateResponse) 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: QueryConnectionConsensusStateResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryConnectionConsensusStateResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ConsensusState", 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.ConsensusState == nil { - m.ConsensusState = &types1.Any{} - } - if err := m.ConsensusState.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ClientId", 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.ClientId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Proof", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Proof = append(m.Proof[:0], dAtA[iNdEx:postIndex]...) - if m.Proof == nil { - m.Proof = []byte{} - } - iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofHeight", 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 err := m.ProofHeight.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/ibc/core/03-connection/types/query.pb.gw.go b/x/ibc/core/03-connection/types/query.pb.gw.go deleted file mode 100644 index f9824f5bd2ae..000000000000 --- a/x/ibc/core/03-connection/types/query.pb.gw.go +++ /dev/null @@ -1,602 +0,0 @@ -// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. -// source: ibc/core/connection/v1/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_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 - 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 := client.Connection(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -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)} -) - -func request_Query_Connections_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, 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 := client.Connections(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -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 - - 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 := client.ClientConnections(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -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 - - 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 := client.ConnectionClientState(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -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 - - 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 := client.ConnectionConsensusState(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -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) { - 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_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.AnnotateContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Query_Connection_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_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.AnnotateContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Query_Connections_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_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.AnnotateContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Query_ClientConnections_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_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.AnnotateContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Query_ConnectionClientState_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_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.AnnotateContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Query_ConnectionConsensusState_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_ConnectionConsensusState_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - return nil -} - -var ( - pattern_Query_Connection_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"ibc", "core", "connection", "v1beta1", "connections", "connection_id"}, "", runtime.AssumeColonVerbOpt(false))) - - pattern_Query_Connections_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"ibc", "core", "connection", "v1beta1", "connections"}, "", runtime.AssumeColonVerbOpt(false))) - - pattern_Query_ClientConnections_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"ibc", "core", "connection", "v1beta1", "client_connections", "client_id"}, "", runtime.AssumeColonVerbOpt(false))) - - pattern_Query_ConnectionClientState_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6}, []string{"ibc", "core", "connection", "v1beta1", "connections", "connection_id", "client_state"}, "", runtime.AssumeColonVerbOpt(false))) - - pattern_Query_ConnectionConsensusState_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 2, 7, 1, 0, 4, 1, 5, 8, 2, 9, 1, 0, 4, 1, 5, 10}, []string{"ibc", "core", "connection", "v1beta1", "connections", "connection_id", "consensus_state", "revision", "revision_number", "height", "revision_height"}, "", runtime.AssumeColonVerbOpt(false))) -) - -var ( - forward_Query_Connection_0 = runtime.ForwardResponseMessage - - forward_Query_Connections_0 = runtime.ForwardResponseMessage - - forward_Query_ClientConnections_0 = runtime.ForwardResponseMessage - - forward_Query_ConnectionClientState_0 = runtime.ForwardResponseMessage - - forward_Query_ConnectionConsensusState_0 = runtime.ForwardResponseMessage -) diff --git a/x/ibc/core/03-connection/types/tx.pb.go b/x/ibc/core/03-connection/types/tx.pb.go deleted file mode 100644 index 00e4fd9d0bb7..000000000000 --- a/x/ibc/core/03-connection/types/tx.pb.go +++ /dev/null @@ -1,2778 +0,0 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: ibc/core/connection/v1/tx.proto - -package types - -import ( - context "context" - fmt "fmt" - types "github.com/cosmos/cosmos-sdk/codec/types" - types1 "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - _ "github.com/gogo/protobuf/gogoproto" - grpc1 "github.com/gogo/protobuf/grpc" - proto "github.com/gogo/protobuf/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 - -// MsgConnectionOpenInit defines the msg sent by an account on Chain A to -// initialize a connection with Chain B. -type MsgConnectionOpenInit struct { - ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty" yaml:"client_id"` - Counterparty Counterparty `protobuf:"bytes,2,opt,name=counterparty,proto3" json:"counterparty"` - Version *Version `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"` - DelayPeriod uint64 `protobuf:"varint,4,opt,name=delay_period,json=delayPeriod,proto3" json:"delay_period,omitempty" yaml:"delay_period"` - Signer string `protobuf:"bytes,5,opt,name=signer,proto3" json:"signer,omitempty"` -} - -func (m *MsgConnectionOpenInit) Reset() { *m = MsgConnectionOpenInit{} } -func (m *MsgConnectionOpenInit) String() string { return proto.CompactTextString(m) } -func (*MsgConnectionOpenInit) ProtoMessage() {} -func (*MsgConnectionOpenInit) Descriptor() ([]byte, []int) { - return fileDescriptor_5d00fde5fc97399e, []int{0} -} -func (m *MsgConnectionOpenInit) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgConnectionOpenInit) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgConnectionOpenInit.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 *MsgConnectionOpenInit) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgConnectionOpenInit.Merge(m, src) -} -func (m *MsgConnectionOpenInit) XXX_Size() int { - return m.Size() -} -func (m *MsgConnectionOpenInit) XXX_DiscardUnknown() { - xxx_messageInfo_MsgConnectionOpenInit.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgConnectionOpenInit proto.InternalMessageInfo - -// MsgConnectionOpenInitResponse defines the Msg/ConnectionOpenInit response type. -type MsgConnectionOpenInitResponse struct { -} - -func (m *MsgConnectionOpenInitResponse) Reset() { *m = MsgConnectionOpenInitResponse{} } -func (m *MsgConnectionOpenInitResponse) String() string { return proto.CompactTextString(m) } -func (*MsgConnectionOpenInitResponse) ProtoMessage() {} -func (*MsgConnectionOpenInitResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_5d00fde5fc97399e, []int{1} -} -func (m *MsgConnectionOpenInitResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgConnectionOpenInitResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgConnectionOpenInitResponse.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 *MsgConnectionOpenInitResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgConnectionOpenInitResponse.Merge(m, src) -} -func (m *MsgConnectionOpenInitResponse) XXX_Size() int { - return m.Size() -} -func (m *MsgConnectionOpenInitResponse) XXX_DiscardUnknown() { - xxx_messageInfo_MsgConnectionOpenInitResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgConnectionOpenInitResponse proto.InternalMessageInfo - -// MsgConnectionOpenTry defines a msg sent by a Relayer to try to open a -// connection on Chain B. -type MsgConnectionOpenTry struct { - ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty" yaml:"client_id"` - // in the case of crossing hello's, when both chains call OpenInit, we need the connection identifier - // of the previous connection in state INIT - PreviousConnectionId string `protobuf:"bytes,2,opt,name=previous_connection_id,json=previousConnectionId,proto3" json:"previous_connection_id,omitempty" yaml:"previous_connection_id"` - ClientState *types.Any `protobuf:"bytes,3,opt,name=client_state,json=clientState,proto3" json:"client_state,omitempty" yaml:"client_state"` - Counterparty Counterparty `protobuf:"bytes,4,opt,name=counterparty,proto3" json:"counterparty"` - DelayPeriod uint64 `protobuf:"varint,5,opt,name=delay_period,json=delayPeriod,proto3" json:"delay_period,omitempty" yaml:"delay_period"` - CounterpartyVersions []*Version `protobuf:"bytes,6,rep,name=counterparty_versions,json=counterpartyVersions,proto3" json:"counterparty_versions,omitempty" yaml:"counterparty_versions"` - ProofHeight types1.Height `protobuf:"bytes,7,opt,name=proof_height,json=proofHeight,proto3" json:"proof_height" yaml:"proof_height"` - // proof of the initialization the connection on Chain A: `UNITIALIZED -> - // INIT` - ProofInit []byte `protobuf:"bytes,8,opt,name=proof_init,json=proofInit,proto3" json:"proof_init,omitempty" yaml:"proof_init"` - // proof of client state included in message - ProofClient []byte `protobuf:"bytes,9,opt,name=proof_client,json=proofClient,proto3" json:"proof_client,omitempty" yaml:"proof_client"` - // proof of client consensus state - ProofConsensus []byte `protobuf:"bytes,10,opt,name=proof_consensus,json=proofConsensus,proto3" json:"proof_consensus,omitempty" yaml:"proof_consensus"` - ConsensusHeight types1.Height `protobuf:"bytes,11,opt,name=consensus_height,json=consensusHeight,proto3" json:"consensus_height" yaml:"consensus_height"` - Signer string `protobuf:"bytes,12,opt,name=signer,proto3" json:"signer,omitempty"` -} - -func (m *MsgConnectionOpenTry) Reset() { *m = MsgConnectionOpenTry{} } -func (m *MsgConnectionOpenTry) String() string { return proto.CompactTextString(m) } -func (*MsgConnectionOpenTry) ProtoMessage() {} -func (*MsgConnectionOpenTry) Descriptor() ([]byte, []int) { - return fileDescriptor_5d00fde5fc97399e, []int{2} -} -func (m *MsgConnectionOpenTry) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgConnectionOpenTry) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgConnectionOpenTry.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 *MsgConnectionOpenTry) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgConnectionOpenTry.Merge(m, src) -} -func (m *MsgConnectionOpenTry) XXX_Size() int { - return m.Size() -} -func (m *MsgConnectionOpenTry) XXX_DiscardUnknown() { - xxx_messageInfo_MsgConnectionOpenTry.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgConnectionOpenTry proto.InternalMessageInfo - -// MsgConnectionOpenTryResponse defines the Msg/ConnectionOpenTry response type. -type MsgConnectionOpenTryResponse struct { -} - -func (m *MsgConnectionOpenTryResponse) Reset() { *m = MsgConnectionOpenTryResponse{} } -func (m *MsgConnectionOpenTryResponse) String() string { return proto.CompactTextString(m) } -func (*MsgConnectionOpenTryResponse) ProtoMessage() {} -func (*MsgConnectionOpenTryResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_5d00fde5fc97399e, []int{3} -} -func (m *MsgConnectionOpenTryResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgConnectionOpenTryResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgConnectionOpenTryResponse.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 *MsgConnectionOpenTryResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgConnectionOpenTryResponse.Merge(m, src) -} -func (m *MsgConnectionOpenTryResponse) XXX_Size() int { - return m.Size() -} -func (m *MsgConnectionOpenTryResponse) XXX_DiscardUnknown() { - xxx_messageInfo_MsgConnectionOpenTryResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgConnectionOpenTryResponse proto.InternalMessageInfo - -// MsgConnectionOpenAck defines a msg sent by a Relayer to Chain A to -// acknowledge the change of connection state to TRYOPEN on Chain B. -type MsgConnectionOpenAck struct { - ConnectionId string `protobuf:"bytes,1,opt,name=connection_id,json=connectionId,proto3" json:"connection_id,omitempty" yaml:"connection_id"` - CounterpartyConnectionId string `protobuf:"bytes,2,opt,name=counterparty_connection_id,json=counterpartyConnectionId,proto3" json:"counterparty_connection_id,omitempty" yaml:"counterparty_connection_id"` - Version *Version `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"` - ClientState *types.Any `protobuf:"bytes,4,opt,name=client_state,json=clientState,proto3" json:"client_state,omitempty" yaml:"client_state"` - ProofHeight types1.Height `protobuf:"bytes,5,opt,name=proof_height,json=proofHeight,proto3" json:"proof_height" yaml:"proof_height"` - // proof of the initialization the connection on Chain B: `UNITIALIZED -> - // TRYOPEN` - ProofTry []byte `protobuf:"bytes,6,opt,name=proof_try,json=proofTry,proto3" json:"proof_try,omitempty" yaml:"proof_try"` - // proof of client state included in message - ProofClient []byte `protobuf:"bytes,7,opt,name=proof_client,json=proofClient,proto3" json:"proof_client,omitempty" yaml:"proof_client"` - // proof of client consensus state - ProofConsensus []byte `protobuf:"bytes,8,opt,name=proof_consensus,json=proofConsensus,proto3" json:"proof_consensus,omitempty" yaml:"proof_consensus"` - ConsensusHeight types1.Height `protobuf:"bytes,9,opt,name=consensus_height,json=consensusHeight,proto3" json:"consensus_height" yaml:"consensus_height"` - Signer string `protobuf:"bytes,10,opt,name=signer,proto3" json:"signer,omitempty"` -} - -func (m *MsgConnectionOpenAck) Reset() { *m = MsgConnectionOpenAck{} } -func (m *MsgConnectionOpenAck) String() string { return proto.CompactTextString(m) } -func (*MsgConnectionOpenAck) ProtoMessage() {} -func (*MsgConnectionOpenAck) Descriptor() ([]byte, []int) { - return fileDescriptor_5d00fde5fc97399e, []int{4} -} -func (m *MsgConnectionOpenAck) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgConnectionOpenAck) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgConnectionOpenAck.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 *MsgConnectionOpenAck) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgConnectionOpenAck.Merge(m, src) -} -func (m *MsgConnectionOpenAck) XXX_Size() int { - return m.Size() -} -func (m *MsgConnectionOpenAck) XXX_DiscardUnknown() { - xxx_messageInfo_MsgConnectionOpenAck.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgConnectionOpenAck proto.InternalMessageInfo - -// MsgConnectionOpenAckResponse defines the Msg/ConnectionOpenAck response type. -type MsgConnectionOpenAckResponse struct { -} - -func (m *MsgConnectionOpenAckResponse) Reset() { *m = MsgConnectionOpenAckResponse{} } -func (m *MsgConnectionOpenAckResponse) String() string { return proto.CompactTextString(m) } -func (*MsgConnectionOpenAckResponse) ProtoMessage() {} -func (*MsgConnectionOpenAckResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_5d00fde5fc97399e, []int{5} -} -func (m *MsgConnectionOpenAckResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgConnectionOpenAckResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgConnectionOpenAckResponse.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 *MsgConnectionOpenAckResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgConnectionOpenAckResponse.Merge(m, src) -} -func (m *MsgConnectionOpenAckResponse) XXX_Size() int { - return m.Size() -} -func (m *MsgConnectionOpenAckResponse) XXX_DiscardUnknown() { - xxx_messageInfo_MsgConnectionOpenAckResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgConnectionOpenAckResponse proto.InternalMessageInfo - -// MsgConnectionOpenConfirm defines a msg sent by a Relayer to Chain B to -// acknowledge the change of connection state to OPEN on Chain A. -type MsgConnectionOpenConfirm struct { - ConnectionId string `protobuf:"bytes,1,opt,name=connection_id,json=connectionId,proto3" json:"connection_id,omitempty" yaml:"connection_id"` - // proof for the change of the connection state on Chain A: `INIT -> OPEN` - ProofAck []byte `protobuf:"bytes,2,opt,name=proof_ack,json=proofAck,proto3" json:"proof_ack,omitempty" yaml:"proof_ack"` - ProofHeight types1.Height `protobuf:"bytes,3,opt,name=proof_height,json=proofHeight,proto3" json:"proof_height" yaml:"proof_height"` - Signer string `protobuf:"bytes,4,opt,name=signer,proto3" json:"signer,omitempty"` -} - -func (m *MsgConnectionOpenConfirm) Reset() { *m = MsgConnectionOpenConfirm{} } -func (m *MsgConnectionOpenConfirm) String() string { return proto.CompactTextString(m) } -func (*MsgConnectionOpenConfirm) ProtoMessage() {} -func (*MsgConnectionOpenConfirm) Descriptor() ([]byte, []int) { - return fileDescriptor_5d00fde5fc97399e, []int{6} -} -func (m *MsgConnectionOpenConfirm) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgConnectionOpenConfirm) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgConnectionOpenConfirm.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 *MsgConnectionOpenConfirm) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgConnectionOpenConfirm.Merge(m, src) -} -func (m *MsgConnectionOpenConfirm) XXX_Size() int { - return m.Size() -} -func (m *MsgConnectionOpenConfirm) XXX_DiscardUnknown() { - xxx_messageInfo_MsgConnectionOpenConfirm.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgConnectionOpenConfirm proto.InternalMessageInfo - -// MsgConnectionOpenConfirmResponse defines the Msg/ConnectionOpenConfirm response type. -type MsgConnectionOpenConfirmResponse struct { -} - -func (m *MsgConnectionOpenConfirmResponse) Reset() { *m = MsgConnectionOpenConfirmResponse{} } -func (m *MsgConnectionOpenConfirmResponse) String() string { return proto.CompactTextString(m) } -func (*MsgConnectionOpenConfirmResponse) ProtoMessage() {} -func (*MsgConnectionOpenConfirmResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_5d00fde5fc97399e, []int{7} -} -func (m *MsgConnectionOpenConfirmResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgConnectionOpenConfirmResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgConnectionOpenConfirmResponse.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 *MsgConnectionOpenConfirmResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgConnectionOpenConfirmResponse.Merge(m, src) -} -func (m *MsgConnectionOpenConfirmResponse) XXX_Size() int { - return m.Size() -} -func (m *MsgConnectionOpenConfirmResponse) XXX_DiscardUnknown() { - xxx_messageInfo_MsgConnectionOpenConfirmResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgConnectionOpenConfirmResponse proto.InternalMessageInfo - -func init() { - proto.RegisterType((*MsgConnectionOpenInit)(nil), "ibc.core.connection.v1.MsgConnectionOpenInit") - proto.RegisterType((*MsgConnectionOpenInitResponse)(nil), "ibc.core.connection.v1.MsgConnectionOpenInitResponse") - proto.RegisterType((*MsgConnectionOpenTry)(nil), "ibc.core.connection.v1.MsgConnectionOpenTry") - proto.RegisterType((*MsgConnectionOpenTryResponse)(nil), "ibc.core.connection.v1.MsgConnectionOpenTryResponse") - proto.RegisterType((*MsgConnectionOpenAck)(nil), "ibc.core.connection.v1.MsgConnectionOpenAck") - proto.RegisterType((*MsgConnectionOpenAckResponse)(nil), "ibc.core.connection.v1.MsgConnectionOpenAckResponse") - proto.RegisterType((*MsgConnectionOpenConfirm)(nil), "ibc.core.connection.v1.MsgConnectionOpenConfirm") - proto.RegisterType((*MsgConnectionOpenConfirmResponse)(nil), "ibc.core.connection.v1.MsgConnectionOpenConfirmResponse") -} - -func init() { proto.RegisterFile("ibc/core/connection/v1/tx.proto", fileDescriptor_5d00fde5fc97399e) } - -var fileDescriptor_5d00fde5fc97399e = []byte{ - // 921 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x56, 0x31, 0x93, 0xdb, 0x44, - 0x14, 0xb6, 0xce, 0xbe, 0x3b, 0x7b, 0x6d, 0x48, 0xb2, 0xf8, 0xee, 0x84, 0x48, 0x2c, 0x47, 0x03, - 0x83, 0x0b, 0x4e, 0x8a, 0x93, 0x30, 0x03, 0x66, 0x28, 0x6c, 0x37, 0x5c, 0x11, 0xc8, 0x88, 0x00, - 0x33, 0x69, 0x3c, 0xb6, 0xbc, 0xd6, 0x69, 0x6c, 0x6b, 0x35, 0x5a, 0xd9, 0x44, 0xb4, 0x34, 0x0c, - 0x15, 0x0d, 0x7d, 0xfe, 0x03, 0x7f, 0x22, 0xe5, 0x95, 0x54, 0x1a, 0xb8, 0x6b, 0xa8, 0xd5, 0xd1, - 0x31, 0xda, 0x95, 0xe4, 0xb5, 0x2d, 0x0f, 0x36, 0x3e, 0x2a, 0xe9, 0xed, 0xfb, 0xde, 0x7b, 0xbb, - 0xef, 0x7d, 0xdf, 0xce, 0x02, 0xd9, 0x1a, 0x18, 0x9a, 0x81, 0x5d, 0xa4, 0x19, 0xd8, 0xb6, 0x91, - 0xe1, 0x59, 0xd8, 0xd6, 0xe6, 0x4d, 0xcd, 0x7b, 0xa5, 0x3a, 0x2e, 0xf6, 0x30, 0x3c, 0xb5, 0x06, - 0x86, 0x1a, 0x01, 0xd4, 0x05, 0x40, 0x9d, 0x37, 0xa5, 0xaa, 0x89, 0x4d, 0x4c, 0x21, 0x5a, 0xf4, - 0xc7, 0xd0, 0xd2, 0xbb, 0x26, 0xc6, 0xe6, 0x04, 0x69, 0xd4, 0x1a, 0xcc, 0x46, 0x5a, 0xdf, 0xf6, - 0x63, 0x17, 0x57, 0x69, 0x62, 0x21, 0xdb, 0x8b, 0xaa, 0xb0, 0xbf, 0x18, 0xf0, 0xe1, 0x86, 0xad, - 0x70, 0x75, 0x29, 0x50, 0xf9, 0xed, 0x00, 0x9c, 0x3c, 0x23, 0x66, 0x37, 0x5d, 0xff, 0xca, 0x41, - 0xf6, 0x85, 0x6d, 0x79, 0xb0, 0x09, 0x4a, 0x2c, 0x65, 0xcf, 0x1a, 0x8a, 0x42, 0x5d, 0x68, 0x94, - 0x3a, 0xd5, 0x30, 0x90, 0xef, 0xfa, 0xfd, 0xe9, 0xa4, 0xa5, 0xa4, 0x2e, 0x45, 0x2f, 0xb2, 0xff, - 0x8b, 0x21, 0xfc, 0x12, 0x54, 0x0c, 0x3c, 0xb3, 0x3d, 0xe4, 0x3a, 0x7d, 0xd7, 0xf3, 0xc5, 0x83, - 0xba, 0xd0, 0x28, 0x3f, 0x7e, 0x5f, 0xcd, 0x3e, 0xb6, 0xda, 0xe5, 0xb0, 0x9d, 0xc2, 0x9b, 0x40, - 0xce, 0xe9, 0x4b, 0xf1, 0xf0, 0x53, 0x70, 0x3c, 0x47, 0x2e, 0xb1, 0xb0, 0x2d, 0xe6, 0x69, 0x2a, - 0x79, 0x53, 0xaa, 0x6f, 0x19, 0x4c, 0x4f, 0xf0, 0xb0, 0x05, 0x2a, 0x43, 0x34, 0xe9, 0xfb, 0x3d, - 0x07, 0xb9, 0x16, 0x1e, 0x8a, 0x85, 0xba, 0xd0, 0x28, 0x74, 0xce, 0xc2, 0x40, 0x7e, 0x87, 0x1d, - 0x80, 0xf7, 0x2a, 0x7a, 0x99, 0x9a, 0xcf, 0xa9, 0x05, 0x4f, 0xc1, 0x11, 0xb1, 0x4c, 0x1b, 0xb9, - 0xe2, 0x61, 0x74, 0x6c, 0x3d, 0xb6, 0x5a, 0xc5, 0x9f, 0x5e, 0xcb, 0xb9, 0xbf, 0x5e, 0xcb, 0x39, - 0x45, 0x06, 0x0f, 0x32, 0x9b, 0xa6, 0x23, 0xe2, 0x60, 0x9b, 0x20, 0xe5, 0xd7, 0x63, 0x50, 0x5d, - 0x43, 0xbc, 0x70, 0xfd, 0xff, 0xd2, 0xd5, 0xef, 0xc0, 0xa9, 0xe3, 0xa2, 0xb9, 0x85, 0x67, 0xa4, - 0xb7, 0x38, 0x75, 0x14, 0x7f, 0x40, 0xe3, 0x1f, 0x86, 0x81, 0xfc, 0x80, 0xc5, 0x67, 0xe3, 0x14, - 0xbd, 0x9a, 0x38, 0x16, 0x1b, 0xba, 0x18, 0xc2, 0xe7, 0xa0, 0x12, 0x17, 0x24, 0x5e, 0xdf, 0x43, - 0x71, 0x8f, 0xab, 0x2a, 0xe3, 0x9d, 0x9a, 0xf0, 0x4e, 0x6d, 0xdb, 0x3e, 0xdf, 0x39, 0x3e, 0x46, - 0xd1, 0xcb, 0xcc, 0xfc, 0x3a, 0xb2, 0xd6, 0x08, 0x50, 0xd8, 0x93, 0x00, 0xab, 0x53, 0x3c, 0xdc, - 0x61, 0x8a, 0x73, 0x70, 0xc2, 0xe7, 0xea, 0xc5, 0xcc, 0x20, 0xe2, 0x51, 0x3d, 0xbf, 0x05, 0x95, - 0x3a, 0xf5, 0x30, 0x90, 0xef, 0xc7, 0x27, 0xce, 0xca, 0xa3, 0xe8, 0x55, 0x7e, 0x3d, 0x0e, 0x23, - 0xf0, 0x25, 0xa8, 0x38, 0x2e, 0xc6, 0xa3, 0xde, 0x25, 0xb2, 0xcc, 0x4b, 0x4f, 0x3c, 0xa6, 0x3d, - 0x90, 0xb8, 0x72, 0x4c, 0xa8, 0xf3, 0xa6, 0xfa, 0x05, 0x45, 0x74, 0xde, 0x8b, 0x4e, 0xbe, 0x38, - 0x13, 0x1f, 0xad, 0xe8, 0x65, 0x6a, 0x32, 0x24, 0x7c, 0x0a, 0x00, 0xf3, 0x5a, 0xb6, 0xe5, 0x89, - 0xc5, 0xba, 0xd0, 0xa8, 0x74, 0x4e, 0xc2, 0x40, 0xbe, 0xc7, 0x47, 0x46, 0x3e, 0x45, 0x2f, 0x51, - 0x83, 0x2a, 0xb9, 0x95, 0xec, 0x88, 0x55, 0x16, 0x4b, 0x34, 0xee, 0x6c, 0xb5, 0x22, 0xf3, 0x26, - 0x15, 0xbb, 0xd4, 0x82, 0x5d, 0x70, 0x27, 0xf6, 0x46, 0xbc, 0xb6, 0xc9, 0x8c, 0x88, 0x80, 0x86, - 0x4b, 0x61, 0x20, 0x9f, 0x2e, 0x85, 0x27, 0x00, 0x45, 0x7f, 0x9b, 0x65, 0x48, 0x16, 0xe0, 0x08, - 0xdc, 0x4d, 0xbd, 0x49, 0x5b, 0xca, 0xff, 0xda, 0x16, 0x39, 0x6e, 0xcb, 0x59, 0x32, 0x84, 0xe5, - 0x0c, 0x8a, 0x7e, 0x27, 0x5d, 0x8a, 0xdb, 0xb3, 0x10, 0x6e, 0x65, 0x83, 0x70, 0x6b, 0xe0, 0x7e, - 0x96, 0x2c, 0x53, 0xdd, 0xfe, 0x79, 0x98, 0xa1, 0xdb, 0xb6, 0x31, 0x86, 0x9f, 0x83, 0xb7, 0x96, - 0xb5, 0xc7, 0xb4, 0x2b, 0x86, 0x81, 0x5c, 0x4d, 0xf7, 0xc7, 0x4b, 0xae, 0x62, 0xf0, 0x52, 0x33, - 0x80, 0xb4, 0x44, 0xa2, 0x2c, 0x1d, 0x7f, 0x10, 0x06, 0xf2, 0xc3, 0x0c, 0xc2, 0xad, 0x24, 0x16, - 0x79, 0xe7, 0x92, 0x9e, 0xf7, 0xb8, 0x2e, 0x57, 0xaf, 0x82, 0xc2, 0xde, 0x57, 0xc1, 0xaa, 0x0c, - 0x0e, 0x6f, 0x51, 0x06, 0x4d, 0xc0, 0xd8, 0xdd, 0xf3, 0x5c, 0x5f, 0x3c, 0xa2, 0x74, 0xe4, 0x2e, - 0xd1, 0xd4, 0xa5, 0xe8, 0x45, 0xfa, 0x1f, 0xdd, 0xbb, 0xab, 0x1a, 0x38, 0xde, 0x4f, 0x03, 0xc5, - 0x5b, 0xd1, 0x40, 0xe9, 0x7f, 0xd5, 0x00, 0xd8, 0x41, 0x03, 0x6d, 0x63, 0x9c, 0x6a, 0xe0, 0xe7, - 0x03, 0x20, 0xae, 0x01, 0xba, 0xd8, 0x1e, 0x59, 0xee, 0x74, 0x5f, 0x1d, 0xa4, 0x93, 0xeb, 0x1b, - 0x63, 0x4a, 0xfb, 0x8c, 0xc9, 0xf5, 0x8d, 0x71, 0x32, 0xb9, 0x48, 0x79, 0xab, 0x44, 0xca, 0xdf, - 0x22, 0x91, 0x16, 0xcd, 0x2a, 0x6c, 0x68, 0x96, 0x02, 0xea, 0x9b, 0x7a, 0x91, 0x34, 0xec, 0xf1, - 0xdf, 0x79, 0x90, 0x7f, 0x46, 0x4c, 0xf8, 0x03, 0x80, 0x19, 0xef, 0xa8, 0xf3, 0x4d, 0x22, 0xcc, - 0x7c, 0x41, 0x48, 0x1f, 0xef, 0x04, 0x4f, 0xf6, 0x00, 0xbf, 0x07, 0xf7, 0xd6, 0x1f, 0x1b, 0x1f, - 0x6d, 0x9d, 0xeb, 0x85, 0xeb, 0x4b, 0x4f, 0x77, 0x41, 0x6f, 0x2e, 0x1c, 0xcd, 0x6c, 0xfb, 0xc2, - 0x6d, 0x63, 0xbc, 0x43, 0x61, 0x8e, 0xa6, 0xf0, 0x47, 0x01, 0x9c, 0x64, 0x73, 0xf4, 0xd1, 0xd6, - 0xf9, 0xe2, 0x08, 0xe9, 0x93, 0x5d, 0x23, 0x92, 0x5d, 0x74, 0xbe, 0x79, 0x73, 0x5d, 0x13, 0xae, - 0xae, 0x6b, 0xc2, 0x1f, 0xd7, 0x35, 0xe1, 0x97, 0x9b, 0x5a, 0xee, 0xea, 0xa6, 0x96, 0xfb, 0xfd, - 0xa6, 0x96, 0x7b, 0xf9, 0x99, 0x69, 0x79, 0x97, 0xb3, 0x81, 0x6a, 0xe0, 0xa9, 0x66, 0x60, 0x32, - 0xc5, 0x24, 0xfe, 0x9c, 0x93, 0xe1, 0x58, 0x7b, 0xa5, 0xa5, 0x2f, 0xf4, 0x47, 0x4f, 0xce, 0xb9, - 0x47, 0xba, 0xe7, 0x3b, 0x88, 0x0c, 0x8e, 0xe8, 0x8d, 0xfb, 0xe4, 0x9f, 0x00, 0x00, 0x00, 0xff, - 0xff, 0xc4, 0x4d, 0xc5, 0x58, 0x53, 0x0c, 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 { - // ConnectionOpenInit defines a rpc handler method for MsgConnectionOpenInit. - ConnectionOpenInit(ctx context.Context, in *MsgConnectionOpenInit, opts ...grpc.CallOption) (*MsgConnectionOpenInitResponse, error) - // ConnectionOpenTry defines a rpc handler method for MsgConnectionOpenTry. - ConnectionOpenTry(ctx context.Context, in *MsgConnectionOpenTry, opts ...grpc.CallOption) (*MsgConnectionOpenTryResponse, error) - // ConnectionOpenAck defines a rpc handler method for MsgConnectionOpenAck. - ConnectionOpenAck(ctx context.Context, in *MsgConnectionOpenAck, opts ...grpc.CallOption) (*MsgConnectionOpenAckResponse, error) - // ConnectionOpenConfirm defines a rpc handler method for MsgConnectionOpenConfirm. - ConnectionOpenConfirm(ctx context.Context, in *MsgConnectionOpenConfirm, opts ...grpc.CallOption) (*MsgConnectionOpenConfirmResponse, error) -} - -type msgClient struct { - cc grpc1.ClientConn -} - -func NewMsgClient(cc grpc1.ClientConn) MsgClient { - return &msgClient{cc} -} - -func (c *msgClient) ConnectionOpenInit(ctx context.Context, in *MsgConnectionOpenInit, opts ...grpc.CallOption) (*MsgConnectionOpenInitResponse, error) { - out := new(MsgConnectionOpenInitResponse) - err := c.cc.Invoke(ctx, "/ibc.core.connection.v1.Msg/ConnectionOpenInit", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *msgClient) ConnectionOpenTry(ctx context.Context, in *MsgConnectionOpenTry, opts ...grpc.CallOption) (*MsgConnectionOpenTryResponse, error) { - out := new(MsgConnectionOpenTryResponse) - err := c.cc.Invoke(ctx, "/ibc.core.connection.v1.Msg/ConnectionOpenTry", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *msgClient) ConnectionOpenAck(ctx context.Context, in *MsgConnectionOpenAck, opts ...grpc.CallOption) (*MsgConnectionOpenAckResponse, error) { - out := new(MsgConnectionOpenAckResponse) - err := c.cc.Invoke(ctx, "/ibc.core.connection.v1.Msg/ConnectionOpenAck", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *msgClient) ConnectionOpenConfirm(ctx context.Context, in *MsgConnectionOpenConfirm, opts ...grpc.CallOption) (*MsgConnectionOpenConfirmResponse, error) { - out := new(MsgConnectionOpenConfirmResponse) - err := c.cc.Invoke(ctx, "/ibc.core.connection.v1.Msg/ConnectionOpenConfirm", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// MsgServer is the server API for Msg service. -type MsgServer interface { - // ConnectionOpenInit defines a rpc handler method for MsgConnectionOpenInit. - ConnectionOpenInit(context.Context, *MsgConnectionOpenInit) (*MsgConnectionOpenInitResponse, error) - // ConnectionOpenTry defines a rpc handler method for MsgConnectionOpenTry. - ConnectionOpenTry(context.Context, *MsgConnectionOpenTry) (*MsgConnectionOpenTryResponse, error) - // ConnectionOpenAck defines a rpc handler method for MsgConnectionOpenAck. - ConnectionOpenAck(context.Context, *MsgConnectionOpenAck) (*MsgConnectionOpenAckResponse, error) - // ConnectionOpenConfirm defines a rpc handler method for MsgConnectionOpenConfirm. - ConnectionOpenConfirm(context.Context, *MsgConnectionOpenConfirm) (*MsgConnectionOpenConfirmResponse, error) -} - -// UnimplementedMsgServer can be embedded to have forward compatible implementations. -type UnimplementedMsgServer struct { -} - -func (*UnimplementedMsgServer) ConnectionOpenInit(ctx context.Context, req *MsgConnectionOpenInit) (*MsgConnectionOpenInitResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ConnectionOpenInit not implemented") -} -func (*UnimplementedMsgServer) ConnectionOpenTry(ctx context.Context, req *MsgConnectionOpenTry) (*MsgConnectionOpenTryResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ConnectionOpenTry not implemented") -} -func (*UnimplementedMsgServer) ConnectionOpenAck(ctx context.Context, req *MsgConnectionOpenAck) (*MsgConnectionOpenAckResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ConnectionOpenAck not implemented") -} -func (*UnimplementedMsgServer) ConnectionOpenConfirm(ctx context.Context, req *MsgConnectionOpenConfirm) (*MsgConnectionOpenConfirmResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ConnectionOpenConfirm not implemented") -} - -func RegisterMsgServer(s grpc1.Server, srv MsgServer) { - s.RegisterService(&_Msg_serviceDesc, srv) -} - -func _Msg_ConnectionOpenInit_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgConnectionOpenInit) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MsgServer).ConnectionOpenInit(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.connection.v1.Msg/ConnectionOpenInit", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).ConnectionOpenInit(ctx, req.(*MsgConnectionOpenInit)) - } - return interceptor(ctx, in, info, handler) -} - -func _Msg_ConnectionOpenTry_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgConnectionOpenTry) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MsgServer).ConnectionOpenTry(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.connection.v1.Msg/ConnectionOpenTry", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).ConnectionOpenTry(ctx, req.(*MsgConnectionOpenTry)) - } - return interceptor(ctx, in, info, handler) -} - -func _Msg_ConnectionOpenAck_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgConnectionOpenAck) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MsgServer).ConnectionOpenAck(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.connection.v1.Msg/ConnectionOpenAck", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).ConnectionOpenAck(ctx, req.(*MsgConnectionOpenAck)) - } - return interceptor(ctx, in, info, handler) -} - -func _Msg_ConnectionOpenConfirm_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgConnectionOpenConfirm) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MsgServer).ConnectionOpenConfirm(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.connection.v1.Msg/ConnectionOpenConfirm", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).ConnectionOpenConfirm(ctx, req.(*MsgConnectionOpenConfirm)) - } - return interceptor(ctx, in, info, handler) -} - -var _Msg_serviceDesc = grpc.ServiceDesc{ - ServiceName: "ibc.core.connection.v1.Msg", - HandlerType: (*MsgServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "ConnectionOpenInit", - Handler: _Msg_ConnectionOpenInit_Handler, - }, - { - MethodName: "ConnectionOpenTry", - Handler: _Msg_ConnectionOpenTry_Handler, - }, - { - MethodName: "ConnectionOpenAck", - Handler: _Msg_ConnectionOpenAck_Handler, - }, - { - MethodName: "ConnectionOpenConfirm", - Handler: _Msg_ConnectionOpenConfirm_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "ibc/core/connection/v1/tx.proto", -} - -func (m *MsgConnectionOpenInit) 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 *MsgConnectionOpenInit) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgConnectionOpenInit) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Signer) > 0 { - i -= len(m.Signer) - copy(dAtA[i:], m.Signer) - i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) - i-- - dAtA[i] = 0x2a - } - if m.DelayPeriod != 0 { - i = encodeVarintTx(dAtA, i, uint64(m.DelayPeriod)) - i-- - dAtA[i] = 0x20 - } - if m.Version != nil { - { - size, err := m.Version.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - } - { - size, err := m.Counterparty.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - if len(m.ClientId) > 0 { - i -= len(m.ClientId) - copy(dAtA[i:], m.ClientId) - i = encodeVarintTx(dAtA, i, uint64(len(m.ClientId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *MsgConnectionOpenInitResponse) 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 *MsgConnectionOpenInitResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgConnectionOpenInitResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - return len(dAtA) - i, nil -} - -func (m *MsgConnectionOpenTry) 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 *MsgConnectionOpenTry) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgConnectionOpenTry) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Signer) > 0 { - i -= len(m.Signer) - copy(dAtA[i:], m.Signer) - i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) - i-- - dAtA[i] = 0x62 - } - { - size, err := m.ConsensusHeight.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x5a - if len(m.ProofConsensus) > 0 { - i -= len(m.ProofConsensus) - copy(dAtA[i:], m.ProofConsensus) - i = encodeVarintTx(dAtA, i, uint64(len(m.ProofConsensus))) - i-- - dAtA[i] = 0x52 - } - if len(m.ProofClient) > 0 { - i -= len(m.ProofClient) - copy(dAtA[i:], m.ProofClient) - i = encodeVarintTx(dAtA, i, uint64(len(m.ProofClient))) - i-- - dAtA[i] = 0x4a - } - if len(m.ProofInit) > 0 { - i -= len(m.ProofInit) - copy(dAtA[i:], m.ProofInit) - i = encodeVarintTx(dAtA, i, uint64(len(m.ProofInit))) - i-- - dAtA[i] = 0x42 - } - { - size, err := m.ProofHeight.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x3a - if len(m.CounterpartyVersions) > 0 { - for iNdEx := len(m.CounterpartyVersions) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.CounterpartyVersions[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x32 - } - } - if m.DelayPeriod != 0 { - i = encodeVarintTx(dAtA, i, uint64(m.DelayPeriod)) - i-- - dAtA[i] = 0x28 - } - { - size, err := m.Counterparty.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x22 - if m.ClientState != nil { - { - size, err := m.ClientState.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - } - if len(m.PreviousConnectionId) > 0 { - i -= len(m.PreviousConnectionId) - copy(dAtA[i:], m.PreviousConnectionId) - i = encodeVarintTx(dAtA, i, uint64(len(m.PreviousConnectionId))) - i-- - dAtA[i] = 0x12 - } - if len(m.ClientId) > 0 { - i -= len(m.ClientId) - copy(dAtA[i:], m.ClientId) - i = encodeVarintTx(dAtA, i, uint64(len(m.ClientId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *MsgConnectionOpenTryResponse) 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 *MsgConnectionOpenTryResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgConnectionOpenTryResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - return len(dAtA) - i, nil -} - -func (m *MsgConnectionOpenAck) 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 *MsgConnectionOpenAck) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgConnectionOpenAck) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Signer) > 0 { - i -= len(m.Signer) - copy(dAtA[i:], m.Signer) - i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) - i-- - dAtA[i] = 0x52 - } - { - size, err := m.ConsensusHeight.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x4a - if len(m.ProofConsensus) > 0 { - i -= len(m.ProofConsensus) - copy(dAtA[i:], m.ProofConsensus) - i = encodeVarintTx(dAtA, i, uint64(len(m.ProofConsensus))) - i-- - dAtA[i] = 0x42 - } - if len(m.ProofClient) > 0 { - i -= len(m.ProofClient) - copy(dAtA[i:], m.ProofClient) - i = encodeVarintTx(dAtA, i, uint64(len(m.ProofClient))) - i-- - dAtA[i] = 0x3a - } - if len(m.ProofTry) > 0 { - i -= len(m.ProofTry) - copy(dAtA[i:], m.ProofTry) - i = encodeVarintTx(dAtA, i, uint64(len(m.ProofTry))) - i-- - dAtA[i] = 0x32 - } - { - size, err := m.ProofHeight.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x2a - if m.ClientState != nil { - { - size, err := m.ClientState.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x22 - } - if m.Version != nil { - { - size, err := m.Version.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - } - if len(m.CounterpartyConnectionId) > 0 { - i -= len(m.CounterpartyConnectionId) - copy(dAtA[i:], m.CounterpartyConnectionId) - i = encodeVarintTx(dAtA, i, uint64(len(m.CounterpartyConnectionId))) - i-- - dAtA[i] = 0x12 - } - if len(m.ConnectionId) > 0 { - i -= len(m.ConnectionId) - copy(dAtA[i:], m.ConnectionId) - i = encodeVarintTx(dAtA, i, uint64(len(m.ConnectionId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *MsgConnectionOpenAckResponse) 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 *MsgConnectionOpenAckResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgConnectionOpenAckResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - return len(dAtA) - i, nil -} - -func (m *MsgConnectionOpenConfirm) 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 *MsgConnectionOpenConfirm) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgConnectionOpenConfirm) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Signer) > 0 { - i -= len(m.Signer) - copy(dAtA[i:], m.Signer) - i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) - i-- - dAtA[i] = 0x22 - } - { - size, err := m.ProofHeight.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - if len(m.ProofAck) > 0 { - i -= len(m.ProofAck) - copy(dAtA[i:], m.ProofAck) - i = encodeVarintTx(dAtA, i, uint64(len(m.ProofAck))) - i-- - dAtA[i] = 0x12 - } - if len(m.ConnectionId) > 0 { - i -= len(m.ConnectionId) - copy(dAtA[i:], m.ConnectionId) - i = encodeVarintTx(dAtA, i, uint64(len(m.ConnectionId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *MsgConnectionOpenConfirmResponse) 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 *MsgConnectionOpenConfirmResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgConnectionOpenConfirmResponse) 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 *MsgConnectionOpenInit) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.ClientId) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = m.Counterparty.Size() - n += 1 + l + sovTx(uint64(l)) - if m.Version != nil { - l = m.Version.Size() - n += 1 + l + sovTx(uint64(l)) - } - if m.DelayPeriod != 0 { - n += 1 + sovTx(uint64(m.DelayPeriod)) - } - l = len(m.Signer) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - return n -} - -func (m *MsgConnectionOpenInitResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - return n -} - -func (m *MsgConnectionOpenTry) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.ClientId) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.PreviousConnectionId) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - if m.ClientState != nil { - l = m.ClientState.Size() - n += 1 + l + sovTx(uint64(l)) - } - l = m.Counterparty.Size() - n += 1 + l + sovTx(uint64(l)) - if m.DelayPeriod != 0 { - n += 1 + sovTx(uint64(m.DelayPeriod)) - } - if len(m.CounterpartyVersions) > 0 { - for _, e := range m.CounterpartyVersions { - l = e.Size() - n += 1 + l + sovTx(uint64(l)) - } - } - l = m.ProofHeight.Size() - n += 1 + l + sovTx(uint64(l)) - l = len(m.ProofInit) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.ProofClient) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.ProofConsensus) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = m.ConsensusHeight.Size() - n += 1 + l + sovTx(uint64(l)) - l = len(m.Signer) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - return n -} - -func (m *MsgConnectionOpenTryResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - return n -} - -func (m *MsgConnectionOpenAck) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.ConnectionId) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.CounterpartyConnectionId) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - if m.Version != nil { - l = m.Version.Size() - n += 1 + l + sovTx(uint64(l)) - } - if m.ClientState != nil { - l = m.ClientState.Size() - n += 1 + l + sovTx(uint64(l)) - } - l = m.ProofHeight.Size() - n += 1 + l + sovTx(uint64(l)) - l = len(m.ProofTry) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.ProofClient) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.ProofConsensus) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = m.ConsensusHeight.Size() - n += 1 + l + sovTx(uint64(l)) - l = len(m.Signer) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - return n -} - -func (m *MsgConnectionOpenAckResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - return n -} - -func (m *MsgConnectionOpenConfirm) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.ConnectionId) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.ProofAck) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = m.ProofHeight.Size() - n += 1 + l + sovTx(uint64(l)) - l = len(m.Signer) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - return n -} - -func (m *MsgConnectionOpenConfirmResponse) 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 *MsgConnectionOpenInit) 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: MsgConnectionOpenInit: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgConnectionOpenInit: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ClientId", 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.ClientId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Counterparty", 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 := m.Counterparty.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Version", 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.Version == nil { - m.Version = &Version{} - } - if err := m.Version.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 4: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field DelayPeriod", wireType) - } - m.DelayPeriod = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.DelayPeriod |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Signer", 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.Signer = 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 *MsgConnectionOpenInitResponse) 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: MsgConnectionOpenInitResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgConnectionOpenInitResponse: 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 *MsgConnectionOpenTry) 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: MsgConnectionOpenTry: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgConnectionOpenTry: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ClientId", 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.ClientId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field PreviousConnectionId", 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.PreviousConnectionId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ClientState", 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.ClientState == nil { - m.ClientState = &types.Any{} - } - if err := m.ClientState.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Counterparty", 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 := m.Counterparty.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 5: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field DelayPeriod", wireType) - } - m.DelayPeriod = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.DelayPeriod |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 6: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field CounterpartyVersions", 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.CounterpartyVersions = append(m.CounterpartyVersions, &Version{}) - if err := m.CounterpartyVersions[len(m.CounterpartyVersions)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 7: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofHeight", 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 := m.ProofHeight.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 8: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofInit", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ProofInit = append(m.ProofInit[:0], dAtA[iNdEx:postIndex]...) - if m.ProofInit == nil { - m.ProofInit = []byte{} - } - iNdEx = postIndex - case 9: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofClient", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ProofClient = append(m.ProofClient[:0], dAtA[iNdEx:postIndex]...) - if m.ProofClient == nil { - m.ProofClient = []byte{} - } - iNdEx = postIndex - case 10: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofConsensus", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ProofConsensus = append(m.ProofConsensus[:0], dAtA[iNdEx:postIndex]...) - if m.ProofConsensus == nil { - m.ProofConsensus = []byte{} - } - iNdEx = postIndex - case 11: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ConsensusHeight", 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 := m.ConsensusHeight.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 12: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Signer", 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.Signer = 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 *MsgConnectionOpenTryResponse) 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: MsgConnectionOpenTryResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgConnectionOpenTryResponse: 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 *MsgConnectionOpenAck) 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: MsgConnectionOpenAck: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgConnectionOpenAck: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ConnectionId", 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.ConnectionId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field CounterpartyConnectionId", 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.CounterpartyConnectionId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Version", 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.Version == nil { - m.Version = &Version{} - } - if err := m.Version.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ClientState", 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.ClientState == nil { - m.ClientState = &types.Any{} - } - if err := m.ClientState.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofHeight", 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 := m.ProofHeight.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 6: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofTry", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ProofTry = append(m.ProofTry[:0], dAtA[iNdEx:postIndex]...) - if m.ProofTry == nil { - m.ProofTry = []byte{} - } - iNdEx = postIndex - case 7: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofClient", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ProofClient = append(m.ProofClient[:0], dAtA[iNdEx:postIndex]...) - if m.ProofClient == nil { - m.ProofClient = []byte{} - } - iNdEx = postIndex - case 8: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofConsensus", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ProofConsensus = append(m.ProofConsensus[:0], dAtA[iNdEx:postIndex]...) - if m.ProofConsensus == nil { - m.ProofConsensus = []byte{} - } - iNdEx = postIndex - case 9: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ConsensusHeight", 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 := m.ConsensusHeight.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 10: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Signer", 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.Signer = 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 *MsgConnectionOpenAckResponse) 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: MsgConnectionOpenAckResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgConnectionOpenAckResponse: 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 *MsgConnectionOpenConfirm) 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: MsgConnectionOpenConfirm: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgConnectionOpenConfirm: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ConnectionId", 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.ConnectionId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofAck", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ProofAck = append(m.ProofAck[:0], dAtA[iNdEx:postIndex]...) - if m.ProofAck == nil { - m.ProofAck = []byte{} - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofHeight", 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 := m.ProofHeight.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Signer", 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.Signer = 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 *MsgConnectionOpenConfirmResponse) 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: MsgConnectionOpenConfirmResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgConnectionOpenConfirmResponse: 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/ibc/core/03-connection/types/version.go b/x/ibc/core/03-connection/types/version.go deleted file mode 100644 index 10c5b33d285c..000000000000 --- a/x/ibc/core/03-connection/types/version.go +++ /dev/null @@ -1,220 +0,0 @@ -package types - -import ( - "strings" - - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -var ( - // DefaultIBCVersion represents the latest supported version of IBC used - // in connection version negotiation. The current version supports only - // ORDERED and UNORDERED channels and requires at least one channel type - // to be agreed upon. - DefaultIBCVersion = NewVersion(DefaultIBCVersionIdentifier, []string{"ORDER_ORDERED", "ORDER_UNORDERED"}) - - // DefaultIBCVersionIdentifier is the IBC v1.0.0 protocol version identifier - DefaultIBCVersionIdentifier = "1" - - // AllowNilFeatureSet is a helper map to indicate if a specified version - // identifier is allowed to have a nil feature set. Any versions supported, - // but not included in the map default to not supporting nil feature sets. - allowNilFeatureSet = map[string]bool{ - DefaultIBCVersionIdentifier: false, - } -) - -var _ exported.Version = &Version{} - -// NewVersion returns a new instance of Version. -func NewVersion(identifier string, features []string) *Version { - return &Version{ - Identifier: identifier, - Features: features, - } -} - -// GetIdentifier implements the VersionI interface -func (version Version) GetIdentifier() string { - return version.Identifier -} - -// GetFeatures implements the VersionI interface -func (version Version) GetFeatures() []string { - return version.Features -} - -// ValidateVersion does basic validation of the version identifier and -// features. It unmarshals the version string into a Version object. -func ValidateVersion(version *Version) error { - if version == nil { - return sdkerrors.Wrap(ErrInvalidVersion, "version cannot be nil") - } - if strings.TrimSpace(version.Identifier) == "" { - return sdkerrors.Wrap(ErrInvalidVersion, "version identifier cannot be blank") - } - for i, feature := range version.Features { - if strings.TrimSpace(feature) == "" { - return sdkerrors.Wrapf(ErrInvalidVersion, "feature cannot be blank, index %d", i) - } - } - - return nil -} - -// VerifyProposedVersion verifies that the entire feature set in the -// proposed version is supported by this chain. If the feature set is -// empty it verifies that this is allowed for the specified version -// identifier. -func (version Version) VerifyProposedVersion(proposedVersion exported.Version) error { - if proposedVersion.GetIdentifier() != version.GetIdentifier() { - return sdkerrors.Wrapf( - ErrVersionNegotiationFailed, - "proposed version identifier does not equal supported version identifier (%s != %s)", proposedVersion.GetIdentifier(), version.GetIdentifier(), - ) - } - - if len(proposedVersion.GetFeatures()) == 0 && !allowNilFeatureSet[proposedVersion.GetIdentifier()] { - return sdkerrors.Wrapf( - ErrVersionNegotiationFailed, - "nil feature sets are not supported for version identifier (%s)", proposedVersion.GetIdentifier(), - ) - } - - for _, proposedFeature := range proposedVersion.GetFeatures() { - if !contains(proposedFeature, version.GetFeatures()) { - return sdkerrors.Wrapf( - ErrVersionNegotiationFailed, - "proposed feature (%s) is not a supported feature set (%s)", proposedFeature, version.GetFeatures(), - ) - } - } - - return nil -} - -// VerifySupportedFeature takes in a version and feature string and returns -// true if the feature is supported by the version and false otherwise. -func VerifySupportedFeature(version exported.Version, feature string) bool { - for _, f := range version.GetFeatures() { - if f == feature { - return true - } - } - return false -} - -// GetCompatibleVersions returns a descending ordered set of compatible IBC -// versions for the caller chain's connection end. The latest supported -// version should be first element and the set should descend to the oldest -// supported version. -func GetCompatibleVersions() []exported.Version { - return []exported.Version{DefaultIBCVersion} -} - -// IsSupportedVersion returns true if the proposed version has a matching version -// identifier and its entire feature set is supported or the version identifier -// supports an empty feature set. -func IsSupportedVersion(proposedVersion *Version) bool { - supportedVersion, found := FindSupportedVersion(proposedVersion, GetCompatibleVersions()) - if !found { - return false - } - - if err := supportedVersion.VerifyProposedVersion(proposedVersion); err != nil { - return false - } - - return true -} - -// FindSupportedVersion returns the version with a matching version identifier -// if it exists. The returned boolean is true if the version is found and -// false otherwise. -func FindSupportedVersion(version exported.Version, supportedVersions []exported.Version) (exported.Version, bool) { - for _, supportedVersion := range supportedVersions { - if version.GetIdentifier() == supportedVersion.GetIdentifier() { - return supportedVersion, true - } - } - return nil, false -} - -// PickVersion iterates over the descending ordered set of compatible IBC -// versions and selects the first version with a version identifier that is -// supported by the counterparty. The returned version contains a feature -// set with the intersection of the features supported by the source and -// counterparty chains. If the feature set intersection is nil and this is -// not allowed for the chosen version identifier then the search for a -// compatible version continues. This function is called in the ConnOpenTry -// handshake procedure. -// -// CONTRACT: PickVersion must only provide a version that is in the -// intersection of the supported versions and the counterparty versions. -func PickVersion(supportedVersions, counterpartyVersions []exported.Version) (*Version, error) { - for _, supportedVersion := range supportedVersions { - // check if the source version is supported by the counterparty - if counterpartyVersion, found := FindSupportedVersion(supportedVersion, counterpartyVersions); found { - featureSet := GetFeatureSetIntersection(supportedVersion.GetFeatures(), counterpartyVersion.GetFeatures()) - if len(featureSet) == 0 && !allowNilFeatureSet[supportedVersion.GetIdentifier()] { - continue - } - - return NewVersion(supportedVersion.GetIdentifier(), featureSet), nil - } - } - - return nil, sdkerrors.Wrapf( - ErrVersionNegotiationFailed, - "failed to find a matching counterparty version (%v) from the supported version list (%v)", counterpartyVersions, supportedVersions, - ) -} - -// GetFeatureSetIntersection returns the intersections of source feature set -// and the counterparty feature set. This is done by iterating over all the -// features in the source version and seeing if they exist in the feature -// set for the counterparty version. -func GetFeatureSetIntersection(sourceFeatureSet, counterpartyFeatureSet []string) (featureSet []string) { - for _, feature := range sourceFeatureSet { - if contains(feature, counterpartyFeatureSet) { - featureSet = append(featureSet, feature) - } - } - - return featureSet -} - -// ExportedVersionsToProto casts a slice of the Version interface to a slice -// of the Version proto definition. -func ExportedVersionsToProto(exportedVersions []exported.Version) []*Version { - versions := make([]*Version, len(exportedVersions)) - for i := range exportedVersions { - versions[i] = exportedVersions[i].(*Version) - } - - return versions -} - -// ProtoVersionsToExported converts a slice of the Version proto definition to -// the Version interface. -func ProtoVersionsToExported(versions []*Version) []exported.Version { - exportedVersions := make([]exported.Version, len(versions)) - for i := range versions { - exportedVersions[i] = versions[i] - } - - return exportedVersions -} - -// contains returns true if the provided string element exists within the -// string set. -func contains(elem string, set []string) bool { - for _, element := range set { - if elem == element { - return true - } - } - - return false -} diff --git a/x/ibc/core/03-connection/types/version_test.go b/x/ibc/core/03-connection/types/version_test.go deleted file mode 100644 index 8f882dd32711..000000000000 --- a/x/ibc/core/03-connection/types/version_test.go +++ /dev/null @@ -1,167 +0,0 @@ -package types_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" -) - -func TestValidateVersion(t *testing.T) { - testCases := []struct { - name string - version *types.Version - expPass bool - }{ - {"valid version", types.DefaultIBCVersion, true}, - {"valid empty feature set", types.NewVersion(types.DefaultIBCVersionIdentifier, []string{}), true}, - {"empty version identifier", types.NewVersion(" ", []string{"ORDER_UNORDERED"}), false}, - {"empty feature", types.NewVersion(types.DefaultIBCVersionIdentifier, []string{"ORDER_UNORDERED", " "}), false}, - } - - for i, tc := range testCases { - err := types.ValidateVersion(tc.version) - - if tc.expPass { - require.NoError(t, err, "valid test case %d failed: %s", i, tc.name) - } else { - require.Error(t, err, "invalid test case %d passed: %s", i, tc.name) - } - } -} - -func TestIsSupportedVersion(t *testing.T) { - testCases := []struct { - name string - version *types.Version - expPass bool - }{ - { - "version is supported", - types.ExportedVersionsToProto(types.GetCompatibleVersions())[0], - true, - }, - { - "version is not supported", - &types.Version{}, - false, - }, - { - "version feature is not supported", - types.NewVersion(types.DefaultIBCVersionIdentifier, []string{"ORDER_DAG"}), - false, - }, - } - - for _, tc := range testCases { - require.Equal(t, tc.expPass, types.IsSupportedVersion(tc.version)) - } -} - -func TestFindSupportedVersion(t *testing.T) { - testCases := []struct { - name string - version *types.Version - supportedVersions []exported.Version - expVersion *types.Version - expFound bool - }{ - {"valid supported version", types.DefaultIBCVersion, types.GetCompatibleVersions(), types.DefaultIBCVersion, true}, - {"empty (invalid) version", &types.Version{}, types.GetCompatibleVersions(), &types.Version{}, false}, - {"empty supported versions", types.DefaultIBCVersion, []exported.Version{}, &types.Version{}, false}, - {"desired version is last", types.DefaultIBCVersion, []exported.Version{types.NewVersion("1.1", nil), types.NewVersion("2", []string{"ORDER_UNORDERED"}), types.NewVersion("3", nil), types.DefaultIBCVersion}, types.DefaultIBCVersion, true}, - {"desired version identifier with different feature set", types.NewVersion(types.DefaultIBCVersionIdentifier, []string{"ORDER_DAG"}), types.GetCompatibleVersions(), types.DefaultIBCVersion, true}, - {"version not supported", types.NewVersion("2", []string{"ORDER_DAG"}), types.GetCompatibleVersions(), &types.Version{}, false}, - } - - for i, tc := range testCases { - version, found := types.FindSupportedVersion(tc.version, tc.supportedVersions) - if tc.expFound { - require.Equal(t, tc.expVersion.GetIdentifier(), version.GetIdentifier(), "test case %d: %s", i, tc.name) - require.True(t, found, "test case %d: %s", i, tc.name) - } else { - require.False(t, found, "test case: %s", tc.name) - require.Nil(t, version, "test case: %s", tc.name) - } - } -} - -func TestPickVersion(t *testing.T) { - testCases := []struct { - name string - supportedVersions []exported.Version - counterpartyVersions []exported.Version - expVer *types.Version - expPass bool - }{ - {"valid default ibc version", types.GetCompatibleVersions(), types.GetCompatibleVersions(), types.DefaultIBCVersion, true}, - {"valid version in counterparty versions", types.GetCompatibleVersions(), []exported.Version{types.NewVersion("version1", nil), types.NewVersion("2.0.0", []string{"ORDER_UNORDERED-ZK"}), types.DefaultIBCVersion}, types.DefaultIBCVersion, true}, - {"valid identifier match but empty feature set not allowed", types.GetCompatibleVersions(), []exported.Version{types.NewVersion(types.DefaultIBCVersionIdentifier, []string{"DAG", "ORDERED-ZK", "UNORDERED-zk]"})}, types.NewVersion(types.DefaultIBCVersionIdentifier, nil), false}, - {"empty counterparty versions", types.GetCompatibleVersions(), []exported.Version{}, &types.Version{}, false}, - {"non-matching counterparty versions", types.GetCompatibleVersions(), []exported.Version{types.NewVersion("2.0.0", nil)}, &types.Version{}, false}, - {"non-matching counterparty versions (uses ordered channels only) contained in supported versions (uses unordered channels only)", []exported.Version{types.NewVersion(types.DefaultIBCVersionIdentifier, []string{"ORDER_UNORDERED"})}, []exported.Version{types.NewVersion(types.DefaultIBCVersionIdentifier, []string{"ORDER_ORDERED"})}, &types.Version{}, false}, - } - - for i, tc := range testCases { - version, err := types.PickVersion(tc.supportedVersions, tc.counterpartyVersions) - - if tc.expPass { - require.NoError(t, err, "valid test case %d failed: %s", i, tc.name) - } else { - require.Error(t, err, "invalid test case %d passed: %s", i, tc.name) - var emptyVersion *types.Version - require.Equal(t, emptyVersion, version, "invalid test case %d passed: %s", i, tc.name) - } - } -} - -func TestVerifyProposedVersion(t *testing.T) { - testCases := []struct { - name string - proposedVersion *types.Version - supportedVersion *types.Version - expPass bool - }{ - {"entire feature set supported", types.DefaultIBCVersion, types.NewVersion("1", []string{"ORDER_ORDERED", "ORDER_UNORDERED", "ORDER_DAG"}), true}, - {"empty feature sets not supported", types.NewVersion("1", []string{}), types.DefaultIBCVersion, false}, - {"one feature missing", types.DefaultIBCVersion, types.NewVersion("1", []string{"ORDER_UNORDERED", "ORDER_DAG"}), false}, - {"both features missing", types.DefaultIBCVersion, types.NewVersion("1", []string{"ORDER_DAG"}), false}, - {"identifiers do not match", types.NewVersion("2", []string{"ORDER_UNORDERED", "ORDER_ORDERED"}), types.DefaultIBCVersion, false}, - } - - for i, tc := range testCases { - err := tc.supportedVersion.VerifyProposedVersion(tc.proposedVersion) - - if tc.expPass { - require.NoError(t, err, "test case %d: %s", i, tc.name) - } else { - require.Error(t, err, "test case %d: %s", i, tc.name) - } - } - -} - -func TestVerifySupportedFeature(t *testing.T) { - nilFeatures := types.NewVersion(types.DefaultIBCVersionIdentifier, nil) - - testCases := []struct { - name string - version *types.Version - feature string - expPass bool - }{ - {"check ORDERED supported", ibctesting.ConnectionVersion, "ORDER_ORDERED", true}, - {"check UNORDERED supported", ibctesting.ConnectionVersion, "ORDER_UNORDERED", true}, - {"check DAG unsupported", ibctesting.ConnectionVersion, "ORDER_DAG", false}, - {"check empty feature set returns false", nilFeatures, "ORDER_ORDERED", false}, - } - - for i, tc := range testCases { - supported := types.VerifySupportedFeature(tc.version, tc.feature) - - require.Equal(t, tc.expPass, supported, "test case %d: %s", i, tc.name) - } -} diff --git a/x/ibc/core/04-channel/client/cli/cli.go b/x/ibc/core/04-channel/client/cli/cli.go deleted file mode 100644 index baf386fecaf3..000000000000 --- a/x/ibc/core/04-channel/client/cli/cli.go +++ /dev/null @@ -1,58 +0,0 @@ -package cli - -import ( - "github.com/spf13/cobra" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" -) - -// GetQueryCmd returns the query commands for IBC channels -func GetQueryCmd() *cobra.Command { - queryCmd := &cobra.Command{ - Use: types.SubModuleName, - Short: "IBC channel query subcommands", - DisableFlagParsing: true, - SuggestionsMinimumDistance: 2, - RunE: client.ValidateCmd, - } - - queryCmd.AddCommand( - GetCmdQueryChannels(), - GetCmdQueryChannel(), - GetCmdQueryConnectionChannels(), - GetCmdQueryChannelClientState(), - GetCmdQueryPacketCommitment(), - GetCmdQueryPacketCommitments(), - GetCmdQueryPacketReceipt(), - GetCmdQueryPacketAcknowledgement(), - GetCmdQueryUnreceivedPackets(), - GetCmdQueryUnreceivedAcks(), - GetCmdQueryNextSequenceReceive(), - // TODO: next sequence Send ? - ) - - return queryCmd -} - -// NewTxCmd returns a CLI command handler for all x/ibc channel transaction commands. -func NewTxCmd() *cobra.Command { - txCmd := &cobra.Command{ - Use: types.SubModuleName, - Short: "IBC channel transaction subcommands", - DisableFlagParsing: true, - SuggestionsMinimumDistance: 2, - RunE: client.ValidateCmd, - } - - txCmd.AddCommand( - NewChannelOpenInitCmd(), - NewChannelOpenTryCmd(), - NewChannelOpenAckCmd(), - NewChannelOpenConfirmCmd(), - NewChannelCloseInitCmd(), - NewChannelCloseConfirmCmd(), - ) - - return txCmd -} diff --git a/x/ibc/core/04-channel/client/cli/query.go b/x/ibc/core/04-channel/client/cli/query.go deleted file mode 100644 index 03df474f1e79..000000000000 --- a/x/ibc/core/04-channel/client/cli/query.go +++ /dev/null @@ -1,457 +0,0 @@ -package cli - -import ( - "fmt" - "strconv" - - "github.com/spf13/cobra" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/version" - "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/client/utils" - "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" -) - -const ( - flagSequences = "sequences" -) - -// GetCmdQueryChannels defines the command to query all the channels ends -// that this chain mantains. -func GetCmdQueryChannels() *cobra.Command { - cmd := &cobra.Command{ - Use: "channels", - Short: "Query all channels", - Long: "Query all channels from a chain", - Example: fmt.Sprintf("%s query %s %s channels", version.AppName, host.ModuleName, types.SubModuleName), - Args: cobra.NoArgs, - RunE: func(cmd *cobra.Command, _ []string) error { - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } - queryClient := types.NewQueryClient(clientCtx) - - pageReq, err := client.ReadPageRequest(cmd.Flags()) - if err != nil { - return err - } - - req := &types.QueryChannelsRequest{ - Pagination: pageReq, - } - - res, err := queryClient.Channels(cmd.Context(), req) - if err != nil { - return err - } - - return clientCtx.PrintProto(res) - }, - } - - flags.AddQueryFlagsToCmd(cmd) - flags.AddPaginationFlagsToCmd(cmd, "channels") - - return cmd -} - -// GetCmdQueryChannel defines the command to query a channel end -func GetCmdQueryChannel() *cobra.Command { - cmd := &cobra.Command{ - Use: "end [port-id] [channel-id]", - Short: "Query a channel end", - Long: "Query an IBC channel end from a port and channel identifiers", - Example: fmt.Sprintf( - "%s query %s %s end [port-id] [channel-id]", version.AppName, host.ModuleName, types.SubModuleName, - ), - Args: cobra.ExactArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } - portID := args[0] - channelID := args[1] - prove, _ := cmd.Flags().GetBool(flags.FlagProve) - - channelRes, err := utils.QueryChannel(clientCtx, portID, channelID, prove) - if err != nil { - return err - } - - return clientCtx.PrintProto(channelRes) - }, - } - - cmd.Flags().Bool(flags.FlagProve, true, "show proofs for the query results") - flags.AddQueryFlagsToCmd(cmd) - - return cmd -} - -// GetCmdQueryConnectionChannels defines the command to query all the channels associated with a -// connection -func GetCmdQueryConnectionChannels() *cobra.Command { - cmd := &cobra.Command{ - Use: "connections [connection-id]", - Short: "Query all channels associated with a connection", - Long: "Query all channels associated with a connection", - Example: fmt.Sprintf("%s query %s %s connections [connection-id]", version.AppName, host.ModuleName, types.SubModuleName), - Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } - queryClient := types.NewQueryClient(clientCtx) - pageReq, err := client.ReadPageRequest(cmd.Flags()) - if err != nil { - return err - } - - req := &types.QueryConnectionChannelsRequest{ - Connection: args[0], - Pagination: pageReq, - } - - res, err := queryClient.ConnectionChannels(cmd.Context(), req) - if err != nil { - return err - } - - return clientCtx.PrintProto(res) - }, - } - - flags.AddQueryFlagsToCmd(cmd) - flags.AddPaginationFlagsToCmd(cmd, "channels associated with a connection") - - return cmd -} - -// GetCmdQueryChannelClientState defines the command to query a client state from a channel -func GetCmdQueryChannelClientState() *cobra.Command { - cmd := &cobra.Command{ - Use: "client-state [port-id] [channel-id]", - Short: "Query the client state associated with a channel", - Long: "Query the client state associated with a channel, by providing its port and channel identifiers.", - Example: fmt.Sprintf("%s query ibc channel client-state [port-id] [channel-id]", version.AppName), - Args: cobra.ExactArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } - portID := args[0] - channelID := args[1] - - res, err := utils.QueryChannelClientState(clientCtx, portID, channelID, false) - if err != nil { - return err - } - - return clientCtx.PrintProto(res.IdentifiedClientState) - }, - } - - flags.AddQueryFlagsToCmd(cmd) - - return cmd -} - -// GetCmdQueryPacketCommitments defines the command to query all packet commitments associated with -// a channel -func GetCmdQueryPacketCommitments() *cobra.Command { - cmd := &cobra.Command{ - Use: "packet-commitments [port-id] [channel-id]", - Short: "Query all packet commitments associated with a channel", - Long: "Query all packet commitments associated with a channel", - Example: fmt.Sprintf("%s query %s %s packet-commitments [port-id] [channel-id]", version.AppName, host.ModuleName, types.SubModuleName), - Args: cobra.ExactArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } - queryClient := types.NewQueryClient(clientCtx) - pageReq, err := client.ReadPageRequest(cmd.Flags()) - if err != nil { - return err - } - - req := &types.QueryPacketCommitmentsRequest{ - PortId: args[0], - ChannelId: args[1], - Pagination: pageReq, - } - - res, err := queryClient.PacketCommitments(cmd.Context(), req) - if err != nil { - return err - } - - return clientCtx.PrintProto(res) - }, - } - - flags.AddQueryFlagsToCmd(cmd) - flags.AddPaginationFlagsToCmd(cmd, "packet commitments associated with a channel") - - return cmd -} - -// GetCmdQueryPacketCommitment defines the command to query a packet commitment -func GetCmdQueryPacketCommitment() *cobra.Command { - cmd := &cobra.Command{ - Use: "packet-commitment [port-id] [channel-id] [sequence]", - Short: "Query a packet commitment", - Long: "Query a packet commitment", - Example: fmt.Sprintf( - "%s query %s %s packet-commitment [port-id] [channel-id] [sequence]", version.AppName, host.ModuleName, types.SubModuleName, - ), - Args: cobra.ExactArgs(3), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } - portID := args[0] - channelID := args[1] - prove, _ := cmd.Flags().GetBool(flags.FlagProve) - - seq, err := strconv.ParseUint(args[2], 10, 64) - if err != nil { - return err - } - - res, err := utils.QueryPacketCommitment(clientCtx, portID, channelID, seq, prove) - if err != nil { - return err - } - - return clientCtx.PrintProto(res) - }, - } - - cmd.Flags().Bool(flags.FlagProve, true, "show proofs for the query results") - flags.AddQueryFlagsToCmd(cmd) - - return cmd -} - -// GetCmdQueryPacketReceipt defines the command to query a packet receipt -func GetCmdQueryPacketReceipt() *cobra.Command { - cmd := &cobra.Command{ - Use: "packet-receipt [port-id] [channel-id] [sequence]", - Short: "Query a packet receipt", - Long: "Query a packet receipt", - Example: fmt.Sprintf( - "%s query %s %s packet-receipt [port-id] [channel-id] [sequence]", version.AppName, host.ModuleName, types.SubModuleName, - ), - Args: cobra.ExactArgs(3), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } - portID := args[0] - channelID := args[1] - prove, _ := cmd.Flags().GetBool(flags.FlagProve) - - seq, err := strconv.ParseUint(args[2], 10, 64) - if err != nil { - return err - } - - res, err := utils.QueryPacketReceipt(clientCtx, portID, channelID, seq, prove) - if err != nil { - return err - } - - return clientCtx.PrintProto(res) - }, - } - - cmd.Flags().Bool(flags.FlagProve, true, "show proofs for the query results") - flags.AddQueryFlagsToCmd(cmd) - - return cmd -} - -// GetCmdQueryPacketAcknowledgement defines the command to query a packet acknowledgement -func GetCmdQueryPacketAcknowledgement() *cobra.Command { - cmd := &cobra.Command{ - Use: "packet-ack [port-id] [channel-id] [sequence]", - Short: "Query a packet acknowledgement", - Long: "Query a packet acknowledgement", - Example: fmt.Sprintf( - "%s query %s %s packet-ack [port-id] [channel-id] [sequence]", version.AppName, host.ModuleName, types.SubModuleName, - ), - Args: cobra.ExactArgs(3), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } - portID := args[0] - channelID := args[1] - prove, _ := cmd.Flags().GetBool(flags.FlagProve) - - seq, err := strconv.ParseUint(args[2], 10, 64) - if err != nil { - return err - } - - res, err := utils.QueryPacketAcknowledgement(clientCtx, portID, channelID, seq, prove) - if err != nil { - return err - } - - return clientCtx.PrintProto(res) - }, - } - - cmd.Flags().Bool(flags.FlagProve, true, "show proofs for the query results") - flags.AddQueryFlagsToCmd(cmd) - - return cmd -} - -// GetCmdQueryUnreceivedPackets defines the command to query all the unreceived -// packets on the receiving chain -func GetCmdQueryUnreceivedPackets() *cobra.Command { - cmd := &cobra.Command{ - Use: "unreceived-packets [port-id] [channel-id]", - Short: "Query all the unreceived packets associated with a channel", - Long: `Determine if a packet, given a list of packet commitment sequences, is unreceived. - -The return value represents: -- Unreceived packet commitments: no acknowledgement exists on receiving chain for the given packet commitment sequence on sending chain. -`, - Example: fmt.Sprintf("%s query %s %s unreceived-packets [port-id] [channel-id] --sequences=1,2,3", version.AppName, host.ModuleName, types.SubModuleName), - Args: cobra.ExactArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } - queryClient := types.NewQueryClient(clientCtx) - - seqSlice, err := cmd.Flags().GetInt64Slice(flagSequences) - if err != nil { - return err - } - - seqs := make([]uint64, len(seqSlice)) - for i := range seqSlice { - seqs[i] = uint64(seqSlice[i]) - } - - req := &types.QueryUnreceivedPacketsRequest{ - PortId: args[0], - ChannelId: args[1], - PacketCommitmentSequences: seqs, - } - - res, err := queryClient.UnreceivedPackets(cmd.Context(), req) - if err != nil { - return err - } - - return clientCtx.PrintProto(res) - }, - } - - cmd.Flags().Int64Slice(flagSequences, []int64{}, "comma separated list of packet sequence numbers") - flags.AddQueryFlagsToCmd(cmd) - - return cmd -} - -// GetCmdQueryUnreceivedAcks defines the command to query all the unreceived acks on the original sending chain -func GetCmdQueryUnreceivedAcks() *cobra.Command { - cmd := &cobra.Command{ - Use: "unreceived-acks [port-id] [channel-id]", - Short: "Query all the unreceived acks associated with a channel", - Long: `Given a list of acknowledgement sequences from counterparty, determine if an ack on the counterparty chain has been received on the executing chain. - -The return value represents: -- Unreceived packet acknowledgement: packet commitment exists on original sending (executing) chain and ack exists on receiving chain. -`, - Example: fmt.Sprintf("%s query %s %s unreceived-acks [port-id] [channel-id] --sequences=1,2,3", version.AppName, host.ModuleName, types.SubModuleName), - Args: cobra.ExactArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } - queryClient := types.NewQueryClient(clientCtx) - - seqSlice, err := cmd.Flags().GetInt64Slice(flagSequences) - if err != nil { - return err - } - - seqs := make([]uint64, len(seqSlice)) - for i := range seqSlice { - seqs[i] = uint64(seqSlice[i]) - } - - req := &types.QueryUnreceivedAcksRequest{ - PortId: args[0], - ChannelId: args[1], - PacketAckSequences: seqs, - } - - res, err := queryClient.UnreceivedAcks(cmd.Context(), req) - if err != nil { - return err - } - - return clientCtx.PrintProto(res) - }, - } - - cmd.Flags().Int64Slice(flagSequences, []int64{}, "comma separated list of packet sequence numbers") - flags.AddQueryFlagsToCmd(cmd) - - return cmd -} - -// GetCmdQueryNextSequenceReceive defines the command to query a next receive sequence for a given channel -func GetCmdQueryNextSequenceReceive() *cobra.Command { - cmd := &cobra.Command{ - Use: "next-sequence-receive [port-id] [channel-id]", - Short: "Query a next receive sequence", - Long: "Query the next receive sequence for a given channel", - Example: fmt.Sprintf( - "%s query %s %s next-sequence-receive [port-id] [channel-id]", version.AppName, host.ModuleName, types.SubModuleName, - ), - Args: cobra.ExactArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } - portID := args[0] - channelID := args[1] - prove, _ := cmd.Flags().GetBool(flags.FlagProve) - - sequenceRes, err := utils.QueryNextSequenceReceive(clientCtx, portID, channelID, prove) - if err != nil { - return err - } - - clientCtx = clientCtx.WithHeight(int64(sequenceRes.ProofHeight.RevisionHeight)) - return clientCtx.PrintProto(sequenceRes) - }, - } - - cmd.Flags().Bool(flags.FlagProve, true, "show proofs for the query results") - flags.AddQueryFlagsToCmd(cmd) - - return cmd -} diff --git a/x/ibc/core/04-channel/client/cli/tx.go b/x/ibc/core/04-channel/client/cli/tx.go deleted file mode 100644 index 20afe6226746..000000000000 --- a/x/ibc/core/04-channel/client/cli/tx.go +++ /dev/null @@ -1,288 +0,0 @@ -package cli - -import ( - "strings" - - "github.com/spf13/cobra" - "github.com/spf13/pflag" - - "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" - "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" -) - -// IBC Channel flags -const ( - FlagOrdered = "ordered" - FlagIBCVersion = "ibc-version" -) - -// NewChannelOpenInitCmd returns the command to create a MsgChannelOpenInit transaction -func NewChannelOpenInitCmd() *cobra.Command { - cmd := &cobra.Command{ - Use: "open-init [port-id] [counterparty-port-id] [connection-hops]", - Short: "Creates and sends a ChannelOpenInit message", - Args: cobra.ExactArgs(3), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - portID := args[0] - counterpartyPortID := args[1] - hops := strings.Split(args[2], "/") - order := channelOrder(cmd.Flags()) - version, _ := cmd.Flags().GetString(FlagIBCVersion) - - msg := types.NewMsgChannelOpenInit( - portID, version, order, hops, - counterpartyPortID, clientCtx.GetFromAddress(), - ) - svcMsgClientConn := &msgservice.ServiceMsgClientConn{} - msgClient := types.NewMsgClient(svcMsgClientConn) - _, err = msgClient.ChannelOpenInit(cmd.Context(), msg) - if err != nil { - return err - } - - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) - }, - } - - cmd.Flags().Bool(FlagOrdered, true, "Pass flag for opening ordered channels") - cmd.Flags().String(FlagIBCVersion, ibctransfertypes.Version, "IBC application version") - flags.AddTxFlagsToCmd(cmd) - - return cmd -} - -// NewChannelOpenTryCmd returns the command to create a MsgChannelOpenTry transaction -func NewChannelOpenTryCmd() *cobra.Command { - cmd := &cobra.Command{ - Use: "open-try [port-id] [channel-id] [counterparty-port-id] [counterparty-channel-id] [connection-hops] [/path/to/proof_init.json] [proof-height]", - Short: "Creates and sends a ChannelOpenTry message", - Args: cobra.ExactArgs(7), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - portID := args[0] - channelID := args[1] - counterpartyPortID := args[2] - counterpartyChannelID := args[3] - hops := strings.Split(args[4], "/") - order := channelOrder(cmd.Flags()) - - // TODO: Differentiate between channel and counterparty versions. - version, _ := cmd.Flags().GetString(FlagIBCVersion) - - proofInit, err := connectionutils.ParseProof(clientCtx.LegacyAmino, args[5]) - if err != nil { - return err - } - - proofHeight, err := clienttypes.ParseHeight(args[6]) - if err != nil { - return err - } - - msg := types.NewMsgChannelOpenTry( - portID, channelID, version, order, hops, - counterpartyPortID, counterpartyChannelID, version, - proofInit, proofHeight, clientCtx.GetFromAddress(), - ) - svcMsgClientConn := &msgservice.ServiceMsgClientConn{} - msgClient := types.NewMsgClient(svcMsgClientConn) - _, err = msgClient.ChannelOpenTry(cmd.Context(), msg) - if err != nil { - return err - } - - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) - }, - } - - cmd.Flags().Bool(FlagOrdered, true, "Pass flag for opening ordered channels") - cmd.Flags().String(FlagIBCVersion, ibctransfertypes.Version, "IBC application version") - flags.AddTxFlagsToCmd(cmd) - - return cmd -} - -// NewChannelOpenAckCmd returns the command to create a MsgChannelOpenAck transaction -func NewChannelOpenAckCmd() *cobra.Command { - cmd := &cobra.Command{ - Use: "open-ack [port-id] [channel-id] [counterparty-channel-id] [/path/to/proof_try.json] [proof-height]", - Short: "Creates and sends a ChannelOpenAck message", - Args: cobra.ExactArgs(5), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - portID := args[0] - channelID := args[1] - counterpartyChannelID := args[2] - - // TODO: Differentiate between channel and counterparty versions. - version, _ := cmd.Flags().GetString(FlagIBCVersion) - - proofTry, err := connectionutils.ParseProof(clientCtx.LegacyAmino, args[3]) - if err != nil { - return err - } - - proofHeight, err := clienttypes.ParseHeight(args[4]) - if err != nil { - return err - } - - msg := types.NewMsgChannelOpenAck( - portID, channelID, counterpartyChannelID, version, proofTry, proofHeight, clientCtx.GetFromAddress(), - ) - svcMsgClientConn := &msgservice.ServiceMsgClientConn{} - msgClient := types.NewMsgClient(svcMsgClientConn) - _, err = msgClient.ChannelOpenAck(cmd.Context(), msg) - if err != nil { - return err - } - - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) - }, - } - cmd.Flags().String(FlagIBCVersion, ibctransfertypes.Version, "IBC application version") - flags.AddTxFlagsToCmd(cmd) - - return cmd -} - -// NewChannelOpenConfirmCmd returns the command to create a MsgChannelOpenConfirm transaction -func NewChannelOpenConfirmCmd() *cobra.Command { - cmd := &cobra.Command{ - Use: "open-confirm [port-id] [channel-id] [/path/to/proof_ack.json] [proof-height]", - Short: "Creates and sends a ChannelOpenConfirm message", - Args: cobra.ExactArgs(4), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - portID := args[0] - channelID := args[1] - - proofAck, err := connectionutils.ParseProof(clientCtx.LegacyAmino, args[2]) - if err != nil { - return err - } - - proofHeight, err := clienttypes.ParseHeight(args[3]) - if err != nil { - return err - } - - msg := types.NewMsgChannelOpenConfirm( - portID, channelID, proofAck, proofHeight, clientCtx.GetFromAddress(), - ) - svcMsgClientConn := &msgservice.ServiceMsgClientConn{} - msgClient := types.NewMsgClient(svcMsgClientConn) - _, err = msgClient.ChannelOpenConfirm(cmd.Context(), msg) - if err != nil { - return err - } - - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) - }, - } - - flags.AddTxFlagsToCmd(cmd) - - return cmd -} - -// NewChannelCloseInitCmd returns the command to create a MsgChannelCloseInit transaction -func NewChannelCloseInitCmd() *cobra.Command { - cmd := &cobra.Command{ - Use: "close-init [port-id] [channel-id]", - Short: "Creates and sends a ChannelCloseInit message", - Args: cobra.ExactArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - portID := args[0] - channelID := args[1] - - msg := types.NewMsgChannelCloseInit(portID, channelID, clientCtx.GetFromAddress()) - svcMsgClientConn := &msgservice.ServiceMsgClientConn{} - msgClient := types.NewMsgClient(svcMsgClientConn) - _, err = msgClient.ChannelCloseInit(cmd.Context(), msg) - if err != nil { - return err - } - - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) - }, - } - - flags.AddTxFlagsToCmd(cmd) - - return cmd -} - -// NewChannelCloseConfirmCmd returns the command to create a MsgChannelCloseConfirm transaction -func NewChannelCloseConfirmCmd() *cobra.Command { - cmd := &cobra.Command{ - Use: "close-confirm [port-id] [channel-id] [/path/to/proof_init.json] [proof-height]", - Short: "Creates and sends a ChannelCloseConfirm message", - Args: cobra.ExactArgs(4), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - portID := args[0] - channelID := args[1] - - proofInit, err := connectionutils.ParseProof(clientCtx.LegacyAmino, args[2]) - if err != nil { - return err - } - - proofHeight, err := clienttypes.ParseHeight(args[3]) - if err != nil { - return err - } - - msg := types.NewMsgChannelCloseConfirm( - portID, channelID, proofInit, proofHeight, clientCtx.GetFromAddress(), - ) - svcMsgClientConn := &msgservice.ServiceMsgClientConn{} - msgClient := types.NewMsgClient(svcMsgClientConn) - _, err = msgClient.ChannelCloseConfirm(cmd.Context(), msg) - if err != nil { - return err - } - - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) - }, - } - - flags.AddTxFlagsToCmd(cmd) - - return cmd -} - -func channelOrder(fs *pflag.FlagSet) types.Order { - if ordered, _ := fs.GetBool(FlagOrdered); ordered { - return types.ORDERED - } - - return types.UNORDERED -} diff --git a/x/ibc/core/04-channel/client/utils/utils.go b/x/ibc/core/04-channel/client/utils/utils.go deleted file mode 100644 index 167e05d048e9..000000000000 --- a/x/ibc/core/04-channel/client/utils/utils.go +++ /dev/null @@ -1,301 +0,0 @@ -package utils - -import ( - "context" - "encoding/binary" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - clientutils "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/client/utils" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - ibcclient "github.com/cosmos/cosmos-sdk/x/ibc/core/client" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -// QueryChannel returns a channel end. -// If prove is true, it performs an ABCI store query in order to retrieve the merkle proof. Otherwise, -// it uses the gRPC query client. -func QueryChannel( - clientCtx client.Context, portID, channelID string, prove bool, -) (*types.QueryChannelResponse, error) { - if prove { - return queryChannelABCI(clientCtx, portID, channelID) - } - - queryClient := types.NewQueryClient(clientCtx) - req := &types.QueryChannelRequest{ - PortId: portID, - ChannelId: channelID, - } - - return queryClient.Channel(context.Background(), req) -} - -func queryChannelABCI(clientCtx client.Context, portID, channelID string) (*types.QueryChannelResponse, error) { - key := host.ChannelKey(portID, channelID) - - value, proofBz, proofHeight, err := ibcclient.QueryTendermintProof(clientCtx, key) - if err != nil { - return nil, err - } - - // check if channel exists - if len(value) == 0 { - return nil, sdkerrors.Wrapf(types.ErrChannelNotFound, "portID (%s), channelID (%s)", portID, channelID) - } - - cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry) - - var channel types.Channel - if err := cdc.UnmarshalBinaryBare(value, &channel); err != nil { - return nil, err - } - - return types.NewQueryChannelResponse(channel, proofBz, proofHeight), nil -} - -// QueryChannelClientState returns the ClientState of a channel end. If -// prove is true, it performs an ABCI store query in order to retrieve the -// merkle proof. Otherwise, it uses the gRPC query client. -func QueryChannelClientState( - clientCtx client.Context, portID, channelID string, prove bool, -) (*types.QueryChannelClientStateResponse, error) { - - queryClient := types.NewQueryClient(clientCtx) - req := &types.QueryChannelClientStateRequest{ - PortId: portID, - ChannelId: channelID, - } - - res, err := queryClient.ChannelClientState(context.Background(), req) - if err != nil { - return nil, err - } - - if prove { - clientStateRes, err := clientutils.QueryClientStateABCI(clientCtx, res.IdentifiedClientState.ClientId) - if err != nil { - return nil, err - } - - // use client state returned from ABCI query in case query height differs - identifiedClientState := clienttypes.IdentifiedClientState{ - ClientId: res.IdentifiedClientState.ClientId, - ClientState: clientStateRes.ClientState, - } - res = types.NewQueryChannelClientStateResponse(identifiedClientState, clientStateRes.Proof, clientStateRes.ProofHeight) - } - - return res, nil -} - -// QueryChannelConsensusState returns the ConsensusState of a channel end. If -// prove is true, it performs an ABCI store query in order to retrieve the -// merkle proof. Otherwise, it uses the gRPC query client. -func QueryChannelConsensusState( - clientCtx client.Context, portID, channelID string, height clienttypes.Height, prove bool, -) (*types.QueryChannelConsensusStateResponse, error) { - - queryClient := types.NewQueryClient(clientCtx) - req := &types.QueryChannelConsensusStateRequest{ - PortId: portID, - ChannelId: channelID, - RevisionNumber: height.RevisionNumber, - RevisionHeight: height.RevisionHeight, - } - - res, err := queryClient.ChannelConsensusState(context.Background(), req) - if err != nil { - return nil, err - } - - if prove { - consensusStateRes, err := clientutils.QueryConsensusStateABCI(clientCtx, res.ClientId, height) - if err != nil { - return nil, err - } - - res = types.NewQueryChannelConsensusStateResponse(res.ClientId, consensusStateRes.ConsensusState, height, consensusStateRes.Proof, consensusStateRes.ProofHeight) - } - - return res, nil -} - -// QueryLatestConsensusState uses the channel Querier to return the -// latest ConsensusState given the source port ID and source channel ID. -func QueryLatestConsensusState( - clientCtx client.Context, portID, channelID string, -) (exported.ConsensusState, clienttypes.Height, clienttypes.Height, error) { - clientRes, err := QueryChannelClientState(clientCtx, portID, channelID, false) - if err != nil { - return nil, clienttypes.Height{}, clienttypes.Height{}, err - } - - var clientState exported.ClientState - if err := clientCtx.InterfaceRegistry.UnpackAny(clientRes.IdentifiedClientState.ClientState, &clientState); err != nil { - return nil, clienttypes.Height{}, clienttypes.Height{}, err - } - - clientHeight, ok := clientState.GetLatestHeight().(clienttypes.Height) - if !ok { - return nil, clienttypes.Height{}, clienttypes.Height{}, sdkerrors.Wrapf(sdkerrors.ErrInvalidHeight, "invalid height type. expected type: %T, got: %T", - clienttypes.Height{}, clientHeight) - } - res, err := QueryChannelConsensusState(clientCtx, portID, channelID, clientHeight, false) - if err != nil { - return nil, clienttypes.Height{}, clienttypes.Height{}, err - } - - var consensusState exported.ConsensusState - if err := clientCtx.InterfaceRegistry.UnpackAny(res.ConsensusState, &consensusState); err != nil { - return nil, clienttypes.Height{}, clienttypes.Height{}, err - } - - return consensusState, clientHeight, res.ProofHeight, nil -} - -// QueryNextSequenceReceive returns the next sequence receive. -// If prove is true, it performs an ABCI store query in order to retrieve the merkle proof. Otherwise, -// it uses the gRPC query client. -func QueryNextSequenceReceive( - clientCtx client.Context, portID, channelID string, prove bool, -) (*types.QueryNextSequenceReceiveResponse, error) { - if prove { - return queryNextSequenceRecvABCI(clientCtx, portID, channelID) - } - - queryClient := types.NewQueryClient(clientCtx) - req := &types.QueryNextSequenceReceiveRequest{ - PortId: portID, - ChannelId: channelID, - } - - return queryClient.NextSequenceReceive(context.Background(), req) -} - -func queryNextSequenceRecvABCI(clientCtx client.Context, portID, channelID string) (*types.QueryNextSequenceReceiveResponse, error) { - key := host.NextSequenceRecvKey(portID, channelID) - - value, proofBz, proofHeight, err := ibcclient.QueryTendermintProof(clientCtx, key) - if err != nil { - return nil, err - } - - // check if next sequence receive exists - if len(value) == 0 { - return nil, sdkerrors.Wrapf(types.ErrChannelNotFound, "portID (%s), channelID (%s)", portID, channelID) - } - - sequence := binary.BigEndian.Uint64(value) - - return types.NewQueryNextSequenceReceiveResponse(sequence, proofBz, proofHeight), nil -} - -// QueryPacketCommitment returns a packet commitment. -// If prove is true, it performs an ABCI store query in order to retrieve the merkle proof. Otherwise, -// it uses the gRPC query client. -func QueryPacketCommitment( - clientCtx client.Context, portID, channelID string, - sequence uint64, prove bool, -) (*types.QueryPacketCommitmentResponse, error) { - if prove { - return queryPacketCommitmentABCI(clientCtx, portID, channelID, sequence) - } - - queryClient := types.NewQueryClient(clientCtx) - req := &types.QueryPacketCommitmentRequest{ - PortId: portID, - ChannelId: channelID, - Sequence: sequence, - } - - return queryClient.PacketCommitment(context.Background(), req) -} - -func queryPacketCommitmentABCI( - clientCtx client.Context, portID, channelID string, sequence uint64, -) (*types.QueryPacketCommitmentResponse, error) { - key := host.PacketCommitmentKey(portID, channelID, sequence) - - value, proofBz, proofHeight, err := ibcclient.QueryTendermintProof(clientCtx, key) - if err != nil { - return nil, err - } - - // check if packet commitment exists - if len(value) == 0 { - return nil, sdkerrors.Wrapf(types.ErrPacketCommitmentNotFound, "portID (%s), channelID (%s), sequence (%d)", portID, channelID, sequence) - } - - return types.NewQueryPacketCommitmentResponse(value, proofBz, proofHeight), nil -} - -// QueryPacketReceipt returns data about a packet receipt. -// If prove is true, it performs an ABCI store query in order to retrieve the merkle proof. Otherwise, -// it uses the gRPC query client. -func QueryPacketReceipt( - clientCtx client.Context, portID, channelID string, - sequence uint64, prove bool, -) (*types.QueryPacketReceiptResponse, error) { - if prove { - return queryPacketReceiptABCI(clientCtx, portID, channelID, sequence) - } - - queryClient := types.NewQueryClient(clientCtx) - req := &types.QueryPacketReceiptRequest{ - PortId: portID, - ChannelId: channelID, - Sequence: sequence, - } - - return queryClient.PacketReceipt(context.Background(), req) -} - -func queryPacketReceiptABCI( - clientCtx client.Context, portID, channelID string, sequence uint64, -) (*types.QueryPacketReceiptResponse, error) { - key := host.PacketReceiptKey(portID, channelID, sequence) - - value, proofBz, proofHeight, err := ibcclient.QueryTendermintProof(clientCtx, key) - if err != nil { - return nil, err - } - - return types.NewQueryPacketReceiptResponse(value != nil, proofBz, proofHeight), nil -} - -// QueryPacketAcknowledgement returns the data about a packet acknowledgement. -// If prove is true, it performs an ABCI store query in order to retrieve the merkle proof. Otherwise, -// it uses the gRPC query client -func QueryPacketAcknowledgement(clientCtx client.Context, portID, channelID string, sequence uint64, prove bool) (*types.QueryPacketAcknowledgementResponse, error) { - if prove { - return queryPacketAcknowledgementABCI(clientCtx, portID, channelID, sequence) - } - - queryClient := types.NewQueryClient(clientCtx) - req := &types.QueryPacketAcknowledgementRequest{ - PortId: portID, - ChannelId: channelID, - Sequence: sequence, - } - - return queryClient.PacketAcknowledgement(context.Background(), req) -} - -func queryPacketAcknowledgementABCI(clientCtx client.Context, portID, channelID string, sequence uint64) (*types.QueryPacketAcknowledgementResponse, error) { - key := host.PacketAcknowledgementKey(portID, channelID, sequence) - - value, proofBz, proofHeight, err := ibcclient.QueryTendermintProof(clientCtx, key) - if err != nil { - return nil, err - } - - if len(value) == 0 { - return nil, sdkerrors.Wrapf(types.ErrInvalidAcknowledgement, "portID (%s), channelID (%s), sequence (%d)", portID, channelID, sequence) - } - - return types.NewQueryPacketAcknowledgementResponse(value, proofBz, proofHeight), nil -} diff --git a/x/ibc/core/04-channel/genesis.go b/x/ibc/core/04-channel/genesis.go deleted file mode 100644 index 07fad47d77b2..000000000000 --- a/x/ibc/core/04-channel/genesis.go +++ /dev/null @@ -1,48 +0,0 @@ -package channel - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/keeper" - "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" -) - -// InitGenesis initializes the ibc channel submodule's state from a provided genesis -// state. -func InitGenesis(ctx sdk.Context, k keeper.Keeper, gs types.GenesisState) { - for _, channel := range gs.Channels { - ch := types.NewChannel(channel.State, channel.Ordering, channel.Counterparty, channel.ConnectionHops, channel.Version) - k.SetChannel(ctx, channel.PortId, channel.ChannelId, ch) - } - for _, ack := range gs.Acknowledgements { - k.SetPacketAcknowledgement(ctx, ack.PortId, ack.ChannelId, ack.Sequence, ack.Data) - } - for _, commitment := range gs.Commitments { - k.SetPacketCommitment(ctx, commitment.PortId, commitment.ChannelId, commitment.Sequence, commitment.Data) - } - for _, receipt := range gs.Receipts { - k.SetPacketReceipt(ctx, receipt.PortId, receipt.ChannelId, receipt.Sequence) - } - for _, ss := range gs.SendSequences { - k.SetNextSequenceSend(ctx, ss.PortId, ss.ChannelId, ss.Sequence) - } - for _, rs := range gs.RecvSequences { - k.SetNextSequenceRecv(ctx, rs.PortId, rs.ChannelId, rs.Sequence) - } - for _, as := range gs.AckSequences { - k.SetNextSequenceAck(ctx, as.PortId, as.ChannelId, as.Sequence) - } - k.SetNextChannelSequence(ctx, gs.NextChannelSequence) -} - -// ExportGenesis returns the ibc channel submodule's exported genesis. -func ExportGenesis(ctx sdk.Context, k keeper.Keeper) types.GenesisState { - return types.GenesisState{ - Channels: k.GetAllChannels(ctx), - Acknowledgements: k.GetAllPacketAcks(ctx), - Commitments: k.GetAllPacketCommitments(ctx), - Receipts: k.GetAllPacketReceipts(ctx), - SendSequences: k.GetAllPacketSendSeqs(ctx), - RecvSequences: k.GetAllPacketRecvSeqs(ctx), - AckSequences: k.GetAllPacketAckSeqs(ctx), - } -} diff --git a/x/ibc/core/04-channel/handler.go b/x/ibc/core/04-channel/handler.go deleted file mode 100644 index 375c35263ec1..000000000000 --- a/x/ibc/core/04-channel/handler.go +++ /dev/null @@ -1,186 +0,0 @@ -package channel - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/keeper" - "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" -) - -// HandleMsgChannelOpenInit defines the sdk.Handler for MsgChannelOpenInit -func HandleMsgChannelOpenInit(ctx sdk.Context, k keeper.Keeper, portCap *capabilitytypes.Capability, msg *types.MsgChannelOpenInit) (*sdk.Result, string, *capabilitytypes.Capability, error) { - channelID, capKey, err := k.ChanOpenInit( - ctx, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.PortId, - portCap, msg.Channel.Counterparty, msg.Channel.Version, - ) - if err != nil { - return nil, "", nil, sdkerrors.Wrap(err, "channel handshake open init failed") - } - - ctx.EventManager().EmitEvents(sdk.Events{ - sdk.NewEvent( - types.EventTypeChannelOpenInit, - sdk.NewAttribute(types.AttributeKeyPortID, msg.PortId), - sdk.NewAttribute(types.AttributeKeyChannelID, channelID), - sdk.NewAttribute(types.AttributeCounterpartyPortID, msg.Channel.Counterparty.PortId), - sdk.NewAttribute(types.AttributeCounterpartyChannelID, msg.Channel.Counterparty.ChannelId), - sdk.NewAttribute(types.AttributeKeyConnectionID, msg.Channel.ConnectionHops[0]), - ), - sdk.NewEvent( - sdk.EventTypeMessage, - sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), - ), - }) - - return &sdk.Result{ - Events: ctx.EventManager().Events().ToABCIEvents(), - }, channelID, capKey, nil -} - -// HandleMsgChannelOpenTry defines the sdk.Handler for MsgChannelOpenTry -func HandleMsgChannelOpenTry(ctx sdk.Context, k keeper.Keeper, portCap *capabilitytypes.Capability, msg *types.MsgChannelOpenTry) (*sdk.Result, string, *capabilitytypes.Capability, error) { - channelID, capKey, err := k.ChanOpenTry(ctx, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.PortId, msg.PreviousChannelId, - portCap, msg.Channel.Counterparty, msg.Channel.Version, msg.CounterpartyVersion, msg.ProofInit, msg.ProofHeight, - ) - if err != nil { - return nil, "", nil, sdkerrors.Wrap(err, "channel handshake open try failed") - } - - ctx.EventManager().EmitEvents(sdk.Events{ - sdk.NewEvent( - types.EventTypeChannelOpenTry, - sdk.NewAttribute(types.AttributeKeyPortID, msg.PortId), - sdk.NewAttribute(types.AttributeKeyChannelID, channelID), - sdk.NewAttribute(types.AttributeCounterpartyPortID, msg.Channel.Counterparty.PortId), - sdk.NewAttribute(types.AttributeCounterpartyChannelID, msg.Channel.Counterparty.ChannelId), - sdk.NewAttribute(types.AttributeKeyConnectionID, msg.Channel.ConnectionHops[0]), - ), - sdk.NewEvent( - sdk.EventTypeMessage, - sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), - ), - }) - - return &sdk.Result{ - Events: ctx.EventManager().Events().ToABCIEvents(), - }, channelID, capKey, nil -} - -// HandleMsgChannelOpenAck defines the sdk.Handler for MsgChannelOpenAck -func HandleMsgChannelOpenAck(ctx sdk.Context, k keeper.Keeper, channelCap *capabilitytypes.Capability, msg *types.MsgChannelOpenAck) (*sdk.Result, error) { - err := k.ChanOpenAck( - ctx, msg.PortId, msg.ChannelId, channelCap, msg.CounterpartyVersion, msg.CounterpartyChannelId, msg.ProofTry, msg.ProofHeight, - ) - if err != nil { - return nil, sdkerrors.Wrap(err, "channel handshake open ack failed") - } - - channel, _ := k.GetChannel(ctx, msg.PortId, msg.ChannelId) - - ctx.EventManager().EmitEvents(sdk.Events{ - sdk.NewEvent( - types.EventTypeChannelOpenAck, - sdk.NewAttribute(types.AttributeKeyPortID, msg.PortId), - sdk.NewAttribute(types.AttributeKeyChannelID, msg.ChannelId), - sdk.NewAttribute(types.AttributeCounterpartyPortID, channel.Counterparty.PortId), - sdk.NewAttribute(types.AttributeCounterpartyChannelID, channel.Counterparty.ChannelId), - sdk.NewAttribute(types.AttributeKeyConnectionID, channel.ConnectionHops[0]), - ), - sdk.NewEvent( - sdk.EventTypeMessage, - sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), - ), - }) - - return &sdk.Result{ - Events: ctx.EventManager().Events().ToABCIEvents(), - }, nil -} - -// HandleMsgChannelOpenConfirm defines the sdk.Handler for MsgChannelOpenConfirm -func HandleMsgChannelOpenConfirm(ctx sdk.Context, k keeper.Keeper, channelCap *capabilitytypes.Capability, msg *types.MsgChannelOpenConfirm) (*sdk.Result, error) { - err := k.ChanOpenConfirm(ctx, msg.PortId, msg.ChannelId, channelCap, msg.ProofAck, msg.ProofHeight) - if err != nil { - return nil, sdkerrors.Wrap(err, "channel handshake open confirm failed") - } - - channel, _ := k.GetChannel(ctx, msg.PortId, msg.ChannelId) - - ctx.EventManager().EmitEvents(sdk.Events{ - sdk.NewEvent( - types.EventTypeChannelOpenConfirm, - sdk.NewAttribute(types.AttributeKeyPortID, msg.PortId), - sdk.NewAttribute(types.AttributeKeyChannelID, msg.ChannelId), - sdk.NewAttribute(types.AttributeCounterpartyPortID, channel.Counterparty.PortId), - sdk.NewAttribute(types.AttributeCounterpartyChannelID, channel.Counterparty.ChannelId), - sdk.NewAttribute(types.AttributeKeyConnectionID, channel.ConnectionHops[0]), - ), - sdk.NewEvent( - sdk.EventTypeMessage, - sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), - ), - }) - - return &sdk.Result{ - Events: ctx.EventManager().Events().ToABCIEvents(), - }, nil -} - -// HandleMsgChannelCloseInit defines the sdk.Handler for MsgChannelCloseInit -func HandleMsgChannelCloseInit(ctx sdk.Context, k keeper.Keeper, channelCap *capabilitytypes.Capability, msg *types.MsgChannelCloseInit) (*sdk.Result, error) { - err := k.ChanCloseInit(ctx, msg.PortId, msg.ChannelId, channelCap) - if err != nil { - return nil, sdkerrors.Wrap(err, "channel handshake close init failed") - } - - channel, _ := k.GetChannel(ctx, msg.PortId, msg.ChannelId) - - ctx.EventManager().EmitEvents(sdk.Events{ - sdk.NewEvent( - types.EventTypeChannelCloseInit, - sdk.NewAttribute(types.AttributeKeyPortID, msg.PortId), - sdk.NewAttribute(types.AttributeKeyChannelID, msg.ChannelId), - sdk.NewAttribute(types.AttributeCounterpartyPortID, channel.Counterparty.PortId), - sdk.NewAttribute(types.AttributeCounterpartyChannelID, channel.Counterparty.ChannelId), - sdk.NewAttribute(types.AttributeKeyConnectionID, channel.ConnectionHops[0]), - ), - sdk.NewEvent( - sdk.EventTypeMessage, - sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), - ), - }) - - return &sdk.Result{ - Events: ctx.EventManager().Events().ToABCIEvents(), - }, nil -} - -// HandleMsgChannelCloseConfirm defines the sdk.Handler for MsgChannelCloseConfirm -func HandleMsgChannelCloseConfirm(ctx sdk.Context, k keeper.Keeper, channelCap *capabilitytypes.Capability, msg *types.MsgChannelCloseConfirm) (*sdk.Result, error) { - err := k.ChanCloseConfirm(ctx, msg.PortId, msg.ChannelId, channelCap, msg.ProofInit, msg.ProofHeight) - if err != nil { - return nil, sdkerrors.Wrap(err, "channel handshake close confirm failed") - } - - channel, _ := k.GetChannel(ctx, msg.PortId, msg.ChannelId) - - ctx.EventManager().EmitEvents(sdk.Events{ - sdk.NewEvent( - types.EventTypeChannelCloseConfirm, - sdk.NewAttribute(types.AttributeKeyPortID, msg.PortId), - sdk.NewAttribute(types.AttributeKeyChannelID, msg.ChannelId), - sdk.NewAttribute(types.AttributeCounterpartyPortID, channel.Counterparty.PortId), - sdk.NewAttribute(types.AttributeCounterpartyChannelID, channel.Counterparty.ChannelId), - sdk.NewAttribute(types.AttributeKeyConnectionID, channel.ConnectionHops[0]), - ), - sdk.NewEvent( - sdk.EventTypeMessage, - sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), - ), - }) - - return &sdk.Result{ - Events: ctx.EventManager().Events().ToABCIEvents(), - }, nil -} diff --git a/x/ibc/core/04-channel/keeper/grpc_query.go b/x/ibc/core/04-channel/keeper/grpc_query.go deleted file mode 100644 index 30df0a33ace5..000000000000 --- a/x/ibc/core/04-channel/keeper/grpc_query.go +++ /dev/null @@ -1,486 +0,0 @@ -package keeper - -import ( - "context" - "strconv" - "strings" - - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - - "github.com/cosmos/cosmos-sdk/store/prefix" - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/cosmos/cosmos-sdk/types/query" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" -) - -var _ types.QueryServer = (*Keeper)(nil) - -// Channel implements the Query/Channel gRPC method -func (q Keeper) Channel(c context.Context, req *types.QueryChannelRequest) (*types.QueryChannelResponse, error) { - if req == nil { - return nil, status.Error(codes.InvalidArgument, "empty request") - } - - if err := validategRPCRequest(req.PortId, req.ChannelId); err != nil { - return nil, err - } - - ctx := sdk.UnwrapSDKContext(c) - channel, found := q.GetChannel(ctx, req.PortId, req.ChannelId) - if !found { - return nil, status.Error( - codes.NotFound, - sdkerrors.Wrapf(types.ErrChannelNotFound, "port-id: %s, channel-id %s", req.PortId, req.ChannelId).Error(), - ) - } - - selfHeight := clienttypes.GetSelfHeight(ctx) - return types.NewQueryChannelResponse(channel, nil, selfHeight), nil -} - -// Channels implements the Query/Channels gRPC method -func (q Keeper) Channels(c context.Context, req *types.QueryChannelsRequest) (*types.QueryChannelsResponse, error) { - if req == nil { - return nil, status.Error(codes.InvalidArgument, "empty request") - } - - ctx := sdk.UnwrapSDKContext(c) - - channels := []*types.IdentifiedChannel{} - store := prefix.NewStore(ctx.KVStore(q.storeKey), []byte(host.KeyChannelEndPrefix)) - - pageRes, err := query.Paginate(store, req.Pagination, func(key, value []byte) error { - var result types.Channel - if err := q.cdc.UnmarshalBinaryBare(value, &result); err != nil { - return err - } - - portID, channelID, err := host.ParseChannelPath(string(key)) - if err != nil { - return err - } - - identifiedChannel := types.NewIdentifiedChannel(portID, channelID, result) - channels = append(channels, &identifiedChannel) - return nil - }) - - if err != nil { - return nil, err - } - - selfHeight := clienttypes.GetSelfHeight(ctx) - return &types.QueryChannelsResponse{ - Channels: channels, - Pagination: pageRes, - Height: selfHeight, - }, nil -} - -// ConnectionChannels implements the Query/ConnectionChannels gRPC method -func (q Keeper) ConnectionChannels(c context.Context, req *types.QueryConnectionChannelsRequest) (*types.QueryConnectionChannelsResponse, error) { - if req == nil { - return nil, status.Error(codes.InvalidArgument, "empty request") - } - - if err := host.ConnectionIdentifierValidator(req.Connection); err != nil { - return nil, status.Error(codes.InvalidArgument, err.Error()) - } - - ctx := sdk.UnwrapSDKContext(c) - - channels := []*types.IdentifiedChannel{} - store := prefix.NewStore(ctx.KVStore(q.storeKey), []byte(host.KeyChannelEndPrefix)) - - pageRes, err := query.Paginate(store, req.Pagination, func(key, value []byte) error { - var result types.Channel - if err := q.cdc.UnmarshalBinaryBare(value, &result); err != nil { - return err - } - - // ignore channel and continue to the next item if the connection is - // different than the requested one - if result.ConnectionHops[0] != req.Connection { - return nil - } - - portID, channelID, err := host.ParseChannelPath(string(key)) - if err != nil { - return err - } - - identifiedChannel := types.NewIdentifiedChannel(portID, channelID, result) - channels = append(channels, &identifiedChannel) - return nil - }) - - if err != nil { - return nil, err - } - - selfHeight := clienttypes.GetSelfHeight(ctx) - return &types.QueryConnectionChannelsResponse{ - Channels: channels, - Pagination: pageRes, - Height: selfHeight, - }, nil -} - -// ChannelClientState implements the Query/ChannelClientState gRPC method -func (q Keeper) ChannelClientState(c context.Context, req *types.QueryChannelClientStateRequest) (*types.QueryChannelClientStateResponse, error) { - if req == nil { - return nil, status.Error(codes.InvalidArgument, "empty request") - } - - if err := validategRPCRequest(req.PortId, req.ChannelId); err != nil { - return nil, err - } - - ctx := sdk.UnwrapSDKContext(c) - - clientID, clientState, err := q.GetChannelClientState(ctx, req.PortId, req.ChannelId) - if err != nil { - return nil, status.Error(codes.NotFound, err.Error()) - } - - identifiedClientState := clienttypes.NewIdentifiedClientState(clientID, clientState) - - selfHeight := clienttypes.GetSelfHeight(ctx) - return types.NewQueryChannelClientStateResponse(identifiedClientState, nil, selfHeight), nil -} - -// ChannelConsensusState implements the Query/ChannelConsensusState gRPC method -func (q Keeper) ChannelConsensusState(c context.Context, req *types.QueryChannelConsensusStateRequest) (*types.QueryChannelConsensusStateResponse, error) { - if req == nil { - return nil, status.Error(codes.InvalidArgument, "empty request") - } - - if err := validategRPCRequest(req.PortId, req.ChannelId); err != nil { - return nil, err - } - - ctx := sdk.UnwrapSDKContext(c) - - channel, found := q.GetChannel(ctx, req.PortId, req.ChannelId) - if !found { - return nil, status.Error( - codes.NotFound, - sdkerrors.Wrapf(types.ErrChannelNotFound, "port-id: %s, channel-id %s", req.PortId, req.ChannelId).Error(), - ) - } - - connection, found := q.connectionKeeper.GetConnection(ctx, channel.ConnectionHops[0]) - if !found { - return nil, status.Error( - codes.NotFound, - sdkerrors.Wrapf(connectiontypes.ErrConnectionNotFound, "connection-id: %s", channel.ConnectionHops[0]).Error(), - ) - } - - consHeight := clienttypes.NewHeight(req.RevisionNumber, req.RevisionHeight) - consensusState, found := q.clientKeeper.GetClientConsensusState(ctx, connection.ClientId, consHeight) - if !found { - return nil, status.Error( - codes.NotFound, - sdkerrors.Wrapf(clienttypes.ErrConsensusStateNotFound, "client-id: %s", connection.ClientId).Error(), - ) - } - - anyConsensusState, err := clienttypes.PackConsensusState(consensusState) - if err != nil { - return nil, status.Error(codes.Internal, err.Error()) - } - - selfHeight := clienttypes.GetSelfHeight(ctx) - return types.NewQueryChannelConsensusStateResponse(connection.ClientId, anyConsensusState, consHeight, nil, selfHeight), nil -} - -// PacketCommitment implements the Query/PacketCommitment gRPC method -func (q Keeper) PacketCommitment(c context.Context, req *types.QueryPacketCommitmentRequest) (*types.QueryPacketCommitmentResponse, error) { - if req == nil { - return nil, status.Error(codes.InvalidArgument, "empty request") - } - - if err := validategRPCRequest(req.PortId, req.ChannelId); err != nil { - return nil, err - } - - if req.Sequence == 0 { - return nil, status.Error(codes.InvalidArgument, "packet sequence cannot be 0") - } - - ctx := sdk.UnwrapSDKContext(c) - - commitmentBz := q.GetPacketCommitment(ctx, req.PortId, req.ChannelId, req.Sequence) - if len(commitmentBz) == 0 { - return nil, status.Error(codes.NotFound, "packet commitment hash not found") - } - - selfHeight := clienttypes.GetSelfHeight(ctx) - return types.NewQueryPacketCommitmentResponse(commitmentBz, nil, selfHeight), nil -} - -// PacketCommitments implements the Query/PacketCommitments gRPC method -func (q Keeper) PacketCommitments(c context.Context, req *types.QueryPacketCommitmentsRequest) (*types.QueryPacketCommitmentsResponse, error) { - if req == nil { - return nil, status.Error(codes.InvalidArgument, "empty request") - } - - if err := validategRPCRequest(req.PortId, req.ChannelId); err != nil { - return nil, err - } - - ctx := sdk.UnwrapSDKContext(c) - - commitments := []*types.PacketState{} - store := prefix.NewStore(ctx.KVStore(q.storeKey), []byte(host.PacketCommitmentPrefixPath(req.PortId, req.ChannelId))) - - pageRes, err := query.Paginate(store, req.Pagination, func(key, value []byte) error { - keySplit := strings.Split(string(key), "/") - - sequence, err := strconv.ParseUint(keySplit[len(keySplit)-1], 10, 64) - if err != nil { - return err - } - - commitment := types.NewPacketState(req.PortId, req.ChannelId, sequence, value) - commitments = append(commitments, &commitment) - return nil - }) - - if err != nil { - return nil, err - } - - selfHeight := clienttypes.GetSelfHeight(ctx) - return &types.QueryPacketCommitmentsResponse{ - Commitments: commitments, - Pagination: pageRes, - Height: selfHeight, - }, nil -} - -// PacketReceipt implements the Query/PacketReceipt gRPC method -func (q Keeper) PacketReceipt(c context.Context, req *types.QueryPacketReceiptRequest) (*types.QueryPacketReceiptResponse, error) { - if req == nil { - return nil, status.Error(codes.InvalidArgument, "empty request") - } - - if err := validategRPCRequest(req.PortId, req.ChannelId); err != nil { - return nil, err - } - - if req.Sequence == 0 { - return nil, status.Error(codes.InvalidArgument, "packet sequence cannot be 0") - } - - ctx := sdk.UnwrapSDKContext(c) - - _, recvd := q.GetPacketReceipt(ctx, req.PortId, req.ChannelId, req.Sequence) - - selfHeight := clienttypes.GetSelfHeight(ctx) - return types.NewQueryPacketReceiptResponse(recvd, nil, selfHeight), nil -} - -// PacketAcknowledgement implements the Query/PacketAcknowledgement gRPC method -func (q Keeper) PacketAcknowledgement(c context.Context, req *types.QueryPacketAcknowledgementRequest) (*types.QueryPacketAcknowledgementResponse, error) { - if req == nil { - return nil, status.Error(codes.InvalidArgument, "empty request") - } - - if err := validategRPCRequest(req.PortId, req.ChannelId); err != nil { - return nil, err - } - - if req.Sequence == 0 { - return nil, status.Error(codes.InvalidArgument, "packet sequence cannot be 0") - } - - ctx := sdk.UnwrapSDKContext(c) - - acknowledgementBz, found := q.GetPacketAcknowledgement(ctx, req.PortId, req.ChannelId, req.Sequence) - if !found || len(acknowledgementBz) == 0 { - return nil, status.Error(codes.NotFound, "packet acknowledgement hash not found") - } - - selfHeight := clienttypes.GetSelfHeight(ctx) - return types.NewQueryPacketAcknowledgementResponse(acknowledgementBz, nil, selfHeight), nil -} - -// PacketAcknowledgements implements the Query/PacketAcknowledgements gRPC method -func (q Keeper) PacketAcknowledgements(c context.Context, req *types.QueryPacketAcknowledgementsRequest) (*types.QueryPacketAcknowledgementsResponse, error) { - if req == nil { - return nil, status.Error(codes.InvalidArgument, "empty request") - } - - if err := validategRPCRequest(req.PortId, req.ChannelId); err != nil { - return nil, err - } - - ctx := sdk.UnwrapSDKContext(c) - - acks := []*types.PacketState{} - store := prefix.NewStore(ctx.KVStore(q.storeKey), []byte(host.PacketAcknowledgementPrefixPath(req.PortId, req.ChannelId))) - - pageRes, err := query.Paginate(store, req.Pagination, func(key, value []byte) error { - keySplit := strings.Split(string(key), "/") - - sequence, err := strconv.ParseUint(keySplit[len(keySplit)-1], 10, 64) - if err != nil { - return err - } - - ack := types.NewPacketState(req.PortId, req.ChannelId, sequence, value) - acks = append(acks, &ack) - return nil - }) - - if err != nil { - return nil, err - } - - selfHeight := clienttypes.GetSelfHeight(ctx) - return &types.QueryPacketAcknowledgementsResponse{ - Acknowledgements: acks, - Pagination: pageRes, - Height: selfHeight, - }, nil -} - -// UnreceivedPackets implements the Query/UnreceivedPackets gRPC method. Given -// a list of counterparty packet commitments, the querier checks if the packet -// has already been received by checking if a receipt exists on this -// chain for the packet sequence. All packets that haven't been received yet -// are returned in the response -// Usage: To use this method correctly, first query all packet commitments on -// the sending chain using the Query/PacketCommitments gRPC method. -// Then input the returned sequences into the QueryUnreceivedPacketsRequest -// and send the request to this Query/UnreceivedPackets on the **receiving** -// chain. This gRPC method will then return the list of packet sequences that -// are yet to be received on the receiving chain. -// -// NOTE: The querier makes the assumption that the provided list of packet -// commitments is correct and will not function properly if the list -// is not up to date. Ideally the query height should equal the latest height -// on the counterparty's client which represents this chain. -func (q Keeper) UnreceivedPackets(c context.Context, req *types.QueryUnreceivedPacketsRequest) (*types.QueryUnreceivedPacketsResponse, error) { - if req == nil { - return nil, status.Error(codes.InvalidArgument, "empty request") - } - - if err := validategRPCRequest(req.PortId, req.ChannelId); err != nil { - return nil, err - } - - ctx := sdk.UnwrapSDKContext(c) - - var unreceivedSequences = []uint64{} - - for i, seq := range req.PacketCommitmentSequences { - if seq == 0 { - return nil, status.Errorf(codes.InvalidArgument, "packet sequence %d cannot be 0", i) - } - - // if packet receipt exists on the receiving chain, then packet has already been received - if _, found := q.GetPacketReceipt(ctx, req.PortId, req.ChannelId, seq); !found { - unreceivedSequences = append(unreceivedSequences, seq) - } - - } - - selfHeight := clienttypes.GetSelfHeight(ctx) - return &types.QueryUnreceivedPacketsResponse{ - Sequences: unreceivedSequences, - Height: selfHeight, - }, nil -} - -// UnreceivedAcks implements the Query/UnreceivedAcks gRPC method. Given -// a list of counterparty packet acknowledgements, the querier checks if the packet -// has already been received by checking if the packet commitment still exists on this -// chain (original sender) for the packet sequence. -// All acknowledgmeents that haven't been received yet are returned in the response. -// Usage: To use this method correctly, first query all packet acknowledgements on -// the original receiving chain (ie the chain that wrote the acks) using the Query/PacketAcknowledgements gRPC method. -// Then input the returned sequences into the QueryUnreceivedAcksRequest -// and send the request to this Query/UnreceivedAcks on the **original sending** -// chain. This gRPC method will then return the list of packet sequences whose -// acknowledgements are already written on the receiving chain but haven't yet -// been received back to the sending chain. -// -// NOTE: The querier makes the assumption that the provided list of packet -// acknowledgements is correct and will not function properly if the list -// is not up to date. Ideally the query height should equal the latest height -// on the counterparty's client which represents this chain. -func (q Keeper) UnreceivedAcks(c context.Context, req *types.QueryUnreceivedAcksRequest) (*types.QueryUnreceivedAcksResponse, error) { - if req == nil { - return nil, status.Error(codes.InvalidArgument, "empty request") - } - - if err := validategRPCRequest(req.PortId, req.ChannelId); err != nil { - return nil, err - } - - ctx := sdk.UnwrapSDKContext(c) - - var unreceivedSequences = []uint64{} - - for i, seq := range req.PacketAckSequences { - if seq == 0 { - return nil, status.Errorf(codes.InvalidArgument, "packet sequence %d cannot be 0", i) - } - - // if packet commitment still exists on the original sending chain, then packet ack has not been received - // since processing the ack will delete the packet commitment - if commitment := q.GetPacketCommitment(ctx, req.PortId, req.ChannelId, seq); len(commitment) != 0 { - unreceivedSequences = append(unreceivedSequences, seq) - } - - } - - selfHeight := clienttypes.GetSelfHeight(ctx) - return &types.QueryUnreceivedAcksResponse{ - Sequences: unreceivedSequences, - Height: selfHeight, - }, nil -} - -// NextSequenceReceive implements the Query/NextSequenceReceive gRPC method -func (q Keeper) NextSequenceReceive(c context.Context, req *types.QueryNextSequenceReceiveRequest) (*types.QueryNextSequenceReceiveResponse, error) { - if req == nil { - return nil, status.Error(codes.InvalidArgument, "empty request") - } - - if err := validategRPCRequest(req.PortId, req.ChannelId); err != nil { - return nil, err - } - - ctx := sdk.UnwrapSDKContext(c) - sequence, found := q.GetNextSequenceRecv(ctx, req.PortId, req.ChannelId) - if !found { - return nil, status.Error( - codes.NotFound, - sdkerrors.Wrapf(types.ErrSequenceReceiveNotFound, "port-id: %s, channel-id %s", req.PortId, req.ChannelId).Error(), - ) - } - - selfHeight := clienttypes.GetSelfHeight(ctx) - return types.NewQueryNextSequenceReceiveResponse(sequence, nil, selfHeight), nil -} - -func validategRPCRequest(portID, channelID string) error { - if err := host.PortIdentifierValidator(portID); err != nil { - return status.Error(codes.InvalidArgument, err.Error()) - } - - if err := host.ChannelIdentifierValidator(channelID); err != nil { - return status.Error(codes.InvalidArgument, err.Error()) - } - - return nil -} diff --git a/x/ibc/core/04-channel/keeper/grpc_query_test.go b/x/ibc/core/04-channel/keeper/grpc_query_test.go deleted file mode 100644 index 689c241c7b8b..000000000000 --- a/x/ibc/core/04-channel/keeper/grpc_query_test.go +++ /dev/null @@ -1,1376 +0,0 @@ -package keeper_test - -import ( - "fmt" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/query" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" -) - -func (suite *KeeperTestSuite) TestQueryChannel() { - var ( - req *types.QueryChannelRequest - expChannel types.Channel - ) - - testCases := []struct { - msg string - malleate func() - expPass bool - }{ - { - "empty request", - func() { - req = nil - }, - false, - }, - { - "invalid port ID", - func() { - req = &types.QueryChannelRequest{ - PortId: "", - ChannelId: "test-channel-id", - } - }, - false, - }, - { - "invalid channel ID", - func() { - req = &types.QueryChannelRequest{ - PortId: "test-port-id", - ChannelId: "", - } - }, - false, - }, - {"channel not found", - func() { - req = &types.QueryChannelRequest{ - PortId: "test-port-id", - ChannelId: "test-channel-id", - } - }, - false, - }, - { - "success", - func() { - _, _, connA, connB := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - // init channel - channelA, _, err := suite.coordinator.ChanOpenInit(suite.chainA, suite.chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, types.ORDERED) - suite.Require().NoError(err) - - expChannel = suite.chainA.GetChannel(channelA) - - req = &types.QueryChannelRequest{ - PortId: channelA.PortID, - ChannelId: channelA.ID, - } - }, - true, - }, - } - - for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { - suite.SetupTest() // reset - - tc.malleate() - ctx := sdk.WrapSDKContext(suite.chainA.GetContext()) - - res, err := suite.chainA.QueryServer.Channel(ctx, req) - - if tc.expPass { - suite.Require().NoError(err) - suite.Require().NotNil(res) - suite.Require().Equal(&expChannel, res.Channel) - } else { - suite.Require().Error(err) - } - }) - } -} - -func (suite *KeeperTestSuite) TestQueryChannels() { - var ( - req *types.QueryChannelsRequest - expChannels = []*types.IdentifiedChannel{} - ) - - testCases := []struct { - msg string - malleate func() - expPass bool - }{ - { - "empty request", - func() { - req = nil - }, - false, - }, - { - "empty pagination", - func() { - req = &types.QueryChannelsRequest{} - }, - true, - }, - { - "success", - func() { - _, _, connA0, connB0, testchannel0, _ := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - // channel0 on first connection on chainA - counterparty0 := types.Counterparty{ - PortId: connB0.Channels[0].PortID, - ChannelId: connB0.Channels[0].ID, - } - - // channel1 is second channel on first connection on chainA - testchannel1, _ := suite.coordinator.CreateMockChannels(suite.chainA, suite.chainB, connA0, connB0, types.ORDERED) - counterparty1 := types.Counterparty{ - PortId: connB0.Channels[1].PortID, - ChannelId: connB0.Channels[1].ID, - } - - channel0 := types.NewChannel( - types.OPEN, types.UNORDERED, - counterparty0, []string{connA0.ID}, testchannel0.Version, - ) - channel1 := types.NewChannel( - types.OPEN, types.ORDERED, - counterparty1, []string{connA0.ID}, testchannel1.Version, - ) - - idCh0 := types.NewIdentifiedChannel(testchannel0.PortID, testchannel0.ID, channel0) - idCh1 := types.NewIdentifiedChannel(testchannel1.PortID, testchannel1.ID, channel1) - - expChannels = []*types.IdentifiedChannel{&idCh0, &idCh1} - - req = &types.QueryChannelsRequest{ - Pagination: &query.PageRequest{ - Key: nil, - Limit: 2, - 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.chainA.GetContext()) - - res, err := suite.chainA.QueryServer.Channels(ctx, req) - - if tc.expPass { - suite.Require().NoError(err) - suite.Require().NotNil(res) - suite.Require().Equal(expChannels, res.Channels) - suite.Require().Equal(len(expChannels), int(res.Pagination.Total)) - } else { - suite.Require().Error(err) - } - }) - } -} - -func (suite *KeeperTestSuite) TestQueryConnectionChannels() { - var ( - req *types.QueryConnectionChannelsRequest - expChannels = []*types.IdentifiedChannel{} - ) - - testCases := []struct { - msg string - malleate func() - expPass bool - }{ - { - "empty request", - func() { - req = nil - }, - false, - }, - { - "invalid connection ID", - func() { - req = &types.QueryConnectionChannelsRequest{ - Connection: "", - } - }, - false, - }, - { - "success", - func() { - _, _, connA0, connB0, testchannel0, _ := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - // channel0 on first connection on chainA - counterparty0 := types.Counterparty{ - PortId: connB0.Channels[0].PortID, - ChannelId: connB0.Channels[0].ID, - } - - // channel1 is second channel on first connection on chainA - testchannel1, _ := suite.coordinator.CreateMockChannels(suite.chainA, suite.chainB, connA0, connB0, types.ORDERED) - counterparty1 := types.Counterparty{ - PortId: connB0.Channels[1].PortID, - ChannelId: connB0.Channels[1].ID, - } - - channel0 := types.NewChannel( - types.OPEN, types.UNORDERED, - counterparty0, []string{connA0.ID}, testchannel0.Version, - ) - channel1 := types.NewChannel( - types.OPEN, types.ORDERED, - counterparty1, []string{connA0.ID}, testchannel1.Version, - ) - - idCh0 := types.NewIdentifiedChannel(testchannel0.PortID, testchannel0.ID, channel0) - idCh1 := types.NewIdentifiedChannel(testchannel1.PortID, testchannel1.ID, channel1) - - expChannels = []*types.IdentifiedChannel{&idCh0, &idCh1} - - req = &types.QueryConnectionChannelsRequest{ - Connection: connA0.ID, - Pagination: &query.PageRequest{ - Key: nil, - Limit: 2, - CountTotal: true, - }, - } - }, - true, - }, - { - "success, empty response", - func() { - suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - expChannels = []*types.IdentifiedChannel{} - req = &types.QueryConnectionChannelsRequest{ - Connection: "externalConnID", - Pagination: &query.PageRequest{ - Key: nil, - Limit: 2, - CountTotal: false, - }, - } - }, - true, - }, - } - - for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { - suite.SetupTest() // reset - - tc.malleate() - ctx := sdk.WrapSDKContext(suite.chainA.GetContext()) - - res, err := suite.chainA.QueryServer.ConnectionChannels(ctx, req) - - if tc.expPass { - suite.Require().NoError(err) - suite.Require().NotNil(res) - suite.Require().Equal(expChannels, res.Channels) - } else { - suite.Require().Error(err) - } - }) - } -} - -func (suite *KeeperTestSuite) TestQueryChannelClientState() { - var ( - req *types.QueryChannelClientStateRequest - expIdentifiedClientState clienttypes.IdentifiedClientState - ) - - testCases := []struct { - msg string - malleate func() - expPass bool - }{ - { - "empty request", - func() { - req = nil - }, - false, - }, - { - "invalid port ID", - func() { - req = &types.QueryChannelClientStateRequest{ - PortId: "", - ChannelId: "test-channel-id", - } - }, - false, - }, - { - "invalid channel ID", - func() { - req = &types.QueryChannelClientStateRequest{ - PortId: "test-port-id", - ChannelId: "", - } - }, - false, - }, - { - "channel not found", - func() { - req = &types.QueryChannelClientStateRequest{ - PortId: "test-port-id", - ChannelId: "test-channel-id", - } - }, - false, - }, - { - "connection not found", - func() { - _, _, _, _, channelA, _ := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - - channel := suite.chainA.GetChannel(channelA) - // update channel to reference a connection that does not exist - channel.ConnectionHops[0] = "doesnotexist" - - // set connection hops to wrong connection ID - suite.chainA.App.IBCKeeper.ChannelKeeper.SetChannel(suite.chainA.GetContext(), channelA.PortID, channelA.ID, channel) - - req = &types.QueryChannelClientStateRequest{ - PortId: channelA.PortID, - ChannelId: channelA.ID, - } - }, false, - }, - { - "client state for channel's connection not found", - func() { - _, _, connA, _, channelA, _ := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - - // set connection to empty so clientID is empty - suite.chainA.App.IBCKeeper.ConnectionKeeper.SetConnection(suite.chainA.GetContext(), connA.ID, connectiontypes.ConnectionEnd{}) - - req = &types.QueryChannelClientStateRequest{ - PortId: channelA.PortID, - ChannelId: channelA.ID, - } - }, false, - }, - { - "success", - func() { - clientA, _, connA, connB := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - // init channel - channelA, _, err := suite.coordinator.ChanOpenInit(suite.chainA, suite.chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, types.ORDERED) - suite.Require().NoError(err) - - expClientState := suite.chainA.GetClientState(clientA) - expIdentifiedClientState = clienttypes.NewIdentifiedClientState(clientA, expClientState) - - req = &types.QueryChannelClientStateRequest{ - PortId: channelA.PortID, - ChannelId: channelA.ID, - } - }, - true, - }, - } - - for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { - suite.SetupTest() // reset - - tc.malleate() - ctx := sdk.WrapSDKContext(suite.chainA.GetContext()) - - res, err := suite.chainA.QueryServer.ChannelClientState(ctx, req) - - if tc.expPass { - 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) - } - }) - } -} - -func (suite *KeeperTestSuite) TestQueryChannelConsensusState() { - var ( - req *types.QueryChannelConsensusStateRequest - expConsensusState exported.ConsensusState - expClientID string - ) - - testCases := []struct { - msg string - malleate func() - expPass bool - }{ - { - "empty request", - func() { - req = nil - }, - false, - }, - { - "invalid port ID", - func() { - req = &types.QueryChannelConsensusStateRequest{ - PortId: "", - ChannelId: "test-channel-id", - RevisionNumber: 0, - RevisionHeight: 1, - } - }, - false, - }, - { - "invalid channel ID", - func() { - req = &types.QueryChannelConsensusStateRequest{ - PortId: "test-port-id", - ChannelId: "", - RevisionNumber: 0, - RevisionHeight: 1, - } - }, - false, - }, - { - "channel not found", - func() { - req = &types.QueryChannelConsensusStateRequest{ - PortId: "test-port-id", - ChannelId: "test-channel-id", - RevisionNumber: 0, - RevisionHeight: 1, - } - }, - false, - }, - { - "connection not found", - func() { - _, _, _, _, channelA, _ := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - - channel := suite.chainA.GetChannel(channelA) - // update channel to reference a connection that does not exist - channel.ConnectionHops[0] = "doesnotexist" - - // set connection hops to wrong connection ID - suite.chainA.App.IBCKeeper.ChannelKeeper.SetChannel(suite.chainA.GetContext(), channelA.PortID, channelA.ID, channel) - - req = &types.QueryChannelConsensusStateRequest{ - PortId: channelA.PortID, - ChannelId: channelA.ID, - RevisionNumber: 0, - RevisionHeight: 1, - } - }, false, - }, - { - "consensus state for channel's connection not found", - func() { - _, _, _, _, channelA, _ := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - - req = &types.QueryChannelConsensusStateRequest{ - PortId: channelA.PortID, - ChannelId: channelA.ID, - RevisionNumber: 0, - RevisionHeight: uint64(suite.chainA.GetContext().BlockHeight()), // use current height - } - }, false, - }, - { - "success", - func() { - clientA, _, connA, connB := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - // init channel - channelA, _, err := suite.coordinator.ChanOpenInit(suite.chainA, suite.chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, types.ORDERED) - suite.Require().NoError(err) - - clientState := suite.chainA.GetClientState(clientA) - expConsensusState, _ = suite.chainA.GetConsensusState(clientA, clientState.GetLatestHeight()) - suite.Require().NotNil(expConsensusState) - expClientID = clientA - - req = &types.QueryChannelConsensusStateRequest{ - PortId: channelA.PortID, - ChannelId: channelA.ID, - RevisionNumber: clientState.GetLatestHeight().GetRevisionNumber(), - RevisionHeight: clientState.GetLatestHeight().GetRevisionHeight(), - } - }, - true, - }, - } - - for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { - suite.SetupTest() // reset - - tc.malleate() - ctx := sdk.WrapSDKContext(suite.chainA.GetContext()) - - res, err := suite.chainA.QueryServer.ChannelConsensusState(ctx, req) - - if tc.expPass { - suite.Require().NoError(err) - suite.Require().NotNil(res) - consensusState, err := clienttypes.UnpackConsensusState(res.ConsensusState) - 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) - } - }) - } -} - -func (suite *KeeperTestSuite) TestQueryPacketCommitment() { - var ( - req *types.QueryPacketCommitmentRequest - expCommitment []byte - ) - - testCases := []struct { - msg string - malleate func() - expPass bool - }{ - { - "empty request", - func() { - req = nil - }, - false, - }, - { - "invalid port ID", - func() { - req = &types.QueryPacketCommitmentRequest{ - PortId: "", - ChannelId: "test-channel-id", - Sequence: 0, - } - }, - false, - }, - { - "invalid channel ID", - func() { - req = &types.QueryPacketCommitmentRequest{ - PortId: "test-port-id", - ChannelId: "", - Sequence: 0, - } - }, - false, - }, - {"invalid sequence", - func() { - req = &types.QueryPacketCommitmentRequest{ - PortId: "test-port-id", - ChannelId: "test-channel-id", - Sequence: 0, - } - }, - false, - }, - {"channel not found", - func() { - req = &types.QueryPacketCommitmentRequest{ - PortId: "test-port-id", - ChannelId: "test-channel-id", - Sequence: 1, - } - }, - false, - }, - { - "success", - func() { - _, _, _, _, channelA, _ := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - expCommitment = []byte("hash") - suite.chainA.App.IBCKeeper.ChannelKeeper.SetPacketCommitment(suite.chainA.GetContext(), channelA.PortID, channelA.ID, 1, expCommitment) - - req = &types.QueryPacketCommitmentRequest{ - PortId: channelA.PortID, - ChannelId: channelA.ID, - Sequence: 1, - } - }, - true, - }, - } - - for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { - suite.SetupTest() // reset - - tc.malleate() - ctx := sdk.WrapSDKContext(suite.chainA.GetContext()) - - res, err := suite.chainA.QueryServer.PacketCommitment(ctx, req) - - if tc.expPass { - suite.Require().NoError(err) - suite.Require().NotNil(res) - suite.Require().Equal(expCommitment, res.Commitment) - } else { - suite.Require().Error(err) - } - }) - } -} - -func (suite *KeeperTestSuite) TestQueryPacketCommitments() { - var ( - req *types.QueryPacketCommitmentsRequest - expCommitments = []*types.PacketState{} - ) - - testCases := []struct { - msg string - malleate func() - expPass bool - }{ - { - "empty request", - func() { - req = nil - }, - false, - }, - { - "invalid ID", - func() { - req = &types.QueryPacketCommitmentsRequest{ - PortId: "", - ChannelId: "test-channel-id", - } - }, - false, - }, - { - "success, empty res", - func() { - expCommitments = []*types.PacketState{} - - req = &types.QueryPacketCommitmentsRequest{ - PortId: "test-port-id", - ChannelId: "test-channel-id", - Pagination: &query.PageRequest{ - Key: nil, - Limit: 2, - CountTotal: true, - }, - } - }, - true, - }, - { - "success", - func() { - _, _, _, _, channelA, _ := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - - expCommitments = make([]*types.PacketState, 9) - - for i := uint64(0); i < 9; i++ { - commitment := types.NewPacketState(channelA.PortID, channelA.ID, i, []byte(fmt.Sprintf("hash_%d", i))) - suite.chainA.App.IBCKeeper.ChannelKeeper.SetPacketCommitment(suite.chainA.GetContext(), commitment.PortId, commitment.ChannelId, commitment.Sequence, commitment.Data) - expCommitments[i] = &commitment - } - - req = &types.QueryPacketCommitmentsRequest{ - PortId: channelA.PortID, - ChannelId: channelA.ID, - Pagination: &query.PageRequest{ - Key: nil, - Limit: 11, - 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.chainA.GetContext()) - - res, err := suite.chainA.QueryServer.PacketCommitments(ctx, req) - - if tc.expPass { - suite.Require().NoError(err) - suite.Require().NotNil(res) - suite.Require().Equal(expCommitments, res.Commitments) - } else { - suite.Require().Error(err) - } - }) - } -} - -func (suite *KeeperTestSuite) TestQueryPacketReceipt() { - var ( - req *types.QueryPacketReceiptRequest - expReceived bool - ) - - testCases := []struct { - msg string - malleate func() - expPass bool - }{ - { - "empty request", - func() { - req = nil - }, - false, - }, - { - "invalid port ID", - func() { - req = &types.QueryPacketReceiptRequest{ - PortId: "", - ChannelId: "test-channel-id", - Sequence: 1, - } - }, - false, - }, - { - "invalid channel ID", - func() { - req = &types.QueryPacketReceiptRequest{ - PortId: "test-port-id", - ChannelId: "", - Sequence: 1, - } - }, - false, - }, - {"invalid sequence", - func() { - req = &types.QueryPacketReceiptRequest{ - PortId: "test-port-id", - ChannelId: "test-channel-id", - Sequence: 0, - } - }, - false, - }, - { - "success: receipt not found", - func() { - _, _, _, _, channelA, _ := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - suite.chainA.App.IBCKeeper.ChannelKeeper.SetPacketReceipt(suite.chainA.GetContext(), channelA.PortID, channelA.ID, 1) - - req = &types.QueryPacketReceiptRequest{ - PortId: channelA.PortID, - ChannelId: channelA.ID, - Sequence: 3, - } - expReceived = false - }, - true, - }, - { - "success: receipt found", - func() { - _, _, _, _, channelA, _ := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - suite.chainA.App.IBCKeeper.ChannelKeeper.SetPacketReceipt(suite.chainA.GetContext(), channelA.PortID, channelA.ID, 1) - - req = &types.QueryPacketReceiptRequest{ - PortId: channelA.PortID, - ChannelId: channelA.ID, - Sequence: 1, - } - expReceived = true - }, - true, - }, - } - - for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { - suite.SetupTest() // reset - - tc.malleate() - ctx := sdk.WrapSDKContext(suite.chainA.GetContext()) - - res, err := suite.chainA.QueryServer.PacketReceipt(ctx, req) - - if tc.expPass { - suite.Require().NoError(err) - suite.Require().NotNil(res) - suite.Require().Equal(expReceived, res.Received) - } else { - suite.Require().Error(err) - } - }) - } -} - -func (suite *KeeperTestSuite) TestQueryPacketAcknowledgement() { - var ( - req *types.QueryPacketAcknowledgementRequest - expAck []byte - ) - - testCases := []struct { - msg string - malleate func() - expPass bool - }{ - { - "empty request", - func() { - req = nil - }, - false, - }, - { - "invalid port ID", - func() { - req = &types.QueryPacketAcknowledgementRequest{ - PortId: "", - ChannelId: "test-channel-id", - Sequence: 0, - } - }, - false, - }, - { - "invalid channel ID", - func() { - req = &types.QueryPacketAcknowledgementRequest{ - PortId: "test-port-id", - ChannelId: "", - Sequence: 0, - } - }, - false, - }, - {"invalid sequence", - func() { - req = &types.QueryPacketAcknowledgementRequest{ - PortId: "test-port-id", - ChannelId: "test-channel-id", - Sequence: 0, - } - }, - false, - }, - {"channel not found", - func() { - req = &types.QueryPacketAcknowledgementRequest{ - PortId: "test-port-id", - ChannelId: "test-channel-id", - Sequence: 1, - } - }, - false, - }, - { - "success", - func() { - _, _, _, _, channelA, _ := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - expAck = []byte("hash") - suite.chainA.App.IBCKeeper.ChannelKeeper.SetPacketAcknowledgement(suite.chainA.GetContext(), channelA.PortID, channelA.ID, 1, expAck) - - req = &types.QueryPacketAcknowledgementRequest{ - PortId: channelA.PortID, - ChannelId: channelA.ID, - Sequence: 1, - } - }, - true, - }, - } - - for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { - suite.SetupTest() // reset - - tc.malleate() - ctx := sdk.WrapSDKContext(suite.chainA.GetContext()) - - res, err := suite.chainA.QueryServer.PacketAcknowledgement(ctx, req) - - if tc.expPass { - suite.Require().NoError(err) - suite.Require().NotNil(res) - suite.Require().Equal(expAck, res.Acknowledgement) - } else { - suite.Require().Error(err) - } - }) - } -} - -func (suite *KeeperTestSuite) TestQueryPacketAcknowledgements() { - var ( - req *types.QueryPacketAcknowledgementsRequest - expAcknowledgements = []*types.PacketState{} - ) - - testCases := []struct { - msg string - malleate func() - expPass bool - }{ - { - "empty request", - func() { - req = nil - }, - false, - }, - { - "invalid ID", - func() { - req = &types.QueryPacketAcknowledgementsRequest{ - PortId: "", - ChannelId: "test-channel-id", - } - }, - false, - }, - { - "success, empty res", - func() { - expAcknowledgements = []*types.PacketState{} - - req = &types.QueryPacketAcknowledgementsRequest{ - PortId: "test-port-id", - ChannelId: "test-channel-id", - Pagination: &query.PageRequest{ - Key: nil, - Limit: 2, - CountTotal: true, - }, - } - }, - true, - }, - { - "success", - func() { - _, _, _, _, channelA, _ := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - - expAcknowledgements = make([]*types.PacketState, 9) - - for i := uint64(0); i < 9; i++ { - ack := types.NewPacketState(channelA.PortID, channelA.ID, i, []byte(fmt.Sprintf("hash_%d", i))) - suite.chainA.App.IBCKeeper.ChannelKeeper.SetPacketAcknowledgement(suite.chainA.GetContext(), ack.PortId, ack.ChannelId, ack.Sequence, ack.Data) - expAcknowledgements[i] = &ack - } - - req = &types.QueryPacketAcknowledgementsRequest{ - PortId: channelA.PortID, - ChannelId: channelA.ID, - Pagination: &query.PageRequest{ - Key: nil, - Limit: 11, - 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.chainA.GetContext()) - - res, err := suite.chainA.QueryServer.PacketAcknowledgements(ctx, req) - - if tc.expPass { - suite.Require().NoError(err) - suite.Require().NotNil(res) - suite.Require().Equal(expAcknowledgements, res.Acknowledgements) - } else { - suite.Require().Error(err) - } - }) - } -} - -func (suite *KeeperTestSuite) TestQueryUnreceivedPackets() { - var ( - req *types.QueryUnreceivedPacketsRequest - expSeq = []uint64{} - ) - - testCases := []struct { - msg string - malleate func() - expPass bool - }{ - { - "empty request", - func() { - req = nil - }, - false, - }, - { - "invalid port ID", - func() { - req = &types.QueryUnreceivedPacketsRequest{ - PortId: "", - ChannelId: "test-channel-id", - } - }, - false, - }, - { - "invalid channel ID", - func() { - req = &types.QueryUnreceivedPacketsRequest{ - PortId: "test-port-id", - ChannelId: "", - } - }, - false, - }, - { - "invalid seq", - func() { - req = &types.QueryUnreceivedPacketsRequest{ - PortId: "test-port-id", - ChannelId: "test-channel-id", - PacketCommitmentSequences: []uint64{0}, - } - }, - false, - }, - { - "basic success unreceived packet commitments", - func() { - _, _, _, _, channelA, _ := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - - // no ack exists - - expSeq = []uint64{1} - req = &types.QueryUnreceivedPacketsRequest{ - PortId: channelA.PortID, - ChannelId: channelA.ID, - PacketCommitmentSequences: []uint64{1}, - } - }, - true, - }, - { - "basic success unreceived packet commitments, nothing to relay", - func() { - _, _, _, _, channelA, _ := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - - suite.chainA.App.IBCKeeper.ChannelKeeper.SetPacketReceipt(suite.chainA.GetContext(), channelA.PortID, channelA.ID, 1) - - expSeq = []uint64{} - req = &types.QueryUnreceivedPacketsRequest{ - PortId: channelA.PortID, - ChannelId: channelA.ID, - PacketCommitmentSequences: []uint64{1}, - } - }, - true, - }, - { - "success multiple unreceived packet commitments", - func() { - _, _, _, _, channelA, _ := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - expSeq = []uint64{} // reset - packetCommitments := []uint64{} - - // set packet receipt for every other sequence - for seq := uint64(1); seq < 10; seq++ { - packetCommitments = append(packetCommitments, seq) - - if seq%2 == 0 { - suite.chainA.App.IBCKeeper.ChannelKeeper.SetPacketReceipt(suite.chainA.GetContext(), channelA.PortID, channelA.ID, seq) - } else { - expSeq = append(expSeq, seq) - } - } - - req = &types.QueryUnreceivedPacketsRequest{ - PortId: channelA.PortID, - ChannelId: channelA.ID, - PacketCommitmentSequences: packetCommitments, - } - }, - true, - }, - } - - for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { - suite.SetupTest() // reset - - tc.malleate() - ctx := sdk.WrapSDKContext(suite.chainA.GetContext()) - - res, err := suite.chainA.QueryServer.UnreceivedPackets(ctx, req) - - if tc.expPass { - suite.Require().NoError(err) - suite.Require().NotNil(res) - suite.Require().Equal(expSeq, res.Sequences) - } else { - suite.Require().Error(err) - } - }) - } -} - -func (suite *KeeperTestSuite) TestQueryUnreceivedAcks() { - var ( - req *types.QueryUnreceivedAcksRequest - expSeq = []uint64{} - ) - - testCases := []struct { - msg string - malleate func() - expPass bool - }{ - { - "empty request", - func() { - req = nil - }, - false, - }, - { - "invalid port ID", - func() { - req = &types.QueryUnreceivedAcksRequest{ - PortId: "", - ChannelId: "test-channel-id", - } - }, - false, - }, - { - "invalid channel ID", - func() { - req = &types.QueryUnreceivedAcksRequest{ - PortId: "test-port-id", - ChannelId: "", - } - }, - false, - }, - { - "invalid seq", - func() { - req = &types.QueryUnreceivedAcksRequest{ - PortId: "test-port-id", - ChannelId: "test-channel-id", - PacketAckSequences: []uint64{0}, - } - }, - false, - }, - { - "basic success unreceived packet acks", - func() { - _, _, _, _, channelA, _ := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - - suite.chainA.App.IBCKeeper.ChannelKeeper.SetPacketCommitment(suite.chainA.GetContext(), channelA.PortID, channelA.ID, 1, []byte("commitment")) - - expSeq = []uint64{1} - req = &types.QueryUnreceivedAcksRequest{ - PortId: channelA.PortID, - ChannelId: channelA.ID, - PacketAckSequences: []uint64{1}, - } - }, - true, - }, - { - "basic success unreceived packet acknowledgements, nothing to relay", - func() { - _, _, _, _, channelA, _ := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - - expSeq = []uint64{} - req = &types.QueryUnreceivedAcksRequest{ - PortId: channelA.PortID, - ChannelId: channelA.ID, - PacketAckSequences: []uint64{1}, - } - }, - true, - }, - { - "success multiple unreceived packet acknowledgements", - func() { - _, _, _, _, channelA, _ := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - expSeq = []uint64{} // reset - packetAcks := []uint64{} - - // set packet commitment for every other sequence - for seq := uint64(1); seq < 10; seq++ { - packetAcks = append(packetAcks, seq) - - if seq%2 == 0 { - suite.chainA.App.IBCKeeper.ChannelKeeper.SetPacketCommitment(suite.chainA.GetContext(), channelA.PortID, channelA.ID, seq, []byte("commitement")) - expSeq = append(expSeq, seq) - } - } - - req = &types.QueryUnreceivedAcksRequest{ - PortId: channelA.PortID, - ChannelId: channelA.ID, - PacketAckSequences: packetAcks, - } - }, - true, - }, - } - - for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { - suite.SetupTest() // reset - - tc.malleate() - ctx := sdk.WrapSDKContext(suite.chainA.GetContext()) - - res, err := suite.chainA.QueryServer.UnreceivedAcks(ctx, req) - - if tc.expPass { - suite.Require().NoError(err) - suite.Require().NotNil(res) - suite.Require().Equal(expSeq, res.Sequences) - } else { - suite.Require().Error(err) - } - }) - } -} - -func (suite *KeeperTestSuite) TestQueryNextSequenceReceive() { - var ( - req *types.QueryNextSequenceReceiveRequest - expSeq uint64 - ) - - testCases := []struct { - msg string - malleate func() - expPass bool - }{ - { - "empty request", - func() { - req = nil - }, - false, - }, - { - "invalid port ID", - func() { - req = &types.QueryNextSequenceReceiveRequest{ - PortId: "", - ChannelId: "test-channel-id", - } - }, - false, - }, - { - "invalid channel ID", - func() { - req = &types.QueryNextSequenceReceiveRequest{ - PortId: "test-port-id", - ChannelId: "", - } - }, - false, - }, - {"channel not found", - func() { - req = &types.QueryNextSequenceReceiveRequest{ - PortId: "test-port-id", - ChannelId: "test-channel-id", - } - }, - false, - }, - { - "success", - func() { - _, _, _, _, channelA, _ := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - expSeq = 1 - suite.chainA.App.IBCKeeper.ChannelKeeper.SetNextSequenceRecv(suite.chainA.GetContext(), channelA.PortID, channelA.ID, expSeq) - - req = &types.QueryNextSequenceReceiveRequest{ - PortId: channelA.PortID, - ChannelId: channelA.ID, - } - }, - true, - }, - } - - for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { - suite.SetupTest() // reset - - tc.malleate() - ctx := sdk.WrapSDKContext(suite.chainA.GetContext()) - - res, err := suite.chainA.QueryServer.NextSequenceReceive(ctx, req) - - if tc.expPass { - suite.Require().NoError(err) - suite.Require().NotNil(res) - suite.Require().Equal(expSeq, res.NextSequenceReceive) - } else { - suite.Require().Error(err) - } - }) - } -} diff --git a/x/ibc/core/04-channel/keeper/handshake.go b/x/ibc/core/04-channel/keeper/handshake.go deleted file mode 100644 index b7cff480c965..000000000000 --- a/x/ibc/core/04-channel/keeper/handshake.go +++ /dev/null @@ -1,496 +0,0 @@ -package keeper - -import ( - "github.com/cosmos/cosmos-sdk/telemetry" - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" - connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - porttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/05-port/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -// CounterpartyHops returns the connection hops of the counterparty channel. -// The counterparty hops are stored in the inverse order as the channel's. -// NOTE: Since connectionHops only supports single connection channels for now, -// this function requires that connection hops only contain a single connection id -func (k Keeper) CounterpartyHops(ctx sdk.Context, ch types.Channel) ([]string, bool) { - // Return empty array if connection hops is more than one - // ConnectionHops length should be verified earlier - if len(ch.ConnectionHops) != 1 { - return []string{}, false - } - counterpartyHops := make([]string, 1) - hop := ch.ConnectionHops[0] - conn, found := k.connectionKeeper.GetConnection(ctx, hop) - if !found { - return []string{}, false - } - - counterpartyHops[0] = conn.GetCounterparty().GetConnectionID() - return counterpartyHops, true -} - -// ChanOpenInit is called by a module to initiate a channel opening handshake with -// a module on another chain. The counterparty channel identifier is validated to be -// empty in msg validation. -func (k Keeper) ChanOpenInit( - ctx sdk.Context, - order types.Order, - connectionHops []string, - portID string, - portCap *capabilitytypes.Capability, - counterparty types.Counterparty, - version string, -) (string, *capabilitytypes.Capability, error) { - // connection hop length checked on msg.ValidateBasic() - connectionEnd, found := k.connectionKeeper.GetConnection(ctx, connectionHops[0]) - if !found { - return "", nil, sdkerrors.Wrap(connectiontypes.ErrConnectionNotFound, connectionHops[0]) - } - - getVersions := connectionEnd.GetVersions() - if len(getVersions) != 1 { - return "", nil, sdkerrors.Wrapf( - connectiontypes.ErrInvalidVersion, - "single version must be negotiated on connection before opening channel, got: %v", - getVersions, - ) - } - - if !connectiontypes.VerifySupportedFeature(getVersions[0], order.String()) { - return "", nil, sdkerrors.Wrapf( - connectiontypes.ErrInvalidVersion, - "connection version %s does not support channel ordering: %s", - getVersions[0], order.String(), - ) - } - - if !k.portKeeper.Authenticate(ctx, portCap, portID) { - return "", nil, sdkerrors.Wrapf(porttypes.ErrInvalidPort, "caller does not own port capability for port ID %s", portID) - } - - channelID := k.GenerateChannelIdentifier(ctx) - channel := types.NewChannel(types.INIT, order, counterparty, connectionHops, version) - k.SetChannel(ctx, portID, channelID, channel) - - capKey, err := k.scopedKeeper.NewCapability(ctx, host.ChannelCapabilityPath(portID, channelID)) - if err != nil { - return "", nil, sdkerrors.Wrapf(err, "could not create channel capability for port ID %s and channel ID %s", portID, channelID) - } - - k.SetNextSequenceSend(ctx, portID, channelID, 1) - k.SetNextSequenceRecv(ctx, portID, channelID, 1) - k.SetNextSequenceAck(ctx, portID, channelID, 1) - - k.Logger(ctx).Info("channel state updated", "port-id", portID, "channel-id", channelID, "previous-state", "NONE", "new-state", "INIT") - - defer func() { - telemetry.IncrCounter(1, "ibc", "channel", "open-init") - }() - - return channelID, capKey, nil -} - -// ChanOpenTry is called by a module to accept the first step of a channel opening -// handshake initiated by a module on another chain. -func (k Keeper) ChanOpenTry( - ctx sdk.Context, - order types.Order, - connectionHops []string, - portID, - previousChannelID string, - portCap *capabilitytypes.Capability, - counterparty types.Counterparty, - version, - counterpartyVersion string, - proofInit []byte, - proofHeight exported.Height, -) (string, *capabilitytypes.Capability, error) { - var ( - previousChannel types.Channel - previousChannelFound bool - ) - - channelID := previousChannelID - - // empty channel identifier indicates continuing a previous channel handshake - if previousChannelID != "" { - // channel identifier and connection hop length checked on msg.ValidateBasic() - // ensure that the previous channel exists - previousChannel, previousChannelFound = k.GetChannel(ctx, portID, previousChannelID) - if !previousChannelFound { - return "", nil, sdkerrors.Wrapf(types.ErrInvalidChannel, "previous channel does not exist for supplied previous channelID %s", previousChannelID) - } - // previous channel must use the same fields - if !(previousChannel.Ordering == order && - previousChannel.Counterparty.PortId == counterparty.PortId && - previousChannel.Counterparty.ChannelId == "" && - previousChannel.ConnectionHops[0] == connectionHops[0] && - previousChannel.Version == version) { - return "", nil, sdkerrors.Wrap(types.ErrInvalidChannel, "channel fields mismatch previous channel fields") - } - - if previousChannel.State != types.INIT { - return "", nil, sdkerrors.Wrapf(types.ErrInvalidChannelState, "previous channel state is in %s, expected INIT", previousChannel.State) - } - - } else { - // generate a new channel - channelID = k.GenerateChannelIdentifier(ctx) - } - - if !k.portKeeper.Authenticate(ctx, portCap, portID) { - return "", nil, sdkerrors.Wrapf(porttypes.ErrInvalidPort, "caller does not own port capability for port ID %s", portID) - } - - connectionEnd, found := k.connectionKeeper.GetConnection(ctx, connectionHops[0]) - if !found { - return "", nil, sdkerrors.Wrap(connectiontypes.ErrConnectionNotFound, connectionHops[0]) - } - - if connectionEnd.GetState() != int32(connectiontypes.OPEN) { - return "", nil, sdkerrors.Wrapf( - connectiontypes.ErrInvalidConnectionState, - "connection state is not OPEN (got %s)", connectiontypes.State(connectionEnd.GetState()).String(), - ) - } - - getVersions := connectionEnd.GetVersions() - if len(getVersions) != 1 { - return "", nil, sdkerrors.Wrapf( - connectiontypes.ErrInvalidVersion, - "single version must be negotiated on connection before opening channel, got: %v", - getVersions, - ) - } - - if !connectiontypes.VerifySupportedFeature(getVersions[0], order.String()) { - return "", nil, sdkerrors.Wrapf( - connectiontypes.ErrInvalidVersion, - "connection version %s does not support channel ordering: %s", - getVersions[0], order.String(), - ) - } - - // NOTE: this step has been switched with the one below to reverse the connection - // hops - channel := types.NewChannel(types.TRYOPEN, order, counterparty, connectionHops, version) - - counterpartyHops, found := k.CounterpartyHops(ctx, channel) - if !found { - // should not reach here, connectionEnd was able to be retrieved above - panic("cannot find connection") - } - - // expectedCounterpaty is the counterparty of the counterparty's channel end - // (i.e self) - expectedCounterparty := types.NewCounterparty(portID, "") - expectedChannel := types.NewChannel( - types.INIT, channel.Ordering, expectedCounterparty, - counterpartyHops, counterpartyVersion, - ) - - if err := k.connectionKeeper.VerifyChannelState( - ctx, connectionEnd, proofHeight, proofInit, - counterparty.PortId, counterparty.ChannelId, expectedChannel, - ); err != nil { - return "", nil, err - } - - var ( - capKey *capabilitytypes.Capability - err error - ) - - if !previousChannelFound { - capKey, err = k.scopedKeeper.NewCapability(ctx, host.ChannelCapabilityPath(portID, channelID)) - if err != nil { - return "", nil, sdkerrors.Wrapf(err, "could not create channel capability for port ID %s and channel ID %s", portID, channelID) - } - - k.SetNextSequenceSend(ctx, portID, channelID, 1) - k.SetNextSequenceRecv(ctx, portID, channelID, 1) - k.SetNextSequenceAck(ctx, portID, channelID, 1) - } else { - // capability initialized in ChanOpenInit - capKey, found = k.scopedKeeper.GetCapability(ctx, host.ChannelCapabilityPath(portID, channelID)) - if !found { - return "", nil, sdkerrors.Wrapf(types.ErrChannelCapabilityNotFound, - "capability not found for existing channel, portID (%s) channelID (%s)", portID, channelID, - ) - } - } - - k.SetChannel(ctx, portID, channelID, channel) - - k.Logger(ctx).Info("channel state updated", "port-id", portID, "channel-id", channelID, "previous-state", previousChannel.State.String(), "new-state", "TRYOPEN") - - defer func() { - telemetry.IncrCounter(1, "ibc", "channel", "open-try") - }() - - return channelID, capKey, nil -} - -// ChanOpenAck is called by the handshake-originating module to acknowledge the -// acceptance of the initial request by the counterparty module on the other chain. -func (k Keeper) ChanOpenAck( - ctx sdk.Context, - portID, - channelID string, - chanCap *capabilitytypes.Capability, - counterpartyVersion, - counterpartyChannelID string, - proofTry []byte, - proofHeight exported.Height, -) error { - channel, found := k.GetChannel(ctx, portID, channelID) - if !found { - return sdkerrors.Wrapf(types.ErrChannelNotFound, "port ID (%s) channel ID (%s)", portID, channelID) - } - - if !(channel.State == types.INIT || channel.State == types.TRYOPEN) { - return sdkerrors.Wrapf( - types.ErrInvalidChannelState, - "channel state should be INIT or TRYOPEN (got %s)", channel.State.String(), - ) - } - - if !k.scopedKeeper.AuthenticateCapability(ctx, chanCap, host.ChannelCapabilityPath(portID, channelID)) { - return sdkerrors.Wrapf(types.ErrChannelCapabilityNotFound, "caller does not own capability for channel, port ID (%s) channel ID (%s)", portID, channelID) - } - - connectionEnd, found := k.connectionKeeper.GetConnection(ctx, channel.ConnectionHops[0]) - if !found { - return sdkerrors.Wrap(connectiontypes.ErrConnectionNotFound, channel.ConnectionHops[0]) - } - - if connectionEnd.GetState() != int32(connectiontypes.OPEN) { - return sdkerrors.Wrapf( - connectiontypes.ErrInvalidConnectionState, - "connection state is not OPEN (got %s)", connectiontypes.State(connectionEnd.GetState()).String(), - ) - } - - counterpartyHops, found := k.CounterpartyHops(ctx, channel) - if !found { - // should not reach here, connectionEnd was able to be retrieved above - panic("cannot find connection") - } - - // counterparty of the counterparty channel end (i.e self) - expectedCounterparty := types.NewCounterparty(portID, channelID) - expectedChannel := types.NewChannel( - types.TRYOPEN, channel.Ordering, expectedCounterparty, - counterpartyHops, counterpartyVersion, - ) - - if err := k.connectionKeeper.VerifyChannelState( - ctx, connectionEnd, proofHeight, proofTry, - channel.Counterparty.PortId, counterpartyChannelID, - expectedChannel, - ); err != nil { - return err - } - - k.Logger(ctx).Info("channel state updated", "port-id", portID, "channel-id", channelID, "previous-state", channel.State.String(), "new-state", "OPEN") - - defer func() { - telemetry.IncrCounter(1, "ibc", "channel", "open-ack") - }() - - channel.State = types.OPEN - channel.Version = counterpartyVersion - channel.Counterparty.ChannelId = counterpartyChannelID - k.SetChannel(ctx, portID, channelID, channel) - - return nil -} - -// ChanOpenConfirm is called by the counterparty module to close their end of the -// channel, since the other end has been closed. -func (k Keeper) ChanOpenConfirm( - ctx sdk.Context, - portID, - channelID string, - chanCap *capabilitytypes.Capability, - proofAck []byte, - proofHeight exported.Height, -) error { - channel, found := k.GetChannel(ctx, portID, channelID) - if !found { - return sdkerrors.Wrapf(types.ErrChannelNotFound, "port ID (%s) channel ID (%s)", portID, channelID) - } - - if channel.State != types.TRYOPEN { - return sdkerrors.Wrapf( - types.ErrInvalidChannelState, - "channel state is not TRYOPEN (got %s)", channel.State.String(), - ) - } - - if !k.scopedKeeper.AuthenticateCapability(ctx, chanCap, host.ChannelCapabilityPath(portID, channelID)) { - return sdkerrors.Wrapf(types.ErrChannelCapabilityNotFound, "caller does not own capability for channel, port ID (%s) channel ID (%s)", portID, channelID) - } - - connectionEnd, found := k.connectionKeeper.GetConnection(ctx, channel.ConnectionHops[0]) - if !found { - return sdkerrors.Wrap(connectiontypes.ErrConnectionNotFound, channel.ConnectionHops[0]) - } - - if connectionEnd.GetState() != int32(connectiontypes.OPEN) { - return sdkerrors.Wrapf( - connectiontypes.ErrInvalidConnectionState, - "connection state is not OPEN (got %s)", connectiontypes.State(connectionEnd.GetState()).String(), - ) - } - - counterpartyHops, found := k.CounterpartyHops(ctx, channel) - if !found { - // Should not reach here, connectionEnd was able to be retrieved above - panic("cannot find connection") - } - - counterparty := types.NewCounterparty(portID, channelID) - expectedChannel := types.NewChannel( - types.OPEN, channel.Ordering, counterparty, - counterpartyHops, channel.Version, - ) - - if err := k.connectionKeeper.VerifyChannelState( - ctx, connectionEnd, proofHeight, proofAck, - channel.Counterparty.PortId, channel.Counterparty.ChannelId, - expectedChannel, - ); err != nil { - return err - } - - channel.State = types.OPEN - k.SetChannel(ctx, portID, channelID, channel) - k.Logger(ctx).Info("channel state updated", "port-id", portID, "channel-id", channelID, "previous-state", "TRYOPEN", "new-state", "OPEN") - - defer func() { - telemetry.IncrCounter(1, "ibc", "channel", "open-confirm") - }() - return nil -} - -// Closing Handshake -// -// This section defines the set of functions required to close a channel handshake -// as defined in https://github.com/cosmos/ics/tree/master/spec/ics-004-channel-and-packet-semantics#closing-handshake -// -// ChanCloseInit is called by either module to close their end of the channel. Once -// closed, channels cannot be reopened. -func (k Keeper) ChanCloseInit( - ctx sdk.Context, - portID, - channelID string, - chanCap *capabilitytypes.Capability, -) error { - if !k.scopedKeeper.AuthenticateCapability(ctx, chanCap, host.ChannelCapabilityPath(portID, channelID)) { - return sdkerrors.Wrapf(types.ErrChannelCapabilityNotFound, "caller does not own capability for channel, port ID (%s) channel ID (%s)", portID, channelID) - } - - channel, found := k.GetChannel(ctx, portID, channelID) - if !found { - return sdkerrors.Wrapf(types.ErrChannelNotFound, "port ID (%s) channel ID (%s)", portID, channelID) - } - - if channel.State == types.CLOSED { - return sdkerrors.Wrap(types.ErrInvalidChannelState, "channel is already CLOSED") - } - - connectionEnd, found := k.connectionKeeper.GetConnection(ctx, channel.ConnectionHops[0]) - if !found { - return sdkerrors.Wrap(connectiontypes.ErrConnectionNotFound, channel.ConnectionHops[0]) - } - - if connectionEnd.GetState() != int32(connectiontypes.OPEN) { - return sdkerrors.Wrapf( - connectiontypes.ErrInvalidConnectionState, - "connection state is not OPEN (got %s)", connectiontypes.State(connectionEnd.GetState()).String(), - ) - } - - k.Logger(ctx).Info("channel state updated", "port-id", portID, "channel-id", channelID, "previous-state", channel.State.String(), "new-state", "CLOSED") - - defer func() { - telemetry.IncrCounter(1, "ibc", "channel", "close-init") - }() - - channel.State = types.CLOSED - k.SetChannel(ctx, portID, channelID, channel) - - return nil -} - -// ChanCloseConfirm is called by the counterparty module to close their end of the -// channel, since the other end has been closed. -func (k Keeper) ChanCloseConfirm( - ctx sdk.Context, - portID, - channelID string, - chanCap *capabilitytypes.Capability, - proofInit []byte, - proofHeight exported.Height, -) error { - if !k.scopedKeeper.AuthenticateCapability(ctx, chanCap, host.ChannelCapabilityPath(portID, channelID)) { - return sdkerrors.Wrap(types.ErrChannelCapabilityNotFound, "caller does not own capability for channel, port ID (%s) channel ID (%s)") - } - - channel, found := k.GetChannel(ctx, portID, channelID) - if !found { - return sdkerrors.Wrapf(types.ErrChannelNotFound, "port ID (%s) channel ID (%s)", portID, channelID) - } - - if channel.State == types.CLOSED { - return sdkerrors.Wrap(types.ErrInvalidChannelState, "channel is already CLOSED") - } - - connectionEnd, found := k.connectionKeeper.GetConnection(ctx, channel.ConnectionHops[0]) - if !found { - return sdkerrors.Wrap(connectiontypes.ErrConnectionNotFound, channel.ConnectionHops[0]) - } - - if connectionEnd.GetState() != int32(connectiontypes.OPEN) { - return sdkerrors.Wrapf( - connectiontypes.ErrInvalidConnectionState, - "connection state is not OPEN (got %s)", connectiontypes.State(connectionEnd.GetState()).String(), - ) - } - - counterpartyHops, found := k.CounterpartyHops(ctx, channel) - if !found { - // Should not reach here, connectionEnd was able to be retrieved above - panic("cannot find connection") - } - - counterparty := types.NewCounterparty(portID, channelID) - expectedChannel := types.NewChannel( - types.CLOSED, channel.Ordering, counterparty, - counterpartyHops, channel.Version, - ) - - if err := k.connectionKeeper.VerifyChannelState( - ctx, connectionEnd, proofHeight, proofInit, - channel.Counterparty.PortId, channel.Counterparty.ChannelId, - expectedChannel, - ); err != nil { - return err - } - - k.Logger(ctx).Info("channel state updated", "port-id", portID, "channel-id", channelID, "previous-state", channel.State.String(), "new-state", "CLOSED") - - defer func() { - telemetry.IncrCounter(1, "ibc", "channel", "close-confirm") - }() - - channel.State = types.CLOSED - k.SetChannel(ctx, portID, channelID, channel) - - return nil -} diff --git a/x/ibc/core/04-channel/keeper/handshake_test.go b/x/ibc/core/04-channel/keeper/handshake_test.go deleted file mode 100644 index 120e1f8fe229..000000000000 --- a/x/ibc/core/04-channel/keeper/handshake_test.go +++ /dev/null @@ -1,773 +0,0 @@ -package keeper_test - -import ( - "fmt" - - capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" -) - -type testCase = struct { - msg string - malleate func() - expPass bool -} - -// TestChanOpenInit tests the OpenInit handshake call for channels. It uses message passing -// to enter into the appropriate state and then calls ChanOpenInit directly. The channel is -// being created on chainA. The port capability must be created on chainA before ChanOpenInit -// can succeed. -func (suite *KeeperTestSuite) TestChanOpenInit() { - var ( - connA *ibctesting.TestConnection - connB *ibctesting.TestConnection - features []string - portCap *capabilitytypes.Capability - ) - - testCases := []testCase{ - {"success", func() { - _, _, connA, connB = suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - features = []string{"ORDER_ORDERED", "ORDER_UNORDERED"} - suite.chainA.CreatePortCapability(suite.chainA.NextTestChannel(connA, ibctesting.MockPort).PortID) - portCap = suite.chainA.GetPortCapability(suite.chainA.NextTestChannel(connA, ibctesting.MockPort).PortID) - }, true}, - {"channel already exists", func() { - _, _, connA, connB, _, _ = suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - }, false}, - {"connection doesn't exist", func() { - // any non-nil values of connA and connB are acceptable - suite.Require().NotNil(connA) - suite.Require().NotNil(connB) - }, false}, - {"capability is incorrect", func() { - _, _, connA, connB = suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - features = []string{"ORDER_ORDERED", "ORDER_UNORDERED"} - portCap = capabilitytypes.NewCapability(3) - }, false}, - {"connection version not negotiated", func() { - _, _, connA, connB = suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - - // modify connA versions - conn := suite.chainA.GetConnection(connA) - - version := connectiontypes.NewVersion("2", []string{"ORDER_ORDERED", "ORDER_UNORDERED"}) - conn.Versions = append(conn.Versions, version) - - suite.chainA.App.IBCKeeper.ConnectionKeeper.SetConnection( - suite.chainA.GetContext(), - connA.ID, conn, - ) - features = []string{"ORDER_ORDERED", "ORDER_UNORDERED"} - suite.chainA.CreatePortCapability(suite.chainA.NextTestChannel(connA, ibctesting.MockPort).PortID) - portCap = suite.chainA.GetPortCapability(suite.chainA.NextTestChannel(connA, ibctesting.MockPort).PortID) - }, false}, - {"connection does not support ORDERED channels", func() { - _, _, connA, connB = suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - - // modify connA versions to only support UNORDERED channels - conn := suite.chainA.GetConnection(connA) - - version := connectiontypes.NewVersion("1", []string{"ORDER_UNORDERED"}) - conn.Versions = []*connectiontypes.Version{version} - - suite.chainA.App.IBCKeeper.ConnectionKeeper.SetConnection( - suite.chainA.GetContext(), - connA.ID, conn, - ) - // NOTE: Opening UNORDERED channels is still expected to pass but ORDERED channels should fail - features = []string{"ORDER_UNORDERED"} - suite.chainA.CreatePortCapability(suite.chainA.NextTestChannel(connA, ibctesting.MockPort).PortID) - portCap = suite.chainA.GetPortCapability(suite.chainA.NextTestChannel(connA, ibctesting.MockPort).PortID) - }, true}, - } - - for _, tc := range testCases { - tc := tc - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { - // run test for all types of ordering - for _, order := range []types.Order{types.UNORDERED, types.ORDERED} { - suite.SetupTest() // reset - tc.malleate() - - counterparty := types.NewCounterparty(connB.FirstOrNextTestChannel(ibctesting.MockPort).PortID, connB.FirstOrNextTestChannel(ibctesting.MockPort).ID) - channelA := connA.FirstOrNextTestChannel(ibctesting.MockPort) - - channelID, cap, err := suite.chainA.App.IBCKeeper.ChannelKeeper.ChanOpenInit( - suite.chainA.GetContext(), order, []string{connA.ID}, - channelA.PortID, portCap, counterparty, channelA.Version, - ) - - // check if order is supported by channel to determine expected behaviour - orderSupported := false - for _, f := range features { - if f == order.String() { - orderSupported = true - } - } - - // Testcase must have expectedPass = true AND channel order supported before - // asserting the channel handshake initiation succeeded - if tc.expPass && orderSupported { - suite.Require().NoError(err) - suite.Require().NotNil(cap) - suite.Require().Equal(types.FormatChannelIdentifier(0), channelID) - - chanCap, ok := suite.chainA.App.ScopedIBCKeeper.GetCapability( - suite.chainA.GetContext(), - host.ChannelCapabilityPath(channelA.PortID, channelA.ID), - ) - suite.Require().True(ok, "could not retrieve channel capability after successful ChanOpenInit") - suite.Require().Equal(chanCap.String(), cap.String(), "channel capability is not correct") - } else { - suite.Require().Error(err) - suite.Require().Nil(cap) - suite.Require().Equal("", channelID) - } - } - }) - } -} - -// TestChanOpenTry tests the OpenTry handshake call for channels. It uses message passing -// to enter into the appropriate state and then calls ChanOpenTry directly. The channel -// is being created on chainB. The port capability must be created on chainB before -// ChanOpenTry can succeed. -func (suite *KeeperTestSuite) TestChanOpenTry() { - var ( - connA *ibctesting.TestConnection - connB *ibctesting.TestConnection - previousChannelID string - portCap *capabilitytypes.Capability - heightDiff uint64 - ) - - testCases := []testCase{ - {"success", func() { - _, _, connA, connB = suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - suite.coordinator.ChanOpenInit(suite.chainA, suite.chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, types.ORDERED) - - suite.chainB.CreatePortCapability(suite.chainB.NextTestChannel(connB, ibctesting.MockPort).PortID) - portCap = suite.chainB.GetPortCapability(suite.chainB.NextTestChannel(connB, ibctesting.MockPort).PortID) - }, true}, - {"success with crossing hello", func() { - _, _, connA, connB = suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - _, channelB, err := suite.coordinator.ChanOpenInitOnBothChains(suite.chainA, suite.chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, types.ORDERED) - suite.Require().NoError(err) - - previousChannelID = channelB.ID - portCap = suite.chainB.GetPortCapability(suite.chainB.NextTestChannel(connB, ibctesting.MockPort).PortID) - }, true}, - {"previous channel with invalid state", func() { - _, _, connA, connB = suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - - // make previous channel have wrong ordering - suite.coordinator.ChanOpenInit(suite.chainB, suite.chainA, connB, connA, ibctesting.MockPort, ibctesting.MockPort, types.UNORDERED) - }, false}, - {"connection doesn't exist", func() { - // any non-nil values of connA and connB are acceptable - suite.Require().NotNil(connA) - suite.Require().NotNil(connB) - - // pass capability check - suite.chainB.CreatePortCapability(connB.FirstOrNextTestChannel(ibctesting.MockPort).PortID) - portCap = suite.chainB.GetPortCapability(connB.FirstOrNextTestChannel(ibctesting.MockPort).PortID) - }, false}, - {"connection is not OPEN", func() { - clientA, clientB := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - // pass capability check - suite.chainB.CreatePortCapability(connB.FirstOrNextTestChannel(ibctesting.MockPort).PortID) - portCap = suite.chainB.GetPortCapability(connB.FirstOrNextTestChannel(ibctesting.MockPort).PortID) - - var err error - connB, connA, err = suite.coordinator.ConnOpenInit(suite.chainB, suite.chainA, clientB, clientA) - suite.Require().NoError(err) - }, false}, - {"consensus state not found", func() { - _, _, connA, connB = suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - suite.coordinator.ChanOpenInit(suite.chainA, suite.chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, types.ORDERED) - - suite.chainB.CreatePortCapability(suite.chainB.NextTestChannel(connB, ibctesting.MockPort).PortID) - portCap = suite.chainB.GetPortCapability(suite.chainB.NextTestChannel(connB, ibctesting.MockPort).PortID) - - heightDiff = 3 // consensus state doesn't exist at this height - }, false}, - {"channel verification failed", func() { - // not creating a channel on chainA will result in an invalid proof of existence - _, _, connA, connB = suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - portCap = suite.chainB.GetPortCapability(suite.chainB.NextTestChannel(connB, ibctesting.MockPort).PortID) - }, false}, - {"port capability not found", func() { - _, _, connA, connB = suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - suite.coordinator.ChanOpenInit(suite.chainA, suite.chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, types.ORDERED) - - portCap = capabilitytypes.NewCapability(3) - }, false}, - {"connection version not negotiated", func() { - _, _, connA, connB = suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - suite.coordinator.ChanOpenInit(suite.chainA, suite.chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, types.ORDERED) - - // modify connB versions - conn := suite.chainB.GetConnection(connB) - - version := connectiontypes.NewVersion("2", []string{"ORDER_ORDERED", "ORDER_UNORDERED"}) - conn.Versions = append(conn.Versions, version) - - suite.chainB.App.IBCKeeper.ConnectionKeeper.SetConnection( - suite.chainB.GetContext(), - connB.ID, conn, - ) - suite.chainB.CreatePortCapability(suite.chainB.NextTestChannel(connB, ibctesting.MockPort).PortID) - portCap = suite.chainB.GetPortCapability(suite.chainB.NextTestChannel(connB, ibctesting.MockPort).PortID) - }, false}, - {"connection does not support ORDERED channels", func() { - _, _, connA, connB = suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - suite.coordinator.ChanOpenInit(suite.chainA, suite.chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, types.ORDERED) - - // modify connA versions to only support UNORDERED channels - conn := suite.chainA.GetConnection(connA) - - version := connectiontypes.NewVersion("1", []string{"ORDER_UNORDERED"}) - conn.Versions = []*connectiontypes.Version{version} - - suite.chainA.App.IBCKeeper.ConnectionKeeper.SetConnection( - suite.chainA.GetContext(), - connA.ID, conn, - ) - suite.chainA.CreatePortCapability(suite.chainA.NextTestChannel(connA, ibctesting.MockPort).PortID) - portCap = suite.chainA.GetPortCapability(suite.chainA.NextTestChannel(connA, ibctesting.MockPort).PortID) - }, false}, - } - - for _, tc := range testCases { - tc := tc - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { - suite.SetupTest() // reset - heightDiff = 0 // must be explicitly changed in malleate - previousChannelID = "" - - tc.malleate() - channelA := connA.FirstOrNextTestChannel(ibctesting.MockPort) - channelB := connB.FirstOrNextTestChannel(ibctesting.MockPort) - counterparty := types.NewCounterparty(channelA.PortID, channelA.ID) - - channelKey := host.ChannelKey(counterparty.PortId, counterparty.ChannelId) - proof, proofHeight := suite.chainA.QueryProof(channelKey) - - channelID, cap, err := suite.chainB.App.IBCKeeper.ChannelKeeper.ChanOpenTry( - suite.chainB.GetContext(), types.ORDERED, []string{connB.ID}, - channelB.PortID, previousChannelID, portCap, counterparty, channelB.Version, connA.FirstOrNextTestChannel(ibctesting.MockPort).Version, - proof, malleateHeight(proofHeight, heightDiff), - ) - - if tc.expPass { - suite.Require().NoError(err) - suite.Require().NotNil(cap) - - chanCap, ok := suite.chainB.App.ScopedIBCKeeper.GetCapability( - suite.chainB.GetContext(), - host.ChannelCapabilityPath(channelB.PortID, channelID), - ) - suite.Require().True(ok, "could not retrieve channel capapbility after successful ChanOpenTry") - suite.Require().Equal(chanCap.String(), cap.String(), "channel capability is not correct") - } else { - suite.Require().Error(err) - } - }) - } -} - -// TestChanOpenAck tests the OpenAck handshake call for channels. It uses message passing -// to enter into the appropriate state and then calls ChanOpenAck directly. The handshake -// call is occurring on chainA. -func (suite *KeeperTestSuite) TestChanOpenAck() { - var ( - connA *ibctesting.TestConnection - connB *ibctesting.TestConnection - counterpartyChannelID string - channelCap *capabilitytypes.Capability - heightDiff uint64 - ) - - testCases := []testCase{ - {"success", func() { - _, _, connA, connB = suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - channelA, channelB, err := suite.coordinator.ChanOpenInit(suite.chainA, suite.chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, types.ORDERED) - suite.Require().NoError(err) - - err = suite.coordinator.ChanOpenTry(suite.chainB, suite.chainA, channelB, channelA, connB, types.ORDERED) - suite.Require().NoError(err) - - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, true}, - {"success with empty stored counterparty channel ID", func() { - _, _, connA, connB = suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - channelA, channelB, err := suite.coordinator.ChanOpenInit(suite.chainA, suite.chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, types.ORDERED) - suite.Require().NoError(err) - - err = suite.coordinator.ChanOpenTry(suite.chainB, suite.chainA, channelB, channelA, connB, types.ORDERED) - suite.Require().NoError(err) - - // set the channel's counterparty channel identifier to empty string - channel := suite.chainA.GetChannel(channelA) - channel.Counterparty.ChannelId = "" - - // use a different channel identifier - counterpartyChannelID = channelB.ID - - suite.chainA.App.IBCKeeper.ChannelKeeper.SetChannel(suite.chainA.GetContext(), channelA.PortID, channelA.ID, channel) - - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, true}, - {"channel doesn't exist", func() {}, false}, - {"channel state is not INIT or TRYOPEN", func() { - // create fully open channels on both chains - _, _, connA, connB, _, _ = suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - channelA := connA.Channels[0] - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, false}, - {"connection not found", func() { - _, _, connA, connB = suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - channelA, channelB, err := suite.coordinator.ChanOpenInit(suite.chainA, suite.chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, types.ORDERED) - suite.Require().NoError(err) - - err = suite.coordinator.ChanOpenTry(suite.chainB, suite.chainA, channelB, channelA, connB, types.ORDERED) - suite.Require().NoError(err) - - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - - // set the channel's connection hops to wrong connection ID - channel := suite.chainA.GetChannel(channelA) - channel.ConnectionHops[0] = "doesnotexist" - suite.chainA.App.IBCKeeper.ChannelKeeper.SetChannel(suite.chainA.GetContext(), channelA.PortID, channelA.ID, channel) - }, false}, - {"connection is not OPEN", func() { - clientA, clientB := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - - var err error - connA, connB, err = suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB) - suite.Require().NoError(err) - - // create channel in init - channelA, _, err := suite.coordinator.ChanOpenInit(suite.chainA, suite.chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, types.ORDERED) - suite.Require().NoError(err) - - suite.chainA.CreateChannelCapability(channelA.PortID, channelA.ID) - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, false}, - {"consensus state not found", func() { - _, _, connA, connB = suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - channelA, channelB, err := suite.coordinator.ChanOpenInit(suite.chainA, suite.chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, types.ORDERED) - suite.Require().NoError(err) - - err = suite.coordinator.ChanOpenTry(suite.chainB, suite.chainA, channelB, channelA, connB, types.ORDERED) - suite.Require().NoError(err) - - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - - heightDiff = 3 // consensus state doesn't exist at this height - }, false}, - {"invalid counterparty channel identifier", func() { - _, _, connA, connB = suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - channelA, channelB, err := suite.coordinator.ChanOpenInit(suite.chainA, suite.chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, types.ORDERED) - suite.Require().NoError(err) - - err = suite.coordinator.ChanOpenTry(suite.chainB, suite.chainA, channelB, channelA, connB, types.ORDERED) - suite.Require().NoError(err) - - counterpartyChannelID = "otheridentifier" - - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, false}, - {"channel verification failed", func() { - // chainB is INIT, chainA in TRYOPEN - _, _, connA, connB = suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - channelB, channelA, err := suite.coordinator.ChanOpenInit(suite.chainB, suite.chainA, connB, connA, ibctesting.MockPort, ibctesting.MockPort, types.ORDERED) - suite.Require().NoError(err) - - err = suite.coordinator.ChanOpenTry(suite.chainA, suite.chainB, channelA, channelB, connA, types.ORDERED) - suite.Require().NoError(err) - - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, false}, - {"channel capability not found", func() { - _, _, connA, connB = suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - channelA, channelB, err := suite.coordinator.ChanOpenInit(suite.chainA, suite.chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, types.ORDERED) - suite.Require().NoError(err) - - suite.coordinator.ChanOpenTry(suite.chainB, suite.chainA, channelB, channelA, connB, types.ORDERED) - - channelCap = capabilitytypes.NewCapability(6) - }, false}, - } - - for _, tc := range testCases { - tc := tc - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { - suite.SetupTest() // reset - counterpartyChannelID = "" // must be explicitly changed in malleate - heightDiff = 0 // must be explicitly changed - - tc.malleate() - - channelA := connA.FirstOrNextTestChannel(ibctesting.MockPort) - channelB := connB.FirstOrNextTestChannel(ibctesting.MockPort) - - if counterpartyChannelID == "" { - counterpartyChannelID = channelB.ID - } - - channelKey := host.ChannelKey(channelB.PortID, channelB.ID) - proof, proofHeight := suite.chainB.QueryProof(channelKey) - - err := suite.chainA.App.IBCKeeper.ChannelKeeper.ChanOpenAck( - suite.chainA.GetContext(), channelA.PortID, channelA.ID, channelCap, channelB.Version, counterpartyChannelID, - proof, malleateHeight(proofHeight, heightDiff), - ) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} - -// TestChanOpenConfirm tests the OpenAck handshake call for channels. It uses message passing -// to enter into the appropriate state and then calls ChanOpenConfirm directly. The handshake -// call is occurring on chainB. -func (suite *KeeperTestSuite) TestChanOpenConfirm() { - var ( - connA *ibctesting.TestConnection - connB *ibctesting.TestConnection - channelCap *capabilitytypes.Capability - heightDiff uint64 - ) - testCases := []testCase{ - {"success", func() { - _, _, connA, connB = suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - channelA, channelB, err := suite.coordinator.ChanOpenInit(suite.chainA, suite.chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, types.ORDERED) - suite.Require().NoError(err) - - err = suite.coordinator.ChanOpenTry(suite.chainB, suite.chainA, channelB, channelA, connB, types.ORDERED) - suite.Require().NoError(err) - - err = suite.coordinator.ChanOpenAck(suite.chainA, suite.chainB, channelA, channelB) - suite.Require().NoError(err) - - channelCap = suite.chainB.GetChannelCapability(channelB.PortID, channelB.ID) - }, true}, - {"channel doesn't exist", func() {}, false}, - {"channel state is not TRYOPEN", func() { - // create fully open channels on both cahins - _, _, connA, connB, _, _ = suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - channelB := connB.Channels[0] - channelCap = suite.chainB.GetChannelCapability(channelB.PortID, channelB.ID) - }, false}, - {"connection not found", func() { - _, _, connA, connB = suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - channelA, channelB, err := suite.coordinator.ChanOpenInit(suite.chainA, suite.chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, types.ORDERED) - suite.Require().NoError(err) - - err = suite.coordinator.ChanOpenTry(suite.chainB, suite.chainA, channelB, channelA, connB, types.ORDERED) - suite.Require().NoError(err) - - err = suite.coordinator.ChanOpenAck(suite.chainA, suite.chainB, channelA, channelB) - suite.Require().NoError(err) - - channelCap = suite.chainB.GetChannelCapability(channelB.PortID, channelB.ID) - - // set the channel's connection hops to wrong connection ID - channel := suite.chainB.GetChannel(channelB) - channel.ConnectionHops[0] = "doesnotexist" - suite.chainB.App.IBCKeeper.ChannelKeeper.SetChannel(suite.chainB.GetContext(), channelB.PortID, channelB.ID, channel) - }, false}, - {"connection is not OPEN", func() { - clientA, clientB := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - - var err error - connA, connB, err = suite.coordinator.ConnOpenInit(suite.chainB, suite.chainA, clientB, clientA) - suite.Require().NoError(err) - channelB := connB.FirstOrNextTestChannel(ibctesting.MockPort) - suite.chainB.CreateChannelCapability(channelB.PortID, channelB.ID) - channelCap = suite.chainB.GetChannelCapability(channelB.PortID, channelB.ID) - }, false}, - {"consensus state not found", func() { - _, _, connA, connB = suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - channelA, channelB, err := suite.coordinator.ChanOpenInit(suite.chainA, suite.chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, types.ORDERED) - suite.Require().NoError(err) - - err = suite.coordinator.ChanOpenTry(suite.chainB, suite.chainA, channelB, channelA, connB, types.ORDERED) - suite.Require().NoError(err) - - err = suite.coordinator.ChanOpenAck(suite.chainA, suite.chainB, channelA, channelB) - suite.Require().NoError(err) - - channelCap = suite.chainB.GetChannelCapability(channelB.PortID, channelB.ID) - - heightDiff = 3 - }, false}, - {"channel verification failed", func() { - // chainA is INIT, chainB in TRYOPEN - _, _, connA, connB = suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - channelA, channelB, err := suite.coordinator.ChanOpenInit(suite.chainA, suite.chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, types.ORDERED) - suite.Require().NoError(err) - - err = suite.coordinator.ChanOpenTry(suite.chainB, suite.chainA, channelB, channelA, connB, types.ORDERED) - suite.Require().NoError(err) - - channelCap = suite.chainB.GetChannelCapability(channelB.PortID, channelB.ID) - }, false}, - {"channel capability not found", func() { - _, _, connA, connB = suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - channelA, channelB, err := suite.coordinator.ChanOpenInit(suite.chainA, suite.chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, types.ORDERED) - suite.Require().NoError(err) - - err = suite.coordinator.ChanOpenTry(suite.chainB, suite.chainA, channelB, channelA, connB, types.ORDERED) - suite.Require().NoError(err) - - err = suite.coordinator.ChanOpenAck(suite.chainA, suite.chainB, channelA, channelB) - suite.Require().NoError(err) - - channelCap = capabilitytypes.NewCapability(6) - }, false}, - } - - for _, tc := range testCases { - tc := tc - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { - suite.SetupTest() // reset - heightDiff = 0 // must be explicitly changed - - tc.malleate() - - channelA := connA.FirstOrNextTestChannel(ibctesting.MockPort) - channelB := connB.FirstOrNextTestChannel(ibctesting.MockPort) - - channelKey := host.ChannelKey(channelA.PortID, channelA.ID) - proof, proofHeight := suite.chainA.QueryProof(channelKey) - - err := suite.chainB.App.IBCKeeper.ChannelKeeper.ChanOpenConfirm( - suite.chainB.GetContext(), channelB.PortID, channelB.ID, - channelCap, proof, malleateHeight(proofHeight, heightDiff), - ) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} - -// TestChanCloseInit tests the initial closing of a handshake on chainA by calling -// ChanCloseInit. Both chains will use message passing to setup OPEN channels. -func (suite *KeeperTestSuite) TestChanCloseInit() { - var ( - connA *ibctesting.TestConnection - connB *ibctesting.TestConnection - channelCap *capabilitytypes.Capability - ) - - testCases := []testCase{ - {"success", func() { - _, _, connA, connB, _, _ = suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - channelA := connA.Channels[0] - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, true}, - {"channel doesn't exist", func() { - // any non-nil values work for connections - suite.Require().NotNil(connA) - suite.Require().NotNil(connB) - channelA := connA.FirstOrNextTestChannel(ibctesting.MockPort) - - // ensure channel capability check passes - suite.chainA.CreateChannelCapability(channelA.PortID, channelA.ID) - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, false}, - {"channel state is CLOSED", func() { - _, _, connA, connB, _, _ = suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - channelA := connA.Channels[0] - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - - // close channel - err := suite.coordinator.SetChannelClosed(suite.chainA, suite.chainB, channelA) - suite.Require().NoError(err) - }, false}, - {"connection not found", func() { - _, _, connA, connB, _, _ = suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - channelA := connA.Channels[0] - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - - // set the channel's connection hops to wrong connection ID - channel := suite.chainA.GetChannel(channelA) - channel.ConnectionHops[0] = "doesnotexist" - suite.chainA.App.IBCKeeper.ChannelKeeper.SetChannel(suite.chainA.GetContext(), channelA.PortID, channelA.ID, channel) - }, false}, - {"connection is not OPEN", func() { - clientA, clientB := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - - var err error - connA, connB, err = suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB) - suite.Require().NoError(err) - - // create channel in init - channelA, _, err := suite.coordinator.ChanOpenInit(suite.chainA, suite.chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, types.ORDERED) - - // ensure channel capability check passes - suite.chainA.CreateChannelCapability(channelA.PortID, channelA.ID) - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, false}, - {"channel capability not found", func() { - _, _, connA, connB, _, _ = suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - channelCap = capabilitytypes.NewCapability(3) - }, false}, - } - - for _, tc := range testCases { - tc := tc - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { - suite.SetupTest() // reset - - tc.malleate() - - channelA := connA.FirstOrNextTestChannel(ibctesting.MockPort) - - err := suite.chainA.App.IBCKeeper.ChannelKeeper.ChanCloseInit( - suite.chainA.GetContext(), channelA.PortID, channelA.ID, channelCap, - ) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} - -// TestChanCloseConfirm tests the confirming closing channel ends by calling ChanCloseConfirm -// on chainB. Both chains will use message passing to setup OPEN channels. ChanCloseInit is -// bypassed on chainA by setting the channel state in the ChannelKeeper. -func (suite *KeeperTestSuite) TestChanCloseConfirm() { - var ( - connA *ibctesting.TestConnection - connB *ibctesting.TestConnection - channelA ibctesting.TestChannel - channelB ibctesting.TestChannel - channelCap *capabilitytypes.Capability - heightDiff uint64 - ) - - testCases := []testCase{ - {"success", func() { - _, _, connA, connB, channelA, channelB = suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - channelCap = suite.chainB.GetChannelCapability(channelB.PortID, channelB.ID) - - err := suite.coordinator.SetChannelClosed(suite.chainA, suite.chainB, channelA) - suite.Require().NoError(err) - }, true}, - {"channel doesn't exist", func() { - // any non-nil values work for connections - suite.Require().NotNil(connA) - suite.Require().NotNil(connB) - channelB = connB.FirstOrNextTestChannel(ibctesting.MockPort) - - // ensure channel capability check passes - suite.chainB.CreateChannelCapability(channelB.PortID, channelB.ID) - channelCap = suite.chainB.GetChannelCapability(channelB.PortID, channelB.ID) - }, false}, - {"channel state is CLOSED", func() { - _, _, connA, connB, _, channelB = suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - channelCap = suite.chainB.GetChannelCapability(channelB.PortID, channelB.ID) - - err := suite.coordinator.SetChannelClosed(suite.chainB, suite.chainA, channelB) - suite.Require().NoError(err) - }, false}, - {"connection not found", func() { - _, _, connA, connB, _, channelB = suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - channelCap = suite.chainB.GetChannelCapability(channelB.PortID, channelB.ID) - - // set the channel's connection hops to wrong connection ID - channel := suite.chainB.GetChannel(channelB) - channel.ConnectionHops[0] = "doesnotexist" - suite.chainB.App.IBCKeeper.ChannelKeeper.SetChannel(suite.chainB.GetContext(), channelB.PortID, channelB.ID, channel) - }, false}, - {"connection is not OPEN", func() { - clientA, clientB := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - - var err error - connB, connA, err = suite.coordinator.ConnOpenInit(suite.chainB, suite.chainA, clientB, clientA) - suite.Require().NoError(err) - - // create channel in init - channelB, _, err := suite.coordinator.ChanOpenInit(suite.chainB, suite.chainA, connB, connA, ibctesting.MockPort, ibctesting.MockPort, types.ORDERED) - suite.Require().NoError(err) - - // ensure channel capability check passes - suite.chainB.CreateChannelCapability(channelB.PortID, channelB.ID) - channelCap = suite.chainB.GetChannelCapability(channelB.PortID, channelB.ID) - }, false}, - {"consensus state not found", func() { - _, _, connA, connB, channelA, channelB = suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - channelCap = suite.chainB.GetChannelCapability(channelB.PortID, channelB.ID) - - err := suite.coordinator.SetChannelClosed(suite.chainA, suite.chainB, channelA) - suite.Require().NoError(err) - - heightDiff = 3 - }, false}, - {"channel verification failed", func() { - // channel not closed - _, _, connA, connB, _, channelB = suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - channelCap = suite.chainB.GetChannelCapability(channelB.PortID, channelB.ID) - }, false}, - {"channel capability not found", func() { - _, _, connA, connB, channelA, channelB = suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - channelCap = suite.chainB.GetChannelCapability(channelB.PortID, channelB.ID) - - err := suite.coordinator.SetChannelClosed(suite.chainA, suite.chainB, channelA) - suite.Require().NoError(err) - - channelCap = capabilitytypes.NewCapability(3) - }, false}, - } - - for _, tc := range testCases { - tc := tc - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { - suite.SetupTest() // reset - heightDiff = 0 // must explicitly be changed - - tc.malleate() - - channelA = connA.FirstOrNextTestChannel(ibctesting.MockPort) - channelB = connB.FirstOrNextTestChannel(ibctesting.MockPort) - - channelKey := host.ChannelKey(channelA.PortID, channelA.ID) - proof, proofHeight := suite.chainA.QueryProof(channelKey) - - err := suite.chainB.App.IBCKeeper.ChannelKeeper.ChanCloseConfirm( - suite.chainB.GetContext(), channelB.PortID, channelB.ID, channelCap, - proof, malleateHeight(proofHeight, heightDiff), - ) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} - -func malleateHeight(height exported.Height, diff uint64) exported.Height { - return clienttypes.NewHeight(height.GetRevisionNumber(), height.GetRevisionHeight()+diff) -} diff --git a/x/ibc/core/04-channel/keeper/keeper.go b/x/ibc/core/04-channel/keeper/keeper.go deleted file mode 100644 index 60452f315bdf..000000000000 --- a/x/ibc/core/04-channel/keeper/keeper.go +++ /dev/null @@ -1,432 +0,0 @@ -package keeper - -import ( - "strconv" - "strings" - - "github.com/tendermint/tendermint/libs/log" - db "github.com/tendermint/tm-db" - - "github.com/cosmos/cosmos-sdk/codec" - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" - capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - porttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/05-port/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -// Keeper defines the IBC channel keeper -type Keeper struct { - // implements gRPC QueryServer interface - types.QueryServer - - storeKey sdk.StoreKey - cdc codec.BinaryMarshaler - clientKeeper types.ClientKeeper - connectionKeeper types.ConnectionKeeper - portKeeper types.PortKeeper - scopedKeeper capabilitykeeper.ScopedKeeper -} - -// NewKeeper creates a new IBC channel Keeper instance -func NewKeeper( - cdc codec.BinaryMarshaler, key sdk.StoreKey, - clientKeeper types.ClientKeeper, connectionKeeper types.ConnectionKeeper, - portKeeper types.PortKeeper, scopedKeeper capabilitykeeper.ScopedKeeper, -) Keeper { - return Keeper{ - storeKey: key, - cdc: cdc, - clientKeeper: clientKeeper, - connectionKeeper: connectionKeeper, - portKeeper: portKeeper, - scopedKeeper: scopedKeeper, - } -} - -// Logger returns a module-specific logger. -func (k Keeper) Logger(ctx sdk.Context) log.Logger { - return ctx.Logger().With("module", "x/"+host.ModuleName+"/"+types.SubModuleName) -} - -// GenerateChannelIdentifier returns the next channel identifier. -func (k Keeper) GenerateChannelIdentifier(ctx sdk.Context) string { - nextChannelSeq := k.GetNextChannelSequence(ctx) - channelID := types.FormatChannelIdentifier(nextChannelSeq) - - nextChannelSeq++ - k.SetNextChannelSequence(ctx, nextChannelSeq) - return channelID -} - -// GetChannel returns a channel with a particular identifier binded to a specific port -func (k Keeper) GetChannel(ctx sdk.Context, portID, channelID string) (types.Channel, bool) { - store := ctx.KVStore(k.storeKey) - bz := store.Get(host.ChannelKey(portID, channelID)) - if bz == nil { - return types.Channel{}, false - } - - var channel types.Channel - k.cdc.MustUnmarshalBinaryBare(bz, &channel) - return channel, true -} - -// SetChannel sets a channel to the store -func (k Keeper) SetChannel(ctx sdk.Context, portID, channelID string, channel types.Channel) { - store := ctx.KVStore(k.storeKey) - bz := k.cdc.MustMarshalBinaryBare(&channel) - store.Set(host.ChannelKey(portID, channelID), bz) -} - -// GetNextChannelSequence gets the next channel sequence from the store. -func (k Keeper) GetNextChannelSequence(ctx sdk.Context) uint64 { - store := ctx.KVStore(k.storeKey) - bz := store.Get([]byte(types.KeyNextChannelSequence)) - if bz == nil { - panic("next channel sequence is nil") - } - - return sdk.BigEndianToUint64(bz) -} - -// SetNextChannelSequence sets the next channel sequence to the store. -func (k Keeper) SetNextChannelSequence(ctx sdk.Context, sequence uint64) { - store := ctx.KVStore(k.storeKey) - bz := sdk.Uint64ToBigEndian(sequence) - store.Set([]byte(types.KeyNextChannelSequence), bz) -} - -// GetNextSequenceSend gets a channel's next send sequence from the store -func (k Keeper) GetNextSequenceSend(ctx sdk.Context, portID, channelID string) (uint64, bool) { - store := ctx.KVStore(k.storeKey) - bz := store.Get(host.NextSequenceSendKey(portID, channelID)) - if bz == nil { - return 0, false - } - - return sdk.BigEndianToUint64(bz), true -} - -// SetNextSequenceSend sets a channel's next send sequence to the store -func (k Keeper) SetNextSequenceSend(ctx sdk.Context, portID, channelID string, sequence uint64) { - store := ctx.KVStore(k.storeKey) - bz := sdk.Uint64ToBigEndian(sequence) - store.Set(host.NextSequenceSendKey(portID, channelID), bz) -} - -// GetNextSequenceRecv gets a channel's next receive sequence from the store -func (k Keeper) GetNextSequenceRecv(ctx sdk.Context, portID, channelID string) (uint64, bool) { - store := ctx.KVStore(k.storeKey) - bz := store.Get(host.NextSequenceRecvKey(portID, channelID)) - if bz == nil { - return 0, false - } - - return sdk.BigEndianToUint64(bz), true -} - -// SetNextSequenceRecv sets a channel's next receive sequence to the store -func (k Keeper) SetNextSequenceRecv(ctx sdk.Context, portID, channelID string, sequence uint64) { - store := ctx.KVStore(k.storeKey) - bz := sdk.Uint64ToBigEndian(sequence) - store.Set(host.NextSequenceRecvKey(portID, channelID), bz) -} - -// GetNextSequenceAck gets a channel's next ack sequence from the store -func (k Keeper) GetNextSequenceAck(ctx sdk.Context, portID, channelID string) (uint64, bool) { - store := ctx.KVStore(k.storeKey) - bz := store.Get(host.NextSequenceAckKey(portID, channelID)) - if bz == nil { - return 0, false - } - - return sdk.BigEndianToUint64(bz), true -} - -// SetNextSequenceAck sets a channel's next ack sequence to the store -func (k Keeper) SetNextSequenceAck(ctx sdk.Context, portID, channelID string, sequence uint64) { - store := ctx.KVStore(k.storeKey) - bz := sdk.Uint64ToBigEndian(sequence) - store.Set(host.NextSequenceAckKey(portID, channelID), bz) -} - -// GetPacketReceipt gets a packet receipt from the store -func (k Keeper) GetPacketReceipt(ctx sdk.Context, portID, channelID string, sequence uint64) (string, bool) { - store := ctx.KVStore(k.storeKey) - bz := store.Get(host.PacketReceiptKey(portID, channelID, sequence)) - if bz == nil { - return "", false - } - - return string(bz), true -} - -// SetPacketReceipt sets an empty packet receipt to the store -func (k Keeper) SetPacketReceipt(ctx sdk.Context, portID, channelID string, sequence uint64) { - store := ctx.KVStore(k.storeKey) - store.Set(host.PacketReceiptKey(portID, channelID, sequence), []byte{byte(1)}) -} - -// GetPacketCommitment gets the packet commitment hash from the store -func (k Keeper) GetPacketCommitment(ctx sdk.Context, portID, channelID string, sequence uint64) []byte { - store := ctx.KVStore(k.storeKey) - bz := store.Get(host.PacketCommitmentKey(portID, channelID, sequence)) - return bz -} - -// HasPacketCommitment returns true if the packet commitment exists -func (k Keeper) HasPacketCommitment(ctx sdk.Context, portID, channelID string, sequence uint64) bool { - store := ctx.KVStore(k.storeKey) - return store.Has(host.PacketCommitmentKey(portID, channelID, sequence)) -} - -// SetPacketCommitment sets the packet commitment hash to the store -func (k Keeper) SetPacketCommitment(ctx sdk.Context, portID, channelID string, sequence uint64, commitmentHash []byte) { - store := ctx.KVStore(k.storeKey) - store.Set(host.PacketCommitmentKey(portID, channelID, sequence), commitmentHash) -} - -func (k Keeper) deletePacketCommitment(ctx sdk.Context, portID, channelID string, sequence uint64) { - store := ctx.KVStore(k.storeKey) - store.Delete(host.PacketCommitmentKey(portID, channelID, sequence)) -} - -// SetPacketAcknowledgement sets the packet ack hash to the store -func (k Keeper) SetPacketAcknowledgement(ctx sdk.Context, portID, channelID string, sequence uint64, ackHash []byte) { - store := ctx.KVStore(k.storeKey) - store.Set(host.PacketAcknowledgementKey(portID, channelID, sequence), ackHash) -} - -// GetPacketAcknowledgement gets the packet ack hash from the store -func (k Keeper) GetPacketAcknowledgement(ctx sdk.Context, portID, channelID string, sequence uint64) ([]byte, bool) { - store := ctx.KVStore(k.storeKey) - bz := store.Get(host.PacketAcknowledgementKey(portID, channelID, sequence)) - if bz == nil { - return nil, false - } - return bz, true -} - -// HasPacketAcknowledgement check if the packet ack hash is already on the store -func (k Keeper) HasPacketAcknowledgement(ctx sdk.Context, portID, channelID string, sequence uint64) bool { - store := ctx.KVStore(k.storeKey) - return store.Has(host.PacketAcknowledgementKey(portID, channelID, sequence)) -} - -// IteratePacketSequence provides an iterator over all send, receive or ack sequences. -// For each sequence, cb will be called. If the cb returns true, the iterator -// will close and stop. -func (k Keeper) IteratePacketSequence(ctx sdk.Context, iterator db.Iterator, cb func(portID, channelID string, sequence uint64) bool) { - defer iterator.Close() - for ; iterator.Valid(); iterator.Next() { - portID, channelID, err := host.ParseChannelPath(string(iterator.Key())) - if err != nil { - // return if the key is not a channel key - return - } - - sequence := sdk.BigEndianToUint64(iterator.Value()) - - if cb(portID, channelID, sequence) { - break - } - } -} - -// GetAllPacketSendSeqs returns all stored next send sequences. -func (k Keeper) GetAllPacketSendSeqs(ctx sdk.Context) (seqs []types.PacketSequence) { - store := ctx.KVStore(k.storeKey) - iterator := sdk.KVStorePrefixIterator(store, []byte(host.KeyNextSeqSendPrefix)) - k.IteratePacketSequence(ctx, iterator, func(portID, channelID string, nextSendSeq uint64) bool { - ps := types.NewPacketSequence(portID, channelID, nextSendSeq) - seqs = append(seqs, ps) - return false - }) - return seqs -} - -// GetAllPacketRecvSeqs returns all stored next recv sequences. -func (k Keeper) GetAllPacketRecvSeqs(ctx sdk.Context) (seqs []types.PacketSequence) { - store := ctx.KVStore(k.storeKey) - iterator := sdk.KVStorePrefixIterator(store, []byte(host.KeyNextSeqRecvPrefix)) - k.IteratePacketSequence(ctx, iterator, func(portID, channelID string, nextRecvSeq uint64) bool { - ps := types.NewPacketSequence(portID, channelID, nextRecvSeq) - seqs = append(seqs, ps) - return false - }) - return seqs -} - -// GetAllPacketAckSeqs returns all stored next acknowledgements sequences. -func (k Keeper) GetAllPacketAckSeqs(ctx sdk.Context) (seqs []types.PacketSequence) { - store := ctx.KVStore(k.storeKey) - iterator := sdk.KVStorePrefixIterator(store, []byte(host.KeyNextSeqAckPrefix)) - k.IteratePacketSequence(ctx, iterator, func(portID, channelID string, nextAckSeq uint64) bool { - ps := types.NewPacketSequence(portID, channelID, nextAckSeq) - seqs = append(seqs, ps) - return false - }) - return seqs -} - -// IteratePacketCommitment provides an iterator over all PacketCommitment objects. For each -// packet commitment, cb will be called. If the cb returns true, the iterator will close -// and stop. -func (k Keeper) IteratePacketCommitment(ctx sdk.Context, cb func(portID, channelID string, sequence uint64, hash []byte) bool) { - store := ctx.KVStore(k.storeKey) - iterator := sdk.KVStorePrefixIterator(store, []byte(host.KeyPacketCommitmentPrefix)) - k.iterateHashes(ctx, iterator, cb) -} - -// GetAllPacketCommitments returns all stored PacketCommitments objects. -func (k Keeper) GetAllPacketCommitments(ctx sdk.Context) (commitments []types.PacketState) { - k.IteratePacketCommitment(ctx, func(portID, channelID string, sequence uint64, hash []byte) bool { - pc := types.NewPacketState(portID, channelID, sequence, hash) - commitments = append(commitments, pc) - return false - }) - return commitments -} - -// IteratePacketCommitmentAtChannel provides an iterator over all PacketCommmitment objects -// at a specified channel. For each packet commitment, cb will be called. If the cb returns -// true, the iterator will close and stop. -func (k Keeper) IteratePacketCommitmentAtChannel(ctx sdk.Context, portID, channelID string, cb func(_, _ string, sequence uint64, hash []byte) bool) { - store := ctx.KVStore(k.storeKey) - iterator := sdk.KVStorePrefixIterator(store, []byte(host.PacketCommitmentPrefixPath(portID, channelID))) - k.iterateHashes(ctx, iterator, cb) -} - -// GetAllPacketCommitmentsAtChannel returns all stored PacketCommitments objects for a specified -// port ID and channel ID. -func (k Keeper) GetAllPacketCommitmentsAtChannel(ctx sdk.Context, portID, channelID string) (commitments []types.PacketState) { - k.IteratePacketCommitmentAtChannel(ctx, portID, channelID, func(_, _ string, sequence uint64, hash []byte) bool { - pc := types.NewPacketState(portID, channelID, sequence, hash) - commitments = append(commitments, pc) - return false - }) - return commitments -} - -// IteratePacketReceipt provides an iterator over all PacketReceipt objects. For each -// receipt, cb will be called. If the cb returns true, the iterator will close -// and stop. -func (k Keeper) IteratePacketReceipt(ctx sdk.Context, cb func(portID, channelID string, sequence uint64, receipt []byte) bool) { - store := ctx.KVStore(k.storeKey) - iterator := sdk.KVStorePrefixIterator(store, []byte(host.KeyPacketReceiptPrefix)) - k.iterateHashes(ctx, iterator, cb) -} - -// GetAllPacketReceipts returns all stored PacketReceipt objects. -func (k Keeper) GetAllPacketReceipts(ctx sdk.Context) (receipts []types.PacketState) { - k.IteratePacketReceipt(ctx, func(portID, channelID string, sequence uint64, receipt []byte) bool { - packetReceipt := types.NewPacketState(portID, channelID, sequence, receipt) - receipts = append(receipts, packetReceipt) - return false - }) - return receipts -} - -// IteratePacketAcknowledgement provides an iterator over all PacketAcknowledgement objects. For each -// aknowledgement, cb will be called. If the cb returns true, the iterator will close -// and stop. -func (k Keeper) IteratePacketAcknowledgement(ctx sdk.Context, cb func(portID, channelID string, sequence uint64, hash []byte) bool) { - store := ctx.KVStore(k.storeKey) - iterator := sdk.KVStorePrefixIterator(store, []byte(host.KeyPacketAckPrefix)) - k.iterateHashes(ctx, iterator, cb) -} - -// GetAllPacketAcks returns all stored PacketAcknowledgements objects. -func (k Keeper) GetAllPacketAcks(ctx sdk.Context) (acks []types.PacketState) { - k.IteratePacketAcknowledgement(ctx, func(portID, channelID string, sequence uint64, ack []byte) bool { - packetAck := types.NewPacketState(portID, channelID, sequence, ack) - acks = append(acks, packetAck) - return false - }) - return acks -} - -// IterateChannels provides an iterator over all Channel objects. For each -// Channel, cb will be called. If the cb returns true, the iterator will close -// and stop. -func (k Keeper) IterateChannels(ctx sdk.Context, cb func(types.IdentifiedChannel) bool) { - store := ctx.KVStore(k.storeKey) - iterator := sdk.KVStorePrefixIterator(store, []byte(host.KeyChannelEndPrefix)) - - defer iterator.Close() - for ; iterator.Valid(); iterator.Next() { - var channel types.Channel - k.cdc.MustUnmarshalBinaryBare(iterator.Value(), &channel) - - portID, channelID := host.MustParseChannelPath(string(iterator.Key())) - identifiedChannel := types.NewIdentifiedChannel(portID, channelID, channel) - if cb(identifiedChannel) { - break - } - } -} - -// GetAllChannels returns all stored Channel objects. -func (k Keeper) GetAllChannels(ctx sdk.Context) (channels []types.IdentifiedChannel) { - k.IterateChannels(ctx, func(channel types.IdentifiedChannel) bool { - channels = append(channels, channel) - return false - }) - return channels -} - -// GetChannelClientState returns the associated client state with its ID, from a port and channel identifier. -func (k Keeper) GetChannelClientState(ctx sdk.Context, portID, channelID string) (string, exported.ClientState, error) { - channel, found := k.GetChannel(ctx, portID, channelID) - if !found { - return "", nil, sdkerrors.Wrapf(types.ErrChannelNotFound, "port-id: %s, channel-id: %s", portID, channelID) - } - - connection, found := k.connectionKeeper.GetConnection(ctx, channel.ConnectionHops[0]) - if !found { - return "", nil, sdkerrors.Wrapf(connectiontypes.ErrConnectionNotFound, "connection-id: %s", channel.ConnectionHops[0]) - } - - clientState, found := k.clientKeeper.GetClientState(ctx, connection.ClientId) - if !found { - return "", nil, sdkerrors.Wrapf(clienttypes.ErrClientNotFound, "client-id: %s", connection.ClientId) - } - - return connection.ClientId, clientState, nil -} - -// LookupModuleByChannel will return the IBCModule along with the capability associated with a given channel defined by its portID and channelID -func (k Keeper) LookupModuleByChannel(ctx sdk.Context, portID, channelID string) (string, *capabilitytypes.Capability, error) { - modules, cap, err := k.scopedKeeper.LookupModules(ctx, host.ChannelCapabilityPath(portID, channelID)) - if err != nil { - return "", nil, err - } - - return porttypes.GetModuleOwner(modules), cap, nil -} - -// common functionality for IteratePacketCommitment and IteratePacketAcknowledgement -func (k Keeper) iterateHashes(_ sdk.Context, iterator db.Iterator, cb func(portID, channelID string, sequence uint64, hash []byte) bool) { - defer iterator.Close() - - for ; iterator.Valid(); iterator.Next() { - keySplit := strings.Split(string(iterator.Key()), "/") - portID := keySplit[2] - channelID := keySplit[4] - - sequence, err := strconv.ParseUint(keySplit[len(keySplit)-1], 10, 64) - if err != nil { - panic(err) - } - - if cb(portID, channelID, sequence, iterator.Value()) { - break - } - } -} diff --git a/x/ibc/core/04-channel/keeper/keeper_test.go b/x/ibc/core/04-channel/keeper/keeper_test.go deleted file mode 100644 index a9b7dd6cf1c6..000000000000 --- a/x/ibc/core/04-channel/keeper/keeper_test.go +++ /dev/null @@ -1,329 +0,0 @@ -package keeper_test - -import ( - "testing" - - "github.com/stretchr/testify/suite" - - "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" -) - -// KeeperTestSuite is a testing suite to test keeper functions. -type KeeperTestSuite struct { - suite.Suite - - coordinator *ibctesting.Coordinator - - // testing chains used for convenience and readability - chainA *ibctesting.TestChain - chainB *ibctesting.TestChain -} - -// TestKeeperTestSuite runs all the tests within this package. -func TestKeeperTestSuite(t *testing.T) { - suite.Run(t, new(KeeperTestSuite)) -} - -// SetupTest creates a coordinator with 2 test chains. -func (suite *KeeperTestSuite) SetupTest() { - suite.coordinator = ibctesting.NewCoordinator(suite.T(), 2) - suite.chainA = suite.coordinator.GetChain(ibctesting.GetChainID(0)) - suite.chainB = suite.coordinator.GetChain(ibctesting.GetChainID(1)) - // commit some blocks so that QueryProof returns valid proof (cannot return valid query if height <= 1) - suite.coordinator.CommitNBlocks(suite.chainA, 2) - suite.coordinator.CommitNBlocks(suite.chainB, 2) -} - -// TestSetChannel create clients and connections on both chains. It tests for the non-existence -// and existence of a channel in INIT on chainA. -func (suite *KeeperTestSuite) TestSetChannel() { - // create client and connections on both chains - _, _, connA, connB := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - - // check for channel to be created on chainA - channelA := suite.chainA.NextTestChannel(connA, ibctesting.MockPort) - _, found := suite.chainA.App.IBCKeeper.ChannelKeeper.GetChannel(suite.chainA.GetContext(), channelA.PortID, channelA.ID) - suite.False(found) - - // init channel - channelA, channelB, err := suite.coordinator.ChanOpenInit(suite.chainA, suite.chainB, connA, connB, ibctesting.MockPort, ibctesting.MockPort, types.ORDERED) - suite.NoError(err) - - storedChannel, found := suite.chainA.App.IBCKeeper.ChannelKeeper.GetChannel(suite.chainA.GetContext(), channelA.PortID, channelA.ID) - // counterparty channel id is empty after open init - expectedCounterparty := types.NewCounterparty(channelB.PortID, "") - - suite.True(found) - suite.Equal(types.INIT, storedChannel.State) - suite.Equal(types.ORDERED, storedChannel.Ordering) - suite.Equal(expectedCounterparty, storedChannel.Counterparty) -} - -// TestGetAllChannels creates multiple channels on chain A through various connections -// and tests their retrieval. 2 channels are on connA0 and 1 channel is on connA1 -func (suite KeeperTestSuite) TestGetAllChannels() { - clientA, clientB, connA0, connB0, testchannel0, _ := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - // channel0 on first connection on chainA - counterparty0 := types.Counterparty{ - PortId: connB0.Channels[0].PortID, - ChannelId: connB0.Channels[0].ID, - } - - // channel1 is second channel on first connection on chainA - testchannel1, _ := suite.coordinator.CreateMockChannels(suite.chainA, suite.chainB, connA0, connB0, types.ORDERED) - counterparty1 := types.Counterparty{ - PortId: connB0.Channels[1].PortID, - ChannelId: connB0.Channels[1].ID, - } - - connA1, connB1 := suite.coordinator.CreateConnection(suite.chainA, suite.chainB, clientA, clientB) - - // channel2 is on a second connection on chainA - testchannel2, _, err := suite.coordinator.ChanOpenInit(suite.chainA, suite.chainB, connA1, connB1, ibctesting.MockPort, ibctesting.MockPort, types.UNORDERED) - suite.Require().NoError(err) - - // counterparty channel id is empty after open init - counterparty2 := types.Counterparty{ - PortId: connB1.Channels[0].PortID, - ChannelId: "", - } - - channel0 := types.NewChannel( - types.OPEN, types.UNORDERED, - counterparty0, []string{connA0.ID}, testchannel0.Version, - ) - channel1 := types.NewChannel( - types.OPEN, types.ORDERED, - counterparty1, []string{connA0.ID}, testchannel1.Version, - ) - channel2 := types.NewChannel( - types.INIT, types.UNORDERED, - counterparty2, []string{connA1.ID}, testchannel2.Version, - ) - - expChannels := []types.IdentifiedChannel{ - types.NewIdentifiedChannel(testchannel0.PortID, testchannel0.ID, channel0), - types.NewIdentifiedChannel(testchannel1.PortID, testchannel1.ID, channel1), - types.NewIdentifiedChannel(testchannel2.PortID, testchannel2.ID, channel2), - } - - ctxA := suite.chainA.GetContext() - - channels := suite.chainA.App.IBCKeeper.ChannelKeeper.GetAllChannels(ctxA) - suite.Require().Len(channels, len(expChannels)) - suite.Require().Equal(expChannels, channels) -} - -// TestGetAllSequences sets all packet sequences for two different channels on chain A and -// tests their retrieval. -func (suite KeeperTestSuite) TestGetAllSequences() { - _, _, connA, connB, channelA0, _ := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - channelA1, _ := suite.coordinator.CreateMockChannels(suite.chainA, suite.chainB, connA, connB, types.UNORDERED) - - seq1 := types.NewPacketSequence(channelA0.PortID, channelA0.ID, 1) - seq2 := types.NewPacketSequence(channelA0.PortID, channelA0.ID, 2) - seq3 := types.NewPacketSequence(channelA1.PortID, channelA1.ID, 3) - - // seq1 should be overwritten by seq2 - expSeqs := []types.PacketSequence{seq2, seq3} - - ctxA := suite.chainA.GetContext() - - for _, seq := range []types.PacketSequence{seq1, seq2, seq3} { - suite.chainA.App.IBCKeeper.ChannelKeeper.SetNextSequenceSend(ctxA, seq.PortId, seq.ChannelId, seq.Sequence) - suite.chainA.App.IBCKeeper.ChannelKeeper.SetNextSequenceRecv(ctxA, seq.PortId, seq.ChannelId, seq.Sequence) - suite.chainA.App.IBCKeeper.ChannelKeeper.SetNextSequenceAck(ctxA, seq.PortId, seq.ChannelId, seq.Sequence) - } - - sendSeqs := suite.chainA.App.IBCKeeper.ChannelKeeper.GetAllPacketSendSeqs(ctxA) - recvSeqs := suite.chainA.App.IBCKeeper.ChannelKeeper.GetAllPacketRecvSeqs(ctxA) - ackSeqs := suite.chainA.App.IBCKeeper.ChannelKeeper.GetAllPacketAckSeqs(ctxA) - suite.Len(sendSeqs, 2) - suite.Len(recvSeqs, 2) - suite.Len(ackSeqs, 2) - - suite.Equal(expSeqs, sendSeqs) - suite.Equal(expSeqs, recvSeqs) - suite.Equal(expSeqs, ackSeqs) -} - -// TestGetAllPacketState creates a set of acks, packet commitments, and receipts on two different -// channels on chain A and tests their retrieval. -func (suite KeeperTestSuite) TestGetAllPacketState() { - _, _, connA, connB, channelA0, _ := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - channelA1, _ := suite.coordinator.CreateMockChannels(suite.chainA, suite.chainB, connA, connB, types.UNORDERED) - - // channel 0 acks - ack1 := types.NewPacketState(channelA0.PortID, channelA0.ID, 1, []byte("ack")) - ack2 := types.NewPacketState(channelA0.PortID, channelA0.ID, 2, []byte("ack")) - - // duplicate ack - ack2dup := types.NewPacketState(channelA0.PortID, channelA0.ID, 2, []byte("ack")) - - // channel 1 acks - ack3 := types.NewPacketState(channelA1.PortID, channelA1.ID, 1, []byte("ack")) - - // create channel 0 receipts - receipt := string([]byte{byte(1)}) - rec1 := types.NewPacketState(channelA0.PortID, channelA0.ID, 1, []byte(receipt)) - rec2 := types.NewPacketState(channelA0.PortID, channelA0.ID, 2, []byte(receipt)) - - // channel 1 receipts - rec3 := types.NewPacketState(channelA1.PortID, channelA1.ID, 1, []byte(receipt)) - rec4 := types.NewPacketState(channelA1.PortID, channelA1.ID, 2, []byte(receipt)) - - // channel 0 packet commitments - comm1 := types.NewPacketState(channelA0.PortID, channelA0.ID, 1, []byte("hash")) - comm2 := types.NewPacketState(channelA0.PortID, channelA0.ID, 2, []byte("hash")) - - // channel 1 packet commitments - comm3 := types.NewPacketState(channelA1.PortID, channelA1.ID, 1, []byte("hash")) - comm4 := types.NewPacketState(channelA1.PortID, channelA1.ID, 2, []byte("hash")) - - expAcks := []types.PacketState{ack1, ack2, ack3} - expReceipts := []types.PacketState{rec1, rec2, rec3, rec4} - expCommitments := []types.PacketState{comm1, comm2, comm3, comm4} - - ctxA := suite.chainA.GetContext() - - // set acknowledgements - for _, ack := range []types.PacketState{ack1, ack2, ack2dup, ack3} { - suite.chainA.App.IBCKeeper.ChannelKeeper.SetPacketAcknowledgement(ctxA, ack.PortId, ack.ChannelId, ack.Sequence, ack.Data) - } - - // set packet receipts - for _, rec := range expReceipts { - suite.chainA.App.IBCKeeper.ChannelKeeper.SetPacketReceipt(ctxA, rec.PortId, rec.ChannelId, rec.Sequence) - } - - // set packet commitments - for _, comm := range expCommitments { - suite.chainA.App.IBCKeeper.ChannelKeeper.SetPacketCommitment(ctxA, comm.PortId, comm.ChannelId, comm.Sequence, comm.Data) - } - - acks := suite.chainA.App.IBCKeeper.ChannelKeeper.GetAllPacketAcks(ctxA) - receipts := suite.chainA.App.IBCKeeper.ChannelKeeper.GetAllPacketReceipts(ctxA) - commitments := suite.chainA.App.IBCKeeper.ChannelKeeper.GetAllPacketCommitments(ctxA) - - suite.Require().Len(acks, len(expAcks)) - suite.Require().Len(commitments, len(expCommitments)) - suite.Require().Len(receipts, len(expReceipts)) - - suite.Require().Equal(expAcks, acks) - suite.Require().Equal(expReceipts, receipts) - suite.Require().Equal(expCommitments, commitments) -} - -// TestSetSequence verifies that the keeper correctly sets the sequence counters. -func (suite *KeeperTestSuite) TestSetSequence() { - _, _, _, _, channelA, _ := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - - ctxA := suite.chainA.GetContext() - one := uint64(1) - - // initialized channel has next send seq of 1 - seq, found := suite.chainA.App.IBCKeeper.ChannelKeeper.GetNextSequenceSend(ctxA, channelA.PortID, channelA.ID) - suite.True(found) - suite.Equal(one, seq) - - // initialized channel has next seq recv of 1 - seq, found = suite.chainA.App.IBCKeeper.ChannelKeeper.GetNextSequenceRecv(ctxA, channelA.PortID, channelA.ID) - suite.True(found) - suite.Equal(one, seq) - - // initialized channel has next seq ack of - seq, found = suite.chainA.App.IBCKeeper.ChannelKeeper.GetNextSequenceAck(ctxA, channelA.PortID, channelA.ID) - suite.True(found) - suite.Equal(one, seq) - - nextSeqSend, nextSeqRecv, nextSeqAck := uint64(10), uint64(10), uint64(10) - suite.chainA.App.IBCKeeper.ChannelKeeper.SetNextSequenceSend(ctxA, channelA.PortID, channelA.ID, nextSeqSend) - suite.chainA.App.IBCKeeper.ChannelKeeper.SetNextSequenceRecv(ctxA, channelA.PortID, channelA.ID, nextSeqRecv) - suite.chainA.App.IBCKeeper.ChannelKeeper.SetNextSequenceAck(ctxA, channelA.PortID, channelA.ID, nextSeqAck) - - storedNextSeqSend, found := suite.chainA.App.IBCKeeper.ChannelKeeper.GetNextSequenceSend(ctxA, channelA.PortID, channelA.ID) - suite.True(found) - suite.Equal(nextSeqSend, storedNextSeqSend) - - storedNextSeqRecv, found := suite.chainA.App.IBCKeeper.ChannelKeeper.GetNextSequenceSend(ctxA, channelA.PortID, channelA.ID) - suite.True(found) - suite.Equal(nextSeqRecv, storedNextSeqRecv) - - storedNextSeqAck, found := suite.chainA.App.IBCKeeper.ChannelKeeper.GetNextSequenceAck(ctxA, channelA.PortID, channelA.ID) - suite.True(found) - suite.Equal(nextSeqAck, storedNextSeqAck) -} - -// TestGetAllPacketCommitmentsAtChannel verifies that the keeper returns all stored packet -// commitments for a specific channel. The test will store consecutive commitments up to the -// value of "seq" and then add non-consecutive up to the value of "maxSeq". A final commitment -// with the value maxSeq + 1 is set on a different channel. -func (suite *KeeperTestSuite) TestGetAllPacketCommitmentsAtChannel() { - _, _, connA, connB, channelA, _ := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - - // create second channel - channelA1, _ := suite.coordinator.CreateMockChannels(suite.chainA, suite.chainB, connA, connB, types.UNORDERED) - - ctxA := suite.chainA.GetContext() - expectedSeqs := make(map[uint64]bool) - hash := []byte("commitment") - - seq := uint64(15) - maxSeq := uint64(25) - suite.Require().Greater(maxSeq, seq) - - // create consecutive commitments - for i := uint64(1); i < seq; i++ { - suite.chainA.App.IBCKeeper.ChannelKeeper.SetPacketCommitment(ctxA, channelA.PortID, channelA.ID, i, hash) - expectedSeqs[i] = true - } - - // add non-consecutive commitments - for i := seq; i < maxSeq; i += 2 { - suite.chainA.App.IBCKeeper.ChannelKeeper.SetPacketCommitment(ctxA, channelA.PortID, channelA.ID, i, hash) - expectedSeqs[i] = true - } - - // add sequence on different channel/port - suite.chainA.App.IBCKeeper.ChannelKeeper.SetPacketCommitment(ctxA, channelA1.PortID, channelA1.ID, maxSeq+1, hash) - - commitments := suite.chainA.App.IBCKeeper.ChannelKeeper.GetAllPacketCommitmentsAtChannel(ctxA, channelA.PortID, channelA.ID) - - suite.Equal(len(expectedSeqs), len(commitments)) - // ensure above for loops occurred - suite.NotEqual(0, len(commitments)) - - // verify that all the packet commitments were stored - for _, packet := range commitments { - suite.True(expectedSeqs[packet.Sequence]) - suite.Equal(channelA.PortID, packet.PortId) - suite.Equal(channelA.ID, packet.ChannelId) - suite.Equal(hash, packet.Data) - - // prevent duplicates from passing checks - expectedSeqs[packet.Sequence] = false - } -} - -// TestSetPacketAcknowledgement verifies that packet acknowledgements are correctly -// set in the keeper. -func (suite *KeeperTestSuite) TestSetPacketAcknowledgement() { - _, _, _, _, channelA, _ := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - - ctxA := suite.chainA.GetContext() - seq := uint64(10) - - storedAckHash, found := suite.chainA.App.IBCKeeper.ChannelKeeper.GetPacketAcknowledgement(ctxA, channelA.PortID, channelA.ID, seq) - suite.Require().False(found) - suite.Require().Nil(storedAckHash) - - ackHash := []byte("ackhash") - suite.chainA.App.IBCKeeper.ChannelKeeper.SetPacketAcknowledgement(ctxA, channelA.PortID, channelA.ID, seq, ackHash) - - storedAckHash, found = suite.chainA.App.IBCKeeper.ChannelKeeper.GetPacketAcknowledgement(ctxA, channelA.PortID, channelA.ID, seq) - suite.Require().True(found) - suite.Require().Equal(ackHash, storedAckHash) - suite.Require().True(suite.chainA.App.IBCKeeper.ChannelKeeper.HasPacketAcknowledgement(ctxA, channelA.PortID, channelA.ID, seq)) -} diff --git a/x/ibc/core/04-channel/keeper/packet.go b/x/ibc/core/04-channel/keeper/packet.go deleted file mode 100644 index 49b59733c5a3..000000000000 --- a/x/ibc/core/04-channel/keeper/packet.go +++ /dev/null @@ -1,528 +0,0 @@ -package keeper - -import ( - "bytes" - "fmt" - "time" - - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -// SendPacket is called by a module in order to send an IBC packet on a channel -// end owned by the calling module to the corresponding module on the counterparty -// chain. -func (k Keeper) SendPacket( - ctx sdk.Context, - channelCap *capabilitytypes.Capability, - packet exported.PacketI, -) error { - if err := packet.ValidateBasic(); err != nil { - return sdkerrors.Wrap(err, "packet failed basic validation") - } - - channel, found := k.GetChannel(ctx, packet.GetSourcePort(), packet.GetSourceChannel()) - if !found { - return sdkerrors.Wrap(types.ErrChannelNotFound, packet.GetSourceChannel()) - } - - if channel.State == types.CLOSED { - return sdkerrors.Wrapf( - types.ErrInvalidChannelState, - "channel is CLOSED (got %s)", channel.State.String(), - ) - } - - if !k.scopedKeeper.AuthenticateCapability(ctx, channelCap, host.ChannelCapabilityPath(packet.GetSourcePort(), packet.GetSourceChannel())) { - return sdkerrors.Wrapf(types.ErrChannelCapabilityNotFound, "caller does not own capability for channel, port ID (%s) channel ID (%s)", packet.GetSourcePort(), packet.GetSourceChannel()) - } - - if packet.GetDestPort() != channel.Counterparty.PortId { - return sdkerrors.Wrapf( - types.ErrInvalidPacket, - "packet destination port doesn't match the counterparty's port (%s ≠ %s)", packet.GetDestPort(), channel.Counterparty.PortId, - ) - } - - if packet.GetDestChannel() != channel.Counterparty.ChannelId { - return sdkerrors.Wrapf( - types.ErrInvalidPacket, - "packet destination channel doesn't match the counterparty's channel (%s ≠ %s)", packet.GetDestChannel(), channel.Counterparty.ChannelId, - ) - } - - connectionEnd, found := k.connectionKeeper.GetConnection(ctx, channel.ConnectionHops[0]) - if !found { - return sdkerrors.Wrap(connectiontypes.ErrConnectionNotFound, channel.ConnectionHops[0]) - } - - clientState, found := k.clientKeeper.GetClientState(ctx, connectionEnd.GetClientID()) - if !found { - return clienttypes.ErrConsensusStateNotFound - } - - // prevent accidental sends with clients that cannot be updated - if clientState.IsFrozen() { - return sdkerrors.Wrapf(clienttypes.ErrClientFrozen, "cannot send packet on a frozen client with ID %s", connectionEnd.GetClientID()) - } - - // check if packet timeouted on the receiving chain - latestHeight := clientState.GetLatestHeight() - timeoutHeight := packet.GetTimeoutHeight() - if !timeoutHeight.IsZero() && latestHeight.GTE(timeoutHeight) { - return sdkerrors.Wrapf( - types.ErrPacketTimeout, - "receiving chain block height >= packet timeout height (%s >= %s)", latestHeight, timeoutHeight, - ) - } - - latestTimestamp, err := k.connectionKeeper.GetTimestampAtHeight(ctx, connectionEnd, latestHeight) - if err != nil { - return err - } - - if packet.GetTimeoutTimestamp() != 0 && latestTimestamp >= packet.GetTimeoutTimestamp() { - return sdkerrors.Wrapf( - types.ErrPacketTimeout, - "receiving chain block timestamp >= packet timeout timestamp (%s >= %s)", time.Unix(0, int64(latestTimestamp)), time.Unix(0, int64(packet.GetTimeoutTimestamp())), - ) - } - - nextSequenceSend, found := k.GetNextSequenceSend(ctx, packet.GetSourcePort(), packet.GetSourceChannel()) - if !found { - return sdkerrors.Wrapf( - types.ErrSequenceSendNotFound, - "source port: %s, source channel: %s", packet.GetSourcePort(), packet.GetSourceChannel(), - ) - } - - if packet.GetSequence() != nextSequenceSend { - return sdkerrors.Wrapf( - types.ErrInvalidPacket, - "packet sequence ≠ next send sequence (%d ≠ %d)", packet.GetSequence(), nextSequenceSend, - ) - } - - commitment := types.CommitPacket(k.cdc, packet) - - nextSequenceSend++ - k.SetNextSequenceSend(ctx, packet.GetSourcePort(), packet.GetSourceChannel(), nextSequenceSend) - k.SetPacketCommitment(ctx, packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence(), commitment) - - // Emit Event with Packet data along with other packet information for relayer to pick up - // and relay to other chain - ctx.EventManager().EmitEvents(sdk.Events{ - sdk.NewEvent( - types.EventTypeSendPacket, - sdk.NewAttribute(types.AttributeKeyData, string(packet.GetData())), - sdk.NewAttribute(types.AttributeKeyTimeoutHeight, timeoutHeight.String()), - sdk.NewAttribute(types.AttributeKeyTimeoutTimestamp, fmt.Sprintf("%d", packet.GetTimeoutTimestamp())), - sdk.NewAttribute(types.AttributeKeySequence, fmt.Sprintf("%d", packet.GetSequence())), - sdk.NewAttribute(types.AttributeKeySrcPort, packet.GetSourcePort()), - sdk.NewAttribute(types.AttributeKeySrcChannel, packet.GetSourceChannel()), - 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, - sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), - ), - }) - - k.Logger(ctx).Info("packet sent", "packet", fmt.Sprintf("%v", packet)) - return nil -} - -// RecvPacket is called by a module in order to receive & process an IBC packet -// sent on the corresponding channel end on the counterparty chain. -func (k Keeper) RecvPacket( - ctx sdk.Context, - chanCap *capabilitytypes.Capability, - packet exported.PacketI, - proof []byte, - proofHeight exported.Height, -) error { - channel, found := k.GetChannel(ctx, packet.GetDestPort(), packet.GetDestChannel()) - if !found { - return sdkerrors.Wrap(types.ErrChannelNotFound, packet.GetDestChannel()) - } - - if channel.State != types.OPEN { - return sdkerrors.Wrapf( - types.ErrInvalidChannelState, - "channel state is not OPEN (got %s)", channel.State.String(), - ) - } - - // Authenticate capability to ensure caller has authority to receive packet on this channel - capName := host.ChannelCapabilityPath(packet.GetDestPort(), packet.GetDestChannel()) - if !k.scopedKeeper.AuthenticateCapability(ctx, chanCap, capName) { - return sdkerrors.Wrapf( - types.ErrInvalidChannelCapability, - "channel capability failed authentication for capability name %s", capName, - ) - } - - // packet must come from the channel's counterparty - if packet.GetSourcePort() != channel.Counterparty.PortId { - return sdkerrors.Wrapf( - types.ErrInvalidPacket, - "packet source port doesn't match the counterparty's port (%s ≠ %s)", packet.GetSourcePort(), channel.Counterparty.PortId, - ) - } - - if packet.GetSourceChannel() != channel.Counterparty.ChannelId { - return sdkerrors.Wrapf( - types.ErrInvalidPacket, - "packet source channel doesn't match the counterparty's channel (%s ≠ %s)", packet.GetSourceChannel(), channel.Counterparty.ChannelId, - ) - } - - // Connection must be OPEN to receive a packet. It is possible for connection to not yet be open if packet was - // sent optimistically before connection and channel handshake completed. However, to receive a packet, - // connection and channel must both be open - connectionEnd, found := k.connectionKeeper.GetConnection(ctx, channel.ConnectionHops[0]) - if !found { - return sdkerrors.Wrap(connectiontypes.ErrConnectionNotFound, channel.ConnectionHops[0]) - } - - if connectionEnd.GetState() != int32(connectiontypes.OPEN) { - return sdkerrors.Wrapf( - connectiontypes.ErrInvalidConnectionState, - "connection state is not OPEN (got %s)", connectiontypes.State(connectionEnd.GetState()).String(), - ) - } - - // check if packet timeouted by comparing it with the latest height of the chain - selfHeight := clienttypes.GetSelfHeight(ctx) - timeoutHeight := packet.GetTimeoutHeight() - if !timeoutHeight.IsZero() && selfHeight.GTE(timeoutHeight) { - return sdkerrors.Wrapf( - types.ErrPacketTimeout, - "block height >= packet timeout height (%s >= %s)", selfHeight, timeoutHeight, - ) - } - - // check if packet timeouted by comparing it with the latest timestamp of the chain - if packet.GetTimeoutTimestamp() != 0 && uint64(ctx.BlockTime().UnixNano()) >= packet.GetTimeoutTimestamp() { - return sdkerrors.Wrapf( - types.ErrPacketTimeout, - "block timestamp >= packet timeout timestamp (%s >= %s)", ctx.BlockTime(), time.Unix(0, int64(packet.GetTimeoutTimestamp())), - ) - } - - commitment := types.CommitPacket(k.cdc, packet) - - // verify that the counterparty did commit to sending this packet - if err := k.connectionKeeper.VerifyPacketCommitment( - ctx, connectionEnd, proofHeight, proof, - packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence(), - commitment, - ); err != nil { - return sdkerrors.Wrap(err, "couldn't verify counterparty packet commitment") - } - - switch channel.Ordering { - case types.UNORDERED: - // check if the packet receipt has been received already for unordered channels - _, found := k.GetPacketReceipt(ctx, packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - if found { - return sdkerrors.Wrapf( - types.ErrInvalidPacket, - "packet sequence (%d) already has been received", packet.GetSequence(), - ) - } - - // All verification complete, update state - // For unordered channels we must set the receipt so it can be verified on the other side. - // This receipt does not contain any data, since the packet has not yet been processed, - // it's just a single store key set to an empty string to indicate that the packet has been received - k.SetPacketReceipt(ctx, packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - - case types.ORDERED: - // check if the packet is being received in order - nextSequenceRecv, found := k.GetNextSequenceRecv(ctx, packet.GetDestPort(), packet.GetDestChannel()) - if !found { - return sdkerrors.Wrapf( - types.ErrSequenceReceiveNotFound, - "destination port: %s, destination channel: %s", packet.GetDestPort(), packet.GetDestChannel(), - ) - } - - if packet.GetSequence() != nextSequenceRecv { - return sdkerrors.Wrapf( - types.ErrInvalidPacket, - "packet sequence ≠ next receive sequence (%d ≠ %d)", packet.GetSequence(), nextSequenceRecv, - ) - } - - // All verification complete, update state - // In ordered case, we must increment nextSequenceRecv - nextSequenceRecv++ - - // incrementing nextSequenceRecv and storing under this chain's channelEnd identifiers - // Since this is the receiving chain, our channelEnd is packet's destination port and channel - k.SetNextSequenceRecv(ctx, packet.GetDestPort(), packet.GetDestChannel(), nextSequenceRecv) - - } - - // log that a packet has been received & executed - k.Logger(ctx).Info("packet received", "packet", fmt.Sprintf("%v", packet)) - - // emit an event that the relayer can query for - ctx.EventManager().EmitEvents(sdk.Events{ - sdk.NewEvent( - types.EventTypeRecvPacket, - sdk.NewAttribute(types.AttributeKeyData, string(packet.GetData())), - sdk.NewAttribute(types.AttributeKeyTimeoutHeight, packet.GetTimeoutHeight().String()), - sdk.NewAttribute(types.AttributeKeyTimeoutTimestamp, fmt.Sprintf("%d", packet.GetTimeoutTimestamp())), - sdk.NewAttribute(types.AttributeKeySequence, fmt.Sprintf("%d", packet.GetSequence())), - sdk.NewAttribute(types.AttributeKeySrcPort, packet.GetSourcePort()), - sdk.NewAttribute(types.AttributeKeySrcChannel, packet.GetSourceChannel()), - 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, - sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), - ), - }) - - return nil -} - -// WriteAcknowledgement writes the packet execution acknowledgement to the state, -// which will be verified by the counterparty chain using AcknowledgePacket. -// -// CONTRACT: -// -// 1) For synchronous execution, this function is be called in the IBC handler . -// For async handling, it needs to be called directly by the module which originally -// processed the packet. -// -// 2) Assumes that packet receipt has been written (unordered), or nextSeqRecv was incremented (ordered) -// previously by RecvPacket. -func (k Keeper) WriteAcknowledgement( - ctx sdk.Context, - chanCap *capabilitytypes.Capability, - packet exported.PacketI, - acknowledgement []byte, -) error { - channel, found := k.GetChannel(ctx, packet.GetDestPort(), packet.GetDestChannel()) - if !found { - return sdkerrors.Wrap(types.ErrChannelNotFound, packet.GetDestChannel()) - } - - if channel.State != types.OPEN { - return sdkerrors.Wrapf( - types.ErrInvalidChannelState, - "channel state is not OPEN (got %s)", channel.State.String(), - ) - } - - // Authenticate capability to ensure caller has authority to receive packet on this channel - capName := host.ChannelCapabilityPath(packet.GetDestPort(), packet.GetDestChannel()) - if !k.scopedKeeper.AuthenticateCapability(ctx, chanCap, capName) { - return sdkerrors.Wrapf( - types.ErrInvalidChannelCapability, - "channel capability failed authentication for capability name %s", capName, - ) - } - - // NOTE: IBC app modules might have written the acknowledgement synchronously on - // the OnRecvPacket callback so we need to check if the acknowledgement is already - // set on the store and return an error if so. - if k.HasPacketAcknowledgement(ctx, packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) { - return types.ErrAcknowledgementExists - } - - if len(acknowledgement) == 0 { - return sdkerrors.Wrap(types.ErrInvalidAcknowledgement, "acknowledgement cannot be empty") - } - - // set the acknowledgement so that it can be verified on the other side - k.SetPacketAcknowledgement( - ctx, packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence(), - types.CommitAcknowledgement(acknowledgement), - ) - - // log that a packet acknowledgement has been written - k.Logger(ctx).Info("acknowledged written", "packet", fmt.Sprintf("%v", packet)) - - // emit an event that the relayer can query for - ctx.EventManager().EmitEvents(sdk.Events{ - sdk.NewEvent( - types.EventTypeWriteAck, - sdk.NewAttribute(types.AttributeKeyData, string(packet.GetData())), - sdk.NewAttribute(types.AttributeKeyTimeoutHeight, packet.GetTimeoutHeight().String()), - sdk.NewAttribute(types.AttributeKeyTimeoutTimestamp, fmt.Sprintf("%d", packet.GetTimeoutTimestamp())), - sdk.NewAttribute(types.AttributeKeySequence, fmt.Sprintf("%d", packet.GetSequence())), - sdk.NewAttribute(types.AttributeKeySrcPort, packet.GetSourcePort()), - sdk.NewAttribute(types.AttributeKeySrcChannel, packet.GetSourceChannel()), - 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, - sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), - ), - }) - - return nil -} - -// AcknowledgePacket is called by a module to process the acknowledgement of a -// packet previously sent by the calling module on a channel to a counterparty -// module on the counterparty chain. Its intended usage is within the ante -// handler. AcknowledgePacket will clean up the packet commitment, -// which is no longer necessary since the packet has been received and acted upon. -// It will also increment NextSequenceAck in case of ORDERED channels. -func (k Keeper) AcknowledgePacket( - ctx sdk.Context, - chanCap *capabilitytypes.Capability, - packet exported.PacketI, - acknowledgement []byte, - proof []byte, - proofHeight exported.Height, -) error { - channel, found := k.GetChannel(ctx, packet.GetSourcePort(), packet.GetSourceChannel()) - if !found { - return sdkerrors.Wrapf( - types.ErrChannelNotFound, - "port ID (%s) channel ID (%s)", packet.GetSourcePort(), packet.GetSourceChannel(), - ) - } - - if channel.State != types.OPEN { - return sdkerrors.Wrapf( - types.ErrInvalidChannelState, - "channel state is not OPEN (got %s)", channel.State.String(), - ) - } - - // Authenticate capability to ensure caller has authority to receive packet on this channel - capName := host.ChannelCapabilityPath(packet.GetSourcePort(), packet.GetSourceChannel()) - if !k.scopedKeeper.AuthenticateCapability(ctx, chanCap, capName) { - return sdkerrors.Wrapf( - types.ErrInvalidChannelCapability, - "channel capability failed authentication for capability name %s", capName, - ) - } - - // packet must have been sent to the channel's counterparty - if packet.GetDestPort() != channel.Counterparty.PortId { - return sdkerrors.Wrapf( - types.ErrInvalidPacket, - "packet destination port doesn't match the counterparty's port (%s ≠ %s)", packet.GetDestPort(), channel.Counterparty.PortId, - ) - } - - if packet.GetDestChannel() != channel.Counterparty.ChannelId { - return sdkerrors.Wrapf( - types.ErrInvalidPacket, - "packet destination channel doesn't match the counterparty's channel (%s ≠ %s)", packet.GetDestChannel(), channel.Counterparty.ChannelId, - ) - } - - connectionEnd, found := k.connectionKeeper.GetConnection(ctx, channel.ConnectionHops[0]) - if !found { - return sdkerrors.Wrap(connectiontypes.ErrConnectionNotFound, channel.ConnectionHops[0]) - } - - if connectionEnd.GetState() != int32(connectiontypes.OPEN) { - return sdkerrors.Wrapf( - connectiontypes.ErrInvalidConnectionState, - "connection state is not OPEN (got %s)", connectiontypes.State(connectionEnd.GetState()).String(), - ) - } - - commitment := k.GetPacketCommitment(ctx, packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) - - packetCommitment := types.CommitPacket(k.cdc, packet) - - // verify we sent the packet and haven't cleared it out yet - if !bytes.Equal(commitment, packetCommitment) { - return sdkerrors.Wrapf(types.ErrInvalidPacket, "commitment bytes are not equal: got (%v), expected (%v)", packetCommitment, commitment) - } - - if err := k.connectionKeeper.VerifyPacketAcknowledgement( - ctx, connectionEnd, proofHeight, proof, packet.GetDestPort(), packet.GetDestChannel(), - packet.GetSequence(), acknowledgement, - ); err != nil { - return sdkerrors.Wrap(err, "packet acknowledgement verification failed") - } - - // assert packets acknowledged in order - if channel.Ordering == types.ORDERED { - nextSequenceAck, found := k.GetNextSequenceAck(ctx, packet.GetSourcePort(), packet.GetSourceChannel()) - if !found { - return sdkerrors.Wrapf( - types.ErrSequenceAckNotFound, - "source port: %s, source channel: %s", packet.GetSourcePort(), packet.GetSourceChannel(), - ) - } - - if packet.GetSequence() != nextSequenceAck { - return sdkerrors.Wrapf( - sdkerrors.ErrInvalidSequence, - "packet sequence ≠ next ack sequence (%d ≠ %d)", packet.GetSequence(), nextSequenceAck, - ) - } - - // All verification complete, in the case of ORDERED channels we must increment nextSequenceAck - nextSequenceAck++ - - // incrementing NextSequenceAck and storing under this chain's channelEnd identifiers - // Since this is the original sending chain, our channelEnd is packet's source port and channel - k.SetNextSequenceAck(ctx, packet.GetSourcePort(), packet.GetSourceChannel(), nextSequenceAck) - - } - - // Delete packet commitment, since the packet has been acknowledged, the commitement is no longer necessary - k.deletePacketCommitment(ctx, packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) - - // log that a packet has been acknowledged - k.Logger(ctx).Info("packet acknowledged", "packet", fmt.Sprintf("%v", packet)) - - // emit an event marking that we have processed the acknowledgement - ctx.EventManager().EmitEvents(sdk.Events{ - sdk.NewEvent( - types.EventTypeAcknowledgePacket, - sdk.NewAttribute(types.AttributeKeyTimeoutHeight, packet.GetTimeoutHeight().String()), - sdk.NewAttribute(types.AttributeKeyTimeoutTimestamp, fmt.Sprintf("%d", packet.GetTimeoutTimestamp())), - sdk.NewAttribute(types.AttributeKeySequence, fmt.Sprintf("%d", packet.GetSequence())), - sdk.NewAttribute(types.AttributeKeySrcPort, packet.GetSourcePort()), - sdk.NewAttribute(types.AttributeKeySrcChannel, packet.GetSourceChannel()), - 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, - sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), - ), - }) - - return nil -} diff --git a/x/ibc/core/04-channel/keeper/packet_test.go b/x/ibc/core/04-channel/keeper/packet_test.go deleted file mode 100644 index 232e68758246..000000000000 --- a/x/ibc/core/04-channel/keeper/packet_test.go +++ /dev/null @@ -1,665 +0,0 @@ -package keeper_test - -import ( - "fmt" - - capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" - ibcmock "github.com/cosmos/cosmos-sdk/x/ibc/testing/mock" -) - -var ( - validPacketData = []byte("VALID PACKET DATA") - disabledTimeoutTimestamp = uint64(0) - disabledTimeoutHeight = clienttypes.ZeroHeight() - timeoutHeight = clienttypes.NewHeight(0, 100) - - // for when the testing package cannot be used - clientIDA = "clientA" - clientIDB = "clientB" - connIDA = "connA" - connIDB = "connB" - portID = "portid" - channelIDA = "channelidA" - channelIDB = "channelidB" -) - -// TestSendPacket tests SendPacket from chainA to chainB -func (suite *KeeperTestSuite) TestSendPacket() { - var ( - packet exported.PacketI - channelCap *capabilitytypes.Capability - ) - - testCases := []testCase{ - {"success: UNORDERED channel", func() { - _, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, true}, - {"success: ORDERED channel", func() { - _, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.ORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, true}, - {"sending packet out of order on UNORDERED channel", func() { - // setup creates an unordered channel - _, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - packet = types.NewPacket(validPacketData, 5, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, false}, - {"sending packet out of order on ORDERED channel", func() { - _, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.ORDERED) - packet = types.NewPacket(validPacketData, 5, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, false}, - {"packet basic validation failed, empty packet data", func() { - _, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - packet = types.NewPacket([]byte{}, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, false}, - {"channel not found", func() { - // use wrong channel naming - _, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - packet = types.NewPacket(validPacketData, 1, ibctesting.InvalidID, ibctesting.InvalidID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, false}, - {"channel closed", func() { - _, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - - err := suite.coordinator.SetChannelClosed(suite.chainA, suite.chainB, channelA) - suite.Require().NoError(err) - }, false}, - {"packet dest port ≠ channel counterparty port", func() { - _, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - // use wrong port for dest - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, ibctesting.InvalidID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, false}, - {"packet dest channel ID ≠ channel counterparty channel ID", func() { - _, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - // use wrong channel for dest - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, ibctesting.InvalidID, timeoutHeight, disabledTimeoutTimestamp) - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, false}, - {"connection not found", func() { - channelA := ibctesting.TestChannel{PortID: portID, ID: channelIDA} - channelB := ibctesting.TestChannel{PortID: portID, ID: channelIDB} - // pass channel check - suite.chainA.App.IBCKeeper.ChannelKeeper.SetChannel( - suite.chainA.GetContext(), - channelA.PortID, channelA.ID, - types.NewChannel(types.OPEN, types.ORDERED, types.NewCounterparty(channelB.PortID, channelB.ID), []string{connIDA}, channelA.Version), - ) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - suite.chainA.CreateChannelCapability(channelA.PortID, channelA.ID) - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, false}, - {"client state not found", func() { - _, _, connA, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - - // change connection client ID - connection := suite.chainA.GetConnection(connA) - connection.ClientId = ibctesting.InvalidID - suite.chainA.App.IBCKeeper.ConnectionKeeper.SetConnection(suite.chainA.GetContext(), connA.ID, connection) - - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, false}, - {"client state is frozen", func() { - _, _, connA, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - - connection := suite.chainA.GetConnection(connA) - clientState := suite.chainA.GetClientState(connection.ClientId) - cs, ok := clientState.(*ibctmtypes.ClientState) - suite.Require().True(ok) - - // freeze client - cs.FrozenHeight = clienttypes.NewHeight(0, 1) - suite.chainA.App.IBCKeeper.ClientKeeper.SetClientState(suite.chainA.GetContext(), connection.ClientId, cs) - - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, false}, - - {"timeout height passed", func() { - clientA, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - // use client state latest height for timeout - clientState := suite.chainA.GetClientState(clientA) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, clientState.GetLatestHeight().(clienttypes.Height), disabledTimeoutTimestamp) - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, false}, - {"timeout timestamp passed", func() { - clientA, _, connA, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - // use latest time on client state - clientState := suite.chainA.GetClientState(clientA) - connection := suite.chainA.GetConnection(connA) - timestamp, err := suite.chainA.App.IBCKeeper.ConnectionKeeper.GetTimestampAtHeight(suite.chainA.GetContext(), connection, clientState.GetLatestHeight()) - suite.Require().NoError(err) - - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, disabledTimeoutHeight, timestamp) - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, false}, - {"next sequence send not found", func() { - _, _, connA, connB := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - channelA := suite.chainA.NextTestChannel(connA, ibctesting.TransferPort) - channelB := suite.chainB.NextTestChannel(connB, ibctesting.TransferPort) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - // manually creating channel prevents next sequence from being set - suite.chainA.App.IBCKeeper.ChannelKeeper.SetChannel( - suite.chainA.GetContext(), - channelA.PortID, channelA.ID, - types.NewChannel(types.OPEN, types.ORDERED, types.NewCounterparty(channelB.PortID, channelB.ID), []string{connA.ID}, channelA.Version), - ) - suite.chainA.CreateChannelCapability(channelA.PortID, channelA.ID) - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, false}, - {"next sequence wrong", func() { - _, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - suite.chainA.App.IBCKeeper.ChannelKeeper.SetNextSequenceSend(suite.chainA.GetContext(), channelA.PortID, channelA.ID, 5) - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, false}, - {"channel capability not found", func() { - _, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - channelCap = capabilitytypes.NewCapability(5) - }, false}, - } - - for i, tc := range testCases { - tc := tc - suite.Run(fmt.Sprintf("Case %s, %d/%d tests", tc.msg, i, len(testCases)), func() { - suite.SetupTest() // reset - - tc.malleate() - - err := suite.chainA.App.IBCKeeper.ChannelKeeper.SendPacket(suite.chainA.GetContext(), channelCap, packet) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } - -} - -// TestRecvPacket test RecvPacket on chainB. Since packet commitment verification will always -// occur last (resource instensive), only tests expected to succeed and packet commitment -// verification tests need to simulate sending a packet from chainA to chainB. -func (suite *KeeperTestSuite) TestRecvPacket() { - var ( - packet exported.PacketI - channelCap *capabilitytypes.Capability - ) - - testCases := []testCase{ - {"success: ORDERED channel", func() { - _, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.ORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - channelCap = suite.chainB.GetChannelCapability(channelB.PortID, channelB.ID) - }, true}, - {"success UNORDERED channel", func() { - // setup uses an UNORDERED channel - _, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - channelCap = suite.chainB.GetChannelCapability(channelB.PortID, channelB.ID) - }, true}, - {"success with out of order packet: UNORDERED channel", func() { - // setup uses an UNORDERED channel - _, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - - // send 2 packets - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - // set sequence to 2 - packet = types.NewPacket(validPacketData, 2, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - err = suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - // attempts to receive packet 2 without receiving packet 1 - channelCap = suite.chainB.GetChannelCapability(channelB.PortID, channelB.ID) - }, true}, - {"out of order packet failure with ORDERED channel", func() { - _, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.ORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - - // send 2 packets - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - // set sequence to 2 - packet = types.NewPacket(validPacketData, 2, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - err = suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - // attempts to receive packet 2 without receiving packet 1 - channelCap = suite.chainB.GetChannelCapability(channelB.PortID, channelB.ID) - }, false}, - {"channel not found", func() { - // use wrong channel naming - _, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, ibctesting.InvalidID, ibctesting.InvalidID, timeoutHeight, disabledTimeoutTimestamp) - channelCap = suite.chainB.GetChannelCapability(channelB.PortID, channelB.ID) - }, false}, - {"channel not open", func() { - _, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - - err := suite.coordinator.SetChannelClosed(suite.chainB, suite.chainA, channelB) - suite.Require().NoError(err) - channelCap = suite.chainB.GetChannelCapability(channelB.PortID, channelB.ID) - }, false}, - {"capability cannot authenticate", func() { - _, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.ORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - channelCap = capabilitytypes.NewCapability(3) - }, false}, - {"packet source port ≠ channel counterparty port", func() { - _, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - // use wrong port for dest - packet = types.NewPacket(validPacketData, 1, ibctesting.InvalidID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - channelCap = suite.chainB.GetChannelCapability(channelB.PortID, channelB.ID) - }, false}, - {"packet source channel ID ≠ channel counterparty channel ID", func() { - _, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - // use wrong port for dest - packet = types.NewPacket(validPacketData, 1, channelA.PortID, ibctesting.InvalidID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - channelCap = suite.chainB.GetChannelCapability(channelB.PortID, channelB.ID) - }, false}, - {"connection not found", func() { - channelA := ibctesting.TestChannel{PortID: portID, ID: channelIDA} - channelB := ibctesting.TestChannel{PortID: portID, ID: channelIDB} - // pass channel check - suite.chainB.App.IBCKeeper.ChannelKeeper.SetChannel( - suite.chainB.GetContext(), - channelB.PortID, channelB.ID, - types.NewChannel(types.OPEN, types.ORDERED, types.NewCounterparty(channelA.PortID, channelA.ID), []string{connIDB}, channelB.Version), - ) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - suite.chainB.CreateChannelCapability(channelB.PortID, channelB.ID) - channelCap = suite.chainB.GetChannelCapability(channelB.PortID, channelB.ID) - }, false}, - {"connection not OPEN", func() { - clientA, clientB := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - // connection on chainB is in INIT - connB, connA, err := suite.coordinator.ConnOpenInit(suite.chainB, suite.chainA, clientB, clientA) - suite.Require().NoError(err) - - channelA := suite.chainA.NextTestChannel(connA, ibctesting.TransferPort) - channelB := suite.chainB.NextTestChannel(connB, ibctesting.TransferPort) - // pass channel check - suite.chainB.App.IBCKeeper.ChannelKeeper.SetChannel( - suite.chainB.GetContext(), - channelB.PortID, channelB.ID, - types.NewChannel(types.OPEN, types.ORDERED, types.NewCounterparty(channelA.PortID, channelA.ID), []string{connB.ID}, channelB.Version), - ) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - suite.chainB.CreateChannelCapability(channelB.PortID, channelB.ID) - channelCap = suite.chainB.GetChannelCapability(channelB.PortID, channelB.ID) - }, false}, - {"timeout height passed", func() { - _, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, clienttypes.GetSelfHeight(suite.chainB.GetContext()), disabledTimeoutTimestamp) - channelCap = suite.chainB.GetChannelCapability(channelB.PortID, channelB.ID) - }, false}, - {"timeout timestamp passed", func() { - _, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, disabledTimeoutHeight, uint64(suite.chainB.GetContext().BlockTime().UnixNano())) - channelCap = suite.chainB.GetChannelCapability(channelB.PortID, channelB.ID) - }, false}, - {"next receive sequence is not found", func() { - _, _, connA, connB := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - channelA := suite.chainA.NextTestChannel(connA, ibctesting.TransferPort) - channelB := suite.chainB.NextTestChannel(connB, ibctesting.TransferPort) - - // manually creating channel prevents next recv sequence from being set - suite.chainB.App.IBCKeeper.ChannelKeeper.SetChannel( - suite.chainB.GetContext(), - channelB.PortID, channelB.ID, - types.NewChannel(types.OPEN, types.ORDERED, types.NewCounterparty(channelA.PortID, channelA.ID), []string{connB.ID}, channelB.Version), - ) - - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - - // manually set packet commitment - suite.chainA.App.IBCKeeper.ChannelKeeper.SetPacketCommitment(suite.chainA.GetContext(), channelA.PortID, channelA.ID, packet.GetSequence(), ibctesting.TestHash) - suite.chainB.CreateChannelCapability(channelB.PortID, channelB.ID) - - channelCap = suite.chainB.GetChannelCapability(channelB.PortID, channelB.ID) - }, false}, - {"receipt already stored", func() { - _, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.chainB.App.IBCKeeper.ChannelKeeper.SetPacketReceipt(suite.chainB.GetContext(), channelB.PortID, channelB.ID, 1) - channelCap = suite.chainB.GetChannelCapability(channelB.PortID, channelB.ID) - }, false}, - {"validation failed", func() { - // packet commitment not set resulting in invalid proof - _, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - channelCap = suite.chainB.GetChannelCapability(channelB.PortID, channelB.ID) - }, false}, - } - - for i, tc := range testCases { - tc := tc - suite.Run(fmt.Sprintf("Case %s, %d/%d tests", tc.msg, i, len(testCases)), func() { - suite.SetupTest() // reset - tc.malleate() - - // get proof of packet commitment from chainA - packetKey := host.PacketCommitmentKey(packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) - proof, proofHeight := suite.chainA.QueryProof(packetKey) - - err := suite.chainB.App.IBCKeeper.ChannelKeeper.RecvPacket(suite.chainB.GetContext(), channelCap, packet, proof, proofHeight) - - if tc.expPass { - suite.Require().NoError(err) - - channelB, _ := suite.chainB.App.IBCKeeper.ChannelKeeper.GetChannel(suite.chainB.GetContext(), packet.GetDestPort(), packet.GetDestChannel()) - nextSeqRecv, found := suite.chainB.App.IBCKeeper.ChannelKeeper.GetNextSequenceRecv(suite.chainB.GetContext(), packet.GetDestPort(), packet.GetDestChannel()) - suite.Require().True(found) - receipt, receiptStored := suite.chainB.App.IBCKeeper.ChannelKeeper.GetPacketReceipt(suite.chainB.GetContext(), packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - - if channelB.Ordering == types.ORDERED { - suite.Require().Equal(packet.GetSequence()+1, nextSeqRecv, "sequence not incremented in ordered channel") - suite.Require().False(receiptStored, "packet receipt stored on ORDERED channel") - } else { - suite.Require().Equal(uint64(1), nextSeqRecv, "sequence incremented for UNORDERED channel") - suite.Require().True(receiptStored, "packet receipt not stored after RecvPacket in UNORDERED channel") - suite.Require().Equal(string([]byte{byte(1)}), receipt, "packet receipt is not empty string") - } - } else { - suite.Require().Error(err) - } - }) - } - -} - -func (suite *KeeperTestSuite) TestWriteAcknowledgement() { - var ( - ack []byte - packet exported.PacketI - channelCap *capabilitytypes.Capability - ) - - testCases := []testCase{ - { - "success", - func() { - _, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - ack = ibctesting.TestHash - channelCap = suite.chainB.GetChannelCapability(channelB.PortID, channelB.ID) - }, - true, - }, - {"channel not found", func() { - // use wrong channel naming - _, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, ibctesting.InvalidID, ibctesting.InvalidID, timeoutHeight, disabledTimeoutTimestamp) - ack = ibctesting.TestHash - channelCap = suite.chainB.GetChannelCapability(channelB.PortID, channelB.ID) - }, false}, - {"channel not open", func() { - _, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - ack = ibctesting.TestHash - - err := suite.coordinator.SetChannelClosed(suite.chainB, suite.chainA, channelB) - suite.Require().NoError(err) - channelCap = suite.chainB.GetChannelCapability(channelB.PortID, channelB.ID) - }, false}, - { - "capability authentication failed", - func() { - _, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - ack = ibctesting.TestHash - channelCap = capabilitytypes.NewCapability(3) - }, - false, - }, - { - "no-op, already acked", - func() { - _, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - ack = ibctesting.TestHash - suite.chainB.App.IBCKeeper.ChannelKeeper.SetPacketAcknowledgement(suite.chainB.GetContext(), packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence(), ack) - channelCap = suite.chainB.GetChannelCapability(channelB.PortID, channelB.ID) - }, - false, - }, - { - "empty acknowledgement", - func() { - _, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - ack = nil - channelCap = suite.chainB.GetChannelCapability(channelB.PortID, channelB.ID) - }, - false, - }, - } - for i, tc := range testCases { - tc := tc - suite.Run(fmt.Sprintf("Case %s, %d/%d tests", tc.msg, i, len(testCases)), func() { - suite.SetupTest() // reset - - tc.malleate() - - err := suite.chainB.App.IBCKeeper.ChannelKeeper.WriteAcknowledgement(suite.chainB.GetContext(), channelCap, packet, ack) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} - -// TestAcknowledgePacket tests the call AcknowledgePacket on chainA. -func (suite *KeeperTestSuite) TestAcknowledgePacket() { - var ( - packet types.Packet - ack = ibcmock.MockAcknowledgement - - channelCap *capabilitytypes.Capability - ) - - testCases := []testCase{ - {"success on ordered channel", func() { - clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.ORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - // create packet commitment - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - - // create packet receipt and acknowledgement - err = suite.coordinator.RecvPacket(suite.chainA, suite.chainB, clientA, packet) - suite.Require().NoError(err) - - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, true}, - {"success on unordered channel", func() { - // setup uses an UNORDERED channel - clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - - // create packet commitment - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - - // create packet receipt and acknowledgement - err = suite.coordinator.RecvPacket(suite.chainA, suite.chainB, clientA, packet) - suite.Require().NoError(err) - - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, true}, - {"channel not found", func() { - // use wrong channel naming - _, _, _, _, _, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - packet = types.NewPacket(validPacketData, 1, ibctesting.InvalidID, ibctesting.InvalidID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - }, false}, - {"channel not open", func() { - _, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - - err := suite.coordinator.SetChannelClosed(suite.chainA, suite.chainB, channelA) - suite.Require().NoError(err) - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, false}, - {"capability authentication failed", func() { - clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.ORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - // create packet commitment - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - - // create packet receipt and acknowledgement - err = suite.coordinator.RecvPacket(suite.chainA, suite.chainB, clientA, packet) - suite.Require().NoError(err) - - channelCap = capabilitytypes.NewCapability(3) - }, false}, - {"packet destination port ≠ channel counterparty port", func() { - _, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - // use wrong port for dest - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, ibctesting.InvalidID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, false}, - {"packet destination channel ID ≠ channel counterparty channel ID", func() { - _, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - // use wrong channel for dest - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, ibctesting.InvalidID, timeoutHeight, disabledTimeoutTimestamp) - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, false}, - {"connection not found", func() { - channelA := ibctesting.TestChannel{PortID: portID, ID: channelIDA} - channelB := ibctesting.TestChannel{PortID: portID, ID: channelIDB} - // pass channel check - suite.chainB.App.IBCKeeper.ChannelKeeper.SetChannel( - suite.chainB.GetContext(), - channelB.PortID, channelB.ID, - types.NewChannel(types.OPEN, types.ORDERED, types.NewCounterparty(channelA.PortID, channelA.ID), []string{connIDB}, channelB.Version), - ) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - suite.chainA.CreateChannelCapability(channelA.PortID, channelA.ID) - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, false}, - {"connection not OPEN", func() { - clientA, clientB := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - // connection on chainA is in INIT - connA, connB, err := suite.coordinator.ConnOpenInit(suite.chainA, suite.chainB, clientA, clientB) - suite.Require().NoError(err) - - channelA := suite.chainA.NextTestChannel(connA, ibctesting.TransferPort) - channelB := suite.chainB.NextTestChannel(connB, ibctesting.TransferPort) - // pass channel check - suite.chainA.App.IBCKeeper.ChannelKeeper.SetChannel( - suite.chainA.GetContext(), - channelA.PortID, channelA.ID, - types.NewChannel(types.OPEN, types.ORDERED, types.NewCounterparty(channelB.PortID, channelB.ID), []string{connA.ID}, channelA.Version), - ) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - suite.chainA.CreateChannelCapability(channelA.PortID, channelA.ID) - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, false}, - {"packet hasn't been sent", func() { - // packet commitment never written - _, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, false}, - {"packet ack verification failed", func() { - // ack never written - _, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - - // create packet commitment - suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, false}, - {"next ack sequence not found", func() { - _, _, connA, connB := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, exported.Tendermint) - channelA := suite.chainA.NextTestChannel(connA, ibctesting.TransferPort) - channelB := suite.chainB.NextTestChannel(connB, ibctesting.TransferPort) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - // manually creating channel prevents next sequence acknowledgement from being set - suite.chainA.App.IBCKeeper.ChannelKeeper.SetChannel( - suite.chainA.GetContext(), - channelA.PortID, channelA.ID, - types.NewChannel(types.OPEN, types.ORDERED, types.NewCounterparty(channelB.PortID, channelB.ID), []string{connA.ID}, channelA.Version), - ) - // manually set packet commitment - suite.chainA.App.IBCKeeper.ChannelKeeper.SetPacketCommitment(suite.chainA.GetContext(), channelA.PortID, channelA.ID, packet.GetSequence(), ibctesting.TestHash) - - // manually set packet acknowledgement and capability - suite.chainB.App.IBCKeeper.ChannelKeeper.SetPacketAcknowledgement(suite.chainB.GetContext(), channelB.PortID, channelB.ID, packet.GetSequence(), ibctesting.TestHash) - suite.chainA.CreateChannelCapability(channelA.PortID, channelA.ID) - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, false}, - {"next ack sequence mismatch", func() { - clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.ORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - // create packet commitment - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - - // create packet acknowledgement - err = suite.coordinator.RecvPacket(suite.chainA, suite.chainB, clientA, packet) - suite.Require().NoError(err) - - // set next sequence ack wrong - suite.chainA.App.IBCKeeper.ChannelKeeper.SetNextSequenceAck(suite.chainA.GetContext(), channelA.PortID, channelA.ID, 10) - channelCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, false}, - } - - for i, tc := range testCases { - tc := tc - suite.Run(fmt.Sprintf("Case %s, %d/%d tests", tc.msg, i, len(testCases)), func() { - suite.SetupTest() // reset - tc.malleate() - - packetKey := host.PacketAcknowledgementKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - proof, proofHeight := suite.chainB.QueryProof(packetKey) - - err := suite.chainA.App.IBCKeeper.ChannelKeeper.AcknowledgePacket(suite.chainA.GetContext(), channelCap, packet, ack, proof, proofHeight) - pc := suite.chainA.App.IBCKeeper.ChannelKeeper.GetPacketCommitment(suite.chainA.GetContext(), packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) - - channelA, _ := suite.chainA.App.IBCKeeper.ChannelKeeper.GetChannel(suite.chainA.GetContext(), packet.GetSourcePort(), packet.GetSourceChannel()) - sequenceAck, _ := suite.chainA.App.IBCKeeper.ChannelKeeper.GetNextSequenceAck(suite.chainA.GetContext(), packet.GetSourcePort(), packet.GetSourceChannel()) - - if tc.expPass { - suite.NoError(err) - suite.Nil(pc) - - if channelA.Ordering == types.ORDERED { - suite.Require().Equal(packet.GetSequence()+1, sequenceAck, "sequence not incremented in ordered channel") - } else { - suite.Require().Equal(uint64(1), sequenceAck, "sequence incremented for UNORDERED channel") - } - } else { - suite.Error(err) - } - }) - } -} diff --git a/x/ibc/core/04-channel/keeper/timeout.go b/x/ibc/core/04-channel/keeper/timeout.go deleted file mode 100644 index 1f3dac918f67..000000000000 --- a/x/ibc/core/04-channel/keeper/timeout.go +++ /dev/null @@ -1,276 +0,0 @@ -package keeper - -import ( - "bytes" - "fmt" - - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" - connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -// TimeoutPacket is called by a module which originally attempted to send a -// packet to a counterparty module, where the timeout height has passed on the -// counterparty chain without the packet being committed, to prove that the -// packet can no longer be executed and to allow the calling module to safely -// perform appropriate state transitions. Its intended usage is within the -// ante handler. -func (k Keeper) TimeoutPacket( - ctx sdk.Context, - packet exported.PacketI, - proof []byte, - proofHeight exported.Height, - nextSequenceRecv uint64, -) error { - channel, found := k.GetChannel(ctx, packet.GetSourcePort(), packet.GetSourceChannel()) - if !found { - return sdkerrors.Wrapf( - types.ErrChannelNotFound, - "port ID (%s) channel ID (%s)", packet.GetSourcePort(), packet.GetSourceChannel(), - ) - } - - if channel.State != types.OPEN { - return sdkerrors.Wrapf( - types.ErrInvalidChannelState, - "channel state is not OPEN (got %s)", channel.State.String(), - ) - } - - // NOTE: TimeoutPacket is called by the AnteHandler which acts upon the packet.Route(), - // so the capability authentication can be omitted here - - if packet.GetDestPort() != channel.Counterparty.PortId { - return sdkerrors.Wrapf( - types.ErrInvalidPacket, - "packet destination port doesn't match the counterparty's port (%s ≠ %s)", packet.GetDestPort(), channel.Counterparty.PortId, - ) - } - - if packet.GetDestChannel() != channel.Counterparty.ChannelId { - return sdkerrors.Wrapf( - types.ErrInvalidPacket, - "packet destination channel doesn't match the counterparty's channel (%s ≠ %s)", packet.GetDestChannel(), channel.Counterparty.ChannelId, - ) - } - - connectionEnd, found := k.connectionKeeper.GetConnection(ctx, channel.ConnectionHops[0]) - if !found { - return sdkerrors.Wrap( - connectiontypes.ErrConnectionNotFound, - channel.ConnectionHops[0], - ) - } - - // check that timeout height or timeout timestamp has passed on the other end - proofTimestamp, err := k.connectionKeeper.GetTimestampAtHeight(ctx, connectionEnd, proofHeight) - if err != nil { - return err - } - - timeoutHeight := packet.GetTimeoutHeight() - if (timeoutHeight.IsZero() || proofHeight.LT(timeoutHeight)) && - (packet.GetTimeoutTimestamp() == 0 || proofTimestamp < packet.GetTimeoutTimestamp()) { - return sdkerrors.Wrap(types.ErrPacketTimeout, "packet timeout has not been reached for height or timestamp") - } - - commitment := k.GetPacketCommitment(ctx, packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) - - packetCommitment := types.CommitPacket(k.cdc, packet) - - // verify we sent the packet and haven't cleared it out yet - if !bytes.Equal(commitment, packetCommitment) { - return sdkerrors.Wrapf(types.ErrInvalidPacket, "packet commitment bytes are not equal: got (%v), expected (%v)", commitment, packetCommitment) - } - - switch channel.Ordering { - case types.ORDERED: - // check that packet has not been received - if nextSequenceRecv > packet.GetSequence() { - return sdkerrors.Wrapf( - types.ErrInvalidPacket, - "packet already received, next sequence receive > packet sequence (%d > %d)", nextSequenceRecv, packet.GetSequence(), - ) - } - - // check that the recv sequence is as claimed - err = k.connectionKeeper.VerifyNextSequenceRecv( - ctx, connectionEnd, proofHeight, proof, - packet.GetDestPort(), packet.GetDestChannel(), nextSequenceRecv, - ) - case types.UNORDERED: - err = k.connectionKeeper.VerifyPacketReceiptAbsence( - ctx, connectionEnd, proofHeight, proof, - packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence(), - ) - default: - panic(sdkerrors.Wrapf(types.ErrInvalidChannelOrdering, channel.Ordering.String())) - } - - if err != nil { - return err - } - - // NOTE: the remaining code is located in the TimeoutExecuted function - return nil -} - -// TimeoutExecuted deletes the commitment send from this chain after it verifies timeout. -// If the timed-out packet came from an ORDERED channel then this channel will be closed. -// -// CONTRACT: this function must be called in the IBC handler -func (k Keeper) TimeoutExecuted( - ctx sdk.Context, - chanCap *capabilitytypes.Capability, - packet exported.PacketI, -) error { - channel, found := k.GetChannel(ctx, packet.GetSourcePort(), packet.GetSourceChannel()) - if !found { - return sdkerrors.Wrapf(types.ErrChannelNotFound, "port ID (%s) channel ID (%s)", packet.GetSourcePort(), packet.GetSourceChannel()) - } - - capName := host.ChannelCapabilityPath(packet.GetSourcePort(), packet.GetSourceChannel()) - if !k.scopedKeeper.AuthenticateCapability(ctx, chanCap, capName) { - return sdkerrors.Wrapf( - types.ErrChannelCapabilityNotFound, - "caller does not own capability for channel with capability name %s", capName, - ) - } - - k.deletePacketCommitment(ctx, packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) - - if channel.Ordering == types.ORDERED { - channel.State = types.CLOSED - k.SetChannel(ctx, packet.GetSourcePort(), packet.GetSourceChannel(), channel) - } - - k.Logger(ctx).Info("packet timed-out", "packet", fmt.Sprintf("%v", packet)) - - // emit an event marking that we have processed the timeout - ctx.EventManager().EmitEvents(sdk.Events{ - sdk.NewEvent( - types.EventTypeTimeoutPacket, - sdk.NewAttribute(types.AttributeKeyTimeoutHeight, packet.GetTimeoutHeight().String()), - sdk.NewAttribute(types.AttributeKeyTimeoutTimestamp, fmt.Sprintf("%d", packet.GetTimeoutTimestamp())), - sdk.NewAttribute(types.AttributeKeySequence, fmt.Sprintf("%d", packet.GetSequence())), - sdk.NewAttribute(types.AttributeKeySrcPort, packet.GetSourcePort()), - sdk.NewAttribute(types.AttributeKeySrcChannel, packet.GetSourceChannel()), - sdk.NewAttribute(types.AttributeKeyDstPort, packet.GetDestPort()), - sdk.NewAttribute(types.AttributeKeyDstChannel, packet.GetDestChannel()), - sdk.NewAttribute(types.AttributeKeyChannelOrdering, channel.Ordering.String()), - ), - sdk.NewEvent( - sdk.EventTypeMessage, - sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), - ), - }) - - return nil -} - -// TimeoutOnClose is called by a module in order to prove that the channel to -// which an unreceived packet was addressed has been closed, so the packet will -// never be received (even if the timeoutHeight has not yet been reached). -func (k Keeper) TimeoutOnClose( - ctx sdk.Context, - chanCap *capabilitytypes.Capability, - packet exported.PacketI, - proof, - proofClosed []byte, - proofHeight exported.Height, - nextSequenceRecv uint64, -) error { - channel, found := k.GetChannel(ctx, packet.GetSourcePort(), packet.GetSourceChannel()) - if !found { - return sdkerrors.Wrapf(types.ErrChannelNotFound, "port ID (%s) channel ID (%s)", packet.GetSourcePort(), packet.GetSourceChannel()) - } - - capName := host.ChannelCapabilityPath(packet.GetSourcePort(), packet.GetSourceChannel()) - if !k.scopedKeeper.AuthenticateCapability(ctx, chanCap, capName) { - return sdkerrors.Wrapf( - types.ErrInvalidChannelCapability, - "channel capability failed authentication with capability name %s", capName, - ) - } - - if packet.GetDestPort() != channel.Counterparty.PortId { - return sdkerrors.Wrapf( - types.ErrInvalidPacket, - "packet destination port doesn't match the counterparty's port (%s ≠ %s)", packet.GetDestPort(), channel.Counterparty.PortId, - ) - } - - if packet.GetDestChannel() != channel.Counterparty.ChannelId { - return sdkerrors.Wrapf( - types.ErrInvalidPacket, - "packet destination channel doesn't match the counterparty's channel (%s ≠ %s)", packet.GetDestChannel(), channel.Counterparty.ChannelId, - ) - } - - connectionEnd, found := k.connectionKeeper.GetConnection(ctx, channel.ConnectionHops[0]) - if !found { - return sdkerrors.Wrap(connectiontypes.ErrConnectionNotFound, channel.ConnectionHops[0]) - } - - commitment := k.GetPacketCommitment(ctx, packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) - - packetCommitment := types.CommitPacket(k.cdc, packet) - - // verify we sent the packet and haven't cleared it out yet - if !bytes.Equal(commitment, packetCommitment) { - return sdkerrors.Wrapf(types.ErrInvalidPacket, "packet commitment bytes are not equal: got (%v), expected (%v)", commitment, packetCommitment) - } - - counterpartyHops, found := k.CounterpartyHops(ctx, channel) - if !found { - // Should not reach here, connectionEnd was able to be retrieved above - panic("cannot find connection") - } - - counterparty := types.NewCounterparty(packet.GetSourcePort(), packet.GetSourceChannel()) - expectedChannel := types.NewChannel( - types.CLOSED, channel.Ordering, counterparty, counterpartyHops, channel.Version, - ) - - // check that the opposing channel end has closed - if err := k.connectionKeeper.VerifyChannelState( - ctx, connectionEnd, proofHeight, proofClosed, - channel.Counterparty.PortId, channel.Counterparty.ChannelId, - expectedChannel, - ); err != nil { - return err - } - - var err error - switch channel.Ordering { - case types.ORDERED: - // check that packet has not been received - if nextSequenceRecv > packet.GetSequence() { - return sdkerrors.Wrapf(types.ErrInvalidPacket, "packet already received, next sequence receive > packet sequence (%d > %d", nextSequenceRecv, packet.GetSequence()) - } - - // check that the recv sequence is as claimed - err = k.connectionKeeper.VerifyNextSequenceRecv( - ctx, connectionEnd, proofHeight, proof, - packet.GetDestPort(), packet.GetDestChannel(), nextSequenceRecv, - ) - case types.UNORDERED: - err = k.connectionKeeper.VerifyPacketReceiptAbsence( - ctx, connectionEnd, proofHeight, proof, - packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence(), - ) - default: - panic(sdkerrors.Wrapf(types.ErrInvalidChannelOrdering, channel.Ordering.String())) - } - - if err != nil { - return err - } - - // NOTE: the remaining code is located in the TimeoutExecuted function - return nil -} diff --git a/x/ibc/core/04-channel/keeper/timeout_test.go b/x/ibc/core/04-channel/keeper/timeout_test.go deleted file mode 100644 index 640452e881be..000000000000 --- a/x/ibc/core/04-channel/keeper/timeout_test.go +++ /dev/null @@ -1,351 +0,0 @@ -package keeper_test - -import ( - "fmt" - - capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" -) - -// TestTimeoutPacket test the TimeoutPacket call on chainA by ensuring the timeout has passed -// on chainB, but that no ack has been written yet. Test cases expected to reach proof -// verification must specify which proof to use using the ordered bool. -func (suite *KeeperTestSuite) TestTimeoutPacket() { - var ( - packet types.Packet - nextSeqRecv uint64 - ordered bool - ) - - testCases := []testCase{ - {"success: ORDERED", func() { - ordered = true - - clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.ORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, clienttypes.GetSelfHeight(suite.chainB.GetContext()), uint64(suite.chainB.GetContext().BlockTime().UnixNano())) - suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - // need to update chainA's client representing chainB to prove missing ack - suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - }, true}, - {"success: UNORDERED", func() { - ordered = false - - clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, clienttypes.GetSelfHeight(suite.chainB.GetContext()), disabledTimeoutTimestamp) - suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - // need to update chainA's client representing chainB to prove missing ack - suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - }, true}, - {"channel not found", func() { - // use wrong channel naming - _, _, _, _, _, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - packet = types.NewPacket(validPacketData, 1, ibctesting.InvalidID, ibctesting.InvalidID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - }, false}, - {"channel not open", func() { - _, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - - err := suite.coordinator.SetChannelClosed(suite.chainA, suite.chainB, channelA) - suite.Require().NoError(err) - }, false}, - {"packet destination port ≠ channel counterparty port", func() { - _, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - // use wrong port for dest - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, ibctesting.InvalidID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - }, false}, - {"packet destination channel ID ≠ channel counterparty channel ID", func() { - _, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - // use wrong channel for dest - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, ibctesting.InvalidID, timeoutHeight, disabledTimeoutTimestamp) - }, false}, - {"connection not found", func() { - channelA := ibctesting.TestChannel{PortID: portID, ID: channelIDA} - channelB := ibctesting.TestChannel{PortID: portID, ID: channelIDB} - // pass channel check - suite.chainA.App.IBCKeeper.ChannelKeeper.SetChannel( - suite.chainA.GetContext(), - channelA.PortID, channelA.ID, - types.NewChannel(types.OPEN, types.ORDERED, types.NewCounterparty(channelB.PortID, channelB.ID), []string{connIDA}, channelA.Version), - ) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - }, false}, - {"timeout", func() { - clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.ORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - }, false}, - {"packet already received ", func() { - ordered = true - nextSeqRecv = 2 - - clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.ORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, uint64(suite.chainB.GetContext().BlockTime().UnixNano())) - suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - }, false}, - {"packet hasn't been sent", func() { - clientA, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.ORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, uint64(suite.chainB.GetContext().BlockTime().UnixNano())) - suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - }, false}, - {"next seq receive verification failed", func() { - // set ordered to false resulting in wrong proof provided - ordered = false - - clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.ORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, clienttypes.GetSelfHeight(suite.chainB.GetContext()), disabledTimeoutTimestamp) - suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - }, false}, - {"packet ack verification failed", func() { - // set ordered to true resulting in wrong proof provided - ordered = true - - clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, clienttypes.GetSelfHeight(suite.chainB.GetContext()), disabledTimeoutTimestamp) - suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - }, false}, - } - - for i, tc := range testCases { - tc := tc - suite.Run(fmt.Sprintf("Case %s, %d/%d tests", tc.msg, i, len(testCases)), func() { - var ( - proof []byte - proofHeight exported.Height - ) - - suite.SetupTest() // reset - nextSeqRecv = 1 // must be explicitly changed - tc.malleate() - - orderedPacketKey := host.NextSequenceRecvKey(packet.GetDestPort(), packet.GetDestChannel()) - unorderedPacketKey := host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - - if ordered { - proof, proofHeight = suite.chainB.QueryProof(orderedPacketKey) - } else { - proof, proofHeight = suite.chainB.QueryProof(unorderedPacketKey) - } - - err := suite.chainA.App.IBCKeeper.ChannelKeeper.TimeoutPacket(suite.chainA.GetContext(), packet, proof, proofHeight, nextSeqRecv) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} - -// TestTimeoutExectued verifies that packet commitments are deleted on chainA after the -// channel capabilities are verified. -func (suite *KeeperTestSuite) TestTimeoutExecuted() { - var ( - packet types.Packet - chanCap *capabilitytypes.Capability - ) - - testCases := []testCase{ - {"success ORDERED", func() { - _, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.ORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, clienttypes.GetSelfHeight(suite.chainB.GetContext()), uint64(suite.chainB.GetContext().BlockTime().UnixNano())) - suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - - chanCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, true}, - {"channel not found", func() { - // use wrong channel naming - _, _, _, _, _, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - packet = types.NewPacket(validPacketData, 1, ibctesting.InvalidID, ibctesting.InvalidID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - }, false}, - {"incorrect capability", func() { - _, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.ORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, clienttypes.GetSelfHeight(suite.chainB.GetContext()), uint64(suite.chainB.GetContext().BlockTime().UnixNano())) - suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - - chanCap = capabilitytypes.NewCapability(100) - }, false}, - } - - for i, tc := range testCases { - tc := tc - suite.Run(fmt.Sprintf("Case %s, %d/%d tests", tc.msg, i, len(testCases)), func() { - suite.SetupTest() // reset - - tc.malleate() - - err := suite.chainA.App.IBCKeeper.ChannelKeeper.TimeoutExecuted(suite.chainA.GetContext(), chanCap, packet) - pc := suite.chainA.App.IBCKeeper.ChannelKeeper.GetPacketCommitment(suite.chainA.GetContext(), packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) - - if tc.expPass { - suite.NoError(err) - suite.Nil(pc) - } else { - suite.Error(err) - } - }) - } -} - -// TestTimeoutOnClose tests the call TimeoutOnClose on chainA by closing the corresponding -// channel on chainB after the packet commitment has been created. -func (suite *KeeperTestSuite) TestTimeoutOnClose() { - var ( - packet types.Packet - chanCap *capabilitytypes.Capability - nextSeqRecv uint64 - ordered bool - ) - - testCases := []testCase{ - {"success: ORDERED", func() { - ordered = true - clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.ORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, clienttypes.GetSelfHeight(suite.chainB.GetContext()), uint64(suite.chainB.GetContext().BlockTime().UnixNano())) - suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.coordinator.SetChannelClosed(suite.chainB, suite.chainA, channelB) - // need to update chainA's client representing chainB to prove missing ack - suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - - chanCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, true}, - {"success: UNORDERED", func() { - ordered = false - clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, clienttypes.GetSelfHeight(suite.chainB.GetContext()), disabledTimeoutTimestamp) - suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.coordinator.SetChannelClosed(suite.chainB, suite.chainA, channelB) - // need to update chainA's client representing chainB to prove missing ack - suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - - chanCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, true}, - {"channel not found", func() { - // use wrong channel naming - _, _, _, _, _, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - packet = types.NewPacket(validPacketData, 1, ibctesting.InvalidID, ibctesting.InvalidID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - }, false}, - {"packet dest port ≠ channel counterparty port", func() { - _, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - // use wrong port for dest - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, ibctesting.InvalidID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - chanCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, false}, - {"packet dest channel ID ≠ channel counterparty channel ID", func() { - _, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - // use wrong channel for dest - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, ibctesting.InvalidID, timeoutHeight, disabledTimeoutTimestamp) - chanCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, false}, - {"connection not found", func() { - channelA := ibctesting.TestChannel{PortID: portID, ID: channelIDA} - channelB := ibctesting.TestChannel{PortID: portID, ID: channelIDB} - // pass channel check - suite.chainA.App.IBCKeeper.ChannelKeeper.SetChannel( - suite.chainA.GetContext(), - channelA.PortID, channelA.ID, - types.NewChannel(types.OPEN, types.ORDERED, types.NewCounterparty(channelB.PortID, channelB.ID), []string{connIDA}, channelA.Version), - ) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, disabledTimeoutTimestamp) - - // create chancap - suite.chainA.CreateChannelCapability(channelA.PortID, channelA.ID) - chanCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, false}, - {"packet hasn't been sent", func() { - _, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.ORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, clienttypes.GetSelfHeight(suite.chainB.GetContext()), uint64(suite.chainB.GetContext().BlockTime().UnixNano())) - chanCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, false}, - {"packet already received", func() { - nextSeqRecv = 2 - ordered = true - clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.ORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, clienttypes.GetSelfHeight(suite.chainB.GetContext()), uint64(suite.chainB.GetContext().BlockTime().UnixNano())) - suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.coordinator.SetChannelClosed(suite.chainB, suite.chainA, channelB) - // need to update chainA's client representing chainB to prove missing ack - suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - - chanCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, false}, - {"channel verification failed", func() { - ordered = true - _, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.ORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, clienttypes.GetSelfHeight(suite.chainB.GetContext()), uint64(suite.chainB.GetContext().BlockTime().UnixNano())) - suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - chanCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, false}, - {"next seq receive verification failed", func() { - // set ordered to false providing the wrong proof for ORDERED case - ordered = false - clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.ORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, clienttypes.GetSelfHeight(suite.chainB.GetContext()), uint64(suite.chainB.GetContext().BlockTime().UnixNano())) - suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.coordinator.SetChannelClosed(suite.chainB, suite.chainA, channelB) - suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - chanCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, false}, - {"packet ack verification failed", func() { - // set ordered to true providing the wrong proof for UNORDERED case - ordered = true - clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.UNORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, clienttypes.GetSelfHeight(suite.chainB.GetContext()), disabledTimeoutTimestamp) - suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.coordinator.SetChannelClosed(suite.chainB, suite.chainA, channelB) - suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - chanCap = suite.chainA.GetChannelCapability(channelA.PortID, channelA.ID) - }, false}, - {"channel capability not found", func() { - ordered = true - clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, types.ORDERED) - packet = types.NewPacket(validPacketData, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, clienttypes.GetSelfHeight(suite.chainB.GetContext()), uint64(suite.chainB.GetContext().BlockTime().UnixNano())) - suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.coordinator.SetChannelClosed(suite.chainB, suite.chainA, channelB) - // need to update chainA's client representing chainB to prove missing ack - suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - - chanCap = capabilitytypes.NewCapability(100) - }, false}, - } - - for i, tc := range testCases { - tc := tc - suite.Run(fmt.Sprintf("Case %s, %d/%d tests", tc.msg, i, len(testCases)), func() { - var proof []byte - - suite.SetupTest() // reset - nextSeqRecv = 1 // must be explicitly changed - tc.malleate() - - channelKey := host.ChannelKey(packet.GetDestPort(), packet.GetDestChannel()) - unorderedPacketKey := host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - orderedPacketKey := host.NextSequenceRecvKey(packet.GetDestPort(), packet.GetDestChannel()) - - proofClosed, proofHeight := suite.chainB.QueryProof(channelKey) - - if ordered { - proof, _ = suite.chainB.QueryProof(orderedPacketKey) - } else { - proof, _ = suite.chainB.QueryProof(unorderedPacketKey) - } - - err := suite.chainA.App.IBCKeeper.ChannelKeeper.TimeoutOnClose(suite.chainA.GetContext(), chanCap, packet, proof, proofClosed, proofHeight, nextSeqRecv) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } - -} diff --git a/x/ibc/core/04-channel/module.go b/x/ibc/core/04-channel/module.go deleted file mode 100644 index 569120ad921d..000000000000 --- a/x/ibc/core/04-channel/module.go +++ /dev/null @@ -1,29 +0,0 @@ -package channel - -import ( - "github.com/gogo/protobuf/grpc" - "github.com/spf13/cobra" - - "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/client/cli" - "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" -) - -// Name returns the IBC channel ICS name. -func Name() string { - return types.SubModuleName -} - -// GetTxCmd returns the root tx command for IBC channels. -func GetTxCmd() *cobra.Command { - return cli.NewTxCmd() -} - -// GetQueryCmd returns the root query command for IBC channels. -func GetQueryCmd() *cobra.Command { - return cli.GetQueryCmd() -} - -// RegisterQueryService registers the gRPC query service for IBC channels. -func RegisterQueryService(server grpc.Server, queryServer types.QueryServer) { - types.RegisterQueryServer(server, queryServer) -} diff --git a/x/ibc/core/04-channel/simulation/decoder.go b/x/ibc/core/04-channel/simulation/decoder.go deleted file mode 100644 index 809976cc0e23..000000000000 --- a/x/ibc/core/04-channel/simulation/decoder.go +++ /dev/null @@ -1,48 +0,0 @@ -package simulation - -import ( - "bytes" - "fmt" - - "github.com/cosmos/cosmos-sdk/codec" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/kv" - "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" -) - -// NewDecodeStore returns a decoder function closure that unmarshals the KVPair's -// Value to the corresponding channel type. -func NewDecodeStore(cdc codec.BinaryMarshaler, kvA, kvB kv.Pair) (string, bool) { - switch { - case bytes.HasPrefix(kvA.Key, []byte(host.KeyChannelEndPrefix)): - var channelA, channelB types.Channel - cdc.MustUnmarshalBinaryBare(kvA.Value, &channelA) - cdc.MustUnmarshalBinaryBare(kvB.Value, &channelB) - return fmt.Sprintf("Channel A: %v\nChannel B: %v", channelA, channelB), true - - case bytes.HasPrefix(kvA.Key, []byte(host.KeyNextSeqSendPrefix)): - seqA := sdk.BigEndianToUint64(kvA.Value) - seqB := sdk.BigEndianToUint64(kvB.Value) - return fmt.Sprintf("NextSeqSend A: %d\nNextSeqSend B: %d", seqA, seqB), true - - case bytes.HasPrefix(kvA.Key, []byte(host.KeyNextSeqRecvPrefix)): - seqA := sdk.BigEndianToUint64(kvA.Value) - seqB := sdk.BigEndianToUint64(kvB.Value) - return fmt.Sprintf("NextSeqRecv A: %d\nNextSeqRecv B: %d", seqA, seqB), true - - case bytes.HasPrefix(kvA.Key, []byte(host.KeyNextSeqAckPrefix)): - seqA := sdk.BigEndianToUint64(kvA.Value) - seqB := sdk.BigEndianToUint64(kvB.Value) - return fmt.Sprintf("NextSeqAck A: %d\nNextSeqAck B: %d", seqA, seqB), true - - case bytes.HasPrefix(kvA.Key, []byte(host.KeyPacketCommitmentPrefix)): - return fmt.Sprintf("CommitmentHash A: %X\nCommitmentHash B: %X", kvA.Value, kvB.Value), true - - case bytes.HasPrefix(kvA.Key, []byte(host.KeyPacketAckPrefix)): - return fmt.Sprintf("AckHash A: %X\nAckHash B: %X", kvA.Value, kvB.Value), true - - default: - return "", false - } -} diff --git a/x/ibc/core/04-channel/simulation/decoder_test.go b/x/ibc/core/04-channel/simulation/decoder_test.go deleted file mode 100644 index 5f2ba2f5ecbf..000000000000 --- a/x/ibc/core/04-channel/simulation/decoder_test.go +++ /dev/null @@ -1,89 +0,0 @@ -package simulation_test - -import ( - "fmt" - "testing" - - "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/ibc/core/04-channel/simulation" - "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" -) - -func TestDecodeStore(t *testing.T) { - app := simapp.Setup(false) - cdc := app.AppCodec() - - channelID := "channelidone" - portID := "portidone" - - channel := types.Channel{ - State: types.OPEN, - Version: "1.0", - } - - bz := []byte{0x1, 0x2, 0x3} - - kvPairs := kv.Pairs{ - Pairs: []kv.Pair{ - { - Key: host.ChannelKey(portID, channelID), - Value: cdc.MustMarshalBinaryBare(&channel), - }, - { - Key: host.NextSequenceSendKey(portID, channelID), - Value: sdk.Uint64ToBigEndian(1), - }, - { - Key: host.NextSequenceRecvKey(portID, channelID), - Value: sdk.Uint64ToBigEndian(1), - }, - { - Key: host.NextSequenceAckKey(portID, channelID), - Value: sdk.Uint64ToBigEndian(1), - }, - { - Key: host.PacketCommitmentKey(portID, channelID, 1), - Value: bz, - }, - { - Key: host.PacketAcknowledgementKey(portID, channelID, 1), - Value: bz, - }, - { - Key: []byte{0x99}, - Value: []byte{0x99}, - }, - }, - } - tests := []struct { - name string - expectedLog string - }{ - {"Channel", fmt.Sprintf("Channel A: %v\nChannel B: %v", channel, channel)}, - {"NextSeqSend", "NextSeqSend A: 1\nNextSeqSend B: 1"}, - {"NextSeqRecv", "NextSeqRecv A: 1\nNextSeqRecv B: 1"}, - {"NextSeqAck", "NextSeqAck A: 1\nNextSeqAck B: 1"}, - {"CommitmentHash", fmt.Sprintf("CommitmentHash A: %X\nCommitmentHash B: %X", bz, bz)}, - {"AckHash", fmt.Sprintf("AckHash A: %X\nAckHash B: %X", bz, bz)}, - {"other", ""}, - } - - for i, tt := range tests { - i, tt := i, tt - t.Run(tt.name, func(t *testing.T) { - res, found := simulation.NewDecodeStore(cdc, kvPairs.Pairs[i], kvPairs.Pairs[i]) - if i == len(tests)-1 { - require.False(t, found, string(kvPairs.Pairs[i].Key)) - require.Empty(t, res, string(kvPairs.Pairs[i].Key)) - } else { - require.True(t, found, string(kvPairs.Pairs[i].Key)) - require.Equal(t, tt.expectedLog, res, string(kvPairs.Pairs[i].Key)) - } - }) - } -} diff --git a/x/ibc/core/04-channel/simulation/genesis.go b/x/ibc/core/04-channel/simulation/genesis.go deleted file mode 100644 index ed33902191b9..000000000000 --- a/x/ibc/core/04-channel/simulation/genesis.go +++ /dev/null @@ -1,13 +0,0 @@ -package simulation - -import ( - "math/rand" - - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" -) - -// GenChannelGenesis returns the default channel genesis state. -func GenChannelGenesis(_ *rand.Rand, _ []simtypes.Account) types.GenesisState { - return types.DefaultGenesisState() -} diff --git a/x/ibc/core/04-channel/types/acknowledgement.go b/x/ibc/core/04-channel/types/acknowledgement.go deleted file mode 100644 index a3f677ab4410..000000000000 --- a/x/ibc/core/04-channel/types/acknowledgement.go +++ /dev/null @@ -1,50 +0,0 @@ -package types - -import ( - "strings" - - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" -) - -// NewResultAcknowledgement returns a new instance of Acknowledgement using an Acknowledgement_Result -// type in the Response field. -func NewResultAcknowledgement(result []byte) Acknowledgement { - return Acknowledgement{ - Response: &Acknowledgement_Result{ - Result: result, - }, - } -} - -// NewErrorAcknowledgement returns a new instance of Acknowledgement using an Acknowledgement_Error -// type in the Response field. -func NewErrorAcknowledgement(err string) Acknowledgement { - return Acknowledgement{ - Response: &Acknowledgement_Error{ - Error: err, - }, - } -} - -// GetBytes is a helper for serialising acknowledgements -func (ack Acknowledgement) GetBytes() []byte { - return sdk.MustSortJSON(SubModuleCdc.MustMarshalJSON(&ack)) -} - -// ValidateBasic performs a basic validation of the acknowledgement -func (ack Acknowledgement) ValidateBasic() error { - switch resp := ack.Response.(type) { - case *Acknowledgement_Result: - if len(resp.Result) == 0 { - return sdkerrors.Wrap(ErrInvalidAcknowledgement, "acknowledgement result cannot be empty") - } - case *Acknowledgement_Error: - if strings.TrimSpace(resp.Error) == "" { - return sdkerrors.Wrap(ErrInvalidAcknowledgement, "acknowledgement error cannot be empty") - } - default: - return sdkerrors.Wrapf(ErrInvalidAcknowledgement, "unsupported acknowledgement response field type %T", resp) - } - return nil -} diff --git a/x/ibc/core/04-channel/types/acknowledgement_test.go b/x/ibc/core/04-channel/types/acknowledgement_test.go deleted file mode 100644 index 58074dd7bde5..000000000000 --- a/x/ibc/core/04-channel/types/acknowledgement_test.go +++ /dev/null @@ -1,63 +0,0 @@ -package types_test - -import "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - -// tests acknowledgement.ValidateBasic and acknowledgement.GetBytes -func (suite TypesTestSuite) TestAcknowledgement() { - testCases := []struct { - name string - ack types.Acknowledgement - expPass bool - }{ - { - "valid successful ack", - types.NewResultAcknowledgement([]byte("success")), - true, - }, - { - "valid failed ack", - types.NewErrorAcknowledgement("error"), - true, - }, - { - "empty successful ack", - types.NewResultAcknowledgement([]byte{}), - false, - }, - { - "empty faied ack", - types.NewErrorAcknowledgement(" "), - false, - }, - { - "nil response", - types.Acknowledgement{ - Response: nil, - }, - false, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - suite.SetupTest() - - err := tc.ack.ValidateBasic() - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - - // expect all acks to be able to be marshaled - suite.NotPanics(func() { - bz := tc.ack.GetBytes() - suite.Require().NotNil(bz) - }) - }) - } - -} diff --git a/x/ibc/core/04-channel/types/channel.go b/x/ibc/core/04-channel/types/channel.go deleted file mode 100644 index b808a220b303..000000000000 --- a/x/ibc/core/04-channel/types/channel.go +++ /dev/null @@ -1,127 +0,0 @@ -package types - -import ( - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -var ( - _ exported.ChannelI = (*Channel)(nil) - _ exported.CounterpartyChannelI = (*Counterparty)(nil) -) - -// NewChannel creates a new Channel instance -func NewChannel( - state State, ordering Order, counterparty Counterparty, - hops []string, version string, -) Channel { - return Channel{ - State: state, - Ordering: ordering, - Counterparty: counterparty, - ConnectionHops: hops, - Version: version, - } -} - -// GetState implements Channel interface. -func (ch Channel) GetState() int32 { - return int32(ch.State) -} - -// GetOrdering implements Channel interface. -func (ch Channel) GetOrdering() int32 { - return int32(ch.Ordering) -} - -// GetCounterparty implements Channel interface. -func (ch Channel) GetCounterparty() exported.CounterpartyChannelI { - return ch.Counterparty -} - -// GetConnectionHops implements Channel interface. -func (ch Channel) GetConnectionHops() []string { - return ch.ConnectionHops -} - -// GetVersion implements Channel interface. -func (ch Channel) GetVersion() string { - return ch.Version -} - -// ValidateBasic performs a basic validation of the channel fields -func (ch Channel) ValidateBasic() error { - if ch.State == UNINITIALIZED { - return ErrInvalidChannelState - } - if !(ch.Ordering == ORDERED || ch.Ordering == UNORDERED) { - return sdkerrors.Wrap(ErrInvalidChannelOrdering, ch.Ordering.String()) - } - if len(ch.ConnectionHops) != 1 { - return sdkerrors.Wrap( - ErrTooManyConnectionHops, - "current IBC version only supports one connection hop", - ) - } - if err := host.ConnectionIdentifierValidator(ch.ConnectionHops[0]); err != nil { - return sdkerrors.Wrap(err, "invalid connection hop ID") - } - return ch.Counterparty.ValidateBasic() -} - -// NewCounterparty returns a new Counterparty instance -func NewCounterparty(portID, channelID string) Counterparty { - return Counterparty{ - PortId: portID, - ChannelId: channelID, - } -} - -// GetPortID implements CounterpartyChannelI interface -func (c Counterparty) GetPortID() string { - return c.PortId -} - -// GetChannelID implements CounterpartyChannelI interface -func (c Counterparty) GetChannelID() string { - return c.ChannelId -} - -// ValidateBasic performs a basic validation check of the identifiers -func (c Counterparty) ValidateBasic() error { - if err := host.PortIdentifierValidator(c.PortId); err != nil { - return sdkerrors.Wrap(err, "invalid counterparty port ID") - } - if c.ChannelId != "" { - if err := host.ChannelIdentifierValidator(c.ChannelId); err != nil { - return sdkerrors.Wrap(err, "invalid counterparty channel ID") - } - } - return nil -} - -// NewIdentifiedChannel creates a new IdentifiedChannel instance -func NewIdentifiedChannel(portID, channelID string, ch Channel) IdentifiedChannel { - return IdentifiedChannel{ - State: ch.State, - Ordering: ch.Ordering, - Counterparty: ch.Counterparty, - ConnectionHops: ch.ConnectionHops, - Version: ch.Version, - PortId: portID, - ChannelId: channelID, - } -} - -// ValidateBasic performs a basic validation of the identifiers and channel fields. -func (ic IdentifiedChannel) ValidateBasic() error { - if err := host.ChannelIdentifierValidator(ic.ChannelId); err != nil { - return sdkerrors.Wrap(err, "invalid channel ID") - } - if err := host.PortIdentifierValidator(ic.PortId); err != nil { - return sdkerrors.Wrap(err, "invalid port ID") - } - channel := NewChannel(ic.State, ic.Ordering, ic.Counterparty, ic.ConnectionHops, ic.Version) - return channel.ValidateBasic() -} diff --git a/x/ibc/core/04-channel/types/channel.pb.go b/x/ibc/core/04-channel/types/channel.pb.go deleted file mode 100644 index 1384a150d578..000000000000 --- a/x/ibc/core/04-channel/types/channel.pb.go +++ /dev/null @@ -1,2268 +0,0 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: ibc/core/channel/v1/channel.proto - -package types - -import ( - fmt "fmt" - types "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - _ "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 - -// State defines if a channel is in one of the following states: -// CLOSED, INIT, TRYOPEN, OPEN or UNINITIALIZED. -type State int32 - -const ( - // Default State - UNINITIALIZED State = 0 - // A channel has just started the opening handshake. - INIT State = 1 - // A channel has acknowledged the handshake step on the counterparty chain. - TRYOPEN State = 2 - // A channel has completed the handshake. Open channels are - // ready to send and receive packets. - OPEN State = 3 - // A channel has been closed and can no longer be used to send or receive - // packets. - CLOSED State = 4 -) - -var State_name = map[int32]string{ - 0: "STATE_UNINITIALIZED_UNSPECIFIED", - 1: "STATE_INIT", - 2: "STATE_TRYOPEN", - 3: "STATE_OPEN", - 4: "STATE_CLOSED", -} - -var State_value = map[string]int32{ - "STATE_UNINITIALIZED_UNSPECIFIED": 0, - "STATE_INIT": 1, - "STATE_TRYOPEN": 2, - "STATE_OPEN": 3, - "STATE_CLOSED": 4, -} - -func (x State) String() string { - return proto.EnumName(State_name, int32(x)) -} - -func (State) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_c3a07336710636a0, []int{0} -} - -// Order defines if a channel is ORDERED or UNORDERED -type Order int32 - -const ( - // zero-value for channel ordering - NONE Order = 0 - // packets can be delivered in any order, which may differ from the order in - // which they were sent. - UNORDERED Order = 1 - // packets are delivered exactly in the order which they were sent - ORDERED Order = 2 -) - -var Order_name = map[int32]string{ - 0: "ORDER_NONE_UNSPECIFIED", - 1: "ORDER_UNORDERED", - 2: "ORDER_ORDERED", -} - -var Order_value = map[string]int32{ - "ORDER_NONE_UNSPECIFIED": 0, - "ORDER_UNORDERED": 1, - "ORDER_ORDERED": 2, -} - -func (x Order) String() string { - return proto.EnumName(Order_name, int32(x)) -} - -func (Order) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_c3a07336710636a0, []int{1} -} - -// 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. -type Channel struct { - // current state of the channel end - State State `protobuf:"varint,1,opt,name=state,proto3,enum=ibc.core.channel.v1.State" json:"state,omitempty"` - // whether the channel is ordered or unordered - Ordering Order `protobuf:"varint,2,opt,name=ordering,proto3,enum=ibc.core.channel.v1.Order" json:"ordering,omitempty"` - // counterparty channel end - Counterparty Counterparty `protobuf:"bytes,3,opt,name=counterparty,proto3" json:"counterparty"` - // list of connection identifiers, in order, along which packets sent on - // this channel will travel - ConnectionHops []string `protobuf:"bytes,4,rep,name=connection_hops,json=connectionHops,proto3" json:"connection_hops,omitempty" yaml:"connection_hops"` - // opaque channel version, which is agreed upon during the handshake - Version string `protobuf:"bytes,5,opt,name=version,proto3" json:"version,omitempty"` -} - -func (m *Channel) Reset() { *m = Channel{} } -func (m *Channel) String() string { return proto.CompactTextString(m) } -func (*Channel) ProtoMessage() {} -func (*Channel) Descriptor() ([]byte, []int) { - return fileDescriptor_c3a07336710636a0, []int{0} -} -func (m *Channel) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *Channel) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_Channel.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 *Channel) XXX_Merge(src proto.Message) { - xxx_messageInfo_Channel.Merge(m, src) -} -func (m *Channel) XXX_Size() int { - return m.Size() -} -func (m *Channel) XXX_DiscardUnknown() { - xxx_messageInfo_Channel.DiscardUnknown(m) -} - -var xxx_messageInfo_Channel proto.InternalMessageInfo - -// IdentifiedChannel defines a channel with additional port and channel -// identifier fields. -type IdentifiedChannel struct { - // current state of the channel end - State State `protobuf:"varint,1,opt,name=state,proto3,enum=ibc.core.channel.v1.State" json:"state,omitempty"` - // whether the channel is ordered or unordered - Ordering Order `protobuf:"varint,2,opt,name=ordering,proto3,enum=ibc.core.channel.v1.Order" json:"ordering,omitempty"` - // counterparty channel end - Counterparty Counterparty `protobuf:"bytes,3,opt,name=counterparty,proto3" json:"counterparty"` - // list of connection identifiers, in order, along which packets sent on - // this channel will travel - ConnectionHops []string `protobuf:"bytes,4,rep,name=connection_hops,json=connectionHops,proto3" json:"connection_hops,omitempty" yaml:"connection_hops"` - // opaque channel version, which is agreed upon during the handshake - Version string `protobuf:"bytes,5,opt,name=version,proto3" json:"version,omitempty"` - // port identifier - PortId string `protobuf:"bytes,6,opt,name=port_id,json=portId,proto3" json:"port_id,omitempty"` - // channel identifier - ChannelId string `protobuf:"bytes,7,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty"` -} - -func (m *IdentifiedChannel) Reset() { *m = IdentifiedChannel{} } -func (m *IdentifiedChannel) String() string { return proto.CompactTextString(m) } -func (*IdentifiedChannel) ProtoMessage() {} -func (*IdentifiedChannel) Descriptor() ([]byte, []int) { - return fileDescriptor_c3a07336710636a0, []int{1} -} -func (m *IdentifiedChannel) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *IdentifiedChannel) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_IdentifiedChannel.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 *IdentifiedChannel) XXX_Merge(src proto.Message) { - xxx_messageInfo_IdentifiedChannel.Merge(m, src) -} -func (m *IdentifiedChannel) XXX_Size() int { - return m.Size() -} -func (m *IdentifiedChannel) XXX_DiscardUnknown() { - xxx_messageInfo_IdentifiedChannel.DiscardUnknown(m) -} - -var xxx_messageInfo_IdentifiedChannel proto.InternalMessageInfo - -// Counterparty defines a channel end counterparty -type Counterparty struct { - // port on the counterparty chain which owns the other end of the channel. - PortId string `protobuf:"bytes,1,opt,name=port_id,json=portId,proto3" json:"port_id,omitempty" yaml:"port_id"` - // channel end on the counterparty chain - ChannelId string `protobuf:"bytes,2,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty" yaml:"channel_id"` -} - -func (m *Counterparty) Reset() { *m = Counterparty{} } -func (m *Counterparty) String() string { return proto.CompactTextString(m) } -func (*Counterparty) ProtoMessage() {} -func (*Counterparty) Descriptor() ([]byte, []int) { - return fileDescriptor_c3a07336710636a0, []int{2} -} -func (m *Counterparty) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *Counterparty) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_Counterparty.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 *Counterparty) XXX_Merge(src proto.Message) { - xxx_messageInfo_Counterparty.Merge(m, src) -} -func (m *Counterparty) XXX_Size() int { - return m.Size() -} -func (m *Counterparty) XXX_DiscardUnknown() { - xxx_messageInfo_Counterparty.DiscardUnknown(m) -} - -var xxx_messageInfo_Counterparty proto.InternalMessageInfo - -// Packet defines a type that carries data across different chains through IBC -type Packet struct { - // 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. - Sequence uint64 `protobuf:"varint,1,opt,name=sequence,proto3" json:"sequence,omitempty"` - // identifies the port on the sending chain. - SourcePort string `protobuf:"bytes,2,opt,name=source_port,json=sourcePort,proto3" json:"source_port,omitempty" yaml:"source_port"` - // identifies the channel end on the sending chain. - SourceChannel string `protobuf:"bytes,3,opt,name=source_channel,json=sourceChannel,proto3" json:"source_channel,omitempty" yaml:"source_channel"` - // identifies the port on the receiving chain. - DestinationPort string `protobuf:"bytes,4,opt,name=destination_port,json=destinationPort,proto3" json:"destination_port,omitempty" yaml:"destination_port"` - // identifies the channel end on the receiving chain. - DestinationChannel string `protobuf:"bytes,5,opt,name=destination_channel,json=destinationChannel,proto3" json:"destination_channel,omitempty" yaml:"destination_channel"` - // actual opaque bytes transferred directly to the application module - Data []byte `protobuf:"bytes,6,opt,name=data,proto3" json:"data,omitempty"` - // block height after which the packet times out - TimeoutHeight types.Height `protobuf:"bytes,7,opt,name=timeout_height,json=timeoutHeight,proto3" json:"timeout_height" yaml:"timeout_height"` - // block timestamp (in nanoseconds) after which the packet times out - TimeoutTimestamp uint64 `protobuf:"varint,8,opt,name=timeout_timestamp,json=timeoutTimestamp,proto3" json:"timeout_timestamp,omitempty" yaml:"timeout_timestamp"` -} - -func (m *Packet) Reset() { *m = Packet{} } -func (m *Packet) String() string { return proto.CompactTextString(m) } -func (*Packet) ProtoMessage() {} -func (*Packet) Descriptor() ([]byte, []int) { - return fileDescriptor_c3a07336710636a0, []int{3} -} -func (m *Packet) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *Packet) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_Packet.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 *Packet) XXX_Merge(src proto.Message) { - xxx_messageInfo_Packet.Merge(m, src) -} -func (m *Packet) XXX_Size() int { - return m.Size() -} -func (m *Packet) XXX_DiscardUnknown() { - xxx_messageInfo_Packet.DiscardUnknown(m) -} - -var xxx_messageInfo_Packet proto.InternalMessageInfo - -// 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. -type PacketState struct { - // channel port identifier. - PortId string `protobuf:"bytes,1,opt,name=port_id,json=portId,proto3" json:"port_id,omitempty" yaml:"port_id"` - // channel unique identifier. - ChannelId string `protobuf:"bytes,2,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty" yaml:"channel_id"` - // packet sequence. - Sequence uint64 `protobuf:"varint,3,opt,name=sequence,proto3" json:"sequence,omitempty"` - // embedded data that represents packet state. - Data []byte `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"` -} - -func (m *PacketState) Reset() { *m = PacketState{} } -func (m *PacketState) String() string { return proto.CompactTextString(m) } -func (*PacketState) ProtoMessage() {} -func (*PacketState) Descriptor() ([]byte, []int) { - return fileDescriptor_c3a07336710636a0, []int{4} -} -func (m *PacketState) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *PacketState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_PacketState.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 *PacketState) XXX_Merge(src proto.Message) { - xxx_messageInfo_PacketState.Merge(m, src) -} -func (m *PacketState) XXX_Size() int { - return m.Size() -} -func (m *PacketState) XXX_DiscardUnknown() { - xxx_messageInfo_PacketState.DiscardUnknown(m) -} - -var xxx_messageInfo_PacketState proto.InternalMessageInfo - -// 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 -type Acknowledgement struct { - // response contains either a result or an error and must be non-empty - // - // Types that are valid to be assigned to Response: - // *Acknowledgement_Result - // *Acknowledgement_Error - Response isAcknowledgement_Response `protobuf_oneof:"response"` -} - -func (m *Acknowledgement) Reset() { *m = Acknowledgement{} } -func (m *Acknowledgement) String() string { return proto.CompactTextString(m) } -func (*Acknowledgement) ProtoMessage() {} -func (*Acknowledgement) Descriptor() ([]byte, []int) { - return fileDescriptor_c3a07336710636a0, []int{5} -} -func (m *Acknowledgement) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *Acknowledgement) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_Acknowledgement.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 *Acknowledgement) XXX_Merge(src proto.Message) { - xxx_messageInfo_Acknowledgement.Merge(m, src) -} -func (m *Acknowledgement) XXX_Size() int { - return m.Size() -} -func (m *Acknowledgement) XXX_DiscardUnknown() { - xxx_messageInfo_Acknowledgement.DiscardUnknown(m) -} - -var xxx_messageInfo_Acknowledgement proto.InternalMessageInfo - -type isAcknowledgement_Response interface { - isAcknowledgement_Response() - MarshalTo([]byte) (int, error) - Size() int -} - -type Acknowledgement_Result struct { - Result []byte `protobuf:"bytes,21,opt,name=result,proto3,oneof" json:"result,omitempty"` -} -type Acknowledgement_Error struct { - Error string `protobuf:"bytes,22,opt,name=error,proto3,oneof" json:"error,omitempty"` -} - -func (*Acknowledgement_Result) isAcknowledgement_Response() {} -func (*Acknowledgement_Error) isAcknowledgement_Response() {} - -func (m *Acknowledgement) GetResponse() isAcknowledgement_Response { - if m != nil { - return m.Response - } - return nil -} - -func (m *Acknowledgement) GetResult() []byte { - if x, ok := m.GetResponse().(*Acknowledgement_Result); ok { - return x.Result - } - return nil -} - -func (m *Acknowledgement) GetError() string { - if x, ok := m.GetResponse().(*Acknowledgement_Error); ok { - return x.Error - } - return "" -} - -// XXX_OneofWrappers is for the internal use of the proto package. -func (*Acknowledgement) XXX_OneofWrappers() []interface{} { - return []interface{}{ - (*Acknowledgement_Result)(nil), - (*Acknowledgement_Error)(nil), - } -} - -func init() { - proto.RegisterEnum("ibc.core.channel.v1.State", State_name, State_value) - proto.RegisterEnum("ibc.core.channel.v1.Order", Order_name, Order_value) - proto.RegisterType((*Channel)(nil), "ibc.core.channel.v1.Channel") - proto.RegisterType((*IdentifiedChannel)(nil), "ibc.core.channel.v1.IdentifiedChannel") - proto.RegisterType((*Counterparty)(nil), "ibc.core.channel.v1.Counterparty") - proto.RegisterType((*Packet)(nil), "ibc.core.channel.v1.Packet") - proto.RegisterType((*PacketState)(nil), "ibc.core.channel.v1.PacketState") - proto.RegisterType((*Acknowledgement)(nil), "ibc.core.channel.v1.Acknowledgement") -} - -func init() { proto.RegisterFile("ibc/core/channel/v1/channel.proto", fileDescriptor_c3a07336710636a0) } - -var fileDescriptor_c3a07336710636a0 = []byte{ - // 904 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x55, 0xcb, 0x6e, 0xdb, 0x46, - 0x14, 0x15, 0x25, 0xea, 0x75, 0x65, 0xc9, 0xf2, 0xa4, 0x56, 0x58, 0x36, 0x11, 0x15, 0xa2, 0x0b, - 0x23, 0x45, 0xa4, 0x38, 0x0d, 0xda, 0x22, 0xab, 0x5a, 0x8f, 0xc0, 0x44, 0x03, 0xc9, 0xa0, 0xe4, - 0x45, 0xb3, 0x51, 0x65, 0x72, 0x2a, 0x11, 0x96, 0x38, 0x2a, 0x39, 0xb2, 0xeb, 0x3f, 0x08, 0xb4, - 0xea, 0x0f, 0x08, 0x28, 0x50, 0xb4, 0xbf, 0xd0, 0x5f, 0xc8, 0x32, 0xcb, 0xae, 0x88, 0xc2, 0x5e, - 0x74, 0xaf, 0x1f, 0x68, 0xc1, 0x99, 0xa1, 0x1e, 0x4e, 0xe0, 0x65, 0x57, 0x59, 0x71, 0xee, 0x39, - 0xe7, 0x3e, 0x74, 0xef, 0xd5, 0x0c, 0x3c, 0x72, 0xce, 0xac, 0x9a, 0x45, 0x3c, 0x5c, 0xb3, 0x46, - 0x03, 0xd7, 0xc5, 0xe3, 0xda, 0xc5, 0x61, 0x74, 0xac, 0x4e, 0x3d, 0x42, 0x09, 0xba, 0xe7, 0x9c, - 0x59, 0xd5, 0x50, 0x52, 0x8d, 0xf0, 0x8b, 0x43, 0xf5, 0x93, 0x21, 0x19, 0x12, 0xc6, 0xd7, 0xc2, - 0x13, 0x97, 0xaa, 0xda, 0x3a, 0xda, 0xd8, 0xc1, 0x2e, 0x65, 0xc1, 0xd8, 0x89, 0x0b, 0xf4, 0xdf, - 0xe3, 0x90, 0x6e, 0xf0, 0x28, 0xe8, 0x29, 0x24, 0x7d, 0x3a, 0xa0, 0x58, 0x91, 0x2a, 0xd2, 0x41, - 0xe1, 0x99, 0x5a, 0xfd, 0x40, 0x9e, 0x6a, 0x37, 0x54, 0x98, 0x5c, 0x88, 0xbe, 0x82, 0x0c, 0xf1, - 0x6c, 0xec, 0x39, 0xee, 0x50, 0x89, 0xdf, 0xe1, 0xd4, 0x09, 0x45, 0xe6, 0x4a, 0x8b, 0xbe, 0x83, - 0x1d, 0x8b, 0xcc, 0x5c, 0x8a, 0xbd, 0xe9, 0xc0, 0xa3, 0x57, 0x4a, 0xa2, 0x22, 0x1d, 0xe4, 0x9e, - 0x3d, 0xfa, 0xa0, 0x6f, 0x63, 0x43, 0x58, 0x97, 0xdf, 0x06, 0x5a, 0xcc, 0xdc, 0x72, 0x46, 0x0d, - 0xd8, 0xb5, 0x88, 0xeb, 0x62, 0x8b, 0x3a, 0xc4, 0xed, 0x8f, 0xc8, 0xd4, 0x57, 0xe4, 0x4a, 0xe2, - 0x20, 0x5b, 0x57, 0x97, 0x81, 0x56, 0xba, 0x1a, 0x4c, 0xc6, 0x2f, 0xf4, 0x5b, 0x02, 0xdd, 0x2c, - 0xac, 0x91, 0x63, 0x32, 0xf5, 0x91, 0x02, 0xe9, 0x0b, 0xec, 0xf9, 0x0e, 0x71, 0x95, 0x64, 0x45, - 0x3a, 0xc8, 0x9a, 0x91, 0xf9, 0x42, 0x7e, 0xf3, 0xab, 0x16, 0xd3, 0xff, 0x89, 0xc3, 0x9e, 0x61, - 0x63, 0x97, 0x3a, 0x3f, 0x3a, 0xd8, 0xfe, 0xd8, 0xb1, 0x3b, 0x3a, 0x86, 0xee, 0x43, 0x7a, 0x4a, - 0x3c, 0xda, 0x77, 0x6c, 0x25, 0xc5, 0x98, 0x54, 0x68, 0x1a, 0x36, 0x7a, 0x08, 0x20, 0xca, 0x0c, - 0xb9, 0x34, 0xe3, 0xb2, 0x02, 0x31, 0x6c, 0xd1, 0xe9, 0x4b, 0xd8, 0xd9, 0xfc, 0x01, 0xe8, 0x8b, - 0x75, 0xb4, 0xb0, 0xcb, 0xd9, 0x3a, 0x5a, 0x06, 0x5a, 0x81, 0x17, 0x29, 0x08, 0x7d, 0x95, 0xe1, - 0xf9, 0x56, 0x86, 0x38, 0xd3, 0xef, 0x2f, 0x03, 0x6d, 0x4f, 0xfc, 0xa8, 0x15, 0xa7, 0xbf, 0x9f, - 0xf8, 0xdf, 0x04, 0xa4, 0x4e, 0x06, 0xd6, 0x39, 0xa6, 0x48, 0x85, 0x8c, 0x8f, 0x7f, 0x9a, 0x61, - 0xd7, 0xe2, 0xa3, 0x95, 0xcd, 0x95, 0x8d, 0xbe, 0x86, 0x9c, 0x4f, 0x66, 0x9e, 0x85, 0xfb, 0x61, - 0x4e, 0x91, 0xa3, 0xb4, 0x0c, 0x34, 0xc4, 0x73, 0x6c, 0x90, 0xba, 0x09, 0xdc, 0x3a, 0x21, 0x1e, - 0x45, 0xdf, 0x42, 0x41, 0x70, 0x22, 0x33, 0x1b, 0x62, 0xb6, 0xfe, 0xe9, 0x32, 0xd0, 0xf6, 0xb7, - 0x7c, 0x05, 0xaf, 0x9b, 0x79, 0x0e, 0x44, 0xeb, 0xf6, 0x12, 0x8a, 0x36, 0xf6, 0xa9, 0xe3, 0x0e, - 0xd8, 0x5c, 0x58, 0x7e, 0x99, 0xc5, 0xf8, 0x6c, 0x19, 0x68, 0xf7, 0x79, 0x8c, 0xdb, 0x0a, 0xdd, - 0xdc, 0xdd, 0x80, 0x58, 0x25, 0x1d, 0xb8, 0xb7, 0xa9, 0x8a, 0xca, 0x61, 0x63, 0xac, 0x97, 0x97, - 0x81, 0xa6, 0xbe, 0x1f, 0x6a, 0x55, 0x13, 0xda, 0x40, 0xa3, 0xc2, 0x10, 0xc8, 0xf6, 0x80, 0x0e, - 0xd8, 0xb8, 0x77, 0x4c, 0x76, 0x46, 0x3f, 0x40, 0x81, 0x3a, 0x13, 0x4c, 0x66, 0xb4, 0x3f, 0xc2, - 0xce, 0x70, 0x44, 0xd9, 0xc0, 0x73, 0x5b, 0xfb, 0xce, 0x6f, 0xa2, 0x8b, 0xc3, 0xea, 0x31, 0x53, - 0xd4, 0x1f, 0x86, 0xcb, 0xba, 0x6e, 0xc7, 0xb6, 0xbf, 0x6e, 0xe6, 0x05, 0xc0, 0xd5, 0xc8, 0x80, - 0xbd, 0x48, 0x11, 0x7e, 0x7d, 0x3a, 0x98, 0x4c, 0x95, 0x4c, 0x38, 0xae, 0xfa, 0x83, 0x65, 0xa0, - 0x29, 0xdb, 0x41, 0x56, 0x12, 0xdd, 0x2c, 0x0a, 0xac, 0x17, 0x41, 0x62, 0x03, 0xfe, 0x90, 0x20, - 0xc7, 0x37, 0x80, 0xfd, 0x67, 0xff, 0x87, 0xd5, 0xdb, 0xda, 0xb4, 0xc4, 0xad, 0x4d, 0x8b, 0xba, - 0x2a, 0xaf, 0xbb, 0x2a, 0x0a, 0xed, 0xc0, 0xee, 0x91, 0x75, 0xee, 0x92, 0xcb, 0x31, 0xb6, 0x87, - 0x78, 0x82, 0x5d, 0x8a, 0x14, 0x48, 0x79, 0xd8, 0x9f, 0x8d, 0xa9, 0xb2, 0x1f, 0xca, 0x8f, 0x63, - 0xa6, 0xb0, 0x51, 0x09, 0x92, 0xd8, 0xf3, 0x88, 0xa7, 0x94, 0xc2, 0x9a, 0x8e, 0x63, 0x26, 0x37, - 0xeb, 0x00, 0x19, 0x0f, 0xfb, 0x53, 0xe2, 0xfa, 0xf8, 0xf1, 0x9f, 0x12, 0x24, 0xbb, 0xe2, 0x82, - 0xd2, 0xba, 0xbd, 0xa3, 0x5e, 0xab, 0x7f, 0xda, 0x36, 0xda, 0x46, 0xcf, 0x38, 0x7a, 0x65, 0xbc, - 0x6e, 0x35, 0xfb, 0xa7, 0xed, 0xee, 0x49, 0xab, 0x61, 0xbc, 0x34, 0x5a, 0xcd, 0x62, 0x4c, 0xdd, - 0x9b, 0x2f, 0x2a, 0xf9, 0x2d, 0x01, 0x52, 0x00, 0xb8, 0x5f, 0x08, 0x16, 0x25, 0x35, 0x33, 0x5f, - 0x54, 0xe4, 0xf0, 0x8c, 0xca, 0x90, 0xe7, 0x4c, 0xcf, 0xfc, 0xbe, 0x73, 0xd2, 0x6a, 0x17, 0xe3, - 0x6a, 0x6e, 0xbe, 0xa8, 0xa4, 0x85, 0xb9, 0xf6, 0x64, 0x64, 0x82, 0x7b, 0x32, 0xe6, 0x01, 0xec, - 0x70, 0xa6, 0xf1, 0xaa, 0xd3, 0x6d, 0x35, 0x8b, 0xb2, 0x0a, 0xf3, 0x45, 0x25, 0xc5, 0x2d, 0x55, - 0x7e, 0xf3, 0x5b, 0x39, 0xf6, 0xf8, 0x12, 0x92, 0xec, 0xae, 0x44, 0x9f, 0x43, 0xa9, 0x63, 0x36, - 0x5b, 0x66, 0xbf, 0xdd, 0x69, 0xb7, 0x6e, 0xd5, 0xcb, 0x42, 0x86, 0x38, 0xd2, 0x61, 0x97, 0xab, - 0x4e, 0xdb, 0xec, 0xdb, 0x6a, 0x16, 0x25, 0x35, 0x3f, 0x5f, 0x54, 0xb2, 0x2b, 0x20, 0x2c, 0x98, - 0x6b, 0x22, 0x85, 0x28, 0x58, 0x98, 0x3c, 0x71, 0xdd, 0x7c, 0x7b, 0x5d, 0x96, 0xde, 0x5d, 0x97, - 0xa5, 0xbf, 0xaf, 0xcb, 0xd2, 0x2f, 0x37, 0xe5, 0xd8, 0xbb, 0x9b, 0x72, 0xec, 0xaf, 0x9b, 0x72, - 0xec, 0xf5, 0x37, 0x43, 0x87, 0x8e, 0x66, 0x67, 0x55, 0x8b, 0x4c, 0x6a, 0x16, 0xf1, 0x27, 0xc4, - 0x17, 0x9f, 0x27, 0xbe, 0x7d, 0x5e, 0xfb, 0xb9, 0xb6, 0x7a, 0x93, 0x9f, 0x3e, 0x7f, 0x12, 0x3d, - 0xf2, 0xf4, 0x6a, 0x8a, 0xfd, 0xb3, 0x14, 0x7b, 0x94, 0xbf, 0xfc, 0x2f, 0x00, 0x00, 0xff, 0xff, - 0xd7, 0x33, 0x69, 0x35, 0x05, 0x08, 0x00, 0x00, -} - -func (m *Channel) 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 *Channel) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *Channel) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Version) > 0 { - i -= len(m.Version) - copy(dAtA[i:], m.Version) - i = encodeVarintChannel(dAtA, i, uint64(len(m.Version))) - i-- - dAtA[i] = 0x2a - } - if len(m.ConnectionHops) > 0 { - for iNdEx := len(m.ConnectionHops) - 1; iNdEx >= 0; iNdEx-- { - i -= len(m.ConnectionHops[iNdEx]) - copy(dAtA[i:], m.ConnectionHops[iNdEx]) - i = encodeVarintChannel(dAtA, i, uint64(len(m.ConnectionHops[iNdEx]))) - i-- - dAtA[i] = 0x22 - } - } - { - size, err := m.Counterparty.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintChannel(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - if m.Ordering != 0 { - i = encodeVarintChannel(dAtA, i, uint64(m.Ordering)) - i-- - dAtA[i] = 0x10 - } - if m.State != 0 { - i = encodeVarintChannel(dAtA, i, uint64(m.State)) - i-- - dAtA[i] = 0x8 - } - return len(dAtA) - i, nil -} - -func (m *IdentifiedChannel) 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 *IdentifiedChannel) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *IdentifiedChannel) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.ChannelId) > 0 { - i -= len(m.ChannelId) - copy(dAtA[i:], m.ChannelId) - i = encodeVarintChannel(dAtA, i, uint64(len(m.ChannelId))) - i-- - dAtA[i] = 0x3a - } - if len(m.PortId) > 0 { - i -= len(m.PortId) - copy(dAtA[i:], m.PortId) - i = encodeVarintChannel(dAtA, i, uint64(len(m.PortId))) - i-- - dAtA[i] = 0x32 - } - if len(m.Version) > 0 { - i -= len(m.Version) - copy(dAtA[i:], m.Version) - i = encodeVarintChannel(dAtA, i, uint64(len(m.Version))) - i-- - dAtA[i] = 0x2a - } - if len(m.ConnectionHops) > 0 { - for iNdEx := len(m.ConnectionHops) - 1; iNdEx >= 0; iNdEx-- { - i -= len(m.ConnectionHops[iNdEx]) - copy(dAtA[i:], m.ConnectionHops[iNdEx]) - i = encodeVarintChannel(dAtA, i, uint64(len(m.ConnectionHops[iNdEx]))) - i-- - dAtA[i] = 0x22 - } - } - { - size, err := m.Counterparty.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintChannel(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - if m.Ordering != 0 { - i = encodeVarintChannel(dAtA, i, uint64(m.Ordering)) - i-- - dAtA[i] = 0x10 - } - if m.State != 0 { - i = encodeVarintChannel(dAtA, i, uint64(m.State)) - i-- - dAtA[i] = 0x8 - } - return len(dAtA) - i, nil -} - -func (m *Counterparty) 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 *Counterparty) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *Counterparty) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.ChannelId) > 0 { - i -= len(m.ChannelId) - copy(dAtA[i:], m.ChannelId) - i = encodeVarintChannel(dAtA, i, uint64(len(m.ChannelId))) - i-- - dAtA[i] = 0x12 - } - if len(m.PortId) > 0 { - i -= len(m.PortId) - copy(dAtA[i:], m.PortId) - i = encodeVarintChannel(dAtA, i, uint64(len(m.PortId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *Packet) 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 *Packet) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *Packet) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.TimeoutTimestamp != 0 { - i = encodeVarintChannel(dAtA, i, uint64(m.TimeoutTimestamp)) - i-- - dAtA[i] = 0x40 - } - { - size, err := m.TimeoutHeight.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintChannel(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x3a - if len(m.Data) > 0 { - i -= len(m.Data) - copy(dAtA[i:], m.Data) - i = encodeVarintChannel(dAtA, i, uint64(len(m.Data))) - i-- - dAtA[i] = 0x32 - } - if len(m.DestinationChannel) > 0 { - i -= len(m.DestinationChannel) - copy(dAtA[i:], m.DestinationChannel) - i = encodeVarintChannel(dAtA, i, uint64(len(m.DestinationChannel))) - i-- - dAtA[i] = 0x2a - } - if len(m.DestinationPort) > 0 { - i -= len(m.DestinationPort) - copy(dAtA[i:], m.DestinationPort) - i = encodeVarintChannel(dAtA, i, uint64(len(m.DestinationPort))) - i-- - dAtA[i] = 0x22 - } - if len(m.SourceChannel) > 0 { - i -= len(m.SourceChannel) - copy(dAtA[i:], m.SourceChannel) - i = encodeVarintChannel(dAtA, i, uint64(len(m.SourceChannel))) - i-- - dAtA[i] = 0x1a - } - if len(m.SourcePort) > 0 { - i -= len(m.SourcePort) - copy(dAtA[i:], m.SourcePort) - i = encodeVarintChannel(dAtA, i, uint64(len(m.SourcePort))) - i-- - dAtA[i] = 0x12 - } - if m.Sequence != 0 { - i = encodeVarintChannel(dAtA, i, uint64(m.Sequence)) - i-- - dAtA[i] = 0x8 - } - return len(dAtA) - i, nil -} - -func (m *PacketState) 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 *PacketState) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *PacketState) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Data) > 0 { - i -= len(m.Data) - copy(dAtA[i:], m.Data) - i = encodeVarintChannel(dAtA, i, uint64(len(m.Data))) - i-- - dAtA[i] = 0x22 - } - if m.Sequence != 0 { - i = encodeVarintChannel(dAtA, i, uint64(m.Sequence)) - i-- - dAtA[i] = 0x18 - } - if len(m.ChannelId) > 0 { - i -= len(m.ChannelId) - copy(dAtA[i:], m.ChannelId) - i = encodeVarintChannel(dAtA, i, uint64(len(m.ChannelId))) - i-- - dAtA[i] = 0x12 - } - if len(m.PortId) > 0 { - i -= len(m.PortId) - copy(dAtA[i:], m.PortId) - i = encodeVarintChannel(dAtA, i, uint64(len(m.PortId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *Acknowledgement) 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 *Acknowledgement) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *Acknowledgement) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.Response != nil { - { - size := m.Response.Size() - i -= size - if _, err := m.Response.MarshalTo(dAtA[i:]); err != nil { - return 0, err - } - } - } - return len(dAtA) - i, nil -} - -func (m *Acknowledgement_Result) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *Acknowledgement_Result) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - if m.Result != nil { - i -= len(m.Result) - copy(dAtA[i:], m.Result) - i = encodeVarintChannel(dAtA, i, uint64(len(m.Result))) - i-- - dAtA[i] = 0x1 - i-- - dAtA[i] = 0xaa - } - return len(dAtA) - i, nil -} -func (m *Acknowledgement_Error) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *Acknowledgement_Error) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - i -= len(m.Error) - copy(dAtA[i:], m.Error) - i = encodeVarintChannel(dAtA, i, uint64(len(m.Error))) - i-- - dAtA[i] = 0x1 - i-- - dAtA[i] = 0xb2 - return len(dAtA) - i, nil -} -func encodeVarintChannel(dAtA []byte, offset int, v uint64) int { - offset -= sovChannel(v) - base := offset - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ - } - dAtA[offset] = uint8(v) - return base -} -func (m *Channel) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.State != 0 { - n += 1 + sovChannel(uint64(m.State)) - } - if m.Ordering != 0 { - n += 1 + sovChannel(uint64(m.Ordering)) - } - l = m.Counterparty.Size() - n += 1 + l + sovChannel(uint64(l)) - if len(m.ConnectionHops) > 0 { - for _, s := range m.ConnectionHops { - l = len(s) - n += 1 + l + sovChannel(uint64(l)) - } - } - l = len(m.Version) - if l > 0 { - n += 1 + l + sovChannel(uint64(l)) - } - return n -} - -func (m *IdentifiedChannel) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.State != 0 { - n += 1 + sovChannel(uint64(m.State)) - } - if m.Ordering != 0 { - n += 1 + sovChannel(uint64(m.Ordering)) - } - l = m.Counterparty.Size() - n += 1 + l + sovChannel(uint64(l)) - if len(m.ConnectionHops) > 0 { - for _, s := range m.ConnectionHops { - l = len(s) - n += 1 + l + sovChannel(uint64(l)) - } - } - l = len(m.Version) - if l > 0 { - n += 1 + l + sovChannel(uint64(l)) - } - l = len(m.PortId) - if l > 0 { - n += 1 + l + sovChannel(uint64(l)) - } - l = len(m.ChannelId) - if l > 0 { - n += 1 + l + sovChannel(uint64(l)) - } - return n -} - -func (m *Counterparty) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.PortId) - if l > 0 { - n += 1 + l + sovChannel(uint64(l)) - } - l = len(m.ChannelId) - if l > 0 { - n += 1 + l + sovChannel(uint64(l)) - } - return n -} - -func (m *Packet) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.Sequence != 0 { - n += 1 + sovChannel(uint64(m.Sequence)) - } - l = len(m.SourcePort) - if l > 0 { - n += 1 + l + sovChannel(uint64(l)) - } - l = len(m.SourceChannel) - if l > 0 { - n += 1 + l + sovChannel(uint64(l)) - } - l = len(m.DestinationPort) - if l > 0 { - n += 1 + l + sovChannel(uint64(l)) - } - l = len(m.DestinationChannel) - if l > 0 { - n += 1 + l + sovChannel(uint64(l)) - } - l = len(m.Data) - if l > 0 { - n += 1 + l + sovChannel(uint64(l)) - } - l = m.TimeoutHeight.Size() - n += 1 + l + sovChannel(uint64(l)) - if m.TimeoutTimestamp != 0 { - n += 1 + sovChannel(uint64(m.TimeoutTimestamp)) - } - return n -} - -func (m *PacketState) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.PortId) - if l > 0 { - n += 1 + l + sovChannel(uint64(l)) - } - l = len(m.ChannelId) - if l > 0 { - n += 1 + l + sovChannel(uint64(l)) - } - if m.Sequence != 0 { - n += 1 + sovChannel(uint64(m.Sequence)) - } - l = len(m.Data) - if l > 0 { - n += 1 + l + sovChannel(uint64(l)) - } - return n -} - -func (m *Acknowledgement) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.Response != nil { - n += m.Response.Size() - } - return n -} - -func (m *Acknowledgement_Result) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.Result != nil { - l = len(m.Result) - n += 2 + l + sovChannel(uint64(l)) - } - return n -} -func (m *Acknowledgement_Error) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Error) - n += 2 + l + sovChannel(uint64(l)) - return n -} - -func sovChannel(x uint64) (n int) { - return (math_bits.Len64(x|1) + 6) / 7 -} -func sozChannel(x uint64) (n int) { - return sovChannel(uint64((x << 1) ^ uint64((int64(x) >> 63)))) -} -func (m *Channel) 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 ErrIntOverflowChannel - } - 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: Channel: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: Channel: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field State", wireType) - } - m.State = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowChannel - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.State |= State(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Ordering", wireType) - } - m.Ordering = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowChannel - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Ordering |= Order(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Counterparty", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowChannel - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthChannel - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthChannel - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.Counterparty.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ConnectionHops", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowChannel - } - 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 ErrInvalidLengthChannel - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthChannel - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ConnectionHops = append(m.ConnectionHops, string(dAtA[iNdEx:postIndex])) - iNdEx = postIndex - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowChannel - } - 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 ErrInvalidLengthChannel - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthChannel - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Version = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipChannel(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthChannel - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *IdentifiedChannel) 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 ErrIntOverflowChannel - } - 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: IdentifiedChannel: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: IdentifiedChannel: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field State", wireType) - } - m.State = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowChannel - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.State |= State(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Ordering", wireType) - } - m.Ordering = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowChannel - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Ordering |= Order(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Counterparty", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowChannel - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthChannel - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthChannel - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.Counterparty.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ConnectionHops", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowChannel - } - 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 ErrInvalidLengthChannel - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthChannel - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ConnectionHops = append(m.ConnectionHops, string(dAtA[iNdEx:postIndex])) - iNdEx = postIndex - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowChannel - } - 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 ErrInvalidLengthChannel - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthChannel - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Version = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 6: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field PortId", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowChannel - } - 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 ErrInvalidLengthChannel - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthChannel - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.PortId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 7: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ChannelId", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowChannel - } - 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 ErrInvalidLengthChannel - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthChannel - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ChannelId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipChannel(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthChannel - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *Counterparty) 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 ErrIntOverflowChannel - } - 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: Counterparty: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: Counterparty: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field PortId", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowChannel - } - 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 ErrInvalidLengthChannel - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthChannel - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.PortId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ChannelId", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowChannel - } - 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 ErrInvalidLengthChannel - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthChannel - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ChannelId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipChannel(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthChannel - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *Packet) 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 ErrIntOverflowChannel - } - 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: Packet: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: Packet: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Sequence", wireType) - } - m.Sequence = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowChannel - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Sequence |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field SourcePort", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowChannel - } - 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 ErrInvalidLengthChannel - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthChannel - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.SourcePort = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field SourceChannel", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowChannel - } - 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 ErrInvalidLengthChannel - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthChannel - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.SourceChannel = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field DestinationPort", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowChannel - } - 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 ErrInvalidLengthChannel - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthChannel - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.DestinationPort = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field DestinationChannel", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowChannel - } - 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 ErrInvalidLengthChannel - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthChannel - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.DestinationChannel = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 6: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowChannel - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthChannel - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthChannel - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...) - if m.Data == nil { - m.Data = []byte{} - } - iNdEx = postIndex - case 7: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field TimeoutHeight", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowChannel - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthChannel - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthChannel - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.TimeoutHeight.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 8: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field TimeoutTimestamp", wireType) - } - m.TimeoutTimestamp = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowChannel - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.TimeoutTimestamp |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - default: - iNdEx = preIndex - skippy, err := skipChannel(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthChannel - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *PacketState) 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 ErrIntOverflowChannel - } - 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: PacketState: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: PacketState: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field PortId", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowChannel - } - 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 ErrInvalidLengthChannel - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthChannel - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.PortId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ChannelId", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowChannel - } - 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 ErrInvalidLengthChannel - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthChannel - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ChannelId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Sequence", wireType) - } - m.Sequence = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowChannel - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Sequence |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowChannel - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthChannel - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthChannel - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...) - if m.Data == nil { - m.Data = []byte{} - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipChannel(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthChannel - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *Acknowledgement) 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 ErrIntOverflowChannel - } - 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: Acknowledgement: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: Acknowledgement: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 21: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Result", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowChannel - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthChannel - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthChannel - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - v := make([]byte, postIndex-iNdEx) - copy(v, dAtA[iNdEx:postIndex]) - m.Response = &Acknowledgement_Result{v} - iNdEx = postIndex - case 22: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Error", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowChannel - } - 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 ErrInvalidLengthChannel - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthChannel - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Response = &Acknowledgement_Error{string(dAtA[iNdEx:postIndex])} - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipChannel(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthChannel - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func skipChannel(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, ErrIntOverflowChannel - } - 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, ErrIntOverflowChannel - } - 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, ErrIntOverflowChannel - } - 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, ErrInvalidLengthChannel - } - iNdEx += length - case 3: - depth++ - case 4: - if depth == 0 { - return 0, ErrUnexpectedEndOfGroupChannel - } - depth-- - case 5: - iNdEx += 4 - default: - return 0, fmt.Errorf("proto: illegal wireType %d", wireType) - } - if iNdEx < 0 { - return 0, ErrInvalidLengthChannel - } - if depth == 0 { - return iNdEx, nil - } - } - return 0, io.ErrUnexpectedEOF -} - -var ( - ErrInvalidLengthChannel = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowChannel = fmt.Errorf("proto: integer overflow") - ErrUnexpectedEndOfGroupChannel = fmt.Errorf("proto: unexpected end of group") -) diff --git a/x/ibc/core/04-channel/types/channel_test.go b/x/ibc/core/04-channel/types/channel_test.go deleted file mode 100644 index a53304972ef5..000000000000 --- a/x/ibc/core/04-channel/types/channel_test.go +++ /dev/null @@ -1,59 +0,0 @@ -package types_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" -) - -func TestChannelValidateBasic(t *testing.T) { - counterparty := types.Counterparty{"portidone", "channelidone"} - testCases := []struct { - name string - channel types.Channel - expPass bool - }{ - {"valid channel", types.NewChannel(types.TRYOPEN, types.ORDERED, counterparty, connHops, version), true}, - {"invalid state", types.NewChannel(types.UNINITIALIZED, types.ORDERED, counterparty, connHops, version), false}, - {"invalid order", types.NewChannel(types.TRYOPEN, types.NONE, counterparty, connHops, version), false}, - {"more than 1 connection hop", types.NewChannel(types.TRYOPEN, types.ORDERED, counterparty, []string{"connection1", "connection2"}, version), false}, - {"invalid connection hop identifier", types.NewChannel(types.TRYOPEN, types.ORDERED, counterparty, []string{"(invalid)"}, version), false}, - {"invalid counterparty", types.NewChannel(types.TRYOPEN, types.ORDERED, types.NewCounterparty("(invalidport)", "channelidone"), connHops, version), false}, - } - - for i, tc := range testCases { - tc := tc - - err := tc.channel.ValidateBasic() - if tc.expPass { - require.NoError(t, err, "valid test case %d failed: %s", i, tc.name) - } else { - require.Error(t, err, "invalid test case %d passed: %s", i, tc.name) - } - } -} - -func TestCounterpartyValidateBasic(t *testing.T) { - testCases := []struct { - name string - counterparty types.Counterparty - expPass bool - }{ - {"valid counterparty", types.Counterparty{"portidone", "channelidone"}, true}, - {"invalid port id", types.Counterparty{"(InvalidPort)", "channelidone"}, false}, - {"invalid channel id", types.Counterparty{"portidone", "(InvalidChannel)"}, false}, - } - - for i, tc := range testCases { - tc := tc - - err := tc.counterparty.ValidateBasic() - if tc.expPass { - require.NoError(t, err, "valid test case %d failed: %s", i, tc.name) - } else { - require.Error(t, err, "invalid test case %d passed: %s", i, tc.name) - } - } -} diff --git a/x/ibc/core/04-channel/types/codec.go b/x/ibc/core/04-channel/types/codec.go deleted file mode 100644 index cfe0110264cb..000000000000 --- a/x/ibc/core/04-channel/types/codec.go +++ /dev/null @@ -1,51 +0,0 @@ -package types - -import ( - "github.com/cosmos/cosmos-sdk/codec" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/msgservice" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -// RegisterInterfaces register the ibc channel submodule interfaces to protobuf -// Any. -func RegisterInterfaces(registry codectypes.InterfaceRegistry) { - registry.RegisterInterface( - "ibc.core.channel.v1.ChannelI", - (*exported.ChannelI)(nil), - &Channel{}, - ) - registry.RegisterInterface( - "ibc.core.channel.v1.CounterpartyChannelI", - (*exported.CounterpartyChannelI)(nil), - &Counterparty{}, - ) - registry.RegisterInterface( - "ibc.core.channel.v1.PacketI", - (*exported.PacketI)(nil), - &Packet{}, - ) - registry.RegisterImplementations( - (*sdk.Msg)(nil), - &MsgChannelOpenInit{}, - &MsgChannelOpenTry{}, - &MsgChannelOpenAck{}, - &MsgChannelOpenConfirm{}, - &MsgChannelCloseInit{}, - &MsgChannelCloseConfirm{}, - &MsgRecvPacket{}, - &MsgAcknowledgement{}, - &MsgTimeout{}, - &MsgTimeoutOnClose{}, - ) - - msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) -} - -// SubModuleCdc references the global x/ibc/core/04-channel 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/core/04-channel and -// defined at the application level. -var SubModuleCdc = codec.NewProtoCodec(codectypes.NewInterfaceRegistry()) diff --git a/x/ibc/core/04-channel/types/errors.go b/x/ibc/core/04-channel/types/errors.go deleted file mode 100644 index 82cf773057d7..000000000000 --- a/x/ibc/core/04-channel/types/errors.go +++ /dev/null @@ -1,28 +0,0 @@ -package types - -import ( - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" -) - -// IBC channel sentinel errors -var ( - ErrChannelExists = sdkerrors.Register(SubModuleName, 2, "channel already exists") - ErrChannelNotFound = sdkerrors.Register(SubModuleName, 3, "channel not found") - ErrInvalidChannel = sdkerrors.Register(SubModuleName, 4, "invalid channel") - ErrInvalidChannelState = sdkerrors.Register(SubModuleName, 5, "invalid channel state") - ErrInvalidChannelOrdering = sdkerrors.Register(SubModuleName, 6, "invalid channel ordering") - ErrInvalidCounterparty = sdkerrors.Register(SubModuleName, 7, "invalid counterparty channel") - ErrInvalidChannelCapability = sdkerrors.Register(SubModuleName, 8, "invalid channel capability") - ErrChannelCapabilityNotFound = sdkerrors.Register(SubModuleName, 9, "channel capability not found") - ErrSequenceSendNotFound = sdkerrors.Register(SubModuleName, 10, "sequence send not found") - ErrSequenceReceiveNotFound = sdkerrors.Register(SubModuleName, 11, "sequence receive not found") - ErrSequenceAckNotFound = sdkerrors.Register(SubModuleName, 12, "sequence acknowledgement not found") - ErrInvalidPacket = sdkerrors.Register(SubModuleName, 13, "invalid packet") - ErrPacketTimeout = sdkerrors.Register(SubModuleName, 14, "packet timeout") - ErrTooManyConnectionHops = sdkerrors.Register(SubModuleName, 15, "too many connection hops") - ErrInvalidAcknowledgement = sdkerrors.Register(SubModuleName, 16, "invalid acknowledgement") - ErrPacketCommitmentNotFound = sdkerrors.Register(SubModuleName, 17, "packet commitment not found") - ErrPacketReceived = sdkerrors.Register(SubModuleName, 18, "packet already received") - ErrAcknowledgementExists = sdkerrors.Register(SubModuleName, 19, "acknowledgement for packet already exists") - ErrInvalidChannelIdentifier = sdkerrors.Register(SubModuleName, 20, "invalid channel identifier") -) diff --git a/x/ibc/core/04-channel/types/events.go b/x/ibc/core/04-channel/types/events.go deleted file mode 100644 index b9ddb3052c30..000000000000 --- a/x/ibc/core/04-channel/types/events.go +++ /dev/null @@ -1,46 +0,0 @@ -package types - -import ( - "fmt" - - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" -) - -// IBC channel events -const ( - AttributeKeyConnectionID = "connection_id" - AttributeKeyPortID = "port_id" - AttributeKeyChannelID = "channel_id" - AttributeCounterpartyPortID = "counterparty_port_id" - AttributeCounterpartyChannelID = "counterparty_channel_id" - - EventTypeSendPacket = "send_packet" - EventTypeRecvPacket = "recv_packet" - EventTypeWriteAck = "write_acknowledgement" - EventTypeAcknowledgePacket = "acknowledge_packet" - EventTypeTimeoutPacket = "timeout_packet" - - AttributeKeyData = "packet_data" - AttributeKeyAck = "packet_ack" - AttributeKeyTimeoutHeight = "packet_timeout_height" - AttributeKeyTimeoutTimestamp = "packet_timeout_timestamp" - AttributeKeySequence = "packet_sequence" - AttributeKeySrcPort = "packet_src_port" - AttributeKeySrcChannel = "packet_src_channel" - AttributeKeyDstPort = "packet_dst_port" - AttributeKeyDstChannel = "packet_dst_channel" - AttributeKeyChannelOrdering = "packet_channel_ordering" - AttributeKeyConnection = "packet_connection" -) - -// IBC channel events vars -var ( - EventTypeChannelOpenInit = MsgChannelOpenInit{}.Type() - EventTypeChannelOpenTry = MsgChannelOpenTry{}.Type() - EventTypeChannelOpenAck = MsgChannelOpenAck{}.Type() - EventTypeChannelOpenConfirm = MsgChannelOpenConfirm{}.Type() - EventTypeChannelCloseInit = MsgChannelCloseInit{}.Type() - EventTypeChannelCloseConfirm = MsgChannelCloseConfirm{}.Type() - - AttributeValueCategory = fmt.Sprintf("%s_%s", host.ModuleName, SubModuleName) -) diff --git a/x/ibc/core/04-channel/types/expected_keepers.go b/x/ibc/core/04-channel/types/expected_keepers.go deleted file mode 100644 index d3b74b7e29ab..000000000000 --- a/x/ibc/core/04-channel/types/expected_keepers.go +++ /dev/null @@ -1,76 +0,0 @@ -package types - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" - capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" - connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -// ClientKeeper expected account IBC client keeper -type ClientKeeper interface { - GetClientState(ctx sdk.Context, clientID string) (exported.ClientState, bool) - GetClientConsensusState(ctx sdk.Context, clientID string, height exported.Height) (exported.ConsensusState, bool) -} - -// ConnectionKeeper expected account IBC connection keeper -type ConnectionKeeper interface { - GetConnection(ctx sdk.Context, connectionID string) (connectiontypes.ConnectionEnd, bool) - GetTimestampAtHeight( - ctx sdk.Context, - connection connectiontypes.ConnectionEnd, - height exported.Height, - ) (uint64, error) - VerifyChannelState( - ctx sdk.Context, - connection exported.ConnectionI, - height exported.Height, - proof []byte, - portID, - channelID string, - channel exported.ChannelI, - ) error - VerifyPacketCommitment( - ctx sdk.Context, - connection exported.ConnectionI, - height exported.Height, - proof []byte, - portID, - channelID string, - sequence uint64, - commitmentBytes []byte, - ) error - VerifyPacketAcknowledgement( - ctx sdk.Context, - connection exported.ConnectionI, - height exported.Height, - proof []byte, - portID, - channelID string, - sequence uint64, - acknowledgement []byte, - ) error - VerifyPacketReceiptAbsence( - ctx sdk.Context, - connection exported.ConnectionI, - height exported.Height, - proof []byte, - portID, - channelID string, - sequence uint64, - ) error - VerifyNextSequenceRecv( - ctx sdk.Context, - connection exported.ConnectionI, - height exported.Height, - proof []byte, - portID, - channelID string, - nextSequenceRecv uint64, - ) error -} - -// PortKeeper expected account IBC port keeper -type PortKeeper interface { - Authenticate(ctx sdk.Context, key *capabilitytypes.Capability, portID string) bool -} diff --git a/x/ibc/core/04-channel/types/genesis.go b/x/ibc/core/04-channel/types/genesis.go deleted file mode 100644 index 2c431e97b335..000000000000 --- a/x/ibc/core/04-channel/types/genesis.go +++ /dev/null @@ -1,156 +0,0 @@ -package types - -import ( - "errors" - "fmt" - - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" -) - -// NewPacketState creates a new PacketState instance. -func NewPacketState(portID, channelID string, seq uint64, data []byte) PacketState { - return PacketState{ - PortId: portID, - ChannelId: channelID, - Sequence: seq, - Data: data, - } -} - -// Validate performs basic validation of fields returning an error upon any -// failure. -func (pa PacketState) Validate() error { - if pa.Data == nil { - return errors.New("data bytes cannot be nil") - } - return validateGenFields(pa.PortId, pa.ChannelId, pa.Sequence) -} - -// NewPacketSequence creates a new PacketSequences instance. -func NewPacketSequence(portID, channelID string, seq uint64) PacketSequence { - return PacketSequence{ - PortId: portID, - ChannelId: channelID, - Sequence: seq, - } -} - -// Validate performs basic validation of fields returning an error upon any -// failure. -func (ps PacketSequence) Validate() error { - return validateGenFields(ps.PortId, ps.ChannelId, ps.Sequence) -} - -// NewGenesisState creates a GenesisState instance. -func NewGenesisState( - channels []IdentifiedChannel, acks, receipts, commitments []PacketState, - sendSeqs, recvSeqs, ackSeqs []PacketSequence, nextChannelSequence uint64, -) GenesisState { - return GenesisState{ - Channels: channels, - Acknowledgements: acks, - Commitments: commitments, - SendSequences: sendSeqs, - RecvSequences: recvSeqs, - AckSequences: ackSeqs, - NextChannelSequence: nextChannelSequence, - } -} - -// DefaultGenesisState returns the ibc channel submodule's default genesis state. -func DefaultGenesisState() GenesisState { - return GenesisState{ - Channels: []IdentifiedChannel{}, - Acknowledgements: []PacketState{}, - Receipts: []PacketState{}, - Commitments: []PacketState{}, - SendSequences: []PacketSequence{}, - RecvSequences: []PacketSequence{}, - AckSequences: []PacketSequence{}, - NextChannelSequence: 0, - } -} - -// Validate performs basic genesis state validation returning an error upon any -// failure. -func (gs GenesisState) Validate() error { - // keep track of the max sequence to ensure it is less than - // the next sequence used in creating connection identifers. - var maxSequence uint64 = 0 - - for i, channel := range gs.Channels { - sequence, err := ParseChannelSequence(channel.ChannelId) - if err != nil { - return err - } - - if sequence > maxSequence { - maxSequence = sequence - } - - if err := channel.ValidateBasic(); err != nil { - return fmt.Errorf("invalid channel %v channel index %d: %w", channel, i, err) - } - } - - if maxSequence != 0 && maxSequence >= gs.NextChannelSequence { - return fmt.Errorf("next channel sequence %d must be greater than maximum sequence used in channel identifier %d", gs.NextChannelSequence, maxSequence) - } - - for i, ack := range gs.Acknowledgements { - if err := ack.Validate(); err != nil { - return fmt.Errorf("invalid acknowledgement %v ack index %d: %w", ack, i, err) - } - if len(ack.Data) == 0 { - return fmt.Errorf("invalid acknowledgement %v ack index %d: data bytes cannot be empty", ack, i) - } - } - - for i, receipt := range gs.Receipts { - if err := receipt.Validate(); err != nil { - return fmt.Errorf("invalid acknowledgement %v ack index %d: %w", receipt, i, err) - } - } - - for i, commitment := range gs.Commitments { - if err := commitment.Validate(); err != nil { - return fmt.Errorf("invalid commitment %v index %d: %w", commitment, i, err) - } - if len(commitment.Data) == 0 { - return fmt.Errorf("invalid acknowledgement %v ack index %d: data bytes cannot be empty", commitment, i) - } - } - - for i, ss := range gs.SendSequences { - if err := ss.Validate(); err != nil { - return fmt.Errorf("invalid send sequence %v index %d: %w", ss, i, err) - } - } - - for i, rs := range gs.RecvSequences { - if err := rs.Validate(); err != nil { - return fmt.Errorf("invalid receive sequence %v index %d: %w", rs, i, err) - } - } - - for i, as := range gs.AckSequences { - if err := as.Validate(); err != nil { - return fmt.Errorf("invalid acknowledgement sequence %v index %d: %w", as, i, err) - } - } - - return nil -} - -func validateGenFields(portID, channelID string, sequence uint64) error { - if err := host.PortIdentifierValidator(portID); err != nil { - return fmt.Errorf("invalid port Id: %w", err) - } - if err := host.ChannelIdentifierValidator(channelID); err != nil { - return fmt.Errorf("invalid channel Id: %w", err) - } - if sequence == 0 { - return errors.New("sequence cannot be 0") - } - return nil -} diff --git a/x/ibc/core/04-channel/types/genesis.pb.go b/x/ibc/core/04-channel/types/genesis.pb.go deleted file mode 100644 index c54c6f9deb03..000000000000 --- a/x/ibc/core/04-channel/types/genesis.pb.go +++ /dev/null @@ -1,1015 +0,0 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: ibc/core/channel/v1/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 defines the ibc channel submodule's genesis state. -type GenesisState struct { - Channels []IdentifiedChannel `protobuf:"bytes,1,rep,name=channels,proto3,casttype=IdentifiedChannel" json:"channels"` - Acknowledgements []PacketState `protobuf:"bytes,2,rep,name=acknowledgements,proto3" json:"acknowledgements"` - Commitments []PacketState `protobuf:"bytes,3,rep,name=commitments,proto3" json:"commitments"` - Receipts []PacketState `protobuf:"bytes,4,rep,name=receipts,proto3" json:"receipts"` - SendSequences []PacketSequence `protobuf:"bytes,5,rep,name=send_sequences,json=sendSequences,proto3" json:"send_sequences" yaml:"send_sequences"` - RecvSequences []PacketSequence `protobuf:"bytes,6,rep,name=recv_sequences,json=recvSequences,proto3" json:"recv_sequences" yaml:"recv_sequences"` - AckSequences []PacketSequence `protobuf:"bytes,7,rep,name=ack_sequences,json=ackSequences,proto3" json:"ack_sequences" yaml:"ack_sequences"` - // the sequence for the next generated channel identifier - NextChannelSequence uint64 `protobuf:"varint,8,opt,name=next_channel_sequence,json=nextChannelSequence,proto3" json:"next_channel_sequence,omitempty" yaml:"next_channel_sequence"` -} - -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_cb06ec201f452595, []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) GetChannels() []IdentifiedChannel { - if m != nil { - return m.Channels - } - return nil -} - -func (m *GenesisState) GetAcknowledgements() []PacketState { - if m != nil { - return m.Acknowledgements - } - return nil -} - -func (m *GenesisState) GetCommitments() []PacketState { - if m != nil { - return m.Commitments - } - return nil -} - -func (m *GenesisState) GetReceipts() []PacketState { - if m != nil { - return m.Receipts - } - return nil -} - -func (m *GenesisState) GetSendSequences() []PacketSequence { - if m != nil { - return m.SendSequences - } - return nil -} - -func (m *GenesisState) GetRecvSequences() []PacketSequence { - if m != nil { - return m.RecvSequences - } - return nil -} - -func (m *GenesisState) GetAckSequences() []PacketSequence { - if m != nil { - return m.AckSequences - } - return nil -} - -func (m *GenesisState) GetNextChannelSequence() uint64 { - if m != nil { - return m.NextChannelSequence - } - return 0 -} - -// PacketSequence defines the genesis type necessary to retrieve and store -// next send and receive sequences. -type PacketSequence struct { - PortId string `protobuf:"bytes,1,opt,name=port_id,json=portId,proto3" json:"port_id,omitempty" yaml:"port_id"` - ChannelId string `protobuf:"bytes,2,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty" yaml:"channel_id"` - Sequence uint64 `protobuf:"varint,3,opt,name=sequence,proto3" json:"sequence,omitempty"` -} - -func (m *PacketSequence) Reset() { *m = PacketSequence{} } -func (m *PacketSequence) String() string { return proto.CompactTextString(m) } -func (*PacketSequence) ProtoMessage() {} -func (*PacketSequence) Descriptor() ([]byte, []int) { - return fileDescriptor_cb06ec201f452595, []int{1} -} -func (m *PacketSequence) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *PacketSequence) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_PacketSequence.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 *PacketSequence) XXX_Merge(src proto.Message) { - xxx_messageInfo_PacketSequence.Merge(m, src) -} -func (m *PacketSequence) XXX_Size() int { - return m.Size() -} -func (m *PacketSequence) XXX_DiscardUnknown() { - xxx_messageInfo_PacketSequence.DiscardUnknown(m) -} - -var xxx_messageInfo_PacketSequence proto.InternalMessageInfo - -func (m *PacketSequence) GetPortId() string { - if m != nil { - return m.PortId - } - return "" -} - -func (m *PacketSequence) GetChannelId() string { - if m != nil { - return m.ChannelId - } - return "" -} - -func (m *PacketSequence) GetSequence() uint64 { - if m != nil { - return m.Sequence - } - return 0 -} - -func init() { - proto.RegisterType((*GenesisState)(nil), "ibc.core.channel.v1.GenesisState") - proto.RegisterType((*PacketSequence)(nil), "ibc.core.channel.v1.PacketSequence") -} - -func init() { proto.RegisterFile("ibc/core/channel/v1/genesis.proto", fileDescriptor_cb06ec201f452595) } - -var fileDescriptor_cb06ec201f452595 = []byte{ - // 501 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x93, 0xcf, 0x6e, 0xd3, 0x40, - 0x10, 0x87, 0xe3, 0x26, 0x4d, 0xd3, 0x6d, 0x13, 0xd1, 0x6d, 0x23, 0x99, 0xa8, 0xd8, 0xc6, 0x48, - 0x28, 0x12, 0xaa, 0x4d, 0xa1, 0x07, 0xc4, 0xd1, 0x1c, 0x20, 0x37, 0xb4, 0x70, 0x42, 0x42, 0x91, - 0xb3, 0x9e, 0xba, 0x2b, 0xc7, 0xde, 0xe0, 0xdd, 0x86, 0xf6, 0x29, 0xe0, 0xb1, 0x7a, 0xec, 0x91, - 0x93, 0x85, 0x92, 0x37, 0xc8, 0x91, 0x13, 0xf2, 0xdf, 0x24, 0x6a, 0x84, 0x68, 0x4f, 0xde, 0x9d, - 0xf9, 0xcd, 0xf7, 0xcd, 0xc1, 0x8b, 0x9e, 0xb2, 0x11, 0xb5, 0x29, 0x8f, 0xc1, 0xa6, 0x17, 0x6e, - 0x14, 0xc1, 0xd8, 0x9e, 0x9e, 0xda, 0x3e, 0x44, 0x20, 0x98, 0xb0, 0x26, 0x31, 0x97, 0x1c, 0x1f, - 0xb2, 0x11, 0xb5, 0xd2, 0x88, 0x55, 0x44, 0xac, 0xe9, 0x69, 0xef, 0xc8, 0xe7, 0x3e, 0xcf, 0xfa, - 0x76, 0x7a, 0xca, 0xa3, 0xbd, 0x8d, 0xb4, 0x72, 0x2a, 0x8b, 0x98, 0xf3, 0x6d, 0xb4, 0xff, 0x3e, - 0xe7, 0x7f, 0x92, 0xae, 0x04, 0xfc, 0x15, 0xb5, 0x8a, 0x84, 0x50, 0x15, 0xa3, 0xde, 0xdf, 0x7b, - 0xf5, 0xdc, 0xda, 0x60, 0xb4, 0x06, 0x1e, 0x44, 0x92, 0x9d, 0x33, 0xf0, 0xde, 0xe5, 0x45, 0xe7, - 0xf1, 0x4d, 0xa2, 0xd7, 0xfe, 0x24, 0xfa, 0xc1, 0x9d, 0x16, 0xa9, 0x90, 0x98, 0xa0, 0x47, 0x2e, - 0x0d, 0x22, 0xfe, 0x7d, 0x0c, 0x9e, 0x0f, 0x21, 0x44, 0x52, 0xa8, 0x5b, 0x99, 0xc6, 0xd8, 0xa8, - 0xf9, 0xe8, 0xd2, 0x00, 0x64, 0xb6, 0x9a, 0xd3, 0x48, 0x05, 0xe4, 0xce, 0x3c, 0xfe, 0x80, 0xf6, - 0x28, 0x0f, 0x43, 0x26, 0x73, 0x5c, 0xfd, 0x5e, 0xb8, 0xd5, 0x51, 0xec, 0xa0, 0x56, 0x0c, 0x14, - 0xd8, 0x44, 0x0a, 0xb5, 0x71, 0x2f, 0x4c, 0x35, 0x87, 0x19, 0xea, 0x08, 0x88, 0xbc, 0xa1, 0x80, - 0x6f, 0x97, 0x10, 0x51, 0x10, 0xea, 0x76, 0x46, 0x7a, 0xf6, 0x2f, 0x52, 0x91, 0x75, 0x9e, 0xa4, - 0xb0, 0x45, 0xa2, 0x77, 0xaf, 0xdd, 0x70, 0xfc, 0xd6, 0x5c, 0x07, 0x99, 0xa4, 0x9d, 0x16, 0xca, - 0x70, 0xa6, 0x8a, 0x81, 0x4e, 0x57, 0x54, 0xcd, 0x07, 0xab, 0xd6, 0x41, 0x26, 0x69, 0xa7, 0x85, - 0xa5, 0xea, 0x1c, 0xb5, 0x5d, 0x1a, 0xac, 0x98, 0x76, 0xfe, 0xdf, 0x74, 0x5c, 0x98, 0x8e, 0x72, - 0xd3, 0x1a, 0xc7, 0x24, 0xfb, 0x2e, 0x0d, 0x96, 0x9e, 0xcf, 0xa8, 0x1b, 0xc1, 0x95, 0x1c, 0x16, - 0xb4, 0x2a, 0xa8, 0xb6, 0x0c, 0xa5, 0xdf, 0x70, 0x8c, 0x45, 0xa2, 0x1f, 0xe7, 0x98, 0x8d, 0x31, - 0x93, 0x1c, 0xa6, 0xf5, 0xe2, 0xbf, 0x2b, 0xb1, 0xe6, 0x0f, 0x05, 0x75, 0xd6, 0x97, 0xc2, 0x2f, - 0xd0, 0xce, 0x84, 0xc7, 0x72, 0xc8, 0x3c, 0x55, 0x31, 0x94, 0xfe, 0xae, 0x83, 0x17, 0x89, 0xde, - 0xc9, 0xd1, 0x45, 0xc3, 0x24, 0xcd, 0xf4, 0x34, 0xf0, 0xf0, 0x19, 0x42, 0xa5, 0x89, 0x79, 0xea, - 0x56, 0x96, 0xef, 0x2e, 0x12, 0xfd, 0x20, 0xcf, 0x2f, 0x7b, 0x26, 0xd9, 0x2d, 0x2e, 0x03, 0x0f, - 0xf7, 0x50, 0xab, 0x5a, 0xbf, 0x9e, 0xae, 0x4f, 0xaa, 0xbb, 0x43, 0x6e, 0x66, 0x9a, 0x72, 0x3b, - 0xd3, 0x94, 0xdf, 0x33, 0x4d, 0xf9, 0x39, 0xd7, 0x6a, 0xb7, 0x73, 0xad, 0xf6, 0x6b, 0xae, 0xd5, - 0xbe, 0xbc, 0xf1, 0x99, 0xbc, 0xb8, 0x1c, 0x59, 0x94, 0x87, 0x36, 0xe5, 0x22, 0xe4, 0xa2, 0xf8, - 0x9c, 0x08, 0x2f, 0xb0, 0xaf, 0xec, 0xea, 0x4d, 0xbf, 0x3c, 0x3b, 0x29, 0x9f, 0xb5, 0xbc, 0x9e, - 0x80, 0x18, 0x35, 0xb3, 0x27, 0xfd, 0xfa, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x3c, 0x42, 0xc2, - 0x18, 0x45, 0x04, 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 m.NextChannelSequence != 0 { - i = encodeVarintGenesis(dAtA, i, uint64(m.NextChannelSequence)) - i-- - dAtA[i] = 0x40 - } - if len(m.AckSequences) > 0 { - for iNdEx := len(m.AckSequences) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.AckSequences[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintGenesis(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x3a - } - } - if len(m.RecvSequences) > 0 { - for iNdEx := len(m.RecvSequences) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.RecvSequences[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintGenesis(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x32 - } - } - if len(m.SendSequences) > 0 { - for iNdEx := len(m.SendSequences) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.SendSequences[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintGenesis(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x2a - } - } - if len(m.Receipts) > 0 { - for iNdEx := len(m.Receipts) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.Receipts[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintGenesis(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x22 - } - } - if len(m.Commitments) > 0 { - for iNdEx := len(m.Commitments) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.Commitments[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintGenesis(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - } - } - if len(m.Acknowledgements) > 0 { - for iNdEx := len(m.Acknowledgements) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.Acknowledgements[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintGenesis(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - } - } - if len(m.Channels) > 0 { - for iNdEx := len(m.Channels) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.Channels[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 *PacketSequence) 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 *PacketSequence) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *PacketSequence) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.Sequence != 0 { - i = encodeVarintGenesis(dAtA, i, uint64(m.Sequence)) - i-- - dAtA[i] = 0x18 - } - if len(m.ChannelId) > 0 { - i -= len(m.ChannelId) - copy(dAtA[i:], m.ChannelId) - i = encodeVarintGenesis(dAtA, i, uint64(len(m.ChannelId))) - i-- - dAtA[i] = 0x12 - } - if len(m.PortId) > 0 { - i -= len(m.PortId) - copy(dAtA[i:], m.PortId) - i = encodeVarintGenesis(dAtA, i, uint64(len(m.PortId))) - 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.Channels) > 0 { - for _, e := range m.Channels { - l = e.Size() - n += 1 + l + sovGenesis(uint64(l)) - } - } - if len(m.Acknowledgements) > 0 { - for _, e := range m.Acknowledgements { - l = e.Size() - n += 1 + l + sovGenesis(uint64(l)) - } - } - if len(m.Commitments) > 0 { - for _, e := range m.Commitments { - l = e.Size() - n += 1 + l + sovGenesis(uint64(l)) - } - } - if len(m.Receipts) > 0 { - for _, e := range m.Receipts { - l = e.Size() - n += 1 + l + sovGenesis(uint64(l)) - } - } - if len(m.SendSequences) > 0 { - for _, e := range m.SendSequences { - l = e.Size() - n += 1 + l + sovGenesis(uint64(l)) - } - } - if len(m.RecvSequences) > 0 { - for _, e := range m.RecvSequences { - l = e.Size() - n += 1 + l + sovGenesis(uint64(l)) - } - } - if len(m.AckSequences) > 0 { - for _, e := range m.AckSequences { - l = e.Size() - n += 1 + l + sovGenesis(uint64(l)) - } - } - if m.NextChannelSequence != 0 { - n += 1 + sovGenesis(uint64(m.NextChannelSequence)) - } - return n -} - -func (m *PacketSequence) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.PortId) - if l > 0 { - n += 1 + l + sovGenesis(uint64(l)) - } - l = len(m.ChannelId) - if l > 0 { - n += 1 + l + sovGenesis(uint64(l)) - } - if m.Sequence != 0 { - n += 1 + sovGenesis(uint64(m.Sequence)) - } - 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 Channels", 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.Channels = append(m.Channels, IdentifiedChannel{}) - if err := m.Channels[len(m.Channels)-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 Acknowledgements", 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.Acknowledgements = append(m.Acknowledgements, PacketState{}) - if err := m.Acknowledgements[len(m.Acknowledgements)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Commitments", 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.Commitments = append(m.Commitments, PacketState{}) - if err := m.Commitments[len(m.Commitments)-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 Receipts", 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.Receipts = append(m.Receipts, PacketState{}) - if err := m.Receipts[len(m.Receipts)-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 SendSequences", 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.SendSequences = append(m.SendSequences, PacketSequence{}) - if err := m.SendSequences[len(m.SendSequences)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 6: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field RecvSequences", 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.RecvSequences = append(m.RecvSequences, PacketSequence{}) - if err := m.RecvSequences[len(m.RecvSequences)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 7: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field AckSequences", 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.AckSequences = append(m.AckSequences, PacketSequence{}) - if err := m.AckSequences[len(m.AckSequences)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 8: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field NextChannelSequence", wireType) - } - m.NextChannelSequence = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenesis - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.NextChannelSequence |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - 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 *PacketSequence) 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: PacketSequence: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: PacketSequence: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field PortId", 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.PortId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ChannelId", 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.ChannelId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Sequence", wireType) - } - m.Sequence = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenesis - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Sequence |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - 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/ibc/core/04-channel/types/genesis_test.go b/x/ibc/core/04-channel/types/genesis_test.go deleted file mode 100644 index a0d21007a776..000000000000 --- a/x/ibc/core/04-channel/types/genesis_test.go +++ /dev/null @@ -1,225 +0,0 @@ -package types_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" -) - -const ( - testPort1 = "firstport" - testPort2 = "secondport" - testConnectionIDA = "connectionidatob" - - testChannel1 = "channel-0" - testChannel2 = "channel-1" - - testChannelOrder = types.ORDERED - testChannelVersion = "1.0" -) - -func TestValidateGenesis(t *testing.T) { - counterparty1 := types.NewCounterparty(testPort1, testChannel1) - counterparty2 := types.NewCounterparty(testPort2, testChannel2) - testCases := []struct { - name string - genState types.GenesisState - expPass bool - }{ - { - name: "default", - genState: types.DefaultGenesisState(), - expPass: true, - }, - { - name: "valid genesis", - genState: types.NewGenesisState( - []types.IdentifiedChannel{ - types.NewIdentifiedChannel( - testPort1, testChannel1, types.NewChannel( - types.INIT, testChannelOrder, counterparty2, []string{testConnectionIDA}, testChannelVersion, - ), - ), - types.NewIdentifiedChannel( - testPort2, testChannel2, types.NewChannel( - types.INIT, testChannelOrder, counterparty1, []string{testConnectionIDA}, testChannelVersion, - ), - ), - }, - []types.PacketState{ - types.NewPacketState(testPort2, testChannel2, 1, []byte("ack")), - }, - []types.PacketState{ - types.NewPacketState(testPort2, testChannel2, 1, []byte("")), - }, - []types.PacketState{ - types.NewPacketState(testPort1, testChannel1, 1, []byte("commit_hash")), - }, - []types.PacketSequence{ - types.NewPacketSequence(testPort1, testChannel1, 1), - }, - []types.PacketSequence{ - types.NewPacketSequence(testPort2, testChannel2, 1), - }, - []types.PacketSequence{ - types.NewPacketSequence(testPort2, testChannel2, 1), - }, - 2, - ), - expPass: true, - }, - { - name: "invalid channel", - genState: types.GenesisState{ - Channels: []types.IdentifiedChannel{ - types.NewIdentifiedChannel( - testPort1, "(testChannel1)", types.NewChannel( - types.INIT, testChannelOrder, counterparty2, []string{testConnectionIDA}, testChannelVersion, - ), - ), - }, - }, - expPass: false, - }, - { - name: "invalid ack", - genState: types.GenesisState{ - Acknowledgements: []types.PacketState{ - types.NewPacketState(testPort2, testChannel2, 1, nil), - }, - }, - expPass: false, - }, - { - name: "invalid commitment", - genState: types.GenesisState{ - Commitments: []types.PacketState{ - types.NewPacketState(testPort1, testChannel1, 1, nil), - }, - }, - expPass: false, - }, - { - name: "invalid send seq", - genState: types.GenesisState{ - SendSequences: []types.PacketSequence{ - types.NewPacketSequence(testPort1, testChannel1, 0), - }, - }, - expPass: false, - }, - { - name: "invalid recv seq", - genState: types.GenesisState{ - RecvSequences: []types.PacketSequence{ - types.NewPacketSequence(testPort1, "(testChannel1)", 1), - }, - }, - expPass: false, - }, - { - name: "invalid recv seq 2", - genState: types.GenesisState{ - RecvSequences: []types.PacketSequence{ - types.NewPacketSequence("(testPort1)", testChannel1, 1), - }, - }, - expPass: false, - }, - { - name: "invalid ack seq", - genState: types.GenesisState{ - AckSequences: []types.PacketSequence{ - types.NewPacketSequence(testPort1, "(testChannel1)", 1), - }, - }, - expPass: false, - }, - { - name: "invalid channel identifier", - genState: types.NewGenesisState( - []types.IdentifiedChannel{ - types.NewIdentifiedChannel( - testPort1, "chan-0", types.NewChannel( - types.INIT, testChannelOrder, counterparty2, []string{testConnectionIDA}, testChannelVersion, - ), - ), - types.NewIdentifiedChannel( - testPort2, testChannel2, types.NewChannel( - types.INIT, testChannelOrder, counterparty1, []string{testConnectionIDA}, testChannelVersion, - ), - ), - }, - []types.PacketState{ - types.NewPacketState(testPort2, testChannel2, 1, []byte("ack")), - }, - []types.PacketState{ - types.NewPacketState(testPort2, testChannel2, 1, []byte("")), - }, - []types.PacketState{ - types.NewPacketState(testPort1, testChannel1, 1, []byte("commit_hash")), - }, - []types.PacketSequence{ - types.NewPacketSequence(testPort1, testChannel1, 1), - }, - []types.PacketSequence{ - types.NewPacketSequence(testPort2, testChannel2, 1), - }, - []types.PacketSequence{ - types.NewPacketSequence(testPort2, testChannel2, 1), - }, - 0, - ), - expPass: false, - }, - { - name: "next channel sequence is less than maximum channel identifier sequence used", - genState: types.NewGenesisState( - []types.IdentifiedChannel{ - types.NewIdentifiedChannel( - testPort1, "channel-10", types.NewChannel( - types.INIT, testChannelOrder, counterparty2, []string{testConnectionIDA}, testChannelVersion, - ), - ), - types.NewIdentifiedChannel( - testPort2, testChannel2, types.NewChannel( - types.INIT, testChannelOrder, counterparty1, []string{testConnectionIDA}, testChannelVersion, - ), - ), - }, - []types.PacketState{ - types.NewPacketState(testPort2, testChannel2, 1, []byte("ack")), - }, - []types.PacketState{ - types.NewPacketState(testPort2, testChannel2, 1, []byte("")), - }, - []types.PacketState{ - types.NewPacketState(testPort1, testChannel1, 1, []byte("commit_hash")), - }, - []types.PacketSequence{ - types.NewPacketSequence(testPort1, testChannel1, 1), - }, - []types.PacketSequence{ - types.NewPacketSequence(testPort2, testChannel2, 1), - }, - []types.PacketSequence{ - types.NewPacketSequence(testPort2, testChannel2, 1), - }, - 0, - ), - expPass: false, - }, - } - - for _, tc := range testCases { - tc := tc - err := tc.genState.Validate() - if tc.expPass { - require.NoError(t, err, tc.name) - } else { - require.Error(t, err, tc.name) - } - } -} diff --git a/x/ibc/core/04-channel/types/keys.go b/x/ibc/core/04-channel/types/keys.go deleted file mode 100644 index d3a6cde24d56..000000000000 --- a/x/ibc/core/04-channel/types/keys.go +++ /dev/null @@ -1,61 +0,0 @@ -package types - -import ( - "fmt" - "regexp" - - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" -) - -const ( - // SubModuleName defines the IBC channels name - SubModuleName = "channel" - - // StoreKey is the store key string for IBC channels - StoreKey = SubModuleName - - // RouterKey is the message route for IBC channels - RouterKey = SubModuleName - - // QuerierRoute is the querier route for IBC channels - QuerierRoute = SubModuleName - - // KeyNextChannelSequence is the key used to store the next channel sequence in - // the keeper. - KeyNextChannelSequence = "nextChannelSequence" - - // ChannelPrefix is the prefix used when creating a channel identifier - ChannelPrefix = "channel-" -) - -// FormatChannelIdentifier returns the channel identifier with the sequence appended. -// This is a SDK specific format not enforced by IBC protocol. -func FormatChannelIdentifier(sequence uint64) string { - return fmt.Sprintf("%s%d", ChannelPrefix, sequence) -} - -// IsChannelIDFormat checks if a channelID is in the format required on the SDK for -// parsing channel identifiers. The channel identifier must be in the form: `channel-{N} -var IsChannelIDFormat = regexp.MustCompile(`^channel-[0-9]{1,20}$`).MatchString - -// IsValidChannelID checks if a channelID is valid and can be parsed to the channel -// identifier format. -func IsValidChannelID(channelID string) bool { - _, err := ParseChannelSequence(channelID) - return err == nil -} - -// ParseChannelSequence parses the channel sequence from the channel identifier. -func ParseChannelSequence(channelID string) (uint64, error) { - if !IsChannelIDFormat(channelID) { - return 0, sdkerrors.Wrap(host.ErrInvalidID, "channel identifier is not in the format: `channel-{N}`") - } - - sequence, err := host.ParseIdentifier(channelID, ChannelPrefix) - if err != nil { - return 0, sdkerrors.Wrap(err, "invalid channel identifier") - } - - return sequence, nil -} diff --git a/x/ibc/core/04-channel/types/keys_test.go b/x/ibc/core/04-channel/types/keys_test.go deleted file mode 100644 index 9bc6500b9aff..000000000000 --- a/x/ibc/core/04-channel/types/keys_test.go +++ /dev/null @@ -1,47 +0,0 @@ -package types_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" -) - -// tests ParseChannelSequence and IsValidChannelID -func TestParseChannelSequence(t *testing.T) { - testCases := []struct { - name string - channelID string - expSeq uint64 - expPass bool - }{ - {"valid 0", "channel-0", 0, true}, - {"valid 1", "channel-1", 1, true}, - {"valid large sequence", "channel-234568219356718293", 234568219356718293, true}, - // one above uint64 max - {"invalid uint64", "channel-18446744073709551616", 0, false}, - // uint64 == 20 characters - {"invalid large sequence", "channel-2345682193567182931243", 0, false}, - {"capital prefix", "Channel-0", 0, false}, - {"missing dash", "channel0", 0, false}, - {"blank id", " ", 0, false}, - {"empty id", "", 0, false}, - {"negative sequence", "channel--1", 0, false}, - } - - for _, tc := range testCases { - - seq, err := types.ParseChannelSequence(tc.channelID) - valid := types.IsValidChannelID(tc.channelID) - require.Equal(t, tc.expSeq, seq) - - if tc.expPass { - require.NoError(t, err, tc.name) - require.True(t, valid) - } else { - require.Error(t, err, tc.name) - require.False(t, valid) - } - } -} diff --git a/x/ibc/core/04-channel/types/msgs.go b/x/ibc/core/04-channel/types/msgs.go deleted file mode 100644 index da14a31030fa..000000000000 --- a/x/ibc/core/04-channel/types/msgs.go +++ /dev/null @@ -1,652 +0,0 @@ -package types - -import ( - "encoding/base64" - - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" -) - -var _ sdk.Msg = &MsgChannelOpenInit{} - -// NewMsgChannelOpenInit creates a new MsgChannelOpenInit. It sets the counterparty channel -// identifier to be empty. -// nolint:interfacer -func NewMsgChannelOpenInit( - portID, version string, channelOrder Order, connectionHops []string, - counterpartyPortID string, signer sdk.AccAddress, -) *MsgChannelOpenInit { - counterparty := NewCounterparty(counterpartyPortID, "") - channel := NewChannel(INIT, channelOrder, counterparty, connectionHops, version) - return &MsgChannelOpenInit{ - PortId: portID, - Channel: channel, - Signer: signer.String(), - } -} - -// Route implements sdk.Msg -func (msg MsgChannelOpenInit) Route() string { - return host.RouterKey -} - -// Type implements sdk.Msg -func (msg MsgChannelOpenInit) Type() string { - return "channel_open_init" -} - -// ValidateBasic implements sdk.Msg -func (msg MsgChannelOpenInit) ValidateBasic() error { - if err := host.PortIdentifierValidator(msg.PortId); err != nil { - return sdkerrors.Wrap(err, "invalid port ID") - } - if msg.Channel.State != INIT { - return sdkerrors.Wrapf(ErrInvalidChannelState, - "channel state must be INIT in MsgChannelOpenInit. expected: %s, got: %s", - INIT, msg.Channel.State, - ) - } - if msg.Channel.Counterparty.ChannelId != "" { - return sdkerrors.Wrap(ErrInvalidCounterparty, "counterparty channel identifier must be empty") - } - _, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err) - } - return msg.Channel.ValidateBasic() -} - -// GetSignBytes implements sdk.Msg. The function will panic since it is used -// for amino transaction verification which IBC does not support. -func (msg MsgChannelOpenInit) GetSignBytes() []byte { - panic("IBC messages do not support amino") -} - -// GetSigners implements sdk.Msg -func (msg MsgChannelOpenInit) GetSigners() []sdk.AccAddress { - signer, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - panic(err) - } - return []sdk.AccAddress{signer} -} - -var _ sdk.Msg = &MsgChannelOpenTry{} - -// NewMsgChannelOpenTry creates a new MsgChannelOpenTry instance -// nolint:interfacer -func NewMsgChannelOpenTry( - portID, previousChannelID, version string, channelOrder Order, connectionHops []string, - counterpartyPortID, counterpartyChannelID, counterpartyVersion string, - proofInit []byte, proofHeight clienttypes.Height, signer sdk.AccAddress, -) *MsgChannelOpenTry { - counterparty := NewCounterparty(counterpartyPortID, counterpartyChannelID) - channel := NewChannel(TRYOPEN, channelOrder, counterparty, connectionHops, version) - return &MsgChannelOpenTry{ - PortId: portID, - PreviousChannelId: previousChannelID, - Channel: channel, - CounterpartyVersion: counterpartyVersion, - ProofInit: proofInit, - ProofHeight: proofHeight, - Signer: signer.String(), - } -} - -// Route implements sdk.Msg -func (msg MsgChannelOpenTry) Route() string { - return host.RouterKey -} - -// Type implements sdk.Msg -func (msg MsgChannelOpenTry) Type() string { - return "channel_open_try" -} - -// ValidateBasic implements sdk.Msg -func (msg MsgChannelOpenTry) ValidateBasic() error { - if err := host.PortIdentifierValidator(msg.PortId); err != nil { - return sdkerrors.Wrap(err, "invalid port ID") - } - if msg.PreviousChannelId != "" { - if !IsValidChannelID(msg.PreviousChannelId) { - return sdkerrors.Wrap(ErrInvalidChannelIdentifier, "invalid previous channel ID") - } - } - if len(msg.ProofInit) == 0 { - return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "cannot submit an empty proof init") - } - if msg.ProofHeight.IsZero() { - return sdkerrors.Wrap(sdkerrors.ErrInvalidHeight, "proof height must be non-zero") - } - if msg.Channel.State != TRYOPEN { - return sdkerrors.Wrapf(ErrInvalidChannelState, - "channel state must be TRYOPEN in MsgChannelOpenTry. expected: %s, got: %s", - TRYOPEN, msg.Channel.State, - ) - } - // counterparty validate basic allows empty counterparty channel identifiers - if err := host.ChannelIdentifierValidator(msg.Channel.Counterparty.ChannelId); err != nil { - return sdkerrors.Wrap(err, "invalid counterparty channel ID") - } - - _, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err) - } - return msg.Channel.ValidateBasic() -} - -// GetSignBytes implements sdk.Msg. The function will panic since it is used -// for amino transaction verification which IBC does not support. -func (msg MsgChannelOpenTry) GetSignBytes() []byte { - panic("IBC messages do not support amino") -} - -// GetSigners implements sdk.Msg -func (msg MsgChannelOpenTry) GetSigners() []sdk.AccAddress { - signer, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - panic(err) - } - return []sdk.AccAddress{signer} -} - -var _ sdk.Msg = &MsgChannelOpenAck{} - -// NewMsgChannelOpenAck creates a new MsgChannelOpenAck instance -// nolint:interfacer -func NewMsgChannelOpenAck( - portID, channelID, counterpartyChannelID string, cpv string, proofTry []byte, proofHeight clienttypes.Height, - signer sdk.AccAddress, -) *MsgChannelOpenAck { - return &MsgChannelOpenAck{ - PortId: portID, - ChannelId: channelID, - CounterpartyChannelId: counterpartyChannelID, - CounterpartyVersion: cpv, - ProofTry: proofTry, - ProofHeight: proofHeight, - Signer: signer.String(), - } -} - -// Route implements sdk.Msg -func (msg MsgChannelOpenAck) Route() string { - return host.RouterKey -} - -// Type implements sdk.Msg -func (msg MsgChannelOpenAck) Type() string { - return "channel_open_ack" -} - -// ValidateBasic implements sdk.Msg -func (msg MsgChannelOpenAck) ValidateBasic() error { - if err := host.PortIdentifierValidator(msg.PortId); err != nil { - return sdkerrors.Wrap(err, "invalid port ID") - } - if !IsValidChannelID(msg.ChannelId) { - return ErrInvalidChannelIdentifier - } - if err := host.ChannelIdentifierValidator(msg.CounterpartyChannelId); err != nil { - return sdkerrors.Wrap(err, "invalid counterparty channel ID") - } - if len(msg.ProofTry) == 0 { - return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "cannot submit an empty proof try") - } - if msg.ProofHeight.IsZero() { - return sdkerrors.Wrap(sdkerrors.ErrInvalidHeight, "proof height must be non-zero") - } - _, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err) - } - return nil -} - -// GetSignBytes implements sdk.Msg. The function will panic since it is used -// for amino transaction verification which IBC does not support. -func (msg MsgChannelOpenAck) GetSignBytes() []byte { - panic("IBC messages do not support amino") -} - -// GetSigners implements sdk.Msg -func (msg MsgChannelOpenAck) GetSigners() []sdk.AccAddress { - signer, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - panic(err) - } - return []sdk.AccAddress{signer} -} - -var _ sdk.Msg = &MsgChannelOpenConfirm{} - -// NewMsgChannelOpenConfirm creates a new MsgChannelOpenConfirm instance -// nolint:interfacer -func NewMsgChannelOpenConfirm( - portID, channelID string, proofAck []byte, proofHeight clienttypes.Height, - signer sdk.AccAddress, -) *MsgChannelOpenConfirm { - return &MsgChannelOpenConfirm{ - PortId: portID, - ChannelId: channelID, - ProofAck: proofAck, - ProofHeight: proofHeight, - Signer: signer.String(), - } -} - -// Route implements sdk.Msg -func (msg MsgChannelOpenConfirm) Route() string { - return host.RouterKey -} - -// Type implements sdk.Msg -func (msg MsgChannelOpenConfirm) Type() string { - return "channel_open_confirm" -} - -// ValidateBasic implements sdk.Msg -func (msg MsgChannelOpenConfirm) ValidateBasic() error { - if err := host.PortIdentifierValidator(msg.PortId); err != nil { - return sdkerrors.Wrap(err, "invalid port ID") - } - if !IsValidChannelID(msg.ChannelId) { - return ErrInvalidChannelIdentifier - } - if len(msg.ProofAck) == 0 { - return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "cannot submit an empty proof ack") - } - if msg.ProofHeight.IsZero() { - return sdkerrors.Wrap(sdkerrors.ErrInvalidHeight, "proof height must be non-zero") - } - _, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err) - } - return nil -} - -// GetSignBytes implements sdk.Msg. The function will panic since it is used -// for amino transaction verification which IBC does not support. -func (msg MsgChannelOpenConfirm) GetSignBytes() []byte { - panic("IBC messages do not support amino") -} - -// GetSigners implements sdk.Msg -func (msg MsgChannelOpenConfirm) GetSigners() []sdk.AccAddress { - signer, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - panic(err) - } - return []sdk.AccAddress{signer} -} - -var _ sdk.Msg = &MsgChannelCloseInit{} - -// NewMsgChannelCloseInit creates a new MsgChannelCloseInit instance -// nolint:interfacer -func NewMsgChannelCloseInit( - portID string, channelID string, signer sdk.AccAddress, -) *MsgChannelCloseInit { - return &MsgChannelCloseInit{ - PortId: portID, - ChannelId: channelID, - Signer: signer.String(), - } -} - -// Route implements sdk.Msg -func (msg MsgChannelCloseInit) Route() string { - return host.RouterKey -} - -// Type implements sdk.Msg -func (msg MsgChannelCloseInit) Type() string { - return "channel_close_init" -} - -// ValidateBasic implements sdk.Msg -func (msg MsgChannelCloseInit) ValidateBasic() error { - if err := host.PortIdentifierValidator(msg.PortId); err != nil { - return sdkerrors.Wrap(err, "invalid port ID") - } - if !IsValidChannelID(msg.ChannelId) { - return ErrInvalidChannelIdentifier - } - _, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err) - } - return nil -} - -// GetSignBytes implements sdk.Msg. The function will panic since it is used -// for amino transaction verification which IBC does not support. -func (msg MsgChannelCloseInit) GetSignBytes() []byte { - panic("IBC messages do not support amino") -} - -// GetSigners implements sdk.Msg -func (msg MsgChannelCloseInit) GetSigners() []sdk.AccAddress { - signer, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - panic(err) - } - return []sdk.AccAddress{signer} -} - -var _ sdk.Msg = &MsgChannelCloseConfirm{} - -// NewMsgChannelCloseConfirm creates a new MsgChannelCloseConfirm instance -// nolint:interfacer -func NewMsgChannelCloseConfirm( - portID, channelID string, proofInit []byte, proofHeight clienttypes.Height, - signer sdk.AccAddress, -) *MsgChannelCloseConfirm { - return &MsgChannelCloseConfirm{ - PortId: portID, - ChannelId: channelID, - ProofInit: proofInit, - ProofHeight: proofHeight, - Signer: signer.String(), - } -} - -// Route implements sdk.Msg -func (msg MsgChannelCloseConfirm) Route() string { - return host.RouterKey -} - -// Type implements sdk.Msg -func (msg MsgChannelCloseConfirm) Type() string { - return "channel_close_confirm" -} - -// ValidateBasic implements sdk.Msg -func (msg MsgChannelCloseConfirm) ValidateBasic() error { - if err := host.PortIdentifierValidator(msg.PortId); err != nil { - return sdkerrors.Wrap(err, "invalid port ID") - } - if !IsValidChannelID(msg.ChannelId) { - return ErrInvalidChannelIdentifier - } - if len(msg.ProofInit) == 0 { - return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "cannot submit an empty proof init") - } - if msg.ProofHeight.IsZero() { - return sdkerrors.Wrap(sdkerrors.ErrInvalidHeight, "proof height must be non-zero") - } - _, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err) - } - return nil -} - -// GetSignBytes implements sdk.Msg. The function will panic since it is used -// for amino transaction verification which IBC does not support. -func (msg MsgChannelCloseConfirm) GetSignBytes() []byte { - panic("IBC messages do not support amino") -} - -// GetSigners implements sdk.Msg -func (msg MsgChannelCloseConfirm) GetSigners() []sdk.AccAddress { - signer, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - panic(err) - } - return []sdk.AccAddress{signer} -} - -var _ sdk.Msg = &MsgRecvPacket{} - -// NewMsgRecvPacket constructs new MsgRecvPacket -// nolint:interfacer -func NewMsgRecvPacket( - packet Packet, proofCommitment []byte, proofHeight clienttypes.Height, - signer sdk.AccAddress, -) *MsgRecvPacket { - return &MsgRecvPacket{ - Packet: packet, - ProofCommitment: proofCommitment, - ProofHeight: proofHeight, - Signer: signer.String(), - } -} - -// Route implements sdk.Msg -func (msg MsgRecvPacket) Route() string { - return host.RouterKey -} - -// ValidateBasic implements sdk.Msg -func (msg MsgRecvPacket) ValidateBasic() error { - if len(msg.ProofCommitment) == 0 { - return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "cannot submit an empty proof") - } - if msg.ProofHeight.IsZero() { - return sdkerrors.Wrap(sdkerrors.ErrInvalidHeight, "proof height must be non-zero") - } - _, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err) - } - return msg.Packet.ValidateBasic() -} - -// GetSignBytes implements sdk.Msg. The function will panic since it is used -// for amino transaction verification which IBC does not support. -func (msg MsgRecvPacket) GetSignBytes() []byte { - panic("IBC messages do not support amino") -} - -// GetDataSignBytes returns the base64-encoded bytes used for the -// data field when signing the packet. -func (msg MsgRecvPacket) GetDataSignBytes() []byte { - s := "\"" + base64.StdEncoding.EncodeToString(msg.Packet.Data) + "\"" - return []byte(s) -} - -// GetSigners implements sdk.Msg -func (msg MsgRecvPacket) GetSigners() []sdk.AccAddress { - signer, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - panic(err) - } - return []sdk.AccAddress{signer} -} - -// Type implements sdk.Msg -func (msg MsgRecvPacket) Type() string { - return "recv_packet" -} - -var _ sdk.Msg = &MsgTimeout{} - -// NewMsgTimeout constructs new MsgTimeout -// nolint:interfacer -func NewMsgTimeout( - packet Packet, nextSequenceRecv uint64, proofUnreceived []byte, - proofHeight clienttypes.Height, signer sdk.AccAddress, -) *MsgTimeout { - return &MsgTimeout{ - Packet: packet, - NextSequenceRecv: nextSequenceRecv, - ProofUnreceived: proofUnreceived, - ProofHeight: proofHeight, - Signer: signer.String(), - } -} - -// Route implements sdk.Msg -func (msg MsgTimeout) Route() string { - return host.RouterKey -} - -// ValidateBasic implements sdk.Msg -func (msg MsgTimeout) ValidateBasic() error { - if len(msg.ProofUnreceived) == 0 { - return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "cannot submit an empty unreceived proof") - } - if msg.ProofHeight.IsZero() { - return sdkerrors.Wrap(sdkerrors.ErrInvalidHeight, "proof height must be non-zero") - } - if msg.NextSequenceRecv == 0 { - return sdkerrors.Wrap(sdkerrors.ErrInvalidSequence, "next sequence receive cannot be 0") - } - _, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err) - } - return msg.Packet.ValidateBasic() -} - -// GetSignBytes implements sdk.Msg. The function will panic since it is used -// for amino transaction verification which IBC does not support. -func (msg MsgTimeout) GetSignBytes() []byte { - panic("IBC messages do not support amino") -} - -// GetSigners implements sdk.Msg -func (msg MsgTimeout) GetSigners() []sdk.AccAddress { - signer, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - panic(err) - } - return []sdk.AccAddress{signer} -} - -// Type implements sdk.Msg -func (msg MsgTimeout) Type() string { - return "timeout_packet" -} - -// NewMsgTimeoutOnClose constructs new MsgTimeoutOnClose -// nolint:interfacer -func NewMsgTimeoutOnClose( - packet Packet, nextSequenceRecv uint64, - proofUnreceived, proofClose []byte, - proofHeight clienttypes.Height, signer sdk.AccAddress, -) *MsgTimeoutOnClose { - return &MsgTimeoutOnClose{ - Packet: packet, - NextSequenceRecv: nextSequenceRecv, - ProofUnreceived: proofUnreceived, - ProofClose: proofClose, - ProofHeight: proofHeight, - Signer: signer.String(), - } -} - -// Route implements sdk.Msg -func (msg MsgTimeoutOnClose) Route() string { - return host.RouterKey -} - -// ValidateBasic implements sdk.Msg -func (msg MsgTimeoutOnClose) ValidateBasic() error { - if msg.NextSequenceRecv == 0 { - return sdkerrors.Wrap(sdkerrors.ErrInvalidSequence, "next sequence receive cannot be 0") - } - if len(msg.ProofUnreceived) == 0 { - return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "cannot submit an empty proof") - } - if len(msg.ProofClose) == 0 { - return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "cannot submit an empty proof of closed counterparty channel end") - } - if msg.ProofHeight.IsZero() { - return sdkerrors.Wrap(sdkerrors.ErrInvalidHeight, "proof height must be non-zero") - } - _, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err) - } - return msg.Packet.ValidateBasic() -} - -// GetSignBytes implements sdk.Msg. The function will panic since it is used -// for amino transaction verification which IBC does not support. -func (msg MsgTimeoutOnClose) GetSignBytes() []byte { - panic("IBC messages do not support amino") -} - -// GetSigners implements sdk.Msg -func (msg MsgTimeoutOnClose) GetSigners() []sdk.AccAddress { - signer, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - panic(err) - } - return []sdk.AccAddress{signer} -} - -// Type implements sdk.Msg -func (msg MsgTimeoutOnClose) Type() string { - return "timeout_on_close_packet" -} - -var _ sdk.Msg = &MsgAcknowledgement{} - -// NewMsgAcknowledgement constructs a new MsgAcknowledgement -// nolint:interfacer -func NewMsgAcknowledgement( - packet Packet, - ack, proofAcked []byte, - proofHeight clienttypes.Height, - signer sdk.AccAddress, -) *MsgAcknowledgement { - return &MsgAcknowledgement{ - Packet: packet, - Acknowledgement: ack, - ProofAcked: proofAcked, - ProofHeight: proofHeight, - Signer: signer.String(), - } -} - -// Route implements sdk.Msg -func (msg MsgAcknowledgement) Route() string { - return host.RouterKey -} - -// ValidateBasic implements sdk.Msg -func (msg MsgAcknowledgement) ValidateBasic() error { - if len(msg.ProofAcked) == 0 { - return sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "cannot submit an empty proof") - } - if msg.ProofHeight.IsZero() { - return sdkerrors.Wrap(sdkerrors.ErrInvalidHeight, "proof height must be non-zero") - } - if len(msg.Acknowledgement) == 0 { - return sdkerrors.Wrap(ErrInvalidAcknowledgement, "ack bytes cannot be empty") - } - _, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err) - } - return msg.Packet.ValidateBasic() -} - -// GetSignBytes implements sdk.Msg. The function will panic since it is used -// for amino transaction verification which IBC does not support. -func (msg MsgAcknowledgement) GetSignBytes() []byte { - panic("IBC messages do not support amino") -} - -// GetSigners implements sdk.Msg -func (msg MsgAcknowledgement) GetSigners() []sdk.AccAddress { - signer, err := sdk.AccAddressFromBech32(msg.Signer) - if err != nil { - panic(err) - } - return []sdk.AccAddress{signer} -} - -// Type implements sdk.Msg -func (msg MsgAcknowledgement) Type() string { - return "acknowledge_packet" -} diff --git a/x/ibc/core/04-channel/types/msgs_test.go b/x/ibc/core/04-channel/types/msgs_test.go deleted file mode 100644 index 9c27fd69efa8..000000000000 --- a/x/ibc/core/04-channel/types/msgs_test.go +++ /dev/null @@ -1,446 +0,0 @@ -package types_test - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/suite" - - abci "github.com/tendermint/tendermint/abci/types" - dbm "github.com/tendermint/tm-db" - - "github.com/cosmos/cosmos-sdk/simapp" - "github.com/cosmos/cosmos-sdk/store/iavl" - "github.com/cosmos/cosmos-sdk/store/rootmulti" - storetypes "github.com/cosmos/cosmos-sdk/store/types" - sdk "github.com/cosmos/cosmos-sdk/types" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -const ( - // valid constatns used for testing - portid = "testportid" - chanid = "channel-0" - cpportid = "testcpport" - cpchanid = "testcpchannel" - - version = "1.0" - - // invalid constants used for testing - invalidPort = "(invalidport1)" - invalidShortPort = "p" - invalidLongPort = "invalidlongportinvalidlongportinvalidlongportidinvalidlongportidinvalid" - - invalidChannel = "(invalidchannel1)" - invalidShortChannel = "invalid" - invalidLongChannel = "invalidlongchannelinvalidlongchannelinvalidlongchannelinvalidlongchannel" - - invalidConnection = "(invalidconnection1)" - invalidShortConnection = "invalidcn" - invalidLongConnection = "invalidlongconnectioninvalidlongconnectioninvalidlongconnectioninvalid" -) - -// define variables used for testing -var ( - height = clienttypes.NewHeight(0, 1) - timeoutHeight = clienttypes.NewHeight(0, 100) - timeoutTimestamp = uint64(100) - disabledTimeout = clienttypes.ZeroHeight() - validPacketData = []byte("testdata") - unknownPacketData = []byte("unknown") - - packet = types.NewPacket(validPacketData, 1, portid, chanid, cpportid, cpchanid, timeoutHeight, timeoutTimestamp) - invalidPacket = types.NewPacket(unknownPacketData, 0, portid, chanid, cpportid, cpchanid, timeoutHeight, timeoutTimestamp) - - emptyProof = []byte{} - invalidProofs1 = exported.Proof(nil) - invalidProofs2 = emptyProof - - addr = sdk.AccAddress("testaddr111111111111") - emptyAddr sdk.AccAddress - - connHops = []string{"testconnection"} - invalidConnHops = []string{"testconnection", "testconnection"} - invalidShortConnHops = []string{invalidShortConnection} - invalidLongConnHops = []string{invalidLongConnection} -) - -type TypesTestSuite struct { - suite.Suite - - proof []byte -} - -func (suite *TypesTestSuite) SetupTest() { - app := simapp.Setup(false) - db := dbm.NewMemDB() - store := rootmulti.NewStore(db) - storeKey := storetypes.NewKVStoreKey("iavlStoreKey") - - store.MountStoreWithDB(storeKey, storetypes.StoreTypeIAVL, nil) - store.LoadVersion(0) - iavlStore := store.GetCommitStore(storeKey).(*iavl.Store) - - iavlStore.Set([]byte("KEY"), []byte("VALUE")) - _ = store.Commit() - - res := store.Query(abci.RequestQuery{ - Path: fmt.Sprintf("/%s/key", storeKey.Name()), // required path to get key/value+proof - Data: []byte("KEY"), - Prove: true, - }) - - merkleProof, err := commitmenttypes.ConvertProofs(res.ProofOps) - suite.Require().NoError(err) - proof, err := app.AppCodec().MarshalBinaryBare(&merkleProof) - suite.Require().NoError(err) - - suite.proof = proof -} - -func TestTypesTestSuite(t *testing.T) { - suite.Run(t, new(TypesTestSuite)) -} - -func (suite *TypesTestSuite) TestMsgChannelOpenInitValidateBasic() { - counterparty := types.NewCounterparty(cpportid, cpchanid) - tryOpenChannel := types.NewChannel(types.TRYOPEN, types.ORDERED, counterparty, connHops, version) - - testCases := []struct { - name string - msg *types.MsgChannelOpenInit - expPass bool - }{ - {"", types.NewMsgChannelOpenInit(portid, version, types.ORDERED, connHops, cpportid, addr), true}, - {"too short port id", types.NewMsgChannelOpenInit(invalidShortPort, version, types.ORDERED, connHops, cpportid, addr), false}, - {"too long port id", types.NewMsgChannelOpenInit(invalidLongPort, version, types.ORDERED, connHops, cpportid, addr), false}, - {"port id contains non-alpha", types.NewMsgChannelOpenInit(invalidPort, version, types.ORDERED, connHops, cpportid, addr), false}, - {"invalid channel order", types.NewMsgChannelOpenInit(portid, version, types.Order(3), connHops, cpportid, addr), false}, - {"connection hops more than 1 ", types.NewMsgChannelOpenInit(portid, version, types.ORDERED, invalidConnHops, cpportid, addr), false}, - {"too short connection id", types.NewMsgChannelOpenInit(portid, version, types.UNORDERED, invalidShortConnHops, cpportid, addr), false}, - {"too long connection id", types.NewMsgChannelOpenInit(portid, version, types.UNORDERED, invalidLongConnHops, cpportid, addr), false}, - {"connection id contains non-alpha", types.NewMsgChannelOpenInit(portid, version, types.UNORDERED, []string{invalidConnection}, cpportid, addr), false}, - {"", types.NewMsgChannelOpenInit(portid, "", types.UNORDERED, connHops, cpportid, addr), true}, - {"invalid counterparty port id", types.NewMsgChannelOpenInit(portid, version, types.UNORDERED, connHops, invalidPort, addr), false}, - {"channel not in INIT state", &types.MsgChannelOpenInit{portid, tryOpenChannel, addr.String()}, false}, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - err := tc.msg.ValidateBasic() - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} - -func (suite *TypesTestSuite) TestMsgChannelOpenTryValidateBasic() { - counterparty := types.NewCounterparty(cpportid, cpchanid) - initChannel := types.NewChannel(types.INIT, types.ORDERED, counterparty, connHops, version) - - testCases := []struct { - name string - msg *types.MsgChannelOpenTry - expPass bool - }{ - {"", types.NewMsgChannelOpenTry(portid, chanid, version, types.ORDERED, connHops, cpportid, cpchanid, version, suite.proof, height, addr), true}, - {"too short port id", types.NewMsgChannelOpenTry(invalidShortPort, chanid, version, types.ORDERED, connHops, cpportid, cpchanid, version, suite.proof, height, addr), false}, - {"too long port id", types.NewMsgChannelOpenTry(invalidLongPort, chanid, version, types.ORDERED, connHops, cpportid, cpchanid, version, suite.proof, height, addr), false}, - {"port id contains non-alpha", types.NewMsgChannelOpenTry(invalidPort, chanid, version, types.ORDERED, connHops, cpportid, cpchanid, version, suite.proof, height, addr), false}, - {"too short channel id", types.NewMsgChannelOpenTry(portid, invalidShortChannel, version, types.ORDERED, connHops, cpportid, cpchanid, version, suite.proof, height, addr), false}, - {"too long channel id", types.NewMsgChannelOpenTry(portid, invalidLongChannel, version, types.ORDERED, connHops, cpportid, cpchanid, version, suite.proof, height, addr), false}, - {"channel id contains non-alpha", types.NewMsgChannelOpenTry(portid, invalidChannel, version, types.ORDERED, connHops, cpportid, cpchanid, version, suite.proof, height, addr), false}, - {"", types.NewMsgChannelOpenTry(portid, chanid, version, types.ORDERED, connHops, cpportid, cpchanid, "", suite.proof, height, addr), true}, - {"proof height is zero", types.NewMsgChannelOpenTry(portid, chanid, version, types.ORDERED, connHops, cpportid, cpchanid, version, suite.proof, clienttypes.ZeroHeight(), addr), false}, - {"invalid channel order", types.NewMsgChannelOpenTry(portid, chanid, version, types.Order(4), connHops, cpportid, cpchanid, version, suite.proof, height, addr), false}, - {"connection hops more than 1 ", types.NewMsgChannelOpenTry(portid, chanid, version, types.UNORDERED, invalidConnHops, cpportid, cpchanid, version, suite.proof, height, addr), false}, - {"too short connection id", types.NewMsgChannelOpenTry(portid, chanid, version, types.UNORDERED, invalidShortConnHops, cpportid, cpchanid, version, suite.proof, height, addr), false}, - {"too long connection id", types.NewMsgChannelOpenTry(portid, chanid, version, types.UNORDERED, invalidLongConnHops, cpportid, cpchanid, version, suite.proof, height, addr), false}, - {"connection id contains non-alpha", types.NewMsgChannelOpenTry(portid, chanid, version, types.UNORDERED, []string{invalidConnection}, cpportid, cpchanid, version, suite.proof, height, addr), false}, - {"", types.NewMsgChannelOpenTry(portid, chanid, "", types.UNORDERED, connHops, cpportid, cpchanid, version, suite.proof, height, addr), true}, - {"invalid counterparty port id", types.NewMsgChannelOpenTry(portid, chanid, version, types.UNORDERED, connHops, invalidPort, cpchanid, version, suite.proof, height, addr), false}, - {"invalid counterparty channel id", types.NewMsgChannelOpenTry(portid, chanid, version, types.UNORDERED, connHops, cpportid, invalidChannel, version, suite.proof, height, addr), false}, - {"empty proof", types.NewMsgChannelOpenTry(portid, chanid, version, types.UNORDERED, connHops, cpportid, cpchanid, version, emptyProof, height, addr), false}, - {"channel not in TRYOPEN state", &types.MsgChannelOpenTry{portid, chanid, initChannel, version, suite.proof, height, addr.String()}, false}, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - err := tc.msg.ValidateBasic() - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} - -func (suite *TypesTestSuite) TestMsgChannelOpenAckValidateBasic() { - testCases := []struct { - name string - msg *types.MsgChannelOpenAck - expPass bool - }{ - {"", types.NewMsgChannelOpenAck(portid, chanid, chanid, version, suite.proof, height, addr), true}, - {"too short port id", types.NewMsgChannelOpenAck(invalidShortPort, chanid, chanid, version, suite.proof, height, addr), false}, - {"too long port id", types.NewMsgChannelOpenAck(invalidLongPort, chanid, chanid, version, suite.proof, height, addr), false}, - {"port id contains non-alpha", types.NewMsgChannelOpenAck(invalidPort, chanid, chanid, version, suite.proof, height, addr), false}, - {"too short channel id", types.NewMsgChannelOpenAck(portid, invalidShortChannel, chanid, version, suite.proof, height, addr), false}, - {"too long channel id", types.NewMsgChannelOpenAck(portid, invalidLongChannel, chanid, version, suite.proof, height, addr), false}, - {"channel id contains non-alpha", types.NewMsgChannelOpenAck(portid, invalidChannel, chanid, version, suite.proof, height, addr), false}, - {"", types.NewMsgChannelOpenAck(portid, chanid, chanid, "", suite.proof, height, addr), true}, - {"empty proof", types.NewMsgChannelOpenAck(portid, chanid, chanid, version, emptyProof, height, addr), false}, - {"proof height is zero", types.NewMsgChannelOpenAck(portid, chanid, chanid, version, suite.proof, clienttypes.ZeroHeight(), addr), false}, - {"invalid counterparty channel id", types.NewMsgChannelOpenAck(portid, chanid, invalidShortChannel, version, suite.proof, height, addr), false}, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - err := tc.msg.ValidateBasic() - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} - -func (suite *TypesTestSuite) TestMsgChannelOpenConfirmValidateBasic() { - testCases := []struct { - name string - msg *types.MsgChannelOpenConfirm - expPass bool - }{ - {"", types.NewMsgChannelOpenConfirm(portid, chanid, suite.proof, height, addr), true}, - {"too short port id", types.NewMsgChannelOpenConfirm(invalidShortPort, chanid, suite.proof, height, addr), false}, - {"too long port id", types.NewMsgChannelOpenConfirm(invalidLongPort, chanid, suite.proof, height, addr), false}, - {"port id contains non-alpha", types.NewMsgChannelOpenConfirm(invalidPort, chanid, suite.proof, height, addr), false}, - {"too short channel id", types.NewMsgChannelOpenConfirm(portid, invalidShortChannel, suite.proof, height, addr), false}, - {"too long channel id", types.NewMsgChannelOpenConfirm(portid, invalidLongChannel, suite.proof, height, addr), false}, - {"channel id contains non-alpha", types.NewMsgChannelOpenConfirm(portid, invalidChannel, suite.proof, height, addr), false}, - {"empty proof", types.NewMsgChannelOpenConfirm(portid, chanid, emptyProof, height, addr), false}, - {"proof height is zero", types.NewMsgChannelOpenConfirm(portid, chanid, suite.proof, clienttypes.ZeroHeight(), addr), false}, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - err := tc.msg.ValidateBasic() - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} - -func (suite *TypesTestSuite) TestMsgChannelCloseInitValidateBasic() { - testCases := []struct { - name string - msg *types.MsgChannelCloseInit - expPass bool - }{ - {"", types.NewMsgChannelCloseInit(portid, chanid, addr), true}, - {"too short port id", types.NewMsgChannelCloseInit(invalidShortPort, chanid, addr), false}, - {"too long port id", types.NewMsgChannelCloseInit(invalidLongPort, chanid, addr), false}, - {"port id contains non-alpha", types.NewMsgChannelCloseInit(invalidPort, chanid, addr), false}, - {"too short channel id", types.NewMsgChannelCloseInit(portid, invalidShortChannel, addr), false}, - {"too long channel id", types.NewMsgChannelCloseInit(portid, invalidLongChannel, addr), false}, - {"channel id contains non-alpha", types.NewMsgChannelCloseInit(portid, invalidChannel, addr), false}, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - err := tc.msg.ValidateBasic() - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} - -func (suite *TypesTestSuite) TestMsgChannelCloseConfirmValidateBasic() { - testCases := []struct { - name string - msg *types.MsgChannelCloseConfirm - expPass bool - }{ - {"", types.NewMsgChannelCloseConfirm(portid, chanid, suite.proof, height, addr), true}, - {"too short port id", types.NewMsgChannelCloseConfirm(invalidShortPort, chanid, suite.proof, height, addr), false}, - {"too long port id", types.NewMsgChannelCloseConfirm(invalidLongPort, chanid, suite.proof, height, addr), false}, - {"port id contains non-alpha", types.NewMsgChannelCloseConfirm(invalidPort, chanid, suite.proof, height, addr), false}, - {"too short channel id", types.NewMsgChannelCloseConfirm(portid, invalidShortChannel, suite.proof, height, addr), false}, - {"too long channel id", types.NewMsgChannelCloseConfirm(portid, invalidLongChannel, suite.proof, height, addr), false}, - {"channel id contains non-alpha", types.NewMsgChannelCloseConfirm(portid, invalidChannel, suite.proof, height, addr), false}, - {"empty proof", types.NewMsgChannelCloseConfirm(portid, chanid, emptyProof, height, addr), false}, - {"proof height is zero", types.NewMsgChannelCloseConfirm(portid, chanid, suite.proof, clienttypes.ZeroHeight(), addr), false}, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - err := tc.msg.ValidateBasic() - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} - -func (suite *TypesTestSuite) TestMsgRecvPacketType() { - msg := types.NewMsgRecvPacket(packet, suite.proof, height, addr) - - suite.Equal("recv_packet", msg.Type()) -} - -func (suite *TypesTestSuite) TestMsgRecvPacketValidateBasic() { - testCases := []struct { - name string - msg *types.MsgRecvPacket - expPass bool - }{ - {"success", types.NewMsgRecvPacket(packet, suite.proof, height, addr), true}, - {"proof height is zero", types.NewMsgRecvPacket(packet, suite.proof, clienttypes.ZeroHeight(), addr), false}, - {"proof contain empty proof", types.NewMsgRecvPacket(packet, emptyProof, height, addr), false}, - {"missing signer address", types.NewMsgRecvPacket(packet, suite.proof, height, emptyAddr), false}, - {"invalid packet", types.NewMsgRecvPacket(invalidPacket, suite.proof, height, addr), false}, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - err := tc.msg.ValidateBasic() - - if tc.expPass { - suite.NoError(err) - } else { - suite.Error(err) - } - }) - } -} - -func (suite *TypesTestSuite) TestMsgRecvPacketGetSigners() { - msg := types.NewMsgRecvPacket(packet, suite.proof, height, addr) - res := msg.GetSigners() - - expected := "[7465737461646472313131313131313131313131]" - suite.Equal(expected, fmt.Sprintf("%v", res)) -} - -func (suite *TypesTestSuite) TestMsgTimeoutValidateBasic() { - testCases := []struct { - name string - msg *types.MsgTimeout - expPass bool - }{ - {"success", types.NewMsgTimeout(packet, 1, suite.proof, height, addr), true}, - {"proof height must be > 0", types.NewMsgTimeout(packet, 1, suite.proof, clienttypes.ZeroHeight(), addr), false}, - {"seq 0", types.NewMsgTimeout(packet, 0, suite.proof, height, addr), false}, - {"missing signer address", types.NewMsgTimeout(packet, 1, suite.proof, height, emptyAddr), false}, - {"cannot submit an empty proof", types.NewMsgTimeout(packet, 1, emptyProof, height, addr), false}, - {"invalid packet", types.NewMsgTimeout(invalidPacket, 1, suite.proof, height, addr), false}, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - err := tc.msg.ValidateBasic() - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} - -func (suite *TypesTestSuite) TestMsgTimeoutOnCloseValidateBasic() { - testCases := []struct { - name string - msg sdk.Msg - expPass bool - }{ - {"success", types.NewMsgTimeoutOnClose(packet, 1, suite.proof, suite.proof, height, addr), true}, - {"seq 0", types.NewMsgTimeoutOnClose(packet, 0, suite.proof, suite.proof, height, addr), false}, - {"empty proof", types.NewMsgTimeoutOnClose(packet, 1, emptyProof, suite.proof, height, addr), false}, - {"empty proof close", types.NewMsgTimeoutOnClose(packet, 1, suite.proof, emptyProof, height, addr), false}, - {"proof height is zero", types.NewMsgTimeoutOnClose(packet, 1, suite.proof, suite.proof, clienttypes.ZeroHeight(), addr), false}, - {"signer address is empty", types.NewMsgTimeoutOnClose(packet, 1, suite.proof, suite.proof, height, emptyAddr), false}, - {"invalid packet", types.NewMsgTimeoutOnClose(invalidPacket, 1, suite.proof, suite.proof, height, addr), false}, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - err := tc.msg.ValidateBasic() - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} - -func (suite *TypesTestSuite) TestMsgAcknowledgementValidateBasic() { - testCases := []struct { - name string - msg *types.MsgAcknowledgement - expPass bool - }{ - {"success", types.NewMsgAcknowledgement(packet, packet.GetData(), suite.proof, height, addr), true}, - {"proof height must be > 0", types.NewMsgAcknowledgement(packet, packet.GetData(), suite.proof, clienttypes.ZeroHeight(), addr), false}, - {"empty ack", types.NewMsgAcknowledgement(packet, nil, suite.proof, height, addr), false}, - {"missing signer address", types.NewMsgAcknowledgement(packet, packet.GetData(), suite.proof, height, emptyAddr), false}, - {"cannot submit an empty proof", types.NewMsgAcknowledgement(packet, packet.GetData(), emptyProof, height, addr), false}, - {"invalid packet", types.NewMsgAcknowledgement(invalidPacket, packet.GetData(), suite.proof, height, addr), false}, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - err := tc.msg.ValidateBasic() - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} diff --git a/x/ibc/core/04-channel/types/packet.go b/x/ibc/core/04-channel/types/packet.go deleted file mode 100644 index b5c8d180438c..000000000000 --- a/x/ibc/core/04-channel/types/packet.go +++ /dev/null @@ -1,112 +0,0 @@ -package types - -import ( - "crypto/sha256" - - "github.com/cosmos/cosmos-sdk/codec" - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -// CommitPacket returns the packet commitment bytes. The commitment consists of: -// sha256_hash(timeout_timestamp + timeout_height.RevisionNumber + timeout_height.RevisionHeight + sha256_hash(data)) -// from a given packet. This results in a fixed length preimage. -// NOTE: sdk.Uint64ToBigEndian sets the uint64 to a slice of length 8. -func CommitPacket(cdc codec.BinaryMarshaler, packet exported.PacketI) []byte { - timeoutHeight := packet.GetTimeoutHeight() - - buf := sdk.Uint64ToBigEndian(packet.GetTimeoutTimestamp()) - - revisionNumber := sdk.Uint64ToBigEndian(timeoutHeight.GetRevisionNumber()) - buf = append(buf, revisionNumber...) - - revisionHeight := sdk.Uint64ToBigEndian(timeoutHeight.GetRevisionHeight()) - buf = append(buf, revisionHeight...) - - dataHash := sha256.Sum256(packet.GetData()) - buf = append(buf, dataHash[:]...) - - hash := sha256.Sum256(buf) - return hash[:] -} - -// CommitAcknowledgement returns the hash of commitment bytes -func CommitAcknowledgement(data []byte) []byte { - hash := sha256.Sum256(data) - return hash[:] -} - -var _ exported.PacketI = (*Packet)(nil) - -// NewPacket creates a new Packet instance. It panics if the provided -// packet data interface is not registered. -func NewPacket( - data []byte, - sequence uint64, sourcePort, sourceChannel, - destinationPort, destinationChannel string, - timeoutHeight clienttypes.Height, timeoutTimestamp uint64, -) Packet { - return Packet{ - Data: data, - Sequence: sequence, - SourcePort: sourcePort, - SourceChannel: sourceChannel, - DestinationPort: destinationPort, - DestinationChannel: destinationChannel, - TimeoutHeight: timeoutHeight, - TimeoutTimestamp: timeoutTimestamp, - } -} - -// GetSequence implements PacketI interface -func (p Packet) GetSequence() uint64 { return p.Sequence } - -// GetSourcePort implements PacketI interface -func (p Packet) GetSourcePort() string { return p.SourcePort } - -// GetSourceChannel implements PacketI interface -func (p Packet) GetSourceChannel() string { return p.SourceChannel } - -// GetDestPort implements PacketI interface -func (p Packet) GetDestPort() string { return p.DestinationPort } - -// GetDestChannel implements PacketI interface -func (p Packet) GetDestChannel() string { return p.DestinationChannel } - -// GetData implements PacketI interface -func (p Packet) GetData() []byte { return p.Data } - -// GetTimeoutHeight implements PacketI interface -func (p Packet) GetTimeoutHeight() exported.Height { return p.TimeoutHeight } - -// GetTimeoutTimestamp implements PacketI interface -func (p Packet) GetTimeoutTimestamp() uint64 { return p.TimeoutTimestamp } - -// ValidateBasic implements PacketI interface -func (p Packet) ValidateBasic() error { - if err := host.PortIdentifierValidator(p.SourcePort); err != nil { - return sdkerrors.Wrap(err, "invalid source port ID") - } - if err := host.PortIdentifierValidator(p.DestinationPort); err != nil { - return sdkerrors.Wrap(err, "invalid destination port ID") - } - if err := host.ChannelIdentifierValidator(p.SourceChannel); err != nil { - return sdkerrors.Wrap(err, "invalid source channel ID") - } - if err := host.ChannelIdentifierValidator(p.DestinationChannel); err != nil { - return sdkerrors.Wrap(err, "invalid destination channel ID") - } - if p.Sequence == 0 { - return sdkerrors.Wrap(ErrInvalidPacket, "packet sequence cannot be 0") - } - if p.TimeoutHeight.IsZero() && p.TimeoutTimestamp == 0 { - return sdkerrors.Wrap(ErrInvalidPacket, "packet timeout height and packet timeout timestamp cannot both be 0") - } - if len(p.Data) == 0 { - return sdkerrors.Wrap(ErrInvalidPacket, "packet data bytes cannot be empty") - } - return nil -} diff --git a/x/ibc/core/04-channel/types/packet_test.go b/x/ibc/core/04-channel/types/packet_test.go deleted file mode 100644 index 12ed828e665f..000000000000 --- a/x/ibc/core/04-channel/types/packet_test.go +++ /dev/null @@ -1,53 +0,0 @@ -package types_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/codec" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" -) - -func TestCommitPacket(t *testing.T) { - packet := types.NewPacket(validPacketData, 1, portid, chanid, cpportid, cpchanid, timeoutHeight, timeoutTimestamp) - - registry := codectypes.NewInterfaceRegistry() - clienttypes.RegisterInterfaces(registry) - types.RegisterInterfaces(registry) - - cdc := codec.NewProtoCodec(registry) - - commitment := types.CommitPacket(cdc, &packet) - require.NotNil(t, commitment) -} - -func TestPacketValidateBasic(t *testing.T) { - testCases := []struct { - packet types.Packet - expPass bool - errMsg string - }{ - {types.NewPacket(validPacketData, 1, portid, chanid, cpportid, cpchanid, timeoutHeight, timeoutTimestamp), true, ""}, - {types.NewPacket(validPacketData, 0, portid, chanid, cpportid, cpchanid, timeoutHeight, timeoutTimestamp), false, "invalid sequence"}, - {types.NewPacket(validPacketData, 1, invalidPort, chanid, cpportid, cpchanid, timeoutHeight, timeoutTimestamp), false, "invalid source port"}, - {types.NewPacket(validPacketData, 1, portid, invalidChannel, cpportid, cpchanid, timeoutHeight, timeoutTimestamp), false, "invalid source channel"}, - {types.NewPacket(validPacketData, 1, portid, chanid, invalidPort, cpchanid, timeoutHeight, timeoutTimestamp), false, "invalid destination port"}, - {types.NewPacket(validPacketData, 1, portid, chanid, cpportid, invalidChannel, timeoutHeight, timeoutTimestamp), false, "invalid destination channel"}, - {types.NewPacket(validPacketData, 1, portid, chanid, cpportid, cpchanid, disabledTimeout, 0), false, "disabled both timeout height and timestamp"}, - {types.NewPacket(validPacketData, 1, portid, chanid, cpportid, cpchanid, disabledTimeout, timeoutTimestamp), true, "disabled timeout height, valid timeout timestamp"}, - {types.NewPacket(validPacketData, 1, portid, chanid, cpportid, cpchanid, timeoutHeight, 0), true, "disabled timeout timestamp, valid timeout height"}, - {types.NewPacket(unknownPacketData, 1, portid, chanid, cpportid, cpchanid, timeoutHeight, timeoutTimestamp), true, ""}, - } - - for i, tc := range testCases { - err := tc.packet.ValidateBasic() - if tc.expPass { - require.NoError(t, err, "Msg %d failed: %s", i, tc.errMsg) - } else { - require.Error(t, err, "Invalid Msg %d passed: %s", i, tc.errMsg) - } - } -} diff --git a/x/ibc/core/04-channel/types/query.go b/x/ibc/core/04-channel/types/query.go deleted file mode 100644 index d1536dfc0565..000000000000 --- a/x/ibc/core/04-channel/types/query.go +++ /dev/null @@ -1,94 +0,0 @@ -package types - -import ( - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - "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{ - Channel: &channel, - Proof: proof, - ProofHeight: height, - } -} - -// NewQueryChannelClientStateResponse creates a newQueryChannelClientStateResponse instance -func NewQueryChannelClientStateResponse(identifiedClientState clienttypes.IdentifiedClientState, proof []byte, height clienttypes.Height) *QueryChannelClientStateResponse { - return &QueryChannelClientStateResponse{ - IdentifiedClientState: &identifiedClientState, - Proof: proof, - ProofHeight: height, - } -} - -// 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{ - ConsensusState: anyConsensusState, - ClientId: clientID, - Proof: proof, - ProofHeight: height, - } -} - -// 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, -) *QueryPacketCommitmentResponse { - return &QueryPacketCommitmentResponse{ - Commitment: commitment, - Proof: proof, - ProofHeight: height, - } -} - -// NewQueryPacketReceiptResponse creates a new QueryPacketReceiptResponse instance -func NewQueryPacketReceiptResponse( - recvd bool, proof []byte, height clienttypes.Height, -) *QueryPacketReceiptResponse { - return &QueryPacketReceiptResponse{ - Received: recvd, - Proof: proof, - ProofHeight: height, - } -} - -// NewQueryPacketAcknowledgementResponse creates a new QueryPacketAcknowledgementResponse instance -func NewQueryPacketAcknowledgementResponse( - acknowledgement []byte, proof []byte, height clienttypes.Height, -) *QueryPacketAcknowledgementResponse { - return &QueryPacketAcknowledgementResponse{ - Acknowledgement: acknowledgement, - Proof: proof, - ProofHeight: height, - } -} - -// NewQueryNextSequenceReceiveResponse creates a new QueryNextSequenceReceiveResponse instance -func NewQueryNextSequenceReceiveResponse( - sequence uint64, proof []byte, height clienttypes.Height, -) *QueryNextSequenceReceiveResponse { - return &QueryNextSequenceReceiveResponse{ - NextSequenceReceive: sequence, - Proof: proof, - ProofHeight: height, - } -} diff --git a/x/ibc/core/04-channel/types/query.pb.go b/x/ibc/core/04-channel/types/query.pb.go deleted file mode 100644 index c5cbd6e8f899..000000000000 --- a/x/ibc/core/04-channel/types/query.pb.go +++ /dev/null @@ -1,7991 +0,0 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: ibc/core/channel/v1/query.proto - -package types - -import ( - context "context" - fmt "fmt" - types1 "github.com/cosmos/cosmos-sdk/codec/types" - query "github.com/cosmos/cosmos-sdk/types/query" - types "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - _ "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 - -// QueryChannelRequest is the request type for the Query/Channel RPC method -type QueryChannelRequest struct { - // port unique identifier - PortId string `protobuf:"bytes,1,opt,name=port_id,json=portId,proto3" json:"port_id,omitempty"` - // channel unique identifier - ChannelId string `protobuf:"bytes,2,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty"` -} - -func (m *QueryChannelRequest) Reset() { *m = QueryChannelRequest{} } -func (m *QueryChannelRequest) String() string { return proto.CompactTextString(m) } -func (*QueryChannelRequest) ProtoMessage() {} -func (*QueryChannelRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_1034a1e9abc4cca1, []int{0} -} -func (m *QueryChannelRequest) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryChannelRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryChannelRequest.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 *QueryChannelRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryChannelRequest.Merge(m, src) -} -func (m *QueryChannelRequest) XXX_Size() int { - return m.Size() -} -func (m *QueryChannelRequest) XXX_DiscardUnknown() { - xxx_messageInfo_QueryChannelRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryChannelRequest proto.InternalMessageInfo - -func (m *QueryChannelRequest) GetPortId() string { - if m != nil { - return m.PortId - } - return "" -} - -func (m *QueryChannelRequest) GetChannelId() string { - if m != nil { - return m.ChannelId - } - return "" -} - -// 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. -type QueryChannelResponse struct { - // channel associated with the request identifiers - Channel *Channel `protobuf:"bytes,1,opt,name=channel,proto3" json:"channel,omitempty"` - // merkle proof of existence - Proof []byte `protobuf:"bytes,2,opt,name=proof,proto3" json:"proof,omitempty"` - // height at which the proof was retrieved - ProofHeight types.Height `protobuf:"bytes,3,opt,name=proof_height,json=proofHeight,proto3" json:"proof_height"` -} - -func (m *QueryChannelResponse) Reset() { *m = QueryChannelResponse{} } -func (m *QueryChannelResponse) String() string { return proto.CompactTextString(m) } -func (*QueryChannelResponse) ProtoMessage() {} -func (*QueryChannelResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_1034a1e9abc4cca1, []int{1} -} -func (m *QueryChannelResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryChannelResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryChannelResponse.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 *QueryChannelResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryChannelResponse.Merge(m, src) -} -func (m *QueryChannelResponse) XXX_Size() int { - return m.Size() -} -func (m *QueryChannelResponse) XXX_DiscardUnknown() { - xxx_messageInfo_QueryChannelResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryChannelResponse proto.InternalMessageInfo - -func (m *QueryChannelResponse) GetChannel() *Channel { - if m != nil { - return m.Channel - } - return nil -} - -func (m *QueryChannelResponse) GetProof() []byte { - if m != nil { - return m.Proof - } - return nil -} - -func (m *QueryChannelResponse) GetProofHeight() types.Height { - if m != nil { - return m.ProofHeight - } - return types.Height{} -} - -// QueryChannelsRequest is the request type for the Query/Channels RPC method -type QueryChannelsRequest struct { - // pagination request - Pagination *query.PageRequest `protobuf:"bytes,1,opt,name=pagination,proto3" json:"pagination,omitempty"` -} - -func (m *QueryChannelsRequest) Reset() { *m = QueryChannelsRequest{} } -func (m *QueryChannelsRequest) String() string { return proto.CompactTextString(m) } -func (*QueryChannelsRequest) ProtoMessage() {} -func (*QueryChannelsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_1034a1e9abc4cca1, []int{2} -} -func (m *QueryChannelsRequest) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryChannelsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryChannelsRequest.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 *QueryChannelsRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryChannelsRequest.Merge(m, src) -} -func (m *QueryChannelsRequest) XXX_Size() int { - return m.Size() -} -func (m *QueryChannelsRequest) XXX_DiscardUnknown() { - xxx_messageInfo_QueryChannelsRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryChannelsRequest proto.InternalMessageInfo - -func (m *QueryChannelsRequest) GetPagination() *query.PageRequest { - if m != nil { - return m.Pagination - } - return nil -} - -// QueryChannelsResponse is the response type for the Query/Channels RPC method. -type QueryChannelsResponse struct { - // list of stored channels of the chain. - Channels []*IdentifiedChannel `protobuf:"bytes,1,rep,name=channels,proto3" json:"channels,omitempty"` - // pagination response - Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` - // query block height - Height types.Height `protobuf:"bytes,3,opt,name=height,proto3" json:"height"` -} - -func (m *QueryChannelsResponse) Reset() { *m = QueryChannelsResponse{} } -func (m *QueryChannelsResponse) String() string { return proto.CompactTextString(m) } -func (*QueryChannelsResponse) ProtoMessage() {} -func (*QueryChannelsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_1034a1e9abc4cca1, []int{3} -} -func (m *QueryChannelsResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryChannelsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryChannelsResponse.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 *QueryChannelsResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryChannelsResponse.Merge(m, src) -} -func (m *QueryChannelsResponse) XXX_Size() int { - return m.Size() -} -func (m *QueryChannelsResponse) XXX_DiscardUnknown() { - xxx_messageInfo_QueryChannelsResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryChannelsResponse proto.InternalMessageInfo - -func (m *QueryChannelsResponse) GetChannels() []*IdentifiedChannel { - if m != nil { - return m.Channels - } - return nil -} - -func (m *QueryChannelsResponse) GetPagination() *query.PageResponse { - if m != nil { - return m.Pagination - } - return nil -} - -func (m *QueryChannelsResponse) GetHeight() types.Height { - if m != nil { - return m.Height - } - return types.Height{} -} - -// QueryConnectionChannelsRequest is the request type for the -// Query/QueryConnectionChannels RPC method -type QueryConnectionChannelsRequest struct { - // connection unique identifier - Connection string `protobuf:"bytes,1,opt,name=connection,proto3" json:"connection,omitempty"` - // pagination request - Pagination *query.PageRequest `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` -} - -func (m *QueryConnectionChannelsRequest) Reset() { *m = QueryConnectionChannelsRequest{} } -func (m *QueryConnectionChannelsRequest) String() string { return proto.CompactTextString(m) } -func (*QueryConnectionChannelsRequest) ProtoMessage() {} -func (*QueryConnectionChannelsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_1034a1e9abc4cca1, []int{4} -} -func (m *QueryConnectionChannelsRequest) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryConnectionChannelsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryConnectionChannelsRequest.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 *QueryConnectionChannelsRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryConnectionChannelsRequest.Merge(m, src) -} -func (m *QueryConnectionChannelsRequest) XXX_Size() int { - return m.Size() -} -func (m *QueryConnectionChannelsRequest) XXX_DiscardUnknown() { - xxx_messageInfo_QueryConnectionChannelsRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryConnectionChannelsRequest proto.InternalMessageInfo - -func (m *QueryConnectionChannelsRequest) GetConnection() string { - if m != nil { - return m.Connection - } - return "" -} - -func (m *QueryConnectionChannelsRequest) GetPagination() *query.PageRequest { - if m != nil { - return m.Pagination - } - return nil -} - -// QueryConnectionChannelsResponse is the Response type for the -// Query/QueryConnectionChannels RPC method -type QueryConnectionChannelsResponse struct { - // list of channels associated with a connection. - Channels []*IdentifiedChannel `protobuf:"bytes,1,rep,name=channels,proto3" json:"channels,omitempty"` - // pagination response - Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` - // query block height - Height types.Height `protobuf:"bytes,3,opt,name=height,proto3" json:"height"` -} - -func (m *QueryConnectionChannelsResponse) Reset() { *m = QueryConnectionChannelsResponse{} } -func (m *QueryConnectionChannelsResponse) String() string { return proto.CompactTextString(m) } -func (*QueryConnectionChannelsResponse) ProtoMessage() {} -func (*QueryConnectionChannelsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_1034a1e9abc4cca1, []int{5} -} -func (m *QueryConnectionChannelsResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryConnectionChannelsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryConnectionChannelsResponse.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 *QueryConnectionChannelsResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryConnectionChannelsResponse.Merge(m, src) -} -func (m *QueryConnectionChannelsResponse) XXX_Size() int { - return m.Size() -} -func (m *QueryConnectionChannelsResponse) XXX_DiscardUnknown() { - xxx_messageInfo_QueryConnectionChannelsResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryConnectionChannelsResponse proto.InternalMessageInfo - -func (m *QueryConnectionChannelsResponse) GetChannels() []*IdentifiedChannel { - if m != nil { - return m.Channels - } - return nil -} - -func (m *QueryConnectionChannelsResponse) GetPagination() *query.PageResponse { - if m != nil { - return m.Pagination - } - return nil -} - -func (m *QueryConnectionChannelsResponse) GetHeight() types.Height { - if m != nil { - return m.Height - } - return types.Height{} -} - -// QueryChannelClientStateRequest is the request type for the Query/ClientState -// RPC method -type QueryChannelClientStateRequest struct { - // port unique identifier - PortId string `protobuf:"bytes,1,opt,name=port_id,json=portId,proto3" json:"port_id,omitempty"` - // channel unique identifier - ChannelId string `protobuf:"bytes,2,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty"` -} - -func (m *QueryChannelClientStateRequest) Reset() { *m = QueryChannelClientStateRequest{} } -func (m *QueryChannelClientStateRequest) String() string { return proto.CompactTextString(m) } -func (*QueryChannelClientStateRequest) ProtoMessage() {} -func (*QueryChannelClientStateRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_1034a1e9abc4cca1, []int{6} -} -func (m *QueryChannelClientStateRequest) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryChannelClientStateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryChannelClientStateRequest.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 *QueryChannelClientStateRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryChannelClientStateRequest.Merge(m, src) -} -func (m *QueryChannelClientStateRequest) XXX_Size() int { - return m.Size() -} -func (m *QueryChannelClientStateRequest) XXX_DiscardUnknown() { - xxx_messageInfo_QueryChannelClientStateRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryChannelClientStateRequest proto.InternalMessageInfo - -func (m *QueryChannelClientStateRequest) GetPortId() string { - if m != nil { - return m.PortId - } - return "" -} - -func (m *QueryChannelClientStateRequest) GetChannelId() string { - if m != nil { - return m.ChannelId - } - return "" -} - -// QueryChannelClientStateResponse is the Response type for the -// Query/QueryChannelClientState RPC method -type QueryChannelClientStateResponse struct { - // client state associated with the channel - IdentifiedClientState *types.IdentifiedClientState `protobuf:"bytes,1,opt,name=identified_client_state,json=identifiedClientState,proto3" json:"identified_client_state,omitempty"` - // merkle proof of existence - Proof []byte `protobuf:"bytes,2,opt,name=proof,proto3" json:"proof,omitempty"` - // height at which the proof was retrieved - ProofHeight types.Height `protobuf:"bytes,3,opt,name=proof_height,json=proofHeight,proto3" json:"proof_height"` -} - -func (m *QueryChannelClientStateResponse) Reset() { *m = QueryChannelClientStateResponse{} } -func (m *QueryChannelClientStateResponse) String() string { return proto.CompactTextString(m) } -func (*QueryChannelClientStateResponse) ProtoMessage() {} -func (*QueryChannelClientStateResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_1034a1e9abc4cca1, []int{7} -} -func (m *QueryChannelClientStateResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryChannelClientStateResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryChannelClientStateResponse.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 *QueryChannelClientStateResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryChannelClientStateResponse.Merge(m, src) -} -func (m *QueryChannelClientStateResponse) XXX_Size() int { - return m.Size() -} -func (m *QueryChannelClientStateResponse) XXX_DiscardUnknown() { - xxx_messageInfo_QueryChannelClientStateResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryChannelClientStateResponse proto.InternalMessageInfo - -func (m *QueryChannelClientStateResponse) GetIdentifiedClientState() *types.IdentifiedClientState { - if m != nil { - return m.IdentifiedClientState - } - return nil -} - -func (m *QueryChannelClientStateResponse) GetProof() []byte { - if m != nil { - return m.Proof - } - return nil -} - -func (m *QueryChannelClientStateResponse) GetProofHeight() types.Height { - if m != nil { - return m.ProofHeight - } - return types.Height{} -} - -// QueryChannelConsensusStateRequest is the request type for the -// Query/ConsensusState RPC method -type QueryChannelConsensusStateRequest struct { - // port unique identifier - PortId string `protobuf:"bytes,1,opt,name=port_id,json=portId,proto3" json:"port_id,omitempty"` - // channel unique identifier - ChannelId string `protobuf:"bytes,2,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty"` - // revision number of the consensus state - RevisionNumber uint64 `protobuf:"varint,3,opt,name=revision_number,json=revisionNumber,proto3" json:"revision_number,omitempty"` - // revision height of the consensus state - RevisionHeight uint64 `protobuf:"varint,4,opt,name=revision_height,json=revisionHeight,proto3" json:"revision_height,omitempty"` -} - -func (m *QueryChannelConsensusStateRequest) Reset() { *m = QueryChannelConsensusStateRequest{} } -func (m *QueryChannelConsensusStateRequest) String() string { return proto.CompactTextString(m) } -func (*QueryChannelConsensusStateRequest) ProtoMessage() {} -func (*QueryChannelConsensusStateRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_1034a1e9abc4cca1, []int{8} -} -func (m *QueryChannelConsensusStateRequest) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryChannelConsensusStateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryChannelConsensusStateRequest.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 *QueryChannelConsensusStateRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryChannelConsensusStateRequest.Merge(m, src) -} -func (m *QueryChannelConsensusStateRequest) XXX_Size() int { - return m.Size() -} -func (m *QueryChannelConsensusStateRequest) XXX_DiscardUnknown() { - xxx_messageInfo_QueryChannelConsensusStateRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryChannelConsensusStateRequest proto.InternalMessageInfo - -func (m *QueryChannelConsensusStateRequest) GetPortId() string { - if m != nil { - return m.PortId - } - return "" -} - -func (m *QueryChannelConsensusStateRequest) GetChannelId() string { - if m != nil { - return m.ChannelId - } - return "" -} - -func (m *QueryChannelConsensusStateRequest) GetRevisionNumber() uint64 { - if m != nil { - return m.RevisionNumber - } - return 0 -} - -func (m *QueryChannelConsensusStateRequest) GetRevisionHeight() uint64 { - if m != nil { - return m.RevisionHeight - } - return 0 -} - -// QueryChannelClientStateResponse is the Response type for the -// Query/QueryChannelClientState RPC method -type QueryChannelConsensusStateResponse struct { - // consensus state associated with the channel - ConsensusState *types1.Any `protobuf:"bytes,1,opt,name=consensus_state,json=consensusState,proto3" json:"consensus_state,omitempty"` - // client ID associated with the consensus state - ClientId string `protobuf:"bytes,2,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"` - // merkle proof of existence - Proof []byte `protobuf:"bytes,3,opt,name=proof,proto3" json:"proof,omitempty"` - // height at which the proof was retrieved - ProofHeight types.Height `protobuf:"bytes,4,opt,name=proof_height,json=proofHeight,proto3" json:"proof_height"` -} - -func (m *QueryChannelConsensusStateResponse) Reset() { *m = QueryChannelConsensusStateResponse{} } -func (m *QueryChannelConsensusStateResponse) String() string { return proto.CompactTextString(m) } -func (*QueryChannelConsensusStateResponse) ProtoMessage() {} -func (*QueryChannelConsensusStateResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_1034a1e9abc4cca1, []int{9} -} -func (m *QueryChannelConsensusStateResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryChannelConsensusStateResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryChannelConsensusStateResponse.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 *QueryChannelConsensusStateResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryChannelConsensusStateResponse.Merge(m, src) -} -func (m *QueryChannelConsensusStateResponse) XXX_Size() int { - return m.Size() -} -func (m *QueryChannelConsensusStateResponse) XXX_DiscardUnknown() { - xxx_messageInfo_QueryChannelConsensusStateResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryChannelConsensusStateResponse proto.InternalMessageInfo - -func (m *QueryChannelConsensusStateResponse) GetConsensusState() *types1.Any { - if m != nil { - return m.ConsensusState - } - return nil -} - -func (m *QueryChannelConsensusStateResponse) GetClientId() string { - if m != nil { - return m.ClientId - } - return "" -} - -func (m *QueryChannelConsensusStateResponse) GetProof() []byte { - if m != nil { - return m.Proof - } - return nil -} - -func (m *QueryChannelConsensusStateResponse) GetProofHeight() types.Height { - if m != nil { - return m.ProofHeight - } - return types.Height{} -} - -// QueryPacketCommitmentRequest is the request type for the -// Query/PacketCommitment RPC method -type QueryPacketCommitmentRequest struct { - // port unique identifier - PortId string `protobuf:"bytes,1,opt,name=port_id,json=portId,proto3" json:"port_id,omitempty"` - // channel unique identifier - ChannelId string `protobuf:"bytes,2,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty"` - // packet sequence - Sequence uint64 `protobuf:"varint,3,opt,name=sequence,proto3" json:"sequence,omitempty"` -} - -func (m *QueryPacketCommitmentRequest) Reset() { *m = QueryPacketCommitmentRequest{} } -func (m *QueryPacketCommitmentRequest) String() string { return proto.CompactTextString(m) } -func (*QueryPacketCommitmentRequest) ProtoMessage() {} -func (*QueryPacketCommitmentRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_1034a1e9abc4cca1, []int{10} -} -func (m *QueryPacketCommitmentRequest) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryPacketCommitmentRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryPacketCommitmentRequest.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 *QueryPacketCommitmentRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryPacketCommitmentRequest.Merge(m, src) -} -func (m *QueryPacketCommitmentRequest) XXX_Size() int { - return m.Size() -} -func (m *QueryPacketCommitmentRequest) XXX_DiscardUnknown() { - xxx_messageInfo_QueryPacketCommitmentRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryPacketCommitmentRequest proto.InternalMessageInfo - -func (m *QueryPacketCommitmentRequest) GetPortId() string { - if m != nil { - return m.PortId - } - return "" -} - -func (m *QueryPacketCommitmentRequest) GetChannelId() string { - if m != nil { - return m.ChannelId - } - return "" -} - -func (m *QueryPacketCommitmentRequest) GetSequence() uint64 { - if m != nil { - return m.Sequence - } - return 0 -} - -// QueryPacketCommitmentResponse defines the client query response for a packet -// which also includes a proof and the height from which the proof was -// retrieved -type QueryPacketCommitmentResponse struct { - // packet associated with the request fields - Commitment []byte `protobuf:"bytes,1,opt,name=commitment,proto3" json:"commitment,omitempty"` - // merkle proof of existence - Proof []byte `protobuf:"bytes,2,opt,name=proof,proto3" json:"proof,omitempty"` - // height at which the proof was retrieved - ProofHeight types.Height `protobuf:"bytes,3,opt,name=proof_height,json=proofHeight,proto3" json:"proof_height"` -} - -func (m *QueryPacketCommitmentResponse) Reset() { *m = QueryPacketCommitmentResponse{} } -func (m *QueryPacketCommitmentResponse) String() string { return proto.CompactTextString(m) } -func (*QueryPacketCommitmentResponse) ProtoMessage() {} -func (*QueryPacketCommitmentResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_1034a1e9abc4cca1, []int{11} -} -func (m *QueryPacketCommitmentResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryPacketCommitmentResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryPacketCommitmentResponse.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 *QueryPacketCommitmentResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryPacketCommitmentResponse.Merge(m, src) -} -func (m *QueryPacketCommitmentResponse) XXX_Size() int { - return m.Size() -} -func (m *QueryPacketCommitmentResponse) XXX_DiscardUnknown() { - xxx_messageInfo_QueryPacketCommitmentResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryPacketCommitmentResponse proto.InternalMessageInfo - -func (m *QueryPacketCommitmentResponse) GetCommitment() []byte { - if m != nil { - return m.Commitment - } - return nil -} - -func (m *QueryPacketCommitmentResponse) GetProof() []byte { - if m != nil { - return m.Proof - } - return nil -} - -func (m *QueryPacketCommitmentResponse) GetProofHeight() types.Height { - if m != nil { - return m.ProofHeight - } - return types.Height{} -} - -// QueryPacketCommitmentsRequest is the request type for the -// Query/QueryPacketCommitments RPC method -type QueryPacketCommitmentsRequest struct { - // port unique identifier - PortId string `protobuf:"bytes,1,opt,name=port_id,json=portId,proto3" json:"port_id,omitempty"` - // channel unique identifier - ChannelId string `protobuf:"bytes,2,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty"` - // pagination request - Pagination *query.PageRequest `protobuf:"bytes,3,opt,name=pagination,proto3" json:"pagination,omitempty"` -} - -func (m *QueryPacketCommitmentsRequest) Reset() { *m = QueryPacketCommitmentsRequest{} } -func (m *QueryPacketCommitmentsRequest) String() string { return proto.CompactTextString(m) } -func (*QueryPacketCommitmentsRequest) ProtoMessage() {} -func (*QueryPacketCommitmentsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_1034a1e9abc4cca1, []int{12} -} -func (m *QueryPacketCommitmentsRequest) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryPacketCommitmentsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryPacketCommitmentsRequest.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 *QueryPacketCommitmentsRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryPacketCommitmentsRequest.Merge(m, src) -} -func (m *QueryPacketCommitmentsRequest) XXX_Size() int { - return m.Size() -} -func (m *QueryPacketCommitmentsRequest) XXX_DiscardUnknown() { - xxx_messageInfo_QueryPacketCommitmentsRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryPacketCommitmentsRequest proto.InternalMessageInfo - -func (m *QueryPacketCommitmentsRequest) GetPortId() string { - if m != nil { - return m.PortId - } - return "" -} - -func (m *QueryPacketCommitmentsRequest) GetChannelId() string { - if m != nil { - return m.ChannelId - } - return "" -} - -func (m *QueryPacketCommitmentsRequest) GetPagination() *query.PageRequest { - if m != nil { - return m.Pagination - } - return nil -} - -// QueryPacketCommitmentsResponse is the request type for the -// Query/QueryPacketCommitments RPC method -type QueryPacketCommitmentsResponse struct { - Commitments []*PacketState `protobuf:"bytes,1,rep,name=commitments,proto3" json:"commitments,omitempty"` - // pagination response - Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` - // query block height - Height types.Height `protobuf:"bytes,3,opt,name=height,proto3" json:"height"` -} - -func (m *QueryPacketCommitmentsResponse) Reset() { *m = QueryPacketCommitmentsResponse{} } -func (m *QueryPacketCommitmentsResponse) String() string { return proto.CompactTextString(m) } -func (*QueryPacketCommitmentsResponse) ProtoMessage() {} -func (*QueryPacketCommitmentsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_1034a1e9abc4cca1, []int{13} -} -func (m *QueryPacketCommitmentsResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryPacketCommitmentsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryPacketCommitmentsResponse.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 *QueryPacketCommitmentsResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryPacketCommitmentsResponse.Merge(m, src) -} -func (m *QueryPacketCommitmentsResponse) XXX_Size() int { - return m.Size() -} -func (m *QueryPacketCommitmentsResponse) XXX_DiscardUnknown() { - xxx_messageInfo_QueryPacketCommitmentsResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryPacketCommitmentsResponse proto.InternalMessageInfo - -func (m *QueryPacketCommitmentsResponse) GetCommitments() []*PacketState { - if m != nil { - return m.Commitments - } - return nil -} - -func (m *QueryPacketCommitmentsResponse) GetPagination() *query.PageResponse { - if m != nil { - return m.Pagination - } - return nil -} - -func (m *QueryPacketCommitmentsResponse) GetHeight() types.Height { - if m != nil { - return m.Height - } - return types.Height{} -} - -// QueryPacketReceiptRequest is the request type for the -// Query/PacketReceipt RPC method -type QueryPacketReceiptRequest struct { - // port unique identifier - PortId string `protobuf:"bytes,1,opt,name=port_id,json=portId,proto3" json:"port_id,omitempty"` - // channel unique identifier - ChannelId string `protobuf:"bytes,2,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty"` - // packet sequence - Sequence uint64 `protobuf:"varint,3,opt,name=sequence,proto3" json:"sequence,omitempty"` -} - -func (m *QueryPacketReceiptRequest) Reset() { *m = QueryPacketReceiptRequest{} } -func (m *QueryPacketReceiptRequest) String() string { return proto.CompactTextString(m) } -func (*QueryPacketReceiptRequest) ProtoMessage() {} -func (*QueryPacketReceiptRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_1034a1e9abc4cca1, []int{14} -} -func (m *QueryPacketReceiptRequest) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryPacketReceiptRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryPacketReceiptRequest.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 *QueryPacketReceiptRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryPacketReceiptRequest.Merge(m, src) -} -func (m *QueryPacketReceiptRequest) XXX_Size() int { - return m.Size() -} -func (m *QueryPacketReceiptRequest) XXX_DiscardUnknown() { - xxx_messageInfo_QueryPacketReceiptRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryPacketReceiptRequest proto.InternalMessageInfo - -func (m *QueryPacketReceiptRequest) GetPortId() string { - if m != nil { - return m.PortId - } - return "" -} - -func (m *QueryPacketReceiptRequest) GetChannelId() string { - if m != nil { - return m.ChannelId - } - return "" -} - -func (m *QueryPacketReceiptRequest) GetSequence() uint64 { - if m != nil { - return m.Sequence - } - return 0 -} - -// QueryPacketReceiptResponse defines the client query response for a packet receipt -// which also includes a proof, and the height from which the proof was -// retrieved -type QueryPacketReceiptResponse struct { - // success flag for if receipt exists - Received bool `protobuf:"varint,2,opt,name=received,proto3" json:"received,omitempty"` - // merkle proof of existence - Proof []byte `protobuf:"bytes,3,opt,name=proof,proto3" json:"proof,omitempty"` - // height at which the proof was retrieved - ProofHeight types.Height `protobuf:"bytes,4,opt,name=proof_height,json=proofHeight,proto3" json:"proof_height"` -} - -func (m *QueryPacketReceiptResponse) Reset() { *m = QueryPacketReceiptResponse{} } -func (m *QueryPacketReceiptResponse) String() string { return proto.CompactTextString(m) } -func (*QueryPacketReceiptResponse) ProtoMessage() {} -func (*QueryPacketReceiptResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_1034a1e9abc4cca1, []int{15} -} -func (m *QueryPacketReceiptResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryPacketReceiptResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryPacketReceiptResponse.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 *QueryPacketReceiptResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryPacketReceiptResponse.Merge(m, src) -} -func (m *QueryPacketReceiptResponse) XXX_Size() int { - return m.Size() -} -func (m *QueryPacketReceiptResponse) XXX_DiscardUnknown() { - xxx_messageInfo_QueryPacketReceiptResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryPacketReceiptResponse proto.InternalMessageInfo - -func (m *QueryPacketReceiptResponse) GetReceived() bool { - if m != nil { - return m.Received - } - return false -} - -func (m *QueryPacketReceiptResponse) GetProof() []byte { - if m != nil { - return m.Proof - } - return nil -} - -func (m *QueryPacketReceiptResponse) GetProofHeight() types.Height { - if m != nil { - return m.ProofHeight - } - return types.Height{} -} - -// QueryPacketAcknowledgementRequest is the request type for the -// Query/PacketAcknowledgement RPC method -type QueryPacketAcknowledgementRequest struct { - // port unique identifier - PortId string `protobuf:"bytes,1,opt,name=port_id,json=portId,proto3" json:"port_id,omitempty"` - // channel unique identifier - ChannelId string `protobuf:"bytes,2,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty"` - // packet sequence - Sequence uint64 `protobuf:"varint,3,opt,name=sequence,proto3" json:"sequence,omitempty"` -} - -func (m *QueryPacketAcknowledgementRequest) Reset() { *m = QueryPacketAcknowledgementRequest{} } -func (m *QueryPacketAcknowledgementRequest) String() string { return proto.CompactTextString(m) } -func (*QueryPacketAcknowledgementRequest) ProtoMessage() {} -func (*QueryPacketAcknowledgementRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_1034a1e9abc4cca1, []int{16} -} -func (m *QueryPacketAcknowledgementRequest) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryPacketAcknowledgementRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryPacketAcknowledgementRequest.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 *QueryPacketAcknowledgementRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryPacketAcknowledgementRequest.Merge(m, src) -} -func (m *QueryPacketAcknowledgementRequest) XXX_Size() int { - return m.Size() -} -func (m *QueryPacketAcknowledgementRequest) XXX_DiscardUnknown() { - xxx_messageInfo_QueryPacketAcknowledgementRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryPacketAcknowledgementRequest proto.InternalMessageInfo - -func (m *QueryPacketAcknowledgementRequest) GetPortId() string { - if m != nil { - return m.PortId - } - return "" -} - -func (m *QueryPacketAcknowledgementRequest) GetChannelId() string { - if m != nil { - return m.ChannelId - } - return "" -} - -func (m *QueryPacketAcknowledgementRequest) GetSequence() uint64 { - if m != nil { - return m.Sequence - } - return 0 -} - -// QueryPacketAcknowledgementResponse defines the client query response for a -// packet which also includes a proof and the height from which the -// proof was retrieved -type QueryPacketAcknowledgementResponse struct { - // packet associated with the request fields - Acknowledgement []byte `protobuf:"bytes,1,opt,name=acknowledgement,proto3" json:"acknowledgement,omitempty"` - // merkle proof of existence - Proof []byte `protobuf:"bytes,2,opt,name=proof,proto3" json:"proof,omitempty"` - // height at which the proof was retrieved - ProofHeight types.Height `protobuf:"bytes,3,opt,name=proof_height,json=proofHeight,proto3" json:"proof_height"` -} - -func (m *QueryPacketAcknowledgementResponse) Reset() { *m = QueryPacketAcknowledgementResponse{} } -func (m *QueryPacketAcknowledgementResponse) String() string { return proto.CompactTextString(m) } -func (*QueryPacketAcknowledgementResponse) ProtoMessage() {} -func (*QueryPacketAcknowledgementResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_1034a1e9abc4cca1, []int{17} -} -func (m *QueryPacketAcknowledgementResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryPacketAcknowledgementResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryPacketAcknowledgementResponse.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 *QueryPacketAcknowledgementResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryPacketAcknowledgementResponse.Merge(m, src) -} -func (m *QueryPacketAcknowledgementResponse) XXX_Size() int { - return m.Size() -} -func (m *QueryPacketAcknowledgementResponse) XXX_DiscardUnknown() { - xxx_messageInfo_QueryPacketAcknowledgementResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryPacketAcknowledgementResponse proto.InternalMessageInfo - -func (m *QueryPacketAcknowledgementResponse) GetAcknowledgement() []byte { - if m != nil { - return m.Acknowledgement - } - return nil -} - -func (m *QueryPacketAcknowledgementResponse) GetProof() []byte { - if m != nil { - return m.Proof - } - return nil -} - -func (m *QueryPacketAcknowledgementResponse) GetProofHeight() types.Height { - if m != nil { - return m.ProofHeight - } - return types.Height{} -} - -// QueryPacketAcknowledgementsRequest is the request type for the -// Query/QueryPacketCommitments RPC method -type QueryPacketAcknowledgementsRequest struct { - // port unique identifier - PortId string `protobuf:"bytes,1,opt,name=port_id,json=portId,proto3" json:"port_id,omitempty"` - // channel unique identifier - ChannelId string `protobuf:"bytes,2,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty"` - // pagination request - Pagination *query.PageRequest `protobuf:"bytes,3,opt,name=pagination,proto3" json:"pagination,omitempty"` -} - -func (m *QueryPacketAcknowledgementsRequest) Reset() { *m = QueryPacketAcknowledgementsRequest{} } -func (m *QueryPacketAcknowledgementsRequest) String() string { return proto.CompactTextString(m) } -func (*QueryPacketAcknowledgementsRequest) ProtoMessage() {} -func (*QueryPacketAcknowledgementsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_1034a1e9abc4cca1, []int{18} -} -func (m *QueryPacketAcknowledgementsRequest) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryPacketAcknowledgementsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryPacketAcknowledgementsRequest.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 *QueryPacketAcknowledgementsRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryPacketAcknowledgementsRequest.Merge(m, src) -} -func (m *QueryPacketAcknowledgementsRequest) XXX_Size() int { - return m.Size() -} -func (m *QueryPacketAcknowledgementsRequest) XXX_DiscardUnknown() { - xxx_messageInfo_QueryPacketAcknowledgementsRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryPacketAcknowledgementsRequest proto.InternalMessageInfo - -func (m *QueryPacketAcknowledgementsRequest) GetPortId() string { - if m != nil { - return m.PortId - } - return "" -} - -func (m *QueryPacketAcknowledgementsRequest) GetChannelId() string { - if m != nil { - return m.ChannelId - } - return "" -} - -func (m *QueryPacketAcknowledgementsRequest) GetPagination() *query.PageRequest { - if m != nil { - return m.Pagination - } - return nil -} - -// QueryPacketAcknowledgemetsResponse is the request type for the -// Query/QueryPacketAcknowledgements RPC method -type QueryPacketAcknowledgementsResponse struct { - Acknowledgements []*PacketState `protobuf:"bytes,1,rep,name=acknowledgements,proto3" json:"acknowledgements,omitempty"` - // pagination response - Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` - // query block height - Height types.Height `protobuf:"bytes,3,opt,name=height,proto3" json:"height"` -} - -func (m *QueryPacketAcknowledgementsResponse) Reset() { *m = QueryPacketAcknowledgementsResponse{} } -func (m *QueryPacketAcknowledgementsResponse) String() string { return proto.CompactTextString(m) } -func (*QueryPacketAcknowledgementsResponse) ProtoMessage() {} -func (*QueryPacketAcknowledgementsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_1034a1e9abc4cca1, []int{19} -} -func (m *QueryPacketAcknowledgementsResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryPacketAcknowledgementsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryPacketAcknowledgementsResponse.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 *QueryPacketAcknowledgementsResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryPacketAcknowledgementsResponse.Merge(m, src) -} -func (m *QueryPacketAcknowledgementsResponse) XXX_Size() int { - return m.Size() -} -func (m *QueryPacketAcknowledgementsResponse) XXX_DiscardUnknown() { - xxx_messageInfo_QueryPacketAcknowledgementsResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryPacketAcknowledgementsResponse proto.InternalMessageInfo - -func (m *QueryPacketAcknowledgementsResponse) GetAcknowledgements() []*PacketState { - if m != nil { - return m.Acknowledgements - } - return nil -} - -func (m *QueryPacketAcknowledgementsResponse) GetPagination() *query.PageResponse { - if m != nil { - return m.Pagination - } - return nil -} - -func (m *QueryPacketAcknowledgementsResponse) GetHeight() types.Height { - if m != nil { - return m.Height - } - return types.Height{} -} - -// QueryUnreceivedPacketsRequest is the request type for the -// Query/UnreceivedPackets RPC method -type QueryUnreceivedPacketsRequest struct { - // port unique identifier - PortId string `protobuf:"bytes,1,opt,name=port_id,json=portId,proto3" json:"port_id,omitempty"` - // channel unique identifier - ChannelId string `protobuf:"bytes,2,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty"` - // list of packet sequences - PacketCommitmentSequences []uint64 `protobuf:"varint,3,rep,packed,name=packet_commitment_sequences,json=packetCommitmentSequences,proto3" json:"packet_commitment_sequences,omitempty"` -} - -func (m *QueryUnreceivedPacketsRequest) Reset() { *m = QueryUnreceivedPacketsRequest{} } -func (m *QueryUnreceivedPacketsRequest) String() string { return proto.CompactTextString(m) } -func (*QueryUnreceivedPacketsRequest) ProtoMessage() {} -func (*QueryUnreceivedPacketsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_1034a1e9abc4cca1, []int{20} -} -func (m *QueryUnreceivedPacketsRequest) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryUnreceivedPacketsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryUnreceivedPacketsRequest.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 *QueryUnreceivedPacketsRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryUnreceivedPacketsRequest.Merge(m, src) -} -func (m *QueryUnreceivedPacketsRequest) XXX_Size() int { - return m.Size() -} -func (m *QueryUnreceivedPacketsRequest) XXX_DiscardUnknown() { - xxx_messageInfo_QueryUnreceivedPacketsRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryUnreceivedPacketsRequest proto.InternalMessageInfo - -func (m *QueryUnreceivedPacketsRequest) GetPortId() string { - if m != nil { - return m.PortId - } - return "" -} - -func (m *QueryUnreceivedPacketsRequest) GetChannelId() string { - if m != nil { - return m.ChannelId - } - return "" -} - -func (m *QueryUnreceivedPacketsRequest) GetPacketCommitmentSequences() []uint64 { - if m != nil { - return m.PacketCommitmentSequences - } - return nil -} - -// QueryUnreceivedPacketsResponse is the response type for the -// Query/UnreceivedPacketCommitments RPC method -type QueryUnreceivedPacketsResponse struct { - // list of unreceived packet sequences - Sequences []uint64 `protobuf:"varint,1,rep,packed,name=sequences,proto3" json:"sequences,omitempty"` - // query block height - Height types.Height `protobuf:"bytes,2,opt,name=height,proto3" json:"height"` -} - -func (m *QueryUnreceivedPacketsResponse) Reset() { *m = QueryUnreceivedPacketsResponse{} } -func (m *QueryUnreceivedPacketsResponse) String() string { return proto.CompactTextString(m) } -func (*QueryUnreceivedPacketsResponse) ProtoMessage() {} -func (*QueryUnreceivedPacketsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_1034a1e9abc4cca1, []int{21} -} -func (m *QueryUnreceivedPacketsResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryUnreceivedPacketsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryUnreceivedPacketsResponse.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 *QueryUnreceivedPacketsResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryUnreceivedPacketsResponse.Merge(m, src) -} -func (m *QueryUnreceivedPacketsResponse) XXX_Size() int { - return m.Size() -} -func (m *QueryUnreceivedPacketsResponse) XXX_DiscardUnknown() { - xxx_messageInfo_QueryUnreceivedPacketsResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryUnreceivedPacketsResponse proto.InternalMessageInfo - -func (m *QueryUnreceivedPacketsResponse) GetSequences() []uint64 { - if m != nil { - return m.Sequences - } - return nil -} - -func (m *QueryUnreceivedPacketsResponse) GetHeight() types.Height { - if m != nil { - return m.Height - } - return types.Height{} -} - -// QueryUnreceivedAcks is the request type for the -// Query/UnreceivedAcks RPC method -type QueryUnreceivedAcksRequest struct { - // port unique identifier - PortId string `protobuf:"bytes,1,opt,name=port_id,json=portId,proto3" json:"port_id,omitempty"` - // channel unique identifier - ChannelId string `protobuf:"bytes,2,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty"` - // list of acknowledgement sequences - PacketAckSequences []uint64 `protobuf:"varint,3,rep,packed,name=packet_ack_sequences,json=packetAckSequences,proto3" json:"packet_ack_sequences,omitempty"` -} - -func (m *QueryUnreceivedAcksRequest) Reset() { *m = QueryUnreceivedAcksRequest{} } -func (m *QueryUnreceivedAcksRequest) String() string { return proto.CompactTextString(m) } -func (*QueryUnreceivedAcksRequest) ProtoMessage() {} -func (*QueryUnreceivedAcksRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_1034a1e9abc4cca1, []int{22} -} -func (m *QueryUnreceivedAcksRequest) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryUnreceivedAcksRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryUnreceivedAcksRequest.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 *QueryUnreceivedAcksRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryUnreceivedAcksRequest.Merge(m, src) -} -func (m *QueryUnreceivedAcksRequest) XXX_Size() int { - return m.Size() -} -func (m *QueryUnreceivedAcksRequest) XXX_DiscardUnknown() { - xxx_messageInfo_QueryUnreceivedAcksRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryUnreceivedAcksRequest proto.InternalMessageInfo - -func (m *QueryUnreceivedAcksRequest) GetPortId() string { - if m != nil { - return m.PortId - } - return "" -} - -func (m *QueryUnreceivedAcksRequest) GetChannelId() string { - if m != nil { - return m.ChannelId - } - return "" -} - -func (m *QueryUnreceivedAcksRequest) GetPacketAckSequences() []uint64 { - if m != nil { - return m.PacketAckSequences - } - return nil -} - -// QueryUnreceivedAcksResponse is the response type for the -// Query/UnreceivedAcks RPC method -type QueryUnreceivedAcksResponse struct { - // list of unreceived acknowledgement sequences - Sequences []uint64 `protobuf:"varint,1,rep,packed,name=sequences,proto3" json:"sequences,omitempty"` - // query block height - Height types.Height `protobuf:"bytes,2,opt,name=height,proto3" json:"height"` -} - -func (m *QueryUnreceivedAcksResponse) Reset() { *m = QueryUnreceivedAcksResponse{} } -func (m *QueryUnreceivedAcksResponse) String() string { return proto.CompactTextString(m) } -func (*QueryUnreceivedAcksResponse) ProtoMessage() {} -func (*QueryUnreceivedAcksResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_1034a1e9abc4cca1, []int{23} -} -func (m *QueryUnreceivedAcksResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryUnreceivedAcksResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryUnreceivedAcksResponse.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 *QueryUnreceivedAcksResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryUnreceivedAcksResponse.Merge(m, src) -} -func (m *QueryUnreceivedAcksResponse) XXX_Size() int { - return m.Size() -} -func (m *QueryUnreceivedAcksResponse) XXX_DiscardUnknown() { - xxx_messageInfo_QueryUnreceivedAcksResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryUnreceivedAcksResponse proto.InternalMessageInfo - -func (m *QueryUnreceivedAcksResponse) GetSequences() []uint64 { - if m != nil { - return m.Sequences - } - return nil -} - -func (m *QueryUnreceivedAcksResponse) GetHeight() types.Height { - if m != nil { - return m.Height - } - return types.Height{} -} - -// QueryNextSequenceReceiveRequest is the request type for the -// Query/QueryNextSequenceReceiveRequest RPC method -type QueryNextSequenceReceiveRequest struct { - // port unique identifier - PortId string `protobuf:"bytes,1,opt,name=port_id,json=portId,proto3" json:"port_id,omitempty"` - // channel unique identifier - ChannelId string `protobuf:"bytes,2,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty"` -} - -func (m *QueryNextSequenceReceiveRequest) Reset() { *m = QueryNextSequenceReceiveRequest{} } -func (m *QueryNextSequenceReceiveRequest) String() string { return proto.CompactTextString(m) } -func (*QueryNextSequenceReceiveRequest) ProtoMessage() {} -func (*QueryNextSequenceReceiveRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_1034a1e9abc4cca1, []int{24} -} -func (m *QueryNextSequenceReceiveRequest) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryNextSequenceReceiveRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryNextSequenceReceiveRequest.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 *QueryNextSequenceReceiveRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryNextSequenceReceiveRequest.Merge(m, src) -} -func (m *QueryNextSequenceReceiveRequest) XXX_Size() int { - return m.Size() -} -func (m *QueryNextSequenceReceiveRequest) XXX_DiscardUnknown() { - xxx_messageInfo_QueryNextSequenceReceiveRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryNextSequenceReceiveRequest proto.InternalMessageInfo - -func (m *QueryNextSequenceReceiveRequest) GetPortId() string { - if m != nil { - return m.PortId - } - return "" -} - -func (m *QueryNextSequenceReceiveRequest) GetChannelId() string { - if m != nil { - return m.ChannelId - } - return "" -} - -// QuerySequenceResponse is the request type for the -// Query/QueryNextSequenceReceiveResponse RPC method -type QueryNextSequenceReceiveResponse struct { - // next sequence receive number - NextSequenceReceive uint64 `protobuf:"varint,1,opt,name=next_sequence_receive,json=nextSequenceReceive,proto3" json:"next_sequence_receive,omitempty"` - // merkle proof of existence - Proof []byte `protobuf:"bytes,2,opt,name=proof,proto3" json:"proof,omitempty"` - // height at which the proof was retrieved - ProofHeight types.Height `protobuf:"bytes,3,opt,name=proof_height,json=proofHeight,proto3" json:"proof_height"` -} - -func (m *QueryNextSequenceReceiveResponse) Reset() { *m = QueryNextSequenceReceiveResponse{} } -func (m *QueryNextSequenceReceiveResponse) String() string { return proto.CompactTextString(m) } -func (*QueryNextSequenceReceiveResponse) ProtoMessage() {} -func (*QueryNextSequenceReceiveResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_1034a1e9abc4cca1, []int{25} -} -func (m *QueryNextSequenceReceiveResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryNextSequenceReceiveResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryNextSequenceReceiveResponse.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 *QueryNextSequenceReceiveResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryNextSequenceReceiveResponse.Merge(m, src) -} -func (m *QueryNextSequenceReceiveResponse) XXX_Size() int { - return m.Size() -} -func (m *QueryNextSequenceReceiveResponse) XXX_DiscardUnknown() { - xxx_messageInfo_QueryNextSequenceReceiveResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryNextSequenceReceiveResponse proto.InternalMessageInfo - -func (m *QueryNextSequenceReceiveResponse) GetNextSequenceReceive() uint64 { - if m != nil { - return m.NextSequenceReceive - } - return 0 -} - -func (m *QueryNextSequenceReceiveResponse) GetProof() []byte { - if m != nil { - return m.Proof - } - return nil -} - -func (m *QueryNextSequenceReceiveResponse) GetProofHeight() types.Height { - if m != nil { - return m.ProofHeight - } - return types.Height{} -} - -func init() { - proto.RegisterType((*QueryChannelRequest)(nil), "ibc.core.channel.v1.QueryChannelRequest") - proto.RegisterType((*QueryChannelResponse)(nil), "ibc.core.channel.v1.QueryChannelResponse") - proto.RegisterType((*QueryChannelsRequest)(nil), "ibc.core.channel.v1.QueryChannelsRequest") - proto.RegisterType((*QueryChannelsResponse)(nil), "ibc.core.channel.v1.QueryChannelsResponse") - proto.RegisterType((*QueryConnectionChannelsRequest)(nil), "ibc.core.channel.v1.QueryConnectionChannelsRequest") - proto.RegisterType((*QueryConnectionChannelsResponse)(nil), "ibc.core.channel.v1.QueryConnectionChannelsResponse") - proto.RegisterType((*QueryChannelClientStateRequest)(nil), "ibc.core.channel.v1.QueryChannelClientStateRequest") - proto.RegisterType((*QueryChannelClientStateResponse)(nil), "ibc.core.channel.v1.QueryChannelClientStateResponse") - proto.RegisterType((*QueryChannelConsensusStateRequest)(nil), "ibc.core.channel.v1.QueryChannelConsensusStateRequest") - proto.RegisterType((*QueryChannelConsensusStateResponse)(nil), "ibc.core.channel.v1.QueryChannelConsensusStateResponse") - proto.RegisterType((*QueryPacketCommitmentRequest)(nil), "ibc.core.channel.v1.QueryPacketCommitmentRequest") - proto.RegisterType((*QueryPacketCommitmentResponse)(nil), "ibc.core.channel.v1.QueryPacketCommitmentResponse") - proto.RegisterType((*QueryPacketCommitmentsRequest)(nil), "ibc.core.channel.v1.QueryPacketCommitmentsRequest") - proto.RegisterType((*QueryPacketCommitmentsResponse)(nil), "ibc.core.channel.v1.QueryPacketCommitmentsResponse") - proto.RegisterType((*QueryPacketReceiptRequest)(nil), "ibc.core.channel.v1.QueryPacketReceiptRequest") - proto.RegisterType((*QueryPacketReceiptResponse)(nil), "ibc.core.channel.v1.QueryPacketReceiptResponse") - proto.RegisterType((*QueryPacketAcknowledgementRequest)(nil), "ibc.core.channel.v1.QueryPacketAcknowledgementRequest") - proto.RegisterType((*QueryPacketAcknowledgementResponse)(nil), "ibc.core.channel.v1.QueryPacketAcknowledgementResponse") - proto.RegisterType((*QueryPacketAcknowledgementsRequest)(nil), "ibc.core.channel.v1.QueryPacketAcknowledgementsRequest") - proto.RegisterType((*QueryPacketAcknowledgementsResponse)(nil), "ibc.core.channel.v1.QueryPacketAcknowledgementsResponse") - proto.RegisterType((*QueryUnreceivedPacketsRequest)(nil), "ibc.core.channel.v1.QueryUnreceivedPacketsRequest") - proto.RegisterType((*QueryUnreceivedPacketsResponse)(nil), "ibc.core.channel.v1.QueryUnreceivedPacketsResponse") - proto.RegisterType((*QueryUnreceivedAcksRequest)(nil), "ibc.core.channel.v1.QueryUnreceivedAcksRequest") - proto.RegisterType((*QueryUnreceivedAcksResponse)(nil), "ibc.core.channel.v1.QueryUnreceivedAcksResponse") - proto.RegisterType((*QueryNextSequenceReceiveRequest)(nil), "ibc.core.channel.v1.QueryNextSequenceReceiveRequest") - proto.RegisterType((*QueryNextSequenceReceiveResponse)(nil), "ibc.core.channel.v1.QueryNextSequenceReceiveResponse") -} - -func init() { proto.RegisterFile("ibc/core/channel/v1/query.proto", fileDescriptor_1034a1e9abc4cca1) } - -var fileDescriptor_1034a1e9abc4cca1 = []byte{ - // 1482 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x59, 0xdd, 0x6f, 0x14, 0x55, - 0x14, 0xef, 0xdd, 0x16, 0x68, 0x0f, 0xc8, 0xc7, 0x6d, 0x0b, 0x65, 0x28, 0x4b, 0x19, 0x8d, 0x14, - 0x12, 0xe6, 0xd2, 0x82, 0x48, 0x62, 0xd0, 0x94, 0x26, 0x62, 0x13, 0x40, 0x1c, 0x40, 0x81, 0x28, - 0x9b, 0xd9, 0xd9, 0xcb, 0x76, 0xd2, 0x76, 0x66, 0xd8, 0x99, 0x2d, 0x6d, 0x9a, 0x7d, 0x50, 0x13, - 0xe2, 0x83, 0x24, 0x26, 0x3c, 0x68, 0x7c, 0xf1, 0xc5, 0xc4, 0xf0, 0xe0, 0x83, 0xff, 0x83, 0x0f, - 0xbc, 0x49, 0xa2, 0x26, 0x18, 0x13, 0x24, 0x60, 0x22, 0x0f, 0x3e, 0xeb, 0xab, 0x99, 0xfb, 0x31, - 0x1f, 0xbb, 0x33, 0xd3, 0x2e, 0xdb, 0x4d, 0x1a, 0x9f, 0xba, 0x73, 0xe7, 0x9c, 0x73, 0x7f, 0xbf, - 0xdf, 0xb9, 0xe7, 0xec, 0x3d, 0x5b, 0x38, 0x60, 0x95, 0x4d, 0x62, 0x3a, 0x35, 0x4a, 0xcc, 0x59, - 0xc3, 0xb6, 0xe9, 0x3c, 0x59, 0x9c, 0x20, 0xb7, 0xea, 0xb4, 0xb6, 0xac, 0xb9, 0x35, 0xc7, 0x77, - 0xf0, 0xa0, 0x55, 0x36, 0xb5, 0xc0, 0x40, 0x13, 0x06, 0xda, 0xe2, 0x84, 0x12, 0xf3, 0x9a, 0xb7, - 0xa8, 0xed, 0x07, 0x4e, 0xfc, 0x13, 0xf7, 0x52, 0x8e, 0x98, 0x8e, 0xb7, 0xe0, 0x78, 0xa4, 0x6c, - 0x78, 0x94, 0x87, 0x23, 0x8b, 0x13, 0x65, 0xea, 0x1b, 0x13, 0xc4, 0x35, 0xaa, 0x96, 0x6d, 0xf8, - 0x96, 0x63, 0x0b, 0xdb, 0x83, 0x69, 0x10, 0xe4, 0x66, 0xdc, 0x64, 0xb4, 0xea, 0x38, 0xd5, 0x79, - 0x4a, 0x0c, 0xd7, 0x22, 0x86, 0x6d, 0x3b, 0x3e, 0xf3, 0xf7, 0xc4, 0xdb, 0xbd, 0xe2, 0x2d, 0x7b, - 0x2a, 0xd7, 0x6f, 0x12, 0xc3, 0x16, 0xe8, 0x95, 0xa1, 0xaa, 0x53, 0x75, 0xd8, 0x47, 0x12, 0x7c, - 0xe2, 0xab, 0xea, 0x79, 0x18, 0x7c, 0x2f, 0xc0, 0x34, 0xcd, 0x37, 0xd1, 0xe9, 0xad, 0x3a, 0xf5, - 0x7c, 0xbc, 0x07, 0xb6, 0xb8, 0x4e, 0xcd, 0x2f, 0x59, 0x95, 0x11, 0x34, 0x86, 0xc6, 0x07, 0xf4, - 0xcd, 0xc1, 0xe3, 0x4c, 0x05, 0xef, 0x07, 0x10, 0x78, 0x82, 0x77, 0x05, 0xf6, 0x6e, 0x40, 0xac, - 0xcc, 0x54, 0xd4, 0xfb, 0x08, 0x86, 0x92, 0xf1, 0x3c, 0xd7, 0xb1, 0x3d, 0x8a, 0x4f, 0xc2, 0x16, - 0x61, 0xc5, 0x02, 0x6e, 0x9d, 0x1c, 0xd5, 0x52, 0xd4, 0xd4, 0xa4, 0x9b, 0x34, 0xc6, 0x43, 0xb0, - 0xc9, 0xad, 0x39, 0xce, 0x4d, 0xb6, 0xd5, 0x36, 0x9d, 0x3f, 0xe0, 0x69, 0xd8, 0xc6, 0x3e, 0x94, - 0x66, 0xa9, 0x55, 0x9d, 0xf5, 0x47, 0x7a, 0x59, 0x48, 0x25, 0x16, 0x92, 0x67, 0x60, 0x71, 0x42, - 0x7b, 0x87, 0x59, 0x9c, 0xe9, 0x7b, 0xf0, 0xf8, 0x40, 0x8f, 0xbe, 0x95, 0x79, 0xf1, 0x25, 0xf5, - 0x46, 0x12, 0xaa, 0x27, 0xb9, 0xbf, 0x0d, 0x10, 0x25, 0x46, 0xa0, 0x7d, 0x55, 0xe3, 0x59, 0xd4, - 0x82, 0x2c, 0x6a, 0xfc, 0x50, 0x88, 0x2c, 0x6a, 0x17, 0x8d, 0x2a, 0x15, 0xbe, 0x7a, 0xcc, 0x53, - 0x7d, 0x8c, 0x60, 0xb8, 0x69, 0x03, 0x21, 0xc6, 0x19, 0xe8, 0x17, 0xfc, 0xbc, 0x11, 0x34, 0xd6, - 0xcb, 0xe2, 0xa7, 0xa9, 0x31, 0x53, 0xa1, 0xb6, 0x6f, 0xdd, 0xb4, 0x68, 0x45, 0xea, 0x12, 0xfa, - 0xe1, 0xb3, 0x09, 0x94, 0x05, 0x86, 0xf2, 0xd0, 0xaa, 0x28, 0x39, 0x80, 0x38, 0x4c, 0x7c, 0x0a, - 0x36, 0xb7, 0xa9, 0xa2, 0xb0, 0x57, 0x3f, 0x43, 0x50, 0xe4, 0x04, 0x1d, 0xdb, 0xa6, 0x66, 0x10, - 0xad, 0x59, 0xcb, 0x22, 0x80, 0x19, 0xbe, 0x14, 0x47, 0x29, 0xb6, 0xd2, 0xa4, 0x75, 0xe1, 0x85, - 0xb5, 0x7e, 0x8e, 0xe0, 0x40, 0x26, 0x94, 0xff, 0x97, 0xea, 0x57, 0xa5, 0xe8, 0x1c, 0xd3, 0x34, - 0xb3, 0xbe, 0xe4, 0x1b, 0x3e, 0xed, 0xb4, 0x78, 0xff, 0x08, 0x45, 0x4c, 0x09, 0x2d, 0x44, 0x34, - 0x60, 0x8f, 0x15, 0xea, 0x53, 0xe2, 0x50, 0x4b, 0x5e, 0x60, 0x22, 0x2a, 0xe5, 0x70, 0x1a, 0x91, - 0x98, 0xa4, 0xb1, 0x98, 0xc3, 0x56, 0xda, 0x72, 0x37, 0x4b, 0xfe, 0x7b, 0x04, 0x07, 0x13, 0x0c, - 0x03, 0x4e, 0xb6, 0x57, 0xf7, 0xd6, 0x43, 0x3f, 0x7c, 0x08, 0x76, 0xd4, 0xe8, 0xa2, 0xe5, 0x59, - 0x8e, 0x5d, 0xb2, 0xeb, 0x0b, 0x65, 0x5a, 0x63, 0x28, 0xfb, 0xf4, 0xed, 0x72, 0xf9, 0x02, 0x5b, - 0x4d, 0x18, 0x0a, 0x3a, 0x7d, 0x49, 0x43, 0x81, 0xf7, 0x77, 0x04, 0x6a, 0x1e, 0x5e, 0x91, 0x94, - 0xd3, 0xb0, 0xc3, 0x94, 0x6f, 0x12, 0xc9, 0x18, 0xd2, 0xf8, 0xf7, 0x81, 0x26, 0xbf, 0x0f, 0xb4, - 0x29, 0x7b, 0x59, 0xdf, 0x6e, 0x26, 0xc2, 0xe0, 0x7d, 0x30, 0x20, 0x12, 0x19, 0xb2, 0xea, 0xe7, - 0x0b, 0x33, 0x95, 0x28, 0x1b, 0xbd, 0x79, 0xd9, 0xe8, 0x7b, 0x91, 0x6c, 0xd4, 0x60, 0x94, 0x91, - 0xbb, 0x68, 0x98, 0x73, 0xd4, 0x9f, 0x76, 0x16, 0x16, 0x2c, 0x7f, 0x81, 0xda, 0x7e, 0xa7, 0x79, - 0x50, 0xa0, 0xdf, 0x0b, 0x42, 0xd8, 0x26, 0x15, 0x09, 0x08, 0x9f, 0xd5, 0xaf, 0x11, 0xec, 0xcf, - 0xd8, 0x54, 0x88, 0xc9, 0x5a, 0x96, 0x5c, 0x65, 0x1b, 0x6f, 0xd3, 0x63, 0x2b, 0xdd, 0x3c, 0x9e, - 0xdf, 0x64, 0x81, 0xf3, 0x3a, 0x95, 0x24, 0xd9, 0x67, 0x7b, 0x5f, 0xb8, 0xcf, 0xfe, 0x25, 0x5b, - 0x7e, 0x0a, 0xc2, 0xb0, 0xcd, 0x6e, 0x8d, 0xd4, 0x92, 0x9d, 0x76, 0x2c, 0xb5, 0xd3, 0xf2, 0x20, - 0xfc, 0x2c, 0xc7, 0x9d, 0x36, 0x42, 0x9b, 0x75, 0x60, 0x6f, 0x8c, 0xa8, 0x4e, 0x4d, 0x6a, 0xb9, - 0x5d, 0x3d, 0x99, 0xf7, 0x10, 0x28, 0x69, 0x3b, 0x0a, 0x59, 0x15, 0xe8, 0xaf, 0x05, 0x4b, 0x8b, - 0x94, 0xc7, 0xed, 0xd7, 0xc3, 0xe7, 0x6e, 0xd6, 0xe8, 0x6d, 0xd1, 0x30, 0x39, 0xa8, 0x29, 0x73, - 0xce, 0x76, 0x6e, 0xcf, 0xd3, 0x4a, 0x95, 0x76, 0xbb, 0x50, 0xef, 0xcb, 0xd6, 0x97, 0xb1, 0xb3, - 0x90, 0x65, 0x1c, 0x76, 0x18, 0xc9, 0x57, 0xa2, 0x64, 0x9b, 0x97, 0xbb, 0x59, 0xb7, 0xdf, 0xe6, - 0x62, 0xdd, 0x30, 0xc5, 0xfb, 0x0f, 0x82, 0x97, 0x73, 0x61, 0x0a, 0x4d, 0xcf, 0xc1, 0xce, 0x26, - 0xf1, 0xd6, 0x5e, 0xc6, 0x2d, 0x9e, 0x1b, 0xa1, 0x96, 0xbf, 0x94, 0x7d, 0xf5, 0x8a, 0x2d, 0x6b, - 0x86, 0x63, 0xee, 0x38, 0x35, 0x6f, 0xc2, 0x3e, 0x97, 0x45, 0x2a, 0x45, 0xed, 0xab, 0x24, 0xcf, - 0xb0, 0x37, 0xd2, 0x3b, 0xd6, 0x3b, 0xde, 0xa7, 0xef, 0x75, 0x9b, 0x9a, 0xe5, 0x25, 0x69, 0xa0, - 0x2e, 0x89, 0x76, 0x9a, 0x02, 0x4c, 0x24, 0x63, 0x14, 0x06, 0xa2, 0x78, 0x88, 0xc5, 0x8b, 0x16, - 0x62, 0x9a, 0x14, 0xda, 0xd4, 0xe4, 0x8e, 0x6c, 0x37, 0xd1, 0xd6, 0x53, 0xe6, 0x5c, 0xc7, 0x82, - 0x1c, 0x83, 0x21, 0x21, 0x88, 0x61, 0xce, 0xb5, 0x28, 0x81, 0x5d, 0x79, 0xf2, 0x22, 0x09, 0xea, - 0xb0, 0x2f, 0x15, 0x47, 0x97, 0xf9, 0x5f, 0x13, 0x77, 0xdd, 0x0b, 0x74, 0x29, 0xcc, 0x87, 0xce, - 0x01, 0x74, 0x7a, 0x8f, 0xfe, 0x01, 0xc1, 0x58, 0x76, 0x6c, 0xc1, 0x6b, 0x12, 0x86, 0x6d, 0xba, - 0x14, 0x1d, 0x96, 0x92, 0x60, 0xcf, 0xb6, 0xea, 0xd3, 0x07, 0xed, 0x56, 0xdf, 0x2e, 0xb6, 0xb0, - 0xc9, 0x9f, 0x76, 0xc3, 0x26, 0x86, 0x19, 0x7f, 0x87, 0x60, 0x8b, 0xb8, 0x6e, 0xe2, 0xf1, 0xd4, - 0x7a, 0x4f, 0xf9, 0xc1, 0x40, 0x39, 0xbc, 0x06, 0x4b, 0xce, 0x5c, 0x3d, 0xfb, 0xc9, 0xcf, 0x7f, - 0xde, 0x2b, 0x4c, 0xe1, 0xb7, 0x48, 0xca, 0xaf, 0x1d, 0xfc, 0x87, 0x11, 0x39, 0x6f, 0x91, 0x95, - 0x48, 0xe7, 0x06, 0x09, 0xd4, 0xf7, 0xc8, 0x8a, 0xc8, 0x49, 0x03, 0xdf, 0x45, 0xd0, 0x2f, 0xa7, - 0x3c, 0xbc, 0x3a, 0x00, 0x79, 0xb6, 0x95, 0x23, 0x6b, 0x31, 0x15, 0x60, 0x8f, 0x30, 0xb0, 0xaf, - 0x60, 0x75, 0x75, 0xb0, 0xf8, 0x47, 0x04, 0xb8, 0x75, 0xfe, 0xc4, 0xc7, 0x73, 0xb6, 0xcb, 0x1a, - 0x9c, 0x95, 0x13, 0xed, 0x39, 0x09, 0xb4, 0xd3, 0x0c, 0xed, 0x69, 0xfc, 0x46, 0x0e, 0xda, 0xd0, - 0x3b, 0x50, 0x37, 0x7c, 0x68, 0x44, 0x34, 0x7e, 0x0d, 0x68, 0xb4, 0x4c, 0x80, 0xb9, 0x34, 0xb2, - 0x46, 0xd1, 0x5c, 0x1a, 0x99, 0x43, 0xa6, 0x7a, 0x99, 0xd1, 0xb8, 0x80, 0xcf, 0x75, 0x78, 0x42, - 0x48, 0x7c, 0x3e, 0xc5, 0x5f, 0x15, 0x60, 0x38, 0x75, 0x8e, 0xc2, 0x27, 0x57, 0x47, 0x99, 0x36, - 0x28, 0x2a, 0xaf, 0xb7, 0xed, 0x27, 0x08, 0xde, 0x45, 0x8c, 0xe1, 0x1d, 0x84, 0x3f, 0x45, 0x1d, - 0x73, 0x4c, 0x4e, 0x7e, 0x44, 0x8e, 0x90, 0x64, 0xa5, 0x69, 0x18, 0x6d, 0x10, 0xde, 0x20, 0x62, - 0x2f, 0xf8, 0x42, 0x03, 0x3f, 0x41, 0xb0, 0xb3, 0xf9, 0x46, 0x8f, 0x27, 0xb2, 0xd9, 0x65, 0x4c, - 0x6c, 0xca, 0x64, 0x3b, 0x2e, 0x42, 0x0b, 0xca, 0xa4, 0x28, 0xe1, 0x8f, 0x3a, 0x15, 0xa2, 0xe5, - 0x8b, 0xd8, 0x23, 0x2b, 0xb2, 0xbb, 0x36, 0xf0, 0x23, 0x04, 0xbb, 0x5a, 0x86, 0x16, 0xdc, 0x06, - 0xe0, 0xb0, 0x34, 0x8f, 0xb7, 0xe5, 0x23, 0x58, 0x5e, 0x67, 0x2c, 0x2f, 0x63, 0x7d, 0xfd, 0x59, - 0xe2, 0x5f, 0x10, 0xbc, 0x94, 0x18, 0x1a, 0xb0, 0xb6, 0x1a, 0xc4, 0xe4, 0x3c, 0xa3, 0x90, 0x35, - 0xdb, 0x0b, 0x3a, 0x65, 0x46, 0xe7, 0x43, 0x7c, 0x7d, 0x9d, 0xe8, 0xd4, 0x78, 0xfc, 0x44, 0xc6, - 0x9e, 0x23, 0x18, 0x4e, 0xbd, 0xa9, 0xe6, 0xd5, 0x6b, 0xde, 0x9c, 0x92, 0x57, 0xaf, 0xb9, 0x53, - 0x86, 0x7a, 0x83, 0xd1, 0xbd, 0x8a, 0xdf, 0x5f, 0x27, 0xba, 0x86, 0x39, 0x97, 0xa0, 0xfa, 0x37, - 0x82, 0xdd, 0xe9, 0x97, 0x72, 0xdc, 0x2e, 0xe6, 0xf0, 0x98, 0x9e, 0x6a, 0xdf, 0x51, 0xb0, 0x2d, - 0x31, 0xb6, 0xd7, 0xf0, 0x07, 0xeb, 0xc7, 0x36, 0xc9, 0xe9, 0xf3, 0x02, 0xec, 0x6a, 0xb9, 0xf1, - 0xe6, 0xd5, 0x62, 0xd6, 0xbd, 0x3d, 0xaf, 0x16, 0x33, 0xaf, 0xd4, 0xeb, 0xda, 0x7d, 0xd3, 0x9a, - 0x4e, 0xce, 0x44, 0xd0, 0x20, 0xf5, 0x10, 0x56, 0xc9, 0x15, 0xc4, 0xff, 0x45, 0xb0, 0x3d, 0x79, - 0xfb, 0xc5, 0x64, 0x2d, 0xbc, 0x62, 0xf7, 0x75, 0xe5, 0xd8, 0xda, 0x1d, 0x84, 0x0a, 0x1f, 0x73, - 0x15, 0x56, 0xf0, 0x72, 0x17, 0x35, 0x48, 0x0c, 0x01, 0x09, 0xf2, 0x41, 0x09, 0xe0, 0xdf, 0x10, - 0x0c, 0xa6, 0x5c, 0x92, 0x71, 0xce, 0xb5, 0x21, 0xfb, 0xbe, 0xae, 0xbc, 0xd6, 0xa6, 0x97, 0x10, - 0xe2, 0x0a, 0xd3, 0xe1, 0x5d, 0x7c, 0xbe, 0x53, 0x1d, 0x12, 0xf7, 0xf9, 0x33, 0xfa, 0x83, 0xa7, - 0x45, 0xf4, 0xf0, 0x69, 0x11, 0x3d, 0x79, 0x5a, 0x44, 0x5f, 0x3c, 0x2b, 0xf6, 0x3c, 0x7c, 0x56, - 0xec, 0x79, 0xf4, 0xac, 0xd8, 0x73, 0xfd, 0x54, 0xd5, 0xf2, 0x67, 0xeb, 0x65, 0xcd, 0x74, 0x16, - 0x88, 0xf8, 0xe7, 0x20, 0xff, 0x73, 0xd4, 0xab, 0xcc, 0x91, 0xa5, 0x08, 0xc6, 0xb1, 0x13, 0x47, - 0x25, 0x12, 0x7f, 0xd9, 0xa5, 0x5e, 0x79, 0x33, 0xfb, 0x1d, 0xf7, 0xf8, 0x7f, 0x01, 0x00, 0x00, - 0xff, 0xff, 0xce, 0x1d, 0x1b, 0xcd, 0xab, 0x1c, 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 { - // Channel queries an IBC Channel. - Channel(ctx context.Context, in *QueryChannelRequest, opts ...grpc.CallOption) (*QueryChannelResponse, error) - // Channels queries all the IBC channels of a chain. - Channels(ctx context.Context, in *QueryChannelsRequest, opts ...grpc.CallOption) (*QueryChannelsResponse, error) - // ConnectionChannels queries all the channels associated with a connection - // end. - ConnectionChannels(ctx context.Context, in *QueryConnectionChannelsRequest, opts ...grpc.CallOption) (*QueryConnectionChannelsResponse, error) - // ChannelClientState queries for the client state for the channel associated - // with the provided channel identifiers. - ChannelClientState(ctx context.Context, in *QueryChannelClientStateRequest, opts ...grpc.CallOption) (*QueryChannelClientStateResponse, error) - // ChannelConsensusState queries for the consensus state for the channel - // associated with the provided channel identifiers. - ChannelConsensusState(ctx context.Context, in *QueryChannelConsensusStateRequest, opts ...grpc.CallOption) (*QueryChannelConsensusStateResponse, error) - // PacketCommitment queries a stored packet commitment hash. - PacketCommitment(ctx context.Context, in *QueryPacketCommitmentRequest, opts ...grpc.CallOption) (*QueryPacketCommitmentResponse, error) - // PacketCommitments returns all the packet commitments hashes associated - // with a channel. - PacketCommitments(ctx context.Context, in *QueryPacketCommitmentsRequest, opts ...grpc.CallOption) (*QueryPacketCommitmentsResponse, error) - // PacketReceipt queries if a given packet sequence has been received on the queried chain - PacketReceipt(ctx context.Context, in *QueryPacketReceiptRequest, opts ...grpc.CallOption) (*QueryPacketReceiptResponse, error) - // PacketAcknowledgement queries a stored packet acknowledgement hash. - PacketAcknowledgement(ctx context.Context, in *QueryPacketAcknowledgementRequest, opts ...grpc.CallOption) (*QueryPacketAcknowledgementResponse, error) - // PacketAcknowledgements returns all the packet acknowledgements associated - // with a channel. - PacketAcknowledgements(ctx context.Context, in *QueryPacketAcknowledgementsRequest, opts ...grpc.CallOption) (*QueryPacketAcknowledgementsResponse, error) - // UnreceivedPackets returns all the unreceived IBC packets associated with a - // channel and sequences. - UnreceivedPackets(ctx context.Context, in *QueryUnreceivedPacketsRequest, opts ...grpc.CallOption) (*QueryUnreceivedPacketsResponse, error) - // UnreceivedAcks returns all the unreceived IBC acknowledgements associated with a - // channel and sequences. - UnreceivedAcks(ctx context.Context, in *QueryUnreceivedAcksRequest, opts ...grpc.CallOption) (*QueryUnreceivedAcksResponse, error) - // NextSequenceReceive returns the next receive sequence for a given channel. - NextSequenceReceive(ctx context.Context, in *QueryNextSequenceReceiveRequest, opts ...grpc.CallOption) (*QueryNextSequenceReceiveResponse, error) -} - -type queryClient struct { - cc grpc1.ClientConn -} - -func NewQueryClient(cc grpc1.ClientConn) QueryClient { - return &queryClient{cc} -} - -func (c *queryClient) Channel(ctx context.Context, in *QueryChannelRequest, opts ...grpc.CallOption) (*QueryChannelResponse, error) { - out := new(QueryChannelResponse) - err := c.cc.Invoke(ctx, "/ibc.core.channel.v1.Query/Channel", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *queryClient) Channels(ctx context.Context, in *QueryChannelsRequest, opts ...grpc.CallOption) (*QueryChannelsResponse, error) { - out := new(QueryChannelsResponse) - err := c.cc.Invoke(ctx, "/ibc.core.channel.v1.Query/Channels", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *queryClient) ConnectionChannels(ctx context.Context, in *QueryConnectionChannelsRequest, opts ...grpc.CallOption) (*QueryConnectionChannelsResponse, error) { - out := new(QueryConnectionChannelsResponse) - err := c.cc.Invoke(ctx, "/ibc.core.channel.v1.Query/ConnectionChannels", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *queryClient) ChannelClientState(ctx context.Context, in *QueryChannelClientStateRequest, opts ...grpc.CallOption) (*QueryChannelClientStateResponse, error) { - out := new(QueryChannelClientStateResponse) - err := c.cc.Invoke(ctx, "/ibc.core.channel.v1.Query/ChannelClientState", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *queryClient) ChannelConsensusState(ctx context.Context, in *QueryChannelConsensusStateRequest, opts ...grpc.CallOption) (*QueryChannelConsensusStateResponse, error) { - out := new(QueryChannelConsensusStateResponse) - err := c.cc.Invoke(ctx, "/ibc.core.channel.v1.Query/ChannelConsensusState", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *queryClient) PacketCommitment(ctx context.Context, in *QueryPacketCommitmentRequest, opts ...grpc.CallOption) (*QueryPacketCommitmentResponse, error) { - out := new(QueryPacketCommitmentResponse) - err := c.cc.Invoke(ctx, "/ibc.core.channel.v1.Query/PacketCommitment", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *queryClient) PacketCommitments(ctx context.Context, in *QueryPacketCommitmentsRequest, opts ...grpc.CallOption) (*QueryPacketCommitmentsResponse, error) { - out := new(QueryPacketCommitmentsResponse) - err := c.cc.Invoke(ctx, "/ibc.core.channel.v1.Query/PacketCommitments", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *queryClient) PacketReceipt(ctx context.Context, in *QueryPacketReceiptRequest, opts ...grpc.CallOption) (*QueryPacketReceiptResponse, error) { - out := new(QueryPacketReceiptResponse) - err := c.cc.Invoke(ctx, "/ibc.core.channel.v1.Query/PacketReceipt", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *queryClient) PacketAcknowledgement(ctx context.Context, in *QueryPacketAcknowledgementRequest, opts ...grpc.CallOption) (*QueryPacketAcknowledgementResponse, error) { - out := new(QueryPacketAcknowledgementResponse) - err := c.cc.Invoke(ctx, "/ibc.core.channel.v1.Query/PacketAcknowledgement", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *queryClient) PacketAcknowledgements(ctx context.Context, in *QueryPacketAcknowledgementsRequest, opts ...grpc.CallOption) (*QueryPacketAcknowledgementsResponse, error) { - out := new(QueryPacketAcknowledgementsResponse) - err := c.cc.Invoke(ctx, "/ibc.core.channel.v1.Query/PacketAcknowledgements", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *queryClient) UnreceivedPackets(ctx context.Context, in *QueryUnreceivedPacketsRequest, opts ...grpc.CallOption) (*QueryUnreceivedPacketsResponse, error) { - out := new(QueryUnreceivedPacketsResponse) - err := c.cc.Invoke(ctx, "/ibc.core.channel.v1.Query/UnreceivedPackets", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *queryClient) UnreceivedAcks(ctx context.Context, in *QueryUnreceivedAcksRequest, opts ...grpc.CallOption) (*QueryUnreceivedAcksResponse, error) { - out := new(QueryUnreceivedAcksResponse) - err := c.cc.Invoke(ctx, "/ibc.core.channel.v1.Query/UnreceivedAcks", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *queryClient) NextSequenceReceive(ctx context.Context, in *QueryNextSequenceReceiveRequest, opts ...grpc.CallOption) (*QueryNextSequenceReceiveResponse, error) { - out := new(QueryNextSequenceReceiveResponse) - err := c.cc.Invoke(ctx, "/ibc.core.channel.v1.Query/NextSequenceReceive", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// QueryServer is the server API for Query service. -type QueryServer interface { - // Channel queries an IBC Channel. - Channel(context.Context, *QueryChannelRequest) (*QueryChannelResponse, error) - // Channels queries all the IBC channels of a chain. - Channels(context.Context, *QueryChannelsRequest) (*QueryChannelsResponse, error) - // ConnectionChannels queries all the channels associated with a connection - // end. - ConnectionChannels(context.Context, *QueryConnectionChannelsRequest) (*QueryConnectionChannelsResponse, error) - // ChannelClientState queries for the client state for the channel associated - // with the provided channel identifiers. - ChannelClientState(context.Context, *QueryChannelClientStateRequest) (*QueryChannelClientStateResponse, error) - // ChannelConsensusState queries for the consensus state for the channel - // associated with the provided channel identifiers. - ChannelConsensusState(context.Context, *QueryChannelConsensusStateRequest) (*QueryChannelConsensusStateResponse, error) - // PacketCommitment queries a stored packet commitment hash. - PacketCommitment(context.Context, *QueryPacketCommitmentRequest) (*QueryPacketCommitmentResponse, error) - // PacketCommitments returns all the packet commitments hashes associated - // with a channel. - PacketCommitments(context.Context, *QueryPacketCommitmentsRequest) (*QueryPacketCommitmentsResponse, error) - // PacketReceipt queries if a given packet sequence has been received on the queried chain - PacketReceipt(context.Context, *QueryPacketReceiptRequest) (*QueryPacketReceiptResponse, error) - // PacketAcknowledgement queries a stored packet acknowledgement hash. - PacketAcknowledgement(context.Context, *QueryPacketAcknowledgementRequest) (*QueryPacketAcknowledgementResponse, error) - // PacketAcknowledgements returns all the packet acknowledgements associated - // with a channel. - PacketAcknowledgements(context.Context, *QueryPacketAcknowledgementsRequest) (*QueryPacketAcknowledgementsResponse, error) - // UnreceivedPackets returns all the unreceived IBC packets associated with a - // channel and sequences. - UnreceivedPackets(context.Context, *QueryUnreceivedPacketsRequest) (*QueryUnreceivedPacketsResponse, error) - // UnreceivedAcks returns all the unreceived IBC acknowledgements associated with a - // channel and sequences. - UnreceivedAcks(context.Context, *QueryUnreceivedAcksRequest) (*QueryUnreceivedAcksResponse, error) - // NextSequenceReceive returns the next receive sequence for a given channel. - NextSequenceReceive(context.Context, *QueryNextSequenceReceiveRequest) (*QueryNextSequenceReceiveResponse, error) -} - -// UnimplementedQueryServer can be embedded to have forward compatible implementations. -type UnimplementedQueryServer struct { -} - -func (*UnimplementedQueryServer) Channel(ctx context.Context, req *QueryChannelRequest) (*QueryChannelResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method Channel not implemented") -} -func (*UnimplementedQueryServer) Channels(ctx context.Context, req *QueryChannelsRequest) (*QueryChannelsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method Channels not implemented") -} -func (*UnimplementedQueryServer) ConnectionChannels(ctx context.Context, req *QueryConnectionChannelsRequest) (*QueryConnectionChannelsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ConnectionChannels not implemented") -} -func (*UnimplementedQueryServer) ChannelClientState(ctx context.Context, req *QueryChannelClientStateRequest) (*QueryChannelClientStateResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ChannelClientState not implemented") -} -func (*UnimplementedQueryServer) ChannelConsensusState(ctx context.Context, req *QueryChannelConsensusStateRequest) (*QueryChannelConsensusStateResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ChannelConsensusState not implemented") -} -func (*UnimplementedQueryServer) PacketCommitment(ctx context.Context, req *QueryPacketCommitmentRequest) (*QueryPacketCommitmentResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method PacketCommitment not implemented") -} -func (*UnimplementedQueryServer) PacketCommitments(ctx context.Context, req *QueryPacketCommitmentsRequest) (*QueryPacketCommitmentsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method PacketCommitments not implemented") -} -func (*UnimplementedQueryServer) PacketReceipt(ctx context.Context, req *QueryPacketReceiptRequest) (*QueryPacketReceiptResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method PacketReceipt not implemented") -} -func (*UnimplementedQueryServer) PacketAcknowledgement(ctx context.Context, req *QueryPacketAcknowledgementRequest) (*QueryPacketAcknowledgementResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method PacketAcknowledgement not implemented") -} -func (*UnimplementedQueryServer) PacketAcknowledgements(ctx context.Context, req *QueryPacketAcknowledgementsRequest) (*QueryPacketAcknowledgementsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method PacketAcknowledgements not implemented") -} -func (*UnimplementedQueryServer) UnreceivedPackets(ctx context.Context, req *QueryUnreceivedPacketsRequest) (*QueryUnreceivedPacketsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method UnreceivedPackets not implemented") -} -func (*UnimplementedQueryServer) UnreceivedAcks(ctx context.Context, req *QueryUnreceivedAcksRequest) (*QueryUnreceivedAcksResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method UnreceivedAcks not implemented") -} -func (*UnimplementedQueryServer) NextSequenceReceive(ctx context.Context, req *QueryNextSequenceReceiveRequest) (*QueryNextSequenceReceiveResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method NextSequenceReceive not implemented") -} - -func RegisterQueryServer(s grpc1.Server, srv QueryServer) { - s.RegisterService(&_Query_serviceDesc, srv) -} - -func _Query_Channel_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryChannelRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(QueryServer).Channel(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.channel.v1.Query/Channel", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).Channel(ctx, req.(*QueryChannelRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Query_Channels_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryChannelsRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(QueryServer).Channels(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.channel.v1.Query/Channels", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).Channels(ctx, req.(*QueryChannelsRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Query_ConnectionChannels_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryConnectionChannelsRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(QueryServer).ConnectionChannels(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.channel.v1.Query/ConnectionChannels", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).ConnectionChannels(ctx, req.(*QueryConnectionChannelsRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Query_ChannelClientState_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryChannelClientStateRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(QueryServer).ChannelClientState(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.channel.v1.Query/ChannelClientState", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).ChannelClientState(ctx, req.(*QueryChannelClientStateRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Query_ChannelConsensusState_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryChannelConsensusStateRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(QueryServer).ChannelConsensusState(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.channel.v1.Query/ChannelConsensusState", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).ChannelConsensusState(ctx, req.(*QueryChannelConsensusStateRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Query_PacketCommitment_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryPacketCommitmentRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(QueryServer).PacketCommitment(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.channel.v1.Query/PacketCommitment", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).PacketCommitment(ctx, req.(*QueryPacketCommitmentRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Query_PacketCommitments_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryPacketCommitmentsRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(QueryServer).PacketCommitments(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.channel.v1.Query/PacketCommitments", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).PacketCommitments(ctx, req.(*QueryPacketCommitmentsRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Query_PacketReceipt_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryPacketReceiptRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(QueryServer).PacketReceipt(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.channel.v1.Query/PacketReceipt", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).PacketReceipt(ctx, req.(*QueryPacketReceiptRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Query_PacketAcknowledgement_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryPacketAcknowledgementRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(QueryServer).PacketAcknowledgement(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.channel.v1.Query/PacketAcknowledgement", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).PacketAcknowledgement(ctx, req.(*QueryPacketAcknowledgementRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Query_PacketAcknowledgements_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryPacketAcknowledgementsRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(QueryServer).PacketAcknowledgements(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.channel.v1.Query/PacketAcknowledgements", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).PacketAcknowledgements(ctx, req.(*QueryPacketAcknowledgementsRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Query_UnreceivedPackets_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryUnreceivedPacketsRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(QueryServer).UnreceivedPackets(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.channel.v1.Query/UnreceivedPackets", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).UnreceivedPackets(ctx, req.(*QueryUnreceivedPacketsRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Query_UnreceivedAcks_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryUnreceivedAcksRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(QueryServer).UnreceivedAcks(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.channel.v1.Query/UnreceivedAcks", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).UnreceivedAcks(ctx, req.(*QueryUnreceivedAcksRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Query_NextSequenceReceive_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryNextSequenceReceiveRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(QueryServer).NextSequenceReceive(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.channel.v1.Query/NextSequenceReceive", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).NextSequenceReceive(ctx, req.(*QueryNextSequenceReceiveRequest)) - } - return interceptor(ctx, in, info, handler) -} - -var _Query_serviceDesc = grpc.ServiceDesc{ - ServiceName: "ibc.core.channel.v1.Query", - HandlerType: (*QueryServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "Channel", - Handler: _Query_Channel_Handler, - }, - { - MethodName: "Channels", - Handler: _Query_Channels_Handler, - }, - { - MethodName: "ConnectionChannels", - Handler: _Query_ConnectionChannels_Handler, - }, - { - MethodName: "ChannelClientState", - Handler: _Query_ChannelClientState_Handler, - }, - { - MethodName: "ChannelConsensusState", - Handler: _Query_ChannelConsensusState_Handler, - }, - { - MethodName: "PacketCommitment", - Handler: _Query_PacketCommitment_Handler, - }, - { - MethodName: "PacketCommitments", - Handler: _Query_PacketCommitments_Handler, - }, - { - MethodName: "PacketReceipt", - Handler: _Query_PacketReceipt_Handler, - }, - { - MethodName: "PacketAcknowledgement", - Handler: _Query_PacketAcknowledgement_Handler, - }, - { - MethodName: "PacketAcknowledgements", - Handler: _Query_PacketAcknowledgements_Handler, - }, - { - MethodName: "UnreceivedPackets", - Handler: _Query_UnreceivedPackets_Handler, - }, - { - MethodName: "UnreceivedAcks", - Handler: _Query_UnreceivedAcks_Handler, - }, - { - MethodName: "NextSequenceReceive", - Handler: _Query_NextSequenceReceive_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "ibc/core/channel/v1/query.proto", -} - -func (m *QueryChannelRequest) 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 *QueryChannelRequest) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryChannelRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.ChannelId) > 0 { - i -= len(m.ChannelId) - copy(dAtA[i:], m.ChannelId) - i = encodeVarintQuery(dAtA, i, uint64(len(m.ChannelId))) - i-- - dAtA[i] = 0x12 - } - if len(m.PortId) > 0 { - i -= len(m.PortId) - copy(dAtA[i:], m.PortId) - i = encodeVarintQuery(dAtA, i, uint64(len(m.PortId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *QueryChannelResponse) 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 *QueryChannelResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryChannelResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - { - size, err := m.ProofHeight.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - if len(m.Proof) > 0 { - i -= len(m.Proof) - copy(dAtA[i:], m.Proof) - i = encodeVarintQuery(dAtA, i, uint64(len(m.Proof))) - i-- - dAtA[i] = 0x12 - } - if m.Channel != nil { - { - size, err := m.Channel.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 *QueryChannelsRequest) 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 *QueryChannelsRequest) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryChannelsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.Pagination != nil { - { - size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *QueryChannelsResponse) 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 *QueryChannelsResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryChannelsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - { - size, err := m.Height.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - 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.Channels) > 0 { - for iNdEx := len(m.Channels) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.Channels[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 *QueryConnectionChannelsRequest) 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 *QueryConnectionChannelsRequest) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryConnectionChannelsRequest) 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.Connection) > 0 { - i -= len(m.Connection) - copy(dAtA[i:], m.Connection) - i = encodeVarintQuery(dAtA, i, uint64(len(m.Connection))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *QueryConnectionChannelsResponse) 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 *QueryConnectionChannelsResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryConnectionChannelsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - { - size, err := m.Height.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - 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.Channels) > 0 { - for iNdEx := len(m.Channels) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.Channels[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 *QueryChannelClientStateRequest) 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 *QueryChannelClientStateRequest) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryChannelClientStateRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.ChannelId) > 0 { - i -= len(m.ChannelId) - copy(dAtA[i:], m.ChannelId) - i = encodeVarintQuery(dAtA, i, uint64(len(m.ChannelId))) - i-- - dAtA[i] = 0x12 - } - if len(m.PortId) > 0 { - i -= len(m.PortId) - copy(dAtA[i:], m.PortId) - i = encodeVarintQuery(dAtA, i, uint64(len(m.PortId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *QueryChannelClientStateResponse) 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 *QueryChannelClientStateResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryChannelClientStateResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - { - size, err := m.ProofHeight.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - if len(m.Proof) > 0 { - i -= len(m.Proof) - copy(dAtA[i:], m.Proof) - i = encodeVarintQuery(dAtA, i, uint64(len(m.Proof))) - i-- - dAtA[i] = 0x12 - } - if m.IdentifiedClientState != nil { - { - size, err := m.IdentifiedClientState.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 *QueryChannelConsensusStateRequest) 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 *QueryChannelConsensusStateRequest) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryChannelConsensusStateRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.RevisionHeight != 0 { - i = encodeVarintQuery(dAtA, i, uint64(m.RevisionHeight)) - i-- - dAtA[i] = 0x20 - } - if m.RevisionNumber != 0 { - i = encodeVarintQuery(dAtA, i, uint64(m.RevisionNumber)) - i-- - dAtA[i] = 0x18 - } - if len(m.ChannelId) > 0 { - i -= len(m.ChannelId) - copy(dAtA[i:], m.ChannelId) - i = encodeVarintQuery(dAtA, i, uint64(len(m.ChannelId))) - i-- - dAtA[i] = 0x12 - } - if len(m.PortId) > 0 { - i -= len(m.PortId) - copy(dAtA[i:], m.PortId) - i = encodeVarintQuery(dAtA, i, uint64(len(m.PortId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *QueryChannelConsensusStateResponse) 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 *QueryChannelConsensusStateResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryChannelConsensusStateResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - { - size, err := m.ProofHeight.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x22 - if len(m.Proof) > 0 { - i -= len(m.Proof) - copy(dAtA[i:], m.Proof) - i = encodeVarintQuery(dAtA, i, uint64(len(m.Proof))) - i-- - dAtA[i] = 0x1a - } - if len(m.ClientId) > 0 { - i -= len(m.ClientId) - copy(dAtA[i:], m.ClientId) - i = encodeVarintQuery(dAtA, i, uint64(len(m.ClientId))) - i-- - dAtA[i] = 0x12 - } - if m.ConsensusState != nil { - { - size, err := m.ConsensusState.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 *QueryPacketCommitmentRequest) 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 *QueryPacketCommitmentRequest) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryPacketCommitmentRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.Sequence != 0 { - i = encodeVarintQuery(dAtA, i, uint64(m.Sequence)) - i-- - dAtA[i] = 0x18 - } - if len(m.ChannelId) > 0 { - i -= len(m.ChannelId) - copy(dAtA[i:], m.ChannelId) - i = encodeVarintQuery(dAtA, i, uint64(len(m.ChannelId))) - i-- - dAtA[i] = 0x12 - } - if len(m.PortId) > 0 { - i -= len(m.PortId) - copy(dAtA[i:], m.PortId) - i = encodeVarintQuery(dAtA, i, uint64(len(m.PortId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *QueryPacketCommitmentResponse) 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 *QueryPacketCommitmentResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryPacketCommitmentResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - { - size, err := m.ProofHeight.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - if len(m.Proof) > 0 { - i -= len(m.Proof) - copy(dAtA[i:], m.Proof) - i = encodeVarintQuery(dAtA, i, uint64(len(m.Proof))) - i-- - dAtA[i] = 0x12 - } - if len(m.Commitment) > 0 { - i -= len(m.Commitment) - copy(dAtA[i:], m.Commitment) - i = encodeVarintQuery(dAtA, i, uint64(len(m.Commitment))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *QueryPacketCommitmentsRequest) 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 *QueryPacketCommitmentsRequest) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryPacketCommitmentsRequest) 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.ChannelId) > 0 { - i -= len(m.ChannelId) - copy(dAtA[i:], m.ChannelId) - i = encodeVarintQuery(dAtA, i, uint64(len(m.ChannelId))) - i-- - dAtA[i] = 0x12 - } - if len(m.PortId) > 0 { - i -= len(m.PortId) - copy(dAtA[i:], m.PortId) - i = encodeVarintQuery(dAtA, i, uint64(len(m.PortId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *QueryPacketCommitmentsResponse) 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 *QueryPacketCommitmentsResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryPacketCommitmentsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - { - size, err := m.Height.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - 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.Commitments) > 0 { - for iNdEx := len(m.Commitments) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.Commitments[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 *QueryPacketReceiptRequest) 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 *QueryPacketReceiptRequest) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryPacketReceiptRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.Sequence != 0 { - i = encodeVarintQuery(dAtA, i, uint64(m.Sequence)) - i-- - dAtA[i] = 0x18 - } - if len(m.ChannelId) > 0 { - i -= len(m.ChannelId) - copy(dAtA[i:], m.ChannelId) - i = encodeVarintQuery(dAtA, i, uint64(len(m.ChannelId))) - i-- - dAtA[i] = 0x12 - } - if len(m.PortId) > 0 { - i -= len(m.PortId) - copy(dAtA[i:], m.PortId) - i = encodeVarintQuery(dAtA, i, uint64(len(m.PortId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *QueryPacketReceiptResponse) 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 *QueryPacketReceiptResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryPacketReceiptResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - { - size, err := m.ProofHeight.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x22 - if len(m.Proof) > 0 { - i -= len(m.Proof) - copy(dAtA[i:], m.Proof) - i = encodeVarintQuery(dAtA, i, uint64(len(m.Proof))) - i-- - dAtA[i] = 0x1a - } - if m.Received { - i-- - if m.Received { - dAtA[i] = 1 - } else { - dAtA[i] = 0 - } - i-- - dAtA[i] = 0x10 - } - return len(dAtA) - i, nil -} - -func (m *QueryPacketAcknowledgementRequest) 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 *QueryPacketAcknowledgementRequest) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryPacketAcknowledgementRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.Sequence != 0 { - i = encodeVarintQuery(dAtA, i, uint64(m.Sequence)) - i-- - dAtA[i] = 0x18 - } - if len(m.ChannelId) > 0 { - i -= len(m.ChannelId) - copy(dAtA[i:], m.ChannelId) - i = encodeVarintQuery(dAtA, i, uint64(len(m.ChannelId))) - i-- - dAtA[i] = 0x12 - } - if len(m.PortId) > 0 { - i -= len(m.PortId) - copy(dAtA[i:], m.PortId) - i = encodeVarintQuery(dAtA, i, uint64(len(m.PortId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *QueryPacketAcknowledgementResponse) 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 *QueryPacketAcknowledgementResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryPacketAcknowledgementResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - { - size, err := m.ProofHeight.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - if len(m.Proof) > 0 { - i -= len(m.Proof) - copy(dAtA[i:], m.Proof) - i = encodeVarintQuery(dAtA, i, uint64(len(m.Proof))) - i-- - dAtA[i] = 0x12 - } - if len(m.Acknowledgement) > 0 { - i -= len(m.Acknowledgement) - copy(dAtA[i:], m.Acknowledgement) - i = encodeVarintQuery(dAtA, i, uint64(len(m.Acknowledgement))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *QueryPacketAcknowledgementsRequest) 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 *QueryPacketAcknowledgementsRequest) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryPacketAcknowledgementsRequest) 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.ChannelId) > 0 { - i -= len(m.ChannelId) - copy(dAtA[i:], m.ChannelId) - i = encodeVarintQuery(dAtA, i, uint64(len(m.ChannelId))) - i-- - dAtA[i] = 0x12 - } - if len(m.PortId) > 0 { - i -= len(m.PortId) - copy(dAtA[i:], m.PortId) - i = encodeVarintQuery(dAtA, i, uint64(len(m.PortId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *QueryPacketAcknowledgementsResponse) 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 *QueryPacketAcknowledgementsResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryPacketAcknowledgementsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - { - size, err := m.Height.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - 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.Acknowledgements) > 0 { - for iNdEx := len(m.Acknowledgements) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.Acknowledgements[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 *QueryUnreceivedPacketsRequest) 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 *QueryUnreceivedPacketsRequest) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryUnreceivedPacketsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.PacketCommitmentSequences) > 0 { - dAtA23 := make([]byte, len(m.PacketCommitmentSequences)*10) - var j22 int - for _, num := range m.PacketCommitmentSequences { - for num >= 1<<7 { - dAtA23[j22] = uint8(uint64(num)&0x7f | 0x80) - num >>= 7 - j22++ - } - dAtA23[j22] = uint8(num) - j22++ - } - i -= j22 - copy(dAtA[i:], dAtA23[:j22]) - i = encodeVarintQuery(dAtA, i, uint64(j22)) - i-- - dAtA[i] = 0x1a - } - if len(m.ChannelId) > 0 { - i -= len(m.ChannelId) - copy(dAtA[i:], m.ChannelId) - i = encodeVarintQuery(dAtA, i, uint64(len(m.ChannelId))) - i-- - dAtA[i] = 0x12 - } - if len(m.PortId) > 0 { - i -= len(m.PortId) - copy(dAtA[i:], m.PortId) - i = encodeVarintQuery(dAtA, i, uint64(len(m.PortId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *QueryUnreceivedPacketsResponse) 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 *QueryUnreceivedPacketsResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryUnreceivedPacketsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - { - size, err := m.Height.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - if len(m.Sequences) > 0 { - dAtA26 := make([]byte, len(m.Sequences)*10) - var j25 int - for _, num := range m.Sequences { - for num >= 1<<7 { - dAtA26[j25] = uint8(uint64(num)&0x7f | 0x80) - num >>= 7 - j25++ - } - dAtA26[j25] = uint8(num) - j25++ - } - i -= j25 - copy(dAtA[i:], dAtA26[:j25]) - i = encodeVarintQuery(dAtA, i, uint64(j25)) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *QueryUnreceivedAcksRequest) 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 *QueryUnreceivedAcksRequest) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryUnreceivedAcksRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.PacketAckSequences) > 0 { - dAtA28 := make([]byte, len(m.PacketAckSequences)*10) - var j27 int - for _, num := range m.PacketAckSequences { - for num >= 1<<7 { - dAtA28[j27] = uint8(uint64(num)&0x7f | 0x80) - num >>= 7 - j27++ - } - dAtA28[j27] = uint8(num) - j27++ - } - i -= j27 - copy(dAtA[i:], dAtA28[:j27]) - i = encodeVarintQuery(dAtA, i, uint64(j27)) - i-- - dAtA[i] = 0x1a - } - if len(m.ChannelId) > 0 { - i -= len(m.ChannelId) - copy(dAtA[i:], m.ChannelId) - i = encodeVarintQuery(dAtA, i, uint64(len(m.ChannelId))) - i-- - dAtA[i] = 0x12 - } - if len(m.PortId) > 0 { - i -= len(m.PortId) - copy(dAtA[i:], m.PortId) - i = encodeVarintQuery(dAtA, i, uint64(len(m.PortId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *QueryUnreceivedAcksResponse) 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 *QueryUnreceivedAcksResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryUnreceivedAcksResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - { - size, err := m.Height.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - if len(m.Sequences) > 0 { - dAtA31 := make([]byte, len(m.Sequences)*10) - var j30 int - for _, num := range m.Sequences { - for num >= 1<<7 { - dAtA31[j30] = uint8(uint64(num)&0x7f | 0x80) - num >>= 7 - j30++ - } - dAtA31[j30] = uint8(num) - j30++ - } - i -= j30 - copy(dAtA[i:], dAtA31[:j30]) - i = encodeVarintQuery(dAtA, i, uint64(j30)) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *QueryNextSequenceReceiveRequest) 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 *QueryNextSequenceReceiveRequest) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryNextSequenceReceiveRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.ChannelId) > 0 { - i -= len(m.ChannelId) - copy(dAtA[i:], m.ChannelId) - i = encodeVarintQuery(dAtA, i, uint64(len(m.ChannelId))) - i-- - dAtA[i] = 0x12 - } - if len(m.PortId) > 0 { - i -= len(m.PortId) - copy(dAtA[i:], m.PortId) - i = encodeVarintQuery(dAtA, i, uint64(len(m.PortId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *QueryNextSequenceReceiveResponse) 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 *QueryNextSequenceReceiveResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryNextSequenceReceiveResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - { - size, err := m.ProofHeight.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - if len(m.Proof) > 0 { - i -= len(m.Proof) - copy(dAtA[i:], m.Proof) - i = encodeVarintQuery(dAtA, i, uint64(len(m.Proof))) - i-- - dAtA[i] = 0x12 - } - if m.NextSequenceReceive != 0 { - i = encodeVarintQuery(dAtA, i, uint64(m.NextSequenceReceive)) - i-- - dAtA[i] = 0x8 - } - 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 *QueryChannelRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.PortId) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - l = len(m.ChannelId) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - return n -} - -func (m *QueryChannelResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.Channel != nil { - l = m.Channel.Size() - n += 1 + l + sovQuery(uint64(l)) - } - l = len(m.Proof) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - l = m.ProofHeight.Size() - n += 1 + l + sovQuery(uint64(l)) - return n -} - -func (m *QueryChannelsRequest) 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 *QueryChannelsResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if len(m.Channels) > 0 { - for _, e := range m.Channels { - l = e.Size() - n += 1 + l + sovQuery(uint64(l)) - } - } - if m.Pagination != nil { - l = m.Pagination.Size() - n += 1 + l + sovQuery(uint64(l)) - } - l = m.Height.Size() - n += 1 + l + sovQuery(uint64(l)) - return n -} - -func (m *QueryConnectionChannelsRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Connection) - 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 *QueryConnectionChannelsResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if len(m.Channels) > 0 { - for _, e := range m.Channels { - l = e.Size() - n += 1 + l + sovQuery(uint64(l)) - } - } - if m.Pagination != nil { - l = m.Pagination.Size() - n += 1 + l + sovQuery(uint64(l)) - } - l = m.Height.Size() - n += 1 + l + sovQuery(uint64(l)) - return n -} - -func (m *QueryChannelClientStateRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.PortId) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - l = len(m.ChannelId) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - return n -} - -func (m *QueryChannelClientStateResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.IdentifiedClientState != nil { - l = m.IdentifiedClientState.Size() - n += 1 + l + sovQuery(uint64(l)) - } - l = len(m.Proof) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - l = m.ProofHeight.Size() - n += 1 + l + sovQuery(uint64(l)) - return n -} - -func (m *QueryChannelConsensusStateRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.PortId) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - l = len(m.ChannelId) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - if m.RevisionNumber != 0 { - n += 1 + sovQuery(uint64(m.RevisionNumber)) - } - if m.RevisionHeight != 0 { - n += 1 + sovQuery(uint64(m.RevisionHeight)) - } - return n -} - -func (m *QueryChannelConsensusStateResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.ConsensusState != nil { - l = m.ConsensusState.Size() - n += 1 + l + sovQuery(uint64(l)) - } - l = len(m.ClientId) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - l = len(m.Proof) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - l = m.ProofHeight.Size() - n += 1 + l + sovQuery(uint64(l)) - return n -} - -func (m *QueryPacketCommitmentRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.PortId) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - l = len(m.ChannelId) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - if m.Sequence != 0 { - n += 1 + sovQuery(uint64(m.Sequence)) - } - return n -} - -func (m *QueryPacketCommitmentResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Commitment) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - l = len(m.Proof) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - l = m.ProofHeight.Size() - n += 1 + l + sovQuery(uint64(l)) - return n -} - -func (m *QueryPacketCommitmentsRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.PortId) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - l = len(m.ChannelId) - 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 *QueryPacketCommitmentsResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if len(m.Commitments) > 0 { - for _, e := range m.Commitments { - l = e.Size() - n += 1 + l + sovQuery(uint64(l)) - } - } - if m.Pagination != nil { - l = m.Pagination.Size() - n += 1 + l + sovQuery(uint64(l)) - } - l = m.Height.Size() - n += 1 + l + sovQuery(uint64(l)) - return n -} - -func (m *QueryPacketReceiptRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.PortId) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - l = len(m.ChannelId) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - if m.Sequence != 0 { - n += 1 + sovQuery(uint64(m.Sequence)) - } - return n -} - -func (m *QueryPacketReceiptResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.Received { - n += 2 - } - l = len(m.Proof) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - l = m.ProofHeight.Size() - n += 1 + l + sovQuery(uint64(l)) - return n -} - -func (m *QueryPacketAcknowledgementRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.PortId) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - l = len(m.ChannelId) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - if m.Sequence != 0 { - n += 1 + sovQuery(uint64(m.Sequence)) - } - return n -} - -func (m *QueryPacketAcknowledgementResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Acknowledgement) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - l = len(m.Proof) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - l = m.ProofHeight.Size() - n += 1 + l + sovQuery(uint64(l)) - return n -} - -func (m *QueryPacketAcknowledgementsRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.PortId) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - l = len(m.ChannelId) - 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 *QueryPacketAcknowledgementsResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if len(m.Acknowledgements) > 0 { - for _, e := range m.Acknowledgements { - l = e.Size() - n += 1 + l + sovQuery(uint64(l)) - } - } - if m.Pagination != nil { - l = m.Pagination.Size() - n += 1 + l + sovQuery(uint64(l)) - } - l = m.Height.Size() - n += 1 + l + sovQuery(uint64(l)) - return n -} - -func (m *QueryUnreceivedPacketsRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.PortId) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - l = len(m.ChannelId) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - if len(m.PacketCommitmentSequences) > 0 { - l = 0 - for _, e := range m.PacketCommitmentSequences { - l += sovQuery(uint64(e)) - } - n += 1 + sovQuery(uint64(l)) + l - } - return n -} - -func (m *QueryUnreceivedPacketsResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if len(m.Sequences) > 0 { - l = 0 - for _, e := range m.Sequences { - l += sovQuery(uint64(e)) - } - n += 1 + sovQuery(uint64(l)) + l - } - l = m.Height.Size() - n += 1 + l + sovQuery(uint64(l)) - return n -} - -func (m *QueryUnreceivedAcksRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.PortId) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - l = len(m.ChannelId) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - if len(m.PacketAckSequences) > 0 { - l = 0 - for _, e := range m.PacketAckSequences { - l += sovQuery(uint64(e)) - } - n += 1 + sovQuery(uint64(l)) + l - } - return n -} - -func (m *QueryUnreceivedAcksResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if len(m.Sequences) > 0 { - l = 0 - for _, e := range m.Sequences { - l += sovQuery(uint64(e)) - } - n += 1 + sovQuery(uint64(l)) + l - } - l = m.Height.Size() - n += 1 + l + sovQuery(uint64(l)) - return n -} - -func (m *QueryNextSequenceReceiveRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.PortId) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - l = len(m.ChannelId) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - return n -} - -func (m *QueryNextSequenceReceiveResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.NextSequenceReceive != 0 { - n += 1 + sovQuery(uint64(m.NextSequenceReceive)) - } - l = len(m.Proof) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - l = m.ProofHeight.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 *QueryChannelRequest) 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: QueryChannelRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryChannelRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field PortId", 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.PortId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ChannelId", 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.ChannelId = 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 *QueryChannelResponse) 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: QueryChannelResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryChannelResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Channel", 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.Channel == nil { - m.Channel = &Channel{} - } - if err := m.Channel.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Proof", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Proof = append(m.Proof[:0], dAtA[iNdEx:postIndex]...) - if m.Proof == nil { - m.Proof = []byte{} - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofHeight", 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 err := m.ProofHeight.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 *QueryChannelsRequest) 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: QueryChannelsRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryChannelsRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.Pagination == nil { - m.Pagination = &query.PageRequest{} - } - if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipQuery(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *QueryChannelsResponse) 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: QueryChannelsResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryChannelsResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Channels", 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.Channels = append(m.Channels, &IdentifiedChannel{}) - if err := m.Channels[len(m.Channels)-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 - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Height", 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 err := m.Height.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 *QueryConnectionChannelsRequest) 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: QueryConnectionChannelsRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryConnectionChannelsRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Connection", 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.Connection = 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 *QueryConnectionChannelsResponse) 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: QueryConnectionChannelsResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryConnectionChannelsResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Channels", 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.Channels = append(m.Channels, &IdentifiedChannel{}) - if err := m.Channels[len(m.Channels)-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 - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Height", 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 err := m.Height.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 *QueryChannelClientStateRequest) 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: QueryChannelClientStateRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryChannelClientStateRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field PortId", 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.PortId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ChannelId", 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.ChannelId = 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 *QueryChannelClientStateResponse) 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: QueryChannelClientStateResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryChannelClientStateResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field IdentifiedClientState", 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.IdentifiedClientState == nil { - m.IdentifiedClientState = &types.IdentifiedClientState{} - } - if err := m.IdentifiedClientState.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Proof", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Proof = append(m.Proof[:0], dAtA[iNdEx:postIndex]...) - if m.Proof == nil { - m.Proof = []byte{} - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofHeight", 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 err := m.ProofHeight.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 *QueryChannelConsensusStateRequest) 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: QueryChannelConsensusStateRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryChannelConsensusStateRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field PortId", 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.PortId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ChannelId", 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.ChannelId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field RevisionNumber", wireType) - } - m.RevisionNumber = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.RevisionNumber |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 4: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field RevisionHeight", wireType) - } - m.RevisionHeight = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.RevisionHeight |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - default: - iNdEx = preIndex - skippy, err := skipQuery(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *QueryChannelConsensusStateResponse) 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: QueryChannelConsensusStateResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryChannelConsensusStateResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ConsensusState", 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.ConsensusState == nil { - m.ConsensusState = &types1.Any{} - } - if err := m.ConsensusState.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ClientId", 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.ClientId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Proof", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Proof = append(m.Proof[:0], dAtA[iNdEx:postIndex]...) - if m.Proof == nil { - m.Proof = []byte{} - } - iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofHeight", 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 err := m.ProofHeight.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 *QueryPacketCommitmentRequest) 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: QueryPacketCommitmentRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryPacketCommitmentRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field PortId", 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.PortId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ChannelId", 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.ChannelId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Sequence", wireType) - } - m.Sequence = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Sequence |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - default: - iNdEx = preIndex - skippy, err := skipQuery(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *QueryPacketCommitmentResponse) 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: QueryPacketCommitmentResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryPacketCommitmentResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Commitment", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Commitment = append(m.Commitment[:0], dAtA[iNdEx:postIndex]...) - if m.Commitment == nil { - m.Commitment = []byte{} - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Proof", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Proof = append(m.Proof[:0], dAtA[iNdEx:postIndex]...) - if m.Proof == nil { - m.Proof = []byte{} - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofHeight", 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 err := m.ProofHeight.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 *QueryPacketCommitmentsRequest) 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: QueryPacketCommitmentsRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryPacketCommitmentsRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field PortId", 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.PortId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ChannelId", 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.ChannelId = 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 *QueryPacketCommitmentsResponse) 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: QueryPacketCommitmentsResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryPacketCommitmentsResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Commitments", 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.Commitments = append(m.Commitments, &PacketState{}) - if err := m.Commitments[len(m.Commitments)-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 - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Height", 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 err := m.Height.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 *QueryPacketReceiptRequest) 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: QueryPacketReceiptRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryPacketReceiptRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field PortId", 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.PortId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ChannelId", 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.ChannelId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Sequence", wireType) - } - m.Sequence = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Sequence |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - default: - iNdEx = preIndex - skippy, err := skipQuery(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *QueryPacketReceiptResponse) 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: QueryPacketReceiptResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryPacketReceiptResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Received", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.Received = bool(v != 0) - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Proof", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Proof = append(m.Proof[:0], dAtA[iNdEx:postIndex]...) - if m.Proof == nil { - m.Proof = []byte{} - } - iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofHeight", 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 err := m.ProofHeight.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 *QueryPacketAcknowledgementRequest) 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: QueryPacketAcknowledgementRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryPacketAcknowledgementRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field PortId", 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.PortId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ChannelId", 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.ChannelId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Sequence", wireType) - } - m.Sequence = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Sequence |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - default: - iNdEx = preIndex - skippy, err := skipQuery(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *QueryPacketAcknowledgementResponse) 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: QueryPacketAcknowledgementResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryPacketAcknowledgementResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Acknowledgement", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Acknowledgement = append(m.Acknowledgement[:0], dAtA[iNdEx:postIndex]...) - if m.Acknowledgement == nil { - m.Acknowledgement = []byte{} - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Proof", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Proof = append(m.Proof[:0], dAtA[iNdEx:postIndex]...) - if m.Proof == nil { - m.Proof = []byte{} - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofHeight", 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 err := m.ProofHeight.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 *QueryPacketAcknowledgementsRequest) 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: QueryPacketAcknowledgementsRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryPacketAcknowledgementsRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field PortId", 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.PortId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ChannelId", 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.ChannelId = 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 *QueryPacketAcknowledgementsResponse) 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: QueryPacketAcknowledgementsResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryPacketAcknowledgementsResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Acknowledgements", 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.Acknowledgements = append(m.Acknowledgements, &PacketState{}) - if err := m.Acknowledgements[len(m.Acknowledgements)-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 - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Height", 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 err := m.Height.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 *QueryUnreceivedPacketsRequest) 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: QueryUnreceivedPacketsRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryUnreceivedPacketsRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field PortId", 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.PortId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ChannelId", 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.ChannelId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType == 0 { - var v uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.PacketCommitmentSequences = append(m.PacketCommitmentSequences, v) - } else if wireType == 2 { - var packedLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - packedLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if packedLen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + packedLen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - var elementCount int - var count int - for _, integer := range dAtA[iNdEx:postIndex] { - if integer < 128 { - count++ - } - } - elementCount = count - if elementCount != 0 && len(m.PacketCommitmentSequences) == 0 { - m.PacketCommitmentSequences = make([]uint64, 0, elementCount) - } - for iNdEx < postIndex { - var v uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.PacketCommitmentSequences = append(m.PacketCommitmentSequences, v) - } - } else { - return fmt.Errorf("proto: wrong wireType = %d for field PacketCommitmentSequences", wireType) - } - 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 *QueryUnreceivedPacketsResponse) 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: QueryUnreceivedPacketsResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryUnreceivedPacketsResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType == 0 { - var v uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.Sequences = append(m.Sequences, v) - } else if wireType == 2 { - var packedLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - packedLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if packedLen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + packedLen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - var elementCount int - var count int - for _, integer := range dAtA[iNdEx:postIndex] { - if integer < 128 { - count++ - } - } - elementCount = count - if elementCount != 0 && len(m.Sequences) == 0 { - m.Sequences = make([]uint64, 0, elementCount) - } - for iNdEx < postIndex { - var v uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.Sequences = append(m.Sequences, v) - } - } else { - return fmt.Errorf("proto: wrong wireType = %d for field Sequences", wireType) - } - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Height", 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 err := m.Height.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 *QueryUnreceivedAcksRequest) 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: QueryUnreceivedAcksRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryUnreceivedAcksRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field PortId", 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.PortId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ChannelId", 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.ChannelId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType == 0 { - var v uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.PacketAckSequences = append(m.PacketAckSequences, v) - } else if wireType == 2 { - var packedLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - packedLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if packedLen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + packedLen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - var elementCount int - var count int - for _, integer := range dAtA[iNdEx:postIndex] { - if integer < 128 { - count++ - } - } - elementCount = count - if elementCount != 0 && len(m.PacketAckSequences) == 0 { - m.PacketAckSequences = make([]uint64, 0, elementCount) - } - for iNdEx < postIndex { - var v uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.PacketAckSequences = append(m.PacketAckSequences, v) - } - } else { - return fmt.Errorf("proto: wrong wireType = %d for field PacketAckSequences", wireType) - } - 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 *QueryUnreceivedAcksResponse) 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: QueryUnreceivedAcksResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryUnreceivedAcksResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType == 0 { - var v uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.Sequences = append(m.Sequences, v) - } else if wireType == 2 { - var packedLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - packedLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if packedLen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + packedLen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - var elementCount int - var count int - for _, integer := range dAtA[iNdEx:postIndex] { - if integer < 128 { - count++ - } - } - elementCount = count - if elementCount != 0 && len(m.Sequences) == 0 { - m.Sequences = make([]uint64, 0, elementCount) - } - for iNdEx < postIndex { - var v uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.Sequences = append(m.Sequences, v) - } - } else { - return fmt.Errorf("proto: wrong wireType = %d for field Sequences", wireType) - } - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Height", 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 err := m.Height.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 *QueryNextSequenceReceiveRequest) 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: QueryNextSequenceReceiveRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryNextSequenceReceiveRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field PortId", 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.PortId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ChannelId", 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.ChannelId = 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 *QueryNextSequenceReceiveResponse) 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: QueryNextSequenceReceiveResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryNextSequenceReceiveResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field NextSequenceReceive", wireType) - } - m.NextSequenceReceive = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.NextSequenceReceive |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Proof", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Proof = append(m.Proof[:0], dAtA[iNdEx:postIndex]...) - if m.Proof == nil { - m.Proof = []byte{} - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofHeight", 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 err := m.ProofHeight.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/ibc/core/04-channel/types/query.pb.gw.go b/x/ibc/core/04-channel/types/query.pb.gw.go deleted file mode 100644 index f38c05956ee9..000000000000 --- a/x/ibc/core/04-channel/types/query.pb.gw.go +++ /dev/null @@ -1,1792 +0,0 @@ -// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. -// source: ibc/core/channel/v1/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_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 - 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.Channel(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -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)} -) - -func request_Query_Channels_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, 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 := client.Channels(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -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}} -) - -func request_Query_ConnectionChannels_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, 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 := client.ConnectionChannels(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -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 - - 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.ChannelClientState(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -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 - - 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["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 := client.ChannelConsensusState(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -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 ( - 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["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.ChannelConsensusState(ctx, &protoReq) - 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 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 := client.PacketCommitment(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 - 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.PacketCommitment(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 - 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_PacketCommitments_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.PacketCommitments(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 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_PacketCommitments_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.PacketCommitments(ctx, &protoReq) - 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 - 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 := client.PacketReceipt(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 - 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.PacketReceipt(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 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 := 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) { - 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_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.AnnotateContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Query_Channel_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_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.AnnotateContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Query_Channels_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_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.AnnotateContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Query_ConnectionChannels_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_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.AnnotateContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Query_ChannelClientState_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_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.AnnotateContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Query_ChannelConsensusState_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_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.AnnotateContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Query_PacketCommitment_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_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.AnnotateContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Query_PacketCommitments_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_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.AnnotateContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Query_PacketReceipt_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_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.AnnotateContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Query_PacketAcknowledgement_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_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.AnnotateContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Query_PacketAcknowledgements_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_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.AnnotateContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Query_UnreceivedPackets_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_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.AnnotateContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Query_UnreceivedAcks_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_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.AnnotateContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Query_NextSequenceReceive_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_NextSequenceReceive_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - return nil -} - -var ( - pattern_Query_Channel_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7}, []string{"ibc", "core", "channel", "v1beta1", "channels", "channel_id", "ports", "port_id"}, "", runtime.AssumeColonVerbOpt(false))) - - pattern_Query_Channels_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"ibc", "core", "channel", "v1beta1", "channels"}, "", runtime.AssumeColonVerbOpt(false))) - - pattern_Query_ConnectionChannels_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6}, []string{"ibc", "core", "channel", "v1beta1", "connections", "connection", "channels"}, "", runtime.AssumeColonVerbOpt(false))) - - pattern_Query_ChannelClientState_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8}, []string{"ibc", "core", "channel", "v1beta1", "channels", "channel_id", "ports", "port_id", "client_state"}, "", runtime.AssumeColonVerbOpt(false))) - - pattern_Query_ChannelConsensusState_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8, 2, 9, 1, 0, 4, 1, 5, 10, 2, 11, 1, 0, 4, 1, 5, 12}, []string{"ibc", "core", "channel", "v1beta1", "channels", "channel_id", "ports", "port_id", "consensus_state", "revision", "revision_number", "height", "revision_height"}, "", runtime.AssumeColonVerbOpt(false))) - - pattern_Query_PacketCommitment_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8, 1, 0, 4, 1, 5, 9}, []string{"ibc", "core", "channel", "v1beta1", "channels", "channel_id", "ports", "port_id", "packet_commitments", "sequence"}, "", runtime.AssumeColonVerbOpt(false))) - - pattern_Query_PacketCommitments_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8}, []string{"ibc", "core", "channel", "v1beta1", "channels", "channel_id", "ports", "port_id", "packet_commitments"}, "", runtime.AssumeColonVerbOpt(false))) - - pattern_Query_PacketReceipt_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8, 1, 0, 4, 1, 5, 9}, []string{"ibc", "core", "channel", "v1beta1", "channels", "channel_id", "ports", "port_id", "packet_receipts", "sequence"}, "", runtime.AssumeColonVerbOpt(false))) - - pattern_Query_PacketAcknowledgement_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8, 1, 0, 4, 1, 5, 9}, []string{"ibc", "core", "channel", "v1beta1", "channels", "channel_id", "ports", "port_id", "packet_acks", "sequence"}, "", runtime.AssumeColonVerbOpt(false))) - - pattern_Query_PacketAcknowledgements_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8}, []string{"ibc", "core", "channel", "v1beta1", "channels", "channel_id", "ports", "port_id", "packet_acknowledgements"}, "", runtime.AssumeColonVerbOpt(false))) - - pattern_Query_UnreceivedPackets_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8, 1, 0, 4, 1, 5, 9, 2, 10}, []string{"ibc", "core", "channel", "v1beta1", "channels", "channel_id", "ports", "port_id", "packet_commitments", "packet_commitment_sequences", "unreceived_packets"}, "", runtime.AssumeColonVerbOpt(false))) - - pattern_Query_UnreceivedAcks_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8, 1, 0, 4, 1, 5, 9, 2, 10}, []string{"ibc", "core", "channel", "v1beta1", "channels", "channel_id", "ports", "port_id", "packet_commitments", "packet_ack_sequences", "unreceived_acks"}, "", runtime.AssumeColonVerbOpt(false))) - - pattern_Query_NextSequenceReceive_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6, 1, 0, 4, 1, 5, 7, 2, 8}, []string{"ibc", "core", "channel", "v1beta1", "channels", "channel_id", "ports", "port_id", "next_sequence"}, "", runtime.AssumeColonVerbOpt(false))) -) - -var ( - forward_Query_Channel_0 = runtime.ForwardResponseMessage - - forward_Query_Channels_0 = runtime.ForwardResponseMessage - - forward_Query_ConnectionChannels_0 = runtime.ForwardResponseMessage - - forward_Query_ChannelClientState_0 = runtime.ForwardResponseMessage - - forward_Query_ChannelConsensusState_0 = runtime.ForwardResponseMessage - - forward_Query_PacketCommitment_0 = runtime.ForwardResponseMessage - - forward_Query_PacketCommitments_0 = runtime.ForwardResponseMessage - - forward_Query_PacketReceipt_0 = runtime.ForwardResponseMessage - - forward_Query_PacketAcknowledgement_0 = runtime.ForwardResponseMessage - - forward_Query_PacketAcknowledgements_0 = runtime.ForwardResponseMessage - - forward_Query_UnreceivedPackets_0 = runtime.ForwardResponseMessage - - forward_Query_UnreceivedAcks_0 = runtime.ForwardResponseMessage - - forward_Query_NextSequenceReceive_0 = runtime.ForwardResponseMessage -) diff --git a/x/ibc/core/04-channel/types/tx.pb.go b/x/ibc/core/04-channel/types/tx.pb.go deleted file mode 100644 index df6a9653f671..000000000000 --- a/x/ibc/core/04-channel/types/tx.pb.go +++ /dev/null @@ -1,5259 +0,0 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: ibc/core/channel/v1/tx.proto - -package types - -import ( - context "context" - fmt "fmt" - types "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - _ "github.com/gogo/protobuf/gogoproto" - grpc1 "github.com/gogo/protobuf/grpc" - proto "github.com/gogo/protobuf/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 - -// MsgChannelOpenInit defines an sdk.Msg to initialize a channel handshake. It -// is called by a relayer on Chain A. -type MsgChannelOpenInit struct { - PortId string `protobuf:"bytes,1,opt,name=port_id,json=portId,proto3" json:"port_id,omitempty" yaml:"port_id"` - Channel Channel `protobuf:"bytes,2,opt,name=channel,proto3" json:"channel"` - Signer string `protobuf:"bytes,3,opt,name=signer,proto3" json:"signer,omitempty"` -} - -func (m *MsgChannelOpenInit) Reset() { *m = MsgChannelOpenInit{} } -func (m *MsgChannelOpenInit) String() string { return proto.CompactTextString(m) } -func (*MsgChannelOpenInit) ProtoMessage() {} -func (*MsgChannelOpenInit) Descriptor() ([]byte, []int) { - return fileDescriptor_bc4637e0ac3fc7b7, []int{0} -} -func (m *MsgChannelOpenInit) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgChannelOpenInit) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgChannelOpenInit.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 *MsgChannelOpenInit) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgChannelOpenInit.Merge(m, src) -} -func (m *MsgChannelOpenInit) XXX_Size() int { - return m.Size() -} -func (m *MsgChannelOpenInit) XXX_DiscardUnknown() { - xxx_messageInfo_MsgChannelOpenInit.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgChannelOpenInit proto.InternalMessageInfo - -// MsgChannelOpenInitResponse defines the Msg/ChannelOpenInit response type. -type MsgChannelOpenInitResponse struct { -} - -func (m *MsgChannelOpenInitResponse) Reset() { *m = MsgChannelOpenInitResponse{} } -func (m *MsgChannelOpenInitResponse) String() string { return proto.CompactTextString(m) } -func (*MsgChannelOpenInitResponse) ProtoMessage() {} -func (*MsgChannelOpenInitResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_bc4637e0ac3fc7b7, []int{1} -} -func (m *MsgChannelOpenInitResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgChannelOpenInitResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgChannelOpenInitResponse.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 *MsgChannelOpenInitResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgChannelOpenInitResponse.Merge(m, src) -} -func (m *MsgChannelOpenInitResponse) XXX_Size() int { - return m.Size() -} -func (m *MsgChannelOpenInitResponse) XXX_DiscardUnknown() { - xxx_messageInfo_MsgChannelOpenInitResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgChannelOpenInitResponse proto.InternalMessageInfo - -// MsgChannelOpenInit defines a msg sent by a Relayer to try to open a channel -// on Chain B. -type MsgChannelOpenTry struct { - PortId string `protobuf:"bytes,1,opt,name=port_id,json=portId,proto3" json:"port_id,omitempty" yaml:"port_id"` - // in the case of crossing hello's, when both chains call OpenInit, we need the channel identifier - // of the previous channel in state INIT - PreviousChannelId string `protobuf:"bytes,2,opt,name=previous_channel_id,json=previousChannelId,proto3" json:"previous_channel_id,omitempty" yaml:"previous_channel_id"` - Channel Channel `protobuf:"bytes,3,opt,name=channel,proto3" json:"channel"` - CounterpartyVersion string `protobuf:"bytes,4,opt,name=counterparty_version,json=counterpartyVersion,proto3" json:"counterparty_version,omitempty" yaml:"counterparty_version"` - ProofInit []byte `protobuf:"bytes,5,opt,name=proof_init,json=proofInit,proto3" json:"proof_init,omitempty" yaml:"proof_init"` - ProofHeight types.Height `protobuf:"bytes,6,opt,name=proof_height,json=proofHeight,proto3" json:"proof_height" yaml:"proof_height"` - Signer string `protobuf:"bytes,7,opt,name=signer,proto3" json:"signer,omitempty"` -} - -func (m *MsgChannelOpenTry) Reset() { *m = MsgChannelOpenTry{} } -func (m *MsgChannelOpenTry) String() string { return proto.CompactTextString(m) } -func (*MsgChannelOpenTry) ProtoMessage() {} -func (*MsgChannelOpenTry) Descriptor() ([]byte, []int) { - return fileDescriptor_bc4637e0ac3fc7b7, []int{2} -} -func (m *MsgChannelOpenTry) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgChannelOpenTry) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgChannelOpenTry.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 *MsgChannelOpenTry) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgChannelOpenTry.Merge(m, src) -} -func (m *MsgChannelOpenTry) XXX_Size() int { - return m.Size() -} -func (m *MsgChannelOpenTry) XXX_DiscardUnknown() { - xxx_messageInfo_MsgChannelOpenTry.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgChannelOpenTry proto.InternalMessageInfo - -// MsgChannelOpenTryResponse defines the Msg/ChannelOpenTry response type. -type MsgChannelOpenTryResponse struct { -} - -func (m *MsgChannelOpenTryResponse) Reset() { *m = MsgChannelOpenTryResponse{} } -func (m *MsgChannelOpenTryResponse) String() string { return proto.CompactTextString(m) } -func (*MsgChannelOpenTryResponse) ProtoMessage() {} -func (*MsgChannelOpenTryResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_bc4637e0ac3fc7b7, []int{3} -} -func (m *MsgChannelOpenTryResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgChannelOpenTryResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgChannelOpenTryResponse.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 *MsgChannelOpenTryResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgChannelOpenTryResponse.Merge(m, src) -} -func (m *MsgChannelOpenTryResponse) XXX_Size() int { - return m.Size() -} -func (m *MsgChannelOpenTryResponse) XXX_DiscardUnknown() { - xxx_messageInfo_MsgChannelOpenTryResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgChannelOpenTryResponse proto.InternalMessageInfo - -// MsgChannelOpenAck defines a msg sent by a Relayer to Chain A to acknowledge -// the change of channel state to TRYOPEN on Chain B. -type MsgChannelOpenAck struct { - PortId string `protobuf:"bytes,1,opt,name=port_id,json=portId,proto3" json:"port_id,omitempty" yaml:"port_id"` - ChannelId string `protobuf:"bytes,2,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty" yaml:"channel_id"` - CounterpartyChannelId string `protobuf:"bytes,3,opt,name=counterparty_channel_id,json=counterpartyChannelId,proto3" json:"counterparty_channel_id,omitempty" yaml:"counterparty_channel_id"` - CounterpartyVersion string `protobuf:"bytes,4,opt,name=counterparty_version,json=counterpartyVersion,proto3" json:"counterparty_version,omitempty" yaml:"counterparty_version"` - ProofTry []byte `protobuf:"bytes,5,opt,name=proof_try,json=proofTry,proto3" json:"proof_try,omitempty" yaml:"proof_try"` - ProofHeight types.Height `protobuf:"bytes,6,opt,name=proof_height,json=proofHeight,proto3" json:"proof_height" yaml:"proof_height"` - Signer string `protobuf:"bytes,7,opt,name=signer,proto3" json:"signer,omitempty"` -} - -func (m *MsgChannelOpenAck) Reset() { *m = MsgChannelOpenAck{} } -func (m *MsgChannelOpenAck) String() string { return proto.CompactTextString(m) } -func (*MsgChannelOpenAck) ProtoMessage() {} -func (*MsgChannelOpenAck) Descriptor() ([]byte, []int) { - return fileDescriptor_bc4637e0ac3fc7b7, []int{4} -} -func (m *MsgChannelOpenAck) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgChannelOpenAck) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgChannelOpenAck.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 *MsgChannelOpenAck) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgChannelOpenAck.Merge(m, src) -} -func (m *MsgChannelOpenAck) XXX_Size() int { - return m.Size() -} -func (m *MsgChannelOpenAck) XXX_DiscardUnknown() { - xxx_messageInfo_MsgChannelOpenAck.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgChannelOpenAck proto.InternalMessageInfo - -// MsgChannelOpenAckResponse defines the Msg/ChannelOpenAck response type. -type MsgChannelOpenAckResponse struct { -} - -func (m *MsgChannelOpenAckResponse) Reset() { *m = MsgChannelOpenAckResponse{} } -func (m *MsgChannelOpenAckResponse) String() string { return proto.CompactTextString(m) } -func (*MsgChannelOpenAckResponse) ProtoMessage() {} -func (*MsgChannelOpenAckResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_bc4637e0ac3fc7b7, []int{5} -} -func (m *MsgChannelOpenAckResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgChannelOpenAckResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgChannelOpenAckResponse.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 *MsgChannelOpenAckResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgChannelOpenAckResponse.Merge(m, src) -} -func (m *MsgChannelOpenAckResponse) XXX_Size() int { - return m.Size() -} -func (m *MsgChannelOpenAckResponse) XXX_DiscardUnknown() { - xxx_messageInfo_MsgChannelOpenAckResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgChannelOpenAckResponse proto.InternalMessageInfo - -// MsgChannelOpenConfirm defines a msg sent by a Relayer to Chain B to -// acknowledge the change of channel state to OPEN on Chain A. -type MsgChannelOpenConfirm struct { - PortId string `protobuf:"bytes,1,opt,name=port_id,json=portId,proto3" json:"port_id,omitempty" yaml:"port_id"` - ChannelId string `protobuf:"bytes,2,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty" yaml:"channel_id"` - ProofAck []byte `protobuf:"bytes,3,opt,name=proof_ack,json=proofAck,proto3" json:"proof_ack,omitempty" yaml:"proof_ack"` - ProofHeight types.Height `protobuf:"bytes,4,opt,name=proof_height,json=proofHeight,proto3" json:"proof_height" yaml:"proof_height"` - Signer string `protobuf:"bytes,5,opt,name=signer,proto3" json:"signer,omitempty"` -} - -func (m *MsgChannelOpenConfirm) Reset() { *m = MsgChannelOpenConfirm{} } -func (m *MsgChannelOpenConfirm) String() string { return proto.CompactTextString(m) } -func (*MsgChannelOpenConfirm) ProtoMessage() {} -func (*MsgChannelOpenConfirm) Descriptor() ([]byte, []int) { - return fileDescriptor_bc4637e0ac3fc7b7, []int{6} -} -func (m *MsgChannelOpenConfirm) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgChannelOpenConfirm) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgChannelOpenConfirm.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 *MsgChannelOpenConfirm) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgChannelOpenConfirm.Merge(m, src) -} -func (m *MsgChannelOpenConfirm) XXX_Size() int { - return m.Size() -} -func (m *MsgChannelOpenConfirm) XXX_DiscardUnknown() { - xxx_messageInfo_MsgChannelOpenConfirm.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgChannelOpenConfirm proto.InternalMessageInfo - -// MsgChannelOpenConfirmResponse defines the Msg/ChannelOpenConfirm response type. -type MsgChannelOpenConfirmResponse struct { -} - -func (m *MsgChannelOpenConfirmResponse) Reset() { *m = MsgChannelOpenConfirmResponse{} } -func (m *MsgChannelOpenConfirmResponse) String() string { return proto.CompactTextString(m) } -func (*MsgChannelOpenConfirmResponse) ProtoMessage() {} -func (*MsgChannelOpenConfirmResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_bc4637e0ac3fc7b7, []int{7} -} -func (m *MsgChannelOpenConfirmResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgChannelOpenConfirmResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgChannelOpenConfirmResponse.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 *MsgChannelOpenConfirmResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgChannelOpenConfirmResponse.Merge(m, src) -} -func (m *MsgChannelOpenConfirmResponse) XXX_Size() int { - return m.Size() -} -func (m *MsgChannelOpenConfirmResponse) XXX_DiscardUnknown() { - xxx_messageInfo_MsgChannelOpenConfirmResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgChannelOpenConfirmResponse proto.InternalMessageInfo - -// MsgChannelCloseInit defines a msg sent by a Relayer to Chain A -// to close a channel with Chain B. -type MsgChannelCloseInit struct { - PortId string `protobuf:"bytes,1,opt,name=port_id,json=portId,proto3" json:"port_id,omitempty" yaml:"port_id"` - ChannelId string `protobuf:"bytes,2,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty" yaml:"channel_id"` - Signer string `protobuf:"bytes,3,opt,name=signer,proto3" json:"signer,omitempty"` -} - -func (m *MsgChannelCloseInit) Reset() { *m = MsgChannelCloseInit{} } -func (m *MsgChannelCloseInit) String() string { return proto.CompactTextString(m) } -func (*MsgChannelCloseInit) ProtoMessage() {} -func (*MsgChannelCloseInit) Descriptor() ([]byte, []int) { - return fileDescriptor_bc4637e0ac3fc7b7, []int{8} -} -func (m *MsgChannelCloseInit) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgChannelCloseInit) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgChannelCloseInit.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 *MsgChannelCloseInit) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgChannelCloseInit.Merge(m, src) -} -func (m *MsgChannelCloseInit) XXX_Size() int { - return m.Size() -} -func (m *MsgChannelCloseInit) XXX_DiscardUnknown() { - xxx_messageInfo_MsgChannelCloseInit.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgChannelCloseInit proto.InternalMessageInfo - -// MsgChannelCloseInitResponse defines the Msg/ChannelCloseInit response type. -type MsgChannelCloseInitResponse struct { -} - -func (m *MsgChannelCloseInitResponse) Reset() { *m = MsgChannelCloseInitResponse{} } -func (m *MsgChannelCloseInitResponse) String() string { return proto.CompactTextString(m) } -func (*MsgChannelCloseInitResponse) ProtoMessage() {} -func (*MsgChannelCloseInitResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_bc4637e0ac3fc7b7, []int{9} -} -func (m *MsgChannelCloseInitResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgChannelCloseInitResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgChannelCloseInitResponse.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 *MsgChannelCloseInitResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgChannelCloseInitResponse.Merge(m, src) -} -func (m *MsgChannelCloseInitResponse) XXX_Size() int { - return m.Size() -} -func (m *MsgChannelCloseInitResponse) XXX_DiscardUnknown() { - xxx_messageInfo_MsgChannelCloseInitResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgChannelCloseInitResponse proto.InternalMessageInfo - -// MsgChannelCloseConfirm defines a msg sent by a Relayer to Chain B -// to acknowledge the change of channel state to CLOSED on Chain A. -type MsgChannelCloseConfirm struct { - PortId string `protobuf:"bytes,1,opt,name=port_id,json=portId,proto3" json:"port_id,omitempty" yaml:"port_id"` - ChannelId string `protobuf:"bytes,2,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty" yaml:"channel_id"` - ProofInit []byte `protobuf:"bytes,3,opt,name=proof_init,json=proofInit,proto3" json:"proof_init,omitempty" yaml:"proof_init"` - ProofHeight types.Height `protobuf:"bytes,4,opt,name=proof_height,json=proofHeight,proto3" json:"proof_height" yaml:"proof_height"` - Signer string `protobuf:"bytes,5,opt,name=signer,proto3" json:"signer,omitempty"` -} - -func (m *MsgChannelCloseConfirm) Reset() { *m = MsgChannelCloseConfirm{} } -func (m *MsgChannelCloseConfirm) String() string { return proto.CompactTextString(m) } -func (*MsgChannelCloseConfirm) ProtoMessage() {} -func (*MsgChannelCloseConfirm) Descriptor() ([]byte, []int) { - return fileDescriptor_bc4637e0ac3fc7b7, []int{10} -} -func (m *MsgChannelCloseConfirm) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgChannelCloseConfirm) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgChannelCloseConfirm.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 *MsgChannelCloseConfirm) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgChannelCloseConfirm.Merge(m, src) -} -func (m *MsgChannelCloseConfirm) XXX_Size() int { - return m.Size() -} -func (m *MsgChannelCloseConfirm) XXX_DiscardUnknown() { - xxx_messageInfo_MsgChannelCloseConfirm.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgChannelCloseConfirm proto.InternalMessageInfo - -// MsgChannelCloseConfirmResponse defines the Msg/ChannelCloseConfirm response type. -type MsgChannelCloseConfirmResponse struct { -} - -func (m *MsgChannelCloseConfirmResponse) Reset() { *m = MsgChannelCloseConfirmResponse{} } -func (m *MsgChannelCloseConfirmResponse) String() string { return proto.CompactTextString(m) } -func (*MsgChannelCloseConfirmResponse) ProtoMessage() {} -func (*MsgChannelCloseConfirmResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_bc4637e0ac3fc7b7, []int{11} -} -func (m *MsgChannelCloseConfirmResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgChannelCloseConfirmResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgChannelCloseConfirmResponse.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 *MsgChannelCloseConfirmResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgChannelCloseConfirmResponse.Merge(m, src) -} -func (m *MsgChannelCloseConfirmResponse) XXX_Size() int { - return m.Size() -} -func (m *MsgChannelCloseConfirmResponse) XXX_DiscardUnknown() { - xxx_messageInfo_MsgChannelCloseConfirmResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgChannelCloseConfirmResponse proto.InternalMessageInfo - -// MsgRecvPacket receives incoming IBC packet -type MsgRecvPacket struct { - Packet Packet `protobuf:"bytes,1,opt,name=packet,proto3" json:"packet"` - ProofCommitment []byte `protobuf:"bytes,2,opt,name=proof_commitment,json=proofCommitment,proto3" json:"proof_commitment,omitempty" yaml:"proof_commitment"` - ProofHeight types.Height `protobuf:"bytes,3,opt,name=proof_height,json=proofHeight,proto3" json:"proof_height" yaml:"proof_height"` - Signer string `protobuf:"bytes,4,opt,name=signer,proto3" json:"signer,omitempty"` -} - -func (m *MsgRecvPacket) Reset() { *m = MsgRecvPacket{} } -func (m *MsgRecvPacket) String() string { return proto.CompactTextString(m) } -func (*MsgRecvPacket) ProtoMessage() {} -func (*MsgRecvPacket) Descriptor() ([]byte, []int) { - return fileDescriptor_bc4637e0ac3fc7b7, []int{12} -} -func (m *MsgRecvPacket) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgRecvPacket) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgRecvPacket.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 *MsgRecvPacket) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgRecvPacket.Merge(m, src) -} -func (m *MsgRecvPacket) XXX_Size() int { - return m.Size() -} -func (m *MsgRecvPacket) XXX_DiscardUnknown() { - xxx_messageInfo_MsgRecvPacket.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgRecvPacket proto.InternalMessageInfo - -// MsgRecvPacketResponse defines the Msg/RecvPacket response type. -type MsgRecvPacketResponse struct { -} - -func (m *MsgRecvPacketResponse) Reset() { *m = MsgRecvPacketResponse{} } -func (m *MsgRecvPacketResponse) String() string { return proto.CompactTextString(m) } -func (*MsgRecvPacketResponse) ProtoMessage() {} -func (*MsgRecvPacketResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_bc4637e0ac3fc7b7, []int{13} -} -func (m *MsgRecvPacketResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgRecvPacketResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgRecvPacketResponse.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 *MsgRecvPacketResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgRecvPacketResponse.Merge(m, src) -} -func (m *MsgRecvPacketResponse) XXX_Size() int { - return m.Size() -} -func (m *MsgRecvPacketResponse) XXX_DiscardUnknown() { - xxx_messageInfo_MsgRecvPacketResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgRecvPacketResponse proto.InternalMessageInfo - -// MsgTimeout receives timed-out packet -type MsgTimeout struct { - Packet Packet `protobuf:"bytes,1,opt,name=packet,proto3" json:"packet"` - ProofUnreceived []byte `protobuf:"bytes,2,opt,name=proof_unreceived,json=proofUnreceived,proto3" json:"proof_unreceived,omitempty" yaml:"proof_unreceived"` - ProofHeight types.Height `protobuf:"bytes,3,opt,name=proof_height,json=proofHeight,proto3" json:"proof_height" yaml:"proof_height"` - NextSequenceRecv uint64 `protobuf:"varint,4,opt,name=next_sequence_recv,json=nextSequenceRecv,proto3" json:"next_sequence_recv,omitempty" yaml:"next_sequence_recv"` - Signer string `protobuf:"bytes,5,opt,name=signer,proto3" json:"signer,omitempty"` -} - -func (m *MsgTimeout) Reset() { *m = MsgTimeout{} } -func (m *MsgTimeout) String() string { return proto.CompactTextString(m) } -func (*MsgTimeout) ProtoMessage() {} -func (*MsgTimeout) Descriptor() ([]byte, []int) { - return fileDescriptor_bc4637e0ac3fc7b7, []int{14} -} -func (m *MsgTimeout) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgTimeout) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgTimeout.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 *MsgTimeout) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgTimeout.Merge(m, src) -} -func (m *MsgTimeout) XXX_Size() int { - return m.Size() -} -func (m *MsgTimeout) XXX_DiscardUnknown() { - xxx_messageInfo_MsgTimeout.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgTimeout proto.InternalMessageInfo - -// MsgTimeoutResponse defines the Msg/Timeout response type. -type MsgTimeoutResponse struct { -} - -func (m *MsgTimeoutResponse) Reset() { *m = MsgTimeoutResponse{} } -func (m *MsgTimeoutResponse) String() string { return proto.CompactTextString(m) } -func (*MsgTimeoutResponse) ProtoMessage() {} -func (*MsgTimeoutResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_bc4637e0ac3fc7b7, []int{15} -} -func (m *MsgTimeoutResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgTimeoutResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgTimeoutResponse.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 *MsgTimeoutResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgTimeoutResponse.Merge(m, src) -} -func (m *MsgTimeoutResponse) XXX_Size() int { - return m.Size() -} -func (m *MsgTimeoutResponse) XXX_DiscardUnknown() { - xxx_messageInfo_MsgTimeoutResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgTimeoutResponse proto.InternalMessageInfo - -// MsgTimeoutOnClose timed-out packet upon counterparty channel closure. -type MsgTimeoutOnClose struct { - Packet Packet `protobuf:"bytes,1,opt,name=packet,proto3" json:"packet"` - ProofUnreceived []byte `protobuf:"bytes,2,opt,name=proof_unreceived,json=proofUnreceived,proto3" json:"proof_unreceived,omitempty" yaml:"proof_unreceived"` - ProofClose []byte `protobuf:"bytes,3,opt,name=proof_close,json=proofClose,proto3" json:"proof_close,omitempty" yaml:"proof_close"` - ProofHeight types.Height `protobuf:"bytes,4,opt,name=proof_height,json=proofHeight,proto3" json:"proof_height" yaml:"proof_height"` - NextSequenceRecv uint64 `protobuf:"varint,5,opt,name=next_sequence_recv,json=nextSequenceRecv,proto3" json:"next_sequence_recv,omitempty" yaml:"next_sequence_recv"` - Signer string `protobuf:"bytes,6,opt,name=signer,proto3" json:"signer,omitempty"` -} - -func (m *MsgTimeoutOnClose) Reset() { *m = MsgTimeoutOnClose{} } -func (m *MsgTimeoutOnClose) String() string { return proto.CompactTextString(m) } -func (*MsgTimeoutOnClose) ProtoMessage() {} -func (*MsgTimeoutOnClose) Descriptor() ([]byte, []int) { - return fileDescriptor_bc4637e0ac3fc7b7, []int{16} -} -func (m *MsgTimeoutOnClose) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgTimeoutOnClose) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgTimeoutOnClose.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 *MsgTimeoutOnClose) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgTimeoutOnClose.Merge(m, src) -} -func (m *MsgTimeoutOnClose) XXX_Size() int { - return m.Size() -} -func (m *MsgTimeoutOnClose) XXX_DiscardUnknown() { - xxx_messageInfo_MsgTimeoutOnClose.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgTimeoutOnClose proto.InternalMessageInfo - -// MsgTimeoutOnCloseResponse defines the Msg/TimeoutOnClose response type. -type MsgTimeoutOnCloseResponse struct { -} - -func (m *MsgTimeoutOnCloseResponse) Reset() { *m = MsgTimeoutOnCloseResponse{} } -func (m *MsgTimeoutOnCloseResponse) String() string { return proto.CompactTextString(m) } -func (*MsgTimeoutOnCloseResponse) ProtoMessage() {} -func (*MsgTimeoutOnCloseResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_bc4637e0ac3fc7b7, []int{17} -} -func (m *MsgTimeoutOnCloseResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgTimeoutOnCloseResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgTimeoutOnCloseResponse.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 *MsgTimeoutOnCloseResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgTimeoutOnCloseResponse.Merge(m, src) -} -func (m *MsgTimeoutOnCloseResponse) XXX_Size() int { - return m.Size() -} -func (m *MsgTimeoutOnCloseResponse) XXX_DiscardUnknown() { - xxx_messageInfo_MsgTimeoutOnCloseResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgTimeoutOnCloseResponse proto.InternalMessageInfo - -// MsgAcknowledgement receives incoming IBC acknowledgement -type MsgAcknowledgement struct { - Packet Packet `protobuf:"bytes,1,opt,name=packet,proto3" json:"packet"` - Acknowledgement []byte `protobuf:"bytes,2,opt,name=acknowledgement,proto3" json:"acknowledgement,omitempty"` - ProofAcked []byte `protobuf:"bytes,3,opt,name=proof_acked,json=proofAcked,proto3" json:"proof_acked,omitempty" yaml:"proof_acked"` - ProofHeight types.Height `protobuf:"bytes,4,opt,name=proof_height,json=proofHeight,proto3" json:"proof_height" yaml:"proof_height"` - Signer string `protobuf:"bytes,5,opt,name=signer,proto3" json:"signer,omitempty"` -} - -func (m *MsgAcknowledgement) Reset() { *m = MsgAcknowledgement{} } -func (m *MsgAcknowledgement) String() string { return proto.CompactTextString(m) } -func (*MsgAcknowledgement) ProtoMessage() {} -func (*MsgAcknowledgement) Descriptor() ([]byte, []int) { - return fileDescriptor_bc4637e0ac3fc7b7, []int{18} -} -func (m *MsgAcknowledgement) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgAcknowledgement) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgAcknowledgement.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 *MsgAcknowledgement) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgAcknowledgement.Merge(m, src) -} -func (m *MsgAcknowledgement) XXX_Size() int { - return m.Size() -} -func (m *MsgAcknowledgement) XXX_DiscardUnknown() { - xxx_messageInfo_MsgAcknowledgement.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgAcknowledgement proto.InternalMessageInfo - -// MsgAcknowledgementResponse defines the Msg/Acknowledgement response type. -type MsgAcknowledgementResponse struct { -} - -func (m *MsgAcknowledgementResponse) Reset() { *m = MsgAcknowledgementResponse{} } -func (m *MsgAcknowledgementResponse) String() string { return proto.CompactTextString(m) } -func (*MsgAcknowledgementResponse) ProtoMessage() {} -func (*MsgAcknowledgementResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_bc4637e0ac3fc7b7, []int{19} -} -func (m *MsgAcknowledgementResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgAcknowledgementResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgAcknowledgementResponse.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 *MsgAcknowledgementResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgAcknowledgementResponse.Merge(m, src) -} -func (m *MsgAcknowledgementResponse) XXX_Size() int { - return m.Size() -} -func (m *MsgAcknowledgementResponse) XXX_DiscardUnknown() { - xxx_messageInfo_MsgAcknowledgementResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgAcknowledgementResponse proto.InternalMessageInfo - -func init() { - proto.RegisterType((*MsgChannelOpenInit)(nil), "ibc.core.channel.v1.MsgChannelOpenInit") - proto.RegisterType((*MsgChannelOpenInitResponse)(nil), "ibc.core.channel.v1.MsgChannelOpenInitResponse") - proto.RegisterType((*MsgChannelOpenTry)(nil), "ibc.core.channel.v1.MsgChannelOpenTry") - proto.RegisterType((*MsgChannelOpenTryResponse)(nil), "ibc.core.channel.v1.MsgChannelOpenTryResponse") - proto.RegisterType((*MsgChannelOpenAck)(nil), "ibc.core.channel.v1.MsgChannelOpenAck") - proto.RegisterType((*MsgChannelOpenAckResponse)(nil), "ibc.core.channel.v1.MsgChannelOpenAckResponse") - proto.RegisterType((*MsgChannelOpenConfirm)(nil), "ibc.core.channel.v1.MsgChannelOpenConfirm") - proto.RegisterType((*MsgChannelOpenConfirmResponse)(nil), "ibc.core.channel.v1.MsgChannelOpenConfirmResponse") - proto.RegisterType((*MsgChannelCloseInit)(nil), "ibc.core.channel.v1.MsgChannelCloseInit") - proto.RegisterType((*MsgChannelCloseInitResponse)(nil), "ibc.core.channel.v1.MsgChannelCloseInitResponse") - proto.RegisterType((*MsgChannelCloseConfirm)(nil), "ibc.core.channel.v1.MsgChannelCloseConfirm") - proto.RegisterType((*MsgChannelCloseConfirmResponse)(nil), "ibc.core.channel.v1.MsgChannelCloseConfirmResponse") - proto.RegisterType((*MsgRecvPacket)(nil), "ibc.core.channel.v1.MsgRecvPacket") - proto.RegisterType((*MsgRecvPacketResponse)(nil), "ibc.core.channel.v1.MsgRecvPacketResponse") - proto.RegisterType((*MsgTimeout)(nil), "ibc.core.channel.v1.MsgTimeout") - proto.RegisterType((*MsgTimeoutResponse)(nil), "ibc.core.channel.v1.MsgTimeoutResponse") - proto.RegisterType((*MsgTimeoutOnClose)(nil), "ibc.core.channel.v1.MsgTimeoutOnClose") - proto.RegisterType((*MsgTimeoutOnCloseResponse)(nil), "ibc.core.channel.v1.MsgTimeoutOnCloseResponse") - proto.RegisterType((*MsgAcknowledgement)(nil), "ibc.core.channel.v1.MsgAcknowledgement") - proto.RegisterType((*MsgAcknowledgementResponse)(nil), "ibc.core.channel.v1.MsgAcknowledgementResponse") -} - -func init() { proto.RegisterFile("ibc/core/channel/v1/tx.proto", fileDescriptor_bc4637e0ac3fc7b7) } - -var fileDescriptor_bc4637e0ac3fc7b7 = []byte{ - // 1120 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x58, 0xcd, 0x6e, 0xdb, 0x46, - 0x10, 0xd6, 0x8f, 0x2d, 0xdb, 0x63, 0x37, 0xb6, 0x29, 0xff, 0x28, 0x94, 0x2d, 0xba, 0x3c, 0x24, - 0x42, 0x8a, 0x48, 0xb1, 0x63, 0xa0, 0x6d, 0xd0, 0x8b, 0x64, 0xa0, 0x68, 0x50, 0xb8, 0x29, 0x18, - 0xb7, 0x07, 0xa3, 0x80, 0x20, 0xaf, 0x36, 0x14, 0x21, 0x89, 0xab, 0x92, 0x94, 0x62, 0xbd, 0x41, - 0x8f, 0x39, 0xf7, 0x94, 0x9e, 0x7b, 0x48, 0x1f, 0x23, 0xc7, 0x9c, 0xda, 0xa2, 0x07, 0xa2, 0xb0, - 0x2f, 0x3d, 0xf3, 0x09, 0x0a, 0xee, 0x2e, 0x29, 0x4a, 0x22, 0x2b, 0x2a, 0xa9, 0x9c, 0x9c, 0xb4, - 0x9c, 0xf9, 0x76, 0x76, 0xf6, 0xfb, 0x86, 0xb3, 0x4b, 0xc1, 0x9e, 0x76, 0x81, 0xca, 0x88, 0x18, - 0xb8, 0x8c, 0x9a, 0x75, 0x5d, 0xc7, 0xed, 0x72, 0xff, 0xb0, 0x6c, 0x5d, 0x96, 0xba, 0x06, 0xb1, - 0x88, 0x90, 0xd5, 0x2e, 0x50, 0xc9, 0xf5, 0x96, 0xb8, 0xb7, 0xd4, 0x3f, 0x14, 0xb7, 0x54, 0xa2, - 0x12, 0xea, 0x2f, 0xbb, 0x23, 0x06, 0x15, 0xa5, 0x61, 0xa0, 0xb6, 0x86, 0x75, 0xcb, 0x8d, 0xc3, - 0x46, 0x1c, 0xf0, 0x71, 0xd8, 0x4a, 0x5e, 0x58, 0x0a, 0x91, 0x7f, 0x49, 0x82, 0x70, 0x6a, 0xaa, - 0x27, 0xcc, 0xf8, 0xa4, 0x8b, 0xf5, 0xc7, 0xba, 0x66, 0x09, 0x9f, 0xc0, 0x52, 0x97, 0x18, 0x56, - 0x4d, 0x6b, 0xe4, 0x92, 0x07, 0xc9, 0xe2, 0x4a, 0x55, 0x70, 0x6c, 0xe9, 0xd6, 0xa0, 0xde, 0x69, - 0x3f, 0x92, 0xb9, 0x43, 0x56, 0x32, 0xee, 0xe8, 0x71, 0x43, 0xf8, 0x02, 0x96, 0x78, 0xd0, 0x5c, - 0xea, 0x20, 0x59, 0x5c, 0x3d, 0xda, 0x2b, 0x85, 0x6c, 0xa2, 0xc4, 0xd7, 0xa8, 0x2e, 0xbc, 0xb6, - 0xa5, 0x84, 0xe2, 0x4d, 0x11, 0x76, 0x20, 0x63, 0x6a, 0xaa, 0x8e, 0x8d, 0x5c, 0xda, 0x5d, 0x49, - 0xe1, 0x4f, 0x8f, 0x96, 0x7f, 0x7a, 0x29, 0x25, 0xfe, 0x79, 0x29, 0x25, 0xe4, 0x3d, 0x10, 0x27, - 0x53, 0x54, 0xb0, 0xd9, 0x25, 0xba, 0x89, 0xe5, 0xdf, 0xd3, 0xb0, 0x39, 0xea, 0x3e, 0x33, 0x06, - 0xb3, 0x6d, 0xe0, 0x1b, 0xc8, 0x76, 0x0d, 0xdc, 0xd7, 0x48, 0xcf, 0xac, 0xf1, 0xb4, 0xdc, 0x89, - 0x29, 0x3a, 0xb1, 0xe0, 0xd8, 0x92, 0xc8, 0x27, 0x4e, 0x82, 0x64, 0x65, 0xd3, 0xb3, 0xf2, 0x0c, - 0x46, 0x09, 0x49, 0xcf, 0x4e, 0x88, 0x02, 0x5b, 0x88, 0xf4, 0x74, 0x0b, 0x1b, 0xdd, 0xba, 0x61, - 0x0d, 0x6a, 0x7d, 0x6c, 0x98, 0x1a, 0xd1, 0x73, 0x0b, 0x34, 0x1d, 0xc9, 0xb1, 0xa5, 0x3c, 0x4b, - 0x27, 0x0c, 0x25, 0x2b, 0xd9, 0xa0, 0xf9, 0x7b, 0x66, 0x15, 0x8e, 0x01, 0xba, 0x06, 0x21, 0xcf, - 0x6a, 0x9a, 0xae, 0x59, 0xb9, 0xc5, 0x83, 0x64, 0x71, 0xad, 0xba, 0xed, 0xd8, 0xd2, 0xa6, 0xb7, - 0x31, 0xcf, 0x27, 0x2b, 0x2b, 0xf4, 0x81, 0x56, 0xc1, 0x39, 0xac, 0x31, 0x4f, 0x13, 0x6b, 0x6a, - 0xd3, 0xca, 0x65, 0xe8, 0x66, 0xc4, 0xc0, 0x66, 0x58, 0xb5, 0xf5, 0x0f, 0x4b, 0x5f, 0x51, 0x44, - 0x35, 0xef, 0x6e, 0xc5, 0xb1, 0xa5, 0x6c, 0x30, 0x2e, 0x9b, 0x2d, 0x2b, 0xab, 0xf4, 0x91, 0x21, - 0x03, 0xb2, 0x2f, 0x45, 0xc8, 0x9e, 0x87, 0xdb, 0x13, 0xba, 0xfa, 0xaa, 0xff, 0x31, 0xa1, 0x7a, - 0x05, 0xb5, 0x66, 0x53, 0xfd, 0x18, 0x60, 0x42, 0xec, 0x00, 0x27, 0x41, 0x8d, 0x57, 0x90, 0xaf, - 0xed, 0x39, 0xec, 0x8e, 0xf0, 0x1e, 0x08, 0x41, 0xeb, 0xb7, 0x2a, 0x3b, 0xb6, 0x54, 0x08, 0x11, - 0x28, 0x18, 0x6f, 0x3b, 0xe8, 0x19, 0xd6, 0xcd, 0x3c, 0x94, 0x3f, 0x04, 0x26, 0x68, 0xcd, 0x32, - 0x06, 0x5c, 0xf8, 0x2d, 0xc7, 0x96, 0x36, 0x82, 0x02, 0x59, 0xc6, 0x40, 0x56, 0x96, 0xe9, 0xd8, - 0x7d, 0x77, 0x3e, 0x30, 0xd9, 0x2b, 0xa8, 0xe5, 0xcb, 0xfe, 0x6b, 0x0a, 0xb6, 0x47, 0xbd, 0x27, - 0x44, 0x7f, 0xa6, 0x19, 0x9d, 0x9b, 0x90, 0xde, 0xa7, 0xb2, 0x8e, 0x5a, 0x54, 0xec, 0x10, 0x2a, - 0xeb, 0xa8, 0xe5, 0x51, 0xe9, 0x16, 0xe4, 0x38, 0x95, 0x0b, 0x73, 0xa1, 0x72, 0x31, 0x82, 0x4a, - 0x09, 0xf6, 0x43, 0xc9, 0xf2, 0xe9, 0xfc, 0x39, 0x09, 0xd9, 0x21, 0xe2, 0xa4, 0x4d, 0x4c, 0x3c, - 0x7b, 0xfb, 0x7f, 0x3b, 0x32, 0xa7, 0xb7, 0xfd, 0x7d, 0xc8, 0x87, 0xe4, 0xe6, 0xe7, 0xfe, 0x2a, - 0x05, 0x3b, 0x63, 0xfe, 0x1b, 0xac, 0x85, 0xd1, 0x86, 0x9a, 0x7e, 0xcb, 0x86, 0x7a, 0xb3, 0xe5, - 0x70, 0x00, 0x85, 0x70, 0xc2, 0x7c, 0x4e, 0x5f, 0xa4, 0xe0, 0xa3, 0x53, 0x53, 0x55, 0x30, 0xea, - 0x7f, 0x5b, 0x47, 0x2d, 0x6c, 0x09, 0x9f, 0x43, 0xa6, 0x4b, 0x47, 0x94, 0xc9, 0xd5, 0xa3, 0x7c, - 0xe8, 0x49, 0xc6, 0xc0, 0xfc, 0x20, 0xe3, 0x13, 0x84, 0x2f, 0x61, 0x83, 0xa5, 0x8b, 0x48, 0xa7, - 0xa3, 0x59, 0x1d, 0xac, 0x5b, 0x94, 0xde, 0xb5, 0x6a, 0xde, 0xb1, 0xa5, 0xdd, 0xe0, 0x86, 0x86, - 0x08, 0x59, 0x59, 0xa7, 0xa6, 0x13, 0xdf, 0x32, 0x41, 0x5a, 0x7a, 0x2e, 0xa4, 0x2d, 0x44, 0x90, - 0xb6, 0x4b, 0x1b, 0xce, 0x90, 0x11, 0x9f, 0xab, 0xbf, 0x52, 0x00, 0xa7, 0xa6, 0x7a, 0xa6, 0x75, - 0x30, 0xe9, 0xfd, 0x3f, 0x44, 0xf5, 0x74, 0x03, 0x23, 0xac, 0xf5, 0x71, 0x23, 0x8a, 0xa8, 0x21, - 0xc2, 0x23, 0xea, 0x3b, 0xdf, 0x32, 0x57, 0xa2, 0xbe, 0x06, 0x41, 0xc7, 0x97, 0x56, 0xcd, 0xc4, - 0x3f, 0xf6, 0xb0, 0x8e, 0x70, 0xcd, 0xc0, 0xa8, 0x4f, 0x49, 0x5b, 0xa8, 0xee, 0x3b, 0xb6, 0x74, - 0x9b, 0x45, 0x98, 0xc4, 0xc8, 0xca, 0x86, 0x6b, 0x7c, 0xca, 0x6d, 0x2e, 0x91, 0x31, 0x4a, 0x75, - 0x8b, 0xde, 0x4a, 0x39, 0xb7, 0xc3, 0x76, 0xc5, 0x0e, 0x7d, 0x6e, 0x7e, 0xa2, 0xd3, 0x1a, 0xfe, - 0x10, 0x98, 0xff, 0x14, 0x56, 0x79, 0x21, 0xbb, 0x19, 0xf1, 0x76, 0xb0, 0xe3, 0xd8, 0x92, 0x30, - 0x52, 0xe5, 0xae, 0x53, 0x56, 0x58, 0xe3, 0x60, 0xb9, 0xcf, 0xb3, 0x21, 0x84, 0x4b, 0xb6, 0xf8, - 0xae, 0x92, 0x65, 0xfe, 0xf3, 0xdc, 0x1e, 0xd5, 0xc6, 0x57, 0xee, 0xb7, 0x14, 0x15, 0xb4, 0x82, - 0x5a, 0x3a, 0x79, 0xde, 0xc6, 0x0d, 0x15, 0xd3, 0x57, 0xfb, 0x1d, 0xa4, 0x2b, 0xc2, 0x7a, 0x7d, - 0x34, 0x1a, 0x53, 0x4e, 0x19, 0x37, 0x0f, 0xc5, 0x71, 0x27, 0x36, 0xa2, 0xc4, 0xa1, 0x4e, 0x4f, - 0x9c, 0x8a, 0xfb, 0xf0, 0x9e, 0xbb, 0x35, 0xfb, 0xea, 0x19, 0x63, 0xcc, 0x23, 0xf4, 0xe8, 0xd5, - 0x32, 0xa4, 0x4f, 0x4d, 0x55, 0x68, 0xc1, 0xfa, 0xf8, 0xb7, 0xdb, 0xdd, 0x50, 0x12, 0x27, 0xbf, - 0xa0, 0xc4, 0x72, 0x4c, 0xa0, 0xb7, 0xa8, 0xd0, 0x84, 0x5b, 0x63, 0x9f, 0x59, 0x77, 0x62, 0x84, - 0x38, 0x33, 0x06, 0x62, 0x29, 0x1e, 0x2e, 0x62, 0x25, 0xf7, 0x26, 0x15, 0x67, 0xa5, 0x0a, 0x6a, - 0xc5, 0x5a, 0x29, 0x70, 0xa3, 0x14, 0x2c, 0x10, 0x42, 0x6e, 0x93, 0xf7, 0x62, 0x44, 0xe1, 0x58, - 0xf1, 0x28, 0x3e, 0xd6, 0x5f, 0x55, 0x87, 0x8d, 0x89, 0x4b, 0x57, 0x71, 0x4a, 0x1c, 0x1f, 0x29, - 0x3e, 0x88, 0x8b, 0xf4, 0xd7, 0x7b, 0x0e, 0xd9, 0xd0, 0x8b, 0x52, 0x9c, 0x40, 0xde, 0x3e, 0x1f, - 0xce, 0x00, 0xf6, 0x17, 0xfe, 0x01, 0x20, 0x70, 0x9b, 0x90, 0xa3, 0x42, 0x0c, 0x31, 0xe2, 0xbd, - 0xe9, 0x18, 0x3f, 0xfa, 0x53, 0x58, 0xf2, 0xce, 0x5f, 0x29, 0x6a, 0x1a, 0x07, 0x88, 0x77, 0xa7, - 0x00, 0x82, 0xb5, 0x37, 0x76, 0xc2, 0xdc, 0x99, 0x32, 0x95, 0xe3, 0xa2, 0x6b, 0x2f, 0xbc, 0x2b, - 0xba, 0x2f, 0xef, 0x78, 0x47, 0x8c, 0xcc, 0x72, 0x0c, 0x18, 0xfd, 0xf2, 0x46, 0x74, 0x8c, 0xaa, - 0xf2, 0xfa, 0xaa, 0x90, 0x7c, 0x73, 0x55, 0x48, 0xfe, 0x7d, 0x55, 0x48, 0xbe, 0xb8, 0x2e, 0x24, - 0xde, 0x5c, 0x17, 0x12, 0x7f, 0x5e, 0x17, 0x12, 0xe7, 0x9f, 0xa9, 0x9a, 0xd5, 0xec, 0x5d, 0x94, - 0x10, 0xe9, 0x94, 0x11, 0x31, 0x3b, 0xc4, 0xe4, 0x3f, 0xf7, 0xcd, 0x46, 0xab, 0x7c, 0x59, 0xf6, - 0xff, 0x45, 0x7a, 0x70, 0x7c, 0xdf, 0xfb, 0x23, 0xc9, 0x1a, 0x74, 0xb1, 0x79, 0x91, 0xa1, 0x7f, - 0x22, 0x3d, 0xfc, 0x37, 0x00, 0x00, 0xff, 0xff, 0x38, 0xe9, 0x16, 0xfa, 0xd3, 0x12, 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 { - // ChannelOpenInit defines a rpc handler method for MsgChannelOpenInit. - ChannelOpenInit(ctx context.Context, in *MsgChannelOpenInit, opts ...grpc.CallOption) (*MsgChannelOpenInitResponse, error) - // ChannelOpenTry defines a rpc handler method for MsgChannelOpenTry. - ChannelOpenTry(ctx context.Context, in *MsgChannelOpenTry, opts ...grpc.CallOption) (*MsgChannelOpenTryResponse, error) - // ChannelOpenAck defines a rpc handler method for MsgChannelOpenAck. - ChannelOpenAck(ctx context.Context, in *MsgChannelOpenAck, opts ...grpc.CallOption) (*MsgChannelOpenAckResponse, error) - // ChannelOpenConfirm defines a rpc handler method for MsgChannelOpenConfirm. - ChannelOpenConfirm(ctx context.Context, in *MsgChannelOpenConfirm, opts ...grpc.CallOption) (*MsgChannelOpenConfirmResponse, error) - // ChannelCloseInit defines a rpc handler method for MsgChannelCloseInit. - ChannelCloseInit(ctx context.Context, in *MsgChannelCloseInit, opts ...grpc.CallOption) (*MsgChannelCloseInitResponse, error) - // ChannelCloseConfirm defines a rpc handler method for MsgChannelCloseConfirm. - ChannelCloseConfirm(ctx context.Context, in *MsgChannelCloseConfirm, opts ...grpc.CallOption) (*MsgChannelCloseConfirmResponse, error) - // RecvPacket defines a rpc handler method for MsgRecvPacket. - RecvPacket(ctx context.Context, in *MsgRecvPacket, opts ...grpc.CallOption) (*MsgRecvPacketResponse, error) - // Timeout defines a rpc handler method for MsgTimeout. - Timeout(ctx context.Context, in *MsgTimeout, opts ...grpc.CallOption) (*MsgTimeoutResponse, error) - // TimeoutOnClose defines a rpc handler method for MsgTimeoutOnClose. - TimeoutOnClose(ctx context.Context, in *MsgTimeoutOnClose, opts ...grpc.CallOption) (*MsgTimeoutOnCloseResponse, error) - // Acknowledgement defines a rpc handler method for MsgAcknowledgement. - Acknowledgement(ctx context.Context, in *MsgAcknowledgement, opts ...grpc.CallOption) (*MsgAcknowledgementResponse, error) -} - -type msgClient struct { - cc grpc1.ClientConn -} - -func NewMsgClient(cc grpc1.ClientConn) MsgClient { - return &msgClient{cc} -} - -func (c *msgClient) ChannelOpenInit(ctx context.Context, in *MsgChannelOpenInit, opts ...grpc.CallOption) (*MsgChannelOpenInitResponse, error) { - out := new(MsgChannelOpenInitResponse) - err := c.cc.Invoke(ctx, "/ibc.core.channel.v1.Msg/ChannelOpenInit", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *msgClient) ChannelOpenTry(ctx context.Context, in *MsgChannelOpenTry, opts ...grpc.CallOption) (*MsgChannelOpenTryResponse, error) { - out := new(MsgChannelOpenTryResponse) - err := c.cc.Invoke(ctx, "/ibc.core.channel.v1.Msg/ChannelOpenTry", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *msgClient) ChannelOpenAck(ctx context.Context, in *MsgChannelOpenAck, opts ...grpc.CallOption) (*MsgChannelOpenAckResponse, error) { - out := new(MsgChannelOpenAckResponse) - err := c.cc.Invoke(ctx, "/ibc.core.channel.v1.Msg/ChannelOpenAck", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *msgClient) ChannelOpenConfirm(ctx context.Context, in *MsgChannelOpenConfirm, opts ...grpc.CallOption) (*MsgChannelOpenConfirmResponse, error) { - out := new(MsgChannelOpenConfirmResponse) - err := c.cc.Invoke(ctx, "/ibc.core.channel.v1.Msg/ChannelOpenConfirm", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *msgClient) ChannelCloseInit(ctx context.Context, in *MsgChannelCloseInit, opts ...grpc.CallOption) (*MsgChannelCloseInitResponse, error) { - out := new(MsgChannelCloseInitResponse) - err := c.cc.Invoke(ctx, "/ibc.core.channel.v1.Msg/ChannelCloseInit", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *msgClient) ChannelCloseConfirm(ctx context.Context, in *MsgChannelCloseConfirm, opts ...grpc.CallOption) (*MsgChannelCloseConfirmResponse, error) { - out := new(MsgChannelCloseConfirmResponse) - err := c.cc.Invoke(ctx, "/ibc.core.channel.v1.Msg/ChannelCloseConfirm", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *msgClient) RecvPacket(ctx context.Context, in *MsgRecvPacket, opts ...grpc.CallOption) (*MsgRecvPacketResponse, error) { - out := new(MsgRecvPacketResponse) - err := c.cc.Invoke(ctx, "/ibc.core.channel.v1.Msg/RecvPacket", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *msgClient) Timeout(ctx context.Context, in *MsgTimeout, opts ...grpc.CallOption) (*MsgTimeoutResponse, error) { - out := new(MsgTimeoutResponse) - err := c.cc.Invoke(ctx, "/ibc.core.channel.v1.Msg/Timeout", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *msgClient) TimeoutOnClose(ctx context.Context, in *MsgTimeoutOnClose, opts ...grpc.CallOption) (*MsgTimeoutOnCloseResponse, error) { - out := new(MsgTimeoutOnCloseResponse) - err := c.cc.Invoke(ctx, "/ibc.core.channel.v1.Msg/TimeoutOnClose", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *msgClient) Acknowledgement(ctx context.Context, in *MsgAcknowledgement, opts ...grpc.CallOption) (*MsgAcknowledgementResponse, error) { - out := new(MsgAcknowledgementResponse) - err := c.cc.Invoke(ctx, "/ibc.core.channel.v1.Msg/Acknowledgement", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// MsgServer is the server API for Msg service. -type MsgServer interface { - // ChannelOpenInit defines a rpc handler method for MsgChannelOpenInit. - ChannelOpenInit(context.Context, *MsgChannelOpenInit) (*MsgChannelOpenInitResponse, error) - // ChannelOpenTry defines a rpc handler method for MsgChannelOpenTry. - ChannelOpenTry(context.Context, *MsgChannelOpenTry) (*MsgChannelOpenTryResponse, error) - // ChannelOpenAck defines a rpc handler method for MsgChannelOpenAck. - ChannelOpenAck(context.Context, *MsgChannelOpenAck) (*MsgChannelOpenAckResponse, error) - // ChannelOpenConfirm defines a rpc handler method for MsgChannelOpenConfirm. - ChannelOpenConfirm(context.Context, *MsgChannelOpenConfirm) (*MsgChannelOpenConfirmResponse, error) - // ChannelCloseInit defines a rpc handler method for MsgChannelCloseInit. - ChannelCloseInit(context.Context, *MsgChannelCloseInit) (*MsgChannelCloseInitResponse, error) - // ChannelCloseConfirm defines a rpc handler method for MsgChannelCloseConfirm. - ChannelCloseConfirm(context.Context, *MsgChannelCloseConfirm) (*MsgChannelCloseConfirmResponse, error) - // RecvPacket defines a rpc handler method for MsgRecvPacket. - RecvPacket(context.Context, *MsgRecvPacket) (*MsgRecvPacketResponse, error) - // Timeout defines a rpc handler method for MsgTimeout. - Timeout(context.Context, *MsgTimeout) (*MsgTimeoutResponse, error) - // TimeoutOnClose defines a rpc handler method for MsgTimeoutOnClose. - TimeoutOnClose(context.Context, *MsgTimeoutOnClose) (*MsgTimeoutOnCloseResponse, error) - // Acknowledgement defines a rpc handler method for MsgAcknowledgement. - Acknowledgement(context.Context, *MsgAcknowledgement) (*MsgAcknowledgementResponse, error) -} - -// UnimplementedMsgServer can be embedded to have forward compatible implementations. -type UnimplementedMsgServer struct { -} - -func (*UnimplementedMsgServer) ChannelOpenInit(ctx context.Context, req *MsgChannelOpenInit) (*MsgChannelOpenInitResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ChannelOpenInit not implemented") -} -func (*UnimplementedMsgServer) ChannelOpenTry(ctx context.Context, req *MsgChannelOpenTry) (*MsgChannelOpenTryResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ChannelOpenTry not implemented") -} -func (*UnimplementedMsgServer) ChannelOpenAck(ctx context.Context, req *MsgChannelOpenAck) (*MsgChannelOpenAckResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ChannelOpenAck not implemented") -} -func (*UnimplementedMsgServer) ChannelOpenConfirm(ctx context.Context, req *MsgChannelOpenConfirm) (*MsgChannelOpenConfirmResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ChannelOpenConfirm not implemented") -} -func (*UnimplementedMsgServer) ChannelCloseInit(ctx context.Context, req *MsgChannelCloseInit) (*MsgChannelCloseInitResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ChannelCloseInit not implemented") -} -func (*UnimplementedMsgServer) ChannelCloseConfirm(ctx context.Context, req *MsgChannelCloseConfirm) (*MsgChannelCloseConfirmResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ChannelCloseConfirm not implemented") -} -func (*UnimplementedMsgServer) RecvPacket(ctx context.Context, req *MsgRecvPacket) (*MsgRecvPacketResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method RecvPacket not implemented") -} -func (*UnimplementedMsgServer) Timeout(ctx context.Context, req *MsgTimeout) (*MsgTimeoutResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method Timeout not implemented") -} -func (*UnimplementedMsgServer) TimeoutOnClose(ctx context.Context, req *MsgTimeoutOnClose) (*MsgTimeoutOnCloseResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method TimeoutOnClose not implemented") -} -func (*UnimplementedMsgServer) Acknowledgement(ctx context.Context, req *MsgAcknowledgement) (*MsgAcknowledgementResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method Acknowledgement not implemented") -} - -func RegisterMsgServer(s grpc1.Server, srv MsgServer) { - s.RegisterService(&_Msg_serviceDesc, srv) -} - -func _Msg_ChannelOpenInit_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgChannelOpenInit) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MsgServer).ChannelOpenInit(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.channel.v1.Msg/ChannelOpenInit", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).ChannelOpenInit(ctx, req.(*MsgChannelOpenInit)) - } - return interceptor(ctx, in, info, handler) -} - -func _Msg_ChannelOpenTry_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgChannelOpenTry) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MsgServer).ChannelOpenTry(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.channel.v1.Msg/ChannelOpenTry", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).ChannelOpenTry(ctx, req.(*MsgChannelOpenTry)) - } - return interceptor(ctx, in, info, handler) -} - -func _Msg_ChannelOpenAck_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgChannelOpenAck) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MsgServer).ChannelOpenAck(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.channel.v1.Msg/ChannelOpenAck", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).ChannelOpenAck(ctx, req.(*MsgChannelOpenAck)) - } - return interceptor(ctx, in, info, handler) -} - -func _Msg_ChannelOpenConfirm_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgChannelOpenConfirm) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MsgServer).ChannelOpenConfirm(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.channel.v1.Msg/ChannelOpenConfirm", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).ChannelOpenConfirm(ctx, req.(*MsgChannelOpenConfirm)) - } - return interceptor(ctx, in, info, handler) -} - -func _Msg_ChannelCloseInit_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgChannelCloseInit) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MsgServer).ChannelCloseInit(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.channel.v1.Msg/ChannelCloseInit", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).ChannelCloseInit(ctx, req.(*MsgChannelCloseInit)) - } - return interceptor(ctx, in, info, handler) -} - -func _Msg_ChannelCloseConfirm_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgChannelCloseConfirm) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MsgServer).ChannelCloseConfirm(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.channel.v1.Msg/ChannelCloseConfirm", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).ChannelCloseConfirm(ctx, req.(*MsgChannelCloseConfirm)) - } - return interceptor(ctx, in, info, handler) -} - -func _Msg_RecvPacket_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgRecvPacket) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MsgServer).RecvPacket(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.channel.v1.Msg/RecvPacket", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).RecvPacket(ctx, req.(*MsgRecvPacket)) - } - return interceptor(ctx, in, info, handler) -} - -func _Msg_Timeout_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgTimeout) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MsgServer).Timeout(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.channel.v1.Msg/Timeout", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).Timeout(ctx, req.(*MsgTimeout)) - } - return interceptor(ctx, in, info, handler) -} - -func _Msg_TimeoutOnClose_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgTimeoutOnClose) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MsgServer).TimeoutOnClose(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.channel.v1.Msg/TimeoutOnClose", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).TimeoutOnClose(ctx, req.(*MsgTimeoutOnClose)) - } - return interceptor(ctx, in, info, handler) -} - -func _Msg_Acknowledgement_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgAcknowledgement) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MsgServer).Acknowledgement(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/ibc.core.channel.v1.Msg/Acknowledgement", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).Acknowledgement(ctx, req.(*MsgAcknowledgement)) - } - return interceptor(ctx, in, info, handler) -} - -var _Msg_serviceDesc = grpc.ServiceDesc{ - ServiceName: "ibc.core.channel.v1.Msg", - HandlerType: (*MsgServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "ChannelOpenInit", - Handler: _Msg_ChannelOpenInit_Handler, - }, - { - MethodName: "ChannelOpenTry", - Handler: _Msg_ChannelOpenTry_Handler, - }, - { - MethodName: "ChannelOpenAck", - Handler: _Msg_ChannelOpenAck_Handler, - }, - { - MethodName: "ChannelOpenConfirm", - Handler: _Msg_ChannelOpenConfirm_Handler, - }, - { - MethodName: "ChannelCloseInit", - Handler: _Msg_ChannelCloseInit_Handler, - }, - { - MethodName: "ChannelCloseConfirm", - Handler: _Msg_ChannelCloseConfirm_Handler, - }, - { - MethodName: "RecvPacket", - Handler: _Msg_RecvPacket_Handler, - }, - { - MethodName: "Timeout", - Handler: _Msg_Timeout_Handler, - }, - { - MethodName: "TimeoutOnClose", - Handler: _Msg_TimeoutOnClose_Handler, - }, - { - MethodName: "Acknowledgement", - Handler: _Msg_Acknowledgement_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "ibc/core/channel/v1/tx.proto", -} - -func (m *MsgChannelOpenInit) 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 *MsgChannelOpenInit) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgChannelOpenInit) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Signer) > 0 { - i -= len(m.Signer) - copy(dAtA[i:], m.Signer) - i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) - i-- - dAtA[i] = 0x1a - } - { - size, err := m.Channel.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - if len(m.PortId) > 0 { - i -= len(m.PortId) - copy(dAtA[i:], m.PortId) - i = encodeVarintTx(dAtA, i, uint64(len(m.PortId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *MsgChannelOpenInitResponse) 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 *MsgChannelOpenInitResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgChannelOpenInitResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - return len(dAtA) - i, nil -} - -func (m *MsgChannelOpenTry) 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 *MsgChannelOpenTry) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgChannelOpenTry) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Signer) > 0 { - i -= len(m.Signer) - copy(dAtA[i:], m.Signer) - i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) - i-- - dAtA[i] = 0x3a - } - { - size, err := m.ProofHeight.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x32 - if len(m.ProofInit) > 0 { - i -= len(m.ProofInit) - copy(dAtA[i:], m.ProofInit) - i = encodeVarintTx(dAtA, i, uint64(len(m.ProofInit))) - i-- - dAtA[i] = 0x2a - } - if len(m.CounterpartyVersion) > 0 { - i -= len(m.CounterpartyVersion) - copy(dAtA[i:], m.CounterpartyVersion) - i = encodeVarintTx(dAtA, i, uint64(len(m.CounterpartyVersion))) - i-- - dAtA[i] = 0x22 - } - { - size, err := m.Channel.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - if len(m.PreviousChannelId) > 0 { - i -= len(m.PreviousChannelId) - copy(dAtA[i:], m.PreviousChannelId) - i = encodeVarintTx(dAtA, i, uint64(len(m.PreviousChannelId))) - i-- - dAtA[i] = 0x12 - } - if len(m.PortId) > 0 { - i -= len(m.PortId) - copy(dAtA[i:], m.PortId) - i = encodeVarintTx(dAtA, i, uint64(len(m.PortId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *MsgChannelOpenTryResponse) 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 *MsgChannelOpenTryResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgChannelOpenTryResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - return len(dAtA) - i, nil -} - -func (m *MsgChannelOpenAck) 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 *MsgChannelOpenAck) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgChannelOpenAck) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Signer) > 0 { - i -= len(m.Signer) - copy(dAtA[i:], m.Signer) - i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) - i-- - dAtA[i] = 0x3a - } - { - size, err := m.ProofHeight.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x32 - if len(m.ProofTry) > 0 { - i -= len(m.ProofTry) - copy(dAtA[i:], m.ProofTry) - i = encodeVarintTx(dAtA, i, uint64(len(m.ProofTry))) - i-- - dAtA[i] = 0x2a - } - if len(m.CounterpartyVersion) > 0 { - i -= len(m.CounterpartyVersion) - copy(dAtA[i:], m.CounterpartyVersion) - i = encodeVarintTx(dAtA, i, uint64(len(m.CounterpartyVersion))) - i-- - dAtA[i] = 0x22 - } - if len(m.CounterpartyChannelId) > 0 { - i -= len(m.CounterpartyChannelId) - copy(dAtA[i:], m.CounterpartyChannelId) - i = encodeVarintTx(dAtA, i, uint64(len(m.CounterpartyChannelId))) - i-- - dAtA[i] = 0x1a - } - if len(m.ChannelId) > 0 { - i -= len(m.ChannelId) - copy(dAtA[i:], m.ChannelId) - i = encodeVarintTx(dAtA, i, uint64(len(m.ChannelId))) - i-- - dAtA[i] = 0x12 - } - if len(m.PortId) > 0 { - i -= len(m.PortId) - copy(dAtA[i:], m.PortId) - i = encodeVarintTx(dAtA, i, uint64(len(m.PortId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *MsgChannelOpenAckResponse) 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 *MsgChannelOpenAckResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgChannelOpenAckResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - return len(dAtA) - i, nil -} - -func (m *MsgChannelOpenConfirm) 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 *MsgChannelOpenConfirm) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgChannelOpenConfirm) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Signer) > 0 { - i -= len(m.Signer) - copy(dAtA[i:], m.Signer) - i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) - i-- - dAtA[i] = 0x2a - } - { - size, err := m.ProofHeight.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x22 - if len(m.ProofAck) > 0 { - i -= len(m.ProofAck) - copy(dAtA[i:], m.ProofAck) - i = encodeVarintTx(dAtA, i, uint64(len(m.ProofAck))) - i-- - dAtA[i] = 0x1a - } - if len(m.ChannelId) > 0 { - i -= len(m.ChannelId) - copy(dAtA[i:], m.ChannelId) - i = encodeVarintTx(dAtA, i, uint64(len(m.ChannelId))) - i-- - dAtA[i] = 0x12 - } - if len(m.PortId) > 0 { - i -= len(m.PortId) - copy(dAtA[i:], m.PortId) - i = encodeVarintTx(dAtA, i, uint64(len(m.PortId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *MsgChannelOpenConfirmResponse) 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 *MsgChannelOpenConfirmResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgChannelOpenConfirmResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - return len(dAtA) - i, nil -} - -func (m *MsgChannelCloseInit) 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 *MsgChannelCloseInit) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgChannelCloseInit) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Signer) > 0 { - i -= len(m.Signer) - copy(dAtA[i:], m.Signer) - i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) - i-- - dAtA[i] = 0x1a - } - if len(m.ChannelId) > 0 { - i -= len(m.ChannelId) - copy(dAtA[i:], m.ChannelId) - i = encodeVarintTx(dAtA, i, uint64(len(m.ChannelId))) - i-- - dAtA[i] = 0x12 - } - if len(m.PortId) > 0 { - i -= len(m.PortId) - copy(dAtA[i:], m.PortId) - i = encodeVarintTx(dAtA, i, uint64(len(m.PortId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *MsgChannelCloseInitResponse) 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 *MsgChannelCloseInitResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgChannelCloseInitResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - return len(dAtA) - i, nil -} - -func (m *MsgChannelCloseConfirm) 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 *MsgChannelCloseConfirm) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgChannelCloseConfirm) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Signer) > 0 { - i -= len(m.Signer) - copy(dAtA[i:], m.Signer) - i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) - i-- - dAtA[i] = 0x2a - } - { - size, err := m.ProofHeight.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x22 - if len(m.ProofInit) > 0 { - i -= len(m.ProofInit) - copy(dAtA[i:], m.ProofInit) - i = encodeVarintTx(dAtA, i, uint64(len(m.ProofInit))) - i-- - dAtA[i] = 0x1a - } - if len(m.ChannelId) > 0 { - i -= len(m.ChannelId) - copy(dAtA[i:], m.ChannelId) - i = encodeVarintTx(dAtA, i, uint64(len(m.ChannelId))) - i-- - dAtA[i] = 0x12 - } - if len(m.PortId) > 0 { - i -= len(m.PortId) - copy(dAtA[i:], m.PortId) - i = encodeVarintTx(dAtA, i, uint64(len(m.PortId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *MsgChannelCloseConfirmResponse) 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 *MsgChannelCloseConfirmResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgChannelCloseConfirmResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - return len(dAtA) - i, nil -} - -func (m *MsgRecvPacket) 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 *MsgRecvPacket) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgRecvPacket) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Signer) > 0 { - i -= len(m.Signer) - copy(dAtA[i:], m.Signer) - i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) - i-- - dAtA[i] = 0x22 - } - { - size, err := m.ProofHeight.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - if len(m.ProofCommitment) > 0 { - i -= len(m.ProofCommitment) - copy(dAtA[i:], m.ProofCommitment) - i = encodeVarintTx(dAtA, i, uint64(len(m.ProofCommitment))) - i-- - dAtA[i] = 0x12 - } - { - size, err := m.Packet.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 *MsgRecvPacketResponse) 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 *MsgRecvPacketResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgRecvPacketResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - return len(dAtA) - i, nil -} - -func (m *MsgTimeout) 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 *MsgTimeout) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgTimeout) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Signer) > 0 { - i -= len(m.Signer) - copy(dAtA[i:], m.Signer) - i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) - i-- - dAtA[i] = 0x2a - } - if m.NextSequenceRecv != 0 { - i = encodeVarintTx(dAtA, i, uint64(m.NextSequenceRecv)) - i-- - dAtA[i] = 0x20 - } - { - size, err := m.ProofHeight.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - if len(m.ProofUnreceived) > 0 { - i -= len(m.ProofUnreceived) - copy(dAtA[i:], m.ProofUnreceived) - i = encodeVarintTx(dAtA, i, uint64(len(m.ProofUnreceived))) - i-- - dAtA[i] = 0x12 - } - { - size, err := m.Packet.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 *MsgTimeoutResponse) 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 *MsgTimeoutResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgTimeoutResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - return len(dAtA) - i, nil -} - -func (m *MsgTimeoutOnClose) 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 *MsgTimeoutOnClose) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgTimeoutOnClose) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Signer) > 0 { - i -= len(m.Signer) - copy(dAtA[i:], m.Signer) - i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) - i-- - dAtA[i] = 0x32 - } - if m.NextSequenceRecv != 0 { - i = encodeVarintTx(dAtA, i, uint64(m.NextSequenceRecv)) - i-- - dAtA[i] = 0x28 - } - { - size, err := m.ProofHeight.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x22 - if len(m.ProofClose) > 0 { - i -= len(m.ProofClose) - copy(dAtA[i:], m.ProofClose) - i = encodeVarintTx(dAtA, i, uint64(len(m.ProofClose))) - i-- - dAtA[i] = 0x1a - } - if len(m.ProofUnreceived) > 0 { - i -= len(m.ProofUnreceived) - copy(dAtA[i:], m.ProofUnreceived) - i = encodeVarintTx(dAtA, i, uint64(len(m.ProofUnreceived))) - i-- - dAtA[i] = 0x12 - } - { - size, err := m.Packet.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 *MsgTimeoutOnCloseResponse) 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 *MsgTimeoutOnCloseResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgTimeoutOnCloseResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - return len(dAtA) - i, nil -} - -func (m *MsgAcknowledgement) 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 *MsgAcknowledgement) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgAcknowledgement) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Signer) > 0 { - i -= len(m.Signer) - copy(dAtA[i:], m.Signer) - i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) - i-- - dAtA[i] = 0x2a - } - { - size, err := m.ProofHeight.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x22 - if len(m.ProofAcked) > 0 { - i -= len(m.ProofAcked) - copy(dAtA[i:], m.ProofAcked) - i = encodeVarintTx(dAtA, i, uint64(len(m.ProofAcked))) - i-- - dAtA[i] = 0x1a - } - if len(m.Acknowledgement) > 0 { - i -= len(m.Acknowledgement) - copy(dAtA[i:], m.Acknowledgement) - i = encodeVarintTx(dAtA, i, uint64(len(m.Acknowledgement))) - i-- - dAtA[i] = 0x12 - } - { - size, err := m.Packet.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 *MsgAcknowledgementResponse) 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 *MsgAcknowledgementResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgAcknowledgementResponse) 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 *MsgChannelOpenInit) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.PortId) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = m.Channel.Size() - n += 1 + l + sovTx(uint64(l)) - l = len(m.Signer) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - return n -} - -func (m *MsgChannelOpenInitResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - return n -} - -func (m *MsgChannelOpenTry) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.PortId) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.PreviousChannelId) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = m.Channel.Size() - n += 1 + l + sovTx(uint64(l)) - l = len(m.CounterpartyVersion) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.ProofInit) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = m.ProofHeight.Size() - n += 1 + l + sovTx(uint64(l)) - l = len(m.Signer) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - return n -} - -func (m *MsgChannelOpenTryResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - return n -} - -func (m *MsgChannelOpenAck) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.PortId) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.ChannelId) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.CounterpartyChannelId) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.CounterpartyVersion) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.ProofTry) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = m.ProofHeight.Size() - n += 1 + l + sovTx(uint64(l)) - l = len(m.Signer) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - return n -} - -func (m *MsgChannelOpenAckResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - return n -} - -func (m *MsgChannelOpenConfirm) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.PortId) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.ChannelId) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.ProofAck) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = m.ProofHeight.Size() - n += 1 + l + sovTx(uint64(l)) - l = len(m.Signer) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - return n -} - -func (m *MsgChannelOpenConfirmResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - return n -} - -func (m *MsgChannelCloseInit) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.PortId) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.ChannelId) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.Signer) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - return n -} - -func (m *MsgChannelCloseInitResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - return n -} - -func (m *MsgChannelCloseConfirm) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.PortId) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.ChannelId) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.ProofInit) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = m.ProofHeight.Size() - n += 1 + l + sovTx(uint64(l)) - l = len(m.Signer) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - return n -} - -func (m *MsgChannelCloseConfirmResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - return n -} - -func (m *MsgRecvPacket) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = m.Packet.Size() - n += 1 + l + sovTx(uint64(l)) - l = len(m.ProofCommitment) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = m.ProofHeight.Size() - n += 1 + l + sovTx(uint64(l)) - l = len(m.Signer) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - return n -} - -func (m *MsgRecvPacketResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - return n -} - -func (m *MsgTimeout) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = m.Packet.Size() - n += 1 + l + sovTx(uint64(l)) - l = len(m.ProofUnreceived) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = m.ProofHeight.Size() - n += 1 + l + sovTx(uint64(l)) - if m.NextSequenceRecv != 0 { - n += 1 + sovTx(uint64(m.NextSequenceRecv)) - } - l = len(m.Signer) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - return n -} - -func (m *MsgTimeoutResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - return n -} - -func (m *MsgTimeoutOnClose) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = m.Packet.Size() - n += 1 + l + sovTx(uint64(l)) - l = len(m.ProofUnreceived) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.ProofClose) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = m.ProofHeight.Size() - n += 1 + l + sovTx(uint64(l)) - if m.NextSequenceRecv != 0 { - n += 1 + sovTx(uint64(m.NextSequenceRecv)) - } - l = len(m.Signer) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - return n -} - -func (m *MsgTimeoutOnCloseResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - return n -} - -func (m *MsgAcknowledgement) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = m.Packet.Size() - n += 1 + l + sovTx(uint64(l)) - l = len(m.Acknowledgement) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.ProofAcked) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = m.ProofHeight.Size() - n += 1 + l + sovTx(uint64(l)) - l = len(m.Signer) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - return n -} - -func (m *MsgAcknowledgementResponse) 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 *MsgChannelOpenInit) 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: MsgChannelOpenInit: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgChannelOpenInit: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field PortId", 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.PortId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Channel", 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 := m.Channel.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Signer", 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.Signer = 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 *MsgChannelOpenInitResponse) 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: MsgChannelOpenInitResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgChannelOpenInitResponse: 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 *MsgChannelOpenTry) 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: MsgChannelOpenTry: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgChannelOpenTry: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field PortId", 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.PortId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field PreviousChannelId", 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.PreviousChannelId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Channel", 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 := m.Channel.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field CounterpartyVersion", 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.CounterpartyVersion = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofInit", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ProofInit = append(m.ProofInit[:0], dAtA[iNdEx:postIndex]...) - if m.ProofInit == nil { - m.ProofInit = []byte{} - } - iNdEx = postIndex - case 6: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofHeight", 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 := m.ProofHeight.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 7: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Signer", 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.Signer = 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 *MsgChannelOpenTryResponse) 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: MsgChannelOpenTryResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgChannelOpenTryResponse: 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 *MsgChannelOpenAck) 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: MsgChannelOpenAck: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgChannelOpenAck: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field PortId", 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.PortId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ChannelId", 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.ChannelId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field CounterpartyChannelId", 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.CounterpartyChannelId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field CounterpartyVersion", 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.CounterpartyVersion = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofTry", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ProofTry = append(m.ProofTry[:0], dAtA[iNdEx:postIndex]...) - if m.ProofTry == nil { - m.ProofTry = []byte{} - } - iNdEx = postIndex - case 6: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofHeight", 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 := m.ProofHeight.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 7: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Signer", 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.Signer = 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 *MsgChannelOpenAckResponse) 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: MsgChannelOpenAckResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgChannelOpenAckResponse: 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 *MsgChannelOpenConfirm) 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: MsgChannelOpenConfirm: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgChannelOpenConfirm: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field PortId", 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.PortId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ChannelId", 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.ChannelId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofAck", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ProofAck = append(m.ProofAck[:0], dAtA[iNdEx:postIndex]...) - if m.ProofAck == nil { - m.ProofAck = []byte{} - } - iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofHeight", 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 := m.ProofHeight.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Signer", 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.Signer = 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 *MsgChannelOpenConfirmResponse) 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: MsgChannelOpenConfirmResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgChannelOpenConfirmResponse: 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 *MsgChannelCloseInit) 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: MsgChannelCloseInit: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgChannelCloseInit: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field PortId", 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.PortId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ChannelId", 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.ChannelId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Signer", 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.Signer = 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 *MsgChannelCloseInitResponse) 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: MsgChannelCloseInitResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgChannelCloseInitResponse: 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 *MsgChannelCloseConfirm) 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: MsgChannelCloseConfirm: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgChannelCloseConfirm: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field PortId", 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.PortId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ChannelId", 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.ChannelId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofInit", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ProofInit = append(m.ProofInit[:0], dAtA[iNdEx:postIndex]...) - if m.ProofInit == nil { - m.ProofInit = []byte{} - } - iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofHeight", 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 := m.ProofHeight.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Signer", 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.Signer = 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 *MsgChannelCloseConfirmResponse) 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: MsgChannelCloseConfirmResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgChannelCloseConfirmResponse: 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 *MsgRecvPacket) 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: MsgRecvPacket: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgRecvPacket: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Packet", 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 := m.Packet.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofCommitment", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ProofCommitment = append(m.ProofCommitment[:0], dAtA[iNdEx:postIndex]...) - if m.ProofCommitment == nil { - m.ProofCommitment = []byte{} - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofHeight", 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 := m.ProofHeight.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Signer", 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.Signer = 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 *MsgRecvPacketResponse) 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: MsgRecvPacketResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgRecvPacketResponse: 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 *MsgTimeout) 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: MsgTimeout: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgTimeout: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Packet", 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 := m.Packet.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofUnreceived", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ProofUnreceived = append(m.ProofUnreceived[:0], dAtA[iNdEx:postIndex]...) - if m.ProofUnreceived == nil { - m.ProofUnreceived = []byte{} - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofHeight", 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 := m.ProofHeight.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 4: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field NextSequenceRecv", wireType) - } - m.NextSequenceRecv = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.NextSequenceRecv |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Signer", 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.Signer = 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 *MsgTimeoutResponse) 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: MsgTimeoutResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgTimeoutResponse: 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 *MsgTimeoutOnClose) 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: MsgTimeoutOnClose: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgTimeoutOnClose: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Packet", 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 := m.Packet.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofUnreceived", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ProofUnreceived = append(m.ProofUnreceived[:0], dAtA[iNdEx:postIndex]...) - if m.ProofUnreceived == nil { - m.ProofUnreceived = []byte{} - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofClose", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ProofClose = append(m.ProofClose[:0], dAtA[iNdEx:postIndex]...) - if m.ProofClose == nil { - m.ProofClose = []byte{} - } - iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofHeight", 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 := m.ProofHeight.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 5: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field NextSequenceRecv", wireType) - } - m.NextSequenceRecv = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.NextSequenceRecv |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 6: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Signer", 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.Signer = 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 *MsgTimeoutOnCloseResponse) 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: MsgTimeoutOnCloseResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgTimeoutOnCloseResponse: 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 *MsgAcknowledgement) 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: MsgAcknowledgement: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgAcknowledgement: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Packet", 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 := m.Packet.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Acknowledgement", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Acknowledgement = append(m.Acknowledgement[:0], dAtA[iNdEx:postIndex]...) - if m.Acknowledgement == nil { - m.Acknowledgement = []byte{} - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofAcked", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ProofAcked = append(m.ProofAcked[:0], dAtA[iNdEx:postIndex]...) - if m.ProofAcked == nil { - m.ProofAcked = []byte{} - } - iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofHeight", 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 := m.ProofHeight.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Signer", 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.Signer = 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 *MsgAcknowledgementResponse) 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: MsgAcknowledgementResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgAcknowledgementResponse: 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/ibc/core/05-port/keeper/keeper.go b/x/ibc/core/05-port/keeper/keeper.go deleted file mode 100644 index 8a4b2300a4e0..000000000000 --- a/x/ibc/core/05-port/keeper/keeper.go +++ /dev/null @@ -1,80 +0,0 @@ -package keeper - -import ( - "fmt" - - "github.com/tendermint/tendermint/libs/log" - - sdk "github.com/cosmos/cosmos-sdk/types" - capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" - capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/05-port/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" -) - -// Keeper defines the IBC connection keeper -type Keeper struct { - scopedKeeper capabilitykeeper.ScopedKeeper -} - -// NewKeeper creates a new IBC connection Keeper instance -func NewKeeper(sck capabilitykeeper.ScopedKeeper) Keeper { - return Keeper{ - scopedKeeper: sck, - } -} - -// Logger returns a module-specific logger. -func (k Keeper) Logger(ctx sdk.Context) log.Logger { - return ctx.Logger().With("module", "x/"+host.ModuleName+"/"+types.SubModuleName) -} - -// isBounded checks a given port ID is already bounded. -func (k Keeper) isBound(ctx sdk.Context, portID string) bool { - _, ok := k.scopedKeeper.GetCapability(ctx, host.PortPath(portID)) - return ok -} - -// BindPort binds to a port and returns the associated capability. -// Ports must be bound statically when the chain starts in `app.go`. -// The capability must then be passed to a module which will need to pass -// it as an extra parameter when calling functions on the IBC module. -func (k *Keeper) BindPort(ctx sdk.Context, portID string) *capabilitytypes.Capability { - if err := host.PortIdentifierValidator(portID); err != nil { - panic(err.Error()) - } - - if k.isBound(ctx, portID) { - panic(fmt.Sprintf("port %s is already bound", portID)) - } - - key, err := k.scopedKeeper.NewCapability(ctx, host.PortPath(portID)) - if err != nil { - panic(err.Error()) - } - - k.Logger(ctx).Info("port binded", "port", portID) - return key -} - -// Authenticate authenticates a capability key against a port ID -// by checking if the memory address of the capability was previously -// generated and bound to the port (provided as a parameter) which the capability -// is being authenticated against. -func (k Keeper) Authenticate(ctx sdk.Context, key *capabilitytypes.Capability, portID string) bool { - if err := host.PortIdentifierValidator(portID); err != nil { - panic(err.Error()) - } - - return k.scopedKeeper.AuthenticateCapability(ctx, key, host.PortPath(portID)) -} - -// LookupModuleByPort will return the IBCModule along with the capability associated with a given portID -func (k Keeper) LookupModuleByPort(ctx sdk.Context, portID string) (string, *capabilitytypes.Capability, error) { - modules, cap, err := k.scopedKeeper.LookupModules(ctx, host.PortPath(portID)) - if err != nil { - return "", nil, err - } - - return types.GetModuleOwner(modules), cap, nil -} diff --git a/x/ibc/core/05-port/keeper/keeper_test.go b/x/ibc/core/05-port/keeper/keeper_test.go deleted file mode 100644 index 29c0e1585741..000000000000 --- a/x/ibc/core/05-port/keeper/keeper_test.go +++ /dev/null @@ -1,70 +0,0 @@ -package keeper_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - "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/ibc/core/05-port/keeper" -) - -var ( - validPort = "validportid" - invalidPort = "(invalidPortID)" -) - -type KeeperTestSuite struct { - suite.Suite - - ctx sdk.Context - keeper *keeper.Keeper -} - -func (suite *KeeperTestSuite) SetupTest() { - isCheckTx := false - app := simapp.Setup(isCheckTx) - - suite.ctx = app.BaseApp.NewContext(isCheckTx, tmproto.Header{}) - suite.keeper = &app.IBCKeeper.PortKeeper -} - -func TestKeeperTestSuite(t *testing.T) { - suite.Run(t, new(KeeperTestSuite)) -} - -func (suite *KeeperTestSuite) TestBind() { - // Test that invalid portID causes panic - require.Panics(suite.T(), func() { suite.keeper.BindPort(suite.ctx, invalidPort) }, "Did not panic on invalid portID") - - // Test that valid BindPort returns capability key - capKey := suite.keeper.BindPort(suite.ctx, validPort) - require.NotNil(suite.T(), capKey, "capabilityKey is nil on valid BindPort") - - // Test that rebinding the same portid causes panic - require.Panics(suite.T(), func() { suite.keeper.BindPort(suite.ctx, validPort) }, "did not panic on re-binding the same port") -} - -func (suite *KeeperTestSuite) TestAuthenticate() { - capKey := suite.keeper.BindPort(suite.ctx, validPort) - - // Require that passing in invalid portID causes panic - require.Panics(suite.T(), func() { suite.keeper.Authenticate(suite.ctx, capKey, invalidPort) }, "did not panic on invalid portID") - - // Valid authentication should return true - auth := suite.keeper.Authenticate(suite.ctx, capKey, validPort) - require.True(suite.T(), auth, "valid authentication failed") - - // Test that authenticating against incorrect portid fails - auth = suite.keeper.Authenticate(suite.ctx, capKey, "wrongportid") - require.False(suite.T(), auth, "invalid authentication failed") - - // Test that authenticating port against different valid - // capability key fails - capKey2 := suite.keeper.BindPort(suite.ctx, "otherportid") - auth = suite.keeper.Authenticate(suite.ctx, capKey2, validPort) - require.False(suite.T(), auth, "invalid authentication for different capKey failed") -} diff --git a/x/ibc/core/05-port/types/errors.go b/x/ibc/core/05-port/types/errors.go deleted file mode 100644 index 23a2776f59d6..000000000000 --- a/x/ibc/core/05-port/types/errors.go +++ /dev/null @@ -1,13 +0,0 @@ -package types - -import ( - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" -) - -// IBC port sentinel errors -var ( - ErrPortExists = sdkerrors.Register(SubModuleName, 2, "port is already binded") - ErrPortNotFound = sdkerrors.Register(SubModuleName, 3, "port not found") - ErrInvalidPort = sdkerrors.Register(SubModuleName, 4, "invalid port") - ErrInvalidRoute = sdkerrors.Register(SubModuleName, 5, "route not found") -) diff --git a/x/ibc/core/05-port/types/keys.go b/x/ibc/core/05-port/types/keys.go deleted file mode 100644 index 6e79bb535066..000000000000 --- a/x/ibc/core/05-port/types/keys.go +++ /dev/null @@ -1,15 +0,0 @@ -package types - -const ( - // SubModuleName defines the IBC port name - SubModuleName = "port" - - // StoreKey is the store key string for IBC ports - StoreKey = SubModuleName - - // RouterKey is the message route for IBC ports - RouterKey = SubModuleName - - // QuerierRoute is the querier route for IBC ports - QuerierRoute = SubModuleName -) diff --git a/x/ibc/core/05-port/types/module.go b/x/ibc/core/05-port/types/module.go deleted file mode 100644 index 4c686732018e..000000000000 --- a/x/ibc/core/05-port/types/module.go +++ /dev/null @@ -1,78 +0,0 @@ -package types - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" - - capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" -) - -// IBCModule defines an interface that implements all the callbacks -// that modules must define as specified in ICS-26 -type IBCModule interface { - OnChanOpenInit( - ctx sdk.Context, - order channeltypes.Order, - connectionHops []string, - portID string, - channelID string, - channelCap *capabilitytypes.Capability, - counterparty channeltypes.Counterparty, - version string, - ) error - - OnChanOpenTry( - ctx sdk.Context, - order channeltypes.Order, - connectionHops []string, - portID, - channelID string, - channelCap *capabilitytypes.Capability, - counterparty channeltypes.Counterparty, - version, - counterpartyVersion string, - ) error - - OnChanOpenAck( - ctx sdk.Context, - portID, - channelID string, - counterpartyVersion string, - ) error - - OnChanOpenConfirm( - ctx sdk.Context, - portID, - channelID string, - ) error - - OnChanCloseInit( - ctx sdk.Context, - portID, - channelID string, - ) error - - OnChanCloseConfirm( - ctx sdk.Context, - portID, - channelID string, - ) error - - // OnRecvPacket must return the acknowledgement bytes - // In the case of an asynchronous acknowledgement, nil should be returned. - OnRecvPacket( - ctx sdk.Context, - packet channeltypes.Packet, - ) (*sdk.Result, []byte, error) - - OnAcknowledgementPacket( - ctx sdk.Context, - packet channeltypes.Packet, - acknowledgement []byte, - ) (*sdk.Result, error) - - OnTimeoutPacket( - ctx sdk.Context, - packet channeltypes.Packet, - ) (*sdk.Result, error) -} diff --git a/x/ibc/core/05-port/types/router.go b/x/ibc/core/05-port/types/router.go deleted file mode 100644 index 6bfba9076abd..000000000000 --- a/x/ibc/core/05-port/types/router.go +++ /dev/null @@ -1,65 +0,0 @@ -package types - -import ( - "fmt" - - sdk "github.com/cosmos/cosmos-sdk/types" -) - -// The router is a map from module name to the IBCModule -// which contains all the module-defined callbacks required by ICS-26 -type Router struct { - routes map[string]IBCModule - sealed bool -} - -func NewRouter() *Router { - return &Router{ - routes: make(map[string]IBCModule), - } -} - -// Seal prevents the Router from any subsequent route handlers to be registered. -// Seal will panic if called more than once. -func (rtr *Router) Seal() { - if rtr.sealed { - panic("router already sealed") - } - rtr.sealed = true -} - -// Sealed returns a boolean signifying if the Router is sealed or not. -func (rtr Router) Sealed() bool { - return rtr.sealed -} - -// AddRoute adds IBCModule for a given module name. It returns the Router -// so AddRoute calls can be linked. It will panic if the Router is sealed. -func (rtr *Router) AddRoute(module string, cbs IBCModule) *Router { - if rtr.sealed { - panic(fmt.Sprintf("router sealed; cannot register %s route callbacks", module)) - } - if !sdk.IsAlphaNumeric(module) { - panic("route expressions can only contain alphanumeric characters") - } - if rtr.HasRoute(module) { - panic(fmt.Sprintf("route %s has already been registered", module)) - } - - rtr.routes[module] = cbs - return rtr -} - -// HasRoute returns true if the Router has a module registered or false otherwise. -func (rtr *Router) HasRoute(module string) bool { - _, ok := rtr.routes[module] - return ok -} - -// GetRoute returns a IBCModule for a given module. -func (rtr *Router) GetRoute(module string) (IBCModule, bool) { - if !rtr.HasRoute(module) { - return nil, false - } - return rtr.routes[module], true -} diff --git a/x/ibc/core/05-port/types/utils.go b/x/ibc/core/05-port/types/utils.go deleted file mode 100644 index a12f2ef7f523..000000000000 --- a/x/ibc/core/05-port/types/utils.go +++ /dev/null @@ -1,17 +0,0 @@ -package types - -import "fmt" - -// GetModuleOwner enforces that only IBC and the module bound to port can own the capability -// while future implementations may allow multiple modules to bind to a port, currently we -// only allow one module to be bound to a port at any given time -func GetModuleOwner(modules []string) string { - if len(modules) != 2 { - panic(fmt.Sprintf("capability should only be owned by port or channel owner and ibc module, multiple owners currently not supported, owners: %v", modules)) - } - - if modules[0] == "ibc" { - return modules[1] - } - return modules[0] -} diff --git a/x/ibc/core/23-commitment/types/bench_test.go b/x/ibc/core/23-commitment/types/bench_test.go deleted file mode 100644 index 83794fc6f6e7..000000000000 --- a/x/ibc/core/23-commitment/types/bench_test.go +++ /dev/null @@ -1,15 +0,0 @@ -package types - -import ( - "testing" -) - -func BenchmarkMerkleProofEmpty(b *testing.B) { - b.ReportAllocs() - var mk MerkleProof - for i := 0; i < b.N; i++ { - if !mk.Empty() { - b.Fatal("supposed to be empty") - } - } -} diff --git a/x/ibc/core/23-commitment/types/codec.go b/x/ibc/core/23-commitment/types/codec.go deleted file mode 100644 index 1195c7c26db9..000000000000 --- a/x/ibc/core/23-commitment/types/codec.go +++ /dev/null @@ -1,43 +0,0 @@ -package types - -import ( - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -// RegisterInterfaces registers the commitment interfaces to protobuf Any. -func RegisterInterfaces(registry codectypes.InterfaceRegistry) { - registry.RegisterInterface( - "ibc.core.commitment.v1.Root", - (*exported.Root)(nil), - ) - registry.RegisterInterface( - "ibc.core.commitment.v1.Prefix", - (*exported.Prefix)(nil), - ) - registry.RegisterInterface( - "ibc.core.commitment.v1.Path", - (*exported.Path)(nil), - ) - registry.RegisterInterface( - "ibc.core.commitment.v1.Proof", - (*exported.Proof)(nil), - ) - - registry.RegisterImplementations( - (*exported.Root)(nil), - &MerkleRoot{}, - ) - registry.RegisterImplementations( - (*exported.Prefix)(nil), - &MerklePrefix{}, - ) - registry.RegisterImplementations( - (*exported.Path)(nil), - &MerklePath{}, - ) - registry.RegisterImplementations( - (*exported.Proof)(nil), - &MerkleProof{}, - ) -} diff --git a/x/ibc/core/23-commitment/types/commitment.pb.go b/x/ibc/core/23-commitment/types/commitment.pb.go deleted file mode 100644 index 06bc66522611..000000000000 --- a/x/ibc/core/23-commitment/types/commitment.pb.go +++ /dev/null @@ -1,863 +0,0 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: ibc/core/commitment/v1/commitment.proto - -package types - -import ( - fmt "fmt" - _go "github.com/confio/ics23/go" - _ "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 - -// MerkleRoot defines a merkle root hash. -// In the Cosmos SDK, the AppHash of a block header becomes the root. -type MerkleRoot struct { - Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` -} - -func (m *MerkleRoot) Reset() { *m = MerkleRoot{} } -func (m *MerkleRoot) String() string { return proto.CompactTextString(m) } -func (*MerkleRoot) ProtoMessage() {} -func (*MerkleRoot) Descriptor() ([]byte, []int) { - return fileDescriptor_7921d88972a41469, []int{0} -} -func (m *MerkleRoot) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MerkleRoot) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MerkleRoot.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 *MerkleRoot) XXX_Merge(src proto.Message) { - xxx_messageInfo_MerkleRoot.Merge(m, src) -} -func (m *MerkleRoot) XXX_Size() int { - return m.Size() -} -func (m *MerkleRoot) XXX_DiscardUnknown() { - xxx_messageInfo_MerkleRoot.DiscardUnknown(m) -} - -var xxx_messageInfo_MerkleRoot proto.InternalMessageInfo - -// MerklePrefix is merkle path prefixed to the key. -// The constructed key from the Path and the key will be append(Path.KeyPath, -// append(Path.KeyPrefix, key...)) -type MerklePrefix struct { - KeyPrefix []byte `protobuf:"bytes,1,opt,name=key_prefix,json=keyPrefix,proto3" json:"key_prefix,omitempty" yaml:"key_prefix"` -} - -func (m *MerklePrefix) Reset() { *m = MerklePrefix{} } -func (m *MerklePrefix) String() string { return proto.CompactTextString(m) } -func (*MerklePrefix) ProtoMessage() {} -func (*MerklePrefix) Descriptor() ([]byte, []int) { - return fileDescriptor_7921d88972a41469, []int{1} -} -func (m *MerklePrefix) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MerklePrefix) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MerklePrefix.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 *MerklePrefix) XXX_Merge(src proto.Message) { - xxx_messageInfo_MerklePrefix.Merge(m, src) -} -func (m *MerklePrefix) XXX_Size() int { - return m.Size() -} -func (m *MerklePrefix) XXX_DiscardUnknown() { - xxx_messageInfo_MerklePrefix.DiscardUnknown(m) -} - -var xxx_messageInfo_MerklePrefix proto.InternalMessageInfo - -func (m *MerklePrefix) GetKeyPrefix() []byte { - if m != nil { - return m.KeyPrefix - } - return nil -} - -// MerklePath is the path used to verify commitment proofs, which can be an -// arbitrary structured object (defined by a commitment type). -// MerklePath is represented from root-to-leaf -type MerklePath struct { - KeyPath []string `protobuf:"bytes,1,rep,name=key_path,json=keyPath,proto3" json:"key_path,omitempty" yaml:"key_path"` -} - -func (m *MerklePath) Reset() { *m = MerklePath{} } -func (*MerklePath) ProtoMessage() {} -func (*MerklePath) Descriptor() ([]byte, []int) { - return fileDescriptor_7921d88972a41469, []int{2} -} -func (m *MerklePath) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MerklePath) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MerklePath.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 *MerklePath) XXX_Merge(src proto.Message) { - xxx_messageInfo_MerklePath.Merge(m, src) -} -func (m *MerklePath) XXX_Size() int { - return m.Size() -} -func (m *MerklePath) XXX_DiscardUnknown() { - xxx_messageInfo_MerklePath.DiscardUnknown(m) -} - -var xxx_messageInfo_MerklePath proto.InternalMessageInfo - -func (m *MerklePath) GetKeyPath() []string { - if m != nil { - return m.KeyPath - } - return nil -} - -// MerkleProof is a wrapper type over a chain of CommitmentProofs. -// It demonstrates membership or non-membership for an element or set of -// elements, verifiable in conjunction with a known commitment root. Proofs -// should be succinct. -// MerkleProofs are ordered from leaf-to-root -type MerkleProof struct { - Proofs []*_go.CommitmentProof `protobuf:"bytes,1,rep,name=proofs,proto3" json:"proofs,omitempty"` -} - -func (m *MerkleProof) Reset() { *m = MerkleProof{} } -func (m *MerkleProof) String() string { return proto.CompactTextString(m) } -func (*MerkleProof) ProtoMessage() {} -func (*MerkleProof) Descriptor() ([]byte, []int) { - return fileDescriptor_7921d88972a41469, []int{3} -} -func (m *MerkleProof) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MerkleProof) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MerkleProof.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 *MerkleProof) XXX_Merge(src proto.Message) { - xxx_messageInfo_MerkleProof.Merge(m, src) -} -func (m *MerkleProof) XXX_Size() int { - return m.Size() -} -func (m *MerkleProof) XXX_DiscardUnknown() { - xxx_messageInfo_MerkleProof.DiscardUnknown(m) -} - -var xxx_messageInfo_MerkleProof proto.InternalMessageInfo - -func (m *MerkleProof) GetProofs() []*_go.CommitmentProof { - if m != nil { - return m.Proofs - } - return nil -} - -func init() { - proto.RegisterType((*MerkleRoot)(nil), "ibc.core.commitment.v1.MerkleRoot") - proto.RegisterType((*MerklePrefix)(nil), "ibc.core.commitment.v1.MerklePrefix") - proto.RegisterType((*MerklePath)(nil), "ibc.core.commitment.v1.MerklePath") - proto.RegisterType((*MerkleProof)(nil), "ibc.core.commitment.v1.MerkleProof") -} - -func init() { - proto.RegisterFile("ibc/core/commitment/v1/commitment.proto", fileDescriptor_7921d88972a41469) -} - -var fileDescriptor_7921d88972a41469 = []byte{ - // 334 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0x91, 0xcf, 0x4e, 0xfa, 0x40, - 0x10, 0xc7, 0xdb, 0xfc, 0x08, 0x3f, 0x59, 0x48, 0x8c, 0x45, 0x89, 0xe1, 0x50, 0x4c, 0x0f, 0xca, - 0x85, 0xdd, 0x00, 0x9e, 0x30, 0x5e, 0xaa, 0x57, 0x13, 0xd2, 0xc4, 0x8b, 0x17, 0xd3, 0xae, 0x5b, - 0xba, 0x29, 0x65, 0x9a, 0xee, 0x4a, 0xe8, 0x1b, 0x78, 0xf4, 0xe8, 0xd1, 0xc7, 0xf1, 0xc8, 0xd1, - 0x13, 0x31, 0xf0, 0x06, 0x3c, 0x81, 0xe9, 0x2e, 0x60, 0x4f, 0x3b, 0xb3, 0xf3, 0x99, 0x7f, 0xdf, - 0x41, 0x57, 0x3c, 0xa0, 0x84, 0x42, 0xc6, 0x08, 0x85, 0x24, 0xe1, 0x32, 0x61, 0x33, 0x49, 0xe6, - 0xfd, 0x92, 0x87, 0xd3, 0x0c, 0x24, 0x58, 0x2d, 0x1e, 0x50, 0x5c, 0x80, 0xb8, 0x14, 0x9a, 0xf7, - 0xdb, 0xa7, 0x13, 0x98, 0x80, 0x42, 0x48, 0x61, 0x69, 0xba, 0xdd, 0xa4, 0x30, 0x0b, 0x39, 0x90, - 0x34, 0x03, 0x08, 0x85, 0xfe, 0x74, 0x2e, 0x11, 0x7a, 0x60, 0x59, 0x3c, 0x65, 0x1e, 0x80, 0xb4, - 0x2c, 0x54, 0x89, 0x7c, 0x11, 0x9d, 0x9b, 0x17, 0x66, 0xb7, 0xe1, 0x29, 0x7b, 0x54, 0x79, 0xfb, - 0xec, 0x18, 0xce, 0x3d, 0x6a, 0x68, 0x6e, 0x9c, 0xb1, 0x90, 0x2f, 0xac, 0x6b, 0x84, 0x62, 0x96, - 0x3f, 0xa7, 0xca, 0xd3, 0xbc, 0x7b, 0xb6, 0x5d, 0x75, 0x4e, 0x72, 0x3f, 0x99, 0x8e, 0x9c, 0xbf, - 0x98, 0xe3, 0xd5, 0x62, 0x96, 0xeb, 0x2c, 0xc7, 0xdd, 0x77, 0x1b, 0xfb, 0x32, 0xb2, 0x30, 0x3a, - 0x52, 0x9c, 0x2f, 0x8b, 0x8e, 0xff, 0xba, 0x35, 0xb7, 0xb9, 0x5d, 0x75, 0x8e, 0x4b, 0x15, 0x7c, - 0x19, 0x39, 0xde, 0xff, 0x22, 0xdf, 0x97, 0xd1, 0xa8, 0xf2, 0x51, 0x4c, 0x72, 0x8b, 0xea, 0xfb, - 0x49, 0x00, 0x42, 0x0b, 0xa3, 0xaa, 0x5e, 0x48, 0x95, 0xa8, 0x0f, 0x5a, 0x98, 0x53, 0x31, 0x18, - 0xe2, 0xbb, 0x83, 0x22, 0x8a, 0xf3, 0x76, 0x94, 0xfb, 0xf8, 0xb5, 0xb6, 0xcd, 0xe5, 0xda, 0x36, - 0x7f, 0xd6, 0xb6, 0xf9, 0xbe, 0xb1, 0x8d, 0xe5, 0xc6, 0x36, 0xbe, 0x37, 0xb6, 0xf1, 0x74, 0x33, - 0xe1, 0x32, 0x7a, 0x0d, 0x0a, 0x2d, 0x09, 0x05, 0x91, 0x80, 0xd8, 0x3d, 0x3d, 0xf1, 0x12, 0x93, - 0x05, 0x39, 0x5c, 0x65, 0x30, 0xec, 0x95, 0x0e, 0x23, 0xf3, 0x94, 0x89, 0xa0, 0xaa, 0xe4, 0x1c, - 0xfe, 0x06, 0x00, 0x00, 0xff, 0xff, 0x1b, 0xe7, 0x68, 0xd0, 0xbc, 0x01, 0x00, 0x00, -} - -func (m *MerkleRoot) 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 *MerkleRoot) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MerkleRoot) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Hash) > 0 { - i -= len(m.Hash) - copy(dAtA[i:], m.Hash) - i = encodeVarintCommitment(dAtA, i, uint64(len(m.Hash))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *MerklePrefix) 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 *MerklePrefix) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MerklePrefix) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.KeyPrefix) > 0 { - i -= len(m.KeyPrefix) - copy(dAtA[i:], m.KeyPrefix) - i = encodeVarintCommitment(dAtA, i, uint64(len(m.KeyPrefix))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *MerklePath) 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 *MerklePath) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MerklePath) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.KeyPath) > 0 { - for iNdEx := len(m.KeyPath) - 1; iNdEx >= 0; iNdEx-- { - i -= len(m.KeyPath[iNdEx]) - copy(dAtA[i:], m.KeyPath[iNdEx]) - i = encodeVarintCommitment(dAtA, i, uint64(len(m.KeyPath[iNdEx]))) - i-- - dAtA[i] = 0xa - } - } - return len(dAtA) - i, nil -} - -func (m *MerkleProof) 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 *MerkleProof) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MerkleProof) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Proofs) > 0 { - for iNdEx := len(m.Proofs) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.Proofs[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintCommitment(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0xa - } - } - return len(dAtA) - i, nil -} - -func encodeVarintCommitment(dAtA []byte, offset int, v uint64) int { - offset -= sovCommitment(v) - base := offset - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ - } - dAtA[offset] = uint8(v) - return base -} -func (m *MerkleRoot) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Hash) - if l > 0 { - n += 1 + l + sovCommitment(uint64(l)) - } - return n -} - -func (m *MerklePrefix) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.KeyPrefix) - if l > 0 { - n += 1 + l + sovCommitment(uint64(l)) - } - return n -} - -func (m *MerklePath) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if len(m.KeyPath) > 0 { - for _, s := range m.KeyPath { - l = len(s) - n += 1 + l + sovCommitment(uint64(l)) - } - } - return n -} - -func (m *MerkleProof) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if len(m.Proofs) > 0 { - for _, e := range m.Proofs { - l = e.Size() - n += 1 + l + sovCommitment(uint64(l)) - } - } - return n -} - -func sovCommitment(x uint64) (n int) { - return (math_bits.Len64(x|1) + 6) / 7 -} -func sozCommitment(x uint64) (n int) { - return sovCommitment(uint64((x << 1) ^ uint64((int64(x) >> 63)))) -} -func (m *MerkleRoot) 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 ErrIntOverflowCommitment - } - 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: MerkleRoot: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MerkleRoot: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Hash", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCommitment - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthCommitment - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthCommitment - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Hash = append(m.Hash[:0], dAtA[iNdEx:postIndex]...) - if m.Hash == nil { - m.Hash = []byte{} - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipCommitment(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthCommitment - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *MerklePrefix) 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 ErrIntOverflowCommitment - } - 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: MerklePrefix: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MerklePrefix: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field KeyPrefix", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCommitment - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthCommitment - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthCommitment - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.KeyPrefix = append(m.KeyPrefix[:0], dAtA[iNdEx:postIndex]...) - if m.KeyPrefix == nil { - m.KeyPrefix = []byte{} - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipCommitment(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthCommitment - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *MerklePath) 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 ErrIntOverflowCommitment - } - 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: MerklePath: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MerklePath: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field KeyPath", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCommitment - } - 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 ErrInvalidLengthCommitment - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthCommitment - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.KeyPath = append(m.KeyPath, string(dAtA[iNdEx:postIndex])) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipCommitment(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthCommitment - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *MerkleProof) 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 ErrIntOverflowCommitment - } - 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: MerkleProof: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MerkleProof: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Proofs", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCommitment - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthCommitment - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthCommitment - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Proofs = append(m.Proofs, &_go.CommitmentProof{}) - if err := m.Proofs[len(m.Proofs)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipCommitment(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthCommitment - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func skipCommitment(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, ErrIntOverflowCommitment - } - 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, ErrIntOverflowCommitment - } - 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, ErrIntOverflowCommitment - } - 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, ErrInvalidLengthCommitment - } - iNdEx += length - case 3: - depth++ - case 4: - if depth == 0 { - return 0, ErrUnexpectedEndOfGroupCommitment - } - depth-- - case 5: - iNdEx += 4 - default: - return 0, fmt.Errorf("proto: illegal wireType %d", wireType) - } - if iNdEx < 0 { - return 0, ErrInvalidLengthCommitment - } - if depth == 0 { - return iNdEx, nil - } - } - return 0, io.ErrUnexpectedEOF -} - -var ( - ErrInvalidLengthCommitment = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowCommitment = fmt.Errorf("proto: integer overflow") - ErrUnexpectedEndOfGroupCommitment = fmt.Errorf("proto: unexpected end of group") -) diff --git a/x/ibc/core/23-commitment/types/commitment_test.go b/x/ibc/core/23-commitment/types/commitment_test.go deleted file mode 100644 index 932599e539cd..000000000000 --- a/x/ibc/core/23-commitment/types/commitment_test.go +++ /dev/null @@ -1,37 +0,0 @@ -package types_test - -import ( - "testing" - - "github.com/stretchr/testify/suite" - - "github.com/cosmos/cosmos-sdk/store/iavl" - "github.com/cosmos/cosmos-sdk/store/rootmulti" - storetypes "github.com/cosmos/cosmos-sdk/store/types" - - dbm "github.com/tendermint/tm-db" -) - -type MerkleTestSuite struct { - suite.Suite - - store *rootmulti.Store - storeKey *storetypes.KVStoreKey - iavlStore *iavl.Store -} - -func (suite *MerkleTestSuite) SetupTest() { - db := dbm.NewMemDB() - suite.store = rootmulti.NewStore(db) - - suite.storeKey = storetypes.NewKVStoreKey("iavlStoreKey") - - suite.store.MountStoreWithDB(suite.storeKey, storetypes.StoreTypeIAVL, nil) - suite.store.LoadVersion(0) - - suite.iavlStore = suite.store.GetCommitStore(suite.storeKey).(*iavl.Store) -} - -func TestMerkleTestSuite(t *testing.T) { - suite.Run(t, new(MerkleTestSuite)) -} diff --git a/x/ibc/core/23-commitment/types/errors.go b/x/ibc/core/23-commitment/types/errors.go deleted file mode 100644 index 7191baef1cc9..000000000000 --- a/x/ibc/core/23-commitment/types/errors.go +++ /dev/null @@ -1,15 +0,0 @@ -package types - -import ( - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" -) - -// SubModuleName is the error codespace -const SubModuleName string = "commitment" - -// IBC connection sentinel errors -var ( - ErrInvalidProof = sdkerrors.Register(SubModuleName, 2, "invalid proof") - ErrInvalidPrefix = sdkerrors.Register(SubModuleName, 3, "invalid prefix") - ErrInvalidMerkleProof = sdkerrors.Register(SubModuleName, 4, "invalid merkle proof") -) diff --git a/x/ibc/core/23-commitment/types/merkle.go b/x/ibc/core/23-commitment/types/merkle.go deleted file mode 100644 index e90fccc34b27..000000000000 --- a/x/ibc/core/23-commitment/types/merkle.go +++ /dev/null @@ -1,312 +0,0 @@ -package types - -import ( - "bytes" - "fmt" - "net/url" - - ics23 "github.com/confio/ics23/go" - "github.com/gogo/protobuf/proto" - tmcrypto "github.com/tendermint/tendermint/proto/tendermint/crypto" - - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -// var representing the proofspecs for a SDK chain -var sdkSpecs = []*ics23.ProofSpec{ics23.IavlSpec, ics23.TendermintSpec} - -// ICS 023 Merkle Types Implementation -// -// This file defines Merkle commitment types that implements ICS 023. - -// Merkle proof implementation of the Proof interface -// Applied on SDK-based IBC implementation -var _ exported.Root = (*MerkleRoot)(nil) - -// GetSDKSpecs is a getter function for the proofspecs of an sdk chain -func GetSDKSpecs() []*ics23.ProofSpec { - return sdkSpecs -} - -// NewMerkleRoot constructs a new MerkleRoot -func NewMerkleRoot(hash []byte) MerkleRoot { - return MerkleRoot{ - Hash: hash, - } -} - -// GetHash implements RootI interface -func (mr MerkleRoot) GetHash() []byte { - return mr.Hash -} - -// Empty returns true if the root is empty -func (mr MerkleRoot) Empty() bool { - return len(mr.GetHash()) == 0 -} - -var _ exported.Prefix = (*MerklePrefix)(nil) - -// NewMerklePrefix constructs new MerklePrefix instance -func NewMerklePrefix(keyPrefix []byte) MerklePrefix { - return MerklePrefix{ - KeyPrefix: keyPrefix, - } -} - -// Bytes returns the key prefix bytes -func (mp MerklePrefix) Bytes() []byte { - return mp.KeyPrefix -} - -// Empty returns true if the prefix is empty -func (mp MerklePrefix) Empty() bool { - return len(mp.Bytes()) == 0 -} - -var _ exported.Path = (*MerklePath)(nil) - -// NewMerklePath creates a new MerklePath instance -// The keys must be passed in from root-to-leaf order -func NewMerklePath(keyPath ...string) MerklePath { - return MerklePath{ - KeyPath: keyPath, - } -} - -// String implements fmt.Stringer. -// This represents the path in the same way the tendermint KeyPath will -// represent a key path. The backslashes partition the key path into -// the respective stores they belong to. -func (mp MerklePath) String() string { - pathStr := "" - for _, k := range mp.KeyPath { - pathStr += "/" + url.PathEscape(k) - } - return pathStr -} - -// Pretty returns the unescaped path of the URL string. -// This function will unescape any backslash within a particular store key. -// This makes the keypath more human-readable while removing information -// about the exact partitions in the key path. -func (mp MerklePath) Pretty() string { - path, err := url.PathUnescape(mp.String()) - if err != nil { - panic(err) - } - return path -} - -// GetKey will return a byte representation of the key -// after URL escaping the key element -func (mp MerklePath) GetKey(i uint64) ([]byte, error) { - if i >= uint64(len(mp.KeyPath)) { - return nil, fmt.Errorf("index out of range. %d (index) >= %d (len)", i, len(mp.KeyPath)) - } - key, err := url.PathUnescape(mp.KeyPath[i]) - if err != nil { - return nil, err - } - return []byte(key), nil -} - -// Empty returns true if the path is empty -func (mp MerklePath) Empty() bool { - return len(mp.KeyPath) == 0 -} - -// ApplyPrefix constructs a new commitment path from the arguments. It prepends the prefix key -// with the given path. -func ApplyPrefix(prefix exported.Prefix, path MerklePath) (MerklePath, error) { - if prefix == nil || prefix.Empty() { - return MerklePath{}, sdkerrors.Wrap(ErrInvalidPrefix, "prefix can't be empty") - } - return NewMerklePath(append([]string{string(prefix.Bytes())}, path.KeyPath...)...), nil -} - -var _ exported.Proof = (*MerkleProof)(nil) - -// VerifyMembership verifies the membership pf a merkle proof against the given root, path, and value. -func (proof MerkleProof) VerifyMembership(specs []*ics23.ProofSpec, root exported.Root, path exported.Path, value []byte) error { - if err := proof.validateVerificationArgs(specs, root); err != nil { - return err - } - - // VerifyMembership specific argument validation - mpath, ok := path.(MerklePath) - if !ok { - return sdkerrors.Wrapf(ErrInvalidProof, "path %v is not of type MerklePath", path) - } - if len(mpath.KeyPath) != len(specs) { - return sdkerrors.Wrapf(ErrInvalidProof, "path length %d not same as proof %d", - len(mpath.KeyPath), len(specs)) - } - if len(value) == 0 { - return sdkerrors.Wrap(ErrInvalidProof, "empty value in membership proof") - } - - // Since every proof in chain is a membership proof we can use verifyChainedMembershipProof from index 0 - // to validate entire proof - if err := verifyChainedMembershipProof(root.GetHash(), specs, proof.Proofs, mpath, value, 0); err != nil { - return err - } - return nil -} - -// VerifyNonMembership verifies the absence of a merkle proof against the given root and path. -// VerifyNonMembership verifies a chained proof where the absence of a given path is proven -// at the lowest subtree and then each subtree's inclusion is proved up to the final root. -func (proof MerkleProof) VerifyNonMembership(specs []*ics23.ProofSpec, root exported.Root, path exported.Path) error { - if err := proof.validateVerificationArgs(specs, root); err != nil { - return err - } - - // VerifyNonMembership specific argument validation - mpath, ok := path.(MerklePath) - if !ok { - return sdkerrors.Wrapf(ErrInvalidProof, "path %v is not of type MerkleProof", path) - } - if len(mpath.KeyPath) != len(specs) { - return sdkerrors.Wrapf(ErrInvalidProof, "path length %d not same as proof %d", - len(mpath.KeyPath), len(specs)) - } - - switch proof.Proofs[0].Proof.(type) { - case *ics23.CommitmentProof_Nonexist: - // VerifyNonMembership will verify the absence of key in lowest subtree, and then chain inclusion proofs - // of all subroots up to final root - subroot, err := proof.Proofs[0].Calculate() - if err != nil { - return sdkerrors.Wrapf(ErrInvalidProof, "could not calculate root for proof index 0, merkle tree is likely empty. %v", err) - } - key, err := mpath.GetKey(uint64(len(mpath.KeyPath) - 1)) - if err != nil { - return sdkerrors.Wrapf(ErrInvalidProof, "could not retrieve key bytes for key: %s", mpath.KeyPath[len(mpath.KeyPath)-1]) - } - if ok := ics23.VerifyNonMembership(specs[0], subroot, proof.Proofs[0], key); !ok { - return sdkerrors.Wrapf(ErrInvalidProof, "could not verify absence of key %s. Please ensure that the path is correct.", string(key)) - } - - // Verify chained membership proof starting from index 1 with value = subroot - if err := verifyChainedMembershipProof(root.GetHash(), specs, proof.Proofs, mpath, subroot, 1); err != nil { - return err - } - case *ics23.CommitmentProof_Exist: - return sdkerrors.Wrapf(ErrInvalidProof, - "got ExistenceProof in VerifyNonMembership. If this is unexpected, please ensure that proof was queried with the correct key.") - default: - return sdkerrors.Wrapf(ErrInvalidProof, - "expected proof type: %T, got: %T", &ics23.CommitmentProof_Exist{}, proof.Proofs[0].Proof) - } - return nil -} - -// BatchVerifyMembership verifies a group of key value pairs against the given root -// NOTE: Currently left unimplemented as it is unused -func (proof MerkleProof) BatchVerifyMembership(specs []*ics23.ProofSpec, root exported.Root, path exported.Path, items map[string][]byte) error { - return sdkerrors.Wrap(ErrInvalidProof, "batch proofs are currently unsupported") -} - -// BatchVerifyNonMembership verifies absence of a group of keys against the given root -// NOTE: Currently left unimplemented as it is unused -func (proof MerkleProof) BatchVerifyNonMembership(specs []*ics23.ProofSpec, root exported.Root, path exported.Path, items [][]byte) error { - return sdkerrors.Wrap(ErrInvalidProof, "batch proofs are currently unsupported") -} - -// verifyChainedMembershipProof takes a list of proofs and specs and verifies each proof sequentially ensuring that the value is committed to -// by first proof and each subsequent subroot is committed to by the next subroot and checking that the final calculated root is equal to the given roothash. -// The proofs and specs are passed in from lowest subtree to the highest subtree, but the keys are passed in from highest subtree to lowest. -// The index specifies what index to start chaining the membership proofs, this is useful since the lowest proof may not be a membership proof, thus we -// will want to start the membership proof chaining from index 1 with value being the lowest subroot -func verifyChainedMembershipProof(root []byte, specs []*ics23.ProofSpec, proofs []*ics23.CommitmentProof, keys MerklePath, value []byte, index int) error { - var ( - subroot []byte - err error - ) - // Initialize subroot to value since the proofs list may be empty. - // This may happen if this call is verifying intermediate proofs after the lowest proof has been executed. - // In this case, there may be no intermediate proofs to verify and we just check that lowest proof root equals final root - subroot = value - for i := index; i < len(proofs); i++ { - switch proofs[i].Proof.(type) { - case *ics23.CommitmentProof_Exist: - subroot, err = proofs[i].Calculate() - if err != nil { - return sdkerrors.Wrapf(ErrInvalidProof, "could not calculate proof root at index %d, merkle tree may be empty. %v", i, err) - } - // Since keys are passed in from highest to lowest, we must grab their indices in reverse order - // from the proofs and specs which are lowest to highest - key, err := keys.GetKey(uint64(len(keys.KeyPath) - 1 - i)) - if err != nil { - return sdkerrors.Wrapf(ErrInvalidProof, "could not retrieve key bytes for key %s: %v", keys.KeyPath[len(keys.KeyPath)-1-i], err) - } - - // verify membership of the proof at this index with appropriate key and value - if ok := ics23.VerifyMembership(specs[i], subroot, proofs[i], key, value); !ok { - return sdkerrors.Wrapf(ErrInvalidProof, - "chained membership proof failed to verify membership of value: %X in subroot %X at index %d. Please ensure the path and value are both correct.", - value, subroot, i) - } - // Set value to subroot so that we verify next proof in chain commits to this subroot - value = subroot - case *ics23.CommitmentProof_Nonexist: - return sdkerrors.Wrapf(ErrInvalidProof, - "chained membership proof contains nonexistence proof at index %d. If this is unexpected, please ensure that proof was queried from the height that contained the value in store and was queried with the correct key.", - i) - default: - return sdkerrors.Wrapf(ErrInvalidProof, - "expected proof type: %T, got: %T", &ics23.CommitmentProof_Exist{}, proofs[i].Proof) - } - } - // Check that chained proof root equals passed-in root - if !bytes.Equal(root, subroot) { - return sdkerrors.Wrapf(ErrInvalidProof, - "proof did not commit to expected root: %X, got: %X. Please ensure proof was submitted with correct proofHeight and to the correct chain.", - root, subroot) - } - return nil -} - -// blankMerkleProof and blankProofOps will be used to compare against their zero values, -// and are declared as globals to avoid having to unnecessarily re-allocate on every comparison. -var blankMerkleProof = &MerkleProof{} -var blankProofOps = &tmcrypto.ProofOps{} - -// Empty returns true if the root is empty -func (proof *MerkleProof) Empty() bool { - return proof == nil || proto.Equal(proof, blankMerkleProof) || proto.Equal(proof, blankProofOps) -} - -// ValidateBasic checks if the proof is empty. -func (proof MerkleProof) ValidateBasic() error { - if proof.Empty() { - return ErrInvalidProof - } - return nil -} - -// validateVerificationArgs verifies the proof arguments are valid -func (proof MerkleProof) validateVerificationArgs(specs []*ics23.ProofSpec, root exported.Root) error { - if proof.Empty() { - return sdkerrors.Wrap(ErrInvalidMerkleProof, "proof cannot be empty") - } - - if root == nil || root.Empty() { - return sdkerrors.Wrap(ErrInvalidMerkleProof, "root cannot be empty") - } - - if len(specs) != len(proof.Proofs) { - return sdkerrors.Wrapf(ErrInvalidMerkleProof, - "length of specs: %d not equal to length of proof: %d", - len(specs), len(proof.Proofs)) - } - - for i, spec := range specs { - if spec == nil { - return sdkerrors.Wrapf(ErrInvalidProof, "spec at position %d is nil", i) - } - } - return nil -} diff --git a/x/ibc/core/23-commitment/types/merkle_test.go b/x/ibc/core/23-commitment/types/merkle_test.go deleted file mode 100644 index 3c53847fadd4..000000000000 --- a/x/ibc/core/23-commitment/types/merkle_test.go +++ /dev/null @@ -1,172 +0,0 @@ -package types_test - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/require" - abci "github.com/tendermint/tendermint/abci/types" - - "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types" -) - -func (suite *MerkleTestSuite) TestVerifyMembership() { - suite.iavlStore.Set([]byte("MYKEY"), []byte("MYVALUE")) - cid := suite.store.Commit() - - res := suite.store.Query(abci.RequestQuery{ - Path: fmt.Sprintf("/%s/key", suite.storeKey.Name()), // required path to get key/value+proof - Data: []byte("MYKEY"), - Prove: true, - }) - require.NotNil(suite.T(), res.ProofOps) - - proof, err := types.ConvertProofs(res.ProofOps) - require.NoError(suite.T(), err) - - suite.Require().NoError(proof.ValidateBasic()) - suite.Require().Error(types.MerkleProof{}.ValidateBasic()) - - cases := []struct { - name string - root []byte - pathArr []string - value []byte - malleate func() - shouldPass bool - }{ - {"valid proof", cid.Hash, []string{suite.storeKey.Name(), "MYKEY"}, []byte("MYVALUE"), func() {}, true}, // valid proof - {"wrong value", cid.Hash, []string{suite.storeKey.Name(), "MYKEY"}, []byte("WRONGVALUE"), func() {}, false}, // invalid proof with wrong value - {"nil value", cid.Hash, []string{suite.storeKey.Name(), "MYKEY"}, []byte(nil), func() {}, false}, // invalid proof with nil value - {"wrong key", cid.Hash, []string{suite.storeKey.Name(), "NOTMYKEY"}, []byte("MYVALUE"), func() {}, false}, // invalid proof with wrong key - {"wrong path 1", cid.Hash, []string{suite.storeKey.Name(), "MYKEY", "MYKEY"}, []byte("MYVALUE"), func() {}, false}, // invalid proof with wrong path - {"wrong path 2", cid.Hash, []string{suite.storeKey.Name()}, []byte("MYVALUE"), func() {}, false}, // invalid proof with wrong path - {"wrong path 3", cid.Hash, []string{"MYKEY"}, []byte("MYVALUE"), func() {}, false}, // invalid proof with wrong path - {"wrong storekey", cid.Hash, []string{"otherStoreKey", "MYKEY"}, []byte("MYVALUE"), func() {}, false}, // invalid proof with wrong store prefix - {"wrong root", []byte("WRONGROOT"), []string{suite.storeKey.Name(), "MYKEY"}, []byte("MYVALUE"), func() {}, false}, // invalid proof with wrong root - {"nil root", []byte(nil), []string{suite.storeKey.Name(), "MYKEY"}, []byte("MYVALUE"), func() {}, false}, // invalid proof with nil root - {"proof is wrong length", cid.Hash, []string{suite.storeKey.Name(), "MYKEY"}, []byte("MYVALUE"), func() { - proof = types.MerkleProof{ - Proofs: proof.Proofs[1:], - } - }, false}, // invalid proof with wrong length - - } - - for i, tc := range cases { - tc := tc - suite.Run(tc.name, func() { - tc.malleate() - - root := types.NewMerkleRoot(tc.root) - path := types.NewMerklePath(tc.pathArr...) - - err := proof.VerifyMembership(types.GetSDKSpecs(), &root, path, tc.value) - - if tc.shouldPass { - // nolint: scopelint - suite.Require().NoError(err, "test case %d should have passed", i) - } else { - // nolint: scopelint - suite.Require().Error(err, "test case %d should have failed", i) - } - }) - } - -} - -func (suite *MerkleTestSuite) TestVerifyNonMembership() { - suite.iavlStore.Set([]byte("MYKEY"), []byte("MYVALUE")) - cid := suite.store.Commit() - - // Get Proof - res := suite.store.Query(abci.RequestQuery{ - Path: fmt.Sprintf("/%s/key", suite.storeKey.Name()), // required path to get key/value+proof - Data: []byte("MYABSENTKEY"), - Prove: true, - }) - require.NotNil(suite.T(), res.ProofOps) - - proof, err := types.ConvertProofs(res.ProofOps) - require.NoError(suite.T(), err) - - suite.Require().NoError(proof.ValidateBasic()) - - cases := []struct { - name string - root []byte - pathArr []string - malleate func() - shouldPass bool - }{ - {"valid proof", cid.Hash, []string{suite.storeKey.Name(), "MYABSENTKEY"}, func() {}, true}, // valid proof - {"wrong key", cid.Hash, []string{suite.storeKey.Name(), "MYKEY"}, func() {}, false}, // invalid proof with existent key - {"wrong path 1", cid.Hash, []string{suite.storeKey.Name(), "MYKEY", "MYABSENTKEY"}, func() {}, false}, // invalid proof with wrong path - {"wrong path 2", cid.Hash, []string{suite.storeKey.Name(), "MYABSENTKEY", "MYKEY"}, func() {}, false}, // invalid proof with wrong path - {"wrong path 3", cid.Hash, []string{suite.storeKey.Name()}, func() {}, false}, // invalid proof with wrong path - {"wrong path 4", cid.Hash, []string{"MYABSENTKEY"}, func() {}, false}, // invalid proof with wrong path - {"wrong storeKey", cid.Hash, []string{"otherStoreKey", "MYABSENTKEY"}, func() {}, false}, // invalid proof with wrong store prefix - {"wrong root", []byte("WRONGROOT"), []string{suite.storeKey.Name(), "MYABSENTKEY"}, func() {}, false}, // invalid proof with wrong root - {"nil root", []byte(nil), []string{suite.storeKey.Name(), "MYABSENTKEY"}, func() {}, false}, // invalid proof with nil root - {"proof is wrong length", cid.Hash, []string{suite.storeKey.Name(), "MYKEY"}, func() { - proof = types.MerkleProof{ - Proofs: proof.Proofs[1:], - } - }, false}, // invalid proof with wrong length - - } - - for i, tc := range cases { - tc := tc - - suite.Run(tc.name, func() { - tc.malleate() - - root := types.NewMerkleRoot(tc.root) - path := types.NewMerklePath(tc.pathArr...) - - err := proof.VerifyNonMembership(types.GetSDKSpecs(), &root, path) - - if tc.shouldPass { - // nolint: scopelint - suite.Require().NoError(err, "test case %d should have passed", i) - } else { - // nolint: scopelint - suite.Require().Error(err, "test case %d should have failed", i) - } - }) - } - -} - -func TestApplyPrefix(t *testing.T) { - prefix := types.NewMerklePrefix([]byte("storePrefixKey")) - - pathStr := "pathone/pathtwo/paththree/key" - path := types.MerklePath{ - KeyPath: []string{pathStr}, - } - - prefixedPath, err := types.ApplyPrefix(prefix, path) - require.NoError(t, err, "valid prefix returns error") - - require.Equal(t, "/storePrefixKey/"+pathStr, prefixedPath.Pretty(), "Prefixed path incorrect") - require.Equal(t, "/storePrefixKey/pathone%2Fpathtwo%2Fpaththree%2Fkey", prefixedPath.String(), "Prefixed escaped path incorrect") -} - -func TestString(t *testing.T) { - path := types.NewMerklePath("rootKey", "storeKey", "path/to/leaf") - - require.Equal(t, "/rootKey/storeKey/path%2Fto%2Fleaf", path.String(), "path String returns unxpected value") - require.Equal(t, "/rootKey/storeKey/path/to/leaf", path.Pretty(), "path's pretty string representation is incorrect") - - onePath := types.NewMerklePath("path/to/leaf") - - require.Equal(t, "/path%2Fto%2Fleaf", onePath.String(), "one element path does not have correct string representation") - require.Equal(t, "/path/to/leaf", onePath.Pretty(), "one element path has incorrect pretty string representation") - - zeroPath := types.NewMerklePath() - - require.Equal(t, "", zeroPath.String(), "zero element path does not have correct string representation") - require.Equal(t, "", zeroPath.Pretty(), "zero element path does not have correct pretty string representation") -} diff --git a/x/ibc/core/23-commitment/types/utils.go b/x/ibc/core/23-commitment/types/utils.go deleted file mode 100644 index e662f772655a..000000000000 --- a/x/ibc/core/23-commitment/types/utils.go +++ /dev/null @@ -1,28 +0,0 @@ -package types - -import ( - ics23 "github.com/confio/ics23/go" - crypto "github.com/tendermint/tendermint/proto/tendermint/crypto" - - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" -) - -// ConvertProofs converts crypto.ProofOps into MerkleProof -func ConvertProofs(tmProof *crypto.ProofOps) (MerkleProof, error) { - if tmProof == nil { - return MerkleProof{}, sdkerrors.Wrapf(ErrInvalidMerkleProof, "tendermint proof is nil") - } - // Unmarshal all proof ops to CommitmentProof - proofs := make([]*ics23.CommitmentProof, len(tmProof.Ops)) - for i, op := range tmProof.Ops { - var p ics23.CommitmentProof - err := p.Unmarshal(op.Data) - if err != nil || p.Proof == nil { - return MerkleProof{}, sdkerrors.Wrapf(ErrInvalidMerkleProof, "could not unmarshal proof op into CommitmentProof at index %d: %v", i, err) - } - proofs[i] = &p - } - return MerkleProof{ - Proofs: proofs, - }, nil -} diff --git a/x/ibc/core/23-commitment/types/utils_test.go b/x/ibc/core/23-commitment/types/utils_test.go deleted file mode 100644 index f852fb6c2c4b..000000000000 --- a/x/ibc/core/23-commitment/types/utils_test.go +++ /dev/null @@ -1,98 +0,0 @@ -package types_test - -import ( - "fmt" - - "github.com/stretchr/testify/require" - abci "github.com/tendermint/tendermint/abci/types" - crypto "github.com/tendermint/tendermint/proto/tendermint/crypto" - - "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types" -) - -func (suite *MerkleTestSuite) TestConvertProofs() { - suite.iavlStore.Set([]byte("MYKEY"), []byte("MYVALUE")) - cid := suite.store.Commit() - - root := types.NewMerkleRoot(cid.Hash) - existsPath := types.NewMerklePath(suite.storeKey.Name(), "MYKEY") - nonexistPath := types.NewMerklePath(suite.storeKey.Name(), "NOTMYKEY") - value := []byte("MYVALUE") - - var proofOps *crypto.ProofOps - testcases := []struct { - name string - malleate func() - keyExists bool - expPass bool - }{ - { - "success for ExistenceProof", - func() { - res := suite.store.Query(abci.RequestQuery{ - Path: fmt.Sprintf("/%s/key", suite.storeKey.Name()), // required path to get key/value+proof - Data: []byte("MYKEY"), - Prove: true, - }) - require.NotNil(suite.T(), res.ProofOps) - - proofOps = res.ProofOps - }, - true, true, - }, - { - "success for NonexistenceProof", - func() { - res := suite.store.Query(abci.RequestQuery{ - Path: fmt.Sprintf("/%s/key", suite.storeKey.Name()), // required path to get key/value+proof - Data: []byte("NOTMYKEY"), - Prove: true, - }) - require.NotNil(suite.T(), res.ProofOps) - - proofOps = res.ProofOps - }, - false, true, - }, - { - "nil proofOps", - func() { - proofOps = nil - }, - true, false, - }, - { - "proof op data is nil", - func() { - res := suite.store.Query(abci.RequestQuery{ - Path: fmt.Sprintf("/%s/key", suite.storeKey.Name()), // required path to get key/value+proof - Data: []byte("MYKEY"), - Prove: true, - }) - require.NotNil(suite.T(), res.ProofOps) - - proofOps = res.ProofOps - proofOps.Ops[0].Data = nil - }, - true, false, - }, - } - - for _, tc := range testcases { - tc.malleate() - - proof, err := types.ConvertProofs(proofOps) - if tc.expPass { - suite.Require().NoError(err, "ConvertProofs unexpectedly returned error for case: %s", tc.name) - if tc.keyExists { - err := proof.VerifyMembership(types.GetSDKSpecs(), &root, existsPath, value) - suite.Require().NoError(err, "converted proof failed to verify membership for case: %s", tc.name) - } else { - err := proof.VerifyNonMembership(types.GetSDKSpecs(), &root, nonexistPath) - suite.Require().NoError(err, "converted proof failed to verify membership for case: %s", tc.name) - } - } else { - suite.Require().Error(err, "ConvertProofs passed on invalid case for case: %s", tc.name) - } - } -} diff --git a/x/ibc/core/24-host/errors.go b/x/ibc/core/24-host/errors.go deleted file mode 100644 index fe8129bde864..000000000000 --- a/x/ibc/core/24-host/errors.go +++ /dev/null @@ -1,15 +0,0 @@ -package host - -import ( - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" -) - -// SubModuleName defines the ICS 24 host -const SubModuleName = "host" - -// IBC client sentinel errors -var ( - ErrInvalidID = sdkerrors.Register(SubModuleName, 2, "invalid identifier") - ErrInvalidPath = sdkerrors.Register(SubModuleName, 3, "invalid path") - ErrInvalidPacket = sdkerrors.Register(SubModuleName, 4, "invalid packet") -) diff --git a/x/ibc/core/24-host/keys.go b/x/ibc/core/24-host/keys.go deleted file mode 100644 index 21f4bc43090d..000000000000 --- a/x/ibc/core/24-host/keys.go +++ /dev/null @@ -1,235 +0,0 @@ -package host - -import ( - "fmt" - - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -const ( - // ModuleName is the name of the IBC module - ModuleName = "ibc" - - // StoreKey is the string store representation - StoreKey string = ModuleName - - // QuerierRoute is the querier route for the IBC module - QuerierRoute string = ModuleName - - // RouterKey is the msg router key for the IBC module - RouterKey string = ModuleName -) - -// KVStore key prefixes for IBC -var ( - KeyClientStorePrefix = []byte("clients") -) - -// KVStore key prefixes for IBC -const ( - KeyClientState = "clientState" - KeyConsensusStatePrefix = "consensusStates" - KeyConnectionPrefix = "connections" - KeyChannelEndPrefix = "channelEnds" - KeyChannelPrefix = "channels" - KeyPortPrefix = "ports" - KeySequencePrefix = "sequences" - KeyChannelCapabilityPrefix = "capabilities" - KeyNextSeqSendPrefix = "nextSequenceSend" - KeyNextSeqRecvPrefix = "nextSequenceRecv" - KeyNextSeqAckPrefix = "nextSequenceAck" - KeyPacketCommitmentPrefix = "commitments" - KeyPacketAckPrefix = "acks" - KeyPacketReceiptPrefix = "receipts" -) - -// FullClientPath returns the full path of a specific client path in the format: -// "clients/{clientID}/{path}" as a string. -func FullClientPath(clientID string, path string) string { - return fmt.Sprintf("%s/%s/%s", KeyClientStorePrefix, clientID, path) -} - -// FullClientKey returns the full path of specific client path in the format: -// "clients/{clientID}/{path}" as a byte array. -func FullClientKey(clientID string, path []byte) []byte { - return []byte(FullClientPath(clientID, string(path))) -} - -// ICS02 -// The following paths are the keys to the store as defined in https://github.com/cosmos/ics/tree/master/spec/ics-002-client-semantics#path-space - -// FullClientStatePath takes a client identifier and returns a Path under which to store a -// particular client state -func FullClientStatePath(clientID string) string { - return FullClientPath(clientID, KeyClientState) -} - -// FullClientStateKey takes a client identifier and returns a Key under which to store a -// particular client state. -func FullClientStateKey(clientID string) []byte { - return FullClientKey(clientID, []byte(KeyClientState)) -} - -// ClientStateKey returns a store key under which a particular client state is stored -// in a client prefixed store -func ClientStateKey() []byte { - return []byte(KeyClientState) -} - -// FullConsensusStatePath takes a client identifier and returns a Path under which to -// store the consensus state of a client. -func FullConsensusStatePath(clientID string, height exported.Height) string { - return FullClientPath(clientID, ConsensusStatePath(height)) -} - -// FullConsensusStateKey returns the store key for the consensus state of a particular -// client. -func FullConsensusStateKey(clientID string, height exported.Height) []byte { - return []byte(FullConsensusStatePath(clientID, height)) -} - -// ConsensusStatePath returns the suffix store key for the consensus state at a -// particular height stored in a client prefixed store. -func ConsensusStatePath(height exported.Height) string { - return fmt.Sprintf("%s/%s", KeyConsensusStatePrefix, height) -} - -// ConsensusStateKey returns the store key for a the consensus state of a particular -// client stored in a client prefixed store. -func ConsensusStateKey(height exported.Height) []byte { - return []byte(ConsensusStatePath(height)) -} - -// ICS03 -// The following paths are the keys to the store as defined in https://github.com/cosmos/ics/tree/master/spec/ics-003-connection-semantics#store-paths - -// ClientConnectionsPath defines a reverse mapping from clients to a set of connections -func ClientConnectionsPath(clientID string) string { - return FullClientPath(clientID, KeyConnectionPrefix) -} - -// ClientConnectionsKey returns the store key for the connections of a given client -func ClientConnectionsKey(clientID string) []byte { - return []byte(ClientConnectionsPath(clientID)) -} - -// ConnectionPath defines the path under which connection paths are stored -func ConnectionPath(connectionID string) string { - return fmt.Sprintf("%s/%s", KeyConnectionPrefix, connectionID) -} - -// ConnectionKey returns the store key for a particular connection -func ConnectionKey(connectionID string) []byte { - return []byte(ConnectionPath(connectionID)) -} - -// ICS04 -// The following paths are the keys to the store as defined in https://github.com/cosmos/ics/tree/master/spec/ics-004-channel-and-packet-semantics#store-paths - -// ChannelPath defines the path under which channels are stored -func ChannelPath(portID, channelID string) string { - return fmt.Sprintf("%s/%s", KeyChannelEndPrefix, channelPath(portID, channelID)) -} - -// ChannelKey returns the store key for a particular channel -func ChannelKey(portID, channelID string) []byte { - return []byte(ChannelPath(portID, channelID)) -} - -// ChannelCapabilityPath defines the path under which capability keys associated -// with a channel are stored -func ChannelCapabilityPath(portID, channelID string) string { - return fmt.Sprintf("%s/%s", KeyChannelCapabilityPrefix, channelPath(portID, channelID)) -} - -// NextSequenceSendPath defines the next send sequence counter store path -func NextSequenceSendPath(portID, channelID string) string { - return fmt.Sprintf("%s/%s", KeyNextSeqSendPrefix, channelPath(portID, channelID)) -} - -// NextSequenceSendKey returns the store key for the send sequence of a particular -// channel binded to a specific port. -func NextSequenceSendKey(portID, channelID string) []byte { - return []byte(NextSequenceSendPath(portID, channelID)) -} - -// NextSequenceRecvPath defines the next receive sequence counter store path. -func NextSequenceRecvPath(portID, channelID string) string { - return fmt.Sprintf("%s/%s", KeyNextSeqRecvPrefix, channelPath(portID, channelID)) -} - -// NextSequenceRecvKey returns the store key for the receive sequence of a particular -// channel binded to a specific port -func NextSequenceRecvKey(portID, channelID string) []byte { - return []byte(NextSequenceRecvPath(portID, channelID)) -} - -// NextSequenceAckPath defines the next acknowledgement sequence counter store path -func NextSequenceAckPath(portID, channelID string) string { - return fmt.Sprintf("%s/%s", KeyNextSeqAckPrefix, channelPath(portID, channelID)) -} - -// NextSequenceAckKey returns the store key for the acknowledgement sequence of -// a particular channel binded to a specific port. -func NextSequenceAckKey(portID, channelID string) []byte { - return []byte(NextSequenceAckPath(portID, channelID)) -} - -// PacketCommitmentPath defines the commitments to packet data fields store path -func PacketCommitmentPath(portID, channelID string, sequence uint64) string { - return fmt.Sprintf("%s/%d", PacketCommitmentPrefixPath(portID, channelID), sequence) -} - -// PacketCommitmentKey returns the store key of under which a packet commitment -// is stored -func PacketCommitmentKey(portID, channelID string, sequence uint64) []byte { - return []byte(PacketCommitmentPath(portID, channelID, sequence)) -} - -// PacketCommitmentPrefixPath defines the prefix for commitments to packet data fields store path. -func PacketCommitmentPrefixPath(portID, channelID string) string { - return fmt.Sprintf("%s/%s/%s", KeyPacketCommitmentPrefix, channelPath(portID, channelID), KeySequencePrefix) -} - -// PacketAcknowledgementPath defines the packet acknowledgement store path -func PacketAcknowledgementPath(portID, channelID string, sequence uint64) string { - return fmt.Sprintf("%s/%d", PacketAcknowledgementPrefixPath(portID, channelID), sequence) -} - -// PacketAcknowledgementKey returns the store key of under which a packet -// acknowledgement is stored -func PacketAcknowledgementKey(portID, channelID string, sequence uint64) []byte { - return []byte(PacketAcknowledgementPath(portID, channelID, sequence)) -} - -// PacketAcknowledgementPrefixPath defines the prefix for commitments to packet data fields store path. -func PacketAcknowledgementPrefixPath(portID, channelID string) string { - return fmt.Sprintf("%s/%s/%s", KeyPacketAckPrefix, channelPath(portID, channelID), KeySequencePrefix) -} - -// PacketReceiptPath defines the packet receipt store path -func PacketReceiptPath(portID, channelID string, sequence uint64) string { - return fmt.Sprintf("%s/%s/%s", KeyPacketReceiptPrefix, channelPath(portID, channelID), sequencePath(sequence)) -} - -// PacketReceiptKey returns the store key of under which a packet -// receipt is stored -func PacketReceiptKey(portID, channelID string, sequence uint64) []byte { - return []byte(PacketReceiptPath(portID, channelID, sequence)) -} - -func channelPath(portID, channelID string) string { - return fmt.Sprintf("%s/%s/%s/%s", KeyPortPrefix, portID, KeyChannelPrefix, channelID) -} - -func sequencePath(sequence uint64) string { - return fmt.Sprintf("%s/%d", KeySequencePrefix, sequence) -} - -// ICS05 -// The following paths are the keys to the store as defined in https://github.com/cosmos/ics/tree/master/spec/ics-005-port-allocation#store-paths - -// PortPath defines the path under which ports paths are stored on the capability module -func PortPath(portID string) string { - return fmt.Sprintf("%s/%s", KeyPortPrefix, portID) -} diff --git a/x/ibc/core/24-host/parse.go b/x/ibc/core/24-host/parse.go deleted file mode 100644 index 8c3459500d92..000000000000 --- a/x/ibc/core/24-host/parse.go +++ /dev/null @@ -1,79 +0,0 @@ -package host - -import ( - "strconv" - "strings" - - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" -) - -// ParseIdentifier parses the sequence from the identifier using the provided prefix. This function -// does not need to be used by counterparty chains. SDK generated connection and channel identifiers -// are required to use this format. -func ParseIdentifier(identifier, prefix string) (uint64, error) { - if !strings.HasPrefix(identifier, prefix) { - return 0, sdkerrors.Wrapf(ErrInvalidID, "identifier doesn't contain prefix `%s`", prefix) - } - - splitStr := strings.Split(identifier, prefix) - if len(splitStr) != 2 { - return 0, sdkerrors.Wrapf(ErrInvalidID, "identifier must be in format: `%s{N}`", prefix) - } - - // sanity check - if splitStr[0] != "" { - return 0, sdkerrors.Wrapf(ErrInvalidID, "identifier must begin with prefix %s", prefix) - } - - sequence, err := strconv.ParseUint(splitStr[1], 10, 64) - if err != nil { - return 0, sdkerrors.Wrap(err, "failed to parse identifier sequence") - } - return sequence, nil -} - -// ParseConnectionPath returns the connection ID from a full path. It returns -// an error if the provided path is invalid. -func ParseConnectionPath(path string) (string, error) { - split := strings.Split(path, "/") - if len(split) != 2 { - return "", sdkerrors.Wrapf(ErrInvalidPath, "cannot parse connection path %s", path) - } - - return split[1], nil -} - -// ParseChannelPath returns the port and channel ID from a full path. It returns -// an error if the provided path is invalid. -func ParseChannelPath(path string) (string, string, error) { - split := strings.Split(path, "/") - if len(split) < 5 { - return "", "", sdkerrors.Wrapf(ErrInvalidPath, "cannot parse channel path %s", path) - } - - if split[1] != KeyPortPrefix || split[3] != KeyChannelPrefix { - return "", "", sdkerrors.Wrapf(ErrInvalidPath, "cannot parse channel path %s", path) - } - - return split[2], split[4], nil -} - -// MustParseConnectionPath returns the connection ID from a full path. Panics -// if the provided path is invalid. -func MustParseConnectionPath(path string) string { - connectionID, err := ParseConnectionPath(path) - if err != nil { - panic(err) - } - return connectionID -} - -// MustParseChannelPath returns the port and channel ID from a full path. Panics -// if the provided path is invalid. -func MustParseChannelPath(path string) (string, string) { - portID, channelID, err := ParseChannelPath(path) - if err != nil { - panic(err) - } - return portID, channelID -} diff --git a/x/ibc/core/24-host/parse_test.go b/x/ibc/core/24-host/parse_test.go deleted file mode 100644 index 9f74bf5f682d..000000000000 --- a/x/ibc/core/24-host/parse_test.go +++ /dev/null @@ -1,48 +0,0 @@ -package host_test - -import ( - "math" - "testing" - - "github.com/stretchr/testify/require" - - connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" -) - -func TestParseIdentifier(t *testing.T) { - testCases := []struct { - name string - identifier string - prefix string - expSeq uint64 - expPass bool - }{ - {"valid 0", "connection-0", "connection-", 0, true}, - {"valid 1", "connection-1", "connection-", 1, true}, - {"valid large sequence", connectiontypes.FormatConnectionIdentifier(math.MaxUint64), "connection-", math.MaxUint64, true}, - // one above uint64 max - {"invalid uint64", "connection-18446744073709551616", "connection-", 0, false}, - // uint64 == 20 characters - {"invalid large sequence", "connection-2345682193567182931243", "connection-", 0, false}, - {"capital prefix", "Connection-0", "connection-", 0, false}, - {"double prefix", "connection-connection-0", "connection-", 0, false}, - {"doesn't have prefix", "connection-0", "prefix", 0, false}, - {"missing dash", "connection0", "connection-", 0, false}, - {"blank id", " ", "connection-", 0, false}, - {"empty id", "", "connection-", 0, false}, - {"negative sequence", "connection--1", "connection-", 0, false}, - } - - for _, tc := range testCases { - - seq, err := host.ParseIdentifier(tc.identifier, tc.prefix) - require.Equal(t, tc.expSeq, seq) - - if tc.expPass { - require.NoError(t, err, tc.name) - } else { - require.Error(t, err, tc.name) - } - } -} diff --git a/x/ibc/core/24-host/validate.go b/x/ibc/core/24-host/validate.go deleted file mode 100644 index 10458e8d3a71..000000000000 --- a/x/ibc/core/24-host/validate.go +++ /dev/null @@ -1,114 +0,0 @@ -package host - -import ( - "regexp" - "strings" - - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" -) - -// DefaultMaxCharacterLength defines the default maximum character length used -// in validation of identifiers including the client, connection, port and -// channel identifiers. -// -// NOTE: this restriction is specific to this golang implementation of IBC. If -// your use case demands a higher limit, please open an issue and we will consider -// adjusting this restriction. -const DefaultMaxCharacterLength = 64 - -// IsValidID defines regular expression to check if the string consist of -// characters in one of the following categories only: -// - Alphanumeric -// - `.`, `_`, `+`, `-`, `#` -// - `[`, `]`, `<`, `>` -var IsValidID = regexp.MustCompile(`^[a-zA-Z0-9\.\_\+\-\#\[\]\<\>]+$`).MatchString - -// ICS 024 Identifier and Path Validation Implementation -// -// This file defines ValidateFn to validate identifier and path strings -// The spec for ICS 024 can be located here: -// https://github.com/cosmos/ics/tree/master/spec/ics-024-host-requirements - -// ValidateFn function type to validate path and identifier bytestrings -type ValidateFn func(string) error - -func defaultIdentifierValidator(id string, min, max int) error { //nolint:unparam - if strings.TrimSpace(id) == "" { - return sdkerrors.Wrap(ErrInvalidID, "identifier cannot be blank") - } - // valid id MUST NOT contain "/" separator - if strings.Contains(id, "/") { - return sdkerrors.Wrapf(ErrInvalidID, "identifier %s cannot contain separator '/'", id) - } - // valid id must fit the length requirements - if len(id) < min || len(id) > max { - return sdkerrors.Wrapf(ErrInvalidID, "identifier %s has invalid length: %d, must be between %d-%d characters", id, len(id), min, max) - } - // valid id must contain only lower alphabetic characters - if !IsValidID(id) { - return sdkerrors.Wrapf( - ErrInvalidID, - "identifier %s must contain only alphanumeric or the following characters: '.', '_', '+', '-', '#', '[', ']', '<', '>'", - id, - ) - } - return nil -} - -// ClientIdentifierValidator is the default validator function for Client identifiers. -// A valid Identifier must be between 9-64 characters and only contain alphanumeric and some allowed -// special characters (see IsValidID). -func ClientIdentifierValidator(id string) error { - return defaultIdentifierValidator(id, 9, DefaultMaxCharacterLength) -} - -// ConnectionIdentifierValidator is the default validator function for Connection identifiers. -// A valid Identifier must be between 10-64 characters and only contain alphanumeric and some allowed -// special characters (see IsValidID). -func ConnectionIdentifierValidator(id string) error { - return defaultIdentifierValidator(id, 10, DefaultMaxCharacterLength) -} - -// ChannelIdentifierValidator is the default validator function for Channel identifiers. -// A valid Identifier must be between 8-64 characters and only contain alphanumeric and some allowed -// special characters (see IsValidID). -func ChannelIdentifierValidator(id string) error { - return defaultIdentifierValidator(id, 8, DefaultMaxCharacterLength) -} - -// PortIdentifierValidator is the default validator function for Port identifiers. -// A valid Identifier must be between 2-64 characters and only contain alphanumeric and some allowed -// special characters (see IsValidID). -func PortIdentifierValidator(id string) error { - return defaultIdentifierValidator(id, 2, DefaultMaxCharacterLength) -} - -// NewPathValidator takes in a Identifier Validator function and returns -// a Path Validator function which requires path to consist of `/`-separated valid identifiers, -// where a valid identifier is between 1-64 characters, contains only alphanumeric and some allowed -// special characters (see IsValidID), and satisfies the custom `idValidator` function. -func NewPathValidator(idValidator ValidateFn) ValidateFn { - return func(path string) error { - pathArr := strings.Split(path, "/") - if len(pathArr) > 0 && pathArr[0] == path { - return sdkerrors.Wrapf(ErrInvalidPath, "path %s doesn't contain any separator '/'", path) - } - - for _, p := range pathArr { - // a path beginning or ending in a separator returns empty string elements. - if p == "" { - return sdkerrors.Wrapf(ErrInvalidPath, "path %s cannot begin or end with '/'", path) - } - - if err := idValidator(p); err != nil { - return err - } - // Each path element must either be a valid identifier or constant number - if err := defaultIdentifierValidator(p, 1, DefaultMaxCharacterLength); err != nil { - return sdkerrors.Wrapf(err, "path %s contains an invalid identifier: '%s'", path, p) - } - } - - return nil - } -} diff --git a/x/ibc/core/24-host/validate_test.go b/x/ibc/core/24-host/validate_test.go deleted file mode 100644 index 40987bd15714..000000000000 --- a/x/ibc/core/24-host/validate_test.go +++ /dev/null @@ -1,119 +0,0 @@ -package host - -import ( - "fmt" - "strings" - "testing" - - "github.com/stretchr/testify/require" -) - -type testCase struct { - msg string - id string - expPass bool -} - -func TestDefaultIdentifierValidator(t *testing.T) { - testCases := []testCase{ - {"valid lowercase", "lowercaseid", true}, - {"valid id special chars", "._+-#[]<>._+-#[]<>", true}, - {"valid id lower and special chars", "lower._+-#[]<>", true}, - {"numeric id", "1234567890", true}, - {"uppercase id", "NOTLOWERCASE", true}, - {"numeric id", "1234567890", true}, - {"blank id", " ", false}, - {"id length out of range", "1", false}, - {"id is too long", "this identifier is too long to be used as a valid identifier", false}, - {"path-like id", "lower/case/id", false}, - {"invalid id", "(clientid)", false}, - {"empty string", "", false}, - } - - for _, tc := range testCases { - - err := ClientIdentifierValidator(tc.id) - err1 := ConnectionIdentifierValidator(tc.id) - err2 := ChannelIdentifierValidator(tc.id) - err3 := PortIdentifierValidator(tc.id) - if tc.expPass { - require.NoError(t, err, tc.msg) - require.NoError(t, err1, tc.msg) - require.NoError(t, err2, tc.msg) - require.NoError(t, err3, tc.msg) - } else { - require.Error(t, err, tc.msg) - require.Error(t, err1, tc.msg) - require.Error(t, err2, tc.msg) - require.Error(t, err3, tc.msg) - } - } -} - -func TestPathValidator(t *testing.T) { - testCases := []testCase{ - {"valid lowercase", "p/lowercaseid", true}, - {"numeric path", "p/239123", true}, - {"valid id special chars", "p/._+-#[]<>._+-#[]<>", true}, - {"valid id lower and special chars", "lower/._+-#[]<>", true}, - {"id length out of range", "p/l", true}, - {"uppercase id", "p/NOTLOWERCASE", true}, - {"invalid path", "lowercaseid", false}, - {"blank id", "p/ ", false}, - {"id length out of range", "p/12345678901234567890123456789012345678901234567890123456789012345", false}, - {"invalid id", "p/(clientid)", false}, - {"empty string", "", false}, - {"separators only", "////", false}, - {"just separator", "/", false}, - {"begins with separator", "/id", false}, - {"blank before separator", " /id", false}, - {"ends with separator", "id/", false}, - {"blank after separator", "id/ ", false}, - {"blanks with separator", " / ", false}, - } - - for _, tc := range testCases { - f := NewPathValidator(func(path string) error { - return nil - }) - - err := f(tc.id) - - if tc.expPass { - seps := strings.Count(tc.id, "/") - require.Equal(t, 1, seps) - require.NoError(t, err, tc.msg) - } else { - require.Error(t, err, tc.msg) - } - } -} - -func TestCustomPathValidator(t *testing.T) { - validateFn := NewPathValidator(func(path string) error { - if !strings.HasPrefix(path, "id_") { - return fmt.Errorf("identifier %s must start with 'id_", path) - } - return nil - }) - - testCases := []testCase{ - {"valid custom path", "id_client/id_one", true}, - {"invalid path", "client", false}, - {"invalid custom path", "id_one/client", false}, - {"invalid identifier", "id_client/id_1234567890123456789012345678901234567890123457890123456789012345", false}, - {"separators only", "////", false}, - {"just separator", "/", false}, - {"ends with separator", "id_client/id_one/", false}, - {"beings with separator", "/id_client/id_one", false}, - } - - for _, tc := range testCases { - err := validateFn(tc.id) - if tc.expPass { - require.NoError(t, err, tc.msg) - } else { - require.Error(t, err, tc.msg) - } - } -} diff --git a/x/ibc/core/client/cli/cli.go b/x/ibc/core/client/cli/cli.go deleted file mode 100644 index bda4123be0ec..000000000000 --- a/x/ibc/core/client/cli/cli.go +++ /dev/null @@ -1,50 +0,0 @@ -package cli - -import ( - "github.com/spf13/cobra" - - "github.com/cosmos/cosmos-sdk/client" - ibcclient "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client" - 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" -) - -// GetTxCmd returns the transaction commands for this module -func GetTxCmd() *cobra.Command { - ibcTxCmd := &cobra.Command{ - Use: host.ModuleName, - Short: "IBC transaction subcommands", - DisableFlagParsing: true, - SuggestionsMinimumDistance: 2, - RunE: client.ValidateCmd, - } - - ibcTxCmd.AddCommand( - ibcclient.GetTxCmd(), - connection.GetTxCmd(), - channel.GetTxCmd(), - ) - - return ibcTxCmd -} - -// GetQueryCmd returns the cli query commands for this module -func GetQueryCmd() *cobra.Command { - // Group ibc queries under a subcommand - ibcQueryCmd := &cobra.Command{ - Use: host.ModuleName, - Short: "Querying commands for the IBC module", - DisableFlagParsing: true, - SuggestionsMinimumDistance: 2, - RunE: client.ValidateCmd, - } - - ibcQueryCmd.AddCommand( - ibcclient.GetQueryCmd(), - connection.GetQueryCmd(), - channel.GetQueryCmd(), - ) - - return ibcQueryCmd -} diff --git a/x/ibc/core/client/query.go b/x/ibc/core/client/query.go deleted file mode 100644 index 7055f1c740bf..000000000000 --- a/x/ibc/core/client/query.go +++ /dev/null @@ -1,67 +0,0 @@ -package client - -import ( - "fmt" - - abci "github.com/tendermint/tendermint/abci/types" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" -) - -// QueryTendermintProof performs an ABCI query with the given key and returns -// the value of the query, the proto encoded merkle proof, and the height of -// the Tendermint block containing the state root. The desired tendermint height -// to perform the query should be set in the client context. The query will be -// performed at one below this height (at the IAVL version) in order to obtain -// the correct merkle proof. Proof queries at height less than or equal to 2 are -// not supported. Queries with a client context height of 0 will perform a query -// at the lastest state available. -// Issue: https://github.com/cosmos/cosmos-sdk/issues/6567 -func QueryTendermintProof(clientCtx client.Context, key []byte) ([]byte, []byte, clienttypes.Height, error) { - height := clientCtx.Height - - // ABCI queries at heights 1, 2 or less than or equal to 0 are not supported. - // Base app does not support queries for height less than or equal to 1. - // Therefore, a query at height 2 would be equivalent to a query at height 3. - // A height of 0 will query with the lastest state. - if height != 0 && height <= 2 { - return nil, nil, clienttypes.Height{}, fmt.Errorf("proof queries at height <= 2 are not supported") - } - - // Use the IAVL height if a valid tendermint height is passed in. - // A height of 0 will query with the latest state. - if height != 0 { - height-- - } - - req := abci.RequestQuery{ - Path: fmt.Sprintf("store/%s/key", host.StoreKey), - Height: height, - Data: key, - Prove: true, - } - - res, err := clientCtx.QueryABCI(req) - if err != nil { - return nil, nil, clienttypes.Height{}, err - } - - merkleProof, err := commitmenttypes.ConvertProofs(res.ProofOps) - if err != nil { - return nil, nil, clienttypes.Height{}, err - } - - cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry) - - proofBz, err := cdc.MarshalBinaryBare(&merkleProof) - if err != nil { - return nil, nil, clienttypes.Height{}, err - } - - revision := clienttypes.ParseChainID(clientCtx.ChainID) - return res.Value, proofBz, clienttypes.NewHeight(revision, uint64(res.Height)+1), nil -} diff --git a/x/ibc/core/exported/channel.go b/x/ibc/core/exported/channel.go deleted file mode 100644 index 6a0d542c1eea..000000000000 --- a/x/ibc/core/exported/channel.go +++ /dev/null @@ -1,32 +0,0 @@ -package exported - -// ChannelI defines the standard interface for a channel end. -type ChannelI interface { - GetState() int32 - GetOrdering() int32 - GetCounterparty() CounterpartyChannelI - GetConnectionHops() []string - GetVersion() string - ValidateBasic() error -} - -// CounterpartyChannelI defines the standard interface for a channel end's -// counterparty. -type CounterpartyChannelI interface { - GetPortID() string - GetChannelID() string - ValidateBasic() error -} - -// PacketI defines the standard interface for IBC packets -type PacketI interface { - GetSequence() uint64 - GetTimeoutHeight() Height - GetTimeoutTimestamp() uint64 - GetSourcePort() string - GetSourceChannel() string - GetDestPort() string - GetDestChannel() string - GetData() []byte - ValidateBasic() error -} diff --git a/x/ibc/core/exported/client.go b/x/ibc/core/exported/client.go deleted file mode 100644 index 3d552b07724a..000000000000 --- a/x/ibc/core/exported/client.go +++ /dev/null @@ -1,223 +0,0 @@ -package exported - -import ( - ics23 "github.com/confio/ics23/go" - proto "github.com/gogo/protobuf/proto" - - "github.com/cosmos/cosmos-sdk/codec" - sdk "github.com/cosmos/cosmos-sdk/types" -) - -const ( - // TypeClientMisbehaviour is the shared evidence misbehaviour type - TypeClientMisbehaviour string = "client_misbehaviour" - - // Solomachine is used to indicate that the light client is a solo machine. - Solomachine string = "06-solomachine" - - // Tendermint is used to indicate that the client uses the Tendermint Consensus Algorithm. - Tendermint string = "07-tendermint" - - // Localhost is the client type for a localhost client. It is also used as the clientID - // for the localhost client. - Localhost string = "09-localhost" -) - -// ClientState defines the required common functions for light clients. -type ClientState interface { - proto.Message - - ClientType() string - GetLatestHeight() Height - IsFrozen() bool - GetFrozenHeight() Height - Validate() error - GetProofSpecs() []*ics23.ProofSpec - - // Initialization function - // Clients must validate the initial consensus state, and may store any client-specific metadata - // necessary for correct light client operation - Initialize(sdk.Context, codec.BinaryMarshaler, sdk.KVStore, ConsensusState) error - - // Genesis function - ExportMetadata(sdk.KVStore) []GenesisMetadata - - // Update and Misbehaviour functions - - CheckHeaderAndUpdateState(sdk.Context, codec.BinaryMarshaler, sdk.KVStore, Header) (ClientState, ConsensusState, error) - CheckMisbehaviourAndUpdateState(sdk.Context, codec.BinaryMarshaler, sdk.KVStore, Misbehaviour) (ClientState, 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 - // 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, - ) (ClientState, ConsensusState, error) - // 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 - - // State verification functions - - VerifyClientState( - store sdk.KVStore, - cdc codec.BinaryMarshaler, - height Height, - prefix Prefix, - counterpartyClientIdentifier string, - proof []byte, - clientState ClientState, - ) error - VerifyClientConsensusState( - store sdk.KVStore, - cdc codec.BinaryMarshaler, - height Height, - counterpartyClientIdentifier string, - consensusHeight Height, - prefix Prefix, - proof []byte, - consensusState ConsensusState, - ) error - VerifyConnectionState( - store sdk.KVStore, - cdc codec.BinaryMarshaler, - height Height, - prefix Prefix, - proof []byte, - connectionID string, - connectionEnd ConnectionI, - ) error - VerifyChannelState( - store sdk.KVStore, - cdc codec.BinaryMarshaler, - height Height, - prefix Prefix, - proof []byte, - portID, - channelID string, - channel ChannelI, - ) error - VerifyPacketCommitment( - store sdk.KVStore, - cdc codec.BinaryMarshaler, - height Height, - currentTimestamp uint64, - delayPeriod uint64, - prefix Prefix, - proof []byte, - portID, - channelID string, - sequence uint64, - commitmentBytes []byte, - ) error - VerifyPacketAcknowledgement( - store sdk.KVStore, - cdc codec.BinaryMarshaler, - height Height, - currentTimestamp uint64, - delayPeriod uint64, - prefix Prefix, - proof []byte, - portID, - channelID string, - sequence uint64, - acknowledgement []byte, - ) error - VerifyPacketReceiptAbsence( - store sdk.KVStore, - cdc codec.BinaryMarshaler, - height Height, - currentTimestamp uint64, - delayPeriod uint64, - prefix Prefix, - proof []byte, - portID, - channelID string, - sequence uint64, - ) error - VerifyNextSequenceRecv( - store sdk.KVStore, - cdc codec.BinaryMarshaler, - height Height, - currentTimestamp uint64, - delayPeriod uint64, - prefix Prefix, - proof []byte, - portID, - channelID string, - nextSequenceRecv uint64, - ) error -} - -// ConsensusState is the state of the consensus process -type ConsensusState interface { - proto.Message - - ClientType() string // Consensus kind - - // GetRoot returns the commitment root of the consensus state, - // which is used for key-value pair verification. - GetRoot() Root - - // GetTimestamp returns the timestamp (in nanoseconds) of the consensus state - GetTimestamp() uint64 - - ValidateBasic() error -} - -// Misbehaviour defines counterparty misbehaviour for a specific consensus type -type Misbehaviour interface { - proto.Message - - ClientType() string - GetClientID() string - ValidateBasic() error - - // Height at which the infraction occurred - GetHeight() Height -} - -// Header is the consensus state update information -type Header interface { - proto.Message - - ClientType() string - GetHeight() Height - ValidateBasic() error -} - -// Height is a wrapper interface over clienttypes.Height -// all clients must use the concrete implementation in types -type Height interface { - IsZero() bool - LT(Height) bool - LTE(Height) bool - EQ(Height) bool - GT(Height) bool - GTE(Height) bool - GetRevisionNumber() uint64 - GetRevisionHeight() uint64 - Increment() Height - Decrement() (Height, bool) - String() string -} - -// GenesisMetadata is a wrapper interface over clienttypes.GenesisMetadata -// all clients must use the concrete implementation in types -type GenesisMetadata interface { - // return store key that contains metadata without clientID-prefix - GetKey() []byte - // returns metadata value - GetValue() []byte -} diff --git a/x/ibc/core/exported/commitment.go b/x/ibc/core/exported/commitment.go deleted file mode 100644 index b4f2c0c18f59..000000000000 --- a/x/ibc/core/exported/commitment.go +++ /dev/null @@ -1,45 +0,0 @@ -package exported - -import ics23 "github.com/confio/ics23/go" - -// ICS 023 Types Implementation -// -// This file includes types defined under -// https://github.com/cosmos/ics/tree/master/spec/ics-023-vector-commitments - -// spec:Path and spec:Value are defined as bytestring - -// Root implements spec:CommitmentRoot. -// A root is constructed from a set of key-value pairs, -// and the inclusion or non-inclusion of an arbitrary key-value pair -// can be proven with the proof. -type Root interface { - GetHash() []byte - Empty() bool -} - -// Prefix implements spec:CommitmentPrefix. -// Prefix represents the common "prefix" that a set of keys shares. -type Prefix interface { - Bytes() []byte - Empty() bool -} - -// Path implements spec:CommitmentPath. -// A path is the additional information provided to the verification function. -type Path interface { - String() string - Empty() bool -} - -// Proof implements spec:CommitmentProof. -// Proof can prove whether the key-value pair is a part of the Root or not. -// Each proof has designated key-value pair it is able to prove. -// Proofs includes key but value is provided dynamically at the verification time. -type Proof interface { - VerifyMembership([]*ics23.ProofSpec, Root, Path, []byte) error - VerifyNonMembership([]*ics23.ProofSpec, Root, Path) error - Empty() bool - - ValidateBasic() error -} diff --git a/x/ibc/core/exported/connection.go b/x/ibc/core/exported/connection.go deleted file mode 100644 index 8f705daff1ad..000000000000 --- a/x/ibc/core/exported/connection.go +++ /dev/null @@ -1,26 +0,0 @@ -package exported - -// ConnectionI describes the required methods for a connection. -type ConnectionI interface { - GetClientID() string - GetState() int32 - GetCounterparty() CounterpartyConnectionI - GetVersions() []Version - GetDelayPeriod() uint64 - ValidateBasic() error -} - -// CounterpartyConnectionI describes the required methods for a counterparty connection. -type CounterpartyConnectionI interface { - GetClientID() string - GetConnectionID() string - GetPrefix() Prefix - ValidateBasic() error -} - -// Version defines an IBC version used in connection handshake negotiation. -type Version interface { - GetIdentifier() string - GetFeatures() []string - VerifyProposedVersion(Version) error -} diff --git a/x/ibc/core/genesis.go b/x/ibc/core/genesis.go deleted file mode 100644 index 7d5d60b93453..000000000000 --- a/x/ibc/core/genesis.go +++ /dev/null @@ -1,27 +0,0 @@ -package ibc - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" - client "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client" - connection "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection" - channel "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel" - "github.com/cosmos/cosmos-sdk/x/ibc/core/keeper" - "github.com/cosmos/cosmos-sdk/x/ibc/core/types" -) - -// InitGenesis initializes the ibc state from a provided genesis -// state. -func InitGenesis(ctx sdk.Context, k keeper.Keeper, createLocalhost bool, gs *types.GenesisState) { - client.InitGenesis(ctx, k.ClientKeeper, gs.ClientGenesis) - connection.InitGenesis(ctx, k.ConnectionKeeper, gs.ConnectionGenesis) - channel.InitGenesis(ctx, k.ChannelKeeper, gs.ChannelGenesis) -} - -// ExportGenesis returns the ibc exported genesis. -func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState { - return &types.GenesisState{ - ClientGenesis: client.ExportGenesis(ctx, k.ClientKeeper), - ConnectionGenesis: connection.ExportGenesis(ctx, k.ConnectionKeeper), - ChannelGenesis: channel.ExportGenesis(ctx, k.ChannelKeeper), - } -} diff --git a/x/ibc/core/genesis_test.go b/x/ibc/core/genesis_test.go deleted file mode 100644 index c29feef7f8fd..000000000000 --- a/x/ibc/core/genesis_test.go +++ /dev/null @@ -1,370 +0,0 @@ -package ibc_test - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/suite" - tmproto "github.com/tendermint/tendermint/proto/tendermint/types" - - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/simapp" - ibc "github.com/cosmos/cosmos-sdk/x/ibc/core" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - "github.com/cosmos/cosmos-sdk/x/ibc/core/types" - ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" - localhosttypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/09-localhost/types" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" -) - -const ( - connectionID = "connection-0" - clientID = "07-tendermint-0" - connectionID2 = "connection-1" - clientID2 = "07-tendermin-1" - localhostID = exported.Localhost + "-1" - - port1 = "firstport" - port2 = "secondport" - - channel1 = "channel-0" - channel2 = "channel-1" -) - -var clientHeight = clienttypes.NewHeight(0, 10) - -type IBCTestSuite struct { - suite.Suite - - coordinator *ibctesting.Coordinator - - chainA *ibctesting.TestChain - chainB *ibctesting.TestChain -} - -// SetupTest creates a coordinator with 2 test chains. -func (suite *IBCTestSuite) SetupTest() { - suite.coordinator = ibctesting.NewCoordinator(suite.T(), 2) - - suite.chainA = suite.coordinator.GetChain(ibctesting.GetChainID(0)) - suite.chainB = suite.coordinator.GetChain(ibctesting.GetChainID(1)) -} - -func TestIBCTestSuite(t *testing.T) { - suite.Run(t, new(IBCTestSuite)) -} - -func (suite *IBCTestSuite) TestValidateGenesis() { - header := suite.chainA.CreateTMClientHeader(suite.chainA.ChainID, suite.chainA.CurrentHeader.Height, clienttypes.NewHeight(0, uint64(suite.chainA.CurrentHeader.Height-1)), suite.chainA.CurrentHeader.Time, suite.chainA.Vals, suite.chainA.Vals, suite.chainA.Signers) - - testCases := []struct { - name string - genState *types.GenesisState - expPass bool - }{ - { - name: "default", - genState: types.DefaultGenesisState(), - expPass: true, - }, - { - name: "valid genesis", - genState: &types.GenesisState{ - ClientGenesis: clienttypes.NewGenesisState( - []clienttypes.IdentifiedClientState{ - clienttypes.NewIdentifiedClientState( - clientID, ibctmtypes.NewClientState(suite.chainA.ChainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), - ), - clienttypes.NewIdentifiedClientState( - localhostID, localhosttypes.NewClientState("chaindID", clientHeight), - ), - }, - []clienttypes.ClientConsensusStates{ - clienttypes.NewClientConsensusStates( - clientID, - []clienttypes.ConsensusStateWithHeight{ - clienttypes.NewConsensusStateWithHeight( - header.GetHeight().(clienttypes.Height), - ibctmtypes.NewConsensusState( - header.GetTime(), commitmenttypes.NewMerkleRoot(header.Header.AppHash), header.Header.NextValidatorsHash, - ), - ), - }, - ), - }, - []clienttypes.IdentifiedGenesisMetadata{ - clienttypes.NewIdentifiedGenesisMetadata( - clientID, - []clienttypes.GenesisMetadata{ - clienttypes.NewGenesisMetadata([]byte("key1"), []byte("val1")), - clienttypes.NewGenesisMetadata([]byte("key2"), []byte("val2")), - }, - ), - }, - clienttypes.NewParams(exported.Tendermint, exported.Localhost), - true, - 2, - ), - ConnectionGenesis: connectiontypes.NewGenesisState( - []connectiontypes.IdentifiedConnection{ - connectiontypes.NewIdentifiedConnection(connectionID, connectiontypes.NewConnectionEnd(connectiontypes.INIT, clientID, connectiontypes.NewCounterparty(clientID2, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))), []*connectiontypes.Version{ibctesting.ConnectionVersion}, 0)), - }, - []connectiontypes.ConnectionPaths{ - connectiontypes.NewConnectionPaths(clientID, []string{connectionID}), - }, - 0, - ), - ChannelGenesis: channeltypes.NewGenesisState( - []channeltypes.IdentifiedChannel{ - channeltypes.NewIdentifiedChannel( - port1, channel1, channeltypes.NewChannel( - channeltypes.INIT, channeltypes.ORDERED, - channeltypes.NewCounterparty(port2, channel2), []string{connectionID}, ibctesting.DefaultChannelVersion, - ), - ), - }, - []channeltypes.PacketState{ - channeltypes.NewPacketState(port2, channel2, 1, []byte("ack")), - }, - []channeltypes.PacketState{ - channeltypes.NewPacketState(port2, channel2, 1, []byte("")), - }, - []channeltypes.PacketState{ - channeltypes.NewPacketState(port1, channel1, 1, []byte("commit_hash")), - }, - []channeltypes.PacketSequence{ - channeltypes.NewPacketSequence(port1, channel1, 1), - }, - []channeltypes.PacketSequence{ - channeltypes.NewPacketSequence(port2, channel2, 1), - }, - []channeltypes.PacketSequence{ - channeltypes.NewPacketSequence(port2, channel2, 1), - }, - 0, - ), - }, - expPass: true, - }, - { - name: "invalid client genesis", - genState: &types.GenesisState{ - ClientGenesis: clienttypes.NewGenesisState( - []clienttypes.IdentifiedClientState{ - clienttypes.NewIdentifiedClientState( - clientID, ibctmtypes.NewClientState(suite.chainA.ChainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), - ), - clienttypes.NewIdentifiedClientState( - localhostID, localhosttypes.NewClientState("(chaindID)", clienttypes.ZeroHeight()), - ), - }, - nil, - []clienttypes.IdentifiedGenesisMetadata{ - clienttypes.NewIdentifiedGenesisMetadata( - clientID, - []clienttypes.GenesisMetadata{ - clienttypes.NewGenesisMetadata([]byte(""), []byte("val1")), - clienttypes.NewGenesisMetadata([]byte("key2"), []byte("")), - }, - ), - }, - clienttypes.NewParams(exported.Tendermint), - false, - 2, - ), - ConnectionGenesis: connectiontypes.DefaultGenesisState(), - }, - expPass: false, - }, - { - name: "invalid connection genesis", - genState: &types.GenesisState{ - ClientGenesis: clienttypes.DefaultGenesisState(), - ConnectionGenesis: connectiontypes.NewGenesisState( - []connectiontypes.IdentifiedConnection{ - connectiontypes.NewIdentifiedConnection(connectionID, connectiontypes.NewConnectionEnd(connectiontypes.INIT, "(CLIENTIDONE)", connectiontypes.NewCounterparty(clientID, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))), []*connectiontypes.Version{connectiontypes.NewVersion("1.1", nil)}, 0)), - }, - []connectiontypes.ConnectionPaths{ - connectiontypes.NewConnectionPaths(clientID, []string{connectionID}), - }, - 0, - ), - }, - expPass: false, - }, - { - name: "invalid channel genesis", - genState: &types.GenesisState{ - ClientGenesis: clienttypes.DefaultGenesisState(), - ConnectionGenesis: connectiontypes.DefaultGenesisState(), - ChannelGenesis: channeltypes.GenesisState{ - Acknowledgements: []channeltypes.PacketState{ - channeltypes.NewPacketState("(portID)", channel1, 1, []byte("ack")), - }, - }, - }, - expPass: false, - }, - } - - for _, tc := range testCases { - tc := tc - err := tc.genState.Validate() - if tc.expPass { - suite.Require().NoError(err, tc.name) - } else { - suite.Require().Error(err, tc.name) - } - } -} - -func (suite *IBCTestSuite) TestInitGenesis() { - header := suite.chainA.CreateTMClientHeader(suite.chainA.ChainID, suite.chainA.CurrentHeader.Height, clienttypes.NewHeight(0, uint64(suite.chainA.CurrentHeader.Height-1)), suite.chainA.CurrentHeader.Time, suite.chainA.Vals, suite.chainA.Vals, suite.chainA.Signers) - - testCases := []struct { - name string - genState *types.GenesisState - }{ - { - name: "default", - genState: types.DefaultGenesisState(), - }, - { - name: "valid genesis", - genState: &types.GenesisState{ - ClientGenesis: clienttypes.NewGenesisState( - []clienttypes.IdentifiedClientState{ - clienttypes.NewIdentifiedClientState( - clientID, ibctmtypes.NewClientState(suite.chainA.ChainID, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod, ibctesting.MaxClockDrift, clientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), - ), - clienttypes.NewIdentifiedClientState( - exported.Localhost, localhosttypes.NewClientState("chaindID", clientHeight), - ), - }, - []clienttypes.ClientConsensusStates{ - clienttypes.NewClientConsensusStates( - clientID, - []clienttypes.ConsensusStateWithHeight{ - clienttypes.NewConsensusStateWithHeight( - header.GetHeight().(clienttypes.Height), - ibctmtypes.NewConsensusState( - header.GetTime(), commitmenttypes.NewMerkleRoot(header.Header.AppHash), header.Header.NextValidatorsHash, - ), - ), - }, - ), - }, - []clienttypes.IdentifiedGenesisMetadata{ - clienttypes.NewIdentifiedGenesisMetadata( - clientID, - []clienttypes.GenesisMetadata{ - clienttypes.NewGenesisMetadata([]byte("key1"), []byte("val1")), - clienttypes.NewGenesisMetadata([]byte("key2"), []byte("val2")), - }, - ), - }, - clienttypes.NewParams(exported.Tendermint, exported.Localhost), - true, - 0, - ), - ConnectionGenesis: connectiontypes.NewGenesisState( - []connectiontypes.IdentifiedConnection{ - connectiontypes.NewIdentifiedConnection(connectionID, connectiontypes.NewConnectionEnd(connectiontypes.INIT, clientID, connectiontypes.NewCounterparty(clientID2, connectionID2, commitmenttypes.NewMerklePrefix([]byte("prefix"))), []*connectiontypes.Version{ibctesting.ConnectionVersion}, 0)), - }, - []connectiontypes.ConnectionPaths{ - connectiontypes.NewConnectionPaths(clientID, []string{connectionID}), - }, - 0, - ), - ChannelGenesis: channeltypes.NewGenesisState( - []channeltypes.IdentifiedChannel{ - channeltypes.NewIdentifiedChannel( - port1, channel1, channeltypes.NewChannel( - channeltypes.INIT, channeltypes.ORDERED, - channeltypes.NewCounterparty(port2, channel2), []string{connectionID}, ibctesting.DefaultChannelVersion, - ), - ), - }, - []channeltypes.PacketState{ - channeltypes.NewPacketState(port2, channel2, 1, []byte("ack")), - }, - []channeltypes.PacketState{ - channeltypes.NewPacketState(port2, channel2, 1, []byte("")), - }, - []channeltypes.PacketState{ - channeltypes.NewPacketState(port1, channel1, 1, []byte("commit_hash")), - }, - []channeltypes.PacketSequence{ - channeltypes.NewPacketSequence(port1, channel1, 1), - }, - []channeltypes.PacketSequence{ - channeltypes.NewPacketSequence(port2, channel2, 1), - }, - []channeltypes.PacketSequence{ - channeltypes.NewPacketSequence(port2, channel2, 1), - }, - 0, - ), - }, - }, - } - - for _, tc := range testCases { - app := simapp.Setup(false) - - suite.NotPanics(func() { - ibc.InitGenesis(app.BaseApp.NewContext(false, tmproto.Header{Height: 1}), *app.IBCKeeper, true, tc.genState) - }) - } -} - -func (suite *IBCTestSuite) TestExportGenesis() { - testCases := []struct { - msg string - malleate func() - }{ - { - "success", - func() { - // creates clients - suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.UNORDERED) - // create extra clients - suite.coordinator.CreateClient(suite.chainA, suite.chainB, exported.Tendermint) - suite.coordinator.CreateClient(suite.chainA, suite.chainB, exported.Tendermint) - }, - }, - } - - for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { - suite.SetupTest() - - tc.malleate() - - var gs *types.GenesisState - suite.NotPanics(func() { - gs = ibc.ExportGenesis(suite.chainA.GetContext(), *suite.chainA.App.IBCKeeper) - }) - - // init genesis based on export - suite.NotPanics(func() { - ibc.InitGenesis(suite.chainA.GetContext(), *suite.chainA.App.IBCKeeper, true, gs) - }) - - suite.NotPanics(func() { - cdc := codec.NewProtoCodec(suite.chainA.App.InterfaceRegistry()) - genState := cdc.MustMarshalJSON(gs) - cdc.MustUnmarshalJSON(genState, gs) - }) - - // init genesis based on marshal and unmarshal - suite.NotPanics(func() { - ibc.InitGenesis(suite.chainA.GetContext(), *suite.chainA.App.IBCKeeper, true, gs) - }) - }) - } -} diff --git a/x/ibc/core/handler.go b/x/ibc/core/handler.go deleted file mode 100644 index c8e4dfc89848..000000000000 --- a/x/ibc/core/handler.go +++ /dev/null @@ -1,98 +0,0 @@ -package ibc - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/keeper" -) - -// NewHandler defines the IBC handler -func NewHandler(k keeper.Keeper) sdk.Handler { - return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { - ctx = ctx.WithEventManager(sdk.NewEventManager()) - - switch msg := msg.(type) { - // IBC client msg interface types - case *clienttypes.MsgCreateClient: - res, err := k.CreateClient(sdk.WrapSDKContext(ctx), msg) - return sdk.WrapServiceResult(ctx, res, err) - - case *clienttypes.MsgUpdateClient: - res, err := k.UpdateClient(sdk.WrapSDKContext(ctx), msg) - return sdk.WrapServiceResult(ctx, res, err) - - case *clienttypes.MsgUpgradeClient: - res, err := k.UpgradeClient(sdk.WrapSDKContext(ctx), msg) - return sdk.WrapServiceResult(ctx, res, err) - - case *clienttypes.MsgSubmitMisbehaviour: - res, err := k.SubmitMisbehaviour(sdk.WrapSDKContext(ctx), msg) - return sdk.WrapServiceResult(ctx, res, err) - - // IBC connection msgs - case *connectiontypes.MsgConnectionOpenInit: - res, err := k.ConnectionOpenInit(sdk.WrapSDKContext(ctx), msg) - return sdk.WrapServiceResult(ctx, res, err) - - case *connectiontypes.MsgConnectionOpenTry: - res, err := k.ConnectionOpenTry(sdk.WrapSDKContext(ctx), msg) - return sdk.WrapServiceResult(ctx, res, err) - - case *connectiontypes.MsgConnectionOpenAck: - res, err := k.ConnectionOpenAck(sdk.WrapSDKContext(ctx), msg) - return sdk.WrapServiceResult(ctx, res, err) - - case *connectiontypes.MsgConnectionOpenConfirm: - res, err := k.ConnectionOpenConfirm(sdk.WrapSDKContext(ctx), msg) - return sdk.WrapServiceResult(ctx, res, err) - - // IBC channel msgs - case *channeltypes.MsgChannelOpenInit: - res, err := k.ChannelOpenInit(sdk.WrapSDKContext(ctx), msg) - return sdk.WrapServiceResult(ctx, res, err) - - case *channeltypes.MsgChannelOpenTry: - res, err := k.ChannelOpenTry(sdk.WrapSDKContext(ctx), msg) - return sdk.WrapServiceResult(ctx, res, err) - - case *channeltypes.MsgChannelOpenAck: - res, err := k.ChannelOpenAck(sdk.WrapSDKContext(ctx), msg) - return sdk.WrapServiceResult(ctx, res, err) - - case *channeltypes.MsgChannelOpenConfirm: - res, err := k.ChannelOpenConfirm(sdk.WrapSDKContext(ctx), msg) - return sdk.WrapServiceResult(ctx, res, err) - - case *channeltypes.MsgChannelCloseInit: - res, err := k.ChannelCloseInit(sdk.WrapSDKContext(ctx), msg) - return sdk.WrapServiceResult(ctx, res, err) - - case *channeltypes.MsgChannelCloseConfirm: - res, err := k.ChannelCloseConfirm(sdk.WrapSDKContext(ctx), msg) - return sdk.WrapServiceResult(ctx, res, err) - - // IBC packet msgs get routed to the appropriate module callback - case *channeltypes.MsgRecvPacket: - res, err := k.RecvPacket(sdk.WrapSDKContext(ctx), msg) - return sdk.WrapServiceResult(ctx, res, err) - - case *channeltypes.MsgAcknowledgement: - res, err := k.Acknowledgement(sdk.WrapSDKContext(ctx), msg) - return sdk.WrapServiceResult(ctx, res, err) - - case *channeltypes.MsgTimeout: - res, err := k.Timeout(sdk.WrapSDKContext(ctx), msg) - return sdk.WrapServiceResult(ctx, res, err) - - case *channeltypes.MsgTimeoutOnClose: - res, err := k.TimeoutOnClose(sdk.WrapSDKContext(ctx), msg) - return sdk.WrapServiceResult(ctx, res, err) - - default: - return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized IBC message type: %T", msg) - } - } -} diff --git a/x/ibc/core/keeper/grpc_query.go b/x/ibc/core/keeper/grpc_query.go deleted file mode 100644 index 3db15d3c0bc7..000000000000 --- a/x/ibc/core/keeper/grpc_query.go +++ /dev/null @@ -1,129 +0,0 @@ -package keeper - -import ( - "context" - - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" -) - -// ClientState implements the IBC QueryServer interface -func (q Keeper) ClientState(c context.Context, req *clienttypes.QueryClientStateRequest) (*clienttypes.QueryClientStateResponse, error) { - return q.ClientKeeper.ClientState(c, req) -} - -// ClientStates implements the IBC QueryServer interface -func (q Keeper) ClientStates(c context.Context, req *clienttypes.QueryClientStatesRequest) (*clienttypes.QueryClientStatesResponse, error) { - return q.ClientKeeper.ClientStates(c, req) -} - -// ConsensusState implements the IBC QueryServer interface -func (q Keeper) ConsensusState(c context.Context, req *clienttypes.QueryConsensusStateRequest) (*clienttypes.QueryConsensusStateResponse, error) { - return q.ClientKeeper.ConsensusState(c, req) -} - -// ConsensusStates implements the IBC QueryServer interface -func (q Keeper) ConsensusStates(c context.Context, req *clienttypes.QueryConsensusStatesRequest) (*clienttypes.QueryConsensusStatesResponse, error) { - return q.ClientKeeper.ConsensusStates(c, req) -} - -// ClientParams implements the IBC QueryServer interface -func (q Keeper) ClientParams(c context.Context, req *clienttypes.QueryClientParamsRequest) (*clienttypes.QueryClientParamsResponse, error) { - return q.ClientKeeper.ClientParams(c, req) -} - -// UpgradedClientState implements the IBC QueryServer interface -func (q Keeper) UpgradedClientState(c context.Context, req *clienttypes.QueryUpgradedClientStateRequest) (*clienttypes.QueryUpgradedClientStateResponse, error) { - return q.ClientKeeper.UpgradedClientState(c, req) -} - -// Connection implements the IBC QueryServer interface -func (q Keeper) Connection(c context.Context, req *connectiontypes.QueryConnectionRequest) (*connectiontypes.QueryConnectionResponse, error) { - return q.ConnectionKeeper.Connection(c, req) -} - -// Connections implements the IBC QueryServer interface -func (q Keeper) Connections(c context.Context, req *connectiontypes.QueryConnectionsRequest) (*connectiontypes.QueryConnectionsResponse, error) { - return q.ConnectionKeeper.Connections(c, req) -} - -// ClientConnections implements the IBC QueryServer interface -func (q Keeper) ClientConnections(c context.Context, req *connectiontypes.QueryClientConnectionsRequest) (*connectiontypes.QueryClientConnectionsResponse, error) { - return q.ConnectionKeeper.ClientConnections(c, req) -} - -// ConnectionClientState implements the IBC QueryServer interface -func (q Keeper) ConnectionClientState(c context.Context, req *connectiontypes.QueryConnectionClientStateRequest) (*connectiontypes.QueryConnectionClientStateResponse, error) { - return q.ConnectionKeeper.ConnectionClientState(c, req) -} - -// ConnectionConsensusState implements the IBC QueryServer interface -func (q Keeper) ConnectionConsensusState(c context.Context, req *connectiontypes.QueryConnectionConsensusStateRequest) (*connectiontypes.QueryConnectionConsensusStateResponse, error) { - return q.ConnectionKeeper.ConnectionConsensusState(c, req) -} - -// Channel implements the IBC QueryServer interface -func (q Keeper) Channel(c context.Context, req *channeltypes.QueryChannelRequest) (*channeltypes.QueryChannelResponse, error) { - return q.ChannelKeeper.Channel(c, req) -} - -// Channels implements the IBC QueryServer interface -func (q Keeper) Channels(c context.Context, req *channeltypes.QueryChannelsRequest) (*channeltypes.QueryChannelsResponse, error) { - return q.ChannelKeeper.Channels(c, req) -} - -// ConnectionChannels implements the IBC QueryServer interface -func (q Keeper) ConnectionChannels(c context.Context, req *channeltypes.QueryConnectionChannelsRequest) (*channeltypes.QueryConnectionChannelsResponse, error) { - return q.ChannelKeeper.ConnectionChannels(c, req) -} - -// ChannelClientState implements the IBC QueryServer interface -func (q Keeper) ChannelClientState(c context.Context, req *channeltypes.QueryChannelClientStateRequest) (*channeltypes.QueryChannelClientStateResponse, error) { - return q.ChannelKeeper.ChannelClientState(c, req) -} - -// ChannelConsensusState implements the IBC QueryServer interface -func (q Keeper) ChannelConsensusState(c context.Context, req *channeltypes.QueryChannelConsensusStateRequest) (*channeltypes.QueryChannelConsensusStateResponse, error) { - return q.ChannelKeeper.ChannelConsensusState(c, req) -} - -// PacketCommitment implements the IBC QueryServer interface -func (q Keeper) PacketCommitment(c context.Context, req *channeltypes.QueryPacketCommitmentRequest) (*channeltypes.QueryPacketCommitmentResponse, error) { - return q.ChannelKeeper.PacketCommitment(c, req) -} - -// PacketCommitments implements the IBC QueryServer interface -func (q Keeper) PacketCommitments(c context.Context, req *channeltypes.QueryPacketCommitmentsRequest) (*channeltypes.QueryPacketCommitmentsResponse, error) { - return q.ChannelKeeper.PacketCommitments(c, req) -} - -// PacketReceipt implements the IBC QueryServer interface -func (q Keeper) PacketReceipt(c context.Context, req *channeltypes.QueryPacketReceiptRequest) (*channeltypes.QueryPacketReceiptResponse, error) { - return q.ChannelKeeper.PacketReceipt(c, req) -} - -// PacketAcknowledgement implements the IBC QueryServer interface -func (q Keeper) PacketAcknowledgement(c context.Context, req *channeltypes.QueryPacketAcknowledgementRequest) (*channeltypes.QueryPacketAcknowledgementResponse, error) { - return q.ChannelKeeper.PacketAcknowledgement(c, req) -} - -// PacketAcknowledgements implements the IBC QueryServer interface -func (q Keeper) PacketAcknowledgements(c context.Context, req *channeltypes.QueryPacketAcknowledgementsRequest) (*channeltypes.QueryPacketAcknowledgementsResponse, error) { - return q.ChannelKeeper.PacketAcknowledgements(c, req) -} - -// UnreceivedPackets implements the IBC QueryServer interface -func (q Keeper) UnreceivedPackets(c context.Context, req *channeltypes.QueryUnreceivedPacketsRequest) (*channeltypes.QueryUnreceivedPacketsResponse, error) { - return q.ChannelKeeper.UnreceivedPackets(c, req) -} - -// UnreceivedAcks implements the IBC QueryServer interface -func (q Keeper) UnreceivedAcks(c context.Context, req *channeltypes.QueryUnreceivedAcksRequest) (*channeltypes.QueryUnreceivedAcksResponse, error) { - return q.ChannelKeeper.UnreceivedAcks(c, req) -} - -// NextSequenceReceive implements the IBC QueryServer interface -func (q Keeper) NextSequenceReceive(c context.Context, req *channeltypes.QueryNextSequenceReceiveRequest) (*channeltypes.QueryNextSequenceReceiveResponse, error) { - return q.ChannelKeeper.NextSequenceReceive(c, req) -} diff --git a/x/ibc/core/keeper/keeper.go b/x/ibc/core/keeper/keeper.go deleted file mode 100644 index dab06caec27d..000000000000 --- a/x/ibc/core/keeper/keeper.go +++ /dev/null @@ -1,66 +0,0 @@ -package keeper - -import ( - "github.com/cosmos/cosmos-sdk/codec" - sdk "github.com/cosmos/cosmos-sdk/types" - capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" - clientkeeper "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/keeper" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - connectionkeeper "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/keeper" - channelkeeper "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/keeper" - portkeeper "github.com/cosmos/cosmos-sdk/x/ibc/core/05-port/keeper" - porttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/05-port/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/types" - paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" -) - -var _ types.QueryServer = (*Keeper)(nil) - -// Keeper defines each ICS keeper for IBC -type Keeper struct { - // implements gRPC QueryServer interface - types.QueryServer - - cdc codec.BinaryMarshaler - - ClientKeeper clientkeeper.Keeper - ConnectionKeeper connectionkeeper.Keeper - ChannelKeeper channelkeeper.Keeper - PortKeeper portkeeper.Keeper - Router *porttypes.Router -} - -// NewKeeper creates a new ibc Keeper -func NewKeeper( - cdc codec.BinaryMarshaler, key sdk.StoreKey, paramSpace paramtypes.Subspace, - stakingKeeper clienttypes.StakingKeeper, upgradeKeeper clienttypes.UpgradeKeeper, - scopedKeeper capabilitykeeper.ScopedKeeper, -) *Keeper { - clientKeeper := clientkeeper.NewKeeper(cdc, key, paramSpace, stakingKeeper, upgradeKeeper) - connectionKeeper := connectionkeeper.NewKeeper(cdc, key, clientKeeper) - portKeeper := portkeeper.NewKeeper(scopedKeeper) - channelKeeper := channelkeeper.NewKeeper(cdc, key, clientKeeper, connectionKeeper, portKeeper, scopedKeeper) - - return &Keeper{ - cdc: cdc, - ClientKeeper: clientKeeper, - ConnectionKeeper: connectionKeeper, - ChannelKeeper: channelKeeper, - PortKeeper: portKeeper, - } -} - -// Codec returns the IBC module codec. -func (k Keeper) Codec() codec.BinaryMarshaler { - return k.cdc -} - -// SetRouter sets the Router in IBC Keeper and seals it. The method panics if -// there is an existing router that's already sealed. -func (k *Keeper) SetRouter(rtr *porttypes.Router) { - if k.Router != nil && k.Router.Sealed() { - panic("cannot reset a sealed router") - } - k.Router = rtr - k.Router.Seal() -} diff --git a/x/ibc/core/keeper/msg_server.go b/x/ibc/core/keeper/msg_server.go deleted file mode 100644 index dcddcaed16d4..000000000000 --- a/x/ibc/core/keeper/msg_server.go +++ /dev/null @@ -1,616 +0,0 @@ -package keeper - -import ( - "context" - - "github.com/armon/go-metrics" - - "github.com/cosmos/cosmos-sdk/telemetry" - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - channel "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - porttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/05-port/types" -) - -var _ clienttypes.MsgServer = Keeper{} -var _ connectiontypes.MsgServer = Keeper{} -var _ channeltypes.MsgServer = Keeper{} - -// CreateClient defines a rpc handler method for MsgCreateClient. -func (k Keeper) CreateClient(goCtx context.Context, msg *clienttypes.MsgCreateClient) (*clienttypes.MsgCreateClientResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - clientState, err := clienttypes.UnpackClientState(msg.ClientState) - if err != nil { - return nil, err - } - - consensusState, err := clienttypes.UnpackConsensusState(msg.ConsensusState) - if err != nil { - return nil, err - } - - clientID, err := k.ClientKeeper.CreateClient(ctx, clientState, consensusState) - if err != nil { - return nil, err - } - - ctx.EventManager().EmitEvents(sdk.Events{ - sdk.NewEvent( - clienttypes.EventTypeCreateClient, - sdk.NewAttribute(clienttypes.AttributeKeyClientID, clientID), - sdk.NewAttribute(clienttypes.AttributeKeyClientType, clientState.ClientType()), - sdk.NewAttribute(clienttypes.AttributeKeyConsensusHeight, clientState.GetLatestHeight().String()), - ), - sdk.NewEvent( - sdk.EventTypeMessage, - sdk.NewAttribute(sdk.AttributeKeyModule, clienttypes.AttributeValueCategory), - ), - }) - - return &clienttypes.MsgCreateClientResponse{}, nil -} - -// UpdateClient defines a rpc handler method for MsgUpdateClient. -func (k Keeper) UpdateClient(goCtx context.Context, msg *clienttypes.MsgUpdateClient) (*clienttypes.MsgUpdateClientResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - header, err := clienttypes.UnpackHeader(msg.Header) - if err != nil { - return nil, err - } - - if err = k.ClientKeeper.UpdateClient(ctx, msg.ClientId, header); err != nil { - return nil, err - } - - ctx.EventManager().EmitEvent( - sdk.NewEvent( - sdk.EventTypeMessage, - sdk.NewAttribute(sdk.AttributeKeyModule, clienttypes.AttributeValueCategory), - ), - ) - - return &clienttypes.MsgUpdateClientResponse{}, nil -} - -// UpgradeClient defines a rpc handler method for MsgUpgradeClient. -func (k Keeper) UpgradeClient(goCtx context.Context, msg *clienttypes.MsgUpgradeClient) (*clienttypes.MsgUpgradeClientResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - upgradedClient, err := clienttypes.UnpackClientState(msg.ClientState) - if err != nil { - return nil, err - } - upgradedConsState, err := clienttypes.UnpackConsensusState(msg.ConsensusState) - if err != nil { - return nil, err - } - - if err = k.ClientKeeper.UpgradeClient(ctx, msg.ClientId, upgradedClient, upgradedConsState, - msg.ProofUpgradeClient, msg.ProofUpgradeConsensusState); err != nil { - return nil, err - } - - ctx.EventManager().EmitEvent( - sdk.NewEvent( - sdk.EventTypeMessage, - sdk.NewAttribute(sdk.AttributeKeyModule, clienttypes.AttributeValueCategory), - ), - ) - - return &clienttypes.MsgUpgradeClientResponse{}, nil -} - -// SubmitMisbehaviour defines a rpc handler method for MsgSubmitMisbehaviour. -func (k Keeper) SubmitMisbehaviour(goCtx context.Context, msg *clienttypes.MsgSubmitMisbehaviour) (*clienttypes.MsgSubmitMisbehaviourResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - misbehaviour, err := clienttypes.UnpackMisbehaviour(msg.Misbehaviour) - if err != nil { - return nil, err - } - - if err := k.ClientKeeper.CheckMisbehaviourAndUpdateState(ctx, misbehaviour); err != nil { - return nil, sdkerrors.Wrap(err, "failed to process misbehaviour for IBC client") - } - - ctx.EventManager().EmitEvent( - sdk.NewEvent( - clienttypes.EventTypeSubmitMisbehaviour, - sdk.NewAttribute(clienttypes.AttributeKeyClientID, msg.ClientId), - sdk.NewAttribute(clienttypes.AttributeKeyClientType, misbehaviour.ClientType()), - sdk.NewAttribute(clienttypes.AttributeKeyConsensusHeight, misbehaviour.GetHeight().String()), - ), - ) - - return &clienttypes.MsgSubmitMisbehaviourResponse{}, nil -} - -// ConnectionOpenInit defines a rpc handler method for MsgConnectionOpenInit. -func (k Keeper) ConnectionOpenInit(goCtx context.Context, msg *connectiontypes.MsgConnectionOpenInit) (*connectiontypes.MsgConnectionOpenInitResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - connectionID, err := k.ConnectionKeeper.ConnOpenInit(ctx, msg.ClientId, msg.Counterparty, msg.Version, msg.DelayPeriod) - if err != nil { - return nil, sdkerrors.Wrap(err, "connection handshake open init failed") - } - - ctx.EventManager().EmitEvents(sdk.Events{ - sdk.NewEvent( - connectiontypes.EventTypeConnectionOpenInit, - sdk.NewAttribute(connectiontypes.AttributeKeyConnectionID, connectionID), - sdk.NewAttribute(connectiontypes.AttributeKeyClientID, msg.ClientId), - sdk.NewAttribute(connectiontypes.AttributeKeyCounterpartyClientID, msg.Counterparty.ClientId), - sdk.NewAttribute(connectiontypes.AttributeKeyCounterpartyConnectionID, msg.Counterparty.ConnectionId), - ), - sdk.NewEvent( - sdk.EventTypeMessage, - sdk.NewAttribute(sdk.AttributeKeyModule, connectiontypes.AttributeValueCategory), - ), - }) - - return &connectiontypes.MsgConnectionOpenInitResponse{}, nil -} - -// ConnectionOpenTry defines a rpc handler method for MsgConnectionOpenTry. -func (k Keeper) ConnectionOpenTry(goCtx context.Context, msg *connectiontypes.MsgConnectionOpenTry) (*connectiontypes.MsgConnectionOpenTryResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - targetClient, err := clienttypes.UnpackClientState(msg.ClientState) - if err != nil { - return nil, sdkerrors.Wrapf(err, "client in msg is not exported.ClientState. invalid client: %v.", targetClient) - } - - connectionID, err := k.ConnectionKeeper.ConnOpenTry( - ctx, msg.PreviousConnectionId, msg.Counterparty, msg.DelayPeriod, msg.ClientId, targetClient, - connectiontypes.ProtoVersionsToExported(msg.CounterpartyVersions), msg.ProofInit, msg.ProofClient, msg.ProofConsensus, - msg.ProofHeight, msg.ConsensusHeight, - ) - if err != nil { - return nil, sdkerrors.Wrap(err, "connection handshake open try failed") - } - - ctx.EventManager().EmitEvents(sdk.Events{ - sdk.NewEvent( - connectiontypes.EventTypeConnectionOpenTry, - sdk.NewAttribute(connectiontypes.AttributeKeyConnectionID, connectionID), - sdk.NewAttribute(connectiontypes.AttributeKeyClientID, msg.ClientId), - sdk.NewAttribute(connectiontypes.AttributeKeyCounterpartyClientID, msg.Counterparty.ClientId), - sdk.NewAttribute(connectiontypes.AttributeKeyCounterpartyConnectionID, msg.Counterparty.ConnectionId), - ), - sdk.NewEvent( - sdk.EventTypeMessage, - sdk.NewAttribute(sdk.AttributeKeyModule, connectiontypes.AttributeValueCategory), - ), - }) - - return &connectiontypes.MsgConnectionOpenTryResponse{}, nil -} - -// ConnectionOpenAck defines a rpc handler method for MsgConnectionOpenAck. -func (k Keeper) ConnectionOpenAck(goCtx context.Context, msg *connectiontypes.MsgConnectionOpenAck) (*connectiontypes.MsgConnectionOpenAckResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - targetClient, err := clienttypes.UnpackClientState(msg.ClientState) - if err != nil { - return nil, sdkerrors.Wrapf(err, "client in msg is not exported.ClientState. invalid client: %v", targetClient) - } - - if err := k.ConnectionKeeper.ConnOpenAck( - ctx, msg.ConnectionId, targetClient, msg.Version, msg.CounterpartyConnectionId, - msg.ProofTry, msg.ProofClient, msg.ProofConsensus, - msg.ProofHeight, msg.ConsensusHeight, - ); err != nil { - return nil, sdkerrors.Wrap(err, "connection handshake open ack failed") - } - - connectionEnd, _ := k.ConnectionKeeper.GetConnection(ctx, msg.ConnectionId) - - ctx.EventManager().EmitEvents(sdk.Events{ - sdk.NewEvent( - connectiontypes.EventTypeConnectionOpenAck, - sdk.NewAttribute(connectiontypes.AttributeKeyConnectionID, msg.ConnectionId), - sdk.NewAttribute(connectiontypes.AttributeKeyClientID, connectionEnd.ClientId), - sdk.NewAttribute(connectiontypes.AttributeKeyCounterpartyClientID, connectionEnd.Counterparty.ClientId), - sdk.NewAttribute(connectiontypes.AttributeKeyCounterpartyConnectionID, connectionEnd.Counterparty.ConnectionId), - ), - sdk.NewEvent( - sdk.EventTypeMessage, - sdk.NewAttribute(sdk.AttributeKeyModule, connectiontypes.AttributeValueCategory), - ), - }) - - return &connectiontypes.MsgConnectionOpenAckResponse{}, nil -} - -// ConnectionOpenConfirm defines a rpc handler method for MsgConnectionOpenConfirm. -func (k Keeper) ConnectionOpenConfirm(goCtx context.Context, msg *connectiontypes.MsgConnectionOpenConfirm) (*connectiontypes.MsgConnectionOpenConfirmResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - if err := k.ConnectionKeeper.ConnOpenConfirm( - ctx, msg.ConnectionId, msg.ProofAck, msg.ProofHeight, - ); err != nil { - return nil, sdkerrors.Wrap(err, "connection handshake open confirm failed") - } - - connectionEnd, _ := k.ConnectionKeeper.GetConnection(ctx, msg.ConnectionId) - - ctx.EventManager().EmitEvents(sdk.Events{ - sdk.NewEvent( - connectiontypes.EventTypeConnectionOpenConfirm, - sdk.NewAttribute(connectiontypes.AttributeKeyConnectionID, msg.ConnectionId), - sdk.NewAttribute(connectiontypes.AttributeKeyClientID, connectionEnd.ClientId), - sdk.NewAttribute(connectiontypes.AttributeKeyCounterpartyClientID, connectionEnd.Counterparty.ClientId), - sdk.NewAttribute(connectiontypes.AttributeKeyCounterpartyConnectionID, connectionEnd.Counterparty.ConnectionId), - ), - sdk.NewEvent( - sdk.EventTypeMessage, - sdk.NewAttribute(sdk.AttributeKeyModule, connectiontypes.AttributeValueCategory), - ), - }) - - return &connectiontypes.MsgConnectionOpenConfirmResponse{}, nil -} - -// ChannelOpenInit defines a rpc handler method for MsgChannelOpenInit. -func (k Keeper) ChannelOpenInit(goCtx context.Context, msg *channeltypes.MsgChannelOpenInit) (*channeltypes.MsgChannelOpenInitResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - // Lookup module by port capability - module, portCap, err := k.PortKeeper.LookupModuleByPort(ctx, msg.PortId) - if err != nil { - return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id") - } - - _, channelID, cap, err := channel.HandleMsgChannelOpenInit(ctx, k.ChannelKeeper, portCap, msg) - if err != nil { - return nil, err - } - - // Retrieve callbacks from router - cbs, ok := k.Router.GetRoute(module) - if !ok { - return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module) - } - - if err = cbs.OnChanOpenInit(ctx, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.PortId, channelID, cap, msg.Channel.Counterparty, msg.Channel.Version); err != nil { - return nil, sdkerrors.Wrap(err, "channel open init callback failed") - } - - return &channeltypes.MsgChannelOpenInitResponse{}, nil -} - -// ChannelOpenTry defines a rpc handler method for MsgChannelOpenTry. -func (k Keeper) ChannelOpenTry(goCtx context.Context, msg *channeltypes.MsgChannelOpenTry) (*channeltypes.MsgChannelOpenTryResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - // Lookup module by port capability - module, portCap, err := k.PortKeeper.LookupModuleByPort(ctx, msg.PortId) - if err != nil { - return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id") - } - - _, channelID, cap, err := channel.HandleMsgChannelOpenTry(ctx, k.ChannelKeeper, portCap, msg) - if err != nil { - return nil, err - } - - // Retrieve callbacks from router - cbs, ok := k.Router.GetRoute(module) - if !ok { - return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module) - } - - if err = cbs.OnChanOpenTry(ctx, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.PortId, channelID, cap, msg.Channel.Counterparty, msg.Channel.Version, msg.CounterpartyVersion); err != nil { - return nil, sdkerrors.Wrap(err, "channel open try callback failed") - } - - return &channeltypes.MsgChannelOpenTryResponse{}, nil -} - -// ChannelOpenAck defines a rpc handler method for MsgChannelOpenAck. -func (k Keeper) ChannelOpenAck(goCtx context.Context, msg *channeltypes.MsgChannelOpenAck) (*channeltypes.MsgChannelOpenAckResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - // Lookup module by channel capability - module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.PortId, msg.ChannelId) - if err != nil { - return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id") - } - - // Retrieve callbacks from router - cbs, ok := k.Router.GetRoute(module) - if !ok { - return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module) - } - - _, 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 -} - -// ChannelOpenConfirm defines a rpc handler method for MsgChannelOpenConfirm. -func (k Keeper) ChannelOpenConfirm(goCtx context.Context, msg *channeltypes.MsgChannelOpenConfirm) (*channeltypes.MsgChannelOpenConfirmResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - // Lookup module by channel capability - module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.PortId, msg.ChannelId) - if err != nil { - return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id") - } - - // Retrieve callbacks from router - cbs, ok := k.Router.GetRoute(module) - if !ok { - return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module) - } - - _, 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 -} - -// ChannelCloseInit defines a rpc handler method for MsgChannelCloseInit. -func (k Keeper) ChannelCloseInit(goCtx context.Context, msg *channeltypes.MsgChannelCloseInit) (*channeltypes.MsgChannelCloseInitResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - // Lookup module by channel capability - module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.PortId, msg.ChannelId) - if err != nil { - return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id") - } - - // Retrieve callbacks from router - cbs, ok := k.Router.GetRoute(module) - if !ok { - return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module) - } - - if err = cbs.OnChanCloseInit(ctx, msg.PortId, msg.ChannelId); err != nil { - return nil, sdkerrors.Wrap(err, "channel close init callback failed") - } - - _, err = channel.HandleMsgChannelCloseInit(ctx, k.ChannelKeeper, cap, msg) - if err != nil { - return nil, err - } - - return &channeltypes.MsgChannelCloseInitResponse{}, nil -} - -// ChannelCloseConfirm defines a rpc handler method for MsgChannelCloseConfirm. -func (k Keeper) ChannelCloseConfirm(goCtx context.Context, msg *channeltypes.MsgChannelCloseConfirm) (*channeltypes.MsgChannelCloseConfirmResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - // Lookup module by channel capability - module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.PortId, msg.ChannelId) - if err != nil { - return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id") - } - - // Retrieve callbacks from router - cbs, ok := k.Router.GetRoute(module) - if !ok { - return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module) - } - - if err = cbs.OnChanCloseConfirm(ctx, msg.PortId, msg.ChannelId); err != nil { - return nil, sdkerrors.Wrap(err, "channel close confirm callback failed") - } - - _, err = channel.HandleMsgChannelCloseConfirm(ctx, k.ChannelKeeper, cap, msg) - if err != nil { - return nil, err - } - - return &channeltypes.MsgChannelCloseConfirmResponse{}, nil -} - -// RecvPacket defines a rpc handler method for MsgRecvPacket. -func (k Keeper) RecvPacket(goCtx context.Context, msg *channeltypes.MsgRecvPacket) (*channeltypes.MsgRecvPacketResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - // Lookup module by channel capability - module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.Packet.DestinationPort, msg.Packet.DestinationChannel) - if err != nil { - return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id") - } - - // Retrieve callbacks from router - cbs, ok := k.Router.GetRoute(module) - if !ok { - return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module) - } - - // Perform TAO verification - if err := k.ChannelKeeper.RecvPacket(ctx, cap, msg.Packet, msg.ProofCommitment, msg.ProofHeight); err != nil { - return nil, sdkerrors.Wrap(err, "receive packet verification failed") - } - - // Perform application logic callback - _, ack, err := cbs.OnRecvPacket(ctx, msg.Packet) - if err != nil { - return nil, sdkerrors.Wrap(err, "receive packet callback failed") - } - - // Set packet acknowledgement only if the acknowledgement is not nil. - // NOTE: IBC applications modules may call the WriteAcknowledgement asynchronously if the - // acknowledgement is nil. - if ack != nil { - if err := k.ChannelKeeper.WriteAcknowledgement(ctx, cap, msg.Packet, ack); err != nil { - return nil, err - } - } - - defer func() { - telemetry.IncrCounterWithLabels( - []string{"tx", "msg", "ibc", msg.Type()}, - 1, - []metrics.Label{ - telemetry.NewLabel("source-port", msg.Packet.SourcePort), - telemetry.NewLabel("source-channel", msg.Packet.SourceChannel), - telemetry.NewLabel("destination-port", msg.Packet.DestinationPort), - telemetry.NewLabel("destination-channel", msg.Packet.DestinationChannel), - }, - ) - }() - - return &channeltypes.MsgRecvPacketResponse{}, nil -} - -// Timeout defines a rpc handler method for MsgTimeout. -func (k Keeper) Timeout(goCtx context.Context, msg *channeltypes.MsgTimeout) (*channeltypes.MsgTimeoutResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - // Lookup module by channel capability - module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.Packet.SourcePort, msg.Packet.SourceChannel) - if err != nil { - return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id") - } - - // Retrieve callbacks from router - cbs, ok := k.Router.GetRoute(module) - if !ok { - return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module) - } - - // Perform TAO verification - if err := k.ChannelKeeper.TimeoutPacket(ctx, msg.Packet, msg.ProofUnreceived, msg.ProofHeight, msg.NextSequenceRecv); err != nil { - return nil, sdkerrors.Wrap(err, "timeout packet verification failed") - } - - // Perform application logic callback - _, err = cbs.OnTimeoutPacket(ctx, msg.Packet) - if err != nil { - return nil, sdkerrors.Wrap(err, "timeout packet callback failed") - } - - // Delete packet commitment - if err = k.ChannelKeeper.TimeoutExecuted(ctx, cap, msg.Packet); err != nil { - return nil, err - } - - defer func() { - telemetry.IncrCounterWithLabels( - []string{"ibc", "timeout", "packet"}, - 1, - []metrics.Label{ - telemetry.NewLabel("source-port", msg.Packet.SourcePort), - telemetry.NewLabel("source-channel", msg.Packet.SourceChannel), - telemetry.NewLabel("destination-port", msg.Packet.DestinationPort), - telemetry.NewLabel("destination-channel", msg.Packet.DestinationChannel), - telemetry.NewLabel("timeout-type", "height"), - }, - ) - }() - - return &channeltypes.MsgTimeoutResponse{}, nil -} - -// TimeoutOnClose defines a rpc handler method for MsgTimeoutOnClose. -func (k Keeper) TimeoutOnClose(goCtx context.Context, msg *channeltypes.MsgTimeoutOnClose) (*channeltypes.MsgTimeoutOnCloseResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - // Lookup module by channel capability - module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.Packet.SourcePort, msg.Packet.SourceChannel) - if err != nil { - return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id") - } - - // Retrieve callbacks from router - cbs, ok := k.Router.GetRoute(module) - if !ok { - return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module) - } - - // Perform TAO verification - if err := k.ChannelKeeper.TimeoutOnClose(ctx, cap, msg.Packet, msg.ProofUnreceived, msg.ProofClose, msg.ProofHeight, msg.NextSequenceRecv); err != nil { - return nil, sdkerrors.Wrap(err, "timeout on close packet verification failed") - } - - // Perform application logic callback - // NOTE: MsgTimeout and MsgTimeoutOnClose use the same "OnTimeoutPacket" - // application logic callback. - _, err = cbs.OnTimeoutPacket(ctx, msg.Packet) - if err != nil { - return nil, sdkerrors.Wrap(err, "timeout packet callback failed") - } - - // Delete packet commitment - if err = k.ChannelKeeper.TimeoutExecuted(ctx, cap, msg.Packet); err != nil { - return nil, err - } - - defer func() { - telemetry.IncrCounterWithLabels( - []string{"ibc", "timeout", "packet"}, - 1, - []metrics.Label{ - telemetry.NewLabel("source-port", msg.Packet.SourcePort), - telemetry.NewLabel("source-channel", msg.Packet.SourceChannel), - telemetry.NewLabel("destination-port", msg.Packet.DestinationPort), - telemetry.NewLabel("destination-channel", msg.Packet.DestinationChannel), - telemetry.NewLabel("timeout-type", "channel-closed"), - }, - ) - }() - - return &channeltypes.MsgTimeoutOnCloseResponse{}, nil -} - -// Acknowledgement defines a rpc handler method for MsgAcknowledgement. -func (k Keeper) Acknowledgement(goCtx context.Context, msg *channeltypes.MsgAcknowledgement) (*channeltypes.MsgAcknowledgementResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - // Lookup module by channel capability - module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.Packet.SourcePort, msg.Packet.SourceChannel) - if err != nil { - return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id") - } - - // Retrieve callbacks from router - cbs, ok := k.Router.GetRoute(module) - if !ok { - return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module) - } - - // Perform TAO verification - if err := k.ChannelKeeper.AcknowledgePacket(ctx, cap, msg.Packet, msg.Acknowledgement, msg.ProofAcked, msg.ProofHeight); err != nil { - return nil, sdkerrors.Wrap(err, "acknowledge packet verification failed") - } - - // Perform application logic callback - _, err = cbs.OnAcknowledgementPacket(ctx, msg.Packet, msg.Acknowledgement) - if err != nil { - return nil, sdkerrors.Wrap(err, "acknowledge packet callback failed") - } - - defer func() { - telemetry.IncrCounterWithLabels( - []string{"tx", "msg", "ibc", msg.Type()}, - 1, - []metrics.Label{ - telemetry.NewLabel("source-port", msg.Packet.SourcePort), - telemetry.NewLabel("source-channel", msg.Packet.SourceChannel), - telemetry.NewLabel("destination-port", msg.Packet.DestinationPort), - telemetry.NewLabel("destination-channel", msg.Packet.DestinationChannel), - }, - ) - }() - - return &channeltypes.MsgAcknowledgementResponse{}, nil -} diff --git a/x/ibc/core/keeper/msg_server_test.go b/x/ibc/core/keeper/msg_server_test.go deleted file mode 100644 index 1c4b60010f7a..000000000000 --- a/x/ibc/core/keeper/msg_server_test.go +++ /dev/null @@ -1,722 +0,0 @@ -package keeper_test - -import ( - "testing" - - "github.com/stretchr/testify/suite" - - sdk "github.com/cosmos/cosmos-sdk/types" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - "github.com/cosmos/cosmos-sdk/x/ibc/core/keeper" - ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" - ibcmock "github.com/cosmos/cosmos-sdk/x/ibc/testing/mock" - upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" -) - -const height = 10 - -var ( - timeoutHeight = clienttypes.NewHeight(0, 10000) - maxSequence = uint64(10) -) - -type KeeperTestSuite struct { - suite.Suite - - coordinator *ibctesting.Coordinator - - chainA *ibctesting.TestChain - chainB *ibctesting.TestChain -} - -// SetupTest creates a coordinator with 2 test chains. -func (suite *KeeperTestSuite) SetupTest() { - suite.coordinator = ibctesting.NewCoordinator(suite.T(), 2) - - suite.chainA = suite.coordinator.GetChain(ibctesting.GetChainID(0)) - suite.chainB = suite.coordinator.GetChain(ibctesting.GetChainID(1)) - // commit some blocks so that QueryProof returns valid proof (cannot return valid query if height <= 1) - suite.coordinator.CommitNBlocks(suite.chainA, 2) - suite.coordinator.CommitNBlocks(suite.chainB, 2) -} - -func TestIBCTestSuite(t *testing.T) { - suite.Run(t, new(KeeperTestSuite)) -} - -// tests the IBC handler receiving a packet on ordered and unordered channels. -// It verifies that the storing of an acknowledgement on success occurs. It -// tests high level properties like ordering and basic sanity checks. More -// rigorous testing of 'RecvPacket' can be found in the -// 04-channel/keeper/packet_test.go. -func (suite *KeeperTestSuite) TestHandleRecvPacket() { - var ( - packet channeltypes.Packet - ) - - testCases := []struct { - name string - malleate func() - expPass bool - }{ - {"success: ORDERED", func() { - _, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.ORDERED) - packet = channeltypes.NewPacket(ibctesting.MockCommitment, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0) - - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - }, true}, - {"success: UNORDERED", func() { - _, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.UNORDERED) - packet = channeltypes.NewPacket(ibctesting.MockCommitment, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0) - - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - }, true}, - {"success: UNORDERED out of order packet", func() { - // setup uses an UNORDERED channel - _, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.UNORDERED) - - // attempts to receive packet with sequence 10 without receiving packet with sequence 1 - for i := uint64(1); i < 10; i++ { - packet = channeltypes.NewPacket(ibctesting.MockCommitment, i, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0) - - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - } - }, true}, - {"failure: ORDERED out of order packet", func() { - _, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.ORDERED) - - // attempts to receive packet with sequence 10 without receiving packet with sequence 1 - for i := uint64(1); i < 10; i++ { - packet = channeltypes.NewPacket(ibctesting.MockCommitment, i, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0) - - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - } - }, false}, - {"channel does not exist", func() { - // any non-nil value of packet is valid - suite.Require().NotNil(packet) - }, false}, - {"packet not sent", func() { - _, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.UNORDERED) - packet = channeltypes.NewPacket(ibctesting.MockCommitment, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0) - }, false}, - {"ORDERED: packet already received (replay)", func() { - clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.ORDERED) - packet = channeltypes.NewPacket(ibctesting.MockCommitment, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0) - - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - - err = suite.coordinator.RecvPacket(suite.chainA, suite.chainB, clientA, packet) - suite.Require().NoError(err) - }, false}, - {"UNORDERED: packet already received (replay)", func() { - clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.UNORDERED) - - packet = channeltypes.NewPacket(ibctesting.MockCommitment, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0) - - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - - err = suite.coordinator.RecvPacket(suite.chainA, suite.chainB, clientA, packet) - suite.Require().NoError(err) - }, false}, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - suite.SetupTest() // reset - - tc.malleate() - - // get proof of packet commitment from chainA - packetKey := host.PacketCommitmentKey(packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) - proof, proofHeight := suite.chainA.QueryProof(packetKey) - - msg := channeltypes.NewMsgRecvPacket(packet, proof, proofHeight, suite.chainB.SenderAccount.GetAddress()) - - // ante-handle RecvPacket - _, err := keeper.Keeper.RecvPacket(*suite.chainB.App.IBCKeeper, sdk.WrapSDKContext(suite.chainB.GetContext()), msg) - - if tc.expPass { - suite.Require().NoError(err) - - // replay should fail since state changes occur - _, err := keeper.Keeper.RecvPacket(*suite.chainB.App.IBCKeeper, sdk.WrapSDKContext(suite.chainB.GetContext()), msg) - suite.Require().Error(err) - - // verify ack was written - ack, found := suite.chainB.App.IBCKeeper.ChannelKeeper.GetPacketAcknowledgement(suite.chainB.GetContext(), packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - suite.Require().NotNil(ack) - suite.Require().True(found) - } else { - suite.Require().Error(err) - } - }) - } -} - -// tests the IBC handler acknowledgement of a packet on ordered and unordered -// channels. It verifies that the deletion of packet commitments from state -// occurs. It test high level properties like ordering and basic sanity -// checks. More rigorous testing of 'AcknowledgePacket' -// can be found in the 04-channel/keeper/packet_test.go. -func (suite *KeeperTestSuite) TestHandleAcknowledgePacket() { - var ( - packet channeltypes.Packet - ) - - testCases := []struct { - name string - malleate func() - expPass bool - }{ - {"success: ORDERED", func() { - clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.ORDERED) - packet = channeltypes.NewPacket(ibctesting.MockCommitment, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0) - - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - - err = suite.coordinator.RecvPacket(suite.chainA, suite.chainB, clientA, packet) - suite.Require().NoError(err) - }, true}, - {"success: UNORDERED", func() { - clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.UNORDERED) - packet = channeltypes.NewPacket(ibctesting.MockCommitment, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0) - - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - - err = suite.coordinator.RecvPacket(suite.chainA, suite.chainB, clientA, packet) - suite.Require().NoError(err) - }, true}, - {"success: UNORDERED acknowledge out of order packet", func() { - // setup uses an UNORDERED channel - clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.UNORDERED) - - // attempts to acknowledge ack with sequence 10 without acknowledging ack with sequence 1 (removing packet commitment) - for i := uint64(1); i < 10; i++ { - packet = channeltypes.NewPacket(ibctesting.MockCommitment, i, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0) - - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - - err = suite.coordinator.RecvPacket(suite.chainA, suite.chainB, clientA, packet) - suite.Require().NoError(err) - } - }, true}, - {"failure: ORDERED acknowledge out of order packet", func() { - clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.ORDERED) - - // attempts to acknowledge ack with sequence 10 without acknowledging ack with sequence 1 (removing packet commitment - for i := uint64(1); i < 10; i++ { - packet = channeltypes.NewPacket(ibctesting.MockCommitment, i, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0) - - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - - err = suite.coordinator.RecvPacket(suite.chainA, suite.chainB, clientA, packet) - suite.Require().NoError(err) - } - }, false}, - {"channel does not exist", func() { - // any non-nil value of packet is valid - suite.Require().NotNil(packet) - }, false}, - {"packet not received", func() { - _, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.UNORDERED) - packet = channeltypes.NewPacket(ibctesting.MockCommitment, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0) - - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - }, false}, - {"ORDERED: packet already acknowledged (replay)", func() { - clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.ORDERED) - packet = channeltypes.NewPacket(ibctesting.MockCommitment, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0) - - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - - err = suite.coordinator.RecvPacket(suite.chainA, suite.chainB, clientA, packet) - suite.Require().NoError(err) - - err = suite.coordinator.AcknowledgePacket(suite.chainA, suite.chainB, clientB, packet, ibctesting.TestHash) - suite.Require().NoError(err) - }, false}, - {"UNORDERED: packet already acknowledged (replay)", func() { - clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.UNORDERED) - - packet = channeltypes.NewPacket(ibctesting.MockCommitment, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0) - - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - - err = suite.coordinator.RecvPacket(suite.chainA, suite.chainB, clientA, packet) - suite.Require().NoError(err) - - err = suite.coordinator.AcknowledgePacket(suite.chainA, suite.chainB, clientB, packet, ibctesting.TestHash) - suite.Require().NoError(err) - }, false}, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - suite.SetupTest() // reset - ibctesting.TestHash = ibctesting.MockAcknowledgement - - tc.malleate() - - packetKey := host.PacketAcknowledgementKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - proof, proofHeight := suite.chainB.QueryProof(packetKey) - - msg := channeltypes.NewMsgAcknowledgement(packet, ibcmock.MockAcknowledgement, proof, proofHeight, suite.chainA.SenderAccount.GetAddress()) - - _, err := keeper.Keeper.Acknowledgement(*suite.chainA.App.IBCKeeper, sdk.WrapSDKContext(suite.chainA.GetContext()), msg) - - if tc.expPass { - suite.Require().NoError(err) - - // replay should an error - _, err := keeper.Keeper.Acknowledgement(*suite.chainA.App.IBCKeeper, sdk.WrapSDKContext(suite.chainA.GetContext()), msg) - suite.Require().Error(err) - - // verify packet commitment was deleted on source chain - has := suite.chainA.App.IBCKeeper.ChannelKeeper.HasPacketCommitment(suite.chainA.GetContext(), packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) - suite.Require().False(has) - - } else { - suite.Require().Error(err) - } - }) - } -} - -// tests the IBC handler timing out a packet on ordered and unordered channels. -// It verifies that the deletion of a packet commitment occurs. It tests -// high level properties like ordering and basic sanity checks. More -// rigorous testing of 'TimeoutPacket' and 'TimeoutExecuted' can be found in -// the 04-channel/keeper/timeout_test.go. -func (suite *KeeperTestSuite) TestHandleTimeoutPacket() { - var ( - packet channeltypes.Packet - packetKey []byte - ) - - testCases := []struct { - name string - malleate func() - expPass bool - }{ - {"success: ORDERED", func() { - clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.ORDERED) - packet = channeltypes.NewPacket(ibctesting.MockCommitment, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, clienttypes.GetSelfHeight(suite.chainB.GetContext()), uint64(suite.chainB.GetContext().BlockTime().UnixNano())) - - // create packet commitment - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - - // need to update chainA client to prove missing ack - suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - - packetKey = host.NextSequenceRecvKey(packet.GetDestPort(), packet.GetDestChannel()) - }, true}, - {"success: UNORDERED", func() { - clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.UNORDERED) - packet = channeltypes.NewPacket(ibctesting.MockCommitment, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, clienttypes.GetSelfHeight(suite.chainB.GetContext()), uint64(suite.chainB.GetContext().BlockTime().UnixNano())) - - // create packet commitment - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - - // need to update chainA client to prove missing ack - suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - - packetKey = host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - }, true}, - {"success: UNORDERED timeout out of order packet", func() { - // setup uses an UNORDERED channel - clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.UNORDERED) - - // attempts to timeout the last packet sent without timing out the first packet - // packet sequences begin at 1 - for i := uint64(1); i < maxSequence; i++ { - packet = channeltypes.NewPacket(ibctesting.MockCommitment, i, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, clienttypes.GetSelfHeight(suite.chainB.GetContext()), 0) - - // create packet commitment - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - } - - suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - packetKey = host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - }, true}, - {"success: ORDERED timeout out of order packet", func() { - clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.ORDERED) - - // attempts to timeout the last packet sent without timing out the first packet - // packet sequences begin at 1 - for i := uint64(1); i < maxSequence; i++ { - packet = channeltypes.NewPacket(ibctesting.MockCommitment, i, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, clienttypes.GetSelfHeight(suite.chainB.GetContext()), 0) - - // create packet commitment - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - } - - suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - packetKey = host.NextSequenceRecvKey(packet.GetDestPort(), packet.GetDestChannel()) - - }, true}, - {"channel does not exist", func() { - // any non-nil value of packet is valid - suite.Require().NotNil(packet) - - packetKey = host.NextSequenceRecvKey(packet.GetDestPort(), packet.GetDestChannel()) - }, false}, - {"UNORDERED: packet not sent", func() { - _, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.UNORDERED) - packet = channeltypes.NewPacket(ibctesting.MockCommitment, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0) - packetKey = host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - }, false}, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - suite.SetupTest() // reset - - tc.malleate() - - proof, proofHeight := suite.chainB.QueryProof(packetKey) - - msg := channeltypes.NewMsgTimeout(packet, 1, proof, proofHeight, suite.chainA.SenderAccount.GetAddress()) - - _, err := keeper.Keeper.Timeout(*suite.chainA.App.IBCKeeper, sdk.WrapSDKContext(suite.chainA.GetContext()), msg) - - if tc.expPass { - suite.Require().NoError(err) - - // replay should return an error - _, err := keeper.Keeper.Timeout(*suite.chainA.App.IBCKeeper, sdk.WrapSDKContext(suite.chainA.GetContext()), msg) - suite.Require().Error(err) - - // verify packet commitment was deleted on source chain - has := suite.chainA.App.IBCKeeper.ChannelKeeper.HasPacketCommitment(suite.chainA.GetContext(), packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) - suite.Require().False(has) - - } else { - suite.Require().Error(err) - } - }) - } -} - -// tests the IBC handler timing out a packet via channel closure on ordered -// and unordered channels. It verifies that the deletion of a packet -// commitment occurs. It tests high level properties like ordering and basic -// sanity checks. More rigorous testing of 'TimeoutOnClose' and -//'TimeoutExecuted' can be found in the 04-channel/keeper/timeout_test.go. -func (suite *KeeperTestSuite) TestHandleTimeoutOnClosePacket() { - var ( - packet channeltypes.Packet - packetKey []byte - counterpartyChannel ibctesting.TestChannel - ) - - testCases := []struct { - name string - malleate func() - expPass bool - }{ - {"success: ORDERED", func() { - clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.ORDERED) - packet = channeltypes.NewPacket(ibctesting.MockCommitment, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0) - counterpartyChannel = ibctesting.TestChannel{ - PortID: channelB.PortID, - ID: channelB.ID, - CounterpartyClientID: clientA, - } - - // create packet commitment - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - - // need to update chainA client to prove missing ack - suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - - packetKey = host.NextSequenceRecvKey(packet.GetDestPort(), packet.GetDestChannel()) - - // close counterparty channel - suite.coordinator.SetChannelClosed(suite.chainB, suite.chainA, counterpartyChannel) - }, true}, - {"success: UNORDERED", func() { - clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.UNORDERED) - packet = channeltypes.NewPacket(ibctesting.MockCommitment, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0) - counterpartyChannel = ibctesting.TestChannel{ - PortID: channelB.PortID, - ID: channelB.ID, - CounterpartyClientID: clientA, - } - - // create packet commitment - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - - // need to update chainA client to prove missing ack - suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - - packetKey = host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - - // close counterparty channel - suite.coordinator.SetChannelClosed(suite.chainB, suite.chainA, counterpartyChannel) - }, true}, - {"success: UNORDERED timeout out of order packet", func() { - // setup uses an UNORDERED channel - clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.UNORDERED) - counterpartyChannel = ibctesting.TestChannel{ - PortID: channelB.PortID, - ID: channelB.ID, - CounterpartyClientID: clientA, - } - - // attempts to timeout the last packet sent without timing out the first packet - // packet sequences begin at 1 - for i := uint64(1); i < maxSequence; i++ { - packet = channeltypes.NewPacket(ibctesting.MockCommitment, i, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0) - - // create packet commitment - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - } - - suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - packetKey = host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - - // close counterparty channel - suite.coordinator.SetChannelClosed(suite.chainB, suite.chainA, counterpartyChannel) - }, true}, - {"success: ORDERED timeout out of order packet", func() { - clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.ORDERED) - counterpartyChannel = ibctesting.TestChannel{ - PortID: channelB.PortID, - ID: channelB.ID, - CounterpartyClientID: clientA, - } - - // attempts to timeout the last packet sent without timing out the first packet - // packet sequences begin at 1 - for i := uint64(1); i < maxSequence; i++ { - packet = channeltypes.NewPacket(ibctesting.MockCommitment, i, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0) - - // create packet commitment - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - } - - suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - packetKey = host.NextSequenceRecvKey(packet.GetDestPort(), packet.GetDestChannel()) - - // close counterparty channel - suite.coordinator.SetChannelClosed(suite.chainB, suite.chainA, counterpartyChannel) - }, true}, - {"channel does not exist", func() { - // any non-nil value of packet is valid - suite.Require().NotNil(packet) - - packetKey = host.NextSequenceRecvKey(packet.GetDestPort(), packet.GetDestChannel()) - }, false}, - {"UNORDERED: packet not sent", func() { - clientA, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.UNORDERED) - packet = channeltypes.NewPacket(ibctesting.MockCommitment, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0) - packetKey = host.PacketAcknowledgementKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - counterpartyChannel = ibctesting.TestChannel{ - PortID: channelB.PortID, - ID: channelB.ID, - CounterpartyClientID: clientA, - } - - // close counterparty channel - suite.coordinator.SetChannelClosed(suite.chainB, suite.chainA, counterpartyChannel) - }, false}, - {"ORDERED: channel not closed", func() { - clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.ORDERED) - packet = channeltypes.NewPacket(ibctesting.MockCommitment, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0) - counterpartyChannel = ibctesting.TestChannel{ - PortID: channelB.PortID, - ID: channelB.ID, - CounterpartyClientID: clientA, - } - - // create packet commitment - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - - // need to update chainA client to prove missing ack - suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - - packetKey = host.NextSequenceRecvKey(packet.GetDestPort(), packet.GetDestChannel()) - }, false}, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - suite.SetupTest() // reset - - tc.malleate() - - proof, proofHeight := suite.chainB.QueryProof(packetKey) - - channelKey := host.ChannelKey(counterpartyChannel.PortID, counterpartyChannel.ID) - proofClosed, _ := suite.chainB.QueryProof(channelKey) - - msg := channeltypes.NewMsgTimeoutOnClose(packet, 1, proof, proofClosed, proofHeight, suite.chainA.SenderAccount.GetAddress()) - - _, err := keeper.Keeper.TimeoutOnClose(*suite.chainA.App.IBCKeeper, sdk.WrapSDKContext(suite.chainA.GetContext()), msg) - - if tc.expPass { - suite.Require().NoError(err) - - // replay should return an error - _, err := keeper.Keeper.TimeoutOnClose(*suite.chainA.App.IBCKeeper, sdk.WrapSDKContext(suite.chainA.GetContext()), msg) - suite.Require().Error(err) - - // verify packet commitment was deleted on source chain - has := suite.chainA.App.IBCKeeper.ChannelKeeper.HasPacketCommitment(suite.chainA.GetContext(), packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) - suite.Require().False(has) - - } else { - suite.Require().Error(err) - } - }) - } -} - -func (suite *KeeperTestSuite) TestUpgradeClient() { - var ( - clientA string - upgradedClient exported.ClientState - upgradedConsState exported.ConsensusState - lastHeight exported.Height - msg *clienttypes.MsgUpgradeClient - ) - - newClientHeight := clienttypes.NewHeight(1, 1) - - cases := []struct { - name string - setup func() - expPass bool - }{ - { - name: "successful upgrade", - setup: func() { - - upgradedClient = ibctmtypes.NewClientState("newChainId", ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod+ibctesting.TrustingPeriod, ibctesting.MaxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) - // Call ZeroCustomFields on upgraded clients to clear any client-chosen parameters in test-case upgradedClient - upgradedClient = upgradedClient.ZeroCustomFields() - - upgradedConsState = &ibctmtypes.ConsensusState{ - NextValidatorsHash: []byte("nextValsHash"), - } - - // last Height is at next block - lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) - - upgradedClientBz, err := clienttypes.MarshalClientState(suite.chainA.App.AppCodec(), upgradedClient) - suite.Require().NoError(err) - upgradedConsStateBz, err := clienttypes.MarshalConsensusState(suite.chainA.App.AppCodec(), upgradedConsState) - suite.Require().NoError(err) - - // zero custom fields and store in upgrade store - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) - suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) - - // commit upgrade store changes and update clients - suite.coordinator.CommitBlock(suite.chainB) - err = suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - suite.Require().NoError(err) - - cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA) - suite.Require().True(found) - - proofUpgradeClient, _ := suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - proofUpgradedConsState, _ := suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - - msg, err = clienttypes.NewMsgUpgradeClient(clientA, upgradedClient, upgradedConsState, - proofUpgradeClient, proofUpgradedConsState, suite.chainA.SenderAccount.GetAddress()) - suite.Require().NoError(err) - }, - expPass: true, - }, - { - name: "VerifyUpgrade fails", - setup: func() { - - upgradedClient = ibctmtypes.NewClientState("newChainId", ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod+ibctesting.TrustingPeriod, ibctesting.MaxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) - // Call ZeroCustomFields on upgraded clients to clear any client-chosen parameters in test-case upgradedClient - upgradedClient = upgradedClient.ZeroCustomFields() - - upgradedConsState = &ibctmtypes.ConsensusState{ - NextValidatorsHash: []byte("nextValsHash"), - } - - // last Height is at next block - lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) - - upgradedClientBz, err := clienttypes.MarshalClientState(suite.chainA.App.AppCodec(), upgradedClient) - suite.Require().NoError(err) - upgradedConsStateBz, err := clienttypes.MarshalConsensusState(suite.chainA.App.AppCodec(), upgradedConsState) - suite.Require().NoError(err) - - // zero custom fields and store in upgrade store - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) - suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) - - // commit upgrade store changes and update clients - suite.coordinator.CommitBlock(suite.chainB) - err = suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - suite.Require().NoError(err) - - msg, err = clienttypes.NewMsgUpgradeClient(clientA, upgradedClient, upgradedConsState, nil, nil, suite.chainA.SenderAccount.GetAddress()) - suite.Require().NoError(err) - }, - expPass: false, - }, - } - - for _, tc := range cases { - tc := tc - clientA, _ = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - - tc.setup() - - _, err := keeper.Keeper.UpgradeClient(*suite.chainA.App.IBCKeeper, sdk.WrapSDKContext(suite.chainA.GetContext()), msg) - - if tc.expPass { - suite.Require().NoError(err, "upgrade handler failed on valid case: %s", tc.name) - newClient, ok := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA) - suite.Require().True(ok) - newChainSpecifiedClient := newClient.ZeroCustomFields() - suite.Require().Equal(upgradedClient, newChainSpecifiedClient) - } else { - suite.Require().Error(err, "upgrade handler passed on invalid case: %s", tc.name) - } - } -} diff --git a/x/ibc/core/module.go b/x/ibc/core/module.go deleted file mode 100644 index 9d5d4e86328c..000000000000 --- a/x/ibc/core/module.go +++ /dev/null @@ -1,198 +0,0 @@ -package ibc - -import ( - "context" - "encoding/json" - "fmt" - "math/rand" - - "github.com/gorilla/mux" - "github.com/grpc-ecosystem/grpc-gateway/runtime" - "github.com/spf13/cobra" - - abci "github.com/tendermint/tendermint/abci/types" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/module" - simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - ibcclient "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/client/cli" - "github.com/cosmos/cosmos-sdk/x/ibc/core/keeper" - "github.com/cosmos/cosmos-sdk/x/ibc/core/simulation" - "github.com/cosmos/cosmos-sdk/x/ibc/core/types" -) - -var ( - _ module.AppModule = AppModule{} - _ module.AppModuleBasic = AppModuleBasic{} - _ module.AppModuleSimulation = AppModule{} -) - -// AppModuleBasic defines the basic application module used by the ibc module. -type AppModuleBasic struct{} - -var _ module.AppModuleBasic = AppModuleBasic{} - -// Name returns the ibc module's name. -func (AppModuleBasic) Name() string { - return host.ModuleName -} - -// RegisterLegacyAminoCodec does nothing. IBC does not support amino. -func (AppModuleBasic) RegisterLegacyAminoCodec(*codec.LegacyAmino) {} - -// DefaultGenesis returns default genesis state as raw bytes for the ibc -// module. -func (AppModuleBasic) DefaultGenesis(cdc codec.JSONMarshaler) json.RawMessage { - return cdc.MustMarshalJSON(types.DefaultGenesisState()) -} - -// ValidateGenesis performs genesis state validation for the ibc module. -func (AppModuleBasic) ValidateGenesis(cdc codec.JSONMarshaler, config client.TxEncodingConfig, bz json.RawMessage) error { - var gs types.GenesisState - if err := cdc.UnmarshalJSON(bz, &gs); err != nil { - return fmt.Errorf("failed to unmarshal %s genesis state: %w", host.ModuleName, err) - } - - return gs.Validate() -} - -// RegisterRESTRoutes does nothing. IBC does not support legacy REST routes. -func (AppModuleBasic) RegisterRESTRoutes(client.Context, *mux.Router) {} - -// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the ibc module. -func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) { - clienttypes.RegisterQueryHandlerClient(context.Background(), mux, clienttypes.NewQueryClient(clientCtx)) - connectiontypes.RegisterQueryHandlerClient(context.Background(), mux, connectiontypes.NewQueryClient(clientCtx)) - channeltypes.RegisterQueryHandlerClient(context.Background(), mux, channeltypes.NewQueryClient(clientCtx)) -} - -// GetTxCmd returns the root tx command for the ibc module. -func (AppModuleBasic) GetTxCmd() *cobra.Command { - return cli.GetTxCmd() -} - -// GetQueryCmd returns no root query command for the ibc module. -func (AppModuleBasic) GetQueryCmd() *cobra.Command { - return cli.GetQueryCmd() -} - -// RegisterInterfaces registers module concrete types into protobuf Any. -func (AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) { - types.RegisterInterfaces(registry) -} - -// AppModule implements an application module for the ibc module. -type AppModule struct { - AppModuleBasic - keeper *keeper.Keeper - - // create localhost by default - createLocalhost bool -} - -// NewAppModule creates a new AppModule object -func NewAppModule(k *keeper.Keeper) AppModule { - return AppModule{ - keeper: k, - } -} - -// Name returns the ibc module's name. -func (AppModule) Name() string { - return host.ModuleName -} - -// RegisterInvariants registers the ibc module invariants. -func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) { - // TODO: -} - -// Route returns the message routing key for the ibc module. -func (am AppModule) Route() sdk.Route { - return sdk.NewRoute(host.RouterKey, NewHandler(*am.keeper)) -} - -// QuerierRoute returns the ibc module's querier route name. -func (AppModule) QuerierRoute() string { - return host.QuerierRoute -} - -// LegacyQuerierHandler returns nil. IBC does not support the legacy querier. -func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sdk.Querier { - return nil -} - -// RegisterServices registers module services. -func (am AppModule) RegisterServices(cfg module.Configurator) { - clienttypes.RegisterMsgServer(cfg.MsgServer(), am.keeper) - connectiontypes.RegisterMsgServer(cfg.MsgServer(), am.keeper) - channeltypes.RegisterMsgServer(cfg.MsgServer(), am.keeper) - types.RegisterQueryService(cfg.QueryServer(), am.keeper) -} - -// InitGenesis performs genesis initialization for the ibc 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 - err := cdc.UnmarshalJSON(bz, &gs) - if err != nil { - panic(fmt.Sprintf("failed to unmarshal %s genesis state: %s", host.ModuleName, err)) - } - InitGenesis(ctx, *am.keeper, am.createLocalhost, &gs) - return []abci.ValidatorUpdate{} -} - -// ExportGenesis returns the exported genesis state as raw bytes for the ibc -// module. -func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json.RawMessage { - 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) -} - -// EndBlock returns the end blocker for the ibc module. It returns no validator -// updates. -func (am AppModule) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) []abci.ValidatorUpdate { - return []abci.ValidatorUpdate{} -} - -// AppModuleSimulation functions - -// GenerateGenesisState creates a randomized GenState of the ibc module. -func (AppModule) GenerateGenesisState(simState *module.SimulationState) { - simulation.RandomizedGenState(simState) -} - -// ProposalContents doesn't return any content functions for governance proposals. -func (AppModule) ProposalContents(_ module.SimulationState) []simtypes.WeightedProposalContent { - return nil -} - -// RandomizedParams returns nil since IBC doesn't register parameter changes. -func (AppModule) RandomizedParams(_ *rand.Rand) []simtypes.ParamChange { - return nil -} - -// RegisterStoreDecoder registers a decoder for ibc module's types -func (am AppModule) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) { - sdr[host.StoreKey] = simulation.NewDecodeStore(*am.keeper) -} - -// WeightedOperations returns the all the ibc module operations with their respective weights. -func (am AppModule) WeightedOperations(_ module.SimulationState) []simtypes.WeightedOperation { - return nil -} diff --git a/x/ibc/core/simulation/decoder.go b/x/ibc/core/simulation/decoder.go deleted file mode 100644 index 459eebb8f078..000000000000 --- a/x/ibc/core/simulation/decoder.go +++ /dev/null @@ -1,32 +0,0 @@ -package simulation - -import ( - "fmt" - - "github.com/cosmos/cosmos-sdk/types/kv" - clientsim "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/simulation" - connectionsim "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/simulation" - channelsim "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/simulation" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/keeper" -) - -// NewDecodeStore returns a decoder function closure that unmarshals the KVPair's -// Value to the corresponding ibc type. -func NewDecodeStore(k keeper.Keeper) func(kvA, kvB kv.Pair) string { - return func(kvA, kvB kv.Pair) string { - if res, found := clientsim.NewDecodeStore(k.ClientKeeper, kvA, kvB); found { - return res - } - - if res, found := connectionsim.NewDecodeStore(k.Codec(), kvA, kvB); found { - return res - } - - if res, found := channelsim.NewDecodeStore(k.Codec(), kvA, kvB); found { - return res - } - - panic(fmt.Sprintf("invalid %s key prefix: %s", host.ModuleName, string(kvA.Key))) - } -} diff --git a/x/ibc/core/simulation/decoder_test.go b/x/ibc/core/simulation/decoder_test.go deleted file mode 100644 index 0951572743b1..000000000000 --- a/x/ibc/core/simulation/decoder_test.go +++ /dev/null @@ -1,80 +0,0 @@ -package simulation_test - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/simapp" - "github.com/cosmos/cosmos-sdk/types/kv" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/simulation" - ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" -) - -func TestDecodeStore(t *testing.T) { - app := simapp.Setup(false) - dec := simulation.NewDecodeStore(*app.IBCKeeper) - - clientID := "clientidone" - connectionID := "connectionidone" - channelID := "channelidone" - portID := "portidone" - - clientState := &ibctmtypes.ClientState{ - FrozenHeight: clienttypes.NewHeight(0, 10), - } - connection := connectiontypes.ConnectionEnd{ - ClientId: "clientidone", - Versions: []*connectiontypes.Version{connectiontypes.NewVersion("1", nil)}, - } - channel := channeltypes.Channel{ - State: channeltypes.OPEN, - Version: "1.0", - } - - kvPairs := kv.Pairs{ - Pairs: []kv.Pair{ - { - Key: host.FullClientStateKey(clientID), - Value: app.IBCKeeper.ClientKeeper.MustMarshalClientState(clientState), - }, - { - Key: host.ConnectionKey(connectionID), - Value: app.IBCKeeper.Codec().MustMarshalBinaryBare(&connection), - }, - { - Key: host.ChannelKey(portID, channelID), - Value: app.IBCKeeper.Codec().MustMarshalBinaryBare(&channel), - }, - { - Key: []byte{0x99}, - Value: []byte{0x99}, - }, - }, - } - tests := []struct { - name string - expectedLog string - }{ - {"ClientState", fmt.Sprintf("ClientState A: %v\nClientState B: %v", clientState, clientState)}, - {"ConnectionEnd", fmt.Sprintf("ConnectionEnd A: %v\nConnectionEnd B: %v", connection, connection)}, - {"Channel", fmt.Sprintf("Channel A: %v\nChannel B: %v", channel, channel)}, - {"other", ""}, - } - - for i, tt := range tests { - i, tt := i, tt - t.Run(tt.name, func(t *testing.T) { - if i == len(tests)-1 { - require.Panics(t, func() { dec(kvPairs.Pairs[i], kvPairs.Pairs[i]) }, tt.name) - } else { - require.Equal(t, tt.expectedLog, dec(kvPairs.Pairs[i], kvPairs.Pairs[i]), tt.name) - } - }) - } -} diff --git a/x/ibc/core/simulation/genesis.go b/x/ibc/core/simulation/genesis.go deleted file mode 100644 index d71f4492500e..000000000000 --- a/x/ibc/core/simulation/genesis.go +++ /dev/null @@ -1,63 +0,0 @@ -package simulation - -// DONTCOVER - -import ( - "encoding/json" - "fmt" - "math/rand" - - "github.com/cosmos/cosmos-sdk/types/module" - clientsims "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/simulation" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - connectionsims "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/simulation" - connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - channelsims "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/simulation" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/types" -) - -// Simulation parameter constants -const ( - clientGenesis = "client_genesis" - connectionGenesis = "connection_genesis" - channelGenesis = "channel_genesis" -) - -// RandomizedGenState generates a random GenesisState for evidence -func RandomizedGenState(simState *module.SimulationState) { - var ( - clientGenesisState clienttypes.GenesisState - connectionGenesisState connectiontypes.GenesisState - channelGenesisState channeltypes.GenesisState - ) - - simState.AppParams.GetOrGenerate( - simState.Cdc, clientGenesis, &clientGenesisState, simState.Rand, - func(r *rand.Rand) { clientGenesisState = clientsims.GenClientGenesis(r, simState.Accounts) }, - ) - - simState.AppParams.GetOrGenerate( - simState.Cdc, connectionGenesis, &connectionGenesisState, simState.Rand, - func(r *rand.Rand) { connectionGenesisState = connectionsims.GenConnectionGenesis(r, simState.Accounts) }, - ) - - simState.AppParams.GetOrGenerate( - simState.Cdc, channelGenesis, &channelGenesisState, simState.Rand, - func(r *rand.Rand) { channelGenesisState = channelsims.GenChannelGenesis(r, simState.Accounts) }, - ) - - ibcGenesis := types.GenesisState{ - ClientGenesis: clientGenesisState, - ConnectionGenesis: connectionGenesisState, - ChannelGenesis: channelGenesisState, - } - - bz, err := json.MarshalIndent(&ibcGenesis, "", " ") - if err != nil { - panic(err) - } - fmt.Printf("Selected randomly generated %s parameters:\n%s\n", host.ModuleName, bz) - simState.GenState[host.ModuleName] = simState.Cdc.MustMarshalJSON(&ibcGenesis) -} diff --git a/x/ibc/core/simulation/genesis_test.go b/x/ibc/core/simulation/genesis_test.go deleted file mode 100644 index 54aff75ad9c8..000000000000 --- a/x/ibc/core/simulation/genesis_test.go +++ /dev/null @@ -1,49 +0,0 @@ -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" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/simulation" - "github.com/cosmos/cosmos-sdk/x/ibc/core/types" -) - -// TestRandomizedGenState tests the normal scenario of applying RandomizedGenState. -// Abonormal scenarios are not tested here. -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), - } - - // Remark: the current RandomizedGenState function - // is actually not random as it does not utilize concretely the random value r. - // This tests will pass for any value of r. - simulation.RandomizedGenState(&simState) - - var ibcGenesis types.GenesisState - simState.Cdc.MustUnmarshalJSON(simState.GenState[host.ModuleName], &ibcGenesis) - - require.NotNil(t, ibcGenesis.ClientGenesis) - require.NotNil(t, ibcGenesis.ConnectionGenesis) - require.NotNil(t, ibcGenesis.ChannelGenesis) -} diff --git a/x/ibc/core/spec/01_concepts.md b/x/ibc/core/spec/01_concepts.md deleted file mode 100644 index 4347fb674154..000000000000 --- a/x/ibc/core/spec/01_concepts.md +++ /dev/null @@ -1,405 +0,0 @@ - - -# Concepts - -> NOTE: if you are not familiar with the IBC terminology and concepts, please read -this [document](https://github.com/cosmos/ics/blob/master/ibc/1_IBC_TERMINOLOGY.md) as prerequisite reading. - -## Client Creation, Updates, and Upgrades - -IBC clients are on chain light clients. The light client is responsible for verifying -counterparty state. A light client can be created by any user submitting a valid initial -`ClientState` and `ConsensusState`. The client identifier is auto generated using the -client type and the global client counter appended in the format: `{client-type}-{N}`. -Clients are given a client identifier prefixed store to store their associated client -state and consensus states. Consensus states are stored using their associated height. - -Clients can be updated by any user submitting a valid `Header`. The client state callback -to `CheckHeaderAndUpdateState` is responsible for verifying the header against previously -stored state. The function should also return the updated client state and consensus state -if the header is considered a valid update. A light client, such as Tendermint, may have -client specific parameters like `TrustLevel` which must be considered valid in relation -to the `Header`. The update height is not necessarily the lastest height of the light -client. Updates may fill in missing consensus state heights. - -Clients may be upgraded. The upgrade should be verified using `VerifyUpgrade`. It is not -a requirement to allow for light client upgrades. For example, the solo machine client -will simply return an error on `VerifyUpgrade`. Clients which implement upgrades -are expected to account for, but not necessarily support, planned and unplanned upgrades. - -## Client Misbehaviour - -IBC clients must freeze when the counterparty chain becomes byzantine and -takes actions that could fool the light client into accepting invalid state -transitions. Thus, relayers are able to submit Misbehaviour proofs that prove -that a counterparty chain has signed two Headers for the same height. This -constitutes misbehaviour as the IBC client could have accepted either header -as valid. Upon verifying the misbehaviour the IBC client must freeze at that -height so that any proof verifications for the frozen height or later fail. - -Note, there is a difference between the chain-level Misbehaviour that IBC is -concerned with and the validator-level Evidence that Tendermint is concerned -with. Tendermint must be able to detect, submit, and punish any evidence of -individual validators breaking the Tendermint consensus protocol and attempting -to mount an attack. IBC clients must only act when an attack is successful -and the chain has successfully forked. In this case, valid Headers submitted -to the IBC client can no longer be trusted and the client must freeze. - -Governance may then choose to override a frozen client and provide the correct, -canonical Header so that the client can continue operating after the Misbehaviour -submission. - -## ClientUpdateProposal - -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. - -The solo machine client requires the boolean flag 'AllowUpdateAfterProposal' to be set -to true in order to be updated by a proposal. This is set upon client creation and cannot -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 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 - -IBC Client Heights are represented by the struct: - -```go -type Height struct { - RevisionNumber uint64 - RevisionHeight uint64 -} -``` - -The `RevisionNumber` represents the revision of the chain that the height is representing. -An revision typically represents a continuous, monotonically increasing range of block-heights. -The `RevisionHeight` represents the height of the chain within the given revision. - -On any reset of the `RevisionHeight`, for example, when hard-forking a Tendermint chain, -the `RevisionNumber` will get incremented. This allows IBC clients to distinguish between a -block-height `n` of a previous revision of the chain (at revision `p`) and block-height `n` of the current -revision of the chain (at revision `e`). - -`Heights` that share the same revision number can be compared by simply comparing their respective `RevisionHeights`. -Heights that do not share the same revision number will only be compared using their respective `RevisionNumbers`. -Thus a height `h` with revision number `e+1` will always be greater than a height `g` with revision number `e`, -**REGARDLESS** of the difference in revision heights. - -Ex: - -```go -Height{RevisionNumber: 3, RevisionHeight: 0} > Height{RevisionNumber: 2, RevisionHeight: 100000000000} -``` - -When a Tendermint chain is running a particular revision, relayers can simply submit headers and proofs with the revision number -given by the chain's chainID, and the revision height given by the Tendermint block height. When a chain updates using a hard-fork -and resets its block-height, it is responsible for updating its chain-id to increment the revision number. -IBC Tendermint clients then verifies the revision number against their `ChainId` and treat the `RevisionHeight` as the Tendermint block-height. - -Tendermint chains wishing to use revisions to maintain persistent IBC connections even across height-resetting upgrades must format their chain-ids -in the following manner: `{chainID}-{revision_number}`. On any height-resetting upgrade, the chainID **MUST** be updated with a higher revision number -than the previous value. - -Ex: - -- Before upgrade ChainID: `gaiamainnet-3` -- After upgrade ChainID: `gaiamainnet-4` - -Clients that do not require revisions, such as the solo-machine client, simply hardcode `0` into the revision number whenever they -need to return an IBC height when implementing IBC interfaces and use the `RevisionHeight` exclusively. - -Other client-types may implement their own logic to verify the IBC Heights that relayers provide in their `Update`, `Misbehavior`, and -`Verify` functions respectively. - -The IBC interfaces expect an `ibcexported.Height` interface, however all clients should use the concrete implementation provided in -`02-client/types` and reproduced above. - -## Connection Handshake - -The connection handshake occurs in 4 steps as defined in [ICS 03](https://github.com/cosmos/ics/tree/master/spec/ics-003-connection-semantics). - -`ConnOpenInit` is the first attempt to initialize a connection on the executing chain. -The handshake is expected to succeed if the version selected is supported. The connection -identifier for the counterparty connection must be left empty indicating that the counterparty -must select its own identifier. The connection identifier is auto derived in the format: -`connection{N}` where N is the next sequence to be used. The counter begins at 0 and increments -by 1. The connection is set and stored in the INIT state upon success. - -`ConnOpenTry` is a response to a chain executing `ConnOpenInit`. The executing chain will validate -the chain level parameters the counterparty has stored such as its chainID. The executing chain -will also verify that if a previous connection exists for the specified connection identifier -that all the parameters match and its previous state was in INIT. This may occur when both -chains execute `ConnOpenInit` simultaneously. If the connection does not exist then a connection -identifier is generated in the same format done in `ConnOpenInit`. The executing chain will verify -that the counterparty created a connection in INIT state. The executing chain will also verify -The `ClientState` and `ConsensusState` the counterparty stores for the executing chain. The -executing chain will select a version from the intersection of its supported versions and the -versions set by the counterparty. The connection is set and stored in the TRYOPEN state upon -success. - -`ConnOpenAck` may be called on a chain when the counterparty connection has entered TRYOPEN. A -previous connection on the executing chain must exist in either INIT or TRYOPEN. The executing -chain will verify the version the counterparty selected. If the counterparty selected its own -connection identifier, it will be validated in the basic validation of a `MsgConnOpenAck`. -The counterparty connection state is verified along with the `ClientState` and `ConsensusState` -stored for the executing chain. The connection is set and stored in the OPEN state upon success. - -`ConnOpenConfirm` is a response to a chain executing `ConnOpenAck`. The executing chain's connection -must be in TRYOPEN. The counterparty connection state is verified to be in the OPEN state. The -connection is set and stored in the OPEN state upon success. - -## Connection Version Negotiation - -During the handshake procedure for connections a version is agreed -upon between the two parties. This occurs during the first 3 steps of the -handshake. - -During `ConnOpenInit`, party A is expected to set all the versions they wish -to support within their connection state. It is expected that this set of -versions is from most preferred to least preferred. This is not a strict -requirement for the SDK implementation of IBC because the party calling -`ConnOpenTry` will greedily select the latest version it supports that the -counterparty supports as well. A specific version can optionally be passed -as `Version` to ensure that the handshake will either complete with that -version or fail. - -During `ConnOpenTry`, party B will select a version from the counterparty's -supported versions. Priority will be placed on the latest supported version. -If a matching version cannot be found an error is returned. - -During `ConnOpenAck`, party A will verify that they can support the version -party B selected. If they do not support the selected version an error is -returned. After this step, the connection version is considered agreed upon. - - -A `Version` is defined as follows: - -```go -type Version struct { - // unique version identifier - Identifier string - // list of features compatible with the specified identifier - Features []string -} -``` - -A version must contain a non empty identifier. Empty feature sets are allowed, but each -feature must be a non empty string. - -::: warning -A set of versions should not contain two versions with the same -identifier, but differing feature sets. This will result in undefined behavior -with regards to version selection in `ConnOpenTry`. Each version in a set of -versions should have a unique version identifier. -::: - -## Channel Handshake - -The channel handshake occurs in 4 steps as defined in [ICS 04](https://github.com/cosmos/ics/tree/master/spec/ics-004-channel-and-packet-semantics). - -`ChanOpenInit` is the first attempt to initialize a channel on top of an existing connection. -The handshake is expected to succeed if the version selected for the existing connection is a -supported IBC version. The portID must correspond to a port already binded upon `InitChain`. -The channel identifier for the counterparty channel must be left empty indicating that the -counterparty must select its own identifier. The channel identifier is auto derived in the -format: `channel{N}` where N is the next sequence to be used. The channel is set and stored -in the INIT state upon success. The channel parameters `NextSequenceSend`, `NextSequenceRecv`, -and `NextSequenceAck` are all set to 1 and a channel capability is created for the given -portID and channelID path. - -`ChanOpenTry` is a response to a chain executing `ChanOpenInit`. If the executing chain is calling -`ChanOpenTry` after previously executing `ChanOpenInit` then the provided channel parameters must -match the previously selected parameters. If the previous channel does not exist then a channel -identifier is generated in the same format as done in `ChanOpenInit`. The connection the channel -is created on top of must be an OPEN state and its IBC version must support the desired channel -type being created (ORDERED, UNORDERED, etc). The executing chain will verify that the channel -state of the counterparty is in INIT. The executing chain will set and store the channel state -in TRYOPEN. The channel parameters `NextSequenceSend`, `NextSequenceRecv`, and `NextSequenceAck` -are all set to 1 and a channel capability is created for the given portID and channelID path only -if the channel did not previously exist. - -`ChanOpenAck` may be called on a chain when the counterparty channel has entered TRYOPEN. A -previous channel on the executing chain must exist be in either INIT or TRYOPEN state. If the -counterparty selected its own channel identifier, it will be validated in the basic validation -of `MsgChanOpenAck`. The executing chain verifies that the counterparty channel state is in -TRYOPEN. The channel is set and stored in the OPEN state upon success. - -`ChanOpenConfirm` is a response to a chain executing `ChanOpenAck`. The executing chain's -previous channel state must be in TRYOPEN. The executing chain verifies that the counterparty -channel state is OPEN. The channel is set and stored in the OPEN state upon success. - -## Channel Version Negotiation - -During the channel handshake procedure a version must be agreed upon between -the two parties. The selection process is largely left to the callers and -the verification of valid versioning must be handled by application developers -in the channel handshake callbacks. - -During `ChanOpenInit`, a version string is passed in and set in party A's -channel state. - -During `ChanOpenTry`, a version string for party A and for party B are passed -in. The party A version string must match the version string used in -`ChanOpenInit` otherwise channel state verification will fail. The party B -version string could be anything (even different than the proposed one by -party A). However, the proposed version by party B is expected to be fully -supported by party A. - -During the `ChanOpenAck` callback, the application module is expected to verify -the version proposed by party B using the `MsgChanOpenAck` `CounterpartyVersion` -field. The application module should throw an error if the version string is -not valid. - -In general empty version strings are to be considered valid options for an -application module. - -Application modules may implement their own versioning system, such as semantic -versioning, or they may lean upon the versioning system used for in connection -version negotiation. To use the connection version semantics the application -would simply pass the proto encoded version into each of the handshake calls -and decode the version string into a `Version` instance to do version verification -in the handshake callbacks. - -Implementations which do not feel they would benefit from versioning can do -basic string matching using a single compatible version. - -## Sending, Receiving, Acknowledging Packets - -Terminology: -**Packet Commitment** A hash of the packet stored on the sending chain. -**Packet Receipt** A single bit indicating that a packet has been received. -Used for timeouts. -**Acknowledgement** Data written to indicate the result of receiving a packet. -Typically conveying either success or failure of the receive. - -A packet may be associated with one of the following states: -- the packet does not exist (ie it has not been sent) -- the packet has been sent but not received (the packet commitment exists on the -sending chain, but no receipt exists on the receiving chain) -- the packet has been received but not acknowledged (packet commitment exists -on the sending chain, a receipt exists on the receiving chain, but no acknowledgement -exists on the receiving chain) -- the packet has been acknowledgement but the acknowledgement has not been relayed -(the packet commitment exists on the sending chain, the receipt and acknowledgement -exist on the receiving chain) -- the packet has completed its life cycle (the packet commitment does not exist on -the sending chain, but a receipt and acknowledgement exist on the receiving chain) - -Sending of a packet is initiated by a call to the `ChannelKeeper.SendPacket` -function by an application module. Packets being sent will be verified for -correctness (core logic only). If the packet is valid, a hash of the packet -will be stored as a packet commitment using the packet sequence in the key. -Packet commitments are stored on the sending chain. - -A message should be sent to the receving chain indicating that the packet -has been committed on the sending chain and should be received on the -receiving chain. The light client on the receiving chain, which verifies -the sending chain's state, should be updated to the lastest sending chain -state if possible. The verification will fail if the latest state of the -light client does not include the packet commitment. The receiving chain -is responsible for verifying that the counterparty set the hash of the -packet. If verification of the packet to be received is successful, the -receiving chain should store a receipt of the packet and call application -logic if necessary. An acknowledgement may be processed and stored at this time (synchronously) -or at another point in the future (asynchronously). - -Acknowledgements written on the receiving chain may be verified on the -sending chain. If the sending chain successfully verifies the acknowledgement -then it may delete the packet commitment stored at that sequence. There is -no requirement for acknowledgements to be written. Only the hash of the -acknowledgement is stored on the chain. Application logic may be executed -in conjunction with verifying an acknowledgement. For example, in fungible -cross-chain token transfer, a failed acknowledgement results in locked or -burned funds being refunded. - -Relayers are responsible for reconstructing packets between the sending, -receiving, and acknowledging of packets. - -IBC applications sending and receiving packets are expected to appropriately -handle data contained within a packet. For example, cross-chain token -transfers will unmarshal the data into proto definitions representing -a token transfer. - -Future optimizations may allow for storage cleanup. Stored packet -commitments could be removed from channels which do not write -packet acknowledgements and acknowledgements could be removed -when a packet has completed its life cycle. - -## Timing out Packets - -A packet may be timed out on the receiving chain if the packet timeout height or timestamp has -been surpassed on the receving chain or the channel has closed. A timed out -packet can only occur if the packet has never been received on the receiving -chain. ORDERED channels will verify that the packet sequence is greater than -the `NextSequenceRecv` on the receiving chain. UNORDERED channels will verify -that the packet receipt has not been written on the receiving chain. A timeout -on channel closure will additionally verify that the counterparty channel has -been closed. A successful timeout may execute application logic as appropriate. - -Both the packet's timeout timestamp and the timeout height must have been -surpassed on the receiving chain for a timeout to be valid. A timeout timestamp -or timeout height with a 0 value indicates the timeout field may be ignored. -Each packet is required to have at least one valid timeout field. - -## Closing Channels - -Closing a channel occurs in occurs in 2 handshake steps as defined in [ICS 04](https://github.com/cosmos/ics/tree/master/spec/ics-004-channel-and-packet-semantics). - -`ChanCloseInit` will close a channel on the executing chain if the channel exists, it is not -already closed and the connection it exists upon is OPEN. Channels can only be closed by a -calling module or in the case of a packet timeout on an ORDERED channel. - -`ChanCloseConfirm` is a response to a counterparty channel executing `ChanCloseInit`. The channel -on the executing chain will be closed if the channel exists, the channel is not already closed, -the connection the channel exists upon is OPEN and the executing chain successfully verifies -that the counterparty channel has been closed. - -## Port and Channel Capabilities - -## Hostname Validation - -Hostname validation is implemented as defined in [ICS 24](https://github.com/cosmos/ics/tree/master/spec/ics-024-host-requirements). - -The 24-host sub-module parses and validates identifiers. It also builds -the key paths used to store IBC related information. - -A valid identifier must conatin only alphanumeric characters or the -following list of allowed characters: -".", "\_", "+", "-", "#", "[", "]", "<", ">" - -- Client identifiers must contain between 9 and 64 characters. -- Connection identifiers must contain between 10 and 64 characters. -- Channel identifiers must contain between 10 and 64 characters. -- Port identifiers must contain between 2 and 64 characters. - -## Proofs - -Proofs for counterparty state validation are provided as bytes. These bytes -can be unmarshaled into proto definitions as necessary by light clients. -For example, the Tendermint light client will use the bytes as a merkle -proof where as the solo machine client will unmarshal the proof into -several layers proto definitions used for signature verficiation. diff --git a/x/ibc/core/spec/02_state.md b/x/ibc/core/spec/02_state.md deleted file mode 100644 index 2c85a525a953..000000000000 --- a/x/ibc/core/spec/02_state.md +++ /dev/null @@ -1,28 +0,0 @@ - - -# State - -The paths for the values stored in state is defined [here](https://github.com/cosmos/ics/blob/master/spec/ics-024-host-requirements/README.md#path-space). -Additionally, the SDK adds a prefix to the path to be able to aggregate the values for querying purposes. -The client type is not stored since it can be obtained through the client state. - -| Prefix | Path | Value type | -|--------|-----------------------------------------------------------------------------|----------------| -| "0/" | "clients/{identifier}/clientState" | ClientState | -| "0/" | "clients/{identifier}/consensusStates/{height}" | ConsensusState | -| "0/" | "clients/{identifier}/connections" | []string | -| "0/" | "nextClientSequence | uint64 | -| "0/" | "connections/{identifier}" | ConnectionEnd | -| "0/" | "nextConnectionSequence" | uint64 | -| "0/" | "ports/{identifier}" | CapabilityKey | -| "0/" | "channelEnds/ports/{identifier}/channels/{identifier}" | ChannelEnd | -| "0/" | "nextChannelSequence" | uint64 | -| "0/" | "capabilities/ports/{identifier}/channels/{identifier}" | CapabilityKey | -| "0/" | "nextSequenceSend/ports/{identifier}/channels/{identifier}" | uint64 | -| "0/" | "nextSequenceRecv/ports/{identifier}/channels/{identifier}" | uint64 | -| "0/" | "nextSequenceAck/ports/{identifier}/channels/{identifier}" | uint64 | -| "0/" | "commitments/ports/{identifier}/channels/{identifier}/sequences/{sequence}" | bytes | -| "0/" | "receipts/ports/{identifier}/channels/{identifier}/sequences/{sequence}" | bytes | -| "0/" | "acks/ports/{identifier}/channels/{identifier}/sequences/{sequence}" | bytes | diff --git a/x/ibc/core/spec/03_state_transitions.md b/x/ibc/core/spec/03_state_transitions.md deleted file mode 100644 index 518ff9247b97..000000000000 --- a/x/ibc/core/spec/03_state_transitions.md +++ /dev/null @@ -1,106 +0,0 @@ - - -# State Transitions - -The described state transitions assume successful message exection. - -## Create Client - -`MsgCreateClient` will initialize and store a `ClientState` and `ConsensusState` in the sub-store -created using a generated client identifier. - -## Update Client - -`MsgUpdateClient` will update the `ClientState` and create a new `ConsensusState` for the -update height. - -## Misbehaviour - -`MsgSubmitMisbehaviour` will freeze a client. - -## Upgrade Client - -`MsgUpgradeClient` will upgrade the `ClientState` and `ConsensusState` to the update chain level -parameters and if applicable will update to the new light client implementation. - -## Client Update Proposal - -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 - -`MsgConnectionOpenInit` will initialize a connection state in INIT. - -## Connection Open Try - -`MsgConnectionOpenTry` will initialize or update a connection state to be in TRYOPEN. - -## Connection Open Ack - -`MsgConnectionOpenAck` will update a connection state from INIT or TRYOPEN to be in OPEN. - -## Connection Open Confirm - -`MsgConnectionOpenAck` will update a connection state from TRYOPEN to OPEN. - -## Channel Open Init - -`MsgChannelOpenInit` will initialize a channel state in INIT. It will create a channel capability -and set all Send, Receive and Ack Sequences to 1 for the channel. - -## Channel Open Try - -`MsgChannelOpenTry` will initialize or update a channel state to be in TRYOPEN. If the channel -is being initialized, It will create a channel capability and set all Send, Receive and Ack -Sequences to 1 for the channel. - -## Channel Open Ack - -`MsgChannelOpenAck` will update the channel state to OPEN. It will set the version and channel -identifier for its counterparty. - -## Channel Open Confirm - -`MsgChannelOpenConfirm` will update the channel state to OPEN. - -## Channel Close Init - -`MsgChannelCloseInit` will update the channel state to CLOSED. - -## Channel Close Confirm - -`MsgChannelCloseConfirm` will update the channel state to CLOSED. - -## Send Packet - -A application calling `ChannelKeeper.SendPacket` will incremenet the next sequence send and set -a hash of the packet as the packet commitment. - -## Receive Packet - -`MsgRecvPacket` will increment the next sequence receive for ORDERED channels and set a packet -receipt for UNORDERED channels. - -## Write Acknowledgement - -`WriteAcknowledgement` may be executed synchronously during the execution of `MsgRecvPacket` or -asynchonously by an application module. It writes an acknowledgement to the store. - -## Acknowledge Packet - -`MsgAcknowledgePacket` deletes the packet commitment and for ORDERED channels increments next -sequences ack. - -## Timeout Packet - -`MsgTimeoutPacket` deletes the packet commitment and for ORDERED channels sets the channel state -to CLOSED. - -## Timeout Packet on Channel Closure - -`MsgTimeoutOnClose` deletes the packet commitment and for ORDERED channels sets the channel state -to CLOSED. diff --git a/x/ibc/core/spec/04_messages.md b/x/ibc/core/spec/04_messages.md deleted file mode 100644 index 3728e6d6f323..000000000000 --- a/x/ibc/core/spec/04_messages.md +++ /dev/null @@ -1,497 +0,0 @@ - - -# Messages - -In this section we describe the processing of the IBC messages and the corresponding updates to the state. - -## ICS 02 - Client - -### MsgCreateClient - -A light client is created using the `MsgCreateClient`. - -```go -type MsgCreateClient struct { - ClientState *types.Any // proto-packed client state - ConsensusState *types.Any // proto-packed consensus state - Signer sdk.AccAddress -} -``` - -This message is expected to fail if: - -- `ClientState` is empty or invalid -- `ConsensusState` is empty or invalid -- `Signer` is empty - -The message creates and stores a light client with an initial consensus state using a generated client -identifier. - -### MsgUpdateClient - -A light client is updated with a new header using the `MsgUpdateClient`. - -```go -type MsgUpdateClient struct { - ClientId string - Header *types.Any // proto-packed header - Signer sdk.AccAddress -} -``` - -This message is expected to fail if: - -- `ClientId` is invalid (not alphanumeric or not within 10-20 characters) -- `Header` is empty or invalid -- `Signer` is empty -- A `ClientState` hasn't been created for the given ID -- The client is frozen due to misbehaviour and cannot be updated -- The header fails to provide a valid update for the client - -The message validates the header and updates the client state and consensus state for the -header height. - -### MsgUpgradeClient -```go -type MsgUpgradeClient struct { - ClientId string - ClientState *types.Any // proto-packed client state - UpgradeHeight *Height - ProofUpgrade []byte - Signer string -} -``` - -This message is expected to fail if: - -- `ClientId` is invalid (not alphanumeric or not within 10-20 characters) -- `ClientState` is empty or invalid -- `UpgradeHeight` is empty or zero -- `ProofUpgrade` is empty -- `Signer` is empty -- A `ClientState` hasn't been created for the given ID -- The client is frozen due to misbehaviour and cannot be upgraded -- The upgrade proof fails - -The message upgrades the client state and consensus state upon successful validation of a -chain upgrade. - -### MsgSubmitMisbehaviour - -Submit a evidence of light client misbehaviour to freeze the client state and prevent additional packets from being relayed. - -```go -type MsgSubmitMisbehaviour struct { - ClientId string - Misbehaviour *types.Any // proto-packed misbehaviour - Signer sdk.AccAddress -} -``` - -This message is expected to fail if: - -- `ClientId` is invalid (not alphanumeric or not within 10-20 characters) -- `Misbehaviour` is empty or invalid -- `Signer` is empty -- A `ClientState` hasn't been created for the given ID -- `Misbehaviour` check failed - -The message verifies the misbehaviour and freezes the client. - -## ICS 03 - Connection - -### MsgConnectionOpenInit - -A connection is initialized on a light client using the `MsgConnectionOpenInit`. - -```go -type MsgConnectionOpenInit struct { - ClientId string - Counterparty Counterparty - Version string - Signer sdk.AccAddress -} -``` - -This message is expected to fail if: -- `ClientId` is invalid (see naming requirements) -- `Counterparty` is empty -- 'Version' is not empty and invalid -- `Signer` is empty -- A Client hasn't been created for the given ID -- A Connection for the given ID already exists - -The message creates a connection for the given ID with an INIT state. - -### MsgConnectionOpenTry - -When a counterparty connection is initialized then a connection is initialized on a light client -using the `MsgConnectionOpenTry`. - -```go -type MsgConnectionOpenTry struct { - ClientId string - PreviousConnectionId string - ClientState *types.Any // proto-packed counterparty client - Counterparty Counterparty - CounterpartyVersions []string - ProofHeight Height - ProofInit []byte - ProofClient []byte - ProofConsensus []byte - ConsensusHeight Height - Signer sdk.AccAddress -} -``` - -This message is expected to fail if: - -- `ClientId` is invalid (see naming requirements) -- `PreviousConnectionId` is not empty and invalid (see naming requirements) -- `ClientState` is not a valid client of the executing chain -- `Counterparty` is empty -- `CounterpartyVersions` is empty -- `ProofHeight` is zero -- `ProofInit` is empty -- `ProofClient` is empty -- `ProofConsensus` is empty -- `ConsensusHeight` is zero -- `Signer` is empty -- A Client hasn't been created for the given ID -- If a previous connection exists but does not match the supplied parameters. -- `ProofInit` does not prove that the counterparty connection is in state INIT -- `ProofClient` does not prove that the counterparty has stored the `ClientState` provided in message -- `ProofConsensus` does not prove that the counterparty has the correct consensus state for this chain - -The message creates a connection for a generated connection ID with an TRYOPEN State. If a previous -connection already exists, it updates the connection state from INIT to TRYOPEN. - -### MsgConnectionOpenAck - -When a counterparty connection is initialized then a connection is opened on a light client -using the `MsgConnectionOpenAck`. - -```go -type MsgConnectionOpenAck struct { - ConnectionId string - CounterpartyConnectionId string - Version string - ClientState *types.Any // proto-packed counterparty client - ProofHeight Height - ProofTry []byte - ProofClient []byte - ProofConsensus []byte - ConsensusHeight Height - Signer sdk.AccAddress -} -``` - -This message is expected to fail if: - -- `ConnectionId` is invalid (see naming requirements) -- `CounterpartyConnectionId` is invalid (see naming requirements) -- `Version` is empty -- `ClientState` is not a valid client of the executing chain -- `ProofHeight` is zero -- `ProofTry` is empty -- `ProofClient` is empty -- `ProofConsensus` is empty -- `ConsensusHeight` is zero -- `Signer` is empty -- `ProofTry` does not prove that the counterparty connection is in state TRYOPEN -- `ProofClient` does not prove that the counterparty has stored the `ClientState` provided by message -- `ProofConsensus` does not prove that the counterparty has the correct consensus state for this chain - -The message sets the connection state for the given ID to OPEN. `CounterpartyConnectionId` -should be the `ConnectionId` used by the counterparty connection. - -### MsgConnectionOpenConfirm - -When a counterparty connection is opened then a connection is opened on a light client using -the `MsgConnectionOpenConfirm`. - -```go -type MsgConnectionOpenConfirm struct { - ConnectionId string - ProofAck []byte - ProofHeight Height - Signer sdk.AccAddress -} -``` - -This message is expected to fail if: - -- `ConnectionId` is invalid (see naming requirements) -- `ProofAck` is empty -- `ProofHeight` is zero -- `Signer` is empty -- A Connection with the given ID does not exist -- `ProofAck` does not prove that the counterparty connection is in state OPEN - -The message sets the connection state for the given ID to OPEN. - -## ICS 04 - Channels - -### MsgChannelOpenInit - -A channel handshake is initiated by a chain A using the `MsgChannelOpenInit` -message. - -```go -type MsgChannelOpenInit struct { - PortId string - Channel Channel - Signer sdk.AccAddress -} -``` - -This message is expected to fail if: - -- `PortId` is invalid (see naming requirements) -- `Channel` is empty -- `Signer` is empty -- A Channel End exists for the given Channel ID and Port ID - -The message creates a channel on chain A with an INIT state for a generated Channel ID -and Port ID. - -### MsgChannelOpenTry - -A channel handshake initialization attempt is acknowledged by a chain B using -the `MsgChannelOpenTry` message. - -```go -type MsgChannelOpenTry struct { - PortId string - PreviousChannelId string - Channel Channel - CounterpartyVersion string - ProofInit []byte - ProofHeight Height - Signer sdk.AccAddress -} -``` - -This message is expected to fail if: - -- `PortId` is invalid (see naming requirements) -- `PreviousChannelId` is not empty and invalid (see naming requirements) -- `Channel` is empty -- `CounterpartyVersion` is empty -- `ProofInit` is empty -- `ProofHeight` is zero -- `Signer` is empty -- A previous channel exists and does not match the provided parameters. -- `ProofInit` does not prove that the counterparty's Channel state is in INIT - -The message creates a channel on chain B with an TRYOPEN state for using a generated Channel ID -and given Port ID if the previous channel does not already exist. Otherwise it udates the -previous channel state from INIT to TRYOPEN. - - -### MsgChannelOpenAck - -A channel handshake is opened by a chain A using the `MsgChannelOpenAck` message. - -```go -type MsgChannelOpenAck struct { - PortId string - ChannelId string - CounterpartyChannelId string - CounterpartyVersion string - ProofTry []byte - ProofHeight Height - Signer sdk.AccAddress -} -``` - -This message is expected to fail if: - -- `PortId` is invalid (see naming requirements) -- `ChannelId` is invalid (see naming requirements) -- `CounterpartyChannelId` is invalid (see naming requirements) -- `CounterpartyVersion` is empty -- `ProofTry` is empty -- `ProofHeight` is zero -- `Signer` is empty -- `ProofTry` does not prove that the counterparty's Channel state is in TRYOPEN - -The message sets a channel on chain A to state OPEN for the given Channel ID and Port ID. -`CounterpartyChannelId` should be the `ChannelId` used by the counterparty channel. - -### MsgChannelOpenConfirm - -A channel handshake is confirmed and opened by a chain B using the `MsgChannelOpenConfirm` -message. - -```go -type MsgChannelOpenConfirm struct { - PortId string - ChannelId string - ProofAck []byte - ProofHeight Height - Signer sdk.AccAddress -} -``` - -This message is expected to fail if: - -- `PortId` is invalid (see naming requirements) -- `ChannelId` is invalid (see naming requirements) -- `ProofAck` is empty -- `ProofHeight` is zero -- `Signer` is empty -- `ProofAck` does not prove that the counterparty's Channel state is in OPEN - -The message sets a channel on chain B to state OPEN for the given Channel ID and Port ID. - -### MsgChannelCloseInit - -A channel is closed on chain A using the `MsgChannelCloseInit`. - -```go -type MsgChannelCloseInit struct { - PortId string - ChannelId string - Signer sdk.AccAddress -} -``` - -This message is expected to fail if: - -- `PortId` is invalid (see naming requirements) -- `ChannelId` is invalid (see naming requirements) -- `Signer` is empty -- A Channel for the given Port ID and Channel ID does not exist or is already closed - -The message closes a channel on chain A for the given Port ID and Channel ID. - -### MsgChannelCloseConfirm - -A channel is closed on chain B using the `MsgChannelCloseConfirm`. - -```go -type MsgChannelCloseConfirm struct { - PortId string - ChannelId string - ProofInit []byte - ProofHeight Height - Signer sdk.AccAddress -} -``` - -This message is expected to fail if: - -- `PortId` is invalid (see naming requirements) -- `ChannelId` is invalid (see naming requirements) -- `ProofInit` is empty -- `ProofHeight` is zero -- `Signer` is empty -- A Channel for the given Port ID and Channel ID does not exist or is already closed -- `ProofInit` does not prove that the counterparty set its channel to state CLOSED - -The message closes a channel on chain B for the given Port ID and Channel ID. - -### MsgRecvPacket - -A packet is received on chain B using the `MsgRecvPacket`. - -```go -type MsgRecvPacket struct { - Packet Packet - Proof []byte - ProofHeight Height - Signer sdk.AccAddress -} -``` - -This message is expected to fail if: - -- `Proof` is empty -- `ProofHeight` is zero -- `Signer` is empty -- `Packet` fails basic validation -- `Proof` does not prove that the counterparty sent the `Packet`. - -The message receives a packet on chain B. - -### MsgTimeout - -A packet is timed out on chain A using the `MsgTimeout`. - -```go -type MsgTimeout struct { - Packet Packet - Proof []byte - ProofHeight Height - NextSequenceRecv uint64 - Signer sdk.AccAddress -} -``` - -This message is expected to fail if: - -- `Proof` is empty -- `ProofHeight` is zero -- `NextSequenceRecv` is zero -- `Signer` is empty -- `Packet` fails basic validation -- `Proof` does not prove that the packet has not been received on the counterparty chain. - -The message times out a packet that was sent on chain A and never received on chain B. - -### MsgTimeoutOnClose - -A packet is timed out on chain A due to the closure of the channel end on chain B using -the `MsgTimeoutOnClose`. - -```go -type MsgTimeoutOnClose struct { - Packet Packet - Proof []byte - ProofClose []byte - ProofHeight Height - NextSequenceRecv uint64 - Signer sdk.AccAddress -} -``` - -This message is expected to fail if: - -- `Proof` is empty -- `ProofClose` is empty -- `ProofHeight` is zero -- `NextSequenceRecv` is zero -- `Signer` is empty -- `Packet` fails basic validation -- `Proof` does not prove that the packet has not been received on the counterparty chain. -- `ProofClose` does not prove that the counterparty channel end has been closed. - -The message times out a packet that was sent on chain A and never received on chain B. - -### MsgAcknowledgement - -A packet is acknowledged on chain A using the `MsgAcknowledgement`. - -```go -type MsgAcknowledgement struct { - Packet Packet - Acknowledgement []byte - Proof []byte - ProofHeight Height - Signer sdk.AccAddress -} -``` - -This message is expected to fail if: - -- `Proof` is empty -- `ProofHeight` is zero -- `Signer` is empty -- `Packet` fails basic validation -- `Acknowledgement` is empty -- `Proof` does not prove that the counterparty received the `Packet`. - -The message acknowledges that the packet sent from chainA was received on chain B. diff --git a/x/ibc/core/spec/05_callbacks.md b/x/ibc/core/spec/05_callbacks.md deleted file mode 100644 index dd7473802590..000000000000 --- a/x/ibc/core/spec/05_callbacks.md +++ /dev/null @@ -1,80 +0,0 @@ - - -# Callbacks - -Application modules implementing the IBC module must implement the following callbacks as found in [05-port](../05-port/types/module.go). -More information on how to implement these callbacks can be found in the [implementation guide](../../../../docs/ibc/custom.md). - -```go -// IBCModule defines an interface that implements all the callbacks -// that modules must define as specified in ICS-26 -type IBCModule interface { - OnChanOpenInit( - ctx sdk.Context, - order channeltypes.Order, - connectionHops []string, - portId string, - channelId string, - channelCap *capability.Capability, - counterparty channeltypes.Counterparty, - version string, - ) error - - OnChanOpenTry( - ctx sdk.Context, - order channeltypes.Order, - connectionHops []string, - portId, - channelId string, - channelCap *capability.Capability, - counterparty channeltypes.Counterparty, - version, - counterpartyVersion string, - ) error - - OnChanOpenAck( - ctx sdk.Context, - portId, - channelId string, - counterpartyVersion string, - ) error - - OnChanOpenConfirm( - ctx sdk.Context, - portId, - channelId string, - ) error - - OnChanCloseInit( - ctx sdk.Context, - portId, - channelId string, - ) error - - OnChanCloseConfirm( - ctx sdk.Context, - portId, - channelId string, - ) error - - // OnRecvPacket must return the acknowledgement bytes - // In the case of an asynchronous acknowledgement, nil should be returned. - OnRecvPacket( - ctx sdk.Context, - packet channeltypes.Packet, - ) (*sdk.Result, []byte, error) - - OnAcknowledgementPacket( - ctx sdk.Context, - packet channeltypes.Packet, - acknowledgement []byte, - ) (*sdk.Result, error) - - OnTimeoutPacket( - ctx sdk.Context, - packet channeltypes.Packet, - ) (*sdk.Result, error) -} -``` diff --git a/x/ibc/core/spec/06_events.md b/x/ibc/core/spec/06_events.md deleted file mode 100644 index 8a416217e1fc..000000000000 --- a/x/ibc/core/spec/06_events.md +++ /dev/null @@ -1,241 +0,0 @@ - - -# Events - -The IBC module emits the following events. It can be expected that the type `message`, -with an attirbute key of `action` will represent the first event for each message -being processed as emitted by the SDK's baseapp. Each IBC TAO message will -also emit its module name in the format 'ibc_sub-modulename'. - -All the events for the Channel handshakes, `SendPacket`, `RecvPacket`, `AcknowledgePacket`, -`TimeoutPacket` and `TimeoutOnClose` will emit additional events not specified here due to -callbacks to IBC applications. - -## ICS 02 - Client - -### MsgCreateClient - -| Type | Attribute Key | Attribute Value | -|---------------|------------------|-------------------| -| create_client | client_id | {clientId} | -| create_client | client_type | {clientType} | -| create_client | consensus_height | {consensusHeight} | -| message | action | create_client | -| message | module | ibc_client | - -### MsgUpdateClient - -| Type | Attribute Key | Attribute Value | -|---------------|------------------|-------------------| -| update_client | client_id | {clientId} | -| update_client | client_type | {clientType} | -| update_client | consensus_height | {consensusHeight} | -| update_client | header | {header} | -| message | action | update_client | -| message | module | ibc_client | - -### MsgSubmitMisbehaviour - -| Type | Attribute Key | Attribute Value | -|---------------------|------------------|---------------------| -| client_misbehaviour | client_id | {clientId} | -| client_misbehaviour | client_type | {clientType} | -| client_misbehaviour | consensus_height | {consensusHeight} | -| message | action | client_misbehaviour | -| message | module | evidence | -| message | sender | {senderAddress} | -| submit_evidence | evidence_hash | {evidenceHash} | - -### UpdateClientProposal - -| Type | Attribute Key | Attribute Value | -|------------------------|------------------|-------------------| -| update_client_proposal | client_id | {clientId} | -| update_client_proposal | client_type | {clientType} | -| update_client_proposal | consensus_height | {consensusHeight} | - - - -## ICS 03 - Connection - -### MsgConnectionOpenInit - -| Type | Attribute Key | Attribute Value | -|----------------------|----------------------------|-----------------------------| -| connection_open_init | connection_id | {connectionId} | -| connection_open_init | client_id | {clientId} | -| connection_open_init | counterparty_client_id | {counterparty.clientId} | -| message | action | connection_open_init | -| message | module | ibc_connection | - -### MsgConnectionOpenTry - -| Type | Attribute Key | Attribute Value | -|---------------------|----------------------------|-----------------------------| -| connection_open_try | connection_id | {connectionId} | -| connection_open_try | client_id | {clientId} | -| connection_open_try | counterparty_client_id | {counterparty.clientId | -| connection_open_try | counterparty_connection_id | {counterparty.connectionId} | -| message | action | connection_open_try | -| message | module | ibc_connection | - -### MsgConnectionOpenAck - -| Type | Attribute Key | Attribute Value | -|----------------------|----------------------------|-----------------------------| -| connection_open_ack | connection_id | {connectionId} | -| connection_open_ack | client_id | {clientId} | -| connection_open_ack | counterparty_client_id | {counterparty.clientId} | -| connection_open_ack | counterparty_connection_id | {counterparty.connectionId} | -| message | module | ibc_connection | -| message | action | connection_open_ack | - -### MsgConnectionOpenConfirm - -| Type | Attribute Key | Attribute Value | -|-------------------------|----------------------------|-----------------------------| -| connection_open_confirm | connection_id | {connectionId} | -| connection_open_confirm | client_id | {clientId} | -| connection_open_confirm | counterparty_client_id | {counterparty.clientId} | -| connection_open_confirm | counterparty_connection_id | {counterparty.connectionId} | -| message | action | connection_open_confirm | -| message | module | ibc_connection | - -## ICS 04 - Channel - -### MsgChannelOpenInit - -| Type | Attribute Key | Attribute Value | -|-------------------|-------------------------|----------------------------------| -| channel_open_init | port_id | {portId} | -| channel_open_init | channel_id | {channelId} | -| channel_open_init | counterparty_port_id | {channel.counterparty.portId} | -| channel_open_init | connection_id | {channel.connectionHops} | -| message | action | channel_open_init | -| message | module | ibc_channel | - -### MsgChannelOpenTry - -| Type | Attribute Key | Attribute Value | -|------------------|-------------------------|----------------------------------| -| channel_open_try | port_id | {portId} | -| channel_open_try | channel_id | {channelId} | -| channel_open_try | counterparty_port_id | {channel.counterparty.portId} | -| channel_open_try | counterparty_channel_id | {channel.counterparty.channelId} | -| channel_open_try | connection_id | {channel.connectionHops} | -| message | action | channel_open_try | -| message | module | ibc_channel | - -### MsgChannelOpenAck - -| Type | Attribute Key | Attribute Value | -|------------------|-------------------------|----------------------------------| -| channel_open_ack | port_id | {portId} | -| channel_open_ack | channel_id | {channelId} | -| channel_open_ack | counterparty_port_id | {channel.counterparty.portId} | -| channel_open_ack | counterparty_channel_id | {channel.counterparty.channelId} | -| channel_open_ack | connection_id | {channel.connectionHops} | -| message | action | channel_open_ack | -| message | module | ibc_channel | - -### MsgChannelOpenConfirm - -| Type | Attribute Key | Attribute Value | -|----------------------|-------------------------|----------------------------------| -| channel_open_confirm | port_id | {portId} | -| channel_open_confirm | channel_id | {channelId} | -| channel_open_confirm | counterparty_port_id | {channel.counterparty.portId} | -| channel_open_confirm | counterparty_channel_id | {channel.counterparty.channelId} | -| channel_open_confirm | connection_id | {channel.connectionHops} | -| message | module | ibc_channel | -| message | action | channel_open_confirm | - -### MsgChannelCloseInit - -| Type | Attribute Key | Attribute Value | -|--------------------|-------------------------|----------------------------------| -| channel_close_init | port_id | {portId} | -| channel_close_init | channel_id | {channelId} | -| channel_close_init | counterparty_port_id | {channel.counterparty.portId} | -| channel_close_init | counterparty_channel_id | {channel.counterparty.channelId} | -| channel_close_init | connection_id | {channel.connectionHops} | -| message | action | channel_close_init | -| message | module | ibc_channel | - -### MsgChannelCloseConfirm - -| Type | Attribute Key | Attribute Value | -|-----------------------|-------------------------|----------------------------------| -| channel_close_confirm | port_id | {portId} | -| channel_close_confirm | channel_id | {channelId} | -| channel_close_confirm | counterparty_port_id | {channel.counterparty.portId} | -| channel_close_confirm | counterparty_channel_id | {channel.counterparty.channelId} | -| channel_close_confirm | connection_id | {channel.connectionHops} | -| message | action | channel_close_confirm | -| message | module | ibc_channel | - -### SendPacket (application module call) - -| Type | Attribute Key | Attribute Value | -|-------------|--------------------------|----------------------------------| -| send_packet | packet_data | {data} | -| send_packet | packet_timeout_height | {timeoutHeight} | -| send_packet | packet_timeout_timestamp | {timeoutTimestamp} | -| send_packet | packet_sequence | {sequence} | -| send_packet | packet_src_port | {sourcePort} | -| send_packet | packet_src_channel | {sourceChannel} | -| send_packet | packet_dst_port | {destinationPort} | -| send_packet | packet_dst_channel | {destinationChannel} | -| send_packet | packet_channel_ordering | {channel.Ordering} | -| message | action | application-module-defined-field | -| message | module | ibc-channel | - -### MsgRecvPacket - -| Type | Attribute Key | Attribute Value | -|-------------|--------------------------|----------------------| -| recv_packet | packet_data | {data} | -| recv_packet | packet_ack | {acknowledgement} | -| recv_packet | packet_timeout_height | {timeoutHeight} | -| recv_packet | packet_timeout_timestamp | {timeoutTimestamp} | -| recv_packet | packet_sequence | {sequence} | -| recv_packet | packet_src_port | {sourcePort} | -| recv_packet | packet_src_channel | {sourceChannel} | -| recv_packet | packet_dst_port | {destinationPort} | -| recv_packet | packet_dst_channel | {destinationChannel} | -| recv_packet | packet_channel_ordering | {channel.Ordering} | -| message | action | recv_packet | -| message | module | ibc-channel | - -### MsgAcknowledgePacket - -| Type | Attribute Key | Attribute Value | -|--------------------|--------------------------|----------------------| -| acknowledge_packet | packet_timeout_height | {timeoutHeight} | -| acknowledge_packet | packet_timeout_timestamp | {timeoutTimestamp} | -| acknowledge_packet | packet_sequence | {sequence} | -| acknowledge_packet | packet_src_port | {sourcePort} | -| acknowledge_packet | packet_src_channel | {sourceChannel} | -| acknowledge_packet | packet_dst_port | {destinationPort} | -| acknowledge_packet | packet_dst_channel | {destinationChannel} | -| acknowledge_packet | packet_channel_ordering | {channel.Ordering} | -| message | action | acknowledge_packet | -| message | module | ibc-channel | - -### MsgTimeoutPacket & MsgTimeoutOnClose - -| Type | Attribute Key | Attribute Value | -|----------------|--------------------------|----------------------| -| timeout_packet | packet_timeout_height | {timeoutHeight} | -| timeout_packet | packet_timeout_timestamp | {timeoutTimestamp} | -| timeout_packet | packet_sequence | {sequence} | -| timeout_packet | packet_src_port | {sourcePort} | -| timeout_packet | packet_src_channel | {sourceChannel} | -| timeout_packet | packet_dst_port | {destinationPort} | -| timeout_packet | packet_dst_channel | {destinationChannel} | -| timeout_packet | packet_channel_ordering | {channel.Ordering} | -| message | action | timeout_packet | -| message | module | ibc-channel | - diff --git a/x/ibc/core/spec/07_params.md b/x/ibc/core/spec/07_params.md deleted file mode 100644 index 67e79ef81ddf..000000000000 --- a/x/ibc/core/spec/07_params.md +++ /dev/null @@ -1,21 +0,0 @@ - - -# Parameters - -## Clients - -The ibc clients contain the following parameters: - -| Key | Type | Default Value | -|------------------|------|---------------| -| `AllowedClients` | []string | `"06-solomachine","07-tendermint"` | - -### AllowedClients - -The allowed clients parameter defines an allowlist of client types supported by the chain. A client -that is not registered on this list will fail upon creation or on genesis validation. Note that, -since the client type is an arbitrary string, chains they must not register two light clients which -return the same value for the `ClientType()` function, otherwise the allowlist check can be -bypassed. diff --git a/x/ibc/core/spec/README.md b/x/ibc/core/spec/README.md deleted file mode 100644 index f6de9749b5eb..000000000000 --- a/x/ibc/core/spec/README.md +++ /dev/null @@ -1,26 +0,0 @@ - - -# `ibc core` - -## Abstract - -This paper defines the implementation of the IBC protocol on the Cosmos SDK, the -changes made to the specification and where to find each specific ICS spec within -the module. - -For the general specification please refer to the [Interchain Standards](https://github.com/cosmos/ics). - -## Contents - -1. **[Concepts](01_concepts.md)** -2. **[State](02_state.md)** -3. **[State Transitions](03_state_transitions.md)** -4. **[Messages](04_messages.md)** -5. **[Callbacks](05_callbacks.md)** -6. **[Events](06_events.md)** -7. **[Params](07_params.md)** diff --git a/x/ibc/core/types/codec.go b/x/ibc/core/types/codec.go deleted file mode 100644 index db110ac9d5fd..000000000000 --- a/x/ibc/core/types/codec.go +++ /dev/null @@ -1,23 +0,0 @@ -package types - -import ( - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types" - solomachinetypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/06-solomachine/types" - ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" - localhosttypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/09-localhost/types" -) - -// RegisterInterfaces registers x/ibc interfaces into protobuf Any. -func RegisterInterfaces(registry codectypes.InterfaceRegistry) { - clienttypes.RegisterInterfaces(registry) - connectiontypes.RegisterInterfaces(registry) - channeltypes.RegisterInterfaces(registry) - solomachinetypes.RegisterInterfaces(registry) - ibctmtypes.RegisterInterfaces(registry) - localhosttypes.RegisterInterfaces(registry) - commitmenttypes.RegisterInterfaces(registry) -} diff --git a/x/ibc/core/types/genesis.go b/x/ibc/core/types/genesis.go deleted file mode 100644 index f7d78e5c1140..000000000000 --- a/x/ibc/core/types/genesis.go +++ /dev/null @@ -1,38 +0,0 @@ -package types - -import ( - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" -) - -var _ codectypes.UnpackInterfacesMessage = GenesisState{} - -// DefaultGenesisState returns the ibc module's default genesis state. -func DefaultGenesisState() *GenesisState { - return &GenesisState{ - ClientGenesis: clienttypes.DefaultGenesisState(), - ConnectionGenesis: connectiontypes.DefaultGenesisState(), - ChannelGenesis: channeltypes.DefaultGenesisState(), - } -} - -// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces -func (gs GenesisState) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { - return gs.ClientGenesis.UnpackInterfaces(unpacker) -} - -// Validate performs basic genesis state validation returning an error upon any -// failure. -func (gs *GenesisState) Validate() error { - if err := gs.ClientGenesis.Validate(); err != nil { - return err - } - - if err := gs.ConnectionGenesis.Validate(); err != nil { - return err - } - - return gs.ChannelGenesis.Validate() -} diff --git a/x/ibc/core/types/genesis.pb.go b/x/ibc/core/types/genesis.pb.go deleted file mode 100644 index a6f2b1754052..000000000000 --- a/x/ibc/core/types/genesis.pb.go +++ /dev/null @@ -1,440 +0,0 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: ibc/core/types/v1/genesis.proto - -package types - -import ( - fmt "fmt" - types "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - types1 "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - types2 "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - _ "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 defines the ibc module's genesis state. -type GenesisState struct { - // ICS002 - Clients genesis state - ClientGenesis types.GenesisState `protobuf:"bytes,1,opt,name=client_genesis,json=clientGenesis,proto3" json:"client_genesis" yaml:"client_genesis"` - // ICS003 - Connections genesis state - ConnectionGenesis types1.GenesisState `protobuf:"bytes,2,opt,name=connection_genesis,json=connectionGenesis,proto3" json:"connection_genesis" yaml:"connection_genesis"` - // ICS004 - Channel genesis state - ChannelGenesis types2.GenesisState `protobuf:"bytes,3,opt,name=channel_genesis,json=channelGenesis,proto3" json:"channel_genesis" yaml:"channel_genesis"` -} - -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_b9a49c5663e6fc59, []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) GetClientGenesis() types.GenesisState { - if m != nil { - return m.ClientGenesis - } - return types.GenesisState{} -} - -func (m *GenesisState) GetConnectionGenesis() types1.GenesisState { - if m != nil { - return m.ConnectionGenesis - } - return types1.GenesisState{} -} - -func (m *GenesisState) GetChannelGenesis() types2.GenesisState { - if m != nil { - return m.ChannelGenesis - } - return types2.GenesisState{} -} - -func init() { - proto.RegisterType((*GenesisState)(nil), "ibc.core.types.v1.GenesisState") -} - -func init() { proto.RegisterFile("ibc/core/types/v1/genesis.proto", fileDescriptor_b9a49c5663e6fc59) } - -var fileDescriptor_b9a49c5663e6fc59 = []byte{ - // 316 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x64, 0x92, 0x3d, 0x4e, 0xc3, 0x30, - 0x18, 0x86, 0x93, 0x22, 0x31, 0x04, 0x28, 0x6a, 0x04, 0x08, 0x2a, 0xe1, 0x36, 0x51, 0x07, 0x96, - 0xda, 0x0a, 0x6c, 0x8c, 0x5d, 0xba, 0x87, 0x8d, 0x05, 0x25, 0xc6, 0xa4, 0x86, 0xc4, 0xae, 0x6a, - 0x13, 0xd1, 0x5b, 0x70, 0xac, 0x8e, 0x1d, 0x11, 0x43, 0x85, 0x92, 0x1b, 0x70, 0x02, 0xd4, 0xd8, - 0xe4, 0x47, 0x9e, 0x12, 0xbd, 0x7e, 0xbe, 0xf7, 0xf9, 0x94, 0xd8, 0x19, 0xd1, 0x18, 0x23, 0xcc, - 0x57, 0x04, 0xc9, 0xf5, 0x92, 0x08, 0x94, 0x07, 0x28, 0x21, 0x8c, 0x08, 0x2a, 0xe0, 0x72, 0xc5, - 0x25, 0x77, 0x07, 0x34, 0xc6, 0x70, 0x0f, 0xc0, 0x0a, 0x80, 0x79, 0x30, 0x3c, 0x4b, 0x78, 0xc2, - 0xab, 0x53, 0xb4, 0x7f, 0x53, 0xe0, 0x70, 0x5c, 0x37, 0xe1, 0x94, 0x12, 0x26, 0x8d, 0xaa, 0xe1, - 0xa4, 0x21, 0x38, 0x63, 0x04, 0x4b, 0xca, 0x99, 0x49, 0x79, 0x0d, 0xb5, 0x88, 0x18, 0x23, 0xa9, - 0x81, 0xf8, 0xdf, 0x3d, 0xe7, 0x78, 0xae, 0x92, 0x07, 0x19, 0x49, 0xe2, 0xbe, 0x38, 0x7d, 0x25, - 0x7d, 0xd2, 0xe0, 0xa5, 0x3d, 0xb6, 0x6f, 0x8e, 0x6e, 0xc7, 0xb0, 0xde, 0x5e, 0x9d, 0xc3, 0x3c, - 0x80, 0xed, 0xc9, 0xd9, 0xf5, 0x66, 0x37, 0xb2, 0x7e, 0x77, 0xa3, 0xf3, 0x75, 0x94, 0xa5, 0xf7, - 0x7e, 0xb7, 0xc5, 0x0f, 0x4f, 0x54, 0xa0, 0x47, 0xdc, 0xdc, 0x71, 0x9b, 0xd5, 0x6b, 0x57, 0xaf, - 0x72, 0x4d, 0x5a, 0xae, 0x9a, 0x31, 0x7c, 0x9e, 0xf6, 0x5d, 0x69, 0x9f, 0xd1, 0xe6, 0x87, 0x83, - 0x26, 0xfc, 0xf7, 0xbe, 0x3a, 0xa7, 0xfa, 0x63, 0xd4, 0xd2, 0x83, 0x4a, 0xea, 0xb5, 0xa4, 0x0a, - 0x30, 0x8c, 0x40, 0x1b, 0x2f, 0xb4, 0xb1, 0xdb, 0xe3, 0x87, 0x7d, 0x9d, 0xe8, 0xa1, 0xd9, 0x7c, - 0x53, 0x00, 0x7b, 0x5b, 0x00, 0xfb, 0xa7, 0x00, 0xf6, 0x67, 0x09, 0xac, 0x6d, 0x09, 0xac, 0xaf, - 0x12, 0x58, 0x8f, 0xd3, 0x84, 0xca, 0xc5, 0x7b, 0x0c, 0x31, 0xcf, 0x10, 0xe6, 0x22, 0xe3, 0x42, - 0x3f, 0xa6, 0xe2, 0xf9, 0x0d, 0x7d, 0xa0, 0xee, 0x55, 0x8a, 0x0f, 0xab, 0x9f, 0x75, 0xf7, 0x17, - 0x00, 0x00, 0xff, 0xff, 0x90, 0x81, 0x26, 0xd1, 0x63, 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 - { - size, err := m.ChannelGenesis.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintGenesis(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - { - size, err := m.ConnectionGenesis.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintGenesis(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - { - size, err := m.ClientGenesis.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 - l = m.ClientGenesis.Size() - n += 1 + l + sovGenesis(uint64(l)) - l = m.ConnectionGenesis.Size() - n += 1 + l + sovGenesis(uint64(l)) - l = m.ChannelGenesis.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 ClientGenesis", 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 := m.ClientGenesis.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ConnectionGenesis", 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 := m.ConnectionGenesis.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ChannelGenesis", 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 := m.ChannelGenesis.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/ibc/core/types/query.go b/x/ibc/core/types/query.go deleted file mode 100644 index fba69b3a1979..000000000000 --- a/x/ibc/core/types/query.go +++ /dev/null @@ -1,26 +0,0 @@ -package types - -import ( - "github.com/gogo/protobuf/grpc" - - client "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - connection "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection" - connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - channel "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" -) - -// QueryServer defines the IBC interfaces that the gRPC query server must implement -type QueryServer interface { - clienttypes.QueryServer - connectiontypes.QueryServer - channeltypes.QueryServer -} - -// RegisterQueryService registers each individual IBC submodule query service -func RegisterQueryService(server grpc.Server, queryService QueryServer) { - client.RegisterQueryService(server, queryService) - connection.RegisterQueryService(server, queryService) - channel.RegisterQueryService(server, queryService) -} diff --git a/x/ibc/light-clients/06-solomachine/doc.go b/x/ibc/light-clients/06-solomachine/doc.go deleted file mode 100644 index 3673f3c3dc08..000000000000 --- a/x/ibc/light-clients/06-solomachine/doc.go +++ /dev/null @@ -1,7 +0,0 @@ -/* -Package solomachine implements a concrete `ConsensusState`, `Header`, -`Misbehaviour` and `Equivocation` types for the Solo Machine light client. -This implementation is based off the ICS 06 specification: -https://github.com/cosmos/ics/tree/master/spec/ics-006-solo-machine-client -*/ -package solomachine diff --git a/x/ibc/light-clients/06-solomachine/module.go b/x/ibc/light-clients/06-solomachine/module.go deleted file mode 100644 index bafbd0152f1c..000000000000 --- a/x/ibc/light-clients/06-solomachine/module.go +++ /dev/null @@ -1,10 +0,0 @@ -package solomachine - -import ( - "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/06-solomachine/types" -) - -// Name returns the solo machine client name. -func Name() string { - return types.SubModuleName -} diff --git a/x/ibc/light-clients/06-solomachine/spec/01_concepts.md b/x/ibc/light-clients/06-solomachine/spec/01_concepts.md deleted file mode 100644 index de486b71b1a8..000000000000 --- a/x/ibc/light-clients/06-solomachine/spec/01_concepts.md +++ /dev/null @@ -1,160 +0,0 @@ - - -# Concepts - -## Client State - -The `ClientState` for a solo machine light client stores the latest sequence, the frozen sequence, -the latest consensus state, and client flag indicating if the client should be allowed to be updated -after a governance proposal. - -If the client is not frozen then the frozen sequence is 0. - -## Consensus State - -The consensus states stores the public key, diversifier, and timestamp of the solo machine light client. - -The diversifier is used to prevent accidental misbehaviour if the same public key is used across -different chains with the same client identifier. It should be unique to the chain the light client -is used on. - -## Public Key - -The public key can be a single public key or a multi-signature public key. The public key type used -must fulfill the tendermint public key interface (this will become the SDK public key interface in the -near future). The public key must be registered on the application codec otherwise encoding/decoding -errors will arise. The public key stored in the consensus state is represented as a protobuf `Any`. -This allows for flexibility in what other public key types can be supported in the future. - -## Counterparty Verification - -The solo machine light client can verify counterparty client state, consensus state, connection state, -channel state, packet commitments, packet acknowledgements, packet receipt absence, -and the next sequence receive. At the end of each successful verification call the light -client sequence number will be incremented. - -Successful verification requires the current public key to sign over the proof. - -## Proofs - -A solo machine proof should verify that the solomachine public key signed -over some specified data. The format for generating marshaled proofs for -the SDK's implementation of solo machine is as follows: - -1. Construct the data using the associated protobuf definition and marshal it. - -For example: - -```go -data := &ClientStateData{ - Path: []byte(path.String()), - ClientState: any, -} - -dataBz, err := cdc.MarshalBinaryBare(data) -``` - -The helper functions `...DataBytes()` in [proofs.go](../types/proofs.go) handle this -functionality. - -2. Construct the `SignBytes` and marshal it. - -For example: - -```go -signBytes := &SignBytes{ - Sequence: sequence, - Timestamp: timestamp, - Diversifier: diversifier, - DataType: CLIENT, - Data: dataBz, -} - -signBz, err := cdc.MarshalBinaryBare(signBytes) -``` - -The helper functions `...SignBytes()` in [proofs.go](../types/proofs.go) handle this functionality. -The `DataType` field is used to disambiguate what type of data was signed to prevent potential -proto encoding overlap. - -3. Sign the sign bytes. Embed the signatures into either `SingleSignatureData` or `MultiSignatureData`. -Convert the `SignatureData` to proto and marshal it. - -For example: - -```go -sig, err := key.Sign(signBz) -sigData := &signing.SingleSignatureData{ - Signature: sig, -} - -protoSigData := signing.SignatureDataToProto(sigData) -bz, err := cdc.MarshalBinaryBare(protoSigData) -``` - -4. Construct a `TimestampedSignatureData` and marshal it. The marshaled result can be passed in -as the proof parameter to the verification functions. - -For example: - -```go -timestampedSignatureData := &types.TimestampedSignatureData{ - SignatureData: sigData, - Timestamp: solomachine.Time, -} - -proof, err := cdc.MarshalBinaryBare(timestampedSignatureData) -``` - -## Updates By Header - -An update by a header will only succeed if: - -- the header provided is parseable to solo machine header -- the header sequence matches the current sequence -- the header timestamp is greater than or equal to the consensus state timestamp -- the currently registered public key generated the proof - -If the update is successful: - -- the public key is updated -- the diversifier is updated -- the timestamp is updated -- the sequence is incremented by 1 -- the new consensus state is set in the client state - -## Updates By Proposal - -An update by a governance proposal will only succeed if: - -- the substitute provided is parseable to solo machine client state -- the `AllowUpdateAfterProposal` client parameter is set to `true` -- the new consensus state public key does not equal the current consensus state public key - -If the update is successful: - -- 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 - -Misbehaviour handling will only succeed if: - -- the misbehaviour provided is parseable to solo machine misbehaviour -- the client is not already frozen -- the current public key signed over two unique data messages at the same sequence and diversifier. - -If the misbehaviour is successfully processed: - -- the client is frozen by setting the frozen sequence to the misbehaviour sequence - -NOTE: Misbehaviour processing is data processing order dependent. A misbehaving solo machine -could update to a new public key to prevent being frozen before misbehaviour is submitted. - -## Upgrades - -Upgrades to solo machine light clients are not supported since an entirely different type of -public key can be set using normal client updates. diff --git a/x/ibc/light-clients/06-solomachine/spec/02_state.md b/x/ibc/light-clients/06-solomachine/spec/02_state.md deleted file mode 100644 index a9ff4ea5b47c..000000000000 --- a/x/ibc/light-clients/06-solomachine/spec/02_state.md +++ /dev/null @@ -1,12 +0,0 @@ - - -# State - -The solo machine light client will only store consensus states for each update by a header -or a governance proposal. The latest client state is also maintained in the store. - -These values can be found under the light client paths defined in the IBC -[core store specs](../../../core/spec/02_state.md). - 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 deleted file mode 100644 index 48a1e18f1c90..000000000000 --- a/x/ibc/light-clients/06-solomachine/spec/03_state_transitions.md +++ /dev/null @@ -1,39 +0,0 @@ - - -# State Transitions - -## Client State Verification Functions - -Successful state verification by a solo machine light client will result in: - -- the sequence being incremented by 1. - -## Update By Header - -A successful update of a solo machine light client by a header 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 incremented by 1 -- the consensus state being updated (consensus state stores the public key, diversifier, and timestamp) - -## Update By Governance Proposal - -A successful update of a solo machine light client by a governance proposal will result in: - -- 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 - -Client udgrades are not supported for the solo machine light client. No state transition occurs. - -## Misbehaviour - -Successful misbehaviour processing of a solo machine light client will result in: - -- the frozen sequence being set to the sequence the misbehaviour occurred at diff --git a/x/ibc/light-clients/06-solomachine/spec/04_messages.md b/x/ibc/light-clients/06-solomachine/spec/04_messages.md deleted file mode 100644 index 465ea6229a77..000000000000 --- a/x/ibc/light-clients/06-solomachine/spec/04_messages.md +++ /dev/null @@ -1,8 +0,0 @@ - - -# Messages - -The messages used to initialize a solo machine light client are defined in the -core sub-module [02-client](../../../core/spec/04_messages.md). diff --git a/x/ibc/light-clients/06-solomachine/spec/README.md b/x/ibc/light-clients/06-solomachine/spec/README.md deleted file mode 100644 index 77db1bfeee14..000000000000 --- a/x/ibc/light-clients/06-solomachine/spec/README.md +++ /dev/null @@ -1,26 +0,0 @@ - - -# `solomachine` - -## Abstract - -This paper defines the implementation of the ICS06 protocol on the Cosmos SDK. For the general -specification please refer to the [ICS06 Specification](https://github.com/cosmos/ics/tree/master/spec/ics-006-solo-machine-client). - -This implementation of a solo machine light client supports single and multi-signature public -keys. The client is capable of handling public key updates by header and governance proposals. -The light client is capable of processing client misbehaviour. Proofs of the counterparty state -are generated by the solo machine client by signing over the desired state with a certain sequence, -diversifier, and timestamp. - -## Contents - -1. **[Concepts](01_concepts.md)** -2. **[State](02_state.md)** -3. **[State Transitions](03_state_transitions.md)** -4. **[Messages](04_messages.md)** diff --git a/x/ibc/light-clients/06-solomachine/types/client_state.go b/x/ibc/light-clients/06-solomachine/types/client_state.go deleted file mode 100644 index 24a6582f0f23..000000000000 --- a/x/ibc/light-clients/06-solomachine/types/client_state.go +++ /dev/null @@ -1,491 +0,0 @@ -package types - -import ( - "reflect" - - ics23 "github.com/confio/ics23/go" - - "github.com/cosmos/cosmos-sdk/codec" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/cosmos/cosmos-sdk/types/tx/signing" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -var _ exported.ClientState = (*ClientState)(nil) - -// NewClientState creates a new ClientState instance. -func NewClientState(latestSequence uint64, consensusState *ConsensusState, allowUpdateAfterProposal bool) *ClientState { - return &ClientState{ - Sequence: latestSequence, - FrozenSequence: 0, - ConsensusState: consensusState, - AllowUpdateAfterProposal: allowUpdateAfterProposal, - } -} - -// ClientType is Solo Machine. -func (cs ClientState) ClientType() string { - return exported.Solomachine -} - -// GetLatestHeight returns the latest sequence number. -// Return exported.Height to satisfy ClientState interface -// Revision number is always 0 for a solo-machine. -func (cs ClientState) GetLatestHeight() exported.Height { - return clienttypes.NewHeight(0, cs.Sequence) -} - -// IsFrozen returns true if the client is frozen. -func (cs ClientState) IsFrozen() bool { - return cs.FrozenSequence != 0 -} - -// GetFrozenHeight returns the frozen sequence of the client. -// Return exported.Height to satisfy interface -// Revision number is always 0 for a solo-machine -func (cs ClientState) GetFrozenHeight() exported.Height { - return clienttypes.NewHeight(0, cs.FrozenSequence) -} - -// GetProofSpecs returns nil proof specs since client state verification uses signatures. -func (cs ClientState) GetProofSpecs() []*ics23.ProofSpec { - return nil -} - -// Validate performs basic validation of the client state fields. -func (cs ClientState) Validate() error { - if cs.Sequence == 0 { - return sdkerrors.Wrap(clienttypes.ErrInvalidClient, "sequence cannot be 0") - } - if cs.ConsensusState == nil { - return sdkerrors.Wrap(clienttypes.ErrInvalidConsensus, "consensus state cannot be nil") - } - return cs.ConsensusState.ValidateBasic() -} - -// ZeroCustomFields returns solomachine client state with client-specific fields FrozenSequence, -// and AllowUpdateAfterProposal zeroed out -func (cs ClientState) ZeroCustomFields() exported.ClientState { - return NewClientState( - cs.Sequence, cs.ConsensusState, false, - ) -} - -// Initialize will check that initial consensus state is equal to the latest consensus state of the initial client. -func (cs ClientState) Initialize(_ sdk.Context, _ codec.BinaryMarshaler, _ sdk.KVStore, consState exported.ConsensusState) error { - if !reflect.DeepEqual(cs.ConsensusState, consState) { - return sdkerrors.Wrapf(clienttypes.ErrInvalidConsensus, "consensus state in initial client does not equal initial consensus state. expected: %s, got: %s", - cs.ConsensusState, consState) - } - return nil -} - -// ExportMetadata is a no-op since solomachine does not store any metadata in client store -func (cs ClientState) ExportMetadata(_ sdk.KVStore) []exported.GenesisMetadata { - return nil -} - -// VerifyUpgradeAndUpdateState returns an error since solomachine client does not support upgrades -func (cs ClientState) VerifyUpgradeAndUpdateState( - _ sdk.Context, _ codec.BinaryMarshaler, _ sdk.KVStore, - _ exported.ClientState, _ exported.ConsensusState, _, _ []byte, -) (exported.ClientState, exported.ConsensusState, error) { - return nil, nil, sdkerrors.Wrap(clienttypes.ErrInvalidUpgradeClient, "cannot upgrade solomachine client") -} - -// VerifyClientState verifies a proof of the client state of the running chain -// stored on the solo machine. -func (cs ClientState) VerifyClientState( - store sdk.KVStore, - cdc codec.BinaryMarshaler, - height exported.Height, - prefix exported.Prefix, - counterpartyClientIdentifier string, - proof []byte, - clientState exported.ClientState, -) error { - publicKey, sigData, timestamp, sequence, err := produceVerificationArgs(cdc, cs, height, prefix, proof) - if err != nil { - return err - } - - clientPrefixedPath := commitmenttypes.NewMerklePath(host.FullClientStatePath(counterpartyClientIdentifier)) - path, err := commitmenttypes.ApplyPrefix(prefix, clientPrefixedPath) - if err != nil { - return err - } - - signBz, err := ClientStateSignBytes(cdc, sequence, timestamp, cs.ConsensusState.Diversifier, path, clientState) - if err != nil { - return err - } - - if err := VerifySignature(publicKey, signBz, sigData); err != nil { - return err - } - - cs.Sequence++ - cs.ConsensusState.Timestamp = timestamp - setClientState(store, cdc, &cs) - return nil -} - -// VerifyClientConsensusState verifies a proof of the consensus state of the -// running chain stored on the solo machine. -func (cs ClientState) VerifyClientConsensusState( - store sdk.KVStore, - cdc codec.BinaryMarshaler, - height exported.Height, - counterpartyClientIdentifier string, - consensusHeight exported.Height, - prefix exported.Prefix, - proof []byte, - consensusState exported.ConsensusState, -) error { - publicKey, sigData, timestamp, sequence, err := produceVerificationArgs(cdc, cs, height, prefix, proof) - if err != nil { - return err - } - - clientPrefixedPath := commitmenttypes.NewMerklePath(host.FullConsensusStatePath(counterpartyClientIdentifier, consensusHeight)) - path, err := commitmenttypes.ApplyPrefix(prefix, clientPrefixedPath) - if err != nil { - return err - } - - signBz, err := ConsensusStateSignBytes(cdc, sequence, timestamp, cs.ConsensusState.Diversifier, path, consensusState) - if err != nil { - return err - } - - if err := VerifySignature(publicKey, signBz, sigData); err != nil { - return err - } - - cs.Sequence++ - cs.ConsensusState.Timestamp = timestamp - setClientState(store, cdc, &cs) - return nil -} - -// VerifyConnectionState verifies a proof of the connection state of the -// specified connection end stored on the target machine. -func (cs ClientState) VerifyConnectionState( - store sdk.KVStore, - cdc codec.BinaryMarshaler, - height exported.Height, - prefix exported.Prefix, - proof []byte, - connectionID string, - connectionEnd exported.ConnectionI, -) error { - publicKey, sigData, timestamp, sequence, err := produceVerificationArgs(cdc, cs, height, prefix, proof) - if err != nil { - return err - } - - connectionPath := commitmenttypes.NewMerklePath(host.ConnectionPath(connectionID)) - path, err := commitmenttypes.ApplyPrefix(prefix, connectionPath) - if err != nil { - return err - } - - signBz, err := ConnectionStateSignBytes(cdc, sequence, timestamp, cs.ConsensusState.Diversifier, path, connectionEnd) - if err != nil { - return err - } - - if err := VerifySignature(publicKey, signBz, sigData); err != nil { - return err - } - - cs.Sequence++ - cs.ConsensusState.Timestamp = timestamp - setClientState(store, cdc, &cs) - return nil -} - -// VerifyChannelState verifies a proof of the channel state of the specified -// channel end, under the specified port, stored on the target machine. -func (cs ClientState) VerifyChannelState( - store sdk.KVStore, - cdc codec.BinaryMarshaler, - height exported.Height, - prefix exported.Prefix, - proof []byte, - portID, - channelID string, - channel exported.ChannelI, -) error { - publicKey, sigData, timestamp, sequence, err := produceVerificationArgs(cdc, cs, height, prefix, proof) - if err != nil { - return err - } - - channelPath := commitmenttypes.NewMerklePath(host.ChannelPath(portID, channelID)) - path, err := commitmenttypes.ApplyPrefix(prefix, channelPath) - if err != nil { - return err - } - - signBz, err := ChannelStateSignBytes(cdc, sequence, timestamp, cs.ConsensusState.Diversifier, path, channel) - if err != nil { - return err - } - - if err := VerifySignature(publicKey, signBz, sigData); err != nil { - return err - } - - cs.Sequence++ - cs.ConsensusState.Timestamp = timestamp - setClientState(store, cdc, &cs) - return nil -} - -// VerifyPacketCommitment verifies a proof of an outgoing packet commitment at -// the specified port, specified channel, and specified sequence. -func (cs ClientState) VerifyPacketCommitment( - store sdk.KVStore, - cdc codec.BinaryMarshaler, - height exported.Height, - _ uint64, - _ uint64, - prefix exported.Prefix, - proof []byte, - portID, - channelID string, - packetSequence uint64, - commitmentBytes []byte, -) error { - publicKey, sigData, timestamp, sequence, err := produceVerificationArgs(cdc, cs, height, prefix, proof) - if err != nil { - return err - } - - commitmentPath := commitmenttypes.NewMerklePath(host.PacketCommitmentPath(portID, channelID, packetSequence)) - path, err := commitmenttypes.ApplyPrefix(prefix, commitmentPath) - if err != nil { - return err - } - - signBz, err := PacketCommitmentSignBytes(cdc, sequence, timestamp, cs.ConsensusState.Diversifier, path, commitmentBytes) - if err != nil { - return err - } - - if err := VerifySignature(publicKey, signBz, sigData); err != nil { - return err - } - - cs.Sequence++ - cs.ConsensusState.Timestamp = timestamp - setClientState(store, cdc, &cs) - return nil -} - -// VerifyPacketAcknowledgement verifies a proof of an incoming packet -// acknowledgement at the specified port, specified channel, and specified sequence. -func (cs ClientState) VerifyPacketAcknowledgement( - store sdk.KVStore, - cdc codec.BinaryMarshaler, - height exported.Height, - _ uint64, - _ uint64, - prefix exported.Prefix, - proof []byte, - portID, - channelID string, - packetSequence uint64, - acknowledgement []byte, -) error { - publicKey, sigData, timestamp, sequence, err := produceVerificationArgs(cdc, cs, height, prefix, proof) - if err != nil { - return err - } - - ackPath := commitmenttypes.NewMerklePath(host.PacketAcknowledgementPath(portID, channelID, packetSequence)) - path, err := commitmenttypes.ApplyPrefix(prefix, ackPath) - if err != nil { - return err - } - - signBz, err := PacketAcknowledgementSignBytes(cdc, sequence, timestamp, cs.ConsensusState.Diversifier, path, acknowledgement) - if err != nil { - return err - } - - if err := VerifySignature(publicKey, signBz, sigData); err != nil { - return err - } - - cs.Sequence++ - cs.ConsensusState.Timestamp = timestamp - setClientState(store, cdc, &cs) - return nil -} - -// VerifyPacketReceiptAbsence verifies a proof of the absence of an -// incoming packet receipt at the specified port, specified channel, and -// specified sequence. -func (cs ClientState) VerifyPacketReceiptAbsence( - store sdk.KVStore, - cdc codec.BinaryMarshaler, - height exported.Height, - _ uint64, - _ uint64, - prefix exported.Prefix, - proof []byte, - portID, - channelID string, - packetSequence uint64, -) error { - publicKey, sigData, timestamp, sequence, err := produceVerificationArgs(cdc, cs, height, prefix, proof) - if err != nil { - return err - } - - receiptPath := commitmenttypes.NewMerklePath(host.PacketReceiptPath(portID, channelID, packetSequence)) - path, err := commitmenttypes.ApplyPrefix(prefix, receiptPath) - if err != nil { - return err - } - - signBz, err := PacketReceiptAbsenceSignBytes(cdc, sequence, timestamp, cs.ConsensusState.Diversifier, path) - if err != nil { - return err - } - - if err := VerifySignature(publicKey, signBz, sigData); err != nil { - return err - } - - cs.Sequence++ - cs.ConsensusState.Timestamp = timestamp - setClientState(store, cdc, &cs) - return nil -} - -// VerifyNextSequenceRecv verifies a proof of the next sequence number to be -// received of the specified channel at the specified port. -func (cs ClientState) VerifyNextSequenceRecv( - store sdk.KVStore, - cdc codec.BinaryMarshaler, - height exported.Height, - _ uint64, - _ uint64, - prefix exported.Prefix, - proof []byte, - portID, - channelID string, - nextSequenceRecv uint64, -) error { - publicKey, sigData, timestamp, sequence, err := produceVerificationArgs(cdc, cs, height, prefix, proof) - if err != nil { - return err - } - - nextSequenceRecvPath := commitmenttypes.NewMerklePath(host.NextSequenceRecvPath(portID, channelID)) - path, err := commitmenttypes.ApplyPrefix(prefix, nextSequenceRecvPath) - if err != nil { - return err - } - - signBz, err := NextSequenceRecvSignBytes(cdc, sequence, timestamp, cs.ConsensusState.Diversifier, path, nextSequenceRecv) - if err != nil { - return err - } - - if err := VerifySignature(publicKey, signBz, sigData); err != nil { - return err - } - - cs.Sequence++ - cs.ConsensusState.Timestamp = timestamp - setClientState(store, cdc, &cs) - return nil -} - -// produceVerificationArgs perfoms the basic checks on the arguments that are -// shared between the verification functions and returns the public key of the -// consensus state, the unmarshalled proof representing the signature and timestamp -// along with the solo-machine sequence encoded in the proofHeight. -func produceVerificationArgs( - cdc codec.BinaryMarshaler, - cs ClientState, - height exported.Height, - prefix exported.Prefix, - proof []byte, -) (cryptotypes.PubKey, signing.SignatureData, uint64, uint64, error) { - if revision := height.GetRevisionNumber(); revision != 0 { - return nil, nil, 0, 0, sdkerrors.Wrapf(sdkerrors.ErrInvalidHeight, "revision must be 0 for solomachine, got revision-number: %d", revision) - } - // sequence is encoded in the revision height of height struct - sequence := height.GetRevisionHeight() - if cs.IsFrozen() { - return nil, nil, 0, 0, clienttypes.ErrClientFrozen - } - - if prefix == nil { - return nil, nil, 0, 0, sdkerrors.Wrap(commitmenttypes.ErrInvalidPrefix, "prefix cannot be empty") - } - - _, ok := prefix.(commitmenttypes.MerklePrefix) - if !ok { - return nil, nil, 0, 0, sdkerrors.Wrapf(commitmenttypes.ErrInvalidPrefix, "invalid prefix type %T, expected MerklePrefix", prefix) - } - - if proof == nil { - return nil, nil, 0, 0, sdkerrors.Wrap(ErrInvalidProof, "proof cannot be empty") - } - - timestampedSigData := &TimestampedSignatureData{} - if err := cdc.UnmarshalBinaryBare(proof, timestampedSigData); err != nil { - return nil, nil, 0, 0, sdkerrors.Wrapf(err, "failed to unmarshal proof into type %T", timestampedSigData) - } - - timestamp := timestampedSigData.Timestamp - - if len(timestampedSigData.SignatureData) == 0 { - return nil, nil, 0, 0, sdkerrors.Wrap(ErrInvalidProof, "signature data cannot be empty") - } - - sigData, err := UnmarshalSignatureData(cdc, timestampedSigData.SignatureData) - if err != nil { - return nil, nil, 0, 0, err - } - - if cs.ConsensusState == nil { - return nil, nil, 0, 0, sdkerrors.Wrap(clienttypes.ErrInvalidConsensus, "consensus state cannot be empty") - } - - latestSequence := cs.GetLatestHeight().GetRevisionHeight() - if latestSequence != sequence { - return nil, nil, 0, 0, sdkerrors.Wrapf( - sdkerrors.ErrInvalidHeight, - "client state sequence != proof sequence (%d != %d)", latestSequence, sequence, - ) - } - - if cs.ConsensusState.GetTimestamp() > timestamp { - return nil, nil, 0, 0, sdkerrors.Wrapf(ErrInvalidProof, "the consensus state timestamp is greater than the signature timestamp (%d >= %d)", cs.ConsensusState.GetTimestamp(), timestamp) - } - - publicKey, err := cs.ConsensusState.GetPubKey() - if err != nil { - return nil, nil, 0, 0, err - } - - return publicKey, sigData, timestamp, sequence, nil -} - -// sets the client state to the store -func setClientState(store sdk.KVStore, cdc codec.BinaryMarshaler, clientState exported.ClientState) { - bz := clienttypes.MustMarshalClientState(cdc, clientState) - store.Set([]byte(host.KeyClientState), bz) -} diff --git a/x/ibc/light-clients/06-solomachine/types/client_state_test.go b/x/ibc/light-clients/06-solomachine/types/client_state_test.go deleted file mode 100644 index 4f6c195c898e..000000000000 --- a/x/ibc/light-clients/06-solomachine/types/client_state_test.go +++ /dev/null @@ -1,912 +0,0 @@ -package types_test - -import ( - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/06-solomachine/types" - ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" -) - -const ( - counterpartyClientIdentifier = "chainA" - testConnectionID = "connectionid" - testChannelID = "testchannelid" - testPortID = "testportid" -) - -var ( - prefix = commitmenttypes.NewMerklePrefix([]byte("ibc")) - consensusHeight = clienttypes.ZeroHeight() -) - -func (suite *SoloMachineTestSuite) TestClientStateValidateBasic() { - // test singlesig and multisig public keys - for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} { - - testCases := []struct { - name string - clientState *types.ClientState - expPass bool - }{ - { - "valid client state", - solomachine.ClientState(), - true, - }, - { - "empty ClientState", - &types.ClientState{}, - false, - }, - { - "sequence is zero", - types.NewClientState(0, &types.ConsensusState{solomachine.ConsensusState().PublicKey, solomachine.Diversifier, solomachine.Time}, false), - false, - }, - { - "timestamp is zero", - types.NewClientState(1, &types.ConsensusState{solomachine.ConsensusState().PublicKey, solomachine.Diversifier, 0}, false), - false, - }, - { - "diversifier is blank", - types.NewClientState(1, &types.ConsensusState{solomachine.ConsensusState().PublicKey, " ", 1}, false), - false, - }, - { - "pubkey is empty", - types.NewClientState(1, &types.ConsensusState{nil, solomachine.Diversifier, solomachine.Time}, false), - false, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - - err := tc.clientState.Validate() - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } - } -} - -func (suite *SoloMachineTestSuite) TestInitialize() { - // test singlesig and multisig public keys - for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} { - malleatedConsensus := solomachine.ClientState().ConsensusState - malleatedConsensus.Timestamp = malleatedConsensus.Timestamp + 10 - - testCases := []struct { - name string - consState exported.ConsensusState - expPass bool - }{ - { - "valid consensus state", - solomachine.ConsensusState(), - true, - }, - { - "nil consensus state", - nil, - false, - }, - { - "invalid consensus state: Tendermint consensus state", - &ibctmtypes.ConsensusState{}, - false, - }, - { - "invalid consensus state: consensus state does not match consensus state in client", - malleatedConsensus, - false, - }, - } - - for _, tc := range testCases { - err := solomachine.ClientState().Initialize( - suite.chainA.GetContext(), suite.chainA.Codec, - suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), "solomachine"), - tc.consState, - ) - - if tc.expPass { - suite.Require().NoError(err, "valid testcase: %s failed", tc.name) - } else { - suite.Require().Error(err, "invalid testcase: %s passed", tc.name) - } - } - } -} - -func (suite *SoloMachineTestSuite) TestVerifyClientState() { - // create client for tendermint so we can use client state for verification - clientA, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - clientState := suite.chainA.GetClientState(clientA) - path := suite.solomachine.GetClientStatePath(counterpartyClientIdentifier) - - // test singlesig and multisig public keys - for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} { - - value, err := types.ClientStateSignBytes(suite.chainA.Codec, solomachine.Sequence, solomachine.Time, solomachine.Diversifier, path, clientState) - suite.Require().NoError(err) - - sig := solomachine.GenerateSignature(value) - - signatureDoc := &types.TimestampedSignatureData{ - SignatureData: sig, - Timestamp: solomachine.Time, - } - - proof, err := suite.chainA.Codec.MarshalBinaryBare(signatureDoc) - suite.Require().NoError(err) - - testCases := []struct { - name string - clientState *types.ClientState - prefix exported.Prefix - proof []byte - expPass bool - }{ - { - "successful verification", - solomachine.ClientState(), - prefix, - proof, - true, - }, - { - "ApplyPrefix failed", - solomachine.ClientState(), - nil, - proof, - false, - }, - { - "client is frozen", - &types.ClientState{ - Sequence: 1, - FrozenSequence: 1, - ConsensusState: solomachine.ConsensusState(), - AllowUpdateAfterProposal: false, - }, - prefix, - proof, - false, - }, - { - "consensus state in client state is nil", - types.NewClientState(1, nil, false), - prefix, - proof, - false, - }, - { - "client state latest height is less than sequence", - types.NewClientState(solomachine.Sequence-1, - &types.ConsensusState{ - Timestamp: solomachine.Time, - PublicKey: solomachine.ConsensusState().PublicKey, - }, false), - prefix, - proof, - false, - }, - { - "consensus state timestamp is greater than signature", - types.NewClientState(solomachine.Sequence, - &types.ConsensusState{ - Timestamp: solomachine.Time + 1, - PublicKey: solomachine.ConsensusState().PublicKey, - }, false), - prefix, - proof, - false, - }, - - { - "proof is nil", - solomachine.ClientState(), - prefix, - nil, - false, - }, - { - "proof verification failed", - solomachine.ClientState(), - prefix, - suite.GetInvalidProof(), - false, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - - var expSeq uint64 - if tc.clientState.ConsensusState != nil { - expSeq = tc.clientState.Sequence + 1 - } - - err := tc.clientState.VerifyClientState( - suite.store, suite.chainA.Codec, solomachine.GetHeight(), tc.prefix, counterpartyClientIdentifier, tc.proof, clientState, - ) - - if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(expSeq, suite.GetSequenceFromStore(), "sequence not updated in the store (%d) on valid test case %s", suite.GetSequenceFromStore(), tc.name) - } else { - suite.Require().Error(err) - } - }) - } - } -} - -func (suite *SoloMachineTestSuite) TestVerifyClientConsensusState() { - // create client for tendermint so we can use consensus state for verification - clientA, _ := suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - clientState := suite.chainA.GetClientState(clientA) - consensusState, found := suite.chainA.GetConsensusState(clientA, clientState.GetLatestHeight()) - suite.Require().True(found) - - path := suite.solomachine.GetConsensusStatePath(counterpartyClientIdentifier, consensusHeight) - - // test singlesig and multisig public keys - for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} { - - value, err := types.ConsensusStateSignBytes(suite.chainA.Codec, solomachine.Sequence, solomachine.Time, solomachine.Diversifier, path, consensusState) - suite.Require().NoError(err) - - sig := solomachine.GenerateSignature(value) - signatureDoc := &types.TimestampedSignatureData{ - SignatureData: sig, - Timestamp: solomachine.Time, - } - - proof, err := suite.chainA.Codec.MarshalBinaryBare(signatureDoc) - suite.Require().NoError(err) - - testCases := []struct { - name string - clientState *types.ClientState - prefix exported.Prefix - proof []byte - expPass bool - }{ - { - "successful verification", - solomachine.ClientState(), - prefix, - proof, - true, - }, - { - "ApplyPrefix failed", - solomachine.ClientState(), - nil, - proof, - false, - }, - { - "client is frozen", - &types.ClientState{ - Sequence: 1, - FrozenSequence: 1, - ConsensusState: solomachine.ConsensusState(), - AllowUpdateAfterProposal: false, - }, - prefix, - proof, - false, - }, - { - "consensus state in client state is nil", - types.NewClientState(1, nil, false), - prefix, - proof, - false, - }, - { - "client state latest height is less than sequence", - types.NewClientState(solomachine.Sequence-1, - &types.ConsensusState{ - Timestamp: solomachine.Time, - PublicKey: solomachine.ConsensusState().PublicKey, - }, false), - prefix, - proof, - false, - }, - { - "consensus state timestamp is greater than signature", - types.NewClientState(solomachine.Sequence, - &types.ConsensusState{ - Timestamp: solomachine.Time + 1, - PublicKey: solomachine.ConsensusState().PublicKey, - }, false), - prefix, - proof, - false, - }, - - { - "proof is nil", - solomachine.ClientState(), - prefix, - nil, - false, - }, - { - "proof verification failed", - solomachine.ClientState(), - prefix, - suite.GetInvalidProof(), - false, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - - var expSeq uint64 - if tc.clientState.ConsensusState != nil { - expSeq = tc.clientState.Sequence + 1 - } - - err := tc.clientState.VerifyClientConsensusState( - suite.store, suite.chainA.Codec, solomachine.GetHeight(), counterpartyClientIdentifier, consensusHeight, tc.prefix, tc.proof, consensusState, - ) - - if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(expSeq, suite.GetSequenceFromStore(), "sequence not updated in the store (%d) on valid test case %s", suite.GetSequenceFromStore(), tc.name) - } else { - suite.Require().Error(err) - } - }) - } - } -} - -func (suite *SoloMachineTestSuite) TestVerifyConnectionState() { - counterparty := connectiontypes.NewCounterparty("clientB", testConnectionID, prefix) - conn := connectiontypes.NewConnectionEnd(connectiontypes.OPEN, "clientA", counterparty, connectiontypes.ExportedVersionsToProto(connectiontypes.GetCompatibleVersions()), 0) - - path := suite.solomachine.GetConnectionStatePath(testConnectionID) - - // test singlesig and multisig public keys - for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} { - - value, err := types.ConnectionStateSignBytes(suite.chainA.Codec, solomachine.Sequence, solomachine.Time, solomachine.Diversifier, path, conn) - suite.Require().NoError(err) - - sig := solomachine.GenerateSignature(value) - signatureDoc := &types.TimestampedSignatureData{ - SignatureData: sig, - Timestamp: solomachine.Time, - } - - proof, err := suite.chainA.Codec.MarshalBinaryBare(signatureDoc) - suite.Require().NoError(err) - - testCases := []struct { - name string - clientState *types.ClientState - prefix exported.Prefix - proof []byte - expPass bool - }{ - { - "successful verification", - solomachine.ClientState(), - prefix, - proof, - true, - }, - { - "ApplyPrefix failed", - solomachine.ClientState(), - commitmenttypes.NewMerklePrefix([]byte{}), - proof, - false, - }, - { - "client is frozen", - &types.ClientState{ - Sequence: 1, - FrozenSequence: 1, - ConsensusState: solomachine.ConsensusState(), - AllowUpdateAfterProposal: false, - }, - prefix, - proof, - false, - }, - { - "proof is nil", - solomachine.ClientState(), - prefix, - nil, - false, - }, - { - "proof verification failed", - solomachine.ClientState(), - prefix, - suite.GetInvalidProof(), - false, - }, - } - - for i, tc := range testCases { - tc := tc - - expSeq := tc.clientState.Sequence + 1 - - err := tc.clientState.VerifyConnectionState( - suite.store, suite.chainA.Codec, solomachine.GetHeight(), tc.prefix, tc.proof, testConnectionID, conn, - ) - - if tc.expPass { - suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name) - suite.Require().Equal(expSeq, suite.GetSequenceFromStore(), "sequence not updated in the store (%d) on valid test case %d: %s", suite.GetSequenceFromStore(), i, tc.name) - } else { - suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name) - } - } - } -} - -func (suite *SoloMachineTestSuite) TestVerifyChannelState() { - counterparty := channeltypes.NewCounterparty(testPortID, testChannelID) - ch := channeltypes.NewChannel(channeltypes.OPEN, channeltypes.ORDERED, counterparty, []string{testConnectionID}, "1.0.0") - - path := suite.solomachine.GetChannelStatePath(testPortID, testChannelID) - - // test singlesig and multisig public keys - for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} { - - value, err := types.ChannelStateSignBytes(suite.chainA.Codec, solomachine.Sequence, solomachine.Time, solomachine.Diversifier, path, ch) - suite.Require().NoError(err) - - sig := solomachine.GenerateSignature(value) - signatureDoc := &types.TimestampedSignatureData{ - SignatureData: sig, - Timestamp: solomachine.Time, - } - - proof, err := suite.chainA.Codec.MarshalBinaryBare(signatureDoc) - suite.Require().NoError(err) - - testCases := []struct { - name string - clientState *types.ClientState - prefix exported.Prefix - proof []byte - expPass bool - }{ - { - "successful verification", - solomachine.ClientState(), - prefix, - proof, - true, - }, - { - "ApplyPrefix failed", - solomachine.ClientState(), - nil, - proof, - false, - }, - { - "client is frozen", - &types.ClientState{ - Sequence: 1, - FrozenSequence: 1, - ConsensusState: solomachine.ConsensusState(), - AllowUpdateAfterProposal: false, - }, - prefix, - proof, - false, - }, - { - "proof is nil", - solomachine.ClientState(), - prefix, - nil, - false, - }, - { - "proof verification failed", - solomachine.ClientState(), - prefix, - suite.GetInvalidProof(), - false, - }, - } - - for i, tc := range testCases { - tc := tc - - expSeq := tc.clientState.Sequence + 1 - - err := tc.clientState.VerifyChannelState( - suite.store, suite.chainA.Codec, solomachine.GetHeight(), tc.prefix, tc.proof, testPortID, testChannelID, ch, - ) - - if tc.expPass { - suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name) - suite.Require().Equal(expSeq, suite.GetSequenceFromStore(), "sequence not updated in the store (%d) on valid test case %d: %s", suite.GetSequenceFromStore(), i, tc.name) - } else { - suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name) - } - } - } -} - -func (suite *SoloMachineTestSuite) TestVerifyPacketCommitment() { - commitmentBytes := []byte("COMMITMENT BYTES") - - // test singlesig and multisig public keys - for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} { - - path := solomachine.GetPacketCommitmentPath(testPortID, testChannelID) - - value, err := types.PacketCommitmentSignBytes(suite.chainA.Codec, solomachine.Sequence, solomachine.Time, solomachine.Diversifier, path, commitmentBytes) - suite.Require().NoError(err) - - sig := solomachine.GenerateSignature(value) - signatureDoc := &types.TimestampedSignatureData{ - SignatureData: sig, - Timestamp: solomachine.Time, - } - - proof, err := suite.chainA.Codec.MarshalBinaryBare(signatureDoc) - suite.Require().NoError(err) - - testCases := []struct { - name string - clientState *types.ClientState - prefix exported.Prefix - proof []byte - expPass bool - }{ - { - "successful verification", - solomachine.ClientState(), - prefix, - proof, - true, - }, - { - "ApplyPrefix failed", - solomachine.ClientState(), - commitmenttypes.NewMerklePrefix([]byte{}), - proof, - false, - }, - { - "client is frozen", - &types.ClientState{ - Sequence: 1, - FrozenSequence: 1, - ConsensusState: solomachine.ConsensusState(), - AllowUpdateAfterProposal: false, - }, - prefix, - proof, - false, - }, - { - "proof is nil", - solomachine.ClientState(), - prefix, - nil, - false, - }, - { - "proof verification failed", - solomachine.ClientState(), - prefix, - suite.GetInvalidProof(), - false, - }, - } - - for i, tc := range testCases { - tc := tc - - expSeq := tc.clientState.Sequence + 1 - - err := tc.clientState.VerifyPacketCommitment( - suite.store, suite.chainA.Codec, solomachine.GetHeight(), 0, 0, tc.prefix, tc.proof, testPortID, testChannelID, solomachine.Sequence, commitmentBytes, - ) - - if tc.expPass { - suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name) - suite.Require().Equal(expSeq, suite.GetSequenceFromStore(), "sequence not updated in the store (%d) on valid test case %d: %s", suite.GetSequenceFromStore(), i, tc.name) - } else { - suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name) - } - } - } -} - -func (suite *SoloMachineTestSuite) TestVerifyPacketAcknowledgement() { - ack := []byte("ACK") - // test singlesig and multisig public keys - for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} { - - path := solomachine.GetPacketAcknowledgementPath(testPortID, testChannelID) - - value, err := types.PacketAcknowledgementSignBytes(suite.chainA.Codec, solomachine.Sequence, solomachine.Time, solomachine.Diversifier, path, ack) - suite.Require().NoError(err) - - sig := solomachine.GenerateSignature(value) - signatureDoc := &types.TimestampedSignatureData{ - SignatureData: sig, - Timestamp: solomachine.Time, - } - - proof, err := suite.chainA.Codec.MarshalBinaryBare(signatureDoc) - suite.Require().NoError(err) - - testCases := []struct { - name string - clientState *types.ClientState - prefix exported.Prefix - proof []byte - expPass bool - }{ - { - "successful verification", - solomachine.ClientState(), - prefix, - proof, - true, - }, - { - "ApplyPrefix failed", - solomachine.ClientState(), - commitmenttypes.NewMerklePrefix([]byte{}), - proof, - false, - }, - { - "client is frozen", - &types.ClientState{ - Sequence: 1, - FrozenSequence: 1, - ConsensusState: solomachine.ConsensusState(), - AllowUpdateAfterProposal: false, - }, - prefix, - proof, - false, - }, - { - "proof is nil", - solomachine.ClientState(), - prefix, - nil, - false, - }, - { - "proof verification failed", - solomachine.ClientState(), - prefix, - suite.GetInvalidProof(), - false, - }, - } - - for i, tc := range testCases { - tc := tc - - expSeq := tc.clientState.Sequence + 1 - - err := tc.clientState.VerifyPacketAcknowledgement( - suite.store, suite.chainA.Codec, solomachine.GetHeight(), 0, 0, tc.prefix, tc.proof, testPortID, testChannelID, solomachine.Sequence, ack, - ) - - if tc.expPass { - suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name) - suite.Require().Equal(expSeq, suite.GetSequenceFromStore(), "sequence not updated in the store (%d) on valid test case %d: %s", suite.GetSequenceFromStore(), i, tc.name) - } else { - suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name) - } - } - } -} - -func (suite *SoloMachineTestSuite) TestVerifyPacketReceiptAbsence() { - // test singlesig and multisig public keys - for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} { - - // absence uses receipt path as well - path := solomachine.GetPacketReceiptPath(testPortID, testChannelID) - - value, err := types.PacketReceiptAbsenceSignBytes(suite.chainA.Codec, solomachine.Sequence, solomachine.Time, solomachine.Diversifier, path) - suite.Require().NoError(err) - - sig := solomachine.GenerateSignature(value) - signatureDoc := &types.TimestampedSignatureData{ - SignatureData: sig, - Timestamp: solomachine.Time, - } - - proof, err := suite.chainA.Codec.MarshalBinaryBare(signatureDoc) - suite.Require().NoError(err) - - testCases := []struct { - name string - clientState *types.ClientState - prefix exported.Prefix - proof []byte - expPass bool - }{ - { - "successful verification", - solomachine.ClientState(), - prefix, - proof, - true, - }, - { - "ApplyPrefix failed", - solomachine.ClientState(), - commitmenttypes.NewMerklePrefix([]byte{}), - proof, - false, - }, - { - "client is frozen", - &types.ClientState{ - Sequence: 1, - FrozenSequence: 1, - ConsensusState: solomachine.ConsensusState(), - AllowUpdateAfterProposal: false, - }, - prefix, - proof, - false, - }, - { - "proof is nil", - solomachine.ClientState(), - prefix, - nil, - false, - }, - { - "proof verification failed", - solomachine.ClientState(), - prefix, - suite.GetInvalidProof(), - false, - }, - } - - for i, tc := range testCases { - tc := tc - - expSeq := tc.clientState.Sequence + 1 - - err := tc.clientState.VerifyPacketReceiptAbsence( - suite.store, suite.chainA.Codec, solomachine.GetHeight(), 0, 0, tc.prefix, tc.proof, testPortID, testChannelID, solomachine.Sequence, - ) - - if tc.expPass { - suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name) - suite.Require().Equal(expSeq, suite.GetSequenceFromStore(), "sequence not updated in the store (%d) on valid test case %d: %s", suite.GetSequenceFromStore(), i, tc.name) - } else { - suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name) - } - } - } -} - -func (suite *SoloMachineTestSuite) TestVerifyNextSeqRecv() { - // test singlesig and multisig public keys - for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} { - - nextSeqRecv := solomachine.Sequence + 1 - path := solomachine.GetNextSequenceRecvPath(testPortID, testChannelID) - - value, err := types.NextSequenceRecvSignBytes(suite.chainA.Codec, solomachine.Sequence, solomachine.Time, solomachine.Diversifier, path, nextSeqRecv) - suite.Require().NoError(err) - - sig := solomachine.GenerateSignature(value) - signatureDoc := &types.TimestampedSignatureData{ - SignatureData: sig, - Timestamp: solomachine.Time, - } - - proof, err := suite.chainA.Codec.MarshalBinaryBare(signatureDoc) - suite.Require().NoError(err) - - testCases := []struct { - name string - clientState *types.ClientState - prefix exported.Prefix - proof []byte - expPass bool - }{ - { - "successful verification", - solomachine.ClientState(), - prefix, - proof, - true, - }, - { - "ApplyPrefix failed", - solomachine.ClientState(), - commitmenttypes.NewMerklePrefix([]byte{}), - proof, - false, - }, - { - "client is frozen", - &types.ClientState{ - Sequence: 1, - FrozenSequence: 1, - ConsensusState: solomachine.ConsensusState(), - AllowUpdateAfterProposal: false, - }, - prefix, - proof, - false, - }, - { - "proof is nil", - solomachine.ClientState(), - prefix, - nil, - false, - }, - { - "proof verification failed", - solomachine.ClientState(), - prefix, - suite.GetInvalidProof(), - false, - }, - } - - for i, tc := range testCases { - tc := tc - - expSeq := tc.clientState.Sequence + 1 - - err := tc.clientState.VerifyNextSequenceRecv( - suite.store, suite.chainA.Codec, solomachine.GetHeight(), 0, 0, tc.prefix, tc.proof, testPortID, testChannelID, nextSeqRecv, - ) - - if tc.expPass { - suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name) - suite.Require().Equal(expSeq, suite.GetSequenceFromStore(), "sequence not updated in the store (%d) on valid test case %d: %s", suite.GetSequenceFromStore(), i, tc.name) - } else { - suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name) - } - } - } -} diff --git a/x/ibc/light-clients/06-solomachine/types/codec.go b/x/ibc/light-clients/06-solomachine/types/codec.go deleted file mode 100644 index 313a910ca96b..000000000000 --- a/x/ibc/light-clients/06-solomachine/types/codec.go +++ /dev/null @@ -1,130 +0,0 @@ -package types - -import ( - "github.com/cosmos/cosmos-sdk/codec" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/cosmos/cosmos-sdk/types/tx/signing" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -// RegisterInterfaces register the ibc channel submodule interfaces to protobuf -// Any. -func RegisterInterfaces(registry codectypes.InterfaceRegistry) { - registry.RegisterImplementations( - (*exported.ClientState)(nil), - &ClientState{}, - ) - registry.RegisterImplementations( - (*exported.ConsensusState)(nil), - &ConsensusState{}, - ) - registry.RegisterImplementations( - (*exported.Header)(nil), - &Header{}, - ) - registry.RegisterImplementations( - (*exported.Misbehaviour)(nil), - &Misbehaviour{}, - ) -} - -func UnmarshalSignatureData(cdc codec.BinaryMarshaler, data []byte) (signing.SignatureData, error) { - protoSigData := &signing.SignatureDescriptor_Data{} - if err := cdc.UnmarshalBinaryBare(data, protoSigData); err != nil { - return nil, sdkerrors.Wrapf(err, "failed to unmarshal proof into type %T", protoSigData) - } - - sigData := signing.SignatureDataFromProto(protoSigData) - - return sigData, nil -} - -// UnmarshalDataByType attempts to unmarshal the data to the specified type. An error is -// return if it fails. -func UnmarshalDataByType(cdc codec.BinaryMarshaler, dataType DataType, data []byte) (Data, error) { - if len(data) == 0 { - return nil, sdkerrors.Wrap(ErrInvalidSignatureAndData, "data cannot be empty") - } - - switch dataType { - case UNSPECIFIED: - return nil, sdkerrors.Wrap(ErrInvalidDataType, "data type cannot be UNSPECIFIED") - - case CLIENT: - clientData := &ClientStateData{} - if err := cdc.UnmarshalBinaryBare(data, clientData); err != nil { - return nil, err - } - - // unpack any - if _, err := clienttypes.UnpackClientState(clientData.ClientState); err != nil { - return nil, err - } - return clientData, nil - - case CONSENSUS: - consensusData := &ConsensusStateData{} - if err := cdc.UnmarshalBinaryBare(data, consensusData); err != nil { - return nil, err - } - - // unpack any - if _, err := clienttypes.UnpackConsensusState(consensusData.ConsensusState); err != nil { - return nil, err - } - return consensusData, nil - - case CONNECTION: - connectionData := &ConnectionStateData{} - if err := cdc.UnmarshalBinaryBare(data, connectionData); err != nil { - return nil, err - } - - return connectionData, nil - - case CHANNEL: - channelData := &ChannelStateData{} - if err := cdc.UnmarshalBinaryBare(data, channelData); err != nil { - return nil, err - } - - return channelData, nil - - case PACKETCOMMITMENT: - commitmentData := &PacketCommitmentData{} - if err := cdc.UnmarshalBinaryBare(data, commitmentData); err != nil { - return nil, err - } - - return commitmentData, nil - - case PACKETACKNOWLEDGEMENT: - ackData := &PacketAcknowledgementData{} - if err := cdc.UnmarshalBinaryBare(data, ackData); err != nil { - return nil, err - } - - return ackData, nil - - case PACKETRECEIPTABSENCE: - receiptAbsenceData := &PacketReceiptAbsenceData{} - if err := cdc.UnmarshalBinaryBare(data, receiptAbsenceData); err != nil { - return nil, err - } - - return receiptAbsenceData, nil - - case NEXTSEQUENCERECV: - nextSeqRecvData := &NextSequenceRecvData{} - if err := cdc.UnmarshalBinaryBare(data, nextSeqRecvData); err != nil { - return nil, err - } - - return nextSeqRecvData, nil - - default: - return nil, sdkerrors.Wrapf(ErrInvalidDataType, "unsupported data type %T", dataType) - } -} diff --git a/x/ibc/light-clients/06-solomachine/types/codec_test.go b/x/ibc/light-clients/06-solomachine/types/codec_test.go deleted file mode 100644 index 70be186a10bb..000000000000 --- a/x/ibc/light-clients/06-solomachine/types/codec_test.go +++ /dev/null @@ -1,190 +0,0 @@ -package types_test - -import ( - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/06-solomachine/types" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" -) - -func (suite SoloMachineTestSuite) TestUnmarshalDataByType() { - var ( - data []byte - err error - ) - - // test singlesig and multisig public keys - for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} { - - cdc := suite.chainA.App.AppCodec() - cases := []struct { - name string - dataType types.DataType - malleate func() - expPass bool - }{ - { - "empty data", types.CLIENT, func() { - data = []byte{} - }, false, - }, - { - "unspecified", types.UNSPECIFIED, func() { - path := solomachine.GetClientStatePath(counterpartyClientIdentifier) - data, err = types.ClientStateDataBytes(cdc, path, solomachine.ClientState()) - suite.Require().NoError(err) - }, false, - }, - { - "client", types.CLIENT, func() { - path := solomachine.GetClientStatePath(counterpartyClientIdentifier) - data, err = types.ClientStateDataBytes(cdc, path, solomachine.ClientState()) - suite.Require().NoError(err) - }, true, - }, - { - "bad client (provides consensus state data)", types.CLIENT, func() { - path := solomachine.GetConsensusStatePath(counterpartyClientIdentifier, clienttypes.NewHeight(0, 5)) - data, err = types.ConsensusStateDataBytes(cdc, path, solomachine.ConsensusState()) - suite.Require().NoError(err) - }, false, - }, - { - "consensus", types.CONSENSUS, func() { - path := solomachine.GetConsensusStatePath(counterpartyClientIdentifier, clienttypes.NewHeight(0, 5)) - data, err = types.ConsensusStateDataBytes(cdc, path, solomachine.ConsensusState()) - suite.Require().NoError(err) - - }, true, - }, - { - "bad consensus (provides client state data)", types.CONSENSUS, func() { - path := solomachine.GetClientStatePath(counterpartyClientIdentifier) - data, err = types.ClientStateDataBytes(cdc, path, solomachine.ClientState()) - suite.Require().NoError(err) - }, false, - }, - { - "connection", types.CONNECTION, func() { - counterparty := connectiontypes.NewCounterparty("clientB", testConnectionID, prefix) - conn := connectiontypes.NewConnectionEnd(connectiontypes.OPEN, "clientA", counterparty, connectiontypes.ExportedVersionsToProto(connectiontypes.GetCompatibleVersions()), 0) - path := solomachine.GetConnectionStatePath("connectionID") - - data, err = types.ConnectionStateDataBytes(cdc, path, conn) - suite.Require().NoError(err) - - }, true, - }, - { - "bad connection (uses channel data)", types.CONNECTION, func() { - counterparty := channeltypes.NewCounterparty(testPortID, testChannelID) - ch := channeltypes.NewChannel(channeltypes.OPEN, channeltypes.ORDERED, counterparty, []string{testConnectionID}, "1.0.0") - path := solomachine.GetChannelStatePath("portID", "channelID") - - data, err = types.ChannelStateDataBytes(cdc, path, ch) - suite.Require().NoError(err) - }, false, - }, - { - "channel", types.CHANNEL, func() { - counterparty := channeltypes.NewCounterparty(testPortID, testChannelID) - ch := channeltypes.NewChannel(channeltypes.OPEN, channeltypes.ORDERED, counterparty, []string{testConnectionID}, "1.0.0") - path := solomachine.GetChannelStatePath("portID", "channelID") - - data, err = types.ChannelStateDataBytes(cdc, path, ch) - suite.Require().NoError(err) - }, true, - }, - { - "bad channel (uses connection data)", types.CHANNEL, func() { - counterparty := connectiontypes.NewCounterparty("clientB", testConnectionID, prefix) - conn := connectiontypes.NewConnectionEnd(connectiontypes.OPEN, "clientA", counterparty, connectiontypes.ExportedVersionsToProto(connectiontypes.GetCompatibleVersions()), 0) - path := solomachine.GetConnectionStatePath("connectionID") - - data, err = types.ConnectionStateDataBytes(cdc, path, conn) - suite.Require().NoError(err) - - }, false, - }, - { - "packet commitment", types.PACKETCOMMITMENT, func() { - commitment := []byte("packet commitment") - path := solomachine.GetPacketCommitmentPath("portID", "channelID") - - data, err = types.PacketCommitmentDataBytes(cdc, path, commitment) - suite.Require().NoError(err) - }, true, - }, - { - "bad packet commitment (uses next seq recv)", types.PACKETCOMMITMENT, func() { - path := solomachine.GetNextSequenceRecvPath("portID", "channelID") - - data, err = types.NextSequenceRecvDataBytes(cdc, path, 10) - suite.Require().NoError(err) - }, false, - }, - { - "packet acknowledgement", types.PACKETACKNOWLEDGEMENT, func() { - commitment := []byte("packet acknowledgement") - path := solomachine.GetPacketAcknowledgementPath("portID", "channelID") - - data, err = types.PacketAcknowledgementDataBytes(cdc, path, commitment) - suite.Require().NoError(err) - }, true, - }, - { - "bad packet acknowledgement (uses next sequence recv)", types.PACKETACKNOWLEDGEMENT, func() { - path := solomachine.GetNextSequenceRecvPath("portID", "channelID") - - data, err = types.NextSequenceRecvDataBytes(cdc, path, 10) - suite.Require().NoError(err) - }, false, - }, - { - "packet acknowledgement absence", types.PACKETRECEIPTABSENCE, func() { - path := solomachine.GetPacketReceiptPath("portID", "channelID") - - data, err = types.PacketReceiptAbsenceDataBytes(cdc, path) - suite.Require().NoError(err) - }, true, - }, - { - "next sequence recv", types.NEXTSEQUENCERECV, func() { - path := solomachine.GetNextSequenceRecvPath("portID", "channelID") - - data, err = types.NextSequenceRecvDataBytes(cdc, path, 10) - suite.Require().NoError(err) - }, true, - }, - { - "bad next sequence recv (uses packet commitment)", types.NEXTSEQUENCERECV, func() { - commitment := []byte("packet commitment") - path := solomachine.GetPacketCommitmentPath("portID", "channelID") - - data, err = types.PacketCommitmentDataBytes(cdc, path, commitment) - suite.Require().NoError(err) - }, false, - }, - } - - for _, tc := range cases { - tc := tc - - suite.Run(tc.name, func() { - tc.malleate() - - data, err := types.UnmarshalDataByType(cdc, tc.dataType, data) - - if tc.expPass { - suite.Require().NoError(err) - suite.Require().NotNil(data) - } else { - suite.Require().Error(err) - suite.Require().Nil(data) - } - }) - } - } - -} diff --git a/x/ibc/light-clients/06-solomachine/types/consensus_state.go b/x/ibc/light-clients/06-solomachine/types/consensus_state.go deleted file mode 100644 index 7d6d09cd046b..000000000000 --- a/x/ibc/light-clients/06-solomachine/types/consensus_state.go +++ /dev/null @@ -1,60 +0,0 @@ -package types - -import ( - "strings" - - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -var _ exported.ConsensusState = &ConsensusState{} - -// ClientType returns Solo Machine type. -func (ConsensusState) ClientType() string { - return exported.Solomachine -} - -// GetTimestamp returns zero. -func (cs ConsensusState) GetTimestamp() uint64 { - return cs.Timestamp -} - -// GetRoot returns nil since solo machines do not have roots. -func (cs ConsensusState) GetRoot() exported.Root { - return nil -} - -// GetPubKey unmarshals the public key into a cryptotypes.PubKey type. -// An error is returned if the public key is nil or the cached value -// is not a PubKey. -func (cs ConsensusState) GetPubKey() (cryptotypes.PubKey, error) { - if cs.PublicKey == nil { - return nil, sdkerrors.Wrap(clienttypes.ErrInvalidConsensus, "consensus state PublicKey cannot be nil") - } - - publicKey, ok := cs.PublicKey.GetCachedValue().(cryptotypes.PubKey) - if !ok { - return nil, sdkerrors.Wrap(clienttypes.ErrInvalidConsensus, "consensus state PublicKey is not cryptotypes.PubKey") - } - - return publicKey, nil -} - -// ValidateBasic defines basic validation for the solo machine consensus state. -func (cs ConsensusState) ValidateBasic() error { - if cs.Timestamp == 0 { - return sdkerrors.Wrap(clienttypes.ErrInvalidConsensus, "timestamp cannot be 0") - } - if cs.Diversifier != "" && strings.TrimSpace(cs.Diversifier) == "" { - return sdkerrors.Wrap(clienttypes.ErrInvalidConsensus, "diversifier cannot contain only spaces") - } - - publicKey, err := cs.GetPubKey() - if err != nil || publicKey == nil || len(publicKey.Bytes()) == 0 { - return sdkerrors.Wrap(clienttypes.ErrInvalidConsensus, "public key cannot be empty") - } - - return nil -} diff --git a/x/ibc/light-clients/06-solomachine/types/consensus_state_test.go b/x/ibc/light-clients/06-solomachine/types/consensus_state_test.go deleted file mode 100644 index e0c22f95957b..000000000000 --- a/x/ibc/light-clients/06-solomachine/types/consensus_state_test.go +++ /dev/null @@ -1,75 +0,0 @@ -package types_test - -import ( - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/06-solomachine/types" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" -) - -func (suite *SoloMachineTestSuite) TestConsensusState() { - consensusState := suite.solomachine.ConsensusState() - - suite.Require().Equal(exported.Solomachine, consensusState.ClientType()) - suite.Require().Equal(suite.solomachine.Time, consensusState.GetTimestamp()) - suite.Require().Nil(consensusState.GetRoot()) -} - -func (suite *SoloMachineTestSuite) TestConsensusStateValidateBasic() { - // test singlesig and multisig public keys - for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} { - - testCases := []struct { - name string - consensusState *types.ConsensusState - expPass bool - }{ - { - "valid consensus state", - solomachine.ConsensusState(), - true, - }, - { - "timestamp is zero", - &types.ConsensusState{ - PublicKey: solomachine.ConsensusState().PublicKey, - Timestamp: 0, - Diversifier: solomachine.Diversifier, - }, - false, - }, - { - "diversifier is blank", - &types.ConsensusState{ - PublicKey: solomachine.ConsensusState().PublicKey, - Timestamp: solomachine.Time, - Diversifier: " ", - }, - false, - }, - { - "pubkey is nil", - &types.ConsensusState{ - Timestamp: solomachine.Time, - Diversifier: solomachine.Diversifier, - PublicKey: nil, - }, - false, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - - err := tc.consensusState.ValidateBasic() - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } - } -} diff --git a/x/ibc/light-clients/06-solomachine/types/errors.go b/x/ibc/light-clients/06-solomachine/types/errors.go deleted file mode 100644 index 3e27f60732ad..000000000000 --- a/x/ibc/light-clients/06-solomachine/types/errors.go +++ /dev/null @@ -1,18 +0,0 @@ -package types - -import ( - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" -) - -const ( - SubModuleName = "solo machine" -) - -var ( - ErrInvalidHeader = sdkerrors.Register(SubModuleName, 2, "invalid header") - ErrInvalidSequence = sdkerrors.Register(SubModuleName, 3, "invalid sequence") - ErrInvalidSignatureAndData = sdkerrors.Register(SubModuleName, 4, "invalid signature and data") - ErrSignatureVerificationFailed = sdkerrors.Register(SubModuleName, 5, "signature verification failed") - ErrInvalidProof = sdkerrors.Register(SubModuleName, 6, "invalid solo machine proof") - ErrInvalidDataType = sdkerrors.Register(SubModuleName, 7, "invalid data type") -) diff --git a/x/ibc/light-clients/06-solomachine/types/header.go b/x/ibc/light-clients/06-solomachine/types/header.go deleted file mode 100644 index f9c5f176fdaa..000000000000 --- a/x/ibc/light-clients/06-solomachine/types/header.go +++ /dev/null @@ -1,67 +0,0 @@ -package types - -import ( - "strings" - - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -var _ exported.Header = &Header{} - -// ClientType defines that the Header is a Solo Machine. -func (Header) ClientType() string { - return exported.Solomachine -} - -// GetHeight returns the current sequence number as the height. -// Return clientexported.Height to satisfy interface -// Revision number is always 0 for a solo-machine -func (h Header) GetHeight() exported.Height { - return clienttypes.NewHeight(0, h.Sequence) -} - -// GetPubKey unmarshals the new public key into a cryptotypes.PubKey type. -// An error is returned if the new public key is nil or the cached value -// is not a PubKey. -func (h Header) GetPubKey() (cryptotypes.PubKey, error) { - if h.NewPublicKey == nil { - return nil, sdkerrors.Wrap(ErrInvalidHeader, "header NewPublicKey cannot be nil") - } - - publicKey, ok := h.NewPublicKey.GetCachedValue().(cryptotypes.PubKey) - if !ok { - return nil, sdkerrors.Wrap(ErrInvalidHeader, "header NewPublicKey is not cryptotypes.PubKey") - } - - return publicKey, nil -} - -// ValidateBasic ensures that the sequence, signature and public key have all -// been initialized. -func (h Header) ValidateBasic() error { - if h.Sequence == 0 { - return sdkerrors.Wrap(clienttypes.ErrInvalidHeader, "sequence number cannot be zero") - } - - if h.Timestamp == 0 { - return sdkerrors.Wrap(clienttypes.ErrInvalidHeader, "timestamp cannot be zero") - } - - if h.NewDiversifier != "" && strings.TrimSpace(h.NewDiversifier) == "" { - return sdkerrors.Wrap(clienttypes.ErrInvalidHeader, "diversifier cannot contain only spaces") - } - - if len(h.Signature) == 0 { - return sdkerrors.Wrap(clienttypes.ErrInvalidHeader, "signature cannot be empty") - } - - newPublicKey, err := h.GetPubKey() - if err != nil || newPublicKey == nil || len(newPublicKey.Bytes()) == 0 { - return sdkerrors.Wrap(clienttypes.ErrInvalidHeader, "new public key cannot be empty") - } - - return nil -} diff --git a/x/ibc/light-clients/06-solomachine/types/header_test.go b/x/ibc/light-clients/06-solomachine/types/header_test.go deleted file mode 100644 index a5ca45e8aa88..000000000000 --- a/x/ibc/light-clients/06-solomachine/types/header_test.go +++ /dev/null @@ -1,98 +0,0 @@ -package types_test - -import ( - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/06-solomachine/types" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" -) - -func (suite *SoloMachineTestSuite) TestHeaderValidateBasic() { - // test singlesig and multisig public keys - for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} { - - header := solomachine.CreateHeader() - - cases := []struct { - name string - header *types.Header - expPass bool - }{ - { - "valid header", - header, - true, - }, - { - "sequence is zero", - &types.Header{ - Sequence: 0, - Timestamp: header.Timestamp, - Signature: header.Signature, - NewPublicKey: header.NewPublicKey, - NewDiversifier: header.NewDiversifier, - }, - false, - }, - { - "timestamp is zero", - &types.Header{ - Sequence: header.Sequence, - Timestamp: 0, - Signature: header.Signature, - NewPublicKey: header.NewPublicKey, - NewDiversifier: header.NewDiversifier, - }, - false, - }, - { - "signature is empty", - &types.Header{ - Sequence: header.Sequence, - Timestamp: header.Timestamp, - Signature: []byte{}, - NewPublicKey: header.NewPublicKey, - NewDiversifier: header.NewDiversifier, - }, - false, - }, - { - "diversifier contains only spaces", - &types.Header{ - Sequence: header.Sequence, - Timestamp: header.Timestamp, - Signature: header.Signature, - NewPublicKey: header.NewPublicKey, - NewDiversifier: " ", - }, - false, - }, - { - "public key is nil", - &types.Header{ - Sequence: header.Sequence, - Timestamp: header.Timestamp, - Signature: header.Signature, - NewPublicKey: nil, - NewDiversifier: header.NewDiversifier, - }, - false, - }, - } - - suite.Require().Equal(exported.Solomachine, header.ClientType()) - - for _, tc := range cases { - tc := tc - - suite.Run(tc.name, func() { - err := tc.header.ValidateBasic() - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } - } -} diff --git a/x/ibc/light-clients/06-solomachine/types/misbehaviour.go b/x/ibc/light-clients/06-solomachine/types/misbehaviour.go deleted file mode 100644 index f5b218ccf208..000000000000 --- a/x/ibc/light-clients/06-solomachine/types/misbehaviour.go +++ /dev/null @@ -1,83 +0,0 @@ -package types - -import ( - "bytes" - - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -var _ exported.Misbehaviour = &Misbehaviour{} - -// ClientType is a Solo Machine light client. -func (misbehaviour Misbehaviour) ClientType() string { - return exported.Solomachine -} - -// GetClientID returns the ID of the client that committed a misbehaviour. -func (misbehaviour Misbehaviour) GetClientID() string { - return misbehaviour.ClientId -} - -// Type implements Evidence interface. -func (misbehaviour Misbehaviour) Type() string { - return exported.TypeClientMisbehaviour -} - -// GetHeight returns the sequence at which misbehaviour occurred. -// Return exported.Height to satisfy interface -// Revision number is always 0 for a solo-machine -func (misbehaviour Misbehaviour) GetHeight() exported.Height { - return clienttypes.NewHeight(0, misbehaviour.Sequence) -} - -// ValidateBasic implements Evidence interface. -func (misbehaviour Misbehaviour) ValidateBasic() error { - if err := host.ClientIdentifierValidator(misbehaviour.ClientId); err != nil { - return sdkerrors.Wrap(err, "invalid client identifier for solo machine") - } - - if misbehaviour.Sequence == 0 { - return sdkerrors.Wrap(clienttypes.ErrInvalidMisbehaviour, "sequence cannot be 0") - } - - if err := misbehaviour.SignatureOne.ValidateBasic(); err != nil { - return sdkerrors.Wrap(err, "signature one failed basic validation") - } - - if err := misbehaviour.SignatureTwo.ValidateBasic(); err != nil { - return sdkerrors.Wrap(err, "signature two failed basic validation") - } - - // misbehaviour signatures cannot be identical - if bytes.Equal(misbehaviour.SignatureOne.Signature, misbehaviour.SignatureTwo.Signature) { - return sdkerrors.Wrap(clienttypes.ErrInvalidMisbehaviour, "misbehaviour signatures cannot be equal") - } - - // message data signed cannot be identical - if bytes.Equal(misbehaviour.SignatureOne.Data, misbehaviour.SignatureTwo.Data) { - return sdkerrors.Wrap(clienttypes.ErrInvalidMisbehaviour, "misbehaviour signature data must be signed over different messages") - } - - return nil -} - -// ValidateBasic ensures that the signature and data fields are non-empty. -func (sd SignatureAndData) ValidateBasic() error { - if len(sd.Signature) == 0 { - return sdkerrors.Wrap(ErrInvalidSignatureAndData, "signature cannot be empty") - } - if len(sd.Data) == 0 { - return sdkerrors.Wrap(ErrInvalidSignatureAndData, "data for signature cannot be empty") - } - if sd.DataType == UNSPECIFIED { - return sdkerrors.Wrap(ErrInvalidSignatureAndData, "data type cannot be UNSPECIFIED") - } - if sd.Timestamp == 0 { - return sdkerrors.Wrap(ErrInvalidSignatureAndData, "timestamp cannot be 0") - } - - return nil -} diff --git a/x/ibc/light-clients/06-solomachine/types/misbehaviour_handle.go b/x/ibc/light-clients/06-solomachine/types/misbehaviour_handle.go deleted file mode 100644 index ce5d6351c48f..000000000000 --- a/x/ibc/light-clients/06-solomachine/types/misbehaviour_handle.go +++ /dev/null @@ -1,92 +0,0 @@ -package types - -import ( - "github.com/cosmos/cosmos-sdk/codec" - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -// CheckMisbehaviourAndUpdateState determines whether or not the currently registered -// public key signed over two different messages with the same sequence. If this is true -// the client state is updated to a frozen status. -// NOTE: Misbehaviour is not tracked for previous public keys, a solo machine may update to -// a new public key before the misbehaviour is processed. Therefore, misbehaviour is data -// order processing dependent. -func (cs ClientState) CheckMisbehaviourAndUpdateState( - ctx sdk.Context, - cdc codec.BinaryMarshaler, - clientStore sdk.KVStore, - misbehaviour exported.Misbehaviour, -) (exported.ClientState, error) { - - soloMisbehaviour, ok := misbehaviour.(*Misbehaviour) - if !ok { - return nil, sdkerrors.Wrapf( - clienttypes.ErrInvalidClientType, - "misbehaviour type %T, expected %T", misbehaviour, &Misbehaviour{}, - ) - } - - if cs.IsFrozen() { - return nil, sdkerrors.Wrapf(clienttypes.ErrClientFrozen, "client is already frozen") - } - - // NOTE: a check that the misbehaviour message data are not equal is done by - // misbehaviour.ValidateBasic which is called by the 02-client keeper. - - // verify first signature - if err := verifySignatureAndData(cdc, cs, soloMisbehaviour, soloMisbehaviour.SignatureOne); err != nil { - return nil, sdkerrors.Wrap(err, "failed to verify signature one") - } - - // verify second signature - if err := verifySignatureAndData(cdc, cs, soloMisbehaviour, soloMisbehaviour.SignatureTwo); err != nil { - return nil, sdkerrors.Wrap(err, "failed to verify signature two") - } - - cs.FrozenSequence = soloMisbehaviour.Sequence - return &cs, nil -} - -// verifySignatureAndData verifies that the currently registered public key has signed -// over the provided data and that the data is valid. The data is valid if it can be -// unmarshaled into the specified data type. -func verifySignatureAndData(cdc codec.BinaryMarshaler, clientState ClientState, misbehaviour *Misbehaviour, sigAndData *SignatureAndData) error { - - // do not check misbehaviour timestamp since we want to allow processing of past misbehaviour - - // ensure data can be unmarshaled to the specified data type - if _, err := UnmarshalDataByType(cdc, sigAndData.DataType, sigAndData.Data); err != nil { - return err - } - - data, err := MisbehaviourSignBytes( - cdc, - misbehaviour.Sequence, sigAndData.Timestamp, - clientState.ConsensusState.Diversifier, - sigAndData.DataType, - sigAndData.Data, - ) - if err != nil { - return err - } - - sigData, err := UnmarshalSignatureData(cdc, sigAndData.Signature) - if err != nil { - return err - } - - publicKey, err := clientState.ConsensusState.GetPubKey() - if err != nil { - return err - } - - if err := VerifySignature(publicKey, data, sigData); err != nil { - return err - } - - return nil - -} diff --git a/x/ibc/light-clients/06-solomachine/types/misbehaviour_handle_test.go b/x/ibc/light-clients/06-solomachine/types/misbehaviour_handle_test.go deleted file mode 100644 index 97ce22a3ed9c..000000000000 --- a/x/ibc/light-clients/06-solomachine/types/misbehaviour_handle_test.go +++ /dev/null @@ -1,275 +0,0 @@ -package types_test - -import ( - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/06-solomachine/types" - ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" -) - -func (suite *SoloMachineTestSuite) TestCheckMisbehaviourAndUpdateState() { - var ( - clientState exported.ClientState - misbehaviour exported.Misbehaviour - ) - - // test singlesig and multisig public keys - for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} { - - testCases := []struct { - name string - setup func() - expPass bool - }{ - { - "valid misbehaviour", - func() { - clientState = solomachine.ClientState() - misbehaviour = solomachine.CreateMisbehaviour() - }, - true, - }, - { - "old misbehaviour is successful (timestamp is less than current consensus state)", - func() { - clientState = solomachine.ClientState() - solomachine.Time = solomachine.Time - 5 - misbehaviour = solomachine.CreateMisbehaviour() - }, true, - }, - { - "client is frozen", - func() { - cs := solomachine.ClientState() - cs.FrozenSequence = 1 - clientState = cs - misbehaviour = solomachine.CreateMisbehaviour() - }, - false, - }, - { - "wrong client state type", - func() { - clientState = &ibctmtypes.ClientState{} - misbehaviour = solomachine.CreateMisbehaviour() - }, - false, - }, - { - "invalid misbehaviour type", - func() { - clientState = solomachine.ClientState() - misbehaviour = &ibctmtypes.Misbehaviour{} - }, - false, - }, - { - "invalid SignatureOne SignatureData", - func() { - clientState = solomachine.ClientState() - m := solomachine.CreateMisbehaviour() - - m.SignatureOne.Signature = suite.GetInvalidProof() - misbehaviour = m - }, false, - }, - { - "invalid SignatureTwo SignatureData", - func() { - clientState = solomachine.ClientState() - m := solomachine.CreateMisbehaviour() - - m.SignatureTwo.Signature = suite.GetInvalidProof() - misbehaviour = m - }, false, - }, - { - "invalid SignatureOne timestamp", - func() { - clientState = solomachine.ClientState() - m := solomachine.CreateMisbehaviour() - - m.SignatureOne.Timestamp = 1000000000000 - misbehaviour = m - }, false, - }, - { - "invalid SignatureTwo timestamp", - func() { - clientState = solomachine.ClientState() - m := solomachine.CreateMisbehaviour() - - m.SignatureTwo.Timestamp = 1000000000000 - misbehaviour = m - }, false, - }, - { - "invalid first signature data", - func() { - clientState = solomachine.ClientState() - - // store in temp before assigning to interface type - m := solomachine.CreateMisbehaviour() - - msg := []byte("DATA ONE") - signBytes := &types.SignBytes{ - Sequence: solomachine.Sequence + 1, - Timestamp: solomachine.Time, - Diversifier: solomachine.Diversifier, - DataType: types.CLIENT, - Data: msg, - } - - data, err := suite.chainA.Codec.MarshalBinaryBare(signBytes) - suite.Require().NoError(err) - - sig := solomachine.GenerateSignature(data) - - m.SignatureOne.Signature = sig - m.SignatureOne.Data = msg - misbehaviour = m - }, - false, - }, - { - "invalid second signature data", - func() { - clientState = solomachine.ClientState() - - // store in temp before assigning to interface type - m := solomachine.CreateMisbehaviour() - - msg := []byte("DATA TWO") - signBytes := &types.SignBytes{ - Sequence: solomachine.Sequence + 1, - Timestamp: solomachine.Time, - Diversifier: solomachine.Diversifier, - DataType: types.CLIENT, - Data: msg, - } - - data, err := suite.chainA.Codec.MarshalBinaryBare(signBytes) - suite.Require().NoError(err) - - sig := solomachine.GenerateSignature(data) - - m.SignatureTwo.Signature = sig - m.SignatureTwo.Data = msg - misbehaviour = m - }, - false, - }, - { - "wrong pubkey generates first signature", - func() { - clientState = solomachine.ClientState() - badMisbehaviour := solomachine.CreateMisbehaviour() - - // update public key to a new one - solomachine.CreateHeader() - m := solomachine.CreateMisbehaviour() - - // set SignatureOne to use the wrong signature - m.SignatureOne = badMisbehaviour.SignatureOne - misbehaviour = m - }, false, - }, - { - "wrong pubkey generates second signature", - func() { - clientState = solomachine.ClientState() - badMisbehaviour := solomachine.CreateMisbehaviour() - - // update public key to a new one - solomachine.CreateHeader() - m := solomachine.CreateMisbehaviour() - - // set SignatureTwo to use the wrong signature - m.SignatureTwo = badMisbehaviour.SignatureTwo - misbehaviour = m - }, false, - }, - - { - "signatures sign over different sequence", - func() { - clientState = solomachine.ClientState() - - // store in temp before assigning to interface type - m := solomachine.CreateMisbehaviour() - - // Signature One - msg := []byte("DATA ONE") - // sequence used is plus 1 - signBytes := &types.SignBytes{ - Sequence: solomachine.Sequence + 1, - Timestamp: solomachine.Time, - Diversifier: solomachine.Diversifier, - DataType: types.CLIENT, - Data: msg, - } - - data, err := suite.chainA.Codec.MarshalBinaryBare(signBytes) - suite.Require().NoError(err) - - sig := solomachine.GenerateSignature(data) - - m.SignatureOne.Signature = sig - m.SignatureOne.Data = msg - - // Signature Two - msg = []byte("DATA TWO") - // sequence used is minus 1 - - signBytes = &types.SignBytes{ - Sequence: solomachine.Sequence - 1, - Timestamp: solomachine.Time, - Diversifier: solomachine.Diversifier, - DataType: types.CLIENT, - Data: msg, - } - data, err = suite.chainA.Codec.MarshalBinaryBare(signBytes) - suite.Require().NoError(err) - - sig = solomachine.GenerateSignature(data) - - m.SignatureTwo.Signature = sig - m.SignatureTwo.Data = msg - - misbehaviour = m - - }, - false, - }, - { - "consensus state pubkey is nil", - func() { - cs := solomachine.ClientState() - cs.ConsensusState.PublicKey = nil - clientState = cs - misbehaviour = solomachine.CreateMisbehaviour() - }, - false, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - // setup test - tc.setup() - - clientState, err := clientState.CheckMisbehaviourAndUpdateState(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), suite.store, misbehaviour) - - if tc.expPass { - suite.Require().NoError(err) - suite.Require().True(clientState.IsFrozen(), "client not frozen") - } else { - suite.Require().Error(err) - suite.Require().Nil(clientState) - } - }) - } - } -} diff --git a/x/ibc/light-clients/06-solomachine/types/misbehaviour_test.go b/x/ibc/light-clients/06-solomachine/types/misbehaviour_test.go deleted file mode 100644 index 7c1f9168aaf6..000000000000 --- a/x/ibc/light-clients/06-solomachine/types/misbehaviour_test.go +++ /dev/null @@ -1,132 +0,0 @@ -package types_test - -import ( - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/06-solomachine/types" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" -) - -func (suite *SoloMachineTestSuite) TestMisbehaviour() { - misbehaviour := suite.solomachine.CreateMisbehaviour() - - suite.Require().Equal(exported.Solomachine, misbehaviour.ClientType()) - suite.Require().Equal(suite.solomachine.ClientID, misbehaviour.GetClientID()) - suite.Require().Equal(uint64(0), misbehaviour.GetHeight().GetRevisionNumber()) - suite.Require().Equal(suite.solomachine.Sequence, misbehaviour.GetHeight().GetRevisionHeight()) -} - -func (suite *SoloMachineTestSuite) TestMisbehaviourValidateBasic() { - // test singlesig and multisig public keys - for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} { - - testCases := []struct { - name string - malleateMisbehaviour func(misbehaviour *types.Misbehaviour) - expPass bool - }{ - { - "valid misbehaviour", - func(*types.Misbehaviour) {}, - true, - }, - { - "invalid client ID", - func(misbehaviour *types.Misbehaviour) { - misbehaviour.ClientId = "(badclientid)" - }, - false, - }, - { - "sequence is zero", - func(misbehaviour *types.Misbehaviour) { - misbehaviour.Sequence = 0 - }, - false, - }, - { - "signature one sig is empty", - func(misbehaviour *types.Misbehaviour) { - misbehaviour.SignatureOne.Signature = []byte{} - }, - false, - }, - { - "signature two sig is empty", - func(misbehaviour *types.Misbehaviour) { - misbehaviour.SignatureTwo.Signature = []byte{} - }, - false, - }, - { - "signature one data is empty", - func(misbehaviour *types.Misbehaviour) { - misbehaviour.SignatureOne.Data = nil - }, - false, - }, - { - "signature two data is empty", - func(misbehaviour *types.Misbehaviour) { - misbehaviour.SignatureTwo.Data = []byte{} - }, - false, - }, - { - "signatures are identical", - func(misbehaviour *types.Misbehaviour) { - misbehaviour.SignatureTwo.Signature = misbehaviour.SignatureOne.Signature - }, - false, - }, - { - "data signed is identical", - func(misbehaviour *types.Misbehaviour) { - misbehaviour.SignatureTwo.Data = misbehaviour.SignatureOne.Data - }, - false, - }, - { - "data type for SignatureOne is unspecified", - func(misbehaviour *types.Misbehaviour) { - misbehaviour.SignatureOne.DataType = types.UNSPECIFIED - }, false, - }, - { - "data type for SignatureTwo is unspecified", - func(misbehaviour *types.Misbehaviour) { - misbehaviour.SignatureTwo.DataType = types.UNSPECIFIED - }, false, - }, - { - "timestamp for SignatureOne is zero", - func(misbehaviour *types.Misbehaviour) { - misbehaviour.SignatureOne.Timestamp = 0 - }, false, - }, - { - "timestamp for SignatureTwo is zero", - func(misbehaviour *types.Misbehaviour) { - misbehaviour.SignatureTwo.Timestamp = 0 - }, false, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - - misbehaviour := solomachine.CreateMisbehaviour() - tc.malleateMisbehaviour(misbehaviour) - - err := misbehaviour.ValidateBasic() - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } - } -} diff --git a/x/ibc/light-clients/06-solomachine/types/proof.go b/x/ibc/light-clients/06-solomachine/types/proof.go deleted file mode 100644 index 6c2e0b842886..000000000000 --- a/x/ibc/light-clients/06-solomachine/types/proof.go +++ /dev/null @@ -1,475 +0,0 @@ -package types - -import ( - "github.com/cosmos/cosmos-sdk/codec" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" - "github.com/cosmos/cosmos-sdk/crypto/types/multisig" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/cosmos/cosmos-sdk/types/tx/signing" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -// VerifySignature verifies if the the provided public key generated the signature -// over the given data. Single and Multi signature public keys are supported. -// The signature data type must correspond to the public key type. An error is -// returned if signature verification fails or an invalid SignatureData type is -// provided. -func VerifySignature(pubKey cryptotypes.PubKey, signBytes []byte, sigData signing.SignatureData) error { - switch pubKey := pubKey.(type) { - case multisig.PubKey: - data, ok := sigData.(*signing.MultiSignatureData) - if !ok { - return sdkerrors.Wrapf(ErrSignatureVerificationFailed, "invalid signature data type, expected %T, got %T", (*signing.MultiSignatureData)(nil), data) - } - - // The function supplied fulfills the VerifyMultisignature interface. No special - // adjustments need to be made to the sign bytes based on the sign mode. - if err := pubKey.VerifyMultisignature(func(signing.SignMode) ([]byte, error) { - return signBytes, nil - }, data); err != nil { - return err - } - - default: - data, ok := sigData.(*signing.SingleSignatureData) - if !ok { - return sdkerrors.Wrapf(ErrSignatureVerificationFailed, "invalid signature data type, expected %T, got %T", (*signing.SingleSignatureData)(nil), data) - } - - if !pubKey.VerifySignature(signBytes, data.Signature) { - return ErrSignatureVerificationFailed - } - } - - return nil -} - -// MisbehaviourSignBytes returns the sign bytes for verification of misbehaviour. -func MisbehaviourSignBytes( - cdc codec.BinaryMarshaler, - sequence, timestamp uint64, - diversifier string, - dataType DataType, - data []byte) ([]byte, error) { - signBytes := &SignBytes{ - Sequence: sequence, - Timestamp: timestamp, - Diversifier: diversifier, - DataType: dataType, - Data: data, - } - - return cdc.MarshalBinaryBare(signBytes) -} - -// HeaderSignBytes returns the sign bytes for verification of misbehaviour. -func HeaderSignBytes( - cdc codec.BinaryMarshaler, - header *Header, -) ([]byte, error) { - data := &HeaderData{ - NewPubKey: header.NewPublicKey, - NewDiversifier: header.NewDiversifier, - } - - dataBz, err := cdc.MarshalBinaryBare(data) - if err != nil { - return nil, err - } - - signBytes := &SignBytes{ - Sequence: header.Sequence, - Timestamp: header.Timestamp, - Diversifier: header.NewDiversifier, - DataType: HEADER, - Data: dataBz, - } - - return cdc.MarshalBinaryBare(signBytes) -} - -// ClientStateSignBytes returns the sign bytes for verification of the -// client state. -func ClientStateSignBytes( - cdc codec.BinaryMarshaler, - sequence, timestamp uint64, - diversifier string, - path commitmenttypes.MerklePath, - clientState exported.ClientState, -) ([]byte, error) { - dataBz, err := ClientStateDataBytes(cdc, path, clientState) - if err != nil { - return nil, err - } - - signBytes := &SignBytes{ - Sequence: sequence, - Timestamp: timestamp, - Diversifier: diversifier, - DataType: CLIENT, - Data: dataBz, - } - - return cdc.MarshalBinaryBare(signBytes) -} - -// ClientStateDataBytes returns the client state data bytes used in constructing -// SignBytes. -func ClientStateDataBytes( - cdc codec.BinaryMarshaler, - path commitmenttypes.MerklePath, // nolint: interfacer - clientState exported.ClientState, -) ([]byte, error) { - any, err := clienttypes.PackClientState(clientState) - if err != nil { - return nil, err - } - - data := &ClientStateData{ - Path: []byte(path.String()), - ClientState: any, - } - - dataBz, err := cdc.MarshalBinaryBare(data) - if err != nil { - return nil, err - } - - return dataBz, nil -} - -// ConsensusStateSignBytes returns the sign bytes for verification of the -// consensus state. -func ConsensusStateSignBytes( - cdc codec.BinaryMarshaler, - sequence, timestamp uint64, - diversifier string, - path commitmenttypes.MerklePath, - consensusState exported.ConsensusState, -) ([]byte, error) { - dataBz, err := ConsensusStateDataBytes(cdc, path, consensusState) - if err != nil { - return nil, err - } - - signBytes := &SignBytes{ - Sequence: sequence, - Timestamp: timestamp, - Diversifier: diversifier, - DataType: CONSENSUS, - Data: dataBz, - } - - return cdc.MarshalBinaryBare(signBytes) -} - -// ConsensusStateDataBytes returns the consensus state data bytes used in constructing -// SignBytes. -func ConsensusStateDataBytes( - cdc codec.BinaryMarshaler, - path commitmenttypes.MerklePath, // nolint: interfacer - consensusState exported.ConsensusState, -) ([]byte, error) { - any, err := clienttypes.PackConsensusState(consensusState) - if err != nil { - return nil, err - } - - data := &ConsensusStateData{ - Path: []byte(path.String()), - ConsensusState: any, - } - - dataBz, err := cdc.MarshalBinaryBare(data) - if err != nil { - return nil, err - } - - return dataBz, nil -} - -// ConnectionStateSignBytes returns the sign bytes for verification of the -// connection state. -func ConnectionStateSignBytes( - cdc codec.BinaryMarshaler, - sequence, timestamp uint64, - diversifier string, - path commitmenttypes.MerklePath, - connectionEnd exported.ConnectionI, -) ([]byte, error) { - dataBz, err := ConnectionStateDataBytes(cdc, path, connectionEnd) - if err != nil { - return nil, err - } - - signBytes := &SignBytes{ - Sequence: sequence, - Timestamp: timestamp, - Diversifier: diversifier, - DataType: CONNECTION, - Data: dataBz, - } - - return cdc.MarshalBinaryBare(signBytes) -} - -// ConnectionStateDataBytes returns the connection state data bytes used in constructing -// SignBytes. -func ConnectionStateDataBytes( - cdc codec.BinaryMarshaler, - path commitmenttypes.MerklePath, // nolint: interfacer - connectionEnd exported.ConnectionI, -) ([]byte, error) { - connection, ok := connectionEnd.(connectiontypes.ConnectionEnd) - if !ok { - return nil, sdkerrors.Wrapf( - connectiontypes.ErrInvalidConnection, - "expected type %T, got %T", connectiontypes.ConnectionEnd{}, connectionEnd, - ) - } - - data := &ConnectionStateData{ - Path: []byte(path.String()), - Connection: &connection, - } - - dataBz, err := cdc.MarshalBinaryBare(data) - if err != nil { - return nil, err - } - - return dataBz, nil -} - -// ChannelStateSignBytes returns the sign bytes for verification of the -// channel state. -func ChannelStateSignBytes( - cdc codec.BinaryMarshaler, - sequence, timestamp uint64, - diversifier string, - path commitmenttypes.MerklePath, - channelEnd exported.ChannelI, -) ([]byte, error) { - dataBz, err := ChannelStateDataBytes(cdc, path, channelEnd) - if err != nil { - return nil, err - } - - signBytes := &SignBytes{ - Sequence: sequence, - Timestamp: timestamp, - Diversifier: diversifier, - DataType: CHANNEL, - Data: dataBz, - } - - return cdc.MarshalBinaryBare(signBytes) -} - -// ChannelStateDataBytes returns the channel state data bytes used in constructing -// SignBytes. -func ChannelStateDataBytes( - cdc codec.BinaryMarshaler, - path commitmenttypes.MerklePath, // nolint: interfacer - channelEnd exported.ChannelI, -) ([]byte, error) { - channel, ok := channelEnd.(channeltypes.Channel) - if !ok { - return nil, sdkerrors.Wrapf( - channeltypes.ErrInvalidChannel, - "expected channel type %T, got %T", channeltypes.Channel{}, channelEnd) - } - - data := &ChannelStateData{ - Path: []byte(path.String()), - Channel: &channel, - } - - dataBz, err := cdc.MarshalBinaryBare(data) - if err != nil { - return nil, err - } - - return dataBz, nil -} - -// PacketCommitmentSignBytes returns the sign bytes for verification of the -// packet commitment. -func PacketCommitmentSignBytes( - cdc codec.BinaryMarshaler, - sequence, timestamp uint64, - diversifier string, - path commitmenttypes.MerklePath, - commitmentBytes []byte, -) ([]byte, error) { - dataBz, err := PacketCommitmentDataBytes(cdc, path, commitmentBytes) - if err != nil { - return nil, err - } - - signBytes := &SignBytes{ - Sequence: sequence, - Timestamp: timestamp, - Diversifier: diversifier, - DataType: PACKETCOMMITMENT, - Data: dataBz, - } - - return cdc.MarshalBinaryBare(signBytes) -} - -// PacketCommitmentDataBytes returns the packet commitment data bytes used in constructing -// SignBytes. -func PacketCommitmentDataBytes( - cdc codec.BinaryMarshaler, - path commitmenttypes.MerklePath, // nolint: interfacer - commitmentBytes []byte, -) ([]byte, error) { - data := &PacketCommitmentData{ - Path: []byte(path.String()), - Commitment: commitmentBytes, - } - - dataBz, err := cdc.MarshalBinaryBare(data) - if err != nil { - return nil, err - } - - return dataBz, nil -} - -// PacketAcknowledgementSignBytes returns the sign bytes for verification of -// the acknowledgement. -func PacketAcknowledgementSignBytes( - cdc codec.BinaryMarshaler, - sequence, timestamp uint64, - diversifier string, - path commitmenttypes.MerklePath, - acknowledgement []byte, -) ([]byte, error) { - dataBz, err := PacketAcknowledgementDataBytes(cdc, path, acknowledgement) - if err != nil { - return nil, err - } - - signBytes := &SignBytes{ - Sequence: sequence, - Timestamp: timestamp, - Diversifier: diversifier, - DataType: PACKETACKNOWLEDGEMENT, - Data: dataBz, - } - - return cdc.MarshalBinaryBare(signBytes) -} - -// PacketAcknowledgementDataBytes returns the packet acknowledgement data bytes used in constructing -// SignBytes. -func PacketAcknowledgementDataBytes( - cdc codec.BinaryMarshaler, - path commitmenttypes.MerklePath, // nolint: interfacer - acknowledgement []byte, -) ([]byte, error) { - data := &PacketAcknowledgementData{ - Path: []byte(path.String()), - Acknowledgement: acknowledgement, - } - - dataBz, err := cdc.MarshalBinaryBare(data) - if err != nil { - return nil, err - } - - return dataBz, nil -} - -// PacketReceiptAbsenceSignBytes returns the sign bytes for verification -// of the absence of an receipt. -func PacketReceiptAbsenceSignBytes( - cdc codec.BinaryMarshaler, - sequence, timestamp uint64, - diversifier string, - path commitmenttypes.MerklePath, -) ([]byte, error) { - dataBz, err := PacketReceiptAbsenceDataBytes(cdc, path) - if err != nil { - return nil, err - } - - signBytes := &SignBytes{ - Sequence: sequence, - Timestamp: timestamp, - Diversifier: diversifier, - DataType: PACKETRECEIPTABSENCE, - Data: dataBz, - } - - return cdc.MarshalBinaryBare(signBytes) -} - -// PacketReceiptAbsenceDataBytes returns the packet receipt absence data bytes -// used in constructing SignBytes. -func PacketReceiptAbsenceDataBytes( - cdc codec.BinaryMarshaler, - path commitmenttypes.MerklePath, // nolint: interfacer -) ([]byte, error) { - data := &PacketReceiptAbsenceData{ - Path: []byte(path.String()), - } - - dataBz, err := cdc.MarshalBinaryBare(data) - if err != nil { - return nil, err - } - - return dataBz, nil -} - -// NextSequenceRecvSignBytes returns the sign bytes for verification of the next -// sequence to be received. -func NextSequenceRecvSignBytes( - cdc codec.BinaryMarshaler, - sequence, timestamp uint64, - diversifier string, - path commitmenttypes.MerklePath, - nextSequenceRecv uint64, -) ([]byte, error) { - dataBz, err := NextSequenceRecvDataBytes(cdc, path, nextSequenceRecv) - if err != nil { - return nil, err - } - - signBytes := &SignBytes{ - Sequence: sequence, - Timestamp: timestamp, - Diversifier: diversifier, - DataType: NEXTSEQUENCERECV, - Data: dataBz, - } - - return cdc.MarshalBinaryBare(signBytes) -} - -// NextSequenceRecvDataBytes returns the next sequence recv data bytes used in constructing -// SignBytes. -func NextSequenceRecvDataBytes( - cdc codec.BinaryMarshaler, - path commitmenttypes.MerklePath, // nolint: interfacer - nextSequenceRecv uint64, -) ([]byte, error) { - data := &NextSequenceRecvData{ - Path: []byte(path.String()), - NextSeqRecv: nextSequenceRecv, - } - - dataBz, err := cdc.MarshalBinaryBare(data) - if err != nil { - return nil, err - } - - return dataBz, nil -} diff --git a/x/ibc/light-clients/06-solomachine/types/proof_test.go b/x/ibc/light-clients/06-solomachine/types/proof_test.go deleted file mode 100644 index e2ba679a5b98..000000000000 --- a/x/ibc/light-clients/06-solomachine/types/proof_test.go +++ /dev/null @@ -1,102 +0,0 @@ -package types_test - -import ( - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" - "github.com/cosmos/cosmos-sdk/types/tx/signing" - "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/06-solomachine/types" - solomachinetypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/06-solomachine/types" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" -) - -func (suite *SoloMachineTestSuite) TestVerifySignature() { - cdc := suite.chainA.App.AppCodec() - signBytes := []byte("sign bytes") - - singleSignature := suite.solomachine.GenerateSignature(signBytes) - singleSigData, err := solomachinetypes.UnmarshalSignatureData(cdc, singleSignature) - suite.Require().NoError(err) - - multiSignature := suite.solomachineMulti.GenerateSignature(signBytes) - multiSigData, err := solomachinetypes.UnmarshalSignatureData(cdc, multiSignature) - suite.Require().NoError(err) - - testCases := []struct { - name string - publicKey cryptotypes.PubKey - sigData signing.SignatureData - expPass bool - }{ - { - "single signature with regular public key", - suite.solomachine.PublicKey, - singleSigData, - true, - }, - { - "multi signature with multisig public key", - suite.solomachineMulti.PublicKey, - multiSigData, - true, - }, - { - "single signature with multisig public key", - suite.solomachineMulti.PublicKey, - singleSigData, - false, - }, - { - "multi signature with regular public key", - suite.solomachine.PublicKey, - multiSigData, - false, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - err := solomachinetypes.VerifySignature(tc.publicKey, signBytes, tc.sigData) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} - -func (suite *SoloMachineTestSuite) TestClientStateSignBytes() { - cdc := suite.chainA.App.AppCodec() - - for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} { - // success - path := solomachine.GetClientStatePath(counterpartyClientIdentifier) - bz, err := types.ClientStateSignBytes(cdc, solomachine.Sequence, solomachine.Time, solomachine.Diversifier, path, solomachine.ClientState()) - suite.Require().NoError(err) - suite.Require().NotNil(bz) - - // nil client state - bz, err = types.ClientStateSignBytes(cdc, solomachine.Sequence, solomachine.Time, solomachine.Diversifier, path, nil) - suite.Require().Error(err) - suite.Require().Nil(bz) - } -} - -func (suite *SoloMachineTestSuite) TestConsensusStateSignBytes() { - cdc := suite.chainA.App.AppCodec() - - for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} { - // success - path := solomachine.GetConsensusStatePath(counterpartyClientIdentifier, consensusHeight) - bz, err := types.ConsensusStateSignBytes(cdc, solomachine.Sequence, solomachine.Time, solomachine.Diversifier, path, solomachine.ConsensusState()) - suite.Require().NoError(err) - suite.Require().NotNil(bz) - - // nil consensus state - bz, err = types.ConsensusStateSignBytes(cdc, solomachine.Sequence, solomachine.Time, solomachine.Diversifier, path, nil) - suite.Require().Error(err) - suite.Require().Nil(bz) - } -} diff --git a/x/ibc/light-clients/06-solomachine/types/proposal_handle.go b/x/ibc/light-clients/06-solomachine/types/proposal_handle.go deleted file mode 100644 index e38155b23615..000000000000 --- a/x/ibc/light-clients/06-solomachine/types/proposal_handle.go +++ /dev/null @@ -1,64 +0,0 @@ -package types - -import ( - "reflect" - - "github.com/cosmos/cosmos-sdk/codec" - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -// 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, sdkerrors.Wrapf( - clienttypes.ErrUpdateClientFailed, - "solo machine client is not allowed to updated with a proposal", - ) - } - - substituteClientState, ok := substituteClient.(*ClientState) - if !ok { - return nil, sdkerrors.Wrapf( - clienttypes.ErrInvalidClientType, "substitute client state type %T, expected %T", substituteClient, &ClientState{}, - ) - } - - subjectPublicKey, err := cs.ConsensusState.GetPubKey() - if err != nil { - return nil, sdkerrors.Wrap(err, "failed to get consensus public key") - } - - substitutePublicKey, err := substituteClientState.ConsensusState.GetPubKey() - if err != nil { - return nil, sdkerrors.Wrap(err, "failed to get substitute client public key") - } - - if reflect.DeepEqual(subjectPublicKey, substitutePublicKey) { - return nil, sdkerrors.Wrapf( - clienttypes.ErrInvalidHeader, "subject and substitute have the same public key", - ) - } - - clientState := &cs - - // update to substitute parameters - clientState.Sequence = substituteClientState.Sequence - clientState.ConsensusState = substituteClientState.ConsensusState - clientState.FrozenSequence = 0 - - 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 deleted file mode 100644 index 0113da104497..000000000000 --- a/x/ibc/light-clients/06-solomachine/types/proposal_handle_test.go +++ /dev/null @@ -1,88 +0,0 @@ -package types_test - -import ( - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/06-solomachine/types" - ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" -) - -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} { - - testCases := []struct { - name string - malleate func() - expPass bool - }{ - { - "valid substitute", func() { - subjectClientState.AllowUpdateAfterProposal = true - }, true, - }, - { - "subject not allowed to be updated", func() { - subjectClientState.AllowUpdateAfterProposal = false - }, false, - }, - { - "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, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - suite.SetupTest() - - subjectClientState = solomachine.ClientState() - subjectClientState.AllowUpdateAfterProposal = true - substitute := ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "substitute", "testing", 5) - substituteClientState = substitute.ClientState() - - tc.malleate() - - subjectClientStore := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), solomachine.ClientID) - substituteClientStore := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), substitute.ClientID) - - updatedClient, err := subjectClientState.CheckSubstituteAndUpdateState(suite.chainA.GetContext(), suite.chainA.App.AppCodec(), subjectClientStore, substituteClientStore, substituteClientState, nil) - - if tc.expPass { - suite.Require().NoError(err) - - 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(updatedClient) - } - }) - } - } -} diff --git a/x/ibc/light-clients/06-solomachine/types/solomachine.go b/x/ibc/light-clients/06-solomachine/types/solomachine.go deleted file mode 100644 index d3936ef42747..000000000000 --- a/x/ibc/light-clients/06-solomachine/types/solomachine.go +++ /dev/null @@ -1,43 +0,0 @@ -package types - -import ( - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -// Interface implementation checks. -var _, _, _, _ codectypes.UnpackInterfacesMessage = &ClientState{}, &ConsensusState{}, &Header{}, &HeaderData{} - -// Data is an interface used for all the signature data bytes proto definitions. -type Data interface{} - -// UnpackInterfaces implements the UnpackInterfaceMessages.UnpackInterfaces method -func (cs ClientState) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { - return cs.ConsensusState.UnpackInterfaces(unpacker) -} - -// UnpackInterfaces implements the UnpackInterfaceMessages.UnpackInterfaces method -func (cs ConsensusState) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { - return unpacker.UnpackAny(cs.PublicKey, new(cryptotypes.PubKey)) -} - -// UnpackInterfaces implements the UnpackInterfaceMessages.UnpackInterfaces method -func (h Header) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { - return unpacker.UnpackAny(h.NewPublicKey, new(cryptotypes.PubKey)) -} - -// UnpackInterfaces implements the UnpackInterfaceMessages.UnpackInterfaces method -func (hd HeaderData) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { - return unpacker.UnpackAny(hd.NewPubKey, new(cryptotypes.PubKey)) -} - -// UnpackInterfaces implements the UnpackInterfaceMessages.UnpackInterfaces method -func (csd ClientStateData) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { - return unpacker.UnpackAny(csd.ClientState, new(exported.ClientState)) -} - -// UnpackInterfaces implements the UnpackInterfaceMessages.UnpackInterfaces method -func (csd ConsensusStateData) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { - return unpacker.UnpackAny(csd.ConsensusState, new(exported.ConsensusState)) -} diff --git a/x/ibc/light-clients/06-solomachine/types/solomachine.pb.go b/x/ibc/light-clients/06-solomachine/types/solomachine.pb.go deleted file mode 100644 index 8b31fb0d4116..000000000000 --- a/x/ibc/light-clients/06-solomachine/types/solomachine.pb.go +++ /dev/null @@ -1,4118 +0,0 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: ibc/lightclients/solomachine/v1/solomachine.proto - -package types - -import ( - fmt "fmt" - types "github.com/cosmos/cosmos-sdk/codec/types" - types1 "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - types2 "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - _ "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 - -// DataType defines the type of solo machine proof being created. This is done to preserve uniqueness of different -// data sign byte encodings. -type DataType int32 - -const ( - // Default State - UNSPECIFIED DataType = 0 - // Data type for client state verification - CLIENT DataType = 1 - // Data type for consensus state verification - CONSENSUS DataType = 2 - // Data type for connection state verification - CONNECTION DataType = 3 - // Data type for channel state verification - CHANNEL DataType = 4 - // Data type for packet commitment verification - PACKETCOMMITMENT DataType = 5 - // Data type for packet acknowledgement verification - PACKETACKNOWLEDGEMENT DataType = 6 - // Data type for packet receipt absence verification - PACKETRECEIPTABSENCE DataType = 7 - // Data type for next sequence recv verification - NEXTSEQUENCERECV DataType = 8 - // Data type for header verification - HEADER DataType = 9 -) - -var DataType_name = map[int32]string{ - 0: "DATA_TYPE_UNINITIALIZED_UNSPECIFIED", - 1: "DATA_TYPE_CLIENT_STATE", - 2: "DATA_TYPE_CONSENSUS_STATE", - 3: "DATA_TYPE_CONNECTION_STATE", - 4: "DATA_TYPE_CHANNEL_STATE", - 5: "DATA_TYPE_PACKET_COMMITMENT", - 6: "DATA_TYPE_PACKET_ACKNOWLEDGEMENT", - 7: "DATA_TYPE_PACKET_RECEIPT_ABSENCE", - 8: "DATA_TYPE_NEXT_SEQUENCE_RECV", - 9: "DATA_TYPE_HEADER", -} - -var DataType_value = map[string]int32{ - "DATA_TYPE_UNINITIALIZED_UNSPECIFIED": 0, - "DATA_TYPE_CLIENT_STATE": 1, - "DATA_TYPE_CONSENSUS_STATE": 2, - "DATA_TYPE_CONNECTION_STATE": 3, - "DATA_TYPE_CHANNEL_STATE": 4, - "DATA_TYPE_PACKET_COMMITMENT": 5, - "DATA_TYPE_PACKET_ACKNOWLEDGEMENT": 6, - "DATA_TYPE_PACKET_RECEIPT_ABSENCE": 7, - "DATA_TYPE_NEXT_SEQUENCE_RECV": 8, - "DATA_TYPE_HEADER": 9, -} - -func (x DataType) String() string { - return proto.EnumName(DataType_name, int32(x)) -} - -func (DataType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_6cc2ee18f7f86d4e, []int{0} -} - -// ClientState defines a solo machine client that tracks the current consensus -// state and if the client is frozen. -type ClientState struct { - // latest sequence of the client state - Sequence uint64 `protobuf:"varint,1,opt,name=sequence,proto3" json:"sequence,omitempty"` - // frozen sequence of the solo machine - FrozenSequence uint64 `protobuf:"varint,2,opt,name=frozen_sequence,json=frozenSequence,proto3" json:"frozen_sequence,omitempty" yaml:"frozen_sequence"` - ConsensusState *ConsensusState `protobuf:"bytes,3,opt,name=consensus_state,json=consensusState,proto3" json:"consensus_state,omitempty" yaml:"consensus_state"` - // when set to true, will allow governance to update a solo machine client. - // The client will be unfrozen if it is frozen. - AllowUpdateAfterProposal bool `protobuf:"varint,4,opt,name=allow_update_after_proposal,json=allowUpdateAfterProposal,proto3" json:"allow_update_after_proposal,omitempty" yaml:"allow_update_after_proposal"` -} - -func (m *ClientState) Reset() { *m = ClientState{} } -func (m *ClientState) String() string { return proto.CompactTextString(m) } -func (*ClientState) ProtoMessage() {} -func (*ClientState) Descriptor() ([]byte, []int) { - return fileDescriptor_6cc2ee18f7f86d4e, []int{0} -} -func (m *ClientState) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *ClientState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_ClientState.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 *ClientState) XXX_Merge(src proto.Message) { - xxx_messageInfo_ClientState.Merge(m, src) -} -func (m *ClientState) XXX_Size() int { - return m.Size() -} -func (m *ClientState) XXX_DiscardUnknown() { - xxx_messageInfo_ClientState.DiscardUnknown(m) -} - -var xxx_messageInfo_ClientState proto.InternalMessageInfo - -// ConsensusState defines a solo machine consensus state. The sequence of a consensus state -// is contained in the "height" key used in storing the consensus state. -type ConsensusState struct { - // public key of the solo machine - PublicKey *types.Any `protobuf:"bytes,1,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty" yaml:"public_key"` - // diversifier allows the same public key to be re-used across different solo machine clients - // (potentially on different chains) without being considered misbehaviour. - Diversifier string `protobuf:"bytes,2,opt,name=diversifier,proto3" json:"diversifier,omitempty"` - Timestamp uint64 `protobuf:"varint,3,opt,name=timestamp,proto3" json:"timestamp,omitempty"` -} - -func (m *ConsensusState) Reset() { *m = ConsensusState{} } -func (m *ConsensusState) String() string { return proto.CompactTextString(m) } -func (*ConsensusState) ProtoMessage() {} -func (*ConsensusState) Descriptor() ([]byte, []int) { - return fileDescriptor_6cc2ee18f7f86d4e, []int{1} -} -func (m *ConsensusState) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *ConsensusState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_ConsensusState.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 *ConsensusState) XXX_Merge(src proto.Message) { - xxx_messageInfo_ConsensusState.Merge(m, src) -} -func (m *ConsensusState) XXX_Size() int { - return m.Size() -} -func (m *ConsensusState) XXX_DiscardUnknown() { - xxx_messageInfo_ConsensusState.DiscardUnknown(m) -} - -var xxx_messageInfo_ConsensusState proto.InternalMessageInfo - -// Header defines a solo machine consensus header -type Header struct { - // sequence to update solo machine public key at - Sequence uint64 `protobuf:"varint,1,opt,name=sequence,proto3" json:"sequence,omitempty"` - Timestamp uint64 `protobuf:"varint,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"` - Signature []byte `protobuf:"bytes,3,opt,name=signature,proto3" json:"signature,omitempty"` - NewPublicKey *types.Any `protobuf:"bytes,4,opt,name=new_public_key,json=newPublicKey,proto3" json:"new_public_key,omitempty" yaml:"new_public_key"` - NewDiversifier string `protobuf:"bytes,5,opt,name=new_diversifier,json=newDiversifier,proto3" json:"new_diversifier,omitempty" yaml:"new_diversifier"` -} - -func (m *Header) Reset() { *m = Header{} } -func (m *Header) String() string { return proto.CompactTextString(m) } -func (*Header) ProtoMessage() {} -func (*Header) Descriptor() ([]byte, []int) { - return fileDescriptor_6cc2ee18f7f86d4e, []int{2} -} -func (m *Header) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *Header) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_Header.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 *Header) XXX_Merge(src proto.Message) { - xxx_messageInfo_Header.Merge(m, src) -} -func (m *Header) XXX_Size() int { - return m.Size() -} -func (m *Header) XXX_DiscardUnknown() { - xxx_messageInfo_Header.DiscardUnknown(m) -} - -var xxx_messageInfo_Header proto.InternalMessageInfo - -// Misbehaviour defines misbehaviour for a solo machine which consists -// of a sequence and two signatures over different messages at that sequence. -type Misbehaviour struct { - ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty" yaml:"client_id"` - Sequence uint64 `protobuf:"varint,2,opt,name=sequence,proto3" json:"sequence,omitempty"` - SignatureOne *SignatureAndData `protobuf:"bytes,3,opt,name=signature_one,json=signatureOne,proto3" json:"signature_one,omitempty" yaml:"signature_one"` - SignatureTwo *SignatureAndData `protobuf:"bytes,4,opt,name=signature_two,json=signatureTwo,proto3" json:"signature_two,omitempty" yaml:"signature_two"` -} - -func (m *Misbehaviour) Reset() { *m = Misbehaviour{} } -func (m *Misbehaviour) String() string { return proto.CompactTextString(m) } -func (*Misbehaviour) ProtoMessage() {} -func (*Misbehaviour) Descriptor() ([]byte, []int) { - return fileDescriptor_6cc2ee18f7f86d4e, []int{3} -} -func (m *Misbehaviour) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *Misbehaviour) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_Misbehaviour.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 *Misbehaviour) XXX_Merge(src proto.Message) { - xxx_messageInfo_Misbehaviour.Merge(m, src) -} -func (m *Misbehaviour) XXX_Size() int { - return m.Size() -} -func (m *Misbehaviour) XXX_DiscardUnknown() { - xxx_messageInfo_Misbehaviour.DiscardUnknown(m) -} - -var xxx_messageInfo_Misbehaviour proto.InternalMessageInfo - -// SignatureAndData contains a signature and the data signed over to create that -// signature. -type SignatureAndData struct { - Signature []byte `protobuf:"bytes,1,opt,name=signature,proto3" json:"signature,omitempty"` - DataType DataType `protobuf:"varint,2,opt,name=data_type,json=dataType,proto3,enum=ibc.lightclients.solomachine.v1.DataType" json:"data_type,omitempty" yaml:"data_type"` - Data []byte `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"` - Timestamp uint64 `protobuf:"varint,4,opt,name=timestamp,proto3" json:"timestamp,omitempty"` -} - -func (m *SignatureAndData) Reset() { *m = SignatureAndData{} } -func (m *SignatureAndData) String() string { return proto.CompactTextString(m) } -func (*SignatureAndData) ProtoMessage() {} -func (*SignatureAndData) Descriptor() ([]byte, []int) { - return fileDescriptor_6cc2ee18f7f86d4e, []int{4} -} -func (m *SignatureAndData) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *SignatureAndData) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_SignatureAndData.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 *SignatureAndData) XXX_Merge(src proto.Message) { - xxx_messageInfo_SignatureAndData.Merge(m, src) -} -func (m *SignatureAndData) XXX_Size() int { - return m.Size() -} -func (m *SignatureAndData) XXX_DiscardUnknown() { - xxx_messageInfo_SignatureAndData.DiscardUnknown(m) -} - -var xxx_messageInfo_SignatureAndData proto.InternalMessageInfo - -// TimestampedSignatureData contains the signature data and the timestamp of the -// signature. -type TimestampedSignatureData struct { - SignatureData []byte `protobuf:"bytes,1,opt,name=signature_data,json=signatureData,proto3" json:"signature_data,omitempty" yaml:"signature_data"` - Timestamp uint64 `protobuf:"varint,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"` -} - -func (m *TimestampedSignatureData) Reset() { *m = TimestampedSignatureData{} } -func (m *TimestampedSignatureData) String() string { return proto.CompactTextString(m) } -func (*TimestampedSignatureData) ProtoMessage() {} -func (*TimestampedSignatureData) Descriptor() ([]byte, []int) { - return fileDescriptor_6cc2ee18f7f86d4e, []int{5} -} -func (m *TimestampedSignatureData) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *TimestampedSignatureData) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_TimestampedSignatureData.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 *TimestampedSignatureData) XXX_Merge(src proto.Message) { - xxx_messageInfo_TimestampedSignatureData.Merge(m, src) -} -func (m *TimestampedSignatureData) XXX_Size() int { - return m.Size() -} -func (m *TimestampedSignatureData) XXX_DiscardUnknown() { - xxx_messageInfo_TimestampedSignatureData.DiscardUnknown(m) -} - -var xxx_messageInfo_TimestampedSignatureData proto.InternalMessageInfo - -// SignBytes defines the signed bytes used for signature verification. -type SignBytes struct { - Sequence uint64 `protobuf:"varint,1,opt,name=sequence,proto3" json:"sequence,omitempty"` - Timestamp uint64 `protobuf:"varint,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"` - Diversifier string `protobuf:"bytes,3,opt,name=diversifier,proto3" json:"diversifier,omitempty"` - // type of the data used - DataType DataType `protobuf:"varint,4,opt,name=data_type,json=dataType,proto3,enum=ibc.lightclients.solomachine.v1.DataType" json:"data_type,omitempty" yaml:"data_type"` - // marshaled data - Data []byte `protobuf:"bytes,5,opt,name=data,proto3" json:"data,omitempty"` -} - -func (m *SignBytes) Reset() { *m = SignBytes{} } -func (m *SignBytes) String() string { return proto.CompactTextString(m) } -func (*SignBytes) ProtoMessage() {} -func (*SignBytes) Descriptor() ([]byte, []int) { - return fileDescriptor_6cc2ee18f7f86d4e, []int{6} -} -func (m *SignBytes) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *SignBytes) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_SignBytes.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 *SignBytes) XXX_Merge(src proto.Message) { - xxx_messageInfo_SignBytes.Merge(m, src) -} -func (m *SignBytes) XXX_Size() int { - return m.Size() -} -func (m *SignBytes) XXX_DiscardUnknown() { - xxx_messageInfo_SignBytes.DiscardUnknown(m) -} - -var xxx_messageInfo_SignBytes proto.InternalMessageInfo - -// HeaderData returns the SignBytes data for update verification. -type HeaderData struct { - // header public key - NewPubKey *types.Any `protobuf:"bytes,1,opt,name=new_pub_key,json=newPubKey,proto3" json:"new_pub_key,omitempty" yaml:"new_pub_key"` - // header diversifier - NewDiversifier string `protobuf:"bytes,2,opt,name=new_diversifier,json=newDiversifier,proto3" json:"new_diversifier,omitempty" yaml:"new_diversifier"` -} - -func (m *HeaderData) Reset() { *m = HeaderData{} } -func (m *HeaderData) String() string { return proto.CompactTextString(m) } -func (*HeaderData) ProtoMessage() {} -func (*HeaderData) Descriptor() ([]byte, []int) { - return fileDescriptor_6cc2ee18f7f86d4e, []int{7} -} -func (m *HeaderData) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *HeaderData) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_HeaderData.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 *HeaderData) XXX_Merge(src proto.Message) { - xxx_messageInfo_HeaderData.Merge(m, src) -} -func (m *HeaderData) XXX_Size() int { - return m.Size() -} -func (m *HeaderData) XXX_DiscardUnknown() { - xxx_messageInfo_HeaderData.DiscardUnknown(m) -} - -var xxx_messageInfo_HeaderData proto.InternalMessageInfo - -// ClientStateData returns the SignBytes data for client state verification. -type ClientStateData struct { - Path []byte `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` - ClientState *types.Any `protobuf:"bytes,2,opt,name=client_state,json=clientState,proto3" json:"client_state,omitempty" yaml:"client_state"` -} - -func (m *ClientStateData) Reset() { *m = ClientStateData{} } -func (m *ClientStateData) String() string { return proto.CompactTextString(m) } -func (*ClientStateData) ProtoMessage() {} -func (*ClientStateData) Descriptor() ([]byte, []int) { - return fileDescriptor_6cc2ee18f7f86d4e, []int{8} -} -func (m *ClientStateData) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *ClientStateData) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_ClientStateData.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 *ClientStateData) XXX_Merge(src proto.Message) { - xxx_messageInfo_ClientStateData.Merge(m, src) -} -func (m *ClientStateData) XXX_Size() int { - return m.Size() -} -func (m *ClientStateData) XXX_DiscardUnknown() { - xxx_messageInfo_ClientStateData.DiscardUnknown(m) -} - -var xxx_messageInfo_ClientStateData proto.InternalMessageInfo - -// ConsensusStateData returns the SignBytes data for consensus state -// verification. -type ConsensusStateData struct { - Path []byte `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` - ConsensusState *types.Any `protobuf:"bytes,2,opt,name=consensus_state,json=consensusState,proto3" json:"consensus_state,omitempty" yaml:"consensus_state"` -} - -func (m *ConsensusStateData) Reset() { *m = ConsensusStateData{} } -func (m *ConsensusStateData) String() string { return proto.CompactTextString(m) } -func (*ConsensusStateData) ProtoMessage() {} -func (*ConsensusStateData) Descriptor() ([]byte, []int) { - return fileDescriptor_6cc2ee18f7f86d4e, []int{9} -} -func (m *ConsensusStateData) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *ConsensusStateData) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_ConsensusStateData.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 *ConsensusStateData) XXX_Merge(src proto.Message) { - xxx_messageInfo_ConsensusStateData.Merge(m, src) -} -func (m *ConsensusStateData) XXX_Size() int { - return m.Size() -} -func (m *ConsensusStateData) XXX_DiscardUnknown() { - xxx_messageInfo_ConsensusStateData.DiscardUnknown(m) -} - -var xxx_messageInfo_ConsensusStateData proto.InternalMessageInfo - -// ConnectionStateData returns the SignBytes data for connection state -// verification. -type ConnectionStateData struct { - Path []byte `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` - Connection *types1.ConnectionEnd `protobuf:"bytes,2,opt,name=connection,proto3" json:"connection,omitempty"` -} - -func (m *ConnectionStateData) Reset() { *m = ConnectionStateData{} } -func (m *ConnectionStateData) String() string { return proto.CompactTextString(m) } -func (*ConnectionStateData) ProtoMessage() {} -func (*ConnectionStateData) Descriptor() ([]byte, []int) { - return fileDescriptor_6cc2ee18f7f86d4e, []int{10} -} -func (m *ConnectionStateData) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *ConnectionStateData) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_ConnectionStateData.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 *ConnectionStateData) XXX_Merge(src proto.Message) { - xxx_messageInfo_ConnectionStateData.Merge(m, src) -} -func (m *ConnectionStateData) XXX_Size() int { - return m.Size() -} -func (m *ConnectionStateData) XXX_DiscardUnknown() { - xxx_messageInfo_ConnectionStateData.DiscardUnknown(m) -} - -var xxx_messageInfo_ConnectionStateData proto.InternalMessageInfo - -// ChannelStateData returns the SignBytes data for channel state -// verification. -type ChannelStateData struct { - Path []byte `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` - Channel *types2.Channel `protobuf:"bytes,2,opt,name=channel,proto3" json:"channel,omitempty"` -} - -func (m *ChannelStateData) Reset() { *m = ChannelStateData{} } -func (m *ChannelStateData) String() string { return proto.CompactTextString(m) } -func (*ChannelStateData) ProtoMessage() {} -func (*ChannelStateData) Descriptor() ([]byte, []int) { - return fileDescriptor_6cc2ee18f7f86d4e, []int{11} -} -func (m *ChannelStateData) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *ChannelStateData) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_ChannelStateData.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 *ChannelStateData) XXX_Merge(src proto.Message) { - xxx_messageInfo_ChannelStateData.Merge(m, src) -} -func (m *ChannelStateData) XXX_Size() int { - return m.Size() -} -func (m *ChannelStateData) XXX_DiscardUnknown() { - xxx_messageInfo_ChannelStateData.DiscardUnknown(m) -} - -var xxx_messageInfo_ChannelStateData proto.InternalMessageInfo - -// PacketCommitmentData returns the SignBytes data for packet commitment -// verification. -type PacketCommitmentData struct { - Path []byte `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` - Commitment []byte `protobuf:"bytes,2,opt,name=commitment,proto3" json:"commitment,omitempty"` -} - -func (m *PacketCommitmentData) Reset() { *m = PacketCommitmentData{} } -func (m *PacketCommitmentData) String() string { return proto.CompactTextString(m) } -func (*PacketCommitmentData) ProtoMessage() {} -func (*PacketCommitmentData) Descriptor() ([]byte, []int) { - return fileDescriptor_6cc2ee18f7f86d4e, []int{12} -} -func (m *PacketCommitmentData) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *PacketCommitmentData) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_PacketCommitmentData.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 *PacketCommitmentData) XXX_Merge(src proto.Message) { - xxx_messageInfo_PacketCommitmentData.Merge(m, src) -} -func (m *PacketCommitmentData) XXX_Size() int { - return m.Size() -} -func (m *PacketCommitmentData) XXX_DiscardUnknown() { - xxx_messageInfo_PacketCommitmentData.DiscardUnknown(m) -} - -var xxx_messageInfo_PacketCommitmentData proto.InternalMessageInfo - -func (m *PacketCommitmentData) GetPath() []byte { - if m != nil { - return m.Path - } - return nil -} - -func (m *PacketCommitmentData) GetCommitment() []byte { - if m != nil { - return m.Commitment - } - return nil -} - -// PacketAcknowledgementData returns the SignBytes data for acknowledgement -// verification. -type PacketAcknowledgementData struct { - Path []byte `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` - Acknowledgement []byte `protobuf:"bytes,2,opt,name=acknowledgement,proto3" json:"acknowledgement,omitempty"` -} - -func (m *PacketAcknowledgementData) Reset() { *m = PacketAcknowledgementData{} } -func (m *PacketAcknowledgementData) String() string { return proto.CompactTextString(m) } -func (*PacketAcknowledgementData) ProtoMessage() {} -func (*PacketAcknowledgementData) Descriptor() ([]byte, []int) { - return fileDescriptor_6cc2ee18f7f86d4e, []int{13} -} -func (m *PacketAcknowledgementData) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *PacketAcknowledgementData) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_PacketAcknowledgementData.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 *PacketAcknowledgementData) XXX_Merge(src proto.Message) { - xxx_messageInfo_PacketAcknowledgementData.Merge(m, src) -} -func (m *PacketAcknowledgementData) XXX_Size() int { - return m.Size() -} -func (m *PacketAcknowledgementData) XXX_DiscardUnknown() { - xxx_messageInfo_PacketAcknowledgementData.DiscardUnknown(m) -} - -var xxx_messageInfo_PacketAcknowledgementData proto.InternalMessageInfo - -func (m *PacketAcknowledgementData) GetPath() []byte { - if m != nil { - return m.Path - } - return nil -} - -func (m *PacketAcknowledgementData) GetAcknowledgement() []byte { - if m != nil { - return m.Acknowledgement - } - return nil -} - -// PacketReceiptAbsenceData returns the SignBytes data for -// packet receipt absence verification. -type PacketReceiptAbsenceData struct { - Path []byte `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` -} - -func (m *PacketReceiptAbsenceData) Reset() { *m = PacketReceiptAbsenceData{} } -func (m *PacketReceiptAbsenceData) String() string { return proto.CompactTextString(m) } -func (*PacketReceiptAbsenceData) ProtoMessage() {} -func (*PacketReceiptAbsenceData) Descriptor() ([]byte, []int) { - return fileDescriptor_6cc2ee18f7f86d4e, []int{14} -} -func (m *PacketReceiptAbsenceData) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *PacketReceiptAbsenceData) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_PacketReceiptAbsenceData.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 *PacketReceiptAbsenceData) XXX_Merge(src proto.Message) { - xxx_messageInfo_PacketReceiptAbsenceData.Merge(m, src) -} -func (m *PacketReceiptAbsenceData) XXX_Size() int { - return m.Size() -} -func (m *PacketReceiptAbsenceData) XXX_DiscardUnknown() { - xxx_messageInfo_PacketReceiptAbsenceData.DiscardUnknown(m) -} - -var xxx_messageInfo_PacketReceiptAbsenceData proto.InternalMessageInfo - -func (m *PacketReceiptAbsenceData) GetPath() []byte { - if m != nil { - return m.Path - } - return nil -} - -// NextSequenceRecvData returns the SignBytes data for verification of the next -// sequence to be received. -type NextSequenceRecvData struct { - Path []byte `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` - NextSeqRecv uint64 `protobuf:"varint,2,opt,name=next_seq_recv,json=nextSeqRecv,proto3" json:"next_seq_recv,omitempty" yaml:"next_seq_recv"` -} - -func (m *NextSequenceRecvData) Reset() { *m = NextSequenceRecvData{} } -func (m *NextSequenceRecvData) String() string { return proto.CompactTextString(m) } -func (*NextSequenceRecvData) ProtoMessage() {} -func (*NextSequenceRecvData) Descriptor() ([]byte, []int) { - return fileDescriptor_6cc2ee18f7f86d4e, []int{15} -} -func (m *NextSequenceRecvData) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *NextSequenceRecvData) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_NextSequenceRecvData.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 *NextSequenceRecvData) XXX_Merge(src proto.Message) { - xxx_messageInfo_NextSequenceRecvData.Merge(m, src) -} -func (m *NextSequenceRecvData) XXX_Size() int { - return m.Size() -} -func (m *NextSequenceRecvData) XXX_DiscardUnknown() { - xxx_messageInfo_NextSequenceRecvData.DiscardUnknown(m) -} - -var xxx_messageInfo_NextSequenceRecvData proto.InternalMessageInfo - -func (m *NextSequenceRecvData) GetPath() []byte { - if m != nil { - return m.Path - } - return nil -} - -func (m *NextSequenceRecvData) GetNextSeqRecv() uint64 { - if m != nil { - return m.NextSeqRecv - } - return 0 -} - -func init() { - proto.RegisterEnum("ibc.lightclients.solomachine.v1.DataType", DataType_name, DataType_value) - proto.RegisterType((*ClientState)(nil), "ibc.lightclients.solomachine.v1.ClientState") - proto.RegisterType((*ConsensusState)(nil), "ibc.lightclients.solomachine.v1.ConsensusState") - proto.RegisterType((*Header)(nil), "ibc.lightclients.solomachine.v1.Header") - proto.RegisterType((*Misbehaviour)(nil), "ibc.lightclients.solomachine.v1.Misbehaviour") - proto.RegisterType((*SignatureAndData)(nil), "ibc.lightclients.solomachine.v1.SignatureAndData") - proto.RegisterType((*TimestampedSignatureData)(nil), "ibc.lightclients.solomachine.v1.TimestampedSignatureData") - proto.RegisterType((*SignBytes)(nil), "ibc.lightclients.solomachine.v1.SignBytes") - proto.RegisterType((*HeaderData)(nil), "ibc.lightclients.solomachine.v1.HeaderData") - proto.RegisterType((*ClientStateData)(nil), "ibc.lightclients.solomachine.v1.ClientStateData") - proto.RegisterType((*ConsensusStateData)(nil), "ibc.lightclients.solomachine.v1.ConsensusStateData") - proto.RegisterType((*ConnectionStateData)(nil), "ibc.lightclients.solomachine.v1.ConnectionStateData") - proto.RegisterType((*ChannelStateData)(nil), "ibc.lightclients.solomachine.v1.ChannelStateData") - proto.RegisterType((*PacketCommitmentData)(nil), "ibc.lightclients.solomachine.v1.PacketCommitmentData") - proto.RegisterType((*PacketAcknowledgementData)(nil), "ibc.lightclients.solomachine.v1.PacketAcknowledgementData") - proto.RegisterType((*PacketReceiptAbsenceData)(nil), "ibc.lightclients.solomachine.v1.PacketReceiptAbsenceData") - proto.RegisterType((*NextSequenceRecvData)(nil), "ibc.lightclients.solomachine.v1.NextSequenceRecvData") -} - -func init() { - proto.RegisterFile("ibc/lightclients/solomachine/v1/solomachine.proto", fileDescriptor_6cc2ee18f7f86d4e) -} - -var fileDescriptor_6cc2ee18f7f86d4e = []byte{ - // 1359 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x57, 0x5f, 0x8f, 0xdb, 0x44, - 0x10, 0x3f, 0xa7, 0xe9, 0xf5, 0x32, 0xb9, 0xe6, 0x82, 0x9b, 0xb6, 0x39, 0xb7, 0x4a, 0x8c, 0x11, - 0xe5, 0x40, 0x34, 0xe1, 0x8a, 0xa8, 0x50, 0x85, 0x00, 0xc7, 0x31, 0x34, 0xed, 0x9d, 0x2f, 0x38, - 0x3e, 0xa0, 0x15, 0x92, 0xe5, 0x38, 0x7b, 0x89, 0x75, 0x89, 0x1d, 0xe2, 0x4d, 0xd2, 0x20, 0x21, - 0x21, 0x9e, 0x4a, 0xc4, 0x03, 0x5f, 0x20, 0x12, 0x02, 0xf1, 0x55, 0x80, 0xc7, 0xf2, 0xc6, 0x53, - 0x40, 0xed, 0x37, 0xc8, 0x27, 0x40, 0xf6, 0x6e, 0x62, 0x3b, 0xd7, 0xcb, 0x89, 0x7f, 0x4f, 0xd9, - 0x9d, 0xf9, 0xcd, 0x6f, 0x66, 0x67, 0x26, 0xb3, 0x6b, 0xd8, 0xb5, 0xea, 0x66, 0xb1, 0x6d, 0x35, - 0x5b, 0xd8, 0x6c, 0x5b, 0xc8, 0xc6, 0x6e, 0xd1, 0x75, 0xda, 0x4e, 0xc7, 0x30, 0x5b, 0x96, 0x8d, - 0x8a, 0x83, 0xdd, 0xf0, 0xb6, 0xd0, 0xed, 0x39, 0xd8, 0x61, 0xf3, 0x56, 0xdd, 0x2c, 0x84, 0x4d, - 0x0a, 0x61, 0xcc, 0x60, 0x97, 0x7b, 0xc5, 0xe3, 0x34, 0x9d, 0x1e, 0x2a, 0x9a, 0x8e, 0x6d, 0x23, - 0x13, 0x5b, 0x8e, 0xed, 0x51, 0x05, 0x3b, 0xc2, 0xc4, 0xbd, 0x18, 0x00, 0x5b, 0x86, 0x6d, 0xa3, - 0xb6, 0x8f, 0x22, 0x4b, 0x0a, 0xc9, 0x34, 0x9d, 0xa6, 0xe3, 0x2f, 0x8b, 0xde, 0x8a, 0x4a, 0xb7, - 0x9b, 0x8e, 0xd3, 0x6c, 0xa3, 0xa2, 0xbf, 0xab, 0xf7, 0x8f, 0x8a, 0x86, 0x3d, 0x22, 0x2a, 0xe1, - 0xb7, 0x18, 0x24, 0x25, 0x3f, 0xae, 0x1a, 0x36, 0x30, 0x62, 0x39, 0xd8, 0x70, 0xd1, 0xe7, 0x7d, - 0x64, 0x9b, 0x28, 0xcb, 0xf0, 0xcc, 0x4e, 0x5c, 0x5d, 0xec, 0x59, 0x09, 0xb6, 0x8e, 0x7a, 0xce, - 0x17, 0xc8, 0xd6, 0x17, 0x90, 0x98, 0x07, 0x29, 0x71, 0xb3, 0x69, 0xfe, 0xca, 0xc8, 0xe8, 0xb4, - 0xef, 0x08, 0x4b, 0x00, 0x41, 0x4d, 0x11, 0x49, 0x6d, 0x4e, 0x82, 0x61, 0xcb, 0x74, 0x6c, 0x17, - 0xd9, 0x6e, 0xdf, 0xd5, 0x5d, 0xcf, 0x67, 0xf6, 0x1c, 0xcf, 0xec, 0x24, 0x6f, 0x15, 0x0b, 0x67, - 0x24, 0xaa, 0x20, 0xcd, 0xed, 0xfc, 0x50, 0xc3, 0x5e, 0x97, 0x18, 0x05, 0x35, 0x65, 0x46, 0xb0, - 0x2c, 0x82, 0x6b, 0x46, 0xbb, 0xed, 0x0c, 0xf5, 0x7e, 0xb7, 0x61, 0x60, 0xa4, 0x1b, 0x47, 0x18, - 0xf5, 0xf4, 0x6e, 0xcf, 0xe9, 0x3a, 0xae, 0xd1, 0xce, 0xc6, 0x79, 0x66, 0x67, 0xa3, 0x74, 0x63, - 0x36, 0xcd, 0x0b, 0x84, 0x70, 0x05, 0x58, 0x50, 0xb3, 0xbe, 0xf6, 0xd0, 0x57, 0x8a, 0x9e, 0xae, - 0x4a, 0x55, 0x77, 0xe2, 0x8f, 0xbf, 0xcf, 0xaf, 0x09, 0x3f, 0x30, 0x90, 0x8a, 0xc6, 0xca, 0xde, - 0x03, 0xe8, 0xf6, 0xeb, 0x6d, 0xcb, 0xd4, 0x8f, 0xd1, 0xc8, 0x4f, 0x6c, 0xf2, 0x56, 0xa6, 0x40, - 0xca, 0x52, 0x98, 0x97, 0xa5, 0x20, 0xda, 0xa3, 0xd2, 0xe5, 0xd9, 0x34, 0xff, 0x02, 0x09, 0x22, - 0xb0, 0x10, 0xd4, 0x04, 0xd9, 0xdc, 0x47, 0x23, 0x96, 0x87, 0x64, 0xc3, 0x1a, 0xa0, 0x9e, 0x6b, - 0x1d, 0x59, 0xa8, 0xe7, 0x97, 0x20, 0xa1, 0x86, 0x45, 0xec, 0x75, 0x48, 0x60, 0xab, 0x83, 0x5c, - 0x6c, 0x74, 0xba, 0x7e, 0x76, 0xe3, 0x6a, 0x20, 0xa0, 0x41, 0x7e, 0x1d, 0x83, 0xf5, 0xbb, 0xc8, - 0x68, 0xa0, 0xde, 0xca, 0x9a, 0x47, 0xa8, 0x62, 0x4b, 0x54, 0x9e, 0xd6, 0xb5, 0x9a, 0xb6, 0x81, - 0xfb, 0x3d, 0x52, 0xc6, 0x4d, 0x35, 0x10, 0xb0, 0x87, 0x90, 0xb2, 0xd1, 0x50, 0x0f, 0x1d, 0x3c, - 0xbe, 0xe2, 0xe0, 0xdb, 0xb3, 0x69, 0xfe, 0x32, 0x39, 0x78, 0xd4, 0x4a, 0x50, 0x37, 0x6d, 0x34, - 0xac, 0x2e, 0xce, 0x2f, 0xc1, 0x96, 0x07, 0x08, 0xe7, 0xe0, 0xbc, 0x97, 0x83, 0x70, 0x43, 0x2c, - 0x01, 0x04, 0xd5, 0x8b, 0xa4, 0x1c, 0x08, 0x68, 0x12, 0x7e, 0x89, 0xc1, 0xe6, 0xbe, 0xe5, 0xd6, - 0x51, 0xcb, 0x18, 0x58, 0x4e, 0xbf, 0xc7, 0xee, 0x42, 0x82, 0x34, 0x9f, 0x6e, 0x35, 0xfc, 0x5c, - 0x24, 0x4a, 0x99, 0xd9, 0x34, 0x9f, 0xa6, 0x6d, 0x36, 0x57, 0x09, 0xea, 0x06, 0x59, 0x57, 0x1a, - 0x91, 0xec, 0xc5, 0x96, 0xb2, 0xd7, 0x85, 0x8b, 0x8b, 0x74, 0xe8, 0x8e, 0x3d, 0x6f, 0xf5, 0xdd, - 0x33, 0x5b, 0xbd, 0x36, 0xb7, 0x12, 0xed, 0x46, 0xd9, 0xc0, 0x46, 0x29, 0x3b, 0x9b, 0xe6, 0x33, - 0x24, 0x8a, 0x08, 0xa3, 0xa0, 0x6e, 0x2e, 0xf6, 0x07, 0xf6, 0x92, 0x47, 0x3c, 0x74, 0x68, 0xca, - 0xff, 0x2b, 0x8f, 0x78, 0xe8, 0x84, 0x3d, 0x6a, 0x43, 0x87, 0x66, 0xf2, 0x67, 0x06, 0xd2, 0xcb, - 0x14, 0xd1, 0xf6, 0x60, 0x96, 0xdb, 0xe3, 0x33, 0x48, 0x34, 0x0c, 0x6c, 0xe8, 0x78, 0xd4, 0x25, - 0x99, 0x4b, 0xdd, 0x7a, 0xf5, 0xcc, 0x30, 0x3d, 0x5e, 0x6d, 0xd4, 0x45, 0xe1, 0xb2, 0x2c, 0x58, - 0x04, 0x75, 0xa3, 0x41, 0xf5, 0x2c, 0x0b, 0x71, 0x6f, 0x4d, 0xbb, 0xd2, 0x5f, 0x47, 0x9b, 0x39, - 0xfe, 0xfc, 0xff, 0xc5, 0x57, 0x0c, 0x64, 0xb5, 0xb9, 0x0c, 0x35, 0x16, 0x67, 0xf2, 0x0f, 0xf4, - 0x3e, 0xa4, 0x82, 0x5c, 0xf8, 0xf4, 0xfe, 0xa9, 0xc2, 0xbd, 0x1b, 0xd5, 0x0b, 0x6a, 0x50, 0x8e, - 0xf2, 0x89, 0x10, 0x62, 0xcf, 0x0f, 0xe1, 0x0f, 0x06, 0x12, 0x9e, 0xdf, 0xd2, 0x08, 0x23, 0xf7, - 0x5f, 0xfc, 0x3b, 0x97, 0x06, 0xc5, 0xb9, 0x93, 0x83, 0x22, 0x52, 0x82, 0xf8, 0xff, 0x55, 0x82, - 0xf3, 0x41, 0x09, 0xe8, 0x09, 0x7f, 0x62, 0x00, 0xc8, 0xf0, 0xf1, 0x93, 0xb2, 0x07, 0x49, 0xfa, - 0x97, 0x3f, 0x73, 0x3c, 0x5e, 0x99, 0x4d, 0xf3, 0x6c, 0x64, 0x4a, 0xd0, 0xf9, 0x48, 0x46, 0xc4, - 0x29, 0xf3, 0x21, 0xf6, 0x0f, 0xe7, 0xc3, 0x97, 0xb0, 0x15, 0xba, 0x1c, 0xfd, 0x58, 0x59, 0x88, - 0x77, 0x0d, 0xdc, 0xa2, 0xed, 0xec, 0xaf, 0xd9, 0x2a, 0x6c, 0xd2, 0xd1, 0x40, 0x2e, 0xb4, 0xd8, - 0x8a, 0x03, 0x5c, 0x9d, 0x4d, 0xf3, 0x97, 0x22, 0xe3, 0x84, 0x5e, 0x59, 0x49, 0x33, 0xf0, 0x44, - 0xdd, 0x7f, 0xc3, 0x00, 0x1b, 0xbd, 0x48, 0x4e, 0x0d, 0xe1, 0xc1, 0xc9, 0x6b, 0x75, 0x55, 0x14, - 0x7f, 0xe3, 0xee, 0xa4, 0xb1, 0x0c, 0xe0, 0x92, 0xb4, 0x78, 0x90, 0xac, 0x8e, 0x45, 0x06, 0x08, - 0xde, 0x2e, 0x34, 0x8c, 0x97, 0xfd, 0xb6, 0xf2, 0x1e, 0x2f, 0x85, 0xd0, 0xbb, 0x86, 0x5c, 0xea, - 0x74, 0x27, 0xdb, 0x0d, 0x35, 0x64, 0x48, 0xfd, 0x36, 0x20, 0x2d, 0x91, 0x27, 0xce, 0x6a, 0xa7, - 0xb7, 0xe1, 0x02, 0x7d, 0x0a, 0x51, 0x8f, 0xd7, 0x43, 0x1e, 0xe9, 0x1b, 0xc9, 0x73, 0x47, 0x96, - 0xea, 0x1c, 0x4c, 0xbd, 0xdc, 0x83, 0x4c, 0xd5, 0x30, 0x8f, 0x11, 0x96, 0x9c, 0x4e, 0xc7, 0xc2, - 0x1d, 0x64, 0xe3, 0x53, 0x3d, 0xe5, 0xbc, 0xe3, 0xcd, 0x51, 0xbe, 0xb3, 0x4d, 0x35, 0x24, 0x11, - 0x1e, 0xc0, 0x36, 0xe1, 0x12, 0xcd, 0x63, 0xdb, 0x19, 0xb6, 0x51, 0xa3, 0x89, 0x56, 0x12, 0xee, - 0xc0, 0x96, 0x11, 0x85, 0x52, 0xd6, 0x65, 0xb1, 0x50, 0x80, 0x2c, 0xa1, 0x56, 0x91, 0x89, 0xac, - 0x2e, 0x16, 0xeb, 0xae, 0x37, 0x07, 0x4e, 0x63, 0x16, 0x5a, 0x90, 0x51, 0xd0, 0x23, 0x3c, 0x7f, - 0x7c, 0xa9, 0xc8, 0x1c, 0x9c, 0x1a, 0xc5, 0x3b, 0x70, 0xd1, 0x46, 0x8f, 0xb0, 0xf7, 0x74, 0xd3, - 0x7b, 0xc8, 0x1c, 0xd0, 0xb7, 0x5d, 0xe8, 0x1a, 0x88, 0xa8, 0x05, 0x35, 0x69, 0x13, 0x6a, 0x8f, - 0xf5, 0xb5, 0x6f, 0xe3, 0xb0, 0x31, 0x1f, 0x0c, 0xec, 0xdb, 0xf0, 0x52, 0x59, 0xd4, 0x44, 0x5d, - 0x7b, 0x50, 0x95, 0xf5, 0x43, 0xa5, 0xa2, 0x54, 0xb4, 0x8a, 0xb8, 0x57, 0x79, 0x28, 0x97, 0xf5, - 0x43, 0xa5, 0x56, 0x95, 0xa5, 0xca, 0x07, 0x15, 0xb9, 0x9c, 0x5e, 0xe3, 0xb6, 0xc6, 0x13, 0x3e, - 0x19, 0x12, 0xb1, 0x37, 0xe0, 0x4a, 0x60, 0x29, 0xed, 0x55, 0x64, 0x45, 0xd3, 0x6b, 0x9a, 0xa8, - 0xc9, 0x69, 0x86, 0x83, 0xf1, 0x84, 0x5f, 0x27, 0x32, 0xf6, 0x75, 0xd8, 0x0e, 0xe1, 0x0e, 0x94, - 0x9a, 0xac, 0xd4, 0x0e, 0x6b, 0x14, 0x1a, 0xe3, 0x2e, 0x8e, 0x27, 0x7c, 0x62, 0x21, 0x66, 0x0b, - 0xc0, 0x45, 0xd0, 0x8a, 0x2c, 0x69, 0x95, 0x03, 0x85, 0xc2, 0xcf, 0x71, 0xa9, 0xf1, 0x84, 0x87, - 0x40, 0xce, 0xee, 0xc0, 0xd5, 0x10, 0xfe, 0xae, 0xa8, 0x28, 0xf2, 0x1e, 0x05, 0xc7, 0xb9, 0xe4, - 0x78, 0xc2, 0x5f, 0xa0, 0x42, 0xf6, 0x2d, 0xb8, 0x16, 0x20, 0xab, 0xa2, 0x74, 0x5f, 0xd6, 0x74, - 0xe9, 0x60, 0x7f, 0xbf, 0xa2, 0xed, 0xcb, 0x8a, 0x96, 0x3e, 0xcf, 0x65, 0xc6, 0x13, 0x3e, 0x4d, - 0x14, 0x81, 0x9c, 0x7d, 0x0f, 0xf8, 0x13, 0x66, 0xa2, 0x74, 0x5f, 0x39, 0xf8, 0x64, 0x4f, 0x2e, - 0x7f, 0x28, 0xfb, 0xb6, 0xeb, 0xdc, 0xf6, 0x78, 0xc2, 0x5f, 0x26, 0xda, 0x25, 0x25, 0xfb, 0xee, - 0x73, 0x08, 0x54, 0x59, 0x92, 0x2b, 0x55, 0x4d, 0x17, 0x4b, 0x35, 0x59, 0x91, 0xe4, 0xf4, 0x05, - 0x2e, 0x3b, 0x9e, 0xf0, 0x19, 0xa2, 0xa5, 0x4a, 0xaa, 0x63, 0x6f, 0xc3, 0xf5, 0xc0, 0x5e, 0x91, - 0x3f, 0xd5, 0xf4, 0x9a, 0xfc, 0xd1, 0xa1, 0xa7, 0xf2, 0x68, 0x3e, 0x4e, 0x6f, 0x90, 0xc0, 0x3d, - 0xcd, 0x5c, 0xe1, 0xc9, 0x59, 0x1e, 0xd2, 0x81, 0xdd, 0x5d, 0x59, 0x2c, 0xcb, 0x6a, 0x3a, 0x41, - 0x2a, 0x43, 0x76, 0x5c, 0xfc, 0xf1, 0x8f, 0xb9, 0xb5, 0x92, 0xfe, 0xeb, 0xd3, 0x1c, 0xf3, 0xe4, - 0x69, 0x8e, 0xf9, 0xf3, 0x69, 0x8e, 0xf9, 0xee, 0x59, 0x6e, 0xed, 0xc9, 0xb3, 0xdc, 0xda, 0xef, - 0xcf, 0x72, 0x6b, 0x0f, 0xe5, 0xa6, 0x85, 0x5b, 0xfd, 0x7a, 0xc1, 0x74, 0x3a, 0x45, 0xd3, 0x71, - 0x3b, 0x8e, 0x4b, 0x7f, 0x6e, 0xba, 0x8d, 0xe3, 0xe2, 0xa3, 0xe2, 0xe2, 0x03, 0xeb, 0xe6, 0xfc, - 0x0b, 0xeb, 0x8d, 0xdb, 0x37, 0xc3, 0x1f, 0x59, 0xde, 0x2d, 0xe3, 0xd6, 0xd7, 0xfd, 0x71, 0xf6, - 0xe6, 0x5f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x80, 0xd3, 0x79, 0xb6, 0x91, 0x0d, 0x00, 0x00, -} - -func (m *ClientState) 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 *ClientState) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *ClientState) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.AllowUpdateAfterProposal { - i-- - if m.AllowUpdateAfterProposal { - dAtA[i] = 1 - } else { - dAtA[i] = 0 - } - i-- - dAtA[i] = 0x20 - } - if m.ConsensusState != nil { - { - size, err := m.ConsensusState.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintSolomachine(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - } - if m.FrozenSequence != 0 { - i = encodeVarintSolomachine(dAtA, i, uint64(m.FrozenSequence)) - i-- - dAtA[i] = 0x10 - } - if m.Sequence != 0 { - i = encodeVarintSolomachine(dAtA, i, uint64(m.Sequence)) - i-- - dAtA[i] = 0x8 - } - return len(dAtA) - i, nil -} - -func (m *ConsensusState) 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 *ConsensusState) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *ConsensusState) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.Timestamp != 0 { - i = encodeVarintSolomachine(dAtA, i, uint64(m.Timestamp)) - i-- - dAtA[i] = 0x18 - } - if len(m.Diversifier) > 0 { - i -= len(m.Diversifier) - copy(dAtA[i:], m.Diversifier) - i = encodeVarintSolomachine(dAtA, i, uint64(len(m.Diversifier))) - i-- - dAtA[i] = 0x12 - } - if m.PublicKey != nil { - { - size, err := m.PublicKey.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintSolomachine(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *Header) 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 *Header) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *Header) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.NewDiversifier) > 0 { - i -= len(m.NewDiversifier) - copy(dAtA[i:], m.NewDiversifier) - i = encodeVarintSolomachine(dAtA, i, uint64(len(m.NewDiversifier))) - i-- - dAtA[i] = 0x2a - } - if m.NewPublicKey != nil { - { - size, err := m.NewPublicKey.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintSolomachine(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x22 - } - if len(m.Signature) > 0 { - i -= len(m.Signature) - copy(dAtA[i:], m.Signature) - i = encodeVarintSolomachine(dAtA, i, uint64(len(m.Signature))) - i-- - dAtA[i] = 0x1a - } - if m.Timestamp != 0 { - i = encodeVarintSolomachine(dAtA, i, uint64(m.Timestamp)) - i-- - dAtA[i] = 0x10 - } - if m.Sequence != 0 { - i = encodeVarintSolomachine(dAtA, i, uint64(m.Sequence)) - i-- - dAtA[i] = 0x8 - } - return len(dAtA) - i, nil -} - -func (m *Misbehaviour) 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 *Misbehaviour) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *Misbehaviour) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.SignatureTwo != nil { - { - size, err := m.SignatureTwo.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintSolomachine(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x22 - } - if m.SignatureOne != nil { - { - size, err := m.SignatureOne.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintSolomachine(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - } - if m.Sequence != 0 { - i = encodeVarintSolomachine(dAtA, i, uint64(m.Sequence)) - i-- - dAtA[i] = 0x10 - } - if len(m.ClientId) > 0 { - i -= len(m.ClientId) - copy(dAtA[i:], m.ClientId) - i = encodeVarintSolomachine(dAtA, i, uint64(len(m.ClientId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *SignatureAndData) 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 *SignatureAndData) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *SignatureAndData) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.Timestamp != 0 { - i = encodeVarintSolomachine(dAtA, i, uint64(m.Timestamp)) - i-- - dAtA[i] = 0x20 - } - if len(m.Data) > 0 { - i -= len(m.Data) - copy(dAtA[i:], m.Data) - i = encodeVarintSolomachine(dAtA, i, uint64(len(m.Data))) - i-- - dAtA[i] = 0x1a - } - if m.DataType != 0 { - i = encodeVarintSolomachine(dAtA, i, uint64(m.DataType)) - i-- - dAtA[i] = 0x10 - } - if len(m.Signature) > 0 { - i -= len(m.Signature) - copy(dAtA[i:], m.Signature) - i = encodeVarintSolomachine(dAtA, i, uint64(len(m.Signature))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *TimestampedSignatureData) 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 *TimestampedSignatureData) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *TimestampedSignatureData) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.Timestamp != 0 { - i = encodeVarintSolomachine(dAtA, i, uint64(m.Timestamp)) - i-- - dAtA[i] = 0x10 - } - if len(m.SignatureData) > 0 { - i -= len(m.SignatureData) - copy(dAtA[i:], m.SignatureData) - i = encodeVarintSolomachine(dAtA, i, uint64(len(m.SignatureData))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *SignBytes) 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 *SignBytes) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *SignBytes) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Data) > 0 { - i -= len(m.Data) - copy(dAtA[i:], m.Data) - i = encodeVarintSolomachine(dAtA, i, uint64(len(m.Data))) - i-- - dAtA[i] = 0x2a - } - if m.DataType != 0 { - i = encodeVarintSolomachine(dAtA, i, uint64(m.DataType)) - i-- - dAtA[i] = 0x20 - } - if len(m.Diversifier) > 0 { - i -= len(m.Diversifier) - copy(dAtA[i:], m.Diversifier) - i = encodeVarintSolomachine(dAtA, i, uint64(len(m.Diversifier))) - i-- - dAtA[i] = 0x1a - } - if m.Timestamp != 0 { - i = encodeVarintSolomachine(dAtA, i, uint64(m.Timestamp)) - i-- - dAtA[i] = 0x10 - } - if m.Sequence != 0 { - i = encodeVarintSolomachine(dAtA, i, uint64(m.Sequence)) - i-- - dAtA[i] = 0x8 - } - return len(dAtA) - i, nil -} - -func (m *HeaderData) 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 *HeaderData) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *HeaderData) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.NewDiversifier) > 0 { - i -= len(m.NewDiversifier) - copy(dAtA[i:], m.NewDiversifier) - i = encodeVarintSolomachine(dAtA, i, uint64(len(m.NewDiversifier))) - i-- - dAtA[i] = 0x12 - } - if m.NewPubKey != nil { - { - size, err := m.NewPubKey.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintSolomachine(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *ClientStateData) 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 *ClientStateData) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *ClientStateData) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.ClientState != nil { - { - size, err := m.ClientState.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintSolomachine(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - } - if len(m.Path) > 0 { - i -= len(m.Path) - copy(dAtA[i:], m.Path) - i = encodeVarintSolomachine(dAtA, i, uint64(len(m.Path))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *ConsensusStateData) 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 *ConsensusStateData) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *ConsensusStateData) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.ConsensusState != nil { - { - size, err := m.ConsensusState.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintSolomachine(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - } - if len(m.Path) > 0 { - i -= len(m.Path) - copy(dAtA[i:], m.Path) - i = encodeVarintSolomachine(dAtA, i, uint64(len(m.Path))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *ConnectionStateData) 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 *ConnectionStateData) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *ConnectionStateData) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.Connection != nil { - { - size, err := m.Connection.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintSolomachine(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - } - if len(m.Path) > 0 { - i -= len(m.Path) - copy(dAtA[i:], m.Path) - i = encodeVarintSolomachine(dAtA, i, uint64(len(m.Path))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *ChannelStateData) 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 *ChannelStateData) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *ChannelStateData) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.Channel != nil { - { - size, err := m.Channel.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintSolomachine(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - } - if len(m.Path) > 0 { - i -= len(m.Path) - copy(dAtA[i:], m.Path) - i = encodeVarintSolomachine(dAtA, i, uint64(len(m.Path))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *PacketCommitmentData) 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 *PacketCommitmentData) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *PacketCommitmentData) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Commitment) > 0 { - i -= len(m.Commitment) - copy(dAtA[i:], m.Commitment) - i = encodeVarintSolomachine(dAtA, i, uint64(len(m.Commitment))) - i-- - dAtA[i] = 0x12 - } - if len(m.Path) > 0 { - i -= len(m.Path) - copy(dAtA[i:], m.Path) - i = encodeVarintSolomachine(dAtA, i, uint64(len(m.Path))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *PacketAcknowledgementData) 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 *PacketAcknowledgementData) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *PacketAcknowledgementData) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Acknowledgement) > 0 { - i -= len(m.Acknowledgement) - copy(dAtA[i:], m.Acknowledgement) - i = encodeVarintSolomachine(dAtA, i, uint64(len(m.Acknowledgement))) - i-- - dAtA[i] = 0x12 - } - if len(m.Path) > 0 { - i -= len(m.Path) - copy(dAtA[i:], m.Path) - i = encodeVarintSolomachine(dAtA, i, uint64(len(m.Path))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *PacketReceiptAbsenceData) 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 *PacketReceiptAbsenceData) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *PacketReceiptAbsenceData) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Path) > 0 { - i -= len(m.Path) - copy(dAtA[i:], m.Path) - i = encodeVarintSolomachine(dAtA, i, uint64(len(m.Path))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *NextSequenceRecvData) 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 *NextSequenceRecvData) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *NextSequenceRecvData) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.NextSeqRecv != 0 { - i = encodeVarintSolomachine(dAtA, i, uint64(m.NextSeqRecv)) - i-- - dAtA[i] = 0x10 - } - if len(m.Path) > 0 { - i -= len(m.Path) - copy(dAtA[i:], m.Path) - i = encodeVarintSolomachine(dAtA, i, uint64(len(m.Path))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func encodeVarintSolomachine(dAtA []byte, offset int, v uint64) int { - offset -= sovSolomachine(v) - base := offset - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ - } - dAtA[offset] = uint8(v) - return base -} -func (m *ClientState) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.Sequence != 0 { - n += 1 + sovSolomachine(uint64(m.Sequence)) - } - if m.FrozenSequence != 0 { - n += 1 + sovSolomachine(uint64(m.FrozenSequence)) - } - if m.ConsensusState != nil { - l = m.ConsensusState.Size() - n += 1 + l + sovSolomachine(uint64(l)) - } - if m.AllowUpdateAfterProposal { - n += 2 - } - return n -} - -func (m *ConsensusState) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.PublicKey != nil { - l = m.PublicKey.Size() - n += 1 + l + sovSolomachine(uint64(l)) - } - l = len(m.Diversifier) - if l > 0 { - n += 1 + l + sovSolomachine(uint64(l)) - } - if m.Timestamp != 0 { - n += 1 + sovSolomachine(uint64(m.Timestamp)) - } - return n -} - -func (m *Header) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.Sequence != 0 { - n += 1 + sovSolomachine(uint64(m.Sequence)) - } - if m.Timestamp != 0 { - n += 1 + sovSolomachine(uint64(m.Timestamp)) - } - l = len(m.Signature) - if l > 0 { - n += 1 + l + sovSolomachine(uint64(l)) - } - if m.NewPublicKey != nil { - l = m.NewPublicKey.Size() - n += 1 + l + sovSolomachine(uint64(l)) - } - l = len(m.NewDiversifier) - if l > 0 { - n += 1 + l + sovSolomachine(uint64(l)) - } - return n -} - -func (m *Misbehaviour) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.ClientId) - if l > 0 { - n += 1 + l + sovSolomachine(uint64(l)) - } - if m.Sequence != 0 { - n += 1 + sovSolomachine(uint64(m.Sequence)) - } - if m.SignatureOne != nil { - l = m.SignatureOne.Size() - n += 1 + l + sovSolomachine(uint64(l)) - } - if m.SignatureTwo != nil { - l = m.SignatureTwo.Size() - n += 1 + l + sovSolomachine(uint64(l)) - } - return n -} - -func (m *SignatureAndData) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Signature) - if l > 0 { - n += 1 + l + sovSolomachine(uint64(l)) - } - if m.DataType != 0 { - n += 1 + sovSolomachine(uint64(m.DataType)) - } - l = len(m.Data) - if l > 0 { - n += 1 + l + sovSolomachine(uint64(l)) - } - if m.Timestamp != 0 { - n += 1 + sovSolomachine(uint64(m.Timestamp)) - } - return n -} - -func (m *TimestampedSignatureData) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.SignatureData) - if l > 0 { - n += 1 + l + sovSolomachine(uint64(l)) - } - if m.Timestamp != 0 { - n += 1 + sovSolomachine(uint64(m.Timestamp)) - } - return n -} - -func (m *SignBytes) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.Sequence != 0 { - n += 1 + sovSolomachine(uint64(m.Sequence)) - } - if m.Timestamp != 0 { - n += 1 + sovSolomachine(uint64(m.Timestamp)) - } - l = len(m.Diversifier) - if l > 0 { - n += 1 + l + sovSolomachine(uint64(l)) - } - if m.DataType != 0 { - n += 1 + sovSolomachine(uint64(m.DataType)) - } - l = len(m.Data) - if l > 0 { - n += 1 + l + sovSolomachine(uint64(l)) - } - return n -} - -func (m *HeaderData) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.NewPubKey != nil { - l = m.NewPubKey.Size() - n += 1 + l + sovSolomachine(uint64(l)) - } - l = len(m.NewDiversifier) - if l > 0 { - n += 1 + l + sovSolomachine(uint64(l)) - } - return n -} - -func (m *ClientStateData) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Path) - if l > 0 { - n += 1 + l + sovSolomachine(uint64(l)) - } - if m.ClientState != nil { - l = m.ClientState.Size() - n += 1 + l + sovSolomachine(uint64(l)) - } - return n -} - -func (m *ConsensusStateData) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Path) - if l > 0 { - n += 1 + l + sovSolomachine(uint64(l)) - } - if m.ConsensusState != nil { - l = m.ConsensusState.Size() - n += 1 + l + sovSolomachine(uint64(l)) - } - return n -} - -func (m *ConnectionStateData) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Path) - if l > 0 { - n += 1 + l + sovSolomachine(uint64(l)) - } - if m.Connection != nil { - l = m.Connection.Size() - n += 1 + l + sovSolomachine(uint64(l)) - } - return n -} - -func (m *ChannelStateData) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Path) - if l > 0 { - n += 1 + l + sovSolomachine(uint64(l)) - } - if m.Channel != nil { - l = m.Channel.Size() - n += 1 + l + sovSolomachine(uint64(l)) - } - return n -} - -func (m *PacketCommitmentData) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Path) - if l > 0 { - n += 1 + l + sovSolomachine(uint64(l)) - } - l = len(m.Commitment) - if l > 0 { - n += 1 + l + sovSolomachine(uint64(l)) - } - return n -} - -func (m *PacketAcknowledgementData) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Path) - if l > 0 { - n += 1 + l + sovSolomachine(uint64(l)) - } - l = len(m.Acknowledgement) - if l > 0 { - n += 1 + l + sovSolomachine(uint64(l)) - } - return n -} - -func (m *PacketReceiptAbsenceData) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Path) - if l > 0 { - n += 1 + l + sovSolomachine(uint64(l)) - } - return n -} - -func (m *NextSequenceRecvData) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Path) - if l > 0 { - n += 1 + l + sovSolomachine(uint64(l)) - } - if m.NextSeqRecv != 0 { - n += 1 + sovSolomachine(uint64(m.NextSeqRecv)) - } - return n -} - -func sovSolomachine(x uint64) (n int) { - return (math_bits.Len64(x|1) + 6) / 7 -} -func sozSolomachine(x uint64) (n int) { - return sovSolomachine(uint64((x << 1) ^ uint64((int64(x) >> 63)))) -} -func (m *ClientState) 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 ErrIntOverflowSolomachine - } - 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: ClientState: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: ClientState: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Sequence", wireType) - } - m.Sequence = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Sequence |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field FrozenSequence", wireType) - } - m.FrozenSequence = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.FrozenSequence |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ConsensusState", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthSolomachine - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthSolomachine - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.ConsensusState == nil { - m.ConsensusState = &ConsensusState{} - } - if err := m.ConsensusState.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 4: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field AllowUpdateAfterProposal", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.AllowUpdateAfterProposal = bool(v != 0) - default: - iNdEx = preIndex - skippy, err := skipSolomachine(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthSolomachine - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *ConsensusState) 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 ErrIntOverflowSolomachine - } - 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: ConsensusState: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: ConsensusState: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field PublicKey", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthSolomachine - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthSolomachine - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.PublicKey == nil { - m.PublicKey = &types.Any{} - } - if err := m.PublicKey.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Diversifier", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - 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 ErrInvalidLengthSolomachine - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthSolomachine - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Diversifier = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType) - } - m.Timestamp = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Timestamp |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - default: - iNdEx = preIndex - skippy, err := skipSolomachine(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthSolomachine - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *Header) 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 ErrIntOverflowSolomachine - } - 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: Header: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: Header: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Sequence", wireType) - } - m.Sequence = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Sequence |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType) - } - m.Timestamp = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Timestamp |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Signature", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthSolomachine - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthSolomachine - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Signature = append(m.Signature[:0], dAtA[iNdEx:postIndex]...) - if m.Signature == nil { - m.Signature = []byte{} - } - iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field NewPublicKey", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthSolomachine - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthSolomachine - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.NewPublicKey == nil { - m.NewPublicKey = &types.Any{} - } - if err := m.NewPublicKey.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field NewDiversifier", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - 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 ErrInvalidLengthSolomachine - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthSolomachine - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.NewDiversifier = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipSolomachine(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthSolomachine - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *Misbehaviour) 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 ErrIntOverflowSolomachine - } - 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: Misbehaviour: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: Misbehaviour: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ClientId", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - 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 ErrInvalidLengthSolomachine - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthSolomachine - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ClientId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Sequence", wireType) - } - m.Sequence = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Sequence |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field SignatureOne", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthSolomachine - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthSolomachine - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.SignatureOne == nil { - m.SignatureOne = &SignatureAndData{} - } - if err := m.SignatureOne.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field SignatureTwo", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthSolomachine - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthSolomachine - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.SignatureTwo == nil { - m.SignatureTwo = &SignatureAndData{} - } - if err := m.SignatureTwo.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipSolomachine(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthSolomachine - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *SignatureAndData) 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 ErrIntOverflowSolomachine - } - 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: SignatureAndData: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: SignatureAndData: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Signature", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthSolomachine - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthSolomachine - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Signature = append(m.Signature[:0], dAtA[iNdEx:postIndex]...) - if m.Signature == nil { - m.Signature = []byte{} - } - iNdEx = postIndex - case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field DataType", wireType) - } - m.DataType = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.DataType |= DataType(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthSolomachine - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthSolomachine - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...) - if m.Data == nil { - m.Data = []byte{} - } - iNdEx = postIndex - case 4: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType) - } - m.Timestamp = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Timestamp |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - default: - iNdEx = preIndex - skippy, err := skipSolomachine(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthSolomachine - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *TimestampedSignatureData) 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 ErrIntOverflowSolomachine - } - 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: TimestampedSignatureData: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: TimestampedSignatureData: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field SignatureData", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthSolomachine - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthSolomachine - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.SignatureData = append(m.SignatureData[:0], dAtA[iNdEx:postIndex]...) - if m.SignatureData == nil { - m.SignatureData = []byte{} - } - iNdEx = postIndex - case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType) - } - m.Timestamp = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Timestamp |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - default: - iNdEx = preIndex - skippy, err := skipSolomachine(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthSolomachine - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *SignBytes) 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 ErrIntOverflowSolomachine - } - 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: SignBytes: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: SignBytes: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Sequence", wireType) - } - m.Sequence = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Sequence |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType) - } - m.Timestamp = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Timestamp |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Diversifier", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - 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 ErrInvalidLengthSolomachine - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthSolomachine - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Diversifier = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 4: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field DataType", wireType) - } - m.DataType = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.DataType |= DataType(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthSolomachine - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthSolomachine - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...) - if m.Data == nil { - m.Data = []byte{} - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipSolomachine(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthSolomachine - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *HeaderData) 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 ErrIntOverflowSolomachine - } - 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: HeaderData: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: HeaderData: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field NewPubKey", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthSolomachine - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthSolomachine - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.NewPubKey == nil { - m.NewPubKey = &types.Any{} - } - if err := m.NewPubKey.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field NewDiversifier", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - 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 ErrInvalidLengthSolomachine - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthSolomachine - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.NewDiversifier = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipSolomachine(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthSolomachine - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *ClientStateData) 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 ErrIntOverflowSolomachine - } - 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: ClientStateData: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: ClientStateData: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Path", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthSolomachine - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthSolomachine - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Path = append(m.Path[:0], dAtA[iNdEx:postIndex]...) - if m.Path == nil { - m.Path = []byte{} - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ClientState", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthSolomachine - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthSolomachine - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.ClientState == nil { - m.ClientState = &types.Any{} - } - if err := m.ClientState.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipSolomachine(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthSolomachine - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *ConsensusStateData) 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 ErrIntOverflowSolomachine - } - 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: ConsensusStateData: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: ConsensusStateData: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Path", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthSolomachine - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthSolomachine - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Path = append(m.Path[:0], dAtA[iNdEx:postIndex]...) - if m.Path == nil { - m.Path = []byte{} - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ConsensusState", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthSolomachine - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthSolomachine - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.ConsensusState == nil { - m.ConsensusState = &types.Any{} - } - if err := m.ConsensusState.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipSolomachine(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthSolomachine - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *ConnectionStateData) 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 ErrIntOverflowSolomachine - } - 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: ConnectionStateData: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: ConnectionStateData: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Path", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthSolomachine - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthSolomachine - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Path = append(m.Path[:0], dAtA[iNdEx:postIndex]...) - if m.Path == nil { - m.Path = []byte{} - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Connection", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthSolomachine - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthSolomachine - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.Connection == nil { - m.Connection = &types1.ConnectionEnd{} - } - if err := m.Connection.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipSolomachine(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthSolomachine - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *ChannelStateData) 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 ErrIntOverflowSolomachine - } - 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: ChannelStateData: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: ChannelStateData: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Path", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthSolomachine - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthSolomachine - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Path = append(m.Path[:0], dAtA[iNdEx:postIndex]...) - if m.Path == nil { - m.Path = []byte{} - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Channel", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthSolomachine - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthSolomachine - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.Channel == nil { - m.Channel = &types2.Channel{} - } - if err := m.Channel.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipSolomachine(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthSolomachine - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *PacketCommitmentData) 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 ErrIntOverflowSolomachine - } - 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: PacketCommitmentData: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: PacketCommitmentData: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Path", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthSolomachine - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthSolomachine - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Path = append(m.Path[:0], dAtA[iNdEx:postIndex]...) - if m.Path == nil { - m.Path = []byte{} - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Commitment", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthSolomachine - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthSolomachine - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Commitment = append(m.Commitment[:0], dAtA[iNdEx:postIndex]...) - if m.Commitment == nil { - m.Commitment = []byte{} - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipSolomachine(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthSolomachine - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *PacketAcknowledgementData) 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 ErrIntOverflowSolomachine - } - 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: PacketAcknowledgementData: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: PacketAcknowledgementData: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Path", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthSolomachine - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthSolomachine - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Path = append(m.Path[:0], dAtA[iNdEx:postIndex]...) - if m.Path == nil { - m.Path = []byte{} - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Acknowledgement", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthSolomachine - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthSolomachine - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Acknowledgement = append(m.Acknowledgement[:0], dAtA[iNdEx:postIndex]...) - if m.Acknowledgement == nil { - m.Acknowledgement = []byte{} - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipSolomachine(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthSolomachine - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *PacketReceiptAbsenceData) 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 ErrIntOverflowSolomachine - } - 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: PacketReceiptAbsenceData: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: PacketReceiptAbsenceData: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Path", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthSolomachine - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthSolomachine - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Path = append(m.Path[:0], dAtA[iNdEx:postIndex]...) - if m.Path == nil { - m.Path = []byte{} - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipSolomachine(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthSolomachine - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *NextSequenceRecvData) 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 ErrIntOverflowSolomachine - } - 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: NextSequenceRecvData: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: NextSequenceRecvData: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Path", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthSolomachine - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthSolomachine - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Path = append(m.Path[:0], dAtA[iNdEx:postIndex]...) - if m.Path == nil { - m.Path = []byte{} - } - iNdEx = postIndex - case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field NextSeqRecv", wireType) - } - m.NextSeqRecv = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowSolomachine - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.NextSeqRecv |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - default: - iNdEx = preIndex - skippy, err := skipSolomachine(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthSolomachine - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func skipSolomachine(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, ErrIntOverflowSolomachine - } - 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, ErrIntOverflowSolomachine - } - 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, ErrIntOverflowSolomachine - } - 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, ErrInvalidLengthSolomachine - } - iNdEx += length - case 3: - depth++ - case 4: - if depth == 0 { - return 0, ErrUnexpectedEndOfGroupSolomachine - } - depth-- - case 5: - iNdEx += 4 - default: - return 0, fmt.Errorf("proto: illegal wireType %d", wireType) - } - if iNdEx < 0 { - return 0, ErrInvalidLengthSolomachine - } - if depth == 0 { - return iNdEx, nil - } - } - return 0, io.ErrUnexpectedEOF -} - -var ( - ErrInvalidLengthSolomachine = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowSolomachine = fmt.Errorf("proto: integer overflow") - ErrUnexpectedEndOfGroupSolomachine = fmt.Errorf("proto: unexpected end of group") -) diff --git a/x/ibc/light-clients/06-solomachine/types/solomachine_test.go b/x/ibc/light-clients/06-solomachine/types/solomachine_test.go deleted file mode 100644 index 50555e45145a..000000000000 --- a/x/ibc/light-clients/06-solomachine/types/solomachine_test.go +++ /dev/null @@ -1,113 +0,0 @@ -package types_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - "github.com/stretchr/testify/suite" - - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" - "github.com/cosmos/cosmos-sdk/testutil/testdata" - sdk "github.com/cosmos/cosmos-sdk/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/06-solomachine/types" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" -) - -type SoloMachineTestSuite struct { - suite.Suite - - solomachine *ibctesting.Solomachine // singlesig public key - solomachineMulti *ibctesting.Solomachine // multisig public key - coordinator *ibctesting.Coordinator - - // testing chain used for convenience and readability - chainA *ibctesting.TestChain - chainB *ibctesting.TestChain - - store sdk.KVStore -} - -func (suite *SoloMachineTestSuite) SetupTest() { - suite.coordinator = ibctesting.NewCoordinator(suite.T(), 2) - suite.chainA = suite.coordinator.GetChain(ibctesting.GetChainID(0)) - suite.chainB = suite.coordinator.GetChain(ibctesting.GetChainID(1)) - - suite.solomachine = ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "solomachinesingle", "testing", 1) - suite.solomachineMulti = ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "solomachinemulti", "testing", 4) - - suite.store = suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), exported.Solomachine) -} - -func TestSoloMachineTestSuite(t *testing.T) { - suite.Run(t, new(SoloMachineTestSuite)) -} - -func (suite *SoloMachineTestSuite) GetSequenceFromStore() uint64 { - bz := suite.store.Get(host.ClientStateKey()) - suite.Require().NotNil(bz) - - var clientState exported.ClientState - err := suite.chainA.Codec.UnmarshalInterface(bz, &clientState) - suite.Require().NoError(err) - return clientState.GetLatestHeight().GetRevisionHeight() -} - -func (suite *SoloMachineTestSuite) GetInvalidProof() []byte { - invalidProof, err := suite.chainA.Codec.MarshalBinaryBare(&types.TimestampedSignatureData{Timestamp: suite.solomachine.Time}) - suite.Require().NoError(err) - - return invalidProof -} - -func TestUnpackInterfaces_Header(t *testing.T) { - registry := testdata.NewTestInterfaceRegistry() - cryptocodec.RegisterInterfaces(registry) - - pk := secp256k1.GenPrivKey().PubKey().(cryptotypes.PubKey) - any, err := codectypes.NewAnyWithValue(pk) - require.NoError(t, err) - - header := types.Header{ - NewPublicKey: any, - } - bz, err := header.Marshal() - require.NoError(t, err) - - var header2 types.Header - err = header2.Unmarshal(bz) - require.NoError(t, err) - - err = codectypes.UnpackInterfaces(header2, registry) - require.NoError(t, err) - - require.Equal(t, pk, header2.NewPublicKey.GetCachedValue()) -} - -func TestUnpackInterfaces_HeaderData(t *testing.T) { - registry := testdata.NewTestInterfaceRegistry() - cryptocodec.RegisterInterfaces(registry) - - pk := secp256k1.GenPrivKey().PubKey().(cryptotypes.PubKey) - any, err := codectypes.NewAnyWithValue(pk) - require.NoError(t, err) - - hd := types.HeaderData{ - NewPubKey: any, - } - bz, err := hd.Marshal() - require.NoError(t, err) - - var hd2 types.HeaderData - err = hd2.Unmarshal(bz) - require.NoError(t, err) - - err = codectypes.UnpackInterfaces(hd2, registry) - require.NoError(t, err) - - require.Equal(t, pk, hd2.NewPubKey.GetCachedValue()) -} diff --git a/x/ibc/light-clients/06-solomachine/types/update.go b/x/ibc/light-clients/06-solomachine/types/update.go deleted file mode 100644 index 4cf31fd98857..000000000000 --- a/x/ibc/light-clients/06-solomachine/types/update.go +++ /dev/null @@ -1,89 +0,0 @@ -package types - -import ( - "github.com/cosmos/cosmos-sdk/codec" - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -// CheckHeaderAndUpdateState checks if the provided header is valid and updates -// the consensus state if appropriate. It returns an error if: -// - the header provided is not parseable to a solo machine header -// - the header sequence does not match the current sequence -// - the header timestamp is less than the consensus state timestamp -// - the currently registered public key did not provide the update signature -func (cs ClientState) CheckHeaderAndUpdateState( - ctx sdk.Context, cdc codec.BinaryMarshaler, clientStore sdk.KVStore, - header exported.Header, -) (exported.ClientState, exported.ConsensusState, error) { - smHeader, ok := header.(*Header) - if !ok { - return nil, nil, sdkerrors.Wrapf( - clienttypes.ErrInvalidHeader, "header type %T, expected %T", header, &Header{}, - ) - } - - if err := checkHeader(cdc, &cs, smHeader); err != nil { - return nil, nil, err - } - - clientState, consensusState := update(&cs, smHeader) - return clientState, consensusState, nil -} - -// checkHeader checks if the Solo Machine update signature is valid. -func checkHeader(cdc codec.BinaryMarshaler, clientState *ClientState, header *Header) error { - // assert update sequence is current sequence - if header.Sequence != clientState.Sequence { - return sdkerrors.Wrapf( - clienttypes.ErrInvalidHeader, - "header sequence does not match the client state sequence (%d != %d)", header.Sequence, clientState.Sequence, - ) - } - - // assert update timestamp is not less than current consensus state timestamp - if header.Timestamp < clientState.ConsensusState.Timestamp { - return sdkerrors.Wrapf( - clienttypes.ErrInvalidHeader, - "header timestamp is less than to the consensus state timestamp (%d < %d)", header.Timestamp, clientState.ConsensusState.Timestamp, - ) - } - - // assert currently registered public key signed over the new public key with correct sequence - data, err := HeaderSignBytes(cdc, header) - if err != nil { - return err - } - - sigData, err := UnmarshalSignatureData(cdc, header.Signature) - if err != nil { - return err - } - - publicKey, err := clientState.ConsensusState.GetPubKey() - if err != nil { - return err - } - - if err := VerifySignature(publicKey, data, sigData); err != nil { - return sdkerrors.Wrap(ErrInvalidHeader, err.Error()) - } - - return nil -} - -// update the consensus state to the new public key and an incremented sequence -func update(clientState *ClientState, header *Header) (*ClientState, *ConsensusState) { - consensusState := &ConsensusState{ - PublicKey: header.NewPublicKey, - Diversifier: header.NewDiversifier, - Timestamp: header.Timestamp, - } - - // increment sequence number - clientState.Sequence++ - clientState.ConsensusState = consensusState - return clientState, consensusState -} diff --git a/x/ibc/light-clients/06-solomachine/types/update_test.go b/x/ibc/light-clients/06-solomachine/types/update_test.go deleted file mode 100644 index e49992cbb551..000000000000 --- a/x/ibc/light-clients/06-solomachine/types/update_test.go +++ /dev/null @@ -1,181 +0,0 @@ -package types_test - -import ( - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/06-solomachine/types" - ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" -) - -func (suite *SoloMachineTestSuite) TestCheckHeaderAndUpdateState() { - var ( - clientState exported.ClientState - header exported.Header - ) - - // test singlesig and multisig public keys - for _, solomachine := range []*ibctesting.Solomachine{suite.solomachine, suite.solomachineMulti} { - - testCases := []struct { - name string - setup func() - expPass bool - }{ - { - "successful update", - func() { - clientState = solomachine.ClientState() - header = solomachine.CreateHeader() - }, - true, - }, - { - "wrong client state type", - func() { - clientState = &ibctmtypes.ClientState{} - header = solomachine.CreateHeader() - }, - false, - }, - { - "invalid header type", - func() { - clientState = solomachine.ClientState() - header = &ibctmtypes.Header{} - }, - false, - }, - { - "wrong sequence in header", - func() { - clientState = solomachine.ClientState() - // store in temp before assigning to interface type - h := solomachine.CreateHeader() - h.Sequence++ - header = h - }, - false, - }, - { - "invalid header Signature", - func() { - clientState = solomachine.ClientState() - h := solomachine.CreateHeader() - h.Signature = suite.GetInvalidProof() - header = h - }, false, - }, - { - "invalid timestamp in header", - func() { - clientState = solomachine.ClientState() - h := solomachine.CreateHeader() - h.Timestamp-- - header = h - }, false, - }, - { - "signature uses wrong sequence", - func() { - clientState = solomachine.ClientState() - solomachine.Sequence++ - header = solomachine.CreateHeader() - }, - false, - }, - { - "signature uses new pubkey to sign", - func() { - // store in temp before assinging to interface type - cs := solomachine.ClientState() - h := solomachine.CreateHeader() - - publicKey, err := codectypes.NewAnyWithValue(solomachine.PublicKey) - suite.NoError(err) - - data := &types.HeaderData{ - NewPubKey: publicKey, - NewDiversifier: h.NewDiversifier, - } - - dataBz, err := suite.chainA.Codec.MarshalBinaryBare(data) - suite.Require().NoError(err) - - // generate invalid signature - signBytes := &types.SignBytes{ - Sequence: cs.Sequence, - Timestamp: solomachine.Time, - Diversifier: solomachine.Diversifier, - DataType: types.CLIENT, - Data: dataBz, - } - - signBz, err := suite.chainA.Codec.MarshalBinaryBare(signBytes) - suite.Require().NoError(err) - - sig := solomachine.GenerateSignature(signBz) - suite.Require().NoError(err) - h.Signature = sig - - clientState = cs - header = h - - }, - false, - }, - { - "signature signs over old pubkey", - func() { - // store in temp before assinging to interface type - cs := solomachine.ClientState() - oldPubKey := solomachine.PublicKey - h := solomachine.CreateHeader() - - // generate invalid signature - data := append(sdk.Uint64ToBigEndian(cs.Sequence), oldPubKey.Bytes()...) - sig := solomachine.GenerateSignature(data) - h.Signature = sig - - clientState = cs - header = h - }, - false, - }, - { - "consensus state public key is nil", - func() { - cs := solomachine.ClientState() - cs.ConsensusState.PublicKey = nil - clientState = cs - header = solomachine.CreateHeader() - }, - false, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - // setup test - tc.setup() - - clientState, consensusState, err := clientState.CheckHeaderAndUpdateState(suite.chainA.GetContext(), suite.chainA.Codec, suite.store, header) - - if tc.expPass { - suite.Require().NoError(err) - suite.Require().Equal(header.(*types.Header).NewPublicKey, clientState.(*types.ClientState).ConsensusState.PublicKey) - suite.Require().Equal(uint64(0), clientState.(*types.ClientState).FrozenSequence) - suite.Require().Equal(header.(*types.Header).Sequence+1, clientState.(*types.ClientState).Sequence) - suite.Require().Equal(consensusState, clientState.(*types.ClientState).ConsensusState) - } else { - suite.Require().Error(err) - suite.Require().Nil(clientState) - suite.Require().Nil(consensusState) - } - }) - } - } -} diff --git a/x/ibc/light-clients/07-tendermint/doc.go b/x/ibc/light-clients/07-tendermint/doc.go deleted file mode 100644 index 26aa430a82da..000000000000 --- a/x/ibc/light-clients/07-tendermint/doc.go +++ /dev/null @@ -1,5 +0,0 @@ -/* -Package tendermint implements a concrete `ConsensusState`, `Header`, -`Misbehaviour` and `Equivocation` types for the Tendermint consensus light client. -*/ -package tendermint diff --git a/x/ibc/light-clients/07-tendermint/module.go b/x/ibc/light-clients/07-tendermint/module.go deleted file mode 100644 index 4c5cc2f947f4..000000000000 --- a/x/ibc/light-clients/07-tendermint/module.go +++ /dev/null @@ -1,10 +0,0 @@ -package tendermint - -import ( - "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" -) - -// Name returns the IBC client name -func Name() string { - return types.SubModuleName -} diff --git a/x/ibc/light-clients/07-tendermint/types/client_state.go b/x/ibc/light-clients/07-tendermint/types/client_state.go deleted file mode 100644 index c2bb5239f5f5..000000000000 --- a/x/ibc/light-clients/07-tendermint/types/client_state.go +++ /dev/null @@ -1,532 +0,0 @@ -package types - -import ( - "strings" - "time" - - ics23 "github.com/confio/ics23/go" - "github.com/tendermint/tendermint/light" - - "github.com/cosmos/cosmos-sdk/codec" - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -var _ exported.ClientState = (*ClientState)(nil) - -// NewClientState creates a new ClientState instance -func NewClientState( - chainID string, trustLevel Fraction, - trustingPeriod, ubdPeriod, maxClockDrift time.Duration, - latestHeight clienttypes.Height, specs []*ics23.ProofSpec, - upgradePath []string, allowUpdateAfterExpiry, allowUpdateAfterMisbehaviour bool, -) *ClientState { - return &ClientState{ - ChainId: chainID, - TrustLevel: trustLevel, - TrustingPeriod: trustingPeriod, - UnbondingPeriod: ubdPeriod, - MaxClockDrift: maxClockDrift, - LatestHeight: latestHeight, - FrozenHeight: clienttypes.ZeroHeight(), - ProofSpecs: specs, - UpgradePath: upgradePath, - AllowUpdateAfterExpiry: allowUpdateAfterExpiry, - AllowUpdateAfterMisbehaviour: allowUpdateAfterMisbehaviour, - } -} - -// GetChainID returns the chain-id -func (cs ClientState) GetChainID() string { - return cs.ChainId -} - -// ClientType is tendermint. -func (cs ClientState) ClientType() string { - return exported.Tendermint -} - -// GetLatestHeight returns latest block height. -func (cs ClientState) GetLatestHeight() exported.Height { - return cs.LatestHeight -} - -// IsFrozen returns true if the frozen height has been set. -func (cs ClientState) IsFrozen() bool { - return !cs.FrozenHeight.IsZero() -} - -// GetFrozenHeight returns the height at which client is frozen -// NOTE: FrozenHeight is zero if client is unfrozen -func (cs ClientState) GetFrozenHeight() exported.Height { - return cs.FrozenHeight -} - -// IsExpired returns whether or not the client has passed the trusting period since the last -// update (in which case no headers are considered valid). -func (cs ClientState) IsExpired(latestTimestamp, now time.Time) bool { - expirationTime := latestTimestamp.Add(cs.TrustingPeriod) - return !expirationTime.After(now) -} - -// Validate performs a basic validation of the client state fields. -func (cs ClientState) Validate() error { - if strings.TrimSpace(cs.ChainId) == "" { - return sdkerrors.Wrap(ErrInvalidChainID, "chain id cannot be empty string") - } - if err := light.ValidateTrustLevel(cs.TrustLevel.ToTendermint()); err != nil { - return err - } - if cs.TrustingPeriod == 0 { - return sdkerrors.Wrap(ErrInvalidTrustingPeriod, "trusting period cannot be zero") - } - if cs.UnbondingPeriod == 0 { - return sdkerrors.Wrap(ErrInvalidUnbondingPeriod, "unbonding period cannot be zero") - } - if cs.MaxClockDrift == 0 { - return sdkerrors.Wrap(ErrInvalidMaxClockDrift, "max clock drift cannot be zero") - } - if cs.LatestHeight.RevisionHeight == 0 { - return sdkerrors.Wrapf(ErrInvalidHeaderHeight, "tendermint revision height cannot be zero") - } - if cs.TrustingPeriod >= cs.UnbondingPeriod { - return sdkerrors.Wrapf( - ErrInvalidTrustingPeriod, - "trusting period (%s) should be < unbonding period (%s)", cs.TrustingPeriod, cs.UnbondingPeriod, - ) - } - - if cs.ProofSpecs == nil { - return sdkerrors.Wrap(ErrInvalidProofSpecs, "proof specs cannot be nil for tm client") - } - for i, spec := range cs.ProofSpecs { - if spec == nil { - return sdkerrors.Wrapf(ErrInvalidProofSpecs, "proof spec cannot be nil at index: %d", i) - } - } - // UpgradePath may be empty, but if it isn't, each key must be non-empty - for i, k := range cs.UpgradePath { - if strings.TrimSpace(k) == "" { - return sdkerrors.Wrapf(clienttypes.ErrInvalidClient, "key in upgrade path at index %d cannot be empty", i) - } - } - - return nil -} - -// GetProofSpecs returns the format the client expects for proof verification -// as a string array specifying the proof type for each position in chained proof -func (cs ClientState) GetProofSpecs() []*ics23.ProofSpec { - return cs.ProofSpecs -} - -// ZeroCustomFields returns a ClientState that is a copy of the current ClientState -// with all client customizable fields zeroed out -func (cs ClientState) ZeroCustomFields() exported.ClientState { - // copy over all chain-specified fields - // and leave custom fields empty - return &ClientState{ - ChainId: cs.ChainId, - UnbondingPeriod: cs.UnbondingPeriod, - LatestHeight: cs.LatestHeight, - ProofSpecs: cs.ProofSpecs, - UpgradePath: cs.UpgradePath, - } -} - -// Initialize will check that initial consensus state is a Tendermint consensus state -// and will store ProcessedTime for initial consensus state as ctx.BlockTime() -func (cs ClientState) Initialize(ctx sdk.Context, _ codec.BinaryMarshaler, clientStore sdk.KVStore, consState exported.ConsensusState) error { - if _, ok := consState.(*ConsensusState); !ok { - return sdkerrors.Wrapf(clienttypes.ErrInvalidConsensus, "invalid initial consensus state. expected type: %T, got: %T", - &ConsensusState{}, consState) - } - // set processed time with initial consensus state height equal to initial client state's latest height - SetProcessedTime(clientStore, cs.GetLatestHeight(), uint64(ctx.BlockTime().UnixNano())) - return nil -} - -// VerifyClientState verifies a proof of the client state of the running chain -// stored on the target machine -func (cs ClientState) VerifyClientState( - store sdk.KVStore, - cdc codec.BinaryMarshaler, - height exported.Height, - prefix exported.Prefix, - counterpartyClientIdentifier string, - proof []byte, - clientState exported.ClientState, -) error { - merkleProof, provingConsensusState, err := produceVerificationArgs(store, cdc, cs, height, prefix, proof) - if err != nil { - return err - } - - clientPrefixedPath := commitmenttypes.NewMerklePath(host.FullClientStatePath(counterpartyClientIdentifier)) - path, err := commitmenttypes.ApplyPrefix(prefix, clientPrefixedPath) - if err != nil { - return err - } - - if clientState == nil { - return sdkerrors.Wrap(clienttypes.ErrInvalidClient, "client state cannot be empty") - } - - _, ok := clientState.(*ClientState) - if !ok { - return sdkerrors.Wrapf(clienttypes.ErrInvalidClient, "invalid client type %T, expected %T", clientState, &ClientState{}) - } - - bz, err := cdc.MarshalInterface(clientState) - if err != nil { - return err - } - - return merkleProof.VerifyMembership(cs.ProofSpecs, provingConsensusState.GetRoot(), path, bz) -} - -// VerifyClientConsensusState verifies a proof of the consensus state of the -// Tendermint client stored on the target machine. -func (cs ClientState) VerifyClientConsensusState( - store sdk.KVStore, - cdc codec.BinaryMarshaler, - height exported.Height, - counterpartyClientIdentifier string, - consensusHeight exported.Height, - prefix exported.Prefix, - proof []byte, - consensusState exported.ConsensusState, -) error { - merkleProof, provingConsensusState, err := produceVerificationArgs(store, cdc, cs, height, prefix, proof) - if err != nil { - return err - } - - clientPrefixedPath := commitmenttypes.NewMerklePath(host.FullConsensusStatePath(counterpartyClientIdentifier, consensusHeight)) - path, err := commitmenttypes.ApplyPrefix(prefix, clientPrefixedPath) - if err != nil { - return err - } - - if consensusState == nil { - return sdkerrors.Wrap(clienttypes.ErrInvalidConsensus, "consensus state cannot be empty") - } - - _, ok := consensusState.(*ConsensusState) - if !ok { - return sdkerrors.Wrapf(clienttypes.ErrInvalidConsensus, "invalid consensus type %T, expected %T", consensusState, &ConsensusState{}) - } - - bz, err := cdc.MarshalInterface(consensusState) - if err != nil { - return err - } - - if err := merkleProof.VerifyMembership(cs.ProofSpecs, provingConsensusState.GetRoot(), path, bz); err != nil { - return err - } - - return nil -} - -// VerifyConnectionState verifies a proof of the connection state of the -// specified connection end stored on the target machine. -func (cs ClientState) VerifyConnectionState( - store sdk.KVStore, - cdc codec.BinaryMarshaler, - height exported.Height, - prefix exported.Prefix, - proof []byte, - connectionID string, - connectionEnd exported.ConnectionI, -) error { - merkleProof, consensusState, err := produceVerificationArgs(store, cdc, cs, height, prefix, proof) - if err != nil { - return err - } - - connectionPath := commitmenttypes.NewMerklePath(host.ConnectionPath(connectionID)) - path, err := commitmenttypes.ApplyPrefix(prefix, connectionPath) - if err != nil { - return err - } - - connection, ok := connectionEnd.(connectiontypes.ConnectionEnd) - if !ok { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "invalid connection type %T", connectionEnd) - } - - bz, err := cdc.MarshalBinaryBare(&connection) - if err != nil { - return err - } - - if err := merkleProof.VerifyMembership(cs.ProofSpecs, consensusState.GetRoot(), path, bz); err != nil { - return err - } - - return nil -} - -// VerifyChannelState verifies a proof of the channel state of the specified -// channel end, under the specified port, stored on the target machine. -func (cs ClientState) VerifyChannelState( - store sdk.KVStore, - cdc codec.BinaryMarshaler, - height exported.Height, - prefix exported.Prefix, - proof []byte, - portID, - channelID string, - channel exported.ChannelI, -) error { - merkleProof, consensusState, err := produceVerificationArgs(store, cdc, cs, height, prefix, proof) - if err != nil { - return err - } - - channelPath := commitmenttypes.NewMerklePath(host.ChannelPath(portID, channelID)) - path, err := commitmenttypes.ApplyPrefix(prefix, channelPath) - if err != nil { - return err - } - - channelEnd, ok := channel.(channeltypes.Channel) - if !ok { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "invalid channel type %T", channel) - } - - bz, err := cdc.MarshalBinaryBare(&channelEnd) - if err != nil { - return err - } - - if err := merkleProof.VerifyMembership(cs.ProofSpecs, consensusState.GetRoot(), path, bz); err != nil { - return err - } - - return nil -} - -// VerifyPacketCommitment verifies a proof of an outgoing packet commitment at -// the specified port, specified channel, and specified sequence. -func (cs ClientState) VerifyPacketCommitment( - store sdk.KVStore, - cdc codec.BinaryMarshaler, - height exported.Height, - currentTimestamp uint64, - delayPeriod uint64, - prefix exported.Prefix, - proof []byte, - portID, - channelID string, - sequence uint64, - commitmentBytes []byte, -) error { - merkleProof, consensusState, err := produceVerificationArgs(store, cdc, cs, height, prefix, proof) - if err != nil { - return err - } - - // check delay period has passed - if err := verifyDelayPeriodPassed(store, height, currentTimestamp, delayPeriod); err != nil { - return err - } - - commitmentPath := commitmenttypes.NewMerklePath(host.PacketCommitmentPath(portID, channelID, sequence)) - path, err := commitmenttypes.ApplyPrefix(prefix, commitmentPath) - if err != nil { - return err - } - - if err := merkleProof.VerifyMembership(cs.ProofSpecs, consensusState.GetRoot(), path, commitmentBytes); err != nil { - return err - } - - return nil -} - -// VerifyPacketAcknowledgement verifies a proof of an incoming packet -// acknowledgement at the specified port, specified channel, and specified sequence. -func (cs ClientState) VerifyPacketAcknowledgement( - store sdk.KVStore, - cdc codec.BinaryMarshaler, - height exported.Height, - currentTimestamp uint64, - delayPeriod uint64, - prefix exported.Prefix, - proof []byte, - portID, - channelID string, - sequence uint64, - acknowledgement []byte, -) error { - merkleProof, consensusState, err := produceVerificationArgs(store, cdc, cs, height, prefix, proof) - if err != nil { - return err - } - - // check delay period has passed - if err := verifyDelayPeriodPassed(store, height, currentTimestamp, delayPeriod); err != nil { - return err - } - - ackPath := commitmenttypes.NewMerklePath(host.PacketAcknowledgementPath(portID, channelID, sequence)) - path, err := commitmenttypes.ApplyPrefix(prefix, ackPath) - if err != nil { - return err - } - - if err := merkleProof.VerifyMembership(cs.ProofSpecs, consensusState.GetRoot(), path, channeltypes.CommitAcknowledgement(acknowledgement)); err != nil { - return err - } - - return nil -} - -// VerifyPacketReceiptAbsence verifies a proof of the absence of an -// incoming packet receipt at the specified port, specified channel, and -// specified sequence. -func (cs ClientState) VerifyPacketReceiptAbsence( - store sdk.KVStore, - cdc codec.BinaryMarshaler, - height exported.Height, - currentTimestamp uint64, - delayPeriod uint64, - prefix exported.Prefix, - proof []byte, - portID, - channelID string, - sequence uint64, -) error { - merkleProof, consensusState, err := produceVerificationArgs(store, cdc, cs, height, prefix, proof) - if err != nil { - return err - } - - // check delay period has passed - if err := verifyDelayPeriodPassed(store, height, currentTimestamp, delayPeriod); err != nil { - return err - } - - receiptPath := commitmenttypes.NewMerklePath(host.PacketReceiptPath(portID, channelID, sequence)) - path, err := commitmenttypes.ApplyPrefix(prefix, receiptPath) - if err != nil { - return err - } - - if err := merkleProof.VerifyNonMembership(cs.ProofSpecs, consensusState.GetRoot(), path); err != nil { - return err - } - - return nil -} - -// VerifyNextSequenceRecv verifies a proof of the next sequence number to be -// received of the specified channel at the specified port. -func (cs ClientState) VerifyNextSequenceRecv( - store sdk.KVStore, - cdc codec.BinaryMarshaler, - height exported.Height, - currentTimestamp uint64, - delayPeriod uint64, - prefix exported.Prefix, - proof []byte, - portID, - channelID string, - nextSequenceRecv uint64, -) error { - merkleProof, consensusState, err := produceVerificationArgs(store, cdc, cs, height, prefix, proof) - if err != nil { - return err - } - - // check delay period has passed - if err := verifyDelayPeriodPassed(store, height, currentTimestamp, delayPeriod); err != nil { - return err - } - - nextSequenceRecvPath := commitmenttypes.NewMerklePath(host.NextSequenceRecvPath(portID, channelID)) - path, err := commitmenttypes.ApplyPrefix(prefix, nextSequenceRecvPath) - if err != nil { - return err - } - - bz := sdk.Uint64ToBigEndian(nextSequenceRecv) - - if err := merkleProof.VerifyMembership(cs.ProofSpecs, consensusState.GetRoot(), path, bz); err != nil { - return err - } - - return nil -} - -// verifyDelayPeriodPassed will ensure that at least delayPeriod amount of time has passed since consensus state was submitted -// before allowing verification to continue. -func verifyDelayPeriodPassed(store sdk.KVStore, proofHeight exported.Height, currentTimestamp, delayPeriod uint64) error { - // check that executing chain's timestamp has passed consensusState's processed time + delay period - processedTime, ok := GetProcessedTime(store, proofHeight) - if !ok { - return sdkerrors.Wrapf(ErrProcessedTimeNotFound, "processed time not found for height: %s", proofHeight) - } - validTime := processedTime + delayPeriod - // NOTE: delay period is inclusive, so if currentTimestamp is validTime, then we return no error - if validTime > currentTimestamp { - return sdkerrors.Wrapf(ErrDelayPeriodNotPassed, "cannot verify packet until time: %d, current time: %d", - validTime, currentTimestamp) - } - return nil -} - -// produceVerificationArgs perfoms the basic checks on the arguments that are -// shared between the verification functions and returns the unmarshalled -// merkle proof, the consensus state and an error if one occurred. -func produceVerificationArgs( - store sdk.KVStore, - cdc codec.BinaryMarshaler, - cs ClientState, - height exported.Height, - prefix exported.Prefix, - proof []byte, -) (merkleProof commitmenttypes.MerkleProof, consensusState *ConsensusState, err error) { - if cs.GetLatestHeight().LT(height) { - return commitmenttypes.MerkleProof{}, nil, sdkerrors.Wrapf( - sdkerrors.ErrInvalidHeight, - "client state height < proof height (%d < %d)", cs.GetLatestHeight(), height, - ) - } - - if cs.IsFrozen() && !cs.FrozenHeight.GT(height) { - return commitmenttypes.MerkleProof{}, nil, clienttypes.ErrClientFrozen - } - - if prefix == nil { - return commitmenttypes.MerkleProof{}, nil, sdkerrors.Wrap(commitmenttypes.ErrInvalidPrefix, "prefix cannot be empty") - } - - _, ok := prefix.(*commitmenttypes.MerklePrefix) - if !ok { - return commitmenttypes.MerkleProof{}, nil, sdkerrors.Wrapf(commitmenttypes.ErrInvalidPrefix, "invalid prefix type %T, expected *MerklePrefix", prefix) - } - - if proof == nil { - return commitmenttypes.MerkleProof{}, nil, sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "proof cannot be empty") - } - - if err = cdc.UnmarshalBinaryBare(proof, &merkleProof); err != nil { - return commitmenttypes.MerkleProof{}, nil, sdkerrors.Wrap(commitmenttypes.ErrInvalidProof, "failed to unmarshal proof into commitment merkle proof") - } - - consensusState, err = GetConsensusState(store, cdc, height) - if err != nil { - return commitmenttypes.MerkleProof{}, nil, err - } - - return merkleProof, consensusState, nil -} diff --git a/x/ibc/light-clients/07-tendermint/types/client_state_test.go b/x/ibc/light-clients/07-tendermint/types/client_state_test.go deleted file mode 100644 index 744b4729f6ef..000000000000 --- a/x/ibc/light-clients/07-tendermint/types/client_state_test.go +++ /dev/null @@ -1,779 +0,0 @@ -package types_test - -import ( - "time" - - ics23 "github.com/confio/ics23/go" - - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" - ibcmock "github.com/cosmos/cosmos-sdk/x/ibc/testing/mock" -) - -const ( - testClientID = "clientidone" - testConnectionID = "connectionid" - testPortID = "testportid" - testChannelID = "testchannelid" - testSequence = 1 -) - -var ( - invalidProof = []byte("invalid proof") -) - -func (suite *TendermintTestSuite) TestValidate() { - testCases := []struct { - name string - clientState *types.ClientState - expPass bool - }{ - { - name: "valid client", - clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false), - expPass: true, - }, - { - name: "valid client with nil upgrade path", - clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), nil, false, false), - expPass: true, - }, - { - name: "invalid chainID", - clientState: types.NewClientState(" ", types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false), - expPass: false, - }, - { - name: "invalid trust level", - clientState: types.NewClientState(chainID, types.Fraction{Numerator: 0, Denominator: 1}, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false), - expPass: false, - }, - { - name: "invalid trusting period", - clientState: types.NewClientState(chainID, types.DefaultTrustLevel, 0, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false), - expPass: false, - }, - { - name: "invalid unbonding period", - clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, 0, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false), - expPass: false, - }, - { - name: "invalid max clock drift", - clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, 0, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false), - expPass: false, - }, - { - name: "invalid height", - clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, clienttypes.ZeroHeight(), commitmenttypes.GetSDKSpecs(), upgradePath, false, false), - expPass: false, - }, - { - name: "trusting period not less than unbonding period", - clientState: types.NewClientState(chainID, types.DefaultTrustLevel, ubdPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false), - expPass: false, - }, - { - name: "proof specs is nil", - clientState: types.NewClientState(chainID, types.DefaultTrustLevel, ubdPeriod, ubdPeriod, maxClockDrift, height, nil, upgradePath, false, false), - expPass: false, - }, - { - name: "proof specs contains nil", - clientState: types.NewClientState(chainID, types.DefaultTrustLevel, ubdPeriod, ubdPeriod, maxClockDrift, height, []*ics23.ProofSpec{ics23.TendermintSpec, nil}, upgradePath, false, false), - expPass: false, - }, - } - - for _, tc := range testCases { - err := tc.clientState.Validate() - if tc.expPass { - suite.Require().NoError(err, tc.name) - } else { - suite.Require().Error(err, tc.name) - } - } -} - -func (suite *TendermintTestSuite) TestInitialize() { - - testCases := []struct { - name string - consensusState exported.ConsensusState - expPass bool - }{ - { - name: "valid consensus", - consensusState: &types.ConsensusState{}, - expPass: true, - }, - { - name: "invalid consensus: consensus state is solomachine consensus", - consensusState: ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec, "solomachine", "", 2).ConsensusState(), - expPass: false, - }, - } - - clientA, err := suite.coordinator.CreateClient(suite.chainA, suite.chainB, exported.Tendermint) - suite.Require().NoError(err) - - clientState := suite.chainA.GetClientState(clientA) - store := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), clientA) - - for _, tc := range testCases { - err := clientState.Initialize(suite.chainA.GetContext(), suite.chainA.Codec, store, tc.consensusState) - if tc.expPass { - suite.Require().NoError(err, "valid case returned an error") - } else { - suite.Require().Error(err, "invalid case didn't return an error") - } - } -} - -func (suite *TendermintTestSuite) TestVerifyClientConsensusState() { - testCases := []struct { - name string - clientState *types.ClientState - consensusState *types.ConsensusState - prefix commitmenttypes.MerklePrefix - proof []byte - expPass bool - }{ - // FIXME: uncomment - // { - // name: "successful verification", - // clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs()), - // consensusState: types.ConsensusState{ - // Root: commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), - // }, - // prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")), - // expPass: true, - // }, - { - name: "ApplyPrefix failed", - clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false), - consensusState: &types.ConsensusState{ - Root: commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), - }, - prefix: commitmenttypes.MerklePrefix{}, - expPass: false, - }, - { - name: "latest client height < height", - clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false), - consensusState: &types.ConsensusState{ - Root: commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), - }, - prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")), - expPass: false, - }, - { - name: "client is frozen", - clientState: &types.ClientState{LatestHeight: height, FrozenHeight: clienttypes.NewHeight(height.RevisionNumber, height.RevisionHeight-1)}, - consensusState: &types.ConsensusState{ - Root: commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), - }, - prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")), - expPass: false, - }, - { - name: "proof verification failed", - clientState: types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false), - consensusState: &types.ConsensusState{ - Root: commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), - NextValidatorsHash: suite.valsHash, - }, - prefix: commitmenttypes.NewMerklePrefix([]byte("ibc")), - proof: []byte{}, - expPass: false, - }, - } - - for i, tc := range testCases { - tc := tc - - err := tc.clientState.VerifyClientConsensusState( - nil, suite.cdc, height, "chainA", tc.clientState.LatestHeight, tc.prefix, tc.proof, tc.consensusState, - ) - - if tc.expPass { - suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name) - } else { - suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name) - } - } -} - -// test verification of the connection on chainB being represented in the -// light client on chainA -func (suite *TendermintTestSuite) TestVerifyConnectionState() { - var ( - clientState *types.ClientState - proof []byte - proofHeight exported.Height - prefix commitmenttypes.MerklePrefix - ) - - testCases := []struct { - name string - malleate func() - expPass bool - }{ - { - "successful verification", func() {}, true, - }, - { - "ApplyPrefix failed", func() { - prefix = commitmenttypes.MerklePrefix{} - }, false, - }, - { - "latest client height < height", func() { - proofHeight = clientState.LatestHeight.Increment() - }, false, - }, - { - "client is frozen", func() { - clientState.FrozenHeight = clienttypes.NewHeight(0, 1) - }, false, - }, - { - "proof verification failed", func() { - proof = invalidProof - }, false, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - suite.SetupTest() // reset - - // setup testing conditions - clientA, _, _, connB, _, _ := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.UNORDERED) - connection := suite.chainB.GetConnection(connB) - - var ok bool - clientStateI := suite.chainA.GetClientState(clientA) - clientState, ok = clientStateI.(*types.ClientState) - suite.Require().True(ok) - - prefix = suite.chainB.GetPrefix() - - // make connection proof - connectionKey := host.ConnectionKey(connB.ID) - proof, proofHeight = suite.chainB.QueryProof(connectionKey) - - tc.malleate() // make changes as necessary - - store := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), clientA) - - err := clientState.VerifyConnectionState( - store, suite.chainA.Codec, proofHeight, &prefix, proof, connB.ID, connection, - ) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} - -// test verification of the channel on chainB being represented in the light -// client on chainA -func (suite *TendermintTestSuite) TestVerifyChannelState() { - var ( - clientState *types.ClientState - proof []byte - proofHeight exported.Height - prefix commitmenttypes.MerklePrefix - ) - - testCases := []struct { - name string - malleate func() - expPass bool - }{ - { - "successful verification", func() {}, true, - }, - { - "ApplyPrefix failed", func() { - prefix = commitmenttypes.MerklePrefix{} - }, false, - }, - { - "latest client height < height", func() { - proofHeight = clientState.LatestHeight.Increment() - }, false, - }, - { - "client is frozen", func() { - clientState.FrozenHeight = clienttypes.NewHeight(0, 1) - }, false, - }, - { - "proof verification failed", func() { - proof = invalidProof - }, false, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - suite.SetupTest() // reset - - // setup testing conditions - clientA, _, _, _, _, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.UNORDERED) - channel := suite.chainB.GetChannel(channelB) - - var ok bool - clientStateI := suite.chainA.GetClientState(clientA) - clientState, ok = clientStateI.(*types.ClientState) - suite.Require().True(ok) - - prefix = suite.chainB.GetPrefix() - - // make channel proof - channelKey := host.ChannelKey(channelB.PortID, channelB.ID) - proof, proofHeight = suite.chainB.QueryProof(channelKey) - - tc.malleate() // make changes as necessary - - store := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), clientA) - - err := clientState.VerifyChannelState( - store, suite.chainA.Codec, proofHeight, &prefix, proof, - channelB.PortID, channelB.ID, channel, - ) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} - -// test verification of the packet commitment on chainB being represented -// in the light client on chainA. A send from chainB to chainA is simulated. -func (suite *TendermintTestSuite) TestVerifyPacketCommitment() { - var ( - clientState *types.ClientState - proof []byte - delayPeriod uint64 - proofHeight exported.Height - prefix commitmenttypes.MerklePrefix - ) - - testCases := []struct { - name string - malleate func() - expPass bool - }{ - { - "successful verification", func() {}, true, - }, - { - name: "delay period has passed", - malleate: func() { - delayPeriod = uint64(time.Second.Nanoseconds()) - }, - expPass: true, - }, - { - name: "delay period has not passed", - malleate: func() { - delayPeriod = uint64(time.Hour.Nanoseconds()) - }, - expPass: false, - }, - { - "ApplyPrefix failed", func() { - prefix = commitmenttypes.MerklePrefix{} - }, false, - }, - { - "latest client height < height", func() { - proofHeight = clientState.LatestHeight.Increment() - }, false, - }, - { - "client is frozen", func() { - clientState.FrozenHeight = clienttypes.NewHeight(0, 1) - }, false, - }, - { - "proof verification failed", func() { - proof = invalidProof - }, false, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - suite.SetupTest() // reset - - // setup testing conditions - clientA, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.UNORDERED) - packet := channeltypes.NewPacket(ibctesting.TestHash, 1, channelB.PortID, channelB.ID, channelA.PortID, channelA.ID, clienttypes.NewHeight(0, 100), 0) - err := suite.coordinator.SendPacket(suite.chainB, suite.chainA, packet, clientA) - suite.Require().NoError(err) - - var ok bool - clientStateI := suite.chainA.GetClientState(clientA) - clientState, ok = clientStateI.(*types.ClientState) - suite.Require().True(ok) - - prefix = suite.chainB.GetPrefix() - - // make packet commitment proof - packetKey := host.PacketCommitmentKey(packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) - proof, proofHeight = suite.chainB.QueryProof(packetKey) - - tc.malleate() // make changes as necessary - - store := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), clientA) - - currentTime := uint64(suite.chainA.GetContext().BlockTime().UnixNano()) - commitment := channeltypes.CommitPacket(suite.chainA.App.IBCKeeper.Codec(), packet) - err = clientState.VerifyPacketCommitment( - store, suite.chainA.Codec, proofHeight, currentTime, delayPeriod, &prefix, proof, - packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence(), commitment, - ) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} - -// test verification of the acknowledgement on chainB being represented -// in the light client on chainA. A send and ack from chainA to chainB -// is simulated. -func (suite *TendermintTestSuite) TestVerifyPacketAcknowledgement() { - var ( - clientState *types.ClientState - proof []byte - delayPeriod uint64 - proofHeight exported.Height - prefix commitmenttypes.MerklePrefix - ) - - testCases := []struct { - name string - malleate func() - expPass bool - }{ - { - "successful verification", func() {}, true, - }, - { - name: "delay period has passed", - malleate: func() { - delayPeriod = uint64(time.Second.Nanoseconds()) - }, - expPass: true, - }, - { - name: "delay period has not passed", - malleate: func() { - delayPeriod = uint64(time.Hour.Nanoseconds()) - }, - expPass: false, - }, - { - "ApplyPrefix failed", func() { - prefix = commitmenttypes.MerklePrefix{} - }, false, - }, - { - "latest client height < height", func() { - proofHeight = clientState.LatestHeight.Increment() - }, false, - }, - { - "client is frozen", func() { - clientState.FrozenHeight = clienttypes.NewHeight(0, 1) - }, false, - }, - { - "proof verification failed", func() { - proof = invalidProof - }, false, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - suite.SetupTest() // reset - - // setup testing conditions - clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.UNORDERED) - packet := channeltypes.NewPacket(ibctesting.TestHash, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, clienttypes.NewHeight(0, 100), 0) - - // send packet - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - - // write receipt and ack - err = suite.coordinator.RecvPacket(suite.chainA, suite.chainB, clientA, packet) - suite.Require().NoError(err) - - var ok bool - clientStateI := suite.chainA.GetClientState(clientA) - clientState, ok = clientStateI.(*types.ClientState) - suite.Require().True(ok) - - prefix = suite.chainB.GetPrefix() - - // make packet acknowledgement proof - acknowledgementKey := host.PacketAcknowledgementKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - proof, proofHeight = suite.chainB.QueryProof(acknowledgementKey) - - tc.malleate() // make changes as necessary - - store := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), clientA) - - currentTime := uint64(suite.chainA.GetContext().BlockTime().UnixNano()) - err = clientState.VerifyPacketAcknowledgement( - store, suite.chainA.Codec, proofHeight, currentTime, delayPeriod, &prefix, proof, - packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence(), ibcmock.MockAcknowledgement, - ) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} - -// test verification of the absent acknowledgement on chainB being represented -// in the light client on chainA. A send from chainB to chainA is simulated, but -// no receive. -func (suite *TendermintTestSuite) TestVerifyPacketReceiptAbsence() { - var ( - clientState *types.ClientState - proof []byte - delayPeriod uint64 - proofHeight exported.Height - prefix commitmenttypes.MerklePrefix - ) - - testCases := []struct { - name string - malleate func() - expPass bool - }{ - { - "successful verification", func() {}, true, - }, - { - name: "delay period has passed", - malleate: func() { - delayPeriod = uint64(time.Second.Nanoseconds()) - }, - expPass: true, - }, - { - name: "delay period has not passed", - malleate: func() { - delayPeriod = uint64(time.Hour.Nanoseconds()) - }, - expPass: false, - }, - { - "ApplyPrefix failed", func() { - prefix = commitmenttypes.MerklePrefix{} - }, false, - }, - { - "latest client height < height", func() { - proofHeight = clientState.LatestHeight.Increment() - }, false, - }, - { - "client is frozen", func() { - clientState.FrozenHeight = clienttypes.NewHeight(0, 1) - }, false, - }, - { - "proof verification failed", func() { - proof = invalidProof - }, false, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - suite.SetupTest() // reset - - // setup testing conditions - clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.UNORDERED) - packet := channeltypes.NewPacket(ibctesting.TestHash, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, clienttypes.NewHeight(0, 100), 0) - - // send packet, but no recv - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - - // need to update chainA's client representing chainB to prove missing ack - suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - - var ok bool - clientStateI := suite.chainA.GetClientState(clientA) - clientState, ok = clientStateI.(*types.ClientState) - suite.Require().True(ok) - - prefix = suite.chainB.GetPrefix() - - // make packet receipt absence proof - receiptKey := host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - proof, proofHeight = suite.chainB.QueryProof(receiptKey) - - tc.malleate() // make changes as necessary - - store := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), clientA) - - currentTime := uint64(suite.chainA.GetContext().BlockTime().UnixNano()) - err = clientState.VerifyPacketReceiptAbsence( - store, suite.chainA.Codec, proofHeight, currentTime, delayPeriod, &prefix, proof, - packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence(), - ) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} - -// test verification of the next receive sequence on chainB being represented -// in the light client on chainA. A send and receive from chainB to chainA is -// simulated. -func (suite *TendermintTestSuite) TestVerifyNextSeqRecv() { - var ( - clientState *types.ClientState - proof []byte - delayPeriod uint64 - proofHeight exported.Height - prefix commitmenttypes.MerklePrefix - ) - - testCases := []struct { - name string - malleate func() - expPass bool - }{ - { - "successful verification", func() {}, true, - }, - { - name: "delay period has passed", - malleate: func() { - delayPeriod = uint64(time.Second.Nanoseconds()) - }, - expPass: true, - }, - { - name: "delay period has not passed", - malleate: func() { - delayPeriod = uint64(time.Hour.Nanoseconds()) - }, - expPass: false, - }, - { - "ApplyPrefix failed", func() { - prefix = commitmenttypes.MerklePrefix{} - }, false, - }, - { - "latest client height < height", func() { - proofHeight = clientState.LatestHeight.Increment() - }, false, - }, - { - "client is frozen", func() { - clientState.FrozenHeight = clienttypes.NewHeight(0, 1) - }, false, - }, - { - "proof verification failed", func() { - proof = invalidProof - }, false, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - suite.SetupTest() // reset - - // setup testing conditions - clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.ORDERED) - packet := channeltypes.NewPacket(ibctesting.TestHash, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, clienttypes.NewHeight(0, 100), 0) - - // send packet - err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB) - suite.Require().NoError(err) - - // next seq recv incremented - err = suite.coordinator.RecvPacket(suite.chainA, suite.chainB, clientA, packet) - suite.Require().NoError(err) - - // need to update chainA's client representing chainB - suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - - var ok bool - clientStateI := suite.chainA.GetClientState(clientA) - clientState, ok = clientStateI.(*types.ClientState) - suite.Require().True(ok) - - prefix = suite.chainB.GetPrefix() - - // make next seq recv proof - nextSeqRecvKey := host.NextSequenceRecvKey(packet.GetDestPort(), packet.GetDestChannel()) - proof, proofHeight = suite.chainB.QueryProof(nextSeqRecvKey) - - tc.malleate() // make changes as necessary - - store := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), clientA) - - currentTime := uint64(suite.chainA.GetContext().BlockTime().UnixNano()) - err = clientState.VerifyNextSequenceRecv( - store, suite.chainA.Codec, proofHeight, currentTime, delayPeriod, &prefix, proof, - packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()+1, - ) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} diff --git a/x/ibc/light-clients/07-tendermint/types/codec.go b/x/ibc/light-clients/07-tendermint/types/codec.go deleted file mode 100644 index 5d876c8fe0e8..000000000000 --- a/x/ibc/light-clients/07-tendermint/types/codec.go +++ /dev/null @@ -1,27 +0,0 @@ -package types - -import ( - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -// RegisterInterfaces registers the tendermint concrete client-related -// implementations and interfaces. -func RegisterInterfaces(registry codectypes.InterfaceRegistry) { - registry.RegisterImplementations( - (*exported.ClientState)(nil), - &ClientState{}, - ) - registry.RegisterImplementations( - (*exported.ConsensusState)(nil), - &ConsensusState{}, - ) - registry.RegisterImplementations( - (*exported.Header)(nil), - &Header{}, - ) - registry.RegisterImplementations( - (*exported.Misbehaviour)(nil), - &Misbehaviour{}, - ) -} diff --git a/x/ibc/light-clients/07-tendermint/types/consensus_state.go b/x/ibc/light-clients/07-tendermint/types/consensus_state.go deleted file mode 100644 index adb469a3d108..000000000000 --- a/x/ibc/light-clients/07-tendermint/types/consensus_state.go +++ /dev/null @@ -1,55 +0,0 @@ -package types - -import ( - "time" - - tmbytes "github.com/tendermint/tendermint/libs/bytes" - tmtypes "github.com/tendermint/tendermint/types" - - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - 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/core/exported" -) - -// NewConsensusState creates a new ConsensusState instance. -func NewConsensusState( - timestamp time.Time, root commitmenttypes.MerkleRoot, nextValsHash tmbytes.HexBytes, -) *ConsensusState { - return &ConsensusState{ - Timestamp: timestamp, - Root: root, - NextValidatorsHash: nextValsHash, - } -} - -// ClientType returns Tendermint -func (ConsensusState) ClientType() string { - return exported.Tendermint -} - -// GetRoot returns the commitment Root for the specific -func (cs ConsensusState) GetRoot() exported.Root { - return cs.Root -} - -// GetTimestamp returns block time in nanoseconds of the header that created consensus state -func (cs ConsensusState) GetTimestamp() uint64 { - return uint64(cs.Timestamp.UnixNano()) -} - -// ValidateBasic defines a basic validation for the tendermint consensus state. -// NOTE: ProcessedTimestamp may be zero if this is an initial consensus state passed in by relayer -// as opposed to a consensus state constructed by the chain. -func (cs ConsensusState) ValidateBasic() error { - if cs.Root.Empty() { - return sdkerrors.Wrap(clienttypes.ErrInvalidConsensus, "root cannot be empty") - } - if err := tmtypes.ValidateHash(cs.NextValidatorsHash); err != nil { - return sdkerrors.Wrap(err, "next validators hash is invalid") - } - if cs.Timestamp.Unix() <= 0 { - return sdkerrors.Wrap(clienttypes.ErrInvalidConsensus, "timestamp must be a positive Unix time") - } - return nil -} diff --git a/x/ibc/light-clients/07-tendermint/types/consensus_state_test.go b/x/ibc/light-clients/07-tendermint/types/consensus_state_test.go deleted file mode 100644 index 313815d0c7b7..000000000000 --- a/x/ibc/light-clients/07-tendermint/types/consensus_state_test.go +++ /dev/null @@ -1,69 +0,0 @@ -package types_test - -import ( - "time" - - commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" -) - -func (suite *TendermintTestSuite) TestConsensusStateValidateBasic() { - testCases := []struct { - msg string - consensusState *types.ConsensusState - expectPass bool - }{ - {"success", - &types.ConsensusState{ - Timestamp: suite.now, - Root: commitmenttypes.NewMerkleRoot([]byte("app_hash")), - NextValidatorsHash: suite.valsHash, - }, - true}, - {"root is nil", - &types.ConsensusState{ - Timestamp: suite.now, - Root: commitmenttypes.MerkleRoot{}, - NextValidatorsHash: suite.valsHash, - }, - false}, - {"root is empty", - &types.ConsensusState{ - Timestamp: suite.now, - Root: commitmenttypes.MerkleRoot{}, - NextValidatorsHash: suite.valsHash, - }, - false}, - {"nextvalshash is invalid", - &types.ConsensusState{ - Timestamp: suite.now, - Root: commitmenttypes.NewMerkleRoot([]byte("app_hash")), - NextValidatorsHash: []byte("hi"), - }, - false}, - - {"timestamp is zero", - &types.ConsensusState{ - Timestamp: time.Time{}, - Root: commitmenttypes.NewMerkleRoot([]byte("app_hash")), - NextValidatorsHash: suite.valsHash, - }, - false}, - } - - for i, tc := range testCases { - tc := tc - - // check just to increase coverage - suite.Require().Equal(exported.Tendermint, tc.consensusState.ClientType()) - suite.Require().Equal(tc.consensusState.GetRoot(), tc.consensusState.Root) - - err := tc.consensusState.ValidateBasic() - if tc.expectPass { - suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.msg) - } else { - suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.msg) - } - } -} diff --git a/x/ibc/light-clients/07-tendermint/types/errors.go b/x/ibc/light-clients/07-tendermint/types/errors.go deleted file mode 100644 index 276c225b7369..000000000000 --- a/x/ibc/light-clients/07-tendermint/types/errors.go +++ /dev/null @@ -1,25 +0,0 @@ -package types - -import ( - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" -) - -const ( - SubModuleName = "tendermint-client" -) - -// IBC tendermint client sentinel errors -var ( - ErrInvalidChainID = sdkerrors.Register(SubModuleName, 2, "invalid chain-id") - ErrInvalidTrustingPeriod = sdkerrors.Register(SubModuleName, 3, "invalid trusting period") - ErrInvalidUnbondingPeriod = sdkerrors.Register(SubModuleName, 4, "invalid unbonding period") - ErrInvalidHeaderHeight = sdkerrors.Register(SubModuleName, 5, "invalid header height") - ErrInvalidHeader = sdkerrors.Register(SubModuleName, 6, "invalid header") - ErrInvalidMaxClockDrift = sdkerrors.Register(SubModuleName, 7, "invalid max clock drift") - ErrProcessedTimeNotFound = sdkerrors.Register(SubModuleName, 8, "processed time not found") - ErrDelayPeriodNotPassed = sdkerrors.Register(SubModuleName, 9, "packet-specified delay period has not been reached") - ErrTrustingPeriodExpired = sdkerrors.Register(SubModuleName, 10, "time since latest trusted state has passed the trusting period") - ErrUnbondingPeriodExpired = sdkerrors.Register(SubModuleName, 11, "time since latest trusted state has passed the unbonding period") - ErrInvalidProofSpecs = sdkerrors.Register(SubModuleName, 12, "invalid proof specs") - ErrInvalidValidatorSet = sdkerrors.Register(SubModuleName, 13, "invalid validator set") -) diff --git a/x/ibc/light-clients/07-tendermint/types/fraction.go b/x/ibc/light-clients/07-tendermint/types/fraction.go deleted file mode 100644 index e445f19ba6f8..000000000000 --- a/x/ibc/light-clients/07-tendermint/types/fraction.go +++ /dev/null @@ -1,25 +0,0 @@ -package types - -import ( - tmmath "github.com/tendermint/tendermint/libs/math" - "github.com/tendermint/tendermint/light" -) - -// DefaultTrustLevel is the tendermint light client default trust level -var DefaultTrustLevel = NewFractionFromTm(light.DefaultTrustLevel) - -// NewFractionFromTm returns a new Fraction instance from a tmmath.Fraction -func NewFractionFromTm(f tmmath.Fraction) Fraction { - return Fraction{ - Numerator: f.Numerator, - Denominator: f.Denominator, - } -} - -// ToTendermint converts Fraction to tmmath.Fraction -func (f Fraction) ToTendermint() tmmath.Fraction { - return tmmath.Fraction{ - Numerator: f.Numerator, - Denominator: f.Denominator, - } -} diff --git a/x/ibc/light-clients/07-tendermint/types/genesis.go b/x/ibc/light-clients/07-tendermint/types/genesis.go deleted file mode 100644 index 7124643b55a0..000000000000 --- a/x/ibc/light-clients/07-tendermint/types/genesis.go +++ /dev/null @@ -1,21 +0,0 @@ -package types - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -// ExportMetadata exports all the processed times in the client store so they can be included in clients genesis -// and imported by a ClientKeeper -func (cs ClientState) ExportMetadata(store sdk.KVStore) []exported.GenesisMetadata { - gm := make([]exported.GenesisMetadata, 0) - IterateProcessedTime(store, func(key, val []byte) bool { - gm = append(gm, clienttypes.NewGenesisMetadata(key, val)) - return false - }) - if len(gm) == 0 { - return nil - } - return gm -} diff --git a/x/ibc/light-clients/07-tendermint/types/genesis_test.go b/x/ibc/light-clients/07-tendermint/types/genesis_test.go deleted file mode 100644 index 5732151e63ce..000000000000 --- a/x/ibc/light-clients/07-tendermint/types/genesis_test.go +++ /dev/null @@ -1,38 +0,0 @@ -package types_test - -import ( - "time" - - sdk "github.com/cosmos/cosmos-sdk/types" - 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" -) - -func (suite *TendermintTestSuite) TestExportMetadata() { - clientState := types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - suite.chainA.App.IBCKeeper.ClientKeeper.SetClientState(suite.chainA.GetContext(), "clientA", clientState) - - gm := clientState.ExportMetadata(suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), "clientA")) - suite.Require().Nil(gm, "client with no metadata returned non-nil exported metadata") - - clientStore := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), "clientA") - - // set some processed times - timestamp1 := uint64(time.Now().UnixNano()) - timestamp2 := uint64(time.Now().Add(time.Minute).UnixNano()) - timestampBz1 := sdk.Uint64ToBigEndian(timestamp1) - timestampBz2 := sdk.Uint64ToBigEndian(timestamp2) - types.SetProcessedTime(clientStore, clienttypes.NewHeight(0, 1), timestamp1) - types.SetProcessedTime(clientStore, clienttypes.NewHeight(0, 2), timestamp2) - - gm = clientState.ExportMetadata(suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), "clientA")) - suite.Require().NotNil(gm, "client with metadata returned nil exported metadata") - suite.Require().Len(gm, 2, "exported metadata has unexpected length") - - suite.Require().Equal(types.ProcessedTimeKey(clienttypes.NewHeight(0, 1)), gm[0].GetKey(), "metadata has unexpected key") - suite.Require().Equal(timestampBz1, gm[0].GetValue(), "metadata has unexpected value") - - suite.Require().Equal(types.ProcessedTimeKey(clienttypes.NewHeight(0, 2)), gm[1].GetKey(), "metadata has unexpected key") - suite.Require().Equal(timestampBz2, gm[1].GetValue(), "metadata has unexpected value") -} diff --git a/x/ibc/light-clients/07-tendermint/types/header.go b/x/ibc/light-clients/07-tendermint/types/header.go deleted file mode 100644 index 0b9cfa1db1e2..000000000000 --- a/x/ibc/light-clients/07-tendermint/types/header.go +++ /dev/null @@ -1,83 +0,0 @@ -package types - -import ( - "bytes" - "time" - - tmtypes "github.com/tendermint/tendermint/types" - - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - 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/core/exported" -) - -var _ exported.Header = &Header{} - -// ConsensusState returns the updated consensus state associated with the header -func (h Header) ConsensusState() *ConsensusState { - return &ConsensusState{ - Timestamp: h.GetTime(), - Root: commitmenttypes.NewMerkleRoot(h.Header.GetAppHash()), - NextValidatorsHash: h.Header.NextValidatorsHash, - } -} - -// ClientType defines that the Header is a Tendermint consensus algorithm -func (h Header) ClientType() string { - return exported.Tendermint -} - -// GetHeight returns the current height. It returns 0 if the tendermint -// header is nil. -// NOTE: the header.Header is checked to be non nil in ValidateBasic. -func (h Header) GetHeight() exported.Height { - revision := clienttypes.ParseChainID(h.Header.ChainID) - return clienttypes.NewHeight(revision, uint64(h.Header.Height)) -} - -// GetTime returns the current block timestamp. It returns a zero time if -// the tendermint header is nil. -// NOTE: the header.Header is checked to be non nil in ValidateBasic. -func (h Header) GetTime() time.Time { - return h.Header.Time -} - -// ValidateBasic calls the SignedHeader ValidateBasic function and checks -// that validatorsets are not nil. -// NOTE: TrustedHeight and TrustedValidators may be empty when creating client -// with MsgCreateClient -func (h Header) ValidateBasic() error { - if h.SignedHeader == nil { - return sdkerrors.Wrap(clienttypes.ErrInvalidHeader, "tendermint signed header cannot be nil") - } - if h.Header == nil { - return sdkerrors.Wrap(clienttypes.ErrInvalidHeader, "tendermint header cannot be nil") - } - tmSignedHeader, err := tmtypes.SignedHeaderFromProto(h.SignedHeader) - if err != nil { - return sdkerrors.Wrap(err, "header is not a tendermint header") - } - if err := tmSignedHeader.ValidateBasic(h.Header.GetChainID()); err != nil { - return sdkerrors.Wrap(err, "header failed basic validation") - } - - // TrustedHeight is less than Header for updates - // and less than or equal to Header for misbehaviour - if h.TrustedHeight.GT(h.GetHeight()) { - return sdkerrors.Wrapf(ErrInvalidHeaderHeight, "TrustedHeight %d must be less than or equal to header height %d", - h.TrustedHeight, h.GetHeight()) - } - - if h.ValidatorSet == nil { - return sdkerrors.Wrap(clienttypes.ErrInvalidHeader, "validator set is nil") - } - tmValset, err := tmtypes.ValidatorSetFromProto(h.ValidatorSet) - if err != nil { - return sdkerrors.Wrap(err, "validator set is not tendermint validator set") - } - if !bytes.Equal(h.Header.ValidatorsHash, tmValset.Hash()) { - return sdkerrors.Wrap(clienttypes.ErrInvalidHeader, "validator set does not match hash") - } - return nil -} diff --git a/x/ibc/light-clients/07-tendermint/types/header_test.go b/x/ibc/light-clients/07-tendermint/types/header_test.go deleted file mode 100644 index 97647f861400..000000000000 --- a/x/ibc/light-clients/07-tendermint/types/header_test.go +++ /dev/null @@ -1,82 +0,0 @@ -package types_test - -import ( - "time" - - tmprotocrypto "github.com/tendermint/tendermint/proto/tendermint/crypto" - - 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" -) - -func (suite *TendermintTestSuite) TestGetHeight() { - header := suite.chainA.LastHeader - suite.Require().NotEqual(uint64(0), header.GetHeight()) -} - -func (suite *TendermintTestSuite) TestGetTime() { - header := suite.chainA.LastHeader - suite.Require().NotEqual(time.Time{}, header.GetTime()) -} - -func (suite *TendermintTestSuite) TestHeaderValidateBasic() { - var ( - header *types.Header - ) - testCases := []struct { - name string - malleate func() - expPass bool - }{ - {"valid header", func() {}, true}, - {"header is nil", func() { - header.Header = nil - }, false}, - {"signed header is nil", func() { - header.SignedHeader = nil - }, false}, - {"SignedHeaderFromProto failed", func() { - header.SignedHeader.Commit.Height = -1 - }, false}, - {"signed header failed tendermint ValidateBasic", func() { - header = suite.chainA.LastHeader - header.SignedHeader.Commit = nil - }, false}, - {"trusted height is greater than header height", func() { - header.TrustedHeight = header.GetHeight().(clienttypes.Height).Increment().(clienttypes.Height) - }, false}, - {"validator set nil", func() { - header.ValidatorSet = nil - }, false}, - {"ValidatorSetFromProto failed", func() { - header.ValidatorSet.Validators[0].PubKey = tmprotocrypto.PublicKey{} - }, false}, - {"header validator hash does not equal hash of validator set", func() { - // use chainB's randomly generated validator set - header.ValidatorSet = suite.chainB.LastHeader.ValidatorSet - }, false}, - } - - suite.Require().Equal(exported.Tendermint, suite.header.ClientType()) - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - suite.SetupTest() - - header = suite.chainA.LastHeader // must be explicitly changed in malleate - - tc.malleate() - - err := header.ValidateBasic() - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} diff --git a/x/ibc/light-clients/07-tendermint/types/misbehaviour.go b/x/ibc/light-clients/07-tendermint/types/misbehaviour.go deleted file mode 100644 index 340130d29fa0..000000000000 --- a/x/ibc/light-clients/07-tendermint/types/misbehaviour.go +++ /dev/null @@ -1,141 +0,0 @@ -package types - -import ( - "bytes" - "time" - - tmproto "github.com/tendermint/tendermint/proto/tendermint/types" - tmtypes "github.com/tendermint/tendermint/types" - - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -var _ exported.Misbehaviour = &Misbehaviour{} - -// NewMisbehaviour creates a new Misbehaviour instance. -func NewMisbehaviour(clientID string, header1, header2 *Header) *Misbehaviour { - return &Misbehaviour{ - ClientId: clientID, - Header1: header1, - Header2: header2, - } -} - -// ClientType is Tendermint light client -func (misbehaviour Misbehaviour) ClientType() string { - return exported.Tendermint -} - -// GetClientID returns the ID of the client that committed a misbehaviour. -func (misbehaviour Misbehaviour) GetClientID() string { - return misbehaviour.ClientId -} - -// GetHeight returns the height at which misbehaviour occurred -// -// NOTE: assumes that misbehaviour headers have the same height -func (misbehaviour Misbehaviour) GetHeight() exported.Height { - return misbehaviour.Header1.GetHeight() -} - -// GetTime returns the timestamp at which misbehaviour occurred. It uses the -// maximum value from both headers to prevent producing an invalid header outside -// of the misbehaviour age range. -func (misbehaviour Misbehaviour) GetTime() time.Time { - t1, t2 := misbehaviour.Header1.GetTime(), misbehaviour.Header2.GetTime() - if t1.After(t2) { - return t1 - } - return t2 -} - -// ValidateBasic implements Misbehaviour interface -func (misbehaviour Misbehaviour) ValidateBasic() error { - if misbehaviour.Header1 == nil { - return sdkerrors.Wrap(ErrInvalidHeader, "misbehaviour Header1 cannot be nil") - } - if misbehaviour.Header2 == nil { - return sdkerrors.Wrap(ErrInvalidHeader, "misbehaviour Header2 cannot be nil") - } - if misbehaviour.Header1.TrustedHeight.RevisionHeight == 0 { - return sdkerrors.Wrapf(ErrInvalidHeaderHeight, "misbehaviour Header1 cannot have zero revision height") - } - if misbehaviour.Header2.TrustedHeight.RevisionHeight == 0 { - return sdkerrors.Wrapf(ErrInvalidHeaderHeight, "misbehaviour Header2 cannot have zero revision height") - } - if misbehaviour.Header1.TrustedValidators == nil { - return sdkerrors.Wrap(ErrInvalidValidatorSet, "trusted validator set in Header1 cannot be empty") - } - if misbehaviour.Header2.TrustedValidators == nil { - return sdkerrors.Wrap(ErrInvalidValidatorSet, "trusted validator set in Header2 cannot be empty") - } - if misbehaviour.Header1.Header.ChainID != misbehaviour.Header2.Header.ChainID { - return sdkerrors.Wrap(clienttypes.ErrInvalidMisbehaviour, "headers must have identical chainIDs") - } - - if err := host.ClientIdentifierValidator(misbehaviour.ClientId); err != nil { - return sdkerrors.Wrap(err, "misbehaviour client ID is invalid") - } - - // ValidateBasic on both validators - if err := misbehaviour.Header1.ValidateBasic(); err != nil { - return sdkerrors.Wrap( - clienttypes.ErrInvalidMisbehaviour, - sdkerrors.Wrap(err, "header 1 failed validation").Error(), - ) - } - if err := misbehaviour.Header2.ValidateBasic(); err != nil { - return sdkerrors.Wrap( - clienttypes.ErrInvalidMisbehaviour, - sdkerrors.Wrap(err, "header 2 failed validation").Error(), - ) - } - // Ensure that Heights are the same - if misbehaviour.Header1.GetHeight() != misbehaviour.Header2.GetHeight() { - return sdkerrors.Wrapf(clienttypes.ErrInvalidMisbehaviour, "headers in misbehaviour are on different heights (%d ≠ %d)", misbehaviour.Header1.GetHeight(), misbehaviour.Header2.GetHeight()) - } - - blockID1, err := tmtypes.BlockIDFromProto(&misbehaviour.Header1.SignedHeader.Commit.BlockID) - if err != nil { - return sdkerrors.Wrap(err, "invalid block ID from header 1 in misbehaviour") - } - blockID2, err := tmtypes.BlockIDFromProto(&misbehaviour.Header2.SignedHeader.Commit.BlockID) - if err != nil { - return sdkerrors.Wrap(err, "invalid block ID from header 2 in misbehaviour") - } - - // Ensure that Commit Hashes are different - if bytes.Equal(blockID1.Hash, blockID2.Hash) { - return sdkerrors.Wrap(clienttypes.ErrInvalidMisbehaviour, "headers block hashes are equal") - } - if err := validCommit(misbehaviour.Header1.Header.ChainID, *blockID1, - misbehaviour.Header1.Commit, misbehaviour.Header1.ValidatorSet); err != nil { - return err - } - if err := validCommit(misbehaviour.Header2.Header.ChainID, *blockID2, - misbehaviour.Header2.Commit, misbehaviour.Header2.ValidatorSet); err != nil { - return err - } - return nil -} - -// validCommit checks if the given commit is a valid commit from the passed-in validatorset -func validCommit(chainID string, blockID tmtypes.BlockID, commit *tmproto.Commit, valSet *tmproto.ValidatorSet) (err error) { - tmCommit, err := tmtypes.CommitFromProto(commit) - if err != nil { - return sdkerrors.Wrap(err, "commit is not tendermint commit type") - } - tmValset, err := tmtypes.ValidatorSetFromProto(valSet) - if err != nil { - return sdkerrors.Wrap(err, "validator set is not tendermint validator set type") - } - - if err := tmValset.VerifyCommitLight(chainID, blockID, tmCommit.Height, tmCommit); err != nil { - return sdkerrors.Wrap(clienttypes.ErrInvalidMisbehaviour, "validator set did not commit to header") - } - - return nil -} diff --git a/x/ibc/light-clients/07-tendermint/types/misbehaviour_handle.go b/x/ibc/light-clients/07-tendermint/types/misbehaviour_handle.go deleted file mode 100644 index 4c55552d3051..000000000000 --- a/x/ibc/light-clients/07-tendermint/types/misbehaviour_handle.go +++ /dev/null @@ -1,119 +0,0 @@ -package types - -import ( - "time" - - tmtypes "github.com/tendermint/tendermint/types" - - "github.com/cosmos/cosmos-sdk/codec" - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -// CheckMisbehaviourAndUpdateState determines whether or not two conflicting -// headers at the same height would have convinced the light client. -// -// NOTE: consensusState1 is the trusted consensus state that corresponds to the TrustedHeight -// of misbehaviour.Header1 -// Similarly, consensusState2 is the trusted consensus state that corresponds -// to misbehaviour.Header2 -func (cs ClientState) CheckMisbehaviourAndUpdateState( - ctx sdk.Context, - cdc codec.BinaryMarshaler, - clientStore sdk.KVStore, - misbehaviour exported.Misbehaviour, -) (exported.ClientState, error) { - tmMisbehaviour, ok := misbehaviour.(*Misbehaviour) - if !ok { - return nil, sdkerrors.Wrapf(clienttypes.ErrInvalidClientType, "expected type %T, got %T", misbehaviour, &Misbehaviour{}) - } - - // If client is already frozen at earlier height than misbehaviour, return with error - if cs.IsFrozen() && cs.FrozenHeight.LTE(misbehaviour.GetHeight()) { - return nil, sdkerrors.Wrapf(clienttypes.ErrInvalidMisbehaviour, - "client is already frozen at earlier height %s than misbehaviour height %s", cs.FrozenHeight, misbehaviour.GetHeight()) - } - - // Retrieve trusted consensus states for each Header in misbehaviour - // and unmarshal from clientStore - - // Get consensus bytes from clientStore - tmConsensusState1, err := GetConsensusState(clientStore, cdc, tmMisbehaviour.Header1.TrustedHeight) - if err != nil { - return nil, sdkerrors.Wrapf(err, "could not get trusted consensus state from clientStore for Header1 at TrustedHeight: %s", tmMisbehaviour.Header1) - } - - // Get consensus bytes from clientStore - tmConsensusState2, err := GetConsensusState(clientStore, cdc, tmMisbehaviour.Header2.TrustedHeight) - if err != nil { - return nil, sdkerrors.Wrapf(err, "could not get trusted consensus state from clientStore for Header2 at TrustedHeight: %s", tmMisbehaviour.Header2) - } - - // Check the validity of the two conflicting headers against their respective - // trusted consensus states - // NOTE: header height and commitment root assertions are checked in - // misbehaviour.ValidateBasic by the client keeper and msg.ValidateBasic - // by the base application. - if err := checkMisbehaviourHeader( - &cs, tmConsensusState1, tmMisbehaviour.Header1, ctx.BlockTime(), - ); err != nil { - return nil, sdkerrors.Wrap(err, "verifying Header1 in Misbehaviour failed") - } - if err := checkMisbehaviourHeader( - &cs, tmConsensusState2, tmMisbehaviour.Header2, ctx.BlockTime(), - ); err != nil { - return nil, sdkerrors.Wrap(err, "verifying Header2 in Misbehaviour failed") - } - - cs.FrozenHeight = tmMisbehaviour.GetHeight().(clienttypes.Height) - return &cs, nil -} - -// checkMisbehaviourHeader checks that a Header in Misbehaviour is valid misbehaviour given -// a trusted ConsensusState -func checkMisbehaviourHeader( - clientState *ClientState, consState *ConsensusState, header *Header, currentTimestamp time.Time, -) error { - - tmTrustedValset, err := tmtypes.ValidatorSetFromProto(header.TrustedValidators) - if err != nil { - return sdkerrors.Wrap(err, "trusted validator set is not tendermint validator set type") - } - - tmCommit, err := tmtypes.CommitFromProto(header.Commit) - if err != nil { - return sdkerrors.Wrap(err, "commit is not tendermint commit type") - } - - // check the trusted fields for the header against ConsensusState - if err := checkTrustedHeader(header, consState); err != nil { - return err - } - - // assert that the age of the trusted consensus state is not older than the trusting period - if currentTimestamp.Sub(consState.Timestamp) >= clientState.TrustingPeriod { - return sdkerrors.Wrapf( - ErrTrustingPeriodExpired, - "current timestamp minus the latest consensus state timestamp is greater than or equal to the trusting period (%d >= %d)", - currentTimestamp.Sub(consState.Timestamp), clientState.TrustingPeriod, - ) - } - - chainID := clientState.GetChainID() - // If chainID is in revision format, then set revision number of chainID with the revision number - // of the misbehaviour header - if clienttypes.IsRevisionFormat(chainID) { - chainID, _ = clienttypes.SetRevisionNumber(chainID, header.GetHeight().GetRevisionNumber()) - } - - // - ValidatorSet must have TrustLevel similarity with trusted FromValidatorSet - // - ValidatorSets on both headers are valid given the last trusted ValidatorSet - if err := tmTrustedValset.VerifyCommitLightTrusting( - chainID, tmCommit, clientState.TrustLevel.ToTendermint(), - ); err != nil { - return sdkerrors.Wrapf(clienttypes.ErrInvalidMisbehaviour, "validator set in header has too much change from trusted validator set: %v", err) - } - return nil -} diff --git a/x/ibc/light-clients/07-tendermint/types/misbehaviour_handle_test.go b/x/ibc/light-clients/07-tendermint/types/misbehaviour_handle_test.go deleted file mode 100644 index 3ca2e4dc1199..000000000000 --- a/x/ibc/light-clients/07-tendermint/types/misbehaviour_handle_test.go +++ /dev/null @@ -1,372 +0,0 @@ -package types_test - -import ( - "fmt" - "time" - - "github.com/tendermint/tendermint/crypto/tmhash" - tmtypes "github.com/tendermint/tendermint/types" - - 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/core/exported" - "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" - ibctestingmock "github.com/cosmos/cosmos-sdk/x/ibc/testing/mock" -) - -func (suite *TendermintTestSuite) TestCheckMisbehaviourAndUpdateState() { - altPrivVal := ibctestingmock.NewPV() - altPubKey, err := altPrivVal.GetPubKey() - suite.Require().NoError(err) - - altVal := tmtypes.NewValidator(altPubKey, 4) - - // Create bothValSet with both suite validator and altVal - bothValSet := tmtypes.NewValidatorSet(append(suite.valSet.Validators, altVal)) - bothValsHash := bothValSet.Hash() - // Create alternative validator set with only altVal - altValSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{altVal}) - - _, suiteVal := suite.valSet.GetByIndex(0) - - // Create signer array and ensure it is in same order as bothValSet - bothSigners := ibctesting.CreateSortedSignerArray(altPrivVal, suite.privVal, altVal, suiteVal) - - altSigners := []tmtypes.PrivValidator{altPrivVal} - - heightMinus1 := clienttypes.NewHeight(height.RevisionNumber, height.RevisionHeight-1) - heightMinus3 := clienttypes.NewHeight(height.RevisionNumber, height.RevisionHeight-3) - - testCases := []struct { - name string - clientState exported.ClientState - consensusState1 exported.ConsensusState - height1 clienttypes.Height - consensusState2 exported.ConsensusState - height2 clienttypes.Height - misbehaviour exported.Misbehaviour - timestamp time.Time - expPass bool - }{ - { - "valid misbehavior misbehaviour", - types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false), - types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash), - height, - types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash), - height, - &types.Misbehaviour{ - Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), height, suite.now, bothValSet, bothValSet, bothSigners), - Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), height, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners), - ClientId: chainID, - }, - suite.now, - true, - }, - { - "valid misbehavior at height greater than last consensusState", - types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false), - types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash), - heightMinus1, - types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash), - heightMinus1, - &types.Misbehaviour{ - Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), heightMinus1, suite.now, bothValSet, bothValSet, bothSigners), - Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), heightMinus1, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners), - ClientId: chainID, - }, - suite.now, - true, - }, - { - "valid misbehaviour with different trusted heights", - types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false), - types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash), - heightMinus1, - types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), suite.valsHash), - heightMinus3, - &types.Misbehaviour{ - Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), heightMinus1, suite.now, bothValSet, bothValSet, bothSigners), - Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), heightMinus3, suite.now.Add(time.Minute), bothValSet, suite.valSet, bothSigners), - ClientId: chainID, - }, - suite.now, - true, - }, - { - "valid misbehaviour at a previous revision", - types.NewClientState(chainIDRevision1, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, clienttypes.NewHeight(1, 1), commitmenttypes.GetSDKSpecs(), upgradePath, false, false), - types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash), - heightMinus1, - types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), suite.valsHash), - heightMinus3, - &types.Misbehaviour{ - Header1: suite.chainA.CreateTMClientHeader(chainIDRevision0, int64(height.RevisionHeight), heightMinus1, suite.now, bothValSet, bothValSet, bothSigners), - Header2: suite.chainA.CreateTMClientHeader(chainIDRevision0, int64(height.RevisionHeight), heightMinus3, suite.now.Add(time.Minute), bothValSet, suite.valSet, bothSigners), - ClientId: chainID, - }, - suite.now, - true, - }, - { - "valid misbehaviour at a future revision", - types.NewClientState(chainIDRevision0, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false), - types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash), - heightMinus1, - types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), suite.valsHash), - heightMinus3, - &types.Misbehaviour{ - Header1: suite.chainA.CreateTMClientHeader(chainIDRevision0, 3, heightMinus1, suite.now, bothValSet, bothValSet, bothSigners), - Header2: suite.chainA.CreateTMClientHeader(chainIDRevision0, 3, heightMinus3, suite.now.Add(time.Minute), bothValSet, suite.valSet, bothSigners), - ClientId: chainID, - }, - suite.now, - true, - }, - { - "valid misbehaviour with trusted heights at a previous revision", - types.NewClientState(chainIDRevision1, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, clienttypes.NewHeight(1, 1), commitmenttypes.GetSDKSpecs(), upgradePath, false, false), - types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash), - heightMinus1, - types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), suite.valsHash), - heightMinus3, - &types.Misbehaviour{ - Header1: suite.chainA.CreateTMClientHeader(chainIDRevision1, 1, heightMinus1, suite.now, bothValSet, bothValSet, bothSigners), - Header2: suite.chainA.CreateTMClientHeader(chainIDRevision1, 1, heightMinus3, suite.now.Add(time.Minute), bothValSet, suite.valSet, bothSigners), - ClientId: chainID, - }, - suite.now, - true, - }, - { - "consensus state's valset hash different from misbehaviour should still pass", - types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false), - types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), suite.valsHash), - height, - types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), suite.valsHash), - height, - &types.Misbehaviour{ - Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), height, suite.now, bothValSet, suite.valSet, bothSigners), - Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), height, suite.now.Add(time.Minute), bothValSet, suite.valSet, bothSigners), - ClientId: chainID, - }, - suite.now, - true, - }, - { - "invalid misbehavior misbehaviour from different chain", - types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false), - types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash), - height, - types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash), - height, - &types.Misbehaviour{ - Header1: suite.chainA.CreateTMClientHeader("ethermint", int64(height.RevisionHeight), height, suite.now, bothValSet, bothValSet, bothSigners), - Header2: suite.chainA.CreateTMClientHeader("ethermint", int64(height.RevisionHeight), height, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners), - ClientId: chainID, - }, - suite.now, - false, - }, - { - "invalid misbehavior misbehaviour with trusted height different from trusted consensus state", - types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false), - types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash), - heightMinus1, - types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), suite.valsHash), - heightMinus3, - &types.Misbehaviour{ - Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), heightMinus1, suite.now, bothValSet, bothValSet, bothSigners), - Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), height, suite.now.Add(time.Minute), bothValSet, suite.valSet, bothSigners), - ClientId: chainID, - }, - suite.now, - false, - }, - { - "invalid misbehavior misbehaviour with trusted validators different from trusted consensus state", - types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false), - types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash), - heightMinus1, - types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), suite.valsHash), - heightMinus3, - &types.Misbehaviour{ - Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), heightMinus1, suite.now, bothValSet, bothValSet, bothSigners), - Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), heightMinus3, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners), - ClientId: chainID, - }, - suite.now, - false, - }, - { - "already frozen client state", - &types.ClientState{FrozenHeight: clienttypes.NewHeight(0, 1)}, - types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash), - height, - types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash), - height, - &types.Misbehaviour{ - Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), height, suite.now, bothValSet, bothValSet, bothSigners), - Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), height, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners), - ClientId: chainID, - }, - suite.now, - false, - }, - { - "trusted consensus state does not exist", - types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false), - nil, // consensus state for trusted height - 1 does not exist in store - clienttypes.Height{}, - types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash), - height, - &types.Misbehaviour{ - Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), heightMinus1, suite.now, bothValSet, bothValSet, bothSigners), - Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), height, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners), - ClientId: chainID, - }, - suite.now, - false, - }, - { - "invalid tendermint misbehaviour", - types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false), - types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash), - height, - types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash), - height, - nil, - suite.now, - false, - }, - { - "provided height > header height", - types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false), - types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash), - height, - types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash), - height, - &types.Misbehaviour{ - Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), heightMinus1, suite.now, bothValSet, bothValSet, bothSigners), - Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), heightMinus1, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners), - ClientId: chainID, - }, - suite.now, - false, - }, - { - "trusting period expired", - types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false), - types.NewConsensusState(time.Time{}, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash), - heightMinus1, - types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash), - height, - &types.Misbehaviour{ - Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), heightMinus1, suite.now, bothValSet, bothValSet, bothSigners), - Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), height, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners), - ClientId: chainID, - }, - suite.now.Add(trustingPeriod), - false, - }, - { - "trusted validators is incorrect for given consensus state", - types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false), - types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash), - height, - types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash), - height, - &types.Misbehaviour{ - Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), height, suite.now, bothValSet, suite.valSet, bothSigners), - Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), height, suite.now.Add(time.Minute), bothValSet, suite.valSet, bothSigners), - ClientId: chainID, - }, - suite.now, - false, - }, - { - "first valset has too much change", - types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false), - types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash), - height, - types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash), - height, - &types.Misbehaviour{ - Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), height, suite.now, altValSet, bothValSet, altSigners), - Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), height, suite.now.Add(time.Minute), bothValSet, bothValSet, bothSigners), - ClientId: chainID, - }, - suite.now, - false, - }, - { - "second valset has too much change", - types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false), - types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash), - height, - types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash), - height, - &types.Misbehaviour{ - Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), height, suite.now, bothValSet, bothValSet, bothSigners), - Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), height, suite.now.Add(time.Minute), altValSet, bothValSet, altSigners), - ClientId: chainID, - }, - suite.now, - false, - }, - { - "both valsets have too much change", - types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false), - types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash), - height, - types.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot(tmhash.Sum([]byte("app_hash"))), bothValsHash), - height, - &types.Misbehaviour{ - Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), height, suite.now, altValSet, bothValSet, altSigners), - Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), height, suite.now.Add(time.Minute), altValSet, bothValSet, altSigners), - ClientId: chainID, - }, - suite.now, - false, - }, - } - - for i, tc := range testCases { - tc := tc - suite.Run(fmt.Sprintf("Case: %s", tc.name), func() { - // reset suite to create fresh application state - suite.SetupTest() - - // Set current timestamp in context - ctx := suite.chainA.GetContext().WithBlockTime(tc.timestamp) - - // Set trusted consensus states in client store - - if tc.consensusState1 != nil { - suite.chainA.App.IBCKeeper.ClientKeeper.SetClientConsensusState(ctx, clientID, tc.height1, tc.consensusState1) - } - if tc.consensusState2 != nil { - suite.chainA.App.IBCKeeper.ClientKeeper.SetClientConsensusState(ctx, clientID, tc.height2, tc.consensusState2) - } - - clientState, err := tc.clientState.CheckMisbehaviourAndUpdateState( - ctx, - suite.cdc, - suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(ctx, clientID), // pass in clientID prefixed clientStore - tc.misbehaviour, - ) - - if tc.expPass { - suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name) - suite.Require().NotNil(clientState, "valid test case %d failed: %s", i, tc.name) - suite.Require().True(clientState.IsFrozen(), "valid test case %d failed: %s", i, tc.name) - suite.Require().Equal(tc.misbehaviour.GetHeight(), clientState.GetFrozenHeight(), - "valid test case %d failed: %s. Expected FrozenHeight %s got %s", tc.misbehaviour.GetHeight(), clientState.GetFrozenHeight()) - } else { - suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name) - suite.Require().Nil(clientState, "invalid test case %d passed: %s", i, tc.name) - } - }) - } -} diff --git a/x/ibc/light-clients/07-tendermint/types/misbehaviour_test.go b/x/ibc/light-clients/07-tendermint/types/misbehaviour_test.go deleted file mode 100644 index dede4e6021a4..000000000000 --- a/x/ibc/light-clients/07-tendermint/types/misbehaviour_test.go +++ /dev/null @@ -1,244 +0,0 @@ -package types_test - -import ( - "time" - - "github.com/tendermint/tendermint/crypto/tmhash" - tmproto "github.com/tendermint/tendermint/proto/tendermint/types" - tmtypes "github.com/tendermint/tendermint/types" - - 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" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" - ibctestingmock "github.com/cosmos/cosmos-sdk/x/ibc/testing/mock" -) - -func (suite *TendermintTestSuite) TestMisbehaviour() { - signers := []tmtypes.PrivValidator{suite.privVal} - heightMinus1 := clienttypes.NewHeight(0, height.RevisionHeight-1) - - misbehaviour := &types.Misbehaviour{ - Header1: suite.header, - Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), heightMinus1, suite.now, suite.valSet, suite.valSet, signers), - ClientId: clientID, - } - - suite.Require().Equal(exported.Tendermint, misbehaviour.ClientType()) - suite.Require().Equal(clientID, misbehaviour.GetClientID()) - suite.Require().Equal(height, misbehaviour.GetHeight()) -} - -func (suite *TendermintTestSuite) TestMisbehaviourValidateBasic() { - altPrivVal := ibctestingmock.NewPV() - altPubKey, err := altPrivVal.GetPubKey() - suite.Require().NoError(err) - - revisionHeight := int64(height.RevisionHeight) - - altVal := tmtypes.NewValidator(altPubKey, revisionHeight) - - // Create bothValSet with both suite validator and altVal - bothValSet := tmtypes.NewValidatorSet(append(suite.valSet.Validators, altVal)) - // Create alternative validator set with only altVal - altValSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{altVal}) - - signers := []tmtypes.PrivValidator{suite.privVal} - - // Create signer array and ensure it is in same order as bothValSet - _, suiteVal := suite.valSet.GetByIndex(0) - bothSigners := ibctesting.CreateSortedSignerArray(altPrivVal, suite.privVal, altVal, suiteVal) - - altSigners := []tmtypes.PrivValidator{altPrivVal} - - heightMinus1 := clienttypes.NewHeight(0, height.RevisionHeight-1) - - testCases := []struct { - name string - misbehaviour *types.Misbehaviour - malleateMisbehaviour func(misbehaviour *types.Misbehaviour) error - expPass bool - }{ - { - "valid misbehaviour", - &types.Misbehaviour{ - Header1: suite.header, - Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), heightMinus1, suite.now.Add(time.Minute), suite.valSet, suite.valSet, signers), - ClientId: clientID, - }, - func(misbehaviour *types.Misbehaviour) error { return nil }, - true, - }, - { - "misbehaviour Header1 is nil", - types.NewMisbehaviour(clientID, nil, suite.header), - func(m *types.Misbehaviour) error { return nil }, - false, - }, - { - "misbehaviour Header2 is nil", - types.NewMisbehaviour(clientID, suite.header, nil), - func(m *types.Misbehaviour) error { return nil }, - false, - }, - { - "valid misbehaviour with different trusted headers", - &types.Misbehaviour{ - Header1: suite.header, - Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), clienttypes.NewHeight(0, height.RevisionHeight-3), suite.now.Add(time.Minute), suite.valSet, bothValSet, signers), - ClientId: clientID, - }, - func(misbehaviour *types.Misbehaviour) error { return nil }, - true, - }, - { - "trusted height is 0 in Header1", - &types.Misbehaviour{ - Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), clienttypes.ZeroHeight(), suite.now.Add(time.Minute), suite.valSet, suite.valSet, signers), - Header2: suite.header, - ClientId: clientID, - }, - func(misbehaviour *types.Misbehaviour) error { return nil }, - false, - }, - { - "trusted height is 0 in Header2", - &types.Misbehaviour{ - Header1: suite.header, - Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), clienttypes.ZeroHeight(), suite.now.Add(time.Minute), suite.valSet, suite.valSet, signers), - ClientId: clientID, - }, - func(misbehaviour *types.Misbehaviour) error { return nil }, - false, - }, - { - "trusted valset is nil in Header1", - &types.Misbehaviour{ - Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), heightMinus1, suite.now.Add(time.Minute), suite.valSet, nil, signers), - Header2: suite.header, - ClientId: clientID, - }, - func(misbehaviour *types.Misbehaviour) error { return nil }, - false, - }, - { - "trusted valset is nil in Header2", - &types.Misbehaviour{ - Header1: suite.header, - Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), heightMinus1, suite.now.Add(time.Minute), suite.valSet, nil, signers), - ClientId: clientID, - }, - func(misbehaviour *types.Misbehaviour) error { return nil }, - false, - }, - { - "invalid client ID ", - &types.Misbehaviour{ - Header1: suite.header, - Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), heightMinus1, suite.now, suite.valSet, suite.valSet, signers), - ClientId: "GAIA", - }, - func(misbehaviour *types.Misbehaviour) error { return nil }, - false, - }, - { - "chainIDs do not match", - &types.Misbehaviour{ - Header1: suite.header, - Header2: suite.chainA.CreateTMClientHeader("ethermint", int64(height.RevisionHeight), heightMinus1, suite.now, suite.valSet, suite.valSet, signers), - ClientId: clientID, - }, - func(misbehaviour *types.Misbehaviour) error { return nil }, - false, - }, - { - "mismatched heights", - &types.Misbehaviour{ - Header1: suite.header, - Header2: suite.chainA.CreateTMClientHeader(chainID, 6, clienttypes.NewHeight(0, 4), suite.now, suite.valSet, suite.valSet, signers), - ClientId: clientID, - }, - func(misbehaviour *types.Misbehaviour) error { return nil }, - false, - }, - { - "same block id", - &types.Misbehaviour{ - Header1: suite.header, - Header2: suite.header, - ClientId: clientID, - }, - func(misbehaviour *types.Misbehaviour) error { return nil }, - false, - }, - { - "header 1 doesn't have 2/3 majority", - &types.Misbehaviour{ - Header1: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), heightMinus1, suite.now, bothValSet, suite.valSet, bothSigners), - Header2: suite.header, - ClientId: clientID, - }, - func(misbehaviour *types.Misbehaviour) error { - // voteSet contains only altVal which is less than 2/3 of total power (height/1height) - wrongVoteSet := tmtypes.NewVoteSet(chainID, int64(misbehaviour.Header1.GetHeight().GetRevisionHeight()), 1, tmproto.PrecommitType, altValSet) - blockID, err := tmtypes.BlockIDFromProto(&misbehaviour.Header1.Commit.BlockID) - if err != nil { - return err - } - - tmCommit, err := tmtypes.MakeCommit(*blockID, int64(misbehaviour.Header2.GetHeight().GetRevisionHeight()), misbehaviour.Header1.Commit.Round, wrongVoteSet, altSigners, suite.now) - misbehaviour.Header1.Commit = tmCommit.ToProto() - return err - }, - false, - }, - { - "header 2 doesn't have 2/3 majority", - &types.Misbehaviour{ - Header1: suite.header, - Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), heightMinus1, suite.now, bothValSet, suite.valSet, bothSigners), - ClientId: clientID, - }, - func(misbehaviour *types.Misbehaviour) error { - // voteSet contains only altVal which is less than 2/3 of total power (height/1height) - wrongVoteSet := tmtypes.NewVoteSet(chainID, int64(misbehaviour.Header2.GetHeight().GetRevisionHeight()), 1, tmproto.PrecommitType, altValSet) - blockID, err := tmtypes.BlockIDFromProto(&misbehaviour.Header2.Commit.BlockID) - if err != nil { - return err - } - - tmCommit, err := tmtypes.MakeCommit(*blockID, int64(misbehaviour.Header2.GetHeight().GetRevisionHeight()), misbehaviour.Header2.Commit.Round, wrongVoteSet, altSigners, suite.now) - misbehaviour.Header2.Commit = tmCommit.ToProto() - return err - }, - false, - }, - { - "validators sign off on wrong commit", - &types.Misbehaviour{ - Header1: suite.header, - Header2: suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), heightMinus1, suite.now, bothValSet, suite.valSet, bothSigners), - ClientId: clientID, - }, - func(misbehaviour *types.Misbehaviour) error { - tmBlockID := ibctesting.MakeBlockID(tmhash.Sum([]byte("other_hash")), 3, tmhash.Sum([]byte("other_partset"))) - misbehaviour.Header2.Commit.BlockID = tmBlockID.ToProto() - return nil - }, - false, - }, - } - - for i, tc := range testCases { - tc := tc - - err := tc.malleateMisbehaviour(tc.misbehaviour) - suite.Require().NoError(err) - - if tc.expPass { - suite.Require().NoError(tc.misbehaviour.ValidateBasic(), "valid test case %d failed: %s", i, tc.name) - } else { - suite.Require().Error(tc.misbehaviour.ValidateBasic(), "invalid test case %d passed: %s", i, tc.name) - } - } -} diff --git a/x/ibc/light-clients/07-tendermint/types/proposal_handle.go b/x/ibc/light-clients/07-tendermint/types/proposal_handle.go deleted file mode 100644 index c64c52b3f810..000000000000 --- a/x/ibc/light-clients/07-tendermint/types/proposal_handle.go +++ /dev/null @@ -1,134 +0,0 @@ -package types - -import ( - "reflect" - - "github.com/cosmos/cosmos-sdk/codec" - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -// 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, 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(subjectClientStore, cdc, cs.GetLatestHeight()) - if err != nil { - return nil, sdkerrors.Wrapf( - err, "unexpected error: could not get consensus state from clientstore at height: %d", cs.GetLatestHeight(), - ) - } - - switch { - - case cs.IsFrozen(): - if !cs.AllowUpdateAfterMisbehaviour { - return nil, sdkerrors.Wrap(clienttypes.ErrUpdateClientFailed, "client is not allowed to be unfrozen") - } - - // unfreeze the client - cs.FrozenHeight = clienttypes.ZeroHeight() - - case cs.IsExpired(consensusState.Timestamp, ctx.BlockTime()): - if !cs.AllowUpdateAfterExpiry { - return nil, sdkerrors.Wrap(clienttypes.ErrUpdateClientFailed, "client is not allowed to be unexpired") - } - - default: - return nil, sdkerrors.Wrap(clienttypes.ErrUpdateClientFailed, "client cannot be updated with proposal") - } - - // 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) - - consensusState, err := GetConsensusState(substituteClientStore, cdc, height) - if err != nil { - // not all consensus states will be filled in - continue - } - SetConsensusState(subjectClientStore, cdc, consensusState, height) - - processedTime, found := GetProcessedTime(substituteClientStore, height) - if !found { - continue - } - SetProcessedTime(subjectClientStore, height, processedTime) - - } - - 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") - } - - 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 cs.IsExpired(latestConsensusState.Timestamp, ctx.BlockTime()) { - return nil, sdkerrors.Wrap(clienttypes.ErrInvalidClient, "updated subject client is expired") - } - - return &cs, 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 deleted file mode 100644 index 66a5120309c0..000000000000 --- a/x/ibc/light-clients/07-tendermint/types/proposal_handle_test.go +++ /dev/null @@ -1,387 +0,0 @@ -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" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" -) - -var ( - frozenHeight = clienttypes.NewHeight(0, 1) -) - -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) TestCheckSubstituteAndUpdateState() { - testCases := []struct { - name string - AllowUpdateAfterExpiry bool - AllowUpdateAfterMisbehaviour bool - FreezeClient bool - ExpireClient bool - expPass bool - }{ - { - name: "not allowed to be updated, not frozen or expired", - AllowUpdateAfterExpiry: false, - AllowUpdateAfterMisbehaviour: false, - FreezeClient: false, - ExpireClient: false, - expPass: false, - }, - { - name: "not allowed to be updated, client is frozen", - AllowUpdateAfterExpiry: false, - AllowUpdateAfterMisbehaviour: false, - FreezeClient: true, - ExpireClient: false, - expPass: false, - }, - { - name: "not allowed to be updated, client is expired", - AllowUpdateAfterExpiry: false, - AllowUpdateAfterMisbehaviour: false, - FreezeClient: false, - ExpireClient: true, - expPass: false, - }, - { - name: "not allowed to be updated, client is frozen and expired", - AllowUpdateAfterExpiry: false, - AllowUpdateAfterMisbehaviour: false, - FreezeClient: true, - ExpireClient: true, - expPass: false, - }, - { - name: "allowed to be updated only after misbehaviour, not frozen or expired", - AllowUpdateAfterExpiry: false, - AllowUpdateAfterMisbehaviour: true, - FreezeClient: false, - ExpireClient: false, - expPass: false, - }, - { - name: "allowed to be updated only after misbehaviour, client is expired", - AllowUpdateAfterExpiry: false, - AllowUpdateAfterMisbehaviour: true, - FreezeClient: false, - ExpireClient: true, - expPass: false, - }, - { - name: "allowed to be updated only after expiry, not frozen or expired", - AllowUpdateAfterExpiry: true, - AllowUpdateAfterMisbehaviour: false, - FreezeClient: false, - ExpireClient: false, - expPass: false, - }, - { - name: "allowed to be updated only after expiry, client is frozen", - AllowUpdateAfterExpiry: true, - AllowUpdateAfterMisbehaviour: false, - FreezeClient: true, - ExpireClient: 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", - AllowUpdateAfterExpiry: true, - AllowUpdateAfterMisbehaviour: false, - FreezeClient: false, - ExpireClient: true, - expPass: true, - }, - { - name: "allowed to be updated only after expiry, client is frozen and expired", - AllowUpdateAfterExpiry: true, - AllowUpdateAfterMisbehaviour: false, - FreezeClient: true, - ExpireClient: true, - expPass: false, - }, - { - name: "allowed to be updated after expiry and misbehaviour, not frozen or expired", - AllowUpdateAfterExpiry: true, - AllowUpdateAfterMisbehaviour: true, - FreezeClient: false, - ExpireClient: false, - expPass: false, - }, - { - name: "PASS: allowed to be updated after expiry and misbehaviour, client is frozen", - AllowUpdateAfterExpiry: true, - AllowUpdateAfterMisbehaviour: true, - FreezeClient: true, - ExpireClient: false, - expPass: true, - }, - { - name: "PASS: allowed to be updated after expiry and misbehaviour, client is expired", - AllowUpdateAfterExpiry: true, - AllowUpdateAfterMisbehaviour: true, - FreezeClient: false, - ExpireClient: true, - expPass: true, - }, - { - name: "PASS: allowed to be updated after expiry and misbehaviour, client is frozen and expired", - AllowUpdateAfterExpiry: true, - AllowUpdateAfterMisbehaviour: true, - FreezeClient: true, - ExpireClient: true, - expPass: true, - }, - } - - for _, tc := range testCases { - tc := tc - - // for each test case a header used for unexpiring clients and unfreezing - // a client are each tested to ensure that unexpiry headers cannot update - // a client when a unfreezing header is required. - suite.Run(tc.name, func() { - - // start by testing unexpiring the client - suite.SetupTest() // reset - - // 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 { - subjectClientState.FrozenHeight = frozenHeight - } - if tc.ExpireClient { - suite.chainA.ExpireClient(subjectClientState.TrustingPeriod) - suite.chainB.ExpireClient(subjectClientState.TrustingPeriod) - suite.coordinator.CommitBlock(suite.chainA, suite.chainB) - } - - // 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 - - 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) - - 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) - // skip a block - suite.coordinator.CommitBlock(suite.chainA, suite.chainB) - } - - // get updated substitute - substituteClientState = suite.chainA.GetClientState(substitute).(*types.ClientState) - - 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.expPass { - suite.Require().NoError(err) - suite.Require().Equal(clienttypes.ZeroHeight(), updatedClient.GetFrozenHeight()) - } else { - suite.Require().Error(err) - suite.Require().Nil(updatedClient) - } - - }) - } -} - -func (suite *TendermintTestSuite) TestIsMatchingClientState() { - var ( - subject, substitute string - subjectClientState, substituteClientState *types.ClientState - ) - - testCases := []struct { - name string - malleate func() - expPass bool - }{ - { - "matching clients", func() { - subjectClientState = suite.chainA.GetClientState(subject).(*types.ClientState) - substituteClientState = suite.chainA.GetClientState(substitute).(*types.ClientState) - }, true, - }, - { - "matching, frozen height is not used in check for equality", func() { - subjectClientState.FrozenHeight = frozenHeight - substituteClientState.FrozenHeight = clienttypes.ZeroHeight() - }, true, - }, - { - "matching, latest height is not used in check for equality", func() { - subjectClientState.LatestHeight = clienttypes.NewHeight(0, 10) - substituteClientState.FrozenHeight = clienttypes.ZeroHeight() - }, true, - }, - { - "matching, chain id is different", func() { - subjectClientState.ChainId = "bitcoin" - substituteClientState.ChainId = "ethereum" - }, true, - }, - { - "not matching, trusting period is different", func() { - subjectClientState.TrustingPeriod = time.Duration(time.Hour * 10) - substituteClientState.TrustingPeriod = time.Duration(time.Hour * 1) - }, false, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - suite.SetupTest() // reset - - subject, _ = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - substitute, _ = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - - tc.malleate() - - suite.Require().Equal(tc.expPass, types.IsMatchingClientState(*subjectClientState, *substituteClientState)) - - }) - } -} diff --git a/x/ibc/light-clients/07-tendermint/types/store.go b/x/ibc/light-clients/07-tendermint/types/store.go deleted file mode 100644 index 7d6a841b89f1..000000000000 --- a/x/ibc/light-clients/07-tendermint/types/store.go +++ /dev/null @@ -1,96 +0,0 @@ -package types - -import ( - "strings" - - "github.com/cosmos/cosmos-sdk/codec" - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -// 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) { - bz := store.Get(host.ConsensusStateKey(height)) - if bz == nil { - return nil, sdkerrors.Wrapf( - clienttypes.ErrConsensusStateNotFound, - "consensus state does not exist for height %s", height, - ) - } - - consensusStateI, err := clienttypes.UnmarshalConsensusState(cdc, bz) - if err != nil { - return nil, sdkerrors.Wrapf(clienttypes.ErrInvalidConsensus, "unmarshal error: %v", err) - } - - consensusState, ok := consensusStateI.(*ConsensusState) - if !ok { - return nil, sdkerrors.Wrapf( - clienttypes.ErrInvalidConsensus, - "invalid consensus type %T, expected %T", consensusState, &ConsensusState{}, - ) - } - - return consensusState, nil -} - -// IterateProcessedTime iterates through the prefix store and applies the callback. -// If the cb returns true, then iterator will close and stop. -func IterateProcessedTime(store sdk.KVStore, cb func(key, val []byte) bool) { - iterator := sdk.KVStorePrefixIterator(store, []byte(host.KeyConsensusStatePrefix)) - - defer iterator.Close() - for ; iterator.Valid(); iterator.Next() { - keySplit := strings.Split(string(iterator.Key()), "/") - // processed time key in prefix store has format: "consensusState//processedTime" - if len(keySplit) != 3 || keySplit[2] != "processedTime" { - // ignore all consensus state keys - continue - } - - if cb(iterator.Key(), iterator.Value()) { - break - } - } -} - -// ProcessedTime Store code - -// ProcessedTimeKey returns the key under which the processed time will be stored in the client store. -func ProcessedTimeKey(height exported.Height) []byte { - return append(host.ConsensusStateKey(height), KeyProcessedTime...) -} - -// SetProcessedTime stores the time at which a header was processed and the corresponding consensus state was created. -// This is useful when validating whether a packet has reached the specified delay period in the tendermint client's -// verification functions -func SetProcessedTime(clientStore sdk.KVStore, height exported.Height, timeNs uint64) { - key := ProcessedTimeKey(height) - val := sdk.Uint64ToBigEndian(timeNs) - clientStore.Set(key, val) -} - -// GetProcessedTime gets the time (in nanoseconds) at which this chain received and processed a tendermint header. -// This is used to validate that a received packet has passed the delay period. -func GetProcessedTime(clientStore sdk.KVStore, height exported.Height) (uint64, bool) { - key := ProcessedTimeKey(height) - bz := clientStore.Get(key) - if bz == nil { - return 0, false - } - return sdk.BigEndianToUint64(bz), true -} diff --git a/x/ibc/light-clients/07-tendermint/types/store_test.go b/x/ibc/light-clients/07-tendermint/types/store_test.go deleted file mode 100644 index b8badc09479a..000000000000 --- a/x/ibc/light-clients/07-tendermint/types/store_test.go +++ /dev/null @@ -1,113 +0,0 @@ -package types_test - -import ( - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - solomachinetypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/06-solomachine/types" - "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" -) - -func (suite *TendermintTestSuite) TestGetConsensusState() { - var ( - height exported.Height - clientA string - ) - - testCases := []struct { - name string - malleate func() - expPass bool - }{ - { - "success", func() {}, true, - }, - { - "consensus state not found", func() { - // use height with no consensus state set - height = height.(clienttypes.Height).Increment() - }, false, - }, - { - "not a consensus state interface", func() { - // marshal an empty client state and set as consensus state - store := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), clientA) - clientStateBz := suite.chainA.App.IBCKeeper.ClientKeeper.MustMarshalClientState(&types.ClientState{}) - store.Set(host.ConsensusStateKey(height), clientStateBz) - }, false, - }, - { - "invalid consensus state (solomachine)", func() { - // marshal and set solomachine consensus state - store := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), clientA) - consensusStateBz := suite.chainA.App.IBCKeeper.ClientKeeper.MustMarshalConsensusState(&solomachinetypes.ConsensusState{}) - store.Set(host.ConsensusStateKey(height), consensusStateBz) - }, false, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - suite.SetupTest() - - clientA, _, _, _, _, _ = suite.coordinator.Setup(suite.chainA, suite.chainB, channeltypes.UNORDERED) - clientState := suite.chainA.GetClientState(clientA) - height = clientState.GetLatestHeight() - - tc.malleate() // change vars as necessary - - store := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), clientA) - consensusState, err := types.GetConsensusState(store, suite.chainA.Codec, height) - - if tc.expPass { - suite.Require().NoError(err) - expConsensusState, found := suite.chainA.GetConsensusState(clientA, height) - suite.Require().True(found) - suite.Require().Equal(expConsensusState, consensusState) - } else { - suite.Require().Error(err) - suite.Require().Nil(consensusState) - } - }) - } -} - -func (suite *TendermintTestSuite) TestGetProcessedTime() { - // Verify ProcessedTime on CreateClient - // coordinator increments time before creating client - expectedTime := suite.chainA.CurrentHeader.Time.Add(ibctesting.TimeIncrement) - - clientA, err := suite.coordinator.CreateClient(suite.chainA, suite.chainB, exported.Tendermint) - suite.Require().NoError(err) - - clientState := suite.chainA.GetClientState(clientA) - height := clientState.GetLatestHeight() - - store := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), clientA) - actualTime, ok := types.GetProcessedTime(store, height) - suite.Require().True(ok, "could not retrieve processed time for stored consensus state") - suite.Require().Equal(uint64(expectedTime.UnixNano()), actualTime, "retrieved processed time is not expected value") - - // Verify ProcessedTime on UpdateClient - // coordinator increments time before updating client - expectedTime = suite.chainA.CurrentHeader.Time.Add(ibctesting.TimeIncrement) - - err = suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - suite.Require().NoError(err) - - clientState = suite.chainA.GetClientState(clientA) - height = clientState.GetLatestHeight() - - store = suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), clientA) - actualTime, ok = types.GetProcessedTime(store, height) - suite.Require().True(ok, "could not retrieve processed time for stored consensus state") - suite.Require().Equal(uint64(expectedTime.UnixNano()), actualTime, "retrieved processed time is not expected value") - - // try to get processed time for height that doesn't exist in store - _, ok = types.GetProcessedTime(store, clienttypes.NewHeight(1, 1)) - suite.Require().False(ok, "retrieved processed time for a non-existent consensus state") -} diff --git a/x/ibc/light-clients/07-tendermint/types/tendermint.pb.go b/x/ibc/light-clients/07-tendermint/types/tendermint.pb.go deleted file mode 100644 index 510a643c256b..000000000000 --- a/x/ibc/light-clients/07-tendermint/types/tendermint.pb.go +++ /dev/null @@ -1,1914 +0,0 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: ibc/lightclients/tendermint/v1/tendermint.proto - -package types - -import ( - fmt "fmt" - _go "github.com/confio/ics23/go" - types "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - types1 "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/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_tendermint_tendermint_libs_bytes "github.com/tendermint/tendermint/libs/bytes" - types2 "github.com/tendermint/tendermint/proto/tendermint/types" - 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 - -// ClientState from Tendermint tracks the current validator set, latest height, -// and a possible frozen height. -type ClientState struct { - ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` - TrustLevel Fraction `protobuf:"bytes,2,opt,name=trust_level,json=trustLevel,proto3" json:"trust_level" yaml:"trust_level"` - // duration of the period since the LastestTimestamp during which the - // submitted headers are valid for upgrade - TrustingPeriod time.Duration `protobuf:"bytes,3,opt,name=trusting_period,json=trustingPeriod,proto3,stdduration" json:"trusting_period" yaml:"trusting_period"` - // duration of the staking unbonding period - UnbondingPeriod time.Duration `protobuf:"bytes,4,opt,name=unbonding_period,json=unbondingPeriod,proto3,stdduration" json:"unbonding_period" yaml:"unbonding_period"` - // defines how much new (untrusted) header's Time can drift into the future. - MaxClockDrift time.Duration `protobuf:"bytes,5,opt,name=max_clock_drift,json=maxClockDrift,proto3,stdduration" json:"max_clock_drift" yaml:"max_clock_drift"` - // Block height when the client was frozen due to a misbehaviour - FrozenHeight types.Height `protobuf:"bytes,6,opt,name=frozen_height,json=frozenHeight,proto3" json:"frozen_height" yaml:"frozen_height"` - // Latest height the client was updated to - LatestHeight types.Height `protobuf:"bytes,7,opt,name=latest_height,json=latestHeight,proto3" json:"latest_height" yaml:"latest_height"` - // Proof specifications used in verifying counterparty state - ProofSpecs []*_go.ProofSpec `protobuf:"bytes,8,rep,name=proof_specs,json=proofSpecs,proto3" json:"proof_specs,omitempty" yaml:"proof_specs"` - // 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"}` - UpgradePath []string `protobuf:"bytes,9,rep,name=upgrade_path,json=upgradePath,proto3" json:"upgrade_path,omitempty" yaml:"upgrade_path"` - // This flag, when set to true, will allow governance to recover a client - // which has expired - AllowUpdateAfterExpiry bool `protobuf:"varint,10,opt,name=allow_update_after_expiry,json=allowUpdateAfterExpiry,proto3" json:"allow_update_after_expiry,omitempty" yaml:"allow_update_after_expiry"` - // This flag, when set to true, will allow governance to unfreeze a client - // whose chain has experienced a misbehaviour event - AllowUpdateAfterMisbehaviour bool `protobuf:"varint,11,opt,name=allow_update_after_misbehaviour,json=allowUpdateAfterMisbehaviour,proto3" json:"allow_update_after_misbehaviour,omitempty" yaml:"allow_update_after_misbehaviour"` -} - -func (m *ClientState) Reset() { *m = ClientState{} } -func (m *ClientState) String() string { return proto.CompactTextString(m) } -func (*ClientState) ProtoMessage() {} -func (*ClientState) Descriptor() ([]byte, []int) { - return fileDescriptor_c6d6cf2b288949be, []int{0} -} -func (m *ClientState) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *ClientState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_ClientState.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 *ClientState) XXX_Merge(src proto.Message) { - xxx_messageInfo_ClientState.Merge(m, src) -} -func (m *ClientState) XXX_Size() int { - return m.Size() -} -func (m *ClientState) XXX_DiscardUnknown() { - xxx_messageInfo_ClientState.DiscardUnknown(m) -} - -var xxx_messageInfo_ClientState proto.InternalMessageInfo - -// ConsensusState defines the consensus state from Tendermint. -type ConsensusState struct { - // timestamp that corresponds to the block height in which the ConsensusState - // was stored. - Timestamp time.Time `protobuf:"bytes,1,opt,name=timestamp,proto3,stdtime" json:"timestamp"` - // commitment root (i.e app hash) - Root types1.MerkleRoot `protobuf:"bytes,2,opt,name=root,proto3" json:"root"` - NextValidatorsHash github_com_tendermint_tendermint_libs_bytes.HexBytes `protobuf:"bytes,3,opt,name=next_validators_hash,json=nextValidatorsHash,proto3,casttype=github.com/tendermint/tendermint/libs/bytes.HexBytes" json:"next_validators_hash,omitempty" yaml:"next_validators_hash"` -} - -func (m *ConsensusState) Reset() { *m = ConsensusState{} } -func (m *ConsensusState) String() string { return proto.CompactTextString(m) } -func (*ConsensusState) ProtoMessage() {} -func (*ConsensusState) Descriptor() ([]byte, []int) { - return fileDescriptor_c6d6cf2b288949be, []int{1} -} -func (m *ConsensusState) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *ConsensusState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_ConsensusState.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 *ConsensusState) XXX_Merge(src proto.Message) { - xxx_messageInfo_ConsensusState.Merge(m, src) -} -func (m *ConsensusState) XXX_Size() int { - return m.Size() -} -func (m *ConsensusState) XXX_DiscardUnknown() { - xxx_messageInfo_ConsensusState.DiscardUnknown(m) -} - -var xxx_messageInfo_ConsensusState proto.InternalMessageInfo - -// Misbehaviour is a wrapper over two conflicting Headers -// that implements Misbehaviour interface expected by ICS-02 -type Misbehaviour struct { - ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty" yaml:"client_id"` - Header1 *Header `protobuf:"bytes,2,opt,name=header_1,json=header1,proto3" json:"header_1,omitempty" yaml:"header_1"` - Header2 *Header `protobuf:"bytes,3,opt,name=header_2,json=header2,proto3" json:"header_2,omitempty" yaml:"header_2"` -} - -func (m *Misbehaviour) Reset() { *m = Misbehaviour{} } -func (m *Misbehaviour) String() string { return proto.CompactTextString(m) } -func (*Misbehaviour) ProtoMessage() {} -func (*Misbehaviour) Descriptor() ([]byte, []int) { - return fileDescriptor_c6d6cf2b288949be, []int{2} -} -func (m *Misbehaviour) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *Misbehaviour) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_Misbehaviour.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 *Misbehaviour) XXX_Merge(src proto.Message) { - xxx_messageInfo_Misbehaviour.Merge(m, src) -} -func (m *Misbehaviour) XXX_Size() int { - return m.Size() -} -func (m *Misbehaviour) XXX_DiscardUnknown() { - xxx_messageInfo_Misbehaviour.DiscardUnknown(m) -} - -var xxx_messageInfo_Misbehaviour proto.InternalMessageInfo - -// 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. -type Header struct { - *types2.SignedHeader `protobuf:"bytes,1,opt,name=signed_header,json=signedHeader,proto3,embedded=signed_header" json:"signed_header,omitempty" yaml:"signed_header"` - ValidatorSet *types2.ValidatorSet `protobuf:"bytes,2,opt,name=validator_set,json=validatorSet,proto3" json:"validator_set,omitempty" yaml:"validator_set"` - TrustedHeight types.Height `protobuf:"bytes,3,opt,name=trusted_height,json=trustedHeight,proto3" json:"trusted_height" yaml:"trusted_height"` - TrustedValidators *types2.ValidatorSet `protobuf:"bytes,4,opt,name=trusted_validators,json=trustedValidators,proto3" json:"trusted_validators,omitempty" yaml:"trusted_validators"` -} - -func (m *Header) Reset() { *m = Header{} } -func (m *Header) String() string { return proto.CompactTextString(m) } -func (*Header) ProtoMessage() {} -func (*Header) Descriptor() ([]byte, []int) { - return fileDescriptor_c6d6cf2b288949be, []int{3} -} -func (m *Header) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *Header) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_Header.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 *Header) XXX_Merge(src proto.Message) { - xxx_messageInfo_Header.Merge(m, src) -} -func (m *Header) XXX_Size() int { - return m.Size() -} -func (m *Header) XXX_DiscardUnknown() { - xxx_messageInfo_Header.DiscardUnknown(m) -} - -var xxx_messageInfo_Header proto.InternalMessageInfo - -func (m *Header) GetValidatorSet() *types2.ValidatorSet { - if m != nil { - return m.ValidatorSet - } - return nil -} - -func (m *Header) GetTrustedHeight() types.Height { - if m != nil { - return m.TrustedHeight - } - return types.Height{} -} - -func (m *Header) GetTrustedValidators() *types2.ValidatorSet { - if m != nil { - return m.TrustedValidators - } - return nil -} - -// Fraction defines the protobuf message type for tmmath.Fraction that only supports positive values. -type Fraction struct { - Numerator uint64 `protobuf:"varint,1,opt,name=numerator,proto3" json:"numerator,omitempty"` - Denominator uint64 `protobuf:"varint,2,opt,name=denominator,proto3" json:"denominator,omitempty"` -} - -func (m *Fraction) Reset() { *m = Fraction{} } -func (m *Fraction) String() string { return proto.CompactTextString(m) } -func (*Fraction) ProtoMessage() {} -func (*Fraction) Descriptor() ([]byte, []int) { - return fileDescriptor_c6d6cf2b288949be, []int{4} -} -func (m *Fraction) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *Fraction) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_Fraction.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 *Fraction) XXX_Merge(src proto.Message) { - xxx_messageInfo_Fraction.Merge(m, src) -} -func (m *Fraction) XXX_Size() int { - return m.Size() -} -func (m *Fraction) XXX_DiscardUnknown() { - xxx_messageInfo_Fraction.DiscardUnknown(m) -} - -var xxx_messageInfo_Fraction proto.InternalMessageInfo - -func (m *Fraction) GetNumerator() uint64 { - if m != nil { - return m.Numerator - } - return 0 -} - -func (m *Fraction) GetDenominator() uint64 { - if m != nil { - return m.Denominator - } - return 0 -} - -func init() { - proto.RegisterType((*ClientState)(nil), "ibc.lightclients.tendermint.v1.ClientState") - proto.RegisterType((*ConsensusState)(nil), "ibc.lightclients.tendermint.v1.ConsensusState") - proto.RegisterType((*Misbehaviour)(nil), "ibc.lightclients.tendermint.v1.Misbehaviour") - proto.RegisterType((*Header)(nil), "ibc.lightclients.tendermint.v1.Header") - proto.RegisterType((*Fraction)(nil), "ibc.lightclients.tendermint.v1.Fraction") -} - -func init() { - proto.RegisterFile("ibc/lightclients/tendermint/v1/tendermint.proto", fileDescriptor_c6d6cf2b288949be) -} - -var fileDescriptor_c6d6cf2b288949be = []byte{ - // 1081 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x56, 0xcf, 0x6f, 0xe3, 0xc4, - 0x17, 0x6f, 0xda, 0x7e, 0xb7, 0xc9, 0x24, 0xdd, 0xf6, 0xeb, 0x2d, 0xdd, 0xb4, 0x74, 0xe3, 0xc8, - 0xa0, 0x25, 0x42, 0xaa, 0x4d, 0xb2, 0x48, 0x48, 0x15, 0x17, 0xdc, 0x82, 0x5a, 0xc4, 0x4a, 0x95, - 0xcb, 0x0f, 0x09, 0x09, 0xcc, 0xc4, 0x9e, 0xc4, 0xa3, 0xda, 0x1e, 0xe3, 0x99, 0x84, 0x94, 0xbf, - 0x00, 0x0e, 0x48, 0x7b, 0x44, 0x9c, 0x38, 0xf0, 0xc7, 0xec, 0xb1, 0x47, 0x4e, 0x06, 0xb5, 0x17, - 0xce, 0x39, 0x72, 0x42, 0x9e, 0x19, 0xdb, 0xd3, 0x6c, 0x97, 0x6a, 0xb9, 0xb4, 0xf3, 0xde, 0xfb, - 0xbc, 0xcf, 0x27, 0xf3, 0xe6, 0xcd, 0x1b, 0x03, 0x0b, 0x0f, 0x3d, 0x2b, 0xc4, 0xe3, 0x80, 0x79, - 0x21, 0x46, 0x31, 0xa3, 0x16, 0x43, 0xb1, 0x8f, 0xd2, 0x08, 0xc7, 0xcc, 0x9a, 0xf6, 0x15, 0xcb, - 0x4c, 0x52, 0xc2, 0x88, 0xd6, 0xc1, 0x43, 0xcf, 0x54, 0x13, 0x4c, 0x05, 0x32, 0xed, 0xef, 0x76, - 0x95, 0x7c, 0x76, 0x91, 0x20, 0x6a, 0x4d, 0x61, 0x88, 0x7d, 0xc8, 0x48, 0x2a, 0x18, 0x76, 0xf7, - 0x5e, 0x40, 0xf0, 0xbf, 0x32, 0xfa, 0xc0, 0x23, 0xf1, 0x08, 0x13, 0x2b, 0x49, 0x09, 0x19, 0x15, - 0xce, 0xce, 0x98, 0x90, 0x71, 0x88, 0x2c, 0x6e, 0x0d, 0x27, 0x23, 0xcb, 0x9f, 0xa4, 0x90, 0x61, - 0x12, 0xcb, 0xb8, 0xbe, 0x18, 0x67, 0x38, 0x42, 0x94, 0xc1, 0x28, 0x29, 0x00, 0xf9, 0x36, 0x3d, - 0x92, 0x22, 0x4b, 0xfc, 0xea, 0x7c, 0x6b, 0x62, 0x25, 0x01, 0x6f, 0x55, 0x00, 0x12, 0x45, 0x98, - 0x45, 0x05, 0xa8, 0xb4, 0x24, 0x70, 0x6b, 0x4c, 0xc6, 0x84, 0x2f, 0xad, 0x7c, 0x25, 0xbc, 0xc6, - 0x5f, 0x6b, 0xa0, 0x79, 0xc8, 0xf9, 0xce, 0x18, 0x64, 0x48, 0xdb, 0x01, 0x75, 0x2f, 0x80, 0x38, - 0x76, 0xb1, 0xdf, 0xae, 0x75, 0x6b, 0xbd, 0x86, 0xb3, 0xc6, 0xed, 0x13, 0x5f, 0x43, 0xa0, 0xc9, - 0xd2, 0x09, 0x65, 0x6e, 0x88, 0xa6, 0x28, 0x6c, 0x2f, 0x77, 0x6b, 0xbd, 0xe6, 0xa0, 0x67, 0xfe, - 0x7b, 0x59, 0xcd, 0x8f, 0x52, 0xe8, 0xe5, 0x1b, 0xb6, 0x77, 0x9f, 0x67, 0xfa, 0xd2, 0x3c, 0xd3, - 0xb5, 0x0b, 0x18, 0x85, 0x07, 0x86, 0x42, 0x65, 0x38, 0x80, 0x5b, 0x9f, 0xe4, 0x86, 0x36, 0x02, - 0x1b, 0xdc, 0xc2, 0xf1, 0xd8, 0x4d, 0x50, 0x8a, 0x89, 0xdf, 0x5e, 0xe1, 0x52, 0x3b, 0xa6, 0x28, - 0x96, 0x59, 0x14, 0xcb, 0x3c, 0x92, 0xc5, 0xb4, 0x0d, 0xc9, 0xbd, 0xad, 0x70, 0x57, 0xf9, 0xc6, - 0xcf, 0x7f, 0xe8, 0x35, 0xe7, 0x7e, 0xe1, 0x3d, 0xe5, 0x4e, 0x0d, 0x83, 0xcd, 0x49, 0x3c, 0x24, - 0xb1, 0xaf, 0x08, 0xad, 0xde, 0x25, 0xf4, 0x86, 0x14, 0x7a, 0x28, 0x84, 0x16, 0x09, 0x84, 0xd2, - 0x46, 0xe9, 0x96, 0x52, 0x08, 0x6c, 0x44, 0x70, 0xe6, 0x7a, 0x21, 0xf1, 0xce, 0x5d, 0x3f, 0xc5, - 0x23, 0xd6, 0xfe, 0xdf, 0x2b, 0x6e, 0x69, 0x21, 0x5f, 0x08, 0xad, 0x47, 0x70, 0x76, 0x98, 0x3b, - 0x8f, 0x72, 0x9f, 0xf6, 0x15, 0x58, 0x1f, 0xa5, 0xe4, 0x7b, 0x14, 0xbb, 0x01, 0xca, 0x0f, 0xa4, - 0x7d, 0x8f, 0x8b, 0xec, 0xf2, 0x23, 0xca, 0x5b, 0xc4, 0x94, 0x9d, 0x33, 0xed, 0x9b, 0xc7, 0x1c, - 0x61, 0xef, 0x49, 0x95, 0x2d, 0xa1, 0x72, 0x23, 0xdd, 0x70, 0x5a, 0xc2, 0x16, 0xd8, 0x9c, 0x3e, - 0x84, 0x0c, 0x51, 0x56, 0xd0, 0xaf, 0xbd, 0x2a, 0xfd, 0x8d, 0x74, 0xc3, 0x69, 0x09, 0x5b, 0xd2, - 0x9f, 0x80, 0x26, 0xbf, 0x3a, 0x2e, 0x4d, 0x90, 0x47, 0xdb, 0xf5, 0xee, 0x4a, 0xaf, 0x39, 0xd8, - 0x34, 0xb1, 0x47, 0x07, 0x4f, 0xcc, 0xd3, 0x3c, 0x72, 0x96, 0x20, 0xcf, 0xde, 0xae, 0x5a, 0x48, - 0x81, 0x1b, 0x0e, 0x48, 0x0a, 0x08, 0xd5, 0x0e, 0x40, 0x6b, 0x92, 0x8c, 0x53, 0xe8, 0x23, 0x37, - 0x81, 0x2c, 0x68, 0x37, 0xba, 0x2b, 0xbd, 0x86, 0xfd, 0x70, 0x9e, 0xe9, 0x0f, 0xe4, 0xb9, 0x29, - 0x51, 0xc3, 0x69, 0x4a, 0xf3, 0x14, 0xb2, 0x40, 0x73, 0xc1, 0x0e, 0x0c, 0x43, 0xf2, 0x9d, 0x3b, - 0x49, 0x7c, 0xc8, 0x90, 0x0b, 0x47, 0x0c, 0xa5, 0x2e, 0x9a, 0x25, 0x38, 0xbd, 0x68, 0x83, 0x6e, - 0xad, 0x57, 0xb7, 0xdf, 0x9c, 0x67, 0x7a, 0x57, 0x10, 0xbd, 0x14, 0x6a, 0x38, 0xdb, 0x3c, 0xf6, - 0x19, 0x0f, 0x7d, 0x90, 0x47, 0x3e, 0xe4, 0x01, 0xed, 0x5b, 0xa0, 0xdf, 0x92, 0x15, 0x61, 0x3a, - 0x44, 0x01, 0x9c, 0x62, 0x32, 0x49, 0xdb, 0x4d, 0x2e, 0xf3, 0xf6, 0x3c, 0xd3, 0x1f, 0xbf, 0x54, - 0x46, 0x4d, 0x30, 0x9c, 0xbd, 0x45, 0xb1, 0xa7, 0x4a, 0xf8, 0x60, 0xf5, 0x87, 0x5f, 0xf5, 0x25, - 0xe3, 0xb7, 0x65, 0x70, 0xff, 0x90, 0xc4, 0x14, 0xc5, 0x74, 0x42, 0xc5, 0x6d, 0xb7, 0x41, 0xa3, - 0x1c, 0x38, 0xfc, 0xba, 0xe7, 0xc7, 0xb9, 0xd8, 0x92, 0x9f, 0x16, 0x08, 0xbb, 0x9e, 0x1f, 0xe7, - 0xb3, 0xbc, 0xf3, 0xaa, 0x34, 0xed, 0x7d, 0xb0, 0x9a, 0x12, 0xc2, 0xe4, 0x3c, 0x30, 0x94, 0x6e, - 0xa8, 0x26, 0xd0, 0xb4, 0x6f, 0x3e, 0x45, 0xe9, 0x79, 0x88, 0x1c, 0x42, 0x98, 0xbd, 0x9a, 0xd3, - 0x38, 0x3c, 0x4b, 0xfb, 0xb1, 0x06, 0xb6, 0x62, 0x34, 0x63, 0x6e, 0x39, 0x6c, 0xa9, 0x1b, 0x40, - 0x1a, 0xf0, 0x3b, 0xdf, 0xb2, 0xbf, 0x98, 0x67, 0xfa, 0xeb, 0xa2, 0x06, 0xb7, 0xa1, 0x8c, 0xbf, - 0x33, 0xfd, 0xdd, 0x31, 0x66, 0xc1, 0x64, 0x98, 0xcb, 0xa9, 0x4f, 0x80, 0xb2, 0x0c, 0xf1, 0x90, - 0x5a, 0xc3, 0x0b, 0x86, 0xa8, 0x79, 0x8c, 0x66, 0x76, 0xbe, 0x70, 0xb4, 0x9c, 0xee, 0xf3, 0x92, - 0xed, 0x18, 0xd2, 0x40, 0x96, 0xe9, 0xa7, 0x65, 0xd0, 0x52, 0xab, 0xa7, 0xf5, 0x41, 0x43, 0x34, - 0x76, 0x39, 0x13, 0xed, 0xad, 0x79, 0xa6, 0x6f, 0x8a, 0x9f, 0x55, 0x86, 0x0c, 0xa7, 0x2e, 0xd6, - 0x27, 0xbe, 0x06, 0x41, 0x3d, 0x40, 0xd0, 0x47, 0xa9, 0xdb, 0x97, 0x75, 0x79, 0x7c, 0xd7, 0x9c, - 0x3c, 0xe6, 0x78, 0xbb, 0x73, 0x95, 0xe9, 0x6b, 0x62, 0xdd, 0x9f, 0x67, 0xfa, 0x86, 0x10, 0x29, - 0xc8, 0x0c, 0x67, 0x4d, 0x2c, 0xfb, 0x8a, 0xc4, 0x40, 0xce, 0xc7, 0xff, 0x20, 0x31, 0x78, 0x41, - 0x62, 0x50, 0x4a, 0x0c, 0x64, 0x3d, 0x7e, 0x59, 0x01, 0xf7, 0x04, 0x5a, 0x83, 0x60, 0x9d, 0xe2, - 0x71, 0x8c, 0x7c, 0x57, 0x40, 0x64, 0xcb, 0x74, 0x54, 0x1d, 0xf1, 0x24, 0x9e, 0x71, 0x98, 0x14, - 0xdc, 0xbb, 0xcc, 0xf4, 0x5a, 0x35, 0x05, 0x6e, 0x50, 0x18, 0x4e, 0x8b, 0x2a, 0xd8, 0x7c, 0xc8, - 0x94, 0x67, 0xec, 0x52, 0x54, 0xb4, 0xd5, 0x2d, 0x12, 0xe5, 0xe1, 0x9d, 0x21, 0x66, 0xb7, 0x2b, - 0xfa, 0x1b, 0xe9, 0x86, 0xd3, 0x9a, 0x2a, 0x38, 0xed, 0x1b, 0x20, 0x9e, 0x01, 0xae, 0xcf, 0x87, - 0xd8, 0xca, 0x9d, 0x43, 0xec, 0x91, 0x1c, 0x62, 0xaf, 0x29, 0x8f, 0x4b, 0x99, 0x6f, 0x38, 0xeb, - 0xd2, 0x21, 0xc7, 0x58, 0x08, 0xb4, 0x02, 0x51, 0x35, 0xab, 0x7c, 0x58, 0xee, 0xda, 0xc5, 0xa3, - 0x79, 0xa6, 0xef, 0xdc, 0x54, 0xa9, 0x38, 0x0c, 0xe7, 0xff, 0xd2, 0x59, 0xb5, 0xad, 0xf1, 0x31, - 0xa8, 0x17, 0x0f, 0xac, 0xb6, 0x07, 0x1a, 0xf1, 0x24, 0x42, 0x69, 0x1e, 0xe1, 0x27, 0xb3, 0xea, - 0x54, 0x0e, 0xad, 0x0b, 0x9a, 0x3e, 0x8a, 0x49, 0x84, 0x63, 0x1e, 0x5f, 0xe6, 0x71, 0xd5, 0x65, - 0x7f, 0xfd, 0xfc, 0xaa, 0x53, 0xbb, 0xbc, 0xea, 0xd4, 0xfe, 0xbc, 0xea, 0xd4, 0x9e, 0x5d, 0x77, - 0x96, 0x2e, 0xaf, 0x3b, 0x4b, 0xbf, 0x5f, 0x77, 0x96, 0xbe, 0x3c, 0x52, 0xae, 0x98, 0x47, 0x68, - 0x44, 0xa8, 0xfc, 0xb7, 0x4f, 0xfd, 0x73, 0x6b, 0x56, 0x7d, 0x8a, 0xed, 0x17, 0xdf, 0x62, 0xef, - 0xbc, 0xb7, 0xbf, 0xf8, 0xb1, 0x34, 0xbc, 0xc7, 0x27, 0xca, 0x93, 0x7f, 0x02, 0x00, 0x00, 0xff, - 0xff, 0x8f, 0xde, 0xf9, 0xa9, 0xba, 0x09, 0x00, 0x00, -} - -func (m *ClientState) 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 *ClientState) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *ClientState) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.AllowUpdateAfterMisbehaviour { - i-- - if m.AllowUpdateAfterMisbehaviour { - dAtA[i] = 1 - } else { - dAtA[i] = 0 - } - i-- - dAtA[i] = 0x58 - } - if m.AllowUpdateAfterExpiry { - i-- - if m.AllowUpdateAfterExpiry { - dAtA[i] = 1 - } else { - dAtA[i] = 0 - } - i-- - dAtA[i] = 0x50 - } - if len(m.UpgradePath) > 0 { - for iNdEx := len(m.UpgradePath) - 1; iNdEx >= 0; iNdEx-- { - i -= len(m.UpgradePath[iNdEx]) - copy(dAtA[i:], m.UpgradePath[iNdEx]) - i = encodeVarintTendermint(dAtA, i, uint64(len(m.UpgradePath[iNdEx]))) - i-- - dAtA[i] = 0x4a - } - } - if len(m.ProofSpecs) > 0 { - for iNdEx := len(m.ProofSpecs) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.ProofSpecs[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTendermint(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x42 - } - } - { - size, err := m.LatestHeight.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTendermint(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x3a - { - size, err := m.FrozenHeight.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTendermint(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x32 - n3, err3 := github_com_gogo_protobuf_types.StdDurationMarshalTo(m.MaxClockDrift, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdDuration(m.MaxClockDrift):]) - if err3 != nil { - return 0, err3 - } - i -= n3 - i = encodeVarintTendermint(dAtA, i, uint64(n3)) - i-- - dAtA[i] = 0x2a - n4, err4 := github_com_gogo_protobuf_types.StdDurationMarshalTo(m.UnbondingPeriod, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdDuration(m.UnbondingPeriod):]) - if err4 != nil { - return 0, err4 - } - i -= n4 - i = encodeVarintTendermint(dAtA, i, uint64(n4)) - i-- - dAtA[i] = 0x22 - n5, err5 := github_com_gogo_protobuf_types.StdDurationMarshalTo(m.TrustingPeriod, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdDuration(m.TrustingPeriod):]) - if err5 != nil { - return 0, err5 - } - i -= n5 - i = encodeVarintTendermint(dAtA, i, uint64(n5)) - i-- - dAtA[i] = 0x1a - { - size, err := m.TrustLevel.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTendermint(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - if len(m.ChainId) > 0 { - i -= len(m.ChainId) - copy(dAtA[i:], m.ChainId) - i = encodeVarintTendermint(dAtA, i, uint64(len(m.ChainId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *ConsensusState) 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 *ConsensusState) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *ConsensusState) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.NextValidatorsHash) > 0 { - i -= len(m.NextValidatorsHash) - copy(dAtA[i:], m.NextValidatorsHash) - i = encodeVarintTendermint(dAtA, i, uint64(len(m.NextValidatorsHash))) - i-- - dAtA[i] = 0x1a - } - { - size, err := m.Root.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTendermint(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - n8, err8 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Timestamp, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Timestamp):]) - if err8 != nil { - return 0, err8 - } - i -= n8 - i = encodeVarintTendermint(dAtA, i, uint64(n8)) - i-- - dAtA[i] = 0xa - return len(dAtA) - i, nil -} - -func (m *Misbehaviour) 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 *Misbehaviour) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *Misbehaviour) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.Header2 != nil { - { - size, err := m.Header2.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTendermint(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - } - if m.Header1 != nil { - { - size, err := m.Header1.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTendermint(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - } - if len(m.ClientId) > 0 { - i -= len(m.ClientId) - copy(dAtA[i:], m.ClientId) - i = encodeVarintTendermint(dAtA, i, uint64(len(m.ClientId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *Header) 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 *Header) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *Header) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.TrustedValidators != nil { - { - size, err := m.TrustedValidators.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTendermint(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x22 - } - { - size, err := m.TrustedHeight.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTendermint(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - if m.ValidatorSet != nil { - { - size, err := m.ValidatorSet.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTendermint(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - } - if m.SignedHeader != nil { - { - size, err := m.SignedHeader.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTendermint(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *Fraction) 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 *Fraction) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *Fraction) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.Denominator != 0 { - i = encodeVarintTendermint(dAtA, i, uint64(m.Denominator)) - i-- - dAtA[i] = 0x10 - } - if m.Numerator != 0 { - i = encodeVarintTendermint(dAtA, i, uint64(m.Numerator)) - i-- - dAtA[i] = 0x8 - } - return len(dAtA) - i, nil -} - -func encodeVarintTendermint(dAtA []byte, offset int, v uint64) int { - offset -= sovTendermint(v) - base := offset - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ - } - dAtA[offset] = uint8(v) - return base -} -func (m *ClientState) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.ChainId) - if l > 0 { - n += 1 + l + sovTendermint(uint64(l)) - } - l = m.TrustLevel.Size() - n += 1 + l + sovTendermint(uint64(l)) - l = github_com_gogo_protobuf_types.SizeOfStdDuration(m.TrustingPeriod) - n += 1 + l + sovTendermint(uint64(l)) - l = github_com_gogo_protobuf_types.SizeOfStdDuration(m.UnbondingPeriod) - n += 1 + l + sovTendermint(uint64(l)) - l = github_com_gogo_protobuf_types.SizeOfStdDuration(m.MaxClockDrift) - n += 1 + l + sovTendermint(uint64(l)) - l = m.FrozenHeight.Size() - n += 1 + l + sovTendermint(uint64(l)) - l = m.LatestHeight.Size() - n += 1 + l + sovTendermint(uint64(l)) - if len(m.ProofSpecs) > 0 { - for _, e := range m.ProofSpecs { - l = e.Size() - n += 1 + l + sovTendermint(uint64(l)) - } - } - if len(m.UpgradePath) > 0 { - for _, s := range m.UpgradePath { - l = len(s) - n += 1 + l + sovTendermint(uint64(l)) - } - } - if m.AllowUpdateAfterExpiry { - n += 2 - } - if m.AllowUpdateAfterMisbehaviour { - n += 2 - } - return n -} - -func (m *ConsensusState) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = github_com_gogo_protobuf_types.SizeOfStdTime(m.Timestamp) - n += 1 + l + sovTendermint(uint64(l)) - l = m.Root.Size() - n += 1 + l + sovTendermint(uint64(l)) - l = len(m.NextValidatorsHash) - if l > 0 { - n += 1 + l + sovTendermint(uint64(l)) - } - return n -} - -func (m *Misbehaviour) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.ClientId) - if l > 0 { - n += 1 + l + sovTendermint(uint64(l)) - } - if m.Header1 != nil { - l = m.Header1.Size() - n += 1 + l + sovTendermint(uint64(l)) - } - if m.Header2 != nil { - l = m.Header2.Size() - n += 1 + l + sovTendermint(uint64(l)) - } - return n -} - -func (m *Header) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.SignedHeader != nil { - l = m.SignedHeader.Size() - n += 1 + l + sovTendermint(uint64(l)) - } - if m.ValidatorSet != nil { - l = m.ValidatorSet.Size() - n += 1 + l + sovTendermint(uint64(l)) - } - l = m.TrustedHeight.Size() - n += 1 + l + sovTendermint(uint64(l)) - if m.TrustedValidators != nil { - l = m.TrustedValidators.Size() - n += 1 + l + sovTendermint(uint64(l)) - } - return n -} - -func (m *Fraction) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.Numerator != 0 { - n += 1 + sovTendermint(uint64(m.Numerator)) - } - if m.Denominator != 0 { - n += 1 + sovTendermint(uint64(m.Denominator)) - } - return n -} - -func sovTendermint(x uint64) (n int) { - return (math_bits.Len64(x|1) + 6) / 7 -} -func sozTendermint(x uint64) (n int) { - return sovTendermint(uint64((x << 1) ^ uint64((int64(x) >> 63)))) -} -func (m *ClientState) 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 ErrIntOverflowTendermint - } - 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: ClientState: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: ClientState: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTendermint - } - 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 ErrInvalidLengthTendermint - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTendermint - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ChainId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field TrustLevel", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTendermint - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTendermint - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTendermint - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.TrustLevel.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field TrustingPeriod", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTendermint - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTendermint - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTendermint - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := github_com_gogo_protobuf_types.StdDurationUnmarshal(&m.TrustingPeriod, dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field UnbondingPeriod", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTendermint - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTendermint - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTendermint - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := github_com_gogo_protobuf_types.StdDurationUnmarshal(&m.UnbondingPeriod, dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field MaxClockDrift", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTendermint - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTendermint - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTendermint - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := github_com_gogo_protobuf_types.StdDurationUnmarshal(&m.MaxClockDrift, dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 6: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field FrozenHeight", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTendermint - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTendermint - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTendermint - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.FrozenHeight.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 7: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field LatestHeight", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTendermint - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTendermint - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTendermint - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.LatestHeight.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 8: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ProofSpecs", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTendermint - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTendermint - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTendermint - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ProofSpecs = append(m.ProofSpecs, &_go.ProofSpec{}) - if err := m.ProofSpecs[len(m.ProofSpecs)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 9: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field UpgradePath", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTendermint - } - 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 ErrInvalidLengthTendermint - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTendermint - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.UpgradePath = append(m.UpgradePath, string(dAtA[iNdEx:postIndex])) - iNdEx = postIndex - case 10: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field AllowUpdateAfterExpiry", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTendermint - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.AllowUpdateAfterExpiry = bool(v != 0) - case 11: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field AllowUpdateAfterMisbehaviour", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTendermint - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.AllowUpdateAfterMisbehaviour = bool(v != 0) - default: - iNdEx = preIndex - skippy, err := skipTendermint(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTendermint - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *ConsensusState) 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 ErrIntOverflowTendermint - } - 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: ConsensusState: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: ConsensusState: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTendermint - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTendermint - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTendermint - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.Timestamp, dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Root", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTendermint - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTendermint - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTendermint - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.Root.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field NextValidatorsHash", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTendermint - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthTendermint - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthTendermint - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.NextValidatorsHash = append(m.NextValidatorsHash[:0], dAtA[iNdEx:postIndex]...) - if m.NextValidatorsHash == nil { - m.NextValidatorsHash = []byte{} - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipTendermint(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTendermint - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *Misbehaviour) 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 ErrIntOverflowTendermint - } - 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: Misbehaviour: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: Misbehaviour: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ClientId", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTendermint - } - 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 ErrInvalidLengthTendermint - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTendermint - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ClientId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Header1", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTendermint - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTendermint - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTendermint - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.Header1 == nil { - m.Header1 = &Header{} - } - if err := m.Header1.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Header2", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTendermint - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTendermint - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTendermint - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.Header2 == nil { - m.Header2 = &Header{} - } - if err := m.Header2.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipTendermint(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTendermint - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *Header) 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 ErrIntOverflowTendermint - } - 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: Header: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: Header: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field SignedHeader", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTendermint - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTendermint - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTendermint - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.SignedHeader == nil { - m.SignedHeader = &types2.SignedHeader{} - } - if err := m.SignedHeader.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ValidatorSet", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTendermint - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTendermint - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTendermint - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.ValidatorSet == nil { - m.ValidatorSet = &types2.ValidatorSet{} - } - if err := m.ValidatorSet.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field TrustedHeight", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTendermint - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTendermint - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTendermint - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.TrustedHeight.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field TrustedValidators", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTendermint - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTendermint - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTendermint - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.TrustedValidators == nil { - m.TrustedValidators = &types2.ValidatorSet{} - } - if err := m.TrustedValidators.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipTendermint(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTendermint - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *Fraction) 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 ErrIntOverflowTendermint - } - 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: Fraction: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: Fraction: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Numerator", wireType) - } - m.Numerator = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTendermint - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Numerator |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Denominator", wireType) - } - m.Denominator = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTendermint - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Denominator |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - default: - iNdEx = preIndex - skippy, err := skipTendermint(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTendermint - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func skipTendermint(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, ErrIntOverflowTendermint - } - 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, ErrIntOverflowTendermint - } - 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, ErrIntOverflowTendermint - } - 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, ErrInvalidLengthTendermint - } - iNdEx += length - case 3: - depth++ - case 4: - if depth == 0 { - return 0, ErrUnexpectedEndOfGroupTendermint - } - depth-- - case 5: - iNdEx += 4 - default: - return 0, fmt.Errorf("proto: illegal wireType %d", wireType) - } - if iNdEx < 0 { - return 0, ErrInvalidLengthTendermint - } - if depth == 0 { - return iNdEx, nil - } - } - return 0, io.ErrUnexpectedEOF -} - -var ( - ErrInvalidLengthTendermint = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowTendermint = fmt.Errorf("proto: integer overflow") - ErrUnexpectedEndOfGroupTendermint = fmt.Errorf("proto: unexpected end of group") -) diff --git a/x/ibc/light-clients/07-tendermint/types/tendermint_test.go b/x/ibc/light-clients/07-tendermint/types/tendermint_test.go deleted file mode 100644 index 4f9b8142bfb9..000000000000 --- a/x/ibc/light-clients/07-tendermint/types/tendermint_test.go +++ /dev/null @@ -1,95 +0,0 @@ -package types_test - -import ( - "testing" - "time" - - "github.com/stretchr/testify/suite" - tmbytes "github.com/tendermint/tendermint/libs/bytes" - tmproto "github.com/tendermint/tendermint/proto/tendermint/types" - tmtypes "github.com/tendermint/tendermint/types" - - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/simapp" - sdk "github.com/cosmos/cosmos-sdk/types" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" - ibctestingmock "github.com/cosmos/cosmos-sdk/x/ibc/testing/mock" -) - -const ( - chainID = "gaia" - chainIDRevision0 = "gaia-revision-0" - chainIDRevision1 = "gaia-revision-1" - clientID = "gaiamainnet" - trustingPeriod time.Duration = time.Hour * 24 * 7 * 2 - ubdPeriod time.Duration = time.Hour * 24 * 7 * 3 - maxClockDrift time.Duration = time.Second * 10 -) - -var ( - height = clienttypes.NewHeight(0, 4) - newClientHeight = clienttypes.NewHeight(1, 1) - upgradePath = []string{"upgrade", "upgradedIBCState"} -) - -type TendermintTestSuite struct { - suite.Suite - - coordinator *ibctesting.Coordinator - - // testing chains used for convenience and readability - chainA *ibctesting.TestChain - chainB *ibctesting.TestChain - - // TODO: deprecate usage in favor of testing package - ctx sdk.Context - cdc codec.Marshaler - privVal tmtypes.PrivValidator - valSet *tmtypes.ValidatorSet - valsHash tmbytes.HexBytes - header *ibctmtypes.Header - now time.Time - headerTime time.Time - clientTime time.Time -} - -func (suite *TendermintTestSuite) SetupTest() { - suite.coordinator = ibctesting.NewCoordinator(suite.T(), 2) - suite.chainA = suite.coordinator.GetChain(ibctesting.GetChainID(0)) - suite.chainB = suite.coordinator.GetChain(ibctesting.GetChainID(1)) - // commit some blocks so that QueryProof returns valid proof (cannot return valid query if height <= 1) - suite.coordinator.CommitNBlocks(suite.chainA, 2) - suite.coordinator.CommitNBlocks(suite.chainB, 2) - - // TODO: deprecate usage in favor of testing package - checkTx := false - app := simapp.Setup(checkTx) - - suite.cdc = app.AppCodec() - - // now is the time of the current chain, must be after the updating header - // mocks ctx.BlockTime() - suite.now = time.Date(2020, 1, 2, 0, 0, 0, 0, time.UTC) - suite.clientTime = time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC) - // Header time is intended to be time for any new header used for updates - suite.headerTime = time.Date(2020, 1, 2, 0, 0, 0, 0, time.UTC) - - suite.privVal = ibctestingmock.NewPV() - - pubKey, err := suite.privVal.GetPubKey() - suite.Require().NoError(err) - - heightMinus1 := clienttypes.NewHeight(0, height.RevisionHeight-1) - - val := tmtypes.NewValidator(pubKey, 10) - suite.valSet = tmtypes.NewValidatorSet([]*tmtypes.Validator{val}) - suite.valsHash = suite.valSet.Hash() - suite.header = suite.chainA.CreateTMClientHeader(chainID, int64(height.RevisionHeight), heightMinus1, suite.now, suite.valSet, suite.valSet, []tmtypes.PrivValidator{suite.privVal}) - suite.ctx = app.BaseApp.NewContext(checkTx, tmproto.Header{Height: 1, Time: suite.now}) -} - -func TestTendermintTestSuite(t *testing.T) { - suite.Run(t, new(TendermintTestSuite)) -} diff --git a/x/ibc/light-clients/07-tendermint/types/update.go b/x/ibc/light-clients/07-tendermint/types/update.go deleted file mode 100644 index e692e7466860..000000000000 --- a/x/ibc/light-clients/07-tendermint/types/update.go +++ /dev/null @@ -1,186 +0,0 @@ -package types - -import ( - "bytes" - "time" - - "github.com/tendermint/tendermint/light" - tmtypes "github.com/tendermint/tendermint/types" - - "github.com/cosmos/cosmos-sdk/codec" - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - 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/core/exported" -) - -// CheckHeaderAndUpdateState checks if the provided header is valid, and if valid it will: -// create the consensus state for the header.Height -// and update the client state if the header height is greater than the latest client state height -// It returns an error if: -// - the client or header provided are not parseable to tendermint types -// - the header is invalid -// - header height is less than or equal to the trusted header height -// - header revision is not equal to trusted header revision -// - header valset commit verification fails -// - header timestamp is past the trusting period in relation to the consensus state -// - header timestamp is less than or equal to the consensus state timestamp -// -// UpdateClient may be used to either create a consensus state for: -// - a future height greater than the latest client state height -// - a past height that was skipped during bisection -// If we are updating to a past height, a consensus state is created for that height to be persisted in client store -// If we are updating to a future height, the consensus state is created and the client state is updated to reflect -// the new latest height -// UpdateClient must only be used to update within a single revision, thus header revision number and trusted height's revision -// number must be the same. To update to a new revision, use a separate upgrade path -// Tendermint client validity checking uses the bisection algorithm described -// in the [Tendermint spec](https://github.com/tendermint/spec/blob/master/spec/consensus/light-client.md). -func (cs ClientState) CheckHeaderAndUpdateState( - ctx sdk.Context, cdc codec.BinaryMarshaler, clientStore sdk.KVStore, - header exported.Header, -) (exported.ClientState, exported.ConsensusState, error) { - tmHeader, ok := header.(*Header) - if !ok { - return nil, nil, sdkerrors.Wrapf( - clienttypes.ErrInvalidHeader, "expected type %T, got %T", &Header{}, header, - ) - } - - // get consensus state from clientStore - tmConsState, err := GetConsensusState(clientStore, cdc, tmHeader.TrustedHeight) - if err != nil { - return nil, nil, sdkerrors.Wrapf( - err, "could not get consensus state from clientstore at TrustedHeight: %s", tmHeader.TrustedHeight, - ) - } - - if err := checkValidity(&cs, tmConsState, tmHeader, ctx.BlockTime()); err != nil { - return nil, nil, err - } - - newClientState, consensusState := update(ctx, clientStore, &cs, tmHeader) - return newClientState, consensusState, nil -} - -// checkTrustedHeader checks that consensus state matches trusted fields of Header -func checkTrustedHeader(header *Header, consState *ConsensusState) error { - tmTrustedValidators, err := tmtypes.ValidatorSetFromProto(header.TrustedValidators) - if err != nil { - return sdkerrors.Wrap(err, "trusted validator set in not tendermint validator set type") - } - - // assert that trustedVals is NextValidators of last trusted header - // to do this, we check that trustedVals.Hash() == consState.NextValidatorsHash - tvalHash := tmTrustedValidators.Hash() - if !bytes.Equal(consState.NextValidatorsHash, tvalHash) { - return sdkerrors.Wrapf( - ErrInvalidValidatorSet, - "trusted validators %s, does not hash to latest trusted validators. Expected: %X, got: %X", - header.TrustedValidators, consState.NextValidatorsHash, tvalHash, - ) - } - return nil -} - -// checkValidity checks if the Tendermint header is valid. -// CONTRACT: consState.Height == header.TrustedHeight -func checkValidity( - clientState *ClientState, consState *ConsensusState, - header *Header, currentTimestamp time.Time, -) error { - if err := checkTrustedHeader(header, consState); err != nil { - return err - } - - // UpdateClient only accepts updates with a header at the same revision - // as the trusted consensus state - if header.GetHeight().GetRevisionNumber() != header.TrustedHeight.RevisionNumber { - return sdkerrors.Wrapf( - ErrInvalidHeaderHeight, - "header height revision %d does not match trusted header revision %d", - header.GetHeight().GetRevisionNumber(), header.TrustedHeight.RevisionNumber, - ) - } - - tmTrustedValidators, err := tmtypes.ValidatorSetFromProto(header.TrustedValidators) - if err != nil { - return sdkerrors.Wrap(err, "trusted validator set in not tendermint validator set type") - } - - tmSignedHeader, err := tmtypes.SignedHeaderFromProto(header.SignedHeader) - if err != nil { - return sdkerrors.Wrap(err, "signed header in not tendermint signed header type") - } - - tmValidatorSet, err := tmtypes.ValidatorSetFromProto(header.ValidatorSet) - if err != nil { - return sdkerrors.Wrap(err, "validator set in not tendermint validator set type") - } - - // assert header height is newer than consensus state - if header.GetHeight().LTE(header.TrustedHeight) { - return sdkerrors.Wrapf( - clienttypes.ErrInvalidHeader, - "header height ≤ consensus state height (%s ≤ %s)", header.GetHeight(), header.TrustedHeight, - ) - } - - chainID := clientState.GetChainID() - // If chainID is in revision format, then set revision number of chainID with the revision number - // of the header we are verifying - // This is useful if the update is at a previous revision rather than an update to the latest revision - // of the client. - // The chainID must be set correctly for the previous revision before attempting verification. - // Updates for previous revisions are not supported if the chainID is not in revision format. - if clienttypes.IsRevisionFormat(chainID) { - chainID, _ = clienttypes.SetRevisionNumber(chainID, header.GetHeight().GetRevisionNumber()) - } - - // Construct a trusted header using the fields in consensus state - // Only Height, Time, and NextValidatorsHash are necessary for verification - trustedHeader := tmtypes.Header{ - ChainID: chainID, - Height: int64(header.TrustedHeight.RevisionHeight), - Time: consState.Timestamp, - NextValidatorsHash: consState.NextValidatorsHash, - } - signedHeader := tmtypes.SignedHeader{ - Header: &trustedHeader, - } - - // Verify next header with the passed-in trustedVals - // - asserts trusting period not passed - // - assert header timestamp is not past the trusting period - // - assert header timestamp is past latest stored consensus state timestamp - // - assert that a TrustLevel proportion of TrustedValidators signed new Commit - err = light.Verify( - &signedHeader, - tmTrustedValidators, tmSignedHeader, tmValidatorSet, - clientState.TrustingPeriod, currentTimestamp, clientState.MaxClockDrift, clientState.TrustLevel.ToTendermint(), - ) - if err != nil { - return sdkerrors.Wrap(err, "failed to verify header") - } - return nil -} - -// update the consensus state from a new header and set processed time metadata -func update(ctx sdk.Context, clientStore sdk.KVStore, clientState *ClientState, header *Header) (*ClientState, *ConsensusState) { - height := header.GetHeight().(clienttypes.Height) - if height.GT(clientState.LatestHeight) { - clientState.LatestHeight = height - } - consensusState := &ConsensusState{ - Timestamp: header.GetTime(), - Root: commitmenttypes.NewMerkleRoot(header.Header.GetAppHash()), - NextValidatorsHash: header.Header.NextValidatorsHash, - } - - // set context time as processed time as this is state internal to tendermint client logic. - // client state and consensus state will be set by client keeper - SetProcessedTime(clientStore, header.GetHeight(), uint64(ctx.BlockTime().UnixNano())) - - return clientState, consensusState -} diff --git a/x/ibc/light-clients/07-tendermint/types/update_test.go b/x/ibc/light-clients/07-tendermint/types/update_test.go deleted file mode 100644 index d9e550ed015a..000000000000 --- a/x/ibc/light-clients/07-tendermint/types/update_test.go +++ /dev/null @@ -1,281 +0,0 @@ -package types_test - -import ( - "time" - - tmtypes "github.com/tendermint/tendermint/types" - - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types" - types "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" - ibctestingmock "github.com/cosmos/cosmos-sdk/x/ibc/testing/mock" -) - -func (suite *TendermintTestSuite) TestCheckHeaderAndUpdateState() { - var ( - clientState *types.ClientState - consensusState *types.ConsensusState - consStateHeight clienttypes.Height - newHeader *types.Header - currentTime time.Time - ) - - // Setup different validators and signers for testing different types of updates - altPrivVal := ibctestingmock.NewPV() - altPubKey, err := altPrivVal.GetPubKey() - suite.Require().NoError(err) - - revisionHeight := int64(height.RevisionHeight) - - // create modified heights to use for test-cases - heightPlus1 := clienttypes.NewHeight(height.RevisionNumber, height.RevisionHeight+1) - heightMinus1 := clienttypes.NewHeight(height.RevisionNumber, height.RevisionHeight-1) - heightMinus3 := clienttypes.NewHeight(height.RevisionNumber, height.RevisionHeight-3) - heightPlus5 := clienttypes.NewHeight(height.RevisionNumber, height.RevisionHeight+5) - - altVal := tmtypes.NewValidator(altPubKey, revisionHeight) - - // Create bothValSet with both suite validator and altVal. Would be valid update - bothValSet := tmtypes.NewValidatorSet(append(suite.valSet.Validators, altVal)) - // Create alternative validator set with only altVal, invalid update (too much change in valSet) - altValSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{altVal}) - - signers := []tmtypes.PrivValidator{suite.privVal} - - // Create signer array and ensure it is in same order as bothValSet - _, suiteVal := suite.valSet.GetByIndex(0) - bothSigners := ibctesting.CreateSortedSignerArray(altPrivVal, suite.privVal, altVal, suiteVal) - - altSigners := []tmtypes.PrivValidator{altPrivVal} - - testCases := []struct { - name string - setup func() - expPass bool - }{ - { - name: "successful update with next height and same validator set", - setup: func() { - clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash) - newHeader = suite.chainA.CreateTMClientHeader(chainID, int64(heightPlus1.RevisionHeight), height, suite.headerTime, suite.valSet, suite.valSet, signers) - currentTime = suite.now - }, - expPass: true, - }, - { - name: "successful update with future height and different validator set", - setup: func() { - clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash) - newHeader = suite.chainA.CreateTMClientHeader(chainID, int64(heightPlus5.RevisionHeight), height, suite.headerTime, bothValSet, suite.valSet, bothSigners) - currentTime = suite.now - }, - expPass: true, - }, - { - name: "successful update with next height and different validator set", - setup: func() { - clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), bothValSet.Hash()) - newHeader = suite.chainA.CreateTMClientHeader(chainID, int64(heightPlus1.RevisionHeight), height, suite.headerTime, bothValSet, bothValSet, bothSigners) - currentTime = suite.now - }, - expPass: true, - }, - { - name: "successful update for a previous height", - setup: func() { - clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash) - consStateHeight = heightMinus3 - newHeader = suite.chainA.CreateTMClientHeader(chainID, int64(heightMinus1.RevisionHeight), heightMinus3, suite.headerTime, bothValSet, suite.valSet, bothSigners) - currentTime = suite.now - }, - expPass: true, - }, - { - name: "successful update for a previous revision", - setup: func() { - clientState = types.NewClientState(chainIDRevision1, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash) - newHeader = suite.chainA.CreateTMClientHeader(chainIDRevision0, int64(height.RevisionHeight), heightMinus3, suite.headerTime, bothValSet, suite.valSet, bothSigners) - currentTime = suite.now - }, - expPass: true, - }, - { - name: "unsuccessful update with incorrect header chain-id", - setup: func() { - clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash) - newHeader = suite.chainA.CreateTMClientHeader("ethermint", int64(heightPlus1.RevisionHeight), height, suite.headerTime, suite.valSet, suite.valSet, signers) - currentTime = suite.now - }, - expPass: false, - }, - { - name: "unsuccessful update to a future revision", - setup: func() { - clientState = types.NewClientState(chainIDRevision0, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash) - newHeader = suite.chainA.CreateTMClientHeader(chainIDRevision1, 1, height, suite.headerTime, suite.valSet, suite.valSet, signers) - currentTime = suite.now - }, - expPass: false, - }, - { - name: "unsuccessful update: header height revision and trusted height revision mismatch", - setup: func() { - clientState = types.NewClientState(chainIDRevision1, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, clienttypes.NewHeight(1, 1), commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash) - newHeader = suite.chainA.CreateTMClientHeader(chainIDRevision1, 3, height, suite.headerTime, suite.valSet, suite.valSet, signers) - currentTime = suite.now - }, - expPass: false, - }, - { - name: "unsuccessful update with next height: update header mismatches nextValSetHash", - setup: func() { - clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash) - newHeader = suite.chainA.CreateTMClientHeader(chainID, int64(heightPlus1.RevisionHeight), height, suite.headerTime, bothValSet, suite.valSet, bothSigners) - currentTime = suite.now - }, - expPass: false, - }, - { - name: "unsuccessful update with next height: update header mismatches different nextValSetHash", - setup: func() { - clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), bothValSet.Hash()) - newHeader = suite.chainA.CreateTMClientHeader(chainID, int64(heightPlus1.RevisionHeight), height, suite.headerTime, suite.valSet, bothValSet, signers) - currentTime = suite.now - }, - expPass: false, - }, - { - name: "unsuccessful update with future height: too much change in validator set", - setup: func() { - clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash) - newHeader = suite.chainA.CreateTMClientHeader(chainID, int64(heightPlus5.RevisionHeight), height, suite.headerTime, altValSet, suite.valSet, altSigners) - currentTime = suite.now - }, - expPass: false, - }, - { - name: "unsuccessful updates, passed in incorrect trusted validators for given consensus state", - setup: func() { - clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash) - newHeader = suite.chainA.CreateTMClientHeader(chainID, int64(heightPlus5.RevisionHeight), height, suite.headerTime, bothValSet, bothValSet, bothSigners) - currentTime = suite.now - }, - expPass: false, - }, - { - name: "unsuccessful update: trusting period has passed since last client timestamp", - setup: func() { - clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash) - newHeader = suite.chainA.CreateTMClientHeader(chainID, int64(heightPlus1.RevisionHeight), height, suite.headerTime, suite.valSet, suite.valSet, signers) - // make current time pass trusting period from last timestamp on clientstate - currentTime = suite.now.Add(trustingPeriod) - }, - expPass: false, - }, - { - name: "unsuccessful update: header timestamp is past current timestamp", - setup: func() { - clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash) - newHeader = suite.chainA.CreateTMClientHeader(chainID, int64(heightPlus1.RevisionHeight), height, suite.now.Add(time.Minute), suite.valSet, suite.valSet, signers) - currentTime = suite.now - }, - expPass: false, - }, - { - name: "unsuccessful update: header timestamp is not past last client timestamp", - setup: func() { - clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash) - newHeader = suite.chainA.CreateTMClientHeader(chainID, int64(heightPlus1.RevisionHeight), height, suite.clientTime, suite.valSet, suite.valSet, signers) - currentTime = suite.now - }, - expPass: false, - }, - { - name: "header basic validation failed", - setup: func() { - clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, height, commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash) - newHeader = suite.chainA.CreateTMClientHeader(chainID, int64(heightPlus1.RevisionHeight), height, suite.headerTime, suite.valSet, suite.valSet, signers) - // cause new header to fail validatebasic by changing commit height to mismatch header height - newHeader.SignedHeader.Commit.Height = revisionHeight - 1 - currentTime = suite.now - }, - expPass: false, - }, - { - name: "header height < consensus height", - setup: func() { - clientState = types.NewClientState(chainID, types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, clienttypes.NewHeight(height.RevisionNumber, heightPlus5.RevisionHeight), commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - consensusState = types.NewConsensusState(suite.clientTime, commitmenttypes.NewMerkleRoot(suite.header.Header.GetAppHash()), suite.valsHash) - // Make new header at height less than latest client state - newHeader = suite.chainA.CreateTMClientHeader(chainID, int64(heightMinus1.RevisionHeight), height, suite.headerTime, suite.valSet, suite.valSet, signers) - currentTime = suite.now - }, - expPass: false, - }, - } - - for i, tc := range testCases { - tc := tc - - consStateHeight = height // must be explicitly changed - // setup test - tc.setup() - - // Set current timestamp in context - ctx := suite.chainA.GetContext().WithBlockTime(currentTime) - - // Set trusted consensus state in client store - suite.chainA.App.IBCKeeper.ClientKeeper.SetClientConsensusState(ctx, clientID, consStateHeight, consensusState) - - height := newHeader.GetHeight() - expectedConsensus := &types.ConsensusState{ - Timestamp: newHeader.GetTime(), - Root: commitmenttypes.NewMerkleRoot(newHeader.Header.GetAppHash()), - NextValidatorsHash: newHeader.Header.NextValidatorsHash, - } - - newClientState, consensusState, err := clientState.CheckHeaderAndUpdateState( - ctx, - suite.cdc, - suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), clientID), // pass in clientID prefixed clientStore - newHeader, - ) - - if tc.expPass { - suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name) - - // Determine if clientState should be updated or not - // TODO: check the entire Height struct once GetLatestHeight returns clienttypes.Height - if height.GT(clientState.LatestHeight) { - // Header Height is greater than clientState latest Height, clientState should be updated with header.GetHeight() - suite.Require().Equal(height, newClientState.GetLatestHeight(), "clientstate height did not update") - } else { - // Update will add past consensus state, clientState should not be updated at all - suite.Require().Equal(clientState.LatestHeight, newClientState.GetLatestHeight(), "client state height updated for past header") - } - - suite.Require().Equal(expectedConsensus, consensusState, "valid test case %d failed: %s", i, tc.name) - } else { - suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name) - suite.Require().Nil(newClientState, "invalid test case %d passed: %s", i, tc.name) - suite.Require().Nil(consensusState, "invalid test case %d passed: %s", i, tc.name) - } - } -} diff --git a/x/ibc/light-clients/07-tendermint/types/upgrade.go b/x/ibc/light-clients/07-tendermint/types/upgrade.go deleted file mode 100644 index 161b725da16e..000000000000 --- a/x/ibc/light-clients/07-tendermint/types/upgrade.go +++ /dev/null @@ -1,156 +0,0 @@ -package types - -import ( - "fmt" - - "github.com/cosmos/cosmos-sdk/codec" - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - 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/core/exported" - upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" -) - -// VerifyUpgradeAndUpdateState checks if the upgraded client has been committed by the current client -// It will zero out all client-specific fields (e.g. TrustingPeriod and verify all data -// in client state that must be the same across all valid Tendermint clients for the new chain. -// VerifyUpgrade will return an error if: -// - the upgradedClient is not a Tendermint ClientState -// - the lastest height of the client state does not have the same revision number or has a greater -// height than the committed client. -// - the height of upgraded client is not greater than that of current client -// - the latest height of the new client does not match or is greater than the height in committed client -// - any Tendermint chain specified parameter in upgraded client such as ChainID, UnbondingPeriod, -// and ProofSpecs do not match parameters set by committed client -func (cs ClientState) VerifyUpgradeAndUpdateState( - ctx sdk.Context, cdc codec.BinaryMarshaler, clientStore sdk.KVStore, - upgradedClient exported.ClientState, upgradedConsState exported.ConsensusState, - proofUpgradeClient, proofUpgradeConsState []byte, -) (exported.ClientState, exported.ConsensusState, error) { - if len(cs.UpgradePath) == 0 { - return nil, nil, sdkerrors.Wrap(clienttypes.ErrInvalidUpgradeClient, "cannot upgrade client, no upgrade path set") - } - - // last height of current counterparty chain must be client's latest height - lastHeight := cs.GetLatestHeight() - - if !upgradedClient.GetLatestHeight().GT(lastHeight) { - return nil, nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidHeight, "upgraded client height %s must be at greater than current client height %s", - upgradedClient.GetLatestHeight(), lastHeight) - } - - // upgraded client state and consensus state must be IBC tendermint client state and consensus state - // this may be modified in the future to upgrade to a new IBC tendermint type - // counterparty must also commit to the upgraded consensus state at a sub-path under the upgrade path specified - tmUpgradeClient, ok := upgradedClient.(*ClientState) - if !ok { - return nil, nil, sdkerrors.Wrapf(clienttypes.ErrInvalidClientType, "upgraded client must be Tendermint client. expected: %T got: %T", - &ClientState{}, upgradedClient) - } - tmUpgradeConsState, ok := upgradedConsState.(*ConsensusState) - if !ok { - return nil, nil, sdkerrors.Wrapf(clienttypes.ErrInvalidConsensus, "upgraded consensus state must be Tendermint consensus state. expected %T, got: %T", - &ConsensusState{}, upgradedConsState) - } - - // unmarshal proofs - var merkleProofClient, merkleProofConsState commitmenttypes.MerkleProof - if err := cdc.UnmarshalBinaryBare(proofUpgradeClient, &merkleProofClient); err != nil { - return nil, nil, sdkerrors.Wrapf(commitmenttypes.ErrInvalidProof, "could not unmarshal client merkle proof: %v", err) - } - if err := cdc.UnmarshalBinaryBare(proofUpgradeConsState, &merkleProofConsState); err != nil { - return nil, nil, sdkerrors.Wrapf(commitmenttypes.ErrInvalidProof, "could not unmarshal consensus state merkle proof: %v", err) - } - - // Must prove against latest consensus state to ensure we are verifying against latest upgrade plan - // This verifies that upgrade is intended for the provided revision, since committed client must exist - // at this consensus state - consState, err := GetConsensusState(clientStore, cdc, lastHeight) - if err != nil { - return nil, nil, sdkerrors.Wrap(err, "could not retrieve consensus state for lastHeight") - } - - if cs.IsExpired(consState.Timestamp, ctx.BlockTime()) { - return nil, nil, sdkerrors.Wrap(clienttypes.ErrInvalidClient, "cannot upgrade an expired client") - } - - // Verify client proof - bz, err := cdc.MarshalInterface(upgradedClient) - if err != nil { - return nil, nil, sdkerrors.Wrapf(clienttypes.ErrInvalidClient, "could not marshal client state: %v", err) - } - // construct clientState Merkle path - upgradeClientPath := constructUpgradeClientMerklePath(cs.UpgradePath, lastHeight) - if err := merkleProofClient.VerifyMembership(cs.ProofSpecs, consState.GetRoot(), upgradeClientPath, bz); err != nil { - return nil, nil, sdkerrors.Wrapf(err, "client state proof failed. Path: %s", upgradeClientPath.Pretty()) - } - - // Verify consensus state proof - bz, err = cdc.MarshalInterface(upgradedConsState) - if err != nil { - return nil, nil, sdkerrors.Wrapf(clienttypes.ErrInvalidConsensus, "could not marshal consensus state: %v", err) - } - // construct consensus state Merkle path - upgradeConsStatePath := constructUpgradeConsStateMerklePath(cs.UpgradePath, lastHeight) - if err := merkleProofConsState.VerifyMembership(cs.ProofSpecs, consState.GetRoot(), upgradeConsStatePath, bz); err != nil { - return nil, nil, sdkerrors.Wrapf(err, "consensus state proof failed. Path: %s", upgradeConsStatePath.Pretty()) - } - - // Construct new client state and consensus state - // Relayer chosen client parameters are ignored. - // All chain-chosen parameters come from committed client, all client-chosen parameters - // come from current client. - newClientState := NewClientState( - tmUpgradeClient.ChainId, cs.TrustLevel, cs.TrustingPeriod, tmUpgradeClient.UnbondingPeriod, - cs.MaxClockDrift, tmUpgradeClient.LatestHeight, tmUpgradeClient.ProofSpecs, tmUpgradeClient.UpgradePath, - cs.AllowUpdateAfterExpiry, cs.AllowUpdateAfterMisbehaviour, - ) - - if err := newClientState.Validate(); err != nil { - return nil, nil, sdkerrors.Wrap(err, "updated client state failed basic validation") - } - - // The new consensus state is merely used as a trusted kernel against which headers on the new - // chain can be verified. The root is empty as it cannot be known in advance, thus no proof verification will pass. - // The timestamp and the NextValidatorsHash of the consensus state is the blocktime and NextValidatorsHash - // of the last block committed by the old chain. This will allow the first block of the new chain to be verified against - // the last validators of the old chain so long as it is submitted within the TrustingPeriod of this client. - // NOTE: We do not set processed time for this consensus state since this consensus state should not be used for packet verification - // as the root is empty. The next consensus state submitted using update will be usable for packet-verification. - newConsState := NewConsensusState( - tmUpgradeConsState.Timestamp, commitmenttypes.MerkleRoot{}, tmUpgradeConsState.NextValidatorsHash, - ) - - return newClientState, newConsState, nil -} - -// construct MerklePath for the committed client from upgradePath -func constructUpgradeClientMerklePath(upgradePath []string, lastHeight exported.Height) commitmenttypes.MerklePath { - // copy all elements from upgradePath except final element - clientPath := make([]string, len(upgradePath)-1) - copy(clientPath, upgradePath) - - // append lastHeight and `upgradedClient` to last key of upgradePath and use as lastKey of clientPath - // this will create the IAVL key that is used to store client in upgrade store - lastKey := upgradePath[len(upgradePath)-1] - appendedKey := fmt.Sprintf("%s/%d/%s", lastKey, lastHeight.GetRevisionHeight(), upgradetypes.KeyUpgradedClient) - - clientPath = append(clientPath, appendedKey) - return commitmenttypes.NewMerklePath(clientPath...) -} - -// construct MerklePath for the committed consensus state from upgradePath -func constructUpgradeConsStateMerklePath(upgradePath []string, lastHeight exported.Height) commitmenttypes.MerklePath { - // copy all elements from upgradePath except final element - consPath := make([]string, len(upgradePath)-1) - copy(consPath, upgradePath) - - // append lastHeight and `upgradedClient` to last key of upgradePath and use as lastKey of clientPath - // this will create the IAVL key that is used to store client in upgrade store - lastKey := upgradePath[len(upgradePath)-1] - appendedKey := fmt.Sprintf("%s/%d/%s", lastKey, lastHeight.GetRevisionHeight(), upgradetypes.KeyUpgradedConsState) - - consPath = append(consPath, appendedKey) - return commitmenttypes.NewMerklePath(consPath...) -} diff --git a/x/ibc/light-clients/07-tendermint/types/upgrade_test.go b/x/ibc/light-clients/07-tendermint/types/upgrade_test.go deleted file mode 100644 index 8a7623f94301..000000000000 --- a/x/ibc/light-clients/07-tendermint/types/upgrade_test.go +++ /dev/null @@ -1,474 +0,0 @@ -package types_test - -import ( - 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/core/exported" - "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" - upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" -) - -func (suite *TendermintTestSuite) TestVerifyUpgrade() { - var ( - upgradedClient exported.ClientState - upgradedConsState exported.ConsensusState - lastHeight clienttypes.Height - clientA string - proofUpgradedClient, proofUpgradedConsState []byte - upgradedClientBz, upgradedConsStateBz []byte - err error - ) - - testCases := []struct { - name string - setup func() - expPass bool - }{ - { - name: "successful upgrade", - setup: func() { - // upgrade Height is at next block - lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) - - // zero custom fields and store in upgrade store - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) - suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) - - // commit upgrade store changes and update clients - - suite.coordinator.CommitBlock(suite.chainB) - err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - suite.Require().NoError(err) - - cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA) - suite.Require().True(found) - - proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - }, - expPass: true, - }, - { - name: "successful upgrade to same revision", - setup: func() { - upgradedHeight := clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+2)) - upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, upgradedHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - upgradedClient = upgradedClient.ZeroCustomFields() - upgradedClientBz, err = clienttypes.MarshalClientState(suite.chainA.App.AppCodec(), upgradedClient) - suite.Require().NoError(err) - - // upgrade Height is at next block - lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) - - // zero custom fields and store in upgrade store - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) - suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) - - // commit upgrade store changes and update clients - - suite.coordinator.CommitBlock(suite.chainB) - err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - suite.Require().NoError(err) - - cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA) - suite.Require().True(found) - - proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - }, - expPass: true, - }, - - { - name: "unsuccessful upgrade: upgrade height revision height is more than the current client revision height", - setup: func() { - // upgrade Height is 10 blocks from now - lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+10)) - - // zero custom fields and store in upgrade store - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) - suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) - - // commit upgrade store changes and update clients - - suite.coordinator.CommitBlock(suite.chainB) - err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - suite.Require().NoError(err) - - cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA) - suite.Require().True(found) - - proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - }, - expPass: false, - }, - { - name: "unsuccessful upgrade: committed client does not have zeroed custom fields", - setup: func() { - // non-zeroed upgrade client - upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - upgradedClientBz, err = clienttypes.MarshalClientState(suite.chainA.App.AppCodec(), upgradedClient) - suite.Require().NoError(err) - - // upgrade Height is at next block - lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) - - // zero custom fields and store in upgrade store - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) - suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) - - // commit upgrade store changes and update clients - - suite.coordinator.CommitBlock(suite.chainB) - err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - suite.Require().NoError(err) - - cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA) - suite.Require().True(found) - - proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - }, - expPass: false, - }, - { - name: "unsuccessful upgrade: chain-specified parameters do not match committed client", - setup: func() { - // upgrade Height is at next block - lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) - - // zero custom fields and store in upgrade store - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) - suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) - - // change upgradedClient client-specified parameters - upgradedClient = types.NewClientState("wrongchainID", types.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, true, true) - - suite.coordinator.CommitBlock(suite.chainB) - err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - suite.Require().NoError(err) - - cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA) - suite.Require().True(found) - - proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - }, - expPass: false, - }, - { - name: "unsuccessful upgrade: client-specified parameters do not match previous client", - setup: func() { - // zero custom fields and store in upgrade store - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) - suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) - - // change upgradedClient client-specified parameters - upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, ubdPeriod, ubdPeriod+trustingPeriod, maxClockDrift+5, lastHeight, commitmenttypes.GetSDKSpecs(), upgradePath, true, false) - - suite.coordinator.CommitBlock(suite.chainB) - err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - suite.Require().NoError(err) - - cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA) - suite.Require().True(found) - - proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - }, - expPass: false, - }, - { - name: "unsuccessful upgrade: relayer-submitted consensus state does not match counterparty-committed consensus state", - setup: func() { - // upgrade Height is at next block - lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) - - // zero custom fields and store in upgrade store - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) - suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) - - // change submitted upgradedConsensusState - upgradedConsState = &types.ConsensusState{ - NextValidatorsHash: []byte("maliciousValidators"), - } - - // commit upgrade store changes and update clients - - suite.coordinator.CommitBlock(suite.chainB) - err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - suite.Require().NoError(err) - - cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA) - suite.Require().True(found) - - proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - }, - expPass: false, - }, - { - name: "unsuccessful upgrade: client proof unmarshal failed", - setup: func() { - suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) - - cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA) - suite.Require().True(found) - - proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - - proofUpgradedClient = []byte("proof") - }, - expPass: false, - }, - { - name: "unsuccessful upgrade: consensus state proof unmarshal failed", - setup: func() { - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) - - cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA) - suite.Require().True(found) - - proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - - proofUpgradedConsState = []byte("proof") - }, - expPass: false, - }, - { - name: "unsuccessful upgrade: client proof verification failed", - setup: func() { - // do not store upgraded client - - // upgrade Height is at next block - lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) - - suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) - - cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA) - suite.Require().True(found) - - proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - }, - expPass: false, - }, - { - name: "unsuccessful upgrade: consensus state proof verification failed", - setup: func() { - // do not store upgraded client - - // upgrade Height is at next block - lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) - - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) - - cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA) - suite.Require().True(found) - - proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - }, - expPass: false, - }, - { - name: "unsuccessful upgrade: upgrade path is empty", - setup: func() { - // upgrade Height is at next block - lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) - - // zero custom fields and store in upgrade store - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) - - // commit upgrade store changes and update clients - - suite.coordinator.CommitBlock(suite.chainB) - err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - suite.Require().NoError(err) - - cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA) - suite.Require().True(found) - - proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - - // SetClientState with empty upgrade path - tmClient, _ := cs.(*types.ClientState) - tmClient.UpgradePath = []string{""} - suite.chainA.App.IBCKeeper.ClientKeeper.SetClientState(suite.chainA.GetContext(), clientA, tmClient) - }, - expPass: false, - }, - { - name: "unsuccessful upgrade: upgraded height is not greater than current height", - setup: func() { - // upgrade Height is at next block - lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) - - // zero custom fields and store in upgrade store - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) - - // commit upgrade store changes and update clients - - suite.coordinator.CommitBlock(suite.chainB) - err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - suite.Require().NoError(err) - - cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA) - suite.Require().True(found) - - proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - }, - expPass: false, - }, - { - name: "unsuccessful upgrade: consensus state for upgrade height cannot be found", - setup: func() { - // upgrade Height is at next block - lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+100)) - - // zero custom fields and store in upgrade store - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) - - // commit upgrade store changes and update clients - - suite.coordinator.CommitBlock(suite.chainB) - err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - suite.Require().NoError(err) - - cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA) - suite.Require().True(found) - - proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - }, - expPass: false, - }, - { - name: "unsuccessful upgrade: client is expired", - setup: func() { - // zero custom fields and store in upgrade store - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) - - // commit upgrade store changes and update clients - - suite.coordinator.CommitBlock(suite.chainB) - err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - suite.Require().NoError(err) - - // expire chainB's client - suite.chainA.ExpireClient(ubdPeriod) - - cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA) - suite.Require().True(found) - - proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - }, - expPass: false, - }, - { - name: "unsuccessful upgrade: updated unbonding period is equal to trusting period", - setup: func() { - // upgrade Height is at next block - lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) - - // zero custom fields and store in upgrade store - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) - - // commit upgrade store changes and update clients - - suite.coordinator.CommitBlock(suite.chainB) - err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - suite.Require().NoError(err) - - cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA) - suite.Require().True(found) - - proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - }, - expPass: false, - }, - { - name: "unsuccessful upgrade: final client is not valid", - setup: func() { - // new client has smaller unbonding period such that old trusting period is no longer valid - upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - upgradedClientBz, err = clienttypes.MarshalClientState(suite.chainA.App.AppCodec(), upgradedClient) - suite.Require().NoError(err) - - // upgrade Height is at next block - lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContext().BlockHeight()+1)) - - // zero custom fields and store in upgrade store - suite.chainB.App.UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) - suite.chainB.App.UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) - - // commit upgrade store changes and update clients - - suite.coordinator.CommitBlock(suite.chainB) - err := suite.coordinator.UpdateClient(suite.chainA, suite.chainB, clientA, exported.Tendermint) - suite.Require().NoError(err) - - cs, found := suite.chainA.App.IBCKeeper.ClientKeeper.GetClientState(suite.chainA.GetContext(), clientA) - suite.Require().True(found) - - proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) - }, - expPass: false, - }, - } - - for _, tc := range testCases { - tc := tc - - // reset suite - suite.SetupTest() - - clientA, _ = suite.coordinator.SetupClients(suite.chainA, suite.chainB, exported.Tendermint) - upgradedClient = types.NewClientState("newChainId", types.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), upgradePath, false, false) - upgradedClient = upgradedClient.ZeroCustomFields() - upgradedClientBz, err = clienttypes.MarshalClientState(suite.chainA.App.AppCodec(), upgradedClient) - suite.Require().NoError(err) - - upgradedConsState = &types.ConsensusState{ - NextValidatorsHash: []byte("nextValsHash"), - } - upgradedConsStateBz, err = clienttypes.MarshalConsensusState(suite.chainA.App.AppCodec(), upgradedConsState) - suite.Require().NoError(err) - - tc.setup() - - cs := suite.chainA.GetClientState(clientA) - clientStore := suite.chainA.App.IBCKeeper.ClientKeeper.ClientStore(suite.chainA.GetContext(), clientA) - - // Call ZeroCustomFields on upgraded clients to clear any client-chosen parameters in test-case upgradedClient - upgradedClient = upgradedClient.ZeroCustomFields() - - clientState, consensusState, err := cs.VerifyUpgradeAndUpdateState( - suite.chainA.GetContext(), - suite.cdc, - clientStore, - upgradedClient, - upgradedConsState, - proofUpgradedClient, - proofUpgradedConsState, - ) - - if tc.expPass { - suite.Require().NoError(err, "verify upgrade failed on valid case: %s", tc.name) - suite.Require().NotNil(clientState, "verify upgrade failed on valid case: %s", tc.name) - suite.Require().NotNil(consensusState, "verify upgrade failed on valid case: %s", tc.name) - } else { - suite.Require().Error(err, "verify upgrade passed on invalid case: %s", tc.name) - suite.Require().Nil(clientState, "verify upgrade passed on invalid case: %s", tc.name) - - suite.Require().Nil(consensusState, "verify upgrade passed on invalid case: %s", tc.name) - - } - } -} diff --git a/x/ibc/light-clients/09-localhost/doc.go b/x/ibc/light-clients/09-localhost/doc.go deleted file mode 100644 index 40a0f0608670..000000000000 --- a/x/ibc/light-clients/09-localhost/doc.go +++ /dev/null @@ -1,5 +0,0 @@ -/* -Package localhost implements a concrete `ConsensusState`, `Header`, -`Misbehaviour` and `Equivocation` types for the loop-back client. -*/ -package localhost diff --git a/x/ibc/light-clients/09-localhost/module.go b/x/ibc/light-clients/09-localhost/module.go deleted file mode 100644 index 57b9c5bb2639..000000000000 --- a/x/ibc/light-clients/09-localhost/module.go +++ /dev/null @@ -1,10 +0,0 @@ -package localhost - -import ( - "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/09-localhost/types" -) - -// Name returns the IBC client name -func Name() string { - return types.SubModuleName -} diff --git a/x/ibc/light-clients/09-localhost/types/client_state.go b/x/ibc/light-clients/09-localhost/types/client_state.go deleted file mode 100644 index 5a4a41a17988..000000000000 --- a/x/ibc/light-clients/09-localhost/types/client_state.go +++ /dev/null @@ -1,346 +0,0 @@ -package types - -import ( - "bytes" - "encoding/binary" - "reflect" - "strings" - - ics23 "github.com/confio/ics23/go" - - "github.com/cosmos/cosmos-sdk/codec" - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -var _ exported.ClientState = (*ClientState)(nil) - -// NewClientState creates a new ClientState instance -func NewClientState(chainID string, height clienttypes.Height) *ClientState { - return &ClientState{ - ChainId: chainID, - Height: height, - } -} - -// GetChainID returns an empty string -func (cs ClientState) GetChainID() string { - return cs.ChainId -} - -// ClientType is localhost. -func (cs ClientState) ClientType() string { - return exported.Localhost -} - -// GetLatestHeight returns the latest height stored. -func (cs ClientState) GetLatestHeight() exported.Height { - return cs.Height -} - -// IsFrozen returns false. -func (cs ClientState) IsFrozen() bool { - return false -} - -// GetFrozenHeight returns an uninitialized IBC Height. -func (cs ClientState) GetFrozenHeight() exported.Height { - return clienttypes.ZeroHeight() -} - -// Validate performs a basic validation of the client state fields. -func (cs ClientState) Validate() error { - if strings.TrimSpace(cs.ChainId) == "" { - return sdkerrors.Wrap(sdkerrors.ErrInvalidChainID, "chain id cannot be blank") - } - if cs.Height.RevisionHeight == 0 { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidHeight, "local revision height cannot be zero") - } - return nil -} - -// GetProofSpecs returns nil since localhost does not have to verify proofs -func (cs ClientState) GetProofSpecs() []*ics23.ProofSpec { - return nil -} - -// ZeroCustomFields returns the same client state since there are no custom fields in localhost -func (cs ClientState) ZeroCustomFields() exported.ClientState { - return &cs -} - -// Initialize ensures that initial consensus state for localhost is nil -func (cs ClientState) Initialize(_ sdk.Context, _ codec.BinaryMarshaler, _ sdk.KVStore, consState exported.ConsensusState) error { - if consState != nil { - return sdkerrors.Wrap(clienttypes.ErrInvalidConsensus, "initial consensus state for localhost must be nil.") - } - return nil -} - -// ExportMetadata is a no-op for localhost client -func (cs ClientState) ExportMetadata(_ sdk.KVStore) []exported.GenesisMetadata { - return nil -} - -// CheckHeaderAndUpdateState updates the localhost client. It only needs access to the context -func (cs *ClientState) CheckHeaderAndUpdateState( - ctx sdk.Context, _ codec.BinaryMarshaler, _ sdk.KVStore, _ exported.Header, -) (exported.ClientState, exported.ConsensusState, error) { - // use the chain ID from context since the localhost client is from the running chain (i.e self). - cs.ChainId = ctx.ChainID() - revision := clienttypes.ParseChainID(cs.ChainId) - cs.Height = clienttypes.NewHeight(revision, uint64(ctx.BlockHeight())) - return cs, nil, nil -} - -// CheckMisbehaviourAndUpdateState implements ClientState -// Since localhost is the client of the running chain, misbehaviour cannot be submitted to it -// Thus, CheckMisbehaviourAndUpdateState returns an error for localhost -func (cs ClientState) CheckMisbehaviourAndUpdateState( - _ sdk.Context, _ codec.BinaryMarshaler, _ sdk.KVStore, _ exported.Misbehaviour, -) (exported.ClientState, error) { - return nil, sdkerrors.Wrap(clienttypes.ErrInvalidMisbehaviour, "cannot submit misbehaviour to localhost client") -} - -// CheckSubstituteAndUpdateState returns an error. The localhost cannot be modified by -// proposals. -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 -func (cs ClientState) VerifyUpgradeAndUpdateState( - _ sdk.Context, _ codec.BinaryMarshaler, _ sdk.KVStore, - _ exported.ClientState, _ exported.ConsensusState, _, _ []byte, -) (exported.ClientState, exported.ConsensusState, error) { - return nil, nil, sdkerrors.Wrap(clienttypes.ErrInvalidUpgradeClient, "cannot upgrade localhost client") -} - -// VerifyClientState verifies that the localhost client state is stored locally -func (cs ClientState) VerifyClientState( - store sdk.KVStore, cdc codec.BinaryMarshaler, - _ exported.Height, _ exported.Prefix, _ string, _ []byte, clientState exported.ClientState, -) error { - path := host.KeyClientState - bz := store.Get([]byte(path)) - if bz == nil { - return sdkerrors.Wrapf(clienttypes.ErrFailedClientStateVerification, - "not found for path: %s", path) - } - - selfClient := clienttypes.MustUnmarshalClientState(cdc, bz) - - if !reflect.DeepEqual(selfClient, clientState) { - return sdkerrors.Wrapf(clienttypes.ErrFailedClientStateVerification, - "stored clientState != provided clientState: \n%v\n≠\n%v", - selfClient, clientState, - ) - } - return nil -} - -// VerifyClientConsensusState returns nil since a local host client does not store consensus -// states. -func (cs ClientState) VerifyClientConsensusState( - sdk.KVStore, codec.BinaryMarshaler, - exported.Height, string, exported.Height, exported.Prefix, - []byte, exported.ConsensusState, -) error { - return nil -} - -// VerifyConnectionState verifies a proof of the connection state of the -// specified connection end stored locally. -func (cs ClientState) VerifyConnectionState( - store sdk.KVStore, - cdc codec.BinaryMarshaler, - _ exported.Height, - _ exported.Prefix, - _ []byte, - connectionID string, - connectionEnd exported.ConnectionI, -) error { - path := host.ConnectionKey(connectionID) - bz := store.Get(path) - if bz == nil { - return sdkerrors.Wrapf(clienttypes.ErrFailedConnectionStateVerification, "not found for path %s", path) - } - - var prevConnection connectiontypes.ConnectionEnd - err := cdc.UnmarshalBinaryBare(bz, &prevConnection) - if err != nil { - return err - } - - if !reflect.DeepEqual(&prevConnection, connectionEnd) { - return sdkerrors.Wrapf( - clienttypes.ErrFailedConnectionStateVerification, - "connection end ≠ previous stored connection: \n%v\n≠\n%v", connectionEnd, prevConnection, - ) - } - - return nil -} - -// VerifyChannelState verifies a proof of the channel state of the specified -// channel end, under the specified port, stored on the local machine. -func (cs ClientState) VerifyChannelState( - store sdk.KVStore, - cdc codec.BinaryMarshaler, - _ exported.Height, - prefix exported.Prefix, - _ []byte, - portID, - channelID string, - channel exported.ChannelI, -) error { - path := host.ChannelKey(portID, channelID) - bz := store.Get(path) - if bz == nil { - return sdkerrors.Wrapf(clienttypes.ErrFailedChannelStateVerification, "not found for path %s", path) - } - - var prevChannel channeltypes.Channel - err := cdc.UnmarshalBinaryBare(bz, &prevChannel) - if err != nil { - return err - } - - if !reflect.DeepEqual(&prevChannel, channel) { - return sdkerrors.Wrapf( - clienttypes.ErrFailedChannelStateVerification, - "channel end ≠ previous stored channel: \n%v\n≠\n%v", channel, prevChannel, - ) - } - - return nil -} - -// VerifyPacketCommitment verifies a proof of an outgoing packet commitment at -// the specified port, specified channel, and specified sequence. -func (cs ClientState) VerifyPacketCommitment( - store sdk.KVStore, - _ codec.BinaryMarshaler, - _ exported.Height, - _ uint64, - _ uint64, - _ exported.Prefix, - _ []byte, - portID, - channelID string, - sequence uint64, - commitmentBytes []byte, -) error { - path := host.PacketCommitmentKey(portID, channelID, sequence) - - data := store.Get(path) - if len(data) == 0 { - return sdkerrors.Wrapf(clienttypes.ErrFailedPacketCommitmentVerification, "not found for path %s", path) - } - - if !bytes.Equal(data, commitmentBytes) { - return sdkerrors.Wrapf( - clienttypes.ErrFailedPacketCommitmentVerification, - "commitment ≠ previous commitment: \n%X\n≠\n%X", commitmentBytes, data, - ) - } - - return nil -} - -// VerifyPacketAcknowledgement verifies a proof of an incoming packet -// acknowledgement at the specified port, specified channel, and specified sequence. -func (cs ClientState) VerifyPacketAcknowledgement( - store sdk.KVStore, - _ codec.BinaryMarshaler, - _ exported.Height, - _ uint64, - _ uint64, - _ exported.Prefix, - _ []byte, - portID, - channelID string, - sequence uint64, - acknowledgement []byte, -) error { - path := host.PacketAcknowledgementKey(portID, channelID, sequence) - - data := store.Get(path) - if len(data) == 0 { - return sdkerrors.Wrapf(clienttypes.ErrFailedPacketAckVerification, "not found for path %s", path) - } - - if !bytes.Equal(data, acknowledgement) { - return sdkerrors.Wrapf( - clienttypes.ErrFailedPacketAckVerification, - "ak bytes ≠ previous ack: \n%X\n≠\n%X", acknowledgement, data, - ) - } - - return nil -} - -// VerifyPacketReceiptAbsence verifies a proof of the absence of an -// incoming packet receipt at the specified port, specified channel, and -// specified sequence. -func (cs ClientState) VerifyPacketReceiptAbsence( - store sdk.KVStore, - _ codec.BinaryMarshaler, - _ exported.Height, - _ uint64, - _ uint64, - _ exported.Prefix, - _ []byte, - portID, - channelID string, - sequence uint64, -) error { - path := host.PacketReceiptKey(portID, channelID, sequence) - - data := store.Get(path) - if data != nil { - return sdkerrors.Wrap(clienttypes.ErrFailedPacketReceiptVerification, "expected no packet receipt") - } - - return nil -} - -// VerifyNextSequenceRecv verifies a proof of the next sequence number to be -// received of the specified channel at the specified port. -func (cs ClientState) VerifyNextSequenceRecv( - store sdk.KVStore, - _ codec.BinaryMarshaler, - _ exported.Height, - _ uint64, - _ uint64, - _ exported.Prefix, - _ []byte, - portID, - channelID string, - nextSequenceRecv uint64, -) error { - path := host.NextSequenceRecvKey(portID, channelID) - - data := store.Get(path) - if len(data) == 0 { - return sdkerrors.Wrapf(clienttypes.ErrFailedNextSeqRecvVerification, "not found for path %s", path) - } - - prevSequenceRecv := binary.BigEndian.Uint64(data) - if prevSequenceRecv != nextSequenceRecv { - return sdkerrors.Wrapf( - clienttypes.ErrFailedNextSeqRecvVerification, - "next sequence receive ≠ previous stored sequence (%d ≠ %d)", nextSequenceRecv, prevSequenceRecv, - ) - } - - return nil -} 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 deleted file mode 100644 index bc58f62539be..000000000000 --- a/x/ibc/light-clients/09-localhost/types/client_state_test.go +++ /dev/null @@ -1,520 +0,0 @@ -package types_test - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" - "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/09-localhost/types" -) - -const ( - testConnectionID = "connectionid" - testPortID = "testportid" - testChannelID = "testchannelid" - testSequence = 1 -) - -func (suite *LocalhostTestSuite) TestValidate() { - testCases := []struct { - name string - clientState *types.ClientState - expPass bool - }{ - { - name: "valid client", - clientState: types.NewClientState("chainID", clienttypes.NewHeight(3, 10)), - expPass: true, - }, - { - name: "invalid chain id", - clientState: types.NewClientState(" ", clienttypes.NewHeight(3, 10)), - expPass: false, - }, - { - name: "invalid height", - clientState: types.NewClientState("chainID", clienttypes.ZeroHeight()), - expPass: false, - }, - } - - for _, tc := range testCases { - err := tc.clientState.Validate() - if tc.expPass { - suite.Require().NoError(err, tc.name) - } else { - suite.Require().Error(err, tc.name) - } - } -} - -func (suite *LocalhostTestSuite) TestInitialize() { - testCases := []struct { - name string - consState exported.ConsensusState - expPass bool - }{ - { - "valid initialization", - nil, - true, - }, - { - "invalid consenus state", - &ibctmtypes.ConsensusState{}, - false, - }, - } - - clientState := types.NewClientState("chainID", clienttypes.NewHeight(3, 10)) - - for _, tc := range testCases { - err := clientState.Initialize(suite.ctx, suite.cdc, suite.store, tc.consState) - - if tc.expPass { - suite.Require().NoError(err, "valid testcase: %s failed", tc.name) - } else { - suite.Require().Error(err, "invalid testcase: %s passed", tc.name) - } - } -} - -func (suite *LocalhostTestSuite) TestVerifyClientState() { - clientState := types.NewClientState("chainID", clientHeight) - invalidClient := types.NewClientState("chainID", clienttypes.NewHeight(0, 12)) - - testCases := []struct { - name string - clientState *types.ClientState - malleate func() - counterparty *types.ClientState - expPass bool - }{ - { - name: "proof verification success", - clientState: clientState, - malleate: func() { - bz := clienttypes.MustMarshalClientState(suite.cdc, clientState) - suite.store.Set(host.ClientStateKey(), bz) - }, - counterparty: clientState, - expPass: true, - }, - { - name: "proof verification failed: invalid client", - clientState: clientState, - malleate: func() { - bz := clienttypes.MustMarshalClientState(suite.cdc, clientState) - suite.store.Set(host.ClientStateKey(), bz) - }, - counterparty: invalidClient, - expPass: false, - }, - { - name: "proof verification failed: client not stored", - clientState: clientState, - malleate: func() {}, - counterparty: clientState, - expPass: false, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - suite.SetupTest() - tc.malleate() - - err := tc.clientState.VerifyClientState( - suite.store, suite.cdc, clienttypes.NewHeight(0, 10), nil, "", []byte{}, tc.counterparty, - ) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } - -} - -func (suite *LocalhostTestSuite) TestVerifyClientConsensusState() { - clientState := types.NewClientState("chainID", clientHeight) - err := clientState.VerifyClientConsensusState( - nil, nil, nil, "", nil, nil, nil, nil, - ) - suite.Require().NoError(err) -} - -func (suite *LocalhostTestSuite) TestCheckHeaderAndUpdateState() { - clientState := types.NewClientState("chainID", clientHeight) - cs, _, err := clientState.CheckHeaderAndUpdateState(suite.ctx, nil, nil, nil) - suite.Require().NoError(err) - suite.Require().Equal(uint64(0), cs.GetLatestHeight().GetRevisionNumber()) - suite.Require().Equal(suite.ctx.BlockHeight(), int64(cs.GetLatestHeight().GetRevisionHeight())) - suite.Require().Equal(suite.ctx.BlockHeader().ChainID, clientState.ChainId) -} - -func (suite *LocalhostTestSuite) TestMisbehaviourAndUpdateState() { - clientState := types.NewClientState("chainID", clientHeight) - cs, err := clientState.CheckMisbehaviourAndUpdateState(suite.ctx, nil, nil, nil) - suite.Require().Error(err) - suite.Require().Nil(cs) -} - -func (suite *LocalhostTestSuite) TestProposedHeaderAndUpdateState() { - clientState := types.NewClientState("chainID", clientHeight) - cs, err := clientState.CheckSubstituteAndUpdateState(suite.ctx, nil, nil, nil, nil, nil) - suite.Require().Error(err) - suite.Require().Nil(cs) -} - -func (suite *LocalhostTestSuite) TestVerifyConnectionState() { - counterparty := connectiontypes.NewCounterparty("clientB", testConnectionID, commitmenttypes.NewMerklePrefix([]byte("ibc"))) - conn1 := connectiontypes.NewConnectionEnd(connectiontypes.OPEN, "clientA", counterparty, []*connectiontypes.Version{connectiontypes.NewVersion("1", nil)}, 0) - conn2 := connectiontypes.NewConnectionEnd(connectiontypes.OPEN, "clientA", counterparty, []*connectiontypes.Version{connectiontypes.NewVersion("2", nil)}, 0) - - testCases := []struct { - name string - clientState *types.ClientState - malleate func() - connection connectiontypes.ConnectionEnd - expPass bool - }{ - { - name: "proof verification success", - clientState: types.NewClientState("chainID", clientHeight), - malleate: func() { - bz, err := suite.cdc.MarshalBinaryBare(&conn1) - suite.Require().NoError(err) - suite.store.Set(host.ConnectionKey(testConnectionID), bz) - }, - connection: conn1, - expPass: true, - }, - { - name: "proof verification failed: connection not stored", - clientState: types.NewClientState("chainID", clientHeight), - malleate: func() {}, - connection: conn1, - expPass: false, - }, - { - name: "proof verification failed: unmarshal error", - clientState: types.NewClientState("chainID", clientHeight), - malleate: func() { - suite.store.Set(host.ConnectionKey(testConnectionID), []byte("connection")) - }, - connection: conn1, - expPass: false, - }, - { - name: "proof verification failed: different connection stored", - clientState: types.NewClientState("chainID", clientHeight), - malleate: func() { - bz, err := suite.cdc.MarshalBinaryBare(&conn2) - suite.Require().NoError(err) - suite.store.Set(host.ConnectionKey(testConnectionID), bz) - }, - connection: conn1, - expPass: false, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - suite.SetupTest() - tc.malleate() - - err := tc.clientState.VerifyConnectionState( - suite.store, suite.cdc, clientHeight, nil, []byte{}, testConnectionID, &tc.connection, - ) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} - -func (suite *LocalhostTestSuite) TestVerifyChannelState() { - counterparty := channeltypes.NewCounterparty(testPortID, testChannelID) - ch1 := channeltypes.NewChannel(channeltypes.OPEN, channeltypes.ORDERED, counterparty, []string{testConnectionID}, "1.0.0") - ch2 := channeltypes.NewChannel(channeltypes.OPEN, channeltypes.ORDERED, counterparty, []string{testConnectionID}, "2.0.0") - - testCases := []struct { - name string - clientState *types.ClientState - malleate func() - channel channeltypes.Channel - expPass bool - }{ - { - name: "proof verification success", - clientState: types.NewClientState("chainID", clientHeight), - malleate: func() { - bz, err := suite.cdc.MarshalBinaryBare(&ch1) - suite.Require().NoError(err) - suite.store.Set(host.ChannelKey(testPortID, testChannelID), bz) - }, - channel: ch1, - expPass: true, - }, - { - name: "proof verification failed: channel not stored", - clientState: types.NewClientState("chainID", clientHeight), - malleate: func() {}, - channel: ch1, - expPass: false, - }, - { - name: "proof verification failed: unmarshal failed", - clientState: types.NewClientState("chainID", clientHeight), - malleate: func() { - suite.store.Set(host.ChannelKey(testPortID, testChannelID), []byte("channel")) - - }, - channel: ch1, - expPass: false, - }, - { - name: "proof verification failed: different channel stored", - clientState: types.NewClientState("chainID", clientHeight), - malleate: func() { - bz, err := suite.cdc.MarshalBinaryBare(&ch2) - suite.Require().NoError(err) - suite.store.Set(host.ChannelKey(testPortID, testChannelID), bz) - - }, - channel: ch1, - expPass: false, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - suite.SetupTest() - tc.malleate() - - err := tc.clientState.VerifyChannelState( - suite.store, suite.cdc, clientHeight, nil, []byte{}, testPortID, testChannelID, &tc.channel, - ) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} - -func (suite *LocalhostTestSuite) TestVerifyPacketCommitment() { - testCases := []struct { - name string - clientState *types.ClientState - malleate func() - commitment []byte - expPass bool - }{ - { - name: "proof verification success", - clientState: types.NewClientState("chainID", clientHeight), - malleate: func() { - suite.store.Set( - host.PacketCommitmentKey(testPortID, testChannelID, testSequence), []byte("commitment"), - ) - }, - commitment: []byte("commitment"), - expPass: true, - }, - { - name: "proof verification failed: different commitment stored", - clientState: types.NewClientState("chainID", clientHeight), - malleate: func() { - suite.store.Set( - host.PacketCommitmentKey(testPortID, testChannelID, testSequence), []byte("different"), - ) - }, - commitment: []byte("commitment"), - expPass: false, - }, - { - name: "proof verification failed: no commitment stored", - clientState: types.NewClientState("chainID", clientHeight), - malleate: func() {}, - commitment: []byte{}, - expPass: false, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - suite.SetupTest() - tc.malleate() - - err := tc.clientState.VerifyPacketCommitment( - suite.store, suite.cdc, clientHeight, 0, 0, nil, []byte{}, testPortID, testChannelID, testSequence, tc.commitment, - ) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} - -func (suite *LocalhostTestSuite) TestVerifyPacketAcknowledgement() { - testCases := []struct { - name string - clientState *types.ClientState - malleate func() - ack []byte - expPass bool - }{ - { - name: "proof verification success", - clientState: types.NewClientState("chainID", clientHeight), - malleate: func() { - suite.store.Set( - host.PacketAcknowledgementKey(testPortID, testChannelID, testSequence), []byte("acknowledgement"), - ) - }, - ack: []byte("acknowledgement"), - expPass: true, - }, - { - name: "proof verification failed: different ack stored", - clientState: types.NewClientState("chainID", clientHeight), - malleate: func() { - suite.store.Set( - host.PacketAcknowledgementKey(testPortID, testChannelID, testSequence), []byte("different"), - ) - }, - ack: []byte("acknowledgement"), - expPass: false, - }, - { - name: "proof verification failed: no commitment stored", - clientState: types.NewClientState("chainID", clientHeight), - malleate: func() {}, - ack: []byte{}, - expPass: false, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - suite.SetupTest() - tc.malleate() - - err := tc.clientState.VerifyPacketAcknowledgement( - suite.store, suite.cdc, clientHeight, 0, 0, nil, []byte{}, testPortID, testChannelID, testSequence, tc.ack, - ) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} - -func (suite *LocalhostTestSuite) TestVerifyPacketReceiptAbsence() { - clientState := types.NewClientState("chainID", clientHeight) - - err := clientState.VerifyPacketReceiptAbsence( - suite.store, suite.cdc, clientHeight, 0, 0, nil, nil, testPortID, testChannelID, testSequence, - ) - - suite.Require().NoError(err, "receipt absence failed") - - suite.store.Set(host.PacketReceiptKey(testPortID, testChannelID, testSequence), []byte("receipt")) - - err = clientState.VerifyPacketReceiptAbsence( - suite.store, suite.cdc, clientHeight, 0, 0, nil, nil, testPortID, testChannelID, testSequence, - ) - suite.Require().Error(err, "receipt exists in store") -} - -func (suite *LocalhostTestSuite) TestVerifyNextSeqRecv() { - nextSeqRecv := uint64(5) - - testCases := []struct { - name string - clientState *types.ClientState - malleate func() - nextSeqRecv uint64 - expPass bool - }{ - { - name: "proof verification success", - clientState: types.NewClientState("chainID", clientHeight), - malleate: func() { - suite.store.Set( - host.NextSequenceRecvKey(testPortID, testChannelID), - sdk.Uint64ToBigEndian(nextSeqRecv), - ) - }, - nextSeqRecv: nextSeqRecv, - expPass: true, - }, - { - name: "proof verification failed: different nextSeqRecv stored", - clientState: types.NewClientState("chainID", clientHeight), - malleate: func() { - suite.store.Set( - host.NextSequenceRecvKey(testPortID, testChannelID), - sdk.Uint64ToBigEndian(3), - ) - }, - nextSeqRecv: nextSeqRecv, - expPass: false, - }, - { - name: "proof verification failed: no nextSeqRecv stored", - clientState: types.NewClientState("chainID", clientHeight), - malleate: func() {}, - nextSeqRecv: nextSeqRecv, - expPass: false, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - suite.SetupTest() - tc.malleate() - - err := tc.clientState.VerifyNextSequenceRecv( - suite.store, suite.cdc, clientHeight, 0, 0, nil, []byte{}, testPortID, testChannelID, nextSeqRecv, - ) - - if tc.expPass { - suite.Require().NoError(err) - } else { - suite.Require().Error(err) - } - }) - } -} diff --git a/x/ibc/light-clients/09-localhost/types/codec.go b/x/ibc/light-clients/09-localhost/types/codec.go deleted file mode 100644 index b338dfb699ac..000000000000 --- a/x/ibc/light-clients/09-localhost/types/codec.go +++ /dev/null @@ -1,15 +0,0 @@ -package types - -import ( - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -// RegisterInterfaces register the ibc interfaces submodule implementations to protobuf -// Any. -func RegisterInterfaces(registry codectypes.InterfaceRegistry) { - registry.RegisterImplementations( - (*exported.ClientState)(nil), - &ClientState{}, - ) -} diff --git a/x/ibc/light-clients/09-localhost/types/errors.go b/x/ibc/light-clients/09-localhost/types/errors.go deleted file mode 100644 index 57ad7c1f6a68..000000000000 --- a/x/ibc/light-clients/09-localhost/types/errors.go +++ /dev/null @@ -1,10 +0,0 @@ -package types - -import ( - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" -) - -// Localhost sentinel errors -var ( - ErrConsensusStatesNotStored = sdkerrors.Register(SubModuleName, 2, "localhost does not store consensus states") -) diff --git a/x/ibc/light-clients/09-localhost/types/keys.go b/x/ibc/light-clients/09-localhost/types/keys.go deleted file mode 100644 index 2fe7c7e48f5b..000000000000 --- a/x/ibc/light-clients/09-localhost/types/keys.go +++ /dev/null @@ -1,6 +0,0 @@ -package types - -const ( - // SubModuleName for the localhost (loopback) client - SubModuleName = "localhost" -) diff --git a/x/ibc/light-clients/09-localhost/types/localhost.pb.go b/x/ibc/light-clients/09-localhost/types/localhost.pb.go deleted file mode 100644 index 53f01758492b..000000000000 --- a/x/ibc/light-clients/09-localhost/types/localhost.pb.go +++ /dev/null @@ -1,369 +0,0 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: ibc/lightclients/localhost/v1/localhost.proto - -package types - -import ( - fmt "fmt" - types "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - _ "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 - -// ClientState defines a loopback (localhost) client. It requires (read-only) -// access to keys outside the client prefix. -type ClientState struct { - // self chain ID - ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty" yaml:"chain_id"` - // self latest block height - Height types.Height `protobuf:"bytes,2,opt,name=height,proto3" json:"height"` -} - -func (m *ClientState) Reset() { *m = ClientState{} } -func (m *ClientState) String() string { return proto.CompactTextString(m) } -func (*ClientState) ProtoMessage() {} -func (*ClientState) Descriptor() ([]byte, []int) { - return fileDescriptor_acd9f5b22d41bf6d, []int{0} -} -func (m *ClientState) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *ClientState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_ClientState.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 *ClientState) XXX_Merge(src proto.Message) { - xxx_messageInfo_ClientState.Merge(m, src) -} -func (m *ClientState) XXX_Size() int { - return m.Size() -} -func (m *ClientState) XXX_DiscardUnknown() { - xxx_messageInfo_ClientState.DiscardUnknown(m) -} - -var xxx_messageInfo_ClientState proto.InternalMessageInfo - -func init() { - proto.RegisterType((*ClientState)(nil), "ibc.lightclients.localhost.v1.ClientState") -} - -func init() { - proto.RegisterFile("ibc/lightclients/localhost/v1/localhost.proto", fileDescriptor_acd9f5b22d41bf6d) -} - -var fileDescriptor_acd9f5b22d41bf6d = []byte{ - // 279 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0xcd, 0x4c, 0x4a, 0xd6, - 0xcf, 0xc9, 0x4c, 0xcf, 0x28, 0x49, 0xce, 0xc9, 0x4c, 0xcd, 0x2b, 0x29, 0xd6, 0xcf, 0xc9, 0x4f, - 0x4e, 0xcc, 0xc9, 0xc8, 0x2f, 0x2e, 0xd1, 0x2f, 0x33, 0x44, 0x70, 0xf4, 0x0a, 0x8a, 0xf2, 0x4b, - 0xf2, 0x85, 0x64, 0x33, 0x93, 0x92, 0xf5, 0x90, 0x95, 0xeb, 0x21, 0x54, 0x94, 0x19, 0x4a, 0x89, - 0xa4, 0xe7, 0xa7, 0xe7, 0x83, 0x55, 0xea, 0x83, 0x58, 0x10, 0x4d, 0x52, 0xf2, 0x20, 0x3b, 0x92, - 0xf3, 0x8b, 0x52, 0xf5, 0x21, 0x9a, 0x40, 0x06, 0x43, 0x58, 0x10, 0x05, 0x4a, 0xb5, 0x5c, 0xdc, - 0xce, 0x60, 0x7e, 0x70, 0x49, 0x62, 0x49, 0xaa, 0x90, 0x1e, 0x17, 0x47, 0x72, 0x46, 0x62, 0x66, - 0x5e, 0x7c, 0x66, 0x8a, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0xa7, 0x93, 0xf0, 0xa7, 0x7b, 0xf2, 0xfc, - 0x95, 0x89, 0xb9, 0x39, 0x56, 0x4a, 0x30, 0x19, 0xa5, 0x20, 0x76, 0x30, 0xd3, 0x33, 0x45, 0xc8, - 0x82, 0x8b, 0x2d, 0x23, 0x15, 0xe4, 0x26, 0x09, 0x26, 0x05, 0x46, 0x0d, 0x6e, 0x23, 0x29, 0x3d, - 0x90, 0x2b, 0x41, 0x16, 0xea, 0x41, 0xad, 0x29, 0x33, 0xd4, 0xf3, 0x00, 0xab, 0x70, 0x62, 0x39, - 0x71, 0x4f, 0x9e, 0x21, 0x08, 0xaa, 0xde, 0x8a, 0xa5, 0x63, 0x81, 0x3c, 0x83, 0x53, 0xec, 0x89, - 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c, 0xc3, - 0x85, 0xc7, 0x72, 0x0c, 0x37, 0x1e, 0xcb, 0x31, 0x44, 0x39, 0xa7, 0x67, 0x96, 0x64, 0x94, 0x26, - 0xe9, 0x25, 0xe7, 0xe7, 0xea, 0x27, 0xe7, 0x17, 0xe7, 0xe6, 0x17, 0x43, 0x29, 0xdd, 0xe2, 0x94, - 0x6c, 0xfd, 0x0a, 0x7d, 0x78, 0xe0, 0xe9, 0xc2, 0x42, 0xcf, 0xc0, 0x52, 0x17, 0x11, 0x80, 0x25, - 0x95, 0x05, 0xa9, 0xc5, 0x49, 0x6c, 0x60, 0x4f, 0x1a, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0xcd, - 0x7d, 0x91, 0x77, 0x6b, 0x01, 0x00, 0x00, -} - -func (m *ClientState) 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 *ClientState) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *ClientState) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - { - size, err := m.Height.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintLocalhost(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - if len(m.ChainId) > 0 { - i -= len(m.ChainId) - copy(dAtA[i:], m.ChainId) - i = encodeVarintLocalhost(dAtA, i, uint64(len(m.ChainId))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func encodeVarintLocalhost(dAtA []byte, offset int, v uint64) int { - offset -= sovLocalhost(v) - base := offset - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ - } - dAtA[offset] = uint8(v) - return base -} -func (m *ClientState) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.ChainId) - if l > 0 { - n += 1 + l + sovLocalhost(uint64(l)) - } - l = m.Height.Size() - n += 1 + l + sovLocalhost(uint64(l)) - return n -} - -func sovLocalhost(x uint64) (n int) { - return (math_bits.Len64(x|1) + 6) / 7 -} -func sozLocalhost(x uint64) (n int) { - return sovLocalhost(uint64((x << 1) ^ uint64((int64(x) >> 63)))) -} -func (m *ClientState) 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 ErrIntOverflowLocalhost - } - 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: ClientState: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: ClientState: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowLocalhost - } - 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 ErrInvalidLengthLocalhost - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthLocalhost - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ChainId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowLocalhost - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthLocalhost - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthLocalhost - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.Height.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipLocalhost(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthLocalhost - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func skipLocalhost(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, ErrIntOverflowLocalhost - } - 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, ErrIntOverflowLocalhost - } - 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, ErrIntOverflowLocalhost - } - 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, ErrInvalidLengthLocalhost - } - iNdEx += length - case 3: - depth++ - case 4: - if depth == 0 { - return 0, ErrUnexpectedEndOfGroupLocalhost - } - depth-- - case 5: - iNdEx += 4 - default: - return 0, fmt.Errorf("proto: illegal wireType %d", wireType) - } - if iNdEx < 0 { - return 0, ErrInvalidLengthLocalhost - } - if depth == 0 { - return iNdEx, nil - } - } - return 0, io.ErrUnexpectedEOF -} - -var ( - ErrInvalidLengthLocalhost = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowLocalhost = fmt.Errorf("proto: integer overflow") - ErrUnexpectedEndOfGroupLocalhost = fmt.Errorf("proto: unexpected end of group") -) diff --git a/x/ibc/light-clients/09-localhost/types/localhost_test.go b/x/ibc/light-clients/09-localhost/types/localhost_test.go deleted file mode 100644 index 8ebaef843b08..000000000000 --- a/x/ibc/light-clients/09-localhost/types/localhost_test.go +++ /dev/null @@ -1,43 +0,0 @@ -package types_test - -import ( - "testing" - - "github.com/stretchr/testify/suite" - tmproto "github.com/tendermint/tendermint/proto/tendermint/types" - - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/simapp" - sdk "github.com/cosmos/cosmos-sdk/types" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -const ( - height = 4 -) - -var ( - clientHeight = clienttypes.NewHeight(0, 10) -) - -type LocalhostTestSuite struct { - suite.Suite - - cdc codec.Marshaler - ctx sdk.Context - store sdk.KVStore -} - -func (suite *LocalhostTestSuite) SetupTest() { - isCheckTx := false - app := simapp.Setup(isCheckTx) - - suite.cdc = app.AppCodec() - suite.ctx = app.BaseApp.NewContext(isCheckTx, tmproto.Header{Height: 1, ChainID: "ibc-chain"}) - suite.store = app.IBCKeeper.ClientKeeper.ClientStore(suite.ctx, exported.Localhost) -} - -func TestLocalhostTestSuite(t *testing.T) { - suite.Run(t, new(LocalhostTestSuite)) -} diff --git a/x/ibc/spec/README.md b/x/ibc/spec/README.md deleted file mode 100644 index a699c10abdc7..000000000000 --- a/x/ibc/spec/README.md +++ /dev/null @@ -1,114 +0,0 @@ - - -# `ibc` - -## Abstract - -This specification defines the implementation of the IBC protocol on the Cosmos SDK, the -changes made to the specification and where to find each specific ICS spec within -the module. - -For the general specification please refer to the [Interchain Standards](https://github.com/cosmos/ics). - -## Contents - -1. **Applications** - - 1.1. [Transfer](./../applications/transfer/spec/README.md) -2. **[Core](./../core/spec/README.md)** -3. **Light Clients** - - 3.1 [Solo Machine Client](./../light-clients/06-solomachine/spec/README.md) - - 3.2 [Tendermint Client](./../light-clients/07-tendermint/spec/README.md) - - 3.3 [Localhost Client](./../light-clients/09-localhost/spec/README.md) - -## Implementation Details - -As stated above, the IBC implementation on the Cosmos SDK introduces some changes -to the general specification, in order to avoid code duplication and to take -advantage of the SDK architectural components such as the transaction routing -through `Handlers`. - -### Interchain Standards reference - -The following list is a mapping from each Interchain Standard to their implementation -in the SDK's `x/ibc` module: - -* [ICS 002 - Client Semantics](https://github.com/cosmos/ics/tree/master/spec/ics-002-client-semantics): Implemented in [`x/ibc/core/02-client`](https://github.com/cosmos/tree/master/ibc/core/02-client) -* [ICS 003 - Connection Semantics](https://github.com/cosmos/ics/blob/master/spec/ics-003-connection-semantics): Implemented in [`x/ibc/core/03-connection`](https://github.com/cosmos/tree/master/ibc/core/03-connection) -* [ICS 004 - Channel and Packet Semantics](https://github.com/cosmos/ics/blob/master/spec/ics-004-channel-and-packet-semantics): Implemented in [`x/ibc/core/04-channel`](https://github.com/cosmos/tree/master/ibc/core/04-channel) -* [ICS 005 - Port Allocation](https://github.com/cosmos/ics/blob/master/spec/ics-005-port-allocation): Implemented in [`x/ibc/core/05-port`](https://github.com/cosmos/tree/master/ibc/core/05-port) -* [ICS 006 - Solo Machine Client](https://github.com/cosmos/ics/blob/master/spec/ics-006-solo-machine-client): Implemented in [`x/ibc/light-clients/06-solomachine`](https://github.com/cosmos/tree/master/ibc/solomachine) -* [ICS 007 - Tendermint Client](https://github.com/cosmos/ics/blob/master/spec/ics-007-tendermint-client): Implemented in [`x/ibc/light-clients/07-tendermint`](https://github.com/cosmos/tree/master/ibc/light-clients/07-tendermint) -* [ICS 009 - Loopback Client](https://github.com/cosmos/ics/blob/master/spec/ics-009-loopback-client): Implemented in [`x/ibc/light-clients/09-localhost`](https://github.com/cosmos/tree/master/ibc/light-clients/09-localhost) -* [ICS 018- Relayer Algorithms](https://github.com/cosmos/ics/tree/master/spec/ics-018-relayer-algorithms): Implemented in it's own [relayer repository](https://github.com/cosmos/relayer) -* [ICS 020 - Fungible Token Transfer](https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer): Implemented in [`x/ibc/applications/transfer`](https://github.com/cosmos/tree/master/ibc/applications/transfer) -* [ICS 023 - Vector Commitments](https://github.com/cosmos/ics/tree/master/spec/ics-023-vector-commitments): Implemented in [`x/ibc/core/23-commitment`](https://github.com/cosmos/tree/master/ibc/core/23-commitment) -* [ICS 024 - Host Requirements](https://github.com/cosmos/ics/tree/master/spec/ics-024-host-requirements): Implemented in [`x/ibc/core/24-host`](https://github.com/cosmos/tree/master/ibc/core/24-host) -* [ICS 025 - Handler Interface](https://github.com/cosmos/ics/tree/master/spec/ics-025-handler-interface): `Handler` interfaces are implemented at the top level in `x/ibc/handler.go`, -which call each ICS submodule's handlers (i.e `x/ibc/*/{XX-ICS}/handler.go`). -* [ICS 026 - Routing Module](https://github.com/cosmos/ics/blob/master/spec/ics-026-routing-module): Replaced by [ADR 15 - IBC Packet Receiver](../../../docs/architecture/adr-015-ibc-packet-receiver.md). - -### Architecture Decision Records (ADR) - -The following ADR provide the design and architecture decision of IBC-related components. - -* [ADR 001 - Coin Source Tracing](../../../docs/architecture/adr-001-coin-source-tracing.md): standard to hash the ICS20's fungible token -denomination trace path in order to support special characters and limit the maximum denomination length. -* [ADR 17 - Historical Header Module](../../../docs/architecture/adr-017-historical-header-module.md): Introduces the ability to introspect past -consensus states in order to verify their membership in the counterparty clients. -* [ADR 19 - Protobuf State Encoding](../../../docs/architecture/adr-019-protobuf-state-encoding.md): Migration from Amino to Protobuf for state encoding. -* [ADR 020 - Protocol Buffer Transaction Encoding](./../../docs/architecture/adr-020-protobuf-transaction-encoding.md): Client side migration to Protobuf. -* [ADR 021 - Protocol Buffer Query Encoding](../../../docs/architecture/adr-020-protobuf-query-encoding.md): Queries migration to Protobuf. -* [ADR 026 - IBC Client Recovery Mechanisms](../../../docs/architecture/adr-026-ibc-client-recovery-mechanisms.md): Allows IBC Clients to be recovered after freezing or expiry. - -### SDK Modules - -* [`x/capability`](https://github.com/cosmos/tree/master/x/capability): The capability module provides object-capability keys support through scoped keepers in order to authenticate usage of ports or channels. Check [ADR 3 - Dynamic Capability Store](../../../docs/architecture/adr-003-dynamic-capability-store.md) for more details. - -## IBC module architecture - -> **NOTE for auditors**: If you're not familiar with the overall module structure from -the SDK modules, please check this [document](../../../docs/building-modules/structure.md) as -prerequisite reading. - -For ease of auditing, every Interchain Standard has been developed in its own -package. The development team separated the IBC TAO (Transport, Authentication, Ordering) ICS specifications from the IBC application level -specification. The following tree describes the architecture of the directories that -the `ibc` (TAO) and `ibc-transfer` ([ICS20](https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer)) modules: - -```shell -x/ibc -├── applications/ -│ └──transfer/ -├── core/ -│   ├── 02-client/ -│   ├── 03-connection/ -│   ├── 04-channel/ -│   ├── 05-port/ -│   ├── 23-commitment/ -│   ├── 24-host/ -│  ├── client -│  │   └── cli -│ │       └── cli.go -│  ├── keeper -│  │ ├── keeper.go -│   │ └── querier.go -│ ├── types -│ │ ├── errors.go -│ │ └── keys.go -│ ├── handler.go -│ └── module.go -├── light-clients/ -│   ├── 06-solomachine/ -│   ├── 07-tendermint/ -│   └── 09-localhost/ -└── testing/ -``` diff --git a/x/ibc/testing/chain.go b/x/ibc/testing/chain.go deleted file mode 100644 index 0534066d88d6..000000000000 --- a/x/ibc/testing/chain.go +++ /dev/null @@ -1,910 +0,0 @@ -package ibctesting - -import ( - "bytes" - "fmt" - "strconv" - "testing" - "time" - - "github.com/stretchr/testify/require" - abci "github.com/tendermint/tendermint/abci/types" - "github.com/tendermint/tendermint/crypto/tmhash" - tmproto "github.com/tendermint/tendermint/proto/tendermint/types" - tmprotoversion "github.com/tendermint/tendermint/proto/tendermint/version" - tmtypes "github.com/tendermint/tendermint/types" - tmversion "github.com/tendermint/tendermint/version" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" - "github.com/cosmos/cosmos-sdk/simapp" - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "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" - capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" - ibctransfertypes "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - "github.com/cosmos/cosmos-sdk/x/ibc/core/types" - ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types" - "github.com/cosmos/cosmos-sdk/x/ibc/testing/mock" - "github.com/cosmos/cosmos-sdk/x/staking/teststaking" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" -) - -const ( - // Default params constants used to create a TM client - TrustingPeriod time.Duration = time.Hour * 24 * 7 * 2 - UnbondingPeriod time.Duration = time.Hour * 24 * 7 * 3 - MaxClockDrift time.Duration = time.Second * 10 - DefaultDelayPeriod uint64 = 0 - - DefaultChannelVersion = ibctransfertypes.Version - InvalidID = "IDisInvalid" - - ConnectionIDPrefix = "conn" - ChannelIDPrefix = "chan" - - TransferPort = ibctransfertypes.ModuleName - MockPort = mock.ModuleName - - // used for testing UpdateClientProposal - Title = "title" - Description = "description" -) - -var ( - DefaultOpenInitVersion *connectiontypes.Version - - // Default params variables used to create a TM client - DefaultTrustLevel ibctmtypes.Fraction = ibctmtypes.DefaultTrustLevel - TestHash = tmhash.Sum([]byte("TESTING HASH")) - TestCoin = sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)) - - UpgradePath = []string{"upgrade", "upgradedIBCState"} - - ConnectionVersion = connectiontypes.ExportedVersionsToProto(connectiontypes.GetCompatibleVersions())[0] - - MockAcknowledgement = mock.MockAcknowledgement - MockCommitment = mock.MockCommitment -) - -// TestChain is a testing struct that wraps a simapp with the last TM Header, the current ABCI -// header and the validators of the TestChain. It also contains a field called ChainID. This -// is the clientID that *other* chains use to refer to this TestChain. The SenderAccount -// is used for delivering transactions through the application state. -// NOTE: the actual application uses an empty chain-id for ease of testing. -type TestChain struct { - t *testing.T - - App *simapp.SimApp - ChainID string - LastHeader *ibctmtypes.Header // header for last block height committed - CurrentHeader tmproto.Header // header for current block height - QueryServer types.QueryServer - TxConfig client.TxConfig - Codec codec.BinaryMarshaler - - Vals *tmtypes.ValidatorSet - Signers []tmtypes.PrivValidator - - senderPrivKey cryptotypes.PrivKey - SenderAccount authtypes.AccountI - - // IBC specific helpers - ClientIDs []string // ClientID's used on this chain - Connections []*TestConnection // track connectionID's created for this chain -} - -// NewTestChain initializes a new TestChain instance with a single validator set using a -// generated private key. It also creates a sender account to be used for delivering transactions. -// -// The first block height is committed to state in order to allow for client creations on -// counterparty chains. The TestChain will return with a block height starting at 2. -// -// Time management is handled by the Coordinator in order to ensure synchrony between chains. -// Each update of any chain increments the block header time for all chains by 5 seconds. -func NewTestChain(t *testing.T, chainID string) *TestChain { - // generate validator private/public key - privVal := mock.NewPV() - pubKey, err := privVal.GetPubKey() - require.NoError(t, err) - - // create validator set with single validator - validator := tmtypes.NewValidator(pubKey, 1) - valSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{validator}) - signers := []tmtypes.PrivValidator{privVal} - - // generate genesis account - senderPrivKey := secp256k1.GenPrivKey() - acc := authtypes.NewBaseAccount(senderPrivKey.PubKey().Address().Bytes(), senderPrivKey.PubKey(), 0, 0) - balance := banktypes.Balance{ - Address: acc.GetAddress().String(), - Coins: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100000000000000))), - } - - app := simapp.SetupWithGenesisValSet(t, valSet, []authtypes.GenesisAccount{acc}, balance) - - // create current header and call begin block - header := tmproto.Header{ - ChainID: chainID, - Height: 1, - Time: globalStartTime, - } - - txConfig := simapp.MakeTestEncodingConfig().TxConfig - - // create an account to send transactions from - chain := &TestChain{ - t: t, - ChainID: chainID, - App: app, - CurrentHeader: header, - QueryServer: app.IBCKeeper, - TxConfig: txConfig, - Codec: app.AppCodec(), - Vals: valSet, - Signers: signers, - senderPrivKey: senderPrivKey, - SenderAccount: acc, - ClientIDs: make([]string, 0), - Connections: make([]*TestConnection, 0), - } - - cap := chain.App.IBCKeeper.PortKeeper.BindPort(chain.GetContext(), MockPort) - err = chain.App.ScopedIBCMockKeeper.ClaimCapability(chain.GetContext(), cap, host.PortPath(MockPort)) - require.NoError(t, err) - - chain.NextBlock() - - return chain -} - -// GetContext returns the current context for the application. -func (chain *TestChain) GetContext() sdk.Context { - return chain.App.BaseApp.NewContext(false, chain.CurrentHeader) -} - -// QueryProof performs an abci query with the given key and returns the proto encoded merkle proof -// for the query and the height at which the proof will succeed on a tendermint verifier. -func (chain *TestChain) QueryProof(key []byte) ([]byte, clienttypes.Height) { - res := chain.App.Query(abci.RequestQuery{ - Path: fmt.Sprintf("store/%s/key", host.StoreKey), - Height: chain.App.LastBlockHeight() - 1, - Data: key, - Prove: true, - }) - - merkleProof, err := commitmenttypes.ConvertProofs(res.ProofOps) - require.NoError(chain.t, err) - - proof, err := chain.App.AppCodec().MarshalBinaryBare(&merkleProof) - require.NoError(chain.t, err) - - revision := clienttypes.ParseChainID(chain.ChainID) - - // proof height + 1 is returned as the proof created corresponds to the height the proof - // was created in the IAVL tree. Tendermint and subsequently the clients that rely on it - // have heights 1 above the IAVL tree. Thus we return proof height + 1 - return proof, clienttypes.NewHeight(revision, uint64(res.Height)+1) -} - -// QueryUpgradeProof performs an abci query with the given key and returns the proto encoded merkle proof -// for the query and the height at which the proof will succeed on a tendermint verifier. -func (chain *TestChain) QueryUpgradeProof(key []byte, height uint64) ([]byte, clienttypes.Height) { - res := chain.App.Query(abci.RequestQuery{ - Path: "store/upgrade/key", - Height: int64(height - 1), - Data: key, - Prove: true, - }) - - merkleProof, err := commitmenttypes.ConvertProofs(res.ProofOps) - require.NoError(chain.t, err) - - proof, err := chain.App.AppCodec().MarshalBinaryBare(&merkleProof) - require.NoError(chain.t, err) - - revision := clienttypes.ParseChainID(chain.ChainID) - - // proof height + 1 is returned as the proof created corresponds to the height the proof - // was created in the IAVL tree. Tendermint and subsequently the clients that rely on it - // have heights 1 above the IAVL tree. Thus we return proof height + 1 - return proof, clienttypes.NewHeight(revision, uint64(res.Height+1)) -} - -// QueryClientStateProof performs and abci query for a client state -// stored with a given clientID and returns the ClientState along with the proof -func (chain *TestChain) QueryClientStateProof(clientID string) (exported.ClientState, []byte) { - // retrieve client state to provide proof for - clientState, found := chain.App.IBCKeeper.ClientKeeper.GetClientState(chain.GetContext(), clientID) - require.True(chain.t, found) - - clientKey := host.FullClientStateKey(clientID) - proofClient, _ := chain.QueryProof(clientKey) - - return clientState, proofClient -} - -// QueryConsensusStateProof performs an abci query for a consensus state -// stored on the given clientID. The proof and consensusHeight are returned. -func (chain *TestChain) QueryConsensusStateProof(clientID string) ([]byte, clienttypes.Height) { - clientState := chain.GetClientState(clientID) - - consensusHeight := clientState.GetLatestHeight().(clienttypes.Height) - consensusKey := host.FullConsensusStateKey(clientID, consensusHeight) - proofConsensus, _ := chain.QueryProof(consensusKey) - - return proofConsensus, consensusHeight -} - -// NextBlock sets the last header to the current header and increments the current header to be -// at the next block height. It does not update the time as that is handled by the Coordinator. -// -// CONTRACT: this function must only be called after app.Commit() occurs -func (chain *TestChain) NextBlock() { - // set the last header to the current header - // use nil trusted fields - chain.LastHeader = chain.CurrentTMClientHeader() - - // increment the current header - chain.CurrentHeader = tmproto.Header{ - ChainID: chain.ChainID, - Height: chain.App.LastBlockHeight() + 1, - AppHash: chain.App.LastCommitID().Hash, - // NOTE: the time is increased by the coordinator to maintain time synchrony amongst - // chains. - Time: chain.CurrentHeader.Time, - ValidatorsHash: chain.Vals.Hash(), - NextValidatorsHash: chain.Vals.Hash(), - } - - chain.App.BeginBlock(abci.RequestBeginBlock{Header: chain.CurrentHeader}) - -} - -// sendMsgs delivers a transaction through the application without returning the result. -func (chain *TestChain) sendMsgs(msgs ...sdk.Msg) error { - _, err := chain.SendMsgs(msgs...) - return err -} - -// SendMsgs delivers a transaction through the application. It updates the senders sequence -// number and updates the TestChain's headers. It returns the result and error if one -// occurred. -func (chain *TestChain) SendMsgs(msgs ...sdk.Msg) (*sdk.Result, error) { - _, r, err := simapp.SignCheckDeliver( - chain.t, - chain.TxConfig, - chain.App.BaseApp, - chain.GetContext().BlockHeader(), - msgs, - chain.ChainID, - []uint64{chain.SenderAccount.GetAccountNumber()}, - []uint64{chain.SenderAccount.GetSequence()}, - true, true, chain.senderPrivKey, - ) - if err != nil { - return nil, err - } - - // SignCheckDeliver calls app.Commit() - chain.NextBlock() - - // increment sequence for successful transaction execution - chain.SenderAccount.SetSequence(chain.SenderAccount.GetSequence() + 1) - - return r, nil -} - -// GetClientState retrieves the client state for the provided clientID. The client is -// expected to exist otherwise testing will fail. -func (chain *TestChain) GetClientState(clientID string) exported.ClientState { - clientState, found := chain.App.IBCKeeper.ClientKeeper.GetClientState(chain.GetContext(), clientID) - require.True(chain.t, found) - - return clientState -} - -// GetConsensusState retrieves the consensus state for the provided clientID and height. -// It will return a success boolean depending on if consensus state exists or not. -func (chain *TestChain) GetConsensusState(clientID string, height exported.Height) (exported.ConsensusState, bool) { - return chain.App.IBCKeeper.ClientKeeper.GetClientConsensusState(chain.GetContext(), clientID, height) -} - -// GetValsAtHeight will return the validator set of the chain at a given height. It will return -// a success boolean depending on if the validator set exists or not at that height. -func (chain *TestChain) GetValsAtHeight(height int64) (*tmtypes.ValidatorSet, bool) { - histInfo, ok := chain.App.StakingKeeper.GetHistoricalInfo(chain.GetContext(), height) - if !ok { - return nil, false - } - - valSet := stakingtypes.Validators(histInfo.Valset) - - tmValidators, err := teststaking.ToTmValidators(valSet) - if err != nil { - panic(err) - } - return tmtypes.NewValidatorSet(tmValidators), true -} - -// GetConnection retrieves an IBC Connection for the provided TestConnection. The -// connection is expected to exist otherwise testing will fail. -func (chain *TestChain) GetConnection(testConnection *TestConnection) connectiontypes.ConnectionEnd { - connection, found := chain.App.IBCKeeper.ConnectionKeeper.GetConnection(chain.GetContext(), testConnection.ID) - require.True(chain.t, found) - - return connection -} - -// GetChannel retrieves an IBC Channel for the provided TestChannel. The channel -// is expected to exist otherwise testing will fail. -func (chain *TestChain) GetChannel(testChannel TestChannel) channeltypes.Channel { - channel, found := chain.App.IBCKeeper.ChannelKeeper.GetChannel(chain.GetContext(), testChannel.PortID, testChannel.ID) - require.True(chain.t, found) - - return channel -} - -// GetAcknowledgement retrieves an acknowledgement for the provided packet. If the -// acknowledgement does not exist then testing will fail. -func (chain *TestChain) GetAcknowledgement(packet exported.PacketI) []byte { - ack, found := chain.App.IBCKeeper.ChannelKeeper.GetPacketAcknowledgement(chain.GetContext(), packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - require.True(chain.t, found) - - return ack -} - -// GetPrefix returns the prefix for used by a chain in connection creation -func (chain *TestChain) GetPrefix() commitmenttypes.MerklePrefix { - return commitmenttypes.NewMerklePrefix(chain.App.IBCKeeper.ConnectionKeeper.GetCommitmentPrefix().Bytes()) -} - -// NewClientID appends a new clientID string in the format: -// ClientFor -func (chain *TestChain) NewClientID(clientType string) string { - clientID := fmt.Sprintf("%s-%s", clientType, strconv.Itoa(len(chain.ClientIDs))) - chain.ClientIDs = append(chain.ClientIDs, clientID) - return clientID -} - -// AddTestConnection appends a new TestConnection which contains references -// to the connection id, client id and counterparty client id. -func (chain *TestChain) AddTestConnection(clientID, counterpartyClientID string) *TestConnection { - conn := chain.ConstructNextTestConnection(clientID, counterpartyClientID) - - chain.Connections = append(chain.Connections, conn) - return conn -} - -// ConstructNextTestConnection constructs the next test connection to be -// created given a clientID and counterparty clientID. The connection id -// format: -conn -func (chain *TestChain) ConstructNextTestConnection(clientID, counterpartyClientID string) *TestConnection { - connectionID := connectiontypes.FormatConnectionIdentifier(uint64(len(chain.Connections))) - return &TestConnection{ - ID: connectionID, - ClientID: clientID, - NextChannelVersion: DefaultChannelVersion, - CounterpartyClientID: counterpartyClientID, - } -} - -// GetFirstTestConnection returns the first test connection for a given clientID. -// The connection may or may not exist in the chain state. -func (chain *TestChain) GetFirstTestConnection(clientID, counterpartyClientID string) *TestConnection { - if len(chain.Connections) > 0 { - return chain.Connections[0] - } - - return chain.ConstructNextTestConnection(clientID, counterpartyClientID) -} - -// AddTestChannel appends a new TestChannel which contains references to the port and channel ID -// used for channel creation and interaction. See 'NextTestChannel' for channel ID naming format. -func (chain *TestChain) AddTestChannel(conn *TestConnection, portID string) TestChannel { - channel := chain.NextTestChannel(conn, portID) - conn.Channels = append(conn.Channels, channel) - return channel -} - -// NextTestChannel returns the next test channel to be created on this connection, but does not -// add it to the list of created channels. This function is expected to be used when the caller -// has not created the associated channel in app state, but would still like to refer to the -// non-existent channel usually to test for its non-existence. -// -// channel ID format: -chan -// -// The port is passed in by the caller. -func (chain *TestChain) NextTestChannel(conn *TestConnection, portID string) TestChannel { - nextChanSeq := chain.App.IBCKeeper.ChannelKeeper.GetNextChannelSequence(chain.GetContext()) - channelID := channeltypes.FormatChannelIdentifier(nextChanSeq) - return TestChannel{ - PortID: portID, - ID: channelID, - ClientID: conn.ClientID, - CounterpartyClientID: conn.CounterpartyClientID, - Version: conn.NextChannelVersion, - } -} - -// ConstructMsgCreateClient constructs a message to create a new client state (tendermint or solomachine). -// NOTE: a solo machine client will be created with an empty diversifier. -func (chain *TestChain) ConstructMsgCreateClient(counterparty *TestChain, clientID string, clientType string) *clienttypes.MsgCreateClient { - var ( - clientState exported.ClientState - consensusState exported.ConsensusState - ) - - switch clientType { - case exported.Tendermint: - height := counterparty.LastHeader.GetHeight().(clienttypes.Height) - clientState = ibctmtypes.NewClientState( - counterparty.ChainID, DefaultTrustLevel, TrustingPeriod, UnbondingPeriod, MaxClockDrift, - height, commitmenttypes.GetSDKSpecs(), UpgradePath, false, false, - ) - consensusState = counterparty.LastHeader.ConsensusState() - case exported.Solomachine: - solo := NewSolomachine(chain.t, chain.Codec, clientID, "", 1) - clientState = solo.ClientState() - consensusState = solo.ConsensusState() - default: - chain.t.Fatalf("unsupported client state type %s", clientType) - } - - msg, err := clienttypes.NewMsgCreateClient( - clientState, consensusState, chain.SenderAccount.GetAddress(), - ) - require.NoError(chain.t, err) - return msg -} - -// CreateTMClient will construct and execute a 07-tendermint MsgCreateClient. A counterparty -// client will be created on the (target) chain. -func (chain *TestChain) CreateTMClient(counterparty *TestChain, clientID string) error { - // construct MsgCreateClient using counterparty - msg := chain.ConstructMsgCreateClient(counterparty, clientID, exported.Tendermint) - return chain.sendMsgs(msg) -} - -// UpdateTMClient will construct and execute a 07-tendermint MsgUpdateClient. The counterparty -// client will be updated on the (target) chain. UpdateTMClient mocks the relayer flow -// necessary for updating a Tendermint client. -func (chain *TestChain) UpdateTMClient(counterparty *TestChain, clientID string) error { - header, err := chain.ConstructUpdateTMClientHeader(counterparty, clientID) - require.NoError(chain.t, err) - - msg, err := clienttypes.NewMsgUpdateClient( - clientID, header, - chain.SenderAccount.GetAddress(), - ) - require.NoError(chain.t, err) - - return chain.sendMsgs(msg) -} - -// ConstructUpdateTMClientHeader will construct a valid 07-tendermint Header to update the -// light client on the source chain. -func (chain *TestChain) ConstructUpdateTMClientHeader(counterparty *TestChain, clientID string) (*ibctmtypes.Header, error) { - header := counterparty.LastHeader - // Relayer must query for LatestHeight on client to get TrustedHeight - trustedHeight := chain.GetClientState(clientID).GetLatestHeight().(clienttypes.Height) - var ( - tmTrustedVals *tmtypes.ValidatorSet - ok bool - ) - // Once we get TrustedHeight from client, we must query the validators from the counterparty chain - // If the LatestHeight == LastHeader.Height, then TrustedValidators are current validators - // If LatestHeight < LastHeader.Height, we can query the historical validator set from HistoricalInfo - if trustedHeight == counterparty.LastHeader.GetHeight() { - tmTrustedVals = counterparty.Vals - } else { - // NOTE: We need to get validators from counterparty at height: trustedHeight+1 - // since the last trusted validators for a header at height h - // is the NextValidators at h+1 committed to in header h by - // NextValidatorsHash - tmTrustedVals, ok = counterparty.GetValsAtHeight(int64(trustedHeight.RevisionHeight + 1)) - if !ok { - return nil, sdkerrors.Wrapf(ibctmtypes.ErrInvalidHeaderHeight, "could not retrieve trusted validators at trustedHeight: %d", trustedHeight) - } - } - // inject trusted fields into last header - // for now assume revision number is 0 - header.TrustedHeight = trustedHeight - - trustedVals, err := tmTrustedVals.ToProto() - if err != nil { - return nil, err - } - header.TrustedValidators = trustedVals - - return header, nil - -} - -// ExpireClient fast forwards the chain's block time by the provided amount of time which will -// expire any clients with a trusting period less than or equal to this amount of time. -func (chain *TestChain) ExpireClient(amount time.Duration) { - chain.CurrentHeader.Time = chain.CurrentHeader.Time.Add(amount) -} - -// CurrentTMClientHeader creates a TM header using the current header parameters -// on the chain. The trusted fields in the header are set to nil. -func (chain *TestChain) CurrentTMClientHeader() *ibctmtypes.Header { - return chain.CreateTMClientHeader(chain.ChainID, chain.CurrentHeader.Height, clienttypes.Height{}, chain.CurrentHeader.Time, chain.Vals, nil, chain.Signers) -} - -// CreateTMClientHeader creates a TM header to update the TM client. Args are passed in to allow -// caller flexibility to use params that differ from the chain. -func (chain *TestChain) CreateTMClientHeader(chainID string, blockHeight int64, trustedHeight clienttypes.Height, timestamp time.Time, tmValSet, tmTrustedVals *tmtypes.ValidatorSet, signers []tmtypes.PrivValidator) *ibctmtypes.Header { - var ( - valSet *tmproto.ValidatorSet - trustedVals *tmproto.ValidatorSet - ) - require.NotNil(chain.t, tmValSet) - - vsetHash := tmValSet.Hash() - - tmHeader := tmtypes.Header{ - Version: tmprotoversion.Consensus{Block: tmversion.BlockProtocol, App: 2}, - ChainID: chainID, - Height: blockHeight, - Time: timestamp, - LastBlockID: MakeBlockID(make([]byte, tmhash.Size), 10_000, make([]byte, tmhash.Size)), - LastCommitHash: chain.App.LastCommitID().Hash, - DataHash: tmhash.Sum([]byte("data_hash")), - ValidatorsHash: vsetHash, - NextValidatorsHash: vsetHash, - ConsensusHash: tmhash.Sum([]byte("consensus_hash")), - AppHash: chain.CurrentHeader.AppHash, - LastResultsHash: tmhash.Sum([]byte("last_results_hash")), - EvidenceHash: tmhash.Sum([]byte("evidence_hash")), - ProposerAddress: tmValSet.Proposer.Address, //nolint:staticcheck - } - hhash := tmHeader.Hash() - blockID := MakeBlockID(hhash, 3, tmhash.Sum([]byte("part_set"))) - voteSet := tmtypes.NewVoteSet(chainID, blockHeight, 1, tmproto.PrecommitType, tmValSet) - - commit, err := tmtypes.MakeCommit(blockID, blockHeight, 1, voteSet, signers, timestamp) - require.NoError(chain.t, err) - - signedHeader := &tmproto.SignedHeader{ - Header: tmHeader.ToProto(), - Commit: commit.ToProto(), - } - - if tmValSet != nil { - valSet, err = tmValSet.ToProto() - if err != nil { - panic(err) - } - } - - if tmTrustedVals != nil { - trustedVals, err = tmTrustedVals.ToProto() - if err != nil { - panic(err) - } - } - - // The trusted fields may be nil. They may be filled before relaying messages to a client. - // The relayer is responsible for querying client and injecting appropriate trusted fields. - return &ibctmtypes.Header{ - SignedHeader: signedHeader, - ValidatorSet: valSet, - TrustedHeight: trustedHeight, - TrustedValidators: trustedVals, - } -} - -// MakeBlockID copied unimported test functions from tmtypes to use them here -func MakeBlockID(hash []byte, partSetSize uint32, partSetHash []byte) tmtypes.BlockID { - return tmtypes.BlockID{ - Hash: hash, - PartSetHeader: tmtypes.PartSetHeader{ - Total: partSetSize, - Hash: partSetHash, - }, - } -} - -// CreateSortedSignerArray takes two PrivValidators, and the corresponding Validator structs -// (including voting power). It returns a signer array of PrivValidators that matches the -// sorting of ValidatorSet. -// The sorting is first by .VotingPower (descending), with secondary index of .Address (ascending). -func CreateSortedSignerArray(altPrivVal, suitePrivVal tmtypes.PrivValidator, - altVal, suiteVal *tmtypes.Validator) []tmtypes.PrivValidator { - - switch { - case altVal.VotingPower > suiteVal.VotingPower: - return []tmtypes.PrivValidator{altPrivVal, suitePrivVal} - case altVal.VotingPower < suiteVal.VotingPower: - return []tmtypes.PrivValidator{suitePrivVal, altPrivVal} - default: - if bytes.Compare(altVal.Address, suiteVal.Address) == -1 { - return []tmtypes.PrivValidator{altPrivVal, suitePrivVal} - } - return []tmtypes.PrivValidator{suitePrivVal, altPrivVal} - } -} - -// ConnectionOpenInit will construct and execute a MsgConnectionOpenInit. -func (chain *TestChain) ConnectionOpenInit( - counterparty *TestChain, - connection, counterpartyConnection *TestConnection, -) error { - msg := connectiontypes.NewMsgConnectionOpenInit( - connection.ClientID, - connection.CounterpartyClientID, - counterparty.GetPrefix(), DefaultOpenInitVersion, DefaultDelayPeriod, - chain.SenderAccount.GetAddress(), - ) - return chain.sendMsgs(msg) -} - -// ConnectionOpenTry will construct and execute a MsgConnectionOpenTry. -func (chain *TestChain) ConnectionOpenTry( - counterparty *TestChain, - connection, counterpartyConnection *TestConnection, -) error { - counterpartyClient, proofClient := counterparty.QueryClientStateProof(counterpartyConnection.ClientID) - - connectionKey := host.ConnectionKey(counterpartyConnection.ID) - proofInit, proofHeight := counterparty.QueryProof(connectionKey) - - proofConsensus, consensusHeight := counterparty.QueryConsensusStateProof(counterpartyConnection.ClientID) - - msg := connectiontypes.NewMsgConnectionOpenTry( - "", connection.ClientID, // does not support handshake continuation - counterpartyConnection.ID, counterpartyConnection.ClientID, - counterpartyClient, counterparty.GetPrefix(), []*connectiontypes.Version{ConnectionVersion}, DefaultDelayPeriod, - proofInit, proofClient, proofConsensus, - proofHeight, consensusHeight, - chain.SenderAccount.GetAddress(), - ) - return chain.sendMsgs(msg) -} - -// ConnectionOpenAck will construct and execute a MsgConnectionOpenAck. -func (chain *TestChain) ConnectionOpenAck( - counterparty *TestChain, - connection, counterpartyConnection *TestConnection, -) error { - counterpartyClient, proofClient := counterparty.QueryClientStateProof(counterpartyConnection.ClientID) - - connectionKey := host.ConnectionKey(counterpartyConnection.ID) - proofTry, proofHeight := counterparty.QueryProof(connectionKey) - - proofConsensus, consensusHeight := counterparty.QueryConsensusStateProof(counterpartyConnection.ClientID) - - msg := connectiontypes.NewMsgConnectionOpenAck( - connection.ID, counterpartyConnection.ID, counterpartyClient, // testing doesn't use flexible selection - proofTry, proofClient, proofConsensus, - proofHeight, consensusHeight, - ConnectionVersion, - chain.SenderAccount.GetAddress(), - ) - return chain.sendMsgs(msg) -} - -// ConnectionOpenConfirm will construct and execute a MsgConnectionOpenConfirm. -func (chain *TestChain) ConnectionOpenConfirm( - counterparty *TestChain, - connection, counterpartyConnection *TestConnection, -) error { - connectionKey := host.ConnectionKey(counterpartyConnection.ID) - proof, height := counterparty.QueryProof(connectionKey) - - msg := connectiontypes.NewMsgConnectionOpenConfirm( - connection.ID, - proof, height, - chain.SenderAccount.GetAddress(), - ) - return chain.sendMsgs(msg) -} - -// CreatePortCapability binds and claims a capability for the given portID if it does not -// already exist. This function will fail testing on any resulting error. -// NOTE: only creation of a capbility for a transfer or mock port is supported -// Other applications must bind to the port in InitGenesis or modify this code. -func (chain *TestChain) CreatePortCapability(portID string) { - // check if the portId is already binded, if not bind it - _, ok := chain.App.ScopedIBCKeeper.GetCapability(chain.GetContext(), host.PortPath(portID)) - if !ok { - // create capability using the IBC capability keeper - cap, err := chain.App.ScopedIBCKeeper.NewCapability(chain.GetContext(), host.PortPath(portID)) - require.NoError(chain.t, err) - - switch portID { - case MockPort: - // claim capability using the mock capability keeper - err = chain.App.ScopedIBCMockKeeper.ClaimCapability(chain.GetContext(), cap, host.PortPath(portID)) - require.NoError(chain.t, err) - case TransferPort: - // claim capability using the transfer capability keeper - err = chain.App.ScopedTransferKeeper.ClaimCapability(chain.GetContext(), cap, host.PortPath(portID)) - require.NoError(chain.t, err) - default: - panic(fmt.Sprintf("unsupported ibc testing package port ID %s", portID)) - } - } - - chain.App.Commit() - - chain.NextBlock() -} - -// GetPortCapability returns the port capability for the given portID. The capability must -// exist, otherwise testing will fail. -func (chain *TestChain) GetPortCapability(portID string) *capabilitytypes.Capability { - cap, ok := chain.App.ScopedIBCKeeper.GetCapability(chain.GetContext(), host.PortPath(portID)) - require.True(chain.t, ok) - - return cap -} - -// CreateChannelCapability binds and claims a capability for the given portID and channelID -// if it does not already exist. This function will fail testing on any resulting error. -func (chain *TestChain) CreateChannelCapability(portID, channelID string) { - capName := host.ChannelCapabilityPath(portID, channelID) - // check if the portId is already binded, if not bind it - _, ok := chain.App.ScopedIBCKeeper.GetCapability(chain.GetContext(), capName) - if !ok { - cap, err := chain.App.ScopedIBCKeeper.NewCapability(chain.GetContext(), capName) - require.NoError(chain.t, err) - err = chain.App.ScopedTransferKeeper.ClaimCapability(chain.GetContext(), cap, capName) - require.NoError(chain.t, err) - } - - chain.App.Commit() - - chain.NextBlock() -} - -// GetChannelCapability returns the channel capability for the given portID and channelID. -// The capability must exist, otherwise testing will fail. -func (chain *TestChain) GetChannelCapability(portID, channelID string) *capabilitytypes.Capability { - cap, ok := chain.App.ScopedIBCKeeper.GetCapability(chain.GetContext(), host.ChannelCapabilityPath(portID, channelID)) - require.True(chain.t, ok) - - return cap -} - -// ChanOpenInit will construct and execute a MsgChannelOpenInit. -func (chain *TestChain) ChanOpenInit( - ch, counterparty TestChannel, - order channeltypes.Order, - connectionID string, -) error { - msg := channeltypes.NewMsgChannelOpenInit( - ch.PortID, - ch.Version, order, []string{connectionID}, - counterparty.PortID, - chain.SenderAccount.GetAddress(), - ) - return chain.sendMsgs(msg) -} - -// ChanOpenTry will construct and execute a MsgChannelOpenTry. -func (chain *TestChain) ChanOpenTry( - counterparty *TestChain, - ch, counterpartyCh TestChannel, - order channeltypes.Order, - connectionID string, -) error { - proof, height := counterparty.QueryProof(host.ChannelKey(counterpartyCh.PortID, counterpartyCh.ID)) - - msg := channeltypes.NewMsgChannelOpenTry( - ch.PortID, "", // does not support handshake continuation - ch.Version, order, []string{connectionID}, - counterpartyCh.PortID, counterpartyCh.ID, counterpartyCh.Version, - proof, height, - chain.SenderAccount.GetAddress(), - ) - return chain.sendMsgs(msg) -} - -// ChanOpenAck will construct and execute a MsgChannelOpenAck. -func (chain *TestChain) ChanOpenAck( - counterparty *TestChain, - ch, counterpartyCh TestChannel, -) error { - proof, height := counterparty.QueryProof(host.ChannelKey(counterpartyCh.PortID, counterpartyCh.ID)) - - msg := channeltypes.NewMsgChannelOpenAck( - ch.PortID, ch.ID, - counterpartyCh.ID, counterpartyCh.Version, // testing doesn't use flexible selection - proof, height, - chain.SenderAccount.GetAddress(), - ) - return chain.sendMsgs(msg) -} - -// ChanOpenConfirm will construct and execute a MsgChannelOpenConfirm. -func (chain *TestChain) ChanOpenConfirm( - counterparty *TestChain, - ch, counterpartyCh TestChannel, -) error { - proof, height := counterparty.QueryProof(host.ChannelKey(counterpartyCh.PortID, counterpartyCh.ID)) - - msg := channeltypes.NewMsgChannelOpenConfirm( - ch.PortID, ch.ID, - proof, height, - chain.SenderAccount.GetAddress(), - ) - return chain.sendMsgs(msg) -} - -// ChanCloseInit will construct and execute a MsgChannelCloseInit. -// -// NOTE: does not work with ibc-transfer module -func (chain *TestChain) ChanCloseInit( - counterparty *TestChain, - channel TestChannel, -) error { - msg := channeltypes.NewMsgChannelCloseInit( - channel.PortID, channel.ID, - chain.SenderAccount.GetAddress(), - ) - return chain.sendMsgs(msg) -} - -// GetPacketData returns a ibc-transfer marshalled packet to be used for -// callback testing. -func (chain *TestChain) GetPacketData(counterparty *TestChain) []byte { - packet := ibctransfertypes.FungibleTokenPacketData{ - Denom: TestCoin.Denom, - Amount: TestCoin.Amount.Uint64(), - Sender: chain.SenderAccount.GetAddress().String(), - Receiver: counterparty.SenderAccount.GetAddress().String(), - } - - return packet.GetBytes() -} - -// SendPacket simulates sending a packet through the channel keeper. No message needs to be -// passed since this call is made from a module. -func (chain *TestChain) SendPacket( - packet exported.PacketI, -) error { - channelCap := chain.GetChannelCapability(packet.GetSourcePort(), packet.GetSourceChannel()) - - // no need to send message, acting as a module - err := chain.App.IBCKeeper.ChannelKeeper.SendPacket(chain.GetContext(), channelCap, packet) - if err != nil { - return err - } - - // commit changes - chain.App.Commit() - chain.NextBlock() - - return nil -} - -// WriteAcknowledgement simulates writing an acknowledgement to the chain. -func (chain *TestChain) WriteAcknowledgement( - packet exported.PacketI, -) error { - channelCap := chain.GetChannelCapability(packet.GetDestPort(), packet.GetDestChannel()) - - // no need to send message, acting as a handler - err := chain.App.IBCKeeper.ChannelKeeper.WriteAcknowledgement(chain.GetContext(), channelCap, packet, TestHash) - if err != nil { - return err - } - - // commit changes - chain.App.Commit() - chain.NextBlock() - - return nil -} diff --git a/x/ibc/testing/chain_test.go b/x/ibc/testing/chain_test.go deleted file mode 100644 index 361a9c4c15af..000000000000 --- a/x/ibc/testing/chain_test.go +++ /dev/null @@ -1,47 +0,0 @@ -package ibctesting_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - tmtypes "github.com/tendermint/tendermint/types" - - ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing" - "github.com/cosmos/cosmos-sdk/x/ibc/testing/mock" -) - -func TestCreateSortedSignerArray(t *testing.T) { - privVal1 := mock.NewPV() - pubKey1, err := privVal1.GetPubKey() - require.NoError(t, err) - - privVal2 := mock.NewPV() - pubKey2, err := privVal2.GetPubKey() - require.NoError(t, err) - - validator1 := tmtypes.NewValidator(pubKey1, 1) - validator2 := tmtypes.NewValidator(pubKey2, 2) - - expected := []tmtypes.PrivValidator{privVal2, privVal1} - - actual := ibctesting.CreateSortedSignerArray(privVal1, privVal2, validator1, validator2) - require.Equal(t, expected, actual) - - // swap order - actual = ibctesting.CreateSortedSignerArray(privVal2, privVal1, validator2, validator1) - require.Equal(t, expected, actual) - - // smaller address - validator1.Address = []byte{1} - validator2.Address = []byte{2} - validator2.VotingPower = 1 - - expected = []tmtypes.PrivValidator{privVal1, privVal2} - - actual = ibctesting.CreateSortedSignerArray(privVal1, privVal2, validator1, validator2) - require.Equal(t, expected, actual) - - // swap order - actual = ibctesting.CreateSortedSignerArray(privVal2, privVal1, validator2, validator1) - require.Equal(t, expected, actual) -} diff --git a/x/ibc/testing/coordinator.go b/x/ibc/testing/coordinator.go deleted file mode 100644 index ade28b4df342..000000000000 --- a/x/ibc/testing/coordinator.go +++ /dev/null @@ -1,700 +0,0 @@ -package ibctesting - -import ( - "fmt" - "strconv" - "testing" - "time" - - "github.com/stretchr/testify/require" - abci "github.com/tendermint/tendermint/abci/types" - - sdk "github.com/cosmos/cosmos-sdk/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" -) - -var ( - ChainIDPrefix = "testchain" - globalStartTime = time.Date(2020, 1, 2, 0, 0, 0, 0, time.UTC) - TimeIncrement = time.Second * 5 -) - -// Coordinator is a testing struct which contains N TestChain's. It handles keeping all chains -// in sync with regards to time. -type Coordinator struct { - t *testing.T - - Chains map[string]*TestChain -} - -// NewCoordinator initializes Coordinator with N TestChain's -func NewCoordinator(t *testing.T, n int) *Coordinator { - chains := make(map[string]*TestChain) - - for i := 0; i < n; i++ { - chainID := GetChainID(i) - chains[chainID] = NewTestChain(t, chainID) - } - return &Coordinator{ - t: t, - Chains: chains, - } -} - -// Setup constructs a TM client, connection, and channel on both chains provided. It will -// fail if any error occurs. The clientID's, TestConnections, and TestChannels are returned -// for both chains. The channels created are connected to the ibc-transfer application. -func (coord *Coordinator) Setup( - chainA, chainB *TestChain, order channeltypes.Order, -) (string, string, *TestConnection, *TestConnection, TestChannel, TestChannel) { - clientA, clientB, connA, connB := coord.SetupClientConnections(chainA, chainB, exported.Tendermint) - - // channels can also be referenced through the returned connections - channelA, channelB := coord.CreateMockChannels(chainA, chainB, connA, connB, order) - - return clientA, clientB, connA, connB, channelA, channelB -} - -// SetupClients is a helper function to create clients on both chains. It assumes the -// caller does not anticipate any errors. -func (coord *Coordinator) SetupClients( - chainA, chainB *TestChain, - clientType string, -) (string, string) { - - clientA, err := coord.CreateClient(chainA, chainB, clientType) - require.NoError(coord.t, err) - - clientB, err := coord.CreateClient(chainB, chainA, clientType) - require.NoError(coord.t, err) - - return clientA, clientB -} - -// SetupClientConnections is a helper function to create clients and the appropriate -// connections on both the source and counterparty chain. It assumes the caller does not -// anticipate any errors. -func (coord *Coordinator) SetupClientConnections( - chainA, chainB *TestChain, - clientType string, -) (string, string, *TestConnection, *TestConnection) { - - clientA, clientB := coord.SetupClients(chainA, chainB, clientType) - - connA, connB := coord.CreateConnection(chainA, chainB, clientA, clientB) - - return clientA, clientB, connA, connB -} - -// CreateClient creates a counterparty client on the source chain and returns the clientID. -func (coord *Coordinator) CreateClient( - source, counterparty *TestChain, - clientType string, -) (clientID string, err error) { - coord.CommitBlock(source, counterparty) - - clientID = source.NewClientID(clientType) - - switch clientType { - case exported.Tendermint: - err = source.CreateTMClient(counterparty, clientID) - - default: - err = fmt.Errorf("client type %s is not supported", clientType) - } - - if err != nil { - return "", err - } - - coord.IncrementTime() - - return clientID, nil -} - -// UpdateClient updates a counterparty client on the source chain. -func (coord *Coordinator) UpdateClient( - source, counterparty *TestChain, - clientID string, - clientType string, -) (err error) { - coord.CommitBlock(source, counterparty) - - switch clientType { - case exported.Tendermint: - err = source.UpdateTMClient(counterparty, clientID) - - default: - err = fmt.Errorf("client type %s is not supported", clientType) - } - - if err != nil { - return err - } - - coord.IncrementTime() - - return nil -} - -// CreateConnection constructs and executes connection handshake messages in order to create -// OPEN channels on chainA and chainB. The connection information of for chainA and chainB -// are returned within a TestConnection struct. The function expects the connections to be -// successfully opened otherwise testing will fail. -func (coord *Coordinator) CreateConnection( - chainA, chainB *TestChain, - clientA, clientB string, -) (*TestConnection, *TestConnection) { - - connA, connB, err := coord.ConnOpenInit(chainA, chainB, clientA, clientB) - require.NoError(coord.t, err) - - err = coord.ConnOpenTry(chainB, chainA, connB, connA) - require.NoError(coord.t, err) - - err = coord.ConnOpenAck(chainA, chainB, connA, connB) - require.NoError(coord.t, err) - - err = coord.ConnOpenConfirm(chainB, chainA, connB, connA) - require.NoError(coord.t, err) - - return connA, connB -} - -// CreateMockChannels constructs and executes channel handshake messages to create OPEN -// channels that use a mock application module that returns nil on all callbacks. This -// function is expects the channels to be successfully opened otherwise testing will -// fail. -func (coord *Coordinator) CreateMockChannels( - chainA, chainB *TestChain, - connA, connB *TestConnection, - order channeltypes.Order, -) (TestChannel, TestChannel) { - return coord.CreateChannel(chainA, chainB, connA, connB, MockPort, MockPort, order) -} - -// CreateTransferChannels constructs and executes channel handshake messages to create OPEN -// ibc-transfer channels on chainA and chainB. The function expects the channels to be -// successfully opened otherwise testing will fail. -func (coord *Coordinator) CreateTransferChannels( - chainA, chainB *TestChain, - connA, connB *TestConnection, - order channeltypes.Order, -) (TestChannel, TestChannel) { - return coord.CreateChannel(chainA, chainB, connA, connB, TransferPort, TransferPort, order) -} - -// CreateChannel constructs and executes channel handshake messages in order to create -// OPEN channels on chainA and chainB. The function expects the channels to be successfully -// opened otherwise testing will fail. -func (coord *Coordinator) CreateChannel( - chainA, chainB *TestChain, - connA, connB *TestConnection, - sourcePortID, counterpartyPortID string, - order channeltypes.Order, -) (TestChannel, TestChannel) { - - channelA, channelB, err := coord.ChanOpenInit(chainA, chainB, connA, connB, sourcePortID, counterpartyPortID, order) - require.NoError(coord.t, err) - - err = coord.ChanOpenTry(chainB, chainA, channelB, channelA, connB, order) - require.NoError(coord.t, err) - - err = coord.ChanOpenAck(chainA, chainB, channelA, channelB) - require.NoError(coord.t, err) - - err = coord.ChanOpenConfirm(chainB, chainA, channelB, channelA) - require.NoError(coord.t, err) - - return channelA, channelB -} - -// SendPacket sends a packet through the channel keeper on the source chain and updates the -// counterparty client for the source chain. -func (coord *Coordinator) SendPacket( - source, counterparty *TestChain, - packet exported.PacketI, - counterpartyClientID string, -) error { - if err := source.SendPacket(packet); err != nil { - return err - } - coord.IncrementTime() - - // update source client on counterparty connection - return coord.UpdateClient( - counterparty, source, - counterpartyClientID, exported.Tendermint, - ) -} - -// RecvPacket receives a channel packet on the counterparty chain and updates -// the client on the source chain representing the counterparty. -func (coord *Coordinator) RecvPacket( - source, counterparty *TestChain, - sourceClient string, - packet channeltypes.Packet, -) error { - // get proof of packet commitment on source - packetKey := host.PacketCommitmentKey(packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) - proof, proofHeight := source.QueryProof(packetKey) - - // Increment time and commit block so that 5 second delay period passes between send and receive - coord.IncrementTime() - coord.CommitBlock(source, counterparty) - - recvMsg := channeltypes.NewMsgRecvPacket(packet, proof, proofHeight, counterparty.SenderAccount.GetAddress()) - - // receive on counterparty and update source client - return coord.SendMsgs(counterparty, source, sourceClient, []sdk.Msg{recvMsg}) -} - -// WriteAcknowledgement writes an acknowledgement to the channel keeper on the source chain and updates the -// counterparty client for the source chain. -func (coord *Coordinator) WriteAcknowledgement( - source, counterparty *TestChain, - packet exported.PacketI, - counterpartyClientID string, -) error { - if err := source.WriteAcknowledgement(packet); err != nil { - return err - } - coord.IncrementTime() - - // update source client on counterparty connection - return coord.UpdateClient( - counterparty, source, - counterpartyClientID, exported.Tendermint, - ) -} - -// AcknowledgePacket acknowledges on the source chain the packet received on -// the counterparty chain and updates the client on the counterparty representing -// the source chain. -// TODO: add a query for the acknowledgement by events -// - https://github.com/cosmos/cosmos-sdk/issues/6509 -func (coord *Coordinator) AcknowledgePacket( - source, counterparty *TestChain, - counterpartyClient string, - packet channeltypes.Packet, ack []byte, -) error { - // get proof of acknowledgement on counterparty - packetKey := host.PacketAcknowledgementKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - proof, proofHeight := counterparty.QueryProof(packetKey) - - // Increment time and commit block so that 5 second delay period passes between send and receive - coord.IncrementTime() - coord.CommitBlock(source, counterparty) - - ackMsg := channeltypes.NewMsgAcknowledgement(packet, ack, proof, proofHeight, source.SenderAccount.GetAddress()) - return coord.SendMsgs(source, counterparty, counterpartyClient, []sdk.Msg{ackMsg}) -} - -// RelayPacket receives a channel packet on counterparty, queries the ack -// and acknowledges the packet on source. The clients are updated as needed. -func (coord *Coordinator) RelayPacket( - source, counterparty *TestChain, - sourceClient, counterpartyClient string, - packet channeltypes.Packet, ack []byte, -) error { - // Increment time and commit block so that 5 second delay period passes between send and receive - coord.IncrementTime() - coord.CommitBlock(counterparty) - - if err := coord.RecvPacket(source, counterparty, sourceClient, packet); err != nil { - return err - } - - // Increment time and commit block so that 5 second delay period passes between send and receive - coord.IncrementTime() - coord.CommitBlock(source) - - return coord.AcknowledgePacket(source, counterparty, counterpartyClient, packet, ack) -} - -// IncrementTime iterates through all the TestChain's and increments their current header time -// by 5 seconds. -// -// CONTRACT: this function must be called after every commit on any TestChain. -func (coord *Coordinator) IncrementTime() { - for _, chain := range coord.Chains { - chain.CurrentHeader.Time = chain.CurrentHeader.Time.Add(TimeIncrement) - chain.App.BeginBlock(abci.RequestBeginBlock{Header: chain.CurrentHeader}) - } -} - -// IncrementTimeBy iterates through all the TestChain's and increments their current header time -// by specified time. -func (coord *Coordinator) IncrementTimeBy(increment time.Duration) { - for _, chain := range coord.Chains { - chain.CurrentHeader.Time = chain.CurrentHeader.Time.Add(increment) - chain.App.BeginBlock(abci.RequestBeginBlock{Header: chain.CurrentHeader}) - } -} - -// SendMsg delivers a single provided message to the chain. The counterparty -// client is update with the new source consensus state. -func (coord *Coordinator) SendMsg(source, counterparty *TestChain, counterpartyClientID string, msg sdk.Msg) error { - return coord.SendMsgs(source, counterparty, counterpartyClientID, []sdk.Msg{msg}) -} - -// SendMsgs delivers the provided messages to the chain. The counterparty -// client is updated with the new source consensus state. -func (coord *Coordinator) SendMsgs(source, counterparty *TestChain, counterpartyClientID string, msgs []sdk.Msg) error { - if err := source.sendMsgs(msgs...); err != nil { - return err - } - - coord.IncrementTime() - - // update source client on counterparty connection - return coord.UpdateClient( - counterparty, source, - counterpartyClientID, exported.Tendermint, - ) -} - -// GetChain returns the TestChain using the given chainID and returns an error if it does -// not exist. -func (coord *Coordinator) GetChain(chainID string) *TestChain { - chain, found := coord.Chains[chainID] - require.True(coord.t, found, fmt.Sprintf("%s chain does not exist", chainID)) - return chain -} - -// GetChainID returns the chainID used for the provided index. -func GetChainID(index int) string { - return ChainIDPrefix + strconv.Itoa(index) -} - -// CommitBlock commits a block on the provided indexes and then increments the global time. -// -// CONTRACT: the passed in list of indexes must not contain duplicates -func (coord *Coordinator) CommitBlock(chains ...*TestChain) { - for _, chain := range chains { - chain.App.Commit() - chain.NextBlock() - } - coord.IncrementTime() -} - -// CommitNBlocks commits n blocks to state and updates the block height by 1 for each commit. -func (coord *Coordinator) CommitNBlocks(chain *TestChain, n uint64) { - for i := uint64(0); i < n; i++ { - chain.App.BeginBlock(abci.RequestBeginBlock{Header: chain.CurrentHeader}) - chain.App.Commit() - chain.NextBlock() - coord.IncrementTime() - } -} - -// ConnOpenInit initializes a connection on the source chain with the state INIT -// using the OpenInit handshake call. -// -// NOTE: The counterparty testing connection will be created even if it is not created in the -// application state. -func (coord *Coordinator) ConnOpenInit( - source, counterparty *TestChain, - clientID, counterpartyClientID string, -) (*TestConnection, *TestConnection, error) { - sourceConnection := source.AddTestConnection(clientID, counterpartyClientID) - counterpartyConnection := counterparty.AddTestConnection(counterpartyClientID, clientID) - - // initialize connection on source - if err := source.ConnectionOpenInit(counterparty, sourceConnection, counterpartyConnection); err != nil { - return sourceConnection, counterpartyConnection, err - } - coord.IncrementTime() - - // update source client on counterparty connection - if err := coord.UpdateClient( - counterparty, source, - counterpartyClientID, exported.Tendermint, - ); err != nil { - return sourceConnection, counterpartyConnection, err - } - - return sourceConnection, counterpartyConnection, nil -} - -// ConnOpenInitOnBothChains initializes a connection on the source chain with the state INIT -// using the OpenInit handshake call. -func (coord *Coordinator) ConnOpenInitOnBothChains( - source, counterparty *TestChain, - clientID, counterpartyClientID string, -) (*TestConnection, *TestConnection, error) { - sourceConnection := source.AddTestConnection(clientID, counterpartyClientID) - counterpartyConnection := counterparty.AddTestConnection(counterpartyClientID, clientID) - - // initialize connection on source - if err := source.ConnectionOpenInit(counterparty, sourceConnection, counterpartyConnection); err != nil { - return sourceConnection, counterpartyConnection, err - } - coord.IncrementTime() - - // initialize connection on counterparty - if err := counterparty.ConnectionOpenInit(source, counterpartyConnection, sourceConnection); err != nil { - return sourceConnection, counterpartyConnection, err - } - coord.IncrementTime() - - // update counterparty client on source connection - if err := coord.UpdateClient( - source, counterparty, - clientID, exported.Tendermint, - ); err != nil { - return sourceConnection, counterpartyConnection, err - } - - // update source client on counterparty connection - if err := coord.UpdateClient( - counterparty, source, - counterpartyClientID, exported.Tendermint, - ); err != nil { - return sourceConnection, counterpartyConnection, err - } - - return sourceConnection, counterpartyConnection, nil -} - -// ConnOpenTry initializes a connection on the source chain with the state TRYOPEN -// using the OpenTry handshake call. -func (coord *Coordinator) ConnOpenTry( - source, counterparty *TestChain, - sourceConnection, counterpartyConnection *TestConnection, -) error { - // initialize TRYOPEN connection on source - if err := source.ConnectionOpenTry(counterparty, sourceConnection, counterpartyConnection); err != nil { - return err - } - coord.IncrementTime() - - // update source client on counterparty connection - return coord.UpdateClient( - counterparty, source, - counterpartyConnection.ClientID, exported.Tendermint, - ) -} - -// ConnOpenAck initializes a connection on the source chain with the state OPEN -// using the OpenAck handshake call. -func (coord *Coordinator) ConnOpenAck( - source, counterparty *TestChain, - sourceConnection, counterpartyConnection *TestConnection, -) error { - // set OPEN connection on source using OpenAck - if err := source.ConnectionOpenAck(counterparty, sourceConnection, counterpartyConnection); err != nil { - return err - } - coord.IncrementTime() - - // update source client on counterparty connection - return coord.UpdateClient( - counterparty, source, - counterpartyConnection.ClientID, exported.Tendermint, - ) -} - -// ConnOpenConfirm initializes a connection on the source chain with the state OPEN -// using the OpenConfirm handshake call. -func (coord *Coordinator) ConnOpenConfirm( - source, counterparty *TestChain, - sourceConnection, counterpartyConnection *TestConnection, -) error { - if err := source.ConnectionOpenConfirm(counterparty, sourceConnection, counterpartyConnection); err != nil { - return err - } - coord.IncrementTime() - - // update source client on counterparty connection - return coord.UpdateClient( - counterparty, source, - counterpartyConnection.ClientID, exported.Tendermint, - ) -} - -// ChanOpenInit initializes a channel on the source chain with the state INIT -// using the OpenInit handshake call. -// -// NOTE: The counterparty testing channel will be created even if it is not created in the -// application state. -func (coord *Coordinator) ChanOpenInit( - source, counterparty *TestChain, - connection, counterpartyConnection *TestConnection, - sourcePortID, counterpartyPortID string, - order channeltypes.Order, -) (TestChannel, TestChannel, error) { - sourceChannel := source.AddTestChannel(connection, sourcePortID) - counterpartyChannel := counterparty.AddTestChannel(counterpartyConnection, counterpartyPortID) - - // NOTE: only creation of a capability for a transfer or mock port is supported - // Other applications must bind to the port in InitGenesis or modify this code. - source.CreatePortCapability(sourceChannel.PortID) - coord.IncrementTime() - - // initialize channel on source - if err := source.ChanOpenInit(sourceChannel, counterpartyChannel, order, connection.ID); err != nil { - return sourceChannel, counterpartyChannel, err - } - coord.IncrementTime() - - // update source client on counterparty connection - if err := coord.UpdateClient( - counterparty, source, - counterpartyConnection.ClientID, exported.Tendermint, - ); err != nil { - return sourceChannel, counterpartyChannel, err - } - - return sourceChannel, counterpartyChannel, nil -} - -// ChanOpenInitOnBothChains initializes a channel on the source chain and counterparty chain -// with the state INIT using the OpenInit handshake call. -func (coord *Coordinator) ChanOpenInitOnBothChains( - source, counterparty *TestChain, - connection, counterpartyConnection *TestConnection, - sourcePortID, counterpartyPortID string, - order channeltypes.Order, -) (TestChannel, TestChannel, error) { - sourceChannel := source.AddTestChannel(connection, sourcePortID) - counterpartyChannel := counterparty.AddTestChannel(counterpartyConnection, counterpartyPortID) - - // NOTE: only creation of a capability for a transfer or mock port is supported - // Other applications must bind to the port in InitGenesis or modify this code. - source.CreatePortCapability(sourceChannel.PortID) - counterparty.CreatePortCapability(counterpartyChannel.PortID) - coord.IncrementTime() - - // initialize channel on source - if err := source.ChanOpenInit(sourceChannel, counterpartyChannel, order, connection.ID); err != nil { - return sourceChannel, counterpartyChannel, err - } - coord.IncrementTime() - - // initialize channel on counterparty - if err := counterparty.ChanOpenInit(counterpartyChannel, sourceChannel, order, counterpartyConnection.ID); err != nil { - return sourceChannel, counterpartyChannel, err - } - coord.IncrementTime() - - // update counterparty client on source connection - if err := coord.UpdateClient( - source, counterparty, - connection.ClientID, exported.Tendermint, - ); err != nil { - return sourceChannel, counterpartyChannel, err - } - - // update source client on counterparty connection - if err := coord.UpdateClient( - counterparty, source, - counterpartyConnection.ClientID, exported.Tendermint, - ); err != nil { - return sourceChannel, counterpartyChannel, err - } - - return sourceChannel, counterpartyChannel, nil -} - -// ChanOpenTry initializes a channel on the source chain with the state TRYOPEN -// using the OpenTry handshake call. -func (coord *Coordinator) ChanOpenTry( - source, counterparty *TestChain, - sourceChannel, counterpartyChannel TestChannel, - connection *TestConnection, - order channeltypes.Order, -) error { - - // initialize channel on source - if err := source.ChanOpenTry(counterparty, sourceChannel, counterpartyChannel, order, connection.ID); err != nil { - return err - } - coord.IncrementTime() - - // update source client on counterparty connection - return coord.UpdateClient( - counterparty, source, - connection.CounterpartyClientID, exported.Tendermint, - ) -} - -// ChanOpenAck initializes a channel on the source chain with the state OPEN -// using the OpenAck handshake call. -func (coord *Coordinator) ChanOpenAck( - source, counterparty *TestChain, - sourceChannel, counterpartyChannel TestChannel, -) error { - - if err := source.ChanOpenAck(counterparty, sourceChannel, counterpartyChannel); err != nil { - return err - } - coord.IncrementTime() - - // update source client on counterparty connection - return coord.UpdateClient( - counterparty, source, - sourceChannel.CounterpartyClientID, exported.Tendermint, - ) -} - -// ChanOpenConfirm initializes a channel on the source chain with the state OPEN -// using the OpenConfirm handshake call. -func (coord *Coordinator) ChanOpenConfirm( - source, counterparty *TestChain, - sourceChannel, counterpartyChannel TestChannel, -) error { - - if err := source.ChanOpenConfirm(counterparty, sourceChannel, counterpartyChannel); err != nil { - return err - } - coord.IncrementTime() - - // update source client on counterparty connection - return coord.UpdateClient( - counterparty, source, - sourceChannel.CounterpartyClientID, exported.Tendermint, - ) -} - -// ChanCloseInit closes a channel on the source chain resulting in the channels state -// being set to CLOSED. -// -// NOTE: does not work with ibc-transfer module -func (coord *Coordinator) ChanCloseInit( - source, counterparty *TestChain, - channel TestChannel, -) error { - - if err := source.ChanCloseInit(counterparty, channel); err != nil { - return err - } - coord.IncrementTime() - - // update source client on counterparty connection - return coord.UpdateClient( - counterparty, source, - channel.CounterpartyClientID, exported.Tendermint, - ) -} - -// SetChannelClosed sets a channel state to CLOSED. -func (coord *Coordinator) SetChannelClosed( - source, counterparty *TestChain, - testChannel TestChannel, -) error { - channel := source.GetChannel(testChannel) - - channel.State = channeltypes.CLOSED - source.App.IBCKeeper.ChannelKeeper.SetChannel(source.GetContext(), testChannel.PortID, testChannel.ID, channel) - - coord.CommitBlock(source) - - // update source client on counterparty connection - return coord.UpdateClient( - counterparty, source, - testChannel.CounterpartyClientID, exported.Tendermint, - ) -} diff --git a/x/ibc/testing/mock/README.md b/x/ibc/testing/mock/README.md deleted file mode 100644 index 5da403f9c34f..000000000000 --- a/x/ibc/testing/mock/README.md +++ /dev/null @@ -1,6 +0,0 @@ -This package is only intended to be used for testing core IBC. In order to maintain secure -testing, we need to do message passing and execution which requires connecting an IBC application -module that fulfills all the callbacks. We cannot connect to ibc-transfer which does not support -all channel types so instead we create a mock application module which does nothing. It simply -return nil in all cases so no error ever occurs. It is intended to be as minimal and lightweight -as possible and should never import simapp. diff --git a/x/ibc/testing/mock/doc.go b/x/ibc/testing/mock/doc.go deleted file mode 100644 index eaaa42b2ab1a..000000000000 --- a/x/ibc/testing/mock/doc.go +++ /dev/null @@ -1,9 +0,0 @@ -/* -This package is only intended to be used for testing core IBC. In order to maintain secure -testing, we need to do message passing and execution which requires connecting an IBC application -module that fulfills all the callbacks. We cannot connect to ibc-transfer which does not support -all channel types so instead we create a mock application module which does nothing. It simply -return nil in all cases so no error ever occurs. It is intended to be as minimal and lightweight -as possible and should never import simapp. -*/ -package mock diff --git a/x/ibc/testing/mock/mock.go b/x/ibc/testing/mock/mock.go deleted file mode 100644 index 16e2ad345c2b..000000000000 --- a/x/ibc/testing/mock/mock.go +++ /dev/null @@ -1,186 +0,0 @@ -package mock - -import ( - "encoding/json" - - "github.com/cosmos/cosmos-sdk/types/module" - - "github.com/grpc-ecosystem/grpc-gateway/runtime" - - "github.com/gorilla/mux" - "github.com/spf13/cobra" - - abci "github.com/tendermint/tendermint/abci/types" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - sdk "github.com/cosmos/cosmos-sdk/types" - capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" - capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" -) - -const ( - ModuleName = "mock" -) - -var ( - MockAcknowledgement = []byte("mock acknowledgement") - MockCommitment = []byte("mock packet commitment") -) - -// AppModuleBasic is the mock AppModuleBasic. -type AppModuleBasic struct{} - -// Name implements AppModuleBasic interface. -func (AppModuleBasic) Name() string { - return ModuleName -} - -// RegisterLegacyAminoCodec implements AppModuleBasic interface. -func (AppModuleBasic) RegisterLegacyAminoCodec(*codec.LegacyAmino) {} - -// RegisterInterfaces implements AppModuleBasic interface. -func (AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) {} - -// DefaultGenesis implements AppModuleBasic interface. -func (AppModuleBasic) DefaultGenesis(cdc codec.JSONMarshaler) json.RawMessage { - return nil -} - -// ValidateGenesis implements the AppModuleBasic interface. -func (AppModuleBasic) ValidateGenesis(codec.JSONMarshaler, client.TxEncodingConfig, json.RawMessage) error { - return nil -} - -// RegisterRESTRoutes implements AppModuleBasic interface. -func (AppModuleBasic) RegisterRESTRoutes(clientCtx client.Context, rtr *mux.Router) {} - -// RegisterGRPCGatewayRoutes implements AppModuleBasic interface. -func (a AppModuleBasic) RegisterGRPCGatewayRoutes(_ client.Context, _ *runtime.ServeMux) {} - -// GetTxCmd implements AppModuleBasic interface. -func (AppModuleBasic) GetTxCmd() *cobra.Command { - return nil -} - -// GetQueryCmd implements AppModuleBasic interface. -func (AppModuleBasic) GetQueryCmd() *cobra.Command { - return nil -} - -// AppModule represents the AppModule for the mock module. -type AppModule struct { - AppModuleBasic - scopedKeeper capabilitykeeper.ScopedKeeper -} - -// NewAppModule returns a mock AppModule instance. -func NewAppModule(sk capabilitykeeper.ScopedKeeper) AppModule { - return AppModule{ - scopedKeeper: sk, - } -} - -// RegisterInvariants implements the AppModule interface. -func (AppModule) RegisterInvariants(ir sdk.InvariantRegistry) {} - -// Route implements the AppModule interface. -func (am AppModule) Route() sdk.Route { - return sdk.NewRoute(ModuleName, nil) -} - -// QuerierRoute implements the AppModule interface. -func (AppModule) QuerierRoute() string { - return "" -} - -// LegacyQuerierHandler implements the AppModule interface. -func (am AppModule) LegacyQuerierHandler(*codec.LegacyAmino) sdk.Querier { - return nil -} - -// RegisterServices implements the AppModule interface. -func (am AppModule) RegisterServices(module.Configurator) {} - -// InitGenesis implements the AppModule interface. -func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONMarshaler, data json.RawMessage) []abci.ValidatorUpdate { - return []abci.ValidatorUpdate{} -} - -// ExportGenesis implements the AppModule interface. -func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json.RawMessage { - return nil -} - -// BeginBlock implements the AppModule interface -func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { -} - -// EndBlock implements the AppModule interface -func (am AppModule) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) []abci.ValidatorUpdate { - return []abci.ValidatorUpdate{} -} - -// OnChanOpenInit implements the IBCModule interface. -func (am AppModule) OnChanOpenInit( - ctx sdk.Context, _ channeltypes.Order, _ []string, portID string, - channelID string, chanCap *capabilitytypes.Capability, _ channeltypes.Counterparty, _ string, -) error { - // Claim channel capability passed back by IBC module - if err := am.scopedKeeper.ClaimCapability(ctx, chanCap, host.ChannelCapabilityPath(portID, channelID)); err != nil { - return err - } - - return nil -} - -// OnChanOpenTry implements the IBCModule interface. -func (am AppModule) OnChanOpenTry( - ctx sdk.Context, _ channeltypes.Order, _ []string, portID string, - channelID string, chanCap *capabilitytypes.Capability, _ channeltypes.Counterparty, _, _ string, -) error { - // Claim channel capability passed back by IBC module - if err := am.scopedKeeper.ClaimCapability(ctx, chanCap, host.ChannelCapabilityPath(portID, channelID)); err != nil { - return err - } - - return nil -} - -// OnChanOpenAck implements the IBCModule interface. -func (am AppModule) OnChanOpenAck(sdk.Context, string, string, string) error { - return nil -} - -// OnChanOpenConfirm implements the IBCModule interface. -func (am AppModule) OnChanOpenConfirm(sdk.Context, string, string) error { - return nil -} - -// OnChanCloseInit implements the IBCModule interface. -func (am AppModule) OnChanCloseInit(sdk.Context, string, string) error { - return nil -} - -// OnChanCloseConfirm implements the IBCModule interface. -func (am AppModule) OnChanCloseConfirm(sdk.Context, string, string) error { - return nil -} - -// OnRecvPacket implements the IBCModule interface. -func (am AppModule) OnRecvPacket(sdk.Context, channeltypes.Packet) (*sdk.Result, []byte, error) { - return nil, MockAcknowledgement, nil -} - -// OnAcknowledgementPacket implements the IBCModule interface. -func (am AppModule) OnAcknowledgementPacket(sdk.Context, channeltypes.Packet, []byte) (*sdk.Result, error) { - return nil, nil -} - -// OnTimeoutPacket implements the IBCModule interface. -func (am AppModule) OnTimeoutPacket(sdk.Context, channeltypes.Packet) (*sdk.Result, error) { - return nil, nil -} diff --git a/x/ibc/testing/mock/privval.go b/x/ibc/testing/mock/privval.go deleted file mode 100644 index fe46659b3df9..000000000000 --- a/x/ibc/testing/mock/privval.go +++ /dev/null @@ -1,50 +0,0 @@ -package mock - -import ( - "github.com/tendermint/tendermint/crypto" - tmproto "github.com/tendermint/tendermint/proto/tendermint/types" - tmtypes "github.com/tendermint/tendermint/types" - - cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" - "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" -) - -var _ tmtypes.PrivValidator = PV{} - -// MockPV implements PrivValidator without any safety or persistence. -// Only use it for testing. -type PV struct { - PrivKey cryptotypes.PrivKey -} - -func NewPV() PV { - return PV{ed25519.GenPrivKey()} -} - -// GetPubKey implements PrivValidator interface -func (pv PV) GetPubKey() (crypto.PubKey, error) { - return cryptocodec.ToTmPubKeyInterface(pv.PrivKey.PubKey()) -} - -// SignVote implements PrivValidator interface -func (pv PV) SignVote(chainID string, vote *tmproto.Vote) error { - signBytes := tmtypes.VoteSignBytes(chainID, vote) - sig, err := pv.PrivKey.Sign(signBytes) - if err != nil { - return err - } - vote.Signature = sig - return nil -} - -// SignProposal implements PrivValidator interface -func (pv PV) SignProposal(chainID string, proposal *tmproto.Proposal) error { - signBytes := tmtypes.ProposalSignBytes(chainID, proposal) - sig, err := pv.PrivKey.Sign(signBytes) - if err != nil { - return err - } - proposal.Signature = sig - return nil -} diff --git a/x/ibc/testing/mock/privval_test.go b/x/ibc/testing/mock/privval_test.go deleted file mode 100644 index b9f0487a36d5..000000000000 --- a/x/ibc/testing/mock/privval_test.go +++ /dev/null @@ -1,44 +0,0 @@ -package mock_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - tmproto "github.com/tendermint/tendermint/proto/tendermint/types" - tmtypes "github.com/tendermint/tendermint/types" - - "github.com/cosmos/cosmos-sdk/x/ibc/testing/mock" -) - -const chainID = "testChain" - -func TestGetPubKey(t *testing.T) { - pv := mock.NewPV() - pk, err := pv.GetPubKey() - require.NoError(t, err) - require.Equal(t, "ed25519", pk.Type()) -} - -func TestSignVote(t *testing.T) { - pv := mock.NewPV() - pk, _ := pv.GetPubKey() - - vote := &tmproto.Vote{Height: 2} - pv.SignVote(chainID, vote) - - msg := tmtypes.VoteSignBytes(chainID, vote) - ok := pk.VerifySignature(msg, vote.Signature) - require.True(t, ok) -} - -func TestSignProposal(t *testing.T) { - pv := mock.NewPV() - pk, _ := pv.GetPubKey() - - proposal := &tmproto.Proposal{Round: 2} - pv.SignProposal(chainID, proposal) - - msg := tmtypes.ProposalSignBytes(chainID, proposal) - ok := pk.VerifySignature(msg, proposal.Signature) - require.True(t, ok) -} diff --git a/x/ibc/testing/solomachine.go b/x/ibc/testing/solomachine.go deleted file mode 100644 index bee63785978b..000000000000 --- a/x/ibc/testing/solomachine.go +++ /dev/null @@ -1,321 +0,0 @@ -package ibctesting - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/codec" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig" - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" - "github.com/cosmos/cosmos-sdk/crypto/types/multisig" - "github.com/cosmos/cosmos-sdk/types/tx/signing" - clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types" - commitmenttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/23-commitment/types" - host "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host" - "github.com/cosmos/cosmos-sdk/x/ibc/core/exported" - solomachinetypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/06-solomachine/types" -) - -var prefix = commitmenttypes.NewMerklePrefix([]byte("ibc")) - -// Solomachine is a testing helper used to simulate a counterparty -// solo machine client. -type Solomachine struct { - t *testing.T - - cdc codec.BinaryMarshaler - ClientID string - PrivateKeys []cryptotypes.PrivKey // keys used for signing - PublicKeys []cryptotypes.PubKey // keys used for generating solo machine pub key - PublicKey cryptotypes.PubKey // key used for verification - Sequence uint64 - Time uint64 - Diversifier string -} - -// NewSolomachine returns a new solomachine instance with an `nKeys` amount of -// generated private/public key pairs and a sequence starting at 1. If nKeys -// is greater than 1 then a multisig public key is used. -func NewSolomachine(t *testing.T, cdc codec.BinaryMarshaler, clientID, diversifier string, nKeys uint64) *Solomachine { - privKeys, pubKeys, pk := GenerateKeys(t, nKeys) - - return &Solomachine{ - t: t, - cdc: cdc, - ClientID: clientID, - PrivateKeys: privKeys, - PublicKeys: pubKeys, - PublicKey: pk, - Sequence: 1, - Time: 10, - Diversifier: diversifier, - } -} - -// GenerateKeys generates a new set of secp256k1 private keys and public keys. -// If the number of keys is greater than one then the public key returned represents -// a multisig public key. The private keys are used for signing, the public -// keys are used for generating the public key and the public key is used for -// solo machine verification. The usage of secp256k1 is entirely arbitrary. -// The key type can be swapped for any key type supported by the PublicKey -// interface, if needed. The same is true for the amino based Multisignature -// public key. -func GenerateKeys(t *testing.T, n uint64) ([]cryptotypes.PrivKey, []cryptotypes.PubKey, cryptotypes.PubKey) { - require.NotEqual(t, uint64(0), n, "generation of zero keys is not allowed") - - privKeys := make([]cryptotypes.PrivKey, n) - pubKeys := make([]cryptotypes.PubKey, n) - for i := uint64(0); i < n; i++ { - privKeys[i] = secp256k1.GenPrivKey() - pubKeys[i] = privKeys[i].PubKey() - } - - var pk cryptotypes.PubKey - if len(privKeys) > 1 { - // generate multi sig pk - pk = kmultisig.NewLegacyAminoPubKey(int(n), pubKeys) - } else { - pk = privKeys[0].PubKey() - } - - return privKeys, pubKeys, pk -} - -// ClientState returns a new solo machine ClientState instance. Default usage does not allow update -// after governance proposal -func (solo *Solomachine) ClientState() *solomachinetypes.ClientState { - return solomachinetypes.NewClientState(solo.Sequence, solo.ConsensusState(), false) -} - -// ConsensusState returns a new solo machine ConsensusState instance -func (solo *Solomachine) ConsensusState() *solomachinetypes.ConsensusState { - publicKey, err := codectypes.NewAnyWithValue(solo.PublicKey) - require.NoError(solo.t, err) - - return &solomachinetypes.ConsensusState{ - PublicKey: publicKey, - Diversifier: solo.Diversifier, - Timestamp: solo.Time, - } -} - -// GetHeight returns an exported.Height with Sequence as RevisionHeight -func (solo *Solomachine) GetHeight() exported.Height { - return clienttypes.NewHeight(0, solo.Sequence) -} - -// CreateHeader generates a new private/public key pair and creates the -// necessary signature to construct a valid solo machine header. -func (solo *Solomachine) CreateHeader() *solomachinetypes.Header { - // generate new private keys and signature for header - newPrivKeys, newPubKeys, newPubKey := GenerateKeys(solo.t, uint64(len(solo.PrivateKeys))) - - publicKey, err := codectypes.NewAnyWithValue(newPubKey) - require.NoError(solo.t, err) - - data := &solomachinetypes.HeaderData{ - NewPubKey: publicKey, - NewDiversifier: solo.Diversifier, - } - - dataBz, err := solo.cdc.MarshalBinaryBare(data) - require.NoError(solo.t, err) - - signBytes := &solomachinetypes.SignBytes{ - Sequence: solo.Sequence, - Timestamp: solo.Time, - Diversifier: solo.Diversifier, - DataType: solomachinetypes.HEADER, - Data: dataBz, - } - - bz, err := solo.cdc.MarshalBinaryBare(signBytes) - require.NoError(solo.t, err) - - sig := solo.GenerateSignature(bz) - - header := &solomachinetypes.Header{ - Sequence: solo.Sequence, - Timestamp: solo.Time, - Signature: sig, - NewPublicKey: publicKey, - NewDiversifier: solo.Diversifier, - } - - // assumes successful header update - solo.Sequence++ - solo.PrivateKeys = newPrivKeys - solo.PublicKeys = newPubKeys - solo.PublicKey = newPubKey - - return header -} - -// CreateMisbehaviour constructs testing misbehaviour for the solo machine client -// by signing over two different data bytes at the same sequence. -func (solo *Solomachine) CreateMisbehaviour() *solomachinetypes.Misbehaviour { - path := solo.GetClientStatePath("counterparty") - dataOne, err := solomachinetypes.ClientStateDataBytes(solo.cdc, path, solo.ClientState()) - require.NoError(solo.t, err) - - path = solo.GetConsensusStatePath("counterparty", clienttypes.NewHeight(0, 1)) - dataTwo, err := solomachinetypes.ConsensusStateDataBytes(solo.cdc, path, solo.ConsensusState()) - require.NoError(solo.t, err) - - signBytes := &solomachinetypes.SignBytes{ - Sequence: solo.Sequence, - Timestamp: solo.Time, - Diversifier: solo.Diversifier, - DataType: solomachinetypes.CLIENT, - Data: dataOne, - } - - bz, err := solo.cdc.MarshalBinaryBare(signBytes) - require.NoError(solo.t, err) - - sig := solo.GenerateSignature(bz) - signatureOne := solomachinetypes.SignatureAndData{ - Signature: sig, - DataType: solomachinetypes.CLIENT, - Data: dataOne, - Timestamp: solo.Time, - } - - // misbehaviour signaturess can have different timestamps - solo.Time++ - - signBytes = &solomachinetypes.SignBytes{ - Sequence: solo.Sequence, - Timestamp: solo.Time, - Diversifier: solo.Diversifier, - DataType: solomachinetypes.CONSENSUS, - Data: dataTwo, - } - - bz, err = solo.cdc.MarshalBinaryBare(signBytes) - require.NoError(solo.t, err) - - sig = solo.GenerateSignature(bz) - signatureTwo := solomachinetypes.SignatureAndData{ - Signature: sig, - DataType: solomachinetypes.CONSENSUS, - Data: dataTwo, - Timestamp: solo.Time, - } - - return &solomachinetypes.Misbehaviour{ - ClientId: solo.ClientID, - Sequence: solo.Sequence, - SignatureOne: &signatureOne, - SignatureTwo: &signatureTwo, - } -} - -// GenerateSignature uses the stored private keys to generate a signature -// over the sign bytes with each key. If the amount of keys is greater than -// 1 then a multisig data type is returned. -func (solo *Solomachine) GenerateSignature(signBytes []byte) []byte { - sigs := make([]signing.SignatureData, len(solo.PrivateKeys)) - for i, key := range solo.PrivateKeys { - sig, err := key.Sign(signBytes) - require.NoError(solo.t, err) - - sigs[i] = &signing.SingleSignatureData{ - Signature: sig, - } - } - - var sigData signing.SignatureData - if len(sigs) == 1 { - // single public key - sigData = sigs[0] - } else { - // generate multi signature data - multiSigData := multisig.NewMultisig(len(sigs)) - for i, sig := range sigs { - multisig.AddSignature(multiSigData, sig, i) - } - - sigData = multiSigData - } - - protoSigData := signing.SignatureDataToProto(sigData) - bz, err := solo.cdc.MarshalBinaryBare(protoSigData) - require.NoError(solo.t, err) - - return bz -} - -// GetClientStatePath returns the commitment path for the client state. -func (solo *Solomachine) GetClientStatePath(counterpartyClientIdentifier string) commitmenttypes.MerklePath { - path, err := commitmenttypes.ApplyPrefix(prefix, commitmenttypes.NewMerklePath(host.FullClientStatePath(counterpartyClientIdentifier))) - require.NoError(solo.t, err) - - return path -} - -// GetConsensusStatePath returns the commitment path for the consensus state. -func (solo *Solomachine) GetConsensusStatePath(counterpartyClientIdentifier string, consensusHeight exported.Height) commitmenttypes.MerklePath { - path, err := commitmenttypes.ApplyPrefix(prefix, commitmenttypes.NewMerklePath(host.FullConsensusStatePath(counterpartyClientIdentifier, consensusHeight))) - require.NoError(solo.t, err) - - return path -} - -// GetConnectionStatePath returns the commitment path for the connection state. -func (solo *Solomachine) GetConnectionStatePath(connID string) commitmenttypes.MerklePath { - connectionPath := commitmenttypes.NewMerklePath(host.ConnectionPath(connID)) - path, err := commitmenttypes.ApplyPrefix(prefix, connectionPath) - require.NoError(solo.t, err) - - return path -} - -// GetChannelStatePath returns the commitment path for that channel state. -func (solo *Solomachine) GetChannelStatePath(portID, channelID string) commitmenttypes.MerklePath { - channelPath := commitmenttypes.NewMerklePath(host.ChannelPath(portID, channelID)) - path, err := commitmenttypes.ApplyPrefix(prefix, channelPath) - require.NoError(solo.t, err) - - return path -} - -// GetPacketCommitmentPath returns the commitment path for a packet commitment. -func (solo *Solomachine) GetPacketCommitmentPath(portID, channelID string) commitmenttypes.MerklePath { - commitmentPath := commitmenttypes.NewMerklePath(host.PacketCommitmentPath(portID, channelID, solo.Sequence)) - path, err := commitmenttypes.ApplyPrefix(prefix, commitmentPath) - require.NoError(solo.t, err) - - return path -} - -// GetPacketAcknowledgementPath returns the commitment path for a packet acknowledgement. -func (solo *Solomachine) GetPacketAcknowledgementPath(portID, channelID string) commitmenttypes.MerklePath { - ackPath := commitmenttypes.NewMerklePath(host.PacketAcknowledgementPath(portID, channelID, solo.Sequence)) - path, err := commitmenttypes.ApplyPrefix(prefix, ackPath) - require.NoError(solo.t, err) - - return path -} - -// GetPacketReceiptPath returns the commitment path for a packet receipt -// and an absent receipts. -func (solo *Solomachine) GetPacketReceiptPath(portID, channelID string) commitmenttypes.MerklePath { - receiptPath := commitmenttypes.NewMerklePath(host.PacketReceiptPath(portID, channelID, solo.Sequence)) - path, err := commitmenttypes.ApplyPrefix(prefix, receiptPath) - require.NoError(solo.t, err) - - return path -} - -// GetNextSequenceRecvPath returns the commitment path for the next sequence recv counter. -func (solo *Solomachine) GetNextSequenceRecvPath(portID, channelID string) commitmenttypes.MerklePath { - nextSequenceRecvPath := commitmenttypes.NewMerklePath(host.NextSequenceRecvPath(portID, channelID)) - path, err := commitmenttypes.ApplyPrefix(prefix, nextSequenceRecvPath) - require.NoError(solo.t, err) - - return path -} diff --git a/x/ibc/testing/types.go b/x/ibc/testing/types.go deleted file mode 100644 index 16cda6216b19..000000000000 --- a/x/ibc/testing/types.go +++ /dev/null @@ -1,44 +0,0 @@ -package ibctesting - -import ( - channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types" -) - -// TestConnection is a testing helper struct to keep track of the connectionID, source clientID, -// counterparty clientID, and the next channel version used in creating and interacting with a -// connection. -type TestConnection struct { - ID string - ClientID string - CounterpartyClientID string - NextChannelVersion string - Channels []TestChannel -} - -// FirstOrNextTestChannel returns the first test channel if it exists, otherwise it -// returns the next test channel to be created. This function is expected to be used -// when the caller does not know if the channel has or has not been created in app -// state, but would still like to refer to it to test existence or non-existence. -func (conn *TestConnection) FirstOrNextTestChannel(portID string) TestChannel { - if len(conn.Channels) > 0 { - return conn.Channels[0] - } - return TestChannel{ - PortID: portID, - ID: channeltypes.FormatChannelIdentifier(0), - ClientID: conn.ClientID, - CounterpartyClientID: conn.CounterpartyClientID, - Version: conn.NextChannelVersion, - } -} - -// TestChannel is a testing helper struct to keep track of the portID and channelID -// used in creating and interacting with a channel. The clientID and counterparty -// client ID are also tracked to cut down on querying and argument passing. -type TestChannel struct { - PortID string - ID string - ClientID string - CounterpartyClientID string - Version string -} From 95fa768671006aa8f775207a9feaa47dccba01a5 Mon Sep 17 00:00:00 2001 From: Amaury <1293565+amaurym@users.noreply.github.com> Date: Thu, 4 Mar 2021 18:28:35 +0100 Subject: [PATCH 155/214] ADR 041: In-Place Store Migrations (#8646) * Initial draft * Draft * Add x/upgrade stuff * Tweaks * Update docs/architecture/adr-041-in-place-store-migrations.md Co-authored-by: Anil Kumar Kammari * Reviews * Use migrator * Update docs/architecture/adr-041-in-place-store-migrations.md Co-authored-by: Robert Zaremba * Update docs/architecture/adr-041-in-place-store-migrations.md Co-authored-by: Aaron Craelius * Update docs/architecture/adr-041-in-place-store-migrations.md Co-authored-by: Robert Zaremba * Update docs/architecture/adr-041-in-place-store-migrations.md Co-authored-by: Robert Zaremba * Update docs/architecture/adr-041-in-place-store-migrations.md Co-authored-by: Robert Zaremba * Update docs/architecture/adr-041-in-place-store-migrations.md Co-authored-by: Robert Zaremba * Update docs/architecture/adr-041-in-place-store-migrations.md Co-authored-by: Robert Zaremba * Update docs/architecture/adr-041-in-place-store-migrations.md Co-authored-by: Robert Zaremba * More fixes * Add grpc, use functions * Add special case with 0 version * Update docs/architecture/adr-041-in-place-store-migrations.md Co-authored-by: Aaron Craelius * Update docs/architecture/adr-041-in-place-store-migrations.md Co-authored-by: Aaron Craelius * Update docs/architecture/adr-041-in-place-store-migrations.md Co-authored-by: Aaron Craelius * Remove useless err return Co-authored-by: Jonathan Gimeno Co-authored-by: Anil Kumar Kammari Co-authored-by: Robert Zaremba Co-authored-by: Aaron Craelius Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- .../adr-041-in-place-store-migrations.md | 180 ++++++++++++++++++ .../architecture/readme.md~origin_master-docs | 5 - 2 files changed, 180 insertions(+), 5 deletions(-) create mode 100644 docs/architecture/adr-041-in-place-store-migrations.md delete mode 100644 docs/architecture/readme.md~origin_master-docs diff --git a/docs/architecture/adr-041-in-place-store-migrations.md b/docs/architecture/adr-041-in-place-store-migrations.md new file mode 100644 index 000000000000..2286c6d2d9bf --- /dev/null +++ b/docs/architecture/adr-041-in-place-store-migrations.md @@ -0,0 +1,180 @@ +# ADR 041: In-Place Store Migrations + +## Changelog + +- 17.02.2021: Initial Draft + +## Status + +Accepted + +## Abstract + +This ADR introduces a mechanism to perform in-place state store migrations during chain software upgrades. + +## Context + +When a chain upgrade introduces state-breaking changes inside modules, the current procedure consists of exporting the whole state into a JSON file (via the `simd export` command), running migration scripts on the JSON file (`simd migrate` command), clearing the stores (`simd unsafe-reset-all` command), and starting a new chain with the migrated JSON file as new genesis (optionally with a custom initial block height). An example of such a procedure can be seen [in the Cosmos Hub 3->4 migration guide](https://github.com/cosmos/gaia/blob/v4.0.3/docs/migration/cosmoshub-3.md#upgrade-procedure). + +This procedure is cumbersome for multiple reasons: + +- The procedure takes time. It can take hours to run the `export` command, plus some additional hours to run `InitChain` on the fresh chain using the migrated JSON. +- The exported JSON file can be heavy (~100MB-1GB), making it difficult to view, edit and transfer, which in turn introduces additional work to solve these problems (such as [streaming genesis](https://github.com/cosmos/cosmos-sdk/issues/6936)). + +## Decision + +We propose a migration procedure based on modifying the KV store in-place without involving the JSON export-process-import flow described above. + +### Module `ConsensusVersion` + +We introduce a new method on the `AppModule` interface: + +```go +type AppModule interface { + // --snip-- + ConsensusVersion() uint64 +} +``` + +This methods returns an `uint64` which serves as state-breaking version of the module. It MUST be incremented on each consensus-breaking change introduced by the module. To avoid potential errors with default values, the initial version of a module MUST be set to 1. In the SDK, version 1 corresponds to the modules in the v0.41 series. + +### Module-Specific Migration Functions + +For each consensus-breaking change introduced by the module, a migration script from ConsensusVersion `N` to version `N+1` MUST be registered in the `Configurator` using its newly-added `RegisterMigration` method. All modules receive a reference to the configurator in their `RegisterServices` method on `AppModule`, and this is where the migration functions should be registered. The migration functions should be registered in increasing order. + +```go +func (am AppModule) RegisterServices(cfg module.Configurator) { + // --snip-- + cfg.RegisterMigration(types.ModuleName, 1, func(ctx sdk.Context) error { + // Perform in-place store migrations from ConsensusVersion 1 to 2. + }) + cfg.RegisterMigration(types.ModuleName, 2, func(ctx sdk.Context) error { + // Perform in-place store migrations from ConsensusVersion 2 to 3. + }) + // etc. +} +``` + +For example, if the new ConsensusVersion of a module is `N` , then `N-1` migration functions MUST be registered in the configurator. + +In the SDK, the migration functions are handled by each module's keeper, because the keeper holds the `sdk.StoreKey` used to perform in-place store migrations. To not overload the keeper, a `Migrator` wrapper is used by each module to handle the migration functions: + +```go +// Migrator is a struct for handling in-place store migrations. +type Migrator struct { + BaseKeeper +} +``` + +Since migration functions manipulate legacy code, they should live inside the `legacy/` folder of each module, and be called by the Migrator's methods. We propose the format `Migrate{M}to{N}` for method names. + +```go +// Migrate1to2 migrates from version 1 to 2. +func (m Migrator) Migrate1to2(ctx sdk.Context) error { + return v042bank.MigrateStore(ctx, m.keeper.storeKey) // v042bank is package `x/bank/legacy/v042`. +} +``` + +Each module's migration functions are specific to the module's store evolutions, and are not described in this ADR. An example of x/bank store key migrations following the introduction of ADR-028 length-prefixed addresses can be seen [here](https://github.com/cosmos/cosmos-sdk/blob/ef8dabcf0f2ecaf26db1c6c6d5922e9399458bb3/x/bank/legacy/v042/store.go#L15). + +### Tracking Module Versions in `x/upgrade` + +We introduce a new prefix store in `x/upgrade`'s store. This store will track each module's current version, it can be modelized as a `map[string]uint64` of module name to module ConsensusVersion, and will be used when running the migrations (see next section for details). The key prefix used is `0x1`, and the key/value format is: + +``` +0x2 | {bytes(module_name)} => LittleEndian(module_consensus_version) +``` + +s +We add a new private field `versionManager` of type `VersionManager` to `x/upgrade`'s keeper, where `VersionManager` is: + +```go +type VersionManager interface { + GetConsensusVersions() VersionMap +} + +// Map of module name => new module Consensus Version. +type VersionMap map[string]uint64 +``` + +This `versionManager` field can be modified via the `SetVersionManager` field, and will allow the upgrade keeper to know the current versions of loaded modules. `SetVersionManager` MUST be called as early as possible in the app initialization; in the SDK's `simapp`, it is called in the `NewSimApp` constructor function. + +The UpgradeHandler signature needs to be updated to take a `VersionMap`, as well as return an error: + +```diff +- type UpgradeHandler func(ctx sdk.Context, plan Plan) ++ type UpgradeHandler func(ctx sdk.Context, plan Plan, versionMap VersionMap) error +``` + +To apply an upgrade, we query the `VersionMap` from the `x/upgrade` store and pass it into the handler. The handler runs the actual migration functions (see next section), and if successful, the current ConsensusVersions of all loaded modules will be stored into state. + +```diff +func (k UpgradeKeeper) ApplyUpgrade(ctx sdk.Context, plan types.Plan) { + // --snip-- +- handler(ctx, plan) ++ err := handler(ctx, plan, k.GetConsensusVersions()) // k.GetConsensusVersions() fetches the VersionMap stored in state. ++ if err != nil { ++ return err ++ } ++ ++ // Get the current ConsensusVersions of the loaded modules (retrieved from ++ // `k.versionManager`), and save them to state. ++ k.SetCurrentConsensusVersions() +} +``` + +An gRPC query endpoint to query the `VersionMap` stored in `x/upgrade`'s state will also be added, so that app developers can double-check the `VersionMap` before the upgrade handler runs. + +### Running Migrations + +Once all the migration handlers are registered inside the configurator (which happens at startup), running migrations can happen by calling the `RunMigrations` method on `module.Manager`. This function will loop through all modules, and for each module: + +- Get the old ConsensusVersion of the module from its `VersionMap` argument (let's call it `M`). +- Fetch the new ConsensusVersion of the module from the `ConsensusVersion()` method on `AppModule` (call it `N`). +- If `N>M`, run all registered migrations for the module sequentially `M -> M+1 -> M+2...` until `N`. + - There is a special case where there is no ConsensusVersion for the module, as this means that the module has been newly added during the upgrade. In this case, no migration function is run, and the module's current ConsensusVersion is saved to `x/upgrade`'s store. + +If a required migration is missing (e.g. if it has not been registered in the `Configurator`), then the `RunMigrations` function will error. + +In practice, the `RunMigrations` method should be called from inside an `UpgradeHandler`. + +```go +app.UpgradeKeeper.SetUpgradeHandler("my-plan", func(ctx sdk.Context, plan upgradetypes.Plan, versionMap VersionMap) error { + return app.mm.RunMigrations(ctx, versionMap) +}) +``` + +Assuming a chain upgrades at block `n`, the procedure should run as follows: + +- the old binary will halt in `BeginBlock` when starting block `N`. In its store, the ConsensusVersions of the old binary's modules are stored. +- the new binary will start at block `N`. The UpgradeHandler is set in the new binary, so will run at `BeginBlock` of the new binary. Inside `x/upgrade`'s `ApplyUpgrade`, the `VersionMap` will be retrieved from the (old binary's) store, and passed into the `RunMigrations` functon, migrating all module stores in-place before the modules' own `BeginBlock`s. + +## Consequences + +### Backwards Compatibility + +This ADR introduces a new method `ConsensusVersion()` on `AppModule`, which all modules need to implement. It also alters the UpgradeHandler function signature. As such, it is not backwards-compatible. + +While modules MUST register their migration functions when bumping ConsensusVersions, running those scripts using an upgrade handler is optional. An application may perfectly well decide to not call the `RunMigrations` inside its upgrade handler, and continue using the legacy JSON migration path. + +### Positive + +- Perform chain upgrades without manipulating JSON files. +- While no benchmark has been made yet, it is probable that in-place store migrations will take less time than JSON migrations. The main reason supporting this claim is that both the `simd export` command on the old binary and the `InitChain` function on the new binary will be skipped. + +### Negative + +- Module developers MUST correctly track consensus-breaking changes in their modules. If a consensus-breaking change is introduced in a module without its corresponding `ConsensusVersion()` bump, then the `RunMigrations` function won't detect the migration, and the chain upgrade might be unsuccessful. Documentation should clearly reflect this. + +### Neutral + +- The SDK will continue to support JSON migrations via the existing `simd export` and `simd migrate` commands. +- The current ADR does not allow creating, renaming or deleting stores, only modifying existing store keys and values. The SDK already has the `StoreLoader` for those operations. + +## Further Discussions + +## References + +- Initial discussion: https://github.com/cosmos/cosmos-sdk/discussions/8429 +- Implementation of `ConsensusVersion` and `RunMigrations`: https://github.com/cosmos/cosmos-sdk/pull/8485 +- Issue discussing `x/upgrade` design: https://github.com/cosmos/cosmos-sdk/issues/8514 diff --git a/docs/architecture/readme.md~origin_master-docs b/docs/architecture/readme.md~origin_master-docs deleted file mode 100644 index f0c07cb68565..000000000000 --- a/docs/architecture/readme.md~origin_master-docs +++ /dev/null @@ -1,5 +0,0 @@ ---- -order: false -parent: - order: false ---- From 82aedba11ebebfa1fd343c9ec139d04f032ef1ff Mon Sep 17 00:00:00 2001 From: Marko Date: Thu, 4 Mar 2021 20:40:01 +0000 Subject: [PATCH 156/214] logging (#8785) Co-authored-by: Alessio Treglia Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- x/crisis/keeper/keeper.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/crisis/keeper/keeper.go b/x/crisis/keeper/keeper.go index 1cfa29d5e2da..b9c563d5293d 100644 --- a/x/crisis/keeper/keeper.go +++ b/x/crisis/keeper/keeper.go @@ -76,7 +76,7 @@ func (k Keeper) AssertInvariants(ctx sdk.Context) { invarRoutes := k.Routes() n := len(invarRoutes) for i, ir := range invarRoutes { - logger.Info("asserting crisis invariants", "inv", fmt.Sprint(i, "/", n)) + logger.Info("asserting crisis invariants", "inv", fmt.Sprint(i, "/", n), "name", ir.FullRoute()) if res, stop := ir.Invar(ctx); stop { // TODO: Include app name as part of context to allow for this to be // variable. From 72fb8b3ca3fbe0ef859739f8ae88f5bbb90cf84e Mon Sep 17 00:00:00 2001 From: SaReN Date: Fri, 5 Mar 2021 02:42:17 +0530 Subject: [PATCH 157/214] revert unintended skip test (#8789) Co-authored-by: Alessio Treglia --- x/feegrant/simulation/decoder_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/x/feegrant/simulation/decoder_test.go b/x/feegrant/simulation/decoder_test.go index 7b991849a239..887111845636 100644 --- a/x/feegrant/simulation/decoder_test.go +++ b/x/feegrant/simulation/decoder_test.go @@ -22,7 +22,6 @@ var ( ) func TestDecodeStore(t *testing.T) { - t.Skip() cdc := simapp.MakeTestEncodingConfig().Marshaler dec := simulation.NewDecodeStore(cdc) From a18f0b111af8e077b0c2637d164148523226192f Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Thu, 4 Mar 2021 22:31:42 +0100 Subject: [PATCH 158/214] Enable secp256r1 (#8786) * enable secp256r1 in antehandlers * Add sig verification benchamrk to find a sigverify fee * adjust the gas fee * enable secp256r1 in antehandlers * Add sig verification benchamrk to find a sigverify fee * adjust the gas fee * Update the secp256r1 fee factor * Update changelog * regenerate docs --- CHANGELOG.md | 9 +++--- crypto/keys/secp256r1/keys.pb.go | 2 +- docs/core/proto-docs.md | 19 +---------- testutil/testdata/tx.go | 11 +++++++ x/auth/ante/sigverify.go | 5 +++ x/auth/ante/sigverify_benchmark_test.go | 42 +++++++++++++++++++++++++ x/auth/ante/sigverify_test.go | 31 +++++++++--------- x/auth/types/params.go | 10 ++++++ 8 files changed, 92 insertions(+), 37 deletions(-) create mode 100644 x/auth/ante/sigverify_benchmark_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 77651cc69cd0..fd2ae140a917 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,13 +38,14 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## Features -* [\#8559](https://github.com/cosmos/cosmos-sdk/pull/8559) Adding Protobuf compatible secp256r1 ECDSA signatures. +* [\#8559](https://github.com/cosmos/cosmos-sdk/pull/8559) Added Protobuf compatible secp256r1 ECDSA signatures. +* [\#8786](https://github.com/cosmos/cosmos-sdk/pull/8786) Enabled secp256r1 in x/auth. ### Client Breaking Changes * [\#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. -* (crypto/ed25519) [\#8690] Adopt zip1215 ed2559 verification rules. +* (crypto/ed25519) [\#8690] Adopt zip1215 ed2559 verification rules. ### API Breaking Changes @@ -55,7 +56,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (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. * [\#8629](https://github.com/cosmos/cosmos-sdk/pull/8629) Deprecated `SetFullFundraiserPath` from `Config` in favor of `SetPurpose` and `SetCoinType`. -* (x/upgrade) [\#8673](https://github.com/cosmos/cosmos-sdk/pull/8673) Remove IBC logic from x/upgrade. Deprecates IBC fields in an Upgrade Plan. IBC upgrade logic moved to 02-client and an IBC UpgradeProposal is added. +* (x/upgrade) [\#8673](https://github.com/cosmos/cosmos-sdk/pull/8673) Remove IBC logic from x/upgrade. Deprecates IBC fields in an Upgrade Plan. IBC upgrade logic moved to 02-client and an IBC UpgradeProposal is added. * (x/bank) [\#8517](https://github.com/cosmos/cosmos-sdk/pull/8517) `SupplyI` interface and `Supply` are removed and uses `sdk.Coins` for supply tracking ### State Machine Breaking @@ -72,7 +73,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (x/bank) [\#8614](https://github.com/cosmos/cosmos-sdk/issues/8614) Add `Name` and `Symbol` fields to denom metadata * (x/auth) [\#8522](https://github.com/cosmos/cosmos-sdk/pull/8522) Allow to query all stored accounts -* (x/ibc) [\#7949](https://github.com/cosmos/cosmos-sdk/issues/7949) Standardized channel `Acknowledgement` moved to its own file. Codec registration redundancy removed. +* (x/ibc) [\#7949](https://github.com/cosmos/cosmos-sdk/issues/7949) Standardized channel `Acknowledgement` moved to its own file. Codec registration redundancy removed. * (crypto/types) [\#8600](https://github.com/cosmos/cosmos-sdk/pull/8600) `CompactBitArray`: optimize the `NumTrueBitsBefore` method and add an `Equal` method. * (x/ibc) [\#8624](https://github.com/cosmos/cosmos-sdk/pull/8624) Emit full header in IBC UpdateClient message. diff --git a/crypto/keys/secp256r1/keys.pb.go b/crypto/keys/secp256r1/keys.pb.go index 898daa499b11..898f19a123cf 100644 --- a/crypto/keys/secp256r1/keys.pb.go +++ b/crypto/keys/secp256r1/keys.pb.go @@ -26,7 +26,7 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // PubKey defines a secp256r1 ECDSA public key. type PubKey struct { // Point on secp256r1 curve in a compressed representation as specified in section - // 4.3.6 of ANSI X9.62. + // 4.3.6 of ANSI X9.62: https://webstore.ansi.org/standards/ascx9/ansix9621998 Key *ecdsaPK `protobuf:"bytes,1,opt,name=key,proto3,customtype=ecdsaPK" json:"key,omitempty"` } diff --git a/docs/core/proto-docs.md b/docs/core/proto-docs.md index 0daa9e3afca6..be2ef77e18e8 100644 --- a/docs/core/proto-docs.md +++ b/docs/core/proto-docs.md @@ -80,7 +80,6 @@ - [Output](#cosmos.bank.v1beta1.Output) - [Params](#cosmos.bank.v1beta1.Params) - [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) @@ -1561,22 +1560,6 @@ sendable). - - - -### Supply -Supply represents a struct that passively keeps track of the total supply -amounts in the network. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `total` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | - - - - - @@ -2946,7 +2929,7 @@ PubKey defines a secp256r1 ECDSA public key. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | Point on secp256r1 curve in a compressed representation as specified in section 4.3.6 of ANSI X9.62. | +| `key` | [bytes](#bytes) | | Point on secp256r1 curve in a compressed representation as specified in section 4.3.6 of ANSI X9.62: https://webstore.ansi.org/standards/ascx9/ansix9621998 | diff --git a/testutil/testdata/tx.go b/testutil/testdata/tx.go index 153846083074..cb7ae9d370e2 100644 --- a/testutil/testdata/tx.go +++ b/testutil/testdata/tx.go @@ -4,8 +4,10 @@ import ( "encoding/json" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256r1" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" ) // KeyTestPubAddr generates a new secp256k1 keypair. @@ -16,6 +18,15 @@ func KeyTestPubAddr() (cryptotypes.PrivKey, cryptotypes.PubKey, sdk.AccAddress) return key, pub, addr } +// KeyTestPubAddr generates a new secp256r1 keypair. +func KeyTestPubAddrSecp256R1(require *require.Assertions) (cryptotypes.PrivKey, cryptotypes.PubKey, sdk.AccAddress) { + key, err := secp256r1.GenPrivKey() + require.NoError(err) + pub := key.PubKey() + addr := sdk.AccAddress(pub.Address()) + return key, pub, addr +} + // NewTestFeeAmount is a test fee amount. func NewTestFeeAmount() sdk.Coins { return sdk.NewCoins(sdk.NewInt64Coin("atom", 150)) diff --git a/x/auth/ante/sigverify.go b/x/auth/ante/sigverify.go index 79fbbcdc676a..19bbdcc3a2a3 100644 --- a/x/auth/ante/sigverify.go +++ b/x/auth/ante/sigverify.go @@ -8,6 +8,7 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256r1" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" "github.com/cosmos/cosmos-sdk/crypto/types/multisig" sdk "github.com/cosmos/cosmos-sdk/types" @@ -368,6 +369,10 @@ func DefaultSigVerificationGasConsumer( meter.ConsumeGas(params.SigVerifyCostSecp256k1, "ante verify: secp256k1") return nil + case *secp256r1.PubKey: + meter.ConsumeGas(params.SigVerifyCostSecp256r1(), "ante verify: secp256r1") + return nil + case multisig.PubKey: multisignature, ok := sig.Data.(*signing.MultiSignatureData) if !ok { diff --git a/x/auth/ante/sigverify_benchmark_test.go b/x/auth/ante/sigverify_benchmark_test.go new file mode 100644 index 000000000000..683cc261a9ff --- /dev/null +++ b/x/auth/ante/sigverify_benchmark_test.go @@ -0,0 +1,42 @@ +package ante_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + tmcrypto "github.com/tendermint/tendermint/crypto" + + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256r1" +) + +// This benchmark is used to asses the ante.Secp256k1ToR1GasFactor value +func BenchmarkSig(b *testing.B) { + require := require.New(b) + msg := tmcrypto.CRandBytes(1000) + + skK := secp256k1.GenPrivKey() + pkK := skK.PubKey() + skR, _ := secp256r1.GenPrivKey() + pkR := skR.PubKey() + + sigK, err := skK.Sign(msg) + require.NoError(err) + sigR, err := skR.Sign(msg) + require.NoError(err) + b.ResetTimer() + + b.Run("secp256k1", func(b *testing.B) { + for i := 0; i < b.N; i++ { + ok := pkK.VerifySignature(msg, sigK) + require.True(ok) + } + }) + + b.Run("secp256r1", func(b *testing.B) { + for i := 0; i < b.N; i++ { + ok := pkR.VerifySignature(msg, sigR) + require.True(ok) + } + }) +} diff --git a/x/auth/ante/sigverify_test.go b/x/auth/ante/sigverify_test.go index fa15e1f179f3..8eb42888aa6b 100644 --- a/x/auth/ante/sigverify_test.go +++ b/x/auth/ante/sigverify_test.go @@ -8,6 +8,7 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256r1" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" "github.com/cosmos/cosmos-sdk/crypto/types/multisig" "github.com/cosmos/cosmos-sdk/simapp" @@ -21,12 +22,13 @@ import ( func (suite *AnteTestSuite) TestSetPubKey() { suite.SetupTest(true) // setup + require := suite.Require() suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder() // keys and addresses priv1, pub1, addr1 := testdata.KeyTestPubAddr() priv2, pub2, addr2 := testdata.KeyTestPubAddr() - priv3, pub3, addr3 := testdata.KeyTestPubAddr() + priv3, pub3, addr3 := testdata.KeyTestPubAddrSecp256R1(require) addrs := []sdk.AccAddress{addr1, addr2, addr3} pubs := []cryptotypes.PubKey{pub1, pub2, pub3} @@ -35,32 +37,30 @@ func (suite *AnteTestSuite) TestSetPubKey() { // set accounts and create msg for each address for i, addr := range addrs { acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr) - suite.Require().NoError(acc.SetAccountNumber(uint64(i))) + require.NoError(acc.SetAccountNumber(uint64(i))) suite.app.AccountKeeper.SetAccount(suite.ctx, acc) msgs[i] = testdata.NewTestMsg(addr) } - suite.Require().NoError(suite.txBuilder.SetMsgs(msgs...)) - - feeAmount := testdata.NewTestFeeAmount() - gasLimit := testdata.NewTestGasLimit() - suite.txBuilder.SetFeeAmount(feeAmount) - suite.txBuilder.SetGasLimit(gasLimit) + require.NoError(suite.txBuilder.SetMsgs(msgs...)) + suite.txBuilder.SetFeeAmount(testdata.NewTestFeeAmount()) + suite.txBuilder.SetGasLimit(testdata.NewTestGasLimit()) privs, accNums, accSeqs := []cryptotypes.PrivKey{priv1, priv2, priv3}, []uint64{0, 1, 2}, []uint64{0, 0, 0} tx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID()) - suite.Require().NoError(err) + require.NoError(err) spkd := ante.NewSetPubKeyDecorator(suite.app.AccountKeeper) antehandler := sdk.ChainAnteDecorators(spkd) ctx, err := antehandler(suite.ctx, tx, false) - suite.Require().Nil(err) + require.NoError(err) // Require that all accounts have pubkey set after Decorator runs for i, addr := range addrs { pk, err := suite.app.AccountKeeper.GetPubKey(ctx, addr) - suite.Require().Nil(err, "Error on retrieving pubkey from account") - suite.Require().Equal(pubs[i], pk, "Pubkey retrieved from account is unexpected") + require.NoError(err, "Error on retrieving pubkey from account") + require.True(pubs[i].Equals(pk), + "Wrong Pubkey retrieved from AccountKeeper, idx=%d\nexpected=%s\n got=%s", i, pubs[i], pk) } } @@ -69,6 +69,8 @@ func (suite *AnteTestSuite) TestConsumeSignatureVerificationGas() { msg := []byte{1, 2, 3, 4} cdc := simapp.MakeTestEncodingConfig().Amino + p := types.DefaultParams() + skR1, _ := secp256r1.GenPrivKey() pkSet1, sigSet1 := generatePubKeysAndSignatures(5, msg, false) multisigKey1 := kmultisig.NewLegacyAminoPubKey(2, pkSet1) multisignature1 := multisig.NewMultisig(len(pkSet1)) @@ -93,8 +95,9 @@ func (suite *AnteTestSuite) TestConsumeSignatureVerificationGas() { gasConsumed uint64 shouldErr bool }{ - {"PubKeyEd25519", args{sdk.NewInfiniteGasMeter(), nil, ed25519.GenPrivKey().PubKey(), params}, types.DefaultSigVerifyCostED25519, true}, - {"PubKeySecp256k1", args{sdk.NewInfiniteGasMeter(), nil, secp256k1.GenPrivKey().PubKey(), params}, types.DefaultSigVerifyCostSecp256k1, false}, + {"PubKeyEd25519", args{sdk.NewInfiniteGasMeter(), nil, ed25519.GenPrivKey().PubKey(), params}, p.SigVerifyCostED25519, true}, + {"PubKeySecp256k1", args{sdk.NewInfiniteGasMeter(), nil, secp256k1.GenPrivKey().PubKey(), params}, p.SigVerifyCostSecp256k1, false}, + {"PubKeySecp256r1", args{sdk.NewInfiniteGasMeter(), nil, skR1.PubKey(), params}, p.SigVerifyCostSecp256r1(), false}, {"Multisig", args{sdk.NewInfiniteGasMeter(), multisignature1, multisigKey1, params}, expectedCost1, false}, {"unknown key", args{sdk.NewInfiniteGasMeter(), nil, nil, params}, 0, true}, } diff --git a/x/auth/types/params.go b/x/auth/types/params.go index 13db369d2353..3b9dbe9592f2 100644 --- a/x/auth/types/params.go +++ b/x/auth/types/params.go @@ -69,6 +69,16 @@ func DefaultParams() Params { } } +// SigVerifyCostSecp256r1 returns gas fee of secp256r1 signature verification. +// Set by benchmarking current implementation: +// BenchmarkSig/secp256k1 4334 277167 ns/op 4128 B/op 79 allocs/op +// BenchmarkSig/secp256r1 10000 108769 ns/op 1672 B/op 33 allocs/op +// Based on the results above secp256k1 is 2.7x is slwer. However we propose to discount it +// because we are we don't compare the cgo implementation of secp256k1, which is faster. +func (p Params) SigVerifyCostSecp256r1() uint64 { + return p.SigVerifyCostSecp256k1 / 2 +} + // String implements the stringer interface. func (p Params) String() string { out, _ := yaml.Marshal(p) From 432b0b2da7e0a170c475c33b95d923b8f5b69b44 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Mar 2021 08:43:33 +0000 Subject: [PATCH 159/214] build(deps): bump JamesIves/github-pages-deploy-action from 4.0.0 to 4.1.0 (#8792) Bumps [JamesIves/github-pages-deploy-action](https://github.com/JamesIves/github-pages-deploy-action) from 4.0.0 to 4.1.0. - [Release notes](https://github.com/JamesIves/github-pages-deploy-action/releases) - [Commits](https://github.com/JamesIves/github-pages-deploy-action/compare/4.0.0...3dbacc7e69578703f91f077118b3475862cb09b8) 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 493d1c21c231..cab87da60dda 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@4.0.0 + uses: JamesIves/github-pages-deploy-action@4.1.0 with: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} BRANCH: gh-pages From 67964b1df47c0953dad3046dbffb8e04d526f3fa Mon Sep 17 00:00:00 2001 From: Akhil Kumar P <36399231+akhilkumarpilli@users.noreply.github.com> Date: Fri, 5 Mar 2021 18:03:41 +0530 Subject: [PATCH 160/214] fix multisig account pubkeys migration (#8794) closes: #8776 --- x/auth/legacy/v040/migrate.go | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/x/auth/legacy/v040/migrate.go b/x/auth/legacy/v040/migrate.go index 363ec7ba82df..f819a1a33d8b 100644 --- a/x/auth/legacy/v040/migrate.go +++ b/x/auth/legacy/v040/migrate.go @@ -2,6 +2,7 @@ package v040 import ( codectypes "github.com/cosmos/cosmos-sdk/codec/types" + multisigtypes "github.com/cosmos/cosmos-sdk/crypto/keys/multisig" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" v039auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v039" v040auth "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -11,9 +12,16 @@ import ( // convertBaseAccount converts a 0.39 BaseAccount to a 0.40 BaseAccount. func convertBaseAccount(old *v039auth.BaseAccount) *v040auth.BaseAccount { var any *codectypes.Any - // If the old genesis had a pubkey, we pack it inside an Any. Or else, we - // just leave it nil. - if old.PubKey != nil { + + _, ok := old.PubKey.(*multisigtypes.LegacyAminoPubKey) + + // If pubkey is multisig type, then leave it as nil for now + // Ref: https://github.com/cosmos/cosmos-sdk/issues/8776#issuecomment-790552126 + // Else if the old genesis had a pubkey, we pack it inside an Any. + // Or else, we just leave it nil. + if ok { + // TODO migrate multisig public_keys + } else if old.PubKey != nil { var err error any, err = codectypes.NewAnyWithValue(old.PubKey) if err != nil { From 7aa0b4b812bc88367664aeb7b1ee434e3eaada73 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Fri, 5 Mar 2021 12:45:18 +0000 Subject: [PATCH 161/214] Update mergify (#8784) * Update mergify Prep for the v0.42 release series. * retire v0.41, the hub can upgrade to v0.42 smoothly --- .mergify.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.mergify.yml b/.mergify.yml index 129fb0090bb5..a7e38c042620 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -8,14 +8,14 @@ pull_request_rules: merge: method: squash strict: true - - name: backport patches to v0.41.x branch + - name: backport patches to v0.42.x branch conditions: - base=master - - label=backport/0.41.x (Stargate) + - label=backport/0.42.x (Stargate) actions: backport: branches: - - release/v0.41.x + - release/v0.42.x - name: backport patches to v0.39.x branch conditions: - base=master From e17953ab112244fece1534b386517bf9cd44ce05 Mon Sep 17 00:00:00 2001 From: Marko Date: Fri, 5 Mar 2021 13:17:31 +0000 Subject: [PATCH 162/214] perf change (#8796) Co-authored-by: Alessio Treglia Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- store/cachekv/memiterator.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/store/cachekv/memiterator.go b/store/cachekv/memiterator.go index c5a00ab8dfcd..675494b8ffe2 100644 --- a/store/cachekv/memiterator.go +++ b/store/cachekv/memiterator.go @@ -19,7 +19,7 @@ type memIterator struct { } func newMemIterator(start, end []byte, items *list.List, ascending bool) *memIterator { - itemsInDomain := make([]*kv.Pair, 0) + itemsInDomain := make([]*kv.Pair, 0, items.Len()) var entered bool From 6520997668def0b02d8d5769831778e8c60d82e8 Mon Sep 17 00:00:00 2001 From: Amaury <1293565+amaurym@users.noreply.github.com> Date: Fri, 5 Mar 2021 15:11:19 +0100 Subject: [PATCH 163/214] Supply by denom Migrations (#8780) * Add back supply proto * Add migration for supply * Fix lint * Update x/bank/spec/01_state.md * Fix test * Proto gen * Update x/bank/spec/01_state.md * Make proto gen Co-authored-by: Jonathan Gimeno --- docs/core/proto-docs.md | 18 ++ proto/cosmos/bank/v1beta1/bank.proto | 15 ++ x/bank/keeper/migrations.go | 2 +- x/bank/keeper/querier.go | 3 +- x/bank/legacy/v042/store.go | 52 ++++- x/bank/legacy/v042/store_test.go | 34 +++- x/bank/spec/01_state.md | 5 +- x/bank/types/bank.pb.go | 285 +++++++++++++++++++++++---- 8 files changed, 363 insertions(+), 51 deletions(-) diff --git a/docs/core/proto-docs.md b/docs/core/proto-docs.md index be2ef77e18e8..9e985a6a6a1b 100644 --- a/docs/core/proto-docs.md +++ b/docs/core/proto-docs.md @@ -80,6 +80,7 @@ - [Output](#cosmos.bank.v1beta1.Output) - [Params](#cosmos.bank.v1beta1.Params) - [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) @@ -1560,6 +1561,23 @@ sendable). + + + +### Supply +Supply represents a struct that passively keeps track of the total supply +amounts in the network. +This message is deprecated now that supply is indexed by denom. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `total` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | + + + + + diff --git a/proto/cosmos/bank/v1beta1/bank.proto b/proto/cosmos/bank/v1beta1/bank.proto index 4742bafb17e5..9b66a4fd7d44 100644 --- a/proto/cosmos/bank/v1beta1/bank.proto +++ b/proto/cosmos/bank/v1beta1/bank.proto @@ -43,6 +43,21 @@ message Output { [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"]; } +// Supply represents a struct that passively keeps track of the total supply +// amounts in the network. +// This message is deprecated now that supply is indexed by denom. +message Supply { + option deprecated = true; + + option (gogoproto.equal) = true; + option (gogoproto.goproto_getters) = false; + + option (cosmos_proto.implements_interface) = "*github.com/cosmos/cosmos-sdk/x/bank/exported.SupplyI"; + + repeated cosmos.base.v1beta1.Coin total = 1 + [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"]; +} + // DenomUnit represents a struct that describes a given // denomination unit of the basic token. message DenomUnit { diff --git a/x/bank/keeper/migrations.go b/x/bank/keeper/migrations.go index 3a200fc2730d..20ef35e3215a 100644 --- a/x/bank/keeper/migrations.go +++ b/x/bank/keeper/migrations.go @@ -17,5 +17,5 @@ func NewMigrator(keeper BaseKeeper) Migrator { // Migrate1to2 migrates from version 1 to 2. func (m Migrator) Migrate1to2(ctx sdk.Context) error { - return v042.MigrateStore(ctx, m.keeper.storeKey) + return v042.MigrateStore(ctx, m.keeper.storeKey, m.keeper.cdc) } diff --git a/x/bank/keeper/querier.go b/x/bank/keeper/querier.go index c2d6ca8a2f67..dca5414f45fd 100644 --- a/x/bank/keeper/querier.go +++ b/x/bank/keeper/querier.go @@ -84,7 +84,8 @@ func queryTotalSupply(ctx sdk.Context, req abci.RequestQuery, k Keeper, legacyQu return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error()) } - //TODO: pagenate + // TODO: paginate + // https://github.com/cosmos/cosmos-sdk/issues/8761 totalSupply := k.GetTotalSupply(ctx) start, end := client.Paginate(len(totalSupply), params.Page, params.Limit, 100) diff --git a/x/bank/legacy/v042/store.go b/x/bank/legacy/v042/store.go index 894305b6c8f7..cc0d9d6f5ae9 100644 --- a/x/bank/legacy/v042/store.go +++ b/x/bank/legacy/v042/store.go @@ -1,6 +1,7 @@ package v042 import ( + "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" v040auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v040" @@ -8,14 +9,38 @@ import ( "github.com/cosmos/cosmos-sdk/x/bank/types" ) -// 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) +// migrateSupply migrates the supply to be stored by denom key instead in a +// single blob. +// ref: https://github.com/cosmos/cosmos-sdk/issues/7092 +func migrateSupply(store sdk.KVStore, cdc codec.BinaryMarshaler) error { + // Old supply was stored as a single blob under the SupplyKey. + var oldSupply types.Supply // nolint:staticcheck + err := cdc.UnmarshalBinaryBare(store.Get(v040bank.SupplyKey), &oldSupply) + if err != nil { + return err + } + + // We delete the single key holding the whole blob. + store.Delete(v040bank.SupplyKey) + + // We add a new key for each denom + supplyStore := prefix.NewStore(store, types.SupplyKey) + for i := range oldSupply.Total { + coin := oldSupply.Total[i] + coinBz, err := cdc.MarshalBinaryBare(&coin) + if err != nil { + return err + } + supplyStore.Set([]byte(coin.Denom), coinBz) + } + + return nil +} + +// migrateBalanceKeys migrate the balances keys to cater for variable-length +// addresses. +func migrateBalanceKeys(store sdk.KVStore) { // old key is of format: // prefix ("balances") || addrBytes (20 bytes) || denomBytes // new key is of format @@ -34,6 +59,17 @@ func MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey) error { store.Set(newStoreKey, oldStoreIter.Value()) oldStore.Delete(oldStoreIter.Key()) } +} - return nil +// 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 +// - Change supply to be indexed by denom +func MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey, cdc codec.BinaryMarshaler) error { + store := ctx.KVStore(storeKey) + + migrateBalanceKeys(store) + return migrateSupply(store, cdc) } diff --git a/x/bank/legacy/v042/store_test.go b/x/bank/legacy/v042/store_test.go index 7481232f5c59..51256ff3c189 100644 --- a/x/bank/legacy/v042/store_test.go +++ b/x/bank/legacy/v042/store_test.go @@ -5,6 +5,8 @@ import ( "github.com/stretchr/testify/require" + "github.com/cosmos/cosmos-sdk/simapp" + "github.com/cosmos/cosmos-sdk/store/prefix" "github.com/cosmos/cosmos-sdk/testutil" "github.com/cosmos/cosmos-sdk/testutil/testdata" sdk "github.com/cosmos/cosmos-sdk/types" @@ -13,7 +15,35 @@ import ( "github.com/cosmos/cosmos-sdk/x/bank/types" ) -func TestStoreMigration(t *testing.T) { +func TestSupplyMigration(t *testing.T) { + encCfg := simapp.MakeTestEncodingConfig() + bankKey := sdk.NewKVStoreKey("bank") + ctx := testutil.DefaultContext(bankKey, sdk.NewTransientStoreKey("transient_test")) + store := ctx.KVStore(bankKey) + + oldFooCoin := sdk.NewCoin("foo", sdk.NewInt(100)) + oldBarCoin := sdk.NewCoin("bar", sdk.NewInt(200)) + + // Old supply was stored as a single blob under the `SupplyKey`. + oldSupply := types.Supply{Total: sdk.NewCoins(oldFooCoin, oldBarCoin)} + store.Set(v040bank.SupplyKey, encCfg.Marshaler.MustMarshalBinaryBare(&oldSupply)) + + // Run migration. + err := v042bank.MigrateStore(ctx, bankKey, encCfg.Marshaler) + require.NoError(t, err) + + // New supply is indexed by denom. + var newFooCoin, newBarCoin sdk.Coin + supplyStore := prefix.NewStore(store, types.SupplyKey) + encCfg.Marshaler.MustUnmarshalBinaryBare(supplyStore.Get([]byte("foo")), &newFooCoin) + encCfg.Marshaler.MustUnmarshalBinaryBare(supplyStore.Get([]byte("bar")), &newBarCoin) + + require.Equal(t, oldFooCoin, newFooCoin) + require.Equal(t, oldBarCoin, newBarCoin) +} + +func TestBalanceKeysMigration(t *testing.T) { + encCfg := simapp.MakeTestEncodingConfig() bankKey := sdk.NewKVStoreKey("bank") ctx := testutil.DefaultContext(bankKey, sdk.NewTransientStoreKey("transient_test")) store := ctx.KVStore(bankKey) @@ -25,7 +55,7 @@ func TestStoreMigration(t *testing.T) { oldKey := append(append(v040bank.BalancesPrefix, addr...), denom...) store.Set(oldKey, value) - err := v042bank.MigrateStore(ctx, bankKey) + err := v042bank.MigrateStore(ctx, bankKey, encCfg.Marshaler) require.NoError(t, err) newKey := append(types.CreateAccountBalancesPrefix(addr), denom...) diff --git a/x/bank/spec/01_state.md b/x/bank/spec/01_state.md index 6ca6b97e8fc1..4b8a512489e6 100644 --- a/x/bank/spec/01_state.md +++ b/x/bank/spec/01_state.md @@ -4,8 +4,9 @@ order: 1 # State -The `x/bank` module keeps state of two primary objects, account balances and the +The `x/bank` module keeps state of three primary objects, account balances, denom metadata and the total supply of all balances. -- Supply: `0x0 -> ProtocolBuffer(Supply)` +- Supply: `0x0 | byte(denom) -> ProtocolBuffer(coin)` +- Denom Metadata: `0x1 | byte(denom) -> ProtocolBuffer(Metadata)` - Balances: `0x2 | byte(address length) | []byte(address) | []byte(balance.Denom) -> ProtocolBuffer(balance)` diff --git a/x/bank/types/bank.pb.go b/x/bank/types/bank.pb.go index 17b97f752add..0511d1e96127 100644 --- a/x/bank/types/bank.pb.go +++ b/x/bank/types/bank.pb.go @@ -209,6 +209,48 @@ func (m *Output) XXX_DiscardUnknown() { var xxx_messageInfo_Output proto.InternalMessageInfo +// Supply represents a struct that passively keeps track of the total supply +// amounts in the network. +// This message is deprecated now that supply is indexed by denom. +// +// Deprecated: Do not use. +type Supply struct { + Total github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,1,rep,name=total,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"total"` +} + +func (m *Supply) Reset() { *m = Supply{} } +func (m *Supply) String() string { return proto.CompactTextString(m) } +func (*Supply) ProtoMessage() {} +func (*Supply) Descriptor() ([]byte, []int) { + return fileDescriptor_dd052eee12edf988, []int{4} +} +func (m *Supply) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Supply) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Supply.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 *Supply) XXX_Merge(src proto.Message) { + xxx_messageInfo_Supply.Merge(m, src) +} +func (m *Supply) XXX_Size() int { + return m.Size() +} +func (m *Supply) XXX_DiscardUnknown() { + xxx_messageInfo_Supply.DiscardUnknown(m) +} + +var xxx_messageInfo_Supply proto.InternalMessageInfo + // DenomUnit represents a struct that describes a given // denomination unit of the basic token. type DenomUnit struct { @@ -228,7 +270,7 @@ func (m *DenomUnit) Reset() { *m = DenomUnit{} } func (m *DenomUnit) String() string { return proto.CompactTextString(m) } func (*DenomUnit) ProtoMessage() {} func (*DenomUnit) Descriptor() ([]byte, []int) { - return fileDescriptor_dd052eee12edf988, []int{4} + return fileDescriptor_dd052eee12edf988, []int{5} } func (m *DenomUnit) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -300,7 +342,7 @@ func (m *Metadata) Reset() { *m = Metadata{} } func (m *Metadata) String() string { return proto.CompactTextString(m) } func (*Metadata) ProtoMessage() {} func (*Metadata) Descriptor() ([]byte, []int) { - return fileDescriptor_dd052eee12edf988, []int{5} + return fileDescriptor_dd052eee12edf988, []int{6} } func (m *Metadata) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -376,6 +418,7 @@ func init() { proto.RegisterType((*SendEnabled)(nil), "cosmos.bank.v1beta1.SendEnabled") proto.RegisterType((*Input)(nil), "cosmos.bank.v1beta1.Input") proto.RegisterType((*Output)(nil), "cosmos.bank.v1beta1.Output") + proto.RegisterType((*Supply)(nil), "cosmos.bank.v1beta1.Supply") proto.RegisterType((*DenomUnit)(nil), "cosmos.bank.v1beta1.DenomUnit") proto.RegisterType((*Metadata)(nil), "cosmos.bank.v1beta1.Metadata") } @@ -383,41 +426,44 @@ func init() { func init() { proto.RegisterFile("cosmos/bank/v1beta1/bank.proto", fileDescriptor_dd052eee12edf988) } var fileDescriptor_dd052eee12edf988 = []byte{ - // 537 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x54, 0xbf, 0x8f, 0xd3, 0x30, - 0x18, 0x8d, 0xaf, 0x3f, 0xe8, 0xb9, 0xb0, 0x98, 0x0a, 0xe5, 0x2a, 0x91, 0x84, 0x48, 0x48, 0x3d, - 0x09, 0x5a, 0x0e, 0xb6, 0x2e, 0x48, 0x3d, 0x10, 0x62, 0x40, 0xa0, 0x20, 0x84, 0x04, 0x43, 0xe5, - 0xd4, 0xbe, 0x62, 0x5d, 0x6c, 0x47, 0xb5, 0x8b, 0xae, 0xff, 0x01, 0x13, 0x30, 0x32, 0xde, 0xcc, - 0x3f, 0xc2, 0x8d, 0x27, 0xb1, 0x30, 0x15, 0xd4, 0x2e, 0xcc, 0xf7, 0x17, 0x20, 0xdb, 0x69, 0x9b, - 0x93, 0x0a, 0x33, 0x53, 0xbf, 0xf7, 0x7d, 0xcf, 0xef, 0x7b, 0x7e, 0x4d, 0x02, 0x83, 0x91, 0x54, - 0x5c, 0xaa, 0x5e, 0x8a, 0xc5, 0x71, 0xef, 0xfd, 0x41, 0x4a, 0x35, 0x3e, 0xb0, 0xa0, 0x9b, 0x4f, - 0xa4, 0x96, 0xe8, 0xba, 0x9b, 0x77, 0x6d, 0xab, 0x98, 0xb7, 0x5b, 0x63, 0x39, 0x96, 0x76, 0xde, - 0x33, 0x95, 0xa3, 0xb6, 0xf7, 0x1c, 0x75, 0xe8, 0x06, 0xc5, 0x39, 0x37, 0xda, 0x6c, 0x51, 0x74, - 0xbd, 0x65, 0x24, 0x99, 0x70, 0xf3, 0xf8, 0x3b, 0x80, 0xf5, 0x17, 0x78, 0x82, 0xb9, 0x42, 0x47, - 0xf0, 0xaa, 0xa2, 0x82, 0x0c, 0xa9, 0xc0, 0x69, 0x46, 0x89, 0x0f, 0xa2, 0x4a, 0xa7, 0x79, 0x3f, - 0xea, 0x6e, 0xf1, 0xd1, 0x7d, 0x49, 0x05, 0x79, 0xec, 0x78, 0x83, 0x5b, 0x17, 0xf3, 0xf0, 0xe6, - 0x0c, 0xf3, 0xac, 0x1f, 0x97, 0xcf, 0xdf, 0x91, 0x9c, 0x69, 0xca, 0x73, 0x3d, 0x8b, 0x93, 0xa6, - 0xda, 0xf0, 0xd1, 0x5b, 0xd8, 0x22, 0xf4, 0x08, 0x4f, 0x33, 0x3d, 0xbc, 0xb4, 0x6f, 0x27, 0x02, - 0x9d, 0xc6, 0x60, 0xff, 0x62, 0x1e, 0xde, 0x76, 0x6a, 0xdb, 0x58, 0x65, 0x55, 0x54, 0x10, 0x4a, - 0x66, 0xfa, 0xd5, 0x2f, 0xa7, 0xa1, 0x17, 0x3f, 0x81, 0xcd, 0x52, 0x13, 0xb5, 0x60, 0x8d, 0x50, - 0x21, 0xb9, 0x0f, 0x22, 0xd0, 0xd9, 0x4d, 0x1c, 0x40, 0x3e, 0xbc, 0x72, 0x69, 0x75, 0xb2, 0x82, - 0xfd, 0x86, 0x11, 0xf9, 0x7d, 0x1a, 0x82, 0xf8, 0x23, 0x80, 0xb5, 0xa7, 0x22, 0x9f, 0x6a, 0xc3, - 0xc6, 0x84, 0x4c, 0xa8, 0x52, 0x85, 0xca, 0x0a, 0x22, 0x0c, 0x6b, 0x26, 0x50, 0xe5, 0xef, 0xd8, - 0xc0, 0xf6, 0x36, 0x81, 0x29, 0xba, 0x0e, 0xec, 0x50, 0x32, 0x31, 0xb8, 0x77, 0x36, 0x0f, 0xbd, - 0xaf, 0x3f, 0xc3, 0xce, 0x98, 0xe9, 0x77, 0xd3, 0xb4, 0x3b, 0x92, 0xbc, 0xf8, 0xb7, 0x8a, 0x9f, - 0xbb, 0x8a, 0x1c, 0xf7, 0xf4, 0x2c, 0xa7, 0xca, 0x1e, 0x50, 0x89, 0x53, 0xee, 0x37, 0x3e, 0x38, - 0x43, 0x5e, 0xfc, 0x09, 0xc0, 0xfa, 0xf3, 0xa9, 0xfe, 0x8f, 0x1c, 0xbd, 0x86, 0xbb, 0x8f, 0x4c, - 0x9e, 0xaf, 0x04, 0xd3, 0x7f, 0x49, 0xba, 0x0d, 0x1b, 0xf4, 0x24, 0x97, 0x82, 0x0a, 0x6d, 0xa3, - 0xbe, 0x96, 0xac, 0xb1, 0xbd, 0x45, 0xc6, 0xb0, 0xa2, 0xca, 0xaf, 0x44, 0x15, 0x7b, 0x0b, 0x07, - 0xe3, 0x6f, 0x00, 0x36, 0x9e, 0x51, 0x8d, 0x09, 0xd6, 0x18, 0x45, 0xb0, 0x49, 0xa8, 0x1a, 0x4d, - 0x58, 0xae, 0x99, 0x14, 0x85, 0x7c, 0xb9, 0x85, 0x1e, 0x1a, 0x86, 0x90, 0x7c, 0x38, 0x15, 0x4c, - 0xaf, 0xae, 0x1e, 0x6c, 0x7d, 0x7a, 0xd7, 0x7e, 0x13, 0x48, 0x56, 0xa5, 0x42, 0x08, 0x56, 0x4d, - 0x40, 0x7e, 0xc5, 0x6a, 0xdb, 0xda, 0xb8, 0x23, 0x4c, 0xe5, 0x19, 0x9e, 0xf9, 0x55, 0x97, 0x71, - 0x01, 0x0d, 0x5b, 0x60, 0x4e, 0xfd, 0x9a, 0x63, 0x9b, 0x1a, 0xdd, 0x80, 0x75, 0x35, 0xe3, 0xa9, - 0xcc, 0xfc, 0xba, 0xed, 0x16, 0x68, 0x70, 0x78, 0xb6, 0x08, 0xc0, 0xf9, 0x22, 0x00, 0xbf, 0x16, - 0x01, 0xf8, 0xbc, 0x0c, 0xbc, 0xf3, 0x65, 0xe0, 0xfd, 0x58, 0x06, 0xde, 0x9b, 0xfd, 0x7f, 0xe6, - 0x7e, 0xe2, 0x3e, 0x0e, 0x36, 0xfe, 0xb4, 0x6e, 0x5f, 0xd8, 0x07, 0x7f, 0x02, 0x00, 0x00, 0xff, - 0xff, 0x42, 0x5b, 0x8d, 0xc8, 0x38, 0x04, 0x00, 0x00, + // 587 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x54, 0xbf, 0x6f, 0xd3, 0x40, + 0x14, 0xf6, 0x35, 0x8d, 0x49, 0x2f, 0xb0, 0x1c, 0x15, 0x72, 0x2b, 0x61, 0x1b, 0x4b, 0x48, 0x29, + 0xa2, 0x0e, 0x05, 0xb1, 0x64, 0x41, 0x4a, 0x41, 0xa8, 0x03, 0x02, 0xb9, 0x42, 0x48, 0x30, 0x44, + 0xe7, 0xdc, 0x35, 0x58, 0xb5, 0xef, 0xac, 0xdc, 0x19, 0xd5, 0xff, 0x01, 0x13, 0x30, 0x32, 0x76, + 0x66, 0x62, 0xe0, 0x7f, 0xa0, 0x63, 0x05, 0x0b, 0x53, 0x40, 0xc9, 0xc2, 0xdc, 0xbf, 0x00, 0xdd, + 0x9d, 0xf3, 0xa3, 0x52, 0x40, 0x0c, 0x0c, 0x4c, 0x79, 0xdf, 0x7b, 0xdf, 0xfb, 0xde, 0xd3, 0x77, + 0xcf, 0x81, 0x6e, 0x9f, 0x8b, 0x8c, 0x8b, 0x76, 0x8c, 0xd9, 0x61, 0xfb, 0xd5, 0x4e, 0x4c, 0x25, + 0xde, 0xd1, 0x20, 0xcc, 0x87, 0x5c, 0x72, 0x74, 0xd9, 0xd4, 0x43, 0x9d, 0xaa, 0xea, 0x9b, 0xeb, + 0x03, 0x3e, 0xe0, 0xba, 0xde, 0x56, 0x91, 0xa1, 0x6e, 0x6e, 0x18, 0x6a, 0xcf, 0x14, 0xaa, 0x3e, + 0x53, 0x9a, 0x4f, 0x11, 0x74, 0x36, 0xa5, 0xcf, 0x13, 0x66, 0xea, 0xc1, 0x57, 0x00, 0xed, 0x27, + 0x78, 0x88, 0x33, 0x81, 0x0e, 0xe0, 0x45, 0x41, 0x19, 0xe9, 0x51, 0x86, 0xe3, 0x94, 0x12, 0x07, + 0xf8, 0xb5, 0x56, 0xf3, 0xb6, 0x1f, 0x2e, 0xd9, 0x23, 0xdc, 0xa7, 0x8c, 0x3c, 0x30, 0xbc, 0xee, + 0xb5, 0xb3, 0x91, 0x77, 0xb5, 0xc4, 0x59, 0xda, 0x09, 0x16, 0xfb, 0x6f, 0xf2, 0x2c, 0x91, 0x34, + 0xcb, 0x65, 0x19, 0x44, 0x4d, 0x31, 0xe7, 0xa3, 0x17, 0x70, 0x9d, 0xd0, 0x03, 0x5c, 0xa4, 0xb2, + 0x77, 0x6e, 0xde, 0x8a, 0x0f, 0x5a, 0x8d, 0xee, 0xd6, 0xd9, 0xc8, 0xbb, 0x6e, 0xd4, 0x96, 0xb1, + 0x16, 0x55, 0x51, 0x45, 0x58, 0x58, 0xa6, 0xb3, 0xfa, 0xfe, 0xd8, 0xb3, 0x82, 0x87, 0xb0, 0xb9, + 0x90, 0x44, 0xeb, 0xb0, 0x4e, 0x28, 0xe3, 0x99, 0x03, 0x7c, 0xd0, 0x5a, 0x8b, 0x0c, 0x40, 0x0e, + 0xbc, 0x70, 0x6e, 0x74, 0x34, 0x85, 0x9d, 0x86, 0x12, 0xf9, 0x79, 0xec, 0x81, 0xe0, 0x0d, 0x80, + 0xf5, 0x3d, 0x96, 0x17, 0x52, 0xb1, 0x31, 0x21, 0x43, 0x2a, 0x44, 0xa5, 0x32, 0x85, 0x08, 0xc3, + 0xba, 0x32, 0x54, 0x38, 0x2b, 0xda, 0xb0, 0x8d, 0xb9, 0x61, 0x82, 0xce, 0x0c, 0xdb, 0xe5, 0x09, + 0xeb, 0xde, 0x3a, 0x19, 0x79, 0xd6, 0x87, 0xef, 0x5e, 0x6b, 0x90, 0xc8, 0x97, 0x45, 0x1c, 0xf6, + 0x79, 0x56, 0xbd, 0x56, 0xf5, 0xb3, 0x2d, 0xc8, 0x61, 0x5b, 0x96, 0x39, 0x15, 0xba, 0x41, 0x44, + 0x46, 0xb9, 0xd3, 0x78, 0x6d, 0x16, 0xb2, 0x82, 0xb7, 0x00, 0xda, 0x8f, 0x0b, 0xf9, 0x1f, 0x6d, + 0xf4, 0x11, 0x40, 0x7b, 0xbf, 0xc8, 0xf3, 0xb4, 0x54, 0x73, 0x25, 0x97, 0x38, 0xad, 0x4e, 0xe7, + 0xdf, 0xce, 0xd5, 0xca, 0x9d, 0xdd, 0x6a, 0x2e, 0xf8, 0xf2, 0x69, 0xfb, 0xee, 0x8d, 0x3f, 0x76, + 0x1f, 0x99, 0x4f, 0x8b, 0x1e, 0xe5, 0x7c, 0x28, 0x29, 0x09, 0xcd, 0x92, 0x7b, 0x0e, 0x08, 0x9e, + 0xc1, 0xb5, 0xfb, 0xea, 0x04, 0x9e, 0xb2, 0x44, 0xfe, 0xe6, 0x38, 0x36, 0x61, 0x43, 0x35, 0x32, + 0xca, 0xa4, 0xbe, 0x8e, 0x4b, 0xd1, 0x0c, 0x6b, 0xe3, 0xd3, 0x04, 0x0b, 0x2a, 0x9c, 0x9a, 0x5f, + 0xd3, 0xc6, 0x1b, 0x18, 0x7c, 0x06, 0xb0, 0xf1, 0x88, 0x4a, 0x4c, 0xb0, 0xc4, 0xc8, 0x87, 0x4d, + 0x42, 0x45, 0x7f, 0x98, 0xe4, 0x32, 0xe1, 0xac, 0x92, 0x5f, 0x4c, 0xa1, 0x7b, 0x8a, 0xc1, 0x78, + 0xd6, 0x2b, 0x58, 0x22, 0xa7, 0xaf, 0xe5, 0x2e, 0xfd, 0xe0, 0x66, 0xfb, 0x46, 0x90, 0x4c, 0x43, + 0x81, 0x10, 0x5c, 0x55, 0xde, 0x3a, 0x35, 0xad, 0xad, 0x63, 0xb5, 0x1d, 0x49, 0x44, 0x9e, 0xe2, + 0xd2, 0x59, 0x35, 0x67, 0x51, 0x41, 0xc5, 0x66, 0x38, 0xa3, 0x4e, 0xdd, 0xb0, 0x55, 0x8c, 0xae, + 0x40, 0x5b, 0x94, 0x59, 0xcc, 0x53, 0xc7, 0xd6, 0xd9, 0x0a, 0x75, 0x77, 0x4f, 0xc6, 0x2e, 0x38, + 0x1d, 0xbb, 0xe0, 0xc7, 0xd8, 0x05, 0xef, 0x26, 0xae, 0x75, 0x3a, 0x71, 0xad, 0x6f, 0x13, 0xd7, + 0x7a, 0xbe, 0xf5, 0x37, 0xa6, 0xeb, 0x97, 0x8b, 0x6d, 0xfd, 0x1f, 0x73, 0xe7, 0x57, 0x00, 0x00, + 0x00, 0xff, 0xff, 0xe7, 0x1c, 0xc1, 0x93, 0xeb, 0x04, 0x00, 0x00, } func (this *SendEnabled) Equal(that interface{}) bool { @@ -447,6 +493,35 @@ func (this *SendEnabled) Equal(that interface{}) bool { } return true } +func (this *Supply) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Supply) + if !ok { + that2, ok := that.(Supply) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if len(this.Total) != len(that1.Total) { + return false + } + for i := range this.Total { + if !this.Total[i].Equal(&that1.Total[i]) { + return false + } + } + return true +} func (m *Params) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -622,6 +697,43 @@ func (m *Output) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *Supply) 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 *Supply) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Supply) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Total) > 0 { + for iNdEx := len(m.Total) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Total[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintBank(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + func (m *DenomUnit) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -821,6 +933,21 @@ func (m *Output) Size() (n int) { return n } +func (m *Supply) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Total) > 0 { + for _, e := range m.Total { + l = e.Size() + n += 1 + l + sovBank(uint64(l)) + } + } + return n +} + func (m *DenomUnit) Size() (n int) { if m == nil { return 0 @@ -1322,6 +1449,90 @@ func (m *Output) Unmarshal(dAtA []byte) error { } return nil } +func (m *Supply) 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 ErrIntOverflowBank + } + 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: Supply: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Supply: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Total", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBank + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthBank + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthBank + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Total = append(m.Total, types.Coin{}) + if err := m.Total[len(m.Total)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipBank(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthBank + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *DenomUnit) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 From 09f9a5573e4132fbedfaab6d948df1cc93e6e896 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 5 Mar 2021 16:23:01 +0100 Subject: [PATCH 164/214] fix make protoc error (#8799) --- Makefile | 2 +- x/authz/types/authz.pb.go | 2 +- x/authz/types/genesis.pb.go | 2 +- x/authz/types/tx.pb.go | 2 +- x/evidence/types/evidence.pb.go | 2 +- x/feegrant/types/feegrant.pb.go | 4 +- x/gov/types/gov.pb.go | 4 +- x/slashing/types/slashing.pb.go | 4 +- x/staking/types/staking.pb.go | 1217 +++++++++++++++---------------- x/staking/types/tx.pb.go | 2 +- x/upgrade/types/upgrade.pb.go | 2 +- 11 files changed, 621 insertions(+), 622 deletions(-) diff --git a/Makefile b/Makefile index 66065b864a23..d7b8a1fa8cfd 100644 --- a/Makefile +++ b/Makefile @@ -373,7 +373,7 @@ proto-all: proto-format proto-lint proto-gen proto-gen: @echo "Generating Protobuf files" - $(DOCKER) run --rm -v $(CURDIR):/workspace --workdir /workspace tendermintdev/sdk-proto-gen sh ./scripts/protocgen.sh + $(DOCKER) run --rm -v $(CURDIR):/workspace --workdir /workspace tendermintdev/sdk-proto-gen:v0.1 sh ./scripts/protocgen.sh proto-format: @echo "Formatting Protobuf files" diff --git a/x/authz/types/authz.pb.go b/x/authz/types/authz.pb.go index 15c103c61312..2e77267b7505 100644 --- a/x/authz/types/authz.pb.go +++ b/x/authz/types/authz.pb.go @@ -9,8 +9,8 @@ import ( _ "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" + _ "google.golang.org/protobuf/types/known/timestamppb" io "io" math "math" math_bits "math/bits" diff --git a/x/authz/types/genesis.pb.go b/x/authz/types/genesis.pb.go index 20dfb9d232b5..eec163fc12ac 100644 --- a/x/authz/types/genesis.pb.go +++ b/x/authz/types/genesis.pb.go @@ -9,8 +9,8 @@ import ( _ "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" + _ "google.golang.org/protobuf/types/known/timestamppb" io "io" math "math" math_bits "math/bits" diff --git a/x/authz/types/tx.pb.go b/x/authz/types/tx.pb.go index 7705f5d44afc..a1f493ff2c53 100644 --- a/x/authz/types/tx.pb.go +++ b/x/authz/types/tx.pb.go @@ -12,11 +12,11 @@ import ( 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" + _ "google.golang.org/protobuf/types/known/timestamppb" io "io" math "math" math_bits "math/bits" diff --git a/x/evidence/types/evidence.pb.go b/x/evidence/types/evidence.pb.go index 284f33a5ba0e..116d6362d5c7 100644 --- a/x/evidence/types/evidence.pb.go +++ b/x/evidence/types/evidence.pb.go @@ -8,7 +8,7 @@ import ( _ "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" + _ "google.golang.org/protobuf/types/known/timestamppb" io "io" math "math" math_bits "math/bits" diff --git a/x/feegrant/types/feegrant.pb.go b/x/feegrant/types/feegrant.pb.go index 2897bcc392d6..28f53e140da8 100644 --- a/x/feegrant/types/feegrant.pb.go +++ b/x/feegrant/types/feegrant.pb.go @@ -11,9 +11,9 @@ import ( _ "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" + _ "google.golang.org/protobuf/types/known/durationpb" + _ "google.golang.org/protobuf/types/known/timestamppb" io "io" math "math" math_bits "math/bits" diff --git a/x/gov/types/gov.pb.go b/x/gov/types/gov.pb.go index caa52a67a818..5f49a4ae4100 100644 --- a/x/gov/types/gov.pb.go +++ b/x/gov/types/gov.pb.go @@ -11,9 +11,9 @@ import ( _ "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" + _ "google.golang.org/protobuf/types/known/durationpb" + _ "google.golang.org/protobuf/types/known/timestamppb" io "io" math "math" math_bits "math/bits" diff --git a/x/slashing/types/slashing.pb.go b/x/slashing/types/slashing.pb.go index 2f48e117ebc9..633b4c5bb944 100644 --- a/x/slashing/types/slashing.pb.go +++ b/x/slashing/types/slashing.pb.go @@ -9,8 +9,8 @@ import ( _ "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" + _ "google.golang.org/protobuf/types/known/durationpb" + _ "google.golang.org/protobuf/types/known/timestamppb" io "io" math "math" math_bits "math/bits" diff --git a/x/staking/types/staking.pb.go b/x/staking/types/staking.pb.go index 36b5a0b666d6..dfd83e451845 100644 --- a/x/staking/types/staking.pb.go +++ b/x/staking/types/staking.pb.go @@ -15,10 +15,10 @@ import ( proto "github.com/gogo/protobuf/proto" github_com_gogo_protobuf_protoc_gen_gogo_descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor" 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" types "github.com/tendermint/tendermint/proto/tendermint/types" + _ "google.golang.org/protobuf/types/known/durationpb" + _ "google.golang.org/protobuf/types/known/timestamppb" io "io" io_ioutil "io/ioutil" math "math" @@ -1260,621 +1260,620 @@ func (this *Pool) Description() (desc *github_com_gogo_protobuf_protoc_gen_gogo_ func StakingDescription() (desc *github_com_gogo_protobuf_protoc_gen_gogo_descriptor.FileDescriptorSet) { d := &github_com_gogo_protobuf_protoc_gen_gogo_descriptor.FileDescriptorSet{} var gzipped = []byte{ - // 9822 bytes of a gzipped FileDescriptorSet + // 9808 bytes of a gzipped FileDescriptorSet 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x7d, 0x6d, 0x70, 0x5c, 0xd7, 0x75, 0x18, 0xde, 0x7e, 0x00, 0xbb, 0x07, 0x0b, 0x60, 0x71, 0x01, 0x92, 0xcb, 0x25, 0x09, 0x40, - 0x4f, 0x5f, 0x14, 0x25, 0x82, 0x12, 0x25, 0x52, 0xd2, 0xd2, 0x96, 0xbc, 0x8b, 0x5d, 0x82, 0x10, + 0x4f, 0x5f, 0x14, 0x25, 0x81, 0x12, 0x25, 0x52, 0xd2, 0xd2, 0xb6, 0xbc, 0x8b, 0x5d, 0x82, 0x10, 0xf1, 0xa5, 0x07, 0x80, 0x92, 0x65, 0xa7, 0x3b, 0x0f, 0xbb, 0x17, 0x8b, 0x27, 0xec, 0xbe, 0xf7, - 0xf4, 0xde, 0x5b, 0x12, 0x90, 0xed, 0x19, 0xc5, 0x76, 0x5d, 0x9b, 0x69, 0x6a, 0xbb, 0xce, 0xa4, - 0xb6, 0x62, 0xba, 0x76, 0x9c, 0xd6, 0xa9, 0xe3, 0x36, 0x1f, 0x76, 0xdd, 0xa6, 0xed, 0x4c, 0xed, - 0xb6, 0x69, 0x6c, 0xb7, 0xc9, 0xd8, 0x6d, 0xa6, 0x4d, 0x33, 0x2d, 0x9d, 0xca, 0x9e, 0x54, 0x75, - 0xdd, 0xc6, 0x61, 0x9c, 0x36, 0x1d, 0x4f, 0xa7, 0x9d, 0xfb, 0xf5, 0xbe, 0xf6, 0x13, 0x10, 0x69, - 0x3b, 0x4d, 0x7e, 0x61, 0xef, 0xb9, 0xe7, 0x9c, 0x7b, 0xee, 0xb9, 0xe7, 0x9c, 0x7b, 0xee, 0xd7, - 0x03, 0xfc, 0xf3, 0x0b, 0x30, 0x53, 0x33, 0x8c, 0x5a, 0x1d, 0x9f, 0x31, 0x2d, 0xc3, 0x31, 0x36, - 0x9b, 0x5b, 0x67, 0xaa, 0xd8, 0xae, 0x58, 0x9a, 0xe9, 0x18, 0xd6, 0x2c, 0x85, 0xa1, 0x31, 0x86, - 0x31, 0x2b, 0x30, 0xe4, 0x25, 0x18, 0xbf, 0xa8, 0xd5, 0x71, 0xd1, 0x45, 0x5c, 0xc3, 0x0e, 0x7a, - 0x02, 0x62, 0x5b, 0x5a, 0x1d, 0x67, 0xa4, 0x99, 0xe8, 0xc9, 0xe1, 0xb3, 0xf7, 0xcc, 0x86, 0x88, - 0x66, 0x83, 0x14, 0xab, 0x04, 0xac, 0x50, 0x0a, 0xf9, 0xdb, 0x31, 0x98, 0x68, 0x53, 0x8b, 0x10, + 0xf4, 0xde, 0x5b, 0x12, 0xa0, 0xed, 0x8e, 0x62, 0xbb, 0xae, 0xcd, 0x4c, 0x1a, 0xbb, 0xee, 0x34, + 0xb6, 0x6c, 0xba, 0x76, 0x9c, 0xd6, 0xa9, 0xe3, 0x36, 0x71, 0xec, 0xba, 0x4d, 0xdb, 0x99, 0xda, + 0x9d, 0xa6, 0xb1, 0xdd, 0x26, 0x63, 0xb7, 0x99, 0x36, 0xcd, 0xb4, 0x74, 0x2a, 0x7b, 0x52, 0xd5, + 0x75, 0x1b, 0x87, 0x71, 0xda, 0x74, 0x3c, 0x9d, 0x76, 0xee, 0xd7, 0xfb, 0xda, 0x4f, 0x40, 0xa4, + 0xe5, 0x34, 0xf9, 0x85, 0xbd, 0xe7, 0x9e, 0x73, 0xee, 0x39, 0xe7, 0x9e, 0x7b, 0xee, 0xb9, 0x5f, + 0x0f, 0xf0, 0x85, 0xf3, 0x30, 0x53, 0x33, 0x8c, 0x5a, 0x1d, 0x9f, 0x36, 0x2d, 0xc3, 0x31, 0x36, + 0x9b, 0x5b, 0xa7, 0xab, 0xd8, 0xae, 0x58, 0x9a, 0xe9, 0x18, 0xd6, 0x2c, 0x85, 0xa1, 0x31, 0x86, + 0x31, 0x2b, 0x30, 0xe4, 0x25, 0x18, 0xbf, 0xa0, 0xd5, 0x71, 0xd1, 0x45, 0x5c, 0xc3, 0x0e, 0x7a, + 0x12, 0x62, 0x5b, 0x5a, 0x1d, 0x67, 0xa4, 0x99, 0xe8, 0xc9, 0xe1, 0x33, 0xf7, 0xcc, 0x86, 0x88, + 0x66, 0x83, 0x14, 0xab, 0x04, 0xac, 0x50, 0x0a, 0xf9, 0xbb, 0x31, 0x98, 0x68, 0x53, 0x8b, 0x10, 0xc4, 0x74, 0xb5, 0x41, 0x38, 0x4a, 0x27, 0x93, 0x0a, 0xfd, 0x8d, 0x32, 0x30, 0x64, 0xaa, 0x95, 0x1d, 0xb5, 0x86, 0x33, 0x11, 0x0a, 0x16, 0x45, 0x34, 0x05, 0x50, 0xc5, 0x26, 0xd6, 0xab, 0x58, 0xaf, 0xec, 0x65, 0xa2, 0x33, 0xd1, 0x93, 0x49, 0xc5, 0x07, 0x41, 0x0f, 0xc2, 0xb8, 0xd9, 0xdc, 0xac, 0x6b, 0x95, 0xb2, 0x0f, 0x0d, 0x66, 0xa2, 0x27, 0xe3, 0x4a, 0x9a, 0x55, 0x14, 0x3d, 0xe4, - 0xfb, 0x61, 0xec, 0x1a, 0x56, 0x77, 0xfc, 0xa8, 0xc3, 0x14, 0x75, 0x94, 0x80, 0x7d, 0x88, 0x73, - 0x90, 0x6a, 0x60, 0xdb, 0x56, 0x6b, 0xb8, 0xec, 0xec, 0x99, 0x38, 0x13, 0xa3, 0xbd, 0x9f, 0x69, - 0xe9, 0x7d, 0xb8, 0xe7, 0xc3, 0x9c, 0x6a, 0x7d, 0xcf, 0xc4, 0x28, 0x0f, 0x49, 0xac, 0x37, 0x1b, - 0x8c, 0x43, 0xbc, 0x83, 0xfe, 0x4a, 0x7a, 0xb3, 0x11, 0xe6, 0x92, 0x20, 0x64, 0x9c, 0xc5, 0x90, - 0x8d, 0xad, 0xab, 0x5a, 0x05, 0x67, 0x06, 0x29, 0x83, 0xfb, 0x5b, 0x18, 0xac, 0xb1, 0xfa, 0x30, - 0x0f, 0x41, 0x87, 0xe6, 0x20, 0x89, 0x77, 0x1d, 0xac, 0xdb, 0x9a, 0xa1, 0x67, 0x86, 0x28, 0x93, - 0x7b, 0xdb, 0x8c, 0x22, 0xae, 0x57, 0xc3, 0x2c, 0x3c, 0x3a, 0x74, 0x1e, 0x86, 0x0c, 0xd3, 0xd1, - 0x0c, 0xdd, 0xce, 0x24, 0x66, 0xa4, 0x93, 0xc3, 0x67, 0x8f, 0xb7, 0x35, 0x84, 0x15, 0x86, 0xa3, - 0x08, 0x64, 0xb4, 0x00, 0x69, 0xdb, 0x68, 0x5a, 0x15, 0x5c, 0xae, 0x18, 0x55, 0x5c, 0xd6, 0xf4, - 0x2d, 0x23, 0x93, 0xa4, 0x0c, 0xa6, 0x5b, 0x3b, 0x42, 0x11, 0xe7, 0x8c, 0x2a, 0x5e, 0xd0, 0xb7, - 0x0c, 0x65, 0xd4, 0x0e, 0x94, 0xd1, 0x61, 0x18, 0xb4, 0xf7, 0x74, 0x47, 0xdd, 0xcd, 0xa4, 0xa8, - 0x85, 0xf0, 0x92, 0xfc, 0xeb, 0x83, 0x30, 0xd6, 0x8f, 0x89, 0x5d, 0x80, 0xf8, 0x16, 0xe9, 0x65, - 0x26, 0xb2, 0x1f, 0x1d, 0x30, 0x9a, 0xa0, 0x12, 0x07, 0x0f, 0xa8, 0xc4, 0x3c, 0x0c, 0xeb, 0xd8, - 0x76, 0x70, 0x95, 0x59, 0x44, 0xb4, 0x4f, 0x9b, 0x02, 0x46, 0xd4, 0x6a, 0x52, 0xb1, 0x03, 0x99, - 0xd4, 0xf3, 0x30, 0xe6, 0x8a, 0x54, 0xb6, 0x54, 0xbd, 0x26, 0x6c, 0xf3, 0x4c, 0x2f, 0x49, 0x66, - 0x4b, 0x82, 0x4e, 0x21, 0x64, 0xca, 0x28, 0x0e, 0x94, 0x51, 0x11, 0xc0, 0xd0, 0xb1, 0xb1, 0x55, - 0xae, 0xe2, 0x4a, 0x3d, 0x93, 0xe8, 0xa0, 0xa5, 0x15, 0x82, 0xd2, 0xa2, 0x25, 0x83, 0x41, 0x2b, - 0x75, 0xf4, 0xa4, 0x67, 0x6a, 0x43, 0x1d, 0x2c, 0x65, 0x89, 0x39, 0x59, 0x8b, 0xb5, 0x6d, 0xc0, - 0xa8, 0x85, 0x89, 0xdd, 0xe3, 0x2a, 0xef, 0x59, 0x92, 0x0a, 0x31, 0xdb, 0xb3, 0x67, 0x0a, 0x27, - 0x63, 0x1d, 0x1b, 0xb1, 0xfc, 0x45, 0x74, 0x37, 0xb8, 0x80, 0x32, 0x35, 0x2b, 0xa0, 0x51, 0x28, - 0x25, 0x80, 0xcb, 0x6a, 0x03, 0x67, 0x5f, 0x86, 0xd1, 0xa0, 0x7a, 0xd0, 0x24, 0xc4, 0x6d, 0x47, - 0xb5, 0x1c, 0x6a, 0x85, 0x71, 0x85, 0x15, 0x50, 0x1a, 0xa2, 0x58, 0xaf, 0xd2, 0x28, 0x17, 0x57, - 0xc8, 0x4f, 0xf4, 0x16, 0xaf, 0xc3, 0x51, 0xda, 0xe1, 0xfb, 0x5a, 0x47, 0x34, 0xc0, 0x39, 0xdc, - 0xef, 0xec, 0xe3, 0x30, 0x12, 0xe8, 0x40, 0xbf, 0x4d, 0xcb, 0xef, 0x84, 0x43, 0x6d, 0x59, 0xa3, - 0xe7, 0x61, 0xb2, 0xa9, 0x6b, 0xba, 0x83, 0x2d, 0xd3, 0xc2, 0xc4, 0x62, 0x59, 0x53, 0x99, 0xff, - 0x32, 0xd4, 0xc1, 0xe6, 0x36, 0xfc, 0xd8, 0x8c, 0x8b, 0x32, 0xd1, 0x6c, 0x05, 0x9e, 0x4a, 0x26, - 0x5e, 0x1f, 0x4a, 0xbf, 0xf2, 0xca, 0x2b, 0xaf, 0x44, 0xe4, 0x2f, 0x0f, 0xc2, 0x64, 0x3b, 0x9f, - 0x69, 0xeb, 0xbe, 0x87, 0x61, 0x50, 0x6f, 0x36, 0x36, 0xb1, 0x45, 0x95, 0x14, 0x57, 0x78, 0x09, - 0xe5, 0x21, 0x5e, 0x57, 0x37, 0x71, 0x3d, 0x13, 0x9b, 0x91, 0x4e, 0x8e, 0x9e, 0x7d, 0xb0, 0x2f, - 0xaf, 0x9c, 0x5d, 0x24, 0x24, 0x0a, 0xa3, 0x44, 0x4f, 0x41, 0x8c, 0x87, 0x68, 0xc2, 0xe1, 0x54, - 0x7f, 0x1c, 0x88, 0x2f, 0x29, 0x94, 0x0e, 0x1d, 0x83, 0x24, 0xf9, 0xcb, 0x6c, 0x63, 0x90, 0xca, - 0x9c, 0x20, 0x00, 0x62, 0x17, 0x28, 0x0b, 0x09, 0xea, 0x26, 0x55, 0x2c, 0xa6, 0x36, 0xb7, 0x4c, - 0x0c, 0xab, 0x8a, 0xb7, 0xd4, 0x66, 0xdd, 0x29, 0x5f, 0x55, 0xeb, 0x4d, 0x4c, 0x0d, 0x3e, 0xa9, - 0xa4, 0x38, 0xf0, 0x0a, 0x81, 0xa1, 0x69, 0x18, 0x66, 0x5e, 0xa5, 0xe9, 0x55, 0xbc, 0x4b, 0xa3, - 0x67, 0x5c, 0x61, 0x8e, 0xb6, 0x40, 0x20, 0xa4, 0xf9, 0x17, 0x6d, 0x43, 0x17, 0xa6, 0x49, 0x9b, - 0x20, 0x00, 0xda, 0xfc, 0xe3, 0xe1, 0xc0, 0x7d, 0xa2, 0x7d, 0xf7, 0x5a, 0x7c, 0xe9, 0x7e, 0x18, - 0xa3, 0x18, 0x8f, 0xf2, 0xa1, 0x57, 0xeb, 0x99, 0xf1, 0x19, 0xe9, 0x64, 0x42, 0x19, 0x65, 0xe0, - 0x15, 0x0e, 0x95, 0xbf, 0x18, 0x81, 0x18, 0x0d, 0x2c, 0x63, 0x30, 0xbc, 0xfe, 0xd6, 0xd5, 0x52, - 0xb9, 0xb8, 0xb2, 0x51, 0x58, 0x2c, 0xa5, 0x25, 0x34, 0x0a, 0x40, 0x01, 0x17, 0x17, 0x57, 0xf2, - 0xeb, 0xe9, 0x88, 0x5b, 0x5e, 0x58, 0x5e, 0x3f, 0xff, 0x58, 0x3a, 0xea, 0x12, 0x6c, 0x30, 0x40, - 0xcc, 0x8f, 0xf0, 0xe8, 0xd9, 0x74, 0x1c, 0xa5, 0x21, 0xc5, 0x18, 0x2c, 0x3c, 0x5f, 0x2a, 0x9e, - 0x7f, 0x2c, 0x3d, 0x18, 0x84, 0x3c, 0x7a, 0x36, 0x3d, 0x84, 0x46, 0x20, 0x49, 0x21, 0x85, 0x95, - 0x95, 0xc5, 0x74, 0xc2, 0xe5, 0xb9, 0xb6, 0xae, 0x2c, 0x2c, 0xcf, 0xa7, 0x93, 0x2e, 0xcf, 0x79, - 0x65, 0x65, 0x63, 0x35, 0x0d, 0x2e, 0x87, 0xa5, 0xd2, 0xda, 0x5a, 0x7e, 0xbe, 0x94, 0x1e, 0x76, - 0x31, 0x0a, 0x6f, 0x5d, 0x2f, 0xad, 0xa5, 0x53, 0x01, 0xb1, 0x1e, 0x3d, 0x9b, 0x1e, 0x71, 0x9b, - 0x28, 0x2d, 0x6f, 0x2c, 0xa5, 0x47, 0xd1, 0x38, 0x8c, 0xb0, 0x26, 0x84, 0x10, 0x63, 0x21, 0xd0, - 0xf9, 0xc7, 0xd2, 0x69, 0x4f, 0x10, 0xc6, 0x65, 0x3c, 0x00, 0x38, 0xff, 0x58, 0x1a, 0xc9, 0x73, - 0x10, 0xa7, 0x66, 0x88, 0x10, 0x8c, 0x2e, 0xe6, 0x0b, 0xa5, 0xc5, 0xf2, 0xca, 0xea, 0xfa, 0xc2, - 0xca, 0x72, 0x7e, 0x31, 0x2d, 0x79, 0x30, 0xa5, 0xf4, 0xec, 0xc6, 0x82, 0x52, 0x2a, 0xa6, 0x23, - 0x7e, 0xd8, 0x6a, 0x29, 0xbf, 0x5e, 0x2a, 0xa6, 0xa3, 0x72, 0x05, 0x26, 0xdb, 0x05, 0xd4, 0xb6, - 0x2e, 0xe4, 0xb3, 0x85, 0x48, 0x07, 0x5b, 0xa0, 0xbc, 0xc2, 0xb6, 0x20, 0x7f, 0x2b, 0x02, 0x13, - 0x6d, 0x26, 0x95, 0xb6, 0x8d, 0x3c, 0x0d, 0x71, 0x66, 0xcb, 0x6c, 0x9a, 0x7d, 0xa0, 0xed, 0xec, - 0x44, 0x2d, 0xbb, 0x65, 0xaa, 0xa5, 0x74, 0xfe, 0x54, 0x23, 0xda, 0x21, 0xd5, 0x20, 0x2c, 0x5a, - 0x0c, 0xf6, 0x27, 0x5a, 0x82, 0x3f, 0x9b, 0x1f, 0xcf, 0xf7, 0x33, 0x3f, 0x52, 0xd8, 0xfe, 0x26, - 0x81, 0x78, 0x9b, 0x49, 0xe0, 0x02, 0x8c, 0xb7, 0x30, 0xea, 0x3b, 0x18, 0xbf, 0x47, 0x82, 0x4c, - 0x27, 0xe5, 0xf4, 0x08, 0x89, 0x91, 0x40, 0x48, 0xbc, 0x10, 0xd6, 0xe0, 0x5d, 0x9d, 0x07, 0xa1, - 0x65, 0xac, 0x3f, 0x23, 0xc1, 0xe1, 0xf6, 0x29, 0x65, 0x5b, 0x19, 0x9e, 0x82, 0xc1, 0x06, 0x76, - 0xb6, 0x0d, 0x91, 0x56, 0xdd, 0xd7, 0x66, 0xb2, 0x26, 0xd5, 0xe1, 0xc1, 0xe6, 0x54, 0xfe, 0xd9, - 0x3e, 0xda, 0x29, 0x2f, 0x64, 0xd2, 0xb4, 0x48, 0xfa, 0x81, 0x08, 0x1c, 0x6a, 0xcb, 0xbc, 0xad, - 0xa0, 0x27, 0x00, 0x34, 0xdd, 0x6c, 0x3a, 0x2c, 0x75, 0x62, 0x91, 0x38, 0x49, 0x21, 0x34, 0x78, - 0x91, 0x28, 0xdb, 0x74, 0xdc, 0xfa, 0x28, 0xad, 0x07, 0x06, 0xa2, 0x08, 0x4f, 0x78, 0x82, 0xc6, - 0xa8, 0xa0, 0x53, 0x1d, 0x7a, 0xda, 0x62, 0x98, 0x0f, 0x43, 0xba, 0x52, 0xd7, 0xb0, 0xee, 0x94, - 0x6d, 0xc7, 0xc2, 0x6a, 0x43, 0xd3, 0x6b, 0x74, 0xaa, 0x49, 0xe4, 0xe2, 0x5b, 0x6a, 0xdd, 0xc6, - 0xca, 0x18, 0xab, 0x5e, 0x13, 0xb5, 0x84, 0x82, 0x1a, 0x90, 0xe5, 0xa3, 0x18, 0x0c, 0x50, 0xb0, - 0x6a, 0x97, 0x42, 0xfe, 0x70, 0x12, 0x86, 0x7d, 0x09, 0x38, 0xba, 0x0b, 0x52, 0x2f, 0xaa, 0x57, - 0xd5, 0xb2, 0x58, 0x54, 0x31, 0x4d, 0x0c, 0x13, 0xd8, 0x2a, 0x5f, 0x58, 0x3d, 0x0c, 0x93, 0x14, - 0xc5, 0x68, 0x3a, 0xd8, 0x2a, 0x57, 0xea, 0xaa, 0x6d, 0x53, 0xa5, 0x25, 0x28, 0x2a, 0x22, 0x75, - 0x2b, 0xa4, 0x6a, 0x4e, 0xd4, 0xa0, 0x73, 0x30, 0x41, 0x29, 0x1a, 0xcd, 0xba, 0xa3, 0x99, 0x75, - 0x5c, 0x26, 0xcb, 0x3c, 0x9b, 0x4e, 0x39, 0xae, 0x64, 0xe3, 0x04, 0x63, 0x89, 0x23, 0x10, 0x89, - 0x6c, 0x54, 0x84, 0x13, 0x94, 0xac, 0x86, 0x75, 0x6c, 0xa9, 0x0e, 0x2e, 0xe3, 0x97, 0x9a, 0x6a, - 0xdd, 0x2e, 0xab, 0x7a, 0xb5, 0xbc, 0xad, 0xda, 0xdb, 0x99, 0x49, 0xc2, 0xa0, 0x10, 0xc9, 0x48, - 0xca, 0x51, 0x82, 0x38, 0xcf, 0xf1, 0x4a, 0x14, 0x2d, 0xaf, 0x57, 0x2f, 0xa9, 0xf6, 0x36, 0xca, - 0xc1, 0x61, 0xca, 0xc5, 0x76, 0x2c, 0x4d, 0xaf, 0x95, 0x2b, 0xdb, 0xb8, 0xb2, 0x53, 0x6e, 0x3a, - 0x5b, 0x4f, 0x64, 0x8e, 0xf9, 0xdb, 0xa7, 0x12, 0xae, 0x51, 0x9c, 0x39, 0x82, 0xb2, 0xe1, 0x6c, - 0x3d, 0x81, 0xd6, 0x20, 0x45, 0x06, 0xa3, 0xa1, 0xbd, 0x8c, 0xcb, 0x5b, 0x86, 0x45, 0xe7, 0xd0, - 0xd1, 0x36, 0xa1, 0xc9, 0xa7, 0xc1, 0xd9, 0x15, 0x4e, 0xb0, 0x64, 0x54, 0x71, 0x2e, 0xbe, 0xb6, - 0x5a, 0x2a, 0x15, 0x95, 0x61, 0xc1, 0xe5, 0xa2, 0x61, 0x11, 0x83, 0xaa, 0x19, 0xae, 0x82, 0x87, - 0x99, 0x41, 0xd5, 0x0c, 0xa1, 0xde, 0x73, 0x30, 0x51, 0xa9, 0xb0, 0x3e, 0x6b, 0x95, 0x32, 0x5f, - 0x8c, 0xd9, 0x99, 0x74, 0x40, 0x59, 0x95, 0xca, 0x3c, 0x43, 0xe0, 0x36, 0x6e, 0xa3, 0x27, 0xe1, - 0x90, 0xa7, 0x2c, 0x3f, 0xe1, 0x78, 0x4b, 0x2f, 0xc3, 0xa4, 0xe7, 0x60, 0xc2, 0xdc, 0x6b, 0x25, - 0x44, 0x81, 0x16, 0xcd, 0xbd, 0x30, 0xd9, 0xe3, 0x30, 0x69, 0x6e, 0x9b, 0xad, 0x74, 0xa7, 0xfc, - 0x74, 0xc8, 0xdc, 0x36, 0xc3, 0x84, 0xf7, 0xd2, 0x95, 0xb9, 0x85, 0x2b, 0xaa, 0x83, 0xab, 0x99, - 0x23, 0x7e, 0x74, 0x5f, 0x05, 0x9a, 0x85, 0x74, 0xa5, 0x52, 0xc6, 0xba, 0xba, 0x59, 0xc7, 0x65, - 0xd5, 0xc2, 0xba, 0x6a, 0x67, 0xa6, 0x29, 0x72, 0xcc, 0xb1, 0x9a, 0x58, 0x19, 0xad, 0x54, 0x4a, - 0xb4, 0x32, 0x4f, 0xeb, 0xd0, 0x29, 0x18, 0x37, 0x36, 0x5f, 0xac, 0x30, 0x8b, 0x2c, 0x9b, 0x16, - 0xde, 0xd2, 0x76, 0x33, 0xf7, 0x50, 0xf5, 0x8e, 0x91, 0x0a, 0x6a, 0x8f, 0xab, 0x14, 0x8c, 0x1e, - 0x80, 0x74, 0xc5, 0xde, 0x56, 0x2d, 0x93, 0x86, 0x64, 0xdb, 0x54, 0x2b, 0x38, 0x73, 0x2f, 0x43, - 0x65, 0xf0, 0x65, 0x01, 0x26, 0x1e, 0x61, 0x5f, 0xd3, 0xb6, 0x1c, 0xc1, 0xf1, 0x7e, 0xe6, 0x11, - 0x14, 0xc6, 0xb9, 0x9d, 0x84, 0x34, 0xd1, 0x44, 0xa0, 0xe1, 0x93, 0x14, 0x6d, 0xd4, 0xdc, 0x36, - 0xfd, 0xed, 0xde, 0x0d, 0x23, 0x04, 0xd3, 0x6b, 0xf4, 0x01, 0x96, 0xb8, 0x99, 0xdb, 0xbe, 0x16, - 0x1f, 0x83, 0xc3, 0x04, 0xa9, 0x81, 0x1d, 0xb5, 0xaa, 0x3a, 0xaa, 0x0f, 0xfb, 0x21, 0x8a, 0x4d, - 0xd4, 0xbe, 0xc4, 0x2b, 0x03, 0x72, 0x5a, 0xcd, 0xcd, 0x3d, 0xd7, 0xb0, 0x4e, 0x33, 0x39, 0x09, - 0x4c, 0x98, 0xd6, 0x1d, 0x4b, 0xce, 0xe5, 0x1c, 0xa4, 0xfc, 0x76, 0x8f, 0x92, 0xc0, 0x2c, 0x3f, - 0x2d, 0x91, 0x24, 0x68, 0x6e, 0xa5, 0x48, 0xd2, 0x97, 0x17, 0x4a, 0xe9, 0x08, 0x49, 0xa3, 0x16, - 0x17, 0xd6, 0x4b, 0x65, 0x65, 0x63, 0x79, 0x7d, 0x61, 0xa9, 0x94, 0x8e, 0xfa, 0x12, 0xfb, 0x67, - 0x62, 0x89, 0xfb, 0xd2, 0xf7, 0xcb, 0xdf, 0x88, 0xc0, 0x68, 0x70, 0xa5, 0x86, 0xde, 0x04, 0x47, - 0xc4, 0xb6, 0x8a, 0x8d, 0x9d, 0xf2, 0x35, 0xcd, 0xa2, 0x0e, 0xd9, 0x50, 0xd9, 0xe4, 0xe8, 0xda, - 0xcf, 0x24, 0xc7, 0x5a, 0xc3, 0xce, 0x73, 0x9a, 0x45, 0xdc, 0xad, 0xa1, 0x3a, 0x68, 0x11, 0xa6, - 0x75, 0xa3, 0x6c, 0x3b, 0xaa, 0x5e, 0x55, 0xad, 0x6a, 0xd9, 0xdb, 0xd0, 0x2a, 0xab, 0x95, 0x0a, - 0xb6, 0x6d, 0x83, 0x4d, 0x84, 0x2e, 0x97, 0xe3, 0xba, 0xb1, 0xc6, 0x91, 0xbd, 0x19, 0x22, 0xcf, - 0x51, 0x43, 0xe6, 0x1b, 0xed, 0x64, 0xbe, 0xc7, 0x20, 0xd9, 0x50, 0xcd, 0x32, 0xd6, 0x1d, 0x6b, - 0x8f, 0xe6, 0xe7, 0x09, 0x25, 0xd1, 0x50, 0xcd, 0x12, 0x29, 0xff, 0x50, 0x96, 0x49, 0xcf, 0xc4, - 0x12, 0x89, 0x74, 0xf2, 0x99, 0x58, 0x22, 0x99, 0x06, 0xf9, 0xb5, 0x28, 0xa4, 0xfc, 0xf9, 0x3a, - 0x59, 0xfe, 0x54, 0xe8, 0x8c, 0x25, 0xd1, 0x98, 0x76, 0x77, 0xd7, 0xec, 0x7e, 0x76, 0x8e, 0x4c, - 0x65, 0xb9, 0x41, 0x96, 0x1c, 0x2b, 0x8c, 0x92, 0xa4, 0x11, 0xc4, 0xd8, 0x30, 0x4b, 0x46, 0x12, - 0x0a, 0x2f, 0xa1, 0x79, 0x18, 0x7c, 0xd1, 0xa6, 0xbc, 0x07, 0x29, 0xef, 0x7b, 0xba, 0xf3, 0x7e, - 0x66, 0x8d, 0x32, 0x4f, 0x3e, 0xb3, 0x56, 0x5e, 0x5e, 0x51, 0x96, 0xf2, 0x8b, 0x0a, 0x27, 0x47, - 0x47, 0x21, 0x56, 0x57, 0x5f, 0xde, 0x0b, 0x4e, 0x7a, 0x14, 0xd4, 0xef, 0x20, 0x1c, 0x85, 0xd8, - 0x35, 0xac, 0xee, 0x04, 0xa7, 0x1a, 0x0a, 0xba, 0x83, 0xce, 0x70, 0x06, 0xe2, 0x54, 0x5f, 0x08, - 0x80, 0x6b, 0x2c, 0x3d, 0x80, 0x12, 0x10, 0x9b, 0x5b, 0x51, 0x88, 0x43, 0xa4, 0x21, 0xc5, 0xa0, - 0xe5, 0xd5, 0x85, 0xd2, 0x5c, 0x29, 0x1d, 0x91, 0xcf, 0xc1, 0x20, 0x53, 0x02, 0x71, 0x16, 0x57, - 0x0d, 0xe9, 0x01, 0x5e, 0xe4, 0x3c, 0x24, 0x51, 0xbb, 0xb1, 0x54, 0x28, 0x29, 0xe9, 0x48, 0x70, - 0xa8, 0x63, 0xe9, 0xb8, 0x6c, 0x43, 0xca, 0x9f, 0x87, 0xff, 0x70, 0x16, 0xe3, 0x5f, 0x92, 0x60, - 0xd8, 0x97, 0x57, 0x93, 0x84, 0x48, 0xad, 0xd7, 0x8d, 0x6b, 0x65, 0xb5, 0xae, 0xa9, 0x36, 0x37, - 0x0d, 0xa0, 0xa0, 0x3c, 0x81, 0xf4, 0x3b, 0x74, 0x3f, 0x24, 0x17, 0x89, 0xa7, 0x07, 0xe5, 0x4f, - 0x48, 0x90, 0x0e, 0x27, 0xb6, 0x21, 0x31, 0xa5, 0x1f, 0xa5, 0x98, 0xf2, 0xc7, 0x25, 0x18, 0x0d, - 0x66, 0xb3, 0x21, 0xf1, 0xee, 0xfa, 0x91, 0x8a, 0xf7, 0xfb, 0x11, 0x18, 0x09, 0xe4, 0xb0, 0xfd, + 0xfb, 0x61, 0xec, 0x2a, 0x56, 0x77, 0xfc, 0xa8, 0xc3, 0x14, 0x75, 0x94, 0x80, 0x7d, 0x88, 0x73, + 0x90, 0x6a, 0x60, 0xdb, 0x56, 0x6b, 0xb8, 0xec, 0xec, 0x99, 0x38, 0x13, 0xa3, 0xda, 0xcf, 0xb4, + 0x68, 0x1f, 0xd6, 0x7c, 0x98, 0x53, 0xad, 0xef, 0x99, 0x18, 0xe5, 0x21, 0x89, 0xf5, 0x66, 0x83, + 0x71, 0x88, 0x77, 0xb0, 0x5f, 0x49, 0x6f, 0x36, 0xc2, 0x5c, 0x12, 0x84, 0x8c, 0xb3, 0x18, 0xb2, + 0xb1, 0x75, 0x45, 0xab, 0xe0, 0xcc, 0x20, 0x65, 0x70, 0x7f, 0x0b, 0x83, 0x35, 0x56, 0x1f, 0xe6, + 0x21, 0xe8, 0xd0, 0x1c, 0x24, 0xf1, 0xae, 0x83, 0x75, 0x5b, 0x33, 0xf4, 0xcc, 0x10, 0x65, 0x72, + 0x6f, 0x9b, 0x5e, 0xc4, 0xf5, 0x6a, 0x98, 0x85, 0x47, 0x87, 0xce, 0xc1, 0x90, 0x61, 0x3a, 0x9a, + 0xa1, 0xdb, 0x99, 0xc4, 0x8c, 0x74, 0x72, 0xf8, 0xcc, 0xf1, 0xb6, 0x8e, 0xb0, 0xc2, 0x70, 0x14, + 0x81, 0x8c, 0x16, 0x20, 0x6d, 0x1b, 0x4d, 0xab, 0x82, 0xcb, 0x15, 0xa3, 0x8a, 0xcb, 0x9a, 0xbe, + 0x65, 0x64, 0x92, 0x94, 0xc1, 0x74, 0xab, 0x22, 0x14, 0x71, 0xce, 0xa8, 0xe2, 0x05, 0x7d, 0xcb, + 0x50, 0x46, 0xed, 0x40, 0x19, 0x1d, 0x86, 0x41, 0x7b, 0x4f, 0x77, 0xd4, 0xdd, 0x4c, 0x8a, 0x7a, + 0x08, 0x2f, 0xc9, 0xbf, 0x3e, 0x08, 0x63, 0xfd, 0xb8, 0xd8, 0x79, 0x88, 0x6f, 0x11, 0x2d, 0x33, + 0x91, 0xfd, 0xd8, 0x80, 0xd1, 0x04, 0x8d, 0x38, 0x78, 0x40, 0x23, 0xe6, 0x61, 0x58, 0xc7, 0xb6, + 0x83, 0xab, 0xcc, 0x23, 0xa2, 0x7d, 0xfa, 0x14, 0x30, 0xa2, 0x56, 0x97, 0x8a, 0x1d, 0xc8, 0xa5, + 0x9e, 0x87, 0x31, 0x57, 0xa4, 0xb2, 0xa5, 0xea, 0x35, 0xe1, 0x9b, 0xa7, 0x7b, 0x49, 0x32, 0x5b, + 0x12, 0x74, 0x0a, 0x21, 0x53, 0x46, 0x71, 0xa0, 0x8c, 0x8a, 0x00, 0x86, 0x8e, 0x8d, 0xad, 0x72, + 0x15, 0x57, 0xea, 0x99, 0x44, 0x07, 0x2b, 0xad, 0x10, 0x94, 0x16, 0x2b, 0x19, 0x0c, 0x5a, 0xa9, + 0xa3, 0xa7, 0x3c, 0x57, 0x1b, 0xea, 0xe0, 0x29, 0x4b, 0x6c, 0x90, 0xb5, 0x78, 0xdb, 0x06, 0x8c, + 0x5a, 0x98, 0xf8, 0x3d, 0xae, 0x72, 0xcd, 0x92, 0x54, 0x88, 0xd9, 0x9e, 0x9a, 0x29, 0x9c, 0x8c, + 0x29, 0x36, 0x62, 0xf9, 0x8b, 0xe8, 0x6e, 0x70, 0x01, 0x65, 0xea, 0x56, 0x40, 0xa3, 0x50, 0x4a, + 0x00, 0x97, 0xd5, 0x06, 0xce, 0x5e, 0x83, 0xd1, 0xa0, 0x79, 0xd0, 0x24, 0xc4, 0x6d, 0x47, 0xb5, + 0x1c, 0xea, 0x85, 0x71, 0x85, 0x15, 0x50, 0x1a, 0xa2, 0x58, 0xaf, 0xd2, 0x28, 0x17, 0x57, 0xc8, + 0x4f, 0xf4, 0x56, 0x4f, 0xe1, 0x28, 0x55, 0xf8, 0xbe, 0xd6, 0x1e, 0x0d, 0x70, 0x0e, 0xeb, 0x9d, + 0x7d, 0x02, 0x46, 0x02, 0x0a, 0xf4, 0xdb, 0xb4, 0xfc, 0x2e, 0x38, 0xd4, 0x96, 0x35, 0x7a, 0x1e, + 0x26, 0x9b, 0xba, 0xa6, 0x3b, 0xd8, 0x32, 0x2d, 0x4c, 0x3c, 0x96, 0x35, 0x95, 0xf9, 0x2f, 0x43, + 0x1d, 0x7c, 0x6e, 0xc3, 0x8f, 0xcd, 0xb8, 0x28, 0x13, 0xcd, 0x56, 0xe0, 0xa9, 0x64, 0xe2, 0xb5, + 0xa1, 0xf4, 0xcb, 0x2f, 0xbf, 0xfc, 0x72, 0x44, 0xfe, 0xea, 0x20, 0x4c, 0xb6, 0x1b, 0x33, 0x6d, + 0x87, 0xef, 0x61, 0x18, 0xd4, 0x9b, 0x8d, 0x4d, 0x6c, 0x51, 0x23, 0xc5, 0x15, 0x5e, 0x42, 0x79, + 0x88, 0xd7, 0xd5, 0x4d, 0x5c, 0xcf, 0xc4, 0x66, 0xa4, 0x93, 0xa3, 0x67, 0x1e, 0xec, 0x6b, 0x54, + 0xce, 0x2e, 0x12, 0x12, 0x85, 0x51, 0xa2, 0xb7, 0x40, 0x8c, 0x87, 0x68, 0xc2, 0xe1, 0x54, 0x7f, + 0x1c, 0xc8, 0x58, 0x52, 0x28, 0x1d, 0x3a, 0x06, 0x49, 0xf2, 0x97, 0xf9, 0xc6, 0x20, 0x95, 0x39, + 0x41, 0x00, 0xc4, 0x2f, 0x50, 0x16, 0x12, 0x74, 0x98, 0x54, 0xb1, 0x98, 0xda, 0xdc, 0x32, 0x71, + 0xac, 0x2a, 0xde, 0x52, 0x9b, 0x75, 0xa7, 0x7c, 0x45, 0xad, 0x37, 0x31, 0x75, 0xf8, 0xa4, 0x92, + 0xe2, 0xc0, 0xcb, 0x04, 0x86, 0xa6, 0x61, 0x98, 0x8d, 0x2a, 0x4d, 0xaf, 0xe2, 0x5d, 0x1a, 0x3d, + 0xe3, 0x0a, 0x1b, 0x68, 0x0b, 0x04, 0x42, 0x9a, 0x7f, 0xd1, 0x36, 0x74, 0xe1, 0x9a, 0xb4, 0x09, + 0x02, 0xa0, 0xcd, 0x3f, 0x11, 0x0e, 0xdc, 0x27, 0xda, 0xab, 0xd7, 0x32, 0x96, 0xee, 0x87, 0x31, + 0x8a, 0xf1, 0x18, 0xef, 0x7a, 0xb5, 0x9e, 0x19, 0x9f, 0x91, 0x4e, 0x26, 0x94, 0x51, 0x06, 0x5e, + 0xe1, 0x50, 0xf9, 0xcb, 0x11, 0x88, 0xd1, 0xc0, 0x32, 0x06, 0xc3, 0xeb, 0x6f, 0x5b, 0x2d, 0x95, + 0x8b, 0x2b, 0x1b, 0x85, 0xc5, 0x52, 0x5a, 0x42, 0xa3, 0x00, 0x14, 0x70, 0x61, 0x71, 0x25, 0xbf, + 0x9e, 0x8e, 0xb8, 0xe5, 0x85, 0xe5, 0xf5, 0x73, 0x8f, 0xa7, 0xa3, 0x2e, 0xc1, 0x06, 0x03, 0xc4, + 0xfc, 0x08, 0x8f, 0x9d, 0x49, 0xc7, 0x51, 0x1a, 0x52, 0x8c, 0xc1, 0xc2, 0xf3, 0xa5, 0xe2, 0xb9, + 0xc7, 0xd3, 0x83, 0x41, 0xc8, 0x63, 0x67, 0xd2, 0x43, 0x68, 0x04, 0x92, 0x14, 0x52, 0x58, 0x59, + 0x59, 0x4c, 0x27, 0x5c, 0x9e, 0x6b, 0xeb, 0xca, 0xc2, 0xf2, 0x7c, 0x3a, 0xe9, 0xf2, 0x9c, 0x57, + 0x56, 0x36, 0x56, 0xd3, 0xe0, 0x72, 0x58, 0x2a, 0xad, 0xad, 0xe5, 0xe7, 0x4b, 0xe9, 0x61, 0x17, + 0xa3, 0xf0, 0xb6, 0xf5, 0xd2, 0x5a, 0x3a, 0x15, 0x10, 0xeb, 0xb1, 0x33, 0xe9, 0x11, 0xb7, 0x89, + 0xd2, 0xf2, 0xc6, 0x52, 0x7a, 0x14, 0x8d, 0xc3, 0x08, 0x6b, 0x42, 0x08, 0x31, 0x16, 0x02, 0x9d, + 0x7b, 0x3c, 0x9d, 0xf6, 0x04, 0x61, 0x5c, 0xc6, 0x03, 0x80, 0x73, 0x8f, 0xa7, 0x91, 0x3c, 0x07, + 0x71, 0xea, 0x86, 0x08, 0xc1, 0xe8, 0x62, 0xbe, 0x50, 0x5a, 0x2c, 0xaf, 0xac, 0xae, 0x2f, 0xac, + 0x2c, 0xe7, 0x17, 0xd3, 0x92, 0x07, 0x53, 0x4a, 0xcf, 0x6e, 0x2c, 0x28, 0xa5, 0x62, 0x3a, 0xe2, + 0x87, 0xad, 0x96, 0xf2, 0xeb, 0xa5, 0x62, 0x3a, 0x2a, 0x57, 0x60, 0xb2, 0x5d, 0x40, 0x6d, 0x3b, + 0x84, 0x7c, 0xbe, 0x10, 0xe9, 0xe0, 0x0b, 0x94, 0x57, 0xd8, 0x17, 0xe4, 0xef, 0x44, 0x60, 0xa2, + 0xcd, 0xa4, 0xd2, 0xb6, 0x91, 0xa7, 0x21, 0xce, 0x7c, 0x99, 0x4d, 0xb3, 0x0f, 0xb4, 0x9d, 0x9d, + 0xa8, 0x67, 0xb7, 0x4c, 0xb5, 0x94, 0xce, 0x9f, 0x6a, 0x44, 0x3b, 0xa4, 0x1a, 0x84, 0x45, 0x8b, + 0xc3, 0xfe, 0x54, 0x4b, 0xf0, 0x67, 0xf3, 0xe3, 0xb9, 0x7e, 0xe6, 0x47, 0x0a, 0xdb, 0xdf, 0x24, + 0x10, 0x6f, 0x33, 0x09, 0x9c, 0x87, 0xf1, 0x16, 0x46, 0x7d, 0x07, 0xe3, 0xf7, 0x4a, 0x90, 0xe9, + 0x64, 0x9c, 0x1e, 0x21, 0x31, 0x12, 0x08, 0x89, 0xe7, 0xc3, 0x16, 0xbc, 0xab, 0x73, 0x27, 0xb4, + 0xf4, 0xf5, 0x67, 0x25, 0x38, 0xdc, 0x3e, 0xa5, 0x6c, 0x2b, 0xc3, 0x5b, 0x60, 0xb0, 0x81, 0x9d, + 0x6d, 0x43, 0xa4, 0x55, 0xf7, 0xb5, 0x99, 0xac, 0x49, 0x75, 0xb8, 0xb3, 0x39, 0x95, 0x7f, 0xb6, + 0x8f, 0x76, 0xca, 0x0b, 0x99, 0x34, 0x2d, 0x92, 0x7e, 0x30, 0x02, 0x87, 0xda, 0x32, 0x6f, 0x2b, + 0xe8, 0x09, 0x00, 0x4d, 0x37, 0x9b, 0x0e, 0x4b, 0x9d, 0x58, 0x24, 0x4e, 0x52, 0x08, 0x0d, 0x5e, + 0x24, 0xca, 0x36, 0x1d, 0xb7, 0x3e, 0x4a, 0xeb, 0x81, 0x81, 0x28, 0xc2, 0x93, 0x9e, 0xa0, 0x31, + 0x2a, 0xe8, 0x54, 0x07, 0x4d, 0x5b, 0x1c, 0xf3, 0x11, 0x48, 0x57, 0xea, 0x1a, 0xd6, 0x9d, 0xb2, + 0xed, 0x58, 0x58, 0x6d, 0x68, 0x7a, 0x8d, 0x4e, 0x35, 0x89, 0x5c, 0x7c, 0x4b, 0xad, 0xdb, 0x58, + 0x19, 0x63, 0xd5, 0x6b, 0xa2, 0x96, 0x50, 0x50, 0x07, 0xb2, 0x7c, 0x14, 0x83, 0x01, 0x0a, 0x56, + 0xed, 0x52, 0xc8, 0x1f, 0x4e, 0xc2, 0xb0, 0x2f, 0x01, 0x47, 0x77, 0x41, 0xea, 0x45, 0xf5, 0x8a, + 0x5a, 0x16, 0x8b, 0x2a, 0x66, 0x89, 0x61, 0x02, 0x5b, 0xe5, 0x0b, 0xab, 0x47, 0x60, 0x92, 0xa2, + 0x18, 0x4d, 0x07, 0x5b, 0xe5, 0x4a, 0x5d, 0xb5, 0x6d, 0x6a, 0xb4, 0x04, 0x45, 0x45, 0xa4, 0x6e, + 0x85, 0x54, 0xcd, 0x89, 0x1a, 0x74, 0x16, 0x26, 0x28, 0x45, 0xa3, 0x59, 0x77, 0x34, 0xb3, 0x8e, + 0xcb, 0x64, 0x99, 0x67, 0xd3, 0x29, 0xc7, 0x95, 0x6c, 0x9c, 0x60, 0x2c, 0x71, 0x04, 0x22, 0x91, + 0x8d, 0x8a, 0x70, 0x82, 0x92, 0xd5, 0xb0, 0x8e, 0x2d, 0xd5, 0xc1, 0x65, 0xfc, 0x52, 0x53, 0xad, + 0xdb, 0x65, 0x55, 0xaf, 0x96, 0xb7, 0x55, 0x7b, 0x3b, 0x33, 0x49, 0x18, 0x14, 0x22, 0x19, 0x49, + 0x39, 0x4a, 0x10, 0xe7, 0x39, 0x5e, 0x89, 0xa2, 0xe5, 0xf5, 0xea, 0x45, 0xd5, 0xde, 0x46, 0x39, + 0x38, 0x4c, 0xb9, 0xd8, 0x8e, 0xa5, 0xe9, 0xb5, 0x72, 0x65, 0x1b, 0x57, 0x76, 0xca, 0x4d, 0x67, + 0xeb, 0xc9, 0xcc, 0x31, 0x7f, 0xfb, 0x54, 0xc2, 0x35, 0x8a, 0x33, 0x47, 0x50, 0x36, 0x9c, 0xad, + 0x27, 0xd1, 0x1a, 0xa4, 0x48, 0x67, 0x34, 0xb4, 0x6b, 0xb8, 0xbc, 0x65, 0x58, 0x74, 0x0e, 0x1d, + 0x6d, 0x13, 0x9a, 0x7c, 0x16, 0x9c, 0x5d, 0xe1, 0x04, 0x4b, 0x46, 0x15, 0xe7, 0xe2, 0x6b, 0xab, + 0xa5, 0x52, 0x51, 0x19, 0x16, 0x5c, 0x2e, 0x18, 0x16, 0x71, 0xa8, 0x9a, 0xe1, 0x1a, 0x78, 0x98, + 0x39, 0x54, 0xcd, 0x10, 0xe6, 0x3d, 0x0b, 0x13, 0x95, 0x0a, 0xd3, 0x59, 0xab, 0x94, 0xf9, 0x62, + 0xcc, 0xce, 0xa4, 0x03, 0xc6, 0xaa, 0x54, 0xe6, 0x19, 0x02, 0xf7, 0x71, 0x1b, 0x3d, 0x05, 0x87, + 0x3c, 0x63, 0xf9, 0x09, 0xc7, 0x5b, 0xb4, 0x0c, 0x93, 0x9e, 0x85, 0x09, 0x73, 0xaf, 0x95, 0x10, + 0x05, 0x5a, 0x34, 0xf7, 0xc2, 0x64, 0x4f, 0xc0, 0xa4, 0xb9, 0x6d, 0xb6, 0xd2, 0x9d, 0xf2, 0xd3, + 0x21, 0x73, 0xdb, 0x0c, 0x13, 0xde, 0x4b, 0x57, 0xe6, 0x16, 0xae, 0xa8, 0x0e, 0xae, 0x66, 0x8e, + 0xf8, 0xd1, 0x7d, 0x15, 0x68, 0x16, 0xd2, 0x95, 0x4a, 0x19, 0xeb, 0xea, 0x66, 0x1d, 0x97, 0x55, + 0x0b, 0xeb, 0xaa, 0x9d, 0x99, 0xa6, 0xc8, 0x31, 0xc7, 0x6a, 0x62, 0x65, 0xb4, 0x52, 0x29, 0xd1, + 0xca, 0x3c, 0xad, 0x43, 0xa7, 0x60, 0xdc, 0xd8, 0x7c, 0xb1, 0xc2, 0x3c, 0xb2, 0x6c, 0x5a, 0x78, + 0x4b, 0xdb, 0xcd, 0xdc, 0x43, 0xcd, 0x3b, 0x46, 0x2a, 0xa8, 0x3f, 0xae, 0x52, 0x30, 0x7a, 0x00, + 0xd2, 0x15, 0x7b, 0x5b, 0xb5, 0x4c, 0x1a, 0x92, 0x6d, 0x53, 0xad, 0xe0, 0xcc, 0xbd, 0x0c, 0x95, + 0xc1, 0x97, 0x05, 0x98, 0x8c, 0x08, 0xfb, 0xaa, 0xb6, 0xe5, 0x08, 0x8e, 0xf7, 0xb3, 0x11, 0x41, + 0x61, 0x9c, 0xdb, 0x49, 0x48, 0x13, 0x4b, 0x04, 0x1a, 0x3e, 0x49, 0xd1, 0x46, 0xcd, 0x6d, 0xd3, + 0xdf, 0xee, 0xdd, 0x30, 0x42, 0x30, 0xbd, 0x46, 0x1f, 0x60, 0x89, 0x9b, 0xb9, 0xed, 0x6b, 0xf1, + 0x71, 0x38, 0x4c, 0x90, 0x1a, 0xd8, 0x51, 0xab, 0xaa, 0xa3, 0xfa, 0xb0, 0x1f, 0xa2, 0xd8, 0xc4, + 0xec, 0x4b, 0xbc, 0x32, 0x20, 0xa7, 0xd5, 0xdc, 0xdc, 0x73, 0x1d, 0xeb, 0x61, 0x26, 0x27, 0x81, + 0x09, 0xd7, 0xba, 0x63, 0xc9, 0xb9, 0x9c, 0x83, 0x94, 0xdf, 0xef, 0x51, 0x12, 0x98, 0xe7, 0xa7, + 0x25, 0x92, 0x04, 0xcd, 0xad, 0x14, 0x49, 0xfa, 0xf2, 0x42, 0x29, 0x1d, 0x21, 0x69, 0xd4, 0xe2, + 0xc2, 0x7a, 0xa9, 0xac, 0x6c, 0x2c, 0xaf, 0x2f, 0x2c, 0x95, 0xd2, 0x51, 0x5f, 0x62, 0xff, 0x4c, + 0x2c, 0x71, 0x5f, 0xfa, 0x7e, 0xf9, 0x5b, 0x11, 0x18, 0x0d, 0xae, 0xd4, 0xd0, 0x9b, 0xe0, 0x88, + 0xd8, 0x56, 0xb1, 0xb1, 0x53, 0xbe, 0xaa, 0x59, 0x74, 0x40, 0x36, 0x54, 0x36, 0x39, 0xba, 0xfe, + 0x33, 0xc9, 0xb1, 0xd6, 0xb0, 0xf3, 0x9c, 0x66, 0x91, 0xe1, 0xd6, 0x50, 0x1d, 0xb4, 0x08, 0xd3, + 0xba, 0x51, 0xb6, 0x1d, 0x55, 0xaf, 0xaa, 0x56, 0xb5, 0xec, 0x6d, 0x68, 0x95, 0xd5, 0x4a, 0x05, + 0xdb, 0xb6, 0xc1, 0x26, 0x42, 0x97, 0xcb, 0x71, 0xdd, 0x58, 0xe3, 0xc8, 0xde, 0x0c, 0x91, 0xe7, + 0xa8, 0x21, 0xf7, 0x8d, 0x76, 0x72, 0xdf, 0x63, 0x90, 0x6c, 0xa8, 0x66, 0x19, 0xeb, 0x8e, 0xb5, + 0x47, 0xf3, 0xf3, 0x84, 0x92, 0x68, 0xa8, 0x66, 0x89, 0x94, 0x7f, 0x2c, 0xcb, 0xa4, 0x67, 0x62, + 0x89, 0x44, 0x3a, 0xf9, 0x4c, 0x2c, 0x91, 0x4c, 0x83, 0xfc, 0x6a, 0x14, 0x52, 0xfe, 0x7c, 0x9d, + 0x2c, 0x7f, 0x2a, 0x74, 0xc6, 0x92, 0x68, 0x4c, 0xbb, 0xbb, 0x6b, 0x76, 0x3f, 0x3b, 0x47, 0xa6, + 0xb2, 0xdc, 0x20, 0x4b, 0x8e, 0x15, 0x46, 0x49, 0xd2, 0x08, 0xe2, 0x6c, 0x98, 0x25, 0x23, 0x09, + 0x85, 0x97, 0xd0, 0x3c, 0x0c, 0xbe, 0x68, 0x53, 0xde, 0x83, 0x94, 0xf7, 0x3d, 0xdd, 0x79, 0x3f, + 0xb3, 0x46, 0x99, 0x27, 0x9f, 0x59, 0x2b, 0x2f, 0xaf, 0x28, 0x4b, 0xf9, 0x45, 0x85, 0x93, 0xa3, + 0xa3, 0x10, 0xab, 0xab, 0xd7, 0xf6, 0x82, 0x93, 0x1e, 0x05, 0xf5, 0xdb, 0x09, 0x47, 0x21, 0x76, + 0x15, 0xab, 0x3b, 0xc1, 0xa9, 0x86, 0x82, 0xee, 0xe0, 0x60, 0x38, 0x0d, 0x71, 0x6a, 0x2f, 0x04, + 0xc0, 0x2d, 0x96, 0x1e, 0x40, 0x09, 0x88, 0xcd, 0xad, 0x28, 0x64, 0x40, 0xa4, 0x21, 0xc5, 0xa0, + 0xe5, 0xd5, 0x85, 0xd2, 0x5c, 0x29, 0x1d, 0x91, 0xcf, 0xc2, 0x20, 0x33, 0x02, 0x19, 0x2c, 0xae, + 0x19, 0xd2, 0x03, 0xbc, 0xc8, 0x79, 0x48, 0xa2, 0x76, 0x63, 0xa9, 0x50, 0x52, 0xd2, 0x91, 0x60, + 0x57, 0xc7, 0xd2, 0x71, 0xd9, 0x86, 0x94, 0x3f, 0x0f, 0xff, 0xf1, 0x2c, 0xc6, 0xbf, 0x22, 0xc1, + 0xb0, 0x2f, 0xaf, 0x26, 0x09, 0x91, 0x5a, 0xaf, 0x1b, 0x57, 0xcb, 0x6a, 0x5d, 0x53, 0x6d, 0xee, + 0x1a, 0x40, 0x41, 0x79, 0x02, 0xe9, 0xb7, 0xeb, 0x7e, 0x4c, 0x43, 0x24, 0x9e, 0x1e, 0x94, 0x3f, + 0x29, 0x41, 0x3a, 0x9c, 0xd8, 0x86, 0xc4, 0x94, 0xde, 0x48, 0x31, 0xe5, 0x4f, 0x48, 0x30, 0x1a, + 0xcc, 0x66, 0x43, 0xe2, 0xdd, 0xf5, 0x86, 0x8a, 0xf7, 0xfb, 0x11, 0x18, 0x09, 0xe4, 0xb0, 0xfd, 0x4a, 0xf7, 0x12, 0x8c, 0x6b, 0x55, 0xdc, 0x30, 0x0d, 0x07, 0xeb, 0x95, 0xbd, 0x72, 0x1d, 0x5f, - 0xc5, 0xf5, 0x8c, 0x4c, 0x83, 0xc6, 0x99, 0xee, 0x59, 0xf2, 0xec, 0x82, 0x47, 0xb7, 0x48, 0xc8, - 0x72, 0x13, 0x0b, 0xc5, 0xd2, 0xd2, 0xea, 0xca, 0x7a, 0x69, 0x79, 0xee, 0xad, 0xe5, 0x8d, 0xe5, - 0xcb, 0xcb, 0x2b, 0xcf, 0x2d, 0x2b, 0x69, 0x2d, 0x84, 0x76, 0x07, 0xdd, 0x7e, 0x15, 0xd2, 0x61, - 0xa1, 0xd0, 0x11, 0x68, 0x27, 0x56, 0x7a, 0x00, 0x4d, 0xc0, 0xd8, 0xf2, 0x4a, 0x79, 0x6d, 0xa1, - 0x58, 0x2a, 0x97, 0x2e, 0x5e, 0x2c, 0xcd, 0xad, 0xaf, 0xb1, 0x7d, 0x0f, 0x17, 0x7b, 0x3d, 0xe0, - 0xe0, 0xf2, 0xab, 0x51, 0x98, 0x68, 0x23, 0x09, 0xca, 0xf3, 0x15, 0x0b, 0x5b, 0x44, 0x9d, 0xee, - 0x47, 0xfa, 0x59, 0x92, 0x33, 0xac, 0xaa, 0x96, 0xc3, 0x17, 0x38, 0x0f, 0x00, 0xd1, 0x92, 0xee, - 0x68, 0x5b, 0x1a, 0xb6, 0xf8, 0x7e, 0x12, 0x5b, 0xc6, 0x8c, 0x79, 0x70, 0xb6, 0xa5, 0xf4, 0x10, - 0x20, 0xd3, 0xb0, 0x35, 0x47, 0xbb, 0x8a, 0xcb, 0x9a, 0x2e, 0x36, 0x9f, 0xc8, 0xb2, 0x26, 0xa6, - 0xa4, 0x45, 0xcd, 0x82, 0xee, 0xb8, 0xd8, 0x3a, 0xae, 0xa9, 0x21, 0x6c, 0x12, 0xcc, 0xa3, 0x4a, - 0x5a, 0xd4, 0xb8, 0xd8, 0x77, 0x41, 0xaa, 0x6a, 0x34, 0x49, 0xae, 0xc7, 0xf0, 0xc8, 0xdc, 0x21, - 0x29, 0xc3, 0x0c, 0xe6, 0xa2, 0xf0, 0x2c, 0xde, 0xdb, 0xf5, 0x4a, 0x29, 0xc3, 0x0c, 0xc6, 0x50, - 0xee, 0x87, 0x31, 0xb5, 0x56, 0xb3, 0x08, 0x73, 0xc1, 0x88, 0xad, 0x4b, 0x46, 0x5d, 0x30, 0x45, - 0xcc, 0x3e, 0x03, 0x09, 0xa1, 0x07, 0x32, 0x55, 0x13, 0x4d, 0x94, 0x4d, 0xb6, 0xd8, 0x8e, 0x9c, - 0x4c, 0x2a, 0x09, 0x5d, 0x54, 0xde, 0x05, 0x29, 0xcd, 0x2e, 0x7b, 0x9b, 0xf8, 0x91, 0x99, 0xc8, - 0xc9, 0x84, 0x32, 0xac, 0xd9, 0xee, 0x06, 0xa8, 0xfc, 0x99, 0x08, 0x8c, 0x06, 0x0f, 0x21, 0x50, - 0x11, 0x12, 0x75, 0xa3, 0xa2, 0x52, 0xd3, 0x62, 0x27, 0x60, 0x27, 0x7b, 0x9c, 0x5b, 0xcc, 0x2e, - 0x72, 0x7c, 0xc5, 0xa5, 0xcc, 0xfe, 0xb6, 0x04, 0x09, 0x01, 0x46, 0x87, 0x21, 0x66, 0xaa, 0xce, - 0x36, 0x65, 0x17, 0x2f, 0x44, 0xd2, 0x92, 0x42, 0xcb, 0x04, 0x6e, 0x9b, 0xaa, 0x4e, 0x4d, 0x80, - 0xc3, 0x49, 0x99, 0x8c, 0x6b, 0x1d, 0xab, 0x55, 0xba, 0xe8, 0x31, 0x1a, 0x0d, 0xac, 0x3b, 0xb6, - 0x18, 0x57, 0x0e, 0x9f, 0xe3, 0x60, 0xf4, 0x20, 0x8c, 0x3b, 0x96, 0xaa, 0xd5, 0x03, 0xb8, 0x31, - 0x8a, 0x9b, 0x16, 0x15, 0x2e, 0x72, 0x0e, 0x8e, 0x0a, 0xbe, 0x55, 0xec, 0xa8, 0x95, 0x6d, 0x5c, - 0xf5, 0x88, 0x06, 0xe9, 0xe6, 0xc6, 0x11, 0x8e, 0x50, 0xe4, 0xf5, 0x82, 0x56, 0xfe, 0x86, 0x04, - 0xe3, 0x62, 0x99, 0x56, 0x75, 0x95, 0xb5, 0x04, 0xa0, 0xea, 0xba, 0xe1, 0xf8, 0xd5, 0xd5, 0x6a, - 0xca, 0x2d, 0x74, 0xb3, 0x79, 0x97, 0x48, 0xf1, 0x31, 0xc8, 0x36, 0x00, 0xbc, 0x9a, 0x8e, 0x6a, - 0x9b, 0x86, 0x61, 0x7e, 0xc2, 0x44, 0x8f, 0x29, 0xd9, 0xc2, 0x1e, 0x18, 0x88, 0xac, 0xe7, 0xd0, - 0x24, 0xc4, 0x37, 0x71, 0x4d, 0xd3, 0xf9, 0xbe, 0x31, 0x2b, 0x88, 0xed, 0x97, 0x98, 0xbb, 0xfd, - 0x52, 0xf8, 0xa0, 0x04, 0x13, 0x15, 0xa3, 0x11, 0x96, 0xb7, 0x90, 0x0e, 0xed, 0x2e, 0xd8, 0x97, - 0xa4, 0x17, 0x9e, 0xaa, 0x69, 0xce, 0x76, 0x73, 0x73, 0xb6, 0x62, 0x34, 0xce, 0xd4, 0x8c, 0xba, - 0xaa, 0xd7, 0xbc, 0x73, 0x56, 0xfa, 0xa3, 0x72, 0xba, 0x86, 0xf5, 0xd3, 0x35, 0xc3, 0x77, 0xea, - 0x7a, 0xc1, 0xfb, 0xf9, 0xa7, 0x92, 0xf4, 0xf3, 0x91, 0xe8, 0xfc, 0x6a, 0xe1, 0xb3, 0x91, 0xec, - 0x3c, 0x6b, 0x6e, 0x55, 0xa8, 0x47, 0xc1, 0x5b, 0x75, 0x5c, 0x21, 0x5d, 0x86, 0xef, 0x3c, 0x08, - 0x93, 0x35, 0xa3, 0x66, 0x50, 0x8e, 0x67, 0xc8, 0x2f, 0x7e, 0x72, 0x9b, 0x74, 0xa1, 0xd9, 0x9e, - 0xc7, 0xbc, 0xb9, 0x65, 0x98, 0xe0, 0xc8, 0x65, 0x7a, 0x74, 0xc4, 0x16, 0x36, 0xa8, 0xeb, 0xae, - 0x5a, 0xe6, 0x57, 0xbf, 0x4d, 0x27, 0x74, 0x65, 0x9c, 0x93, 0x92, 0x3a, 0xb6, 0xf6, 0xc9, 0x29, - 0x70, 0x28, 0xc0, 0x8f, 0xb9, 0x2d, 0xb6, 0x7a, 0x70, 0xfc, 0x0d, 0xce, 0x71, 0xc2, 0xc7, 0x71, - 0x8d, 0x93, 0xe6, 0xe6, 0x60, 0x64, 0x3f, 0xbc, 0xfe, 0x25, 0xe7, 0x95, 0xc2, 0x7e, 0x26, 0xf3, - 0x30, 0x46, 0x99, 0x54, 0x9a, 0xb6, 0x63, 0x34, 0x68, 0x4c, 0xec, 0xce, 0xe6, 0x37, 0xbf, 0xcd, - 0xfc, 0x68, 0x94, 0x90, 0xcd, 0xb9, 0x54, 0xb9, 0x1c, 0xd0, 0xd3, 0xb2, 0x2a, 0xae, 0xd4, 0x7b, - 0x70, 0xf8, 0x0a, 0x17, 0xc4, 0xc5, 0xcf, 0x5d, 0x81, 0x49, 0xf2, 0x9b, 0x86, 0x2c, 0xbf, 0x24, - 0xbd, 0xb7, 0xe0, 0x32, 0xdf, 0x78, 0x0f, 0x73, 0xd5, 0x09, 0x97, 0x81, 0x4f, 0x26, 0xdf, 0x28, - 0xd6, 0xb0, 0xe3, 0x60, 0xcb, 0x2e, 0xab, 0xf5, 0x76, 0xe2, 0xf9, 0xf6, 0x30, 0x32, 0x1f, 0xfb, - 0x6e, 0x70, 0x14, 0xe7, 0x19, 0x65, 0xbe, 0x5e, 0xcf, 0x6d, 0xc0, 0x91, 0x36, 0x56, 0xd1, 0x07, - 0xcf, 0x57, 0x39, 0xcf, 0xc9, 0x16, 0xcb, 0x20, 0x6c, 0x57, 0x41, 0xc0, 0xdd, 0xb1, 0xec, 0x83, - 0xe7, 0xcf, 0x71, 0x9e, 0x88, 0xd3, 0x8a, 0x21, 0x25, 0x1c, 0x9f, 0x81, 0xf1, 0xab, 0xd8, 0xda, - 0x34, 0x6c, 0xbe, 0x6f, 0xd4, 0x07, 0xbb, 0x8f, 0x73, 0x76, 0x63, 0x9c, 0x90, 0x6e, 0x24, 0x11, - 0x5e, 0x4f, 0x42, 0x62, 0x4b, 0xad, 0xe0, 0x3e, 0x58, 0xdc, 0xe0, 0x2c, 0x86, 0x08, 0x3e, 0x21, - 0xcd, 0x43, 0xaa, 0x66, 0xf0, 0x59, 0xab, 0x37, 0xf9, 0x27, 0x38, 0xf9, 0xb0, 0xa0, 0xe1, 0x2c, - 0x4c, 0xc3, 0x6c, 0xd6, 0xc9, 0x94, 0xd6, 0x9b, 0xc5, 0xdf, 0x14, 0x2c, 0x04, 0x0d, 0x67, 0xb1, - 0x0f, 0xb5, 0x7e, 0x52, 0xb0, 0xb0, 0x7d, 0xfa, 0x7c, 0x1a, 0x86, 0x0d, 0xbd, 0xbe, 0x67, 0xe8, - 0xfd, 0x08, 0xf1, 0x29, 0xce, 0x01, 0x38, 0x09, 0x61, 0x70, 0x01, 0x92, 0xfd, 0x0e, 0xc4, 0xdf, - 0xfa, 0xae, 0x70, 0x0f, 0x31, 0x02, 0xf3, 0x30, 0x26, 0x02, 0x94, 0x66, 0xe8, 0x7d, 0xb0, 0xf8, - 0xdb, 0x9c, 0xc5, 0xa8, 0x8f, 0x8c, 0x77, 0xc3, 0xc1, 0xb6, 0x53, 0xc3, 0xfd, 0x30, 0xf9, 0x8c, - 0xe8, 0x06, 0x27, 0xe1, 0xaa, 0xdc, 0xc4, 0x7a, 0x65, 0xbb, 0x3f, 0x0e, 0xbf, 0x28, 0x54, 0x29, - 0x68, 0x08, 0x8b, 0x39, 0x18, 0x69, 0xa8, 0x96, 0xbd, 0xad, 0xd6, 0xfb, 0x1a, 0x8e, 0xbf, 0xc3, - 0x79, 0xa4, 0x5c, 0x22, 0xae, 0x91, 0xa6, 0xbe, 0x1f, 0x36, 0x9f, 0x15, 0x1a, 0xf1, 0x91, 0x71, - 0xd7, 0xb3, 0x1d, 0xba, 0xc9, 0xb6, 0x1f, 0x6e, 0xbf, 0x24, 0x5c, 0x8f, 0xd1, 0x2e, 0xf9, 0x39, - 0x5e, 0x80, 0xa4, 0xad, 0xbd, 0xdc, 0x17, 0x9b, 0xcf, 0x89, 0x91, 0xa6, 0x04, 0x84, 0xf8, 0xad, - 0x70, 0xb4, 0xed, 0x34, 0xd1, 0x07, 0xb3, 0xbf, 0xcb, 0x99, 0x1d, 0x6e, 0x33, 0x55, 0xf0, 0x90, - 0xb0, 0x5f, 0x96, 0x7f, 0x4f, 0x84, 0x04, 0x1c, 0xe2, 0xb5, 0x4a, 0xd6, 0x11, 0xb6, 0xba, 0xb5, - 0x3f, 0xad, 0xfd, 0xb2, 0xd0, 0x1a, 0xa3, 0x0d, 0x68, 0x6d, 0x1d, 0x0e, 0x73, 0x8e, 0xfb, 0x1b, - 0xd7, 0x5f, 0x11, 0x81, 0x95, 0x51, 0x6f, 0x04, 0x47, 0xf7, 0x6d, 0x90, 0x75, 0xd5, 0x29, 0x12, - 0x56, 0xbb, 0xdc, 0x50, 0xcd, 0x3e, 0x38, 0xff, 0x2a, 0xe7, 0x2c, 0x22, 0xbe, 0x9b, 0xf1, 0xda, - 0x4b, 0xaa, 0x49, 0x98, 0x3f, 0x0f, 0x19, 0xc1, 0xbc, 0xa9, 0x5b, 0xb8, 0x62, 0xd4, 0x74, 0xed, - 0x65, 0x5c, 0xed, 0x83, 0xf5, 0xaf, 0x85, 0x86, 0x6a, 0xc3, 0x47, 0x4e, 0x38, 0x2f, 0x40, 0xda, - 0xcd, 0x55, 0xca, 0x5a, 0xc3, 0x34, 0x2c, 0xa7, 0x07, 0xc7, 0xcf, 0x8b, 0x91, 0x72, 0xe9, 0x16, - 0x28, 0x59, 0xae, 0x04, 0xec, 0xe4, 0xb9, 0x5f, 0x93, 0xfc, 0x02, 0x67, 0x34, 0xe2, 0x51, 0xf1, - 0xc0, 0x51, 0x31, 0x1a, 0xa6, 0x6a, 0xf5, 0x13, 0xff, 0xfe, 0xbe, 0x08, 0x1c, 0x9c, 0x84, 0x07, - 0x0e, 0x67, 0xcf, 0xc4, 0x64, 0xb6, 0xef, 0x83, 0xc3, 0x17, 0x45, 0xe0, 0x10, 0x34, 0x9c, 0x85, - 0x48, 0x18, 0xfa, 0x60, 0xf1, 0x0f, 0x04, 0x0b, 0x41, 0x43, 0x58, 0x3c, 0xeb, 0x4d, 0xb4, 0x16, - 0xae, 0x69, 0xb6, 0x63, 0xb1, 0x34, 0xb9, 0x3b, 0xab, 0x7f, 0xf8, 0xdd, 0x60, 0x12, 0xa6, 0xf8, - 0x48, 0x49, 0x24, 0xe2, 0xdb, 0xae, 0x74, 0x15, 0xd5, 0x5b, 0xb0, 0x5f, 0x17, 0x91, 0xc8, 0x47, - 0x46, 0x64, 0xf3, 0x65, 0x88, 0x44, 0xed, 0x15, 0xb2, 0x76, 0xe8, 0x83, 0xdd, 0x3f, 0x0a, 0x09, - 0xb7, 0x26, 0x68, 0x09, 0x4f, 0x5f, 0xfe, 0xd3, 0xd4, 0x77, 0xf0, 0x5e, 0x5f, 0xd6, 0xf9, 0x8f, - 0x43, 0xf9, 0xcf, 0x06, 0xa3, 0x64, 0x31, 0x64, 0x2c, 0x94, 0x4f, 0xa1, 0x5e, 0xf7, 0x8c, 0x32, - 0x3f, 0xf9, 0x7d, 0xde, 0xdf, 0x60, 0x3a, 0x95, 0x5b, 0x24, 0x46, 0x1e, 0x4c, 0x7a, 0x7a, 0x33, - 0x7b, 0xcf, 0xf7, 0x5d, 0x3b, 0x0f, 0xe4, 0x3c, 0xb9, 0x8b, 0x30, 0x12, 0x48, 0x78, 0x7a, 0xb3, - 0x7a, 0x2f, 0x67, 0x95, 0xf2, 0xe7, 0x3b, 0xb9, 0x73, 0x10, 0x23, 0xc9, 0x4b, 0x6f, 0xf2, 0xbf, - 0xcc, 0xc9, 0x29, 0x7a, 0xee, 0xcd, 0x90, 0x10, 0x49, 0x4b, 0x6f, 0xd2, 0xf7, 0x71, 0x52, 0x97, - 0x84, 0x90, 0x8b, 0x84, 0xa5, 0x37, 0xf9, 0x5f, 0x11, 0xe4, 0x82, 0x84, 0x90, 0xf7, 0xaf, 0xc2, - 0x2f, 0xfd, 0x54, 0x8c, 0x4f, 0x3a, 0x42, 0x77, 0x17, 0x60, 0x88, 0x67, 0x2a, 0xbd, 0xa9, 0x3f, - 0xc0, 0x1b, 0x17, 0x14, 0xb9, 0xc7, 0x21, 0xde, 0xa7, 0xc2, 0x7f, 0x9a, 0x93, 0x32, 0xfc, 0xdc, - 0x1c, 0x0c, 0xfb, 0xb2, 0x93, 0xde, 0xe4, 0x7f, 0x8d, 0x93, 0xfb, 0xa9, 0x88, 0xe8, 0x3c, 0x3b, - 0xe9, 0xcd, 0xe0, 0x83, 0x42, 0x74, 0x4e, 0x41, 0xd4, 0x26, 0x12, 0x93, 0xde, 0xd4, 0x1f, 0x12, - 0x5a, 0x17, 0x24, 0xb9, 0xa7, 0x21, 0xe9, 0x4e, 0x36, 0xbd, 0xe9, 0x3f, 0xcc, 0xe9, 0x3d, 0x1a, - 0xa2, 0x01, 0xdf, 0x64, 0xd7, 0x9b, 0xc5, 0x5f, 0x17, 0x1a, 0xf0, 0x51, 0x11, 0x37, 0x0a, 0x27, - 0x30, 0xbd, 0x39, 0x7d, 0x44, 0xb8, 0x51, 0x28, 0x7f, 0x21, 0xa3, 0x49, 0x63, 0x7e, 0x6f, 0x16, - 0x3f, 0x23, 0x46, 0x93, 0xe2, 0x13, 0x31, 0xc2, 0x19, 0x41, 0x6f, 0x1e, 0x7f, 0x43, 0x88, 0x11, - 0x4a, 0x08, 0x72, 0xab, 0x80, 0x5a, 0xb3, 0x81, 0xde, 0xfc, 0x3e, 0xca, 0xf9, 0x8d, 0xb7, 0x24, - 0x03, 0xb9, 0xe7, 0xe0, 0x70, 0xfb, 0x4c, 0xa0, 0x37, 0xd7, 0x8f, 0x7d, 0x3f, 0xb4, 0x76, 0xf3, - 0x27, 0x02, 0xb9, 0x75, 0x6f, 0x4a, 0xf1, 0x67, 0x01, 0xbd, 0xd9, 0xbe, 0xfa, 0xfd, 0x60, 0xe0, - 0xf6, 0x27, 0x01, 0xb9, 0x3c, 0x80, 0x37, 0x01, 0xf7, 0xe6, 0xf5, 0x71, 0xce, 0xcb, 0x47, 0x44, - 0x5c, 0x83, 0xcf, 0xbf, 0xbd, 0xe9, 0x6f, 0x08, 0xd7, 0xe0, 0x14, 0xc4, 0x35, 0xc4, 0xd4, 0xdb, - 0x9b, 0xfa, 0x13, 0xc2, 0x35, 0x04, 0x09, 0xb1, 0x6c, 0xdf, 0xec, 0xd6, 0x9b, 0xc3, 0xa7, 0x84, - 0x65, 0xfb, 0xa8, 0x72, 0xcb, 0x30, 0xde, 0x32, 0x21, 0xf6, 0x66, 0xf5, 0xf3, 0x9c, 0x55, 0x3a, - 0x3c, 0x1f, 0xfa, 0x27, 0x2f, 0x3e, 0x19, 0xf6, 0xe6, 0xf6, 0xe9, 0xd0, 0xe4, 0xc5, 0xe7, 0xc2, - 0xdc, 0x05, 0x48, 0xe8, 0xcd, 0x7a, 0x9d, 0x38, 0x0f, 0xea, 0x7e, 0x37, 0x30, 0xf3, 0x5f, 0x7f, - 0xc0, 0xb5, 0x23, 0x08, 0x72, 0xe7, 0x20, 0x8e, 0x1b, 0x9b, 0xb8, 0xda, 0x8b, 0xf2, 0x3b, 0x3f, - 0x10, 0x01, 0x93, 0x60, 0xe7, 0x9e, 0x06, 0x60, 0x5b, 0x23, 0xf4, 0x78, 0xb0, 0x07, 0xed, 0x7f, - 0xfb, 0x01, 0xbf, 0x8c, 0xe3, 0x91, 0x78, 0x0c, 0xd8, 0xd5, 0x9e, 0xee, 0x0c, 0xbe, 0x1b, 0x64, - 0x40, 0x47, 0xe4, 0x49, 0x18, 0x7a, 0xd1, 0x36, 0x74, 0x47, 0xad, 0xf5, 0xa2, 0xfe, 0xef, 0x9c, - 0x5a, 0xe0, 0x13, 0x85, 0x35, 0x0c, 0x0b, 0x3b, 0x6a, 0xcd, 0xee, 0x45, 0xfb, 0x3f, 0x38, 0xad, - 0x4b, 0x40, 0x88, 0x2b, 0xaa, 0xed, 0xf4, 0xd3, 0xef, 0x3f, 0x14, 0xc4, 0x82, 0x80, 0x08, 0x4d, - 0x7e, 0xef, 0xe0, 0xbd, 0x5e, 0xb4, 0xdf, 0x13, 0x42, 0x73, 0xfc, 0xdc, 0x9b, 0x21, 0x49, 0x7e, - 0xb2, 0x1b, 0x76, 0x3d, 0x88, 0xff, 0x88, 0x13, 0x7b, 0x14, 0xa4, 0x65, 0xdb, 0xa9, 0x3a, 0x5a, - 0x6f, 0x65, 0xdf, 0xe2, 0x23, 0x2d, 0xf0, 0x73, 0x79, 0x18, 0xb6, 0x9d, 0x6a, 0xb5, 0xc9, 0xf3, - 0xd3, 0x1e, 0xe4, 0x7f, 0xfc, 0x03, 0x77, 0xcb, 0xc2, 0xa5, 0x21, 0xa3, 0x7d, 0x6d, 0xc7, 0x31, - 0x0d, 0x7a, 0x04, 0xd2, 0x8b, 0xc3, 0xf7, 0x39, 0x07, 0x1f, 0x49, 0x6e, 0x0e, 0x52, 0xa4, 0x2f, - 0x16, 0x36, 0x31, 0x3d, 0xaf, 0xea, 0xc1, 0xe2, 0x4f, 0xb8, 0x02, 0x02, 0x44, 0x85, 0x9f, 0xf8, - 0xca, 0x6b, 0x53, 0xd2, 0xd7, 0x5f, 0x9b, 0x92, 0x7e, 0xff, 0xb5, 0x29, 0xe9, 0x43, 0xdf, 0x9a, - 0x1a, 0xf8, 0xfa, 0xb7, 0xa6, 0x06, 0x7e, 0xf7, 0x5b, 0x53, 0x03, 0xed, 0xb7, 0x8d, 0x61, 0xde, - 0x98, 0x37, 0xd8, 0x86, 0xf1, 0x0b, 0x72, 0x60, 0xbb, 0xb8, 0x66, 0x78, 0xbb, 0xb5, 0xee, 0x22, - 0x07, 0xde, 0x1d, 0x85, 0xa3, 0x15, 0xc3, 0x6e, 0x18, 0x76, 0x99, 0xed, 0xf7, 0xb2, 0x02, 0xdf, - 0xf1, 0x4d, 0xf9, 0xab, 0xfa, 0xd8, 0xf4, 0xbd, 0x04, 0xa3, 0xb4, 0xeb, 0x74, 0xbb, 0x8b, 0x5a, - 0x5b, 0xcf, 0x00, 0xf1, 0xd5, 0x7f, 0x17, 0xa7, 0xbd, 0x1e, 0x71, 0x09, 0xe9, 0x79, 0xfe, 0x3a, - 0x4c, 0x6a, 0x0d, 0xb3, 0x8e, 0xe9, 0xc6, 0x7f, 0xd9, 0xad, 0xeb, 0xcd, 0xef, 0x6b, 0x9c, 0xdf, - 0x84, 0x47, 0xbe, 0x20, 0xa8, 0x73, 0x8b, 0x30, 0xae, 0x56, 0x2a, 0xd8, 0x0c, 0xb0, 0xec, 0x31, - 0x2c, 0x42, 0xc0, 0x34, 0xa7, 0x74, 0xb9, 0x15, 0x9e, 0xee, 0x34, 0x34, 0x2f, 0xdc, 0xeb, 0xd3, - 0xbc, 0x85, 0x6b, 0x58, 0x3f, 0xad, 0x63, 0xe7, 0x9a, 0x61, 0xed, 0x70, 0xf5, 0x9e, 0x66, 0x4d, - 0x0d, 0xb2, 0x3b, 0xcd, 0xf0, 0xde, 0x28, 0x4c, 0xb1, 0x8a, 0x33, 0x9b, 0xaa, 0x8d, 0xcf, 0x5c, - 0x7d, 0x64, 0x13, 0x3b, 0xea, 0x23, 0x67, 0x2a, 0x86, 0xa6, 0xf3, 0x91, 0x98, 0xe0, 0xe3, 0x42, - 0xea, 0x67, 0x79, 0x7d, 0xb6, 0xed, 0x36, 0xbd, 0x3c, 0x0f, 0xb1, 0x39, 0x43, 0xd3, 0xd1, 0x24, - 0xc4, 0xab, 0x58, 0x37, 0x1a, 0xfc, 0x16, 0x1e, 0x2b, 0xa0, 0xbb, 0x61, 0x50, 0x6d, 0x18, 0x4d, - 0xdd, 0x61, 0x67, 0x16, 0x85, 0xe1, 0xaf, 0xdc, 0x9c, 0x1e, 0xf8, 0xbd, 0x9b, 0xd3, 0xd1, 0x05, - 0xdd, 0x51, 0x78, 0x55, 0x2e, 0xf6, 0xfa, 0x27, 0xa7, 0x25, 0xf9, 0x19, 0x18, 0x2a, 0xe2, 0xca, - 0x41, 0x78, 0x15, 0x71, 0x25, 0xc4, 0xeb, 0x01, 0x48, 0x2c, 0xe8, 0x0e, 0xbb, 0x27, 0x79, 0x02, - 0xa2, 0x9a, 0xce, 0xae, 0xde, 0x84, 0xda, 0x27, 0x70, 0x82, 0x5a, 0xc4, 0x15, 0x17, 0xb5, 0x8a, - 0x2b, 0x61, 0x54, 0xc2, 0x9e, 0xc0, 0x0b, 0xc5, 0xdf, 0xfd, 0xcf, 0x53, 0x03, 0xaf, 0xbc, 0x36, - 0x35, 0xd0, 0x71, 0x24, 0xfc, 0x3e, 0xc0, 0x55, 0xcc, 0x87, 0xc0, 0xae, 0xee, 0x9c, 0x21, 0x26, - 0x6a, 0xbb, 0xc3, 0xf0, 0x5b, 0x83, 0x20, 0x73, 0x1c, 0xdb, 0x51, 0x77, 0x34, 0xbd, 0xe6, 0x8e, - 0x84, 0xda, 0x74, 0xb6, 0x5f, 0xe6, 0x43, 0x71, 0x98, 0x0f, 0x05, 0xc7, 0xe9, 0x3e, 0x1a, 0xd9, - 0xce, 0xde, 0x95, 0xed, 0x31, 0xe6, 0xf2, 0xbf, 0x8e, 0x02, 0x5a, 0x73, 0xd4, 0x1d, 0x9c, 0x6f, - 0x3a, 0xdb, 0x86, 0xa5, 0xbd, 0xcc, 0x62, 0x19, 0x06, 0x68, 0xa8, 0xbb, 0x65, 0xc7, 0xd8, 0xc1, - 0xba, 0x4d, 0x55, 0x33, 0x7c, 0xf6, 0xe8, 0x6c, 0x1b, 0xfb, 0x98, 0x25, 0x43, 0x57, 0x78, 0xf0, - 0xb3, 0xdf, 0x9c, 0xbe, 0xbf, 0xb7, 0x16, 0x28, 0x32, 0x49, 0xae, 0x77, 0xd7, 0x29, 0x63, 0x74, - 0x05, 0xd8, 0xb5, 0x8b, 0x72, 0x5d, 0xb3, 0x1d, 0x7e, 0x73, 0xfb, 0xdc, 0x6c, 0xfb, 0xbe, 0xcf, - 0xb6, 0x8a, 0x39, 0x7b, 0x45, 0xad, 0x6b, 0x55, 0xd5, 0x31, 0x2c, 0xfb, 0xd2, 0x80, 0x92, 0xa4, - 0xac, 0x16, 0x35, 0xdb, 0x41, 0xeb, 0x90, 0xac, 0x62, 0x7d, 0x8f, 0xb1, 0x8d, 0xbe, 0x31, 0xb6, - 0x09, 0xc2, 0x89, 0x72, 0x7d, 0x1e, 0x90, 0xea, 0xc7, 0x13, 0x4f, 0x95, 0xd8, 0x8d, 0xcb, 0x0e, - 0xec, 0x03, 0x9c, 0xe9, 0xcb, 0x8a, 0x71, 0x35, 0x0c, 0xca, 0xde, 0x07, 0xe0, 0xb5, 0x89, 0x32, - 0x30, 0xa4, 0x56, 0xab, 0x16, 0xb6, 0x6d, 0x7a, 0x24, 0x98, 0x54, 0x44, 0x31, 0x37, 0xfe, 0x6f, - 0xbe, 0x70, 0x7a, 0x24, 0xc0, 0xb1, 0x90, 0x02, 0xb8, 0xea, 0x92, 0x9e, 0xfa, 0x84, 0x04, 0xe3, - 0x2d, 0x2d, 0x22, 0x19, 0xa6, 0xf2, 0x1b, 0xeb, 0x97, 0x56, 0x94, 0x85, 0x17, 0xf2, 0xeb, 0x0b, - 0x2b, 0xcb, 0x65, 0xf6, 0x08, 0x60, 0x79, 0x6d, 0xb5, 0x34, 0xb7, 0x70, 0x71, 0xa1, 0x54, 0x4c, - 0x0f, 0xa0, 0x69, 0x38, 0xd6, 0x06, 0xa7, 0x58, 0x5a, 0x2c, 0xcd, 0xe7, 0xd7, 0x4b, 0x69, 0x09, - 0xdd, 0x05, 0x27, 0xda, 0x32, 0x71, 0x51, 0x22, 0x1d, 0x50, 0x94, 0x92, 0x8b, 0x12, 0x2d, 0x5c, - 0xec, 0xe8, 0x45, 0x0f, 0x75, 0xb5, 0x9f, 0x5d, 0xd7, 0x5d, 0x82, 0xfe, 0xf4, 0x27, 0x12, 0x1c, - 0x0d, 0x4f, 0x19, 0xaa, 0xbe, 0xd7, 0xe1, 0x1d, 0x68, 0x87, 0x68, 0xf6, 0x26, 0x88, 0xe6, 0xf5, - 0x3d, 0x74, 0x94, 0xe5, 0xd3, 0xe5, 0xa6, 0x55, 0xe7, 0x31, 0x68, 0x88, 0x94, 0x37, 0xac, 0x3a, - 0x89, 0x4d, 0xe2, 0xea, 0xbf, 0x74, 0x32, 0xc5, 0xef, 0xf3, 0xe7, 0x62, 0xdf, 0xfb, 0xd4, 0xf4, - 0x40, 0x61, 0x27, 0xdc, 0xa5, 0x2f, 0xf5, 0x9c, 0x41, 0x13, 0x79, 0x7d, 0x8f, 0x06, 0x9f, 0x55, - 0xe9, 0x85, 0x38, 0xed, 0x90, 0x38, 0x34, 0x9d, 0x0a, 0x1f, 0x9a, 0x3e, 0x87, 0xeb, 0xf5, 0xcb, - 0xba, 0x71, 0x8d, 0x8e, 0xa4, 0xd7, 0xef, 0xbf, 0x1a, 0x81, 0xa9, 0x96, 0xa9, 0x92, 0x67, 0x15, - 0x9d, 0x1e, 0xc1, 0xe6, 0x20, 0x51, 0x14, 0xc9, 0x4a, 0x06, 0x86, 0x6c, 0x5c, 0x31, 0xf4, 0x2a, - 0xf3, 0xee, 0xa8, 0x22, 0x8a, 0xa4, 0xab, 0xba, 0xaa, 0x1b, 0x36, 0xbf, 0x79, 0xcf, 0x0a, 0x85, - 0x9f, 0x91, 0xf6, 0x97, 0x23, 0x8c, 0x88, 0x96, 0x44, 0x37, 0x4f, 0x75, 0x3b, 0x57, 0xa6, 0x2a, - 0x70, 0xe5, 0xf7, 0x9d, 0x21, 0xf7, 0xab, 0x8e, 0x0f, 0x45, 0x60, 0x3a, 0xac, 0x0e, 0x92, 0xa3, - 0xd9, 0x8e, 0xda, 0x30, 0x3b, 0xe9, 0xe3, 0x02, 0x24, 0xd7, 0x05, 0xce, 0xbe, 0x15, 0xf2, 0xb3, - 0xfb, 0x54, 0xc8, 0xa8, 0xdb, 0x94, 0xd0, 0xc8, 0x83, 0xbd, 0x35, 0xe2, 0x76, 0xe1, 0x00, 0x2a, - 0xf9, 0x6c, 0x0c, 0x4e, 0xd0, 0xc7, 0x58, 0x56, 0x43, 0xd3, 0x9d, 0x33, 0x15, 0x6b, 0xcf, 0x74, - 0x68, 0x7a, 0x66, 0x6c, 0x71, 0x85, 0x8c, 0x7b, 0xd5, 0xb3, 0xac, 0xba, 0x83, 0x7f, 0x6c, 0x41, - 0x7c, 0x95, 0xd0, 0x11, 0x55, 0x38, 0x86, 0xa3, 0xd6, 0xb9, 0x8a, 0x58, 0x81, 0x40, 0xd9, 0x03, - 0xae, 0x08, 0x83, 0x6a, 0xe2, 0xed, 0x56, 0x1d, 0xab, 0x5b, 0xec, 0x1e, 0x7c, 0x94, 0xba, 0x4d, - 0x82, 0x00, 0xe8, 0x95, 0xf7, 0x49, 0x88, 0xab, 0x4d, 0x76, 0x85, 0x23, 0x4a, 0xfc, 0x89, 0x16, - 0xe4, 0xcb, 0x30, 0xc4, 0x8f, 0x8d, 0x51, 0x1a, 0xa2, 0x3b, 0x78, 0x8f, 0xb6, 0x93, 0x52, 0xc8, - 0x4f, 0x34, 0x0b, 0x71, 0x2a, 0x3c, 0x9f, 0x26, 0x32, 0xb3, 0x2d, 0xd2, 0xcf, 0x52, 0x21, 0x15, - 0x86, 0x26, 0x3f, 0x03, 0x89, 0xa2, 0xd1, 0xd0, 0x74, 0x23, 0xc8, 0x2d, 0xc9, 0xb8, 0x51, 0x99, - 0xcd, 0x26, 0xcf, 0x2a, 0x14, 0x56, 0x40, 0x87, 0x61, 0x90, 0xbd, 0x8b, 0xe0, 0xd7, 0x50, 0x78, - 0x49, 0x9e, 0x83, 0x21, 0xca, 0x7b, 0xc5, 0x44, 0x88, 0xbf, 0xa8, 0xe3, 0x0f, 0x30, 0x68, 0x02, - 0xca, 0xd9, 0x47, 0x3c, 0x61, 0x11, 0xc4, 0xaa, 0xaa, 0xa3, 0xf2, 0x7e, 0xd3, 0xdf, 0xf2, 0x53, - 0x90, 0xe0, 0x4c, 0x6c, 0x74, 0x16, 0xa2, 0x86, 0x69, 0xf3, 0x8b, 0x24, 0xd9, 0x4e, 0x5d, 0x59, - 0x31, 0x0b, 0x31, 0x92, 0x8f, 0x28, 0x04, 0xb9, 0xa0, 0x74, 0x0c, 0x9d, 0x4f, 0xf8, 0x2c, 0xc9, - 0x37, 0xe4, 0xbe, 0x9f, 0x6c, 0x48, 0x5b, 0xcc, 0xc1, 0x35, 0x96, 0x4f, 0x45, 0x60, 0xca, 0x57, - 0x7b, 0x15, 0x5b, 0xb6, 0x66, 0xe8, 0x7c, 0xd6, 0x66, 0xd6, 0x82, 0x7c, 0x42, 0xf2, 0xfa, 0x0e, - 0xe6, 0xf2, 0x66, 0x88, 0xe6, 0x4d, 0x13, 0x65, 0x21, 0xc1, 0x2e, 0x8c, 0x18, 0xcc, 0x5e, 0x62, - 0x8a, 0x5b, 0x26, 0x75, 0xb6, 0xb1, 0xe5, 0x5c, 0x53, 0x2d, 0xf7, 0xe9, 0xa0, 0x28, 0xcb, 0x4f, - 0x42, 0x72, 0xce, 0xd0, 0x6d, 0xac, 0xdb, 0x4d, 0xea, 0x7c, 0x9b, 0x75, 0xa3, 0xb2, 0xc3, 0x39, - 0xb0, 0x02, 0x51, 0xb8, 0x6a, 0x9a, 0x94, 0x32, 0xa6, 0x90, 0x9f, 0x2c, 0x03, 0x2c, 0xac, 0x75, - 0x54, 0xd1, 0x93, 0xfb, 0x57, 0x11, 0xef, 0xa4, 0xab, 0xa3, 0xff, 0x23, 0xc1, 0xf1, 0x56, 0x87, - 0xda, 0xc1, 0x7b, 0xf6, 0x7e, 0xfd, 0xe9, 0x79, 0x48, 0xae, 0xd2, 0xf7, 0xfb, 0x97, 0xf1, 0x1e, - 0xca, 0xc2, 0x10, 0xae, 0x9e, 0x3d, 0x77, 0xee, 0x91, 0x27, 0x99, 0xb5, 0x5f, 0x1a, 0x50, 0x04, - 0x00, 0x4d, 0x41, 0xd2, 0xc6, 0x15, 0xf3, 0xec, 0xb9, 0xf3, 0x3b, 0x8f, 0x30, 0xf3, 0x22, 0x79, - 0x8e, 0x0b, 0xca, 0x25, 0x48, 0xaf, 0x5f, 0xff, 0xd4, 0xb4, 0x54, 0x88, 0x43, 0xd4, 0x6e, 0x36, - 0xee, 0xa8, 0x8d, 0xbc, 0x1a, 0x87, 0x19, 0x3f, 0x25, 0x8d, 0x50, 0x6e, 0xee, 0xc1, 0x75, 0x90, - 0xf6, 0xe9, 0x80, 0x62, 0x74, 0x48, 0x59, 0xbb, 0x6a, 0x52, 0xfe, 0x35, 0x09, 0x52, 0x6e, 0x42, - 0xb4, 0x86, 0x1d, 0x74, 0xc1, 0x9f, 0xe5, 0x70, 0xb7, 0x39, 0x36, 0x1b, 0x6e, 0xcb, 0x4b, 0xdc, - 0x14, 0x1f, 0x3a, 0x7a, 0x9c, 0x1a, 0xa2, 0x69, 0xd8, 0xfc, 0x39, 0x59, 0x0f, 0x52, 0x17, 0x19, - 0x3d, 0x04, 0x88, 0x46, 0xb8, 0xf2, 0x55, 0xc3, 0xd1, 0xf4, 0x5a, 0xd9, 0x34, 0xae, 0xf1, 0x47, - 0xba, 0x51, 0x25, 0x4d, 0x6b, 0xae, 0xd0, 0x8a, 0x55, 0x02, 0x27, 0x42, 0x27, 0x5d, 0x2e, 0xc1, - 0x24, 0x8e, 0x04, 0x01, 0x51, 0x44, 0x17, 0x60, 0xc8, 0x6c, 0x6e, 0x96, 0x45, 0xc4, 0x18, 0x3e, - 0x7b, 0xbc, 0x9d, 0xff, 0x0b, 0xfb, 0xe0, 0x11, 0x60, 0xd0, 0x6c, 0x6e, 0x12, 0x6b, 0xb9, 0x0b, - 0x52, 0x6d, 0x84, 0x19, 0xbe, 0xea, 0xc9, 0x41, 0x3f, 0x1b, 0xc1, 0x7b, 0x50, 0x36, 0x2d, 0xcd, - 0xb0, 0x34, 0x67, 0x8f, 0x66, 0xa9, 0x51, 0x25, 0x2d, 0x2a, 0x56, 0x39, 0x5c, 0xde, 0x81, 0xb1, - 0x35, 0xba, 0x8a, 0xf5, 0x24, 0x3f, 0xe7, 0xc9, 0x27, 0xf5, 0x96, 0xaf, 0xa3, 0x64, 0x91, 0x16, - 0xc9, 0x0a, 0xcf, 0x76, 0xb4, 0xce, 0xc7, 0xf7, 0x6f, 0x9d, 0xc1, 0x3c, 0xf0, 0x0f, 0x8f, 0x06, - 0x9c, 0x93, 0x4f, 0x9f, 0xbe, 0xf0, 0xd5, 0xaf, 0x61, 0xf6, 0x4a, 0x23, 0xb2, 0xdd, 0x27, 0xd5, - 0x6c, 0x8f, 0x30, 0x9a, 0xed, 0xe9, 0x42, 0xf2, 0x93, 0x30, 0xb2, 0xaa, 0x5a, 0xce, 0x1a, 0x76, - 0x2e, 0x61, 0xb5, 0x8a, 0xad, 0xe0, 0xac, 0x3b, 0x22, 0x66, 0x5d, 0x04, 0x31, 0x3a, 0xb5, 0xb2, - 0x59, 0x87, 0xfe, 0x96, 0xb7, 0x21, 0x46, 0x6f, 0x84, 0xba, 0x33, 0x32, 0xa7, 0x60, 0x33, 0x32, - 0x89, 0xa5, 0x7b, 0x0e, 0xb6, 0x45, 0x12, 0x4b, 0x0b, 0xe8, 0x31, 0x31, 0xaf, 0x46, 0xbb, 0xcf, - 0xab, 0xdc, 0x10, 0xf9, 0xec, 0x5a, 0x87, 0xa1, 0x02, 0x09, 0xc5, 0x0b, 0x45, 0x57, 0x10, 0xc9, - 0x13, 0x04, 0x2d, 0xc1, 0x98, 0xa9, 0x5a, 0x0e, 0x7d, 0x0a, 0xb3, 0x4d, 0x7b, 0xc1, 0x6d, 0x7d, - 0xba, 0xd5, 0xf3, 0x02, 0x9d, 0xe5, 0xad, 0x8c, 0x98, 0x7e, 0xa0, 0xfc, 0x07, 0x31, 0x18, 0xe4, - 0xca, 0x78, 0x33, 0x0c, 0x71, 0xb5, 0x72, 0xeb, 0x3c, 0x31, 0xdb, 0x3a, 0x31, 0xcd, 0xba, 0x13, - 0x08, 0xe7, 0x27, 0x68, 0xd0, 0x7d, 0x90, 0xa8, 0x6c, 0xab, 0x9a, 0x5e, 0xd6, 0xaa, 0x62, 0x43, - 0xe1, 0xb5, 0x9b, 0xd3, 0x43, 0x73, 0x04, 0xb6, 0x50, 0x54, 0x86, 0x68, 0xe5, 0x42, 0x95, 0x64, - 0x02, 0xdb, 0x58, 0xab, 0x6d, 0x3b, 0xdc, 0xc3, 0x78, 0x09, 0x3d, 0x01, 0x31, 0x62, 0x10, 0xfc, - 0xa1, 0x64, 0xb6, 0x65, 0x5b, 0xc7, 0xcd, 0xf2, 0x0a, 0x09, 0xd2, 0xf0, 0x87, 0xbe, 0x39, 0x2d, - 0x29, 0x94, 0x02, 0xcd, 0xc1, 0x48, 0x5d, 0xb5, 0x9d, 0x32, 0x9d, 0xc1, 0x48, 0xf3, 0x71, 0xbe, - 0xaa, 0x6e, 0x51, 0x08, 0x57, 0x2c, 0x17, 0x7d, 0x98, 0x50, 0x31, 0x50, 0x15, 0x9d, 0x84, 0x34, - 0x65, 0x52, 0x31, 0x1a, 0x0d, 0xcd, 0x61, 0xb9, 0xd5, 0x20, 0xd5, 0xfb, 0x28, 0x81, 0xcf, 0x51, - 0x30, 0xcd, 0xb0, 0x8e, 0x41, 0x92, 0x3e, 0xcd, 0xa2, 0x28, 0xec, 0x1a, 0x72, 0x82, 0x00, 0x68, - 0xe5, 0xfd, 0x30, 0xe6, 0xc5, 0x47, 0x86, 0x92, 0x60, 0x5c, 0x3c, 0x30, 0x45, 0x7c, 0x18, 0x26, - 0x75, 0xbc, 0x4b, 0x2f, 0x46, 0x07, 0xb0, 0x93, 0x14, 0x1b, 0x91, 0xba, 0x2b, 0x41, 0x8a, 0x7b, - 0x61, 0xb4, 0x22, 0x94, 0xcf, 0x70, 0x81, 0xe2, 0x8e, 0xb8, 0x50, 0x8a, 0x76, 0x14, 0x12, 0xaa, - 0x69, 0x32, 0x84, 0x61, 0x1e, 0x1f, 0x4d, 0x93, 0x56, 0x9d, 0x82, 0x71, 0xda, 0x47, 0x0b, 0xdb, - 0xcd, 0xba, 0xc3, 0x99, 0xa4, 0x28, 0xce, 0x18, 0xa9, 0x50, 0x18, 0x9c, 0xe2, 0xde, 0x0d, 0x23, - 0xf8, 0xaa, 0x56, 0xc5, 0x7a, 0x05, 0x33, 0xbc, 0x11, 0x8a, 0x97, 0x12, 0x40, 0x8a, 0xf4, 0x00, - 0xb8, 0x71, 0xaf, 0x2c, 0x62, 0xf2, 0x28, 0xe3, 0x27, 0xe0, 0x79, 0x06, 0x96, 0x33, 0x10, 0x2b, - 0xaa, 0x8e, 0x4a, 0x12, 0x0c, 0x67, 0x97, 0x4d, 0x34, 0x29, 0x85, 0xfc, 0x94, 0x5f, 0x8f, 0x40, - 0xec, 0x8a, 0xe1, 0x60, 0xf4, 0xa8, 0x2f, 0x01, 0x1c, 0x6d, 0x67, 0xcf, 0x6b, 0x5a, 0x4d, 0xc7, - 0xd5, 0x25, 0xbb, 0xe6, 0xfb, 0x8e, 0x82, 0x67, 0x4e, 0x91, 0x80, 0x39, 0x4d, 0x42, 0xdc, 0x32, - 0x9a, 0x7a, 0x55, 0xdc, 0xe0, 0xa5, 0x05, 0x54, 0x82, 0x84, 0x6b, 0x25, 0xb1, 0x5e, 0x56, 0x32, - 0x46, 0xac, 0x84, 0xd8, 0x30, 0x07, 0x28, 0x43, 0x9b, 0xdc, 0x58, 0x0a, 0x90, 0x74, 0x83, 0x17, - 0xb7, 0xb6, 0xfe, 0x0c, 0xd6, 0x23, 0x23, 0x93, 0x89, 0x3b, 0xf6, 0xae, 0xf2, 0x98, 0xc5, 0xa5, - 0xdd, 0x0a, 0xae, 0xbd, 0x80, 0x59, 0xf1, 0x6f, 0x3a, 0x0c, 0xd1, 0x7e, 0x79, 0x66, 0xc5, 0xbe, - 0xeb, 0x70, 0x1c, 0x92, 0xb6, 0x56, 0xd3, 0x55, 0xa7, 0x69, 0x61, 0x6e, 0x79, 0x1e, 0x40, 0xfe, - 0x92, 0x04, 0x83, 0xcc, 0x92, 0x7d, 0x7a, 0x93, 0xda, 0xeb, 0x2d, 0xd2, 0x49, 0x6f, 0xd1, 0x83, - 0xeb, 0x2d, 0x0f, 0xe0, 0x0a, 0x63, 0xf3, 0xa7, 0xf6, 0x6d, 0x32, 0x06, 0x26, 0xe2, 0x9a, 0x56, - 0xe3, 0x8e, 0xea, 0x23, 0x92, 0xff, 0x93, 0x44, 0x92, 0x58, 0x5e, 0x8f, 0xf2, 0x30, 0x22, 0xe4, - 0x2a, 0x6f, 0xd5, 0xd5, 0x1a, 0xb7, 0x9d, 0x13, 0x1d, 0x85, 0xbb, 0x58, 0x57, 0x6b, 0xca, 0x30, - 0x97, 0x87, 0x14, 0xda, 0x8f, 0x43, 0xa4, 0xc3, 0x38, 0x04, 0x06, 0x3e, 0x7a, 0xb0, 0x81, 0x0f, - 0x0c, 0x51, 0x2c, 0x3c, 0x44, 0x9f, 0x8f, 0xd0, 0xc5, 0x8c, 0x69, 0xd8, 0x6a, 0xfd, 0x87, 0xe1, - 0x11, 0xc7, 0x20, 0x69, 0x1a, 0xf5, 0x32, 0xab, 0x61, 0x37, 0xdb, 0x13, 0xa6, 0x51, 0x57, 0x5a, - 0x86, 0x3d, 0x7e, 0x9b, 0xdc, 0x65, 0xf0, 0x36, 0x68, 0x6d, 0x28, 0xac, 0x35, 0x0b, 0x52, 0x4c, - 0x15, 0x7c, 0x2e, 0x7b, 0x98, 0xe8, 0x80, 0x4e, 0x8e, 0x52, 0xeb, 0xdc, 0xcb, 0xc4, 0x66, 0x98, - 0x0a, 0xc7, 0x23, 0x14, 0x2c, 0xf4, 0xb7, 0x5b, 0x05, 0xfb, 0xcd, 0x52, 0xe1, 0x78, 0xf2, 0xcf, - 0x4a, 0x00, 0x8b, 0x44, 0xb3, 0xb4, 0xbf, 0x64, 0x16, 0xb2, 0xa9, 0x08, 0xe5, 0x40, 0xcb, 0x53, - 0x9d, 0x06, 0x8d, 0xb7, 0x9f, 0xb2, 0xfd, 0x72, 0xcf, 0xc1, 0x88, 0x67, 0x8c, 0x36, 0x16, 0xc2, - 0x4c, 0x75, 0xc9, 0xaa, 0xd7, 0xb0, 0xa3, 0xa4, 0xae, 0xfa, 0x4a, 0xf2, 0x3f, 0x93, 0x20, 0x49, - 0x65, 0x5a, 0xc2, 0x8e, 0x1a, 0x18, 0x43, 0xe9, 0xe0, 0x63, 0x78, 0x02, 0x80, 0xb1, 0xb1, 0xb5, - 0x97, 0x31, 0xb7, 0xac, 0x24, 0x85, 0xac, 0x69, 0x2f, 0x63, 0x74, 0xde, 0x55, 0x78, 0xb4, 0xbb, - 0xc2, 0x45, 0xd6, 0xcd, 0xd5, 0x7e, 0x04, 0x86, 0xe8, 0xa7, 0xa9, 0x76, 0x6d, 0x9e, 0x48, 0x0f, - 0xea, 0xcd, 0xc6, 0xfa, 0xae, 0x2d, 0xbf, 0x08, 0x43, 0xeb, 0xbb, 0x6c, 0x6f, 0xe4, 0x18, 0x24, - 0x2d, 0xc3, 0xe0, 0x73, 0x32, 0xcb, 0x85, 0x12, 0x04, 0x40, 0xa7, 0x20, 0xb1, 0x1f, 0x10, 0xf1, - 0xf6, 0x03, 0xbc, 0x0d, 0x8d, 0x68, 0x5f, 0x1b, 0x1a, 0xa7, 0xfe, 0xbd, 0x04, 0xc3, 0xbe, 0xf8, - 0x80, 0x1e, 0x81, 0x43, 0x85, 0xc5, 0x95, 0xb9, 0xcb, 0xe5, 0x85, 0x62, 0xf9, 0xe2, 0x62, 0x7e, - 0xde, 0x7b, 0xbb, 0x95, 0x3d, 0x7c, 0xfd, 0xc6, 0x0c, 0xf2, 0xe1, 0x6e, 0xe8, 0x3b, 0xba, 0x71, - 0x4d, 0x47, 0x67, 0x60, 0x32, 0x48, 0x92, 0x2f, 0xac, 0x95, 0x96, 0xd7, 0xd3, 0x52, 0xf6, 0xd0, - 0xf5, 0x1b, 0x33, 0xe3, 0x3e, 0x8a, 0xfc, 0xa6, 0x8d, 0x75, 0xa7, 0x95, 0x60, 0x6e, 0x65, 0x69, - 0x69, 0x61, 0x3d, 0x1d, 0x69, 0x21, 0xe0, 0x01, 0xfb, 0x01, 0x18, 0x0f, 0x12, 0x2c, 0x2f, 0x2c, - 0xa6, 0xa3, 0x59, 0x74, 0xfd, 0xc6, 0xcc, 0xa8, 0x0f, 0x7b, 0x59, 0xab, 0x67, 0x13, 0xef, 0xff, - 0xf4, 0xd4, 0xc0, 0x2f, 0xfe, 0xc2, 0x94, 0x44, 0x7a, 0x36, 0x12, 0x88, 0x11, 0xe8, 0x21, 0x38, - 0xb2, 0xb6, 0x30, 0xbf, 0x5c, 0x2a, 0x96, 0x97, 0xd6, 0xe6, 0xc5, 0x4e, 0xb3, 0xe8, 0xdd, 0xd8, - 0xf5, 0x1b, 0x33, 0xc3, 0xbc, 0x4b, 0x9d, 0xb0, 0x57, 0x95, 0xd2, 0x95, 0x95, 0xf5, 0x52, 0x5a, - 0x62, 0xd8, 0xab, 0x16, 0xbe, 0x6a, 0x38, 0xec, 0xdb, 0x75, 0x0f, 0xc3, 0xd1, 0x36, 0xd8, 0x6e, - 0xc7, 0xc6, 0xaf, 0xdf, 0x98, 0x19, 0x59, 0xb5, 0x30, 0xf3, 0x1f, 0x4a, 0x31, 0x0b, 0x99, 0x56, - 0x8a, 0x95, 0xd5, 0x95, 0xb5, 0xfc, 0x62, 0x7a, 0x26, 0x9b, 0xbe, 0x7e, 0x63, 0x26, 0x25, 0x82, - 0x21, 0xdd, 0xce, 0x77, 0x7b, 0x76, 0x27, 0x57, 0x3c, 0x7f, 0x7c, 0x1a, 0xee, 0xe9, 0x70, 0x92, - 0x24, 0xce, 0x20, 0x0e, 0x74, 0x96, 0xd4, 0x71, 0x37, 0x3d, 0xdb, 0x63, 0xc3, 0xb9, 0xf7, 0xd2, - 0xe9, 0xe0, 0xe7, 0x54, 0xd9, 0xae, 0x8b, 0x3b, 0xf9, 0x03, 0x12, 0x8c, 0x5e, 0xd2, 0x6c, 0xc7, - 0xb0, 0xb4, 0x8a, 0x5a, 0xa7, 0x2f, 0xb6, 0xce, 0xf7, 0x1b, 0x5b, 0x43, 0xae, 0xfe, 0x34, 0x0c, - 0x5e, 0x55, 0xeb, 0x2c, 0xa8, 0x45, 0xe9, 0x07, 0x66, 0x3a, 0x1c, 0xec, 0xb8, 0xa1, 0x4d, 0x30, - 0x60, 0x64, 0xf2, 0x2f, 0x47, 0x60, 0x8c, 0x3a, 0x83, 0xcd, 0x3e, 0x3d, 0x46, 0xd6, 0x58, 0x05, - 0x88, 0x59, 0xaa, 0xc3, 0x37, 0x0d, 0x0b, 0xb3, 0xfc, 0x8c, 0xf1, 0xbe, 0x3e, 0x4e, 0xcc, 0x8a, - 0xb8, 0xa2, 0x50, 0x5a, 0xf4, 0x76, 0x48, 0x34, 0xd4, 0xdd, 0x32, 0xe5, 0xc3, 0x56, 0x2e, 0xf9, - 0xfd, 0xf1, 0xb9, 0x75, 0x73, 0x7a, 0x6c, 0x4f, 0x6d, 0xd4, 0x73, 0xb2, 0xe0, 0x23, 0x2b, 0x43, - 0x0d, 0x75, 0x97, 0x88, 0x88, 0x4c, 0x18, 0x23, 0xd0, 0xca, 0xb6, 0xaa, 0xd7, 0x30, 0x6b, 0x84, - 0x6e, 0x81, 0x16, 0x2e, 0xed, 0xbb, 0x91, 0xc3, 0x5e, 0x23, 0x3e, 0x76, 0xb2, 0x32, 0xd2, 0x50, - 0x77, 0xe7, 0x28, 0x80, 0xb4, 0x98, 0x4b, 0x7c, 0xf4, 0x93, 0xd3, 0x03, 0xf4, 0xdc, 0xf6, 0x1b, - 0x12, 0x80, 0xa7, 0x31, 0xf4, 0x76, 0x48, 0x57, 0xdc, 0x12, 0xa5, 0x15, 0x27, 0x90, 0xf7, 0x77, - 0x1a, 0x8b, 0x90, 0xbe, 0xd9, 0xdc, 0xfc, 0xf5, 0x9b, 0xd3, 0x92, 0x32, 0x56, 0x09, 0x0d, 0xc5, - 0xdb, 0x60, 0xb8, 0x69, 0x56, 0x55, 0x07, 0x97, 0xe9, 0x3a, 0x2e, 0xd2, 0x73, 0x9e, 0x9f, 0x22, - 0xbc, 0x6e, 0xdd, 0x9c, 0x46, 0xac, 0x5b, 0x3e, 0x62, 0x99, 0xce, 0xfe, 0xc0, 0x20, 0x84, 0xc0, - 0xd7, 0xa7, 0xaf, 0x4a, 0x30, 0x5c, 0xf4, 0xdd, 0x9c, 0xcc, 0xc0, 0x50, 0xc3, 0xd0, 0xb5, 0x1d, - 0x6e, 0x8f, 0x49, 0x45, 0x14, 0x51, 0x16, 0x12, 0xec, 0x11, 0xab, 0xb3, 0x27, 0xb6, 0x42, 0x45, - 0x99, 0x50, 0x5d, 0xc3, 0x9b, 0xb6, 0x26, 0x46, 0x43, 0x11, 0x45, 0x74, 0x11, 0xd2, 0x36, 0xae, - 0x34, 0x2d, 0xcd, 0xd9, 0x2b, 0x57, 0x0c, 0xdd, 0x51, 0x2b, 0x0e, 0x7b, 0x0e, 0x59, 0x38, 0x76, - 0xeb, 0xe6, 0xf4, 0x11, 0x26, 0x6b, 0x18, 0x43, 0x56, 0xc6, 0x04, 0x68, 0x8e, 0x41, 0x48, 0x0b, - 0x55, 0xec, 0xa8, 0x5a, 0xdd, 0xce, 0xb0, 0x2b, 0x08, 0xa2, 0xe8, 0xeb, 0xcb, 0xe7, 0x86, 0xfc, - 0x1b, 0x5b, 0x17, 0x21, 0x6d, 0x98, 0xd8, 0x0a, 0x24, 0xa2, 0x52, 0xb8, 0xe5, 0x30, 0x86, 0xac, - 0x8c, 0x09, 0x90, 0x48, 0x52, 0x1d, 0x32, 0xcc, 0x62, 0xa1, 0x68, 0x36, 0x37, 0xbd, 0xfd, 0xb0, - 0xc9, 0x96, 0xd1, 0xc8, 0xeb, 0x7b, 0x85, 0x47, 0x3d, 0xee, 0x61, 0x3a, 0xf9, 0x6b, 0x5f, 0x38, - 0x3d, 0xc9, 0x4d, 0xc3, 0xdb, 0x9f, 0xba, 0x8c, 0xf7, 0xc8, 0xf0, 0x73, 0xd4, 0x55, 0x8a, 0x49, - 0xd2, 0xce, 0x17, 0x55, 0xad, 0x2e, 0x9e, 0xf5, 0x2b, 0xbc, 0x84, 0x72, 0x30, 0x68, 0x3b, 0xaa, - 0xd3, 0xb4, 0xf9, 0x79, 0xae, 0xdc, 0xc9, 0xd4, 0x0a, 0x86, 0x5e, 0x5d, 0xa3, 0x98, 0x0a, 0xa7, - 0x40, 0x17, 0x61, 0x90, 0x1f, 0x94, 0xc7, 0xf7, 0xed, 0xdf, 0xf4, 0x46, 0x04, 0xa3, 0x26, 0x1a, - 0xa9, 0xe2, 0x3a, 0xae, 0xb1, 0xb4, 0x6a, 0x5b, 0x25, 0xab, 0x0f, 0xfa, 0xcd, 0xbd, 0xc2, 0xc2, - 0xbe, 0x9d, 0x90, 0x6b, 0x2a, 0xcc, 0x4f, 0x56, 0xc6, 0x5c, 0xd0, 0x1a, 0x85, 0xa0, 0xcb, 0x81, - 0x2b, 0xbe, 0xfc, 0xc3, 0x94, 0x77, 0x77, 0xea, 0xbe, 0xcf, 0xa6, 0xc5, 0xfe, 0x84, 0xff, 0x82, - 0xf0, 0x45, 0x48, 0x37, 0xf5, 0x4d, 0x43, 0xa7, 0x6f, 0x6f, 0x79, 0x7e, 0x4f, 0xd6, 0x77, 0x51, - 0xbf, 0x71, 0x84, 0x31, 0x64, 0x65, 0xcc, 0x05, 0x5d, 0x62, 0xab, 0x80, 0x2a, 0x8c, 0x7a, 0x58, - 0xd4, 0x51, 0x93, 0x3d, 0x1d, 0xf5, 0x2e, 0xee, 0xa8, 0x87, 0xc2, 0xad, 0x78, 0xbe, 0x3a, 0xe2, - 0x02, 0x09, 0x19, 0xba, 0x04, 0xe0, 0x85, 0x07, 0xba, 0x4f, 0x31, 0xdc, 0x79, 0xe0, 0xbd, 0x18, - 0x23, 0xd6, 0x7b, 0x1e, 0x2d, 0x7a, 0x27, 0x4c, 0x34, 0x34, 0xbd, 0x6c, 0xe3, 0xfa, 0x56, 0x99, - 0x2b, 0x98, 0xb0, 0xa4, 0x9f, 0x4e, 0x2a, 0x2c, 0xee, 0xcf, 0x1e, 0x6e, 0xdd, 0x9c, 0xce, 0xf2, - 0x10, 0xda, 0xca, 0x52, 0x56, 0xc6, 0x1b, 0x9a, 0xbe, 0x86, 0xeb, 0x5b, 0x45, 0x17, 0x96, 0x4b, - 0xbd, 0xff, 0x93, 0xd3, 0x03, 0xdc, 0x5d, 0x07, 0xe4, 0xf3, 0x74, 0xef, 0x9c, 0xbb, 0x19, 0xb6, - 0xc9, 0x9a, 0x44, 0x15, 0x05, 0x7e, 0xa1, 0xc0, 0x03, 0x30, 0x37, 0x7f, 0xe5, 0x3f, 0xce, 0x48, - 0xf2, 0xe7, 0x24, 0x18, 0x2c, 0x5e, 0x59, 0x55, 0x35, 0x0b, 0x2d, 0xc0, 0xb8, 0x67, 0x39, 0x41, - 0x27, 0x3f, 0x7e, 0xeb, 0xe6, 0x74, 0x26, 0x6c, 0x5c, 0xae, 0x97, 0x7b, 0x06, 0x2c, 0xdc, 0x7c, - 0xa1, 0xd3, 0xc2, 0x35, 0xc0, 0xaa, 0x05, 0x45, 0x6e, 0x5d, 0xd6, 0x86, 0xba, 0x59, 0x82, 0x21, - 0x26, 0xad, 0x8d, 0x72, 0x10, 0x37, 0xc9, 0x0f, 0x7e, 0x30, 0x30, 0xd5, 0xd1, 0x78, 0x29, 0xbe, - 0xbb, 0x91, 0x49, 0x48, 0xe4, 0x0f, 0x47, 0x00, 0x8a, 0x57, 0xae, 0xac, 0x5b, 0x9a, 0x59, 0xc7, - 0xce, 0xed, 0xec, 0xf9, 0x3a, 0x1c, 0xf2, 0xad, 0x92, 0xac, 0x4a, 0xa8, 0xf7, 0x33, 0xb7, 0x6e, - 0x4e, 0x1f, 0x0f, 0xf7, 0xde, 0x87, 0x26, 0x2b, 0x13, 0xde, 0x7a, 0xc9, 0xaa, 0xb4, 0xe5, 0x5a, - 0xb5, 0x1d, 0x97, 0x6b, 0xb4, 0x33, 0x57, 0x1f, 0x9a, 0x9f, 0x6b, 0xd1, 0x76, 0xda, 0xab, 0x76, - 0x0d, 0x86, 0x3d, 0x95, 0xd8, 0xa8, 0x08, 0x09, 0x87, 0xff, 0xe6, 0x1a, 0x96, 0x3b, 0x6b, 0x58, - 0x90, 0x71, 0x2d, 0xbb, 0x94, 0xf2, 0x9f, 0x4a, 0x00, 0x9e, 0xcd, 0xfe, 0x78, 0x9a, 0x18, 0x09, - 0xe5, 0x3c, 0xf0, 0x46, 0x0f, 0x94, 0xaa, 0x71, 0xea, 0x90, 0x3e, 0x7f, 0x2a, 0x02, 0x13, 0x1b, - 0x22, 0xf2, 0xfc, 0xd8, 0xeb, 0x60, 0x15, 0x86, 0xb0, 0xee, 0x58, 0x1a, 0x55, 0x02, 0x19, 0xed, - 0x87, 0x3b, 0x8d, 0x76, 0x9b, 0x3e, 0xd1, 0x8f, 0x47, 0x89, 0x4d, 0x77, 0xce, 0x26, 0xa4, 0x8d, - 0x0f, 0x46, 0x21, 0xd3, 0x89, 0x12, 0xcd, 0xc1, 0x58, 0xc5, 0xc2, 0xec, 0x7a, 0x95, 0x7f, 0xe7, - 0xaf, 0x90, 0xf5, 0x32, 0xcb, 0x10, 0x82, 0xac, 0x8c, 0x0a, 0x08, 0x9f, 0x3d, 0x6a, 0x40, 0xd2, - 0x3e, 0x62, 0x76, 0xf4, 0x96, 0x56, 0x7f, 0x79, 0x9e, 0xcc, 0xa7, 0x0f, 0xd1, 0x48, 0x90, 0x01, - 0x9b, 0x3f, 0x46, 0x3d, 0x28, 0x9d, 0x40, 0x5e, 0x82, 0x31, 0x4d, 0xd7, 0x1c, 0x4d, 0xad, 0x97, - 0x37, 0xd5, 0xba, 0xaa, 0x57, 0x0e, 0x92, 0x35, 0xb3, 0x90, 0xcf, 0x9b, 0x0d, 0xb1, 0x93, 0x95, - 0x51, 0x0e, 0x29, 0x30, 0x00, 0xba, 0x04, 0x43, 0xa2, 0xa9, 0xd8, 0x81, 0xb2, 0x0d, 0x41, 0xee, - 0x4b, 0xf0, 0x7e, 0x3a, 0x0a, 0xe3, 0x0a, 0xae, 0xfe, 0xc5, 0x50, 0xec, 0x6f, 0x28, 0x96, 0x00, - 0x98, 0xbb, 0x93, 0x00, 0x7b, 0x80, 0xd1, 0x20, 0x01, 0x23, 0xc9, 0x38, 0x14, 0x6d, 0xc7, 0x37, - 0x1e, 0x37, 0x23, 0x90, 0xf2, 0x8f, 0xc7, 0x9f, 0xd3, 0x59, 0x09, 0x2d, 0x78, 0x91, 0x28, 0xc6, - 0x3f, 0xb9, 0xdb, 0x21, 0x12, 0xb5, 0x58, 0x6f, 0xf7, 0x10, 0xf4, 0x3f, 0x23, 0x30, 0xb8, 0xaa, - 0x5a, 0x6a, 0xc3, 0x46, 0x95, 0x96, 0x4c, 0x53, 0x6c, 0x3f, 0xb6, 0x7c, 0x58, 0x9d, 0xef, 0x76, - 0xf4, 0x48, 0x34, 0x3f, 0xda, 0x26, 0xd1, 0x7c, 0x0b, 0x8c, 0x92, 0xe5, 0xb0, 0xef, 0x0a, 0x03, - 0xd1, 0xf6, 0x48, 0xe1, 0xa8, 0xc7, 0x25, 0x58, 0xcf, 0x56, 0xcb, 0x57, 0xfc, 0x77, 0x18, 0x86, - 0x09, 0x86, 0x17, 0x98, 0x09, 0xf9, 0x61, 0x6f, 0x59, 0xea, 0xab, 0x94, 0x15, 0x68, 0xa8, 0xbb, - 0x25, 0x56, 0x40, 0x8b, 0x80, 0xb6, 0xdd, 0x9d, 0x91, 0xb2, 0xa7, 0x4e, 0x42, 0x7f, 0xe2, 0xd6, - 0xcd, 0xe9, 0xa3, 0x8c, 0xbe, 0x15, 0x47, 0x56, 0xc6, 0x3d, 0xa0, 0xe0, 0xf6, 0x18, 0x00, 0xe9, - 0x57, 0x99, 0x5d, 0xd4, 0x66, 0xcb, 0x9d, 0x43, 0xb7, 0x6e, 0x4e, 0x8f, 0x33, 0x2e, 0x5e, 0x9d, - 0xac, 0x24, 0x49, 0xa1, 0x48, 0x7e, 0xfb, 0x2c, 0xfb, 0xd3, 0x12, 0x20, 0x2f, 0xe4, 0x2b, 0xd8, - 0x36, 0xc9, 0xfa, 0x8c, 0x24, 0xe2, 0xbe, 0xac, 0x59, 0xea, 0x9e, 0x88, 0x7b, 0xf4, 0x22, 0x11, - 0xf7, 0x79, 0xca, 0x93, 0x5e, 0x78, 0x8c, 0xf4, 0xba, 0xb5, 0xcc, 0x4d, 0x24, 0x1c, 0x0f, 0x07, - 0xe4, 0x7f, 0x25, 0xc1, 0xd1, 0x16, 0x8b, 0x72, 0x85, 0xfd, 0x4b, 0x80, 0x2c, 0x5f, 0x25, 0xff, - 0x7e, 0x22, 0x13, 0x7a, 0xdf, 0x06, 0x3a, 0x6e, 0xb5, 0xc4, 0xdd, 0xdb, 0x17, 0xe1, 0xd9, 0xb5, - 0xf8, 0x7f, 0x2a, 0xc1, 0xa4, 0xbf, 0x79, 0xb7, 0x23, 0xcb, 0x90, 0xf2, 0xb7, 0xce, 0xbb, 0x70, - 0x4f, 0x3f, 0x5d, 0xe0, 0xd2, 0x07, 0xe8, 0xd1, 0xb3, 0x9e, 0xbb, 0xb2, 0xbd, 0xb3, 0x47, 0xfa, - 0xd6, 0x86, 0x90, 0x29, 0xec, 0xb6, 0x31, 0x3a, 0x1e, 0xff, 0x57, 0x82, 0xd8, 0xaa, 0x61, 0xd4, - 0x91, 0x01, 0xe3, 0xba, 0xe1, 0x94, 0x89, 0x65, 0xe1, 0xaa, 0xff, 0x76, 0x7a, 0xb2, 0x30, 0xb7, - 0x3f, 0x25, 0x7d, 0xe7, 0xe6, 0x74, 0x2b, 0x2b, 0x65, 0x4c, 0x37, 0x9c, 0x02, 0x85, 0xf0, 0x0b, - 0xea, 0xef, 0x84, 0x91, 0x60, 0x63, 0x2c, 0x4a, 0x3e, 0xb7, 0xef, 0xc6, 0x82, 0x6c, 0x6e, 0xdd, - 0x9c, 0x9e, 0xf4, 0x3c, 0xc6, 0x05, 0xcb, 0x4a, 0x6a, 0xd3, 0xd7, 0x3a, 0xbb, 0xde, 0xf5, 0xbd, - 0x4f, 0x4e, 0x4b, 0xa7, 0xbe, 0x28, 0x01, 0x78, 0x3b, 0x0f, 0xe8, 0x21, 0x38, 0x52, 0x58, 0x59, - 0x2e, 0x96, 0xd7, 0xd6, 0xf3, 0xeb, 0x1b, 0x6b, 0xc1, 0x9b, 0xdc, 0x62, 0x7b, 0xdc, 0x36, 0x71, - 0x45, 0xdb, 0xd2, 0x70, 0x15, 0xdd, 0x07, 0x93, 0x41, 0x6c, 0x52, 0x2a, 0x15, 0xd3, 0x52, 0x36, - 0x75, 0xfd, 0xc6, 0x4c, 0x82, 0xe5, 0x62, 0xb8, 0x8a, 0x4e, 0xc2, 0xa1, 0x56, 0xbc, 0x85, 0xe5, - 0xf9, 0x74, 0x24, 0x3b, 0x72, 0xfd, 0xc6, 0x4c, 0xd2, 0x4d, 0xda, 0x90, 0x0c, 0xc8, 0x8f, 0xc9, - 0xf9, 0x45, 0xb3, 0x70, 0xfd, 0xc6, 0xcc, 0x20, 0x53, 0x60, 0x36, 0xf6, 0xfe, 0x4f, 0x4f, 0x0d, - 0xdc, 0xf6, 0xfb, 0xde, 0x7f, 0x34, 0xd4, 0x71, 0xd7, 0xbb, 0x86, 0x75, 0x6c, 0x6b, 0xf6, 0x81, - 0x76, 0xbd, 0xfb, 0xda, 0x49, 0x97, 0x7f, 0x27, 0x0e, 0xa9, 0x79, 0xd6, 0x0a, 0x19, 0x08, 0x8c, - 0xde, 0x04, 0x83, 0x26, 0x9d, 0x46, 0xdc, 0x63, 0xb4, 0x0e, 0x06, 0xcf, 0x26, 0x1b, 0xf7, 0x2e, - 0x17, 0x9b, 0x7a, 0x6c, 0x7e, 0x99, 0x83, 0xdd, 0x31, 0xf3, 0x6e, 0x4d, 0xa5, 0xf6, 0xb5, 0xdf, - 0xc3, 0x72, 0x16, 0xbe, 0xb5, 0x12, 0xe6, 0x27, 0xb3, 0x7b, 0x21, 0xeb, 0x04, 0xc2, 0x6e, 0x87, - 0xbd, 0x57, 0x82, 0x43, 0x14, 0xcb, 0x9b, 0x88, 0x29, 0xa6, 0x48, 0xf6, 0x4f, 0x75, 0xea, 0xc2, - 0xa2, 0x6a, 0x7b, 0x77, 0x3d, 0xd8, 0x7d, 0xae, 0x7b, 0xf8, 0x44, 0x78, 0xdc, 0xd7, 0x78, 0x98, - 0xad, 0xac, 0x4c, 0xd4, 0x5b, 0x28, 0x6d, 0x34, 0x1f, 0xb8, 0xd0, 0x17, 0xdb, 0xdf, 0x56, 0xbb, - 0xff, 0x72, 0xdf, 0x33, 0x30, 0xec, 0xc5, 0x12, 0x9b, 0xff, 0xbf, 0x97, 0xfe, 0xe7, 0x0e, 0x3f, - 0x31, 0x7a, 0x9f, 0x04, 0x87, 0xbc, 0xd9, 0xdc, 0xcf, 0x96, 0xfd, 0x5f, 0x9c, 0x07, 0xf7, 0xb1, - 0x10, 0x0a, 0x2b, 0xa7, 0x2d, 0x5f, 0x59, 0x99, 0x6c, 0xb6, 0x92, 0x92, 0x25, 0xd8, 0x88, 0x3f, - 0xb2, 0xda, 0x19, 0xf1, 0xe9, 0xc7, 0xfe, 0x43, 0x73, 0x90, 0x01, 0xfb, 0x5f, 0x1d, 0xa6, 0x61, - 0x39, 0xb8, 0x4a, 0x37, 0xe4, 0x12, 0x8a, 0x5b, 0x96, 0x97, 0x01, 0xb5, 0x0e, 0x6e, 0xf8, 0x02, - 0xa3, 0xf7, 0x0a, 0x05, 0x4d, 0x42, 0xdc, 0x7f, 0xc5, 0x8f, 0x15, 0x72, 0x89, 0xf7, 0xf3, 0xe9, - 0xf3, 0xb6, 0xfb, 0xfc, 0xbf, 0x88, 0xc0, 0x29, 0xff, 0xf1, 0xd0, 0x4b, 0x4d, 0x6c, 0xed, 0xb9, - 0x2e, 0x6a, 0xaa, 0x35, 0x4d, 0xf7, 0xbf, 0x7b, 0x38, 0xea, 0x9f, 0xf0, 0x29, 0xae, 0xd0, 0x93, - 0xac, 0xc3, 0xf0, 0xaa, 0x5a, 0xc3, 0x0a, 0x7e, 0xa9, 0x89, 0x6d, 0xa7, 0xcd, 0x25, 0xf3, 0xc3, - 0x30, 0x68, 0x6c, 0x6d, 0x89, 0x23, 0xed, 0x98, 0xc2, 0x4b, 0xa4, 0xcb, 0x75, 0xad, 0xa1, 0xb1, - 0xdb, 0x60, 0x31, 0x85, 0x15, 0xd0, 0x34, 0x0c, 0x57, 0x8c, 0xa6, 0xce, 0x3d, 0x2e, 0x13, 0x13, - 0x1f, 0x54, 0x69, 0xea, 0xcc, 0xe3, 0xe4, 0xa7, 0x21, 0xc5, 0xda, 0xe3, 0x33, 0xee, 0x51, 0x48, - 0xd0, 0xeb, 0x54, 0x5e, 0xab, 0x43, 0xa4, 0x7c, 0x99, 0x5d, 0x48, 0x67, 0x5c, 0x58, 0xc3, 0xac, - 0x50, 0x28, 0x74, 0x54, 0xe5, 0xc9, 0xde, 0xa1, 0x81, 0x29, 0xca, 0x55, 0xe3, 0x6f, 0xc4, 0xe1, - 0x10, 0x3f, 0xa1, 0x53, 0x4d, 0xed, 0xcc, 0xb6, 0xe3, 0x88, 0x97, 0x11, 0xc0, 0x53, 0x5d, 0xd5, - 0xd4, 0xe4, 0x3d, 0x88, 0x5d, 0x72, 0x1c, 0x13, 0x9d, 0x82, 0xb8, 0xd5, 0xac, 0x63, 0xb1, 0xe3, - 0xe3, 0xee, 0xc9, 0xab, 0xa6, 0x36, 0x4b, 0x10, 0x94, 0x66, 0x1d, 0x2b, 0x0c, 0x05, 0x95, 0x60, - 0x7a, 0xab, 0x59, 0xaf, 0xef, 0x95, 0xab, 0x98, 0xfe, 0x2f, 0x2c, 0xf7, 0xbf, 0x49, 0xe0, 0x5d, - 0x53, 0x15, 0xdf, 0xa4, 0x24, 0xba, 0x39, 0x4e, 0xd1, 0x8a, 0x14, 0x4b, 0xfc, 0x27, 0x89, 0x92, - 0xc0, 0x91, 0x7f, 0x2f, 0x02, 0x09, 0xc1, 0x9a, 0xde, 0x10, 0xc7, 0x75, 0x5c, 0x71, 0x0c, 0x71, - 0x62, 0xe2, 0x96, 0x11, 0x82, 0x68, 0x8d, 0x0f, 0x51, 0xf2, 0xd2, 0x80, 0x42, 0x0a, 0x04, 0xe6, - 0xde, 0xdb, 0x27, 0x30, 0xb3, 0x49, 0x46, 0x2d, 0x66, 0x1a, 0x62, 0x69, 0x76, 0x69, 0x40, 0xa1, - 0x25, 0x94, 0x81, 0x41, 0xe2, 0x19, 0x0e, 0xfb, 0xd0, 0x27, 0x81, 0xf3, 0x32, 0x3a, 0x0c, 0x71, - 0x53, 0x75, 0x2a, 0xec, 0x4a, 0x1d, 0xa9, 0x60, 0x45, 0xf4, 0x38, 0x0c, 0xb2, 0x07, 0xd6, 0xe1, - 0x7f, 0x34, 0x43, 0x94, 0xc1, 0xbe, 0x64, 0x47, 0xe4, 0x5e, 0x55, 0x1d, 0x07, 0x5b, 0x3a, 0x61, - 0xc8, 0xd0, 0x11, 0x82, 0xd8, 0xa6, 0x51, 0xdd, 0xe3, 0xff, 0xfc, 0x86, 0xfe, 0xe6, 0xff, 0x6d, - 0x83, 0xda, 0x43, 0x99, 0x56, 0xb2, 0xff, 0xf9, 0x95, 0x12, 0xc0, 0x02, 0x41, 0x2a, 0xc1, 0x84, - 0x5a, 0xad, 0x6a, 0xec, 0xff, 0xd0, 0x94, 0x37, 0x35, 0x1a, 0x21, 0x6c, 0xfa, 0x1f, 0xdd, 0x3a, - 0x8d, 0x05, 0xf2, 0x08, 0x0a, 0x1c, 0xbf, 0x90, 0x84, 0x21, 0x93, 0x09, 0x25, 0x5f, 0x80, 0xf1, - 0x16, 0x49, 0x89, 0x7c, 0x3b, 0x9a, 0x5e, 0x15, 0x8f, 0x19, 0xc8, 0x6f, 0x02, 0xa3, 0x5f, 0xa3, - 0x64, 0x67, 0x51, 0xf4, 0x77, 0xe1, 0xdd, 0x9d, 0x1f, 0xbb, 0x8c, 0xfa, 0x1e, 0xbb, 0xa8, 0xa6, - 0x56, 0x48, 0x52, 0xfe, 0xfc, 0x89, 0x4b, 0x9e, 0x57, 0xb0, 0xe7, 0x2d, 0xb3, 0x86, 0x55, 0x23, - 0xb3, 0xb4, 0x98, 0x7d, 0x49, 0x95, 0x6a, 0x6a, 0x36, 0x35, 0x47, 0xef, 0xeb, 0x98, 0xf6, 0x05, - 0xdf, 0x6f, 0xfa, 0xf0, 0x25, 0x36, 0x9f, 0x5f, 0x5d, 0x70, 0xed, 0xf8, 0xcb, 0x11, 0x38, 0xee, - 0xb3, 0x63, 0x1f, 0x72, 0xab, 0x39, 0x67, 0xdb, 0x5b, 0x7c, 0x1f, 0xcf, 0x8c, 0x2f, 0x43, 0x8c, - 0xe0, 0xa3, 0x1e, 0xff, 0x0b, 0x23, 0xf3, 0x2b, 0x5f, 0xfb, 0x27, 0x72, 0xf0, 0xd4, 0x2a, 0x30, - 0x2a, 0x94, 0x49, 0xe1, 0x7d, 0xfd, 0xeb, 0x2f, 0xed, 0x7d, 0x18, 0xd4, 0xbe, 0x7d, 0x6a, 0x0c, - 0xeb, 0xf0, 0xdb, 0xe7, 0x3a, 0x3e, 0x43, 0x65, 0x11, 0xb3, 0x7b, 0x12, 0xb5, 0x8f, 0x70, 0xdc, - 0xe9, 0xfe, 0x7f, 0xb7, 0x11, 0xec, 0x33, 0x1d, 0xdb, 0x85, 0xc3, 0xcf, 0x92, 0xb6, 0xbd, 0x65, - 0xb2, 0x08, 0xec, 0x87, 0xdd, 0xd3, 0x3c, 0x89, 0xff, 0x43, 0x3d, 0x71, 0x52, 0x07, 0x9e, 0x7c, - 0x7c, 0x81, 0x78, 0xdf, 0x6c, 0xc7, 0xf9, 0x62, 0xd6, 0x37, 0x59, 0x28, 0x3e, 0x4a, 0xf9, 0x97, - 0x24, 0x38, 0xd2, 0xd2, 0x34, 0x8f, 0xf1, 0xf3, 0x6d, 0x9e, 0x2a, 0x1c, 0x28, 0xb3, 0x99, 0x6f, - 0x23, 0xec, 0xfd, 0x3d, 0x85, 0x65, 0x52, 0x04, 0xa4, 0x7d, 0x0a, 0x0e, 0x05, 0x85, 0x15, 0x6a, - 0xba, 0x17, 0x46, 0x83, 0x3b, 0xc2, 0x5c, 0x5d, 0x23, 0x81, 0x3d, 0x61, 0xb9, 0x1c, 0xd6, 0xb3, - 0xdb, 0xd7, 0x12, 0x24, 0x5d, 0x54, 0x9e, 0x02, 0xf7, 0xdd, 0x55, 0x8f, 0x52, 0xfe, 0xb0, 0x04, - 0x33, 0xc1, 0x16, 0x7c, 0xc9, 0xd0, 0xfe, 0x84, 0xbd, 0x6d, 0x43, 0xfc, 0xba, 0x04, 0x77, 0x75, - 0x91, 0x89, 0x2b, 0xe0, 0x65, 0x98, 0xf4, 0xed, 0x04, 0x88, 0x10, 0x2e, 0x86, 0xfd, 0x54, 0xef, - 0x34, 0xd4, 0x5d, 0xf8, 0x1e, 0x23, 0x4a, 0xf9, 0xec, 0x37, 0xa7, 0x27, 0x5a, 0xeb, 0x6c, 0x65, - 0xa2, 0x75, 0xf5, 0x7e, 0x1b, 0xed, 0xe3, 0x55, 0x09, 0x1e, 0x08, 0x76, 0xb5, 0x4d, 0x3e, 0xfb, - 0xa3, 0x1a, 0x87, 0xff, 0x20, 0xc1, 0xa9, 0x7e, 0x84, 0xe3, 0x03, 0xb2, 0x09, 0x13, 0x5e, 0xa6, - 0x1d, 0x1e, 0x8f, 0x7d, 0xe5, 0xef, 0xcc, 0x4a, 0x91, 0xcb, 0xed, 0x0e, 0x28, 0xde, 0xe4, 0x8e, - 0xe5, 0x1f, 0x72, 0x57, 0xc9, 0xc1, 0xdd, 0x5c, 0xa1, 0xe4, 0xc0, 0x7e, 0x6e, 0x9b, 0xb1, 0x88, - 0xb4, 0x19, 0x0b, 0x2f, 0x35, 0x97, 0xaf, 0xf2, 0xb8, 0xd5, 0x66, 0x0f, 0xee, 0x6d, 0x30, 0xd1, - 0xc6, 0x94, 0xb9, 0x57, 0xef, 0xc3, 0x92, 0x15, 0xd4, 0x6a, 0xac, 0xf2, 0x1e, 0x4c, 0xd3, 0x76, - 0xdb, 0x28, 0xfa, 0x4e, 0x77, 0xb9, 0xc1, 0x63, 0x4b, 0xdb, 0xa6, 0x79, 0xdf, 0x17, 0x60, 0x90, - 0x8d, 0x33, 0xef, 0xee, 0x01, 0x0c, 0x85, 0x33, 0x90, 0x7f, 0x4e, 0xc4, 0xb2, 0xa2, 0x10, 0xbb, - 0xbd, 0x0f, 0xf5, 0xd3, 0xd7, 0xdb, 0xe4, 0x43, 0x3e, 0x65, 0x7c, 0x43, 0x44, 0xb5, 0xf6, 0xd2, - 0x71, 0x75, 0x54, 0x6e, 0x5b, 0x54, 0x63, 0xba, 0xb9, 0xb3, 0xe1, 0xeb, 0x17, 0x44, 0xf8, 0x72, - 0xfb, 0xd4, 0x23, 0x7c, 0xfd, 0x68, 0x54, 0xef, 0x06, 0xb2, 0x1e, 0x62, 0xfe, 0x59, 0x0c, 0x64, - 0xdf, 0x93, 0xe0, 0x28, 0xed, 0x9b, 0x7f, 0x23, 0x62, 0xbf, 0x2a, 0x7f, 0x08, 0x90, 0x6d, 0x55, - 0xca, 0x6d, 0xbd, 0x3b, 0x6d, 0x5b, 0x95, 0x2b, 0x81, 0xf9, 0xe5, 0x21, 0x40, 0xd5, 0xc0, 0x76, - 0x13, 0xc5, 0x66, 0xb7, 0xe4, 0xd2, 0x55, 0xdf, 0x6e, 0x46, 0x9b, 0xe1, 0x8c, 0xdd, 0x86, 0xe1, - 0xfc, 0xba, 0x04, 0xd9, 0x76, 0x5d, 0xe6, 0xc3, 0xa7, 0xc1, 0xe1, 0xc0, 0x21, 0x41, 0x78, 0x04, - 0x1f, 0xea, 0x67, 0x2b, 0x27, 0xe4, 0x46, 0x87, 0x2c, 0x7c, 0xa7, 0xf3, 0x80, 0xe9, 0xa0, 0x85, - 0xb6, 0x66, 0xd6, 0x3f, 0x32, 0xf7, 0xf9, 0x42, 0x4b, 0x5c, 0xfd, 0x33, 0x91, 0x7b, 0xef, 0xc2, - 0x54, 0x07, 0xa9, 0xef, 0xf4, 0xbc, 0xb7, 0xdd, 0x71, 0x30, 0x6f, 0x77, 0xfa, 0xfe, 0x18, 0xf7, - 0x84, 0xe0, 0x0d, 0x6c, 0xdf, 0x5a, 0xac, 0xdd, 0x13, 0x2e, 0xf9, 0xad, 0x70, 0xac, 0x2d, 0x15, - 0x97, 0x2d, 0x07, 0xb1, 0x6d, 0xcd, 0x76, 0xb8, 0x58, 0xf7, 0x75, 0x12, 0x2b, 0x44, 0x4d, 0x69, - 0x64, 0x04, 0x69, 0xca, 0x7a, 0xd5, 0x30, 0xea, 0x5c, 0x0c, 0xf9, 0x32, 0x8c, 0xfb, 0x60, 0xbc, - 0x91, 0xf3, 0x10, 0x33, 0x0d, 0xfe, 0x79, 0x82, 0xe1, 0xb3, 0xc7, 0x3b, 0xee, 0xde, 0x1b, 0x46, - 0x9d, 0x77, 0x9b, 0xe2, 0xcb, 0x93, 0x80, 0x18, 0x33, 0xba, 0x91, 0x2f, 0x9a, 0x58, 0x83, 0x89, - 0x00, 0x94, 0x37, 0xf2, 0x86, 0x0e, 0x09, 0xce, 0x7e, 0xe7, 0x10, 0xc4, 0x29, 0x57, 0xf4, 0x31, - 0x29, 0xf0, 0x95, 0xa0, 0xd9, 0x4e, 0x6c, 0xda, 0xaf, 0x89, 0xb3, 0x67, 0xfa, 0xc6, 0xe7, 0x39, - 0xdb, 0xa9, 0x77, 0xff, 0xdb, 0x6f, 0x7f, 0x24, 0x72, 0x0f, 0x92, 0xcf, 0x74, 0x58, 0x8d, 0xfb, - 0xfc, 0xe5, 0x33, 0x81, 0xb7, 0xef, 0xa7, 0xfb, 0x6b, 0x4a, 0x48, 0x36, 0xdb, 0x2f, 0x3a, 0x17, - 0xec, 0x02, 0x15, 0xec, 0x1c, 0x7a, 0xb4, 0xb7, 0x60, 0x67, 0xde, 0x11, 0x74, 0x9a, 0x77, 0xa1, - 0xdf, 0x91, 0x60, 0xb2, 0xdd, 0x92, 0x0e, 0x3d, 0xd1, 0x9f, 0x14, 0xad, 0x29, 0x45, 0xf6, 0xc9, - 0x03, 0x50, 0xf2, 0xae, 0xcc, 0xd3, 0xae, 0xe4, 0xd1, 0xd3, 0x07, 0xe8, 0xca, 0x19, 0xff, 0xfe, - 0xfe, 0xff, 0x96, 0xe0, 0x44, 0xd7, 0x15, 0x12, 0xca, 0xf7, 0x27, 0x65, 0x97, 0xdc, 0x29, 0x5b, - 0x78, 0x23, 0x2c, 0x78, 0x8f, 0x9f, 0xa5, 0x3d, 0xbe, 0x8c, 0x16, 0x0e, 0xd2, 0xe3, 0xb6, 0x87, - 0x28, 0xe8, 0x37, 0x83, 0x37, 0x0b, 0xbb, 0x9b, 0x53, 0xcb, 0xc2, 0xa3, 0x87, 0x63, 0xb4, 0x26, - 0xb5, 0xf2, 0xf3, 0xb4, 0x0b, 0x0a, 0x5a, 0x7d, 0x83, 0x83, 0x76, 0xe6, 0x1d, 0xc1, 0xc0, 0xff, - 0x2e, 0xf4, 0xbf, 0xa4, 0xf6, 0x17, 0x05, 0x1f, 0xef, 0x2a, 0x62, 0xe7, 0x45, 0x55, 0xf6, 0x89, - 0xfd, 0x13, 0xf2, 0x4e, 0x36, 0x68, 0x27, 0x6b, 0x08, 0xdf, 0xee, 0x4e, 0xb6, 0x1d, 0x44, 0xf4, - 0x55, 0x09, 0x26, 0xdb, 0xad, 0x49, 0x7a, 0xb8, 0x65, 0x97, 0x45, 0x56, 0x0f, 0xb7, 0xec, 0xb6, - 0x00, 0x92, 0xdf, 0x44, 0x3b, 0x7f, 0x1e, 0x3d, 0xd6, 0xa9, 0xf3, 0x5d, 0x47, 0x91, 0xf8, 0x62, - 0xd7, 0x24, 0xbf, 0x87, 0x2f, 0xf6, 0xb3, 0x8e, 0xe9, 0xe1, 0x8b, 0x7d, 0xad, 0x31, 0x7a, 0xfb, - 0xa2, 0xdb, 0xb3, 0x3e, 0x87, 0xd1, 0x46, 0x5f, 0x96, 0x60, 0x24, 0x90, 0x11, 0xa3, 0x47, 0xba, - 0x0a, 0xda, 0x6e, 0xc1, 0x90, 0x3d, 0xbb, 0x1f, 0x12, 0xde, 0x97, 0x05, 0xda, 0x97, 0x39, 0x94, - 0x3f, 0x48, 0x5f, 0x82, 0x67, 0xa5, 0x5f, 0x97, 0x60, 0xa2, 0x4d, 0x96, 0xd9, 0xc3, 0x0b, 0x3b, - 0x27, 0xcd, 0xd9, 0x27, 0xf6, 0x4f, 0xc8, 0x7b, 0x75, 0x91, 0xf6, 0xea, 0x2d, 0xe8, 0xa9, 0x83, - 0xf4, 0xca, 0x37, 0x3f, 0xdf, 0xf4, 0xee, 0x5d, 0xf9, 0xda, 0x41, 0xe7, 0xf7, 0x29, 0x98, 0xe8, - 0xd0, 0xe3, 0xfb, 0xa6, 0xe3, 0xfd, 0x79, 0x8e, 0xf6, 0xe7, 0x59, 0xb4, 0xf2, 0xc6, 0xfa, 0xd3, - 0x3a, 0xad, 0x7f, 0xbe, 0xf5, 0x05, 0x60, 0x77, 0x2b, 0x6a, 0x9b, 0xac, 0x66, 0x1f, 0xdd, 0x17, - 0x0d, 0xef, 0xd4, 0x13, 0xb4, 0x53, 0x67, 0xd1, 0xc3, 0x9d, 0x3a, 0xe5, 0xbb, 0x5c, 0xa7, 0xe9, - 0x5b, 0xc6, 0x99, 0x77, 0xb0, 0x14, 0xf8, 0x5d, 0xe8, 0x27, 0xc5, 0xc5, 0xa6, 0x93, 0x5d, 0xdb, - 0xf5, 0xe5, 0xb1, 0xd9, 0x07, 0xfa, 0xc0, 0xe4, 0x72, 0xdd, 0x43, 0xe5, 0x9a, 0x42, 0xc7, 0x3b, - 0xc9, 0x45, 0x72, 0x59, 0xf4, 0x01, 0xc9, 0xbd, 0x0b, 0x79, 0xaa, 0x3b, 0x6f, 0x7f, 0xb2, 0x9b, - 0x7d, 0xb0, 0x2f, 0x5c, 0x2e, 0xc9, 0x7d, 0x54, 0x92, 0x19, 0x34, 0xd5, 0x51, 0x12, 0x96, 0xfa, - 0xde, 0xee, 0x9b, 0x03, 0xd7, 0x8f, 0xc0, 0x74, 0x87, 0x16, 0x9d, 0xdd, 0x1e, 0x67, 0x5c, 0x5d, - 0x1e, 0xc2, 0xf6, 0x7c, 0xe8, 0x7a, 0xbb, 0x3f, 0xd3, 0xda, 0xe7, 0x81, 0xd8, 0x6f, 0xc5, 0x00, - 0x2d, 0xd9, 0xb5, 0x39, 0x0b, 0xb3, 0x7f, 0x22, 0xc9, 0xbd, 0x3c, 0xf4, 0xc2, 0x4b, 0x7a, 0x43, - 0x2f, 0xbc, 0x96, 0x02, 0x6f, 0xa6, 0x22, 0xfb, 0x7b, 0x97, 0xd9, 0xf7, 0xc3, 0xa9, 0xe8, 0x0f, - 0xe5, 0xe1, 0x54, 0xfb, 0x7b, 0xd5, 0xb1, 0xdb, 0xf7, 0x00, 0x23, 0x7e, 0xd0, 0x47, 0x28, 0xfc, - 0x3d, 0xe4, 0x60, 0x97, 0xf7, 0x90, 0x99, 0x8e, 0x8f, 0x1e, 0x39, 0x35, 0x3a, 0x27, 0x3e, 0x5a, - 0x3a, 0xd4, 0xdf, 0x4d, 0x58, 0xfe, 0x55, 0x53, 0x6f, 0x0b, 0xe1, 0x38, 0x64, 0x5b, 0xcd, 0xc9, - 0x75, 0xea, 0x8f, 0x44, 0x21, 0xbd, 0x64, 0xd7, 0x4a, 0x55, 0xcd, 0xb9, 0x43, 0xb6, 0xf6, 0x74, - 0xe7, 0x47, 0x2d, 0xe8, 0xd6, 0xcd, 0xe9, 0x51, 0xa6, 0xd3, 0x2e, 0x9a, 0x6c, 0xc0, 0x58, 0xe8, - 0x29, 0x31, 0xb7, 0xac, 0xe2, 0x41, 0x5e, 0x34, 0x87, 0x58, 0xc9, 0xf4, 0x0d, 0x82, 0xcf, 0xbe, - 0xd1, 0x6e, 0x7b, 0x63, 0x66, 0x06, 0x75, 0xe9, 0x4e, 0xbe, 0x00, 0xf4, 0xc6, 0x2c, 0x0b, 0x99, - 0xf0, 0xa0, 0xb8, 0x23, 0xf6, 0x07, 0x12, 0x0c, 0x2f, 0xd9, 0x22, 0x15, 0xc4, 0x3f, 0xa6, 0xef, - 0x8f, 0x1e, 0x77, 0xbf, 0xf8, 0x1d, 0xed, 0xcf, 0x6e, 0xc5, 0x57, 0xc0, 0x3d, 0x25, 0x1c, 0x82, - 0x09, 0x5f, 0x3f, 0xdd, 0xfe, 0xff, 0x76, 0x84, 0xc6, 0xc7, 0x02, 0xae, 0x69, 0xba, 0x9b, 0x45, - 0xe2, 0x3f, 0xaf, 0xaf, 0x2b, 0x3c, 0x3d, 0xc7, 0x0e, 0xaa, 0xe7, 0x1d, 0x1a, 0x20, 0x42, 0xfa, - 0x74, 0x37, 0xbe, 0x96, 0x5a, 0xdf, 0xfe, 0x48, 0xfb, 0xf8, 0xac, 0x4e, 0xe8, 0x85, 0x8f, 0xfc, - 0xba, 0x04, 0x23, 0x4b, 0x76, 0x6d, 0x43, 0xaf, 0xfe, 0x7f, 0x6f, 0xbf, 0x5b, 0x70, 0x28, 0xd0, - 0xd3, 0x3b, 0xa4, 0xd2, 0xb3, 0xaf, 0xc6, 0x20, 0xba, 0x64, 0xd7, 0xd0, 0x4b, 0x30, 0x16, 0x4e, - 0x1a, 0x3a, 0xe6, 0x82, 0xad, 0x33, 0x42, 0xe7, 0xf5, 0x5a, 0xe7, 0xd9, 0x03, 0xed, 0xc0, 0x48, - 0x70, 0xe6, 0x38, 0xd9, 0x85, 0x49, 0x00, 0x33, 0xfb, 0x70, 0xbf, 0x98, 0x6e, 0x63, 0x6f, 0x87, - 0x84, 0x1b, 0xf4, 0xee, 0xee, 0x42, 0x2d, 0x90, 0x3a, 0x67, 0xb7, 0x6d, 0xc2, 0x0a, 0xd1, 0x5e, - 0x38, 0xa4, 0x74, 0xd3, 0x5e, 0x08, 0xb7, 0xab, 0xf6, 0x3a, 0xb9, 0xd6, 0x26, 0x80, 0xcf, 0x0f, - 0xee, 0xed, 0xc2, 0xc1, 0x43, 0xcb, 0x9e, 0xee, 0x0b, 0xcd, 0x3d, 0x74, 0xba, 0xcd, 0xc9, 0xf8, - 0xff, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x80, 0x38, 0xe7, 0x40, 0xba, 0x97, 0x00, 0x00, + 0xc1, 0xf5, 0x8c, 0x4c, 0x83, 0xc6, 0xe9, 0xee, 0x59, 0xf2, 0xec, 0x82, 0x47, 0xb7, 0x48, 0xc8, + 0x72, 0x13, 0x0b, 0xc5, 0xd2, 0xd2, 0xea, 0xca, 0x7a, 0x69, 0x79, 0xee, 0x6d, 0xe5, 0x8d, 0xe5, + 0x4b, 0xcb, 0x2b, 0xcf, 0x2d, 0x2b, 0x69, 0x2d, 0x84, 0x76, 0x07, 0x87, 0xfd, 0x2a, 0xa4, 0xc3, + 0x42, 0xa1, 0x23, 0xd0, 0x4e, 0xac, 0xf4, 0x00, 0x9a, 0x80, 0xb1, 0xe5, 0x95, 0xf2, 0xda, 0x42, + 0xb1, 0x54, 0x2e, 0x5d, 0xb8, 0x50, 0x9a, 0x5b, 0x5f, 0x63, 0xfb, 0x1e, 0x2e, 0xf6, 0x7a, 0x60, + 0x80, 0xcb, 0xaf, 0x44, 0x61, 0xa2, 0x8d, 0x24, 0x28, 0xcf, 0x57, 0x2c, 0x6c, 0x11, 0xf5, 0x70, + 0x3f, 0xd2, 0xcf, 0x92, 0x9c, 0x61, 0x55, 0xb5, 0x1c, 0xbe, 0xc0, 0x79, 0x00, 0x88, 0x95, 0x74, + 0x47, 0xdb, 0xd2, 0xb0, 0xc5, 0xf7, 0x93, 0xd8, 0x32, 0x66, 0xcc, 0x83, 0xb3, 0x2d, 0xa5, 0x87, + 0x00, 0x99, 0x86, 0xad, 0x39, 0xda, 0x15, 0x5c, 0xd6, 0x74, 0xb1, 0xf9, 0x44, 0x96, 0x35, 0x31, + 0x25, 0x2d, 0x6a, 0x16, 0x74, 0xc7, 0xc5, 0xd6, 0x71, 0x4d, 0x0d, 0x61, 0x93, 0x60, 0x1e, 0x55, + 0xd2, 0xa2, 0xc6, 0xc5, 0xbe, 0x0b, 0x52, 0x55, 0xa3, 0x49, 0x72, 0x3d, 0x86, 0x47, 0xe6, 0x0e, + 0x49, 0x19, 0x66, 0x30, 0x17, 0x85, 0x67, 0xf1, 0xde, 0xae, 0x57, 0x4a, 0x19, 0x66, 0x30, 0x86, + 0x72, 0x3f, 0x8c, 0xa9, 0xb5, 0x9a, 0x45, 0x98, 0x0b, 0x46, 0x6c, 0x5d, 0x32, 0xea, 0x82, 0x29, + 0x62, 0xf6, 0x19, 0x48, 0x08, 0x3b, 0x90, 0xa9, 0x9a, 0x58, 0xa2, 0x6c, 0xb2, 0xc5, 0x76, 0xe4, + 0x64, 0x52, 0x49, 0xe8, 0xa2, 0xf2, 0x2e, 0x48, 0x69, 0x76, 0xd9, 0xdb, 0xc4, 0x8f, 0xcc, 0x44, + 0x4e, 0x26, 0x94, 0x61, 0xcd, 0x76, 0x37, 0x40, 0xe5, 0xcf, 0x46, 0x60, 0x34, 0x78, 0x08, 0x81, + 0x8a, 0x90, 0xa8, 0x1b, 0x15, 0x95, 0xba, 0x16, 0x3b, 0x01, 0x3b, 0xd9, 0xe3, 0xdc, 0x62, 0x76, + 0x91, 0xe3, 0x2b, 0x2e, 0x65, 0xf6, 0xb7, 0x25, 0x48, 0x08, 0x30, 0x3a, 0x0c, 0x31, 0x53, 0x75, + 0xb6, 0x29, 0xbb, 0x78, 0x21, 0x92, 0x96, 0x14, 0x5a, 0x26, 0x70, 0xdb, 0x54, 0x75, 0xea, 0x02, + 0x1c, 0x4e, 0xca, 0xa4, 0x5f, 0xeb, 0x58, 0xad, 0xd2, 0x45, 0x8f, 0xd1, 0x68, 0x60, 0xdd, 0xb1, + 0x45, 0xbf, 0x72, 0xf8, 0x1c, 0x07, 0xa3, 0x07, 0x61, 0xdc, 0xb1, 0x54, 0xad, 0x1e, 0xc0, 0x8d, + 0x51, 0xdc, 0xb4, 0xa8, 0x70, 0x91, 0x73, 0x70, 0x54, 0xf0, 0xad, 0x62, 0x47, 0xad, 0x6c, 0xe3, + 0xaa, 0x47, 0x34, 0x48, 0x37, 0x37, 0x8e, 0x70, 0x84, 0x22, 0xaf, 0x17, 0xb4, 0xf2, 0xb7, 0x24, + 0x18, 0x17, 0xcb, 0xb4, 0xaa, 0x6b, 0xac, 0x25, 0x00, 0x55, 0xd7, 0x0d, 0xc7, 0x6f, 0xae, 0x56, + 0x57, 0x6e, 0xa1, 0x9b, 0xcd, 0xbb, 0x44, 0x8a, 0x8f, 0x41, 0xb6, 0x01, 0xe0, 0xd5, 0x74, 0x34, + 0xdb, 0x34, 0x0c, 0xf3, 0x13, 0x26, 0x7a, 0x4c, 0xc9, 0x16, 0xf6, 0xc0, 0x40, 0x64, 0x3d, 0x87, + 0x26, 0x21, 0xbe, 0x89, 0x6b, 0x9a, 0xce, 0xf7, 0x8d, 0x59, 0x41, 0x6c, 0xbf, 0xc4, 0xdc, 0xed, + 0x97, 0xc2, 0x5f, 0x86, 0x89, 0x8a, 0xd1, 0x08, 0x8b, 0x5b, 0x48, 0x87, 0x36, 0x17, 0xec, 0x8b, + 0xd2, 0x0b, 0x0f, 0x73, 0xa4, 0x9a, 0x51, 0x57, 0xf5, 0xda, 0xac, 0x61, 0xd5, 0xbc, 0x63, 0x56, + 0x92, 0xf1, 0xd8, 0xbe, 0xc3, 0x56, 0x73, 0xf3, 0x4f, 0x25, 0xe9, 0x17, 0x22, 0xd1, 0xf9, 0xd5, + 0xc2, 0xe7, 0x22, 0xd9, 0x79, 0x46, 0xb8, 0x2a, 0x8c, 0xa1, 0xe0, 0xad, 0x3a, 0xae, 0x10, 0x05, + 0xe1, 0x7b, 0x0f, 0xc2, 0x64, 0xcd, 0xa8, 0x19, 0x94, 0xd3, 0x69, 0xf2, 0x8b, 0x9f, 0xd3, 0x26, + 0x5d, 0x68, 0xb6, 0xe7, 0xa1, 0x6e, 0x6e, 0x19, 0x26, 0x38, 0x72, 0x99, 0x1e, 0x14, 0xb1, 0x65, + 0x0c, 0xea, 0xba, 0x87, 0x96, 0xf9, 0xc2, 0x77, 0xe9, 0xf4, 0xad, 0x8c, 0x73, 0x52, 0x52, 0xc7, + 0x56, 0x3a, 0x39, 0x05, 0x0e, 0x05, 0xf8, 0xb1, 0x41, 0x8a, 0xad, 0x1e, 0x1c, 0x7f, 0x83, 0x73, + 0x9c, 0xf0, 0x71, 0x5c, 0xe3, 0xa4, 0xb9, 0x39, 0x18, 0xd9, 0x0f, 0xaf, 0x7f, 0xc9, 0x79, 0xa5, + 0xb0, 0x9f, 0xc9, 0x3c, 0x8c, 0x51, 0x26, 0x95, 0xa6, 0xed, 0x18, 0x0d, 0x1a, 0x01, 0xbb, 0xb3, + 0xf9, 0xcd, 0xef, 0xb2, 0x51, 0x33, 0x4a, 0xc8, 0xe6, 0x5c, 0xaa, 0x5c, 0x0e, 0xe8, 0xd9, 0x58, + 0x15, 0x57, 0xea, 0x3d, 0x38, 0x7c, 0x8d, 0x0b, 0xe2, 0xe2, 0xe7, 0x2e, 0xc3, 0x24, 0xf9, 0x4d, + 0x03, 0x94, 0x5f, 0x92, 0xde, 0x1b, 0x6e, 0x99, 0x6f, 0xbd, 0x97, 0x0d, 0xcc, 0x09, 0x97, 0x81, + 0x4f, 0x26, 0x5f, 0x2f, 0xd6, 0xb0, 0xe3, 0x60, 0xcb, 0x2e, 0xab, 0xf5, 0x76, 0xe2, 0xf9, 0x76, + 0x2c, 0x32, 0x1f, 0xfb, 0x7e, 0xb0, 0x17, 0xe7, 0x19, 0x65, 0xbe, 0x5e, 0xcf, 0x6d, 0xc0, 0x91, + 0x36, 0x5e, 0xd1, 0x07, 0xcf, 0x57, 0x38, 0xcf, 0xc9, 0x16, 0xcf, 0x20, 0x6c, 0x57, 0x41, 0xc0, + 0xdd, 0xbe, 0xec, 0x83, 0xe7, 0xc7, 0x39, 0x4f, 0xc4, 0x69, 0x45, 0x97, 0x12, 0x8e, 0xcf, 0xc0, + 0xf8, 0x15, 0x6c, 0x6d, 0x1a, 0x36, 0xdf, 0x25, 0xea, 0x83, 0xdd, 0x27, 0x38, 0xbb, 0x31, 0x4e, + 0x48, 0xb7, 0x8d, 0x08, 0xaf, 0xa7, 0x20, 0xb1, 0xa5, 0x56, 0x70, 0x1f, 0x2c, 0x6e, 0x70, 0x16, + 0x43, 0x04, 0x9f, 0x90, 0xe6, 0x21, 0x55, 0x33, 0xf8, 0x1c, 0xd5, 0x9b, 0xfc, 0x93, 0x9c, 0x7c, + 0x58, 0xd0, 0x70, 0x16, 0xa6, 0x61, 0x36, 0xeb, 0x64, 0x02, 0xeb, 0xcd, 0xe2, 0x6f, 0x09, 0x16, + 0x82, 0x86, 0xb3, 0xd8, 0x87, 0x59, 0x3f, 0x25, 0x58, 0xd8, 0x3e, 0x7b, 0x3e, 0x0d, 0xc3, 0x86, + 0x5e, 0xdf, 0x33, 0xf4, 0x7e, 0x84, 0xf8, 0x34, 0xe7, 0x00, 0x9c, 0x84, 0x30, 0x38, 0x0f, 0xc9, + 0x7e, 0x3b, 0xe2, 0x6f, 0x7f, 0x5f, 0x0c, 0x0f, 0xd1, 0x03, 0xf3, 0x30, 0x26, 0x02, 0x94, 0x66, + 0xe8, 0x7d, 0xb0, 0xf8, 0x3b, 0x9c, 0xc5, 0xa8, 0x8f, 0x8c, 0xab, 0xe1, 0x60, 0xdb, 0xa9, 0xe1, + 0x7e, 0x98, 0x7c, 0x56, 0xa8, 0xc1, 0x49, 0xb8, 0x29, 0x37, 0xb1, 0x5e, 0xd9, 0xee, 0x8f, 0xc3, + 0x2f, 0x09, 0x53, 0x0a, 0x1a, 0xc2, 0x62, 0x0e, 0x46, 0x1a, 0xaa, 0x65, 0x6f, 0xab, 0xf5, 0xbe, + 0xba, 0xe3, 0xef, 0x72, 0x1e, 0x29, 0x97, 0x88, 0x5b, 0xa4, 0xa9, 0xef, 0x87, 0xcd, 0xe7, 0x84, + 0x45, 0x7c, 0x64, 0x7c, 0xe8, 0xd9, 0x0e, 0xdd, 0x52, 0xdb, 0x0f, 0xb7, 0x5f, 0x16, 0x43, 0x8f, + 0xd1, 0x2e, 0xf9, 0x39, 0x9e, 0x87, 0xa4, 0xad, 0x5d, 0xeb, 0x8b, 0xcd, 0xe7, 0x45, 0x4f, 0x53, + 0x02, 0x42, 0xfc, 0x36, 0x38, 0xda, 0x76, 0x9a, 0xe8, 0x83, 0xd9, 0xdf, 0xe3, 0xcc, 0x0e, 0xb7, + 0x99, 0x2a, 0x78, 0x48, 0xd8, 0x2f, 0xcb, 0xbf, 0x2f, 0x42, 0x02, 0x0e, 0xf1, 0x5a, 0x25, 0xab, + 0x06, 0x5b, 0xdd, 0xda, 0x9f, 0xd5, 0x7e, 0x45, 0x58, 0x8d, 0xd1, 0x06, 0xac, 0xb6, 0x0e, 0x87, + 0x39, 0xc7, 0xfd, 0xf5, 0xeb, 0xaf, 0x8a, 0xc0, 0xca, 0xa8, 0x37, 0x82, 0xbd, 0xfb, 0x76, 0xc8, + 0xba, 0xe6, 0x14, 0xe9, 0xa9, 0x5d, 0x6e, 0xa8, 0x66, 0x1f, 0x9c, 0xbf, 0xc0, 0x39, 0x8b, 0x88, + 0xef, 0xe6, 0xb7, 0xf6, 0x92, 0x6a, 0x12, 0xe6, 0xcf, 0x43, 0x46, 0x30, 0x6f, 0xea, 0x16, 0xae, + 0x18, 0x35, 0x5d, 0xbb, 0x86, 0xab, 0x7d, 0xb0, 0xfe, 0xb5, 0x50, 0x57, 0x6d, 0xf8, 0xc8, 0x09, + 0xe7, 0x05, 0x48, 0xbb, 0xb9, 0x4a, 0x59, 0x6b, 0x98, 0x86, 0xe5, 0xf4, 0xe0, 0xf8, 0x45, 0xd1, + 0x53, 0x2e, 0xdd, 0x02, 0x25, 0xcb, 0x95, 0x80, 0x9d, 0x33, 0xf7, 0xeb, 0x92, 0x5f, 0xe2, 0x8c, + 0x46, 0x3c, 0x2a, 0x1e, 0x38, 0x2a, 0x46, 0xc3, 0x54, 0xad, 0x7e, 0xe2, 0xdf, 0x3f, 0x10, 0x81, + 0x83, 0x93, 0xf0, 0xc0, 0x41, 0x32, 0x3a, 0x32, 0xdb, 0xf7, 0xc1, 0xe1, 0xcb, 0x22, 0x70, 0x08, + 0x1a, 0xce, 0x42, 0x24, 0x0c, 0x7d, 0xb0, 0xf8, 0x87, 0x82, 0x85, 0xa0, 0x21, 0x2c, 0x9e, 0xf5, + 0x26, 0x5a, 0x0b, 0xd7, 0x34, 0xdb, 0xb1, 0x58, 0x52, 0xdc, 0x9d, 0xd5, 0x3f, 0xfa, 0x7e, 0x30, + 0x09, 0x53, 0x7c, 0xa4, 0x24, 0x12, 0xf1, 0x4d, 0x56, 0xba, 0x66, 0xea, 0x2d, 0xd8, 0xaf, 0x8b, + 0x48, 0xe4, 0x23, 0x23, 0xb2, 0xf9, 0x32, 0x44, 0x62, 0xf6, 0x0a, 0x59, 0x29, 0xf4, 0xc1, 0xee, + 0x1f, 0x87, 0x84, 0x5b, 0x13, 0xb4, 0x84, 0xa7, 0x2f, 0xff, 0x69, 0xea, 0x3b, 0x78, 0xaf, 0x2f, + 0xef, 0xfc, 0x27, 0xa1, 0xfc, 0x67, 0x83, 0x51, 0xb2, 0x18, 0x32, 0x16, 0xca, 0xa7, 0x50, 0xaf, + 0x5b, 0x45, 0x99, 0x9f, 0xfe, 0x21, 0xd7, 0x37, 0x98, 0x4e, 0xe5, 0x16, 0x89, 0x93, 0x07, 0x93, + 0x9e, 0xde, 0xcc, 0xde, 0xfb, 0x43, 0xd7, 0xcf, 0x03, 0x39, 0x4f, 0xee, 0x02, 0x8c, 0x04, 0x12, + 0x9e, 0xde, 0xac, 0xde, 0xc7, 0x59, 0xa5, 0xfc, 0xf9, 0x4e, 0xee, 0x2c, 0xc4, 0x48, 0xf2, 0xd2, + 0x9b, 0xfc, 0xaf, 0x70, 0x72, 0x8a, 0x9e, 0x7b, 0x33, 0x24, 0x44, 0xd2, 0xd2, 0x9b, 0xf4, 0xfd, + 0x9c, 0xd4, 0x25, 0x21, 0xe4, 0x22, 0x61, 0xe9, 0x4d, 0xfe, 0x57, 0x05, 0xb9, 0x20, 0x21, 0xe4, + 0xfd, 0x9b, 0xf0, 0x2b, 0x3f, 0x13, 0xe3, 0x93, 0x8e, 0xb0, 0xdd, 0x79, 0x18, 0xe2, 0x99, 0x4a, + 0x6f, 0xea, 0x0f, 0xf2, 0xc6, 0x05, 0x45, 0xee, 0x09, 0x88, 0xf7, 0x69, 0xf0, 0x9f, 0xe5, 0xa4, + 0x0c, 0x3f, 0x37, 0x07, 0xc3, 0xbe, 0xec, 0xa4, 0x37, 0xf9, 0x5f, 0xe3, 0xe4, 0x7e, 0x2a, 0x22, + 0x3a, 0xcf, 0x4e, 0x7a, 0x33, 0xf8, 0x39, 0x21, 0x3a, 0xa7, 0x20, 0x66, 0x13, 0x89, 0x49, 0x6f, + 0xea, 0x0f, 0x09, 0xab, 0x0b, 0x92, 0xdc, 0xd3, 0x90, 0x74, 0x27, 0x9b, 0xde, 0xf4, 0x1f, 0xe6, + 0xf4, 0x1e, 0x0d, 0xb1, 0x80, 0x6f, 0xb2, 0xeb, 0xcd, 0xe2, 0xaf, 0x0b, 0x0b, 0xf8, 0xa8, 0xc8, + 0x30, 0x0a, 0x27, 0x30, 0xbd, 0x39, 0x7d, 0x44, 0x0c, 0xa3, 0x50, 0xfe, 0x42, 0x7a, 0x93, 0xc6, + 0xfc, 0xde, 0x2c, 0xfe, 0x86, 0xe8, 0x4d, 0x8a, 0x4f, 0xc4, 0x08, 0x67, 0x04, 0xbd, 0x79, 0xfc, + 0xbc, 0x10, 0x23, 0x94, 0x10, 0xe4, 0x56, 0x01, 0xb5, 0x66, 0x03, 0xbd, 0xf9, 0x7d, 0x94, 0xf3, + 0x1b, 0x6f, 0x49, 0x06, 0x72, 0xcf, 0xc1, 0xe1, 0xf6, 0x99, 0x40, 0x6f, 0xae, 0x1f, 0xfb, 0x61, + 0x68, 0xed, 0xe6, 0x4f, 0x04, 0x72, 0xeb, 0xde, 0x94, 0xe2, 0xcf, 0x02, 0x7a, 0xb3, 0x7d, 0xe5, + 0x87, 0xc1, 0xc0, 0xed, 0x4f, 0x02, 0x72, 0x79, 0x00, 0x6f, 0x02, 0xee, 0xcd, 0xeb, 0x13, 0x9c, + 0x97, 0x8f, 0x88, 0x0c, 0x0d, 0x3e, 0xff, 0xf6, 0xa6, 0xbf, 0x21, 0x86, 0x06, 0xa7, 0x20, 0x43, + 0x43, 0x4c, 0xbd, 0xbd, 0xa9, 0x3f, 0x29, 0x86, 0x86, 0x20, 0x21, 0x9e, 0xed, 0x9b, 0xdd, 0x7a, + 0x73, 0xf8, 0xb4, 0xf0, 0x6c, 0x1f, 0x55, 0x6e, 0x19, 0xc6, 0x5b, 0x26, 0xc4, 0xde, 0xac, 0x7e, + 0x81, 0xb3, 0x4a, 0x87, 0xe7, 0x43, 0xff, 0xe4, 0xc5, 0x27, 0xc3, 0xde, 0xdc, 0x3e, 0x13, 0x9a, + 0xbc, 0xf8, 0x5c, 0x98, 0x3b, 0x0f, 0x09, 0xbd, 0x59, 0xaf, 0x93, 0xc1, 0x83, 0xba, 0xdf, 0x04, + 0xcc, 0xfc, 0xd7, 0x1f, 0x71, 0xeb, 0x08, 0x82, 0xdc, 0x59, 0x88, 0xe3, 0xc6, 0x26, 0xae, 0xf6, + 0xa2, 0xfc, 0xde, 0x8f, 0x44, 0xc0, 0x24, 0xd8, 0xb9, 0xa7, 0x01, 0xd8, 0xd6, 0x08, 0x3d, 0x0c, + 0xec, 0x41, 0xfb, 0xdf, 0x7e, 0xc4, 0xaf, 0xde, 0x78, 0x24, 0x1e, 0x03, 0x76, 0x91, 0xa7, 0x3b, + 0x83, 0xef, 0x07, 0x19, 0xd0, 0x1e, 0x79, 0x0a, 0x86, 0x5e, 0xb4, 0x0d, 0xdd, 0x51, 0x6b, 0xbd, + 0xa8, 0xff, 0x3b, 0xa7, 0x16, 0xf8, 0xc4, 0x60, 0x0d, 0xc3, 0xc2, 0x8e, 0x5a, 0xb3, 0x7b, 0xd1, + 0xfe, 0x0f, 0x4e, 0xeb, 0x12, 0x10, 0xe2, 0x8a, 0x6a, 0x3b, 0xfd, 0xe8, 0xfd, 0x87, 0x82, 0x58, + 0x10, 0x10, 0xa1, 0xc9, 0xef, 0x1d, 0xbc, 0xd7, 0x8b, 0xf6, 0x07, 0x42, 0x68, 0x8e, 0x9f, 0x7b, + 0x33, 0x24, 0xc9, 0x4f, 0x76, 0x9f, 0xae, 0x07, 0xf1, 0x1f, 0x71, 0x62, 0x8f, 0x82, 0xb4, 0x6c, + 0x3b, 0x55, 0x47, 0xeb, 0x6d, 0xec, 0x5b, 0xbc, 0xa7, 0x05, 0x7e, 0x2e, 0x0f, 0xc3, 0xb6, 0x53, + 0xad, 0x36, 0x79, 0x7e, 0xda, 0x83, 0xfc, 0x8f, 0x7f, 0xe4, 0x6e, 0x59, 0xb8, 0x34, 0xa4, 0xb7, + 0xaf, 0xee, 0x38, 0xa6, 0x41, 0x0f, 0x3c, 0x7a, 0x71, 0xf8, 0x21, 0xe7, 0xe0, 0x23, 0xc9, 0xcd, + 0x41, 0x8a, 0xe8, 0x62, 0x61, 0x13, 0xd3, 0xd3, 0xa9, 0x1e, 0x2c, 0xfe, 0x84, 0x1b, 0x20, 0x40, + 0x54, 0xf8, 0xa9, 0xaf, 0xbd, 0x3a, 0x25, 0x7d, 0xf3, 0xd5, 0x29, 0xe9, 0xf7, 0x5f, 0x9d, 0x92, + 0x3e, 0xf4, 0x9d, 0xa9, 0x81, 0x6f, 0x7e, 0x67, 0x6a, 0xe0, 0x77, 0xbf, 0x33, 0x35, 0xd0, 0x7e, + 0x97, 0x18, 0xe6, 0x8d, 0x79, 0x83, 0xed, 0x0f, 0xbf, 0x20, 0xd7, 0x34, 0x67, 0xbb, 0xb9, 0x39, + 0x5b, 0x31, 0x1a, 0x74, 0x1b, 0xd7, 0xdb, 0xad, 0x75, 0x17, 0x39, 0xf0, 0x9e, 0x28, 0x1c, 0xad, + 0x18, 0x76, 0xc3, 0xb0, 0xcb, 0x6c, 0xbf, 0x97, 0x15, 0xf8, 0x8e, 0x6f, 0xca, 0x5f, 0xd5, 0xc7, + 0xa6, 0xef, 0x45, 0x18, 0xa5, 0xaa, 0xd3, 0xed, 0x2e, 0xea, 0x6d, 0x3d, 0x03, 0xc4, 0xd7, 0xff, + 0x5d, 0x9c, 0x6a, 0x3d, 0xe2, 0x12, 0xd2, 0xd3, 0xfb, 0x75, 0x98, 0xd4, 0x1a, 0x66, 0x1d, 0xd3, + 0x6d, 0xfe, 0xb2, 0x5b, 0xd7, 0x9b, 0xdf, 0x37, 0x38, 0xbf, 0x09, 0x8f, 0x7c, 0x41, 0x50, 0xe7, + 0x16, 0x61, 0x5c, 0xad, 0x54, 0xb0, 0x19, 0x60, 0xd9, 0xa3, 0x5b, 0x84, 0x80, 0x69, 0x4e, 0xe9, + 0x72, 0x2b, 0x3c, 0xdd, 0xa9, 0x6b, 0x5e, 0xb8, 0xd7, 0x67, 0x79, 0x0b, 0xd7, 0xb0, 0xfe, 0xb0, + 0x8e, 0x9d, 0xab, 0x86, 0xb5, 0xc3, 0xcd, 0xfb, 0x30, 0x6b, 0x6a, 0x90, 0xdd, 0x60, 0x86, 0xf7, + 0x45, 0x61, 0x8a, 0x55, 0x9c, 0xde, 0x54, 0x6d, 0x7c, 0xfa, 0xca, 0xa3, 0x9b, 0xd8, 0x51, 0x1f, + 0x3d, 0x5d, 0x31, 0x34, 0x9d, 0xf7, 0xc4, 0x04, 0xef, 0x17, 0x52, 0x3f, 0xcb, 0xeb, 0xb3, 0x6d, + 0xb7, 0xe9, 0xe5, 0x79, 0x88, 0xcd, 0x19, 0x9a, 0x8e, 0x26, 0x21, 0x5e, 0xc5, 0xba, 0xd1, 0xe0, + 0x77, 0xee, 0x58, 0x01, 0xdd, 0x0d, 0x83, 0x6a, 0xc3, 0x68, 0xea, 0x0e, 0x3b, 0xa1, 0x28, 0x0c, + 0x7f, 0xed, 0xe6, 0xf4, 0xc0, 0xef, 0xdd, 0x9c, 0x8e, 0x2e, 0xe8, 0x8e, 0xc2, 0xab, 0x72, 0xb1, + 0xd7, 0x3e, 0x35, 0x2d, 0xc9, 0xcf, 0xc0, 0x50, 0x11, 0x57, 0x0e, 0xc2, 0xab, 0x88, 0x2b, 0x21, + 0x5e, 0x0f, 0x40, 0x62, 0x41, 0x77, 0xd8, 0xad, 0xc8, 0x13, 0x10, 0xd5, 0x74, 0x76, 0xd1, 0x26, + 0xd4, 0x3e, 0x81, 0x13, 0xd4, 0x22, 0xae, 0xb8, 0xa8, 0x55, 0x5c, 0x09, 0xa3, 0x12, 0xf6, 0x04, + 0x5e, 0x28, 0xfe, 0xee, 0x7f, 0x9e, 0x1a, 0x78, 0xf9, 0xd5, 0xa9, 0x81, 0x8e, 0x3d, 0xe1, 0x1f, + 0x03, 0xdc, 0xc4, 0xbc, 0x0b, 0xec, 0xea, 0x0e, 0x3b, 0x23, 0x71, 0xbb, 0xe1, 0xb7, 0x06, 0x41, + 0xe6, 0x38, 0xb6, 0xa3, 0xee, 0x68, 0x7a, 0xcd, 0xed, 0x09, 0xb5, 0xe9, 0x6c, 0x5f, 0xe3, 0x5d, + 0x71, 0x98, 0x77, 0x05, 0xc7, 0xe9, 0xde, 0x1b, 0xd9, 0xce, 0xa3, 0x2b, 0xdb, 0xa3, 0xcf, 0xe5, + 0x7f, 0x1d, 0x05, 0xb4, 0xe6, 0xa8, 0x3b, 0x38, 0xdf, 0x74, 0xb6, 0x0d, 0x4b, 0xbb, 0xc6, 0x62, + 0x19, 0x06, 0x68, 0xa8, 0xbb, 0x65, 0xc7, 0xd8, 0xc1, 0xba, 0x4d, 0x4d, 0x33, 0x7c, 0xe6, 0xe8, + 0x6c, 0x1b, 0xff, 0x98, 0x25, 0x5d, 0x57, 0x78, 0xf0, 0x73, 0xdf, 0x9e, 0xbe, 0xbf, 0xb7, 0x15, + 0x28, 0x32, 0x49, 0xae, 0x77, 0xd7, 0x29, 0x63, 0x74, 0x19, 0xd8, 0x25, 0x8b, 0x72, 0x5d, 0xb3, + 0x1d, 0x7e, 0x4f, 0xfb, 0xec, 0x6c, 0x7b, 0xdd, 0x67, 0x5b, 0xc5, 0x9c, 0xbd, 0xac, 0xd6, 0xb5, + 0xaa, 0xea, 0x18, 0x96, 0x7d, 0x71, 0x40, 0x49, 0x52, 0x56, 0x8b, 0x9a, 0xed, 0xa0, 0x75, 0x48, + 0x56, 0xb1, 0xbe, 0xc7, 0xd8, 0x46, 0x5f, 0x1f, 0xdb, 0x04, 0xe1, 0x44, 0xb9, 0x3e, 0x0f, 0x48, + 0xf5, 0xe3, 0x89, 0x87, 0x49, 0xec, 0x7e, 0x65, 0x07, 0xf6, 0x01, 0xce, 0xf4, 0x1d, 0xc5, 0xb8, + 0x1a, 0x06, 0x65, 0xef, 0x03, 0xf0, 0xda, 0x44, 0x19, 0x18, 0x52, 0xab, 0x55, 0x0b, 0xdb, 0x36, + 0x3d, 0x00, 0x4c, 0x2a, 0xa2, 0x98, 0x1b, 0xff, 0x37, 0x5f, 0x7a, 0x78, 0x24, 0xc0, 0xb1, 0x90, + 0x02, 0xb8, 0xe2, 0x92, 0x9e, 0xfa, 0xa4, 0x04, 0xe3, 0x2d, 0x2d, 0x22, 0x19, 0xa6, 0xf2, 0x1b, + 0xeb, 0x17, 0x57, 0x94, 0x85, 0x17, 0xf2, 0xeb, 0x0b, 0x2b, 0xcb, 0x65, 0x76, 0xe5, 0x7f, 0x79, + 0x6d, 0xb5, 0x34, 0xb7, 0x70, 0x61, 0xa1, 0x54, 0x4c, 0x0f, 0xa0, 0x69, 0x38, 0xd6, 0x06, 0xa7, + 0x58, 0x5a, 0x2c, 0xcd, 0xe7, 0xd7, 0x4b, 0x69, 0x09, 0xdd, 0x05, 0x27, 0xda, 0x32, 0x71, 0x51, + 0x22, 0x1d, 0x50, 0x94, 0x92, 0x8b, 0x12, 0x2d, 0x5c, 0xe8, 0x38, 0x8a, 0x1e, 0xea, 0xea, 0x3f, + 0xbb, 0xee, 0x70, 0x09, 0x8e, 0xa7, 0x3f, 0x91, 0xe0, 0x68, 0x78, 0xca, 0x50, 0xf5, 0xbd, 0x0e, + 0xaf, 0x3e, 0x3b, 0x44, 0xb3, 0x37, 0x41, 0x34, 0xaf, 0xef, 0xa1, 0xa3, 0x2c, 0x9f, 0x2e, 0x37, + 0xad, 0x3a, 0x8f, 0x41, 0x43, 0xa4, 0xbc, 0x61, 0xd5, 0x49, 0x6c, 0x12, 0x17, 0xfd, 0xa5, 0x93, + 0x29, 0x7e, 0x7b, 0x3f, 0x17, 0xfb, 0xc1, 0xa7, 0xa7, 0x07, 0x0a, 0x3b, 0x61, 0x95, 0xbe, 0xd2, + 0x73, 0x06, 0x4d, 0xe4, 0xf5, 0x3d, 0x1a, 0x7c, 0x56, 0xa5, 0x17, 0xe2, 0x54, 0x21, 0x71, 0x68, + 0x3a, 0x15, 0x3e, 0x34, 0x7d, 0x0e, 0xd7, 0xeb, 0x97, 0x74, 0xe3, 0x2a, 0xed, 0x49, 0x4f, 0xef, + 0x8f, 0x44, 0x60, 0xaa, 0x65, 0xaa, 0xe4, 0x59, 0x45, 0xa7, 0x27, 0xaf, 0x39, 0x48, 0x14, 0x45, + 0xb2, 0x92, 0x81, 0x21, 0x1b, 0x57, 0x0c, 0xbd, 0xca, 0x46, 0x77, 0x54, 0x11, 0x45, 0xa2, 0xaa, + 0xae, 0xea, 0x86, 0xcd, 0xef, 0xd9, 0xb3, 0x42, 0xe1, 0xe3, 0xd2, 0xfe, 0x72, 0x84, 0x11, 0xd1, + 0x92, 0x50, 0xf3, 0xd1, 0x9e, 0xc7, 0xc8, 0x3b, 0x44, 0x4b, 0x57, 0x89, 0xc0, 0x51, 0x72, 0xbf, + 0x56, 0xf9, 0xf9, 0x08, 0x4c, 0x87, 0xad, 0x42, 0x52, 0x35, 0xdb, 0x51, 0x1b, 0x66, 0x27, 0xb3, + 0x9c, 0x87, 0xe4, 0xba, 0xc0, 0xd9, 0xb7, 0x5d, 0x6e, 0xec, 0xd3, 0x2e, 0xa3, 0x6e, 0x53, 0xc2, + 0x30, 0x67, 0xfa, 0x34, 0x8c, 0xab, 0xc7, 0x81, 0x2c, 0xf3, 0xb9, 0x18, 0x9c, 0xa0, 0x0f, 0xb1, + 0xac, 0x86, 0xa6, 0x3b, 0xa7, 0x2b, 0xd6, 0x9e, 0xe9, 0xd0, 0x64, 0xcd, 0xd8, 0xe2, 0x76, 0x19, + 0xf7, 0xaa, 0x67, 0x59, 0x75, 0x87, 0xd1, 0xb2, 0x05, 0xf1, 0x55, 0x42, 0x47, 0x2c, 0xe2, 0x18, + 0x8e, 0x5a, 0xe7, 0x96, 0x62, 0x05, 0x02, 0x65, 0x8f, 0xb7, 0x22, 0x0c, 0xaa, 0x89, 0x77, 0x5b, + 0x75, 0xac, 0x6e, 0xb1, 0x3b, 0xf0, 0x51, 0x3a, 0x88, 0x12, 0x04, 0x40, 0xaf, 0xbb, 0x4f, 0x42, + 0x5c, 0x6d, 0xb2, 0xeb, 0x1b, 0x51, 0x32, 0xba, 0x68, 0x41, 0xbe, 0x04, 0x43, 0xfc, 0x10, 0x19, + 0xa5, 0x21, 0xba, 0x83, 0xf7, 0x68, 0x3b, 0x29, 0x85, 0xfc, 0x44, 0xb3, 0x10, 0xa7, 0xc2, 0xf3, + 0x49, 0x23, 0x33, 0xdb, 0x22, 0xfd, 0x2c, 0x15, 0x52, 0x61, 0x68, 0xf2, 0x33, 0x90, 0x28, 0x1a, + 0x0d, 0x4d, 0x37, 0x82, 0xdc, 0x92, 0x8c, 0x1b, 0x95, 0xd9, 0x6c, 0xf2, 0x1c, 0x43, 0x61, 0x05, + 0x74, 0x18, 0x06, 0xd9, 0x9b, 0x08, 0x7e, 0x05, 0x85, 0x97, 0xe4, 0x39, 0x18, 0xa2, 0xbc, 0x57, + 0x4c, 0x84, 0xf8, 0x6b, 0x3a, 0xfe, 0xf8, 0x82, 0xa6, 0xa3, 0x9c, 0x7d, 0xc4, 0x13, 0x16, 0x41, + 0xac, 0xaa, 0x3a, 0x2a, 0xd7, 0x9b, 0xfe, 0x96, 0xdf, 0x02, 0x09, 0xce, 0xc4, 0x46, 0x67, 0x20, + 0x6a, 0x98, 0x36, 0xbf, 0x44, 0x92, 0xed, 0xa4, 0xca, 0x8a, 0x59, 0x88, 0x91, 0xec, 0x44, 0x21, + 0xc8, 0x05, 0xa5, 0x63, 0x20, 0x7d, 0xd2, 0x17, 0x48, 0x7d, 0x5d, 0xee, 0xfb, 0xc9, 0xba, 0xb4, + 0xc5, 0x1d, 0x5c, 0x67, 0xf9, 0x74, 0x04, 0xa6, 0x7c, 0xb5, 0x57, 0xb0, 0x65, 0x6b, 0x86, 0xce, + 0xe7, 0x70, 0xe6, 0x2d, 0xc8, 0x27, 0x24, 0xaf, 0xef, 0xe0, 0x2e, 0x6f, 0x86, 0x68, 0xde, 0x34, + 0x51, 0x16, 0x12, 0xb4, 0x5c, 0x31, 0x98, 0xbf, 0xc4, 0x14, 0xb7, 0x4c, 0xea, 0x6c, 0x63, 0xcb, + 0xb9, 0xaa, 0x5a, 0xee, 0xb3, 0x41, 0x51, 0x96, 0x9f, 0x82, 0xe4, 0x9c, 0xa1, 0xdb, 0x58, 0xb7, + 0x9b, 0x74, 0x0c, 0x6e, 0xd6, 0x8d, 0xca, 0x0e, 0xe7, 0xc0, 0x0a, 0xc4, 0xe0, 0xaa, 0x69, 0x52, + 0xca, 0x98, 0x42, 0x7e, 0xb2, 0x7c, 0xb0, 0xb0, 0xd6, 0xd1, 0x44, 0x4f, 0xed, 0xdf, 0x44, 0x5c, + 0x49, 0xd7, 0x46, 0xff, 0x47, 0x82, 0xe3, 0xad, 0x03, 0x6a, 0x07, 0xef, 0xd9, 0xfb, 0x1d, 0x4f, + 0xcf, 0x43, 0x72, 0x95, 0xbe, 0xdd, 0xbf, 0x84, 0xf7, 0x50, 0x16, 0x86, 0x70, 0xf5, 0xcc, 0xd9, + 0xb3, 0x8f, 0x3e, 0xc5, 0xbc, 0xfd, 0xe2, 0x80, 0x22, 0x00, 0x68, 0x0a, 0x92, 0x36, 0xae, 0x98, + 0x67, 0xce, 0x9e, 0xdb, 0x79, 0x94, 0xb9, 0x17, 0xc9, 0x7a, 0x5c, 0x50, 0x2e, 0x41, 0xb4, 0x7e, + 0xed, 0xd3, 0xd3, 0x52, 0x21, 0x0e, 0x51, 0xbb, 0xd9, 0xb8, 0xa3, 0x3e, 0xf2, 0x4a, 0x1c, 0x66, + 0xfc, 0x94, 0x34, 0x52, 0xb9, 0x99, 0x08, 0xb7, 0x41, 0xda, 0x67, 0x03, 0x8a, 0xd1, 0x21, 0x81, + 0xed, 0x6a, 0x49, 0xf9, 0xd7, 0x24, 0x48, 0xb9, 0xe9, 0xd1, 0x1a, 0x76, 0xd0, 0x79, 0x7f, 0xce, + 0xc3, 0x87, 0xcd, 0xb1, 0xd9, 0x70, 0x5b, 0x5e, 0x1a, 0xa7, 0xf8, 0xd0, 0xd1, 0x13, 0xd4, 0x11, + 0x4d, 0xc3, 0xe6, 0x4f, 0xc9, 0x7a, 0x90, 0xba, 0xc8, 0xe8, 0x21, 0x40, 0x34, 0xc2, 0x95, 0xaf, + 0x18, 0x8e, 0xa6, 0xd7, 0xca, 0xa6, 0x71, 0x95, 0x3f, 0xd0, 0x8d, 0x2a, 0x69, 0x5a, 0x73, 0x99, + 0x56, 0xac, 0x12, 0x38, 0x11, 0x3a, 0xe9, 0x72, 0x09, 0xa6, 0x74, 0x24, 0x08, 0x88, 0x22, 0x3a, + 0x0f, 0x43, 0x66, 0x73, 0xb3, 0x2c, 0x22, 0xc6, 0xf0, 0x99, 0xe3, 0xed, 0xc6, 0xbf, 0xf0, 0x0f, + 0x1e, 0x01, 0x06, 0xcd, 0xe6, 0x26, 0xf1, 0x96, 0xbb, 0x20, 0xd5, 0x46, 0x98, 0xe1, 0x2b, 0x9e, + 0x1c, 0xf4, 0x93, 0x11, 0x5c, 0x83, 0xb2, 0x69, 0x69, 0x86, 0xa5, 0x39, 0x7b, 0x34, 0x67, 0x8d, + 0x2a, 0x69, 0x51, 0xb1, 0xca, 0xe1, 0xf2, 0x0e, 0x8c, 0xad, 0xd1, 0x35, 0xad, 0x27, 0xf9, 0x59, + 0x4f, 0x3e, 0xa9, 0xb7, 0x7c, 0x1d, 0x25, 0x8b, 0xb4, 0x48, 0x56, 0x78, 0xb6, 0xa3, 0x77, 0x3e, + 0xb1, 0x7f, 0xef, 0x0c, 0x66, 0x85, 0x7f, 0x78, 0x34, 0x30, 0x38, 0x99, 0x73, 0xfa, 0xc3, 0x57, + 0xbf, 0x8e, 0xd9, 0x2b, 0x9b, 0xc8, 0x76, 0x9f, 0x54, 0xb3, 0x3d, 0xc2, 0x68, 0xb6, 0xe7, 0x10, + 0x92, 0x9f, 0x82, 0x91, 0x55, 0xd5, 0x72, 0xd6, 0xb0, 0x73, 0x11, 0xab, 0x55, 0x6c, 0x05, 0x67, + 0xdd, 0x11, 0x31, 0xeb, 0x22, 0x88, 0xd1, 0xa9, 0x95, 0xcd, 0x3a, 0xf4, 0xb7, 0xbc, 0x0d, 0x31, + 0x7a, 0x1b, 0xd4, 0x9d, 0x91, 0x39, 0x05, 0x9b, 0x91, 0x49, 0x2c, 0xdd, 0x73, 0xb0, 0x2d, 0x52, + 0x5a, 0x5a, 0x40, 0x8f, 0x8b, 0x79, 0x35, 0xda, 0x7d, 0x5e, 0xe5, 0x8e, 0xc8, 0x67, 0xd7, 0x3a, + 0x0c, 0x15, 0x48, 0x28, 0x5e, 0x28, 0xba, 0x82, 0x48, 0x9e, 0x20, 0x68, 0x09, 0xc6, 0x4c, 0xd5, + 0x72, 0xe8, 0x33, 0x98, 0x6d, 0xaa, 0x05, 0xf7, 0xf5, 0xe9, 0xd6, 0x91, 0x17, 0x50, 0x96, 0xb7, + 0x32, 0x62, 0xfa, 0x81, 0xf2, 0x1f, 0xc4, 0x60, 0x90, 0x1b, 0xe3, 0xcd, 0x30, 0xc4, 0xcd, 0xca, + 0xbd, 0xf3, 0xc4, 0x6c, 0xeb, 0xc4, 0x34, 0xeb, 0x4e, 0x20, 0x9c, 0x9f, 0xa0, 0x41, 0xf7, 0x41, + 0xa2, 0xb2, 0xad, 0x6a, 0x7a, 0x59, 0xab, 0x8a, 0xed, 0x85, 0x57, 0x6f, 0x4e, 0x0f, 0xcd, 0x11, + 0xd8, 0x42, 0x51, 0x19, 0xa2, 0x95, 0x0b, 0x55, 0x92, 0x09, 0x6c, 0x63, 0xad, 0xb6, 0xed, 0xf0, + 0x11, 0xc6, 0x4b, 0xe8, 0x49, 0x88, 0x11, 0x87, 0xe0, 0x8f, 0x24, 0xb3, 0x2d, 0x9b, 0x3c, 0x6e, + 0xb2, 0x57, 0x48, 0x90, 0x86, 0x3f, 0xf4, 0xed, 0x69, 0x49, 0xa1, 0x14, 0x68, 0x0e, 0x46, 0xea, + 0xaa, 0xed, 0x94, 0xe9, 0x0c, 0x46, 0x9a, 0x8f, 0xf3, 0x35, 0x76, 0x8b, 0x41, 0xb8, 0x61, 0xb9, + 0xe8, 0xc3, 0x84, 0x8a, 0x81, 0xaa, 0xe8, 0x24, 0xa4, 0x29, 0x93, 0x8a, 0xd1, 0x68, 0x68, 0x0e, + 0xcb, 0xad, 0x06, 0xa9, 0xdd, 0x47, 0x09, 0x7c, 0x8e, 0x82, 0x69, 0x86, 0x75, 0x0c, 0x92, 0xf4, + 0x59, 0x16, 0x45, 0x61, 0x57, 0x90, 0x13, 0x04, 0x40, 0x2b, 0xef, 0x87, 0x31, 0x2f, 0x3e, 0x32, + 0x94, 0x04, 0xe3, 0xe2, 0x81, 0x29, 0xe2, 0x23, 0x30, 0xa9, 0xe3, 0x5d, 0x7a, 0x29, 0x3a, 0x80, + 0x9d, 0xa4, 0xd8, 0x88, 0xd4, 0x5d, 0x0e, 0x52, 0xdc, 0x0b, 0xa3, 0x15, 0x61, 0x7c, 0x86, 0x0b, + 0x14, 0x77, 0xc4, 0x85, 0x52, 0xb4, 0xa3, 0x90, 0x50, 0x4d, 0x93, 0x21, 0x0c, 0xf3, 0xf8, 0x68, + 0x9a, 0xb4, 0xea, 0x14, 0x8c, 0x53, 0x1d, 0x2d, 0x6c, 0x37, 0xeb, 0x0e, 0x67, 0x92, 0xa2, 0x38, + 0x63, 0xa4, 0x42, 0x61, 0x70, 0x8a, 0x7b, 0x37, 0x8c, 0xe0, 0x2b, 0x5a, 0x15, 0xeb, 0x15, 0xcc, + 0xf0, 0x46, 0x28, 0x5e, 0x4a, 0x00, 0x29, 0xd2, 0x03, 0xe0, 0xc6, 0xbd, 0xb2, 0x88, 0xc9, 0xa3, + 0x8c, 0x9f, 0x80, 0xe7, 0x19, 0x58, 0xce, 0x40, 0xac, 0xa8, 0x3a, 0x2a, 0x49, 0x30, 0x9c, 0x5d, + 0x36, 0xd1, 0xa4, 0x14, 0xf2, 0x53, 0x7e, 0x2d, 0x02, 0xb1, 0xcb, 0x86, 0x83, 0xd1, 0x63, 0xbe, + 0x04, 0x70, 0xb4, 0x9d, 0x3f, 0xaf, 0x69, 0x35, 0x1d, 0x57, 0x97, 0xec, 0x9a, 0xef, 0x1b, 0x0a, + 0x9e, 0x3b, 0x45, 0x02, 0xee, 0x34, 0x09, 0x71, 0xcb, 0x68, 0xea, 0x55, 0x71, 0x7b, 0x97, 0x16, + 0x50, 0x09, 0x12, 0xae, 0x97, 0xc4, 0x7a, 0x79, 0xc9, 0x18, 0xf1, 0x12, 0xe2, 0xc3, 0x1c, 0xa0, + 0x0c, 0x6d, 0x72, 0x67, 0x29, 0x40, 0xd2, 0x0d, 0x5e, 0xdc, 0xdb, 0xfa, 0x73, 0x58, 0x8f, 0x8c, + 0x4c, 0x26, 0x6e, 0xdf, 0xbb, 0xc6, 0x63, 0x1e, 0x97, 0x76, 0x2b, 0xb8, 0xf5, 0x02, 0x6e, 0xc5, + 0xbf, 0xe7, 0x30, 0x44, 0xf5, 0xf2, 0xdc, 0x8a, 0x7d, 0xd3, 0xe1, 0x38, 0x24, 0x6d, 0xad, 0xa6, + 0xab, 0x4e, 0xd3, 0xc2, 0xdc, 0xf3, 0x3c, 0x80, 0xfc, 0x15, 0x09, 0x06, 0x99, 0x27, 0xfb, 0xec, + 0x26, 0xb5, 0xb7, 0x5b, 0xa4, 0x93, 0xdd, 0xa2, 0x07, 0xb7, 0x5b, 0x1e, 0xc0, 0x15, 0xc6, 0xe6, + 0xcf, 0xec, 0xdb, 0x64, 0x0c, 0x4c, 0xc4, 0x35, 0xad, 0xc6, 0x07, 0xaa, 0x8f, 0x48, 0xfe, 0x4f, + 0x12, 0x49, 0x62, 0x79, 0x3d, 0xca, 0xc3, 0x88, 0x90, 0xab, 0xbc, 0x55, 0x57, 0x6b, 0xdc, 0x77, + 0x4e, 0x74, 0x14, 0xee, 0x42, 0x5d, 0xad, 0x29, 0xc3, 0x5c, 0x1e, 0x52, 0x68, 0xdf, 0x0f, 0x91, + 0x0e, 0xfd, 0x10, 0xe8, 0xf8, 0xe8, 0xc1, 0x3a, 0x3e, 0xd0, 0x45, 0xb1, 0x70, 0x17, 0x7d, 0x31, + 0x42, 0x17, 0x33, 0xa6, 0x61, 0xab, 0xf5, 0x1f, 0xc7, 0x88, 0x38, 0x06, 0x49, 0xd3, 0xa8, 0x97, + 0x59, 0x0d, 0xbb, 0xd5, 0x9e, 0x30, 0x8d, 0xba, 0xd2, 0xd2, 0xed, 0xf1, 0xdb, 0x34, 0x5c, 0x06, + 0x6f, 0x83, 0xd5, 0x86, 0xc2, 0x56, 0xb3, 0x20, 0xc5, 0x4c, 0xc1, 0xe7, 0xb2, 0x47, 0x88, 0x0d, + 0xe8, 0xe4, 0x28, 0xb5, 0xce, 0xbd, 0x4c, 0x6c, 0x86, 0xa9, 0x70, 0x3c, 0x42, 0xc1, 0x42, 0x7f, + 0xbb, 0x55, 0xb0, 0xdf, 0x2d, 0x15, 0x8e, 0x27, 0xff, 0x4d, 0x09, 0x60, 0x91, 0x58, 0x96, 0xea, + 0x4b, 0x66, 0x21, 0x9b, 0x8a, 0x50, 0x0e, 0xb4, 0x3c, 0xd5, 0xa9, 0xd3, 0x78, 0xfb, 0x29, 0xdb, + 0x2f, 0xf7, 0x1c, 0x8c, 0x78, 0xce, 0x68, 0x63, 0x21, 0xcc, 0x54, 0x97, 0xac, 0x7a, 0x0d, 0x3b, + 0x4a, 0xea, 0x8a, 0xaf, 0x24, 0xff, 0x73, 0x09, 0x92, 0x54, 0xa6, 0x25, 0xec, 0xa8, 0x81, 0x3e, + 0x94, 0x0e, 0xde, 0x87, 0x27, 0x00, 0x18, 0x1b, 0x5b, 0xbb, 0x86, 0xb9, 0x67, 0x25, 0x29, 0x64, + 0x4d, 0xbb, 0x86, 0xd1, 0x39, 0xd7, 0xe0, 0xd1, 0xee, 0x06, 0x17, 0x59, 0x37, 0x37, 0xfb, 0x11, + 0x18, 0xa2, 0x9f, 0xa5, 0xda, 0xb5, 0x79, 0x22, 0x3d, 0xa8, 0x37, 0x1b, 0xeb, 0xbb, 0xb6, 0xfc, + 0x22, 0x0c, 0xad, 0xef, 0xb2, 0xbd, 0x91, 0x63, 0x90, 0xb4, 0x0c, 0x83, 0xcf, 0xc9, 0x2c, 0x17, + 0x4a, 0x10, 0x00, 0x9d, 0x82, 0xc4, 0x7e, 0x40, 0xc4, 0xdb, 0x0f, 0xf0, 0x36, 0x34, 0xa2, 0x7d, + 0x6d, 0x68, 0x9c, 0xfa, 0xf7, 0x12, 0x0c, 0xfb, 0xe2, 0x03, 0x7a, 0x14, 0x0e, 0x15, 0x16, 0x57, + 0xe6, 0x2e, 0x95, 0x17, 0x8a, 0xe5, 0x0b, 0x8b, 0xf9, 0x79, 0xef, 0xdd, 0x56, 0xf6, 0xf0, 0xf5, + 0x1b, 0x33, 0xc8, 0x87, 0xbb, 0xa1, 0xd3, 0x1d, 0x25, 0x74, 0x1a, 0x26, 0x83, 0x24, 0xf9, 0xc2, + 0x5a, 0x69, 0x79, 0x3d, 0x2d, 0x65, 0x0f, 0x5d, 0xbf, 0x31, 0x33, 0xee, 0xa3, 0xc8, 0x6f, 0xda, + 0x58, 0x77, 0x5a, 0x09, 0xe6, 0x56, 0x96, 0x96, 0x16, 0xd6, 0xd3, 0x91, 0x16, 0x02, 0x1e, 0xb0, + 0x1f, 0x80, 0xf1, 0x20, 0xc1, 0xf2, 0xc2, 0x62, 0x3a, 0x9a, 0x45, 0xd7, 0x6f, 0xcc, 0x8c, 0xfa, + 0xb0, 0x97, 0xb5, 0x7a, 0x36, 0xf1, 0x81, 0xcf, 0x4c, 0x0d, 0xfc, 0xd2, 0x2f, 0x4e, 0x49, 0x44, + 0xb3, 0x91, 0x40, 0x8c, 0x40, 0x0f, 0xc1, 0x91, 0xb5, 0x85, 0xf9, 0xe5, 0x52, 0xb1, 0xbc, 0xb4, + 0x36, 0x2f, 0xf6, 0x9d, 0x85, 0x76, 0x63, 0xd7, 0x6f, 0xcc, 0x0c, 0x73, 0x95, 0x3a, 0x61, 0xaf, + 0x2a, 0xa5, 0xcb, 0x2b, 0xeb, 0xa5, 0xb4, 0xc4, 0xb0, 0x57, 0x2d, 0x7c, 0xc5, 0x70, 0xd8, 0x77, + 0xeb, 0x1e, 0x81, 0xa3, 0x6d, 0xb0, 0x5d, 0xc5, 0xc6, 0xaf, 0xdf, 0x98, 0x19, 0x59, 0xb5, 0x30, + 0x1b, 0x3f, 0x94, 0x62, 0x16, 0x32, 0xad, 0x14, 0x2b, 0xab, 0x2b, 0x6b, 0xf9, 0xc5, 0xf4, 0x4c, + 0x36, 0x7d, 0xfd, 0xc6, 0x4c, 0x4a, 0x04, 0x43, 0xba, 0xb9, 0xef, 0x6a, 0x76, 0x27, 0x57, 0x3c, + 0x7f, 0xfc, 0x30, 0xdc, 0xd3, 0xe1, 0x5c, 0x49, 0x9c, 0x48, 0x1c, 0xe8, 0x64, 0xa9, 0xe3, 0xde, + 0x7a, 0xb6, 0xc7, 0xf6, 0x73, 0xef, 0xa5, 0xd3, 0xc1, 0x4f, 0xad, 0xb2, 0x5d, 0x17, 0x77, 0xf2, + 0x07, 0x25, 0x18, 0xbd, 0xa8, 0xd9, 0x8e, 0x61, 0x69, 0x15, 0xb5, 0x4e, 0x5f, 0x6b, 0x9d, 0xeb, + 0x37, 0xb6, 0x86, 0x86, 0xfa, 0xd3, 0x30, 0x78, 0x45, 0xad, 0xb3, 0xa0, 0x16, 0xa5, 0x1f, 0x97, + 0xe9, 0x70, 0xcc, 0xe3, 0x86, 0x36, 0xc1, 0x80, 0x91, 0xc9, 0xbf, 0x12, 0x81, 0x31, 0x3a, 0x18, + 0x6c, 0xf6, 0xd9, 0x31, 0xb2, 0xc6, 0x2a, 0x40, 0xcc, 0x52, 0x1d, 0xbe, 0x69, 0x58, 0x98, 0xe5, + 0x27, 0x8e, 0xf7, 0xf5, 0x71, 0x7e, 0x56, 0xc4, 0x15, 0x85, 0xd2, 0xa2, 0x77, 0x40, 0xa2, 0xa1, + 0xee, 0x96, 0x29, 0x1f, 0xb6, 0x72, 0xc9, 0xef, 0x8f, 0xcf, 0xad, 0x9b, 0xd3, 0x63, 0x7b, 0x6a, + 0xa3, 0x9e, 0x93, 0x05, 0x1f, 0x59, 0x19, 0x6a, 0xa8, 0xbb, 0x44, 0x44, 0x64, 0xc2, 0x18, 0x81, + 0x56, 0xb6, 0x55, 0xbd, 0x86, 0x59, 0x23, 0x74, 0x0b, 0xb4, 0x70, 0x71, 0xdf, 0x8d, 0x1c, 0xf6, + 0x1a, 0xf1, 0xb1, 0x93, 0x95, 0x91, 0x86, 0xba, 0x3b, 0x47, 0x01, 0xa4, 0xc5, 0x5c, 0xe2, 0xa3, + 0x9f, 0x9a, 0x1e, 0xa0, 0xa7, 0xb8, 0xdf, 0x92, 0x00, 0x3c, 0x8b, 0xa1, 0x77, 0x40, 0xba, 0xe2, + 0x96, 0x28, 0xad, 0x38, 0x8f, 0xbc, 0xbf, 0x53, 0x5f, 0x84, 0xec, 0xcd, 0xe6, 0xe6, 0x6f, 0xde, + 0x9c, 0x96, 0x94, 0xb1, 0x4a, 0xa8, 0x2b, 0xde, 0x0e, 0xc3, 0x4d, 0xb3, 0xaa, 0x3a, 0xb8, 0x4c, + 0xd7, 0x71, 0x91, 0x9e, 0xf3, 0xfc, 0x14, 0xe1, 0x75, 0xeb, 0xe6, 0x34, 0x62, 0x6a, 0xf9, 0x88, + 0x65, 0x3a, 0xfb, 0x03, 0x83, 0x10, 0x02, 0x9f, 0x4e, 0x5f, 0x97, 0x60, 0xb8, 0xe8, 0xbb, 0x47, + 0x99, 0x81, 0xa1, 0x86, 0xa1, 0x6b, 0x3b, 0xdc, 0x1f, 0x93, 0x8a, 0x28, 0xa2, 0x2c, 0x24, 0xd8, + 0x03, 0x56, 0x67, 0x4f, 0x6c, 0x85, 0x8a, 0x32, 0xa1, 0xba, 0x8a, 0x37, 0x6d, 0x4d, 0xf4, 0x86, + 0x22, 0x8a, 0xe8, 0x02, 0xa4, 0x6d, 0x5c, 0x69, 0x5a, 0x9a, 0xb3, 0x57, 0xae, 0x18, 0xba, 0xa3, + 0x56, 0x1c, 0xf6, 0x14, 0xb2, 0x70, 0xec, 0xd6, 0xcd, 0xe9, 0x23, 0x4c, 0xd6, 0x30, 0x86, 0xac, + 0x8c, 0x09, 0xd0, 0x1c, 0x83, 0x90, 0x16, 0xaa, 0xd8, 0x51, 0xb5, 0xba, 0x9d, 0x61, 0x17, 0x12, + 0x44, 0xd1, 0xa7, 0xcb, 0xe7, 0x87, 0xfc, 0x1b, 0x5b, 0x17, 0x20, 0x6d, 0x98, 0xd8, 0x0a, 0x24, + 0xa2, 0x52, 0xb8, 0xe5, 0x30, 0x86, 0xac, 0x8c, 0x09, 0x90, 0x48, 0x52, 0x1d, 0xd2, 0xcd, 0x62, + 0xa1, 0x68, 0x36, 0x37, 0xbd, 0xfd, 0xb0, 0xc9, 0x96, 0xde, 0xc8, 0xeb, 0x7b, 0x85, 0xc7, 0x3c, + 0xee, 0x61, 0x3a, 0xf9, 0x1b, 0x5f, 0x7a, 0x78, 0x92, 0xbb, 0x86, 0xb7, 0x3f, 0x75, 0x09, 0xef, + 0x91, 0xee, 0xe7, 0xa8, 0xab, 0x14, 0x93, 0xa4, 0x9d, 0x2f, 0xaa, 0x5a, 0x5d, 0x3c, 0xe9, 0x57, + 0x78, 0x09, 0xe5, 0x60, 0xd0, 0x76, 0x54, 0xa7, 0x69, 0xf3, 0xd3, 0x5d, 0xb9, 0x93, 0xab, 0x15, + 0x0c, 0xbd, 0xba, 0x46, 0x31, 0x15, 0x4e, 0x81, 0x2e, 0xc0, 0x20, 0x3f, 0x36, 0x8f, 0xef, 0x7b, + 0x7c, 0xd3, 0xfb, 0x11, 0x8c, 0x9a, 0x58, 0xa4, 0x8a, 0xeb, 0xb8, 0xc6, 0xd2, 0xaa, 0x6d, 0x95, + 0xac, 0x3e, 0xe8, 0xf7, 0xf6, 0x0a, 0x0b, 0xfb, 0x1e, 0x84, 0xdc, 0x52, 0x61, 0x7e, 0xb2, 0x32, + 0xe6, 0x82, 0xd6, 0x28, 0x04, 0x5d, 0x0a, 0x5c, 0xf8, 0xe5, 0x1f, 0xa5, 0xbc, 0xbb, 0x93, 0xfa, + 0x3e, 0x9f, 0x16, 0xfb, 0x13, 0xfe, 0xeb, 0xc2, 0x17, 0x20, 0xdd, 0xd4, 0x37, 0x0d, 0x9d, 0xbe, + 0xbb, 0xe5, 0xf9, 0x3d, 0x59, 0xdf, 0x45, 0xfd, 0xce, 0x11, 0xc6, 0x90, 0x95, 0x31, 0x17, 0x74, + 0x91, 0xad, 0x02, 0xaa, 0x30, 0xea, 0x61, 0xd1, 0x81, 0x9a, 0xec, 0x39, 0x50, 0xef, 0xe2, 0x03, + 0xf5, 0x50, 0xb8, 0x15, 0x6f, 0xac, 0x8e, 0xb8, 0x40, 0x42, 0x86, 0x2e, 0x02, 0x78, 0xe1, 0x81, + 0xee, 0x53, 0x0c, 0x77, 0xee, 0x78, 0x2f, 0xc6, 0x88, 0xf5, 0x9e, 0x47, 0x8b, 0xde, 0x05, 0x13, + 0x0d, 0x4d, 0x2f, 0xdb, 0xb8, 0xbe, 0x55, 0xe6, 0x06, 0x26, 0x2c, 0xe9, 0x67, 0x93, 0x0a, 0x8b, + 0xfb, 0xf3, 0x87, 0x5b, 0x37, 0xa7, 0xb3, 0x3c, 0x84, 0xb6, 0xb2, 0x94, 0x95, 0xf1, 0x86, 0xa6, + 0xaf, 0xe1, 0xfa, 0x56, 0xd1, 0x85, 0xe5, 0x52, 0x1f, 0xf8, 0xd4, 0xf4, 0x00, 0x1f, 0xae, 0x03, + 0xf2, 0x39, 0xba, 0x77, 0xce, 0x87, 0x19, 0xb6, 0xc9, 0x9a, 0x44, 0x15, 0x05, 0x7e, 0xbd, 0xc0, + 0x03, 0xb0, 0x61, 0xfe, 0xf2, 0x7f, 0x9c, 0x91, 0xe4, 0xcf, 0x4b, 0x30, 0x58, 0xbc, 0xbc, 0xaa, + 0x6a, 0x16, 0x5a, 0x80, 0x71, 0xcf, 0x73, 0x82, 0x83, 0xfc, 0xf8, 0xad, 0x9b, 0xd3, 0x99, 0xb0, + 0x73, 0xb9, 0xa3, 0xdc, 0x73, 0x60, 0x31, 0xcc, 0x17, 0x3a, 0x2d, 0x5c, 0x03, 0xac, 0x5a, 0x50, + 0xe4, 0xd6, 0x65, 0x6d, 0x48, 0xcd, 0x12, 0x0c, 0x31, 0x69, 0x6d, 0x94, 0x83, 0xb8, 0x49, 0x7e, + 0xf0, 0x83, 0x81, 0xa9, 0x8e, 0xce, 0x4b, 0xf1, 0xdd, 0x8d, 0x4c, 0x42, 0x22, 0x7f, 0x38, 0x02, + 0x50, 0xbc, 0x7c, 0x79, 0xdd, 0xd2, 0xcc, 0x3a, 0x76, 0x6e, 0xa7, 0xe6, 0xeb, 0x70, 0xc8, 0xb7, + 0x4a, 0xb2, 0x2a, 0x21, 0xed, 0x67, 0x6e, 0xdd, 0x9c, 0x3e, 0x1e, 0xd6, 0xde, 0x87, 0x26, 0x2b, + 0x13, 0xde, 0x7a, 0xc9, 0xaa, 0xb4, 0xe5, 0x5a, 0xb5, 0x1d, 0x97, 0x6b, 0xb4, 0x33, 0x57, 0x1f, + 0x9a, 0x9f, 0x6b, 0xd1, 0x76, 0xda, 0x9b, 0x76, 0x0d, 0x86, 0x3d, 0x93, 0xd8, 0xa8, 0x08, 0x09, + 0x87, 0xff, 0xe6, 0x16, 0x96, 0x3b, 0x5b, 0x58, 0x90, 0x71, 0x2b, 0xbb, 0x94, 0xf2, 0x9f, 0x4a, + 0x00, 0x9e, 0xcf, 0xfe, 0x64, 0xba, 0x18, 0x09, 0xe5, 0x3c, 0xf0, 0x46, 0x0f, 0x94, 0xaa, 0x71, + 0xea, 0x90, 0x3d, 0x7f, 0x26, 0x02, 0x13, 0x1b, 0x22, 0xf2, 0xfc, 0xc4, 0xdb, 0x60, 0x15, 0x86, + 0xb0, 0xee, 0x58, 0x1a, 0x35, 0x02, 0xe9, 0xed, 0x47, 0x3a, 0xf5, 0x76, 0x1b, 0x9d, 0xe8, 0x87, + 0xa3, 0xc4, 0xa6, 0x3b, 0x67, 0x13, 0xb2, 0xc6, 0xcf, 0x45, 0x21, 0xd3, 0x89, 0x12, 0xcd, 0xc1, + 0x58, 0xc5, 0xc2, 0xec, 0xb2, 0x95, 0x7f, 0xe7, 0xaf, 0x90, 0xf5, 0x32, 0xcb, 0x10, 0x82, 0xac, + 0x8c, 0x0a, 0x08, 0x9f, 0x3d, 0x6a, 0x40, 0xd2, 0x3e, 0xe2, 0x76, 0xf4, 0xce, 0x56, 0x7f, 0x79, + 0x9e, 0xcc, 0xa7, 0x0f, 0xd1, 0x48, 0x90, 0x01, 0x9b, 0x3f, 0x46, 0x3d, 0x28, 0x9d, 0x40, 0x5e, + 0x82, 0x31, 0x4d, 0xd7, 0x1c, 0x4d, 0xad, 0x97, 0x37, 0xd5, 0xba, 0xaa, 0x57, 0x0e, 0x92, 0x35, + 0xb3, 0x90, 0xcf, 0x9b, 0x0d, 0xb1, 0x93, 0x95, 0x51, 0x0e, 0x29, 0x30, 0x00, 0xba, 0x08, 0x43, + 0xa2, 0xa9, 0xd8, 0x81, 0xb2, 0x0d, 0x41, 0xee, 0x4b, 0xf0, 0x7e, 0x36, 0x0a, 0xe3, 0x0a, 0xae, + 0xfe, 0x45, 0x57, 0xec, 0xaf, 0x2b, 0x96, 0x00, 0xd8, 0x70, 0x27, 0x01, 0xf6, 0x00, 0xbd, 0x41, + 0x02, 0x46, 0x92, 0x71, 0x28, 0xda, 0x8e, 0xaf, 0x3f, 0x6e, 0x46, 0x20, 0xe5, 0xef, 0x8f, 0x3f, + 0xa7, 0xb3, 0x12, 0x5a, 0xf0, 0x22, 0x51, 0x8c, 0x7f, 0x6e, 0xb7, 0x43, 0x24, 0x6a, 0xf1, 0xde, + 0xee, 0x21, 0xe8, 0x7f, 0x46, 0x60, 0x70, 0x55, 0xb5, 0xd4, 0x86, 0x8d, 0x2a, 0x2d, 0x99, 0xa6, + 0xd8, 0x7e, 0x6c, 0xf9, 0xa8, 0x3a, 0xdf, 0xed, 0xe8, 0x91, 0x68, 0x7e, 0xb4, 0x4d, 0xa2, 0xf9, + 0x56, 0x18, 0x25, 0xcb, 0x61, 0xdf, 0x15, 0x06, 0x62, 0xed, 0x91, 0xc2, 0x51, 0x8f, 0x4b, 0xb0, + 0x9e, 0xad, 0x96, 0x2f, 0xfb, 0xef, 0x30, 0x0c, 0x13, 0x0c, 0x2f, 0x30, 0x13, 0xf2, 0xc3, 0xde, + 0xb2, 0xd4, 0x57, 0x29, 0x2b, 0xd0, 0x50, 0x77, 0x4b, 0xac, 0x80, 0x16, 0x01, 0x6d, 0xbb, 0x3b, + 0x23, 0x65, 0xcf, 0x9c, 0x84, 0xfe, 0xc4, 0xad, 0x9b, 0xd3, 0x47, 0x19, 0x7d, 0x2b, 0x8e, 0xac, + 0x8c, 0x7b, 0x40, 0xc1, 0xed, 0x71, 0x00, 0xa2, 0x57, 0x99, 0x5d, 0xdb, 0x66, 0xcb, 0x9d, 0x43, + 0xb7, 0x6e, 0x4e, 0x8f, 0x33, 0x2e, 0x5e, 0x9d, 0xac, 0x24, 0x49, 0xa1, 0x48, 0x7e, 0xfb, 0x3c, + 0xfb, 0x33, 0x12, 0x20, 0x2f, 0xe4, 0x2b, 0xd8, 0x36, 0xc9, 0xfa, 0x8c, 0x24, 0xe2, 0xbe, 0xac, + 0x59, 0xea, 0x9e, 0x88, 0x7b, 0xf4, 0x22, 0x11, 0xf7, 0x8d, 0x94, 0xa7, 0xbc, 0xf0, 0x18, 0xe9, + 0x75, 0x87, 0x99, 0xbb, 0x48, 0x38, 0x1e, 0x0e, 0xc8, 0xff, 0x4a, 0x82, 0xa3, 0x2d, 0x1e, 0xe5, + 0x0a, 0xfb, 0x97, 0x00, 0x59, 0xbe, 0x4a, 0xfe, 0xed, 0x44, 0x26, 0xf4, 0xbe, 0x1d, 0x74, 0xdc, + 0x6a, 0x89, 0xbb, 0xb7, 0x2f, 0xc2, 0xb3, 0x4b, 0xf2, 0xff, 0x4c, 0x82, 0x49, 0x7f, 0xf3, 0xae, + 0x22, 0xcb, 0x90, 0xf2, 0xb7, 0xce, 0x55, 0xb8, 0xa7, 0x1f, 0x15, 0xb8, 0xf4, 0x01, 0x7a, 0xf4, + 0xac, 0x37, 0x5c, 0xd9, 0xde, 0xd9, 0xa3, 0x7d, 0x5b, 0x43, 0xc8, 0x14, 0x1e, 0xb6, 0x31, 0xda, + 0x1f, 0xff, 0x57, 0x82, 0xd8, 0xaa, 0x61, 0xd4, 0x91, 0x01, 0xe3, 0xba, 0xe1, 0x94, 0x89, 0x67, + 0xe1, 0xaa, 0xff, 0xae, 0x7a, 0xb2, 0x30, 0xb7, 0x3f, 0x23, 0x7d, 0xef, 0xe6, 0x74, 0x2b, 0x2b, + 0x65, 0x4c, 0x37, 0x9c, 0x02, 0x85, 0xf0, 0xeb, 0xea, 0xef, 0x82, 0x91, 0x60, 0x63, 0x2c, 0x4a, + 0x3e, 0xb7, 0xef, 0xc6, 0x82, 0x6c, 0x6e, 0xdd, 0x9c, 0x9e, 0xf4, 0x46, 0x8c, 0x0b, 0x96, 0x95, + 0xd4, 0xa6, 0xaf, 0x75, 0x76, 0xbd, 0xeb, 0x07, 0x9f, 0x9a, 0x96, 0x4e, 0x7d, 0x59, 0x02, 0xf0, + 0x76, 0x1e, 0xd0, 0x43, 0x70, 0xa4, 0xb0, 0xb2, 0x5c, 0x2c, 0xaf, 0xad, 0xe7, 0xd7, 0x37, 0xd6, + 0x82, 0xf7, 0xba, 0xc5, 0xf6, 0xb8, 0x6d, 0xe2, 0x8a, 0xb6, 0xa5, 0xe1, 0x2a, 0xba, 0x0f, 0x26, + 0x83, 0xd8, 0xa4, 0x54, 0x2a, 0xa6, 0xa5, 0x6c, 0xea, 0xfa, 0x8d, 0x99, 0x04, 0xcb, 0xc5, 0x70, + 0x15, 0x9d, 0x84, 0x43, 0xad, 0x78, 0x0b, 0xcb, 0xf3, 0xe9, 0x48, 0x76, 0xe4, 0xfa, 0x8d, 0x99, + 0xa4, 0x9b, 0xb4, 0x21, 0x19, 0x90, 0x1f, 0x93, 0xf3, 0x8b, 0x66, 0xe1, 0xfa, 0x8d, 0x99, 0x41, + 0x66, 0xc0, 0x6c, 0xec, 0x03, 0x9f, 0x99, 0x1a, 0xb8, 0xed, 0xb7, 0xbf, 0xff, 0x68, 0xa8, 0xe3, + 0xae, 0x77, 0x0d, 0xeb, 0xd8, 0xd6, 0xec, 0x03, 0xed, 0x7a, 0xf7, 0xb5, 0x93, 0x2e, 0xff, 0x4e, + 0x1c, 0x52, 0xf3, 0xac, 0x15, 0xd2, 0x11, 0x18, 0xbd, 0x09, 0x06, 0x4d, 0x3a, 0x8d, 0xb8, 0xc7, + 0x68, 0x1d, 0x1c, 0x9e, 0x4d, 0x36, 0xee, 0x5d, 0x2e, 0x36, 0xf5, 0xd8, 0xfc, 0x32, 0x07, 0xbb, + 0x63, 0xe6, 0xdd, 0x9a, 0x4a, 0xed, 0x6b, 0xbf, 0x87, 0xe5, 0x2c, 0x7c, 0x6b, 0x25, 0xcc, 0x4f, + 0x66, 0xf7, 0x42, 0xd6, 0x09, 0x84, 0xdd, 0x0e, 0x7b, 0x9f, 0x04, 0x87, 0x28, 0x96, 0x37, 0x11, + 0x53, 0x4c, 0x91, 0xec, 0x9f, 0xea, 0xa4, 0xc2, 0xa2, 0x6a, 0x7b, 0x77, 0x3d, 0xd8, 0x7d, 0xae, + 0x7b, 0xf8, 0x44, 0x78, 0xdc, 0xd7, 0x78, 0x98, 0xad, 0xac, 0x4c, 0xd4, 0x5b, 0x28, 0x6d, 0x34, + 0x1f, 0xb8, 0xd0, 0x17, 0xdb, 0xdf, 0x56, 0xbb, 0xff, 0x72, 0xdf, 0x33, 0x30, 0xec, 0xc5, 0x12, + 0x9b, 0xff, 0xaf, 0x97, 0xfe, 0xe7, 0x0e, 0x3f, 0x31, 0x7a, 0xbf, 0x04, 0x87, 0xbc, 0xd9, 0xdc, + 0xcf, 0x96, 0xfd, 0x4f, 0x9c, 0x07, 0xf7, 0xb1, 0x10, 0x0a, 0x1b, 0xa7, 0x2d, 0x5f, 0x59, 0x99, + 0x6c, 0xb6, 0x92, 0x92, 0x25, 0xd8, 0x88, 0x3f, 0xb2, 0xda, 0x19, 0xf1, 0xd9, 0xc7, 0xfe, 0x43, + 0x73, 0x90, 0x01, 0xfb, 0x3f, 0x1d, 0xa6, 0x61, 0x39, 0xb8, 0x4a, 0x37, 0xe4, 0x12, 0x8a, 0x5b, + 0x96, 0x97, 0x01, 0xb5, 0x76, 0x6e, 0xf8, 0x02, 0xa3, 0xf7, 0x26, 0x05, 0x4d, 0x42, 0xdc, 0x7f, + 0xc5, 0x8f, 0x15, 0x72, 0x89, 0x0f, 0xf0, 0xe9, 0xf3, 0xb6, 0x8f, 0xf9, 0x7f, 0x11, 0x81, 0x53, + 0xfe, 0xe3, 0xa1, 0x97, 0x9a, 0xd8, 0xda, 0x73, 0x87, 0xa8, 0xa9, 0xd6, 0x34, 0xdd, 0xff, 0x0a, + 0xe2, 0xa8, 0x7f, 0xc2, 0xa7, 0xb8, 0xc2, 0x4e, 0xb2, 0x0e, 0xc3, 0xab, 0x6a, 0x0d, 0x2b, 0xf8, + 0xa5, 0x26, 0xb6, 0x9d, 0x36, 0x97, 0xcc, 0x0f, 0xc3, 0xa0, 0xb1, 0xb5, 0x25, 0x8e, 0xb4, 0x63, + 0x0a, 0x2f, 0x11, 0x95, 0xeb, 0x5a, 0x43, 0x63, 0xb7, 0xc1, 0x62, 0x0a, 0x2b, 0xa0, 0x69, 0x18, + 0xae, 0x18, 0x4d, 0x9d, 0x8f, 0xb8, 0x4c, 0x4c, 0x7c, 0x5e, 0xa5, 0xa9, 0xb3, 0x11, 0x27, 0x3f, + 0x0d, 0x29, 0xd6, 0x1e, 0x9f, 0x71, 0x8f, 0x42, 0x82, 0x5e, 0xa7, 0xf2, 0x5a, 0x1d, 0x22, 0xe5, + 0x4b, 0xec, 0x42, 0x3a, 0xe3, 0xc2, 0x1a, 0x66, 0x85, 0x42, 0xa1, 0xa3, 0x29, 0x4f, 0xf6, 0x0e, + 0x0d, 0xcc, 0x50, 0xae, 0x19, 0x7f, 0x23, 0x0e, 0x87, 0xf8, 0x09, 0x9d, 0x6a, 0x6a, 0xa7, 0xb7, + 0x1d, 0x47, 0x3c, 0x90, 0x00, 0x9e, 0xea, 0xaa, 0xa6, 0x26, 0xef, 0x41, 0xec, 0xa2, 0xe3, 0x98, + 0xe8, 0x14, 0xc4, 0xad, 0x66, 0x1d, 0x8b, 0x1d, 0x1f, 0x77, 0x4f, 0x5e, 0x35, 0xb5, 0x59, 0x82, + 0xa0, 0x34, 0xeb, 0x58, 0x61, 0x28, 0xa8, 0x04, 0xd3, 0x5b, 0xcd, 0x7a, 0x7d, 0xaf, 0x5c, 0xc5, + 0xf4, 0xff, 0x60, 0xb9, 0xff, 0x49, 0x02, 0xef, 0x9a, 0xaa, 0xf8, 0x1e, 0x25, 0xb1, 0xcd, 0x71, + 0x8a, 0x56, 0xa4, 0x58, 0xe2, 0xbf, 0x48, 0x94, 0x04, 0x8e, 0xfc, 0x7b, 0x11, 0x48, 0x08, 0xd6, + 0xf4, 0x86, 0x38, 0xae, 0xe3, 0x8a, 0x63, 0x88, 0x13, 0x13, 0xb7, 0x8c, 0x10, 0x44, 0x6b, 0xbc, + 0x8b, 0x92, 0x17, 0x07, 0x14, 0x52, 0x20, 0x30, 0xf7, 0xde, 0x3e, 0x81, 0x99, 0x4d, 0xd2, 0x6b, + 0x31, 0xd3, 0x10, 0x4b, 0xb3, 0x8b, 0x03, 0x0a, 0x2d, 0xa1, 0x0c, 0x0c, 0x92, 0x91, 0xe1, 0xb0, + 0x8f, 0x7c, 0x12, 0x38, 0x2f, 0xa3, 0xc3, 0x10, 0x37, 0x55, 0xa7, 0xc2, 0xae, 0xd4, 0x91, 0x0a, + 0x56, 0x44, 0x4f, 0xc0, 0x20, 0x7b, 0x6e, 0x1d, 0xfe, 0x27, 0x33, 0xc4, 0x18, 0xec, 0xbb, 0x76, + 0x44, 0xee, 0x55, 0xd5, 0x71, 0xb0, 0xa5, 0x13, 0x86, 0x0c, 0x1d, 0x21, 0x88, 0x6d, 0x1a, 0xd5, + 0x3d, 0xfe, 0x8f, 0x6f, 0xe8, 0x6f, 0xfe, 0x9f, 0x36, 0xa8, 0x3f, 0x94, 0x69, 0x25, 0xfb, 0x7f, + 0x5f, 0x29, 0x01, 0x2c, 0x10, 0xa4, 0x12, 0x4c, 0xa8, 0xd5, 0xaa, 0xc6, 0xfe, 0x07, 0x4d, 0x79, + 0x53, 0xa3, 0x11, 0xc2, 0xa6, 0xff, 0xcd, 0xad, 0x53, 0x5f, 0x20, 0x8f, 0xa0, 0xc0, 0xf1, 0x0b, + 0x49, 0x18, 0x32, 0x99, 0x50, 0xf2, 0x79, 0x18, 0x6f, 0x91, 0x94, 0xc8, 0xb7, 0xa3, 0xe9, 0x55, + 0xf1, 0x98, 0x81, 0xfc, 0x26, 0x30, 0xfa, 0x25, 0x4a, 0x76, 0x16, 0x45, 0x7f, 0x17, 0xde, 0xd3, + 0xf9, 0xcd, 0xcb, 0xa8, 0xef, 0xcd, 0x8b, 0x6a, 0x6a, 0x85, 0x24, 0xe5, 0xcf, 0x5f, 0xba, 0xe4, + 0x5b, 0x5f, 0xba, 0xd4, 0xb0, 0x2e, 0x66, 0x5f, 0x52, 0xa5, 0x9a, 0x9a, 0x4d, 0xdd, 0xd1, 0xfb, + 0x32, 0xa6, 0x7d, 0xde, 0xf7, 0x9b, 0x3e, 0x7c, 0x89, 0xcd, 0xe7, 0x57, 0x17, 0x5c, 0x3f, 0xfe, + 0x6a, 0x04, 0x8e, 0xfb, 0xfc, 0xd8, 0x87, 0xdc, 0xea, 0xce, 0xd9, 0xf6, 0x1e, 0xdf, 0xc7, 0xa3, + 0xe3, 0x4b, 0x10, 0x23, 0xf8, 0xa8, 0xc7, 0xff, 0xc1, 0xc8, 0xfc, 0xea, 0x37, 0xfe, 0xa9, 0x1c, + 0x3c, 0xb5, 0x0a, 0xf4, 0x0a, 0x65, 0x52, 0x78, 0x7f, 0xff, 0xf6, 0x4b, 0x7b, 0x1f, 0x05, 0xb5, + 0x6f, 0x9f, 0x19, 0xc3, 0x36, 0xfc, 0xee, 0xd9, 0x8e, 0x8f, 0x52, 0x59, 0xc4, 0xec, 0x9e, 0x44, + 0xed, 0x23, 0x1c, 0x77, 0xba, 0xff, 0xdf, 0xad, 0x07, 0xfb, 0x4c, 0xc7, 0x76, 0xe1, 0xf0, 0xb3, + 0xa4, 0x6d, 0x6f, 0x99, 0x2c, 0x02, 0xfb, 0x61, 0xf7, 0x34, 0x4f, 0xe2, 0xff, 0x4c, 0x4f, 0x9c, + 0xd4, 0x81, 0x27, 0x1f, 0x5f, 0x20, 0xde, 0x37, 0xdb, 0x71, 0xbe, 0x98, 0xf5, 0x4d, 0x16, 0x8a, + 0x8f, 0x52, 0xfe, 0x65, 0x09, 0x8e, 0xb4, 0x34, 0xcd, 0x63, 0xfc, 0x7c, 0x9b, 0xa7, 0x0a, 0x07, + 0xca, 0x6c, 0xe6, 0xdb, 0x08, 0x7b, 0x7f, 0x4f, 0x61, 0x99, 0x14, 0x01, 0x69, 0xdf, 0x02, 0x87, + 0x82, 0xc2, 0x0a, 0x33, 0xdd, 0x0b, 0xa3, 0xc1, 0x1d, 0x61, 0x6e, 0xae, 0x91, 0xc0, 0x9e, 0xb0, + 0x5c, 0x0e, 0xdb, 0xd9, 0xd5, 0xb5, 0x04, 0x49, 0x17, 0x95, 0xa7, 0xc0, 0x7d, 0xab, 0xea, 0x51, + 0xca, 0x1f, 0x96, 0x60, 0x26, 0xd8, 0x82, 0x2f, 0x19, 0xda, 0x9f, 0xb0, 0xb7, 0xad, 0x8b, 0x5f, + 0x93, 0xe0, 0xae, 0x2e, 0x32, 0x71, 0x03, 0x5c, 0x83, 0x49, 0xdf, 0x4e, 0x80, 0x08, 0xe1, 0xa2, + 0xdb, 0x4f, 0xf5, 0x4e, 0x43, 0xdd, 0x85, 0xef, 0x31, 0x62, 0x94, 0xcf, 0x7d, 0x7b, 0x7a, 0xa2, + 0xb5, 0xce, 0x56, 0x26, 0x5a, 0x57, 0xef, 0xb7, 0xd1, 0x3f, 0x5e, 0x91, 0xe0, 0x81, 0xa0, 0xaa, + 0x6d, 0xf2, 0xd9, 0x37, 0xaa, 0x1f, 0xfe, 0x83, 0x04, 0xa7, 0xfa, 0x11, 0x8e, 0x77, 0xc8, 0x26, + 0x4c, 0x78, 0x99, 0x76, 0xb8, 0x3f, 0xf6, 0x95, 0xbf, 0x33, 0x2f, 0x45, 0x2e, 0xb7, 0x3b, 0x60, + 0x78, 0x93, 0x0f, 0x2c, 0x7f, 0x97, 0xbb, 0x46, 0x0e, 0xee, 0xe6, 0x0a, 0x23, 0x07, 0xf6, 0x73, + 0xdb, 0xf4, 0x45, 0xa4, 0x4d, 0x5f, 0x78, 0xa9, 0xb9, 0x7c, 0x85, 0xc7, 0xad, 0x36, 0x7b, 0x70, + 0x6f, 0x87, 0x89, 0x36, 0xae, 0xcc, 0x47, 0xf5, 0x3e, 0x3c, 0x59, 0x41, 0xad, 0xce, 0x2a, 0xef, + 0xc1, 0x34, 0x6d, 0xb7, 0x8d, 0xa1, 0xef, 0xb4, 0xca, 0x0d, 0x1e, 0x5b, 0xda, 0x36, 0xcd, 0x75, + 0x5f, 0x80, 0x41, 0xd6, 0xcf, 0x5c, 0xdd, 0x03, 0x38, 0x0a, 0x67, 0x20, 0x7f, 0x5c, 0xc4, 0xb2, + 0xa2, 0x10, 0xbb, 0xfd, 0x18, 0xea, 0x47, 0xd7, 0xdb, 0x34, 0x86, 0x7c, 0xc6, 0xf8, 0x96, 0x88, + 0x6a, 0xed, 0xa5, 0xe3, 0xe6, 0xa8, 0xdc, 0xb6, 0xa8, 0xc6, 0x6c, 0x73, 0x67, 0xc3, 0xd7, 0x2f, + 0x8a, 0xf0, 0xe5, 0xea, 0xd4, 0x23, 0x7c, 0xbd, 0x31, 0xa6, 0x77, 0x03, 0x59, 0x0f, 0x31, 0xff, + 0x2c, 0x06, 0xb2, 0x1f, 0x48, 0x70, 0x94, 0xea, 0xe6, 0xdf, 0x88, 0xd8, 0xaf, 0xc9, 0x1f, 0x02, + 0x64, 0x5b, 0x95, 0x72, 0xdb, 0xd1, 0x9d, 0xb6, 0xad, 0xca, 0xe5, 0xc0, 0xfc, 0xf2, 0x10, 0xa0, + 0x6a, 0x60, 0xbb, 0x89, 0x62, 0xb3, 0x5b, 0x72, 0xe9, 0xaa, 0x6f, 0x37, 0xa3, 0x4d, 0x77, 0xc6, + 0x6e, 0x43, 0x77, 0x7e, 0x53, 0x82, 0x6c, 0x3b, 0x95, 0x79, 0xf7, 0x69, 0x70, 0x38, 0x70, 0x48, + 0x10, 0xee, 0xc1, 0x87, 0xfa, 0xd9, 0xca, 0x09, 0x0d, 0xa3, 0x43, 0x16, 0xbe, 0xd3, 0x79, 0xc0, + 0x74, 0xd0, 0x43, 0x5b, 0x33, 0xeb, 0x37, 0x6c, 0xf8, 0x7c, 0xa9, 0x25, 0xae, 0xfe, 0x99, 0xc8, + 0xbd, 0x77, 0x61, 0xaa, 0x83, 0xd4, 0x77, 0x7a, 0xde, 0xdb, 0xee, 0xd8, 0x99, 0xb7, 0x3b, 0x7d, + 0x7f, 0x9c, 0x8f, 0x84, 0xe0, 0x0d, 0x6c, 0xdf, 0x5a, 0xac, 0xdd, 0x13, 0x2e, 0xf9, 0x6d, 0x70, + 0xac, 0x2d, 0x15, 0x97, 0x2d, 0x07, 0xb1, 0x6d, 0xcd, 0x76, 0xb8, 0x58, 0xf7, 0x75, 0x12, 0x2b, + 0x44, 0x4d, 0x69, 0x64, 0x04, 0x69, 0xca, 0x7a, 0xd5, 0x30, 0xea, 0x5c, 0x0c, 0xf9, 0x12, 0x8c, + 0xfb, 0x60, 0xbc, 0x91, 0x73, 0x10, 0x33, 0x0d, 0xfe, 0x79, 0x82, 0xe1, 0x33, 0xc7, 0x3b, 0xee, + 0xde, 0x1b, 0x46, 0x9d, 0xab, 0x4d, 0xf1, 0xe5, 0x49, 0x40, 0x8c, 0x19, 0xdd, 0xc8, 0x17, 0x4d, + 0xac, 0xc1, 0x44, 0x00, 0xca, 0x1b, 0x79, 0x5d, 0x87, 0x04, 0x67, 0xbe, 0x77, 0x08, 0xe2, 0x94, + 0x2b, 0xfa, 0x98, 0x14, 0xf8, 0x66, 0xd0, 0x6c, 0x27, 0x36, 0xed, 0xd7, 0xc4, 0xd9, 0xd3, 0x7d, + 0xe3, 0xf3, 0x9c, 0xed, 0xd4, 0x7b, 0xfe, 0xed, 0x77, 0x3f, 0x12, 0xb9, 0x07, 0xc9, 0xa7, 0x3b, + 0xac, 0xc6, 0x7d, 0xe3, 0xe5, 0xb3, 0x81, 0xb7, 0xef, 0x0f, 0xf7, 0xd7, 0x94, 0x90, 0x6c, 0xb6, + 0x5f, 0x74, 0x2e, 0xd8, 0x79, 0x2a, 0xd8, 0x59, 0xf4, 0x58, 0x6f, 0xc1, 0x4e, 0xbf, 0x33, 0x38, + 0x68, 0xde, 0x8d, 0x7e, 0x47, 0x82, 0xc9, 0x76, 0x4b, 0x3a, 0xf4, 0x64, 0x7f, 0x52, 0xb4, 0xa6, + 0x14, 0xd9, 0xa7, 0x0e, 0x40, 0xc9, 0x55, 0x99, 0xa7, 0xaa, 0xe4, 0xd1, 0xd3, 0x07, 0x50, 0xe5, + 0xb4, 0x7f, 0x7f, 0xff, 0x7f, 0x4b, 0x70, 0xa2, 0xeb, 0x0a, 0x09, 0xe5, 0xfb, 0x93, 0xb2, 0x4b, + 0xee, 0x94, 0x2d, 0xbc, 0x1e, 0x16, 0x5c, 0xe3, 0x67, 0xa9, 0xc6, 0x97, 0xd0, 0xc2, 0x41, 0x34, + 0x6e, 0x7b, 0x88, 0x82, 0x7e, 0x33, 0x78, 0xb3, 0xb0, 0xbb, 0x3b, 0xb5, 0x2c, 0x3c, 0x7a, 0x0c, + 0x8c, 0xd6, 0xa4, 0x56, 0x7e, 0x9e, 0xaa, 0xa0, 0xa0, 0xd5, 0xd7, 0xd9, 0x69, 0xa7, 0xdf, 0x19, + 0x0c, 0xfc, 0xef, 0x46, 0xff, 0x4b, 0x6a, 0x7f, 0x51, 0xf0, 0x89, 0xae, 0x22, 0x76, 0x5e, 0x54, + 0x65, 0x9f, 0xdc, 0x3f, 0x21, 0x57, 0xb2, 0x41, 0x95, 0xac, 0x21, 0x7c, 0xbb, 0x95, 0x6c, 0xdb, + 0x89, 0xe8, 0xeb, 0x12, 0x4c, 0xb6, 0x5b, 0x93, 0xf4, 0x18, 0x96, 0x5d, 0x16, 0x59, 0x3d, 0x86, + 0x65, 0xb7, 0x05, 0x90, 0xfc, 0x26, 0xaa, 0xfc, 0x39, 0xf4, 0x78, 0x27, 0xe5, 0xbb, 0xf6, 0x22, + 0x19, 0x8b, 0x5d, 0x93, 0xfc, 0x1e, 0x63, 0xb1, 0x9f, 0x75, 0x4c, 0x8f, 0xb1, 0xd8, 0xd7, 0x1a, + 0xa3, 0xf7, 0x58, 0x74, 0x35, 0xeb, 0xb3, 0x1b, 0x6d, 0xf4, 0x55, 0x09, 0x46, 0x02, 0x19, 0x31, + 0x7a, 0xb4, 0xab, 0xa0, 0xed, 0x16, 0x0c, 0xd9, 0x33, 0xfb, 0x21, 0xe1, 0xba, 0x2c, 0x50, 0x5d, + 0xe6, 0x50, 0xfe, 0x20, 0xba, 0x04, 0xcf, 0x4a, 0xbf, 0x29, 0xc1, 0x44, 0x9b, 0x2c, 0xb3, 0xc7, + 0x28, 0xec, 0x9c, 0x34, 0x67, 0x9f, 0xdc, 0x3f, 0x21, 0xd7, 0xea, 0x02, 0xd5, 0xea, 0xad, 0xe8, + 0x2d, 0x07, 0xd1, 0xca, 0x37, 0x3f, 0xdf, 0xf4, 0xee, 0x5d, 0xf9, 0xda, 0x41, 0xe7, 0xf6, 0x29, + 0x98, 0x50, 0xe8, 0x89, 0x7d, 0xd3, 0x71, 0x7d, 0x9e, 0xa3, 0xfa, 0x3c, 0x8b, 0x56, 0x5e, 0x9f, + 0x3e, 0xad, 0xd3, 0xfa, 0x17, 0x5b, 0x5f, 0x00, 0x76, 0xf7, 0xa2, 0xb6, 0xc9, 0x6a, 0xf6, 0xb1, + 0x7d, 0xd1, 0x70, 0xa5, 0x9e, 0xa4, 0x4a, 0x9d, 0x41, 0x8f, 0x74, 0x52, 0xca, 0x77, 0xb9, 0x4e, + 0xd3, 0xb7, 0x8c, 0xd3, 0xef, 0x64, 0x29, 0xf0, 0xbb, 0xd1, 0x4f, 0x8b, 0x8b, 0x4d, 0x27, 0xbb, + 0xb6, 0xeb, 0xcb, 0x63, 0xb3, 0x0f, 0xf4, 0x81, 0xc9, 0xe5, 0xba, 0x87, 0xca, 0x35, 0x85, 0x8e, + 0x77, 0x92, 0x8b, 0xe4, 0xb2, 0xe8, 0x83, 0x92, 0x7b, 0x17, 0xf2, 0x54, 0x77, 0xde, 0xfe, 0x64, + 0x37, 0xfb, 0x60, 0x5f, 0xb8, 0x5c, 0x92, 0xfb, 0xa8, 0x24, 0x33, 0x68, 0xaa, 0xa3, 0x24, 0x2c, + 0xf5, 0xbd, 0xdd, 0x37, 0x07, 0xae, 0x1f, 0x81, 0xe9, 0x0e, 0x2d, 0x3a, 0xbb, 0x3d, 0xce, 0xb8, + 0xba, 0x3c, 0x84, 0xed, 0xf9, 0xd0, 0xf5, 0x76, 0x7f, 0xb4, 0xb5, 0xcf, 0x03, 0xb1, 0xdf, 0x8a, + 0x01, 0x5a, 0xb2, 0x6b, 0x73, 0x16, 0x66, 0xff, 0x40, 0x92, 0x8f, 0xf2, 0xd0, 0x0b, 0x2f, 0xe9, + 0x75, 0xbd, 0xf0, 0x5a, 0x0a, 0xbc, 0x99, 0x8a, 0xec, 0xef, 0x5d, 0x66, 0xdf, 0x0f, 0xa7, 0xa2, + 0x3f, 0x96, 0x87, 0x53, 0xed, 0xef, 0x55, 0xc7, 0x6e, 0xdf, 0x03, 0x8c, 0xf8, 0x41, 0x1f, 0xa1, + 0xf0, 0xf7, 0x90, 0x83, 0x5d, 0xde, 0x43, 0x66, 0x3a, 0x3e, 0x7a, 0xe4, 0xd4, 0xe8, 0xac, 0xf8, + 0x84, 0xe9, 0x50, 0x7f, 0x37, 0x61, 0xf9, 0x37, 0x4e, 0xbd, 0x2d, 0x84, 0xe3, 0x90, 0x6d, 0x75, + 0x27, 0x77, 0x50, 0x7f, 0x24, 0x0a, 0xe9, 0x25, 0xbb, 0x56, 0xaa, 0x6a, 0xce, 0x1d, 0xf2, 0xb5, + 0xa7, 0x3b, 0x3f, 0x6a, 0x41, 0xb7, 0x6e, 0x4e, 0x8f, 0x32, 0x9b, 0x76, 0xb1, 0x64, 0x03, 0xc6, + 0x42, 0x4f, 0x89, 0xb9, 0x67, 0x15, 0x0f, 0xf2, 0xa2, 0x39, 0xc4, 0x4a, 0xa6, 0x6f, 0x10, 0x7c, + 0xfe, 0x8d, 0x76, 0xdb, 0x3b, 0x33, 0x73, 0xa8, 0x8b, 0x77, 0xf2, 0x05, 0xa0, 0xd7, 0x67, 0x59, + 0xc8, 0x84, 0x3b, 0xc5, 0xed, 0xb1, 0x3f, 0x90, 0x60, 0x78, 0xc9, 0x16, 0xa9, 0x20, 0xfe, 0x09, + 0x7d, 0x7f, 0xf4, 0x84, 0xfb, 0xfd, 0xef, 0x68, 0x7f, 0x7e, 0x2b, 0xbe, 0x09, 0xee, 0x19, 0xe1, + 0x10, 0x4c, 0xf8, 0xf4, 0x74, 0xf5, 0xff, 0xed, 0x08, 0x8d, 0x8f, 0x05, 0x5c, 0xd3, 0x74, 0x37, + 0x8b, 0xc4, 0x7f, 0x5e, 0x5f, 0x57, 0x78, 0x76, 0x8e, 0x1d, 0xd4, 0xce, 0x3b, 0x34, 0x40, 0x84, + 0xec, 0xe9, 0x6e, 0x7c, 0x2d, 0xb5, 0xbe, 0xfd, 0x91, 0xf6, 0xf1, 0x59, 0x9d, 0xd0, 0x0b, 0x1f, + 0xf9, 0x35, 0x09, 0x46, 0x96, 0xec, 0xda, 0x86, 0x5e, 0xfd, 0xff, 0xde, 0x7f, 0xb7, 0xe0, 0x50, + 0x40, 0xd3, 0x3b, 0x64, 0xd2, 0x33, 0xaf, 0xc4, 0x20, 0xba, 0x64, 0xd7, 0xd0, 0x4b, 0x30, 0x16, + 0x4e, 0x1a, 0x3a, 0xe6, 0x82, 0xad, 0x33, 0x42, 0xe7, 0xf5, 0x5a, 0xe7, 0xd9, 0x03, 0xed, 0xc0, + 0x48, 0x70, 0xe6, 0x38, 0xd9, 0x85, 0x49, 0x00, 0x33, 0xfb, 0x48, 0xbf, 0x98, 0x6e, 0x63, 0xef, + 0x80, 0x84, 0x1b, 0xf4, 0xee, 0xee, 0x42, 0x2d, 0x90, 0x3a, 0x67, 0xb7, 0x6d, 0xc2, 0x0a, 0xb1, + 0x5e, 0x38, 0xa4, 0x74, 0xb3, 0x5e, 0x08, 0xb7, 0xab, 0xf5, 0x3a, 0x0d, 0xad, 0x4d, 0x00, 0xdf, + 0x38, 0xb8, 0xb7, 0x0b, 0x07, 0x0f, 0x2d, 0xfb, 0x70, 0x5f, 0x68, 0xee, 0xa1, 0xd3, 0x6d, 0x4e, + 0xc6, 0xff, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xd4, 0x8f, 0xbc, 0xb2, 0xb6, 0x97, 0x00, 0x00, } r := bytes.NewReader(gzipped) gzipr, err := compress_gzip.NewReader(r) diff --git a/x/staking/types/tx.pb.go b/x/staking/types/tx.pb.go index 50e1765ff6c0..c3a1bf706599 100644 --- a/x/staking/types/tx.pb.go +++ b/x/staking/types/tx.pb.go @@ -13,11 +13,11 @@ import ( 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" + _ "google.golang.org/protobuf/types/known/timestamppb" io "io" math "math" math_bits "math/bits" diff --git a/x/upgrade/types/upgrade.pb.go b/x/upgrade/types/upgrade.pb.go index c77d90f34df8..ae27a70fd5dc 100644 --- a/x/upgrade/types/upgrade.pb.go +++ b/x/upgrade/types/upgrade.pb.go @@ -9,7 +9,7 @@ import ( _ "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" + _ "google.golang.org/protobuf/types/known/timestamppb" io "io" math "math" math_bits "math/bits" From a65f838eb1e6cacf98db2a13ee762221baf93dee Mon Sep 17 00:00:00 2001 From: Albert Chon Date: Fri, 5 Mar 2021 17:25:19 +0100 Subject: [PATCH 165/214] reduce gas costs by 10x for transient store operations (#8790) * reduce gas costs by 10x for transient store operations * fix TestTransientGasConfig for ReadCostFlat * added changelog entry * fix changelog * fix changelog Co-authored-by: Alessio Treglia --- CHANGELOG.md | 1 + store/types/gas.go | 11 +++++++++-- store/types/gas_test.go | 14 +++++++------- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fd2ae140a917..972be3a80771 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -68,6 +68,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (x/gov) [\#7733](https://github.com/cosmos/cosmos-sdk/pull/7733) ADR 037 Implementation: Governance Split Votes * (x/bank) [\#8656](https://github.com/cosmos/cosmos-sdk/pull/8656) balance and supply are now correctly tracked via `coin_spent`, `coin_received`, `coinbase` and `burn` events. * (x/bank) [\#8517](https://github.com/cosmos/cosmos-sdk/pull/8517) Supply is now stored and tracked as `sdk.Coins` +* (store) [\#8790](https://github.com/cosmos/cosmos-sdk/pull/8790) Reduce gas costs by 10x for transient store operations. ### Improvements diff --git a/store/types/gas.go b/store/types/gas.go index c6c94f859e02..028edc350ecd 100644 --- a/store/types/gas.go +++ b/store/types/gas.go @@ -176,6 +176,13 @@ func KVGasConfig() GasConfig { // TransientGasConfig returns a default gas config for TransientStores. func TransientGasConfig() GasConfig { - // TODO: define gasconfig for transient stores - return KVGasConfig() + return GasConfig{ + HasCost: 100, + DeleteCost: 100, + ReadCostFlat: 100, + ReadCostPerByte: 0, + WriteCostFlat: 200, + WriteCostPerByte: 3, + IterNextCostFlat: 3, + } } diff --git a/store/types/gas_test.go b/store/types/gas_test.go index bd62d463cd67..f4490747135b 100644 --- a/store/types/gas_test.go +++ b/store/types/gas_test.go @@ -93,12 +93,12 @@ func TestTransientGasConfig(t *testing.T) { t.Parallel() config := TransientGasConfig() require.Equal(t, config, GasConfig{ - HasCost: 1000, - DeleteCost: 1000, - ReadCostFlat: 1000, - ReadCostPerByte: 3, - WriteCostFlat: 2000, - WriteCostPerByte: 30, - IterNextCostFlat: 30, + HasCost: 100, + DeleteCost: 100, + ReadCostFlat: 100, + ReadCostPerByte: 0, + WriteCostFlat: 200, + WriteCostPerByte: 3, + IterNextCostFlat: 3, }) } From be23295bdf03b0d2a6801516b33998be66d4bb7e Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Mon, 8 Mar 2021 14:38:24 +0000 Subject: [PATCH 166/214] x/gov: fix NormalizeProposalType() return values (#8808) Closes: #8806 --- x/gov/client/cli/cli_test.go | 8 ++++ x/gov/client/rest/grpc_query_test.go | 20 +++++++--- x/gov/client/rest/rest_test.go | 56 ++++++++++++++++++++++++++++ x/gov/client/utils/utils.go | 8 ++-- x/gov/client/utils/utils_test.go | 32 +++++++++++++++- 5 files changed, 113 insertions(+), 11 deletions(-) diff --git a/x/gov/client/cli/cli_test.go b/x/gov/client/cli/cli_test.go index 54bcdde07d48..8b56aff9d2b7 100644 --- a/x/gov/client/cli/cli_test.go +++ b/x/gov/client/cli/cli_test.go @@ -431,6 +431,14 @@ func (s *IntegrationTestSuite) TestCmdGetProposals() { }, false, }, + { + "get proposals with invalid status", + []string{ + "--status=unknown", + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + true, + }, } 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 9e4984a9aaab..57e0d8f2b782 100644 --- a/x/gov/client/rest/grpc_query_test.go +++ b/x/gov/client/rest/grpc_query_test.go @@ -119,10 +119,11 @@ func (s *IntegrationTestSuite) TestGetProposalsGRPC() { val := s.network.Validators[0] testCases := []struct { - name string - url string - headers map[string]string - expErr bool + name string + url string + headers map[string]string + wantNumProposals int + expErr bool }{ { "get proposals with height 1", @@ -130,12 +131,21 @@ func (s *IntegrationTestSuite) TestGetProposalsGRPC() { map[string]string{ grpctypes.GRPCBlockHeightHeader: "1", }, + 0, true, }, { "valid request", fmt.Sprintf("%s/cosmos/gov/v1beta1/proposals", val.APIAddress), map[string]string{}, + 3, + false, + }, + { + "valid request with filter by status", + fmt.Sprintf("%s/cosmos/gov/v1beta1/proposals?proposal_status=1", val.APIAddress), + map[string]string{}, + 1, false, }, } @@ -153,7 +163,7 @@ func (s *IntegrationTestSuite) TestGetProposalsGRPC() { s.Require().Empty(proposals.Proposals) } else { s.Require().NoError(err) - s.Require().Len(proposals.Proposals, 3) + s.Require().Len(proposals.Proposals, tc.wantNumProposals) } }) } diff --git a/x/gov/client/rest/rest_test.go b/x/gov/client/rest/rest_test.go index adca107ada07..9049bd264017 100644 --- a/x/gov/client/rest/rest_test.go +++ b/x/gov/client/rest/rest_test.go @@ -10,6 +10,62 @@ import ( "github.com/cosmos/cosmos-sdk/x/gov/types" ) +func (s *IntegrationTestSuite) TestLegacyGetAllProposals() { + val := s.network.Validators[0] + + testCases := []struct { + name string + url string + numProposals int + expErr bool + expErrMsg string + }{ + { + "get all existing proposals", + fmt.Sprintf("%s/gov/proposals", val.APIAddress), + 3, false, "", + }, + { + "get proposals in deposit period", + fmt.Sprintf("%s/gov/proposals?status=deposit_period", val.APIAddress), + 1, false, "", + }, + { + "get proposals in voting period", + fmt.Sprintf("%s/gov/proposals?status=voting_period", val.APIAddress), + 2, false, "", + }, + { + "wrong status parameter", + fmt.Sprintf("%s/gov/proposals?status=invalidstatus", val.APIAddress), + 0, true, "'invalidstatus' is not a valid proposal status", + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + respJSON, err := rest.GetRequest(tc.url) + s.Require().NoError(err) + + if tc.expErr { + var errResp rest.ErrorResponse + s.Require().NoError(val.ClientCtx.LegacyAmino.UnmarshalJSON(respJSON, &errResp)) + s.Require().Equal(errResp.Error, tc.expErrMsg) + } else { + var resp = rest.ResponseWithHeight{} + err = val.ClientCtx.LegacyAmino.UnmarshalJSON(respJSON, &resp) + s.Require().NoError(err) + + // Check results. + var proposals types.Proposals + s.Require().NoError(val.ClientCtx.LegacyAmino.UnmarshalJSON(resp.Result, &proposals)) + s.Require().Equal(tc.numProposals, len(proposals)) + } + }) + } +} + func (s *IntegrationTestSuite) TestLegacyGetVote() { val := s.network.Validators[0] voterAddressBech32 := val.Address.String() diff --git a/x/gov/client/utils/utils.go b/x/gov/client/utils/utils.go index c88be3df3cb3..f0bf6ead263a 100644 --- a/x/gov/client/utils/utils.go +++ b/x/gov/client/utils/utils.go @@ -55,13 +55,13 @@ func NormalizeProposalType(proposalType string) string { func NormalizeProposalStatus(status string) string { switch status { case "DepositPeriod", "deposit_period": - return "DepositPeriod" + return types.StatusDepositPeriod.String() case "VotingPeriod", "voting_period": - return "VotingPeriod" + return types.StatusVotingPeriod.String() case "Passed", "passed": - return "Passed" + return types.StatusPassed.String() case "Rejected", "rejected": - return "Rejected" + return types.StatusRejected.String() default: return status } diff --git a/x/gov/client/utils/utils_test.go b/x/gov/client/utils/utils_test.go index 0da66b3c29ba..bc3c43ca81d6 100644 --- a/x/gov/client/utils/utils_test.go +++ b/x/gov/client/utils/utils_test.go @@ -1,9 +1,11 @@ -package utils +package utils_test import ( "testing" "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/x/gov/client/utils" ) func TestNormalizeWeightedVoteOptions(t *testing.T) { @@ -50,7 +52,33 @@ func TestNormalizeWeightedVoteOptions(t *testing.T) { } for _, tc := range cases { - normalized := NormalizeWeightedVoteOptions(tc.options) + normalized := utils.NormalizeWeightedVoteOptions(tc.options) require.Equal(t, normalized, tc.normalized) } } + +func TestNormalizeProposalStatus(t *testing.T) { + type args struct { + status string + } + tests := []struct { + name string + args args + want string + }{ + {"invalid", args{"unknown"}, "unknown"}, + {"deposit_period", args{"deposit_period"}, "PROPOSAL_STATUS_DEPOSIT_PERIOD"}, + {"DepositPeriod", args{"DepositPeriod"}, "PROPOSAL_STATUS_DEPOSIT_PERIOD"}, + {"voting_period", args{"deposit_period"}, "PROPOSAL_STATUS_DEPOSIT_PERIOD"}, + {"VotingPeriod", args{"DepositPeriod"}, "PROPOSAL_STATUS_DEPOSIT_PERIOD"}, + {"passed", args{"passed"}, "PROPOSAL_STATUS_PASSED"}, + {"Passed", args{"Passed"}, "PROPOSAL_STATUS_PASSED"}, + {"Rejected", args{"Rejected"}, "PROPOSAL_STATUS_REJECTED"}, + {"rejected", args{"rejected"}, "PROPOSAL_STATUS_REJECTED"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + require.Equal(t, tt.want, utils.NormalizeProposalStatus(tt.args.status)) + }) + } +} From c2d5b24f58a6537d2a7205ca4f2960c8424c4bef Mon Sep 17 00:00:00 2001 From: Emmanuel T Odeke Date: Mon, 8 Mar 2021 09:16:23 -0800 Subject: [PATCH 167/214] store/cachekv: use typed types/kv.List instead of container/list.List (#8811) Reduces CPU burn by using a typed List to avoid the expensive type assertions from using an interface. This is the only option for now until Go makes generics generally available. The change brings time spent on the time assertion cummulatively to: 580ms down from 6.88s Explanation: The type assertions were showing up heavily in profiles: * Before this commit ```shell Total: 42.18s ROUTINE ======================== github.com/cosmos/cosmos-sdk/store/cachekv.newMemIterator in /Users/emmanuelodeke/go/src/github.com/cosmos/cosmos-sdk/store/cachekv/memiterator.go 14.01s 18.87s (flat, cum) 44.74% of Total . . 17: items []*kv.Pair . . 18: ascending bool . . 19:} . . 20: . . 21:func newMemIterator(start, end []byte, items *list.List, ascending bool) *memIterator { . 620ms 22: itemsInDomain := make([]*kv.Pair, 0, items.Len()) . . 23: . . 24: var entered bool . . 25: 510ms 870ms 26: for e := items.Front(); e != nil; e = e.Next() { 6.85s 6.88s 27: item := e.Value.(*kv.Pair) 5.71s 8.19s 28: if !dbm.IsKeyInDomain(item.Key, start, end) { 120ms 120ms 29: if entered { . . 30: break . . 31: } . . 32: . . 33: continue . . 34: } . . 35: 820ms 980ms 36: itemsInDomain = append(itemsInDomain, item) . . 37: entered = true . . 38: } . . 39: . 1.21s 40: return &memIterator{ . . 41: start: start, . . 42: end: end, . . 43: items: itemsInDomain, . . 44: ascending: ascending, . . 45: } ``` and given that the list only uses that type, it is only right to lift the code from container/list.List, and only modify Element.Value's type. For emphasis, the code is basically just a retrofit of container/list/list.go but with a typing, and we'll keep it as is until perhaps Go1.17 or Go1.18 or when everyone uses Go1.17+ after generics have landed. * After this commit ```shell Total: 45.25s ROUTINE ======================== github.com/cosmos/cosmos-sdk/store/cachekv.newMemIterator in /Users/emmanuelodeke/go/src/github.com/cosmos/cosmos-sdk/store/cachekv/memiterator.go 4.84s 6.77s (flat, cum) 14.96% of Total . . 16: items []*kv.Pair . . 17: ascending bool . . 18:} . . 19: . . 20:func newMemIterator(start, end []byte, items *kv.List, ascending bool) *memIterator { . 330ms 21: itemsInDomain := make([]*kv.Pair, 0, items.Len()) . . 22: . . 23: var entered bool . . 24: 60ms 160ms 25: for e := items.Front(); e != nil; e = e.Next() { 580ms 580ms 26: item := e.Value 3.68s 4.78s 27: if !dbm.IsKeyInDomain(item.Key, start, end) { 80ms 80ms 28: if entered { . . 29: break . . 30: } . . 31: . . 32: continue . . 33: } . . 34: 440ms 580ms 35: itemsInDomain = append(itemsInDomain, item) . . 36: entered = true . . 37: } . . 38: . 260ms 39: return &memIterator{ . . 40: start: start, . . 41: end: end, . . 42: items: itemsInDomain, . . 43: ascending: ascending, . . 44: } ``` Fixes #8810 --- store/cachekv/memiterator.go | 5 +- store/cachekv/store.go | 9 +- types/kv/kv.go | 4 +- types/kv/list.go | 236 +++++++++++++++++++++++++++++++++++ 4 files changed, 245 insertions(+), 9 deletions(-) create mode 100644 types/kv/list.go diff --git a/store/cachekv/memiterator.go b/store/cachekv/memiterator.go index 675494b8ffe2..b197ac141660 100644 --- a/store/cachekv/memiterator.go +++ b/store/cachekv/memiterator.go @@ -1,7 +1,6 @@ package cachekv import ( - "container/list" "errors" dbm "github.com/tendermint/tm-db" @@ -18,13 +17,13 @@ type memIterator struct { ascending bool } -func newMemIterator(start, end []byte, items *list.List, ascending bool) *memIterator { +func newMemIterator(start, end []byte, items *kv.List, ascending bool) *memIterator { itemsInDomain := make([]*kv.Pair, 0, items.Len()) var entered bool for e := items.Front(); e != nil; e = e.Next() { - item := e.Value.(*kv.Pair) + item := e.Value if !dbm.IsKeyInDomain(item.Key, start, end) { if entered { break diff --git a/store/cachekv/store.go b/store/cachekv/store.go index a953d4436b1b..af5d75f9c83e 100644 --- a/store/cachekv/store.go +++ b/store/cachekv/store.go @@ -2,7 +2,6 @@ package cachekv import ( "bytes" - "container/list" "io" "sort" "sync" @@ -30,7 +29,7 @@ type Store struct { mtx sync.Mutex cache map[string]*cValue unsortedCache map[string]struct{} - sortedCache *list.List // always ascending sorted + sortedCache *kv.List // always ascending sorted parent types.KVStore } @@ -41,7 +40,7 @@ func NewStore(parent types.KVStore) *Store { return &Store{ cache: make(map[string]*cValue), unsortedCache: make(map[string]struct{}), - sortedCache: list.New(), + sortedCache: kv.NewList(), parent: parent, } } @@ -134,7 +133,7 @@ func (store *Store) Write() { // Clear the cache store.cache = make(map[string]*cValue) store.unsortedCache = make(map[string]struct{}) - store.sortedCache = list.New() + store.sortedCache = kv.NewList() } // CacheWrap implements CacheWrapper. @@ -206,7 +205,7 @@ func (store *Store) dirtyItems(start, end []byte) { for e := store.sortedCache.Front(); e != nil && len(unsorted) != 0; { uitem := unsorted[0] - sitem := e.Value.(*kv.Pair) + sitem := e.Value comp := bytes.Compare(uitem.Key, sitem.Key) switch comp { diff --git a/types/kv/kv.go b/types/kv/kv.go index a0aab3f47fec..1f3da91cc2c5 100644 --- a/types/kv/kv.go +++ b/types/kv/kv.go @@ -23,4 +23,6 @@ func (kvs Pairs) Less(i, j int) bool { } func (kvs Pairs) Swap(i, j int) { kvs.Pairs[i], kvs.Pairs[j] = kvs.Pairs[j], kvs.Pairs[i] } -func (kvs Pairs) Sort() { sort.Sort(kvs) } + +// Sort invokes sort.Sort on kvs. +func (kvs Pairs) Sort() { sort.Sort(kvs) } diff --git a/types/kv/list.go b/types/kv/list.go new file mode 100644 index 000000000000..9e928c84912b --- /dev/null +++ b/types/kv/list.go @@ -0,0 +1,236 @@ +package kv + +// This code was copied from golang.org/pkg/container/list, but specially adapted +// for use with kv.Pair to avoid the type assertion CPU expense of using Value with +// an interface, per https://github.com/cosmos/cosmos-sdk/issues/8810 +// +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Element is an element of a linked list. +type Element struct { + // Next and previous pointers in the doubly-linked list of elements. + // To simplify the implementation, internally a list l is implemented + // as a ring, such that &l.root is both the next element of the last + // list element (l.Back()) and the previous element of the first list + // element (l.Front()). + next, prev *Element + + // The list to which this element belongs. + list *List + + // The value stored with this element. + Value *Pair +} + +// Next returns the next list element or nil. +func (e *Element) Next() *Element { + if p := e.next; e.list != nil && p != &e.list.root { + return p + } + return nil +} + +// Prev returns the previous list element or nil. +func (e *Element) Prev() *Element { + if p := e.prev; e.list != nil && p != &e.list.root { + return p + } + return nil +} + +// List represents a doubly linked list. +// The zero value for List is an empty list ready to use. +type List struct { + root Element // sentinel list element, only &root, root.prev, and root.next are used + len int // current list length excluding (this) sentinel element +} + +// Init initializes or clears list l. +func (l *List) Init() *List { + l.root.next = &l.root + l.root.prev = &l.root + l.len = 0 + return l +} + +// NewList returns an initialized list. +func NewList() *List { return new(List).Init() } + +// Len returns the number of elements of list l. +// The complexity is O(1). +func (l *List) Len() int { return l.len } + +// Front returns the first element of list l or nil if the list is empty. +func (l *List) Front() *Element { + if l.len == 0 { + return nil + } + return l.root.next +} + +// Back returns the last element of list l or nil if the list is empty. +func (l *List) Back() *Element { + if l.len == 0 { + return nil + } + return l.root.prev +} + +// lazyInit lazily initializes a zero List value. +func (l *List) lazyInit() { + if l.root.next == nil { + l.Init() + } +} + +// insert inserts e after at, increments l.len, and returns e. +func (l *List) insert(e, at *Element) *Element { + e.prev = at + e.next = at.next + e.prev.next = e + e.next.prev = e + e.list = l + l.len++ + return e +} + +// insertValue is a convenience wrapper for insert(&Element{Value: v}, at). +func (l *List) insertValue(v *Pair, at *Element) *Element { + return l.insert(&Element{Value: v}, at) +} + +// remove removes e from its list, decrements l.len, and returns e. +func (l *List) remove(e *Element) *Element { + e.prev.next = e.next + e.next.prev = e.prev + e.next = nil // avoid memory leaks + e.prev = nil // avoid memory leaks + e.list = nil + l.len-- + return e +} + +// move moves e to next to at and returns e. +// nolint: unparam +func (l *List) move(e, at *Element) *Element { + if e == at { + return e + } + e.prev.next = e.next + e.next.prev = e.prev + + e.prev = at + e.next = at.next + e.prev.next = e + e.next.prev = e + + return e +} + +// Remove removes e from l if e is an element of list l. +// It returns the element value e.Value. +// The element must not be nil. +func (l *List) Remove(e *Element) *Pair { + if e.list == l { + // if e.list == l, l must have been initialized when e was inserted + // in l or l == nil (e is a zero Element) and l.remove will crash + l.remove(e) + } + return e.Value +} + +// PushFront inserts a new element e with value v at the front of list l and returns e. +func (l *List) PushFront(v *Pair) *Element { + l.lazyInit() + return l.insertValue(v, &l.root) +} + +// PushBack inserts a new element e with value v at the back of list l and returns e. +func (l *List) PushBack(v *Pair) *Element { + l.lazyInit() + return l.insertValue(v, l.root.prev) +} + +// InsertBefore inserts a new element e with value v immediately before mark and returns e. +// If mark is not an element of l, the list is not modified. +// The mark must not be nil. +func (l *List) InsertBefore(v *Pair, mark *Element) *Element { + if mark.list != l { + return nil + } + // see comment in List.Remove about initialization of l + return l.insertValue(v, mark.prev) +} + +// InsertAfter inserts a new element e with value v immediately after mark and returns e. +// If mark is not an element of l, the list is not modified. +// The mark must not be nil. +func (l *List) InsertAfter(v *Pair, mark *Element) *Element { + if mark.list != l { + return nil + } + // see comment in List.Remove about initialization of l + return l.insertValue(v, mark) +} + +// MoveToFront moves element e to the front of list l. +// If e is not an element of l, the list is not modified. +// The element must not be nil. +func (l *List) MoveToFront(e *Element) { + if e.list != l || l.root.next == e { + return + } + // see comment in List.Remove about initialization of l + l.move(e, &l.root) +} + +// MoveToBack moves element e to the back of list l. +// If e is not an element of l, the list is not modified. +// The element must not be nil. +func (l *List) MoveToBack(e *Element) { + if e.list != l || l.root.prev == e { + return + } + // see comment in List.Remove about initialization of l + l.move(e, l.root.prev) +} + +// MoveBefore moves element e to its new position before mark. +// If e or mark is not an element of l, or e == mark, the list is not modified. +// The element and mark must not be nil. +func (l *List) MoveBefore(e, mark *Element) { + if e.list != l || e == mark || mark.list != l { + return + } + l.move(e, mark.prev) +} + +// MoveAfter moves element e to its new position after mark. +// If e or mark is not an element of l, or e == mark, the list is not modified. +// The element and mark must not be nil. +func (l *List) MoveAfter(e, mark *Element) { + if e.list != l || e == mark || mark.list != l { + return + } + l.move(e, mark) +} + +// PushBackList inserts a copy of another list at the back of list l. +// The lists l and other may be the same. They must not be nil. +func (l *List) PushBackList(other *List) { + l.lazyInit() + for i, e := other.Len(), other.Front(); i > 0; i, e = i-1, e.Next() { + l.insertValue(e.Value, l.root.prev) + } +} + +// PushFrontList inserts a copy of another list at the front of list l. +// The lists l and other may be the same. They must not be nil. +func (l *List) PushFrontList(other *List) { + l.lazyInit() + for i, e := other.Len(), other.Back(); i > 0; i, e = i-1, e.Prev() { + l.insertValue(e.Value, &l.root) + } +} From 6ac8898fec9bd7ea2c1e5c79e0ed0c3f827beb55 Mon Sep 17 00:00:00 2001 From: Amaury <1293565+amaurym@users.noreply.github.com> Date: Mon, 8 Mar 2021 23:36:06 +0100 Subject: [PATCH 168/214] Move all migration scripts to v043 (#8814) * Move all migration scripts to v043 * Fix permaling * Fix test * Fix test again Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- .../adr-041-in-place-store-migrations.md | 2 +- x/bank/keeper/migrations.go | 4 ++-- x/bank/legacy/{v042 => v043}/store.go | 2 +- x/bank/legacy/{v042 => v043}/store_test.go | 8 ++++---- x/distribution/keeper/migrations.go | 4 ++-- x/distribution/legacy/{v042 => v043}/helpers.go | 2 +- x/distribution/legacy/{v042 => v043}/store.go | 2 +- .../legacy/{v042 => v043}/store_test.go | 6 +++--- x/gov/keeper/migrations.go | 4 ++-- x/gov/legacy/{v042 => v043}/store.go | 2 +- x/gov/legacy/{v042 => v043}/store_test.go | 6 +++--- x/slashing/keeper/migrations.go | 4 ++-- x/slashing/legacy/{v042 => v043}/store.go | 10 +++++----- x/slashing/legacy/{v042 => v043}/store_test.go | 6 +++--- x/staking/keeper/migrations.go | 4 ++-- x/staking/legacy/{v042 => v043}/store.go | 16 ++++++++-------- x/staking/legacy/{v042 => v043}/store_test.go | 6 +++--- 17 files changed, 44 insertions(+), 44 deletions(-) rename x/bank/legacy/{v042 => v043}/store.go (99%) rename x/bank/legacy/{v042 => v043}/store_test.go (91%) rename x/distribution/legacy/{v042 => v043}/helpers.go (99%) rename x/distribution/legacy/{v042 => v043}/store.go (98%) rename x/distribution/legacy/{v042 => v043}/store_test.go (94%) rename x/gov/legacy/{v042 => v043}/store.go (99%) rename x/gov/legacy/{v042 => v043}/store_test.go (95%) rename x/slashing/legacy/{v042 => v043}/store.go (62%) rename x/slashing/legacy/{v042 => v043}/store_test.go (92%) rename x/staking/legacy/{v042 => v043}/store.go (85%) rename x/staking/legacy/{v042 => v043}/store_test.go (96%) diff --git a/docs/architecture/adr-041-in-place-store-migrations.md b/docs/architecture/adr-041-in-place-store-migrations.md index 2286c6d2d9bf..072a121f5d66 100644 --- a/docs/architecture/adr-041-in-place-store-migrations.md +++ b/docs/architecture/adr-041-in-place-store-migrations.md @@ -71,7 +71,7 @@ Since migration functions manipulate legacy code, they should live inside the `l ```go // Migrate1to2 migrates from version 1 to 2. func (m Migrator) Migrate1to2(ctx sdk.Context) error { - return v042bank.MigrateStore(ctx, m.keeper.storeKey) // v042bank is package `x/bank/legacy/v042`. + return v043bank.MigrateStore(ctx, m.keeper.storeKey) // v043bank is package `x/bank/legacy/v043`. } ``` diff --git a/x/bank/keeper/migrations.go b/x/bank/keeper/migrations.go index 20ef35e3215a..e46b386b81a9 100644 --- a/x/bank/keeper/migrations.go +++ b/x/bank/keeper/migrations.go @@ -2,7 +2,7 @@ package keeper import ( sdk "github.com/cosmos/cosmos-sdk/types" - v042 "github.com/cosmos/cosmos-sdk/x/bank/legacy/v042" + v043 "github.com/cosmos/cosmos-sdk/x/bank/legacy/v043" ) // Migrator is a struct for handling in-place store migrations. @@ -17,5 +17,5 @@ func NewMigrator(keeper BaseKeeper) Migrator { // Migrate1to2 migrates from version 1 to 2. func (m Migrator) Migrate1to2(ctx sdk.Context) error { - return v042.MigrateStore(ctx, m.keeper.storeKey, m.keeper.cdc) + return v043.MigrateStore(ctx, m.keeper.storeKey, m.keeper.cdc) } diff --git a/x/bank/legacy/v042/store.go b/x/bank/legacy/v043/store.go similarity index 99% rename from x/bank/legacy/v042/store.go rename to x/bank/legacy/v043/store.go index cc0d9d6f5ae9..74a560d5e2c5 100644 --- a/x/bank/legacy/v042/store.go +++ b/x/bank/legacy/v043/store.go @@ -1,4 +1,4 @@ -package v042 +package v043 import ( "github.com/cosmos/cosmos-sdk/codec" diff --git a/x/bank/legacy/v042/store_test.go b/x/bank/legacy/v043/store_test.go similarity index 91% rename from x/bank/legacy/v042/store_test.go rename to x/bank/legacy/v043/store_test.go index 51256ff3c189..ff4b3c3c08d0 100644 --- a/x/bank/legacy/v042/store_test.go +++ b/x/bank/legacy/v043/store_test.go @@ -1,4 +1,4 @@ -package v042_test +package v043_test import ( "testing" @@ -11,7 +11,7 @@ import ( "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" + v043bank "github.com/cosmos/cosmos-sdk/x/bank/legacy/v043" "github.com/cosmos/cosmos-sdk/x/bank/types" ) @@ -29,7 +29,7 @@ func TestSupplyMigration(t *testing.T) { store.Set(v040bank.SupplyKey, encCfg.Marshaler.MustMarshalBinaryBare(&oldSupply)) // Run migration. - err := v042bank.MigrateStore(ctx, bankKey, encCfg.Marshaler) + err := v043bank.MigrateStore(ctx, bankKey, encCfg.Marshaler) require.NoError(t, err) // New supply is indexed by denom. @@ -55,7 +55,7 @@ func TestBalanceKeysMigration(t *testing.T) { oldKey := append(append(v040bank.BalancesPrefix, addr...), denom...) store.Set(oldKey, value) - err := v042bank.MigrateStore(ctx, bankKey, encCfg.Marshaler) + err := v043bank.MigrateStore(ctx, bankKey, encCfg.Marshaler) require.NoError(t, err) newKey := append(types.CreateAccountBalancesPrefix(addr), denom...) diff --git a/x/distribution/keeper/migrations.go b/x/distribution/keeper/migrations.go index 7c5d40dba4db..7f7273c650b7 100644 --- a/x/distribution/keeper/migrations.go +++ b/x/distribution/keeper/migrations.go @@ -2,7 +2,7 @@ package keeper import ( sdk "github.com/cosmos/cosmos-sdk/types" - v042 "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v042" + v043 "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v043" ) // Migrator is a struct for handling in-place store migrations. @@ -17,5 +17,5 @@ func NewMigrator(keeper Keeper) Migrator { // Migrate1to2 migrates from version 1 to 2. func (m Migrator) Migrate1to2(ctx sdk.Context) error { - return v042.MigrateStore(ctx, m.keeper.storeKey) + return v043.MigrateStore(ctx, m.keeper.storeKey) } diff --git a/x/distribution/legacy/v042/helpers.go b/x/distribution/legacy/v043/helpers.go similarity index 99% rename from x/distribution/legacy/v042/helpers.go rename to x/distribution/legacy/v043/helpers.go index afc99cf70888..4394d271c33a 100644 --- a/x/distribution/legacy/v042/helpers.go +++ b/x/distribution/legacy/v043/helpers.go @@ -1,4 +1,4 @@ -package v042 +package v043 import ( "github.com/cosmos/cosmos-sdk/store/prefix" diff --git a/x/distribution/legacy/v042/store.go b/x/distribution/legacy/v043/store.go similarity index 98% rename from x/distribution/legacy/v042/store.go rename to x/distribution/legacy/v043/store.go index 31c575b4adc3..1cb78ea0be85 100644 --- a/x/distribution/legacy/v042/store.go +++ b/x/distribution/legacy/v043/store.go @@ -1,4 +1,4 @@ -package v042 +package v043 import ( sdk "github.com/cosmos/cosmos-sdk/types" diff --git a/x/distribution/legacy/v042/store_test.go b/x/distribution/legacy/v043/store_test.go similarity index 94% rename from x/distribution/legacy/v042/store_test.go rename to x/distribution/legacy/v043/store_test.go index 2a4a5df75bb1..848430133579 100644 --- a/x/distribution/legacy/v042/store_test.go +++ b/x/distribution/legacy/v043/store_test.go @@ -1,4 +1,4 @@ -package v042_test +package v043_test import ( "bytes" @@ -10,7 +10,7 @@ import ( "github.com/cosmos/cosmos-sdk/testutil/testdata" sdk "github.com/cosmos/cosmos-sdk/types" v040distribution "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v040" - v042distribution "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v042" + v043distribution "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v043" "github.com/cosmos/cosmos-sdk/x/distribution/types" ) @@ -83,7 +83,7 @@ func TestStoreMigration(t *testing.T) { } // Run migrations. - err := v042distribution.MigrateStore(ctx, distributionKey) + err := v043distribution.MigrateStore(ctx, distributionKey) require.NoError(t, err) // Make sure the new keys are set and old keys are deleted. diff --git a/x/gov/keeper/migrations.go b/x/gov/keeper/migrations.go index e0134012258f..cad01432bb7d 100644 --- a/x/gov/keeper/migrations.go +++ b/x/gov/keeper/migrations.go @@ -2,7 +2,7 @@ package keeper import ( sdk "github.com/cosmos/cosmos-sdk/types" - v042 "github.com/cosmos/cosmos-sdk/x/gov/legacy/v042" + v043 "github.com/cosmos/cosmos-sdk/x/gov/legacy/v043" ) // Migrator is a struct for handling in-place store migrations. @@ -17,5 +17,5 @@ func NewMigrator(keeper Keeper) Migrator { // Migrate1to2 migrates from version 1 to 2. func (m Migrator) Migrate1to2(ctx sdk.Context) error { - return v042.MigrateStore(ctx, m.keeper.storeKey, m.keeper.cdc) + return v043.MigrateStore(ctx, m.keeper.storeKey, m.keeper.cdc) } diff --git a/x/gov/legacy/v042/store.go b/x/gov/legacy/v043/store.go similarity index 99% rename from x/gov/legacy/v042/store.go rename to x/gov/legacy/v043/store.go index 4c49d016bebd..9189e12f736a 100644 --- a/x/gov/legacy/v042/store.go +++ b/x/gov/legacy/v043/store.go @@ -1,4 +1,4 @@ -package v042 +package v043 import ( "github.com/cosmos/cosmos-sdk/codec" diff --git a/x/gov/legacy/v042/store_test.go b/x/gov/legacy/v043/store_test.go similarity index 95% rename from x/gov/legacy/v042/store_test.go rename to x/gov/legacy/v043/store_test.go index 6eaeab7e9bcb..22d3e3ba4fb2 100644 --- a/x/gov/legacy/v042/store_test.go +++ b/x/gov/legacy/v043/store_test.go @@ -1,4 +1,4 @@ -package v042_test +package v043_test import ( "bytes" @@ -12,7 +12,7 @@ import ( "github.com/cosmos/cosmos-sdk/testutil/testdata" sdk "github.com/cosmos/cosmos-sdk/types" v040gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v040" - v042gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v042" + v043gov "github.com/cosmos/cosmos-sdk/x/gov/legacy/v043" "github.com/cosmos/cosmos-sdk/x/gov/types" ) @@ -75,7 +75,7 @@ func TestStoreMigration(t *testing.T) { } // Run migrations. - err := v042gov.MigrateStore(ctx, govKey, cdc) + err := v043gov.MigrateStore(ctx, govKey, cdc) require.NoError(t, err) // Make sure the new keys are set and old keys are deleted. diff --git a/x/slashing/keeper/migrations.go b/x/slashing/keeper/migrations.go index b1bda4ab648e..84f19c01ab7c 100644 --- a/x/slashing/keeper/migrations.go +++ b/x/slashing/keeper/migrations.go @@ -2,7 +2,7 @@ package keeper import ( sdk "github.com/cosmos/cosmos-sdk/types" - v042 "github.com/cosmos/cosmos-sdk/x/slashing/legacy/v042" + v043 "github.com/cosmos/cosmos-sdk/x/slashing/legacy/v043" ) // Migrator is a struct for handling in-place store migrations. @@ -17,5 +17,5 @@ func NewMigrator(keeper Keeper) Migrator { // Migrate1to2 migrates from version 1 to 2. func (m Migrator) Migrate1to2(ctx sdk.Context) error { - return v042.MigrateStore(ctx, m.keeper.storeKey) + return v043.MigrateStore(ctx, m.keeper.storeKey) } diff --git a/x/slashing/legacy/v042/store.go b/x/slashing/legacy/v043/store.go similarity index 62% rename from x/slashing/legacy/v042/store.go rename to x/slashing/legacy/v043/store.go index 7864087b10ff..4737315e98f3 100644 --- a/x/slashing/legacy/v042/store.go +++ b/x/slashing/legacy/v043/store.go @@ -1,8 +1,8 @@ -package v042 +package v043 import ( sdk "github.com/cosmos/cosmos-sdk/types" - v042distribution "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v042" + v043distribution "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v043" v040slashing "github.com/cosmos/cosmos-sdk/x/slashing/legacy/v040" ) @@ -12,9 +12,9 @@ import ( // - Change addresses to be length-prefixed. func MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey) error { store := ctx.KVStore(storeKey) - v042distribution.MigratePrefixAddress(store, v040slashing.ValidatorSigningInfoKeyPrefix) - v042distribution.MigratePrefixAddressBytes(store, v040slashing.ValidatorMissedBlockBitArrayKeyPrefix) - v042distribution.MigratePrefixAddress(store, v040slashing.AddrPubkeyRelationKeyPrefix) + v043distribution.MigratePrefixAddress(store, v040slashing.ValidatorSigningInfoKeyPrefix) + v043distribution.MigratePrefixAddressBytes(store, v040slashing.ValidatorMissedBlockBitArrayKeyPrefix) + v043distribution.MigratePrefixAddress(store, v040slashing.AddrPubkeyRelationKeyPrefix) return nil } diff --git a/x/slashing/legacy/v042/store_test.go b/x/slashing/legacy/v043/store_test.go similarity index 92% rename from x/slashing/legacy/v042/store_test.go rename to x/slashing/legacy/v043/store_test.go index 60bf43a27b84..f0440c1e8416 100644 --- a/x/slashing/legacy/v042/store_test.go +++ b/x/slashing/legacy/v043/store_test.go @@ -1,4 +1,4 @@ -package v042_test +package v043_test import ( "bytes" @@ -10,7 +10,7 @@ import ( "github.com/cosmos/cosmos-sdk/testutil/testdata" sdk "github.com/cosmos/cosmos-sdk/types" v040slashing "github.com/cosmos/cosmos-sdk/x/slashing/legacy/v040" - v042slashing "github.com/cosmos/cosmos-sdk/x/slashing/legacy/v042" + v043slashing "github.com/cosmos/cosmos-sdk/x/slashing/legacy/v043" "github.com/cosmos/cosmos-sdk/x/slashing/types" ) @@ -52,7 +52,7 @@ func TestStoreMigration(t *testing.T) { } // Run migrations. - err := v042slashing.MigrateStore(ctx, slashingKey) + err := v043slashing.MigrateStore(ctx, slashingKey) require.NoError(t, err) // Make sure the new keys are set and old keys are deleted. diff --git a/x/staking/keeper/migrations.go b/x/staking/keeper/migrations.go index 948f93ed67af..101ca195b390 100644 --- a/x/staking/keeper/migrations.go +++ b/x/staking/keeper/migrations.go @@ -2,7 +2,7 @@ package keeper import ( sdk "github.com/cosmos/cosmos-sdk/types" - v042 "github.com/cosmos/cosmos-sdk/x/staking/legacy/v042" + v043 "github.com/cosmos/cosmos-sdk/x/staking/legacy/v043" ) // Migrator is a struct for handling in-place store migrations. @@ -17,5 +17,5 @@ func NewMigrator(keeper Keeper) Migrator { // Migrate1to2 migrates from version 1 to 2. func (m Migrator) Migrate1to2(ctx sdk.Context) error { - return v042.MigrateStore(ctx, m.keeper.storeKey) + return v043.MigrateStore(ctx, m.keeper.storeKey) } diff --git a/x/staking/legacy/v042/store.go b/x/staking/legacy/v043/store.go similarity index 85% rename from x/staking/legacy/v042/store.go rename to x/staking/legacy/v043/store.go index 2be604e66099..4bd6b31e1f2d 100644 --- a/x/staking/legacy/v042/store.go +++ b/x/staking/legacy/v043/store.go @@ -1,11 +1,11 @@ -package v042 +package v043 import ( "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/address" v040auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v040" - v042distribution "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v042" + v043distribution "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v043" v040staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v040" "github.com/cosmos/cosmos-sdk/x/staking/types" ) @@ -61,15 +61,15 @@ func migrateValidatorsByPowerIndexKey(store sdk.KVStore) { func MigrateStore(ctx sdk.Context, storeKey sdk.StoreKey) error { store := ctx.KVStore(storeKey) - v042distribution.MigratePrefixAddress(store, v040staking.LastValidatorPowerKey) + v043distribution.MigratePrefixAddress(store, v040staking.LastValidatorPowerKey) - v042distribution.MigratePrefixAddress(store, v040staking.ValidatorsKey) - v042distribution.MigratePrefixAddress(store, v040staking.ValidatorsByConsAddrKey) + v043distribution.MigratePrefixAddress(store, v040staking.ValidatorsKey) + v043distribution.MigratePrefixAddress(store, v040staking.ValidatorsByConsAddrKey) migrateValidatorsByPowerIndexKey(store) - v042distribution.MigratePrefixAddressAddress(store, v040staking.DelegationKey) - v042distribution.MigratePrefixAddressAddress(store, v040staking.UnbondingDelegationKey) - v042distribution.MigratePrefixAddressAddress(store, v040staking.UnbondingDelegationByValIndexKey) + v043distribution.MigratePrefixAddressAddress(store, v040staking.DelegationKey) + v043distribution.MigratePrefixAddressAddress(store, v040staking.UnbondingDelegationKey) + v043distribution.MigratePrefixAddressAddress(store, v040staking.UnbondingDelegationByValIndexKey) migratePrefixAddressAddressAddress(store, v040staking.RedelegationKey) migratePrefixAddressAddressAddress(store, v040staking.RedelegationByValSrcIndexKey) migratePrefixAddressAddressAddress(store, v040staking.RedelegationByValDstIndexKey) diff --git a/x/staking/legacy/v042/store_test.go b/x/staking/legacy/v043/store_test.go similarity index 96% rename from x/staking/legacy/v042/store_test.go rename to x/staking/legacy/v043/store_test.go index 963ef02ed9c9..0abe8f3b1e86 100644 --- a/x/staking/legacy/v042/store_test.go +++ b/x/staking/legacy/v043/store_test.go @@ -1,4 +1,4 @@ -package v042_test +package v043_test import ( "bytes" @@ -11,7 +11,7 @@ import ( "github.com/cosmos/cosmos-sdk/testutil/testdata" sdk "github.com/cosmos/cosmos-sdk/types" v040staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v040" - v042staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v042" + v043staking "github.com/cosmos/cosmos-sdk/x/staking/legacy/v043" "github.com/cosmos/cosmos-sdk/x/staking/teststaking" "github.com/cosmos/cosmos-sdk/x/staking/types" ) @@ -121,7 +121,7 @@ func TestStoreMigration(t *testing.T) { } // Run migrations. - err := v042staking.MigrateStore(ctx, stakingKey) + err := v043staking.MigrateStore(ctx, stakingKey) require.NoError(t, err) // Make sure the new keys are set and old keys are deleted. From 24ed401c81e881ee85e629da824bd407fe0b6b6d Mon Sep 17 00:00:00 2001 From: Charly <16255463+charleenfei@users.noreply.github.com> Date: Tue, 9 Mar 2021 10:51:52 +0100 Subject: [PATCH 169/214] fixed broken links, typos (#8783) * fixed broken links, typos * Update docs/ibc/overview.md Co-authored-by: Amaury <1293565+amaurym@users.noreply.github.com> * Update docs/intro/sdk-app-architecture.md Co-authored-by: Marko * Update docs/building-modules/simulator.md Co-authored-by: Marko Co-authored-by: chrly Co-authored-by: Amaury <1293565+amaurym@users.noreply.github.com> Co-authored-by: Jonathan Gimeno Co-authored-by: Marko Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- docs/building-modules/intro.md | 6 +++--- docs/building-modules/simulator.md | 6 +++--- docs/ibc/integration.md | 2 +- docs/ibc/overview.md | 2 +- docs/intro/sdk-app-architecture.md | 12 ++++++------ docs/intro/why-app-specific.md | 8 ++++---- docs/run-node/interact-node.md | 2 +- x/capability/simulation/decoder.go | 2 +- 8 files changed, 20 insertions(+), 20 deletions(-) diff --git a/docs/building-modules/intro.md b/docs/building-modules/intro.md index 95d45fa7b6cd..9bec674acc55 100644 --- a/docs/building-modules/intro.md +++ b/docs/building-modules/intro.md @@ -13,7 +13,7 @@ Modules define most of the logic of SDK applications. Developers compose module ## Role of Modules in an SDK Application -The Cosmos SDK can be thought as the Ruby-on-Rails of blockchain development. It comes with a core that provides the basic functionalities every blockchain application needs, like a [boilerplate implementation of the ABCI](../core/baseapp.md) to communicate with the underlying consensus engine, a [`multistore`](../core/store.md#multistore) to persist state, a [server](../core/node.md) to form a full-node and [interfaces](../interfaces/interfaces-intro.md) to handle queries. +The Cosmos SDK can be thought as the Ruby-on-Rails of blockchain development. It comes with a core that provides the basic functionalities every blockchain application needs, like a [boilerplate implementation of the ABCI](../core/baseapp.md) to communicate with the underlying consensus engine, a [`multistore`](../core/store.md#multistore) to persist state, a [server](../core/node.md) to form a full-node and [interfaces](./module-interfaces.md) to handle queries. On top of this core, the Cosmos SDK enables developers to build modules that implement the business logic of their application. In other words, SDK modules implement the bulk of the logic of applications, while the core does the wiring and enables modules to be composed together. The end goal is to build a robust ecosystem of open-source SDK modules, making it increasingly easier to build complex blockchain applications. @@ -68,11 +68,11 @@ As a result of this architecture, building an SDK application usually revolves a ## How to Approach Building Modules as a Developer -While there is no definitive guidelines for writing modules, here are some important design principles developers should keep in mind when building them: +While there are no definitive guidelines for writing modules, here are some important design principles developers should keep in mind when building them: - **Composability**: SDK applications are almost always composed of multiple modules. This means developers need to carefully consider the integration of their module not only with the core of the Cosmos SDK, but also with other modules. The former is achieved by following standard design patterns outlined [here](#main-components-of-sdk-modules), while the latter is achieved by properly exposing the store(s) of the module via the [`keeper`](./keeper.md). - **Specialization**: A direct consequence of the **composability** feature is that modules should be **specialized**. Developers should carefully establish the scope of their module and not batch multiple functionalities into the same module. This separation of concern enables modules to be re-used in other projects and improves the upgradability of the application. **Specialization** also plays an important role in the [object-capabilities model](../core/ocap.md) of the Cosmos SDK. -- **Capabilities**: Most modules need to read and/or write to the store(s) of other modules. However, in an open-source environment, it is possible for some module to be malicious. That is why module developers need to carefully think not only about how their module interracts with other modules, but also about how to give access to the module's store(s). The Cosmos SDK takes a capabilities-oriented approach to inter-module security. This means that each store defined by a module is accessed by a `key`, which is held by the module's [`keeper`](./keeper.md). This `keeper` defines how to access the store(s) and under what conditions. Access to the module's store(s) is done by passing a reference to the module's `keeper`. +- **Capabilities**: Most modules need to read and/or write to the store(s) of other modules. However, in an open-source environment, it is possible for some module to be malicious. That is why module developers need to carefully think not only about how their module interacts with other modules, but also about how to give access to the module's store(s). The Cosmos SDK takes a capabilities-oriented approach to inter-module security. This means that each store defined by a module is accessed by a `key`, which is held by the module's [`keeper`](./keeper.md). This `keeper` defines how to access the store(s) and under what conditions. Access to the module's store(s) is done by passing a reference to the module's `keeper`. ## Main Components of SDK Modules diff --git a/docs/building-modules/simulator.md b/docs/building-modules/simulator.md index bd5301725615..4a7e9ba9714c 100644 --- a/docs/building-modules/simulator.md +++ b/docs/building-modules/simulator.md @@ -33,7 +33,7 @@ for the key-value pairs from the stores to be decoded (_i.e_ unmarshalled) to their corresponding types. In particular, it matches the key to a concrete type and then unmarshals the value from the `KVPair` to the type provided. -You can use the example [here](https://github.com/cosmos/cosmos-sdk/blob/release%2Fv0.38.0/x/distribution/simulation/decoder.go) from the distribution module to implement your store decoders. +You can use the example [here](https://github.com/cosmos/cosmos-sdk/blob/master/x/distribution/simulation/decoder.go) from the distribution module to implement your store decoders. ### Randomized genesis @@ -44,13 +44,13 @@ Once the module genesis parameter are generated randomly (or with the key and values defined in a `params` file), they are marshaled to JSON format and added to the app genesis JSON to use it on the simulations. -You can check an example on how to create the randomized genesis [here](https://github.com/cosmos/cosmos-sdk/blob/release%2Fv0.38.0/x/staking/simulation/genesis.go). +You can check an example on how to create the randomized genesis [here](https://github.com/cosmos/cosmos-sdk/blob/v0.42.0/x/staking/simulation/genesis.go). ### Randomized parameter changes The simulator is able to test parameter changes at random. The simulator package from each module must contain a `RandomizedParams` func that will simulate parameter changes of the module throughout the simulations lifespan. -You can see how an example of what is needed to fully test parameter changes [here](https://github.com/cosmos/cosmos-sdk/blob/release%2Fv0.38.0/x/staking/simulation/params.go) +You can see how an example of what is needed to fully test parameter changes [here](https://github.com/cosmos/cosmos-sdk/blob/master/x/staking/simulation/params.go) ### Random weighted operations diff --git a/docs/ibc/integration.md b/docs/ibc/integration.md index 50bc983f9b7a..aed01392f183 100644 --- a/docs/ibc/integration.md +++ b/docs/ibc/integration.md @@ -126,7 +126,7 @@ IBC module. Adding the module routes allows the IBC handler to call the appropriate callback when processing a channel handshake or a packet. -The second `Router` that is required is the evidence module router. This router handles genenal +The second `Router` that is required is the evidence module router. This router handles general evidence submission and routes the business logic to each registered evidence handler. In the case of IBC, it is required to submit evidence for [light client misbehaviour](https://github.com/cosmos/ics/tree/master/spec/ics-002-client-semantics#misbehaviour) diff --git a/docs/ibc/overview.md b/docs/ibc/overview.md index ff915eee8a0f..bdfaf26525ba 100644 --- a/docs/ibc/overview.md +++ b/docs/ibc/overview.md @@ -174,7 +174,7 @@ Once an acknowledgement is received successfully on the original sender the chai If you want to learn more about IBC, check the following specifications: * [IBC specification overview](https://github.com/cosmos/ics/blob/master/ibc/README.md) -* [IBC SDK specification](../../modules/ibc) +* [IBC SDK specification](../../x/ibc/spec/README.md) ## Next {hide} diff --git a/docs/intro/sdk-app-architecture.md b/docs/intro/sdk-app-architecture.md index 55ffad8a12a6..9e61cf4c0902 100644 --- a/docs/intro/sdk-app-architecture.md +++ b/docs/intro/sdk-app-architecture.md @@ -56,13 +56,13 @@ Blockchain node | | Consensus | | ``` -[Tendermint](https://tendermint.com/docs/introduction/what-is-tendermint.html) is an application-agnostic engine that is responsible for handling the *networking* and *consensus* layers of a blockchain. In practice, this means that Tendermint is responsible for propagating and ordering transaction bytes. Tendermint Core relies on an eponymous Byzantine-Fault-Tolerant (BFT) algorithm to reach consensus on the order of transactions. +[Tendermint](https://docs.tendermint.com/v0.34/introduction/what-is-tendermint.html) is an application-agnostic engine that is responsible for handling the *networking* and *consensus* layers of a blockchain. In practice, this means that Tendermint is responsible for propagating and ordering transaction bytes. Tendermint Core relies on an eponymous Byzantine-Fault-Tolerant (BFT) algorithm to reach consensus on the order of transactions. -The Tendermint [consensus algorithm](https://tendermint.com/docs/introduction/what-is-tendermint.html#consensus-overview) works with a set of special nodes called *Validators*. Validators are responsible for adding blocks of transactions to the blockchain. At any given block, there is a validator set V. A validator in V is chosen by the algorithm to be the proposer of the next block. This block is considered valid if more than two thirds of V signed a *[prevote](https://tendermint.com/docs/spec/consensus/consensus.html#prevote-step-height-h-round-r)* and a *[precommit](https://tendermint.com/docs/spec/consensus/consensus.html#precommit-step-height-h-round-r)* on it, and if all the transactions that it contains are valid. The validator set can be changed by rules written in the state-machine. +The Tendermint [consensus algorithm](https://docs.tendermint.com/master/introduction/what-is-tendermint.html#consensus-overview) works with a set of special nodes called *Validators*. Validators are responsible for adding blocks of transactions to the blockchain. At any given block, there is a validator set V. A validator in V is chosen by the algorithm to be the proposer of the next block. This block is considered valid if more than two thirds of V signed a *[prevote](https://docs.tendermint.com/master/spec/consensus/consensus.html#prevote-step-height-h-round-r)* and a *[precommit](https://docs.tendermint.com/master/spec/consensus/consensus.html#precommit-step-height-h-round-r)* on it, and if all the transactions that it contains are valid. The validator set can be changed by rules written in the state-machine. ## ABCI -Tendermint passes transactions to the application through an interface called the [ABCI](https://tendermint.com/docs/spec/abci/), which the application must implement. +Tendermint passes transactions to the application through an interface called the [ABCI](https://docs.tendermint.com/master/spec/abci/), which the application must implement. ``` +---------------------+ @@ -86,11 +86,11 @@ Note that **Tendermint only handles transaction bytes**. It has no knowledge of Here are the most important messages of the ABCI: -- `CheckTx`: When a transaction is received by Tendermint Core, it is passed to the application to check if a few basic requirements are met. `CheckTx` is used to protect the mempool of full-nodes against spam transactions. A special handler called the [`AnteHandler`](../basics/gas-fees.md#antehandler) is used to execute a series of validation steps such as checking for sufficient fees and validating the signatures. If the checks are valid, the transaction is added to the [mempool](https://tendermint.com/docs/spec/reactors/mempool/functionality.html#mempool-functionality) and relayed to peer nodes. Note that transactions are not processed (i.e. no modification of the state occurs) with `CheckTx` since they have not been included in a block yet. -- `DeliverTx`: When a [valid block](https://tendermint.com/docs/spec/blockchain/blockchain.html#validation) is received by Tendermint Core, each transaction in the block is passed to the application via `DeliverTx` in order to be processed. It is during this stage that the state transitions occur. The `AnteHandler` executes again along with the actual [`Msg` service methods](../building-modules/msg-services.md) for each message in the transaction. +- `CheckTx`: When a transaction is received by Tendermint Core, it is passed to the application to check if a few basic requirements are met. `CheckTx` is used to protect the mempool of full-nodes against spam transactions. A special handler called the [`AnteHandler`](../basics/gas-fees.md#antehandler) is used to execute a series of validation steps such as checking for sufficient fees and validating the signatures. If the checks are valid, the transaction is added to the [mempool](https://docs.tendermint.com/master/tendermint-core/mempool.html#mempool) and relayed to peer nodes. Note that transactions are not processed (i.e. no modification of the state occurs) with `CheckTx` since they have not been included in a block yet. +- `DeliverTx`: When a [valid block](https://docs.tendermint.com/master/spec/blockchain/blockchain.html#validation) is received by Tendermint Core, each transaction in the block is passed to the application via `DeliverTx` in order to be processed. It is during this stage that the state transitions occur. The `AnteHandler` executes again along with the actual [`Msg` service methods](../building-modules/msg-services.md) for each message in the transaction. - `BeginBlock`/`EndBlock`: These messages are executed at the beginning and the end of each block, whether the block contains transaction or not. It is useful to trigger automatic execution of logic. Proceed with caution though, as computationally expensive loops could slow down your blockchain, or even freeze it if the loop is infinite. -Find a more detailed view of the ABCI methods from the [Tendermint docs](https://tendermint.com/docs/spec/abci/abci.html#overview). +Find a more detailed view of the ABCI methods from the [Tendermint docs](https://docs.tendermint.com/master/spec/abci/abci.html#overview). Any application built on Tendermint needs to implement the ABCI interface in order to communicate with the underlying local Tendermint engine. Fortunately, you do not have to implement the ABCI interface. The Cosmos SDK provides a boilerplate implementation of it in the form of [baseapp](./sdk-design.md#baseapp). diff --git a/docs/intro/why-app-specific.md b/docs/intro/why-app-specific.md index 5852489127b4..99ce398baef6 100644 --- a/docs/intro/why-app-specific.md +++ b/docs/intro/why-app-specific.md @@ -44,20 +44,20 @@ Application-Specific Blockchains are designed to address these shortcomings. Application-specific blockchains give maximum flexibility to developers: -- In Cosmos blockchains, the state-machine is typically connected to the underlying consensus engine via an interface called the [ABCI](https://tendermint.com/docs/spec/abci/). This interface can be wrapped in any programming language, meaning developers can build their state-machine in the programming language of their choice. +- In Cosmos blockchains, the state-machine is typically connected to the underlying consensus engine via an interface called the [ABCI](https://docs.tendermint.com/master/spec/abci/). This interface can be wrapped in any programming language, meaning developers can build their state-machine in the programming language of their choice. - Developers can choose among multiple frameworks to build their state-machine. The most widely used today is the Cosmos SDK, but others exist (e.g. [Lotion](https://github.com/nomic-io/lotion), [Weave](https://github.com/iov-one/weave), ...). The choice will most of the time be done based on the programming language they want to use (Cosmos SDK and Weave are in Golang, Lotion is in Javascript, ...). - The ABCI also allows developers to swap the consensus engine of their application-specific blockchain. Today, only Tendermint is production-ready, but in the future other consensus engines are expected to emerge. - Even when they settle for a framework and consensus engine, developers still have the freedom to tweak them if they don't perfectly match their requirements in their pristine forms. - Developers are free to explore the full spectrum of tradeoffs (e.g. number of validators vs transaction throughput, safety vs availability in asynchrony, ...) and design choices (DB or IAVL tree for storage, UTXO or account model, ...). - Developers can implement automatic execution of code. In the Cosmos SDK, logic can be automatically triggered at the beginning and the end of each block. They are also free to choose the cryptographic library used in their application, as opposed to being constrained by what is made available by the underlying environment in the case of virtual-machine blockchains. -The list above contains a few examples that show how much flexibility application-specific blockchains give to developers. The goal of Cosmos and the Cosmos SDK is to make developer tooling as generic and composable as possible, so that each part of the stack can be forked, tweaked and improved without losing compatibility. As the community grows, more alternative for each of the core building blocks will emerge, giving more options to developers. +The list above contains a few examples that show how much flexibility application-specific blockchains give to developers. The goal of Cosmos and the Cosmos SDK is to make developer tooling as generic and composable as possible, so that each part of the stack can be forked, tweaked and improved without losing compatibility. As the community grows, more alternatives for each of the core building blocks will emerge, giving more options to developers. ### Performance -Decentralised applications built with Smart Contracts are inherently capped in performance by the underlying environment. For a decentralised application to optimise performance, it needs to be built as an application-specific blockchains. Next are some of the benefits an application-specific blockchains brings in terms of performance: +Decentralised applications built with Smart Contracts are inherently capped in performance by the underlying environment. For a decentralised application to optimise performance, it needs to be built as an application-specific blockchains. Next are some of the benefits an application-specific blockchain brings in terms of performance: -- Developers of application-specific blockchains can choose to operate with novel consensus engine such as Tendermint BFT. Compared to Proof-of-Work (used by most virtual-machine blockchains today), it offers significant gains in throuhgput. +- Developers of application-specific blockchains can choose to operate with a novel consensus engine such as Tendermint BFT. Compared to Proof-of-Work (used by most virtual-machine blockchains today), it offers significant gains in throuhgput. - An application-specific blockchain only operates a single application, so that the application does not compete with others for computation and storage. This is the opposite of most non-sharded virtual-machine blockchains today, where smart contracts all compete for computation and storage. - Even if a virtual-machine blockchain offered application-based sharding coupled with an efficient consensus algorithm, performance would still be limited by the virtual-machine itself. The real throughput bottleneck is the state-machine, and requiring transactions to be interpreted by a virtual-machine significantly increases the computational complexity of processing them. diff --git a/docs/run-node/interact-node.md b/docs/run-node/interact-node.md index bb208f7d8df1..9b7fa11800d0 100644 --- a/docs/run-node/interact-node.md +++ b/docs/run-node/interact-node.md @@ -50,7 +50,7 @@ You should see two delegations, the first one made from the `gentx`, and the sec ## Using gRPC -The Protobuf ecosystem developed tools for different use cases, including code-generation from `*.proto` files into various languages. These tools allow to build clients easily. Often, the client connection (i.e. the transport) can be plugged and replaced very easily. Let's explore one of the most popular transport: [gRPC](../core/grpc_rest.md). +The Protobuf ecosystem developed tools for different use cases, including code-generation from `*.proto` files into various languages. These tools allow the building of clients easily. Often, the client connection (i.e. the transport) can be plugged and replaced very easily. Let's explore one of the most popular transport: [gRPC](../core/grpc_rest.md). Since the code generation library largely depends on your own tech stack, we will only present three alternatives: diff --git a/x/capability/simulation/decoder.go b/x/capability/simulation/decoder.go index 9ab5521b747f..9cd0dcc6da4e 100644 --- a/x/capability/simulation/decoder.go +++ b/x/capability/simulation/decoder.go @@ -11,7 +11,7 @@ import ( ) // NewDecodeStore returns a decoder function closure that unmarshals the KVPair's -// Value to the corresponding capaility type. +// Value to the corresponding capability type. func NewDecodeStore(cdc codec.Marshaler) func(kvA, kvB kv.Pair) string { return func(kvA, kvB kv.Pair) string { switch { From 8f7cdafc32776955fd9751b2b3546e0b77412f25 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Wed, 10 Mar 2021 08:16:04 +0100 Subject: [PATCH 170/214] update SigVerifiableTx.GetPubKeys to return an error (#8828) closes: #8129 --- CHANGELOG.md | 4 ++++ x/auth/ante/sigverify.go | 10 ++++++++-- x/auth/legacy/legacytx/stdtx.go | 4 ++-- x/auth/signing/sig_verifiable_tx.go | 2 +- x/auth/testutil/suite.go | 8 ++++++-- x/auth/tx/builder.go | 15 +++++++++++---- x/auth/tx/builder_test.go | 10 +++++++--- 7 files changed, 39 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 972be3a80771..af60dafd1a4a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,12 +41,14 @@ Ref: https://keepachangelog.com/en/1.0.0/ * [\#8559](https://github.com/cosmos/cosmos-sdk/pull/8559) Added Protobuf compatible secp256r1 ECDSA signatures. * [\#8786](https://github.com/cosmos/cosmos-sdk/pull/8786) Enabled secp256r1 in x/auth. + ### Client Breaking Changes * [\#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. * (crypto/ed25519) [\#8690] Adopt zip1215 ed2559 verification rules. + ### API Breaking Changes * (keyring) [#\8662](https://github.com/cosmos/cosmos-sdk/pull/8662) `NewMnemonic` now receives an additional `passphrase` argument to secure the key generated by the bip39 mnemonic. @@ -58,6 +60,8 @@ Ref: https://keepachangelog.com/en/1.0.0/ * [\#8629](https://github.com/cosmos/cosmos-sdk/pull/8629) Deprecated `SetFullFundraiserPath` from `Config` in favor of `SetPurpose` and `SetCoinType`. * (x/upgrade) [\#8673](https://github.com/cosmos/cosmos-sdk/pull/8673) Remove IBC logic from x/upgrade. Deprecates IBC fields in an Upgrade Plan. IBC upgrade logic moved to 02-client and an IBC UpgradeProposal is added. * (x/bank) [\#8517](https://github.com/cosmos/cosmos-sdk/pull/8517) `SupplyI` interface and `Supply` are removed and uses `sdk.Coins` for supply tracking +* (x/auth) [\#8129](https://github.com/cosmos/cosmos-sdk/pull/8828) Updated `SigVerifiableTx.GetPubKeys` method signature to return error. + ### State Machine Breaking diff --git a/x/auth/ante/sigverify.go b/x/auth/ante/sigverify.go index 19bbdcc3a2a3..daa59d0b52d9 100644 --- a/x/auth/ante/sigverify.go +++ b/x/auth/ante/sigverify.go @@ -59,7 +59,10 @@ func (spkd SetPubKeyDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate b return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid tx type") } - pubkeys := sigTx.GetPubKeys() + pubkeys, err := sigTx.GetPubKeys() + if err != nil { + return ctx, err + } signers := sigTx.GetSigners() for i, pk := range pubkeys { @@ -339,7 +342,10 @@ func (vscd ValidateSigCountDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, sim } params := vscd.ak.GetParams(ctx) - pubKeys := sigTx.GetPubKeys() + pubKeys, err := sigTx.GetPubKeys() + if err != nil { + return ctx, err + } sigCount := 0 for _, pk := range pubKeys { diff --git a/x/auth/legacy/legacytx/stdtx.go b/x/auth/legacy/legacytx/stdtx.go index 2b8a6c0e0547..c1a982c85efe 100644 --- a/x/auth/legacy/legacytx/stdtx.go +++ b/x/auth/legacy/legacytx/stdtx.go @@ -246,14 +246,14 @@ func (tx StdTx) GetSignaturesV2() ([]signing.SignatureV2, error) { // GetPubkeys returns the pubkeys of signers if the pubkey is included in the signature // If pubkey is not included in the signature, then nil is in the slice instead -func (tx StdTx) GetPubKeys() []cryptotypes.PubKey { +func (tx StdTx) GetPubKeys() ([]cryptotypes.PubKey, error) { pks := make([]cryptotypes.PubKey, len(tx.Signatures)) for i, stdSig := range tx.Signatures { pks[i] = stdSig.GetPubKey() } - return pks + return pks, nil } // GetGas returns the Gas in StdFee diff --git a/x/auth/signing/sig_verifiable_tx.go b/x/auth/signing/sig_verifiable_tx.go index 8381ad491aa3..2d8aeb49db9a 100644 --- a/x/auth/signing/sig_verifiable_tx.go +++ b/x/auth/signing/sig_verifiable_tx.go @@ -11,7 +11,7 @@ import ( type SigVerifiableTx interface { types.Tx GetSigners() []types.AccAddress - GetPubKeys() []cryptotypes.PubKey // If signer already has pubkey in context, this list will have nil in its place + GetPubKeys() ([]cryptotypes.PubKey, error) // If signer already has pubkey in context, this list will have nil in its place GetSignaturesV2() ([]signing.SignatureV2, error) } diff --git a/x/auth/testutil/suite.go b/x/auth/testutil/suite.go index 15f6334b40a3..253ce3409c5b 100644 --- a/x/auth/testutil/suite.go +++ b/x/auth/testutil/suite.go @@ -258,7 +258,9 @@ func (s *TxConfigTestSuite) TestTxEncodeDecode() { tx3Sigs, err := tx3.GetSignaturesV2() s.Require().NoError(err) s.Require().Equal([]signingtypes.SignatureV2{sig}, tx3Sigs) - s.Require().Equal([]cryptotypes.PubKey{pubkey}, tx3.GetPubKeys()) + pks, err := tx3.GetPubKeys() + s.Require().NoError(err) + s.Require().Equal([]cryptotypes.PubKey{pubkey}, pks) log("JSON encode transaction") jsonTxBytes, err := s.TxConfig.TxJSONEncoder()(tx) @@ -277,7 +279,9 @@ func (s *TxConfigTestSuite) TestTxEncodeDecode() { tx3Sigs, err = tx3.GetSignaturesV2() s.Require().NoError(err) s.Require().Equal([]signingtypes.SignatureV2{sig}, tx3Sigs) - s.Require().Equal([]cryptotypes.PubKey{pubkey}, tx3.GetPubKeys()) + pks, err = tx3.GetPubKeys() + s.Require().NoError(err) + s.Require().Equal([]cryptotypes.PubKey{pubkey}, pks) } func (s *TxConfigTestSuite) TestWrapTxBuilder() { diff --git a/x/auth/tx/builder.go b/x/auth/tx/builder.go index 06e347dfc7fb..25295b465051 100644 --- a/x/auth/tx/builder.go +++ b/x/auth/tx/builder.go @@ -7,6 +7,7 @@ import ( codectypes "github.com/cosmos/cosmos-sdk/codec/types" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/types/tx" "github.com/cosmos/cosmos-sdk/types/tx/signing" "github.com/cosmos/cosmos-sdk/x/auth/ante" @@ -100,7 +101,7 @@ func (w *wrapper) GetSigners() []sdk.AccAddress { return w.tx.GetSigners() } -func (w *wrapper) GetPubKeys() []cryptotypes.PubKey { +func (w *wrapper) GetPubKeys() ([]cryptotypes.PubKey, error) { signerInfos := w.tx.AuthInfo.SignerInfos pks := make([]cryptotypes.PubKey, len(signerInfos)) @@ -111,13 +112,16 @@ func (w *wrapper) GetPubKeys() []cryptotypes.PubKey { continue } - pk, ok := si.PublicKey.GetCachedValue().(cryptotypes.PubKey) + pkAny := si.PublicKey.GetCachedValue() + pk, ok := pkAny.(cryptotypes.PubKey) if ok { pks[i] = pk + } else { + return nil, sdkerrors.Wrapf(sdkerrors.ErrLogic, "Expecting PubKey, got: %T", pkAny) } } - return pks + return pks, nil } func (w *wrapper) GetGas() uint64 { @@ -165,7 +169,10 @@ func (w *wrapper) GetTimeoutHeight() uint64 { func (w *wrapper) GetSignaturesV2() ([]signing.SignatureV2, error) { signerInfos := w.tx.AuthInfo.SignerInfos sigs := w.tx.Signatures - pubKeys := w.GetPubKeys() + pubKeys, err := w.GetPubKeys() + if err != nil { + return nil, err + } n := len(signerInfos) res := make([]signing.SignatureV2, n) diff --git a/x/auth/tx/builder_test.go b/x/auth/tx/builder_test.go index ddec560851be..6948299df515 100644 --- a/x/auth/tx/builder_test.go +++ b/x/auth/tx/builder_test.go @@ -89,7 +89,9 @@ func TestTxBuilder(t *testing.T) { txBuilder.SetMemo(memo) require.Equal(t, bodyBytes, txBuilder.getBodyBytes()) require.Equal(t, len(msgs), len(txBuilder.GetMsgs())) - require.Equal(t, 0, len(txBuilder.GetPubKeys())) + pks, err := txBuilder.GetPubKeys() + require.NoError(t, err) + require.Empty(t, pks) t.Log("verify that updated AuthInfo results in the correct getAuthInfoBytes and GetPubKeys") require.NotEqual(t, authInfoBytes, txBuilder.getAuthInfoBytes()) @@ -104,8 +106,10 @@ func TestTxBuilder(t *testing.T) { require.Equal(t, authInfoBytes, txBuilder.getAuthInfoBytes()) require.Equal(t, len(msgs), len(txBuilder.GetMsgs())) - require.Equal(t, 1, len(txBuilder.GetPubKeys())) - require.Equal(t, legacy.Cdc.MustMarshalBinaryBare(pubkey), legacy.Cdc.MustMarshalBinaryBare(txBuilder.GetPubKeys()[0])) + pks, err = txBuilder.GetPubKeys() + require.NoError(t, err) + require.Equal(t, 1, len(pks)) + require.True(t, pubkey.Equals(pks[0])) any, err = codectypes.NewAnyWithValue(testdata.NewTestMsg()) require.NoError(t, err) From 7a4903842fe286a9e52da6ad51b37f3f11efd277 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Wed, 10 Mar 2021 08:32:39 +0000 Subject: [PATCH 171/214] ci: revert cleanup action's upstream latest changes (#8834) Upstream's latest changes are causing mayhem in the build pipelines. This change reverts upstream's latest commit. Upstream issue: rokroskar/workflow-run-cleanup-action#16 --- .github/workflows/release-sims.yml | 2 +- .github/workflows/sims.yml | 2 +- .github/workflows/test.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release-sims.yml b/.github/workflows/release-sims.yml index 82e68ff41b07..b9272b176c4d 100644 --- a/.github/workflows/release-sims.yml +++ b/.github/workflows/release-sims.yml @@ -10,7 +10,7 @@ jobs: cleanup-runs: runs-on: ubuntu-latest steps: - - uses: rokroskar/workflow-run-cleanup-action@master + - uses: tendermint/workflow-run-cleanup-action@master env: GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" if: "!startsWith(github.ref, 'refs/tags/') && github.ref != 'refs/heads/master'" diff --git a/.github/workflows/sims.yml b/.github/workflows/sims.yml index a64e808b3874..c1fd10f0c350 100644 --- a/.github/workflows/sims.yml +++ b/.github/workflows/sims.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest if: "!startsWith(github.ref, 'refs/tags/') && github.ref != 'refs/heads/master'" steps: - - uses: rokroskar/workflow-run-cleanup-action@master + - uses: tendermint/workflow-run-cleanup-action@master env: GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1024339295b0..a059ab6c85fe 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,7 +10,7 @@ jobs: cleanup-runs: runs-on: ubuntu-latest steps: - - uses: rokroskar/workflow-run-cleanup-action@master + - uses: tendermint/workflow-run-cleanup-action@master env: GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" if: "!startsWith(github.ref, 'refs/tags/') && github.ref != 'refs/heads/master'" From d761f088ab7077c285fc198ad61e72b77e5aea0f Mon Sep 17 00:00:00 2001 From: Gianguido Sora Date: Wed, 10 Mar 2021 09:56:12 +0100 Subject: [PATCH 172/214] add trust to macOS Keychain for calling apps by default (#8826) This commit automatically trusts the calling application with its data, avoiding all the annoying keychain popups that appears when dealing with keys (list, add...). Co-authored-by: Alessio Treglia --- crypto/keyring/keyring.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index 9734af37b1ae..0634871a5516 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -607,9 +607,10 @@ func SignWithLedger(info Info, msg []byte) (sig []byte, pub types.PubKey, err er func newOSBackendKeyringConfig(appName, dir string, buf io.Reader) keyring.Config { return keyring.Config{ - ServiceName: appName, - FileDir: dir, - FilePasswordFunc: newRealPrompt(dir, buf), + ServiceName: appName, + FileDir: dir, + KeychainTrustApplication: true, + FilePasswordFunc: newRealPrompt(dir, buf), } } From da669fcf1b19e1f212ed507d8a05a7b1add3cd94 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 10 Mar 2021 10:33:23 +0000 Subject: [PATCH 173/214] build(deps): bump codecov/codecov-action from v1.2.1 to v1.2.2 (#8833) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from v1.2.1 to v1.2.2. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/master/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v1.2.1...1f8f3abcccf7960749744fd13547965f0e7d1bdd) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alessio Treglia --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a059ab6c85fe..872eaff7c939 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -172,7 +172,7 @@ jobs: sed -i.bak "/$(echo $filename | sed 's/\//\\\//g')/d" coverage.txt done if: env.GIT_DIFF - - uses: codecov/codecov-action@v1.2.1 + - uses: codecov/codecov-action@v1.2.2 with: file: ./coverage.txt if: env.GIT_DIFF From 4b4768d242b2ae12cbd9fee8b1e8e4063767abe0 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Wed, 10 Mar 2021 10:57:16 +0000 Subject: [PATCH 174/214] merge v0.42.0 changelog (#8836) Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- CHANGELOG.md | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index af60dafd1a4a..39a231c74a5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -80,16 +80,28 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (x/auth) [\#8522](https://github.com/cosmos/cosmos-sdk/pull/8522) Allow to query all stored accounts * (x/ibc) [\#7949](https://github.com/cosmos/cosmos-sdk/issues/7949) Standardized channel `Acknowledgement` moved to its own file. Codec registration redundancy removed. * (crypto/types) [\#8600](https://github.com/cosmos/cosmos-sdk/pull/8600) `CompactBitArray`: optimize the `NumTrueBitsBefore` method and add an `Equal` method. -* (x/ibc) [\#8624](https://github.com/cosmos/cosmos-sdk/pull/8624) Emit full header in IBC UpdateClient message. ### Bug Fixes * (keyring) [#\8635](https://github.com/cosmos/cosmos-sdk/issues/8635) Remove hardcoded default passphrase value on `NewMnemonic` -* (x/evidence) [#8461](https://github.com/cosmos/cosmos-sdk/pull/8461) Fix bech32 prefix in evidence validator address conversion * (x/bank) [\#8434](https://github.com/cosmos/cosmos-sdk/pull/8434) Fix legacy REST API `GET /bank/total` and `GET /bank/total/{denom}` in swagger * (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 +## [v0.42.0](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.42.0) - 2021-03-08 + +**IMPORTANT**: This release contains an important security fix for all non Cosmos Hub chains running Stargate version of the Cosmos SDK (>0.40). Non-hub chains should not be using any version of the SDK in the v0.40.x or v0.41.x release series. See [#8461](https://github.com/cosmos/cosmos-sdk/pull/8461) for more details. + +### Improvements + +* (x/ibc) [\#8624](https://github.com/cosmos/cosmos-sdk/pull/8624) Emit full header in IBC UpdateClient message. +* (x/crisis) [\#8621](https://github.com/cosmos/cosmos-sdk/issues/8621) crisis invariants names now print to loggers. + +### Bug fixes + +* (x/evidence) [\#8461](https://github.com/cosmos/cosmos-sdk/pull/8461) Fix bech32 prefix in evidence validator address conversion +* (x/gov) [\#8806](https://github.com/cosmos/cosmos-sdk/issues/8806) Fix q gov proposals command's mishandling of the --status parameter's values. + ## [v0.41.4](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.41.3) - 2021-03-02 **IMPORTANT**: Due to a bug in the v0.41.x series with how evidence handles validator consensus addresses #8461, SDK based chains that are not using the default bech32 prefix (cosmos, aka all chains except for t From 2b685ee41d34f2f4488efa90bc0008e54939b510 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Wed, 10 Mar 2021 16:31:51 +0000 Subject: [PATCH 175/214] Revert "ci: revert cleanup action's upstream latest changes (#8834)" (#8840) This reverts commit 7a4903842fe286a9e52da6ad51b37f3f11efd277. --- .github/workflows/release-sims.yml | 2 +- .github/workflows/sims.yml | 2 +- .github/workflows/test.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release-sims.yml b/.github/workflows/release-sims.yml index b9272b176c4d..82e68ff41b07 100644 --- a/.github/workflows/release-sims.yml +++ b/.github/workflows/release-sims.yml @@ -10,7 +10,7 @@ jobs: cleanup-runs: runs-on: ubuntu-latest steps: - - uses: tendermint/workflow-run-cleanup-action@master + - uses: rokroskar/workflow-run-cleanup-action@master env: GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" if: "!startsWith(github.ref, 'refs/tags/') && github.ref != 'refs/heads/master'" diff --git a/.github/workflows/sims.yml b/.github/workflows/sims.yml index c1fd10f0c350..a64e808b3874 100644 --- a/.github/workflows/sims.yml +++ b/.github/workflows/sims.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest if: "!startsWith(github.ref, 'refs/tags/') && github.ref != 'refs/heads/master'" steps: - - uses: tendermint/workflow-run-cleanup-action@master + - uses: rokroskar/workflow-run-cleanup-action@master env: GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 872eaff7c939..fb25c58fe190 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,7 +10,7 @@ jobs: cleanup-runs: runs-on: ubuntu-latest steps: - - uses: tendermint/workflow-run-cleanup-action@master + - uses: rokroskar/workflow-run-cleanup-action@master env: GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" if: "!startsWith(github.ref, 'refs/tags/') && github.ref != 'refs/heads/master'" From 55fc465dce737f35f245932152198847f2b96f4f Mon Sep 17 00:00:00 2001 From: Charly Date: Wed, 10 Mar 2021 20:14:12 +0100 Subject: [PATCH 176/214] fixes: permalinks for docs (#8838) * fixed broken links, typos * Update docs/ibc/overview.md Co-authored-by: Amaury <1293565+amaurym@users.noreply.github.com> * Update docs/intro/sdk-app-architecture.md Co-authored-by: Marko * Update docs/building-modules/simulator.md Co-authored-by: Marko * build(deps): bump JamesIves/github-pages-deploy-action from 4.0.0 to 4.1.0 (#8792) Bumps [JamesIves/github-pages-deploy-action](https://github.com/JamesIves/github-pages-deploy-action) from 4.0.0 to 4.1.0. - [Release notes](https://github.com/JamesIves/github-pages-deploy-action/releases) - [Commits](https://github.com/JamesIves/github-pages-deploy-action/compare/4.0.0...3dbacc7e69578703f91f077118b3475862cb09b8) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix multisig account pubkeys migration (#8794) closes: #8776 * Update mergify (#8784) * Update mergify Prep for the v0.42 release series. * retire v0.41, the hub can upgrade to v0.42 smoothly * perf change (#8796) Co-authored-by: Alessio Treglia Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> * Supply by denom Migrations (#8780) * Add back supply proto * Add migration for supply * Fix lint * Update x/bank/spec/01_state.md * Fix test * Proto gen * Update x/bank/spec/01_state.md * Make proto gen Co-authored-by: Jonathan Gimeno * fix make protoc error (#8799) * reduce gas costs by 10x for transient store operations (#8790) * reduce gas costs by 10x for transient store operations * fix TestTransientGasConfig for ReadCostFlat * added changelog entry * fix changelog * fix changelog Co-authored-by: Alessio Treglia * x/gov: fix NormalizeProposalType() return values (#8808) Closes: #8806 * store/cachekv: use typed types/kv.List instead of container/list.List (#8811) Reduces CPU burn by using a typed List to avoid the expensive type assertions from using an interface. This is the only option for now until Go makes generics generally available. The change brings time spent on the time assertion cummulatively to: 580ms down from 6.88s Explanation: The type assertions were showing up heavily in profiles: * Before this commit ```shell Total: 42.18s ROUTINE ======================== github.com/cosmos/cosmos-sdk/store/cachekv.newMemIterator in /Users/emmanuelodeke/go/src/github.com/cosmos/cosmos-sdk/store/cachekv/memiterator.go 14.01s 18.87s (flat, cum) 44.74% of Total . . 17: items []*kv.Pair . . 18: ascending bool . . 19:} . . 20: . . 21:func newMemIterator(start, end []byte, items *list.List, ascending bool) *memIterator { . 620ms 22: itemsInDomain := make([]*kv.Pair, 0, items.Len()) . . 23: . . 24: var entered bool . . 25: 510ms 870ms 26: for e := items.Front(); e != nil; e = e.Next() { 6.85s 6.88s 27: item := e.Value.(*kv.Pair) 5.71s 8.19s 28: if !dbm.IsKeyInDomain(item.Key, start, end) { 120ms 120ms 29: if entered { . . 30: break . . 31: } . . 32: . . 33: continue . . 34: } . . 35: 820ms 980ms 36: itemsInDomain = append(itemsInDomain, item) . . 37: entered = true . . 38: } . . 39: . 1.21s 40: return &memIterator{ . . 41: start: start, . . 42: end: end, . . 43: items: itemsInDomain, . . 44: ascending: ascending, . . 45: } ``` and given that the list only uses that type, it is only right to lift the code from container/list.List, and only modify Element.Value's type. For emphasis, the code is basically just a retrofit of container/list/list.go but with a typing, and we'll keep it as is until perhaps Go1.17 or Go1.18 or when everyone uses Go1.17+ after generics have landed. * After this commit ```shell Total: 45.25s ROUTINE ======================== github.com/cosmos/cosmos-sdk/store/cachekv.newMemIterator in /Users/emmanuelodeke/go/src/github.com/cosmos/cosmos-sdk/store/cachekv/memiterator.go 4.84s 6.77s (flat, cum) 14.96% of Total . . 16: items []*kv.Pair . . 17: ascending bool . . 18:} . . 19: . . 20:func newMemIterator(start, end []byte, items *kv.List, ascending bool) *memIterator { . 330ms 21: itemsInDomain := make([]*kv.Pair, 0, items.Len()) . . 22: . . 23: var entered bool . . 24: 60ms 160ms 25: for e := items.Front(); e != nil; e = e.Next() { 580ms 580ms 26: item := e.Value 3.68s 4.78s 27: if !dbm.IsKeyInDomain(item.Key, start, end) { 80ms 80ms 28: if entered { . . 29: break . . 30: } . . 31: . . 32: continue . . 33: } . . 34: 440ms 580ms 35: itemsInDomain = append(itemsInDomain, item) . . 36: entered = true . . 37: } . . 38: . 260ms 39: return &memIterator{ . . 40: start: start, . . 41: end: end, . . 42: items: itemsInDomain, . . 43: ascending: ascending, . . 44: } ``` Fixes #8810 * Move all migration scripts to v043 (#8814) * Move all migration scripts to v043 * Fix permaling * Fix test * Fix test again Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> * permalinks Co-authored-by: chrly Co-authored-by: Amaury <1293565+amaurym@users.noreply.github.com> Co-authored-by: Jonathan Gimeno Co-authored-by: Marko Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Akhil Kumar P <36399231+akhilkumarpilli@users.noreply.github.com> Co-authored-by: Alessio Treglia Co-authored-by: Marko Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Albert Chon Co-authored-by: Emmanuel T Odeke --- docs/building-modules/simulator.md | 6 +++--- docs/intro/sdk-app-architecture.md | 10 +++++----- docs/intro/why-app-specific.md | 3 ++- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/docs/building-modules/simulator.md b/docs/building-modules/simulator.md index 4a7e9ba9714c..586119a331cc 100644 --- a/docs/building-modules/simulator.md +++ b/docs/building-modules/simulator.md @@ -33,7 +33,7 @@ for the key-value pairs from the stores to be decoded (_i.e_ unmarshalled) to their corresponding types. In particular, it matches the key to a concrete type and then unmarshals the value from the `KVPair` to the type provided. -You can use the example [here](https://github.com/cosmos/cosmos-sdk/blob/master/x/distribution/simulation/decoder.go) from the distribution module to implement your store decoders. +You can use the example [here](https://github.com/cosmos/cosmos-sdk/blob/v0.42.0/x/distribution/simulation/decoder.go) from the distribution module to implement your store decoders. ### Randomized genesis @@ -50,7 +50,7 @@ You can check an example on how to create the randomized genesis [here](https:// The simulator is able to test parameter changes at random. The simulator package from each module must contain a `RandomizedParams` func that will simulate parameter changes of the module throughout the simulations lifespan. -You can see how an example of what is needed to fully test parameter changes [here](https://github.com/cosmos/cosmos-sdk/blob/master/x/staking/simulation/params.go) +You can see how an example of what is needed to fully test parameter changes [here](https://github.com/cosmos/cosmos-sdk/blob/v0.42.0/x/staking/simulation/params.go) ### Random weighted operations @@ -83,7 +83,7 @@ them to be used on the parameters. Now that all the required functions are defined, we need to integrate them into the module pattern within the `module.go`: -+++ https://github.com/cosmos/cosmos-sdk/blob/master/x/distribution/module.go ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.42.0/x/distribution/module.go ## App Simulator manager diff --git a/docs/intro/sdk-app-architecture.md b/docs/intro/sdk-app-architecture.md index 9e61cf4c0902..ccd17118574c 100644 --- a/docs/intro/sdk-app-architecture.md +++ b/docs/intro/sdk-app-architecture.md @@ -58,11 +58,11 @@ Blockchain node | | Consensus | | [Tendermint](https://docs.tendermint.com/v0.34/introduction/what-is-tendermint.html) is an application-agnostic engine that is responsible for handling the *networking* and *consensus* layers of a blockchain. In practice, this means that Tendermint is responsible for propagating and ordering transaction bytes. Tendermint Core relies on an eponymous Byzantine-Fault-Tolerant (BFT) algorithm to reach consensus on the order of transactions. -The Tendermint [consensus algorithm](https://docs.tendermint.com/master/introduction/what-is-tendermint.html#consensus-overview) works with a set of special nodes called *Validators*. Validators are responsible for adding blocks of transactions to the blockchain. At any given block, there is a validator set V. A validator in V is chosen by the algorithm to be the proposer of the next block. This block is considered valid if more than two thirds of V signed a *[prevote](https://docs.tendermint.com/master/spec/consensus/consensus.html#prevote-step-height-h-round-r)* and a *[precommit](https://docs.tendermint.com/master/spec/consensus/consensus.html#precommit-step-height-h-round-r)* on it, and if all the transactions that it contains are valid. The validator set can be changed by rules written in the state-machine. +The Tendermint [consensus algorithm](https://docs.tendermint.com/v0.34/introduction/what-is-tendermint.html#consensus-overview) works with a set of special nodes called *Validators*. Validators are responsible for adding blocks of transactions to the blockchain. At any given block, there is a validator set V. A validator in V is chosen by the algorithm to be the proposer of the next block. This block is considered valid if more than two thirds of V signed a *[prevote](https://docs.tendermint.com/v0.34/spec/consensus/consensus.html#prevote-step-height-h-round-r)* and a *[precommit](https://docs.tendermint.com/v0.34/spec/consensus/consensus.html#precommit-step-height-h-round-r)* on it, and if all the transactions that it contains are valid. The validator set can be changed by rules written in the state-machine. ## ABCI -Tendermint passes transactions to the application through an interface called the [ABCI](https://docs.tendermint.com/master/spec/abci/), which the application must implement. +Tendermint passes transactions to the application through an interface called the [ABCI](https://docs.tendermint.com/v0.34/spec/abci/), which the application must implement. ``` +---------------------+ @@ -86,11 +86,11 @@ Note that **Tendermint only handles transaction bytes**. It has no knowledge of Here are the most important messages of the ABCI: -- `CheckTx`: When a transaction is received by Tendermint Core, it is passed to the application to check if a few basic requirements are met. `CheckTx` is used to protect the mempool of full-nodes against spam transactions. A special handler called the [`AnteHandler`](../basics/gas-fees.md#antehandler) is used to execute a series of validation steps such as checking for sufficient fees and validating the signatures. If the checks are valid, the transaction is added to the [mempool](https://docs.tendermint.com/master/tendermint-core/mempool.html#mempool) and relayed to peer nodes. Note that transactions are not processed (i.e. no modification of the state occurs) with `CheckTx` since they have not been included in a block yet. -- `DeliverTx`: When a [valid block](https://docs.tendermint.com/master/spec/blockchain/blockchain.html#validation) is received by Tendermint Core, each transaction in the block is passed to the application via `DeliverTx` in order to be processed. It is during this stage that the state transitions occur. The `AnteHandler` executes again along with the actual [`Msg` service methods](../building-modules/msg-services.md) for each message in the transaction. +- `CheckTx`: When a transaction is received by Tendermint Core, it is passed to the application to check if a few basic requirements are met. `CheckTx` is used to protect the mempool of full-nodes against spam transactions. A special handler called the [`AnteHandler`](../basics/gas-fees.md#antehandler) is used to execute a series of validation steps such as checking for sufficient fees and validating the signatures. If the checks are valid, the transaction is added to the [mempool](https://docs.tendermint.com/v0.34/tendermint-core/mempool.html#mempool) and relayed to peer nodes. Note that transactions are not processed (i.e. no modification of the state occurs) with `CheckTx` since they have not been included in a block yet. +- `DeliverTx`: When a [valid block](https://docs.tendermint.com/v0.34/spec/blockchain/blockchain.html#validation) is received by Tendermint Core, each transaction in the block is passed to the application via `DeliverTx` in order to be processed. It is during this stage that the state transitions occur. The `AnteHandler` executes again along with the actual [`Msg` service methods](../building-modules/msg-services.md) for each message in the transaction. - `BeginBlock`/`EndBlock`: These messages are executed at the beginning and the end of each block, whether the block contains transaction or not. It is useful to trigger automatic execution of logic. Proceed with caution though, as computationally expensive loops could slow down your blockchain, or even freeze it if the loop is infinite. -Find a more detailed view of the ABCI methods from the [Tendermint docs](https://docs.tendermint.com/master/spec/abci/abci.html#overview). +Find a more detailed view of the ABCI methods from the [Tendermint docs](https://docs.tendermint.com/v0.34/spec/abci/abci.html#overview). Any application built on Tendermint needs to implement the ABCI interface in order to communicate with the underlying local Tendermint engine. Fortunately, you do not have to implement the ABCI interface. The Cosmos SDK provides a boilerplate implementation of it in the form of [baseapp](./sdk-design.md#baseapp). diff --git a/docs/intro/why-app-specific.md b/docs/intro/why-app-specific.md index 99ce398baef6..14f6eea03d7c 100644 --- a/docs/intro/why-app-specific.md +++ b/docs/intro/why-app-specific.md @@ -44,7 +44,8 @@ Application-Specific Blockchains are designed to address these shortcomings. Application-specific blockchains give maximum flexibility to developers: -- In Cosmos blockchains, the state-machine is typically connected to the underlying consensus engine via an interface called the [ABCI](https://docs.tendermint.com/master/spec/abci/). This interface can be wrapped in any programming language, meaning developers can build their state-machine in the programming language of their choice. +- In Cosmos blockchains, the state-machine is typically connected to the underlying consensus engine via an interface called the [ABCI](https://docs.tendermint.com/v0.34/spec/abci/). This interface can be wrapped in any programming language, meaning developers can build their state-machine in the programming language of their choice. + - Developers can choose among multiple frameworks to build their state-machine. The most widely used today is the Cosmos SDK, but others exist (e.g. [Lotion](https://github.com/nomic-io/lotion), [Weave](https://github.com/iov-one/weave), ...). The choice will most of the time be done based on the programming language they want to use (Cosmos SDK and Weave are in Golang, Lotion is in Javascript, ...). - The ABCI also allows developers to swap the consensus engine of their application-specific blockchain. Today, only Tendermint is production-ready, but in the future other consensus engines are expected to emerge. - Even when they settle for a framework and consensus engine, developers still have the freedom to tweak them if they don't perfectly match their requirements in their pristine forms. From 0e3ff45380d8a544ce0d29d90fc376705d7bd00a Mon Sep 17 00:00:00 2001 From: Dev Ojha Date: Wed, 10 Mar 2021 15:50:30 -0600 Subject: [PATCH 177/214] Fix typo (#8848) --- x/auth/spec/03_antehandlers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/auth/spec/03_antehandlers.md b/x/auth/spec/03_antehandlers.md index 709cae3789f4..7e0ffdba21e2 100644 --- a/x/auth/spec/03_antehandlers.md +++ b/x/auth/spec/03_antehandlers.md @@ -2,7 +2,7 @@ order: 3 --> -# AnthHandlers +# AnteHandlers ## Handlers From e73cf2b410793070c5cec48014dbac21281185f5 Mon Sep 17 00:00:00 2001 From: Aleksandr Bezobchuk Date: Wed, 10 Mar 2021 17:31:21 -0500 Subject: [PATCH 178/214] Merge pull request from GHSA-mvm6-gfm2-89xj Co-authored-by: Alessio Treglia --- simapp/app.go | 18 +----------------- simapp/app_test.go | 7 +++++-- 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/simapp/app.go b/simapp/app.go index 000d5234fd37..77c75c8f9ca3 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -130,11 +130,6 @@ var ( stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, govtypes.ModuleName: {authtypes.Burner}, } - - // module accounts that are allowed to receive tokens - allowedReceivingModAcc = map[string]bool{ - distrtypes.ModuleName: true, - } ) var ( @@ -242,7 +237,7 @@ func NewSimApp( appCodec, keys[authtypes.StoreKey], app.GetSubspace(authtypes.ModuleName), authtypes.ProtoBaseAccount, maccPerms, ) app.BankKeeper = bankkeeper.NewBaseKeeper( - appCodec, keys[banktypes.StoreKey], app.AccountKeeper, app.GetSubspace(banktypes.ModuleName), app.BlockedAddrs(), + appCodec, keys[banktypes.StoreKey], app.AccountKeeper, app.GetSubspace(banktypes.ModuleName), app.ModuleAccountAddrs(), ) stakingKeeper := stakingkeeper.NewKeeper( appCodec, keys[stakingtypes.StoreKey], app.AccountKeeper, app.BankKeeper, app.GetSubspace(stakingtypes.ModuleName), @@ -444,17 +439,6 @@ func (app *SimApp) ModuleAccountAddrs() map[string]bool { return modAccAddrs } -// BlockedAddrs returns all the app's module account addresses that are not -// allowed to receive external tokens. -func (app *SimApp) BlockedAddrs() map[string]bool { - blockedAddrs := make(map[string]bool) - for acc := range maccPerms { - blockedAddrs[authtypes.NewModuleAddress(acc).String()] = !allowedReceivingModAcc[acc] - } - - return blockedAddrs -} - // LegacyAmino returns SimApp's amino codec. // // NOTE: This is solely to be used for testing purposes as it may be desirable diff --git a/simapp/app_test.go b/simapp/app_test.go index 7e14ab062b79..55963732655f 100644 --- a/simapp/app_test.go +++ b/simapp/app_test.go @@ -38,8 +38,11 @@ func TestSimAppExportAndBlockedAddrs(t *testing.T) { app := NewSimApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encCfg, EmptyAppOptions{}) for acc := range maccPerms { - require.Equal(t, !allowedReceivingModAcc[acc], app.BankKeeper.BlockedAddr(app.AccountKeeper.GetModuleAddress(acc)), - "ensure that blocked addresses are properly set in bank keeper") + require.True( + t, + app.BankKeeper.BlockedAddr(app.AccountKeeper.GetModuleAddress(acc)), + "ensure that blocked addresses are properly set in bank keeper", + ) } genesisState := NewDefaultGenesisState(encCfg.Marshaler) From 280ee4f15e46117a5061ab3a374d9b695ed082bf Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 11 Mar 2021 15:20:32 +0100 Subject: [PATCH 179/214] Fix SendToModuleAccountTest (#8857) --- x/bank/app_test.go | 80 ------------------------------------------ x/bank/handler_test.go | 68 +++++++++++++++++++++++++++++++++-- 2 files changed, 66 insertions(+), 82 deletions(-) diff --git a/x/bank/app_test.go b/x/bank/app_test.go index 6cb3655cc829..5007b087454a 100644 --- a/x/bank/app_test.go +++ b/x/bank/app_test.go @@ -12,7 +12,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/cosmos/cosmos-sdk/x/bank/types" - distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" ) type ( @@ -121,85 +120,6 @@ func TestSendNotEnoughBalance(t *testing.T) { require.Equal(t, res2.GetSequence(), origSeq+1) } -// A module account cannot be the recipient of bank sends unless it has been marked as such -func TestSendToModuleAcc(t *testing.T) { - tests := []struct { - name string - fromBalance sdk.Coins - msg *types.MsgSend - expSimPass bool - expPass bool - expFromBalance sdk.Coins - expToBalance sdk.Coins - }{ - { - name: "Normal module account cannot be the recipient of bank sends", - fromBalance: coins, - msg: types.NewMsgSend(addr1, moduleAccAddr, coins), - expSimPass: false, - expPass: false, - expFromBalance: coins, - expToBalance: sdk.NewCoins(), - }, - { - name: "Allowed module account can be the recipient of bank sends", - fromBalance: coins, - msg: types.NewMsgSend(addr1, authtypes.NewModuleAddress(distrtypes.ModuleName), coins), - expPass: true, - expSimPass: true, - expFromBalance: sdk.NewCoins(), - expToBalance: coins, - }, - } - - for _, test := range tests { - test := test - t.Run(test.name, func(t *testing.T) { - acc := &authtypes.BaseAccount{ - Address: test.msg.FromAddress, - } - - genAccs := []authtypes.GenesisAccount{acc} - app := simapp.SetupWithGenesisAccounts(genAccs) - ctx := app.BaseApp.NewContext(false, tmproto.Header{}) - - fromAddr, err := sdk.AccAddressFromBech32(test.msg.FromAddress) - require.NoError(t, err) - toAddr, err := sdk.AccAddressFromBech32(test.msg.ToAddress) - require.NoError(t, err) - - require.NoError(t, simapp.FundAccount(app, ctx, fromAddr, test.fromBalance)) - - app.Commit() - - res1 := app.AccountKeeper.GetAccount(ctx, fromAddr) - require.NotNil(t, res1) - require.Equal(t, acc, res1.(*authtypes.BaseAccount)) - - origAccNum := res1.GetAccountNumber() - origSeq := res1.GetSequence() - - header := tmproto.Header{Height: app.LastBlockHeight() + 1} - txGen := simapp.MakeTestEncodingConfig().TxConfig - _, _, err = simapp.SignCheckDeliver(t, txGen, app.BaseApp, header, []sdk.Msg{test.msg}, "", []uint64{origAccNum}, []uint64{origSeq}, test.expSimPass, test.expPass, priv1) - if test.expPass { - require.NoError(t, err) - } else { - require.Error(t, err) - } - - simapp.CheckBalance(t, app, fromAddr, test.expFromBalance) - simapp.CheckBalance(t, app, toAddr, test.expToBalance) - - res2 := app.AccountKeeper.GetAccount(app.NewContext(true, tmproto.Header{}), addr1) - require.NotNil(t, res2) - - require.Equal(t, res2.GetAccountNumber(), origAccNum) - require.Equal(t, res2.GetSequence(), origSeq+1) - }) - } -} - func TestMsgMultiSendWithAccounts(t *testing.T) { acc := &authtypes.BaseAccount{ Address: addr1.String(), diff --git a/x/bank/handler_test.go b/x/bank/handler_test.go index e16e8590a14e..5fcdf02f1a93 100644 --- a/x/bank/handler_test.go +++ b/x/bank/handler_test.go @@ -1,4 +1,4 @@ -package bank +package bank_test import ( "strings" @@ -7,13 +7,20 @@ import ( "github.com/stretchr/testify/require" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + "github.com/cosmos/cosmos-sdk/simapp" "github.com/cosmos/cosmos-sdk/testutil/testdata" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/bank" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + "github.com/cosmos/cosmos-sdk/x/bank/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) func TestInvalidMsg(t *testing.T) { - h := NewHandler(nil) + h := bank.NewHandler(nil) res, err := h(sdk.NewContext(nil, tmproto.Header{}, false, nil), testdata.NewTestMsg()) require.Error(t, err) @@ -22,3 +29,60 @@ func TestInvalidMsg(t *testing.T) { _, _, log := sdkerrors.ABCIInfo(err, false) require.True(t, strings.Contains(log, "unrecognized bank message type")) } + +// A module account cannot be the recipient of bank sends unless it has been marked as such +func TestSendToModuleAccount(t *testing.T) { + priv1 := secp256k1.GenPrivKey() + addr1 := sdk.AccAddress(priv1.PubKey().Address()) + moduleAccAddr := authtypes.NewModuleAddress(stakingtypes.BondedPoolName) + coins := sdk.Coins{sdk.NewInt64Coin("foocoin", 10)} + + tests := []struct { + name string + expectedError error + msg *types.MsgSend + }{ + { + name: "not allowed module account", + msg: types.NewMsgSend(addr1, moduleAccAddr, coins), + expectedError: sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "%s is not allowed to receive funds", moduleAccAddr), + }, + { + name: "allowed module account", + msg: types.NewMsgSend(addr1, authtypes.NewModuleAddress(stakingtypes.ModuleName), coins), + expectedError: nil, + }, + } + + acc1 := &authtypes.BaseAccount{ + Address: addr1.String(), + } + accs := authtypes.GenesisAccounts{acc1} + balances := []types.Balance{ + { + Address: addr1.String(), + Coins: coins, + }, + } + + app := simapp.SetupWithGenesisAccounts(accs, balances...) + ctx := app.BaseApp.NewContext(false, tmproto.Header{}) + + app.BankKeeper = bankkeeper.NewBaseKeeper( + app.AppCodec(), app.GetKey(types.StoreKey), app.AccountKeeper, app.GetSubspace(types.ModuleName), map[string]bool{ + moduleAccAddr.String(): true, + }, + ) + handler := bank.NewHandler(app.BankKeeper) + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + _, err := handler(ctx, tc.msg) + if tc.expectedError != nil { + require.EqualError(t, err, tc.expectedError.Error()) + } else { + require.NoError(t, err) + } + }) + } +} From 288f8dda4b21e893e0af0ae19375e5fc53b14f5a Mon Sep 17 00:00:00 2001 From: Frojdi Dymylja <33157909+fdymylja@users.noreply.github.com> Date: Thu, 11 Mar 2021 16:01:29 +0100 Subject: [PATCH 180/214] [rosetta] implement balance tracking and redo tx construction (#8729) Co-authored-by: Alessio Treglia Co-authored-by: Robert Zaremba --- CHANGELOG.md | 2 +- contrib/rosetta/configuration/bootstrap.json | 2 +- contrib/rosetta/configuration/data.sh | 2 +- contrib/rosetta/configuration/rosetta.json | 2 +- contrib/rosetta/configuration/run_tests.sh | 12 - contrib/rosetta/configuration/staking.json | 30 - contrib/rosetta/configuration/staking.ros | 147 ---- contrib/rosetta/configuration/transfer.ros | 40 +- contrib/rosetta/node/data.tar.gz | Bin 36558 -> 35433 bytes go.mod | 2 +- go.sum | 4 +- server/rosetta/client_offline.go | 209 ++--- server/rosetta/client_online.go | 473 +++++------ server/rosetta/conv_from_rosetta.go | 211 ----- server/rosetta/conv_to_rosetta.go | 95 --- server/rosetta/converter.go | 804 +++++++++++++++++++ server/rosetta/converter_test.go | 348 ++++++++ server/rosetta/types.go | 107 ++- server/rosetta/util.go | 119 +-- types/codec.go | 11 +- x/bank/types/msgs.go | 84 -- x/distribution/types/msg.go | 50 -- x/staking/types/msg.go | 274 ------- 23 files changed, 1606 insertions(+), 1422 deletions(-) delete mode 100644 contrib/rosetta/configuration/staking.json delete mode 100644 contrib/rosetta/configuration/staking.ros delete mode 100644 server/rosetta/conv_from_rosetta.go delete mode 100644 server/rosetta/conv_to_rosetta.go create mode 100644 server/rosetta/converter.go create mode 100644 server/rosetta/converter_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 39a231c74a5a..f878eabadf4a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,7 +40,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * [\#8559](https://github.com/cosmos/cosmos-sdk/pull/8559) Added Protobuf compatible secp256r1 ECDSA signatures. * [\#8786](https://github.com/cosmos/cosmos-sdk/pull/8786) Enabled secp256r1 in x/auth. - +* (rosetta) [\#8729](https://github.com/cosmos/cosmos-sdk/pull/8729) Data API fully supports balance tracking. Construction API can now construct any message supported by the application. ### Client Breaking Changes diff --git a/contrib/rosetta/configuration/bootstrap.json b/contrib/rosetta/configuration/bootstrap.json index 1793988f37e5..f75c7ec145bb 100644 --- a/contrib/rosetta/configuration/bootstrap.json +++ b/contrib/rosetta/configuration/bootstrap.json @@ -1,7 +1,7 @@ [ { "account_identifier": { - "address":"cosmos158nkd0l9tyemv2crp579rmj8dg37qty8lzff88" + "address":"cosmos1ujtnemf6jmfm995j000qdry064n5lq854gfe3j" }, "currency":{ "symbol":"stake", diff --git a/contrib/rosetta/configuration/data.sh b/contrib/rosetta/configuration/data.sh index 45297d5a21bf..4d7d5ff0b056 100644 --- a/contrib/rosetta/configuration/data.sh +++ b/contrib/rosetta/configuration/data.sh @@ -45,7 +45,7 @@ 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 +simd tx bank send "$addr" cosmos19g9cm8ymzchq2qkcdv3zgqtwayj9asv3hjv5u5 100stake --yes --keyring-backend=test --broadcast-mode=block --chain-id=testing sleep 10 diff --git a/contrib/rosetta/configuration/rosetta.json b/contrib/rosetta/configuration/rosetta.json index 39a0bb3811dd..b4adc6a756f1 100644 --- a/contrib/rosetta/configuration/rosetta.json +++ b/contrib/rosetta/configuration/rosetta.json @@ -25,7 +25,7 @@ "constructor_dsl_file": "transfer.ros", "end_conditions": { "create_account": 1, - "transfer": 3 + "transfer": 1 } }, "data": { diff --git a/contrib/rosetta/configuration/run_tests.sh b/contrib/rosetta/configuration/run_tests.sh index cd7af92acda2..c53f89ff88a4 100755 --- a/contrib/rosetta/configuration/run_tests.sh +++ b/contrib/rosetta/configuration/run_tests.sh @@ -2,16 +2,6 @@ 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 } @@ -25,5 +15,3 @@ 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/staking.json b/contrib/rosetta/configuration/staking.json deleted file mode 100644 index 9c5e5da3ba46..000000000000 --- a/contrib/rosetta/configuration/staking.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "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 deleted file mode 100644 index 4f89a43b9893..000000000000 --- a/contrib/rosetta/configuration/staking.ros +++ /dev/null @@ -1,147 +0,0 @@ -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" : "cosmosvaloper158nkd0l9tyemv2crp579rmj8dg37qty86kaut5" - } - }, - "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" : "cosmosvaloper158nkd0l9tyemv2crp579rmj8dg37qty86kaut5" - } - }, - "amount":{ - "value":{{sender_amount}}, - "currency":{{currency}} - } - } - ]; - } -} diff --git a/contrib/rosetta/configuration/transfer.ros b/contrib/rosetta/configuration/transfer.ros index a1cb3f8caf89..74ebd2ddf50c 100644 --- a/contrib/rosetta/configuration/transfer.ros +++ b/contrib/rosetta/configuration/transfer.ros @@ -26,7 +26,7 @@ request_funds(1){ loaded_account = find_balance({ "account_identifier": {{random_account.account_identifier}}, "minimum_balance":{ - "value": "100", + "value": "50", "currency": {{currency}} } }); @@ -57,6 +57,8 @@ transfer(3){ "currency": {{currency}} } }); + acc_identifier = {{sender.account_identifier}}; + sender_address = {{acc_identifier.address}}; // Set the recipient_amount as some value <= sender.balance-max_fee max_fee = "0"; fee_amount = "1"; @@ -76,34 +78,28 @@ transfer(3){ "create_probability": 50 }); transfer.confirmation_depth = "1"; + recipient_account_identifier = {{recipient.account_identifier}}; + recipient_address = {{recipient_account_identifier.address}}; 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}} + "metadata": { + "amount": [ + { + "amount": {{recipient_amount}}, + "denom": {{currency.symbol}} + } + ], + "from_address": {{sender_address}}, + "to_address": {{recipient_address}} } } ]; + transfer.preprocess_metadata = { + "gas_price": "1stake", + "gas_limit": 250000 + }; } } diff --git a/contrib/rosetta/node/data.tar.gz b/contrib/rosetta/node/data.tar.gz index ad285ac62e75198c4945859e12ccf7b563c7c29b..987bb88b33acaa6ad7324d25828ba755dd9bad29 100644 GIT binary patch literal 35433 zcmV(}K+wM*iwFP!000001MFN0T#R`ipJ!&&^ay!e8N42|&bFPN=b2|tTB(p&N5xv! zGRIRU)nsN$xt3KFLhEiLYgsIts}!kUb)Yq8{bx8(iLOw-n+Mr(wR`T6LX zdVcf#?%(%$p8ug%skAO!jWSpo8tOuOGlT&WVwnDj)jsM!<0M94B#sM(JQ{`*7&xH( zH>6Ju3e#w%Y80iZfg|eUGk5+yC3W@qE2LWK8%Tl%#Gk+jTo-?#KxmDBV^Hn*Q{hSl z6(Xm&3Ymp+K_7oU{}t<>1o7wN0=_l=jY0Lt-(#eYPyeBQuPH+pU;#wm~FkHN1mqv8FZFCeV_zfs6s{0CY< zhPn9jNxo_P`PTm5IOJNB(9eJ~_|B;AJq+4&q@PDG)Pw`ZaS4G*2oaaylOS3sxH)tS zq5`N81v(%nZD?5V0A&z``sSqRj=svN6go5~t$&DC9f^A6q`6BKhR^Q$&+b7g`6P5O zm6JA@itMjetJJ7xPMW7$6&gxaG7iZ}8=}J|bVN>?FEtqmK>c#k{FK2|{~&3ohEn{a z5f2A>gP{tUn<|tFL3KZrAptec^GN|3PN_9YRfrpiyjG|4*l{{_F?ZcjuKTsxH%LB- zi*;8Fl!hn)80z>5bRb}_$wcz1#41!Flukt+#>Iq~Fj(_0KUCGOf0-^M8epo$-T>)p z{MFz8@bvZ1$F1*w8iUNm-x655p!=%wj;#~QN{_Bq?d{qlxnGImyQM=mEMMIr!Y6&C z#4Lw9dLp^Ql@7fJMRj*Q(qYZw^=nrD35|>Wxb1Q5jtxe(D46DLmcs{S&Wg{NQP{KZ zl+4Wdf!e z_aO+7ftZ!yaE8vd#@90O_3l>G-WP!v8G9lh6!iF2h{xpb>P$s3 zpH3SvwG$1pscsOgha_JeBr#c#12p23zi%#}L$)S8i;!SXm`ENIj$_o!X*#Edl1>(L z3xO(|#``WEhqW)*b#>l1a729W`3UbxWfk|<2tw!l9$NCvyHgr13%j&Pz2@CHWx!DW zl6c1RK4lN+saFH1e>`9(KR$?`u99x^)vpbV|?<{X0JMXU2Whv_P}US<)h% zeiGh(wD;(^^!BS*A>mOEAc$qst%*zeZawna;V!<9J1lS=8pm?6`ETI3Z#E?^=8S57 zQj*YS+^>^!3^tpS;gH8TK z@W%uSnLx@{hzO}rEEo9`1Ydwra*8JvOL0D5A(shpIROzTQdVe>fzD^r^xxaI{^?K0 z76Y7WYKl_?Fo@2!SdG+c&|JMicguD?p>y1>_PQ(HSiagm=_9XQoey{%n;EcT$imiJ zx|L~GuHx*!uyn)XXXOsQkxxF(iv4`V1G^>{dbk%vsKr^1--eU71Nt;u>DZkDIAvcC zPSNjN-gojB2Gq<1r+5-8q(ome#G!|Uam>U1nm-S$ke=)hj-_lcmHGbzI$&Fr*_fd?R0nv1jj*eCl|R& z6Rgs3WzvvI+;Ch*X{9*#GfjYtFBPIdg5XaK=kc&WZ3q?YF9;0w4;G90f#8XDvO*mR z9(Y6eL6b#%GQgkW1tLavae!DJEQ$=CDxWx+m^?|Y2;5jSLh^HQ~I8f#Lix zKHDB{0-j4JQ3wOaFl01593B97HmW37M}}%uTn!};1?^)J&K({m8%#waAHiK16{XP! zV=tai%-{a`(~ajkj&eBiP}d@ z^gA(A`CB^q&8*nE+}l>bz3X&o-Rh{sKAJ(&Cs$)OWUf82FKQ5H;^Z*soYS;nF1MZB z%A0PD^R`W!rS)}Y`8PZFnocWO@G$bPA`IPDruLbHAc78z_dC&OWu zZ7pcGHiNg?3{dEKk+v9sdka%=#{p0ia=Ah#67hJr%wL3&Vu3;=^B0KaLaA5=aGuBW z7m7(-#>X&`LP&}gLY`QPDZpP8A`0UDUYPp@0CxuyaDQ*Hu&>+Roxq-!rr^#?g;)%> z#j1o8P^UpnSqt?Bok-Z(g5%ch;<dfezg64eCO(qQhjcAI$QM!qibwG=5heGB$dKGA(xWt}tqDfG zuPy!i@u!vG`LmrVM3DeN>)9rnXLyLyd)rsR~T`tZ=_U!L6HlXc7`*Ep`%?tWo zpARs~u^xYx#{Voa1Gr)He|6*kLXyC(`NmM)2OD`M*FTAt@xqb%R%Yy8gRSsQ&oBz4hM$YyWQ) zvd;hgu&Ms~x5VsUv-M931=aR{!S(e|l00kuHwM|QDgWx0UDfH5nbNWJrTmVZaU?!}MeIul98} zqjTS!hMsbjGGx34+>2_tx}R@I%zvth`B$#+(q8~11f>k86x_-W>Nk-XU22N@SL(Ji zMlM*T2n(WIbmj1B-)y0c;7+8J0TZ==|CPRBmSc}Si@~Zl`~_Uj;p#_`ZBCbr^+T!TcuY^hlZKo zWrv}Jt6fMZxuy-qHeXMm4M1jrNL$RVdgBBB^#o;v?agLLNZ7VANJuZ(#t;ys{<3g{ zBqW%LWu2ezy7K?6GmsAw^4W3U=&SZ@MfZ4DIG+ljD@<^kP2|FP)bUt97O4F6M4 zhy=E+tQ|{fDTABUXd_5(m}P7k4R_+pWpwz*6ArMAA=MG4E~bu<>HS~*_y2Ei{~w`s z|A$5)>-gV?P4(CR+uQ#~U|s*;C}b}FZ)^V_YyWQ?dX4>maDwC$qIYNf4`?LfiO72P z|G~jovO(j21kMwRg=WV808@3bRpWnRu2{&!-?#BUxrRGM8f3|Bz;!kL>ifUz>Yv2H z!8-oe2vleM!GBB1(D(m3$iP4wIp*R zgwQ!O=Ke*q!5I`bE(JZYECHNxU^ju=-(05hVq~yk)f{^(PWF7;KVmQra z03TR4QhA#jsl>&NZCfKfOQLSvd0Bc=;VLZ^r1ZK1xPPnSezxHcz?}sl2OxMKM5IA* z3Z&bEf@86qbTW!6iaC7=B3^2=yPInX8S%N(9knR2dET-Fl8nP2}AoWUEV;$9APFA1OU_b8`NHKH>=gr&a7Za!wh&*On%J*x~`m2zi3 z9dU%)0yiMl-5^&52P?H>nyl$r!x6Kh{sjCcj-bC0N9fm_*X4-UU5TEbU6B9`>sDo0 z;=1J3bfgX33OJ%gl_Na#UWjd1a0D>7u3|1d_2-Xtgvp_^pmjF}!8JU(Ew|v5!K3tQ z9vwA$FWy9#xc%yX5tYS{@EPr9^QAgQ+@W)l z&5g|BuUi**D9Un%Un$;PApTG2%AQMjs&PA3OB1eD%yUi|_-(iU<@AkaFYZ!g^V7%A zey7ps%d4z8dM4=*9f@j!%x(f#FrCVnzz5b%Uf#j2Fg}1yUc`!9`85hNDk=H;%L-GE zB+jla`IQaSz#K1i(FCK8$ zLK21vl2~ZHr%~#XznA^MkhrZ9{@we0V)ieAPyU>->%|cMbosmok$$;R!5U~e>ck5u+l5VKJX1gvgyzWZw zC*kR*^@(5yyI~o3%%wxzD#YDLYC2luq-le_QIq!iA4~~sa zzS+A6nR2V!|Jl11XsFh=j|L@$QHW?ah~zRZ!=OTjBcyUmxr|}P%rFNIYE>cQ2(G4dRiKKGxDiTRW;=lKdI%d#5XZ_E2*0;Xz?6s`Lw)gY?e$Vqh&-1?T z-p{+~ReA=OP}NbDtEqKSFAl9M?+>5jA|C8_A9e6t*-*W#wh>$HjwzgzcC8I_KmoJOK!fH!yd;ad70ys zSxnAI%;aC(opFjS95Y2_5vae-4|RUPYKtLF6f+~gH72pmOqBte{Ormp=MZ|F*!-|N zIpj9If!4uVb^pxFL)lF#vM0}5>biDKDLm_=a8P99)$UTQQ(n?>GVM}?O(%aJnPBi6 zD>`^)ujrU)_ak+5Ffy-~GbB!2TE$DdNA~HA75OBW+~L#&7NT znWSt{UiLtY$sYbU9*2xf*+yd8o8|&hUiv_oO2|(W(CGP=2Mv6UijS8+{wE&Y{4K}W z=YQZYG-@CLdLi_0Dgos^|NU#{TDNnf1m&UBgen> zpZ~uPSpVn0qw!yrfd16~4UN&5G2eeNGyHe|r+?;1zB1puU+qWzCl34()nyxmSU@j- z)7b_LSBKm@lnPb>hmyoNaclOglT^YbWEU394k$^ryZHPCAR;EFK;UvH2FnN$%Sd#l zEd{(YkV9gz#Zg8WQ042eF&X3*==_HB-fmuOf zK}8Y>&{9Gg{?x#=+f?AE|6;j})g)r{A#Qb`)LWUld%r7n(cE_H7el_H$SWJgk%9as&+m5J7ywe^OCGXxEKD685OJ3_e39Sxa z&|njZ1K^kea9{rnf*y;V>5QT@u9n{u_IeNwL#C`CSiz$QW2i1%*r z3f`Ss(I`400v`~`E5SnOw3@#nd->ZyY<_LvN-5>uYa#_3~4D>%UBkZWD=Ez0g z`;sBr1dA~<74AEM{h|uh%D2m3QYL5bt6S$_z*(%eu=v5DY&rR2HbQB@obSqfjGhD< zl?ate@j_z+Sg9;zjUibhc+A}`&be1+P{$~xlt?5s-m_2+0~|OpIQAsc+-MYNAtoKFW95~a>V7Xn<=aJAwGNqY zTAz5iFkN&9AwIHlTp`hw>NASu9dG zfkjk6q4m**XrV(W9KTE7h*QeT(TY6n^(Ot)94(a=zxpT*jr|=RuRQi>dYF+w-NH2l zz$pcQqa%o^sADkbre=MGkMwK(Cxcr1wpF%Sb8~M`U3+ogr>F0)MtFg-U>qF-aQy^; zBP$3)ylFx4owOKd#pKraVGDHLZ-0s?p&Qsb*04)rHY-OtSb{bH1XaUiaM|M+!34$# zZt>DOS)Efe_p_^2XEo9p8VawTMW9`8S>(@FPDA^XO`rjvKugdXB$q+uL~;lbye5ob zn&^39YoR&~X=JLBW9jnSLjSOsW6f?Z*Ke0F^Sc(#Y>MQK04Hn$fYSv4M?nxxh$4Qd z#=ev`e27%EswV%#0-Y8WN=E&Rhlpyq&?mB~^T((*oXVjPS%h!`k;o!VI2xEc%WKvt z7mHVgwCAg|lfO6%?%rFBY3A7QF!@tiD446~~e&igl zeEp}+%2V%pUw(`nxeFf(4#b$maYCt(XD8$%mK`e1c%ZvMO03*z!SBBAjc2#(A2jiN zeSTS~<v2dUb7< zd~P{}O}2K=uAQw9J1+F91cB)n z*5LrS=mEfS7X+mjUt8Jpy6bao*1hbkUkz>ao<~_<)RD~9ck3sKpTK7NOa>-O!~ooQ z0)S&I2&H^=v)-bFZC+OH*iNE6tFAe{=g1So`__eLPWY4`C#J=SLUSCb?{Ek-S|tBA zS~O}cm&xKny&0`IXrsht_d_4fN2k?$f*v)d830b1033Qj5H-`X2Cs#d*wPnS z?>JhOwWZoee_!hSZF8rp23PN!xo{Yo)*!(s!{HC2+2F8oHHpBQf-*HWG{hJQhwCzz z7hiTRa7tPhSsz&2ey};pU%Mqa*CNa_>dcT~fG%1GvNTWJFH8b$36nu2@luVc8B87s zn_RVI`X-U-*E&~uTKt_dt%=k_0 zXUSGUmIb?%!4{_TS^(*Ba8SOM97)$gvy?u)&kB-F-S{$yo_gRkn-d4HijQAuaGhB8-;SxT0<-Mc zZV$jYEdWPS5XCY^Fn(^zE!X1@S~2Z11K*Nm5G5D~qp$wEUIr0jYwFRUc~#jo0-FMc zYy%uKoWY^eNsa_64L34tosKe{xc7)AH(KFaUrPDh+1lV2S5K0tQ+c%SKx^?S?KNxL zLY`kUg_an9hzAYtMkO;yL@?5F50N^q?lTtmol0jmKUs zeQj}+kdW@rH}<;|z@GK9MgTY^0B|$}@o4Ut&Dgoa`iB0V1La@NnQeIV@+S9sdjC$t%nIZ?DK}oo%SDRfpJ!07qL8PrKUb2Q4w_1>H$Hy21NTsTDdZS@yMFJvXE#e#Z62 zS0iZ2MQtJ_@qOq|Eel9geXh$$b3k57@%^$ffS~cEDqz~a+}nY2ABgv@n&;)KLJ16t zwoo(BDB&jocxl^)<^+7eD$M0)r%TtTJglk7>6}s1Mc6ZC%Go5<>05XiYm6)ajw%3$ zQ4qy@RP43lujZlg&$X?aY=2D|K1SMF!^L~=pPgT3keaxT_fX|K3I{5*xj!|KK!f&I zppw|)JcS8L%(Xt$kcKFqzH`NaVwQ#V9BoVLjbpDV!^a~_tLV4t>Xe`%-*<^%2pth6 zDzwbt6qSBgR>`GpQ~msuhS$lCu^;n}<9->~&>4}+$n@PJ;RUK^95DbKApj1aAdHIr z%o~7GS4Z+HoK#tES)G>|MXb0%R`uGtQ~Qmgm#aV)pE(M~k99US^xn6iEEBwwe{%KJ zB3JH?6Hgv>bFv4jOjMmh9}_%k$c=s*GIU4F@?e0oI3oBPv|R-fWr#I2F`2kydQ%P- zbuE%DU-t$-*%{Td!Tq)sbMc3=Qo|(~I*uEf-+F`E8ecR3#}I&nEr?`Jr5Y|*+pXM# zQJQi$eVTH>&5cQmOW}-s)5)em&v)% zJ&C~Y69SB3nDVj!ImP8T{o65thgqtpdqGcGW2fYOnnE^b&*=f zz5$enG;YjH9)Mel0N{9v&KQM(HS#!H6o3QcvxQQrAtGw`{RZe~CM1a)N@fv=q(4N7 z$Uf9*+$ADvKXO70I*EoZ4J3pT0;n`9ClVa{t)y{*X^@q*%-shq zzRVO|{x)n$be!E*wU{h-sT~=~%$nrH4N^Zg?}Xa?qeO?d>!3|wAa8diMFwHTt&T9YUYA(%)ZU?aK4CiEaQiJ~+Ki45S)(D58*2#LYQhccNo zWr+YTi$P*3OOCkwC=v_tzSC}dsYkDA)Njvj+Rpvld4U_WI`2A8e4US+8rmm=Phz#) zCEVj8l)d}VwEGHIuIXu788pX={wWqdqgZev$#k}H1ckyjjtn!wnuSs#jEUhU1anL< z!;E7_3#FTwp;<}@qymG-u6PSm9wremOsoAwEE#az7@zCxq% zZ42D(KbPqriQf5m_WP6;t3@Az{**qgN9hwyM4Lq#nPSLvIya1C5`_*oCxm0M=wJq$ zWrjuvn?^CrLl{cp$Vp)2_^!NBVD-#uGYvc)SLfiXZhl=<8pi3} zA#CDZAO6&4l~8DjmfOFL8f7*!8BuHs0qh3 z(41q=3NbeiBx13&NNx~KNen4HdPR2>+TzompQdgtOCGkVib%UN-aBHZ5#Md6MEQxsmt{FJ|)06c~qmtQkB}pgyDA* zyfi>7HGhfQr|AV<}cE z)y~-E!+W-RMFyQitS>ytCjWKY(Typ_=x|yXI|xgovA7YOQ0{-&yY_G>x9>mi7=v+% zA-TmXQORY7aT(o2E~lf?O^MRPAjWkp zZ*KBtUiQ?tKYo84f7J7M_Fn6=*1PuJYp?ZrU*2xP%utfIkAZiPkEw^DsjF##0-lIt z*9nyH?0~k(v7IfYa>MuYIL!yu6S)D3W+M!GnlQ+L2pG{xJ!7|2cc|*9yiZ)1&M-@8Jb6a9 z25N%;_&7=BXOFpDMBf9VJoT{oF+t_tISr3Na8XAKKV1AI#8hRjBR0JW#;gelq zs$FND%d!nhJr1#x&g+@06j#pKAYpT>IsKc(3l41sMG6e^77W6N03k8^(Ej=pJ26L3 z$Gtq)e%!}<~i|fBx?R@uk$NH$p_McOtQjV~x4-kezAo5Dc1|%b@ zF_l6!HZmcq^8XH5GO>+9MHr-PRRUGo-K#YYxW^hNKvWfU&1huGtxB9 zgJP%hzN_!chAXaldz$9D<8dTq%d9Et_J?#QugK~fOHKVNC3c+@+cKe{oL6RW<`7tr z2rXH6-B%E_iZ_A%?FC4WE#~{}#<$R}{`DVqdvKJ$@ETVYx|G#rjtuOtxRX@4T&!D-ILX2H~d`-PQgThQG#tgbo zFpV1I#-uWXC-7mAYH1CY9Q#PLUPooC+Yu|1%q=Ir9#b`T$~cl66d?j2Qng%Qb(I(JpEUb;{}CaLjSp z$D~S(6c&pnEseIHRg)ubg>>!{h6{ZI2Gj+$*wQ?KMdpvh(%jD^E zD(Rz0he5`|ApAdg?rc{9bPDS>FFNmej%H$p{hSWt*BPWepOobduRuEEwYj#UT`o9i z2!pmlKNx9hLTHPO_fJaBskEf}R_r@Fqp`j-ZQF$NFKqBQSl5Ur7Hy**O{}-pv9W+vc%Kkx#6{80|!fR9Ny~ZCWIs6^I z`AdSmkkgcl)3Q!hN%g5aO(@pmYCt=7Ig+IYH3;(sc~)D(Mr*55rqq?g%*0?bwc2jy z`;Fh~6TK`Awc2Df^LefuQ8Wy)9tMF&qFFT0oUw=MHe2lJtRovA-X5@YcWo{wh|i-h zIenxCA}r+e9!7B`42ldGWG@m;D#4)t+3e-JFzOZMmAX0VE3>0A`w22nZEZSJ-fy&o zX?TfI7X=Jj<1olx?&-}zGqg#9U^(9C3kws2e0dY3*pqZQ8!oRN>f3N3Q=L>Pn?1|b-xcKko%7fG}lyt&^khpXO3lCawCIPu!YCj8m?bxxZJ zy?OhvZ1dGo&Hn-+@&P}8dLZyN#tfnb)BK6Q;|zy|w7(xE212G*;HgH-bpy=W{5@@QouPzeTzNA`f$<+lPiYyYY0bkcfkSOv;OvR3ervbX3mv zKh$vCO?|(6kUraw6Hs#qROb#8uOKr=1poMiSD$RR=$-Ug?Kigg2k%Wjutn~2*@I25 z9)07aDCpv0&@+ZX*oR?pSaDt|#+=+?V;yBbX5P|U>1|a86E8H4`)pXJZnmXa&6%|^ zjSw<0D9mAyp~J9*&z<(~w<~>Bo71JfCN*T;RFZdIbTi%F^57G@e>PVTl}y+TQ4QYe zC&(##mJ-X>>daf~6RrM<>94)-e1y0l?ti!YsJ&M4RY`pf)R7ql*KX2^=wG<~Toa3kq~n_6-nu z?^~G@@2^_{kMZ60+5y@eDr+pN|zn;OSPBM%SGih zrmntXWY84yXkV1`xl$Kf))vQ#KNz$YVNfIw(;NJL=es9&O-ReTm&c*6! zvtyiQUXF3YOM&({7_?`@ATMw`euJ2X5-2EX5H8D^)U-`tHPWK3;AxkkBC*55n zA|Bd^Ox6t8V}Brh`x?%6``4u;$rF=W_H98|kht{LBe}O|y6yvB*DRw%&&|VgDnzJL zl_yzf+^jh@_O!x<`eig)-`0fE{KZksqOA(k4l%nS9ToOeNS=VYT+sv;m@p}|P5Z~( z4gR94=HGno$(GiPMTWvI8iWH*W3(w*oU{#sL6Bh(Ff`rkI)wI6^~!VGpDPKkJ*9JD zpRnw2rxw#>Fh}n9r#bKKjc;4BgX@ zGI#IMTfm&pKI3qLF9cOlh&bB$g91TwN}q$yo|;eMS$8BRCOO$vJFn77e;e-N=6w88 zMTtd00Lz^}0|5s42nHFAhO*(o{JhY6>b}R)?+3g|FOMPZ_6`Y3%Dc5b$m*}F1)^b` z1PI;nFeqSPkPFZNF&~TGxxI1ztmv)ED`#9!+7Yq$sO#4f8eD1!#?C8j5{;3M1 zCpv?*N@*;bWT@HII(K7IN2RuU#M-=IPoaME3xCE&J7BRd{l@2!z3H7VXSMBQiHd6PN+||o8XRu4 zu>LLmb$m1D{1`ntU{J`zAgduIK43$K2neB{SY~Ju7TU?1AjF;|#MCFp3$wNuJp!If zY2kiF3&dt2>JvnG#1-xYQ0_)FAP|O_C)_ze3X3j5n8Pm-P{mY&5Y5$WodC)= z*nkF83jyt=5PskwaA$!+l1L;-`Otk_5Rrj_M49>w8v9m+6@?%vroMk*kT0G4SFM>C z5rzIs<`^genF;Z=c(6c^FFIp^XC+jL;Dic`Y0FqVAVYw5@qRIGgoJAA(VBxAj?r)Y zt`(3yrSEq8DyZAXnoO@Q&Z%vV)vLazg~8$=3`|fRES-)uH83uz@6}IS~Nx1qe$JV;9vz;TpnK^ZCWLP~V3J(0xmTleUSeZlQi$6V%d59p ziO)z1VUUAhkTqz4-07`_@81;_9a{Hx=ax#%Hq+V{I?jS4i8OiJ5 z#0O+88lbK#$4C{)E`M6rt4ORCi#?PPQE^JCEPd(am+!k|Y2*-A;)4SvKA_l!K~_T+ ze8Bt=dpGBQ(CrU=JrqC*=wboBc?h5cm{EfU2%-d(m4nlE0hE9e0APk7h!Ws!5Hvs# zCBQo{Xn-I}K>0uTf*^nr(Cr6&JrY0(@TvnEAczuRK?pQpl=~DG25o#LW>M#quuwK{ z0{i37!#Odj-XfjnGtSP@4-Z)o`ZoD%>GTG=%;zw#kB6#-1C}c?m$HvDbefRauhE1Q zAbz4y0wr6dHgbMd#p|h&c}^I|!^=zuJh`n|+$`5v`5j)tquGf-O?oWbSZL6Q=fn6Ve1`thwTD_nf~RVA`q82?$w6&)PyBUtKgeHus^&7|c|k1C z&=Ez0sX8F=NHk^m1OBON->Ek3HFtY6DP4N|l9ZM|^%bppLMLNex{h_ySXuk1j1JIq zgF*Hp(M(<5TwSla?^5QKzqF?iGTv*jdam~1slcn}ld=0yF7@xz$9XQkk zdC^!|_o#$4P+-C!dm*#$X!!P2APosLU^L-C8X{=GXu?7KC@_I)6yZRw7-+y~!a)Q= zFvD;Z;UE$lnB_K#a1dV)Oz0a$IH>jsERLcu;;=Ai`K3n2#Vo`_#k>h(7(PavSI)}B z4hv%4M#jU;)0=knZQCEuTi+)^tg2 z`Vvi{_e86^reZLXtGjQx;iYl^Gm!;k95e%oiEmQ|adW`rozdlk`d7dP7eGFU$McIs zA1n-dc(~K8%Pld`9RwiM?+svq9ojC>KQ2wgKov+ysNWmFVv67Ew%A~xyU3vO6FvgvV5_>@jTk<7lo{RId zk7SKF@#C4dOLNN9XWA0YINi3P7u?v_NJCR9)sRg2{(>9D(A0!%L?)4q4Jalg6AFcF zLZTR%a}J*ngCkBKM*OfKTD(##COAq6j%X>6yKQ<*q>rXuttMIa~Ly15Cagb4grQE z=>S+hIsiuTy*z8PspZ>jkaPecUX-kyG331@NXLj z*~S)JcJ!Q!x16y!{79u-kOjY5%Eb=;4_bP_wFy!HEJlL{j8MuIf>?|E-&2}p(I%!gIy<(>KI0ZK@V<^*b9?D78FX;)Oyx4j8cZ^$wxllEP|5H=Sucg& zhh3M}n>cgoO*4z7tL;aiS$;*~w^Z&A zhe>lPwl~3^HM=a)SX*P{f3rR-*q|JAAAa{m!Hc1_}iYsmF z7%BT}n)Cw}QJBa#V-58i0>#Vejc{19tZ{7dI8XNtFEWIU+Fkt9ltP2&oqVv)O)F$o znwj#qW*=t5>rbR^}>d7axwLpC!ey7N5$Ua>aJqL+ZGl?&s;>)C$O;)$FCw za$0y)PD@|vEN9g`pT*1Vq0GDf#?|Y49Up8?d|YI~*K&bD9kUtHY`Hx(#K-cvDbRX3h$ga6gdJp&go4-U7US&>WIY!29$ti^9%BM z<~tl#$lfgG+gQltTrQp;S=%ltUjL;Fk$Mhz)Lbp(he{$}S#N zr4=t`SMFW(EfX)~7;(IO~UAb*9u^U`s4WTc*f%7&S#Cw#RK7iw#AcHxnustdiGNo$&%4s1_rvYpY| zelN0iUatH0ihn8-KWo{d!?ZDPtJhi78EYq&F(xDsX<3!$-nMS3*MDwv@%4Y1_!ct>&?Sc+tFwu@c6QZBpQbuc8 z{l@yy@!rw(TH+;VtV+{jZ%W>2H)1`!UGH3wWsI&;1gZc)0raywR&Vm!i=!8BFg~lX zBDK6&rsaaL+3itCf$H@x*R35Z?ir&iX@M#LPyqex#uaKl3lV?r*SWqOvmo>LOacz? zbLGwEsMrHHnwxLr-Eky|5`Ve^00qZAgWmV7h4N%zA`Q?F6)1*S!RXTu6=mS64c7_) z9)UXVqx02g3K;CCzut%#p3D?HrfGe`zT+g^=iYzd#Y~wrLs4#vg^~NPO*YptTW=d) zPYyQp)hYmVK#RXm$#IYN9VtC^pCbBt!D2Y^^JEH@t|<_=VozI=-7u<(ZCGku^qT0= zqvdMc>OcBkx{_R{lkP5AJW;ww_h6_glPxcvsa>Lzbc#MWO8Y* z-@M#Wtn)_bLj;ROpqLQIF>baGH6r(Ry=3ZCJU#bhg}7s0$wh;eLS07&} zX!qp!U}_3OosK@q1!DGWjxVshX*-Ub?^{?$m_l&Jm+e?-Rsr#m(6T$u4zi}huSl>uzVK?Tdy?PDZ$dO8ZGrqF3LCX>PFKhU{T zQ&g<-0z3D{dL8hIz2W<5&+eVw7VUvoH=mWZP@V1?5I~&OV-u#Pa337p3|_t!ck=$e zCn;Bly&_A5H(sC8Es?%pKN5X9O~EB;-)zj+TrUr53e-Rd6b(0r?khHQW;(T2`emyf z{FH6w(NQ-{GyS!jcD=q>h=1(l1GeaUcF5EeC|Yg~Q3?+xc9Ju?C74>j<;yxx_ph71 zGEpUa@4V-QUJ-A_M>`Tn5g}>{G`0~aYCb^qzPAa;&w>O5F#>UDeuiYzX9T3aK>~sp zfoMuFk4XR{AbSfE5X1;n(*%p2f*1kWRgi!nMnEnoAV9l!-P#jNC>O*QL@R}Prvey( zD3LH{QUD_m0}!SN@@A;u5$O51^RwA{0}OV2@57EKngkD@USV9^=!BaEP zGst1JH^tlC!O@=@XS=PMno*kt!W;yzD=W!MU6v1H5g1E1WRhbr~Ay0jzC{fpzgFSstq?UDXv*MP# zM8mBtwHwRPZ)zSV1wauD=A?i_OJdzKkC|_>oMX4x-Ak!#dajUqmwf%6x}mck;KLwz>xPaI zfX^A=ts6Qi0X|BBw{8gO1wz62=mrlxfCTvH29JD!1o-HN&SDtCVGVc$nr|f4SP>yC zb~^U2#mbLZ*7v$hku~`(jRZ}SoNr@sAksm7mZq9^K;*^tUUk| zbxoQkQ-j=xWo2lPX$pmD*n_N`4JXdj6E;(Fthj}VP?_0pf3Qfm|0GUDt@pKRY6?s4^hPrZm%yvO!OgIQDJEMaUfbzX=s4< zL$nIu3@1btKLDb7`hA|is4$k&JBWED>HSVola9Rgi;DLTjT$~zwqfTVdWo8^TG z5!)smP`S9|nNLM{;X<+}c}BvUd(-re=6jjg5=gw-1%dh#ftrAuL*A$EDpk43Tc?a= zGxJ4{R6BPp+K*iod0}p`_vP7}EmL%QItotGYfu;r28G;zpmR^sw<)Ykxm!n%fAWXd zrY`y%7x!WLD;7Rde6>f^H0gHyQ;%6aHsK^a_rbxEetJlBr0b%~b@1MZ?V@n`*z*k1fpH2IrTt_kI4D`rcAD$*kdM zmEoPvRQ<(zD{ToxUabx%>7i)3Zt2xh^y!Qx)71(SD>i2^DeDbf zN^Ut4N0Fc;Jv6ovC~7{rI{aUMp+Xc~sS>~lSf7Ig1Tg}YEPke@(PsoI*uWJX0gQlk zEJ#2QBhVrWTxAJj1gtYb0)iL;i>;7=AV$E_J0u{85vY6**Y^c50u@2wDk<;mJOP0o ze1QcgCrje6CcRHNZloi(_Yo7Xy|PXe{(L#&b0urZv&AWX7ephMo~=^)SULAkQR|-9 z+22b#!Ve@Jb;K94tF5Gz6c2aIbEr6!e?`>vQiw;ou1Ij(L-o44map$P9;72Ef}xU* z`uY(1kORN;AOj$63KHN!IwBxYyBzeZOM^7RricE_7w1p^IIMEIFupf39dS9|O-*gmOLlCtSN_)QgXIQk=XT{ST2OPT#ZUd^(PKVkyHxMi zUQ^z5|5nCr+WB)YYJ1fVmbqh;-kGdk7@bHlJ*@2~7o02Bw6yZk_ANRA4{>|Kf;VaQ z_T*16cOb_(y^-mv`p}9`I8fjG;;xsrFDZd6hkv~4{+#FZ{9|wN27mTWAl}R!sPPdf zUQTa(Ptkv6{~|j=e}eheICALTt+#{BqV<&IWt_!HB|FYiS)?(1dlG>LCIZFFg%{BG zgopTQFrkf)a)_D-bNBcthqzoY*^7^IDCr4iMfoWQsaTKzKjk1X6cXU49Hg{C0{oOi zbU2tV$45Cx+=K-9DF>;+kN`jB5HAlV?hRz_5D@68NuDO)Z% z&yLm_5T|?I+1$)H*)6bL-J)sJ%Ba(^W4bnVpE5?D`TrYx4@C!x9e;JR%-Q_)qa8)t zuUf9JWeDj`+Ov80R7`4-g6h(JLg+gTXF-b*65i2|F+`9ZLE7<^F;o$sF}jB^Bq^p+ znG;6N4>s|PYEK9{R1>BXsF#I__C35dUPSM5%s0Z&v-K^fjs~voUghT;_eT8uJ6vf2 z-G;_2J3LDsY(;I;T=w~-6>l7ig4e?9Bk7DmiZ1jrFvz=x6`x&7vTCTz~L`&+8i6cn@5r&`u z`kzXfF;YA&a8aws$rHM5x1R5gkwn(7%d?(s^SG-cci&_`N78uGPZNfq;J6cR`X2ER z-)M-0q(1!+#|kE4@z)P=$6#_9fBjHJ87w(-CnOONXmCU|Yu#7CV7&$u><18%2$%`8 zLt^AHSZ@#}O2EX~6*(GVus(voLaX43n5(zV6{7Ol#{9u7VFCctC15I z80lhjE6w|s&&uM<`PvGRUSpNgl+U{_OF8ON^M07t*D~#QtVYiVzlH`=lR?q!!)h?q zX%uw^m8wD3)TGd847xgnqCw-f?^s{&Lq%(_s?7zfK|r8j81r*Y(5?@Fu^I%7cVw}O zEC#y{0O}Gj_xHuf>te8hoPq-|H3YDz|B4j)3{?{}Kn>^4PXrJd66vSK%)?>V_k)BVE|3d?D45n2V4E^j3zYlgz@MPf&`R}3{0VvkG^zXHPY41aE`C6P2y#Pz6bL~8 z6bL6Yg&+VlF>s(#1QG8;r4R%_rSt)q2rz(&6JkObxC`39;PPR! zebrRaRVB;IOU;qx%Thysc(^*SdS;fYqrKXEJ#!Poxt3NlzAYVxVx#9i291X4U48cd zi~c7AL#C-ydUk`<(4b<}$r^Mz9fJ(X*kCU|bb|UI$k&G8CkOrizx2vcw=zWE4_HYL zCx0goM|)NMKwqZ-*R@UtY|ox4@5}bVVenW2CTVvGiHO1Cuy`Ed|Jv#QuD|U9=fBwk z1Jj?h0nUH)_mA_RL8USNoB#jBB|!fh{j3eB|LHV(|Nf`^_x%57F6|#LWIoy$bQOf6 zP9Y=HtgQ@`kbV-vWU>}TU5lcj%3x9%sFVlWMc2d0#c7QrVpx=I?&oRf>fwY~7G?MR zwR8<~Ld=V@=dSVf2}BHvvh`Vx-+t?V{jKl8c5p{bormu+!SY(`N69iZ zT@i-qV#kqAd>qL;EiSBQEWad6@*D1zNAm6{@kol~Njf{u+-*&Prmqx5uq{KnwkQg8 zShsb_*0dXt>=A4QwqV1u6+^e7ZPMhM?(f=LSSjsLbrlDc- z&!Uj@!v~cztQhw{|Bu_{*QLI4L)(4(DnbV7*{EpW`c%=8KRjK(~k#SyKHIj zoh9EqUw7b(5PUHTmg1LP9l;+yv3y2;xNv1kSuz!cPrL5ovM_52!&4_#*rg12Og=j~ zcQM6I8^??Mn36xLFG|Ddb5nE6$12tYKP;3_jE%dBJbBi)ChX;t=W}N+j1>+aW@1t~ zC`UacC5^IaFb#t6el=#VnhNi`C%5g&2YnM7(6R+>?oWc719|1 z2lO%^mj(DcBaKTkLtT6G^xx?Jfx|=Q-!vMiCg|uotpA`+;8G$F{x5DC2Q9`s-2YqX zfAq}E%=oFfjnimb|MT_w7e$Hf#{aDtb+>ok%B4zoyaA(y{}Y4Yl2G4okVb3&7i5-~ zSJ!`>D5tot|8K=G?)o41@AoC*opkVj3Yt0HGrTcd{iA!XGU2zZ4=oon#Gr}>SYdz_ z=i&~CgIY=C(ifS2MlC9al{KJxWWsk_;GhA$lcAW|sL*6MgtRSBx4g2K4W2D9Lsyv` z_JjDLq^xAa+K+*XjECw=f@|<_LBWFqhyq#48n&-w@p1-VbYQOaGttw82$53IvsSs3 zCDYCMzl(>NC!^wDsu#9 z3n$yHtAf+iG*|bK_ZwPZ1+EMw%M4j%(~KEFedcr!JwrIx7t4Xd;p;UNIe9!3iPUzD zE1`NX;Yoagw_40#h+0;+l$@z+2-MGLdR{4;D1_QGzFXD_0#gBUffUw1HPtq(00)?> zT>=c`wOSNciO4Oo)W{ZLYQUOTb{w;EW7qWupkPbBf?+$tXK zdtlJ6zO1-f0NwCn6GGb-MwDjY4ZkV|@MXgSuB)dT@=WP;iQA z+RKrfAOIv1umU1X_?Y!q0^85o8nM0-I1$9+=Ak8gj2=gqlU`xe)j>XI<0y>t^1xD^ z$kIx-Wh@Y(<6Co>hJan4*gC3VSk-AZRP2Y`#D+oAKnY1VPOy!h0b?R*K;&EHng=uzh^4Pd7%sS_$gfsK!PEVztZ9TTzwN>0`Di%$F9WT;a~tW!o*6NQe=H`ZS2vT?DBYZ8J!eVzY3yr2BSu zHCz)^*Me~6hhiYw#kwMIMqvx$rO*VuVp(O7KFD^-2vZ%#!$wZ7^)ss^?Pu%78&e~3 zHH@)qQ?7!S!YZU`xUK;+f_boV6R?5}vw#{z(*qev&47YFgw*F1T|ozs1dbE=Kz`Bm zf_gW4Kdr7_#ekuO4Gq*DmS!&p2E~N=A^<=V@!2&r3nwkoNX^3y?7sdY)pz~+k-PU$yP{rr z+y2BC|8#2jcN2+QYVq$TEjnO*dONja)h~CLp5ASTYJX3`zsYhOdXwoNP0XxA?B^4k zu^o_;xOn%sK409P*jcN*UL~g*GrH%XjRdCg;?CZ|-T`WVJ)13fy!%r-DUG@ndv@ri zRNYw8wceklc88zc-e~FAl28=bWpl~Pr%lr>ulP=RL0j@F>_UlOD3{U&A+4qt`x3o( zQ9FZDpqJuVF(Z@c(wCqvQ@fE0_PxCsYG;r~HxK<&32L_wrI(intPfFpU;>6?K-`N- z$SY2MNdbIHsgRNQis?!Dbn1$*pqpk|6(QcZi@pLRfIGZDvYFhCQM4^R|Q zl;_~QhNxZmVN?0+$P_vj(^d7ap37R_0RA6 z!M|kp-b(j&Lw^nZk()F1^mLMXZvWQ3`=0&ov3s7GI3<4aiS0jr=(YdsdG_1$k32Z> z+u}$e9!?v`9TEj>`z? zOh({R?NU!lNXuMOGvDz(jI2hHVQtpclQU$aw5-s>_`8b=oY3oWnsF#lfty! zHp@=p)tCSMdmrALxUF?zD!kf9y}qXx*ISO4G{F}oY9F}{&O-LN`oi2u9IrCV<9%D@$RZ5_Ct$HOud(^>HwE?Tk~#f{T{N`jw|Cf@Z)Y}bNls|ZA0w^#zrFUAANF)x^P93Y-_glpr0o_o zbrPR@@e3zDv@6lux;0OApBZ%v)3;M$Dx`Tf)1ok~S)Q?7VM`-QLmAiMvyV$Y%4CFr|#=}lRe-qOh%St9$Z}2A ze-)A$DJ|b@>%V#yNVRDD-li=8i9X)>`i}zf{}kI@|8XluEB!}n1#NUO&>Ppk44=FD z--^+x{x`B1XxsXauhTzdpYHm9TQj=rf4;Lvr~Xf@W1WkE-dO)f{6EEY_kY-u(W(A7 zax<{4{_FRD;yLIEyZYaX(Y^oo&K{lm|3+>G-f;ZqWGU5+|64LT*Z=x&2Da0Gf8O}fO#c=x2fLtGHn!_mb&&Yq zLjOFUs^9;Q6}tPsY{|IFkp14mg@&Ww_LBES$*$zna27*z_<~XOm$S3>%%HNkWG+1@ zE{@99)PnBKI_B)@nRA>f3hvlxr>riVQx}9qr+D0&5l$RC&!1ViBD(sNH8?X`wCqJy zUYu-d4wO&lp?FJD_t6tj@|0{>r*U0gw?tml@25Ror;EPtcteAO z1;a0vb4k@M4Wh*in2J>(pD4Ke)YRPg5It;FXh-pjbWS(zWm;7%_(Ur?&o;}xP9M~h zg(S@kE-CI{siG|Fo?X(TeuQ~|wq3yF>i8>xC7t$d+AjimfT1` z0mASA3-jKiQzypUidrzX$S9+d97Plvk(&~~2aWq4$ClCIf9xId5*p0X5>6M%vG>!CpCB?nAS13RN} zD-CkNT&yKJXIP3`p&Zv=8Z1mwEtVa6v23UdW`&rXy=WP1!uAAf^I=M>P3r47*qJG`k!KSHb3k2%})$p;sy z28R@_pu1WQ&>X6{>|l*=12xTe2dgIsATD@5?buG)ga~Ss98)jpmQVEg0EMPIKs#j! z9R)l52B9`^n?qH84wgOLqv4xTu<2zNRI9tu)i}-YqpO4Lz|QD`s)mQ)!YZ0v*#M{Y zl>#trhu;R^s~3YjKuL@Xdch7MTJXGvL?hH|Gg5>4P;5DktY`&LW|2sbz_eh6%s)cZLINSk1C*A_ zhE|TA8`~ta$`9hukKphHK}milce9UC@0c@%c5G(;Oq9M>sm^m<_ z8c0hqX)=*8C5H^qaWJ07lp3bPW3yAINYbXs1~!Hj1`RsgdX0{M$O6gRC&9&r(~#VC zU!hSf(XMYhj`8AOkvbrICA*Un<;#M`daZ;G7 zL&Z6~Q&m}X%b;FSt8OI_Zcgf0RvBK97lWxr+|^eFLy_%MTGjn-G!2- z-2^tkICTl^6_sX)G}1u)suM3>vm;K-R#(rnMn@y=j4A5>+k4XHw3RLA>*H6bNYz|>p26%(-el^5u^nvV4ZNmOl#m3- zfJBgFOj4PeA2Rdj=9kP_y0x*`dGXDCx5lcvH%96{y`HttInC;ZLbep;w@;sc17_u* zYy{$p4I2t?__Jpy`&>C#Ao*`eD1$o~q&$sxqH<(oMe6QrY`;k`wW)UO?A+$1;1}omkh_yQ#a5CzvE4r!V?AA^%rcO z!Mfcem0r@TMFHCap3vz{Lo6OMNmY-bCT6E^#7Z5@Fw{ zmSKBNm`|Xl-mneSSzIB&@b=#N*y)`A>y6QC(i+L1+T)vV~cL+3)9tw?J0AW zd6Y_X3fmk+eUQOqms}v_G#kDGJyAzMK0)dS7zhA5141vXDg2lzXKjTp1fvdTQ1Y|r zx1r;U_E2ix|E_%V=!24KTi>DFH<*i4Z_>1SwrA<*NOeQ6LHLTjKgHRatK%I7B+5Y8 zq4ODJQOH7@*}ISYy~oFu+%H}#DM!3 z+XHLI`L+>wBW&IS%PZwsCeRr{;F=92cPev(UB~O;C6ztHpWEMNs4C*(ts)FNB(Dnr z31hw|cqu5NZKzGOv4H-%TpQXPk3qDCZjq58O+yiVAimq>PU3K~&kP4eEYm<{H!vSz z{sjGw4hy=vVq}LzjDU2W*w7=!5~{t;II&^i04+N7cd^0$!$apA*u*G4C`BCnM_{jG zo5jVsYLZ3=19qSA1=<7&Hg-ezX6x1r_wY^a^0aw+_#QYo7E=YY7idHHlFc~4>c(T> zZVrkArX{gNNaX-#Ft&RzVMxZ6`3w+55jRopDD$DI4Ov`KL>LxcL5-^-#UQ-l6%}iRZqcT7z*l^! zHg7z9Hi2MP9|OWKLtyA`Zerl5pa{K3T~c^7W9FKDR5A?4OyJZYcaZ#{(XFzy<#5v5 zf`#MsweadslIKh!BEA8eT0(UU|0P2;!wU4g-yEsM`&NmxG&LHL{-Dr6clV)@P>p;N zS6RD@9f1@0k-RM&pI{1Y1m)O7O;40w}^_=>5HPxBd0F1jG@@U|B+6im#_v(kxZ zvr<;tyxjAp2rmQF!j67V_0LSX`F&a-y9!bEx*rG0%q`Kg8`xu zOJ1>|fV$LIz8W(c?$ox>v`MCRZDjZRk|S&{Z8g%6NSWg+m$7*v_@M2;ml%6S9}mn) zza!=&?zJZ*v#ppxF~NGEJDl0BJ2tvP)MBwJGg&QIsS+riQNSjfstY_!jLAp*u{&|_ z+Gr}!B?uo#<3YfeBv-g%p}4#w%~r^60*Jegfs2s9v~+Z{GK$REoD|$PLXwH%mZ8Cy z#}&|gM1x5MK?YB6$>t2}kb*r*2lIHErjfPYcnTp*8wn9!T~3X0cW6`MNdsul?sx$l zQ=N~QdNy4sbc7Y2mOPDAShZMZWLvm{2em>iV9W=h3E#{pW2aE^b<+_`jDmMq z6Q{<^{`%qI1{BsnP==9uc5yUeGPaJ0((Wd8Q_@jEakdESu=ySy$2yKVWjTdMMq}Mh zh|# z5?YwQrxQc8rVQ0l1UqtwdxVammwD&4$(CuOwy&+Yg8ufCWQC8_8Ylt6B2J z97ZWlFxOZHDXFC@_@p?Yk+vm)^F@JMCuC0{7Y4k*Iv^^rMck)&?Q}x82$2m_)ig}V z#{vr=QM6rl!eQe;wpEXQgf&c%>JGZ2!#dlCVynI*8)D8NTR|gJF#=$l6?nfgQL%Eq zT*y|KmbJw=h`y>Yp>!s#vy_9UHPQayF%JyDP-mb&&$emUq3;O-5ztF9c@3M;Xl6|8 zM?74mL$@ekfAfn@2$R@*-tOCyy4g(NfE1XhBp}o&VkV*&Q5RCpmf*7;LPP%o`i6oZ zqM=;2zUP8Kmrfx5r$qe}Od9;1;ts8_F$R1EO%I6bL4$#|Lc2nJ3YA8)2$mEk5u1$R zA)*S~<{K{>ui1CGhO2b;<<9g_ZCl#iFagMeSkn`Sc}?E{>HzD(4j4MC&<2PO^kEC# z^3ipR#DK_VAY19}?d^Nz%Azf!Gw1nHTS>88EwOb2JMND$^ExD{O()gpV6<8P`6-%2 z2ifRZ^cnXlwMc$OGj(d}=(%LuF370r)Dfqt#1+w>2{|76E1?fX-(Y=vhnOL7Mpwvo z;<$aH;%BsP$!H_S8fGNOQw&wdg_nQ?oatC4Zz!Ng2oYsy_MJ*Am(rbuTyG>GVJMON z5s?n<(g=;z;b?#S-k@DP7`w^Xslpxyg$!j?CNktf_D&h1V*?;7%k&Iz>jbDb1-E=O z$ae4_N=CRP(u5JM8>-L&70CeEYjhrq7#taS&^I;8P=^do8g)c}L0@AbDTLd>`ILih zC?GMUe2HP3U0w*3uz!-PnLOf`;1_h>9GxSk<1+&k6$7XX>3&oI{UQRV0e_=Rq5o;6 zHg;^nN{2^`XK->bxEh*069N?KZSRD=59byLKo9LW;`lUF-LbuyX7C;(DIbM$VU}gN zFUa01B~ekAg)($*-J@KwO1p8KLT4MDo%v9G!IDzc7X~)Z@qkM%*n1U4j@)iuPL^l& zxc6kCRkr>!2QADEW8`c{I|YRovO9g#QZ3CSpi|FcRcOl@tM~`6(!_Ln25c46o~09b zP$L(WgaPiQm`Efw;swrIs6e2xWJ{G{W)jm|C_{7@g#%2G>J0l4xs1h((ZFS7l?4f5 z1ivUiBUhiPvqi`Sm$haeuYBCshMqNoDHoj5k;ffpZ3R&dC7&&KF-3fbdD?X+Q=-^6 zh(yBpMZ{=FVLv-4gub47sA)V>MjuV4Bh0*ARuwT`E1kfG!ZOxR6KwPbT}7?;LI#aj zAlT@0$n+XFwBM$PaT6!%@5#|FyR9T2Gf7_}*;Z0)9Wn;0wjl3CLGU8JoK!c5b+bwG z8|<^50{i|k<2QtB+cR7evq-NeOGr>Rhjr1*cWk(*>*xl#UlEWU@@<;{-`Cj^764HG zRrv2RIN90<8p-SM)ji(>ZL?YNr z$P#lVcC$rp@~G~i$qdbWLv&C>nj;K8ER0RWJ{2>zqu|}4B$?UXV2GVj$B5($mWXhI zfxgQD1v4Z#3r$hTCm*fzwml*P9@#TVl_nFSf!(nKX^jtK1h(_06a#&*#nGVrjQj<; zgJoMOHWs=O;cco~rlxoxu@E;@$y-YZhGg{!8p6Y-xf&ca5#jr$+a5@4UHs9dE(g&;geU?Gn0*r?(%DWxFlg!-%8oqJ^ZUA7lhmn48{Syie zsB0r!ReM0zZxsb^m;2AaPlIa3ThuUQ|(UFhg^O|$=uJ|uR0-HL6hSQHZZoIVrrnr zQzQe)9yfHHDjE#A5J!wE@5E7UIP{0m34J|;c>F{tO_0(s0^Z0RN1-wT;ejyX+2vVlkt60%@J-4d_2|r9Kd-*N~)|ptjFEUu^unHk}!5M(jPq5`N(4pd%Wv z5$u#*r>h zuKcn6gDMj%|FJzpy(cd+8r>v8G` z1>wL8P9UK~GDvv6Z~_S~C$dN=$wkvX$W<4o3<uYp?2+#5$D$^8lDgr$))PR^tpHFcwZcvk6f?^; zU1%){zvf2I0ilq8IELn-XLFaFb~TsZ>d=-scJRmdon&w)AwtJe^{>O(A5{zYLsx{x!`6l7 zEDUOa&4kBA-IZlv4CqVWrRaSa2RYo&=qGP~n8~rJbvMr@?Ad9qSQ=&H^I6+1XNFq) zDCazl%rDj3YU%d+|%{^*owt9f|Z zZJjmtyN%}M{$2;>6!GPYhsI5s37q4;L3QK`;5-ae)D%JSfDc--t|IL3l~RrG5;|6QtB;^u1>Pkhr+$HxSQTT z-FWT!Q}g1wY@3DK#lhubc>YwW8?({fyzt~a-oVlwI=i*HcLCDT=kIS?+dt8>ivLIa zo?oGjXZSyUjNkv4$-mwI^h=&^iN7$_LeGFwIom6j3`5W7s#T++7t5J)sREkQUr0qn z1@Y78KaFbh_PpR(iT~5->m~pDm*?<5TLP?Ky8kKvmjC;gJil-Lzt?@%B*c?XC?}pg zblC8`d%f%^e*eVb7AOp4ga-i(J@7RnmiUOHeq~M?HoEtNY(8`jkEdB7A6%st{)suu z41h|ZffK{v6AIZZW!S@`(X~g0mHiv&L4cL? zBZp4c3^oO$Nr}-&H+0{#*-xnifS*XJxMik|G;~TEvKt2;B%&`i zbteR#z{Ft-AUle5WFbUxzslL54tqiZIPLD|cd5+>kKWx$H4 zi;kVHF<8(EBn>H@SkW~)LQf`^dl&l0406o z*r!M2YykXa*D4q`;<|7KnIh#Pk|^M*Gv4Y3dO8#EAmBQ!G=r#dB=G1>V@vcP0**g* z^b48z`PImY1jkPo>tKoq9;n#k>--UJc`BPB+&iMe3s z2cC_j#QlFuMmy+)_gK6eK5T-DPRn?7Z3~9x`{N+X0id3x3FhZ#lntD;w=mz1i`{`a z7}{ffTX>M~#D+l_<2x;fLly%6AND*EqYO5@=K9-KuHxp6K-?CHC%#Gfu1Xm`9S87) z7kd=N!w&xra~Cd40Y`+Tp_hKpkBpBbpP>Cm%J~vTFx>dC%MAV^qlrM~Q@+tVOrrHY z{S8oiX7)VSI5rmFF-AcwGl_>zc*W+pLqncCempy(o@hoA4BssU*M9#=MJF0`yZI!| z(rJePW5zD|2IkkCV(dclGkde71W=Lw?3IPPcN>Jyj)DHtbj8Vw^f)LXlyIqZp>PV`6^v9e>HxRlZO-dtu)sBsL5y!if(l?a&GJ z%%>8n%tjXehzIwxtcVbBkx*~Rmasdp`eQie3?V{!i2e~k7 z3iUCZYB8M%B`1mIUCHLNW$6$HG{p)B-Gm_resVIW7-fcw_{qVS6uwPGeb(@dOT^h- z8mcaQnj_Fd%n+mT(8pc+^pgZHg?EbUO5x{J5X+vG&~Gs9*9*W$(u1vlPv1igNcb>C zbz5K5DOz<6d^tNpUNk7B7qvk_uA&8;Dg2OHk=ToO-xZ}f+&jB$hc^)YUfO-imPm@o z3Bpa%^vJ^yb(fjxjJAE6pW>n^%AOkRrdP(LcN=m2(gwQds(+{mFylUKz<1fpAI1As zc)0@BTKs%p$y8XkKNZ2a5j+%EL*U;ewh~!qB}dALz^S~MP$ERj=|re7Gy=@zMNRne zz|X>$B>}kjQ$z%~lnQY*Et!e0#F(QgsQn-knI%Rw$0V}LI>H(DtluA_E)iNiIor`y z11$x4r7gaAPfBiw2Kv_orSWE1uflLIw8V$nfdpGTWsWq+I{$Utu;Md)w8$#^J z?w5S2nyLOo*y7sZzFWT>)X5v8_u}<<_q#1eYHsvsNiZ8IbZPy{V98a>A~R9Ypvd}7 zDnd|Xhm{1*dgm@%KTI~P0YCqNHRj&@=sIVA?K-c`4)IIZIg&FXh#_ZlcaTPj=1-=S zz|gx0RYtW8MU++f9;9gxb1sQA5#gJ3C=~#x9}AIfLYis>-Cs6Vp(RjctQiUu4ClZ| z`9akZNMNRxhIuF8S3wM#Z;lS~Lmwr7q1uYcpq zYqasq`G299$;HqA%bBmSe5(tET+rDNe-PIV`Hq?jI?7TF84legv$+$5ZV>(Sf5HpOpoAJE^#wYU$y7@s zenWg7sPr+F4PImCyQb}`T>?%%s7d%y67$$FC{~D zsZ2RniMSN6?7qlv743-c3lQ#!h^6VGvnhF6B_yX#3cuZ?c=I_5j8kGDsPBG&3}7?m zfWa;#{Wrvmf{8~T*hmke3*!$4jkoA4JySJ2?4VUC1`C37|AcYk(%V!?mX|($HM*M3 ziD+nYcy7YQ5CGqI$0g;UpE(;F<$J0%dTxtQLQo-p6NJ!G3B!IjR)!?*_!{-pF{Y2$utu*l*&4{3(MIA8iLR4# zyCS{Yp zMaG@*;?p5pK+@?Q$liu@42?jTnZQxPwPpI%F1f0QH_+O_#fIjib)+SbocTmj5W!7b z6+Hn!j&^~{sx%VN)s~_|!X3b*0Wty3tUEI>v9zeS94iv8XIseWR#q%*s))LeK2zru z4e}huz)W^Ab>_N3if^AjFVzepSNsM=^g{@Llb9vPv_k{&*$J<`=i-W@;w45Hs~?JO z(KHX#8O%M`4dQs#77z5j=Ku?jkJZJ3QOZ0vt40~R#SinYb@>!|c}uSnA42b9rD1I- zz#?24*NaqPpUy?=fE)(fIJ}(r3R9l0rwkmv6(e7vV6GUMTPAd?c;8FHy_Ug5;=fk3 zgZ+{*VdB2sWhh8z{5Y}DZi|%gW5?DNSdJ%KSJIC$!-Mbm*Y7Jv84g2RJxGoxQ`W?$ zt(+D=TuoUMuePpMB!q1ZU3$^5Rz|snNquC_mg3%ih9e88DG$WII9b6+KILaZ`Jw>haeZ;= z7D?=K1YbnPq(aZd`~^Ia1{sx~f>6LX8I1-8zJ!#9BL{zMuPuiYZrE)<6k_-?{11W< zSNB^6Ca(M{0ASaa;uTjEkMFwGU0S2rtO60=4{;e&y!J67zJZX_2H}#5A1@g%B*G_G zFq0shGR{c8uibg!kjvQS`uzehH)|wOdBlDU%ObuIB{NY915ijE&<*lKic46wYb=SD z3}Q)Qqxx|h5q(1rCBDa|D~7cjY2!0gF<7jy8cR2S$gYu>XkY zxacsm62=$Lo_P~y_xXHWorsuTq;o45E^ZPml8=UKcVjhHfM2PEQ97ouSOfeCd8)bckfeq7uPRoW^lG4WFB8efI*%pRM)TortW{bHs3+GQ(V0cQB8iW?z z=L|n|Po2!0I5#cbo(sGRcZnoRE{fd>%00Is@nDavx(^_sM{KVp#F(%}kQBH6jKib4 zq12UPikBMNSeu)DPM!{S95%E@xkOdLpQB}sPbgZ?&9v{f?wjbdm29C9n+2p&L84G7 z1znGQ2E_`!OyFBN^d+Qj2L)){QIm!qN1>&e7}MR5c&$ixYR}{LO8y+k`BY?`HojVy zU$zvSHnXRuTW@umg?3gm zPxg);w8`~QKfE3_A8fPrP+PRxnR#oGnV+_6Ppyu7uY`J={IPe}m(%wRx*i z8(d#sHkyZ-D*X0Z4ehDbxGS7?YEMmbZrH2-<=xW|c%`WyI%BB7QwB-l8Q+1EJwe;}om%E3r2mL|cYUb~6>*+x+Rmy&xnpe}= zmlG{BXpI;8dBJLwEBB{I3-hQnxH@c&9xETsMy_&sGOf<`bG^GNsHfA~Ve#~^q@Nfc zZ|^^zf63pU<=czScv!!^zdxzfI_FmYY*wuwbSB=@S*>zAXjFR_cSG;4HLZL-Kd!c% z)V*1I8k|>(7dKyK)$?4r^ks14>9@5nNA;slYT7u`Di_zer<$2R=zKjmG_3MaJ<-ud_`nqxYczb+#keZcmCm$c1hqa0MU{22->c``Pp^mbRdZAe;PICRb%H(>G z&UqgfR_DmPY0mqdtGns=w0Eoz{^;HK_WbH+J^k zw$kp=psltlrM&CyRUUGe6}5LbK7LRiAFr)NZd|RYt>e?hop!u;u)jAq%!1vYpMn_F zOg(s7Njtrm51#P2Zu&I3DRu{)$>p^MtYb2oem(FCR zo9n&fFO$Xf{$;J+aJ`9fmvW!(^7qwx!TmbAydPdW!*)g=I-R4d{-S@h$Tkb-8M`~t zuWwK0M@3g1?4O+s&E~`6I$vrWdhTPUd0VSw52sfHbN|fQKT~Vxj&|C)9ToNq?p5mX zx>GF~<%PblPl|)K{jpTAYDXF4%h6-AHhJg{hlZu+F3m~)vT{;e^bU^m-NuRC{g|8H z9387xbFbYm>}QY5x1+(xK5u)DTId{4S_}RDYI1u!xUJvJn;9r&+z;;6=H*>_ytrIc pQ_i%1RnHx|TH(0uPMQ~g^u~XC-k!JT?fHNH{2yOcrB(n=0sy~_8Lj{T literal 36558 zcmV)BK*PTuiwFP!000001MFN2coS8=@1%u>ft4Crw_9Y5kyV5?op+M1d=i7UZd*E1=-xipuAeRdn6U+lxho6)TH+T@_`$An0`!6jr#pey)ow zdb#J!OwyzYNr6)3Gw1uD$vOWy|Nr?vf9FhQWJyv>?TQd!L!r`~OVcpW92lnk#ghMO zpK%JqD1sqzg2=&e0%MpQD}9ONNoZk3Wo4^1M+S;WN0({*GHr6a{W(@;FM$)Bm;Gtb zkCU(~YyWO&$@T~OP`&93jDHf?pQ7<>{C7)BV}H#sxLuU|7s&(8!%);Y z>`xLjNcM^GPeXUHVqLPr4DCm5|KW%JcpqXx5aTQSi=ci!$SZ;}Lh>HFexA+v=2nFO zZ!5DA7=f2ycnRUC#mO=pE29WIK{*L0P0X|v+q`wG5OfP1pj3H96@q@yDFg*oU`2Nw zFZks7%_P$M){hT7~_1ixDp0s_>j zBic2WcY7s8b%%IalUoxT3_@Zcir{O}$D<;a*=Sd)afSDW0H+2#PPMGpD}{q9T;e?2 zFt}PUSPIAkl46JA+atJ#S6SR%&MN$HofnCMbl_&|j4$|2g} zk^}Wl&QCfT)fT5X*XMIO!Ig$)ZDql*D8>YU_Vn;T^)^j%zA>yD9DJP*RSrd&8&#?;$v5n(>Y*>U!h#yhqFt1G@vVfhgg$rMrR}zBy z9Kc)eO+n4qbTU~0832;NpjBC*e;==TY+3tG>VzWVIE4(`-OCd=C4lVOdtjy`ucq(cs2s275aw-LRlc3gdGTY>aR!p)p zSfo27Nn)b3dXJ_Uju&}9%mMD$L_*LfDY_4ZWRQuZIC1olm%=L4AqR4!A)i4X%P4N( z<>5eB1ZjbDL&kyv6G#$S9ndXsZZAl!=a|SFmSrB8D`B`@YFPYWj*geQ{bEG~Y0Aw< zcs=0fbV#l3pS2-SCxDSPU4f5owOMy$TS+X4SoK^oP2IlxO0 zVdTQp)~;tbyR4;T;5JE47A*-eiX^9vQh=Nt1jQvrn8INJ-vFqW3NQNHhFOdmo>u@Om*XMsf`A!Cef`FdmlS2?q-n>UB7IdKjqicHChHhASf&MlYoRNPw_x2Pn{l ze6tGh2{4CS(wxqSk09s(eyD0;my*V)KUz>})kW}wWEzVx4K0X**PULQvGUtdpTi?^ z{g6<3{>dH^^qhCPU=+lSbeXqxlOpibyt zv?+lSST!u`@Q9o?Jv5`9uNXepGoE0^)VL;i9p0J=zH#10vTAB+&{4s8=lWdLWQ|fW zcf=S{p3VnH4|m~>9^Z^fW4t&{Rt~S8Ia;aoH7nEW@p`&+W<#xi=um*Sv|J=bw8ci# zo1TDyy)b?}j0)q`=6BFB#p9a zr-*dy1Cw{`(gil8N|aWwM5^K8THr!N=o6zA36w%Ih39~|!XU6f*hB;aq`*>_>}2!f z4GmeiJ4Q~7n^rQ7@_BB~?c@OiKc=k2ab$wN4tN@wMCO;kDgb)qc-{S(R7Cm?QrlUz z@GQ)242k13q3bWYJbkC4p(nWiP26d~TEH1wQGgmjWo*)Oh0TBhIss%68$CzRg2AA+ z1+E7$CVmggz(iq4;P%0NBV0ZwfwIGE40JUlO`7T&okbe_0_W=hAt8>6Ez+on2EWWv z3;*%2V}F%4{;}xQEAHrD@nr93H!ggDD?}|9b#)%)W3G^!SqD8yWg0sgl%|lJ*-j@9637E-}Gq|_;oj?C+QO|-^tF}dm z?^%y!-!uQwNX-SPeLCW?9@(;|e9gDl^n3WsKVE%EdT!v2n}#3d9=Wgji3c9)-(0g} zN_|F(5YqeTFD-`=q-VVGEUd>X)bL6O`iSlt&*fT5EhT6{M={gLShO@3eFQIH&P2tf>CDKYkLj^>ar!Zrj5HsE(LM2n~}J|{JoY~V%F>7_wZkQ-ID5V5$>o{ENa zVwVQUIudIVBZ|){igLJF4TT%Hh|+?A*&4zDr=N6sosHnqtI?i14z-{JM!OtZ{wqY# z5oo@#5xc9{Ii*jjsNYb`{U%^5C&ERmlkOOPN-9GZA$J;)N~Oj&}suq3sPP<{;{T81tIDt1eP1@)#PKh` zJhPptGudv;{X>@*{p44xH|3VT{3*Gujr^?O(c@PM3?ssZ809BApK0PU9HP5R?ORP!#UK zDB77a+jYVS^$~_vNWa|ZVO#&xfe3R^wEc|Oa$}5nf56=C zN@CunyqnQ{;|RaIS3NIb)p5*8CyCoJs^gx!OPRN{FZ-q#=K+v2W>4bWrL6P(k1qxg zqIVhyK>-Ny(WPxFX9R|a;%F8DsqUZ4-pY1+~95CsR&Dk)Jw50 z;|4_gM7WU}wciiSpEGFp!+o&LFXfi?Z?DV+AiHXMw`is-M9Ln@2r4?a!jzz*b87;Z z_KRhGGagIuWoaQrXXoy)eBB!?dC&;}<184yI512*ofwk_3^TaHg*hpw%YkPC!;Ax` z7(3>`X`G>Of*=VR$4LiunSkNW8=&eBm#@`Pn1KURZW)Qe)|!>uwDpQ@-xqg7rWw>A^6SJy5%73_&^x%#{X1I0@3} zaJZZd;mm{~T=1a6&XA-7cRC4*VrYyY9Mt77ddbYsPW#{d{n2M`-M;39$DbP-+OoIjim}{){!>2x z=Gno$%||p0vE|h-M`t0#WeFjAbmlzm&70m?JMeVTiK83NU{C$mgYVpZ3t|pSLw1h+ zo4m1L_ge!((Wk9`04>e)f8&OaA2YIYa&3v83oe`oy!zbF|G`0~!}FgE37`MYKL2;= z+YYRDq%8+QibOubi=4+^-lFnNg2Gow0r(>`keW?7xkz5lldE4b_sl^|NUkX_^R(G^ znY1+VUp-+|*YL;`|1{Mx{%MSHWaGa(+R(&i9m@u-grnFBpYpX1no?VFleGg0YCQEz z+HnRaD3?`~{KG`v54IuJk!`Kx!-0{4$Xh43wZgxXg}JY8MET?}i z*FKlSp9ov4__kI6zba)}lC2}!T1S9=Nr*QHtJ_+uVREugYHOX$Hv$IM+P2nOA;4FP zY)Ij`c8LfABXP{id4>UK8nnXy0EkN%cM*)$cpi5cbag26tT|9ztQ`LJ!mn{xP%eg~ z;EeTbPypEw(i7HEfIN}NNyON4Qjmutf~^EeIUNB7&1{G7tEG+qimEQ*k+J?Kz5jv6 z>1_OWOG{(_iYYZUmE&tKo<~Oe6G`@`X)dBj$`L@{zKzV z9CKwj|A9oLBh~p2fjRNZ?EEJ&{=4D`==|{?%@Eo6@0OO{{#|nfl+pf4=Rd&w+4p~T zOUs`B{J2|k{CgF96DxM*Yrvsnb^iVD+WVhzc>gbZ{&VTuIqeVrbrlaS|DV(TI7JhV zxc5Kf(EbiQTmQSItvOx^?QB8&nD=WxPJ93B+rL39CR@%eYi5^&5i1&f4s_N2t)~!6 zLD3bc*_>DK#I}`hOVEz zbxel80Nfj+zVqlxK)oHYY(vn^NYMraeHt-a!Nl#q${O5duf-r@&$NDf$5K<-uxV=t z|K`1Z%!a++%KKhg^2Hv{8;||sdiBWN_Z+D@+;4x&+0Qjzge^W%mDEtp~tADBbVmnAdkdWvt`G!-iDvc_*ZlcHd%6rj6W?a%ScgfJ-B}7uf415CY~x&oa;(nd+FL0^ry3`hR*GQ zRBt@?RYB?4j1)E2yhW>b&VPT0PPZlZWqsKHK+>hAmH;rCUF}fA1ZQ8<$^Evwh*Oww(xHSKRwG_uBPaeG4nzpY`Gf(}b#x z1JRaM<3@so4T>#n&9;vZn=FOs)j$oFcs1xRAFMuk?41Nf9DMVW!%2!TT@pp;51gMv z5g+Uy_Iu@>HP3Mq#UuHP2ld|{x?=l`tE&pWoAli%dU@>($7}q=t&h%Iu*tD`?Cg={ zM+e;Wvp$hiFWmgE#Z7~sI{j(>|Fd^3;83Oi-(1j6wWd*s)G=MOD&{_8QW05|)S|mf zb44y=%?wIyDAiVqBwZAx=pt!}Y${zvDM=+MDoMyCv?=jFGlPF;hR*KO)Naquc^=Qh zc+dNO@1OU~_q^Y){=-Je-eznMV-@=v8<4nR7)?+R8a;xrluDsmr(RNNY-rEm9UYrK zB5`Ouasc9Ep5}XqM6c(bJdBb`6#0on?RWt;(xS3SmM6-(;;HN?QAEbNMr2Ps4Q@S_ zgu)^LMCarJVVA+m##P>k-G-7HEK)I^dY1Z$yW**Aba7K0I9ef|BIV+#a%u#Sx>rrl z+Y^Ffn*X%d#gI}N{ilk*W{N>wK!%D=)PWGdu00V^R8nM~MAmY750LVP8FcuHu{gxq zI!E6Cl{4mTr$)`Yooj{P{A1ir=glfA$mkw!Hs^oc2x7l-W*ekBq`cHQC$I4 zHahuUD>zyKNt9c$L$=iQcTwr6z5-}DYcsjXEO0cl)9dy5^uVl0x|211#g&zBYePDs zoyHtn)p`mTmRf6ZaPI9F_YWS5*v(iQ>T-DUlzUa>Q#($~(omaWnhG*zh#5HGiFCF0 zgMT6v!d?%M96O`Q1BVy(48Pu(jZnmquOSB6S~i4 zN{oL)OWocbg>Grv59eD~VFA{)^7o>M#q+Ku+_OLq!&y=Px|Ecg+%|N**?^0iZuoKrgeyIRixW;8 z;nESfQwU57LiacVb3}q5C^-aC&cRwz_o7=$w~t_&w;^mx%&P*;Q?0As`wm{xyvmm_ zcS&(jz?!U@nfCy3q-BPyk2Nah+-k_<_Ph%tnbA3GgdMJ8c_ZyF}Y`>l)jK zo7^g!7@jEWxc$+OcTYWbI5?3B7)E3vpXQIa_{YWM$<%u12YLpx*%MZYYXw!OOy0c{ zlzuDxfU5-a74hQ~5|e_&Y(rqSATT4kE8$COaeUen!hz?*#d%@=S*4GESg%BP5Jpvc z?hS_`5(v0On0Xj$%qW=J{J7B=1LXVX?<1D$6fHIoCIp{I$f@}=R(*fS{L~ck+8bW0 zLTW*e2Tcy4gTSG&IeP}_nwJ!0ZU2QD99w#Ir&dg4UFQa!oL_35(*&`9%uB*h_Grhlh;)3rs%YR8`)mK(Vy<@r^6?6@kYyus7WWQdE@Rhp@O7I8mu4*VBKPZ{FE z1qbZMy9tmm7JR7Ks+TY(1zg?ON6W#%w|fR>$3L*bT|nTn5tu9lDFcB?li;l~ivo17 zR92ifwJ)4`^5|#R#xXl%9Ak9OW)C0u|=p=`%rw(?Ry zeibQ5k2Uro1$-vH0lo6gC=V)%C78FFos?Shko>H9gIVh9rV5;mr&hd?I=*;`?$D2k z!9V|Wu_g9Mj&Ue6j^cH1)mD#ovfAqz`Yv5)D_bmfYlEE>ZBYtn+fnr5co*8r#ugqv zH&2STC}*Rczd?jqlKFDJRG8@A&^9dfp-mUsR?AGPGIeeb+P-Ulbq|F_1Bie(h=LjmPd(mArKycwR&(fKNBEnFePzY# zmp50ZO&@r0$Q1Aq7`eTNm%4(+#kf#aTqhdSjy7sTg92zl<8GiaTTt@HYCp9aC2l8x z*1}ASH6+pTW*v{2Waoiv=4*sbBWi0!olP%zt-~DH_TPC}gR3<0cdAuCDcc z-?GSaMcj;CmKwEgM-#Y(YE*>C;Ob!Uj>w3vU?*FwxH62b5bS!8BUSH597GC7k~Xpx zk>hJfp|CD)Szl6!3R!<&|FrcVO?M4$RxjbKjLb>?0r&K1{9h`9a}~I{XN$LDA22dmJMsZFz2-wybtv{7wN(=gL66<#Zb+g=R`JrSK_i zI)%bxQ|Sx_jY6gJ*%UI5M`BZ1JOY)O6C=BpE5{1P<5HqjE zP1cfYWrVV15~Ri?+GIT;Uj^ES2<>3WBz~`{n7@LoSL&-kd-GtVkmMkNB(x;=?%w!w z<7OnZy9*ezNK8V1YOp^w_-~{J!}I}cBLdn;2#nUG$I@u6oG)jw1!&!V%l=PU_OMOK z4q(uS^mmd3eFmRKU=eu~0)tCukT`5Qo5A4|=xn|zg-#;zsirh4g-c-5h+G=W6hsIz zkxk%HC>%1CMB%a-EClK3@R@t_RG>|JP~UM_=QiI8&zI|_A;Brq_nN?n(HY0nm+Si> zhf~Nk9ILoqJ{sr_Kui%lRz>3jyF{$`OLxcr|oDnP-W|5vR4MCm{O z|81`R`cMDc7o7hqqXHD1|0~viq7jMx_5Z)g^(FP62y{?ml>buwCnA|>N+I=K|A|N@ z5h=ufQvV4wMFN=sQ~yaah(_(L{u7ZvAbn@`pXB}j%PT;^;=f}3PZFWu|G&uvr+;Ns zfP&S(V*Mu?fz+@6Z*le4fBN6P6#XCk#mj>uZMCSR7l8lS`@bZ~`@fQMQT^}#euE2E z|4MiP__Oh!NTyOg-TzD9|D}VwwEp=2Ew0!%r6s!zdfxw?1^yr=3QatjzS2&MCO-By zM^o^63@t0XI(4@A?w-*+y#O_=S=tEph3FZX&np2HBvOkd7P*_uVFk|Nc?&Gv!8J93<@!zDh#R_Au|`=%EvvoEw3HMph(X@iq$ zNGEj+1gEw2@b(a)@N~IZY^K>Ioe`q*;T}znZ<%Q(i3#(ntS?B?u6%PQX zZ2*o-C_VFPpW24jdj&+}2)JcU&5xS*;wF-wn2Z#l3+>tN5sssJtXm?Jl{^VC^LT!e zFUioLrsO32woE)DB+bRRa<0ZS6gMbNe20Un(YSx}x=y{9!&c+-5?|4lyij6d#pAQY zULwiMBr|+iY%d-cE%Fodpwm_Cd*>f_WAeNSMH>!|RC_(X9pScheL%-nlXodkZ>kyA zI)e)9YdQdqGXRcQC@nW{lxb7a&koPaC)ST_eWKGo-n{n-%EF2E{JKGw~!6_{cyorQs(^KXzkDKAc3vua=7pIT`!T(CW>?Q|vDf ziVv_F&R9Ku_V1c3H}9=kCIYRb#i0CpTMd9?7J%aeO2_Xl`BU85ZysG96c+BhVPmr< zHZvn50LLDbh*)(_)_`rVh4wkD_}aSaE_;ytmn)Wb6!($*k4|EI zveoPw)NM;d0);`P)8uW3(}vKxqkARyh5LZSUH4bnn24s1G&^4ympDZ8yb!JP-c;tw zG8z|jcQKX`sUL**6|-GEc`IB+D|{uZEX8-Xkad<@Cn4eBf=8$H5_6tEM{(UI-K<$2 z9Dcubf99ywAwyfn&MEEk@m|*f-~s!hl}h4c3VzA2+cK#eAj6Gmczk?3ii@0{05$BVuH(z;(7>0ejaSGM2994{<~Y1 z%eq%<;R(hBg?80);rMmz8Y`WYB*PUa7FEY4k22J&a4A_iX3U=2+N$~6#?GhnK-t1A z1i%RefMW+rQ+91T|I*l!e5XM#jUTof?%HtcnYsArm4Uxz?s{9=a5iue7z=ulF#u;L z035SWGE|>TIG?vW*j790X@ma+qlS&8=nLK^mb2~(F9fgCU1>8J)Byk$jlf4N>_rI_ z7$rD_4>C%q8yLSwct?NuV{e}^T2+q%3HFznsUviE6PCGABpW`+N|NKqVjmCD3K1(% zx&#SkiKa?Rrv6|YiKdq{*>0!VGXLPi&=EeSs~p4_PGQACkp_M1t>M1 z+O8dUt*?4@#__Tj-c5Zo!KgydeP7AYBJ`ahz7Mg{KPiYdz(eHD^`J>j~uA4#Dw387L%T@G|x0rKWgmI##24Uh<6$Q z^aaEK+fp&o^kS+Q|=M&?qG!E8AoC} zB9@oe3fXO5LHJ+A0za|DnhC~avV1H8ja%gI#}m2>ytvXKRQX6E8RE|q30$G$dYMYj z)Nj4IQCwlQdm8uNbViv4+hb&Sio+N;5~2C{jv;FYlp`friItG+FOa+_CA)2O5MK7@ z-}b0OX4-*MH+wzJsEnMKdBk&K8&}UL{Lo{yb&hdw(t~!FEC4-9VHp5Um;fC0P$Gio zm+E{(+tofhxu+=2q$DQJ>cq8Bzw~9T*2($J3F$8+dm)?$n`2_(+9zx>XwVP>6@$0wZRM%iXv2yRao^H_dA;AvzckxG(>1@w-PcYEW?LzCUH zZv<88@5{y6m4@2bXREE>#yJ1F#d;AayI!UP;MfJ==!BBtEFQmo_e!Tq#T{-&q)zqQF;KJ>H#?Zpk!RLt9-Zl|Jb|oc&NAcZ|rwMHK}Cl zLn-?WeEbS?+ZX)-RiliM`Qb^jV6t1-Lo6lGpj6U7p z>;Czje|XJn<~i^8`#jG%&w0-IoH1}nS|(cnlU|_RV=ln$zXHpD*WGXup?fY=8Ejnbz-fx(X`WQF)!0=Xx1} z^ODf89g{*ACgrP#CiV&Q`gqe07LMyB4 zh4aY-(*P7z01EP06!Y;0l0G^)^=(Fy>!RG*rnRvt45!(ag)RY#79889`@|9SV+u1D zDD8}kOVaz}FG?gOZ+%v@nDXa7ZNzc2!wPsOm0DX>ZfOHjU|MCY>9qtdc{z>1q>{lF z%#aW*w2*cfCBtXK;BH)6>1{(S+&RB;TaxUe!u*<)7PZQGUIGaxZ2^Fy4nPqYH=4EM z&(Np*_WY2}qlG&xPf~W5hh+pNm1M|C9MrbF9Nn`)5DF8O1fbjifFd~-#V)C7N8O7R z;x=U`Q#O1XZ2dFLG%q2pJ95vbQw+C;=Tp`RrsDCD06;}C0L5)wj)JbZ@W;A)wtFqu zC2moXb;sJfp4zbzw{V(Mmr^VXcBu+FUP*{SAOP0}%-H0H6SlF2Rx|y*wbClqo~UU@ zcTD~AJ$0(|W%MfZuRgn8PzW(~O{M}v8XP)-BN%|GCN`{KCfAQawkP<}ZH8CKO4^vo z-N%izva`5mf9b(6qGfbX@u%bqys1U?h3>T~soe{5P`8Kz_xZVb0E#LAMPV!=SZeE1 z@AemPkDJ?CykeWkvW;pD8CmURr*+*nKMiRInGkPv)p&PS)u;2=$c7i?yeqBof2M>e99?qM*h6PbBSS3=O(H{$$bh-@ zIGgwb&TUqG9p;rz4+AZGfUn0Q8S$A^ZZnPno0~m{Z9ou6`7@gU6mtLy^;kSN?iwmC z8d#cs?#8Tws0Z3pBwjRf=j^=pye*=E_SaLR{lZf0PlN=Zd;@@DJQfcrYuYyZf-_S} zw-;@dN!I#gaknXb$>q1}>YjApx}cWiEL@WQ&(G+Cv@+) zp6Jj#Q}ZM`yWm5LzM+5SY0V;g70bT%lJf(aGUwJ_{b~;8Gn$jNH00sGRDURWo^bRKGU^&ynJWc z;4$*HI-a+Crh5K$ll0_p;a1LwtyO;DkrF>5fes$(@*{I(gzAm8m~utgzC7-6PsOsA z+yWfUJeT9P6&J}_emmHO5%#>wTey&))FJ>y4uC>D7ERupBH$w_;q&?MeR;p{u-Mp; zkz(SU>^}z)Pf-PIqX&eu)dZ~os9p!4SdK;EA*1)6eeK4z$^$WJS0ii89XtEK%r&dJ zqrgq<``)b6C0sZ{g#`c=>;M$mane{FXxS%SrIg^DRmQfknyYK+clFpS+TaO(Wi_Ls zu~7xg)JLQdq-4WA1RGa{x|PYg3aE6wN!?%rzn*u!aU+%{S=KU5<5KwPO!F`&HP9Pp zikKO#e{#U*V#nncjns;J*Avo_m%q(kuDHp|th=hC)rEUJJ4!0YiR9SpF7O@kwg4zL z02I!#NKoDmKB=`OrE7WdCm%L^;O2g*Mrk+%J|L{CqqcfQ<`{~yTE`Tu^GSmL!1Ig< zZ8Mx13N`tNl5)ieReGTZdAZaD$1;xj zt`t6UfAH?%t=O%4FT4&@V-qg^W$9k|XrN;CSA!(9n?QfDwg5;{P%y^=ss1a`wQUx? z^0&nvhO5|#3)WBbeRY0Hj$csgeJ*Z^KhslMc2bQ1sJ;WBXpY6A`20XV{WH77e?$1~ zvsa@kJuYP53c1ecjnkI1v76HfcbA1v;tBwiKLb!a$0G6hGAF9>@t*Z_;;f6Oq!*<> zSs~G4V_hC1ja`y8|7lF@MtN0n5eq;KKL8ZPu`tR%pHW!e3|E);8KlbGdi`*h(aJU_ z2}cV#_{)ejY#+QUTz`Dt3qa-T02H^e5VkK~zCz;wvS`oC>c>}Y+B;VoJ$$`c=ez4s zYYO$vz?LKH6znGyngFOu8308LrYwSiJ$%{%20($iD{+6Gjs$Gv2(Iu!pIM-#kzeWj zVN2pt!sF@}FxcLAqj?NBDU(b{JZ)Eg1N8zYJ(*`@wt8ue=3)3v;Mwz?T zyrdl77c)Rx;0|u6h*MZE_Q9W!fUOyR1H4ZTrVoBl7-Y+Q~vEsf4!_iWj70Njg%Nuc0};X;GCDH@N#qwp9s7NI%uJ<((sh8S(; z2QR4hbd~BqHy&+i-g|rE zxk?~fsnJ`QVADsw`2zry3D;!e?!$1{y5TP%Mgb6rL=$HAfs8u$!?#{m+w%X4ddXFQ z)pl613~b2;asOy~tJm&K1gq3DVGH|$ZhbvZd}mXZP?PqNp!{gT_FxWNd&GCaKKgN` z2#ds{ldXwFa1#cx8g4dvwFsY%p^^M)i~tG}i$UVCNK-0>LSP1lGD)GNKn5+C9zdb7 zRpb!zBeR*REGRel*O$j;lG!52G3%ogK5bkdB;7O^QQkX{RIg#Z#OB4C#`jukEz_o1 z=4A{acj^pU78Yx}O*8t4D?C0Yl~tFT9QjMgH;N#q&{4P`4wJzlg%X2s=*?)7`DRoo zn&3~O5paAS62+jHl4&YZ2!yY&y5h}c1(2B>??4udK7w6UZg@5lAwhVM>^LJcbarr@ zA@gFW9@8~VJ#vP$+%&z|=0U0U3fBR}yR-hjWTdmyq%8*aOJaJ6h{@$s z860E?jmAOpgHSkZAT0z*3Pus|Xn!V_i=_uLP*_v8iZo&tlg0J^cY<11DR;!yCu>Ca zv9oNxQu(VBw2P0k?1_#px+kf(w2Y#Mn1p#hHE>X)%QwdsEjKZbQ6re4O@?}39996T#{eiHL}09xe44C&A=ZsX@H0gy zWo=ou(WFV=$TAVdhFjUbXqnUH)}(sn1~k z(g8K^KV}^K-C@wi=q6#yP}ilRSJ_HQa_>5H)BG>_oYH-}w*5Hum%7ecr0e{HFlY{v z%HB-D1Y!K?NKzn*iy`8EHaQ%T(qWZrT@GqhTC&sa6l~FWdzPB zSpL7gkm*0VPYHmDkkoZ1yiu;UL=)2GlWX-dzfc1x+oX@fU)^+I!a8DBOAk4yIF0~R zZvs#Piop2p&dP^-`t;z}=H~2Z8#JuyF1Y9Y?9swP&hv#g(u>XvdqxXucFEfqr@`IZ zHu5Rwr6YALI8-PyfJ~?3h-f;8%-+l; zsK5}46f)VH$fDE9L@rAd?m)>a?d$dzPT6juKb;xzeS={wpCcD#@v3#j!_u8Hn*+eY z{R}Fd2h@#VJ(C$)l=bVFWycGC-*Y$N_Ytx*xLL~)l#OfsATP%{DmMR6!m z1!4S1RH5)Jm`8qVAp;wEDnns3u@@dBW%k@MR7WZ=NoJcHeaH^|!}FqM%jc6G;T zbVbjOl%`8^8+_H`PF`$8wHKR#dnJ;};<7TK>FFa)$d5E3YJK0Elt!Cm$~O1pP(PX% zD(<+>2G@QsTm?4tnLOR;_6^~#$xo~UP(lDu_(jn?Is5)^*eOZU>aB%OPU`GF>}=DC zd3D${?X%h}WHHQ8Lw|^?xXE9L20p?SHijezd3sTRx^(mN)1}e&5sblE8JJ#0HG`E0 zjS^MhuMg>?hs=tbIfUkBj+j-zgD){M>aMv^#ar_BLR#mS!@G|F2P*sbemZDow<-)1 zo>^2ab$?jKNm~G*m;+E8MA6`|@Ym6afhnmc?<~hNZ)Tib+}iwZ|2FOXXDel;0VDLV zjN)ScXELH|dSv|eH2Z7hny!Bt9`h~9S;}3n!17pLwNjs!yY^+{A+zE}G@&`A5wkKA zoc!GxjRqMlZ^JC}E>E&oN}fjUik|Rjnbk9l`4>_$&z~CBZ&K3$6lDMkyeJw5ZFk_N z*!$sAZ-?5|_tti;PoPX|u^|&mYY*nT*d_Z$K6LU%WOWaOfDU~G_ZH6@iaBx5duje!~9rsQD zjr$@`l5*ftNLP_>)+<9(Z4BweOZV5F{=K~l>*;`Apj_}02G38&EB8?d1e8k z>tyo18Qt}9t@P3_+OK0OcRBq@c;!%_;_i_l3DVaROaB{8q*}-dB(ovYa!i0Ag+n9$ ziwYkgr9V2An5$0Mq#b=($ik&LehiYm#9Di}B^)vFlL*AbBTA~%CwvYe`jZK6Ftc$& zzALN8@4Aq(?io+}44N`wVW@#X=jJ_ew$kHhkEaG72(`$Trqlw3!% z^44uz7bJ!=pHj-Z75I(=4wN(x!N4?$%K%Vr4nPqdhecc90=oSj~r-ZHl?mn0pO z>e|7H{aaP`>>_%2cz|M)=|F;Gy8f}_g>`Vv^Wgf$z)Y+uv2SjH{oA$d|0~o~e-atv zD7wdfjqYyFu-Qmf)%*11e&mZ&Is+*r+Vr;h4a=+sn=)&p1r#Nn&2C8l@8@FvtGlTG zH-d^dV4`YQh#_|`t?0H|05pgeh8 zyY`E=*4ouQFY!2fB|_3cF-Va&&n%Nn(~W@bIqarP-n&__LjE_Q{eSFTd00)|_wStQ zcDpKd8x7S#p+enmrP81@siagy8g7H;ISEObCF(`POVOY~QFuv2ghIqCQzNNFLWUQG z_}+Ufj=J}*^7}pC=l6S__YaT9wfEYewa?mnuf5jitb;*&5(a5H1mKyM-7m)yS4nT& z^M_CTe9M!SfBczbzAM^MIO6&H3m!`jc@Tu4Jr0BRYz&$OL>!OlrvnCoOSLvI--#fx z_t!~{Vt*VUfKj!p^b z(R$k^W*3 z)B`il%Z93G28!m6t*Q2lx^~@D&g{YI2M1_f@fE%1Veyp=`iW?uXJj~oJ{;)jZ|fPd zl98kyoEN+-iRO133oHfR*EN6ndUWf%3Q60I3K>pEwf-V6eW83yK#B3@HJK@k$%p48 z%IeTI!R0q-hrbvIbcFFz%Vk9c~C{E&XRxNi5 zSmPplf9g)GXZJGx6UEQY+bB22p5K#(C>RBuVLDW-#bJrn7`QNA%U5_MSd*I{@nPF z?mwYGa?ZRuU`Hk(JMkAgRfeozUatzI8hCtmxwPAxE2Z-L!tRx0gf|~NafLQ>#W&xw zd9lRe1q5bv(?q5w5+s&K zJ1c=%AwHex-Ai{a_E;WY;y~6&TpL+m7)zA%|5hU97nNMdyy77k1Q~;Xu^M~LvQ6@n z7jHJ0gU)rd+Jr0(RU#&3dF#7Avp&|@Cl;nMfw6j6hlW^A&aOoFe3ierPZqUr4Qi#D z#6_KRXo*R+$bCa}tGB3cGqz&*!#pEDG-ZegnUk-|0)pF;0O{?LXI-28iPw`nY9A=o z*APBliAt>%inyk08+j>&KAoe1fI)MFK}xeisW(n~W8An3gKO=vxuJ7jA!ovSr}G;e z+IXUFMo)OQ^Ihg;iS@)|kilTk6tDuc?(qcm6pG-xWoZ*vZMNi>jk`v>8T|76t90YF8;hQQEz^mKm|eW+Tw_Tl zGm=7J9Z6v=@zl+v&zX1Iml#n#7}lt%-dMMeYpU4+;bQHh(Jq$b_eU|UmT%-%E9x4+ zr~SOa==JJ-nzUAH{j4mZoy67vbU=&0*UP+GoucCN?&r-hRFQ@PRY^Dr@9wY{7%L)+XwxIo<(wKx5 zV#@Q}y`8JN0_4;TJ!&Q1*4@+CcQeR?>1%Sf4h%AR4AL4IKMdHAS8B_6ntW;JI`%VmJG`P$X^O2gYX|5$-T$%2{6eZZwNT=qK{^R|SVSd}I|8 zageUp-vhc6GI|V>!uoqad@%A%5-*ebHNpXAkeK<{{?-sFi%cd71$YLy{PZZvTx2B@ zgQn3h03uZ}8q?g}`x`@vEe1A5D7U{g6vZVglLmP${T-lN2U(Rw!YRV+19`;^{ETY^ zvoYieF&^HJ%LTIsuy^bA6W?egxMGb4VOZT3Wds0Z-_|7srgEyb{ z9iX48Jpa45Vdy?T1Yr83jIc6+`EBBby*Ctfr_B|SR` zUubkQ2BTRRv>=9z``zzC^c45P^xD(9S+y@Uw2wASJ|L+VqrU?C(4jRmC)|vO$ioP; zK^p-EDKKQ*ue1DGy*{)|nindz>~F8UQ*r3D`!Bxw#uO;DRgCBJ%=aJ&^ZbvaSdemv zE*?`5&PQPW4IL}sxdX_Df^2XUjnNR@bGeYicxl6;6)1Q{b9XDH(!~@E6NBgAprET#xn@(r8$P6PpabJ;VEDv%nt^Bg zjFy1!HT+0lVy%|zOCyE* zEBw!N>L?q?cZTMQMEV?%l0BSupvp~;M&B_wvSc8rqhiTO?z7U#Db|>hc_U%VX|H=1 zGomIgP?c>xmKkj$a`~iR^enpGbTq8ER6}?e!xa74y;rMT1yh>(Du@=FOSSGXTh7J}D9Tne%wvJTGg^<`i9Ao`2amP4AK{mM#H#5eh56ZT17r|j=5N}YqVnj zw2zimqrZQx!KtOh*H6a8A30SMTJyDY!m&^YJZj zOR?p(ZTyD05s%&wS6k2sLOdMVT99F4kiLla4>ZG$5|GLSHQ*#1qCvqtDGtJ+%OrT) zPyB;>+C2gVobSOwoUXWZRCW$C7_pt7?RZ{g~NUO35+B&xY>$ps!}yIhh98biN04*{Ljpi8)^$8*HhZRolMWXlqAR-%|F*> zXTuV;lA|sY8KOs%%m{7rpdY$Oia^u4_eTV)iF4g|C*K(_Cz@Py%=y_t$6tGO8 zWhEKDf3W8E)AQ4cbxY#*FS-(w_spM<$2PKW&*y@uHhso}VjbR=!#yaf29-*ss0=l9 z);WW;t-^EB8e2D~u`896qodDNCCwkF9`jWp=Ur!0SZ&7`9mbffWBijyvV&tvur>~s zA#>S-D-v^a7O5%BOPKbe#QTuI+wZP@(@Gp|zsg`1vm%$%ZG&A>0h%BT(uNhFS>GER zB9y~=z8x1YYuJ3HKxdPoM#}oo-rI&Z)}OOowPZQn&H3%50;DY~K)UB;$nz(ji+s6N zT2b1kEr%=}5Mui3zFNI@SZ^q=_B0Q=rvoJwAlt?utr5dvz=oYPP{ssKsf=I{Fp&f` z7|9@D5*cbRl0l$EG@Pj(!60B(7HTk(L7(&J>%NssXro@lQ&91s!P&rA@jI7P{ zF@M&AU<7BVnp#>^irSA_5NcG-*%WmO;|qRjvsGrRsZnODsHtoA`|!+RhRrjSeFW2! zEDBAa7^F zC0bVbO55aZa;AirEun2LYKmT58B-y%?|Ma6;>_yPFGC6T3@3$ki5BhOE72l_3@_4h zL&i-eDWRH=@AG;Q^Jnf(OZmCKZ|;fZY0jx|Tiw7LsL+VCr#J4{*iEH4rL zHDivF!3h4aj5#`*j5#`jjQJ0G06Hpq0KGMIRUeX!M}I3BPwxe7*S{v?(Gf5(aDwp;OPtKF#1AGT+en>E~Ep$aM-1p zxIyzZ2-A0_FT-cUmLWdP#0?s@lu+cuNPgt`KnHQIUy2EpNj3(mEi$`0X-)pO3zrr1 zR94@5eo`XutZs*bl{?U`3~VReaI3c;K}C$8MGsc_ z283%+ebrV(Xa$CN(6m$o!$N~qeS=ja!dCjZ`+2HG(5S)TQuz7=8xK}=mexvIQuZv~ zv0|JTO*Qa?aq^g&vk~(TKU;7pV7Vj8!v-2$Y6VgoKSPIJIE|MJJwERGoLEX|4!6i< z35SsKJH?HsB{ZdLD-JsH5D084zCap`rs9ijd9tX*(j(uuDLbe;<+T&5v(L)$@>lzI z-EW{xUQ@o_kw7B+Zp9Z!MI4Ow&4E6WcU5(-6;*|Pt_WG-RbD@1$3^S}+PE&i{)+scfJwdU{{ozd4W?YF$&tDyo- zAP$CFY!|sOe%*z-B>SS4rCOiIb~g%z=PWTAL)~U%O1iRbJbkKJm-*nwN%3;YpAlld zp=b3!!FKOUnkI)|a_F4arEGiWYT;e?aCOh6bY*_8%m;)I2g22%X1dk-(sH|F=T?0X z3>4p5Rw?n_&p~D-;Zd1y_AT@NMf7`RJ|G40B~SL(nJ+7>mkeo$?rY7`OG)5Y$}e1$ z5c|&=lW!g;-E{gF5z8_kkWFBaiZ~c`+4FpBv$1sNZSRya8zNRoVy_;_8{XBE5h*&I zHtW#_N1_;kO_>j98^9nH5v@TOgB~Y3c))-qM4$#7WJ9Hc;Mzj$WkYpd;6gC$WkaQG z;958AWkX&j=!SBT4HfZ%t9-GS4ONnXOUTXmmlbzHZFCt`bef?Q^RORB{U3Qu@`Z>Uvo&!J~6+I`T zKyw}+^7;AtwCFJD#+whyKG}cM_LKL1TqC}x#Xo(_47%QQG_1TkCK`c3g_%XTae|w7 z@w;C0U0tmheC@JZ{w2q}xTgze7+Yo(g%sb{OX)NmP?N1-n4AMa$D>(v<&;15rBCDG zR}K>|zMgQdV3OD}kNeT{|9XFl+?-KCo7J!82v|tNp6BQJLH9gs_e;6F6Z7p&5sQcx zOj)<1Q?OmfCH!qq$ zWp!wSVuMXkAB}#pa%3Sv=7~Z2{=(~N)wXh+dp$YDVOzG_e$mA_Ij?Na9`N#)wNQVw zMEv3u_5NueVJ#!gfr3W(5l9>JC!6iA6b3@2K=gwr5KkvtzlhtQRUct?d+mVO(ej+~?Y~T=P4?dr z+9;xwnYY_zp6}kz$)bk6abMHgYAkH74lD}xJSRw93<8cvb5cgHpe=2KTw*sdLTjv4 ztbfpb_cuG|Wjy7%Y~PS&Z$DtU?0HVmupJXt7n=@BMNi06$~)PR$4h-L`$5IG2k*j>Lv|N0>u zBC^3uHx9xDJ1iGi#Eix;L`x31p5DlJMuV<8`~APFWbPA-FUoc zOG+9a(eG2Ni7K|DWy0QetwRWwytdH|*f2--oZF2BHQuCjB1vxRf+Ss(jGw74* zi4`X*j?7Vi?euWMBnvmCsFhto9mkb>dV(7MTkj)%dGhdZW8mMWQ?nQM9h%yw9LN{{eS(R)n&(y5ln1sRWNndIlIcB_=IL1yc^jg?$yGlW$TOom zDC<7HwC;YSUanVl4M4As7Lf36r{kA zag7K&xB8wBdAP&9TT!;|W5ka8?<>I40n>OP9!11~H5cGryVN&i>{*yT!A;$Q0_qk+W)nk5{AjLBT5Lcps6~ zk;Arj!S{YS&mXoJ30A9CC?#8~K5ggE zxz+QhezVB(kBNeHsbRA|k9e)}`E!3JZ&yg)sOWps-j}PsIq=d`qhRHkw@vcRPggx0 zefNg7`R*nRwo2jFh{y?@17H@ioGcLdz$LNlJv_vJyzwDhvy0&6b^4& zx$lS2^-T1J1?fwnB=F9xK|J?HSce6@s zN>Q~tx?|FJhUdED)D+5hdj6&@<$F5@KmDZBvsb=`QRwb}K1@KJ=ER?`@Qoy%b)KB{I5SZiJRN-~08;46(dAa&YUmmCZ>+Rb_bGWpv zsN;=iJSgXubhOiAPcB!&t!G+q_o%y15>n^piqVfrU)^H;TS0v<22y_2DX|4Mz%rGHwQ2< z4}n$YZmS(PF2=>uab2H1AD5d zCmyp~JxjaYLU7YCXLZ}}?p^k{@yaVNZ{hgAvVW%cFlHX}Vqsv9x-f9^sX-Mp-de2N z+P2O5yF=c%@0pxGgkLP(@ZeIxLPNh>GtHBmdSGB!4H^mqTYC(QJA{IXFa=PY875E< z49r7d?Yb&DjsvVAv+Ya{z`K~wl0BZ2*G!I z3V3xOV4f=wFwYeT7zo2w_H7_wAPtMu+7r*<1lYa00|pqJ1#{%~3^0!!L~8>l^H{*i zH5f3EhPgF644CIK2F$VsHW)BC1JT}ny8Z^{h z^Qu3g*8`XUOaZI|LVIXE?wXIl+I8rnVm+`%9K>DoIrB=>I)SOz;CiNBJC_zs%NTxg zbN)%a^5AEmhj*Wr*Ct?d;J>m`Hhh>-_OKb4dI@Z&Ud&E^nwCl^Ok$mSNl^krDIBN8 z5(!2S6p3OOO*qcxk8uXaA`Z-R?pg42s2 zAL>L_9teovDBvbmWz(Kx4~?zk4|b@sciU z^)ogq=+#jp3R}glJ&ir+_L=y9y9V(3?l`OR5(=EsR4}_Cu=?7OW|318%MSaW(3h|9 z^@s{y_2YlOH=XU!)mZ%B`~I)bnVA-7X?9mxr|`YM?n@X_w&!*Mdh5fF^hXv1pDRBU zSbXv1wll=PcHAtl%GOoZX;x=`n^)VOJa{5JV9hnt+|>MG*FU*;Yw*;QIbWXsXyU4~ zRb94z)(KW!1Xgg{(p-2r@~U>>&Yl;`+mCJC;qlbv`KMbi$_#s)CFgwjmEy>Ns(#f7 z)(KW$J4#P;b^C}(+b8~#5;FD6Gt)m0o_N>P`QYM!S>3lpZ0P!(pGx2@aLPKtIwk_E zuLFd_>inSyAWXnn=1_VSCg3b{7~$0r1k9Q_l)ZxqILjOgufYVIWe!6&;Y_EK%wcpY z9A9;kISe3#6NXMQhq01yn9@n+u=`Nxjj96hvDI&uPeQ{W2z=B%{g^Aq)u%I zuk&f^C%(Dy@e1#8*FDQ_@Vrb}ujO~C44OV=*wlToz%Bn4&y(%a`MGIi<(+W@TBV#F zPxMeV+b1lUnsxtvWz2_2YGaf^Ud7i>KwfHB#sJY;(8A;iCxFVLppH@ed zPSKXlc{?d?#J95o%S*S89I6V6swi8k{HS8|^P9;Q{K;3<_Vqx1-jz~4xvc%dklQz+u#0mxe*fOrZv5#*;7`l0#6R7?)}VawMnF;f*LTkTDET!q zG$e?du>2AJ?9Etj%kUwfbQ1y_54H53eQyT&^De=s&)+hnZ(k5mW?Ep#;LH`%^Qq07 z28n-o9?KU980-o*yb)LhYUv%jH|cE8lo^5Xl`-#T+*!6g$E)ma*9o_}tqlEc*wY`I zwT|^_Az+0+!75No@4EcJ<7pk}*X3JH6@B}j{ zeA$l=jUaF9<>BWe19tFf@vwX{xqsb(FVgRsTaPFD0%ExY@pgpXses!Khc2>b*Oj4o?=g8$9B`Oa4sW zu3%_wei+~XjYzD^z+d0xwzwQVJYnH^zoqoZ3iUINe>-_$Pz-R;TrL8u69Oxk!&gml zdiVbDt(9M0+^jb}>G8fm|LUx+chdWg3%rqWI=Dq=4<;VO0z;FaG=X9So90t^>|FQ3 z=-l~j<}H{oq@{e%*NXnA;Y4fY0&$7p!ls@1`JlEgVQ8=_GzdeBJLeZ?O24(H@|n0< z@327Kut86ByxyUEqB?#Oe)2-gxvAjdRUd{1vnK*;0!IZ3o4zDhaqaRKA%}dG8OMe! zy14D)gn{q=n+VVyUBA0@Ze>5lP;d;5#wd!y#I-xRV+`$wJ_C)RJ8p94jOd=f{V>`u zsEg-_HaD7uo-W$raV$M~T^OSij-fg39F7!rIkM<{%jKslmVA5sX4u^GJ@n(E7u_k2 z_sjfz_tJ|)&gGax|Mg&Kum(b4wQ*FS!aGk7_sG<54hYOXa`BRJK?HYqK<1wE1D@-J z^AZmDqp5ta`dS^1p}}hFs6hL_L!Tw@i@n%wW_U#lLkfLu*Fs^&rrWJJCEwqj`CfTT zwO16z(xrSP=^!jER;ZTaF~D-42_S#9AER$ z<&(N`xbvVG8lQ80;T`YW9^Co0I1ysEr+{CJA>g~r5P&ma3$3;c0UHH1&;*c%ElAoy z6MPoXgwyAm@mWv{H7pB|hDH1ASr%{t?8c}LxWjh^+~K$p7D@&&@T41RJzDs=T}qwaTap0e@s`(^X7c2dmRU;vxt4S41Z! z1zBdD4bj1zM-c?4YT{b^6C9*CVlcfWFbWrA7zY*8B#Cm61}Sqj6@byCM-X#EIFo}N z|C6SjXp%z2;d1@5H6~5AIxSdMWYmn+8Z`3U9L5bAbM+n^9+%HqyYMT47l-S?<$3Ub z??SuN3ro=PKWIoyV|BpBKS|Uc{}e`w-Q&M0Qn-CW2B>rhM)yH56cZ!8h9$`ZkXj-_ zF&-*LLkTQcA_0CHN3wG>BC<6Z8l4(Zl$H!G$WdssHArG<3G2ve)G*yCwN=pVY&IySxElJem z0|iJ@X-SecM-!c`$}?!xH6@agC{2-wIxQkMPoqPaf51e^_PCgm(uhf;H-PRP0ZeaX z$~CJYF* zzg_%~vA-B~$N!opx#NF-?ZkHcHzo`S8~^t4Kim@kcl-Y)NsWpBNhM-TO#gA>e|RuT z5TvBu_@DW>1jX6M|G*hEjuE8O_@6~cg4d1zNrEYw#QtRQzxu|1!^42C&Hv2ne-z=q z{x?ZtYyZZC0ipJ<9sdK)2PfS2Z;IrO|NXU7-SKZMRBClKf;#HF{8vQrajRl^ibqYrWEy_M{A_*-?Ta+o(WhKNzrydQ(z=@Hd!_}i7x zYNniAbwRc!#Jq2u)tRl0g~1lI5y-PT11j;qW&)ny77yWku5b=l=;O z*{;55)U`L+`q{mp%xAc8sPF~7snmxr^bl};xjuaF{VQ7dMVvjpYf(J;=E`pmF6*#- z;hoCqzWd{EU8QnYelm2O_k2-wYV*@qD%zSVn^hbdzVUXiJ?+0*IBCn(g9+X}uBRSp zDGL)F^7Ii1nQhFVS^SprMvfPO8(p2zAPNP48jJEYqEJzll|_9-Dx-yh)mV;aX^OyM z%NPYmO{(kyMxMz_G_g9K4#PTazo$Y+JMbr!k4U7 zb+Pk;&LtIkSt{q_+Asm9wgcrdSI0+CT?px-|rQPwLCQ0t~pTBl;KK@?-{LN{|`VUFc?)9H0Ney5B!GkdgilgKo zY5fN$#Gp6Tzy1S`V-)Jj`VUS?X`F_v|1d%%?Qs1^f=d2m>p%A6ztQkFrvdzrn4~E8 z_-~Tr-2N{B{^q#4{)1cg|G49SO_JQ}KY#61cl_t+wI-!Wm914XlYb?1jno8Z8gg|F z)?pt1b;rGR{8K1VGyX}GS^s60f!*W33DS5Wf`}}!U{NR{B1CGDVbxU)DoOThm&zelYB&WO#jS$!;mpa3H=9+7-~`s8l5i1hpF{rWf|e&BCD#j zB6A245m7Q!0_LP*wAOQwFpQ9(kr=9=B)C{EiIOP93S1%~F}Z{wDNH7jqY9FamP9EO z@+h$!B{7Zn8?DWFVf#L+6JsXY$@s53|HE;H|8TGW z{`Sd{{lTrA#-KGc>7E=kq_yWUto#9~!0H{=X@b+5cA=TxkUN)QqoXZvKN%aS%o) zSz%A$W-;JZQ!K7IeT+)0Q)-!OgsAG7&6WdNaFeW6Wh-kgDdMU#a&-oc&QM@bTAr>0 z4l%mHku)X*VEqby$Waw4t$v?z$0#bL%(++(XQ<2vgTysIGlf@bbB!vcIdf(i2NjtQ zPPE8~s-H_#TbC+Bqtq4TD9r`2o(ss9GSpv-I)vc@1x+ZQUq#afxI&C!}|PS-g& zPNPiEH5iq78ojx3ENx>e#$*8Mq8(jik*uyX5G18eC9P|@_GY&>5mVLlbY@x1zFljo z2_zycYnX_rdZCzU9qZDyOl8nSTJo?d$^WtUq|I#{$9@ie#T1l!A}!)135u$xSC1lT zi4iZ8v?a@>LhUgCR$T0?_86NXA5y z-**66f}(j3P=eI=%M0+TD4@1Pfob>4b7T2A)l%Kgb`E=Q6c&1IR*~m;K}FsdBi6r^ z$I}__10sS4ienjAwl7_RP+*lSCsyhsi%MgXD3vuH*_Lm?KGyK)aft0GFDNfkT}Y!I zs5vghhrwIb`}*8Cvlhk# z^QkP9n{>LS76F@tDul=bk5ZhC4j{2Wk|$D@1!(2wDqG9cy0lX9 z4dK|d;8aDrDSRkgtBi)23PiHV8oV@4?$_8iTe-^;FX^i8x~QA1y3uO#WBP4@#V)MF zNCGE*%A$~}Z6ngfpu%BAsmge%z`JFcz@K4gfPyvy$dj-gX*Z8pNIUj8AZQ){?mdlA zoWX)55Q3~8>B0s*pZr6+cK^4AUFM>=YLgL1OrW>*pO5(i6-9IGin;}4NE zbAiFOr|+HxuKKWh9$fX(^Yh;RWfbhZewN(LqLU-#*guSZK21Ikdj7i~UVa@%bZ=QR z#t%dqG^Xz48y0S@`}^Zo)vU}FmHeE(wLjeM4;`oP^tauSv zT<-oaBs|^0UKeEg#c(t#B>)5v6EJWIh19Pq>uq_TKn@7vI96m@%9dCU3g9-_o`lSQ z^NhlT616FuB^zHiqgYJ@SDZP3hfOKSneRE{e?r!(-KA@#?cgr@^elY!`StnVKAgP2 z_%wYx{It0EJPHn^oc{D~5q-KiS`P1@g9~uJQva1Jo2ih|BAEKCqiY%oGL{%QD@uI$*X+%|k(9>FRo{SEg%`OCp%SuF(&yOHb z)i+nh^JU4)>f&|bYHz=LAO8GF9v*zL&xfOvtNjaS&$+sooH?Jj-~QAK_6}X=%Vhs_ z`zk*Ca&)pCy_dn8gZ;s0d-C%SC(dB7eSC2G;Z1xzxsTs}8hqOAeYm~BGWq)Kq8yK? zyJ9So1wy-o8FOjKX6Xw>#KoZOMmyIw!rz%S4?C!U>tEoY$j4}h+ znkiqW5xeUGi}syN)VMOE0eoXZ<=IXtZ}YK@d8})Ml~jZ7Rjs(WJkDxUo9|!$X6|kLx0qXm9OTOGxLI)u=Mvj3H3hX%fMHtP7y~6lE=ORH#Ac*O4$Tt zTo#4|;GHx!<3jRTX5Fp63+SxA$@I{>Y$irY>`5w$m0?f2 zfC62>r}|kq4JpC)Ivs?SQ?RRG9q&Ao?P5@0SKJzNR+!9Wyt-79p+@S;?fT05M}@Kh;YN{gKEXnQc&9j;(pMy$Mc+BQEZ z@K8aBfKXs!v2MJCq#0Jj?J3AFB zpmWZ0M}z>VS8juGi9AyGy~3SB#V8*@`z}}I+^P!IC;^mA#)(Q$b-~?KO746+Pj6|+ zs)AB;IjUax%4xH5NF-O@lJ}vC64EVlP$lkUk7O0u1H;YPUG~IQjwF_b;d<4ieogHk ztCUrnekl0pibYOeNIP<>DBITdi;}hc=*YG`^p}2LS?&(g`%9u1$pj;9y1 z`{XE`ro-s{v!6a3a8mxCW2>6h`f3fJpz>KL58o%|Lp(ymwbM0{l(NF zC&T?6cd{p);m+=kJsFPVw(IN+u_E*rG7&oX`%e+=KR;jbY0`iGr<rK66mfBrM&3h;@9p4J3^sNQc&o6F{UxdlwdLdI$?&GQKDO`#%y6iF;P+)0rrk<4Iu7$aN{QVfVumj(vU=)$II zBfJ=(wEz0%;_SHBEffNUy%f4lX-n8?0u)Gn7ZKzdiYx9sOZ@fb3}*@%+zG(b!-NLl z0d+bZTF9BZV&YrVE^Pa8J_twDKWCN~2<%4_hs>%AJ{W5l3Lg#UQSgEN-W*=yo_{<) zc`st++{#4g;8Cav@#Wyv;fW~xhR7CE32y}!&UgX=<^Un&ILIW*pfmMZZa+j z+Y78{*$N|dzZ}Cv@e*P^Cj|NHcjSv4n0bLq$R%EA_DtQdTjF~wPOg`M12Cvm9plY8 z3M_2WnWdrloO;f!za)`Ui@;YFX8i^@Y#noK-E zA_CUR$jruV>aURm+JT&jspIHNFfj*XryeM6Vod>QrT^-{pK&&1lh)On=T&9mxKCpg ziCbhP-UGOWP2+%$r+PNtGFTnIzdXJ=IXgbTIXKmq=GGDo2I33C1Tupb3=!-&7A~|A z0XIP)Q50hsPn~r6K5-`+vDN$F0lW*tIo?Lm0!zmRhdxz$#2TDeP}G24jYt9XcbVkW zQE{ih%o$OS#;iew_HO{Kp@1H;*>df%mU7hGOeWhUJ;+Qy4u?N*DES8*b&)0^*m{~s zHo;fZDJa?&@W$~|Qp*sQu%=QE()|Z57&zuDFR2!;ityM+z7S7CA56kivEe8myeI5O z-Y4kE#8XVFo)Q!uj9_SVTYC<)s2;9m`GPj0U9v_%WXAXsU8;76f4jaoC#Nl_OUeth z(Ga>JUu5+haNY?S7X`P$xy!^7NS2m)3V@)zq$8>7(;)4yUKTTS3w%4|7C06;Y+;O% zqXE{AY^OORgefXfK(AK4{#35TP*}mV#9b<2aUd5WloH7t^O`si15#Hy9{T%kmjKc zd;{XGUqDVieuWAmR}rI_F)FHID^s6(fVrmwOdO0xLq#5V4K!>{q~f>(P9DQ^^sN#` z=u8KEy#tAkOX`d+iqj22wMg;wmyb`uS;ZI|LAatopzv`36=Cf2V~hjZ-?d>3N-)Ni z0s~TBxrM{WrZK``^AgK6B|O2(&y*XpFjGGPrF=ZkC_Kg8P5X$;%NSs=O#998!BKll zv|k_J;6Ila*Z6N`^#HgWQ-COD5CNgeJPINP7$R~(dq*4&97l!;egioJmL{DWEDpop z?>kovN4lMNum)daq3qxbWenrw(H|rv5E10Y3ZzQoqMyJ_{YXj7SrQ$pABpJK7`hQ78Mz~v=xm5`CZdZ z2iqAuupJDsJc-V3>fHhTwEZq`3s7y?*=sUJU^-8+osPAHW^b}itl2m~D{uWtW%K{^ z*15+>@8YG{#m&C~_v$MS7Z;XC869jmxyK7w6C~J(hMPvKc!o0k?%?YD>uamiuffBYm~eV#3P5eMUf=+InE`xDInvP zt~}zD!-MkhZWi0v3Q6n7W4y~bA5DTQSrRx;Vh?+mDe$;^%UB`4t)PH|3Dw zFystI6CjW8Cseos%SUFU5Gbw58At63EX%z^rHbh+iz^5^tDvF?#*1tlAT|VLXCHxi z5$Q1=VqhMD^)xPJ0c4}LG!(=Fa;FdrD~h8s#vWZ|M1X$03@*`zC_!WdOPeNK4Ph+1 zEmLqZ&+lata)`k#$P&FA7=+#Aco^VPxhO6dc3K?yJ~Ta>Ni~-c-)Vs;Cnbjl(DFN3 z?S%pVczJ%wbOBo8v%vV`&om6eVoYsHVP;d<<Ktuh|JSZ4MmU=ubP7{prp=vXRL7+ej72U=K6g1HMSf?J1c^vz)!p-YnY9`%0eBmuG`2ODI$C{7EHy@F7gU4|A_4`vbz2B=0Hc~!Oo z>C!}ekr8b-Q~{PYsnqV=s>#H7gw2|$QHDgx96#}c%j>`gYX@1xXv+y6m{Wd7&PPAL zO-iPMN5Kw|EVPz*m{^IA_~v*Xt10Ho~nW6zv zxqFyv&cKHb$S57m<7t{h)p~hfP?&2pMEC$BEyn1OP?{G|_)GAZ*1~7=sdbR7rwnc34yo*-Y3OHxvT6l~HwK^?e&4-`~ufSIjCY|KFUaVP+fp;+zr^UR<>g}Ka>S`b) z!)QInxSOIGTV+H^x+&c>c2rxO4bnPX-p1qDIQBx0Q+Q{z*Ugq5UDvN0HJ$pBeG?%j zrYTrhVND^vinW0#*4pXVBJ);W*lkhCZtSL9+m~anY?l%7f{}2F{=M6pVKrrD-Ilat zh`LAWSh%ryO#l0wR*!S7&!yx$j9<#o9Uhl>M)vsdMt zz{3`$?)VN2&e>k>p1s;K3$bS~t6-67w*+956ZmX0SuuQ%;@~;kvTMB$vac2pl+L7G zj&ks{ri>3B^S}nA6+!+SZPK<2_ge%ax0jlDM~c)al5=&3hpTkxRtB62zeYlr#Prh{ zo5s2+HgI4HJWLW0YKWSN>P6OtQnMO-u0uH3UqJUT@Iy5;Y@4L`5OTML`rpy>J3ut} z-eH6qYK*yG;U~k33+CAhNriP^7>#8S9H~npii+U{qY7g4D>IFG_M72hQ_fyT#>TX* zCfz^)^g*2I>BGE}tNp=vh%PF*k(1C7j;9J?Tb&JA)k}y!M^!@wyFT{@liHysh z=l9l1cK7y2T-`v#vpx17$0S|TNi{YYtW!>v7ZS&9`-9?55+`szP&}x5Ikd|V>^A^uAk7wQ&|0Lv#d4jNYJN9%SFZ; zKpIZyThtAeKkcP^r@G?Gw6jp_jRB+!B}N`m>98)1&?p@)^UdBvWQV>S)cQt7A>X8*K3oW>uHD`L2>Ao{dgIgfE_LQ+X z?zp%XsB#$jY$VGN^&RNcOXeY2?02X{y7)!LXiIRP9Sp)=Pq(l%9w}pwCfgBq-U+9Q z_;VfI7A{nbvA)@0V>f7%wLUBqG#Te6AH5^uct~#K6i+7vCG$& z3FbPkr1mQUvPHdZbMX8B*WQ&bCypfH{X2dNf{xgB?^rYvhs{j%4=!^Ufw_G|2O&U! zKu8z~b2uC^53>7m^CVlDRi%T&ZBM)1JF!+ocNkREePm^R`DLGK!rTl3|77@GnjJ6g z3%2BS&egPoKzmxP_+7)~z}(0+=9T^v{YO}6K;GD9)^bwR+*jRj})BBHM&6MR9Fy0ij~aAn(|lyZpN_1FHtXyRxg*SG!4i_9@C#>;DjK~MSV=NY2ud?S=$H~l9@79=R&eB1t##ubjS!1dK zCH4`j%&20mgQ*;@504@j6CqBuGgZb?WKT-z`}J21kFKCV{S2Ns*uLvf-vMs39ueaJYM0FrZK2U3+P0qeiRB_fWRM#_-AfRU~VO#prkO~ z-K+vsy5CkVV!=#x;;9t9AFz&cr6*vR2|6;(|r55@+jpqorjP}i*r)?Ys$~EuGy`t%O z17}%>z*UV`#Iup@Hz|86-7|F^?<~ib53T9RuS0*?;U;IWGE)Ql3n8O#kL^1Eq>CVw ze{2506%Ms|N6uepVE1si{cP{qzyGt(|J&!Z@d{;pi~mKEqFeso@vszm_y2y2=fT6J z^1xVBo+44<{3*e;62Huu*V%p~+^(mGUGaR=Pv%qQoSI0dYl+;b+uE49>*8jd?JmOi zY4P)&(YVR!#a}mP`Rn_xE~T5R`|L_?jZ2GWx)!UkN*qLWe0!itoR21k0i#o_J1iVM&IK&k;^2v$&03UW^JOnXA7SACVd_3_5Yj|LR84ko{ z@C0EvKxeueaA7}DCMkDsGzB2a-WNOJrJ)n{MN0UKffAg!2)n~~AOr$setH=P+oK}_ zJaBSuPDbm{al35XkB?tZSfqjP2{f=1TL2h2_eB%9CB=O!e!%Tl(gshUfQPNn0A%`m zng0*=<}S%U>(3Vv`ojcs>G~fWYW@dC!oSPG|M+;~q0=Wl0ey@l`47$rKtFg$@Es0( zPI?ck%OSZB(kwj$_P0Ndvi|Gi`>pMN=-JEvH=Dg4`PVl}iE4(rg9N8iBQj!%!V$qeH1e4t{D@qFUDpG)*%cMjM2416%~a zsP>2^{hc&?fyOrlGGMk+ZiWFv900J%``^%{#Iawz9Bu=!6a<*Fw9eNcqXAgxSPQ8k zQmNjEnsGtN1z1e1jwgG}W;<_|$w`0%*$}3R7*861?zt_Y#ALrQ9tWP9Gy6~%)2U)m zl#x4R;2i*_(vR#H0-`&?$ZFUhPqx0s7JZ~PKj#gv#K$9E=ocqCCwHI&j-EL)gHV(k zI!r@TIbfar7Jyy0I$Wa#0-F>%+EX<&p#_h2Yq#~nXL6%9UPZSVa*nz2QR5G_#d4q= zgOAycpNVUp9Rh**U_rVO5qdgBnOUQS4a94%KXzAj%(99F?j8ZgL{4%1EVeN<2bE1* z{VkAoVqCb;H^&a;Km;8>4-c%3`yoSh1ivvA+KXVUeXZpSo3@&w%gCZ?8rmvA-6*V2 zPA>o+cyB-awO-)vpg*i17;cQ3lr^IUS3ZMTddd9M4At`OZoZ*62LrI*xrl4J8c9|h zBSUTa%x9adUka@t&4#tkjKMS5xo}Hl`6+Wc)m1<`V&<;HWhhW^y+&b!2Wz^?mj`a( z@Uahe;i8dAOD>%RJP*1k!JCEk z1vP%s-U#xw|F59Gf|hrVZCAs|8*>HFBABjBcAz=-csO!MrVFFT4nK!c(gkTA1K)-X z)nP%BJ~0I8$yPIP#WapZI{;aU{STTIVaLm#$_SuyJMszT{-*UB7 z$ij?)v4?*{`d6C)b~*T!TC)X~DWgAnW#R6_6T)Xh1-zt94z}mXpC5jN@Of+VTA)q* za!v-9^eLVE6LrlzCny9Q4dNiofr}abB_KU27wxh%WQQ}&w(t=Fr>ww$Ei(lGnjvb6 zX8}K`S27t~0aQRFEs<>}l<&#netmrp|86KyVaN^(DK)*xNLJKY4f3$)Mou;(*K*D= z@O>X{h{ED$*cY&xhst88($&Z?bl{;5P3ONC_!oQf0XY`j4|oc&;wxQMw|0Ik;P;2K zV4c1v2RJjdc5yPCQwW)%d^j2MMu2YxKW0T_9)Y#X zbWK(I4Abb#-E$a%Hx6K2Ii?pScrLu7Uxxs%1=p8V2 zC_%7>H$6lc!QEx9S(8uBo-fd(0u?|!5Cxiz+N(EZ}DLEQ_wmfa?TQ=XgZ4Q{5K2?R~Za+xJ!6O zkN38J)W|Ib&PtP|2cuEwh=2M?D*;&sf37C>cF2if_b&r4edkm2pWmAHO@D75ii_*) zVuS$GH~aayln5uj!)@tcb3Ys&4yJ{+7FE?*2sDOf-$DGdFeQdZ#&Khy~E#hoP9pyt`8|yce^wy z*nixm99(aFyE0tMKt$Q+@6AmE?^KKlbJC)<)F|Lz5ts?zW*FSkm_AC3Pchmmg?eW?F zC+Zs1x&mnXe=hzrCPv=zpKtLT9)CqtPvi0KK#j!`kw`Z#b;FTxKhledsv13wD^f%a zOTDwx5Ig=3mx1_?!{aZ8rLFOoB2g*!j{kUzM_m_3-CR$rXvJ!E(rU<>SZHnvVp+3O za-$Hfi#@HBE{=QC)~KIrO$y|+mdDApTn{hFzjb+?T*(`AC1=dAtVK8SrYe;i%~&CA zE#*vdSvYSstLv0~S+|y@aWX28Crcv2k>3`q!nC!xUKiqpNp@Xs+~lj_FqE~Fr?OTV z4_B22Nn<3}JxDVi4X#_QjhycnYDO(u9iO+wn2MY#+nH7KCYL;2D{UjzRVTwxx-z-zbmx<{K3R>LxnfAXx@if+&9qdm zYuAZ>Ct+tI7izvZxM{EZ_xa?FQMy~*SysJxQ5}{y-M(BDRyUc%Mjoazi$(q_)sN(2 z`C86c%C@*_jhlmEsylAiMPaz?T^7P}MJe0qS*tl8B*w|!S|5+@R%5Au9+||et6V2; zOKRtA9*K=QbuAMWC;3UOFPc+E=smGH0ZRX0oW)BE|S<-neQEL-AH(kjQK1d8(C+ z6w8;T+-X-@{_Oeq{=DsTc>f>tLtxZ@b?J9X!T28dA zovBN5Lr<-wR7}=JcTyp%U-Wx-SM7v6ys(>O|5HYatc&@^Sz5WC%^M-IC09mg!&!M~ zrnGP)a(|Uc3k9uTkqV_%VRq4#W}9AkbEEf?(M-Fj$1XOqWtwT>LLOIgb}rwq%x?HSnYaJOhSIs-JlQ;9HX6Yv!r!Nl9N#3euvGh}~aLJ00P4b6T-t_3}91EJ}Ao{7MU(YPJ;D(tSC$j8t!Kt|Gm0 zqu(%vNkflE#)V1!G7%mLl2p7NByXmcQq6Xyb|qDhXZnj|akJ{&C0D{oYbS1MXPxts zKB-3=QB^-bFDK7ZmHYVO`l>VUOdBPu7QWL)+1hH^?v*1;sbn;h{XtZkimOTYs@@L| zviGZW)h>?HRUsd{j0{%!^Yg3gny{A2XQgI#5{kB`iCE&^&^!8ie!hwHi}i(={Mi%# W{ds@hpZDkg{P{11*Qv_@PyztMa6X;@ diff --git a/go.mod b/go.mod index d409d401313f..b23c929c8d09 100644 --- a/go.mod +++ b/go.mod @@ -45,7 +45,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-rc2 + github.com/tendermint/cosmos-rosetta-gateway v0.3.0-rc2.0.20210304154332-87d6ca4410df github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 github.com/tendermint/go-amino v0.16.0 github.com/tendermint/tendermint v0.34.8 diff --git a/go.sum b/go.sum index a2c9cd63ed57..06f18fa3feea 100644 --- a/go.sum +++ b/go.sum @@ -660,8 +660,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-rc2 h1:crekJuQ57yIBDuKd3/dMJ00ZvOHURuv9RGJSi2hWTW4= -github.com/tendermint/cosmos-rosetta-gateway v0.3.0-rc2/go.mod h1:gBPw8WV2Erm4UGHlBRiM3zaEBst4bsuihmMCNQdgP/s= +github.com/tendermint/cosmos-rosetta-gateway v0.3.0-rc2.0.20210304154332-87d6ca4410df h1:hoMLrOS4WyyMM+Y+iWdGu94o0zzp6Q43y7v89Q1/OIw= +github.com/tendermint/cosmos-rosetta-gateway v0.3.0-rc2.0.20210304154332-87d6ca4410df/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= diff --git a/server/rosetta/client_offline.go b/server/rosetta/client_offline.go index f619bfc6d2cf..75fba0a7115d 100644 --- a/server/rosetta/client_offline.go +++ b/server/rosetta/client_offline.go @@ -3,28 +3,23 @@ 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" ) +// ---------- cosmos-rosetta-gateway.types.NetworkInformationProvider implementation ------------ // + func (c *Client) OperationStatuses() []*types.OperationStatus { return []*types.OperationStatus{ { - Status: StatusSuccess, + Status: StatusTxSuccess, Successful: true, }, { - Status: StatusReverted, + Status: StatusTxReverted, Successful: false, }, } @@ -35,76 +30,13 @@ func (c *Client) Version() string { } 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 + return c.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 - } +// ---------- cosmos-rosetta-gateway.types.OfflineClient implementation ------------ // - 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) SignedTx(_ context.Context, txBytes []byte, signatures []*types.Signature) (signedTxBytes []byte, err error) { + return c.converter.ToSDK().SignedTx(txBytes, signatures) } func (c *Client) ConstructionPayload(_ context.Context, request *types.ConstructionPayloadsRequest) (resp *types.ConstructionPayloadsResponse, err error) { @@ -113,109 +45,90 @@ func (c *Client) ConstructionPayload(_ context.Context, request *types.Construct 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) + tx, err := c.converter.ToSDK().UnsignedTx(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()) + metadata := new(ConstructionMetadata) + if err = metadata.FromMetadata(request.Metadata); err != nil { + return nil, err } - 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...) + txBytes, payloads, err := c.converter.ToRosetta().SigningComponents(tx, metadata, request.PublicKeys) 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(), - } + return &types.ConstructionPayloadsResponse{ + UnsignedTransaction: hex.EncodeToString(txBytes), + Payloads: payloads, + }, nil +} - signBytes, err := TxConfig.SignModeHandler().GetSignBytes(txFactory.SignMode(), signerData, txBldr.GetTx()) - if err != nil { - return nil, err +func (c *Client) PreprocessOperationsToOptions(_ context.Context, req *types.ConstructionPreprocessRequest) (response *types.ConstructionPreprocessResponse, err error) { + if len(req.Operations) == 0 { + return nil, crgerrs.WrapError(crgerrs.ErrBadArgument, "no operations") } - txBytes, err := TxConfig.TxEncoder()(txBldr.GetTx()) + // now we need to parse the operations to cosmos sdk messages + tx, err := c.converter.ToSDK().UnsignedTx(req.Operations) if err != nil { return nil, err } - accIdentifiers := getAccountIdentifiersByMsgs(msgs) + // get the signers + signers := tx.GetSigners() + signersStr := make([]string, len(signers)) + accountIdentifiers := make([]*types.AccountIdentifier, len(signers)) - payloads := make([]*types.SigningPayload, len(accIdentifiers)) - for i, accID := range accIdentifiers { - payloads[i] = &types.SigningPayload{ - AccountIdentifier: accID, - Bytes: crypto.Sha256(signBytes), - SignatureType: types.Ecdsa, + for i, sig := range signers { + addr := sig.String() + signersStr[i] = addr + accountIdentifiers[i] = &types.AccountIdentifier{ + Address: addr, } } - - 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()}) - } + // get the metadata request information + meta := new(ConstructionPreprocessMetadata) + err = meta.FromMetadata(req.Metadata) + if err != nil { + return nil, err } - 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") + if meta.GasPrice == "" { + return nil, crgerrs.WrapError(crgerrs.ErrBadArgument, "no gas prices") } - msgs, err := opsToMsgs(c.ir, operations) - if err != nil { - return nil, crgerrs.WrapError(crgerrs.ErrInvalidOperation, err.Error()) + if meta.GasLimit == 0 { + return nil, crgerrs.WrapError(crgerrs.ErrBadArgument, "no gas limit") } - if len(msgs) < 1 || len(msgs[0].GetSigners()) < 1 { - return nil, crgerrs.WrapError(crgerrs.ErrInvalidOperation, "operation produced no msg or signers") + // prepare the options to return + options := &PreprocessOperationsOptionsResponse{ + ExpectedSigners: signersStr, + Memo: meta.Memo, + GasLimit: meta.GasLimit, + GasPrice: meta.GasPrice, } - memo, ok := req.Metadata["memo"] - if !ok { - memo = "" + metaOptions, err := options.ToMetadata() + if err != nil { + return nil, err } + return &types.ConstructionPreprocessResponse{ + Options: metaOptions, + RequiredPublicKeys: accountIdentifiers, + }, nil +} - defaultGas := float64(200000) - - gas := req.SuggestedFeeMultiplier - if gas == nil { - gas = &defaultGas +func (c *Client) AccountIdentifierFromPublicKey(pubKey *types.PublicKey) (*types.AccountIdentifier, error) { + pk, err := c.converter.ToSDK().PubKey(pubKey) + if err != nil { + return nil, err } - return map[string]interface{}{ - OptionAddress: msgs[0].GetSigners()[0], - OptionMemo: memo, - OptionGas: gas, + return &types.AccountIdentifier{ + Address: sdk.AccAddress(pk.Address()).String(), }, nil } diff --git a/server/rosetta/client_online.go b/server/rosetta/client_online.go index f5e5cfafeebf..bd122b4069d7 100644 --- a/server/rosetta/client_online.go +++ b/server/rosetta/client_online.go @@ -6,34 +6,29 @@ import ( "encoding/hex" "fmt" "strconv" + "strings" "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" + rosettatypes "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" 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" + + tmrpc "github.com/tendermint/tendermint/rpc/client" ) // interface assertion @@ -44,36 +39,17 @@ 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 + supportedOperations []string - ir codectypes.InterfaceRegistry + config *Config - clientCtx client.Context + auth auth.QueryClient + bank bank.QueryClient + tmRPC tmrpc.Client 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 + converter Converter } // NewClient instantiates a new online servicer @@ -85,14 +61,76 @@ func NewClient(cfg *Config) (*Client, error) { v = "unknown" } + txConfig := authtx.NewTxConfig(cfg.Codec, authtx.DefaultSignModes) + + var supportedOperations []string + for _, ii := range cfg.InterfaceRegistry.ListImplementations(sdk.MsgInterfaceProtoName) { + resolvedMsg, err := cfg.InterfaceRegistry.Resolve(ii) + if err != nil { + continue + } + + if _, ok := resolvedMsg.(sdk.Msg); ok { + supportedOperations = append(supportedOperations, strings.TrimLeft(ii, "/")) + } + } + + supportedOperations = append( + supportedOperations, + bank.EventTypeCoinSpent, bank.EventTypeCoinReceived, + ) + return &Client{ - config: cfg, - ir: cfg.InterfaceRegistry, - version: fmt.Sprintf("%s/%s", info.AppName, v), + supportedOperations: supportedOperations, + config: cfg, + auth: nil, + bank: nil, + tmRPC: nil, + version: fmt.Sprintf("%s/%s", info.AppName, v), + converter: NewConverter(cfg.Codec, cfg.InterfaceRegistry, txConfig), }, nil } -func (c *Client) accountInfo(ctx context.Context, addr string, height *int64) (auth.AccountI, error) { +// ---------- cosmos-rosetta-gateway.types.Client implementation ------------ // + +// Bootstrap is gonna connect the client to the endpoints +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) + + c.auth = authClient + c.bank = bankClient + c.tmRPC = tmRPC + + return nil +} + +// Ready performs a health check and returns an error if the client is not ready. +func (c *Client) Ready() error { + ctx, cancel := context.WithTimeout(context.Background(), defaultNodeTimeout) + defer cancel() + _, err := c.tmRPC.Health(ctx) + if err != nil { + return err + } + _, err = c.bank.TotalSupply(ctx, &bank.QueryTotalSupplyRequest{}) + if err != nil { + return err + } + return nil +} + +func (c *Client) accountInfo(ctx context.Context, addr string, height *int64) (*SignerData, error) { if height != nil { strHeight := strconv.FormatInt(*height, 10) ctx = metadata.AppendToOutgoingContext(ctx, grpctypes.GRPCBlockHeightHeader, strHeight) @@ -105,16 +143,14 @@ func (c *Client) accountInfo(ctx context.Context, addr string, height *int64) (a return nil, crgerrs.FromGRPCToRosettaError(err) } - var account auth.AccountI - err = c.ir.UnpackAny(accountInfo.Account, &account) + signerData, err := c.converter.ToRosetta().SignerData(accountInfo.Account) if err != nil { - return nil, crgerrs.WrapError(crgerrs.ErrCodec, err.Error()) + return nil, err } - - return account, nil + return signerData, nil } -func (c *Client) Balances(ctx context.Context, addr string, height *int64) ([]*types.Amount, error) { +func (c *Client) Balances(ctx context.Context, addr string, height *int64) ([]*rosettatypes.Amount, error) { if height != nil { strHeight := strconv.FormatInt(*height, 10) ctx = metadata.AppendToOutgoingContext(ctx, grpctypes.GRPCBlockHeightHeader, strHeight) @@ -132,7 +168,7 @@ func (c *Client) Balances(ctx context.Context, addr string, height *int64) ([]*t return nil, err } - return sdkCoinsToRosettaAmounts(balance.Balances, availableCoins), nil + return c.converter.ToRosetta().Amounts(balance.Balances, availableCoins), nil } func (c *Client) BlockByHash(ctx context.Context, hash string) (crgtypes.BlockResponse, error) { @@ -141,64 +177,39 @@ func (c *Client) BlockByHash(ctx context.Context, hash string) (crgtypes.BlockRe return crgtypes.BlockResponse{}, fmt.Errorf("invalid block hash: %s", err) } - block, err := c.clientCtx.Client.BlockByHash(ctx, bHash) + block, err := c.tmRPC.BlockByHash(ctx, bHash) if err != nil { - return crgtypes.BlockResponse{}, err + return crgtypes.BlockResponse{}, crgerrs.WrapError(crgerrs.ErrBadGateway, err.Error()) } - return buildBlockResponse(block), nil + return c.converter.ToRosetta().BlockResponse(block), nil } func (c *Client) BlockByHeight(ctx context.Context, height *int64) (crgtypes.BlockResponse, error) { - block, err := c.clientCtx.Client.Block(ctx, height) + block, err := c.tmRPC.Block(ctx, height) if err != nil { - return crgtypes.BlockResponse{}, err + return crgtypes.BlockResponse{}, crgerrs.WrapError(crgerrs.ErrBadGateway, err.Error()) } - 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)), - } + return c.converter.ToRosetta().BlockResponse(block), nil } func (c *Client) BlockTransactionsByHash(ctx context.Context, hash string) (crgtypes.BlockTransactionsResponse, error) { + // TODO(fdymylja): use a faster path, by searching the block by hash, instead of doing a double query operation 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 + return c.blockTxs(ctx, &blockResp.Block.Index) } func (c *Client) BlockTransactionsByHeight(ctx context.Context, height *int64) (crgtypes.BlockTransactionsResponse, error) { - blockResp, err := c.BlockByHeight(ctx, height) + blockTxResp, err := c.blockTxs(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 + return blockTxResp, nil } // Coins fetches the existing coins in the application @@ -210,69 +221,80 @@ func (c *Client) coins(ctx context.Context) (sdk.Coins, error) { 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 +func (c *Client) TxOperationsAndSignersAccountIdentifiers(signed bool, txBytes []byte) (ops []*rosettatypes.Operation, signers []*rosettatypes.AccountIdentifier, err error) { + switch signed { + case false: + rosTx, err := c.converter.ToRosetta().Tx(txBytes, nil) + if err != nil { + return nil, nil, err + } + return rosTx.Operations, nil, err + default: + ops, signers, err = c.converter.ToRosetta().OpsAndSigners(txBytes) + return } - 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) +// GetTx returns a transaction given its hash. For Rosetta we make a synthetic transaction for BeginBlock +// and EndBlock to adhere to balance tracking rules. +func (c *Client) GetTx(ctx context.Context, hash string) (*rosettatypes.Transaction, error) { + hashBytes, err := hex.DecodeString(hash) if err != nil { - return nil, nil, err + return nil, crgerrs.WrapError(crgerrs.ErrCodec, fmt.Sprintf("bad tx hash: %s", err)) } - txBldr, err := txConfig.WrapTxBuilder(rawTx) - if err != nil { - return nil, nil, err - } + // get tx type and hash + txType, hashBytes := c.converter.ToSDK().HashToTxType(hashBytes) - var accountIdentifierSigners []*types.AccountIdentifier - if signed { - addrs := txBldr.GetTx().GetSigners() - for _, addr := range addrs { - signer := &types.AccountIdentifier{ - Address: addr.String(), - } - accountIdentifierSigners = append(accountIdentifierSigners, signer) + // construct rosetta tx + switch txType { + // handle begin block hash + case BeginBlockTx: + // get block height by hash + block, err := c.tmRPC.BlockByHash(ctx, hashBytes) + if err != nil { + return nil, crgerrs.WrapError(crgerrs.ErrUnknown, err.Error()) } - } - return sdkTxToOperations(txBldr.GetTx(), false, false), accountIdentifierSigners, nil -} + // get block txs + fullBlock, err := c.blockTxs(ctx, &block.Block.Height) + if err != nil { + return nil, err + } -// GetTx returns a transaction given its hash -func (c *Client) GetTx(_ context.Context, hash string) (*types.Transaction, error) { - txResp, err := authtx.QueryTx(c.clientCtx, hash) - if err != nil { - return nil, crgerrs.WrapError(crgerrs.ErrUnknown, err.Error()) + return fullBlock.Transactions[0], nil + // handle deliver tx hash + case DeliverTxTx: + rawTx, err := c.tmRPC.Tx(ctx, hashBytes, true) + if err != nil { + return nil, crgerrs.WrapError(crgerrs.ErrUnknown, err.Error()) + } + return c.converter.ToRosetta().Tx(rawTx.Tx, &rawTx.TxResult) + // handle end block hash + case EndBlockTx: + // get block height by hash + block, err := c.tmRPC.BlockByHash(ctx, hashBytes) + if err != nil { + return nil, crgerrs.WrapError(crgerrs.ErrUnknown, err.Error()) + } + + // get block txs + fullBlock, err := c.blockTxs(ctx, &block.Block.Height) + if err != nil { + return nil, err + } + + // get last tx + return fullBlock.Transactions[len(fullBlock.Transactions)-1], nil + // unrecognized tx + default: + return nil, crgerrs.WrapError(crgerrs.ErrBadArgument, fmt.Sprintf("invalid tx hash provided: %s", hash)) } - 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) +func (c *Client) GetUnconfirmedTx(ctx context.Context, hash string) (*rosettatypes.Transaction, error) { + res, err := c.tmRPC.UnconfirmedTxs(ctx, nil) if err != nil { return nil, crgerrs.WrapError(crgerrs.ErrNotFound, "unconfirmed tx not found") } @@ -282,165 +304,168 @@ func (c *Client) GetUnconfirmedTx(ctx context.Context, hash string) (*types.Tran 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 - } + // assert that correct tx length is provided + switch len(hashAsBytes) { + default: + return nil, crgerrs.WrapError(crgerrs.ErrBadArgument, fmt.Sprintf("unrecognized tx size: %d", len(hashAsBytes))) + case BeginEndBlockTxSize: + return nil, crgerrs.WrapError(crgerrs.ErrBadArgument, "endblock and begin block txs cannot be unconfirmed") + case DeliverTxSize: + break + } - return &types.Transaction{ - TransactionIdentifier: TmTxToRosettaTxsIdentifier(tx), - Operations: sdkTxToOperations(sdkTx, false, false), - Metadata: nil, - }, nil + // iterate over unconfirmed txs to find the one with matching hash + for _, unconfirmedTx := range res.Txs { + if !bytes.Equal(unconfirmedTx.Hash(), hashAsBytes) { + continue } - } - return nil, crgerrs.WrapError(crgerrs.ErrNotFound, "transaction not found in mempool") + return c.converter.ToRosetta().Tx(unconfirmedTx, nil) + } + return nil, crgerrs.WrapError(crgerrs.ErrNotFound, "transaction not found in mempool: "+hash) } // 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) +func (c *Client) Mempool(ctx context.Context) ([]*rosettatypes.TransactionIdentifier, error) { + txs, err := c.tmRPC.UnconfirmedTxs(ctx, nil) if err != nil { return nil, err } - return TMTxsToRosettaTxsIdentifiers(txs.Txs), nil + return c.converter.ToRosetta().TxIdentifiers(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) +func (c *Client) Peers(ctx context.Context) ([]*rosettatypes.Peer, error) { + netInfo, err := c.tmRPC.NetInfo(ctx) if err != nil { return nil, crgerrs.WrapError(crgerrs.ErrUnknown, err.Error()) } - return TmPeersToRosettaPeers(netInfo.Peers), nil + return c.converter.ToRosetta().Peers(netInfo.Peers), nil } -func (c *Client) Status(ctx context.Context) (*types.SyncStatus, error) { - status, err := c.clientCtx.Client.Status(ctx) +func (c *Client) Status(ctx context.Context) (*rosettatypes.SyncStatus, error) { + status, err := c.tmRPC.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 + return c.converter.ToRosetta().SyncStatus(status), err } -func (c *Client) PostTx(txBytes []byte) (*types.TransactionIdentifier, map[string]interface{}, error) { +func (c *Client) PostTx(txBytes []byte) (*rosettatypes.TransactionIdentifier, map[string]interface{}, error) { // sync ensures it will go through checkTx - res, err := c.clientCtx.BroadcastTxSync(txBytes) + res, err := c.tmRPC.BroadcastTxSync(context.Background(), 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 nil, nil, crgerrs.WrapError( + crgerrs.ErrUnknown, + fmt.Sprintf("transaction broadcast failure: (%d) %s ", res.Code, res.Log), + ) } - return &types.TransactionIdentifier{ - Hash: res.TxHash, + return &rosettatypes.TransactionIdentifier{ + Hash: fmt.Sprintf("%X", res.Hash), }, map[string]interface{}{ - Log: res.RawLog, + Log: res.Log, }, nil } +// construction endpoints + +// ConstructionMetadataFromOptions builds the metadata given the options 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") - } + constructionOptions := new(PreprocessOperationsOptionsResponse) - accountInfo, err := c.accountInfo(ctx, addrString, nil) + err = constructionOptions.FromMetadata(options) if err != nil { return nil, err } - gas, ok := options[OptionGas] - if !ok { - return nil, crgerrs.WrapError(crgerrs.ErrInvalidAddress, "gas not set") - } + signersData := make([]*SignerData, len(constructionOptions.ExpectedSigners)) + + for i, signer := range constructionOptions.ExpectedSigners { + accountInfo, err := c.accountInfo(ctx, signer, nil) + if err != nil { + return nil, err + } - memo, ok := options[OptionMemo] - if !ok { - return nil, crgerrs.WrapError(crgerrs.ErrInvalidMemo, "memo not set") + signersData[i] = accountInfo } - status, err := c.clientCtx.Client.Status(ctx) + status, err := c.tmRPC.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 + metadataResp := ConstructionMetadata{ + ChainID: status.NodeInfo.Network, + SignersData: signersData, + GasLimit: constructionOptions.GasLimit, + GasPrice: constructionOptions.GasPrice, + Memo: constructionOptions.Memo, + } + + return metadataResp.ToMetadata() } -func (c *Client) Ready() error { - ctx, cancel := context.WithTimeout(context.Background(), defaultNodeTimeout) - defer cancel() - _, err := c.clientCtx.Client.Health(ctx) +func (c *Client) blockTxs(ctx context.Context, height *int64) (crgtypes.BlockTransactionsResponse, error) { + // get block info + blockInfo, err := c.tmRPC.Block(ctx, height) if err != nil { - return err + return crgtypes.BlockTransactionsResponse{}, err } - _, err = c.bank.TotalSupply(ctx, &bank.QueryTotalSupplyRequest{}) + // get block events + blockResults, err := c.tmRPC.BlockResults(ctx, height) if err != nil { - return err + return crgtypes.BlockTransactionsResponse{}, err } - return nil -} -func (c *Client) Bootstrap() error { - grpcConn, err := grpc.Dial(c.config.GRPCEndpoint, grpc.WithInsecure()) - if err != nil { - return err + if len(blockResults.TxsResults) != len(blockInfo.Block.Txs) { + // wtf? + panic("block results transactions do now match block transactions") } - - tmRPC, err := http.New(c.config.TendermintRPC, tmWebsocketPath) - if err != nil { - return err + // process begin and end block txs + beginBlockTx := &rosettatypes.Transaction{ + TransactionIdentifier: &rosettatypes.TransactionIdentifier{Hash: c.converter.ToRosetta().BeginBlockTxHash(blockInfo.BlockID.Hash)}, + Operations: AddOperationIndexes( + nil, + c.converter.ToRosetta().BalanceOps(StatusTxSuccess, blockResults.BeginBlockEvents), + ), } - authClient := auth.NewQueryClient(grpcConn) - bankClient := bank.NewQueryClient(grpcConn) + endBlockTx := &rosettatypes.Transaction{ + TransactionIdentifier: &rosettatypes.TransactionIdentifier{Hash: c.converter.ToRosetta().EndBlockTxHash(blockInfo.BlockID.Hash)}, + Operations: AddOperationIndexes( + nil, + c.converter.ToRosetta().BalanceOps(StatusTxSuccess, blockResults.EndBlockEvents), + ), + } - // 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) + deliverTx := make([]*rosettatypes.Transaction, len(blockInfo.Block.Txs)) + // process normal txs + for i, tx := range blockInfo.Block.Txs { + rosTx, err := c.converter.ToRosetta().Tx(tx, blockResults.TxsResults[i]) + if err != nil { + return crgtypes.BlockTransactionsResponse{}, err + } + deliverTx[i] = rosTx + } - c.auth = authClient - c.bank = bankClient - c.clientCtx = clientCtx - c.ir = c.config.InterfaceRegistry + finalTxs := make([]*rosettatypes.Transaction, 0, 2+len(deliverTx)) + finalTxs = append(finalTxs, beginBlockTx) + finalTxs = append(finalTxs, deliverTx...) + finalTxs = append(finalTxs, endBlockTx) - return nil + return crgtypes.BlockTransactionsResponse{ + BlockResponse: c.converter.ToRosetta().BlockResponse(blockInfo), + Transactions: finalTxs, + }, nil } diff --git a/server/rosetta/conv_from_rosetta.go b/server/rosetta/conv_from_rosetta.go deleted file mode 100644 index da9ea5b2ed6f..000000000000 --- a/server/rosetta/conv_from_rosetta.go +++ /dev/null @@ -1,211 +0,0 @@ -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 deleted file mode 100644 index 09146eed4f3e..000000000000 --- a/server/rosetta/conv_to_rosetta.go +++ /dev/null @@ -1,95 +0,0 @@ -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/converter.go b/server/rosetta/converter.go new file mode 100644 index 000000000000..43c9460014fc --- /dev/null +++ b/server/rosetta/converter.go @@ -0,0 +1,804 @@ +package rosetta + +import ( + "bytes" + "encoding/json" + "fmt" + "reflect" + + auth "github.com/cosmos/cosmos-sdk/x/auth/types" + + "github.com/tendermint/tendermint/crypto" + + "github.com/btcsuite/btcd/btcec" + crgtypes "github.com/tendermint/cosmos-rosetta-gateway/types" + tmcoretypes "github.com/tendermint/tendermint/rpc/core/types" + + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + "github.com/cosmos/cosmos-sdk/types/tx/signing" + + rosettatypes "github.com/coinbase/rosetta-sdk-go/types" + "github.com/gogo/protobuf/proto" + crgerrs "github.com/tendermint/cosmos-rosetta-gateway/errors" + abci "github.com/tendermint/tendermint/abci/types" + tmtypes "github.com/tendermint/tendermint/types" + + sdkclient "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + sdk "github.com/cosmos/cosmos-sdk/types" + authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +// Converter is a utility that can be used to convert +// back and forth from rosetta to sdk and tendermint types +// IMPORTANT NOTES: +// - IT SHOULD BE USED ONLY TO DEAL WITH THINGS +// IN A STATELESS WAY! IT SHOULD NEVER INTERACT DIRECTLY +// WITH TENDERMINT RPC AND COSMOS GRPC +// +// - IT SHOULD RETURN cosmos rosetta gateway error types! +type Converter interface { + // ToSDK exposes the methods that convert + // rosetta types to cosmos sdk and tendermint types + ToSDK() ToSDKConverter + // ToRosetta exposes the methods that convert + // sdk and tendermint types to rosetta types + ToRosetta() ToRosettaConverter +} + +// ToRosettaConverter is an interface that exposes +// all the functions used to convert sdk and +// tendermint types to rosetta known types +type ToRosettaConverter interface { + // BlockResponse returns a block response given a result block + BlockResponse(block *tmcoretypes.ResultBlock) crgtypes.BlockResponse + // BeginBlockToTx converts the given begin block hash to rosetta transaction hash + BeginBlockTxHash(blockHash []byte) string + // EndBlockTxHash converts the given endblock hash to rosetta transaction hash + EndBlockTxHash(blockHash []byte) string + // Amounts converts sdk.Coins to rosetta.Amounts + Amounts(ownedCoins []sdk.Coin, availableCoins sdk.Coins) []*rosettatypes.Amount + // Ops converts an sdk.Msg to rosetta operations + Ops(status string, msg sdk.Msg) ([]*rosettatypes.Operation, error) + // OpsAndSigners takes raw transaction bytes and returns rosetta operations and the expected signers + OpsAndSigners(txBytes []byte) (ops []*rosettatypes.Operation, signers []*rosettatypes.AccountIdentifier, err error) + // Meta converts an sdk.Msg to rosetta metadata + Meta(msg sdk.Msg) (meta map[string]interface{}, err error) + // SignerData returns account signing data from a queried any account + SignerData(anyAccount *codectypes.Any) (*SignerData, error) + // SigningComponents returns rosetta's components required to build a signable transaction + SigningComponents(tx authsigning.Tx, metadata *ConstructionMetadata, rosPubKeys []*rosettatypes.PublicKey) (txBytes []byte, payloadsToSign []*rosettatypes.SigningPayload, err error) + // Tx converts a tendermint transaction and tx result if provided to a rosetta tx + Tx(rawTx tmtypes.Tx, txResult *abci.ResponseDeliverTx) (*rosettatypes.Transaction, error) + // TxIdentifiers converts a tendermint tx to transaction identifiers + TxIdentifiers(txs []tmtypes.Tx) []*rosettatypes.TransactionIdentifier + // BalanceOps converts events to balance operations + BalanceOps(status string, events []abci.Event) []*rosettatypes.Operation + // SyncStatus converts a tendermint status to sync status + SyncStatus(status *tmcoretypes.ResultStatus) *rosettatypes.SyncStatus + // Peers converts tendermint peers to rosetta + Peers(peers []tmcoretypes.Peer) []*rosettatypes.Peer +} + +// ToSDKConverter is an interface that exposes +// all the functions used to convert rosetta types +// to tendermint and sdk types +type ToSDKConverter interface { + // UnsignedTx converts rosetta operations to an unsigned cosmos sdk transactions + UnsignedTx(ops []*rosettatypes.Operation) (tx authsigning.Tx, err error) + // SignedTx adds the provided signatures after decoding the unsigned transaction raw bytes + // and returns the signed tx bytes + SignedTx(txBytes []byte, signatures []*rosettatypes.Signature) (signedTxBytes []byte, err error) + // Msg converts metadata to an sdk message + Msg(meta map[string]interface{}, msg sdk.Msg) (err error) + // HashToTxType returns the transaction type (end block, begin block or deliver tx) + // and the real hash to query in order to get information + HashToTxType(hashBytes []byte) (txType TransactionType, realHash []byte) + // PubKey attempts to convert a rosetta public key to cosmos sdk one + PubKey(pk *rosettatypes.PublicKey) (cryptotypes.PubKey, error) +} + +type converter struct { + newTxBuilder func() sdkclient.TxBuilder + txBuilderFromTx func(tx sdk.Tx) (sdkclient.TxBuilder, error) + txDecode sdk.TxDecoder + txEncode sdk.TxEncoder + bytesToSign func(tx authsigning.Tx, signerData authsigning.SignerData) (b []byte, err error) + ir codectypes.InterfaceRegistry + cdc *codec.ProtoCodec +} + +func NewConverter(cdc *codec.ProtoCodec, ir codectypes.InterfaceRegistry, cfg sdkclient.TxConfig) Converter { + return converter{ + newTxBuilder: cfg.NewTxBuilder, + txBuilderFromTx: cfg.WrapTxBuilder, + txDecode: cfg.TxDecoder(), + txEncode: cfg.TxEncoder(), + bytesToSign: func(tx authsigning.Tx, signerData authsigning.SignerData) (b []byte, err error) { + bytesToSign, err := cfg.SignModeHandler().GetSignBytes(signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, signerData, tx) + if err != nil { + return nil, err + } + + return crypto.Sha256(bytesToSign), nil + }, + ir: ir, + cdc: cdc, + } +} + +func (c converter) ToSDK() ToSDKConverter { + return c +} + +func (c converter) ToRosetta() ToRosettaConverter { + return c +} + +// OpsToUnsignedTx returns all the sdk.Msgs given the operations +func (c converter) UnsignedTx(ops []*rosettatypes.Operation) (tx authsigning.Tx, err error) { + builder := c.newTxBuilder() + + var msgs []sdk.Msg + + for i := 0; i < len(ops); i++ { + op := ops[i] + + protoMessage, err := c.ir.Resolve("/" + op.Type) + if err != nil { + return nil, crgerrs.WrapError(crgerrs.ErrBadArgument, "operation not found: "+op.Type) + } + + msg, ok := protoMessage.(sdk.Msg) + if !ok { + return nil, crgerrs.WrapError(crgerrs.ErrBadArgument, "operation is not a valid supported sdk.Msg: "+op.Type) + } + + err = c.Msg(op.Metadata, msg) + if err != nil { + return nil, crgerrs.WrapError(crgerrs.ErrCodec, err.Error()) + } + + // verify message correctness + if err = msg.ValidateBasic(); err != nil { + return nil, crgerrs.WrapError( + crgerrs.ErrBadArgument, + fmt.Sprintf("validation of operation at index %d failed: %s", op.OperationIdentifier.Index, err), + ) + } + signers := msg.GetSigners() + // check if there are enough signers + if len(signers) == 0 { + return nil, crgerrs.WrapError(crgerrs.ErrBadArgument, fmt.Sprintf("operation at index %d got no signers", op.OperationIdentifier.Index)) + } + // append the msg + msgs = append(msgs, msg) + // if there's only one signer then simply continue + if len(signers) == 1 { + continue + } + // after we have got the msg, we need to verify if the message has multiple signers + // if it has got multiple signers, then we need to fetch all the related operations + // which involve the other signers of the msg, we expect to find them in order + // so if the msg is named "v1.test.Send" and it expects 3 signers, the next 3 operations + // must be with the same name "v1.test.Send" and contain the other signers + // then we can just skip their processing + for j := 0; j < len(signers)-1; j++ { + skipOp := ops[i+j] // get the next index + // verify that the operation is equal to the new one + if skipOp.Type != op.Type { + return nil, crgerrs.WrapError( + crgerrs.ErrBadArgument, + fmt.Sprintf("operation at index %d should have had type %s got: %s", i+j, op.Type, skipOp.Type), + ) + } + + if !reflect.DeepEqual(op.Metadata, skipOp.Metadata) { + return nil, crgerrs.WrapError( + crgerrs.ErrBadArgument, + fmt.Sprintf("operation at index %d should have had metadata equal to %#v, got: %#v", i+j, op.Metadata, skipOp.Metadata)) + } + + i++ // increase so we skip it + } + } + + if err := builder.SetMsgs(msgs...); err != nil { + return nil, crgerrs.WrapError(crgerrs.ErrBadArgument, err.Error()) + } + + return builder.GetTx(), nil + +} + +// Msg unmarshals the rosetta metadata to the given sdk.Msg +func (c converter) Msg(meta map[string]interface{}, msg sdk.Msg) error { + metaBytes, err := json.Marshal(meta) + if err != nil { + return err + } + return c.cdc.UnmarshalJSON(metaBytes, msg) +} + +func (c converter) Meta(msg sdk.Msg) (meta map[string]interface{}, err error) { + b, err := c.cdc.MarshalJSON(msg) + if err != nil { + return nil, crgerrs.WrapError(crgerrs.ErrCodec, err.Error()) + } + + err = json.Unmarshal(b, &meta) + if err != nil { + return nil, crgerrs.WrapError(crgerrs.ErrCodec, err.Error()) + } + + return +} + +// Ops will create an operation for each msg signer +// with the message proto name as type, and the raw fields +// as metadata +func (c converter) Ops(status string, msg sdk.Msg) ([]*rosettatypes.Operation, error) { + opName := proto.MessageName(msg) + // in case proto does not recognize the message name + // then we should try to cast it to service msg, to + // check if it was wrapped or not, in case the cast + // from sdk.ServiceMsg to sdk.Msg fails, then a + // codec error is returned + if opName == "" { + unwrappedMsg, ok := msg.(sdk.ServiceMsg) + if !ok { + return nil, crgerrs.WrapError(crgerrs.ErrCodec, fmt.Sprintf("unrecognized message type: %T", msg)) + } + + msg, ok = unwrappedMsg.Request.(sdk.Msg) + if !ok { + return nil, crgerrs.WrapError( + crgerrs.ErrCodec, + fmt.Sprintf("unable to cast %T to sdk.Msg, method: %s", unwrappedMsg.Request, unwrappedMsg.MethodName), + ) + } + + opName = proto.MessageName(msg) + if opName == "" { + return nil, crgerrs.WrapError(crgerrs.ErrCodec, fmt.Sprintf("unrecognized message type: %T", msg)) + } + } + + meta, err := c.Meta(msg) + if err != nil { + return nil, err + } + + ops := make([]*rosettatypes.Operation, len(msg.GetSigners())) + for i, signer := range msg.GetSigners() { + op := &rosettatypes.Operation{ + Type: opName, + Status: status, + Account: &rosettatypes.AccountIdentifier{Address: signer.String()}, + Metadata: meta, + } + + ops[i] = op + } + + return ops, nil +} + +// Tx converts a tendermint raw transaction and its result (if provided) to a rosetta transaction +func (c converter) Tx(rawTx tmtypes.Tx, txResult *abci.ResponseDeliverTx) (*rosettatypes.Transaction, error) { + // decode tx + tx, err := c.txDecode(rawTx) + if err != nil { + return nil, crgerrs.WrapError(crgerrs.ErrCodec, err.Error()) + } + // get initial status, as per sdk design, if one msg fails + // the whole TX will be considered failing, so we can't have + // 1 msg being success and 1 msg being reverted + status := StatusTxSuccess + switch txResult { + // if nil, we're probably checking an unconfirmed tx + // or trying to build a new transaction, so status + // is not put inside + case nil: + status = "" + // set the status + default: + if txResult.Code != abci.CodeTypeOK { + status = StatusTxReverted + } + } + // get operations from msgs + msgs := tx.GetMsgs() + + var rawTxOps []*rosettatypes.Operation + for _, msg := range msgs { + ops, err := c.Ops(status, msg) + if err != nil { + return nil, err + } + rawTxOps = append(rawTxOps, ops...) + } + + // now get balance events from response deliver tx + var balanceOps []*rosettatypes.Operation + // tx result might be nil, in case we're querying an unconfirmed tx from the mempool + if txResult != nil { + balanceOps = c.BalanceOps(status, txResult.Events) + } + + // now normalize indexes + totalOps := AddOperationIndexes(rawTxOps, balanceOps) + + return &rosettatypes.Transaction{ + TransactionIdentifier: &rosettatypes.TransactionIdentifier{Hash: fmt.Sprintf("%X", rawTx.Hash())}, + Operations: totalOps, + }, nil +} + +func (c converter) BalanceOps(status string, events []abci.Event) []*rosettatypes.Operation { + var ops []*rosettatypes.Operation + + for _, e := range events { + balanceOps, ok := sdkEventToBalanceOperations(status, e) + if !ok { + continue + } + ops = append(ops, balanceOps...) + } + + return ops +} + +// sdkEventToBalanceOperations converts an event to a rosetta balance operation +// it will panic if the event is malformed because it might mean the sdk spec +// has changed and rosetta needs to reflect those changes too. +// The balance operations are multiple, one for each denom. +func sdkEventToBalanceOperations(status string, event abci.Event) (operations []*rosettatypes.Operation, isBalanceEvent bool) { + + var ( + accountIdentifier string + coinChange sdk.Coins + isSub bool + ) + + switch event.Type { + default: + return nil, false + case banktypes.EventTypeCoinSpent: + spender, err := sdk.AccAddressFromBech32((string)(event.Attributes[0].Value)) + if err != nil { + panic(err) + } + coins, err := sdk.ParseCoinsNormalized((string)(event.Attributes[1].Value)) + if err != nil { + panic(err) + } + + isSub = true + coinChange = coins + accountIdentifier = spender.String() + + case banktypes.EventTypeCoinReceived: + receiver, err := sdk.AccAddressFromBech32((string)(event.Attributes[0].Value)) + if err != nil { + panic(err) + } + coins, err := sdk.ParseCoinsNormalized((string)(event.Attributes[1].Value)) + if err != nil { + panic(err) + } + + isSub = false + coinChange = coins + accountIdentifier = receiver.String() + + // rosetta does not have the concept of burning coins, so we need to mock + // the burn as a send to an address that cannot be resolved to anything + case banktypes.EventTypeCoinBurn: + coins, err := sdk.ParseCoinsNormalized((string)(event.Attributes[1].Value)) + if err != nil { + panic(err) + } + + coinChange = coins + accountIdentifier = BurnerAddressIdentifier + } + + operations = make([]*rosettatypes.Operation, len(coinChange)) + + for i, coin := range coinChange { + + value := coin.Amount.String() + // in case the event is a subtract balance one the rewrite value with + // the negative coin identifier + if isSub { + value = "-" + value + } + + op := &rosettatypes.Operation{ + Type: event.Type, + Status: status, + Account: &rosettatypes.AccountIdentifier{Address: accountIdentifier}, + Amount: &rosettatypes.Amount{ + Value: value, + Currency: &rosettatypes.Currency{ + Symbol: coin.Denom, + Decimals: 0, + }, + }, + } + + operations[i] = op + } + return operations, true +} + +// Amounts converts []sdk.Coin to rosetta amounts +func (c converter) Amounts(ownedCoins []sdk.Coin, availableCoins sdk.Coins) []*rosettatypes.Amount { + amounts := make([]*rosettatypes.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] = &rosettatypes.Amount{ + Value: sdk.NewInt(0).String(), + Currency: &rosettatypes.Currency{ + Symbol: coin.Denom, + }, + } + continue + } + amounts[i] = &rosettatypes.Amount{ + Value: value.String(), + Currency: &rosettatypes.Currency{ + Symbol: coin.Denom, + }, + } + } + + return amounts +} + +// AddOperationIndexes adds the indexes to operations adhering to specific rules: +// operations related to messages will be always before than the balance ones +func AddOperationIndexes(msgOps []*rosettatypes.Operation, balanceOps []*rosettatypes.Operation) (finalOps []*rosettatypes.Operation) { + lenMsgOps := len(msgOps) + lenBalanceOps := len(balanceOps) + finalOps = make([]*rosettatypes.Operation, 0, lenMsgOps+lenBalanceOps) + + var currentIndex int64 + // add indexes to msg ops + for _, op := range msgOps { + op.OperationIdentifier = &rosettatypes.OperationIdentifier{ + Index: currentIndex, + } + + finalOps = append(finalOps, op) + currentIndex++ + } + + // add indexes to balance ops + for _, op := range balanceOps { + op.OperationIdentifier = &rosettatypes.OperationIdentifier{ + Index: currentIndex, + } + + finalOps = append(finalOps, op) + currentIndex++ + } + + return finalOps +} + +// EndBlockTxHash produces a mock endblock hash that rosetta can query +// for endblock operations, it also serves the purpose of representing +// part of the state changes happening at endblock level (balance ones) +func (c converter) EndBlockTxHash(hash []byte) string { + final := append([]byte{EndBlockHashStart}, hash...) + return fmt.Sprintf("%X", final) +} + +// BeginBlockTxHash produces a mock beginblock hash that rosetta can query +// for beginblock operations, it also serves the purpose of representing +// part of the state changes happening at beginblock level (balance ones) +func (c converter) BeginBlockTxHash(hash []byte) string { + final := append([]byte{BeginBlockHashStart}, hash...) + return fmt.Sprintf("%X", final) +} + +// HashToTxType takes the provided hash bytes from rosetta and discerns if they are +// a deliver tx type or endblock/begin block hash, returning the real hash afterwards +func (c converter) HashToTxType(hashBytes []byte) (txType TransactionType, realHash []byte) { + switch len(hashBytes) { + case DeliverTxSize: + return DeliverTxTx, hashBytes + + case BeginEndBlockTxSize: + switch hashBytes[0] { + case BeginBlockHashStart: + return BeginBlockTx, hashBytes[1:] + case EndBlockHashStart: + return EndBlockTx, hashBytes[1:] + default: + return UnrecognizedTx, nil + } + + default: + return UnrecognizedTx, nil + } +} + +// StatusToSyncStatus converts a tendermint status to rosetta sync status +func (c converter) SyncStatus(status *tmcoretypes.ResultStatus) *rosettatypes.SyncStatus { + // determine sync status + var stage = StatusPeerSynced + if status.SyncInfo.CatchingUp { + stage = StatusPeerSyncing + } + + return &rosettatypes.SyncStatus{ + CurrentIndex: status.SyncInfo.LatestBlockHeight, + TargetIndex: nil, // sync info does not allow us to get target height + Stage: &stage, + } +} + +// TxIdentifiers converts a tendermint raw transactions into an array of rosetta tx identifiers +func (c converter) TxIdentifiers(txs []tmtypes.Tx) []*rosettatypes.TransactionIdentifier { + converted := make([]*rosettatypes.TransactionIdentifier, len(txs)) + for i, tx := range txs { + converted[i] = &rosettatypes.TransactionIdentifier{Hash: fmt.Sprintf("%X", tx.Hash())} + } + + return converted +} + +// tmResultBlockToRosettaBlockResponse converts a tendermint result block to block response +func (c converter) BlockResponse(block *tmcoretypes.ResultBlock) crgtypes.BlockResponse { + var parentBlock *rosettatypes.BlockIdentifier + + switch block.Block.Height { + case 1: + parentBlock = &rosettatypes.BlockIdentifier{ + Index: 1, + Hash: fmt.Sprintf("%X", block.BlockID.Hash.Bytes()), + } + default: + parentBlock = &rosettatypes.BlockIdentifier{ + Index: block.Block.Height - 1, + Hash: fmt.Sprintf("%X", block.Block.LastBlockID.Hash.Bytes()), + } + } + return crgtypes.BlockResponse{ + Block: &rosettatypes.BlockIdentifier{ + Index: block.Block.Height, + Hash: block.Block.Hash().String(), + }, + ParentBlock: parentBlock, + MillisecondTimestamp: timeToMilliseconds(block.Block.Time), + TxCount: int64(len(block.Block.Txs)), + } +} + +// Peers converts tm peers to rosetta peers +func (c converter) Peers(peers []tmcoretypes.Peer) []*rosettatypes.Peer { + converted := make([]*rosettatypes.Peer, len(peers)) + + for i, peer := range peers { + converted[i] = &rosettatypes.Peer{ + PeerID: peer.NodeInfo.Moniker, + Metadata: map[string]interface{}{ + "addr": peer.NodeInfo.ListenAddr, + }, + } + } + + return converted +} + +// OpsAndSigners takes transactions bytes and returns the operation, is signed is true it will return +// the account identifiers which have signed the transaction +func (c converter) OpsAndSigners(txBytes []byte) (ops []*rosettatypes.Operation, signers []*rosettatypes.AccountIdentifier, err error) { + + rosTx, err := c.ToRosetta().Tx(txBytes, nil) + if err != nil { + return nil, nil, err + } + ops = rosTx.Operations + + // get the signers + sdkTx, err := c.txDecode(txBytes) + if err != nil { + return nil, nil, crgerrs.WrapError(crgerrs.ErrCodec, err.Error()) + } + + txBuilder, err := c.txBuilderFromTx(sdkTx) + if err != nil { + return nil, nil, crgerrs.WrapError(crgerrs.ErrCodec, err.Error()) + } + + for _, signer := range txBuilder.GetTx().GetSigners() { + signers = append(signers, &rosettatypes.AccountIdentifier{ + Address: signer.String(), + }) + } + + return +} + +func (c converter) SignedTx(txBytes []byte, signatures []*rosettatypes.Signature) (signedTxBytes []byte, err error) { + rawTx, err := c.txDecode(txBytes) + if err != nil { + return nil, err + } + + txBuilder, err := c.txBuilderFromTx(rawTx) + if err != nil { + return nil, err + } + + notSignedSigs, err := txBuilder.GetTx().GetSignaturesV2() // + if err != nil { + return nil, crgerrs.WrapError(crgerrs.ErrCodec, err.Error()) + } + + if len(notSignedSigs) != len(signatures) { + return nil, crgerrs.WrapError( + crgerrs.ErrInvalidTransaction, + fmt.Sprintf("expected transaction to have signers data matching the provided signatures: %d <-> %d", len(notSignedSigs), len(signatures))) + } + + signedSigs := make([]signing.SignatureV2, len(notSignedSigs)) + for i, signature := range signatures { + // TODO(fdymylja): here we should check that the public key matches... + signedSigs[i] = signing.SignatureV2{ + PubKey: notSignedSigs[i].PubKey, + Data: &signing.SingleSignatureData{ + SignMode: signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, + Signature: signature.Bytes, + }, + Sequence: notSignedSigs[i].Sequence, + } + } + + if err = txBuilder.SetSignatures(signedSigs...); err != nil { + return nil, err + } + + txBytes, err = c.txEncode(txBuilder.GetTx()) + if err != nil { + return nil, err + } + + return txBytes, nil +} + +func (c converter) PubKey(pubKey *rosettatypes.PublicKey) (cryptotypes.PubKey, 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 pk, nil +} + +// SigningComponents takes a sdk tx and construction metadata and returns signable components +func (c converter) SigningComponents(tx authsigning.Tx, metadata *ConstructionMetadata, rosPubKeys []*rosettatypes.PublicKey) (txBytes []byte, payloadsToSign []*rosettatypes.SigningPayload, err error) { + + // verify metadata correctness + feeAmount, err := sdk.ParseCoinsNormalized(metadata.GasPrice) + if err != nil { + return nil, nil, crgerrs.WrapError(crgerrs.ErrBadArgument, err.Error()) + } + + signers := tx.GetSigners() + // assert the signers data provided in options are the same as the expected signing accounts + // and that the number of rosetta provided public keys equals the one of the signers + if len(metadata.SignersData) != len(signers) || len(signers) != len(rosPubKeys) { + return nil, nil, crgerrs.WrapError(crgerrs.ErrBadArgument, "signers data and account identifiers mismatch") + } + + // add transaction metadata + builder, err := c.txBuilderFromTx(tx) + if err != nil { + return nil, nil, crgerrs.WrapError(crgerrs.ErrCodec, err.Error()) + } + builder.SetFeeAmount(feeAmount) + builder.SetGasLimit(metadata.GasLimit) + builder.SetMemo(metadata.Memo) + + // build signatures + partialSignatures := make([]signing.SignatureV2, len(signers)) + payloadsToSign = make([]*rosettatypes.SigningPayload, len(signers)) + + // pub key ordering matters, in a future release this check might be relaxed + for i, signer := range signers { + // assert that the provided public keys are correctly ordered + // by checking if the signer at index i matches the pubkey at index + pubKey, err := c.ToSDK().PubKey(rosPubKeys[0]) + if err != nil { + return nil, nil, err + } + if !bytes.Equal(pubKey.Address().Bytes(), signer.Bytes()) { + return nil, nil, crgerrs.WrapError( + crgerrs.ErrBadArgument, + fmt.Sprintf("public key at index %d does not match the expected transaction signer: %X <-> %X", i, rosPubKeys[i].Bytes, signer.Bytes()), + ) + } + + // set the signer data + signerData := authsigning.SignerData{ + ChainID: metadata.ChainID, + AccountNumber: metadata.SignersData[i].AccountNumber, + Sequence: metadata.SignersData[i].Sequence, + } + + // get signature bytes + signBytes, err := c.bytesToSign(tx, signerData) + if err != nil { + return nil, nil, crgerrs.WrapError(crgerrs.ErrUnknown, fmt.Sprintf("unable to sign tx: %s", err.Error())) + } + + // set payload + payloadsToSign[i] = &rosettatypes.SigningPayload{ + AccountIdentifier: &rosettatypes.AccountIdentifier{Address: signer.String()}, + Bytes: signBytes, + SignatureType: rosettatypes.Ecdsa, + } + + // set partial signature + partialSignatures[i] = signing.SignatureV2{ + PubKey: pubKey, + Data: &signing.SingleSignatureData{}, // needs to be set to empty otherwise the codec will cry + Sequence: metadata.SignersData[i].Sequence, + } + + } + + // now we set the partial signatures in the tx + // because we will need to decode the sequence + // information of each account in a stateless way + err = builder.SetSignatures(partialSignatures...) + if err != nil { + return nil, nil, crgerrs.WrapError(crgerrs.ErrCodec, err.Error()) + } + + // finally encode the tx + txBytes, err = c.txEncode(builder.GetTx()) + if err != nil { + return nil, nil, crgerrs.WrapError(crgerrs.ErrCodec, err.Error()) + } + + return txBytes, payloadsToSign, nil +} + +// SignerData converts the given any account to signer data +func (c converter) SignerData(anyAccount *codectypes.Any) (*SignerData, error) { + var acc auth.AccountI + err := c.ir.UnpackAny(anyAccount, &acc) + if err != nil { + return nil, crgerrs.WrapError(crgerrs.ErrCodec, err.Error()) + } + + return &SignerData{ + AccountNumber: acc.GetAccountNumber(), + Sequence: acc.GetSequence(), + }, nil +} diff --git a/server/rosetta/converter_test.go b/server/rosetta/converter_test.go new file mode 100644 index 000000000000..22d466801686 --- /dev/null +++ b/server/rosetta/converter_test.go @@ -0,0 +1,348 @@ +package rosetta_test + +import ( + "encoding/hex" + "encoding/json" + "testing" + + "github.com/cosmos/cosmos-sdk/server/rosetta" + + abci "github.com/tendermint/tendermint/abci/types" + + authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + + rosettatypes "github.com/coinbase/rosetta-sdk-go/types" + "github.com/stretchr/testify/suite" + crgerrs "github.com/tendermint/cosmos-rosetta-gateway/errors" + + sdk "github.com/cosmos/cosmos-sdk/types" + authtx "github.com/cosmos/cosmos-sdk/x/auth/tx" + bank "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +type ConverterTestSuite struct { + suite.Suite + + c rosetta.Converter + unsignedTxBytes []byte + unsignedTx authsigning.Tx + + ir codectypes.InterfaceRegistry + cdc *codec.ProtoCodec + txConf client.TxConfig +} + +func (s *ConverterTestSuite) SetupTest() { + // create an unsigned tx + const unsignedTxHex = "0a8e010a8b010a1c2f636f736d6f732e62616e6b2e763162657461312e4d736753656e64126b0a2d636f736d6f733134376b6c68377468356a6b6a793361616a736a3272717668747668396d666465333777713567122d636f736d6f73316d6e7670386c786b616679346c787777617175356561653764787630647a36687767797436331a0b0a057374616b651202313612600a4c0a460a1f2f636f736d6f732e63727970746f2e736563703235366b312e5075624b657912230a21034c92046950c876f4a5cb6c7797d6eeb9ef80d67ced4d45fb62b1e859240ba9ad12020a0012100a0a0a057374616b651201311090a10f1a00" + unsignedTxBytes, err := hex.DecodeString(unsignedTxHex) + s.Require().NoError(err) + s.unsignedTxBytes = unsignedTxBytes + // instantiate converter + cdc, ir := rosetta.MakeCodec() + txConfig := authtx.NewTxConfig(cdc, authtx.DefaultSignModes) + s.c = rosetta.NewConverter(cdc, ir, txConfig) + // add utils + s.ir = ir + s.cdc = cdc + s.txConf = txConfig + // add authsigning tx + sdkTx, err := txConfig.TxDecoder()(unsignedTxBytes) + s.Require().NoError(err) + builder, err := txConfig.WrapTxBuilder(sdkTx) + s.Require().NoError(err) + + s.unsignedTx = builder.GetTx() +} + +func (s *ConverterTestSuite) TestFromRosettaOpsToTxSuccess() { + addr1 := sdk.AccAddress("address1").String() + addr2 := sdk.AccAddress("address2").String() + + msg1 := &bank.MsgSend{ + FromAddress: addr1, + ToAddress: addr2, + Amount: sdk.NewCoins(sdk.NewInt64Coin("test", 10)), + } + + msg2 := &bank.MsgSend{ + FromAddress: addr2, + ToAddress: addr1, + Amount: sdk.NewCoins(sdk.NewInt64Coin("utxo", 10)), + } + + ops, err := s.c.ToRosetta().Ops("", msg1) + s.Require().NoError(err) + + ops2, err := s.c.ToRosetta().Ops("", msg2) + s.Require().NoError(err) + + ops = append(ops, ops2...) + + tx, err := s.c.ToSDK().UnsignedTx(ops) + s.Require().NoError(err) + + getMsgs := tx.GetMsgs() + + s.Require().Equal(2, len(getMsgs)) + + s.Require().Equal(getMsgs[0], msg1) + s.Require().Equal(getMsgs[1], msg2) + +} + +func (s *ConverterTestSuite) TestFromRosettaOpsToTxErrors() { + s.Run("unrecognized op", func() { + op := &rosettatypes.Operation{ + Type: "non-existent", + } + + _, err := s.c.ToSDK().UnsignedTx([]*rosettatypes.Operation{op}) + + s.Require().ErrorIs(err, crgerrs.ErrBadArgument) + }) + + s.Run("codec type but not sdk.Msg", func() { + op := &rosettatypes.Operation{ + Type: "cosmos.crypto.ed25519.PubKey", + } + + _, err := s.c.ToSDK().UnsignedTx([]*rosettatypes.Operation{op}) + + s.Require().ErrorIs(err, crgerrs.ErrBadArgument) + + }) + +} + +func (s *ConverterTestSuite) TestMsgToMetaMetaToMsg() { + msg := &bank.MsgSend{ + FromAddress: "addr1", + ToAddress: "addr2", + Amount: sdk.NewCoins(sdk.NewInt64Coin("test", 10)), + } + msg.Route() + + meta, err := s.c.ToRosetta().Meta(msg) + s.Require().NoError(err) + + copyMsg := new(bank.MsgSend) + err = s.c.ToSDK().Msg(meta, copyMsg) + s.Require().NoError(err) + s.Require().Equal(msg, copyMsg) +} + +func (s *ConverterTestSuite) TestSignedTx() { + + s.Run("success", func() { + const payloadsJSON = `[{"hex_bytes":"82ccce81a3e4a7272249f0e25c3037a316ee2acce76eb0c25db00ef6634a4d57303b2420edfdb4c9a635ad8851fe5c7a9379b7bc2baadc7d74f7e76ac97459b5","signing_payload":{"address":"cosmos147klh7th5jkjy3aajsj2rqvhtvh9mfde37wq5g","hex_bytes":"ed574d84b095250280de38bf8c254e4a1f8755e5bd300b1f6ca2671688136ecc","account_identifier":{"address":"cosmos147klh7th5jkjy3aajsj2rqvhtvh9mfde37wq5g"},"signature_type":"ecdsa"},"public_key":{"hex_bytes":"034c92046950c876f4a5cb6c7797d6eeb9ef80d67ced4d45fb62b1e859240ba9ad","curve_type":"secp256k1"},"signature_type":"ecdsa"}]` + const expectedSignedTxHex = "0a8e010a8b010a1c2f636f736d6f732e62616e6b2e763162657461312e4d736753656e64126b0a2d636f736d6f733134376b6c68377468356a6b6a793361616a736a3272717668747668396d666465333777713567122d636f736d6f73316d6e7670386c786b616679346c787777617175356561653764787630647a36687767797436331a0b0a057374616b651202313612620a4e0a460a1f2f636f736d6f732e63727970746f2e736563703235366b312e5075624b657912230a21034c92046950c876f4a5cb6c7797d6eeb9ef80d67ced4d45fb62b1e859240ba9ad12040a02087f12100a0a0a057374616b651201311090a10f1a4082ccce81a3e4a7272249f0e25c3037a316ee2acce76eb0c25db00ef6634a4d57303b2420edfdb4c9a635ad8851fe5c7a9379b7bc2baadc7d74f7e76ac97459b5" + + var payloads []*rosettatypes.Signature + s.Require().NoError(json.Unmarshal([]byte(payloadsJSON), &payloads)) + + signedTx, err := s.c.ToSDK().SignedTx(s.unsignedTxBytes, payloads) + s.Require().NoError(err) + + signedTxHex := hex.EncodeToString(signedTx) + + s.Require().Equal(signedTxHex, expectedSignedTxHex) + }) + + s.Run("signers data and signing payloads mismatch", func() { + _, err := s.c.ToSDK().SignedTx(s.unsignedTxBytes, nil) + s.Require().ErrorIs(err, crgerrs.ErrInvalidTransaction) + }) +} + +func (s *ConverterTestSuite) TestOpsAndSigners() { + s.Run("success", func() { + addr1 := sdk.AccAddress("address1").String() + addr2 := sdk.AccAddress("address2").String() + + msg := &bank.MsgSend{ + FromAddress: addr1, + ToAddress: addr2, + Amount: sdk.NewCoins(sdk.NewInt64Coin("test", 10)), + } + + builder := s.txConf.NewTxBuilder() + s.Require().NoError(builder.SetMsgs(msg)) + + sdkTx := builder.GetTx() + txBytes, err := s.txConf.TxEncoder()(sdkTx) + s.Require().NoError(err) + + ops, signers, err := s.c.ToRosetta().OpsAndSigners(txBytes) + s.Require().NoError(err) + + s.Require().Equal(len(ops), len(sdkTx.GetMsgs())*len(sdkTx.GetSigners()), "operation number mismatch") + + s.Require().Equal(len(signers), len(sdkTx.GetSigners()), "signers number mismatch") + }) +} + +func (s *ConverterTestSuite) TestBeginEndBlockAndHashToTxType() { + const deliverTxHex = "5229A67AA008B5C5F1A0AEA77D4DEBE146297A30AAEF01777AF10FAD62DD36AB" + + deliverTxBytes, err := hex.DecodeString(deliverTxHex) + s.Require().NoError(err) + + endBlockTxHex := s.c.ToRosetta().EndBlockTxHash(deliverTxBytes) + beginBlockTxHex := s.c.ToRosetta().BeginBlockTxHash(deliverTxBytes) + + txType, hash := s.c.ToSDK().HashToTxType(deliverTxBytes) + + s.Require().Equal(rosetta.DeliverTxTx, txType) + s.Require().Equal(deliverTxBytes, hash, "deliver tx hash should not change") + + endBlockTxBytes, err := hex.DecodeString(endBlockTxHex) + s.Require().NoError(err) + + txType, hash = s.c.ToSDK().HashToTxType(endBlockTxBytes) + + s.Require().Equal(rosetta.EndBlockTx, txType) + s.Require().Equal(deliverTxBytes, hash, "end block tx hash should be equal to a block hash") + + beginBlockTxBytes, err := hex.DecodeString(beginBlockTxHex) + s.Require().NoError(err) + + txType, hash = s.c.ToSDK().HashToTxType(beginBlockTxBytes) + + s.Require().Equal(rosetta.BeginBlockTx, txType) + s.Require().Equal(deliverTxBytes, hash, "begin block tx hash should be equal to a block hash") + + txType, hash = s.c.ToSDK().HashToTxType([]byte("invalid")) + + s.Require().Equal(rosetta.UnrecognizedTx, txType) + s.Require().Nil(hash) + + txType, hash = s.c.ToSDK().HashToTxType(append([]byte{0x3}, deliverTxBytes...)) + s.Require().Equal(rosetta.UnrecognizedTx, txType) + s.Require().Nil(hash) +} + +func (s *ConverterTestSuite) TestSigningComponents() { + s.Run("invalid metadata coins", func() { + _, _, err := s.c.ToRosetta().SigningComponents(nil, &rosetta.ConstructionMetadata{GasPrice: "invalid"}, nil) + s.Require().ErrorIs(err, crgerrs.ErrBadArgument) + }) + + s.Run("length signers data does not match signers", func() { + _, _, err := s.c.ToRosetta().SigningComponents(s.unsignedTx, &rosetta.ConstructionMetadata{GasPrice: "10stake"}, nil) + s.Require().ErrorIs(err, crgerrs.ErrBadArgument) + }) + + s.Run("length pub keys does not match signers", func() { + _, _, err := s.c.ToRosetta().SigningComponents( + s.unsignedTx, + &rosetta.ConstructionMetadata{GasPrice: "10stake", SignersData: []*rosetta.SignerData{ + { + AccountNumber: 0, + Sequence: 0, + }, + }}, + nil) + s.Require().ErrorIs(err, crgerrs.ErrBadArgument) + }) + + s.Run("ros pub key is valid but not the one we expect", func() { + validButUnexpected, err := hex.DecodeString("030da9096a40eb1d6c25f1e26e9cbf8941fc84b8f4dc509c8df5e62a29ab8f2415") + s.Require().NoError(err) + + _, _, err = s.c.ToRosetta().SigningComponents( + s.unsignedTx, + &rosetta.ConstructionMetadata{GasPrice: "10stake", SignersData: []*rosetta.SignerData{ + { + AccountNumber: 0, + Sequence: 0, + }, + }}, + []*rosettatypes.PublicKey{ + { + Bytes: validButUnexpected, + CurveType: rosettatypes.Secp256k1, + }, + }) + s.Require().ErrorIs(err, crgerrs.ErrBadArgument) + }) + + s.Run("success", func() { + expectedPubKey, err := hex.DecodeString("034c92046950c876f4a5cb6c7797d6eeb9ef80d67ced4d45fb62b1e859240ba9ad") + s.Require().NoError(err) + + _, _, err = s.c.ToRosetta().SigningComponents( + s.unsignedTx, + &rosetta.ConstructionMetadata{GasPrice: "10stake", SignersData: []*rosetta.SignerData{ + { + AccountNumber: 0, + Sequence: 0, + }, + }}, + []*rosettatypes.PublicKey{ + { + Bytes: expectedPubKey, + CurveType: rosettatypes.Secp256k1, + }, + }) + s.Require().NoError(err) + }) + +} + +func (s *ConverterTestSuite) TestBalanceOps() { + s.Run("not a balance op", func() { + notBalanceOp := abci.Event{ + Type: "not-a-balance-op", + } + + ops := s.c.ToRosetta().BalanceOps("", []abci.Event{notBalanceOp}) + s.Len(ops, 0, "expected no balance ops") + }) + + s.Run("multiple balance ops from 2 multicoins event", func() { + subBalanceOp := bank.NewCoinSpentEvent( + sdk.AccAddress("test"), + sdk.NewCoins(sdk.NewInt64Coin("test", 10), sdk.NewInt64Coin("utxo", 10)), + ) + + addBalanceOp := bank.NewCoinReceivedEvent( + sdk.AccAddress("test"), + sdk.NewCoins(sdk.NewInt64Coin("test", 10), sdk.NewInt64Coin("utxo", 10)), + ) + + ops := s.c.ToRosetta().BalanceOps("", []abci.Event{(abci.Event)(subBalanceOp), (abci.Event)(addBalanceOp)}) + s.Len(ops, 4) + }) + + s.Run("spec broken", func() { + s.Require().Panics(func() { + specBrokenSub := abci.Event{ + Type: bank.EventTypeCoinSpent, + } + _ = s.c.ToRosetta().BalanceOps("", []abci.Event{specBrokenSub}) + }) + + s.Require().Panics(func() { + specBrokenSub := abci.Event{ + Type: bank.EventTypeCoinBurn, + } + _ = s.c.ToRosetta().BalanceOps("", []abci.Event{specBrokenSub}) + }) + + s.Require().Panics(func() { + specBrokenSub := abci.Event{ + Type: bank.EventTypeCoinReceived, + } + _ = s.c.ToRosetta().BalanceOps("", []abci.Event{specBrokenSub}) + }) + }) +} + +func TestConverterTestSuite(t *testing.T) { + suite.Run(t, new(ConverterTestSuite)) +} diff --git a/server/rosetta/types.go b/server/rosetta/types.go index 626e7470ab91..0d1eada89272 100644 --- a/server/rosetta/types.go +++ b/server/rosetta/types.go @@ -1,41 +1,104 @@ package rosetta import ( - "github.com/coinbase/rosetta-sdk-go/types" - - sdk "github.com/cosmos/cosmos-sdk/types" + "crypto/sha256" ) // statuses const ( - StatusSuccess = "Success" - StatusReverted = "Reverted" - StageSynced = "synced" - StageSyncing = "syncing" + StatusTxSuccess = "Success" + StatusTxReverted = "Reverted" + StatusPeerSynced = "synced" + StatusPeerSyncing = "syncing" ) -// misc +// In rosetta all state transitions must be represented as transactions +// since in tendermint begin block and end block are state transitions +// which are not represented as transactions we mock only the balance changes +// happening at those levels as transactions. (check BeginBlockTxHash for more info) const ( - Log = "log" + DeliverTxSize = sha256.Size + BeginEndBlockTxSize = DeliverTxSize + 1 + EndBlockHashStart = 0x0 + BeginBlockHashStart = 0x1 ) -// operations const ( - OperationFee = "fee" + // BurnerAddressIdentifier mocks the account identifier of a burner address + // all coins burned in the sdk will be sent to this identifier, which per sdk.AccAddress + // design we will never be able to query (as of now). + // Rosetta does not understand supply contraction. + BurnerAddressIdentifier = "burner" ) -// options +// TransactionType is used to distinguish if a rosetta provided hash +// represents endblock, beginblock or deliver tx +type TransactionType int + const ( - OptionAccountNumber = "account_number" - OptionAddress = "address" - OptionChainID = "chain_id" - OptionSequence = "sequence" - OptionMemo = "memo" - OptionGas = "gas" + UnrecognizedTx TransactionType = iota + BeginBlockTx + EndBlockTx + DeliverTxTx ) -type Msg interface { - sdk.Msg - ToOperations(withStatus, hasError bool) []*types.Operation - FromOperations(ops []*types.Operation) (sdk.Msg, error) +// metadata options + +// misc +const ( + Log = "log" +) + +// ConstructionPreprocessMetadata is used to represent +// the metadata rosetta can provide during preprocess options +type ConstructionPreprocessMetadata struct { + Memo string `json:"memo"` + GasLimit uint64 `json:"gas_limit"` + GasPrice string `json:"gas_price"` +} + +func (c *ConstructionPreprocessMetadata) FromMetadata(meta map[string]interface{}) error { + return unmarshalMetadata(meta, c) +} + +// PreprocessOperationsOptionsResponse is the structured metadata options returned by the preprocess operations endpoint +type PreprocessOperationsOptionsResponse struct { + ExpectedSigners []string `json:"expected_signers"` + Memo string `json:"memo"` + GasLimit uint64 `json:"gas_limit"` + GasPrice string `json:"gas_price"` +} + +func (c PreprocessOperationsOptionsResponse) ToMetadata() (map[string]interface{}, error) { + return marshalMetadata(c) +} + +func (c *PreprocessOperationsOptionsResponse) FromMetadata(meta map[string]interface{}) error { + return unmarshalMetadata(meta, c) +} + +// SignerData contains information on the signers when the request +// is being created, used to populate the account information +type SignerData struct { + AccountNumber uint64 `json:"account_number"` + Sequence uint64 `json:"sequence"` +} + +// ConstructionMetadata are the metadata options used to +// construct a transaction. It is returned by ConstructionMetadataFromOptions +// and fed to ConstructionPayload to process the bytes to sign. +type ConstructionMetadata struct { + ChainID string `json:"chain_id"` + SignersData []*SignerData `json:"signer_data"` + GasLimit uint64 `json:"gas_limit"` + GasPrice string `json:"gas_price"` + Memo string `json:"memo"` +} + +func (c ConstructionMetadata) ToMetadata() (map[string]interface{}, error) { + return marshalMetadata(c) +} + +func (c *ConstructionMetadata) FromMetadata(meta map[string]interface{}) error { + return unmarshalMetadata(meta, c) } diff --git a/server/rosetta/util.go b/server/rosetta/util.go index 29e4a1587dc2..43626b5ed351 100644 --- a/server/rosetta/util.go +++ b/server/rosetta/util.go @@ -1,112 +1,43 @@ package rosetta import ( - "fmt" + "encoding/json" + "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" + crgerrs "github.com/tendermint/cosmos-rosetta-gateway/errors" ) -// 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 +// timeToMilliseconds converts time to milliseconds timestamp +func timeToMilliseconds(t time.Time) int64 { + return t.UnixNano() / (int64(time.Millisecond) / int64(time.Nanosecond)) } -func tmTxToSdkTx(decode sdk.TxDecoder, tx tmtypes.Tx) (sdk.Tx, error) { - sdkTx, err := decode(tx) +// unmarshalMetadata unmarshals the given meta to the target +func unmarshalMetadata(meta map[string]interface{}, target interface{}) error { + b, err := json.Marshal(meta) 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") + return crgerrs.WrapError(crgerrs.ErrCodec, err.Error()) } - gasNum, ok := req.Metadata[OptionGas] - if !ok { - return nil, fmt.Errorf("gas metadata was not provided") + err = json.Unmarshal(b, target) + if err != nil { + return crgerrs.WrapError(crgerrs.ErrCodec, err.Error()) } - gasF64, ok := gasNum.(float64) - if !ok { - return nil, fmt.Errorf("invalid gas value") - } + return nil +} - memo, ok := req.Metadata[OptionMemo] - if !ok { - memo = "" +// marshalMetadata marshals the given interface to map[string]interface{} +func marshalMetadata(o interface{}) (meta map[string]interface{}, err error) { + b, err := json.Marshal(o) + if err != nil { + return nil, crgerrs.WrapError(crgerrs.ErrCodec, err.Error()) } - - memoStr, ok := memo.(string) - if !ok { - return nil, fmt.Errorf("invalid memo") + meta = make(map[string]interface{}) + err = json.Unmarshal(b, &meta) + if err != nil { + return nil, err } - return &PayloadReqMetadata{ - ChainID: chainID, - Sequence: uint64(seqNum), - AccountNumber: uint64(accNum), - Gas: uint64(gasF64), - Memo: memoStr, - }, nil + return } diff --git a/types/codec.go b/types/codec.go index 152bb9d724f5..8123fc7d51a4 100644 --- a/types/codec.go +++ b/types/codec.go @@ -5,6 +5,13 @@ import ( "github.com/cosmos/cosmos-sdk/codec/types" ) +const ( + // MsgInterfaceProtoName defines the protobuf name of the cosmos Msg interface + MsgInterfaceProtoName = "cosmos.base.v1beta1.Msg" + // ServiceMsgInterfaceProtoName defines the protobuf name of the cosmos MsgRequest interface + ServiceMsgInterfaceProtoName = "cosmos.base.v1beta1.ServiceMsg" +) + // RegisterLegacyAminoCodec registers the sdk message type. func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { cdc.RegisterInterface((*Msg)(nil), nil) @@ -13,8 +20,8 @@ func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { // RegisterInterfaces registers the sdk message type. func RegisterInterfaces(registry types.InterfaceRegistry) { - registry.RegisterInterface("cosmos.base.v1beta1.Msg", (*Msg)(nil)) + registry.RegisterInterface(MsgInterfaceProtoName, (*Msg)(nil)) // the interface name for MsgRequest is ServiceMsg because this is most useful for clients // to understand - it will be the way for clients to introspect on available Msg service methods - registry.RegisterInterface("cosmos.base.v1beta1.ServiceMsg", (*MsgRequest)(nil)) + registry.RegisterInterface(ServiceMsgInterfaceProtoName, (*MsgRequest)(nil)) } diff --git a/x/bank/types/msgs.go b/x/bank/types/msgs.go index dd41975468ca..22fdc30b3886 100644 --- a/x/bank/types/msgs.go +++ b/x/bank/types/msgs.go @@ -1,13 +1,6 @@ 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" ) @@ -69,83 +62,6 @@ 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 62c8bfc2abbb..8dc72081e9ac 100644 --- a/x/distribution/types/msg.go +++ b/x/distribution/types/msg.go @@ -2,12 +2,6 @@ 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" ) @@ -96,50 +90,6 @@ 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/staking/types/msg.go b/x/staking/types/msg.go index d1da12386ae1..e397046e5779 100644 --- a/x/staking/types/msg.go +++ b/x/staking/types/msg.go @@ -2,17 +2,9 @@ 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" ) @@ -264,90 +256,6 @@ 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( @@ -403,103 +311,6 @@ 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 { @@ -547,88 +358,3 @@ 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 -} From 3954c244b641e68b8a1a2159ba8fb45b9a0b03c9 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Thu, 11 Mar 2021 15:17:43 +0000 Subject: [PATCH 181/214] keyring: update documentation (#8839) * keyring: update documentation * Update docs/run-node/keyring.md Co-authored-by: Barrie Byron * Update docs/run-node/keyring.md Co-authored-by: Barrie Byron Co-authored-by: Barrie Byron Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- client/flags/flags.go | 2 +- docs/run-node/keyring.md | 21 +++++++++++++++------ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/client/flags/flags.go b/client/flags/flags.go index 1afb55b46733..62e4b15bca45 100644 --- a/client/flags/flags.go +++ b/client/flags/flags.go @@ -110,7 +110,7 @@ func AddTxFlagsToCmd(cmd *cobra.Command) { cmd.Flags().Bool(FlagGenerateOnly, false, "Build an unsigned transaction and write it to STDOUT (when enabled, the local Keybase is not accessible)") cmd.Flags().Bool(FlagOffline, false, "Offline mode (does not allow any online functionality") cmd.Flags().BoolP(FlagSkipConfirmation, "y", false, "Skip tx broadcasting prompt confirmation") - cmd.Flags().String(FlagKeyringBackend, DefaultKeyringBackend, "Select keyring's backend (os|file|kwallet|pass|test)") + cmd.Flags().String(FlagKeyringBackend, DefaultKeyringBackend, "Select keyring's backend (os|file|kwallet|pass|test|memory)") 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") diff --git a/docs/run-node/keyring.md b/docs/run-node/keyring.md index 61636f27fd47..4051bfd5ed8c 100644 --- a/docs/run-node/keyring.md +++ b/docs/run-node/keyring.md @@ -38,6 +38,8 @@ client. designed to meet users' most common needs and provide them with a comfortable experience without compromising on security. +The recommended backends for headless environments are `file` and `pass`. + ### The `file` backend The `file` backend more closely resembles the keybase implementation used prior to @@ -82,12 +84,6 @@ $ pass init Replace `` with your GPG key ID. You can use your personal GPG key or an alternative one you may want to use specifically to encrypt the password store. -### The `test` backend - -The `test` backend is a password-less variation of the `file` backend. Keys are stored -unencrypted on disk. This backend is meant for testing purposes only and **should never be used -in production environments**. - ### The `kwallet` backend The `kwallet` backend uses `KDE Wallet Manager`, which comes installed by default on the @@ -95,6 +91,19 @@ GNU/Linux distributions that ships KDE as default desktop environment. Please re [KWallet Handbook](https://docs.kde.org/stable5/en/kdeutils/kwallet5/index.html) for more information. +### The `test` backend + +The `test` backend is a password-less variation of the `file` backend. Keys are stored +unencrypted on disk. + +**Provided for testing purposes only. The `test` backend is not recommended for use in production environments**. + +### The `memory` backend + +The `memory` backend stores keys in memory. The keys are immediately deleted after the program has exited. + +**Provided for testing purposes only. The `memory` backend is not recommended for use in production environments**. + ## Adding keys to the keyring ::: warning From b9f3db1be8b9978094265407396fc864e19c00cd Mon Sep 17 00:00:00 2001 From: Emmanuel T Odeke Date: Thu, 11 Mar 2021 07:59:13 -0800 Subject: [PATCH 182/214] all: skip noisy/faulty benchmarks + add b.ReportAllocs for every benchmark (#8856) * Skips very noisy benchmarks that end up running only for b.N=1 because their entire time is spent in setup, and varying parameters doesn't change much given that the number of stores is what dominates the expense. To ensure we can provide reliable benchmarks, progressively for the project, skip these until there is a proper re-work of what the benchmarks need to do * Previously sub-benchmarks: b.Run(...) did not b.ReportAllocs() due to a faulty assumption that invoking b.ReportAllocs() at the top would be inherited by all sub-benchmarks. This change fixes that Fixes #8779 Fixes #8855 Co-authored-by: Alessio Treglia Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- crypto/armor_test.go | 3 +-- crypto/types/compact_bit_array_test.go | 1 + store/rootmulti/store_test.go | 4 ++++ types/coin_benchmark_test.go | 2 ++ x/auth/ante/sigverify_benchmark_test.go | 2 ++ x/auth/keeper/keeper_bench_test.go | 1 + x/bank/bench_test.go | 1 + 7 files changed, 12 insertions(+), 2 deletions(-) diff --git a/crypto/armor_test.go b/crypto/armor_test.go index fb80b5266ab8..8c7c0c5257d7 100644 --- a/crypto/armor_test.go +++ b/crypto/armor_test.go @@ -158,12 +158,11 @@ func TestUnarmorInfoBytesErrors(t *testing.T) { } func BenchmarkBcryptGenerateFromPassword(b *testing.B) { - b.ReportAllocs() - passphrase := []byte("passphrase") for securityParam := 9; securityParam < 16; securityParam++ { param := securityParam b.Run(fmt.Sprintf("benchmark-security-param-%d", param), func(b *testing.B) { + b.ReportAllocs() saltBytes := tmcrypto.CRandBytes(16) b.ResetTimer() for i := 0; i < b.N; i++ { diff --git a/crypto/types/compact_bit_array_test.go b/crypto/types/compact_bit_array_test.go index be4b87a23c20..44f97d6f4013 100644 --- a/crypto/types/compact_bit_array_test.go +++ b/crypto/types/compact_bit_array_test.go @@ -233,6 +233,7 @@ func BenchmarkNumTrueBitsBefore(b *testing.B) { ba, _ := randCompactBitArray(100) b.Run("new", func(b *testing.B) { + b.ReportAllocs() for i := 0; i < b.N; i++ { ba.NumTrueBitsBefore(90) } diff --git a/store/rootmulti/store_test.go b/store/rootmulti/store_test.go index eafc0d6bb817..4b4028c27237 100644 --- a/store/rootmulti/store_test.go +++ b/store/rootmulti/store_test.go @@ -689,6 +689,8 @@ func BenchmarkMultistoreSnapshotRestore1M(b *testing.B) { } func benchmarkMultistoreSnapshot(b *testing.B, stores uint8, storeKeys uint64) { + b.Skip("Noisy with slow setup time, please see https://github.com/cosmos/cosmos-sdk/issues/8855.") + b.ReportAllocs() b.StopTimer() source := newMultiStoreWithGeneratedData(dbm.NewMemDB(), stores, storeKeys) @@ -717,6 +719,8 @@ func benchmarkMultistoreSnapshot(b *testing.B, stores uint8, storeKeys uint64) { } func benchmarkMultistoreSnapshotRestore(b *testing.B, stores uint8, storeKeys uint64) { + b.Skip("Noisy with slow setup time, please see https://github.com/cosmos/cosmos-sdk/issues/8855.") + b.ReportAllocs() b.StopTimer() source := newMultiStoreWithGeneratedData(dbm.NewMemDB(), stores, storeKeys) diff --git a/types/coin_benchmark_test.go b/types/coin_benchmark_test.go index c6e040112115..8c8088923e4b 100644 --- a/types/coin_benchmark_test.go +++ b/types/coin_benchmark_test.go @@ -13,6 +13,7 @@ func BenchmarkCoinsAdditionIntersect(b *testing.B) { b.ReportAllocs() benchmarkingFunc := func(numCoinsA int, numCoinsB int) func(b *testing.B) { return func(b *testing.B) { + b.ReportAllocs() coinsA := Coins(make([]Coin, numCoinsA)) coinsB := Coins(make([]Coin, numCoinsB)) @@ -43,6 +44,7 @@ func BenchmarkCoinsAdditionNoIntersect(b *testing.B) { b.ReportAllocs() benchmarkingFunc := func(numCoinsA int, numCoinsB int) func(b *testing.B) { return func(b *testing.B) { + b.ReportAllocs() coinsA := Coins(make([]Coin, numCoinsA)) coinsB := Coins(make([]Coin, numCoinsB)) diff --git a/x/auth/ante/sigverify_benchmark_test.go b/x/auth/ante/sigverify_benchmark_test.go index 683cc261a9ff..56e596fa6b55 100644 --- a/x/auth/ante/sigverify_benchmark_test.go +++ b/x/auth/ante/sigverify_benchmark_test.go @@ -27,6 +27,7 @@ func BenchmarkSig(b *testing.B) { b.ResetTimer() b.Run("secp256k1", func(b *testing.B) { + b.ReportAllocs() for i := 0; i < b.N; i++ { ok := pkK.VerifySignature(msg, sigK) require.True(ok) @@ -34,6 +35,7 @@ func BenchmarkSig(b *testing.B) { }) b.Run("secp256r1", func(b *testing.B) { + b.ReportAllocs() for i := 0; i < b.N; i++ { ok := pkR.VerifySignature(msg, sigR) require.True(ok) diff --git a/x/auth/keeper/keeper_bench_test.go b/x/auth/keeper/keeper_bench_test.go index 1a18dff84557..3e15783d9605 100644 --- a/x/auth/keeper/keeper_bench_test.go +++ b/x/auth/keeper/keeper_bench_test.go @@ -26,6 +26,7 @@ func BenchmarkAccountMapperGetAccountFound(b *testing.B) { } func BenchmarkAccountMapperSetAccount(b *testing.B) { + b.ReportAllocs() app, ctx := createTestApp(false) b.ResetTimer() diff --git a/x/bank/bench_test.go b/x/bank/bench_test.go index c7da72c199dd..7de0682ee537 100644 --- a/x/bank/bench_test.go +++ b/x/bank/bench_test.go @@ -60,6 +60,7 @@ func BenchmarkOneBankSendTxPerBlock(b *testing.B) { } func BenchmarkOneBankMultiSendTxPerBlock(b *testing.B) { + b.ReportAllocs() // Add an account at genesis acc := authtypes.BaseAccount{ Address: addr1.String(), From 0711e161739681d925fbc2fbcf986371e9626f97 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Fri, 12 Mar 2021 13:24:07 +0100 Subject: [PATCH 183/214] Any: update and test String method (#8854) * Any: update and test String method * remove commented code * disable Any proto String() and GoString() generation * fix linter issues --- codec/types/any.go | 25 ++++++++ codec/types/any.pb.go | 67 ++++----------------- codec/types/any_internal_test.go | 12 ++++ third_party/proto/google/protobuf/any.proto | 3 + 4 files changed, 52 insertions(+), 55 deletions(-) diff --git a/codec/types/any.go b/codec/types/any.go index 1d9d34ff2a22..14087efa8fd6 100644 --- a/codec/types/any.go +++ b/codec/types/any.go @@ -1,6 +1,8 @@ package types import ( + fmt "fmt" + "github.com/gogo/protobuf/proto" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" @@ -116,3 +118,26 @@ func (any *Any) pack(x proto.Message) error { func (any *Any) GetCachedValue() interface{} { return any.cachedValue } + +// GoString returns a string representing valid go code to reproduce the current state of +// the struct. +func (any *Any) GoString() string { + if any == nil { + return "nil" + } + extra := "" + if any.XXX_unrecognized != nil { + extra = fmt.Sprintf(",\n XXX_unrecognized: %#v,\n", any.XXX_unrecognized) + } + return fmt.Sprintf("&Any{TypeUrl: %#v,\n Value: %#v%s\n}", + any.TypeUrl, any.Value, extra) +} + +// String implements the stringer interface +func (any *Any) String() string { + if any == nil { + return "nil" + } + return fmt.Sprintf("&Any{TypeUrl:%v,Value:%v,XXX_unrecognized:%v}", + any.TypeUrl, any.Value, any.XXX_unrecognized) +} diff --git a/codec/types/any.pb.go b/codec/types/any.pb.go index 94cf80216287..cb904a5af43c 100644 --- a/codec/types/any.pb.go +++ b/codec/types/any.pb.go @@ -11,8 +11,6 @@ import ( io "io" math "math" math_bits "math/bits" - reflect "reflect" - strings "strings" ) // Reference imports to suppress errors if they are not otherwise used. @@ -82,22 +80,23 @@ func init() { func init() { proto.RegisterFile("google/protobuf/any.proto", fileDescriptor_b53526c13ae22eb4) } var fileDescriptor_b53526c13ae22eb4 = []byte{ - // 235 bytes of a gzipped FileDescriptorProto + // 248 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4c, 0xcf, 0xcf, 0x4f, 0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x4f, 0xcc, 0xab, 0xd4, 0x03, 0x73, 0x84, 0xf8, 0x21, 0x52, 0x7a, 0x30, 0x29, 0x29, 0x91, 0xf4, 0xfc, 0xf4, 0x7c, 0x30, - 0x4f, 0x1f, 0xc4, 0x82, 0x48, 0x28, 0xd9, 0x70, 0x31, 0x3b, 0xe6, 0x55, 0x0a, 0x49, 0x72, 0x71, + 0x4f, 0x1f, 0xc4, 0x82, 0x48, 0x28, 0x79, 0x70, 0x31, 0x3b, 0xe6, 0x55, 0x0a, 0x49, 0x72, 0x71, 0x94, 0x54, 0x16, 0xa4, 0xc6, 0x97, 0x16, 0xe5, 0x48, 0x30, 0x2a, 0x30, 0x6a, 0x70, 0x06, 0xb1, 0x83, 0xf8, 0xa1, 0x45, 0x39, 0x42, 0x22, 0x5c, 0xac, 0x65, 0x89, 0x39, 0xa5, 0xa9, 0x12, 0x4c, - 0x0a, 0x8c, 0x1a, 0x3c, 0x41, 0x10, 0x8e, 0x15, 0xcb, 0x87, 0x85, 0xf2, 0x0c, 0x4e, 0xcd, 0x8c, - 0x37, 0x1e, 0xca, 0x31, 0x7c, 0x78, 0x28, 0xc7, 0xf8, 0xe3, 0xa1, 0x1c, 0x63, 0xc3, 0x23, 0x39, - 0xc6, 0x15, 0x8f, 0xe4, 0x18, 0x4f, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x48, 0x8e, 0xf1, 0xc1, 0x23, - 0x39, 0xc6, 0x17, 0x8f, 0xe4, 0x18, 0x3e, 0x80, 0xc4, 0x1f, 0xcb, 0x31, 0x1e, 0x78, 0x2c, 0xc7, - 0x70, 0xe2, 0xb1, 0x1c, 0x23, 0x97, 0x70, 0x72, 0x7e, 0xae, 0x1e, 0x9a, 0xfb, 0x9c, 0x38, 0x1c, - 0xf3, 0x2a, 0x03, 0x40, 0x9c, 0x00, 0xc6, 0x28, 0x56, 0x90, 0xe5, 0xc5, 0x8b, 0x98, 0x98, 0xdd, - 0x03, 0x9c, 0x56, 0x31, 0xc9, 0xb9, 0x43, 0x94, 0x06, 0x40, 0x95, 0xea, 0x85, 0xa7, 0xe6, 0xe4, - 0x78, 0xe7, 0xe5, 0x97, 0xe7, 0x85, 0x80, 0x94, 0x25, 0xb1, 0x81, 0xcd, 0x30, 0x06, 0x04, 0x00, - 0x00, 0xff, 0xff, 0xe6, 0xfb, 0xa0, 0x21, 0x0e, 0x01, 0x00, 0x00, + 0x0a, 0x8c, 0x1a, 0x3c, 0x41, 0x10, 0x8e, 0x95, 0xc0, 0x8c, 0x05, 0xf2, 0x0c, 0x1b, 0x16, 0xc8, + 0x33, 0x7c, 0x58, 0x28, 0xcf, 0xd0, 0x70, 0x47, 0x81, 0xc1, 0xa9, 0x99, 0xf1, 0xc6, 0x43, 0x39, + 0x86, 0x0f, 0x0f, 0xe5, 0x18, 0x7f, 0x3c, 0x94, 0x63, 0x6c, 0x78, 0x24, 0xc7, 0xb8, 0xe2, 0x91, + 0x1c, 0xe3, 0x89, 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0xf8, 0xe2, + 0x91, 0x1c, 0xc3, 0x07, 0x90, 0xf8, 0x63, 0x39, 0xc6, 0x03, 0x8f, 0xe5, 0x18, 0x4e, 0x3c, 0x96, + 0x63, 0xe4, 0x12, 0x4e, 0xce, 0xcf, 0xd5, 0x43, 0x73, 0xab, 0x13, 0x87, 0x63, 0x5e, 0x65, 0x00, + 0x88, 0x13, 0xc0, 0x18, 0xc5, 0x0a, 0x72, 0x48, 0xf1, 0x22, 0x26, 0x66, 0xf7, 0x00, 0xa7, 0x55, + 0x4c, 0x72, 0xee, 0x10, 0xa5, 0x01, 0x50, 0xa5, 0x7a, 0xe1, 0xa9, 0x39, 0x39, 0xde, 0x79, 0xf9, + 0xe5, 0x79, 0x21, 0x20, 0x65, 0x49, 0x6c, 0x60, 0x33, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, + 0x4d, 0x91, 0x00, 0xa0, 0x1a, 0x01, 0x00, 0x00, } func (this *Any) Compare(that interface{}) int { @@ -169,28 +168,6 @@ func (this *Any) Equal(that interface{}) bool { } return true } -func (this *Any) GoString() string { - if this == nil { - return "nil" - } - s := make([]string, 0, 6) - s = append(s, "&types.Any{") - s = append(s, "TypeUrl: "+fmt.Sprintf("%#v", this.TypeUrl)+",\n") - s = append(s, "Value: "+fmt.Sprintf("%#v", this.Value)+",\n") - if this.XXX_unrecognized != nil { - s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n") - } - s = append(s, "}") - return strings.Join(s, "") -} -func valueToGoStringAny(v interface{}, typ string) string { - rv := reflect.ValueOf(v) - if rv.IsNil() { - return "nil" - } - pv := reflect.Indirect(rv).Interface() - return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv) -} func (m *Any) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -355,26 +332,6 @@ func sovAny(x uint64) (n int) { func sozAny(x uint64) (n int) { return sovAny(uint64((x << 1) ^ uint64((int64(x) >> 63)))) } -func (this *Any) String() string { - if this == nil { - return "nil" - } - s := strings.Join([]string{`&Any{`, - `TypeUrl:` + fmt.Sprintf("%v", this.TypeUrl) + `,`, - `Value:` + fmt.Sprintf("%v", this.Value) + `,`, - `XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`, - `}`, - }, "") - return s -} -func valueToStringAny(v interface{}) string { - rv := reflect.ValueOf(v) - if rv.IsNil() { - return "nil" - } - pv := reflect.Indirect(rv).Interface() - return fmt.Sprintf("*%v", pv) -} func (m *Any) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/codec/types/any_internal_test.go b/codec/types/any_internal_test.go index fda205f591ca..b3e847965d59 100644 --- a/codec/types/any_internal_test.go +++ b/codec/types/any_internal_test.go @@ -51,3 +51,15 @@ func TestAnyPackUnpack(t *testing.T) { require.NoError(t, err) require.Equal(t, spot, animal) } + +func TestString(t *testing.T) { + require := require.New(t) + spot := &Dog{Name: "Spot"} + any, err := NewAnyWithValue(spot) + require.NoError(err) + + require.Equal("&Any{TypeUrl:/tests/dog,Value:[10 4 83 112 111 116],XXX_unrecognized:[]}", any.String()) + require.Equal(`&Any{TypeUrl: "/tests/dog", + Value: []byte{0xa, 0x4, 0x53, 0x70, 0x6f, 0x74} +}`, any.GoString()) +} diff --git a/third_party/proto/google/protobuf/any.proto b/third_party/proto/google/protobuf/any.proto index 1431810ea45f..58b511583a8b 100644 --- a/third_party/proto/google/protobuf/any.proto +++ b/third_party/proto/google/protobuf/any.proto @@ -156,6 +156,9 @@ message Any { bytes value = 2; option (gogoproto.typedecl) = false; + option (gogoproto.goproto_stringer) = false; + option (gogoproto.gostring) = false; + option (gogoproto.stringer) = false; } option (gogoproto.goproto_registration) = false; From adf5f625c1bc5fb1c763d5345c48c4d607be3405 Mon Sep 17 00:00:00 2001 From: MD Aleem <72057206+aleem1314@users.noreply.github.com> Date: Sat, 13 Mar 2021 00:17:10 +0530 Subject: [PATCH 184/214] add orderBy parameter to TxsByEvents (#8815) Co-authored-by: Alessio Treglia Co-authored-by: Jonathan Gimeno --- CHANGELOG.md | 1 + docs/core/proto-docs.md | 15 +++ proto/cosmos/tx/v1beta1/service.proto | 12 ++ types/tx/service.pb.go | 184 +++++++++++++++++++------- x/auth/tx/service.go | 14 +- x/auth/tx/service_test.go | 26 ++++ 6 files changed, 203 insertions(+), 49 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f878eabadf4a..24048f26493a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -80,6 +80,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (x/auth) [\#8522](https://github.com/cosmos/cosmos-sdk/pull/8522) Allow to query all stored accounts * (x/ibc) [\#7949](https://github.com/cosmos/cosmos-sdk/issues/7949) Standardized channel `Acknowledgement` moved to its own file. Codec registration redundancy removed. * (crypto/types) [\#8600](https://github.com/cosmos/cosmos-sdk/pull/8600) `CompactBitArray`: optimize the `NumTrueBitsBefore` method and add an `Equal` method. +* (grpc) [\#8815](https://github.com/cosmos/cosmos-sdk/pull/8815) Add orderBy parameter to `TxsByEvents` endpoint. ### Bug Fixes diff --git a/docs/core/proto-docs.md b/docs/core/proto-docs.md index 9e985a6a6a1b..4d493b27c4ab 100644 --- a/docs/core/proto-docs.md +++ b/docs/core/proto-docs.md @@ -515,6 +515,7 @@ - [SimulateResponse](#cosmos.tx.v1beta1.SimulateResponse) - [BroadcastMode](#cosmos.tx.v1beta1.BroadcastMode) + - [OrderBy](#cosmos.tx.v1beta1.OrderBy) - [Service](#cosmos.tx.v1beta1.Service) @@ -7221,6 +7222,7 @@ RPC method. | ----- | ---- | ----- | ----------- | | `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. | +| `order_by` | [OrderBy](#cosmos.tx.v1beta1.OrderBy) | | | @@ -7293,6 +7295,19 @@ BroadcastMode specifies the broadcast mode for the TxService.Broadcast RPC metho | BROADCAST_MODE_ASYNC | 3 | BROADCAST_MODE_ASYNC defines a tx broadcasting mode where the client returns immediately. | + + + +### OrderBy +OrderBy defines the sorting order + +| Name | Number | Description | +| ---- | ------ | ----------- | +| ORDER_BY_UNSPECIFIED | 0 | ORDER_BY_UNSPECIFIED specifies an unknown sorting order. OrderBy defaults to ASC in this case. | +| ORDER_BY_ASC | 1 | ORDER_BY_ASC defines ascending order | +| ORDER_BY_DESC | 2 | ORDER_BY_DESC defines descending order | + + diff --git a/proto/cosmos/tx/v1beta1/service.proto b/proto/cosmos/tx/v1beta1/service.proto index 59df75bab12b..25214c4374e9 100644 --- a/proto/cosmos/tx/v1beta1/service.proto +++ b/proto/cosmos/tx/v1beta1/service.proto @@ -7,6 +7,7 @@ import "cosmos/tx/v1beta1/tx.proto"; import "gogoproto/gogo.proto"; import "cosmos/base/query/v1beta1/pagination.proto"; +option (gogoproto.goproto_registration) = true; option go_package = "github.com/cosmos/cosmos-sdk/types/tx"; // Service defines a gRPC service for interacting with transactions. @@ -42,6 +43,17 @@ message GetTxsEventRequest { repeated string events = 1; // pagination defines an pagination for the request. cosmos.base.query.v1beta1.PageRequest pagination = 2; + OrderBy order_by = 3; +} + +// OrderBy defines the sorting order +enum OrderBy { + // ORDER_BY_UNSPECIFIED specifies an unknown sorting order. OrderBy defaults to ASC in this case. + ORDER_BY_UNSPECIFIED = 0; + // ORDER_BY_ASC defines ascending order + ORDER_BY_ASC = 1; + // ORDER_BY_DESC defines descending order + ORDER_BY_DESC = 2; } // GetTxsEventResponse is the response type for the Service.TxsByEvents diff --git a/types/tx/service.pb.go b/types/tx/service.pb.go index f01a60fe52a9..f0eabcaca9a4 100644 --- a/types/tx/service.pb.go +++ b/types/tx/service.pb.go @@ -11,6 +11,7 @@ import ( _ "github.com/gogo/protobuf/gogoproto" grpc1 "github.com/gogo/protobuf/grpc" proto "github.com/gogo/protobuf/proto" + golang_proto "github.com/golang/protobuf/proto" _ "google.golang.org/genproto/googleapis/api/annotations" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" @@ -22,6 +23,7 @@ import ( // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal +var _ = golang_proto.Marshal var _ = fmt.Errorf var _ = math.Inf @@ -31,6 +33,38 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package +// OrderBy defines the sorting order +type OrderBy int32 + +const ( + // ORDER_BY_UNSPECIFIED specifies an unknown sorting order. OrderBy defaults to ASC in this case. + OrderBy_ORDER_BY_UNSPECIFIED OrderBy = 0 + // ORDER_BY_ASC defines ascending order + OrderBy_ORDER_BY_ASC OrderBy = 1 + // ORDER_BY_DESC defines descending order + OrderBy_ORDER_BY_DESC OrderBy = 2 +) + +var OrderBy_name = map[int32]string{ + 0: "ORDER_BY_UNSPECIFIED", + 1: "ORDER_BY_ASC", + 2: "ORDER_BY_DESC", +} + +var OrderBy_value = map[string]int32{ + "ORDER_BY_UNSPECIFIED": 0, + "ORDER_BY_ASC": 1, + "ORDER_BY_DESC": 2, +} + +func (x OrderBy) String() string { + return proto.EnumName(OrderBy_name, int32(x)) +} + +func (OrderBy) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_e0b00a618705eca7, []int{0} +} + // BroadcastMode specifies the broadcast mode for the TxService.Broadcast RPC method. type BroadcastMode int32 @@ -67,7 +101,7 @@ func (x BroadcastMode) String() string { } func (BroadcastMode) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_e0b00a618705eca7, []int{0} + return fileDescriptor_e0b00a618705eca7, []int{1} } // GetTxsEventRequest is the request type for the Service.TxsByEvents @@ -77,6 +111,7 @@ type GetTxsEventRequest struct { Events []string `protobuf:"bytes,1,rep,name=events,proto3" json:"events,omitempty"` // pagination defines an pagination for the request. Pagination *query.PageRequest `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` + OrderBy OrderBy `protobuf:"varint,3,opt,name=order_by,json=orderBy,proto3,enum=cosmos.tx.v1beta1.OrderBy" json:"order_by,omitempty"` } func (m *GetTxsEventRequest) Reset() { *m = GetTxsEventRequest{} } @@ -126,6 +161,13 @@ func (m *GetTxsEventRequest) GetPagination() *query.PageRequest { return nil } +func (m *GetTxsEventRequest) GetOrderBy() OrderBy { + if m != nil { + return m.OrderBy + } + return OrderBy_ORDER_BY_UNSPECIFIED +} + // GetTxsEventResponse is the response type for the Service.TxsByEvents // RPC method. type GetTxsEventResponse struct { @@ -499,67 +541,86 @@ func (m *GetTxResponse) GetTxResponse() *types.TxResponse { } func init() { + proto.RegisterEnum("cosmos.tx.v1beta1.OrderBy", OrderBy_name, OrderBy_value) + golang_proto.RegisterEnum("cosmos.tx.v1beta1.OrderBy", OrderBy_name, OrderBy_value) proto.RegisterEnum("cosmos.tx.v1beta1.BroadcastMode", BroadcastMode_name, BroadcastMode_value) + golang_proto.RegisterEnum("cosmos.tx.v1beta1.BroadcastMode", BroadcastMode_name, BroadcastMode_value) proto.RegisterType((*GetTxsEventRequest)(nil), "cosmos.tx.v1beta1.GetTxsEventRequest") + golang_proto.RegisterType((*GetTxsEventRequest)(nil), "cosmos.tx.v1beta1.GetTxsEventRequest") proto.RegisterType((*GetTxsEventResponse)(nil), "cosmos.tx.v1beta1.GetTxsEventResponse") + golang_proto.RegisterType((*GetTxsEventResponse)(nil), "cosmos.tx.v1beta1.GetTxsEventResponse") proto.RegisterType((*BroadcastTxRequest)(nil), "cosmos.tx.v1beta1.BroadcastTxRequest") + golang_proto.RegisterType((*BroadcastTxRequest)(nil), "cosmos.tx.v1beta1.BroadcastTxRequest") proto.RegisterType((*BroadcastTxResponse)(nil), "cosmos.tx.v1beta1.BroadcastTxResponse") + golang_proto.RegisterType((*BroadcastTxResponse)(nil), "cosmos.tx.v1beta1.BroadcastTxResponse") proto.RegisterType((*SimulateRequest)(nil), "cosmos.tx.v1beta1.SimulateRequest") + golang_proto.RegisterType((*SimulateRequest)(nil), "cosmos.tx.v1beta1.SimulateRequest") proto.RegisterType((*SimulateResponse)(nil), "cosmos.tx.v1beta1.SimulateResponse") + golang_proto.RegisterType((*SimulateResponse)(nil), "cosmos.tx.v1beta1.SimulateResponse") proto.RegisterType((*GetTxRequest)(nil), "cosmos.tx.v1beta1.GetTxRequest") + golang_proto.RegisterType((*GetTxRequest)(nil), "cosmos.tx.v1beta1.GetTxRequest") proto.RegisterType((*GetTxResponse)(nil), "cosmos.tx.v1beta1.GetTxResponse") + golang_proto.RegisterType((*GetTxResponse)(nil), "cosmos.tx.v1beta1.GetTxResponse") } func init() { proto.RegisterFile("cosmos/tx/v1beta1/service.proto", fileDescriptor_e0b00a618705eca7) } +func init() { + golang_proto.RegisterFile("cosmos/tx/v1beta1/service.proto", fileDescriptor_e0b00a618705eca7) +} var fileDescriptor_e0b00a618705eca7 = []byte{ - // 737 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x55, 0xcd, 0x4f, 0x13, 0x41, - 0x14, 0xef, 0xb6, 0xc8, 0xc7, 0x2b, 0x68, 0x1d, 0x10, 0x6b, 0xd1, 0xa5, 0x2c, 0x16, 0x08, 0x89, - 0xbb, 0xa1, 0x7a, 0x20, 0xc6, 0xc4, 0xd0, 0x52, 0x08, 0x51, 0x3e, 0xb2, 0xc5, 0x83, 0xc6, 0xa4, - 0x99, 0xb6, 0xc3, 0xb2, 0x91, 0xee, 0x94, 0xce, 0x94, 0x2c, 0x01, 0x62, 0xe2, 0xd1, 0x93, 0x89, - 0xff, 0x94, 0x47, 0x12, 0x2f, 0x1e, 0x0d, 0xf8, 0x47, 0x78, 0x34, 0x3b, 0x3b, 0x6d, 0xb7, 0x65, - 0x0b, 0xc4, 0x13, 0x33, 0xcc, 0xef, 0xfd, 0x3e, 0xde, 0x9b, 0x9d, 0xc2, 0x74, 0x85, 0xb2, 0x1a, - 0x65, 0x06, 0x77, 0x8d, 0xa3, 0xa5, 0x32, 0xe1, 0x78, 0xc9, 0x60, 0xa4, 0x71, 0x64, 0x57, 0x88, - 0x5e, 0x6f, 0x50, 0x4e, 0xd1, 0x7d, 0x1f, 0xa0, 0x73, 0x57, 0x97, 0x80, 0xd4, 0x63, 0x8b, 0x52, - 0xeb, 0x80, 0x18, 0xb8, 0x6e, 0x1b, 0xd8, 0x71, 0x28, 0xc7, 0xdc, 0xa6, 0x0e, 0xf3, 0x0b, 0x52, - 0xb3, 0x92, 0xb1, 0x8c, 0x19, 0x31, 0x70, 0xb9, 0x62, 0xb7, 0x89, 0xbd, 0x8d, 0x04, 0xa5, 0xae, - 0xca, 0x72, 0x57, 0x9e, 0x4d, 0x58, 0xd4, 0xa2, 0x62, 0x69, 0x78, 0x2b, 0xf9, 0xdf, 0xc5, 0x20, - 0xed, 0x61, 0x93, 0x34, 0x8e, 0xdb, 0x95, 0x75, 0x6c, 0xd9, 0x8e, 0xf0, 0xe0, 0x63, 0x35, 0x0e, - 0x68, 0x9d, 0xf0, 0x5d, 0x97, 0x15, 0x8e, 0x88, 0xc3, 0x4d, 0x72, 0xd8, 0x24, 0x8c, 0xa3, 0x49, - 0x18, 0x24, 0xde, 0x9e, 0x25, 0x95, 0x74, 0x6c, 0x61, 0xc4, 0x94, 0x3b, 0xb4, 0x06, 0xd0, 0x61, - 0x48, 0x46, 0xd3, 0xca, 0x42, 0x3c, 0x3b, 0xa7, 0xcb, 0xd8, 0x9e, 0x9c, 0x2e, 0xe4, 0x5a, 0xf1, - 0xf5, 0x1d, 0x6c, 0x11, 0xc9, 0x69, 0x06, 0x2a, 0xb5, 0x73, 0x05, 0xc6, 0xbb, 0x64, 0x59, 0x9d, - 0x3a, 0x8c, 0xa0, 0x79, 0x88, 0x71, 0xd7, 0x17, 0x8d, 0x67, 0x1f, 0xe8, 0x57, 0xfa, 0xa9, 0xef, - 0xba, 0xa6, 0x87, 0x40, 0xeb, 0x30, 0xca, 0xdd, 0x52, 0x43, 0xd6, 0xb1, 0x64, 0x54, 0x54, 0x3c, - 0xed, 0xb2, 0x22, 0x7a, 0x18, 0x28, 0x94, 0x60, 0x33, 0xce, 0xdb, 0x6b, 0x8f, 0x28, 0x98, 0x28, - 0x26, 0x12, 0xcd, 0xdf, 0x98, 0x48, 0x32, 0x05, 0x23, 0x11, 0x40, 0xb9, 0x06, 0xc5, 0xd5, 0x0a, - 0x66, 0xdc, 0x13, 0xf3, 0x1b, 0xf9, 0x08, 0x86, 0xb9, 0x5b, 0x2a, 0x1f, 0x73, 0xe2, 0xa5, 0x52, - 0x16, 0x46, 0xcd, 0x21, 0xee, 0xe6, 0xbc, 0x2d, 0x7a, 0x01, 0x03, 0x35, 0x5a, 0x25, 0xa2, 0x8b, - 0x77, 0xb3, 0xe9, 0x90, 0xb0, 0x6d, 0xbe, 0x4d, 0x5a, 0x25, 0xa6, 0x40, 0x6b, 0x1f, 0x61, 0xbc, - 0x4b, 0x46, 0x36, 0xae, 0x00, 0xf1, 0x40, 0x3f, 0x84, 0xd4, 0x6d, 0xdb, 0x01, 0x9d, 0x76, 0x68, - 0xcb, 0x70, 0xaf, 0x68, 0xd7, 0x9a, 0x07, 0x98, 0xb7, 0xc6, 0x86, 0x32, 0x10, 0xe5, 0xae, 0x24, - 0xec, 0x33, 0x91, 0x28, 0x77, 0xb5, 0xaf, 0x0a, 0x24, 0x3a, 0xa5, 0xd2, 0xd5, 0x2b, 0x18, 0xb6, - 0x30, 0x2b, 0xd9, 0xce, 0x1e, 0x95, 0x0c, 0x33, 0xfd, 0x2d, 0xad, 0x63, 0xb6, 0xe1, 0xec, 0x51, - 0x73, 0xc8, 0xf2, 0x17, 0x68, 0x19, 0x06, 0x1b, 0x84, 0x35, 0x0f, 0xb8, 0xbc, 0x68, 0xe9, 0xfe, - 0xb5, 0xa6, 0xc0, 0x99, 0x12, 0xaf, 0x69, 0x30, 0x2a, 0x6e, 0x57, 0x2b, 0x03, 0x82, 0x81, 0x7d, - 0xcc, 0xf6, 0x85, 0x87, 0x11, 0x53, 0xac, 0xb5, 0x33, 0x18, 0x93, 0x18, 0x69, 0xf6, 0x76, 0x41, - 0x7b, 0x3b, 0x1d, 0xfd, 0xbf, 0x4e, 0x2f, 0x9e, 0xc2, 0x58, 0xd7, 0x78, 0x91, 0x0a, 0xa9, 0x9c, - 0xb9, 0xbd, 0xb2, 0x9a, 0x5f, 0x29, 0xee, 0x96, 0x36, 0xb7, 0x57, 0x0b, 0xa5, 0x77, 0x5b, 0xc5, - 0x9d, 0x42, 0x7e, 0x63, 0x6d, 0xa3, 0xb0, 0x9a, 0x88, 0xa0, 0x24, 0x4c, 0xf4, 0x9c, 0xe7, 0xde, - 0x6e, 0xe7, 0xdf, 0x24, 0x14, 0xf4, 0x10, 0xc6, 0x7b, 0x4e, 0x8a, 0xef, 0xb7, 0xf2, 0x89, 0x68, - 0x48, 0xc9, 0x8a, 0x38, 0x89, 0x65, 0xff, 0xc6, 0x60, 0xa8, 0xe8, 0xbf, 0x5d, 0xe8, 0x04, 0x86, - 0x5b, 0x83, 0x43, 0x5a, 0x48, 0xee, 0x9e, 0x0b, 0x91, 0x9a, 0xbd, 0x16, 0x23, 0x2f, 0xd2, 0xdc, - 0x97, 0x9f, 0x7f, 0xbe, 0x47, 0xd3, 0xda, 0x94, 0x11, 0xf2, 0x68, 0x4a, 0xf0, 0x4b, 0x65, 0x11, - 0x1d, 0xc2, 0x1d, 0x31, 0x05, 0x34, 0x1d, 0xc2, 0x1a, 0x9c, 0x61, 0x2a, 0xdd, 0x1f, 0x20, 0x35, - 0x33, 0x42, 0x73, 0x1a, 0x3d, 0x31, 0xc2, 0x5e, 0x4c, 0x66, 0x9c, 0x78, 0x73, 0x3f, 0x43, 0x9f, - 0x21, 0x1e, 0xf8, 0x82, 0x50, 0xe6, 0xba, 0x0f, 0xaf, 0x23, 0x3f, 0x77, 0x13, 0x4c, 0x9a, 0x98, - 0x11, 0x26, 0xa6, 0xb4, 0xc9, 0x70, 0x13, 0x5e, 0xe6, 0x53, 0x88, 0x07, 0xde, 0xbe, 0x50, 0x03, - 0x57, 0x9f, 0xe4, 0x50, 0x03, 0x21, 0x4f, 0xa8, 0xa6, 0x0a, 0x03, 0x49, 0xd4, 0xc7, 0x40, 0xee, - 0xf5, 0x8f, 0x0b, 0x55, 0x39, 0xbf, 0x50, 0x95, 0xdf, 0x17, 0xaa, 0xf2, 0xed, 0x52, 0x8d, 0x9c, - 0x5f, 0xaa, 0x91, 0x5f, 0x97, 0x6a, 0xe4, 0x43, 0xc6, 0xb2, 0xf9, 0x7e, 0xb3, 0xac, 0x57, 0x68, - 0xad, 0x55, 0xeb, 0xff, 0x79, 0xc6, 0xaa, 0x9f, 0x0c, 0x7e, 0x5c, 0x27, 0x1e, 0x59, 0x79, 0x50, - 0xfc, 0x70, 0x3c, 0xff, 0x17, 0x00, 0x00, 0xff, 0xff, 0x96, 0xba, 0xfb, 0xcb, 0x0f, 0x07, 0x00, + // 817 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x55, 0xcf, 0x6f, 0xe3, 0x44, + 0x14, 0x8e, 0x9d, 0xa5, 0xc9, 0xbe, 0xa4, 0x4b, 0x76, 0x5a, 0x96, 0x90, 0x05, 0x37, 0xeb, 0x25, + 0x6d, 0x14, 0x09, 0x5b, 0x0d, 0x20, 0x55, 0x88, 0x4b, 0x7e, 0xb5, 0x54, 0xd0, 0xa6, 0x72, 0xca, + 0xa1, 0x08, 0x29, 0x72, 0x92, 0xa9, 0x6b, 0xd1, 0x78, 0x52, 0xcf, 0xa4, 0x72, 0xd4, 0x56, 0x48, + 0x1c, 0x39, 0x21, 0xf1, 0x67, 0xf0, 0x4f, 0x70, 0xe4, 0x58, 0x89, 0x0b, 0x47, 0xd4, 0xf0, 0x47, + 0x70, 0x44, 0x1e, 0x4f, 0x12, 0x27, 0x75, 0xda, 0x8a, 0x53, 0xde, 0x64, 0xbe, 0xf7, 0xbd, 0xef, + 0x7d, 0xf3, 0x66, 0x0c, 0x1b, 0x5d, 0x42, 0xfb, 0x84, 0xea, 0xcc, 0xd3, 0x2f, 0xb7, 0x3b, 0x98, + 0x99, 0xdb, 0x3a, 0xc5, 0xee, 0xa5, 0xdd, 0xc5, 0xda, 0xc0, 0x25, 0x8c, 0xa0, 0x97, 0x01, 0x40, + 0x63, 0x9e, 0x26, 0x00, 0xb9, 0x0f, 0x2d, 0x42, 0xac, 0x73, 0xac, 0x9b, 0x03, 0x5b, 0x37, 0x1d, + 0x87, 0x30, 0x93, 0xd9, 0xc4, 0xa1, 0x41, 0x42, 0xee, 0xad, 0x60, 0xec, 0x98, 0x14, 0xeb, 0x66, + 0xa7, 0x6b, 0x4f, 0x89, 0xfd, 0x85, 0x00, 0xe5, 0xee, 0x97, 0x65, 0x9e, 0xd8, 0x5b, 0xb7, 0x88, + 0x45, 0x78, 0xa8, 0xfb, 0x91, 0xf8, 0xb7, 0x14, 0xa6, 0xbd, 0x18, 0x62, 0x77, 0x34, 0xcd, 0x1c, + 0x98, 0x96, 0xed, 0x70, 0x0d, 0x01, 0x56, 0xfd, 0x4d, 0x02, 0xb4, 0x87, 0xd9, 0xb1, 0x47, 0x1b, + 0x97, 0xd8, 0x61, 0x06, 0xbe, 0x18, 0x62, 0xca, 0xd0, 0x2b, 0x58, 0xc1, 0xfe, 0x9a, 0x66, 0xa5, + 0x7c, 0xbc, 0xf8, 0xdc, 0x10, 0x2b, 0xb4, 0x0b, 0x30, 0xa3, 0xc8, 0xca, 0x79, 0xa9, 0x98, 0x2a, + 0x6f, 0x6a, 0xa2, 0x6f, 0xbf, 0x9e, 0xc6, 0xeb, 0x4d, 0xfa, 0xd7, 0x8e, 0x4c, 0x0b, 0x0b, 0x4e, + 0x23, 0x94, 0x89, 0x3e, 0x87, 0x24, 0x71, 0x7b, 0xd8, 0x6d, 0x77, 0x46, 0xd9, 0x78, 0x5e, 0x2a, + 0xbe, 0x28, 0xe7, 0xb4, 0x7b, 0xee, 0x69, 0x4d, 0x1f, 0x52, 0x1d, 0x19, 0x09, 0x12, 0x04, 0xea, + 0xad, 0x04, 0x6b, 0x73, 0x6a, 0xe9, 0x80, 0x38, 0x14, 0xa3, 0x2d, 0x88, 0x33, 0x2f, 0xd0, 0x9a, + 0x2a, 0xbf, 0x17, 0xc1, 0x74, 0xec, 0x19, 0x3e, 0x02, 0xed, 0x41, 0x9a, 0x79, 0x6d, 0x57, 0xe4, + 0xd1, 0xac, 0xcc, 0x33, 0x3e, 0x9e, 0xeb, 0x80, 0x7b, 0x1f, 0x4a, 0x14, 0x60, 0x23, 0xc5, 0xa6, + 0xb1, 0x4f, 0x14, 0x36, 0x22, 0xce, 0x8d, 0xd8, 0x7a, 0xd4, 0x08, 0xc1, 0x14, 0x4a, 0x55, 0x31, + 0xa0, 0xaa, 0x4b, 0xcc, 0x5e, 0xd7, 0xa4, 0xcc, 0x2f, 0x16, 0xf8, 0xff, 0x01, 0x24, 0x99, 0xd7, + 0xee, 0x8c, 0x18, 0xf6, 0xbb, 0x92, 0x8a, 0x69, 0x23, 0xc1, 0xbc, 0xaa, 0xbf, 0x44, 0x9f, 0xc1, + 0xb3, 0x3e, 0xe9, 0x61, 0x6e, 0xfe, 0x8b, 0x72, 0x3e, 0xa2, 0xd9, 0x29, 0xdf, 0x01, 0xe9, 0x61, + 0x83, 0xa3, 0xd5, 0xef, 0x61, 0x6d, 0xae, 0x8c, 0x30, 0xae, 0x01, 0xa9, 0x90, 0x1f, 0xbc, 0xd4, + 0x53, 0xed, 0x80, 0x99, 0x1d, 0xea, 0x0e, 0xbc, 0xdb, 0xb2, 0xfb, 0xc3, 0x73, 0x93, 0x4d, 0x4e, + 0x1b, 0x15, 0x40, 0x66, 0x9e, 0x20, 0x5c, 0x72, 0x22, 0x32, 0xf3, 0xd4, 0x9f, 0x25, 0xc8, 0xcc, + 0x52, 0x85, 0xaa, 0x2f, 0x21, 0x69, 0x99, 0xb4, 0x6d, 0x3b, 0xa7, 0x44, 0x30, 0xbc, 0x59, 0x2e, + 0x69, 0xcf, 0xa4, 0xfb, 0xce, 0x29, 0x31, 0x12, 0x56, 0x10, 0xa0, 0x1d, 0x58, 0x71, 0x31, 0x1d, + 0x9e, 0x33, 0x31, 0x9f, 0xf9, 0xe5, 0xb9, 0x06, 0xc7, 0x19, 0x02, 0xaf, 0xaa, 0x90, 0xe6, 0xd3, + 0x35, 0xe9, 0x01, 0xc1, 0xb3, 0x33, 0x93, 0x9e, 0x71, 0x0d, 0xcf, 0x0d, 0x1e, 0xab, 0x37, 0xb0, + 0x2a, 0x30, 0x42, 0xec, 0xd3, 0x1a, 0x5d, 0x74, 0x5a, 0xfe, 0x7f, 0x4e, 0x97, 0xbe, 0x82, 0x84, + 0xb8, 0x15, 0x28, 0x0b, 0xeb, 0x4d, 0xa3, 0xde, 0x30, 0xda, 0xd5, 0x93, 0xf6, 0xb7, 0x87, 0xad, + 0xa3, 0x46, 0x6d, 0x7f, 0x77, 0xbf, 0x51, 0xcf, 0xc4, 0x50, 0x06, 0xd2, 0xd3, 0x9d, 0x4a, 0xab, + 0x96, 0x91, 0xd0, 0x4b, 0x58, 0x9d, 0xfe, 0x53, 0x6f, 0xb4, 0x6a, 0x19, 0xb9, 0x74, 0x0d, 0xab, + 0x73, 0x83, 0x82, 0x14, 0xc8, 0x55, 0x8d, 0x66, 0xa5, 0x5e, 0xab, 0xb4, 0x8e, 0xdb, 0x07, 0xcd, + 0x7a, 0x63, 0x81, 0x35, 0x0b, 0xeb, 0x0b, 0xfb, 0xd5, 0x6f, 0x9a, 0xb5, 0xaf, 0x33, 0x12, 0x7a, + 0x1f, 0xd6, 0x16, 0x76, 0x5a, 0x27, 0x87, 0xb5, 0x8c, 0x1c, 0x91, 0x52, 0xe1, 0x3b, 0xf1, 0xf2, + 0xbf, 0x71, 0x48, 0xb4, 0x82, 0xd7, 0x13, 0x5d, 0x41, 0x72, 0x32, 0x02, 0x48, 0x8d, 0x70, 0x70, + 0x61, 0xb4, 0x72, 0x6f, 0x1f, 0xc4, 0x88, 0x91, 0xdc, 0xfc, 0xe9, 0xcf, 0x7f, 0x7e, 0x95, 0xf3, + 0xea, 0x6b, 0x3d, 0xe2, 0xd9, 0x16, 0xe0, 0x2f, 0xa4, 0x12, 0xba, 0x80, 0x77, 0xf8, 0x79, 0xa2, + 0x8d, 0x08, 0xd6, 0xf0, 0x34, 0xe4, 0xf2, 0xcb, 0x01, 0xa2, 0x66, 0x81, 0xd7, 0xdc, 0x40, 0x1f, + 0xe9, 0x51, 0x6f, 0x36, 0xd5, 0xaf, 0xfc, 0x09, 0xba, 0x41, 0x3f, 0x42, 0x2a, 0x74, 0x17, 0x51, + 0xe1, 0xa1, 0x2b, 0x3c, 0x2b, 0xbf, 0xf9, 0x18, 0x4c, 0x88, 0x78, 0xc3, 0x45, 0xbc, 0x56, 0x5f, + 0x45, 0x8b, 0xf0, 0x7b, 0xbe, 0x86, 0x54, 0xe8, 0x15, 0x8d, 0x14, 0x70, 0xff, 0x9b, 0x10, 0x29, + 0x20, 0xe2, 0x31, 0x56, 0x15, 0x2e, 0x20, 0x8b, 0x96, 0x08, 0xa8, 0xd6, 0xfe, 0xb8, 0x53, 0xa4, + 0xdb, 0x3b, 0x45, 0xfa, 0xfb, 0x4e, 0x91, 0x7e, 0x19, 0x2b, 0xb1, 0xdf, 0xc7, 0x8a, 0x74, 0x3b, + 0x56, 0x62, 0x7f, 0x8d, 0x95, 0xd8, 0x77, 0x05, 0xcb, 0x66, 0x67, 0xc3, 0x8e, 0xd6, 0x25, 0xfd, + 0x49, 0x7e, 0xf0, 0xf3, 0x09, 0xed, 0xfd, 0xa0, 0xb3, 0xd1, 0x00, 0xfb, 0x84, 0x9d, 0x15, 0xfe, + 0xf9, 0xfa, 0xf4, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7b, 0x64, 0xf5, 0xff, 0x95, 0x07, 0x00, 0x00, } @@ -779,6 +840,11 @@ func (m *GetTxsEventRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.OrderBy != 0 { + i = encodeVarintService(dAtA, i, uint64(m.OrderBy)) + i-- + dAtA[i] = 0x18 + } if m.Pagination != nil { { size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) @@ -1122,6 +1188,9 @@ func (m *GetTxsEventRequest) Size() (n int) { l = m.Pagination.Size() n += 1 + l + sovService(uint64(l)) } + if m.OrderBy != 0 { + n += 1 + sovService(uint64(m.OrderBy)) + } return n } @@ -1342,6 +1411,25 @@ func (m *GetTxsEventRequest) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field OrderBy", wireType) + } + m.OrderBy = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowService + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.OrderBy |= OrderBy(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipService(dAtA[iNdEx:]) diff --git a/x/auth/tx/service.go b/x/auth/tx/service.go index d33bcac91329..2d73a110b704 100644 --- a/x/auth/tx/service.go +++ b/x/auth/tx/service.go @@ -52,6 +52,7 @@ func (s txServer) GetTxsEvent(ctx context.Context, req *txtypes.GetTxsEventReque if err != nil { return nil, err } + orderBy := parseOrderBy(req.OrderBy) if len(req.Events) == 0 { return nil, status.Error(codes.InvalidArgument, "must declare at least one event to search") @@ -63,7 +64,7 @@ func (s txServer) GetTxsEvent(ctx context.Context, req *txtypes.GetTxsEventReque } } - result, err := QueryTxsByEvents(s.clientCtx, req.Events, page, limit, "") + result, err := QueryTxsByEvents(s.clientCtx, req.Events, page, limit, orderBy) if err != nil { return nil, err } @@ -161,3 +162,14 @@ func RegisterTxService( func RegisterGRPCGatewayRoutes(clientConn gogogrpc.ClientConn, mux *runtime.ServeMux) { txtypes.RegisterServiceHandlerClient(context.Background(), mux, txtypes.NewServiceClient(clientConn)) } + +func parseOrderBy(orderBy txtypes.OrderBy) string { + switch orderBy { + case txtypes.OrderBy_ORDER_BY_ASC: + return "asc" + case txtypes.OrderBy_ORDER_BY_DESC: + return "desc" + default: + return "asc" + } +} diff --git a/x/auth/tx/service_test.go b/x/auth/tx/service_test.go index b460867b4b25..03944d6c41e2 100644 --- a/x/auth/tx/service_test.go +++ b/x/auth/tx/service_test.go @@ -173,6 +173,14 @@ func (s IntegrationTestSuite) TestGetTxEvents_GRPC() { &tx.GetTxsEventRequest{Events: []string{"foobar"}}, true, "event foobar should be of the format: {eventType}.{eventAttribute}={value}", }, + { + "request with order-by", + &tx.GetTxsEventRequest{ + Events: []string{"message.action='/cosmos.bank.v1beta1.Msg/Send'"}, + OrderBy: tx.OrderBy_ORDER_BY_ASC, + }, + false, "", + }, { "without pagination", &tx.GetTxsEventRequest{ @@ -248,6 +256,24 @@ func (s IntegrationTestSuite) TestGetTxEvents_GRPCGateway() { false, "", }, + { + "valid request: order by asc", + fmt.Sprintf("%s/cosmos/tx/v1beta1/txs?events=%s&events=%s&order_by=ORDER_BY_ASC", val.APIAddress, "message.action='/cosmos.bank.v1beta1.Msg/Send'", "message.module='bank'"), + false, + "", + }, + { + "valid request: order by desc", + fmt.Sprintf("%s/cosmos/tx/v1beta1/txs?events=%s&events=%s&order_by=ORDER_BY_DESC", val.APIAddress, "message.action='/cosmos.bank.v1beta1.Msg/Send'", "message.module='bank'"), + false, + "", + }, + { + "invalid request: invalid order by", + fmt.Sprintf("%s/cosmos/tx/v1beta1/txs?events=%s&events=%s&order_by=invalid_order", val.APIAddress, "message.action='/cosmos.bank.v1beta1.Msg/Send'", "message.module='bank'"), + true, + "is not a valid tx.OrderBy", + }, { "expect pass with multiple-events", fmt.Sprintf("%s/cosmos/tx/v1beta1/txs?events=%s&events=%s", val.APIAddress, "message.action='/cosmos.bank.v1beta1.Msg/Send'", "message.module='bank'"), From c6af0ed87ede190932f76e49a7083ba28b415d25 Mon Sep 17 00:00:00 2001 From: technicallyty <48813565+technicallyty@users.noreply.github.com> Date: Sat, 13 Mar 2021 17:03:01 -0800 Subject: [PATCH 185/214] x/upgrade: remove support for time based upgrades (#8849) * remove time based upgrades * cleanup * cleanup evidence of time based upgrades * cleanup docs referring to time based upgrades * forgot one * added line to changelog deprecated section * Update proto/cosmos/upgrade/v1beta1/upgrade.proto Co-authored-by: Amaury <1293565+amaurym@users.noreply.github.com> * update changelog line to correct section * update buf config to allow reserved fields Co-authored-by: technicallyty <48813565+tytech3@users.noreply.github.com> Co-authored-by: Amaury <1293565+amaurym@users.noreply.github.com> Co-authored-by: SaReN Co-authored-by: Aaron Craelius --- CHANGELOG.md | 1 + buf.yaml | 2 + docs/core/proto-docs.md | 1 - proto/cosmos/upgrade/v1beta1/upgrade.proto | 7 +- x/gov/legacy/v040/migrate.go | 1 - x/gov/legacy/v040/migrate_test.go | 3 +- x/upgrade/abci_test.go | 45 ++------- x/upgrade/client/cli/tx.go | 33 +------ x/upgrade/client/rest/tx.go | 12 +-- x/upgrade/doc.go | 10 +- x/upgrade/keeper/keeper.go | 6 +- x/upgrade/keeper/keeper_test.go | 20 ---- x/upgrade/spec/01_concepts.md | 7 +- x/upgrade/spec/README.md | 2 +- x/upgrade/types/plan.go | 23 +---- x/upgrade/types/plan_test.go | 45 +-------- x/upgrade/types/proposal_test.go | 6 +- x/upgrade/types/upgrade.pb.go | 102 +++++---------------- 18 files changed, 64 insertions(+), 262 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 24048f26493a..437d6af38149 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * [\#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. * (crypto/ed25519) [\#8690] Adopt zip1215 ed2559 verification rules. +* [\#8849](https://github.com/cosmos/cosmos-sdk/pull/8849) Upgrade module no longer supports time based upgrades. ### API Breaking Changes diff --git a/buf.yaml b/buf.yaml index 37f716cabaa2..5418e290609b 100644 --- a/buf.yaml +++ b/buf.yaml @@ -26,6 +26,8 @@ lint: breaking: use: - FILE + except: + - FIELD_NO_DELETE ignore: - tendermint - gogoproto diff --git a/docs/core/proto-docs.md b/docs/core/proto-docs.md index 4d493b27c4ab..4da3e3dd3758 100644 --- a/docs/core/proto-docs.md +++ b/docs/core/proto-docs.md @@ -7362,7 +7362,6 @@ 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 | diff --git a/proto/cosmos/upgrade/v1beta1/upgrade.proto b/proto/cosmos/upgrade/v1beta1/upgrade.proto index 76fb14e2d3ca..7b767dedfdb7 100644 --- a/proto/cosmos/upgrade/v1beta1/upgrade.proto +++ b/proto/cosmos/upgrade/v1beta1/upgrade.proto @@ -22,9 +22,10 @@ message Plan { // reached and the software will exit. string name = 1; - // The time after which the upgrade must be performed. - // Leave set to its zero value to use a pre-defined Height instead. - google.protobuf.Timestamp time = 2 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false]; + // Time based upgrades have been deprecated. Time based upgrade logic + // has been removed from the SDK. + reserved 2; + reserved "time"; // The height at which the upgrade must be performed. // Only used if Time is not set. diff --git a/x/gov/legacy/v040/migrate.go b/x/gov/legacy/v040/migrate.go index 69b32a621cc5..4845c8303d94 100644 --- a/x/gov/legacy/v040/migrate.go +++ b/x/gov/legacy/v040/migrate.go @@ -106,7 +106,6 @@ func migrateContent(oldContent v036gov.Content) *codectypes.Any { Title: oldContent.Title, Plan: v040upgrade.Plan{ Name: oldContent.Plan.Name, - Time: oldContent.Plan.Time, Height: oldContent.Plan.Height, Info: oldContent.Plan.Info, }, diff --git a/x/gov/legacy/v040/migrate_test.go b/x/gov/legacy/v040/migrate_test.go index c28e43fdf2c9..51604809abb7 100644 --- a/x/gov/legacy/v040/migrate_test.go +++ b/x/gov/legacy/v040/migrate_test.go @@ -175,8 +175,7 @@ func TestMigrate(t *testing.T) { "plan": { "height": "123", "info": "foo_upgrade_info", - "name": "foo_upgrade_name", - "time": "0001-01-01T00:00:00Z" + "name": "foo_upgrade_name" }, "title": "foo_software_upgrade" }, diff --git a/x/upgrade/abci_test.go b/x/upgrade/abci_test.go index 9eb0fc1a7ab9..4dc2a4c5f76d 100644 --- a/x/upgrade/abci_test.go +++ b/x/upgrade/abci_test.go @@ -68,13 +68,6 @@ func TestRequireName(t *testing.T) { require.True(t, errors.Is(sdkerrors.ErrInvalidRequest, err), err) } -func TestRequireFutureTime(t *testing.T) { - s := setupTest(10, map[int64]bool{}) - err := s.handler(s.ctx, &types.SoftwareUpgradeProposal{Title: "prop", Plan: types.Plan{Name: "test", Time: s.ctx.BlockHeader().Time}}) - require.NotNil(t, err) - require.True(t, errors.Is(sdkerrors.ErrInvalidRequest, err), err) -} - func TestRequireFutureBlock(t *testing.T) { s := setupTest(10, map[int64]bool{}) err := s.handler(s.ctx, &types.SoftwareUpgradeProposal{Title: "prop", Plan: types.Plan{Name: "test", Height: s.ctx.BlockHeight()}}) @@ -82,22 +75,6 @@ func TestRequireFutureBlock(t *testing.T) { require.True(t, errors.Is(sdkerrors.ErrInvalidRequest, err), err) } -func TestCantSetBothTimeAndHeight(t *testing.T) { - s := setupTest(10, map[int64]bool{}) - err := s.handler(s.ctx, &types.SoftwareUpgradeProposal{Title: "prop", Plan: types.Plan{Name: "test", Time: time.Now(), Height: s.ctx.BlockHeight() + 1}}) - require.NotNil(t, err) - require.True(t, errors.Is(sdkerrors.ErrInvalidRequest, err), err) -} - -func TestDoTimeUpgrade(t *testing.T) { - s := setupTest(10, map[int64]bool{}) - t.Log("Verify can schedule an upgrade") - err := s.handler(s.ctx, &types.SoftwareUpgradeProposal{Title: "prop", Plan: types.Plan{Name: "test", Time: time.Now()}}) - require.Nil(t, err) - - VerifyDoUpgrade(t) -} - func TestDoHeightUpgrade(t *testing.T) { s := setupTest(10, map[int64]bool{}) t.Log("Verify can schedule an upgrade") @@ -119,7 +96,7 @@ func TestCanOverwriteScheduleUpgrade(t *testing.T) { } func VerifyDoUpgrade(t *testing.T) { - t.Log("Verify that a panic happens at the upgrade time/height") + t.Log("Verify that a panic happens at the upgrade height") newCtx := s.ctx.WithBlockHeight(s.ctx.BlockHeight() + 1).WithBlockTime(time.Now()) req := abci.RequestBeginBlock{Header: newCtx.BlockHeader()} @@ -137,7 +114,7 @@ func VerifyDoUpgrade(t *testing.T) { } func VerifyDoUpgradeWithCtx(t *testing.T, newCtx sdk.Context, proposalName string) { - t.Log("Verify that a panic happens at the upgrade time/height") + t.Log("Verify that a panic happens at the upgrade height") req := abci.RequestBeginBlock{Header: newCtx.BlockHeader()} require.Panics(t, func() { s.module.BeginBlock(newCtx, req) @@ -195,7 +172,7 @@ func VerifyCleared(t *testing.T, newCtx sdk.Context) { func TestCanClear(t *testing.T) { s := setupTest(10, map[int64]bool{}) t.Log("Verify upgrade is scheduled") - err := s.handler(s.ctx, &types.SoftwareUpgradeProposal{Title: "prop", Plan: types.Plan{Name: "test", Time: time.Now()}}) + err := s.handler(s.ctx, &types.SoftwareUpgradeProposal{Title: "prop", Plan: types.Plan{Name: "test", Height: s.ctx.BlockHeight() + 100}}) require.Nil(t, err) err = s.handler(s.ctx, &types.CancelSoftwareUpgradeProposal{Title: "cancel"}) @@ -206,11 +183,12 @@ func TestCanClear(t *testing.T) { func TestCantApplySameUpgradeTwice(t *testing.T) { s := setupTest(10, map[int64]bool{}) - err := s.handler(s.ctx, &types.SoftwareUpgradeProposal{Title: "prop", Plan: types.Plan{Name: "test", Time: time.Now()}}) + height := s.ctx.BlockHeader().Height + 1 + err := s.handler(s.ctx, &types.SoftwareUpgradeProposal{Title: "prop", Plan: types.Plan{Name: "test", Height: height}}) require.Nil(t, err) VerifyDoUpgrade(t) t.Log("Verify an executed upgrade \"test\" can't be rescheduled") - err = s.handler(s.ctx, &types.SoftwareUpgradeProposal{Title: "prop", Plan: types.Plan{Name: "test", Time: time.Now()}}) + err = s.handler(s.ctx, &types.SoftwareUpgradeProposal{Title: "prop", Plan: types.Plan{Name: "test", Height: height}}) require.NotNil(t, err) require.True(t, errors.Is(sdkerrors.ErrInvalidRequest, err), err) } @@ -225,20 +203,15 @@ func TestNoSpuriousUpgrades(t *testing.T) { } func TestPlanStringer(t *testing.T) { - ti, err := time.Parse(time.RFC3339, "2020-01-01T00:00:00Z") - require.Nil(t, err) - require.Equal(t, `Upgrade Plan - Name: test - Time: 2020-01-01T00:00:00Z - Info: .`, types.Plan{Name: "test", Time: ti}.String()) require.Equal(t, `Upgrade Plan Name: test Height: 100 - Info: .`, types.Plan{Name: "test", Height: 100}.String()) + Info: .`, types.Plan{Name: "test", Height: 100, Info: ""}.String()) + require.Equal(t, fmt.Sprintf(`Upgrade Plan Name: test Height: 100 - Info: .`), types.Plan{Name: "test", Height: 100}.String()) + Info: .`), types.Plan{Name: "test", Height: 100, Info: ""}.String()) } func VerifyNotDone(t *testing.T, newCtx sdk.Context, name string) { diff --git a/x/upgrade/client/cli/tx.go b/x/upgrade/client/cli/tx.go index bb8382af03c4..9dc75ac141e4 100644 --- a/x/upgrade/client/cli/tx.go +++ b/x/upgrade/client/cli/tx.go @@ -1,9 +1,6 @@ package cli import ( - "fmt" - "time" - "github.com/spf13/cobra" "github.com/cosmos/cosmos-sdk/client" @@ -16,11 +13,7 @@ import ( ) const ( - // TimeFormat specifies ISO UTC format for submitting the time for a new upgrade proposal - TimeFormat = "2006-01-02T15:04:05Z" - FlagUpgradeHeight = "upgrade-height" - FlagUpgradeTime = "upgrade-time" FlagUpgradeInfo = "upgrade-info" ) @@ -37,11 +30,11 @@ func GetTxCmd() *cobra.Command { // NewCmdSubmitUpgradeProposal implements a command handler for submitting a software upgrade proposal transaction. func NewCmdSubmitUpgradeProposal() *cobra.Command { cmd := &cobra.Command{ - Use: "software-upgrade [name] (--upgrade-height [height] | --upgrade-time [time]) (--upgrade-info [info]) [flags]", + Use: "software-upgrade [name] (--upgrade-height [height]) (--upgrade-info [info]) [flags]", Args: cobra.ExactArgs(1), Short: "Submit a software upgrade proposal", Long: "Submit a software upgrade along with an initial deposit.\n" + - "Please specify a unique name and height OR time for the upgrade to take effect.\n" + + "Please specify a unique name and height for the upgrade to take effect.\n" + "You may include info to reference a binary download link, in a format compatible with: https://github.com/cosmos/cosmos-sdk/tree/master/cosmovisor", RunE: func(cmd *cobra.Command, args []string) error { clientCtx, err := client.GetClientTxContext(cmd) @@ -84,8 +77,7 @@ func NewCmdSubmitUpgradeProposal() *cobra.Command { cmd.Flags().String(cli.FlagTitle, "", "title of proposal") cmd.Flags().String(cli.FlagDescription, "", "description of proposal") cmd.Flags().String(cli.FlagDeposit, "", "deposit of proposal") - cmd.Flags().Int64(FlagUpgradeHeight, 0, "The height at which the upgrade must happen (not to be used together with --upgrade-time)") - cmd.Flags().String(FlagUpgradeTime, "", fmt.Sprintf("The time at which the upgrade must happen (ex. %s) (not to be used together with --upgrade-height)", TimeFormat)) + cmd.Flags().Int64(FlagUpgradeHeight, 0, "The height at which the upgrade must happen") cmd.Flags().String(FlagUpgradeInfo, "", "Optional info for the planned upgrade such as commit hash, etc.") return cmd @@ -168,29 +160,12 @@ func parseArgsToContent(cmd *cobra.Command, name string) (gov.Content, error) { return nil, err } - timeStr, err := cmd.Flags().GetString(FlagUpgradeTime) - if err != nil { - return nil, err - } - - if height != 0 && len(timeStr) != 0 { - return nil, fmt.Errorf("only one of --upgrade-time or --upgrade-height should be specified") - } - - var upgradeTime time.Time - if len(timeStr) != 0 { - upgradeTime, err = time.Parse(TimeFormat, timeStr) - if err != nil { - return nil, err - } - } - info, err := cmd.Flags().GetString(FlagUpgradeInfo) if err != nil { return nil, err } - plan := types.Plan{Name: name, Time: upgradeTime, Height: height, Info: info} + plan := types.Plan{Name: name, Height: height, Info: info} content := types.NewSoftwareUpgradeProposal(title, description, plan) return content, nil } diff --git a/x/upgrade/client/rest/tx.go b/x/upgrade/client/rest/tx.go index 51bdb8f9235a..131173fa2ac9 100644 --- a/x/upgrade/client/rest/tx.go +++ b/x/upgrade/client/rest/tx.go @@ -2,7 +2,6 @@ package rest import ( "net/http" - "time" "github.com/cosmos/cosmos-sdk/client/tx" @@ -32,7 +31,6 @@ type PlanRequest struct { Deposit sdk.Coins `json:"deposit" yaml:"deposit"` UpgradeName string `json:"upgrade_name" yaml:"upgrade_name"` UpgradeHeight int64 `json:"upgrade_height" yaml:"upgrade_height"` - UpgradeTime string `json:"upgrade_time" yaml:"upgrade_time"` UpgradeInfo string `json:"upgrade_info" yaml:"upgrade_info"` } @@ -76,15 +74,7 @@ func newPostPlanHandler(clientCtx client.Context) http.HandlerFunc { return } - var t time.Time - if req.UpgradeTime != "" { - t, err = time.Parse(time.RFC3339, req.UpgradeTime) - if rest.CheckBadRequestError(w, err) { - return - } - } - - plan := types.Plan{Name: req.UpgradeName, Time: t, Height: req.UpgradeHeight, Info: req.UpgradeInfo} + plan := types.Plan{Name: req.UpgradeName, Height: req.UpgradeHeight, Info: req.UpgradeInfo} content := types.NewSoftwareUpgradeProposal(req.Title, req.Description, plan) msg, err := govtypes.NewMsgSubmitProposal(content, req.Deposit, fromAddr) if rest.CheckBadRequestError(w, err) { diff --git a/x/upgrade/doc.go b/x/upgrade/doc.go index 4ac16c878c16..b9d696914f94 100644 --- a/x/upgrade/doc.go +++ b/x/upgrade/doc.go @@ -1,7 +1,7 @@ /* Package upgrade provides a Cosmos SDK module that can be used for smoothly upgrading a live Cosmos chain to a new software version. It accomplishes this by providing a BeginBlocker hook that prevents the blockchain state -machine from proceeding once a pre-defined upgrade block time or height has been reached. The module does not prescribe +machine from proceeding once a pre-defined upgrade block height has been reached. The module does not prescribe anything regarding how governance decides to do an upgrade, but just the mechanism for coordinating the upgrade safely. Without software support for upgrades, upgrading a live chain is risky because all of the validators need to pause their state machines at exactly the same point in the process. If this is not done correctly, there can be state @@ -21,9 +21,9 @@ perform a migration, but also to identify if this is the old or new version (eg. a handler registered for the named upgrade). Once the release candidate along with an appropriate upgrade handler is frozen, -we can have a governance vote to approve this upgrade at some future block time -or block height (e.g. 200000). This is known as an upgrade.Plan. The v0.38.0 code will not know of this -handler, but will continue to run until block 200000, when the plan kicks in at BeginBlock. It will check +we can have a governance vote to approve this upgrade at some future block height (e.g. 200000). +This is known as an upgrade.Plan. The v0.38.0 code will not know of this handler, but will +continue to run until block 200000, when the plan kicks in at BeginBlock. It will check for existence of the handler, and finding it missing, know that it is running the obsolete software, and gracefully exit. @@ -54,7 +54,7 @@ should call ScheduleUpgrade to schedule an upgrade and ClearUpgradePlan to cance Performing Upgrades -Upgrades can be scheduled at either a predefined block height or time. Once this block height or time is reached, the +Upgrades can be scheduled at a predefined block height. Once this block height is reached, the existing software will cease to process ABCI messages and a new version with code that handles the upgrade must be deployed. All upgrades are coordinated by a unique upgrade name that cannot be reused on the same blockchain. In order for the upgrade module to know that the upgrade has been safely applied, a handler with the name of the upgrade must be installed. diff --git a/x/upgrade/keeper/keeper.go b/x/upgrade/keeper/keeper.go index e366ae09198e..3536937fbe3e 100644 --- a/x/upgrade/keeper/keeper.go +++ b/x/upgrade/keeper/keeper.go @@ -58,11 +58,7 @@ func (k Keeper) ScheduleUpgrade(ctx sdk.Context, plan types.Plan) error { return err } - if plan.Time.Unix() > 0 { - if !plan.Time.After(ctx.BlockHeader().Time) { - return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "upgrade cannot be scheduled in the past") - } - } else if plan.Height <= ctx.BlockHeight() { + if plan.Height <= ctx.BlockHeight() { return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "upgrade cannot be scheduled in the past") } diff --git a/x/upgrade/keeper/keeper_test.go b/x/upgrade/keeper/keeper_test.go index 48f0301d3ff1..a8f6cd30b533 100644 --- a/x/upgrade/keeper/keeper_test.go +++ b/x/upgrade/keeper/keeper_test.go @@ -63,16 +63,6 @@ func (s *KeeperTestSuite) TestScheduleUpgrade() { setup func() expPass bool }{ - { - name: "successful time schedule", - plan: types.Plan{ - Name: "all-good", - Info: "some text here", - Time: s.ctx.BlockTime().Add(time.Hour), - }, - setup: func() {}, - expPass: true, - }, { name: "successful height schedule", plan: types.Plan{ @@ -107,16 +97,6 @@ func (s *KeeperTestSuite) TestScheduleUpgrade() { setup: func() {}, expPass: false, }, - { - name: "unsuccessful time schedule: due date in past", - plan: types.Plan{ - Name: "all-good", - Info: "some text here", - Time: s.ctx.BlockTime(), - }, - setup: func() {}, - expPass: false, - }, { name: "unsuccessful height schedule: due date in past", plan: types.Plan{ diff --git a/x/upgrade/spec/01_concepts.md b/x/upgrade/spec/01_concepts.md index 54147f8b5ebd..9ff387fc75fa 100644 --- a/x/upgrade/spec/01_concepts.md +++ b/x/upgrade/spec/01_concepts.md @@ -7,7 +7,7 @@ order: 1 ## Plan The `x/upgrade` module defines a `Plan` type in which a live upgrade is scheduled -to occur. A `Plan` can be scheduled at a specific block height or time, but not both. +to occur. A `Plan` can be scheduled at a specific block height. A `Plan` is created once a (frozen) release candidate along with an appropriate upgrade `Handler` (see below) is agreed upon, where the `Name` of a `Plan` corresponds to a specific `Handler`. Typically, a `Plan` is created through a governance proposal @@ -30,7 +30,6 @@ for more info. ```go type Plan struct { Name string - Time Time Height int64 Info string } @@ -52,7 +51,7 @@ type UpgradeHandler func(Context, Plan) ``` During each `EndBlock` execution, the `x/upgrade` module checks if there exists a -`Plan` that should execute (is scheduled at that time or height). If so, the corresponding +`Plan` that should execute (is scheduled at that height). If so, the corresponding `Handler` is executed. If the `Plan` is expected to execute but no `Handler` is registered or if the binary was upgraded too early, the node will gracefully panic and exit. @@ -88,7 +87,7 @@ will ensure these `StoreUpgrades` takes place only in planned upgrade handler. Typically, a `Plan` is proposed and submitted through governance via a `SoftwareUpgradeProposal`. This proposal prescribes to the standard governance process. If the proposal passes, the `Plan`, which targets a specific `Handler`, is persisted and scheduled. The -upgrade can be delayed or hastened by updating the `Plan.Time` in a new proposal. +upgrade can be delayed or hastened by updating the `Plan.Height` in a new proposal. ```go type SoftwareUpgradeProposal struct { diff --git a/x/upgrade/spec/README.md b/x/upgrade/spec/README.md index eb34357071e6..82e2a719b07d 100644 --- a/x/upgrade/spec/README.md +++ b/x/upgrade/spec/README.md @@ -12,7 +12,7 @@ parent: `x/upgrade` is an implementation of a Cosmos SDK module that facilitates smoothly upgrading a live Cosmos chain to a new (breaking) software version. It accomplishes this by providing a `BeginBlocker` hook that prevents the blockchain state machine from -proceeding once a pre-defined upgrade block time or height has been reached. +proceeding once a pre-defined upgrade block height has been reached. The module does not prescribe anything regarding how governance decides to do an upgrade, but just the mechanism for coordinating the upgrade safely. Without software diff --git a/x/upgrade/types/plan.go b/x/upgrade/types/plan.go index 6088ecea15c4..57ac95027664 100644 --- a/x/upgrade/types/plan.go +++ b/x/upgrade/types/plan.go @@ -2,8 +2,6 @@ package types import ( "fmt" - "strings" - "time" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" @@ -11,11 +9,10 @@ import ( func (p Plan) String() string { due := p.DueAt() - dueUp := strings.ToUpper(due[0:1]) + due[1:] return fmt.Sprintf(`Upgrade Plan Name: %s %s - Info: %s.`, p.Name, dueUp, p.Info) + Info: %s.`, p.Name, due, p.Info) } // ValidateBasic does basic validation of a Plan @@ -23,14 +20,8 @@ func (p Plan) ValidateBasic() error { if len(p.Name) == 0 { return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "name cannot be empty") } - if p.Height < 0 { - return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "height cannot be negative") - } - if p.Time.Unix() <= 0 && p.Height == 0 { - return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "must set either time or height") - } - if p.Time.Unix() > 0 && p.Height != 0 { - return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "cannot set both time and height") + if p.Height <= 0 { + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "height must be greater than 0") } return nil @@ -38,9 +29,6 @@ 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.Unix() > 0 { - return !ctx.BlockTime().Before(p.Time) - } if p.Height > 0 { return p.Height <= ctx.BlockHeight() } @@ -49,8 +37,5 @@ 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.Unix() > 0 { - return fmt.Sprintf("time: %s", p.Time.UTC().Format(time.RFC3339)) - } - return fmt.Sprintf("height: %d", p.Height) + return fmt.Sprintf("Height: %d", p.Height) } diff --git a/x/upgrade/types/plan_test.go b/x/upgrade/types/plan_test.go index 37f5f5c9abcb..fe59fea52ffb 100644 --- a/x/upgrade/types/plan_test.go +++ b/x/upgrade/types/plan_test.go @@ -27,14 +27,6 @@ func TestPlanString(t *testing.T) { p types.Plan expect string }{ - "with time": { - p: types.Plan{ - Name: "due_time", - Info: "https://foo.bar", - Time: mustParseTime("2019-07-08T11:33:55Z"), - }, - expect: "Upgrade Plan\n Name: due_time\n Time: 2019-07-08T11:33:55Z\n Info: https://foo.bar.", - }, "with height": { p: types.Plan{ Name: "by height", @@ -65,14 +57,6 @@ func TestPlanValid(t *testing.T) { p types.Plan valid bool }{ - "proper": { - p: types.Plan{ - Name: "all-good", - Info: "some text here", - Time: mustParseTime("2019-07-08T11:33:55Z"), - }, - valid: true, - }, "proper by height": { p: types.Plan{ Name: "all-good", @@ -120,34 +104,7 @@ func TestShouldExecute(t *testing.T) { ctxHeight int64 expected bool }{ - "past time": { - p: types.Plan{ - Name: "do-good", - Info: "some text here", - Time: mustParseTime("2019-07-08T11:33:55Z"), - }, - ctxTime: mustParseTime("2019-07-08T11:32:00Z"), - ctxHeight: 100000, - expected: false, - }, - "on time": { - p: types.Plan{ - Name: "do-good", - Time: mustParseTime("2019-07-08T11:33:55Z"), - }, - ctxTime: mustParseTime("2019-07-08T11:33:55Z"), - ctxHeight: 100000, - expected: true, - }, - "future time": { - p: types.Plan{ - Name: "do-good", - Time: mustParseTime("2019-07-08T11:33:55Z"), - }, - ctxTime: mustParseTime("2019-07-08T11:33:57Z"), - ctxHeight: 100000, - expected: true, - }, + "past height": { p: types.Plan{ Name: "do-good", diff --git a/x/upgrade/types/proposal_test.go b/x/upgrade/types/proposal_test.go index 4f5ed16a82fa..19c5321ce7e3 100644 --- a/x/upgrade/types/proposal_test.go +++ b/x/upgrade/types/proposal_test.go @@ -26,9 +26,9 @@ func TestContentAccessors(t *testing.T) { }{ "upgrade": { p: types.NewSoftwareUpgradeProposal("Title", "desc", types.Plan{ - Name: "due_time", - Info: "https://foo.bar", - Time: mustParseTime("2019-07-08T11:33:55Z"), + Name: "due_height", + Info: "https://foo.bar", + Height: 99999999999, }), title: "Title", desc: "desc", diff --git a/x/upgrade/types/upgrade.pb.go b/x/upgrade/types/upgrade.pb.go index ae27a70fd5dc..5ff492b021d7 100644 --- a/x/upgrade/types/upgrade.pb.go +++ b/x/upgrade/types/upgrade.pb.go @@ -8,19 +8,16 @@ import ( _ "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" _ "google.golang.org/protobuf/types/known/timestamppb" 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. @@ -38,9 +35,6 @@ type Plan struct { // assumed that the software is out-of-date when the upgrade Time or Height is // reached and the software will exit. Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // The time after which the upgrade must be performed. - // Leave set to its zero value to use a pre-defined Height instead. - Time time.Time `protobuf:"bytes,2,opt,name=time,proto3,stdtime" json:"time"` // The height at which the upgrade must be performed. // Only used if Time is not set. Height int64 `protobuf:"varint,3,opt,name=height,proto3" json:"height,omitempty"` @@ -171,32 +165,30 @@ func init() { } var fileDescriptor_ccf2a7d4d7b48dca = []byte{ - // 391 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x52, 0xb1, 0x6e, 0xdb, 0x30, - 0x10, 0x15, 0x6b, 0x5a, 0xb0, 0xe9, 0xa5, 0x20, 0x0c, 0x57, 0x35, 0x5a, 0x4a, 0x30, 0x3a, 0x78, - 0x68, 0x29, 0xd8, 0x05, 0x8a, 0xa2, 0xa3, 0xbb, 0x75, 0x28, 0x0c, 0xb5, 0x5d, 0x0a, 0x64, 0xa0, - 0x64, 0x5a, 0x16, 0x22, 0x89, 0x82, 0x44, 0x27, 0xf1, 0x57, 0xc4, 0x43, 0x3e, 0x20, 0x9f, 0xe3, - 0xd1, 0xa3, 0xa7, 0x24, 0xb6, 0x97, 0x7c, 0x46, 0x20, 0x52, 0x0a, 0x82, 0x20, 0x63, 0x26, 0xbd, - 0x3b, 0xbc, 0x7b, 0xf7, 0xf4, 0x78, 0xe8, 0x53, 0x20, 0x8a, 0x44, 0x14, 0xee, 0x32, 0x0b, 0x73, - 0x36, 0xe3, 0xee, 0xd9, 0xc8, 0xe7, 0x92, 0x8d, 0xea, 0x9a, 0x66, 0xb9, 0x90, 0x02, 0xf7, 0x34, - 0x8b, 0xd6, 0xdd, 0x8a, 0xd5, 0x7f, 0x1f, 0x0a, 0x11, 0xc6, 0xdc, 0x55, 0x2c, 0x7f, 0x39, 0x77, - 0x59, 0xba, 0xd2, 0x23, 0xfd, 0x6e, 0x28, 0x42, 0xa1, 0xa0, 0x5b, 0xa2, 0xaa, 0x6b, 0x3f, 0x1f, - 0x90, 0x51, 0xc2, 0x0b, 0xc9, 0x92, 0x4c, 0x13, 0x06, 0x57, 0x00, 0xc1, 0x69, 0xcc, 0x52, 0x8c, - 0x11, 0x4c, 0x59, 0xc2, 0x2d, 0xe0, 0x80, 0x61, 0xdb, 0x53, 0x18, 0x7f, 0x47, 0xb0, 0xe4, 0x5b, - 0x6f, 0x1c, 0x30, 0xec, 0x8c, 0xfb, 0x54, 0x8b, 0xd1, 0x5a, 0x8c, 0xfe, 0xad, 0xc5, 0x26, 0xad, - 0xcd, 0x8d, 0x6d, 0xac, 0x6f, 0x6d, 0xe0, 0xa9, 0x09, 0xdc, 0x43, 0xe6, 0x82, 0x47, 0xe1, 0x42, - 0x5a, 0x0d, 0x07, 0x0c, 0x1b, 0x5e, 0x55, 0x95, 0x5b, 0xa2, 0x74, 0x2e, 0x2c, 0xa8, 0xb7, 0x94, - 0xf8, 0x07, 0xbc, 0xbf, 0xb6, 0xc1, 0x2f, 0xd8, 0x6a, 0xbe, 0x35, 0x3d, 0x53, 0x64, 0x32, 0x12, - 0xe9, 0xe0, 0x12, 0xa0, 0x77, 0x7f, 0xc4, 0x5c, 0x9e, 0xb3, 0x9c, 0xff, 0xd3, 0x21, 0x4c, 0x73, - 0x91, 0x89, 0x82, 0xc5, 0xb8, 0x8b, 0x9a, 0x32, 0x92, 0x71, 0x6d, 0x55, 0x17, 0xd8, 0x41, 0x9d, - 0x19, 0x2f, 0x82, 0x3c, 0x52, 0x02, 0xca, 0x72, 0xdb, 0x7b, 0xda, 0xc2, 0xdf, 0x10, 0xcc, 0x62, - 0x96, 0x2a, 0x47, 0x9d, 0xf1, 0x07, 0xfa, 0x72, 0xc6, 0xb4, 0x4c, 0x63, 0x02, 0xcb, 0xff, 0xf1, - 0x14, 0x5f, 0xfb, 0x1b, 0x9c, 0xa0, 0x8f, 0x3f, 0x59, 0x1a, 0xf0, 0xf8, 0x95, 0x6d, 0x69, 0xf9, - 0xc9, 0xef, 0xcd, 0x9e, 0x18, 0xbb, 0x3d, 0x31, 0x36, 0x07, 0x02, 0xb6, 0x07, 0x02, 0xee, 0x0e, - 0x04, 0xac, 0x8f, 0xc4, 0xd8, 0x1e, 0x89, 0xb1, 0x3b, 0x12, 0xe3, 0xff, 0xe7, 0x30, 0x92, 0x8b, - 0xa5, 0x4f, 0x03, 0x91, 0xb8, 0xd5, 0x11, 0xe9, 0xcf, 0x97, 0x62, 0x76, 0xea, 0x5e, 0x3c, 0x5e, - 0x94, 0x5c, 0x65, 0xbc, 0xf0, 0x4d, 0xf5, 0x48, 0x5f, 0x1f, 0x02, 0x00, 0x00, 0xff, 0xff, 0x9b, - 0x57, 0x9e, 0x92, 0x70, 0x02, 0x00, 0x00, + // 364 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x92, 0xcd, 0x4e, 0xea, 0x40, + 0x14, 0xc7, 0x3b, 0x30, 0x34, 0xdc, 0x61, 0x43, 0x1a, 0xc2, 0xed, 0x25, 0xd7, 0x81, 0x10, 0x17, + 0x2c, 0xb4, 0x0d, 0x9a, 0xb8, 0x70, 0x89, 0x3b, 0x16, 0x86, 0xd4, 0xb8, 0x31, 0x71, 0x31, 0x2d, + 0xd3, 0xd2, 0xd8, 0xf6, 0x34, 0xed, 0xa0, 0xf2, 0x14, 0xfa, 0x08, 0x3e, 0x0e, 0x4b, 0x96, 0xac, + 0x8c, 0xc0, 0xc6, 0xc7, 0x30, 0x9d, 0x29, 0xc6, 0x18, 0x97, 0xae, 0xe6, 0x7f, 0xce, 0xfc, 0xce, + 0xd7, 0xcc, 0x21, 0x87, 0x1e, 0xe4, 0x31, 0xe4, 0xf6, 0x3c, 0x0d, 0x32, 0x36, 0xe5, 0xf6, 0xfd, + 0xd0, 0xe5, 0x82, 0x0d, 0xf7, 0xb6, 0x95, 0x66, 0x20, 0xc0, 0x68, 0x2b, 0xca, 0xda, 0x7b, 0x4b, + 0xaa, 0xf3, 0x2f, 0x00, 0x08, 0x22, 0x6e, 0x4b, 0xca, 0x9d, 0xfb, 0x36, 0x4b, 0x16, 0x2a, 0xa4, + 0xd3, 0x0a, 0x20, 0x00, 0x29, 0xed, 0x42, 0x95, 0xde, 0xee, 0xf7, 0x00, 0x11, 0xc6, 0x3c, 0x17, + 0x2c, 0x4e, 0x15, 0xd0, 0xf7, 0x09, 0x9e, 0x44, 0x2c, 0x31, 0x0c, 0x82, 0x13, 0x16, 0x73, 0x13, + 0xf5, 0xd0, 0xe0, 0x8f, 0x23, 0xb5, 0xd1, 0x26, 0xfa, 0x8c, 0x87, 0xc1, 0x4c, 0x98, 0xd5, 0x1e, + 0x1a, 0x54, 0x9d, 0xd2, 0x2a, 0xd8, 0x30, 0xf1, 0xc1, 0xc4, 0x8a, 0x2d, 0xf4, 0x39, 0x7e, 0x7f, + 0xe9, 0xa2, 0x31, 0xae, 0x57, 0x9a, 0xd5, 0x31, 0xae, 0xd7, 0x9a, 0xba, 0x83, 0x8b, 0x52, 0x8e, + 0x0e, 0xa9, 0x08, 0x21, 0xe9, 0x3f, 0x21, 0xf2, 0xf7, 0x0a, 0x7c, 0xf1, 0xc0, 0x32, 0x7e, 0xad, + 0xa6, 0x9a, 0x64, 0x90, 0x42, 0xce, 0x22, 0xa3, 0x45, 0x6a, 0x22, 0x14, 0xd1, 0xbe, 0xb8, 0x32, + 0x8c, 0x1e, 0x69, 0x4c, 0x79, 0xee, 0x65, 0xa1, 0x4c, 0x60, 0x56, 0xe4, 0xdd, 0x57, 0x97, 0x71, + 0x46, 0x70, 0x1a, 0xb1, 0x44, 0x76, 0xd7, 0x38, 0xf9, 0x6f, 0xfd, 0xfc, 0x68, 0x56, 0x31, 0xdf, + 0x08, 0x2f, 0x5f, 0xbb, 0x9a, 0x23, 0x79, 0xd5, 0x6b, 0xff, 0x96, 0x1c, 0x5c, 0xb0, 0xc4, 0xe3, + 0xd1, 0x2f, 0xb7, 0xa5, 0xd2, 0x8f, 0x2e, 0x97, 0x1b, 0xaa, 0xad, 0x37, 0x54, 0x5b, 0x6e, 0x29, + 0x5a, 0x6d, 0x29, 0x7a, 0xdb, 0x52, 0xf4, 0xbc, 0xa3, 0xda, 0x6a, 0x47, 0xb5, 0xf5, 0x8e, 0x6a, + 0x37, 0x47, 0x41, 0x28, 0x66, 0x73, 0xd7, 0xf2, 0x20, 0xb6, 0xcb, 0xad, 0x50, 0xc7, 0x71, 0x3e, + 0xbd, 0xb3, 0x1f, 0x3f, 0x57, 0x44, 0x2c, 0x52, 0x9e, 0xbb, 0xba, 0xfc, 0xaf, 0xd3, 0x8f, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xb1, 0x05, 0xd5, 0x12, 0x41, 0x02, 0x00, 0x00, } func (this *Plan) Equal(that interface{}) bool { @@ -221,9 +213,6 @@ func (this *Plan) Equal(that interface{}) bool { if this.Name != that1.Name { return false } - if !this.Time.Equal(that1.Time) { - return false - } if this.Height != that1.Height { return false } @@ -321,14 +310,6 @@ func (m *Plan) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x18 } - n1, err1 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):]) - if err1 != nil { - return 0, err1 - } - i -= n1 - i = encodeVarintUpgrade(dAtA, i, uint64(n1)) - i-- - dAtA[i] = 0x12 if len(m.Name) > 0 { i -= len(m.Name) copy(dAtA[i:], m.Name) @@ -444,8 +425,6 @@ func (m *Plan) Size() (n int) { if l > 0 { n += 1 + l + sovUpgrade(uint64(l)) } - l = github_com_gogo_protobuf_types.SizeOfStdTime(m.Time) - n += 1 + l + sovUpgrade(uint64(l)) if m.Height != 0 { n += 1 + sovUpgrade(uint64(m.Height)) } @@ -559,39 +538,6 @@ func (m *Plan) Unmarshal(dAtA []byte) error { } m.Name = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 2: - 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 ErrIntOverflowUpgrade - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthUpgrade - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthUpgrade - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.Time, dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex case 3: if wireType != 0 { return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) From c219c72e57060fda715035580141ce108ddd21c6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Mar 2021 08:44:02 +0000 Subject: [PATCH 186/214] build(deps): bump github.com/prometheus/common from 0.18.0 to 0.19.0 (#8874) Bumps [github.com/prometheus/common](https://github.com/prometheus/common) from 0.18.0 to 0.19.0. - [Release notes](https://github.com/prometheus/common/releases) - [Commits](https://github.com/prometheus/common/compare/v0.18.0...v0.19.0) 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 b23c929c8d09..6f88f451cd5b 100644 --- a/go.mod +++ b/go.mod @@ -33,7 +33,7 @@ require ( github.com/pelletier/go-toml v1.8.1 // indirect github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.9.0 - github.com/prometheus/common v0.18.0 + github.com/prometheus/common v0.19.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 06f18fa3feea..b8d2468d1509 100644 --- a/go.sum +++ b/go.sum @@ -557,8 +557,8 @@ github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8b 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/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= -github.com/prometheus/common v0.18.0 h1:WCVKW7aL6LEe1uryfI9dnEc2ZqNB1Fn0ok930v0iL1Y= -github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= +github.com/prometheus/common v0.19.0 h1:Itb4+NjG9wRdkAWgVucbM/adyIXxEhbw0866e0uZE6A= +github.com/prometheus/common v0.19.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 a4b7f7611065f310110082c65d991b0626ba4dbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?colin=20axn=C3=A9r?= <25233464+colin-axner@users.noreply.github.com> Date: Mon, 15 Mar 2021 11:03:18 +0100 Subject: [PATCH 187/214] update CHANGELOG to remove x/ibc notions (#8863) Co-authored-by: Alessio Treglia --- CHANGELOG.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 437d6af38149..a8819d154f7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -67,8 +67,6 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### 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. -* (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 * (x/bank) [\#8656](https://github.com/cosmos/cosmos-sdk/pull/8656) balance and supply are now correctly tracked via `coin_spent`, `coin_received`, `coinbase` and `burn` events. @@ -79,7 +77,6 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (x/bank) [\#8614](https://github.com/cosmos/cosmos-sdk/issues/8614) Add `Name` and `Symbol` fields to denom metadata * (x/auth) [\#8522](https://github.com/cosmos/cosmos-sdk/pull/8522) Allow to query all stored accounts -* (x/ibc) [\#7949](https://github.com/cosmos/cosmos-sdk/issues/7949) Standardized channel `Acknowledgement` moved to its own file. Codec registration redundancy removed. * (crypto/types) [\#8600](https://github.com/cosmos/cosmos-sdk/pull/8600) `CompactBitArray`: optimize the `NumTrueBitsBefore` method and add an `Equal` method. * (grpc) [\#8815](https://github.com/cosmos/cosmos-sdk/pull/8815) Add orderBy parameter to `TxsByEvents` endpoint. From d02a39739be4850548c8c157660cb952b83e2ac7 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Mon, 15 Mar 2021 10:15:48 +0000 Subject: [PATCH 188/214] server: try avoid the "address already in use" error (#8842) Replace defer l.Close() with l.Close() to shutdown the listener as fast as possible to avoid the "bind: address already in use" error that so often occurs in CI build. From: https://github.com/phayes/freeport/pull/8 Reference: #6671 Co-authored-by: Amaury <1293565+amaurym@users.noreply.github.com> --- server/test_helpers.go | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/server/test_helpers.go b/server/test_helpers.go index 0bc6bac8014e..bb19df695d45 100644 --- a/server/test_helpers.go +++ b/server/test_helpers.go @@ -13,16 +13,10 @@ func FreeTCPAddr() (addr, port string, err error) { return "", "", err } - closer := func() { - err := l.Close() - if err != nil { - // TODO: Handle with #870 - panic(err) - } + if err := l.Close(); err != nil { + return "", "", fmt.Errorf("couldn't close the listener: %w", err) } - defer closer() - portI := l.Addr().(*net.TCPAddr).Port port = fmt.Sprintf("%d", portI) addr = fmt.Sprintf("tcp://0.0.0.0:%s", port) From 5f71e93b1e0f9a7d9617f5ea88f5c18b73361a7b Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Mon, 15 Mar 2021 12:18:46 +0000 Subject: [PATCH 189/214] add --output-document to multisign-batch (#8873) Closes: #8870 Co-authored-by: SaReN --- x/auth/client/cli/tx_multisign.go | 12 +++++++++++- x/auth/client/cli/tx_sign.go | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/x/auth/client/cli/tx_multisign.go b/x/auth/client/cli/tx_multisign.go index c04d37123c2f..7fdcace968f5 100644 --- a/x/auth/client/cli/tx_multisign.go +++ b/x/auth/client/cli/tx_multisign.go @@ -217,6 +217,7 @@ The SIGN_MODE_DIRECT sign mode is not supported.' flagMultisig, "", "Address of the multisig account that the transaction signs on behalf of", ) + cmd.Flags().String(flags.FlagOutputDocument, "", "The document is written to the given file instead of STDOUT") flags.AddTxFlagsToCmd(cmd) return cmd @@ -277,6 +278,15 @@ func makeBatchMultisignCmd() func(cmd *cobra.Command, args []string) error { txFactory = txFactory.WithAccountNumber(accnum).WithSequence(seq) } + // prepare output document + closeFunc, err := setOutputFile(cmd) + if err != nil { + return err + } + + defer closeFunc() + clientCtx.WithOutput(cmd.OutOrStdout()) + for i := 0; scanner.Scan(); i++ { txBldr, err := txCfg.WrapTxBuilder(scanner.Tx()) if err != nil { @@ -350,7 +360,7 @@ func makeBatchMultisignCmd() func(cmd *cobra.Command, args []string) error { txFactory = txFactory.WithSequence(sequence) } - return nil + return scanner.UnmarshalErr() } } diff --git a/x/auth/client/cli/tx_sign.go b/x/auth/client/cli/tx_sign.go index 955554512125..f814f9b99a41 100644 --- a/x/auth/client/cli/tx_sign.go +++ b/x/auth/client/cli/tx_sign.go @@ -137,7 +137,7 @@ func makeSignBatchCmd() func(cmd *cobra.Command, args []string) error { return err } - return scanner.Err() + return scanner.UnmarshalErr() } } From d4d27e1c0c138d76ab3082ba8e380d4d26db050a Mon Sep 17 00:00:00 2001 From: Amaury <1293565+amaurym@users.noreply.github.com> Date: Mon, 15 Mar 2021 13:42:10 +0100 Subject: [PATCH 190/214] Fix multisig LegacyAminoPubKey Amino marshaling (#8841) * Use v034auth RegisterCrypto * Add custom amino for LegacyAminoPubKey * Fix registercrypto * Revert old PR * revert some genutil stuff * Add comment * Add changelog * Remove binary marshalling * Fix lint * Fix lint again * Fix lint, 3rd time's a charm * ignore wrong linter warning * Fix UnmarshalAmioJSON Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Alessio Treglia Co-authored-by: Anil Kumar Kammari --- CHANGELOG.md | 1 + crypto/keys/multisig/amino.go | 88 +++++++++++++++++++++++++++ crypto/keys/multisig/codec.go | 3 + crypto/keys/multisig/multisig_test.go | 78 +++++++++++++++++++++++- x/auth/legacy/legacytx/stdtx.go | 2 +- x/auth/legacy/v040/migrate.go | 11 +--- x/genutil/legacy/v038/migrate.go | 2 + 7 files changed, 172 insertions(+), 13 deletions(-) create mode 100644 crypto/keys/multisig/amino.go diff --git a/CHANGELOG.md b/CHANGELOG.md index a8819d154f7e..ae7ce9a177fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -86,6 +86,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (x/bank) [\#8434](https://github.com/cosmos/cosmos-sdk/pull/8434) Fix legacy REST API `GET /bank/total` and `GET /bank/total/{denom}` in swagger * (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 +* (crypto) [\#8841](https://github.com/cosmos/cosmos-sdk/pull/8841) Fix legacy multisig amino marshaling, allowing migrations to work between v0.39 and v0.40+. ## [v0.42.0](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.42.0) - 2021-03-08 diff --git a/crypto/keys/multisig/amino.go b/crypto/keys/multisig/amino.go new file mode 100644 index 000000000000..4849a23173d2 --- /dev/null +++ b/crypto/keys/multisig/amino.go @@ -0,0 +1,88 @@ +package multisig + +import ( + types "github.com/cosmos/cosmos-sdk/codec/types" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +// tmMultisig implements a K of N threshold multisig. It is used for +// Amino JSON marshaling of LegacyAminoPubKey (see below for details). +// +// This struct is copy-pasted from: +// https://github.com/tendermint/tendermint/blob/v0.33.9/crypto/multisig/threshold_pubkey.go +// +// This struct was used in the SDK <=0.39. In 0.40 and the switch to protobuf, +// it has been converted to LegacyAminoPubKey. However, there's one difference: +// the threshold field was an `uint` before, and an `uint32` after. This caused +// amino marshaling to be breaking: amino marshals `uint32` as a JSON number, +// and `uint` as a JSON string. +// +// In this file, we're overriding LegacyAminoPubKey's default JSON Amino +// marshaling by using this struct. Please note that we are NOT overriding the +// Amino binary marshaling, as that _might_ introduce breaking changes in the +// keyring, where multisigs are amino-binary-encoded. +// +// ref: https://github.com/cosmos/cosmos-sdk/issues/8776 +type tmMultisig struct { + K uint `json:"threshold"` + PubKeys []cryptotypes.PubKey `json:"pubkeys"` +} + +// protoToTm converts a LegacyAminoPubKey into a tmMultisig. +func protoToTm(protoPk *LegacyAminoPubKey) (tmMultisig, error) { + var ok bool + pks := make([]cryptotypes.PubKey, len(protoPk.PubKeys)) + for i, pk := range protoPk.PubKeys { + pks[i], ok = pk.GetCachedValue().(cryptotypes.PubKey) + if !ok { + return tmMultisig{}, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "expected %T, got %T", (cryptotypes.PubKey)(nil), pk.GetCachedValue()) + } + } + + return tmMultisig{ + K: uint(protoPk.Threshold), + PubKeys: pks, + }, nil +} + +// tmToProto converts a tmMultisig into a LegacyAminoPubKey. +func tmToProto(tmPk tmMultisig) (*LegacyAminoPubKey, error) { + var err error + pks := make([]*types.Any, len(tmPk.PubKeys)) + for i, pk := range tmPk.PubKeys { + pks[i], err = types.NewAnyWithValue(pk) + if err != nil { + return nil, err + } + } + + return &LegacyAminoPubKey{ + Threshold: uint32(tmPk.K), + PubKeys: pks, + }, nil +} + +// MarshalAminoJSON overrides amino JSON unmarshaling. +func (m LegacyAminoPubKey) MarshalAminoJSON() (tmMultisig, error) { //nolint:golint + return protoToTm(&m) +} + +// UnmarshalAminoJSON overrides amino JSON unmarshaling. +func (m *LegacyAminoPubKey) UnmarshalAminoJSON(tmPk tmMultisig) error { + protoPk, err := tmToProto(tmPk) + if err != nil { + return err + } + + // Instead of just doing `*m = *protoPk`, we prefer to modify in-place the + // existing Anys inside `m` (instead of allocating new Anys), as so not to + // break the `.compat` fields in the existing Anys. + for i := range m.PubKeys { + m.PubKeys[i].TypeUrl = protoPk.PubKeys[i].TypeUrl + m.PubKeys[i].Value = protoPk.PubKeys[i].Value + } + m.Threshold = protoPk.Threshold + + return nil +} diff --git a/crypto/keys/multisig/codec.go b/crypto/keys/multisig/codec.go index b92576e4f3f5..d501e1b427cf 100644 --- a/crypto/keys/multisig/codec.go +++ b/crypto/keys/multisig/codec.go @@ -15,6 +15,9 @@ const ( PubKeyAminoRoute = "tendermint/PubKeyMultisigThreshold" ) +//nolint +// Deprecated: Amino is being deprecated in the SDK. But even if you need to +// use Amino for some reason, please use `codec/legacy.Cdc` instead. var AminoCdc = codec.NewLegacyAmino() func init() { diff --git a/crypto/keys/multisig/multisig_test.go b/crypto/keys/multisig/multisig_test.go index 69b4f10d2694..197a433a72eb 100644 --- a/crypto/keys/multisig/multisig_test.go +++ b/crypto/keys/multisig/multisig_test.go @@ -6,7 +6,9 @@ import ( "github.com/stretchr/testify/require" "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/legacy" "github.com/cosmos/cosmos-sdk/codec/types" + cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" @@ -272,12 +274,12 @@ func TestPubKeyMultisigThresholdAminoToIface(t *testing.T) { pubkeys, _ := generatePubKeysAndSignatures(5, msg) multisigKey := kmultisig.NewLegacyAminoPubKey(2, pubkeys) - ab, err := kmultisig.AminoCdc.MarshalBinaryLengthPrefixed(multisigKey) + ab, err := legacy.Cdc.MarshalBinaryLengthPrefixed(multisigKey) require.NoError(t, err) // like other cryptotypes.Pubkey implementations (e.g. ed25519.PubKey), // LegacyAminoPubKey should be deserializable into a cryptotypes.LegacyAminoPubKey: var pubKey kmultisig.LegacyAminoPubKey - err = kmultisig.AminoCdc.UnmarshalBinaryLengthPrefixed(ab, &pubKey) + err = legacy.Cdc.UnmarshalBinaryLengthPrefixed(ab, &pubKey) require.NoError(t, err) require.Equal(t, multisigKey.Equals(&pubKey), true) @@ -329,3 +331,75 @@ func reorderPubKey(pk *kmultisig.LegacyAminoPubKey) (other *kmultisig.LegacyAmin other = &kmultisig.LegacyAminoPubKey{Threshold: 2, PubKeys: pubkeysCpy} return } + +func TestAminoBinary(t *testing.T) { + pubKey1 := secp256k1.GenPrivKey().PubKey() + pubKey2 := secp256k1.GenPrivKey().PubKey() + multisigKey := kmultisig.NewLegacyAminoPubKey(2, []cryptotypes.PubKey{pubKey1, pubKey2}) + + // Do a round-trip key->bytes->key. + bz, err := legacy.Cdc.MarshalBinaryBare(multisigKey) + require.NoError(t, err) + var newMultisigKey cryptotypes.PubKey + err = legacy.Cdc.UnmarshalBinaryBare(bz, &newMultisigKey) + require.NoError(t, err) + require.Equal(t, multisigKey.Threshold, newMultisigKey.(*kmultisig.LegacyAminoPubKey).Threshold) +} + +func TestAminoMarshalJSON(t *testing.T) { + pubKey1 := secp256k1.GenPrivKey().PubKey() + pubKey2 := secp256k1.GenPrivKey().PubKey() + multisigKey := kmultisig.NewLegacyAminoPubKey(2, []cryptotypes.PubKey{pubKey1, pubKey2}) + + bz, err := legacy.Cdc.MarshalJSON(multisigKey) + require.NoError(t, err) + + // Note the quotes around `"2"`. They are present because we are overriding + // the Amino JSON marshaling of LegacyAminoPubKey (using tmMultisig). + // Without the override, there would not be any quotes. + require.Contains(t, string(bz), "\"threshold\":\"2\"") +} + +func TestAminoUnmarshalJSON(t *testing.T) { + // This is a real multisig from the Akash chain. It has been exported from + // v0.39, hence the `threshold` field as a string. + // We are testing that when unmarshaling this JSON into a LegacyAminoPubKey + // with amino, there's no error. + // ref: https://github.com/cosmos/cosmos-sdk/issues/8776 + pkJSON := `{ + "type": "tendermint/PubKeyMultisigThreshold", + "value": { + "pubkeys": [ + { + "type": "tendermint/PubKeySecp256k1", + "value": "AzYxq2VNeD10TyABwOgV36OVWDIMn8AtI4OFA0uQX2MK" + }, + { + "type": "tendermint/PubKeySecp256k1", + "value": "A39cdsrm00bTeQ3RVZVqjkH8MvIViO9o99c8iLiNO35h" + }, + { + "type": "tendermint/PubKeySecp256k1", + "value": "A/uLLCZph8MkFg2tCxqSMGwFfPHdt1kkObmmrqy9aiYD" + }, + { + "type": "tendermint/PubKeySecp256k1", + "value": "A4mOMhM5gPDtBAkAophjRs6uDGZm4tD4Dbok3ai4qJi8" + }, + { + "type": "tendermint/PubKeySecp256k1", + "value": "A90icFucrjNNz2SAdJWMApfSQcARIqt+M2x++t6w5fFs" + } + ], + "threshold": "3" + } +}` + + cdc := codec.NewLegacyAmino() + cryptocodec.RegisterCrypto(cdc) + + var pk cryptotypes.PubKey + err := cdc.UnmarshalJSON([]byte(pkJSON), &pk) + require.NoError(t, err) + require.Equal(t, uint32(3), pk.(*kmultisig.LegacyAminoPubKey).Threshold) +} diff --git a/x/auth/legacy/legacytx/stdtx.go b/x/auth/legacy/legacytx/stdtx.go index c1a982c85efe..c2b60736e4c3 100644 --- a/x/auth/legacy/legacytx/stdtx.go +++ b/x/auth/legacy/legacytx/stdtx.go @@ -287,7 +287,7 @@ func (tx StdTx) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { // Signatures contain PubKeys, which need to be unpacked. for _, s := range tx.Signatures { - err := codectypes.UnpackInterfaces(s, unpacker) + err := s.UnpackInterfaces(unpacker) if err != nil { return err } diff --git a/x/auth/legacy/v040/migrate.go b/x/auth/legacy/v040/migrate.go index f819a1a33d8b..4ba3e0cb7c81 100644 --- a/x/auth/legacy/v040/migrate.go +++ b/x/auth/legacy/v040/migrate.go @@ -2,7 +2,6 @@ package v040 import ( codectypes "github.com/cosmos/cosmos-sdk/codec/types" - multisigtypes "github.com/cosmos/cosmos-sdk/crypto/keys/multisig" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" v039auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v039" v040auth "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -13,15 +12,7 @@ import ( func convertBaseAccount(old *v039auth.BaseAccount) *v040auth.BaseAccount { var any *codectypes.Any - _, ok := old.PubKey.(*multisigtypes.LegacyAminoPubKey) - - // If pubkey is multisig type, then leave it as nil for now - // Ref: https://github.com/cosmos/cosmos-sdk/issues/8776#issuecomment-790552126 - // Else if the old genesis had a pubkey, we pack it inside an Any. - // Or else, we just leave it nil. - if ok { - // TODO migrate multisig public_keys - } else if old.PubKey != nil { + if old.PubKey != nil { var err error any, err = codectypes.NewAnyWithValue(old.PubKey) if err != nil { diff --git a/x/genutil/legacy/v038/migrate.go b/x/genutil/legacy/v038/migrate.go index d0ca4c4186bc..017d0e68fa53 100644 --- a/x/genutil/legacy/v038/migrate.go +++ b/x/genutil/legacy/v038/migrate.go @@ -3,6 +3,7 @@ package v038 import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" + cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" v036auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v036" v038auth "github.com/cosmos/cosmos-sdk/x/auth/legacy/v038" v036distr "github.com/cosmos/cosmos-sdk/x/distribution/legacy/v036" @@ -19,6 +20,7 @@ import ( // Migrate migrates exported state from v0.36/v0.37 to a v0.38 genesis state. func Migrate(appState types.AppMap, _ client.Context) types.AppMap { v036Codec := codec.NewLegacyAmino() + cryptocodec.RegisterCrypto(v036Codec) v036gov.RegisterLegacyAminoCodec(v036Codec) v036distr.RegisterLegacyAminoCodec(v036Codec) v036params.RegisterLegacyAminoCodec(v036Codec) From 42919c8f338535d1bf2147ae299026a8389eeae8 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Mon, 15 Mar 2021 13:50:12 +0000 Subject: [PATCH 191/214] server: wrap errors (#8879) Follow-up of #8842 --- server/test_helpers.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server/test_helpers.go b/server/test_helpers.go index bb19df695d45..68d87aa08d62 100644 --- a/server/test_helpers.go +++ b/server/test_helpers.go @@ -3,6 +3,8 @@ package server import ( "fmt" "net" + + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) // Get a free address for a test tendermint server @@ -14,7 +16,7 @@ func FreeTCPAddr() (addr, port string, err error) { } if err := l.Close(); err != nil { - return "", "", fmt.Errorf("couldn't close the listener: %w", err) + return "", "", sdkerrors.Wrap(err, "couldn't close the listener") } portI := l.Addr().(*net.TCPAddr).Port From e23d361a6f9b72073e716d754ea66a922c814044 Mon Sep 17 00:00:00 2001 From: Amaury <1293565+amaurym@users.noreply.github.com> Date: Mon, 15 Mar 2021 17:53:13 +0100 Subject: [PATCH 192/214] Allow proto CI to pass when no proto files changed (#8881) --- .github/workflows/proto.yml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/.github/workflows/proto.yml b/.github/workflows/proto.yml index 13f05c131a1f..503bed0c43cd 100644 --- a/.github/workflows/proto.yml +++ b/.github/workflows/proto.yml @@ -3,19 +3,28 @@ name: Protobuf # This workflow is only run when a .proto file has been changed on: pull_request: - paths: - - "**.proto" + jobs: lint: runs-on: ubuntu-latest timeout-minutes: 5 steps: - uses: actions/checkout@master + - uses: technote-space/get-diff-action@v4 + with: + PATTERNS: | + **/**.proto - name: lint run: make proto-lint + if: env.GIT_DIFF breakage: runs-on: ubuntu-latest steps: - uses: actions/checkout@master + - uses: technote-space/get-diff-action@v4 + with: + PATTERNS: | + **/**.proto - name: check-breakage run: make proto-check-breaking + if: env.GIT_DIFF From 553aac50305b02e406cd51479b48a99ca34b4a4e Mon Sep 17 00:00:00 2001 From: MD Aleem <72057206+aleem1314@users.noreply.github.com> Date: Mon, 15 Mar 2021 23:26:33 +0530 Subject: [PATCH 193/214] add orderBy parameter to TxsByEvents (#8815) * add orderBy parameter to grpc query * add orderby parameter * change orderBy param to enum * lint * proto lint * add changelog * Update x/auth/tx/service.go Co-authored-by: Amaury <1293565+amaurym@users.noreply.github.com> Co-authored-by: Alessio Treglia Co-authored-by: Jonathan Gimeno Co-authored-by: Amaury <1293565+amaurym@users.noreply.github.com> --- x/auth/tx/service.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/auth/tx/service.go b/x/auth/tx/service.go index 2d73a110b704..4ceebb787013 100644 --- a/x/auth/tx/service.go +++ b/x/auth/tx/service.go @@ -170,6 +170,6 @@ func parseOrderBy(orderBy txtypes.OrderBy) string { case txtypes.OrderBy_ORDER_BY_DESC: return "desc" default: - return "asc" + return "" // Defaults to Tendermint's default, which is `asc` now. } } From e66c4e6f9c53ae86c51bd88efd85f6de118dce86 Mon Sep 17 00:00:00 2001 From: Cyrus Goh Date: Mon, 15 Mar 2021 12:21:08 -0700 Subject: [PATCH 194/214] =?UTF-8?q?docs:=20update=20dropdown=200.41=20?= =?UTF-8?q?=E2=86=92=200.42=20(#8884)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * redirect /0.41 → /0.42 --- docs/.vuepress/config.js | 4 ++-- docs/.vuepress/enhanceApp.js | 1 + docs/versions | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 59e33da233d0..01ae958a804e 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -43,8 +43,8 @@ module.exports = { "key": "v0.39" }, { - "label": "v0.41", - "key": "v0.41" + "label": "v0.42", + "key": "v0.42" }, { "label": "master", diff --git a/docs/.vuepress/enhanceApp.js b/docs/.vuepress/enhanceApp.js index 79974546e9b2..93b211af8df8 100644 --- a/docs/.vuepress/enhanceApp.js +++ b/docs/.vuepress/enhanceApp.js @@ -2,5 +2,6 @@ export default ({ router }) => { router.addRoutes([ { path: '/master/spec/*', redirect: '/master/modules/' }, { path: '/master/spec/governance/', redirect: '/master/modules/gov/' }, + { path: '/v0.41/', redirect: '/v0.42/' }, ]) } \ No newline at end of file diff --git a/docs/versions b/docs/versions index 31c880a13dde..e6a5db5b85f1 100644 --- a/docs/versions +++ b/docs/versions @@ -1,3 +1,3 @@ master master launchpad/backports v0.39 -release/v0.41.x v0.41 +release/v0.42.x v0.42 \ No newline at end of file From 4bd695de4ec6115e83a73e48f942a268ccdc4d64 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Tue, 16 Mar 2021 02:09:31 +0100 Subject: [PATCH 195/214] errors: Add Wrap handy method (#8845) Co-authored-by: Alessio Treglia Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- types/errors/errors.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/types/errors/errors.go b/types/errors/errors.go index 1dcc63e6566b..c635beb9761a 100644 --- a/types/errors/errors.go +++ b/types/errors/errors.go @@ -257,6 +257,14 @@ func (e *Error) Is(err error) bool { } } +// Wrap extends this error with an additional information. +// It's a handy function to call Wrap with sdk errors. +func (e Error) Wrap(desc string) error { return Wrap(e, desc) } + +// Wrapf extends this error with an additional information. +// It's a handy function to call Wrapf with sdk errors. +func (e Error) Wrapf(desc string, args ...interface{}) error { return Wrapf(e, desc, args...) } + func isNilErr(err error) bool { // Reflect usage is necessary to correctly compare with // a nil implementation of an error. From 1f50a54cf9daffeace4e9382dd9add41c5456de5 Mon Sep 17 00:00:00 2001 From: Pavel Voronin Date: Tue, 16 Mar 2021 14:28:37 +0300 Subject: [PATCH 196/214] fix typo (#8893) --- docs/basics/app-anatomy.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/basics/app-anatomy.md b/docs/basics/app-anatomy.md index b75ecf8e7aaf..df91171eb4c0 100644 --- a/docs/basics/app-anatomy.md +++ b/docs/basics/app-anatomy.md @@ -69,7 +69,7 @@ Here are the main actions performed by this function: - Instantiate the application's [module manager](../building-modules/module-manager.md#manager) with the [`AppModule`](#application-module-interface) object of each of the application's modules. - With the module manager, initialize the application's [`Msg` services](../core/baseapp.md#msg-services), [gRPC `Query` services](../core/baseapp.md#grpc-query-services), [legacy `Msg` routes](../core/baseapp.md#routing) and [legacy query routes](../core/baseapp.md#query-routing). When a transaction is relayed to the application by Tendermint via the ABCI, it is routed to the appropriate module's [`Msg` service](#msg-services) using the routes defined here. Likewise, when a gRPC query request is received by the application, it is routed to the appropriate module's [`gRPC query service`](#grpc-query-services) using the gRPC routes defined here. The SDK still supports legacy `Msg`s and legacy Tendermint queries, which are routed using respectively the legacy `Msg` routes and the legacy query routes. - With the module manager, register the [application's modules' invariants](../building-modules/invariants.md). Invariants are variables (e.g. total supply of a token) that are evaluated at the end of each block. The process of checking invariants is done via a special module called the [`InvariantsRegistry`](../building-modules/invariants.md#invariant-registry). The value of the invariant should be equal to a predicted value defined in the module. Should the value be different than the predicted one, special logic defined in the invariant registry will be triggered (usually the chain is halted). This is useful to make sure no critical bug goes unnoticed and produces long-lasting effects that would be hard to fix. -- With the module manager, set the order of execution between the `InitGenesis`, `BegingBlocker` and `EndBlocker` functions of each of the [application's modules](#application-module-interface). Note that not all modules implement these functions. +- With the module manager, set the order of execution between the `InitGenesis`, `BeginBlocker` and `EndBlocker` functions of each of the [application's modules](#application-module-interface). Note that not all modules implement these functions. - Set the remainer of application's parameters: - [`InitChainer`](#initchainer): used to initialize the application when it is first started. - [`BeginBlocker`, `EndBlocker`](#beginblocker-and-endlbocker): called at the beginning and the end of every block). From 2bce1a7baefe6b90a0c1f4f965e6408af8a98e4b Mon Sep 17 00:00:00 2001 From: Pavel Voronin Date: Tue, 16 Mar 2021 14:32:43 +0300 Subject: [PATCH 197/214] fix typo (#8891) Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- docs/intro/sdk-design.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/intro/sdk-design.md b/docs/intro/sdk-design.md index d9629a3abdaf..4d31fbbbc2cd 100644 --- a/docs/intro/sdk-design.md +++ b/docs/intro/sdk-design.md @@ -15,7 +15,7 @@ Here is a simplified view of how transactions are handled by an application buil ## `baseapp` -`baseapp` is the boilerplate implementation of a Cosmos SDK application. It comes with an implementation of the ABCI to handle the connexion with the underlying consensus engine. Typically, a Cosmos SDK application extends `baseapp` by embedding it in [`app.go`](../basics/app-anatomy.md#core-application-file). See an example of this from the SDK application tutorial: +`baseapp` is the boilerplate implementation of a Cosmos SDK application. It comes with an implementation of the ABCI to handle the connection with the underlying consensus engine. Typically, a Cosmos SDK application extends `baseapp` by embedding it in [`app.go`](../basics/app-anatomy.md#core-application-file). See an example of this from the SDK application tutorial: +++ https://github.com/cosmos/sdk-tutorials/blob/c6754a1e313eb1ed973c5c91dcc606f2fd288811/app.go#L72-L92 From 36f68eb9e041e20a5bb47e216ac5eb8b91f95471 Mon Sep 17 00:00:00 2001 From: Pash Date: Tue, 16 Mar 2021 12:14:54 +0000 Subject: [PATCH 198/214] Update docs (#8751) * docs/basics/app-anatomy.md: update code snippets * Update outdated code snippets * docs/basics/accounts.md: update code snippets * Update outdated code snippets * docs/core/baseapp.md: update code snippets * Update outdated code snippets * docs/core/node.md: update code snippets * Update outdated code snippets * docs/core/store.md: fixed typos * docs/core/grpc_rest.md: fix typos * docs/core/cli.md: fix typos * docs/core/ocap.md: fix code snippet * docs/building-modules/msg-services.md: fix snippet * Update stale code snippets * docs/building-modules/simulator.md: snippets fix * Update outdated code snippet Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- docs/basics/accounts.md | 4 ++-- docs/basics/app-anatomy.md | 12 ++++++------ docs/building-modules/msg-services.md | 6 +++--- docs/building-modules/simulator.md | 2 +- docs/core/baseapp.md | 4 ++-- docs/core/cli.md | 4 ++-- docs/core/grpc_rest.md | 6 +++--- docs/core/node.md | 4 ++-- docs/core/ocap.md | 2 +- docs/core/store.md | 4 ++-- 10 files changed, 24 insertions(+), 24 deletions(-) diff --git a/docs/basics/accounts.md b/docs/basics/accounts.md index 3b50c7a145b7..756545af4aad 100644 --- a/docs/basics/accounts.md +++ b/docs/basics/accounts.md @@ -125,11 +125,11 @@ aa := sdk.AccAddress(pub.Address().Bytes()) These addresses implement the `Address` interface: -+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/types/address.go#L73-L82 ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/types/address.go#L76-L85 Of note, the `Marshal()` and `Bytes()` method both return the same raw `[]byte` form of the address, the former being needed for Protobuf compatibility. Also, the `String()` method is used to return the `bech32` encoded form of the address, which should be the only address format with which end-user interract. Here is an example: -+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/types/address.go#L232-L246 ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/types/address.go#L235-L249 ## Next {hide} diff --git a/docs/basics/app-anatomy.md b/docs/basics/app-anatomy.md index df91171eb4c0..8980ebda54af 100644 --- a/docs/basics/app-anatomy.md +++ b/docs/basics/app-anatomy.md @@ -53,13 +53,13 @@ The first thing defined in `app.go` is the `type` of the application. It is gene See an example of application type definition from `simapp`, the SDK's own app used for demo and testing purposes: -+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/simapp/app.go#L139-L181 ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/simapp/app.go#L145-L187 ### Constructor Function This function constructs a new application of the type defined in the section above. It must fulfill the `AppCreator` signature in order to be used in the [`start` command](../core/node.md#start-command) of the application's daemon command. -+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/server/types/app.go#L42-L44 ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/server/types/app.go#L48-L50 Here are the main actions performed by this function: @@ -81,7 +81,7 @@ Note that this function only creates an instance of the app, while the actual st See an example of application constructor from `simapp`: -+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/simapp/app.go#L192-L429 ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/simapp/app.go#L198-L441 ### InitChainer @@ -91,7 +91,7 @@ In general, the `InitChainer` is mostly composed of the [`InitGenesis`](../build See an example of an `InitChainer` from `simapp`: -+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/simapp/app.go#L452-L459 ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/simapp/app.go#L464-L471 ### BeginBlocker and EndBlocker @@ -103,7 +103,7 @@ As a sidenote, it is important to remember that application-specific blockchains See an example of `BeginBlocker` and `EndBlocker` functions from `simapp` -+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/simapp/app.go#L442-L450 ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/simapp/app.go#L454-L462 ### Register Codec @@ -125,7 +125,7 @@ NOTE: this function is marked deprecated and should only be used to create an ap See an example of a `MakeTestEncodingConfig` from `simapp`: -+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/simapp/simd/cmd/root.go#L179-196 ++++ https://github.com/cosmos/cosmos-sdk/blob/590358652cc1cbc13872ea1659187e073ea38e75/simapp/encoding.go#L8-L19 ## Modules diff --git a/docs/building-modules/msg-services.md b/docs/building-modules/msg-services.md index 868d74b4a21d..6941252f3a76 100644 --- a/docs/building-modules/msg-services.md +++ b/docs/building-modules/msg-services.md @@ -26,7 +26,7 @@ When possible, the existing module's [`Keeper`](keeper.md) should implement `Msg `msgServer` methods can retrieve the `sdk.Context` from the `context.Context` parameter method using the `sdk.UnwrapSDKContext`: -+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc1/x/bank/keeper/msg_server.go#L27 ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc1/x/bank/keeper/msg_server.go#L27-L28 `Msg` processing usually follows these 2 steps: @@ -48,7 +48,7 @@ These events are relayed back to the underlying consensus engine and can be used The invoked `msgServer` method returns a `proto.Message` response and an `error`. These return values are then wrapped into an `*sdk.Result` or an `error` using `sdk.WrapServiceResult(ctx sdk.Context, res proto.Message, err error)`: -+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc2/baseapp/msg_service_router.go#L104 ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc2/baseapp/msg_service_router.go#L104-L104 This method takes care of marshaling the `res` parameter to protobuf and attaching any events on the `ctx.EventManager()` to the `sdk.Result`. @@ -62,7 +62,7 @@ The `handler` type defined in the Cosmos SDK will be deprecated in favor of [`Ms Here is the typical structure of a `handler` function: -+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc2/types/handler.go#L4 ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc2/types/handler.go#L4-L4 Let us break it down: diff --git a/docs/building-modules/simulator.md b/docs/building-modules/simulator.md index 586119a331cc..1d46f3c70e47 100644 --- a/docs/building-modules/simulator.md +++ b/docs/building-modules/simulator.md @@ -63,7 +63,7 @@ Operations on the simulation are simulated using the full [transaction cycle](.. Shown below is how weights are set: -+++ https://github.com/cosmos/cosmos-sdk/blob/master/x/staking/simulation/operations.go#L18 ++++ https://github.com/cosmos/cosmos-sdk/blob/master/x/staking/simulation/operations.go#L18-L68 As you can see the weights are predefined in this case but there are options on how to override this behavior with different weights. One is allowing `*rand.Rand` to define a random weight for the operation, or you can inject your own predefined weights. diff --git a/docs/core/baseapp.md b/docs/core/baseapp.md index 5d0fd115f3ef..c17ce939de44 100644 --- a/docs/core/baseapp.md +++ b/docs/core/baseapp.md @@ -262,7 +262,7 @@ The response contains: - `Info (string):` Additional information. May be non-deterministic. - `GasWanted (int64)`: Amount of gas requested for transaction. It is provided by users when they generate the transaction. - `GasUsed (int64)`: Amount of gas consumed by transaction. During `CheckTx`, this value is computed by multiplying the standard cost of a transaction byte by the size of the raw transaction. Next is an example: - +++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/x/auth/ante/basic.go#L104 + +++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/x/auth/ante/basic.go#L104-L105 - `Events ([]cmn.KVPair)`: Key-Value tags for filtering and indexing transactions (eg. by account). See [`event`s](./events.md) for more. - `Codespace (string)`: Namespace for the Code. @@ -288,7 +288,7 @@ Before the first transaction of a given block is processed, a [volatile state](# During the additional fifth step outlined in (2), each read/write to the store increases the value of `GasConsumed`. You can find the default cost of each operation: -+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/store/types/gas.go#L153-L162 ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/store/types/gas.go#L164-L175 At any point, if `GasConsumed > GasWanted`, the function returns with `Code != 0` and `DeliverTx` fails. diff --git a/docs/core/cli.md b/docs/core/cli.md index a09b81407c67..364e9714c73a 100644 --- a/docs/core/cli.md +++ b/docs/core/cli.md @@ -72,7 +72,7 @@ The root-level `status` and `keys` subcommands are common across most applicatio 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. +- **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, the 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. @@ -106,7 +106,7 @@ A _persistent_ flag (as opposed to a _local_ flag) added to a command transcends 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 ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/simapp/simd/cmd/root.go#L118-L119 ## Environment variables diff --git a/docs/core/grpc_rest.md b/docs/core/grpc_rest.md index cea6c0ed3cea..853fedd11269 100644 --- a/docs/core/grpc_rest.md +++ b/docs/core/grpc_rest.md @@ -43,9 +43,9 @@ The `grpc.Server` is a concrete gRPC server, which spawns and serves any gRPC re - `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:9090`. -::tip +:::tip `~/.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. @@ -67,7 +67,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.41.0/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. diff --git a/docs/core/node.md b/docs/core/node.md index 661322b2c010..4a4fec9a3177 100644 --- a/docs/core/node.md +++ b/docs/core/node.md @@ -46,10 +46,10 @@ The flow of the `start` command is pretty straightforward. First, it retrieves t With the `db`, the `start` command creates a new instance of the application using an `appCreator` function: -+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/server/start.go#L227 ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/server/start.go#L227-L228 Note that an `appCreator` is a function that fulfills the `AppCreator` signature: -+++https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/server/types/app.go#L48-L50 ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/server/types/app.go#L48-L50 In practice, the [constructor of the application](../basics/app-anatomy.md#constructor-function) is passed as the `appCreator`. diff --git a/docs/core/ocap.md b/docs/core/ocap.md index 3f0ec2e1d7ec..db8d0b7e5c86 100644 --- a/docs/core/ocap.md +++ b/docs/core/ocap.md @@ -68,7 +68,7 @@ sumValue := externalModule.ComputeSumValue(*account) In the Cosmos SDK, you can see the application of this principle in the gaia app. -+++ https://github.com/cosmos/gaia/blob/master/app/app.go#L197-L209 ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.41.4/simapp/app.go#L249-L273 ## Next {hide} diff --git a/docs/core/store.md b/docs/core/store.md index 79be79d4c641..5de83b8269c5 100644 --- a/docs/core/store.md +++ b/docs/core/store.md @@ -108,7 +108,7 @@ Whenever the `rootMulti.Store` needs to be branched, a [`cachemulti.Store`](http +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc6/store/cachemulti/store.go#L17-L28 -`cachemulti.Store` branches all substores (creates a virtual store for each substore) in its constructor and hold them in `Store.stores`. Moreover cachese all read queries. `Store.GetKVStore()` returns the store from `Store.stores`, and `Store.Write()` recursively calls `CacheWrap.Write()` on all the substores. +`cachemulti.Store` branches all substores (creates a virtual store for each substore) in its constructor and hold them in `Store.stores`. Moreover caches all read queries. `Store.GetKVStore()` returns the store from `Store.stores`, and `Store.Write()` recursively calls `CacheWrap.Write()` on all the substores. ## Base-layer KVStores @@ -180,7 +180,7 @@ This is the type used whenever an IAVL Store needs to be branched to create an i #### `Set` -`Store.Set()` sets the key-value pair to the `Store.cache`. `cValue` has the field dirty bool which indicates whether the cached value is different from the underlying value. When `Store.Set()` cachees a new pair, the `cValue.dirty` is set `true` so when `Store.Write()` is called it can be written to the underlying store. +`Store.Set()` sets the key-value pair to the `Store.cache`. `cValue` has the field dirty bool which indicates whether the cached value is different from the underlying value. When `Store.Set()` caches a new pair, the `cValue.dirty` is set `true` so when `Store.Write()` is called it can be written to the underlying store. #### `Iterator` From 05d4e43d1ce8f58b0bd264607a12014b27223948 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Tue, 16 Mar 2021 18:48:54 +0100 Subject: [PATCH 199/214] account.Address: use RWLocker (#8774) Co-authored-by: Alessio Treglia --- types/address.go | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/types/address.go b/types/address.go index c6f6404e8775..1a2009103385 100644 --- a/types/address.go +++ b/types/address.go @@ -78,11 +78,11 @@ const ( var ( // AccAddress.String() is expensive and if unoptimized dominantly showed up in profiles, // yet has no mechanisms to trivially cache the result given that AccAddress is a []byte type. - accAddrMu sync.Mutex + accAddrMu sync.RWMutex accAddrCache *simplelru.LRU - consAddrMu sync.Mutex + consAddrMu sync.RWMutex consAddrCache *simplelru.LRU - valAddrMu sync.Mutex + valAddrMu sync.RWMutex valAddrCache *simplelru.LRU ) @@ -268,12 +268,13 @@ func (aa AccAddress) String() string { } var key = conv.UnsafeBytesToStr(aa) - accAddrMu.Lock() - defer accAddrMu.Unlock() - if addr, ok := accAddrCache.Get(key); ok { + accAddrMu.RLock() + addr, ok := accAddrCache.Get(key) + accAddrMu.RUnlock() + if ok { return addr.(string) } - return cacheBech32Addr(GetConfig().GetBech32AccountAddrPrefix(), aa, accAddrCache, key) + return cacheBech32Addr(GetConfig().GetBech32AccountAddrPrefix(), aa, accAddrCache, key, &accAddrMu) } // Format implements the fmt.Formatter interface. @@ -417,12 +418,13 @@ func (va ValAddress) String() string { } var key = conv.UnsafeBytesToStr(va) - valAddrMu.Lock() - defer valAddrMu.Unlock() - if addr, ok := valAddrCache.Get(key); ok { + valAddrMu.RLock() + addr, ok := valAddrCache.Get(key) + valAddrMu.RUnlock() + if ok { return addr.(string) } - return cacheBech32Addr(GetConfig().GetBech32ValidatorAddrPrefix(), va, valAddrCache, key) + return cacheBech32Addr(GetConfig().GetBech32ValidatorAddrPrefix(), va, valAddrCache, key, &valAddrMu) } // Format implements the fmt.Formatter interface. @@ -571,12 +573,13 @@ func (ca ConsAddress) String() string { } var key = conv.UnsafeBytesToStr(ca) - consAddrMu.Lock() - defer consAddrMu.Unlock() - if addr, ok := consAddrCache.Get(key); ok { + consAddrMu.RLock() + addr, ok := consAddrCache.Get(key) + consAddrMu.RUnlock() + if ok { return addr.(string) } - return cacheBech32Addr(GetConfig().GetBech32ConsensusAddrPrefix(), ca, consAddrCache, key) + return cacheBech32Addr(GetConfig().GetBech32ConsensusAddrPrefix(), ca, consAddrCache, key, &consAddrMu) } // Bech32ifyAddressBytes returns a bech32 representation of address bytes. @@ -722,11 +725,13 @@ func addressBytesFromHexString(address string) ([]byte, error) { return hex.DecodeString(address) } -func cacheBech32Addr(prefix string, addr []byte, cache *simplelru.LRU, cacheKey string) string { +func cacheBech32Addr(prefix string, addr []byte, cache *simplelru.LRU, cacheKey string, m sync.Locker) string { bech32Addr, err := bech32.ConvertAndEncode(prefix, addr) if err != nil { panic(err) } + m.Lock() cache.Add(cacheKey, bech32Addr) + m.Unlock() return bech32Addr } From 864a07290e3d972ac6e864c35b21729d12b6f993 Mon Sep 17 00:00:00 2001 From: Pavel Voronin Date: Wed, 17 Mar 2021 11:46:00 +0300 Subject: [PATCH 200/214] ascii scheme didn't fit view area (#8892) Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- docs/intro/sdk-design.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/intro/sdk-design.md b/docs/intro/sdk-design.md index 4d31fbbbc2cd..9a348ebc78f1 100644 --- a/docs/intro/sdk-design.md +++ b/docs/intro/sdk-design.md @@ -38,9 +38,9 @@ Here is a simplified view of how a transaction is processed by the application o ``` + | - | Transaction relayed from the full-node's Tendermint engine - | to the node's application via DeliverTx - | + | Transaction relayed from the full-node's + | Tendermint engine to the node's application + | via DeliverTx | | +---------------------v--------------------------+ @@ -56,9 +56,9 @@ Here is a simplified view of how a transaction is processed by the application o +---------------------------+ | | - | - | Message routed to the correct - | module to be processed + | Message routed to + | the correct module + | to be processed | | +----------------+ +---------------+ +----------------+ +------v----------+ From a9b73e6452124f564e41e495bde5541203345b7e Mon Sep 17 00:00:00 2001 From: Cory Date: Wed, 17 Mar 2021 01:53:51 -0700 Subject: [PATCH 201/214] add newline at end of docs/versions file (#8900) Co-authored-by: Marko --- docs/versions | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/versions b/docs/versions index e6a5db5b85f1..0fc449e86f44 100644 --- a/docs/versions +++ b/docs/versions @@ -1,3 +1,3 @@ master master launchpad/backports v0.39 -release/v0.42.x v0.42 \ No newline at end of file +release/v0.42.x v0.42 From 4ace9be59d2b362289bf4e9601078fce04af1933 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Mar 2021 09:08:00 +0000 Subject: [PATCH 202/214] build(deps): bump codecov/codecov-action from v1.2.2 to v1.3.1 (#8903) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from v1.2.2 to v1.3.1. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/master/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v1.2.2...fcebab03f26c7530a22baa63f06b3e0515f0c7cd) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Marko --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fb25c58fe190..c701d142ffa4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -172,7 +172,7 @@ jobs: sed -i.bak "/$(echo $filename | sed 's/\//\\\//g')/d" coverage.txt done if: env.GIT_DIFF - - uses: codecov/codecov-action@v1.2.2 + - uses: codecov/codecov-action@v1.3.1 with: file: ./coverage.txt if: env.GIT_DIFF From 0836361c0e873a73554ccc6aab338c7d5af1e2c7 Mon Sep 17 00:00:00 2001 From: Hanjun Kim Date: Wed, 17 Mar 2021 18:53:51 +0900 Subject: [PATCH 203/214] Fix typo (#8905) Co-authored-by: Marko --- simapp/params/doc.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/simapp/params/doc.go b/simapp/params/doc.go index 1c721342a9c9..a2f3620a8351 100644 --- a/simapp/params/doc.go +++ b/simapp/params/doc.go @@ -3,9 +3,9 @@ Package params defines the simulation parameters in the simapp. It contains the default weights used for each transaction used on the module's simulation. These weights define the chance for a transaction to be simulated at -any gived operation. +any given operation. -You can repace the default values for the weights by providing a params.json +You can replace the default values for the weights by providing a params.json file with the weights defined for each of the transaction operations: { From 1a4418b32b4ee0245478c560caf93f3496cbe017 Mon Sep 17 00:00:00 2001 From: Amaury <1293565+amaurym@users.noreply.github.com> Date: Wed, 17 Mar 2021 13:15:20 +0100 Subject: [PATCH 204/214] Docs: Anys Usage, Events & small cleanups (#8895) Co-authored-by: Barrie Byron Co-authored-by: Alessio Treglia --- .../adr-041-in-place-store-migrations.md | 2 +- docs/basics/accounts.md | 2 +- docs/basics/app-anatomy.md | 4 +- docs/building-modules/invariants.md | 2 +- docs/building-modules/simulator.md | 4 +- docs/core/baseapp.md | 4 +- docs/core/encoding.md | 162 +++++++++++++++--- docs/core/events.md | 103 ++++++----- docs/core/store.md | 6 +- 9 files changed, 208 insertions(+), 81 deletions(-) diff --git a/docs/architecture/adr-041-in-place-store-migrations.md b/docs/architecture/adr-041-in-place-store-migrations.md index 072a121f5d66..4687ef31f880 100644 --- a/docs/architecture/adr-041-in-place-store-migrations.md +++ b/docs/architecture/adr-041-in-place-store-migrations.md @@ -75,7 +75,7 @@ func (m Migrator) Migrate1to2(ctx sdk.Context) error { } ``` -Each module's migration functions are specific to the module's store evolutions, and are not described in this ADR. An example of x/bank store key migrations following the introduction of ADR-028 length-prefixed addresses can be seen [here](https://github.com/cosmos/cosmos-sdk/blob/ef8dabcf0f2ecaf26db1c6c6d5922e9399458bb3/x/bank/legacy/v042/store.go#L15). +Each module's migration functions are specific to the module's store evolutions, and are not described in this ADR. An example of x/bank store key migrations after the introduction of ADR-028 length-prefixed addresses can be seen in this [store.go code](https://github.com/cosmos/cosmos-sdk/blob/36f68eb9e041e20a5bb47e216ac5eb8b91f95471/x/bank/legacy/v043/store.go#L41-L62). ### Tracking Module Versions in `x/upgrade` diff --git a/docs/basics/accounts.md b/docs/basics/accounts.md index 756545af4aad..9b7648b8c7dd 100644 --- a/docs/basics/accounts.md +++ b/docs/basics/accounts.md @@ -98,7 +98,7 @@ Also see the [`Addresses`](#addresses) section for more information. `PubKey`s used in the Cosmos SDK are Protobuf messages and have the following methods: -+++ https://github.com/cosmos/cosmos-sdk/blob/master/crypto/types/types.go#L8-L17 ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/crypto/types/types.go#L8-L17 - For `secp256k1` keys, the actual implementation can be found [here](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/crypto/keys/secp256k1/secp256k1.go). - For `ed25519` keys, it can be found [here](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/crypto/keys/ed25519/ed25519.go). diff --git a/docs/basics/app-anatomy.md b/docs/basics/app-anatomy.md index 8980ebda54af..70b725865aba 100644 --- a/docs/basics/app-anatomy.md +++ b/docs/basics/app-anatomy.md @@ -113,8 +113,8 @@ 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` (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). +- `InterfaceRegistry`: The `InterfaceRegistry` is used by the Protobuf codec to handle interfaces that 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 that 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 that can be used to register the module's own interfaces and implementations. + - You can read more about Any in [ADR-19](../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 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). diff --git a/docs/building-modules/invariants.md b/docs/building-modules/invariants.md index d21100cb24b5..32fd30591b07 100644 --- a/docs/building-modules/invariants.md +++ b/docs/building-modules/invariants.md @@ -74,7 +74,7 @@ At its core, the `InvariantRegistry` is defined in the SDK as an interface: Typically, this interface is implemented in the `keeper` of a specific module. The most used implementation of an `InvariantRegistry` can be found in the `crisis` module: -+++ https://github.com/cosmos/cosmos-sdk/blob/master/x/crisis/keeper/keeper.go#L50-L54 ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/x/crisis/keeper/keeper.go#L50-L54 The `InvariantRegistry` is therefore typically instantiated by instantiating the `keeper` of the `crisis` module in the [application's constructor function](../basics/app-anatomy.md#constructor-function). diff --git a/docs/building-modules/simulator.md b/docs/building-modules/simulator.md index 1d46f3c70e47..7a9e72ca00d6 100644 --- a/docs/building-modules/simulator.md +++ b/docs/building-modules/simulator.md @@ -63,9 +63,9 @@ Operations on the simulation are simulated using the full [transaction cycle](.. Shown below is how weights are set: -+++ https://github.com/cosmos/cosmos-sdk/blob/master/x/staking/simulation/operations.go#L18-L68 ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/x/staking/simulation/operations.go#L18-L68 -As you can see the weights are predefined in this case but there are options on how to override this behavior with different weights. One is allowing `*rand.Rand` to define a random weight for the operation, or you can inject your own predefined weights. +As you can see, the weights are predefined in this case. Options exist to override this behavior with different weights. One option is to use `*rand.Rand` to define a random weight for the operation, or you can inject your own predefined weights. Here is how one can override the above package `simappparams`. diff --git a/docs/core/baseapp.md b/docs/core/baseapp.md index c17ce939de44..67dbd557e032 100644 --- a/docs/core/baseapp.md +++ b/docs/core/baseapp.md @@ -126,7 +126,7 @@ is the canonical state of the application and the volatile states, `checkState` are used to handle state transitions in-between the main state made during [`Commit`](#commit). Internally, there is only a single `CommitMultiStore` which we refer to as the main or root state. -From this root state, we derive two volatile state through a mechanism called _store branching_ (performed by `CacheWrap` function). +From this root state, we derive two volatile states by using a mechanism called _store branching_ (performed by `CacheWrap` function). The types can be illustrated as follows: ![Types](./baseapp_state_types.png) @@ -333,7 +333,7 @@ The `AnteHandler` is theoretically optional, but still a very important componen - Perform preliminary _stateful_ validity checks like ensuring signatures are valid or that the sender has enough funds to pay for fees. - Play a role in the incentivisation of stakeholders via the collection of transaction fees. -`BaseApp` holds an `anteHandler` as paraemter, which is initialized in the [application's constructor](../basics/app-anatomy.md#application-constructor). The most widely used `anteHandler` today is that of the [`auth` module](https://github.com/cosmos/cosmos-sdk/blob/master/x/auth/ante/ante.go). +`BaseApp` holds an `anteHandler` as parameter that is initialized in the [application's constructor](../basics/app-anatomy.md#application-constructor). The most widely used `anteHandler` is the [`auth` module](https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/x/auth/ante/ante.go). Click [here](../basics/gas-fees.md#antehandler) for more on the `anteHandler`. diff --git a/docs/core/encoding.md b/docs/core/encoding.md index a4cbddc2acd7..fc390f79dd5c 100644 --- a/docs/core/encoding.md +++ b/docs/core/encoding.md @@ -69,9 +69,141 @@ typically used for when the data needs to be streamed or grouped together ### Gogoproto -Modules are encouraged to utilize Protobuf encoding for their respective types. +Modules are encouraged to utilize Protobuf encoding for their respective types. In the SDK, we use the [Gogoproto](https://github.com/gogo/protobuf) specific implementation of the Protobuf spec that offers speed and DX improvements compared to the official [Google protobuf implementation](https://github.com/protocolbuffers/protobuf). -#### FAQ +### Guidelines for protobuf message definitions + +In addition to [following official Protocol Buffer guidelines](https://developers.google.com/protocol-buffers/docs/proto3#simple), we recommend using these annotations in .proto files when dealing with interfaces: + +- use `cosmos_proto.accepts_interface` to annote fields that accept interfaces +- pass the same fully qualified name as `protoName` to `InterfaceRegistry.RegisterInterface` +- annotate interface implementations with `cosmos_proto.implements_interface` +- pass the same fully qualified name as `protoName` to `InterfaceRegistry.RegisterInterface` + +### Transaction Encoding + +Another important use of Protobuf is the encoding and decoding of +[transactions](./transactions.md). Transactions are defined by the application or +the SDK but are then passed to the underlying consensus engine to be relayed to +other peers. Since the underlying consensus engine is agnostic to the application, +the consensus engine accepts only transactions in the form of raw bytes. + +- The `TxEncoder` object performs the encoding. +- The `TxDecoder` object performs the decoding. + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc4/types/tx_msg.go#L83-L87 + +A standard implementation of both these objects can be found in the [`auth` module](../../x/auth/spec/README.md): + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc4/x/auth/tx/decoder.go + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc4/x/auth/tx/encoder.go + +See [ADR-020](../architecture/adr-020-protobuf-transaction-encoding.md) for details of how a transaction is encoded. + +### Interface Encoding and Usage of `Any` + +The Protobuf DSL is strongly typed, which can make inserting variable-typed fields difficult. Imagine we want to create a `Profile` protobuf message that serves as a wrapper over [an account](../basics/accounts.md): + +```proto +message Profile { + // account is the account associated to a profile. + cosmos.auth.v1beta1.BaseAccount account = 1; + // bio is a short description of the account. + string bio = 4; +} +``` + +In this `Profile` example, we hardcoded `account` as a `BaseAccount`. However, there are several other types of [user accounts related to vesting](../../x/auth/spec/05_vesting.md), such as `BaseVestingAccount` or `ContinuousVestingAccount`. All of these accounts are different, but they all implement the `AccountI` interface. How would you create a `Profile` that allows all these types of accounts with an `account` field that accepts an `AccountI` interface? + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/x/auth/types/account.go#L307-L330 + +In [ADR-019](../architecture/adr-019-protobuf-state-encoding.md), it has been decided to use [`Any`](https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/any.proto)s to encode interfaces in protobuf. An `Any` contains an arbitrary serialized message as bytes, along with a URL that acts as a globally unique identifier for and resolves to that message's type. This strategy allows us to pack arbitrary Go types inside protobuf messages. Our new `Profile` then looks like: + +```protobuf +message Profile { + // account is the account associated to a profile. + google.protobuf.Any account = 1 [ + (cosmos_proto.accepts_interface) = "AccountI"; // Asserts that this field only accepts Go types implementing `AccountI`. It is purely informational for now. + ]; + // bio is a short description of the account. + string bio = 4; +} +``` + +To add an account inside a profile, we need to "pack" it inside an `Any` first, using `codectypes.NewAnyWithValue`: + +```go +var myAccount AccountI +myAccount = ... // Can be a BaseAccount, a ContinuousVestingAccount or any struct implementing `AccountI` + +// Pack the account into an Any +accAny, err := codectypes.NewAnyWithValue(myAccount) +if err != nil { + return nil, err +} + +// Create a new Profile with the any. +profile := Profile { + Account: accAny, + Bio: "some bio", +} + +// We can then marshal the profile as usual. +bz, err := cdc.MarshalBinaryBare(profile) +jsonBz, err := cdc.MarshalJSON(profile) +``` + +To summarize, to encode an interface, you must 1/ pack the interface into an `Any` and 2/ marshal the `Any`. For convenience, the SDK provides a `MarshalInterface` method to bundle these two steps. Have a look at [a real-life example in the x/auth module](https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/x/auth/keeper/keeper.go#L218-L221). + +The reverse operation of retrieving the concrete Go type from inside an `Any`, called "unpacking", is done with the `GetCachedValue()` on `Any`. + +```go +profileBz := ... // The proto-encoded bytes of a Profile, e.g. retrieved through gRPC. +var myProfile Profile +// Unmarshal the bytes into the myProfile struct. +err := cdc.UnmarshalBinaryBare(profilebz, &myProfile) + +// Let's see the types of the Account field. +fmt.Printf("%T\n", myProfile.Account) // Prints "Any" +fmt.Printf("%T\n", myProfile.Account.GetCachedValue()) // Prints "BaseAccount", "ContinuousVestingAccount" or whatever was initially packed in the Any. + +// Get the address of the accountt. +accAddr := myProfile.Account.GetCachedValue().(AccountI).GetAddress() +``` + +It is important to note that for `GetCachedValue()` to work, `Profile` (and any other structs embedding `Profile`) must implement the `UnpackInterfaces` method: + +```go +func (p *Profile) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { + if p.Account != nil { + var account AccountI + return unpacker.UnpackAny(p.Account, &account) + } + + return nil +} +``` + +The `UnpackInterfaces` gets called recursively on all structs implementing this method, to allow all `Any`s to have their `GetCachedValue()` correctly populated. + +For more information about interface encoding, and especially on `UnpackInterfaces` and how the `Any`'s `type_url` gets resolved using the `InterfaceRegistry`, please refer to [ADR-019](../architecture/adr-019-protobuf-state-encoding.md). + +#### `Any` Encoding in the SDK + +The above `Profile` example is a fictive example used for educational purposes. In the SDK, we use `Any` encoding in several places (non-exhaustive list): + +- the `cryptotypes.PubKey` interface for encoding different types of public keys, +- the `sdk.Msg` interface for encoding different `Msg`s in a transaction, +- the `AccountI` interface for encodinig different types of accounts (similar to the above example) in the x/auth query responses, +- the `Evidencei` interface for encoding different types of evidences in the x/evidence module, +- the `AuthorizationI` interface for encoding different types of x/authz authorizations. + +A real-life example of encoding the pubkey as `Any` inside the Validator struct in x/staking is shown in the following example: + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/x/staking/types/validator.go#L40-L61 + +## FAQ 1. How to create modules using protobuf encoding? @@ -123,32 +255,6 @@ type UnpackInterfacesMessage interface { } ``` -#### Guidelines for protobuf message definitions - -In addition to [following official guidelines](https://developers.google.com/protocol-buffers/docs/proto3#simple), we recommend to use these annotations in .proto files when dealing with interfaces: - -- fields which accept interfaces should be annotated with `cosmos_proto.accepts_interface` - using the same full-qualified name passed as `protoName` to `InterfaceRegistry.RegisterInterface` -- interface implementations should be annotated with `cosmos_proto.implements_interface` - using the same full-qualified name passed as `protoName` to `InterfaceRegistry.RegisterInterface` - -#### Transaction Encoding - -Another important use of Protobuf is the encoding and decoding of -[transactions](./transactions.md). Transactions are defined by the application or -the SDK, but passed to the underlying consensus engine in order to be relayed to -other peers. Since the underlying consensus engine is agnostic to the application, -it only accepts transactions in the form of raw bytes. The encoding is done by an -object called `TxEncoder` and the decoding by an object called `TxDecoder`. - -+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc4/types/tx_msg.go#L83-L87 - -A standard implementation of both these objects can be found in the [`auth` module](https://github.com/cosmos/cosmos-sdk/blob/master/x/auth): - -+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc4/x/auth/tx/decoder.go - -+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc4/x/auth/tx/encoder.go - ## Next {hide} Learn about [gRPC, REST and other endpoints](./grpc_rest.md) {hide} diff --git a/docs/core/events.md b/docs/core/events.md index d199d94ced52..999d2876169e 100644 --- a/docs/core/events.md +++ b/docs/core/events.md @@ -9,20 +9,28 @@ order: 9 ## Pre-requisite Readings - [Anatomy of an SDK application](../basics/app-anatomy.md) {prereq} +- [Tendermint Documentation on Events](https://docs.tendermint.com/master/spec/abci/abci.html#events) {prereq} ## Events Events are implemented in the Cosmos SDK as an alias of the ABCI `Event` type and -take the form of: `{eventType}.{eventAttribute}={value}`. +take the form of: `{eventType}.{attributeKey}={attributeValue}`. -+++ https://github.com/tendermint/tendermint/blob/bc572217c07b90ad9cee851f193aaa8e9557cbc7/abci/types/types.pb.go#L2187-L2193 ++++ https://github.com/tendermint/tendermint/blob/v0.34.8/proto/tendermint/abci/types.proto#L304-L313 -Events contain: +An Event contains: -- 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 +- A `type` to categorize the Event at a high-level; for example, the SDK uses the `"message"` type to filter Events by `Msg`s. +- A list of `attributes` are key-value pairs that give more information about the categorized Event. For example, for the `"message"` type, we can filter Events by key-value pairs using `message.action={some_action}`, `message.module={some_module}` or `message.sender={some_sender}`. + +::: tip +To parse the attribute values as strings, make sure to add `'` (single quotes) around each attribute value. +::: + +Events, the `type` and `attributes` are defined on a **per-module basis** in the module's +`/types/events.go` file, and triggered from the module's [`Msg` service](../building-modules/msg-services.md) +by using the [`EventManager`](#eventmanager). In addition, each module documents its Events under +`spec/xx_events.md`. Events are returned to the underlying consensus engine in the response of the following ABCI messages: @@ -31,28 +39,35 @@ Events are returned to the underlying consensus engine in the response of the fo - [`CheckTx`](./baseapp.md#checktx) - [`DeliverTx`](./baseapp.md#delivertx) -Events, the `type` and `attributes`, are defined on a **per-module basis** in the module's -`/types/events.go` file, and triggered from the module's [`Msg` service](../building-modules/msg-services.md) -via the [`EventManager`](#eventmanager). In addition, each module documents its events under -`spec/xx_events.md`. +### Examples + +The following examples show how to query Events using the SDK. + +| Event | Description | +| ------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `tx.height=23` | Query all transactions at height 23 | +| `message.action='/cosmos.bank.v1beta1.Msg/Send'` | Query all transactions containing a x/bank `Send` [Service `Msg`](../building-modules/msg-services.md). Note the `'`s around the value. | +| `message.action='send'` | Query all transactions containing a x/bank `Send` [legacy `Msg`](../building-modules/msg-services.md#legacy-amino-msgs). Note the `'`s around the value. | +| `message.module='bank'` | Query all transactions containing messages from the x/bank module. Note the `'`s around the value. | +| `create_validator.validator='cosmosval1...'` | x/staking-specific Event, see [x/staking SPEC](../../../cosmos-sdk/x/staking/spec/07_events.md). | ## EventManager -In Cosmos SDK applications, events are managed by an abstraction called the `EventManager`. -Internally, the `EventManager` tracks a list of `Events` for the entire execution flow of a +In Cosmos SDK applications, Events are managed by an abstraction called the `EventManager`. +Internally, the `EventManager` tracks a list of Events for the entire execution flow of a transaction or `BeginBlock`/`EndBlock`. -+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/types/events.go#L16-L20 ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/types/events.go#L17-L25 -The `EventManager` comes with a set of useful methods to manage events. Among them, the one that is -used the most by module and application developers is the `EmitEvent` method, which tracks -an `event` in the `EventManager`. +The `EventManager` comes with a set of useful methods to manage Events. The method +that is used most by module and application developers is `EmitEvent` that tracks +an Event in the `EventManager`. -+++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/types/events.go#L29-L31 ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/types/events.go#L33-L37 -Module developers should handle event emission via the `EventManager#EmitEvent` in each message +Module developers should handle Event emission via the `EventManager#EmitEvent` in each message `Handler` and in each `BeginBlock`/`EndBlock` handler. The `EventManager` is accessed via -the [`Context`](./context.md), where event emission generally follows this pattern: +the [`Context`](./context.md), where Event emission generally follows this pattern: ```go ctx.EventManager().EmitEvent( @@ -60,7 +75,8 @@ ctx.EventManager().EmitEvent( ) ``` -Module's `handler` function should also set a new `EventManager` to the `context` to isolate emitted events per `message`: +Module's `handler` function should also set a new `EventManager` to the `context` to isolate emitted Events per `message`: + ```go func NewHandler(keeper Keeper) sdk.Handler { return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { @@ -69,48 +85,53 @@ func NewHandler(keeper Keeper) sdk.Handler { ``` See the [`Msg` services](../building-modules/msg-services.md) concept doc for a more detailed -view on how to typically implement `Events` and use the `EventManager` in modules. +view on how to typically implement Events and use the `EventManager` in modules. ## Subscribing to Events -It is possible to subscribe to `Events` via Tendermint's [Websocket](https://tendermint.com/docs/app-dev/subscribing-to-events-via-websocket.html#subscribing-to-events-via-websocket). -This is done by calling the `subscribe` RPC method via Websocket: +You can use Tendermint's [Websocket](https://docs.tendermint.com/master/tendermint-core/subscription.html#subscribing-to-events-via-websocket) to subscribe to Events by calling the `subscribe` RPC method: ```json { - "jsonrpc": "2.0", - "method": "subscribe", - "id": "0", - "params": { - "query": "tm.event='eventCategory' AND eventType.eventAttribute='attributeValue'" - } + "jsonrpc": "2.0", + "method": "subscribe", + "id": "0", + "params": { + "query": "tm.event='eventCategory' AND eventType.eventAttribute='attributeValue'" + } } ``` The main `eventCategory` you can subscribe to are: -- `NewBlock`: Contains `events` triggered during `BeginBlock` and `EndBlock`. -- `Tx`: Contains `events` triggered during `DeliverTx` (i.e. transaction processing). +- `NewBlock`: Contains Events triggered during `BeginBlock` and `EndBlock`. +- `Tx`: Contains Events triggered during `DeliverTx` (i.e. transaction processing). - `ValidatorSetUpdates`: Contains validator set updates for the block. -These events are triggered from the `state` package after a block is committed. You can get the -full list of `event` categories [here](https://godoc.org/github.com/tendermint/tendermint/types#pkg-constants). +These Events are triggered from the `state` package after a block is committed. You can get the +full list of Event categories [on the Tendermint Godoc page](https://godoc.org/github.com/tendermint/tendermint/types#pkg-constants). -The `type` and `attribute` value of the `query` allow you to filter the specific `event` you are looking for. For example, a `transfer` transaction triggers an `event` of type `Transfer` and has `Recipient` and `Sender` as `attributes` (as defined in the [`events` file of the `bank` module](https://github.com/cosmos/cosmos-sdk/blob/master/x/bank/types/events.go)). Subscribing to this `event` would be done like so: +The `type` and `attribute` value of the `query` allow you to filter the specific Event you are looking for. For example, a `transfer` transaction triggers an Event of type `Transfer` and has `Recipient` and `Sender` as `attributes` (as defined in the [`events.go` file of the `bank` module](https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/x/bank/types/events.go)). Subscribing to this Event would be done like so: ```json { - "jsonrpc": "2.0", - "method": "subscribe", - "id": "0", - "params": { - "query": "tm.event='Tx' AND transfer.sender='senderAddress'" - } + "jsonrpc": "2.0", + "method": "subscribe", + "id": "0", + "params": { + "query": "tm.event='Tx' AND transfer.sender='senderAddress'" + } } ``` where `senderAddress` is an address following the [`AccAddress`](../basics/accounts.md#addresses) format. +## Typed Events (coming soon) + +As previously described, Events are defined on a per-module basis. It is the responsibility of the module developer to define Event types and Event attributes. Except in the `spec/XX_events.md` file, these Event types and attributes are unfortunately not easily discoverable, so the SDK proposes to use Protobuf-defined [Typed Events](../architecture/adr-032-typed-events.md) for emitting and querying Events. + +The Typed Events proposal has not yet been fully implemented. Documentation is not yet available. + ## Next {hide} Learn about SDK [telemetry](./telemetry.md) {hide} diff --git a/docs/core/store.md b/docs/core/store.md index 5de83b8269c5..a469b77ebfd3 100644 --- a/docs/core/store.md +++ b/docs/core/store.md @@ -56,11 +56,11 @@ The Cosmos SDK comes with a large set of stores to persist the state of applicat ### Store Interface -At its very core, a Cosmos SDK `store` is an object that holds a `CacheWrapper` and has a `GetStoreType()` method: +At its very core, a Cosmos SDK `store` is an object that holds a `CacheWrapper` and has a `GetStoreType()` method: +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc6/store/types/store.go#L15-L18 -The `GetStoreType` is a simple method that returns the type of store, whereas a `CacheWrapper` is a simple interface that implements store read caching and write branching through `Write` method: +The `GetStoreType` is a simple method that returns the type of store, whereas a `CacheWrapper` is a simple interface that implements store read caching and write branching through `Write` method: +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc6/store/types/store.go#L240-L264 @@ -104,7 +104,7 @@ The `rootMulti.Store` is a base-layer multistore built around a `db` on top of w ### CacheMultiStore -Whenever the `rootMulti.Store` needs to be branched, a [`cachemulti.Store`](https://github.com/cosmos/cosmos-sdk/blob/master/store/cachemulti/store.go) is used. +Whenever the `rootMulti.Store` needs to be branched, a [`cachemulti.Store`](https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/store/cachemulti/store.go) is used. +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc6/store/cachemulti/store.go#L17-L28 From 0c2d4a86fd3b2acb7bda7f09b9a68bab67a566ee Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Mar 2021 14:07:28 +0000 Subject: [PATCH 205/214] build(deps): bump elliptic from 6.5.3 to 6.5.4 in /docs (#8824) Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.3 to 6.5.4. - [Release notes](https://github.com/indutny/elliptic/releases) - [Commits](https://github.com/indutny/elliptic/compare/v6.5.3...v6.5.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> --- docs/package-lock.json | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/package-lock.json b/docs/package-lock.json index 7e60448152d8..f473df3fa8a5 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -4128,23 +4128,23 @@ "integrity": "sha512-cev+jOrz/Zm1i+Yh334Hed6lQVOkkemk2wRozfMF4MtTR7pxf3r3L5Rbd7uX1zMcEqVJ7alJBnJL7+JffkC6FQ==" }, "elliptic": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", - "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", + "bn.js": "^4.11.9", + "brorand": "^1.1.0", "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.0" + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" }, "dependencies": { "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" } } }, From 1fddce73b361e1b9442811e36a401e8501a87468 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Wed, 17 Mar 2021 20:06:54 +0000 Subject: [PATCH 206/214] x/distribution: fix module's parameters validation (#8918) * x/distribution: fix module's parameters validation closes: #8914 * Update x/distribution/types/params.go Co-authored-by: Aleksandr Bezobchuk * Update x/distribution/types/params_internal_test.go Co-authored-by: Robert Zaremba Co-authored-by: Aleksandr Bezobchuk Co-authored-by: Robert Zaremba --- x/distribution/types/fee_pool_test.go | 8 ++-- x/distribution/types/params.go | 6 +-- x/distribution/types/params_internal_test.go | 34 ++++++++++++++++ x/distribution/types/params_test.go | 43 +++++++++++++------- 4 files changed, 70 insertions(+), 21 deletions(-) create mode 100644 x/distribution/types/params_internal_test.go diff --git a/x/distribution/types/fee_pool_test.go b/x/distribution/types/fee_pool_test.go index ebf5bc4b0233..de774ca3cc0f 100644 --- a/x/distribution/types/fee_pool_test.go +++ b/x/distribution/types/fee_pool_test.go @@ -1,4 +1,4 @@ -package types +package types_test import ( "testing" @@ -6,14 +6,14 @@ import ( "github.com/stretchr/testify/require" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/distribution/types" ) func TestValidateGenesis(t *testing.T) { - fp := InitialFeePool() + fp := types.InitialFeePool() require.Nil(t, fp.ValidateGenesis()) - fp2 := FeePool{CommunityPool: sdk.DecCoins{{Denom: "stake", Amount: sdk.NewDec(-1)}}} + fp2 := types.FeePool{CommunityPool: sdk.DecCoins{{Denom: "stake", Amount: sdk.NewDec(-1)}}} require.NotNil(t, fp2.ValidateGenesis()) - } diff --git a/x/distribution/types/params.go b/x/distribution/types/params.go index ecd04ece67c3..212b0b99f3e5 100644 --- a/x/distribution/types/params.go +++ b/x/distribution/types/params.go @@ -51,7 +51,7 @@ func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { func (p Params) ValidateBasic() error { if p.CommunityTax.IsNegative() || p.CommunityTax.GT(sdk.OneDec()) { return fmt.Errorf( - "community tax should non-negative and less than one: %s", p.CommunityTax, + "community tax should be non-negative and less than one: %s", p.CommunityTax, ) } if p.BaseProposerReward.IsNegative() { @@ -64,9 +64,9 @@ func (p Params) ValidateBasic() error { "bonus proposer reward should be positive: %s", p.BonusProposerReward, ) } - if v := p.BaseProposerReward.Add(p.BonusProposerReward); v.GT(sdk.OneDec()) { + if v := p.BaseProposerReward.Add(p.BonusProposerReward).Add(p.CommunityTax); v.GT(sdk.OneDec()) { return fmt.Errorf( - "sum of base and bonus proposer reward cannot greater than one: %s", v, + "sum of base, bonus proposer rewards, and community tax cannot be greater than one: %s", v, ) } diff --git a/x/distribution/types/params_internal_test.go b/x/distribution/types/params_internal_test.go new file mode 100644 index 000000000000..f132df9d5daf --- /dev/null +++ b/x/distribution/types/params_internal_test.go @@ -0,0 +1,34 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func Test_validateAuxFuncs(t *testing.T) { + type args struct { + i interface{} + } + tests := []struct { + name string + args args + wantErr bool + }{ + {"wrong type", args{10.5}, true}, + {"empty sdk.Dec", args{sdk.Dec{}}, true}, + {"negative", args{sdk.NewDec(-1)}, true}, + {"one dec", args{sdk.NewDec(1)}, false}, + {"two dec", args{sdk.NewDec(2)}, true}, + } + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + require.Equal(t, tt.wantErr, validateCommunityTax(tt.args.i) != nil) + require.Equal(t, tt.wantErr, validateBaseProposerReward(tt.args.i) != nil) + require.Equal(t, tt.wantErr, validateBonusProposerReward(tt.args.i) != nil) + }) + } +} diff --git a/x/distribution/types/params_test.go b/x/distribution/types/params_test.go index cf250160477a..d156df728d65 100644 --- a/x/distribution/types/params_test.go +++ b/x/distribution/types/params_test.go @@ -1,4 +1,4 @@ -package types +package types_test import ( "testing" @@ -6,29 +6,44 @@ import ( "github.com/stretchr/testify/require" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/distribution/types" ) -func Test_validateAuxFuncs(t *testing.T) { - type args struct { - i interface{} +func TestParams_ValidateBasic(t *testing.T) { + toDec := sdk.MustNewDecFromStr + + type fields struct { + CommunityTax sdk.Dec + BaseProposerReward sdk.Dec + BonusProposerReward sdk.Dec + WithdrawAddrEnabled bool } tests := []struct { name string - args args + fields fields wantErr bool }{ - {"wrong type", args{10.5}, true}, - {"nil Int pointer", args{sdk.Dec{}}, true}, - {"negative", args{sdk.NewDec(-1)}, true}, - {"one dec", args{sdk.NewDec(1)}, false}, - {"two dec", args{sdk.NewDec(2)}, true}, + {"success", fields{toDec("0.1"), toDec("0.5"), toDec("0.4"), false}, false}, + {"negative community tax", fields{toDec("-0.1"), toDec("0.5"), toDec("0.4"), false}, true}, + {"negative base proposer reward", fields{toDec("0.1"), toDec("-0.5"), toDec("0.4"), false}, true}, + {"negative bonus proposer reward", fields{toDec("0.1"), toDec("0.5"), toDec("-0.4"), false}, true}, + {"total sum greater than 1", fields{toDec("0.2"), toDec("0.5"), toDec("0.4"), false}, true}, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { - require.Equal(t, tt.wantErr, validateCommunityTax(tt.args.i) != nil) - require.Equal(t, tt.wantErr, validateBaseProposerReward(tt.args.i) != nil) - require.Equal(t, tt.wantErr, validateBonusProposerReward(tt.args.i) != nil) + p := types.Params{ + CommunityTax: tt.fields.CommunityTax, + BaseProposerReward: tt.fields.BaseProposerReward, + BonusProposerReward: tt.fields.BonusProposerReward, + WithdrawAddrEnabled: tt.fields.WithdrawAddrEnabled, + } + if err := p.ValidateBasic(); (err != nil) != tt.wantErr { + t.Errorf("ValidateBasic() error = %v, wantErr %v", err, tt.wantErr) + } }) } } + +func TestDefaultParams(t *testing.T) { + require.NoError(t, types.DefaultParams().ValidateBasic()) +} From deaee531111fb4aad3ccabbfa6771f9a67ae42ce Mon Sep 17 00:00:00 2001 From: Gianguido Sora Date: Thu, 18 Mar 2021 09:27:03 +0100 Subject: [PATCH 207/214] CLI/keys: define default supported keyring algorithms (#8825) * define package-level supported Keyring algorithms This commit lets developer define what algorithms Keyring supports instead of relying on just keyring.New options. This change is needed since it allows us to support those algorithms in CLI commands too without subverting their current execution flow. * read dry run cli flag as persistent command flag * add dry run field to CLI command handling context * use CLI context keyring instead of creating a new one * keyring supported algorithms are used as if they were defaults, name them as such * --dry-run value is now associated to client.context.Simulate Since Simulate is now used in both tx and query commands, move its reading routine into ReadPersistentCommandFlags. Removed DryRun from Context, since it's not needed anymore. * rename supported algorithms variable Co-authored-by: Alessio Treglia * remove keyring algorithms global, let user set them via client.Context methods * remove old keyring globals test Co-authored-by: Alessio Treglia Co-authored-by: Jonathan Gimeno --- client/cmd.go | 10 +++++----- client/context.go | 13 ++++++++++--- client/keys/add.go | 16 +--------------- 3 files changed, 16 insertions(+), 23 deletions(-) diff --git a/client/cmd.go b/client/cmd.go index 437022695d47..8c71c40cf4f0 100644 --- a/client/cmd.go +++ b/client/cmd.go @@ -99,6 +99,11 @@ func ReadPersistentCommandFlags(clientCtx Context, flagSet *pflag.FlagSet) (Cont clientCtx = clientCtx.WithHomeDir(homeDir) } + if !clientCtx.Simulate || flagSet.Changed(flags.FlagDryRun) { + dryRun, _ := flagSet.GetBool(flags.FlagDryRun) + clientCtx = clientCtx.WithSimulation(dryRun) + } + if clientCtx.KeyringDir == "" || flagSet.Changed(flags.FlagKeyringDir) { keyringDir, _ := flagSet.GetString(flags.FlagKeyringDir) @@ -191,11 +196,6 @@ func readTxCommandFlags(clientCtx Context, flagSet *pflag.FlagSet) (Context, err clientCtx = clientCtx.WithGenerateOnly(genOnly) } - if !clientCtx.Simulate || flagSet.Changed(flags.FlagDryRun) { - dryRun, _ := flagSet.GetBool(flags.FlagDryRun) - clientCtx = clientCtx.WithSimulation(dryRun) - } - if !clientCtx.Offline || flagSet.Changed(flags.FlagOffline) { offline, _ := flagSet.GetBool(flags.FlagOffline) clientCtx = clientCtx.WithOffline(offline) diff --git a/client/context.go b/client/context.go index f7f555339c2c..292f914943db 100644 --- a/client/context.go +++ b/client/context.go @@ -27,6 +27,7 @@ type Context struct { InterfaceRegistry codectypes.InterfaceRegistry Input io.Reader Keyring keyring.Keyring + KeyringOptions []keyring.Option Output io.Writer OutputFormat string Height int64 @@ -56,6 +57,12 @@ func (ctx Context) WithKeyring(k keyring.Keyring) Context { return ctx } +// WithKeyringOptions returns a copy of the context with an updated keyring. +func (ctx Context) WithKeyringOptions(opts ...keyring.Option) Context { + ctx.KeyringOptions = opts + return ctx +} + // WithInput returns a copy of the context with an updated input. func (ctx Context) WithInput(r io.Reader) Context { ctx.Input = r @@ -324,9 +331,9 @@ func GetFromFields(kr keyring.Keyring, from string, genOnly bool) (sdk.AccAddres } func newKeyringFromFlags(ctx Context, backend string) (keyring.Keyring, error) { - if ctx.GenerateOnly { - return keyring.New(sdk.KeyringServiceName(), keyring.BackendMemory, ctx.KeyringDir, ctx.Input) + if ctx.GenerateOnly || ctx.Simulate { + return keyring.New(sdk.KeyringServiceName(), keyring.BackendMemory, ctx.KeyringDir, ctx.Input, ctx.KeyringOptions...) } - return keyring.New(sdk.KeyringServiceName(), backend, ctx.KeyringDir, ctx.Input) + return keyring.New(sdk.KeyringServiceName(), backend, ctx.KeyringDir, ctx.Input, ctx.KeyringOptions...) } diff --git a/client/keys/add.go b/client/keys/add.go index ae937b5a4b0d..e0344decdfb6 100644 --- a/client/keys/add.go +++ b/client/keys/add.go @@ -90,21 +90,7 @@ func runAddCmd(cmd *cobra.Command, args []string) error { return err } - var kr keyring.Keyring - - dryRun, _ := cmd.Flags().GetBool(flags.FlagDryRun) - if dryRun { - kr, err = keyring.New(sdk.KeyringServiceName(), keyring.BackendMemory, clientCtx.KeyringDir, buf) - } else { - backend, _ := cmd.Flags().GetString(flags.FlagKeyringBackend) - kr, err = keyring.New(sdk.KeyringServiceName(), backend, clientCtx.KeyringDir, buf) - } - - if err != nil { - return err - } - - return RunAddCmd(cmd, args, kr, buf) + return RunAddCmd(cmd, args, clientCtx.Keyring, buf) } /* From 641b13ee47d59c838cc05d1b288a496c4d9f3301 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Thu, 18 Mar 2021 11:30:17 +0000 Subject: [PATCH 208/214] ci: test detection must not hide errors (#8924) --- .github/workflows/test.yml | 40 +------------------------------------- 1 file changed, 1 insertion(+), 39 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c701d142ffa4..697be726c47d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -201,7 +201,7 @@ jobs: if: env.GIT_DIFF - name: test & coverage report creation run: | - xargs --arg-file=pkgs.txt.part.${{ matrix.part }} go test -mod=readonly -json -timeout 30m -race -tags='cgo ledger test_ledger_mock' | tee ${{ matrix.part }}-race-output.txt + xargs --arg-file=pkgs.txt.part.${{ matrix.part }} go test -mod=readonly -timeout 30m -race -tags='cgo ledger test_ledger_mock' if: env.GIT_DIFF - uses: actions/upload-artifact@v2 with: @@ -225,44 +225,6 @@ jobs: make test-rosetta # if: env.GIT_DIFF - race-detector-report: - runs-on: ubuntu-latest - needs: [test-race, install-tparse] - timeout-minutes: 5 - steps: - - uses: actions/checkout@v2 - - uses: technote-space/get-diff-action@v4 - id: git_diff - with: - PATTERNS: | - **/**.go - go.mod - go.sum - - uses: actions/download-artifact@v2 - with: - name: "${{ github.sha }}-00-race-output" - if: env.GIT_DIFF - - uses: actions/download-artifact@v2 - with: - name: "${{ github.sha }}-01-race-output" - if: env.GIT_DIFF - - uses: actions/download-artifact@v2 - with: - name: "${{ github.sha }}-02-race-output" - if: env.GIT_DIFF - - uses: actions/download-artifact@v2 - with: - name: "${{ github.sha }}-03-race-output" - if: env.GIT_DIFF - - uses: actions/cache@v2.1.4 - with: - path: ~/go/bin - key: ${{ runner.os }}-go-tparse-binary - if: env.GIT_DIFF - - name: Generate test report (go test -race) - run: cat ./*-race-output.txt | ~/go/bin/tparse - if: env.GIT_DIFF - liveness-test: runs-on: ubuntu-latest timeout-minutes: 10 From 7b09f95ab5bed044ef9c74de0c7b093cf26ef648 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Fri, 19 Mar 2021 11:24:29 +0000 Subject: [PATCH 209/214] add +nobuild flags to all relevant test cases (#8934) Closes: #8923 --- x/auth/client/cli/cli_test.go | 2 ++ x/auth/client/rest/rest_test.go | 2 ++ x/authz/client/cli/tx_test.go | 2 ++ x/authz/client/rest/grpc_query_test.go | 2 ++ 4 files changed, 8 insertions(+) diff --git a/x/auth/client/cli/cli_test.go b/x/auth/client/cli/cli_test.go index 6d9d776f1b03..0345406e4754 100644 --- a/x/auth/client/cli/cli_test.go +++ b/x/auth/client/cli/cli_test.go @@ -1,3 +1,5 @@ +// +build norace + package cli_test import ( diff --git a/x/auth/client/rest/rest_test.go b/x/auth/client/rest/rest_test.go index 3c62648bb79c..41a22a26eb21 100644 --- a/x/auth/client/rest/rest_test.go +++ b/x/auth/client/rest/rest_test.go @@ -1,3 +1,5 @@ +// +build norace + package rest_test import ( diff --git a/x/authz/client/cli/tx_test.go b/x/authz/client/cli/tx_test.go index 0f604a12c76a..179feca333d6 100644 --- a/x/authz/client/cli/tx_test.go +++ b/x/authz/client/cli/tx_test.go @@ -1,3 +1,5 @@ +// +build norace + package cli_test import ( diff --git a/x/authz/client/rest/grpc_query_test.go b/x/authz/client/rest/grpc_query_test.go index c5aae6b5f6c0..676af3915b01 100644 --- a/x/authz/client/rest/grpc_query_test.go +++ b/x/authz/client/rest/grpc_query_test.go @@ -1,3 +1,5 @@ +// +build norace + package rest_test import ( From 0b2497049ab90e8be5c10ded1717997a10fd2a4f Mon Sep 17 00:00:00 2001 From: Rikard Hjort <8545447+hjorthjort@users.noreply.github.com> Date: Fri, 19 Mar 2021 13:06:53 +0100 Subject: [PATCH 210/214] Staking spec updates (#8843) * Overview of keepers in object capability model (OCM) * Updates to the spec, making clarifications * Create a sequence diagram of a (fresh) delegation * Misc notes, not yet decided where to put them * Description of the shares abstraction in validators * Model all keeper dependencies and move the UML file to docs * Move and rename delegation sequence diagram * Move shares description * Remove TODO * Diagram touch-ups * Add how consensus power is calculated * remove temp file * Diagram improvements * Describe slashing in more detail * Describe redelegation * Describe unbonding * Delegation updates * Delegation updates * Make a diagram describing overall transaction flow * Add delegation flows for the events of tokens being bonded/unbonding/etc. * Grammar fix * Diagram updates: distinguish alts, remove numbering. * Use groups instead of "func:" participants * Remove unused keepers from dependency diagram * Add title to unbonding diagram * Move keeper dependencies * small doc updates * remove numbers on sequence diagram * !!!WIP EndBlock * Explain "Last"-prefix in storage * Remove `panic` step (they are supposed to never happen) * EndBlock sequence diagram (with TODOs) * Add TODO * More visible TODOs * Remove numbering * Complete EndBlock * Remove numbering * Remove TODOs and update title * add title back * remove endblock seq-diagram * spec updates * Make power index update conditional on not being jailed * update title * Delete sequnce diagrams * Fix tokens to consensus power ratio * Fix type Co-authored-by: Amaury <1293565+amaurym@users.noreply.github.com> Co-authored-by: hjort <> Co-authored-by: Amaury <1293565+amaurym@users.noreply.github.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- x/staking/spec/01_state.md | 17 +++++++++-------- x/staking/spec/02_state_transitions.md | 9 ++++++++- x/staking/spec/03_messages.md | 7 ++++++- x/staking/spec/05_end_block.md | 20 +++++++++++++------- 4 files changed, 36 insertions(+), 17 deletions(-) diff --git a/x/staking/spec/01_state.md b/x/staking/spec/01_state.md index 66c6c0c5d61c..7238994118f1 100644 --- a/x/staking/spec/01_state.md +++ b/x/staking/spec/01_state.md @@ -7,6 +7,7 @@ order: 1 ## LastTotalPower LastTotalPower tracks the total amounts of bonded tokens recorded during the previous end block. +Store entries prefixed with "Last" must remain unchanged until EndBlock. - LastTotalPower: `0x12 -> ProtocolBuffer(sdk.Int)` @@ -29,12 +30,12 @@ Validators can have one of three statuses active set during [`EndBlock`](./05_end_block.md#validator-set-changes) and their status is updated to `Bonded`. 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 + 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. -- `Unbonding`: When a validator leaves the active set, either by choice or due to slashing or +- `Unbonding`: When a validator leaves the active set, either by choice or due to slashing, jailing or tombstoning, an unbonding of all their delegations begins. All delegations must then wait the UnbondingTime - before moving their tokens to their accounts from the `BondedPool`. + before their tokens are moved to their accounts from the `BondedPool`. Validators objects should be primarily stored and accessed by the `OperatorAddr`, an SDK validator address for the operator of the validator. Two @@ -59,10 +60,10 @@ When Tendermint reports evidence, it provides the validator address, so this map is needed to find the operator. Note that the `ConsAddr` corresponds to the address which can be derived from the validator's `ConsPubKey`. -`ValidatorsByPower` is an additional index that provides a sorted list o +`ValidatorsByPower` is an additional index that provides a sorted list of potential validators to quickly determine the current active set. Here -ConsensusPower is validator.Tokens/10^6. Note that all validators where -`Jailed` is true are not stored within this index. +ConsensusPower is validator.Tokens/10^6 by default. 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 last-block's bonded validators. This index remains constant during a block but @@ -151,7 +152,7 @@ A redelegation object is created every time a redelegation occurs. To prevent - the (re)delegator already has another immature redelegation in progress 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`. + 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 @@ -182,7 +183,7 @@ delegations queue is kept. For the purpose of tracking progress of redelegations the redelegation queue is kept. -- UnbondingDelegation: `0x42 | format(time) -> []DVVTriplet` +- RedelegationQueue: `0x42 | format(time) -> []DVVTriplet` +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/staking.proto#L140-L152 diff --git a/x/staking/spec/02_state_transitions.md b/x/staking/spec/02_state_transitions.md index 4a69769b95dd..b46f1f002a1c 100644 --- a/x/staking/spec/02_state_transitions.md +++ b/x/staking/spec/02_state_transitions.md @@ -15,7 +15,11 @@ This document describes the state transition operations pertaining to: 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 +A validator can be `Unbonded`, `Unbonding` or `Bonded`. `Unbonded` +and `Unbonding` are collectively called `Not Bonded`. A validator can move +directly between all the states, except for from `Bonded` to `Unbonded`. + +### Not bonded to Bonded The following transition occurs when a validator's ranking in the `ValidatorPowerIndex` surpasses that of the `LastValidator`. @@ -55,6 +59,9 @@ this process may be also be reversed. the following operations occur: - if jailed delete record from `ValidatorByPowerIndex` - if unjailed add record to `ValidatorByPowerIndex` +Jailed validators are not present in any of the following stores: +- the power store (from consensus power to address) + ## Delegations ### Delegate diff --git a/x/staking/spec/03_messages.md b/x/staking/spec/03_messages.md index d0f059ecf6b6..fb6eb06837fa 100644 --- a/x/staking/spec/03_messages.md +++ b/x/staking/spec/03_messages.md @@ -62,7 +62,6 @@ assigned to `Delegation.Shares`. 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` - the exchange rate is invalid, meaning the validator has no tokens (due to slashing) but there are outstanding shares - the amount delegated is less than the minimum allowed delegation @@ -75,6 +74,12 @@ The delegator receives newly minted shares at the current exchange rate. The exchange rate is the number of existing shares in the validator divided by the number of currently delegated tokens. +The validator is updated in the `ValidatorByPower` index, and the delegation is +tracked in validator object in the `Validators` index. + +It is possible to delegate to a jailed validator, the only difference being it +will not be added to the power index until it is unjailed. + ## Msg/Undelegate The `Msg/Undelegate` service message allows delegators to undelegate their tokens from diff --git a/x/staking/spec/05_end_block.md b/x/staking/spec/05_end_block.md index c0777896fbfd..769b986b7c0e 100644 --- a/x/staking/spec/05_end_block.md +++ b/x/staking/spec/05_end_block.md @@ -16,7 +16,7 @@ validator set which is responsible for validating Tendermint messages at the consensus layer. Operations are as following: - the new validator set is taken as the top `params.MaxValidators` number of - validators retrieved from the ValidatorsByPower index + validators retrieved from the `ValidatorsByPower` index - the previous validator set is compared with the new validator set: - missing validators begin unbonding and their `Tokens` are transferred from the `BondedPool` to the `NotBondedPool` `ModuleAccount` @@ -25,7 +25,12 @@ consensus layer. Operations are as following: In all cases, any validators leaving or entering the bonded validator set or changing balances and staying within the bonded validator set incur an update -message which is passed back to Tendermint. +message reporting their new consensus power which is passed back to Tendermint. + +The `LastTotalPower` and `LastValidatorsPower` hold the state of the total power +and validator power from the end of the last block, and are used to check for +changes that have occured in `ValidatorsByPower` and the total new power, which +is calculated during `EndBlock`. ## Queues @@ -41,14 +46,15 @@ When a validator is kicked out of the bonded validator set (either through being jailed, or not having sufficient bonded tokens) it begins the unbonding process along with all its delegations begin unbonding (while still being delegated to this validator). At this point the validator is said to be an -unbonding validator, whereby it will mature to become an "unbonded validator" +"unbonding validator", whereby it will mature to become an "unbonded validator" after the unbonding period has passed. Each block the validator queue is to be checked for mature unbonding validators -(namely with a completion time <= current time). At this point any mature -validators which do not have any delegations remaining are deleted from state. -For all other mature unbonding validators that still have remaining -delegations, the `validator.Status` is switched from `types.Unbonding` to +(namely with a completion time <= current time and completion height <= current +block height). At this point any mature validators which do not have any +delegations remaining are deleted from state. For all other mature unbonding +validators that still have remaining delegations, the `validator.Status` is +switched from `types.Unbonding` to `types.Unbonded`. ### Unbonding Delegations From cc1db18df54c4b2cc49a95b7732c32aa8be088a5 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Fri, 19 Mar 2021 15:22:59 +0100 Subject: [PATCH 211/214] doc secp256r1 (#8899) * Update docs for things related to secp256r1 * docs: update accounts and pubkey documentation * update table formatting * Apply suggestions from code review Co-authored-by: Alessio Treglia * Apply suggestions from code review Awesome grammar fixes and style improvements Co-authored-by: Barrie Byron * Apply suggestions from code review Awesome grammar and style improvements. Co-authored-by: Barrie Byron Co-authored-by: Alessio Treglia * hd wallet docs update * Apply suggestions from code review Co-authored-by: Barrie Byron * Update docs/basics/accounts.md Co-authored-by: Amaury <1293565+amaurym@users.noreply.github.com> * Update docs/architecture/adr-020-protobuf-transaction-encoding.md I agree, let's use "and" * update code snippet links Co-authored-by: Alessio Treglia Co-authored-by: Barrie Byron Co-authored-by: Amaury <1293565+amaurym@users.noreply.github.com> --- .../adr-020-protobuf-transaction-encoding.md | 4 +- docs/basics/accounts.md | 107 +++++++++++------- 2 files changed, 66 insertions(+), 45 deletions(-) diff --git a/docs/architecture/adr-020-protobuf-transaction-encoding.md b/docs/architecture/adr-020-protobuf-transaction-encoding.md index 062dac13eb2b..dde981f7e9ec 100644 --- a/docs/architecture/adr-020-protobuf-transaction-encoding.md +++ b/docs/architecture/adr-020-protobuf-transaction-encoding.md @@ -288,8 +288,8 @@ and `FileDescriptor`s and returns a boolean result. ### Public Key Encoding Public keys in the Cosmos SDK implement the `cryptotypes.PubKey` interface. -We propose to use `Any` for protobuf encoding as we are doing with other interfaces (e.g. in `BaseAccount` `PubKey` or `SignerInfo` `PublicKey`). -Following public keys are implemented: secp256k1, ed25519 and multisignature. +We propose to use `Any` for protobuf encoding as we are doing with other interfaces (for example, in `BaseAccount.PubKey` and `SignerInfo.PublicKey`). +The following public keys are implemented: secp256k1, secp256r1, ed25519 and legacy-multisignature. Ex: diff --git a/docs/basics/accounts.md b/docs/basics/accounts.md index 9b7648b8c7dd..f19240b95d37 100644 --- a/docs/basics/accounts.md +++ b/docs/basics/accounts.md @@ -14,7 +14,7 @@ This document describes the in-built accounts system of the Cosmos SDK. {synopsi In the Cosmos SDK, an _account_ designates a pair of _public key_ `PubKey` and _private key_ `PrivKey`. The `PubKey` can be derived to generate various `Addresses`, which are used to identify users (among other parties) in the application. `Addresses` are also associated with [`message`s](../building-modules/messages-and-queries.md#messages) to identify the sender of the `message`. The `PrivKey` is used to generate [digital signatures](#signatures) to prove that an `Address` associated with the `PrivKey` approved of a given `message`. -To derive `PubKey`s and `PrivKey`s, the Cosmos SDK uses a standard called [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki). This standard defines how to build an HD wallet, where a wallet is a set of accounts. At the core of every account, there is a seed, which takes the form of a 12 or 24-words mnemonic. From this mnemonic, it is possible to derive any number of `PrivKey`s using one-way cryptographic function. Then, a `PubKey` can be derived from the `PrivKey`. Naturally, the mnemonic is the most sensitive information, as private keys can always be re-generated if the mnemonic is preserved. +For HD key derivation the Cosmos SDK uses a standard called [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki). The BIP32 allows users to create an HD wallet (as specified in [BIP44(https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki)]) - a set of accounts derived from an initial secret seed. A seed is usually created from a 12- or 24-word mnemonic. A single seed can derive any number of `PrivKey`s using a one-way cryptographic function. Then, a `PubKey` can be derived from the `PrivKey`. Naturally, the mnemonic is the most sensitive information, as private keys can always be re-generated if the mnemonic is preserved. ``` Account 0 Account 1 Account 2 @@ -56,80 +56,101 @@ To derive `PubKey`s and `PrivKey`s, the Cosmos SDK uses a standard called [BIP32 +-------------------+ ``` -In the Cosmos SDK, accounts are stored and managed via an object called a [`Keyring`](#keyring). +In the Cosmos SDK, keys are stored and managed by using an object called a [`Keyring`](#keyring). -## Keyring -A `Keyring` is an object that stores and manages accounts. In the Cosmos SDK, a `Keyring` implementation follows the `Keyring` interface: +## Keys, accounts, addresses, and signatures -+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/crypto/keyring/keyring.go#L50-L88 +The principal way of authenticating a user is done using [digital signatures](https://en.wikipedia.org/wiki/Digital_signature). Users sign transactions using their own private key. Signature verification is done with the associated public key. For on-chain signature verification purposes, we store the public key in an `Account` object (alongside other data required for a proper transaction validation). -The default implementation of `Keyring` comes from the third-party [`99designs/keyring`](https://github.com/99designs/keyring) library. +The Cosmos SDK supports the following digital key schemes for creating digital signatures: -A few notes on the `Keyring` methods: +- `secp256k1`, as implemented in the [SDK's `crypto/keys/secp256k1` package](https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/crypto/keys/secp256k1/secp256k1.go). +- `secp256r1`, as implemented in the [SDK's `crypto/keys/secp256r1` package](https://github.com/cosmos/cosmos-sdk/blob/master/crypto/keys/secp256r1/pubkey.go), +- `tm-ed25519`, as implemented in the [SDK `crypto/keys/ed25519` package](https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/crypto/keys/ed25519/ed25519.go). This scheme is supported only for the consensus validation. + + +| | Address length | Public key length | Used for transaction | Used for consensus | +| | in bytes | in bytes | authentication | (tendermint) | +|--------------+----------------+-------------------+----------------------+--------------------| +| `secp256k1` | 20 | 33 | yes | no | +| `secp256r1` | 32 | 33 | yes | no | +| `tm-ed25519` | -- not used -- | 32 | no | yes | -- `Sign(uid string, payload []byte) ([]byte, tmcrypto.PubKey, error)` strictly deals with the signature of the `payload` bytes. Some preliminary work should be done beforehand to prepare and encode the transaction into a canonical `[]byte` form. Protobuf being not deterministic, it has been decided in [ADR-020](../architecture/adr-020-protobuf-transaction-encoding.md) that the canonical `payload` to sign is the `SignDoc` struct, deterministically encoded using [ADR-027](adr-027-deterministic-protobuf-serialization.md). Note that signature verification is not implemented in the SDK by default, it is deferred to the [`anteHandler`](../core/baseapp.md#antehandler). - +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/proto/cosmos/tx/v1beta1/tx.proto#L47-L64 -- `NewAccount(uid, mnemonic, bip39Passwd, hdPath string, algo SignatureAlgo) (Info, error)` creates a new account based on the [`bip44 path`](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) and persists it on disk (note that the `PrivKey` is [encrypted with a passphrase before being persisted](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/crypto/armor.go), it is **never stored unencrypted**). In the context of this method, the `account` and `address` parameters refer to the segment of the BIP44 derivation path (e.g. `0`, `1`, `2`, ...) used to derive the `PrivKey` and `PubKey` from the mnemonic (note that given the same mnemonic and `account`, the same `PrivKey` will be generated, and given the same `account` and `address`, the same `PubKey` and `Address` will be generated). Finally, note that the `NewAccount` method derives keys and addresses using the algorithm specified in the last argument `algo`. Currently, the SDK supports two public key algorithms: - - `secp256k1`, as implemented in the [SDK's `crypto/keys/secp256k1` package](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/crypto/keys/secp256k1/secp256k1.go), - - `ed25519`, as implemented in the [SDK's `crypto/keys/ed25519` package](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/crypto/keys/ed25519/ed25519.go). +## Addresses -- `ExportPrivKeyArmor(uid, encryptPassphrase string) (armor string, err error)` exports a private key in ASCII-armored encrypted format, using the given passphrase. You can then either import it again into the keyring using the `ImportPrivKey(uid, armor, passphrase string)` function, or decrypt it into a raw private key using the `UnarmorDecryptPrivKey(armorStr string, passphrase string)` function. +`Addresses` and `PubKey`s are both public information that identifies actors in the application. `Account` is used to store authentication information. The basic account implementation is provided by a `BaseAccount` object. -Also see the [`Addresses`](#addresses) section for more information. +Each account is identified using `Address` which is a sequence of bytes derived from a public key. In SDK, we define 3 types of addresses that specify a context where an account is used: -## Addresses and PubKeys +- `AccAddress` identifies users (the sender of a `message`). +- `ValAddress` identifies validator operators. +- `ConsAddress` identifies validator nodes that are participating in consensus. Validator nodes are derived using the **`ed25519`** curve. + +These types implement the `Address` interface: + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/types/address.go#L71-L90 + +Address construction algorithm is defined in [ADR-28](https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-028-public-key-addresses.md). +Here is the standard way to obtain an account address from a `pub` public key: + +```go +sdk.AccAddress(pub.Address().Bytes()) +``` -`Addresses` and `PubKey`s are both public information that identify actors in the application. There are 3 main types of `Addresses`/`PubKeys` available by default in the Cosmos SDK: +Of note, the `Marshal()` and `Bytes()` method both return the same raw `[]byte` form of the address. `Marshal()` is required for Protobuf compatibility. -- Addresses and Keys for **accounts**, which identify users (e.g. the sender of a `message`). They are derived using the **`secp256k1`** curve. -- Addresses and Keys for **validator operators**, which identify the operators of validators. They are derived using the **`secp256k1`** curve. -- Addresses and Keys for **consensus nodes**, which identify the validator nodes participating in consensus. They are derived using the **`ed25519`** curve. +Addresses and public keys are formatted using [Bech32](https://en.bitcoin.it/wiki/Bech32) and implemented by the `String` method. The Bech32 method is the only supported format to use when interacting with a blockchain. The Bech32 human-readable part (Bech32 prefix) is used to denote an address type. Example: -| | Address bech32 Prefix | Pubkey bech32 Prefix | Curve | Address byte length | Pubkey byte length | -| ------------------ | --------------------- | -------------------- | ----------- | ------------------- | ------------------ | -| Accounts | cosmos | cosmospub | `secp256k1` | `20` | `33` | -| Validator Operator | cosmosvaloper | cosmosvaloperpub | `secp256k1` | `20` | `33` | -| Consensus Nodes | cosmosvalcons | cosmosvalconspub | `ed25519` | `20` | `32` | ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/types/address.go#L230-L244 -### PubKeys -`PubKey`s used in the Cosmos SDK are Protobuf messages and have the following methods: +| | Address bech32 Prefix | Pubkey bech32 Prefix | +| ------------------ | --------------------- | -------------------- | +| Accounts | cosmos | cosmospub | +| Validator Operator | cosmosvaloper | cosmosvaloperpub | +| Consensus Nodes | cosmosvalcons | cosmosvalconspub | + + +### Public Keys + +Public keys in Cosmos SDK are defined by `cryptotypes.PubKey` interface. Since public keys are saved in a store, `cryptotypes.PubKey` extends the `proto.Message` interface: +++ https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/crypto/types/types.go#L8-L17 -- For `secp256k1` keys, the actual implementation can be found [here](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/crypto/keys/secp256k1/secp256k1.go). -- For `ed25519` keys, it can be found [here](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/crypto/keys/ed25519/ed25519.go). +A compressed format is used for `secp256k1` and `secp256r1` serialization. +- The first byte 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`. -In both case, the actual key (as raw bytes) is the compressed form of the pubkey. The first byte 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. +This prefix is followed by the `x`-coordinate. -Note that in the Cosmos SDK, `Pubkeys` are not manipulated in their raw bytes form. Instead, they are encoded to string using [`Amino`](../core/encoding.md#amino) and [`bech32`](https://en.bitcoin.it/wiki/Bech32). In the SDK, it is done by first calling the `Bytes()` method on the raw `Pubkey` (which applies amino encoding), and then the `ConvertAndEncode` method of `bech32`. +Like `Address`, Bech32 is used to format `PubKey` and for all communication with a blockchain: +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/types/address.go#L579-L729 -### Addresses -The Cosmos SDK comes by default with 3 types of addresses: +## Keyring -- `AccAddress` for accounts. -- `ValAddress` for validator operators. -- `ConsAddress` for validator nodes. +A `Keyring` is an object that stores and manages accounts. In the Cosmos SDK, a `Keyring` implementation follows the `Keyring` interface: -Each of these address types are an alias for an hex-encoded `[]byte` array of length 20. Here is the standard way to obtain an address `aa` from a `Pubkey pub`: ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/crypto/keyring/keyring.go#L51-L89 -```go -aa := sdk.AccAddress(pub.Address().Bytes()) -``` +The default implementation of `Keyring` comes from the third-party [`99designs/keyring`](https://github.com/99designs/keyring) library. + +A few notes on the `Keyring` methods: + +- `Sign(uid string, payload []byte) ([]byte, sdkcrypto.PubKey, error)` strictly deals with the signature of the `payload` bytes. You must prepare and encode the transaction into a canonical `[]byte` form. Because protobuf is not deterministic, it has been decided in [ADR-020](../architecture/adr-020-protobuf-transaction-encoding.md) that the canonical `payload` to sign is the `SignDoc` struct, deterministically encoded using [ADR-027](adr-027-deterministic-protobuf-serialization.md). Note that signature verification is not implemented in the SDK by default, it is deferred to the [`anteHandler`](../core/baseapp.md#antehandler). + +++ https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/proto/cosmos/tx/v1beta1/tx.proto#L47-L64 -These addresses implement the `Address` interface: +- `NewAccount(uid, mnemonic, bip39Passwd, hdPath string, algo SignatureAlgo) (Info, error)` creates a new account based on the [`bip44 path`](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) and persists it on disk. The `PrivKey` is **never stored unencrypted**, instead it is [encrypted with a passphrase](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/crypto/armor.go) before being persisted. In the context of this method, the key type and sequence number refer to the segment of the BIP44 derivation path (for example, `0`, `1`, `2`, ...) that is used to derive a private and a public key from the mnemonic. Using the same mnemonic and derivation path, the same `PrivKey`, `PubKey` and `Address` is generated. The following keys are supported by the keyring: -+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/types/address.go#L76-L85 +- `secp256k1` +- `ed25519` -Of note, the `Marshal()` and `Bytes()` method both return the same raw `[]byte` form of the address, the former being needed for Protobuf compatibility. Also, the `String()` method is used to return the `bech32` encoded form of the address, which should be the only address format with which end-user interract. Here is an example: +- `ExportPrivKeyArmor(uid, encryptPassphrase string) (armor string, err error)` exports a private key in ASCII-armored encrypted format using the given passphrase. You can then either import the private key again into the keyring using the `ImportPrivKey(uid, armor, passphrase string)` function or decrypt it into a raw private key using the `UnarmorDecryptPrivKey(armorStr string, passphrase string)` function. -+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/types/address.go#L235-L249 ## Next {hide} From c9ef428053308091ced3f275404ba97c5f6ef75c Mon Sep 17 00:00:00 2001 From: Cory Date: Fri, 19 Mar 2021 07:35:25 -0700 Subject: [PATCH 212/214] Add issue template for "Module Readiness Checklist" (#8901) * add module readiness checklist template * Update .github/ISSUE_TEMPLATE/module_readiness_checklist.md Co-authored-by: Aleksandr Bezobchuk * update about in module-readiness-checklist Co-authored-by: Aleksandr Bezobchuk Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- .../module-readiness-checklist.md | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/module-readiness-checklist.md diff --git a/.github/ISSUE_TEMPLATE/module-readiness-checklist.md b/.github/ISSUE_TEMPLATE/module-readiness-checklist.md new file mode 100644 index 000000000000..2d14413ad971 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/module-readiness-checklist.md @@ -0,0 +1,40 @@ +--- +name: Module Readiness Checklist +about: Pre-flight checklist that modules must pass in order to be included in a release of the Cosmos SDK +labels: 'module-readiness-checklist' +--- + +## x/{MODULE_NAME} Module Readiness Checklist + +This checklist is to be used for tracking the final internal audit of new Cosmos SDK modules prior to inclusion in a published release. + +### Release Candidate Checklist + +The following checklist should be gone through once the module has been fully implemented. This audit should be performed directly on `master`, or preferably on a `alpha` or `beta` release tag that includes the module. + +The module **should not** be included in any Release Candidate tag until it has passed this checklist. + +- [ ] API audit (at least 1 person) (@assignee) + - [ ] Are Msg and Query methods and types well-named and organized? + - [ ] Is everything well documented (inline godoc as well as [`/spec/` folder](https://github.com/cosmos/cosmos-sdk/blob/master/docs/spec/SPEC-SPEC.md) in module directory) +- [ ] State machine audit (at least 2 people) (@assignee1, @assignee2) + - [ ] Read through MsgServer code and verify correctness upon visual inspection + - [ ] Ensure all state machine code which could be confusing is properly commented + - [ ] Make sure state machine logic matches Msg method documentation + - [ ] Ensure that all state machine edge cases are covered with tests and that test coverage is sufficient (at least 90% coverage on module code) + - [ ] Assess potential threats for each method including spam attacks and ensure that threats have been addressed sufficiently. This should be done by writing up threat assessment for each method + - [ ] Assess potential risks of any new third party dependencies and decide whether a dependency audit is needed +- [ ] Completeness audit, fully implemented with tests (at least 1 person) (@assignee) + - [ ] Genesis import and export of all state + - [ ] Query services + - [ ] CLI methods + - [ ] All necessary migration scripts are present (if this is an upgrade of existing module) + +### Published Release Checklist + +After the above checks have been audited and the module is included in a tagged Release Candidate, the following additional checklist should be undertaken for live testing, and potentially a 3rd party audit (if deemed necessary): + +- [ ] Testnet / devnet testing (2-3 people) (@assignee1, @assignee2, @assignee3) + - [ ] All Msg methods have been tested especially in light of any potential threats identified + - [ ] Genesis import and export has been tested +- [ ] Nice to have (and needed in some cases if threats could be high): Official 3rd party audit From 129267cc92b6dd505a4ac634907bf67ec6f5f47d Mon Sep 17 00:00:00 2001 From: Riccardo Montagnin Date: Fri, 19 Mar 2021 16:20:23 +0100 Subject: [PATCH 213/214] Added the possibility of specifying custom genesis accounts and balances inside CLI tests (#8936) Co-authored-by: Amaury <1293565+amaurym@users.noreply.github.com> --- testutil/network/util.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testutil/network/util.go b/testutil/network/util.go index 4f36d464018c..126ca7e81c42 100644 --- a/testutil/network/util.go +++ b/testutil/network/util.go @@ -168,14 +168,14 @@ func initGenFiles(cfg Config, genAccounts []authtypes.GenesisAccount, genBalance return err } - authGenState.Accounts = accounts + authGenState.Accounts = append(authGenState.Accounts, accounts...) cfg.GenesisState[authtypes.ModuleName] = cfg.Codec.MustMarshalJSON(&authGenState) // set the balances in the genesis state var bankGenState banktypes.GenesisState cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[banktypes.ModuleName], &bankGenState) - bankGenState.Balances = genBalances + bankGenState.Balances = append(bankGenState.Balances, genBalances...) cfg.GenesisState[banktypes.ModuleName] = cfg.Codec.MustMarshalJSON(&bankGenState) appGenStateJSON, err := json.MarshalIndent(cfg.GenesisState, "", " ") From 5bd93bfe7bffef8d8012c97105c2df16c1fecdaf Mon Sep 17 00:00:00 2001 From: technicallyty <48813565+technicallyty@users.noreply.github.com> Date: Fri, 19 Mar 2021 15:01:29 -0700 Subject: [PATCH 214/214] x/upgrade: added consensus version tracking (part of ADR-041) (#8743) * -added consensus version tracking to x/upgrade * -added interface to module manager -added e2e test for migrations using consensus version store in x/upgrade -cleaned up x/upgrade Keeper -handler in apply upgrade now handles errors and setting consensus versions -cleaned up migration map keys -removed init chainer method -simapp now implements GetConsensusVersions to assist with testing * Changed MigrationMap identifier to VersionMap removed module_test * updated docs * forgot this * added line to changelog for this PR * Change set consensus version function to match adr 041 spec * add documentation * remove newline from changelog unnecessary newline removed * updated example in simapp for RunMigrations, SetCurrentConsensusVersions now returns an error * switch TestMigrations to use Require instead of t.Fatal * Update CHANGELOG.md Co-authored-by: Aaron Craelius * docs for SetVersionManager * -init genesis method added -removed panics/fails from setting consensus versions * update identifiers to be more go-like * update docs and UpgradeHandler fnc sig * Upgrade Keeper now takes a VersionMap instead of a VersionManager interface * upgrade keeper transition to Version Map * cleanup, added versionmap return to RunMigrations * quick fix * Update docs/architecture/adr-041-in-place-store-migrations.md Co-authored-by: Amaury <1293565+amaurym@users.noreply.github.com> * remove support for versionmap field on upgrade keeper * cleanup * rename get/set version map keeper functions * update adr doc to match name changes * remove redudant line Co-authored-by: technicallyty <48813565+tytech3@users.noreply.github.com> Co-authored-by: Aaron Craelius Co-authored-by: Amaury <1293565+amaurym@users.noreply.github.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- CHANGELOG.md | 2 + .../adr-041-in-place-store-migrations.md | 36 +++++----------- simapp/app.go | 13 ++---- simapp/app_test.go | 28 ++++++++++++- types/module/module.go | 28 +++++++++---- x/upgrade/abci_test.go | 13 ++++-- x/upgrade/keeper/grpc_query_test.go | 5 ++- x/upgrade/keeper/keeper.go | 41 ++++++++++++++++++- x/upgrade/keeper/keeper_test.go | 27 +++++++++++- x/upgrade/spec/01_concepts.md | 2 +- x/upgrade/spec/02_state.md | 12 +++++- x/upgrade/types/handler.go | 3 +- x/upgrade/types/keys.go | 3 ++ 13 files changed, 160 insertions(+), 53 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae7ce9a177fa..551ab5614ebf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -61,6 +61,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * [\#8629](https://github.com/cosmos/cosmos-sdk/pull/8629) Deprecated `SetFullFundraiserPath` from `Config` in favor of `SetPurpose` and `SetCoinType`. * (x/upgrade) [\#8673](https://github.com/cosmos/cosmos-sdk/pull/8673) Remove IBC logic from x/upgrade. Deprecates IBC fields in an Upgrade Plan. IBC upgrade logic moved to 02-client and an IBC UpgradeProposal is added. * (x/bank) [\#8517](https://github.com/cosmos/cosmos-sdk/pull/8517) `SupplyI` interface and `Supply` are removed and uses `sdk.Coins` for supply tracking +* (x/upgrade) [\#8743](https://github.com/cosmos/cosmos-sdk/pull/8743) `UpgradeHandler` includes a new argument `VersionMap` which helps facilitate in-place migrations. * (x/auth) [\#8129](https://github.com/cosmos/cosmos-sdk/pull/8828) Updated `SigVerifiableTx.GetPubKeys` method signature to return error. @@ -79,6 +80,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (x/auth) [\#8522](https://github.com/cosmos/cosmos-sdk/pull/8522) Allow to query all stored accounts * (crypto/types) [\#8600](https://github.com/cosmos/cosmos-sdk/pull/8600) `CompactBitArray`: optimize the `NumTrueBitsBefore` method and add an `Equal` method. * (grpc) [\#8815](https://github.com/cosmos/cosmos-sdk/pull/8815) Add orderBy parameter to `TxsByEvents` endpoint. +* (x/upgrade) [\#8743](https://github.com/cosmos/cosmos-sdk/pull/8743) Add tracking module versions as per ADR-041 ### Bug Fixes diff --git a/docs/architecture/adr-041-in-place-store-migrations.md b/docs/architecture/adr-041-in-place-store-migrations.md index 4687ef31f880..179219b94cc9 100644 --- a/docs/architecture/adr-041-in-place-store-migrations.md +++ b/docs/architecture/adr-041-in-place-store-migrations.md @@ -82,48 +82,34 @@ Each module's migration functions are specific to the module's store evolutions, We introduce a new prefix store in `x/upgrade`'s store. This store will track each module's current version, it can be modelized as a `map[string]uint64` of module name to module ConsensusVersion, and will be used when running the migrations (see next section for details). The key prefix used is `0x1`, and the key/value format is: ``` -0x2 | {bytes(module_name)} => LittleEndian(module_consensus_version) +0x2 | {bytes(module_name)} => BigEndian(module_consensus_version) ``` +The initial state of the store is set from `app.go`'s `InitChainer` method. -s -We add a new private field `versionManager` of type `VersionManager` to `x/upgrade`'s keeper, where `VersionManager` is: - -```go -type VersionManager interface { - GetConsensusVersions() VersionMap -} - -// Map of module name => new module Consensus Version. -type VersionMap map[string]uint64 -``` - -This `versionManager` field can be modified via the `SetVersionManager` field, and will allow the upgrade keeper to know the current versions of loaded modules. `SetVersionManager` MUST be called as early as possible in the app initialization; in the SDK's `simapp`, it is called in the `NewSimApp` constructor function. - -The UpgradeHandler signature needs to be updated to take a `VersionMap`, as well as return an error: +The UpgradeHandler signature needs to be updated to take a `VersionMap`, as well as return an upgraded `VersionMap` and an error: ```diff - type UpgradeHandler func(ctx sdk.Context, plan Plan) -+ type UpgradeHandler func(ctx sdk.Context, plan Plan, versionMap VersionMap) error ++ type UpgradeHandler func(ctx sdk.Context, plan Plan, versionMap VersionMap) (VersionMap, error) ``` -To apply an upgrade, we query the `VersionMap` from the `x/upgrade` store and pass it into the handler. The handler runs the actual migration functions (see next section), and if successful, the current ConsensusVersions of all loaded modules will be stored into state. +To apply an upgrade, we query the `VersionMap` from the `x/upgrade` store and pass it into the handler. The handler runs the actual migration functions (see next section), and if successful, returns an updated `VersionMap` to be stored in state. ```diff func (k UpgradeKeeper) ApplyUpgrade(ctx sdk.Context, plan types.Plan) { // --snip-- - handler(ctx, plan) -+ err := handler(ctx, plan, k.GetConsensusVersions()) // k.GetConsensusVersions() fetches the VersionMap stored in state. ++ updatedVM, err := handler(ctx, plan, k.GetModuleVersionMap(ctx)) // k.GetModuleVersionMap() fetches the VersionMap stored in state. + if err != nil { + return err + } + -+ // Get the current ConsensusVersions of the loaded modules (retrieved from -+ // `k.versionManager`), and save them to state. -+ k.SetCurrentConsensusVersions() ++ // Set the updated consensus versions to state ++ k.SetModuleVersionMap(ctx, updatedVM) } ``` -An gRPC query endpoint to query the `VersionMap` stored in `x/upgrade`'s state will also be added, so that app developers can double-check the `VersionMap` before the upgrade handler runs. +A gRPC query endpoint to query the `VersionMap` stored in `x/upgrade`'s state will also be added, so that app developers can double-check the `VersionMap` before the upgrade handler runs. ### Running Migrations @@ -139,8 +125,8 @@ If a required migration is missing (e.g. if it has not been registered in the `C In practice, the `RunMigrations` method should be called from inside an `UpgradeHandler`. ```go -app.UpgradeKeeper.SetUpgradeHandler("my-plan", func(ctx sdk.Context, plan upgradetypes.Plan, versionMap VersionMap) error { - return app.mm.RunMigrations(ctx, versionMap) +app.UpgradeKeeper.SetUpgradeHandler("my-plan", func(ctx sdk.Context, plan upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) { + return app.mm.RunMigrations(ctx, vm) }) ``` diff --git a/simapp/app.go b/simapp/app.go index 77c75c8f9ca3..97a71d4015e4 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -421,6 +421,7 @@ func (app *SimApp) InitChainer(ctx sdk.Context, req abci.RequestInitChain) abci. if err := json.Unmarshal(req.AppStateBytes, &genesisState); err != nil { panic(err) } + app.UpgradeKeeper.SetModuleVersionMap(ctx, app.mm.GetVersionMap()) return app.mm.InitGenesis(ctx, app.appCodec, genesisState) } @@ -535,16 +536,10 @@ func (app *SimApp) RegisterTendermintService(clientCtx client.Context) { // // 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) -// } +// app.UpgradeKeeper.SetUpgradeHandler("store-migration", func(ctx sdk.Context, plan upgradetypes.Plan, vm module.VersionMap) { +// return app.RunMigrations(ctx, vm) // }) -func (app *SimApp) RunMigrations(ctx sdk.Context, migrateFromVersions module.MigrationMap) error { +func (app *SimApp) RunMigrations(ctx sdk.Context, migrateFromVersions module.VersionMap) (module.VersionMap, error) { return app.mm.RunMigrations(ctx, app.configurator, migrateFromVersions) } diff --git a/simapp/app_test.go b/simapp/app_test.go index 55963732655f..c4aa9885b5d8 100644 --- a/simapp/app_test.go +++ b/simapp/app_test.go @@ -160,9 +160,9 @@ func TestRunMigrations(t *testing.T) { // Run migrations only for bank. That's why we put the initial // version for bank as 1, and for all other modules, we put as // their latest ConsensusVersion. - err = app.RunMigrations( + _, err = app.RunMigrations( app.NewContext(true, tmproto.Header{Height: app.LastBlockHeight()}), - module.MigrationMap{ + module.VersionMap{ "bank": 1, "auth": auth.AppModule{}.ConsensusVersion(), "authz": authz.AppModule{}.ConsensusVersion(), @@ -190,3 +190,27 @@ func TestRunMigrations(t *testing.T) { }) } } + +func TestUpgradeStateOnGenesis(t *testing.T) { + encCfg := MakeTestEncodingConfig() + db := dbm.NewMemDB() + app := NewSimApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encCfg, EmptyAppOptions{}) + genesisState := NewDefaultGenesisState(encCfg.Marshaler) + stateBytes, err := json.MarshalIndent(genesisState, "", " ") + require.NoError(t, err) + + // Initialize the chain + app.InitChain( + abci.RequestInitChain{ + Validators: []abci.ValidatorUpdate{}, + AppStateBytes: stateBytes, + }, + ) + + // make sure the upgrade keeper has version map in state + ctx := app.NewContext(false, tmproto.Header{}) + vm := app.UpgradeKeeper.GetModuleVersionMap(ctx) + for v, i := range app.mm.Modules { + require.Equal(t, vm[v], i.ConsensusVersion()) + } +} diff --git a/types/module/module.go b/types/module/module.go index 9123c9af7ec9..ba6a6a47a6ce 100644 --- a/types/module/module.go +++ b/types/module/module.go @@ -333,25 +333,27 @@ func (m *Manager) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) map[st // MigrationHandler is the migration function that each module registers. type MigrationHandler func(sdk.Context) error -// MigrationMap is a map of moduleName -> version, where version denotes the +// VersionMap 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 +type VersionMap map[string]uint64 // RunMigrations performs in-place store migrations for all modules. -func (m Manager) RunMigrations(ctx sdk.Context, cfg Configurator, migrateFromVersions MigrationMap) error { +func (m Manager) RunMigrations(ctx sdk.Context, cfg Configurator, fromVM VersionMap) (VersionMap, error) { c, ok := cfg.(configurator) if !ok { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "expected %T, got %T", configurator{}, cfg) + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "expected %T, got %T", configurator{}, cfg) } + updatedVM := make(VersionMap) for moduleName, module := range m.Modules { - err := c.runModuleMigrations(ctx, moduleName, migrateFromVersions[moduleName], module.ConsensusVersion()) + err := c.runModuleMigrations(ctx, moduleName, fromVM[moduleName], module.ConsensusVersion()) + updatedVM[moduleName] = module.ConsensusVersion() if err != nil { - return err + return nil, err } } - return nil + return updatedVM, nil } // BeginBlock performs begin block functionality for all modules. It creates a @@ -395,3 +397,15 @@ func (m *Manager) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) abci.Respo Events: ctx.EventManager().ABCIEvents(), } } + +// GetVersionMap gets consensus version from all modules +func (m *Manager) GetVersionMap() VersionMap { + vermap := make(VersionMap) + for _, v := range m.Modules { + version := v.ConsensusVersion() + name := v.Name() + vermap[name] = version + } + + return vermap +} diff --git a/x/upgrade/abci_test.go b/x/upgrade/abci_test.go index 4dc2a4c5f76d..9735ae619638 100644 --- a/x/upgrade/abci_test.go +++ b/x/upgrade/abci_test.go @@ -105,7 +105,9 @@ func VerifyDoUpgrade(t *testing.T) { }) t.Log("Verify that the upgrade can be successfully applied with a handler") - s.keeper.SetUpgradeHandler("test", func(ctx sdk.Context, plan types.Plan) {}) + s.keeper.SetUpgradeHandler("test", func(ctx sdk.Context, plan types.Plan, vm module.VersionMap) (module.VersionMap, error) { + return vm, nil + }) require.NotPanics(t, func() { s.module.BeginBlock(newCtx, req) }) @@ -121,7 +123,9 @@ func VerifyDoUpgradeWithCtx(t *testing.T, newCtx sdk.Context, proposalName strin }) t.Log("Verify that the upgrade can be successfully applied with a handler") - s.keeper.SetUpgradeHandler(proposalName, func(ctx sdk.Context, plan types.Plan) {}) + s.keeper.SetUpgradeHandler(proposalName, func(ctx sdk.Context, plan types.Plan, vm module.VersionMap) (module.VersionMap, error) { + return vm, nil + }) require.NotPanics(t, func() { s.module.BeginBlock(newCtx, req) }) @@ -133,7 +137,10 @@ func TestHaltIfTooNew(t *testing.T) { s := setupTest(10, map[int64]bool{}) t.Log("Verify that we don't panic with registered plan not in database at all") var called int - s.keeper.SetUpgradeHandler("future", func(ctx sdk.Context, plan types.Plan) { called++ }) + s.keeper.SetUpgradeHandler("future", func(ctx sdk.Context, plan types.Plan, vm module.VersionMap) (module.VersionMap, error) { + called++ + return vm, nil + }) newCtx := s.ctx.WithBlockHeight(s.ctx.BlockHeight() + 1).WithBlockTime(time.Now()) req := abci.RequestBeginBlock{Header: newCtx.BlockHeader()} diff --git a/x/upgrade/keeper/grpc_query_test.go b/x/upgrade/keeper/grpc_query_test.go index d307157402de..b44fc1e67c00 100644 --- a/x/upgrade/keeper/grpc_query_test.go +++ b/x/upgrade/keeper/grpc_query_test.go @@ -11,6 +11,7 @@ import ( "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/x/upgrade/types" ) @@ -110,7 +111,9 @@ func (suite *UpgradeTestSuite) TestAppliedCurrentPlan() { suite.app.UpgradeKeeper.ScheduleUpgrade(suite.ctx, plan) suite.ctx = suite.ctx.WithBlockHeight(expHeight) - suite.app.UpgradeKeeper.SetUpgradeHandler(planName, func(ctx sdk.Context, plan types.Plan) {}) + suite.app.UpgradeKeeper.SetUpgradeHandler(planName, func(ctx sdk.Context, plan types.Plan, vm module.VersionMap) (module.VersionMap, error) { + return vm, nil + }) suite.app.UpgradeKeeper.ApplyUpgrade(suite.ctx, plan) req = &types.QueryAppliedPlanRequest{Name: planName} diff --git a/x/upgrade/keeper/keeper.go b/x/upgrade/keeper/keeper.go index 3536937fbe3e..b171a219b59b 100644 --- a/x/upgrade/keeper/keeper.go +++ b/x/upgrade/keeper/keeper.go @@ -16,6 +16,7 @@ import ( store "github.com/cosmos/cosmos-sdk/store/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/upgrade/types" ) @@ -48,6 +49,39 @@ func (k Keeper) SetUpgradeHandler(name string, upgradeHandler types.UpgradeHandl k.upgradeHandlers[name] = upgradeHandler } +// SetModuleVersionMap saves a given version map to state +func (k Keeper) SetModuleVersionMap(ctx sdk.Context, vm module.VersionMap) { + if len(vm) > 0 { + store := ctx.KVStore(k.storeKey) + versionStore := prefix.NewStore(store, []byte{types.VersionMapByte}) + for modName, ver := range vm { + nameBytes := []byte(modName) + verBytes := make([]byte, 8) + binary.BigEndian.PutUint64(verBytes, ver) + versionStore.Set(nameBytes, verBytes) + } + } +} + +// GetModuleVersionMap returns a map of key module name and value module consensus version +// as defined in ADR-041. +func (k Keeper) GetModuleVersionMap(ctx sdk.Context) module.VersionMap { + store := ctx.KVStore(k.storeKey) + it := sdk.KVStorePrefixIterator(store, []byte{types.VersionMapByte}) + + vm := make(module.VersionMap) + defer it.Close() + for ; it.Valid(); it.Next() { + moduleBytes := it.Key() + // first byte is prefix key, so we remove it here + name := string(moduleBytes[1:]) + moduleVersion := binary.BigEndian.Uint64(it.Value()) + vm[name] = moduleVersion + } + + return vm +} + // ScheduleUpgrade schedules an upgrade based on the specified plan. // If there is another Plan already scheduled, it will overwrite it // (implicitly cancelling the current plan) @@ -187,7 +221,12 @@ func (k Keeper) ApplyUpgrade(ctx sdk.Context, plan types.Plan) { panic("ApplyUpgrade should never be called without first checking HasHandler") } - handler(ctx, plan) + updatedVM, err := handler(ctx, plan, k.GetModuleVersionMap(ctx)) + if err != nil { + panic(err) + } + + k.SetModuleVersionMap(ctx, updatedVM) // Must clear IBC state after upgrade is applied as it is stored separately from the upgrade plan. // This will prevent resubmission of upgrade msg after upgrade is already completed. diff --git a/x/upgrade/keeper/keeper_test.go b/x/upgrade/keeper/keeper_test.go index a8f6cd30b533..9a5c38f64974 100644 --- a/x/upgrade/keeper/keeper_test.go +++ b/x/upgrade/keeper/keeper_test.go @@ -11,6 +11,7 @@ import ( "github.com/cosmos/cosmos-sdk/simapp" store "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/x/upgrade/keeper" "github.com/cosmos/cosmos-sdk/x/upgrade/types" ) @@ -115,7 +116,9 @@ func (s *KeeperTestSuite) TestScheduleUpgrade() { Height: 123450000, }, setup: func() { - s.app.UpgradeKeeper.SetUpgradeHandler("all-good", func(_ sdk.Context, _ types.Plan) {}) + s.app.UpgradeKeeper.SetUpgradeHandler("all-good", func(ctx sdk.Context, plan types.Plan, vm module.VersionMap) (module.VersionMap, error) { + return vm, nil + }) s.app.UpgradeKeeper.ApplyUpgrade(s.ctx, types.Plan{ Name: "all-good", Info: "some text here", @@ -191,6 +194,28 @@ func (s *KeeperTestSuite) TestSetUpgradedClient() { } +// Tests that the underlying state of x/upgrade is set correctly after +// an upgrade. +func (s *KeeperTestSuite) TestMigrations() { + initialVM := module.VersionMap{"bank": uint64(1)} + s.app.UpgradeKeeper.SetModuleVersionMap(s.ctx, initialVM) + vmBefore := s.app.UpgradeKeeper.GetModuleVersionMap(s.ctx) + s.app.UpgradeKeeper.SetUpgradeHandler("dummy", func(_ sdk.Context, _ types.Plan, vm module.VersionMap) (module.VersionMap, error) { + // simulate upgrading the bank module + vm["bank"] = vm["bank"] + 1 + return vm, nil + }) + dummyPlan := types.Plan{ + Name: "dummy", + Info: "some text here", + Height: 123450000, + } + + s.app.UpgradeKeeper.ApplyUpgrade(s.ctx, dummyPlan) + vm := s.app.UpgradeKeeper.GetModuleVersionMap(s.ctx) + s.Require().Equal(vmBefore["bank"]+1, vm["bank"]) +} + func TestKeeperTestSuite(t *testing.T) { suite.Run(t, new(KeeperTestSuite)) } diff --git a/x/upgrade/spec/01_concepts.md b/x/upgrade/spec/01_concepts.md index 9ff387fc75fa..3985631303eb 100644 --- a/x/upgrade/spec/01_concepts.md +++ b/x/upgrade/spec/01_concepts.md @@ -47,7 +47,7 @@ and not defined on a per-module basis. Registering a `Handler` is done via `Keeper#SetUpgradeHandler` in the application. ```go -type UpgradeHandler func(Context, Plan) +type UpgradeHandler func(Context, Plan, VersionMap) (VersionMap, error) ``` During each `EndBlock` execution, the `x/upgrade` module checks if there exists a diff --git a/x/upgrade/spec/02_state.md b/x/upgrade/spec/02_state.md index f069b4f96797..796b99686d20 100644 --- a/x/upgrade/spec/02_state.md +++ b/x/upgrade/spec/02_state.md @@ -5,7 +5,15 @@ order: 2 # State The internal state of the `x/upgrade` module is relatively minimal and simple. The -state only contains the currently active upgrade `Plan` (if one exists) by key -`0x0` and if a `Plan` is marked as "done" by key `0x1`. +state contains the currently active upgrade `Plan` (if one exists) by key +`0x0` and if a `Plan` is marked as "done" by key `0x1`. Additionally, the state +contains the consensus versions of all app modules in the application. The versions +are stored as big endian `uint64`, and can be accessed with prefix `0x2` appended +by the corresponding module name of type `string`. + +- Plan: `0x0 -> Plan` +- Done: `0x1 | byte(plan name) -> BigEndian(Block Height)` +- ConsensusVersion: `0x2 | byte(module name) -> BigEndian(Module Consensus Version)` + The `x/upgrade` module contains no genesis state. diff --git a/x/upgrade/types/handler.go b/x/upgrade/types/handler.go index 44e50cff112f..0dccaefebde8 100644 --- a/x/upgrade/types/handler.go +++ b/x/upgrade/types/handler.go @@ -2,7 +2,8 @@ package types import ( sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" ) // UpgradeHandler specifies the type of function that is called when an upgrade is applied -type UpgradeHandler func(ctx sdk.Context, plan Plan) +type UpgradeHandler func(ctx sdk.Context, plan Plan, vm module.VersionMap) (module.VersionMap, error) diff --git a/x/upgrade/types/keys.go b/x/upgrade/types/keys.go index 410f63597c6e..2505bd5ce451 100644 --- a/x/upgrade/types/keys.go +++ b/x/upgrade/types/keys.go @@ -22,6 +22,9 @@ const ( // DoneByte is a prefix for to look up completed upgrade plan by name DoneByte = 0x1 + // VersionMapByte is a prefix to look up module names (key) and versions (value) + VersionMapByte = 0x2 + // KeyUpgradedIBCState is the key under which upgraded ibc state is stored in the upgrade store KeyUpgradedIBCState = "upgradedIBCState"